aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig11
-rw-r--r--drivers/acpi/Makefile3
-rw-r--r--drivers/acpi/acpi_dbg.c30
-rw-r--r--drivers/acpi/acpi_video.c20
-rw-r--r--drivers/acpi/acpica/acapps.h4
-rw-r--r--drivers/acpi/acpica/accommon.h2
-rw-r--r--drivers/acpi/acpica/acconvert.h2
-rw-r--r--drivers/acpi/acpica/acdebug.h5
-rw-r--r--drivers/acpi/acpica/acdispat.h2
-rw-r--r--drivers/acpi/acpica/acevents.h2
-rw-r--r--drivers/acpi/acpica/acglobal.h3
-rw-r--r--drivers/acpi/acpica/achware.h2
-rw-r--r--drivers/acpi/acpica/acinterp.h2
-rw-r--r--drivers/acpi/acpica/aclocal.h4
-rw-r--r--drivers/acpi/acpica/acmacros.h4
-rw-r--r--drivers/acpi/acpica/acnamesp.h2
-rw-r--r--drivers/acpi/acpica/acobject.h3
-rw-r--r--drivers/acpi/acpica/acopcode.h2
-rw-r--r--drivers/acpi/acpica/acparser.h2
-rw-r--r--drivers/acpi/acpica/acpredef.h17
-rw-r--r--drivers/acpi/acpica/acresrc.h2
-rw-r--r--drivers/acpi/acpica/acstruct.h2
-rw-r--r--drivers/acpi/acpica/actables.h2
-rw-r--r--drivers/acpi/acpica/acutils.h2
-rw-r--r--drivers/acpi/acpica/amlcode.h2
-rw-r--r--drivers/acpi/acpica/amlresrc.h2
-rw-r--r--drivers/acpi/acpica/dbdisply.c4
-rw-r--r--drivers/acpi/acpica/dbexec.c4
-rw-r--r--drivers/acpi/acpica/dbhistry.c2
-rw-r--r--drivers/acpi/acpica/dbnames.c2
-rw-r--r--drivers/acpi/acpica/dbobject.c2
-rw-r--r--drivers/acpi/acpica/dbtest.c164
-rw-r--r--drivers/acpi/acpica/dsargs.c2
-rw-r--r--drivers/acpi/acpica/dscontrol.c2
-rw-r--r--drivers/acpi/acpica/dsdebug.c2
-rw-r--r--drivers/acpi/acpica/dsfield.c9
-rw-r--r--drivers/acpi/acpica/dsinit.c2
-rw-r--r--drivers/acpi/acpica/dsmethod.c2
-rw-r--r--drivers/acpi/acpica/dsobject.c2
-rw-r--r--drivers/acpi/acpica/dsopcode.c28
-rw-r--r--drivers/acpi/acpica/dspkginit.c2
-rw-r--r--drivers/acpi/acpica/dswexec.c2
-rw-r--r--drivers/acpi/acpica/dswload.c2
-rw-r--r--drivers/acpi/acpica/dswload2.c4
-rw-r--r--drivers/acpi/acpica/dswscope.c2
-rw-r--r--drivers/acpi/acpica/dswstate.c2
-rw-r--r--drivers/acpi/acpica/evevent.c2
-rw-r--r--drivers/acpi/acpica/evglock.c2
-rw-r--r--drivers/acpi/acpica/evgpe.c4
-rw-r--r--drivers/acpi/acpica/evgpeblk.c2
-rw-r--r--drivers/acpi/acpica/evgpeinit.c2
-rw-r--r--drivers/acpi/acpica/evgpeutil.c2
-rw-r--r--drivers/acpi/acpica/evhandler.c2
-rw-r--r--drivers/acpi/acpica/evmisc.c2
-rw-r--r--drivers/acpi/acpica/evregion.c4
-rw-r--r--drivers/acpi/acpica/evrgnini.c21
-rw-r--r--drivers/acpi/acpica/evxface.c2
-rw-r--r--drivers/acpi/acpica/evxfevnt.c2
-rw-r--r--drivers/acpi/acpica/evxfgpe.c6
-rw-r--r--drivers/acpi/acpica/evxfregn.c2
-rw-r--r--drivers/acpi/acpica/exconcat.c2
-rw-r--r--drivers/acpi/acpica/exconfig.c2
-rw-r--r--drivers/acpi/acpica/exconvrt.c4
-rw-r--r--drivers/acpi/acpica/excreate.c2
-rw-r--r--drivers/acpi/acpica/exdebug.c2
-rw-r--r--drivers/acpi/acpica/exdump.c2
-rw-r--r--drivers/acpi/acpica/exfield.c71
-rw-r--r--drivers/acpi/acpica/exfldio.c2
-rw-r--r--drivers/acpi/acpica/exmisc.c2
-rw-r--r--drivers/acpi/acpica/exmutex.c2
-rw-r--r--drivers/acpi/acpica/exnames.c2
-rw-r--r--drivers/acpi/acpica/exoparg1.c2
-rw-r--r--drivers/acpi/acpica/exoparg2.c10
-rw-r--r--drivers/acpi/acpica/exoparg3.c2
-rw-r--r--drivers/acpi/acpica/exoparg6.c2
-rw-r--r--drivers/acpi/acpica/exprep.c2
-rw-r--r--drivers/acpi/acpica/exregion.c2
-rw-r--r--drivers/acpi/acpica/exresnte.c2
-rw-r--r--drivers/acpi/acpica/exresolv.c2
-rw-r--r--drivers/acpi/acpica/exresop.c2
-rw-r--r--drivers/acpi/acpica/exserial.c4
-rw-r--r--drivers/acpi/acpica/exstore.c2
-rw-r--r--drivers/acpi/acpica/exstoren.c2
-rw-r--r--drivers/acpi/acpica/exstorob.c2
-rw-r--r--drivers/acpi/acpica/exsystem.c2
-rw-r--r--drivers/acpi/acpica/extrace.c2
-rw-r--r--drivers/acpi/acpica/exutils.c4
-rw-r--r--drivers/acpi/acpica/hwacpi.c2
-rw-r--r--drivers/acpi/acpica/hwesleep.c2
-rw-r--r--drivers/acpi/acpica/hwgpe.c2
-rw-r--r--drivers/acpi/acpica/hwsleep.c2
-rw-r--r--drivers/acpi/acpica/hwtimer.c2
-rw-r--r--drivers/acpi/acpica/hwvalid.c2
-rw-r--r--drivers/acpi/acpica/hwxface.c2
-rw-r--r--drivers/acpi/acpica/hwxfsleep.c98
-rw-r--r--drivers/acpi/acpica/nsarguments.c2
-rw-r--r--drivers/acpi/acpica/nsconvert.c2
-rw-r--r--drivers/acpi/acpica/nsdump.c2
-rw-r--r--drivers/acpi/acpica/nsdumpdv.c2
-rw-r--r--drivers/acpi/acpica/nsinit.c2
-rw-r--r--drivers/acpi/acpica/nsload.c4
-rw-r--r--drivers/acpi/acpica/nsparse.c68
-rw-r--r--drivers/acpi/acpica/nspredef.c2
-rw-r--r--drivers/acpi/acpica/nsprepkg.c2
-rw-r--r--drivers/acpi/acpica/nsrepair.c2
-rw-r--r--drivers/acpi/acpica/nsrepair2.c2
-rw-r--r--drivers/acpi/acpica/nsutils.c4
-rw-r--r--drivers/acpi/acpica/nswalk.c2
-rw-r--r--drivers/acpi/acpica/nsxfname.c2
-rw-r--r--drivers/acpi/acpica/psargs.c2
-rw-r--r--drivers/acpi/acpica/psloop.c195
-rw-r--r--drivers/acpi/acpica/psobject.c2
-rw-r--r--drivers/acpi/acpica/psopcode.c2
-rw-r--r--drivers/acpi/acpica/psopinfo.c2
-rw-r--r--drivers/acpi/acpica/psparse.c10
-rw-r--r--drivers/acpi/acpica/psscope.c2
-rw-r--r--drivers/acpi/acpica/pstree.c2
-rw-r--r--drivers/acpi/acpica/psutils.c2
-rw-r--r--drivers/acpi/acpica/pswalk.c2
-rw-r--r--drivers/acpi/acpica/psxface.c2
-rw-r--r--drivers/acpi/acpica/rsdumpinfo.c14
-rw-r--r--drivers/acpi/acpica/rsirq.c8
-rw-r--r--drivers/acpi/acpica/rsserial.c10
-rw-r--r--drivers/acpi/acpica/tbdata.c2
-rw-r--r--drivers/acpi/acpica/tbfadt.c4
-rw-r--r--drivers/acpi/acpica/tbfind.c2
-rw-r--r--drivers/acpi/acpica/tbinstal.c2
-rw-r--r--drivers/acpi/acpica/tbprint.c2
-rw-r--r--drivers/acpi/acpica/tbutils.c2
-rw-r--r--drivers/acpi/acpica/tbxface.c6
-rw-r--r--drivers/acpi/acpica/tbxfload.c27
-rw-r--r--drivers/acpi/acpica/tbxfroot.c2
-rw-r--r--drivers/acpi/acpica/utaddress.c2
-rw-r--r--drivers/acpi/acpica/utalloc.c2
-rw-r--r--drivers/acpi/acpica/utascii.c2
-rw-r--r--drivers/acpi/acpica/utbuffer.c2
-rw-r--r--drivers/acpi/acpica/utcache.c2
-rw-r--r--drivers/acpi/acpica/utcopy.c2
-rw-r--r--drivers/acpi/acpica/utdebug.c2
-rw-r--r--drivers/acpi/acpica/utdecode.c20
-rw-r--r--drivers/acpi/acpica/utdelete.c4
-rw-r--r--drivers/acpi/acpica/uterror.c9
-rw-r--r--drivers/acpi/acpica/uteval.c2
-rw-r--r--drivers/acpi/acpica/utglobal.c2
-rw-r--r--drivers/acpi/acpica/uthex.c2
-rw-r--r--drivers/acpi/acpica/utids.c2
-rw-r--r--drivers/acpi/acpica/utinit.c2
-rw-r--r--drivers/acpi/acpica/utlock.c2
-rw-r--r--drivers/acpi/acpica/utobject.c2
-rw-r--r--drivers/acpi/acpica/utosi.c2
-rw-r--r--drivers/acpi/acpica/utpredef.c2
-rw-r--r--drivers/acpi/acpica/utprint.c2
-rw-r--r--drivers/acpi/acpica/uttrack.c14
-rw-r--r--drivers/acpi/acpica/utuuid.c2
-rw-r--r--drivers/acpi/acpica/utxface.c2
-rw-r--r--drivers/acpi/acpica/utxferror.c44
-rw-r--r--drivers/acpi/acpica/utxfinit.c2
-rw-r--r--drivers/acpi/apei/Kconfig12
-rw-r--r--drivers/acpi/apei/bert.c23
-rw-r--r--drivers/acpi/apei/einj.c93
-rw-r--r--drivers/acpi/apei/erst.c27
-rw-r--r--drivers/acpi/apei/ghes.c655
-rw-r--r--drivers/acpi/apei/hest.c16
-rw-r--r--drivers/acpi/arm64/iort.c5
-rw-r--r--drivers/acpi/bus.c41
-rw-r--r--drivers/acpi/cppc_acpi.c42
-rw-r--r--drivers/acpi/custom_method.c6
-rw-r--r--drivers/acpi/dptf/Makefile2
-rw-r--r--drivers/acpi/dptf/int340x_thermal.c2
-rw-r--r--drivers/acpi/ec.c208
-rw-r--r--drivers/acpi/ec_sys.c36
-rw-r--r--drivers/acpi/internal.h8
-rw-r--r--drivers/acpi/irq.c4
-rw-r--r--drivers/acpi/nfit/core.c86
-rw-r--r--drivers/acpi/nfit/intel.c8
-rw-r--r--drivers/acpi/numa.c6
-rw-r--r--drivers/acpi/pci_link.c8
-rw-r--r--drivers/acpi/pmic/intel_pmic_xpower.c41
-rw-r--r--drivers/acpi/power.c22
-rw-r--r--drivers/acpi/pptt.c13
-rw-r--r--drivers/acpi/processor_idle.c7
-rw-r--r--drivers/acpi/resource.c4
-rw-r--r--drivers/acpi/tables.c12
-rw-r--r--drivers/acpi/x86/utils.c5
-rw-r--r--drivers/android/Kconfig2
-rw-r--r--drivers/android/binder.c593
-rw-r--r--drivers/android/binder_alloc.c303
-rw-r--r--drivers/android/binder_alloc.h47
-rw-r--r--drivers/android/binder_alloc_selftest.c7
-rw-r--r--drivers/android/binder_internal.h9
-rw-r--r--drivers/android/binder_trace.h2
-rw-r--r--drivers/android/binderfs.c296
-rw-r--r--drivers/ata/Kconfig2
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/ahci_mvebu.c87
-rw-r--r--drivers/ata/libahci_platform.c13
-rw-r--r--drivers/ata/libata-core.c1
-rw-r--r--drivers/ata/pata_macio.c9
-rw-r--r--drivers/ata/sata_fsl.c4
-rw-r--r--drivers/ata/sata_inic162x.c22
-rw-r--r--drivers/atm/he.c41
-rw-r--r--drivers/atm/idt77252.c16
-rw-r--r--drivers/auxdisplay/ht16k33.c2
-rw-r--r--drivers/base/base.h12
-rw-r--r--drivers/base/bus.c66
-rw-r--r--drivers/base/cacheinfo.c6
-rw-r--r--drivers/base/class.c14
-rw-r--r--drivers/base/component.c206
-rw-r--r--drivers/base/core.c246
-rw-r--r--drivers/base/cpu.c2
-rw-r--r--drivers/base/dd.c188
-rw-r--r--drivers/base/devcon.c62
-rw-r--r--drivers/base/firmware_loader/Makefile4
-rw-r--r--drivers/base/firmware_loader/builtin/.gitignore1
-rw-r--r--drivers/base/firmware_loader/builtin/Makefile40
-rw-r--r--drivers/base/firmware_loader/fallback_table.c5
-rw-r--r--drivers/base/firmware_loader/main.c8
-rw-r--r--drivers/base/platform.c21
-rw-r--r--drivers/base/power/clock_ops.c13
-rw-r--r--drivers/base/power/common.c2
-rw-r--r--drivers/base/power/domain.c13
-rw-r--r--drivers/base/power/main.c26
-rw-r--r--drivers/base/power/runtime.c190
-rw-r--r--drivers/base/power/sysfs.c17
-rw-r--r--drivers/base/power/wakeup.c2
-rw-r--r--drivers/base/regmap/regcache-rbtree.c2
-rw-r--r--drivers/base/regmap/regmap-irq.c107
-rw-r--r--drivers/base/swnode.c23
-rw-r--r--drivers/base/test/test_async_driver_probe.c261
-rw-r--r--drivers/bcma/bcma_private.h9
-rw-r--r--drivers/bcma/driver_gpio.c2
-rw-r--r--drivers/bcma/host_pci.c2
-rw-r--r--drivers/bcma/host_soc.c4
-rw-r--r--drivers/bcma/main.c45
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/block/loop.c35
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c5
-rw-r--r--drivers/block/nbd.c5
-rw-r--r--drivers/block/null_blk.h1
-rw-r--r--drivers/block/rbd.c54
-rw-r--r--drivers/block/skd_main.c4
-rw-r--r--drivers/block/zram/zram_drv.c90
-rw-r--r--drivers/block/zram/zram_drv.h5
-rw-r--r--drivers/bluetooth/Kconfig4
-rw-r--r--drivers/bluetooth/btmrvl_drv.h2
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c43
-rw-r--r--drivers/bluetooth/btmtkuart.c538
-rw-r--r--drivers/bluetooth/btqca.c19
-rw-r--r--drivers/bluetooth/btqca.h8
-rw-r--r--drivers/bluetooth/btqcomsmd.c31
-rw-r--r--drivers/bluetooth/btrtl.c10
-rw-r--r--drivers/bluetooth/btusb.c75
-rw-r--r--drivers/bluetooth/h4_recv.h7
-rw-r--r--drivers/bluetooth/hci_h4.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c24
-rw-r--r--drivers/bluetooth/hci_qca.c121
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-allocator.c11
-rw-r--r--drivers/bus/fsl-mc/mc-io.c13
-rw-r--r--drivers/bus/hisi_lpc.c5
-rw-r--r--drivers/bus/imx-weim.c70
-rw-r--r--drivers/bus/ti-sysc.c6
-rw-r--r--drivers/char/Kconfig19
-rw-r--r--drivers/char/Makefile6
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/applicom.c35
-rw-r--r--drivers/char/efirtc.c23
-rw-r--r--drivers/char/generic_nvram.c159
-rw-r--r--drivers/char/hpet.c9
-rw-r--r--drivers/char/hw_random/Kconfig15
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/bcm2835-rng.c18
-rw-r--r--drivers/char/hw_random/optee-rng.c306
-rw-r--r--drivers/char/hw_random/virtio-rng.c2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c173
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c25
-rw-r--r--drivers/char/lp.c4
-rw-r--r--drivers/char/mbcs.c1
-rw-r--r--drivers/char/mwave/mwavedd.c7
-rw-r--r--drivers/char/nvram.c673
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/at91/at91sam9x5.c5
-rw-r--r--drivers/clk/at91/sama5d2.c4
-rw-r--r--drivers/clk/at91/sama5d4.c2
-rw-r--r--drivers/clk/clk-versaclock5.c4
-rw-r--r--drivers/clk/clk.c16
-rw-r--r--drivers/clk/imx/clk-frac-pll.c5
-rw-r--r--drivers/clk/imx/clk-imx8qxp-lpcg.c2
-rw-r--r--drivers/clk/mmp/clk-of-mmp2.c4
-rw-r--r--drivers/clk/qcom/Kconfig1
-rw-r--r--drivers/clk/qcom/gcc-sdm845.c14
-rw-r--r--drivers/clk/socfpga/clk-pll-s10.c2
-rw-r--r--drivers/clk/socfpga/clk-s10.c20
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-a31.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-v3s.c2
-rw-r--r--drivers/clk/tegra/Kconfig5
-rw-r--r--drivers/clk/tegra/Makefile2
-rw-r--r--drivers/clk/tegra/clk-dfll.c459
-rw-r--r--drivers/clk/tegra/clk-dfll.h6
-rw-r--r--drivers/clk/tegra/clk-tegra124-dfll-fcpu.c524
-rw-r--r--drivers/clk/tegra/cvb.c12
-rw-r--r--drivers/clk/tegra/cvb.h7
-rw-r--r--drivers/clk/ti/divider.c11
-rw-r--r--drivers/clk/zynqmp/clkc.c4
-rw-r--r--drivers/clocksource/Kconfig22
-rw-r--r--drivers/clocksource/Makefile7
-rw-r--r--drivers/clocksource/arm_arch_timer.c55
-rw-r--r--drivers/clocksource/exynos_mct.c48
-rw-r--r--drivers/clocksource/timer-cs5535.c (renamed from drivers/clocksource/cs5535-clockevt.c)0
-rw-r--r--drivers/clocksource/timer-milbeaut.c161
-rw-r--r--drivers/clocksource/timer-pxa.c (renamed from drivers/clocksource/pxa_timer.c)0
-rw-r--r--drivers/clocksource/timer-riscv.c23
-rw-r--r--drivers/clocksource/timer-sun5i.c10
-rw-r--r--drivers/clocksource/timer-tango-xtal.c (renamed from drivers/clocksource/tango_xtal.c)0
-rw-r--r--drivers/clocksource/timer-tegra20.c370
-rw-r--r--drivers/clocksource/timer-ti-dm.c5
-rw-r--r--drivers/cpufreq/Kconfig3
-rw-r--r--drivers/cpufreq/Kconfig.arm20
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c4
-rw-r--r--drivers/cpufreq/arm_big_little.c2
-rw-r--r--drivers/cpufreq/armada-8k-cpufreq.c206
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c65
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c1
-rw-r--r--drivers/cpufreq/cpufreq-dt.c33
-rw-r--r--drivers/cpufreq/cpufreq.c146
-rw-r--r--drivers/cpufreq/cpufreq_stats.c16
-rw-r--r--drivers/cpufreq/davinci-cpufreq.c5
-rw-r--r--drivers/cpufreq/e_powersaver.c5
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c25
-rw-r--r--drivers/cpufreq/intel_pstate.c105
-rw-r--r--drivers/cpufreq/longhaul.c2
-rw-r--r--drivers/cpufreq/mediatek-cpufreq.c16
-rw-r--r--drivers/cpufreq/omap-cpufreq.c4
-rw-r--r--drivers/cpufreq/pcc-cpufreq.c2
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c10
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c53
-rw-r--r--drivers/cpufreq/qcom-cpufreq-kryo.c22
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c15
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c67
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c61
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c21
-rw-r--r--drivers/cpufreq/speedstep-ich.c3
-rw-r--r--drivers/cpufreq/tegra124-cpufreq.c46
-rw-r--r--drivers/cpuidle/Kconfig11
-rw-r--r--drivers/cpuidle/dt_idle_states.c15
-rw-r--r--drivers/cpuidle/governors/Makefile1
-rw-r--r--drivers/cpuidle/governors/teo.c444
-rw-r--r--drivers/cpuidle/poll_state.c2
-rw-r--r--drivers/crypto/Kconfig1
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c93
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.h4
-rw-r--r--drivers/crypto/amcc/crypto4xx_reg_def.h1
-rw-r--r--drivers/crypto/amcc/crypto4xx_trng.c4
-rw-r--r--drivers/crypto/amcc/crypto4xx_trng.h4
-rw-r--r--drivers/crypto/atmel-tdes.c2
-rw-r--r--drivers/crypto/axis/artpec6_crypto.c326
-rw-r--r--drivers/crypto/bcm/Makefile2
-rw-r--r--drivers/crypto/bcm/cipher.c54
-rw-r--r--drivers/crypto/bcm/cipher.h4
-rw-r--r--drivers/crypto/bcm/util.c40
-rw-r--r--drivers/crypto/bcm/util.h6
-rw-r--r--drivers/crypto/caam/Kconfig1
-rw-r--r--drivers/crypto/caam/caamalg.c240
-rw-r--r--drivers/crypto/caam/caamalg_desc.c18
-rw-r--r--drivers/crypto/caam/caamalg_qi.c29
-rw-r--r--drivers/crypto/caam/caamalg_qi2.c85
-rw-r--r--drivers/crypto/caam/caamalg_qi2.h2
-rw-r--r--drivers/crypto/caam/caamhash.c444
-rw-r--r--drivers/crypto/caam/caamhash_desc.c68
-rw-r--r--drivers/crypto/caam/caamhash_desc.h8
-rw-r--r--drivers/crypto/caam/compat.h1
-rw-r--r--drivers/crypto/caam/ctrl.c25
-rw-r--r--drivers/crypto/caam/desc.h1
-rw-r--r--drivers/crypto/caam/error.c6
-rw-r--r--drivers/crypto/caam/error.h9
-rw-r--r--drivers/crypto/caam/intern.h1
-rw-r--r--drivers/crypto/caam/key_gen.c30
-rw-r--r--drivers/crypto/caam/qi.c4
-rw-r--r--drivers/crypto/cavium/cpt/cptpf_main.c4
-rw-r--r--drivers/crypto/cavium/cpt/cptvf_main.c7
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_debugfs.c27
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_debugfs.h5
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_lib.c6
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_main.c4
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_reqmgr.c10
-rw-r--r--drivers/crypto/cavium/zip/zip_main.c58
-rw-r--r--drivers/crypto/ccp/ccp-crypto-aes-cmac.c2
-rw-r--r--drivers/crypto/ccp/ccp-crypto-des3.c2
-rw-r--r--drivers/crypto/ccp/ccp-crypto-sha.c2
-rw-r--r--drivers/crypto/ccp/ccp-debugfs.c36
-rw-r--r--drivers/crypto/ccp/ccp-dev-v5.c6
-rw-r--r--drivers/crypto/ccp/ccp-ops.c2
-rw-r--r--drivers/crypto/ccp/psp-dev.c37
-rw-r--r--drivers/crypto/ccp/psp-dev.h2
-rw-r--r--drivers/crypto/ccp/sp-dev.c2
-rw-r--r--drivers/crypto/ccp/sp-dev.h2
-rw-r--r--drivers/crypto/ccp/sp-pci.c6
-rw-r--r--drivers/crypto/ccp/sp-platform.c2
-rw-r--r--drivers/crypto/ccree/cc_aead.c40
-rw-r--r--drivers/crypto/ccree/cc_buffer_mgr.c87
-rw-r--r--drivers/crypto/ccree/cc_cipher.c10
-rw-r--r--drivers/crypto/ccree/cc_debugfs.c22
-rw-r--r--drivers/crypto/ccree/cc_debugfs.h8
-rw-r--r--drivers/crypto/ccree/cc_driver.c20
-rw-r--r--drivers/crypto/ccree/cc_driver.h2
-rw-r--r--drivers/crypto/ccree/cc_pm.c13
-rw-r--r--drivers/crypto/ccree/cc_pm.h3
-rw-r--r--drivers/crypto/chelsio/Makefile2
-rw-r--r--drivers/crypto/chelsio/chcr_algo.c12
-rw-r--r--drivers/crypto/chelsio/chcr_core.h2
-rw-r--r--drivers/crypto/chelsio/chcr_ipsec.c42
-rw-r--r--drivers/crypto/chelsio/chtls/Makefile3
-rw-r--r--drivers/crypto/chelsio/chtls/chtls_cm.c6
-rw-r--r--drivers/crypto/chelsio/chtls/chtls_io.c12
-rw-r--r--drivers/crypto/chelsio/chtls/chtls_main.c1
-rw-r--r--drivers/crypto/hifn_795x.c3
-rw-r--r--drivers/crypto/hisilicon/sec/sec_algs.c4
-rw-r--r--drivers/crypto/hisilicon/sec/sec_drv.c15
-rw-r--r--drivers/crypto/inside-secure/safexcel_cipher.c2
-rw-r--r--drivers/crypto/ixp4xx_crypto.c10
-rw-r--r--drivers/crypto/marvell/cipher.c4
-rw-r--r--drivers/crypto/mediatek/mtk-platform.c16
-rw-r--r--drivers/crypto/n2_core.c2
-rw-r--r--drivers/crypto/omap-des.c2
-rw-r--r--drivers/crypto/picoxcell_crypto.c3
-rw-r--r--drivers/crypto/qat/qat_c3xxx/Makefile2
-rw-r--r--drivers/crypto/qat/qat_c3xxx/adf_drv.c5
-rw-r--r--drivers/crypto/qat/qat_c3xxxvf/Makefile2
-rw-r--r--drivers/crypto/qat/qat_c3xxxvf/adf_drv.c5
-rw-r--r--drivers/crypto/qat/qat_c62x/Makefile2
-rw-r--r--drivers/crypto/qat/qat_c62x/adf_drv.c5
-rw-r--r--drivers/crypto/qat/qat_c62xvf/Makefile2
-rw-r--r--drivers/crypto/qat/qat_c62xvf/adf_drv.c5
-rw-r--r--drivers/crypto/qat/qat_common/adf_admin.c12
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg.c7
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport.c7
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport_debug.c15
-rw-r--r--drivers/crypto/qat/qat_common/qat_algs.c24
-rw-r--r--drivers/crypto/qat/qat_common/qat_asym_algs.c68
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/Makefile2
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_drv.c5
-rw-r--r--drivers/crypto/qat/qat_dh895xccvf/Makefile2
-rw-r--r--drivers/crypto/qat/qat_dh895xccvf/adf_drv.c5
-rw-r--r--drivers/crypto/qce/ablkcipher.c4
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.c2
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.h4
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c41
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto_ahash.c2
-rw-r--r--drivers/crypto/s5p-sss.c64
-rw-r--r--drivers/crypto/stm32/stm32-hash.c2
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-cipher.c2
-rw-r--r--drivers/crypto/talitos.c28
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c26
-rw-r--r--drivers/crypto/virtio/virtio_crypto_algs.c2
-rw-r--r--drivers/dio/dio.c4
-rw-r--r--drivers/dma/at_xdmac.c19
-rw-r--r--drivers/dma/bcm2835-dma.c70
-rw-r--r--drivers/dma/dmaengine.c4
-rw-r--r--drivers/dma/dmatest.c32
-rw-r--r--drivers/dma/imx-dma.c8
-rw-r--r--drivers/dma/imx-sdma.c8
-rw-r--r--drivers/dma/mediatek/mtk-hsdma.c4
-rw-r--r--drivers/dma/mxs-dma.c6
-rw-r--r--drivers/dma/xgene-dma.c4
-rw-r--r--drivers/dma/xilinx/xilinx_dma.c14
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c6
-rw-r--r--drivers/edac/altera_edac.h4
-rw-r--r--drivers/extcon/Kconfig8
-rw-r--r--drivers/extcon/Makefile1
-rw-r--r--drivers/extcon/extcon-ptn5150.c339
-rw-r--r--drivers/firewire/sbp2.c5
-rw-r--r--drivers/firmware/Kconfig2
-rw-r--r--drivers/firmware/arm_scmi/bus.c9
-rw-r--r--drivers/firmware/arm_sdei.c68
-rw-r--r--drivers/firmware/efi/Kconfig6
-rw-r--r--drivers/firmware/efi/Makefile1
-rw-r--r--drivers/firmware/efi/apple-properties.c13
-rw-r--r--drivers/firmware/efi/arm-init.c6
-rw-r--r--drivers/firmware/efi/arm-runtime.c11
-rw-r--r--drivers/firmware/efi/capsule-loader.c4
-rw-r--r--drivers/firmware/efi/capsule.c4
-rw-r--r--drivers/firmware/efi/cper-arm.c14
-rw-r--r--drivers/firmware/efi/cper.c27
-rw-r--r--drivers/firmware/efi/dev-path-parser.c9
-rw-r--r--drivers/firmware/efi/earlycon.c206
-rw-r--r--drivers/firmware/efi/efi-bgrt.c5
-rw-r--r--drivers/firmware/efi/efi-pstore.c2
-rw-r--r--drivers/firmware/efi/efi.c4
-rw-r--r--drivers/firmware/efi/efibc.c10
-rw-r--r--drivers/firmware/efi/efivars.c58
-rw-r--r--drivers/firmware/efi/esrt.c1
-rw-r--r--drivers/firmware/efi/fake_mem.c16
-rw-r--r--drivers/firmware/efi/libstub/Makefile4
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c8
-rw-r--r--drivers/firmware/efi/libstub/arm32-stub.c6
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c6
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c15
-rw-r--r--drivers/firmware/efi/libstub/efistub.h12
-rw-r--r--drivers/firmware/efi/libstub/fdt.c115
-rw-r--r--drivers/firmware/efi/libstub/gop.c4
-rw-r--r--drivers/firmware/efi/libstub/random.c6
-rw-r--r--drivers/firmware/efi/libstub/secureboot.c4
-rw-r--r--drivers/firmware/efi/libstub/tpm.c4
-rw-r--r--drivers/firmware/efi/memattr.c7
-rw-r--r--drivers/firmware/efi/runtime-map.c3
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c55
-rw-r--r--drivers/firmware/efi/test/efi_test.c1
-rw-r--r--drivers/firmware/efi/test/efi_test.h2
-rw-r--r--drivers/firmware/efi/tpm.c5
-rw-r--r--drivers/firmware/efi/vars.c15
-rw-r--r--drivers/firmware/imx/misc.c38
-rw-r--r--drivers/firmware/imx/scu-pd.c1
-rw-r--r--drivers/firmware/raspberrypi.c11
-rw-r--r--drivers/firmware/tegra/Makefile3
-rw-r--r--drivers/firmware/tegra/bpmp-private.h34
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c305
-rw-r--r--drivers/firmware/tegra/bpmp-tegra210.c243
-rw-r--r--drivers/firmware/tegra/bpmp.c376
-rw-r--r--drivers/firmware/ti_sci.c21
-rw-r--r--drivers/firmware/xilinx/Kconfig1
-rw-r--r--drivers/firmware/xilinx/zynqmp.c166
-rw-r--r--drivers/fpga/Kconfig2
-rw-r--r--drivers/fpga/altera-ps-spi.c2
-rw-r--r--drivers/fpga/stratix10-soc.c5
-rw-r--r--drivers/gnss/Kconfig13
-rw-r--r--drivers/gnss/Makefile3
-rw-r--r--drivers/gnss/core.c1
-rw-r--r--drivers/gnss/mtk.c152
-rw-r--r--drivers/gnss/sirf.c256
-rw-r--r--drivers/gpio/gpio-altera-a10sr.c4
-rw-r--r--drivers/gpio/gpio-eic-sprd.c14
-rw-r--r--drivers/gpio/gpio-mt7621.c20
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpio-pcf857x.c26
-rw-r--r--drivers/gpio/gpio-pxa.c1
-rw-r--r--drivers/gpio/gpio-vf610.c5
-rw-r--r--drivers/gpio/gpiolib-acpi.c24
-rw-r--r--drivers/gpio/gpiolib-of.c2
-rw-r--r--drivers/gpio/gpiolib.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c59
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/Kconfig4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c21
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c76
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c23
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c2
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h13
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c24
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c1
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c8
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c12
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c22
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c21
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c34
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h2
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c4
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c1
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c48
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c9
-rw-r--r--drivers/gpu/drm/drm_atomic_uapi.c3
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c2
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c133
-rw-r--r--drivers/gpu/drm/drm_lease.c3
-rw-r--r--drivers/gpu/drm/drm_mode_object.c4
-rw-r--r--drivers/gpu/drm/drm_modes.c2
-rw-r--r--drivers/gpu/drm/drm_pci.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/hypercall.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c30
-rw-r--r--drivers/gpu/drm/i915/gvt/mpt.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c75
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.h1
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c12
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c12
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c15
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c23
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.c38
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.h6
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h18
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c4
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h6
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c4
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c240
-rw-r--r--drivers/gpu/drm/i915/intel_display.c50
-rw-r--r--drivers/gpu/drm/i915/intel_display.h16
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c4
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h10
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c45
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c7
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c38
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c6
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h9
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c2
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c25
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c4
-rw-r--r--drivers/gpu/drm/meson/meson_crtc.c23
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c14
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c22
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c26
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h6
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c8
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h6
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c33
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/falcon.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c7
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c27
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_prime.c14
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c1
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c5
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_rgb.c15
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_rgb.h11
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c5
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_prime.c14
-rw-r--r--drivers/gpu/drm/vkms/vkms_crc.c3
-rw-r--r--drivers/gpu/drm/vkms/vkms_crtc.c8
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c7
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h2
-rw-r--r--drivers/gpu/drm/vkms/vkms_gem.c8
-rw-r--r--drivers/gpu/drm/vkms/vkms_output.c8
-rw-r--r--drivers/gpu/drm/vkms/vkms_plane.c8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c81
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c6
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c8
-rw-r--r--drivers/gpu/ipu-v3/ipu-pre.c6
-rw-r--r--drivers/gpu/vga/Kconfig1
-rw-r--r--drivers/hid/hid-core.c23
-rw-r--r--drivers/hid/hid-debug.c120
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c2
-rw-r--r--drivers/hv/channel.c13
-rw-r--r--drivers/hv/channel_mgmt.c18
-rw-r--r--drivers/hv/hv_balloon.c31
-rw-r--r--drivers/hv/hyperv_vmbus.h4
-rw-r--r--drivers/hv/ring_buffer.c45
-rw-r--r--drivers/hv/vmbus_drv.c177
-rw-r--r--drivers/hwmon/ad7418.c78
-rw-r--r--drivers/hwmon/adm1029.c67
-rw-r--r--drivers/hwmon/adt7462.c4
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c97
-rw-r--r--drivers/hwmon/f71882fg.c2
-rw-r--r--drivers/hwmon/gl518sm.c120
-rw-r--r--drivers/hwmon/gl520sm.c184
-rw-r--r--drivers/hwmon/gpio-fan.c2
-rw-r--r--drivers/hwmon/hih6130.c21
-rw-r--r--drivers/hwmon/hwmon.c4
-rw-r--r--drivers/hwmon/i5500_temp.c14
-rw-r--r--drivers/hwmon/i5k_amb.c12
-rw-r--r--drivers/hwmon/ibmaem.c15
-rw-r--r--drivers/hwmon/ibmpex.c14
-rw-r--r--drivers/hwmon/iio_hwmon.c2
-rw-r--r--drivers/hwmon/ina209.c151
-rw-r--r--drivers/hwmon/ina3221.c36
-rw-r--r--drivers/hwmon/jc42.c8
-rw-r--r--drivers/hwmon/k8temp.c12
-rw-r--r--drivers/hwmon/lineage-pem.c77
-rw-r--r--drivers/hwmon/lm73.c34
-rw-r--r--drivers/hwmon/lm75.c6
-rw-r--r--drivers/hwmon/lm77.c45
-rw-r--r--drivers/hwmon/lm80.c142
-rw-r--r--drivers/hwmon/lm83.c62
-rw-r--r--drivers/hwmon/lm85.c43
-rw-r--r--drivers/hwmon/lm90.c12
-rw-r--r--drivers/hwmon/lm92.c39
-rw-r--r--drivers/hwmon/lm93.c630
-rw-r--r--drivers/hwmon/lm95241.c8
-rw-r--r--drivers/hwmon/lm95245.c8
-rw-r--r--drivers/hwmon/ltc2990.c32
-rw-r--r--drivers/hwmon/ltc4151.c11
-rw-r--r--drivers/hwmon/ltc4222.c56
-rw-r--r--drivers/hwmon/ltc4245.c8
-rw-r--r--drivers/hwmon/ltc4261.c28
-rw-r--r--drivers/hwmon/max16065.c225
-rw-r--r--drivers/hwmon/max1619.c33
-rw-r--r--drivers/hwmon/max31722.c8
-rw-r--r--drivers/hwmon/max31790.c6
-rw-r--r--drivers/hwmon/max6639.c92
-rw-r--r--drivers/hwmon/max6642.c31
-rw-r--r--drivers/hwmon/max6650.c6
-rw-r--r--drivers/hwmon/mc13783-adc.c49
-rw-r--r--drivers/hwmon/nct6775.c15
-rw-r--r--drivers/hwmon/nct7904.c10
-rw-r--r--drivers/hwmon/nsa320-hwmon.c8
-rw-r--r--drivers/hwmon/ntc_thermistor.c106
-rw-r--r--drivers/hwmon/occ/common.c27
-rw-r--r--drivers/hwmon/occ/common.h3
-rw-r--r--drivers/hwmon/occ/p8_i2c.c3
-rw-r--r--drivers/hwmon/occ/p9_sbe.c3
-rw-r--r--drivers/hwmon/occ/sysfs.c13
-rw-r--r--drivers/hwmon/pc87360.c427
-rw-r--r--drivers/hwmon/pc87427.c317
-rw-r--r--drivers/hwmon/pmbus/pmbus.c64
-rw-r--r--drivers/hwmon/pmbus/tps53679.c9
-rw-r--r--drivers/hwmon/powr1220.c144
-rw-r--r--drivers/hwmon/pwm-fan.c43
-rw-r--r--drivers/hwmon/sch5627.c146
-rw-r--r--drivers/hwmon/sch5636.c202
-rw-r--r--drivers/hwmon/scmi-hwmon.c2
-rw-r--r--drivers/hwmon/scpi-hwmon.c4
-rw-r--r--drivers/hwmon/sht15.c34
-rw-r--r--drivers/hwmon/sht21.c17
-rw-r--r--drivers/hwmon/sht3x.c50
-rw-r--r--drivers/hwmon/smsc47b397.c24
-rw-r--r--drivers/hwmon/stts751.c64
-rw-r--r--drivers/hwmon/tc654.c60
-rw-r--r--drivers/hwmon/tc74.c4
-rw-r--r--drivers/hwmon/tmp102.c4
-rw-r--r--drivers/hwmon/tmp103.c20
-rw-r--r--drivers/hwmon/tmp421.c6
-rw-r--r--drivers/hwmon/vexpress-hwmon.c25
-rw-r--r--drivers/hwmon/via-cputemp.c15
-rw-r--r--drivers/hwtracing/coresight/coresight-cpu-debug.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c119
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.h6
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c3
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h1
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c12
-rw-r--r--drivers/hwtracing/coresight/coresight.c60
-rw-r--r--drivers/hwtracing/coresight/of_coresight.c4
-rw-r--r--drivers/hwtracing/intel_th/core.c6
-rw-r--r--drivers/hwtracing/intel_th/gth.c4
-rw-r--r--drivers/hwtracing/intel_th/pti.c16
-rw-r--r--drivers/hwtracing/intel_th/sth.c4
-rw-r--r--drivers/hwtracing/stm/core.c11
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c12
-rw-r--r--drivers/i2c/busses/i2c-cadence.c9
-rw-r--r--drivers/i2c/busses/i2c-omap.c13
-rw-r--r--drivers/i2c/busses/i2c-tegra.c15
-rw-r--r--drivers/i2c/i2c-dev.c6
-rw-r--r--drivers/i3c/master.c2
-rw-r--r--drivers/i3c/master/dw-i3c-master.c26
-rw-r--r--drivers/i3c/master/i3c-master-cdns.c4
-rw-r--r--drivers/ide/ide-atapi.c9
-rw-r--r--drivers/ide/ide-io.c61
-rw-r--r--drivers/ide/ide-park.c2
-rw-r--r--drivers/ide/ide-probe.c23
-rw-r--r--drivers/ide/ide-proc.c2
-rw-r--r--drivers/idle/intel_idle.c1
-rw-r--r--drivers/iio/accel/adxl345_core.c4
-rw-r--r--drivers/iio/accel/mma8452.c105
-rw-r--r--drivers/iio/accel/st_accel_core.c171
-rw-r--r--drivers/iio/adc/Kconfig80
-rw-r--r--drivers/iio/adc/Makefile7
-rw-r--r--drivers/iio/adc/ad7476.c20
-rw-r--r--drivers/iio/adc/ad7606.c (renamed from drivers/staging/iio/adc/ad7606.c)272
-rw-r--r--drivers/iio/adc/ad7606.h (renamed from drivers/staging/iio/adc/ad7606.h)17
-rw-r--r--drivers/iio/adc/ad7606_par.c (renamed from drivers/staging/iio/adc/ad7606_par.c)46
-rw-r--r--drivers/iio/adc/ad7606_spi.c (renamed from drivers/staging/iio/adc/ad7606_spi.c)35
-rw-r--r--drivers/iio/adc/ad7768-1.c655
-rw-r--r--drivers/iio/adc/axp288_adc.c76
-rw-r--r--drivers/iio/adc/exynos_adc.c19
-rw-r--r--drivers/iio/adc/ingenic-adc.c364
-rw-r--r--drivers/iio/adc/lpc32xx_adc.c15
-rw-r--r--drivers/iio/adc/meson_saradc.c33
-rw-r--r--drivers/iio/adc/npcm_adc.c335
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c10
-rw-r--r--drivers/iio/adc/ti-ads124s08.c376
-rw-r--r--drivers/iio/adc/ti-ads8688.c3
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c5
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c4
-rw-r--r--drivers/iio/chemical/Kconfig21
-rw-r--r--drivers/iio/chemical/Makefile3
-rw-r--r--drivers/iio/chemical/atlas-ph-sensor.c7
-rw-r--r--drivers/iio/chemical/bme680_i2c.c7
-rw-r--r--drivers/iio/chemical/bme680_spi.c8
-rw-r--r--drivers/iio/chemical/pms7003.c340
-rw-r--r--drivers/iio/chemical/sgp30.c591
-rw-r--r--drivers/iio/chemical/sps30.c548
-rw-r--r--drivers/iio/dac/Kconfig16
-rw-r--r--drivers/iio/dac/Makefile1
-rw-r--r--drivers/iio/dac/ad5686-spi.c9
-rw-r--r--drivers/iio/dac/ad5686.c44
-rw-r--r--drivers/iio/dac/ad5686.h4
-rw-r--r--drivers/iio/dac/ad5696-i2c.c2
-rw-r--r--drivers/iio/dac/ad5758.c2
-rw-r--r--drivers/iio/dac/ti-dac7612.c184
-rw-r--r--drivers/iio/frequency/ad9523.c7
-rw-r--r--drivers/iio/imu/bmi160/bmi160.h11
-rw-r--r--drivers/iio/imu/bmi160/bmi160_core.c317
-rw-r--r--drivers/iio/imu/bmi160/bmi160_i2c.c5
-rw-r--r--drivers/iio/imu/bmi160/bmi160_spi.c4
-rw-r--r--drivers/iio/imu/inv_mpu6050/Kconfig8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c31
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c6
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c12
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c2
-rw-r--r--drivers/iio/industrialio-core.c5
-rw-r--r--drivers/iio/light/Kconfig10
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/isl29018.c46
-rw-r--r--drivers/iio/light/max44009.c555
-rw-r--r--drivers/iio/magnetometer/mag3110.c94
-rw-r--r--drivers/iio/pressure/Kconfig2
-rw-r--r--drivers/iio/pressure/st_pressure.h2
-rw-r--r--drivers/iio/pressure/st_pressure_core.c69
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c5
-rw-r--r--drivers/iio/pressure/st_pressure_spi.c5
-rw-r--r--drivers/infiniband/core/cma.c5
-rw-r--r--drivers/infiniband/core/core_priv.h1
-rw-r--r--drivers/infiniband/core/device.c13
-rw-r--r--drivers/infiniband/core/nldev.c4
-rw-r--r--drivers/infiniband/core/rdma_core.h2
-rw-r--r--drivers/infiniband/core/umem_odp.c3
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c11
-rw-r--r--drivers/infiniband/core/uverbs_ioctl.c62
-rw-r--r--drivers/infiniband/core/uverbs_main.c26
-rw-r--r--drivers/infiniband/core/uverbs_std_types_device.c8
-rw-r--r--drivers/infiniband/hw/bnxt_re/Kconfig1
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c4
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c8
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c6
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c15
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c5
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.c3
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c2
-rw-r--r--drivers/infiniband/hw/hfi1/init.c32
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c9
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c27
-rw-r--r--drivers/infiniband/hw/hfi1/ud.c1
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_alloc.c11
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c10
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_srq.c10
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_utils.c4
-rw-r--r--drivers/infiniband/hw/mlx4/Kconfig1
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c6
-rw-r--r--drivers/infiniband/hw/mlx5/cmd.c37
-rw-r--r--drivers/infiniband/hw/mlx5/cmd.h2
-rw-r--r--drivers/infiniband/hw/mlx5/flow.c3
-rw-r--r--drivers/infiniband/hw/mlx5/ib_rep.c77
-rw-r--r--drivers/infiniband/hw/mlx5/ib_rep.h10
-rw-r--r--drivers/infiniband/hw/mlx5/mad.c11
-rw-r--r--drivers/infiniband/hw/mlx5/main.c95
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h5
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c39
-rw-r--r--drivers/infiniband/hw/mlx5/odp.c10
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c16
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c4
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c14
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_stats.c4
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c6
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_ud.c1
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma.h35
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c4
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c6
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c3
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c10
-rw-r--r--drivers/input/joystick/xpad.c3
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/cap11xx.c35
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c4
-rw-r--r--drivers/input/keyboard/matrix_keypad.c2
-rw-r--r--drivers/input/keyboard/qt2160.c69
-rw-r--r--drivers/input/keyboard/st-keyscan.c4
-rw-r--r--drivers/input/misc/apanel.c24
-rw-r--r--drivers/input/misc/bma150.c9
-rw-r--r--drivers/input/misc/pwm-vibra.c19
-rw-r--r--drivers/input/misc/uinput.c5
-rw-r--r--drivers/input/mouse/elan_i2c_core.c2
-rw-r--r--drivers/input/mouse/elantech.c9
-rw-r--r--drivers/input/serio/olpc_apsp.c17
-rw-r--r--drivers/input/serio/ps2-gpio.c1
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/raspberrypi-ts.c4
-rw-r--r--drivers/interconnect/Kconfig15
-rw-r--r--drivers/interconnect/Makefile6
-rw-r--r--drivers/interconnect/core.c799
-rw-r--r--drivers/interconnect/qcom/Kconfig13
-rw-r--r--drivers/interconnect/qcom/Makefile5
-rw-r--r--drivers/interconnect/qcom/sdm845.c838
-rw-r--r--drivers/iommu/amd_iommu.c19
-rw-r--r--drivers/iommu/dmar.c7
-rw-r--r--drivers/iommu/exynos-iommu.c1
-rw-r--r--drivers/iommu/intel-iommu.c13
-rw-r--r--drivers/iommu/mtk_iommu_v1.c9
-rw-r--r--drivers/iommu/of_iommu.c2
-rw-r--r--drivers/iommu/rockchip-iommu.c3
-rw-r--r--drivers/irqchip/Kconfig19
-rw-r--r--drivers/irqchip/Makefile3
-rw-r--r--drivers/irqchip/irq-brcmstb-l2.c10
-rw-r--r--drivers/irqchip/irq-csky-apb-intc.c77
-rw-r--r--drivers/irqchip/irq-davinci-aintc.c163
-rw-r--r--drivers/irqchip/irq-davinci-cp-intc.c260
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c154
-rw-r--r--drivers/irqchip/irq-gic-v3-mbi.c2
-rw-r--r--drivers/irqchip/irq-i8259.c9
-rw-r--r--drivers/irqchip/irq-imx-irqsteer.c115
-rw-r--r--drivers/irqchip/irq-ls1x.c192
-rw-r--r--drivers/irqchip/irq-madera.c2
-rw-r--r--drivers/irqchip/irq-mmp.c6
-rw-r--r--drivers/irqchip/irq-sifive-plic.c116
-rw-r--r--drivers/irqchip/irq-stm32-exti.c1
-rw-r--r--drivers/irqchip/irq-xtensa-mx.c40
-rw-r--r--drivers/irqchip/irq-xtensa-pic.c6
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c2
-rw-r--r--drivers/isdn/hardware/avm/b1.c2
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c6
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/netjet.c6
-rw-r--r--drivers/isdn/hisax/q931.c2
-rw-r--r--drivers/isdn/hisax/st5481.h2
-rw-r--r--drivers/isdn/i4l/isdn_common.c7
-rw-r--r--drivers/isdn/i4l/isdn_tty.c8
-rw-r--r--drivers/isdn/i4l/isdn_v110.c2
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c2
-rw-r--r--drivers/isdn/mISDN/socket.c2
-rw-r--r--drivers/isdn/mISDN/timerdev.c2
-rw-r--r--drivers/leds/led-core.c30
-rw-r--r--drivers/leds/leds-lp5523.c4
-rw-r--r--drivers/leds/leds-lp55xx-common.c4
-rw-r--r--drivers/leds/trigger/ledtrig-oneshot.c38
-rw-r--r--drivers/leds/trigger/ledtrig-pattern.c99
-rw-r--r--drivers/leds/trigger/ledtrig-timer.c34
-rw-r--r--drivers/macintosh/via-cuda.c8
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c4
-rw-r--r--drivers/mailbox/mailbox.c1
-rw-r--r--drivers/md/dm-crypt.c27
-rw-r--r--drivers/md/dm-rq.c2
-rw-r--r--drivers/md/dm-thin-metadata.c4
-rw-r--r--drivers/md/dm-thin-metadata.h2
-rw-r--r--drivers/md/dm-thin.c65
-rw-r--r--drivers/md/dm.c41
-rw-r--r--drivers/md/md.c7
-rw-r--r--drivers/md/raid1.c28
-rw-r--r--drivers/md/raid5-cache.c33
-rw-r--r--drivers/md/raid5.c8
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2.c4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-g723.c4
-rw-r--r--drivers/media/pci/tw686x/tw686x-audio.c3
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c2
-rw-r--r--drivers/media/platform/vim2m.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c24
-rw-r--r--drivers/mfd/Kconfig3
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab8500-core.c2
-rw-r--r--drivers/mfd/axp20x.c126
-rw-r--r--drivers/mfd/bcm2835-pm.c92
-rw-r--r--drivers/mfd/bd9571mwv.c1
-rw-r--r--drivers/mfd/cros_ec_dev.c1
-rw-r--r--drivers/mfd/db8500-prcmu.c4
-rw-r--r--drivers/mfd/exynos-lpass.c4
-rw-r--r--drivers/mfd/madera-core.c5
-rw-r--r--drivers/mfd/max77620.c2
-rw-r--r--drivers/mfd/mc13xxx-core.c4
-rw-r--r--drivers/mfd/mt6397-core.c3
-rw-r--r--drivers/mfd/qcom_rpm.c4
-rw-r--r--drivers/mfd/rave-sp.c2
-rw-r--r--drivers/mfd/stmpe.c12
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c5
-rw-r--r--drivers/mfd/tps65218.c24
-rw-r--r--drivers/mfd/tps6586x.c24
-rw-r--r--drivers/mfd/twl-core.c4
-rw-r--r--drivers/mfd/wm5110-tables.c2
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/ad525x_dpot.c24
-rw-r--r--drivers/misc/cardreader/rts5227.c64
-rw-r--r--drivers/misc/cardreader/rts5249.c32
-rw-r--r--drivers/misc/cardreader/rts5260.c136
-rw-r--r--drivers/misc/cardreader/rtsx_pcr.c40
-rw-r--r--drivers/misc/cardreader/rtsx_pcr.h5
-rw-r--r--drivers/misc/enclosure.c4
-rw-r--r--drivers/misc/fastrpc.c1401
-rw-r--r--drivers/misc/genwqe/card_utils.c4
-rw-r--r--drivers/misc/habanalabs/Kconfig25
-rw-r--r--drivers/misc/habanalabs/Makefile14
-rw-r--r--drivers/misc/habanalabs/asid.c57
-rw-r--r--drivers/misc/habanalabs/command_buffer.c445
-rw-r--r--drivers/misc/habanalabs/command_submission.c780
-rw-r--r--drivers/misc/habanalabs/context.c215
-rw-r--r--drivers/misc/habanalabs/debugfs.c1077
-rw-r--r--drivers/misc/habanalabs/device.c1140
-rw-r--r--drivers/misc/habanalabs/goya/Makefile3
-rw-r--r--drivers/misc/habanalabs/goya/goya.c5391
-rw-r--r--drivers/misc/habanalabs/goya/goyaP.h211
-rw-r--r--drivers/misc/habanalabs/goya/goya_hwmgr.c254
-rw-r--r--drivers/misc/habanalabs/goya/goya_security.c2999
-rw-r--r--drivers/misc/habanalabs/habanalabs.h1464
-rw-r--r--drivers/misc/habanalabs/habanalabs_drv.c461
-rw-r--r--drivers/misc/habanalabs/habanalabs_ioctl.c234
-rw-r--r--drivers/misc/habanalabs/hw_queue.c635
-rw-r--r--drivers/misc/habanalabs/hwmon.c458
-rw-r--r--drivers/misc/habanalabs/include/armcp_if.h335
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h191
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h61
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h49
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h181
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h227
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h465
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h1372
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h275
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h118
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h653
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h331
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h373
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h1537
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h465
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h1153
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h143
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h53
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h227
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h243
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h447
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h745
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h143
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h83
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h83
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h83
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h83
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h83
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h117
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h55
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h1607
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h373
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h347
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h313
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h209
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h227
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h465
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h323
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h887
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h139
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h227
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h179
-rw-r--r--drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h105
-rw-r--r--drivers/misc/habanalabs/include/goya/goya.h45
-rw-r--r--drivers/misc/habanalabs/include/goya/goya_async_events.h186
-rw-r--r--drivers/misc/habanalabs/include/goya/goya_fw_if.h28
-rw-r--r--drivers/misc/habanalabs/include/goya/goya_packets.h129
-rw-r--r--drivers/misc/habanalabs/include/hl_boot_if.h30
-rw-r--r--drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h47
-rw-r--r--drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h15
-rw-r--r--drivers/misc/habanalabs/include/qman_if.h56
-rw-r--r--drivers/misc/habanalabs/irq.c327
-rw-r--r--drivers/misc/habanalabs/memory.c1723
-rw-r--r--drivers/misc/habanalabs/mmu.c906
-rw-r--r--drivers/misc/habanalabs/sysfs.c539
-rw-r--r--drivers/misc/hpilo.c14
-rw-r--r--drivers/misc/ibmvmc.c7
-rw-r--r--drivers/misc/ics932s401.c2
-rw-r--r--drivers/misc/lkdtm/core.c15
-rw-r--r--drivers/misc/lkdtm/lkdtm.h2
-rw-r--r--drivers/misc/lkdtm/perms.c36
-rw-r--r--drivers/misc/mei/Kconfig10
-rw-r--r--drivers/misc/mei/Makefile2
-rw-r--r--drivers/misc/mei/bus-fixup.c16
-rw-r--r--drivers/misc/mei/bus.c22
-rw-r--r--drivers/misc/mei/client.c5
-rw-r--r--drivers/misc/mei/hbm.c19
-rw-r--r--drivers/misc/mei/hdcp/Makefile7
-rw-r--r--drivers/misc/mei/hdcp/mei_hdcp.c849
-rw-r--r--drivers/misc/mei/hdcp/mei_hdcp.h377
-rw-r--r--drivers/misc/mei/hw-me-regs.h4
-rw-r--r--drivers/misc/mei/hw.h3
-rw-r--r--drivers/misc/mei/pci-me.c6
-rw-r--r--drivers/misc/mic/Kconfig3
-rw-r--r--drivers/misc/mic/bus/scif_bus.h8
-rw-r--r--drivers/misc/mic/bus/vop_bus.h8
-rw-r--r--drivers/misc/mic/card/mic_device.c8
-rw-r--r--drivers/misc/mic/host/mic_boot.c8
-rw-r--r--drivers/misc/mic/scif/scif_map.h4
-rw-r--r--drivers/misc/mic/scif/scif_rma.c2
-rw-r--r--drivers/misc/mic/vop/vop_main.c111
-rw-r--r--drivers/misc/mic/vop/vop_vringh.c51
-rw-r--r--drivers/misc/pvpanic.c4
-rw-r--r--drivers/misc/sgi-gru/grufault.c4
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c3
-rw-r--r--drivers/misc/vmw_balloon.c56
-rw-r--r--drivers/misc/vmw_vmci/vmci_doorbell.c9
-rw-r--r--drivers/misc/vmw_vmci/vmci_doorbell.h2
-rw-r--r--drivers/misc/vmw_vmci/vmci_driver.h2
-rw-r--r--drivers/misc/vmw_vmci/vmci_guest.c39
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c63
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.h4
-rw-r--r--drivers/mmc/core/Makefile2
-rw-r--r--drivers/mmc/core/block.c37
-rw-r--r--drivers/mmc/core/core.c338
-rw-r--r--drivers/mmc/core/core.h1
-rw-r--r--drivers/mmc/core/host.c50
-rw-r--r--drivers/mmc/core/mmc.c10
-rw-r--r--drivers/mmc/core/mmc_ops.c2
-rw-r--r--drivers/mmc/core/queue.c9
-rw-r--r--drivers/mmc/core/regulator.c260
-rw-r--r--drivers/mmc/core/sd.c20
-rw-r--r--drivers/mmc/core/sd_ops.c33
-rw-r--r--drivers/mmc/core/sd_ops.h3
-rw-r--r--drivers/mmc/core/sdio.c9
-rw-r--r--drivers/mmc/core/sdio_bus.c3
-rw-r--r--drivers/mmc/core/sdio_io.c29
-rw-r--r--drivers/mmc/core/sdio_ops.h1
-rw-r--r--drivers/mmc/core/slot-gpio.c9
-rw-r--r--drivers/mmc/host/Kconfig6
-rw-r--r--drivers/mmc/host/atmel-mci.c8
-rw-r--r--drivers/mmc/host/bcm2835.c25
-rw-r--r--drivers/mmc/host/cb710-mmc.c42
-rw-r--r--drivers/mmc/host/cqhci.c13
-rw-r--r--drivers/mmc/host/davinci_mmc.c2
-rw-r--r--drivers/mmc/host/dw_mmc-bluefield.c5
-rw-r--r--drivers/mmc/host/jz4740_mmc.c73
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c33
-rw-r--r--drivers/mmc/host/mmc_spi.c3
-rw-r--r--drivers/mmc/host/mmci.c27
-rw-r--r--drivers/mmc/host/mmci.h1
-rw-r--r--drivers/mmc/host/mtk-sd.c2
-rw-r--r--drivers/mmc/host/mxcmmc.c2
-rw-r--r--drivers/mmc/host/mxs-mmc.c2
-rw-r--r--drivers/mmc/host/of_mmc_spi.c22
-rw-r--r--drivers/mmc/host/omap.c2
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi.h2
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c19
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c1
-rw-r--r--drivers/mmc/host/renesas_sdhi_sys_dmac.c1
-rw-r--r--drivers/mmc/host/s3cmci.c2
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c2
-rw-r--r--drivers/mmc/host/sdhci-brcmstb.c4
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c310
-rw-r--r--drivers/mmc/host/sdhci-iproc.c5
-rw-r--r--drivers/mmc/host/sdhci-omap.c1
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c10
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.c140
-rw-r--r--drivers/mmc/host/sdhci-pci.h6
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c1
-rw-r--r--drivers/mmc/host/sdhci-tegra.c286
-rw-r--r--drivers/mmc/host/sdhci-xenon-phy.c2
-rw-r--r--drivers/mmc/host/sdhci.c32
-rw-r--r--drivers/mmc/host/sdhci.h6
-rw-r--r--drivers/mmc/host/sdhci_am654.c2
-rw-r--r--drivers/mmc/host/sunxi-mmc.c28
-rw-r--r--drivers/mmc/host/tmio_mmc.h5
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c20
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c1
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c3
-rw-r--r--drivers/mtd/chips/gen_probe.c2
-rw-r--r--drivers/mtd/devices/docg3.c7
-rw-r--r--drivers/mtd/devices/m25p80.c9
-rw-r--r--drivers/mtd/devices/mtdram.c2
-rw-r--r--drivers/mtd/devices/powernv_flash.c2
-rw-r--r--drivers/mtd/lpddr/qinfo_probe.c4
-rw-r--r--drivers/mtd/mtdcore.c86
-rw-r--r--drivers/mtd/mtdcore.h2
-rw-r--r--drivers/mtd/mtdpart.c39
-rw-r--r--drivers/mtd/nand/raw/Kconfig17
-rw-r--r--drivers/mtd/nand/raw/Makefile2
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.c21
-rw-r--r--drivers/mtd/nand/raw/denali.c44
-rw-r--r--drivers/mtd/nand/raw/denali.h1
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c27
-rw-r--r--drivers/mtd/nand/raw/fsmc_nand.c37
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c13
-rw-r--r--drivers/mtd/nand/raw/jz4740_nand.c2
-rw-r--r--drivers/mtd/nand/raw/jz4780_bch.c9
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c5
-rw-r--r--drivers/mtd/nand/raw/meson_nand.c1464
-rw-r--r--drivers/mtd/nand/raw/mtk_ecc.c8
-rw-r--r--drivers/mtd/nand/raw/mtk_nand.c3
-rw-r--r--drivers/mtd/nand/raw/nand_base.c160
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/raw/nand_legacy.c3
-rw-r--r--drivers/mtd/nand/raw/omap2.c20
-rw-r--r--drivers/mtd/nand/raw/qcom_nandc.c20
-rw-r--r--drivers/mtd/nand/raw/r852.c3
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c2073
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c732
-rw-r--r--drivers/mtd/nand/raw/tmio_nand.c21
-rw-r--r--drivers/mtd/nand/spi/core.c46
-rw-r--r--drivers/mtd/nand/spi/gigadevice.c83
-rw-r--r--drivers/mtd/nand/spi/macronix.c8
-rw-r--r--drivers/mtd/nand/spi/toshiba.c79
-rw-r--r--drivers/mtd/spi-nor/Kconfig25
-rw-r--r--drivers/mtd/spi-nor/Makefile3
-rw-r--r--drivers/mtd/spi-nor/cadence-quadspi.c74
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c1224
-rw-r--r--drivers/mtd/spi-nor/mtk-quadspi.c3
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c35
-rw-r--r--drivers/net/Kconfig14
-rw-r--r--drivers/net/appletalk/cops.c2
-rw-r--r--drivers/net/bonding/bond_3ad.c188
-rw-r--r--drivers/net/bonding/bond_main.c39
-rw-r--r--drivers/net/bonding/bond_netlink.c67
-rw-r--r--drivers/net/bonding/bond_options.c2
-rw-r--r--drivers/net/caif/caif_serial.c5
-rw-r--r--drivers/net/caif/caif_spi.c30
-rw-r--r--drivers/net/can/dev.c27
-rw-r--r--drivers/net/can/flexcan.c4
-rw-r--r--drivers/net/dsa/b53/b53_common.c94
-rw-r--r--drivers/net/dsa/b53/b53_priv.h5
-rw-r--r--drivers/net/dsa/b53/b53_srab.c3
-rw-r--r--drivers/net/dsa/bcm_sf2.c60
-rw-r--r--drivers/net/dsa/bcm_sf2.h8
-rw-r--r--drivers/net/dsa/bcm_sf2_cfp.c206
-rw-r--r--drivers/net/dsa/bcm_sf2_regs.h4
-rw-r--r--drivers/net/dsa/dsa_loop.c2
-rw-r--r--drivers/net/dsa/lan9303-core.c3
-rw-r--r--drivers/net/dsa/lantiq_gswip.c35
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c390
-rw-r--r--drivers/net/dsa/microchip/ksz9477_spi.c4
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c150
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h23
-rw-r--r--drivers/net/dsa/microchip/ksz_priv.h15
-rw-r--r--drivers/net/dsa/mt7530.c104
-rw-r--r--drivers/net/dsa/mt7530.h9
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c244
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h8
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1_atu.c21
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c12
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h11
-rw-r--r--drivers/net/dsa/mv88e6xxx/ptp.c2
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.c51
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.h8
-rw-r--r--drivers/net/dsa/qca8k.c21
-rw-r--r--drivers/net/dsa/qca8k.h1
-rw-r--r--drivers/net/dsa/realtek-smi.c18
-rw-r--r--drivers/net/dsa/rtl8366rb.c3
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx.c3
-rw-r--r--drivers/net/ethernet/3com/3c509.c2
-rw-r--r--drivers/net/ethernet/3com/3c515.c4
-rw-r--r--drivers/net/ethernet/3com/3c59x.c4
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c2
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c12
-rw-r--r--drivers/net/ethernet/alacritech/slicoss.c12
-rw-r--r--drivers/net/ethernet/alteon/acenic.c2
-rw-r--r--drivers/net/ethernet/altera/altera_msgdma.c3
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c4
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.c61
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c10
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.h2
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c6
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c6
-rw-r--r--drivers/net/ethernet/amd/lance.c2
-rw-r--r--drivers/net/ethernet/amd/ni65.c2
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-common.h2
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c22
-rw-r--r--drivers/net/ethernet/apm/xgene-v2/main.c8
-rw-r--r--drivers/net/ethernet/apple/bmac.c2
-rw-r--r--drivers/net/ethernet/apple/mace.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h14
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_nic.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c25
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c19
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c30
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h16
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h15
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c116
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c68
-rw-r--r--drivers/net/ethernet/arc/emac_main.c2
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c7
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c12
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c2
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c2
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c8
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig1
-rw-r--r--drivers/net/ethernet/broadcom/b44.c4
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c8
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c33
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.h2
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c14
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c178
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c8
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c152
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h9
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c31
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h197
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c58
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c256
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c12
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c2
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c26
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c11
-rw-r--r--drivers/net/ethernet/cadence/macb.h8
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c264
-rw-r--r--drivers/net/ethernet/cavium/Kconfig2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_core.c3
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c24
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c25
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h14
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_main.c149
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c128
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c2
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c2
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/sge.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/t3_hw.c6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h37
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c219
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c263
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c8
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c450
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c33
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sched.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c336
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/smt.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/srq.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c114
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.h1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_values.h6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h32
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/adapter.h14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c252
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/sge.c39
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c6
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.c3
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c3
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c1
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/eeprom.c4
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c4
-rw-r--r--drivers/net/ethernet/dlink/sundance.c5
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c68
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c18
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c22
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c16
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c7
-rw-r--r--drivers/net/ethernet/fealnx.c2
-rw-r--r--drivers/net/ethernet/freescale/Kconfig1
-rw-r--r--drivers/net/ethernet/freescale/Makefile3
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c6
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/Kconfig5
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/Makefile1
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c237
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h31
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c429
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h80
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c1
-rw-r--r--drivers/net/ethernet/freescale/enetc/Kconfig31
-rw-r--r--drivers/net/ethernet/freescale/enetc/Makefile19
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c1604
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h230
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_cbdr.c210
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_ethtool.c597
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_hw.h533
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_mdio.c199
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_msg.c164
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c943
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.h55
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_ptp.c144
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_vf.c255
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c6
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c2
-rw-r--r--drivers/net/ethernet/freescale/fman/mac.c4
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c2
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c6
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c22
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ethtool.c16
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h7
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.c47
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h22
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c681
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.h18
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c78
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c97
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h17
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c97
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c105
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c808
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h55
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c133
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c25
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c155
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h8
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c25
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c192
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c12
-rw-r--r--drivers/net/ethernet/hisilicon/hns_mdio.c2
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c16
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c13
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h3
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c8
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_if.c28
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_if.h14
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_io.c6
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c10
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c8
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_main.c10
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_rx.c11
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_tx.c8
-rw-r--r--drivers/net/ethernet/i825xx/82596.c2
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c2
-rw-r--r--drivers/net/ethernet/ibm/emac/Kconfig12
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c64
-rw-r--r--drivers/net/ethernet/ibm/emac/core.h10
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c4
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c2
-rw-r--r--drivers/net/ethernet/intel/Kconfig2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c8
-rw-r--r--drivers/net/ethernet/intel/e1000e/80003es2lan.c33
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c25
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_main.c6
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pf.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h14
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c26
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c244
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c252
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.c129
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.h2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c195
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h18
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h77
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c181
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.h11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c812
-rw-r--r--drivers/net/ethernet/intel/ice/ice_hw_autogen.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c378
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c264
-rw-r--r--drivers/net/ethernet/intel/ice/ice_nvm.c82
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c197
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_status.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c17
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.c97
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.h32
-rw-r--r--drivers/net/ethernet/intel/ice/ice_type.h4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c94
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h2
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c89
-rw-r--r--drivers/net/ethernet/intel/igc/Makefile3
-rw-r--r--drivers/net/ethernet/intel/igc/igc.h34
-rw-r--r--drivers/net/ethernet/intel/igc/igc_base.c76
-rw-r--r--drivers/net/ethernet/intel/igc/igc_base.h25
-rw-r--r--drivers/net/ethernet/intel/igc/igc_defines.h4
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c1032
-rw-r--r--drivers/net/ethernet/intel/igc/igc_hw.h1
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c118
-rw-r--r--drivers/net/ethernet/intel/igc/igc_phy.c8
-rw-r--r--drivers/net/ethernet/intel/igc/igc_regs.h4
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c10
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c30
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c32
-rw-r--r--drivers/net/ethernet/jme.c5
-rw-r--r--drivers/net/ethernet/lantiq_etop.c6
-rw-r--r--drivers/net/ethernet/lantiq_xrx200.c1
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c7
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c65
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2.h15
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c456
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/common.h2
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c29
-rw-r--r--drivers/net/ethernet/marvell/skge.c6
-rw-r--r--drivers/net/ethernet/marvell/sky2.c26
-rw-r--r--drivers/net/ethernet/mediatek/Kconfig2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c84
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Kconfig1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/alloc.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cq.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c75
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.c101
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.h22
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Kconfig1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/alloc.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c85
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ecpf.c112
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ecpf.h33
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h53
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.c142
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.h16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c309
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c96
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h17
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c331
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c350
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c230
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c167
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c982
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tx.c23
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c466
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h75
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c522
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/events.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag.c99
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag.h65
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c315
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c205
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h24
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mad.c75
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c73
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mr.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c54
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/port.c115
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/qp.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sriov.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/uar.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/vport.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw.h35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h36
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h36
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Kconfig2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/Makefile2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_env.c238
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_env.h17
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c275
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_thermal.c477
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c137
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/minimal.c361
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c54
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci_hw.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h260
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/resources.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c942
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h55
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c27
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c40
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c40
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c147
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c1330
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h40
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c313
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c257
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c157
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c296
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c163
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/switchx2.c37
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.c2
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c2
-rw-r--r--drivers/net/ethernet/microchip/lan743x_ethtool.c217
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c27
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.h17
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c13
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.h1
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c68
-rw-r--r--drivers/net/ethernet/mscc/ocelot.h1
-rw-r--r--drivers/net/ethernet/mscc/ocelot_board.c16
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c8
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c2
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c72
-rw-r--r--drivers/net/ethernet/natsemi/sonic.c2
-rw-r--r--drivers/net/ethernet/neterion/s2io.c2
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c4
-rw-r--r--drivers/net/ethernet/netronome/Kconfig1
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/jit.c246
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.h51
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/offload.c13
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/verifier.c74
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/action.c201
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/cmsg.c8
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/cmsg.h3
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/main.c109
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/main.h89
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/match.c413
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/metadata.c27
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c155
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c612
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_app.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_devlink.c181
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_main.c41
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_main.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c17
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c53
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_repr.c5
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_port.c23
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_port.h4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c346
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h21
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c6
-rw-r--r--drivers/net/ethernet/ni/nixge.c130
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c2
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c12
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c2
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c4
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c6
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed.h13
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_cxt.c29
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c261
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev_api.h12
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hsi.h3
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.c11
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.c126
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_int.h3
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iwarp.c21
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iwarp.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c24
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.h3
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ll2.c24
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c32
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c121
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.h56
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ptp.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_reg_addr.h2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sp_commands.c3
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_spq.c37
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_sriov.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.c10
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede.h8
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_ethtool.c11
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_filter.c572
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_fp.c13
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c295
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_rdma.c63
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c28
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c4
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-mac.c4
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c2
-rw-r--r--drivers/net/ethernet/realtek/atp.c27
-rw-r--r--drivers/net/ethernet/realtek/r8169.c770
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c12
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c79
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h3
-rw-r--r--drivers/net/ethernet/rocker/rocker.h2
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c125
-rw-r--r--drivers/net/ethernet/rocker/rocker_ofdpa.c15
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c12
-rw-r--r--drivers/net/ethernet/sfc/ef10.c45
-rw-r--r--drivers/net/ethernet/sfc/efx.c2
-rw-r--r--drivers/net/ethernet/sfc/falcon/nic.c4
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c56
-rw-r--r--drivers/net/ethernet/sfc/mcdi_pcol.h8
-rw-r--r--drivers/net/ethernet/sfc/mtd.c3
-rw-r--r--drivers/net/ethernet/sfc/nic.c4
-rw-r--r--drivers/net/ethernet/sfc/rx.c3
-rw-r--r--drivers/net/ethernet/sfc/tx.c2
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c2
-rw-r--r--drivers/net/ethernet/sgi/meth.c27
-rw-r--r--drivers/net/ethernet/sis/sis190.c2
-rw-r--r--drivers/net/ethernet/sis/sis900.c2
-rw-r--r--drivers/net/ethernet/smsc/epic100.c2
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c4
-rw-r--r--drivers/net/ethernet/socionext/netsec.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c545
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c24
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c36
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c254
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c2
-rw-r--r--drivers/net/ethernet/sun/cassini.c17
-rw-r--r--drivers/net/ethernet/sun/cassini.h15
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c2
-rw-r--r--drivers/net/ethernet/sun/sungem.c2
-rw-r--r--drivers/net/ethernet/sun/sunhme.c2
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c2
-rw-r--r--drivers/net/ethernet/ti/Kconfig6
-rw-r--r--drivers/net/ethernet/ti/cpmac.c2
-rw-r--r--drivers/net/ethernet/ti/cpsw-phy-sel.c4
-rw-r--r--drivers/net/ethernet/ti/cpsw.h6
-rw-r--r--drivers/net/ethernet/ti/netcp_core.c2
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c8
-rw-r--r--drivers/net/ethernet/via/via-velocity.c2
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c14
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c14
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c2
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c2
-rw-r--r--drivers/net/fddi/defxx.c8
-rw-r--r--drivers/net/fddi/skfp/pcmplc.c1
-rw-r--r--drivers/net/fddi/skfp/skfddi.c8
-rw-r--r--drivers/net/geneve.c21
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c26
-rw-r--r--drivers/net/hyperv/hyperv_net.h12
-rw-r--r--drivers/net/hyperv/netvsc.c4
-rw-r--r--drivers/net/hyperv/netvsc_drv.c167
-rw-r--r--drivers/net/hyperv/rndis_filter.c36
-rw-r--r--drivers/net/ieee802154/mcr20a.c6
-rw-r--r--drivers/net/ipvlan/Makefile3
-rw-r--r--drivers/net/ipvlan/ipvlan.h37
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c105
-rw-r--r--drivers/net/ipvlan/ipvlan_l3s.c227
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c121
-rw-r--r--drivers/net/macvlan.c12
-rw-r--r--drivers/net/netdevsim/bpf.c5
-rw-r--r--drivers/net/netdevsim/netdev.c23
-rw-r--r--drivers/net/phy/Kconfig12
-rw-r--r--drivers/net/phy/Makefile5
-rw-r--r--drivers/net/phy/amd.c7
-rw-r--r--drivers/net/phy/aquantia.c193
-rw-r--r--drivers/net/phy/aquantia.h16
-rw-r--r--drivers/net/phy/aquantia_hwmon.c250
-rw-r--r--drivers/net/phy/aquantia_main.c283
-rw-r--r--drivers/net/phy/asix.c8
-rw-r--r--drivers/net/phy/at803x.c77
-rw-r--r--drivers/net/phy/bcm-cygnus.c10
-rw-r--r--drivers/net/phy/bcm-phy-lib.c10
-rw-r--r--drivers/net/phy/bcm-phy-lib.h10
-rw-r--r--drivers/net/phy/bcm63xx.c6
-rw-r--r--drivers/net/phy/bcm7xxx.c6
-rw-r--r--drivers/net/phy/bcm87xx.c9
-rw-r--r--drivers/net/phy/broadcom.c6
-rw-r--r--drivers/net/phy/cicada.c7
-rw-r--r--drivers/net/phy/cortina.c15
-rw-r--r--drivers/net/phy/davicom.c7
-rw-r--r--drivers/net/phy/dp83640.c28
-rw-r--r--drivers/net/phy/dp83822.c12
-rw-r--r--drivers/net/phy/dp83848.c12
-rw-r--r--drivers/net/phy/dp83867.c62
-rw-r--r--drivers/net/phy/dp83tc811.c15
-rw-r--r--drivers/net/phy/et1011c.c7
-rw-r--r--drivers/net/phy/fixed_phy.c121
-rw-r--r--drivers/net/phy/icplus.c7
-rw-r--r--drivers/net/phy/intel-xway.c11
-rw-r--r--drivers/net/phy/lxt.c7
-rw-r--r--drivers/net/phy/marvell.c60
-rw-r--r--drivers/net/phy/marvell10g.c237
-rw-r--r--drivers/net/phy/mdio-bcm-iproc.c10
-rw-r--r--drivers/net/phy/mdio-bcm-unimac.c6
-rw-r--r--drivers/net/phy/mdio-bitbang.c7
-rw-r--r--drivers/net/phy/mdio-boardinfo.c6
-rw-r--r--drivers/net/phy/mdio-cavium.c7
-rw-r--r--drivers/net/phy/mdio-cavium.h5
-rw-r--r--drivers/net/phy/mdio-gpio.c7
-rw-r--r--drivers/net/phy/mdio-hisi-femac.c16
-rw-r--r--drivers/net/phy/mdio-i2c.c5
-rw-r--r--drivers/net/phy/mdio-i2c.h5
-rw-r--r--drivers/net/phy/mdio-moxart.c7
-rw-r--r--drivers/net/phy/mdio-mux-bcm-iproc.c13
-rw-r--r--drivers/net/phy/mdio-mux-gpio.c7
-rw-r--r--drivers/net/phy/mdio-mux-mmioreg.c5
-rw-r--r--drivers/net/phy/mdio-mux-multiplexer.c122
-rw-r--r--drivers/net/phy/mdio-mux.c7
-rw-r--r--drivers/net/phy/mdio-octeon.c7
-rw-r--r--drivers/net/phy/mdio-sun4i.c7
-rw-r--r--drivers/net/phy/mdio-thunder.c7
-rw-r--r--drivers/net/phy/mdio-xgene.c14
-rw-r--r--drivers/net/phy/mdio-xgene.h14
-rw-r--r--drivers/net/phy/mdio_bus.c22
-rw-r--r--drivers/net/phy/mdio_device.c7
-rw-r--r--drivers/net/phy/meson-gxl.c13
-rw-r--r--drivers/net/phy/micrel.c64
-rw-r--r--drivers/net/phy/microchip.c14
-rw-r--r--drivers/net/phy/mscc.c1
-rw-r--r--drivers/net/phy/national.c7
-rw-r--r--drivers/net/phy/phy-c45.c313
-rw-r--r--drivers/net/phy/phy-core.c354
-rw-r--r--drivers/net/phy/phy.c152
-rw-r--r--drivers/net/phy/phy_device.c410
-rw-r--r--drivers/net/phy/phy_led_triggers.c14
-rw-r--r--drivers/net/phy/phylink.c64
-rw-r--r--drivers/net/phy/qsemi.c7
-rw-r--r--drivers/net/phy/realtek.c23
-rw-r--r--drivers/net/phy/rockchip.c9
-rw-r--r--drivers/net/phy/sfp-bus.c2
-rw-r--r--drivers/net/phy/sfp.c31
-rw-r--r--drivers/net/phy/sfp.h2
-rw-r--r--drivers/net/phy/smsc.c6
-rw-r--r--drivers/net/phy/spi_ks8995.c5
-rw-r--r--drivers/net/phy/ste10Xp.c7
-rw-r--r--drivers/net/phy/swphy.c16
-rw-r--r--drivers/net/phy/teranetics.c9
-rw-r--r--drivers/net/phy/uPD60620.c7
-rw-r--r--drivers/net/phy/vitesse.c9
-rw-r--r--drivers/net/phy/xilinx_gmii2rgmii.c16
-rw-r--r--drivers/net/ppp/pppoe.c1
-rw-r--r--drivers/net/sb1000.c11
-rw-r--r--drivers/net/tap.c4
-rw-r--r--drivers/net/team/team.c32
-rw-r--r--drivers/net/team/team_mode_loadbalance.c15
-rw-r--r--drivers/net/tun.c22
-rw-r--r--drivers/net/usb/aqc111.c15
-rw-r--r--drivers/net/usb/asix_devices.c9
-rw-r--r--drivers/net/usb/cdc-phonet.c4
-rw-r--r--drivers/net/usb/cdc_ether.c34
-rw-r--r--drivers/net/usb/lan78xx.c3
-rw-r--r--drivers/net/usb/pegasus.c1
-rw-r--r--drivers/net/usb/qmi_wwan.c31
-rw-r--r--drivers/net/usb/r8152.c5
-rw-r--r--drivers/net/usb/rtl8150.c3
-rw-r--r--drivers/net/usb/sr9700.c2
-rw-r--r--drivers/net/veth.c7
-rw-r--r--drivers/net/virtio_net.c182
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c8
-rw-r--r--drivers/net/vrf.c3
-rw-r--r--drivers/net/vxlan.c589
-rw-r--r--drivers/net/wan/cosa.c2
-rw-r--r--drivers/net/wan/dscc4.c52
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c71
-rw-r--r--drivers/net/wan/ixp4xx_hss.c2
-rw-r--r--drivers/net/wan/lmc/Makefile2
-rw-r--r--drivers/net/wan/lmc/lmc_main.c3
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wan/wanxl.c7
-rw-r--r--drivers/net/wan/z85230.c2
-rw-r--r--drivers/net/wimax/i2400m/rx.c4
-rw-r--r--drivers/net/wimax/i2400m/usb.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c188
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h31
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c76
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h44
-rw-r--r--drivers/net/wireless/ath/ath10k/coredump.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/coredump.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h33
-rw-r--r--drivers/net/wireless/ath/ath10k/debugfs_sta.c30
-rw-r--r--drivers/net/wireless/ath/ath10k/hif.h29
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c22
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h14
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h135
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c153
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c70
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c55
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h48
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c257
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c65
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h16
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c242
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h47
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c83
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c93
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.h15
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/swap.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/swap.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/targaddrs.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode_i.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/thermal.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/thermal.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/trace.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/trace.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c19
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/usb.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/usb.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h44
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c197
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h68
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c135
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h121
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.h13
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/debug_sta.c70
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c247
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c2
-rw-r--r--drivers/net/wireless/ath/regd.h2
-rw-r--r--drivers/net/wireless/ath/regd_common.h2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c17
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c20
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c23
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c13
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c10
-rw-r--r--drivers/net/wireless/ath/wil6210/trace.h3
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c254
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h51
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx_edma.c19
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h16
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c83
-rw-r--r--drivers/net/wireless/broadcom/b43/debugfs.c36
-rw-r--r--drivers/net/wireless/broadcom/b43/dma.c6
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/debugfs.c35
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/dma.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c22
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c577
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c48
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c135
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h19
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c15
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c22
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c25
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h18
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c38
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c114
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c88
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c81
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c27
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c71
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c9
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c26
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c13
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile4
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945-mac.c5
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c5
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.h6
-rw-r--r--drivers/net/wireless/intel/iwlegacy/debug.c34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Kconfig3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c162
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c141
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/agn.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rx.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/scan.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tt.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/alive.h48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h55
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h180
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/debug.h33
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h878
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h51
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/stats.h15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tof.h393
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tx.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c1302
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h107
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h106
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/init.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h67
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-debug.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c104
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c120
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.h82
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-modparams.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c96
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/Makefile4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c813
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c229
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c654
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c244
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c148
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/led.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c322
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c577
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h262
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c177
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c56
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c197
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sf.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c519
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c33
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tof.c305
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tof.h89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c186
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c297
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h74
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c227
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c254
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c75
-rw-r--r--drivers/net/wireless/intersil/orinoco/mic.c10
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c14
-rw-r--r--drivers/net/wireless/marvell/libertas/debugfs.c6
-rw-r--r--drivers/net/wireless/marvell/libertas/mesh.c5
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/cmd.c9
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/if_usb.c38
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/libertas_tf.h18
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/main.c105
-rw-r--r--drivers/net/wireless/marvell/mwifiex/Kconfig2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c23
-rw-r--r--drivers/net/wireless/marvell/mwifiex/debugfs.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/ioctl.h1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.h70
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_ioctl.c11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_event.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/Kconfig1
-rw-r--r--drivers/net/wireless/mediatek/mt76/Makefile6
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c60
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/eeprom.c24
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c82
-rw-r--r--drivers/net/wireless/mediatek/mt76/mcu.c60
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h72
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/Kconfig9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/Makefile6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/beacon.c186
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/core.c73
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c56
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/dma.c215
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c168
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h86
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/init.c578
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mac.c1749
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mac.h242
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/main.c709
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mcu.c483
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mcu.h110
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h253
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/pci.c80
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/regs.h774
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/soc.c85
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c54
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/init.c41
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/main.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci.c30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/phy.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb.c82
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02.h30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.c303
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.h18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c70
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c166
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_phy.c47
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_phy.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_regs.h38
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c14
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c102
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.c167
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/init.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mac.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mac.h8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci.c26
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c96
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/phy.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb.c35
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c37
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c24
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c22
-rw-r--r--drivers/net/wireless/mediatek/mt76/usb.c210
-rw-r--r--drivers/net/wireless/mediatek/mt76/usb_mcu.c56
-rw-r--r--drivers/net/wireless/mediatek/mt76/util.c42
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/dma.c6
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/eeprom.h2
-rw-r--r--drivers/net/wireless/quantenna/Makefile1
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/bus.h19
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c83
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c92
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.h24
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c21
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/debug.c31
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/debug.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c197
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c6
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink.h63
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink_util.c16
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink_util.h28
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/trans.c17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/trans.h17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/util.c17
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/util.h17
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c143
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00debug.c27
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c6
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt61pci.c93
-rw-r--r--drivers/net/wireless/ray_cs.c4
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c8
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c35
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/cam.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/cam.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.c39
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.c79
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rc.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rc.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.c35
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c45
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c51
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c73
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c37
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h85
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c138
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c38
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c313
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h24
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c138
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c95
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c50
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c92
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c94
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h54
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h33
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c48
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c70
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h75
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h20
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c121
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h44
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c29
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h23
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c32
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c128
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h25
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c260
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c158
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h30
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h60
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c213
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h28
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/stats.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/stats.h26
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c33
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.h31
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h403
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_debugfs.c13
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_hal.c3
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c106
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_main.c7
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c174
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c39
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c9
-rw-r--r--drivers/net/wireless/rsi/rsi_main.h23
-rw-r--r--drivers/net/wireless/rsi/rsi_mgmt.h35
-rw-r--r--drivers/net/wireless/st/cw1200/debug.c26
-rw-r--r--drivers/net/wireless/st/cw1200/fwio.c4
-rw-r--r--drivers/net/wireless/st/cw1200/queue.c1
-rw-r--r--drivers/net/wireless/st/cw1200/scan.c5
-rw-r--r--drivers/net/wireless/ti/wl1251/debugfs.c59
-rw-r--r--drivers/net/wireless/ti/wl12xx/debugfs.c20
-rw-r--r--drivers/net/wireless/ti/wl18xx/debugfs.c20
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c28
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.h10
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c15
-rw-r--r--drivers/net/wireless/virt_wifi.c12
-rw-r--r--drivers/net/xen-netback/hash.c2
-rw-r--r--drivers/net/xen-netback/interface.c7
-rw-r--r--drivers/net/xen-netback/netback.c25
-rw-r--r--drivers/net/xen-netback/xenbus.c2
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.h30
-rw-r--r--drivers/ntb/hw/mscc/ntb_hw_switchtec.c44
-rw-r--r--drivers/nvdimm/bus.c11
-rw-r--r--drivers/nvdimm/dimm.c6
-rw-r--r--drivers/nvdimm/dimm_devs.c22
-rw-r--r--drivers/nvdimm/nd-core.h4
-rw-r--r--drivers/nvdimm/nd.h1
-rw-r--r--drivers/nvme/host/core.c27
-rw-r--r--drivers/nvme/host/fabrics.c2
-rw-r--r--drivers/nvme/host/multipath.c5
-rw-r--r--drivers/nvme/host/nvme.h6
-rw-r--r--drivers/nvme/host/pci.c217
-rw-r--r--drivers/nvme/host/rdma.c64
-rw-r--r--drivers/nvme/host/tcp.c35
-rw-r--r--drivers/nvme/target/rdma.c15
-rw-r--r--drivers/nvme/target/tcp.c2
-rw-r--r--drivers/nvmem/Kconfig12
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/bcm-ocotp.c37
-rw-r--r--drivers/nvmem/core.c42
-rw-r--r--drivers/nvmem/imx-ocotp.c13
-rw-r--r--drivers/nvmem/sc27xx-efuse.c12
-rw-r--r--drivers/nvmem/zynqmp_nvmem.c86
-rw-r--r--drivers/of/dynamic.c3
-rw-r--r--drivers/of/fdt.c4
-rw-r--r--drivers/of/of_mdio.c9
-rw-r--r--drivers/of/overlay.c3
-rw-r--r--drivers/of/pdt.c1
-rw-r--r--drivers/of/property.c1
-rw-r--r--drivers/opp/core.c103
-rw-r--r--drivers/opp/debugfs.c110
-rw-r--r--drivers/opp/of.c101
-rw-r--r--drivers/opp/opp.h17
-rw-r--r--drivers/parisc/ccio-dma.c11
-rw-r--r--drivers/parisc/dino.c11
-rw-r--r--drivers/parisc/eisa.c2
-rw-r--r--drivers/parisc/hppb.c2
-rw-r--r--drivers/parisc/iommu.h55
-rw-r--r--drivers/parisc/iosapic.c17
-rw-r--r--drivers/parisc/lba_pci.c30
-rw-r--r--drivers/parisc/sba_iommu.c2
-rw-r--r--drivers/parport/daisy.c32
-rw-r--r--drivers/parport/parport_pc.c2
-rw-r--r--drivers/parport/probe.c2
-rw-r--r--drivers/parport/share.c10
-rw-r--r--drivers/pci/Kconfig22
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c11
-rw-r--r--drivers/pci/controller/dwc/pci-meson.c1
-rw-r--r--drivers/pci/controller/dwc/pcie-armada8k.c16
-rw-r--r--drivers/pci/controller/pcie-iproc-msi.c6
-rw-r--r--drivers/pci/msi.c61
-rw-r--r--drivers/pci/pci-sysfs.c5
-rw-r--r--drivers/pci/pci.c10
-rw-r--r--drivers/pci/quirks.c5
-rw-r--r--drivers/pci/switch/switchtec.c8
-rw-r--r--drivers/perf/arm-cci.c10
-rw-r--r--drivers/perf/arm-ccn.c6
-rw-r--r--drivers/perf/arm_dsu_pmu.c9
-rw-r--r--drivers/perf/arm_pmu.c15
-rw-r--r--drivers/perf/arm_spe_pmu.c6
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c1
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_hha_pmu.c1
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c1
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pmu.c9
-rw-r--r--drivers/perf/qcom_l2_pmu.c9
-rw-r--r--drivers/perf/qcom_l3_pmu.c8
-rw-r--r--drivers/perf/thunderx2_pmu.c10
-rw-r--r--drivers/perf/xgene_pmu.c6
-rw-r--r--drivers/phy/broadcom/phy-bcm-sr-pcie.c4
-rw-r--r--drivers/phy/cadence/Kconfig13
-rw-r--r--drivers/phy/cadence/Makefile1
-rw-r--r--drivers/phy/cadence/cdns-dphy.c391
-rw-r--r--drivers/phy/freescale/Kconfig2
-rw-r--r--drivers/phy/marvell/Kconfig31
-rw-r--r--drivers/phy/marvell/Makefile3
-rw-r--r--drivers/phy/marvell/phy-armada375-usb2.c13
-rw-r--r--drivers/phy/marvell/phy-armada38x-comphy.c237
-rw-r--r--drivers/phy/marvell/phy-berlin-sata.c5
-rw-r--r--drivers/phy/marvell/phy-mvebu-a3700-comphy.c318
-rw-r--r--drivers/phy/marvell/phy-mvebu-a3700-utmi.c278
-rw-r--r--drivers/phy/marvell/phy-mvebu-cp110-comphy.c2
-rw-r--r--drivers/phy/marvell/phy-mvebu-sata.c9
-rw-r--r--drivers/phy/phy-core-mipi-dphy.c8
-rw-r--r--drivers/phy/phy-core.c12
-rw-r--r--drivers/phy/qualcomm/phy-ath79-usb.c4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.c143
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.h4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c40
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-i.h19
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c48
-rw-r--r--drivers/phy/ti/Kconfig7
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c4
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c105
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c8
-rw-r--r--drivers/pinctrl/mediatek/Kconfig3
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson8b.c2
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.c7
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs404.c2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c44
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.h2
-rw-r--r--drivers/platform/goldfish/Kconfig4
-rw-r--r--drivers/platform/x86/Kconfig8
-rw-r--r--drivers/platform/x86/intel_cht_int33fe.c15
-rw-r--r--drivers/platform/x86/sony-laptop.c8
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c14
-rw-r--r--drivers/powercap/intel_rapl.c2
-rw-r--r--drivers/ptp/Kconfig4
-rw-r--r--drivers/ptp/Makefile4
-rw-r--r--drivers/ptp/ptp_chardev.c3
-rw-r--r--drivers/ptp/ptp_clock.c2
-rw-r--r--drivers/ptp/ptp_qoriq.c518
-rw-r--r--drivers/ptp/ptp_qoriq_debugfs.c101
-rw-r--r--drivers/rapidio/devices/tsi721.c22
-rw-r--r--drivers/rapidio/devices/tsi721_dma.c8
-rw-r--r--drivers/rapidio/rio-sysfs.c5
-rw-r--r--drivers/regulator/88pm8607.c38
-rw-r--r--drivers/regulator/Kconfig27
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/act8865-regulator.c5
-rw-r--r--drivers/regulator/act8945a-regulator.c11
-rw-r--r--drivers/regulator/arizona-ldo1.c56
-rw-r--r--drivers/regulator/as3722-regulator.c2
-rw-r--r--drivers/regulator/axp20x-regulator.c27
-rw-r--r--drivers/regulator/bcm590xx-regulator.c4
-rw-r--r--drivers/regulator/bd70528-regulator.c289
-rw-r--r--drivers/regulator/bd718x7-regulator.c215
-rw-r--r--drivers/regulator/bd9571mwv-regulator.c8
-rw-r--r--drivers/regulator/core.c88
-rw-r--r--drivers/regulator/cpcap-regulator.c106
-rw-r--r--drivers/regulator/da9052-regulator.c64
-rw-r--r--drivers/regulator/da9055-regulator.c46
-rw-r--r--drivers/regulator/da9062-regulator.c37
-rw-r--r--drivers/regulator/da9063-regulator.c37
-rw-r--r--drivers/regulator/da9210-regulator.c53
-rw-r--r--drivers/regulator/fan53555.c109
-rw-r--r--drivers/regulator/fixed.c35
-rw-r--r--drivers/regulator/gpio-regulator.c194
-rw-r--r--drivers/regulator/helpers.c125
-rw-r--r--drivers/regulator/hi655x-regulator.c1
-rw-r--r--drivers/regulator/isl6271a-regulator.c13
-rw-r--r--drivers/regulator/lm363x-regulator.c6
-rw-r--r--drivers/regulator/lochnagar-regulator.c7
-rw-r--r--drivers/regulator/lp3971.c4
-rw-r--r--drivers/regulator/lp3972.c4
-rw-r--r--drivers/regulator/lp872x.c82
-rw-r--r--drivers/regulator/lp873x-regulator.c51
-rw-r--r--drivers/regulator/lp8755.c6
-rw-r--r--drivers/regulator/lp87565-regulator.c4
-rw-r--r--drivers/regulator/lp8788-buck.c40
-rw-r--r--drivers/regulator/lp8788-ldo.c4
-rw-r--r--drivers/regulator/ltc3676.c65
-rw-r--r--drivers/regulator/max14577-regulator.c1
-rw-r--r--drivers/regulator/max77620-regulator.c12
-rw-r--r--drivers/regulator/max77650-regulator.c498
-rw-r--r--drivers/regulator/max77802-regulator.c6
-rw-r--r--drivers/regulator/mc13783-regulator.c82
-rw-r--r--drivers/regulator/mc13892-regulator.c72
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c4
-rw-r--r--drivers/regulator/mc13xxx.h24
-rw-r--r--drivers/regulator/mcp16502.c2
-rw-r--r--drivers/regulator/mt6311-regulator.c10
-rw-r--r--drivers/regulator/of_regulator.c4
-rw-r--r--drivers/regulator/palmas-regulator.c2
-rw-r--r--drivers/regulator/pv88060-regulator.c62
-rw-r--r--drivers/regulator/pv88080-regulator.c55
-rw-r--r--drivers/regulator/pv88090-regulator.c53
-rw-r--r--drivers/regulator/pwm-regulator.c17
-rw-r--r--drivers/regulator/qcom_smd-regulator.c104
-rw-r--r--drivers/regulator/rk808-regulator.c64
-rw-r--r--drivers/regulator/rt5033-regulator.c4
-rw-r--r--drivers/regulator/s2mpa01.c10
-rw-r--r--drivers/regulator/s2mps11.c6
-rw-r--r--drivers/regulator/s5m8767.c8
-rw-r--r--drivers/regulator/stm32-vrefbuf.c121
-rw-r--r--drivers/regulator/stpmic1_regulator.c300
-rw-r--r--drivers/regulator/tps65218-regulator.c23
-rw-r--r--drivers/regulator/twl-regulator.c7
-rw-r--r--drivers/regulator/twl6030-regulator.c88
-rw-r--r--drivers/regulator/uniphier-regulator.c8
-rw-r--r--drivers/regulator/wm831x-dcdc.c85
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c9
-rw-r--r--drivers/reset/Kconfig32
-rw-r--r--drivers/reset/Makefile5
-rw-r--r--drivers/reset/core.c42
-rw-r--r--drivers/reset/reset-brcmstb.c132
-rw-r--r--drivers/reset/reset-hsdk.c1
-rw-r--r--drivers/reset/reset-imx7.c172
-rw-r--r--drivers/reset/reset-simple.c13
-rw-r--r--drivers/reset/reset-socfpga.c88
-rw-r--r--drivers/reset/reset-sunxi.c1
-rw-r--r--drivers/reset/reset-uniphier-glue.c (renamed from drivers/reset/reset-uniphier-usb3.c)50
-rw-r--r--drivers/reset/reset-zynqmp.c114
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_eckd.c8
-rw-r--r--drivers/s390/char/sclp.h4
-rw-r--r--drivers/s390/char/sclp_config.c2
-rw-r--r--drivers/s390/char/sclp_early.c2
-rw-r--r--drivers/s390/cio/qdio_setup.c6
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c55
-rw-r--r--drivers/s390/crypto/ap_bus.c22
-rw-r--r--drivers/s390/crypto/ap_bus.h3
-rw-r--r--drivers/s390/crypto/ap_queue.c7
-rw-r--r--drivers/s390/crypto/pkey_api.c2
-rw-r--r--drivers/s390/crypto/vfio_ap_drv.c44
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c4
-rw-r--r--drivers/s390/crypto/vfio_ap_private.h1
-rw-r--r--drivers/s390/net/Makefile2
-rw-r--r--drivers/s390/net/ism_drv.c27
-rw-r--r--drivers/s390/net/qeth_core.h167
-rw-r--r--drivers/s390/net/qeth_core_main.c1223
-rw-r--r--drivers/s390/net/qeth_core_mpc.c23
-rw-r--r--drivers/s390/net/qeth_core_mpc.h17
-rw-r--r--drivers/s390/net/qeth_core_sys.c64
-rw-r--r--drivers/s390/net/qeth_ethtool.c370
-rw-r--r--drivers/s390/net/qeth_l2_main.c556
-rw-r--r--drivers/s390/net/qeth_l3_main.c366
-rw-r--r--drivers/s390/net/qeth_l3_sys.c12
-rw-r--r--drivers/s390/scsi/zfcp_aux.c1
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c4
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c2
-rw-r--r--drivers/s390/virtio/virtio_ccw.c12
-rw-r--r--drivers/scsi/3w-9xxx.c14
-rw-r--r--drivers/scsi/3w-sas.c17
-rw-r--r--drivers/scsi/53c700.c2
-rw-r--r--drivers/scsi/Kconfig6
-rw-r--r--drivers/scsi/a100u2w.c8
-rw-r--r--drivers/scsi/aacraid/linit.c9
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c16
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c18
-rw-r--r--drivers/scsi/atari_scsi.c10
-rw-r--r--drivers/scsi/be2iscsi/be_main.c6
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c11
-rw-r--r--drivers/scsi/bfa/bfad.c18
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c6
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c49
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c4
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c44
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c8
-rw-r--r--drivers/scsi/csiostor/csio_attr.c2
-rw-r--r--drivers/scsi/csiostor/csio_init.c7
-rw-r--r--drivers/scsi/csiostor/csio_wr.c4
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c9
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c28
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c7
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h5
-rw-r--r--drivers/scsi/cxlflash/main.c2
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c8
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c20
-rw-r--r--drivers/scsi/hptiop.c10
-rw-r--r--drivers/scsi/isci/init.c14
-rw-r--r--drivers/scsi/libfc/fc_lport.c6
-rw-r--r--drivers/scsi/libfc/fc_rport.c1
-rw-r--r--drivers/scsi/libiscsi.c6
-rw-r--r--drivers/scsi/libsas/sas_expander.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c16
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c35
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c15
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c28
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c8
-rw-r--r--drivers/scsi/mesh.c5
-rw-r--r--drivers/scsi/mvumi.c9
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c6
-rw-r--r--drivers/scsi/qedf/qedf_main.c29
-rw-r--r--drivers/scsi/qedi/qedi_iscsi.c3
-rw-r--r--drivers/scsi/qedi/qedi_iscsi.h1
-rw-r--r--drivers/scsi/qedi/qedi_main.c39
-rw-r--r--drivers/scsi/qla1280.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c18
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c12
-rw-r--r--drivers/scsi/scsi_debug.c41
-rw-r--r--drivers/scsi/scsi_lib.c6
-rw-r--r--drivers/scsi/scsi_pm.c26
-rw-r--r--drivers/scsi/sd.c18
-rw-r--r--drivers/scsi/sd_zbc.c20
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c34
-rw-r--r--drivers/scsi/ufs/ufs.h2
-rw-r--r--drivers/scsi/ufs/ufshcd.c12
-rw-r--r--drivers/slimbus/core.c45
-rw-r--r--drivers/soc/amlogic/meson-canvas.c18
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c196
-rw-r--r--drivers/soc/bcm/Kconfig12
-rw-r--r--drivers/soc/bcm/Makefile1
-rw-r--r--drivers/soc/bcm/bcm2835-power.c661
-rw-r--r--drivers/soc/fsl/Kconfig1
-rw-r--r--drivers/soc/fsl/dpio/dpio-cmd.h6
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c93
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c46
-rw-r--r--drivers/soc/fsl/dpio/dpio.c39
-rw-r--r--drivers/soc/fsl/dpio/dpio.h9
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.c5
-rw-r--r--drivers/soc/fsl/guts.c10
-rw-r--r--drivers/soc/fsl/qbman/dpaa_sys.c2
-rw-r--r--drivers/soc/fsl/qbman/qman.c9
-rw-r--r--drivers/soc/fsl/qe/qe_tdm.c55
-rw-r--r--drivers/soc/imx/Kconfig2
-rw-r--r--drivers/soc/imx/gpcv2.c76
-rw-r--r--drivers/soc/lantiq/Makefile1
-rw-r--r--drivers/soc/lantiq/gphy.c224
-rw-r--r--drivers/soc/qcom/Kconfig18
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/llcc-sdm845.c6
-rw-r--r--drivers/soc/qcom/llcc-slice.c101
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c7
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c32
-rw-r--r--drivers/soc/qcom/rpmh.c37
-rw-r--r--drivers/soc/qcom/rpmhpd.c406
-rw-r--r--drivers/soc/qcom/rpmpd.c315
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/renesas/Kconfig2
-rw-r--r--drivers/soc/renesas/r8a774c0-sysc.c23
-rw-r--r--drivers/soc/tegra/Kconfig1
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c12
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra210.c2
-rw-r--r--drivers/soc/tegra/pmc.c424
-rw-r--r--drivers/soc/ti/knav_dma.c2
-rw-r--r--drivers/soc/xilinx/Kconfig20
-rw-r--r--drivers/soc/xilinx/Makefile2
-rw-r--r--drivers/soc/xilinx/zynqmp_pm_domains.c321
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c178
-rw-r--r--drivers/spi/Kconfig36
-rw-r--r--drivers/spi/Makefile3
-rw-r--r--drivers/spi/atmel-quadspi.c270
-rw-r--r--drivers/spi/spi-ath79.c114
-rw-r--r--drivers/spi/spi-atmel.c102
-rw-r--r--drivers/spi/spi-bcm2835aux.c2
-rw-r--r--drivers/spi/spi-bitbang.c13
-rw-r--r--drivers/spi/spi-cadence.c84
-rw-r--r--drivers/spi/spi-clps711x.c23
-rw-r--r--drivers/spi/spi-davinci.c54
-rw-r--r--drivers/spi/spi-dw-mmio.c22
-rw-r--r--drivers/spi/spi-dw.c54
-rw-r--r--drivers/spi/spi-fsl-dspi.c42
-rw-r--r--drivers/spi/spi-fsl-lpspi.c92
-rw-r--r--drivers/spi/spi-fsl-qspi.c966
-rw-r--r--drivers/spi/spi-geni-qcom.c56
-rw-r--r--drivers/spi/spi-gpio.c4
-rw-r--r--drivers/spi/spi-mem.c72
-rw-r--r--drivers/spi/spi-mxs.c5
-rw-r--r--drivers/spi/spi-npcm-pspi.c3
-rw-r--r--drivers/spi/spi-nxp-fspi.c1106
-rw-r--r--drivers/spi/spi-omap2-mcspi.c4
-rw-r--r--drivers/spi/spi-pic32-sqi.c6
-rw-r--r--drivers/spi/spi-pl022.c30
-rw-r--r--drivers/spi/spi-pxa2xx-dma.c58
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c4
-rw-r--r--drivers/spi/spi-pxa2xx.c157
-rw-r--r--drivers/spi/spi-pxa2xx.h4
-rw-r--r--drivers/spi/spi-rspi.c170
-rw-r--r--drivers/spi/spi-sh-hspi.c39
-rw-r--r--drivers/spi/spi-sh-msiof.c184
-rw-r--r--drivers/spi/spi-sifive.c448
-rw-r--r--drivers/spi/spi-sprd.c354
-rw-r--r--drivers/spi/spi-stm32.c1403
-rw-r--r--drivers/spi/spi-ti-qspi.c6
-rw-r--r--drivers/spi/spi-topcliff-pch.c6
-rw-r--r--drivers/spi/spi.c115
-rw-r--r--drivers/staging/Kconfig6
-rw-r--r--drivers/staging/Makefile13
-rw-r--r--drivers/staging/android/ashmem.c70
-rw-r--r--drivers/staging/android/ion/Makefile2
-rw-r--r--drivers/staging/android/ion/ion-ioctl.c98
-rw-r--r--drivers/staging/android/ion/ion.c86
-rw-r--r--drivers/staging/android/ion/ion.h42
-rw-r--r--drivers/staging/android/ion/ion_carveout_heap.c19
-rw-r--r--drivers/staging/android/ion/ion_chunk_heap.c25
-rw-r--r--drivers/staging/android/ion/ion_cma_heap.c6
-rw-r--r--drivers/staging/android/ion/ion_heap.c8
-rw-r--r--drivers/staging/android/ion/ion_page_pool.c2
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c10
-rw-r--r--drivers/staging/android/uapi/ion.h2
-rw-r--r--drivers/staging/android/vsoc.c1
-rw-r--r--drivers/staging/comedi/comedi_fops.c3
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c444
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.c71
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.h4
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c2
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c31
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.h2
-rw-r--r--drivers/staging/erofs/Documentation/filesystems/erofs.txt208
-rw-r--r--drivers/staging/erofs/Makefile2
-rw-r--r--drivers/staging/erofs/data.c37
-rw-r--r--drivers/staging/erofs/dir.c12
-rw-r--r--drivers/staging/erofs/inode.c41
-rw-r--r--drivers/staging/erofs/internal.h147
-rw-r--r--drivers/staging/erofs/namei.c194
-rw-r--r--drivers/staging/erofs/super.c29
-rw-r--r--drivers/staging/erofs/unzip_vle.c165
-rw-r--r--drivers/staging/erofs/unzip_vle.h23
-rw-r--r--drivers/staging/erofs/unzip_vle_lz4.c21
-rw-r--r--drivers/staging/erofs/utils.c58
-rw-r--r--drivers/staging/erofs/xattr.c115
-rw-r--r--drivers/staging/erofs/xattr.h10
-rw-r--r--drivers/staging/fbtft/fb_agm1264k-fl.c52
-rw-r--r--drivers/staging/fbtft/fb_bd663474.c6
-rw-r--r--drivers/staging/fbtft/fb_ili9163.c6
-rw-r--r--drivers/staging/fbtft/fb_ili9320.c2
-rw-r--r--drivers/staging/fbtft/fb_ili9325.c6
-rw-r--r--drivers/staging/fbtft/fb_ili9340.c2
-rw-r--r--drivers/staging/fbtft/fb_pcd8544.c4
-rw-r--r--drivers/staging/fbtft/fb_ra8875.c4
-rw-r--r--drivers/staging/fbtft/fb_s6d1121.c6
-rw-r--r--drivers/staging/fbtft/fb_sh1106.c2
-rw-r--r--drivers/staging/fbtft/fb_ssd1289.c6
-rw-r--r--drivers/staging/fbtft/fb_ssd1305.c4
-rw-r--r--drivers/staging/fbtft/fb_ssd1306.c4
-rw-r--r--drivers/staging/fbtft/fb_ssd1325.c6
-rw-r--r--drivers/staging/fbtft/fb_ssd1331.c10
-rw-r--r--drivers/staging/fbtft/fb_ssd1351.c4
-rw-r--r--drivers/staging/fbtft/fb_tinylcd.c2
-rw-r--r--drivers/staging/fbtft/fb_tls8204.c6
-rw-r--r--drivers/staging/fbtft/fb_uc1611.c4
-rw-r--r--drivers/staging/fbtft/fb_uc1701.c6
-rw-r--r--drivers/staging/fbtft/fb_upd161704.c6
-rw-r--r--drivers/staging/fbtft/fb_watterott.c4
-rw-r--r--drivers/staging/fbtft/fbtft-bus.c6
-rw-r--r--drivers/staging/fbtft/fbtft-core.c178
-rw-r--r--drivers/staging/fbtft/fbtft-io.c26
-rw-r--r--drivers/staging/fbtft/fbtft.h21
-rw-r--r--drivers/staging/fbtft/fbtft_device.c344
-rw-r--r--drivers/staging/fbtft/flexfb.c12
-rw-r--r--drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h2
-rw-r--r--drivers/staging/fsl-dpaa2/ethsw/dpsw.h2
-rw-r--r--drivers/staging/fsl-dpaa2/ethsw/ethsw.c76
-rw-r--r--drivers/staging/fsl-dpaa2/ethsw/ethsw.h2
-rw-r--r--drivers/staging/fwserial/fwserial.c1
-rw-r--r--drivers/staging/gasket/gasket_interrupt.c1
-rw-r--r--drivers/staging/goldfish/goldfish_audio.c10
-rw-r--r--drivers/staging/greybus/Kconfig1
-rw-r--r--drivers/staging/greybus/TODO2
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c152
-rw-r--r--drivers/staging/greybus/arche-platform.c124
-rw-r--r--drivers/staging/greybus/audio_topology.c1
-rw-r--r--drivers/staging/greybus/bundle.c2
-rw-r--r--drivers/staging/greybus/connection.h2
-rw-r--r--drivers/staging/greybus/control.c1
-rw-r--r--drivers/staging/greybus/core.c2
-rw-r--r--drivers/staging/greybus/gpio.c156
-rw-r--r--drivers/staging/gs_fpgaboot/gs_fpgaboot.c12
-rw-r--r--drivers/staging/gs_fpgaboot/gs_fpgaboot.h12
-rw-r--r--drivers/staging/gs_fpgaboot/io.c16
-rw-r--r--drivers/staging/gs_fpgaboot/io.h12
-rw-r--r--drivers/staging/iio/adc/Kconfig34
-rw-r--r--drivers/staging/iio/adc/Makefile4
-rw-r--r--drivers/staging/iio/adc/ad7280a.c243
-rw-r--r--drivers/staging/iio/adc/ad7816.c7
-rw-r--r--drivers/staging/iio/addac/adt7316-i2c.c6
-rw-r--r--drivers/staging/iio/addac/adt7316-spi.c4
-rw-r--r--drivers/staging/iio/addac/adt7316.c143
-rw-r--r--drivers/staging/iio/cdc/Kconfig10
-rw-r--r--drivers/staging/iio/cdc/Makefile1
-rw-r--r--drivers/staging/iio/cdc/ad7152.c552
-rw-r--r--drivers/staging/iio/frequency/ad9834.c54
-rw-r--r--drivers/staging/iio/frequency/ad9834.h28
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c57
-rw-r--r--drivers/staging/ks7010/Makefile2
-rw-r--r--drivers/staging/ks7010/TODO2
-rw-r--r--drivers/staging/ks7010/ks_hostif.c119
-rw-r--r--drivers/staging/ks7010/ks_wlan_net.c2
-rw-r--r--drivers/staging/ks7010/michael_mic.c127
-rw-r--r--drivers/staging/ks7010/michael_mic.h21
-rw-r--r--drivers/staging/media/davinci_vpfe/Makefile2
-rw-r--r--drivers/staging/most/Makefile2
-rw-r--r--drivers/staging/most/cdev/Makefile2
-rw-r--r--drivers/staging/most/cdev/cdev.c5
-rw-r--r--drivers/staging/most/dim2/Makefile2
-rw-r--r--drivers/staging/most/i2c/Makefile2
-rw-r--r--drivers/staging/most/net/Makefile2
-rw-r--r--drivers/staging/most/sound/Makefile2
-rw-r--r--drivers/staging/most/usb/Makefile2
-rw-r--r--drivers/staging/most/video/Makefile2
-rw-r--r--drivers/staging/mt7621-dma/Kconfig6
-rw-r--r--drivers/staging/mt7621-dma/Makefile1
-rw-r--r--drivers/staging/mt7621-dma/mtk-hsdma.c11
-rw-r--r--drivers/staging/mt7621-dts/gbpc1.dts4
-rw-r--r--drivers/staging/mt7621-dts/mt7621.dtsi59
-rw-r--r--drivers/staging/mt7621-eth/ethtool.c1
-rw-r--r--drivers/staging/mt7621-eth/ethtool.h11
-rw-r--r--drivers/staging/mt7621-eth/mtk_eth_soc.c3
-rw-r--r--drivers/staging/mt7621-mmc/Kconfig2
-rw-r--r--drivers/staging/mt7621-mmc/dbg.c1
-rw-r--r--drivers/staging/mt7621-mmc/mt6575_sd.h2
-rw-r--r--drivers/staging/mt7621-pci-phy/Kconfig7
-rw-r--r--drivers/staging/mt7621-pci-phy/Makefile1
-rw-r--r--drivers/staging/mt7621-pci-phy/TODO4
-rw-r--r--drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt54
-rw-r--r--drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c387
-rw-r--r--drivers/staging/mt7621-pci/Makefile2
-rw-r--r--drivers/staging/mt7621-pci/TODO8
-rw-r--r--drivers/staging/mt7621-pci/pci-mt7621.c300
-rw-r--r--drivers/staging/mt7621-pinctrl/Kconfig1
-rw-r--r--drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c49
-rw-r--r--drivers/staging/mt7621-spi/spi-mt7621.c72
-rw-r--r--drivers/staging/netlogic/Kconfig2
-rw-r--r--drivers/staging/netlogic/platform_net.c51
-rw-r--r--drivers/staging/netlogic/platform_net.h32
-rw-r--r--drivers/staging/netlogic/xlr_net.c31
-rw-r--r--drivers/staging/netlogic/xlr_net.h33
-rw-r--r--drivers/staging/octeon-usb/octeon-hcd.h2
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c2
-rw-r--r--drivers/staging/ralink-gdma/Kconfig6
-rw-r--r--drivers/staging/ralink-gdma/Makefile3
-rw-r--r--drivers/staging/ralink-gdma/ralink-gdma.c (renamed from drivers/staging/mt7621-dma/ralink-gdma.c)6
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c8
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c12
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c4
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c10
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ioctl_set.c12
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c44
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c38
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_security.c6
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c18
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/odm.c11
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c67
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c4
-rw-r--r--drivers/staging/rtl8188eu/include/odm.h1
-rw-r--r--drivers/staging/rtl8188eu/include/odm_hwconfig.h9
-rw-r--r--drivers/staging/rtl8188eu/include/wifi.h12
-rw-r--r--drivers/staging/rtl8188eu/include/wlan_bssdef.h6
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c34
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mlme_linux.c72
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c26
-rw-r--r--drivers/staging/rtl8188eu/os_dep/rtw_android.c2
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c7
-rw-r--r--drivers/staging/rtl8192e/dot11d.c120
-rw-r--r--drivers/staging/rtl8192e/dot11d.h77
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c8
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c23
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c8
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c6
-rw-r--r--drivers/staging/rtl8192e/rtllib.h6
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c2
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c4
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c22
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c4
-rw-r--r--drivers/staging/rtl8192u/Makefile2
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c24
-rw-r--r--drivers/staging/rtl8712/ieee80211.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c2
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c2
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c8
-rw-r--r--drivers/staging/rtl8712/usb_intf.c16
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c8
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c2
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h1
-rw-r--r--drivers/staging/rtl8723bs/include/ieee80211.h6
-rw-r--r--drivers/staging/rtl8723bs/os_dep/osdep_service.c4
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_intf.c2
-rw-r--r--drivers/staging/rtlwifi/Kconfig2
-rw-r--r--drivers/staging/rtlwifi/efuse.c6
-rw-r--r--drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c5
-rw-r--r--drivers/staging/rtlwifi/pci.h3
-rw-r--r--drivers/staging/rtlwifi/phydm/phydm_rainfo.c2
-rw-r--r--drivers/staging/rtlwifi/rtl8822be/fw.c2
-rw-r--r--drivers/staging/rts5208/ms.c5
-rw-r--r--drivers/staging/rts5208/sd.c7
-rw-r--r--drivers/staging/sm750fb/ddk750_display.c6
-rw-r--r--drivers/staging/speakup/Kconfig32
-rw-r--r--drivers/staging/speakup/kobjects.c2
-rw-r--r--drivers/staging/speakup/main.c14
-rw-r--r--drivers/staging/speakup/speakup_decext.c3
-rw-r--r--drivers/staging/speakup/speakup_dectlk.c3
-rw-r--r--drivers/staging/speakup/speakup_soft.c4
-rw-r--r--drivers/staging/speakup/spk_priv_keyinfo.h9
-rw-r--r--drivers/staging/speakup/spk_ttyio.c26
-rw-r--r--drivers/staging/speakup/varhandlers.c4
-rw-r--r--drivers/staging/unisys/visorhba/Makefile3
-rw-r--r--drivers/staging/unisys/visornic/Makefile3
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c4
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/Makefile3
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/Makefile2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c6
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c1
-rw-r--r--drivers/staging/vt6655/baseband.c10
-rw-r--r--drivers/staging/vt6655/baseband.h2
-rw-r--r--drivers/staging/vt6655/card.c16
-rw-r--r--drivers/staging/vt6655/card.h2
-rw-r--r--drivers/staging/vt6655/device_main.c23
-rw-r--r--drivers/staging/vt6656/key.c4
-rw-r--r--drivers/staging/vt6656/mac.h2
-rw-r--r--drivers/staging/wilc1000/Makefile2
-rw-r--r--drivers/staging/wilc1000/host_interface.c1169
-rw-r--r--drivers/staging/wilc1000/host_interface.h165
-rw-r--r--drivers/staging/wilc1000/wilc_mon.c (renamed from drivers/staging/wilc1000/linux_mon.c)77
-rw-r--r--drivers/staging/wilc1000/wilc_netdev.c (renamed from drivers/staging/wilc1000/linux_wlan.c)430
-rw-r--r--drivers/staging/wilc1000/wilc_sdio.c187
-rw-r--r--drivers/staging/wilc1000/wilc_spi.c4
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c644
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.h7
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_netdevice.h14
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.c59
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.h38
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_cfg.c39
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_if.h40
-rw-r--r--drivers/staging/wlan-ng/Kconfig2
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c3
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c5
-rw-r--r--drivers/staging/xgifb/Kconfig11
-rw-r--r--drivers/staging/xgifb/Makefile4
-rw-r--r--drivers/staging/xgifb/TODO13
-rw-r--r--drivers/staging/xgifb/XGI_main.h365
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c2084
-rw-r--r--drivers/staging/xgifb/XGIfb.h109
-rw-r--r--drivers/staging/xgifb/vb_def.h257
-rw-r--r--drivers/staging/xgifb/vb_init.c1367
-rw-r--r--drivers/staging/xgifb/vb_init.h6
-rw-r--r--drivers/staging/xgifb/vb_setmode.c5528
-rw-r--r--drivers/staging/xgifb/vb_setmode.h24
-rw-r--r--drivers/staging/xgifb/vb_struct.h165
-rw-r--r--drivers/staging/xgifb/vb_table.h2513
-rw-r--r--drivers/staging/xgifb/vb_util.h46
-rw-r--r--drivers/staging/xgifb/vgatypes.h51
-rw-r--r--drivers/target/iscsi/iscsi_target.c2
-rw-r--r--drivers/target/target_core_configfs.c8
-rw-r--r--drivers/target/target_core_user.c89
-rw-r--r--drivers/tee/optee/Makefile1
-rw-r--r--drivers/tee/optee/core.c8
-rw-r--r--drivers/tee/optee/device.c160
-rw-r--r--drivers/tee/optee/optee_msg.h26
-rw-r--r--drivers/tee/optee/optee_private.h3
-rw-r--r--drivers/tee/optee/optee_smc.h26
-rw-r--r--drivers/tee/optee/supp.c10
-rw-r--r--drivers/tee/tee_core.c78
-rw-r--r--drivers/thermal/Kconfig1
-rw-r--r--drivers/thermal/cpu_cooling.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/Kconfig2
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c30
-rw-r--r--drivers/thermal/of-thermal.c4
-rw-r--r--drivers/tty/Kconfig24
-rw-r--r--drivers/tty/hvc/hvc_xen.c2
-rw-r--r--drivers/tty/ipwireless/hardware.c2
-rw-r--r--drivers/tty/n_gsm.c246
-rw-r--r--drivers/tty/n_hdlc.c3
-rw-r--r--drivers/tty/n_tty.c6
-rw-r--r--drivers/tty/nozomi.c10
-rw-r--r--drivers/tty/serdev/serdev-ttyport.c4
-rw-r--r--drivers/tty/serial/8250/8250_core.c17
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c13
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c3
-rw-r--r--drivers/tty/serial/8250/8250_of.c5
-rw-r--r--drivers/tty/serial/8250/8250_omap.c75
-rw-r--r--drivers/tty/serial/8250/8250_pci.c179
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c4
-rw-r--r--drivers/tty/serial/Kconfig34
-rw-r--r--drivers/tty/serial/Makefile2
-rw-r--r--drivers/tty/serial/clps711x.c23
-rw-r--r--drivers/tty/serial/earlycon-riscv-sbi.c31
-rw-r--r--drivers/tty/serial/fsl_lpuart.c210
-rw-r--r--drivers/tty/serial/lantiq.c36
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c4
-rw-r--r--drivers/tty/serial/max310x.c21
-rw-r--r--drivers/tty/serial/meson_uart.c13
-rw-r--r--drivers/tty/serial/mps2-uart.c138
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c283
-rw-r--r--drivers/tty/serial/samsung.c42
-rw-r--r--drivers/tty/serial/sc16is7xx.c4
-rw-r--r--drivers/tty/serial/serial_core.c20
-rw-r--r--drivers/tty/serial/sh-sci.c80
-rw-r--r--drivers/tty/serial/sprd_serial.c2
-rw-r--r--drivers/tty/serial/tegra-tcu.c298
-rw-r--r--drivers/tty/serial/xilinx_uartps.c40
-rw-r--r--drivers/tty/synclink.c54
-rw-r--r--drivers/tty/sysrq.c8
-rw-r--r--drivers/tty/tty_buffer.c2
-rw-r--r--drivers/tty/tty_io.c26
-rw-r--r--drivers/tty/tty_ldisc.c47
-rw-r--r--drivers/tty/vt/vc_screen.c48
-rw-r--r--drivers/tty/vt/vt.c127
-rw-r--r--drivers/uio/uio.c16
-rw-r--r--drivers/uio/uio_pci_generic.c17
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/README54
-rw-r--r--drivers/usb/atm/Kconfig1
-rw-r--r--drivers/usb/chipidea/Kconfig2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c9
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h1
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c1
-rw-r--r--drivers/usb/chipidea/core.c46
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c7
-rw-r--r--drivers/usb/class/Kconfig1
-rw-r--r--drivers/usb/class/cdc-acm.c7
-rw-r--r--drivers/usb/class/cdc-wdm.c2
-rw-r--r--drivers/usb/core/Kconfig13
-rw-r--r--drivers/usb/core/config.c14
-rw-r--r--drivers/usb/core/devio.c10
-rw-r--r--drivers/usb/core/driver.c23
-rw-r--r--drivers/usb/core/generic.c41
-rw-r--r--drivers/usb/core/hcd.c56
-rw-r--r--drivers/usb/core/hub.c66
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/ledtrig-usbport.c17
-rw-r--r--drivers/usb/core/message.c10
-rw-r--r--drivers/usb/core/phy.c28
-rw-r--r--drivers/usb/core/phy.h2
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/core/sysfs.c5
-rw-r--r--drivers/usb/core/urb.c5
-rw-r--r--drivers/usb/core/usb-acpi.c163
-rw-r--r--drivers/usb/core/usb.c37
-rw-r--r--drivers/usb/core/usb.h10
-rw-r--r--drivers/usb/dwc2/Kconfig2
-rw-r--r--drivers/usb/dwc2/gadget.c116
-rw-r--r--drivers/usb/dwc2/hcd.c4
-rw-r--r--drivers/usb/dwc3/Kconfig8
-rw-r--r--drivers/usb/dwc3/core.h12
-rw-r--r--drivers/usb/dwc3/debug.h156
-rw-r--r--drivers/usb/dwc3/drd.c9
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c4
-rw-r--r--drivers/usb/dwc3/dwc3-haps.c9
-rw-r--r--drivers/usb/dwc3/dwc3-keystone.c11
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c1
-rw-r--r--drivers/usb/dwc3/gadget.c71
-rw-r--r--drivers/usb/dwc3/gadget.h4
-rw-r--r--drivers/usb/dwc3/trace.h10
-rw-r--r--drivers/usb/gadget/Kconfig1
-rw-r--r--drivers/usb/gadget/epautoconf.c41
-rw-r--r--drivers/usb/gadget/function/f_fs.c12
-rw-r--r--drivers/usb/gadget/function/f_sourcesink.c2
-rw-r--r--drivers/usb/gadget/function/f_uac1.c10
-rw-r--r--drivers/usb/gadget/function/u_ecm.h2
-rw-r--r--drivers/usb/gadget/function/u_eem.h2
-rw-r--r--drivers/usb/gadget/function/u_ether_configfs.h2
-rw-r--r--drivers/usb/gadget/function/u_fs.h2
-rw-r--r--drivers/usb/gadget/function/u_gether.h2
-rw-r--r--drivers/usb/gadget/function/u_hid.h2
-rw-r--r--drivers/usb/gadget/function/u_midi.h2
-rw-r--r--drivers/usb/gadget/function/u_ncm.h2
-rw-r--r--drivers/usb/gadget/function/u_printer.h2
-rw-r--r--drivers/usb/gadget/function/u_rndis.h2
-rw-r--r--drivers/usb/gadget/function/u_serial.c35
-rw-r--r--drivers/usb/gadget/function/u_uac2.h2
-rw-r--r--drivers/usb/gadget/function/u_uvc.h2
-rw-r--r--drivers/usb/gadget/function/uvc.h2
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c10
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.h2
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.h2
-rw-r--r--drivers/usb/gadget/function/uvc_video.h2
-rw-r--r--drivers/usb/gadget/legacy/Kconfig1
-rw-r--r--drivers/usb/gadget/legacy/inode.c40
-rw-r--r--drivers/usb/gadget/u_f.c2
-rw-r--r--drivers/usb/gadget/u_f.h2
-rw-r--r--drivers/usb/gadget/u_os_desc.h2
-rw-r--r--drivers/usb/gadget/udc/Kconfig1
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/epn.c2
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/hub.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/Kconfig2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_cmd.c4
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c13
-rw-r--r--drivers/usb/gadget/udc/core.c8
-rw-r--r--drivers/usb/gadget/udc/fotg210-udc.c11
-rw-r--r--drivers/usb/gadget/udc/net2272.c2
-rw-r--r--drivers/usb/gadget/udc/net2280.c6
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c4
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c17
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/ehci-fsl.c69
-rw-r--r--drivers/usb/host/ehci-mv.c1
-rw-r--r--drivers/usb/host/ehci-orion.c44
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c6
-rw-r--r--drivers/usb/host/ohci-at91.c7
-rw-r--r--drivers/usb/host/ohci-da8xx.c118
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c10
-rw-r--r--drivers/usb/host/u132-hcd.c6
-rw-r--r--drivers/usb/host/uhci-hcd.c6
-rw-r--r--drivers/usb/host/whci/Makefile (renamed from drivers/usb/host/whci/Kbuild)2
-rw-r--r--drivers/usb/host/xhci-dbgcap.c6
-rw-r--r--drivers/usb/host/xhci-debugfs.h1
-rw-r--r--drivers/usb/host/xhci-mem.c10
-rw-r--r--drivers/usb/host/xhci-mvebu.c11
-rw-r--r--drivers/usb/host/xhci-mvebu.h6
-rw-r--r--drivers/usb/host/xhci-pci.c1
-rw-r--r--drivers/usb/host/xhci-plat.c7
-rw-r--r--drivers/usb/host/xhci-tegra.c4
-rw-r--r--drivers/usb/host/xhci.c3
-rw-r--r--drivers/usb/image/Kconfig1
-rw-r--r--drivers/usb/isp1760/Kconfig2
-rw-r--r--drivers/usb/misc/Kconfig1
-rw-r--r--drivers/usb/misc/ftdi-elan.c26
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig1
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile3
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c32
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h15
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c127
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c5
-rw-r--r--drivers/usb/misc/usb251xb.c15
-rw-r--r--drivers/usb/misc/usb3503.c38
-rw-r--r--drivers/usb/misc/usbtest.c28
-rw-r--r--drivers/usb/mon/Kconfig1
-rw-r--r--drivers/usb/mtu3/Kconfig2
-rw-r--r--drivers/usb/musb/Kconfig5
-rw-r--r--drivers/usb/musb/jz4740.c10
-rw-r--r--drivers/usb/musb/musb_gadget.c13
-rw-r--r--drivers/usb/musb/musb_host.c4
-rw-r--r--drivers/usb/musb/musbhsdma.c21
-rw-r--r--drivers/usb/phy/Kconfig3
-rw-r--r--drivers/usb/phy/phy-am335x.c5
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
-rw-r--r--drivers/usb/renesas_usbhs/mod_host.c2
-rw-r--r--drivers/usb/renesas_usbhs/rcar3.c2
-rw-r--r--drivers/usb/renesas_usbhs/rza.c2
-rw-r--r--drivers/usb/roles/Kconfig2
-rw-r--r--drivers/usb/roles/Makefile2
-rw-r--r--drivers/usb/roles/class.c21
-rw-r--r--drivers/usb/serial/Kconfig1
-rw-r--r--drivers/usb/serial/cp210x.c130
-rw-r--r--drivers/usb/serial/ftdi_sio.c17
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h6
-rw-r--r--drivers/usb/serial/keyspan_usa26msg.h1
-rw-r--r--drivers/usb/serial/keyspan_usa28msg.h1
-rw-r--r--drivers/usb/serial/keyspan_usa49msg.h1
-rw-r--r--drivers/usb/serial/keyspan_usa67msg.h1
-rw-r--r--drivers/usb/serial/keyspan_usa90msg.h1
-rw-r--r--drivers/usb/serial/option.c2
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h2
-rw-r--r--drivers/usb/serial/usb-serial-simple.c3
-rw-r--r--drivers/usb/storage/Kconfig1
-rw-r--r--drivers/usb/storage/karma.c2
-rw-r--r--drivers/usb/storage/scsiglue.c8
-rw-r--r--drivers/usb/storage/unusual_devs.h12
-rw-r--r--drivers/usb/typec/Kconfig1
-rw-r--r--drivers/usb/typec/altmodes/Kconfig1
-rw-r--r--drivers/usb/typec/altmodes/Makefile2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c4
-rw-r--r--drivers/usb/typec/class.c33
-rw-r--r--drivers/usb/typec/mux.c94
-rw-r--r--drivers/usb/typec/mux/Kconfig2
-rw-r--r--drivers/usb/typec/tcpm/Kconfig2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c71
-rw-r--r--drivers/usb/typec/tps6598x.c79
-rw-r--r--drivers/usb/typec/ucsi/Kconfig2
-rw-r--r--drivers/usb/typec/ucsi/debug.h65
-rw-r--r--drivers/usb/typec/ucsi/trace.c59
-rw-r--r--drivers/usb/typec/ucsi/trace.h7
-rw-r--r--drivers/usb/usbip/Kconfig2
-rw-r--r--drivers/usb/usbip/README7
-rw-r--r--drivers/usb/usbip/vhci_hcd.c6
-rw-r--r--drivers/usb/usbip/vudc_dev.c3
-rw-r--r--drivers/usb/wusbcore/Kconfig1
-rw-r--r--drivers/usb/wusbcore/cbaf.c15
-rw-r--r--drivers/usb/wusbcore/dev-sysfs.c5
-rw-r--r--drivers/usb/wusbcore/devconnect.c2
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c15
-rw-r--r--drivers/usb/wusbcore/wusbhc.c6
-rw-r--r--drivers/uwb/drp-ie.c5
-rw-r--r--drivers/vfio/mdev/mdev_core.c16
-rw-r--r--drivers/vfio/mdev/mdev_private.h5
-rw-r--r--drivers/vfio/mdev/mdev_sysfs.c6
-rw-r--r--drivers/vfio/pci/trace.h8
-rw-r--r--drivers/vfio/pci/vfio_pci.c90
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c2
-rw-r--r--drivers/vfio/pci/vfio_pci_nvlink2.c36
-rw-r--r--drivers/vfio/pci/vfio_pci_private.h6
-rw-r--r--drivers/vfio/platform/reset/Makefile2
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_amdxgbe.c2
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c2
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c2
-rw-r--r--drivers/vfio/vfio.c8
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c3
-rw-r--r--drivers/vfio/vfio_iommu_type1.c2
-rw-r--r--drivers/vhost/net.c6
-rw-r--r--drivers/vhost/scsi.c22
-rw-r--r--drivers/vhost/vhost.c112
-rw-r--r--drivers/vhost/vhost.h7
-rw-r--r--drivers/vhost/vsock.c4
-rw-r--r--drivers/video/backlight/88pm860x_bl.c2
-rw-r--r--drivers/video/backlight/pwm_bl.c28
-rw-r--r--drivers/video/console/vgacon.c7
-rw-r--r--drivers/video/fbdev/Kconfig2
-rw-r--r--drivers/video/fbdev/controlfb.c42
-rw-r--r--drivers/video/fbdev/core/fbcon.c7
-rw-r--r--drivers/video/fbdev/core/fbmem.c19
-rw-r--r--drivers/video/fbdev/da8xx-fb.c6
-rw-r--r--drivers/video/fbdev/imsttfb.c23
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c7
-rw-r--r--drivers/video/fbdev/offb.c18
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c2
-rw-r--r--drivers/video/fbdev/platinumfb.c21
-rw-r--r--drivers/video/fbdev/valkyriefb.c30
-rw-r--r--drivers/video/logo/Kconfig9
-rw-r--r--drivers/virt/vboxguest/vboxguest_core.c2
-rw-r--r--drivers/virtio/virtio_balloon.c98
-rw-r--r--drivers/virtio/virtio_mmio.c9
-rw-r--r--drivers/virtio/virtio_pci_common.c8
-rw-r--r--drivers/virtio/virtio_ring.c15
-rw-r--r--drivers/watchdog/bcm2835_wdt.c26
-rw-r--r--drivers/watchdog/mt7621_wdt.c1
-rw-r--r--drivers/watchdog/rt2880_wdt.c1
-rw-r--r--drivers/watchdog/tqmx86_wdt.c8
-rw-r--r--drivers/xen/balloon.c18
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/pvcalls-back.c9
-rw-r--r--drivers/xen/pvcalls-front.c104
-rw-r--r--drivers/xen/swiotlb-xen.c4
3500 files changed, 159982 insertions, 67158 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4f9f99057ff8..45f9decb9848 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -228,4 +228,6 @@ source "drivers/siox/Kconfig"
source "drivers/slimbus/Kconfig"
+source "drivers/interconnect/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index e1ce029d28fd..bb15b9d0e793 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/
obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
obj-$(CONFIG_SIOX) += siox/
obj-$(CONFIG_GNSS) += gnss/
+obj-$(CONFIG_INTERCONNECT) += interconnect/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7b65a807b3dd..4e015c77e48e 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -10,6 +10,7 @@ menuconfig ACPI
bool "ACPI (Advanced Configuration and Power Interface) Support"
depends on ARCH_SUPPORTS_ACPI
select PNP
+ select NLS
default y if X86
help
Advanced Configuration and Power Interface (ACPI) support for
@@ -356,6 +357,16 @@ config ACPI_TABLE_UPGRADE
initrd, therefore it's safe to say Y.
See Documentation/acpi/initrd_table_override.txt for details
+config ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD
+ bool "Override ACPI tables from built-in initrd"
+ depends on ACPI_TABLE_UPGRADE
+ depends on INITRAMFS_SOURCE!="" && INITRAMFS_COMPRESSION=""
+ help
+ This option provides functionality to override arbitrary ACPI tables
+ from built-in uncompressed initrd.
+
+ See Documentation/acpi/initrd_table_override.txt for details
+
config ACPI_DEBUG
bool "Debug Statements"
help
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 7c6afc111d76..bb857421c2e8 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -41,7 +41,8 @@ acpi-y += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o
obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o
-acpi-y += acpi_lpss.o acpi_apd.o
+acpi-$(CONFIG_PCI) += acpi_lpss.o
+acpi-y += acpi_apd.o
acpi-y += acpi_platform.o
acpi-y += acpi_pnp.o
acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o
diff --git a/drivers/acpi/acpi_dbg.c b/drivers/acpi/acpi_dbg.c
index a2dcd62ea32f..4a434c23a196 100644
--- a/drivers/acpi/acpi_dbg.c
+++ b/drivers/acpi/acpi_dbg.c
@@ -750,48 +750,36 @@ static const struct acpi_debugger_ops acpi_aml_debugger = {
int __init acpi_aml_init(void)
{
- int ret = 0;
-
- if (!acpi_debugfs_dir) {
- ret = -ENOENT;
- goto err_exit;
- }
+ int ret;
/* Initialize AML IO interface */
mutex_init(&acpi_aml_io.lock);
init_waitqueue_head(&acpi_aml_io.wait);
acpi_aml_io.out_crc.buf = acpi_aml_io.out_buf;
acpi_aml_io.in_crc.buf = acpi_aml_io.in_buf;
+
acpi_aml_dentry = debugfs_create_file("acpidbg",
S_IFREG | S_IRUGO | S_IWUSR,
acpi_debugfs_dir, NULL,
&acpi_aml_operations);
- if (acpi_aml_dentry == NULL) {
- ret = -ENODEV;
- goto err_exit;
- }
- ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
- if (ret)
- goto err_fs;
- acpi_aml_initialized = true;
-err_fs:
+ ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
if (ret) {
debugfs_remove(acpi_aml_dentry);
acpi_aml_dentry = NULL;
+ return ret;
}
-err_exit:
- return ret;
+
+ acpi_aml_initialized = true;
+ return 0;
}
void __exit acpi_aml_exit(void)
{
if (acpi_aml_initialized) {
acpi_unregister_debugger(&acpi_aml_debugger);
- if (acpi_aml_dentry) {
- debugfs_remove(acpi_aml_dentry);
- acpi_aml_dentry = NULL;
- }
+ debugfs_remove(acpi_aml_dentry);
+ acpi_aml_dentry = NULL;
acpi_aml_initialized = false;
}
}
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index f0b52266b3ac..d73afb562ad9 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -2124,21 +2124,29 @@ static int __init intel_opregion_present(void)
return opregion;
}
+/* Check if the chassis-type indicates there is no builtin LCD panel */
static bool dmi_is_desktop(void)
{
const char *chassis_type;
+ unsigned long type;
chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
if (!chassis_type)
return false;
- if (!strcmp(chassis_type, "3") || /* 3: Desktop */
- !strcmp(chassis_type, "4") || /* 4: Low Profile Desktop */
- !strcmp(chassis_type, "5") || /* 5: Pizza Box */
- !strcmp(chassis_type, "6") || /* 6: Mini Tower */
- !strcmp(chassis_type, "7") || /* 7: Tower */
- !strcmp(chassis_type, "11")) /* 11: Main Server Chassis */
+ if (kstrtoul(chassis_type, 10, &type) != 0)
+ return false;
+
+ switch (type) {
+ case 0x03: /* Desktop */
+ case 0x04: /* Low Profile Desktop */
+ case 0x05: /* Pizza Box */
+ case 0x06: /* Mini Tower */
+ case 0x07: /* Tower */
+ case 0x10: /* Lunch Box */
+ case 0x11: /* Main Server Chassis */
return true;
+ }
return false;
}
diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h
index 5a9c2febc0fb..863ade9add6d 100644
--- a/drivers/acpi/acpica/acapps.h
+++ b/drivers/acpi/acpica/acapps.h
@@ -3,7 +3,7 @@
*
* Module Name: acapps - common include for ACPI applications/tools
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -17,7 +17,7 @@
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
-#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2018 Intel Corporation"
+#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2019 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH " (64-bit version)"
diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h
index 8bc935977d8e..54f81eac7ec9 100644
--- a/drivers/acpi/acpica/accommon.h
+++ b/drivers/acpi/acpica/accommon.h
@@ -3,7 +3,7 @@
*
* Name: accommon.h - Common include files for generation of ACPICA source
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acconvert.h b/drivers/acpi/acpica/acconvert.h
index 4ebe18826646..d5478cd4a857 100644
--- a/drivers/acpi/acpica/acconvert.h
+++ b/drivers/acpi/acpica/acconvert.h
@@ -3,7 +3,7 @@
*
* Module Name: acapps - common include for ACPI applications/tools
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 57d9495e5933..32f2e38c7570 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -3,7 +3,7 @@
*
* Name: acdebug.h - ACPI/AML debugger
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -16,7 +16,8 @@
#include "acdisasm.h"
#endif
-#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
+#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
+#define ACPI_DEBUG_LENGTH_FORMAT " (%.4X bits, %.3X bytes)"
struct acpi_db_command_info {
const char *name; /* Command Name */
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index e577f3a40e6a..82f81501566b 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -3,7 +3,7 @@
*
* Name: acdispat.h - dispatcher (parser to interpreter interface)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index b412aa909907..831660179662 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -3,7 +3,7 @@
*
* Name: acevents.h - Event subcomponent prototypes and defines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 87d6eb01beaf..d056a1845613 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -3,7 +3,7 @@
*
* Name: acglobal.h - Declarations for global variables
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -164,6 +164,7 @@ ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_global_list);
ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_ns_node_list);
ACPI_GLOBAL(u8, acpi_gbl_display_final_mem_stats);
ACPI_GLOBAL(u8, acpi_gbl_disable_mem_tracking);
+ACPI_GLOBAL(u8, acpi_gbl_verbose_leak_dump);
#endif
/*****************************************************************************
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index ef99e2fc37f8..bcf8f7501db7 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -3,7 +3,7 @@
*
* Name: achware.h -- hardware specific interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h
index c5b2be0b6613..20706adbc148 100644
--- a/drivers/acpi/acpica/acinterp.h
+++ b/drivers/acpi/acpica/acinterp.h
@@ -3,7 +3,7 @@
*
* Name: acinterp.h - Interpreter subcomponent prototypes and defines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 99b0da899109..a2dfbf6b004e 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -3,7 +3,7 @@
*
* Name: aclocal.h - Internal data types used across the ACPI subsystem
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -802,7 +802,7 @@ struct acpi_comment_addr_node {
/*
* File node - used for "Include" operator file stack and
- * depdendency tree for the -ca option
+ * dependency tree for the -ca option
*/
struct acpi_file_node {
void *file;
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index de52cd6e868a..283614e82a20 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -3,7 +3,7 @@
*
* Name: acmacros.h - C macros for the entire subsystem.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -462,7 +462,7 @@
#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
/*
- * Macors used for the ASL-/ASL+ converter utility
+ * Macros used for the ASL-/ASL+ converter utility
*/
#ifdef ACPI_ASL_COMPILER
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 9bd25f36c608..39812fc4386a 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -3,7 +3,7 @@
*
* Name: acnamesp.h - Namespace subcomponent prototypes and defines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index ac992b6ebce9..b2ef703d7df8 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -3,7 +3,7 @@
*
* Name: acobject.h - Definition of union acpi_operand_object (Internal object only)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -239,6 +239,7 @@ struct acpi_object_region_field {
union acpi_operand_object *region_obj; /* Containing op_region object */
u8 *resource_buffer; /* resource_template for serial regions/fields */
u16 pin_number_index; /* Index relative to previous Connection/Template */
+ u8 *internal_pcc_buffer; /* Internal buffer for fields associated with PCC */
};
struct acpi_object_bank_field {
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index 818eba413614..9d78134428e3 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -3,7 +3,7 @@
*
* Name: acopcode.h - AML opcode information for the AML parser and interpreter
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index ab48196ae55e..6e32c97cba6c 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -3,7 +3,7 @@
*
* Module Name: acparser.h - AML Parser subcomponent prototypes and defines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index d31bb04facb6..387163b962a7 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -3,7 +3,7 @@
*
* Name: acpredef - Information table for ACPI predefined methods and objects
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -631,6 +631,21 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_MTL", METHOD_0ARGS, /* ACPI 6.0 */
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
+ {{"_NBS", METHOD_0ARGS, /* ACPI 6.3 */
+ METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
+
+ {{"_NCH", METHOD_0ARGS, /* ACPI 6.3 */
+ METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
+
+ {{"_NIC", METHOD_0ARGS, /* ACPI 6.3 */
+ METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
+
+ {{"_NIG", METHOD_1ARGS(ACPI_TYPE_BUFFER), /* ACPI 6.3 */
+ METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
+
+ {{"_NIH", METHOD_0ARGS, /* ACPI 6.3 */
+ METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
+
{{"_NTT", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h
index 59ae8b1a6e40..422cd8f2b92e 100644
--- a/drivers/acpi/acpica/acresrc.h
+++ b/drivers/acpi/acpica/acresrc.h
@@ -3,7 +3,7 @@
*
* Name: acresrc.h - Resource Manager function prototypes
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h
index 14be32961b4c..8a4e6b4aaf2c 100644
--- a/drivers/acpi/acpica/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
@@ -3,7 +3,7 @@
*
* Name: acstruct.h - Internal structs
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index 12fac33ce77e..dfbf1dbd4033 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -3,7 +3,7 @@
*
* Name: actables.h - ACPI table management
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 3374d41582b5..9022537567e9 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -3,7 +3,7 @@
*
* Name: acutils.h -- prototypes for the common (subsystem-wide) procedures
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h
index 6c05355447c1..49e412edd7c6 100644
--- a/drivers/acpi/acpica/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
@@ -5,7 +5,7 @@
* Declarations and definitions contained herein are derived
* directly from the ACPI specification.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index cdb590176e9d..7c3bd4ab60fc 100644
--- a/drivers/acpi/acpica/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
@@ -3,7 +3,7 @@
*
* Module Name: amlresrc.h - AML resource descriptors
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c
index 9fcb8ec64681..30ab62b0fec8 100644
--- a/drivers/acpi/acpica/dbdisply.c
+++ b/drivers/acpi/acpica/dbdisply.c
@@ -237,7 +237,7 @@ void acpi_db_decode_and_display_object(char *target, char *output_type)
default:
- /* Is not a recognizeable object */
+ /* Is not a recognizable object */
acpi_os_printf
("Not a known ACPI internal object, descriptor type %2.2X\n",
@@ -647,7 +647,7 @@ void acpi_db_display_object_type(char *object_arg)
*
* DESCRIPTION: Display the result of an AML opcode
*
- * Note: Curently only displays the result object if we are single stepping.
+ * Note: Currently only displays the result object if we are single stepping.
* However, this output may be useful in other contexts and could be enabled
* to do so if needed.
*
diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c
index 6abb6b834d97..bb43305cb215 100644
--- a/drivers/acpi/acpica/dbexec.c
+++ b/drivers/acpi/acpica/dbexec.c
@@ -160,12 +160,12 @@ acpi_db_execute_method(struct acpi_db_method_info *info,
}
ACPI_EXCEPTION((AE_INFO, status,
- "while executing %s from debugger",
+ "while executing %s from AML Debugger",
info->pathname));
if (status == AE_BUFFER_OVERFLOW) {
ACPI_ERROR((AE_INFO,
- "Possible overflow of internal debugger "
+ "Possible buffer overflow within AML Debugger "
"buffer (size 0x%X needed 0x%X)",
ACPI_DEBUG_BUFFER_SIZE,
(u32)return_obj->length));
diff --git a/drivers/acpi/acpica/dbhistry.c b/drivers/acpi/acpica/dbhistry.c
index b0b9a26c7db5..7809bd94a18d 100644
--- a/drivers/acpi/acpica/dbhistry.c
+++ b/drivers/acpi/acpica/dbhistry.c
@@ -3,7 +3,7 @@
*
* Module Name: dbhistry - debugger HISTORY command
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c
index 992bd7b92540..004d34d9369b 100644
--- a/drivers/acpi/acpica/dbnames.c
+++ b/drivers/acpi/acpica/dbnames.c
@@ -904,7 +904,7 @@ acpi_db_bus_walk(acpi_handle obj_handle,
*
* RETURN: None
*
- * DESCRIPTION: Display info about system busses.
+ * DESCRIPTION: Display info about system buses.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/dbobject.c b/drivers/acpi/acpica/dbobject.c
index a1c76bf21122..d220168dca01 100644
--- a/drivers/acpi/acpica/dbobject.c
+++ b/drivers/acpi/acpica/dbobject.c
@@ -243,7 +243,7 @@ acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
acpi_os_printf("[%s] ",
acpi_ut_get_reference_name(obj_desc));
- /* Decode the refererence */
+ /* Decode the reference */
switch (obj_desc->reference.class) {
case ACPI_REFCLASS_LOCAL:
diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c
index 8a5462439a97..6db44a5ac786 100644
--- a/drivers/acpi/acpica/dbtest.c
+++ b/drivers/acpi/acpica/dbtest.c
@@ -10,6 +10,7 @@
#include "acdebug.h"
#include "acnamesp.h"
#include "acpredef.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbtest")
@@ -33,6 +34,9 @@ acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length);
static acpi_status acpi_db_test_package_type(struct acpi_namespace_node *node);
static acpi_status
+acpi_db_test_field_unit_type(union acpi_operand_object *obj_desc);
+
+static acpi_status
acpi_db_read_from_object(struct acpi_namespace_node *node,
acpi_object_type expected_type,
union acpi_object **value);
@@ -74,7 +78,7 @@ static struct acpi_db_argument_info acpi_db_test_types[] = {
static acpi_handle read_handle = NULL;
static acpi_handle write_handle = NULL;
-/* ASL Definitions of the debugger read/write control methods */
+/* ASL Definitions of the debugger read/write control methods. AML below. */
#if 0
definition_block("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
@@ -227,10 +231,8 @@ static void acpi_db_test_all_objects(void)
* RETURN: Status
*
* DESCRIPTION: Test one namespace object. Supported types are Integer,
- * String, Buffer, buffer_field, and field_unit. All other object
- * types are simply ignored.
- *
- * Note: Support for Packages is not implemented.
+ * String, Buffer, Package, buffer_field, and field_unit.
+ * All other object types are simply ignored.
*
******************************************************************************/
@@ -240,7 +242,6 @@ acpi_db_test_one_object(acpi_handle obj_handle,
{
struct acpi_namespace_node *node;
union acpi_operand_object *obj_desc;
- union acpi_operand_object *region_obj;
acpi_object_type local_type;
u32 bit_length = 0;
u32 byte_length = 0;
@@ -281,18 +282,21 @@ acpi_db_test_one_object(acpi_handle obj_handle,
break;
case ACPI_TYPE_FIELD_UNIT:
- case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
+ local_type = ACPI_TYPE_FIELD_UNIT;
+ break;
+
+ case ACPI_TYPE_BUFFER_FIELD:
+ /*
+ * The returned object will be a Buffer if the field length
+ * is larger than the size of an Integer (32 or 64 bits
+ * depending on the DSDT version).
+ */
local_type = ACPI_TYPE_INTEGER;
if (obj_desc) {
- /*
- * Returned object will be a Buffer if the field length
- * is larger than the size of an Integer (32 or 64 bits
- * depending on the DSDT version).
- */
bit_length = obj_desc->common_field.bit_length;
byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length);
if (bit_length > acpi_gbl_integer_bit_width) {
@@ -303,7 +307,7 @@ acpi_db_test_one_object(acpi_handle obj_handle,
default:
- /* Ignore all other types */
+ /* Ignore all non-data types - Methods, Devices, Scopes, etc. */
return (AE_OK);
}
@@ -314,40 +318,10 @@ acpi_db_test_one_object(acpi_handle obj_handle,
acpi_ut_get_type_name(node->type), node->name.ascii);
if (!obj_desc) {
- acpi_os_printf(" Ignoring, no attached object\n");
+ acpi_os_printf(" No attached sub-object, ignoring\n");
return (AE_OK);
}
- /*
- * Check for unsupported region types. Note: acpi_exec simulates
- * access to system_memory, system_IO, PCI_Config, and EC.
- */
- switch (node->type) {
- case ACPI_TYPE_LOCAL_REGION_FIELD:
-
- region_obj = obj_desc->field.region_obj;
- switch (region_obj->region.space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- case ACPI_ADR_SPACE_SYSTEM_IO:
- case ACPI_ADR_SPACE_PCI_CONFIG:
-
- break;
-
- default:
-
- acpi_os_printf
- (" %s space is not supported in this command [%4.4s]\n",
- acpi_ut_get_region_name(region_obj->region.
- space_id),
- region_obj->region.node->name.ascii);
- return (AE_OK);
- }
- break;
-
- default:
- break;
- }
-
/* At this point, we have resolved the object to one of the major types */
switch (local_type) {
@@ -371,6 +345,11 @@ acpi_db_test_one_object(acpi_handle obj_handle,
status = acpi_db_test_package_type(node);
break;
+ case ACPI_TYPE_FIELD_UNIT:
+
+ status = acpi_db_test_field_unit_type(obj_desc);
+ break;
+
default:
acpi_os_printf(" Ignoring, type not implemented (%2.2X)",
@@ -382,24 +361,8 @@ acpi_db_test_one_object(acpi_handle obj_handle,
if (ACPI_FAILURE(status)) {
status = AE_OK;
- goto exit;
- }
-
- switch (node->type) {
- case ACPI_TYPE_LOCAL_REGION_FIELD:
-
- region_obj = obj_desc->field.region_obj;
- acpi_os_printf(" (%s)",
- acpi_ut_get_region_name(region_obj->region.
- space_id));
-
- break;
-
- default:
- break;
}
-exit:
acpi_os_printf("\n");
return (status);
}
@@ -444,7 +407,7 @@ acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length)
return (status);
}
- acpi_os_printf(" (%4.4X/%3.3X) %8.8X%8.8X",
+ acpi_os_printf(ACPI_DEBUG_LENGTH_FORMAT " %8.8X%8.8X",
bit_length, ACPI_ROUND_BITS_UP_TO_BYTES(bit_length),
ACPI_FORMAT_UINT64(temp1->integer.value));
@@ -558,8 +521,9 @@ acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length)
/* Emit a few bytes of the buffer */
- acpi_os_printf(" (%4.4X/%3.3X)", bit_length, temp1->buffer.length);
- for (i = 0; ((i < 4) && (i < byte_length)); i++) {
+ acpi_os_printf(ACPI_DEBUG_LENGTH_FORMAT, bit_length,
+ temp1->buffer.length);
+ for (i = 0; ((i < 8) && (i < byte_length)); i++) {
acpi_os_printf(" %2.2X", temp1->buffer.pointer[i]);
}
acpi_os_printf("... ");
@@ -665,8 +629,9 @@ acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length)
return (status);
}
- acpi_os_printf(" (%4.4X/%3.3X) \"%s\"", (temp1->string.length * 8),
- temp1->string.length, temp1->string.pointer);
+ acpi_os_printf(ACPI_DEBUG_LENGTH_FORMAT " \"%s\"",
+ (temp1->string.length * 8), temp1->string.length,
+ temp1->string.pointer);
/* Write a new value */
@@ -750,13 +715,80 @@ static acpi_status acpi_db_test_package_type(struct acpi_namespace_node *node)
return (status);
}
- acpi_os_printf(" %8.8X Elements", temp1->package.count);
+ acpi_os_printf(" %.2X Elements", temp1->package.count);
acpi_os_free(temp1);
return (status);
}
/*******************************************************************************
*
+ * FUNCTION: acpi_db_test_field_unit_type
+ *
+ * PARAMETERS: obj_desc - A field unit object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Test read/write on a named field unit.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_db_test_field_unit_type(union acpi_operand_object *obj_desc)
+{
+ union acpi_operand_object *region_obj;
+ u32 bit_length = 0;
+ u32 byte_length = 0;
+ acpi_status status = AE_OK;
+ union acpi_operand_object *ret_buffer_desc;
+
+ /* Supported spaces are memory/io/pci_config */
+
+ region_obj = obj_desc->field.region_obj;
+ switch (region_obj->region.space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ case ACPI_ADR_SPACE_PCI_CONFIG:
+
+ /* Need the interpreter to execute */
+
+ acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+
+ /* Exercise read-then-write */
+
+ status =
+ acpi_ex_read_data_from_field(NULL, obj_desc,
+ &ret_buffer_desc);
+ if (status == AE_OK) {
+ acpi_ex_write_data_to_field(ret_buffer_desc, obj_desc,
+ NULL);
+ acpi_ut_remove_reference(ret_buffer_desc);
+ }
+
+ acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
+
+ bit_length = obj_desc->common_field.bit_length;
+ byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length);
+
+ acpi_os_printf(ACPI_DEBUG_LENGTH_FORMAT " [%s]", bit_length,
+ byte_length,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id));
+ return (status);
+
+ default:
+
+ acpi_os_printf
+ (" %s address space is not supported in this command [%4.4s]",
+ acpi_ut_get_region_name(region_obj->region.space_id),
+ region_obj->region.node->name.ascii);
+ return (AE_OK);
+ }
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_db_read_from_object
*
* PARAMETERS: node - Parent NS node for the object
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
index 6b15625e8099..85b34d02233e 100644
--- a/drivers/acpi/acpica/dsargs.c
+++ b/drivers/acpi/acpica/dsargs.c
@@ -4,7 +4,7 @@
* Module Name: dsargs - Support for execution of dynamic arguments for static
* objects (regions, fields, buffer fields, etc.)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index 0da96268deb5..4847f89c678c 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -4,7 +4,7 @@
* Module Name: dscontrol - Support for execution control opcodes -
* if/else/while/return
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dsdebug.c b/drivers/acpi/acpica/dsdebug.c
index 9d33f0bb2885..0d3e1ced1f57 100644
--- a/drivers/acpi/acpica/dsdebug.c
+++ b/drivers/acpi/acpica/dsdebug.c
@@ -3,7 +3,7 @@
*
* Module Name: dsdebug - Parser/Interpreter interface - debugging
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 30fe89545d6a..cf4e061bb0f0 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -3,7 +3,7 @@
*
* Module Name: dsfield - Dispatcher field routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -518,6 +518,13 @@ acpi_ds_create_field(union acpi_parse_object *op,
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
+ if (info.region_node->object->region.space_id ==
+ ACPI_ADR_SPACE_PLATFORM_COMM
+ && !(region_node->object->field.internal_pcc_buffer =
+ ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
+ length))) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c
index e8de1b0ce2f5..a4a24ffe5fae 100644
--- a/drivers/acpi/acpica/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -3,7 +3,7 @@
*
* Module Name: dsinit - Object initialization namespace walk
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index c1a4d02fafd5..f59b4d944f7f 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -3,7 +3,7 @@
*
* Module Name: dsmethod - Parser/Interpreter interface - control method parsing
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index 6a9cc613adaa..179129a2deb1 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -3,7 +3,7 @@
*
* Module Name: dsobject - Dispatcher object management routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 78f9de260d5f..10f32b62608e 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -3,7 +3,7 @@
*
* Module Name: dsopcode - Dispatcher support for regions and fields
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -130,8 +130,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
/* Must have a valid (>0) bit count */
if (bit_count == 0) {
- ACPI_ERROR((AE_INFO,
- "Attempt to CreateField of length zero"));
+ ACPI_BIOS_ERROR((AE_INFO,
+ "Attempt to CreateField of length zero"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -194,12 +194,13 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
/* Entire field must fit within the current length of the buffer */
if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) {
- ACPI_ERROR((AE_INFO,
- "Field [%4.4s] at bit offset/length %u/%u "
- "exceeds size of target Buffer (%u bits)",
- acpi_ut_get_node_name(result_desc), bit_offset,
- bit_count, 8 * (u32)buffer_desc->buffer.length));
status = AE_AML_BUFFER_LIMIT;
+ ACPI_BIOS_EXCEPTION((AE_INFO, status,
+ "Field [%4.4s] at bit offset/length %u/%u "
+ "exceeds size of target Buffer (%u bits)",
+ acpi_ut_get_node_name(result_desc),
+ bit_offset, bit_count,
+ 8 * (u32)buffer_desc->buffer.length));
goto cleanup;
}
@@ -355,6 +356,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
union acpi_operand_object *operand_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
+ acpi_adr_space_type space_id;
ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
@@ -367,6 +369,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
/* next_op points to the op that holds the space_ID */
next_op = op->common.value.arg;
+ space_id = (acpi_adr_space_type)next_op->common.value.integer;
/* next_op points to address op */
@@ -402,6 +405,15 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
obj_desc->region.length = (u32) operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
+ /* A zero-length operation region is unusable. Just warn */
+
+ if (!obj_desc->region.length
+ && (space_id < ACPI_NUM_PREDEFINED_REGIONS)) {
+ ACPI_WARNING((AE_INFO,
+ "Operation Region [%4.4s] has zero length (SpaceId %X)",
+ node->name.ascii, space_id));
+ }
+
/*
* Get the address and save it
* (at top of stack - 1)
diff --git a/drivers/acpi/acpica/dspkginit.c b/drivers/acpi/acpica/dspkginit.c
index 584853385268..997faa10f615 100644
--- a/drivers/acpi/acpica/dspkginit.c
+++ b/drivers/acpi/acpica/dspkginit.c
@@ -3,7 +3,7 @@
*
* Module Name: dspkginit - Completion of deferred package initialization
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index 1504b93cc5f4..d75aae304595 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -4,7 +4,7 @@
* Module Name: dswexec - Dispatcher method execution callbacks;
* dispatch to interpreter.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index e2ef09643d50..c88fd31208a5 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -3,7 +3,7 @@
*
* Module Name: dswload - Dispatcher first pass namespace load callbacks
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index 9a309f5c4de8..935a8e2623e4 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -3,7 +3,7 @@
*
* Module Name: dswload2 - Dispatcher second pass namespace load callbacks
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -24,7 +24,7 @@ ACPI_MODULE_NAME("dswload2")
* FUNCTION: acpi_ds_load2_begin_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
- * out_op - Wher to return op if a new one is created
+ * out_op - Where to return op if a new one is created
*
* RETURN: Status
*
diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c
index 7592176a8fa2..39acf7b286da 100644
--- a/drivers/acpi/acpica/dswscope.c
+++ b/drivers/acpi/acpica/dswscope.c
@@ -3,7 +3,7 @@
*
* Module Name: dswscope - Scope stack manipulation
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index 4c1ec202d5ab..de79f835a373 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -3,7 +3,7 @@
*
* Module Name: dswstate - Dispatcher parse tree walk management routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index b3d07cc14d75..9e2f5a05c066 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -3,7 +3,7 @@
*
* Module Name: evevent - Fixed Event handling and dispatch
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c
index 1b8a662a14a9..5c77bee5d31f 100644
--- a/drivers/acpi/acpica/evglock.c
+++ b/drivers/acpi/acpica/evglock.c
@@ -3,7 +3,7 @@
*
* Module Name: evglock - Global Lock support
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index e10fec99a182..62d3aa74277b 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -3,7 +3,7 @@
*
* Module Name: evgpe - General Purpose Event handling and dispatch
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -801,7 +801,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
dispatch.handler->
context);
- /* If requested, clear (if level-triggered) and reenable the GPE */
+ /* If requested, clear (if level-triggered) and re-enable the GPE */
if (return_value & ACPI_REENABLE_GPE) {
(void)acpi_ev_finish_gpe(gpe_event_info);
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index b253063b09d3..328d1d6123ad 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -3,7 +3,7 @@
*
* Module Name: evgpeblk - GPE block creation and initialization.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index 1f686750bb1a..c92d2f6ebe01 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -3,7 +3,7 @@
*
* Module Name: evgpeinit - System GPE initialization and update
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index 0fb6c70f44ed..917892227e09 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -3,7 +3,7 @@
*
* Module Name: evgpeutil - GPE utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c
index 4ed1e67db6be..3ef4e27995f0 100644
--- a/drivers/acpi/acpica/evhandler.c
+++ b/drivers/acpi/acpica/evhandler.c
@@ -3,7 +3,7 @@
*
* Module Name: evhandler - Support for Address Space handlers
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index baadd635b5af..d45f7639f7ee 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -3,7 +3,7 @@
*
* Module Name: evmisc - Miscellaneous event manager support functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 49decca4e08f..45dc797df05d 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -3,7 +3,7 @@
*
* Module Name: evregion - Operation Region support
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -250,7 +250,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
- * know what it will do, so we can't hold the lock on the intepreter.
+ * know what it will do, so we can't hold the lock on the interpreter.
*/
acpi_ex_exit_interpreter();
}
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 17df5dacd43c..0b47bbcd2a23 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -3,7 +3,7 @@
*
* Module Name: evrgnini- ACPI address_space (op_region) init
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -516,25 +516,6 @@ acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
handler_obj = obj_desc->common_notify.handler;
break;
- case ACPI_TYPE_METHOD:
- /*
- * If we are executing module level code, the original
- * Node's object was replaced by this Method object and we
- * saved the handler in the method object.
- *
- * Note: Only used for the legacy MLC support. Will
- * be removed in the future.
- *
- * See acpi_ns_exec_module_code
- */
- if (!acpi_gbl_execute_tables_as_methods &&
- obj_desc->method.
- info_flags & ACPI_METHOD_MODULE_LEVEL) {
- handler_obj =
- obj_desc->method.dispatch.handler;
- }
- break;
-
default:
/* Ignore other objects */
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index febc332b00ac..3df00eb6621b 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -3,7 +3,7 @@
*
* Module Name: evxface - External interfaces for ACPI events
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 970e940bdb17..e528fe56b755 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -3,7 +3,7 @@
*
* Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index b2d5f66cc1b0..30a083902f52 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -3,7 +3,7 @@
*
* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -669,9 +669,9 @@ ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
*
* RETURN: Status
*
- * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
+ * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
* processing. Intended for use by asynchronous host-installed
- * GPE handlers. The GPE is only reenabled if the enable_for_run bit
+ * GPE handlers. The GPE is only re-enabled if the enable_for_run bit
* is set in the GPE info.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 3b3a25d9f0e6..47265b073e6f 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -4,7 +4,7 @@
* Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
* Address Spaces.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exconcat.c b/drivers/acpi/acpica/exconcat.c
index 5e75c510ca25..c7af07566b7b 100644
--- a/drivers/acpi/acpica/exconcat.c
+++ b/drivers/acpi/acpica/exconcat.c
@@ -3,7 +3,7 @@
*
* Module Name: exconcat - Concatenate-type AML operators
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 2373a7492151..587aeeeb5070 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -3,7 +3,7 @@
*
* Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 1a70b80cc406..ca2966bacb50 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -3,7 +3,7 @@
*
* Module Name: exconvrt - Object conversion routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -520,7 +520,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
for (i = 0; i < obj_desc->buffer.length; i++) {
if (base == 16) {
- /* Emit 0x prefix for explict/implicit hex conversion */
+ /* Emit 0x prefix for explicit/implicit hex conversion */
*new_buf++ = '0';
*new_buf++ = 'x';
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 3304c6b1e8a7..f376fc00064e 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -3,7 +3,7 @@
*
* Module Name: excreate - Named object creation
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index ebbc244039ab..b1aeec8cac55 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -3,7 +3,7 @@
*
* Module Name: exdebug - Support for stores to the AML Debug Object
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index f71dfa1e90e1..6526b2deeaad 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -3,7 +3,7 @@
*
* Module Name: exdump - Interpreter debug output routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index e5798f15793a..d3d2dbfba680 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -3,7 +3,7 @@
*
* Module Name: exfield - AML execution - field_unit read/write
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -41,6 +41,17 @@ const u8 acpi_protocol_lengths[] = {
0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */
};
+#define PCC_MASTER_SUBSPACE 3
+
+/*
+ * The following macros determine a given offset is a COMD field.
+ * According to the specification, generic subspaces (types 0-2) contains a
+ * 2-byte COMD field at offset 4 and master subspaces (type 3) contains a 4-byte
+ * COMD field starting at offset 12.
+ */
+#define GENERIC_SUBSPACE_COMMAND(a) (4 == a || a == 5)
+#define MASTER_SUBSPACE_COMMAND(a) (12 <= a && a <= 15)
+
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_protocol_buffer_length
@@ -177,6 +188,25 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
status = acpi_ex_read_gpio(obj_desc, buffer);
goto exit;
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_PLATFORM_COMM)) {
+ /*
+ * Reading from a PCC field unit does not require the handler because
+ * it only requires reading from the internal_pcc_buffer.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "PCC FieldRead bits %u\n",
+ obj_desc->field.bit_length));
+
+ memcpy(buffer,
+ obj_desc->field.region_obj->field.internal_pcc_buffer +
+ obj_desc->field.base_byte_offset,
+ (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
+ bit_length));
+
+ *ret_buffer_desc = buffer_desc;
+ return AE_OK;
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -229,6 +259,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
{
acpi_status status;
u32 buffer_length;
+ u32 data_length;
void *buffer;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
@@ -272,6 +303,44 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
acpi_ex_write_serial_bus(source_desc, obj_desc,
result_desc);
return_ACPI_STATUS(status);
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_PLATFORM_COMM)) {
+ /*
+ * According to the spec a write to the COMD field will invoke the
+ * region handler. Otherwise, write to the pcc_internal buffer. This
+ * implementation will use the offsets specified rather than the name
+ * of the field. This is considered safer because some firmware tools
+ * are known to obfiscate named objects.
+ */
+ data_length =
+ (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
+ bit_length);
+ memcpy(obj_desc->field.region_obj->field.internal_pcc_buffer +
+ obj_desc->field.base_byte_offset,
+ source_desc->buffer.pointer, data_length);
+
+ if ((obj_desc->field.region_obj->region.address ==
+ PCC_MASTER_SUBSPACE
+ && MASTER_SUBSPACE_COMMAND(obj_desc->field.
+ base_byte_offset))
+ || GENERIC_SUBSPACE_COMMAND(obj_desc->field.
+ base_byte_offset)) {
+
+ /* Perform the write */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "PCC COMD field has been written. Invoking PCC handler now.\n"));
+
+ status =
+ acpi_ex_access_region(obj_desc, 0,
+ (u64 *)obj_desc->field.
+ region_obj->field.
+ internal_pcc_buffer,
+ ACPI_WRITE);
+ return_ACPI_STATUS(status);
+ }
+ return (AE_OK);
}
/* Get a pointer to the data to be written */
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 516994133128..95a0dcb4f7b9 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -3,7 +3,7 @@
*
* Module Name: exfldio - Aml Field I/O
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c
index d91f15cdf3ae..60e854965af9 100644
--- a/drivers/acpi/acpica/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -3,7 +3,7 @@
*
* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index c06079774bad..775cd62af5b3 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -3,7 +3,7 @@
*
* Module Name: exmutex - ASL Mutex Acquire/Release functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c
index 7eed79dcda83..bd68d66e89f0 100644
--- a/drivers/acpi/acpica/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -3,7 +3,7 @@
*
* Module Name: exnames - interpreter/scanner name load/execute
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index ba9fbae0cf91..06e35ea09823 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -3,7 +3,7 @@
*
* Module Name: exoparg1 - AML execution - opcodes with 1 argument
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index 3a477566ba1b..5e4a31a11df4 100644
--- a/drivers/acpi/acpica/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -3,7 +3,7 @@
*
* Module Name: exoparg2 - AML execution - opcodes with 2 arguments
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -390,10 +390,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
/* Failure means that the Index was beyond the end of the object */
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
- ACPI_FORMAT_UINT64(index),
- (u32)length));
+ ACPI_BIOS_EXCEPTION((AE_INFO, status,
+ "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
+ ACPI_FORMAT_UINT64(index),
+ (u32)length));
goto cleanup;
}
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index 764fa6f924ff..a4ebce417930 100644
--- a/drivers/acpi/acpica/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -3,7 +3,7 @@
*
* Module Name: exoparg3 - AML execution - opcodes with 3 arguments
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index 3941525f3d6b..31385a0b2dab 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -3,7 +3,7 @@
*
* Module Name: exoparg6 - AML execution - opcodes with 6 arguments
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 738f3c732363..728d752f7adc 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -3,7 +3,7 @@
*
* Module Name: exprep - ACPI AML field prep utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index 2c58f5e00b1a..c08521194b29 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -3,7 +3,7 @@
*
* Module Name: exregion - ACPI default op_region (address space) handlers
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index ea4b0fe674f1..b223d01e6bf8 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -3,7 +3,7 @@
*
* Module Name: exresnte - AML Interpreter object resolution
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index 5e42c7de46fa..36da5c0ef69c 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -3,7 +3,7 @@
*
* Module Name: exresolv - AML Interpreter object resolution
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index d94190bc5985..bdfe4d33b483 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -3,7 +3,7 @@
*
* Module Name: exresop - AML Interpreter operand/object resolution
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c
index ec61553c4483..c5aa4b0deb70 100644
--- a/drivers/acpi/acpica/exserial.c
+++ b/drivers/acpi/acpica/exserial.c
@@ -3,7 +3,7 @@
*
* Module Name: exserial - field_unit support for serial address spaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -21,7 +21,7 @@ ACPI_MODULE_NAME("exserial")
* FUNCTION: acpi_ex_read_gpio
*
* PARAMETERS: obj_desc - The named field to read
- * buffer - Where the return data is returnd
+ * buffer - Where the return data is returned
*
* RETURN: Status
*
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index 75d5665b7b2f..7f3c3571c292 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -3,7 +3,7 @@
*
* Module Name: exstore - AML Interpreter object store support
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index 31cba19652ed..4e43c8277f07 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -4,7 +4,7 @@
* Module Name: exstoren - AML Interpreter object store support,
* Store to Node (namespace object)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 4cd82ff509bc..dc9e2b1c1ad9 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -3,7 +3,7 @@
*
* Module Name: exstorob - AML object store support, store to object
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index ec8b5a22cad4..a538f7799b78 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -3,7 +3,7 @@
*
* Module Name: exsystem - Interface to OS services
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/extrace.c b/drivers/acpi/acpica/extrace.c
index 9bd3fa56b51a..db7f93ca539f 100644
--- a/drivers/acpi/acpica/extrace.c
+++ b/drivers/acpi/acpica/extrace.c
@@ -3,7 +3,7 @@
*
* Module Name: extrace - Support for interpreter execution tracing
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index bd22e27adf9b..75380be1c2ef 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -3,7 +3,7 @@
*
* Module Name: exutils - interpreter/scanner utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -160,7 +160,7 @@ u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
* RETURN: None
*
* DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
- * flags specifiy that it is to be obtained before field access.
+ * flags specify that it is to be obtained before field access.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index 525e6ea5c114..926f7e080f22 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -3,7 +3,7 @@
*
* Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c
index e0ad3f11142e..dee3affaca49 100644
--- a/drivers/acpi/acpica/hwesleep.c
+++ b/drivers/acpi/acpica/hwesleep.c
@@ -4,7 +4,7 @@
* Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
* extended FADT-V5 sleep registers.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 2d2e2e41a685..565bd3f29f31 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -3,7 +3,7 @@
*
* Module Name: hwgpe - Low level GPE enable/disable/clear functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index d8b8fc2ff563..b62db8ec446f 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -4,7 +4,7 @@
* Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
* original/legacy sleep/PM registers.
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index 5d5e27146fc2..2fb9f75d71c5 100644
--- a/drivers/acpi/acpica/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -3,7 +3,7 @@
*
* Name: hwtimer.c - ACPI Power Management Timer Interface
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index 24f9b61aa404..cd576153257c 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -3,7 +3,7 @@
*
* Module Name: hwvalid - I/O request validation
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 6e39a771a56e..c4fd97104024 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -3,7 +3,7 @@
*
* Module Name: hwxface - Public ACPICA hardware interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 3f22f7dd4556..abbf9702aa7f 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -3,7 +3,7 @@
*
* Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -23,33 +23,6 @@ acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
acpi_physical_address physical_address64);
#endif
-static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
-
-/*
- * Dispatch table used to efficiently branch to the various sleep
- * functions.
- */
-#define ACPI_SLEEP_FUNCTION_ID 0
-#define ACPI_WAKE_PREP_FUNCTION_ID 1
-#define ACPI_WAKE_FUNCTION_ID 2
-
-/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
-
-static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
- {ACPI_STRUCT_INIT(legacy_function,
- ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep)),
- ACPI_STRUCT_INIT(extended_function,
- acpi_hw_extended_sleep)},
- {ACPI_STRUCT_INIT(legacy_function,
- ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep)),
- ACPI_STRUCT_INIT(extended_function,
- acpi_hw_extended_wake_prep)},
- {ACPI_STRUCT_INIT(legacy_function,
- ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake)),
- ACPI_STRUCT_INIT(extended_function,
- acpi_hw_extended_wake)}
-};
-
/*
* These functions are removed for the ACPI_REDUCED_HARDWARE case:
* acpi_set_firmware_waking_vector
@@ -209,53 +182,6 @@ acpi_status acpi_enter_sleep_state_s4bios(void)
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
#endif /* !ACPI_REDUCED_HARDWARE */
-/*******************************************************************************
- *
- * FUNCTION: acpi_hw_sleep_dispatch
- *
- * PARAMETERS: sleep_state - Which sleep state to enter/exit
- * function_id - Sleep, wake_prep, or Wake
- *
- * RETURN: Status from the invoked sleep handling function.
- *
- * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
- * function.
- *
- ******************************************************************************/
-static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
-{
- acpi_status status;
- struct acpi_sleep_functions *sleep_functions =
- &acpi_sleep_dispatch[function_id];
-
-#if (!ACPI_REDUCED_HARDWARE)
- /*
- * If the Hardware Reduced flag is set (from the FADT), we must
- * use the extended sleep registers (FADT). Note: As per the ACPI
- * specification, these extended registers are to be used for HW-reduced
- * platforms only. They are not general-purpose replacements for the
- * legacy PM register sleep support.
- */
- if (acpi_gbl_reduced_hardware) {
- status = sleep_functions->extended_function(sleep_state);
- } else {
- /* Legacy sleep */
-
- status = sleep_functions->legacy_function(sleep_state);
- }
-
- return (status);
-
-#else
- /*
- * For the case where reduced-hardware-only code is being generated,
- * we know that only the extended sleep registers are available
- */
- status = sleep_functions->extended_function(sleep_state);
- return (status);
-
-#endif /* !ACPI_REDUCED_HARDWARE */
-}
/*******************************************************************************
*
@@ -362,7 +288,12 @@ acpi_status acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
- status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+ if (!acpi_gbl_reduced_hardware)
+ status = acpi_hw_legacy_sleep(sleep_state);
+ else
+#endif
+ status = acpi_hw_extended_sleep(sleep_state);
return_ACPI_STATUS(status);
}
@@ -388,8 +319,12 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
- status =
- acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+ if (!acpi_gbl_reduced_hardware)
+ status = acpi_hw_legacy_wake_prep(sleep_state);
+ else
+#endif
+ status = acpi_hw_extended_wake_prep(sleep_state);
return_ACPI_STATUS(status);
}
@@ -413,7 +348,12 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
- status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+ if (!acpi_gbl_reduced_hardware)
+ status = acpi_hw_legacy_wake(sleep_state);
+ else
+#endif
+ status = acpi_hw_extended_wake(sleep_state);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c
index b9ede797b654..0e97ed38973f 100644
--- a/drivers/acpi/acpica/nsarguments.c
+++ b/drivers/acpi/acpica/nsarguments.c
@@ -3,7 +3,7 @@
*
* Module Name: nsarguments - Validation of args for ACPI predefined methods
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c
index f9527346b0f7..14cbf63f1991 100644
--- a/drivers/acpi/acpica/nsconvert.c
+++ b/drivers/acpi/acpica/nsconvert.c
@@ -4,7 +4,7 @@
* Module Name: nsconvert - Object conversions for objects returned by
* predefined methods
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 90ccffcd770b..15070bd0c28a 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -3,7 +3,7 @@
*
* Module Name: nsdump - table dumping routines for debug
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
index 2b291c500fb0..73e5c83c8c9f 100644
--- a/drivers/acpi/acpica/nsdumpdv.c
+++ b/drivers/acpi/acpica/nsdumpdv.c
@@ -3,7 +3,7 @@
*
* Module Name: nsdump - table dumping routines for debug
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index d77257d1c827..19fb8dda870f 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -3,7 +3,7 @@
*
* Module Name: nsinit - namespace initialization
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index 04bc73e82aed..35fff5c75da1 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -3,7 +3,7 @@
*
* Module Name: nsload - namespace loading/expanding/contracting procedures
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -75,7 +75,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
/*
* On error, delete any namespace objects created by this table.
* We cannot initialize these objects, so delete them. There are
- * a couple of expecially bad cases:
+ * a couple of especially bad cases:
* AE_ALREADY_EXISTS - namespace collision.
* AE_NOT_FOUND - the target of a Scope operator does not
* exist. This target of Scope must already exist in the
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index 488ff39d86f7..c0b4f7bedfab 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -3,7 +3,7 @@
*
* Module Name: nsparse - namespace interface to AML parser
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -253,61 +253,19 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
ACPI_FUNCTION_TRACE(ns_parse_table);
- if (acpi_gbl_execute_tables_as_methods) {
- /*
- * This case executes the AML table as one large control method.
- * The point of this is to execute any module-level code in-place
- * as the table is parsed. Some AML code depends on this behavior.
- *
- * It is a run-time option at this time, but will eventually become
- * the default.
- *
- * Note: This causes the table to only have a single-pass parse.
- * However, this is compatible with other ACPI implementations.
- */
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
- "%s: **** Start table execution pass\n",
- ACPI_GET_FUNCTION_NAME));
-
- status = acpi_ns_execute_table(table_index, start_node);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- } else {
- /*
- * AML Parse, pass 1
- *
- * In this pass, we load most of the namespace. Control methods
- * are not parsed until later. A parse tree is not created.
- * Instead, each Parser Op subtree is deleted when it is finished.
- * This saves a great deal of memory, and allows a small cache of
- * parse objects to service the entire parse. The second pass of
- * the parse then performs another complete parse of the AML.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
-
- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
- table_index, start_node);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ /*
+ * Executes the AML table as one large control method.
+ * The point of this is to execute any module-level code in-place
+ * as the table is parsed. Some AML code depends on this behavior.
+ *
+ * Note: This causes the table to only have a single-pass parse.
+ * However, this is compatible with other ACPI implementations.
+ */
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
+ "%s: **** Start table execution pass\n",
+ ACPI_GET_FUNCTION_NAME));
- /*
- * AML Parse, pass 2
- *
- * In this pass, we resolve forward references and other things
- * that could not be completed during the first pass.
- * Another complete parse of the AML is performed, but the
- * overhead of this is compensated for by the fact that the
- * parse objects are all cached.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
- table_index, start_node);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
+ status = acpi_ns_execute_table(table_index, start_node);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 29c68b15a64f..2f9d93122d0c 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -3,7 +3,7 @@
*
* Module Name: nspredef - Validation of ACPI predefined methods and objects
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c
index 51523473e7fe..9a80e3b23496 100644
--- a/drivers/acpi/acpica/nsprepkg.c
+++ b/drivers/acpi/acpica/nsprepkg.c
@@ -3,7 +3,7 @@
*
* Module Name: nsprepkg - Validation of package objects for predefined names
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index ff2ab8fbec38..0aacfa48e20d 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -3,7 +3,7 @@
*
* Module Name: nsrepair - Repair for objects returned by predefined methods
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index a3bd6280882c..d5804a6d1d65 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -4,7 +4,7 @@
* Module Name: nsrepair2 - Repair for objects returned by specific
* predefined methods
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index a2bf4b2caa6c..e5cef1edf49f 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -4,7 +4,7 @@
* Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
* parents and siblings and Scope manipulation
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -350,7 +350,7 @@ acpi_ns_internalize_name(const char *external_name, char **converted_name)
*
* FUNCTION: acpi_ns_externalize_name
*
- * PARAMETERS: internal_name_length - Lenth of the internal name below
+ * PARAMETERS: internal_name_length - Length of the internal name below
* internal_name - Internal representation of name
* converted_name_length - Where the length is returned
* converted_name - Where the resulting external name
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index e9a061da9bb2..ceea6af79d12 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -3,7 +3,7 @@
*
* Module Name: nswalk - Functions for walking the ACPI namespace
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index b2915c9cceaf..de2d3135d6a9 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -4,7 +4,7 @@
* Module Name: nsxfname - Public interfaces to the ACPI subsystem
* ACPI Namespace oriented interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index 176d28d60125..9d9d442cd999 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -3,7 +3,7 @@
*
* Module Name: psargs - Parse AML opcode arguments
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index e00d1af6fa80..207805047bc4 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -3,7 +3,7 @@
*
* Module Name: psloop - Main AML parse loop
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -32,10 +32,6 @@ static acpi_status
acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
u8 * aml_op_start, union acpi_parse_object *op);
-static void
-acpi_ps_link_module_code(union acpi_parse_object *parent_op,
- u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_arguments
@@ -56,7 +52,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
{
acpi_status status = AE_OK;
union acpi_parse_object *arg = NULL;
- const struct acpi_opcode_info *op_info;
ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
@@ -136,96 +131,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
walk_state->arg_count,
walk_state->pass_number));
- /*
- * This case handles the legacy option that groups all module-level
- * code blocks together and defers execution until all of the tables
- * are loaded. Execute all of these blocks at this time.
- * Execute any module-level code that was detected during the table
- * load phase.
- *
- * Note: this option is deprecated and will be eliminated in the
- * future. Use of this option can cause problems with AML code that
- * depends upon in-order immediate execution of module-level code.
- */
- if (!acpi_gbl_execute_tables_as_methods &&
- (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
- ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
- /*
- * We want to skip If/Else/While constructs during Pass1 because we
- * want to actually conditionally execute the code during Pass2.
- *
- * Except for disassembly, where we always want to walk the
- * If/Else/While packages
- */
- switch (op->common.aml_opcode) {
- case AML_IF_OP:
- case AML_ELSE_OP:
- case AML_WHILE_OP:
- /*
- * Currently supported module-level opcodes are:
- * IF/ELSE/WHILE. These appear to be the most common,
- * and easiest to support since they open an AML
- * package.
- */
- if (walk_state->pass_number ==
- ACPI_IMODE_LOAD_PASS1) {
- acpi_ps_link_module_code(op->common.
- parent,
- aml_op_start,
- (u32)
- (walk_state->
- parser_state.
- pkg_end -
- aml_op_start),
- walk_state->
- owner_id);
- }
-
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Pass1: Skipping an If/Else/While body\n"));
-
- /* Skip body of if/else/while in pass 1 */
-
- walk_state->parser_state.aml =
- walk_state->parser_state.pkg_end;
- walk_state->arg_count = 0;
- break;
-
- default:
- /*
- * Check for an unsupported executable opcode at module
- * level. We must be in PASS1, the parent must be a SCOPE,
- * The opcode class must be EXECUTE, and the opcode must
- * not be an argument to another opcode.
- */
- if ((walk_state->pass_number ==
- ACPI_IMODE_LOAD_PASS1)
- && (op->common.parent->common.aml_opcode ==
- AML_SCOPE_OP)) {
- op_info =
- acpi_ps_get_opcode_info(op->common.
- aml_opcode);
- if ((op_info->class ==
- AML_CLASS_EXECUTE) && (!arg)) {
- ACPI_WARNING((AE_INFO,
- "Unsupported module-level executable opcode "
- "0x%.2X at table offset 0x%.4X",
- op->common.
- aml_opcode,
- (u32)
- (ACPI_PTR_DIFF
- (aml_op_start,
- walk_state->
- parser_state.
- aml_start) +
- sizeof(struct
- acpi_table_header))));
- }
- }
- break;
- }
- }
-
/* Special processing for certain opcodes */
switch (op->common.aml_opcode) {
@@ -302,104 +207,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
/*******************************************************************************
*
- * FUNCTION: acpi_ps_link_module_code
- *
- * PARAMETERS: parent_op - Parent parser op
- * aml_start - Pointer to the AML
- * aml_length - Length of executable AML
- * owner_id - owner_id of module level code
- *
- * RETURN: None.
- *
- * DESCRIPTION: Wrap the module-level code with a method object and link the
- * object to the global list. Note, the mutex field of the method
- * object is used to link multiple module-level code objects.
- *
- * NOTE: In this legacy option, each block of detected executable AML
- * code that is outside of any control method is wrapped with a temporary
- * control method object and placed on a global list below.
- *
- * This function executes the module-level code for all tables only after
- * all of the tables have been loaded. It is a legacy option and is
- * not compatible with other ACPI implementations. See acpi_ns_load_table.
- *
- * This function will be removed when the legacy option is removed.
- *
- ******************************************************************************/
-
-static void
-acpi_ps_link_module_code(union acpi_parse_object *parent_op,
- u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
-{
- union acpi_operand_object *prev;
- union acpi_operand_object *next;
- union acpi_operand_object *method_obj;
- struct acpi_namespace_node *parent_node;
-
- ACPI_FUNCTION_TRACE(ps_link_module_code);
-
- /* Get the tail of the list */
-
- prev = next = acpi_gbl_module_code_list;
- while (next) {
- prev = next;
- next = next->method.mutex;
- }
-
- /*
- * Insert the module level code into the list. Merge it if it is
- * adjacent to the previous element.
- */
- if (!prev ||
- ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
-
- /* Create, initialize, and link a new temporary method object */
-
- method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
- if (!method_obj) {
- return_VOID;
- }
-
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Create/Link new code block: %p\n",
- method_obj));
-
- if (parent_op->common.node) {
- parent_node = parent_op->common.node;
- } else {
- parent_node = acpi_gbl_root_node;
- }
-
- method_obj->method.aml_start = aml_start;
- method_obj->method.aml_length = aml_length;
- method_obj->method.owner_id = owner_id;
- method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
-
- /*
- * Save the parent node in next_object. This is cheating, but we
- * don't want to expand the method object.
- */
- method_obj->method.next_object =
- ACPI_CAST_PTR(union acpi_operand_object, parent_node);
-
- if (!prev) {
- acpi_gbl_module_code_list = method_obj;
- } else {
- prev->method.mutex = method_obj;
- }
- } else {
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Appending to existing code block: %p\n",
- prev));
-
- prev->method.aml_length += aml_length;
- }
-
- return_VOID;
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ps_parse_loop
*
* PARAMETERS: walk_state - Current state
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c
index e1fd819a2955..98e5c7400e54 100644
--- a/drivers/acpi/acpica/psobject.c
+++ b/drivers/acpi/acpica/psobject.c
@@ -3,7 +3,7 @@
*
* Module Name: psobject - Support for parse objects
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
index 8d7dc98bad17..43775c5ce17c 100644
--- a/drivers/acpi/acpica/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -3,7 +3,7 @@
*
* Module Name: psopcode - Parser/Interpreter opcode information table
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c
index f310954eea59..15e7563829f1 100644
--- a/drivers/acpi/acpica/psopinfo.c
+++ b/drivers/acpi/acpica/psopinfo.c
@@ -3,7 +3,7 @@
*
* Module Name: psopinfo - AML opcode information functions and dispatch tables
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 65603473b6cb..9b386530ffbe 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -3,7 +3,7 @@
*
* Module Name: psparse - Parser top level AML parse routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -523,12 +523,12 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
if (status == AE_ABORT_METHOD) {
acpi_ns_print_node_pathname(walk_state->
method_node,
- "Method aborted:");
+ "Aborting method");
acpi_os_printf("\n");
} else {
- ACPI_ERROR_METHOD
- ("Method parse/execution failed",
- walk_state->method_node, NULL, status);
+ ACPI_ERROR_METHOD("Aborting method",
+ walk_state->method_node, NULL,
+ status);
}
acpi_ex_enter_interpreter();
diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c
index 00c67bc249aa..f153ca804740 100644
--- a/drivers/acpi/acpica/psscope.c
+++ b/drivers/acpi/acpica/psscope.c
@@ -3,7 +3,7 @@
*
* Module Name: psscope - Parser scope stack management routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c
index 64a8329a17f1..22d8a2becdd0 100644
--- a/drivers/acpi/acpica/pstree.c
+++ b/drivers/acpi/acpica/pstree.c
@@ -3,7 +3,7 @@
*
* Module Name: pstree - Parser op tree manipulation/traversal/search
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index ef8a5805a836..2512f584fa3c 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -3,7 +3,7 @@
*
* Module Name: psutils - Parser miscellaneous utilities (Parser only)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c
index bd6af8c87d48..cf91841297c2 100644
--- a/drivers/acpi/acpica/pswalk.c
+++ b/drivers/acpi/acpica/pswalk.c
@@ -3,7 +3,7 @@
*
* Module Name: pswalk - Parser routines to walk parsed op tree(s)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index 5743b22399a0..ee2ee2c858f2 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -3,7 +3,7 @@
*
* Module Name: psxface - Parser external interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c
index 77a3263169fa..cafa8134b4c6 100644
--- a/drivers/acpi/acpica/rsdumpinfo.c
+++ b/drivers/acpi/acpica/rsdumpinfo.c
@@ -32,7 +32,7 @@ struct acpi_rsdump_info acpi_rs_dump_irq[7] = {
acpi_gbl_he_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
acpi_gbl_ll_decode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing",
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(irq.shareable), "Sharing",
acpi_gbl_shr_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count),
"Interrupt Count", NULL},
@@ -222,7 +222,7 @@ struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = {
"Triggering", acpi_gbl_he_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity",
acpi_gbl_ll_decode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing",
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(extended_irq.shareable), "Sharing",
acpi_gbl_shr_decode},
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL,
NULL},
@@ -255,7 +255,7 @@ struct acpi_rsdump_info acpi_rs_dump_gpio[16] = {
"ProducerConsumer", acpi_gbl_consume_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig",
acpi_gbl_ppc_decode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharing",
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.shareable), "Sharing",
acpi_gbl_shr_decode},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction),
"IoRestriction", acpi_gbl_ior_decode},
@@ -285,7 +285,7 @@ struct acpi_rsdump_info acpi_rs_dump_pin_function[10] = {
"RevisionId", NULL},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(pin_function.pin_config), "PinConfig",
acpi_gbl_ppc_decode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_function.sharable), "Sharing",
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_function.shareable), "Sharing",
acpi_gbl_shr_decode},
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(pin_function.function_number),
"FunctionNumber", NULL},
@@ -308,7 +308,7 @@ struct acpi_rsdump_info acpi_rs_dump_pin_config[11] = {
NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_config.producer_consumer),
"ProducerConsumer", acpi_gbl_consume_decode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_config.sharable), "Sharing",
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_config.shareable), "Sharing",
acpi_gbl_shr_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(pin_config.pin_config_type),
"PinConfigType", NULL},
@@ -353,7 +353,7 @@ struct acpi_rsdump_info acpi_rs_dump_pin_group_function[9] = {
{ACPI_RSD_1BITFLAG,
ACPI_RSD_OFFSET(pin_group_function.producer_consumer),
"ProducerConsumer", acpi_gbl_consume_decode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_group_function.sharable),
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_group_function.shareable),
"Sharing", acpi_gbl_shr_decode},
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(pin_group_function.function_number),
"FunctionNumber", NULL},
@@ -375,7 +375,7 @@ struct acpi_rsdump_info acpi_rs_dump_pin_group_config[10] = {
"RevisionId", NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_group_config.producer_consumer),
"ProducerConsumer", acpi_gbl_consume_decode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_group_config.sharable),
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(pin_group_config.shareable),
"Sharing", acpi_gbl_shr_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(pin_group_config.pin_config_type),
"PinConfigType", NULL},
diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c
index 134b67cd48ee..b0d970efa072 100644
--- a/drivers/acpi/acpica/rsirq.c
+++ b/drivers/acpi/acpica/rsirq.c
@@ -54,7 +54,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[9] = {
AML_OFFSET(irq.flags),
3},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.shareable),
AML_OFFSET(irq.flags),
4},
@@ -92,7 +92,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[14] = {
AML_OFFSET(irq.flags),
3},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.shareable),
AML_OFFSET(irq.flags),
4},
@@ -139,7 +139,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[14] = {
ACPI_ACTIVE_HIGH},
{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
- ACPI_RS_OFFSET(data.irq.sharable),
+ ACPI_RS_OFFSET(data.irq.shareable),
ACPI_EXCLUSIVE},
/* We can optimize to a 2-byte irq_no_flags() descriptor */
@@ -178,7 +178,7 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[10] = {
AML_OFFSET(extended_irq.flags),
2},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.shareable),
AML_OFFSET(extended_irq.flags),
3},
diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c
index d073ebb51f90..1b937d88980f 100644
--- a/drivers/acpi/acpica/rsserial.c
+++ b/drivers/acpi/acpica/rsserial.c
@@ -39,7 +39,7 @@ struct acpi_rsconvert_info acpi_rs_convert_gpio[18] = {
AML_OFFSET(gpio.flags),
0},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.shareable),
AML_OFFSET(gpio.int_flags),
3},
@@ -128,7 +128,7 @@ struct acpi_rsconvert_info acpi_rs_convert_pin_function[13] = {
AML_OFFSET(pin_function.revision_id),
1},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_function.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_function.shareable),
AML_OFFSET(pin_function.flags),
0},
@@ -518,7 +518,7 @@ struct acpi_rsconvert_info acpi_rs_convert_pin_config[14] = {
AML_OFFSET(pin_config.revision_id),
1},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_config.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_config.shareable),
AML_OFFSET(pin_config.flags),
0},
@@ -658,7 +658,7 @@ struct acpi_rsconvert_info acpi_rs_convert_pin_group_function[13] = {
AML_OFFSET(pin_group_function.revision_id),
1},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_group_function.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_group_function.shareable),
AML_OFFSET(pin_group_function.flags),
0},
@@ -735,7 +735,7 @@ struct acpi_rsconvert_info acpi_rs_convert_pin_group_config[14] = {
AML_OFFSET(pin_group_config.revision_id),
1},
- {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_group_config.sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.pin_group_config.shareable),
AML_OFFSET(pin_group_config.flags),
0},
diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c
index 862149c8a208..0cecd0039acf 100644
--- a/drivers/acpi/acpica/tbdata.c
+++ b/drivers/acpi/acpica/tbdata.c
@@ -3,7 +3,7 @@
*
* Module Name: tbdata - Table manager data structure functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 99d325a51816..0041bfba9abc 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -3,7 +3,7 @@
*
* Module Name: tbfadt - FADT table utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -556,7 +556,7 @@ static void acpi_tb_convert_fadt(void)
* 64-bit X length field.
* Note: If the legacy length field is > 0xFF bits, ignore
* this check. (GPE registers can be larger than the
- * 64-bit GAS structure can accomodate, 0xFF bits).
+ * 64-bit GAS structure can accommodate, 0xFF bits).
*/
if ((ACPI_MUL_8(length) <= ACPI_UINT8_MAX) &&
(address64->bit_width !=
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index f00694b1d000..951bd8e1c50a 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -3,7 +3,7 @@
*
* Module Name: tbfind - find table
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 5f8e7b561c90..be6642bf6366 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -3,7 +3,7 @@
*
* Module Name: tbinstal - ACPI table installation and removal
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c
index e303418a895b..9b5df95d881b 100644
--- a/drivers/acpi/acpica/tbprint.c
+++ b/drivers/acpi/acpica/tbprint.c
@@ -3,7 +3,7 @@
*
* Module Name: tbprint - Table output utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index b526096560b5..2469e01310e2 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -3,7 +3,7 @@
*
* Module Name: tbutils - ACPI Table utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index e4d0dc8948cd..36592888f0e7 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -3,7 +3,7 @@
*
* Module Name: tbxface - ACPI table-oriented external interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -108,7 +108,7 @@ acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
/*
* Get the root table (RSDT or XSDT) and extract all entries to the local
* Root Table Array. This array contains the information of the RSDT/XSDT
- * in a common, more useable format.
+ * in a common, more usable format.
*/
status = acpi_tb_parse_root_table(rsdp_address);
return_ACPI_STATUS(status);
@@ -169,7 +169,7 @@ acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
if (!acpi_gbl_enable_table_validation) {
/*
* Now it's safe to do full table validation. We can do deferred
- * table initilization here once the flag is set.
+ * table initialization here once the flag is set.
*/
acpi_gbl_enable_table_validation = TRUE;
for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index 9011297552af..1a2592cc3245 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -3,7 +3,7 @@
*
* Module Name: tbxfload - Table load/unload external interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -69,23 +69,18 @@ acpi_status ACPI_INIT_FUNCTION acpi_load_tables(void)
"While loading namespace from ACPI tables"));
}
- if (acpi_gbl_execute_tables_as_methods) {
- /*
- * If the module-level code support is enabled, initialize the objects
- * in the namespace that remain uninitialized. This runs the executable
- * AML that may be part of the declaration of these name objects:
- * operation_regions, buffer_fields, Buffers, and Packages.
- *
- * Note: The module-level code is optional at this time, but will
- * become the default in the future.
- */
- status = acpi_ns_initialize_objects();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ /*
+ * Initialize the objects in the namespace that remain uninitialized.
+ * This runs the executable AML that may be part of the declaration of
+ * these name objects:
+ * operation_regions, buffer_fields, Buffers, and Packages.
+ *
+ */
+ status = acpi_ns_initialize_objects();
+ if (ACPI_SUCCESS(status)) {
+ acpi_gbl_namespace_initialized = TRUE;
}
- acpi_gbl_namespace_initialized = TRUE;
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 483d0ce5180a..e2859d09ca2e 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -3,7 +3,7 @@
*
* Module Name: tbxfroot - Find the root ACPI table (RSDT)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
index dbabe680ff58..bb260376bd59 100644
--- a/drivers/acpi/acpica/utaddress.c
+++ b/drivers/acpi/acpica/utaddress.c
@@ -3,7 +3,7 @@
*
* Module Name: utaddress - op_region address range check
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c
index 8cbcd7d6bd5e..d64da4d9e8d0 100644
--- a/drivers/acpi/acpica/utalloc.c
+++ b/drivers/acpi/acpica/utalloc.c
@@ -3,7 +3,7 @@
*
* Module Name: utalloc - local memory allocation routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utascii.c b/drivers/acpi/acpica/utascii.c
index 04ff61e284f5..79d7426fd7bf 100644
--- a/drivers/acpi/acpica/utascii.c
+++ b/drivers/acpi/acpica/utascii.c
@@ -3,7 +3,7 @@
*
* Module Name: utascii - Utility ascii functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c
index fffa6f5ae59e..61db9967ebe4 100644
--- a/drivers/acpi/acpica/utbuffer.c
+++ b/drivers/acpi/acpica/utbuffer.c
@@ -3,7 +3,7 @@
*
* Module Name: utbuffer - Buffer dump routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
index 97d6ec174c28..8533fce7fa93 100644
--- a/drivers/acpi/acpica/utcache.c
+++ b/drivers/acpi/acpica/utcache.c
@@ -3,7 +3,7 @@
*
* Module Name: utcache - local cache allocation routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index a872ed7879ca..1fb8327f3c3b 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -3,7 +3,7 @@
*
* Module Name: utcopy - Internal to external object translation utilities
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index aabdc25effd9..01b1b36c8a8e 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -3,7 +3,7 @@
*
* Module Name: utdebug - Debug print/trace routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index dad02b821e19..ad9f77eb554f 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -3,7 +3,7 @@
*
* Module Name: utdecode - Utility decoding routines (value-to-string)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -284,7 +284,7 @@ const char *acpi_ut_get_node_name(void *object)
static const char *acpi_gbl_desc_type_names[] = {
/* 00 */ "Not a Descriptor",
- /* 01 */ "Cached",
+ /* 01 */ "Cached Object",
/* 02 */ "State-Generic",
/* 03 */ "State-Update",
/* 04 */ "State-Package",
@@ -295,10 +295,10 @@ static const char *acpi_gbl_desc_type_names[] = {
/* 09 */ "State-Result",
/* 10 */ "State-Notify",
/* 11 */ "State-Thread",
- /* 12 */ "Walk",
- /* 13 */ "Parser",
- /* 14 */ "Operand",
- /* 15 */ "Node"
+ /* 12 */ "Tree Walk State",
+ /* 13 */ "Parse Tree Op",
+ /* 14 */ "Operand Object",
+ /* 15 */ "Namespace Node"
};
const char *acpi_ut_get_descriptor_name(void *object)
@@ -430,8 +430,10 @@ static const char *acpi_gbl_generic_notify[ACPI_GENERIC_NOTIFY_MAX + 1] = {
/* 0C */ "Reserved (was previously Shutdown Request)",
/* Reserved in ACPI 6.0 */
/* 0D */ "System Resource Affinity Update",
- /* 0E */ "Heterogeneous Memory Attributes Update"
+ /* 0E */ "Heterogeneous Memory Attributes Update",
/* ACPI 6.2 */
+ /* 0F */ "Error Disconnect Recover"
+ /* ACPI 6.3 */
};
static const char *acpi_gbl_device_notify[5] = {
@@ -461,13 +463,13 @@ static const char *acpi_gbl_thermal_notify[5] = {
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
{
- /* 00 - 0D are "common to all object types" (from ACPI Spec) */
+ /* 00 - 0F are "common to all object types" (from ACPI Spec) */
if (notify_value <= ACPI_GENERIC_NOTIFY_MAX) {
return (acpi_gbl_generic_notify[notify_value]);
}
- /* 0E - 7F are reserved */
+ /* 10 - 7F are reserved */
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index 8cc4392c61f3..eee263cb7beb 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -257,6 +257,10 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
acpi_ut_delete_object_desc(second_desc);
}
+ if (object->field.internal_pcc_buffer) {
+ ACPI_FREE(object->field.internal_pcc_buffer);
+ }
+
break;
case ACPI_TYPE_BUFFER_FIELD:
diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c
index e47430272692..075457341bad 100644
--- a/drivers/acpi/acpica/uterror.c
+++ b/drivers/acpi/acpica/uterror.c
@@ -183,19 +183,19 @@ acpi_ut_prefixed_namespace_error(const char *module_name,
case AE_ALREADY_EXISTS:
acpi_os_printf(ACPI_MSG_BIOS_ERROR);
- message = "Failure creating";
+ message = "Failure creating named object";
break;
case AE_NOT_FOUND:
acpi_os_printf(ACPI_MSG_BIOS_ERROR);
- message = "Could not resolve";
+ message = "Could not resolve symbol";
break;
default:
acpi_os_printf(ACPI_MSG_ERROR);
- message = "Failure resolving";
+ message = "Failure resolving symbol";
break;
}
@@ -317,7 +317,8 @@ acpi_ut_method_error(const char *module_name,
}
acpi_ns_print_node_pathname(node, message);
- acpi_os_printf(", %s", acpi_format_exception(method_status));
+ acpi_os_printf(" due to previous error (%s)",
+ acpi_format_exception(method_status));
ACPI_MSG_SUFFIX;
ACPI_MSG_REDIRECT_END;
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index c56ae6e058d5..558a9f3b0678 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -3,7 +3,7 @@
*
* Module Name: uteval - Object evaluation
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index f8c5b49344df..b0622ec4bb85 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -3,7 +3,7 @@
*
* Module Name: utglobal - Global variables for the ACPI subsystem
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c
index 3d63a9e8da4f..b6da135d5f41 100644
--- a/drivers/acpi/acpica/uthex.c
+++ b/drivers/acpi/acpica/uthex.c
@@ -3,7 +3,7 @@
*
* Module Name: uthex -- Hex/ASCII support functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index 70e6bf1107a1..e805abdd95b8 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -3,7 +3,7 @@
*
* Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 0646ed62b351..bc124591320e 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -3,7 +3,7 @@
*
* Module Name: utinit - Common ACPI subsystem initialization
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c
index d61e01bd01a3..8b4ff11d617a 100644
--- a/drivers/acpi/acpica/utlock.c
+++ b/drivers/acpi/acpica/utlock.c
@@ -3,7 +3,7 @@
*
* Module Name: utlock - Reader/Writer lock interfaces
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index ae6d8cc18cec..eee97a902696 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -3,7 +3,7 @@
*
* Module Name: utobject - ACPI object create/delete/size/cache routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 902a47463abf..688c61a90725 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -3,7 +3,7 @@
*
* Module Name: utosi - Support for the _OSI predefined control method
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c
index 65ca9807c2a8..a9f08f43c685 100644
--- a/drivers/acpi/acpica/utpredef.c
+++ b/drivers/acpi/acpica/utpredef.c
@@ -3,7 +3,7 @@
*
* Module Name: utpredef - support functions for predefined names
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c
index a98c334c3bb7..5839f2fa7400 100644
--- a/drivers/acpi/acpica/utprint.c
+++ b/drivers/acpi/acpica/utprint.c
@@ -3,7 +3,7 @@
*
* Module Name: utprint - Formatted printing routines
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
index 016a6621cc6f..8052f7ef5025 100644
--- a/drivers/acpi/acpica/uttrack.c
+++ b/drivers/acpi/acpica/uttrack.c
@@ -3,7 +3,7 @@
*
* Module Name: uttrack - Memory allocation tracking routines (debug only)
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
@@ -588,6 +588,18 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
acpi_ut_get_descriptor_name
(descriptor));
+ /* Optional object hex dump */
+
+ if (acpi_gbl_verbose_leak_dump) {
+ acpi_os_printf("\n");
+ acpi_ut_dump_buffer((u8 *)
+ descriptor,
+ element->
+ size,
+ DB_BYTE_DISPLAY,
+ 0);
+ }
+
/* Validate the descriptor type using Type field and length */
descriptor_type = 0; /* Not a valid descriptor type */
diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c
index 59ae118092a3..0a7cf8007643 100644
--- a/drivers/acpi/acpica/utuuid.c
+++ b/drivers/acpi/acpica/utuuid.c
@@ -3,7 +3,7 @@
*
* Module Name: utuuid -- UUID support functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index d2d6cc065181..f497c4b30e65 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -3,7 +3,7 @@
*
* Module Name: utxface - External interfaces, miscellaneous utility functions
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
index 6bb85d691fcb..a1ed7fced4db 100644
--- a/drivers/acpi/acpica/utxferror.c
+++ b/drivers/acpi/acpica/utxferror.c
@@ -187,6 +187,50 @@ ACPI_EXPORT_SYMBOL(acpi_bios_error)
/*******************************************************************************
*
+ * FUNCTION: acpi_bios_exception
+ *
+ * PARAMETERS: module_name - Caller's module name (for error output)
+ * line_number - Caller's line number (for error output)
+ * status - Status value to be decoded/formatted
+ * format - Printf format string + additional args
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Print an "ACPI Firmware Error" message with module/line/version
+ * info as well as decoded acpi_status.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_bios_exception(const char *module_name,
+ u32 line_number,
+ acpi_status status, const char *format, ...)
+{
+ va_list arg_list;
+
+ ACPI_MSG_REDIRECT_BEGIN;
+
+ /* For AE_OK, just print the message */
+
+ if (ACPI_SUCCESS(status)) {
+ acpi_os_printf(ACPI_MSG_BIOS_ERROR);
+
+ } else {
+ acpi_os_printf(ACPI_MSG_BIOS_ERROR "%s, ",
+ acpi_format_exception(status));
+ }
+
+ va_start(arg_list, format);
+ acpi_os_vprintf(format, arg_list);
+ ACPI_MSG_SUFFIX;
+ va_end(arg_list);
+
+ ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_bios_exception)
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_bios_warning
*
* PARAMETERS: module_name - Caller's module name (for warning output)
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
index e3c60f57c9f0..9f3b1e3a09de 100644
--- a/drivers/acpi/acpica/utxfinit.c
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -3,7 +3,7 @@
*
* Module Name: utxfinit - External interfaces for ACPICA initialization
*
- * Copyright (C) 2000 - 2018, Intel Corp.
+ * Copyright (C) 2000 - 2019, Intel Corp.
*
*****************************************************************************/
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index 52ae5438edeb..6b18f8bc7be3 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -41,19 +41,9 @@ config ACPI_APEI_PCIEAER
Turn on this option to enable the corresponding support.
config ACPI_APEI_SEA
- bool "APEI Synchronous External Abort logging/recovering support"
+ bool
depends on ARM64 && ACPI_APEI_GHES
default y
- help
- This option should be enabled if the system supports
- firmware first handling of SEA (Synchronous External Abort).
- SEA happens with certain faults of data abort or instruction
- abort synchronous exceptions on ARMv8 systems. If a system
- supports firmware first handling of SEA, the platform analyzes
- and handles hardware error notifications from SEA, and it may then
- form a HW error record for the OS to parse and handle. This
- option allows the OS to look for such hardware error record, and
- take appropriate action.
config ACPI_APEI_MEMORY_FAILURE
bool "APEI memory error recovering support"
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
index 12771fcf0417..0d948d0a41af 100644
--- a/drivers/acpi/apei/bert.c
+++ b/drivers/acpi/apei/bert.c
@@ -42,15 +42,7 @@ static void __init bert_print_all(struct acpi_bert_region *region,
int remain = region_len;
u32 estatus_len;
- if (!estatus->block_status)
- return;
-
- while (remain > sizeof(struct acpi_bert_region)) {
- if (cper_estatus_check(estatus)) {
- pr_err(FW_BUG "Invalid error record.\n");
- return;
- }
-
+ while (remain >= sizeof(struct acpi_bert_region)) {
estatus_len = cper_estatus_len(estatus);
if (remain < estatus_len) {
pr_err(FW_BUG "Truncated status block (length: %u).\n",
@@ -58,6 +50,15 @@ static void __init bert_print_all(struct acpi_bert_region *region,
return;
}
+ /* No more error records. */
+ if (!estatus->block_status)
+ return;
+
+ if (cper_estatus_check(estatus)) {
+ pr_err(FW_BUG "Invalid error record.\n");
+ return;
+ }
+
pr_info_once("Error records from previous boot:\n");
cper_estatus_print(KERN_INFO HW_ERR, estatus);
@@ -70,10 +71,6 @@ static void __init bert_print_all(struct acpi_bert_region *region,
estatus->block_status = 0;
estatus = (void *)estatus + estatus_len;
- /* No more error records. */
- if (!estatus->block_status)
- return;
-
remain -= estatus_len;
}
}
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index fcccbfdbdd1a..2d4be94f8c00 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -644,8 +644,8 @@ static int error_type_set(void *data, u64 val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(error_type_fops, error_type_get,
- error_type_set, "0x%llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(error_type_fops, error_type_get, error_type_set,
+ "0x%llx\n");
static int error_inject_set(void *data, u64 val)
{
@@ -656,8 +656,7 @@ static int error_inject_set(void *data, u64 val)
error_param3, error_param4);
}
-DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
- error_inject_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(error_inject_fops, NULL, error_inject_set, "%llu\n");
static int einj_check_table(struct acpi_table_einj *einj_tab)
{
@@ -679,7 +678,6 @@ static int __init einj_init(void)
{
int rc;
acpi_status status;
- struct dentry *fentry;
struct apei_exec_context ctx;
if (acpi_disabled) {
@@ -707,25 +705,13 @@ static int __init einj_init(void)
rc = -ENOMEM;
einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir());
- if (!einj_debug_dir) {
- pr_err("Error creating debugfs node.\n");
- goto err_cleanup;
- }
- fentry = debugfs_create_file("available_error_type", S_IRUSR,
- einj_debug_dir, NULL,
- &available_error_type_fops);
- if (!fentry)
- goto err_cleanup;
-
- fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR,
- einj_debug_dir, NULL, &error_type_fops);
- if (!fentry)
- goto err_cleanup;
- fentry = debugfs_create_file("error_inject", S_IWUSR,
- einj_debug_dir, NULL, &error_inject_fops);
- if (!fentry)
- goto err_cleanup;
+ debugfs_create_file("available_error_type", S_IRUSR, einj_debug_dir,
+ NULL, &available_error_type_fops);
+ debugfs_create_file_unsafe("error_type", 0600, einj_debug_dir,
+ NULL, &error_type_fops);
+ debugfs_create_file_unsafe("error_inject", 0200, einj_debug_dir,
+ NULL, &error_inject_fops);
apei_resources_init(&einj_resources);
einj_exec_ctx_init(&ctx);
@@ -750,66 +736,37 @@ static int __init einj_init(void)
rc = -ENOMEM;
einj_param = einj_get_parameter_address();
if ((param_extension || acpi5) && einj_param) {
- fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_flags);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param1);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param2);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param3);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param4);
- if (!fentry)
- goto err_unmap;
-
- fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
- einj_debug_dir, &notrigger);
- if (!fentry)
- goto err_unmap;
+ debugfs_create_x32("flags", S_IRUSR | S_IWUSR, einj_debug_dir,
+ &error_flags);
+ debugfs_create_x64("param1", S_IRUSR | S_IWUSR, einj_debug_dir,
+ &error_param1);
+ debugfs_create_x64("param2", S_IRUSR | S_IWUSR, einj_debug_dir,
+ &error_param2);
+ debugfs_create_x64("param3", S_IRUSR | S_IWUSR, einj_debug_dir,
+ &error_param3);
+ debugfs_create_x64("param4", S_IRUSR | S_IWUSR, einj_debug_dir,
+ &error_param4);
+ debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
+ einj_debug_dir, &notrigger);
}
if (vendor_dev[0]) {
vendor_blob.data = vendor_dev;
vendor_blob.size = strlen(vendor_dev);
- fentry = debugfs_create_blob("vendor", S_IRUSR,
- einj_debug_dir, &vendor_blob);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x32("vendor_flags", S_IRUSR | S_IWUSR,
- einj_debug_dir, &vendor_flags);
- if (!fentry)
- goto err_unmap;
+ debugfs_create_blob("vendor", S_IRUSR, einj_debug_dir,
+ &vendor_blob);
+ debugfs_create_x32("vendor_flags", S_IRUSR | S_IWUSR,
+ einj_debug_dir, &vendor_flags);
}
pr_info("Error INJection is initialized.\n");
return 0;
-err_unmap:
- if (einj_param) {
- acpi_size size = (acpi5) ?
- sizeof(struct set_error_type_with_address) :
- sizeof(struct einj_parameter);
-
- acpi_os_unmap_iomem(einj_param, size);
- pr_err("Error creating param extension debugfs nodes.\n");
- }
- apei_exec_post_unmap_gars(&ctx);
err_release:
apei_resources_release(&einj_resources);
err_fini:
apei_resources_fini(&einj_resources);
-err_cleanup:
- pr_err("Error creating primary debugfs nodes.\n");
debugfs_remove_recursive(einj_debug_dir);
return rc;
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 9953e50667ec..389d88e35ffb 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -938,17 +938,17 @@ static struct pstore_info erst_info = {
};
#define CPER_CREATOR_PSTORE \
- UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \
- 0x64, 0x90, 0xb8, 0x9d)
+ GUID_INIT(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \
+ 0x64, 0x90, 0xb8, 0x9d)
#define CPER_SECTION_TYPE_DMESG \
- UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \
- 0x94, 0x19, 0xeb, 0x12)
+ GUID_INIT(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \
+ 0x94, 0x19, 0xeb, 0x12)
#define CPER_SECTION_TYPE_DMESG_Z \
- UUID_LE(0x4f118707, 0x04dd, 0x4055, 0xb5, 0xdd, 0x95, 0x6d, \
- 0x34, 0xdd, 0xfa, 0xc6)
+ GUID_INIT(0x4f118707, 0x04dd, 0x4055, 0xb5, 0xdd, 0x95, 0x6d, \
+ 0x34, 0xdd, 0xfa, 0xc6)
#define CPER_SECTION_TYPE_MCE \
- UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
- 0x04, 0x4a, 0x38, 0xfc)
+ GUID_INIT(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
+ 0x04, 0x4a, 0x38, 0xfc)
struct cper_pstore_record {
struct cper_record_header hdr;
@@ -1012,7 +1012,7 @@ skip:
rc = -EIO;
goto out;
}
- if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
+ if (!guid_equal(&rcd->hdr.creator_id, &CPER_CREATOR_PSTORE))
goto skip;
record->buf = kmalloc(len, GFP_KERNEL);
@@ -1024,15 +1024,12 @@ skip:
record->id = record_id;
record->compressed = false;
record->ecc_notice_size = 0;
- if (uuid_le_cmp(rcd->sec_hdr.section_type,
- CPER_SECTION_TYPE_DMESG_Z) == 0) {
+ if (guid_equal(&rcd->sec_hdr.section_type, &CPER_SECTION_TYPE_DMESG_Z)) {
record->type = PSTORE_TYPE_DMESG;
record->compressed = true;
- } else if (uuid_le_cmp(rcd->sec_hdr.section_type,
- CPER_SECTION_TYPE_DMESG) == 0)
+ } else if (guid_equal(&rcd->sec_hdr.section_type, &CPER_SECTION_TYPE_DMESG))
record->type = PSTORE_TYPE_DMESG;
- else if (uuid_le_cmp(rcd->sec_hdr.section_type,
- CPER_SECTION_TYPE_MCE) == 0)
+ else if (guid_equal(&rcd->sec_hdr.section_type, &CPER_SECTION_TYPE_MCE))
record->type = PSTORE_TYPE_MCE;
else
record->type = PSTORE_TYPE_MAX;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index f008ba7c9ced..0b5ae91fd0fb 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -25,6 +25,7 @@
* GNU General Public License for more details.
*/
+#include <linux/arm_sdei.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -33,7 +34,6 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/cper.h>
-#include <linux/kdebug.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/ratelimit.h>
@@ -42,6 +42,7 @@
#include <linux/llist.h>
#include <linux/genalloc.h>
#include <linux/pci.h>
+#include <linux/pfn.h>
#include <linux/aer.h>
#include <linux/nmi.h>
#include <linux/sched/clock.h>
@@ -85,6 +86,15 @@
((struct acpi_hest_generic_status *) \
((struct ghes_estatus_node *)(estatus_node) + 1))
+/*
+ * NMI-like notifications vary by architecture, before the compiler can prune
+ * unused static functions it needs a value for these enums.
+ */
+#ifndef CONFIG_ARM_SDE_INTERFACE
+#define FIX_APEI_GHES_SDEI_NORMAL __end_of_fixed_addresses
+#define FIX_APEI_GHES_SDEI_CRITICAL __end_of_fixed_addresses
+#endif
+
static inline bool is_hest_type_generic_v2(struct ghes *ghes)
{
return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2;
@@ -115,11 +125,10 @@ static DEFINE_MUTEX(ghes_list_mutex);
* handler, but general ioremap can not be used in atomic context, so
* the fixmap is used instead.
*
- * These 2 spinlocks are used to prevent the fixmap entries from being used
+ * This spinlock is used to prevent the fixmap entry from being used
* simultaneously.
*/
-static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
-static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
+static DEFINE_SPINLOCK(ghes_notify_lock_irq);
static struct gen_pool *ghes_estatus_pool;
static unsigned long ghes_estatus_pool_size_request;
@@ -129,82 +138,49 @@ static atomic_t ghes_estatus_cache_alloced;
static int ghes_panic_timeout __read_mostly = 30;
-static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
+static void __iomem *ghes_map(u64 pfn, enum fixed_addresses fixmap_idx)
{
phys_addr_t paddr;
pgprot_t prot;
- paddr = pfn << PAGE_SHIFT;
+ paddr = PFN_PHYS(pfn);
prot = arch_apei_get_mem_attribute(paddr);
- __set_fixmap(FIX_APEI_GHES_NMI, paddr, prot);
+ __set_fixmap(fixmap_idx, paddr, prot);
- return (void __iomem *) fix_to_virt(FIX_APEI_GHES_NMI);
+ return (void __iomem *) __fix_to_virt(fixmap_idx);
}
-static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
+static void ghes_unmap(void __iomem *vaddr, enum fixed_addresses fixmap_idx)
{
- phys_addr_t paddr;
- pgprot_t prot;
-
- paddr = pfn << PAGE_SHIFT;
- prot = arch_apei_get_mem_attribute(paddr);
- __set_fixmap(FIX_APEI_GHES_IRQ, paddr, prot);
-
- return (void __iomem *) fix_to_virt(FIX_APEI_GHES_IRQ);
-}
+ int _idx = virt_to_fix((unsigned long)vaddr);
-static void ghes_iounmap_nmi(void)
-{
- clear_fixmap(FIX_APEI_GHES_NMI);
+ WARN_ON_ONCE(fixmap_idx != _idx);
+ clear_fixmap(fixmap_idx);
}
-static void ghes_iounmap_irq(void)
+int ghes_estatus_pool_init(int num_ghes)
{
- clear_fixmap(FIX_APEI_GHES_IRQ);
-}
+ unsigned long addr, len;
-static int ghes_estatus_pool_init(void)
-{
ghes_estatus_pool = gen_pool_create(GHES_ESTATUS_POOL_MIN_ALLOC_ORDER, -1);
if (!ghes_estatus_pool)
return -ENOMEM;
- return 0;
-}
-static void ghes_estatus_pool_free_chunk_page(struct gen_pool *pool,
- struct gen_pool_chunk *chunk,
- void *data)
-{
- free_page(chunk->start_addr);
-}
-
-static void ghes_estatus_pool_exit(void)
-{
- gen_pool_for_each_chunk(ghes_estatus_pool,
- ghes_estatus_pool_free_chunk_page, NULL);
- gen_pool_destroy(ghes_estatus_pool);
-}
+ len = GHES_ESTATUS_CACHE_AVG_SIZE * GHES_ESTATUS_CACHE_ALLOCED_MAX;
+ len += (num_ghes * GHES_ESOURCE_PREALLOC_MAX_SIZE);
-static int ghes_estatus_pool_expand(unsigned long len)
-{
- unsigned long i, pages, size, addr;
- int ret;
+ ghes_estatus_pool_size_request = PAGE_ALIGN(len);
+ addr = (unsigned long)vmalloc(PAGE_ALIGN(len));
+ if (!addr)
+ return -ENOMEM;
- ghes_estatus_pool_size_request += PAGE_ALIGN(len);
- size = gen_pool_size(ghes_estatus_pool);
- if (size >= ghes_estatus_pool_size_request)
- return 0;
- pages = (ghes_estatus_pool_size_request - size) / PAGE_SIZE;
- for (i = 0; i < pages; i++) {
- addr = __get_free_page(GFP_KERNEL);
- if (!addr)
- return -ENOMEM;
- ret = gen_pool_add(ghes_estatus_pool, addr, PAGE_SIZE, -1);
- if (ret)
- return ret;
- }
+ /*
+ * New allocation must be visible in all pgd before it can be found by
+ * an NMI allocating from the pool.
+ */
+ vmalloc_sync_all();
- return 0;
+ return gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1);
}
static int map_gen_v2(struct ghes *ghes)
@@ -217,6 +193,21 @@ static void unmap_gen_v2(struct ghes *ghes)
apei_unmap_generic_address(&ghes->generic_v2->read_ack_register);
}
+static void ghes_ack_error(struct acpi_hest_generic_v2 *gv2)
+{
+ int rc;
+ u64 val = 0;
+
+ rc = apei_read(&val, &gv2->read_ack_register);
+ if (rc)
+ return;
+
+ val &= gv2->read_ack_preserve << gv2->read_ack_register.bit_offset;
+ val |= gv2->read_ack_write << gv2->read_ack_register.bit_offset;
+
+ apei_write(val, &gv2->read_ack_register);
+}
+
static struct ghes *ghes_new(struct acpi_hest_generic *generic)
{
struct ghes *ghes;
@@ -289,23 +280,16 @@ static inline int ghes_severity(int severity)
}
static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
- int from_phys)
+ int from_phys,
+ enum fixed_addresses fixmap_idx)
{
void __iomem *vaddr;
- unsigned long flags = 0;
- int in_nmi = in_nmi();
u64 offset;
u32 trunk;
while (len > 0) {
offset = paddr - (paddr & PAGE_MASK);
- if (in_nmi) {
- raw_spin_lock(&ghes_ioremap_lock_nmi);
- vaddr = ghes_ioremap_pfn_nmi(paddr >> PAGE_SHIFT);
- } else {
- spin_lock_irqsave(&ghes_ioremap_lock_irq, flags);
- vaddr = ghes_ioremap_pfn_irq(paddr >> PAGE_SHIFT);
- }
+ vaddr = ghes_map(PHYS_PFN(paddr), fixmap_idx);
trunk = PAGE_SIZE - offset;
trunk = min(trunk, len);
if (from_phys)
@@ -315,72 +299,114 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
len -= trunk;
paddr += trunk;
buffer += trunk;
- if (in_nmi) {
- ghes_iounmap_nmi();
- raw_spin_unlock(&ghes_ioremap_lock_nmi);
- } else {
- ghes_iounmap_irq();
- spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags);
- }
+ ghes_unmap(vaddr, fixmap_idx);
+ }
+}
+
+/* Check the top-level record header has an appropriate size. */
+static int __ghes_check_estatus(struct ghes *ghes,
+ struct acpi_hest_generic_status *estatus)
+{
+ u32 len = cper_estatus_len(estatus);
+
+ if (len < sizeof(*estatus)) {
+ pr_warn_ratelimited(FW_WARN GHES_PFX "Truncated error status block!\n");
+ return -EIO;
+ }
+
+ if (len > ghes->generic->error_block_length) {
+ pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid error status block length!\n");
+ return -EIO;
+ }
+
+ if (cper_estatus_check_header(estatus)) {
+ pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid CPER header!\n");
+ return -EIO;
}
+
+ return 0;
}
-static int ghes_read_estatus(struct ghes *ghes, int silent)
+/* Read the CPER block, returning its address, and header in estatus. */
+static int __ghes_peek_estatus(struct ghes *ghes,
+ struct acpi_hest_generic_status *estatus,
+ u64 *buf_paddr, enum fixed_addresses fixmap_idx)
{
struct acpi_hest_generic *g = ghes->generic;
- u64 buf_paddr;
- u32 len;
int rc;
- rc = apei_read(&buf_paddr, &g->error_status_address);
+ rc = apei_read(buf_paddr, &g->error_status_address);
if (rc) {
- if (!silent && printk_ratelimit())
- pr_warning(FW_WARN GHES_PFX
+ *buf_paddr = 0;
+ pr_warn_ratelimited(FW_WARN GHES_PFX
"Failed to read error status block address for hardware error source: %d.\n",
g->header.source_id);
return -EIO;
}
- if (!buf_paddr)
+ if (!*buf_paddr)
return -ENOENT;
- ghes_copy_tofrom_phys(ghes->estatus, buf_paddr,
- sizeof(*ghes->estatus), 1);
- if (!ghes->estatus->block_status)
+ ghes_copy_tofrom_phys(estatus, *buf_paddr, sizeof(*estatus), 1,
+ fixmap_idx);
+ if (!estatus->block_status) {
+ *buf_paddr = 0;
return -ENOENT;
+ }
- ghes->buffer_paddr = buf_paddr;
- ghes->flags |= GHES_TO_CLEAR;
+ return __ghes_check_estatus(ghes, estatus);
+}
- rc = -EIO;
- len = cper_estatus_len(ghes->estatus);
- if (len < sizeof(*ghes->estatus))
- goto err_read_block;
- if (len > ghes->generic->error_block_length)
- goto err_read_block;
- if (cper_estatus_check_header(ghes->estatus))
- goto err_read_block;
- ghes_copy_tofrom_phys(ghes->estatus + 1,
- buf_paddr + sizeof(*ghes->estatus),
- len - sizeof(*ghes->estatus), 1);
- if (cper_estatus_check(ghes->estatus))
- goto err_read_block;
- rc = 0;
-
-err_read_block:
- if (rc && !silent && printk_ratelimit())
- pr_warning(FW_WARN GHES_PFX
- "Failed to read error status block!\n");
- return rc;
+static int __ghes_read_estatus(struct acpi_hest_generic_status *estatus,
+ u64 buf_paddr, enum fixed_addresses fixmap_idx,
+ size_t buf_len)
+{
+ ghes_copy_tofrom_phys(estatus, buf_paddr, buf_len, 1, fixmap_idx);
+ if (cper_estatus_check(estatus)) {
+ pr_warn_ratelimited(FW_WARN GHES_PFX
+ "Failed to read error status block!\n");
+ return -EIO;
+ }
+
+ return 0;
}
-static void ghes_clear_estatus(struct ghes *ghes)
+static int ghes_read_estatus(struct ghes *ghes,
+ struct acpi_hest_generic_status *estatus,
+ u64 *buf_paddr, enum fixed_addresses fixmap_idx)
{
- ghes->estatus->block_status = 0;
- if (!(ghes->flags & GHES_TO_CLEAR))
+ int rc;
+
+ rc = __ghes_peek_estatus(ghes, estatus, buf_paddr, fixmap_idx);
+ if (rc)
+ return rc;
+
+ rc = __ghes_check_estatus(ghes, estatus);
+ if (rc)
+ return rc;
+
+ return __ghes_read_estatus(estatus, *buf_paddr, fixmap_idx,
+ cper_estatus_len(estatus));
+}
+
+static void ghes_clear_estatus(struct ghes *ghes,
+ struct acpi_hest_generic_status *estatus,
+ u64 buf_paddr, enum fixed_addresses fixmap_idx)
+{
+ estatus->block_status = 0;
+
+ if (!buf_paddr)
return;
- ghes_copy_tofrom_phys(ghes->estatus, ghes->buffer_paddr,
- sizeof(ghes->estatus->block_status), 0);
- ghes->flags &= ~GHES_TO_CLEAR;
+
+ ghes_copy_tofrom_phys(estatus, buf_paddr,
+ sizeof(estatus->block_status), 0,
+ fixmap_idx);
+
+ /*
+ * GHESv2 type HEST entries introduce support for error acknowledgment,
+ * so only acknowledge the error if this support is present.
+ */
+ if (is_hest_type_generic_v2(ghes))
+ ghes_ack_error(ghes->generic_v2);
}
static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
@@ -672,26 +698,13 @@ static void ghes_estatus_cache_add(
rcu_read_unlock();
}
-static int ghes_ack_error(struct acpi_hest_generic_v2 *gv2)
+static void __ghes_panic(struct ghes *ghes,
+ struct acpi_hest_generic_status *estatus,
+ u64 buf_paddr, enum fixed_addresses fixmap_idx)
{
- int rc;
- u64 val = 0;
+ __ghes_print_estatus(KERN_EMERG, ghes->generic, estatus);
- rc = apei_read(&val, &gv2->read_ack_register);
- if (rc)
- return rc;
-
- val &= gv2->read_ack_preserve << gv2->read_ack_register.bit_offset;
- val |= gv2->read_ack_write << gv2->read_ack_register.bit_offset;
-
- return apei_write(val, &gv2->read_ack_register);
-}
-
-static void __ghes_panic(struct ghes *ghes)
-{
- __ghes_print_estatus(KERN_EMERG, ghes->generic, ghes->estatus);
-
- ghes_clear_estatus(ghes);
+ ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
/* reboot to log the error! */
if (!panic_timeout)
@@ -701,34 +714,25 @@ static void __ghes_panic(struct ghes *ghes)
static int ghes_proc(struct ghes *ghes)
{
+ struct acpi_hest_generic_status *estatus = ghes->estatus;
+ u64 buf_paddr;
int rc;
- rc = ghes_read_estatus(ghes, 0);
+ rc = ghes_read_estatus(ghes, estatus, &buf_paddr, FIX_APEI_GHES_IRQ);
if (rc)
goto out;
- if (ghes_severity(ghes->estatus->error_severity) >= GHES_SEV_PANIC) {
- __ghes_panic(ghes);
- }
+ if (ghes_severity(estatus->error_severity) >= GHES_SEV_PANIC)
+ __ghes_panic(ghes, estatus, buf_paddr, FIX_APEI_GHES_IRQ);
- if (!ghes_estatus_cached(ghes->estatus)) {
- if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus))
- ghes_estatus_cache_add(ghes->generic, ghes->estatus);
+ if (!ghes_estatus_cached(estatus)) {
+ if (ghes_print_estatus(NULL, ghes->generic, estatus))
+ ghes_estatus_cache_add(ghes->generic, estatus);
}
- ghes_do_proc(ghes, ghes->estatus);
+ ghes_do_proc(ghes, estatus);
out:
- ghes_clear_estatus(ghes);
-
- if (rc == -ENOENT)
- return rc;
-
- /*
- * GHESv2 type HEST entries introduce support for error acknowledgment,
- * so only acknowledge the error if this support is present.
- */
- if (is_hest_type_generic_v2(ghes))
- return ghes_ack_error(ghes->generic_v2);
+ ghes_clear_estatus(ghes, estatus, buf_paddr, FIX_APEI_GHES_IRQ);
return rc;
}
@@ -751,8 +755,11 @@ static void ghes_add_timer(struct ghes *ghes)
static void ghes_poll_func(struct timer_list *t)
{
struct ghes *ghes = from_timer(ghes, t, timer);
+ unsigned long flags;
+ spin_lock_irqsave(&ghes_notify_lock_irq, flags);
ghes_proc(ghes);
+ spin_unlock_irqrestore(&ghes_notify_lock_irq, flags);
if (!(ghes->flags & GHES_EXITING))
ghes_add_timer(ghes);
}
@@ -760,9 +767,12 @@ static void ghes_poll_func(struct timer_list *t)
static irqreturn_t ghes_irq_func(int irq, void *data)
{
struct ghes *ghes = data;
+ unsigned long flags;
int rc;
+ spin_lock_irqsave(&ghes_notify_lock_irq, flags);
rc = ghes_proc(ghes);
+ spin_unlock_irqrestore(&ghes_notify_lock_irq, flags);
if (rc)
return IRQ_NONE;
@@ -773,14 +783,17 @@ static int ghes_notify_hed(struct notifier_block *this, unsigned long event,
void *data)
{
struct ghes *ghes;
+ unsigned long flags;
int ret = NOTIFY_DONE;
+ spin_lock_irqsave(&ghes_notify_lock_irq, flags);
rcu_read_lock();
list_for_each_entry_rcu(ghes, &ghes_hed, list) {
if (!ghes_proc(ghes))
ret = NOTIFY_OK;
}
rcu_read_unlock();
+ spin_unlock_irqrestore(&ghes_notify_lock_irq, flags);
return ret;
}
@@ -789,66 +802,20 @@ static struct notifier_block ghes_notifier_hed = {
.notifier_call = ghes_notify_hed,
};
-#ifdef CONFIG_ACPI_APEI_SEA
-static LIST_HEAD(ghes_sea);
-
-/*
- * Return 0 only if one of the SEA error sources successfully reported an error
- * record sent from the firmware.
- */
-int ghes_notify_sea(void)
-{
- struct ghes *ghes;
- int ret = -ENOENT;
-
- rcu_read_lock();
- list_for_each_entry_rcu(ghes, &ghes_sea, list) {
- if (!ghes_proc(ghes))
- ret = 0;
- }
- rcu_read_unlock();
- return ret;
-}
-
-static void ghes_sea_add(struct ghes *ghes)
-{
- mutex_lock(&ghes_list_mutex);
- list_add_rcu(&ghes->list, &ghes_sea);
- mutex_unlock(&ghes_list_mutex);
-}
-
-static void ghes_sea_remove(struct ghes *ghes)
-{
- mutex_lock(&ghes_list_mutex);
- list_del_rcu(&ghes->list);
- mutex_unlock(&ghes_list_mutex);
- synchronize_rcu();
-}
-#else /* CONFIG_ACPI_APEI_SEA */
-static inline void ghes_sea_add(struct ghes *ghes) { }
-static inline void ghes_sea_remove(struct ghes *ghes) { }
-#endif /* CONFIG_ACPI_APEI_SEA */
-
-#ifdef CONFIG_HAVE_ACPI_APEI_NMI
/*
- * printk is not safe in NMI context. So in NMI handler, we allocate
- * required memory from lock-less memory allocator
- * (ghes_estatus_pool), save estatus into it, put them into lock-less
- * list (ghes_estatus_llist), then delay printk into IRQ context via
- * irq_work (ghes_proc_irq_work). ghes_estatus_size_request record
- * required pool size by all NMI error source.
+ * Handlers for CPER records may not be NMI safe. For example,
+ * memory_failure_queue() takes spinlocks and calls schedule_work_on().
+ * In any NMI-like handler, memory from ghes_estatus_pool is used to save
+ * estatus, and added to the ghes_estatus_llist. irq_work_queue() causes
+ * ghes_proc_in_irq() to run in IRQ context where each estatus in
+ * ghes_estatus_llist is processed.
+ *
+ * Memory from the ghes_estatus_pool is also used with the ghes_estatus_cache
+ * to suppress frequent messages.
*/
static struct llist_head ghes_estatus_llist;
static struct irq_work ghes_proc_irq_work;
-/*
- * NMI may be triggered on any CPU, so ghes_in_nmi is used for
- * having only one concurrent reader.
- */
-static atomic_t ghes_in_nmi = ATOMIC_INIT(0);
-
-static LIST_HEAD(ghes_nmi);
-
static void ghes_proc_in_irq(struct irq_work *irq_work)
{
struct llist_node *llnode, *next;
@@ -905,96 +872,154 @@ static void ghes_print_queued_estatus(void)
}
}
-/* Save estatus for further processing in IRQ context */
-static void __process_error(struct ghes *ghes)
+static int ghes_in_nmi_queue_one_entry(struct ghes *ghes,
+ enum fixed_addresses fixmap_idx)
{
-#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
- u32 len, node_len;
+ struct acpi_hest_generic_status *estatus, tmp_header;
struct ghes_estatus_node *estatus_node;
- struct acpi_hest_generic_status *estatus;
+ u32 len, node_len;
+ u64 buf_paddr;
+ int sev, rc;
- if (ghes_estatus_cached(ghes->estatus))
- return;
+ if (!IS_ENABLED(CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG))
+ return -EOPNOTSUPP;
- len = cper_estatus_len(ghes->estatus);
- node_len = GHES_ESTATUS_NODE_LEN(len);
+ rc = __ghes_peek_estatus(ghes, &tmp_header, &buf_paddr, fixmap_idx);
+ if (rc) {
+ ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
+ return rc;
+ }
+ rc = __ghes_check_estatus(ghes, &tmp_header);
+ if (rc) {
+ ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
+ return rc;
+ }
+
+ len = cper_estatus_len(&tmp_header);
+ node_len = GHES_ESTATUS_NODE_LEN(len);
estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool, node_len);
if (!estatus_node)
- return;
+ return -ENOMEM;
estatus_node->ghes = ghes;
estatus_node->generic = ghes->generic;
estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
- memcpy(estatus, ghes->estatus, len);
- llist_add(&estatus_node->llnode, &ghes_estatus_llist);
-#endif
-}
-static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
-{
- struct ghes *ghes;
- int sev, ret = NMI_DONE;
+ if (__ghes_read_estatus(estatus, buf_paddr, fixmap_idx, len)) {
+ ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
+ rc = -ENOENT;
+ goto no_work;
+ }
- if (!atomic_add_unless(&ghes_in_nmi, 1, 1))
- return ret;
+ sev = ghes_severity(estatus->error_severity);
+ if (sev >= GHES_SEV_PANIC) {
+ ghes_print_queued_estatus();
+ __ghes_panic(ghes, estatus, buf_paddr, fixmap_idx);
+ }
- list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
- if (ghes_read_estatus(ghes, 1)) {
- ghes_clear_estatus(ghes);
- continue;
- } else {
- ret = NMI_HANDLED;
- }
+ ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
- sev = ghes_severity(ghes->estatus->error_severity);
- if (sev >= GHES_SEV_PANIC) {
- oops_begin();
- ghes_print_queued_estatus();
- __ghes_panic(ghes);
- }
+ /* This error has been reported before, don't process it again. */
+ if (ghes_estatus_cached(estatus))
+ goto no_work;
- if (!(ghes->flags & GHES_TO_CLEAR))
- continue;
+ llist_add(&estatus_node->llnode, &ghes_estatus_llist);
+
+ return rc;
+
+no_work:
+ gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node,
+ node_len);
+
+ return rc;
+}
- __process_error(ghes);
- ghes_clear_estatus(ghes);
+static int ghes_in_nmi_spool_from_list(struct list_head *rcu_list,
+ enum fixed_addresses fixmap_idx)
+{
+ int ret = -ENOENT;
+ struct ghes *ghes;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ghes, rcu_list, list) {
+ if (!ghes_in_nmi_queue_one_entry(ghes, fixmap_idx))
+ ret = 0;
}
+ rcu_read_unlock();
-#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
- if (ret == NMI_HANDLED)
+ if (IS_ENABLED(CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG) && !ret)
irq_work_queue(&ghes_proc_irq_work);
-#endif
- atomic_dec(&ghes_in_nmi);
+
return ret;
}
-static unsigned long ghes_esource_prealloc_size(
- const struct acpi_hest_generic *generic)
+#ifdef CONFIG_ACPI_APEI_SEA
+static LIST_HEAD(ghes_sea);
+
+/*
+ * Return 0 only if one of the SEA error sources successfully reported an error
+ * record sent from the firmware.
+ */
+int ghes_notify_sea(void)
{
- unsigned long block_length, prealloc_records, prealloc_size;
+ static DEFINE_RAW_SPINLOCK(ghes_notify_lock_sea);
+ int rv;
- block_length = min_t(unsigned long, generic->error_block_length,
- GHES_ESTATUS_MAX_SIZE);
- prealloc_records = max_t(unsigned long,
- generic->records_to_preallocate, 1);
- prealloc_size = min_t(unsigned long, block_length * prealloc_records,
- GHES_ESOURCE_PREALLOC_MAX_SIZE);
+ raw_spin_lock(&ghes_notify_lock_sea);
+ rv = ghes_in_nmi_spool_from_list(&ghes_sea, FIX_APEI_GHES_SEA);
+ raw_spin_unlock(&ghes_notify_lock_sea);
- return prealloc_size;
+ return rv;
}
-static void ghes_estatus_pool_shrink(unsigned long len)
+static void ghes_sea_add(struct ghes *ghes)
{
- ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
+ mutex_lock(&ghes_list_mutex);
+ list_add_rcu(&ghes->list, &ghes_sea);
+ mutex_unlock(&ghes_list_mutex);
}
-static void ghes_nmi_add(struct ghes *ghes)
+static void ghes_sea_remove(struct ghes *ghes)
{
- unsigned long len;
+ mutex_lock(&ghes_list_mutex);
+ list_del_rcu(&ghes->list);
+ mutex_unlock(&ghes_list_mutex);
+ synchronize_rcu();
+}
+#else /* CONFIG_ACPI_APEI_SEA */
+static inline void ghes_sea_add(struct ghes *ghes) { }
+static inline void ghes_sea_remove(struct ghes *ghes) { }
+#endif /* CONFIG_ACPI_APEI_SEA */
+
+#ifdef CONFIG_HAVE_ACPI_APEI_NMI
+/*
+ * NMI may be triggered on any CPU, so ghes_in_nmi is used for
+ * having only one concurrent reader.
+ */
+static atomic_t ghes_in_nmi = ATOMIC_INIT(0);
+
+static LIST_HEAD(ghes_nmi);
+
+static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
+{
+ static DEFINE_RAW_SPINLOCK(ghes_notify_lock_nmi);
+ int ret = NMI_DONE;
+
+ if (!atomic_add_unless(&ghes_in_nmi, 1, 1))
+ return ret;
+
+ raw_spin_lock(&ghes_notify_lock_nmi);
+ if (!ghes_in_nmi_spool_from_list(&ghes_nmi, FIX_APEI_GHES_NMI))
+ ret = NMI_HANDLED;
+ raw_spin_unlock(&ghes_notify_lock_nmi);
- len = ghes_esource_prealloc_size(ghes->generic);
- ghes_estatus_pool_expand(len);
+ atomic_dec(&ghes_in_nmi);
+ return ret;
+}
+
+static void ghes_nmi_add(struct ghes *ghes)
+{
mutex_lock(&ghes_list_mutex);
if (list_empty(&ghes_nmi))
register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, "ghes");
@@ -1004,8 +1029,6 @@ static void ghes_nmi_add(struct ghes *ghes)
static void ghes_nmi_remove(struct ghes *ghes)
{
- unsigned long len;
-
mutex_lock(&ghes_list_mutex);
list_del_rcu(&ghes->list);
if (list_empty(&ghes_nmi))
@@ -1016,24 +1039,79 @@ static void ghes_nmi_remove(struct ghes *ghes)
* freed after NMI handler finishes.
*/
synchronize_rcu();
- len = ghes_esource_prealloc_size(ghes->generic);
- ghes_estatus_pool_shrink(len);
}
+#else /* CONFIG_HAVE_ACPI_APEI_NMI */
+static inline void ghes_nmi_add(struct ghes *ghes) { }
+static inline void ghes_nmi_remove(struct ghes *ghes) { }
+#endif /* CONFIG_HAVE_ACPI_APEI_NMI */
static void ghes_nmi_init_cxt(void)
{
init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
}
-#else /* CONFIG_HAVE_ACPI_APEI_NMI */
-static inline void ghes_nmi_add(struct ghes *ghes) { }
-static inline void ghes_nmi_remove(struct ghes *ghes) { }
-static inline void ghes_nmi_init_cxt(void) { }
-#endif /* CONFIG_HAVE_ACPI_APEI_NMI */
+
+static int __ghes_sdei_callback(struct ghes *ghes,
+ enum fixed_addresses fixmap_idx)
+{
+ if (!ghes_in_nmi_queue_one_entry(ghes, fixmap_idx)) {
+ irq_work_queue(&ghes_proc_irq_work);
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int ghes_sdei_normal_callback(u32 event_num, struct pt_regs *regs,
+ void *arg)
+{
+ static DEFINE_RAW_SPINLOCK(ghes_notify_lock_sdei_normal);
+ struct ghes *ghes = arg;
+ int err;
+
+ raw_spin_lock(&ghes_notify_lock_sdei_normal);
+ err = __ghes_sdei_callback(ghes, FIX_APEI_GHES_SDEI_NORMAL);
+ raw_spin_unlock(&ghes_notify_lock_sdei_normal);
+
+ return err;
+}
+
+static int ghes_sdei_critical_callback(u32 event_num, struct pt_regs *regs,
+ void *arg)
+{
+ static DEFINE_RAW_SPINLOCK(ghes_notify_lock_sdei_critical);
+ struct ghes *ghes = arg;
+ int err;
+
+ raw_spin_lock(&ghes_notify_lock_sdei_critical);
+ err = __ghes_sdei_callback(ghes, FIX_APEI_GHES_SDEI_CRITICAL);
+ raw_spin_unlock(&ghes_notify_lock_sdei_critical);
+
+ return err;
+}
+
+static int apei_sdei_register_ghes(struct ghes *ghes)
+{
+ if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE))
+ return -EOPNOTSUPP;
+
+ return sdei_register_ghes(ghes, ghes_sdei_normal_callback,
+ ghes_sdei_critical_callback);
+}
+
+static int apei_sdei_unregister_ghes(struct ghes *ghes)
+{
+ if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE))
+ return -EOPNOTSUPP;
+
+ return sdei_unregister_ghes(ghes);
+}
static int ghes_probe(struct platform_device *ghes_dev)
{
struct acpi_hest_generic *generic;
struct ghes *ghes = NULL;
+ unsigned long flags;
int rc = -EINVAL;
@@ -1064,6 +1142,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
goto err;
}
break;
+ case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED:
+ if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE)) {
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via SDE Interface is not supported!\n",
+ generic->header.source_id);
+ goto err;
+ }
+ break;
case ACPI_HEST_NOTIFY_LOCAL:
pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
generic->header.source_id);
@@ -1127,6 +1212,11 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_add(ghes);
break;
+ case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED:
+ rc = apei_sdei_register_ghes(ghes);
+ if (rc)
+ goto err;
+ break;
default:
BUG();
}
@@ -1136,7 +1226,9 @@ static int ghes_probe(struct platform_device *ghes_dev)
ghes_edac_register(ghes, &ghes_dev->dev);
/* Handle any pending errors right away */
+ spin_lock_irqsave(&ghes_notify_lock_irq, flags);
ghes_proc(ghes);
+ spin_unlock_irqrestore(&ghes_notify_lock_irq, flags);
return 0;
@@ -1150,6 +1242,7 @@ err:
static int ghes_remove(struct platform_device *ghes_dev)
{
+ int rc;
struct ghes *ghes;
struct acpi_hest_generic *generic;
@@ -1182,6 +1275,11 @@ static int ghes_remove(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_remove(ghes);
break;
+ case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED:
+ rc = apei_sdei_unregister_ghes(ghes);
+ if (rc)
+ return rc;
+ break;
default:
BUG();
break;
@@ -1230,18 +1328,9 @@ static int __init ghes_init(void)
ghes_nmi_init_cxt();
- rc = ghes_estatus_pool_init();
- if (rc)
- goto err;
-
- rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE *
- GHES_ESTATUS_CACHE_ALLOCED_MAX);
- if (rc)
- goto err_pool_exit;
-
rc = platform_driver_register(&ghes_platform_driver);
if (rc)
- goto err_pool_exit;
+ goto err;
rc = apei_osc_setup();
if (rc == 0 && osc_sb_apei_support_acked)
@@ -1254,8 +1343,6 @@ static int __init ghes_init(void)
pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n");
return 0;
-err_pool_exit:
- ghes_estatus_pool_exit();
err:
return rc;
}
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index b1e9f81ebeea..8113ddb14d28 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <acpi/apei.h>
+#include <acpi/ghes.h>
#include "apei-internal.h"
@@ -53,6 +54,7 @@ static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
[ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge),
[ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic),
[ACPI_HEST_TYPE_GENERIC_ERROR_V2] = sizeof(struct acpi_hest_generic_v2),
+ [ACPI_HEST_TYPE_IA32_DEFERRED_CHECK] = -1,
};
static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
@@ -75,6 +77,11 @@ static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
mc = (struct acpi_hest_ia_machine_check *)hest_hdr;
len = sizeof(*mc) + mc->num_hardware_banks *
sizeof(struct acpi_hest_ia_error_bank);
+ } else if (hest_type == ACPI_HEST_TYPE_IA32_DEFERRED_CHECK) {
+ struct acpi_hest_ia_deferred_check *mc;
+ mc = (struct acpi_hest_ia_deferred_check *)hest_hdr;
+ len = sizeof(*mc) + mc->num_hardware_banks *
+ sizeof(struct acpi_hest_ia_error_bank);
}
BUG_ON(len == -1);
@@ -203,6 +210,11 @@ static int __init hest_ghes_dev_register(unsigned int ghes_count)
rc = apei_hest_parse(hest_parse_ghes, &ghes_arr);
if (rc)
goto err;
+
+ rc = ghes_estatus_pool_init(ghes_count);
+ if (rc)
+ goto err;
+
out:
kfree(ghes_arr.ghes_devs);
return rc;
@@ -251,7 +263,9 @@ void __init acpi_hest_init(void)
rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
if (rc)
goto err;
- rc = hest_ghes_dev_register(ghes_count);
+
+ if (ghes_count)
+ rc = hest_ghes_dev_register(ghes_count);
if (rc)
goto err;
}
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index fdd90ffceb85..e48894e002ba 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -876,7 +876,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
return (resv == its->its_count) ? resv : -ENODEV;
}
#else
-static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev);
+static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev)
{ return NULL; }
static inline int iort_add_device_replay(const struct iommu_ops *ops,
struct device *dev)
@@ -952,9 +952,10 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
{
struct acpi_iort_node *node;
struct acpi_iort_root_complex *rc;
+ struct pci_bus *pbus = to_pci_dev(dev)->bus;
node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
- iort_match_node_callback, dev);
+ iort_match_node_callback, &pbus->dev);
if (!node || node->revision < 1)
return -ENODEV;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 99d820a693a8..6ecbbabf1233 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -799,10 +799,24 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
}
EXPORT_SYMBOL_GPL(acpi_match_device);
+static const void *acpi_of_device_get_match_data(const struct device *dev)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ const struct of_device_id *match = NULL;
+
+ if (!acpi_of_match_device(adev, dev->driver->of_match_table, &match))
+ return NULL;
+
+ return match->data;
+}
+
const void *acpi_device_get_match_data(const struct device *dev)
{
const struct acpi_device_id *match;
+ if (!dev->driver->acpi_match_table)
+ return acpi_of_device_get_match_data(dev);
+
match = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!match)
return NULL;
@@ -1029,6 +1043,9 @@ void __init acpi_early_init(void)
acpi_permanent_mmap = true;
+ /* Initialize debug output. Linux does not use ACPICA defaults */
+ acpi_dbg_level = ACPI_LV_INFO | ACPI_LV_REPAIR;
+
#ifdef CONFIG_X86
/*
* If the machine falls into the DMI check table,
@@ -1054,18 +1071,6 @@ void __init acpi_early_init(void)
goto error0;
}
- /*
- * ACPI 2.0 requires the EC driver to be loaded and work before
- * the EC device is found in the namespace (i.e. before
- * acpi_load_tables() is called).
- *
- * This is accomplished by looking for the ECDT table, and getting
- * the EC parameters out of that.
- *
- * Ignore the result. Not having an ECDT is not fatal.
- */
- status = acpi_ec_ecdt_probe();
-
#ifdef CONFIG_X86
if (!acpi_ioapic) {
/* compatible (0) means level (3) */
@@ -1142,6 +1147,18 @@ static int __init acpi_bus_init(void)
goto error1;
}
+ /*
+ * ACPI 2.0 requires the EC driver to be loaded and work before the EC
+ * device is found in the namespace.
+ *
+ * This is accomplished by looking for the ECDT table and getting the EC
+ * parameters out of that.
+ *
+ * Do that before calling acpi_initialize_objects() which may trigger EC
+ * address space accesses.
+ */
+ acpi_ec_ecdt_probe();
+
status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 217a782c3e55..1b207fca1420 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1051,6 +1051,48 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
}
/**
+ * cppc_get_desired_perf - Get the value of desired performance register.
+ * @cpunum: CPU from which to get desired performance.
+ * @desired_perf: address of a variable to store the returned desired performance
+ *
+ * Return: 0 for success, -EIO otherwise.
+ */
+int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
+{
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
+ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
+ struct cpc_register_resource *desired_reg;
+ struct cppc_pcc_data *pcc_ss_data = NULL;
+
+ desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
+
+ if (CPC_IN_PCC(desired_reg)) {
+ int ret = 0;
+
+ if (pcc_ss_id < 0)
+ return -EIO;
+
+ pcc_ss_data = pcc_data[pcc_ss_id];
+
+ down_write(&pcc_ss_data->pcc_lock);
+
+ if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0)
+ cpc_read(cpunum, desired_reg, desired_perf);
+ else
+ ret = -EIO;
+
+ up_write(&pcc_ss_data->pcc_lock);
+
+ return ret;
+ }
+
+ cpc_read(cpunum, desired_reg, desired_perf);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
+
+/**
* cppc_get_perf_caps - Get a CPUs performance capabilities.
* @cpunum: CPU from which to get capabilities info.
* @perf_caps: ptr to cppc_perf_caps. See cppc_acpi.h
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
index 4451877f83b6..aa972dc5cb7e 100644
--- a/drivers/acpi/custom_method.c
+++ b/drivers/acpi/custom_method.c
@@ -79,14 +79,8 @@ static const struct file_operations cm_fops = {
static int __init acpi_custom_method_init(void)
{
- if (acpi_debugfs_dir == NULL)
- return -ENOENT;
-
cm_dentry = debugfs_create_file("custom_method", S_IWUSR,
acpi_debugfs_dir, NULL, &cm_fops);
- if (cm_dentry == NULL)
- return -ENODEV;
-
return 0;
}
diff --git a/drivers/acpi/dptf/Makefile b/drivers/acpi/dptf/Makefile
index 06ea8809583d..e6032e47e83f 100644
--- a/drivers/acpi/dptf/Makefile
+++ b/drivers/acpi/dptf/Makefile
@@ -1,4 +1,2 @@
obj-$(CONFIG_ACPI) += int340x_thermal.o
obj-$(CONFIG_DPTF_POWER) += dptf_power.o
-
-ccflags-y += -Idrivers/acpi
diff --git a/drivers/acpi/dptf/int340x_thermal.c b/drivers/acpi/dptf/int340x_thermal.c
index 86364097e236..0aa7c2e62e95 100644
--- a/drivers/acpi/dptf/int340x_thermal.c
+++ b/drivers/acpi/dptf/int340x_thermal.c
@@ -12,7 +12,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
-#include "internal.h"
+#include "../internal.h"
#define INT3401_DEVICE 0X01
static const struct acpi_device_id int340x_thermal_device_ids[] = {
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 9d66a47d32fb..48d4815603e5 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -186,14 +186,17 @@ static void advance_transaction(struct acpi_ec *ec);
static void acpi_ec_event_handler(struct work_struct *work);
static void acpi_ec_event_processor(struct work_struct *work);
-struct acpi_ec *boot_ec, *first_ec;
+struct acpi_ec *first_ec;
EXPORT_SYMBOL(first_ec);
+
+static struct acpi_ec *boot_ec;
static bool boot_ec_is_ecdt = false;
static struct workqueue_struct *ec_query_wq;
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
+static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
/* --------------------------------------------------------------------------
* Logging/Debugging
@@ -499,6 +502,26 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
ec_log_drv("event blocked");
}
+/*
+ * Process _Q events that might have accumulated in the EC.
+ * Run with locked ec mutex.
+ */
+static void acpi_ec_clear(struct acpi_ec *ec)
+{
+ int i, status;
+ u8 value = 0;
+
+ for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
+ status = acpi_ec_query(ec, &value);
+ if (status || !value)
+ break;
+ }
+ if (unlikely(i == ACPI_EC_CLEAR_MAX))
+ pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
+ else
+ pr_info("%d stale EC events cleared\n", i);
+}
+
static void acpi_ec_enable_event(struct acpi_ec *ec)
{
unsigned long flags;
@@ -507,6 +530,10 @@ static void acpi_ec_enable_event(struct acpi_ec *ec)
if (acpi_ec_started(ec))
__acpi_ec_enable_event(ec);
spin_unlock_irqrestore(&ec->lock, flags);
+
+ /* Drain additional events if hardware requires that */
+ if (EC_FLAGS_CLEAR_ON_RESUME)
+ acpi_ec_clear(ec);
}
#ifdef CONFIG_PM_SLEEP
@@ -1539,49 +1566,6 @@ static int acpi_ec_setup(struct acpi_ec *ec, bool handle_events)
return ret;
}
-static int acpi_config_boot_ec(struct acpi_ec *ec, acpi_handle handle,
- bool handle_events, bool is_ecdt)
-{
- int ret;
-
- /*
- * Changing the ACPI handle results in a re-configuration of the
- * boot EC. And if it happens after the namespace initialization,
- * it causes _REG evaluations.
- */
- if (boot_ec && boot_ec->handle != handle)
- ec_remove_handlers(boot_ec);
-
- /* Unset old boot EC */
- if (boot_ec != ec)
- acpi_ec_free(boot_ec);
-
- /*
- * ECDT device creation is split into acpi_ec_ecdt_probe() and
- * acpi_ec_ecdt_start(). This function takes care of completing the
- * ECDT parsing logic as the handle update should be performed
- * between the installation/uninstallation of the handlers.
- */
- if (ec->handle != handle)
- ec->handle = handle;
-
- ret = acpi_ec_setup(ec, handle_events);
- if (ret)
- return ret;
-
- /* Set new boot EC */
- if (!boot_ec) {
- boot_ec = ec;
- boot_ec_is_ecdt = is_ecdt;
- }
-
- acpi_handle_info(boot_ec->handle,
- "Used as boot %s EC to handle transactions%s\n",
- is_ecdt ? "ECDT" : "DSDT",
- handle_events ? " and events" : "");
- return ret;
-}
-
static bool acpi_ec_ecdt_get_handle(acpi_handle *phandle)
{
struct acpi_table_ecdt *ecdt_ptr;
@@ -1601,43 +1585,34 @@ static bool acpi_ec_ecdt_get_handle(acpi_handle *phandle)
return true;
}
-static bool acpi_is_boot_ec(struct acpi_ec *ec)
-{
- if (!boot_ec)
- return false;
- if (ec->command_addr == boot_ec->command_addr &&
- ec->data_addr == boot_ec->data_addr)
- return true;
- return false;
-}
-
static int acpi_ec_add(struct acpi_device *device)
{
struct acpi_ec *ec = NULL;
- int ret;
- bool is_ecdt = false;
+ bool dep_update = true;
acpi_status status;
+ int ret;
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
if (!strcmp(acpi_device_hid(device), ACPI_ECDT_HID)) {
- is_ecdt = true;
+ boot_ec_is_ecdt = true;
ec = boot_ec;
+ dep_update = false;
} else {
ec = acpi_ec_alloc();
if (!ec)
return -ENOMEM;
+
status = ec_parse_device(device->handle, 0, ec, NULL);
if (status != AE_CTRL_TERMINATE) {
ret = -EINVAL;
goto err_alloc;
}
- }
- if (acpi_is_boot_ec(ec)) {
- boot_ec_is_ecdt = is_ecdt;
- if (!is_ecdt) {
+ if (boot_ec && ec->command_addr == boot_ec->command_addr &&
+ ec->data_addr == boot_ec->data_addr) {
+ boot_ec_is_ecdt = false;
/*
* Trust PNP0C09 namespace location rather than
* ECDT ID. But trust ECDT GPE rather than _GPE
@@ -1649,12 +1624,17 @@ static int acpi_ec_add(struct acpi_device *device)
acpi_ec_free(ec);
ec = boot_ec;
}
- ret = acpi_config_boot_ec(ec, ec->handle, true, is_ecdt);
- } else
- ret = acpi_ec_setup(ec, true);
+ }
+
+ ret = acpi_ec_setup(ec, true);
if (ret)
goto err_query;
+ if (ec == boot_ec)
+ acpi_handle_info(boot_ec->handle,
+ "Boot %s EC used to handle transactions and events\n",
+ boot_ec_is_ecdt ? "ECDT" : "DSDT");
+
device->driver_data = ec;
ret = !!request_region(ec->data_addr, 1, "EC data");
@@ -1662,7 +1642,7 @@ static int acpi_ec_add(struct acpi_device *device)
ret = !!request_region(ec->command_addr, 1, "EC cmd");
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
- if (!is_ecdt) {
+ if (dep_update) {
/* Reprobe devices depending on the EC */
acpi_walk_dep_device_list(ec->handle);
}
@@ -1730,10 +1710,10 @@ static const struct acpi_device_id ec_device_ids[] = {
* namespace EC before the main ACPI device enumeration process. It is
* retained for historical reason and will be deprecated in the future.
*/
-int __init acpi_ec_dsdt_probe(void)
+void __init acpi_ec_dsdt_probe(void)
{
- acpi_status status;
struct acpi_ec *ec;
+ acpi_status status;
int ret;
/*
@@ -1743,21 +1723,22 @@ int __init acpi_ec_dsdt_probe(void)
* picking up an invalid EC device.
*/
if (boot_ec)
- return -ENODEV;
+ return;
ec = acpi_ec_alloc();
if (!ec)
- return -ENOMEM;
+ return;
+
/*
* At this point, the namespace is initialized, so start to find
* the namespace objects.
*/
- status = acpi_get_devices(ec_device_ids[0].id,
- ec_parse_device, ec, NULL);
+ status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, ec, NULL);
if (ACPI_FAILURE(status) || !ec->handle) {
- ret = -ENODEV;
- goto error;
+ acpi_ec_free(ec);
+ return;
}
+
/*
* When the DSDT EC is available, always re-configure boot EC to
* have _REG evaluated. _REG can only be evaluated after the
@@ -1765,11 +1746,16 @@ int __init acpi_ec_dsdt_probe(void)
* At this point, the GPE is not fully initialized, so do not to
* handle the events.
*/
- ret = acpi_config_boot_ec(ec, ec->handle, false, false);
-error:
- if (ret)
+ ret = acpi_ec_setup(ec, false);
+ if (ret) {
acpi_ec_free(ec);
- return ret;
+ return;
+ }
+
+ boot_ec = ec;
+
+ acpi_handle_info(ec->handle,
+ "Boot DSDT EC used to handle transactions\n");
}
/*
@@ -1821,6 +1807,31 @@ static int ec_flag_query_handshake(const struct dmi_system_id *id)
#endif
/*
+ * On some hardware it is necessary to clear events accumulated by the EC during
+ * sleep. These ECs stop reporting GPEs until they are manually polled, if too
+ * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=44161
+ *
+ * Ideally, the EC should also be instructed NOT to accumulate events during
+ * sleep (which Windows seems to do somehow), but the interface to control this
+ * behaviour is not known at this time.
+ *
+ * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
+ * however it is very likely that other Samsung models are affected.
+ *
+ * On systems which don't accumulate _Q events during sleep, this extra check
+ * should be harmless.
+ */
+static int ec_clear_on_resume(const struct dmi_system_id *id)
+{
+ pr_debug("Detected system needing EC poll on resume.\n");
+ EC_FLAGS_CLEAR_ON_RESUME = 1;
+ ec_event_clearing = ACPI_EC_EVT_TIMING_STATUS;
+ return 0;
+}
+
+/*
* Some ECDTs contain wrong register addresses.
* MSI MS-171F
* https://bugzilla.kernel.org/show_bug.cgi?id=12461
@@ -1869,39 +1880,38 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
ec_honor_ecdt_gpe, "ASUS X580VD", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
+ {
+ ec_clear_on_resume, "Samsung hardware", {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{},
};
-int __init acpi_ec_ecdt_probe(void)
+void __init acpi_ec_ecdt_probe(void)
{
- int ret;
- acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
struct acpi_ec *ec;
+ acpi_status status;
+ int ret;
- ec = acpi_ec_alloc();
- if (!ec)
- return -ENOMEM;
- /*
- * Generate a boot ec context
- */
+ /* Generate a boot ec context. */
dmi_check_system(ec_dmi_table);
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
- if (ACPI_FAILURE(status)) {
- ret = -ENODEV;
- goto error;
- }
+ if (ACPI_FAILURE(status))
+ return;
if (!ecdt_ptr->control.address || !ecdt_ptr->data.address) {
/*
* Asus X50GL:
* https://bugzilla.kernel.org/show_bug.cgi?id=11880
*/
- ret = -ENODEV;
- goto error;
+ return;
}
+ ec = acpi_ec_alloc();
+ if (!ec)
+ return;
+
if (EC_FLAGS_CORRECT_ECDT) {
ec->command_addr = ecdt_ptr->data.address;
ec->data_addr = ecdt_ptr->control.address;
@@ -1910,16 +1920,22 @@ int __init acpi_ec_ecdt_probe(void)
ec->data_addr = ecdt_ptr->data.address;
}
ec->gpe = ecdt_ptr->gpe;
+ ec->handle = ACPI_ROOT_OBJECT;
/*
* At this point, the namespace is not initialized, so do not find
* the namespace objects, or handle the events.
*/
- ret = acpi_config_boot_ec(ec, ACPI_ROOT_OBJECT, false, true);
-error:
- if (ret)
+ ret = acpi_ec_setup(ec, false);
+ if (ret) {
acpi_ec_free(ec);
- return ret;
+ return;
+ }
+
+ boot_ec = ec;
+ boot_ec_is_ecdt = true;
+
+ pr_info("Boot ECDT EC used to handle transactions\n");
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index dd70d6c2bca0..23faa66ea772 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -108,52 +108,32 @@ static const struct file_operations acpi_ec_io_ops = {
.llseek = default_llseek,
};
-static int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
+static void acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
{
struct dentry *dev_dir;
char name[64];
umode_t mode = 0400;
- if (ec_device_count == 0) {
+ if (ec_device_count == 0)
acpi_ec_debugfs_dir = debugfs_create_dir("ec", NULL);
- if (!acpi_ec_debugfs_dir)
- return -ENOMEM;
- }
sprintf(name, "ec%u", ec_device_count);
dev_dir = debugfs_create_dir(name, acpi_ec_debugfs_dir);
- if (!dev_dir) {
- if (ec_device_count != 0)
- goto error;
- return -ENOMEM;
- }
- if (!debugfs_create_x32("gpe", 0444, dev_dir, &first_ec->gpe))
- goto error;
- if (!debugfs_create_bool("use_global_lock", 0444, dev_dir,
- &first_ec->global_lock))
- goto error;
+ debugfs_create_x32("gpe", 0444, dev_dir, &first_ec->gpe);
+ debugfs_create_bool("use_global_lock", 0444, dev_dir,
+ &first_ec->global_lock);
if (write_support)
mode = 0600;
- if (!debugfs_create_file("io", mode, dev_dir, ec, &acpi_ec_io_ops))
- goto error;
-
- return 0;
-
-error:
- debugfs_remove_recursive(acpi_ec_debugfs_dir);
- return -ENOMEM;
+ debugfs_create_file("io", mode, dev_dir, ec, &acpi_ec_io_ops);
}
static int __init acpi_ec_sys_init(void)
{
- int err = 0;
if (first_ec)
- err = acpi_ec_add_debugfs(first_ec, 0);
- else
- err = -ENODEV;
- return err;
+ acpi_ec_add_debugfs(first_ec, 0);
+ return 0;
}
static void __exit acpi_ec_sys_exit(void)
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 7e6952edb5b0..6eaf06db7752 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -81,7 +81,11 @@ void acpi_debugfs_init(void);
#else
static inline void acpi_debugfs_init(void) { return; }
#endif
+#ifdef CONFIG_PCI
void acpi_lpss_init(void);
+#else
+static inline void acpi_lpss_init(void) {}
+#endif
void acpi_apd_init(void);
@@ -188,8 +192,8 @@ extern struct acpi_ec *first_ec;
typedef int (*acpi_ec_query_func) (void *data);
int acpi_ec_init(void);
-int acpi_ec_ecdt_probe(void);
-int acpi_ec_dsdt_probe(void);
+void acpi_ec_ecdt_probe(void);
+void acpi_ec_dsdt_probe(void);
void acpi_ec_block_transactions(void);
void acpi_ec_unblock_transactions(void);
void acpi_ec_mark_gpe_for_wake(void);
diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 7c352cba0528..c3b2222e2129 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -196,7 +196,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares,
fwnode = acpi_gsi_domain_id;
acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index],
irq->triggering, irq->polarity,
- irq->sharable, ctx);
+ irq->shareable, ctx);
return AE_CTRL_TERMINATE;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
eirq = &ares->data.extended_irq;
@@ -209,7 +209,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares,
fwnode = acpi_get_irq_source_fwhandle(&eirq->resource_source);
acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index],
eirq->triggering, eirq->polarity,
- eirq->sharable, ctx);
+ eirq->shareable, ctx);
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 011d3db19c80..e18ade5d74e9 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -26,7 +26,6 @@
#include <acpi/nfit.h>
#include "intel.h"
#include "nfit.h"
-#include "intel.h"
/*
* For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
@@ -78,12 +77,6 @@ const guid_t *to_nfit_uuid(enum nfit_uuids id)
}
EXPORT_SYMBOL(to_nfit_uuid);
-static struct acpi_nfit_desc *to_acpi_nfit_desc(
- struct nvdimm_bus_descriptor *nd_desc)
-{
- return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
{
struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
@@ -416,10 +409,36 @@ static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func)
return true;
}
+static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
+ struct nd_cmd_pkg *call_pkg)
+{
+ if (call_pkg) {
+ int i;
+
+ if (nfit_mem->family != call_pkg->nd_family)
+ return -ENOTTY;
+
+ for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
+ if (call_pkg->nd_reserved2[i])
+ return -EINVAL;
+ return call_pkg->nd_command;
+ }
+
+ /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
+ if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+ return cmd;
+
+ /*
+ * Force function number validation to fail since 0 is never
+ * published as a valid function in dsm_mask.
+ */
+ return 0;
+}
+
int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+ struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
union acpi_object in_obj, in_buf, *out_obj;
const struct nd_cmd_desc *desc = NULL;
@@ -429,30 +448,23 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
unsigned long cmd_mask, dsm_mask;
u32 offset, fw_status = 0;
acpi_handle handle;
- unsigned int func;
const guid_t *guid;
- int rc, i;
+ int func, rc, i;
if (cmd_rc)
*cmd_rc = -EINVAL;
- func = cmd;
- if (cmd == ND_CMD_CALL) {
- call_pkg = buf;
- func = call_pkg->nd_command;
-
- for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
- if (call_pkg->nd_reserved2[i])
- return -EINVAL;
- }
if (nvdimm) {
struct acpi_device *adev = nfit_mem->adev;
if (!adev)
return -ENOTTY;
- if (call_pkg && nfit_mem->family != call_pkg->nd_family)
- return -ENOTTY;
+ if (cmd == ND_CMD_CALL)
+ call_pkg = buf;
+ func = cmd_to_func(nfit_mem, cmd, call_pkg);
+ if (func < 0)
+ return func;
dimm_name = nvdimm_name(nvdimm);
cmd_name = nvdimm_cmd_name(cmd);
cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -463,6 +475,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
} else {
struct acpi_device *adev = to_acpi_dev(acpi_desc);
+ func = cmd;
cmd_name = nvdimm_bus_cmd_name(cmd);
cmd_mask = nd_desc->cmd_mask;
dsm_mask = cmd_mask;
@@ -477,7 +490,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
return -ENOTTY;
- if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
+ /*
+ * Check for a valid command. For ND_CMD_CALL, we also have to
+ * make sure that the DSM function is supported.
+ */
+ if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+ return -ENOTTY;
+ else if (!test_bit(cmd, &cmd_mask))
return -ENOTTY;
in_obj.type = ACPI_TYPE_PACKAGE;
@@ -721,6 +740,7 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
struct acpi_nfit_memory_map *memdev;
struct acpi_nfit_desc *acpi_desc;
struct nfit_mem *nfit_mem;
+ u16 physical_id;
mutex_lock(&acpi_desc_lock);
list_for_each_entry(acpi_desc, &acpi_descs, list) {
@@ -728,10 +748,11 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
memdev = __to_nfit_memdev(nfit_mem);
if (memdev->device_handle == device_handle) {
+ *flags = memdev->flags;
+ physical_id = memdev->physical_id;
mutex_unlock(&acpi_desc->init_mutex);
mutex_unlock(&acpi_desc_lock);
- *flags = memdev->flags;
- return memdev->physical_id;
+ return physical_id;
}
}
mutex_unlock(&acpi_desc->init_mutex);
@@ -1872,6 +1893,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
return 0;
}
+ /*
+ * Function 0 is the command interrogation function, don't
+ * export it to potential userspace use, and enable it to be
+ * used as an error value in acpi_nfit_ctl().
+ */
+ dsm_mask &= ~1UL;
+
guid = to_nfit_uuid(nfit_mem->family);
for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
if (acpi_check_dsm(adev_dimm->handle, guid,
@@ -2047,11 +2075,6 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
if (!nvdimm)
continue;
- rc = nvdimm_security_setup_events(nvdimm);
- if (rc < 0)
- dev_warn(acpi_desc->dev,
- "security event setup failed: %d\n", rc);
-
nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
if (nfit_kernfs)
nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
@@ -2231,7 +2254,6 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
if (!nd_set)
return -ENOMEM;
- ndr_desc->nd_set = nd_set;
guid_copy(&nd_set->type_guid, (guid_t *) spa->range_guid);
info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL);
@@ -3367,7 +3389,7 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+ struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
struct device *dev = acpi_desc->dev;
/* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
@@ -3384,7 +3406,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd)
{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+ struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
if (nvdimm)
return 0;
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index 850b2927b4e7..f70de71f79d6 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -146,7 +146,7 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
static void nvdimm_invalidate_cache(void);
-static int intel_security_unlock(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
const struct nvdimm_key_data *key_data)
{
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -227,7 +227,7 @@ static int intel_security_disable(struct nvdimm *nvdimm,
return 0;
}
-static int intel_security_erase(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
const struct nvdimm_key_data *key,
enum nvdimm_passphrase_type ptype)
{
@@ -276,7 +276,7 @@ static int intel_security_erase(struct nvdimm *nvdimm,
return 0;
}
-static int intel_security_query_overwrite(struct nvdimm *nvdimm)
+static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
{
int rc;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -313,7 +313,7 @@ static int intel_security_query_overwrite(struct nvdimm *nvdimm)
return 0;
}
-static int intel_security_overwrite(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
const struct nvdimm_key_data *nkey)
{
int rc;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 274699463b4f..7bbbf8256a41 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -146,9 +146,9 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
{
struct acpi_srat_mem_affinity *p =
(struct acpi_srat_mem_affinity *)header;
- pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
- (unsigned long)p->base_address,
- (unsigned long)p->length,
+ pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
+ (unsigned long long)p->base_address,
+ (unsigned long long)p->length,
p->proximity_domain,
(p->flags & ACPI_SRAT_MEM_ENABLED) ?
"enabled" : "disabled",
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index d5eec352a6e1..df70b1eaef58 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -317,10 +317,10 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
resource->res.data.irq.polarity =
link->irq.polarity;
if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.sharable =
+ resource->res.data.irq.shareable =
ACPI_EXCLUSIVE;
else
- resource->res.data.irq.sharable = ACPI_SHARED;
+ resource->res.data.irq.shareable = ACPI_SHARED;
resource->res.data.irq.interrupt_count = 1;
resource->res.data.irq.interrupts[0] = irq;
break;
@@ -335,10 +335,10 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
resource->res.data.extended_irq.polarity =
link->irq.polarity;
if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.sharable =
+ resource->res.data.irq.shareable =
ACPI_EXCLUSIVE;
else
- resource->res.data.irq.sharable = ACPI_SHARED;
+ resource->res.data.irq.shareable = ACPI_SHARED;
resource->res.data.extended_irq.interrupt_count = 1;
resource->res.data.extended_irq.interrupts[0] = irq;
/* ignore resource_source, it's optional */
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
index 2579675b7082..e7c0006e6602 100644
--- a/drivers/acpi/pmic/intel_pmic_xpower.c
+++ b/drivers/acpi/pmic/intel_pmic_xpower.c
@@ -20,8 +20,11 @@
#define GPI1_LDO_ON (3 << 0)
#define GPI1_LDO_OFF (4 << 0)
-#define AXP288_ADC_TS_PIN_GPADC 0xf2
-#define AXP288_ADC_TS_PIN_ON 0xf3
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON (3 << 0)
static struct pmic_table power_table[] = {
{
@@ -212,22 +215,44 @@ out:
*/
static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg)
{
+ int ret, adc_ts_pin_ctrl;
u8 buf[2];
- int ret;
- ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL,
- AXP288_ADC_TS_PIN_GPADC);
+ /*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ *
+ * Note that the switching from on to on-ondemand is not necessary
+ * when the TS current-source is off (this happens on devices which
+ * do not use the TS-pin).
+ */
+ ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl);
if (ret)
return ret;
- /* After switching to the GPADC pin give things some time to settle */
- usleep_range(6000, 10000);
+ if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+ ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+ AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+ AXP288_ADC_TS_CURRENT_ON_ONDEMAND);
+ if (ret)
+ return ret;
+
+ /* Wait a bit after switching the current-source */
+ usleep_range(6000, 10000);
+ }
ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2);
if (ret == 0)
ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f);
- regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON);
+ if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+ regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+ AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+ AXP288_ADC_TS_CURRENT_ON);
+ }
return ret;
}
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 1b475bc1ae16..665e93ca0b40 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
}
}
+static bool acpi_power_resource_is_dup(union acpi_object *package,
+ unsigned int start, unsigned int i)
+{
+ acpi_handle rhandle, dup;
+ unsigned int j;
+
+ /* The caller is expected to check the package element types */
+ rhandle = package->package.elements[i].reference.handle;
+ for (j = start; j < i; j++) {
+ dup = package->package.elements[j].reference.handle;
+ if (dup == rhandle)
+ return true;
+ }
+
+ return false;
+}
+
int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
struct list_head *list)
{
@@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
err = -ENODEV;
break;
}
+
+ /* Some ACPI tables contain duplicate power resource references */
+ if (acpi_power_resource_is_dup(package, start, i))
+ continue;
+
err = acpi_add_power_resource(rhandle);
if (err)
break;
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index da031b1df6f5..ad31c50de3be 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -451,6 +451,11 @@ static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_ta
return cpu;
}
+static void acpi_pptt_warn_missing(void)
+{
+ pr_warn_once("No PPTT table found, cpu and cache topology may be inaccurate\n");
+}
+
/**
* topology_get_acpi_cpu_tag() - Find a unique topology value for a feature
* @table: Pointer to the head of the PPTT table
@@ -498,7 +503,7 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag)
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
if (ACPI_FAILURE(status)) {
- pr_warn_once("No PPTT table found, cpu topology may be inaccurate\n");
+ acpi_pptt_warn_missing();
return -ENOENT;
}
retval = topology_get_acpi_cpu_tag(table, cpu, level, flag);
@@ -531,7 +536,7 @@ int acpi_find_last_cache_level(unsigned int cpu)
acpi_cpu_id = get_acpi_id_for_cpu(cpu);
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
if (ACPI_FAILURE(status)) {
- pr_warn_once("No PPTT table found, cache topology may be inaccurate\n");
+ acpi_pptt_warn_missing();
} else {
number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id);
acpi_put_table(table);
@@ -563,7 +568,7 @@ int cache_setup_acpi(unsigned int cpu)
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
if (ACPI_FAILURE(status)) {
- pr_warn_once("No PPTT table found, cache topology may be inaccurate\n");
+ acpi_pptt_warn_missing();
return -ENOENT;
}
@@ -617,7 +622,7 @@ int find_acpi_cpu_cache_topology(unsigned int cpu, int level)
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
if (ACPI_FAILURE(status)) {
- pr_warn_once("No PPTT table found, topology may be inaccurate\n");
+ acpi_pptt_warn_missing();
return -ENOENT;
}
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index b2131c4ea124..98d4ec5bf450 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -282,6 +282,13 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
pr->power.states[ACPI_STATE_C2].address,
pr->power.states[ACPI_STATE_C3].address));
+ snprintf(pr->power.states[ACPI_STATE_C2].desc,
+ ACPI_CX_DESC_LEN, "ACPI P_LVL2 IOPORT 0x%x",
+ pr->power.states[ACPI_STATE_C2].address);
+ snprintf(pr->power.states[ACPI_STATE_C3].desc,
+ ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x",
+ pr->power.states[ACPI_STATE_C3].address);
+
return 0;
}
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 316a0fc785e3..d556f2144de8 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -476,7 +476,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
}
acpi_dev_get_irqresource(res, irq->interrupts[index],
irq->triggering, irq->polarity,
- irq->sharable, true);
+ irq->shareable, true);
break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
ext_irq = &ares->data.extended_irq;
@@ -487,7 +487,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
if (is_gsi(ext_irq))
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
ext_irq->triggering, ext_irq->polarity,
- ext_irq->sharable, false);
+ ext_irq->shareable, false);
else
acpi_dev_irqresource_disabled(res, 0);
break;
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 48eabb6c2d4f..8fccbe49612a 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -473,14 +473,22 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
void __init acpi_table_upgrade(void)
{
- void *data = (void *)initrd_start;
- size_t size = initrd_end - initrd_start;
+ void *data;
+ size_t size;
int sig, no, table_nr = 0, total_offset = 0;
long offset = 0;
struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file;
+ if (IS_ENABLED(CONFIG_ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD)) {
+ data = __initramfs_start;
+ size = __initramfs_size;
+ } else {
+ data = (void *)initrd_start;
+ size = initrd_end - initrd_start;
+ }
+
if (data == NULL || size == 0)
return;
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 9a8e286dd86f..c6df14802741 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -56,6 +56,11 @@ static const struct always_present_id always_present_ids[] = {
*/
ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT), {}),
ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
+
+ /* Lenovo Yoga Book uses PWM2 for keyboard backlight control */
+ ENTRY("80862289", "2", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
+ }),
/*
* The INT0002 device is necessary to clear wakeup interrupt sources
* on Cherry Trail devices, without it we get nobody cared IRQ msgs.
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 4c190f8d1f4c..6fdf2abe4598 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -10,7 +10,7 @@ if ANDROID
config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
- depends on MMU && !CPU_CACHE_VIVT
+ depends on MMU
default n
---help---
Binder is used in Android for both communication between processes,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index cdfc87629efb..8685882da64c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -329,6 +329,8 @@ struct binder_error {
* (invariant after initialized)
* @min_priority: minimum scheduling priority
* (invariant after initialized)
+ * @txn_security_ctx: require sender's security context
+ * (invariant after initialized)
* @async_todo: list of async work items
* (protected by @proc->inner_lock)
*
@@ -365,6 +367,7 @@ struct binder_node {
* invariant after initialization
*/
u8 accept_fds:1;
+ u8 txn_security_ctx:1;
u8 min_priority;
};
bool has_async_transaction;
@@ -615,6 +618,7 @@ struct binder_transaction {
long saved_priority;
kuid_t sender_euid;
struct list_head fd_fixups;
+ binder_uintptr_t security_ctx;
/**
* @lock: protects @from, @to_proc, and @to_thread
*
@@ -625,6 +629,26 @@ struct binder_transaction {
};
/**
+ * struct binder_object - union of flat binder object types
+ * @hdr: generic object header
+ * @fbo: binder object (nodes and refs)
+ * @fdo: file descriptor object
+ * @bbo: binder buffer pointer
+ * @fdao: file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+ union {
+ struct binder_object_header hdr;
+ struct flat_binder_object fbo;
+ struct binder_fd_object fdo;
+ struct binder_buffer_object bbo;
+ struct binder_fd_array_object fdao;
+ };
+};
+
+/**
* binder_proc_lock() - Acquire outer lock for given binder_proc
* @proc: struct binder_proc to acquire
*
@@ -1152,6 +1176,7 @@ static struct binder_node *binder_init_node_ilocked(
node->work.type = BINDER_WORK_NODE;
node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+ node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX);
spin_lock_init(&node->lock);
INIT_LIST_HEAD(&node->work.entry);
INIT_LIST_HEAD(&node->async_todo);
@@ -2012,26 +2037,33 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
}
/**
- * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * binder_get_object() - gets object and checks for valid metadata
+ * @proc: binder_proc owning the buffer
* @buffer: binder_buffer that we're parsing.
- * @offset: offset in the buffer at which to validate an object.
+ * @offset: offset in the @buffer at which to validate an object.
+ * @object: struct binder_object to read into
*
* Return: If there's a valid metadata object at @offset in @buffer, the
- * size of that object. Otherwise, it returns zero.
+ * size of that object. Otherwise, it returns zero. The object
+ * is read into the struct binder_object pointed to by @object.
*/
-static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+static size_t binder_get_object(struct binder_proc *proc,
+ struct binder_buffer *buffer,
+ unsigned long offset,
+ struct binder_object *object)
{
- /* Check if we can read a header first */
+ size_t read_size;
struct binder_object_header *hdr;
size_t object_size = 0;
- if (buffer->data_size < sizeof(*hdr) ||
- offset > buffer->data_size - sizeof(*hdr) ||
- !IS_ALIGNED(offset, sizeof(u32)))
+ read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
+ if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
return 0;
+ binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size);
- /* Ok, now see if we can read a complete object. */
- hdr = (struct binder_object_header *)(buffer->data + offset);
+ /* Ok, now see if we read a complete object. */
+ hdr = &object->hdr;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER:
@@ -2060,10 +2092,13 @@ static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
/**
* binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @proc: binder_proc owning the buffer
* @b: binder_buffer containing the object
+ * @object: struct binder_object to read into
* @index: index in offset array at which the binder_buffer_object is
* located
- * @start: points to the start of the offset array
+ * @start_offset: points to the start of the offset array
+ * @object_offsetp: offset of @object read from @b
* @num_valid: the number of valid offsets in the offset array
*
* Return: If @index is within the valid range of the offset array
@@ -2074,34 +2109,46 @@ static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
* Note that the offset found in index @index itself is not
* verified; this function assumes that @num_valid elements
* from @start were previously verified to have valid offsets.
+ * If @object_offsetp is non-NULL, then the offset within
+ * @b is written to it.
*/
-static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b,
- binder_size_t index,
- binder_size_t *start,
- binder_size_t num_valid)
+static struct binder_buffer_object *binder_validate_ptr(
+ struct binder_proc *proc,
+ struct binder_buffer *b,
+ struct binder_object *object,
+ binder_size_t index,
+ binder_size_t start_offset,
+ binder_size_t *object_offsetp,
+ binder_size_t num_valid)
{
- struct binder_buffer_object *buffer_obj;
- binder_size_t *offp;
+ size_t object_size;
+ binder_size_t object_offset;
+ unsigned long buffer_offset;
if (index >= num_valid)
return NULL;
- offp = start + index;
- buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
- if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+ buffer_offset = start_offset + sizeof(binder_size_t) * index;
+ binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ b, buffer_offset, sizeof(object_offset));
+ object_size = binder_get_object(proc, b, object_offset, object);
+ if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
+ if (object_offsetp)
+ *object_offsetp = object_offset;
- return buffer_obj;
+ return &object->bbo;
}
/**
* binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @proc: binder_proc owning the buffer
* @b: transaction buffer
- * @objects_start start of objects buffer
- * @buffer: binder_buffer_object in which to fix up
- * @offset: start offset in @buffer to fix up
- * @last_obj: last binder_buffer_object that we fixed up in
- * @last_min_offset: minimum fixup offset in @last_obj
+ * @objects_start_offset: offset to start of objects buffer
+ * @buffer_obj_offset: offset to binder_buffer_object in which to fix up
+ * @fixup_offset: start offset in @buffer to fix up
+ * @last_obj_offset: offset to last binder_buffer_object that we fixed
+ * @last_min_offset: minimum fixup offset in object at @last_obj_offset
*
* Return: %true if a fixup in buffer @buffer at offset @offset is
* allowed.
@@ -2132,28 +2179,41 @@ static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b,
* C (parent = A, offset = 16)
* D (parent = B, offset = 0) // B is not A or any of A's parents
*/
-static bool binder_validate_fixup(struct binder_buffer *b,
- binder_size_t *objects_start,
- struct binder_buffer_object *buffer,
+static bool binder_validate_fixup(struct binder_proc *proc,
+ struct binder_buffer *b,
+ binder_size_t objects_start_offset,
+ binder_size_t buffer_obj_offset,
binder_size_t fixup_offset,
- struct binder_buffer_object *last_obj,
+ binder_size_t last_obj_offset,
binder_size_t last_min_offset)
{
- if (!last_obj) {
+ if (!last_obj_offset) {
/* Nothing to fix up in */
return false;
}
- while (last_obj != buffer) {
+ while (last_obj_offset != buffer_obj_offset) {
+ unsigned long buffer_offset;
+ struct binder_object last_object;
+ struct binder_buffer_object *last_bbo;
+ size_t object_size = binder_get_object(proc, b, last_obj_offset,
+ &last_object);
+ if (object_size != sizeof(*last_bbo))
+ return false;
+
+ last_bbo = &last_object.bbo;
/*
* Safe to retrieve the parent of last_obj, since it
* was already previously verified by the driver.
*/
- if ((last_obj->flags & BINDER_BUFFER_FLAG_HAS_PARENT) == 0)
+ if ((last_bbo->flags & BINDER_BUFFER_FLAG_HAS_PARENT) == 0)
return false;
- last_min_offset = last_obj->parent_offset + sizeof(uintptr_t);
- last_obj = (struct binder_buffer_object *)
- (b->data + *(objects_start + last_obj->parent));
+ last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t);
+ buffer_offset = objects_start_offset +
+ sizeof(binder_size_t) * last_bbo->parent,
+ binder_alloc_copy_from_buffer(&proc->alloc, &last_obj_offset,
+ b, buffer_offset,
+ sizeof(last_obj_offset));
}
return (fixup_offset >= last_min_offset);
}
@@ -2218,35 +2278,42 @@ static void binder_deferred_fd_close(int fd)
static void binder_transaction_buffer_release(struct binder_proc *proc,
struct binder_buffer *buffer,
- binder_size_t *failed_at)
+ binder_size_t failed_at,
+ bool is_failure)
{
- binder_size_t *offp, *off_start, *off_end;
int debug_id = buffer->debug_id;
+ binder_size_t off_start_offset, buffer_offset, off_end_offset;
binder_debug(BINDER_DEBUG_TRANSACTION,
- "%d buffer release %d, size %zd-%zd, failed at %pK\n",
+ "%d buffer release %d, size %zd-%zd, failed at %llx\n",
proc->pid, buffer->debug_id,
- buffer->data_size, buffer->offsets_size, failed_at);
+ buffer->data_size, buffer->offsets_size,
+ (unsigned long long)failed_at);
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
- off_start = (binder_size_t *)(buffer->data +
- ALIGN(buffer->data_size, sizeof(void *)));
- if (failed_at)
- off_end = failed_at;
- else
- off_end = (void *)off_start + buffer->offsets_size;
- for (offp = off_start; offp < off_end; offp++) {
+ off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
+ off_end_offset = is_failure ? failed_at :
+ off_start_offset + buffer->offsets_size;
+ for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+ buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
- size_t object_size = binder_validate_object(buffer, *offp);
-
+ size_t object_size;
+ struct binder_object object;
+ binder_size_t object_offset;
+
+ binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ buffer, buffer_offset,
+ sizeof(object_offset));
+ object_size = binder_get_object(proc, buffer,
+ object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset %lld, size %zd\n",
- debug_id, (u64)*offp, buffer->data_size);
+ debug_id, (u64)object_offset, buffer->data_size);
continue;
}
- hdr = (struct binder_object_header *)(buffer->data + *offp);
+ hdr = &object.hdr;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
@@ -2309,10 +2376,11 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
case BINDER_TYPE_FDA: {
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
- uintptr_t parent_buffer;
- u32 *fd_array;
+ struct binder_object ptr_object;
+ binder_size_t fda_offset;
size_t fd_index;
binder_size_t fd_buf_size;
+ binder_size_t num_valid;
if (proc->tsk != current->group_leader) {
/*
@@ -2323,23 +2391,19 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
continue;
}
+ num_valid = (buffer_offset - off_start_offset) /
+ sizeof(binder_size_t);
fda = to_binder_fd_array_object(hdr);
- parent = binder_validate_ptr(buffer, fda->parent,
- off_start,
- offp - off_start);
+ parent = binder_validate_ptr(proc, buffer, &ptr_object,
+ fda->parent,
+ off_start_offset,
+ NULL,
+ num_valid);
if (!parent) {
pr_err("transaction release %d bad parent offset\n",
debug_id);
continue;
}
- /*
- * Since the parent was already fixed up, convert it
- * back to kernel address space to access it
- */
- parent_buffer = parent->buffer -
- binder_alloc_get_user_buffer_offset(
- &proc->alloc);
-
fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
pr_err("transaction release %d invalid number of fds (%lld)\n",
@@ -2353,9 +2417,29 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
debug_id, (u64)fda->num_fds);
continue;
}
- fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
- for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
- binder_deferred_fd_close(fd_array[fd_index]);
+ /*
+ * the source data for binder_buffer_object is visible
+ * to user-space and the @buffer element is the user
+ * pointer to the buffer_object containing the fd_array.
+ * Convert the address to an offset relative to
+ * the base of the transaction buffer.
+ */
+ fda_offset =
+ (parent->buffer - (uintptr_t)buffer->user_data) +
+ fda->parent_offset;
+ for (fd_index = 0; fd_index < fda->num_fds;
+ fd_index++) {
+ u32 fd;
+ binder_size_t offset = fda_offset +
+ fd_index * sizeof(fd);
+
+ binder_alloc_copy_from_buffer(&proc->alloc,
+ &fd,
+ buffer,
+ offset,
+ sizeof(fd));
+ binder_deferred_fd_close(fd);
+ }
} break;
default:
pr_err("transaction release %d bad object type %x\n",
@@ -2491,7 +2575,7 @@ done:
return ret;
}
-static int binder_translate_fd(u32 *fdp,
+static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
struct binder_transaction *t,
struct binder_thread *thread,
struct binder_transaction *in_reply_to)
@@ -2502,7 +2586,6 @@ static int binder_translate_fd(u32 *fdp,
struct file *file;
int ret = 0;
bool target_allows_fd;
- int fd = *fdp;
if (in_reply_to)
target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS);
@@ -2541,7 +2624,7 @@ static int binder_translate_fd(u32 *fdp,
goto err_alloc;
}
fixup->file = file;
- fixup->offset = (uintptr_t)fdp - (uintptr_t)t->buffer->data;
+ fixup->offset = fd_offset;
trace_binder_transaction_fd_send(t, fd, fixup->offset);
list_add_tail(&fixup->fixup_entry, &t->fd_fixups);
@@ -2562,8 +2645,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
struct binder_transaction *in_reply_to)
{
binder_size_t fdi, fd_buf_size;
- uintptr_t parent_buffer;
- u32 *fd_array;
+ binder_size_t fda_offset;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2581,20 +2663,29 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
return -EINVAL;
}
/*
- * Since the parent was already fixed up, convert it
- * back to the kernel address space to access it
+ * the source data for binder_buffer_object is visible
+ * to user-space and the @buffer element is the user
+ * pointer to the buffer_object containing the fd_array.
+ * Convert the address to an offset relative to
+ * the base of the transaction buffer.
*/
- parent_buffer = parent->buffer -
- binder_alloc_get_user_buffer_offset(&target_proc->alloc);
- fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
- if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
+ fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
+ fda->parent_offset;
+ if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned correctly.\n",
proc->pid, thread->pid);
return -EINVAL;
}
for (fdi = 0; fdi < fda->num_fds; fdi++) {
- int ret = binder_translate_fd(&fd_array[fdi], t, thread,
- in_reply_to);
+ u32 fd;
+ int ret;
+ binder_size_t offset = fda_offset + fdi * sizeof(fd);
+
+ binder_alloc_copy_from_buffer(&target_proc->alloc,
+ &fd, t->buffer,
+ offset, sizeof(fd));
+ ret = binder_translate_fd(fd, offset, t, thread,
+ in_reply_to);
if (ret < 0)
return ret;
}
@@ -2604,30 +2695,34 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
static int binder_fixup_parent(struct binder_transaction *t,
struct binder_thread *thread,
struct binder_buffer_object *bp,
- binder_size_t *off_start,
+ binder_size_t off_start_offset,
binder_size_t num_valid,
- struct binder_buffer_object *last_fixup_obj,
+ binder_size_t last_fixup_obj_off,
binder_size_t last_fixup_min_off)
{
struct binder_buffer_object *parent;
- u8 *parent_buffer;
struct binder_buffer *b = t->buffer;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
+ struct binder_object object;
+ binder_size_t buffer_offset;
+ binder_size_t parent_offset;
if (!(bp->flags & BINDER_BUFFER_FLAG_HAS_PARENT))
return 0;
- parent = binder_validate_ptr(b, bp->parent, off_start, num_valid);
+ parent = binder_validate_ptr(target_proc, b, &object, bp->parent,
+ off_start_offset, &parent_offset,
+ num_valid);
if (!parent) {
binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
proc->pid, thread->pid);
return -EINVAL;
}
- if (!binder_validate_fixup(b, off_start,
- parent, bp->parent_offset,
- last_fixup_obj,
+ if (!binder_validate_fixup(target_proc, b, off_start_offset,
+ parent_offset, bp->parent_offset,
+ last_fixup_obj_off,
last_fixup_min_off)) {
binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
proc->pid, thread->pid);
@@ -2641,10 +2736,10 @@ static int binder_fixup_parent(struct binder_transaction *t,
proc->pid, thread->pid);
return -EINVAL;
}
- parent_buffer = (u8 *)((uintptr_t)parent->buffer -
- binder_alloc_get_user_buffer_offset(
- &target_proc->alloc));
- *(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer;
+ buffer_offset = bp->parent_offset +
+ (uintptr_t)parent->buffer - (uintptr_t)b->user_data;
+ binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
+ &bp->buffer, sizeof(bp->buffer));
return 0;
}
@@ -2763,9 +2858,10 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_transaction *t;
struct binder_work *w;
struct binder_work *tcomplete;
- binder_size_t *offp, *off_end, *off_start;
+ binder_size_t buffer_offset = 0;
+ binder_size_t off_start_offset, off_end_offset;
binder_size_t off_min;
- u8 *sg_bufp, *sg_buf_end;
+ binder_size_t sg_buf_offset, sg_buf_end_offset;
struct binder_proc *target_proc = NULL;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
@@ -2774,10 +2870,12 @@ static void binder_transaction(struct binder_proc *proc,
uint32_t return_error = 0;
uint32_t return_error_param = 0;
uint32_t return_error_line = 0;
- struct binder_buffer_object *last_fixup_obj = NULL;
+ binder_size_t last_fixup_obj_off = 0;
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
+ char *secctx = NULL;
+ u32 secctx_sz = 0;
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3020,6 +3118,20 @@ static void binder_transaction(struct binder_proc *proc,
t->flags = tr->flags;
t->priority = task_nice(current);
+ if (target_node && target_node->txn_security_ctx) {
+ u32 secid;
+
+ security_task_getsecid(proc->tsk, &secid);
+ ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+ if (ret) {
+ return_error = BR_FAILED_REPLY;
+ return_error_param = ret;
+ return_error_line = __LINE__;
+ goto err_get_secctx_failed;
+ }
+ extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+ }
+
trace_binder_transaction(reply, t, target_node);
t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
@@ -3036,16 +3148,30 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
+ if (secctx) {
+ size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
+ ALIGN(tr->offsets_size, sizeof(void *)) +
+ ALIGN(extra_buffers_size, sizeof(void *)) -
+ ALIGN(secctx_sz, sizeof(u64));
+
+ t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer, buf_offset,
+ secctx, secctx_sz);
+ security_release_secctx(secctx, secctx_sz);
+ secctx = NULL;
+ }
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
trace_binder_transaction_alloc_buf(t->buffer);
- off_start = (binder_size_t *)(t->buffer->data +
- ALIGN(tr->data_size, sizeof(void *)));
- offp = off_start;
- if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
- tr->data.ptr.buffer, tr->data_size)) {
+ if (binder_alloc_copy_user_to_buffer(
+ &target_proc->alloc,
+ t->buffer, 0,
+ (const void __user *)
+ (uintptr_t)tr->data.ptr.buffer,
+ tr->data_size)) {
binder_user_error("%d:%d got transaction with invalid data ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3053,8 +3179,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
- if (copy_from_user(offp, (const void __user *)(uintptr_t)
- tr->data.ptr.offsets, tr->offsets_size)) {
+ if (binder_alloc_copy_user_to_buffer(
+ &target_proc->alloc,
+ t->buffer,
+ ALIGN(tr->data_size, sizeof(void *)),
+ (const void __user *)
+ (uintptr_t)tr->data.ptr.offsets,
+ tr->offsets_size)) {
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3079,17 +3210,30 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
- off_end = (void *)off_start + tr->offsets_size;
- sg_bufp = (u8 *)(PTR_ALIGN(off_end, sizeof(void *)));
- sg_buf_end = sg_bufp + extra_buffers_size;
+ off_start_offset = ALIGN(tr->data_size, sizeof(void *));
+ buffer_offset = off_start_offset;
+ off_end_offset = off_start_offset + tr->offsets_size;
+ sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
+ sg_buf_end_offset = sg_buf_offset + extra_buffers_size;
off_min = 0;
- for (; offp < off_end; offp++) {
+ for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+ buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
- size_t object_size = binder_validate_object(t->buffer, *offp);
-
- if (object_size == 0 || *offp < off_min) {
+ size_t object_size;
+ struct binder_object object;
+ binder_size_t object_offset;
+
+ binder_alloc_copy_from_buffer(&target_proc->alloc,
+ &object_offset,
+ t->buffer,
+ buffer_offset,
+ sizeof(object_offset));
+ object_size = binder_get_object(target_proc, t->buffer,
+ object_offset, &object);
+ if (object_size == 0 || object_offset < off_min) {
binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
- proc->pid, thread->pid, (u64)*offp,
+ proc->pid, thread->pid,
+ (u64)object_offset,
(u64)off_min,
(u64)t->buffer->data_size);
return_error = BR_FAILED_REPLY;
@@ -3098,8 +3242,8 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_offset;
}
- hdr = (struct binder_object_header *)(t->buffer->data + *offp);
- off_min = *offp + object_size;
+ hdr = &object.hdr;
+ off_min = object_offset + object_size;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
@@ -3113,6 +3257,9 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_translate_failed;
}
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer, object_offset,
+ fp, sizeof(*fp));
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
@@ -3126,12 +3273,17 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_translate_failed;
}
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer, object_offset,
+ fp, sizeof(*fp));
} break;
case BINDER_TYPE_FD: {
struct binder_fd_object *fp = to_binder_fd_object(hdr);
- int ret = binder_translate_fd(&fp->fd, t, thread,
- in_reply_to);
+ binder_size_t fd_offset = object_offset +
+ (uintptr_t)&fp->fd - (uintptr_t)fp;
+ int ret = binder_translate_fd(fp->fd, fd_offset, t,
+ thread, in_reply_to);
if (ret < 0) {
return_error = BR_FAILED_REPLY;
@@ -3140,14 +3292,23 @@ static void binder_transaction(struct binder_proc *proc,
goto err_translate_failed;
}
fp->pad_binder = 0;
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer, object_offset,
+ fp, sizeof(*fp));
} break;
case BINDER_TYPE_FDA: {
+ struct binder_object ptr_object;
+ binder_size_t parent_offset;
struct binder_fd_array_object *fda =
to_binder_fd_array_object(hdr);
+ size_t num_valid = (buffer_offset - off_start_offset) *
+ sizeof(binder_size_t);
struct binder_buffer_object *parent =
- binder_validate_ptr(t->buffer, fda->parent,
- off_start,
- offp - off_start);
+ binder_validate_ptr(target_proc, t->buffer,
+ &ptr_object, fda->parent,
+ off_start_offset,
+ &parent_offset,
+ num_valid);
if (!parent) {
binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
proc->pid, thread->pid);
@@ -3156,9 +3317,11 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_parent;
}
- if (!binder_validate_fixup(t->buffer, off_start,
- parent, fda->parent_offset,
- last_fixup_obj,
+ if (!binder_validate_fixup(target_proc, t->buffer,
+ off_start_offset,
+ parent_offset,
+ fda->parent_offset,
+ last_fixup_obj_off,
last_fixup_min_off)) {
binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
proc->pid, thread->pid);
@@ -3175,14 +3338,15 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_translate_failed;
}
- last_fixup_obj = parent;
+ last_fixup_obj_off = parent_offset;
last_fixup_min_off =
fda->parent_offset + sizeof(u32) * fda->num_fds;
} break;
case BINDER_TYPE_PTR: {
struct binder_buffer_object *bp =
to_binder_buffer_object(hdr);
- size_t buf_left = sg_buf_end - sg_bufp;
+ size_t buf_left = sg_buf_end_offset - sg_buf_offset;
+ size_t num_valid;
if (bp->length > buf_left) {
binder_user_error("%d:%d got transaction with too large buffer\n",
@@ -3192,9 +3356,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
- if (copy_from_user(sg_bufp,
- (const void __user *)(uintptr_t)
- bp->buffer, bp->length)) {
+ if (binder_alloc_copy_user_to_buffer(
+ &target_proc->alloc,
+ t->buffer,
+ sg_buf_offset,
+ (const void __user *)
+ (uintptr_t)bp->buffer,
+ bp->length)) {
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
proc->pid, thread->pid);
return_error_param = -EFAULT;
@@ -3203,14 +3371,16 @@ static void binder_transaction(struct binder_proc *proc,
goto err_copy_data_failed;
}
/* Fixup buffer pointer to target proc address space */
- bp->buffer = (uintptr_t)sg_bufp +
- binder_alloc_get_user_buffer_offset(
- &target_proc->alloc);
- sg_bufp += ALIGN(bp->length, sizeof(u64));
-
- ret = binder_fixup_parent(t, thread, bp, off_start,
- offp - off_start,
- last_fixup_obj,
+ bp->buffer = (uintptr_t)
+ t->buffer->user_data + sg_buf_offset;
+ sg_buf_offset += ALIGN(bp->length, sizeof(u64));
+
+ num_valid = (buffer_offset - off_start_offset) *
+ sizeof(binder_size_t);
+ ret = binder_fixup_parent(t, thread, bp,
+ off_start_offset,
+ num_valid,
+ last_fixup_obj_off,
last_fixup_min_off);
if (ret < 0) {
return_error = BR_FAILED_REPLY;
@@ -3218,7 +3388,10 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_translate_failed;
}
- last_fixup_obj = bp;
+ binder_alloc_copy_to_buffer(&target_proc->alloc,
+ t->buffer, object_offset,
+ bp, sizeof(*bp));
+ last_fixup_obj_off = object_offset;
last_fixup_min_off = 0;
} break;
default:
@@ -3298,13 +3471,17 @@ err_bad_parent:
err_copy_data_failed:
binder_free_txn_fixups(t);
trace_binder_transaction_failed_buffer_release(t->buffer);
- binder_transaction_buffer_release(target_proc, t->buffer, offp);
+ binder_transaction_buffer_release(target_proc, t->buffer,
+ buffer_offset, true);
if (target_node)
binder_dec_node_tmpref(target_node);
target_node = NULL;
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
+ if (secctx)
+ security_release_secctx(secctx, secctx_sz);
+err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
err_alloc_tcomplete_failed:
@@ -3396,7 +3573,7 @@ binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
binder_node_inner_unlock(buf_node);
}
trace_binder_transaction_buffer_release(buffer);
- binder_transaction_buffer_release(proc, buffer, NULL);
+ binder_transaction_buffer_release(proc, buffer, 0, false);
binder_alloc_free_buf(&proc->alloc, buffer);
}
@@ -3915,6 +4092,7 @@ static int binder_wait_for_work(struct binder_thread *thread,
/**
* binder_apply_fd_fixups() - finish fd translation
+ * @proc: binder_proc associated @t->buffer
* @t: binder transaction with list of fd fixups
*
* Now that we are in the context of the transaction target
@@ -3926,14 +4104,14 @@ static int binder_wait_for_work(struct binder_thread *thread,
* fput'ing files that have not been processed and ksys_close'ing
* any fds that have already been allocated.
*/
-static int binder_apply_fd_fixups(struct binder_transaction *t)
+static int binder_apply_fd_fixups(struct binder_proc *proc,
+ struct binder_transaction *t)
{
struct binder_txn_fd_fixup *fixup, *tmp;
int ret = 0;
list_for_each_entry(fixup, &t->fd_fixups, fixup_entry) {
int fd = get_unused_fd_flags(O_CLOEXEC);
- u32 *fdp;
if (fd < 0) {
binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -3948,33 +4126,20 @@ static int binder_apply_fd_fixups(struct binder_transaction *t)
trace_binder_transaction_fd_recv(t, fd, fixup->offset);
fd_install(fd, fixup->file);
fixup->file = NULL;
- fdp = (u32 *)(t->buffer->data + fixup->offset);
- /*
- * This store can cause problems for CPUs with a
- * VIVT cache (eg ARMv5) since the cache cannot
- * detect virtual aliases to the same physical cacheline.
- * To support VIVT, this address and the user-space VA
- * would both need to be flushed. Since this kernel
- * VA is not constructed via page_to_virt(), we can't
- * use flush_dcache_page() on it, so we'd have to use
- * an internal function. If devices with VIVT ever
- * need to run Android, we'll either need to go back
- * to patching the translated fd from the sender side
- * (using the non-standard kernel functions), or rework
- * how the kernel uses the buffer to use page_to_virt()
- * addresses instead of allocating in our own vm area.
- *
- * For now, we disable compilation if CONFIG_CPU_CACHE_VIVT.
- */
- *fdp = fd;
+ binder_alloc_copy_to_buffer(&proc->alloc, t->buffer,
+ fixup->offset, &fd,
+ sizeof(u32));
}
list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) {
if (fixup->file) {
fput(fixup->file);
} else if (ret) {
- u32 *fdp = (u32 *)(t->buffer->data + fixup->offset);
+ u32 fd;
- binder_deferred_fd_close(*fdp);
+ binder_alloc_copy_from_buffer(&proc->alloc, &fd,
+ t->buffer, fixup->offset,
+ sizeof(fd));
+ binder_deferred_fd_close(fd);
}
list_del(&fixup->fixup_entry);
kfree(fixup);
@@ -4036,11 +4201,13 @@ retry:
while (1) {
uint32_t cmd;
- struct binder_transaction_data tr;
+ struct binder_transaction_data_secctx tr;
+ struct binder_transaction_data *trd = &tr.transaction_data;
struct binder_work *w = NULL;
struct list_head *list = NULL;
struct binder_transaction *t = NULL;
struct binder_thread *t_from;
+ size_t trsize = sizeof(*trd);
binder_inner_proc_lock(proc);
if (!binder_worklist_empty_ilocked(&thread->todo))
@@ -4240,8 +4407,8 @@ retry:
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
- tr.target.ptr = target_node->ptr;
- tr.cookie = target_node->cookie;
+ trd->target.ptr = target_node->ptr;
+ trd->cookie = target_node->cookie;
t->saved_priority = task_nice(current);
if (t->priority < target_node->min_priority &&
!(t->flags & TF_ONE_WAY))
@@ -4251,25 +4418,26 @@ retry:
binder_set_nice(target_node->min_priority);
cmd = BR_TRANSACTION;
} else {
- tr.target.ptr = 0;
- tr.cookie = 0;
+ trd->target.ptr = 0;
+ trd->cookie = 0;
cmd = BR_REPLY;
}
- tr.code = t->code;
- tr.flags = t->flags;
- tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
+ trd->code = t->code;
+ trd->flags = t->flags;
+ trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
t_from = binder_get_txn_from(t);
if (t_from) {
struct task_struct *sender = t_from->proc->tsk;
- tr.sender_pid = task_tgid_nr_ns(sender,
- task_active_pid_ns(current));
+ trd->sender_pid =
+ task_tgid_nr_ns(sender,
+ task_active_pid_ns(current));
} else {
- tr.sender_pid = 0;
+ trd->sender_pid = 0;
}
- ret = binder_apply_fd_fixups(t);
+ ret = binder_apply_fd_fixups(proc, t);
if (ret) {
struct binder_buffer *buffer = t->buffer;
bool oneway = !!(t->flags & TF_ONE_WAY);
@@ -4297,15 +4465,18 @@ retry:
}
continue;
}
- tr.data_size = t->buffer->data_size;
- tr.offsets_size = t->buffer->offsets_size;
- tr.data.ptr.buffer = (binder_uintptr_t)
- ((uintptr_t)t->buffer->data +
- binder_alloc_get_user_buffer_offset(&proc->alloc));
- tr.data.ptr.offsets = tr.data.ptr.buffer +
+ trd->data_size = t->buffer->data_size;
+ trd->offsets_size = t->buffer->offsets_size;
+ trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data;
+ trd->data.ptr.offsets = trd->data.ptr.buffer +
ALIGN(t->buffer->data_size,
sizeof(void *));
+ tr.secctx = t->security_ctx;
+ if (t->security_ctx) {
+ cmd = BR_TRANSACTION_SEC_CTX;
+ trsize = sizeof(tr);
+ }
if (put_user(cmd, (uint32_t __user *)ptr)) {
if (t_from)
binder_thread_dec_tmpref(t_from);
@@ -4316,7 +4487,7 @@ retry:
return -EFAULT;
}
ptr += sizeof(uint32_t);
- if (copy_to_user(ptr, &tr, sizeof(tr))) {
+ if (copy_to_user(ptr, &tr, trsize)) {
if (t_from)
binder_thread_dec_tmpref(t_from);
@@ -4325,7 +4496,7 @@ retry:
return -EFAULT;
}
- ptr += sizeof(tr);
+ ptr += trsize;
trace_binder_transaction_received(t);
binder_stat_br(proc, thread, cmd);
@@ -4333,16 +4504,18 @@ retry:
"%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
proc->pid, thread->pid,
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
- "BR_REPLY",
+ (cmd == BR_TRANSACTION_SEC_CTX) ?
+ "BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
t->debug_id, t_from ? t_from->proc->pid : 0,
t_from ? t_from->pid : 0, cmd,
t->buffer->data_size, t->buffer->offsets_size,
- (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
+ (u64)trd->data.ptr.buffer,
+ (u64)trd->data.ptr.offsets);
if (t_from)
binder_thread_dec_tmpref(t_from);
t->buffer->allow_user_free = 1;
- if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+ if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) {
binder_inner_proc_lock(thread->proc);
t->to_parent = thread->transaction_stack;
t->to_thread = thread;
@@ -4690,7 +4863,8 @@ out:
return ret;
}
-static int binder_ioctl_set_ctx_mgr(struct file *filp)
+static int binder_ioctl_set_ctx_mgr(struct file *filp,
+ struct flat_binder_object *fbo)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
@@ -4719,7 +4893,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
} else {
context->binder_context_mgr_uid = curr_euid;
}
- new_node = binder_new_node(proc, NULL);
+ new_node = binder_new_node(proc, fbo);
if (!new_node) {
ret = -ENOMEM;
goto out;
@@ -4842,8 +5016,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
binder_inner_proc_unlock(proc);
break;
}
+ case BINDER_SET_CONTEXT_MGR_EXT: {
+ struct flat_binder_object fbo;
+
+ if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
+ ret = -EINVAL;
+ goto err;
+ }
+ ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
+ if (ret)
+ goto err;
+ break;
+ }
case BINDER_SET_CONTEXT_MGR:
- ret = binder_ioctl_set_ctx_mgr(filp);
+ ret = binder_ioctl_set_ctx_mgr(filp, NULL);
if (ret)
goto err;
break;
@@ -5319,7 +5505,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
seq_printf(m, " node %d", buffer->target_node->debug_id);
seq_printf(m, " size %zd:%zd data %pK\n",
buffer->data_size, buffer->offsets_size,
- buffer->data);
+ buffer->user_data);
}
static void print_binder_work_ilocked(struct seq_file *m,
@@ -5854,9 +6040,10 @@ static int __init init_binder_device(const char *name)
static int __init binder_init(void)
{
int ret;
- char *device_name, *device_names, *device_tmp;
+ char *device_name, *device_tmp;
struct binder_device *device;
struct hlist_node *tmp;
+ char *device_names = NULL;
ret = binder_alloc_shrinker_init();
if (ret)
@@ -5898,23 +6085,29 @@ static int __init binder_init(void)
&transaction_log_fops);
}
- /*
- * Copy the module_parameter string, because we don't want to
- * tokenize it in-place.
- */
- device_names = kstrdup(binder_devices_param, GFP_KERNEL);
- if (!device_names) {
- ret = -ENOMEM;
- goto err_alloc_device_names_failed;
- }
+ if (strcmp(binder_devices_param, "") != 0) {
+ /*
+ * Copy the module_parameter string, because we don't want to
+ * tokenize it in-place.
+ */
+ device_names = kstrdup(binder_devices_param, GFP_KERNEL);
+ if (!device_names) {
+ ret = -ENOMEM;
+ goto err_alloc_device_names_failed;
+ }
- device_tmp = device_names;
- while ((device_name = strsep(&device_tmp, ","))) {
- ret = init_binder_device(device_name);
- if (ret)
- goto err_init_binder_device_failed;
+ device_tmp = device_names;
+ while ((device_name = strsep(&device_tmp, ","))) {
+ ret = init_binder_device(device_name);
+ if (ret)
+ goto err_init_binder_device_failed;
+ }
}
+ ret = init_binderfs();
+ if (ret)
+ goto err_init_binder_device_failed;
+
return ret;
err_init_binder_device_failed:
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 022cd80e80cc..6389467670a0 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -29,6 +29,8 @@
#include <linux/list_lru.h>
#include <linux/ratelimit.h>
#include <asm/cacheflush.h>
+#include <linux/uaccess.h>
+#include <linux/highmem.h>
#include "binder_alloc.h"
#include "binder_trace.h"
@@ -67,9 +69,8 @@ static size_t binder_alloc_buffer_size(struct binder_alloc *alloc,
struct binder_buffer *buffer)
{
if (list_is_last(&buffer->entry, &alloc->buffers))
- return (u8 *)alloc->buffer +
- alloc->buffer_size - (u8 *)buffer->data;
- return (u8 *)binder_buffer_next(buffer)->data - (u8 *)buffer->data;
+ return alloc->buffer + alloc->buffer_size - buffer->user_data;
+ return binder_buffer_next(buffer)->user_data - buffer->user_data;
}
static void binder_insert_free_buffer(struct binder_alloc *alloc,
@@ -119,9 +120,9 @@ static void binder_insert_allocated_buffer_locked(
buffer = rb_entry(parent, struct binder_buffer, rb_node);
BUG_ON(buffer->free);
- if (new_buffer->data < buffer->data)
+ if (new_buffer->user_data < buffer->user_data)
p = &parent->rb_left;
- else if (new_buffer->data > buffer->data)
+ else if (new_buffer->user_data > buffer->user_data)
p = &parent->rb_right;
else
BUG();
@@ -136,17 +137,17 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(
{
struct rb_node *n = alloc->allocated_buffers.rb_node;
struct binder_buffer *buffer;
- void *kern_ptr;
+ void __user *uptr;
- kern_ptr = (void *)(user_ptr - alloc->user_buffer_offset);
+ uptr = (void __user *)user_ptr;
while (n) {
buffer = rb_entry(n, struct binder_buffer, rb_node);
BUG_ON(buffer->free);
- if (kern_ptr < buffer->data)
+ if (uptr < buffer->user_data)
n = n->rb_left;
- else if (kern_ptr > buffer->data)
+ else if (uptr > buffer->user_data)
n = n->rb_right;
else {
/*
@@ -186,9 +187,9 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc,
}
static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
- void *start, void *end)
+ void __user *start, void __user *end)
{
- void *page_addr;
+ void __user *page_addr;
unsigned long user_page_addr;
struct binder_lru_page *page;
struct vm_area_struct *vma = NULL;
@@ -263,18 +264,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
page->alloc = alloc;
INIT_LIST_HEAD(&page->lru);
- ret = map_kernel_range_noflush((unsigned long)page_addr,
- PAGE_SIZE, PAGE_KERNEL,
- &page->page_ptr);
- flush_cache_vmap((unsigned long)page_addr,
- (unsigned long)page_addr + PAGE_SIZE);
- if (ret != 1) {
- pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n",
- alloc->pid, page_addr);
- goto err_map_kernel_failed;
- }
- user_page_addr =
- (uintptr_t)page_addr + alloc->user_buffer_offset;
+ user_page_addr = (uintptr_t)page_addr;
ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr);
if (ret) {
pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n",
@@ -312,8 +302,6 @@ free_range:
continue;
err_vm_insert_page_failed:
- unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
__free_page(page->page_ptr);
page->page_ptr = NULL;
err_alloc_page_failed:
@@ -368,8 +356,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
struct binder_buffer *buffer;
size_t buffer_size;
struct rb_node *best_fit = NULL;
- void *has_page_addr;
- void *end_page_addr;
+ void __user *has_page_addr;
+ void __user *end_page_addr;
size_t size, data_offsets_size;
int ret;
@@ -467,15 +455,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
"%d: binder_alloc_buf size %zd got buffer %pK size %zd\n",
alloc->pid, size, buffer, buffer_size);
- has_page_addr =
- (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
+ has_page_addr = (void __user *)
+ (((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK);
WARN_ON(n && buffer_size != size);
end_page_addr =
- (void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
+ (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
if (end_page_addr > has_page_addr)
end_page_addr = has_page_addr;
- ret = binder_update_page_range(alloc, 1,
- (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr);
+ ret = binder_update_page_range(alloc, 1, (void __user *)
+ PAGE_ALIGN((uintptr_t)buffer->user_data), end_page_addr);
if (ret)
return ERR_PTR(ret);
@@ -488,7 +476,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
__func__, alloc->pid);
goto err_alloc_buf_struct_failed;
}
- new_buffer->data = (u8 *)buffer->data + size;
+ new_buffer->user_data = (u8 __user *)buffer->user_data + size;
list_add(&new_buffer->entry, &buffer->entry);
new_buffer->free = 1;
binder_insert_free_buffer(alloc, new_buffer);
@@ -514,8 +502,8 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
return buffer;
err_alloc_buf_struct_failed:
- binder_update_page_range(alloc, 0,
- (void *)PAGE_ALIGN((uintptr_t)buffer->data),
+ binder_update_page_range(alloc, 0, (void __user *)
+ PAGE_ALIGN((uintptr_t)buffer->user_data),
end_page_addr);
return ERR_PTR(-ENOMEM);
}
@@ -550,14 +538,15 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
return buffer;
}
-static void *buffer_start_page(struct binder_buffer *buffer)
+static void __user *buffer_start_page(struct binder_buffer *buffer)
{
- return (void *)((uintptr_t)buffer->data & PAGE_MASK);
+ return (void __user *)((uintptr_t)buffer->user_data & PAGE_MASK);
}
-static void *prev_buffer_end_page(struct binder_buffer *buffer)
+static void __user *prev_buffer_end_page(struct binder_buffer *buffer)
{
- return (void *)(((uintptr_t)(buffer->data) - 1) & PAGE_MASK);
+ return (void __user *)
+ (((uintptr_t)(buffer->user_data) - 1) & PAGE_MASK);
}
static void binder_delete_free_buffer(struct binder_alloc *alloc,
@@ -572,7 +561,8 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
to_free = false;
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK share page with %pK\n",
- alloc->pid, buffer->data, prev->data);
+ alloc->pid, buffer->user_data,
+ prev->user_data);
}
if (!list_is_last(&buffer->entry, &alloc->buffers)) {
@@ -582,23 +572,24 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK share page with %pK\n",
alloc->pid,
- buffer->data,
- next->data);
+ buffer->user_data,
+ next->user_data);
}
}
- if (PAGE_ALIGNED(buffer->data)) {
+ if (PAGE_ALIGNED(buffer->user_data)) {
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer start %pK is page aligned\n",
- alloc->pid, buffer->data);
+ alloc->pid, buffer->user_data);
to_free = false;
}
if (to_free) {
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK do not share page with %pK or %pK\n",
- alloc->pid, buffer->data,
- prev->data, next ? next->data : NULL);
+ alloc->pid, buffer->user_data,
+ prev->user_data,
+ next ? next->user_data : NULL);
binder_update_page_range(alloc, 0, buffer_start_page(buffer),
buffer_start_page(buffer) + PAGE_SIZE);
}
@@ -624,8 +615,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
BUG_ON(buffer->free);
BUG_ON(size > buffer_size);
BUG_ON(buffer->transaction != NULL);
- BUG_ON(buffer->data < alloc->buffer);
- BUG_ON(buffer->data > alloc->buffer + alloc->buffer_size);
+ BUG_ON(buffer->user_data < alloc->buffer);
+ BUG_ON(buffer->user_data > alloc->buffer + alloc->buffer_size);
if (buffer->async_transaction) {
alloc->free_async_space += size + sizeof(struct binder_buffer);
@@ -636,8 +627,9 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
}
binder_update_page_range(alloc, 0,
- (void *)PAGE_ALIGN((uintptr_t)buffer->data),
- (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK));
+ (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data),
+ (void __user *)(((uintptr_t)
+ buffer->user_data + buffer_size) & PAGE_MASK));
rb_erase(&buffer->rb_node, &alloc->allocated_buffers);
buffer->free = 1;
@@ -693,7 +685,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
struct vm_area_struct *vma)
{
int ret;
- struct vm_struct *area;
const char *failure_string;
struct binder_buffer *buffer;
@@ -704,28 +695,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
goto err_already_mapped;
}
- area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC);
- if (area == NULL) {
- ret = -ENOMEM;
- failure_string = "get_vm_area";
- goto err_get_vm_area_failed;
- }
- alloc->buffer = area->addr;
- alloc->user_buffer_offset =
- vma->vm_start - (uintptr_t)alloc->buffer;
+ alloc->buffer = (void __user *)vma->vm_start;
mutex_unlock(&binder_alloc_mmap_lock);
-#ifdef CONFIG_CPU_CACHE_VIPT
- if (cache_is_vipt_aliasing()) {
- while (CACHE_COLOUR(
- (vma->vm_start ^ (uint32_t)alloc->buffer))) {
- pr_info("%s: %d %lx-%lx maps %pK bad alignment\n",
- __func__, alloc->pid, vma->vm_start,
- vma->vm_end, alloc->buffer);
- vma->vm_start += PAGE_SIZE;
- }
- }
-#endif
alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
sizeof(alloc->pages[0]),
GFP_KERNEL);
@@ -743,7 +715,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
goto err_alloc_buf_struct_failed;
}
- buffer->data = alloc->buffer;
+ buffer->user_data = alloc->buffer;
list_add(&buffer->entry, &alloc->buffers);
buffer->free = 1;
binder_insert_free_buffer(alloc, buffer);
@@ -758,9 +730,7 @@ err_alloc_buf_struct_failed:
alloc->pages = NULL;
err_alloc_pages_failed:
mutex_lock(&binder_alloc_mmap_lock);
- vfree(alloc->buffer);
alloc->buffer = NULL;
-err_get_vm_area_failed:
err_already_mapped:
mutex_unlock(&binder_alloc_mmap_lock);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
@@ -806,7 +776,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
int i;
for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
- void *page_addr;
+ void __user *page_addr;
bool on_lru;
if (!alloc->pages[i].page_ptr)
@@ -819,12 +789,10 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
"%s: %d: page %d at %pK %s\n",
__func__, alloc->pid, i, page_addr,
on_lru ? "on lru" : "active");
- unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
__free_page(alloc->pages[i].page_ptr);
page_count++;
}
kfree(alloc->pages);
- vfree(alloc->buffer);
}
mutex_unlock(&alloc->mutex);
if (alloc->vma_vm_mm)
@@ -839,7 +807,7 @@ static void print_binder_buffer(struct seq_file *m, const char *prefix,
struct binder_buffer *buffer)
{
seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n",
- prefix, buffer->debug_id, buffer->data,
+ prefix, buffer->debug_id, buffer->user_data,
buffer->data_size, buffer->offsets_size,
buffer->extra_buffers_size,
buffer->transaction ? "active" : "delivered");
@@ -964,7 +932,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
if (!mmget_not_zero(alloc->vma_vm_mm))
goto err_mmget;
mm = alloc->vma_vm_mm;
- if (!down_write_trylock(&mm->mmap_sem))
+ if (!down_read_trylock(&mm->mmap_sem))
goto err_down_write_mmap_sem_failed;
}
@@ -974,19 +942,16 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
if (vma) {
trace_binder_unmap_user_start(alloc, index);
- zap_page_range(vma,
- page_addr + alloc->user_buffer_offset,
- PAGE_SIZE);
+ zap_page_range(vma, page_addr, PAGE_SIZE);
trace_binder_unmap_user_end(alloc, index);
- up_write(&mm->mmap_sem);
+ up_read(&mm->mmap_sem);
mmput(mm);
}
trace_binder_unmap_kernel_start(alloc, index);
- unmap_kernel_range(page_addr, PAGE_SIZE);
__free_page(page->page_ptr);
page->page_ptr = NULL;
@@ -1053,3 +1018,173 @@ int binder_alloc_shrinker_init(void)
}
return ret;
}
+
+/**
+ * check_buffer() - verify that buffer/offset is safe to access
+ * @alloc: binder_alloc for this proc
+ * @buffer: binder buffer to be accessed
+ * @offset: offset into @buffer data
+ * @bytes: bytes to access from offset
+ *
+ * Check that the @offset/@bytes are within the size of the given
+ * @buffer and that the buffer is currently active and not freeable.
+ * Offsets must also be multiples of sizeof(u32). The kernel is
+ * allowed to touch the buffer in two cases:
+ *
+ * 1) when the buffer is being created:
+ * (buffer->free == 0 && buffer->allow_user_free == 0)
+ * 2) when the buffer is being torn down:
+ * (buffer->free == 0 && buffer->transaction == NULL).
+ *
+ * Return: true if the buffer is safe to access
+ */
+static inline bool check_buffer(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t offset, size_t bytes)
+{
+ size_t buffer_size = binder_alloc_buffer_size(alloc, buffer);
+
+ return buffer_size >= bytes &&
+ offset <= buffer_size - bytes &&
+ IS_ALIGNED(offset, sizeof(u32)) &&
+ !buffer->free &&
+ (!buffer->allow_user_free || !buffer->transaction);
+}
+
+/**
+ * binder_alloc_get_page() - get kernel pointer for given buffer offset
+ * @alloc: binder_alloc for this proc
+ * @buffer: binder buffer to be accessed
+ * @buffer_offset: offset into @buffer data
+ * @pgoffp: address to copy final page offset to
+ *
+ * Lookup the struct page corresponding to the address
+ * at @buffer_offset into @buffer->user_data. If @pgoffp is not
+ * NULL, the byte-offset into the page is written there.
+ *
+ * The caller is responsible to ensure that the offset points
+ * to a valid address within the @buffer and that @buffer is
+ * not freeable by the user. Since it can't be freed, we are
+ * guaranteed that the corresponding elements of @alloc->pages[]
+ * cannot change.
+ *
+ * Return: struct page
+ */
+static struct page *binder_alloc_get_page(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ pgoff_t *pgoffp)
+{
+ binder_size_t buffer_space_offset = buffer_offset +
+ (buffer->user_data - alloc->buffer);
+ pgoff_t pgoff = buffer_space_offset & ~PAGE_MASK;
+ size_t index = buffer_space_offset >> PAGE_SHIFT;
+ struct binder_lru_page *lru_page;
+
+ lru_page = &alloc->pages[index];
+ *pgoffp = pgoff;
+ return lru_page->page_ptr;
+}
+
+/**
+ * binder_alloc_copy_user_to_buffer() - copy src user to tgt user
+ * @alloc: binder_alloc for this proc
+ * @buffer: binder buffer to be accessed
+ * @buffer_offset: offset into @buffer data
+ * @from: userspace pointer to source buffer
+ * @bytes: bytes to copy
+ *
+ * Copy bytes from source userspace to target buffer.
+ *
+ * Return: bytes remaining to be copied
+ */
+unsigned long
+binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ const void __user *from,
+ size_t bytes)
+{
+ if (!check_buffer(alloc, buffer, buffer_offset, bytes))
+ return bytes;
+
+ while (bytes) {
+ unsigned long size;
+ unsigned long ret;
+ struct page *page;
+ pgoff_t pgoff;
+ void *kptr;
+
+ page = binder_alloc_get_page(alloc, buffer,
+ buffer_offset, &pgoff);
+ size = min_t(size_t, bytes, PAGE_SIZE - pgoff);
+ kptr = kmap(page) + pgoff;
+ ret = copy_from_user(kptr, from, size);
+ kunmap(page);
+ if (ret)
+ return bytes - size + ret;
+ bytes -= size;
+ from += size;
+ buffer_offset += size;
+ }
+ return 0;
+}
+
+static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
+ bool to_buffer,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ void *ptr,
+ size_t bytes)
+{
+ /* All copies must be 32-bit aligned and 32-bit size */
+ BUG_ON(!check_buffer(alloc, buffer, buffer_offset, bytes));
+
+ while (bytes) {
+ unsigned long size;
+ struct page *page;
+ pgoff_t pgoff;
+ void *tmpptr;
+ void *base_ptr;
+
+ page = binder_alloc_get_page(alloc, buffer,
+ buffer_offset, &pgoff);
+ size = min_t(size_t, bytes, PAGE_SIZE - pgoff);
+ base_ptr = kmap_atomic(page);
+ tmpptr = base_ptr + pgoff;
+ if (to_buffer)
+ memcpy(tmpptr, ptr, size);
+ else
+ memcpy(ptr, tmpptr, size);
+ /*
+ * kunmap_atomic() takes care of flushing the cache
+ * if this device has VIVT cache arch
+ */
+ kunmap_atomic(base_ptr);
+ bytes -= size;
+ pgoff = 0;
+ ptr = ptr + size;
+ buffer_offset += size;
+ }
+}
+
+void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ void *src,
+ size_t bytes)
+{
+ binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset,
+ src, bytes);
+}
+
+void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
+ void *dest,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ size_t bytes)
+{
+ binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
+ dest, bytes);
+}
+
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index c0aadbbf7f19..b60d161b7a7a 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/list_lru.h>
+#include <uapi/linux/android/binder.h>
extern struct list_lru binder_alloc_lru;
struct binder_transaction;
@@ -39,7 +40,7 @@ struct binder_transaction;
* @data_size: size of @transaction data
* @offsets_size: size of array of offsets
* @extra_buffers_size: size of space for other objects (like sg lists)
- * @data: pointer to base of buffer space
+ * @user_data: user pointer to base of buffer space
*
* Bookkeeping structure for binder transaction buffers
*/
@@ -58,7 +59,7 @@ struct binder_buffer {
size_t data_size;
size_t offsets_size;
size_t extra_buffers_size;
- void *data;
+ void __user *user_data;
};
/**
@@ -81,7 +82,6 @@ struct binder_lru_page {
* (invariant after init)
* @vma_vm_mm: copy of vma->vm_mm (invarient after mmap)
* @buffer: base of per-proc address space mapped via mmap
- * @user_buffer_offset: offset between user and kernel VAs for buffer
* @buffers: list of all buffers for this proc
* @free_buffers: rb tree of buffers available for allocation
* sorted by size
@@ -102,8 +102,7 @@ struct binder_alloc {
struct mutex mutex;
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
- void *buffer;
- ptrdiff_t user_buffer_offset;
+ void __user *buffer;
struct list_head buffers;
struct rb_root free_buffers;
struct rb_root allocated_buffers;
@@ -162,26 +161,24 @@ binder_alloc_get_free_async_space(struct binder_alloc *alloc)
return free_async_space;
}
-/**
- * binder_alloc_get_user_buffer_offset() - get offset between kernel/user addrs
- * @alloc: binder_alloc for this proc
- *
- * Return: the offset between kernel and user-space addresses to use for
- * virtual address conversion
- */
-static inline ptrdiff_t
-binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc)
-{
- /*
- * user_buffer_offset is constant if vma is set and
- * undefined if vma is not set. It is possible to
- * get here with !alloc->vma if the target process
- * is dying while a transaction is being initiated.
- * Returning the old value is ok in this case and
- * the transaction will fail.
- */
- return alloc->user_buffer_offset;
-}
+unsigned long
+binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ const void __user *from,
+ size_t bytes);
+
+void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ void *src,
+ size_t bytes);
+
+void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
+ void *dest,
+ struct binder_buffer *buffer,
+ binder_size_t buffer_offset,
+ size_t bytes);
#endif /* _LINUX_BINDER_ALLOC_H */
diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c
index 8bd7bcef967d..b72708918b06 100644
--- a/drivers/android/binder_alloc_selftest.c
+++ b/drivers/android/binder_alloc_selftest.c
@@ -102,11 +102,12 @@ static bool check_buffer_pages_allocated(struct binder_alloc *alloc,
struct binder_buffer *buffer,
size_t size)
{
- void *page_addr, *end;
+ void __user *page_addr;
+ void __user *end;
int page_index;
- end = (void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
- page_addr = buffer->data;
+ end = (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
+ page_addr = buffer->user_data;
for (; page_addr < end; page_addr += PAGE_SIZE) {
page_index = (page_addr - alloc->buffer) / PAGE_SIZE;
if (!alloc->pages[page_index].page_ptr ||
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 7fb97f503ef2..045b3e42d98b 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode *inode)
}
#endif
+#ifdef CONFIG_ANDROID_BINDERFS
+extern int __init init_binderfs(void);
+#else
+static inline int __init init_binderfs(void)
+{
+ return 0;
+}
+#endif
+
#endif /* _LINUX_BINDER_INTERNAL_H */
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 14de7ac57a34..83cc254d2335 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -293,7 +293,7 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
TRACE_EVENT(binder_update_page_range,
TP_PROTO(struct binder_alloc *alloc, bool allocate,
- void *start, void *end),
+ void __user *start, void __user *end),
TP_ARGS(alloc, allocate, start, end),
TP_STRUCT__entry(
__field(int, proc)
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
index 7496b10532aa..e773f45d19d9 100644
--- a/drivers/android/binderfs.c
+++ b/drivers/android/binderfs.c
@@ -11,6 +11,7 @@
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/namei.h>
#include <linux/magic.h>
#include <linux/major.h>
#include <linux/miscdevice.h>
@@ -20,6 +21,7 @@
#include <linux/parser.h>
#include <linux/radix-tree.h>
#include <linux/sched.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock_types.h>
#include <linux/stddef.h>
@@ -30,7 +32,7 @@
#include <linux/xarray.h>
#include <uapi/asm-generic/errno-base.h>
#include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binder_ctl.h>
+#include <uapi/linux/android/binderfs.h>
#include "binder_internal.h"
@@ -39,14 +41,32 @@
#define INODE_OFFSET 3
#define INTSTRLEN 21
#define BINDERFS_MAX_MINOR (1U << MINORBITS)
-
-static struct vfsmount *binderfs_mnt;
+/* Ensure that the initial ipc namespace always has devices available. */
+#define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4)
static dev_t binderfs_dev;
static DEFINE_MUTEX(binderfs_minors_mutex);
static DEFINE_IDA(binderfs_minors);
/**
+ * binderfs_mount_opts - mount options for binderfs
+ * @max: maximum number of allocatable binderfs binder devices
+ */
+struct binderfs_mount_opts {
+ int max;
+};
+
+enum {
+ Opt_max,
+ Opt_err
+};
+
+static const match_table_t tokens = {
+ { Opt_max, "max=%d" },
+ { Opt_err, NULL }
+};
+
+/**
* binderfs_info - information about a binderfs mount
* @ipc_ns: The ipc namespace the binderfs mount belongs to.
* @control_dentry: This records the dentry of this binderfs mount
@@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors);
* created.
* @root_gid: gid that needs to be used when a new binder device is
* created.
+ * @mount_opts: The mount options in use.
+ * @device_count: The current number of allocated binder devices.
*/
struct binderfs_info {
struct ipc_namespace *ipc_ns;
struct dentry *control_dentry;
kuid_t root_uid;
kgid_t root_gid;
-
+ struct binderfs_mount_opts mount_opts;
+ int device_count;
};
static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
@@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode)
* @userp: buffer to copy information about new device for userspace to
* @req: struct binderfs_device as copied from userspace
*
- * This function allocated a new binder_device and reserves a new minor
+ * This function allocates a new binder_device and reserves a new minor
* number for it.
* Minor numbers are limited and tracked globally in binderfs_minors. The
* function will stash a struct binder_device for the specific binder
@@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
struct binderfs_device *req)
{
int minor, ret;
- struct dentry *dentry, *dup, *root;
+ struct dentry *dentry, *root;
struct binder_device *device;
- size_t name_len = BINDERFS_MAX_NAME + 1;
char *name = NULL;
+ size_t name_len;
struct inode *inode = NULL;
struct super_block *sb = ref_inode->i_sb;
struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+ bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+ bool use_reserve = true;
+#endif
/* Reserve new minor number for the new device. */
mutex_lock(&binderfs_minors_mutex);
- minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
- mutex_unlock(&binderfs_minors_mutex);
- if (minor < 0)
+ if (++info->device_count <= info->mount_opts.max)
+ minor = ida_alloc_max(&binderfs_minors,
+ use_reserve ? BINDERFS_MAX_MINOR :
+ BINDERFS_MAX_MINOR_CAPPED,
+ GFP_KERNEL);
+ else
+ minor = -ENOSPC;
+ if (minor < 0) {
+ --info->device_count;
+ mutex_unlock(&binderfs_minors_mutex);
return minor;
+ }
+ mutex_unlock(&binderfs_minors_mutex);
ret = -ENOMEM;
device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
inode->i_uid = info->root_uid;
inode->i_gid = info->root_gid;
- name = kmalloc(name_len, GFP_KERNEL);
+ req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */
+ name_len = strlen(req->name);
+ /* Make sure to include terminating NUL byte */
+ name = kmemdup(req->name, name_len + 1, GFP_KERNEL);
if (!name)
goto err;
- strscpy(name, req->name, name_len);
-
device->binderfs_inode = inode;
device->context.binder_context_mgr_uid = INVALID_UID;
device->context.name = name;
@@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
root = sb->s_root;
inode_lock(d_inode(root));
- dentry = d_alloc_name(root, name);
- if (!dentry) {
+
+ /* look it up */
+ dentry = lookup_one_len(name, root, name_len);
+ if (IS_ERR(dentry)) {
inode_unlock(d_inode(root));
- ret = -ENOMEM;
+ ret = PTR_ERR(dentry);
goto err;
}
- /* Verify that the name userspace gave us is not already in use. */
- dup = d_lookup(root, &dentry->d_name);
- if (dup) {
- if (d_really_is_positive(dup)) {
- dput(dup);
- dput(dentry);
- inode_unlock(d_inode(root));
- ret = -EEXIST;
- goto err;
- }
- dput(dup);
+ if (d_really_is_positive(dentry)) {
+ /* already exists */
+ dput(dentry);
+ inode_unlock(d_inode(root));
+ ret = -EEXIST;
+ goto err;
}
inode->i_private = device;
- d_add(dentry, inode);
+ d_instantiate(dentry, inode);
fsnotify_create(root->d_inode, dentry);
inode_unlock(d_inode(root));
@@ -187,6 +222,7 @@ err:
kfree(name);
kfree(device);
mutex_lock(&binderfs_minors_mutex);
+ --info->device_count;
ida_free(&binderfs_minors, minor);
mutex_unlock(&binderfs_minors_mutex);
iput(inode);
@@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd,
static void binderfs_evict_inode(struct inode *inode)
{
struct binder_device *device = inode->i_private;
+ struct binderfs_info *info = BINDERFS_I(inode);
clear_inode(inode);
@@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode)
return;
mutex_lock(&binderfs_minors_mutex);
+ --info->device_count;
ida_free(&binderfs_minors, device->miscdev.minor);
mutex_unlock(&binderfs_minors_mutex);
@@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode)
kfree(device);
}
+/**
+ * binderfs_parse_mount_opts - parse binderfs mount options
+ * @data: options to set (can be NULL in which case defaults are used)
+ */
+static int binderfs_parse_mount_opts(char *data,
+ struct binderfs_mount_opts *opts)
+{
+ char *p;
+ opts->max = BINDERFS_MAX_MINOR;
+
+ while ((p = strsep(&data, ",")) != NULL) {
+ substring_t args[MAX_OPT_ARGS];
+ int token;
+ int max_devices;
+
+ if (!*p)
+ continue;
+
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case Opt_max:
+ if (match_int(&args[0], &max_devices) ||
+ (max_devices < 0 ||
+ (max_devices > BINDERFS_MAX_MINOR)))
+ return -EINVAL;
+
+ opts->max = max_devices;
+ break;
+ default:
+ pr_err("Invalid mount options\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int binderfs_remount(struct super_block *sb, int *flags, char *data)
+{
+ struct binderfs_info *info = sb->s_fs_info;
+ return binderfs_parse_mount_opts(data, &info->mount_opts);
+}
+
+static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
+{
+ struct binderfs_info *info;
+
+ info = root->d_sb->s_fs_info;
+ if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
+ seq_printf(seq, ",max=%d", info->mount_opts.max);
+
+ return 0;
+}
+
static const struct super_operations binderfs_super_ops = {
- .statfs = simple_statfs,
- .evict_inode = binderfs_evict_inode,
+ .evict_inode = binderfs_evict_inode,
+ .remount_fs = binderfs_remount,
+ .show_options = binderfs_show_mount_opts,
+ .statfs = simple_statfs,
};
+static inline bool is_binderfs_control_device(const struct dentry *dentry)
+{
+ struct binderfs_info *info = dentry->d_sb->s_fs_info;
+ return info->control_dentry == dentry;
+}
+
static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
- struct inode *inode = d_inode(old_dentry);
-
- /* binderfs doesn't support directories. */
- if (d_is_dir(old_dentry))
+ if (is_binderfs_control_device(old_dentry) ||
+ is_binderfs_control_device(new_dentry))
return -EPERM;
- if (flags & ~RENAME_NOREPLACE)
- return -EINVAL;
-
- if (!simple_empty(new_dentry))
- return -ENOTEMPTY;
-
- if (d_really_is_positive(new_dentry))
- simple_unlink(new_dir, new_dentry);
-
- old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
- new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
-
- return 0;
+ return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
}
static int binderfs_unlink(struct inode *dir, struct dentry *dentry)
{
- /*
- * The control dentry is only ever touched during mount so checking it
- * here should not require us to take lock.
- */
- if (BINDERFS_I(dir)->control_dentry == dentry)
+ if (is_binderfs_control_device(dentry))
return -EPERM;
return simple_unlink(dir, dentry);
@@ -313,13 +395,16 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
struct inode *inode = NULL;
struct dentry *root = sb->s_root;
struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+ bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+ bool use_reserve = true;
+#endif
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (!device)
return -ENOMEM;
- inode_lock(d_inode(root));
-
/* If we have already created a binder-control node, return. */
if (info->control_dentry) {
ret = 0;
@@ -333,7 +418,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
/* Reserve a new minor number for the new device. */
mutex_lock(&binderfs_minors_mutex);
- minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
+ minor = ida_alloc_max(&binderfs_minors,
+ use_reserve ? BINDERFS_MAX_MINOR :
+ BINDERFS_MAX_MINOR_CAPPED,
+ GFP_KERNEL);
mutex_unlock(&binderfs_minors_mutex);
if (minor < 0) {
ret = minor;
@@ -358,12 +446,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
inode->i_private = device;
info->control_dentry = dentry;
d_add(dentry, inode);
- inode_unlock(d_inode(root));
return 0;
out:
- inode_unlock(d_inode(root));
kfree(device);
iput(inode);
@@ -378,12 +464,9 @@ static const struct inode_operations binderfs_dir_inode_operations = {
static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
{
+ int ret;
struct binderfs_info *info;
- int ret = -ENOMEM;
struct inode *inode = NULL;
- struct ipc_namespace *ipc_ns = sb->s_fs_info;
-
- get_ipc_ns(ipc_ns);
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
@@ -405,11 +488,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &binderfs_super_ops;
sb->s_time_gran = 1;
- info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
- if (!info)
- goto err_without_dentry;
+ sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
+ if (!sb->s_fs_info)
+ return -ENOMEM;
+ info = sb->s_fs_info;
+
+ info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+
+ ret = binderfs_parse_mount_opts(data, &info->mount_opts);
+ if (ret)
+ return ret;
- info->ipc_ns = ipc_ns;
info->root_gid = make_kgid(sb->s_user_ns, 0);
if (!gid_valid(info->root_gid))
info->root_gid = GLOBAL_ROOT_GID;
@@ -417,11 +506,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
if (!uid_valid(info->root_uid))
info->root_uid = GLOBAL_ROOT_UID;
- sb->s_fs_info = info;
-
inode = new_inode(sb);
if (!inode)
- goto err_without_dentry;
+ return -ENOMEM;
inode->i_ino = FIRST_INODE;
inode->i_fop = &simple_dir_operations;
@@ -432,79 +519,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_root = d_make_root(inode);
if (!sb->s_root)
- goto err_without_dentry;
-
- ret = binderfs_binder_ctl_create(sb);
- if (ret)
- goto err_with_dentry;
-
- return 0;
-
-err_with_dentry:
- dput(sb->s_root);
- sb->s_root = NULL;
-
-err_without_dentry:
- put_ipc_ns(ipc_ns);
- iput(inode);
- kfree(info);
-
- return ret;
-}
-
-static int binderfs_test_super(struct super_block *sb, void *data)
-{
- struct binderfs_info *info = sb->s_fs_info;
-
- if (info)
- return info->ipc_ns == data;
-
- return 0;
-}
+ return -ENOMEM;
-static int binderfs_set_super(struct super_block *sb, void *data)
-{
- sb->s_fs_info = data;
- return set_anon_super(sb, NULL);
+ return binderfs_binder_ctl_create(sb);
}
static struct dentry *binderfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data)
{
- struct super_block *sb;
- struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-
- if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN))
- return ERR_PTR(-EPERM);
-
- sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super,
- flags, ipc_ns->user_ns, ipc_ns);
- if (IS_ERR(sb))
- return ERR_CAST(sb);
-
- if (!sb->s_root) {
- int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
- if (ret) {
- deactivate_locked_super(sb);
- return ERR_PTR(ret);
- }
-
- sb->s_flags |= SB_ACTIVE;
- }
-
- return dget(sb->s_root);
+ return mount_nodev(fs_type, flags, data, binderfs_fill_super);
}
static void binderfs_kill_super(struct super_block *sb)
{
struct binderfs_info *info = sb->s_fs_info;
+ kill_litter_super(sb);
+
if (info && info->ipc_ns)
put_ipc_ns(info->ipc_ns);
kfree(info);
- kill_litter_super(sb);
}
static struct file_system_type binder_fs_type = {
@@ -514,7 +550,7 @@ static struct file_system_type binder_fs_type = {
.fs_flags = FS_USERNS_MOUNT,
};
-static int __init init_binderfs(void)
+int __init init_binderfs(void)
{
int ret;
@@ -530,15 +566,5 @@ static int __init init_binderfs(void)
return ret;
}
- binderfs_mnt = kern_mount(&binder_fs_type);
- if (IS_ERR(binderfs_mnt)) {
- ret = PTR_ERR(binderfs_mnt);
- binderfs_mnt = NULL;
- unregister_filesystem(&binder_fs_type);
- unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR);
- }
-
return ret;
}
-
-device_initcall(init_binderfs);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4ca7a6b4eaae..8218db17ebdb 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -1091,7 +1091,7 @@ comment "Generic fallback / legacy drivers"
config PATA_ACPI
tristate "ACPI firmware driver for PATA"
- depends on ATA_ACPI && ATA_BMDMA
+ depends on ATA_ACPI && ATA_BMDMA && PCI
help
This option enables an ACPI method driver which drives
motherboard PATA controller interfaces through the ACPI
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index ef356e70e6de..8810475f307a 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -254,6 +254,8 @@ enum {
AHCI_HFLAG_IS_MOBILE = (1 << 25), /* mobile chipset, use
SATA_MOBILE_LPM_POLICY
as default lpm_policy */
+ AHCI_HFLAG_SUSPEND_PHYS = (1 << 26), /* handle PHYs during
+ suspend/resume */
/* ap->flags bits */
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index f9cb51be38eb..d4bba3ace45d 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -28,6 +28,11 @@
#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4))
#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4))
+struct ahci_mvebu_plat_data {
+ int (*plat_config)(struct ahci_host_priv *hpriv);
+ unsigned int flags;
+};
+
static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv,
const struct mbus_dram_target_info *dram)
{
@@ -62,6 +67,35 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
}
+static int ahci_mvebu_armada_380_config(struct ahci_host_priv *hpriv)
+{
+ const struct mbus_dram_target_info *dram;
+ int rc = 0;
+
+ dram = mv_mbus_dram_info();
+ if (dram)
+ ahci_mvebu_mbus_config(hpriv, dram);
+ else
+ rc = -ENODEV;
+
+ ahci_mvebu_regret_option(hpriv);
+
+ return rc;
+}
+
+static int ahci_mvebu_armada_3700_config(struct ahci_host_priv *hpriv)
+{
+ u32 reg;
+
+ writel(0, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR);
+
+ reg = readl(hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+ reg |= BIT(6);
+ writel(reg, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+
+ return 0;
+}
+
/**
* ahci_mvebu_stop_engine
*
@@ -126,13 +160,9 @@ static int ahci_mvebu_resume(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
struct ahci_host_priv *hpriv = host->private_data;
- const struct mbus_dram_target_info *dram;
+ const struct ahci_mvebu_plat_data *pdata = hpriv->plat_data;
- dram = mv_mbus_dram_info();
- if (dram)
- ahci_mvebu_mbus_config(hpriv, dram);
-
- ahci_mvebu_regret_option(hpriv);
+ pdata->plat_config(hpriv);
return ahci_platform_resume_host(&pdev->dev);
}
@@ -154,29 +184,30 @@ static struct scsi_host_template ahci_platform_sht = {
static int ahci_mvebu_probe(struct platform_device *pdev)
{
+ const struct ahci_mvebu_plat_data *pdata;
struct ahci_host_priv *hpriv;
- const struct mbus_dram_target_info *dram;
int rc;
+ pdata = of_device_get_match_data(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
+
hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
+ hpriv->flags |= pdata->flags;
+ hpriv->plat_data = (void *)pdata;
+
rc = ahci_platform_enable_resources(hpriv);
if (rc)
return rc;
hpriv->stop_engine = ahci_mvebu_stop_engine;
- if (of_device_is_compatible(pdev->dev.of_node,
- "marvell,armada-380-ahci")) {
- dram = mv_mbus_dram_info();
- if (!dram)
- return -ENODEV;
-
- ahci_mvebu_mbus_config(hpriv, dram);
- ahci_mvebu_regret_option(hpriv);
- }
+ rc = pdata->plat_config(hpriv);
+ if (rc)
+ goto disable_resources;
rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
&ahci_platform_sht);
@@ -190,18 +221,28 @@ disable_resources:
return rc;
}
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_380_plat_data = {
+ .plat_config = ahci_mvebu_armada_380_config,
+};
+
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = {
+ .plat_config = ahci_mvebu_armada_3700_config,
+ .flags = AHCI_HFLAG_SUSPEND_PHYS,
+};
+
static const struct of_device_id ahci_mvebu_of_match[] = {
- { .compatible = "marvell,armada-380-ahci", },
- { .compatible = "marvell,armada-3700-ahci", },
+ {
+ .compatible = "marvell,armada-380-ahci",
+ .data = &ahci_mvebu_armada_380_plat_data,
+ },
+ {
+ .compatible = "marvell,armada-3700-ahci",
+ .data = &ahci_mvebu_armada_3700_plat_data,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
-/*
- * We currently don't provide power management related operations,
- * since there is no suspend/resume support at the platform level for
- * Armada 38x for the moment.
- */
static struct platform_driver ahci_mvebu_driver = {
.probe = ahci_mvebu_probe,
.remove = ata_platform_remove_one,
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 4b900fc659f7..81b1a3332ed6 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -56,6 +56,12 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
if (rc)
goto disable_phys;
+ rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
+ if (rc) {
+ phy_exit(hpriv->phys[i]);
+ goto disable_phys;
+ }
+
rc = phy_power_on(hpriv->phys[i]);
if (rc) {
phy_exit(hpriv->phys[i]);
@@ -738,6 +744,9 @@ int ahci_platform_suspend_host(struct device *dev)
writel(ctl, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */
+ if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+ ahci_platform_disable_phys(hpriv);
+
return ata_host_suspend(host, PMSG_SUSPEND);
}
EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
@@ -756,6 +765,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
int ahci_platform_resume_host(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
int rc;
if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
@@ -766,6 +776,9 @@ int ahci_platform_resume_host(struct device *dev)
ahci_init_controller(host);
}
+ if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+ ahci_platform_enable_phys(hpriv);
+
ata_host_resume(host);
return 0;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b8c3f9e6af89..adf28788cab5 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4554,6 +4554,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
{ "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM, },
{ "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_HORKAGE_NOLPM, },
+ { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, },
/* devices that don't properly handle queued TRIM commands */
{ "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 8cc9c429ad95..9e7fc302430f 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -915,6 +915,10 @@ static struct scsi_host_template pata_macio_sht = {
.sg_tablesize = MAX_DCMDS,
/* We may not need that strict one */
.dma_boundary = ATA_DMA_BOUNDARY,
+ /* Not sure what the real max is but we know it's less than 64K, let's
+ * use 64K minus 256
+ */
+ .max_segment_size = MAX_DBDMA_SEG,
.slave_configure = pata_macio_slave_config,
};
@@ -1044,11 +1048,6 @@ static int pata_macio_common_init(struct pata_macio_priv *priv,
/* Make sure we have sane initial timings in the cache */
pata_macio_default_timings(priv);
- /* Not sure what the real max is but we know it's less than 64K, let's
- * use 64K minus 256
- */
- dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG);
-
/* Allocate libata host for 1 port */
memset(&pinfo, 0, sizeof(struct ata_port_info));
pmac_macio_calc_timing_masks(priv, &pinfo);
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 4dc528bf8e85..9c1247d42897 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -729,8 +729,8 @@ static int sata_fsl_port_start(struct ata_port *ap)
if (!pp)
return -ENOMEM;
- mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
- GFP_KERNEL);
+ mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+ GFP_KERNEL);
if (!mem) {
kfree(pp);
return -ENOMEM;
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index e0bcf9b2dab0..174e84ce4379 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -245,8 +245,15 @@ struct inic_port_priv {
static struct scsi_host_template inic_sht = {
ATA_BASE_SHT(DRV_NAME),
- .sg_tablesize = LIBATA_MAX_PRD, /* maybe it can be larger? */
- .dma_boundary = INIC_DMA_BOUNDARY,
+ .sg_tablesize = LIBATA_MAX_PRD, /* maybe it can be larger? */
+
+ /*
+ * This controller is braindamaged. dma_boundary is 0xffff like others
+ * but it will lock up the whole machine HARD if 65536 byte PRD entry
+ * is fed. Reduce maximum segment size.
+ */
+ .dma_boundary = INIC_DMA_BOUNDARY,
+ .max_segment_size = 65536 - 512,
};
static const int scr_map[] = {
@@ -868,17 +875,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
- /*
- * This controller is braindamaged. dma_boundary is 0xffff
- * like others but it will lock up the whole machine HARD if
- * 65536 byte PRD entry is fed. Reduce maximum segment size.
- */
- rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512);
- if (rc) {
- dev_err(&pdev->dev, "failed to set the maximum segment size\n");
- return rc;
- }
-
rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
if (rc) {
dev_err(&pdev->dev, "failed to initialize controller\n");
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 29f102dcfec4..211607986134 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -533,9 +533,10 @@ static void he_init_tx_lbfp(struct he_dev *he_dev)
static int he_init_tpdrq(struct he_dev *he_dev)
{
- he_dev->tpdrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
- &he_dev->tpdrq_phys, GFP_KERNEL);
+ he_dev->tpdrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
+ &he_dev->tpdrq_phys,
+ GFP_KERNEL);
if (he_dev->tpdrq_base == NULL) {
hprintk("failed to alloc tpdrq\n");
return -ENOMEM;
@@ -717,7 +718,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev)
instead of '/ 512', use '>> 9' to prevent a call
to divdu3 on x86 platforms
*/
- rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+ rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
if (rate_cps < 10)
rate_cps = 10; /* 2.2.1 minimum payload rate is 10 cps */
@@ -805,9 +806,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
goto out_free_rbpl_virt;
}
- he_dev->rbpl_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
- &he_dev->rbpl_phys, GFP_KERNEL);
+ he_dev->rbpl_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+ &he_dev->rbpl_phys, GFP_KERNEL);
if (he_dev->rbpl_base == NULL) {
hprintk("failed to alloc rbpl_base\n");
goto out_destroy_rbpl_pool;
@@ -844,9 +845,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
/* rx buffer ready queue */
- he_dev->rbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
- &he_dev->rbrq_phys, GFP_KERNEL);
+ he_dev->rbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+ &he_dev->rbrq_phys, GFP_KERNEL);
if (he_dev->rbrq_base == NULL) {
hprintk("failed to allocate rbrq\n");
goto out_free_rbpl;
@@ -868,9 +869,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
/* tx buffer ready queue */
- he_dev->tbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
- &he_dev->tbrq_phys, GFP_KERNEL);
+ he_dev->tbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+ &he_dev->tbrq_phys, GFP_KERNEL);
if (he_dev->tbrq_base == NULL) {
hprintk("failed to allocate tbrq\n");
goto out_free_rbpq_base;
@@ -913,11 +914,9 @@ static int he_init_irq(struct he_dev *he_dev)
/* 2.9.3.5 tail offset for each interrupt queue is located after the
end of the interrupt queue */
- he_dev->irq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- (CONFIG_IRQ_SIZE + 1)
- * sizeof(struct he_irq),
- &he_dev->irq_phys,
- GFP_KERNEL);
+ he_dev->irq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ (CONFIG_IRQ_SIZE + 1) * sizeof(struct he_irq),
+ &he_dev->irq_phys, GFP_KERNEL);
if (he_dev->irq_base == NULL) {
hprintk("failed to allocate irq\n");
return -ENOMEM;
@@ -1464,9 +1463,9 @@ static int he_start(struct atm_dev *dev)
/* host status page */
- he_dev->hsp = dma_zalloc_coherent(&he_dev->pci_dev->dev,
- sizeof(struct he_hsp),
- &he_dev->hsp_phys, GFP_KERNEL);
+ he_dev->hsp = dma_alloc_coherent(&he_dev->pci_dev->dev,
+ sizeof(struct he_hsp),
+ &he_dev->hsp_phys, GFP_KERNEL);
if (he_dev->hsp == NULL) {
hprintk("failed to allocate host status page\n");
return -ENOMEM;
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 6e737142ceaa..43a14579e80e 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -641,8 +641,8 @@ alloc_scq(struct idt77252_dev *card, int class)
scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
if (!scq)
return NULL;
- scq->base = dma_zalloc_coherent(&card->pcidev->dev, SCQ_SIZE,
- &scq->paddr, GFP_KERNEL);
+ scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE,
+ &scq->paddr, GFP_KERNEL);
if (scq->base == NULL) {
kfree(scq);
return NULL;
@@ -971,8 +971,8 @@ init_rsq(struct idt77252_dev *card)
{
struct rsq_entry *rsqe;
- card->rsq.base = dma_zalloc_coherent(&card->pcidev->dev, RSQSIZE,
- &card->rsq.paddr, GFP_KERNEL);
+ card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
+ &card->rsq.paddr, GFP_KERNEL);
if (card->rsq.base == NULL) {
printk("%s: can't allocate RSQ.\n", card->name);
return -1;
@@ -3390,10 +3390,10 @@ static int init_card(struct atm_dev *dev)
writel(0, SAR_REG_GP);
/* Initialize RAW Cell Handle Register */
- card->raw_cell_hnd = dma_zalloc_coherent(&card->pcidev->dev,
- 2 * sizeof(u32),
- &card->raw_cell_paddr,
- GFP_KERNEL);
+ card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev,
+ 2 * sizeof(u32),
+ &card->raw_cell_paddr,
+ GFP_KERNEL);
if (!card->raw_cell_hnd) {
printk("%s: memory allocation failure.\n", card->name);
deinit_card(card);
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index a43276c76fc6..21393ec3b9a4 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -509,7 +509,7 @@ static int ht16k33_remove(struct i2c_client *client)
struct ht16k33_priv *priv = i2c_get_clientdata(client);
struct ht16k33_fbdev *fbdev = &priv->fbdev;
- cancel_delayed_work(&fbdev->work);
+ cancel_delayed_work_sync(&fbdev->work);
unregister_framebuffer(fbdev->info);
framebuffer_release(fbdev->info);
free_page((unsigned long) fbdev->buffer);
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 7a419a7a6235..b405436ee28e 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -60,12 +60,17 @@ struct driver_private {
* @knode_parent - node in sibling list
* @knode_driver - node in driver list
* @knode_bus - node in bus list
+ * @knode_class - node in class list
* @deferred_probe - entry in deferred_probe_list which is used to retry the
* binding of drivers which were unable to get all the resources needed by
* the device; typically because it depends on another driver getting
* probed first.
+ * @async_driver - pointer to device driver awaiting probe via async_probe
* @device - pointer back to the struct device that this structure is
* associated with.
+ * @dead - This device is currently either in the process of or has been
+ * removed from the system. Any asynchronous events scheduled for this
+ * device should exit without taking any action.
*
* Nothing outside of the driver core should ever touch these fields.
*/
@@ -74,8 +79,11 @@ struct device_private {
struct klist_node knode_parent;
struct klist_node knode_driver;
struct klist_node knode_bus;
+ struct klist_node knode_class;
struct list_head deferred_probe;
+ struct device_driver *async_driver;
struct device *device;
+ u8 dead:1;
};
#define to_device_private_parent(obj) \
container_of(obj, struct device_private, knode_parent)
@@ -83,6 +91,8 @@ struct device_private {
container_of(obj, struct device_private, knode_driver)
#define to_device_private_bus(obj) \
container_of(obj, struct device_private, knode_bus)
+#define to_device_private_class(obj) \
+ container_of(obj, struct device_private, knode_class)
/* initialisation functions */
extern int devices_init(void);
@@ -124,6 +134,8 @@ extern int driver_add_groups(struct device_driver *drv,
const struct attribute_group **groups);
extern void driver_remove_groups(struct device_driver *drv,
const struct attribute_group **groups);
+int device_driver_attach(struct device_driver *drv, struct device *dev);
+void device_driver_detach(struct device *dev);
extern char *make_class_name(const char *name, struct kobject *kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index e06a57936cc9..0a58e969f8b7 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -187,11 +187,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == drv) {
- if (dev->parent && dev->bus->need_parent_lock)
- device_lock(dev->parent);
- device_release_driver(dev);
- if (dev->parent && dev->bus->need_parent_lock)
- device_unlock(dev->parent);
+ device_driver_detach(dev);
err = count;
}
put_device(dev);
@@ -214,13 +210,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
- if (dev->parent && bus->need_parent_lock)
- device_lock(dev->parent);
- device_lock(dev);
- err = driver_probe_device(drv, dev);
- device_unlock(dev);
- if (dev->parent && bus->need_parent_lock)
- device_unlock(dev->parent);
+ err = device_driver_attach(drv, dev);
if (err > 0) {
/* success */
@@ -236,12 +226,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
}
static DRIVER_ATTR_IGNORE_LOCKDEP(bind, S_IWUSR, NULL, bind_store);
-static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
+static ssize_t drivers_autoprobe_show(struct bus_type *bus, char *buf)
{
return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
}
-static ssize_t store_drivers_autoprobe(struct bus_type *bus,
+static ssize_t drivers_autoprobe_store(struct bus_type *bus,
const char *buf, size_t count)
{
if (buf[0] == '0')
@@ -251,7 +241,7 @@ static ssize_t store_drivers_autoprobe(struct bus_type *bus,
return count;
}
-static ssize_t store_drivers_probe(struct bus_type *bus,
+static ssize_t drivers_probe_store(struct bus_type *bus,
const char *buf, size_t count)
{
struct device *dev;
@@ -586,9 +576,8 @@ static void remove_bind_files(struct device_driver *drv)
driver_remove_file(drv, &driver_attr_unbind);
}
-static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
-static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
- show_drivers_autoprobe, store_drivers_autoprobe);
+static BUS_ATTR_WO(drivers_probe);
+static BUS_ATTR_RW(drivers_autoprobe);
static int add_probe_files(struct bus_type *bus)
{
@@ -621,17 +610,6 @@ static ssize_t uevent_store(struct device_driver *drv, const char *buf,
}
static DRIVER_ATTR_WO(uevent);
-static void driver_attach_async(void *_drv, async_cookie_t cookie)
-{
- struct device_driver *drv = _drv;
- int ret;
-
- ret = driver_attach(drv);
-
- pr_debug("bus: '%s': driver %s async attach completed: %d\n",
- drv->bus->name, drv->name, ret);
-}
-
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
@@ -664,15 +642,9 @@ int bus_add_driver(struct device_driver *drv)
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
if (drv->bus->p->drivers_autoprobe) {
- if (driver_allows_async_probing(drv)) {
- pr_debug("bus: '%s': probing driver %s asynchronously\n",
- drv->bus->name, drv->name);
- async_schedule(driver_attach_async, drv);
- } else {
- error = driver_attach(drv);
- if (error)
- goto out_unregister;
- }
+ error = driver_attach(drv);
+ if (error)
+ goto out_unregister;
}
module_add_driver(drv->owner, drv);
@@ -774,13 +746,8 @@ EXPORT_SYMBOL_GPL(bus_rescan_devices);
*/
int device_reprobe(struct device *dev)
{
- if (dev->driver) {
- if (dev->parent && dev->bus->need_parent_lock)
- device_lock(dev->parent);
- device_release_driver(dev);
- if (dev->parent && dev->bus->need_parent_lock)
- device_unlock(dev->parent);
- }
+ if (dev->driver)
+ device_driver_detach(dev);
return bus_rescan_devices_helper(dev, NULL);
}
EXPORT_SYMBOL_GPL(device_reprobe);
@@ -838,7 +805,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
rc = kobject_synth_uevent(&bus->p->subsys.kobj, buf, count);
return rc ? rc : count;
}
-static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
+/*
+ * "open code" the old BUS_ATTR() macro here. We want to use BUS_ATTR_WO()
+ * here, but can not use it as earlier in the file we have
+ * DEVICE_ATTR_WO(uevent), which would cause a clash with the with the store
+ * function name.
+ */
+static struct bus_attribute bus_attr_uevent = __ATTR(uevent, S_IWUSR, NULL,
+ bus_uevent_store);
/**
* bus_register - register a driver-core subsystem
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index cf78fa6d470d..a7359535caf5 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -79,8 +79,7 @@ static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].size_prop;
- if (of_property_read_u32(np, propname, &this_leaf->size))
- this_leaf->size = 0;
+ of_property_read_u32(np, propname, &this_leaf->size);
}
/* not cache_line_size() because that's a macro in include/linux/cache.h */
@@ -114,8 +113,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
ct_idx = get_cacheinfo_idx(this_leaf->type);
propname = cache_type_info[ct_idx].nr_sets_prop;
- if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
- this_leaf->number_of_sets = 0;
+ of_property_read_u32(np, propname, &this_leaf->number_of_sets);
}
static void cache_associativity(struct cacheinfo *this_leaf)
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 54def4e02f00..d8a6a5864c2e 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -117,16 +117,22 @@ static void class_put(struct class *cls)
kset_put(&cls->p->subsys);
}
+static struct device *klist_class_to_dev(struct klist_node *n)
+{
+ struct device_private *p = to_device_private_class(n);
+ return p->device;
+}
+
static void klist_class_dev_get(struct klist_node *n)
{
- struct device *dev = container_of(n, struct device, knode_class);
+ struct device *dev = klist_class_to_dev(n);
get_device(dev);
}
static void klist_class_dev_put(struct klist_node *n)
{
- struct device *dev = container_of(n, struct device, knode_class);
+ struct device *dev = klist_class_to_dev(n);
put_device(dev);
}
@@ -277,7 +283,7 @@ void class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
struct klist_node *start_knode = NULL;
if (start)
- start_knode = &start->knode_class;
+ start_knode = &start->p->knode_class;
klist_iter_init_node(&class->p->klist_devices, &iter->ki, start_knode);
iter->type = type;
}
@@ -304,7 +310,7 @@ struct device *class_dev_iter_next(struct class_dev_iter *iter)
knode = klist_next(&iter->ki);
if (!knode)
return NULL;
- dev = container_of(knode, struct device, knode_class);
+ dev = klist_class_to_dev(knode);
if (!iter->type || iter->type == dev->type)
return dev;
}
diff --git a/drivers/base/component.c b/drivers/base/component.c
index ddcea8739c12..532a3a5d8f63 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -16,11 +16,38 @@
#include <linux/slab.h>
#include <linux/debugfs.h>
+/**
+ * DOC: overview
+ *
+ * The component helper allows drivers to collect a pile of sub-devices,
+ * including their bound drivers, into an aggregate driver. Various subsystems
+ * already provide functions to get hold of such components, e.g.
+ * of_clk_get_by_name(). The component helper can be used when such a
+ * subsystem-specific way to find a device is not available: The component
+ * helper fills the niche of aggregate drivers for specific hardware, where
+ * further standardization into a subsystem would not be practical. The common
+ * example is when a logical device (e.g. a DRM display driver) is spread around
+ * the SoC on various components (scanout engines, blending blocks, transcoders
+ * for various outputs and so on).
+ *
+ * The component helper also doesn't solve runtime dependencies, e.g. for system
+ * suspend and resume operations. See also :ref:`device links<device_link>`.
+ *
+ * Components are registered using component_add() and unregistered with
+ * component_del(), usually from the driver's probe and disconnect functions.
+ *
+ * Aggregate drivers first assemble a component match list of what they need
+ * using component_match_add(). This is then registered as an aggregate driver
+ * using component_master_add_with_match(), and unregistered using
+ * component_master_del().
+ */
+
struct component;
struct component_match_array {
void *data;
int (*compare)(struct device *, void *);
+ int (*compare_typed)(struct device *, int, void *);
void (*release)(struct device *, void *);
struct component *component;
bool duplicate;
@@ -48,6 +75,7 @@ struct component {
bool bound;
const struct component_ops *ops;
+ int subcomponent;
struct device *dev;
};
@@ -132,7 +160,7 @@ static struct master *__master_find(struct device *dev,
}
static struct component *find_component(struct master *master,
- int (*compare)(struct device *, void *), void *compare_data)
+ struct component_match_array *mc)
{
struct component *c;
@@ -140,7 +168,11 @@ static struct component *find_component(struct master *master,
if (c->master && c->master != master)
continue;
- if (compare(c->dev, compare_data))
+ if (mc->compare && mc->compare(c->dev, mc->data))
+ return c;
+
+ if (mc->compare_typed &&
+ mc->compare_typed(c->dev, c->subcomponent, mc->data))
return c;
}
@@ -166,7 +198,7 @@ static int find_components(struct master *master)
if (match->compare[i].component)
continue;
- c = find_component(master, mc->compare, mc->data);
+ c = find_component(master, mc);
if (!c) {
ret = -ENXIO;
break;
@@ -301,15 +333,12 @@ static int component_match_realloc(struct device *dev,
return 0;
}
-/*
- * Add a component to be matched, with a release function.
- *
- * The match array is first created or extended if necessary.
- */
-void component_match_add_release(struct device *master,
+static void __component_match_add(struct device *master,
struct component_match **matchptr,
void (*release)(struct device *, void *),
- int (*compare)(struct device *, void *), void *compare_data)
+ int (*compare)(struct device *, void *),
+ int (*compare_typed)(struct device *, int, void *),
+ void *compare_data)
{
struct component_match *match = *matchptr;
@@ -341,13 +370,69 @@ void component_match_add_release(struct device *master,
}
match->compare[match->num].compare = compare;
+ match->compare[match->num].compare_typed = compare_typed;
match->compare[match->num].release = release;
match->compare[match->num].data = compare_data;
match->compare[match->num].component = NULL;
match->num++;
}
+
+/**
+ * component_match_add_release - add a component match entry with release callback
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @release: release function for @compare_data
+ * @compare: compare function to match against all components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * Adds a new component match to the list stored in @matchptr, which the @master
+ * aggregate driver needs to function. The list of component matches pointed to
+ * by @matchptr must be initialized to NULL before adding the first match. This
+ * only matches against components added with component_add().
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions, where upon @release will be called to free any references held by
+ * @compare_data, e.g. when @compare_data is a &device_node that must be
+ * released with of_node_put().
+ *
+ * See also component_match_add() and component_match_add_typed().
+ */
+void component_match_add_release(struct device *master,
+ struct component_match **matchptr,
+ void (*release)(struct device *, void *),
+ int (*compare)(struct device *, void *), void *compare_data)
+{
+ __component_match_add(master, matchptr, release, compare, NULL,
+ compare_data);
+}
EXPORT_SYMBOL(component_match_add_release);
+/**
+ * component_match_add_typed - add a component match entry for a typed component
+ * @master: device with the aggregate driver
+ * @matchptr: pointer to the list of component matches
+ * @compare_typed: compare function to match against all typed components
+ * @compare_data: opaque pointer passed to the @compare function
+ *
+ * Adds a new component match to the list stored in @matchptr, which the @master
+ * aggregate driver needs to function. The list of component matches pointed to
+ * by @matchptr must be initialized to NULL before adding the first match. This
+ * only matches against components added with component_add_typed().
+ *
+ * The allocated match list in @matchptr is automatically released using devm
+ * actions.
+ *
+ * See also component_match_add_release() and component_match_add_typed().
+ */
+void component_match_add_typed(struct device *master,
+ struct component_match **matchptr,
+ int (*compare_typed)(struct device *, int, void *), void *compare_data)
+{
+ __component_match_add(master, matchptr, NULL, NULL, compare_typed,
+ compare_data);
+}
+EXPORT_SYMBOL(component_match_add_typed);
+
static void free_master(struct master *master)
{
struct component_match *match = master->match;
@@ -367,6 +452,18 @@ static void free_master(struct master *master)
kfree(master);
}
+/**
+ * component_master_add_with_match - register an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ * @match: component match list for the aggregate driver
+ *
+ * Registers a new aggregate driver consisting of the components added to @match
+ * by calling one of the component_match_add() functions. Once all components in
+ * @match are available, it will be assembled by calling
+ * &component_master_ops.bind from @ops. Must be unregistered by calling
+ * component_master_del().
+ */
int component_master_add_with_match(struct device *dev,
const struct component_master_ops *ops,
struct component_match *match)
@@ -403,6 +500,15 @@ int component_master_add_with_match(struct device *dev,
}
EXPORT_SYMBOL_GPL(component_master_add_with_match);
+/**
+ * component_master_del - unregister an aggregate driver
+ * @dev: device with the aggregate driver
+ * @ops: callbacks for the aggregate driver
+ *
+ * Unregisters an aggregate driver registered with
+ * component_master_add_with_match(). If necessary the aggregate driver is first
+ * disassembled by calling &component_master_ops.unbind from @ops.
+ */
void component_master_del(struct device *dev,
const struct component_master_ops *ops)
{
@@ -430,6 +536,15 @@ static void component_unbind(struct component *component,
devres_release_group(component->dev, component);
}
+/**
+ * component_unbind_all - unbind all components of an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Unbinds all components of the aggregate @dev by passing @data to their
+ * &component_ops.unbind functions. Should be called from
+ * &component_master_ops.unbind.
+ */
void component_unbind_all(struct device *master_dev, void *data)
{
struct master *master;
@@ -503,6 +618,15 @@ static int component_bind(struct component *component, struct master *master,
return ret;
}
+/**
+ * component_bind_all - bind all components of an aggregate driver
+ * @master_dev: device with the aggregate driver
+ * @data: opaque pointer, passed to all components
+ *
+ * Binds all components of the aggregate @dev by passing @data to their
+ * &component_ops.bind functions. Should be called from
+ * &component_master_ops.bind.
+ */
int component_bind_all(struct device *master_dev, void *data)
{
struct master *master;
@@ -537,7 +661,8 @@ int component_bind_all(struct device *master_dev, void *data)
}
EXPORT_SYMBOL_GPL(component_bind_all);
-int component_add(struct device *dev, const struct component_ops *ops)
+static int __component_add(struct device *dev, const struct component_ops *ops,
+ int subcomponent)
{
struct component *component;
int ret;
@@ -548,6 +673,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
component->ops = ops;
component->dev = dev;
+ component->subcomponent = subcomponent;
dev_dbg(dev, "adding component (ops %ps)\n", ops);
@@ -566,8 +692,66 @@ int component_add(struct device *dev, const struct component_ops *ops)
return ret < 0 ? ret : 0;
}
+
+/**
+ * component_add_typed - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ * @subcomponent: nonzero identifier for subcomponents
+ *
+ * Register a new component for @dev. Functions in @ops will be call when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * @subcomponent must be nonzero and is used to differentiate between multiple
+ * components registerd on the same device @dev. These components are match
+ * using component_match_add_typed().
+ *
+ * The component needs to be unregistered at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add().
+ */
+int component_add_typed(struct device *dev, const struct component_ops *ops,
+ int subcomponent)
+{
+ if (WARN_ON(subcomponent == 0))
+ return -EINVAL;
+
+ return __component_add(dev, ops, subcomponent);
+}
+EXPORT_SYMBOL_GPL(component_add_typed);
+
+/**
+ * component_add - register a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Register a new component for @dev. Functions in @ops will be called when the
+ * aggregate driver is ready to bind the overall driver by calling
+ * component_bind_all(). See also &struct component_ops.
+ *
+ * The component needs to be unregistered at driver unload/disconnect by
+ * calling component_del().
+ *
+ * See also component_add_typed() for a variant that allows multipled different
+ * components on the same device.
+ */
+int component_add(struct device *dev, const struct component_ops *ops)
+{
+ return __component_add(dev, ops, 0);
+}
EXPORT_SYMBOL_GPL(component_add);
+/**
+ * component_del - unregister a component
+ * @dev: component device
+ * @ops: component callbacks
+ *
+ * Unregister a component added with component_add(). If the component is bound
+ * into an aggregate driver, this will force the entire aggregate driver, including
+ * all its components, to be unbound.
+ */
void component_del(struct device *dev, const struct component_ops *ops)
{
struct component *c, *component = NULL;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 0073b09bb99f..4aeaa0c92bda 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -179,10 +179,31 @@ void device_pm_move_to_tail(struct device *dev)
* of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
* ignored.
*
- * If the DL_FLAG_AUTOREMOVE_CONSUMER is set, the link will be removed
- * automatically when the consumer device driver unbinds from it.
- * The combination of both DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_STATELESS
- * set is invalid and will cause NULL to be returned.
+ * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by
+ * the driver core and, in particular, the caller of this function is expected
+ * to drop the reference to the link acquired by it directly.
+ *
+ * If that flag is not set, however, the caller of this function is handing the
+ * management of the link over to the driver core entirely and its return value
+ * can only be used to check whether or not the link is present. In that case,
+ * the DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER device link
+ * flags can be used to indicate to the driver core when the link can be safely
+ * deleted. Namely, setting one of them in @flags indicates to the driver core
+ * that the link is not going to be used (by the given caller of this function)
+ * after unbinding the consumer or supplier driver, respectively, from its
+ * device, so the link can be deleted at that point. If none of them is set,
+ * the link will be maintained until one of the devices pointed to by it (either
+ * the consumer or the supplier) is unregistered.
+ *
+ * Also, if DL_FLAG_STATELESS, DL_FLAG_AUTOREMOVE_CONSUMER and
+ * DL_FLAG_AUTOREMOVE_SUPPLIER are not set in @flags (that is, a persistent
+ * managed device link is being added), the DL_FLAG_AUTOPROBE_CONSUMER flag can
+ * be used to request the driver core to automaticall probe for a consmer
+ * driver after successfully binding a driver to the supplier device.
+ *
+ * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER
+ * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and
+ * will cause NULL to be returned upfront.
*
* A side effect of the link creation is re-ordering of dpm_list and the
* devices_kset list by moving the consumer device and all devices depending
@@ -199,10 +220,22 @@ struct device_link *device_link_add(struct device *consumer,
struct device_link *link;
if (!consumer || !supplier ||
- ((flags & DL_FLAG_STATELESS) &&
- (flags & DL_FLAG_AUTOREMOVE_CONSUMER)))
+ (flags & DL_FLAG_STATELESS &&
+ flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
+ DL_FLAG_AUTOREMOVE_SUPPLIER |
+ DL_FLAG_AUTOPROBE_CONSUMER)) ||
+ (flags & DL_FLAG_AUTOPROBE_CONSUMER &&
+ flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
+ DL_FLAG_AUTOREMOVE_SUPPLIER)))
return NULL;
+ if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) {
+ if (pm_runtime_get_sync(supplier) < 0) {
+ pm_runtime_put_noidle(supplier);
+ return NULL;
+ }
+ }
+
device_links_write_lock();
device_pm_lock();
@@ -217,35 +250,71 @@ struct device_link *device_link_add(struct device *consumer,
goto out;
}
- list_for_each_entry(link, &supplier->links.consumers, s_node)
- if (link->consumer == consumer) {
+ /*
+ * DL_FLAG_AUTOREMOVE_SUPPLIER indicates that the link will be needed
+ * longer than for DL_FLAG_AUTOREMOVE_CONSUMER and setting them both
+ * together doesn't make sense, so prefer DL_FLAG_AUTOREMOVE_SUPPLIER.
+ */
+ if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
+ flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
+
+ list_for_each_entry(link, &supplier->links.consumers, s_node) {
+ if (link->consumer != consumer)
+ continue;
+
+ /*
+ * Don't return a stateless link if the caller wants a stateful
+ * one and vice versa.
+ */
+ if (WARN_ON((flags & DL_FLAG_STATELESS) != (link->flags & DL_FLAG_STATELESS))) {
+ link = NULL;
+ goto out;
+ }
+
+ if (flags & DL_FLAG_PM_RUNTIME) {
+ if (!(link->flags & DL_FLAG_PM_RUNTIME)) {
+ pm_runtime_new_link(consumer);
+ link->flags |= DL_FLAG_PM_RUNTIME;
+ }
+ if (flags & DL_FLAG_RPM_ACTIVE)
+ refcount_inc(&link->rpm_active);
+ }
+
+ if (flags & DL_FLAG_STATELESS) {
kref_get(&link->kref);
goto out;
}
+ /*
+ * If the life time of the link following from the new flags is
+ * longer than indicated by the flags of the existing link,
+ * update the existing link to stay around longer.
+ */
+ if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) {
+ if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
+ link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
+ link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
+ }
+ } else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) {
+ link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
+ DL_FLAG_AUTOREMOVE_SUPPLIER);
+ }
+ goto out;
+ }
+
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
goto out;
+ refcount_set(&link->rpm_active, 1);
+
if (flags & DL_FLAG_PM_RUNTIME) {
- if (flags & DL_FLAG_RPM_ACTIVE) {
- if (pm_runtime_get_sync(supplier) < 0) {
- pm_runtime_put_noidle(supplier);
- kfree(link);
- link = NULL;
- goto out;
- }
- link->rpm_active = true;
- }
+ if (flags & DL_FLAG_RPM_ACTIVE)
+ refcount_inc(&link->rpm_active);
+
pm_runtime_new_link(consumer);
- /*
- * If the link is being added by the consumer driver at probe
- * time, balance the decrementation of the supplier's runtime PM
- * usage counter after consumer probe in driver_probe_device().
- */
- if (consumer->links.status == DL_DEV_PROBING)
- pm_runtime_get_noresume(supplier);
}
+
get_device(supplier);
link->supplier = supplier;
INIT_LIST_HEAD(&link->s_node);
@@ -260,17 +329,26 @@ struct device_link *device_link_add(struct device *consumer,
link->status = DL_STATE_NONE;
} else {
switch (supplier->links.status) {
- case DL_DEV_DRIVER_BOUND:
+ case DL_DEV_PROBING:
switch (consumer->links.status) {
case DL_DEV_PROBING:
/*
- * Some callers expect the link creation during
- * consumer driver probe to resume the supplier
- * even without DL_FLAG_RPM_ACTIVE.
+ * A consumer driver can create a link to a
+ * supplier that has not completed its probing
+ * yet as long as it knows that the supplier is
+ * already functional (for example, it has just
+ * acquired some resources from the supplier).
*/
- if (flags & DL_FLAG_PM_RUNTIME)
- pm_runtime_resume(supplier);
-
+ link->status = DL_STATE_CONSUMER_PROBE;
+ break;
+ default:
+ link->status = DL_STATE_DORMANT;
+ break;
+ }
+ break;
+ case DL_DEV_DRIVER_BOUND:
+ switch (consumer->links.status) {
+ case DL_DEV_PROBING:
link->status = DL_STATE_CONSUMER_PROBE;
break;
case DL_DEV_DRIVER_BOUND:
@@ -291,6 +369,14 @@ struct device_link *device_link_add(struct device *consumer,
}
/*
+ * Some callers expect the link creation during consumer driver probe to
+ * resume the supplier even without DL_FLAG_RPM_ACTIVE.
+ */
+ if (link->status == DL_STATE_CONSUMER_PROBE &&
+ flags & DL_FLAG_PM_RUNTIME)
+ pm_runtime_resume(supplier);
+
+ /*
* Move the consumer and all of the devices depending on it to the end
* of dpm_list and the devices_kset list.
*
@@ -302,17 +388,24 @@ struct device_link *device_link_add(struct device *consumer,
list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);
- dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
+ dev_dbg(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
out:
device_pm_unlock();
device_links_write_unlock();
+
+ if ((flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) && !link)
+ pm_runtime_put(supplier);
+
return link;
}
EXPORT_SYMBOL_GPL(device_link_add);
static void device_link_free(struct device_link *link)
{
+ while (refcount_dec_not_one(&link->rpm_active))
+ pm_runtime_put(link->supplier);
+
put_device(link->consumer);
put_device(link->supplier);
kfree(link);
@@ -328,8 +421,8 @@ static void __device_link_del(struct kref *kref)
{
struct device_link *link = container_of(kref, struct device_link, kref);
- dev_info(link->consumer, "Dropping the link to %s\n",
- dev_name(link->supplier));
+ dev_dbg(link->consumer, "Dropping the link to %s\n",
+ dev_name(link->supplier));
if (link->flags & DL_FLAG_PM_RUNTIME)
pm_runtime_drop_link(link->consumer);
@@ -355,8 +448,16 @@ static void __device_link_del(struct kref *kref)
}
#endif /* !CONFIG_SRCU */
+static void device_link_put_kref(struct device_link *link)
+{
+ if (link->flags & DL_FLAG_STATELESS)
+ kref_put(&link->kref, __device_link_del);
+ else
+ WARN(1, "Unable to drop a managed device link reference\n");
+}
+
/**
- * device_link_del - Delete a link between two devices.
+ * device_link_del - Delete a stateless link between two devices.
* @link: Device link to delete.
*
* The caller must ensure proper synchronization of this function with runtime
@@ -368,14 +469,14 @@ void device_link_del(struct device_link *link)
{
device_links_write_lock();
device_pm_lock();
- kref_put(&link->kref, __device_link_del);
+ device_link_put_kref(link);
device_pm_unlock();
device_links_write_unlock();
}
EXPORT_SYMBOL_GPL(device_link_del);
/**
- * device_link_remove - remove a link between two devices.
+ * device_link_remove - Delete a stateless link between two devices.
* @consumer: Consumer end of the link.
* @supplier: Supplier end of the link.
*
@@ -394,7 +495,7 @@ void device_link_remove(void *consumer, struct device *supplier)
list_for_each_entry(link, &supplier->links.consumers, s_node) {
if (link->consumer == consumer) {
- kref_put(&link->kref, __device_link_del);
+ device_link_put_kref(link);
break;
}
}
@@ -474,8 +575,21 @@ void device_links_driver_bound(struct device *dev)
if (link->flags & DL_FLAG_STATELESS)
continue;
+ /*
+ * Links created during consumer probe may be in the "consumer
+ * probe" state to start with if the supplier is still probing
+ * when they are created and they may become "active" if the
+ * consumer probe returns first. Skip them here.
+ */
+ if (link->status == DL_STATE_CONSUMER_PROBE ||
+ link->status == DL_STATE_ACTIVE)
+ continue;
+
WARN_ON(link->status != DL_STATE_DORMANT);
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
+
+ if (link->flags & DL_FLAG_AUTOPROBE_CONSUMER)
+ driver_deferred_probe_add(link->consumer);
}
list_for_each_entry(link, &dev->links.suppliers, c_node) {
@@ -512,18 +626,49 @@ static void __device_links_no_driver(struct device *dev)
continue;
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
- kref_put(&link->kref, __device_link_del);
- else if (link->status != DL_STATE_SUPPLIER_UNBIND)
+ __device_link_del(&link->kref);
+ else if (link->status == DL_STATE_CONSUMER_PROBE ||
+ link->status == DL_STATE_ACTIVE)
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
}
dev->links.status = DL_DEV_NO_DRIVER;
}
+/**
+ * device_links_no_driver - Update links after failing driver probe.
+ * @dev: Device whose driver has just failed to probe.
+ *
+ * Clean up leftover links to consumers for @dev and invoke
+ * %__device_links_no_driver() to update links to suppliers for it as
+ * appropriate.
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
void device_links_no_driver(struct device *dev)
{
+ struct device_link *link;
+
device_links_write_lock();
+
+ list_for_each_entry(link, &dev->links.consumers, s_node) {
+ if (link->flags & DL_FLAG_STATELESS)
+ continue;
+
+ /*
+ * The probe has failed, so if the status of the link is
+ * "consumer probe" or "active", it must have been added by
+ * a probing consumer while this device was still probing.
+ * Change its state to "dormant", as it represents a valid
+ * relationship, but it is not functionally meaningful.
+ */
+ if (link->status == DL_STATE_CONSUMER_PROBE ||
+ link->status == DL_STATE_ACTIVE)
+ WRITE_ONCE(link->status, DL_STATE_DORMANT);
+ }
+
__device_links_no_driver(dev);
+
device_links_write_unlock();
}
@@ -539,11 +684,11 @@ void device_links_no_driver(struct device *dev)
*/
void device_links_driver_cleanup(struct device *dev)
{
- struct device_link *link;
+ struct device_link *link, *ln;
device_links_write_lock();
- list_for_each_entry(link, &dev->links.consumers, s_node) {
+ list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
if (link->flags & DL_FLAG_STATELESS)
continue;
@@ -557,7 +702,7 @@ void device_links_driver_cleanup(struct device *dev)
*/
if (link->status == DL_STATE_SUPPLIER_UNBIND &&
link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
- kref_put(&link->kref, __device_link_del);
+ __device_link_del(&link->kref);
WRITE_ONCE(link->status, DL_STATE_DORMANT);
}
@@ -1966,7 +2111,7 @@ int device_add(struct device *dev)
if (dev->class) {
mutex_lock(&dev->class->p->mutex);
/* tie the class to the device */
- klist_add_tail(&dev->knode_class,
+ klist_add_tail(&dev->p->knode_class,
&dev->class->p->klist_devices);
/* notify any interfaces that the device is here */
@@ -2080,6 +2225,17 @@ void device_del(struct device *dev)
struct kobject *glue_dir = NULL;
struct class_interface *class_intf;
+ /*
+ * Hold the device lock and set the "dead" flag to guarantee that
+ * the update behavior is consistent with the other bitfields near
+ * it and that we cannot have an asynchronous probe routine trying
+ * to run while we are tearing out the bus/class/sysfs from
+ * underneath the device.
+ */
+ device_lock(dev);
+ dev->p->dead = true;
+ device_unlock(dev);
+
/* Notify clients of device removal. This call must come
* before dpm_sysfs_remove().
*/
@@ -2105,7 +2261,7 @@ void device_del(struct device *dev)
if (class_intf->remove_dev)
class_intf->remove_dev(dev, class_intf);
/* remove the device from the class list */
- klist_del(&dev->knode_class);
+ klist_del(&dev->p->knode_class);
mutex_unlock(&dev->class->p->mutex);
}
device_remove_file(dev, &dev_attr_uevent);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index eb9443d5bae1..668139cfa664 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -409,6 +409,7 @@ static void device_create_release(struct device *dev)
kfree(dev);
}
+__printf(4, 0)
static struct device *
__cpu_device_create(struct device *parent, void *drvdata,
const struct attribute_group **groups,
@@ -427,6 +428,7 @@ __cpu_device_create(struct device *parent, void *drvdata,
dev->parent = parent;
dev->groups = groups;
dev->release = device_create_release;
+ device_set_pm_not_required(dev);
dev_set_drvdata(dev, drvdata);
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 8ac10af17c00..a823f469e53f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -57,6 +57,10 @@ static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
static struct dentry *deferred_devices;
static bool initcalls_done;
+/* Save the async probe drivers' name from kernel cmdline */
+#define ASYNC_DRV_NAMES_MAX_LEN 256
+static char async_probe_drv_names[ASYNC_DRV_NAMES_MAX_LEN];
+
/*
* In some cases, like suspend to RAM or hibernation, It might be reasonable
* to prohibit probing of devices as it could be unsafe.
@@ -116,7 +120,7 @@ static void deferred_probe_work_func(struct work_struct *work)
}
static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func);
-static void driver_deferred_probe_add(struct device *dev)
+void driver_deferred_probe_add(struct device *dev)
{
mutex_lock(&deferred_probe_mutex);
if (list_empty(&dev->p->deferred_probe)) {
@@ -674,6 +678,23 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
return ret;
}
+static inline bool cmdline_requested_async_probing(const char *drv_name)
+{
+ return parse_option_str(async_probe_drv_names, drv_name);
+}
+
+/* The option format is "driver_async_probe=drv_name1,drv_name2,..." */
+static int __init save_async_options(char *buf)
+{
+ if (strlen(buf) >= ASYNC_DRV_NAMES_MAX_LEN)
+ printk(KERN_WARNING
+ "Too long list of driver names for 'driver_async_probe'!\n");
+
+ strlcpy(async_probe_drv_names, buf, ASYNC_DRV_NAMES_MAX_LEN);
+ return 0;
+}
+__setup("driver_async_probe=", save_async_options);
+
bool driver_allows_async_probing(struct device_driver *drv)
{
switch (drv->probe_type) {
@@ -684,6 +705,9 @@ bool driver_allows_async_probing(struct device_driver *drv)
return false;
default:
+ if (cmdline_requested_async_probing(drv->name))
+ return true;
+
if (module_requested_async_probing(drv->owner))
return true;
@@ -731,15 +755,6 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
bool async_allowed;
int ret;
- /*
- * Check if device has already been claimed. This may
- * happen with driver loading, device discovery/registration,
- * and deferred probe processing happens all at once with
- * multiple threads.
- */
- if (dev->driver)
- return -EBUSY;
-
ret = driver_match_device(drv, dev);
if (ret == 0) {
/* no match */
@@ -774,6 +789,15 @@ static void __device_attach_async_helper(void *_dev, async_cookie_t cookie)
device_lock(dev);
+ /*
+ * Check if device has already been removed or claimed. This may
+ * happen with driver loading, device discovery/registration,
+ * and deferred probe processing happens all at once with
+ * multiple threads.
+ */
+ if (dev->p->dead || dev->driver)
+ goto out_unlock;
+
if (dev->parent)
pm_runtime_get_sync(dev->parent);
@@ -784,7 +808,7 @@ static void __device_attach_async_helper(void *_dev, async_cookie_t cookie)
if (dev->parent)
pm_runtime_put(dev->parent);
-
+out_unlock:
device_unlock(dev);
put_device(dev);
@@ -829,7 +853,7 @@ static int __device_attach(struct device *dev, bool allow_async)
*/
dev_dbg(dev, "scheduling asynchronous probe\n");
get_device(dev);
- async_schedule(__device_attach_async_helper, dev);
+ async_schedule_dev(__device_attach_async_helper, dev);
} else {
pm_request_idle(dev);
}
@@ -867,6 +891,88 @@ void device_initial_probe(struct device *dev)
__device_attach(dev, true);
}
+/*
+ * __device_driver_lock - acquire locks needed to manipulate dev->drv
+ * @dev: Device we will update driver info for
+ * @parent: Parent device. Needed if the bus requires parent lock
+ *
+ * This function will take the required locks for manipulating dev->drv.
+ * Normally this will just be the @dev lock, but when called for a USB
+ * interface, @parent lock will be held as well.
+ */
+static void __device_driver_lock(struct device *dev, struct device *parent)
+{
+ if (parent && dev->bus->need_parent_lock)
+ device_lock(parent);
+ device_lock(dev);
+}
+
+/*
+ * __device_driver_unlock - release locks needed to manipulate dev->drv
+ * @dev: Device we will update driver info for
+ * @parent: Parent device. Needed if the bus requires parent lock
+ *
+ * This function will release the required locks for manipulating dev->drv.
+ * Normally this will just be the the @dev lock, but when called for a
+ * USB interface, @parent lock will be released as well.
+ */
+static void __device_driver_unlock(struct device *dev, struct device *parent)
+{
+ device_unlock(dev);
+ if (parent && dev->bus->need_parent_lock)
+ device_unlock(parent);
+}
+
+/**
+ * device_driver_attach - attach a specific driver to a specific device
+ * @drv: Driver to attach
+ * @dev: Device to attach it to
+ *
+ * Manually attach driver to a device. Will acquire both @dev lock and
+ * @dev->parent lock if needed.
+ */
+int device_driver_attach(struct device_driver *drv, struct device *dev)
+{
+ int ret = 0;
+
+ __device_driver_lock(dev, dev->parent);
+
+ /*
+ * If device has been removed or someone has already successfully
+ * bound a driver before us just skip the driver probe call.
+ */
+ if (!dev->p->dead && !dev->driver)
+ ret = driver_probe_device(drv, dev);
+
+ __device_driver_unlock(dev, dev->parent);
+
+ return ret;
+}
+
+static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
+{
+ struct device *dev = _dev;
+ struct device_driver *drv;
+ int ret = 0;
+
+ __device_driver_lock(dev, dev->parent);
+
+ drv = dev->p->async_driver;
+
+ /*
+ * If device has been removed or someone has already successfully
+ * bound a driver before us just skip the driver probe call.
+ */
+ if (!dev->p->dead && !dev->driver)
+ ret = driver_probe_device(drv, dev);
+
+ __device_driver_unlock(dev, dev->parent);
+
+ dev_dbg(dev, "driver %s async attach completed: %d\n", drv->name, ret);
+
+ put_device(dev);
+}
+
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
@@ -894,14 +1000,26 @@ static int __driver_attach(struct device *dev, void *data)
return ret;
} /* ret > 0 means positive match */
- if (dev->parent && dev->bus->need_parent_lock)
- device_lock(dev->parent);
- device_lock(dev);
- if (!dev->driver)
- driver_probe_device(drv, dev);
- device_unlock(dev);
- if (dev->parent && dev->bus->need_parent_lock)
- device_unlock(dev->parent);
+ if (driver_allows_async_probing(drv)) {
+ /*
+ * Instead of probing the device synchronously we will
+ * probe it asynchronously to allow for more parallelism.
+ *
+ * We only take the device lock here in order to guarantee
+ * that the dev->driver and async_driver fields are protected
+ */
+ dev_dbg(dev, "probing driver %s asynchronously\n", drv->name);
+ device_lock(dev);
+ if (!dev->driver) {
+ get_device(dev);
+ dev->p->async_driver = drv;
+ async_schedule_dev(__driver_attach_async_helper, dev);
+ }
+ device_unlock(dev);
+ return 0;
+ }
+
+ device_driver_attach(drv, dev);
return 0;
}
@@ -932,15 +1050,11 @@ static void __device_release_driver(struct device *dev, struct device *parent)
drv = dev->driver;
if (drv) {
while (device_links_busy(dev)) {
- device_unlock(dev);
- if (parent && dev->bus->need_parent_lock)
- device_unlock(parent);
+ __device_driver_unlock(dev, parent);
device_links_unbind_consumers(dev);
- if (parent && dev->bus->need_parent_lock)
- device_lock(parent);
- device_lock(dev);
+ __device_driver_lock(dev, parent);
/*
* A concurrent invocation of the same function might
* have released the driver successfully while this one
@@ -968,9 +1082,9 @@ static void __device_release_driver(struct device *dev, struct device *parent)
drv->remove(dev);
device_links_driver_cleanup(dev);
- arch_teardown_dma_ops(dev);
devres_release_all(dev);
+ arch_teardown_dma_ops(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
@@ -993,16 +1107,12 @@ void device_release_driver_internal(struct device *dev,
struct device_driver *drv,
struct device *parent)
{
- if (parent && dev->bus->need_parent_lock)
- device_lock(parent);
+ __device_driver_lock(dev, parent);
- device_lock(dev);
if (!drv || drv == dev->driver)
__device_release_driver(dev, parent);
- device_unlock(dev);
- if (parent && dev->bus->need_parent_lock)
- device_unlock(parent);
+ __device_driver_unlock(dev, parent);
}
/**
@@ -1028,6 +1138,18 @@ void device_release_driver(struct device *dev)
EXPORT_SYMBOL_GPL(device_release_driver);
/**
+ * device_driver_detach - detach driver from a specific device
+ * @dev: device to detach driver from
+ *
+ * Detach driver from device. Will acquire both @dev lock and @dev->parent
+ * lock if needed.
+ */
+void device_driver_detach(struct device *dev)
+{
+ device_release_driver_internal(dev, NULL, dev->parent);
+}
+
+/**
* driver_detach - detach driver from all devices it controls.
* @drv: driver.
*/
diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c
index d427e806cd73..04db9ae235e4 100644
--- a/drivers/base/devcon.c
+++ b/drivers/base/devcon.c
@@ -7,10 +7,37 @@
*/
#include <linux/device.h>
+#include <linux/property.h>
static DEFINE_MUTEX(devcon_lock);
static LIST_HEAD(devcon_list);
+typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep,
+ void *data);
+
+static void *
+fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
+ void *data, devcon_match_fn_t match)
+{
+ struct device_connection con = { .id = con_id };
+ struct fwnode_handle *ep;
+ void *ret;
+
+ fwnode_graph_for_each_endpoint(fwnode, ep) {
+ con.fwnode = fwnode_graph_get_remote_port_parent(ep);
+ if (!fwnode_device_is_available(con.fwnode))
+ continue;
+
+ ret = match(&con, -1, data);
+ fwnode_handle_put(con.fwnode);
+ if (ret) {
+ fwnode_handle_put(ep);
+ return ret;
+ }
+ }
+ return NULL;
+}
+
/**
* device_connection_find_match - Find physical connection to a device
* @dev: Device with the connection
@@ -23,10 +50,9 @@ static LIST_HEAD(devcon_list);
* caller is expecting to be returned.
*/
void *device_connection_find_match(struct device *dev, const char *con_id,
- void *data,
- void *(*match)(struct device_connection *con,
- int ep, void *data))
+ void *data, devcon_match_fn_t match)
{
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
const char *devname = dev_name(dev);
struct device_connection *con;
void *ret = NULL;
@@ -35,6 +61,12 @@ void *device_connection_find_match(struct device *dev, const char *con_id,
if (!match)
return NULL;
+ if (fwnode) {
+ ret = fwnode_graph_devcon_match(fwnode, con_id, data, match);
+ if (ret)
+ return ret;
+ }
+
mutex_lock(&devcon_lock);
list_for_each_entry(con, &devcon_list, list) {
@@ -75,12 +107,36 @@ static struct bus_type *generic_match_buses[] = {
NULL,
};
+static int device_fwnode_match(struct device *dev, void *fwnode)
+{
+ return dev_fwnode(dev) == fwnode;
+}
+
+static void *device_connection_fwnode_match(struct device_connection *con)
+{
+ struct bus_type *bus;
+ struct device *dev;
+
+ for (bus = generic_match_buses[0]; bus; bus++) {
+ dev = bus_find_device(bus, NULL, (void *)con->fwnode,
+ device_fwnode_match);
+ if (dev && !strncmp(dev_name(dev), con->id, strlen(con->id)))
+ return dev;
+
+ put_device(dev);
+ }
+ return NULL;
+}
+
/* This tries to find the device from the most common bus types by name. */
static void *generic_match(struct device_connection *con, int ep, void *data)
{
struct bus_type *bus;
struct device *dev;
+ if (con->fwnode)
+ return device_connection_fwnode_match(con);
+
for (bus = generic_match_buses[0]; bus; bus++) {
dev = bus_find_device_by_name(bus, NULL, con->endpoint[ep]);
if (dev)
diff --git a/drivers/base/firmware_loader/Makefile b/drivers/base/firmware_loader/Makefile
index a97eeb0be1d8..0b2dfa6259c9 100644
--- a/drivers/base/firmware_loader/Makefile
+++ b/drivers/base/firmware_loader/Makefile
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for the Linux firmware loader
-obj-y := fallback_table.o
+obj-$(CONFIG_FW_LOADER_USER_HELPER) += fallback_table.o
obj-$(CONFIG_FW_LOADER) += firmware_class.o
firmware_class-objs := main.o
firmware_class-$(CONFIG_FW_LOADER_USER_HELPER) += fallback.o
+
+obj-y += builtin/
diff --git a/drivers/base/firmware_loader/builtin/.gitignore b/drivers/base/firmware_loader/builtin/.gitignore
new file mode 100644
index 000000000000..9c8bdb9fdcc3
--- /dev/null
+++ b/drivers/base/firmware_loader/builtin/.gitignore
@@ -0,0 +1 @@
+*.gen.S
diff --git a/drivers/base/firmware_loader/builtin/Makefile b/drivers/base/firmware_loader/builtin/Makefile
new file mode 100644
index 000000000000..37e5ae387400
--- /dev/null
+++ b/drivers/base/firmware_loader/builtin/Makefile
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Create $(fwdir) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a
+# leading /, it's relative to $(srctree).
+fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR))
+fwdir := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir))
+
+obj-y := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE)))
+
+FWNAME = $(patsubst $(obj)/%.gen.S,%,$@)
+FWSTR = $(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME))))
+ASM_WORD = $(if $(CONFIG_64BIT),.quad,.long)
+ASM_ALIGN = $(if $(CONFIG_64BIT),3,2)
+PROGBITS = $(if $(CONFIG_ARM),%,@)progbits
+
+filechk_fwbin = \
+ echo "/* Generated by $(src)/Makefile */" ;\
+ echo " .section .rodata" ;\
+ echo " .p2align $(ASM_ALIGN)" ;\
+ echo "_fw_$(FWSTR)_bin:" ;\
+ echo " .incbin \"$(fwdir)/$(FWNAME)\"" ;\
+ echo "_fw_end:" ;\
+ echo " .section .rodata.str,\"aMS\",$(PROGBITS),1" ;\
+ echo " .p2align $(ASM_ALIGN)" ;\
+ echo "_fw_$(FWSTR)_name:" ;\
+ echo " .string \"$(FWNAME)\"" ;\
+ echo " .section .builtin_fw,\"a\",$(PROGBITS)" ;\
+ echo " .p2align $(ASM_ALIGN)" ;\
+ echo " $(ASM_WORD) _fw_$(FWSTR)_name" ;\
+ echo " $(ASM_WORD) _fw_$(FWSTR)_bin" ;\
+ echo " $(ASM_WORD) _fw_end - _fw_$(FWSTR)_bin"
+
+$(obj)/%.gen.S: FORCE
+ $(call filechk,fwbin)
+
+# The .o files depend on the binaries directly; the .S files don't.
+$(addprefix $(obj)/, $(obj-y)): $(obj)/%.gen.o: $(fwdir)/%
+
+targets := $(patsubst $(obj)/%,%, \
+ $(shell find $(obj) -name \*.gen.S 2>/dev/null))
diff --git a/drivers/base/firmware_loader/fallback_table.c b/drivers/base/firmware_loader/fallback_table.c
index 7428659d8df9..776dd69cf5be 100644
--- a/drivers/base/firmware_loader/fallback_table.c
+++ b/drivers/base/firmware_loader/fallback_table.c
@@ -16,9 +16,6 @@
* firmware fallback configuration table
*/
-/* Module or buit-in */
-#ifdef CONFIG_FW_LOADER_USER_HELPER
-
static unsigned int zero;
static unsigned int one = 1;
@@ -51,5 +48,3 @@ struct ctl_table firmware_config_table[] = {
{ }
};
EXPORT_SYMBOL_GPL(firmware_config_table);
-
-#endif
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 8e9213b36e31..7eaaf5ee5ba6 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -328,12 +328,12 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
rc = kernel_read_file_from_path(path, &fw_priv->data, &size,
msize, id);
if (rc) {
- if (rc == -ENOENT)
- dev_dbg(device, "loading %s failed with error %d\n",
- path, rc);
- else
+ if (rc != -ENOENT)
dev_warn(device, "loading %s failed with error %d\n",
path, rc);
+ else
+ dev_dbg(device, "loading %s failed for no such file or directory.\n",
+ path);
continue;
}
dev_dbg(device, "direct-loading %s\n", fw_priv->fw_name);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 1c958eb33ef4..4e45ac21d672 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -127,7 +127,20 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS);
}
- return r ? r->start : -ENXIO;
+ if (r)
+ return r->start;
+
+ /*
+ * For the index 0 interrupt, allow falling back to GpioInt
+ * resources. While a device could have both Interrupt and GpioInt
+ * resources, making this fallback ambiguous, in many common cases
+ * the device will only expose one IRQ, and this fallback
+ * allows a common code path across either kind of resource.
+ */
+ if (num == 0 && has_acpi_companion(&dev->dev))
+ return acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+
+ return -ENXIO;
#endif
}
EXPORT_SYMBOL_GPL(platform_get_irq);
@@ -508,10 +521,12 @@ struct platform_device *platform_device_register_full(
pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
if (!pdev)
- goto err_alloc;
+ return ERR_PTR(-ENOMEM);
pdev->dev.parent = pdevinfo->parent;
pdev->dev.fwnode = pdevinfo->fwnode;
+ pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
+ pdev->dev.of_node_reused = pdevinfo->of_node_reused;
if (pdevinfo->dma_mask) {
/*
@@ -553,8 +568,6 @@ struct platform_device *platform_device_register_full(
err:
ACPI_COMPANION_SET(&pdev->dev, NULL);
kfree(pdev->dev.dma_mask);
-
-err_alloc:
platform_device_put(pdev);
return ERR_PTR(ret);
}
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 5a42ae4078c2..365ad751ce0f 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -65,10 +65,15 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
if (IS_ERR(ce->clk)) {
ce->status = PCE_STATUS_ERROR;
} else {
- clk_prepare(ce->clk);
- ce->status = PCE_STATUS_ACQUIRED;
- dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n",
- ce->clk, ce->con_id);
+ if (clk_prepare(ce->clk)) {
+ ce->status = PCE_STATUS_ERROR;
+ dev_err(dev, "clk_prepare() failed\n");
+ } else {
+ ce->status = PCE_STATUS_ACQUIRED;
+ dev_dbg(dev,
+ "Clock %pC con_id %s managed by runtime PM.\n",
+ ce->clk, ce->con_id);
+ }
}
}
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index b413951c6abc..22aedb28aad7 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -160,7 +160,7 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_id);
* For a detailed function description, see dev_pm_domain_attach_by_id().
*/
struct device *dev_pm_domain_attach_by_name(struct device *dev,
- char *name)
+ const char *name)
{
if (dev->pm_domain)
return ERR_PTR(-EEXIST);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 500de1dee967..2c334c01fc43 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2483,7 +2483,7 @@ EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_id);
* power-domain-names DT property. For further description see
* genpd_dev_pm_attach_by_id().
*/
-struct device *genpd_dev_pm_attach_by_name(struct device *dev, char *name)
+struct device *genpd_dev_pm_attach_by_name(struct device *dev, const char *name)
{
int index;
@@ -2948,18 +2948,11 @@ static int __init genpd_debug_init(void)
genpd_debugfs_dir = debugfs_create_dir("pm_genpd", NULL);
- if (!genpd_debugfs_dir)
- return -ENOMEM;
-
- d = debugfs_create_file("pm_genpd_summary", S_IRUGO,
- genpd_debugfs_dir, NULL, &summary_fops);
- if (!d)
- return -ENOMEM;
+ debugfs_create_file("pm_genpd_summary", S_IRUGO, genpd_debugfs_dir,
+ NULL, &summary_fops);
list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
d = debugfs_create_dir(genpd->name, genpd_debugfs_dir);
- if (!d)
- return -ENOMEM;
debugfs_create_file("current_state", 0444,
d, genpd, &status_fops);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index a690fd400260..5a8149829ab3 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -32,6 +32,7 @@
#include <trace/events/power.h>
#include <linux/cpufreq.h>
#include <linux/cpuidle.h>
+#include <linux/devfreq.h>
#include <linux/timer.h>
#include "../base.h"
@@ -123,6 +124,10 @@ void device_pm_unlock(void)
*/
void device_pm_add(struct device *dev)
{
+ /* Skip PM setup/initialization. */
+ if (device_pm_not_required(dev))
+ return;
+
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
device_pm_check_callbacks(dev);
@@ -141,6 +146,9 @@ void device_pm_add(struct device *dev)
*/
void device_pm_remove(struct device *dev)
{
+ if (device_pm_not_required(dev))
+ return;
+
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
complete_all(&dev->power.completion);
@@ -726,7 +734,7 @@ void dpm_noirq_resume_devices(pm_message_t state)
reinit_completion(&dev->power.completion);
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_resume_noirq, dev);
+ async_schedule_dev(async_resume_noirq, dev);
}
}
@@ -883,7 +891,7 @@ void dpm_resume_early(pm_message_t state)
reinit_completion(&dev->power.completion);
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_resume_early, dev);
+ async_schedule_dev(async_resume_early, dev);
}
}
@@ -1047,7 +1055,7 @@ void dpm_resume(pm_message_t state)
reinit_completion(&dev->power.completion);
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_resume, dev);
+ async_schedule_dev(async_resume, dev);
}
}
@@ -1078,6 +1086,7 @@ void dpm_resume(pm_message_t state)
dpm_show_time(starttime, state, 0, NULL);
cpufreq_resume();
+ devfreq_resume();
trace_suspend_resume(TPS("dpm_resume"), state.event, false);
}
@@ -1366,7 +1375,7 @@ static int device_suspend_noirq(struct device *dev)
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_suspend_noirq, dev);
+ async_schedule_dev(async_suspend_noirq, dev);
return 0;
}
return __device_suspend_noirq(dev, pm_transition, false);
@@ -1569,7 +1578,7 @@ static int device_suspend_late(struct device *dev)
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_suspend_late, dev);
+ async_schedule_dev(async_suspend_late, dev);
return 0;
}
@@ -1739,8 +1748,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (dev->power.direct_complete) {
if (pm_runtime_status_suspended(dev)) {
pm_runtime_disable(dev);
- if (pm_runtime_status_suspended(dev))
+ if (pm_runtime_status_suspended(dev)) {
+ pm_dev_dbg(dev, state, "direct-complete ");
goto Complete;
+ }
pm_runtime_enable(dev);
}
@@ -1833,7 +1844,7 @@ static int device_suspend(struct device *dev)
if (is_async(dev)) {
get_device(dev);
- async_schedule(async_suspend, dev);
+ async_schedule_dev(async_suspend, dev);
return 0;
}
@@ -1852,6 +1863,7 @@ int dpm_suspend(pm_message_t state)
trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
might_sleep();
+ devfreq_suspend();
cpufreq_suspend();
mutex_lock(&dpm_list_mtx);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 70624695b6d5..a80dbf08a99c 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -66,20 +66,30 @@ static int rpm_suspend(struct device *dev, int rpmflags);
*/
void update_pm_runtime_accounting(struct device *dev)
{
- unsigned long now = jiffies;
- unsigned long delta;
+ u64 now, last, delta;
- delta = now - dev->power.accounting_timestamp;
+ if (dev->power.disable_depth > 0)
+ return;
+
+ last = dev->power.accounting_timestamp;
+ now = ktime_get_mono_fast_ns();
dev->power.accounting_timestamp = now;
- if (dev->power.disable_depth > 0)
+ /*
+ * Because ktime_get_mono_fast_ns() is not monotonic during
+ * timekeeping updates, ensure that 'now' is after the last saved
+ * timesptamp.
+ */
+ if (now < last)
return;
+ delta = now - last;
+
if (dev->power.runtime_status == RPM_SUSPENDED)
- dev->power.suspended_jiffies += delta;
+ dev->power.suspended_time += delta;
else
- dev->power.active_jiffies += delta;
+ dev->power.active_time += delta;
}
static void __update_runtime_status(struct device *dev, enum rpm_status status)
@@ -88,6 +98,22 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status)
dev->power.runtime_status = status;
}
+u64 pm_runtime_suspended_time(struct device *dev)
+{
+ u64 time;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ update_pm_runtime_accounting(dev);
+ time = dev->power.suspended_time;
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+
+ return time;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_suspended_time);
+
/**
* pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
* @dev: Device to handle.
@@ -95,7 +121,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status)
static void pm_runtime_deactivate_timer(struct device *dev)
{
if (dev->power.timer_expires > 0) {
- hrtimer_cancel(&dev->power.suspend_timer);
+ hrtimer_try_to_cancel(&dev->power.suspend_timer);
dev->power.timer_expires = 0;
}
}
@@ -121,7 +147,7 @@ static void pm_runtime_cancel_pending(struct device *dev)
* Compute the autosuspend-delay expiration time based on the device's
* power.last_busy time. If the delay has already expired or is disabled
* (negative) or the power.use_autosuspend flag isn't set, return 0.
- * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero).
*
* This function may be called either with or without dev->power.lock held.
* Either way it can be racy, since power.last_busy may be updated at any time.
@@ -129,24 +155,21 @@ static void pm_runtime_cancel_pending(struct device *dev)
u64 pm_runtime_autosuspend_expiration(struct device *dev)
{
int autosuspend_delay;
- u64 last_busy, expires = 0;
- u64 now = ktime_to_ns(ktime_get());
+ u64 expires;
if (!dev->power.use_autosuspend)
- goto out;
+ return 0;
autosuspend_delay = READ_ONCE(dev->power.autosuspend_delay);
if (autosuspend_delay < 0)
- goto out;
-
- last_busy = READ_ONCE(dev->power.last_busy);
+ return 0;
- expires = last_busy + autosuspend_delay * NSEC_PER_MSEC;
- if (expires <= now)
- expires = 0; /* Already expired. */
+ expires = READ_ONCE(dev->power.last_busy);
+ expires += (u64)autosuspend_delay * NSEC_PER_MSEC;
+ if (expires > ktime_get_mono_fast_ns())
+ return expires; /* Expires in the future */
- out:
- return expires;
+ return 0;
}
EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
@@ -259,11 +282,8 @@ static int rpm_get_suppliers(struct device *dev)
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
int retval;
- if (!(link->flags & DL_FLAG_PM_RUNTIME))
- continue;
-
- if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND ||
- link->rpm_active)
+ if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
+ READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
continue;
retval = pm_runtime_get_sync(link->supplier);
@@ -272,7 +292,7 @@ static int rpm_get_suppliers(struct device *dev)
pm_runtime_put_noidle(link->supplier);
return retval;
}
- link->rpm_active = true;
+ refcount_inc(&link->rpm_active);
}
return 0;
}
@@ -281,12 +301,13 @@ static void rpm_put_suppliers(struct device *dev)
{
struct device_link *link;
- list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
- if (link->rpm_active &&
- READ_ONCE(link->status) != DL_STATE_SUPPLIER_UNBIND) {
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
+ if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
+ continue;
+
+ while (refcount_dec_not_one(&link->rpm_active))
pm_runtime_put(link->supplier);
- link->rpm_active = false;
- }
+ }
}
/**
@@ -525,7 +546,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
* We add a slack of 25% to gather wakeups
* without sacrificing the granularity.
*/
- u64 slack = READ_ONCE(dev->power.autosuspend_delay) *
+ u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) *
(NSEC_PER_MSEC >> 2);
dev->power.timer_expires = expires;
@@ -905,8 +926,11 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer)
spin_lock_irqsave(&dev->power.lock, flags);
expires = dev->power.timer_expires;
- /* If 'expire' is after 'jiffies' we've been called too early. */
- if (expires > 0 && expires < ktime_to_ns(ktime_get())) {
+ /*
+ * If 'expires' is after the current time, we've been called
+ * too early.
+ */
+ if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
dev->power.timer_expires = 0;
rpm_suspend(dev, dev->power.timer_autosuspends ?
(RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
@@ -925,7 +949,7 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer)
int pm_schedule_suspend(struct device *dev, unsigned int delay)
{
unsigned long flags;
- ktime_t expires;
+ u64 expires;
int retval;
spin_lock_irqsave(&dev->power.lock, flags);
@@ -942,8 +966,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
/* Other scheduled or pending requests need to be canceled. */
pm_runtime_cancel_pending(dev);
- expires = ktime_add(ktime_get(), ms_to_ktime(delay));
- dev->power.timer_expires = ktime_to_ns(expires);
+ expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC;
+ dev->power.timer_expires = expires;
dev->power.timer_autosuspends = 0;
hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
@@ -1088,24 +1112,57 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
* and the device parent's counter of unsuspended children is modified to
* reflect the new status. If the new status is RPM_SUSPENDED, an idle
* notification request for the parent is submitted.
+ *
+ * If @dev has any suppliers (as reflected by device links to them), and @status
+ * is RPM_ACTIVE, they will be activated upfront and if the activation of one
+ * of them fails, the status of @dev will be changed to RPM_SUSPENDED (instead
+ * of the @status value) and the suppliers will be deacticated on exit. The
+ * error returned by the failing supplier activation will be returned in that
+ * case.
*/
int __pm_runtime_set_status(struct device *dev, unsigned int status)
{
struct device *parent = dev->parent;
- unsigned long flags;
bool notify_parent = false;
int error = 0;
if (status != RPM_ACTIVE && status != RPM_SUSPENDED)
return -EINVAL;
- spin_lock_irqsave(&dev->power.lock, flags);
+ spin_lock_irq(&dev->power.lock);
- if (!dev->power.runtime_error && !dev->power.disable_depth) {
+ /*
+ * Prevent PM-runtime from being enabled for the device or return an
+ * error if it is enabled already and working.
+ */
+ if (dev->power.runtime_error || dev->power.disable_depth)
+ dev->power.disable_depth++;
+ else
error = -EAGAIN;
- goto out;
+
+ spin_unlock_irq(&dev->power.lock);
+
+ if (error)
+ return error;
+
+ /*
+ * If the new status is RPM_ACTIVE, the suppliers can be activated
+ * upfront regardless of the current status, because next time
+ * rpm_put_suppliers() runs, the rpm_active refcounts of the links
+ * involved will be dropped down to one anyway.
+ */
+ if (status == RPM_ACTIVE) {
+ int idx = device_links_read_lock();
+
+ error = rpm_get_suppliers(dev);
+ if (error)
+ status = RPM_SUSPENDED;
+
+ device_links_read_unlock(idx);
}
+ spin_lock_irq(&dev->power.lock);
+
if (dev->power.runtime_status == status || !parent)
goto out_set;
@@ -1133,19 +1190,33 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
spin_unlock(&parent->power.lock);
- if (error)
+ if (error) {
+ status = RPM_SUSPENDED;
goto out;
+ }
}
out_set:
__update_runtime_status(dev, status);
- dev->power.runtime_error = 0;
+ if (!error)
+ dev->power.runtime_error = 0;
+
out:
- spin_unlock_irqrestore(&dev->power.lock, flags);
+ spin_unlock_irq(&dev->power.lock);
if (notify_parent)
pm_request_idle(parent);
+ if (status == RPM_SUSPENDED) {
+ int idx = device_links_read_lock();
+
+ rpm_put_suppliers(dev);
+
+ device_links_read_unlock(idx);
+ }
+
+ pm_runtime_enable(dev);
+
return error;
}
EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
@@ -1273,6 +1344,9 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
pm_runtime_put_noidle(dev);
}
+ /* Update time accounting before disabling PM-runtime. */
+ update_pm_runtime_accounting(dev);
+
if (!dev->power.disable_depth++)
__pm_runtime_barrier(dev);
@@ -1291,10 +1365,15 @@ void pm_runtime_enable(struct device *dev)
spin_lock_irqsave(&dev->power.lock, flags);
- if (dev->power.disable_depth > 0)
+ if (dev->power.disable_depth > 0) {
dev->power.disable_depth--;
- else
+
+ /* About to enable runtime pm, set accounting_timestamp to now */
+ if (!dev->power.disable_depth)
+ dev->power.accounting_timestamp = ktime_get_mono_fast_ns();
+ } else {
dev_warn(dev, "Unbalanced %s!\n", __func__);
+ }
WARN(!dev->power.disable_depth &&
dev->power.runtime_status == RPM_SUSPENDED &&
@@ -1491,7 +1570,6 @@ void pm_runtime_init(struct device *dev)
dev->power.request_pending = false;
dev->power.request = RPM_REQ_NONE;
dev->power.deferred_resume = false;
- dev->power.accounting_timestamp = jiffies;
INIT_WORK(&dev->power.work, pm_runtime_work);
dev->power.timer_expires = 0;
@@ -1536,7 +1614,7 @@ void pm_runtime_remove(struct device *dev)
*
* Check links from this device to any consumers and if any of them have active
* runtime PM references to the device, drop the usage counter of the device
- * (once per link).
+ * (as many times as needed).
*
* Links with the DL_FLAG_STATELESS flag set are ignored.
*
@@ -1558,10 +1636,8 @@ void pm_runtime_clean_up_links(struct device *dev)
if (link->flags & DL_FLAG_STATELESS)
continue;
- if (link->rpm_active) {
+ while (refcount_dec_not_one(&link->rpm_active))
pm_runtime_put_noidle(dev);
- link->rpm_active = false;
- }
}
device_links_read_unlock(idx);
@@ -1579,8 +1655,11 @@ void pm_runtime_get_suppliers(struct device *dev)
idx = device_links_read_lock();
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
- if (link->flags & DL_FLAG_PM_RUNTIME)
+ if (link->flags & DL_FLAG_PM_RUNTIME) {
+ link->supplier_preactivated = true;
+ refcount_inc(&link->rpm_active);
pm_runtime_get_sync(link->supplier);
+ }
device_links_read_unlock(idx);
}
@@ -1597,8 +1676,11 @@ void pm_runtime_put_suppliers(struct device *dev)
idx = device_links_read_lock();
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
- if (link->flags & DL_FLAG_PM_RUNTIME)
- pm_runtime_put(link->supplier);
+ if (link->supplier_preactivated) {
+ link->supplier_preactivated = false;
+ if (refcount_dec_not_one(&link->rpm_active))
+ pm_runtime_put(link->supplier);
+ }
device_links_read_unlock(idx);
}
@@ -1612,8 +1694,6 @@ void pm_runtime_new_link(struct device *dev)
void pm_runtime_drop_link(struct device *dev)
{
- rpm_put_suppliers(dev);
-
spin_lock_irq(&dev->power.lock);
WARN_ON(dev->power.links_count == 0);
dev->power.links_count--;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index d713738ce796..c6bf76124184 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -125,9 +125,12 @@ static ssize_t runtime_active_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
+ u64 tmp;
spin_lock_irq(&dev->power.lock);
update_pm_runtime_accounting(dev);
- ret = sprintf(buf, "%i\n", jiffies_to_msecs(dev->power.active_jiffies));
+ tmp = dev->power.active_time;
+ do_div(tmp, NSEC_PER_MSEC);
+ ret = sprintf(buf, "%llu\n", tmp);
spin_unlock_irq(&dev->power.lock);
return ret;
}
@@ -138,10 +141,12 @@ static ssize_t runtime_suspended_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
+ u64 tmp;
spin_lock_irq(&dev->power.lock);
update_pm_runtime_accounting(dev);
- ret = sprintf(buf, "%i\n",
- jiffies_to_msecs(dev->power.suspended_jiffies));
+ tmp = dev->power.suspended_time;
+ do_div(tmp, NSEC_PER_MSEC);
+ ret = sprintf(buf, "%llu\n", tmp);
spin_unlock_irq(&dev->power.lock);
return ret;
}
@@ -648,6 +653,10 @@ int dpm_sysfs_add(struct device *dev)
{
int rc;
+ /* No need to create PM sysfs if explicitly disabled. */
+ if (device_pm_not_required(dev))
+ return 0;
+
rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
if (rc)
return rc;
@@ -727,6 +736,8 @@ void rpm_sysfs_remove(struct device *dev)
void dpm_sysfs_remove(struct device *dev)
{
+ if (device_pm_not_required(dev))
+ return;
sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
dev_pm_qos_constraints_destroy(dev);
rpm_sysfs_remove(dev);
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 5fa1898755a3..f1fee72ed970 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -783,7 +783,7 @@ void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
/**
- * pm_wakeup_event - Notify the PM core of a wakeup event.
+ * pm_wakeup_dev_event - Notify the PM core of a wakeup event.
* @dev: Device the wakeup event is related to.
* @msec: Anticipated event processing time (in milliseconds).
* @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 2e8f0144f9ab..9cbb4b0cd01b 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -33,7 +33,7 @@ struct regcache_rbtree_node {
unsigned int blklen;
/* the actual rbtree node holding this block */
struct rb_node node;
-} __attribute__ ((packed));
+};
struct regcache_rbtree_ctx {
struct rb_root root;
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 1bd1145ad8b5..5059748afd4c 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -35,6 +35,7 @@ struct regmap_irq_chip_data {
int wake_count;
void *status_reg_buf;
+ unsigned int *main_status_buf;
unsigned int *status_buf;
unsigned int *mask_buf;
unsigned int *mask_buf_def;
@@ -108,6 +109,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
*/
for (i = 0; i < d->chip->num_regs; i++) {
+ if (!d->chip->mask_base)
+ continue;
+
reg = d->chip->mask_base +
(i * map->reg_stride * d->irq_reg_stride);
if (d->chip->mask_invert) {
@@ -258,7 +262,7 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
const struct regmap_irq_type *t = &irq_data->type;
if ((t->types_supported & type) != type)
- return -ENOTSUPP;
+ return 0;
reg = t->type_reg_offset / map->reg_stride;
@@ -326,6 +330,33 @@ static const struct irq_chip regmap_irq_chip = {
.irq_set_wake = regmap_irq_set_wake,
};
+static inline int read_sub_irq_data(struct regmap_irq_chip_data *data,
+ unsigned int b)
+{
+ const struct regmap_irq_chip *chip = data->chip;
+ struct regmap *map = data->map;
+ struct regmap_irq_sub_irq_map *subreg;
+ int i, ret = 0;
+
+ if (!chip->sub_reg_offsets) {
+ /* Assume linear mapping */
+ ret = regmap_read(map, chip->status_base +
+ (b * map->reg_stride * data->irq_reg_stride),
+ &data->status_buf[b]);
+ } else {
+ subreg = &chip->sub_reg_offsets[b];
+ for (i = 0; i < subreg->num_regs; i++) {
+ unsigned int offset = subreg->offset[i];
+
+ ret = regmap_read(map, chip->status_base + offset,
+ &data->status_buf[offset]);
+ if (ret)
+ break;
+ }
+ }
+ return ret;
+}
+
static irqreturn_t regmap_irq_thread(int irq, void *d)
{
struct regmap_irq_chip_data *data = d;
@@ -349,11 +380,65 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
/*
- * Read in the statuses, using a single bulk read if possible
- * in order to reduce the I/O overheads.
+ * Read only registers with active IRQs if the chip has 'main status
+ * register'. Else read in the statuses, using a single bulk read if
+ * possible in order to reduce the I/O overheads.
*/
- if (!map->use_single_read && map->reg_stride == 1 &&
- data->irq_reg_stride == 1) {
+
+ if (chip->num_main_regs) {
+ unsigned int max_main_bits;
+ unsigned long size;
+
+ size = chip->num_regs * sizeof(unsigned int);
+
+ max_main_bits = (chip->num_main_status_bits) ?
+ chip->num_main_status_bits : chip->num_regs;
+ /* Clear the status buf as we don't read all status regs */
+ memset(data->status_buf, 0, size);
+
+ /* We could support bulk read for main status registers
+ * but I don't expect to see devices with really many main
+ * status registers so let's only support single reads for the
+ * sake of simplicity. and add bulk reads only if needed
+ */
+ for (i = 0; i < chip->num_main_regs; i++) {
+ ret = regmap_read(map, chip->main_status +
+ (i * map->reg_stride
+ * data->irq_reg_stride),
+ &data->main_status_buf[i]);
+ if (ret) {
+ dev_err(map->dev,
+ "Failed to read IRQ status %d\n",
+ ret);
+ goto exit;
+ }
+ }
+
+ /* Read sub registers with active IRQs */
+ for (i = 0; i < chip->num_main_regs; i++) {
+ unsigned int b;
+ const unsigned long mreg = data->main_status_buf[i];
+
+ for_each_set_bit(b, &mreg, map->format.val_bytes * 8) {
+ if (i * map->format.val_bytes * 8 + b >
+ max_main_bits)
+ break;
+ ret = read_sub_irq_data(data, b);
+
+ if (ret != 0) {
+ dev_err(map->dev,
+ "Failed to read IRQ status %d\n",
+ ret);
+ if (chip->runtime_pm)
+ pm_runtime_put(map->dev);
+ goto exit;
+ }
+ }
+
+ }
+ } else if (!map->use_single_read && map->reg_stride == 1 &&
+ data->irq_reg_stride == 1) {
+
u8 *buf8 = data->status_reg_buf;
u16 *buf16 = data->status_reg_buf;
u32 *buf32 = data->status_reg_buf;
@@ -518,6 +603,15 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
if (!d)
return -ENOMEM;
+ if (chip->num_main_regs) {
+ d->main_status_buf = kcalloc(chip->num_main_regs,
+ sizeof(unsigned int),
+ GFP_KERNEL);
+
+ if (!d->main_status_buf)
+ goto err_alloc;
+ }
+
d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->status_buf)
@@ -588,6 +682,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
/* Mask all the interrupts by default */
for (i = 0; i < chip->num_regs; i++) {
d->mask_buf[i] = d->mask_buf_def[i];
+ if (!chip->mask_base)
+ continue;
+
reg = chip->mask_base +
(i * map->reg_stride * d->irq_reg_stride);
if (chip->mask_invert)
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 89ad8dee6ad5..1fad9291f6aa 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -499,6 +499,28 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
return &c->fwnode;
}
+static struct fwnode_handle *
+software_node_get_named_child_node(const struct fwnode_handle *fwnode,
+ const char *childname)
+{
+ struct software_node *swnode = to_software_node(fwnode);
+ const struct property_entry *prop;
+ struct software_node *child;
+
+ if (!swnode || list_empty(&swnode->children))
+ return NULL;
+
+ list_for_each_entry(child, &swnode->children, entry) {
+ prop = property_entry_get(child->properties, "name");
+ if (!prop)
+ continue;
+ if (!strcmp(childname, prop->value.str)) {
+ kobject_get(&child->kobj);
+ return &child->fwnode;
+ }
+ }
+ return NULL;
+}
static const struct fwnode_operations software_node_ops = {
.get = software_node_get,
@@ -508,6 +530,7 @@ static const struct fwnode_operations software_node_ops = {
.property_read_string_array = software_node_read_string_array,
.get_parent = software_node_get_parent,
.get_next_child_node = software_node_get_next_child,
+ .get_named_child_node = software_node_get_named_child_node,
};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/base/test/test_async_driver_probe.c b/drivers/base/test/test_async_driver_probe.c
index e7f145d662f0..f4b1d8e54daf 100644
--- a/drivers/base/test/test_async_driver_probe.c
+++ b/drivers/base/test/test_async_driver_probe.c
@@ -11,16 +11,47 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/time.h>
+#include <linux/numa.h>
+#include <linux/nodemask.h>
+#include <linux/topology.h>
#define TEST_PROBE_DELAY (5 * 1000) /* 5 sec */
#define TEST_PROBE_THRESHOLD (TEST_PROBE_DELAY / 2)
+static atomic_t warnings, errors, timeout, async_completed;
+
static int test_probe(struct platform_device *pdev)
{
- dev_info(&pdev->dev, "sleeping for %d msecs in probe\n",
- TEST_PROBE_DELAY);
- msleep(TEST_PROBE_DELAY);
- dev_info(&pdev->dev, "done sleeping\n");
+ struct device *dev = &pdev->dev;
+
+ /*
+ * Determine if we have hit the "timeout" limit for the test if we
+ * have then report it as an error, otherwise we wil sleep for the
+ * required amount of time and then report completion.
+ */
+ if (atomic_read(&timeout)) {
+ dev_err(dev, "async probe took too long\n");
+ atomic_inc(&errors);
+ } else {
+ dev_dbg(&pdev->dev, "sleeping for %d msecs in probe\n",
+ TEST_PROBE_DELAY);
+ msleep(TEST_PROBE_DELAY);
+ dev_dbg(&pdev->dev, "done sleeping\n");
+ }
+
+ /*
+ * Report NUMA mismatch if device node is set and we are not
+ * performing an async init on that node.
+ */
+ if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
+ if (dev_to_node(dev) != numa_node_id()) {
+ dev_warn(dev, "NUMA node mismatch %d != %d\n",
+ dev_to_node(dev), numa_node_id());
+ atomic_inc(&warnings);
+ }
+
+ atomic_inc(&async_completed);
+ }
return 0;
}
@@ -41,31 +72,64 @@ static struct platform_driver sync_driver = {
.probe = test_probe,
};
-static struct platform_device *async_dev_1, *async_dev_2;
-static struct platform_device *sync_dev_1;
+static struct platform_device *async_dev[NR_CPUS * 2];
+static struct platform_device *sync_dev[2];
+
+static struct platform_device *
+test_platform_device_register_node(char *name, int id, int nid)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc(name, id);
+ if (!pdev)
+ return NULL;
+
+ if (nid != NUMA_NO_NODE)
+ set_dev_node(&pdev->dev, nid);
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ platform_device_put(pdev);
+ return ERR_PTR(ret);
+ }
+
+ return pdev;
+
+}
static int __init test_async_probe_init(void)
{
- ktime_t calltime, delta;
+ struct platform_device **pdev = NULL;
+ int async_id = 0, sync_id = 0;
unsigned long long duration;
- int error;
+ ktime_t calltime, delta;
+ int err, nid, cpu;
+
+ pr_info("registering first set of asynchronous devices...\n");
- pr_info("registering first asynchronous device...\n");
+ for_each_online_cpu(cpu) {
+ nid = cpu_to_node(cpu);
+ pdev = &async_dev[async_id];
+ *pdev = test_platform_device_register_node("test_async_driver",
+ async_id,
+ nid);
+ if (IS_ERR(*pdev)) {
+ err = PTR_ERR(*pdev);
+ *pdev = NULL;
+ pr_err("failed to create async_dev: %d\n", err);
+ goto err_unregister_async_devs;
+ }
- async_dev_1 = platform_device_register_simple("test_async_driver", 1,
- NULL, 0);
- if (IS_ERR(async_dev_1)) {
- error = PTR_ERR(async_dev_1);
- pr_err("failed to create async_dev_1: %d\n", error);
- return error;
+ async_id++;
}
pr_info("registering asynchronous driver...\n");
calltime = ktime_get();
- error = platform_driver_register(&async_driver);
- if (error) {
- pr_err("Failed to register async_driver: %d\n", error);
- goto err_unregister_async_dev_1;
+ err = platform_driver_register(&async_driver);
+ if (err) {
+ pr_err("Failed to register async_driver: %d\n", err);
+ goto err_unregister_async_devs;
}
delta = ktime_sub(ktime_get(), calltime);
@@ -73,86 +137,163 @@ static int __init test_async_probe_init(void)
pr_info("registration took %lld msecs\n", duration);
if (duration > TEST_PROBE_THRESHOLD) {
pr_err("test failed: probe took too long\n");
- error = -ETIMEDOUT;
+ err = -ETIMEDOUT;
goto err_unregister_async_driver;
}
- pr_info("registering second asynchronous device...\n");
+ pr_info("registering second set of asynchronous devices...\n");
calltime = ktime_get();
- async_dev_2 = platform_device_register_simple("test_async_driver", 2,
- NULL, 0);
- if (IS_ERR(async_dev_2)) {
- error = PTR_ERR(async_dev_2);
- pr_err("failed to create async_dev_2: %d\n", error);
- goto err_unregister_async_driver;
+ for_each_online_cpu(cpu) {
+ nid = cpu_to_node(cpu);
+ pdev = &sync_dev[sync_id];
+
+ *pdev = test_platform_device_register_node("test_async_driver",
+ async_id,
+ nid);
+ if (IS_ERR(*pdev)) {
+ err = PTR_ERR(*pdev);
+ *pdev = NULL;
+ pr_err("failed to create async_dev: %d\n", err);
+ goto err_unregister_async_driver;
+ }
+
+ async_id++;
}
delta = ktime_sub(ktime_get(), calltime);
duration = (unsigned long long) ktime_to_ms(delta);
- pr_info("registration took %lld msecs\n", duration);
+ dev_info(&(*pdev)->dev,
+ "registration took %lld msecs\n", duration);
if (duration > TEST_PROBE_THRESHOLD) {
- pr_err("test failed: probe took too long\n");
- error = -ETIMEDOUT;
- goto err_unregister_async_dev_2;
+ dev_err(&(*pdev)->dev,
+ "test failed: probe took too long\n");
+ err = -ETIMEDOUT;
+ goto err_unregister_async_driver;
}
- pr_info("registering synchronous driver...\n");
- error = platform_driver_register(&sync_driver);
- if (error) {
- pr_err("Failed to register async_driver: %d\n", error);
- goto err_unregister_async_dev_2;
+ pr_info("registering first synchronous device...\n");
+ nid = cpu_to_node(cpu);
+ pdev = &sync_dev[sync_id];
+
+ *pdev = test_platform_device_register_node("test_sync_driver",
+ sync_id,
+ NUMA_NO_NODE);
+ if (IS_ERR(*pdev)) {
+ err = PTR_ERR(*pdev);
+ *pdev = NULL;
+ pr_err("failed to create sync_dev: %d\n", err);
+ goto err_unregister_async_driver;
}
- pr_info("registering synchronous device...\n");
+ sync_id++;
+
+ pr_info("registering synchronous driver...\n");
calltime = ktime_get();
- sync_dev_1 = platform_device_register_simple("test_sync_driver", 1,
- NULL, 0);
- if (IS_ERR(sync_dev_1)) {
- error = PTR_ERR(sync_dev_1);
- pr_err("failed to create sync_dev_1: %d\n", error);
- goto err_unregister_sync_driver;
+ err = platform_driver_register(&sync_driver);
+ if (err) {
+ pr_err("Failed to register async_driver: %d\n", err);
+ goto err_unregister_sync_devs;
}
delta = ktime_sub(ktime_get(), calltime);
duration = (unsigned long long) ktime_to_ms(delta);
pr_info("registration took %lld msecs\n", duration);
if (duration < TEST_PROBE_THRESHOLD) {
- pr_err("test failed: probe was too quick\n");
- error = -ETIMEDOUT;
- goto err_unregister_sync_dev_1;
+ dev_err(&(*pdev)->dev,
+ "test failed: probe was too quick\n");
+ err = -ETIMEDOUT;
+ goto err_unregister_sync_driver;
}
- pr_info("completed successfully");
+ pr_info("registering second synchronous device...\n");
+ pdev = &sync_dev[sync_id];
+ calltime = ktime_get();
- return 0;
+ *pdev = test_platform_device_register_node("test_sync_driver",
+ sync_id,
+ NUMA_NO_NODE);
+ if (IS_ERR(*pdev)) {
+ err = PTR_ERR(*pdev);
+ *pdev = NULL;
+ pr_err("failed to create sync_dev: %d\n", err);
+ goto err_unregister_sync_driver;
+ }
-err_unregister_sync_dev_1:
- platform_device_unregister(sync_dev_1);
+ sync_id++;
-err_unregister_sync_driver:
- platform_driver_unregister(&sync_driver);
+ delta = ktime_sub(ktime_get(), calltime);
+ duration = (unsigned long long) ktime_to_ms(delta);
+ dev_info(&(*pdev)->dev,
+ "registration took %lld msecs\n", duration);
+ if (duration < TEST_PROBE_THRESHOLD) {
+ dev_err(&(*pdev)->dev,
+ "test failed: probe was too quick\n");
+ err = -ETIMEDOUT;
+ goto err_unregister_sync_driver;
+ }
-err_unregister_async_dev_2:
- platform_device_unregister(async_dev_2);
+ /*
+ * The async events should have completed while we were taking care
+ * of the synchronous events. We will now terminate any outstanding
+ * asynchronous probe calls remaining by forcing timeout and remove
+ * the driver before we return which should force the flush of the
+ * pending asynchronous probe calls.
+ *
+ * Otherwise if they completed without errors or warnings then
+ * report successful completion.
+ */
+ if (atomic_read(&async_completed) != async_id) {
+ pr_err("async events still pending, forcing timeout\n");
+ atomic_inc(&timeout);
+ err = -ETIMEDOUT;
+ } else if (!atomic_read(&errors) && !atomic_read(&warnings)) {
+ pr_info("completed successfully\n");
+ return 0;
+ }
+err_unregister_sync_driver:
+ platform_driver_unregister(&sync_driver);
+err_unregister_sync_devs:
+ while (sync_id--)
+ platform_device_unregister(sync_dev[sync_id]);
err_unregister_async_driver:
platform_driver_unregister(&async_driver);
+err_unregister_async_devs:
+ while (async_id--)
+ platform_device_unregister(async_dev[async_id]);
+
+ /*
+ * If err is already set then count that as an additional error for
+ * the test. Otherwise we will report an invalid argument error and
+ * not count that as we should have reached here as a result of
+ * errors or warnings being reported by the probe routine.
+ */
+ if (err)
+ atomic_inc(&errors);
+ else
+ err = -EINVAL;
-err_unregister_async_dev_1:
- platform_device_unregister(async_dev_1);
+ pr_err("Test failed with %d errors and %d warnings\n",
+ atomic_read(&errors), atomic_read(&warnings));
- return error;
+ return err;
}
module_init(test_async_probe_init);
static void __exit test_async_probe_exit(void)
{
+ int id = 2;
+
platform_driver_unregister(&async_driver);
platform_driver_unregister(&sync_driver);
- platform_device_unregister(async_dev_1);
- platform_device_unregister(async_dev_2);
- platform_device_unregister(sync_dev_1);
+
+ while (id--)
+ platform_device_unregister(sync_dev[id]);
+
+ id = NR_CPUS * 2;
+ while (id--)
+ platform_device_unregister(async_dev[id]);
}
module_exit(test_async_probe_exit);
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index a4aac370f21f..6eded32d1aac 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -10,13 +10,13 @@
#include <linux/delay.h>
#define bcma_err(bus, fmt, ...) \
- pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+ dev_err((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
#define bcma_warn(bus, fmt, ...) \
- pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+ dev_warn((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
#define bcma_info(bus, fmt, ...) \
- pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+ dev_info((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
#define bcma_debug(bus, fmt, ...) \
- pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+ dev_dbg((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
struct bcma_bus;
@@ -33,7 +33,6 @@ int __init bcma_bus_early_register(struct bcma_bus *bus);
int bcma_bus_suspend(struct bcma_bus *bus);
int bcma_bus_resume(struct bcma_bus *bus);
#endif
-struct device *bcma_bus_get_host_dev(struct bcma_bus *bus);
/* scan.c */
void bcma_detect_chip(struct bcma_bus *bus);
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 2c0ffb77d738..a5df3d111334 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -183,7 +183,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output;
chip->owner = THIS_MODULE;
- chip->parent = bcma_bus_get_host_dev(bus);
+ chip->parent = bus->dev;
#if IS_BUILTIN(CONFIG_OF)
chip->of_node = cc->core->dev.of_node;
#endif
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 63410ecfe640..f52239feb4cb 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -196,6 +196,8 @@ static int bcma_host_pci_probe(struct pci_dev *dev,
goto err_pci_release_regions;
}
+ bus->dev = &dev->dev;
+
/* Map MMIO */
err = -ENOMEM;
bus->mmio = pci_iomap(dev, 0, ~0UL);
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
index 2dce34789329..c8073b509a2b 100644
--- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c
@@ -179,7 +179,6 @@ int __init bcma_host_soc_register(struct bcma_soc *soc)
/* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops;
- bus->host_pdev = NULL;
/* Initialize struct, detect chip */
bcma_init_bus(bus);
@@ -213,6 +212,8 @@ static int bcma_host_soc_probe(struct platform_device *pdev)
if (!bus)
return -ENOMEM;
+ bus->dev = dev;
+
/* Map MMIO */
bus->mmio = of_iomap(np, 0);
if (!bus->mmio)
@@ -221,7 +222,6 @@ static int bcma_host_soc_probe(struct platform_device *pdev)
/* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops;
- bus->host_pdev = pdev;
/* Initialize struct, detect chip */
bcma_init_bus(bus);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index fc1f4acdd189..6535614a7dc1 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -223,8 +223,8 @@ unsigned int bcma_core_irq(struct bcma_device *core, int num)
mips_irq = bcma_core_mips_irq(core);
return mips_irq <= 4 ? mips_irq + 2 : 0;
}
- if (bus->host_pdev)
- return bcma_of_get_irq(&bus->host_pdev->dev, core, num);
+ if (bus->dev)
+ return bcma_of_get_irq(bus->dev, core, num);
return 0;
case BCMA_HOSTTYPE_SDIO:
return 0;
@@ -239,18 +239,18 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
core->dev.release = bcma_release_core_dev;
core->dev.bus = &bcma_bus_type;
dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
- core->dev.parent = bcma_bus_get_host_dev(bus);
- if (core->dev.parent)
- bcma_of_fill_device(core->dev.parent, core);
+ core->dev.parent = bus->dev;
+ if (bus->dev)
+ bcma_of_fill_device(bus->dev, core);
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
- core->dma_dev = &bus->host_pci->dev;
+ core->dma_dev = bus->dev;
core->irq = bus->host_pci->irq;
break;
case BCMA_HOSTTYPE_SOC:
- if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
- core->dma_dev = &bus->host_pdev->dev;
+ if (IS_ENABLED(CONFIG_OF) && bus->dev) {
+ core->dma_dev = bus->dev;
} else {
core->dev.dma_mask = &core->dev.coherent_dma_mask;
core->dma_dev = &core->dev;
@@ -261,28 +261,6 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
}
}
-struct device *bcma_bus_get_host_dev(struct bcma_bus *bus)
-{
- switch (bus->hosttype) {
- case BCMA_HOSTTYPE_PCI:
- if (bus->host_pci)
- return &bus->host_pci->dev;
- else
- return NULL;
- case BCMA_HOSTTYPE_SOC:
- if (bus->host_pdev)
- return &bus->host_pdev->dev;
- else
- return NULL;
- case BCMA_HOSTTYPE_SDIO:
- if (bus->host_sdio)
- return &bus->host_sdio->dev;
- else
- return NULL;
- }
- return NULL;
-}
-
void bcma_init_bus(struct bcma_bus *bus)
{
mutex_lock(&bcma_buses_mutex);
@@ -402,7 +380,6 @@ int bcma_bus_register(struct bcma_bus *bus)
{
int err;
struct bcma_device *core;
- struct device *dev;
/* Scan for devices (cores) */
err = bcma_bus_scan(bus);
@@ -425,10 +402,8 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_pci_early_init(&bus->drv_pci[0]);
}
- dev = bcma_bus_get_host_dev(bus);
- if (dev) {
- of_platform_default_populate(dev->of_node, NULL, dev);
- }
+ if (bus->dev)
+ of_platform_default_populate(bus->dev->of_node, NULL, bus->dev);
/* Cores providing flash access go before SPROM init */
list_for_each_entry(core, &bus->cores, list) {
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 6f2856c6d0f2..55481b40df9a 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4075,7 +4075,7 @@ static unsigned int floppy_check_events(struct gendisk *disk,
if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
if (lock_fdc(drive))
- return -EINTR;
+ return 0;
poll_drive(false, 0);
process_fd_request();
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b8a0720d3653..cf5538942834 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1190,6 +1190,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
goto out_unlock;
}
+ if (lo->lo_offset != info->lo_offset ||
+ lo->lo_sizelimit != info->lo_sizelimit) {
+ sync_blockdev(lo->lo_device);
+ kill_bdev(lo->lo_device);
+ }
+
/* I/O need to be drained during transfer transition */
blk_mq_freeze_queue(lo->lo_queue);
@@ -1218,6 +1224,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
if (lo->lo_offset != info->lo_offset ||
lo->lo_sizelimit != info->lo_sizelimit) {
+ /* kill_bdev should have truncated all the pages */
+ if (lo->lo_device->bd_inode->i_mapping->nrpages) {
+ err = -EAGAIN;
+ pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+ __func__, lo->lo_number, lo->lo_file_name,
+ lo->lo_device->bd_inode->i_mapping->nrpages);
+ goto out_unfreeze;
+ }
if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
err = -EFBIG;
goto out_unfreeze;
@@ -1443,22 +1457,39 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
{
+ int err = 0;
+
if (lo->lo_state != Lo_bound)
return -ENXIO;
if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
return -EINVAL;
+ if (lo->lo_queue->limits.logical_block_size != arg) {
+ sync_blockdev(lo->lo_device);
+ kill_bdev(lo->lo_device);
+ }
+
blk_mq_freeze_queue(lo->lo_queue);
+ /* kill_bdev should have truncated all the pages */
+ if (lo->lo_queue->limits.logical_block_size != arg &&
+ lo->lo_device->bd_inode->i_mapping->nrpages) {
+ err = -EAGAIN;
+ pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+ __func__, lo->lo_number, lo->lo_file_name,
+ lo->lo_device->bd_inode->i_mapping->nrpages);
+ goto out_unfreeze;
+ }
+
blk_queue_logical_block_size(lo->lo_queue, arg);
blk_queue_physical_block_size(lo->lo_queue, arg);
blk_queue_io_min(lo->lo_queue, arg);
loop_update_dio(lo);
-
+out_unfreeze:
blk_mq_unfreeze_queue(lo->lo_queue);
- return 0;
+ return err;
}
static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 88e8440e75c3..2f3ee4d6af82 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -40,6 +40,7 @@
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/prefetch.h>
+#include <linux/numa.h>
#include "mtip32xx.h"
#define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32)
@@ -4018,9 +4019,9 @@ static int get_least_used_cpu_on_node(int node)
/* Helper for selecting a node in round robin mode */
static inline int mtip_get_next_rr_node(void)
{
- static int next_node = -1;
+ static int next_node = NUMA_NO_NODE;
- if (next_node == -1) {
+ if (next_node == NUMA_NO_NODE) {
next_node = first_online_node;
return next_node;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 08696f5f00bb..7c9a949e876b 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -288,9 +288,10 @@ static void nbd_size_update(struct nbd_device *nbd)
blk_queue_physical_block_size(nbd->disk->queue, config->blksize);
set_capacity(nbd->disk, config->bytesize >> 9);
if (bdev) {
- if (bdev->bd_disk)
+ if (bdev->bd_disk) {
bd_set_size(bdev, config->bytesize);
- else
+ set_blocksize(bdev, config->blksize);
+ } else
bdev->bd_invalidated = 1;
bdput(bdev);
}
diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h
index b3df2793e7cd..34b22d6523ba 100644
--- a/drivers/block/null_blk.h
+++ b/drivers/block/null_blk.h
@@ -97,6 +97,7 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
#else
static inline int null_zone_init(struct nullb_device *dev)
{
+ pr_err("null_blk: CONFIG_BLK_DEV_ZONED not enabled\n");
return -EINVAL;
}
static inline void null_zone_exit(struct nullb_device *dev) {}
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 8e5140bbf241..282e2e82d849 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -428,14 +428,13 @@ static bool single_major = true;
module_param(single_major, bool, 0444);
MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (default: true)");
-static ssize_t rbd_add(struct bus_type *bus, const char *buf,
- size_t count);
-static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
- size_t count);
-static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf,
- size_t count);
-static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
- size_t count);
+static ssize_t add_store(struct bus_type *bus, const char *buf, size_t count);
+static ssize_t remove_store(struct bus_type *bus, const char *buf,
+ size_t count);
+static ssize_t add_single_major_store(struct bus_type *bus, const char *buf,
+ size_t count);
+static ssize_t remove_single_major_store(struct bus_type *bus, const char *buf,
+ size_t count);
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
static int rbd_dev_id_to_minor(int dev_id)
@@ -464,16 +463,16 @@ static bool rbd_is_lock_owner(struct rbd_device *rbd_dev)
return is_lock_owner;
}
-static ssize_t rbd_supported_features_show(struct bus_type *bus, char *buf)
+static ssize_t supported_features_show(struct bus_type *bus, char *buf)
{
return sprintf(buf, "0x%llx\n", RBD_FEATURES_SUPPORTED);
}
-static BUS_ATTR(add, 0200, NULL, rbd_add);
-static BUS_ATTR(remove, 0200, NULL, rbd_remove);
-static BUS_ATTR(add_single_major, 0200, NULL, rbd_add_single_major);
-static BUS_ATTR(remove_single_major, 0200, NULL, rbd_remove_single_major);
-static BUS_ATTR(supported_features, 0444, rbd_supported_features_show, NULL);
+static BUS_ATTR_WO(add);
+static BUS_ATTR_WO(remove);
+static BUS_ATTR_WO(add_single_major);
+static BUS_ATTR_WO(remove_single_major);
+static BUS_ATTR_RO(supported_features);
static struct attribute *rbd_bus_attrs[] = {
&bus_attr_add.attr,
@@ -5934,9 +5933,7 @@ err_out_args:
goto out;
}
-static ssize_t rbd_add(struct bus_type *bus,
- const char *buf,
- size_t count)
+static ssize_t add_store(struct bus_type *bus, const char *buf, size_t count)
{
if (single_major)
return -EINVAL;
@@ -5944,9 +5941,8 @@ static ssize_t rbd_add(struct bus_type *bus,
return do_rbd_add(bus, buf, count);
}
-static ssize_t rbd_add_single_major(struct bus_type *bus,
- const char *buf,
- size_t count)
+static ssize_t add_single_major_store(struct bus_type *bus, const char *buf,
+ size_t count)
{
return do_rbd_add(bus, buf, count);
}
@@ -5986,7 +5982,6 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
struct list_head *tmp;
int dev_id;
char opt_buf[6];
- bool already = false;
bool force = false;
int ret;
@@ -6019,13 +6014,13 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
spin_lock_irq(&rbd_dev->lock);
if (rbd_dev->open_count && !force)
ret = -EBUSY;
- else
- already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
- &rbd_dev->flags);
+ else if (test_and_set_bit(RBD_DEV_FLAG_REMOVING,
+ &rbd_dev->flags))
+ ret = -EINPROGRESS;
spin_unlock_irq(&rbd_dev->lock);
}
spin_unlock(&rbd_dev_list_lock);
- if (ret < 0 || already)
+ if (ret)
return ret;
if (force) {
@@ -6050,9 +6045,7 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
return count;
}
-static ssize_t rbd_remove(struct bus_type *bus,
- const char *buf,
- size_t count)
+static ssize_t remove_store(struct bus_type *bus, const char *buf, size_t count)
{
if (single_major)
return -EINVAL;
@@ -6060,9 +6053,8 @@ static ssize_t rbd_remove(struct bus_type *bus,
return do_rbd_remove(bus, buf, count);
}
-static ssize_t rbd_remove_single_major(struct bus_type *bus,
- const char *buf,
- size_t count)
+static ssize_t remove_single_major_store(struct bus_type *bus, const char *buf,
+ size_t count)
{
return do_rbd_remove(bus, buf, count);
}
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index a10d5736d8f7..ab893a7571a2 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -2641,8 +2641,8 @@ static int skd_cons_skcomp(struct skd_device *skdev)
"comp pci_alloc, total bytes %zd entries %d\n",
SKD_SKCOMP_SIZE, SKD_N_COMPLETION_ENTRY);
- skcomp = dma_zalloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
- &skdev->cq_dma_address, GFP_KERNEL);
+ skcomp = dma_alloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
+ &skdev->cq_dma_address, GFP_KERNEL);
if (skcomp == NULL) {
rc = -ENOMEM;
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 33c5cc879f24..04ca65912638 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -316,11 +316,9 @@ static ssize_t idle_store(struct device *dev,
* See the comment in writeback_store.
*/
zram_slot_lock(zram, index);
- if (!zram_allocated(zram, index) ||
- zram_test_flag(zram, index, ZRAM_UNDER_WB))
- goto next;
- zram_set_flag(zram, index, ZRAM_IDLE);
-next:
+ if (zram_allocated(zram, index) &&
+ !zram_test_flag(zram, index, ZRAM_UNDER_WB))
+ zram_set_flag(zram, index, ZRAM_IDLE);
zram_slot_unlock(zram, index);
}
@@ -330,6 +328,41 @@ next:
}
#ifdef CONFIG_ZRAM_WRITEBACK
+static ssize_t writeback_limit_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct zram *zram = dev_to_zram(dev);
+ u64 val;
+ ssize_t ret = -EINVAL;
+
+ if (kstrtoull(buf, 10, &val))
+ return ret;
+
+ down_read(&zram->init_lock);
+ spin_lock(&zram->wb_limit_lock);
+ zram->wb_limit_enable = val;
+ spin_unlock(&zram->wb_limit_lock);
+ up_read(&zram->init_lock);
+ ret = len;
+
+ return ret;
+}
+
+static ssize_t writeback_limit_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool val;
+ struct zram *zram = dev_to_zram(dev);
+
+ down_read(&zram->init_lock);
+ spin_lock(&zram->wb_limit_lock);
+ val = zram->wb_limit_enable;
+ spin_unlock(&zram->wb_limit_lock);
+ up_read(&zram->init_lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
static ssize_t writeback_limit_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
@@ -341,9 +374,9 @@ static ssize_t writeback_limit_store(struct device *dev,
return ret;
down_read(&zram->init_lock);
- atomic64_set(&zram->stats.bd_wb_limit, val);
- if (val == 0)
- zram->stop_writeback = false;
+ spin_lock(&zram->wb_limit_lock);
+ zram->bd_wb_limit = val;
+ spin_unlock(&zram->wb_limit_lock);
up_read(&zram->init_lock);
ret = len;
@@ -357,7 +390,9 @@ static ssize_t writeback_limit_show(struct device *dev,
struct zram *zram = dev_to_zram(dev);
down_read(&zram->init_lock);
- val = atomic64_read(&zram->stats.bd_wb_limit);
+ spin_lock(&zram->wb_limit_lock);
+ val = zram->bd_wb_limit;
+ spin_unlock(&zram->wb_limit_lock);
up_read(&zram->init_lock);
return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
@@ -588,8 +623,8 @@ static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec,
return 1;
}
-#define HUGE_WRITEBACK 0x1
-#define IDLE_WRITEBACK 0x2
+#define HUGE_WRITEBACK 1
+#define IDLE_WRITEBACK 2
static ssize_t writeback_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
@@ -602,7 +637,7 @@ static ssize_t writeback_store(struct device *dev,
struct page *page;
ssize_t ret, sz;
char mode_buf[8];
- unsigned long mode = -1UL;
+ int mode = -1;
unsigned long blk_idx = 0;
sz = strscpy(mode_buf, buf, sizeof(mode_buf));
@@ -618,7 +653,7 @@ static ssize_t writeback_store(struct device *dev,
else if (!strcmp(mode_buf, "huge"))
mode = HUGE_WRITEBACK;
- if (mode == -1UL)
+ if (mode == -1)
return -EINVAL;
down_read(&zram->init_lock);
@@ -645,10 +680,13 @@ static ssize_t writeback_store(struct device *dev,
bvec.bv_len = PAGE_SIZE;
bvec.bv_offset = 0;
- if (zram->stop_writeback) {
+ spin_lock(&zram->wb_limit_lock);
+ if (zram->wb_limit_enable && !zram->bd_wb_limit) {
+ spin_unlock(&zram->wb_limit_lock);
ret = -EIO;
break;
}
+ spin_unlock(&zram->wb_limit_lock);
if (!blk_idx) {
blk_idx = alloc_block_bdev(zram);
@@ -667,10 +705,11 @@ static ssize_t writeback_store(struct device *dev,
zram_test_flag(zram, index, ZRAM_UNDER_WB))
goto next;
- if ((mode & IDLE_WRITEBACK &&
- !zram_test_flag(zram, index, ZRAM_IDLE)) &&
- (mode & HUGE_WRITEBACK &&
- !zram_test_flag(zram, index, ZRAM_HUGE)))
+ if (mode == IDLE_WRITEBACK &&
+ !zram_test_flag(zram, index, ZRAM_IDLE))
+ goto next;
+ if (mode == HUGE_WRITEBACK &&
+ !zram_test_flag(zram, index, ZRAM_HUGE))
goto next;
/*
* Clearing ZRAM_UNDER_WB is duty of caller.
@@ -732,11 +771,10 @@ static ssize_t writeback_store(struct device *dev,
zram_set_element(zram, index, blk_idx);
blk_idx = 0;
atomic64_inc(&zram->stats.pages_stored);
- if (atomic64_add_unless(&zram->stats.bd_wb_limit,
- -1 << (PAGE_SHIFT - 12), 0)) {
- if (atomic64_read(&zram->stats.bd_wb_limit) == 0)
- zram->stop_writeback = true;
- }
+ spin_lock(&zram->wb_limit_lock);
+ if (zram->wb_limit_enable && zram->bd_wb_limit > 0)
+ zram->bd_wb_limit -= 1UL << (PAGE_SHIFT - 12);
+ spin_unlock(&zram->wb_limit_lock);
next:
zram_slot_unlock(zram, index);
}
@@ -1812,6 +1850,7 @@ static DEVICE_ATTR_RW(comp_algorithm);
static DEVICE_ATTR_RW(backing_dev);
static DEVICE_ATTR_WO(writeback);
static DEVICE_ATTR_RW(writeback_limit);
+static DEVICE_ATTR_RW(writeback_limit_enable);
#endif
static struct attribute *zram_disk_attrs[] = {
@@ -1828,6 +1867,7 @@ static struct attribute *zram_disk_attrs[] = {
&dev_attr_backing_dev.attr,
&dev_attr_writeback.attr,
&dev_attr_writeback_limit.attr,
+ &dev_attr_writeback_limit_enable.attr,
#endif
&dev_attr_io_stat.attr,
&dev_attr_mm_stat.attr,
@@ -1867,7 +1907,9 @@ static int zram_add(void)
device_id = ret;
init_rwsem(&zram->init_lock);
-
+#ifdef CONFIG_ZRAM_WRITEBACK
+ spin_lock_init(&zram->wb_limit_lock);
+#endif
queue = blk_alloc_queue(GFP_KERNEL);
if (!queue) {
pr_err("Error allocating disk queue for device %d\n",
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 4bd3afd15e83..f2fd46daa760 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -86,7 +86,6 @@ struct zram_stats {
atomic64_t bd_count; /* no. of pages in backing device */
atomic64_t bd_reads; /* no. of reads from backing device */
atomic64_t bd_writes; /* no. of writes from backing device */
- atomic64_t bd_wb_limit; /* writeback limit of backing device */
#endif
};
@@ -114,8 +113,10 @@ struct zram {
*/
bool claim; /* Protected by bdev->bd_mutex */
struct file *backing_dev;
- bool stop_writeback;
#ifdef CONFIG_ZRAM_WRITEBACK
+ spinlock_t wb_limit_lock;
+ bool wb_limit_enable;
+ u64 bd_wb_limit;
struct block_device *bdev;
unsigned int old_block_size;
unsigned long *bitmap;
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 845b0314ce3a..7b2e76e7f22f 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -336,7 +336,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support
- Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997.
+ Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8977/8997.
Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module.
@@ -350,7 +350,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth
- devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997
+ devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997
chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index f0454541e5fd..fb7729779166 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -24,11 +24,9 @@
#include <linux/slab.h>
#include <net/bluetooth/bluetooth.h>
#include <linux/err.h>
-#include <linux/gpio.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index fb3d03928460..047b75ce1deb 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -62,13 +62,14 @@ static const struct of_device_id btmrvl_sdio_of_match_table[] = {
static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
{
struct btmrvl_sdio_card *card = priv;
+ struct device *dev = &card->func->dev;
struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
- pr_info("%s: wake by bt\n", __func__);
+ dev_info(dev, "wake by bt\n");
cfg->wake_by_bt = true;
disable_irq_nosync(irq);
- pm_wakeup_event(&card->func->dev, 0);
+ pm_wakeup_event(dev, 0);
pm_system_wakeup();
return IRQ_HANDLED;
@@ -87,7 +88,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
if (!dev->of_node ||
!of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
- pr_err("sdio platform data not available\n");
+ dev_info(dev, "sdio device tree data not available\n");
return -1;
}
@@ -211,6 +212,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.fw_dump_end = 0xea,
};
+static const struct btmrvl_sdio_card_reg btmrvl_reg_8977 = {
+ .cfg = 0x00,
+ .host_int_mask = 0x08,
+ .host_intstatus = 0x0c,
+ .card_status = 0x5c,
+ .sq_read_base_addr_a0 = 0xf8,
+ .sq_read_base_addr_a1 = 0xf9,
+ .card_revision = 0xc8,
+ .card_fw_status0 = 0xe8,
+ .card_fw_status1 = 0xe9,
+ .card_rx_len = 0xea,
+ .card_rx_unit = 0xeb,
+ .io_port_0 = 0xe4,
+ .io_port_1 = 0xe5,
+ .io_port_2 = 0xe6,
+ .int_read_to_clear = true,
+ .host_int_rsr = 0x04,
+ .card_misc_cfg = 0xD8,
+ .fw_dump_ctrl = 0xf0,
+ .fw_dump_start = 0xf1,
+ .fw_dump_end = 0xf8,
+};
+
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
.cfg = 0x00,
.host_int_mask = 0x08,
@@ -279,6 +303,15 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.supports_fw_dump = true,
};
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
+ .helper = NULL,
+ .firmware = "mrvl/sd8977_uapsta.bin",
+ .reg = &btmrvl_reg_8977,
+ .support_pscan_win_report = true,
+ .sd_blksz_fw_dl = 256,
+ .supports_fw_dump = true,
+};
+
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
.helper = NULL,
.firmware = "mrvl/sd8997_uapsta.bin",
@@ -307,6 +340,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
+ /* Marvell SD8977 Bluetooth device */
+ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9146),
+ .driver_data = (unsigned long)&btmrvl_sdio_sd8977 },
/* Marvell SD8997 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
.driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
@@ -1760,4 +1796,5 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index 4593baff2bc9..b0b680dd69f4 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -12,10 +12,15 @@
#include <linux/atomic.h>
#include <linux/clk.h>
#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/serdev.h>
#include <linux/skbuff.h>
@@ -24,20 +29,38 @@
#include "h4_recv.h"
-#define VERSION "0.1"
+#define VERSION "0.2"
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
+#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
+#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
#define MTK_STP_TLR_SIZE 2
#define BTMTKUART_TX_STATE_ACTIVE 1
#define BTMTKUART_TX_STATE_WAKEUP 2
#define BTMTKUART_TX_WAIT_VND_EVT 3
+#define BTMTKUART_REQUIRED_WAKEUP 4
+
+#define BTMTKUART_FLAG_STANDALONE_HW BIT(0)
enum {
MTK_WMT_PATCH_DWNLD = 0x1,
+ MTK_WMT_TEST = 0x2,
+ MTK_WMT_WAKEUP = 0x3,
+ MTK_WMT_HIF = 0x4,
MTK_WMT_FUNC_CTRL = 0x6,
- MTK_WMT_RST = 0x7
+ MTK_WMT_RST = 0x7,
+ MTK_WMT_SEMAPHORE = 0x17,
+};
+
+enum {
+ BTMTK_WMT_INVALID,
+ BTMTK_WMT_PATCH_UNDONE,
+ BTMTK_WMT_PATCH_DONE,
+ BTMTK_WMT_ON_UNDONE,
+ BTMTK_WMT_ON_DONE,
+ BTMTK_WMT_ON_PROGRESS,
};
struct mtk_stp_hdr {
@@ -46,6 +69,11 @@ struct mtk_stp_hdr {
u8 cs;
} __packed;
+struct btmtkuart_data {
+ unsigned int flags;
+ const char *fwname;
+};
+
struct mtk_wmt_hdr {
u8 dir;
u8 op;
@@ -58,41 +86,85 @@ struct mtk_hci_wmt_cmd {
u8 data[256];
} __packed;
+struct btmtk_hci_wmt_evt {
+ struct hci_event_hdr hhdr;
+ struct mtk_wmt_hdr whdr;
+} __packed;
+
+struct btmtk_hci_wmt_evt_funcc {
+ struct btmtk_hci_wmt_evt hwhdr;
+ __be16 status;
+} __packed;
+
+struct btmtk_tci_sleep {
+ u8 mode;
+ __le16 duration;
+ __le16 host_duration;
+ u8 host_wakeup_pin;
+ u8 time_compensation;
+} __packed;
+
+struct btmtk_hci_wmt_params {
+ u8 op;
+ u8 flag;
+ u16 dlen;
+ const void *data;
+ u32 *status;
+};
+
struct btmtkuart_dev {
struct hci_dev *hdev;
struct serdev_device *serdev;
struct clk *clk;
+ struct regulator *vcc;
+ struct gpio_desc *reset;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_runtime;
+ struct pinctrl_state *pins_boot;
+ speed_t desired_speed;
+ speed_t curr_speed;
+
struct work_struct tx_work;
unsigned long tx_state;
struct sk_buff_head txq;
struct sk_buff *rx_skb;
+ struct sk_buff *evt_skb;
u8 stp_pad[6];
u8 stp_cursor;
u16 stp_dlen;
+
+ const struct btmtkuart_data *data;
};
-static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen,
- const void *param)
+#define btmtkuart_is_standalone(bdev) \
+ ((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW)
+#define btmtkuart_is_builtin_soc(bdev) \
+ !((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW)
+
+static int mtk_hci_wmt_sync(struct hci_dev *hdev,
+ struct btmtk_hci_wmt_params *wmt_params)
{
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
+ struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
+ u32 hlen, status = BTMTK_WMT_INVALID;
+ struct btmtk_hci_wmt_evt *wmt_evt;
struct mtk_hci_wmt_cmd wc;
struct mtk_wmt_hdr *hdr;
- u32 hlen;
int err;
- hlen = sizeof(*hdr) + plen;
+ hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255)
return -EINVAL;
hdr = (struct mtk_wmt_hdr *)&wc;
hdr->dir = 1;
- hdr->op = op;
- hdr->dlen = cpu_to_le16(plen + 1);
- hdr->flag = flag;
- memcpy(wc.data, param, plen);
+ hdr->op = wmt_params->op;
+ hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
+ hdr->flag = wmt_params->flag;
+ memcpy(wc.data, wmt_params->data, wmt_params->dlen);
set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
@@ -107,7 +179,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen,
* Complete as with usual HCI command flow control.
*
* After sending the command, wait for BTMTKUART_TX_WAIT_VND_EVT
- * state to be cleared. The driver speicfic event receive routine
+ * state to be cleared. The driver specific event receive routine
* will clear that state and with that indicate completion of the
* WMT command.
*/
@@ -115,26 +187,63 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen,
TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted");
+ clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
return err;
}
if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out");
+ clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
return -ETIMEDOUT;
}
- return 0;
+ /* Parse and handle the return WMT event */
+ wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
+ if (wmt_evt->whdr.op != hdr->op) {
+ bt_dev_err(hdev, "Wrong op received %d expected %d",
+ wmt_evt->whdr.op, hdr->op);
+ err = -EIO;
+ goto err_free_skb;
+ }
+
+ switch (wmt_evt->whdr.op) {
+ case MTK_WMT_SEMAPHORE:
+ if (wmt_evt->whdr.flag == 2)
+ status = BTMTK_WMT_PATCH_UNDONE;
+ else
+ status = BTMTK_WMT_PATCH_DONE;
+ break;
+ case MTK_WMT_FUNC_CTRL:
+ wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
+ if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
+ status = BTMTK_WMT_ON_DONE;
+ else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
+ status = BTMTK_WMT_ON_PROGRESS;
+ else
+ status = BTMTK_WMT_ON_UNDONE;
+ break;
+ }
+
+ if (wmt_params->status)
+ *wmt_params->status = status;
+
+err_free_skb:
+ kfree_skb(bdev->evt_skb);
+ bdev->evt_skb = NULL;
+
+ return err;
}
-static int mtk_setup_fw(struct hci_dev *hdev)
+static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
{
+ struct btmtk_hci_wmt_params wmt_params;
const struct firmware *fw;
const u8 *fw_ptr;
size_t fw_size;
int err, dlen;
u8 flag;
- err = request_firmware(&fw, FIRMWARE_MT7622, &hdev->dev);
+ err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
return err;
@@ -153,6 +262,9 @@ static int mtk_setup_fw(struct hci_dev *hdev)
fw_ptr += 30;
flag = 1;
+ wmt_params.op = MTK_WMT_PATCH_DWNLD;
+ wmt_params.status = NULL;
+
while (fw_size > 0) {
dlen = min_t(int, 250, fw_size);
@@ -162,18 +274,37 @@ static int mtk_setup_fw(struct hci_dev *hdev)
else if (fw_size < fw->size - 30)
flag = 2;
- err = mtk_hci_wmt_sync(hdev, MTK_WMT_PATCH_DWNLD, flag, dlen,
- fw_ptr);
+ wmt_params.flag = flag;
+ wmt_params.dlen = dlen;
+ wmt_params.data = fw_ptr;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
err);
- break;
+ goto free_fw;
}
fw_size -= dlen;
fw_ptr += dlen;
}
+ wmt_params.op = MTK_WMT_RST;
+ wmt_params.flag = 4;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = NULL;
+
+ /* Activate funciton the firmware providing to */
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
+ goto free_fw;
+ }
+
+ /* Wait a few moments for firmware activation done */
+ usleep_range(10000, 12000);
+
free_fw:
release_firmware(fw);
return err;
@@ -192,7 +323,20 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
if (hdr->evt == 0xe4)
hdr->evt = HCI_EV_VENDOR;
+ /* When someone waits for the WMT event, the skb is being cloned
+ * and being processed the events from there then.
+ */
+ if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) {
+ bdev->evt_skb = skb_clone(skb, GFP_KERNEL);
+ if (!bdev->evt_skb) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ }
+
err = hci_recv_frame(hdev, skb);
+ if (err < 0)
+ goto err_free_skb;
if (hdr->evt == HCI_EV_VENDOR) {
if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT,
@@ -203,6 +347,13 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
}
}
+ return 0;
+
+err_free_skb:
+ kfree_skb(bdev->evt_skb);
+ bdev->evt_skb = NULL;
+
+err_out:
return err;
}
@@ -404,6 +555,23 @@ static int btmtkuart_open(struct hci_dev *hdev)
goto err_open;
}
+ if (btmtkuart_is_standalone(bdev)) {
+ if (bdev->curr_speed != bdev->desired_speed)
+ err = serdev_device_set_baudrate(bdev->serdev,
+ 115200);
+ else
+ err = serdev_device_set_baudrate(bdev->serdev,
+ bdev->desired_speed);
+
+ if (err < 0) {
+ bt_dev_err(hdev, "Unable to set baudrate UART device %s",
+ dev_name(&bdev->serdev->dev));
+ goto err_serdev_close;
+ }
+
+ serdev_device_set_flow_control(bdev->serdev, false);
+ }
+
bdev->stp_cursor = 2;
bdev->stp_dlen = 0;
@@ -427,6 +595,8 @@ err_put_rpm:
pm_runtime_put_sync(dev);
err_disable_rpm:
pm_runtime_disable(dev);
+err_serdev_close:
+ serdev_device_close(bdev->serdev);
err_open:
return err;
}
@@ -465,42 +635,222 @@ static int btmtkuart_flush(struct hci_dev *hdev)
return 0;
}
+static int btmtkuart_func_query(struct hci_dev *hdev)
+{
+ struct btmtk_hci_wmt_params wmt_params;
+ int status, err;
+ u8 param = 0;
+
+ /* Query whether the function is enabled */
+ wmt_params.op = MTK_WMT_FUNC_CTRL;
+ wmt_params.flag = 4;
+ wmt_params.dlen = sizeof(param);
+ wmt_params.data = &param;
+ wmt_params.status = &status;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to query function status (%d)", err);
+ return err;
+ }
+
+ return status;
+}
+
+static int btmtkuart_change_baudrate(struct hci_dev *hdev)
+{
+ struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
+ struct btmtk_hci_wmt_params wmt_params;
+ u32 baudrate;
+ u8 param;
+ int err;
+
+ /* Indicate the device to enter the probe state the host is
+ * ready to change a new baudrate.
+ */
+ baudrate = cpu_to_le32(bdev->desired_speed);
+ wmt_params.op = MTK_WMT_HIF;
+ wmt_params.flag = 1;
+ wmt_params.dlen = 4;
+ wmt_params.data = &baudrate;
+ wmt_params.status = NULL;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to device baudrate (%d)", err);
+ return err;
+ }
+
+ err = serdev_device_set_baudrate(bdev->serdev,
+ bdev->desired_speed);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to set up host baudrate (%d)",
+ err);
+ return err;
+ }
+
+ serdev_device_set_flow_control(bdev->serdev, false);
+
+ /* Send a dummy byte 0xff to activate the new baudrate */
+ param = 0xff;
+ err = serdev_device_write(bdev->serdev, &param, sizeof(param),
+ MAX_SCHEDULE_TIMEOUT);
+ if (err < 0 || err < sizeof(param))
+ return err;
+
+ serdev_device_wait_until_sent(bdev->serdev, 0);
+
+ /* Wait some time for the device changing baudrate done */
+ usleep_range(20000, 22000);
+
+ /* Test the new baudrate */
+ wmt_params.op = MTK_WMT_TEST;
+ wmt_params.flag = 7;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = NULL;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to test new baudrate (%d)",
+ err);
+ return err;
+ }
+
+ bdev->curr_speed = bdev->desired_speed;
+
+ return 0;
+}
+
static int btmtkuart_setup(struct hci_dev *hdev)
{
+ struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
+ struct btmtk_hci_wmt_params wmt_params;
+ ktime_t calltime, delta, rettime;
+ struct btmtk_tci_sleep tci_sleep;
+ unsigned long long duration;
+ struct sk_buff *skb;
+ int err, status;
u8 param = 0x1;
- int err = 0;
+
+ calltime = ktime_get();
+
+ /* Wakeup MCUSYS is required for certain devices before we start to
+ * do any setups.
+ */
+ if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) {
+ wmt_params.op = MTK_WMT_WAKEUP;
+ wmt_params.flag = 3;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = NULL;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to wakeup the chip (%d)", err);
+ return err;
+ }
+
+ clear_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state);
+ }
+
+ if (btmtkuart_is_standalone(bdev))
+ btmtkuart_change_baudrate(hdev);
+
+ /* Query whether the firmware is already download */
+ wmt_params.op = MTK_WMT_SEMAPHORE;
+ wmt_params.flag = 1;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = &status;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
+ return err;
+ }
+
+ if (status == BTMTK_WMT_PATCH_DONE) {
+ bt_dev_info(hdev, "Firmware already downloaded");
+ goto ignore_setup_fw;
+ }
/* Setup a firmware which the device definitely requires */
- err = mtk_setup_fw(hdev);
+ err = mtk_setup_firmware(hdev, bdev->data->fwname);
if (err < 0)
return err;
- /* Activate function the firmware providing to */
- err = mtk_hci_wmt_sync(hdev, MTK_WMT_RST, 0x4, 0, 0);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
+ignore_setup_fw:
+ /* Query whether the device is already enabled */
+ err = readx_poll_timeout(btmtkuart_func_query, hdev, status,
+ status < 0 || status != BTMTK_WMT_ON_PROGRESS,
+ 2000, 5000000);
+ /* -ETIMEDOUT happens */
+ if (err < 0)
return err;
+
+ /* The other errors happen in btusb_mtk_func_query */
+ if (status < 0)
+ return status;
+
+ if (status == BTMTK_WMT_ON_DONE) {
+ bt_dev_info(hdev, "function already on");
+ goto ignore_func_on;
}
/* Enable Bluetooth protocol */
- err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param),
- &param);
+ wmt_params.op = MTK_WMT_FUNC_CTRL;
+ wmt_params.flag = 0;
+ wmt_params.dlen = sizeof(param);
+ wmt_params.data = &param;
+ wmt_params.status = NULL;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
return err;
}
+ignore_func_on:
+ /* Apply the low power environment setup */
+ tci_sleep.mode = 0x5;
+ tci_sleep.duration = cpu_to_le16(0x640);
+ tci_sleep.host_duration = cpu_to_le16(0x640);
+ tci_sleep.host_wakeup_pin = 0;
+ tci_sleep.time_compensation = 0;
+
+ skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
+ return err;
+ }
+ kfree_skb(skb);
+
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Device setup in %llu usecs", duration);
+
return 0;
}
static int btmtkuart_shutdown(struct hci_dev *hdev)
{
+ struct btmtk_hci_wmt_params wmt_params;
u8 param = 0x0;
int err;
/* Disable the device */
- err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param),
- &param);
+ wmt_params.op = MTK_WMT_FUNC_CTRL;
+ wmt_params.flag = 0;
+ wmt_params.dlen = sizeof(param);
+ wmt_params.data = &param;
+ wmt_params.status = NULL;
+
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
return err;
@@ -543,24 +893,82 @@ static int btmtkuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
+static int btmtkuart_parse_dt(struct serdev_device *serdev)
+{
+ struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
+ struct device_node *node = serdev->dev.of_node;
+ u32 speed = 921600;
+ int err;
+
+ if (btmtkuart_is_standalone(bdev)) {
+ of_property_read_u32(node, "current-speed", &speed);
+
+ bdev->desired_speed = speed;
+
+ bdev->vcc = devm_regulator_get(&serdev->dev, "vcc");
+ if (IS_ERR(bdev->vcc)) {
+ err = PTR_ERR(bdev->vcc);
+ return err;
+ }
+
+ bdev->pinctrl = devm_pinctrl_get(&serdev->dev);
+ if (IS_ERR(bdev->pinctrl)) {
+ err = PTR_ERR(bdev->pinctrl);
+ return err;
+ }
+
+ bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl,
+ "default");
+ if (IS_ERR(bdev->pins_boot)) {
+ err = PTR_ERR(bdev->pins_boot);
+ return err;
+ }
+
+ bdev->pins_runtime = pinctrl_lookup_state(bdev->pinctrl,
+ "runtime");
+ if (IS_ERR(bdev->pins_runtime)) {
+ err = PTR_ERR(bdev->pins_runtime);
+ return err;
+ }
+
+ bdev->reset = devm_gpiod_get_optional(&serdev->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(bdev->reset)) {
+ err = PTR_ERR(bdev->reset);
+ return err;
+ }
+ } else if (btmtkuart_is_builtin_soc(bdev)) {
+ bdev->clk = devm_clk_get(&serdev->dev, "ref");
+ if (IS_ERR(bdev->clk))
+ return PTR_ERR(bdev->clk);
+ }
+
+ return 0;
+}
+
static int btmtkuart_probe(struct serdev_device *serdev)
{
struct btmtkuart_dev *bdev;
struct hci_dev *hdev;
+ int err;
bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL);
if (!bdev)
return -ENOMEM;
- bdev->clk = devm_clk_get(&serdev->dev, "ref");
- if (IS_ERR(bdev->clk))
- return PTR_ERR(bdev->clk);
+ bdev->data = of_device_get_match_data(&serdev->dev);
+ if (!bdev->data)
+ return -ENODEV;
bdev->serdev = serdev;
serdev_device_set_drvdata(serdev, bdev);
serdev_device_set_client_ops(serdev, &btmtkuart_client_ops);
+ err = btmtkuart_parse_dt(serdev);
+ if (err < 0)
+ return err;
+
INIT_WORK(&bdev->tx_work, btmtkuart_tx_work);
skb_queue_head_init(&bdev->txq);
@@ -587,13 +995,54 @@ static int btmtkuart_probe(struct serdev_device *serdev)
hdev->manufacturer = 70;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
- if (hci_register_dev(hdev) < 0) {
+ if (btmtkuart_is_standalone(bdev)) {
+ /* Switch to the specific pin state for the booting requires */
+ pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
+
+ /* Power on */
+ err = regulator_enable(bdev->vcc);
+ if (err < 0)
+ return err;
+
+ /* Reset if the reset-gpios is available otherwise the board
+ * -level design should be guaranteed.
+ */
+ if (bdev->reset) {
+ gpiod_set_value_cansleep(bdev->reset, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(bdev->reset, 0);
+ }
+
+ /* Wait some time until device got ready and switch to the pin
+ * mode the device requires for UART transfers.
+ */
+ msleep(50);
+ pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime);
+
+ /* A standalone device doesn't depends on power domain on SoC,
+ * so mark it as no callbacks.
+ */
+ pm_runtime_no_callbacks(&serdev->dev);
+
+ set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state);
+ }
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
dev_err(&serdev->dev, "Can't register HCI device\n");
hci_free_dev(hdev);
- return -ENODEV;
+ goto err_regulator_disable;
}
return 0;
+
+err_regulator_disable:
+ if (btmtkuart_is_standalone(bdev)) {
+ pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
+ regulator_disable(bdev->vcc);
+ }
+
+ return err;
}
static void btmtkuart_remove(struct serdev_device *serdev)
@@ -601,13 +1050,34 @@ static void btmtkuart_remove(struct serdev_device *serdev)
struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
struct hci_dev *hdev = bdev->hdev;
+ if (btmtkuart_is_standalone(bdev)) {
+ pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
+ regulator_disable(bdev->vcc);
+ }
+
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
+static const struct btmtkuart_data mt7622_data = {
+ .fwname = FIRMWARE_MT7622,
+};
+
+static const struct btmtkuart_data mt7663_data = {
+ .flags = BTMTKUART_FLAG_STANDALONE_HW,
+ .fwname = FIRMWARE_MT7663,
+};
+
+static const struct btmtkuart_data mt7668_data = {
+ .flags = BTMTKUART_FLAG_STANDALONE_HW,
+ .fwname = FIRMWARE_MT7668,
+};
+
#ifdef CONFIG_OF
static const struct of_device_id mtk_of_match_table[] = {
- { .compatible = "mediatek,mt7622-bluetooth"},
+ { .compatible = "mediatek,mt7622-bluetooth", .data = &mt7622_data},
+ { .compatible = "mediatek,mt7663u-bluetooth", .data = &mt7663_data},
+ { .compatible = "mediatek,mt7668u-bluetooth", .data = &mt7668_data},
{ }
};
MODULE_DEVICE_TABLE(of, mtk_of_match_table);
@@ -629,3 +1099,5 @@ MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7622);
+MODULE_FIRMWARE(FIRMWARE_MT7663);
+MODULE_FIRMWARE(FIRMWARE_MT7668);
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index ec9e03a6b778..612268574fc7 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -391,6 +391,25 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
EXPORT_SYMBOL_GPL(qca_uart_setup);
+int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ int err;
+
+ skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr,
+ HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err);
+ return err;
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qca_set_bdaddr);
+
MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>");
MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index 0c01f375fe83..c72c56ea7480 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -20,6 +20,7 @@
#define EDL_PATCH_CMD_OPCODE (0xFC00)
#define EDL_NVM_ACCESS_OPCODE (0xFC0B)
+#define EDL_WRITE_BD_ADDR_OPCODE (0xFC14)
#define EDL_PATCH_CMD_LEN (1)
#define EDL_PATCH_VER_REQ_CMD (0x19)
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
@@ -140,7 +141,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, u32 soc_ver);
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
-
+int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
#else
static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
@@ -159,4 +160,9 @@ static inline int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)
return -EOPNOTSUPP;
}
+static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ return -EOPNOTSUPP;
+}
+
#endif
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c
index 7df3eed1ef5e..e0d4c6f1d3ab 100644
--- a/drivers/bluetooth/btqcomsmd.c
+++ b/drivers/bluetooth/btqcomsmd.c
@@ -28,7 +28,6 @@
struct btqcomsmd {
struct hci_dev *hdev;
- bdaddr_t bdaddr;
struct rpmsg_endpoint *acl_channel;
struct rpmsg_endpoint *cmd_channel;
};
@@ -116,32 +115,17 @@ static int btqcomsmd_close(struct hci_dev *hdev)
static int btqcomsmd_setup(struct hci_dev *hdev)
{
- struct btqcomsmd *btq = hci_get_drvdata(hdev);
struct sk_buff *skb;
- int err;
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb);
- /* Devices do not have persistent storage for BD address. If no
- * BD address has been retrieved during probe, mark the device
- * as having an invalid BD address.
- */
- if (!bacmp(&btq->bdaddr, BDADDR_ANY)) {
- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
- return 0;
- }
-
- /* When setting a configured BD address fails, mark the device
- * as having an invalid BD address.
+ /* Devices do not have persistent storage for BD address. Retrieve
+ * it from the firmware node property.
*/
- err = qca_set_bdaddr_rome(hdev, &btq->bdaddr);
- if (err) {
- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
- return 0;
- }
+ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
return 0;
}
@@ -169,15 +153,6 @@ static int btqcomsmd_probe(struct platform_device *pdev)
if (IS_ERR(btq->cmd_channel))
return PTR_ERR(btq->cmd_channel);
- /* The local-bd-address property is usually injected by the
- * bootloader which has access to the allocated BD address.
- */
- if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address",
- (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) {
- dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree",
- &btq->bdaddr);
- }
-
hdev = hci_alloc_dev();
if (!hdev)
return -ENOMEM;
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 41405de27d66..c91bba00df4e 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -552,10 +552,9 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
hdev->bus);
if (!btrtl_dev->ic_info) {
- rtl_dev_err(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
+ rtl_dev_info(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
lmp_subver, hci_rev, hci_ver);
- ret = -EINVAL;
- goto err_free;
+ return btrtl_dev;
}
if (btrtl_dev->ic_info->has_rom_version) {
@@ -610,6 +609,11 @@ int btrtl_download_firmware(struct hci_dev *hdev,
* standard btusb. Once that firmware is uploaded, the subver changes
* to a different value.
*/
+ if (!btrtl_dev->ic_info) {
+ rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n");
+ return 0;
+ }
+
switch (btrtl_dev->ic_info->lmp_subver) {
case RTL_ROM_LMP_8723A:
case RTL_ROM_LMP_3499:
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 4761499db9ee..ded198328f21 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -29,6 +29,7 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/suspend.h>
+#include <linux/gpio/consumer.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -439,6 +440,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
#define BTUSB_BOOTING 9
#define BTUSB_DIAG_RUNNING 10
#define BTUSB_OOB_WAKE_ENABLED 11
+#define BTUSB_HW_RESET_ACTIVE 12
struct btusb_data {
struct hci_dev *hdev;
@@ -476,6 +478,8 @@ struct btusb_data {
struct usb_endpoint_descriptor *diag_tx_ep;
struct usb_endpoint_descriptor *diag_rx_ep;
+ struct gpio_desc *reset_gpio;
+
__u8 cmdreq_type;
__u8 cmdreq;
@@ -489,8 +493,41 @@ struct btusb_data {
int (*setup_on_usb)(struct hci_dev *hdev);
int oob_wake_irq; /* irq for out-of-band wake-on-bt */
+ unsigned cmd_timeout_cnt;
};
+
+static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct gpio_desc *reset_gpio = data->reset_gpio;
+
+ if (++data->cmd_timeout_cnt < 5)
+ return;
+
+ if (!reset_gpio) {
+ bt_dev_err(hdev, "No way to reset. Ignoring and continuing");
+ return;
+ }
+
+ /*
+ * Toggle the hard reset line if the platform provides one. The reset
+ * is going to yank the device off the USB and then replug. So doing
+ * once is enough. The cleanup is handled correctly on the way out
+ * (standard USB disconnect), and the new device is detected cleanly
+ * and bound to the driver again like it should be.
+ */
+ if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
+ bt_dev_err(hdev, "last reset failed? Not resetting again");
+ return;
+ }
+
+ bt_dev_err(hdev, "Initiating HW reset via gpio");
+ gpiod_set_value_cansleep(reset_gpio, 1);
+ msleep(100);
+ gpiod_set_value_cansleep(reset_gpio, 0);
+}
+
static inline void btusb_free_frags(struct btusb_data *data)
{
unsigned long flags;
@@ -2397,6 +2434,24 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
return 0;
}
+static int btusb_shutdown_intel_new(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ /* Send HCI Reset to the controller to stop any BT activity which
+ * were triggered. This will help to save power and maintain the
+ * sync b/w Host and controller
+ */
+ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "HCI reset during shutdown failed");
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
#ifdef CONFIG_PM
/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
static int marvell_config_oob_wake(struct hci_dev *hdev)
@@ -2862,6 +2917,8 @@ static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
static const struct of_device_id btusb_match_table[] = {
{ .compatible = "usb1286,204e" },
+ { .compatible = "usbcf3,e300" }, /* QCA6174A */
+ { .compatible = "usb4ca,301a" }, /* QCA6174A (Lite-On) */
{ }
};
MODULE_DEVICE_TABLE(of, btusb_match_table);
@@ -2915,6 +2972,7 @@ static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *ep_desc;
+ struct gpio_desc *reset_gpio;
struct btusb_data *data;
struct hci_dev *hdev;
unsigned ifnum_base;
@@ -3028,6 +3086,15 @@ static int btusb_probe(struct usb_interface *intf,
SET_HCIDEV_DEV(hdev, &intf->dev);
+ reset_gpio = gpiod_get_optional(&data->udev->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio)) {
+ err = PTR_ERR(reset_gpio);
+ goto out_free_dev;
+ } else if (reset_gpio) {
+ data->reset_gpio = reset_gpio;
+ }
+
hdev->open = btusb_open;
hdev->close = btusb_close;
hdev->flush = btusb_flush;
@@ -3082,6 +3149,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->shutdown = btusb_shutdown_intel;
hdev->set_diag = btintel_set_diag_mfg;
hdev->set_bdaddr = btintel_set_bdaddr;
+ hdev->cmd_timeout = btusb_intel_cmd_timeout;
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
@@ -3091,9 +3159,11 @@ static int btusb_probe(struct usb_interface *intf,
hdev->manufacturer = 2;
hdev->send = btusb_send_frame_intel;
hdev->setup = btusb_setup_intel_new;
+ hdev->shutdown = btusb_shutdown_intel_new;
hdev->hw_error = btintel_hw_error;
hdev->set_diag = btintel_set_diag;
hdev->set_bdaddr = btintel_set_bdaddr;
+ hdev->cmd_timeout = btusb_intel_cmd_timeout;
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
@@ -3226,6 +3296,8 @@ static int btusb_probe(struct usb_interface *intf,
return 0;
out_free_dev:
+ if (data->reset_gpio)
+ gpiod_put(data->reset_gpio);
hci_free_dev(hdev);
return err;
}
@@ -3269,6 +3341,9 @@ static void btusb_disconnect(struct usb_interface *intf)
if (data->oob_wake_irq)
device_init_wakeup(&data->udev->dev, false);
+ if (data->reset_gpio)
+ gpiod_put(data->reset_gpio);
+
hci_free_dev(hdev);
}
diff --git a/drivers/bluetooth/h4_recv.h b/drivers/bluetooth/h4_recv.h
index b432651f8236..87ccaceadba7 100644
--- a/drivers/bluetooth/h4_recv.h
+++ b/drivers/bluetooth/h4_recv.h
@@ -60,12 +60,13 @@ static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev,
const struct h4_recv_pkt *pkts,
int pkts_count)
{
+ /* Check for error from previous call */
+ if (IS_ERR(skb))
+ skb = NULL;
+
while (count) {
int i, len;
- if (!count)
- break;
-
if (!skb) {
for (i = 0; i < pkts_count; i++) {
if (buffer[0] != (&pkts[i])->type)
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index fb97a3bf069b..5d97d77627c1 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -174,6 +174,10 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
struct hci_uart *hu = hci_get_drvdata(hdev);
u8 alignment = hu->alignment ? hu->alignment : 1;
+ /* Check for error from previous call */
+ if (IS_ERR(skb))
+ skb = NULL;
+
while (count) {
int i, len;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index fbf7b4df23ab..9562e72c1ae5 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -207,11 +207,11 @@ void hci_uart_init_work(struct work_struct *work)
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
+ clear_bit(HCI_UART_PROTO_READY, &hu->flags);
+ hu->proto->close(hu);
hdev = hu->hdev;
hu->hdev = NULL;
hci_free_dev(hdev);
- clear_bit(HCI_UART_PROTO_READY, &hu->flags);
- hu->proto->close(hu);
return;
}
@@ -616,6 +616,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
static int hci_uart_register_dev(struct hci_uart *hu)
{
struct hci_dev *hdev;
+ int err;
BT_DBG("");
@@ -659,11 +660,22 @@ static int hci_uart_register_dev(struct hci_uart *hu)
else
hdev->dev_type = HCI_PRIMARY;
+ /* Only call open() for the protocol after hdev is fully initialized as
+ * open() (or a timer/workqueue it starts) may attempt to reference it.
+ */
+ err = hu->proto->open(hu);
+ if (err) {
+ hu->hdev = NULL;
+ hci_free_dev(hdev);
+ return err;
+ }
+
if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return 0;
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
+ hu->proto->close(hu);
hu->hdev = NULL;
hci_free_dev(hdev);
return -ENODEV;
@@ -683,20 +695,14 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
if (!p)
return -EPROTONOSUPPORT;
- err = p->open(hu);
- if (err)
- return err;
-
hu->proto = p;
- set_bit(HCI_UART_PROTO_READY, &hu->flags);
err = hci_uart_register_dev(hu);
if (err) {
- clear_bit(HCI_UART_PROTO_READY, &hu->flags);
- p->close(hu);
return err;
}
+ set_bit(HCI_UART_PROTO_READY, &hu->flags);
return 0;
}
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index f036c8f98ea3..237aea34b69f 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -59,7 +59,7 @@
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_TX_IDLE_TIMEOUT_MS 2000
-#define BAUDRATE_SETTLE_TIMEOUT_MS 300
+#define CMD_TRANS_TIMEOUT_MS 100
/* susclk rate */
#define SUSCLK_RATE_32KHZ 32768
@@ -770,16 +770,17 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+ spin_lock_irqsave(&qca->hci_ibs_lock, flags);
+
/* Don't go to sleep in middle of patch download or
* Out-Of-Band(GPIOs control) sleep is selected.
*/
if (!test_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags)) {
skb_queue_tail(&qca->txq, skb);
+ spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
return 0;
}
- spin_lock_irqsave(&qca->hci_ibs_lock, flags);
-
/* Act according to current state */
switch (qca->tx_ibs_state) {
case HCI_IBS_TX_AWAKE:
@@ -962,8 +963,8 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
- struct sk_buff *skb;
struct qca_serdev *qcadev;
+ struct sk_buff *skb;
u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 };
if (baudrate > QCA_BAUDRATE_3200000)
@@ -977,13 +978,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
return -ENOMEM;
}
- /* Disabling hardware flow control is mandatory while
- * sending change baudrate request to wcn3990 SoC.
- */
- qcadev = serdev_device_get_drvdata(hu->serdev);
- if (qcadev->btsoc_type == QCA_WCN3990)
- hci_uart_set_flow_control(hu, true);
-
/* Assign commands to change baudrate and packet type. */
skb_put_data(skb, cmd, sizeof(cmd));
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
@@ -991,16 +985,21 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
skb_queue_tail(&qca->txq, skb);
hci_uart_tx_wakeup(hu);
- /* wait 300ms to change new baudrate on controller side
- * controller will come back after they receive this HCI command
- * then host can communicate with new baudrate to controller
- */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS));
- set_current_state(TASK_RUNNING);
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+
+ /* Wait for the baudrate change request to be sent */
+
+ while (!skb_queue_empty(&qca->txq))
+ usleep_range(100, 200);
+ serdev_device_wait_until_sent(hu->serdev,
+ msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
+
+ /* Give the controller time to process the request */
if (qcadev->btsoc_type == QCA_WCN3990)
- hci_uart_set_flow_control(hu, false);
+ msleep(10);
+ else
+ msleep(300);
return 0;
}
@@ -1013,11 +1012,11 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
hci_uart_set_baudrate(hu, speed);
}
-static int qca_send_power_pulse(struct hci_dev *hdev, u8 cmd)
+static int qca_send_power_pulse(struct hci_uart *hu, bool on)
{
- struct hci_uart *hu = hci_get_drvdata(hdev);
- struct qca_data *qca = hu->priv;
- struct sk_buff *skb;
+ int ret;
+ int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
+ u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE;
/* These power pulses are single byte command which are sent
* at required baudrate to wcn3990. On wcn3990, we have an external
@@ -1029,24 +1028,25 @@ static int qca_send_power_pulse(struct hci_dev *hdev, u8 cmd)
* save power. Disabling hardware flow control is mandatory while
* sending power pulses to SoC.
*/
- bt_dev_dbg(hdev, "sending power pulse %02x to SoC", cmd);
-
- skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
+ bt_dev_dbg(hu->hdev, "sending power pulse %02x to controller", cmd);
+ serdev_device_write_flush(hu->serdev);
hci_uart_set_flow_control(hu, true);
+ ret = serdev_device_write_buf(hu->serdev, &cmd, sizeof(cmd));
+ if (ret < 0) {
+ bt_dev_err(hu->hdev, "failed to send power pulse %02x", cmd);
+ return ret;
+ }
- skb_put_u8(skb, cmd);
- hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
-
- skb_queue_tail(&qca->txq, skb);
- hci_uart_tx_wakeup(hu);
-
- /* Wait for 100 uS for SoC to settle down */
- usleep_range(100, 200);
+ serdev_device_wait_until_sent(hu->serdev, timeout);
hci_uart_set_flow_control(hu, false);
+ /* Give to controller time to boot/shutdown */
+ if (on)
+ msleep(100);
+ else
+ msleep(10);
+
return 0;
}
@@ -1091,7 +1091,8 @@ static int qca_check_speeds(struct hci_uart *hu)
static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
{
unsigned int speed, qca_baudrate;
- int ret;
+ struct qca_serdev *qcadev;
+ int ret = 0;
if (speed_type == QCA_INIT_SPEED) {
speed = qca_get_speed(hu, QCA_INIT_SPEED);
@@ -1102,21 +1103,31 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
if (!speed)
return 0;
+ /* Disable flow control for wcn3990 to deassert RTS while
+ * changing the baudrate of chip and host.
+ */
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+ if (qcadev->btsoc_type == QCA_WCN3990)
+ hci_uart_set_flow_control(hu, true);
+
qca_baudrate = qca_get_baudrate_value(speed);
bt_dev_dbg(hu->hdev, "Set UART speed to %d", speed);
ret = qca_set_baudrate(hu->hdev, qca_baudrate);
if (ret)
- return ret;
+ goto error;
host_set_baudrate(hu, speed);
+
+error:
+ if (qcadev->btsoc_type == QCA_WCN3990)
+ hci_uart_set_flow_control(hu, false);
}
- return 0;
+ return ret;
}
static int qca_wcn3990_init(struct hci_uart *hu)
{
- struct hci_dev *hdev = hu->hdev;
struct qca_serdev *qcadev;
int ret;
@@ -1139,18 +1150,15 @@ static int qca_wcn3990_init(struct hci_uart *hu)
/* Forcefully enable wcn3990 to enter in to boot mode. */
host_set_baudrate(hu, 2400);
- ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE);
+ ret = qca_send_power_pulse(hu, false);
if (ret)
return ret;
qca_set_speed(hu, QCA_INIT_SPEED);
- ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWERON_PULSE);
+ ret = qca_send_power_pulse(hu, true);
if (ret)
return ret;
- /* Wait for 100 ms for SoC to boot */
- msleep(100);
-
/* Now the device is in ready state to communicate with host.
* To sync host with device we need to reopen port.
* Without this, we will have RTS and CTS synchronization
@@ -1193,6 +1201,7 @@ static int qca_setup(struct hci_uart *hu)
* setup for every hci up.
*/
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
hu->hdev->shutdown = qca_power_off;
ret = qca_wcn3990_init(hu);
if (ret)
@@ -1241,7 +1250,10 @@ static int qca_setup(struct hci_uart *hu)
}
/* Setup bdaddr */
- hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
+ if (qcadev->btsoc_type == QCA_WCN3990)
+ hu->hdev->set_bdaddr = qca_set_bdaddr;
+ else
+ hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
return ret;
}
@@ -1274,13 +1286,20 @@ static const struct qca_vreg_data qca_soc_data = {
static void qca_power_shutdown(struct hci_uart *hu)
{
- struct serdev_device *serdev = hu->serdev;
- unsigned char cmd = QCA_WCN3990_POWEROFF_PULSE;
+ struct qca_data *qca = hu->priv;
+ unsigned long flags;
+
+ /* From this point we go into power off state. But serial port is
+ * still open, stop queueing the IBS data and flush all the buffered
+ * data in skb's.
+ */
+ spin_lock_irqsave(&qca->hci_ibs_lock, flags);
+ clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
+ qca_flush(hu);
+ spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
host_set_baudrate(hu, 2400);
- hci_uart_set_flow_control(hu, true);
- serdev_device_write_buf(serdev, &cmd, sizeof(cmd));
- hci_uart_set_flow_control(hu, false);
+ qca_send_power_pulse(hu, false);
qca_power_setup(hu, false);
}
diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
index e906ecfe23dd..8ad77246f322 100644
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -295,6 +295,14 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
if (!mc_adev)
goto error;
+ mc_adev->consumer_link = device_link_add(&mc_dev->dev,
+ &mc_adev->dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!mc_adev->consumer_link) {
+ error = -EINVAL;
+ goto error;
+ }
+
*new_mc_adev = mc_adev;
return 0;
error:
@@ -321,6 +329,9 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
return;
fsl_mc_resource_free(resource);
+
+ device_link_del(mc_adev->consumer_link);
+ mc_adev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_object_free);
diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
index 7226cfc49b6f..3ae574a58cce 100644
--- a/drivers/bus/fsl-mc/mc-io.c
+++ b/drivers/bus/fsl-mc/mc-io.c
@@ -209,9 +209,19 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
if (error < 0)
goto error_cleanup_resource;
+ dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
+ &dpmcp_dev->dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!dpmcp_dev->consumer_link) {
+ error = -EINVAL;
+ goto error_cleanup_mc_io;
+ }
+
*new_mc_io = mc_io;
return 0;
+error_cleanup_mc_io:
+ fsl_destroy_mc_io(mc_io);
error_cleanup_resource:
fsl_mc_resource_free(resource);
return error;
@@ -244,6 +254,9 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
fsl_destroy_mc_io(mc_io);
fsl_mc_resource_free(resource);
+
+ device_link_del(dpmcp_dev->consumer_link);
+ dpmcp_dev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index d5f85455fa62..19d7b6ff2f17 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -522,10 +522,9 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
if (!found) {
dev_warn(hostdev,
- "could not find cell for child device (%s)\n",
+ "could not find cell for child device (%s), discarding\n",
hid);
- ret = -ENODEV;
- goto fail;
+ continue;
}
pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index d84996a4528e..db74334ca5ef 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -46,6 +46,17 @@ static const struct imx_weim_devtype imx51_weim_devtype = {
};
#define MAX_CS_REGS_COUNT 6
+#define MAX_CS_COUNT 6
+#define OF_REG_SIZE 3
+
+struct cs_timing {
+ bool is_applied;
+ u32 regs[MAX_CS_REGS_COUNT];
+};
+
+struct cs_timing_state {
+ struct cs_timing cs[MAX_CS_COUNT];
+};
static const struct of_device_id weim_id_table[] = {
/* i.MX1/21 */
@@ -111,21 +122,19 @@ err:
}
/* Parse and set the timing for this device. */
-static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
- const struct imx_weim_devtype *devtype)
+static int __init weim_timing_setup(struct device *dev,
+ struct device_node *np, void __iomem *base,
+ const struct imx_weim_devtype *devtype,
+ struct cs_timing_state *ts)
{
u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
+ int reg_idx, num_regs;
+ struct cs_timing *cst;
if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
return -EINVAL;
-
- /* get the CS index from this child node's "reg" property. */
- ret = of_property_read_u32(np, "reg", &cs_idx);
- if (ret)
- return ret;
-
- if (cs_idx >= devtype->cs_count)
+ if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
return -EINVAL;
ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
@@ -133,9 +142,43 @@ static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
if (ret)
return ret;
- /* set the timing for WEIM */
- for (i = 0; i < devtype->cs_regs_count; i++)
- writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
+ /*
+ * the child node's "reg" property may contain multiple address ranges,
+ * extract the chip select for each.
+ */
+ num_regs = of_property_count_elems_of_size(np, "reg", OF_REG_SIZE);
+ if (num_regs < 0)
+ return num_regs;
+ if (!num_regs)
+ return -EINVAL;
+ for (reg_idx = 0; reg_idx < num_regs; reg_idx++) {
+ /* get the CS index from this child node's "reg" property. */
+ ret = of_property_read_u32_index(np, "reg",
+ reg_idx * OF_REG_SIZE, &cs_idx);
+ if (ret)
+ break;
+
+ if (cs_idx >= devtype->cs_count)
+ return -EINVAL;
+
+ /* prevent re-configuring a CS that's already been configured */
+ cst = &ts->cs[cs_idx];
+ if (cst->is_applied && memcmp(value, cst->regs,
+ devtype->cs_regs_count * sizeof(u32))) {
+ dev_err(dev, "fsl,weim-cs-timing conflict on %pOF", np);
+ return -EINVAL;
+ }
+
+ /* set the timing for WEIM */
+ for (i = 0; i < devtype->cs_regs_count; i++)
+ writel(value[i],
+ base + cs_idx * devtype->cs_stride + i * 4);
+ if (!cst->is_applied) {
+ cst->is_applied = true;
+ memcpy(cst->regs, value,
+ devtype->cs_regs_count * sizeof(u32));
+ }
+ }
return 0;
}
@@ -148,6 +191,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
const struct imx_weim_devtype *devtype = of_id->data;
struct device_node *child;
int ret, have_child = 0;
+ struct cs_timing_state ts = {};
if (devtype == &imx50_weim_devtype) {
ret = imx_weim_gpr_setup(pdev);
@@ -156,7 +200,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
}
for_each_available_child_of_node(pdev->dev.of_node, child) {
- ret = weim_timing_setup(child, base, devtype);
+ ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
if (ret)
dev_warn(&pdev->dev, "%pOF set timing failed.\n",
child);
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index f94d33525771..d299ec79e4c3 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -781,12 +781,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
+ 0),
/* Some timers on omap4 and later */
SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
+ 0),
SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
- SYSC_QUIRK_LEGACY_IDLE),
+ 0),
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
/* Uarts on omap4 and later */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 2e2ffe7010aa..72866a004f07 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -244,26 +244,23 @@ source "drivers/char/hw_random/Kconfig"
config NVRAM
tristate "/dev/nvram support"
- depends on ATARI || X86 || GENERIC_NVRAM
+ depends on X86 || HAVE_ARCH_NVRAM_OPS
+ default M68K || PPC
---help---
If you say Y here and create a character special file /dev/nvram
with major number 10 and minor number 144 using mknod ("man mknod"),
- you get read and write access to the extra bytes of non-volatile
- memory in the real time clock (RTC), which is contained in every PC
- and most Ataris. The actual number of bytes varies, depending on the
- nvram in the system, but is usually 114 (128-14 for the RTC).
-
- This memory is conventionally called "CMOS RAM" on PCs and "NVRAM"
- on Ataris. /dev/nvram may be used to view settings there, or to
- change them (with some utility). It could also be used to frequently
+ you get read and write access to the non-volatile memory.
+
+ /dev/nvram may be used to view settings in NVRAM or to change them
+ (with some utility). It could also be used to frequently
save a few bits of very important data that may not be lost over
power-off and for which writing to disk is too insecure. Note
however that most NVRAM space in a PC belongs to the BIOS and you
should NEVER idly tamper with it. See Ralf Brown's interrupt list
for a guide to the use of CMOS bytes by your BIOS.
- On Atari machines, /dev/nvram is always configured and does not need
- to be selected.
+ This memory is conventionally called "NVRAM" on PowerPC machines,
+ "CMOS RAM" on PCs, "NVRAM" on Ataris and "PRAM" on Macintoshes.
To compile this driver as a module, choose M here: the
module will be called nvram.
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b8d42b4e979b..fbea7dd12932 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -26,11 +26,7 @@ obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_HPET) += hpet.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/
-ifeq ($(CONFIG_GENERIC_NVRAM),y)
- obj-$(CONFIG_NVRAM) += generic_nvram.o
-else
- obj-$(CONFIG_NVRAM) += nvram.o
-endif
+obj-$(CONFIG_NVRAM) += nvram.o
obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random/
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 7f88490b5479..c53f0f9ef5b0 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -163,7 +163,6 @@ static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
unsigned long page = efficeon_private.l1_table[index];
if (page) {
efficeon_private.l1_table[index] = 0;
- ClearPageReserved(virt_to_page((char *)page));
free_page(page);
freed++;
}
@@ -219,7 +218,6 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
efficeon_free_gatt_table(agp_bridge);
return -ENOMEM;
}
- SetPageReserved(virt_to_page((char *)page));
for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
clflush((char *)page+offset);
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index c0a5b1f3a986..4ccc39e00ced 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -32,6 +32,7 @@
#include <linux/wait.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/nospec.h>
#include <asm/io.h>
#include <linux/uaccess.h>
@@ -386,7 +387,11 @@ static ssize_t ac_write(struct file *file, const char __user *buf, size_t count,
TicCard = st_loc.tic_des_from_pc; /* tic number to send */
IndexCard = NumCard - 1;
- if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO)
+ if (IndexCard >= MAX_BOARD)
+ return -EINVAL;
+ IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
+
+ if (!apbs[IndexCard].RamIO)
return -EINVAL;
#ifdef DEBUG
@@ -697,6 +702,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned char IndexCard;
void __iomem *pmem;
int ret = 0;
+ static int warncount = 10;
volatile unsigned char byte_reset_it;
struct st_ram_io *adgl;
void __user *argp = (void __user *)arg;
@@ -711,16 +717,12 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_lock(&ac_mutex);
IndexCard = adgl->num_card-1;
- if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
- static int warncount = 10;
- if (warncount) {
- printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
- warncount--;
- }
- kfree(adgl);
- mutex_unlock(&ac_mutex);
- return -EINVAL;
- }
+ if (cmd != 6 && IndexCard >= MAX_BOARD)
+ goto err;
+ IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
+
+ if (cmd != 6 && !apbs[IndexCard].RamIO)
+ goto err;
switch (cmd) {
@@ -838,5 +840,16 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
kfree(adgl);
mutex_unlock(&ac_mutex);
return 0;
+
+err:
+ if (warncount) {
+ pr_warn("APPLICOM driver IOCTL, bad board number %d\n",
+ (int)IndexCard + 1);
+ warncount--;
+ }
+ kfree(adgl);
+ mutex_unlock(&ac_mutex);
+ return -EINVAL;
+
}
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index d9aab643997e..11781ebffbf7 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -255,35 +255,12 @@ static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
}
/*
- * We enforce only one user at a time here with the open/close.
- * Also clear the previous interrupt data on an open, and clean
- * up things on a close.
- */
-
-static int efi_rtc_open(struct inode *inode, struct file *file)
-{
- /*
- * nothing special to do here
- * We do accept multiple open files at the same time as we
- * synchronize on the per call operation.
- */
- return 0;
-}
-
-static int efi_rtc_close(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-/*
* The various file operations we support.
*/
static const struct file_operations efi_rtc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = efi_rtc_ioctl,
- .open = efi_rtc_open,
- .release = efi_rtc_close,
.llseek = no_llseek,
};
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
deleted file mode 100644
index ff5394f47587..000000000000
--- a/drivers/char/generic_nvram.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Generic /dev/nvram driver for architectures providing some
- * "generic" hooks, that is :
- *
- * nvram_read_byte, nvram_write_byte, nvram_sync, nvram_get_size
- *
- * Note that an additional hook is supported for PowerMac only
- * for getting the nvram "partition" informations
- *
- */
-
-#define NVRAM_VERSION "1.1"
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/pagemap.h>
-#include <linux/uaccess.h>
-#include <asm/nvram.h>
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#endif
-
-#define NVRAM_SIZE 8192
-
-static DEFINE_MUTEX(nvram_mutex);
-static ssize_t nvram_len;
-
-static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
-{
- return generic_file_llseek_size(file, offset, origin,
- MAX_LFS_FILESIZE, nvram_len);
-}
-
-static ssize_t read_nvram(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int i;
- char __user *p = buf;
-
- if (!access_ok(buf, count))
- return -EFAULT;
- if (*ppos >= nvram_len)
- return 0;
- for (i = *ppos; count > 0 && i < nvram_len; ++i, ++p, --count)
- if (__put_user(nvram_read_byte(i), p))
- return -EFAULT;
- *ppos = i;
- return p - buf;
-}
-
-static ssize_t write_nvram(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int i;
- const char __user *p = buf;
- char c;
-
- if (!access_ok(buf, count))
- return -EFAULT;
- if (*ppos >= nvram_len)
- return 0;
- for (i = *ppos; count > 0 && i < nvram_len; ++i, ++p, --count) {
- if (__get_user(c, p))
- return -EFAULT;
- nvram_write_byte(c, i);
- }
- *ppos = i;
- return p - buf;
-}
-
-static int nvram_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- switch(cmd) {
-#ifdef CONFIG_PPC_PMAC
- case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
- printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
- case IOC_NVRAM_GET_OFFSET: {
- int part, offset;
-
- if (!machine_is(powermac))
- return -EINVAL;
- if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
- return -EFAULT;
- if (part < pmac_nvram_OF || part > pmac_nvram_NR)
- return -EINVAL;
- offset = pmac_get_partition(part);
- if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
- return -EFAULT;
- break;
- }
-#endif /* CONFIG_PPC_PMAC */
- case IOC_NVRAM_SYNC:
- nvram_sync();
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static long nvram_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- mutex_lock(&nvram_mutex);
- ret = nvram_ioctl(file, cmd, arg);
- mutex_unlock(&nvram_mutex);
-
- return ret;
-}
-
-const struct file_operations nvram_fops = {
- .owner = THIS_MODULE,
- .llseek = nvram_llseek,
- .read = read_nvram,
- .write = write_nvram,
- .unlocked_ioctl = nvram_unlocked_ioctl,
-};
-
-static struct miscdevice nvram_dev = {
- NVRAM_MINOR,
- "nvram",
- &nvram_fops
-};
-
-int __init nvram_init(void)
-{
- int ret = 0;
-
- printk(KERN_INFO "Generic non-volatile memory driver v%s\n",
- NVRAM_VERSION);
- ret = misc_register(&nvram_dev);
- if (ret != 0)
- goto out;
-
- nvram_len = nvram_get_size();
- if (nvram_len < 0)
- nvram_len = NVRAM_SIZE;
-
-out:
- return ret;
-}
-
-void __exit nvram_cleanup(void)
-{
- misc_deregister( &nvram_dev );
-}
-
-module_init(nvram_init);
-module_exit(nvram_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 4a22b4b41aef..d0ad85900b79 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -377,7 +377,7 @@ static __init int hpet_mmap_enable(char *str)
pr_info("HPET mmap %s\n", hpet_mmap_enabled ? "enabled" : "disabled");
return 1;
}
-__setup("hpet_mmap", hpet_mmap_enable);
+__setup("hpet_mmap=", hpet_mmap_enable);
static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
{
@@ -842,7 +842,6 @@ int hpet_alloc(struct hpet_data *hdp)
struct hpet_dev *devp;
u32 i, ntimer;
struct hpets *hpetp;
- size_t siz;
struct hpet __iomem *hpet;
static struct hpets *last;
unsigned long period;
@@ -860,10 +859,8 @@ int hpet_alloc(struct hpet_data *hdp)
return 0;
}
- siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
- sizeof(struct hpet_dev));
-
- hpetp = kzalloc(siz, GFP_KERNEL);
+ hpetp = kzalloc(struct_size(hpetp, hp_dev, hdp->hd_nirqs - 1),
+ GFP_KERNEL);
if (!hpetp)
return -ENOMEM;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index dac895dc01b9..25a7d8ffdb5d 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -424,6 +424,21 @@ config HW_RANDOM_EXYNOS
will be called exynos-trng.
If unsure, say Y.
+
+config HW_RANDOM_OPTEE
+ tristate "OP-TEE based Random Number Generator support"
+ depends on OPTEE
+ default HW_RANDOM
+ help
+ This driver provides support for OP-TEE based Random Number
+ Generator on ARM SoCs where hardware entropy sources are not
+ accessible to normal world (Linux).
+
+ To compile this driver as a module, choose M here: the module
+ will be called optee-rng.
+
+ If unsure, say Y.
+
endif # HW_RANDOM
config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index e35ec3ce3a20..7c9ef4a7667f 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o
obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o
+obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 256b0b1d0f26..f759790c3cdb 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -168,14 +168,16 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
priv->rng.read = bcm2835_rng_read;
priv->rng.cleanup = bcm2835_rng_cleanup;
- rng_id = of_match_node(bcm2835_rng_of_match, np);
- if (!rng_id)
- return -EINVAL;
-
- /* Check for rng init function, execute it */
- of_data = rng_id->data;
- if (of_data)
- priv->mask_interrupts = of_data->mask_interrupts;
+ if (dev_of_node(dev)) {
+ rng_id = of_match_node(bcm2835_rng_of_match, np);
+ if (!rng_id)
+ return -EINVAL;
+
+ /* Check for rng init function, execute it */
+ of_data = rng_id->data;
+ if (of_data)
+ priv->mask_interrupts = of_data->mask_interrupts;
+ }
/* register driver */
err = devm_hwrng_register(dev, &priv->rng);
diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c
new file mode 100644
index 000000000000..ddfbabaa5f8f
--- /dev/null
+++ b/drivers/char/hw_random/optee-rng.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018-2019 Linaro Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/hw_random.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+
+#define DRIVER_NAME "optee-rng"
+
+#define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001
+
+/*
+ * TA_CMD_GET_ENTROPY - Get Entropy from RNG
+ *
+ * param[0] (inout memref) - Entropy buffer memory reference
+ * param[1] unused
+ * param[2] unused
+ * param[3] unused
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool
+ * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed
+ */
+#define TA_CMD_GET_ENTROPY 0x0
+
+/*
+ * TA_CMD_GET_RNG_INFO - Get RNG information
+ *
+ * param[0] (out value) - value.a: RNG data-rate in bytes per second
+ * value.b: Quality/Entropy per 1024 bit of data
+ * param[1] unused
+ * param[2] unused
+ * param[3] unused
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_GET_RNG_INFO 0x1
+
+#define MAX_ENTROPY_REQ_SZ (4 * 1024)
+
+/**
+ * struct optee_rng_private - OP-TEE Random Number Generator private data
+ * @dev: OP-TEE based RNG device.
+ * @ctx: OP-TEE context handler.
+ * @session_id: RNG TA session identifier.
+ * @data_rate: RNG data rate.
+ * @entropy_shm_pool: Memory pool shared with RNG device.
+ * @optee_rng: OP-TEE RNG driver structure.
+ */
+struct optee_rng_private {
+ struct device *dev;
+ struct tee_context *ctx;
+ u32 session_id;
+ u32 data_rate;
+ struct tee_shm *entropy_shm_pool;
+ struct hwrng optee_rng;
+};
+
+#define to_optee_rng_private(r) \
+ container_of(r, struct optee_rng_private, optee_rng)
+
+static size_t get_optee_rng_data(struct optee_rng_private *pvt_data,
+ void *buf, size_t req_size)
+{
+ int ret = 0;
+ u8 *rng_data = NULL;
+ size_t rng_size = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(&param, 0, sizeof(param));
+
+ /* Invoke TA_CMD_GET_ENTROPY function of Trusted App */
+ inv_arg.func = TA_CMD_GET_ENTROPY;
+ inv_arg.session = pvt_data->session_id;
+ inv_arg.num_params = 4;
+
+ /* Fill invoke cmd params */
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ param[0].u.memref.shm = pvt_data->entropy_shm_pool;
+ param[0].u.memref.size = req_size;
+ param[0].u.memref.shm_offs = 0;
+
+ ret = tee_client_invoke_func(pvt_data->ctx, &inv_arg, param);
+ if ((ret < 0) || (inv_arg.ret != 0)) {
+ dev_err(pvt_data->dev, "TA_CMD_GET_ENTROPY invoke err: %x\n",
+ inv_arg.ret);
+ return 0;
+ }
+
+ rng_data = tee_shm_get_va(pvt_data->entropy_shm_pool, 0);
+ if (IS_ERR(rng_data)) {
+ dev_err(pvt_data->dev, "tee_shm_get_va failed\n");
+ return 0;
+ }
+
+ rng_size = param[0].u.memref.size;
+ memcpy(buf, rng_data, rng_size);
+
+ return rng_size;
+}
+
+static int optee_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
+ size_t read = 0, rng_size = 0;
+ int timeout = 1;
+ u8 *data = buf;
+
+ if (max > MAX_ENTROPY_REQ_SZ)
+ max = MAX_ENTROPY_REQ_SZ;
+
+ while (read == 0) {
+ rng_size = get_optee_rng_data(pvt_data, data, (max - read));
+
+ data += rng_size;
+ read += rng_size;
+
+ if (wait) {
+ if (timeout-- == 0)
+ return read;
+ msleep((1000 * (max - read)) / pvt_data->data_rate);
+ } else {
+ return read;
+ }
+ }
+
+ return read;
+}
+
+static int optee_rng_init(struct hwrng *rng)
+{
+ struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
+ struct tee_shm *entropy_shm_pool = NULL;
+
+ entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
+ TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ if (IS_ERR(entropy_shm_pool)) {
+ dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
+ return PTR_ERR(entropy_shm_pool);
+ }
+
+ pvt_data->entropy_shm_pool = entropy_shm_pool;
+
+ return 0;
+}
+
+static void optee_rng_cleanup(struct hwrng *rng)
+{
+ struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
+
+ tee_shm_free(pvt_data->entropy_shm_pool);
+}
+
+static struct optee_rng_private pvt_data = {
+ .optee_rng = {
+ .name = DRIVER_NAME,
+ .init = optee_rng_init,
+ .cleanup = optee_rng_cleanup,
+ .read = optee_rng_read,
+ }
+};
+
+static int get_optee_rng_info(struct device *dev)
+{
+ int ret = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(&param, 0, sizeof(param));
+
+ /* Invoke TA_CMD_GET_RNG_INFO function of Trusted App */
+ inv_arg.func = TA_CMD_GET_RNG_INFO;
+ inv_arg.session = pvt_data.session_id;
+ inv_arg.num_params = 4;
+
+ /* Fill invoke cmd params */
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+ ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
+ if ((ret < 0) || (inv_arg.ret != 0)) {
+ dev_err(dev, "TA_CMD_GET_RNG_INFO invoke err: %x\n",
+ inv_arg.ret);
+ return -EINVAL;
+ }
+
+ pvt_data.data_rate = param[0].u.value.a;
+ pvt_data.optee_rng.quality = param[0].u.value.b;
+
+ return 0;
+}
+
+static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+ if (ver->impl_id == TEE_IMPL_ID_OPTEE)
+ return 1;
+ else
+ return 0;
+}
+
+static int optee_rng_probe(struct device *dev)
+{
+ struct tee_client_device *rng_device = to_tee_client_device(dev);
+ int ret = 0, err = -ENODEV;
+ struct tee_ioctl_open_session_arg sess_arg;
+
+ memset(&sess_arg, 0, sizeof(sess_arg));
+
+ /* Open context with TEE driver */
+ pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
+ NULL);
+ if (IS_ERR(pvt_data.ctx))
+ return -ENODEV;
+
+ /* Open session with hwrng Trusted App */
+ memcpy(sess_arg.uuid, rng_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+ sess_arg.num_params = 0;
+
+ ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
+ if ((ret < 0) || (sess_arg.ret != 0)) {
+ dev_err(dev, "tee_client_open_session failed, err: %x\n",
+ sess_arg.ret);
+ err = -EINVAL;
+ goto out_ctx;
+ }
+ pvt_data.session_id = sess_arg.session;
+
+ err = get_optee_rng_info(dev);
+ if (err)
+ goto out_sess;
+
+ err = hwrng_register(&pvt_data.optee_rng);
+ if (err) {
+ dev_err(dev, "hwrng registration failed (%d)\n", err);
+ goto out_sess;
+ }
+
+ pvt_data.dev = dev;
+
+ return 0;
+
+out_sess:
+ tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
+out_ctx:
+ tee_client_close_context(pvt_data.ctx);
+
+ return err;
+}
+
+static int optee_rng_remove(struct device *dev)
+{
+ hwrng_unregister(&pvt_data.optee_rng);
+ tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
+ tee_client_close_context(pvt_data.ctx);
+
+ return 0;
+}
+
+static const struct tee_client_device_id optee_rng_id_table[] = {
+ {UUID_INIT(0xab7a617c, 0xb8e7, 0x4d8f,
+ 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(tee, optee_rng_id_table);
+
+static struct tee_client_driver optee_rng_driver = {
+ .id_table = optee_rng_id_table,
+ .driver = {
+ .name = DRIVER_NAME,
+ .bus = &tee_bus_type,
+ .probe = optee_rng_probe,
+ .remove = optee_rng_remove,
+ },
+};
+
+static int __init optee_rng_mod_init(void)
+{
+ return driver_register(&optee_rng_driver.driver);
+}
+
+static void __exit optee_rng_mod_exit(void)
+{
+ driver_unregister(&optee_rng_driver.driver);
+}
+
+module_init(optee_rng_mod_init);
+module_exit(optee_rng_mod_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sumit Garg <sumit.garg@linaro.org>");
+MODULE_DESCRIPTION("OP-TEE based random number generator driver");
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index b89df66ea1ae..7abd604e938c 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -73,7 +73,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
if (!vi->busy) {
vi->busy = true;
- init_completion(&vi->have_data);
+ reinit_completion(&vi->have_data);
register_buffer(vi, buf, size);
}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a74ce885b541..c518659b4d9f 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -32,6 +32,7 @@
#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#include <linux/uuid.h>
+#include <linux/nospec.h>
#define IPMI_DRIVER_VERSION "39.2"
@@ -62,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
{ }
#endif
-static int initialized;
+static bool initialized;
+static bool drvregistered;
enum ipmi_panic_event_op {
IPMI_SEND_PANIC_EVENT_NONE,
@@ -612,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
static LIST_HEAD(ipmi_interfaces);
static DEFINE_MUTEX(ipmi_interfaces_mutex);
-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
+struct srcu_struct ipmi_interfaces_srcu;
/*
* List of watchers that want to know when smi's are added and deleted.
@@ -720,7 +722,15 @@ struct watcher_entry {
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
{
struct ipmi_smi *intf;
- int index;
+ int index, rv;
+
+ /*
+ * Make sure the driver is actually initialized, this handles
+ * problems with initialization order.
+ */
+ rv = ipmi_init_msghandler();
+ if (rv)
+ return rv;
mutex_lock(&smi_watchers_mutex);
@@ -884,7 +894,7 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
if (user) {
user->handler->ipmi_recv_hndl(msg, user->handler_data);
- release_ipmi_user(msg->user, index);
+ release_ipmi_user(user, index);
} else {
/* User went away, give up. */
ipmi_free_recv_msg(msg);
@@ -1076,7 +1086,7 @@ int ipmi_create_user(unsigned int if_num,
{
unsigned long flags;
struct ipmi_user *new_user;
- int rv = 0, index;
+ int rv, index;
struct ipmi_smi *intf;
/*
@@ -1094,18 +1104,9 @@ int ipmi_create_user(unsigned int if_num,
* Make sure the driver is actually initialized, this handles
* problems with initialization order.
*/
- if (!initialized) {
- rv = ipmi_init_msghandler();
- if (rv)
- return rv;
-
- /*
- * The init code doesn't return an error if it was turned
- * off, but it won't initialize. Check that.
- */
- if (!initialized)
- return -ENODEV;
- }
+ rv = ipmi_init_msghandler();
+ if (rv)
+ return rv;
new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
if (!new_user)
@@ -1183,6 +1184,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info);
static void free_user(struct kref *ref)
{
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
+ cleanup_srcu_struct(&user->release_barrier);
kfree(user);
}
@@ -1259,7 +1261,6 @@ int ipmi_destroy_user(struct ipmi_user *user)
{
_ipmi_destroy_user(user);
- cleanup_srcu_struct(&user->release_barrier);
kref_put(&user->refcount, free_user);
return 0;
@@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user,
if (!user)
return -ENODEV;
- if (channel >= IPMI_MAX_CHANNELS)
+ if (channel >= IPMI_MAX_CHANNELS) {
rv = -EINVAL;
- else
+ } else {
+ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
user->intf->addrinfo[channel].address = address;
+ }
release_ipmi_user(user, index);
return rv;
@@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user,
if (!user)
return -ENODEV;
- if (channel >= IPMI_MAX_CHANNELS)
+ if (channel >= IPMI_MAX_CHANNELS) {
rv = -EINVAL;
- else
+ } else {
+ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
*address = user->intf->addrinfo[channel].address;
+ }
release_ipmi_user(user, index);
return rv;
@@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user,
if (!user)
return -ENODEV;
- if (channel >= IPMI_MAX_CHANNELS)
+ if (channel >= IPMI_MAX_CHANNELS) {
rv = -EINVAL;
- else
+ } else {
+ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
user->intf->addrinfo[channel].lun = LUN & 0x3;
+ }
release_ipmi_user(user, index);
return rv;
@@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user,
if (!user)
return -ENODEV;
- if (channel >= IPMI_MAX_CHANNELS)
+ if (channel >= IPMI_MAX_CHANNELS) {
rv = -EINVAL;
- else
+ } else {
+ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
*address = user->intf->addrinfo[channel].lun;
+ }
release_ipmi_user(user, index);
return rv;
@@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi *intf,
{
if (addr->channel >= IPMI_MAX_CHANNELS)
return -EINVAL;
+ addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
*lun = intf->addrinfo[addr->channel].lun;
*saddr = intf->addrinfo[addr->channel].address;
return 0;
@@ -3291,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
* Make sure the driver is actually initialized, this handles
* problems with initialization order.
*/
- if (!initialized) {
- rv = ipmi_init_msghandler();
- if (rv)
- return rv;
- /*
- * The init code doesn't return an error if it was turned
- * off, but it won't initialize. Check that.
- */
- if (!initialized)
- return -ENODEV;
- }
+ rv = ipmi_init_msghandler();
+ if (rv)
+ return rv;
intf = kzalloc(sizeof(*intf), GFP_KERNEL);
if (!intf)
@@ -5017,6 +5019,22 @@ static int panic_event(struct notifier_block *this,
return NOTIFY_DONE;
}
+/* Must be called with ipmi_interfaces_mutex held. */
+static int ipmi_register_driver(void)
+{
+ int rv;
+
+ if (drvregistered)
+ return 0;
+
+ rv = driver_register(&ipmidriver.driver);
+ if (rv)
+ pr_err("Could not register IPMI driver\n");
+ else
+ drvregistered = true;
+ return rv;
+}
+
static struct notifier_block panic_block = {
.notifier_call = panic_event,
.next = NULL,
@@ -5027,66 +5045,75 @@ static int ipmi_init_msghandler(void)
{
int rv;
+ mutex_lock(&ipmi_interfaces_mutex);
+ rv = ipmi_register_driver();
+ if (rv)
+ goto out;
if (initialized)
- return 0;
-
- rv = driver_register(&ipmidriver.driver);
- if (rv) {
- pr_err("Could not register IPMI driver\n");
- return rv;
- }
+ goto out;
- pr_info("version " IPMI_DRIVER_VERSION "\n");
+ init_srcu_struct(&ipmi_interfaces_srcu);
timer_setup(&ipmi_timer, ipmi_timeout, 0);
mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
- initialized = 1;
+ initialized = true;
- return 0;
+out:
+ mutex_unlock(&ipmi_interfaces_mutex);
+ return rv;
}
static int __init ipmi_init_msghandler_mod(void)
{
- ipmi_init_msghandler();
- return 0;
+ int rv;
+
+ pr_info("version " IPMI_DRIVER_VERSION "\n");
+
+ mutex_lock(&ipmi_interfaces_mutex);
+ rv = ipmi_register_driver();
+ mutex_unlock(&ipmi_interfaces_mutex);
+
+ return rv;
}
static void __exit cleanup_ipmi(void)
{
int count;
- if (!initialized)
- return;
-
- atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+ if (initialized) {
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &panic_block);
- /*
- * This can't be called if any interfaces exist, so no worry
- * about shutting down the interfaces.
- */
+ /*
+ * This can't be called if any interfaces exist, so no worry
+ * about shutting down the interfaces.
+ */
- /*
- * Tell the timer to stop, then wait for it to stop. This
- * avoids problems with race conditions removing the timer
- * here.
- */
- atomic_inc(&stop_operation);
- del_timer_sync(&ipmi_timer);
+ /*
+ * Tell the timer to stop, then wait for it to stop. This
+ * avoids problems with race conditions removing the timer
+ * here.
+ */
+ atomic_inc(&stop_operation);
+ del_timer_sync(&ipmi_timer);
- driver_unregister(&ipmidriver.driver);
+ initialized = false;
- initialized = 0;
+ /* Check for buffer leaks. */
+ count = atomic_read(&smi_msg_inuse_count);
+ if (count != 0)
+ pr_warn("SMI message count %d at exit\n", count);
+ count = atomic_read(&recv_msg_inuse_count);
+ if (count != 0)
+ pr_warn("recv message count %d at exit\n", count);
- /* Check for buffer leaks. */
- count = atomic_read(&smi_msg_inuse_count);
- if (count != 0)
- pr_warn("SMI message count %d at exit\n", count);
- count = atomic_read(&recv_msg_inuse_count);
- if (count != 0)
- pr_warn("recv message count %d at exit\n", count);
+ cleanup_srcu_struct(&ipmi_interfaces_srcu);
+ }
+ if (drvregistered)
+ driver_unregister(&ipmidriver.driver);
}
module_exit(cleanup_ipmi);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index ca9528c4f183..b7a1ae2afaea 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
/* Remove the multi-part read marker. */
len -= 2;
+ data += 2;
for (i = 0; i < len; i++)
- ssif_info->data[i] = data[i+2];
+ ssif_info->data[i] = data[i];
ssif_info->multi_len = len;
ssif_info->multi_pos = 1;
@@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
}
blocknum = data[0];
+ len--;
+ data++;
+
+ if (blocknum != 0xff && len != 31) {
+ /* All blocks but the last must have 31 data bytes. */
+ result = -EIO;
+ if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+ pr_info("Received middle message <31\n");
- if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
+ goto continue_op;
+ }
+
+ if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
/* Received message too big, abort the operation. */
result = -E2BIG;
if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
goto continue_op;
}
- /* Remove the blocknum from the data. */
- len--;
for (i = 0; i < len; i++)
- ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
+ ssif_info->data[i + ssif_info->multi_len] = data[i];
ssif_info->multi_len += len;
if (blocknum == 0xff) {
/* End of read */
len = ssif_info->multi_len;
data = ssif_info->data;
- } else if (blocknum + 1 != ssif_info->multi_pos) {
+ } else if (blocknum != ssif_info->multi_pos) {
/*
* Out of sequence block, just abort. Block
* numbers start at zero for the second block,
@@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
}
}
+ continue_op:
if (result < 0) {
ssif_inc_stat(ssif_info, receive_errors);
} else {
@@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
ssif_inc_stat(ssif_info, received_message_parts);
}
-
- continue_op:
if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
pr_info("DONE 1: state = %d, result=%d\n",
ssif_info->ssif_state, result);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 5c8d780637bd..3406852f67ff 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -729,7 +729,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
ret = lp_set_timeout32(minor, (void __user *)arg);
break;
}
- /* fallthrough for 64-bit */
+ /* fall through - for 64-bit */
case LPSETTIMEOUT_NEW:
ret = lp_set_timeout64(minor, (void __user *)arg);
break;
@@ -757,7 +757,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
ret = lp_set_timeout32(minor, (void __user *)arg);
break;
}
- /* fallthrough for x32 mode */
+ /* fall through - for x32 mode */
case LPSETTIMEOUT_NEW:
ret = lp_set_timeout64(minor, (void __user *)arg);
break;
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 8c9216a0f62e..0a31b60bee7b 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -50,6 +50,7 @@ static LIST_HEAD(soft_list);
* file operations
*/
static const struct file_operations mbcs_ops = {
+ .owner = THIS_MODULE,
.open = mbcs_open,
.llseek = mbcs_sram_llseek,
.read = mbcs_sram_read,
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index b5e3103c1175..e43c876a9223 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -59,6 +59,7 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/serial_8250.h>
+#include <linux/nospec.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum);
return -EINVAL;
}
+ ipcnum = array_index_nospec(ipcnum,
+ ARRAY_SIZE(pDrvData->IPCs));
PRINTK_3(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
" ipcnum %x entry usIntCount %x\n",
@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" Invalid ipcnum %x\n", ipcnum);
return -EINVAL;
}
+ ipcnum = array_index_nospec(ipcnum,
+ ARRAY_SIZE(pDrvData->IPCs));
PRINTK_3(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
" ipcnum %x, usIntCount %x\n",
@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum);
return -EINVAL;
}
+ ipcnum = array_index_nospec(ipcnum,
+ ARRAY_SIZE(pDrvData->IPCs));
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
pDrvData->IPCs[ipcnum].bIsEnabled = false;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 25264d65e716..eff1e3f1b3a2 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -21,13 +21,6 @@
* ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid
* again; use with care!)
*
- * This file also provides some functions for other parts of the kernel that
- * want to access the NVRAM: nvram_{read,write,check_checksum,set_checksum}.
- * Obviously this can be used only if this driver is always configured into
- * the kernel and is not a module. Since the functions are used by some Atari
- * drivers, this is the case on the Atari.
- *
- *
* 1.1 Cesar Barros: SMP locking fixes
* added changelog
* 1.2 Erik Gilling: Cobalt Networks support
@@ -39,64 +32,6 @@
#include <linux/module.h>
#include <linux/nvram.h>
-
-#define PC 1
-#define ATARI 2
-
-/* select machine configuration */
-#if defined(CONFIG_ATARI)
-# define MACH ATARI
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and ?? */
-# define MACH PC
-#else
-# error Cannot build nvram driver for this machine configuration.
-#endif
-
-#if MACH == PC
-
-/* RTC in a PC */
-#define CHECK_DRIVER_INIT() 1
-
-/* On PCs, the checksum is built only over bytes 2..31 */
-#define PC_CKS_RANGE_START 2
-#define PC_CKS_RANGE_END 31
-#define PC_CKS_LOC 32
-#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)
-
-#define mach_check_checksum pc_check_checksum
-#define mach_set_checksum pc_set_checksum
-#define mach_proc_infos pc_proc_infos
-
-#endif
-
-#if MACH == ATARI
-
-/* Special parameters for RTC in Atari machines */
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#define RTC_PORT(x) (TT_RTC_BAS + 2*(x))
-#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))
-
-#define NVRAM_BYTES 50
-
-/* On Ataris, the checksum is over all bytes except the checksum bytes
- * themselves; these are at the very end */
-#define ATARI_CKS_RANGE_START 0
-#define ATARI_CKS_RANGE_END 47
-#define ATARI_CKS_LOC 48
-
-#define mach_check_checksum atari_check_checksum
-#define mach_set_checksum atari_set_checksum
-#define mach_proc_infos atari_proc_infos
-
-#endif
-
-/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
- * rtc_lock held. Due to the index-port/data-port design of the RTC, we
- * don't want two different things trying to get to it at once. (e.g. the
- * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
- */
-
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
@@ -106,28 +41,26 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
+#ifdef CONFIG_PPC
+#include <asm/nvram.h>
+#endif
static DEFINE_MUTEX(nvram_mutex);
static DEFINE_SPINLOCK(nvram_state_lock);
static int nvram_open_cnt; /* #times opened */
static int nvram_open_mode; /* special open modes */
+static ssize_t nvram_size;
#define NVRAM_WRITE 1 /* opened for writing (exclusive) */
#define NVRAM_EXCL 2 /* opened with O_EXCL */
-static int mach_check_checksum(void);
-static void mach_set_checksum(void);
-
-#ifdef CONFIG_PROC_FS
-static void mach_proc_infos(unsigned char *contents, struct seq_file *seq,
- void *offset);
-#endif
-
+#ifdef CONFIG_X86
/*
* These functions are provided to be called internally or by other parts of
* the kernel. It's up to the caller to ensure correct checksum before reading
@@ -139,13 +72,20 @@ static void mach_proc_infos(unsigned char *contents, struct seq_file *seq,
* know about the RTC cruft.
*/
-unsigned char __nvram_read_byte(int i)
+#define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE)
+
+/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
+ * rtc_lock held. Due to the index-port/data-port design of the RTC, we
+ * don't want two different things trying to get to it at once. (e.g. the
+ * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
+ */
+
+static unsigned char __nvram_read_byte(int i)
{
return CMOS_READ(NVRAM_FIRST_BYTE + i);
}
-EXPORT_SYMBOL(__nvram_read_byte);
-unsigned char nvram_read_byte(int i)
+static unsigned char pc_nvram_read_byte(int i)
{
unsigned long flags;
unsigned char c;
@@ -155,16 +95,14 @@ unsigned char nvram_read_byte(int i)
spin_unlock_irqrestore(&rtc_lock, flags);
return c;
}
-EXPORT_SYMBOL(nvram_read_byte);
/* This races nicely with trying to read with checksum checking (nvram_read) */
-void __nvram_write_byte(unsigned char c, int i)
+static void __nvram_write_byte(unsigned char c, int i)
{
CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
}
-EXPORT_SYMBOL(__nvram_write_byte);
-void nvram_write_byte(unsigned char c, int i)
+static void pc_nvram_write_byte(unsigned char c, int i)
{
unsigned long flags;
@@ -172,172 +110,266 @@ void nvram_write_byte(unsigned char c, int i)
__nvram_write_byte(c, i);
spin_unlock_irqrestore(&rtc_lock, flags);
}
-EXPORT_SYMBOL(nvram_write_byte);
-int __nvram_check_checksum(void)
+/* On PCs, the checksum is built only over bytes 2..31 */
+#define PC_CKS_RANGE_START 2
+#define PC_CKS_RANGE_END 31
+#define PC_CKS_LOC 32
+
+static int __nvram_check_checksum(void)
{
- return mach_check_checksum();
+ int i;
+ unsigned short sum = 0;
+ unsigned short expect;
+
+ for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
+ sum += __nvram_read_byte(i);
+ expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
+ __nvram_read_byte(PC_CKS_LOC+1);
+ return (sum & 0xffff) == expect;
}
-EXPORT_SYMBOL(__nvram_check_checksum);
-int nvram_check_checksum(void)
+static void __nvram_set_checksum(void)
{
- unsigned long flags;
- int rv;
+ int i;
+ unsigned short sum = 0;
- spin_lock_irqsave(&rtc_lock, flags);
- rv = __nvram_check_checksum();
- spin_unlock_irqrestore(&rtc_lock, flags);
- return rv;
+ for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
+ sum += __nvram_read_byte(i);
+ __nvram_write_byte(sum >> 8, PC_CKS_LOC);
+ __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
}
-EXPORT_SYMBOL(nvram_check_checksum);
-static void __nvram_set_checksum(void)
+static long pc_nvram_set_checksum(void)
{
- mach_set_checksum();
+ spin_lock_irq(&rtc_lock);
+ __nvram_set_checksum();
+ spin_unlock_irq(&rtc_lock);
+ return 0;
}
-#if 0
-void nvram_set_checksum(void)
+static long pc_nvram_initialize(void)
{
- unsigned long flags;
+ ssize_t i;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
+ for (i = 0; i < NVRAM_BYTES; ++i)
+ __nvram_write_byte(0, i);
__nvram_set_checksum();
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
+ return 0;
}
-#endif /* 0 */
-
-/*
- * The are the file operation function for user access to /dev/nvram
- */
-static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
+static ssize_t pc_nvram_get_size(void)
{
- return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
- NVRAM_BYTES);
+ return NVRAM_BYTES;
}
-static ssize_t nvram_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t pc_nvram_read(char *buf, size_t count, loff_t *ppos)
{
- unsigned char contents[NVRAM_BYTES];
- unsigned i = *ppos;
- unsigned char *tmp;
+ char *p = buf;
+ loff_t i;
spin_lock_irq(&rtc_lock);
+ if (!__nvram_check_checksum()) {
+ spin_unlock_irq(&rtc_lock);
+ return -EIO;
+ }
+ for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
+ *p = __nvram_read_byte(i);
+ spin_unlock_irq(&rtc_lock);
- if (!__nvram_check_checksum())
- goto checksum_err;
+ *ppos = i;
+ return p - buf;
+}
- for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
- *tmp = __nvram_read_byte(i);
+static ssize_t pc_nvram_write(char *buf, size_t count, loff_t *ppos)
+{
+ char *p = buf;
+ loff_t i;
+ spin_lock_irq(&rtc_lock);
+ if (!__nvram_check_checksum()) {
+ spin_unlock_irq(&rtc_lock);
+ return -EIO;
+ }
+ for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
+ __nvram_write_byte(*p, i);
+ __nvram_set_checksum();
spin_unlock_irq(&rtc_lock);
- if (copy_to_user(buf, contents, tmp - contents))
- return -EFAULT;
-
*ppos = i;
+ return p - buf;
+}
- return tmp - contents;
+const struct nvram_ops arch_nvram_ops = {
+ .read = pc_nvram_read,
+ .write = pc_nvram_write,
+ .read_byte = pc_nvram_read_byte,
+ .write_byte = pc_nvram_write_byte,
+ .get_size = pc_nvram_get_size,
+ .set_checksum = pc_nvram_set_checksum,
+ .initialize = pc_nvram_initialize,
+};
+EXPORT_SYMBOL(arch_nvram_ops);
+#endif /* CONFIG_X86 */
-checksum_err:
- spin_unlock_irq(&rtc_lock);
- return -EIO;
-}
+/*
+ * The are the file operation function for user access to /dev/nvram
+ */
-static ssize_t nvram_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)
{
- unsigned char contents[NVRAM_BYTES];
- unsigned i = *ppos;
- unsigned char *tmp;
+ return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
+ nvram_size);
+}
- if (i >= NVRAM_BYTES)
- return 0; /* Past EOF */
+static ssize_t nvram_misc_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *tmp;
+ ssize_t ret;
- if (count > NVRAM_BYTES - i)
- count = NVRAM_BYTES - i;
- if (count > NVRAM_BYTES)
- return -EFAULT; /* Can't happen, but prove it to gcc */
- if (copy_from_user(contents, buf, count))
+ if (!access_ok(buf, count))
return -EFAULT;
+ if (*ppos >= nvram_size)
+ return 0;
- spin_lock_irq(&rtc_lock);
+ count = min_t(size_t, count, nvram_size - *ppos);
+ count = min_t(size_t, count, PAGE_SIZE);
- if (!__nvram_check_checksum())
- goto checksum_err;
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
- for (tmp = contents; count--; ++i, ++tmp)
- __nvram_write_byte(*tmp, i);
+ ret = nvram_read(tmp, count, ppos);
+ if (ret <= 0)
+ goto out;
- __nvram_set_checksum();
+ if (copy_to_user(buf, tmp, ret)) {
+ *ppos -= ret;
+ ret = -EFAULT;
+ }
- spin_unlock_irq(&rtc_lock);
+out:
+ kfree(tmp);
+ return ret;
+}
- *ppos = i;
+static ssize_t nvram_misc_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *tmp;
+ ssize_t ret;
- return tmp - contents;
+ if (!access_ok(buf, count))
+ return -EFAULT;
+ if (*ppos >= nvram_size)
+ return 0;
-checksum_err:
- spin_unlock_irq(&rtc_lock);
- return -EIO;
+ count = min_t(size_t, count, nvram_size - *ppos);
+ count = min_t(size_t, count, PAGE_SIZE);
+
+ tmp = memdup_user(buf, count);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ ret = nvram_write(tmp, count, ppos);
+ kfree(tmp);
+ return ret;
}
-static long nvram_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
+static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
- int i;
+ long ret = -ENOTTY;
switch (cmd) {
-
+#ifdef CONFIG_PPC
+ case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
+ pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
+ /* fall through */
+ case IOC_NVRAM_GET_OFFSET:
+ ret = -EINVAL;
+#ifdef CONFIG_PPC_PMAC
+ if (machine_is(powermac)) {
+ int part, offset;
+
+ if (copy_from_user(&part, (void __user *)arg,
+ sizeof(part)) != 0)
+ return -EFAULT;
+ if (part < pmac_nvram_OF || part > pmac_nvram_NR)
+ return -EINVAL;
+ offset = pmac_get_partition(part);
+ if (offset < 0)
+ return -EINVAL;
+ if (copy_to_user((void __user *)arg,
+ &offset, sizeof(offset)) != 0)
+ return -EFAULT;
+ ret = 0;
+ }
+#endif
+ break;
+#ifdef CONFIG_PPC32
+ case IOC_NVRAM_SYNC:
+ if (ppc_md.nvram_sync != NULL) {
+ mutex_lock(&nvram_mutex);
+ ppc_md.nvram_sync();
+ mutex_unlock(&nvram_mutex);
+ }
+ ret = 0;
+ break;
+#endif
+#elif defined(CONFIG_X86) || defined(CONFIG_M68K)
case NVRAM_INIT:
/* initialize NVRAM contents and checksum */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- mutex_lock(&nvram_mutex);
- spin_lock_irq(&rtc_lock);
-
- for (i = 0; i < NVRAM_BYTES; ++i)
- __nvram_write_byte(0, i);
- __nvram_set_checksum();
-
- spin_unlock_irq(&rtc_lock);
- mutex_unlock(&nvram_mutex);
- return 0;
-
+ if (arch_nvram_ops.initialize != NULL) {
+ mutex_lock(&nvram_mutex);
+ ret = arch_nvram_ops.initialize();
+ mutex_unlock(&nvram_mutex);
+ }
+ break;
case NVRAM_SETCKS:
/* just set checksum, contents unchanged (maybe useful after
* checksum garbaged somehow...) */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- mutex_lock(&nvram_mutex);
- spin_lock_irq(&rtc_lock);
- __nvram_set_checksum();
- spin_unlock_irq(&rtc_lock);
- mutex_unlock(&nvram_mutex);
- return 0;
-
- default:
- return -ENOTTY;
+ if (arch_nvram_ops.set_checksum != NULL) {
+ mutex_lock(&nvram_mutex);
+ ret = arch_nvram_ops.set_checksum();
+ mutex_unlock(&nvram_mutex);
+ }
+ break;
+#endif /* CONFIG_X86 || CONFIG_M68K */
}
+ return ret;
}
-static int nvram_open(struct inode *inode, struct file *file)
+static int nvram_misc_open(struct inode *inode, struct file *file)
{
spin_lock(&nvram_state_lock);
+ /* Prevent multiple readers/writers if desired. */
if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
- (nvram_open_mode & NVRAM_EXCL) ||
- ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
+ (nvram_open_mode & NVRAM_EXCL)) {
spin_unlock(&nvram_state_lock);
return -EBUSY;
}
+#if defined(CONFIG_X86) || defined(CONFIG_M68K)
+ /* Prevent multiple writers if the set_checksum ioctl is implemented. */
+ if ((arch_nvram_ops.set_checksum != NULL) &&
+ (file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) {
+ spin_unlock(&nvram_state_lock);
+ return -EBUSY;
+ }
+#endif
+
if (file->f_flags & O_EXCL)
nvram_open_mode |= NVRAM_EXCL;
if (file->f_mode & FMODE_WRITE)
@@ -349,7 +381,7 @@ static int nvram_open(struct inode *inode, struct file *file)
return 0;
}
-static int nvram_release(struct inode *inode, struct file *file)
+static int nvram_misc_release(struct inode *inode, struct file *file)
{
spin_lock(&nvram_state_lock);
@@ -366,123 +398,7 @@ static int nvram_release(struct inode *inode, struct file *file)
return 0;
}
-#ifndef CONFIG_PROC_FS
-static int nvram_add_proc_fs(void)
-{
- return 0;
-}
-
-#else
-
-static int nvram_proc_read(struct seq_file *seq, void *offset)
-{
- unsigned char contents[NVRAM_BYTES];
- int i = 0;
-
- spin_lock_irq(&rtc_lock);
- for (i = 0; i < NVRAM_BYTES; ++i)
- contents[i] = __nvram_read_byte(i);
- spin_unlock_irq(&rtc_lock);
-
- mach_proc_infos(contents, seq, offset);
-
- return 0;
-}
-
-static int nvram_add_proc_fs(void)
-{
- if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read))
- return -ENOMEM;
- return 0;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-static const struct file_operations nvram_fops = {
- .owner = THIS_MODULE,
- .llseek = nvram_llseek,
- .read = nvram_read,
- .write = nvram_write,
- .unlocked_ioctl = nvram_ioctl,
- .open = nvram_open,
- .release = nvram_release,
-};
-
-static struct miscdevice nvram_dev = {
- NVRAM_MINOR,
- "nvram",
- &nvram_fops
-};
-
-static int __init nvram_init(void)
-{
- int ret;
-
- /* First test whether the driver should init at all */
- if (!CHECK_DRIVER_INIT())
- return -ENODEV;
-
- ret = misc_register(&nvram_dev);
- if (ret) {
- printk(KERN_ERR "nvram: can't misc_register on minor=%d\n",
- NVRAM_MINOR);
- goto out;
- }
- ret = nvram_add_proc_fs();
- if (ret) {
- printk(KERN_ERR "nvram: can't create /proc/driver/nvram\n");
- goto outmisc;
- }
- ret = 0;
- printk(KERN_INFO "Non-volatile memory driver v" NVRAM_VERSION "\n");
-out:
- return ret;
-outmisc:
- misc_deregister(&nvram_dev);
- goto out;
-}
-
-static void __exit nvram_cleanup_module(void)
-{
- remove_proc_entry("driver/nvram", NULL);
- misc_deregister(&nvram_dev);
-}
-
-module_init(nvram_init);
-module_exit(nvram_cleanup_module);
-
-/*
- * Machine specific functions
- */
-
-#if MACH == PC
-
-static int pc_check_checksum(void)
-{
- int i;
- unsigned short sum = 0;
- unsigned short expect;
-
- for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
- sum += __nvram_read_byte(i);
- expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
- __nvram_read_byte(PC_CKS_LOC+1);
- return (sum & 0xffff) == expect;
-}
-
-static void pc_set_checksum(void)
-{
- int i;
- unsigned short sum = 0;
-
- for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
- sum += __nvram_read_byte(i);
- __nvram_write_byte(sum >> 8, PC_CKS_LOC);
- __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
-}
-
-#ifdef CONFIG_PROC_FS
-
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
static const char * const floppy_types[] = {
"none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
"3.5'' 2.88M", "3.5'' 2.88M"
@@ -495,8 +411,8 @@ static const char * const gfx_types[] = {
"monochrome",
};
-static void pc_proc_infos(unsigned char *nvram, struct seq_file *seq,
- void *offset)
+static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
+ void *offset)
{
int checksum;
int type;
@@ -557,143 +473,76 @@ static void pc_proc_infos(unsigned char *nvram, struct seq_file *seq,
return;
}
-#endif
-#endif /* MACH == PC */
-
-#if MACH == ATARI
-
-static int atari_check_checksum(void)
+static int nvram_proc_read(struct seq_file *seq, void *offset)
{
- int i;
- unsigned char sum = 0;
+ unsigned char contents[NVRAM_BYTES];
+ int i = 0;
- for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
- sum += __nvram_read_byte(i);
- return (__nvram_read_byte(ATARI_CKS_LOC) == (~sum & 0xff)) &&
- (__nvram_read_byte(ATARI_CKS_LOC + 1) == (sum & 0xff));
-}
+ spin_lock_irq(&rtc_lock);
+ for (i = 0; i < NVRAM_BYTES; ++i)
+ contents[i] = __nvram_read_byte(i);
+ spin_unlock_irq(&rtc_lock);
-static void atari_set_checksum(void)
-{
- int i;
- unsigned char sum = 0;
+ pc_nvram_proc_read(contents, seq, offset);
- for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
- sum += __nvram_read_byte(i);
- __nvram_write_byte(~sum, ATARI_CKS_LOC);
- __nvram_write_byte(sum, ATARI_CKS_LOC + 1);
+ return 0;
}
+#endif /* CONFIG_X86 && CONFIG_PROC_FS */
-#ifdef CONFIG_PROC_FS
-
-static struct {
- unsigned char val;
- const char *name;
-} boot_prefs[] = {
- { 0x80, "TOS" },
- { 0x40, "ASV" },
- { 0x20, "NetBSD (?)" },
- { 0x10, "Linux" },
- { 0x00, "unspecified" }
-};
-
-static const char * const languages[] = {
- "English (US)",
- "German",
- "French",
- "English (UK)",
- "Spanish",
- "Italian",
- "6 (undefined)",
- "Swiss (French)",
- "Swiss (German)"
-};
-
-static const char * const dateformat[] = {
- "MM%cDD%cYY",
- "DD%cMM%cYY",
- "YY%cMM%cDD",
- "YY%cDD%cMM",
- "4 (undefined)",
- "5 (undefined)",
- "6 (undefined)",
- "7 (undefined)"
+static const struct file_operations nvram_misc_fops = {
+ .owner = THIS_MODULE,
+ .llseek = nvram_misc_llseek,
+ .read = nvram_misc_read,
+ .write = nvram_misc_write,
+ .unlocked_ioctl = nvram_misc_ioctl,
+ .open = nvram_misc_open,
+ .release = nvram_misc_release,
};
-static const char * const colors[] = {
- "2", "4", "16", "256", "65536", "??", "??", "??"
+static struct miscdevice nvram_misc = {
+ NVRAM_MINOR,
+ "nvram",
+ &nvram_misc_fops,
};
-static void atari_proc_infos(unsigned char *nvram, struct seq_file *seq,
- void *offset)
+static int __init nvram_module_init(void)
{
- int checksum = nvram_check_checksum();
- int i;
- unsigned vmode;
+ int ret;
- seq_printf(seq, "Checksum status : %svalid\n", checksum ? "" : "not ");
+ nvram_size = nvram_get_size();
+ if (nvram_size < 0)
+ return nvram_size;
- seq_printf(seq, "Boot preference : ");
- for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i) {
- if (nvram[1] == boot_prefs[i].val) {
- seq_printf(seq, "%s\n", boot_prefs[i].name);
- break;
- }
+ ret = misc_register(&nvram_misc);
+ if (ret) {
+ pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
+ return ret;
}
- if (i < 0)
- seq_printf(seq, "0x%02x (undefined)\n", nvram[1]);
-
- seq_printf(seq, "SCSI arbitration : %s\n",
- (nvram[16] & 0x80) ? "on" : "off");
- seq_printf(seq, "SCSI host ID : ");
- if (nvram[16] & 0x80)
- seq_printf(seq, "%d\n", nvram[16] & 7);
- else
- seq_printf(seq, "n/a\n");
-
- /* the following entries are defined only for the Falcon */
- if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON)
- return;
- seq_printf(seq, "OS language : ");
- if (nvram[6] < ARRAY_SIZE(languages))
- seq_printf(seq, "%s\n", languages[nvram[6]]);
- else
- seq_printf(seq, "%u (undefined)\n", nvram[6]);
- seq_printf(seq, "Keyboard language: ");
- if (nvram[7] < ARRAY_SIZE(languages))
- seq_printf(seq, "%s\n", languages[nvram[7]]);
- else
- seq_printf(seq, "%u (undefined)\n", nvram[7]);
- seq_printf(seq, "Date format : ");
- seq_printf(seq, dateformat[nvram[8] & 7],
- nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/');
- seq_printf(seq, ", %dh clock\n", nvram[8] & 16 ? 24 : 12);
- seq_printf(seq, "Boot delay : ");
- if (nvram[10] == 0)
- seq_printf(seq, "default");
- else
- seq_printf(seq, "%ds%s\n", nvram[10],
- nvram[10] < 8 ? ", no memory test" : "");
-
- vmode = (nvram[14] << 8) | nvram[15];
- seq_printf(seq,
- "Video mode : %s colors, %d columns, %s %s monitor\n",
- colors[vmode & 7],
- vmode & 8 ? 80 : 40,
- vmode & 16 ? "VGA" : "TV", vmode & 32 ? "PAL" : "NTSC");
- seq_printf(seq, " %soverscan, compat. mode %s%s\n",
- vmode & 64 ? "" : "no ",
- vmode & 128 ? "on" : "off",
- vmode & 256 ?
- (vmode & 16 ? ", line doubling" : ", half screen") : "");
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
+ if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
+ pr_err("nvram: can't create /proc/driver/nvram\n");
+ misc_deregister(&nvram_misc);
+ return -ENOMEM;
+ }
+#endif
- return;
+ pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n");
+ return 0;
}
+
+static void __exit nvram_module_exit(void)
+{
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
+ remove_proc_entry("driver/nvram", NULL);
#endif
+ misc_deregister(&nvram_misc);
+}
-#endif /* MACH == ATARI */
+module_init(nvram_module_init);
+module_exit(nvram_module_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
+MODULE_ALIAS("devname:nvram");
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e5b2fe80eab4..d2f0bb5ba47e 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -293,7 +293,6 @@ config COMMON_CLK_BD718XX
source "drivers/clk/actions/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
-source "drivers/clk/imx/Kconfig"
source "drivers/clk/imgtec/Kconfig"
source "drivers/clk/imx/Kconfig"
source "drivers/clk/ingenic/Kconfig"
diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c
index 2fe225a697df..3487e03d4bc6 100644
--- a/drivers/clk/at91/at91sam9x5.c
+++ b/drivers/clk/at91/at91sam9x5.c
@@ -144,8 +144,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
return;
at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
- nck(at91sam9x5_systemck),
- nck(at91sam9x35_periphck), 0);
+ nck(at91sam9x5_systemck), 31, 0);
if (!at91sam9x5_pmc)
return;
@@ -210,7 +209,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "mck";
+ parent_names[4] = "masterck";
for (i = 0; i < 2; i++) {
char name[6];
diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c
index d69ad96fe988..cd0ef7274fdb 100644
--- a/drivers/clk/at91/sama5d2.c
+++ b/drivers/clk/at91/sama5d2.c
@@ -240,7 +240,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "mck";
+ parent_names[4] = "masterck";
for (i = 0; i < 3; i++) {
char name[6];
@@ -291,7 +291,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "mck";
+ parent_names[4] = "masterck";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c
index e358be7f6c8d..b645a9d59cdb 100644
--- a/drivers/clk/at91/sama5d4.c
+++ b/drivers/clk/at91/sama5d4.c
@@ -207,7 +207,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "mck";
+ parent_names[4] = "masterck";
for (i = 0; i < 3; i++) {
char name[6];
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index 5b393e711e94..7d16ab0784ec 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
if (vc5->clk_mux_ins == VC5_MUX_IN_XIN)
src = VC5_PRIM_SRC_SHDN_EN_XTAL;
- if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
+ else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
src = VC5_PRIM_SRC_SHDN_EN_CLKIN;
+ else /* Invalid; should have been caught by vc5_probe() */
+ return -EINVAL;
}
return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 75d13c0eff12..d2477a5058ac 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1513,9 +1513,19 @@ static int clk_fetch_parent_index(struct clk_core *core,
if (!parent)
return -EINVAL;
- for (i = 0; i < core->num_parents; i++)
- if (clk_core_get_parent_by_index(core, i) == parent)
+ for (i = 0; i < core->num_parents; i++) {
+ if (core->parents[i] == parent)
+ return i;
+
+ if (core->parents[i])
+ continue;
+
+ /* Fallback to comparing globally unique names */
+ if (!strcmp(parent->name, core->parent_names[i])) {
+ core->parents[i] = parent;
return i;
+ }
+ }
return -EINVAL;
}
@@ -2779,7 +2789,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
seq_printf(s, "\"protect_count\": %d,", c->protect_count);
seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
- seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+ seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
seq_printf(s, "\"duty_cycle\": %u",
clk_core_get_scaled_duty_cycle(c, 100000));
}
diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
index 0026c3969b1e..76b9eb15604e 100644
--- a/drivers/clk/imx/clk-frac-pll.c
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -155,13 +155,14 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val, divfi, divff;
- u64 temp64 = parent_rate;
+ u64 temp64;
int ret;
parent_rate *= 8;
rate *= 2;
divfi = rate / parent_rate;
- temp64 *= rate - divfi;
+ temp64 = parent_rate * divfi;
+ temp64 = rate - temp64;
temp64 *= PLL_FRAC_DENOM;
do_div(temp64, parent_rate);
divff = temp64;
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
index 99c2508de8e5..fb6edf1b8aa2 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -169,6 +169,8 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
base = devm_ioremap(dev, res->start, resource_size(res));
if (!base)
return -ENOMEM;
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 61fefc046ec5..d083b860f083 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -53,7 +53,6 @@
#define APMU_DISP1 0x110
#define APMU_CCIC0 0x50
#define APMU_CCIC1 0xf4
-#define APMU_SP 0x68
#define MPMU_UART_PLL 0x14
struct mmp2_clk_unit {
@@ -210,8 +209,6 @@ static struct mmp_clk_mix_config ccic1_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32),
};
-static DEFINE_SPINLOCK(sp_lock);
-
static struct mmp_param_mux_clk apmu_mux_clks[] = {
{MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock},
{MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock},
@@ -242,7 +239,6 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
{MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock},
{MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
{MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
- {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock},
};
static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 1b1ba54e33dd..1c04575c118f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -215,6 +215,7 @@ config MSM_MMCC_8996
config MSM_GCC_8998
tristate "MSM8998 Global Clock Controller"
+ select QCOM_GDSC
help
Support for the global clock controller on msm8998 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index c782e62dd98b..58fa5c247af1 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -115,8 +115,8 @@ static const char * const gcc_parent_names_6[] = {
"core_bi_pll_test_se",
};
-static const char * const gcc_parent_names_7[] = {
- "bi_tcxo",
+static const char * const gcc_parent_names_7_ao[] = {
+ "bi_tcxo_ao",
"gpll0",
"gpll0_out_even",
"core_bi_pll_test_se",
@@ -128,6 +128,12 @@ static const char * const gcc_parent_names_8[] = {
"core_bi_pll_test_se",
};
+static const char * const gcc_parent_names_8_ao[] = {
+ "bi_tcxo_ao",
+ "gpll0",
+ "core_bi_pll_test_se",
+};
+
static const struct parent_map gcc_parent_map_10[] = {
{ P_BI_TCXO, 0 },
{ P_GPLL0_OUT_MAIN, 1 },
@@ -210,7 +216,7 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
.freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_cpuss_ahb_clk_src",
- .parent_names = gcc_parent_names_7,
+ .parent_names = gcc_parent_names_7_ao,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
@@ -229,7 +235,7 @@ static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = {
.freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_cpuss_rbcpr_clk_src",
- .parent_names = gcc_parent_names_8,
+ .parent_names = gcc_parent_names_8_ao,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
index 2d5d8b43727e..c4d0b6f6abf2 100644
--- a/drivers/clk/socfpga/clk-pll-s10.c
+++ b/drivers/clk/socfpga/clk-pll-s10.c
@@ -43,7 +43,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
/* Read mdiv and fdiv from the fdbck register */
reg = readl(socfpgaclk->hw.reg + 0x4);
mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
- vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+ vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
return (unsigned long)vco_freq;
}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
index 5b238fc314ac..8281dfbf38c2 100644
--- a/drivers/clk/socfpga/clk-s10.c
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -12,17 +12,17 @@
#include "stratix10-clk.h"
-static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
- "f2s_free_clk",};
+static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
+ "f2s-free-clk",};
static const char * const cntr_mux[] = { "main_pll", "periph_pll",
- "osc1", "cb_intosc_hs_div2_clk",
- "f2s_free_clk"};
-static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+ "osc1", "cb-intosc-hs-div2-clk",
+ "f2s-free-clk"};
+static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
static const char * const noc_free_mux[] = {"main_noc_base_clk",
"peri_noc_base_clk",
- "osc1", "cb_intosc_hs_div2_clk",
- "f2s_free_clk"};
+ "osc1", "cb-intosc-hs-div2-clk",
+ "f2s-free-clk"};
static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
@@ -33,14 +33,14 @@ static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"
static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
-static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
"peri_mpu_base_clk",
- "osc1", "cb_intosc_hs_div2_clk",
- "f2s_free_clk"};
+ "osc1", "cb-intosc-hs-div2-clk",
+ "f2s-free-clk"};
/* clocks in AO (always on) controller */
static const struct stratix10_pll_clock s10_pll_clks[] = {
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
index 3b97f60540ad..609970c0b666 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
@@ -264,9 +264,9 @@ static SUNXI_CCU_GATE(ahb1_mmc1_clk, "ahb1-mmc1", "ahb1",
static SUNXI_CCU_GATE(ahb1_mmc2_clk, "ahb1-mmc2", "ahb1",
0x060, BIT(10), 0);
static SUNXI_CCU_GATE(ahb1_mmc3_clk, "ahb1-mmc3", "ahb1",
- 0x060, BIT(12), 0);
+ 0x060, BIT(11), 0);
static SUNXI_CCU_GATE(ahb1_nand1_clk, "ahb1-nand1", "ahb1",
- 0x060, BIT(13), 0);
+ 0x060, BIT(12), 0);
static SUNXI_CCU_GATE(ahb1_nand0_clk, "ahb1-nand0", "ahb1",
0x060, BIT(13), 0);
static SUNXI_CCU_GATE(ahb1_sdram_clk, "ahb1-sdram", "ahb1",
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index 621b1cd996db..ac12f261f8ca 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -542,7 +542,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_BUS_OHCI0] = { 0x2c0, BIT(29) },
[RST_BUS_VE] = { 0x2c4, BIT(0) },
- [RST_BUS_TCON0] = { 0x2c4, BIT(3) },
+ [RST_BUS_TCON0] = { 0x2c4, BIT(4) },
[RST_BUS_CSI] = { 0x2c4, BIT(8) },
[RST_BUS_DE] = { 0x2c4, BIT(12) },
[RST_BUS_DBG] = { 0x2c4, BIT(31) },
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
index 7ddacae5d0b1..1adcccfa7829 100644
--- a/drivers/clk/tegra/Kconfig
+++ b/drivers/clk/tegra/Kconfig
@@ -5,3 +5,8 @@ config TEGRA_CLK_EMC
config CLK_TEGRA_BPMP
def_bool y
depends on TEGRA_BPMP
+
+config TEGRA_CLK_DFLL
+ depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
+ select PM_OPP
+ def_bool y
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 6507acc843c7..4812e45c2214 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
-obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o
+obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
obj-y += cvb.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index 609e363dabf8..0400e5b1d627 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -1,7 +1,7 @@
/*
* clk-dfll.c - Tegra DFLL clock source common code
*
- * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
*
* Aleksandr Frid <afrid@nvidia.com>
* Paul Walmsley <pwalmsley@nvidia.com>
@@ -47,6 +47,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -243,6 +244,12 @@ enum dfll_tune_range {
DFLL_TUNE_LOW = 1,
};
+
+enum tegra_dfll_pmu_if {
+ TEGRA_DFLL_PMU_I2C = 0,
+ TEGRA_DFLL_PMU_PWM = 1,
+};
+
/**
* struct dfll_rate_req - target DFLL rate request data
* @rate: target frequency, after the postscaling
@@ -300,10 +307,19 @@ struct tegra_dfll {
u32 i2c_reg;
u32 i2c_slave_addr;
- /* i2c_lut array entries are regulator framework selectors */
- unsigned i2c_lut[MAX_DFLL_VOLTAGES];
- int i2c_lut_size;
- u8 lut_min, lut_max, lut_safe;
+ /* lut array entries are regulator framework selectors or PWM values*/
+ unsigned lut[MAX_DFLL_VOLTAGES];
+ unsigned long lut_uv[MAX_DFLL_VOLTAGES];
+ int lut_size;
+ u8 lut_bottom, lut_min, lut_max, lut_safe;
+
+ /* PWM interface */
+ enum tegra_dfll_pmu_if pmu_if;
+ unsigned long pwm_rate;
+ struct pinctrl *pwm_pin;
+ struct pinctrl_state *pwm_enable_state;
+ struct pinctrl_state *pwm_disable_state;
+ u32 reg_init_uV;
};
#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -490,6 +506,34 @@ static void dfll_set_mode(struct tegra_dfll *td,
}
/*
+ * DVCO rate control
+ */
+
+static unsigned long get_dvco_rate_below(struct tegra_dfll *td, u8 out_min)
+{
+ struct dev_pm_opp *opp;
+ unsigned long rate, prev_rate;
+ unsigned long uv, min_uv;
+
+ min_uv = td->lut_uv[out_min];
+ for (rate = 0, prev_rate = 0; ; rate++) {
+ opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
+ if (IS_ERR(opp))
+ break;
+
+ uv = dev_pm_opp_get_voltage(opp);
+ dev_pm_opp_put(opp);
+
+ if (uv && uv > min_uv)
+ return prev_rate;
+
+ prev_rate = rate;
+ }
+
+ return prev_rate;
+}
+
+/*
* DFLL-to-I2C controller interface
*/
@@ -518,6 +562,118 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
return 0;
}
+
+/*
+ * DFLL-to-PWM controller interface
+ */
+
+/**
+ * dfll_pwm_set_output_enabled - enable/disable PWM voltage requests
+ * @td: DFLL instance
+ * @enable: whether to enable or disable the PWM voltage requests
+ *
+ * Set the master enable control for PWM control value updates. If disabled,
+ * then the PWM signal is not driven. Also configure the PWM output pad
+ * to the appropriate state.
+ */
+static int dfll_pwm_set_output_enabled(struct tegra_dfll *td, bool enable)
+{
+ int ret;
+ u32 val, div;
+
+ if (enable) {
+ ret = pinctrl_select_state(td->pwm_pin, td->pwm_enable_state);
+ if (ret < 0) {
+ dev_err(td->dev, "setting enable state failed\n");
+ return -EINVAL;
+ }
+ val = dfll_readl(td, DFLL_OUTPUT_CFG);
+ val &= ~DFLL_OUTPUT_CFG_PWM_DIV_MASK;
+ div = DIV_ROUND_UP(td->ref_rate, td->pwm_rate);
+ val |= (div << DFLL_OUTPUT_CFG_PWM_DIV_SHIFT)
+ & DFLL_OUTPUT_CFG_PWM_DIV_MASK;
+ dfll_writel(td, val, DFLL_OUTPUT_CFG);
+ dfll_wmb(td);
+
+ val |= DFLL_OUTPUT_CFG_PWM_ENABLE;
+ dfll_writel(td, val, DFLL_OUTPUT_CFG);
+ dfll_wmb(td);
+ } else {
+ ret = pinctrl_select_state(td->pwm_pin, td->pwm_disable_state);
+ if (ret < 0)
+ dev_warn(td->dev, "setting disable state failed\n");
+
+ val = dfll_readl(td, DFLL_OUTPUT_CFG);
+ val &= ~DFLL_OUTPUT_CFG_PWM_ENABLE;
+ dfll_writel(td, val, DFLL_OUTPUT_CFG);
+ dfll_wmb(td);
+ }
+
+ return 0;
+}
+
+/**
+ * dfll_set_force_output_value - set fixed value for force output
+ * @td: DFLL instance
+ * @out_val: value to force output
+ *
+ * Set the fixed value for force output, DFLL will output this value when
+ * force output is enabled.
+ */
+static u32 dfll_set_force_output_value(struct tegra_dfll *td, u8 out_val)
+{
+ u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
+
+ val = (val & DFLL_OUTPUT_FORCE_ENABLE) | (out_val & OUT_MASK);
+ dfll_writel(td, val, DFLL_OUTPUT_FORCE);
+ dfll_wmb(td);
+
+ return dfll_readl(td, DFLL_OUTPUT_FORCE);
+}
+
+/**
+ * dfll_set_force_output_enabled - enable/disable force output
+ * @td: DFLL instance
+ * @enable: whether to enable or disable the force output
+ *
+ * Set the enable control for fouce output with fixed value.
+ */
+static void dfll_set_force_output_enabled(struct tegra_dfll *td, bool enable)
+{
+ u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
+
+ if (enable)
+ val |= DFLL_OUTPUT_FORCE_ENABLE;
+ else
+ val &= ~DFLL_OUTPUT_FORCE_ENABLE;
+
+ dfll_writel(td, val, DFLL_OUTPUT_FORCE);
+ dfll_wmb(td);
+}
+
+/**
+ * dfll_force_output - force output a fixed value
+ * @td: DFLL instance
+ * @out_sel: value to force output
+ *
+ * Set the fixed value for force output, DFLL will output this value.
+ */
+static int dfll_force_output(struct tegra_dfll *td, unsigned int out_sel)
+{
+ u32 val;
+
+ if (out_sel > OUT_MASK)
+ return -EINVAL;
+
+ val = dfll_set_force_output_value(td, out_sel);
+ if ((td->mode < DFLL_CLOSED_LOOP) &&
+ !(val & DFLL_OUTPUT_FORCE_ENABLE)) {
+ dfll_set_force_output_enabled(td, true);
+ }
+
+ return 0;
+}
+
/**
* dfll_load_lut - load the voltage lookup table
* @td: struct tegra_dfll *
@@ -539,7 +695,7 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td)
lut_index = i;
val = regulator_list_hardware_vsel(td->vdd_reg,
- td->i2c_lut[lut_index]);
+ td->lut[lut_index]);
__raw_writel(val, td->lut_base + i * 4);
}
@@ -594,24 +750,41 @@ static void dfll_init_out_if(struct tegra_dfll *td)
{
u32 val;
- td->lut_min = 0;
- td->lut_max = td->i2c_lut_size - 1;
- td->lut_safe = td->lut_min + 1;
+ td->lut_min = td->lut_bottom;
+ td->lut_max = td->lut_size - 1;
+ td->lut_safe = td->lut_min + (td->lut_min < td->lut_max ? 1 : 0);
+
+ /* clear DFLL_OUTPUT_CFG before setting new value */
+ dfll_writel(td, 0, DFLL_OUTPUT_CFG);
+ dfll_wmb(td);
- dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
- (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
- (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
- dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
- dfll_i2c_wmb(td);
+ (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
+ (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
+ dfll_writel(td, val, DFLL_OUTPUT_CFG);
+ dfll_wmb(td);
dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
dfll_i2c_writel(td, 0, DFLL_INTR_EN);
dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
DFLL_INTR_STS);
- dfll_load_i2c_lut(td);
- dfll_init_i2c_if(td);
+ if (td->pmu_if == TEGRA_DFLL_PMU_PWM) {
+ u32 vinit = td->reg_init_uV;
+ int vstep = td->soc->alignment.step_uv;
+ unsigned long vmin = td->lut_uv[0];
+
+ /* set initial voltage */
+ if ((vinit >= vmin) && vstep) {
+ unsigned int vsel;
+
+ vsel = DIV_ROUND_UP((vinit - vmin), vstep);
+ dfll_force_output(td, vsel);
+ }
+ } else {
+ dfll_load_i2c_lut(td);
+ dfll_init_i2c_if(td);
+ }
}
/*
@@ -631,17 +804,17 @@ static void dfll_init_out_if(struct tegra_dfll *td)
static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
{
struct dev_pm_opp *opp;
- int i, uv;
+ int i, align_step;
opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
if (IS_ERR(opp))
return PTR_ERR(opp);
- uv = dev_pm_opp_get_voltage(opp);
+ align_step = dev_pm_opp_get_voltage(opp) / td->soc->alignment.step_uv;
dev_pm_opp_put(opp);
- for (i = 0; i < td->i2c_lut_size; i++) {
- if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
+ for (i = td->lut_bottom; i < td->lut_size; i++) {
+ if ((td->lut_uv[i] / td->soc->alignment.step_uv) >= align_step)
return i;
}
@@ -863,9 +1036,14 @@ static int dfll_lock(struct tegra_dfll *td)
return -EINVAL;
}
- dfll_i2c_set_output_enabled(td, true);
+ if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
+ dfll_pwm_set_output_enabled(td, true);
+ else
+ dfll_i2c_set_output_enabled(td, true);
+
dfll_set_mode(td, DFLL_CLOSED_LOOP);
dfll_set_frequency_request(td, req);
+ dfll_set_force_output_enabled(td, false);
return 0;
default:
@@ -889,7 +1067,10 @@ static int dfll_unlock(struct tegra_dfll *td)
case DFLL_CLOSED_LOOP:
dfll_set_open_loop_config(td);
dfll_set_mode(td, DFLL_OPEN_LOOP);
- dfll_i2c_set_output_enabled(td, false);
+ if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
+ dfll_pwm_set_output_enabled(td, false);
+ else
+ dfll_i2c_set_output_enabled(td, false);
return 0;
case DFLL_OPEN_LOOP:
@@ -1171,15 +1352,17 @@ static int attr_registers_show(struct seq_file *s, void *data)
seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
dfll_i2c_readl(td, offs));
- seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
- offs = DFLL_I2C_CLK_DIVISOR;
- seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- __raw_readl(td->i2c_controller_base + offs));
-
- seq_puts(s, "\nLUT:\n");
- for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
+ if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
+ seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
+ offs = DFLL_I2C_CLK_DIVISOR;
seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- __raw_readl(td->lut_base + offs));
+ __raw_readl(td->i2c_controller_base + offs));
+
+ seq_puts(s, "\nLUT:\n");
+ for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
+ seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+ __raw_readl(td->lut_base + offs));
+ }
return 0;
}
@@ -1349,15 +1532,21 @@ di_err1:
*/
static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
{
- int i, n_voltages, reg_uV;
+ int i, n_voltages, reg_uV,reg_volt_id, align_step;
+
+ if (WARN_ON(td->pmu_if == TEGRA_DFLL_PMU_PWM))
+ return -EINVAL;
+ align_step = uV / td->soc->alignment.step_uv;
n_voltages = regulator_count_voltages(td->vdd_reg);
for (i = 0; i < n_voltages; i++) {
reg_uV = regulator_list_voltage(td->vdd_reg, i);
if (reg_uV < 0)
break;
- if (uV == reg_uV)
+ reg_volt_id = reg_uV / td->soc->alignment.step_uv;
+
+ if (align_step == reg_volt_id)
return i;
}
@@ -1371,15 +1560,21 @@ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
* */
static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
{
- int i, n_voltages, reg_uV;
+ int i, n_voltages, reg_uV, reg_volt_id, align_step;
+ if (WARN_ON(td->pmu_if == TEGRA_DFLL_PMU_PWM))
+ return -EINVAL;
+
+ align_step = uV / td->soc->alignment.step_uv;
n_voltages = regulator_count_voltages(td->vdd_reg);
for (i = 0; i < n_voltages; i++) {
reg_uV = regulator_list_voltage(td->vdd_reg, i);
if (reg_uV < 0)
break;
- if (uV <= reg_uV)
+ reg_volt_id = reg_uV / td->soc->alignment.step_uv;
+
+ if (align_step <= reg_volt_id)
return i;
}
@@ -1387,9 +1582,61 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
return -EINVAL;
}
+/*
+ * dfll_build_pwm_lut - build the PWM regulator lookup table
+ * @td: DFLL instance
+ * @v_max: Vmax from OPP table
+ *
+ * Look-up table in h/w is ignored when PWM is used as DFLL interface to PMIC.
+ * In this case closed loop output is controlling duty cycle directly. The s/w
+ * look-up that maps PWM duty cycle to voltage is still built by this function.
+ */
+static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
+{
+ int i;
+ unsigned long rate, reg_volt;
+ u8 lut_bottom = MAX_DFLL_VOLTAGES;
+ int v_min = td->soc->cvb->min_millivolts * 1000;
+
+ for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
+ reg_volt = td->lut_uv[i];
+
+ /* since opp voltage is exact mv */
+ reg_volt = (reg_volt / 1000) * 1000;
+ if (reg_volt > v_max)
+ break;
+
+ td->lut[i] = i;
+ if ((lut_bottom == MAX_DFLL_VOLTAGES) && (reg_volt >= v_min))
+ lut_bottom = i;
+ }
+
+ /* determine voltage boundaries */
+ td->lut_size = i;
+ if ((lut_bottom == MAX_DFLL_VOLTAGES) ||
+ (lut_bottom + 1 >= td->lut_size)) {
+ dev_err(td->dev, "no voltage above DFLL minimum %d mV\n",
+ td->soc->cvb->min_millivolts);
+ return -EINVAL;
+ }
+ td->lut_bottom = lut_bottom;
+
+ /* determine rate boundaries */
+ rate = get_dvco_rate_below(td, td->lut_bottom);
+ if (!rate) {
+ dev_err(td->dev, "no opp below DFLL minimum voltage %d mV\n",
+ td->soc->cvb->min_millivolts);
+ return -EINVAL;
+ }
+ td->dvco_rate_min = rate;
+
+ return 0;
+}
+
/**
* dfll_build_i2c_lut - build the I2C voltage register lookup table
* @td: DFLL instance
+ * @v_max: Vmax from OPP table
*
* The DFLL hardware has 33 bytes of look-up table RAM that must be filled with
* PMIC voltage register values that span the entire DFLL operating range.
@@ -1397,33 +1644,24 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
* the soc-specific platform driver (td->soc->opp_dev) and the PMIC
* register-to-voltage mapping queried from the regulator framework.
*
- * On success, fills in td->i2c_lut and returns 0, or -err on failure.
+ * On success, fills in td->lut and returns 0, or -err on failure.
*/
-static int dfll_build_i2c_lut(struct tegra_dfll *td)
+static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
{
+ unsigned long rate, v, v_opp;
int ret = -EINVAL;
- int j, v, v_max, v_opp;
- int selector;
- unsigned long rate;
- struct dev_pm_opp *opp;
- int lut;
-
- rate = ULONG_MAX;
- opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
- if (IS_ERR(opp)) {
- dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
- goto out;
- }
- v_max = dev_pm_opp_get_voltage(opp);
- dev_pm_opp_put(opp);
+ int j, selector, lut;
v = td->soc->cvb->min_millivolts * 1000;
lut = find_vdd_map_entry_exact(td, v);
if (lut < 0)
goto out;
- td->i2c_lut[0] = lut;
+ td->lut[0] = lut;
+ td->lut_bottom = 0;
for (j = 1, rate = 0; ; rate++) {
+ struct dev_pm_opp *opp;
+
opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
if (IS_ERR(opp))
break;
@@ -1435,39 +1673,64 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
dev_pm_opp_put(opp);
for (;;) {
- v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
+ v += max(1UL, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
if (v >= v_opp)
break;
selector = find_vdd_map_entry_min(td, v);
if (selector < 0)
goto out;
- if (selector != td->i2c_lut[j - 1])
- td->i2c_lut[j++] = selector;
+ if (selector != td->lut[j - 1])
+ td->lut[j++] = selector;
}
v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp;
selector = find_vdd_map_entry_exact(td, v);
if (selector < 0)
goto out;
- if (selector != td->i2c_lut[j - 1])
- td->i2c_lut[j++] = selector;
+ if (selector != td->lut[j - 1])
+ td->lut[j++] = selector;
if (v >= v_max)
break;
}
- td->i2c_lut_size = j;
+ td->lut_size = j;
if (!td->dvco_rate_min)
dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
td->soc->cvb->min_millivolts);
- else
+ else {
ret = 0;
+ for (j = 0; j < td->lut_size; j++)
+ td->lut_uv[j] =
+ regulator_list_voltage(td->vdd_reg,
+ td->lut[j]);
+ }
out:
return ret;
}
+static int dfll_build_lut(struct tegra_dfll *td)
+{
+ unsigned long rate, v_max;
+ struct dev_pm_opp *opp;
+
+ rate = ULONG_MAX;
+ opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
+ if (IS_ERR(opp)) {
+ dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
+ return -EINVAL;
+ }
+ v_max = dev_pm_opp_get_voltage(opp);
+ dev_pm_opp_put(opp);
+
+ if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
+ return dfll_build_pwm_lut(td, v_max);
+ else
+ return dfll_build_i2c_lut(td, v_max);
+}
+
/**
* read_dt_param - helper function for reading required parameters from the DT
* @td: DFLL instance
@@ -1526,11 +1789,56 @@ static int dfll_fetch_i2c_params(struct tegra_dfll *td)
}
td->i2c_reg = vsel_reg;
- ret = dfll_build_i2c_lut(td);
- if (ret) {
- dev_err(td->dev, "couldn't build I2C LUT\n");
+ return 0;
+}
+
+static int dfll_fetch_pwm_params(struct tegra_dfll *td)
+{
+ int ret, i;
+ u32 pwm_period;
+
+ if (!td->soc->alignment.step_uv || !td->soc->alignment.offset_uv) {
+ dev_err(td->dev,
+ "Missing step or alignment info for PWM regulator");
+ return -EINVAL;
+ }
+ for (i = 0; i < MAX_DFLL_VOLTAGES; i++)
+ td->lut_uv[i] = td->soc->alignment.offset_uv +
+ i * td->soc->alignment.step_uv;
+
+ ret = read_dt_param(td, "nvidia,pwm-tristate-microvolts",
+ &td->reg_init_uV);
+ if (!ret) {
+ dev_err(td->dev, "couldn't get initialized voltage\n");
+ return ret;
+ }
+
+ ret = read_dt_param(td, "nvidia,pwm-period-nanoseconds", &pwm_period);
+ if (!ret) {
+ dev_err(td->dev, "couldn't get PWM period\n");
return ret;
}
+ td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES - 1);
+
+ td->pwm_pin = devm_pinctrl_get(td->dev);
+ if (IS_ERR(td->pwm_pin)) {
+ dev_err(td->dev, "DT: missing pinctrl device\n");
+ return PTR_ERR(td->pwm_pin);
+ }
+
+ td->pwm_enable_state = pinctrl_lookup_state(td->pwm_pin,
+ "dvfs_pwm_enable");
+ if (IS_ERR(td->pwm_enable_state)) {
+ dev_err(td->dev, "DT: missing pwm enabled state\n");
+ return PTR_ERR(td->pwm_enable_state);
+ }
+
+ td->pwm_disable_state = pinctrl_lookup_state(td->pwm_pin,
+ "dvfs_pwm_disable");
+ if (IS_ERR(td->pwm_disable_state)) {
+ dev_err(td->dev, "DT: missing pwm disabled state\n");
+ return PTR_ERR(td->pwm_disable_state);
+ }
return 0;
}
@@ -1597,16 +1905,6 @@ int tegra_dfll_register(struct platform_device *pdev,
td->soc = soc;
- td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
- if (IS_ERR(td->vdd_reg)) {
- ret = PTR_ERR(td->vdd_reg);
- if (ret != -EPROBE_DEFER)
- dev_err(td->dev, "couldn't get vdd_cpu regulator: %d\n",
- ret);
-
- return ret;
- }
-
td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
if (IS_ERR(td->dvco_rst)) {
dev_err(td->dev, "couldn't get dvco reset\n");
@@ -1619,10 +1917,27 @@ int tegra_dfll_register(struct platform_device *pdev,
return ret;
}
- ret = dfll_fetch_i2c_params(td);
+ if (of_property_read_bool(td->dev->of_node, "nvidia,pwm-to-pmic")) {
+ td->pmu_if = TEGRA_DFLL_PMU_PWM;
+ ret = dfll_fetch_pwm_params(td);
+ } else {
+ td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
+ if (IS_ERR(td->vdd_reg)) {
+ dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
+ return PTR_ERR(td->vdd_reg);
+ }
+ td->pmu_if = TEGRA_DFLL_PMU_I2C;
+ ret = dfll_fetch_i2c_params(td);
+ }
if (ret)
return ret;
+ ret = dfll_build_lut(td);
+ if (ret) {
+ dev_err(td->dev, "couldn't build LUT\n");
+ return ret;
+ }
+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(td->dev, "no control register resource\n");
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
index 83352c8078f2..85d0d95223f3 100644
--- a/drivers/clk/tegra/clk-dfll.h
+++ b/drivers/clk/tegra/clk-dfll.h
@@ -1,6 +1,6 @@
/*
* clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver
- * Copyright (C) 2013 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2013-2019 NVIDIA Corporation. All rights reserved.
*
* Aleksandr Frid <afrid@nvidia.com>
* Paul Walmsley <pwalmsley@nvidia.com>
@@ -22,11 +22,14 @@
#include <linux/reset.h>
#include <linux/types.h>
+#include "cvb.h"
+
/**
* struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
* @dev: struct device * that holds the OPP table for the DFLL
* @max_freq: maximum frequency supported on this SoC
* @cvb: CPU frequency table for this SoC
+ * @alignment: parameters of the regulator step and offset
* @init_clock_trimmers: callback to initialize clock trimmers
* @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
* @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
@@ -35,6 +38,7 @@ struct tegra_dfll_soc_data {
struct device *dev;
unsigned long max_freq;
const struct cvb_table *cvb;
+ struct rail_alignment alignment;
void (*init_clock_trimmers)(void);
void (*set_clock_trimmers_high)(void);
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
index 269d3595758b..e8ec42bf8638 100644
--- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -1,7 +1,7 @@
/*
* Tegra124 DFLL FCPU clock source driver
*
- * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
*
* Aleksandr Frid <afrid@nvidia.com>
* Paul Walmsley <pwalmsley@nvidia.com>
@@ -21,15 +21,24 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <soc/tegra/fuse.h>
#include "clk.h"
#include "clk-dfll.h"
#include "cvb.h"
+struct dfll_fcpu_data {
+ const unsigned long *cpu_max_freq_table;
+ unsigned int cpu_max_freq_table_size;
+ const struct cvb_table *cpu_cvb_tables;
+ unsigned int cpu_cvb_tables_size;
+};
+
/* Maximum CPU frequency, indexed by CPU speedo id */
-static const unsigned long cpu_max_freq_table[] = {
+static const unsigned long tegra124_cpu_max_freq_table[] = {
[0] = 2014500000UL,
[1] = 2320500000UL,
[2] = 2116500000UL,
@@ -42,9 +51,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
.process_id = -1,
.min_millivolts = 900,
.max_millivolts = 1260,
- .alignment = {
- .step_uv = 10000, /* 10mV */
- },
.speedo_scale = 100,
.voltage_scale = 1000,
.entries = {
@@ -82,16 +88,493 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
},
};
+static const unsigned long tegra210_cpu_max_freq_table[] = {
+ [0] = 1912500000UL,
+ [1] = 1912500000UL,
+ [2] = 2218500000UL,
+ [3] = 1785000000UL,
+ [4] = 1632000000UL,
+ [5] = 1912500000UL,
+ [6] = 2014500000UL,
+ [7] = 1734000000UL,
+ [8] = 1683000000UL,
+ [9] = 1555500000UL,
+ [10] = 1504500000UL,
+};
+
+#define CPU_CVB_TABLE \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 1007452, -23865, 370 } }, \
+ { 306000000UL, { 1052709, -24875, 370 } }, \
+ { 408000000UL, { 1099069, -25895, 370 } }, \
+ { 510000000UL, { 1146534, -26905, 370 } }, \
+ { 612000000UL, { 1195102, -27915, 370 } }, \
+ { 714000000UL, { 1244773, -28925, 370 } }, \
+ { 816000000UL, { 1295549, -29935, 370 } }, \
+ { 918000000UL, { 1347428, -30955, 370 } }, \
+ { 1020000000UL, { 1400411, -31965, 370 } }, \
+ { 1122000000UL, { 1454497, -32975, 370 } }, \
+ { 1224000000UL, { 1509687, -33985, 370 } }, \
+ { 1326000000UL, { 1565981, -35005, 370 } }, \
+ { 1428000000UL, { 1623379, -36015, 370 } }, \
+ { 1530000000UL, { 1681880, -37025, 370 } }, \
+ { 1632000000UL, { 1741485, -38035, 370 } }, \
+ { 1734000000UL, { 1802194, -39055, 370 } }, \
+ { 1836000000UL, { 1864006, -40065, 370 } }, \
+ { 1912500000UL, { 1910780, -40815, 370 } }, \
+ { 2014500000UL, { 1227000, 0, 0 } }, \
+ { 2218500000UL, { 1227000, 0, 0 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+#define CPU_CVB_TABLE_XA \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 1250024, -39785, 565 } }, \
+ { 306000000UL, { 1297556, -41145, 565 } }, \
+ { 408000000UL, { 1346718, -42505, 565 } }, \
+ { 510000000UL, { 1397511, -43855, 565 } }, \
+ { 612000000UL, { 1449933, -45215, 565 } }, \
+ { 714000000UL, { 1503986, -46575, 565 } }, \
+ { 816000000UL, { 1559669, -47935, 565 } }, \
+ { 918000000UL, { 1616982, -49295, 565 } }, \
+ { 1020000000UL, { 1675926, -50645, 565 } }, \
+ { 1122000000UL, { 1736500, -52005, 565 } }, \
+ { 1224000000UL, { 1798704, -53365, 565 } }, \
+ { 1326000000UL, { 1862538, -54725, 565 } }, \
+ { 1428000000UL, { 1928003, -56085, 565 } }, \
+ { 1530000000UL, { 1995097, -57435, 565 } }, \
+ { 1606500000UL, { 2046149, -58445, 565 } }, \
+ { 1632000000UL, { 2063822, -58795, 565 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+#define CPU_CVB_TABLE_EUCM1 \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 734429, 0, 0 } }, \
+ { 306000000UL, { 768191, 0, 0 } }, \
+ { 408000000UL, { 801953, 0, 0 } }, \
+ { 510000000UL, { 835715, 0, 0 } }, \
+ { 612000000UL, { 869477, 0, 0 } }, \
+ { 714000000UL, { 903239, 0, 0 } }, \
+ { 816000000UL, { 937001, 0, 0 } }, \
+ { 918000000UL, { 970763, 0, 0 } }, \
+ { 1020000000UL, { 1004525, 0, 0 } }, \
+ { 1122000000UL, { 1038287, 0, 0 } }, \
+ { 1224000000UL, { 1072049, 0, 0 } }, \
+ { 1326000000UL, { 1105811, 0, 0 } }, \
+ { 1428000000UL, { 1130000, 0, 0 } }, \
+ { 1555500000UL, { 1130000, 0, 0 } }, \
+ { 1632000000UL, { 1170000, 0, 0 } }, \
+ { 1734000000UL, { 1227500, 0, 0 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+#define CPU_CVB_TABLE_EUCM2 \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 742283, 0, 0 } }, \
+ { 306000000UL, { 776249, 0, 0 } }, \
+ { 408000000UL, { 810215, 0, 0 } }, \
+ { 510000000UL, { 844181, 0, 0 } }, \
+ { 612000000UL, { 878147, 0, 0 } }, \
+ { 714000000UL, { 912113, 0, 0 } }, \
+ { 816000000UL, { 946079, 0, 0 } }, \
+ { 918000000UL, { 980045, 0, 0 } }, \
+ { 1020000000UL, { 1014011, 0, 0 } }, \
+ { 1122000000UL, { 1047977, 0, 0 } }, \
+ { 1224000000UL, { 1081943, 0, 0 } }, \
+ { 1326000000UL, { 1090000, 0, 0 } }, \
+ { 1479000000UL, { 1090000, 0, 0 } }, \
+ { 1555500000UL, { 1162000, 0, 0 } }, \
+ { 1683000000UL, { 1195000, 0, 0 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+#define CPU_CVB_TABLE_EUCM2_JOINT_RAIL \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 742283, 0, 0 } }, \
+ { 306000000UL, { 776249, 0, 0 } }, \
+ { 408000000UL, { 810215, 0, 0 } }, \
+ { 510000000UL, { 844181, 0, 0 } }, \
+ { 612000000UL, { 878147, 0, 0 } }, \
+ { 714000000UL, { 912113, 0, 0 } }, \
+ { 816000000UL, { 946079, 0, 0 } }, \
+ { 918000000UL, { 980045, 0, 0 } }, \
+ { 1020000000UL, { 1014011, 0, 0 } }, \
+ { 1122000000UL, { 1047977, 0, 0 } }, \
+ { 1224000000UL, { 1081943, 0, 0 } }, \
+ { 1326000000UL, { 1090000, 0, 0 } }, \
+ { 1479000000UL, { 1090000, 0, 0 } }, \
+ { 1504500000UL, { 1120000, 0, 0 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+#define CPU_CVB_TABLE_ODN \
+ .speedo_scale = 100, \
+ .voltage_scale = 1000, \
+ .entries = { \
+ { 204000000UL, { 721094, 0, 0 } }, \
+ { 306000000UL, { 754040, 0, 0 } }, \
+ { 408000000UL, { 786986, 0, 0 } }, \
+ { 510000000UL, { 819932, 0, 0 } }, \
+ { 612000000UL, { 852878, 0, 0 } }, \
+ { 714000000UL, { 885824, 0, 0 } }, \
+ { 816000000UL, { 918770, 0, 0 } }, \
+ { 918000000UL, { 915716, 0, 0 } }, \
+ { 1020000000UL, { 984662, 0, 0 } }, \
+ { 1122000000UL, { 1017608, 0, 0 } }, \
+ { 1224000000UL, { 1050554, 0, 0 } }, \
+ { 1326000000UL, { 1083500, 0, 0 } }, \
+ { 1428000000UL, { 1116446, 0, 0 } }, \
+ { 1581000000UL, { 1130000, 0, 0 } }, \
+ { 1683000000UL, { 1168000, 0, 0 } }, \
+ { 1785000000UL, { 1227500, 0, 0 } }, \
+ { 0UL, { 0, 0, 0 } }, \
+ }
+
+static struct cvb_table tegra210_cpu_cvb_tables[] = {
+ {
+ .speedo_id = 10,
+ .process_id = 0,
+ .min_millivolts = 840,
+ .max_millivolts = 1120,
+ CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 10,
+ .process_id = 1,
+ .min_millivolts = 840,
+ .max_millivolts = 1120,
+ CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 9,
+ .process_id = 0,
+ .min_millivolts = 900,
+ .max_millivolts = 1162,
+ CPU_CVB_TABLE_EUCM2,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 9,
+ .process_id = 1,
+ .min_millivolts = 900,
+ .max_millivolts = 1162,
+ CPU_CVB_TABLE_EUCM2,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 8,
+ .process_id = 0,
+ .min_millivolts = 900,
+ .max_millivolts = 1195,
+ CPU_CVB_TABLE_EUCM2,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 8,
+ .process_id = 1,
+ .min_millivolts = 900,
+ .max_millivolts = 1195,
+ CPU_CVB_TABLE_EUCM2,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 7,
+ .process_id = 0,
+ .min_millivolts = 841,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE_EUCM1,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 7,
+ .process_id = 1,
+ .min_millivolts = 841,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE_EUCM1,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 6,
+ .process_id = 0,
+ .min_millivolts = 870,
+ .max_millivolts = 1150,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 6,
+ .process_id = 1,
+ .min_millivolts = 870,
+ .max_millivolts = 1150,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ }
+ },
+ {
+ .speedo_id = 5,
+ .process_id = 0,
+ .min_millivolts = 818,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 5,
+ .process_id = 1,
+ .min_millivolts = 818,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 4,
+ .process_id = -1,
+ .min_millivolts = 918,
+ .max_millivolts = 1113,
+ CPU_CVB_TABLE_XA,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune1 = 0x17711BD,
+ }
+ },
+ {
+ .speedo_id = 3,
+ .process_id = 0,
+ .min_millivolts = 825,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE_ODN,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 3,
+ .process_id = 1,
+ .min_millivolts = 825,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE_ODN,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 2,
+ .process_id = 0,
+ .min_millivolts = 870,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ }
+ },
+ {
+ .speedo_id = 2,
+ .process_id = 1,
+ .min_millivolts = 870,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ }
+ },
+ {
+ .speedo_id = 1,
+ .process_id = 0,
+ .min_millivolts = 837,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 1,
+ .process_id = 1,
+ .min_millivolts = 837,
+ .max_millivolts = 1227,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 0,
+ .process_id = 0,
+ .min_millivolts = 850,
+ .max_millivolts = 1170,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x20091d9,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+ {
+ .speedo_id = 0,
+ .process_id = 1,
+ .min_millivolts = 850,
+ .max_millivolts = 1170,
+ CPU_CVB_TABLE,
+ .cpu_dfll_data = {
+ .tune0_low = 0xffead0ff,
+ .tune0_high = 0xffead0ff,
+ .tune1 = 0x25501d0,
+ .tune_high_min_millivolts = 864,
+ }
+ },
+};
+
+static const struct dfll_fcpu_data tegra124_dfll_fcpu_data = {
+ .cpu_max_freq_table = tegra124_cpu_max_freq_table,
+ .cpu_max_freq_table_size = ARRAY_SIZE(tegra124_cpu_max_freq_table),
+ .cpu_cvb_tables = tegra124_cpu_cvb_tables,
+ .cpu_cvb_tables_size = ARRAY_SIZE(tegra124_cpu_cvb_tables)
+};
+
+static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
+ .cpu_max_freq_table = tegra210_cpu_max_freq_table,
+ .cpu_max_freq_table_size = ARRAY_SIZE(tegra210_cpu_max_freq_table),
+ .cpu_cvb_tables = tegra210_cpu_cvb_tables,
+ .cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
+};
+
+static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
+ {
+ .compatible = "nvidia,tegra124-dfll",
+ .data = &tegra124_dfll_fcpu_data,
+ },
+ {
+ .compatible = "nvidia,tegra210-dfll",
+ .data = &tegra210_dfll_fcpu_data
+ },
+ { },
+};
+
+static void get_alignment_from_dt(struct device *dev,
+ struct rail_alignment *align)
+{
+ if (of_property_read_u32(dev->of_node,
+ "nvidia,pwm-voltage-step-microvolts",
+ &align->step_uv))
+ align->step_uv = 0;
+
+ if (of_property_read_u32(dev->of_node,
+ "nvidia,pwm-min-microvolts",
+ &align->offset_uv))
+ align->offset_uv = 0;
+}
+
+static int get_alignment_from_regulator(struct device *dev,
+ struct rail_alignment *align)
+{
+ struct regulator *reg = devm_regulator_get(dev, "vdd-cpu");
+
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ align->offset_uv = regulator_list_voltage(reg, 0);
+ align->step_uv = regulator_get_linear_step(reg);
+
+ devm_regulator_put(reg);
+
+ return 0;
+}
+
static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
{
int process_id, speedo_id, speedo_value, err;
struct tegra_dfll_soc_data *soc;
+ const struct dfll_fcpu_data *fcpu_data;
+ struct rail_alignment align;
+
+ fcpu_data = of_device_get_match_data(&pdev->dev);
+ if (!fcpu_data)
+ return -ENODEV;
process_id = tegra_sku_info.cpu_process_id;
speedo_id = tegra_sku_info.cpu_speedo_id;
speedo_value = tegra_sku_info.cpu_speedo_value;
- if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) {
+ if (speedo_id >= fcpu_data->cpu_max_freq_table_size) {
dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
speedo_id);
return -ENODEV;
@@ -107,12 +590,22 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
return -ENODEV;
}
- soc->max_freq = cpu_max_freq_table[speedo_id];
+ if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic")) {
+ get_alignment_from_dt(&pdev->dev, &align);
+ } else {
+ err = get_alignment_from_regulator(&pdev->dev, &align);
+ if (err)
+ return err;
+ }
+
+ soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id];
+
+ soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
+ fcpu_data->cpu_cvb_tables_size,
+ &align, process_id, speedo_id,
+ speedo_value, soc->max_freq);
+ soc->alignment = align;
- soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
- ARRAY_SIZE(tegra124_cpu_cvb_tables),
- process_id, speedo_id, speedo_value,
- soc->max_freq);
if (IS_ERR(soc->cvb)) {
dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
PTR_ERR(soc->cvb));
@@ -133,20 +626,17 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
struct tegra_dfll_soc_data *soc;
soc = tegra_dfll_unregister(pdev);
- if (IS_ERR(soc))
+ if (IS_ERR(soc)) {
dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n",
PTR_ERR(soc));
+ return PTR_ERR(soc);
+ }
tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
return 0;
}
-static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
- { .compatible = "nvidia,tegra124-dfll", },
- { },
-};
-
static const struct dev_pm_ops tegra124_dfll_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
tegra_dfll_runtime_resume, NULL)
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index da9e8e7b5ce5..35eeb6adc68e 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -1,7 +1,7 @@
/*
* Utility functions for parsing Tegra CVB voltage tables
*
- * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved.
*
* 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
@@ -62,9 +62,9 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
}
static int build_opp_table(struct device *dev, const struct cvb_table *table,
+ struct rail_alignment *align,
int speedo_value, unsigned long max_freq)
{
- const struct rail_alignment *align = &table->alignment;
int i, ret, dfll_mv, min_mv, max_mv;
min_mv = round_voltage(table->min_millivolts, align, UP);
@@ -109,8 +109,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
*/
const struct cvb_table *
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
- size_t count, int process_id, int speedo_id,
- int speedo_value, unsigned long max_freq)
+ size_t count, struct rail_alignment *align,
+ int process_id, int speedo_id, int speedo_value,
+ unsigned long max_freq)
{
size_t i;
int ret;
@@ -124,7 +125,8 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
if (table->process_id != -1 && table->process_id != process_id)
continue;
- ret = build_opp_table(dev, table, speedo_value, max_freq);
+ ret = build_opp_table(dev, table, align, speedo_value,
+ max_freq);
return ret ? ERR_PTR(ret) : table;
}
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
index c1f077993b2a..91a1941c21ef 100644
--- a/drivers/clk/tegra/cvb.h
+++ b/drivers/clk/tegra/cvb.h
@@ -41,6 +41,7 @@ struct cvb_cpu_dfll_data {
u32 tune0_low;
u32 tune0_high;
u32 tune1;
+ unsigned int tune_high_min_millivolts;
};
struct cvb_table {
@@ -49,7 +50,6 @@ struct cvb_table {
int min_millivolts;
int max_millivolts;
- struct rail_alignment alignment;
int speedo_scale;
int voltage_scale;
@@ -59,8 +59,9 @@ struct cvb_table {
const struct cvb_table *
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
- size_t count, int process_id, int speedo_id,
- int speedo_value, unsigned long max_freq);
+ size_t count, struct rail_alignment *align,
+ int process_id, int speedo_id, int speedo_value,
+ unsigned long max_freq);
void tegra_cvb_remove_opp_table(struct device *dev,
const struct cvb_table *table,
unsigned long max_freq);
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 8d77090ad94a..0241450f3eb3 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -403,8 +403,10 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
num_dividers = i;
tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
- if (!tmp)
+ if (!tmp) {
+ *table = ERR_PTR(-ENOMEM);
return -ENOMEM;
+ }
valid_div = 0;
*width = 0;
@@ -439,6 +441,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
{
struct clk_omap_divider *div;
struct clk_omap_reg *reg;
+ int ret;
if (!setup)
return NULL;
@@ -458,6 +461,12 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
div->flags |= CLK_DIVIDER_POWER_OF_TWO;
div->table = _get_div_table_from_setup(setup, &div->width);
+ if (IS_ERR(div->table)) {
+ ret = PTR_ERR(div->table);
+ kfree(div);
+ return ERR_PTR(ret);
+ }
+
div->shift = setup->bit_shift;
div->latch = -EINVAL;
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index f65cc0ff76ab..b0908ec62f73 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -669,8 +669,8 @@ static int zynqmp_clk_setup(struct device_node *np)
if (ret)
return ret;
- zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) *
- clock_max_idx, GFP_KERNEL);
+ zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx),
+ GFP_KERNEL);
if (!zynqmp_data)
return -ENOMEM;
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a9e26f6a81a1..171502a356aa 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -131,7 +131,8 @@ config SUN5I_HSTIMER
config TEGRA_TIMER
bool "Tegra timer driver" if COMPILE_TEST
select CLKSRC_MMIO
- depends on ARM
+ select TIMER_OF
+ depends on ARM || ARM64
help
Enables support for the Tegra driver.
@@ -360,6 +361,16 @@ config ARM64_ERRATUM_858921
The workaround will be dynamically enabled when an affected
core is detected.
+config SUN50I_ERRATUM_UNKNOWN1
+ bool "Workaround for Allwinner A64 erratum UNKNOWN1"
+ default y
+ depends on ARM_ARCH_TIMER && ARM64 && ARCH_SUNXI
+ select ARM_ARCH_TIMER_OOL_WORKAROUND
+ help
+ This option enables a workaround for instability in the timer on
+ the Allwinner A64 SoC. The workaround will only be active if the
+ allwinner,erratum-unknown1 property is found in the timer node.
+
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
select TIMER_OF if OF
@@ -634,4 +645,13 @@ config GX6605S_TIMER
help
This option enables support for gx6605s SOC's timer.
+config MILBEAUT_TIMER
+ bool "Milbeaut timer driver" if COMPILE_TEST
+ depends on OF
+ depends on ARM
+ select TIMER_OF
+ select CLKSRC_MMIO
+ help
+ Enables the support for Milbeaut timer driver.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cdd210ff89ea..be6e0fbc7489 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
-obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o
+obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += timer-cs5535.o
obj-$(CONFIG_CLKSRC_JCORE_PIT) += jcore-pit.o
obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
@@ -29,7 +29,7 @@ obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o
obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o
obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o
obj-$(CONFIG_MXS_TIMER) += mxs_timer.o
-obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o
+obj-$(CONFIG_CLKSRC_PXA) += timer-pxa.o
obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
obj-$(CONFIG_U300_TIMER) += timer-u300.o
obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o
@@ -55,6 +55,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
obj-$(CONFIG_OWL_TIMER) += timer-owl.o
+obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
obj-$(CONFIG_RDA_TIMER) += timer-rda.o
@@ -69,7 +70,7 @@ obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o
obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += timer-versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
-obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o
+obj-$(CONFIG_CLKSRC_TANGO_XTAL) += timer-tango-xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 9a7d4dc00b6e..a8b20b65bd4b 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -326,6 +326,48 @@ static u64 notrace arm64_1188873_read_cntvct_el0(void)
}
#endif
+#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
+/*
+ * The low bits of the counter registers are indeterminate while bit 10 or
+ * greater is rolling over. Since the counter value can jump both backward
+ * (7ff -> 000 -> 800) and forward (7ff -> fff -> 800), ignore register values
+ * with all ones or all zeros in the low bits. Bound the loop by the maximum
+ * number of CPU cycles in 3 consecutive 24 MHz counter periods.
+ */
+#define __sun50i_a64_read_reg(reg) ({ \
+ u64 _val; \
+ int _retries = 150; \
+ \
+ do { \
+ _val = read_sysreg(reg); \
+ _retries--; \
+ } while (((_val + 1) & GENMASK(9, 0)) <= 1 && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _val; \
+})
+
+static u64 notrace sun50i_a64_read_cntpct_el0(void)
+{
+ return __sun50i_a64_read_reg(cntpct_el0);
+}
+
+static u64 notrace sun50i_a64_read_cntvct_el0(void)
+{
+ return __sun50i_a64_read_reg(cntvct_el0);
+}
+
+static u32 notrace sun50i_a64_read_cntp_tval_el0(void)
+{
+ return read_sysreg(cntp_cval_el0) - sun50i_a64_read_cntpct_el0();
+}
+
+static u32 notrace sun50i_a64_read_cntv_tval_el0(void)
+{
+ return read_sysreg(cntv_cval_el0) - sun50i_a64_read_cntvct_el0();
+}
+#endif
+
#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround);
EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
@@ -423,6 +465,19 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = {
.read_cntvct_el0 = arm64_1188873_read_cntvct_el0,
},
#endif
+#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
+ {
+ .match_type = ate_match_dt,
+ .id = "allwinner,erratum-unknown1",
+ .desc = "Allwinner erratum UNKNOWN1",
+ .read_cntp_tval_el0 = sun50i_a64_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = sun50i_a64_read_cntv_tval_el0,
+ .read_cntpct_el0 = sun50i_a64_read_cntpct_el0,
+ .read_cntvct_el0 = sun50i_a64_read_cntvct_el0,
+ .set_next_event_phys = erratum_set_next_event_tval_phys,
+ .set_next_event_virt = erratum_set_next_event_tval_virt,
+ },
+#endif
};
typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 7a244b681876..34bd250d46c6 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -10,14 +10,12 @@
* published by the Free Software Foundation.
*/
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/cpu.h>
-#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/percpu.h>
#include <linux/of.h>
@@ -388,6 +386,13 @@ static void exynos4_mct_tick_start(unsigned long cycles,
exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
}
+static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
+{
+ /* Clear the MCT tick interrupt */
+ if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+}
+
static int exynos4_tick_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
@@ -404,6 +409,7 @@ static int set_state_shutdown(struct clock_event_device *evt)
mevt = container_of(evt, struct mct_clock_event_device, evt);
exynos4_mct_tick_stop(mevt);
+ exynos4_mct_tick_clear(mevt);
return 0;
}
@@ -420,8 +426,11 @@ static int set_state_periodic(struct clock_event_device *evt)
return 0;
}
-static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
{
+ struct mct_clock_event_device *mevt = dev_id;
+ struct clock_event_device *evt = &mevt->evt;
+
/*
* This is for supporting oneshot mode.
* Mct would generate interrupt periodically
@@ -430,16 +439,6 @@ static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
if (!clockevent_state_periodic(&mevt->evt))
exynos4_mct_tick_stop(mevt);
- /* Clear the MCT tick interrupt */
- if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
- exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
-}
-
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
-{
- struct mct_clock_event_device *mevt = dev_id;
- struct clock_event_device *evt = &mevt->evt;
-
exynos4_mct_tick_clear(mevt);
evt->event_handler(evt);
@@ -507,13 +506,12 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
int err, cpu;
struct clk *mct_clk, *tick_clk;
- tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
- clk_get(NULL, "fin_pll");
+ tick_clk = of_clk_get_by_name(np, "fin_pll");
if (IS_ERR(tick_clk))
panic("%s: unable to determine tick clock rate\n", __func__);
clk_rate = clk_get_rate(tick_clk);
- mct_clk = np ? of_clk_get_by_name(np, "mct") : clk_get(NULL, "mct");
+ mct_clk = of_clk_get_by_name(np, "mct");
if (IS_ERR(mct_clk))
panic("%s: unable to retrieve mct clock instance\n", __func__);
clk_prepare_enable(mct_clk);
@@ -562,7 +560,19 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
return 0;
out_irq:
- free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
+ if (mct_int_type == MCT_INT_PPI) {
+ free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
+ } else {
+ for_each_possible_cpu(cpu) {
+ struct mct_clock_event_device *pcpu_mevt =
+ per_cpu_ptr(&percpu_mct_tick, cpu);
+
+ if (pcpu_mevt->evt.irq != -1) {
+ free_irq(pcpu_mevt->evt.irq, pcpu_mevt);
+ pcpu_mevt->evt.irq = -1;
+ }
+ }
+ }
return err;
}
@@ -581,11 +591,7 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
* timer irqs are specified after the four global timer
* irqs are specified.
*/
-#ifdef CONFIG_OF
nr_irqs = of_irq_count(np);
-#else
- nr_irqs = 0;
-#endif
for (i = MCT_L0_IRQ; i < nr_irqs; i++)
mct_irqs[i] = irq_of_parse_and_map(np, i);
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/timer-cs5535.c
index 1de8cac99a0e..1de8cac99a0e 100644
--- a/drivers/clocksource/cs5535-clockevt.c
+++ b/drivers/clocksource/timer-cs5535.c
diff --git a/drivers/clocksource/timer-milbeaut.c b/drivers/clocksource/timer-milbeaut.c
new file mode 100644
index 000000000000..f2019a88e3ee
--- /dev/null
+++ b/drivers/clocksource/timer-milbeaut.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Socionext Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/sched_clock.h>
+#include "timer-of.h"
+
+#define MLB_TMR_TMCSR_OFS 0x0
+#define MLB_TMR_TMR_OFS 0x4
+#define MLB_TMR_TMRLR1_OFS 0x8
+#define MLB_TMR_TMRLR2_OFS 0xc
+#define MLB_TMR_REGSZPCH 0x10
+
+#define MLB_TMR_TMCSR_OUTL BIT(5)
+#define MLB_TMR_TMCSR_RELD BIT(4)
+#define MLB_TMR_TMCSR_INTE BIT(3)
+#define MLB_TMR_TMCSR_UF BIT(2)
+#define MLB_TMR_TMCSR_CNTE BIT(1)
+#define MLB_TMR_TMCSR_TRG BIT(0)
+
+#define MLB_TMR_TMCSR_CSL_DIV2 0
+#define MLB_TMR_DIV_CNT 2
+
+#define MLB_TMR_SRC_CH (1)
+#define MLB_TMR_EVT_CH (0)
+
+#define MLB_TMR_SRC_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_SRC_CH)
+#define MLB_TMR_EVT_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_EVT_CH)
+
+#define MLB_TMR_SRC_TMCSR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMCSR_OFS)
+#define MLB_TMR_SRC_TMR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMR_OFS)
+#define MLB_TMR_SRC_TMRLR1_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR1_OFS)
+#define MLB_TMR_SRC_TMRLR2_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR2_OFS)
+
+#define MLB_TMR_EVT_TMCSR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMCSR_OFS)
+#define MLB_TMR_EVT_TMR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMR_OFS)
+#define MLB_TMR_EVT_TMRLR1_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR1_OFS)
+#define MLB_TMR_EVT_TMRLR2_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR2_OFS)
+
+#define MLB_TIMER_RATING 500
+
+static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *clk = dev_id;
+ struct timer_of *to = to_timer_of(clk);
+ u32 val;
+
+ val = readl_relaxed(timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ val &= ~MLB_TMR_TMCSR_UF;
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+
+ clk->event_handler(clk);
+
+ return IRQ_HANDLED;
+}
+
+static int mlb_set_state_periodic(struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+ u32 val = MLB_TMR_TMCSR_CSL_DIV2;
+
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+
+ writel_relaxed(to->of_clk.period, timer_of_base(to) +
+ MLB_TMR_EVT_TMRLR1_OFS);
+ val |= MLB_TMR_TMCSR_RELD | MLB_TMR_TMCSR_CNTE |
+ MLB_TMR_TMCSR_TRG | MLB_TMR_TMCSR_INTE;
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_set_state_oneshot(struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+ u32 val = MLB_TMR_TMCSR_CSL_DIV2;
+
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_clkevt_next_event(unsigned long event,
+ struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+
+ writel_relaxed(event, timer_of_base(to) + MLB_TMR_EVT_TMRLR1_OFS);
+ writel_relaxed(MLB_TMR_TMCSR_CSL_DIV2 |
+ MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_INTE |
+ MLB_TMR_TMCSR_TRG, timer_of_base(to) +
+ MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_config_clock_source(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMR_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR1_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR2_OFS);
+ writel_relaxed(BIT(4) | BIT(1) | BIT(0), timer_of_base(to) +
+ MLB_TMR_SRC_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_config_clock_event(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static struct timer_of to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+
+ .clkevt = {
+ .name = "mlb-clkevt",
+ .rating = MLB_TIMER_RATING,
+ .cpumask = cpu_possible_mask,
+ .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_oneshot = mlb_set_state_oneshot,
+ .set_state_periodic = mlb_set_state_periodic,
+ .set_next_event = mlb_clkevt_next_event,
+ },
+
+ .of_irq = {
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = mlb_timer_interrupt,
+ },
+};
+
+static u64 notrace mlb_timer_sched_read(void)
+{
+ return ~readl_relaxed(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS);
+}
+
+static int __init mlb_timer_init(struct device_node *node)
+{
+ int ret;
+ unsigned long rate;
+
+ ret = timer_of_init(node, &to);
+ if (ret)
+ return ret;
+
+ rate = timer_of_rate(&to) / MLB_TMR_DIV_CNT;
+ mlb_config_clock_source(&to);
+ clocksource_mmio_init(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS,
+ node->name, rate, MLB_TIMER_RATING, 32,
+ clocksource_mmio_readl_down);
+ sched_clock_register(mlb_timer_sched_read, 32, rate);
+ mlb_config_clock_event(&to);
+ clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), 15,
+ 0xffffffff);
+ return 0;
+}
+TIMER_OF_DECLARE(mlb_peritimer, "socionext,milbeaut-timer",
+ mlb_timer_init);
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/timer-pxa.c
index 395837938301..395837938301 100644
--- a/drivers/clocksource/pxa_timer.c
+++ b/drivers/clocksource/timer-pxa.c
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 431892200a08..e8163693e936 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -95,13 +95,30 @@ static int __init riscv_timer_init_dt(struct device_node *n)
struct clocksource *cs;
hartid = riscv_of_processor_hartid(n);
+ if (hartid < 0) {
+ pr_warn("Not valid hartid for node [%pOF] error = [%d]\n",
+ n, hartid);
+ return hartid;
+ }
+
cpuid = riscv_hartid_to_cpuid(hartid);
+ if (cpuid < 0) {
+ pr_warn("Invalid cpuid for hartid [%d]\n", hartid);
+ return cpuid;
+ }
if (cpuid != smp_processor_id())
return 0;
+ pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
+ __func__, cpuid, hartid);
cs = per_cpu_ptr(&riscv_clocksource, cpuid);
- clocksource_register_hz(cs, riscv_timebase);
+ error = clocksource_register_hz(cs, riscv_timebase);
+ if (error) {
+ pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
+ error, cpuid);
+ return error;
+ }
sched_clock_register(riscv_sched_clock,
BITS_PER_LONG, riscv_timebase);
@@ -110,8 +127,8 @@ static int __init riscv_timer_init_dt(struct device_node *n)
"clockevents/riscv/timer:starting",
riscv_timer_starting_cpu, riscv_timer_dying_cpu);
if (error)
- pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
- error, cpuid);
+ pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
+ error);
return error;
}
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index 3b56ea3f52af..552c5254390c 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -202,6 +202,11 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
}
rate = clk_get_rate(clk);
+ if (!rate) {
+ pr_err("Couldn't get parent clock rate\n");
+ ret = -EINVAL;
+ goto err_disable_clk;
+ }
cs->timer.base = base;
cs->timer.clk = clk;
@@ -275,6 +280,11 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem
}
rate = clk_get_rate(clk);
+ if (!rate) {
+ pr_err("Couldn't get parent clock rate\n");
+ ret = -EINVAL;
+ goto err_disable_clk;
+ }
ce->timer.base = base;
ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/timer-tango-xtal.c
index 3f94e454ef99..3f94e454ef99 100644
--- a/drivers/clocksource/tango_xtal.c
+++ b/drivers/clocksource/timer-tango-xtal.c
diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c
index 4293943f4e2b..fdb3d795a409 100644
--- a/drivers/clocksource/timer-tegra20.c
+++ b/drivers/clocksource/timer-tegra20.c
@@ -15,21 +15,24 @@
*
*/
-#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/time.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <linux/clocksource.h>
-#include <linux/clk.h>
-#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/percpu.h>
#include <linux/sched_clock.h>
-#include <linux/delay.h>
+#include <linux/time.h>
+
+#include "timer-of.h"
+#ifdef CONFIG_ARM
#include <asm/mach/time.h>
+#endif
#define RTC_SECONDS 0x08
#define RTC_SHADOW_SECONDS 0x0c
@@ -39,74 +42,161 @@
#define TIMERUS_USEC_CFG 0x14
#define TIMERUS_CNTR_FREEZE 0x4c
-#define TIMER1_BASE 0x0
-#define TIMER2_BASE 0x8
-#define TIMER3_BASE 0x50
-#define TIMER4_BASE 0x58
-
-#define TIMER_PTV 0x0
-#define TIMER_PCR 0x4
-
+#define TIMER_PTV 0x0
+#define TIMER_PTV_EN BIT(31)
+#define TIMER_PTV_PER BIT(30)
+#define TIMER_PCR 0x4
+#define TIMER_PCR_INTR_CLR BIT(30)
+
+#ifdef CONFIG_ARM
+#define TIMER_CPU0 0x50 /* TIMER3 */
+#else
+#define TIMER_CPU0 0x90 /* TIMER10 */
+#define TIMER10_IRQ_IDX 10
+#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu)
+#endif
+#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8)
+
+static u32 usec_config;
static void __iomem *timer_reg_base;
+#ifdef CONFIG_ARM
static void __iomem *rtc_base;
-
static struct timespec64 persistent_ts;
static u64 persistent_ms, last_persistent_ms;
-
static struct delay_timer tegra_delay_timer;
-
-#define timer_writel(value, reg) \
- writel_relaxed(value, timer_reg_base + (reg))
-#define timer_readl(reg) \
- readl_relaxed(timer_reg_base + (reg))
+#endif
static int tegra_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- u32 reg;
+ void __iomem *reg_base = timer_of_base(to_timer_of(evt));
- reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0);
- timer_writel(reg, TIMER3_BASE + TIMER_PTV);
+ writel(TIMER_PTV_EN |
+ ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */
+ reg_base + TIMER_PTV);
return 0;
}
-static inline void timer_shutdown(struct clock_event_device *evt)
+static int tegra_timer_shutdown(struct clock_event_device *evt)
{
- timer_writel(0, TIMER3_BASE + TIMER_PTV);
+ void __iomem *reg_base = timer_of_base(to_timer_of(evt));
+
+ writel(0, reg_base + TIMER_PTV);
+
+ return 0;
}
-static int tegra_timer_shutdown(struct clock_event_device *evt)
+static int tegra_timer_set_periodic(struct clock_event_device *evt)
{
- timer_shutdown(evt);
+ void __iomem *reg_base = timer_of_base(to_timer_of(evt));
+
+ writel(TIMER_PTV_EN | TIMER_PTV_PER |
+ ((timer_of_rate(to_timer_of(evt)) / HZ) - 1),
+ reg_base + TIMER_PTV);
+
return 0;
}
-static int tegra_timer_set_periodic(struct clock_event_device *evt)
+static irqreturn_t tegra_timer_isr(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+ void __iomem *reg_base = timer_of_base(to_timer_of(evt));
+
+ writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR);
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static void tegra_timer_suspend(struct clock_event_device *evt)
+{
+ void __iomem *reg_base = timer_of_base(to_timer_of(evt));
+
+ writel(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR);
+}
+
+static void tegra_timer_resume(struct clock_event_device *evt)
+{
+ writel(usec_config, timer_reg_base + TIMERUS_USEC_CFG);
+}
+
+#ifdef CONFIG_ARM64
+static DEFINE_PER_CPU(struct timer_of, tegra_to) = {
+ .flags = TIMER_OF_CLOCK | TIMER_OF_BASE,
+
+ .clkevt = {
+ .name = "tegra_timer",
+ .rating = 460,
+ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+ .set_next_event = tegra_timer_set_next_event,
+ .set_state_shutdown = tegra_timer_shutdown,
+ .set_state_periodic = tegra_timer_set_periodic,
+ .set_state_oneshot = tegra_timer_shutdown,
+ .tick_resume = tegra_timer_shutdown,
+ .suspend = tegra_timer_suspend,
+ .resume = tegra_timer_resume,
+ },
+};
+
+static int tegra_timer_setup(unsigned int cpu)
{
- u32 reg = 0xC0000000 | ((1000000 / HZ) - 1);
+ struct timer_of *to = per_cpu_ptr(&tegra_to, cpu);
+
+ irq_force_affinity(to->clkevt.irq, cpumask_of(cpu));
+ enable_irq(to->clkevt.irq);
+
+ clockevents_config_and_register(&to->clkevt, timer_of_rate(to),
+ 1, /* min */
+ 0x1fffffff); /* 29 bits */
- timer_shutdown(evt);
- timer_writel(reg, TIMER3_BASE + TIMER_PTV);
return 0;
}
-static struct clock_event_device tegra_clockevent = {
- .name = "timer0",
- .rating = 300,
- .features = CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_DYNIRQ,
- .set_next_event = tegra_timer_set_next_event,
- .set_state_shutdown = tegra_timer_shutdown,
- .set_state_periodic = tegra_timer_set_periodic,
- .set_state_oneshot = tegra_timer_shutdown,
- .tick_resume = tegra_timer_shutdown,
+static int tegra_timer_stop(unsigned int cpu)
+{
+ struct timer_of *to = per_cpu_ptr(&tegra_to, cpu);
+
+ to->clkevt.set_state_shutdown(&to->clkevt);
+ disable_irq_nosync(to->clkevt.irq);
+
+ return 0;
+}
+#else /* CONFIG_ARM */
+static struct timer_of tegra_to = {
+ .flags = TIMER_OF_CLOCK | TIMER_OF_BASE | TIMER_OF_IRQ,
+
+ .clkevt = {
+ .name = "tegra_timer",
+ .rating = 300,
+ .features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_DYNIRQ,
+ .set_next_event = tegra_timer_set_next_event,
+ .set_state_shutdown = tegra_timer_shutdown,
+ .set_state_periodic = tegra_timer_set_periodic,
+ .set_state_oneshot = tegra_timer_shutdown,
+ .tick_resume = tegra_timer_shutdown,
+ .suspend = tegra_timer_suspend,
+ .resume = tegra_timer_resume,
+ .cpumask = cpu_possible_mask,
+ },
+
+ .of_irq = {
+ .index = 2,
+ .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH,
+ .handler = tegra_timer_isr,
+ },
};
static u64 notrace tegra_read_sched_clock(void)
{
- return timer_readl(TIMERUS_CNTR_1US);
+ return readl(timer_reg_base + TIMERUS_CNTR_1US);
+}
+
+static unsigned long tegra_delay_timer_read_counter_long(void)
+{
+ return readl(timer_reg_base + TIMERUS_CNTR_1US);
}
/*
@@ -143,100 +233,155 @@ static void tegra_read_persistent_clock64(struct timespec64 *ts)
timespec64_add_ns(&persistent_ts, delta * NSEC_PER_MSEC);
*ts = persistent_ts;
}
+#endif
-static unsigned long tegra_delay_timer_read_counter_long(void)
-{
- return readl(timer_reg_base + TIMERUS_CNTR_1US);
-}
-
-static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = (struct clock_event_device *)dev_id;
- timer_writel(1<<30, TIMER3_BASE + TIMER_PCR);
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static struct irqaction tegra_timer_irq = {
- .name = "timer0",
- .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH,
- .handler = tegra_timer_interrupt,
- .dev_id = &tegra_clockevent,
-};
-
-static int __init tegra20_init_timer(struct device_node *np)
+static int tegra_timer_common_init(struct device_node *np, struct timer_of *to)
{
- struct clk *clk;
- unsigned long rate;
- int ret;
-
- timer_reg_base = of_iomap(np, 0);
- if (!timer_reg_base) {
- pr_err("Can't map timer registers\n");
- return -ENXIO;
- }
+ int ret = 0;
- tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
- if (tegra_timer_irq.irq <= 0) {
- pr_err("Failed to map timer IRQ\n");
- return -EINVAL;
- }
+ ret = timer_of_init(np, to);
+ if (ret < 0)
+ goto out;
- clk = of_clk_get(np, 0);
- if (IS_ERR(clk)) {
- pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
- rate = 12000000;
- } else {
- clk_prepare_enable(clk);
- rate = clk_get_rate(clk);
- }
+ timer_reg_base = timer_of_base(to);
- switch (rate) {
+ /*
+ * Configure microsecond timers to have 1MHz clock
+ * Config register is 0xqqww, where qq is "dividend", ww is "divisor"
+ * Uses n+1 scheme
+ */
+ switch (timer_of_rate(to)) {
case 12000000:
- timer_writel(0x000b, TIMERUS_USEC_CFG);
+ usec_config = 0x000b; /* (11+1)/(0+1) */
+ break;
+ case 12800000:
+ usec_config = 0x043f; /* (63+1)/(4+1) */
break;
case 13000000:
- timer_writel(0x000c, TIMERUS_USEC_CFG);
+ usec_config = 0x000c; /* (12+1)/(0+1) */
+ break;
+ case 16800000:
+ usec_config = 0x0453; /* (83+1)/(4+1) */
break;
case 19200000:
- timer_writel(0x045f, TIMERUS_USEC_CFG);
+ usec_config = 0x045f; /* (95+1)/(4+1) */
break;
case 26000000:
- timer_writel(0x0019, TIMERUS_USEC_CFG);
+ usec_config = 0x0019; /* (25+1)/(0+1) */
+ break;
+ case 38400000:
+ usec_config = 0x04bf; /* (191+1)/(4+1) */
+ break;
+ case 48000000:
+ usec_config = 0x002f; /* (47+1)/(0+1) */
break;
default:
- WARN(1, "Unknown clock rate");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ writel(usec_config, timer_of_base(to) + TIMERUS_USEC_CFG);
+
+out:
+ return ret;
+}
+
+#ifdef CONFIG_ARM64
+static int __init tegra_init_timer(struct device_node *np)
+{
+ int cpu, ret = 0;
+ struct timer_of *to;
+
+ to = this_cpu_ptr(&tegra_to);
+ ret = tegra_timer_common_init(np, to);
+ if (ret < 0)
+ goto out;
+
+ for_each_possible_cpu(cpu) {
+ struct timer_of *cpu_to;
+
+ cpu_to = per_cpu_ptr(&tegra_to, cpu);
+ cpu_to->of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(cpu);
+ cpu_to->of_clk.rate = timer_of_rate(to);
+ cpu_to->clkevt.cpumask = cpumask_of(cpu);
+ cpu_to->clkevt.irq =
+ irq_of_parse_and_map(np, IRQ_IDX_FOR_CPU(cpu));
+ if (!cpu_to->clkevt.irq) {
+ pr_err("%s: can't map IRQ for CPU%d\n",
+ __func__, cpu);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ irq_set_status_flags(cpu_to->clkevt.irq, IRQ_NOAUTOEN);
+ ret = request_irq(cpu_to->clkevt.irq, tegra_timer_isr,
+ IRQF_TIMER | IRQF_NOBALANCING,
+ cpu_to->clkevt.name, &cpu_to->clkevt);
+ if (ret) {
+ pr_err("%s: cannot setup irq %d for CPU%d\n",
+ __func__, cpu_to->clkevt.irq, cpu);
+ ret = -EINVAL;
+ goto out_irq;
+ }
+ }
+
+ cpuhp_setup_state(CPUHP_AP_TEGRA_TIMER_STARTING,
+ "AP_TEGRA_TIMER_STARTING", tegra_timer_setup,
+ tegra_timer_stop);
+
+ return ret;
+out_irq:
+ for_each_possible_cpu(cpu) {
+ struct timer_of *cpu_to;
+
+ cpu_to = per_cpu_ptr(&tegra_to, cpu);
+ if (cpu_to->clkevt.irq) {
+ free_irq(cpu_to->clkevt.irq, &cpu_to->clkevt);
+ irq_dispose_mapping(cpu_to->clkevt.irq);
+ }
}
+out:
+ timer_of_cleanup(to);
+ return ret;
+}
+#else /* CONFIG_ARM */
+static int __init tegra_init_timer(struct device_node *np)
+{
+ int ret = 0;
+
+ ret = tegra_timer_common_init(np, &tegra_to);
+ if (ret < 0)
+ goto out;
- sched_clock_register(tegra_read_sched_clock, 32, 1000000);
+ tegra_to.of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(0);
+ tegra_to.of_clk.rate = 1000000; /* microsecond timer */
+ sched_clock_register(tegra_read_sched_clock, 32,
+ timer_of_rate(&tegra_to));
ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
- "timer_us", 1000000, 300, 32,
- clocksource_mmio_readl_up);
+ "timer_us", timer_of_rate(&tegra_to),
+ 300, 32, clocksource_mmio_readl_up);
if (ret) {
pr_err("Failed to register clocksource\n");
- return ret;
+ goto out;
}
tegra_delay_timer.read_current_timer =
tegra_delay_timer_read_counter_long;
- tegra_delay_timer.freq = 1000000;
+ tegra_delay_timer.freq = timer_of_rate(&tegra_to);
register_current_timer_delay(&tegra_delay_timer);
- ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
- if (ret) {
- pr_err("Failed to register timer IRQ: %d\n", ret);
- return ret;
- }
+ clockevents_config_and_register(&tegra_to.clkevt,
+ timer_of_rate(&tegra_to),
+ 0x1,
+ 0x1fffffff);
- tegra_clockevent.cpumask = cpu_possible_mask;
- tegra_clockevent.irq = tegra_timer_irq.irq;
- clockevents_config_and_register(&tegra_clockevent, 1000000,
- 0x1, 0x1fffffff);
+ return ret;
+out:
+ timer_of_cleanup(&tegra_to);
- return 0;
+ return ret;
}
-TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
static int __init tegra20_init_rtc(struct device_node *np)
{
@@ -261,3 +406,6 @@ static int __init tegra20_init_rtc(struct device_node *np)
return register_persistent_clock(tegra_read_persistent_clock64);
}
TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
+#endif
+TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra_init_timer);
+TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra_init_timer);
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index 595124074821..c364027638e1 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -154,6 +154,10 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
if (IS_ERR(parent))
return -ENODEV;
+ /* Bail out if both clocks point to fck */
+ if (clk_is_match(parent, timer->fclk))
+ return 0;
+
ret = clk_set_parent(timer->fclk, parent);
if (ret < 0)
pr_err("%s: failed to set parent\n", __func__);
@@ -864,7 +868,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
timer->pdev = pdev;
pm_runtime_enable(dev);
- pm_runtime_irq_safe(dev);
if (!timer->reserved) {
ret = pm_runtime_get_sync(dev);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 608af20a3494..b22e6bba71f1 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -207,8 +207,6 @@ comment "CPU frequency scaling drivers"
config CPUFREQ_DT
tristate "Generic DT based cpufreq driver"
depends on HAVE_CLK && OF
- # if CPU_THERMAL is on and THERMAL=m, CPUFREQ_DT cannot be =y:
- depends on !CPU_THERMAL || THERMAL
select CPUFREQ_DT_PLATDEV
select PM_OPP
help
@@ -327,7 +325,6 @@ endif
config QORIQ_CPUFREQ
tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64)
- depends on !CPU_THERMAL || THERMAL
select CLK_QORIQ
help
This adds the CPUFreq driver support for Freescale QorIQ SoCs
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 688f10227793..179a1d302f48 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -25,12 +25,21 @@ config ARM_ARMADA_37XX_CPUFREQ
This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
The Armada 37xx PMU supports 4 frequency and VDD levels.
+config ARM_ARMADA_8K_CPUFREQ
+ tristate "Armada 8K CPUFreq driver"
+ depends on ARCH_MVEBU && CPUFREQ_DT
+ help
+ This enables the CPUFreq driver support for Marvell
+ Armada8k SOCs.
+ Armada8K device has the AP806 which supports scaling
+ to any full integer divider.
+
+ If in doubt, say N.
+
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM_CPU_TOPOLOGY && HAVE_CLK
- # if CPU_THERMAL is on and THERMAL=m, ARM_BIT_LITTLE_CPUFREQ cannot be =y
- depends on !CPU_THERMAL || THERMAL
select PM_OPP
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
@@ -38,7 +47,6 @@ config ARM_BIG_LITTLE_CPUFREQ
config ARM_SCPI_CPUFREQ
tristate "SCPI based CPUfreq driver"
depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
- depends on !CPU_THERMAL || THERMAL
help
This adds the CPUfreq driver support for ARM platforms using SCPI
protocol for CPU power management.
@@ -93,7 +101,6 @@ config ARM_KIRKWOOD_CPUFREQ
config ARM_MEDIATEK_CPUFREQ
tristate "CPU Frequency scaling support for MediaTek SoCs"
depends on ARCH_MEDIATEK && REGULATOR
- depends on !CPU_THERMAL || THERMAL
select PM_OPP
help
This adds the CPUFreq driver support for MediaTek SoCs.
@@ -233,7 +240,6 @@ config ARM_SA1110_CPUFREQ
config ARM_SCMI_CPUFREQ
tristate "SCMI based CPUfreq driver"
depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
- depends on !CPU_THERMAL || THERMAL
select PM_OPP
help
This adds the CPUfreq driver support for ARM platforms using SCMI
@@ -272,8 +278,8 @@ config ARM_TEGRA20_CPUFREQ
This adds the CPUFreq driver support for Tegra20 SOCs.
config ARM_TEGRA124_CPUFREQ
- tristate "Tegra124 CPUFreq support"
- depends on ARCH_TEGRA && CPUFREQ_DT && REGULATOR
+ bool "Tegra124 CPUFreq support"
+ depends on ARCH_TEGRA && CPUFREQ_DT
default y
help
This adds the CPUFreq driver support for Tegra124 SOCs.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 08c071be2491..689b26c6f949 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o
obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
+obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index d62fd374d5c7..c72258a44ba4 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -916,8 +916,10 @@ static void __init acpi_cpufreq_boost_init(void)
{
int ret;
- if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)))
+ if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA))) {
+ pr_debug("Boost capabilities not present in the processor\n");
return;
+ }
acpi_cpufreq_driver.set_boost = set_boost;
acpi_cpufreq_driver.boost_enabled = boost_state(0);
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index cf62a1f64dd7..7fe52fcddcf1 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -487,6 +487,8 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency =
arm_bL_ops->get_transition_latency(cpu_dev);
+ dev_pm_opp_of_register_em(policy->cpus);
+
if (is_bL_switching_enabled())
per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c
new file mode 100644
index 000000000000..b3f4bd647e9b
--- /dev/null
+++ b/drivers/cpufreq/armada-8k-cpufreq.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPUFreq support for Armada 8K
+ *
+ * Copyright (C) 2018 Marvell
+ *
+ * Omri Itach <omrii@marvell.com>
+ * Gregory Clement <gregory.clement@bootlin.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+
+/*
+ * Setup the opps list with the divider for the max frequency, that
+ * will be filled at runtime.
+ */
+static const int opps_div[] __initconst = {1, 2, 3, 4};
+
+static struct platform_device *armada_8k_pdev;
+
+struct freq_table {
+ struct device *cpu_dev;
+ unsigned int freq[ARRAY_SIZE(opps_div)];
+};
+
+/* If the CPUs share the same clock, then they are in the same cluster. */
+static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk,
+ struct cpumask *cpumask)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct device *cpu_dev;
+ struct clk *clk;
+
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev) {
+ pr_warn("Failed to get cpu%d device\n", cpu);
+ continue;
+ }
+
+ clk = clk_get(cpu_dev, 0);
+ if (IS_ERR(clk)) {
+ pr_warn("Cannot get clock for CPU %d\n", cpu);
+ } else {
+ if (clk_is_match(clk, cur_clk))
+ cpumask_set_cpu(cpu, cpumask);
+
+ clk_put(clk);
+ }
+ }
+}
+
+static int __init armada_8k_add_opp(struct clk *clk, struct device *cpu_dev,
+ struct freq_table *freq_tables,
+ int opps_index)
+{
+ unsigned int cur_frequency;
+ unsigned int freq;
+ int i, ret;
+
+ /* Get nominal (current) CPU frequency. */
+ cur_frequency = clk_get_rate(clk);
+ if (!cur_frequency) {
+ dev_err(cpu_dev, "Failed to get clock rate for this CPU\n");
+ return -EINVAL;
+ }
+
+ freq_tables[opps_index].cpu_dev = cpu_dev;
+
+ for (i = 0; i < ARRAY_SIZE(opps_div); i++) {
+ freq = cur_frequency / opps_div[i];
+
+ ret = dev_pm_opp_add(cpu_dev, freq, 0);
+ if (ret)
+ return ret;
+
+ freq_tables[opps_index].freq[i] = freq;
+ }
+
+ return 0;
+}
+
+static void armada_8k_cpufreq_free_table(struct freq_table *freq_tables)
+{
+ int opps_index, nb_cpus = num_possible_cpus();
+
+ for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) {
+ int i;
+
+ /* If cpu_dev is NULL then we reached the end of the array */
+ if (!freq_tables[opps_index].cpu_dev)
+ break;
+
+ for (i = 0; i < ARRAY_SIZE(opps_div); i++) {
+ /*
+ * A 0Hz frequency is not valid, this meant
+ * that it was not yet initialized so there is
+ * no more opp to free
+ */
+ if (freq_tables[opps_index].freq[i] == 0)
+ break;
+
+ dev_pm_opp_remove(freq_tables[opps_index].cpu_dev,
+ freq_tables[opps_index].freq[i]);
+ }
+ }
+
+ kfree(freq_tables);
+}
+
+static int __init armada_8k_cpufreq_init(void)
+{
+ int ret = 0, opps_index = 0, cpu, nb_cpus;
+ struct freq_table *freq_tables;
+ struct device_node *node;
+ struct cpumask cpus;
+
+ node = of_find_compatible_node(NULL, NULL, "marvell,ap806-cpu-clock");
+ if (!node || !of_device_is_available(node)) {
+ of_node_put(node);
+ return -ENODEV;
+ }
+
+ nb_cpus = num_possible_cpus();
+ freq_tables = kcalloc(nb_cpus, sizeof(*freq_tables), GFP_KERNEL);
+ cpumask_copy(&cpus, cpu_possible_mask);
+
+ /*
+ * For each CPU, this loop registers the operating points
+ * supported (which are the nominal CPU frequency and full integer
+ * divisions of it).
+ */
+ for_each_cpu(cpu, &cpus) {
+ struct cpumask shared_cpus;
+ struct device *cpu_dev;
+ struct clk *clk;
+
+ cpu_dev = get_cpu_device(cpu);
+
+ if (!cpu_dev) {
+ pr_err("Cannot get CPU %d\n", cpu);
+ continue;
+ }
+
+ clk = clk_get(cpu_dev, 0);
+
+ if (IS_ERR(clk)) {
+ pr_err("Cannot get clock for CPU %d\n", cpu);
+ ret = PTR_ERR(clk);
+ goto remove_opp;
+ }
+
+ ret = armada_8k_add_opp(clk, cpu_dev, freq_tables, opps_index);
+ if (ret) {
+ clk_put(clk);
+ goto remove_opp;
+ }
+
+ opps_index++;
+ cpumask_clear(&shared_cpus);
+ armada_8k_get_sharing_cpus(clk, &shared_cpus);
+ dev_pm_opp_set_sharing_cpus(cpu_dev, &shared_cpus);
+ cpumask_andnot(&cpus, &cpus, &shared_cpus);
+ clk_put(clk);
+ }
+
+ armada_8k_pdev = platform_device_register_simple("cpufreq-dt", -1,
+ NULL, 0);
+ ret = PTR_ERR_OR_ZERO(armada_8k_pdev);
+ if (ret)
+ goto remove_opp;
+
+ platform_set_drvdata(armada_8k_pdev, freq_tables);
+
+ return 0;
+
+remove_opp:
+ armada_8k_cpufreq_free_table(freq_tables);
+ return ret;
+}
+module_init(armada_8k_cpufreq_init);
+
+static void __exit armada_8k_cpufreq_exit(void)
+{
+ struct freq_table *freq_tables = platform_get_drvdata(armada_8k_pdev);
+
+ platform_device_unregister(armada_8k_pdev);
+ armada_8k_cpufreq_free_table(freq_tables);
+}
+module_exit(armada_8k_cpufreq_exit);
+
+MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>");
+MODULE_DESCRIPTION("Armada 8K cpufreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index fd25c21cee72..2ae978d27e61 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -42,6 +42,66 @@
*/
static struct cppc_cpudata **all_cpu_data;
+struct cppc_workaround_oem_info {
+ char oem_id[ACPI_OEM_ID_SIZE +1];
+ char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
+ u32 oem_revision;
+};
+
+static bool apply_hisi_workaround;
+
+static struct cppc_workaround_oem_info wa_info[] = {
+ {
+ .oem_id = "HISI ",
+ .oem_table_id = "HIP07 ",
+ .oem_revision = 0,
+ }, {
+ .oem_id = "HISI ",
+ .oem_table_id = "HIP08 ",
+ .oem_revision = 0,
+ }
+};
+
+static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu,
+ unsigned int perf);
+
+/*
+ * HISI platform does not support delivered performance counter and
+ * reference performance counter. It can calculate the performance using the
+ * platform specific mechanism. We reuse the desired performance register to
+ * store the real performance calculated by the platform.
+ */
+static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpunum)
+{
+ struct cppc_cpudata *cpudata = all_cpu_data[cpunum];
+ u64 desired_perf;
+ int ret;
+
+ ret = cppc_get_desired_perf(cpunum, &desired_perf);
+ if (ret < 0)
+ return -EIO;
+
+ return cppc_cpufreq_perf_to_khz(cpudata, desired_perf);
+}
+
+static void cppc_check_hisi_workaround(void)
+{
+ struct acpi_table_header *tbl;
+ acpi_status status = AE_OK;
+ int i;
+
+ status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl);
+ if (ACPI_FAILURE(status) || !tbl)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(wa_info); i++) {
+ if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
+ !memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
+ wa_info[i].oem_revision == tbl->oem_revision)
+ apply_hisi_workaround = true;
+ }
+}
+
/* Callback function used to retrieve the max frequency from DMI */
static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
{
@@ -334,6 +394,9 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum)
struct cppc_cpudata *cpu = all_cpu_data[cpunum];
int ret;
+ if (apply_hisi_workaround)
+ return hisi_cppc_cpufreq_get_rate(cpunum);
+
ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0);
if (ret)
return ret;
@@ -386,6 +449,8 @@ static int __init cppc_cpufreq_init(void)
goto out;
}
+ cppc_check_hisi_workaround();
+
ret = cpufreq_register_driver(&cppc_cpufreq_driver);
if (ret)
goto out;
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index b1c5468dca16..47729a22c159 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -119,6 +119,7 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "mediatek,mt8176", },
{ .compatible = "nvidia,tegra124", },
+ { .compatible = "nvidia,tegra210", },
{ .compatible = "qcom,apq8096", },
{ .compatible = "qcom,msm8996", },
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index e58bfcb1169e..bde28878725b 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -13,7 +13,6 @@
#include <linux/clk.h>
#include <linux/cpu.h>
-#include <linux/cpu_cooling.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/err.h>
@@ -30,7 +29,6 @@
struct private_data {
struct opp_table *opp_table;
struct device *cpu_dev;
- struct thermal_cooling_device *cdev;
const char *reg_name;
bool have_static_opps;
};
@@ -280,6 +278,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = transition_latency;
policy->dvfs_possible_from_any_cpu = true;
+ dev_pm_opp_of_register_em(policy->cpus);
+
return 0;
out_free_cpufreq_table:
@@ -297,11 +297,25 @@ out_put_clk:
return ret;
}
+static int cpufreq_online(struct cpufreq_policy *policy)
+{
+ /* We did light-weight tear down earlier, nothing to do here */
+ return 0;
+}
+
+static int cpufreq_offline(struct cpufreq_policy *policy)
+{
+ /*
+ * Preserve policy->driver_data and don't free resources on light-weight
+ * tear down.
+ */
+ return 0;
+}
+
static int cpufreq_exit(struct cpufreq_policy *policy)
{
struct private_data *priv = policy->driver_data;
- cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
if (priv->have_static_opps)
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
@@ -314,21 +328,16 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
return 0;
}
-static void cpufreq_ready(struct cpufreq_policy *policy)
-{
- struct private_data *priv = policy->driver_data;
-
- priv->cdev = of_cpufreq_cooling_register(policy);
-}
-
static struct cpufreq_driver dt_cpufreq_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = set_target,
.get = cpufreq_generic_get,
.init = cpufreq_init,
.exit = cpufreq_exit,
- .ready = cpufreq_ready,
+ .online = cpufreq_online,
+ .offline = cpufreq_offline,
.name = "cpufreq-dt",
.attr = cpufreq_dt_attr,
.suspend = cpufreq_generic_suspend,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6f23ebb395f1..0e626b00053b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -19,6 +19,7 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
+#include <linux/cpu_cooling.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
@@ -545,13 +546,13 @@ EXPORT_SYMBOL_GPL(cpufreq_policy_transition_delay_us);
* SYSFS INTERFACE *
*********************************************************************/
static ssize_t show_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
}
-static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
+static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
{
int ret, enable;
@@ -1200,28 +1201,39 @@ static int cpufreq_online(unsigned int cpu)
return -ENOMEM;
}
- cpumask_copy(policy->cpus, cpumask_of(cpu));
+ if (!new_policy && cpufreq_driver->online) {
+ ret = cpufreq_driver->online(policy);
+ if (ret) {
+ pr_debug("%s: %d: initialization failed\n", __func__,
+ __LINE__);
+ goto out_exit_policy;
+ }
- /* call driver. From then on the cpufreq must be able
- * to accept all calls to ->verify and ->setpolicy for this CPU
- */
- ret = cpufreq_driver->init(policy);
- if (ret) {
- pr_debug("initialization failed\n");
- goto out_free_policy;
- }
+ /* Recover policy->cpus using related_cpus */
+ cpumask_copy(policy->cpus, policy->related_cpus);
+ } else {
+ cpumask_copy(policy->cpus, cpumask_of(cpu));
- ret = cpufreq_table_validate_and_sort(policy);
- if (ret)
- goto out_exit_policy;
+ /*
+ * Call driver. From then on the cpufreq must be able
+ * to accept all calls to ->verify and ->setpolicy for this CPU.
+ */
+ ret = cpufreq_driver->init(policy);
+ if (ret) {
+ pr_debug("%s: %d: initialization failed\n", __func__,
+ __LINE__);
+ goto out_free_policy;
+ }
- down_write(&policy->rwsem);
+ ret = cpufreq_table_validate_and_sort(policy);
+ if (ret)
+ goto out_exit_policy;
- if (new_policy) {
/* related_cpus should at least include policy->cpus. */
cpumask_copy(policy->related_cpus, policy->cpus);
}
+ down_write(&policy->rwsem);
/*
* affected cpus must always be the one, which are online. We aren't
* managing offline cpus here.
@@ -1305,8 +1317,6 @@ static int cpufreq_online(unsigned int cpu)
if (ret) {
pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n",
__func__, cpu, ret);
- /* cpufreq_policy_free() will notify based on this */
- new_policy = false;
goto out_destroy_policy;
}
@@ -1318,6 +1328,10 @@ static int cpufreq_online(unsigned int cpu)
if (cpufreq_driver->ready)
cpufreq_driver->ready(policy);
+ if (IS_ENABLED(CONFIG_CPU_THERMAL) &&
+ cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV)
+ policy->cdev = of_cpufreq_cooling_register(policy);
+
pr_debug("initialization complete\n");
return 0;
@@ -1405,6 +1419,12 @@ static int cpufreq_offline(unsigned int cpu)
goto unlock;
}
+ if (IS_ENABLED(CONFIG_CPU_THERMAL) &&
+ cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) {
+ cpufreq_cooling_unregister(policy->cdev);
+ policy->cdev = NULL;
+ }
+
if (cpufreq_driver->stop_cpu)
cpufreq_driver->stop_cpu(policy);
@@ -1412,11 +1432,12 @@ static int cpufreq_offline(unsigned int cpu)
cpufreq_exit_governor(policy);
/*
- * Perform the ->exit() even during light-weight tear-down,
- * since this is a core component, and is essential for the
- * subsequent light-weight ->init() to succeed.
+ * Perform the ->offline() during light-weight tear-down, as
+ * that allows fast recovery when the CPU comes back.
*/
- if (cpufreq_driver->exit) {
+ if (cpufreq_driver->offline) {
+ cpufreq_driver->offline(policy);
+ } else if (cpufreq_driver->exit) {
cpufreq_driver->exit(policy);
policy->freq_table = NULL;
}
@@ -1445,8 +1466,13 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
cpumask_clear_cpu(cpu, policy->real_cpus);
remove_cpu_dev_symlink(policy, dev);
- if (cpumask_empty(policy->real_cpus))
+ if (cpumask_empty(policy->real_cpus)) {
+ /* We did light-weight exit earlier, do full tear down now */
+ if (cpufreq_driver->offline)
+ cpufreq_driver->exit(policy);
+
cpufreq_policy_free(policy);
+ }
}
/**
@@ -1530,17 +1556,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
{
unsigned int ret_freq = 0;
- if (!cpufreq_driver->get)
+ if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
return ret_freq;
ret_freq = cpufreq_driver->get(policy->cpu);
/*
- * Updating inactive policies is invalid, so avoid doing that. Also
- * if fast frequency switching is used with the given policy, the check
+ * If fast frequency switching is used with the given policy, the check
* against policy->cur is pointless, so skip it in that case too.
*/
- if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
+ if (policy->fast_switch_enabled)
return ret_freq;
if (ret_freq && policy->cur &&
@@ -1569,10 +1594,7 @@ unsigned int cpufreq_get(unsigned int cpu)
if (policy) {
down_read(&policy->rwsem);
-
- if (!policy_is_inactive(policy))
- ret_freq = __cpufreq_get(policy);
-
+ ret_freq = __cpufreq_get(policy);
up_read(&policy->rwsem);
cpufreq_cpu_put(policy);
@@ -2196,12 +2218,25 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_get_policy);
-/*
- * policy : current policy.
- * new_policy: policy to be set.
+/**
+ * cpufreq_set_policy - Modify cpufreq policy parameters.
+ * @policy: Policy object to modify.
+ * @new_policy: New policy data.
+ *
+ * Pass @new_policy to the cpufreq driver's ->verify() callback, run the
+ * installed policy notifiers for it with the CPUFREQ_ADJUST value, pass it to
+ * the driver's ->verify() callback again and run the notifiers for it again
+ * with the CPUFREQ_NOTIFY value. Next, copy the min and max parameters
+ * of @new_policy to @policy and either invoke the driver's ->setpolicy()
+ * callback (if present) or carry out a governor update for @policy. That is,
+ * run the current governor's ->limits() callback (if the governor field in
+ * @new_policy points to the same object as the one in @policy) or replace the
+ * governor for @policy with the new one stored in @new_policy.
+ *
+ * The cpuinfo part of @policy is not updated by this function.
*/
static int cpufreq_set_policy(struct cpufreq_policy *policy,
- struct cpufreq_policy *new_policy)
+ struct cpufreq_policy *new_policy)
{
struct cpufreq_governor *old_gov;
int ret;
@@ -2251,11 +2286,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
if (cpufreq_driver->setpolicy) {
policy->policy = new_policy->policy;
pr_debug("setting range\n");
- return cpufreq_driver->setpolicy(new_policy);
+ return cpufreq_driver->setpolicy(policy);
}
if (new_policy->governor == policy->governor) {
- pr_debug("cpufreq: governor limits update\n");
+ pr_debug("governor limits update\n");
cpufreq_governor_limits(policy);
return 0;
}
@@ -2276,7 +2311,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
if (!ret) {
ret = cpufreq_start_governor(policy);
if (!ret) {
- pr_debug("cpufreq: governor change\n");
+ pr_debug("governor change\n");
sched_cpufreq_governor_change(policy, old_gov);
return 0;
}
@@ -2297,11 +2332,14 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
}
/**
- * cpufreq_update_policy - re-evaluate an existing cpufreq policy
- * @cpu: CPU which shall be re-evaluated
+ * cpufreq_update_policy - Re-evaluate an existing cpufreq policy.
+ * @cpu: CPU to re-evaluate the policy for.
*
- * Useful for policy notifiers which have different necessities
- * at different times.
+ * Update the current frequency for the cpufreq policy of @cpu and use
+ * cpufreq_set_policy() to re-apply the min and max limits saved in the
+ * user_policy sub-structure of that policy, which triggers the evaluation
+ * of policy notifiers and the cpufreq driver's ->verify() callback for the
+ * policy in question, among other things.
*/
void cpufreq_update_policy(unsigned int cpu)
{
@@ -2316,23 +2354,18 @@ void cpufreq_update_policy(unsigned int cpu)
if (policy_is_inactive(policy))
goto unlock;
- pr_debug("updating policy for CPU %u\n", cpu);
- memcpy(&new_policy, policy, sizeof(*policy));
- new_policy.min = policy->user_policy.min;
- new_policy.max = policy->user_policy.max;
-
/*
* BIOS might change freq behind our back
* -> ask driver for current freq and notify governors about a change
*/
- if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
- if (cpufreq_suspended)
- goto unlock;
+ if (cpufreq_driver->get && !cpufreq_driver->setpolicy &&
+ (cpufreq_suspended || WARN_ON(!cpufreq_update_current_freq(policy))))
+ goto unlock;
- new_policy.cur = cpufreq_update_current_freq(policy);
- if (WARN_ON(!new_policy.cur))
- goto unlock;
- }
+ pr_debug("updating policy for CPU %u\n", cpu);
+ memcpy(&new_policy, policy, sizeof(*policy));
+ new_policy.min = policy->user_policy.min;
+ new_policy.max = policy->user_policy.max;
cpufreq_set_policy(policy, &new_policy);
@@ -2483,7 +2516,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
driver_data->target) ||
(driver_data->setpolicy && (driver_data->target_index ||
driver_data->target)) ||
- (!!driver_data->get_intermediate != !!driver_data->target_intermediate))
+ (!driver_data->get_intermediate != !driver_data->target_intermediate) ||
+ (!driver_data->online != !driver_data->offline))
return -EINVAL;
pr_debug("trying to register driver %s\n", driver_data->name);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 1572129844a5..e2db5581489a 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -31,26 +31,27 @@ static void cpufreq_stats_update(struct cpufreq_stats *stats)
{
unsigned long long cur_time = get_jiffies_64();
- spin_lock(&cpufreq_stats_lock);
stats->time_in_state[stats->last_index] += cur_time - stats->last_time;
stats->last_time = cur_time;
- spin_unlock(&cpufreq_stats_lock);
}
static void cpufreq_stats_clear_table(struct cpufreq_stats *stats)
{
unsigned int count = stats->max_state;
+ spin_lock(&cpufreq_stats_lock);
memset(stats->time_in_state, 0, count * sizeof(u64));
memset(stats->trans_table, 0, count * count * sizeof(int));
stats->last_time = get_jiffies_64();
stats->total_trans = 0;
+ spin_unlock(&cpufreq_stats_lock);
}
static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
{
return sprintf(buf, "%d\n", policy->stats->total_trans);
}
+cpufreq_freq_attr_ro(total_trans);
static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
{
@@ -61,7 +62,10 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
if (policy->fast_switch_enabled)
return 0;
+ spin_lock(&cpufreq_stats_lock);
cpufreq_stats_update(stats);
+ spin_unlock(&cpufreq_stats_lock);
+
for (i = 0; i < stats->state_num; i++) {
len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i],
(unsigned long long)
@@ -69,6 +73,7 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
}
return len;
}
+cpufreq_freq_attr_ro(time_in_state);
static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf,
size_t count)
@@ -77,6 +82,7 @@ static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf,
cpufreq_stats_clear_table(policy->stats);
return count;
}
+cpufreq_freq_attr_wo(reset);
static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
{
@@ -126,10 +132,6 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
}
cpufreq_freq_attr_ro(trans_table);
-cpufreq_freq_attr_ro(total_trans);
-cpufreq_freq_attr_ro(time_in_state);
-cpufreq_freq_attr_wo(reset);
-
static struct attribute *default_attrs[] = {
&total_trans.attr,
&time_in_state.attr,
@@ -240,9 +242,11 @@ void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
if (old_index == -1 || new_index == -1 || old_index == new_index)
return;
+ spin_lock(&cpufreq_stats_lock);
cpufreq_stats_update(stats);
stats->last_index = new_index;
stats->trans_table[old_index * stats->max_state + new_index]++;
stats->total_trans++;
+ spin_unlock(&cpufreq_stats_lock);
}
diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
index d54a27c99121..940fe85db97a 100644
--- a/drivers/cpufreq/davinci-cpufreq.c
+++ b/drivers/cpufreq/davinci-cpufreq.c
@@ -23,13 +23,10 @@
#include <linux/init.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/platform_data/davinci-cpufreq.h>
#include <linux/platform_device.h>
#include <linux/export.h>
-#include <mach/hardware.h>
-#include <mach/cpufreq.h>
-#include <mach/common.h>
-
struct davinci_cpufreq {
struct device *dev;
struct clk *armclk;
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 60bea302abbe..2d3ef208dd70 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -323,9 +323,8 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
states = 2;
/* Allocate private data and frequency table for current cpu */
- centaur = kzalloc(sizeof(*centaur)
- + (states + 1) * sizeof(struct cpufreq_frequency_table),
- GFP_KERNEL);
+ centaur = kzalloc(struct_size(centaur, freq_table, states + 1),
+ GFP_KERNEL);
if (!centaur)
return -ENOMEM;
eps_cpu[0] = centaur;
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 9fedf627e000..a4ff09f91c8f 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -9,7 +9,6 @@
#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
-#include <linux/cpu_cooling.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
@@ -52,7 +51,6 @@ static struct clk_bulk_data clks[] = {
};
static struct device *cpu_dev;
-static struct thermal_cooling_device *cdev;
static bool free_opp;
static struct cpufreq_frequency_table *freq_table;
static unsigned int max_freq;
@@ -193,16 +191,6 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
return 0;
}
-static void imx6q_cpufreq_ready(struct cpufreq_policy *policy)
-{
- cdev = of_cpufreq_cooling_register(policy);
-
- if (!cdev)
- dev_err(cpu_dev,
- "running cpufreq without cooling device: %ld\n",
- PTR_ERR(cdev));
-}
-
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
{
int ret;
@@ -210,26 +198,19 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
policy->clk = clks[ARM].clk;
ret = cpufreq_generic_init(policy, freq_table, transition_latency);
policy->suspend_freq = max_freq;
+ dev_pm_opp_of_register_em(policy->cpus);
return ret;
}
-static int imx6q_cpufreq_exit(struct cpufreq_policy *policy)
-{
- cpufreq_cooling_unregister(cdev);
-
- return 0;
-}
-
static struct cpufreq_driver imx6q_cpufreq_driver = {
- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = imx6q_set_target,
.get = cpufreq_generic_get,
.init = imx6q_cpufreq_init,
- .exit = imx6q_cpufreq_exit,
.name = "imx6q-cpufreq",
- .ready = imx6q_cpufreq_ready,
.attr = cpufreq_generic_attr,
.suspend = cpufreq_generic_suspend,
};
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index dd66decf2087..002f5169d4eb 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -50,6 +50,8 @@
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
#define fp_toint(X) ((X) >> FRAC_BITS)
+#define ONE_EIGHTH_FP ((int64_t)1 << (FRAC_BITS - 3))
+
#define EXT_BITS 6
#define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS)
#define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS)
@@ -895,7 +897,7 @@ static void intel_pstate_update_policies(void)
/************************** sysfs begin ************************/
#define show_one(file_name, object) \
static ssize_t show_##file_name \
- (struct kobject *kobj, struct attribute *attr, char *buf) \
+ (struct kobject *kobj, struct kobj_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%u\n", global.object); \
}
@@ -904,7 +906,7 @@ static ssize_t intel_pstate_show_status(char *buf);
static int intel_pstate_update_status(const char *buf, size_t size);
static ssize_t show_status(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
ssize_t ret;
@@ -915,7 +917,7 @@ static ssize_t show_status(struct kobject *kobj,
return ret;
}
-static ssize_t store_status(struct kobject *a, struct attribute *b,
+static ssize_t store_status(struct kobject *a, struct kobj_attribute *b,
const char *buf, size_t count)
{
char *p = memchr(buf, '\n', count);
@@ -929,7 +931,7 @@ static ssize_t store_status(struct kobject *a, struct attribute *b,
}
static ssize_t show_turbo_pct(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
struct cpudata *cpu;
int total, no_turbo, turbo_pct;
@@ -955,7 +957,7 @@ static ssize_t show_turbo_pct(struct kobject *kobj,
}
static ssize_t show_num_pstates(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
struct cpudata *cpu;
int total;
@@ -976,7 +978,7 @@ static ssize_t show_num_pstates(struct kobject *kobj,
}
static ssize_t show_no_turbo(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
ssize_t ret;
@@ -998,7 +1000,7 @@ static ssize_t show_no_turbo(struct kobject *kobj,
return ret;
}
-static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
+static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
const char *buf, size_t count)
{
unsigned int input;
@@ -1045,7 +1047,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
return count;
}
-static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
+static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b,
const char *buf, size_t count)
{
unsigned int input;
@@ -1075,7 +1077,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
return count;
}
-static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
+static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b,
const char *buf, size_t count)
{
unsigned int input;
@@ -1107,12 +1109,13 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
}
static ssize_t show_hwp_dynamic_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u\n", hwp_boost);
}
-static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute *b,
+static ssize_t store_hwp_dynamic_boost(struct kobject *a,
+ struct kobj_attribute *b,
const char *buf, size_t count)
{
unsigned int input;
@@ -1444,12 +1447,6 @@ static int knl_get_turbo_pstate(void)
return ret;
}
-static int intel_pstate_get_base_pstate(struct cpudata *cpu)
-{
- return global.no_turbo || global.turbo_disabled ?
- cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
-}
-
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
{
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
@@ -1470,11 +1467,9 @@ static void intel_pstate_set_min_pstate(struct cpudata *cpu)
static void intel_pstate_max_within_limits(struct cpudata *cpu)
{
- int pstate;
+ int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
update_turbo_state();
- pstate = intel_pstate_get_base_pstate(cpu);
- pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
intel_pstate_set_pstate(cpu, pstate);
}
@@ -1678,17 +1673,14 @@ static inline int32_t get_avg_pstate(struct cpudata *cpu)
static inline int32_t get_target_pstate(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
- int32_t busy_frac, boost;
+ int32_t busy_frac;
int target, avg_pstate;
busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift,
sample->tsc);
- boost = cpu->iowait_boost;
- cpu->iowait_boost >>= 1;
-
- if (busy_frac < boost)
- busy_frac = boost;
+ if (busy_frac < cpu->iowait_boost)
+ busy_frac = cpu->iowait_boost;
sample->busy_scaled = busy_frac * 100;
@@ -1715,11 +1707,9 @@ static inline int32_t get_target_pstate(struct cpudata *cpu)
static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate)
{
- int max_pstate = intel_pstate_get_base_pstate(cpu);
- int min_pstate;
+ int min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio);
+ int max_pstate = max(min_pstate, cpu->max_perf_ratio);
- min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio);
- max_pstate = max(min_pstate, cpu->max_perf_ratio);
return clamp_t(int, pstate, min_pstate, max_pstate);
}
@@ -1767,29 +1757,30 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time,
if (smp_processor_id() != cpu->cpu)
return;
+ delta_ns = time - cpu->last_update;
if (flags & SCHED_CPUFREQ_IOWAIT) {
- cpu->iowait_boost = int_tofp(1);
- cpu->last_update = time;
- /*
- * The last time the busy was 100% so P-state was max anyway
- * so avoid overhead of computation.
- */
- if (fp_toint(cpu->sample.busy_scaled) == 100)
- return;
-
- goto set_pstate;
+ /* Start over if the CPU may have been idle. */
+ if (delta_ns > TICK_NSEC) {
+ cpu->iowait_boost = ONE_EIGHTH_FP;
+ } else if (cpu->iowait_boost) {
+ cpu->iowait_boost <<= 1;
+ if (cpu->iowait_boost > int_tofp(1))
+ cpu->iowait_boost = int_tofp(1);
+ } else {
+ cpu->iowait_boost = ONE_EIGHTH_FP;
+ }
} else if (cpu->iowait_boost) {
/* Clear iowait_boost if the CPU may have been idle. */
- delta_ns = time - cpu->last_update;
if (delta_ns > TICK_NSEC)
cpu->iowait_boost = 0;
+ else
+ cpu->iowait_boost >>= 1;
}
cpu->last_update = time;
delta_ns = time - cpu->sample.time;
if ((s64)delta_ns < INTEL_PSTATE_SAMPLING_INTERVAL)
return;
-set_pstate:
if (intel_pstate_sample(cpu, time))
intel_pstate_adjust_pstate(cpu);
}
@@ -1976,7 +1967,8 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
if (hwp_active) {
intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state);
} else {
- max_state = intel_pstate_get_base_pstate(cpu);
+ max_state = global.no_turbo || global.turbo_disabled ?
+ cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
turbo_max = cpu->pstate.turbo_pstate;
}
@@ -2475,6 +2467,7 @@ static bool __init intel_pstate_no_acpi_pss(void)
kfree(pss);
}
+ pr_debug("ACPI _PSS not found\n");
return true;
}
@@ -2485,9 +2478,14 @@ static bool __init intel_pstate_no_acpi_pcch(void)
status = acpi_get_handle(NULL, "\\_SB", &handle);
if (ACPI_FAILURE(status))
- return true;
+ goto not_found;
+
+ if (acpi_has_method(handle, "PCCH"))
+ return false;
- return !acpi_has_method(handle, "PCCH");
+not_found:
+ pr_debug("ACPI PCCH not found\n");
+ return true;
}
static bool __init intel_pstate_has_acpi_ppc(void)
@@ -2502,6 +2500,7 @@ static bool __init intel_pstate_has_acpi_ppc(void)
if (acpi_has_method(pr->handle, "_PPC"))
return true;
}
+ pr_debug("ACPI _PPC not found\n");
return false;
}
@@ -2539,8 +2538,10 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
id = x86_match_cpu(intel_pstate_cpu_oob_ids);
if (id) {
rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr);
- if ( misc_pwr & (1 << 8))
+ if (misc_pwr & (1 << 8)) {
+ pr_debug("Bit 8 in the MISC_PWR_MGMT MSR set\n");
return true;
+ }
}
idx = acpi_match_platform_list(plat_info);
@@ -2606,22 +2607,28 @@ static int __init intel_pstate_init(void)
}
} else {
id = x86_match_cpu(intel_pstate_cpu_ids);
- if (!id)
+ if (!id) {
+ pr_info("CPU ID not supported\n");
return -ENODEV;
+ }
copy_cpu_funcs((struct pstate_funcs *)id->driver_data);
}
- if (intel_pstate_msrs_not_valid())
+ if (intel_pstate_msrs_not_valid()) {
+ pr_info("Invalid MSRs\n");
return -ENODEV;
+ }
hwp_cpu_matched:
/*
* The Intel pstate driver will be ignored if the platform
* firmware has its own power management modes.
*/
- if (intel_pstate_platform_pwr_mgmt_exists())
+ if (intel_pstate_platform_pwr_mgmt_exists()) {
+ pr_info("P-states controlled by the platform\n");
return -ENODEV;
+ }
if (!hwp_active && hwp_only)
return -ENOTSUPP;
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 279bd9e9fa95..fb546e0d0356 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -851,7 +851,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
case TYPE_POWERSAVER:
pr_cont("Powersaver supported\n");
break;
- };
+ }
/* Doesn't hurt */
longhaul_setup_southbridge();
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index eb8920d39818..48e9829274c6 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -14,7 +14,6 @@
#include <linux/clk.h>
#include <linux/cpu.h>
-#include <linux/cpu_cooling.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/module.h>
@@ -48,7 +47,6 @@ struct mtk_cpu_dvfs_info {
struct regulator *sram_reg;
struct clk *cpu_clk;
struct clk *inter_clk;
- struct thermal_cooling_device *cdev;
struct list_head list_head;
int intermediate_voltage;
bool need_voltage_tracking;
@@ -307,13 +305,6 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
#define DYNAMIC_POWER "dynamic-power-coefficient"
-static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
-{
- struct mtk_cpu_dvfs_info *info = policy->driver_data;
-
- info->cdev = of_cpufreq_cooling_register(policy);
-}
-
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
{
struct device *cpu_dev;
@@ -465,6 +456,8 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
policy->driver_data = info;
policy->clk = info->cpu_clk;
+ dev_pm_opp_of_register_em(policy->cpus);
+
return 0;
}
@@ -472,7 +465,6 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
{
struct mtk_cpu_dvfs_info *info = policy->driver_data;
- cpufreq_cooling_unregister(info->cdev);
dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
return 0;
@@ -480,13 +472,13 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
static struct cpufreq_driver mtk_cpufreq_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
- CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
+ CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = mtk_cpufreq_set_target,
.get = cpufreq_generic_get,
.init = mtk_cpufreq_init,
.exit = mtk_cpufreq_exit,
- .ready = mtk_cpufreq_ready,
.name = "mtk-cpufreq",
.attr = cpufreq_generic_attr,
};
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 71e81bbf031b..68052b74d28f 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -133,8 +133,10 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
/* FIXME: what's the actual transition time? */
result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
- if (!result)
+ if (!result) {
+ dev_pm_opp_of_register_em(policy->cpus);
return 0;
+ }
freq_table_free();
fail:
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 099a849396f6..1e5e64643c3a 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -268,7 +268,7 @@ static int pcc_get_offset(int cpu)
if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) {
ret = -ENODEV;
goto out_free;
- };
+ }
offset = &(pccp->package.elements[0]);
if (!offset || offset->type != ACPI_TYPE_INTEGER) {
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 7e7ad3879c4e..d2230812fa4b 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -244,6 +244,7 @@ static int init_powernv_pstates(void)
u32 len_ids, len_freqs;
u32 pstate_min, pstate_max, pstate_nominal;
u32 pstate_turbo, pstate_ultra_turbo;
+ int rc = -ENODEV;
power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
if (!power_mgt) {
@@ -327,8 +328,11 @@ next:
powernv_freqs[i].frequency = freq * 1000; /* kHz */
powernv_freqs[i].driver_data = id & 0xFF;
- revmap_data = (struct pstate_idx_revmap_data *)
- kmalloc(sizeof(*revmap_data), GFP_KERNEL);
+ revmap_data = kmalloc(sizeof(*revmap_data), GFP_KERNEL);
+ if (!revmap_data) {
+ rc = -ENOMEM;
+ goto out;
+ }
revmap_data->pstate_id = id & 0xFF;
revmap_data->cpufreq_table_idx = i;
@@ -357,7 +361,7 @@ next:
return 0;
out:
of_node_put(power_mgt);
- return -ENODEV;
+ return rc;
}
/* Returns the CPU frequency corresponding to the pstate_id. */
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index d83939a1b3d4..4b0b50403901 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -10,18 +10,21 @@
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
#include <linux/slab.h>
#define LUT_MAX_ENTRIES 40U
#define LUT_SRC GENMASK(31, 30)
#define LUT_L_VAL GENMASK(7, 0)
#define LUT_CORE_COUNT GENMASK(18, 16)
+#define LUT_VOLT GENMASK(11, 0)
#define LUT_ROW_SIZE 32
#define CLK_HW_DIV 2
/* Register offsets */
#define REG_ENABLE 0x0
-#define REG_LUT_TABLE 0x110
+#define REG_FREQ_LUT 0x110
+#define REG_VOLT_LUT 0x114
#define REG_PERF_STATE 0x920
static unsigned long cpu_hw_rate, xo_rate;
@@ -70,11 +73,12 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
return policy->freq_table[index].frequency;
}
-static int qcom_cpufreq_hw_read_lut(struct device *dev,
+static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
struct cpufreq_policy *policy,
void __iomem *base)
{
u32 data, src, lval, i, core_count, prev_cc = 0, prev_freq = 0, freq;
+ u32 volt;
unsigned int max_cores = cpumask_weight(policy->cpus);
struct cpufreq_frequency_table *table;
@@ -83,23 +87,28 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev,
return -ENOMEM;
for (i = 0; i < LUT_MAX_ENTRIES; i++) {
- data = readl_relaxed(base + REG_LUT_TABLE + i * LUT_ROW_SIZE);
+ data = readl_relaxed(base + REG_FREQ_LUT +
+ i * LUT_ROW_SIZE);
src = FIELD_GET(LUT_SRC, data);
lval = FIELD_GET(LUT_L_VAL, data);
core_count = FIELD_GET(LUT_CORE_COUNT, data);
+ data = readl_relaxed(base + REG_VOLT_LUT +
+ i * LUT_ROW_SIZE);
+ volt = FIELD_GET(LUT_VOLT, data) * 1000;
+
if (src)
freq = xo_rate * lval / 1000;
else
freq = cpu_hw_rate / 1000;
- /* Ignore boosts in the middle of the table */
- if (core_count != max_cores) {
- table[i].frequency = CPUFREQ_ENTRY_INVALID;
- } else {
+ if (freq != prev_freq && core_count == max_cores) {
table[i].frequency = freq;
- dev_dbg(dev, "index=%d freq=%d, core_count %d\n", i,
+ dev_pm_opp_add(cpu_dev, freq * 1000, volt);
+ dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i,
freq, core_count);
+ } else {
+ table[i].frequency = CPUFREQ_ENTRY_INVALID;
}
/*
@@ -116,6 +125,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev,
if (prev_cc != max_cores) {
prev->frequency = prev_freq;
prev->flags = CPUFREQ_BOOST_FREQ;
+ dev_pm_opp_add(cpu_dev, prev_freq * 1000, volt);
}
break;
@@ -127,6 +137,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev,
table[i].frequency = CPUFREQ_TABLE_END;
policy->freq_table = table;
+ dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
return 0;
}
@@ -159,10 +170,18 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
struct device *dev = &global_pdev->dev;
struct of_phandle_args args;
struct device_node *cpu_np;
+ struct device *cpu_dev;
struct resource *res;
void __iomem *base;
int ret, index;
+ cpu_dev = get_cpu_device(policy->cpu);
+ if (!cpu_dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__,
+ policy->cpu);
+ return -ENODEV;
+ }
+
cpu_np = of_cpu_device_node_get(policy->cpu);
if (!cpu_np)
return -EINVAL;
@@ -199,12 +218,21 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
policy->driver_data = base + REG_PERF_STATE;
- ret = qcom_cpufreq_hw_read_lut(dev, policy, base);
+ ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy, base);
if (ret) {
dev_err(dev, "Domain-%d failed to read LUT\n", index);
goto error;
}
+ ret = dev_pm_opp_get_opp_count(cpu_dev);
+ if (ret <= 0) {
+ dev_err(cpu_dev, "Failed to add OPPs\n");
+ ret = -ENODEV;
+ goto error;
+ }
+
+ dev_pm_opp_of_register_em(policy->cpus);
+
policy->fast_switch_possible = true;
return 0;
@@ -215,8 +243,10 @@ error:
static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
{
+ struct device *cpu_dev = get_cpu_device(policy->cpu);
void __iomem *base = policy->driver_data - REG_PERF_STATE;
+ dev_pm_opp_remove_all_dynamic(cpu_dev);
kfree(policy->freq_table);
devm_iounmap(&global_pdev->dev, base);
@@ -231,7 +261,8 @@ static struct freq_attr *qcom_cpufreq_hw_attr[] = {
static struct cpufreq_driver cpufreq_qcom_hw_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
- CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
+ CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = qcom_cpufreq_hw_target_index,
.get = qcom_cpufreq_hw_get,
@@ -296,7 +327,7 @@ static int __init qcom_cpufreq_hw_init(void)
{
return platform_driver_register(&qcom_cpufreq_hw_driver);
}
-subsys_initcall(qcom_cpufreq_hw_init);
+device_initcall(qcom_cpufreq_hw_init);
static void __exit qcom_cpufreq_hw_exit(void)
{
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
index 2a3675c24032..dd64dcf89c74 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -42,7 +42,7 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS,
};
-struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
+static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void)
{
@@ -75,7 +75,7 @@ static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void)
static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
{
- struct opp_table *opp_tables[NR_CPUS] = {0};
+ struct opp_table **opp_tables;
enum _msm8996_version msm8996_version;
struct nvmem_cell *speedbin_nvmem;
struct device_node *np;
@@ -133,6 +133,10 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
}
kfree(speedbin);
+ opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL);
+ if (!opp_tables)
+ return -ENOMEM;
+
for_each_possible_cpu(cpu) {
cpu_dev = get_cpu_device(cpu);
if (NULL == cpu_dev) {
@@ -151,8 +155,10 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
NULL, 0);
- if (!IS_ERR(cpufreq_dt_pdev))
+ if (!IS_ERR(cpufreq_dt_pdev)) {
+ platform_set_drvdata(pdev, opp_tables);
return 0;
+ }
ret = PTR_ERR(cpufreq_dt_pdev);
dev_err(cpu_dev, "Failed to register platform device\n");
@@ -163,13 +169,23 @@ free_opp:
break;
dev_pm_opp_put_supported_hw(opp_tables[cpu]);
}
+ kfree(opp_tables);
return ret;
}
static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
{
+ struct opp_table **opp_tables = platform_get_drvdata(pdev);
+ unsigned int cpu;
+
platform_device_unregister(cpufreq_dt_pdev);
+
+ for_each_possible_cpu(cpu)
+ dev_pm_opp_put_supported_hw(opp_tables[cpu]);
+
+ kfree(opp_tables);
+
return 0;
}
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 3d773f64b4df..4295e5476264 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -13,7 +13,6 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/cpufreq.h>
-#include <linux/cpu_cooling.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -31,7 +30,6 @@
struct cpu_data {
struct clk **pclk;
struct cpufreq_frequency_table *table;
- struct thermal_cooling_device *cdev;
};
/*
@@ -239,7 +237,6 @@ static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{
struct cpu_data *data = policy->driver_data;
- cpufreq_cooling_unregister(data->cdev);
kfree(data->pclk);
kfree(data->table);
kfree(data);
@@ -258,23 +255,15 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
return clk_set_parent(policy->clk, parent);
}
-
-static void qoriq_cpufreq_ready(struct cpufreq_policy *policy)
-{
- struct cpu_data *cpud = policy->driver_data;
-
- cpud->cdev = of_cpufreq_cooling_register(policy);
-}
-
static struct cpufreq_driver qoriq_cpufreq_driver = {
.name = "qoriq_cpufreq",
- .flags = CPUFREQ_CONST_LOOPS,
+ .flags = CPUFREQ_CONST_LOOPS |
+ CPUFREQ_IS_COOLING_DEV,
.init = qoriq_cpufreq_cpu_init,
.exit = qoriq_cpufreq_cpu_exit,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = qoriq_cpufreq_target,
.get = cpufreq_generic_get,
- .ready = qoriq_cpufreq_ready,
.attr = cpufreq_generic_attr,
};
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index dbecd7667db2..5b4289460bc9 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -584,7 +584,7 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
static int s5pv210_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *np;
- int id;
+ int id, result = 0;
/*
* HACK: This is a temporary workaround to get access to clock
@@ -594,18 +594,39 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev)
* this whole driver as soon as S5PV210 gets migrated to use
* cpufreq-dt driver.
*/
+ arm_regulator = regulator_get(NULL, "vddarm");
+ if (IS_ERR(arm_regulator)) {
+ if (PTR_ERR(arm_regulator) == -EPROBE_DEFER)
+ pr_debug("vddarm regulator not ready, defer\n");
+ else
+ pr_err("failed to get regulator vddarm\n");
+ return PTR_ERR(arm_regulator);
+ }
+
+ int_regulator = regulator_get(NULL, "vddint");
+ if (IS_ERR(int_regulator)) {
+ if (PTR_ERR(int_regulator) == -EPROBE_DEFER)
+ pr_debug("vddint regulator not ready, defer\n");
+ else
+ pr_err("failed to get regulator vddint\n");
+ result = PTR_ERR(int_regulator);
+ goto err_int_regulator;
+ }
+
np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
if (!np) {
pr_err("%s: failed to find clock controller DT node\n",
__func__);
- return -ENODEV;
+ result = -ENODEV;
+ goto err_clock;
}
clk_base = of_iomap(np, 0);
of_node_put(np);
if (!clk_base) {
pr_err("%s: failed to map clock registers\n", __func__);
- return -EFAULT;
+ result = -EFAULT;
+ goto err_clock;
}
for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {
@@ -614,7 +635,8 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev)
pr_err("%s: failed to get alias of dmc node '%pOFn'\n",
__func__, np);
of_node_put(np);
- return id;
+ result = id;
+ goto err_clk_base;
}
dmc_base[id] = of_iomap(np, 0);
@@ -622,33 +644,40 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev)
pr_err("%s: failed to map dmc%d registers\n",
__func__, id);
of_node_put(np);
- return -EFAULT;
+ result = -EFAULT;
+ goto err_dmc;
}
}
for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) {
if (!dmc_base[id]) {
pr_err("%s: failed to find dmc%d node\n", __func__, id);
- return -ENODEV;
+ result = -ENODEV;
+ goto err_dmc;
}
}
- arm_regulator = regulator_get(NULL, "vddarm");
- if (IS_ERR(arm_regulator)) {
- pr_err("failed to get regulator vddarm\n");
- return PTR_ERR(arm_regulator);
- }
-
- int_regulator = regulator_get(NULL, "vddint");
- if (IS_ERR(int_regulator)) {
- pr_err("failed to get regulator vddint\n");
- regulator_put(arm_regulator);
- return PTR_ERR(int_regulator);
- }
-
register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
return cpufreq_register_driver(&s5pv210_driver);
+
+err_dmc:
+ for (id = 0; id < ARRAY_SIZE(dmc_base); ++id)
+ if (dmc_base[id]) {
+ iounmap(dmc_base[id]);
+ dmc_base[id] = NULL;
+ }
+
+err_clk_base:
+ iounmap(clk_base);
+
+err_clock:
+ regulator_put(int_regulator);
+
+err_int_regulator:
+ regulator_put(arm_regulator);
+
+ return result;
}
static struct platform_driver s5pv210_cpufreq_platdrv = {
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 50b1551ba894..e6182c89df79 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -11,7 +11,7 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
-#include <linux/cpu_cooling.h>
+#include <linux/energy_model.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/pm_opp.h>
@@ -22,7 +22,6 @@
struct scmi_data {
int domain_id;
struct device *cpu_dev;
- struct thermal_cooling_device *cdev;
};
static const struct scmi_handle *handle;
@@ -52,9 +51,9 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
int ret;
struct scmi_data *priv = policy->driver_data;
struct scmi_perf_ops *perf_ops = handle->perf_ops;
- u64 freq = policy->freq_table[index].frequency * 1000;
+ u64 freq = policy->freq_table[index].frequency;
- ret = perf_ops->freq_set(handle, priv->domain_id, freq, false);
+ ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
if (!ret)
arch_set_freq_scale(policy->related_cpus, freq,
policy->cpuinfo.max_freq);
@@ -103,13 +102,42 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
return 0;
}
+static int __maybe_unused
+scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, int cpu)
+{
+ struct device *cpu_dev = get_cpu_device(cpu);
+ unsigned long Hz;
+ int ret, domain;
+
+ if (!cpu_dev) {
+ pr_err("failed to get cpu%d device\n", cpu);
+ return -ENODEV;
+ }
+
+ domain = handle->perf_ops->device_domain_id(cpu_dev);
+ if (domain < 0)
+ return domain;
+
+ /* Get the power cost of the performance domain. */
+ Hz = *KHz * 1000;
+ ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power);
+ if (ret)
+ return ret;
+
+ /* The EM framework specifies the frequency in KHz. */
+ *KHz = Hz / 1000;
+
+ return 0;
+}
+
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
{
- int ret;
+ int ret, nr_opp;
unsigned int latency;
struct device *cpu_dev;
struct scmi_data *priv;
struct cpufreq_frequency_table *freq_table;
+ struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);
cpu_dev = get_cpu_device(policy->cpu);
if (!cpu_dev) {
@@ -136,8 +164,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return ret;
}
- ret = dev_pm_opp_get_opp_count(cpu_dev);
- if (ret <= 0) {
+ nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+ if (nr_opp <= 0) {
dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
ret = -EPROBE_DEFER;
goto out_free_opp;
@@ -171,12 +199,15 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = latency;
policy->fast_switch_possible = true;
+
+ em_register_perf_domain(policy->cpus, nr_opp, &em_cb);
+
return 0;
out_free_priv:
kfree(priv);
out_free_opp:
- dev_pm_opp_cpumask_remove_table(policy->cpus);
+ dev_pm_opp_remove_all_dynamic(cpu_dev);
return ret;
}
@@ -185,25 +216,18 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
{
struct scmi_data *priv = policy->driver_data;
- cpufreq_cooling_unregister(priv->cdev);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+ dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
kfree(priv);
- dev_pm_opp_cpumask_remove_table(policy->related_cpus);
return 0;
}
-static void scmi_cpufreq_ready(struct cpufreq_policy *policy)
-{
- struct scmi_data *priv = policy->driver_data;
-
- priv->cdev = of_cpufreq_cooling_register(policy);
-}
-
static struct cpufreq_driver scmi_cpufreq_driver = {
.name = "scmi",
.flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
- CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.attr = cpufreq_generic_attr,
.target_index = scmi_cpufreq_set_target,
@@ -211,7 +235,6 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
.get = scmi_cpufreq_get_rate,
.init = scmi_cpufreq_init,
.exit = scmi_cpufreq_exit,
- .ready = scmi_cpufreq_ready,
};
static int scmi_cpufreq_probe(struct scmi_device *sdev)
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 87a98ec77773..3f49427766b8 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -22,7 +22,6 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
-#include <linux/cpu_cooling.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/of_platform.h>
@@ -34,7 +33,6 @@
struct scpi_data {
struct clk *clk;
struct device *cpu_dev;
- struct thermal_cooling_device *cdev;
};
static struct scpi_ops *scpi_ops;
@@ -170,6 +168,9 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = latency;
policy->fast_switch_possible = false;
+
+ dev_pm_opp_of_register_em(policy->cpus);
+
return 0;
out_free_cpufreq_table:
@@ -177,7 +178,7 @@ out_free_cpufreq_table:
out_free_priv:
kfree(priv);
out_free_opp:
- dev_pm_opp_cpumask_remove_table(policy->cpus);
+ dev_pm_opp_remove_all_dynamic(cpu_dev);
return ret;
}
@@ -186,32 +187,24 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy)
{
struct scpi_data *priv = policy->driver_data;
- cpufreq_cooling_unregister(priv->cdev);
clk_put(priv->clk);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
kfree(priv);
- dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+ dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
return 0;
}
-static void scpi_cpufreq_ready(struct cpufreq_policy *policy)
-{
- struct scpi_data *priv = policy->driver_data;
-
- priv->cdev = of_cpufreq_cooling_register(policy);
-}
-
static struct cpufreq_driver scpi_cpufreq_driver = {
.name = "scpi-cpufreq",
.flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
- CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+ CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.attr = cpufreq_generic_attr,
.get = scpi_cpufreq_get_rate,
.init = scpi_cpufreq_init,
.exit = scpi_cpufreq_exit,
- .ready = scpi_cpufreq_ready,
.target_index = scpi_cpufreq_set_target,
};
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index fbbcb88db061..5d8a09b82efb 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -243,8 +243,7 @@ static unsigned int speedstep_get(unsigned int cpu)
unsigned int speed;
/* You're supposed to ensure CPU is online. */
- if (smp_call_function_single(cpu, get_freq_data, &speed, 1) != 0)
- BUG();
+ BUG_ON(smp_call_function_single(cpu, get_freq_data, &speed, 1));
pr_debug("detected %u kHz as current frequency\n", speed);
return speed;
diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
index 43530254201a..5e748c8a5c9a 100644
--- a/drivers/cpufreq/tegra124-cpufreq.c
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -22,11 +22,9 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
-#include <linux/regulator/consumer.h>
#include <linux/types.h>
struct tegra124_cpufreq_priv {
- struct regulator *vdd_cpu_reg;
struct clk *cpu_clk;
struct clk *pllp_clk;
struct clk *pllx_clk;
@@ -60,14 +58,6 @@ out:
return ret;
}
-static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv)
-{
- clk_set_parent(priv->cpu_clk, priv->pllp_clk);
- clk_disable_unprepare(priv->dfll_clk);
- regulator_sync_voltage(priv->vdd_cpu_reg);
- clk_set_parent(priv->cpu_clk, priv->pllx_clk);
-}
-
static int tegra124_cpufreq_probe(struct platform_device *pdev)
{
struct tegra124_cpufreq_priv *priv;
@@ -88,16 +78,10 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
if (!np)
return -ENODEV;
- priv->vdd_cpu_reg = regulator_get(cpu_dev, "vdd-cpu");
- if (IS_ERR(priv->vdd_cpu_reg)) {
- ret = PTR_ERR(priv->vdd_cpu_reg);
- goto out_put_np;
- }
-
priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
if (IS_ERR(priv->cpu_clk)) {
ret = PTR_ERR(priv->cpu_clk);
- goto out_put_vdd_cpu_reg;
+ goto out_put_np;
}
priv->dfll_clk = of_clk_get_by_name(np, "dfll");
@@ -129,15 +113,15 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
platform_device_register_full(&cpufreq_dt_devinfo);
if (IS_ERR(priv->cpufreq_dt_pdev)) {
ret = PTR_ERR(priv->cpufreq_dt_pdev);
- goto out_switch_to_pllx;
+ goto out_put_pllp_clk;
}
platform_set_drvdata(pdev, priv);
+ of_node_put(np);
+
return 0;
-out_switch_to_pllx:
- tegra124_cpu_switch_to_pllx(priv);
out_put_pllp_clk:
clk_put(priv->pllp_clk);
out_put_pllx_clk:
@@ -146,34 +130,15 @@ out_put_dfll_clk:
clk_put(priv->dfll_clk);
out_put_cpu_clk:
clk_put(priv->cpu_clk);
-out_put_vdd_cpu_reg:
- regulator_put(priv->vdd_cpu_reg);
out_put_np:
of_node_put(np);
return ret;
}
-static int tegra124_cpufreq_remove(struct platform_device *pdev)
-{
- struct tegra124_cpufreq_priv *priv = platform_get_drvdata(pdev);
-
- platform_device_unregister(priv->cpufreq_dt_pdev);
- tegra124_cpu_switch_to_pllx(priv);
-
- clk_put(priv->pllp_clk);
- clk_put(priv->pllx_clk);
- clk_put(priv->dfll_clk);
- clk_put(priv->cpu_clk);
- regulator_put(priv->vdd_cpu_reg);
-
- return 0;
-}
-
static struct platform_driver tegra124_cpufreq_platdrv = {
.driver.name = "cpufreq-tegra124",
.probe = tegra124_cpufreq_probe,
- .remove = tegra124_cpufreq_remove,
};
static int __init tegra_cpufreq_init(void)
@@ -181,7 +146,8 @@ static int __init tegra_cpufreq_init(void)
int ret;
struct platform_device *pdev;
- if (!of_machine_is_compatible("nvidia,tegra124"))
+ if (!(of_machine_is_compatible("nvidia,tegra124") ||
+ of_machine_is_compatible("nvidia,tegra210")))
return -ENODEV;
/*
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 7e48eb5bf0a7..8caccbbd7353 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -4,7 +4,7 @@ config CPU_IDLE
bool "CPU idle PM support"
default y if ACPI || PPC_PSERIES
select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
- select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE)
+ select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE) && !CPU_IDLE_GOV_TEO
help
CPU idle is a generic framework for supporting software-controlled
idle processor power management. It includes modular cross-platform
@@ -23,6 +23,15 @@ config CPU_IDLE_GOV_LADDER
config CPU_IDLE_GOV_MENU
bool "Menu governor (for tickless system)"
+config CPU_IDLE_GOV_TEO
+ bool "Timer events oriented (TEO) governor (for tickless systems)"
+ help
+ This governor implements a simplified idle state selection method
+ focused on timer events and does not do any interactivity boosting.
+
+ Some workloads benefit from using it and it generally should be safe
+ to use. Say Y here if you are not happy with the alternatives.
+
config DT_IDLE_STATES
bool
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index 53342b7f1010..add9569636b5 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -22,16 +22,12 @@
#include "dt_idle_states.h"
static int init_state_node(struct cpuidle_state *idle_state,
- const struct of_device_id *matches,
+ const struct of_device_id *match_id,
struct device_node *state_node)
{
int err;
- const struct of_device_id *match_id;
const char *desc;
- match_id = of_match_node(matches, state_node);
- if (!match_id)
- return -ENODEV;
/*
* CPUidle drivers are expected to initialize the const void *data
* pointer of the passed in struct of_device_id array to the idle
@@ -160,6 +156,7 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
{
struct cpuidle_state *idle_state;
struct device_node *state_node, *cpu_node;
+ const struct of_device_id *match_id;
int i, err = 0;
const cpumask_t *cpumask;
unsigned int state_idx = start_idx;
@@ -180,6 +177,12 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
if (!state_node)
break;
+ match_id = of_match_node(matches, state_node);
+ if (!match_id) {
+ err = -ENODEV;
+ break;
+ }
+
if (!of_device_is_available(state_node)) {
of_node_put(state_node);
continue;
@@ -198,7 +201,7 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
}
idle_state = &drv->states[state_idx++];
- err = init_state_node(idle_state, matches, state_node);
+ err = init_state_node(idle_state, match_id, state_node);
if (err) {
pr_err("Parsing idle state node %pOF failed with err %d\n",
state_node, err);
diff --git a/drivers/cpuidle/governors/Makefile b/drivers/cpuidle/governors/Makefile
index 1b512722689f..4d8aff5248a8 100644
--- a/drivers/cpuidle/governors/Makefile
+++ b/drivers/cpuidle/governors/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
+obj-$(CONFIG_CPU_IDLE_GOV_TEO) += teo.o
diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c
new file mode 100644
index 000000000000..7d05efdbd3c6
--- /dev/null
+++ b/drivers/cpuidle/governors/teo.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Timer events oriented CPU idle governor
+ *
+ * Copyright (C) 2018 Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * The idea of this governor is based on the observation that on many systems
+ * timer events are two or more orders of magnitude more frequent than any
+ * other interrupts, so they are likely to be the most significant source of CPU
+ * wakeups from idle states. Moreover, information about what happened in the
+ * (relatively recent) past can be used to estimate whether or not the deepest
+ * idle state with target residency within the time to the closest timer is
+ * likely to be suitable for the upcoming idle time of the CPU and, if not, then
+ * which of the shallower idle states to choose.
+ *
+ * Of course, non-timer wakeup sources are more important in some use cases and
+ * they can be covered by taking a few most recent idle time intervals of the
+ * CPU into account. However, even in that case it is not necessary to consider
+ * idle duration values greater than the time till the closest timer, as the
+ * patterns that they may belong to produce average values close enough to
+ * the time till the closest timer (sleep length) anyway.
+ *
+ * Thus this governor estimates whether or not the upcoming idle time of the CPU
+ * is likely to be significantly shorter than the sleep length and selects an
+ * idle state for it in accordance with that, as follows:
+ *
+ * - Find an idle state on the basis of the sleep length and state statistics
+ * collected over time:
+ *
+ * o Find the deepest idle state whose target residency is less than or equal
+ * to the sleep length.
+ *
+ * o Select it if it matched both the sleep length and the observed idle
+ * duration in the past more often than it matched the sleep length alone
+ * (i.e. the observed idle duration was significantly shorter than the sleep
+ * length matched by it).
+ *
+ * o Otherwise, select the shallower state with the greatest matched "early"
+ * wakeups metric.
+ *
+ * - If the majority of the most recent idle duration values are below the
+ * target residency of the idle state selected so far, use those values to
+ * compute the new expected idle duration and find an idle state matching it
+ * (which has to be shallower than the one selected so far).
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/sched/clock.h>
+#include <linux/tick.h>
+
+/*
+ * The PULSE value is added to metrics when they grow and the DECAY_SHIFT value
+ * is used for decreasing metrics on a regular basis.
+ */
+#define PULSE 1024
+#define DECAY_SHIFT 3
+
+/*
+ * Number of the most recent idle duration values to take into consideration for
+ * the detection of wakeup patterns.
+ */
+#define INTERVALS 8
+
+/**
+ * struct teo_idle_state - Idle state data used by the TEO cpuidle governor.
+ * @early_hits: "Early" CPU wakeups "matching" this state.
+ * @hits: "On time" CPU wakeups "matching" this state.
+ * @misses: CPU wakeups "missing" this state.
+ *
+ * A CPU wakeup is "matched" by a given idle state if the idle duration measured
+ * after the wakeup is between the target residency of that state and the target
+ * residency of the next one (or if this is the deepest available idle state, it
+ * "matches" a CPU wakeup when the measured idle duration is at least equal to
+ * its target residency).
+ *
+ * Also, from the TEO governor perspective, a CPU wakeup from idle is "early" if
+ * it occurs significantly earlier than the closest expected timer event (that
+ * is, early enough to match an idle state shallower than the one matching the
+ * time till the closest timer event). Otherwise, the wakeup is "on time", or
+ * it is a "hit".
+ *
+ * A "miss" occurs when the given state doesn't match the wakeup, but it matches
+ * the time till the closest timer event used for idle state selection.
+ */
+struct teo_idle_state {
+ unsigned int early_hits;
+ unsigned int hits;
+ unsigned int misses;
+};
+
+/**
+ * struct teo_cpu - CPU data used by the TEO cpuidle governor.
+ * @time_span_ns: Time between idle state selection and post-wakeup update.
+ * @sleep_length_ns: Time till the closest timer event (at the selection time).
+ * @states: Idle states data corresponding to this CPU.
+ * @last_state: Idle state entered by the CPU last time.
+ * @interval_idx: Index of the most recent saved idle interval.
+ * @intervals: Saved idle duration values.
+ */
+struct teo_cpu {
+ u64 time_span_ns;
+ u64 sleep_length_ns;
+ struct teo_idle_state states[CPUIDLE_STATE_MAX];
+ int last_state;
+ int interval_idx;
+ unsigned int intervals[INTERVALS];
+};
+
+static DEFINE_PER_CPU(struct teo_cpu, teo_cpus);
+
+/**
+ * teo_update - Update CPU data after wakeup.
+ * @drv: cpuidle driver containing state data.
+ * @dev: Target CPU.
+ */
+static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+{
+ struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
+ unsigned int sleep_length_us = ktime_to_us(cpu_data->sleep_length_ns);
+ int i, idx_hit = -1, idx_timer = -1;
+ unsigned int measured_us;
+
+ if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) {
+ /*
+ * One of the safety nets has triggered or this was a timer
+ * wakeup (or equivalent).
+ */
+ measured_us = sleep_length_us;
+ } else {
+ unsigned int lat = drv->states[cpu_data->last_state].exit_latency;
+
+ measured_us = ktime_to_us(cpu_data->time_span_ns);
+ /*
+ * The delay between the wakeup and the first instruction
+ * executed by the CPU is not likely to be worst-case every
+ * time, so take 1/2 of the exit latency as a very rough
+ * approximation of the average of it.
+ */
+ if (measured_us >= lat)
+ measured_us -= lat / 2;
+ else
+ measured_us /= 2;
+ }
+
+ /*
+ * Decay the "early hits" metric for all of the states and find the
+ * states matching the sleep length and the measured idle duration.
+ */
+ for (i = 0; i < drv->state_count; i++) {
+ unsigned int early_hits = cpu_data->states[i].early_hits;
+
+ cpu_data->states[i].early_hits -= early_hits >> DECAY_SHIFT;
+
+ if (drv->states[i].target_residency <= sleep_length_us) {
+ idx_timer = i;
+ if (drv->states[i].target_residency <= measured_us)
+ idx_hit = i;
+ }
+ }
+
+ /*
+ * Update the "hits" and "misses" data for the state matching the sleep
+ * length. If it matches the measured idle duration too, this is a hit,
+ * so increase the "hits" metric for it then. Otherwise, this is a
+ * miss, so increase the "misses" metric for it. In the latter case
+ * also increase the "early hits" metric for the state that actually
+ * matches the measured idle duration.
+ */
+ if (idx_timer >= 0) {
+ unsigned int hits = cpu_data->states[idx_timer].hits;
+ unsigned int misses = cpu_data->states[idx_timer].misses;
+
+ hits -= hits >> DECAY_SHIFT;
+ misses -= misses >> DECAY_SHIFT;
+
+ if (idx_timer > idx_hit) {
+ misses += PULSE;
+ if (idx_hit >= 0)
+ cpu_data->states[idx_hit].early_hits += PULSE;
+ } else {
+ hits += PULSE;
+ }
+
+ cpu_data->states[idx_timer].misses = misses;
+ cpu_data->states[idx_timer].hits = hits;
+ }
+
+ /*
+ * If the total time span between idle state selection and the "reflect"
+ * callback is greater than or equal to the sleep length determined at
+ * the idle state selection time, the wakeup is likely to be due to a
+ * timer event.
+ */
+ if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns)
+ measured_us = UINT_MAX;
+
+ /*
+ * Save idle duration values corresponding to non-timer wakeups for
+ * pattern detection.
+ */
+ cpu_data->intervals[cpu_data->interval_idx++] = measured_us;
+ if (cpu_data->interval_idx > INTERVALS)
+ cpu_data->interval_idx = 0;
+}
+
+/**
+ * teo_find_shallower_state - Find shallower idle state matching given duration.
+ * @drv: cpuidle driver containing state data.
+ * @dev: Target CPU.
+ * @state_idx: Index of the capping idle state.
+ * @duration_us: Idle duration value to match.
+ */
+static int teo_find_shallower_state(struct cpuidle_driver *drv,
+ struct cpuidle_device *dev, int state_idx,
+ unsigned int duration_us)
+{
+ int i;
+
+ for (i = state_idx - 1; i >= 0; i--) {
+ if (drv->states[i].disabled || dev->states_usage[i].disable)
+ continue;
+
+ state_idx = i;
+ if (drv->states[i].target_residency <= duration_us)
+ break;
+ }
+ return state_idx;
+}
+
+/**
+ * teo_select - Selects the next idle state to enter.
+ * @drv: cpuidle driver containing state data.
+ * @dev: Target CPU.
+ * @stop_tick: Indication on whether or not to stop the scheduler tick.
+ */
+static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
+ bool *stop_tick)
+{
+ struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
+ int latency_req = cpuidle_governor_latency_req(dev->cpu);
+ unsigned int duration_us, count;
+ int max_early_idx, idx, i;
+ ktime_t delta_tick;
+
+ if (cpu_data->last_state >= 0) {
+ teo_update(drv, dev);
+ cpu_data->last_state = -1;
+ }
+
+ cpu_data->time_span_ns = local_clock();
+
+ cpu_data->sleep_length_ns = tick_nohz_get_sleep_length(&delta_tick);
+ duration_us = ktime_to_us(cpu_data->sleep_length_ns);
+
+ count = 0;
+ max_early_idx = -1;
+ idx = -1;
+
+ for (i = 0; i < drv->state_count; i++) {
+ struct cpuidle_state *s = &drv->states[i];
+ struct cpuidle_state_usage *su = &dev->states_usage[i];
+
+ if (s->disabled || su->disable) {
+ /*
+ * If the "early hits" metric of a disabled state is
+ * greater than the current maximum, it should be taken
+ * into account, because it would be a mistake to select
+ * a deeper state with lower "early hits" metric. The
+ * index cannot be changed to point to it, however, so
+ * just increase the max count alone and let the index
+ * still point to a shallower idle state.
+ */
+ if (max_early_idx >= 0 &&
+ count < cpu_data->states[i].early_hits)
+ count = cpu_data->states[i].early_hits;
+
+ continue;
+ }
+
+ if (idx < 0)
+ idx = i; /* first enabled state */
+
+ if (s->target_residency > duration_us)
+ break;
+
+ if (s->exit_latency > latency_req) {
+ /*
+ * If we break out of the loop for latency reasons, use
+ * the target residency of the selected state as the
+ * expected idle duration to avoid stopping the tick
+ * as long as that target residency is low enough.
+ */
+ duration_us = drv->states[idx].target_residency;
+ goto refine;
+ }
+
+ idx = i;
+
+ if (count < cpu_data->states[i].early_hits &&
+ !(tick_nohz_tick_stopped() &&
+ drv->states[i].target_residency < TICK_USEC)) {
+ count = cpu_data->states[i].early_hits;
+ max_early_idx = i;
+ }
+ }
+
+ /*
+ * If the "hits" metric of the idle state matching the sleep length is
+ * greater than its "misses" metric, that is the one to use. Otherwise,
+ * it is more likely that one of the shallower states will match the
+ * idle duration observed after wakeup, so take the one with the maximum
+ * "early hits" metric, but if that cannot be determined, just use the
+ * state selected so far.
+ */
+ if (cpu_data->states[idx].hits <= cpu_data->states[idx].misses &&
+ max_early_idx >= 0) {
+ idx = max_early_idx;
+ duration_us = drv->states[idx].target_residency;
+ }
+
+refine:
+ if (idx < 0) {
+ idx = 0; /* No states enabled. Must use 0. */
+ } else if (idx > 0) {
+ u64 sum = 0;
+
+ count = 0;
+
+ /*
+ * Count and sum the most recent idle duration values less than
+ * the target residency of the state selected so far, find the
+ * max.
+ */
+ for (i = 0; i < INTERVALS; i++) {
+ unsigned int val = cpu_data->intervals[i];
+
+ if (val >= drv->states[idx].target_residency)
+ continue;
+
+ count++;
+ sum += val;
+ }
+
+ /*
+ * Give up unless the majority of the most recent idle duration
+ * values are in the interesting range.
+ */
+ if (count > INTERVALS / 2) {
+ unsigned int avg_us = div64_u64(sum, count);
+
+ /*
+ * Avoid spending too much time in an idle state that
+ * would be too shallow.
+ */
+ if (!(tick_nohz_tick_stopped() && avg_us < TICK_USEC)) {
+ idx = teo_find_shallower_state(drv, dev, idx, avg_us);
+ duration_us = avg_us;
+ }
+ }
+ }
+
+ /*
+ * Don't stop the tick if the selected state is a polling one or if the
+ * expected idle duration is shorter than the tick period length.
+ */
+ if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
+ duration_us < TICK_USEC) && !tick_nohz_tick_stopped()) {
+ unsigned int delta_tick_us = ktime_to_us(delta_tick);
+
+ *stop_tick = false;
+
+ /*
+ * The tick is not going to be stopped, so if the target
+ * residency of the state to be returned is not within the time
+ * till the closest timer including the tick, try to correct
+ * that.
+ */
+ if (idx > 0 && drv->states[idx].target_residency > delta_tick_us)
+ idx = teo_find_shallower_state(drv, dev, idx, delta_tick_us);
+ }
+
+ return idx;
+}
+
+/**
+ * teo_reflect - Note that governor data for the CPU need to be updated.
+ * @dev: Target CPU.
+ * @state: Entered state.
+ */
+static void teo_reflect(struct cpuidle_device *dev, int state)
+{
+ struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
+
+ cpu_data->last_state = state;
+ /*
+ * If the wakeup was not "natural", but triggered by one of the safety
+ * nets, assume that the CPU might have been idle for the entire sleep
+ * length time.
+ */
+ if (dev->poll_time_limit ||
+ (tick_nohz_idle_got_tick() && cpu_data->sleep_length_ns > TICK_NSEC)) {
+ dev->poll_time_limit = false;
+ cpu_data->time_span_ns = cpu_data->sleep_length_ns;
+ } else {
+ cpu_data->time_span_ns = local_clock() - cpu_data->time_span_ns;
+ }
+}
+
+/**
+ * teo_enable_device - Initialize the governor's data for the target CPU.
+ * @drv: cpuidle driver (not used).
+ * @dev: Target CPU.
+ */
+static int teo_enable_device(struct cpuidle_driver *drv,
+ struct cpuidle_device *dev)
+{
+ struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
+ int i;
+
+ memset(cpu_data, 0, sizeof(*cpu_data));
+
+ for (i = 0; i < INTERVALS; i++)
+ cpu_data->intervals[i] = UINT_MAX;
+
+ return 0;
+}
+
+static struct cpuidle_governor teo_governor = {
+ .name = "teo",
+ .rating = 19,
+ .enable = teo_enable_device,
+ .select = teo_select,
+ .reflect = teo_reflect,
+};
+
+static int __init teo_governor_init(void)
+{
+ return cpuidle_register_governor(&teo_governor);
+}
+
+postcore_initcall(teo_governor_init);
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
index b17d153e724f..23a1b27579a5 100644
--- a/drivers/cpuidle/poll_state.c
+++ b/drivers/cpuidle/poll_state.c
@@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
local_irq_enable();
if (!current_set_polling_and_test()) {
unsigned int loop_count = 0;
- u64 limit = TICK_USEC;
+ u64 limit = TICK_NSEC;
int i;
for (i = 1; i < drv->state_count; i++) {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 5a90075f719d..0be55fcc19ba 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -692,6 +692,7 @@ config CRYPTO_DEV_BCM_SPU
depends on ARCH_BCM_IPROC
depends on MAILBOX
default m
+ select CRYPTO_AUTHENC
select CRYPTO_DES
select CRYPTO_MD5
select CRYPTO_SHA1
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 63cb6956c948..06574a884715 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -40,9 +40,11 @@
#include <crypto/ctr.h>
#include <crypto/gcm.h>
#include <crypto/sha.h>
+#include <crypto/rng.h>
#include <crypto/scatterwalk.h>
#include <crypto/skcipher.h>
#include <crypto/internal/aead.h>
+#include <crypto/internal/rng.h>
#include <crypto/internal/skcipher.h>
#include "crypto4xx_reg_def.h"
#include "crypto4xx_core.h"
@@ -283,9 +285,9 @@ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
*/
static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
{
- dev->gdr = dma_zalloc_coherent(dev->core_dev->device,
- sizeof(struct ce_gd) * PPC4XX_NUM_GD,
- &dev->gdr_pa, GFP_ATOMIC);
+ dev->gdr = dma_alloc_coherent(dev->core_dev->device,
+ sizeof(struct ce_gd) * PPC4XX_NUM_GD,
+ &dev->gdr_pa, GFP_ATOMIC);
if (!dev->gdr)
return -ENOMEM;
@@ -1035,6 +1037,10 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
rc = crypto_register_ahash(&alg->alg.u.hash);
break;
+ case CRYPTO_ALG_TYPE_RNG:
+ rc = crypto_register_rng(&alg->alg.u.rng);
+ break;
+
default:
rc = crypto_register_skcipher(&alg->alg.u.cipher);
break;
@@ -1064,6 +1070,10 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)
crypto_unregister_aead(&alg->alg.u.aead);
break;
+ case CRYPTO_ALG_TYPE_RNG:
+ crypto_unregister_rng(&alg->alg.u.rng);
+ break;
+
default:
crypto_unregister_skcipher(&alg->alg.u.cipher);
}
@@ -1122,6 +1132,69 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
PPC4XX_TMO_ERR_INT);
}
+static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
+ u8 *data, unsigned int max)
+{
+ unsigned int i, curr = 0;
+ u32 val[2];
+
+ do {
+ /* trigger PRN generation */
+ writel(PPC4XX_PRNG_CTRL_AUTO_EN,
+ dev->ce_base + CRYPTO4XX_PRNG_CTRL);
+
+ for (i = 0; i < 1024; i++) {
+ /* usually 19 iterations are enough */
+ if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
+ CRYPTO4XX_PRNG_STAT_BUSY))
+ continue;
+
+ val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
+ val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
+ break;
+ }
+ if (i == 1024)
+ return -ETIMEDOUT;
+
+ if ((max - curr) >= 8) {
+ memcpy(data, &val, 8);
+ data += 8;
+ curr += 8;
+ } else {
+ /* copy only remaining bytes */
+ memcpy(data, &val, max - curr);
+ break;
+ }
+ } while (curr < max);
+
+ return curr;
+}
+
+static int crypto4xx_prng_generate(struct crypto_rng *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dstn, unsigned int dlen)
+{
+ struct rng_alg *alg = crypto_rng_alg(tfm);
+ struct crypto4xx_alg *amcc_alg;
+ struct crypto4xx_device *dev;
+ int ret;
+
+ amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
+ dev = amcc_alg->dev;
+
+ mutex_lock(&dev->core_dev->rng_lock);
+ ret = ppc4xx_prng_data_read(dev, dstn, dlen);
+ mutex_unlock(&dev->core_dev->rng_lock);
+ return ret;
+}
+
+
+static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
+ unsigned int slen)
+{
+ return 0;
+}
+
/**
* Supported Crypto Algorithms
*/
@@ -1291,6 +1364,18 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = {
.cra_module = THIS_MODULE,
},
} },
+ { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
+ .base = {
+ .cra_name = "stdrng",
+ .cra_driver_name = "crypto4xx_rng",
+ .cra_priority = 300,
+ .cra_ctxsize = 0,
+ .cra_module = THIS_MODULE,
+ },
+ .generate = crypto4xx_prng_generate,
+ .seed = crypto4xx_prng_seed,
+ .seedsize = 0,
+ } },
};
/**
@@ -1360,6 +1445,7 @@ static int crypto4xx_probe(struct platform_device *ofdev)
core_dev->dev->core_dev = core_dev;
core_dev->dev->is_revb = is_revb;
core_dev->device = dev;
+ mutex_init(&core_dev->rng_lock);
spin_lock_init(&core_dev->lock);
INIT_LIST_HEAD(&core_dev->dev->alg_list);
ratelimit_default_init(&core_dev->dev->aead_ratelimit);
@@ -1439,6 +1525,7 @@ static int crypto4xx_remove(struct platform_device *ofdev)
tasklet_kill(&core_dev->tasklet);
/* Un-register with Linux CryptoAPI */
crypto4xx_unregister_alg(core_dev->dev);
+ mutex_destroy(&core_dev->rng_lock);
/* Free all allocated memory */
crypto4xx_stop_all(core_dev);
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
index e2ca56722f07..18df695ca6b1 100644
--- a/drivers/crypto/amcc/crypto4xx_core.h
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -23,8 +23,10 @@
#define __CRYPTO4XX_CORE_H__
#include <linux/ratelimit.h>
+#include <linux/mutex.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/aead.h>
+#include <crypto/internal/rng.h>
#include <crypto/internal/skcipher.h>
#include "crypto4xx_reg_def.h"
#include "crypto4xx_sa.h"
@@ -119,6 +121,7 @@ struct crypto4xx_core_device {
u32 irq;
struct tasklet_struct tasklet;
spinlock_t lock;
+ struct mutex rng_lock;
};
struct crypto4xx_ctx {
@@ -143,6 +146,7 @@ struct crypto4xx_alg_common {
struct skcipher_alg cipher;
struct ahash_alg hash;
struct aead_alg aead;
+ struct rng_alg rng;
} u;
};
diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h
index 472331787e04..80c67490bbf6 100644
--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
@@ -100,6 +100,7 @@
#define CRYPTO4XX_ENDIAN_CFG 0x000600d8
#define CRYPTO4XX_PRNG_STAT 0x00070000
+#define CRYPTO4XX_PRNG_STAT_BUSY 0x1
#define CRYPTO4XX_PRNG_CTRL 0x00070004
#define CRYPTO4XX_PRNG_SEED_L 0x00070008
#define CRYPTO4XX_PRNG_SEED_H 0x0007000c
diff --git a/drivers/crypto/amcc/crypto4xx_trng.c b/drivers/crypto/amcc/crypto4xx_trng.c
index 5e63742b0d22..53ab1f140a26 100644
--- a/drivers/crypto/amcc/crypto4xx_trng.c
+++ b/drivers/crypto/amcc/crypto4xx_trng.c
@@ -80,8 +80,10 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
/* Find the TRNG device node and map it */
trng = of_find_matching_node(NULL, ppc4xx_trng_match);
- if (!trng || !of_device_is_available(trng))
+ if (!trng || !of_device_is_available(trng)) {
+ of_node_put(trng);
return;
+ }
dev->trng_base = of_iomap(trng, 0);
of_node_put(trng);
diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h
index 931d22531f51..7bbda51b7337 100644
--- a/drivers/crypto/amcc/crypto4xx_trng.h
+++ b/drivers/crypto/amcc/crypto4xx_trng.h
@@ -26,9 +26,9 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev);
#else
static inline void ppc4xx_trng_probe(
- struct crypto4xx_device *dev __maybe_unused) { }
+ struct crypto4xx_core_device *dev __maybe_unused) { }
static inline void ppc4xx_trng_remove(
- struct crypto4xx_device *dev __maybe_unused) { }
+ struct crypto4xx_core_device *dev __maybe_unused) { }
#endif
#endif
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index 438e1ffb2ec0..65bf1a299562 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -785,7 +785,7 @@ static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
}
err = des_ekey(tmp, key);
- if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c
index f3442c2bdbdc..57e5dca3253f 100644
--- a/drivers/crypto/axis/artpec6_crypto.c
+++ b/drivers/crypto/axis/artpec6_crypto.c
@@ -135,8 +135,6 @@
#define regk_crypto_ext 0x00000001
#define regk_crypto_hmac_sha1 0x00000007
#define regk_crypto_hmac_sha256 0x00000009
-#define regk_crypto_hmac_sha384 0x0000000b
-#define regk_crypto_hmac_sha512 0x0000000d
#define regk_crypto_init 0x00000000
#define regk_crypto_key_128 0x00000000
#define regk_crypto_key_192 0x00000001
@@ -144,8 +142,6 @@
#define regk_crypto_null 0x00000000
#define regk_crypto_sha1 0x00000006
#define regk_crypto_sha256 0x00000008
-#define regk_crypto_sha384 0x0000000a
-#define regk_crypto_sha512 0x0000000c
/* DMA descriptor structures */
struct pdma_descr_ctrl {
@@ -190,8 +186,6 @@ struct pdma_stat_descr {
/* Hash modes (including HMAC variants) */
#define ARTPEC6_CRYPTO_HASH_SHA1 1
#define ARTPEC6_CRYPTO_HASH_SHA256 2
-#define ARTPEC6_CRYPTO_HASH_SHA384 3
-#define ARTPEC6_CRYPTO_HASH_SHA512 4
/* Crypto modes */
#define ARTPEC6_CRYPTO_CIPHER_AES_ECB 1
@@ -284,6 +278,7 @@ enum artpec6_crypto_hash_flags {
struct artpec6_crypto_req_common {
struct list_head list;
+ struct list_head complete_in_progress;
struct artpec6_crypto_dma_descriptors *dma;
struct crypto_async_request *req;
void (*complete)(struct crypto_async_request *req);
@@ -291,11 +286,11 @@ struct artpec6_crypto_req_common {
};
struct artpec6_hash_request_context {
- char partial_buffer[SHA512_BLOCK_SIZE];
- char partial_buffer_out[SHA512_BLOCK_SIZE];
- char key_buffer[SHA512_BLOCK_SIZE];
- char pad_buffer[SHA512_BLOCK_SIZE + 32];
- unsigned char digeststate[SHA512_DIGEST_SIZE];
+ char partial_buffer[SHA256_BLOCK_SIZE];
+ char partial_buffer_out[SHA256_BLOCK_SIZE];
+ char key_buffer[SHA256_BLOCK_SIZE];
+ char pad_buffer[SHA256_BLOCK_SIZE + 32];
+ unsigned char digeststate[SHA256_DIGEST_SIZE];
size_t partial_bytes;
u64 digcnt;
u32 key_md;
@@ -305,8 +300,8 @@ struct artpec6_hash_request_context {
};
struct artpec6_hash_export_state {
- char partial_buffer[SHA512_BLOCK_SIZE];
- unsigned char digeststate[SHA512_DIGEST_SIZE];
+ char partial_buffer[SHA256_BLOCK_SIZE];
+ unsigned char digeststate[SHA256_DIGEST_SIZE];
size_t partial_bytes;
u64 digcnt;
int oper;
@@ -314,7 +309,7 @@ struct artpec6_hash_export_state {
};
struct artpec6_hashalg_context {
- char hmac_key[SHA512_BLOCK_SIZE];
+ char hmac_key[SHA256_BLOCK_SIZE];
size_t hmac_key_length;
struct crypto_shash *child_hash;
};
@@ -670,8 +665,8 @@ artpec6_crypto_dma_map_descs(struct artpec6_crypto_req_common *common)
* to be written.
*/
return artpec6_crypto_dma_map_single(common,
- dma->stat + dma->in_cnt - 1,
- sizeof(dma->stat[0]),
+ dma->stat,
+ sizeof(dma->stat[0]) * dma->in_cnt,
DMA_BIDIRECTIONAL,
&dma->stat_dma_addr);
}
@@ -1315,8 +1310,7 @@ static int artpec6_crypto_prepare_hash(struct ahash_request *areq)
struct artpec6_hashalg_context *ctx = crypto_tfm_ctx(areq->base.tfm);
struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(areq);
size_t digestsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(areq));
- size_t contextsize = digestsize == SHA384_DIGEST_SIZE ?
- SHA512_DIGEST_SIZE : digestsize;
+ size_t contextsize = digestsize;
size_t blocksize = crypto_tfm_alg_blocksize(
crypto_ahash_tfm(crypto_ahash_reqtfm(areq)));
struct artpec6_crypto_req_common *common = &req_ctx->common;
@@ -1456,7 +1450,6 @@ static int artpec6_crypto_prepare_hash(struct ahash_request *areq)
/* Finalize */
if (req_ctx->hash_flags & HASH_FLAG_FINALIZE) {
- bool needtrim = contextsize != digestsize;
size_t hash_pad_len;
u64 digest_bits;
u32 oper;
@@ -1502,19 +1495,10 @@ static int artpec6_crypto_prepare_hash(struct ahash_request *areq)
/* Descriptor for the final result */
error = artpec6_crypto_setup_in_descr(common, areq->result,
digestsize,
- !needtrim);
+ true);
if (error)
return error;
- if (needtrim) {
- /* Discard the extra context bytes for SHA-384 */
- error = artpec6_crypto_setup_in_descr(common,
- req_ctx->partial_buffer,
- digestsize - contextsize, true);
- if (error)
- return error;
- }
-
} else { /* This is not the final operation for this request */
if (!run_hw)
return ARTPEC6_CRYPTO_PREPARE_HASH_NO_START;
@@ -1923,7 +1907,7 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq)
/* For the decryption, cryptlen includes the tag. */
input_length = areq->cryptlen;
if (req_ctx->decrypt)
- input_length -= AES_BLOCK_SIZE;
+ input_length -= crypto_aead_authsize(cipher);
/* Prepare the context buffer */
req_ctx->hw_ctx.aad_length_bits =
@@ -1988,7 +1972,7 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq)
size_t output_len = areq->cryptlen;
if (req_ctx->decrypt)
- output_len -= AES_BLOCK_SIZE;
+ output_len -= crypto_aead_authsize(cipher);
artpec6_crypto_walk_init(&walk, areq->dst);
@@ -2017,19 +2001,32 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq)
* the output ciphertext. For decryption it is put in a context
* buffer for later compare against the input tag.
*/
- count = AES_BLOCK_SIZE;
if (req_ctx->decrypt) {
ret = artpec6_crypto_setup_in_descr(common,
- req_ctx->decryption_tag, count, false);
+ req_ctx->decryption_tag, AES_BLOCK_SIZE, false);
if (ret)
return ret;
} else {
+ /* For encryption the requested tag size may be smaller
+ * than the hardware's generated tag.
+ */
+ size_t authsize = crypto_aead_authsize(cipher);
+
ret = artpec6_crypto_setup_sg_descrs_in(common, &walk,
- count);
+ authsize);
if (ret)
return ret;
+
+ if (authsize < AES_BLOCK_SIZE) {
+ count = AES_BLOCK_SIZE - authsize;
+ ret = artpec6_crypto_setup_in_descr(common,
+ ac->pad_buffer,
+ count, false);
+ if (ret)
+ return ret;
+ }
}
}
@@ -2045,7 +2042,8 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq)
return artpec6_crypto_dma_map_descs(common);
}
-static void artpec6_crypto_process_queue(struct artpec6_crypto *ac)
+static void artpec6_crypto_process_queue(struct artpec6_crypto *ac,
+ struct list_head *completions)
{
struct artpec6_crypto_req_common *req;
@@ -2056,7 +2054,7 @@ static void artpec6_crypto_process_queue(struct artpec6_crypto *ac)
list_move_tail(&req->list, &ac->pending);
artpec6_crypto_start_dma(req);
- req->req->complete(req->req, -EINPROGRESS);
+ list_add_tail(&req->complete_in_progress, completions);
}
/*
@@ -2086,6 +2084,11 @@ static void artpec6_crypto_task(unsigned long data)
struct artpec6_crypto *ac = (struct artpec6_crypto *)data;
struct artpec6_crypto_req_common *req;
struct artpec6_crypto_req_common *n;
+ struct list_head complete_done;
+ struct list_head complete_in_progress;
+
+ INIT_LIST_HEAD(&complete_done);
+ INIT_LIST_HEAD(&complete_in_progress);
if (list_empty(&ac->pending)) {
pr_debug("Spurious IRQ\n");
@@ -2097,9 +2100,12 @@ static void artpec6_crypto_task(unsigned long data)
list_for_each_entry_safe(req, n, &ac->pending, list) {
struct artpec6_crypto_dma_descriptors *dma = req->dma;
u32 stat;
+ dma_addr_t stataddr;
- dma_sync_single_for_cpu(artpec6_crypto_dev, dma->stat_dma_addr,
- sizeof(dma->stat[0]),
+ stataddr = dma->stat_dma_addr + 4 * (req->dma->in_cnt - 1);
+ dma_sync_single_for_cpu(artpec6_crypto_dev,
+ stataddr,
+ 4,
DMA_BIDIRECTIONAL);
stat = req->dma->stat[req->dma->in_cnt-1];
@@ -2119,19 +2125,30 @@ static void artpec6_crypto_task(unsigned long data)
pr_debug("Completing request %p\n", req);
- list_del(&req->list);
+ list_move_tail(&req->list, &complete_done);
+ ac->pending_count--;
+ }
+
+ artpec6_crypto_process_queue(ac, &complete_in_progress);
+
+ spin_unlock_bh(&ac->queue_lock);
+
+ /* Perform the completion callbacks without holding the queue lock
+ * to allow new request submissions from the callbacks.
+ */
+ list_for_each_entry_safe(req, n, &complete_done, list) {
artpec6_crypto_dma_unmap_all(req);
artpec6_crypto_copy_bounce_buffers(req);
-
- ac->pending_count--;
artpec6_crypto_common_destroy(req);
+
req->complete(req->req);
}
- artpec6_crypto_process_queue(ac);
-
- spin_unlock_bh(&ac->queue_lock);
+ list_for_each_entry_safe(req, n, &complete_in_progress,
+ complete_in_progress) {
+ req->req->complete(req->req, -EINPROGRESS);
+ }
}
static void artpec6_crypto_complete_crypto(struct crypto_async_request *req)
@@ -2170,27 +2187,29 @@ static void artpec6_crypto_complete_aead(struct crypto_async_request *req)
/* Verify GCM hashtag. */
struct aead_request *areq = container_of(req,
struct aead_request, base);
+ struct crypto_aead *aead = crypto_aead_reqtfm(areq);
struct artpec6_crypto_aead_req_ctx *req_ctx = aead_request_ctx(areq);
if (req_ctx->decrypt) {
u8 input_tag[AES_BLOCK_SIZE];
+ unsigned int authsize = crypto_aead_authsize(aead);
sg_pcopy_to_buffer(areq->src,
sg_nents(areq->src),
input_tag,
- AES_BLOCK_SIZE,
+ authsize,
areq->assoclen + areq->cryptlen -
- AES_BLOCK_SIZE);
+ authsize);
- if (memcmp(req_ctx->decryption_tag,
- input_tag,
- AES_BLOCK_SIZE)) {
+ if (crypto_memneq(req_ctx->decryption_tag,
+ input_tag,
+ authsize)) {
pr_debug("***EBADMSG:\n");
print_hex_dump_debug("ref:", DUMP_PREFIX_ADDRESS, 32, 1,
- input_tag, AES_BLOCK_SIZE, true);
+ input_tag, authsize, true);
print_hex_dump_debug("out:", DUMP_PREFIX_ADDRESS, 32, 1,
req_ctx->decryption_tag,
- AES_BLOCK_SIZE, true);
+ authsize, true);
result = -EBADMSG;
}
@@ -2266,13 +2285,6 @@ artpec6_crypto_init_hash(struct ahash_request *req, u8 type, int hmac)
case ARTPEC6_CRYPTO_HASH_SHA256:
oper = hmac ? regk_crypto_hmac_sha256 : regk_crypto_sha256;
break;
- case ARTPEC6_CRYPTO_HASH_SHA384:
- oper = hmac ? regk_crypto_hmac_sha384 : regk_crypto_sha384;
- break;
- case ARTPEC6_CRYPTO_HASH_SHA512:
- oper = hmac ? regk_crypto_hmac_sha512 : regk_crypto_sha512;
- break;
-
default:
pr_err("%s: Unsupported hash type 0x%x\n", MODULE_NAME, type);
return -EINVAL;
@@ -2368,53 +2380,11 @@ static int artpec6_crypto_sha256_digest(struct ahash_request *req)
return artpec6_crypto_prepare_submit_hash(req);
}
-static int __maybe_unused artpec6_crypto_sha384_init(struct ahash_request *req)
-{
- return artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA384, 0);
-}
-
-static int __maybe_unused
-artpec6_crypto_sha384_digest(struct ahash_request *req)
-{
- struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(req);
-
- artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA384, 0);
- req_ctx->hash_flags |= HASH_FLAG_UPDATE | HASH_FLAG_FINALIZE;
-
- return artpec6_crypto_prepare_submit_hash(req);
-}
-
-static int artpec6_crypto_sha512_init(struct ahash_request *req)
-{
- return artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA512, 0);
-}
-
-static int artpec6_crypto_sha512_digest(struct ahash_request *req)
-{
- struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(req);
-
- artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA512, 0);
- req_ctx->hash_flags |= HASH_FLAG_UPDATE | HASH_FLAG_FINALIZE;
-
- return artpec6_crypto_prepare_submit_hash(req);
-}
-
static int artpec6_crypto_hmac_sha256_init(struct ahash_request *req)
{
return artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA256, 1);
}
-static int __maybe_unused
-artpec6_crypto_hmac_sha384_init(struct ahash_request *req)
-{
- return artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA384, 1);
-}
-
-static int artpec6_crypto_hmac_sha512_init(struct ahash_request *req)
-{
- return artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA512, 1);
-}
-
static int artpec6_crypto_hmac_sha256_digest(struct ahash_request *req)
{
struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(req);
@@ -2425,27 +2395,6 @@ static int artpec6_crypto_hmac_sha256_digest(struct ahash_request *req)
return artpec6_crypto_prepare_submit_hash(req);
}
-static int __maybe_unused
-artpec6_crypto_hmac_sha384_digest(struct ahash_request *req)
-{
- struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(req);
-
- artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA384, 1);
- req_ctx->hash_flags |= HASH_FLAG_UPDATE | HASH_FLAG_FINALIZE;
-
- return artpec6_crypto_prepare_submit_hash(req);
-}
-
-static int artpec6_crypto_hmac_sha512_digest(struct ahash_request *req)
-{
- struct artpec6_hash_request_context *req_ctx = ahash_request_ctx(req);
-
- artpec6_crypto_init_hash(req, ARTPEC6_CRYPTO_HASH_SHA512, 1);
- req_ctx->hash_flags |= HASH_FLAG_UPDATE | HASH_FLAG_FINALIZE;
-
- return artpec6_crypto_prepare_submit_hash(req);
-}
-
static int artpec6_crypto_ahash_init_common(struct crypto_tfm *tfm,
const char *base_hash_name)
{
@@ -2480,17 +2429,6 @@ static int artpec6_crypto_ahash_init_hmac_sha256(struct crypto_tfm *tfm)
return artpec6_crypto_ahash_init_common(tfm, "sha256");
}
-static int __maybe_unused
-artpec6_crypto_ahash_init_hmac_sha384(struct crypto_tfm *tfm)
-{
- return artpec6_crypto_ahash_init_common(tfm, "sha384");
-}
-
-static int artpec6_crypto_ahash_init_hmac_sha512(struct crypto_tfm *tfm)
-{
- return artpec6_crypto_ahash_init_common(tfm, "sha512");
-}
-
static void artpec6_crypto_ahash_exit(struct crypto_tfm *tfm)
{
struct artpec6_hashalg_context *tfm_ctx = crypto_tfm_ctx(tfm);
@@ -2761,103 +2699,6 @@ static struct ahash_alg hash_algos[] = {
},
};
-static struct ahash_alg artpec7_hash_algos[] = {
- /* SHA-384 */
- {
- .init = artpec6_crypto_sha384_init,
- .update = artpec6_crypto_hash_update,
- .final = artpec6_crypto_hash_final,
- .digest = artpec6_crypto_sha384_digest,
- .import = artpec6_crypto_hash_import,
- .export = artpec6_crypto_hash_export,
- .halg.digestsize = SHA384_DIGEST_SIZE,
- .halg.statesize = sizeof(struct artpec6_hash_export_state),
- .halg.base = {
- .cra_name = "sha384",
- .cra_driver_name = "artpec-sha384",
- .cra_priority = 300,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = SHA384_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_init = artpec6_crypto_ahash_init,
- .cra_exit = artpec6_crypto_ahash_exit,
- }
- },
- /* HMAC SHA-384 */
- {
- .init = artpec6_crypto_hmac_sha384_init,
- .update = artpec6_crypto_hash_update,
- .final = artpec6_crypto_hash_final,
- .digest = artpec6_crypto_hmac_sha384_digest,
- .import = artpec6_crypto_hash_import,
- .export = artpec6_crypto_hash_export,
- .setkey = artpec6_crypto_hash_set_key,
- .halg.digestsize = SHA384_DIGEST_SIZE,
- .halg.statesize = sizeof(struct artpec6_hash_export_state),
- .halg.base = {
- .cra_name = "hmac(sha384)",
- .cra_driver_name = "artpec-hmac-sha384",
- .cra_priority = 300,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = SHA384_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_init = artpec6_crypto_ahash_init_hmac_sha384,
- .cra_exit = artpec6_crypto_ahash_exit,
- }
- },
- /* SHA-512 */
- {
- .init = artpec6_crypto_sha512_init,
- .update = artpec6_crypto_hash_update,
- .final = artpec6_crypto_hash_final,
- .digest = artpec6_crypto_sha512_digest,
- .import = artpec6_crypto_hash_import,
- .export = artpec6_crypto_hash_export,
- .halg.digestsize = SHA512_DIGEST_SIZE,
- .halg.statesize = sizeof(struct artpec6_hash_export_state),
- .halg.base = {
- .cra_name = "sha512",
- .cra_driver_name = "artpec-sha512",
- .cra_priority = 300,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = SHA512_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_init = artpec6_crypto_ahash_init,
- .cra_exit = artpec6_crypto_ahash_exit,
- }
- },
- /* HMAC SHA-512 */
- {
- .init = artpec6_crypto_hmac_sha512_init,
- .update = artpec6_crypto_hash_update,
- .final = artpec6_crypto_hash_final,
- .digest = artpec6_crypto_hmac_sha512_digest,
- .import = artpec6_crypto_hash_import,
- .export = artpec6_crypto_hash_export,
- .setkey = artpec6_crypto_hash_set_key,
- .halg.digestsize = SHA512_DIGEST_SIZE,
- .halg.statesize = sizeof(struct artpec6_hash_export_state),
- .halg.base = {
- .cra_name = "hmac(sha512)",
- .cra_driver_name = "artpec-hmac-sha512",
- .cra_priority = 300,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = SHA512_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_init = artpec6_crypto_ahash_init_hmac_sha512,
- .cra_exit = artpec6_crypto_ahash_exit,
- }
- },
-};
-
/* Crypto */
static struct skcipher_alg crypto_algos[] = {
/* AES - ECB */
@@ -2984,12 +2825,6 @@ static void artpec6_crypto_init_debugfs(void)
{
dbgfs_root = debugfs_create_dir("artpec6_crypto", NULL);
- if (!dbgfs_root || IS_ERR(dbgfs_root)) {
- dbgfs_root = NULL;
- pr_err("%s: Could not initialise debugfs!\n", MODULE_NAME);
- return;
- }
-
#ifdef CONFIG_FAULT_INJECTION
fault_create_debugfs_attr("fail_status_read", dbgfs_root,
&artpec6_crypto_fail_status_read);
@@ -3001,9 +2836,6 @@ static void artpec6_crypto_init_debugfs(void)
static void artpec6_crypto_free_debugfs(void)
{
- if (!dbgfs_root)
- return;
-
debugfs_remove_recursive(dbgfs_root);
dbgfs_root = NULL;
}
@@ -3104,19 +2936,10 @@ static int artpec6_crypto_probe(struct platform_device *pdev)
goto disable_hw;
}
- if (variant != ARTPEC6_CRYPTO) {
- err = crypto_register_ahashes(artpec7_hash_algos,
- ARRAY_SIZE(artpec7_hash_algos));
- if (err) {
- dev_err(dev, "Failed to register ahashes\n");
- goto unregister_ahashes;
- }
- }
-
err = crypto_register_skciphers(crypto_algos, ARRAY_SIZE(crypto_algos));
if (err) {
dev_err(dev, "Failed to register ciphers\n");
- goto unregister_a7_ahashes;
+ goto unregister_ahashes;
}
err = crypto_register_aeads(aead_algos, ARRAY_SIZE(aead_algos));
@@ -3129,10 +2952,6 @@ static int artpec6_crypto_probe(struct platform_device *pdev)
unregister_algs:
crypto_unregister_skciphers(crypto_algos, ARRAY_SIZE(crypto_algos));
-unregister_a7_ahashes:
- if (variant != ARTPEC6_CRYPTO)
- crypto_unregister_ahashes(artpec7_hash_algos,
- ARRAY_SIZE(artpec7_hash_algos));
unregister_ahashes:
crypto_unregister_ahashes(hash_algos, ARRAY_SIZE(hash_algos));
disable_hw:
@@ -3148,9 +2967,6 @@ static int artpec6_crypto_remove(struct platform_device *pdev)
int irq = platform_get_irq(pdev, 0);
crypto_unregister_ahashes(hash_algos, ARRAY_SIZE(hash_algos));
- if (ac->variant != ARTPEC6_CRYPTO)
- crypto_unregister_ahashes(artpec7_hash_algos,
- ARRAY_SIZE(artpec7_hash_algos));
crypto_unregister_skciphers(crypto_algos, ARRAY_SIZE(crypto_algos));
crypto_unregister_aeads(aead_algos, ARRAY_SIZE(aead_algos));
diff --git a/drivers/crypto/bcm/Makefile b/drivers/crypto/bcm/Makefile
index 13cb80eb2665..7469e19afe85 100644
--- a/drivers/crypto/bcm/Makefile
+++ b/drivers/crypto/bcm/Makefile
@@ -11,5 +11,3 @@
obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) := bcm_crypto_spu.o
bcm_crypto_spu-objs := util.o spu.o spu2.o cipher.o
-
-ccflags-y += -I. -DBCMDRIVER
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c
index c9393ffb70ed..28f592f7e1b7 100644
--- a/drivers/crypto/bcm/cipher.c
+++ b/drivers/crypto/bcm/cipher.c
@@ -717,7 +717,7 @@ static int handle_ahash_req(struct iproc_reqctx_s *rctx)
*/
unsigned int new_data_len;
- unsigned int chunk_start = 0;
+ unsigned int __maybe_unused chunk_start = 0;
u32 db_size; /* Length of data field, incl gcm and hash padding */
int pad_len = 0; /* total pad len, including gcm, hash, stat padding */
u32 data_pad_len = 0; /* length of GCM/CCM padding */
@@ -1675,8 +1675,6 @@ static void spu_rx_callback(struct mbox_client *cl, void *msg)
struct spu_hw *spu = &iproc_priv.spu;
struct brcm_message *mssg = msg;
struct iproc_reqctx_s *rctx;
- struct iproc_ctx_s *ctx;
- struct crypto_async_request *areq;
int err = 0;
rctx = mssg->ctx;
@@ -1686,8 +1684,6 @@ static void spu_rx_callback(struct mbox_client *cl, void *msg)
err = -EFAULT;
goto cb_finish;
}
- areq = rctx->parent;
- ctx = rctx->ctx;
/* process the SPU status */
err = spu->spu_status_process(rctx->msg_buf.rx_stat);
@@ -1822,7 +1818,7 @@ static int des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
if (keylen == DES_KEY_SIZE) {
if (des_ekey(tmp, key) == 0) {
if (crypto_ablkcipher_get_flags(cipher) &
- CRYPTO_TFM_REQ_WEAK_KEY) {
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) {
u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
crypto_ablkcipher_set_flags(cipher, flags);
@@ -2845,44 +2841,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
struct spu_hw *spu = &iproc_priv.spu;
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
- struct rtattr *rta = (void *)key;
- struct crypto_authenc_key_param *param;
- const u8 *origkey = key;
- const unsigned int origkeylen = keylen;
-
- int ret = 0;
+ struct crypto_authenc_keys keys;
+ int ret;
flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
keylen);
flow_dump(" key: ", key, keylen);
- if (!RTA_OK(rta, keylen))
- goto badkey;
- if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
- goto badkey;
- if (RTA_PAYLOAD(rta) < sizeof(*param))
+ ret = crypto_authenc_extractkeys(&keys, key, keylen);
+ if (ret)
goto badkey;
- param = RTA_DATA(rta);
- ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
- key += RTA_ALIGN(rta->rta_len);
- keylen -= RTA_ALIGN(rta->rta_len);
-
- if (keylen < ctx->enckeylen)
- goto badkey;
- if (ctx->enckeylen > MAX_KEY_SIZE)
+ if (keys.enckeylen > MAX_KEY_SIZE ||
+ keys.authkeylen > MAX_KEY_SIZE)
goto badkey;
- ctx->authkeylen = keylen - ctx->enckeylen;
-
- if (ctx->authkeylen > MAX_KEY_SIZE)
- goto badkey;
+ ctx->enckeylen = keys.enckeylen;
+ ctx->authkeylen = keys.authkeylen;
- memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+ memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
/* May end up padding auth key. So make sure it's zeroed. */
memset(ctx->authkey, 0, sizeof(ctx->authkey));
- memcpy(ctx->authkey, key, ctx->authkeylen);
+ memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
switch (ctx->alg->cipher_info.alg) {
case CIPHER_ALG_DES:
@@ -2890,9 +2870,9 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
u32 tmp[DES_EXPKEY_WORDS];
u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
- if (des_ekey(tmp, key) == 0) {
+ if (des_ekey(tmp, keys.enckey) == 0) {
if (crypto_aead_get_flags(cipher) &
- CRYPTO_TFM_REQ_WEAK_KEY) {
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) {
crypto_aead_set_flags(cipher, flags);
return -EINVAL;
}
@@ -2905,7 +2885,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
break;
case CIPHER_ALG_3DES:
if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
- const u32 *K = (const u32 *)key;
+ const u32 *K = (const u32 *)keys.enckey;
u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2956,9 +2936,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
ctx->fallback_cipher->base.crt_flags |=
tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
- ret =
- crypto_aead_setkey(ctx->fallback_cipher, origkey,
- origkeylen);
+ ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
if (ret) {
flow_log(" fallback setkey() returned:%d\n", ret);
tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
diff --git a/drivers/crypto/bcm/cipher.h b/drivers/crypto/bcm/cipher.h
index 763c425c41ca..f6da49758954 100644
--- a/drivers/crypto/bcm/cipher.h
+++ b/drivers/crypto/bcm/cipher.h
@@ -23,6 +23,7 @@
#include <crypto/aes.h>
#include <crypto/internal/hash.h>
#include <crypto/aead.h>
+#include <crypto/arc4.h>
#include <crypto/gcm.h>
#include <crypto/sha.h>
#include <crypto/sha3.h>
@@ -34,9 +35,6 @@
/* Driver supports up to MAX_SPUS SPU blocks */
#define MAX_SPUS 16
-#define ARC4_MIN_KEY_SIZE 1
-#define ARC4_MAX_KEY_SIZE 256
-#define ARC4_BLOCK_SIZE 1
#define ARC4_STATE_SIZE 4
#define CCM_AES_IV_SIZE 16
diff --git a/drivers/crypto/bcm/util.c b/drivers/crypto/bcm/util.c
index a912c6ad3e85..d8cda5fb75ad 100644
--- a/drivers/crypto/bcm/util.c
+++ b/drivers/crypto/bcm/util.c
@@ -201,46 +201,6 @@ struct sdesc {
char ctx[];
};
-/* do a synchronous decrypt operation */
-int do_decrypt(char *alg_name,
- void *key_ptr, unsigned int key_len,
- void *iv_ptr, void *src_ptr, void *dst_ptr,
- unsigned int block_len)
-{
- struct scatterlist sg_in[1], sg_out[1];
- struct crypto_blkcipher *tfm =
- crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
- struct blkcipher_desc desc = {.tfm = tfm, .flags = 0 };
- int ret = 0;
- void *iv;
- int ivsize;
-
- flow_log("%s() name:%s block_len:%u\n", __func__, alg_name, block_len);
-
- if (IS_ERR(tfm))
- return PTR_ERR(tfm);
-
- crypto_blkcipher_setkey((void *)tfm, key_ptr, key_len);
-
- sg_init_table(sg_in, 1);
- sg_set_buf(sg_in, src_ptr, block_len);
-
- sg_init_table(sg_out, 1);
- sg_set_buf(sg_out, dst_ptr, block_len);
-
- iv = crypto_blkcipher_crt(tfm)->iv;
- ivsize = crypto_blkcipher_ivsize(tfm);
- memcpy(iv, iv_ptr, ivsize);
-
- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, block_len);
- crypto_free_blkcipher(tfm);
-
- if (ret < 0)
- pr_err("aes_decrypt failed %d\n", ret);
-
- return ret;
-}
-
/**
* do_shash() - Do a synchronous hash operation in software
* @name: The name of the hash algorithm
diff --git a/drivers/crypto/bcm/util.h b/drivers/crypto/bcm/util.h
index 712e029795f8..15c60356518a 100644
--- a/drivers/crypto/bcm/util.h
+++ b/drivers/crypto/bcm/util.h
@@ -95,12 +95,6 @@ u32 spu_msg_sg_add(struct scatterlist **to_sg,
void add_to_ctr(u8 *ctr_pos, unsigned int increment);
-/* do a synchronous decrypt operation */
-int do_decrypt(char *alg_name,
- void *key_ptr, unsigned int key_len,
- void *iv_ptr, void *src_ptr, void *dst_ptr,
- unsigned int block_len);
-
/* produce a message digest from data of length n bytes */
int do_shash(unsigned char *name, unsigned char *result,
const u8 *data1, unsigned int data1_len,
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index c4b1cade55c1..577c9844b322 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -91,6 +91,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
select CRYPTO_AEAD
select CRYPTO_AUTHENC
select CRYPTO_BLKCIPHER
+ select CRYPTO_DES
help
Selecting this will offload crypto for users of the
scatterlist crypto API (such as the linux native IPSec
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 92e593e2069a..9eac5099098e 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -3,7 +3,7 @@
* caam - Freescale FSL CAAM support for crypto API
*
* Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2016-2018 NXP
+ * Copyright 2016-2019 NXP
*
* Based on talitos crypto API driver.
*
@@ -766,6 +766,27 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key,
return 0;
}
+static int des_skcipher_setkey(struct crypto_skcipher *skcipher,
+ const u8 *key, unsigned int keylen)
+{
+ u32 tmp[DES3_EDE_EXPKEY_WORDS];
+ struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
+
+ if (keylen == DES3_EDE_KEY_SIZE &&
+ __des3_ede_setkey(tmp, &tfm->crt_flags, key, DES3_EDE_KEY_SIZE)) {
+ return -EINVAL;
+ }
+
+ if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) &
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
+ crypto_skcipher_set_flags(skcipher,
+ CRYPTO_TFM_RES_WEAK_KEY);
+ return -EINVAL;
+ }
+
+ return skcipher_setkey(skcipher, key, keylen);
+}
+
static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key,
unsigned int keylen)
{
@@ -802,6 +823,8 @@ static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key,
* aead_edesc - s/w-extended aead descriptor
* @src_nents: number of segments in input s/w scatterlist
* @dst_nents: number of segments in output s/w scatterlist
+ * @mapped_src_nents: number of segments in input h/w link table
+ * @mapped_dst_nents: number of segments in output h/w link table
* @sec4_sg_bytes: length of dma mapped sec4_sg space
* @sec4_sg_dma: bus physical mapped address of h/w link table
* @sec4_sg: pointer to h/w link table
@@ -810,6 +833,8 @@ static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key,
struct aead_edesc {
int src_nents;
int dst_nents;
+ int mapped_src_nents;
+ int mapped_dst_nents;
int sec4_sg_bytes;
dma_addr_t sec4_sg_dma;
struct sec4_sg_entry *sec4_sg;
@@ -820,6 +845,8 @@ struct aead_edesc {
* skcipher_edesc - s/w-extended skcipher descriptor
* @src_nents: number of segments in input s/w scatterlist
* @dst_nents: number of segments in output s/w scatterlist
+ * @mapped_src_nents: number of segments in input h/w link table
+ * @mapped_dst_nents: number of segments in output h/w link table
* @iv_dma: dma address of iv for checking continuity and link table
* @sec4_sg_bytes: length of dma mapped sec4_sg space
* @sec4_sg_dma: bus physical mapped address of h/w link table
@@ -830,6 +857,8 @@ struct aead_edesc {
struct skcipher_edesc {
int src_nents;
int dst_nents;
+ int mapped_src_nents;
+ int mapped_dst_nents;
dma_addr_t iv_dma;
int sec4_sg_bytes;
dma_addr_t sec4_sg_dma;
@@ -846,7 +875,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) {
if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
- dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+ if (dst_nents)
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
} else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
}
@@ -961,8 +991,9 @@ static void skcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
* The crypto API expects us to set the IV (req->iv) to the last
* ciphertext block. This is used e.g. by the CTS mode.
*/
- scatterwalk_map_and_copy(req->iv, req->dst, req->cryptlen - ivsize,
- ivsize, 0);
+ if (ivsize)
+ scatterwalk_map_and_copy(req->iv, req->dst, req->cryptlen -
+ ivsize, ivsize, 0);
kfree(edesc);
@@ -1023,11 +1054,12 @@ static void init_aead_job(struct aead_request *req,
init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
if (all_contig) {
- src_dma = edesc->src_nents ? sg_dma_address(req->src) : 0;
+ src_dma = edesc->mapped_src_nents ? sg_dma_address(req->src) :
+ 0;
in_options = 0;
} else {
src_dma = edesc->sec4_sg_dma;
- sec4_sg_index += edesc->src_nents;
+ sec4_sg_index += edesc->mapped_src_nents;
in_options = LDST_SGF;
}
@@ -1038,8 +1070,11 @@ static void init_aead_job(struct aead_request *req,
out_options = in_options;
if (unlikely(req->src != req->dst)) {
- if (edesc->dst_nents == 1) {
+ if (!edesc->mapped_dst_nents) {
+ dst_dma = 0;
+ } else if (edesc->mapped_dst_nents == 1) {
dst_dma = sg_dma_address(req->dst);
+ out_options = 0;
} else {
dst_dma = edesc->sec4_sg_dma +
sec4_sg_index *
@@ -1183,9 +1218,9 @@ static void init_skcipher_job(struct skcipher_request *req,
int ivsize = crypto_skcipher_ivsize(skcipher);
u32 *desc = edesc->hw_desc;
u32 *sh_desc;
- u32 out_options = 0;
- dma_addr_t dst_dma, ptr;
- int len;
+ u32 in_options = 0, out_options = 0;
+ dma_addr_t src_dma, dst_dma, ptr;
+ int len, sec4_sg_index = 0;
#ifdef DEBUG
print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
@@ -1203,21 +1238,27 @@ static void init_skcipher_job(struct skcipher_request *req,
len = desc_len(sh_desc);
init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
- append_seq_in_ptr(desc, edesc->sec4_sg_dma, req->cryptlen + ivsize,
- LDST_SGF);
+ if (ivsize || edesc->mapped_src_nents > 1) {
+ src_dma = edesc->sec4_sg_dma;
+ sec4_sg_index = edesc->mapped_src_nents + !!ivsize;
+ in_options = LDST_SGF;
+ } else {
+ src_dma = sg_dma_address(req->src);
+ }
+
+ append_seq_in_ptr(desc, src_dma, req->cryptlen + ivsize, in_options);
if (likely(req->src == req->dst)) {
- dst_dma = edesc->sec4_sg_dma + sizeof(struct sec4_sg_entry);
- out_options = LDST_SGF;
+ dst_dma = src_dma + !!ivsize * sizeof(struct sec4_sg_entry);
+ out_options = in_options;
+ } else if (edesc->mapped_dst_nents == 1) {
+ dst_dma = sg_dma_address(req->dst);
} else {
- if (edesc->dst_nents == 1) {
- dst_dma = sg_dma_address(req->dst);
- } else {
- dst_dma = edesc->sec4_sg_dma + (edesc->src_nents + 1) *
- sizeof(struct sec4_sg_entry);
- out_options = LDST_SGF;
- }
+ dst_dma = edesc->sec4_sg_dma + sec4_sg_index *
+ sizeof(struct sec4_sg_entry);
+ out_options = LDST_SGF;
}
+
append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
}
@@ -1289,12 +1330,19 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
mapped_src_nents = 0;
}
- mapped_dst_nents = dma_map_sg(jrdev, req->dst, dst_nents,
- DMA_FROM_DEVICE);
- if (unlikely(!mapped_dst_nents)) {
- dev_err(jrdev, "unable to map destination\n");
- dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
- return ERR_PTR(-ENOMEM);
+ /* Cover also the case of null (zero length) output data */
+ if (dst_nents) {
+ mapped_dst_nents = dma_map_sg(jrdev, req->dst,
+ dst_nents,
+ DMA_FROM_DEVICE);
+ if (unlikely(!mapped_dst_nents)) {
+ dev_err(jrdev, "unable to map destination\n");
+ dma_unmap_sg(jrdev, req->src, src_nents,
+ DMA_TO_DEVICE);
+ return ERR_PTR(-ENOMEM);
+ }
+ } else {
+ mapped_dst_nents = 0;
}
}
@@ -1313,6 +1361,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
edesc->src_nents = src_nents;
edesc->dst_nents = dst_nents;
+ edesc->mapped_src_nents = mapped_src_nents;
+ edesc->mapped_dst_nents = mapped_dst_nents;
edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
desc_bytes;
*all_contig_ptr = !(mapped_src_nents > 1);
@@ -1586,7 +1636,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
GFP_KERNEL : GFP_ATOMIC;
int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0;
struct skcipher_edesc *edesc;
- dma_addr_t iv_dma;
+ dma_addr_t iv_dma = 0;
u8 *iv;
int ivsize = crypto_skcipher_ivsize(skcipher);
int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes;
@@ -1621,7 +1671,6 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
dev_err(jrdev, "unable to map source\n");
return ERR_PTR(-ENOMEM);
}
-
mapped_dst_nents = dma_map_sg(jrdev, req->dst, dst_nents,
DMA_FROM_DEVICE);
if (unlikely(!mapped_dst_nents)) {
@@ -1631,7 +1680,10 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
}
}
- sec4_sg_ents = 1 + mapped_src_nents;
+ if (!ivsize && mapped_src_nents == 1)
+ sec4_sg_ents = 0; // no need for an input hw s/g table
+ else
+ sec4_sg_ents = mapped_src_nents + !!ivsize;
dst_sg_idx = sec4_sg_ents;
sec4_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0;
sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry);
@@ -1650,39 +1702,48 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
edesc->src_nents = src_nents;
edesc->dst_nents = dst_nents;
+ edesc->mapped_src_nents = mapped_src_nents;
+ edesc->mapped_dst_nents = mapped_dst_nents;
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (struct sec4_sg_entry *)((u8 *)edesc->hw_desc +
desc_bytes);
/* Make sure IV is located in a DMAable area */
- iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes;
- memcpy(iv, req->iv, ivsize);
+ if (ivsize) {
+ iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes;
+ memcpy(iv, req->iv, ivsize);
+
+ iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ caam_unmap(jrdev, req->src, req->dst, src_nents,
+ dst_nents, 0, 0, 0, 0);
+ kfree(edesc);
+ return ERR_PTR(-ENOMEM);
+ }
- iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, iv_dma)) {
- dev_err(jrdev, "unable to map IV\n");
- caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
- 0, 0, 0);
- kfree(edesc);
- return ERR_PTR(-ENOMEM);
+ dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
}
-
- dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
- sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg + 1, 0);
+ if (dst_sg_idx)
+ sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg +
+ !!ivsize, 0);
if (mapped_dst_nents > 1) {
sg_to_sec4_sg_last(req->dst, mapped_dst_nents,
edesc->sec4_sg + dst_sg_idx, 0);
}
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
- dev_err(jrdev, "unable to map S/G table\n");
- caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
- iv_dma, ivsize, 0, 0);
- kfree(edesc);
- return ERR_PTR(-ENOMEM);
+ if (sec4_sg_bytes) {
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ caam_unmap(jrdev, req->src, req->dst, src_nents,
+ dst_nents, iv_dma, ivsize, 0, 0);
+ kfree(edesc);
+ return ERR_PTR(-ENOMEM);
+ }
}
edesc->iv_dma = iv_dma;
@@ -1749,8 +1810,9 @@ static int skcipher_decrypt(struct skcipher_request *req)
* The crypto API expects us to set the IV (req->iv) to the last
* ciphertext block.
*/
- scatterwalk_map_and_copy(req->iv, req->src, req->cryptlen - ivsize,
- ivsize, 0);
+ if (ivsize)
+ scatterwalk_map_and_copy(req->iv, req->src, req->cryptlen -
+ ivsize, ivsize, 0);
/* Create and submit job descriptor*/
init_skcipher_job(req, edesc, false);
@@ -1796,7 +1858,7 @@ static struct caam_skcipher_alg driver_algs[] = {
.cra_driver_name = "cbc-3des-caam",
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
},
- .setkey = skcipher_setkey,
+ .setkey = des_skcipher_setkey,
.encrypt = skcipher_encrypt,
.decrypt = skcipher_decrypt,
.min_keysize = DES3_EDE_KEY_SIZE,
@@ -1812,7 +1874,7 @@ static struct caam_skcipher_alg driver_algs[] = {
.cra_driver_name = "cbc-des-caam",
.cra_blocksize = DES_BLOCK_SIZE,
},
- .setkey = skcipher_setkey,
+ .setkey = des_skcipher_setkey,
.encrypt = skcipher_encrypt,
.decrypt = skcipher_decrypt,
.min_keysize = DES_KEY_SIZE,
@@ -1878,6 +1940,66 @@ static struct caam_skcipher_alg driver_algs[] = {
},
.caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XTS,
},
+ {
+ .skcipher = {
+ .base = {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-caam",
+ .cra_blocksize = DES_BLOCK_SIZE,
+ },
+ .setkey = des_skcipher_setkey,
+ .encrypt = skcipher_encrypt,
+ .decrypt = skcipher_decrypt,
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ },
+ .caam.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_ECB,
+ },
+ {
+ .skcipher = {
+ .base = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-caam",
+ .cra_blocksize = AES_BLOCK_SIZE,
+ },
+ .setkey = skcipher_setkey,
+ .encrypt = skcipher_encrypt,
+ .decrypt = skcipher_decrypt,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ },
+ .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_ECB,
+ },
+ {
+ .skcipher = {
+ .base = {
+ .cra_name = "ecb(des3_ede)",
+ .cra_driver_name = "ecb-des3-caam",
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ },
+ .setkey = des_skcipher_setkey,
+ .encrypt = skcipher_encrypt,
+ .decrypt = skcipher_decrypt,
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ },
+ .caam.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_ECB,
+ },
+ {
+ .skcipher = {
+ .base = {
+ .cra_name = "ecb(arc4)",
+ .cra_driver_name = "ecb-arc4-caam",
+ .cra_blocksize = ARC4_BLOCK_SIZE,
+ },
+ .setkey = skcipher_setkey,
+ .encrypt = skcipher_encrypt,
+ .decrypt = skcipher_decrypt,
+ .min_keysize = ARC4_MIN_KEY_SIZE,
+ .max_keysize = ARC4_MAX_KEY_SIZE,
+ },
+ .caam.class1_alg_type = OP_ALG_ALGSEL_ARC4 | OP_ALG_AAI_ECB,
+ },
};
static struct caam_aead_alg driver_aeads[] = {
@@ -3337,6 +3459,7 @@ static int __init caam_algapi_init(void)
struct caam_drv_private *priv;
int i = 0, err = 0;
u32 aes_vid, aes_inst, des_inst, md_vid, md_inst, ccha_inst, ptha_inst;
+ u32 arc4_inst;
unsigned int md_limit = SHA512_DIGEST_SIZE;
bool registered = false;
@@ -3381,6 +3504,8 @@ static int __init caam_algapi_init(void)
CHA_ID_LS_DES_SHIFT;
aes_inst = cha_inst & CHA_ID_LS_AES_MASK;
md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
+ arc4_inst = (cha_inst & CHA_ID_LS_ARC4_MASK) >>
+ CHA_ID_LS_ARC4_SHIFT;
ccha_inst = 0;
ptha_inst = 0;
} else {
@@ -3397,6 +3522,7 @@ static int __init caam_algapi_init(void)
md_inst = mdha & CHA_VER_NUM_MASK;
ccha_inst = rd_reg32(&priv->ctrl->vreg.ccha) & CHA_VER_NUM_MASK;
ptha_inst = rd_reg32(&priv->ctrl->vreg.ptha) & CHA_VER_NUM_MASK;
+ arc4_inst = rd_reg32(&priv->ctrl->vreg.afha) & CHA_VER_NUM_MASK;
}
/* If MD is present, limit digest size based on LP256 */
@@ -3417,6 +3543,10 @@ static int __init caam_algapi_init(void)
if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
continue;
+ /* Skip ARC4 algorithms if not supported by device */
+ if (!arc4_inst && alg_sel == OP_ALG_ALGSEL_ARC4)
+ continue;
+
/*
* Check support for AES modes not available
* on LP devices.
@@ -3476,7 +3606,7 @@ static int __init caam_algapi_init(void)
* Skip algorithms requiring message digests
* if MD or MD size is not supported by device.
*/
- if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
+ if (is_mdha(c2_alg_sel) &&
(!md_inst || t_alg->aead.maxauthsize > md_limit))
continue;
diff --git a/drivers/crypto/caam/caamalg_desc.c b/drivers/crypto/caam/caamalg_desc.c
index 7db1640d3577..1e1a376edc2f 100644
--- a/drivers/crypto/caam/caamalg_desc.c
+++ b/drivers/crypto/caam/caamalg_desc.c
@@ -2,7 +2,7 @@
/*
* Shared descriptors for aead, skcipher algorithms
*
- * Copyright 2016-2018 NXP
+ * Copyright 2016-2019 NXP
*/
#include "compat.h"
@@ -1396,9 +1396,11 @@ void cnstr_shdsc_skcipher_encap(u32 * const desc, struct alginfo *cdata,
set_jump_tgt_here(desc, key_jump_cmd);
- /* Load iv */
- append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
- LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
+ /* Load IV, if there is one */
+ if (ivsize)
+ append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (ctx1_iv_off <<
+ LDST_OFFSET_SHIFT));
/* Load counter into CONTEXT1 reg */
if (is_rfc3686)
@@ -1462,9 +1464,11 @@ void cnstr_shdsc_skcipher_decap(u32 * const desc, struct alginfo *cdata,
set_jump_tgt_here(desc, key_jump_cmd);
- /* load IV */
- append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
- LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
+ /* Load IV, if there is one */
+ if (ivsize)
+ append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | (ctx1_iv_off <<
+ LDST_OFFSET_SHIFT));
/* Load counter into CONTEXT1 reg */
if (is_rfc3686)
diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c
index c0d55310aade..a15ce9213310 100644
--- a/drivers/crypto/caam/caamalg_qi.c
+++ b/drivers/crypto/caam/caamalg_qi.c
@@ -782,7 +782,7 @@ static struct caam_drv_ctx *get_drv_ctx(struct caam_ctx *ctx,
cpu = smp_processor_id();
drv_ctx = caam_drv_ctx_init(ctx->qidev, &cpu, desc);
- if (likely(!IS_ERR_OR_NULL(drv_ctx)))
+ if (!IS_ERR_OR_NULL(drv_ctx))
drv_ctx->op_type = type;
ctx->drv_ctx[type] = drv_ctx;
@@ -802,7 +802,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) {
if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
- dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+ if (dst_nents)
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
} else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
}
@@ -892,7 +893,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
struct caam_drv_ctx *drv_ctx;
drv_ctx = get_drv_ctx(ctx, encrypt ? ENCRYPT : DECRYPT);
- if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ if (IS_ERR_OR_NULL(drv_ctx))
return (struct aead_edesc *)drv_ctx;
/* allocate space for base edesc and hw desc commands, link tables */
@@ -955,13 +956,19 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
mapped_src_nents = 0;
}
- mapped_dst_nents = dma_map_sg(qidev, req->dst, dst_nents,
- DMA_FROM_DEVICE);
- if (unlikely(!mapped_dst_nents)) {
- dev_err(qidev, "unable to map destination\n");
- dma_unmap_sg(qidev, req->src, src_nents, DMA_TO_DEVICE);
- qi_cache_free(edesc);
- return ERR_PTR(-ENOMEM);
+ if (dst_nents) {
+ mapped_dst_nents = dma_map_sg(qidev, req->dst,
+ dst_nents,
+ DMA_FROM_DEVICE);
+ if (unlikely(!mapped_dst_nents)) {
+ dev_err(qidev, "unable to map destination\n");
+ dma_unmap_sg(qidev, req->src, src_nents,
+ DMA_TO_DEVICE);
+ qi_cache_free(edesc);
+ return ERR_PTR(-ENOMEM);
+ }
+ } else {
+ mapped_dst_nents = 0;
}
}
@@ -1184,7 +1191,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req,
struct caam_drv_ctx *drv_ctx;
drv_ctx = get_drv_ctx(ctx, encrypt ? ENCRYPT : DECRYPT);
- if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ if (IS_ERR_OR_NULL(drv_ctx))
return (struct skcipher_edesc *)drv_ctx;
src_nents = sg_nents_for_len(req->src, req->cryptlen);
diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
index 425d5d974613..c2c1abc68f81 100644
--- a/drivers/crypto/caam/caamalg_qi2.c
+++ b/drivers/crypto/caam/caamalg_qi2.c
@@ -25,13 +25,6 @@
#define CAAM_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE + \
SHA512_DIGEST_SIZE * 2)
-#if !IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM)
-bool caam_little_end;
-EXPORT_SYMBOL(caam_little_end);
-bool caam_imx;
-EXPORT_SYMBOL(caam_imx);
-#endif
-
/*
* This is a a cache of buffers, from which the users of CAAM QI driver
* can allocate short buffers. It's speedier than doing kmalloc on the hotpath.
@@ -151,7 +144,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) {
if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
- dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+ if (dst_nents)
+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
} else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
}
@@ -392,13 +386,18 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
mapped_src_nents = 0;
}
- mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents,
- DMA_FROM_DEVICE);
- if (unlikely(!mapped_dst_nents)) {
- dev_err(dev, "unable to map destination\n");
- dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
- qi_cache_free(edesc);
- return ERR_PTR(-ENOMEM);
+ if (dst_nents) {
+ mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents,
+ DMA_FROM_DEVICE);
+ if (unlikely(!mapped_dst_nents)) {
+ dev_err(dev, "unable to map destination\n");
+ dma_unmap_sg(dev, req->src, src_nents,
+ DMA_TO_DEVICE);
+ qi_cache_free(edesc);
+ return ERR_PTR(-ENOMEM);
+ }
+ } else {
+ mapped_dst_nents = 0;
}
} else {
src_nents = sg_nents_for_len(req->src, req->assoclen +
@@ -4503,7 +4502,8 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv)
nctx->cb = dpaa2_caam_fqdan_cb;
/* Register notification callbacks */
- err = dpaa2_io_service_register(NULL, nctx);
+ ppriv->dpio = dpaa2_io_service_select(cpu);
+ err = dpaa2_io_service_register(ppriv->dpio, nctx, dev);
if (unlikely(err)) {
dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu);
nctx->cb = NULL;
@@ -4536,7 +4536,7 @@ err:
ppriv = per_cpu_ptr(priv->ppriv, cpu);
if (!ppriv->nctx.cb)
break;
- dpaa2_io_service_deregister(NULL, &ppriv->nctx);
+ dpaa2_io_service_deregister(ppriv->dpio, &ppriv->nctx, dev);
}
for_each_online_cpu(cpu) {
@@ -4556,7 +4556,8 @@ static void __cold dpaa2_dpseci_dpio_free(struct dpaa2_caam_priv *priv)
for_each_online_cpu(cpu) {
ppriv = per_cpu_ptr(priv->ppriv, cpu);
- dpaa2_io_service_deregister(NULL, &ppriv->nctx);
+ dpaa2_io_service_deregister(ppriv->dpio, &ppriv->nctx,
+ priv->dev);
dpaa2_io_store_destroy(ppriv->store);
if (++i == priv->num_pairs)
@@ -4654,7 +4655,7 @@ static int dpaa2_caam_pull_fq(struct dpaa2_caam_priv_per_cpu *ppriv)
/* Retry while portal is busy */
do {
- err = dpaa2_io_service_pull_fq(NULL, ppriv->rsp_fqid,
+ err = dpaa2_io_service_pull_fq(ppriv->dpio, ppriv->rsp_fqid,
ppriv->store);
} while (err == -EBUSY);
@@ -4722,7 +4723,7 @@ static int dpaa2_dpseci_poll(struct napi_struct *napi, int budget)
if (cleaned < budget) {
napi_complete_done(napi, cleaned);
- err = dpaa2_io_service_rearm(NULL, &ppriv->nctx);
+ err = dpaa2_io_service_rearm(ppriv->dpio, &ppriv->nctx);
if (unlikely(err))
dev_err(priv->dev, "Notification rearm failed: %d\n",
err);
@@ -4863,21 +4864,31 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
i = 0;
for_each_online_cpu(cpu) {
- dev_dbg(dev, "pair %d: rx queue %d, tx queue %d\n", i,
- priv->rx_queue_attr[i].fqid,
- priv->tx_queue_attr[i].fqid);
+ u8 j;
+
+ j = i % priv->num_pairs;
ppriv = per_cpu_ptr(priv->ppriv, cpu);
- ppriv->req_fqid = priv->tx_queue_attr[i].fqid;
- ppriv->rsp_fqid = priv->rx_queue_attr[i].fqid;
- ppriv->prio = i;
+ ppriv->req_fqid = priv->tx_queue_attr[j].fqid;
+
+ /*
+ * Allow all cores to enqueue, while only some of them
+ * will take part in dequeuing.
+ */
+ if (++i > priv->num_pairs)
+ continue;
+
+ ppriv->rsp_fqid = priv->rx_queue_attr[j].fqid;
+ ppriv->prio = j;
+
+ dev_dbg(dev, "pair %d: rx queue %d, tx queue %d\n", j,
+ priv->rx_queue_attr[j].fqid,
+ priv->tx_queue_attr[j].fqid);
ppriv->net_dev.dev = *dev;
INIT_LIST_HEAD(&ppriv->net_dev.napi_list);
netif_napi_add(&ppriv->net_dev, &ppriv->napi, dpaa2_dpseci_poll,
DPAA2_CAAM_NAPI_WEIGHT);
- if (++i == priv->num_pairs)
- break;
}
return 0;
@@ -5229,7 +5240,8 @@ int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req)
{
struct dpaa2_fd fd;
struct dpaa2_caam_priv *priv = dev_get_drvdata(dev);
- int err = 0, i, id;
+ struct dpaa2_caam_priv_per_cpu *ppriv;
+ int err = 0, i;
if (IS_ERR(req))
return PTR_ERR(req);
@@ -5259,23 +5271,18 @@ int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req)
dpaa2_fd_set_len(&fd, dpaa2_fl_get_len(&req->fd_flt[1]));
dpaa2_fd_set_flc(&fd, req->flc_dma);
- /*
- * There is no guarantee that preemption is disabled here,
- * thus take action.
- */
- preempt_disable();
- id = smp_processor_id() % priv->dpseci_attr.num_tx_queues;
+ ppriv = this_cpu_ptr(priv->ppriv);
for (i = 0; i < (priv->dpseci_attr.num_tx_queues << 1); i++) {
- err = dpaa2_io_service_enqueue_fq(NULL,
- priv->tx_queue_attr[id].fqid,
+ err = dpaa2_io_service_enqueue_fq(ppriv->dpio, ppriv->req_fqid,
&fd);
if (err != -EBUSY)
break;
+
+ cpu_relax();
}
- preempt_enable();
if (unlikely(err)) {
- dev_err(dev, "Error enqueuing frame: %d\n", err);
+ dev_err_ratelimited(dev, "Error enqueuing frame: %d\n", err);
goto err_out;
}
diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
index 9823bdefd029..20890780fb82 100644
--- a/drivers/crypto/caam/caamalg_qi2.h
+++ b/drivers/crypto/caam/caamalg_qi2.h
@@ -76,6 +76,7 @@ struct dpaa2_caam_priv {
* @nctx: notification context of response FQ
* @store: where dequeued frames are stored
* @priv: backpointer to dpaa2_caam_priv
+ * @dpio: portal used for data path operations
*/
struct dpaa2_caam_priv_per_cpu {
struct napi_struct napi;
@@ -86,6 +87,7 @@ struct dpaa2_caam_priv_per_cpu {
struct dpaa2_io_notification_ctx nctx;
struct dpaa2_io_store *store;
struct dpaa2_caam_priv *priv;
+ struct dpaa2_io *dpio;
};
/*
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 81712aa5d0f2..d7483e4d0ce2 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -3,7 +3,7 @@
* caam - Freescale FSL CAAM support for ahash functions of crypto API
*
* Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2018 NXP
+ * Copyright 2018-2019 NXP
*
* Based on caamalg.c crypto API driver.
*
@@ -98,13 +98,14 @@ struct caam_hash_ctx {
u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
+ u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned;
dma_addr_t sh_desc_update_dma ____cacheline_aligned;
dma_addr_t sh_desc_update_first_dma;
dma_addr_t sh_desc_fin_dma;
dma_addr_t sh_desc_digest_dma;
+ dma_addr_t key_dma;
enum dma_data_direction dir;
struct device *jrdev;
- u8 key[CAAM_MAX_HASH_KEY_SIZE];
int ctx_len;
struct alginfo adata;
};
@@ -113,6 +114,7 @@ struct caam_hash_ctx {
struct caam_hash_state {
dma_addr_t buf_dma;
dma_addr_t ctx_dma;
+ int ctx_dma_len;
u8 buf_0[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
int buflen_0;
u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
@@ -158,6 +160,11 @@ static inline int *alt_buflen(struct caam_hash_state *state)
return state->current_buf ? &state->buflen_0 : &state->buflen_1;
}
+static inline bool is_cmac_aes(u32 algtype)
+{
+ return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
+ (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC);
+}
/* Common job descriptor seq in/out ptr routines */
/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
@@ -165,6 +172,7 @@ static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
struct caam_hash_state *state,
int ctx_len)
{
+ state->ctx_dma_len = ctx_len;
state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
ctx_len, DMA_FROM_DEVICE);
if (dma_mapping_error(jrdev, state->ctx_dma)) {
@@ -178,18 +186,6 @@ static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
return 0;
}
-/* Map req->result, and append seq_out_ptr command that points to it */
-static inline dma_addr_t map_seq_out_ptr_result(u32 *desc, struct device *jrdev,
- u8 *result, int digestsize)
-{
- dma_addr_t dst_dma;
-
- dst_dma = dma_map_single(jrdev, result, digestsize, DMA_FROM_DEVICE);
- append_seq_out_ptr(desc, dst_dma, digestsize, 0);
-
- return dst_dma;
-}
-
/* Map current buffer in state (if length > 0) and put it in link table */
static inline int buf_map_to_sec4_sg(struct device *jrdev,
struct sec4_sg_entry *sec4_sg,
@@ -218,6 +214,7 @@ static inline int ctx_map_to_sec4_sg(struct device *jrdev,
struct caam_hash_state *state, int ctx_len,
struct sec4_sg_entry *sec4_sg, u32 flag)
{
+ state->ctx_dma_len = ctx_len;
state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
if (dma_mapping_error(jrdev, state->ctx_dma)) {
dev_err(jrdev, "unable to map ctx\n");
@@ -292,14 +289,119 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash)
return 0;
}
+static int axcbc_set_sh_desc(struct crypto_ahash *ahash)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc;
+
+ /* key is loaded from memory for UPDATE and FINALIZE states */
+ ctx->adata.key_dma = ctx->key_dma;
+
+ /* shared descriptor for ahash_update */
+ desc = ctx->sh_desc_update;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
+ ctx->ctx_len, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+ 1);
+
+ /* shared descriptor for ahash_{final,finup} */
+ desc = ctx->sh_desc_fin;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
+ digestsize, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+ 1);
+
+ /* key is immediate data for INIT and INITFINAL states */
+ ctx->adata.key_virt = ctx->key;
+
+ /* shared descriptor for first invocation of ahash_update */
+ desc = ctx->sh_desc_update_first;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
+ ctx->ctx_len, ctx->key_dma);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+ 1);
+
+ /* shared descriptor for ahash_digest */
+ desc = ctx->sh_desc_digest;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
+ digestsize, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+ 1);
+ return 0;
+}
+
+static int acmac_set_sh_desc(struct crypto_ahash *ahash)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc;
+
+ /* shared descriptor for ahash_update */
+ desc = ctx->sh_desc_update;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
+ ctx->ctx_len, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+
+ /* shared descriptor for ahash_{final,finup} */
+ desc = ctx->sh_desc_fin;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
+ digestsize, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+
+ /* shared descriptor for first invocation of ahash_update */
+ desc = ctx->sh_desc_update_first;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
+ ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+
+ /* shared descriptor for ahash_digest */
+ desc = ctx->sh_desc_digest;
+ cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
+ digestsize, ctx->ctx_len, 0);
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
+ desc_bytes(desc), ctx->dir);
+ print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+
+ return 0;
+}
+
/* Digest hash size if it is too large */
-static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
- u32 *keylen, u8 *key_out, u32 digestsize)
+static int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key,
+ u32 digestsize)
{
struct device *jrdev = ctx->jrdev;
u32 *desc;
struct split_key_result result;
- dma_addr_t src_dma, dst_dma;
+ dma_addr_t key_dma;
int ret;
desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
@@ -310,18 +412,9 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
init_job_desc(desc, 0);
- src_dma = dma_map_single(jrdev, (void *)key_in, *keylen,
- DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, src_dma)) {
- dev_err(jrdev, "unable to map key input memory\n");
- kfree(desc);
- return -ENOMEM;
- }
- dst_dma = dma_map_single(jrdev, (void *)key_out, digestsize,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(jrdev, dst_dma)) {
- dev_err(jrdev, "unable to map key output memory\n");
- dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
+ key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(jrdev, key_dma)) {
+ dev_err(jrdev, "unable to map key memory\n");
kfree(desc);
return -ENOMEM;
}
@@ -329,16 +422,16 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
/* Job descriptor to perform unkeyed hash on key_in */
append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
OP_ALG_AS_INITFINAL);
- append_seq_in_ptr(desc, src_dma, *keylen, 0);
+ append_seq_in_ptr(desc, key_dma, *keylen, 0);
append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
- append_seq_out_ptr(desc, dst_dma, digestsize, 0);
+ append_seq_out_ptr(desc, key_dma, digestsize, 0);
append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
LDST_SRCDST_BYTE_CONTEXT);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "key_in@"__stringify(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, key_in, *keylen, 1);
+ DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
#endif
@@ -354,12 +447,10 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
#ifdef DEBUG
print_hex_dump(KERN_ERR,
"digested key@"__stringify(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, key_in,
- digestsize, 1);
+ DUMP_PREFIX_ADDRESS, 16, 4, key, digestsize, 1);
#endif
}
- dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
- dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL);
*keylen = digestsize;
@@ -383,13 +474,10 @@ static int ahash_setkey(struct crypto_ahash *ahash,
#endif
if (keylen > blocksize) {
- hashed_key = kmalloc_array(digestsize,
- sizeof(*hashed_key),
- GFP_KERNEL | GFP_DMA);
+ hashed_key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA);
if (!hashed_key)
return -ENOMEM;
- ret = hash_digest_key(ctx, key, &keylen, hashed_key,
- digestsize);
+ ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
if (ret)
goto bad_free_key;
key = hashed_key;
@@ -424,9 +512,39 @@ static int ahash_setkey(struct crypto_ahash *ahash,
return -EINVAL;
}
+static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key,
+ unsigned int keylen)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct device *jrdev = ctx->jrdev;
+
+ memcpy(ctx->key, key, keylen);
+ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE);
+ ctx->adata.keylen = keylen;
+
+ print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1);
+
+ return axcbc_set_sh_desc(ahash);
+}
+
+static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
+ unsigned int keylen)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+
+ /* key is immediate data for all cmac shared descriptors */
+ ctx->adata.key_virt = key;
+ ctx->adata.keylen = keylen;
+
+ print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+
+ return acmac_set_sh_desc(ahash);
+}
+
/*
* ahash_edesc - s/w-extended ahash descriptor
- * @dst_dma: physical mapped address of req->result
* @sec4_sg_dma: physical mapped address of h/w link table
* @src_nents: number of segments in input scatterlist
* @sec4_sg_bytes: length of dma mapped sec4_sg space
@@ -434,7 +552,6 @@ static int ahash_setkey(struct crypto_ahash *ahash,
* @sec4_sg: h/w link table
*/
struct ahash_edesc {
- dma_addr_t dst_dma;
dma_addr_t sec4_sg_dma;
int src_nents;
int sec4_sg_bytes;
@@ -450,8 +567,6 @@ static inline void ahash_unmap(struct device *dev,
if (edesc->src_nents)
dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
- if (edesc->dst_dma)
- dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
if (edesc->sec4_sg_bytes)
dma_unmap_single(dev, edesc->sec4_sg_dma,
@@ -468,12 +583,10 @@ static inline void ahash_unmap_ctx(struct device *dev,
struct ahash_edesc *edesc,
struct ahash_request *req, int dst_len, u32 flag)
{
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
struct caam_hash_state *state = ahash_request_ctx(req);
if (state->ctx_dma) {
- dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
+ dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag);
state->ctx_dma = 0;
}
ahash_unmap(dev, edesc, req, dst_len);
@@ -486,9 +599,9 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
struct ahash_edesc *edesc;
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
int digestsize = crypto_ahash_digestsize(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
#ifdef DEBUG
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
- struct caam_hash_state *state = ahash_request_ctx(req);
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
#endif
@@ -497,17 +610,14 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
- ahash_unmap(jrdev, edesc, req, digestsize);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ memcpy(req->result, state->caam_ctx, digestsize);
kfree(edesc);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
ctx->ctx_len, 1);
- if (req->result)
- print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, req->result,
- digestsize, 1);
#endif
req->base.complete(&req->base, err);
@@ -555,9 +665,9 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
struct ahash_edesc *edesc;
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
int digestsize = crypto_ahash_digestsize(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
#ifdef DEBUG
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
- struct caam_hash_state *state = ahash_request_ctx(req);
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
#endif
@@ -566,17 +676,14 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
- ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_TO_DEVICE);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
+ memcpy(req->result, state->caam_ctx, digestsize);
kfree(edesc);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "ctx@"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
ctx->ctx_len, 1);
- if (req->result)
- print_hex_dump(KERN_ERR, "result@"__stringify(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, req->result,
- digestsize, 1);
#endif
req->base.complete(&req->base, err);
@@ -688,6 +795,7 @@ static int ahash_update_ctx(struct ahash_request *req)
u8 *buf = current_buf(state);
int *buflen = current_buflen(state);
u8 *next_buf = alt_buf(state);
+ int blocksize = crypto_ahash_blocksize(ahash);
int *next_buflen = alt_buflen(state), last_buflen;
int in_len = *buflen + req->nbytes, to_hash;
u32 *desc;
@@ -696,9 +804,20 @@ static int ahash_update_ctx(struct ahash_request *req)
int ret = 0;
last_buflen = *next_buflen;
- *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
+ *next_buflen = in_len & (blocksize - 1);
to_hash = in_len - *next_buflen;
+ /*
+ * For XCBC and CMAC, if to_hash is multiple of block size,
+ * keep last block in internal buffer
+ */
+ if ((is_xcbc_aes(ctx->adata.algtype) ||
+ is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
+ (*next_buflen == 0)) {
+ *next_buflen = blocksize;
+ to_hash -= blocksize;
+ }
+
if (to_hash) {
src_nents = sg_nents_for_len(req->src,
req->nbytes - (*next_buflen));
@@ -801,7 +920,7 @@ static int ahash_update_ctx(struct ahash_request *req)
#endif
return ret;
- unmap_ctx:
+unmap_ctx:
ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
kfree(edesc);
return ret;
@@ -837,7 +956,7 @@ static int ahash_final_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
- edesc->sec4_sg, DMA_TO_DEVICE);
+ edesc->sec4_sg, DMA_BIDIRECTIONAL);
if (ret)
goto unmap_ctx;
@@ -857,14 +976,7 @@ static int ahash_final_ctx(struct ahash_request *req)
append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
LDST_SGF);
-
- edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
- digestsize);
- if (dma_mapping_error(jrdev, edesc->dst_dma)) {
- dev_err(jrdev, "unable to map dst\n");
- ret = -ENOMEM;
- goto unmap_ctx;
- }
+ append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -877,7 +989,7 @@ static int ahash_final_ctx(struct ahash_request *req)
return -EINPROGRESS;
unmap_ctx:
- ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
kfree(edesc);
return ret;
}
@@ -931,7 +1043,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
edesc->src_nents = src_nents;
ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
- edesc->sec4_sg, DMA_TO_DEVICE);
+ edesc->sec4_sg, DMA_BIDIRECTIONAL);
if (ret)
goto unmap_ctx;
@@ -945,13 +1057,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
if (ret)
goto unmap_ctx;
- edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
- digestsize);
- if (dma_mapping_error(jrdev, edesc->dst_dma)) {
- dev_err(jrdev, "unable to map dst\n");
- ret = -ENOMEM;
- goto unmap_ctx;
- }
+ append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -964,7 +1070,7 @@ static int ahash_finup_ctx(struct ahash_request *req)
return -EINPROGRESS;
unmap_ctx:
- ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
kfree(edesc);
return ret;
}
@@ -1023,10 +1129,8 @@ static int ahash_digest(struct ahash_request *req)
desc = edesc->hw_desc;
- edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
- digestsize);
- if (dma_mapping_error(jrdev, edesc->dst_dma)) {
- dev_err(jrdev, "unable to map dst\n");
+ ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
+ if (ret) {
ahash_unmap(jrdev, edesc, req, digestsize);
kfree(edesc);
return -ENOMEM;
@@ -1041,7 +1145,7 @@ static int ahash_digest(struct ahash_request *req)
if (!ret) {
ret = -EINPROGRESS;
} else {
- ahash_unmap(jrdev, edesc, req, digestsize);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
kfree(edesc);
}
@@ -1072,20 +1176,20 @@ static int ahash_final_no_ctx(struct ahash_request *req)
desc = edesc->hw_desc;
- state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, state->buf_dma)) {
- dev_err(jrdev, "unable to map src\n");
- goto unmap;
- }
+ if (buflen) {
+ state->buf_dma = dma_map_single(jrdev, buf, buflen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, state->buf_dma)) {
+ dev_err(jrdev, "unable to map src\n");
+ goto unmap;
+ }
- append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+ append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+ }
- edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
- digestsize);
- if (dma_mapping_error(jrdev, edesc->dst_dma)) {
- dev_err(jrdev, "unable to map dst\n");
+ ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
+ if (ret)
goto unmap;
- }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1096,7 +1200,7 @@ static int ahash_final_no_ctx(struct ahash_request *req)
if (!ret) {
ret = -EINPROGRESS;
} else {
- ahash_unmap(jrdev, edesc, req, digestsize);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
kfree(edesc);
}
@@ -1119,6 +1223,7 @@ static int ahash_update_no_ctx(struct ahash_request *req)
GFP_KERNEL : GFP_ATOMIC;
u8 *buf = current_buf(state);
int *buflen = current_buflen(state);
+ int blocksize = crypto_ahash_blocksize(ahash);
u8 *next_buf = alt_buf(state);
int *next_buflen = alt_buflen(state);
int in_len = *buflen + req->nbytes, to_hash;
@@ -1127,9 +1232,20 @@ static int ahash_update_no_ctx(struct ahash_request *req)
u32 *desc;
int ret = 0;
- *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
+ *next_buflen = in_len & (blocksize - 1);
to_hash = in_len - *next_buflen;
+ /*
+ * For XCBC and CMAC, if to_hash is multiple of block size,
+ * keep last block in internal buffer
+ */
+ if ((is_xcbc_aes(ctx->adata.algtype) ||
+ is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
+ (*next_buflen == 0)) {
+ *next_buflen = blocksize;
+ to_hash -= blocksize;
+ }
+
if (to_hash) {
src_nents = sg_nents_for_len(req->src,
req->nbytes - *next_buflen);
@@ -1295,12 +1411,9 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
goto unmap;
}
- edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
- digestsize);
- if (dma_mapping_error(jrdev, edesc->dst_dma)) {
- dev_err(jrdev, "unable to map dst\n");
+ ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
+ if (ret)
goto unmap;
- }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1311,7 +1424,7 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
if (!ret) {
ret = -EINPROGRESS;
} else {
- ahash_unmap(jrdev, edesc, req, digestsize);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
kfree(edesc);
}
@@ -1335,15 +1448,26 @@ static int ahash_update_first(struct ahash_request *req)
u8 *next_buf = alt_buf(state);
int *next_buflen = alt_buflen(state);
int to_hash;
+ int blocksize = crypto_ahash_blocksize(ahash);
u32 *desc;
int src_nents, mapped_nents;
struct ahash_edesc *edesc;
int ret = 0;
- *next_buflen = req->nbytes & (crypto_tfm_alg_blocksize(&ahash->base) -
- 1);
+ *next_buflen = req->nbytes & (blocksize - 1);
to_hash = req->nbytes - *next_buflen;
+ /*
+ * For XCBC and CMAC, if to_hash is multiple of block size,
+ * keep last block in internal buffer
+ */
+ if ((is_xcbc_aes(ctx->adata.algtype) ||
+ is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
+ (*next_buflen == 0)) {
+ *next_buflen = blocksize;
+ to_hash -= blocksize;
+ }
+
if (to_hash) {
src_nents = sg_nents_for_len(req->src,
req->nbytes - *next_buflen);
@@ -1443,6 +1567,7 @@ static int ahash_init(struct ahash_request *req)
state->final = ahash_final_no_ctx;
state->ctx_dma = 0;
+ state->ctx_dma_len = 0;
state->current_buf = 0;
state->buf_dma = 0;
state->buflen_0 = 0;
@@ -1651,6 +1776,44 @@ static struct caam_hash_template driver_hash[] = {
},
},
.alg_type = OP_ALG_ALGSEL_MD5,
+ }, {
+ .hmac_name = "xcbc(aes)",
+ .hmac_driver_name = "xcbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = axcbc_setkey,
+ .halg = {
+ .digestsize = AES_BLOCK_SIZE,
+ .statesize = sizeof(struct caam_export_state),
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
+ }, {
+ .hmac_name = "cmac(aes)",
+ .hmac_driver_name = "cmac-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = acmac_setkey,
+ .halg = {
+ .digestsize = AES_BLOCK_SIZE,
+ .statesize = sizeof(struct caam_export_state),
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC,
},
};
@@ -1692,14 +1855,45 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
}
priv = dev_get_drvdata(ctx->jrdev->parent);
- ctx->dir = priv->era >= 6 ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
+
+ if (is_xcbc_aes(caam_hash->alg_type)) {
+ ctx->dir = DMA_TO_DEVICE;
+ ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
+ ctx->ctx_len = 48;
+
+ ctx->key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key,
+ ARRAY_SIZE(ctx->key),
+ DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(ctx->jrdev, ctx->key_dma)) {
+ dev_err(ctx->jrdev, "unable to map key\n");
+ caam_jr_free(ctx->jrdev);
+ return -ENOMEM;
+ }
+ } else if (is_cmac_aes(caam_hash->alg_type)) {
+ ctx->dir = DMA_TO_DEVICE;
+ ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
+ ctx->ctx_len = 32;
+ } else {
+ ctx->dir = priv->era >= 6 ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
+ ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
+ ctx->ctx_len = runninglen[(ctx->adata.algtype &
+ OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT];
+ }
dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update,
- offsetof(struct caam_hash_ctx,
- sh_desc_update_dma),
+ offsetof(struct caam_hash_ctx, key),
ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
if (dma_mapping_error(ctx->jrdev, dma_addr)) {
dev_err(ctx->jrdev, "unable to map shared descriptors\n");
+
+ if (is_xcbc_aes(caam_hash->alg_type))
+ dma_unmap_single_attrs(ctx->jrdev, ctx->key_dma,
+ ARRAY_SIZE(ctx->key),
+ DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
+
caam_jr_free(ctx->jrdev);
return -ENOMEM;
}
@@ -1713,16 +1907,14 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx,
sh_desc_digest);
- /* copy descriptor header template value */
- ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
-
- ctx->ctx_len = runninglen[(ctx->adata.algtype &
- OP_ALG_ALGSEL_SUBMASK) >>
- OP_ALG_ALGSEL_SHIFT];
-
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
sizeof(struct caam_hash_state));
- return ahash_set_sh_desc(ahash);
+
+ /*
+ * For keyed hash algorithms shared descriptors
+ * will be created later in setkey() callback
+ */
+ return alg->setkey ? 0 : ahash_set_sh_desc(ahash);
}
static void caam_hash_cra_exit(struct crypto_tfm *tfm)
@@ -1730,9 +1922,12 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm)
struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma,
- offsetof(struct caam_hash_ctx,
- sh_desc_update_dma),
+ offsetof(struct caam_hash_ctx, key),
ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
+ if (is_xcbc_aes(ctx->adata.algtype))
+ dma_unmap_single_attrs(ctx->jrdev, ctx->key_dma,
+ ARRAY_SIZE(ctx->key), DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
caam_jr_free(ctx->jrdev);
}
@@ -1863,14 +2058,16 @@ static int __init caam_algapi_hash_init(void)
struct caam_hash_template *alg = driver_hash + i;
/* If MD size is not supported by device, skip registration */
- if (alg->template_ahash.halg.digestsize > md_limit)
+ if (is_mdha(alg->alg_type) &&
+ alg->template_ahash.halg.digestsize > md_limit)
continue;
/* register hmac version */
t_alg = caam_hash_alloc(alg, true);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
- pr_warn("%s alg allocation failed\n", alg->driver_name);
+ pr_warn("%s alg allocation failed\n",
+ alg->hmac_driver_name);
continue;
}
@@ -1883,6 +2080,9 @@ static int __init caam_algapi_hash_init(void)
} else
list_add_tail(&t_alg->entry, &hash_list);
+ if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES)
+ continue;
+
/* register unkeyed version */
t_alg = caam_hash_alloc(alg, false);
if (IS_ERR(t_alg)) {
diff --git a/drivers/crypto/caam/caamhash_desc.c b/drivers/crypto/caam/caamhash_desc.c
index a12f7959a2c3..71d018343ee4 100644
--- a/drivers/crypto/caam/caamhash_desc.c
+++ b/drivers/crypto/caam/caamhash_desc.c
@@ -2,7 +2,7 @@
/*
* Shared descriptors for ahash algorithms
*
- * Copyright 2017 NXP
+ * Copyright 2017-2019 NXP
*/
#include "compat.h"
@@ -75,6 +75,72 @@ void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state,
}
EXPORT_SYMBOL(cnstr_shdsc_ahash);
+/**
+ * cnstr_shdsc_sk_hash - shared descriptor for symmetric key cipher-based
+ * hash algorithms
+ * @desc: pointer to buffer used for descriptor construction
+ * @adata: pointer to authentication transform definitions.
+ * @state: algorithm state OP_ALG_AS_{INIT, FINALIZE, INITFINALIZE, UPDATE}
+ * @digestsize: algorithm's digest size
+ * @ctx_len: size of Context Register
+ * @key_dma: I/O Virtual Address of the key
+ */
+void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state,
+ int digestsize, int ctx_len, dma_addr_t key_dma)
+{
+ u32 *skip_key_load;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+
+ /* Skip loading of key, context if already shared */
+ skip_key_load = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+
+ if (state == OP_ALG_AS_INIT || state == OP_ALG_AS_INITFINAL) {
+ append_key_as_imm(desc, adata->key_virt, adata->keylen,
+ adata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ } else { /* UPDATE, FINALIZE */
+ if (is_xcbc_aes(adata->algtype))
+ /* Load K1 */
+ append_key(desc, adata->key_dma, adata->keylen,
+ CLASS_1 | KEY_DEST_CLASS_REG | KEY_ENC);
+ else /* CMAC */
+ append_key_as_imm(desc, adata->key_virt, adata->keylen,
+ adata->keylen, CLASS_1 |
+ KEY_DEST_CLASS_REG);
+ /* Restore context */
+ append_seq_load(desc, ctx_len, LDST_CLASS_1_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+ }
+
+ set_jump_tgt_here(desc, skip_key_load);
+
+ /* Class 1 operation */
+ append_operation(desc, adata->algtype | state | OP_ALG_ENCRYPT);
+
+ /*
+ * Load from buf and/or src and write to req->result or state->context
+ * Calculate remaining bytes to read
+ */
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+ /* Read remaining bytes */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_MSG | FIFOLDST_VLF);
+
+ /*
+ * Save context:
+ * - xcbc: partial hash, keys K2 and K3
+ * - cmac: partial hash, constant L = E(K,0)
+ */
+ append_seq_store(desc, digestsize, LDST_CLASS_1_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+ if (is_xcbc_aes(adata->algtype) && state == OP_ALG_AS_INIT)
+ /* Save K1 */
+ append_fifo_store(desc, key_dma, adata->keylen,
+ LDST_CLASS_1_CCB | FIFOST_TYPE_KEY_KEK);
+}
+EXPORT_SYMBOL(cnstr_shdsc_sk_hash);
+
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("FSL CAAM ahash descriptors support");
MODULE_AUTHOR("NXP Semiconductors");
diff --git a/drivers/crypto/caam/caamhash_desc.h b/drivers/crypto/caam/caamhash_desc.h
index 631fc1ac312c..6947ee1f200c 100644
--- a/drivers/crypto/caam/caamhash_desc.h
+++ b/drivers/crypto/caam/caamhash_desc.h
@@ -15,7 +15,15 @@
#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
+static inline bool is_xcbc_aes(u32 algtype)
+{
+ return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
+ (OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC);
+}
+
void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state,
int digestsize, int ctx_len, bool import_ctx, int era);
+void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state,
+ int digestsize, int ctx_len, dma_addr_t key_dma);
#endif /* _CAAMHASH_DESC_H_ */
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 87d9efe4c7aa..8639b2df0371 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -43,6 +43,7 @@
#include <crypto/akcipher.h>
#include <crypto/scatterwalk.h>
#include <crypto/skcipher.h>
+#include <crypto/arc4.h>
#include <crypto/internal/skcipher.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/rsa.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 16bbc72f041a..858bdc9ab4a3 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -18,12 +18,8 @@
#include "desc_constr.h"
#include "ctrl.h"
-bool caam_little_end;
-EXPORT_SYMBOL(caam_little_end);
bool caam_dpaa2;
EXPORT_SYMBOL(caam_dpaa2);
-bool caam_imx;
-EXPORT_SYMBOL(caam_imx);
#ifdef CONFIG_CAAM_QI
#include "qi.h"
@@ -863,27 +859,18 @@ static int caam_probe(struct platform_device *pdev)
/* Internal covering keys (useful in non-secure mode only) */
ctrlpriv->ctl_kek_wrap.data = (__force void *)&ctrlpriv->ctrl->kek[0];
ctrlpriv->ctl_kek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
- ctrlpriv->ctl_kek = debugfs_create_blob("kek",
- S_IRUSR |
- S_IRGRP | S_IROTH,
- ctrlpriv->ctl,
- &ctrlpriv->ctl_kek_wrap);
+ debugfs_create_blob("kek", S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl,
+ &ctrlpriv->ctl_kek_wrap);
ctrlpriv->ctl_tkek_wrap.data = (__force void *)&ctrlpriv->ctrl->tkek[0];
ctrlpriv->ctl_tkek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
- ctrlpriv->ctl_tkek = debugfs_create_blob("tkek",
- S_IRUSR |
- S_IRGRP | S_IROTH,
- ctrlpriv->ctl,
- &ctrlpriv->ctl_tkek_wrap);
+ debugfs_create_blob("tkek", S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl,
+ &ctrlpriv->ctl_tkek_wrap);
ctrlpriv->ctl_tdsk_wrap.data = (__force void *)&ctrlpriv->ctrl->tdsk[0];
ctrlpriv->ctl_tdsk_wrap.size = KEK_KEY_SIZE * sizeof(u32);
- ctrlpriv->ctl_tdsk = debugfs_create_blob("tdsk",
- S_IRUSR |
- S_IRGRP | S_IROTH,
- ctrlpriv->ctl,
- &ctrlpriv->ctl_tdsk_wrap);
+ debugfs_create_blob("tdsk", S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl,
+ &ctrlpriv->ctl_tdsk_wrap);
#endif
return 0;
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index ec10230178c5..4b6854bf896a 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1155,6 +1155,7 @@
#define OP_ALG_ALGSEL_DES (0x20 << OP_ALG_ALGSEL_SHIFT)
#define OP_ALG_ALGSEL_3DES (0x21 << OP_ALG_ALGSEL_SHIFT)
#define OP_ALG_ALGSEL_ARC4 (0x30 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_CHA_MDHA (0x40 << OP_ALG_ALGSEL_SHIFT)
#define OP_ALG_ALGSEL_MD5 (0x40 << OP_ALG_ALGSEL_SHIFT)
#define OP_ALG_ALGSEL_SHA1 (0x41 << OP_ALG_ALGSEL_SHIFT)
#define OP_ALG_ALGSEL_SHA224 (0x42 << OP_ALG_ALGSEL_SHIFT)
diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 7e8d690f2827..21a70fd32f5d 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -50,6 +50,12 @@ void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
#endif /* DEBUG */
EXPORT_SYMBOL(caam_dump_sg);
+bool caam_little_end;
+EXPORT_SYMBOL(caam_little_end);
+
+bool caam_imx;
+EXPORT_SYMBOL(caam_imx);
+
static const struct {
u8 value;
const char *error_text;
diff --git a/drivers/crypto/caam/error.h b/drivers/crypto/caam/error.h
index 67ea94079837..8c6b83e02a70 100644
--- a/drivers/crypto/caam/error.h
+++ b/drivers/crypto/caam/error.h
@@ -7,6 +7,9 @@
#ifndef CAAM_ERROR_H
#define CAAM_ERROR_H
+
+#include "desc.h"
+
#define CAAM_ERROR_STR_MAX 302
void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
@@ -17,4 +20,10 @@ void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
int rowsize, int groupsize, struct scatterlist *sg,
size_t tlen, bool ascii);
+
+static inline bool is_mdha(u32 algtype)
+{
+ return (algtype & OP_ALG_ALGSEL_MASK & ~OP_ALG_ALGSEL_SUBMASK) ==
+ OP_ALG_CHA_MDHA;
+}
#endif /* CAAM_ERROR_H */
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index babc78abd155..5869ad58d497 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -106,7 +106,6 @@ struct caam_drv_private {
struct dentry *dfs_root;
struct dentry *ctl; /* controller dir */
struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap;
- struct dentry *ctl_kek, *ctl_tkek, *ctl_tdsk;
#endif
};
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index 312b5f042f31..8d0713fae6ac 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -48,7 +48,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
{
u32 *desc;
struct split_key_result result;
- dma_addr_t dma_addr_in, dma_addr_out;
+ dma_addr_t dma_addr;
int ret = -ENOMEM;
adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK);
@@ -71,22 +71,17 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
return ret;
}
- dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen,
- DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, dma_addr_in)) {
- dev_err(jrdev, "unable to map key input memory\n");
- goto out_free;
- }
+ memcpy(key_out, key_in, keylen);
- dma_addr_out = dma_map_single(jrdev, key_out, adata->keylen_pad,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(jrdev, dma_addr_out)) {
- dev_err(jrdev, "unable to map key output memory\n");
- goto out_unmap_in;
+ dma_addr = dma_map_single(jrdev, key_out, adata->keylen_pad,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(jrdev, dma_addr)) {
+ dev_err(jrdev, "unable to map key memory\n");
+ goto out_free;
}
init_job_desc(desc, 0);
- append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
+ append_key(desc, dma_addr, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
/* Sets MDHA up into an HMAC-INIT */
append_operation(desc, (adata->algtype & OP_ALG_ALGSEL_MASK) |
@@ -104,12 +99,10 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
* FIFO_STORE with the explicit split-key content store
* (0x26 output type)
*/
- append_fifo_store(desc, dma_addr_out, adata->keylen,
+ append_fifo_store(desc, dma_addr, adata->keylen,
LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
#ifdef DEBUG
- print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
#endif
@@ -129,10 +122,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
#endif
}
- dma_unmap_single(jrdev, dma_addr_out, adata->keylen_pad,
- DMA_FROM_DEVICE);
-out_unmap_in:
- dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
+ dma_unmap_single(jrdev, dma_addr, adata->keylen_pad, DMA_BIDIRECTIONAL);
out_free:
kfree(desc);
return ret;
diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c
index b84e6c8b1e13..7cb8b1755e57 100644
--- a/drivers/crypto/caam/qi.c
+++ b/drivers/crypto/caam/qi.c
@@ -318,7 +318,7 @@ int caam_drv_ctx_update(struct caam_drv_ctx *drv_ctx, u32 *sh_desc)
/* Create a new req FQ in parked state */
new_fq = create_caam_req_fq(drv_ctx->qidev, drv_ctx->rsp_fq,
drv_ctx->context_a, 0);
- if (unlikely(IS_ERR_OR_NULL(new_fq))) {
+ if (IS_ERR_OR_NULL(new_fq)) {
dev_err(qidev, "FQ allocation for shdesc update failed\n");
return PTR_ERR(new_fq);
}
@@ -431,7 +431,7 @@ struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev,
/* Attach request FQ */
drv_ctx->req_fq = create_caam_req_fq(qidev, drv_ctx->rsp_fq, hwdesc,
QMAN_INITFQ_FLAG_SCHED);
- if (unlikely(IS_ERR_OR_NULL(drv_ctx->req_fq))) {
+ if (IS_ERR_OR_NULL(drv_ctx->req_fq)) {
dev_err(qidev, "create_caam_req_fq failed\n");
dma_unmap_single(qidev, hwdesc, size, DMA_BIDIRECTIONAL);
kfree(drv_ctx);
diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c
index 06ad85ab5e86..a876535529d1 100644
--- a/drivers/crypto/cavium/cpt/cptpf_main.c
+++ b/drivers/crypto/cavium/cpt/cptpf_main.c
@@ -278,8 +278,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae)
mcode->num_cores = is_ae ? 6 : 10;
/* Allocate DMAable space */
- mcode->code = dma_zalloc_coherent(&cpt->pdev->dev, mcode->code_size,
- &mcode->phys_base, GFP_KERNEL);
+ mcode->code = dma_alloc_coherent(&cpt->pdev->dev, mcode->code_size,
+ &mcode->phys_base, GFP_KERNEL);
if (!mcode->code) {
dev_err(dev, "Unable to allocate space for microcode");
ret = -ENOMEM;
diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c
index 5c796ed55eba..2ca431ed1db8 100644
--- a/drivers/crypto/cavium/cpt/cptvf_main.c
+++ b/drivers/crypto/cavium/cpt/cptvf_main.c
@@ -236,9 +236,10 @@ static int alloc_command_queues(struct cpt_vf *cptvf,
c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes :
rem_q_size;
- curr->head = (u8 *)dma_zalloc_coherent(&pdev->dev,
- c_size + CPT_NEXT_CHUNK_PTR_SIZE,
- &curr->dma_addr, GFP_KERNEL);
+ curr->head = (u8 *)dma_alloc_coherent(&pdev->dev,
+ c_size + CPT_NEXT_CHUNK_PTR_SIZE,
+ &curr->dma_addr,
+ GFP_KERNEL);
if (!curr->head) {
dev_err(&pdev->dev, "Command Q (%d) chunk (%d) allocation failed\n",
i, queue->nchunks);
diff --git a/drivers/crypto/cavium/nitrox/nitrox_debugfs.c b/drivers/crypto/cavium/nitrox/nitrox_debugfs.c
index 0196b992280f..848ec93d4333 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_debugfs.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_debugfs.c
@@ -55,31 +55,14 @@ void nitrox_debugfs_exit(struct nitrox_device *ndev)
ndev->debugfs_dir = NULL;
}
-int nitrox_debugfs_init(struct nitrox_device *ndev)
+void nitrox_debugfs_init(struct nitrox_device *ndev)
{
- struct dentry *dir, *f;
+ struct dentry *dir;
dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!dir)
- return -ENOMEM;
ndev->debugfs_dir = dir;
- f = debugfs_create_file("firmware", 0400, dir, ndev,
- &firmware_fops);
- if (!f)
- goto err;
- f = debugfs_create_file("device", 0400, dir, ndev,
- &device_fops);
- if (!f)
- goto err;
- f = debugfs_create_file("stats", 0400, dir, ndev,
- &stats_fops);
- if (!f)
- goto err;
-
- return 0;
-
-err:
- nitrox_debugfs_exit(ndev);
- return -ENODEV;
+ debugfs_create_file("firmware", 0400, dir, ndev, &firmware_fops);
+ debugfs_create_file("device", 0400, dir, ndev, &device_fops);
+ debugfs_create_file("stats", 0400, dir, ndev, &stats_fops);
}
diff --git a/drivers/crypto/cavium/nitrox/nitrox_debugfs.h b/drivers/crypto/cavium/nitrox/nitrox_debugfs.h
index a8d85ffa619c..f177b79bbab0 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_debugfs.h
+++ b/drivers/crypto/cavium/nitrox/nitrox_debugfs.h
@@ -5,12 +5,11 @@
#include "nitrox_dev.h"
#ifdef CONFIG_DEBUG_FS
-int nitrox_debugfs_init(struct nitrox_device *ndev);
+void nitrox_debugfs_init(struct nitrox_device *ndev);
void nitrox_debugfs_exit(struct nitrox_device *ndev);
#else
-static inline int nitrox_debugfs_init(struct nitrox_device *ndev)
+static inline void nitrox_debugfs_init(struct nitrox_device *ndev)
{
- return 0;
}
static inline void nitrox_debugfs_exit(struct nitrox_device *ndev)
diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c
index 9138bae12521..4ace9bcd603a 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_lib.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c
@@ -25,9 +25,9 @@ static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes)
struct nitrox_device *ndev = cmdq->ndev;
cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes;
- cmdq->unalign_base = dma_zalloc_coherent(DEV(ndev), cmdq->qsize,
- &cmdq->unalign_dma,
- GFP_KERNEL);
+ cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize,
+ &cmdq->unalign_dma,
+ GFP_KERNEL);
if (!cmdq->unalign_base)
return -ENOMEM;
diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c
index 014e9863c20e..faa78f651238 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_main.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_main.c
@@ -404,9 +404,7 @@ static int nitrox_probe(struct pci_dev *pdev,
if (err)
goto pf_hw_fail;
- err = nitrox_debugfs_init(ndev);
- if (err)
- goto pf_hw_fail;
+ nitrox_debugfs_init(ndev);
/* clear the statistics */
atomic64_set(&ndev->stats.posted, 0);
diff --git a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c
index e34e4df8fd24..4c97478d44bd 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c
@@ -537,6 +537,8 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
struct nitrox_device *ndev = cmdq->ndev;
struct nitrox_softreq *sr;
int req_completed = 0, err = 0, budget;
+ completion_t callback;
+ void *cb_arg;
/* check all pending requests */
budget = atomic_read(&cmdq->pending_count);
@@ -564,13 +566,13 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
smp_mb__after_atomic();
/* remove from response list */
response_list_del(sr, cmdq);
-
/* ORH error code */
err = READ_ONCE(*sr->resp.orh) & 0xff;
+ callback = sr->callback;
+ cb_arg = sr->cb_arg;
softreq_destroy(sr);
-
- if (sr->callback)
- sr->callback(sr->cb_arg, err);
+ if (callback)
+ callback(cb_arg, err);
req_completed++;
}
diff --git a/drivers/crypto/cavium/zip/zip_main.c b/drivers/crypto/cavium/zip/zip_main.c
index be055b9547f6..a8447a3cf366 100644
--- a/drivers/crypto/cavium/zip/zip_main.c
+++ b/drivers/crypto/cavium/zip/zip_main.c
@@ -351,6 +351,7 @@ static struct pci_driver zip_driver = {
static struct crypto_alg zip_comp_deflate = {
.cra_name = "deflate",
+ .cra_driver_name = "deflate-cavium",
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
.cra_ctxsize = sizeof(struct zip_kernel_ctx),
.cra_priority = 300,
@@ -365,6 +366,7 @@ static struct crypto_alg zip_comp_deflate = {
static struct crypto_alg zip_comp_lzs = {
.cra_name = "lzs",
+ .cra_driver_name = "lzs-cavium",
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
.cra_ctxsize = sizeof(struct zip_kernel_ctx),
.cra_priority = 300,
@@ -384,7 +386,7 @@ static struct scomp_alg zip_scomp_deflate = {
.decompress = zip_scomp_decompress,
.base = {
.cra_name = "deflate",
- .cra_driver_name = "deflate-scomp",
+ .cra_driver_name = "deflate-scomp-cavium",
.cra_module = THIS_MODULE,
.cra_priority = 300,
}
@@ -397,7 +399,7 @@ static struct scomp_alg zip_scomp_lzs = {
.decompress = zip_scomp_decompress,
.base = {
.cra_name = "lzs",
- .cra_driver_name = "lzs-scomp",
+ .cra_driver_name = "lzs-scomp-cavium",
.cra_module = THIS_MODULE,
.cra_priority = 300,
}
@@ -618,41 +620,23 @@ static const struct file_operations zip_regs_fops = {
/* Root directory for thunderx_zip debugfs entry */
static struct dentry *zip_debugfs_root;
-static int __init zip_debugfs_init(void)
+static void __init zip_debugfs_init(void)
{
- struct dentry *zip_stats, *zip_clear, *zip_regs;
-
if (!debugfs_initialized())
- return -ENODEV;
+ return;
zip_debugfs_root = debugfs_create_dir("thunderx_zip", NULL);
- if (!zip_debugfs_root)
- return -ENOMEM;
/* Creating files for entries inside thunderx_zip directory */
- zip_stats = debugfs_create_file("zip_stats", 0444,
- zip_debugfs_root,
- NULL, &zip_stats_fops);
- if (!zip_stats)
- goto failed_to_create;
-
- zip_clear = debugfs_create_file("zip_clear", 0444,
- zip_debugfs_root,
- NULL, &zip_clear_fops);
- if (!zip_clear)
- goto failed_to_create;
-
- zip_regs = debugfs_create_file("zip_regs", 0444,
- zip_debugfs_root,
- NULL, &zip_regs_fops);
- if (!zip_regs)
- goto failed_to_create;
+ debugfs_create_file("zip_stats", 0444, zip_debugfs_root, NULL,
+ &zip_stats_fops);
- return 0;
+ debugfs_create_file("zip_clear", 0444, zip_debugfs_root, NULL,
+ &zip_clear_fops);
+
+ debugfs_create_file("zip_regs", 0444, zip_debugfs_root, NULL,
+ &zip_regs_fops);
-failed_to_create:
- debugfs_remove_recursive(zip_debugfs_root);
- return -ENOENT;
}
static void __exit zip_debugfs_exit(void)
@@ -661,13 +645,8 @@ static void __exit zip_debugfs_exit(void)
}
#else
-static int __init zip_debugfs_init(void)
-{
- return 0;
-}
-
+static void __init zip_debugfs_init(void) { }
static void __exit zip_debugfs_exit(void) { }
-
#endif
/* debugfs - end */
@@ -691,17 +670,10 @@ static int __init zip_init_module(void)
}
/* comp-decomp statistics are handled with debugfs interface */
- ret = zip_debugfs_init();
- if (ret < 0) {
- zip_err("ZIP: debugfs initialization failed\n");
- goto err_crypto_unregister;
- }
+ zip_debugfs_init();
return ret;
-err_crypto_unregister:
- zip_unregister_compression_device();
-
err_pci_unregister:
pci_unregister_driver(&zip_driver);
return ret;
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
index 9108015e56cc..f6e252c1d6fb 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
@@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) AES CMAC crypto API support
*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
*
diff --git a/drivers/crypto/ccp/ccp-crypto-des3.c b/drivers/crypto/ccp/ccp-crypto-des3.c
index ae87b741f9d5..c2ff551d215b 100644
--- a/drivers/crypto/ccp/ccp-crypto-des3.c
+++ b/drivers/crypto/ccp/ccp-crypto-des3.c
@@ -57,7 +57,7 @@ static int ccp_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
!((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
- (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
index 2ca64bb57d2e..10a61cd54fce 100644
--- a/drivers/crypto/ccp/ccp-crypto-sha.c
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) SHA crypto API support
*
- * Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
diff --git a/drivers/crypto/ccp/ccp-debugfs.c b/drivers/crypto/ccp/ccp-debugfs.c
index 1a734bd2070a..4bd26af7098d 100644
--- a/drivers/crypto/ccp/ccp-debugfs.c
+++ b/drivers/crypto/ccp/ccp-debugfs.c
@@ -286,10 +286,7 @@ void ccp5_debugfs_setup(struct ccp_device *ccp)
{
struct ccp_cmd_queue *cmd_q;
char name[MAX_NAME_LEN + 1];
- struct dentry *debugfs_info;
- struct dentry *debugfs_stats;
struct dentry *debugfs_q_instance;
- struct dentry *debugfs_q_stats;
int i;
if (!debugfs_initialized())
@@ -299,24 +296,14 @@ void ccp5_debugfs_setup(struct ccp_device *ccp)
if (!ccp_debugfs_dir)
ccp_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
mutex_unlock(&ccp_debugfs_lock);
- if (!ccp_debugfs_dir)
- return;
ccp->debugfs_instance = debugfs_create_dir(ccp->name, ccp_debugfs_dir);
- if (!ccp->debugfs_instance)
- goto err;
- debugfs_info = debugfs_create_file("info", 0400,
- ccp->debugfs_instance, ccp,
- &ccp_debugfs_info_ops);
- if (!debugfs_info)
- goto err;
+ debugfs_create_file("info", 0400, ccp->debugfs_instance, ccp,
+ &ccp_debugfs_info_ops);
- debugfs_stats = debugfs_create_file("stats", 0600,
- ccp->debugfs_instance, ccp,
- &ccp_debugfs_stats_ops);
- if (!debugfs_stats)
- goto err;
+ debugfs_create_file("stats", 0600, ccp->debugfs_instance, ccp,
+ &ccp_debugfs_stats_ops);
for (i = 0; i < ccp->cmd_q_count; i++) {
cmd_q = &ccp->cmd_q[i];
@@ -325,21 +312,12 @@ void ccp5_debugfs_setup(struct ccp_device *ccp)
debugfs_q_instance =
debugfs_create_dir(name, ccp->debugfs_instance);
- if (!debugfs_q_instance)
- goto err;
-
- debugfs_q_stats =
- debugfs_create_file("stats", 0600,
- debugfs_q_instance, cmd_q,
- &ccp_debugfs_queue_ops);
- if (!debugfs_q_stats)
- goto err;
+
+ debugfs_create_file("stats", 0600, debugfs_q_instance, cmd_q,
+ &ccp_debugfs_queue_ops);
}
return;
-
-err:
- debugfs_remove_recursive(ccp->debugfs_instance);
}
void ccp5_debugfs_destroy(void)
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index 44a4d2779b15..c9bfd4f439ce 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -822,9 +822,9 @@ static int ccp5_init(struct ccp_device *ccp)
/* Page alignment satisfies our needs for N <= 128 */
BUILD_BUG_ON(COMMANDS_PER_QUEUE > 128);
cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
- cmd_q->qbase = dma_zalloc_coherent(dev, cmd_q->qsize,
- &cmd_q->qbase_dma,
- GFP_KERNEL);
+ cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize,
+ &cmd_q->qbase_dma,
+ GFP_KERNEL);
if (!cmd_q->qbase) {
dev_err(dev, "unable to allocate command queue\n");
ret = -ENOMEM;
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index 0ea43cdeb05f..267a367bd076 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) driver
*
- * Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
index b16be8a11d92..fadf859a14b8 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -1,7 +1,7 @@
/*
* AMD Platform Security Processor (PSP) interface
*
- * Copyright (C) 2016-2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2016,2018 Advanced Micro Devices, Inc.
*
* Author: Brijesh Singh <brijesh.singh@amd.com>
*
@@ -437,6 +437,7 @@ static int sev_get_api_version(void)
psp_master->api_major = status->api_major;
psp_master->api_minor = status->api_minor;
psp_master->build = status->build;
+ psp_master->sev_state = status->state;
return 0;
}
@@ -857,15 +858,15 @@ static int sev_misc_init(struct psp_device *psp)
return 0;
}
-static int sev_init(struct psp_device *psp)
+static int psp_check_sev_support(struct psp_device *psp)
{
/* Check if device supports SEV feature */
if (!(ioread32(psp->io_regs + psp->vdata->feature_reg) & 1)) {
- dev_dbg(psp->dev, "device does not support SEV\n");
- return 1;
+ dev_dbg(psp->dev, "psp does not support SEV\n");
+ return -ENODEV;
}
- return sev_misc_init(psp);
+ return 0;
}
int psp_dev_init(struct sp_device *sp)
@@ -890,6 +891,10 @@ int psp_dev_init(struct sp_device *sp)
psp->io_regs = sp->io_map;
+ ret = psp_check_sev_support(psp);
+ if (ret)
+ goto e_disable;
+
/* Disable and clear interrupts until ready */
iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
@@ -901,7 +906,7 @@ int psp_dev_init(struct sp_device *sp)
goto e_err;
}
- ret = sev_init(psp);
+ ret = sev_misc_init(psp);
if (ret)
goto e_irq;
@@ -923,6 +928,11 @@ e_err:
dev_notice(dev, "psp initialization failed\n");
return ret;
+
+e_disable:
+ sp->psp_data = NULL;
+
+ return ret;
}
void psp_dev_destroy(struct sp_device *sp)
@@ -964,6 +974,21 @@ void psp_pci_init(void)
if (sev_get_api_version())
goto err;
+ /*
+ * If platform is not in UNINIT state then firmware upgrade and/or
+ * platform INIT command will fail. These command require UNINIT state.
+ *
+ * In a normal boot we should never run into case where the firmware
+ * is not in UNINIT state on boot. But in case of kexec boot, a reboot
+ * may not go through a typical shutdown sequence and may leave the
+ * firmware in INIT or WORKING state.
+ */
+
+ if (psp_master->sev_state != SEV_STATE_UNINIT) {
+ sev_platform_shutdown(NULL);
+ psp_master->sev_state = SEV_STATE_UNINIT;
+ }
+
if (SEV_VERSION_GREATER_OR_EQUAL(0, 15) &&
sev_update_firmware(psp_master->dev) == 0)
sev_get_api_version();
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
index 8b53a9674ecb..f5afeccf42a1 100644
--- a/drivers/crypto/ccp/psp-dev.h
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -1,7 +1,7 @@
/*
* AMD Platform Security Processor (PSP) interface driver
*
- * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
*
* Author: Brijesh Singh <brijesh.singh@amd.com>
*
diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
index e0459002eb71..b2879767fc98 100644
--- a/drivers/crypto/ccp/sp-dev.c
+++ b/drivers/crypto/ccp/sp-dev.c
@@ -1,7 +1,7 @@
/*
* AMD Secure Processor driver
*
- * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 14398cad1625..5b0790025db3 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -1,7 +1,7 @@
/*
* AMD Secure Processor driver
*
- * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index 7da93e9bebed..41bce0a3f4bb 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -1,7 +1,7 @@
/*
* AMD Secure Processor device driver
*
- * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
@@ -226,8 +226,6 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto e_err;
- dev_notice(dev, "enabled\n");
-
return 0;
e_err:
@@ -246,8 +244,6 @@ static void sp_pci_remove(struct pci_dev *pdev)
sp_destroy(sp);
sp_free_irqs(sp);
-
- dev_notice(dev, "disabled\n");
}
#ifdef CONFIG_PM
diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c
index b75dc7db2d4a..d24228efbaaa 100644
--- a/drivers/crypto/ccp/sp-platform.c
+++ b/drivers/crypto/ccp/sp-platform.c
@@ -1,7 +1,7 @@
/*
* AMD Secure Processor device driver
*
- * Copyright (C) 2014,2016 Advanced Micro Devices, Inc.
+ * Copyright (C) 2014,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
*
diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c
index f2643cda45db..a3527c00b29a 100644
--- a/drivers/crypto/ccree/cc_aead.c
+++ b/drivers/crypto/ccree/cc_aead.c
@@ -549,13 +549,12 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
- struct rtattr *rta = (struct rtattr *)key;
struct cc_crypto_req cc_req = {};
- struct crypto_authenc_key_param *param;
struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
- int rc = -EINVAL;
unsigned int seq_len = 0;
struct device *dev = drvdata_to_dev(ctx->drvdata);
+ const u8 *enckey, *authkey;
+ int rc;
dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
@@ -563,35 +562,33 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
/* STAT_PHASE_0: Init and sanity checks */
if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
- if (!RTA_OK(rta, keylen))
- goto badkey;
- if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
- goto badkey;
- if (RTA_PAYLOAD(rta) < sizeof(*param))
- goto badkey;
- param = RTA_DATA(rta);
- ctx->enc_keylen = be32_to_cpu(param->enckeylen);
- key += RTA_ALIGN(rta->rta_len);
- keylen -= RTA_ALIGN(rta->rta_len);
- if (keylen < ctx->enc_keylen)
+ struct crypto_authenc_keys keys;
+
+ rc = crypto_authenc_extractkeys(&keys, key, keylen);
+ if (rc)
goto badkey;
- ctx->auth_keylen = keylen - ctx->enc_keylen;
+ enckey = keys.enckey;
+ authkey = keys.authkey;
+ ctx->enc_keylen = keys.enckeylen;
+ ctx->auth_keylen = keys.authkeylen;
if (ctx->cipher_mode == DRV_CIPHER_CTR) {
/* the nonce is stored in bytes at end of key */
+ rc = -EINVAL;
if (ctx->enc_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
*/
- memcpy(ctx->ctr_nonce, key + ctx->auth_keylen +
- ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE,
- CTR_RFC3686_NONCE_SIZE);
+ memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen -
+ CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
/* Set CTR key size */
ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
}
} else { /* non-authenc - has just one key */
+ enckey = key;
+ authkey = NULL;
ctx->enc_keylen = keylen;
ctx->auth_keylen = 0;
}
@@ -603,13 +600,14 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
/* STAT_PHASE_1: Copy key to ctx */
/* Get key material */
- memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
+ memcpy(ctx->enckey, enckey, ctx->enc_keylen);
if (ctx->enc_keylen == 24)
memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
- memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
+ memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey,
+ ctx->auth_keylen);
} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
- rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
+ rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen);
if (rc)
goto badkey;
}
diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c
index dd948e1df9e5..0ee1c52da0a4 100644
--- a/drivers/crypto/ccree/cc_buffer_mgr.c
+++ b/drivers/crypto/ccree/cc_buffer_mgr.c
@@ -156,8 +156,11 @@ static int cc_render_buff_to_mlli(struct device *dev, dma_addr_t buff_dma,
/* 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)
+ if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES) {
+ dev_err(dev, "Too many mlli entries. current %d max %d\n",
+ new_nents, MAX_NUM_OF_TOTAL_MLLI_ENTRIES);
return -ENOMEM;
+ }
/*handle buffer longer than 64 kbytes */
while (buff_size > CC_MAX_MLLI_ENTRY_SIZE) {
@@ -511,10 +514,8 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx,
/* Map the src SGL */
rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
- if (rc) {
- rc = -ENOMEM;
+ if (rc)
goto cipher_exit;
- }
if (mapped_nents > 1)
req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
@@ -528,12 +529,11 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx,
}
} else {
/* Map the dst sg */
- if (cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL,
- &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
- &dummy, &mapped_nents)) {
- rc = -ENOMEM;
+ rc = cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL,
+ &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
+ &dummy, &mapped_nents);
+ if (rc)
goto cipher_exit;
- }
if (mapped_nents > 1)
req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
@@ -614,10 +614,10 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req)
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) {
+ /* Release pool */
+ if ((areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
+ areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) &&
+ (areq_ctx->mlli_params.mlli_virt_addr)) {
dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
&areq_ctx->mlli_params.mlli_dma_addr,
areq_ctx->mlli_params.mlli_virt_addr);
@@ -1078,10 +1078,8 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata,
&areq_ctx->dst.nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes,
&dst_mapped_nents);
- if (rc) {
- rc = -ENOMEM;
+ if (rc)
goto chain_data_exit;
- }
}
dst_mapped_nents = cc_get_sgl_nents(dev, req->dst, size_for_map,
@@ -1235,11 +1233,10 @@ int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req)
}
areq_ctx->ccm_iv0_dma_addr = dma_addr;
- if (cc_set_aead_conf_buf(dev, areq_ctx, areq_ctx->ccm_config,
- &sg_data, req->assoclen)) {
- rc = -ENOMEM;
+ rc = cc_set_aead_conf_buf(dev, areq_ctx, areq_ctx->ccm_config,
+ &sg_data, req->assoclen);
+ if (rc)
goto aead_map_failure;
- }
}
if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
@@ -1299,10 +1296,8 @@ int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req)
(LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES +
LLI_MAX_NUM_OF_DATA_ENTRIES),
&dummy, &mapped_nents);
- if (rc) {
- rc = -ENOMEM;
+ if (rc)
goto aead_map_failure;
- }
if (areq_ctx->is_single_pass) {
/*
@@ -1386,6 +1381,7 @@ int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
struct mlli_params *mlli_params = &areq_ctx->mlli_params;
struct buffer_array sg_data;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
+ int rc = 0;
u32 dummy = 0;
u32 mapped_nents = 0;
@@ -1405,18 +1401,18 @@ int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
/*TODO: copy data in case that buffer is enough for operation */
/* map the previous buffer */
if (*curr_buff_cnt) {
- if (cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
- &sg_data)) {
- return -ENOMEM;
- }
+ rc = cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
+ &sg_data);
+ if (rc)
+ return rc;
}
if (src && nbytes > 0 && do_update) {
- if (cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE,
- &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
- &dummy, &mapped_nents)) {
+ rc = cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE,
+ &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
+ &dummy, &mapped_nents);
+ if (rc)
goto unmap_curr_buff;
- }
if (src && mapped_nents == 1 &&
areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
memcpy(areq_ctx->buff_sg, src,
@@ -1435,7 +1431,8 @@ int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
/* add the src data to the sg_data */
cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes,
0, true, &areq_ctx->mlli_nents);
- if (cc_generate_mlli(dev, &sg_data, mlli_params, flags))
+ rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
+ if (rc)
goto fail_unmap_din;
}
/* change the buffer index for the unmap function */
@@ -1451,7 +1448,7 @@ unmap_curr_buff:
if (*curr_buff_cnt)
dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
- return -ENOMEM;
+ return rc;
}
int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
@@ -1470,6 +1467,7 @@ int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
struct buffer_array sg_data;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
unsigned int swap_index = 0;
+ int rc = 0;
u32 dummy = 0;
u32 mapped_nents = 0;
@@ -1514,21 +1512,21 @@ int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
}
if (*curr_buff_cnt) {
- if (cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
- &sg_data)) {
- return -ENOMEM;
- }
+ rc = cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
+ &sg_data);
+ if (rc)
+ return rc;
/* change the buffer index for next operation */
swap_index = 1;
}
if (update_data_len > *curr_buff_cnt) {
- if (cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt),
- DMA_TO_DEVICE, &areq_ctx->in_nents,
- LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
- &mapped_nents)) {
+ rc = cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt),
+ DMA_TO_DEVICE, &areq_ctx->in_nents,
+ LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
+ &mapped_nents);
+ if (rc)
goto unmap_curr_buff;
- }
if (mapped_nents == 1 &&
areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
/* only one entry in the SG and no previous data */
@@ -1548,7 +1546,8 @@ int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src,
(update_data_len - *curr_buff_cnt), 0, true,
&areq_ctx->mlli_nents);
- if (cc_generate_mlli(dev, &sg_data, mlli_params, flags))
+ rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
+ if (rc)
goto fail_unmap_din;
}
areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
@@ -1562,7 +1561,7 @@ unmap_curr_buff:
if (*curr_buff_cnt)
dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
- return -ENOMEM;
+ return rc;
}
void cc_unmap_hash_request(struct device *dev, void *ctx,
diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c
index cc92b031fad1..d9c17078517b 100644
--- a/drivers/crypto/ccree/cc_cipher.c
+++ b/drivers/crypto/ccree/cc_cipher.c
@@ -80,6 +80,7 @@ static int validate_keys_sizes(struct cc_cipher_ctx *ctx_p, u32 size)
default:
break;
}
+ break;
case S_DIN_to_DES:
if (size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE)
return 0;
@@ -352,7 +353,8 @@ static int cc_cipher_setkey(struct crypto_skcipher *sktfm, const u8 *key,
dev_dbg(dev, "weak 3DES key");
return -EINVAL;
} else if (!des_ekey(tmp, key) &&
- (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ (crypto_tfm_get_flags(tfm) &
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
dev_dbg(dev, "weak DES key");
return -EINVAL;
@@ -652,6 +654,8 @@ static void cc_cipher_complete(struct device *dev, void *cc_req, int err)
unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm);
unsigned int len;
+ cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst);
+
switch (ctx_p->cipher_mode) {
case DRV_CIPHER_CBC:
/*
@@ -681,7 +685,6 @@ static void cc_cipher_complete(struct device *dev, void *cc_req, int err)
break;
}
- cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst);
kzfree(req_ctx->iv);
skcipher_request_complete(req, err);
@@ -799,7 +802,8 @@ static int cc_cipher_decrypt(struct skcipher_request *req)
memset(req_ctx, 0, sizeof(*req_ctx));
- if (ctx_p->cipher_mode == DRV_CIPHER_CBC) {
+ if ((ctx_p->cipher_mode == DRV_CIPHER_CBC) &&
+ (req->cryptlen >= ivsize)) {
/* Allocate and save the last IV sized bytes of the source,
* which will be lost in case of in-place decryption.
diff --git a/drivers/crypto/ccree/cc_debugfs.c b/drivers/crypto/ccree/cc_debugfs.c
index 5ca184e42483..5fa05a7bcf36 100644
--- a/drivers/crypto/ccree/cc_debugfs.c
+++ b/drivers/crypto/ccree/cc_debugfs.c
@@ -39,11 +39,9 @@ static struct debugfs_reg32 debug_regs[] = {
CC_DEBUG_REG(AXIM_MON_COMP),
};
-int __init cc_debugfs_global_init(void)
+void __init cc_debugfs_global_init(void)
{
cc_debugfs_dir = debugfs_create_dir("ccree", NULL);
-
- return !cc_debugfs_dir;
}
void __exit cc_debugfs_global_fini(void)
@@ -56,7 +54,6 @@ int cc_debugfs_init(struct cc_drvdata *drvdata)
struct device *dev = drvdata_to_dev(drvdata);
struct cc_debugfs_ctx *ctx;
struct debugfs_regset32 *regset;
- struct dentry *file;
debug_regs[0].offset = drvdata->sig_offset;
debug_regs[1].offset = drvdata->ver_offset;
@@ -74,22 +71,9 @@ int cc_debugfs_init(struct cc_drvdata *drvdata)
regset->base = drvdata->cc_base;
ctx->dir = debugfs_create_dir(drvdata->plat_dev->name, cc_debugfs_dir);
- if (!ctx->dir)
- return -ENFILE;
-
- file = debugfs_create_regset32("regs", 0400, ctx->dir, regset);
- if (!file) {
- debugfs_remove(ctx->dir);
- return -ENFILE;
- }
- file = debugfs_create_bool("coherent", 0400, ctx->dir,
- &drvdata->coherent);
-
- if (!file) {
- debugfs_remove_recursive(ctx->dir);
- return -ENFILE;
- }
+ debugfs_create_regset32("regs", 0400, ctx->dir, regset);
+ debugfs_create_bool("coherent", 0400, ctx->dir, &drvdata->coherent);
drvdata->debugfs = ctx;
diff --git a/drivers/crypto/ccree/cc_debugfs.h b/drivers/crypto/ccree/cc_debugfs.h
index 5b5320eca7d2..01cbd9a95659 100644
--- a/drivers/crypto/ccree/cc_debugfs.h
+++ b/drivers/crypto/ccree/cc_debugfs.h
@@ -5,7 +5,7 @@
#define __CC_DEBUGFS_H__
#ifdef CONFIG_DEBUG_FS
-int cc_debugfs_global_init(void);
+void cc_debugfs_global_init(void);
void cc_debugfs_global_fini(void);
int cc_debugfs_init(struct cc_drvdata *drvdata);
@@ -13,11 +13,7 @@ void cc_debugfs_fini(struct cc_drvdata *drvdata);
#else
-static inline int cc_debugfs_global_init(void)
-{
- return 0;
-}
-
+static inline void cc_debugfs_global_init(void) {}
static inline void cc_debugfs_global_fini(void) {}
static inline int cc_debugfs_init(struct cc_drvdata *drvdata)
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c
index 8ada308d72ee..3bcc6c76e090 100644
--- a/drivers/crypto/ccree/cc_driver.c
+++ b/drivers/crypto/ccree/cc_driver.c
@@ -103,10 +103,10 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
/* read the interrupt status */
irr = cc_ioread(drvdata, CC_REG(HOST_IRR));
dev_dbg(dev, "Got IRR=0x%08X\n", irr);
- if (irr == 0) { /* Probably shared interrupt line */
- dev_err(dev, "Got interrupt with empty IRR\n");
+
+ if (irr == 0) /* Probably shared interrupt line */
return IRQ_NONE;
- }
+
imr = cc_ioread(drvdata, CC_REG(HOST_IMR));
/* clear interrupt - must be before processing events */
@@ -380,7 +380,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
rc = cc_ivgen_init(new_drvdata);
if (rc) {
dev_err(dev, "cc_ivgen_init failed\n");
- goto post_power_mgr_err;
+ goto post_buf_mgr_err;
}
/* Allocate crypto algs */
@@ -403,6 +403,9 @@ static int init_cc_resources(struct platform_device *plat_dev)
goto post_hash_err;
}
+ /* All set, we can allow autosuspend */
+ cc_pm_go(new_drvdata);
+
/* If we got here and FIPS mode is enabled
* it means all FIPS test passed, so let TEE
* know we're good.
@@ -417,8 +420,6 @@ post_cipher_err:
cc_cipher_free(new_drvdata);
post_ivgen_err:
cc_ivgen_fini(new_drvdata);
-post_power_mgr_err:
- cc_pm_fini(new_drvdata);
post_buf_mgr_err:
cc_buffer_mgr_fini(new_drvdata);
post_req_mgr_err:
@@ -538,13 +539,8 @@ static struct platform_driver ccree_driver = {
static int __init ccree_init(void)
{
- int ret;
-
cc_hash_global_init();
-
- ret = cc_debugfs_global_init();
- if (ret)
- return ret;
+ cc_debugfs_global_init();
return platform_driver_register(&ccree_driver);
}
diff --git a/drivers/crypto/ccree/cc_driver.h b/drivers/crypto/ccree/cc_driver.h
index 5be7fd431b05..33dbf3e6d15d 100644
--- a/drivers/crypto/ccree/cc_driver.h
+++ b/drivers/crypto/ccree/cc_driver.h
@@ -111,13 +111,11 @@ struct cc_crypto_req {
* @cc_base: virt address of the CC registers
* @irq: device IRQ number
* @irq_mask: Interrupt mask shadow (1 for masked interrupts)
- * @fw_ver: SeP loaded firmware version
*/
struct cc_drvdata {
void __iomem *cc_base;
int irq;
u32 irq_mask;
- u32 fw_ver;
struct completion hw_queue_avail; /* wait for HW queue availability */
struct platform_device *plat_dev;
cc_sram_addr_t mlli_sram_addr;
diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c
index d990f472e89f..6ff7e75ad90e 100644
--- a/drivers/crypto/ccree/cc_pm.c
+++ b/drivers/crypto/ccree/cc_pm.c
@@ -100,20 +100,19 @@ int cc_pm_put_suspend(struct device *dev)
int cc_pm_init(struct cc_drvdata *drvdata)
{
- int rc = 0;
struct device *dev = drvdata_to_dev(drvdata);
/* must be before the enabling to avoid resdundent suspending */
pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev);
/* activate the PM module */
- rc = pm_runtime_set_active(dev);
- if (rc)
- return rc;
- /* enable the PM module*/
- pm_runtime_enable(dev);
+ return pm_runtime_set_active(dev);
+}
- return rc;
+/* enable the PM module*/
+void cc_pm_go(struct cc_drvdata *drvdata)
+{
+ pm_runtime_enable(drvdata_to_dev(drvdata));
}
void cc_pm_fini(struct cc_drvdata *drvdata)
diff --git a/drivers/crypto/ccree/cc_pm.h b/drivers/crypto/ccree/cc_pm.h
index 020a5403c58b..907a6db4d6c0 100644
--- a/drivers/crypto/ccree/cc_pm.h
+++ b/drivers/crypto/ccree/cc_pm.h
@@ -16,6 +16,7 @@
extern const struct dev_pm_ops ccree_pm;
int cc_pm_init(struct cc_drvdata *drvdata);
+void cc_pm_go(struct cc_drvdata *drvdata);
void cc_pm_fini(struct cc_drvdata *drvdata);
int cc_pm_suspend(struct device *dev);
int cc_pm_resume(struct device *dev);
@@ -29,6 +30,8 @@ static inline int cc_pm_init(struct cc_drvdata *drvdata)
return 0;
}
+static inline void cc_pm_go(struct cc_drvdata *drvdata) {}
+
static inline void cc_pm_fini(struct cc_drvdata *drvdata) {}
static inline int cc_pm_suspend(struct device *dev)
diff --git a/drivers/crypto/chelsio/Makefile b/drivers/crypto/chelsio/Makefile
index 639e5718dff4..b7bd980a27d8 100644
--- a/drivers/crypto/chelsio/Makefile
+++ b/drivers/crypto/chelsio/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
+ccflags-y := -I $(srctree)/drivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chcr.o
chcr-objs := chcr_core.o chcr_algo.o
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index bcef76508dfa..8d8cf80b9294 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -1368,7 +1368,6 @@ static int chcr_aes_decrypt(struct ablkcipher_request *req)
static int chcr_device_init(struct chcr_context *ctx)
{
struct uld_ctx *u_ctx = NULL;
- struct adapter *adap;
unsigned int id;
int txq_perchan, txq_idx, ntxq;
int err = 0, rxq_perchan, rxq_idx;
@@ -1382,7 +1381,6 @@ static int chcr_device_init(struct chcr_context *ctx)
goto out;
}
ctx->dev = &u_ctx->dev;
- adap = padap(ctx->dev);
ntxq = u_ctx->lldi.ntxq;
rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
txq_perchan = ntxq / u_ctx->lldi.nchan;
@@ -2762,7 +2760,7 @@ static int set_msg_len(u8 *block, unsigned int msglen, int csize)
return 0;
}
-static void generate_b0(struct aead_request *req, u8 *ivptr,
+static int generate_b0(struct aead_request *req, u8 *ivptr,
unsigned short op_type)
{
unsigned int l, lp, m;
@@ -2787,6 +2785,8 @@ static void generate_b0(struct aead_request *req, u8 *ivptr,
rc = set_msg_len(b0 + 16 - l,
(op_type == CHCR_DECRYPT_OP) ?
req->cryptlen - m : req->cryptlen, l);
+
+ return rc;
}
static inline int crypto_ccm_check_iv(const u8 *iv)
@@ -2821,7 +2821,7 @@ static int ccm_format_packet(struct aead_request *req,
*((unsigned short *)(reqctx->scratch_pad + 16)) =
htons(assoclen);
- generate_b0(req, ivptr, op_type);
+ rc = generate_b0(req, ivptr, op_type);
/* zero the ctr value */
memset(ivptr + 15 - ivptr[0], 0, ivptr[0] + 1);
return rc;
@@ -3676,9 +3676,9 @@ static int chcr_aead_op(struct aead_request *req,
/* Form a WR from req */
skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[a_ctx(tfm)->rx_qidx], size);
- if (IS_ERR(skb) || !skb) {
+ if (IS_ERR_OR_NULL(skb)) {
chcr_dec_wrcount(cdev);
- return PTR_ERR(skb);
+ return PTR_ERR_OR_ZERO(skb);
}
skb->dev = u_ctx->lldi.ports[0];
diff --git a/drivers/crypto/chelsio/chcr_core.h b/drivers/crypto/chelsio/chcr_core.h
index 1159dee964ed..ad874d548aa5 100644
--- a/drivers/crypto/chelsio/chcr_core.h
+++ b/drivers/crypto/chelsio/chcr_core.h
@@ -183,7 +183,7 @@ struct chcr_ipsec_aadiv {
struct ipsec_sa_entry {
int hmac_ctrl;
u16 esn;
- u16 imm;
+ u16 resv;
unsigned int enckey_len;
unsigned int kctx_len;
unsigned int authsize;
diff --git a/drivers/crypto/chelsio/chcr_ipsec.c b/drivers/crypto/chelsio/chcr_ipsec.c
index 2fb48cce4462..2f60049361ef 100644
--- a/drivers/crypto/chelsio/chcr_ipsec.c
+++ b/drivers/crypto/chelsio/chcr_ipsec.c
@@ -303,6 +303,9 @@ static bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
return false;
}
+ /* Inline single pdu */
+ if (skb_shinfo(skb)->gso_size)
+ return false;
return true;
}
@@ -333,7 +336,8 @@ static inline int is_eth_imm(const struct sk_buff *skb,
}
static inline unsigned int calc_tx_sec_flits(const struct sk_buff *skb,
- struct ipsec_sa_entry *sa_entry)
+ struct ipsec_sa_entry *sa_entry,
+ bool *immediate)
{
unsigned int kctx_len;
unsigned int flits;
@@ -351,8 +355,10 @@ static inline unsigned int calc_tx_sec_flits(const struct sk_buff *skb,
* TX Packet header plus the skb data in the Work Request.
*/
- if (hdrlen)
+ if (hdrlen) {
+ *immediate = true;
return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64));
+ }
flits = sgl_len(skb_shinfo(skb)->nr_frags + 1);
@@ -415,12 +421,12 @@ inline void *copy_esn_pktxt(struct sk_buff *skb,
iv = skb_transport_header(skb) + sizeof(struct ip_esp_hdr);
memcpy(aadiv->iv, iv, 8);
- if (sa_entry->imm) {
+ if (is_eth_imm(skb, sa_entry) && !skb_is_nonlinear(skb)) {
sc_imm = (struct ulptx_idata *)(pos +
(DIV_ROUND_UP(sizeof(struct chcr_ipsec_aadiv),
sizeof(__be64)) << 3));
- sc_imm->cmd_more = FILL_CMD_MORE(!sa_entry->imm);
- sc_imm->len = cpu_to_be32(sa_entry->imm);
+ sc_imm->cmd_more = FILL_CMD_MORE(0);
+ sc_imm->len = cpu_to_be32(skb->len);
}
pos += len;
return pos;
@@ -528,15 +534,18 @@ inline void *chcr_crypto_wreq(struct sk_buff *skb,
struct adapter *adap = pi->adapter;
unsigned int ivsize = GCM_ESP_IV_SIZE;
struct chcr_ipsec_wr *wr;
+ bool immediate = false;
u16 immdatalen = 0;
unsigned int flits;
u32 ivinoffset;
u32 aadstart;
u32 aadstop;
u32 ciphstart;
+ u16 sc_more = 0;
u32 ivdrop = 0;
u32 esnlen = 0;
u32 wr_mid;
+ u16 ndesc;
int qidx = skb_get_queue_mapping(skb);
struct sge_eth_txq *q = &adap->sge.ethtxq[qidx + pi->first_qset];
unsigned int kctx_len = sa_entry->kctx_len;
@@ -544,22 +553,24 @@ inline void *chcr_crypto_wreq(struct sk_buff *skb,
atomic_inc(&adap->chcr_stats.ipsec_cnt);
- flits = calc_tx_sec_flits(skb, sa_entry);
+ flits = calc_tx_sec_flits(skb, sa_entry, &immediate);
+ ndesc = DIV_ROUND_UP(flits, 2);
if (sa_entry->esn)
ivdrop = 1;
- if (is_eth_imm(skb, sa_entry)) {
+ if (immediate)
immdatalen = skb->len;
- sa_entry->imm = immdatalen;
- }
- if (sa_entry->esn)
+ if (sa_entry->esn) {
esnlen = sizeof(struct chcr_ipsec_aadiv);
+ if (!skb_is_nonlinear(skb))
+ sc_more = 1;
+ }
/* WR Header */
wr = (struct chcr_ipsec_wr *)pos;
wr->wreq.op_to_compl = htonl(FW_WR_OP_V(FW_ULPTX_WR));
- wr_mid = FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(flits, 2));
+ wr_mid = FW_CRYPTO_LOOKASIDE_WR_LEN16_V(ndesc);
if (unlikely(credits < ETHTXQ_STOP_THRES)) {
netif_tx_stop_queue(q->txq);
@@ -571,10 +582,10 @@ inline void *chcr_crypto_wreq(struct sk_buff *skb,
/* ULPTX */
wr->req.ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(pi->port_id, qid);
- wr->req.ulptx.len = htonl(DIV_ROUND_UP(flits, 2) - 1);
+ wr->req.ulptx.len = htonl(ndesc - 1);
/* Sub-command */
- wr->req.sc_imm.cmd_more = FILL_CMD_MORE(!immdatalen);
+ wr->req.sc_imm.cmd_more = FILL_CMD_MORE(!immdatalen || sc_more);
wr->req.sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) +
sizeof(wr->req.key_ctx) +
kctx_len +
@@ -697,7 +708,7 @@ out_free: dev_kfree_skb_any(skb);
cxgb4_reclaim_completed_tx(adap, &q->q, true);
- flits = calc_tx_sec_flits(skb, sa_entry);
+ flits = calc_tx_sec_flits(skb, sa_entry, &immediate);
ndesc = flits_to_desc(flits);
credits = txq_avail(&q->q) - ndesc;
@@ -710,9 +721,6 @@ out_free: dev_kfree_skb_any(skb);
return NETDEV_TX_BUSY;
}
- if (is_eth_imm(skb, sa_entry))
- immediate = true;
-
if (!immediate &&
unlikely(cxgb4_map_skb(adap->pdev_dev, skb, addr) < 0)) {
q->mapping_err++;
diff --git a/drivers/crypto/chelsio/chtls/Makefile b/drivers/crypto/chelsio/chtls/Makefile
index df1379570a8e..b958f1b8ec39 100644
--- a/drivers/crypto/chelsio/chtls/Makefile
+++ b/drivers/crypto/chelsio/chtls/Makefile
@@ -1,4 +1,5 @@
-ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4 -Idrivers/crypto/chelsio/
+ccflags-y := -I $(srctree)/drivers/net/ethernet/chelsio/cxgb4 \
+ -I $(srctree)/drivers/crypto/chelsio
obj-$(CONFIG_CRYPTO_DEV_CHELSIO_TLS) += chtls.o
chtls-objs := chtls_main.o chtls_cm.o chtls_io.o chtls_hw.o
diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c
index 59b75299fcbc..4e22332496c5 100644
--- a/drivers/crypto/chelsio/chtls/chtls_cm.c
+++ b/drivers/crypto/chelsio/chtls/chtls_cm.c
@@ -24,6 +24,7 @@
#include <net/inet_common.h>
#include <net/tcp.h>
#include <net/dst.h>
+#include <net/tls.h>
#include "chtls.h"
#include "chtls_cm.h"
@@ -615,7 +616,7 @@ int chtls_listen_start(struct chtls_dev *cdev, struct sock *sk)
pi = netdev_priv(ndev);
adap = pi->adapter;
- if (!(adap->flags & FULL_INIT_DONE))
+ if (!(adap->flags & CXGB4_FULL_INIT_DONE))
return -EBADF;
if (listen_hash_find(cdev, sk) >= 0) /* already have it */
@@ -1015,6 +1016,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
{
struct inet_sock *newinet;
const struct iphdr *iph;
+ struct tls_context *ctx;
struct net_device *ndev;
struct chtls_sock *csk;
struct dst_entry *dst;
@@ -1063,6 +1065,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
oreq->ts_recent = PASS_OPEN_TID_G(ntohl(req->tos_stid));
sk_setup_caps(newsk, dst);
+ ctx = tls_get_ctx(lsk);
+ newsk->sk_destruct = ctx->sk_destruct;
csk->sk = newsk;
csk->passive_reap_next = oreq;
csk->tx_chan = cxgb4_port_chan(ndev);
diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c
index 18f553fcc167..1285a1bceda7 100644
--- a/drivers/crypto/chelsio/chtls/chtls_io.c
+++ b/drivers/crypto/chelsio/chtls/chtls_io.c
@@ -922,14 +922,13 @@ static int csk_wait_memory(struct chtls_dev *cdev,
struct sock *sk, long *timeo_p)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
- int sndbuf, err = 0;
+ int err = 0;
long current_timeo;
long vm_wait = 0;
bool noblock;
current_timeo = *timeo_p;
noblock = (*timeo_p ? false : true);
- sndbuf = cdev->max_host_sndbuf;
if (csk_mem_free(cdev, sk)) {
current_timeo = (prandom_u32() % (HZ / 5)) + 2;
vm_wait = (prandom_u32() % (HZ / 5)) + 2;
@@ -1401,23 +1400,18 @@ static int chtls_pt_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len)
{
struct chtls_sock *csk = rcu_dereference_sk_user_data(sk);
- struct net_device *dev = csk->egress_dev;
struct chtls_hws *hws = &csk->tlshws;
struct tcp_sock *tp = tcp_sk(sk);
- struct adapter *adap;
unsigned long avail;
int buffers_freed;
int copied = 0;
- int request;
int target;
long timeo;
- adap = netdev2adap(dev);
buffers_freed = 0;
timeo = sock_rcvtimeo(sk, nonblock);
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
- request = len;
if (unlikely(csk_flag(sk, CSK_UPDATE_RCV_WND)))
chtls_cleanup_rbuf(sk, copied);
@@ -1694,11 +1688,9 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
{
struct tcp_sock *tp = tcp_sk(sk);
struct chtls_sock *csk;
- struct chtls_hws *hws;
unsigned long avail; /* amount of available data in current skb */
int buffers_freed;
int copied = 0;
- int request;
long timeo;
int target; /* Read at least this many bytes */
@@ -1718,7 +1710,6 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
lock_sock(sk);
csk = rcu_dereference_sk_user_data(sk);
- hws = &csk->tlshws;
if (is_tls_rx(csk))
return chtls_pt_recvmsg(sk, msg, len, nonblock,
@@ -1726,7 +1717,6 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
timeo = sock_rcvtimeo(sk, nonblock);
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
- request = len;
if (unlikely(csk_flag(sk, CSK_UPDATE_RCV_WND)))
chtls_cleanup_rbuf(sk, copied);
diff --git a/drivers/crypto/chelsio/chtls/chtls_main.c b/drivers/crypto/chelsio/chtls/chtls_main.c
index 563f8fe7686a..dd2daf2a54e0 100644
--- a/drivers/crypto/chelsio/chtls/chtls_main.c
+++ b/drivers/crypto/chelsio/chtls/chtls_main.c
@@ -30,7 +30,6 @@
*/
static LIST_HEAD(cdev_list);
static DEFINE_MUTEX(cdev_mutex);
-static DEFINE_MUTEX(cdev_list_lock);
static DEFINE_MUTEX(notify_mutex);
static RAW_NOTIFIER_HEAD(listen_notify_list);
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index a5a36fe7bf2c..dad212cabe63 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -1961,7 +1961,8 @@ static int hifn_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
u32 tmp[DES_EXPKEY_WORDS];
int ret = des_ekey(tmp, key);
- if (unlikely(ret == 0) && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (unlikely(ret == 0) &&
+ (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c
index cdc4f9a171d9..adc0cd8ae97b 100644
--- a/drivers/crypto/hisilicon/sec/sec_algs.c
+++ b/drivers/crypto/hisilicon/sec/sec_algs.c
@@ -241,8 +241,8 @@ static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm,
memset(ctx->key, 0, SEC_MAX_CIPHER_KEY);
} else {
/* new key */
- ctx->key = dma_zalloc_coherent(dev, SEC_MAX_CIPHER_KEY,
- &ctx->pkey, GFP_KERNEL);
+ ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY,
+ &ctx->pkey, GFP_KERNEL);
if (!ctx->key) {
mutex_unlock(&ctx->lock);
return -ENOMEM;
diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c
index c1ee4e7bf996..91ee2bb575df 100644
--- a/drivers/crypto/hisilicon/sec/sec_drv.c
+++ b/drivers/crypto/hisilicon/sec/sec_drv.c
@@ -1082,9 +1082,8 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
struct sec_queue_ring_db *ring_db = &queue->ring_db;
int ret;
- ring_cmd->vaddr = dma_zalloc_coherent(dev, SEC_Q_CMD_SIZE,
- &ring_cmd->paddr,
- GFP_KERNEL);
+ ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE,
+ &ring_cmd->paddr, GFP_KERNEL);
if (!ring_cmd->vaddr)
return -ENOMEM;
@@ -1092,17 +1091,15 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
mutex_init(&ring_cmd->lock);
ring_cmd->callback = sec_alg_callback;
- ring_cq->vaddr = dma_zalloc_coherent(dev, SEC_Q_CQ_SIZE,
- &ring_cq->paddr,
- GFP_KERNEL);
+ ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE,
+ &ring_cq->paddr, GFP_KERNEL);
if (!ring_cq->vaddr) {
ret = -ENOMEM;
goto err_free_ring_cmd;
}
- ring_db->vaddr = dma_zalloc_coherent(dev, SEC_Q_DB_SIZE,
- &ring_db->paddr,
- GFP_KERNEL);
+ ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE,
+ &ring_db->paddr, GFP_KERNEL);
if (!ring_db->vaddr) {
ret = -ENOMEM;
goto err_free_ring_cq;
diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c
index d531c14020dc..7ef30a98cb24 100644
--- a/drivers/crypto/inside-secure/safexcel_cipher.c
+++ b/drivers/crypto/inside-secure/safexcel_cipher.c
@@ -940,7 +940,7 @@ static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
}
ret = des_ekey(tmp, key);
- if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 19fba998b86b..5c4659b04d70 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -260,9 +260,9 @@ static int setup_crypt_desc(void)
{
struct device *dev = &pdev->dev;
BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64);
- crypt_virt = dma_zalloc_coherent(dev,
- NPE_QLEN * sizeof(struct crypt_ctl),
- &crypt_phys, GFP_ATOMIC);
+ crypt_virt = dma_alloc_coherent(dev,
+ NPE_QLEN * sizeof(struct crypt_ctl),
+ &crypt_phys, GFP_ATOMIC);
if (!crypt_virt)
return -ENOMEM;
return 0;
@@ -847,7 +847,7 @@ static int ablk_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
goto out;
if (*flags & CRYPTO_TFM_RES_WEAK_KEY) {
- if (*flags & CRYPTO_TFM_REQ_WEAK_KEY) {
+ if (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) {
ret = -EINVAL;
} else {
*flags &= ~CRYPTO_TFM_RES_WEAK_KEY;
@@ -1125,7 +1125,7 @@ static int aead_setup(struct crypto_aead *tfm, unsigned int authsize)
goto out;
if (*flags & CRYPTO_TFM_RES_WEAK_KEY) {
- if (*flags & CRYPTO_TFM_REQ_WEAK_KEY) {
+ if (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) {
ret = -EINVAL;
goto out;
} else {
diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
index 0ae84ec9e21c..fb279b3a1ca1 100644
--- a/drivers/crypto/marvell/cipher.c
+++ b/drivers/crypto/marvell/cipher.c
@@ -286,7 +286,7 @@ static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
}
ret = des_ekey(tmp, key);
- if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
@@ -322,7 +322,6 @@ static int mv_cesa_skcipher_dma_req_init(struct skcipher_request *req,
struct mv_cesa_skcipher_dma_iter iter;
bool skip_ctx = false;
int ret;
- unsigned int ivsize;
basereq->chain.first = NULL;
basereq->chain.last = NULL;
@@ -381,7 +380,6 @@ static int mv_cesa_skcipher_dma_req_init(struct skcipher_request *req,
} while (mv_cesa_skcipher_req_iter_next_op(&iter));
/* Add output data for IV */
- ivsize = crypto_skcipher_ivsize(crypto_skcipher_reqtfm(req));
ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET,
CESA_SA_DATA_SRAM_OFFSET,
CESA_TDMA_SRC_IN_SRAM, flags);
diff --git a/drivers/crypto/mediatek/mtk-platform.c b/drivers/crypto/mediatek/mtk-platform.c
index ee0404e27a0f..5660e5e5e022 100644
--- a/drivers/crypto/mediatek/mtk-platform.c
+++ b/drivers/crypto/mediatek/mtk-platform.c
@@ -453,17 +453,17 @@ static int mtk_desc_ring_alloc(struct mtk_cryp *cryp)
if (!ring[i])
goto err_cleanup;
- ring[i]->cmd_base = dma_zalloc_coherent(cryp->dev,
- MTK_DESC_RING_SZ,
- &ring[i]->cmd_dma,
- GFP_KERNEL);
+ ring[i]->cmd_base = dma_alloc_coherent(cryp->dev,
+ MTK_DESC_RING_SZ,
+ &ring[i]->cmd_dma,
+ GFP_KERNEL);
if (!ring[i]->cmd_base)
goto err_cleanup;
- ring[i]->res_base = dma_zalloc_coherent(cryp->dev,
- MTK_DESC_RING_SZ,
- &ring[i]->res_dma,
- GFP_KERNEL);
+ ring[i]->res_base = dma_alloc_coherent(cryp->dev,
+ MTK_DESC_RING_SZ,
+ &ring[i]->res_dma,
+ GFP_KERNEL);
if (!ring[i]->res_base)
goto err_cleanup;
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 55f34cfc43ff..9450c41211b2 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -772,7 +772,7 @@ static int n2_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
}
err = des_ekey(tmp, key);
- if (err == 0 && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (err == 0 && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 6369019219d4..1ba2633e90d6 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -662,7 +662,7 @@ static int omap_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
pr_debug("enter, keylen: %d\n", keylen);
/* Do we need to test against weak key? */
- if (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY) {
+ if (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) {
u32 tmp[DES_EXPKEY_WORDS];
int ret = des_ekey(tmp, key);
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 17068b55fea5..1b3acdeffede 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -759,7 +759,8 @@ static int spacc_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
}
if (unlikely(!des_ekey(tmp, key)) &&
- (crypto_ablkcipher_get_flags(cipher) & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ (crypto_ablkcipher_get_flags(cipher) &
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
diff --git a/drivers/crypto/qat/qat_c3xxx/Makefile b/drivers/crypto/qat/qat_c3xxx/Makefile
index 8f5fd4838a96..822b5de58ec6 100644
--- a/drivers/crypto/qat/qat_c3xxx/Makefile
+++ b/drivers/crypto/qat/qat_c3xxx/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_C3XXX) += qat_c3xxx.o
qat_c3xxx-objs := adf_drv.o adf_c3xxx_hw_data.o
diff --git a/drivers/crypto/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/qat/qat_c3xxx/adf_drv.c
index 763c2166ee0e..d937cc7248a5 100644
--- a/drivers/crypto/qat/qat_c3xxx/adf_drv.c
+++ b/drivers/crypto/qat/qat_c3xxx/adf_drv.c
@@ -193,11 +193,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qat/qat_c3xxxvf/Makefile b/drivers/crypto/qat/qat_c3xxxvf/Makefile
index 16d178e2eaa2..8f56d27c7479 100644
--- a/drivers/crypto/qat/qat_c3xxxvf/Makefile
+++ b/drivers/crypto/qat/qat_c3xxxvf/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_C3XXXVF) += qat_c3xxxvf.o
qat_c3xxxvf-objs := adf_drv.o adf_c3xxxvf_hw_data.o
diff --git a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
index 613c7d5644ce..1dc5ac859f7b 100644
--- a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
+++ b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
@@ -177,11 +177,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qat/qat_c62x/Makefile b/drivers/crypto/qat/qat_c62x/Makefile
index bd75ace59b76..6dcd404578fc 100644
--- a/drivers/crypto/qat/qat_c62x/Makefile
+++ b/drivers/crypto/qat/qat_c62x/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_C62X) += qat_c62x.o
qat_c62x-objs := adf_drv.o adf_c62x_hw_data.o
diff --git a/drivers/crypto/qat/qat_c62x/adf_drv.c b/drivers/crypto/qat/qat_c62x/adf_drv.c
index 9cb832963357..2bc06c89d2fe 100644
--- a/drivers/crypto/qat/qat_c62x/adf_drv.c
+++ b/drivers/crypto/qat/qat_c62x/adf_drv.c
@@ -193,11 +193,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qat/qat_c62xvf/Makefile b/drivers/crypto/qat/qat_c62xvf/Makefile
index ecd708c213b2..1e5d51de778f 100644
--- a/drivers/crypto/qat/qat_c62xvf/Makefile
+++ b/drivers/crypto/qat/qat_c62xvf/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_C62XVF) += qat_c62xvf.o
qat_c62xvf-objs := adf_drv.o adf_c62xvf_hw_data.o
diff --git a/drivers/crypto/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/qat/qat_c62xvf/adf_drv.c
index 278452b8ef81..a68358b31292 100644
--- a/drivers/crypto/qat/qat_c62xvf/adf_drv.c
+++ b/drivers/crypto/qat/qat_c62xvf/adf_drv.c
@@ -177,11 +177,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qat/qat_common/adf_admin.c b/drivers/crypto/qat/qat_common/adf_admin.c
index 3744b22f0c46..d28cba34773e 100644
--- a/drivers/crypto/qat/qat_common/adf_admin.c
+++ b/drivers/crypto/qat/qat_common/adf_admin.c
@@ -244,18 +244,18 @@ int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
dev_to_node(&GET_DEV(accel_dev)));
if (!admin)
return -ENOMEM;
- admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
- &admin->phy_addr, GFP_KERNEL);
+ admin->virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+ &admin->phy_addr, GFP_KERNEL);
if (!admin->virt_addr) {
dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
kfree(admin);
return -ENOMEM;
}
- admin->virt_tbl_addr = dma_zalloc_coherent(&GET_DEV(accel_dev),
- PAGE_SIZE,
- &admin->const_tbl_addr,
- GFP_KERNEL);
+ admin->virt_tbl_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
+ PAGE_SIZE,
+ &admin->const_tbl_addr,
+ GFP_KERNEL);
if (!admin->virt_tbl_addr) {
dev_err(&GET_DEV(accel_dev), "Failed to allocate const_tbl\n");
dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
diff --git a/drivers/crypto/qat/qat_common/adf_cfg.c b/drivers/crypto/qat/qat_common/adf_cfg.c
index d0879790561f..5c7fdb0fc53d 100644
--- a/drivers/crypto/qat/qat_common/adf_cfg.c
+++ b/drivers/crypto/qat/qat_common/adf_cfg.c
@@ -141,13 +141,6 @@ int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
accel_dev->debugfs_dir,
dev_cfg_data,
&qat_dev_cfg_fops);
- if (!dev_cfg_data->debug) {
- dev_err(&GET_DEV(accel_dev),
- "Failed to create qat cfg debugfs entry.\n");
- kfree(dev_cfg_data);
- accel_dev->cfg = NULL;
- return -EFAULT;
- }
return 0;
}
EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c
index 57d2622728a5..2136cbe4bf6c 100644
--- a/drivers/crypto/qat/qat_common/adf_transport.c
+++ b/drivers/crypto/qat/qat_common/adf_transport.c
@@ -486,12 +486,6 @@ int adf_init_etr_data(struct adf_accel_dev *accel_dev)
/* accel_dev->debugfs_dir should always be non-NULL here */
etr_data->debug = debugfs_create_dir("transport",
accel_dev->debugfs_dir);
- if (!etr_data->debug) {
- dev_err(&GET_DEV(accel_dev),
- "Unable to create transport debugfs entry\n");
- ret = -ENOENT;
- goto err_bank_debug;
- }
for (i = 0; i < num_banks; i++) {
ret = adf_init_bank(accel_dev, &etr_data->banks[i], i,
@@ -504,7 +498,6 @@ int adf_init_etr_data(struct adf_accel_dev *accel_dev)
err_bank_all:
debugfs_remove(etr_data->debug);
-err_bank_debug:
kfree(etr_data->banks);
err_bank:
kfree(etr_data);
diff --git a/drivers/crypto/qat/qat_common/adf_transport_debug.c b/drivers/crypto/qat/qat_common/adf_transport_debug.c
index 52340b9bb387..e794e9d97b2c 100644
--- a/drivers/crypto/qat/qat_common/adf_transport_debug.c
+++ b/drivers/crypto/qat/qat_common/adf_transport_debug.c
@@ -163,11 +163,6 @@ int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
ring_debug->debug = debugfs_create_file(entry_name, S_IRUSR,
ring->bank->bank_debug_dir,
ring, &adf_ring_debug_fops);
- if (!ring_debug->debug) {
- pr_err("QAT: Failed to create ring debug entry.\n");
- kfree(ring_debug);
- return -EFAULT;
- }
ring->ring_debug = ring_debug;
return 0;
}
@@ -271,19 +266,9 @@ int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
bank->bank_debug_dir = debugfs_create_dir(name, parent);
- if (!bank->bank_debug_dir) {
- pr_err("QAT: Failed to create bank debug dir.\n");
- return -EFAULT;
- }
-
bank->bank_debug_cfg = debugfs_create_file("config", S_IRUSR,
bank->bank_debug_dir, bank,
&adf_bank_debug_fops);
- if (!bank->bank_debug_cfg) {
- pr_err("QAT: Failed to create bank debug entry.\n");
- debugfs_remove(bank->bank_debug_dir);
- return -EFAULT;
- }
return 0;
}
diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
index d2698299896f..975c75198f56 100644
--- a/drivers/crypto/qat/qat_common/qat_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_algs.c
@@ -601,15 +601,15 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
dev = &GET_DEV(inst->accel_dev);
ctx->inst = inst;
- ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
- &ctx->enc_cd_paddr,
- GFP_ATOMIC);
+ ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+ &ctx->enc_cd_paddr,
+ GFP_ATOMIC);
if (!ctx->enc_cd) {
return -ENOMEM;
}
- ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
- &ctx->dec_cd_paddr,
- GFP_ATOMIC);
+ ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+ &ctx->dec_cd_paddr,
+ GFP_ATOMIC);
if (!ctx->dec_cd) {
goto out_free_enc;
}
@@ -933,16 +933,16 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
dev = &GET_DEV(inst->accel_dev);
ctx->inst = inst;
- ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
- &ctx->enc_cd_paddr,
- GFP_ATOMIC);
+ ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+ &ctx->enc_cd_paddr,
+ GFP_ATOMIC);
if (!ctx->enc_cd) {
spin_unlock(&ctx->lock);
return -ENOMEM;
}
- ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
- &ctx->dec_cd_paddr,
- GFP_ATOMIC);
+ ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+ &ctx->dec_cd_paddr,
+ GFP_ATOMIC);
if (!ctx->dec_cd) {
spin_unlock(&ctx->lock);
goto out_free_enc;
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index 320e7854b4ee..c9f324730d71 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -332,10 +332,10 @@ static int qat_dh_compute_value(struct kpp_request *req)
} else {
int shift = ctx->p_size - req->src_len;
- qat_req->src_align = dma_zalloc_coherent(dev,
- ctx->p_size,
- &qat_req->in.dh.in.b,
- GFP_KERNEL);
+ qat_req->src_align = dma_alloc_coherent(dev,
+ ctx->p_size,
+ &qat_req->in.dh.in.b,
+ GFP_KERNEL);
if (unlikely(!qat_req->src_align))
return ret;
@@ -360,9 +360,9 @@ static int qat_dh_compute_value(struct kpp_request *req)
goto unmap_src;
} else {
- qat_req->dst_align = dma_zalloc_coherent(dev, ctx->p_size,
- &qat_req->out.dh.r,
- GFP_KERNEL);
+ qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size,
+ &qat_req->out.dh.r,
+ GFP_KERNEL);
if (unlikely(!qat_req->dst_align))
goto unmap_src;
}
@@ -447,7 +447,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
return -EINVAL;
ctx->p_size = params->p_size;
- ctx->p = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
+ ctx->p = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
if (!ctx->p)
return -ENOMEM;
memcpy(ctx->p, params->p, ctx->p_size);
@@ -458,7 +458,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
return 0;
}
- ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
+ ctx->g = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
if (!ctx->g)
return -ENOMEM;
memcpy(ctx->g + (ctx->p_size - params->g_size), params->g,
@@ -503,8 +503,8 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (ret < 0)
goto err_clear_ctx;
- ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
- GFP_KERNEL);
+ ctx->xa = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
+ GFP_KERNEL);
if (!ctx->xa) {
ret = -ENOMEM;
goto err_clear_ctx;
@@ -737,9 +737,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
} else {
int shift = ctx->key_sz - req->src_len;
- qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
- &qat_req->in.rsa.enc.m,
- GFP_KERNEL);
+ qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+ &qat_req->in.rsa.enc.m,
+ GFP_KERNEL);
if (unlikely(!qat_req->src_align))
return ret;
@@ -756,9 +756,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
goto unmap_src;
} else {
- qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
- &qat_req->out.rsa.enc.c,
- GFP_KERNEL);
+ qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.rsa.enc.c,
+ GFP_KERNEL);
if (unlikely(!qat_req->dst_align))
goto unmap_src;
@@ -881,9 +881,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
} else {
int shift = ctx->key_sz - req->src_len;
- qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
- &qat_req->in.rsa.dec.c,
- GFP_KERNEL);
+ qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+ &qat_req->in.rsa.dec.c,
+ GFP_KERNEL);
if (unlikely(!qat_req->src_align))
return ret;
@@ -900,9 +900,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
goto unmap_src;
} else {
- qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
- &qat_req->out.rsa.dec.m,
- GFP_KERNEL);
+ qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.rsa.dec.m,
+ GFP_KERNEL);
if (unlikely(!qat_req->dst_align))
goto unmap_src;
@@ -989,7 +989,7 @@ static int qat_rsa_set_n(struct qat_rsa_ctx *ctx, const char *value,
goto err;
ret = -ENOMEM;
- ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
+ ctx->n = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
if (!ctx->n)
goto err;
@@ -1018,7 +1018,7 @@ static int qat_rsa_set_e(struct qat_rsa_ctx *ctx, const char *value,
return -EINVAL;
}
- ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
+ ctx->e = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
if (!ctx->e)
return -ENOMEM;
@@ -1044,7 +1044,7 @@ static int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value,
goto err;
ret = -ENOMEM;
- ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
+ ctx->d = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
if (!ctx->d)
goto err;
@@ -1077,7 +1077,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto err;
- ctx->p = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
+ ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
if (!ctx->p)
goto err;
memcpy(ctx->p + (half_key_sz - len), ptr, len);
@@ -1088,7 +1088,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_p;
- ctx->q = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
+ ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
if (!ctx->q)
goto free_p;
memcpy(ctx->q + (half_key_sz - len), ptr, len);
@@ -1099,8 +1099,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_q;
- ctx->dp = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dp,
- GFP_KERNEL);
+ ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp,
+ GFP_KERNEL);
if (!ctx->dp)
goto free_q;
memcpy(ctx->dp + (half_key_sz - len), ptr, len);
@@ -1111,8 +1111,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_dp;
- ctx->dq = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dq,
- GFP_KERNEL);
+ ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq,
+ GFP_KERNEL);
if (!ctx->dq)
goto free_dp;
memcpy(ctx->dq + (half_key_sz - len), ptr, len);
@@ -1123,8 +1123,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_dq;
- ctx->qinv = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
- GFP_KERNEL);
+ ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
+ GFP_KERNEL);
if (!ctx->qinv)
goto free_dq;
memcpy(ctx->qinv + (half_key_sz - len), ptr, len);
diff --git a/drivers/crypto/qat/qat_dh895xcc/Makefile b/drivers/crypto/qat/qat_dh895xcc/Makefile
index 180a00ed7f89..0fc06b1e1632 100644
--- a/drivers/crypto/qat/qat_dh895xcc/Makefile
+++ b/drivers/crypto/qat/qat_dh895xcc/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc.o
qat_dh895xcc-objs := adf_drv.o adf_dh895xcc_hw_data.o
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
index 3a9708ef4ce2..b11bf8c0e683 100644
--- a/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
@@ -193,11 +193,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qat/qat_dh895xccvf/Makefile b/drivers/crypto/qat/qat_dh895xccvf/Makefile
index 5c3ccf8267eb..9ce906af6034 100644
--- a/drivers/crypto/qat/qat_dh895xccvf/Makefile
+++ b/drivers/crypto/qat/qat_dh895xccvf/Makefile
@@ -1,3 +1,3 @@
-ccflags-y := -I$(src)/../qat_common
+ccflags-y := -I $(srctree)/$(src)/../qat_common
obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCCVF) += qat_dh895xccvf.o
qat_dh895xccvf-objs := adf_drv.o adf_dh895xccvf_hw_data.o
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
index 3da0f951cb59..1b762eefc6c1 100644
--- a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
+++ b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
@@ -177,11 +177,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_FUNC(pdev->devfn));
accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
- if (!accel_dev->debugfs_dir) {
- dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
- ret = -EINVAL;
- goto out_err;
- }
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c
index 25c13e26d012..154b6baa124e 100644
--- a/drivers/crypto/qce/ablkcipher.c
+++ b/drivers/crypto/qce/ablkcipher.c
@@ -180,8 +180,8 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
u32 tmp[DES_EXPKEY_WORDS];
ret = des_ekey(tmp, key);
- if (!ret && crypto_ablkcipher_get_flags(ablk) &
- CRYPTO_TFM_REQ_WEAK_KEY)
+ if (!ret && (crypto_ablkcipher_get_flags(ablk) &
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS))
goto weakkey;
}
diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c
index c9d622abd90c..0ce4a65b95f5 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.c
+++ b/drivers/crypto/rockchip/rk3288_crypto.c
@@ -119,7 +119,7 @@ static int rk_load_data(struct rk_crypto_info *dev,
count = (dev->left_bytes > PAGE_SIZE) ?
PAGE_SIZE : dev->left_bytes;
- if (!sg_pcopy_to_buffer(dev->first, dev->nents,
+ if (!sg_pcopy_to_buffer(dev->first, dev->src_nents,
dev->addr_vir, count,
dev->total - dev->left_bytes)) {
dev_err(dev->dev, "[%s:%d] pcopy err\n",
diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h
index d5fb4013fb42..54ee5b3ed9db 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.h
+++ b/drivers/crypto/rockchip/rk3288_crypto.h
@@ -207,7 +207,8 @@ struct rk_crypto_info {
void *addr_vir;
int aligned;
int align_size;
- size_t nents;
+ size_t src_nents;
+ size_t dst_nents;
unsigned int total;
unsigned int count;
dma_addr_t addr_in;
@@ -244,6 +245,7 @@ struct rk_cipher_ctx {
struct rk_crypto_info *dev;
unsigned int keylen;
u32 mode;
+ u8 iv[AES_BLOCK_SIZE];
};
enum alg_type {
diff --git a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
index 639c15c5364b..02dac6ae7e53 100644
--- a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
+++ b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
@@ -60,7 +60,7 @@ static int rk_tdes_setkey(struct crypto_ablkcipher *cipher,
if (keylen == DES_KEY_SIZE) {
if (!des_ekey(tmp, key) &&
- (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
@@ -242,6 +242,17 @@ static void crypto_dma_start(struct rk_crypto_info *dev)
static int rk_set_data_start(struct rk_crypto_info *dev)
{
int err;
+ struct ablkcipher_request *req =
+ ablkcipher_request_cast(dev->async_req);
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 ivsize = crypto_ablkcipher_ivsize(tfm);
+ u8 *src_last_blk = page_address(sg_page(dev->sg_src)) +
+ dev->sg_src->offset + dev->sg_src->length - ivsize;
+
+ /* store the iv that need to be updated in chain mode */
+ if (ctx->mode & RK_CRYPTO_DEC)
+ memcpy(ctx->iv, src_last_blk, ivsize);
err = dev->load_data(dev, dev->sg_src, dev->sg_dst);
if (!err)
@@ -260,8 +271,9 @@ static int rk_ablk_start(struct rk_crypto_info *dev)
dev->total = req->nbytes;
dev->sg_src = req->src;
dev->first = req->src;
- dev->nents = sg_nents(req->src);
+ dev->src_nents = sg_nents(req->src);
dev->sg_dst = req->dst;
+ dev->dst_nents = sg_nents(req->dst);
dev->aligned = 1;
spin_lock_irqsave(&dev->lock, flags);
@@ -285,6 +297,28 @@ static void rk_iv_copyback(struct rk_crypto_info *dev)
memcpy_fromio(req->info, dev->reg + RK_CRYPTO_AES_IV_0, ivsize);
}
+static void rk_update_iv(struct rk_crypto_info *dev)
+{
+ struct ablkcipher_request *req =
+ ablkcipher_request_cast(dev->async_req);
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 ivsize = crypto_ablkcipher_ivsize(tfm);
+ u8 *new_iv = NULL;
+
+ if (ctx->mode & RK_CRYPTO_DEC) {
+ new_iv = ctx->iv;
+ } else {
+ new_iv = page_address(sg_page(dev->sg_dst)) +
+ dev->sg_dst->offset + dev->sg_dst->length - ivsize;
+ }
+
+ if (ivsize == DES_BLOCK_SIZE)
+ memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, new_iv, ivsize);
+ else if (ivsize == AES_BLOCK_SIZE)
+ memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, new_iv, ivsize);
+}
+
/* return:
* true some err was occurred
* fault no err, continue
@@ -297,7 +331,7 @@ static int rk_ablk_rx(struct rk_crypto_info *dev)
dev->unload_data(dev);
if (!dev->aligned) {
- if (!sg_pcopy_from_buffer(req->dst, dev->nents,
+ if (!sg_pcopy_from_buffer(req->dst, dev->dst_nents,
dev->addr_vir, dev->count,
dev->total - dev->left_bytes -
dev->count)) {
@@ -306,6 +340,7 @@ static int rk_ablk_rx(struct rk_crypto_info *dev)
}
}
if (dev->left_bytes) {
+ rk_update_iv(dev);
if (dev->aligned) {
if (sg_is_last(dev->sg_src)) {
dev_err(dev->dev, "[%s:%d] Lack of data\n",
diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
index 821a506b9e17..c336ae75e361 100644
--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c
+++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
@@ -206,7 +206,7 @@ static int rk_ahash_start(struct rk_crypto_info *dev)
dev->sg_dst = NULL;
dev->sg_src = req->src;
dev->first = req->src;
- dev->nents = sg_nents(req->src);
+ dev->src_nents = sg_nents(req->src);
rctx = ahash_request_ctx(req);
rctx->mode = 0;
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 0064be0e3941..f4e625cf53ca 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -232,6 +232,7 @@
* struct samsung_aes_variant - platform specific SSS driver data
* @aes_offset: AES register offset from SSS module's base.
* @hash_offset: HASH register offset from SSS module's base.
+ * @clk_names: names of clocks needed to run SSS IP
*
* Specifies platform specific configuration of SSS module.
* Note: A structure for driver specific platform data is used for future
@@ -240,6 +241,7 @@
struct samsung_aes_variant {
unsigned int aes_offset;
unsigned int hash_offset;
+ const char *clk_names[];
};
struct s5p_aes_reqctx {
@@ -296,6 +298,7 @@ struct s5p_aes_ctx {
struct s5p_aes_dev {
struct device *dev;
struct clk *clk;
+ struct clk *pclk;
void __iomem *ioaddr;
void __iomem *aes_ioaddr;
int irq_fc;
@@ -384,11 +387,19 @@ struct s5p_hash_ctx {
static const struct samsung_aes_variant s5p_aes_data = {
.aes_offset = 0x4000,
.hash_offset = 0x6000,
+ .clk_names = { "secss", },
};
static const struct samsung_aes_variant exynos_aes_data = {
.aes_offset = 0x200,
.hash_offset = 0x400,
+ .clk_names = { "secss", },
+};
+
+static const struct samsung_aes_variant exynos5433_slim_aes_data = {
+ .aes_offset = 0x400,
+ .hash_offset = 0x800,
+ .clk_names = { "pclk", "aclk", },
};
static const struct of_device_id s5p_sss_dt_match[] = {
@@ -400,6 +411,10 @@ static const struct of_device_id s5p_sss_dt_match[] = {
.compatible = "samsung,exynos4210-secss",
.data = &exynos_aes_data,
},
+ {
+ .compatible = "samsung,exynos5433-slim-sss",
+ .data = &exynos5433_slim_aes_data,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, s5p_sss_dt_match);
@@ -463,6 +478,9 @@ static void s5p_sg_copy_buf(void *buf, struct scatterlist *sg,
static void s5p_sg_done(struct s5p_aes_dev *dev)
{
+ struct ablkcipher_request *req = dev->req;
+ struct s5p_aes_reqctx *reqctx = ablkcipher_request_ctx(req);
+
if (dev->sg_dst_cpy) {
dev_dbg(dev->dev,
"Copying %d bytes of output data back to original place\n",
@@ -472,6 +490,11 @@ static void s5p_sg_done(struct s5p_aes_dev *dev)
}
s5p_free_sg_cpy(dev, &dev->sg_src_cpy);
s5p_free_sg_cpy(dev, &dev->sg_dst_cpy);
+ if (reqctx->mode & FLAGS_AES_CBC)
+ memcpy_fromio(req->info, dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), AES_BLOCK_SIZE);
+
+ else if (reqctx->mode & FLAGS_AES_CTR)
+ memcpy_fromio(req->info, dev->aes_ioaddr + SSS_REG_AES_CNT_DATA(0), AES_BLOCK_SIZE);
}
/* Calls the completion. Cannot be called with dev->lock hold. */
@@ -1819,10 +1842,12 @@ static void s5p_set_aes(struct s5p_aes_dev *dev,
void __iomem *keystart;
if (iv)
- memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10);
+ memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv,
+ AES_BLOCK_SIZE);
if (ctr)
- memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_CNT_DATA(0), ctr, 0x10);
+ memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_CNT_DATA(0), ctr,
+ AES_BLOCK_SIZE);
if (keylen == AES_KEYSIZE_256)
keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(0);
@@ -2208,18 +2233,39 @@ static int s5p_aes_probe(struct platform_device *pdev)
return PTR_ERR(pdata->ioaddr);
}
- pdata->clk = devm_clk_get(dev, "secss");
+ pdata->clk = devm_clk_get(dev, variant->clk_names[0]);
if (IS_ERR(pdata->clk)) {
- dev_err(dev, "failed to find secss clock source\n");
+ dev_err(dev, "failed to find secss clock %s\n",
+ variant->clk_names[0]);
return -ENOENT;
}
err = clk_prepare_enable(pdata->clk);
if (err < 0) {
- dev_err(dev, "Enabling SSS clk failed, err %d\n", err);
+ dev_err(dev, "Enabling clock %s failed, err %d\n",
+ variant->clk_names[0], err);
return err;
}
+ if (variant->clk_names[1]) {
+ pdata->pclk = devm_clk_get(dev, variant->clk_names[1]);
+ if (IS_ERR(pdata->pclk)) {
+ dev_err(dev, "failed to find clock %s\n",
+ variant->clk_names[1]);
+ err = -ENOENT;
+ goto err_clk;
+ }
+
+ err = clk_prepare_enable(pdata->pclk);
+ if (err < 0) {
+ dev_err(dev, "Enabling clock %s failed, err %d\n",
+ variant->clk_names[0], err);
+ goto err_clk;
+ }
+ } else {
+ pdata->pclk = NULL;
+ }
+
spin_lock_init(&pdata->lock);
spin_lock_init(&pdata->hash_lock);
@@ -2295,8 +2341,11 @@ err_algs:
tasklet_kill(&pdata->tasklet);
err_irq:
- clk_disable_unprepare(pdata->clk);
+ if (pdata->pclk)
+ clk_disable_unprepare(pdata->pclk);
+err_clk:
+ clk_disable_unprepare(pdata->clk);
s5p_dev = NULL;
return err;
@@ -2323,6 +2372,9 @@ static int s5p_aes_remove(struct platform_device *pdev)
pdata->use_hash = false;
}
+ if (pdata->pclk)
+ clk_disable_unprepare(pdata->pclk);
+
clk_disable_unprepare(pdata->clk);
s5p_dev = NULL;
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 590d7352837e..4a6cc8a3045d 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -1564,7 +1564,7 @@ err_engine:
static int stm32_hash_remove(struct platform_device *pdev)
{
- static struct stm32_hash_dev *hdev;
+ struct stm32_hash_dev *hdev;
int ret;
hdev = platform_get_drvdata(pdev);
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
index 5cf64746731a..54fd714d53ca 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
@@ -517,7 +517,7 @@ int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
flags = crypto_skcipher_get_flags(tfm);
ret = des_ekey(tmp, key);
- if (unlikely(!ret) && (flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (unlikely(!ret) && (flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY);
dev_dbg(ss->dev, "Weak key %u\n", keylen);
return -EINVAL;
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 45e20707cef8..de78b54bcfb1 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1361,23 +1361,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
struct talitos_private *priv = dev_get_drvdata(dev);
bool is_sec1 = has_ftr_sec1(priv);
int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
- void *err;
if (cryptlen + authsize > max_len) {
dev_err(dev, "length exceeds h/w max limit\n");
return ERR_PTR(-EINVAL);
}
- if (ivsize)
- iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
-
if (!dst || dst == src) {
src_len = assoclen + cryptlen + authsize;
src_nents = sg_nents_for_len(src, src_len);
if (src_nents < 0) {
dev_err(dev, "Invalid number of src SG.\n");
- err = ERR_PTR(-EINVAL);
- goto error_sg;
+ return ERR_PTR(-EINVAL);
}
src_nents = (src_nents == 1) ? 0 : src_nents;
dst_nents = dst ? src_nents : 0;
@@ -1387,16 +1382,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
src_nents = sg_nents_for_len(src, src_len);
if (src_nents < 0) {
dev_err(dev, "Invalid number of src SG.\n");
- err = ERR_PTR(-EINVAL);
- goto error_sg;
+ return ERR_PTR(-EINVAL);
}
src_nents = (src_nents == 1) ? 0 : src_nents;
dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
dst_nents = sg_nents_for_len(dst, dst_len);
if (dst_nents < 0) {
dev_err(dev, "Invalid number of dst SG.\n");
- err = ERR_PTR(-EINVAL);
- goto error_sg;
+ return ERR_PTR(-EINVAL);
}
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
@@ -1423,11 +1416,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
/* if its a ahash, add space for a second desc next to the first one */
if (is_sec1 && !dst)
alloc_len += sizeof(struct talitos_desc);
+ alloc_len += ivsize;
edesc = kmalloc(alloc_len, GFP_DMA | flags);
- if (!edesc) {
- err = ERR_PTR(-ENOMEM);
- goto error_sg;
+ if (!edesc)
+ return ERR_PTR(-ENOMEM);
+ if (ivsize) {
+ iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
+ iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
}
memset(&edesc->desc, 0, sizeof(edesc->desc));
@@ -1445,10 +1441,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
DMA_BIDIRECTIONAL);
}
return edesc;
-error_sg:
- if (iv_dma)
- dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
- return err;
}
static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
@@ -1543,7 +1535,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
}
if (unlikely(crypto_ablkcipher_get_flags(cipher) &
- CRYPTO_TFM_REQ_WEAK_KEY) &&
+ CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) &&
!des_ekey(tmp, key)) {
crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
return -EINVAL;
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index a92a66b1ff46..3235611928f2 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -595,6 +595,12 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
}
cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie)) {
+ dev_dbg(ctx->device->dev, "[%s]: DMA submission failed\n",
+ __func__);
+ return cookie;
+ }
+
dma_async_issue_pending(channel);
return 0;
@@ -994,10 +1000,11 @@ static int des_ablkcipher_setkey(struct crypto_ablkcipher *cipher,
}
ret = des_ekey(tmp, key);
- if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (unlikely(ret == 0) &&
+ (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
- pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_REQ_WEAK_KEY",
- __func__);
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_WEAK_KEY",
+ __func__);
return -EINVAL;
}
@@ -1028,18 +1035,19 @@ static int des3_ablkcipher_setkey(struct crypto_ablkcipher *cipher,
/* Checking key interdependency for weak key detection. */
if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
!((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
- (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
- pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_REQ_WEAK_KEY",
- __func__);
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_WEAK_KEY",
+ __func__);
return -EINVAL;
}
for (i = 0; i < 3; i++) {
ret = des_ekey(tmp, key + i*DES_KEY_SIZE);
- if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ if (unlikely(ret == 0) &&
+ (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) {
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
- pr_debug(DEV_DBG_NAME " [%s]: "
- "CRYPTO_TFM_REQ_WEAK_KEY", __func__);
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_WEAK_KEY",
+ __func__);
return -EINVAL;
}
}
diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c b/drivers/crypto/virtio/virtio_crypto_algs.c
index 2c573d1aaa64..0704833ece92 100644
--- a/drivers/crypto/virtio/virtio_crypto_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_algs.c
@@ -406,7 +406,7 @@ __virtio_crypto_ablkcipher_do_req(struct virtio_crypto_sym_request *vc_sym_req,
} else {
req_data->header.session_id =
cpu_to_le64(ctx->dec_sess_info.session_id);
- req_data->header.opcode =
+ req_data->header.opcode =
cpu_to_le32(VIRTIO_CRYPTO_CIPHER_DECRYPT);
}
req_data->u.sym_req.op_type = cpu_to_le32(VIRTIO_CRYPTO_SYM_OP_CIPHER);
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index 92e78d16b476..c9aa15fb86a9 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -89,8 +89,8 @@ static struct dioname names[] =
#undef DIONAME
#undef DIOFBNAME
-static const char *unknowndioname
- = "unknown DIO board -- please email <linux-m68k@lists.linux-m68k.org>!";
+static const char unknowndioname[]
+ = "unknown DIO board, please email linux-m68k@lists.linux-m68k.org";
static const char *dio_getname(int id)
{
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 4e557684f792..fe69dccfa0c0 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -203,6 +203,7 @@ struct at_xdmac_chan {
u32 save_cim;
u32 save_cnda;
u32 save_cndc;
+ u32 irq_status;
unsigned long status;
struct tasklet_struct tasklet;
struct dma_slave_config sconfig;
@@ -1580,8 +1581,8 @@ static void at_xdmac_tasklet(unsigned long data)
struct at_xdmac_desc *desc;
u32 error_mask;
- dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
- __func__, atchan->status);
+ dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n",
+ __func__, atchan->irq_status);
error_mask = AT_XDMAC_CIS_RBEIS
| AT_XDMAC_CIS_WBEIS
@@ -1589,15 +1590,15 @@ static void at_xdmac_tasklet(unsigned long data)
if (at_xdmac_chan_is_cyclic(atchan)) {
at_xdmac_handle_cyclic(atchan);
- } else if ((atchan->status & AT_XDMAC_CIS_LIS)
- || (atchan->status & error_mask)) {
+ } else if ((atchan->irq_status & AT_XDMAC_CIS_LIS)
+ || (atchan->irq_status & error_mask)) {
struct dma_async_tx_descriptor *txd;
- if (atchan->status & AT_XDMAC_CIS_RBEIS)
+ if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
dev_err(chan2dev(&atchan->chan), "read bus error!!!");
- if (atchan->status & AT_XDMAC_CIS_WBEIS)
+ if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
dev_err(chan2dev(&atchan->chan), "write bus error!!!");
- if (atchan->status & AT_XDMAC_CIS_ROIS)
+ if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
spin_lock(&atchan->lock);
@@ -1652,7 +1653,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
atchan = &atxdmac->chan[i];
chan_imr = at_xdmac_chan_read(atchan, AT_XDMAC_CIM);
chan_status = at_xdmac_chan_read(atchan, AT_XDMAC_CIS);
- atchan->status = chan_status & chan_imr;
+ atchan->irq_status = chan_status & chan_imr;
dev_vdbg(atxdmac->dma.dev,
"%s: chan%d: imr=0x%x, status=0x%x\n",
__func__, i, chan_imr, chan_status);
@@ -1666,7 +1667,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
- if (atchan->status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
+ if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
tasklet_schedule(&atchan->tasklet);
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 1a44c8086d77..ae10f5614f95 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
}
}
-static int bcm2835_dma_abort(void __iomem *chan_base)
+static int bcm2835_dma_abort(struct bcm2835_chan *c)
{
- unsigned long cs;
+ void __iomem *chan_base = c->chan_base;
long int timeout = 10000;
- cs = readl(chan_base + BCM2835_DMA_CS);
- if (!(cs & BCM2835_DMA_ACTIVE))
+ /*
+ * A zero control block address means the channel is idle.
+ * (The ACTIVE flag in the CS register is not a reliable indicator.)
+ */
+ if (!readl(chan_base + BCM2835_DMA_ADDR))
return 0;
/* Write 0 to the active bit - Pause the DMA */
writel(0, chan_base + BCM2835_DMA_CS);
/* Wait for any current AXI transfer to complete */
- while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
+ while ((readl(chan_base + BCM2835_DMA_CS) &
+ BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
cpu_relax();
- cs = readl(chan_base + BCM2835_DMA_CS);
- }
- /* We'll un-pause when we set of our next DMA */
+ /* Peripheral might be stuck and fail to signal AXI write responses */
if (!timeout)
- return -ETIMEDOUT;
-
- if (!(cs & BCM2835_DMA_ACTIVE))
- return 0;
-
- /* Terminate the control block chain */
- writel(0, chan_base + BCM2835_DMA_NEXTCB);
-
- /* Abort the whole DMA */
- writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
- chan_base + BCM2835_DMA_CS);
+ dev_err(c->vc.chan.device->dev,
+ "failed to complete outstanding writes\n");
+ writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
return 0;
}
@@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
spin_lock_irqsave(&c->vc.lock, flags);
- /* Acknowledge interrupt */
- writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+ /*
+ * Clear the INT flag to receive further interrupts. Keep the channel
+ * active in case the descriptor is cyclic or in case the client has
+ * already terminated the descriptor and issued a new one. (May happen
+ * if this IRQ handler is threaded.) If the channel is finished, it
+ * will remain idle despite the ACTIVE flag being set.
+ */
+ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+ c->chan_base + BCM2835_DMA_CS);
d = c->desc;
@@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
if (d->cyclic) {
/* call the cyclic callback */
vchan_cyclic_callback(&d->vd);
-
- /* Keep the DMA engine running */
- writel(BCM2835_DMA_ACTIVE,
- c->chan_base + BCM2835_DMA_CS);
- } else {
+ } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
vchan_cookie_complete(&c->desc->vd);
bcm2835_dma_start_desc(c);
}
@@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
unsigned long flags;
- int timeout = 10000;
LIST_HEAD(head);
spin_lock_irqsave(&c->vc.lock, flags);
@@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
list_del_init(&c->node);
spin_unlock(&d->lock);
- /*
- * Stop DMA activity: we assume the callback will not be called
- * after bcm_dma_abort() returns (even if it does, it will see
- * c->desc is NULL and exit.)
- */
+ /* stop DMA activity */
if (c->desc) {
vchan_terminate_vdesc(&c->desc->vd);
c->desc = NULL;
- bcm2835_dma_abort(c->chan_base);
-
- /* Wait for stopping */
- while (--timeout) {
- if (!(readl(c->chan_base + BCM2835_DMA_CS) &
- BCM2835_DMA_ACTIVE))
- break;
-
- cpu_relax();
- }
-
- if (!timeout)
- dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+ bcm2835_dma_abort(c);
}
vchan_get_all_descriptors(&c->vc, &head);
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index f1a441ab395d..3a11b1092e80 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -63,6 +63,7 @@
#include <linux/acpi_dma.h>
#include <linux/of_dma.h>
#include <linux/mempool.h>
+#include <linux/numa.h>
static DEFINE_MUTEX(dma_list_mutex);
static DEFINE_IDA(dma_ida);
@@ -386,7 +387,8 @@ EXPORT_SYMBOL(dma_issue_pending_all);
static bool dma_chan_is_local(struct dma_chan *chan, int cpu)
{
int node = dev_to_node(chan->device->dev);
- return node == -1 || cpumask_test_cpu(cpu, cpumask_of_node(node));
+ return node == NUMA_NO_NODE ||
+ cpumask_test_cpu(cpu, cpumask_of_node(node));
}
/**
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 2eea4ef72915..6511928b4cdf 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -711,11 +711,9 @@ static int dmatest_func(void *data)
srcs[i] = um->addr[i] + src_off;
ret = dma_mapping_error(dev->dev, um->addr[i]);
if (ret) {
- dmaengine_unmap_put(um);
result("src mapping error", total_tests,
src_off, dst_off, len, ret);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
}
um->to_cnt++;
}
@@ -730,11 +728,9 @@ static int dmatest_func(void *data)
DMA_BIDIRECTIONAL);
ret = dma_mapping_error(dev->dev, dsts[i]);
if (ret) {
- dmaengine_unmap_put(um);
result("dst mapping error", total_tests,
src_off, dst_off, len, ret);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
}
um->bidi_cnt++;
}
@@ -762,12 +758,10 @@ static int dmatest_func(void *data)
}
if (!tx) {
- dmaengine_unmap_put(um);
result("prep error", total_tests, src_off,
dst_off, len, ret);
msleep(100);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
}
done->done = false;
@@ -776,12 +770,10 @@ static int dmatest_func(void *data)
cookie = tx->tx_submit(tx);
if (dma_submit_error(cookie)) {
- dmaengine_unmap_put(um);
result("submit error", total_tests, src_off,
dst_off, len, ret);
msleep(100);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
}
dma_async_issue_pending(chan);
@@ -790,22 +782,20 @@ static int dmatest_func(void *data)
status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
- dmaengine_unmap_put(um);
-
if (!done->done) {
result("test timed out", total_tests, src_off, dst_off,
len, 0);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
} else if (status != DMA_COMPLETE) {
result(status == DMA_ERROR ?
"completion error status" :
"completion busy status", total_tests, src_off,
dst_off, len, ret);
- failed_tests++;
- continue;
+ goto error_unmap_continue;
}
+ dmaengine_unmap_put(um);
+
if (params->noverify) {
verbose_result("test passed", total_tests, src_off,
dst_off, len, 0);
@@ -846,6 +836,12 @@ static int dmatest_func(void *data)
verbose_result("test passed", total_tests, src_off,
dst_off, len, 0);
}
+
+ continue;
+
+error_unmap_continue:
+ dmaengine_unmap_put(um);
+ failed_tests++;
}
ktime = ktime_sub(ktime_get(), ktime);
ktime = ktime_sub(ktime, comparetime);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index c2fff3f6c9ca..4a09af3cd546 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data)
{
struct imxdma_channel *imxdmac = (void *)data;
struct imxdma_engine *imxdma = imxdmac->imxdma;
- struct imxdma_desc *desc;
+ struct imxdma_desc *desc, *next_desc;
unsigned long flags;
spin_lock_irqsave(&imxdma->lock, flags);
@@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data)
list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
if (!list_empty(&imxdmac->ld_queue)) {
- desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
- node);
+ next_desc = list_first_entry(&imxdmac->ld_queue,
+ struct imxdma_desc, node);
list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
- if (imxdma_xfer_desc(desc) < 0)
+ if (imxdma_xfer_desc(next_desc) < 0)
dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
__func__, imxdmac->channel);
}
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index a2b0a0e71168..86708fb9bda1 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1182,8 +1182,8 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
{
int ret = -EBUSY;
- sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
- GFP_NOWAIT);
+ sdma->bd0 = dma_alloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
+ GFP_NOWAIT);
if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
@@ -1205,8 +1205,8 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
int ret = 0;
- desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
- GFP_NOWAIT);
+ desc->bd = dma_alloc_coherent(NULL, bd_size, &desc->bd_phys,
+ GFP_NOWAIT);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index b7ec56ae02a6..1a2028e1c29e 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -325,8 +325,8 @@ static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma,
* and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring.
*/
pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd);
- ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
- &ring->tphys, GFP_NOWAIT);
+ ring->txd = dma_alloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
+ &ring->tphys, GFP_NOWAIT);
if (!ring->txd)
return -ENOMEM;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 35193b31a9e0..22cc7f68ef6e 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -416,9 +416,9 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int ret;
- mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev,
- CCW_BLOCK_SIZE,
- &mxs_chan->ccw_phys, GFP_KERNEL);
+ mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
+ CCW_BLOCK_SIZE,
+ &mxs_chan->ccw_phys, GFP_KERNEL);
if (!mxs_chan->ccw) {
ret = -ENOMEM;
goto err_alloc;
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 1d5988849aa6..eafd6c4b90fe 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -1208,8 +1208,8 @@ static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan,
ring->size = ret;
/* Allocate memory for DMA ring descriptor */
- ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
- &ring->desc_paddr, GFP_KERNEL);
+ ring->desc_vaddr = dma_alloc_coherent(chan->dev, ring->size,
+ &ring->desc_paddr, GFP_KERNEL);
if (!ring->desc_vaddr) {
chan_err(chan, "Failed to allocate ring desc\n");
return -ENOMEM;
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 02880963092f..cb20b411493e 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -879,10 +879,9 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
*/
if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
/* Allocate the buffer descriptors. */
- chan->seg_v = dma_zalloc_coherent(chan->dev,
- sizeof(*chan->seg_v) *
- XILINX_DMA_NUM_DESCS,
- &chan->seg_p, GFP_KERNEL);
+ chan->seg_v = dma_alloc_coherent(chan->dev,
+ sizeof(*chan->seg_v) * XILINX_DMA_NUM_DESCS,
+ &chan->seg_p, GFP_KERNEL);
if (!chan->seg_v) {
dev_err(chan->dev,
"unable to allocate channel %d descriptors\n",
@@ -895,9 +894,10 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
* so allocating a desc segment during channel allocation for
* programming tail descriptor.
*/
- chan->cyclic_seg_v = dma_zalloc_coherent(chan->dev,
- sizeof(*chan->cyclic_seg_v),
- &chan->cyclic_seg_p, GFP_KERNEL);
+ chan->cyclic_seg_v = dma_alloc_coherent(chan->dev,
+ sizeof(*chan->cyclic_seg_v),
+ &chan->cyclic_seg_p,
+ GFP_KERNEL);
if (!chan->cyclic_seg_v) {
dev_err(chan->dev,
"unable to allocate desc segment for cyclic DMA\n");
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index 8db51750ce93..4478787a247f 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -490,9 +490,9 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
list_add_tail(&desc->node, &chan->free_list);
}
- chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
- (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
- &chan->desc_pool_p, GFP_KERNEL);
+ chan->desc_pool_v = dma_alloc_coherent(chan->dev,
+ (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+ &chan->desc_pool_p, GFP_KERNEL);
if (!chan->desc_pool_v)
return -ENOMEM;
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h
index 4213cb0bb2a7..f8664bac9fa8 100644
--- a/drivers/edac/altera_edac.h
+++ b/drivers/edac/altera_edac.h
@@ -295,8 +295,8 @@ struct altr_sdram_mc_data {
#define S10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xA0
/* Sticky registers for Uncorrected Errors */
-#define S10_SYSMGR_UE_VAL_OFST 0x120
-#define S10_SYSMGR_UE_ADDR_OFST 0x124
+#define S10_SYSMGR_UE_VAL_OFST 0x220
+#define S10_SYSMGR_UE_ADDR_OFST 0x224
#define S10_DDR0_IRQ_MASK BIT(16)
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index de15bf55895b..8e17149655f0 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -114,6 +114,14 @@ config EXTCON_PALMAS
Say Y here to enable support for USB peripheral and USB host
detection by palmas usb.
+config EXTCON_PTN5150
+ tristate "NXP PTN5150 CC LOGIC USB EXTCON support"
+ depends on I2C && GPIOLIB || COMPILE_TEST
+ select REGMAP_I2C
+ help
+ Say Y here to enable support for USB peripheral and USB host
+ detection by NXP PTN5150 CC (Configuration Channel) logic chip.
+
config EXTCON_QCOM_SPMI_MISC
tristate "Qualcomm USB extcon support"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 0888fdeded72..261ce4cfe209 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
+obj-$(CONFIG_EXTCON_PTN5150) += extcon-ptn5150.o
obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o
obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
new file mode 100644
index 000000000000..d1c997599390
--- /dev/null
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// extcon-ptn5150.c - PTN5150 CC logic extcon driver to support USB detection
+//
+// Based on extcon-sm5502.c driver
+// Copyright (c) 2018-2019 by Vijai Kumar K
+// Author: Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/extcon-provider.h>
+#include <linux/gpio/consumer.h>
+
+/* PTN5150 registers */
+enum ptn5150_reg {
+ PTN5150_REG_DEVICE_ID = 0x01,
+ PTN5150_REG_CONTROL,
+ PTN5150_REG_INT_STATUS,
+ PTN5150_REG_CC_STATUS,
+ PTN5150_REG_CON_DET = 0x09,
+ PTN5150_REG_VCONN_STATUS,
+ PTN5150_REG_RESET,
+ PTN5150_REG_INT_MASK = 0x18,
+ PTN5150_REG_INT_REG_STATUS,
+ PTN5150_REG_END,
+};
+
+#define PTN5150_DFP_ATTACHED 0x1
+#define PTN5150_UFP_ATTACHED 0x2
+
+/* Define PTN5150 MASK/SHIFT constant */
+#define PTN5150_REG_DEVICE_ID_VENDOR_SHIFT 0
+#define PTN5150_REG_DEVICE_ID_VENDOR_MASK \
+ (0x3 << PTN5150_REG_DEVICE_ID_VENDOR_SHIFT)
+
+#define PTN5150_REG_DEVICE_ID_VERSION_SHIFT 3
+#define PTN5150_REG_DEVICE_ID_VERSION_MASK \
+ (0x1f << PTN5150_REG_DEVICE_ID_VERSION_SHIFT)
+
+#define PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT 2
+#define PTN5150_REG_CC_PORT_ATTACHMENT_MASK \
+ (0x7 << PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT)
+
+#define PTN5150_REG_CC_VBUS_DETECTION_SHIFT 7
+#define PTN5150_REG_CC_VBUS_DETECTION_MASK \
+ (0x1 << PTN5150_REG_CC_VBUS_DETECTION_SHIFT)
+
+#define PTN5150_REG_INT_CABLE_ATTACH_SHIFT 0
+#define PTN5150_REG_INT_CABLE_ATTACH_MASK \
+ (0x1 << PTN5150_REG_INT_CABLE_ATTACH_SHIFT)
+
+#define PTN5150_REG_INT_CABLE_DETACH_SHIFT 1
+#define PTN5150_REG_INT_CABLE_DETACH_MASK \
+ (0x1 << PTN5150_REG_CC_CABLE_DETACH_SHIFT)
+
+struct ptn5150_info {
+ struct device *dev;
+ struct extcon_dev *edev;
+ struct i2c_client *i2c;
+ struct regmap *regmap;
+ struct gpio_desc *int_gpiod;
+ struct gpio_desc *vbus_gpiod;
+ int irq;
+ struct work_struct irq_work;
+ struct mutex mutex;
+};
+
+/* List of detectable cables */
+static const unsigned int ptn5150_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
+static const struct regmap_config ptn5150_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PTN5150_REG_END,
+};
+
+static void ptn5150_irq_work(struct work_struct *work)
+{
+ struct ptn5150_info *info = container_of(work,
+ struct ptn5150_info, irq_work);
+ int ret = 0;
+ unsigned int reg_data;
+ unsigned int int_status;
+
+ if (!info->edev)
+ return;
+
+ mutex_lock(&info->mutex);
+
+ ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
+ if (ret) {
+ dev_err(info->dev, "failed to read CC STATUS %d\n", ret);
+ mutex_unlock(&info->mutex);
+ return;
+ }
+
+ /* Clear interrupt. Read would clear the register */
+ ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
+ if (ret) {
+ dev_err(info->dev, "failed to read INT STATUS %d\n", ret);
+ mutex_unlock(&info->mutex);
+ return;
+ }
+
+ if (int_status) {
+ unsigned int cable_attach;
+
+ cable_attach = int_status & PTN5150_REG_INT_CABLE_ATTACH_MASK;
+ if (cable_attach) {
+ unsigned int port_status;
+ unsigned int vbus;
+
+ port_status = ((reg_data &
+ PTN5150_REG_CC_PORT_ATTACHMENT_MASK) >>
+ PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT);
+
+ switch (port_status) {
+ case PTN5150_DFP_ATTACHED:
+ extcon_set_state_sync(info->edev,
+ EXTCON_USB_HOST, false);
+ gpiod_set_value(info->vbus_gpiod, 0);
+ extcon_set_state_sync(info->edev, EXTCON_USB,
+ true);
+ break;
+ case PTN5150_UFP_ATTACHED:
+ extcon_set_state_sync(info->edev, EXTCON_USB,
+ false);
+ vbus = ((reg_data &
+ PTN5150_REG_CC_VBUS_DETECTION_MASK) >>
+ PTN5150_REG_CC_VBUS_DETECTION_SHIFT);
+ if (vbus)
+ gpiod_set_value(info->vbus_gpiod, 0);
+ else
+ gpiod_set_value(info->vbus_gpiod, 1);
+
+ extcon_set_state_sync(info->edev,
+ EXTCON_USB_HOST, true);
+ break;
+ default:
+ dev_err(info->dev,
+ "Unknown Port status : %x\n",
+ port_status);
+ break;
+ }
+ } else {
+ extcon_set_state_sync(info->edev,
+ EXTCON_USB_HOST, false);
+ extcon_set_state_sync(info->edev,
+ EXTCON_USB, false);
+ gpiod_set_value(info->vbus_gpiod, 0);
+ }
+ }
+
+ /* Clear interrupt. Read would clear the register */
+ ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS,
+ &int_status);
+ if (ret) {
+ dev_err(info->dev,
+ "failed to read INT REG STATUS %d\n", ret);
+ mutex_unlock(&info->mutex);
+ return;
+ }
+
+ mutex_unlock(&info->mutex);
+}
+
+
+static irqreturn_t ptn5150_irq_handler(int irq, void *data)
+{
+ struct ptn5150_info *info = data;
+
+ schedule_work(&info->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static int ptn5150_init_dev_type(struct ptn5150_info *info)
+{
+ unsigned int reg_data, vendor_id, version_id;
+ int ret;
+
+ ret = regmap_read(info->regmap, PTN5150_REG_DEVICE_ID, &reg_data);
+ if (ret) {
+ dev_err(info->dev, "failed to read DEVICE_ID %d\n", ret);
+ return -EINVAL;
+ }
+
+ vendor_id = ((reg_data & PTN5150_REG_DEVICE_ID_VENDOR_MASK) >>
+ PTN5150_REG_DEVICE_ID_VENDOR_SHIFT);
+ version_id = ((reg_data & PTN5150_REG_DEVICE_ID_VERSION_MASK) >>
+ PTN5150_REG_DEVICE_ID_VERSION_SHIFT);
+
+ dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
+ version_id, vendor_id);
+
+ /* Clear any existing interrupts */
+ ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &reg_data);
+ if (ret) {
+ dev_err(info->dev,
+ "failed to read PTN5150_REG_INT_STATUS %d\n",
+ ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS, &reg_data);
+ if (ret) {
+ dev_err(info->dev,
+ "failed to read PTN5150_REG_INT_REG_STATUS %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ptn5150_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c->dev;
+ struct device_node *np = i2c->dev.of_node;
+ struct ptn5150_info *info;
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+
+ info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ i2c_set_clientdata(i2c, info);
+
+ info->dev = &i2c->dev;
+ info->i2c = i2c;
+ info->int_gpiod = devm_gpiod_get(&i2c->dev, "int", GPIOD_IN);
+ if (IS_ERR(info->int_gpiod)) {
+ dev_err(dev, "failed to get INT GPIO\n");
+ return PTR_ERR(info->int_gpiod);
+ }
+ info->vbus_gpiod = devm_gpiod_get(&i2c->dev, "vbus", GPIOD_IN);
+ if (IS_ERR(info->vbus_gpiod)) {
+ dev_err(dev, "failed to get VBUS GPIO\n");
+ return PTR_ERR(info->vbus_gpiod);
+ }
+ ret = gpiod_direction_output(info->vbus_gpiod, 0);
+ if (ret) {
+ dev_err(dev, "failed to set VBUS GPIO direction\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&info->mutex);
+
+ INIT_WORK(&info->irq_work, ptn5150_irq_work);
+
+ info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(info->dev, "failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (info->int_gpiod) {
+ info->irq = gpiod_to_irq(info->int_gpiod);
+ if (info->irq < 0) {
+ dev_err(dev, "failed to get INTB IRQ\n");
+ return info->irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->irq, NULL,
+ ptn5150_irq_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ i2c->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for INTB IRQ\n");
+ return ret;
+ }
+ }
+
+ /* Allocate extcon device */
+ info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(info->dev, "failed to allocate memory for extcon\n");
+ return -ENOMEM;
+ }
+
+ /* Register extcon device */
+ ret = devm_extcon_dev_register(info->dev, info->edev);
+ if (ret) {
+ dev_err(info->dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ /* Initialize PTN5150 device and print vendor id and version id */
+ ret = ptn5150_init_dev_type(info);
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct of_device_id ptn5150_dt_match[] = {
+ { .compatible = "nxp,ptn5150" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ptn5150_dt_match);
+
+static const struct i2c_device_id ptn5150_i2c_id[] = {
+ { "ptn5150", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id);
+
+static struct i2c_driver ptn5150_i2c_driver = {
+ .driver = {
+ .name = "ptn5150",
+ .of_match_table = ptn5150_dt_match,
+ },
+ .probe = ptn5150_i2c_probe,
+ .id_table = ptn5150_i2c_id,
+};
+
+static int __init ptn5150_i2c_init(void)
+{
+ return i2c_add_driver(&ptn5150_i2c_driver);
+}
+subsys_initcall(ptn5150_i2c_init);
+
+MODULE_DESCRIPTION("NXP PTN5150 CC logic Extcon driver");
+MODULE_AUTHOR("Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 09b845e90114..a785ffd5af89 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1144,10 +1144,6 @@ static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
if (device->is_local)
return -ENODEV;
- if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
- WARN_ON(dma_set_max_seg_size(device->card->device,
- SBP2_MAX_SEG_SIZE));
-
shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
if (shost == NULL)
return -ENOMEM;
@@ -1610,6 +1606,7 @@ static struct scsi_host_template scsi_driver_template = {
.eh_abort_handler = sbp2_scsi_abort,
.this_id = -1,
.sg_tablesize = SG_ALL,
+ .max_segment_size = SBP2_MAX_SEG_SIZE,
.can_queue = 1,
.sdev_attrs = sbp2_scsi_sysfs_attrs,
};
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index f754578414f0..cac16c4b0df3 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -218,7 +218,7 @@ config FW_CFG_SYSFS_CMDLINE
config INTEL_STRATIX10_SERVICE
tristate "Intel Stratix10 Service Layer"
- depends on HAVE_ARM_SMCCC
+ depends on ARCH_STRATIX10 && HAVE_ARM_SMCCC
default n
help
Intel Stratix10 service layer runs at privileged exception level,
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 472c88ae1c0f..92f843eaf1e0 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -119,6 +119,11 @@ void scmi_driver_unregister(struct scmi_driver *driver)
}
EXPORT_SYMBOL_GPL(scmi_driver_unregister);
+static void scmi_device_release(struct device *dev)
+{
+ kfree(to_scmi_dev(dev));
+}
+
struct scmi_device *
scmi_device_create(struct device_node *np, struct device *parent, int protocol)
{
@@ -138,6 +143,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
scmi_dev->dev.parent = parent;
scmi_dev->dev.of_node = np;
scmi_dev->dev.bus = &scmi_bus_type;
+ scmi_dev->dev.release = scmi_device_release;
dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
retval = device_register(&scmi_dev->dev);
@@ -156,9 +162,8 @@ free_mem:
void scmi_device_destroy(struct scmi_device *scmi_dev)
{
scmi_handle_put(scmi_dev->handle);
- device_unregister(&scmi_dev->dev);
ida_simple_remove(&scmi_bus_id, scmi_dev->id);
- kfree(scmi_dev);
+ device_unregister(&scmi_dev->dev);
}
void scmi_set_handle(struct scmi_device *scmi_dev)
diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c
index c64c7da73829..e6376f985ef7 100644
--- a/drivers/firmware/arm_sdei.c
+++ b/drivers/firmware/arm_sdei.c
@@ -2,6 +2,7 @@
// Copyright (C) 2017 Arm Ltd.
#define pr_fmt(fmt) "sdei: " fmt
+#include <acpi/ghes.h>
#include <linux/acpi.h>
#include <linux/arm_sdei.h>
#include <linux/arm-smccc.h>
@@ -887,6 +888,73 @@ static void sdei_smccc_hvc(unsigned long function_id,
arm_smccc_hvc(function_id, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
}
+int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
+ sdei_event_callback *critical_cb)
+{
+ int err;
+ u64 result;
+ u32 event_num;
+ sdei_event_callback *cb;
+
+ if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
+ return -EOPNOTSUPP;
+
+ event_num = ghes->generic->notify.vector;
+ if (event_num == 0) {
+ /*
+ * Event 0 is reserved by the specification for
+ * SDEI_EVENT_SIGNAL.
+ */
+ return -EINVAL;
+ }
+
+ err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY,
+ &result);
+ if (err)
+ return err;
+
+ if (result == SDEI_EVENT_PRIORITY_CRITICAL)
+ cb = critical_cb;
+ else
+ cb = normal_cb;
+
+ err = sdei_event_register(event_num, cb, ghes);
+ if (!err)
+ err = sdei_event_enable(event_num);
+
+ return err;
+}
+
+int sdei_unregister_ghes(struct ghes *ghes)
+{
+ int i;
+ int err;
+ u32 event_num = ghes->generic->notify.vector;
+
+ might_sleep();
+
+ if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
+ return -EOPNOTSUPP;
+
+ /*
+ * The event may be running on another CPU. Disable it
+ * to stop new events, then try to unregister a few times.
+ */
+ err = sdei_event_disable(event_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < 3; i++) {
+ err = sdei_event_unregister(event_num);
+ if (err != -EINPROGRESS)
+ break;
+
+ schedule();
+ }
+
+ return err;
+}
+
static int sdei_get_conduit(struct platform_device *pdev)
{
const char *method;
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 89110dfc7127..190be0b1d109 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -198,3 +198,9 @@ config EFI_DEV_PATH_PARSER
bool
depends on ACPI
default n
+
+config EFI_EARLYCON
+ def_bool y
+ depends on SERIAL_EARLYCON && !ARM && !IA64
+ select FONT_SUPPORT
+ select ARCH_USE_MEMREMAP_PROT
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 5f9f5039de50..d2d0d2030620 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -30,5 +30,6 @@ arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
obj-$(CONFIG_ARM) += $(arm-obj-y)
obj-$(CONFIG_ARM64) += $(arm-obj-y)
obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
+obj-$(CONFIG_EFI_EARLYCON) += earlycon.o
obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o
obj-$(CONFIG_UEFI_CPER_X86) += cper-x86.o
diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c
index ac1654f74dc7..0e206c9e0d7a 100644
--- a/drivers/firmware/efi/apple-properties.c
+++ b/drivers/firmware/efi/apple-properties.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* apple-properties.c - EFI device properties on Macs
* Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
*
- * 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/>.
- *
* Note, all properties are considered as u8 arrays.
* To get a value of any of them the caller must use device_property_read_u8_array().
*/
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 1a6a77df8a5e..311cd349a862 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Extensible Firmware Interface
*
* Based on Extensible Firmware Interface Specification version 2.4
*
* Copyright (C) 2013 - 2015 Linaro Ltd.
- *
- * 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.
- *
*/
#define pr_fmt(fmt) "efi: " fmt
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 23ea1ed409d1..f99995666f86 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Extensible Firmware Interface
*
* Based on Extensible Firmware Interface Specification version 2.4
*
* Copyright (C) 2013, 2014 Linaro Ltd.
- *
- * 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/dmi.h>
@@ -37,8 +33,9 @@ extern u64 efi_system_table;
static struct ptdump_info efi_ptdump_info = {
.mm = &efi_mm,
.markers = (struct addr_marker[]){
- { 0, "UEFI runtime start" },
- { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" }
+ { 0, "UEFI runtime start" },
+ { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" },
+ { -1, NULL }
},
.base_addr = 0,
};
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c
index 96688986da56..b1395133389e 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* EFI capsule loader driver.
*
* Copyright 2015 Intel Corporation
- *
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2.
*/
#define pr_fmt(fmt) "efi: " fmt
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index 4938c29b7c5d..598b7800d14e 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* EFI capsule support.
*
* Copyright 2013 Intel Corporation; author Matt Fleming
- *
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2.
*/
#define pr_fmt(fmt) "efi: " fmt
diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c
index 502811344e81..36d3b8b9da47 100644
--- a/drivers/firmware/efi/cper-arm.c
+++ b/drivers/firmware/efi/cper-arm.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* UEFI Common Platform Error Record (CPER) support
*
* Copyright (C) 2017, The Linux Foundation. All rights reserved.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index a7902fccdcfa..8fa977c7861f 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* UEFI Common Platform Error Record (CPER) support
*
@@ -9,19 +10,6 @@
*
* For more information about CPER, please refer to Appendix N of UEFI
* Specification version 2.4.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
@@ -546,19 +534,24 @@ EXPORT_SYMBOL_GPL(cper_estatus_check_header);
int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
{
struct acpi_hest_generic_data *gdata;
- unsigned int data_len, gedata_len;
+ unsigned int data_len, record_size;
int rc;
rc = cper_estatus_check_header(estatus);
if (rc)
return rc;
+
data_len = estatus->data_length;
apei_estatus_for_each_section(estatus, gdata) {
- gedata_len = acpi_hest_get_error_length(gdata);
- if (gedata_len > data_len - acpi_hest_get_size(gdata))
+ if (sizeof(struct acpi_hest_generic_data) > data_len)
return -EINVAL;
- data_len -= acpi_hest_get_record_size(gdata);
+
+ record_size = acpi_hest_get_record_size(gdata);
+ if (record_size > data_len)
+ return -EINVAL;
+
+ data_len -= record_size;
}
if (data_len)
return -EINVAL;
diff --git a/drivers/firmware/efi/dev-path-parser.c b/drivers/firmware/efi/dev-path-parser.c
index 85d1834ee9b7..85ec99f97841 100644
--- a/drivers/firmware/efi/dev-path-parser.c
+++ b/drivers/firmware/efi/dev-path-parser.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* dev-path-parser.c - EFI Device Path parser
* Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
@@ -5,14 +6,6 @@
* 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 <linux/acpi.h>
diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
new file mode 100644
index 000000000000..c9a0efca17b0
--- /dev/null
+++ b/drivers/firmware/efi/earlycon.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013 Intel Corporation; author Matt Fleming
+ */
+
+#include <linux/console.h>
+#include <linux/efi.h>
+#include <linux/font.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/serial_core.h>
+#include <linux/screen_info.h>
+
+#include <asm/early_ioremap.h>
+
+static const struct font_desc *font;
+static u32 efi_x, efi_y;
+static u64 fb_base;
+static pgprot_t fb_prot;
+
+static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
+{
+ return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
+}
+
+static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
+{
+ early_memunmap(addr, len);
+}
+
+static void efi_earlycon_clear_scanline(unsigned int y)
+{
+ unsigned long *dst;
+ u16 len;
+
+ len = screen_info.lfb_linelength;
+ dst = efi_earlycon_map(y*len, len);
+ if (!dst)
+ return;
+
+ memset(dst, 0, len);
+ efi_earlycon_unmap(dst, len);
+}
+
+static void efi_earlycon_scroll_up(void)
+{
+ unsigned long *dst, *src;
+ u16 len;
+ u32 i, height;
+
+ len = screen_info.lfb_linelength;
+ height = screen_info.lfb_height;
+
+ for (i = 0; i < height - font->height; i++) {
+ dst = efi_earlycon_map(i*len, len);
+ if (!dst)
+ return;
+
+ src = efi_earlycon_map((i + font->height) * len, len);
+ if (!src) {
+ efi_earlycon_unmap(dst, len);
+ return;
+ }
+
+ memmove(dst, src, len);
+
+ efi_earlycon_unmap(src, len);
+ efi_earlycon_unmap(dst, len);
+ }
+}
+
+static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
+{
+ const u32 color_black = 0x00000000;
+ const u32 color_white = 0x00ffffff;
+ const u8 *src;
+ u8 s8;
+ int m;
+
+ src = font->data + c * font->height;
+ s8 = *(src + h);
+
+ for (m = 0; m < 8; m++) {
+ if ((s8 >> (7 - m)) & 1)
+ *dst = color_white;
+ else
+ *dst = color_black;
+ dst++;
+ }
+}
+
+static void
+efi_earlycon_write(struct console *con, const char *str, unsigned int num)
+{
+ struct screen_info *si;
+ unsigned int len;
+ const char *s;
+ void *dst;
+
+ si = &screen_info;
+ len = si->lfb_linelength;
+
+ while (num) {
+ unsigned int linemax;
+ unsigned int h, count = 0;
+
+ for (s = str; *s && *s != '\n'; s++) {
+ if (count == num)
+ break;
+ count++;
+ }
+
+ linemax = (si->lfb_width - efi_x) / font->width;
+ if (count > linemax)
+ count = linemax;
+
+ for (h = 0; h < font->height; h++) {
+ unsigned int n, x;
+
+ dst = efi_earlycon_map((efi_y + h) * len, len);
+ if (!dst)
+ return;
+
+ s = str;
+ n = count;
+ x = efi_x;
+
+ while (n-- > 0) {
+ efi_earlycon_write_char(dst + x*4, *s, h);
+ x += font->width;
+ s++;
+ }
+
+ efi_earlycon_unmap(dst, len);
+ }
+
+ num -= count;
+ efi_x += count * font->width;
+ str += count;
+
+ if (num > 0 && *s == '\n') {
+ efi_x = 0;
+ efi_y += font->height;
+ str++;
+ num--;
+ }
+
+ if (efi_x + font->width > si->lfb_width) {
+ efi_x = 0;
+ efi_y += font->height;
+ }
+
+ if (efi_y + font->height > si->lfb_height) {
+ u32 i;
+
+ efi_y -= font->height;
+ efi_earlycon_scroll_up();
+
+ for (i = 0; i < font->height; i++)
+ efi_earlycon_clear_scanline(efi_y + i);
+ }
+ }
+}
+
+static int __init efi_earlycon_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ struct screen_info *si;
+ u16 xres, yres;
+ u32 i;
+
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+ return -ENODEV;
+
+ fb_base = screen_info.lfb_base;
+ if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+ fb_base |= (u64)screen_info.ext_lfb_base << 32;
+
+ if (opt && !strcmp(opt, "ram"))
+ fb_prot = PAGE_KERNEL;
+ else
+ fb_prot = pgprot_writecombine(PAGE_KERNEL);
+
+ si = &screen_info;
+ xres = si->lfb_width;
+ yres = si->lfb_height;
+
+ /*
+ * efi_earlycon_write_char() implicitly assumes a framebuffer with
+ * 32 bits per pixel.
+ */
+ if (si->lfb_depth != 32)
+ return -ENODEV;
+
+ font = get_default_font(xres, yres, -1, -1);
+ if (!font)
+ return -ENODEV;
+
+ efi_y = rounddown(yres, font->height) - font->height;
+ for (i = 0; i < (yres - efi_y) / font->height; i++)
+ efi_earlycon_scroll_up();
+
+ device->con->write = efi_earlycon_write;
+ return 0;
+}
+EARLYCON_DECLARE(efifb, efi_earlycon_setup);
diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index b22ccfb0c991..a2384184a7de 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2012 Intel Corporation
* Author: Josh Triplett <josh@joshtriplett.org>
@@ -5,10 +6,6 @@
* Based on the bgrt driver:
* Copyright 2012 Red Hat, Inc <mjg@redhat.com>
* Author: Matthew Garrett
- *
- * 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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 0f7d97917197..9ea13e8d12ec 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#include <linux/efi.h>
#include <linux/module.h>
#include <linux/pstore.h>
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 4c46ff6f2242..55b77c576c42 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
early_memunmap(tbl, sizeof(*tbl));
}
- return 0;
-}
-int __init efi_apply_persistent_mem_reservations(void)
-{
if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
unsigned long prsv = efi.mem_reserve;
diff --git a/drivers/firmware/efi/efibc.c b/drivers/firmware/efi/efibc.c
index 503bbe2a9d49..61e099826cbb 100644
--- a/drivers/firmware/efi/efibc.c
+++ b/drivers/firmware/efi/efibc.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* efibc: control EFI bootloaders which obey LoaderEntryOneShot var
* Copyright (c) 2013-2016, 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.
*/
#define pr_fmt(fmt) "efibc: " fmt
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index 8061667a6765..7576450c8254 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Originally from efivars.c,
*
@@ -6,63 +7,6 @@
*
* This code takes all variables accessible from EFI runtime and
* exports them via sysfs
- *
- * 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
- *
- * Changelog:
- *
- * 17 May 2004 - Matt Domsch <Matt_Domsch@dell.com>
- * remove check for efi_enabled in exit
- * add MODULE_VERSION
- *
- * 26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com>
- * minor bug fixes
- *
- * 21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com)
- * converted driver to export variable information via sysfs
- * and moved to drivers/firmware directory
- * bumped revision number to v0.07 to reflect conversion & move
- *
- * 10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
- * fix locking per Peter Chubb's findings
- *
- * 25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
- * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_to_str()
- *
- * 12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
- * use list_for_each_safe when deleting vars.
- * remove ifdef CONFIG_SMP around include <linux/smp.h>
- * v0.04 release to linux-ia64@linuxia64.org
- *
- * 20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
- * Moved vars from /proc/efi to /proc/efi/vars, and made
- * efi.c own the /proc/efi directory.
- * v0.03 release to linux-ia64@linuxia64.org
- *
- * 26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
- * At the request of Stephane, moved ownership of /proc/efi
- * to efi.c, and now efivars lives under /proc/efi/vars.
- *
- * 12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
- * Feedback received from Stephane Eranian incorporated.
- * efivar_write() checks copy_from_user() return value.
- * efivar_read/write() returns proper errno.
- * v0.02 release to linux-ia64@linuxia64.org
- *
- * 26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
- * v0.01 release to linux-ia64@linuxia64.org
*/
#include <linux/efi.h>
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 5d06bd247d07..d6dd5f503fa2 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* esrt.c
*
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 6c7d60c239b5..9501edc0fcfb 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* fake_mem.c
*
@@ -8,21 +9,6 @@
* By specifying this parameter, you can add arbitrary attribute to
* specific memory range by updating original (firmware provided) EFI
* memmap.
- *
- * 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/>.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
*/
#include <linux/kernel.h>
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index d9845099635e..b0103e16fc1b 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -52,7 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \
lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += arm64-stub.o
-CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
+CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
#
# arm64 puts the stub in the kernel proper, which will unnecessarily retain all
@@ -89,7 +89,7 @@ quiet_cmd_stubcopy = STUBCPY $@
cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \
then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \
then (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \
- rm -f $@; /bin/false); \
+ rm -f $@; /bin/false); \
else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi \
else /bin/false; fi
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index eee42d5e25ee..04e6ecd72cd9 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
efi_status_t status;
- if (IS_ENABLED(CONFIG_ARM))
- return;
-
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv);
if (status != EFI_SUCCESS) {
@@ -370,6 +367,11 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
paddr = in->phys_addr;
size = in->num_pages * EFI_PAGE_SIZE;
+ if (novamap()) {
+ in->virt_addr = in->phys_addr;
+ continue;
+ }
+
/*
* Make the mapping compatible with 64k pages: this allows
* a 4k page size kernel to kexec a 64k page size kernel and
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index becbda445913..e8f7aefb6813 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2013 Linaro Ltd; <roy.franz@linaro.org>
- *
- * 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/efi.h>
#include <asm/efi.h>
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 1b4d465cc5d9..1550d244e996 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
*
* This file implements the EFI boot stub for the arm64 kernel.
* Adapted from ARM version by Mark Salter <msalter@redhat.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.
- *
*/
/*
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index e94975f4655b..e4610e72b78f 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Helper functions used by the EFI stub on multiple
* architectures. This should be #included by the EFI stub
* implementation files.
*
* Copyright 2011 Intel Corporation; author Matt Fleming
- *
- * This file is part of the Linux kernel, and is made available
- * under the terms of the GNU General Public License version 2.
- *
*/
#include <linux/efi.h>
@@ -34,6 +31,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
static int __section(.data) __nokaslr;
static int __section(.data) __quiet;
+static int __section(.data) __novamap;
int __pure nokaslr(void)
{
@@ -43,6 +41,10 @@ int __pure is_quiet(void)
{
return __quiet;
}
+int __pure novamap(void)
+{
+ return __novamap;
+}
#define EFI_MMAP_NR_SLACK_SLOTS 8
@@ -482,6 +484,11 @@ efi_status_t efi_parse_options(char const *cmdline)
__chunk_size = -1UL;
}
+ if (!strncmp(str, "novamap", 7)) {
+ str += strlen("novamap");
+ __novamap = 1;
+ }
+
/* Group words together, delimited by "," */
while (*str && *str != ' ' && *str != ',')
str++;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 32799cf039ef..1b1dfcaa6fb9 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -27,6 +27,7 @@
extern int __pure nokaslr(void);
extern int __pure is_quiet(void);
+extern int __pure novamap(void);
#define pr_efi(sys_table, msg) do { \
if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
@@ -64,4 +65,15 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+/* Helper macros for the usual case of using simple C variables: */
+#ifndef fdt_setprop_inplace_var
+#define fdt_setprop_inplace_var(fdt, node_offset, name, var) \
+ fdt_setprop_inplace((fdt), (node_offset), (name), &(var), sizeof(var))
+#endif
+
+#ifndef fdt_setprop_var
+#define fdt_setprop_var(fdt, node_offset, name, var) \
+ fdt_setprop((fdt), (node_offset), (name), &(var), sizeof(var))
+#endif
+
#endif
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 0dc7b4987cc2..5440ba17a1c5 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* FDT related Helper functions used by the EFI stub on multiple
* architectures. This should be #included by the EFI stub
* implementation files.
*
* Copyright 2013 Linaro Limited; author Roy Franz
- *
- * This file is part of the Linux kernel, and is made available
- * under the terms of the GNU General Public License version 2.
- *
*/
#include <linux/efi.h>
@@ -26,10 +23,8 @@ static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt)
offset = fdt_path_offset(fdt, "/");
/* Set the #address-cells and #size-cells values for an empty tree */
- fdt_setprop_u32(fdt, offset, "#address-cells",
- EFI_DT_ADDR_CELLS_DEFAULT);
-
- fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT);
+ fdt_setprop_u32(fdt, offset, "#address-cells", EFI_DT_ADDR_CELLS_DEFAULT);
+ fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT);
}
static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
@@ -42,7 +37,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
u32 fdt_val32;
u64 fdt_val64;
- /* Do some checks on provided FDT, if it exists*/
+ /* Do some checks on provided FDT, if it exists: */
if (orig_fdt) {
if (fdt_check_header(orig_fdt)) {
pr_efi_err(sys_table, "Device Tree header not valid!\n");
@@ -50,7 +45,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
}
/*
* We don't get the size of the FDT if we get if from a
- * configuration table.
+ * configuration table:
*/
if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
pr_efi_err(sys_table, "Truncated device tree! foo!\n");
@@ -64,8 +59,8 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
status = fdt_create_empty_tree(fdt, new_fdt_size);
if (status == 0) {
/*
- * Any failure from the following function is non
- * critical
+ * Any failure from the following function is
+ * non-critical:
*/
fdt_update_cell_size(sys_table, fdt);
}
@@ -86,12 +81,13 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
if (node < 0) {
node = fdt_add_subnode(fdt, 0, "chosen");
if (node < 0) {
- status = node; /* node is error code when negative */
+ /* 'node' is an error code when negative: */
+ status = node;
goto fdt_set_fail;
}
}
- if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+ if (cmdline_ptr != NULL && strlen(cmdline_ptr) > 0) {
status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
strlen(cmdline_ptr) + 1);
if (status)
@@ -103,13 +99,12 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
u64 initrd_image_end;
u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
- status = fdt_setprop(fdt, node, "linux,initrd-start",
- &initrd_image_start, sizeof(u64));
+ status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start);
if (status)
goto fdt_set_fail;
+
initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
- status = fdt_setprop(fdt, node, "linux,initrd-end",
- &initrd_image_end, sizeof(u64));
+ status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end);
if (status)
goto fdt_set_fail;
}
@@ -117,30 +112,28 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
/* Add FDT entries for EFI runtime services in chosen node. */
node = fdt_subnode_offset(fdt, 0, "chosen");
fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
- status = fdt_setprop(fdt, node, "linux,uefi-system-table",
- &fdt_val64, sizeof(fdt_val64));
+
+ status = fdt_setprop_var(fdt, node, "linux,uefi-system-table", fdt_val64);
if (status)
goto fdt_set_fail;
fdt_val64 = U64_MAX; /* placeholder */
- status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
- &fdt_val64, sizeof(fdt_val64));
+
+ status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
if (status)
goto fdt_set_fail;
fdt_val32 = U32_MAX; /* placeholder */
- status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
- &fdt_val32, sizeof(fdt_val32));
+
+ status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
if (status)
goto fdt_set_fail;
- status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
- &fdt_val32, sizeof(fdt_val32));
+ status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32);
if (status)
goto fdt_set_fail;
- status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
- &fdt_val32, sizeof(fdt_val32));
+ status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32);
if (status)
goto fdt_set_fail;
@@ -150,8 +143,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64),
(u8 *)&fdt_val64);
if (efi_status == EFI_SUCCESS) {
- status = fdt_setprop(fdt, node, "kaslr-seed",
- &fdt_val64, sizeof(fdt_val64));
+ status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64);
if (status)
goto fdt_set_fail;
} else if (efi_status != EFI_NOT_FOUND) {
@@ -159,7 +151,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
}
}
- /* shrink the FDT back to its minimum size */
+ /* Shrink the FDT back to its minimum size: */
fdt_pack(fdt);
return EFI_SUCCESS;
@@ -182,26 +174,26 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
return EFI_LOAD_ERROR;
fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
- err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start",
- &fdt_val64, sizeof(fdt_val64));
+
+ err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
if (err)
return EFI_LOAD_ERROR;
fdt_val32 = cpu_to_fdt32(*map->map_size);
- err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size",
- &fdt_val32, sizeof(fdt_val32));
+
+ err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
if (err)
return EFI_LOAD_ERROR;
fdt_val32 = cpu_to_fdt32(*map->desc_size);
- err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size",
- &fdt_val32, sizeof(fdt_val32));
+
+ err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32);
if (err)
return EFI_LOAD_ERROR;
fdt_val32 = cpu_to_fdt32(*map->desc_ver);
- err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver",
- &fdt_val32, sizeof(fdt_val32));
+
+ err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32);
if (err)
return EFI_LOAD_ERROR;
@@ -209,13 +201,13 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
}
#ifndef EFI_FDT_ALIGN
-#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+# define EFI_FDT_ALIGN EFI_PAGE_SIZE
#endif
struct exit_boot_struct {
- efi_memory_desc_t *runtime_map;
- int *runtime_entry_count;
- void *new_fdt_addr;
+ efi_memory_desc_t *runtime_map;
+ int *runtime_entry_count;
+ void *new_fdt_addr;
};
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -235,7 +227,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
}
#ifndef MAX_FDT_SIZE
-#define MAX_FDT_SIZE SZ_2M
+# define MAX_FDT_SIZE SZ_2M
#endif
/*
@@ -266,16 +258,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
unsigned long mmap_key;
efi_memory_desc_t *memory_map, *runtime_map;
efi_status_t status;
- int runtime_entry_count = 0;
+ int runtime_entry_count;
struct efi_boot_memmap map;
struct exit_boot_struct priv;
- map.map = &runtime_map;
- map.map_size = &map_size;
- map.desc_size = &desc_size;
- map.desc_ver = &desc_ver;
- map.key_ptr = &mmap_key;
- map.buff_size = &buff_size;
+ map.map = &runtime_map;
+ map.map_size = &map_size;
+ map.desc_size = &desc_size;
+ map.desc_ver = &desc_ver;
+ map.key_ptr = &mmap_key;
+ map.buff_size = &buff_size;
/*
* Get a copy of the current memory map that we will use to prepare
@@ -289,15 +281,13 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
return status;
}
- pr_efi(sys_table,
- "Exiting boot services and installing virtual address map...\n");
+ pr_efi(sys_table, "Exiting boot services and installing virtual address map...\n");
map.map = &memory_map;
status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
new_fdt_addr, max_addr);
if (status != EFI_SUCCESS) {
- pr_efi_err(sys_table,
- "Unable to allocate memory for new device tree.\n");
+ pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
goto fail;
}
@@ -318,15 +308,19 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
goto fail_free_new_fdt;
}
- priv.runtime_map = runtime_map;
- priv.runtime_entry_count = &runtime_entry_count;
- priv.new_fdt_addr = (void *)*new_fdt_addr;
- status = efi_exit_boot_services(sys_table, handle, &map, &priv,
- exit_boot_func);
+ runtime_entry_count = 0;
+ priv.runtime_map = runtime_map;
+ priv.runtime_entry_count = &runtime_entry_count;
+ priv.new_fdt_addr = (void *)*new_fdt_addr;
+
+ status = efi_exit_boot_services(sys_table, handle, &map, &priv, exit_boot_func);
if (status == EFI_SUCCESS) {
efi_set_virtual_address_map_t *svam;
+ if (novamap())
+ return EFI_SUCCESS;
+
/* Install the new virtual address map */
svam = sys_table->runtime->set_virtual_address_map;
status = svam(runtime_entry_count * desc_size, desc_size,
@@ -363,6 +357,7 @@ fail_free_new_fdt:
fail:
sys_table->boottime->free_pool(runtime_map);
+
return EFI_LOAD_ERROR;
}
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 24c461dea7af..0101ca4c13b1 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/* -----------------------------------------------------------------------
*
* Copyright 2011 Intel Corporation; author Matt Fleming
*
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2.
- *
* ----------------------------------------------------------------------- */
#include <linux/efi.h>
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index e0e603a89aa9..b4b1d1dcb5fd 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2016 Linaro Ltd; <ard.biesheuvel@linaro.org>
- *
- * 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/efi.h>
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
index 72d9dfbebf08..edba5e7a3743 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Secure boot handling.
*
@@ -5,9 +6,6 @@
* Roy Franz <roy.franz@linaro.org
* Copyright (C) 2013 Red Hat, Inc.
* Mark Salter <msalter@redhat.com>
- *
- * This file is part of the Linux kernel, and is made available under the
- * terms of the GNU General Public License version 2.
*/
#include <linux/efi.h>
#include <asm/efi.h>
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index a90b0b8fc69a..5bd04f75d8d6 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* TPM handling.
*
@@ -5,9 +6,6 @@
* Copyright (C) 2017 Google, Inc.
* Matthew Garrett <mjg59@google.com>
* Thiebaud Weksteen <tweek@google.com>
- *
- * This file is part of the Linux kernel, and is made available under the
- * terms of the GNU General Public License version 2.
*/
#include <linux/efi.h>
#include <linux/tpm_eventlog.h>
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 8986757eafaf..58452fde92cc 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
- *
- * 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.
*/
#define pr_fmt(fmt) "efi: memattr: " fmt
@@ -94,7 +91,7 @@ static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out)
if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;
- if (md->virt_addr == 0) {
+ if (md->virt_addr == 0 && md->phys_addr != 0) {
/* no virtual mapping has been installed by the stub */
break;
}
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
index 84a11d0a8023..ad9ddefc9dcb 100644
--- a/drivers/firmware/efi/runtime-map.c
+++ b/drivers/firmware/efi/runtime-map.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* linux/drivers/efi/runtime-map.c
* Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com>
- *
- * This file is released under the GPLv2.
*/
#include <linux/string.h>
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index 8903b9ccfc2b..698745c249e8 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -85,7 +85,7 @@ struct efi_runtime_work efi_rts_work;
pr_err("Failed to queue work to efi_rts_wq.\n"); \
\
exit: \
- efi_rts_work.efi_rts_id = NONE; \
+ efi_rts_work.efi_rts_id = EFI_NONE; \
efi_rts_work.status; \
})
@@ -147,6 +147,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
static DEFINE_SEMAPHORE(efi_runtime_lock);
/*
+ * Expose the EFI runtime lock to the UV platform
+ */
+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
+/*
* Calls the appropriate efi_runtime_service() with the appropriate
* arguments.
*
@@ -168,50 +175,50 @@ static void efi_call_rts(struct work_struct *work)
arg5 = efi_rts_work.arg5;
switch (efi_rts_work.efi_rts_id) {
- case GET_TIME:
+ case EFI_GET_TIME:
status = efi_call_virt(get_time, (efi_time_t *)arg1,
(efi_time_cap_t *)arg2);
break;
- case SET_TIME:
+ case EFI_SET_TIME:
status = efi_call_virt(set_time, (efi_time_t *)arg1);
break;
- case GET_WAKEUP_TIME:
+ case EFI_GET_WAKEUP_TIME:
status = efi_call_virt(get_wakeup_time, (efi_bool_t *)arg1,
(efi_bool_t *)arg2, (efi_time_t *)arg3);
break;
- case SET_WAKEUP_TIME:
+ case EFI_SET_WAKEUP_TIME:
status = efi_call_virt(set_wakeup_time, *(efi_bool_t *)arg1,
(efi_time_t *)arg2);
break;
- case GET_VARIABLE:
+ case EFI_GET_VARIABLE:
status = efi_call_virt(get_variable, (efi_char16_t *)arg1,
(efi_guid_t *)arg2, (u32 *)arg3,
(unsigned long *)arg4, (void *)arg5);
break;
- case GET_NEXT_VARIABLE:
+ case EFI_GET_NEXT_VARIABLE:
status = efi_call_virt(get_next_variable, (unsigned long *)arg1,
(efi_char16_t *)arg2,
(efi_guid_t *)arg3);
break;
- case SET_VARIABLE:
+ case EFI_SET_VARIABLE:
status = efi_call_virt(set_variable, (efi_char16_t *)arg1,
(efi_guid_t *)arg2, *(u32 *)arg3,
*(unsigned long *)arg4, (void *)arg5);
break;
- case QUERY_VARIABLE_INFO:
+ case EFI_QUERY_VARIABLE_INFO:
status = efi_call_virt(query_variable_info, *(u32 *)arg1,
(u64 *)arg2, (u64 *)arg3, (u64 *)arg4);
break;
- case GET_NEXT_HIGH_MONO_COUNT:
+ case EFI_GET_NEXT_HIGH_MONO_COUNT:
status = efi_call_virt(get_next_high_mono_count, (u32 *)arg1);
break;
- case UPDATE_CAPSULE:
+ case EFI_UPDATE_CAPSULE:
status = efi_call_virt(update_capsule,
(efi_capsule_header_t **)arg1,
*(unsigned long *)arg2,
*(unsigned long *)arg3);
break;
- case QUERY_CAPSULE_CAPS:
+ case EFI_QUERY_CAPSULE_CAPS:
status = efi_call_virt(query_capsule_caps,
(efi_capsule_header_t **)arg1,
*(unsigned long *)arg2, (u64 *)arg3,
@@ -235,7 +242,7 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
+ status = efi_queue_work(EFI_GET_TIME, tm, tc, NULL, NULL, NULL);
up(&efi_runtime_lock);
return status;
}
@@ -246,7 +253,7 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
+ status = efi_queue_work(EFI_SET_TIME, tm, NULL, NULL, NULL, NULL);
up(&efi_runtime_lock);
return status;
}
@@ -259,7 +266,7 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
+ status = efi_queue_work(EFI_GET_WAKEUP_TIME, enabled, pending, tm, NULL,
NULL);
up(&efi_runtime_lock);
return status;
@@ -271,7 +278,7 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
+ status = efi_queue_work(EFI_SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
NULL);
up(&efi_runtime_lock);
return status;
@@ -287,7 +294,7 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
+ status = efi_queue_work(EFI_GET_VARIABLE, name, vendor, attr, data_size,
data);
up(&efi_runtime_lock);
return status;
@@ -301,7 +308,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
+ status = efi_queue_work(EFI_GET_NEXT_VARIABLE, name_size, name, vendor,
NULL, NULL);
up(&efi_runtime_lock);
return status;
@@ -317,7 +324,7 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
+ status = efi_queue_work(EFI_SET_VARIABLE, name, vendor, &attr, &data_size,
data);
up(&efi_runtime_lock);
return status;
@@ -352,7 +359,7 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
+ status = efi_queue_work(EFI_QUERY_VARIABLE_INFO, &attr, storage_space,
remaining_space, max_variable_size, NULL);
up(&efi_runtime_lock);
return status;
@@ -384,7 +391,7 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
+ status = efi_queue_work(EFI_GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
NULL, NULL);
up(&efi_runtime_lock);
return status;
@@ -400,7 +407,7 @@ static void virt_efi_reset_system(int reset_type,
"could not get exclusive access to the firmware\n");
return;
}
- efi_rts_work.efi_rts_id = RESET_SYSTEM;
+ efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM;
__efi_call_virt(reset_system, reset_type, status, data_size, data);
up(&efi_runtime_lock);
}
@@ -416,7 +423,7 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
+ status = efi_queue_work(EFI_UPDATE_CAPSULE, capsules, &count, &sg_list,
NULL, NULL);
up(&efi_runtime_lock);
return status;
@@ -434,7 +441,7 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
if (down_interruptible(&efi_runtime_lock))
return EFI_ABORTED;
- status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
+ status = efi_queue_work(EFI_QUERY_CAPSULE_CAPS, capsules, &count,
max_size, reset_type, NULL);
up(&efi_runtime_lock);
return status;
diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c
index 51ecf7d6da48..877745c3aaf2 100644
--- a/drivers/firmware/efi/test/efi_test.c
+++ b/drivers/firmware/efi/test/efi_test.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* EFI Test Driver for Runtime Services
*
diff --git a/drivers/firmware/efi/test/efi_test.h b/drivers/firmware/efi/test/efi_test.h
index 5f4818bf112f..f2446aa1c2e3 100644
--- a/drivers/firmware/efi/test/efi_test.h
+++ b/drivers/firmware/efi/test/efi_test.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* EFI Test driver Header
*
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
index 0cbeb3d46b18..3a689b40ccc0 100644
--- a/drivers/firmware/efi/tpm.c
+++ b/drivers/firmware/efi/tpm.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2017 Google, Inc.
* Thiebaud Weksteen <tweek@google.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/efi.h>
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index fceaafd67ec6..436d1776bc7b 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Originally from efivars.c
*
* Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
* Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.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.
- *
- * 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
*/
#include <linux/capability.h>
diff --git a/drivers/firmware/imx/misc.c b/drivers/firmware/imx/misc.c
index 97f5424dbac9..4b56a587dacd 100644
--- a/drivers/firmware/imx/misc.c
+++ b/drivers/firmware/imx/misc.c
@@ -18,6 +18,14 @@ struct imx_sc_msg_req_misc_set_ctrl {
u16 resource;
} __packed;
+struct imx_sc_msg_req_cpu_start {
+ struct imx_sc_rpc_msg hdr;
+ u32 address_hi;
+ u32 address_lo;
+ u16 resource;
+ u8 enable;
+} __packed;
+
struct imx_sc_msg_req_misc_get_ctrl {
struct imx_sc_rpc_msg hdr;
u32 ctrl;
@@ -97,3 +105,33 @@ int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
return 0;
}
EXPORT_SYMBOL(imx_sc_misc_get_control);
+
+/*
+ * This function starts/stops a CPU identified by @resource
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource the control is associated with
+ * @param[in] enable true for start, false for stop
+ * @param[in] phys_addr initial instruction address to be executed
+ *
+ * @return Returns 0 for success and < 0 for errors.
+ */
+int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
+ bool enable, u64 phys_addr)
+{
+ struct imx_sc_msg_req_cpu_start msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_CPU_START;
+ hdr->size = 4;
+
+ msg.address_hi = phys_addr >> 32;
+ msg.address_lo = phys_addr;
+ msg.resource = resource;
+ msg.enable = enable;
+
+ return imx_scu_call_rpc(ipc, &msg, true);
+}
+EXPORT_SYMBOL(imx_sc_pm_cpu_start);
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 407245f2efd0..39a94c7177fc 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -322,6 +322,7 @@ static int imx_sc_pd_probe(struct platform_device *pdev)
static const struct of_device_id imx_sc_pd_match[] = {
{ .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
+ { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
{ /* sentinel */ }
};
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a13558154ac3..61be15d9df7d 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -238,6 +238,16 @@ static int rpi_firmware_probe(struct platform_device *pdev)
return 0;
}
+static void rpi_firmware_shutdown(struct platform_device *pdev)
+{
+ struct rpi_firmware *fw = platform_get_drvdata(pdev);
+
+ if (!fw)
+ return;
+
+ rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
+}
+
static int rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
@@ -278,6 +288,7 @@ static struct platform_driver rpi_firmware_driver = {
.of_match_table = rpi_firmware_of_match,
},
.probe = rpi_firmware_probe,
+ .shutdown = rpi_firmware_shutdown,
.remove = rpi_firmware_remove,
};
module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
index 1b826dcca719..676b01caff05 100644
--- a/drivers/firmware/tegra/Makefile
+++ b/drivers/firmware/tegra/Makefile
@@ -1,4 +1,7 @@
tegra-bpmp-y = bpmp.o
+tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o
+tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
+tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o
tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
obj-$(CONFIG_TEGRA_IVC) += ivc.o
diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h
new file mode 100644
index 000000000000..54d560c48398
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-private.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION.
+ */
+
+#ifndef __FIRMWARE_TEGRA_BPMP_PRIVATE_H
+#define __FIRMWARE_TEGRA_BPMP_PRIVATE_H
+
+#include <soc/tegra/bpmp.h>
+
+struct tegra_bpmp_ops {
+ int (*init)(struct tegra_bpmp *bpmp);
+ void (*deinit)(struct tegra_bpmp *bpmp);
+ bool (*is_response_ready)(struct tegra_bpmp_channel *channel);
+ bool (*is_request_ready)(struct tegra_bpmp_channel *channel);
+ int (*ack_response)(struct tegra_bpmp_channel *channel);
+ int (*ack_request)(struct tegra_bpmp_channel *channel);
+ bool (*is_response_channel_free)(struct tegra_bpmp_channel *channel);
+ bool (*is_request_channel_free)(struct tegra_bpmp_channel *channel);
+ int (*post_response)(struct tegra_bpmp_channel *channel);
+ int (*post_request)(struct tegra_bpmp_channel *channel);
+ int (*ring_doorbell)(struct tegra_bpmp *bpmp);
+ int (*resume)(struct tegra_bpmp *bpmp);
+};
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
+ IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
+extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
+#endif
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
+extern const struct tegra_bpmp_ops tegra210_bpmp_ops;
+#endif
+
+#endif
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
new file mode 100644
index 000000000000..ea308751635f
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION.
+ */
+
+#include <linux/genalloc.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+#include <soc/tegra/ivc.h>
+
+#include "bpmp-private.h"
+
+struct tegra186_bpmp {
+ struct tegra_bpmp *parent;
+
+ struct {
+ struct gen_pool *pool;
+ dma_addr_t phys;
+ void *virt;
+ } tx, rx;
+
+ struct {
+ struct mbox_client client;
+ struct mbox_chan *channel;
+ } mbox;
+};
+
+static inline struct tegra_bpmp *
+mbox_client_to_bpmp(struct mbox_client *client)
+{
+ struct tegra186_bpmp *priv;
+
+ priv = container_of(client, struct tegra186_bpmp, mbox.client);
+
+ return priv->parent;
+}
+
+static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
+{
+ void *frame;
+
+ frame = tegra_ivc_read_get_next_frame(channel->ivc);
+ if (IS_ERR(frame)) {
+ channel->ib = NULL;
+ return false;
+ }
+
+ channel->ib = frame;
+
+ return true;
+}
+
+static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
+{
+ void *frame;
+
+ frame = tegra_ivc_write_get_next_frame(channel->ivc);
+ if (IS_ERR(frame)) {
+ channel->ob = NULL;
+ return false;
+ }
+
+ channel->ob = frame;
+
+ return true;
+}
+
+static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
+{
+ return tegra_ivc_read_advance(channel->ivc);
+}
+
+static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
+{
+ return tegra_ivc_write_advance(channel->ivc);
+}
+
+static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv = bpmp->priv;
+ int err;
+
+ err = mbox_send_message(priv->mbox.channel, NULL);
+ if (err < 0)
+ return err;
+
+ mbox_client_txdone(priv->mbox.channel, 0);
+
+ return 0;
+}
+
+static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
+{
+ struct tegra_bpmp *bpmp = data;
+ struct tegra186_bpmp *priv = bpmp->priv;
+
+ if (WARN_ON(priv->mbox.channel == NULL))
+ return;
+
+ tegra186_bpmp_ring_doorbell(bpmp);
+}
+
+static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
+ struct tegra_bpmp *bpmp,
+ unsigned int index)
+{
+ struct tegra186_bpmp *priv = bpmp->priv;
+ size_t message_size, queue_size;
+ unsigned int offset;
+ int err;
+
+ channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
+ GFP_KERNEL);
+ if (!channel->ivc)
+ return -ENOMEM;
+
+ message_size = tegra_ivc_align(MSG_MIN_SZ);
+ queue_size = tegra_ivc_total_queue_size(message_size);
+ offset = queue_size * index;
+
+ err = tegra_ivc_init(channel->ivc, NULL,
+ priv->rx.virt + offset, priv->rx.phys + offset,
+ priv->tx.virt + offset, priv->tx.phys + offset,
+ 1, message_size, tegra186_bpmp_ivc_notify,
+ bpmp);
+ if (err < 0) {
+ dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
+ index, err);
+ return err;
+ }
+
+ init_completion(&channel->completion);
+ channel->bpmp = bpmp;
+
+ return 0;
+}
+
+static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
+{
+ /* reset the channel state */
+ tegra_ivc_reset(channel->ivc);
+
+ /* sync the channel state with BPMP */
+ while (tegra_ivc_notified(channel->ivc))
+ ;
+}
+
+static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
+{
+ tegra_ivc_cleanup(channel->ivc);
+}
+
+static void mbox_handle_rx(struct mbox_client *client, void *data)
+{
+ struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
+
+ tegra_bpmp_handle_rx(bpmp);
+}
+
+static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv;
+ unsigned int i;
+ int err;
+
+ priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ bpmp->priv = priv;
+ priv->parent = bpmp;
+
+ priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
+ if (!priv->tx.pool) {
+ dev_err(bpmp->dev, "TX shmem pool not found\n");
+ return -ENOMEM;
+ }
+
+ priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
+ if (!priv->tx.virt) {
+ dev_err(bpmp->dev, "failed to allocate from TX pool\n");
+ return -ENOMEM;
+ }
+
+ priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
+ if (!priv->rx.pool) {
+ dev_err(bpmp->dev, "RX shmem pool not found\n");
+ err = -ENOMEM;
+ goto free_tx;
+ }
+
+ priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
+ if (!priv->rx.virt) {
+ dev_err(bpmp->dev, "failed to allocate from RX pool\n");
+ err = -ENOMEM;
+ goto free_tx;
+ }
+
+ err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
+ bpmp->soc->channels.cpu_tx.offset);
+ if (err < 0)
+ goto free_rx;
+
+ err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
+ bpmp->soc->channels.cpu_rx.offset);
+ if (err < 0)
+ goto cleanup_tx_channel;
+
+ for (i = 0; i < bpmp->threaded.count; i++) {
+ unsigned int index = bpmp->soc->channels.thread.offset + i;
+
+ err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
+ bpmp, index);
+ if (err < 0)
+ goto cleanup_channels;
+ }
+
+ /* mbox registration */
+ priv->mbox.client.dev = bpmp->dev;
+ priv->mbox.client.rx_callback = mbox_handle_rx;
+ priv->mbox.client.tx_block = false;
+ priv->mbox.client.knows_txdone = false;
+
+ priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
+ if (IS_ERR(priv->mbox.channel)) {
+ err = PTR_ERR(priv->mbox.channel);
+ dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
+ goto cleanup_channels;
+ }
+
+ tegra186_bpmp_channel_reset(bpmp->tx_channel);
+ tegra186_bpmp_channel_reset(bpmp->rx_channel);
+
+ for (i = 0; i < bpmp->threaded.count; i++)
+ tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+
+ return 0;
+
+cleanup_channels:
+ for (i = 0; i < bpmp->threaded.count; i++) {
+ if (!bpmp->threaded_channels[i].bpmp)
+ continue;
+
+ tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
+ }
+
+ tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
+cleanup_tx_channel:
+ tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
+free_rx:
+ gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
+free_tx:
+ gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
+
+ return err;
+}
+
+static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv = bpmp->priv;
+ unsigned int i;
+
+ mbox_free_channel(priv->mbox.channel);
+
+ for (i = 0; i < bpmp->threaded.count; i++)
+ tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
+
+ tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
+ tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
+
+ gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
+ gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
+}
+
+static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
+{
+ unsigned int i;
+
+ /* reset message channels */
+ tegra186_bpmp_channel_reset(bpmp->tx_channel);
+ tegra186_bpmp_channel_reset(bpmp->rx_channel);
+
+ for (i = 0; i < bpmp->threaded.count; i++)
+ tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+
+ return 0;
+}
+
+const struct tegra_bpmp_ops tegra186_bpmp_ops = {
+ .init = tegra186_bpmp_init,
+ .deinit = tegra186_bpmp_deinit,
+ .is_response_ready = tegra186_bpmp_is_message_ready,
+ .is_request_ready = tegra186_bpmp_is_message_ready,
+ .ack_response = tegra186_bpmp_ack_message,
+ .ack_request = tegra186_bpmp_ack_message,
+ .is_response_channel_free = tegra186_bpmp_is_channel_free,
+ .is_request_channel_free = tegra186_bpmp_is_channel_free,
+ .post_response = tegra186_bpmp_post_message,
+ .post_request = tegra186_bpmp_post_message,
+ .ring_doorbell = tegra186_bpmp_ring_doorbell,
+ .resume = tegra186_bpmp_resume,
+};
diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c
new file mode 100644
index 000000000000..ae15940a078e
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra210.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <soc/tegra/bpmp.h>
+
+#include "bpmp-private.h"
+
+#define TRIGGER_OFFSET 0x000
+#define RESULT_OFFSET(id) (0xc00 + id * 4)
+#define TRIGGER_ID_SHIFT 16
+#define TRIGGER_CMD_GET 4
+
+#define STA_OFFSET 0
+#define SET_OFFSET 4
+#define CLR_OFFSET 8
+
+#define CH_MASK(ch) (0x3 << ((ch) * 2))
+#define SL_SIGL(ch) (0x0 << ((ch) * 2))
+#define SL_QUED(ch) (0x1 << ((ch) * 2))
+#define MA_FREE(ch) (0x2 << ((ch) * 2))
+#define MA_ACKD(ch) (0x3 << ((ch) * 2))
+
+struct tegra210_bpmp {
+ void __iomem *atomics;
+ void __iomem *arb_sema;
+ struct irq_data *tx_irq_data;
+};
+
+static u32 bpmp_channel_status(struct tegra_bpmp *bpmp, unsigned int index)
+{
+ struct tegra210_bpmp *priv = bpmp->priv;
+
+ return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(index);
+}
+
+static bool tegra210_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
+{
+ unsigned int index = channel->index;
+
+ return bpmp_channel_status(channel->bpmp, index) == MA_ACKD(index);
+}
+
+static bool tegra210_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
+{
+ unsigned int index = channel->index;
+
+ return bpmp_channel_status(channel->bpmp, index) == SL_SIGL(index);
+}
+
+static bool
+tegra210_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
+{
+ unsigned int index = channel->index;
+
+ return bpmp_channel_status(channel->bpmp, index) == MA_FREE(index);
+}
+
+static bool
+tegra210_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
+{
+ unsigned int index = channel->index;
+
+ return bpmp_channel_status(channel->bpmp, index) == SL_QUED(index);
+}
+
+static int tegra210_bpmp_post_request(struct tegra_bpmp_channel *channel)
+{
+ struct tegra210_bpmp *priv = channel->bpmp->priv;
+
+ __raw_writel(CH_MASK(channel->index), priv->arb_sema + CLR_OFFSET);
+
+ return 0;
+}
+
+static int tegra210_bpmp_post_response(struct tegra_bpmp_channel *channel)
+{
+ struct tegra210_bpmp *priv = channel->bpmp->priv;
+
+ __raw_writel(MA_ACKD(channel->index), priv->arb_sema + SET_OFFSET);
+
+ return 0;
+}
+
+static int tegra210_bpmp_ack_response(struct tegra_bpmp_channel *channel)
+{
+ struct tegra210_bpmp *priv = channel->bpmp->priv;
+
+ __raw_writel(MA_ACKD(channel->index) ^ MA_FREE(channel->index),
+ priv->arb_sema + CLR_OFFSET);
+
+ return 0;
+}
+
+static int tegra210_bpmp_ack_request(struct tegra_bpmp_channel *channel)
+{
+ struct tegra210_bpmp *priv = channel->bpmp->priv;
+
+ __raw_writel(SL_QUED(channel->index), priv->arb_sema + SET_OFFSET);
+
+ return 0;
+}
+
+static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
+{
+ struct tegra210_bpmp *priv = bpmp->priv;
+ struct irq_data *irq_data = priv->tx_irq_data;
+
+ /*
+ * Tegra Legacy Interrupt Controller (LIC) is used to notify BPMP of
+ * available messages
+ */
+ if (irq_data->chip->irq_retrigger)
+ return irq_data->chip->irq_retrigger(irq_data);
+
+ return -EINVAL;
+}
+
+static irqreturn_t rx_irq(int irq, void *data)
+{
+ struct tegra_bpmp *bpmp = data;
+
+ tegra_bpmp_handle_rx(bpmp);
+
+ return IRQ_HANDLED;
+}
+
+static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
+ struct tegra_bpmp *bpmp,
+ unsigned int index)
+{
+ struct tegra210_bpmp *priv = bpmp->priv;
+ u32 address;
+ void *p;
+
+ /* Retrieve channel base address from BPMP */
+ writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
+ priv->atomics + TRIGGER_OFFSET);
+ address = readl(priv->atomics + RESULT_OFFSET(index));
+
+ p = devm_ioremap(bpmp->dev, address, 0x80);
+ if (!p)
+ return -ENOMEM;
+
+ channel->ib = p;
+ channel->ob = p;
+ channel->index = index;
+ init_completion(&channel->completion);
+ channel->bpmp = bpmp;
+
+ return 0;
+}
+
+static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
+{
+ struct platform_device *pdev = to_platform_device(bpmp->dev);
+ struct tegra210_bpmp *priv;
+ struct resource *res;
+ unsigned int i;
+ int err;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ bpmp->priv = priv;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->atomics = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->atomics))
+ return PTR_ERR(priv->atomics);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->arb_sema = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->arb_sema))
+ return PTR_ERR(priv->arb_sema);
+
+ err = tegra210_bpmp_channel_init(bpmp->tx_channel, bpmp,
+ bpmp->soc->channels.cpu_tx.offset);
+ if (err < 0)
+ return err;
+
+ err = tegra210_bpmp_channel_init(bpmp->rx_channel, bpmp,
+ bpmp->soc->channels.cpu_rx.offset);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < bpmp->threaded.count; i++) {
+ unsigned int index = bpmp->soc->channels.thread.offset + i;
+
+ err = tegra210_bpmp_channel_init(&bpmp->threaded_channels[i],
+ bpmp, index);
+ if (err < 0)
+ return err;
+ }
+
+ err = platform_get_irq_byname(pdev, "tx");
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
+ return err;
+ }
+
+ priv->tx_irq_data = irq_get_irq_data(err);
+ if (!priv->tx_irq_data) {
+ dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
+ return err;
+ }
+
+ err = platform_get_irq_byname(pdev, "rx");
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
+ return err;
+ }
+
+ err = devm_request_irq(&pdev->dev, err, rx_irq,
+ IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+const struct tegra_bpmp_ops tegra210_bpmp_ops = {
+ .init = tegra210_bpmp_init,
+ .is_response_ready = tegra210_bpmp_is_response_ready,
+ .is_request_ready = tegra210_bpmp_is_request_ready,
+ .ack_response = tegra210_bpmp_ack_response,
+ .ack_request = tegra210_bpmp_ack_request,
+ .is_response_channel_free = tegra210_bpmp_is_response_channel_free,
+ .is_request_channel_free = tegra210_bpmp_is_request_channel_free,
+ .post_response = tegra210_bpmp_post_response,
+ .post_request = tegra210_bpmp_post_request,
+ .ring_doorbell = tegra210_bpmp_ring_doorbell,
+};
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 689478b92bce..dd775e8ba5a0 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -26,6 +26,8 @@
#include <soc/tegra/bpmp-abi.h>
#include <soc/tegra/ivc.h>
+#include "bpmp-private.h"
+
#define MSG_ACK BIT(0)
#define MSG_RING BIT(1)
#define TAG_SZ 32
@@ -36,6 +38,14 @@ mbox_client_to_bpmp(struct mbox_client *client)
return container_of(client, struct tegra_bpmp, mbox.client);
}
+static inline const struct tegra_bpmp_ops *
+channel_to_ops(struct tegra_bpmp_channel *channel)
+{
+ struct tegra_bpmp *bpmp = channel->bpmp;
+
+ return bpmp->soc->ops;
+}
+
struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
{
struct platform_device *pdev;
@@ -96,22 +106,21 @@ static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
(msg->rx.size == 0 || msg->rx.data);
}
-static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel)
+static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
{
- void *frame;
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
- frame = tegra_ivc_read_get_next_frame(channel->ivc);
- if (IS_ERR(frame)) {
- channel->ib = NULL;
- return false;
- }
+ return ops->is_response_ready(channel);
+}
- channel->ib = frame;
+static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
- return true;
+ return ops->is_request_ready(channel);
}
-static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
+static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
{
unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
ktime_t end;
@@ -119,29 +128,45 @@ static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
end = ktime_add_us(ktime_get(), timeout);
do {
- if (tegra_bpmp_master_acked(channel))
+ if (tegra_bpmp_is_response_ready(channel))
return 0;
} while (ktime_before(ktime_get(), end));
return -ETIMEDOUT;
}
-static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel)
+static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel)
{
- void *frame;
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
- frame = tegra_ivc_write_get_next_frame(channel->ivc);
- if (IS_ERR(frame)) {
- channel->ob = NULL;
- return false;
- }
+ return ops->ack_response(channel);
+}
- channel->ob = frame;
+static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
- return true;
+ return ops->ack_request(channel);
}
-static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
+static bool
+tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
+
+ return ops->is_request_channel_free(channel);
+}
+
+static bool
+tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
+
+ return ops->is_response_channel_free(channel);
+}
+
+static int
+tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel)
{
unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
ktime_t start, now;
@@ -149,7 +174,7 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
start = ns_to_ktime(local_clock());
do {
- if (tegra_bpmp_master_free(channel))
+ if (tegra_bpmp_is_request_channel_free(channel))
return 0;
now = ns_to_ktime(local_clock());
@@ -158,6 +183,25 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
return -ETIMEDOUT;
}
+static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
+
+ return ops->post_request(channel);
+}
+
+static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel)
+{
+ const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
+
+ return ops->post_response(channel);
+}
+
+static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
+{
+ return bpmp->soc->ops->ring_doorbell(bpmp);
+}
+
static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
void *data, size_t size, int *ret)
{
@@ -166,7 +210,7 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
if (data && size > 0)
memcpy(data, channel->ib->data, size);
- err = tegra_ivc_read_advance(channel->ivc);
+ err = tegra_bpmp_ack_response(channel);
if (err < 0)
return err;
@@ -210,7 +254,7 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
if (data && size > 0)
memcpy(channel->ob->data, data, size);
- return tegra_ivc_write_advance(channel->ivc);
+ return tegra_bpmp_post_request(channel);
}
static struct tegra_bpmp_channel *
@@ -238,7 +282,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
channel = &bpmp->threaded_channels[index];
- if (!tegra_bpmp_master_free(channel)) {
+ if (!tegra_bpmp_is_request_channel_free(channel)) {
err = -EBUSY;
goto unlock;
}
@@ -270,7 +314,7 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
{
int err;
- err = tegra_bpmp_wait_master_free(channel);
+ err = tegra_bpmp_wait_request_channel_free(channel);
if (err < 0)
return err;
@@ -302,13 +346,11 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
spin_unlock(&bpmp->atomic_tx_lock);
- err = mbox_send_message(bpmp->mbox.channel, NULL);
+ err = tegra_bpmp_ring_doorbell(bpmp);
if (err < 0)
return err;
- mbox_client_txdone(bpmp->mbox.channel, 0);
-
- err = tegra_bpmp_wait_ack(channel);
+ err = tegra_bpmp_wait_response(channel);
if (err < 0)
return err;
@@ -335,12 +377,10 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
if (IS_ERR(channel))
return PTR_ERR(channel);
- err = mbox_send_message(bpmp->mbox.channel, NULL);
+ err = tegra_bpmp_ring_doorbell(bpmp);
if (err < 0)
return err;
- mbox_client_txdone(bpmp->mbox.channel, 0);
-
timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
err = wait_for_completion_timeout(&channel->completion, timeout);
@@ -369,38 +409,34 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
{
unsigned long flags = channel->ib->flags;
struct tegra_bpmp *bpmp = channel->bpmp;
- struct tegra_bpmp_mb_data *frame;
int err;
if (WARN_ON(size > MSG_DATA_MIN_SZ))
return;
- err = tegra_ivc_read_advance(channel->ivc);
+ err = tegra_bpmp_ack_request(channel);
if (WARN_ON(err < 0))
return;
if ((flags & MSG_ACK) == 0)
return;
- frame = tegra_ivc_write_get_next_frame(channel->ivc);
- if (WARN_ON(IS_ERR(frame)))
+ if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
return;
- frame->code = code;
+ channel->ob->code = code;
if (data && size > 0)
- memcpy(frame->data, data, size);
+ memcpy(channel->ob->data, data, size);
- err = tegra_ivc_write_advance(channel->ivc);
+ err = tegra_bpmp_post_response(channel);
if (WARN_ON(err < 0))
return;
if (flags & MSG_RING) {
- err = mbox_send_message(bpmp->mbox.channel, NULL);
+ err = tegra_bpmp_ring_doorbell(bpmp);
if (WARN_ON(err < 0))
return;
-
- mbox_client_txdone(bpmp->mbox.channel, 0);
}
}
EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return);
@@ -627,9 +663,8 @@ static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
complete(&channel->completion);
}
-static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
+void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
{
- struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
struct tegra_bpmp_channel *channel;
unsigned int i, count;
unsigned long *busy;
@@ -638,7 +673,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
count = bpmp->soc->channels.thread.count;
busy = bpmp->threaded.busy;
- if (tegra_bpmp_master_acked(channel))
+ if (tegra_bpmp_is_request_ready(channel))
tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
spin_lock(&bpmp->lock);
@@ -648,7 +683,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
channel = &bpmp->threaded_channels[i];
- if (tegra_bpmp_master_acked(channel)) {
+ if (tegra_bpmp_is_response_ready(channel)) {
tegra_bpmp_channel_signal(channel);
clear_bit(i, busy);
}
@@ -657,74 +692,9 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
spin_unlock(&bpmp->lock);
}
-static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
-{
- struct tegra_bpmp *bpmp = data;
- int err;
-
- if (WARN_ON(bpmp->mbox.channel == NULL))
- return;
-
- err = mbox_send_message(bpmp->mbox.channel, NULL);
- if (err < 0)
- return;
-
- mbox_client_txdone(bpmp->mbox.channel, 0);
-}
-
-static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
- struct tegra_bpmp *bpmp,
- unsigned int index)
-{
- size_t message_size, queue_size;
- unsigned int offset;
- int err;
-
- channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
- GFP_KERNEL);
- if (!channel->ivc)
- return -ENOMEM;
-
- message_size = tegra_ivc_align(MSG_MIN_SZ);
- queue_size = tegra_ivc_total_queue_size(message_size);
- offset = queue_size * index;
-
- err = tegra_ivc_init(channel->ivc, NULL,
- bpmp->rx.virt + offset, bpmp->rx.phys + offset,
- bpmp->tx.virt + offset, bpmp->tx.phys + offset,
- 1, message_size, tegra_bpmp_ivc_notify,
- bpmp);
- if (err < 0) {
- dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
- index, err);
- return err;
- }
-
- init_completion(&channel->completion);
- channel->bpmp = bpmp;
-
- return 0;
-}
-
-static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
-{
- /* reset the channel state */
- tegra_ivc_reset(channel->ivc);
-
- /* sync the channel state with BPMP */
- while (tegra_ivc_notified(channel->ivc))
- ;
-}
-
-static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
-{
- tegra_ivc_cleanup(channel->ivc);
-}
-
static int tegra_bpmp_probe(struct platform_device *pdev)
{
struct tegra_bpmp *bpmp;
- unsigned int i;
char tag[TAG_SZ];
size_t size;
int err;
@@ -736,32 +706,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
bpmp->soc = of_device_get_match_data(&pdev->dev);
bpmp->dev = &pdev->dev;
- bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
- if (!bpmp->tx.pool) {
- dev_err(&pdev->dev, "TX shmem pool not found\n");
- return -ENOMEM;
- }
-
- bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
- if (!bpmp->tx.virt) {
- dev_err(&pdev->dev, "failed to allocate from TX pool\n");
- return -ENOMEM;
- }
-
- bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
- if (!bpmp->rx.pool) {
- dev_err(&pdev->dev, "RX shmem pool not found\n");
- err = -ENOMEM;
- goto free_tx;
- }
-
- bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
- if (!bpmp->rx.virt) {
- dev_err(&pdev->dev, "failed to allocate from RX pool\n");
- err = -ENOMEM;
- goto free_tx;
- }
-
INIT_LIST_HEAD(&bpmp->mrqs);
spin_lock_init(&bpmp->lock);
@@ -771,81 +715,38 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
- if (!bpmp->threaded.allocated) {
- err = -ENOMEM;
- goto free_rx;
- }
+ if (!bpmp->threaded.allocated)
+ return -ENOMEM;
bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
- if (!bpmp->threaded.busy) {
- err = -ENOMEM;
- goto free_rx;
- }
+ if (!bpmp->threaded.busy)
+ return -ENOMEM;
spin_lock_init(&bpmp->atomic_tx_lock);
bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
GFP_KERNEL);
- if (!bpmp->tx_channel) {
- err = -ENOMEM;
- goto free_rx;
- }
+ if (!bpmp->tx_channel)
+ return -ENOMEM;
bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
GFP_KERNEL);
- if (!bpmp->rx_channel) {
- err = -ENOMEM;
- goto free_rx;
- }
+ if (!bpmp->rx_channel)
+ return -ENOMEM;
bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
sizeof(*bpmp->threaded_channels),
GFP_KERNEL);
- if (!bpmp->threaded_channels) {
- err = -ENOMEM;
- goto free_rx;
- }
-
- err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
- bpmp->soc->channels.cpu_tx.offset);
- if (err < 0)
- goto free_rx;
+ if (!bpmp->threaded_channels)
+ return -ENOMEM;
- err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp,
- bpmp->soc->channels.cpu_rx.offset);
+ err = bpmp->soc->ops->init(bpmp);
if (err < 0)
- goto cleanup_tx_channel;
-
- for (i = 0; i < bpmp->threaded.count; i++) {
- err = tegra_bpmp_channel_init(
- &bpmp->threaded_channels[i], bpmp,
- bpmp->soc->channels.thread.offset + i);
- if (err < 0)
- goto cleanup_threaded_channels;
- }
-
- /* mbox registration */
- bpmp->mbox.client.dev = &pdev->dev;
- bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
- bpmp->mbox.client.tx_block = false;
- bpmp->mbox.client.knows_txdone = false;
-
- bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
- if (IS_ERR(bpmp->mbox.channel)) {
- err = PTR_ERR(bpmp->mbox.channel);
- dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
- goto cleanup_threaded_channels;
- }
-
- /* reset message channels */
- tegra_bpmp_channel_reset(bpmp->tx_channel);
- tegra_bpmp_channel_reset(bpmp->rx_channel);
- for (i = 0; i < bpmp->threaded.count; i++)
- tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+ return err;
err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
tegra_bpmp_mrq_handle_ping, bpmp);
if (err < 0)
- goto free_mbox;
+ goto deinit;
err = tegra_bpmp_ping(bpmp);
if (err < 0) {
@@ -867,17 +768,23 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
if (err < 0)
goto free_mrq;
- err = tegra_bpmp_init_clocks(bpmp);
- if (err < 0)
- goto free_mrq;
+ if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
+ err = tegra_bpmp_init_clocks(bpmp);
+ if (err < 0)
+ goto free_mrq;
+ }
- err = tegra_bpmp_init_resets(bpmp);
- if (err < 0)
- goto free_mrq;
+ if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
+ err = tegra_bpmp_init_resets(bpmp);
+ if (err < 0)
+ goto free_mrq;
+ }
- err = tegra_bpmp_init_powergates(bpmp);
- if (err < 0)
- goto free_mrq;
+ if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
+ err = tegra_bpmp_init_powergates(bpmp);
+ if (err < 0)
+ goto free_mrq;
+ }
err = tegra_bpmp_init_debugfs(bpmp);
if (err < 0)
@@ -887,41 +794,27 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
free_mrq:
tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
-free_mbox:
- mbox_free_channel(bpmp->mbox.channel);
-cleanup_threaded_channels:
- for (i = 0; i < bpmp->threaded.count; i++) {
- if (bpmp->threaded_channels[i].bpmp)
- tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
- }
+deinit:
+ if (bpmp->soc->ops->deinit)
+ bpmp->soc->ops->deinit(bpmp);
- tegra_bpmp_channel_cleanup(bpmp->rx_channel);
-cleanup_tx_channel:
- tegra_bpmp_channel_cleanup(bpmp->tx_channel);
-free_rx:
- gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
-free_tx:
- gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
return err;
}
static int __maybe_unused tegra_bpmp_resume(struct device *dev)
{
struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
- unsigned int i;
-
- /* reset message channels */
- tegra_bpmp_channel_reset(bpmp->tx_channel);
- tegra_bpmp_channel_reset(bpmp->rx_channel);
-
- for (i = 0; i < bpmp->threaded.count; i++)
- tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
- return 0;
+ if (bpmp->soc->ops->resume)
+ return bpmp->soc->ops->resume(bpmp);
+ else
+ return 0;
}
static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume);
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
+ IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
static const struct tegra_bpmp_soc tegra186_soc = {
.channels = {
.cpu_tx = {
@@ -938,11 +831,42 @@ static const struct tegra_bpmp_soc tegra186_soc = {
.timeout = 0,
},
},
+ .ops = &tegra186_bpmp_ops,
.num_resets = 193,
};
+#endif
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
+static const struct tegra_bpmp_soc tegra210_soc = {
+ .channels = {
+ .cpu_tx = {
+ .offset = 0,
+ .count = 1,
+ .timeout = 60 * USEC_PER_SEC,
+ },
+ .thread = {
+ .offset = 4,
+ .count = 1,
+ .timeout = 600 * USEC_PER_SEC,
+ },
+ .cpu_rx = {
+ .offset = 8,
+ .count = 1,
+ .timeout = 0,
+ },
+ },
+ .ops = &tegra210_bpmp_ops,
+};
+#endif
static const struct of_device_id tegra_bpmp_match[] = {
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
+ IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
{ .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
+#endif
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
+ { .compatible = "nvidia,tegra210-bpmp", .data = &tegra210_soc },
+#endif
{ }
};
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 69ed1464175c..3fbbb61012c4 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -146,25 +146,8 @@ static int ti_sci_debug_show(struct seq_file *s, void *unused)
return 0;
}
-/**
- * ti_sci_debug_open() - debug file open
- * @inode: inode pointer
- * @file: file pointer
- *
- * Return: result of single_open
- */
-static int ti_sci_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ti_sci_debug_show, inode->i_private);
-}
-
-/* log file operations */
-static const struct file_operations ti_sci_debug_fops = {
- .open = ti_sci_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+/* Provide the log file operations interface*/
+DEFINE_SHOW_ATTRIBUTE(ti_sci_debug);
/**
* ti_sci_debugfs_create() - Create log debug file
diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig
index 8f44b9cd295a..bd33bbf70daf 100644
--- a/drivers/firmware/xilinx/Kconfig
+++ b/drivers/firmware/xilinx/Kconfig
@@ -6,6 +6,7 @@ menu "Zynq MPSoC Firmware Drivers"
config ZYNQMP_FIRMWARE
bool "Enable Xilinx Zynq MPSoC firmware interface"
+ select MFD_CORE
help
Firmware interface driver is used by different
drivers to communicate with the firmware for
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 9a1c72a9280f..98f936125643 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -14,6 +14,7 @@
#include <linux/compiler.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -23,6 +24,12 @@
#include <linux/firmware/xlnx-zynqmp.h>
#include "zynqmp-debug.h"
+static const struct mfd_cell firmware_devs[] = {
+ {
+ .name = "zynqmp_power_controller",
+ },
+};
+
/**
* zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
* @ret_status: PMUFW return code
@@ -187,6 +194,29 @@ static int zynqmp_pm_get_api_version(u32 *version)
}
/**
+ * zynqmp_pm_get_chipid - Get silicon ID registers
+ * @idcode: IDCODE register
+ * @version: version register
+ *
+ * Return: Returns the status of the operation and the idcode and version
+ * registers in @idcode and @version.
+ */
+static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
+{
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (!idcode || !version)
+ return -EINVAL;
+
+ ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+ *idcode = ret_payload[1];
+ *version = ret_payload[2];
+
+ return ret;
+}
+
+/**
* zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
* @version: Returned version value
*
@@ -469,8 +499,129 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
arg1, arg2, out);
}
+/**
+ * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
+ * @reset: Reset to be configured
+ * @assert_flag: Flag stating should reset be asserted (1) or
+ * released (0)
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
+ const enum zynqmp_pm_reset_action assert_flag)
+{
+ return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
+ 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_reset_get_status - Get status of the reset
+ * @reset: Reset whose status should be returned
+ * @status: Returned status
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
+ u32 *status)
+{
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (!status)
+ return -EINVAL;
+
+ ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
+ 0, 0, ret_payload);
+ *status = ret_payload[1];
+
+ return ret;
+}
+
+/**
+ * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
+ * master has initialized its own power management
+ *
+ * This API function is to be used for notify the power management controller
+ * about the completed power management initialization.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_init_finalize(void)
+{
+ return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_suspend_mode() - Set system suspend mode
+ * @mode: Mode to set for system suspend
+ *
+ * This API function is used to set mode of system suspend.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_suspend_mode(u32 mode)
+{
+ return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_request_node() - Request a node with specific capabilities
+ * @node: Node ID of the slave
+ * @capabilities: Requested capabilities of the slave
+ * @qos: Quality of service (not supported)
+ * @ack: Flag to specify whether acknowledge is requested
+ *
+ * This function is used by master to request particular node from firmware.
+ * Every master must request node before using it.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
+ const u32 qos,
+ const enum zynqmp_pm_request_ack ack)
+{
+ return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
+ qos, ack, NULL);
+}
+
+/**
+ * zynqmp_pm_release_node() - Release a node
+ * @node: Node ID of the slave
+ *
+ * This function is used by master to inform firmware that master
+ * has released node. Once released, master must not use that node
+ * without re-request.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_release_node(const u32 node)
+{
+ return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
+ * @node: Node ID of the slave
+ * @capabilities: Requested capabilities of the slave
+ * @qos: Quality of service (not supported)
+ * @ack: Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ * to change its capabilities.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
+ const u32 qos,
+ const enum zynqmp_pm_request_ack ack)
+{
+ return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
+ qos, ack, NULL);
+}
+
static const struct zynqmp_eemi_ops eemi_ops = {
.get_api_version = zynqmp_pm_get_api_version,
+ .get_chipid = zynqmp_pm_get_chipid,
.query_data = zynqmp_pm_query_data,
.clock_enable = zynqmp_pm_clock_enable,
.clock_disable = zynqmp_pm_clock_disable,
@@ -482,6 +633,13 @@ static const struct zynqmp_eemi_ops eemi_ops = {
.clock_setparent = zynqmp_pm_clock_setparent,
.clock_getparent = zynqmp_pm_clock_getparent,
.ioctl = zynqmp_pm_ioctl,
+ .reset_assert = zynqmp_pm_reset_assert,
+ .reset_get_status = zynqmp_pm_reset_get_status,
+ .init_finalize = zynqmp_pm_init_finalize,
+ .set_suspend_mode = zynqmp_pm_set_suspend_mode,
+ .request_node = zynqmp_pm_request_node,
+ .release_node = zynqmp_pm_release_node,
+ .set_requirement = zynqmp_pm_set_requirement,
};
/**
@@ -538,11 +696,19 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
zynqmp_pm_api_debugfs_init();
+ ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
+ ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
+ return ret;
+ }
+
return of_platform_populate(dev->of_node, NULL, NULL, dev);
}
static int zynqmp_firmware_remove(struct platform_device *pdev)
{
+ mfd_remove_devices(&pdev->dev);
zynqmp_pm_api_debugfs_exit();
return 0;
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 0bb7b5cd6cdc..c20445b867ae 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -104,7 +104,7 @@ config SOCFPGA_FPGA_BRIDGE
config ALTERA_FREEZE_BRIDGE
tristate "Altera FPGA Freeze Bridge"
- depends on ARCH_SOCFPGA && FPGA_BRIDGE
+ depends on FPGA_BRIDGE && HAS_IOMEM
help
Say Y to enable drivers for Altera FPGA Freeze bridges. A
freeze bridge is a bridge that exists in the FPGA fabric to
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c
index 8c18beec6b57..678d0115f840 100644
--- a/drivers/fpga/altera-ps-spi.c
+++ b/drivers/fpga/altera-ps-spi.c
@@ -205,7 +205,7 @@ static int altera_ps_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
{
struct altera_ps_conf *conf = mgr->priv;
- const char dummy[] = {0};
+ static const char dummy[] = {0};
int ret;
if (gpiod_get_value_cansleep(conf->status)) {
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
index a1a09e04fab8..13851b3d1c56 100644
--- a/drivers/fpga/stratix10-soc.c
+++ b/drivers/fpga/stratix10-soc.c
@@ -508,14 +508,11 @@ static int __init s10_init(void)
return -ENODEV;
np = of_find_matching_node(fw_np, s10_of_match);
- if (!np) {
- of_node_put(fw_np);
+ if (!np)
return -ENODEV;
- }
of_node_put(np);
ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
- of_node_put(fw_np);
if (ret)
return ret;
diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig
index 6abc88514512..6d8c8027e1cd 100644
--- a/drivers/gnss/Kconfig
+++ b/drivers/gnss/Kconfig
@@ -15,6 +15,19 @@ if GNSS
config GNSS_SERIAL
tristate
+config GNSS_MTK_SERIAL
+ tristate "Mediatek GNSS receiver support"
+ depends on SERIAL_DEV_BUS
+ select GNSS_SERIAL
+ help
+ Say Y here if you have a Mediatek-based GNSS receiver which uses a
+ serial interface.
+
+ To compile this driver as a module, choose M here: the module will
+ be called gnss-mtk.
+
+ If unsure, say N.
+
config GNSS_SIRF_SERIAL
tristate "SiRFstar GNSS receiver support"
depends on SERIAL_DEV_BUS
diff --git a/drivers/gnss/Makefile b/drivers/gnss/Makefile
index 5cf0ebe0330a..451f11401ecc 100644
--- a/drivers/gnss/Makefile
+++ b/drivers/gnss/Makefile
@@ -9,6 +9,9 @@ gnss-y := core.o
obj-$(CONFIG_GNSS_SERIAL) += gnss-serial.o
gnss-serial-y := serial.o
+obj-$(CONFIG_GNSS_MTK_SERIAL) += gnss-mtk.o
+gnss-mtk-y := mtk.o
+
obj-$(CONFIG_GNSS_SIRF_SERIAL) += gnss-sirf.o
gnss-sirf-y := sirf.o
diff --git a/drivers/gnss/core.c b/drivers/gnss/core.c
index 4291a0dd22aa..320cfca80d5f 100644
--- a/drivers/gnss/core.c
+++ b/drivers/gnss/core.c
@@ -334,6 +334,7 @@ static const char * const gnss_type_names[GNSS_TYPE_COUNT] = {
[GNSS_TYPE_NMEA] = "NMEA",
[GNSS_TYPE_SIRF] = "SiRF",
[GNSS_TYPE_UBX] = "UBX",
+ [GNSS_TYPE_MTK] = "MTK",
};
static const char *gnss_type_name(struct gnss_device *gdev)
diff --git a/drivers/gnss/mtk.c b/drivers/gnss/mtk.c
new file mode 100644
index 000000000000..d1fc55560daf
--- /dev/null
+++ b/drivers/gnss/mtk.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek GNSS receiver driver
+ *
+ * Copyright (C) 2018 Johan Hovold <johan@kernel.org>
+ */
+
+#include <linux/errno.h>
+#include <linux/gnss.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/serdev.h>
+
+#include "serial.h"
+
+struct mtk_data {
+ struct regulator *vbackup;
+ struct regulator *vcc;
+};
+
+static int mtk_set_active(struct gnss_serial *gserial)
+{
+ struct mtk_data *data = gnss_serial_get_drvdata(gserial);
+ int ret;
+
+ ret = regulator_enable(data->vcc);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mtk_set_standby(struct gnss_serial *gserial)
+{
+ struct mtk_data *data = gnss_serial_get_drvdata(gserial);
+ int ret;
+
+ ret = regulator_disable(data->vcc);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mtk_set_power(struct gnss_serial *gserial,
+ enum gnss_serial_pm_state state)
+{
+ switch (state) {
+ case GNSS_SERIAL_ACTIVE:
+ return mtk_set_active(gserial);
+ case GNSS_SERIAL_OFF:
+ case GNSS_SERIAL_STANDBY:
+ return mtk_set_standby(gserial);
+ }
+
+ return -EINVAL;
+}
+
+static const struct gnss_serial_ops mtk_gserial_ops = {
+ .set_power = mtk_set_power,
+};
+
+static int mtk_probe(struct serdev_device *serdev)
+{
+ struct gnss_serial *gserial;
+ struct mtk_data *data;
+ int ret;
+
+ gserial = gnss_serial_allocate(serdev, sizeof(*data));
+ if (IS_ERR(gserial)) {
+ ret = PTR_ERR(gserial);
+ return ret;
+ }
+
+ gserial->ops = &mtk_gserial_ops;
+
+ gserial->gdev->type = GNSS_TYPE_MTK;
+
+ data = gnss_serial_get_drvdata(gserial);
+
+ data->vcc = devm_regulator_get(&serdev->dev, "vcc");
+ if (IS_ERR(data->vcc)) {
+ ret = PTR_ERR(data->vcc);
+ goto err_free_gserial;
+ }
+
+ data->vbackup = devm_regulator_get_optional(&serdev->dev, "vbackup");
+ if (IS_ERR(data->vbackup)) {
+ ret = PTR_ERR(data->vbackup);
+ if (ret == -ENODEV)
+ data->vbackup = NULL;
+ else
+ goto err_free_gserial;
+ }
+
+ if (data->vbackup) {
+ ret = regulator_enable(data->vbackup);
+ if (ret)
+ goto err_free_gserial;
+ }
+
+ ret = gnss_serial_register(gserial);
+ if (ret)
+ goto err_disable_vbackup;
+
+ return 0;
+
+err_disable_vbackup:
+ if (data->vbackup)
+ regulator_disable(data->vbackup);
+err_free_gserial:
+ gnss_serial_free(gserial);
+
+ return ret;
+}
+
+static void mtk_remove(struct serdev_device *serdev)
+{
+ struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
+ struct mtk_data *data = gnss_serial_get_drvdata(gserial);
+
+ gnss_serial_deregister(gserial);
+ if (data->vbackup)
+ regulator_disable(data->vbackup);
+ gnss_serial_free(gserial);
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id mtk_of_match[] = {
+ { .compatible = "globaltop,pa6h" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_of_match);
+#endif
+
+static struct serdev_device_driver mtk_driver = {
+ .driver = {
+ .name = "gnss-mtk",
+ .of_match_table = of_match_ptr(mtk_of_match),
+ .pm = &gnss_serial_pm_ops,
+ },
+ .probe = mtk_probe,
+ .remove = mtk_remove,
+};
+module_serdev_device_driver(mtk_driver);
+
+MODULE_AUTHOR("Loys Ollivier <lollivier@baylibre.com>");
+MODULE_DESCRIPTION("Mediatek GNSS receiver driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c
index 226f6e6fe01b..effed3a8d398 100644
--- a/drivers/gnss/sirf.c
+++ b/drivers/gnss/sirf.c
@@ -25,31 +25,83 @@
#define SIRF_ON_OFF_PULSE_TIME 100
#define SIRF_ACTIVATE_TIMEOUT 200
#define SIRF_HIBERNATE_TIMEOUT 200
+/*
+ * If no data arrives for this time, we assume that the chip is off.
+ * REVISIT: The report cycle is configurable and can be several minutes long,
+ * so this will only work reliably if the report cycle is set to a reasonable
+ * low value. Also power saving settings (like send data only on movement)
+ * might things work even worse.
+ * Workaround might be to parse shutdown or bootup messages.
+ */
+#define SIRF_REPORT_CYCLE 2000
struct sirf_data {
struct gnss_device *gdev;
struct serdev_device *serdev;
speed_t speed;
struct regulator *vcc;
+ struct regulator *lna;
struct gpio_desc *on_off;
struct gpio_desc *wakeup;
int irq;
bool active;
+
+ struct mutex gdev_mutex;
+ bool open;
+
+ struct mutex serdev_mutex;
+ int serdev_count;
+
wait_queue_head_t power_wait;
};
+static int sirf_serdev_open(struct sirf_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->serdev_mutex);
+ if (++data->serdev_count == 1) {
+ ret = serdev_device_open(data->serdev);
+ if (ret) {
+ data->serdev_count--;
+ goto out_unlock;
+ }
+
+ serdev_device_set_baudrate(data->serdev, data->speed);
+ serdev_device_set_flow_control(data->serdev, false);
+ }
+
+out_unlock:
+ mutex_unlock(&data->serdev_mutex);
+
+ return ret;
+}
+
+static void sirf_serdev_close(struct sirf_data *data)
+{
+ mutex_lock(&data->serdev_mutex);
+ if (--data->serdev_count == 0)
+ serdev_device_close(data->serdev);
+ mutex_unlock(&data->serdev_mutex);
+}
+
static int sirf_open(struct gnss_device *gdev)
{
struct sirf_data *data = gnss_get_drvdata(gdev);
struct serdev_device *serdev = data->serdev;
int ret;
- ret = serdev_device_open(serdev);
- if (ret)
- return ret;
+ mutex_lock(&data->gdev_mutex);
+ data->open = true;
+ mutex_unlock(&data->gdev_mutex);
- serdev_device_set_baudrate(serdev, data->speed);
- serdev_device_set_flow_control(serdev, false);
+ ret = sirf_serdev_open(data);
+ if (ret) {
+ mutex_lock(&data->gdev_mutex);
+ data->open = false;
+ mutex_unlock(&data->gdev_mutex);
+ return ret;
+ }
ret = pm_runtime_get_sync(&serdev->dev);
if (ret < 0) {
@@ -61,7 +113,11 @@ static int sirf_open(struct gnss_device *gdev)
return 0;
err_close:
- serdev_device_close(serdev);
+ sirf_serdev_close(data);
+
+ mutex_lock(&data->gdev_mutex);
+ data->open = false;
+ mutex_unlock(&data->gdev_mutex);
return ret;
}
@@ -71,9 +127,13 @@ static void sirf_close(struct gnss_device *gdev)
struct sirf_data *data = gnss_get_drvdata(gdev);
struct serdev_device *serdev = data->serdev;
- serdev_device_close(serdev);
+ sirf_serdev_close(data);
pm_runtime_put(&serdev->dev);
+
+ mutex_lock(&data->gdev_mutex);
+ data->open = false;
+ mutex_unlock(&data->gdev_mutex);
}
static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,
@@ -105,8 +165,19 @@ static int sirf_receive_buf(struct serdev_device *serdev,
{
struct sirf_data *data = serdev_device_get_drvdata(serdev);
struct gnss_device *gdev = data->gdev;
+ int ret = 0;
+
+ if (!data->wakeup && !data->active) {
+ data->active = true;
+ wake_up_interruptible(&data->power_wait);
+ }
+
+ mutex_lock(&data->gdev_mutex);
+ if (data->open)
+ ret = gnss_insert_raw(gdev, buf, count);
+ mutex_unlock(&data->gdev_mutex);
- return gnss_insert_raw(gdev, buf, count);
+ return ret;
}
static const struct serdev_device_ops sirf_serdev_ops = {
@@ -125,17 +196,45 @@ static irqreturn_t sirf_wakeup_handler(int irq, void *dev_id)
if (ret < 0)
goto out;
- data->active = !!ret;
+ data->active = ret;
wake_up_interruptible(&data->power_wait);
out:
return IRQ_HANDLED;
}
+static int sirf_wait_for_power_state_nowakeup(struct sirf_data *data,
+ bool active,
+ unsigned long timeout)
+{
+ int ret;
+
+ /* Wait for state change (including any shutdown messages). */
+ msleep(timeout);
+
+ /* Wait for data reception or timeout. */
+ data->active = false;
+ ret = wait_event_interruptible_timeout(data->power_wait,
+ data->active, msecs_to_jiffies(SIRF_REPORT_CYCLE));
+ if (ret < 0)
+ return ret;
+
+ if (ret > 0 && !active)
+ return -ETIMEDOUT;
+
+ if (ret == 0 && active)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
static int sirf_wait_for_power_state(struct sirf_data *data, bool active,
unsigned long timeout)
{
int ret;
+ if (!data->wakeup)
+ return sirf_wait_for_power_state_nowakeup(data, active, timeout);
+
ret = wait_event_interruptible_timeout(data->power_wait,
data->active == active, msecs_to_jiffies(timeout));
if (ret < 0)
@@ -168,21 +267,22 @@ static int sirf_set_active(struct sirf_data *data, bool active)
else
timeout = SIRF_HIBERNATE_TIMEOUT;
+ if (!data->wakeup) {
+ ret = sirf_serdev_open(data);
+ if (ret)
+ return ret;
+ }
+
do {
sirf_pulse_on_off(data);
ret = sirf_wait_for_power_state(data, active, timeout);
- if (ret < 0) {
- if (ret == -ETIMEDOUT)
- continue;
+ } while (ret == -ETIMEDOUT && retries--);
- return ret;
- }
+ if (!data->wakeup)
+ sirf_serdev_close(data);
- break;
- } while (retries--);
-
- if (retries < 0)
- return -ETIMEDOUT;
+ if (ret)
+ return ret;
return 0;
}
@@ -190,21 +290,60 @@ static int sirf_set_active(struct sirf_data *data, bool active)
static int sirf_runtime_suspend(struct device *dev)
{
struct sirf_data *data = dev_get_drvdata(dev);
+ int ret2;
+ int ret;
- if (!data->on_off)
- return regulator_disable(data->vcc);
+ if (data->on_off)
+ ret = sirf_set_active(data, false);
+ else
+ ret = regulator_disable(data->vcc);
+
+ if (ret)
+ return ret;
+
+ ret = regulator_disable(data->lna);
+ if (ret)
+ goto err_reenable;
- return sirf_set_active(data, false);
+ return 0;
+
+err_reenable:
+ if (data->on_off)
+ ret2 = sirf_set_active(data, true);
+ else
+ ret2 = regulator_enable(data->vcc);
+
+ if (ret2)
+ dev_err(dev,
+ "failed to reenable power on failed suspend: %d\n",
+ ret2);
+
+ return ret;
}
static int sirf_runtime_resume(struct device *dev)
{
struct sirf_data *data = dev_get_drvdata(dev);
+ int ret;
- if (!data->on_off)
- return regulator_enable(data->vcc);
+ ret = regulator_enable(data->lna);
+ if (ret)
+ return ret;
+
+ if (data->on_off)
+ ret = sirf_set_active(data, true);
+ else
+ ret = regulator_enable(data->vcc);
+
+ if (ret)
+ goto err_disable_lna;
+
+ return 0;
+
+err_disable_lna:
+ regulator_disable(data->lna);
- return sirf_set_active(data, true);
+ return ret;
}
static int __maybe_unused sirf_suspend(struct device *dev)
@@ -275,6 +414,8 @@ static int sirf_probe(struct serdev_device *serdev)
data->serdev = serdev;
data->gdev = gdev;
+ mutex_init(&data->gdev_mutex);
+ mutex_init(&data->serdev_mutex);
init_waitqueue_head(&data->power_wait);
serdev_device_set_drvdata(serdev, data);
@@ -290,6 +431,12 @@ static int sirf_probe(struct serdev_device *serdev)
goto err_put_device;
}
+ data->lna = devm_regulator_get(dev, "lna");
+ if (IS_ERR(data->lna)) {
+ ret = PTR_ERR(data->lna);
+ goto err_put_device;
+ }
+
data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
GPIOD_OUT_LOW);
if (IS_ERR(data->on_off))
@@ -301,39 +448,53 @@ static int sirf_probe(struct serdev_device *serdev)
if (IS_ERR(data->wakeup))
goto err_put_device;
- /*
- * Configurations where WAKEUP has been left not connected,
- * are currently not supported.
- */
- if (!data->wakeup) {
- dev_err(dev, "no wakeup gpio specified\n");
- ret = -ENODEV;
+ ret = regulator_enable(data->vcc);
+ if (ret)
goto err_put_device;
- }
+
+ /* Wait for chip to boot into hibernate mode. */
+ msleep(SIRF_BOOT_DELAY);
}
if (data->wakeup) {
- ret = gpiod_to_irq(data->wakeup);
+ ret = gpiod_get_value_cansleep(data->wakeup);
if (ret < 0)
- goto err_put_device;
+ goto err_disable_vcc;
+ data->active = ret;
+ ret = gpiod_to_irq(data->wakeup);
+ if (ret < 0)
+ goto err_disable_vcc;
data->irq = ret;
- ret = devm_request_threaded_irq(dev, data->irq, NULL,
- sirf_wakeup_handler,
+ ret = request_threaded_irq(data->irq, NULL, sirf_wakeup_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"wakeup", data);
if (ret)
- goto err_put_device;
+ goto err_disable_vcc;
}
if (data->on_off) {
- ret = regulator_enable(data->vcc);
- if (ret)
- goto err_put_device;
+ if (!data->wakeup) {
+ data->active = false;
- /* Wait for chip to boot into hibernate mode */
- msleep(SIRF_BOOT_DELAY);
+ ret = sirf_serdev_open(data);
+ if (ret)
+ goto err_disable_vcc;
+
+ msleep(SIRF_REPORT_CYCLE);
+ sirf_serdev_close(data);
+ }
+
+ /* Force hibernate mode if already active. */
+ if (data->active) {
+ ret = sirf_set_active(data, false);
+ if (ret) {
+ dev_err(dev, "failed to set hibernate mode: %d\n",
+ ret);
+ goto err_free_irq;
+ }
+ }
}
if (IS_ENABLED(CONFIG_PM)) {
@@ -342,7 +503,7 @@ static int sirf_probe(struct serdev_device *serdev)
} else {
ret = sirf_runtime_resume(dev);
if (ret < 0)
- goto err_disable_vcc;
+ goto err_free_irq;
}
ret = gnss_register_device(gdev);
@@ -356,6 +517,9 @@ err_disable_rpm:
pm_runtime_disable(dev);
else
sirf_runtime_suspend(dev);
+err_free_irq:
+ if (data->wakeup)
+ free_irq(data->irq, data);
err_disable_vcc:
if (data->on_off)
regulator_disable(data->vcc);
@@ -376,6 +540,9 @@ static void sirf_remove(struct serdev_device *serdev)
else
sirf_runtime_suspend(&serdev->dev);
+ if (data->wakeup)
+ free_irq(data->irq, data);
+
if (data->on_off)
regulator_disable(data->vcc);
@@ -386,6 +553,7 @@ static void sirf_remove(struct serdev_device *serdev)
static const struct of_device_id sirf_of_match[] = {
{ .compatible = "fastrax,uc430" },
{ .compatible = "linx,r4" },
+ { .compatible = "wi2wi,w2sg0004" },
{ .compatible = "wi2wi,w2sg0008i" },
{ .compatible = "wi2wi,w2sg0084i" },
{},
diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c
index 6b11f1314248..7f9e0304b510 100644
--- a/drivers/gpio/gpio-altera-a10sr.c
+++ b/drivers/gpio/gpio-altera-a10sr.c
@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
unsigned int nr, int value)
{
- if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+ if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
+ altr_a10sr_gpio_set(gc, nr, value);
return 0;
+ }
return -EINVAL;
}
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
index e0d6a0a7bc69..e41223c05f6e 100644
--- a/drivers/gpio/gpio-eic-sprd.c
+++ b/drivers/gpio/gpio-eic-sprd.c
@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
{
- return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+ struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+
+ switch (sprd_eic->type) {
+ case SPRD_EIC_DEBOUNCE:
+ return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+ case SPRD_EIC_ASYNC:
+ return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
+ case SPRD_EIC_SYNC:
+ return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
+ default:
+ return -ENOTSUPP;
+ }
}
static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
irq_set_handler_locked(data, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_BOTH:
+ sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
irq_set_handler_locked(data, handle_edge_irq);
break;
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index 00e954f22bc9..74401e0adb29 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -30,6 +30,7 @@
#define GPIO_REG_EDGE 0xA0
struct mtk_gc {
+ struct irq_chip irq_chip;
struct gpio_chip chip;
spinlock_t lock;
int bank;
@@ -189,13 +190,6 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
return 0;
}
-static struct irq_chip mediatek_gpio_irq_chip = {
- .irq_unmask = mediatek_gpio_irq_unmask,
- .irq_mask = mediatek_gpio_irq_mask,
- .irq_mask_ack = mediatek_gpio_irq_mask,
- .irq_set_type = mediatek_gpio_irq_type,
-};
-
static int
mediatek_gpio_xlate(struct gpio_chip *chip,
const struct of_phandle_args *spec, u32 *flags)
@@ -254,6 +248,13 @@ mediatek_gpio_bank_probe(struct device *dev,
return ret;
}
+ rg->irq_chip.name = dev_name(dev);
+ rg->irq_chip.parent_device = dev;
+ rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
+ rg->irq_chip.irq_mask = mediatek_gpio_irq_mask;
+ rg->irq_chip.irq_mask_ack = mediatek_gpio_irq_mask;
+ rg->irq_chip.irq_set_type = mediatek_gpio_irq_type;
+
if (mtk->gpio_irq) {
/*
* Manually request the irq here instead of passing
@@ -270,14 +271,14 @@ mediatek_gpio_bank_probe(struct device *dev,
return ret;
}
- ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip,
+ ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip,
0, handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "failed to add gpiochip_irqchip\n");
return ret;
}
- gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip,
+ gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip,
mtk->gpio_irq, NULL);
}
@@ -310,7 +311,6 @@ mediatek_gpio_probe(struct platform_device *pdev)
mtk->gpio_irq = irq_of_parse_and_map(np, 0);
mtk->dev = dev;
platform_set_drvdata(pdev, mtk);
- mediatek_gpio_irq_chip.name = dev_name(dev);
for (i = 0; i < MTK_BANK_CNT; i++) {
ret = mediatek_gpio_bank_probe(dev, np, i);
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 83617fdc661d..0dc96419efe3 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -289,7 +289,7 @@ static bool pca953x_volatile_register(struct device *dev, unsigned int reg)
return pca953x_check_register(chip, reg, bank);
}
-const struct regmap_config pca953x_i2c_regmap = {
+static const struct regmap_config pca953x_i2c_regmap = {
.reg_bits = 8,
.val_bits = 8,
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index adf72dda25a2..68a35b65925a 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
*/
struct pcf857x {
struct gpio_chip chip;
+ struct irq_chip irqchip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
unsigned out; /* software latch */
@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
mutex_unlock(&gpio->lock);
}
-static struct irq_chip pcf857x_irq_chip = {
- .name = "pcf857x",
- .irq_enable = pcf857x_irq_enable,
- .irq_disable = pcf857x_irq_disable,
- .irq_ack = noop,
- .irq_mask = noop,
- .irq_unmask = noop,
- .irq_set_wake = pcf857x_irq_set_wake,
- .irq_bus_lock = pcf857x_irq_bus_lock,
- .irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
-};
-
/*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client,
@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
/* Enable irqchip if we have an interrupt */
if (client->irq) {
+ gpio->irqchip.name = "pcf857x",
+ gpio->irqchip.irq_enable = pcf857x_irq_enable,
+ gpio->irqchip.irq_disable = pcf857x_irq_disable,
+ gpio->irqchip.irq_ack = noop,
+ gpio->irqchip.irq_mask = noop,
+ gpio->irqchip.irq_unmask = noop,
+ gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
+ gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
+ gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
status = gpiochip_irqchip_add_nested(&gpio->chip,
- &pcf857x_irq_chip,
+ &gpio->irqchip,
0, handle_level_irq,
IRQ_TYPE_NONE);
if (status) {
@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
if (status)
goto fail;
- gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+ gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
client->irq);
gpio->irq_parent = client->irq;
}
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index e9600b556f39..bcc6be4a5cb2 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -245,6 +245,7 @@ static bool pxa_gpio_has_pinctrl(void)
{
switch (gpio_type) {
case PXA3XX_GPIO:
+ case MMP2_GPIO:
return false;
default:
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 1b79ebcfce3e..541fa6ac399d 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
struct vf610_gpio_port *port;
struct resource *iores;
struct gpio_chip *gc;
+ int i;
int ret;
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ /* Mask all GPIO interrupts */
+ for (i = 0; i < gc->ngpio; i++)
+ vf610_gpio_writel(0, port->base + PORT_PCR(i));
+
/* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR);
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 48534bda73d3..3e8e2d3ce7a8 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -357,8 +357,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
- struct gpio_desc *desc;
-
if (event->irq_requested) {
if (event->irq_is_wake)
disable_irq_wake(event->irq);
@@ -366,11 +364,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
free_irq(event->irq, event);
}
- desc = event->desc;
- if (WARN_ON(IS_ERR(desc)))
- continue;
gpiochip_unlock_as_irq(chip, event->pin);
- gpiochip_free_own_desc(desc);
+ gpiochip_free_own_desc(event->desc);
list_del(&event->node);
kfree(event);
}
@@ -535,17 +530,24 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
return 1;
- if (lookup->n++ == lookup->index && !lookup->desc) {
+ if (!lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
- int pin_index = lookup->pin_index;
+ bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
+ int pin_index;
+
+ if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
+ lookup->index++;
+
+ if (lookup->n++ != lookup->index)
+ return 1;
+ pin_index = lookup->pin_index;
if (pin_index >= agpio->pin_table_length)
return 1;
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]);
- lookup->info.gpioint =
- agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
+ lookup->info.gpioint = gpioint;
/*
* Polarity and triggering are only specified for GpioInt
@@ -897,7 +899,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
* event but only if the access here is ACPI_READ. In that
* case we "borrow" the event GPIO instead.
*/
- if (!found && agpio->sharable == ACPI_SHARED &&
+ if (!found && agpio->shareable == ACPI_SHARED &&
function == ACPI_READ) {
struct acpi_gpio_event *event;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index a6e1891217e2..c34eb9d9c59a 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -125,7 +125,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
for_each_child_of_node(np, child) {
ret = of_property_read_u32(child, "reg", &cs);
- if (!ret)
+ if (ret)
continue;
if (cs == index) {
/*
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1651d7f0a303..d1adfdf50fb3 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
/* Do not leak kernel stack to userspace */
memset(&ge, 0, sizeof(ge));
- ge.timestamp = le->timestamp;
+ /*
+ * We may be running from a nested threaded interrupt in which case
+ * we didn't get the timestamp from lineevent_irq_handler().
+ */
+ if (!le->timestamp)
+ ge.timestamp = ktime_get_real_ns();
+ else
+ ge.timestamp = le->timestamp;
if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
&& le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index a028661d9e20..92b11de19581 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
+ { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0, 0, 0, 0, 0 },
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 8a078f4ae73d..7ff3a28fc903 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1701,8 +1701,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
amdgpu_xgmi_add_device(adev);
amdgpu_amdkfd_device_init(adev);
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev)) {
+ amdgpu_virt_init_data_exchange(adev);
amdgpu_virt_release_full_gpu(adev, true);
+ }
return 0;
}
@@ -2632,9 +2634,6 @@ fence_driver_init:
goto failed;
}
- if (amdgpu_sriov_vf(adev))
- amdgpu_virt_init_data_exchange(adev);
-
amdgpu_fbdev_init(adev);
r = amdgpu_pm_sysfs_init(adev);
@@ -2798,7 +2797,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
struct drm_framebuffer *fb = crtc->primary->fb;
struct amdgpu_bo *robj;
- if (amdgpu_crtc->cursor_bo) {
+ if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
r = amdgpu_bo_reserve(aobj, true);
if (r == 0) {
@@ -2906,7 +2905,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- if (amdgpu_crtc->cursor_bo) {
+ if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
r = amdgpu_bo_reserve(aobj, true);
if (r == 0) {
@@ -3226,6 +3225,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
r = amdgpu_ib_ring_tests(adev);
error:
+ amdgpu_virt_init_data_exchange(adev);
amdgpu_virt_release_full_gpu(adev, true);
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
atomic_inc(&adev->vram_lost_counter);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 15ce7e681d67..b083b219b1a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
goto cleanup;
}
- r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
- if (unlikely(r != 0)) {
- DRM_ERROR("failed to pin new abo buffer before flip\n");
- goto unreserve;
+ if (!adev->enable_virtual_display) {
+ r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
+ if (unlikely(r != 0)) {
+ DRM_ERROR("failed to pin new abo buffer before flip\n");
+ goto unreserve;
+ }
}
r = amdgpu_ttm_alloc_gart(&new_abo->tbo);
@@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);
amdgpu_bo_unreserve(new_abo);
- work->base = amdgpu_bo_gpu_offset(new_abo);
+ if (!adev->enable_virtual_display)
+ work->base = amdgpu_bo_gpu_offset(new_abo);
work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
@@ -242,9 +245,10 @@ pflip_cleanup:
goto cleanup;
}
unpin:
- if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
- DRM_ERROR("failed to unpin new abo in error path\n");
- }
+ if (!adev->enable_virtual_display)
+ if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
+ DRM_ERROR("failed to unpin new abo in error path\n");
+
unreserve:
amdgpu_bo_unreserve(new_abo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index bc62bf41b7e9..5dc349173e4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -212,6 +212,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
}
if (amdgpu_device_is_px(dev)) {
+ dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP);
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
pm_runtime_set_active(dev->dev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index aadd0fa42e43..3aa42c64484a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -405,6 +405,7 @@ struct amdgpu_crtc {
struct amdgpu_flip_work *pflip_works;
enum amdgpu_flip_status pflip_status;
int deferred_flip_completion;
+ u64 last_flip_vblank;
/* pll sharing */
struct amdgpu_atom_ss ss;
bool ss_enabled;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 1f61ed95727c..0ed41a9d2d77 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
effective_mode &= ~S_IWUSR;
if ((adev->flags & AMD_IS_APU) &&
- (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+ (attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
+ attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
return 0;
@@ -2008,6 +2009,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
{
+ struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
int ret;
if (adev->pm.sysfs_initialized)
@@ -2091,12 +2093,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
"pp_power_profile_mode\n");
return ret;
}
- ret = device_create_file(adev->dev,
- &dev_attr_pp_od_clk_voltage);
- if (ret) {
- DRM_ERROR("failed to create device file "
- "pp_od_clk_voltage\n");
- return ret;
+ if (hwmgr->od_enabled) {
+ ret = device_create_file(adev->dev,
+ &dev_attr_pp_od_clk_voltage);
+ if (ret) {
+ DRM_ERROR("failed to create device file "
+ "pp_od_clk_voltage\n");
+ return ret;
+ }
}
ret = device_create_file(adev->dev,
&dev_attr_gpu_busy_percent);
@@ -2118,6 +2122,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
{
+ struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+
if (adev->pm.dpm_enabled == 0)
return;
@@ -2138,8 +2144,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
device_remove_file(adev->dev,
&dev_attr_pp_power_profile_mode);
- device_remove_file(adev->dev,
- &dev_attr_pp_od_clk_voltage);
+ if (hwmgr->od_enabled)
+ device_remove_file(adev->dev,
+ &dev_attr_pp_od_clk_voltage);
device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 71913a18d142..a38e0fb4a6fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -38,6 +38,7 @@
#include "amdgpu_gem.h"
#include <drm/amdgpu_drm.h>
#include <linux/dma-buf.h>
+#include <linux/dma-fence-array.h>
/**
* amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
@@ -187,6 +188,48 @@ error:
return ERR_PTR(ret);
}
+static int
+__reservation_object_make_exclusive(struct reservation_object *obj)
+{
+ struct dma_fence **fences;
+ unsigned int count;
+ int r;
+
+ if (!reservation_object_get_list(obj)) /* no shared fences to convert */
+ return 0;
+
+ r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences);
+ if (r)
+ return r;
+
+ if (count == 0) {
+ /* Now that was unexpected. */
+ } else if (count == 1) {
+ reservation_object_add_excl_fence(obj, fences[0]);
+ dma_fence_put(fences[0]);
+ kfree(fences);
+ } else {
+ struct dma_fence_array *array;
+
+ array = dma_fence_array_create(count, fences,
+ dma_fence_context_alloc(1), 0,
+ false);
+ if (!array)
+ goto err_fences_put;
+
+ reservation_object_add_excl_fence(obj, &array->base);
+ dma_fence_put(&array->base);
+ }
+
+ return 0;
+
+err_fences_put:
+ while (count--)
+ dma_fence_put(fences[count]);
+ kfree(fences);
+ return -ENOMEM;
+}
+
/**
* amdgpu_gem_map_attach - &dma_buf_ops.attach implementation
* @dma_buf: Shared DMA buffer
@@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
if (attach->dev->driver != adev->dev->driver) {
/*
- * Wait for all shared fences to complete before we switch to future
- * use of exclusive fence on this prime shared bo.
+ * We only create shared fences for internal use, but importers
+ * of the dmabuf rely on exclusive fences for implicitly
+ * tracking write hazards. As any of the current fences may
+ * correspond to a write, we need to convert all existing
+ * fences on the reservation object into a single exclusive
+ * fence.
*/
- r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
- true, false,
- MAX_SCHEDULE_TIMEOUT);
- if (unlikely(r < 0)) {
- DRM_DEBUG_PRIME("Fence wait failed: %li\n", r);
+ r = __reservation_object_make_exclusive(bo->tbo.resv);
+ if (r)
goto error_unreserve;
- }
}
/* pin buffer into GTT */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 8fab0d637ee5..3a9b48b227ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle)
adev->psp.sos_fw = NULL;
release_firmware(adev->psp.asd_fw);
adev->psp.asd_fw = NULL;
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
+ if (adev->psp.ta_fw) {
+ release_firmware(adev->psp.ta_fw);
+ adev->psp.ta_fw = NULL;
+ }
return 0;
}
@@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)
struct ta_xgmi_shared_memory *xgmi_cmd;
int ret;
+ if (!psp->adev->psp.ta_fw)
+ return -ENOENT;
+
if (!psp->xgmi_context.initialized) {
ret = psp_xgmi_init_shared_buf(psp);
if (ret)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index e73d152659a2..698bcb8ce61d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -638,12 +638,14 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
struct ttm_bo_global *glob = adev->mman.bdev.glob;
struct amdgpu_vm_bo_base *bo_base;
+#if 0
if (vm->bulk_moveable) {
spin_lock(&glob->lru_lock);
ttm_bo_bulk_move_lru_tail(&vm->lru_bulk_move);
spin_unlock(&glob->lru_lock);
return;
}
+#endif
memset(&vm->lru_bulk_move, 0, sizeof(vm->lru_bulk_move));
@@ -847,9 +849,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
bp->size = amdgpu_vm_bo_size(adev, level);
bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
- if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 &&
- adev->flags & AMD_IS_APU)
- bp->domain |= AMDGPU_GEM_DOMAIN_GTT;
bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -3366,14 +3365,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
struct amdgpu_task_info *task_info)
{
struct amdgpu_vm *vm;
+ unsigned long flags;
- spin_lock(&adev->vm_manager.pasid_lock);
+ spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
if (vm)
*task_info = vm->task_info;
- spin_unlock(&adev->vm_manager.pasid_lock);
+ spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index fdace004544d..e4cc1d48eaab 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
- if (crtc->primary->fb) {
- int r;
- struct amdgpu_bo *abo;
-
- abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]);
- r = amdgpu_bo_reserve(abo, true);
- if (unlikely(r))
- DRM_ERROR("failed to reserve abo before unpin\n");
- else {
- amdgpu_bo_unpin(abo);
- amdgpu_bo_unreserve(abo);
- }
- }
amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
amdgpu_crtc->encoder = NULL;
@@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_crtc_vblank_put(&amdgpu_crtc->base);
- schedule_work(&works->unpin_work);
+ amdgpu_bo_unref(&works->old_abo);
+ kfree(works->shared);
+ kfree(works);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 381f593b0cda..57cb3a51bda7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
u32 tmp;
u32 rb_bufsz;
u64 rb_addr, rptr_addr, wptr_gpu_addr;
- int r;
/* Set the write pointer delay */
WREG32(mmCP_RB_WPTR_DELAY, 0);
@@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
amdgpu_ring_clear_ring(ring);
gfx_v8_0_cp_gfx_start(adev);
ring->sched.ready = true;
- r = amdgpu_ring_test_helper(ring);
- return r;
+ return 0;
}
static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
@@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
}
- r = amdgpu_ring_test_helper(kiq_ring);
- if (r)
- DRM_ERROR("KCQ enable failed\n");
- return r;
+ amdgpu_ring_commit(kiq_ring);
+
+ return 0;
}
static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
@@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)
if (r)
goto done;
- /* Test KCQs - reversing the order of rings seems to fix ring test failure
- * after GPU reset
- */
- for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) {
+done:
+ return r;
+}
+
+static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
+{
+ int r, i;
+ struct amdgpu_ring *ring;
+
+ /* collect all the ring_tests here, gfx, kiq, compute */
+ ring = &adev->gfx.gfx_ring[0];
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+
+ ring = &adev->gfx.kiq.ring;
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
ring = &adev->gfx.compute_ring[i];
- r = amdgpu_ring_test_helper(ring);
+ amdgpu_ring_test_helper(ring);
}
-done:
- return r;
+ return 0;
}
static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
@@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
r = gfx_v8_0_kcq_resume(adev);
if (r)
return r;
+
+ r = gfx_v8_0_cp_test_all_rings(adev);
+ if (r)
+ return r;
+
gfx_v8_0_enable_gui_idle_interrupt(adev, true);
return 0;
@@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))
gfx_v8_0_cp_gfx_resume(adev);
+ gfx_v8_0_cp_test_all_rings(adev);
+
adev->gfx.rlc.funcs->start(adev);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 7556716038d3..fbca0494f871 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff)
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
};
static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
@@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
};
static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
@@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t data, def;
+ amdgpu_gfx_rlc_enter_safe_mode(adev);
+
/* It is disabled by HW by default */
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
/* 1 - RLC_CGTT_MGCG_OVERRIDE */
@@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
}
}
+
+ amdgpu_gfx_rlc_exit_safe_mode(adev);
}
static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
index 8cbb4655896a..b11a1c17a7f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
@@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
return r;
}
/* Retrieve checksum from mailbox2 */
- if (req == IDH_REQ_GPU_INIT_ACCESS) {
+ if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {
adev->virt.fw_reserve.checksum_key =
RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2));
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
index 4cd31a276dcd..186db182f924 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
@@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev,
static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
bool enable)
{
+ u32 tmp = 0;
+ if (enable) {
+ tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) |
+ REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) |
+ REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0);
+
+ WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW,
+ lower_32_bits(adev->doorbell.base));
+ WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH,
+ upper_32_bits(adev->doorbell.base));
+ }
+
+ WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp);
}
static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 0c6e7f9b143f..189fcb004579 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err)
- goto out2;
-
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out2;
-
- ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
- adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
- adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
- adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
- le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+ if (err) {
+ release_firmware(adev->psp.ta_fw);
+ adev->psp.ta_fw = NULL;
+ dev_info(adev->dev,
+ "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
+ } else {
+ err = amdgpu_ucode_validate(adev->psp.ta_fw);
+ if (err)
+ goto out2;
+
+ ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
+ adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
+ adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
+ adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+ }
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index fd0bfe140ee0..aa2f71cc1eba 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
- SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
@@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
+ SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
};
@@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
+ SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
};
@@ -127,7 +128,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2_init[] = {
static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
{
- SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
+ SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
@@ -157,7 +158,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
};
static const struct soc15_reg_golden golden_settings_sdma1_4_2[] = {
- SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
+ SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index 8849b74078d6..9b639974c70c 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle)
case CHIP_RAVEN:
adev->asic_funcs = &soc15_asic_funcs;
if (adev->rev_id >= 0x8)
- adev->external_rev_id = adev->rev_id + 0x81;
+ adev->external_rev_id = adev->rev_id + 0x79;
else if (adev->pdev->device == 0x15d8)
adev->external_rev_id = adev->rev_id + 0x41;
+ else if (adev->rev_id == 1)
+ adev->external_rev_id = adev->rev_id + 0x20;
else
- adev->external_rev_id = 0x1;
+ adev->external_rev_id = adev->rev_id + 0x01;
if (adev->rev_id >= 0x8) {
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
diff --git a/drivers/gpu/drm/amd/amdkfd/Kconfig b/drivers/gpu/drm/amd/amdkfd/Kconfig
index fbf0ee5201c3..c3613604a4f8 100644
--- a/drivers/gpu/drm/amd/amdkfd/Kconfig
+++ b/drivers/gpu/drm/amd/amdkfd/Kconfig
@@ -4,8 +4,8 @@
config HSA_AMD
bool "HSA kernel driver for AMD GPU devices"
- depends on DRM_AMDGPU && X86_64
- imply AMD_IOMMU_V2
+ depends on DRM_AMDGPU && (X86_64 || ARM64)
+ imply AMD_IOMMU_V2 if X86_64
select MMU_NOTIFIER
help
Enable this if you want to use HSA features on AMD GPU devices.
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index b7bc7d7d048f..2e7c44955f43 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
return 0;
}
+#ifdef CONFIG_X86_64
static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
uint32_t *num_entries,
struct crat_subtype_iolink *sub_type_hdr)
@@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
return 0;
}
+#endif
/* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
*
@@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
struct crat_subtype_generic *sub_type_hdr;
int avail_size = *size;
int numa_node_id;
+#ifdef CONFIG_X86_64
uint32_t entries = 0;
+#endif
int ret = 0;
if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
@@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
sub_type_hdr->length);
/* Fill in Subtype: IO Link */
+#ifdef CONFIG_X86_64
ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
&entries,
(struct crat_subtype_iolink *)sub_type_hdr);
@@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
sub_type_hdr->length * entries);
+#else
+ pr_info("IO link not available for non x86 platforms\n");
+#endif
crat_table->num_domains++;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 5f5b2acedbac..09da91644f9f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
* the GPU device is not already present in the topology device
* list then return NULL. This means a new topology device has to
* be created for this GPU.
- * TODO: Rather than assiging @gpu to first topology device withtout
- * gpu attached, it will better to have more stringent check.
*/
static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
{
@@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
struct kfd_topology_device *out_dev = NULL;
down_write(&topology_lock);
- list_for_each_entry(dev, &topology_device_list, list)
+ list_for_each_entry(dev, &topology_device_list, list) {
+ /* Discrete GPUs need their own topology device list
+ * entries. Don't assign them to CPU/APU nodes.
+ */
+ if (!gpu->device_info->needs_iommu_device &&
+ dev->node_props.cpu_cores_count)
+ continue;
+
if (!dev->gpu && (dev->node_props.simd_count > 0)) {
dev->gpu = gpu;
out_dev = dev;
break;
}
+ }
up_write(&topology_lock);
return out_dev;
}
@@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
{
- const struct cpuinfo_x86 *cpuinfo;
int first_cpu_of_numa_node;
if (!cpumask || cpumask == cpu_none_mask)
@@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
first_cpu_of_numa_node = cpumask_first(cpumask);
if (first_cpu_of_numa_node >= nr_cpu_ids)
return -1;
- cpuinfo = &cpu_data(first_cpu_of_numa_node);
-
- return cpuinfo->apicid;
+#ifdef CONFIG_X86_64
+ return cpu_data(first_cpu_of_numa_node).apicid;
+#else
+ return first_cpu_of_numa_node;
+#endif
}
/* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a9a28dbc3e24..636d14a60952 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -303,12 +303,11 @@ static void dm_pflip_high_irq(void *interrupt_params)
return;
}
+ /* Update to correct count(s) if racing with vblank irq */
+ amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
/* wake up userspace */
if (amdgpu_crtc->event) {
- /* Update to correct count(s) if racing with vblank irq */
- drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
-
drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event);
/* page flip completed. clean up */
@@ -699,22 +698,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
{
struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector;
+ struct drm_dp_mst_topology_mgr *mgr;
+ int ret;
+ bool need_hotplug = false;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- aconnector = to_amdgpu_dm_connector(connector);
- if (aconnector->dc_link->type == dc_connection_mst_branch &&
- !aconnector->mst_port) {
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ head) {
+ aconnector = to_amdgpu_dm_connector(connector);
+ if (aconnector->dc_link->type != dc_connection_mst_branch ||
+ aconnector->mst_port)
+ continue;
+
+ mgr = &aconnector->mst_mgr;
- if (suspend)
- drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
- else
- drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr);
- }
+ if (suspend) {
+ drm_dp_mst_topology_mgr_suspend(mgr);
+ } else {
+ ret = drm_dp_mst_topology_mgr_resume(mgr);
+ if (ret < 0) {
+ drm_dp_mst_topology_mgr_set_mst(mgr, false);
+ need_hotplug = true;
+ }
+ }
}
drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+ if (need_hotplug)
+ drm_kms_helper_hotplug_event(dev);
}
/**
@@ -772,12 +785,13 @@ static int dm_suspend(void *handle)
struct amdgpu_display_manager *dm = &adev->dm;
int ret = 0;
+ WARN_ON(adev->dm.cached_state);
+ adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
+
s3_handle_mst(adev->ddev, true);
amdgpu_dm_irq_suspend(adev);
- WARN_ON(adev->dm.cached_state);
- adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
@@ -898,7 +912,6 @@ static int dm_resume(void *handle)
struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state;
enum dc_connection_type new_connection_type = dc_connection_none;
- int ret;
int i;
/* power on hardware */
@@ -971,13 +984,13 @@ static int dm_resume(void *handle)
}
}
- ret = drm_atomic_helper_resume(ddev, dm->cached_state);
+ drm_atomic_helper_resume(ddev, dm->cached_state);
dm->cached_state = NULL;
amdgpu_dm_irq_resume_late(adev);
- return ret;
+ return 0;
}
/**
@@ -1759,7 +1772,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+ caps.min_input_signal * 0x101;
if (dc_link_set_backlight_level(dm->backlight_link,
- brightness, 0, 0))
+ brightness, 0))
return 0;
else
return 1;
@@ -4069,7 +4082,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
}
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
- connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+ connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+ connector_type == DRM_MODE_CONNECTOR_eDP) {
drm_connector_attach_vrr_capable_property(
&aconnector->base);
}
@@ -4813,6 +4827,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
int planes_count = 0;
unsigned long flags;
+ u64 last_flip_vblank;
+ bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
/* update planes when needed */
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
@@ -4844,6 +4860,16 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
/* In commit tail framework this cannot happen */
WARN_ON(1);
}
+
+ /* For variable refresh rate mode only:
+ * Get vblank of last completed flip to avoid > 1 vrr flips per
+ * video frame by use of throttling, but allow flip programming
+ * anywhere in the possibly large variable vrr vblank interval
+ * for fine-grained flip timing control and more opportunity to
+ * avoid stutter on late submission of amdgpu_dm_do_flip() calls.
+ */
+ last_flip_vblank = acrtc_attach->last_flip_vblank;
+
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) {
@@ -4867,10 +4893,18 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
drm_crtc_vblank_get(crtc);
+ /* Use old throttling in non-vrr fixed refresh rate mode
+ * to keep flip scheduling based on target vblank counts
+ * working in a backwards compatible way, e.g., clients
+ * using GLX_OML_sync_control extension.
+ */
+ if (!vrr_active)
+ last_flip_vblank = drm_crtc_vblank_count(crtc);
+
amdgpu_dm_do_flip(
crtc,
fb,
- (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank,
+ (uint32_t) last_flip_vblank + *wait_for_vblank,
dc_state);
}
@@ -5920,7 +5954,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed &&
- !new_crtc_state->vrr_enabled)
+ old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
continue;
if (!new_crtc_state->enable)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 9a7ac58eb18e..ddd75a4d8ba5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
return bytes_from_user;
}
+/*
+ * Returns the min and max vrr vfreq through the connector's debugfs file.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
+ */
+static int vrr_range_show(struct seq_file *m, void *data)
+{
+ struct drm_connector *connector = m->private;
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+ if (connector->status != connector_status_connected)
+ return -ENODEV;
+
+ seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
+ seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
static const struct file_operations dp_link_settings_debugfs_fops = {
.owner = THIS_MODULE,
.read = dp_link_settings_read,
@@ -697,7 +716,8 @@ static const struct {
} dp_debugfs_entries[] = {
{"link_settings", &dp_link_settings_debugfs_fops},
{"phy_settings", &dp_phy_settings_debugfs_fop},
- {"test_pattern", &dp_phy_test_pattern_fops}
+ {"test_pattern", &dp_phy_test_pattern_fops},
+ {"vrr_range", &vrr_range_fops}
};
int connector_debugfs_init(struct amdgpu_dm_connector *connector)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 52deacf39841..b0265dbebd4c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
bool dc_link_set_backlight_level(const struct dc_link *link,
uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp,
- const struct dc_stream_state *stream)
+ uint32_t frame_ramp)
{
struct dc *core_dc = link->ctx->dc;
struct abm *abm = core_dc->res_pool->abm;
@@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
(abm->funcs->set_backlight_level_pwm == NULL))
return false;
- if (stream)
- ((struct dc_stream_state *)stream)->bl_pwm_level =
- backlight_pwm_u16_16;
-
use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
@@ -2637,11 +2632,6 @@ void core_link_enable_stream(
if (dc_is_dp_signal(pipe_ctx->stream->signal))
enable_stream_features(pipe_ctx);
-
- dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
- pipe_ctx->stream->bl_pwm_level,
- 0,
- pipe_ctx->stream);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index 29f19d57ff7a..b2243e0dad1f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
*/
bool dc_link_set_backlight_level(const struct dc_link *dc_link,
uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp,
- const struct dc_stream_state *stream);
+ uint32_t frame_ramp);
int dc_link_get_backlight_level(const struct dc_link *dc_link);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index be34d638e15d..d70c9e1cda3d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -91,7 +91,6 @@ struct dc_stream_state {
/* DMCU info */
unsigned int abm_level;
- unsigned int bl_pwm_level;
/* from core_stream struct */
struct dc_context *ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
index afd287f08bc9..7a72ee46f14b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
@@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements(
dc,
context->bw.dce.sclk_khz);
- pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
+ /*
+ * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
+ * This is not required for less than 5 displays,
+ * thus don't request decfclk in dc to avoid impact
+ * on power saving.
+ *
+ */
+ pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)?
+ pp_display_cfg->min_engine_clock_khz : 0;
pp_display_cfg->min_engine_clock_deep_sleep_khz
= context->bw.dce.sclk_deep_sleep_khz;
@@ -654,6 +662,11 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr,
{
struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
struct dm_pp_power_level_change_request level_change_req;
+ int patched_disp_clk = context->bw.dce.dispclk_khz;
+
+ /*TODO: W/A for dal3 linux, investigate why this works */
+ if (!clk_mgr_dce->dfs_bypass_active)
+ patched_disp_clk = patched_disp_clk * 115 / 100;
level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
/* get max clock state from PPLIB */
@@ -663,9 +676,9 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr,
clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
}
- if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) {
- context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, context->bw.dce.dispclk_khz);
- clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz;
+ if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
+ context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk);
+ clk_mgr->clks.dispclk_khz = patched_disp_clk;
}
dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h
index acd418515346..a6b80fdaa666 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h
@@ -37,6 +37,10 @@ void dce100_prepare_bandwidth(
struct dc *dc,
struct dc_state *context);
+void dce100_optimize_bandwidth(
+ struct dc *dc,
+ struct dc_state *context);
+
bool dce100_enable_display_power_gating(struct dc *dc, uint8_t controller_id,
struct dc_bios *dcb,
enum pipe_gating_control power_gating);
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 4bf24758217f..8f09b8625c5d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
- if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+ if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
/* un-mute audio */
@@ -1017,6 +1017,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, true);
if (pipe_ctx->stream_res.audio) {
+ struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
+
if (option != KEEP_ACQUIRED_RESOURCE ||
!dc->debug.az_endpoint_mute_only) {
/*only disalbe az_endpoint if power down or free*/
@@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
pipe_ctx->stream_res.audio = NULL;
}
+ if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+ pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
/* TODO: notify audio driver for if audio modes list changed
* add audio mode list change flag */
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
index a60a90e68d91..c4543178ba20 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
@@ -77,6 +77,6 @@ void dce80_hw_sequencer_construct(struct dc *dc)
dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
dc->hwss.pipe_control_lock = dce_pipe_control_lock;
dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
- dc->hwss.optimize_bandwidth = dce100_prepare_bandwidth;
+ dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
index cdd1d6b7b9f2..4e9ea50141bd 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -790,9 +790,22 @@ bool dce80_validate_bandwidth(
struct dc *dc,
struct dc_state *context)
{
- /* TODO implement when needed but for now hardcode max value*/
- context->bw.dce.dispclk_khz = 681000;
- context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ;
+ int i;
+ bool at_least_one_pipe = false;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (context->res_ctx.pipe_ctx[i].stream)
+ at_least_one_pipe = true;
+ }
+
+ if (at_least_one_pipe) {
+ /* TODO implement when needed but for now hardcode max value*/
+ context->bw.dce.dispclk_khz = 681000;
+ context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ;
+ } else {
+ context->bw.dce.dispclk_khz = 0;
+ context->bw.dce.yclk_khz = 0;
+ }
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
index dcb3c5530236..cd1ebe57ed59 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
@@ -463,7 +463,7 @@ void dpp1_set_cursor_position(
if (src_y_offset >= (int)param->viewport.height)
cur_en = 0; /* not visible beyond bottom edge*/
- if (src_y_offset < 0)
+ if (src_y_offset + (int)height <= 0)
cur_en = 0; /* not visible beyond top edge*/
REG_UPDATE(CURSOR0_CONTROL,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
index 345af015d061..d1acd7165bc8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
@@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position(
if (src_y_offset >= (int)param->viewport.height)
cur_en = 0; /* not visible beyond bottom edge*/
- if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
+ if (src_y_offset + (int)hubp->curs_attr.height <= 0)
cur_en = 0; /* not visible beyond top edge*/
if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 91e015e14355..41883c981789 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(
top_pipe_to_program->plane_state->update_flags.bits.full_update)
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
+ tg = pipe_ctx->stream_res.tg;
/* Skip inactive pipes and ones already updated */
if (!pipe_ctx->stream || pipe_ctx->stream == stream
- || !pipe_ctx->plane_state)
+ || !pipe_ctx->plane_state
+ || !tg->funcs->is_tg_enabled(tg))
continue;
- pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+ tg->funcs->lock(tg);
pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
pipe_ctx->plane_res.hubp,
&pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs);
- }
-
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
- if (!pipe_ctx->stream || pipe_ctx->stream == stream
- || !pipe_ctx->plane_state)
- continue;
-
- dcn10_pipe_control_lock(dc, pipe_ctx, false);
- }
+ tg->funcs->unlock(tg);
+ }
if (num_planes == 0)
false_optc_underflow_wa(dc, stream, tg);
@@ -2665,8 +2658,8 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
.mirror = pipe_ctx->plane_state->horizontal_mirror
};
- pos_cpy.x -= pipe_ctx->plane_state->dst_rect.x;
- pos_cpy.y -= pipe_ctx->plane_state->dst_rect.y;
+ pos_cpy.x_hotspot += pipe_ctx->plane_state->dst_rect.x;
+ pos_cpy.y_hotspot += pipe_ctx->plane_state->dst_rect.y;
if (pipe_ctx->plane_state->address.type
== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index 00f63b7dd32f..c11a443dcbc8 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
#define NUM_POWER_FN_SEGS 8
#define NUM_BL_CURVE_SEGS 16
+#pragma pack(push, 1)
/* NOTE: iRAM is 256B in size */
struct iram_table_v_2 {
/* flags */
@@ -100,6 +101,7 @@ struct iram_table_v_2 {
uint8_t dummy8; /* 0xfe */
uint8_t dummy9; /* 0xff */
};
+#pragma pack(pop)
static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
{
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 1479ea1dc3e7..789c4f288485 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -127,12 +127,13 @@ enum amd_pp_task {
};
enum PP_SMC_POWER_PROFILE {
- PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0,
- PP_SMC_POWER_PROFILE_POWERSAVING = 0x1,
- PP_SMC_POWER_PROFILE_VIDEO = 0x2,
- PP_SMC_POWER_PROFILE_VR = 0x3,
- PP_SMC_POWER_PROFILE_COMPUTE = 0x4,
- PP_SMC_POWER_PROFILE_CUSTOM = 0x5,
+ PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0,
+ PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1,
+ PP_SMC_POWER_PROFILE_POWERSAVING = 0x2,
+ PP_SMC_POWER_PROFILE_VIDEO = 0x3,
+ PP_SMC_POWER_PROFILE_VR = 0x4,
+ PP_SMC_POWER_PROFILE_COMPUTE = 0x5,
+ PP_SMC_POWER_PROFILE_CUSTOM = 0x6,
};
enum {
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
index 0173d0480024..310b102a9292 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
{
- hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
- hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
- hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
- hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
- hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
-
- hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
- hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
- hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
- hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
- hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
+ hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+
+ hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+ hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
+ hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
+ hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
+ hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
}
int hwmgr_early_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index f95c5f50eb0f..5273de3c5b98 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
break;
case amd_pp_dpp_clock:
pclk_vol_table = pinfo->vdd_dep_on_dppclk;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index d91390459326..c8f5c00dd1e7 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -77,8 +77,9 @@
#define PCIE_BUS_CLK 10000
#define TCLK (PCIE_BUS_CLK / 10)
-static const struct profile_mode_setting smu7_profiling[6] =
- {{1, 0, 100, 30, 1, 0, 100, 10},
+static const struct profile_mode_setting smu7_profiling[7] =
+ {{0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 0, 100, 30, 1, 0, 100, 10},
{1, 10, 0, 30, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 10, 16, 31},
{1, 0, 11, 50, 1, 0, 100, 10},
@@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
uint32_t i, size = 0;
uint32_t len;
- static const char *profile_name[6] = {"3D_FULL_SCREEN",
+ static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+ "3D_FULL_SCREEN",
"POWER_SAVING",
"VIDEO",
"VR",
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 79c86247d0ac..91e3bbe6d61d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -804,9 +804,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
hwmgr->backend = data;
- hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
- hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
- hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+ hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+ hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
vega10_set_default_registry_data(hwmgr);
data->disable_dpm_mask = 0xff;
@@ -4668,13 +4668,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
{
struct vega10_hwmgr *data = hwmgr->backend;
uint32_t i, size = 0;
- static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,},
+ static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,},
+ {70, 60, 1, 3,},
{90, 60, 0, 0,},
{70, 60, 0, 0,},
{70, 90, 0, 0,},
{30, 60, 0, 6,},
};
- static const char *profile_name[6] = {"3D_FULL_SCREEN",
+ static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+ "3D_FULL_SCREEN",
"POWER_SAVING",
"VIDEO",
"VR",
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
index b8747a5c9204..99d596dc0e89 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
@@ -32,6 +32,7 @@
#include "vega10_pptable.h"
#define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
enum phm_platform_caps cap)
@@ -258,7 +259,26 @@ static int init_over_drive_limits(
struct pp_hwmgr *hwmgr,
const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
{
- hwmgr->platform_descriptor.overdriveLimit.engineClock =
+ const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+ (const ATOM_Vega10_GFXCLK_Dependency_Table *)
+ (((unsigned long) powerplay_table) +
+ le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+ bool is_acg_enabled = false;
+ ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+ if (gfxclk_dep_table->ucRevId == 1) {
+ patom_record_v2 =
+ (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+ is_acg_enabled =
+ (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+ }
+
+ if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+ !is_acg_enabled)
+ hwmgr->platform_descriptor.overdriveLimit.engineClock =
+ VEGA10_ENGINECLOCK_HARDMAX;
+ else
+ hwmgr->platform_descriptor.overdriveLimit.engineClock =
le32_to_cpu(powerplay_table->ulMaxODEngineClock);
hwmgr->platform_descriptor.overdriveLimit.memoryClock =
le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
index 54364444ecd1..0c8212902275 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
@@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
return 0;
}
+static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
+{
+ uint32_t result;
+
+ PP_ASSERT_WITH_CODE(
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0,
+ "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
+ return -EINVAL);
+
+ result = smum_get_argument(hwmgr);
+ PP_ASSERT_WITH_CODE(result == 1,
+ "Failed to run ACG BTC!", return -EINVAL);
+
+ return 0;
+}
+
static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
{
struct vega12_hwmgr *data =
@@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
"Failed to initialize SMC table!",
result = tmp_result);
+ tmp_result = vega12_run_acg_btc(hwmgr);
+ PP_ASSERT_WITH_CODE(!tmp_result,
+ "Failed to run ACG BTC!",
+ result = tmp_result);
+
result = vega12_enable_all_smu_features(hwmgr);
PP_ASSERT_WITH_CODE(!result,
"Failed to enable all smu features!",
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 26154f9b2178..82935a3bd950 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -390,9 +390,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
hwmgr->backend = data;
- hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
- hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
- hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+ hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+ hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
vega20_set_default_registry_data(hwmgr);
@@ -980,6 +980,9 @@ static int vega20_od8_set_feature_capabilities(
pp_table->FanZeroRpmEnable)
od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
+ if (!od_settings->overdrive8_capabilities)
+ hwmgr->od_enabled = false;
+
return 0;
}
@@ -1689,13 +1692,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
(PPCLK_UCLK << 16) | (min_freq & 0xffff))),
"Failed to set soft min memclk !",
return ret);
-
- min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
- PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
- hwmgr, PPSMC_MSG_SetHardMinByFreq,
- (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
- "Failed to set hard min memclk !",
- return ret);
}
if (data->smu_features[GNLD_DPM_UVD].enabled &&
@@ -2248,6 +2244,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
soft_min_level = mask ? (ffs(mask) - 1) : 0;
soft_max_level = mask ? (fls(mask) - 1) : 0;
+ if (soft_max_level >= data->dpm_table.gfx_table.count) {
+ pr_err("Clock level specified %d is over max allowed %d\n",
+ soft_max_level,
+ data->dpm_table.gfx_table.count - 1);
+ return -EINVAL;
+ }
+
data->dpm_table.gfx_table.dpm_state.soft_min_level =
data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
data->dpm_table.gfx_table.dpm_state.soft_max_level =
@@ -2268,6 +2271,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
soft_min_level = mask ? (ffs(mask) - 1) : 0;
soft_max_level = mask ? (fls(mask) - 1) : 0;
+ if (soft_max_level >= data->dpm_table.mem_table.count) {
+ pr_err("Clock level specified %d is over max allowed %d\n",
+ soft_max_level,
+ data->dpm_table.mem_table.count - 1);
+ return -EINVAL;
+ }
+
data->dpm_table.mem_table.dpm_state.soft_min_level =
data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
data->dpm_table.mem_table.dpm_state.soft_max_level =
@@ -3261,6 +3271,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile)
int pplib_workload = 0;
switch (power_profile) {
+ case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
+ pplib_workload = WORKLOAD_DEFAULT_BIT;
+ break;
case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
break;
@@ -3290,6 +3303,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
uint32_t i, size = 0;
uint16_t workload_type = 0;
static const char *profile_name[] = {
+ "BOOTUP_DEFAULT",
"3D_FULL_SCREEN",
"POWER_SAVING",
"VIDEO",
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 0d298a0409f5..8cb831b6a016 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -705,7 +705,7 @@ enum PP_TABLE_VERSION {
/**
* The main hardware manager structure.
*/
-#define Workload_Policy_Max 5
+#define Workload_Policy_Max 6
struct pp_hwmgr {
void *adev;
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index f3dd66ae990a..aa35007262cd 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -154,6 +154,10 @@ static int bochs_pci_probe(struct pci_dev *pdev,
if (IS_ERR(dev))
return PTR_ERR(dev);
+ ret = pci_enable_device(pdev);
+ if (ret)
+ goto err_free_dev;
+
dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
index cf3f0caf9c63..ed7af7518b52 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
@@ -614,7 +614,6 @@ static int snd_dw_hdmi_suspend(struct device *dev)
struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
- snd_pcm_suspend_all(dw->pcm);
return 0;
}
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 8e28e738cb52..e6403b9549f1 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -98,6 +98,8 @@
#define DP0_STARTVAL 0x064c
#define DP0_ACTIVEVAL 0x0650
#define DP0_SYNCVAL 0x0654
+#define SYNCVAL_HS_POL_ACTIVE_LOW (1 << 15)
+#define SYNCVAL_VS_POL_ACTIVE_LOW (1 << 31)
#define DP0_MISC 0x0658
#define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */
#define BPC_6 (0 << 5)
@@ -142,6 +144,8 @@
#define DP0_LTLOOPCTRL 0x06d8
#define DP0_SNKLTCTRL 0x06e4
+#define DP1_SRCCTRL 0x07a0
+
/* PHY */
#define DP_PHY_CTRL 0x0800
#define DP_PHY_RST BIT(28) /* DP PHY Global Soft Reset */
@@ -150,6 +154,7 @@
#define PHY_M1_RST BIT(12) /* Reset PHY1 Main Channel */
#define PHY_RDY BIT(16) /* PHY Main Channels Ready */
#define PHY_M0_RST BIT(8) /* Reset PHY0 Main Channel */
+#define PHY_2LANE BIT(2) /* PHY Enable 2 lanes */
#define PHY_A0_EN BIT(1) /* PHY Aux Channel0 Enable */
#define PHY_M0_EN BIT(0) /* PHY Main Channel0 Enable */
@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
unsigned long rate;
u32 value;
int ret;
+ u32 dp_phy_ctrl;
rate = clk_get_rate(tc->refclk);
switch (rate) {
@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value);
- tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN);
+ dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
+ if (tc->link.base.num_lanes == 2)
+ dp_phy_ctrl |= PHY_2LANE;
+ tc_write(DP_PHY_CTRL, dp_phy_ctrl);
/*
* Initially PLLs are in bypass. Force PLL parameter update,
@@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
- tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0));
+ tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
+ ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
+ ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
@@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)
if (!tc->mode)
return -EINVAL;
- /* from excel file - DP0_SrcCtrl */
- tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B |
- DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 |
- DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT);
- /* from excel file - DP1_SrcCtrl */
- tc_write(0x07a0, 0x00003083);
+ tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
+ /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
+ tc_write(DP1_SRCCTRL,
+ (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
+ ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
rate = clk_get_rate(tc->refclk);
switch (rate) {
@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)
}
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
tc_write(SYS_PLLPARAM, value);
+
/* Setup Main Link */
- dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN | PHY_M0_EN;
+ dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
+ if (tc->link.base.num_lanes == 2)
+ dp_phy_ctrl |= PHY_2LANE;
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
msleep(100);
@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct tc_data *tc = connector_to_tc(connector);
+ u32 req, avail;
+ u32 bits_per_pixel = 24;
+
/* DPI interface clock limitation: upto 154 MHz */
if (mode->clock > 154000)
return MODE_CLOCK_HIGH;
+ req = mode->clock * bits_per_pixel / 8;
+ avail = tc->link.base.num_lanes * tc->link.base.rate;
+
+ if (req > avail)
+ return MODE_BAD;
+
return MODE_OK;
}
@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
/* Create eDP connector */
drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
- DRM_MODE_CONNECTOR_eDP);
+ tc->panel ? DRM_MODE_CONNECTOR_eDP :
+ DRM_MODE_CONNECTOR_DisplayPort);
if (ret)
return ret;
@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
drm_display_info_set_bus_formats(&tc->connector.display_info,
&bus_format, 1);
+ tc->connector.display_info.bus_flags =
+ DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_NEGEDGE;
drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
return 0;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 54e2ae614dcc..f4290f6b0c38 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1602,6 +1602,15 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
old_plane_state->crtc != new_plane_state->crtc)
return -EINVAL;
+ /*
+ * FIXME: Since prepare_fb and cleanup_fb are always called on
+ * the new_plane_state for async updates we need to block framebuffer
+ * changes. This prevents use of a fb that's been cleaned up and
+ * double cleanups from occuring.
+ */
+ if (old_plane_state->fb != new_plane_state->fb)
+ return -EINVAL;
+
funcs = plane->helper_private;
if (!funcs->atomic_async_update)
return -EINVAL;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index c40889888a16..9a1f41adfc67 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1296,12 +1296,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
return -EINVAL;
- drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
-
state = drm_atomic_state_alloc(dev);
if (!state)
return -ENOMEM;
+ drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
state->acquire_ctx = &ctx;
state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 2d6c491a0542..516e82d0ed50 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1273,6 +1273,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
{ OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
/* LG LP140WF6-SPM1 eDP panel */
{ OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
+ /* Apple panels need some additional handling to support PSR */
+ { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }
};
#undef OUI
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d3af098b0922..d73703a695e8 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1621,6 +1621,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
var_1->transp.msb_right == var_2->transp.msb_right;
}
+static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
+ u8 depth)
+{
+ switch (depth) {
+ case 8:
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 8; /* 8bit DAC */
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 15:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ var->transp.length = 1;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ default:
+ break;
+ }
+}
+
/**
* drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
* @var: screeninfo to check
@@ -1632,9 +1690,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
- if (var->pixclock != 0 || in_dbg_master())
+ if (in_dbg_master())
return -EINVAL;
+ if (var->pixclock != 0) {
+ DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
+ var->pixclock = 0;
+ }
+
if ((drm_format_info_block_width(fb->format, 0) > 1) ||
(drm_format_info_block_height(fb->format, 0) > 1))
return -EINVAL;
@@ -1655,6 +1718,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
}
/*
+ * Workaround for SDL 1.2, which is known to be setting all pixel format
+ * fields values to zero in some cases. We treat this situation as a
+ * kind of "use some reasonable autodetected values".
+ */
+ if (!var->red.offset && !var->green.offset &&
+ !var->blue.offset && !var->transp.offset &&
+ !var->red.length && !var->green.length &&
+ !var->blue.length && !var->transp.length &&
+ !var->red.msb_right && !var->green.msb_right &&
+ !var->blue.msb_right && !var->transp.msb_right) {
+ drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
+ }
+
+ /*
* drm fbdev emulation doesn't support changing the pixel format at all,
* so reject all pixel format changing requests.
*/
@@ -1967,59 +2044,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
info->var.yoffset = 0;
info->var.activate = FB_ACTIVATE_NOW;
- switch (fb->format->depth) {
- case 8:
- info->var.red.offset = 0;
- info->var.green.offset = 0;
- info->var.blue.offset = 0;
- info->var.red.length = 8; /* 8bit DAC */
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 15:
- info->var.red.offset = 10;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 5;
- info->var.blue.length = 5;
- info->var.transp.offset = 15;
- info->var.transp.length = 1;
- break;
- case 16:
- info->var.red.offset = 11;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 6;
- info->var.blue.length = 5;
- info->var.transp.offset = 0;
- break;
- case 24:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 32:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 24;
- info->var.transp.length = 8;
- break;
- default:
- break;
- }
+ drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
info->var.xres = fb_width;
info->var.yres = fb_height;
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 99cba8ea5d82..5df1256618cc 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
object_count = cl->object_count;
- object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32));
+ object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
+ array_size(object_count, sizeof(__u32)));
if (IS_ERR(object_ids))
return PTR_ERR(object_ids);
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index cd9bc0ce9be0..004191d01772 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -459,11 +459,11 @@ static int set_property_atomic(struct drm_mode_object *obj,
struct drm_modeset_acquire_ctx ctx;
int ret;
- drm_modeset_acquire_init(&ctx, 0);
-
state = drm_atomic_state_alloc(dev);
if (!state)
return -ENOMEM;
+
+ drm_modeset_acquire_init(&ctx, 0);
state->acquire_ctx = &ctx;
retry:
if (prop == state->dev->mode_config.dpms_property) {
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 24a750436559..f91e02c87fd8 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
if (mode->hsync)
return mode->hsync;
- if (mode->htotal < 0)
+ if (mode->htotal <= 0)
return 0;
calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index a9d9df6c85ad..693748ad8b88 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -61,8 +61,9 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
return NULL;
dmah->size = size;
- dmah->vaddr = dma_zalloc_coherent(&dev->pdev->dev, size, &dmah->busaddr,
- GFP_KERNEL | __GFP_COMP);
+ dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size,
+ &dmah->busaddr,
+ GFP_KERNEL | __GFP_COMP);
if (dmah->vaddr == NULL) {
kfree(dmah);
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index b5475c91e2ef..e9f343b124b0 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
return 0;
}
diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h
index 5af11cf1b482..e1675a00df12 100644
--- a/drivers/gpu/drm/i915/gvt/hypercall.h
+++ b/drivers/gpu/drm/i915/gvt/hypercall.h
@@ -41,7 +41,7 @@ struct intel_gvt_mpt {
int (*host_init)(struct device *dev, void *gvt, const void *ops);
void (*host_exit)(struct device *dev, void *gvt);
int (*attach_vgpu)(void *vgpu, unsigned long *handle);
- void (*detach_vgpu)(unsigned long handle);
+ void (*detach_vgpu)(void *vgpu);
int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
unsigned long (*from_virt_to_mfn)(void *p);
int (*enable_page_track)(unsigned long handle, u64 gfn);
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index c1072143da1d..dd3dfd00f4e6 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
{
unsigned int index;
u64 virtaddr;
- unsigned long req_size, pgoff = 0;
+ unsigned long req_size, pgoff, req_start;
pgprot_t pg_prot;
struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
@@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
pg_prot = vma->vm_page_prot;
virtaddr = vma->vm_start;
req_size = vma->vm_end - vma->vm_start;
- pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+ pgoff = vma->vm_pgoff &
+ ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+ req_start = pgoff << PAGE_SHIFT;
+
+ if (!intel_vgpu_in_aperture(vgpu, req_start))
+ return -EINVAL;
+ if (req_start + req_size >
+ vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu))
+ return -EINVAL;
+
+ pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;
return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
}
@@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
return 0;
}
-static void kvmgt_detach_vgpu(unsigned long handle)
+static void kvmgt_detach_vgpu(void *p_vgpu)
{
- /* nothing to do here */
+ int i;
+ struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu;
+
+ if (!vgpu->vdev.region)
+ return;
+
+ for (i = 0; i < vgpu->vdev.num_regions; i++)
+ if (vgpu->vdev.region[i].ops->release)
+ vgpu->vdev.region[i].ops->release(vgpu,
+ &vgpu->vdev.region[i]);
+ vgpu->vdev.num_regions = 0;
+ kfree(vgpu->vdev.region);
+ vgpu->vdev.region = NULL;
}
static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h
index 67f19992b226..3ed34123d8d1 100644
--- a/drivers/gpu/drm/i915/gvt/mpt.h
+++ b/drivers/gpu/drm/i915/gvt/mpt.h
@@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
if (!intel_gvt_host.mpt->detach_vgpu)
return;
- intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+ intel_gvt_host.mpt->detach_vgpu(vgpu);
}
#define MSI_CAP_CONTROL(offset) (offset + 2)
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 1ad8c5e1455d..55bb7885e228 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+
+ wa_ctx->indirect_ctx.obj = NULL;
+ wa_ctx->indirect_ctx.shadow_va = NULL;
}
static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
@@ -356,6 +359,33 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
return 0;
}
+static int
+intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload)
+{
+ struct intel_vgpu *vgpu = workload->vgpu;
+ struct intel_vgpu_submission *s = &vgpu->submission;
+ struct i915_gem_context *shadow_ctx = s->shadow_ctx;
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
+ struct i915_request *rq;
+ int ret = 0;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+ if (workload->req)
+ goto out;
+
+ rq = i915_request_alloc(engine, shadow_ctx);
+ if (IS_ERR(rq)) {
+ gvt_vgpu_err("fail to allocate gem request\n");
+ ret = PTR_ERR(rq);
+ goto out;
+ }
+ workload->req = i915_request_get(rq);
+out:
+ return ret;
+}
+
/**
* intel_gvt_scan_and_shadow_workload - audit the workload by scanning and
* shadow it as well, include ringbuffer,wa_ctx and ctx.
@@ -372,12 +402,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
struct intel_context *ce;
- struct i915_request *rq;
int ret;
lockdep_assert_held(&dev_priv->drm.struct_mutex);
- if (workload->req)
+ if (workload->shadow)
return 0;
ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
@@ -417,22 +446,8 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
goto err_shadow;
}
- rq = i915_request_alloc(engine, shadow_ctx);
- if (IS_ERR(rq)) {
- gvt_vgpu_err("fail to allocate gem request\n");
- ret = PTR_ERR(rq);
- goto err_shadow;
- }
- workload->req = i915_request_get(rq);
-
- ret = populate_shadow_context(workload);
- if (ret)
- goto err_req;
-
+ workload->shadow = true;
return 0;
-err_req:
- rq = fetch_and_zero(&workload->req);
- i915_request_put(rq);
err_shadow:
release_shadow_wa_ctx(&workload->wa_ctx);
err_unpin:
@@ -671,23 +686,31 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
mutex_lock(&vgpu->vgpu_lock);
mutex_lock(&dev_priv->drm.struct_mutex);
+ ret = intel_gvt_workload_req_alloc(workload);
+ if (ret)
+ goto err_req;
+
ret = intel_gvt_scan_and_shadow_workload(workload);
if (ret)
goto out;
- ret = prepare_workload(workload);
+ ret = populate_shadow_context(workload);
+ if (ret) {
+ release_shadow_wa_ctx(&workload->wa_ctx);
+ goto out;
+ }
+ ret = prepare_workload(workload);
out:
- if (ret)
- workload->status = ret;
-
if (!IS_ERR_OR_NULL(workload->req)) {
gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
ring_id, workload->req);
i915_request_add(workload->req);
workload->dispatched = true;
}
-
+err_req:
+ if (ret)
+ workload->status = ret;
mutex_unlock(&dev_priv->drm.struct_mutex);
mutex_unlock(&vgpu->vgpu_lock);
return ret;
@@ -891,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
list_del_init(&workload->list);
- if (!workload->status) {
- release_shadow_batch_buffer(workload);
- release_shadow_wa_ctx(&workload->wa_ctx);
- }
-
if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
/* if workload->status is not successful means HW GPU
* has occurred GPU hang or something wrong with i915/GVT,
@@ -1263,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
{
struct intel_vgpu_submission *s = &workload->vgpu->submission;
+ release_shadow_batch_buffer(workload);
+ release_shadow_wa_ctx(&workload->wa_ctx);
+
if (workload->shadow_mm)
intel_vgpu_mm_put(workload->shadow_mm);
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h
index ca5529d0e48e..2065cba59aab 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.h
+++ b/drivers/gpu/drm/i915/gvt/scheduler.h
@@ -83,6 +83,7 @@ struct intel_vgpu_workload {
struct i915_request *req;
/* if this workload has been dispatched to i915? */
bool dispatched;
+ bool shadow; /* if workload has done shadow of guest request */
int status;
struct intel_vgpu_mm *shadow_mm;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 38dcee1ca062..40a61ef9aac1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -984,8 +984,8 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
intel_runtime_pm_get(i915);
gpu = i915_capture_gpu_state(i915);
intel_runtime_pm_put(i915);
- if (!gpu)
- return -ENOMEM;
+ if (IS_ERR(gpu))
+ return PTR_ERR(gpu);
file->private_data = gpu;
return 0;
@@ -1018,7 +1018,13 @@ i915_error_state_write(struct file *filp,
static int i915_error_state_open(struct inode *inode, struct file *file)
{
- file->private_data = i915_first_error_state(inode->i_private);
+ struct i915_gpu_state *error;
+
+ error = i915_first_error_state(inode->i_private);
+ if (IS_ERR(error))
+ return PTR_ERR(error);
+
+ file->private_data = error;
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 216f52b744a6..c882ea94172c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
return 0;
}
+static inline bool
+__vma_matches(struct vm_area_struct *vma, struct file *filp,
+ unsigned long addr, unsigned long size)
+{
+ if (vma->vm_file != filp)
+ return false;
+
+ return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
+}
+
/**
* i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
* it is mapped to.
@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
return -EINTR;
}
vma = find_vma(mm, addr);
- if (vma)
+ if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
vma->vm_page_prot =
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
else
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index add1fe7aeb93..bd17dd1f5da5 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2075,6 +2075,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)
int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
{
struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
+ int err;
/*
* Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
@@ -2090,9 +2091,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
* allocator works in address space sizes, so it's multiplied by page
* size. We allocate at the top of the GTT to avoid fragmentation.
*/
- return i915_vma_pin(ppgtt->vma,
- 0, GEN6_PD_ALIGN,
- PIN_GLOBAL | PIN_HIGH);
+ err = i915_vma_pin(ppgtt->vma,
+ 0, GEN6_PD_ALIGN,
+ PIN_GLOBAL | PIN_HIGH);
+ if (err)
+ goto unpin;
+
+ return 0;
+
+unpin:
+ ppgtt->pin_count = 0;
+ return err;
}
void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 07465123c166..3f9ce403c755 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1907,9 +1907,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915)
{
struct i915_gpu_state *error;
+ /* Check if GPU capture has been disabled */
+ error = READ_ONCE(i915->gpu_error.first_error);
+ if (IS_ERR(error))
+ return error;
+
error = kzalloc(sizeof(*error), GFP_ATOMIC);
- if (!error)
- return NULL;
+ if (!error) {
+ i915_disable_error_state(i915, -ENOMEM);
+ return ERR_PTR(-ENOMEM);
+ }
kref_init(&error->ref);
error->i915 = i915;
@@ -1945,11 +1952,8 @@ void i915_capture_error_state(struct drm_i915_private *i915,
return;
error = i915_capture_gpu_state(i915);
- if (!error) {
- DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
- i915_disable_error_state(i915, -ENOMEM);
+ if (IS_ERR(error))
return;
- }
i915_error_capture_msg(i915, error, engine_mask, error_msg);
DRM_INFO("%s\n", error->error_msg);
@@ -1987,7 +1991,7 @@ i915_first_error_state(struct drm_i915_private *i915)
spin_lock_irq(&i915->gpu_error.lock);
error = i915->gpu_error.first_error;
- if (error)
+ if (!IS_ERR_OR_NULL(error))
i915_gpu_state_get(error);
spin_unlock_irq(&i915->gpu_error.lock);
@@ -2000,10 +2004,11 @@ void i915_reset_error_state(struct drm_i915_private *i915)
spin_lock_irq(&i915->gpu_error.lock);
error = i915->gpu_error.first_error;
- i915->gpu_error.first_error = NULL;
+ if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */
+ i915->gpu_error.first_error = NULL;
spin_unlock_irq(&i915->gpu_error.lock);
- if (!IS_ERR(error))
+ if (!IS_ERR_OR_NULL(error))
i915_gpu_state_put(error);
}
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index d6c8f8fdfda5..cf7c66bb3ed9 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -5,6 +5,7 @@
*/
#include <linux/irq.h>
+#include <linux/pm_runtime.h>
#include "i915_pmu.h"
#include "intel_ringbuffer.h"
#include "i915_drv.h"
@@ -478,7 +479,6 @@ static u64 get_rc6(struct drm_i915_private *i915)
* counter value.
*/
spin_lock_irqsave(&i915->pmu.lock, flags);
- spin_lock(&kdev->power.lock);
/*
* After the above branch intel_runtime_pm_get_if_in_use failed
@@ -491,16 +491,13 @@ static u64 get_rc6(struct drm_i915_private *i915)
* suspended and if not we cannot do better than report the last
* known RC6 value.
*/
- if (kdev->power.runtime_status == RPM_SUSPENDED) {
- if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
- i915->pmu.suspended_jiffies_last =
- kdev->power.suspended_jiffies;
+ if (pm_runtime_status_suspended(kdev)) {
+ val = pm_runtime_suspended_time(kdev);
- val = kdev->power.suspended_jiffies -
- i915->pmu.suspended_jiffies_last;
- val += jiffies - kdev->power.accounting_timestamp;
+ if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
+ i915->pmu.suspended_time_last = val;
- val = jiffies_to_nsecs(val);
+ val -= i915->pmu.suspended_time_last;
val += i915->pmu.sample[__I915_SAMPLE_RC6].cur;
i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
@@ -510,7 +507,6 @@ static u64 get_rc6(struct drm_i915_private *i915)
val = i915->pmu.sample[__I915_SAMPLE_RC6].cur;
}
- spin_unlock(&kdev->power.lock);
spin_unlock_irqrestore(&i915->pmu.lock, flags);
}
@@ -594,7 +590,8 @@ static void i915_pmu_enable(struct perf_event *event)
* Update the bitmask of enabled events and increment
* the event reference counter.
*/
- GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+ BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS);
+ GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
i915->pmu.enable |= BIT_ULL(bit);
i915->pmu.enable_count[bit]++;
@@ -615,11 +612,16 @@ static void i915_pmu_enable(struct perf_event *event)
engine = intel_engine_lookup_user(i915,
engine_event_class(event),
engine_event_instance(event));
- GEM_BUG_ON(!engine);
- engine->pmu.enable |= BIT(sample);
- GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+ BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
+ I915_ENGINE_SAMPLE_COUNT);
+ BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
+ I915_ENGINE_SAMPLE_COUNT);
+ GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+ GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
+
+ engine->pmu.enable |= BIT(sample);
engine->pmu.enable_count[sample]++;
}
@@ -649,9 +651,11 @@ static void i915_pmu_disable(struct perf_event *event)
engine = intel_engine_lookup_user(i915,
engine_event_class(event),
engine_event_instance(event));
- GEM_BUG_ON(!engine);
- GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+
+ GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+ GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
+
/*
* Decrement the reference count and clear the enabled
* bitmask when the last listener on an event goes away.
@@ -660,7 +664,7 @@ static void i915_pmu_disable(struct perf_event *event)
engine->pmu.enable &= ~BIT(sample);
}
- GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+ GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
/*
* Decrement the reference count and clear the enabled
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h
index 7f164ca3db12..4fc4f2478301 100644
--- a/drivers/gpu/drm/i915/i915_pmu.h
+++ b/drivers/gpu/drm/i915/i915_pmu.h
@@ -31,6 +31,8 @@ enum {
((1 << I915_PMU_SAMPLE_BITS) + \
(I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
+#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
+
struct i915_pmu_sample {
u64 cur;
};
@@ -95,9 +97,9 @@ struct i915_pmu {
*/
struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS];
/**
- * @suspended_jiffies_last: Cached suspend time from PM core.
+ * @suspended_time_last: Cached suspend time from PM core.
*/
- unsigned long suspended_jiffies_last;
+ u64 suspended_time_last;
/**
* @i915_attr: Memory block holding device attributes.
*/
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 0a7d60509ca7..067054cf4a86 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1790,7 +1790,7 @@ enum i915_power_well_id {
#define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40
#define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40
#define _CNL_PORT_TX_F_LN0_OFFSET 0x162840
-#define _CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \
+#define _CNL_PORT_TX_DW_GRP(dw, port) (_PICK((port), \
_CNL_PORT_TX_AE_GRP_OFFSET, \
_CNL_PORT_TX_B_GRP_OFFSET, \
_CNL_PORT_TX_B_GRP_OFFSET, \
@@ -1798,7 +1798,7 @@ enum i915_power_well_id {
_CNL_PORT_TX_AE_GRP_OFFSET, \
_CNL_PORT_TX_F_GRP_OFFSET) + \
4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \
+#define _CNL_PORT_TX_DW_LN0(dw, port) (_PICK((port), \
_CNL_PORT_TX_AE_LN0_OFFSET, \
_CNL_PORT_TX_B_LN0_OFFSET, \
_CNL_PORT_TX_B_LN0_OFFSET, \
@@ -1834,9 +1834,9 @@ enum i915_power_well_id {
#define _CNL_PORT_TX_DW4_LN0_AE 0x162450
#define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 4))
-#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4))
-#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \
+#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
+#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
+#define CNL_PORT_TX_DW4_LN(port, ln) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
_CNL_PORT_TX_DW4_LN0_AE)))
#define ICL_PORT_TX_DW4_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
@@ -1864,8 +1864,12 @@ enum i915_power_well_id {
#define RTERM_SELECT(x) ((x) << 3)
#define RTERM_SELECT_MASK (0x7 << 3)
-#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP((port), 7))
-#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0((port), 7))
+#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
+#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
+#define ICL_PORT_TX_DW7_AUX(port) _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
+#define ICL_PORT_TX_DW7_GRP(port) _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
+#define ICL_PORT_TX_DW7_LN0(port) _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
+#define ICL_PORT_TX_DW7_LN(port, ln) _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
#define N_SCALAR(x) ((x) << 24)
#define N_SCALAR_MASK (0x7F << 24)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 535caebd9813..c0cfe7ae2ba5 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -521,7 +521,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
ssize_t ret;
gpu = i915_first_error_state(i915);
- if (gpu) {
+ if (IS_ERR(gpu)) {
+ ret = PTR_ERR(gpu);
+ } else if (gpu) {
ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
i915_gpu_state_put(gpu);
} else {
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 9726df37c4c4..540e20eb032c 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -123,12 +123,6 @@ static inline u64 ptr_to_u64(const void *ptr)
#include <linux/list.h>
-static inline int list_is_first(const struct list_head *list,
- const struct list_head *head)
-{
- return head->next == list;
-}
-
static inline void __list_del_many(struct list_head *head,
struct list_head *first)
{
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index ae55a6865d5c..b32681632f30 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -984,7 +984,9 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
{
int ret;
- ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops);
+ ret = component_add_typed(dev_priv->drm.dev,
+ &i915_audio_component_bind_ops,
+ I915_COMPONENT_AUDIO);
if (ret < 0) {
DRM_ERROR("failed to add audio component (%d)\n", ret);
/* continue with reduced functionality */
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index f3e1d6a0b7dd..7edce1b7b348 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
{ 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
};
-struct icl_combo_phy_ddi_buf_trans {
- u32 dw2_swing_select;
- u32 dw2_swing_scalar;
- u32 dw4_scaling;
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = {
- /* Voltage mV db */
- { 0x2, 0x98, 0x0018 }, /* 400 0.0 */
- { 0x2, 0x98, 0x3015 }, /* 400 3.5 */
- { 0x2, 0x98, 0x6012 }, /* 400 6.0 */
- { 0x2, 0x98, 0x900F }, /* 400 9.5 */
- { 0xB, 0x70, 0x0018 }, /* 600 0.0 */
- { 0xB, 0x70, 0x3015 }, /* 600 3.5 */
- { 0xB, 0x70, 0x6012 }, /* 600 6.0 */
- { 0x5, 0x00, 0x0018 }, /* 800 0.0 */
- { 0x5, 0x00, 0x3015 }, /* 800 3.5 */
- { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */
-};
-
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = {
- /* Voltage mV db */
- { 0x0, 0x00, 0x00 }, /* 200 0.0 */
- { 0x0, 0x00, 0x00 }, /* 200 1.5 */
- { 0x0, 0x00, 0x00 }, /* 200 4.0 */
- { 0x0, 0x00, 0x00 }, /* 200 6.0 */
- { 0x0, 0x00, 0x00 }, /* 250 0.0 */
- { 0x0, 0x00, 0x00 }, /* 250 1.5 */
- { 0x0, 0x00, 0x00 }, /* 250 4.0 */
- { 0x0, 0x00, 0x00 }, /* 300 0.0 */
- { 0x0, 0x00, 0x00 }, /* 300 1.5 */
- { 0x0, 0x00, 0x00 }, /* 350 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = {
- /* Voltage mV db */
- { 0x2, 0x98, 0x0018 }, /* 400 0.0 */
- { 0x2, 0x98, 0x3015 }, /* 400 3.5 */
- { 0x2, 0x98, 0x6012 }, /* 400 6.0 */
- { 0x2, 0x98, 0x900F }, /* 400 9.5 */
- { 0x4, 0x98, 0x0018 }, /* 600 0.0 */
- { 0x4, 0x98, 0x3015 }, /* 600 3.5 */
- { 0x4, 0x98, 0x6012 }, /* 600 6.0 */
- { 0x5, 0x76, 0x0018 }, /* 800 0.0 */
- { 0x5, 0x76, 0x3015 }, /* 800 3.5 */
- { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */
+/* icl_combo_phy_ddi_translations */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
+ { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
+ { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
+ { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
+ { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
+ { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
+ { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
+ { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
+ { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
+ { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
};
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = {
- /* Voltage mV db */
- { 0x0, 0x00, 0x00 }, /* 200 0.0 */
- { 0x0, 0x00, 0x00 }, /* 200 1.5 */
- { 0x0, 0x00, 0x00 }, /* 200 4.0 */
- { 0x0, 0x00, 0x00 }, /* 200 6.0 */
- { 0x0, 0x00, 0x00 }, /* 250 0.0 */
- { 0x0, 0x00, 0x00 }, /* 250 1.5 */
- { 0x0, 0x00, 0x00 }, /* 250 4.0 */
- { 0x0, 0x00, 0x00 }, /* 300 0.0 */
- { 0x0, 0x00, 0x00 }, /* 300 1.5 */
- { 0x0, 0x00, 0x00 }, /* 350 0.0 */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { 0x0, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */
+ { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 200 250 1.9 */
+ { 0x1, 0x7F, 0x33, 0x00, 0x0C }, /* 200 300 3.5 */
+ { 0x9, 0x7F, 0x31, 0x00, 0x0E }, /* 200 350 4.9 */
+ { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */
+ { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 250 300 1.6 */
+ { 0x9, 0x7F, 0x35, 0x00, 0x0A }, /* 250 350 2.9 */
+ { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */
+ { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */
+ { 0x9, 0x7F, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
};
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = {
- /* Voltage mV db */
- { 0x2, 0x98, 0x0018 }, /* 400 0.0 */
- { 0x2, 0x98, 0x3015 }, /* 400 3.5 */
- { 0x2, 0x98, 0x6012 }, /* 400 6.0 */
- { 0x2, 0x98, 0x900F }, /* 400 9.5 */
- { 0x4, 0x98, 0x0018 }, /* 600 0.0 */
- { 0x4, 0x98, 0x3015 }, /* 600 3.5 */
- { 0x4, 0x98, 0x6012 }, /* 600 6.0 */
- { 0x5, 0x71, 0x0018 }, /* 800 0.0 */
- { 0x5, 0x71, 0x3015 }, /* 800 3.5 */
- { 0x6, 0x98, 0x0018 }, /* 1200 0.0 */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
+ /* NT mV Trans mV db */
+ { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
+ { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
+ { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
+ { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
+ { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
+ { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
+ { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
+ { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
+ { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
+ { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
};
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = {
- /* Voltage mV db */
- { 0x0, 0x00, 0x00 }, /* 200 0.0 */
- { 0x0, 0x00, 0x00 }, /* 200 1.5 */
- { 0x0, 0x00, 0x00 }, /* 200 4.0 */
- { 0x0, 0x00, 0x00 }, /* 200 6.0 */
- { 0x0, 0x00, 0x00 }, /* 250 0.0 */
- { 0x0, 0x00, 0x00 }, /* 250 1.5 */
- { 0x0, 0x00, 0x00 }, /* 250 4.0 */
- { 0x0, 0x00, 0x00 }, /* 300 0.0 */
- { 0x0, 0x00, 0x00 }, /* 300 1.5 */
- { 0x0, 0x00, 0x00 }, /* 350 0.0 */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
+ /* NT mV Trans mV db */
+ { 0xA, 0x60, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */
+ { 0xB, 0x73, 0x36, 0x00, 0x09 }, /* 450 650 3.2 */
+ { 0x6, 0x7F, 0x31, 0x00, 0x0E }, /* 450 850 5.5 */
+ { 0xB, 0x73, 0x3F, 0x00, 0x00 }, /* 650 650 0.0 ALS */
+ { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 650 850 2.3 */
+ { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 850 850 0.0 */
+ { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
};
struct icl_mg_phy_ddi_buf_trans {
@@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
}
}
-static const struct icl_combo_phy_ddi_buf_trans *
+static const struct cnl_ddi_buf_trans *
icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
- int type, int *n_entries)
+ int type, int rate, int *n_entries)
{
- u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
-
- if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
- switch (voltage) {
- case VOLTAGE_INFO_0_85V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
- return icl_combo_phy_ddi_translations_edp_0_85V;
- case VOLTAGE_INFO_0_95V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
- return icl_combo_phy_ddi_translations_edp_0_95V;
- case VOLTAGE_INFO_1_05V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
- return icl_combo_phy_ddi_translations_edp_1_05V;
- default:
- MISSING_CASE(voltage);
- return NULL;
- }
- } else {
- switch (voltage) {
- case VOLTAGE_INFO_0_85V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
- return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
- case VOLTAGE_INFO_0_95V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
- return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
- case VOLTAGE_INFO_1_05V:
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
- return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
- default:
- MISSING_CASE(voltage);
- return NULL;
- }
+ if (type == INTEL_OUTPUT_HDMI) {
+ *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
+ return icl_combo_phy_ddi_translations_hdmi;
+ } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) {
+ *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
+ return icl_combo_phy_ddi_translations_edp_hbr3;
+ } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+ *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
+ return icl_combo_phy_ddi_translations_edp_hbr2;
}
+
+ *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
+ return icl_combo_phy_ddi_translations_dp_hbr2;
}
static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
@@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
if (IS_ICELAKE(dev_priv)) {
if (intel_port_is_combophy(dev_priv, port))
- icl_get_combo_buf_trans(dev_priv, port,
- INTEL_OUTPUT_HDMI, &n_entries);
+ icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
+ 0, &n_entries);
else
n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
default_entry = n_entries - 1;
@@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
return DDI_CLK_SEL_TBT_810;
default:
MISSING_CASE(clock);
- break;
+ return DDI_CLK_SEL_NONE;
}
case DPLL_ID_ICL_MGPLL1:
case DPLL_ID_ICL_MGPLL2:
@@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
enum port port = encoder->port;
int n_entries;
if (IS_ICELAKE(dev_priv)) {
if (intel_port_is_combophy(dev_priv, port))
icl_get_combo_buf_trans(dev_priv, port, encoder->type,
- &n_entries);
+ intel_dp->link_rate, &n_entries);
else
n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
} else if (IS_CANNONLAKE(dev_priv)) {
@@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
}
static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
- u32 level, enum port port, int type)
+ u32 level, enum port port, int type,
+ int rate)
{
- const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+ const struct cnl_ddi_buf_trans *ddi_translations = NULL;
u32 n_entries, val;
int ln;
ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
- &n_entries);
+ rate, &n_entries);
if (!ddi_translations)
return;
@@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
level = n_entries - 1;
}
- /* Set PORT_TX_DW5 Rterm Sel to 110b. */
+ /* Set PORT_TX_DW5 */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
- val &= ~RTERM_SELECT_MASK;
+ val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
+ TAP2_DISABLE | TAP3_DISABLE);
+ val |= SCALING_MODE_SEL(0x2);
val |= RTERM_SELECT(0x6);
- I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
-
- /* Program PORT_TX_DW5 */
- val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
- /* Set DisableTap2 and DisableTap3 if MIPI DSI
- * Clear DisableTap2 and DisableTap3 for all other Ports
- */
- if (type == INTEL_OUTPUT_DSI) {
- val |= TAP2_DISABLE;
- val |= TAP3_DISABLE;
- } else {
- val &= ~TAP2_DISABLE;
- val &= ~TAP3_DISABLE;
- }
+ val |= TAP3_DISABLE;
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
/* Program PORT_TX_DW2 */
val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
RCOMP_SCALAR_MASK);
- val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
- val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+ val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
+ val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
/* Program Rcomp scalar for every table entry */
- val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+ val |= RCOMP_SCALAR(0x98);
I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
/* Program PORT_TX_DW4 */
@@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
CURSOR_COEFF_MASK);
- val |= ddi_translations[level].dw4_scaling;
+ val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
+ val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
+ val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
}
+
+ /* Program PORT_TX_DW7 */
+ val = I915_READ(ICL_PORT_TX_DW7_LN0(port));
+ val &= ~N_SCALAR_MASK;
+ val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+ I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);
}
static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
@@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
/* 5. Program swing and de-emphasis */
- icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+ icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);
/* 6. Set training enable to trigger update */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3da9c0f9e948..248128126422 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
}
}
+static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+ /*
+ * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
+ * the hardware when a high res displays plugged in. DPLL P
+ * divider is zero, and the pipe timings are bonkers. We'll
+ * try to disable everything in that case.
+ *
+ * FIXME would be nice to be able to sanitize this state
+ * without several WARNs, but for now let's take the easy
+ * road.
+ */
+ return IS_GEN6(dev_priv) &&
+ crtc_state->base.active &&
+ crtc_state->shared_dpll &&
+ crtc_state->port_clock == 0;
+}
+
static void intel_sanitize_encoder(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_connector *connector;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ struct intel_crtc_state *crtc_state = crtc ?
+ to_intel_crtc_state(crtc->base.state) : NULL;
/* We need to check both for a crtc link (meaning that the
* encoder is active and trying to read from a pipe) and the
* pipe itself being active. */
- bool has_active_crtc = encoder->base.crtc &&
- to_intel_crtc(encoder->base.crtc)->active;
+ bool has_active_crtc = crtc_state &&
+ crtc_state->base.active;
+
+ if (crtc_state && has_bogus_dpll_config(crtc_state)) {
+ DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
+ pipe_name(crtc->pipe));
+ has_active_crtc = false;
+ }
connector = intel_encoder_find_connector(encoder);
if (connector && !has_active_crtc) {
@@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
/* Connector is active, but has no active pipe. This is
* fallout from our resume register restoring. Disable
* the encoder manually again. */
- if (encoder->base.crtc) {
- struct drm_crtc_state *crtc_state = encoder->base.crtc->state;
+ if (crtc_state) {
+ struct drm_encoder *best_encoder;
DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
encoder->base.base.id,
encoder->base.name);
+
+ /* avoid oopsing in case the hooks consult best_encoder */
+ best_encoder = connector->base.state->best_encoder;
+ connector->base.state->best_encoder = &encoder->base;
+
if (encoder->disable)
- encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+ encoder->disable(encoder, crtc_state,
+ connector->base.state);
if (encoder->post_disable)
- encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+ encoder->post_disable(encoder, crtc_state,
+ connector->base.state);
+
+ connector->base.state->best_encoder = best_encoder;
}
encoder->base.crtc = NULL;
diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
index 4262452963b3..79203666fc62 100644
--- a/drivers/gpu/drm/i915/intel_display.h
+++ b/drivers/gpu/drm/i915/intel_display.h
@@ -26,6 +26,7 @@
#define _INTEL_DISPLAY_H_
#include <drm/drm_util.h>
+#include <drm/i915_drm.h>
enum i915_gpio {
GPIOA,
@@ -150,21 +151,6 @@ enum plane_id {
for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \
for_each_if((__crtc)->plane_ids_mask & BIT(__p))
-enum port {
- PORT_NONE = -1,
-
- PORT_A = 0,
- PORT_B,
- PORT_C,
- PORT_D,
- PORT_E,
- PORT_F,
-
- I915_MAX_PORTS
-};
-
-#define port_name(p) ((p) + 'A')
-
/*
* Ports identifier referenced from other drivers.
* Expected to remain stable over time
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index fdd2cbc56fa3..22a74608c6e4 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
static int icl_max_source_rate(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
enum port port = dig_port->base.port;
- if (port == PORT_B)
+ if (intel_port_is_combophy(dev_priv, port) &&
+ !intel_dp_is_edp(intel_dp))
return 540000;
return 810000;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f94a04b4ad87..e9ddeaf05a14 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -209,6 +209,16 @@ struct intel_fbdev {
unsigned long vma_flags;
async_cookie_t cookie;
int preferred_bpp;
+
+ /* Whether or not fbdev hpd processing is temporarily suspended */
+ bool hpd_suspended : 1;
+ /* Set when a hotplug was received while HPD processing was
+ * suspended
+ */
+ bool hpd_waiting : 1;
+
+ /* Protects hpd_suspended */
+ struct mutex hpd_lock;
};
struct intel_encoder {
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index fb5bb5b32a60..4ee16b264dbe 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -336,8 +336,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
bool *enabled, int width, int height)
{
struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
- unsigned long conn_configured, conn_seq, mask;
unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
+ unsigned long conn_configured, conn_seq;
int i, j;
bool *save_enabled;
bool fallback = true, ret = true;
@@ -355,10 +355,9 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
drm_modeset_backoff(&ctx);
memcpy(save_enabled, enabled, count);
- mask = GENMASK(count - 1, 0);
+ conn_seq = GENMASK(count - 1, 0);
conn_configured = 0;
retry:
- conn_seq = conn_configured;
for (i = 0; i < count; i++) {
struct drm_fb_helper_connector *fb_conn;
struct drm_connector *connector;
@@ -371,7 +370,8 @@ retry:
if (conn_configured & BIT(i))
continue;
- if (conn_seq == 0 && !connector->has_tile)
+ /* First pass, only consider tiled connectors */
+ if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
continue;
if (connector->status == connector_status_connected)
@@ -475,8 +475,10 @@ retry:
conn_configured |= BIT(i);
}
- if ((conn_configured & mask) != mask && conn_configured != conn_seq)
+ if (conn_configured != conn_seq) { /* repeat until no more are found */
+ conn_seq = conn_configured;
goto retry;
+ }
/*
* If the BIOS didn't enable everything it could, fall back to have the
@@ -679,6 +681,7 @@ int intel_fbdev_init(struct drm_device *dev)
if (ifbdev == NULL)
return -ENOMEM;
+ mutex_init(&ifbdev->hpd_lock);
drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
if (!intel_fbdev_init_bios(dev, ifbdev))
@@ -752,6 +755,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
intel_fbdev_destroy(ifbdev);
}
+/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
+ * processing, fbdev will perform a full connector reprobe if a hotplug event
+ * was received while HPD was suspended.
+ */
+static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
+{
+ bool send_hpd = false;
+
+ mutex_lock(&ifbdev->hpd_lock);
+ ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
+ send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
+ ifbdev->hpd_waiting = false;
+ mutex_unlock(&ifbdev->hpd_lock);
+
+ if (send_hpd) {
+ DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
+ drm_fb_helper_hotplug_event(&ifbdev->helper);
+ }
+}
+
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
{
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -773,6 +796,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
*/
if (state != FBINFO_STATE_RUNNING)
flush_work(&dev_priv->fbdev_suspend_work);
+
console_lock();
} else {
/*
@@ -800,17 +824,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
drm_fb_helper_set_suspend(&ifbdev->helper, state);
console_unlock();
+
+ intel_fbdev_hpd_set_suspend(ifbdev, state);
}
void intel_fbdev_output_poll_changed(struct drm_device *dev)
{
struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+ bool send_hpd;
if (!ifbdev)
return;
intel_fbdev_sync(ifbdev);
- if (ifbdev->vma || ifbdev->helper.deferred_setup)
+
+ mutex_lock(&ifbdev->hpd_lock);
+ send_hpd = !ifbdev->hpd_suspended;
+ ifbdev->hpd_waiting = true;
+ mutex_unlock(&ifbdev->hpd_lock);
+
+ if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
drm_fb_helper_hotplug_event(&ifbdev->helper);
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 4be167dcd209..eab9341a5152 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)
*/
if (!(prio & I915_PRIORITY_NEWCLIENT)) {
prio |= I915_PRIORITY_NEWCLIENT;
+ active->sched.attr.priority = prio;
list_move_tail(&active->sched.link,
i915_sched_lookup_priolist(engine, prio));
}
@@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
int i;
priolist_for_each_request_consume(rq, rn, p, i) {
+ GEM_BUG_ON(last &&
+ need_preempt(engine, last, rq_prio(rq)));
+
/*
* Can we combine this request with the current port?
* It has to be the same context/ringbuffer and not
@@ -2244,6 +2248,8 @@ static int logical_ring_init(struct intel_engine_cs *engine)
if (ret)
return ret;
+ intel_engine_init_workarounds(engine);
+
if (HAS_LOGICAL_RING_ELSQ(i915)) {
execlists->submit_reg = i915->regs +
i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine));
@@ -2310,7 +2316,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
}
intel_engine_init_whitelist(engine);
- intel_engine_init_workarounds(engine);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index b8f106d9ecf8..3ac20153705a 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -55,7 +55,12 @@
struct opregion_header {
u8 signature[16];
u32 size;
- u32 opregion_ver;
+ struct {
+ u8 rsvd;
+ u8 revision;
+ u8 minor;
+ u8 major;
+ } __packed over;
u8 bios_ver[32];
u8 vbios_ver[16];
u8 driver_ver[16];
@@ -119,7 +124,8 @@ struct opregion_asle {
u64 fdss;
u32 fdsp;
u32 stat;
- u64 rvda; /* Physical address of raw vbt data */
+ u64 rvda; /* Physical (2.0) or relative from opregion (2.1+)
+ * address of raw VBT data. */
u32 rvds; /* Size of raw vbt data */
u8 rsvd[58];
} __packed;
@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
opregion->header = base;
opregion->lid_state = base + ACPI_CLID;
+ DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
+ opregion->header->over.major,
+ opregion->header->over.minor,
+ opregion->header->over.revision);
+
mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) {
DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
if (dmi_check_system(intel_no_opregion_vbt))
goto out;
- if (opregion->header->opregion_ver >= 2 && opregion->asle &&
+ if (opregion->header->over.major >= 2 && opregion->asle &&
opregion->asle->rvda && opregion->asle->rvds) {
- opregion->rvda = memremap(opregion->asle->rvda,
- opregion->asle->rvds,
+ resource_size_t rvda = opregion->asle->rvda;
+
+ /*
+ * opregion 2.0: rvda is the physical VBT address.
+ *
+ * opregion 2.1+: rvda is unsigned, relative offset from
+ * opregion base, and should never point within opregion.
+ */
+ if (opregion->header->over.major > 2 ||
+ opregion->header->over.minor >= 1) {
+ WARN_ON(rvda < OPREGION_SIZE);
+
+ rvda += asls;
+ }
+
+ opregion->rvda = memremap(rvda, opregion->asle->rvds,
MEMREMAP_WB);
+
vbt = opregion->rvda;
vbt_size = opregion->asle->rvds;
if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
goto out;
} else {
DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
+ memunmap(opregion->rvda);
+ opregion->rvda = NULL;
}
}
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 419e56342523..f71970df9936 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -274,10 +274,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
+ if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
+ DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
+ return;
+ }
+
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
return;
}
+
dev_priv->psr.sink_support = true;
dev_priv->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 72edaa7ff411..a1a7cc29fdd1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -415,16 +415,17 @@ struct intel_engine_cs {
/**
* @enable_count: Reference count for the enabled samplers.
*
- * Index number corresponds to the bit number from @enable.
+ * Index number corresponds to @enum drm_i915_pmu_engine_sample.
*/
- unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+ unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];
/**
* @sample: Counter values for sampling events.
*
* Our internal timer stores the current counters in this field.
+ *
+ * Index number corresponds to @enum drm_i915_pmu_engine_sample.
*/
-#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1)
- struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+ struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
} pmu;
/*
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d2e003d8f3db..5170a0f5fe7b 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane,
keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
- keymsk = key->channel_mask & 0x3ffffff;
+ keymsk = key->channel_mask & 0x7ffffff;
if (alpha < 0xff)
keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 2c5bbe317353..e31e263cf86b 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
int bus_format;
ret = of_property_read_u32(child, "reg", &i);
- if (ret || i < 0 || i > 1)
- return -EINVAL;
+ if (ret || i < 0 || i > 1) {
+ ret = -EINVAL;
+ goto free_child;
+ }
if (!of_device_is_available(child))
continue;
@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
channel = &imx_ldb->channel[i];
channel->ldb = imx_ldb;
channel->chno = i;
- channel->child = child;
/*
* The output port is port@4 with an external 4-port mux or
@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
imx_ldb->lvds_mux ? 4 : 2, 0,
&channel->panel, &channel->bridge);
if (ret && ret != -ENODEV)
- return ret;
+ goto free_child;
/* panel ddc only if there is no bridge */
if (!channel->bridge) {
ret = imx_ldb_panel_ddc(dev, channel, child);
if (ret)
- return ret;
+ goto free_child;
}
bus_format = of_get_bus_format(dev, child);
@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
if (bus_format < 0) {
dev_err(dev, "could not determine data mapping: %d\n",
bus_format);
- return bus_format;
+ ret = bus_format;
+ goto free_child;
}
channel->bus_format = bus_format;
+ channel->child = child;
ret = imx_ldb_register(drm, channel);
- if (ret)
- return ret;
+ if (ret) {
+ channel->child = NULL;
+ goto free_child;
+ }
}
dev_set_drvdata(dev, imx_ldb);
return 0;
+
+free_child:
+ of_node_put(child);
+ return ret;
}
static void imx_ldb_unbind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index c390924de93d..21e964f6ab5c 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
if (ret)
return ret;
- /* CRTC should be enabled */
+ /* nothing to check when disabling or disabled */
if (!crtc_state->enable)
- return -EINVAL;
+ return 0;
switch (plane->type) {
case DRM_PLANE_TYPE_PRIMARY:
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 75d97f1b2e8f..4f5c67f70c4d 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -46,7 +46,6 @@ struct meson_crtc {
struct drm_crtc base;
struct drm_pending_vblank_event *event;
struct meson_drm *priv;
- bool enabled;
};
#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
@@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
};
-static void meson_crtc_enable(struct drm_crtc *crtc)
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
{
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
struct drm_crtc_state *crtc_state = crtc->state;
@@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc)
drm_crtc_vblank_on(crtc);
- meson_crtc->enabled = true;
-}
-
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
- struct drm_crtc_state *old_state)
-{
- struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
- struct meson_drm *priv = meson_crtc->priv;
-
- DRM_DEBUG_DRIVER("\n");
-
- if (!meson_crtc->enabled)
- meson_crtc_enable(crtc);
-
priv->viu.osd1_enabled = true;
}
@@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
crtc->state->event = NULL;
}
-
- meson_crtc->enabled = false;
}
static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
unsigned long flags;
- if (crtc->state->enable && !meson_crtc->enabled)
- meson_crtc_enable(crtc);
-
if (crtc->state->event) {
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 3ee4d4a4ecba..12ff47b13668 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {
.fb_create = drm_gem_fb_create,
};
+static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = {
+ .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
static irqreturn_t meson_irq(int irq, void *arg)
{
struct drm_device *dev = arg;
@@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
drm->mode_config.max_width = 3840;
drm->mode_config.max_height = 2160;
drm->mode_config.funcs = &meson_mode_config_funcs;
+ drm->mode_config.helper_private = &meson_mode_config_helpers;
/* Hardware Initialization */
@@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev,
remote_node = of_graph_get_remote_port_parent(ep);
if (!remote_node ||
remote_node == parent || /* Ignore parent endpoint */
- !of_device_is_available(remote_node))
+ !of_device_is_available(remote_node)) {
+ of_node_put(remote_node);
continue;
+ }
count += meson_probe_remote(pdev, match, remote, remote_node);
@@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev)
for_each_endpoint_of_node(np, ep) {
remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote))
+ if (!remote || !of_device_is_available(remote)) {
+ of_node_put(remote);
continue;
+ }
count += meson_probe_remote(pdev, &match, np, remote);
+ of_node_put(remote);
}
if (count && !match)
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index cf549f1ed403..78c9e5a5e793 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -5,6 +5,7 @@ config DRM_MSM
depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST)
depends on OF && COMMON_CLK
depends on MMU
+ depends on INTERCONNECT || !INTERCONNECT
select QCOM_MDT_LOADER if ARCH_QCOM
select REGULATOR
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 5beb83d1cf87..d1662a75c7ec 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
#include <linux/clk.h>
+#include <linux/interconnect.h>
#include <linux/pm_opp.h>
#include <soc/qcom/cmd-db.h>
@@ -84,6 +85,9 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
{
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
int ret;
gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
@@ -106,6 +110,12 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
gmu->freq = gmu->gpu_freqs[index];
+
+ /*
+ * Eventually we will want to scale the path vote with the frequency but
+ * for now leave it at max so that the performance is nominal.
+ */
+ icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216));
}
void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
@@ -705,6 +715,8 @@ out:
int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
int status, ret;
@@ -720,6 +732,9 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
if (ret)
goto out;
+ /* Set the bus quota to a reasonable value for boot */
+ icc_set_bw(gpu->icc_path, 0, MBps_to_icc(3072));
+
a6xx_gmu_irq_enable(gmu);
/* Check to see if we are doing a cold or warm boot */
@@ -760,6 +775,8 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u32 val;
@@ -806,6 +823,9 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
/* Tell RPMh to power off the GPU */
a6xx_rpmh_stop(gmu);
+ /* Remove the bus vote */
+ icc_set_bw(gpu->icc_path, 0, 0);
+
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
pm_runtime_put_sync(gmu->dev);
@@ -944,7 +964,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
np = dev_pm_opp_get_of_node(opp);
if (np) {
- of_property_read_u32(np, "qcom,level", &val);
+ of_property_read_u32(np, "opp-level", &val);
of_node_put(np);
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 2e4372ef17a3..27898475cdf4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -18,6 +18,7 @@
*/
#include <linux/ascii85.h>
+#include <linux/interconnect.h>
#include <linux/kernel.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
@@ -747,6 +748,11 @@ static int adreno_get_pwrlevels(struct device *dev,
DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate);
+ /* Check for an interconnect path for the bus */
+ gpu->icc_path = of_icc_get(dev, NULL);
+ if (IS_ERR(gpu->icc_path))
+ gpu->icc_path = NULL;
+
return 0;
}
@@ -765,7 +771,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
adreno_gpu->rev = config->rev;
adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
- adreno_gpu_config.irqname = "kgsl_3d0_irq";
adreno_gpu_config.va_start = SZ_16M;
adreno_gpu_config.va_end = 0xffffffff;
@@ -788,10 +793,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
{
+ struct msm_gpu *gpu = &adreno_gpu->base;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++)
release_firmware(adreno_gpu->fw[i]);
+ icc_put(gpu->icc_path);
+
msm_gpu_cleanup(&adreno_gpu->base);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index fd75870eb17f..6aefcd6db46b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
&pdpu->pipe_qos_cfg);
}
-static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
-{
- struct dpu_plane *pdpu = to_dpu_plane(plane);
- struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
-
- if (!pdpu->is_rt_pipe)
- return;
-
- pm_runtime_get_sync(&dpu_kms->pdev->dev);
- _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
- pm_runtime_put_sync(&dpu_kms->pdev->dev);
-}
-
/**
* _dpu_plane_set_ot_limit - set OT limit for the given plane
* @plane: Pointer to drm plane
@@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane)
}
#ifdef CONFIG_DEBUG_FS
+static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+{
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+
+ if (!pdpu->is_rt_pipe)
+ return;
+
+ pm_runtime_get_sync(&dpu_kms->pdev->dev);
+ _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
+ pm_runtime_put_sync(&dpu_kms->pdev->dev);
+}
+
static ssize_t _dpu_plane_danger_read(struct file *file,
char __user *buff, size_t count, loff_t *ppos)
{
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 9cd6a96c6bf2..927e5d86f7c1 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma);
int msm_gem_map_vma(struct msm_gem_address_space *aspace,
- struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+ struct msm_gem_vma *vma, int prot,
+ struct sg_table *sgt, int npages);
void msm_gem_close_vma(struct msm_gem_address_space *aspace,
struct msm_gem_vma *vma);
@@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo,
struct drm_gem_object *msm_gem_import(struct drm_device *dev,
struct dma_buf *dmabuf, struct sg_table *sgt);
+__printf(2, 3)
void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...);
int msm_framebuffer_prepare(struct drm_framebuffer *fb,
@@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
int msm_debugfs_late_init(struct drm_device *dev);
int msm_rd_debugfs_init(struct drm_minor *minor);
void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
+__printf(3, 4)
void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
const char *fmt, ...);
int msm_perf_debugfs_init(struct drm_minor *minor);
void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
#else
static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
+__printf(3, 4)
static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
const char *fmt, ...) {}
static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 51a95da694d8..c8886d3071fa 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
struct msm_gem_object *msm_obj = to_msm_bo(obj);
struct msm_gem_vma *vma;
struct page **pages;
+ int prot = IOMMU_READ;
+
+ if (!(msm_obj->flags & MSM_BO_GPU_READONLY))
+ prot |= IOMMU_WRITE;
WARN_ON(!mutex_is_locked(&msm_obj->lock));
@@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
if (IS_ERR(pages))
return PTR_ERR(pages);
- return msm_gem_map_vma(aspace, vma, msm_obj->sgt,
- obj->size >> PAGE_SHIFT);
+ return msm_gem_map_vma(aspace, vma, prot,
+ msm_obj->sgt, obj->size >> PAGE_SHIFT);
}
/* get iova and pin it. Should have a matching put */
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 557360788084..49c04829cf34 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
int
msm_gem_map_vma(struct msm_gem_address_space *aspace,
- struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+ struct msm_gem_vma *vma, int prot,
+ struct sg_table *sgt, int npages)
{
unsigned size = npages << PAGE_SHIFT;
int ret = 0;
@@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
if (aspace->mmu)
ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
- size, IOMMU_READ | IOMMU_WRITE);
+ size, prot);
if (ret)
vma->mapped = false;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 5f3eff304355..10babd18e286 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
}
/* Get Interrupt: */
- gpu->irq = platform_get_irq_byname(pdev, config->irqname);
+ gpu->irq = platform_get_irq(pdev, 0);
if (gpu->irq < 0) {
ret = gpu->irq;
DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index efb49bb64191..6241986bab51 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -19,6 +19,7 @@
#define __MSM_GPU_H__
#include <linux/clk.h>
+#include <linux/interconnect.h>
#include <linux/regulator/consumer.h>
#include "msm_drv.h"
@@ -31,7 +32,6 @@ struct msm_gpu_state;
struct msm_gpu_config {
const char *ioname;
- const char *irqname;
uint64_t va_start;
uint64_t va_end;
unsigned int nr_rings;
@@ -63,7 +63,7 @@ struct msm_gpu_funcs {
struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);
void (*recover)(struct msm_gpu *gpu);
void (*destroy)(struct msm_gpu *gpu);
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
/* show GPU status in debugfs: */
void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,
struct drm_printer *p);
@@ -119,6 +119,8 @@ struct msm_gpu {
struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk;
uint32_t fast_rate;
+ struct icc_path *icc_path;
+
/* Hang and Inactivity Detection:
*/
#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 90e9d0a48dc0..d21172933d92 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
char *fptr = &fifo->buf[fifo->head];
int n;
- wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
+ wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
+ if (!rd->open)
+ return;
/* Note that smp_load_acquire() is not strictly required
* as CIRC_SPACE_TO_END() does not access the tail more
@@ -213,7 +215,10 @@ out:
static int rd_release(struct inode *inode, struct file *file)
{
struct msm_rd_state *rd = inode->i_private;
+
rd->open = false;
+ wake_up_all(&rd->fifo_event);
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 5f5be6368aed..c7a94c94dbf3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -253,6 +253,9 @@ nouveau_backlight_init(struct drm_connector *connector)
case NV_DEVICE_INFO_V0_FERMI:
case NV_DEVICE_INFO_V0_KEPLER:
case NV_DEVICE_INFO_V0_MAXWELL:
+ case NV_DEVICE_INFO_V0_PASCAL:
+ case NV_DEVICE_INFO_V0_VOLTA:
+ case NV_DEVICE_INFO_V0_TURING:
ret = nv50_backlight_init(nv_encoder, &props, &ops);
break;
default:
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index bfbc9341e0c2..d9edb5785813 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2435,6 +2435,38 @@ nv140_chipset = {
};
static const struct nvkm_device_chip
+nv162_chipset = {
+ .name = "TU102",
+ .bar = tu104_bar_new,
+ .bios = nvkm_bios_new,
+ .bus = gf100_bus_new,
+ .devinit = tu104_devinit_new,
+ .fault = tu104_fault_new,
+ .fb = gv100_fb_new,
+ .fuse = gm107_fuse_new,
+ .gpio = gk104_gpio_new,
+ .i2c = gm200_i2c_new,
+ .ibus = gm200_ibus_new,
+ .imem = nv50_instmem_new,
+ .ltc = gp102_ltc_new,
+ .mc = tu104_mc_new,
+ .mmu = tu104_mmu_new,
+ .pci = gp100_pci_new,
+ .pmu = gp102_pmu_new,
+ .therm = gp100_therm_new,
+ .timer = gk20a_timer_new,
+ .top = gk104_top_new,
+ .ce[0] = tu104_ce_new,
+ .ce[1] = tu104_ce_new,
+ .ce[2] = tu104_ce_new,
+ .ce[3] = tu104_ce_new,
+ .ce[4] = tu104_ce_new,
+ .disp = tu104_disp_new,
+ .dma = gv100_dma_new,
+ .fifo = tu104_fifo_new,
+};
+
+static const struct nvkm_device_chip
nv164_chipset = {
.name = "TU104",
.bar = tu104_bar_new,
@@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x138: device->chip = &nv138_chipset; break;
case 0x13b: device->chip = &nv13b_chipset; break;
case 0x140: device->chip = &nv140_chipset; break;
+ case 0x162: device->chip = &nv162_chipset; break;
case 0x164: device->chip = &nv164_chipset; break;
case 0x166: device->chip = &nv166_chipset; break;
default:
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
index 816ccaedfc73..8675613e142b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
@@ -22,6 +22,7 @@
#include <engine/falcon.h>
#include <core/gpuobj.h>
+#include <subdev/mc.h>
#include <subdev/timer.h>
#include <engine/fifo.h>
@@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
}
}
- nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
- nvkm_wr32(device, base + 0x014, 0xffffffff);
+ if (nvkm_mc_enabled(device, engine->subdev.index)) {
+ nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
+ nvkm_wr32(device, base + 0x014, 0xffffffff);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index 3695cde669f8..07914e36939e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -132,11 +132,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
duty = nvkm_therm_update_linear(therm);
break;
case NVBIOS_THERM_FAN_OTHER:
- if (therm->cstate)
+ if (therm->cstate) {
duty = therm->cstate;
- else
+ poll = false;
+ } else {
duty = nvkm_therm_update_linear_fallback(therm);
- poll = false;
+ }
break;
}
immd = false;
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 00a9c2ab9e6c..64fb788b6647 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll)
static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
{
- struct dsi_data *dsi = p;
+ struct dsi_data *dsi = s->private;
struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
enum dss_clk_source dispc_clk_src, dsi_clk_src;
int dsi_module = dsi->module_id;
@@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
{
- struct dsi_data *dsi = p;
+ struct dsi_data *dsi = s->private;
unsigned long flags;
struct dsi_irq_stats stats;
@@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
static int dsi_dump_dsi_regs(struct seq_file *s, void *p)
{
- struct dsi_data *dsi = p;
+ struct dsi_data *dsi = s->private;
if (dsi_runtime_get(dsi))
return 0;
@@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+ /*
+ * HACK: These flags should be handled through the omap_dss_device bus
+ * flags, but this will only be possible when the DSI encoder will be
+ * converted to the omapdrm-managed encoder model.
+ */
+ dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+ dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
dss_mgr_set_timings(&dsi->output, &dsi->vm);
@@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
- dsi_dump_dsi_regs, &dsi);
+ dsi_dump_dsi_regs, dsi);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
- dsi_dump_dsi_irqs, &dsi);
+ dsi_dump_dsi_irqs, dsi);
#endif
snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
- dsi_dump_dsi_clocks, &dsi);
+ dsi_dump_dsi_clocks, dsi);
return 0;
}
@@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data)
dss_debugfs_remove_file(dsi->debugfs.irqs);
dss_debugfs_remove_file(dsi->debugfs.regs);
- of_platform_depopulate(dev);
-
WARN_ON(dsi->scp_clk_refcount > 0);
dss_pll_unregister(&dsi->pll);
@@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev)
dsi_uninit_output(dsi);
+ of_platform_depopulate(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 13c8a662f9b4..ccb090f3ab30 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = {
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = qxl_debugfs_init,
#endif
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .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_pin = qxl_gem_prime_pin,
.gem_prime_unpin = qxl_gem_prime_unpin,
- .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
- .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
.gem_prime_vmap = qxl_gem_prime_vmap,
.gem_prime_vunmap = qxl_gem_prime_vunmap,
.gem_prime_mmap = qxl_gem_prime_mmap,
diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
index a55dece118b2..df65d3c1a7b8 100644
--- a/drivers/gpu/drm/qxl/qxl_prime.c
+++ b/drivers/gpu/drm/qxl/qxl_prime.c
@@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj)
WARN_ONCE(1, "not implemented");
}
-struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
- WARN_ONCE(1, "not implemented");
- return ERR_PTR(-ENOSYS);
-}
-
-struct drm_gem_object *qxl_gem_prime_import_sg_table(
- struct drm_device *dev, struct dma_buf_attachment *attach,
- struct sg_table *table)
-{
- WARN_ONCE(1, "not implemented");
- return ERR_PTR(-ENOSYS);
-}
-
void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
{
WARN_ONCE(1, "not implemented");
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index d587779a80b4..a97294ac96d5 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)
u16 data_offset, size;
u8 frev, crev;
struct ci_power_info *pi;
- enum pci_bus_speed speed_cap;
+ enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
struct pci_dev *root = rdev->pdev->bus->self;
int ret;
@@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)
return -ENOMEM;
rdev->pm.dpm.priv = pi;
- speed_cap = pcie_get_speed_cap(root);
+ if (!pci_is_root_bus(rdev->pdev->bus))
+ speed_cap = pcie_get_speed_cap(root);
if (speed_cap == PCI_SPEED_UNKNOWN) {
pi->sys_pcie_mask = 0;
} else {
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index dec1e081f529..6a8fb6fd183c 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -172,6 +172,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
}
if (radeon_is_px(dev)) {
+ dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP);
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
pm_runtime_set_active(dev->dev);
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 8fb60b3af015..0a785ef0ab66 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)
struct ni_power_info *ni_pi;
struct si_power_info *si_pi;
struct atom_clock_dividers dividers;
- enum pci_bus_speed speed_cap;
+ enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
struct pci_dev *root = rdev->pdev->bus->self;
int ret;
@@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)
eg_pi = &ni_pi->eg;
pi = &eg_pi->rv7xx;
- speed_cap = pcie_get_speed_cap(root);
+ if (!pci_is_root_bus(rdev->pdev->bus))
+ speed_cap = pcie_get_speed_cap(root);
if (speed_cap == PCI_SPEED_UNKNOWN) {
si_pi->sys_pcie_mask = 0;
} else {
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
index 96ac1458a59c..c0351abf83a3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
* Author:
* Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 <drm/drmP.h>
@@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
child_count++;
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,
&panel, &bridge);
- if (!ret)
+ if (!ret) {
+ of_node_put(endpoint);
break;
+ }
}
of_node_put(port);
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.h b/drivers/gpu/drm/rockchip/rockchip_rgb.h
index 38b52e63b2b0..27b9635124bc 100644
--- a/drivers/gpu/drm/rockchip/rockchip_rgb.h
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.h
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
* Author:
* Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
*/
#ifdef CONFIG_ROCKCHIP_RGB
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 4463d3826ecb..e2942c9a11a7 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
while ((entity->dependency =
sched->ops->dependency(sched_job, entity))) {
+ trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
- if (drm_sched_entity_add_dependency_cb(entity)) {
-
- trace_drm_sched_job_wait_dep(sched_job,
- entity->dependency);
+ if (drm_sched_entity_add_dependency_cb(entity))
return NULL;
- }
}
/* skip jobs from entity that marked guilty */
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 9e9255ee59cd..a021bab11a4f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
remote = of_graph_get_remote_port_parent(ep);
if (!remote)
continue;
+ of_node_put(remote);
/* does this node match any registered engines? */
list_for_each_entry(frontend, &drv->frontend_list, list) {
if (remote == frontend->node) {
- of_node_put(remote);
of_node_put(port);
+ of_node_put(ep);
return frontend;
}
}
}
-
+ of_node_put(port);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 061d2e0d9011..416da5376701 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+ clk_disable_unprepare(hdmi->tmds_clk);
}
static void sun4i_hdmi_enable(struct drm_encoder *encoder)
@@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
+ clk_prepare_enable(hdmi->tmds_clk);
+
sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 0420f5c978b9..cf45d0f940f9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
return PTR_ERR(tcon->sclk0);
}
}
+ clk_prepare_enable(tcon->sclk0);
if (tcon->quirks->has_channel_1) {
tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
{
+ clk_disable_unprepare(tcon->sclk0);
clk_disable_unprepare(tcon->clk);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index f7f32a885af7..2d1aaca49105 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -127,14 +127,10 @@ static struct drm_driver driver = {
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = virtio_gpu_debugfs_init,
#endif
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .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_pin = virtgpu_gem_prime_pin,
.gem_prime_unpin = virtgpu_gem_prime_unpin,
- .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
- .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
.gem_prime_vmap = virtgpu_gem_prime_vmap,
.gem_prime_vunmap = virtgpu_gem_prime_vunmap,
.gem_prime_mmap = virtgpu_gem_prime_mmap,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 1deb41d42ea4..0c15000f926e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);
/* virtgpu_prime.c */
int virtgpu_gem_prime_pin(struct drm_gem_object *obj);
void virtgpu_gem_prime_unpin(struct drm_gem_object *obj);
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
- struct drm_device *dev, struct dma_buf_attachment *attach,
- struct sg_table *sgt);
void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
index 86ce0ae93f59..c59ec34c80a5 100644
--- a/drivers/gpu/drm/virtio/virtgpu_prime.c
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)
WARN_ONCE(1, "not implemented");
}
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
- WARN_ONCE(1, "not implemented");
- return ERR_PTR(-ENODEV);
-}
-
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
- struct drm_device *dev, struct dma_buf_attachment *attach,
- struct sg_table *table)
-{
- WARN_ONCE(1, "not implemented");
- return ERR_PTR(-ENODEV);
-}
-
void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)
{
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
index 9d9e8146db90..d7b409a3c0f8 100644
--- a/drivers/gpu/drm/vkms/vkms_crc.c
+++ b/drivers/gpu/drm/vkms/vkms_crc.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
#include "vkms_drv.h"
#include <linux/crc32.h>
#include <drm/drm_atomic.h>
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 177bbcb38306..eb56ee893761 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include "vkms_drv.h"
#include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 83087877565c..7dcbecb5fac2 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -1,9 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
/**
* DOC: vkms (Virtual Kernel Modesetting)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index e4469cd3d254..81f1cfbeb936 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
#ifndef _VKMS_DRV_H_
#define _VKMS_DRV_H_
diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
index 80311daed47a..138b0bb325cf 100644
--- a/drivers/gpu/drm/vkms/vkms_gem.c
+++ b/drivers/gpu/drm/vkms/vkms_gem.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include <linux/shmem_fs.h>
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 271a0eb9042c..4173e4f48334 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include "vkms_drv.h"
#include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 418817600ad1..0e67d2d42f0c 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include "vkms_drv.h"
#include <drm/drm_plane_helper.h>
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 25afb1d594e3..7ef5dcb06104 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -26,6 +26,7 @@
**************************************************************************/
#include <linux/module.h>
#include <linux/console.h>
+#include <linux/dma-mapping.h>
#include <drm/drmP.h>
#include "vmwgfx_drv.h"
@@ -34,7 +35,6 @@
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_module.h>
-#include <linux/intel-iommu.h>
#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
#define VMWGFX_CHIP_SVGAII 0
@@ -546,6 +546,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
}
/**
+ * vmw_assume_iommu - Figure out whether coherent dma-remapping might be
+ * taking place.
+ * @dev: Pointer to the struct drm_device.
+ *
+ * Return: true if iommu present, false otherwise.
+ */
+static bool vmw_assume_iommu(struct drm_device *dev)
+{
+ const struct dma_map_ops *ops = get_dma_ops(dev->dev);
+
+ return !dma_is_direct(ops) && ops &&
+ ops->map_page != dma_direct_map_page;
+}
+
+/**
* vmw_dma_select_mode - Determine how DMA mappings should be set up for this
* system.
*
@@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
[vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
[vmw_dma_map_populate] = "Keeping DMA mappings.",
[vmw_dma_map_bind] = "Giving up DMA mappings early."};
-#ifdef CONFIG_X86
- const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev);
-#ifdef CONFIG_INTEL_IOMMU
- if (intel_iommu_enabled) {
+ if (vmw_force_coherent)
+ dev_priv->map_mode = vmw_dma_alloc_coherent;
+ else if (vmw_assume_iommu(dev_priv->dev))
dev_priv->map_mode = vmw_dma_map_populate;
- goto out_fixup;
- }
-#endif
-
- if (!(vmw_force_iommu || vmw_force_coherent)) {
+ else if (!vmw_force_iommu)
dev_priv->map_mode = vmw_dma_phys;
- DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
- return 0;
- }
-
- dev_priv->map_mode = vmw_dma_map_populate;
-
- if (dma_ops && dma_ops->sync_single_for_cpu)
+ else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl())
dev_priv->map_mode = vmw_dma_alloc_coherent;
-#ifdef CONFIG_SWIOTLB
- if (swiotlb_nr_tbl() == 0)
+ else
dev_priv->map_mode = vmw_dma_map_populate;
-#endif
-#ifdef CONFIG_INTEL_IOMMU
-out_fixup:
-#endif
- if (dev_priv->map_mode == vmw_dma_map_populate &&
- vmw_restrict_iommu)
+ if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu)
dev_priv->map_mode = vmw_dma_map_bind;
- if (vmw_force_coherent)
- dev_priv->map_mode = vmw_dma_alloc_coherent;
-
-#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU)
- /*
- * No coherent page pool
- */
- if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+ /* No TTM coherent page pool? FIXME: Ask TTM instead! */
+ if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) &&
+ (dev_priv->map_mode == vmw_dma_alloc_coherent))
return -EINVAL;
-#endif
-
-#else /* CONFIG_X86 */
- dev_priv->map_mode = vmw_dma_map_populate;
-#endif /* CONFIG_X86 */
DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-
return 0;
}
@@ -625,24 +612,20 @@ out_fixup:
* With 32-bit we can only handle 32 bit PFNs. Optionally set that
* restriction also for 64-bit systems.
*/
-#ifdef CONFIG_INTEL_IOMMU
static int vmw_dma_masks(struct vmw_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
+ int ret = 0;
- if (intel_iommu_enabled &&
+ ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
+ if (dev_priv->map_mode != vmw_dma_phys &&
(sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
DRM_INFO("Restricting DMA addresses to 44 bits.\n");
- return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+ return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
}
- return 0;
-}
-#else
-static int vmw_dma_masks(struct vmw_private *dev_priv)
-{
- return 0;
+
+ return ret;
}
-#endif
static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
{
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index f2d13a72c05d..88b8178d4687 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
*p_fence = NULL;
}
- return 0;
+ return ret;
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index b351fb5214d3..ed2f67822f45 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,
struct drm_connector_state *conn_state;
struct vmw_connector_state *vmw_conn_state;
- if (!du->pref_active) {
+ if (!du->pref_active && new_crtc_state->enable) {
ret = -EINVAL;
goto clean;
}
@@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
user_fence_rep)
{
struct vmw_fence_obj *fence = NULL;
- uint32_t handle;
- int ret;
+ uint32_t handle = 0;
+ int ret = 0;
if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||
out_fence)
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 474b00e19697..0a7d4395d427 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {
.cpmem_ofs = 0x1f000000,
.srm_ofs = 0x1f040000,
.tpm_ofs = 0x1f060000,
- .csi0_ofs = 0x1f030000,
- .csi1_ofs = 0x1f038000,
+ .csi0_ofs = 0x1e030000,
+ .csi1_ofs = 0x1e038000,
.ic_ofs = 0x1e020000,
.disp0_ofs = 0x1e040000,
.disp1_ofs = 0x1e048000,
@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {
.cpmem_ofs = 0x07000000,
.srm_ofs = 0x07040000,
.tpm_ofs = 0x07060000,
- .csi0_ofs = 0x07030000,
- .csi1_ofs = 0x07038000,
+ .csi0_ofs = 0x06030000,
+ .csi1_ofs = 0x06038000,
.ic_ofs = 0x06020000,
.disp0_ofs = 0x06040000,
.disp1_ofs = 0x06048000,
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
index 2f8db9d62551..4a28f3fbb0a2 100644
--- a/drivers/gpu/ipu-v3/ipu-pre.c
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -106,6 +106,7 @@ struct ipu_pre {
void *buffer_virt;
bool in_use;
unsigned int safe_window_end;
+ unsigned int last_bufaddr;
};
static DEFINE_MUTEX(ipu_pre_list_mutex);
@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+ pre->last_bufaddr = bufaddr;
val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
unsigned short current_yblock;
u32 val;
+ if (bufaddr == pre->last_bufaddr)
+ return;
+
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+ pre->last_bufaddr = bufaddr;
do {
if (time_after(jiffies, timeout)) {
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index b677e5d524e6..d5f1d8e1c6f8 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -21,6 +21,7 @@ config VGA_SWITCHEROO
bool "Laptop Hybrid Graphics - GPU switching support"
depends on X86
depends on ACPI
+ depends on PCI
select VGA_ARB
help
Many laptops released in 2008/9/10 have two GPUs with a multiplexer
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f41d5fe51abe..9993b692598f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
{
struct hid_collection *collection;
unsigned usage;
+ int collection_index;
usage = parser->local.usage[0];
@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
parser->collection_stack[parser->collection_stack_ptr++] =
parser->device->maxcollection;
- collection = parser->device->collection +
- parser->device->maxcollection++;
+ collection_index = parser->device->maxcollection++;
+ collection = parser->device->collection + collection_index;
collection->type = type;
collection->usage = usage;
collection->level = parser->collection_stack_ptr - 1;
- collection->parent = parser->active_collection;
- parser->active_collection = collection;
+ collection->parent_idx = (collection->level == 0) ? -1 :
+ parser->collection_stack[collection->level - 1];
if (type == HID_COLLECTION_APPLICATION)
parser->device->maxapplication++;
@@ -192,8 +193,6 @@ static int close_collection(struct hid_parser *parser)
return -EINVAL;
}
parser->collection_stack_ptr--;
- if (parser->active_collection)
- parser->active_collection = parser->active_collection->parent;
return 0;
}
@@ -1006,10 +1005,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
usage = &field->usage[i];
collection = &hid->collection[usage->collection_index];
- while (collection && collection != multiplier_collection)
- collection = collection->parent;
+ while (collection->parent_idx != -1 &&
+ collection != multiplier_collection)
+ collection = &hid->collection[collection->parent_idx];
- if (collection || multiplier_collection == NULL)
+ if (collection->parent_idx != -1 ||
+ multiplier_collection == NULL)
usage->resolution_multiplier = effective_multiplier;
}
@@ -1044,9 +1045,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
* applicable fields later.
*/
multiplier_collection = &hid->collection[multiplier->usage->collection_index];
- while (multiplier_collection &&
+ while (multiplier_collection->parent_idx != -1 &&
multiplier_collection->type != HID_COLLECTION_LOGICAL)
- multiplier_collection = multiplier_collection->parent;
+ multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
effective_multiplier = hid_calculate_multiplier(hid, multiplier);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index c530476edba6..ac9fda1b5a72 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/kfifo.h>
#include <linux/sched/signal.h>
#include <linux/export.h>
#include <linux/slab.h>
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
/* enqueue string to 'events' ring buffer */
void hid_debug_event(struct hid_device *hdev, char *buf)
{
- unsigned i;
struct hid_debug_list *list;
unsigned long flags;
spin_lock_irqsave(&hdev->debug_list_lock, flags);
- list_for_each_entry(list, &hdev->debug_list, node) {
- for (i = 0; buf[i]; i++)
- list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
- buf[i];
- list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
- }
+ list_for_each_entry(list, &hdev->debug_list, node)
+ kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
wake_up_interruptible(&hdev->debug_wait);
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
hid_debug_event(hdev, buf);
kfree(buf);
- wake_up_interruptible(&hdev->debug_wait);
-
+ wake_up_interruptible(&hdev->debug_wait);
}
EXPORT_SYMBOL_GPL(hid_dump_input);
@@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
goto out;
}
- if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
- err = -ENOMEM;
+ err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
+ if (err) {
kfree(list);
goto out;
}
@@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
struct hid_debug_list *list = file->private_data;
- int ret = 0, len;
+ int ret = 0, copied;
DECLARE_WAITQUEUE(wait, current);
mutex_lock(&list->read_mutex);
- while (ret == 0) {
- if (list->head == list->tail) {
- add_wait_queue(&list->hdev->debug_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- while (list->head == list->tail) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
+ if (kfifo_is_empty(&list->hid_debug_fifo)) {
+ add_wait_queue(&list->hdev->debug_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (kfifo_is_empty(&list->hid_debug_fifo)) {
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
- if (!list->hdev || !list->hdev->debug) {
- ret = -EIO;
- set_current_state(TASK_RUNNING);
- goto out;
- }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
- /* allow O_NONBLOCK from other threads */
- mutex_unlock(&list->read_mutex);
- schedule();
- mutex_lock(&list->read_mutex);
- set_current_state(TASK_INTERRUPTIBLE);
+ /* if list->hdev is NULL we cannot remove_wait_queue().
+ * if list->hdev->debug is 0 then hid_debug_unregister()
+ * was already called and list->hdev is being destroyed.
+ * if we add remove_wait_queue() here we can hit a race.
+ */
+ if (!list->hdev || !list->hdev->debug) {
+ ret = -EIO;
+ set_current_state(TASK_RUNNING);
+ goto out;
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hdev->debug_wait, &wait);
+ /* allow O_NONBLOCK from other threads */
+ mutex_unlock(&list->read_mutex);
+ schedule();
+ mutex_lock(&list->read_mutex);
+ set_current_state(TASK_INTERRUPTIBLE);
}
- if (ret)
- goto out;
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&list->hdev->debug_wait, &wait);
- /* pass the ringbuffer contents to userspace */
-copy_rest:
- if (list->tail == list->head)
+ if (ret)
goto out;
- if (list->tail > list->head) {
- len = list->tail - list->head;
- if (len > count)
- len = count;
-
- if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
- ret = -EFAULT;
- goto out;
- }
- ret += len;
- list->head += len;
- } else {
- len = HID_DEBUG_BUFSIZE - list->head;
- if (len > count)
- len = count;
-
- if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
- ret = -EFAULT;
- goto out;
- }
- list->head = 0;
- ret += len;
- count -= len;
- if (count > 0)
- goto copy_rest;
- }
-
}
+
+ /* pass the fifo content to userspace, locking is not needed with only
+ * one concurrent reader and one concurrent writer
+ */
+ ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
+ if (ret)
+ goto out;
+ ret = copied;
out:
mutex_unlock(&list->read_mutex);
return ret;
@@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait)
struct hid_debug_list *list = file->private_data;
poll_wait(file, &list->hdev->debug_wait, wait);
- if (list->head != list->tail)
+ if (!kfifo_is_empty(&list->hid_debug_fifo))
return EPOLLIN | EPOLLRDNORM;
if (!list->hdev->debug)
return EPOLLERR | EPOLLHUP;
@@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
list_del(&list->node);
spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
- kfree(list->hid_debug_buf);
+ kfifo_free(&list->hid_debug_fifo);
kfree(list);
return 0;
@@ -1246,4 +1221,3 @@ void hid_debug_exit(void)
{
debugfs_remove_recursive(hid_debug_root);
}
-
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 518fa76414f5..24f846d67478 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -461,6 +461,9 @@
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
+#define I2C_VENDOR_ID_GOODIX 0x27c6
+#define I2C_DEVICE_ID_GOODIX_01F0 0x01f0
+
#define USB_VENDOR_ID_GOODTOUCH 0x1aad
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 8555ce7e737b..c5edfa966343 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -179,6 +179,8 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
{ USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
I2C_HID_QUIRK_NO_RUNTIME_PM },
+ { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
+ I2C_HID_QUIRK_NO_RUNTIME_PM },
{ 0, 0 }
};
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index ce0ba2062723..23381c41d087 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -282,8 +282,8 @@ int vmbus_open(struct vmbus_channel *newchannel,
EXPORT_SYMBOL_GPL(vmbus_open);
/* Used for Hyper-V Socket: a guest client's connect() to the host */
-int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
- const uuid_le *shv_host_servie_id)
+int vmbus_send_tl_connect_request(const guid_t *shv_guest_servie_id,
+ const guid_t *shv_host_servie_id)
{
struct vmbus_channel_tl_connect_request conn_msg;
int ret;
@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
int vmbus_disconnect_ring(struct vmbus_channel *channel)
{
struct vmbus_channel *cur_channel, *tmp;
- unsigned long flags;
- LIST_HEAD(list);
int ret;
if (channel->primary_channel != NULL)
return -EINVAL;
- /* Snapshot the list of subchannels */
- spin_lock_irqsave(&channel->lock, flags);
- list_splice_init(&channel->sc_list, &list);
- spin_unlock_irqrestore(&channel->lock, flags);
-
- list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) {
+ list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
if (cur_channel->rescind)
wait_for_completion(&cur_channel->rescind_event);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index d01689079e9b..62703b354d6d 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -141,7 +141,7 @@ static const struct vmbus_device vmbus_devs[] = {
};
static const struct {
- uuid_le guid;
+ guid_t guid;
} vmbus_unsupported_devs[] = {
{ HV_AVMA1_GUID },
{ HV_AVMA2_GUID },
@@ -171,26 +171,26 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel)
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
}
-static bool is_unsupported_vmbus_devs(const uuid_le *guid)
+static bool is_unsupported_vmbus_devs(const guid_t *guid)
{
int i;
for (i = 0; i < ARRAY_SIZE(vmbus_unsupported_devs); i++)
- if (!uuid_le_cmp(*guid, vmbus_unsupported_devs[i].guid))
+ if (guid_equal(guid, &vmbus_unsupported_devs[i].guid))
return true;
return false;
}
static u16 hv_get_dev_type(const struct vmbus_channel *channel)
{
- const uuid_le *guid = &channel->offermsg.offer.if_type;
+ const guid_t *guid = &channel->offermsg.offer.if_type;
u16 i;
if (is_hvsock_channel(channel) || is_unsupported_vmbus_devs(guid))
return HV_UNKNOWN;
for (i = HV_IDE; i < HV_UNKNOWN; i++) {
- if (!uuid_le_cmp(*guid, vmbus_devs[i].guid))
+ if (guid_equal(guid, &vmbus_devs[i].guid))
return i;
}
pr_info("Unknown GUID: %pUl\n", guid);
@@ -561,10 +561,10 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
atomic_dec(&vmbus_connection.offer_in_progress);
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
- if (!uuid_le_cmp(channel->offermsg.offer.if_type,
- newchannel->offermsg.offer.if_type) &&
- !uuid_le_cmp(channel->offermsg.offer.if_instance,
- newchannel->offermsg.offer.if_instance)) {
+ if (guid_equal(&channel->offermsg.offer.if_type,
+ &newchannel->offermsg.offer.if_type) &&
+ guid_equal(&channel->offermsg.offer.if_instance,
+ &newchannel->offermsg.offer.if_instance)) {
fnew = false;
break;
}
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 5301fef16c31..dd475f3bcc8a 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -681,8 +681,13 @@ static struct notifier_block hv_memory_nb = {
/* Check if the particular page is backed and can be onlined and online it. */
static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg)
{
- if (!has_pfn_is_backed(has, page_to_pfn(pg)))
+ if (!has_pfn_is_backed(has, page_to_pfn(pg))) {
+ if (!PageOffline(pg))
+ __SetPageOffline(pg);
return;
+ }
+ if (PageOffline(pg))
+ __ClearPageOffline(pg);
/* This frame is currently backed; online the page. */
__online_page_set_limits(pg);
@@ -771,7 +776,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
}
}
-static void hv_online_page(struct page *pg)
+static void hv_online_page(struct page *pg, unsigned int order)
{
struct hv_hotadd_state *has;
unsigned long flags;
@@ -780,10 +785,11 @@ static void hv_online_page(struct page *pg)
spin_lock_irqsave(&dm_device.ha_lock, flags);
list_for_each_entry(has, &dm_device.ha_region_list, list) {
/* The page belongs to a different HAS. */
- if ((pfn < has->start_pfn) || (pfn >= has->end_pfn))
+ if ((pfn < has->start_pfn) ||
+ (pfn + (1UL << order) > has->end_pfn))
continue;
- hv_page_online_one(has, pg);
+ hv_bring_pgs_online(has, pfn, 1UL << order);
break;
}
spin_unlock_irqrestore(&dm_device.ha_lock, flags);
@@ -888,12 +894,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
pfn_cnt -= pgs_ol;
/*
* Check if the corresponding memory block is already
- * online by checking its last previously backed page.
- * In case it is we need to bring rest (which was not
- * backed previously) online too.
+ * online. It is possible to observe struct pages still
+ * being uninitialized here so check section instead.
+ * In case the section is online we need to bring the
+ * rest of pfns (which were not backed previously)
+ * online too.
*/
if (start_pfn > has->start_pfn &&
- !PageReserved(pfn_to_page(start_pfn - 1)))
+ online_section_nr(pfn_to_section_nr(start_pfn)))
hv_bring_pgs_online(has, start_pfn, pgs_ol);
}
@@ -1199,6 +1207,7 @@ static void free_balloon_pages(struct hv_dynmem_device *dm,
for (i = 0; i < num_pages; i++) {
pg = pfn_to_page(i + start_frame);
+ __ClearPageOffline(pg);
__free_page(pg);
dm->num_pages_ballooned--;
}
@@ -1211,7 +1220,7 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
struct dm_balloon_response *bl_resp,
int alloc_unit)
{
- unsigned int i = 0;
+ unsigned int i, j;
struct page *pg;
if (num_pages < alloc_unit)
@@ -1243,6 +1252,10 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
if (alloc_unit != 1)
split_page(pg, get_order(alloc_unit << PAGE_SHIFT));
+ /* mark all pages offline */
+ for (j = 0; j < (1 << get_order(alloc_unit << PAGE_SHIFT)); j++)
+ __SetPageOffline(pg + j);
+
bl_resp->range_count++;
bl_resp->range_array[i].finfo.start_page =
page_to_pfn(pg);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index a1f6ce6e5974..cb86b133eb4d 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -312,8 +312,8 @@ extern const struct vmbus_channel_message_table_entry
/* General vmbus interface */
-struct hv_device *vmbus_device_create(const uuid_le *type,
- const uuid_le *instance,
+struct hv_device *vmbus_device_create(const guid_t *type,
+ const guid_t *instance,
struct vmbus_channel *channel);
int vmbus_device_register(struct hv_device *child_device_obj);
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 64d0c85d5161..9e8b31ccc142 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -74,8 +74,10 @@ static void hv_signal_on_write(u32 old_write, struct vmbus_channel *channel)
* This is the only case we need to signal when the
* ring transitions from being empty to non-empty.
*/
- if (old_write == READ_ONCE(rbi->ring_buffer->read_index))
+ if (old_write == READ_ONCE(rbi->ring_buffer->read_index)) {
+ ++channel->intr_out_empty;
vmbus_setevent(channel);
+ }
}
/* Get the next write location for the specified ring buffer. */
@@ -164,26 +166,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
}
/* Get various debug metrics for the specified ring buffer. */
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
- struct hv_ring_buffer_debug_info *debug_info)
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+ struct hv_ring_buffer_debug_info *debug_info)
{
u32 bytes_avail_towrite;
u32 bytes_avail_toread;
- if (ring_info->ring_buffer) {
- hv_get_ringbuffer_availbytes(ring_info,
- &bytes_avail_toread,
- &bytes_avail_towrite);
-
- debug_info->bytes_avail_toread = bytes_avail_toread;
- debug_info->bytes_avail_towrite = bytes_avail_towrite;
- debug_info->current_read_index =
- ring_info->ring_buffer->read_index;
- debug_info->current_write_index =
- ring_info->ring_buffer->write_index;
- debug_info->current_interrupt_mask =
- ring_info->ring_buffer->interrupt_mask;
- }
+ if (!ring_info->ring_buffer)
+ return -EINVAL;
+
+ hv_get_ringbuffer_availbytes(ring_info,
+ &bytes_avail_toread,
+ &bytes_avail_towrite);
+ debug_info->bytes_avail_toread = bytes_avail_toread;
+ debug_info->bytes_avail_towrite = bytes_avail_towrite;
+ debug_info->current_read_index = ring_info->ring_buffer->read_index;
+ debug_info->current_write_index = ring_info->ring_buffer->write_index;
+ debug_info->current_interrupt_mask
+ = ring_info->ring_buffer->interrupt_mask;
+ return 0;
}
EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
@@ -273,10 +274,19 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
* is empty since the read index == write index.
*/
if (bytes_avail_towrite <= totalbytes_towrite) {
+ ++channel->out_full_total;
+
+ if (!channel->out_full_flag) {
+ ++channel->out_full_first;
+ channel->out_full_flag = true;
+ }
+
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
return -EAGAIN;
}
+ channel->out_full_flag = false;
+
/* Write to the ring buffer */
next_write_location = hv_get_next_write_location(outring_info);
@@ -531,6 +541,7 @@ void hv_pkt_iter_close(struct vmbus_channel *channel)
if (curr_write_sz <= pending_sz)
return;
+ ++channel->intr_in_full;
vmbus_setevent(channel);
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_close);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index d0ff65675292..000b53e5a17a 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -234,7 +234,7 @@ static ssize_t server_monitor_pending_show(struct device *dev,
return -ENODEV;
return sprintf(buf, "%d\n",
channel_pending(hv_dev->channel,
- vmbus_connection.monitor_pages[1]));
+ vmbus_connection.monitor_pages[0]));
}
static DEVICE_ATTR_RO(server_monitor_pending);
@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+ &outbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(out_intr_mask);
@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+ &outbound);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n", outbound.current_read_index);
}
static DEVICE_ATTR_RO(out_read_index);
@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+ &outbound);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n", outbound.current_write_index);
}
static DEVICE_ATTR_RO(out_write_index);
@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+ &outbound);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(out_read_bytes_avail);
@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+ &outbound);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(out_write_bytes_avail);
@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(in_intr_mask);
@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", inbound.current_read_index);
}
static DEVICE_ATTR_RO(in_read_index);
@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", inbound.current_write_index);
}
static DEVICE_ATTR_RO(in_write_index);
@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(in_read_bytes_avail);
@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
+ int ret;
if (!hv_dev->channel)
return -ENODEV;
- if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
- return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(in_write_bytes_avail);
@@ -623,38 +654,28 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
return ret;
}
-static const uuid_le null_guid;
-
-static inline bool is_null_guid(const uuid_le *guid)
-{
- if (uuid_le_cmp(*guid, null_guid))
- return false;
- return true;
-}
-
static const struct hv_vmbus_device_id *
-hv_vmbus_dev_match(const struct hv_vmbus_device_id *id, const uuid_le *guid)
-
+hv_vmbus_dev_match(const struct hv_vmbus_device_id *id, const guid_t *guid)
{
if (id == NULL)
return NULL; /* empty device table */
- for (; !is_null_guid(&id->guid); id++)
- if (!uuid_le_cmp(id->guid, *guid))
+ for (; !guid_is_null(&id->guid); id++)
+ if (guid_equal(&id->guid, guid))
return id;
return NULL;
}
static const struct hv_vmbus_device_id *
-hv_vmbus_dynid_match(struct hv_driver *drv, const uuid_le *guid)
+hv_vmbus_dynid_match(struct hv_driver *drv, const guid_t *guid)
{
const struct hv_vmbus_device_id *id = NULL;
struct vmbus_dynid *dynid;
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
- if (!uuid_le_cmp(dynid->id.guid, *guid)) {
+ if (guid_equal(&dynid->id.guid, guid)) {
id = &dynid->id;
break;
}
@@ -664,9 +685,7 @@ hv_vmbus_dynid_match(struct hv_driver *drv, const uuid_le *guid)
return id;
}
-static const struct hv_vmbus_device_id vmbus_device_null = {
- .guid = NULL_UUID_LE,
-};
+static const struct hv_vmbus_device_id vmbus_device_null;
/*
* Return a matching hv_vmbus_device_id pointer.
@@ -675,7 +694,7 @@ static const struct hv_vmbus_device_id vmbus_device_null = {
static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv,
struct hv_device *dev)
{
- const uuid_le *guid = &dev->dev_type;
+ const guid_t *guid = &dev->dev_type;
const struct hv_vmbus_device_id *id;
/* When driver_override is set, only bind to the matching driver */
@@ -695,7 +714,7 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv,
}
/* vmbus_add_dynid - add a new device ID to this driver and re-probe devices */
-static int vmbus_add_dynid(struct hv_driver *drv, uuid_le *guid)
+static int vmbus_add_dynid(struct hv_driver *drv, guid_t *guid)
{
struct vmbus_dynid *dynid;
@@ -733,10 +752,10 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf,
size_t count)
{
struct hv_driver *drv = drv_to_hv_drv(driver);
- uuid_le guid;
+ guid_t guid;
ssize_t retval;
- retval = uuid_le_to_bin(buf, &guid);
+ retval = guid_parse(buf, &guid);
if (retval)
return retval;
@@ -760,10 +779,10 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
{
struct hv_driver *drv = drv_to_hv_drv(driver);
struct vmbus_dynid *dynid, *n;
- uuid_le guid;
+ guid_t guid;
ssize_t retval;
- retval = uuid_le_to_bin(buf, &guid);
+ retval = guid_parse(buf, &guid);
if (retval)
return retval;
@@ -772,7 +791,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
struct hv_vmbus_device_id *id = &dynid->id;
- if (!uuid_le_cmp(id->guid, guid)) {
+ if (guid_equal(&id->guid, &guid)) {
list_del(&dynid->node);
kfree(dynid);
retval = count;
@@ -1465,6 +1484,38 @@ static ssize_t channel_events_show(const struct vmbus_channel *channel, char *bu
}
static VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL);
+static ssize_t channel_intr_in_full_show(const struct vmbus_channel *channel,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)channel->intr_in_full);
+}
+static VMBUS_CHAN_ATTR(intr_in_full, 0444, channel_intr_in_full_show, NULL);
+
+static ssize_t channel_intr_out_empty_show(const struct vmbus_channel *channel,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)channel->intr_out_empty);
+}
+static VMBUS_CHAN_ATTR(intr_out_empty, 0444, channel_intr_out_empty_show, NULL);
+
+static ssize_t channel_out_full_first_show(const struct vmbus_channel *channel,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)channel->out_full_first);
+}
+static VMBUS_CHAN_ATTR(out_full_first, 0444, channel_out_full_first_show, NULL);
+
+static ssize_t channel_out_full_total_show(const struct vmbus_channel *channel,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)channel->out_full_total);
+}
+static VMBUS_CHAN_ATTR(out_full_total, 0444, channel_out_full_total_show, NULL);
+
static ssize_t subchannel_monitor_id_show(const struct vmbus_channel *channel,
char *buf)
{
@@ -1490,6 +1541,10 @@ static struct attribute *vmbus_chan_attrs[] = {
&chan_attr_latency.attr,
&chan_attr_interrupts.attr,
&chan_attr_events.attr,
+ &chan_attr_intr_in_full.attr,
+ &chan_attr_intr_out_empty.attr,
+ &chan_attr_out_full_first.attr,
+ &chan_attr_out_full_total.attr,
&chan_attr_monitor_id.attr,
&chan_attr_subchannel_id.attr,
NULL
@@ -1525,8 +1580,8 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
* vmbus_device_create - Creates and registers a new child device
* on the vmbus.
*/
-struct hv_device *vmbus_device_create(const uuid_le *type,
- const uuid_le *instance,
+struct hv_device *vmbus_device_create(const guid_t *type,
+ const guid_t *instance,
struct vmbus_channel *channel)
{
struct hv_device *child_device_obj;
@@ -1538,12 +1593,10 @@ struct hv_device *vmbus_device_create(const uuid_le *type,
}
child_device_obj->channel = channel;
- memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
- memcpy(&child_device_obj->dev_instance, instance,
- sizeof(uuid_le));
+ guid_copy(&child_device_obj->dev_type, type);
+ guid_copy(&child_device_obj->dev_instance, instance);
child_device_obj->vendor_id = 0x1414; /* MSFT vendor ID */
-
return child_device_obj;
}
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 76f0a5c01e8a..4aeba29b4629 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -19,6 +19,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -54,10 +55,11 @@ struct ad7418_data {
u16 in[4];
};
-static struct ad7418_data *ad7418_update_device(struct device *dev)
+static int ad7418_update_device(struct device *dev)
{
struct ad7418_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
+ s32 val;
mutex_lock(&data->lock);
@@ -67,47 +69,74 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
int i, ch;
/* read config register and clear channel bits */
- cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+ val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+ if (val < 0)
+ goto abort;
+
+ cfg = val;
cfg &= 0x1F;
- i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
+ val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
cfg | AD7418_CH_TEMP);
+ if (val < 0)
+ goto abort;
+
udelay(30);
for (i = 0; i < 3; i++) {
- data->temp[i] =
- i2c_smbus_read_word_swapped(client,
- AD7418_REG_TEMP[i]);
+ val = i2c_smbus_read_word_swapped(client,
+ AD7418_REG_TEMP[i]);
+ if (val < 0)
+ goto abort;
+
+ data->temp[i] = val;
}
for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
- i2c_smbus_write_byte_data(client,
- AD7418_REG_CONF,
+ val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
cfg | AD7418_REG_ADC_CH(ch));
+ if (val < 0)
+ goto abort;
udelay(15);
- data->in[data->adc_max - 1 - i] =
- i2c_smbus_read_word_swapped(client,
- AD7418_REG_ADC);
+ val = i2c_smbus_read_word_swapped(client,
+ AD7418_REG_ADC);
+ if (val < 0)
+ goto abort;
+
+ data->in[data->adc_max - 1 - i] = val;
}
/* restore old configuration value */
- i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
+ val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF,
+ cfg);
+ if (val < 0)
+ goto abort;
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->lock);
+ return 0;
- return data;
+abort:
+ data->valid = 0;
+ mutex_unlock(&data->lock);
+ return val;
}
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct ad7418_data *data = ad7418_update_device(dev);
+ struct ad7418_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ ret = ad7418_update_device(dev);
+ if (ret < 0)
+ return ret;
+
return sprintf(buf, "%d\n",
LM75_TEMP_FROM_REG(data->temp[attr->index]));
}
@@ -116,7 +145,12 @@ static ssize_t adc_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct ad7418_data *data = ad7418_update_device(dev);
+ struct ad7418_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ ret = ad7418_update_device(dev);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n",
((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
@@ -220,7 +254,10 @@ static int ad7418_probe(struct i2c_client *client,
mutex_init(&data->lock);
data->client = client;
- data->type = id->driver_data;
+ if (dev->of_node)
+ data->type = (enum chips)of_device_get_match_data(dev);
+ else
+ data->type = id->driver_data;
switch (data->type) {
case ad7416:
@@ -258,9 +295,18 @@ static const struct i2c_device_id ad7418_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ad7418_id);
+static const struct of_device_id ad7418_dt_ids[] = {
+ { .compatible = "adi,ad7416", .data = (void *)ad7416, },
+ { .compatible = "adi,ad7417", .data = (void *)ad7417, },
+ { .compatible = "adi,ad7418", .data = (void *)ad7418, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7418_dt_ids);
+
static struct i2c_driver ad7418_driver = {
.driver = {
.name = "ad7418",
+ .of_match_table = ad7418_dt_ids,
},
.probe = ad7418_probe,
.id_table = ad7418_id,
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 8c5cdb560258..e561279aea21 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
*
@@ -19,10 +20,6 @@
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
@@ -111,7 +108,7 @@ static const u8 ADM1029_REG_FAN_DIV[] = {
struct adm1029_data {
struct i2c_client *client;
- struct mutex update_lock;
+ struct mutex update_lock; /* protect register access */
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -134,8 +131,7 @@ static struct adm1029_data *adm1029_update_device(struct device *dev)
* Use the "cache" Luke, don't recheck values
* if there are already checked not a long time later
*/
- if (time_after(jiffies, data->last_updated + HZ * 2)
- || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int nr;
dev_dbg(&client->dev, "Updating adm1029 data\n");
@@ -174,6 +170,7 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm1029_data *data = adm1029_update_device(dev);
+
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
@@ -183,9 +180,10 @@ show_fan(struct device *dev, struct device_attribute *devattr, char *buf)
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm1029_data *data = adm1029_update_device(dev);
u16 val;
- if (data->fan[attr->index] == 0
- || (data->fan_div[attr->index] & 0xC0) == 0
- || data->fan[attr->index] == 255) {
+
+ if (data->fan[attr->index] == 0 ||
+ (data->fan_div[attr->index] & 0xC0) == 0 ||
+ data->fan[attr->index] == 255) {
return sprintf(buf, "0\n");
}
@@ -199,13 +197,14 @@ show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm1029_data *data = adm1029_update_device(dev);
+
if ((data->fan_div[attr->index] & 0xC0) == 0)
return sprintf(buf, "0\n");
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
}
-static ssize_t set_fan_div(struct device *dev,
- struct device_attribute *devattr, const char *buf, size_t count)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct adm1029_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -213,6 +212,7 @@ static ssize_t set_fan_div(struct device *dev,
u8 reg;
long val;
int ret = kstrtol(buf, 10, &val);
+
if (ret < 0)
return ret;
@@ -253,32 +253,27 @@ static ssize_t set_fan_div(struct device *dev,
return count;
}
-/*
- * Access rights on sysfs. S_IRUGO: Is Readable by User, Group and Others
- * S_IWUSR: Is Writable by User.
- */
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+/* Access rights on sysfs. */
+static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, 0444, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, 0444, show_temp, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp1_max, 0444, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max, 0444, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp3_max, 0444, show_temp, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp1_min, 0444, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp2_min, 0444, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp3_min, 0444, show_temp, NULL, 8);
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_input, 0444, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, 0444, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_min, 0444, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan2_min, 0444, show_fan, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
- show_fan_div, set_fan_div, 0);
-static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
- show_fan_div, set_fan_div, 1);
+static SENSOR_DEVICE_ATTR(fan1_div, 0644, show_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, 0644, show_fan_div, set_fan_div, 1);
static struct attribute *adm1029_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -327,10 +322,10 @@ static int adm1029_detect(struct i2c_client *client,
temp_devices_installed = i2c_smbus_read_byte_data(client,
ADM1029_REG_TEMP_DEVICES_INSTALLED);
nb_fan_support = i2c_smbus_read_byte_data(client,
- ADM1029_REG_NB_FAN_SUPPORT);
+ ADM1029_REG_NB_FAN_SUPPORT);
/* 0x41 is Analog Devices */
- if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01
- || nb_fan_support != 0x03)
+ if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 ||
+ nb_fan_support != 0x03)
return -ENODEV;
if ((chip_id & 0xF0) != 0x00) {
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index b0211f731251..030f5d49c061 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -448,6 +448,7 @@ static const char *voltage_label(struct adt7462_data *data, int which)
case 3:
return "+1.5V";
}
+ /* fall through */
case 2:
if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
return "+12V3";
@@ -505,6 +506,7 @@ static const char *voltage_label(struct adt7462_data *data, int which)
case 3:
return "+1.5";
}
+ /* fall through */
case 11:
if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
ADT7462_PIN28_VOLT &&
@@ -542,6 +544,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which)
case 3:
return 7800;
}
+ /* fall through */
case 2:
if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
return 62500;
@@ -599,6 +602,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which)
case 3:
return 7800;
}
+ /* fall through */
case 11:
case 12:
if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 68c9a6664557..a6a38ceec174 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -82,9 +82,15 @@ static bool disallow_fan_support;
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
#define I8K_HWMON_HAVE_TEMP3 (1 << 2)
#define I8K_HWMON_HAVE_TEMP4 (1 << 3)
-#define I8K_HWMON_HAVE_FAN1 (1 << 4)
-#define I8K_HWMON_HAVE_FAN2 (1 << 5)
-#define I8K_HWMON_HAVE_FAN3 (1 << 6)
+#define I8K_HWMON_HAVE_TEMP5 (1 << 4)
+#define I8K_HWMON_HAVE_TEMP6 (1 << 5)
+#define I8K_HWMON_HAVE_TEMP7 (1 << 6)
+#define I8K_HWMON_HAVE_TEMP8 (1 << 7)
+#define I8K_HWMON_HAVE_TEMP9 (1 << 8)
+#define I8K_HWMON_HAVE_TEMP10 (1 << 9)
+#define I8K_HWMON_HAVE_FAN1 (1 << 10)
+#define I8K_HWMON_HAVE_FAN2 (1 << 11)
+#define I8K_HWMON_HAVE_FAN3 (1 << 12)
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
@@ -737,6 +743,18 @@ static SENSOR_DEVICE_ATTR_RO(temp3_input, i8k_hwmon_temp, 2);
static SENSOR_DEVICE_ATTR_RO(temp3_label, i8k_hwmon_temp_label, 2);
static SENSOR_DEVICE_ATTR_RO(temp4_input, i8k_hwmon_temp, 3);
static SENSOR_DEVICE_ATTR_RO(temp4_label, i8k_hwmon_temp_label, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_input, i8k_hwmon_temp, 4);
+static SENSOR_DEVICE_ATTR_RO(temp5_label, i8k_hwmon_temp_label, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_input, i8k_hwmon_temp, 5);
+static SENSOR_DEVICE_ATTR_RO(temp6_label, i8k_hwmon_temp_label, 5);
+static SENSOR_DEVICE_ATTR_RO(temp7_input, i8k_hwmon_temp, 6);
+static SENSOR_DEVICE_ATTR_RO(temp7_label, i8k_hwmon_temp_label, 6);
+static SENSOR_DEVICE_ATTR_RO(temp8_input, i8k_hwmon_temp, 7);
+static SENSOR_DEVICE_ATTR_RO(temp8_label, i8k_hwmon_temp_label, 7);
+static SENSOR_DEVICE_ATTR_RO(temp9_input, i8k_hwmon_temp, 8);
+static SENSOR_DEVICE_ATTR_RO(temp9_label, i8k_hwmon_temp_label, 8);
+static SENSOR_DEVICE_ATTR_RO(temp10_input, i8k_hwmon_temp, 9);
+static SENSOR_DEVICE_ATTR_RO(temp10_label, i8k_hwmon_temp_label, 9);
static SENSOR_DEVICE_ATTR_RO(fan1_input, i8k_hwmon_fan, 0);
static SENSOR_DEVICE_ATTR_RO(fan1_label, i8k_hwmon_fan_label, 0);
static SENSOR_DEVICE_ATTR_RW(pwm1, i8k_hwmon_pwm, 0);
@@ -756,15 +774,27 @@ static struct attribute *i8k_attrs[] = {
&sensor_dev_attr_temp3_label.dev_attr.attr, /* 5 */
&sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */
&sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */
- &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */
- &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */
- &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */
- &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */
- &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */
- &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */
- &sensor_dev_attr_fan3_input.dev_attr.attr, /* 14 */
- &sensor_dev_attr_fan3_label.dev_attr.attr, /* 15 */
- &sensor_dev_attr_pwm3.dev_attr.attr, /* 16 */
+ &sensor_dev_attr_temp5_input.dev_attr.attr, /* 8 */
+ &sensor_dev_attr_temp5_label.dev_attr.attr, /* 9 */
+ &sensor_dev_attr_temp6_input.dev_attr.attr, /* 10 */
+ &sensor_dev_attr_temp6_label.dev_attr.attr, /* 11 */
+ &sensor_dev_attr_temp7_input.dev_attr.attr, /* 12 */
+ &sensor_dev_attr_temp7_label.dev_attr.attr, /* 13 */
+ &sensor_dev_attr_temp8_input.dev_attr.attr, /* 14 */
+ &sensor_dev_attr_temp8_label.dev_attr.attr, /* 15 */
+ &sensor_dev_attr_temp9_input.dev_attr.attr, /* 16 */
+ &sensor_dev_attr_temp9_label.dev_attr.attr, /* 17 */
+ &sensor_dev_attr_temp10_input.dev_attr.attr, /* 18 */
+ &sensor_dev_attr_temp10_label.dev_attr.attr, /* 19 */
+ &sensor_dev_attr_fan1_input.dev_attr.attr, /* 20 */
+ &sensor_dev_attr_fan1_label.dev_attr.attr, /* 21 */
+ &sensor_dev_attr_pwm1.dev_attr.attr, /* 22 */
+ &sensor_dev_attr_fan2_input.dev_attr.attr, /* 23 */
+ &sensor_dev_attr_fan2_label.dev_attr.attr, /* 24 */
+ &sensor_dev_attr_pwm2.dev_attr.attr, /* 25 */
+ &sensor_dev_attr_fan3_input.dev_attr.attr, /* 26 */
+ &sensor_dev_attr_fan3_label.dev_attr.attr, /* 27 */
+ &sensor_dev_attr_pwm3.dev_attr.attr, /* 28 */
NULL
};
@@ -788,13 +818,32 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
if (index >= 6 && index <= 7 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
return 0;
- if (index >= 8 && index <= 10 &&
+ if (index >= 8 && index <= 9 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP5))
+ return 0;
+ if (index >= 10 && index <= 11 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP6))
+ return 0;
+ if (index >= 12 && index <= 13 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP7))
+ return 0;
+ if (index >= 14 && index <= 15 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP8))
+ return 0;
+ if (index >= 16 && index <= 17 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP9))
+ return 0;
+ if (index >= 18 && index <= 19 &&
+ !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP10))
+ return 0;
+
+ if (index >= 20 && index <= 22 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
return 0;
- if (index >= 11 && index <= 13 &&
+ if (index >= 23 && index <= 25 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
return 0;
- if (index >= 14 && index <= 16 &&
+ if (index >= 26 && index <= 28 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN3))
return 0;
@@ -827,6 +876,24 @@ static int __init i8k_init_hwmon(void)
err = i8k_get_temp_type(3);
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
+ err = i8k_get_temp_type(4);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP5;
+ err = i8k_get_temp_type(5);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP6;
+ err = i8k_get_temp_type(6);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP7;
+ err = i8k_get_temp_type(7);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP8;
+ err = i8k_get_temp_type(8);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP9;
+ err = i8k_get_temp_type(9);
+ if (err >= 0)
+ i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP10;
/* First fan attributes, if fan status or type is OK */
err = i8k_get_fan_status(0);
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index ca54ce5c8e10..83023798e489 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2455,7 +2455,7 @@ static int f71882fg_probe(struct platform_device *pdev)
case f71869a:
/* These always have signed auto point temps */
data->auto_point_temp_signed = 1;
- /* Fall through to select correct fan/pwm reg bank! */
+ /* Fall through - to select correct fan/pwm reg bank! */
case f71889fg:
case f71889ed:
case f71889a:
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index b267510daeb2..b7e453298409 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -264,7 +264,7 @@ show(RAW, alarms, alarms);
show(BOOL, beep_enable, beep_enable);
show(BEEP_MASK, beep_mask, beep_mask);
-static ssize_t show_fan_input(struct device *dev,
+static ssize_t fan_input_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = to_sensor_dev_attr(attr)->index;
@@ -273,8 +273,8 @@ static ssize_t show_fan_input(struct device *dev,
DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = to_sensor_dev_attr(attr)->index;
struct gl518_data *data = gl518_update_device(dev);
@@ -282,8 +282,8 @@ static ssize_t show_fan_min(struct device *dev,
DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_div(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = to_sensor_dev_attr(attr)->index;
struct gl518_data *data = gl518_update_device(dev);
@@ -350,8 +350,9 @@ set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT);
set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct gl518_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -383,8 +384,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_div_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct gl518_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -427,40 +429,36 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
return count;
}
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1);
-static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO,
- show_temp_hyst1, set_temp_hyst1);
-static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO,
- show_fan_min, set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO,
- show_fan_min, set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO,
- show_fan_div, set_fan_div, 0);
-static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO,
- show_fan_div, set_fan_div, 1);
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
-static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
-static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
-static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);
-static DEVICE_ATTR(in0_min, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0);
-static DEVICE_ATTR(in1_min, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1);
-static DEVICE_ATTR(in2_min, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2);
-static DEVICE_ATTR(in3_min, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3);
-static DEVICE_ATTR(in0_max, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0);
-static DEVICE_ATTR(in1_max, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1);
-static DEVICE_ATTR(in2_max, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2);
-static DEVICE_ATTR(in3_max, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3);
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO,
- show_beep_enable, set_beep_enable);
-static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO,
- show_beep_mask, set_beep_mask);
-
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static DEVICE_ATTR(temp1_input, 0444, show_temp_input1, NULL);
+static DEVICE_ATTR(temp1_max, 0644, show_temp_max1, set_temp_max1);
+static DEVICE_ATTR(temp1_max_hyst, 0644,
+ show_temp_hyst1, set_temp_hyst1);
+static DEVICE_ATTR(fan1_auto, 0644, show_fan_auto1, set_fan_auto1);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
+static DEVICE_ATTR(in0_input, 0444, show_in_input0, NULL);
+static DEVICE_ATTR(in1_input, 0444, show_in_input1, NULL);
+static DEVICE_ATTR(in2_input, 0444, show_in_input2, NULL);
+static DEVICE_ATTR(in3_input, 0444, show_in_input3, NULL);
+static DEVICE_ATTR(in0_min, 0644, show_in_min0, set_in_min0);
+static DEVICE_ATTR(in1_min, 0644, show_in_min1, set_in_min1);
+static DEVICE_ATTR(in2_min, 0644, show_in_min2, set_in_min2);
+static DEVICE_ATTR(in3_min, 0644, show_in_min3, set_in_min3);
+static DEVICE_ATTR(in0_max, 0644, show_in_max0, set_in_max0);
+static DEVICE_ATTR(in1_max, 0644, show_in_max1, set_in_max1);
+static DEVICE_ATTR(in2_max, 0644, show_in_max2, set_in_max2);
+static DEVICE_ATTR(in3_max, 0644, show_in_max3, set_in_max3);
+static DEVICE_ATTR(alarms, 0444, show_alarms, NULL);
+static DEVICE_ATTR(beep_enable, 0644,
+ show_beep_enable, set_beep_enable);
+static DEVICE_ATTR(beep_mask, 0644,
+ show_beep_mask, set_beep_mask);
+
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -468,24 +466,24 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 6);
-static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t beep_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
struct gl518_data *data = gl518_update_device(dev);
return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
}
-static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t beep_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct gl518_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -511,13 +509,13 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0);
-static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1);
-static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2);
-static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3);
-static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4);
-static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5);
-static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6);
+static SENSOR_DEVICE_ATTR_RW(in0_beep, beep, 0);
+static SENSOR_DEVICE_ATTR_RW(in1_beep, beep, 1);
+static SENSOR_DEVICE_ATTR_RW(in2_beep, beep, 2);
+static SENSOR_DEVICE_ATTR_RW(in3_beep, beep, 3);
+static SENSOR_DEVICE_ATTR_RW(temp1_beep, beep, 4);
+static SENSOR_DEVICE_ATTR_RW(fan1_beep, beep, 5);
+static SENSOR_DEVICE_ATTR_RW(fan2_beep, beep, 6);
static struct attribute *gl518_attributes[] = {
&dev_attr_in3_input.attr,
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 4ff32ee67fb6..7d430ad955fe 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -216,8 +216,8 @@ static DEVICE_ATTR_RO(cpu0_vid);
#define IN_CLAMP(val) clamp_val(val, 0, 255 * 19)
#define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19)
-static ssize_t get_in_input(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t in_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -229,8 +229,8 @@ static ssize_t get_in_input(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", IN_FROM_REG(r));
}
-static ssize_t get_in_min(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t in_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -242,8 +242,8 @@ static ssize_t get_in_min(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", IN_FROM_REG(r));
}
-static ssize_t get_in_max(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t in_max_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -255,8 +255,8 @@ static ssize_t get_in_max(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", IN_FROM_REG(r));
}
-static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t in_min_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -289,8 +289,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t in_max_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -323,31 +323,21 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4);
-static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
- get_in_min, set_in_min, 0);
-static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
- get_in_min, set_in_min, 1);
-static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
- get_in_min, set_in_min, 2);
-static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
- get_in_min, set_in_min, 3);
-static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
- get_in_min, set_in_min, 4);
-static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
- get_in_max, set_in_max, 0);
-static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
- get_in_max, set_in_max, 1);
-static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
- get_in_max, set_in_max, 2);
-static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
- get_in_max, set_in_max, 3);
-static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
- get_in_max, set_in_max, 4);
+static SENSOR_DEVICE_ATTR_RO(in0_input, in_input, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4);
+static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
+static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
+static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
+static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
+static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
+static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
+static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
+static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
+static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
+static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
#define DIV_FROM_REG(val) (1 << (val))
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div))))
@@ -359,8 +349,8 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
DIV_ROUND_CLOSEST(480000, \
FAN_CLAMP(val, div) << (div)))
-static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t fan_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -369,8 +359,8 @@ static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
data->fan_div[n]));
}
-static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -379,8 +369,8 @@ static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr,
data->fan_div[n]));
}
-static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -395,8 +385,9 @@ static ssize_t fan1_off_show(struct device *dev,
return sprintf(buf, "%d\n", data->fan_off);
}
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -434,8 +425,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_div_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -508,24 +500,20 @@ static ssize_t fan1_off_store(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
- get_fan_min, set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
- get_fan_min, set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
- get_fan_div, set_fan_div, 0);
-static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
- get_fan_div, set_fan_div, 1);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
static DEVICE_ATTR_RW(fan1_off);
#define TEMP_FROM_REG(val) (((val) - 130) * 1000)
#define TEMP_CLAMP(val) clamp_val(val, -130000, 125000)
#define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130)
-static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t temp_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -533,8 +521,8 @@ static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n]));
}
-static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t temp_max_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -542,8 +530,8 @@ static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n]));
}
-static ssize_t get_temp_max_hyst(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp_max_hyst_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int n = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -551,8 +539,9 @@ static ssize_t get_temp_max_hyst(struct device *dev,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n]));
}
-static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_max_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -571,8 +560,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
- *attr, const char *buf, size_t count)
+static ssize_t temp_max_hyst_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -592,16 +582,12 @@ static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
- get_temp_max, set_temp_max, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
- get_temp_max, set_temp_max, 1);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
- get_temp_max_hyst, set_temp_max_hyst, 0);
-static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
- get_temp_max_hyst, set_temp_max_hyst, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_max_hyst, 1);
static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -674,8 +660,8 @@ static DEVICE_ATTR_RO(alarms);
static DEVICE_ATTR_RW(beep_enable);
static DEVICE_ATTR_RW(beep_mask);
-static ssize_t get_alarm(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int bit_nr = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -683,18 +669,18 @@ static ssize_t get_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1);
}
-static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7);
-static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 7);
+static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 7);
-static ssize_t get_beep(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t beep_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
struct gl520_data *data = gl520_update_device(dev);
@@ -702,8 +688,8 @@ static ssize_t get_beep(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1);
}
-static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t beep_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct gl520_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -729,15 +715,15 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0);
-static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1);
-static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2);
-static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3);
-static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4);
-static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5);
-static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6);
-static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7);
-static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7);
+static SENSOR_DEVICE_ATTR_RW(in0_beep, beep, 0);
+static SENSOR_DEVICE_ATTR_RW(in1_beep, beep, 1);
+static SENSOR_DEVICE_ATTR_RW(in2_beep, beep, 2);
+static SENSOR_DEVICE_ATTR_RW(in3_beep, beep, 3);
+static SENSOR_DEVICE_ATTR_RW(temp1_beep, beep, 4);
+static SENSOR_DEVICE_ATTR_RW(fan1_beep, beep, 5);
+static SENSOR_DEVICE_ATTR_RW(fan2_beep, beep, 6);
+static SENSOR_DEVICE_ATTR_RW(temp2_beep, beep, 7);
+static SENSOR_DEVICE_ATTR_RW(in4_beep, beep, 7);
static struct attribute *gl520_attributes[] = {
&dev_attr_cpu0_vid.attr,
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index a3974cddef07..f1bf67aca9e8 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -307,7 +307,7 @@ static DEVICE_ATTR_RO(pwm1_mode);
static DEVICE_ATTR_RO(fan1_min);
static DEVICE_ATTR_RO(fan1_max);
static DEVICE_ATTR_RO(fan1_input);
-static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, fan1_input_show, set_rpm);
+static DEVICE_ATTR(fan1_target, 0644, fan1_input_show, set_rpm);
static umode_t gpio_fan_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
index 0ae1ee1dbf76..d167fcfec765 100644
--- a/drivers/hwmon/hih6130.c
+++ b/drivers/hwmon/hih6130.c
@@ -171,7 +171,7 @@ out:
* Will be called on read access to temp1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t hih6130_show_temperature(struct device *dev,
+static ssize_t hih6130_temperature_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -193,7 +193,7 @@ static ssize_t hih6130_show_temperature(struct device *dev,
* Will be called on read access to humidity1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t hih6130_show_humidity(struct device *dev,
+static ssize_t hih6130_humidity_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hih6130 *hih6130 = dev_get_drvdata(dev);
@@ -206,10 +206,8 @@ static ssize_t hih6130_show_humidity(struct device *dev,
}
/* sysfs attributes */
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, hih6130_show_temperature,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, hih6130_show_humidity,
- NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, hih6130_temperature, 0);
+static SENSOR_DEVICE_ATTR_RO(humidity1_input, hih6130_humidity, 0);
static struct attribute *hih6130_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -254,8 +252,17 @@ static const struct i2c_device_id hih6130_id[] = {
};
MODULE_DEVICE_TABLE(i2c, hih6130_id);
+static const struct of_device_id hih6130_of_match[] = {
+ { .compatible = "honeywell,hih6130", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hih6130_of_match);
+
static struct i2c_driver hih6130_driver = {
- .driver.name = "hih6130",
+ .driver = {
+ .name = "hih6130",
+ .of_match_table = of_match_ptr(hih6130_of_match),
+ },
.probe = hih6130_probe,
.id_table = hih6130_id,
};
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 36ed50d4b276..c22dc1e07911 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -278,10 +278,10 @@ static struct attribute *hwmon_genattr(struct device *dev,
if (!mode)
return ERR_PTR(-ENOENT);
- if ((mode & S_IRUGO) && ((is_string && !ops->read_string) ||
+ if ((mode & 0444) && ((is_string && !ops->read_string) ||
(!is_string && !ops->read)))
return ERR_PTR(-EINVAL);
- if ((mode & S_IWUGO) && !ops->write)
+ if ((mode & 0222) && !ops->write)
return ERR_PTR(-EINVAL);
hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL);
diff --git a/drivers/hwmon/i5500_temp.c b/drivers/hwmon/i5500_temp.c
index 400e0675a90b..a51038c6597d 100644
--- a/drivers/hwmon/i5500_temp.c
+++ b/drivers/hwmon/i5500_temp.c
@@ -58,7 +58,7 @@ static ssize_t temp1_input_show(struct device *dev,
return sprintf(buf, "%ld\n", temp);
}
-static ssize_t show_thresh(struct device *dev,
+static ssize_t thresh_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev->parent);
@@ -72,7 +72,7 @@ static ssize_t show_thresh(struct device *dev,
return sprintf(buf, "%ld\n", temp);
}
-static ssize_t show_alarm(struct device *dev,
+static ssize_t alarm_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev->parent);
@@ -84,11 +84,11 @@ static ssize_t show_alarm(struct device *dev,
}
static DEVICE_ATTR_RO(temp1_input);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_thresh, NULL, 0xE2);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_thresh, NULL, 0xEC);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_thresh, NULL, 0xEE);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit, thresh, 0xE2);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, thresh, 0xEC);
+static SENSOR_DEVICE_ATTR_RO(temp1_max, thresh, 0xEE);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
static struct attribute *i5500_temp_attrs[] = {
&dev_attr_temp1_input.attr,
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index a4edc43dd060..2cf73d8eec1c 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -296,7 +296,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_label", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0444;
iattr->s_attr.dev_attr.show = show_label;
iattr->s_attr.index = k;
sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
@@ -311,7 +311,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_input", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0444;
iattr->s_attr.dev_attr.show = show_amb_temp;
iattr->s_attr.index = k;
sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
@@ -326,7 +326,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_min", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0644;
iattr->s_attr.dev_attr.show = show_amb_min;
iattr->s_attr.dev_attr.store = store_amb_min;
iattr->s_attr.index = k;
@@ -342,7 +342,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_mid", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0644;
iattr->s_attr.dev_attr.show = show_amb_mid;
iattr->s_attr.dev_attr.store = store_amb_mid;
iattr->s_attr.index = k;
@@ -358,7 +358,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_max", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0644;
iattr->s_attr.dev_attr.show = show_amb_max;
iattr->s_attr.dev_attr.store = store_amb_max;
iattr->s_attr.index = k;
@@ -374,7 +374,7 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
"temp%d_alarm", d);
iattr->s_attr.dev_attr.attr.name = iattr->name;
- iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.attr.mode = 0444;
iattr->s_attr.dev_attr.show = show_amb_alarm;
iattr->s_attr.index = k;
sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 9e92673f6913..db63c1295cb2 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -813,25 +813,24 @@ static void aem_bmc_gone(int iface)
/* sysfs support functions */
/* AEM device name */
-static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct aem_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major);
}
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(name, name, 0);
/* AEM device version */
-static ssize_t show_version(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
+static ssize_t version_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct aem_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor);
}
-static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(version, version, 0);
/* Display power use */
static ssize_t aem_show_power(struct device *dev,
@@ -931,7 +930,7 @@ static int aem_register_sensors(struct aem_data *data,
while (ro->label) {
sysfs_attr_init(&sensors->dev_attr.attr);
sensors->dev_attr.attr.name = ro->label;
- sensors->dev_attr.attr.mode = S_IRUGO;
+ sensors->dev_attr.attr.mode = 0444;
sensors->dev_attr.show = ro->show;
sensors->index = ro->index;
@@ -948,7 +947,7 @@ static int aem_register_sensors(struct aem_data *data,
while (rw->label) {
sysfs_attr_init(&sensors->dev_attr.attr);
sensors->dev_attr.attr.name = rw->label;
- sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
+ sensors->dev_attr.attr.mode = 0644;
sensors->dev_attr.show = rw->show;
sensors->dev_attr.store = rw->set;
sensors->index = rw->index;
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index bb17a29af64c..5fd70faf0d16 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -269,12 +269,12 @@ static struct ibmpex_bmc_data *get_bmc_data(int iface)
return NULL;
}
-static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
return sprintf(buf, "%s\n", DRVNAME);
}
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(name, name, 0);
static ssize_t ibmpex_show_sensor(struct device *dev,
struct device_attribute *devattr,
@@ -289,10 +289,9 @@ static ssize_t ibmpex_show_sensor(struct device *dev,
data->sensors[attr->index].values[attr->nr] * mult);
}
-static ssize_t ibmpex_reset_high_low(struct device *dev,
+static ssize_t ibmpex_high_low_store(struct device *dev,
struct device_attribute *devattr,
- const char *buf,
- size_t count)
+ const char *buf, size_t count)
{
struct ibmpex_bmc_data *data = dev_get_drvdata(dev);
@@ -301,8 +300,7 @@ static ssize_t ibmpex_reset_high_low(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(reset_high_low, S_IWUSR, NULL,
- ibmpex_reset_high_low, 0);
+static SENSOR_DEVICE_ATTR_WO(reset_high_low, ibmpex_high_low, 0);
static int is_power_sensor(const char *sensor_id, int len)
{
@@ -358,7 +356,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type,
sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr);
data->sensors[sensor].attr[func].dev_attr.attr.name = n;
- data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO;
+ data->sensors[sensor].attr[func].dev_attr.attr.mode = 0444;
data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor;
data->sensors[sensor].attr[func].index = sensor;
data->sensors[sensor].attr[func].nr = func;
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index eed66e533ee2..5c3c08449de7 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -129,7 +129,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
return -ENOMEM;
a->dev_attr.show = iio_hwmon_read_val;
- a->dev_attr.attr.mode = S_IRUGO;
+ a->dev_attr.attr.mode = 0444;
a->index = i;
st->attrs[i] = &a->dev_attr.attr;
}
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index aa0768ce8aea..e3854463db84 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -230,9 +230,9 @@ static u16 ina209_reg_from_interval(u16 config, long interval)
return (config & 0xf807) | (adc << 3) | (adc << 7);
}
-static ssize_t ina209_set_interval(struct device *dev,
- struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t ina209_interval_store(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
{
struct ina209_data *data = ina209_update_device(dev);
long val;
@@ -257,7 +257,7 @@ static ssize_t ina209_set_interval(struct device *dev,
return count;
}
-static ssize_t ina209_show_interval(struct device *dev,
+static ssize_t ina209_interval_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct ina209_data *data = dev_get_drvdata(dev);
@@ -279,10 +279,9 @@ static u16 ina209_reset_history_regs[] = {
INA209_POWER_PEAK
};
-static ssize_t ina209_reset_history(struct device *dev,
+static ssize_t ina209_history_store(struct device *dev,
struct device_attribute *da,
- const char *buf,
- size_t count)
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina209_data *data = dev_get_drvdata(dev);
@@ -306,10 +305,9 @@ static ssize_t ina209_reset_history(struct device *dev,
return count;
}
-static ssize_t ina209_set_value(struct device *dev,
- struct device_attribute *da,
- const char *buf,
- size_t count)
+static ssize_t ina209_value_store(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
{
struct ina209_data *data = ina209_update_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -337,9 +335,8 @@ abort:
return count;
}
-static ssize_t ina209_show_value(struct device *dev,
- struct device_attribute *da,
- char *buf)
+static ssize_t ina209_value_show(struct device *dev,
+ struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina209_data *data = ina209_update_device(dev);
@@ -352,9 +349,8 @@ static ssize_t ina209_show_value(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%ld\n", val);
}
-static ssize_t ina209_show_alarm(struct device *dev,
- struct device_attribute *da,
- char *buf)
+static ssize_t ina209_alarm_show(struct device *dev,
+ struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina209_data *data = ina209_update_device(dev);
@@ -374,82 +370,65 @@ static ssize_t ina209_show_alarm(struct device *dev,
}
/* Shunt voltage, history, limits, alarms */
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE);
-static SENSOR_DEVICE_ATTR(in0_input_highest, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE_POS_PEAK);
-static SENSOR_DEVICE_ATTR(in0_input_lowest, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE_NEG_PEAK);
-static SENSOR_DEVICE_ATTR(in0_reset_history, S_IWUSR, NULL,
- ina209_reset_history, (1 << 0) | (1 << 1));
-static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_SHUNT_VOLTAGE_POS_WARN);
-static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_SHUNT_VOLTAGE_NEG_WARN);
-static SENSOR_DEVICE_ATTR(in0_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_CRITICAL_DAC_POS);
-static SENSOR_DEVICE_ATTR(in0_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_CRITICAL_DAC_NEG);
-
-static SENSOR_DEVICE_ATTR(in0_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 11);
-static SENSOR_DEVICE_ATTR(in0_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 12);
-static SENSOR_DEVICE_ATTR(in0_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 6);
-static SENSOR_DEVICE_ATTR(in0_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 7);
+static SENSOR_DEVICE_ATTR_RO(in0_input, ina209_value, INA209_SHUNT_VOLTAGE);
+static SENSOR_DEVICE_ATTR_RO(in0_input_highest, ina209_value,
+ INA209_SHUNT_VOLTAGE_POS_PEAK);
+static SENSOR_DEVICE_ATTR_RO(in0_input_lowest, ina209_value,
+ INA209_SHUNT_VOLTAGE_NEG_PEAK);
+static SENSOR_DEVICE_ATTR_WO(in0_reset_history, ina209_history,
+ (1 << 0) | (1 << 1));
+static SENSOR_DEVICE_ATTR_RW(in0_max, ina209_value,
+ INA209_SHUNT_VOLTAGE_POS_WARN);
+static SENSOR_DEVICE_ATTR_RW(in0_min, ina209_value,
+ INA209_SHUNT_VOLTAGE_NEG_WARN);
+static SENSOR_DEVICE_ATTR_RW(in0_crit_max, ina209_value,
+ INA209_CRITICAL_DAC_POS);
+static SENSOR_DEVICE_ATTR_RW(in0_crit_min, ina209_value,
+ INA209_CRITICAL_DAC_NEG);
+
+static SENSOR_DEVICE_ATTR_RO(in0_min_alarm, ina209_alarm, 1 << 11);
+static SENSOR_DEVICE_ATTR_RO(in0_max_alarm, ina209_alarm, 1 << 12);
+static SENSOR_DEVICE_ATTR_RO(in0_crit_min_alarm, ina209_alarm, 1 << 6);
+static SENSOR_DEVICE_ATTR_RO(in0_crit_max_alarm, ina209_alarm, 1 << 7);
/* Bus voltage, history, limits, alarms */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE);
-static SENSOR_DEVICE_ATTR(in1_input_highest, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE_MAX_PEAK);
-static SENSOR_DEVICE_ATTR(in1_input_lowest, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE_MIN_PEAK);
-static SENSOR_DEVICE_ATTR(in1_reset_history, S_IWUSR, NULL,
- ina209_reset_history, (1 << 2) | (1 << 3));
-static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_OVER_WARN);
-static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_UNDER_WARN);
-static SENSOR_DEVICE_ATTR(in1_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_OVER_LIMIT);
-static SENSOR_DEVICE_ATTR(in1_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_UNDER_LIMIT);
-
-static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 14);
-static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 15);
-static SENSOR_DEVICE_ATTR(in1_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 9);
-static SENSOR_DEVICE_ATTR(in1_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 10);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ina209_value, INA209_BUS_VOLTAGE);
+static SENSOR_DEVICE_ATTR_RO(in1_input_highest, ina209_value,
+ INA209_BUS_VOLTAGE_MAX_PEAK);
+static SENSOR_DEVICE_ATTR_RO(in1_input_lowest, ina209_value,
+ INA209_BUS_VOLTAGE_MIN_PEAK);
+static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ina209_history,
+ (1 << 2) | (1 << 3));
+static SENSOR_DEVICE_ATTR_RW(in1_max, ina209_value,
+ INA209_BUS_VOLTAGE_OVER_WARN);
+static SENSOR_DEVICE_ATTR_RW(in1_min, ina209_value,
+ INA209_BUS_VOLTAGE_UNDER_WARN);
+static SENSOR_DEVICE_ATTR_RW(in1_crit_max, ina209_value,
+ INA209_BUS_VOLTAGE_OVER_LIMIT);
+static SENSOR_DEVICE_ATTR_RW(in1_crit_min, ina209_value,
+ INA209_BUS_VOLTAGE_UNDER_LIMIT);
+
+static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ina209_alarm, 1 << 14);
+static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ina209_alarm, 1 << 15);
+static SENSOR_DEVICE_ATTR_RO(in1_crit_min_alarm, ina209_alarm, 1 << 9);
+static SENSOR_DEVICE_ATTR_RO(in1_crit_max_alarm, ina209_alarm, 1 << 10);
/* Power */
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_POWER);
-static SENSOR_DEVICE_ATTR(power1_input_highest, S_IRUGO, ina209_show_value,
- NULL, INA209_POWER_PEAK);
-static SENSOR_DEVICE_ATTR(power1_reset_history, S_IWUSR, NULL,
- ina209_reset_history, 1 << 4);
-static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_POWER_WARN);
-static SENSOR_DEVICE_ATTR(power1_crit, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_POWER_OVER_LIMIT);
-
-static SENSOR_DEVICE_ATTR(power1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 13);
-static SENSOR_DEVICE_ATTR(power1_crit_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 8);
+static SENSOR_DEVICE_ATTR_RO(power1_input, ina209_value, INA209_POWER);
+static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ina209_value,
+ INA209_POWER_PEAK);
+static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ina209_history, 1 << 4);
+static SENSOR_DEVICE_ATTR_RW(power1_max, ina209_value, INA209_POWER_WARN);
+static SENSOR_DEVICE_ATTR_RW(power1_crit, ina209_value,
+ INA209_POWER_OVER_LIMIT);
+
+static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ina209_alarm, 1 << 13);
+static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina209_alarm, 1 << 8);
/* Current */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_CURRENT);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ina209_value, INA209_CURRENT);
-static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
- ina209_show_interval, ina209_set_interval, 0);
+static SENSOR_DEVICE_ATTR_RW(update_interval, ina209_interval, 0);
/*
* Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index e90ccac8bebb..3626b87a5fd2 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -111,6 +111,7 @@ struct ina3221_input {
* @inputs: Array of channel input source specific structures
* @lock: mutex lock to serialize sysfs attribute accesses
* @reg_config: Register value of INA3221_CONFIG
+ * @single_shot: running in single-shot operating mode
*/
struct ina3221_data {
struct device *pm_dev;
@@ -119,6 +120,8 @@ struct ina3221_data {
struct ina3221_input inputs[INA3221_NUM_CHANNELS];
struct mutex lock;
u32 reg_config;
+
+ bool single_shot;
};
static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
@@ -188,6 +191,11 @@ static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val)
if (!ina3221_is_enabled(ina, channel))
return -ENODATA;
+ /* Write CONFIG register to trigger a single-shot measurement */
+ if (ina->single_shot)
+ regmap_write(ina->regmap, INA3221_CONFIG,
+ ina->reg_config);
+
ret = ina3221_wait_for_data(ina);
if (ret)
return ret;
@@ -232,6 +240,11 @@ static int ina3221_read_curr(struct device *dev, u32 attr,
if (!ina3221_is_enabled(ina, channel))
return -ENODATA;
+ /* Write CONFIG register to trigger a single-shot measurement */
+ if (ina->single_shot)
+ regmap_write(ina->regmap, INA3221_CONFIG,
+ ina->reg_config);
+
ret = ina3221_wait_for_data(ina);
if (ret)
return ret;
@@ -499,7 +512,7 @@ static const struct hwmon_chip_info ina3221_chip_info = {
};
/* Extra attribute groups */
-static ssize_t ina3221_show_shunt(struct device *dev,
+static ssize_t ina3221_shunt_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
@@ -510,9 +523,9 @@ static ssize_t ina3221_show_shunt(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor);
}
-static ssize_t ina3221_set_shunt(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t ina3221_shunt_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
struct ina3221_data *ina = dev_get_drvdata(dev);
@@ -533,12 +546,9 @@ static ssize_t ina3221_set_shunt(struct device *dev,
}
/* shunt resistance */
-static SENSOR_DEVICE_ATTR(shunt1_resistor, S_IRUGO | S_IWUSR,
- ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL1);
-static SENSOR_DEVICE_ATTR(shunt2_resistor, S_IRUGO | S_IWUSR,
- ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL2);
-static SENSOR_DEVICE_ATTR(shunt3_resistor, S_IRUGO | S_IWUSR,
- ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL3);
+static SENSOR_DEVICE_ATTR_RW(shunt1_resistor, ina3221_shunt, INA3221_CHANNEL1);
+static SENSOR_DEVICE_ATTR_RW(shunt2_resistor, ina3221_shunt, INA3221_CHANNEL2);
+static SENSOR_DEVICE_ATTR_RW(shunt3_resistor, ina3221_shunt, INA3221_CHANNEL3);
static struct attribute *ina3221_attrs[] = {
&sensor_dev_attr_shunt1_resistor.dev_attr.attr,
@@ -617,6 +627,8 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
if (!np)
return 0;
+ ina->single_shot = of_property_read_bool(np, "ti,single-shot");
+
for_each_child_of_node(np, child) {
ret = ina3221_probe_child_from_dt(dev, child, ina);
if (ret)
@@ -666,6 +678,10 @@ static int ina3221_probe(struct i2c_client *client,
/* The driver will be reset, so use reset value */
ina->reg_config = INA3221_CONFIG_DEFAULT;
+ /* Clear continuous bit to use single-shot mode */
+ if (ina->single_shot)
+ ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS;
+
/* Disable channels if their inputs are disconnected */
for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
if (ina->inputs[i].disconnected)
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index e5234f953a6d..4fa482ae0eb5 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -390,21 +390,21 @@ static umode_t jc42_is_visible(const void *_data, enum hwmon_sensor_types type,
{
const struct jc42_data *data = _data;
unsigned int config = data->config;
- umode_t mode = S_IRUGO;
+ umode_t mode = 0444;
switch (attr) {
case hwmon_temp_min:
case hwmon_temp_max:
if (!(config & JC42_CFG_EVENT_LOCK))
- mode |= S_IWUSR;
+ mode |= 0200;
break;
case hwmon_temp_crit:
if (!(config & JC42_CFG_TCRIT_LOCK))
- mode |= S_IWUSR;
+ mode |= 0200;
break;
case hwmon_temp_crit_hyst:
if (!(config & (JC42_CFG_EVENT_LOCK | JC42_CFG_TCRIT_LOCK)))
- mode |= S_IWUSR;
+ mode |= 0200;
break;
case hwmon_temp_input:
case hwmon_temp_max_hyst:
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index e59f9113fb93..93a5d51f3c6d 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -109,8 +109,8 @@ static ssize_t name_show(struct device *dev, struct device_attribute
}
-static ssize_t show_temp(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute_2 *attr =
to_sensor_dev_attr_2(devattr);
@@ -129,10 +129,10 @@ static ssize_t show_temp(struct device *dev,
/* core, place */
-static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
-static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1);
-static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
-static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
+static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, 0, 0);
+static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, 0, 1);
+static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, 1, 0);
+static SENSOR_DEVICE_ATTR_2_RO(temp4_input, temp, 1, 1);
static DEVICE_ATTR_RO(name);
static const struct pci_device_id k8temp_ids[] = {
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c
index 84d791bdb62d..d470295760e2 100644
--- a/drivers/hwmon/lineage-pem.c
+++ b/drivers/hwmon/lineage-pem.c
@@ -282,8 +282,8 @@ static long pem_get_fan(u8 *data, int len, int index)
* Show boolean, either a fault or an alarm.
* .nr points to the register, .index is the bit mask to check
*/
-static ssize_t pem_show_bool(struct device *dev,
- struct device_attribute *da, char *buf)
+static ssize_t pem_bool_show(struct device *dev, struct device_attribute *da,
+ char *buf)
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
struct pem_data *data = pem_update_device(dev);
@@ -296,7 +296,7 @@ static ssize_t pem_show_bool(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", !!status);
}
-static ssize_t pem_show_data(struct device *dev, struct device_attribute *da,
+static ssize_t pem_data_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -312,7 +312,7 @@ static ssize_t pem_show_data(struct device *dev, struct device_attribute *da,
return snprintf(buf, PAGE_SIZE, "%ld\n", value);
}
-static ssize_t pem_show_input(struct device *dev, struct device_attribute *da,
+static ssize_t pem_input_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -328,7 +328,7 @@ static ssize_t pem_show_input(struct device *dev, struct device_attribute *da,
return snprintf(buf, PAGE_SIZE, "%ld\n", value);
}
-static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da,
+static ssize_t pem_fan_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -345,53 +345,42 @@ static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da,
}
/* Voltages */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, pem_show_data, NULL,
- PEM_DATA_VOUT_LSB);
-static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_VOUT_OUT_LIMIT);
-static SENSOR_DEVICE_ATTR_2(in1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_OV_VOLT_SHUTDOWN);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, pem_show_input, NULL,
- PEM_INPUT_VOLTAGE);
-static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1,
- ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT);
+static SENSOR_DEVICE_ATTR_RO(in1_input, pem_data, PEM_DATA_VOUT_LSB);
+static SENSOR_DEVICE_ATTR_2_RO(in1_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_VOUT_OUT_LIMIT);
+static SENSOR_DEVICE_ATTR_2_RO(in1_crit_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_OV_VOLT_SHUTDOWN);
+static SENSOR_DEVICE_ATTR_RO(in2_input, pem_input, PEM_INPUT_VOLTAGE);
+static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT);
/* Currents */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, pem_show_data, NULL,
- PEM_DATA_CURRENT);
-static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_VIN_OVERCURRENT);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, pem_data, PEM_DATA_CURRENT);
+static SENSOR_DEVICE_ATTR_2_RO(curr1_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_VIN_OVERCURRENT);
/* Power */
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pem_show_input, NULL,
- PEM_INPUT_POWER_LSB);
-static SENSOR_DEVICE_ATTR_2(power1_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_POWER_LIMIT);
+static SENSOR_DEVICE_ATTR_RO(power1_input, pem_input, PEM_INPUT_POWER_LSB);
+static SENSOR_DEVICE_ATTR_2_RO(power1_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_POWER_LIMIT);
/* Fans */
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pem_show_fan, NULL,
- PEM_FAN_FAN1);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, pem_show_fan, NULL,
- PEM_FAN_FAN2);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, pem_show_fan, NULL,
- PEM_FAN_FAN3);
-static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_2, ALRM2_FAN_FAULT);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, pem_fan, PEM_FAN_FAN1);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, pem_fan, PEM_FAN_FAN2);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, pem_fan, PEM_FAN_FAN3);
+static SENSOR_DEVICE_ATTR_2_RO(fan1_alarm, pem_bool, PEM_DATA_ALARM_2,
+ ALRM2_FAN_FAULT);
/* Temperatures */
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pem_show_data, NULL,
- PEM_DATA_TEMP);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, pem_show_data, NULL,
- PEM_DATA_TEMP_MAX);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, pem_show_data, NULL,
- PEM_DATA_TEMP_CRIT);
-static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_TEMP_WARNING);
-static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_1, ALRM1_TEMP_SHUTDOWN);
-static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, pem_show_bool, NULL,
- PEM_DATA_ALARM_2, ALRM2_TEMP_FAULT);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, pem_data, PEM_DATA_TEMP);
+static SENSOR_DEVICE_ATTR_RO(temp1_max, pem_data, PEM_DATA_TEMP_MAX);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit, pem_data, PEM_DATA_TEMP_CRIT);
+static SENSOR_DEVICE_ATTR_2_RO(temp1_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_TEMP_WARNING);
+static SENSOR_DEVICE_ATTR_2_RO(temp1_crit_alarm, pem_bool, PEM_DATA_ALARM_1,
+ ALRM1_TEMP_SHUTDOWN);
+static SENSOR_DEVICE_ATTR_2_RO(temp1_fault, pem_bool, PEM_DATA_ALARM_2,
+ ALRM2_TEMP_FAULT);
static struct attribute *pem_attributes[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 9653bb870a47..d1d728aa31d2 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -62,8 +62,8 @@ struct lm73_data {
/*-----------------------------------------------------------------------*/
-static ssize_t set_temp(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct lm73_data *data = dev_get_drvdata(dev);
@@ -81,7 +81,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
return (err < 0) ? err : count;
}
-static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+static ssize_t temp_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -98,8 +98,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
}
-static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t convrate_store(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
{
struct lm73_data *data = dev_get_drvdata(dev);
unsigned long convrate;
@@ -133,7 +133,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
return count;
}
-static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
+static ssize_t convrate_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct lm73_data *data = dev_get_drvdata(dev);
@@ -143,7 +143,7 @@ static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
return scnprintf(buf, PAGE_SIZE, "%hu\n", lm73_convrates[res]);
}
-static ssize_t show_maxmin_alarm(struct device *dev,
+static ssize_t maxmin_alarm_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -168,18 +168,14 @@ abort:
/* sysfs attributes for hwmon */
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
- show_temp, set_temp, LM73_REG_MAX);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
- show_temp, set_temp, LM73_REG_MIN);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
- show_temp, NULL, LM73_REG_INPUT);
-static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
- show_convrate, set_convrate, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
- show_maxmin_alarm, NULL, LM73_CTRL_HI_SHIFT);
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
- show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, LM73_REG_MAX);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, LM73_REG_MIN);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, LM73_REG_INPUT);
+static SENSOR_DEVICE_ATTR_RW(update_interval, convrate, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, maxmin_alarm,
+ LM73_CTRL_HI_SHIFT);
+static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, maxmin_alarm,
+ LM73_CTRL_LO_SHIFT);
static struct attribute *lm73_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 62acb9f16ec5..447af07450f1 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -176,16 +176,16 @@ static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type,
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
- return S_IRUGO;
+ return 0444;
}
break;
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_max:
case hwmon_temp_max_hyst:
- return S_IRUGO | S_IWUSR;
+ return 0644;
}
break;
default:
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 69b05cc2f60e..c27073dc24c1 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -137,7 +137,7 @@ static struct lm77_data *lm77_update_device(struct device *dev)
/* sysfs stuff */
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -146,7 +146,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", data->temp[attr->index]);
}
-static ssize_t show_temp_hyst(struct device *dev,
+static ssize_t temp_hyst_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -160,8 +160,9 @@ static ssize_t show_temp_hyst(struct device *dev,
return sprintf(buf, "%d\n", temp);
}
-static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm77_data *data = dev_get_drvdata(dev);
@@ -186,9 +187,9 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
* hysteresis is stored as a relative value on the chip, so it has to be
* converted first.
*/
-static ssize_t set_temp_hyst(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_hyst_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct lm77_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -208,7 +209,7 @@ static ssize_t set_temp_hyst(struct device *dev,
return count;
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -216,22 +217,18 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_crit);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_min);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_max);
-
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst,
- set_temp_hyst, t_crit);
-static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp_hyst, NULL, t_min);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max);
-
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max);
+
+static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit);
+static SENSOR_DEVICE_ATTR_RO(temp1_min_hyst, temp_hyst, t_min);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
static struct attribute *lm77_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 0e30fa00204c..54cf24a2b0ed 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -269,7 +269,7 @@ done:
* Sysfs stuff
*/
-static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+static ssize_t in_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
@@ -281,8 +281,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr][index]));
}
-static ssize_t set_in(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t in_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct lm80_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -303,7 +303,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int index = to_sensor_dev_attr_2(attr)->index;
@@ -315,8 +315,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
DIV_FROM_REG(data->fan_div[index])));
}
-static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = to_sensor_dev_attr(attr)->index;
struct lm80_data *data = lm80_update_device(dev);
@@ -325,8 +325,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
}
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int index = to_sensor_dev_attr_2(attr)->index;
int nr = to_sensor_dev_attr_2(attr)->nr;
@@ -352,8 +352,9 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
* least surprise; the user doesn't expect the fan minimum to change just
* because the divisor changed.
*/
-static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_div_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
struct lm80_data *data = dev_get_drvdata(dev);
@@ -393,8 +394,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
}
rv = lm80_read_value(client, LM80_REG_FANDIV);
- if (rv < 0)
+ if (rv < 0) {
+ mutex_unlock(&data->update_lock);
return rv;
+ }
reg = (rv & ~(3 << (2 * (nr + 1))))
| (data->fan_div[nr] << (2 * (nr + 1)));
lm80_write_value(client, LM80_REG_FANDIV, reg);
@@ -408,7 +411,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -418,8 +421,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm80_data *data = dev_get_drvdata(dev);
@@ -446,7 +450,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%u\n", data->alarms);
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -456,72 +460,50 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 0);
-static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 1);
-static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 2);
-static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 3);
-static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 4);
-static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 5);
-static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO,
- show_in, set_in, i_min, 6);
-static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 0);
-static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 1);
-static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 2);
-static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 3);
-static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 4);
-static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 5);
-static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO,
- show_in, set_in, i_max, 6);
-static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, i_input, 0);
-static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, i_input, 1);
-static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, i_input, 2);
-static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, i_input, 3);
-static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, i_input, 4);
-static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, i_input, 5);
-static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, i_input, 6);
-static SENSOR_DEVICE_ATTR_2(fan1_min, S_IWUSR | S_IRUGO,
- show_fan, set_fan_min, f_min, 0);
-static SENSOR_DEVICE_ATTR_2(fan2_min, S_IWUSR | S_IRUGO,
- show_fan, set_fan_min, f_min, 1);
-static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, f_input, 0);
-static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, f_input, 1);
-static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO,
- show_fan_div, set_fan_div, 0);
-static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO,
- show_fan_div, set_fan_div, 1);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp,
- set_temp, t_hot_max);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp,
- set_temp, t_hot_hyst);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp,
- set_temp, t_os_max);
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp,
- set_temp, t_os_hyst);
+static SENSOR_DEVICE_ATTR_2_RW(in0_min, in, i_min, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_min, in, i_min, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_min, in, i_min, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_min, in, i_min, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_min, in, i_min, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_min, in, i_min, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_min, in, i_min, 6);
+static SENSOR_DEVICE_ATTR_2_RW(in0_max, in, i_max, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_max, in, i_max, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_max, in, i_max, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_max, in, i_max, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_max, in, i_max, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_max, in, i_max, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_max, in, i_max, 6);
+static SENSOR_DEVICE_ATTR_2_RO(in0_input, in, i_input, 0);
+static SENSOR_DEVICE_ATTR_2_RO(in1_input, in, i_input, 1);
+static SENSOR_DEVICE_ATTR_2_RO(in2_input, in, i_input, 2);
+static SENSOR_DEVICE_ATTR_2_RO(in3_input, in, i_input, 3);
+static SENSOR_DEVICE_ATTR_2_RO(in4_input, in, i_input, 4);
+static SENSOR_DEVICE_ATTR_2_RO(in5_input, in, i_input, 5);
+static SENSOR_DEVICE_ATTR_2_RO(in6_input, in, i_input, 6);
+static SENSOR_DEVICE_ATTR_2_RW(fan1_min, fan, f_min, 0);
+static SENSOR_DEVICE_ATTR_2_RW(fan2_min, fan, f_min, 1);
+static SENSOR_DEVICE_ATTR_2_RO(fan1_input, fan, f_input, 0);
+static SENSOR_DEVICE_ATTR_2_RO(fan2_input, fan, f_input, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_hot_max);
+static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp, t_hot_hyst);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_os_max);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp, t_os_hyst);
static DEVICE_ATTR_RO(alarms);
-static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 10);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 11);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 8);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 13);
/*
* Real code
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index cbfd0bb7f135..5bb35dff3d76 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -158,7 +158,7 @@ static struct lm83_data *lm83_update_device(struct device *dev)
* Sysfs stuff
*/
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -166,8 +166,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm83_data *data = dev_get_drvdata(dev);
@@ -195,8 +196,8 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *dummy,
return sprintf(buf, "%d\n", data->alarms);
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm83_data *data = lm83_update_device(dev);
@@ -205,36 +206,31 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp,
- set_temp, 4);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp,
- set_temp, 5);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp,
- set_temp, 6);
-static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp,
- set_temp, 7);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
- set_temp, 8);
-static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 4);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, 5);
+static SENSOR_DEVICE_ATTR_RW(temp3_max, temp, 6);
+static SENSOR_DEVICE_ATTR_RW(temp4_max, temp, 7);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp, 8);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp, 8);
+static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp, 8);
+static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp, 8);
/* Individual alarm files */
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
-static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10);
-static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13);
-static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
+static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 9);
+static SENSOR_DEVICE_ATTR_RO(temp4_fault, alarm, 10);
+static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, alarm, 12);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 13);
+static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 15);
/* Raw alarm file for compatibility */
static DEVICE_ATTR_RO(alarms);
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 0a325878e8f5..a95d48316f06 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -41,7 +41,7 @@
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
enum chips {
- lm85,
+ lm85, lm96000,
adm1027, adt7463, adt7468,
emc6d100, emc6d102, emc6d103, emc6d103s
};
@@ -198,13 +198,18 @@ static int RANGE_TO_REG(long range)
#define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f]
/* These are the PWM frequency encodings */
-static const int lm85_freq_map[8] = { /* 1 Hz */
+static const int lm85_freq_map[] = { /* 1 Hz */
10, 15, 23, 30, 38, 47, 61, 94
};
-static const int adm1027_freq_map[8] = { /* 1 Hz */
+
+static const int lm96000_freq_map[] = { /* 1 Hz */
+ 10, 15, 23, 30, 38, 47, 61, 94,
+ 22500, 24000, 25700, 25700, 27700, 27700, 30000, 30000
+};
+
+static const int adm1027_freq_map[] = { /* 1 Hz */
11, 15, 22, 29, 35, 44, 59, 88
};
-#define FREQ_MAP_LEN 8
static int FREQ_TO_REG(const int *map,
unsigned int map_size, unsigned long freq)
@@ -212,9 +217,9 @@ static int FREQ_TO_REG(const int *map,
return find_closest(freq, map, map_size);
}
-static int FREQ_FROM_REG(const int *map, u8 reg)
+static int FREQ_FROM_REG(const int *map, unsigned int map_size, u8 reg)
{
- return map[reg & 0x07];
+ return map[reg % map_size];
}
/*
@@ -296,6 +301,8 @@ struct lm85_data {
struct i2c_client *client;
const struct attribute_group *groups[6];
const int *freq_map;
+ unsigned int freq_map_size;
+
enum chips type;
bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */
@@ -514,7 +521,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
data->autofan[i].config =
lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
- data->pwm_freq[i] = val & 0x07;
+ data->pwm_freq[i] = val % data->freq_map_size;
data->zone[i].range = val >> 4;
data->autofan[i].min_pwm =
lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
@@ -791,7 +798,8 @@ static ssize_t show_pwm_freq(struct device *dev,
if (IS_ADT7468_HFPWM(data))
freq = 22500;
else
- freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]);
+ freq = FREQ_FROM_REG(data->freq_map, data->freq_map_size,
+ data->pwm_freq[nr]);
return sprintf(buf, "%d\n", freq);
}
@@ -820,7 +828,7 @@ static ssize_t set_pwm_freq(struct device *dev,
lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5);
} else { /* Low freq. mode */
data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map,
- FREQ_MAP_LEN, val);
+ data->freq_map_size, val);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
(data->zone[nr].range << 4)
| data->pwm_freq[nr]);
@@ -1196,7 +1204,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
TEMP_FROM_REG(data->zone[nr].limit));
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->pwm_freq[nr] & 0x07));
+ | data->pwm_freq[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -1232,7 +1240,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
val - min);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->pwm_freq[nr] & 0x07));
+ | data->pwm_freq[nr]);
mutex_unlock(&data->update_lock);
return count;
}
@@ -1496,7 +1504,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
"Found Winbond WPCD377I, ignoring\n");
return -ENODEV;
}
- type_name = "lm85";
+ type_name = "lm96000";
break;
}
} else if (company == LM85_COMPANY_ANALOG_DEV) {
@@ -1569,9 +1577,15 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
case emc6d103:
case emc6d103s:
data->freq_map = adm1027_freq_map;
+ data->freq_map_size = ARRAY_SIZE(adm1027_freq_map);
+ break;
+ case lm96000:
+ data->freq_map = lm96000_freq_map;
+ data->freq_map_size = ARRAY_SIZE(lm96000_freq_map);
break;
default:
data->freq_map = lm85_freq_map;
+ data->freq_map_size = ARRAY_SIZE(lm85_freq_map);
}
/* Set the VRM version */
@@ -1618,6 +1632,7 @@ static const struct i2c_device_id lm85_id[] = {
{ "lm85", lm85 },
{ "lm85b", lm85 },
{ "lm85c", lm85 },
+ { "lm96000", lm96000 },
{ "emc6d100", emc6d100 },
{ "emc6d101", emc6d100 },
{ "emc6d102", emc6d102 },
@@ -1653,6 +1668,10 @@ static const struct of_device_id lm85_of_match[] = {
.data = (void *)lm85
},
{
+ .compatible = "ti,lm96000",
+ .data = (void *)lm96000
+ },
+ {
.compatible = "smsc,emc6d100",
.data = (void *)emc6d100
},
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index c2f411c290bf..480d70a51778 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1266,17 +1266,17 @@ static umode_t lm90_temp_is_visible(const void *data, u32 attr, int channel)
case hwmon_temp_emergency_alarm:
case hwmon_temp_emergency_hyst:
case hwmon_temp_fault:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_min:
case hwmon_temp_max:
case hwmon_temp_crit:
case hwmon_temp_emergency:
case hwmon_temp_offset:
- return S_IRUGO | S_IWUSR;
+ return 0644;
case hwmon_temp_crit_hyst:
if (channel == 0)
- return S_IRUGO | S_IWUSR;
- return S_IRUGO;
+ return 0644;
+ return 0444;
default:
return 0;
}
@@ -1338,9 +1338,9 @@ static umode_t lm90_chip_is_visible(const void *data, u32 attr, int channel)
{
switch (attr) {
case hwmon_chip_update_interval:
- return S_IRUGO | S_IWUSR;
+ return 0644;
case hwmon_chip_alarms:
- return S_IRUGO;
+ return 0444;
default:
return 0;
}
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index e7333f8e185c..39d8afe4279a 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -143,7 +143,7 @@ static struct lm92_data *lm92_update_device(struct device *dev)
return data;
}
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -152,8 +152,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm92_data *data = dev_get_drvdata(dev);
@@ -173,7 +174,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
return count;
}
-static ssize_t show_temp_hyst(struct device *dev,
+static ssize_t temp_hyst_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -192,9 +193,9 @@ static ssize_t temp1_min_hyst_show(struct device *dev,
+ TEMP_FROM_REG(data->temp[t_hyst]));
}
-static ssize_t set_temp_hyst(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_hyst_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm92_data *data = dev_get_drvdata(dev);
@@ -224,7 +225,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input]));
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -232,21 +233,17 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_crit);
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst,
- set_temp_hyst, t_crit);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_min);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min);
static DEVICE_ATTR_RO(temp1_min_hyst);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_max);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max);
static DEVICE_ATTR_RO(alarms);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
/*
* Detection and registration
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 77a0a83399b3..a0b5fbf958f3 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -1111,8 +1111,8 @@ static void lm93_update_client_min(struct lm93_data *data,
}
/* following are the sysfs callback functions */
-static ssize_t show_in(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t in_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1120,25 +1120,25 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr]));
}
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5);
-static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6);
-static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7);
-static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8);
-static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9);
-static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10);
-static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11);
-static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12);
-static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13);
-static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14);
-static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15);
-
-static ssize_t show_in_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static SENSOR_DEVICE_ATTR_RO(in1_input, in, 0);
+static SENSOR_DEVICE_ATTR_RO(in2_input, in, 1);
+static SENSOR_DEVICE_ATTR_RO(in3_input, in, 2);
+static SENSOR_DEVICE_ATTR_RO(in4_input, in, 3);
+static SENSOR_DEVICE_ATTR_RO(in5_input, in, 4);
+static SENSOR_DEVICE_ATTR_RO(in6_input, in, 5);
+static SENSOR_DEVICE_ATTR_RO(in7_input, in, 6);
+static SENSOR_DEVICE_ATTR_RO(in8_input, in, 7);
+static SENSOR_DEVICE_ATTR_RO(in9_input, in, 8);
+static SENSOR_DEVICE_ATTR_RO(in10_input, in, 9);
+static SENSOR_DEVICE_ATTR_RO(in11_input, in, 10);
+static SENSOR_DEVICE_ATTR_RO(in12_input, in, 11);
+static SENSOR_DEVICE_ATTR_RO(in13_input, in, 12);
+static SENSOR_DEVICE_ATTR_RO(in14_input, in, 13);
+static SENSOR_DEVICE_ATTR_RO(in15_input, in, 14);
+static SENSOR_DEVICE_ATTR_RO(in16_input, in, 15);
+
+static ssize_t in_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1154,7 +1154,7 @@ static ssize_t show_in_min(struct device *dev,
return sprintf(buf, "%ld\n", rc);
}
-static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
+static ssize_t in_min_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1185,41 +1185,25 @@ static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 0);
-static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 1);
-static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 2);
-static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 3);
-static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 4);
-static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 5);
-static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 6);
-static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 7);
-static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 8);
-static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 9);
-static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 10);
-static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 11);
-static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 12);
-static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 13);
-static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 14);
-static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO,
- show_in_min, store_in_min, 15);
-
-static ssize_t show_in_max(struct device *dev,
- struct device_attribute *attr, char *buf)
+static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 0);
+static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 1);
+static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 2);
+static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 3);
+static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 4);
+static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 5);
+static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 6);
+static SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 7);
+static SENSOR_DEVICE_ATTR_RW(in9_min, in_min, 8);
+static SENSOR_DEVICE_ATTR_RW(in10_min, in_min, 9);
+static SENSOR_DEVICE_ATTR_RW(in11_min, in_min, 10);
+static SENSOR_DEVICE_ATTR_RW(in12_min, in_min, 11);
+static SENSOR_DEVICE_ATTR_RW(in13_min, in_min, 12);
+static SENSOR_DEVICE_ATTR_RW(in14_min, in_min, 13);
+static SENSOR_DEVICE_ATTR_RW(in15_min, in_min, 14);
+static SENSOR_DEVICE_ATTR_RW(in16_min, in_min, 15);
+
+static ssize_t in_max_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1235,7 +1219,7 @@ static ssize_t show_in_max(struct device *dev,
return sprintf(buf, "%ld\n", rc);
}
-static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
+static ssize_t in_max_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1266,61 +1250,46 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 0);
-static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 1);
-static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 2);
-static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 3);
-static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 4);
-static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 5);
-static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 6);
-static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 7);
-static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 8);
-static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 9);
-static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 10);
-static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 11);
-static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 12);
-static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 13);
-static SENSOR_DEVICE_ATTR(in15_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 14);
-static SENSOR_DEVICE_ATTR(in16_max, S_IWUSR | S_IRUGO,
- show_in_max, store_in_max, 15);
-
-static ssize_t show_temp(struct device *dev,
- struct device_attribute *attr, char *buf)
+static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 0);
+static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 1);
+static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 2);
+static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 3);
+static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 4);
+static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 5);
+static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 6);
+static SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 7);
+static SENSOR_DEVICE_ATTR_RW(in9_max, in_max, 8);
+static SENSOR_DEVICE_ATTR_RW(in10_max, in_max, 9);
+static SENSOR_DEVICE_ATTR_RW(in11_max, in_max, 10);
+static SENSOR_DEVICE_ATTR_RW(in12_max, in_max, 11);
+static SENSOR_DEVICE_ATTR_RW(in13_max, in_max, 12);
+static SENSOR_DEVICE_ATTR_RW(in14_max, in_max, 13);
+static SENSOR_DEVICE_ATTR_RW(in15_max, in_max, 14);
+static SENSOR_DEVICE_ATTR_RW(in16_max, in_max, 15);
+
+static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block2[nr]));
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
-static ssize_t show_temp_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp_min_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].min));
}
-static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_min_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1339,14 +1308,11 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
- show_temp_min, store_temp_min, 0);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO,
- show_temp_min, store_temp_min, 1);
-static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO,
- show_temp_min, store_temp_min, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
-static ssize_t show_temp_max(struct device *dev,
+static ssize_t temp_max_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1354,8 +1320,9 @@ static ssize_t show_temp_max(struct device *dev,
return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].max));
}
-static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_max_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1374,24 +1341,21 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
- show_temp_max, store_temp_max, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO,
- show_temp_max, store_temp_max, 1);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO,
- show_temp_max, store_temp_max, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
-static ssize_t show_temp_auto_base(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp_auto_base_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block10.base[nr]));
}
-static ssize_t store_temp_auto_base(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_auto_base_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1410,14 +1374,11 @@ static ssize_t store_temp_auto_base(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_auto_base, S_IWUSR | S_IRUGO,
- show_temp_auto_base, store_temp_auto_base, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_base, S_IWUSR | S_IRUGO,
- show_temp_auto_base, store_temp_auto_base, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_base, S_IWUSR | S_IRUGO,
- show_temp_auto_base, store_temp_auto_base, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_auto_base, temp_auto_base, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_auto_base, temp_auto_base, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_auto_base, temp_auto_base, 2);
-static ssize_t show_temp_auto_boost(struct device *dev,
+static ssize_t temp_auto_boost_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1425,7 +1386,7 @@ static ssize_t show_temp_auto_boost(struct device *dev,
return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->boost[nr]));
}
-static ssize_t store_temp_auto_boost(struct device *dev,
+static ssize_t temp_auto_boost_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -1446,14 +1407,11 @@ static ssize_t store_temp_auto_boost(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_auto_boost, S_IWUSR | S_IRUGO,
- show_temp_auto_boost, store_temp_auto_boost, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_boost, S_IWUSR | S_IRUGO,
- show_temp_auto_boost, store_temp_auto_boost, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_boost, S_IWUSR | S_IRUGO,
- show_temp_auto_boost, store_temp_auto_boost, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_auto_boost, temp_auto_boost, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_auto_boost, temp_auto_boost, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_auto_boost, temp_auto_boost, 2);
-static ssize_t show_temp_auto_boost_hyst(struct device *dev,
+static ssize_t temp_auto_boost_hyst_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1464,7 +1422,7 @@ static ssize_t show_temp_auto_boost_hyst(struct device *dev,
LM93_AUTO_BOOST_HYST_FROM_REGS(data, nr, mode));
}
-static ssize_t store_temp_auto_boost_hyst(struct device *dev,
+static ssize_t temp_auto_boost_hyst_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -1490,18 +1448,12 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_auto_boost_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_boost_hyst,
- store_temp_auto_boost_hyst, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_boost_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_boost_hyst,
- store_temp_auto_boost_hyst, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_boost_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_boost_hyst,
- store_temp_auto_boost_hyst, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_auto_boost_hyst, temp_auto_boost_hyst, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_auto_boost_hyst, temp_auto_boost_hyst, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_auto_boost_hyst, temp_auto_boost_hyst, 2);
-static ssize_t show_temp_auto_offset(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp_auto_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
int nr = s_attr->index;
@@ -1513,9 +1465,9 @@ static ssize_t show_temp_auto_offset(struct device *dev,
nr, mode));
}
-static ssize_t store_temp_auto_offset(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_auto_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
int nr = s_attr->index;
@@ -1542,81 +1494,46 @@ static ssize_t store_temp_auto_offset(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset1, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 0, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset2, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 1, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset3, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 2, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset4, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 3, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset5, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 4, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset6, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 5, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset7, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 6, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset8, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 7, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset9, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 8, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset10, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 9, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset11, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 10, 0);
-static SENSOR_DEVICE_ATTR_2(temp1_auto_offset12, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 11, 0);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset1, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 0, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset2, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 1, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset3, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 2, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset4, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 3, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset5, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 4, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset6, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 5, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset7, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 6, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset8, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 7, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset9, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 8, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset10, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 9, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset11, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 10, 1);
-static SENSOR_DEVICE_ATTR_2(temp2_auto_offset12, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 11, 1);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset1, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 0, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset2, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 1, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset3, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 2, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset4, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 3, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset5, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 4, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset6, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 5, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset7, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 6, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset8, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 7, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset9, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 8, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset10, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 9, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset11, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 10, 2);
-static SENSOR_DEVICE_ATTR_2(temp3_auto_offset12, S_IWUSR | S_IRUGO,
- show_temp_auto_offset, store_temp_auto_offset, 11, 2);
-
-static ssize_t show_temp_auto_pwm_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset1, temp_auto_offset, 0, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset2, temp_auto_offset, 1, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset3, temp_auto_offset, 2, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset4, temp_auto_offset, 3, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset5, temp_auto_offset, 4, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset6, temp_auto_offset, 5, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset7, temp_auto_offset, 6, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset8, temp_auto_offset, 7, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset9, temp_auto_offset, 8, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset10, temp_auto_offset, 9, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset11, temp_auto_offset, 10, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_offset12, temp_auto_offset, 11, 0);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset1, temp_auto_offset, 0, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset2, temp_auto_offset, 1, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset3, temp_auto_offset, 2, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset4, temp_auto_offset, 3, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset5, temp_auto_offset, 4, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset6, temp_auto_offset, 5, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset7, temp_auto_offset, 6, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset8, temp_auto_offset, 7, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset9, temp_auto_offset, 8, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset10, temp_auto_offset, 9, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset11, temp_auto_offset, 10, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_offset12, temp_auto_offset, 11, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset1, temp_auto_offset, 0, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset2, temp_auto_offset, 1, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset3, temp_auto_offset, 2, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset4, temp_auto_offset, 3, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset5, temp_auto_offset, 4, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset6, temp_auto_offset, 5, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset7, temp_auto_offset, 6, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset8, temp_auto_offset, 7, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset9, temp_auto_offset, 8, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset10, temp_auto_offset, 9, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset11, temp_auto_offset, 10, 2);
+static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_offset12, temp_auto_offset, 11, 2);
+
+static ssize_t temp_auto_pwm_min_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
u8 reg, ctl4;
@@ -1627,9 +1544,9 @@ static ssize_t show_temp_auto_pwm_min(struct device *dev,
LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
}
-static ssize_t store_temp_auto_pwm_min(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_auto_pwm_min_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1655,18 +1572,13 @@ static ssize_t store_temp_auto_pwm_min(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_auto_pwm_min, S_IWUSR | S_IRUGO,
- show_temp_auto_pwm_min,
- store_temp_auto_pwm_min, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_pwm_min, S_IWUSR | S_IRUGO,
- show_temp_auto_pwm_min,
- store_temp_auto_pwm_min, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_pwm_min, S_IWUSR | S_IRUGO,
- show_temp_auto_pwm_min,
- store_temp_auto_pwm_min, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_auto_pwm_min, temp_auto_pwm_min, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_auto_pwm_min, temp_auto_pwm_min, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_auto_pwm_min, temp_auto_pwm_min, 2);
-static ssize_t show_temp_auto_offset_hyst(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp_auto_offset_hyst_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1675,9 +1587,9 @@ static ssize_t show_temp_auto_offset_hyst(struct device *dev,
data->auto_pwm_min_hyst[nr / 2], mode));
}
-static ssize_t store_temp_auto_offset_hyst(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_auto_offset_hyst_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1703,18 +1615,12 @@ static ssize_t store_temp_auto_offset_hyst(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_auto_offset_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_offset_hyst,
- store_temp_auto_offset_hyst, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_offset_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_offset_hyst,
- store_temp_auto_offset_hyst, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_offset_hyst, S_IWUSR | S_IRUGO,
- show_temp_auto_offset_hyst,
- store_temp_auto_offset_hyst, 2);
+static SENSOR_DEVICE_ATTR_RW(temp1_auto_offset_hyst, temp_auto_offset_hyst, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_auto_offset_hyst, temp_auto_offset_hyst, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_auto_offset_hyst, temp_auto_offset_hyst, 2);
-static ssize_t show_fan_input(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
int nr = s_attr->index;
@@ -1723,13 +1629,13 @@ static ssize_t show_fan_input(struct device *dev,
return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block5[nr]));
}
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_input, fan_input, 3);
-static ssize_t show_fan_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1737,8 +1643,9 @@ static ssize_t show_fan_min(struct device *dev,
return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block8[nr]));
}
-static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1757,14 +1664,10 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
- show_fan_min, store_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
- show_fan_min, store_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
- show_fan_min, store_fan_min, 2);
-static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
- show_fan_min, store_fan_min, 3);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
+static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
/*
* some tedious bit-twiddling here to deal with the register format:
@@ -1780,8 +1683,8 @@ static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
* T4 T3 T2 T1
*/
-static ssize_t show_fan_smart_tach(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_smart_tach_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1819,9 +1722,9 @@ static void lm93_write_fan_smart_tach(struct i2c_client *client,
lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
}
-static ssize_t store_fan_smart_tach(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_smart_tach_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1849,16 +1752,12 @@ static ssize_t store_fan_smart_tach(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(fan1_smart_tach, S_IWUSR | S_IRUGO,
- show_fan_smart_tach, store_fan_smart_tach, 0);
-static SENSOR_DEVICE_ATTR(fan2_smart_tach, S_IWUSR | S_IRUGO,
- show_fan_smart_tach, store_fan_smart_tach, 1);
-static SENSOR_DEVICE_ATTR(fan3_smart_tach, S_IWUSR | S_IRUGO,
- show_fan_smart_tach, store_fan_smart_tach, 2);
-static SENSOR_DEVICE_ATTR(fan4_smart_tach, S_IWUSR | S_IRUGO,
- show_fan_smart_tach, store_fan_smart_tach, 3);
+static SENSOR_DEVICE_ATTR_RW(fan1_smart_tach, fan_smart_tach, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_smart_tach, fan_smart_tach, 1);
+static SENSOR_DEVICE_ATTR_RW(fan3_smart_tach, fan_smart_tach, 2);
+static SENSOR_DEVICE_ATTR_RW(fan4_smart_tach, fan_smart_tach, 3);
-static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -1876,8 +1775,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%ld\n", rc);
}
-static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -1904,11 +1803,11 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
-static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
-static ssize_t show_pwm_enable(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t pwm_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -1923,7 +1822,7 @@ static ssize_t show_pwm_enable(struct device *dev,
return sprintf(buf, "%ld\n", rc);
}
-static ssize_t store_pwm_enable(struct device *dev,
+static ssize_t pwm_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -1961,13 +1860,11 @@ static ssize_t store_pwm_enable(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, store_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, store_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1);
-static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t pwm_freq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2001,9 +1898,9 @@ static void lm93_disable_fan_smart_tach(struct i2c_client *client,
lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
}
-static ssize_t store_pwm_freq(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pwm_freq_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2028,22 +1925,21 @@ static ssize_t store_pwm_freq(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_freq, S_IWUSR | S_IRUGO,
- show_pwm_freq, store_pwm_freq, 0);
-static SENSOR_DEVICE_ATTR(pwm2_freq, S_IWUSR | S_IRUGO,
- show_pwm_freq, store_pwm_freq, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_freq, pwm_freq, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_freq, pwm_freq, 1);
-static ssize_t show_pwm_auto_channels(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t pwm_auto_channels_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
return sprintf(buf, "%d\n", data->block9[nr][LM93_PWM_CTL1]);
}
-static ssize_t store_pwm_auto_channels(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pwm_auto_channels_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2063,13 +1959,12 @@ static ssize_t store_pwm_auto_channels(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_auto_channels, S_IWUSR | S_IRUGO,
- show_pwm_auto_channels, store_pwm_auto_channels, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_channels, S_IWUSR | S_IRUGO,
- show_pwm_auto_channels, store_pwm_auto_channels, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_channels, pwm_auto_channels, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_auto_channels, pwm_auto_channels, 1);
-static ssize_t show_pwm_auto_spinup_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t pwm_auto_spinup_min_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2082,9 +1977,9 @@ static ssize_t show_pwm_auto_spinup_min(struct device *dev,
LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
}
-static ssize_t store_pwm_auto_spinup_min(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pwm_auto_spinup_min_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2109,15 +2004,12 @@ static ssize_t store_pwm_auto_spinup_min(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_min, S_IWUSR | S_IRUGO,
- show_pwm_auto_spinup_min,
- store_pwm_auto_spinup_min, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_min, S_IWUSR | S_IRUGO,
- show_pwm_auto_spinup_min,
- store_pwm_auto_spinup_min, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_spinup_min, pwm_auto_spinup_min, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_auto_spinup_min, pwm_auto_spinup_min, 1);
-static ssize_t show_pwm_auto_spinup_time(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t pwm_auto_spinup_time_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2125,9 +2017,9 @@ static ssize_t show_pwm_auto_spinup_time(struct device *dev,
data->block9[nr][LM93_PWM_CTL3]));
}
-static ssize_t store_pwm_auto_spinup_time(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pwm_auto_spinup_time_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2149,12 +2041,8 @@ static ssize_t store_pwm_auto_spinup_time(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_time, S_IWUSR | S_IRUGO,
- show_pwm_auto_spinup_time,
- store_pwm_auto_spinup_time, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_time, S_IWUSR | S_IRUGO,
- show_pwm_auto_spinup_time,
- store_pwm_auto_spinup_time, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_spinup_time, pwm_auto_spinup_time, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_auto_spinup_time, pwm_auto_spinup_time, 1);
static ssize_t pwm_auto_prochot_ramp_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -2220,7 +2108,7 @@ static ssize_t pwm_auto_vrdhot_ramp_store(struct device *dev,
static DEVICE_ATTR_RW(pwm_auto_vrdhot_ramp);
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+static ssize_t vid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -2228,21 +2116,21 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", LM93_VID_FROM_REG(data->vid[nr]));
}
-static SENSOR_DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL, 0);
-static SENSOR_DEVICE_ATTR(cpu1_vid, S_IRUGO, show_vid, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(cpu0_vid, vid, 0);
+static SENSOR_DEVICE_ATTR_RO(cpu1_vid, vid, 1);
-static ssize_t show_prochot(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t prochot_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
return sprintf(buf, "%d\n", data->block4[nr].cur);
}
-static SENSOR_DEVICE_ATTR(prochot1, S_IRUGO, show_prochot, NULL, 0);
-static SENSOR_DEVICE_ATTR(prochot2, S_IRUGO, show_prochot, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(prochot1, prochot, 0);
+static SENSOR_DEVICE_ATTR_RO(prochot2, prochot, 1);
-static ssize_t show_prochot_avg(struct device *dev,
+static ssize_t prochot_avg_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -2250,10 +2138,10 @@ static ssize_t show_prochot_avg(struct device *dev,
return sprintf(buf, "%d\n", data->block4[nr].avg);
}
-static SENSOR_DEVICE_ATTR(prochot1_avg, S_IRUGO, show_prochot_avg, NULL, 0);
-static SENSOR_DEVICE_ATTR(prochot2_avg, S_IRUGO, show_prochot_avg, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(prochot1_avg, prochot_avg, 0);
+static SENSOR_DEVICE_ATTR_RO(prochot2_avg, prochot_avg, 1);
-static ssize_t show_prochot_max(struct device *dev,
+static ssize_t prochot_max_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
@@ -2261,9 +2149,9 @@ static ssize_t show_prochot_max(struct device *dev,
return sprintf(buf, "%d\n", data->prochot_max[nr]);
}
-static ssize_t store_prochot_max(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t prochot_max_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2283,15 +2171,13 @@ static ssize_t store_prochot_max(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(prochot1_max, S_IWUSR | S_IRUGO,
- show_prochot_max, store_prochot_max, 0);
-static SENSOR_DEVICE_ATTR(prochot2_max, S_IWUSR | S_IRUGO,
- show_prochot_max, store_prochot_max, 1);
+static SENSOR_DEVICE_ATTR_RW(prochot1_max, prochot_max, 0);
+static SENSOR_DEVICE_ATTR_RW(prochot2_max, prochot_max, 1);
static const u8 prochot_override_mask[] = { 0x80, 0x40 };
-static ssize_t show_prochot_override(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t prochot_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2299,9 +2185,9 @@ static ssize_t show_prochot_override(struct device *dev,
(data->prochot_override & prochot_override_mask[nr]) ? 1 : 0);
}
-static ssize_t store_prochot_override(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t prochot_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2324,13 +2210,11 @@ static ssize_t store_prochot_override(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(prochot1_override, S_IWUSR | S_IRUGO,
- show_prochot_override, store_prochot_override, 0);
-static SENSOR_DEVICE_ATTR(prochot2_override, S_IWUSR | S_IRUGO,
- show_prochot_override, store_prochot_override, 1);
+static SENSOR_DEVICE_ATTR_RW(prochot1_override, prochot_override, 0);
+static SENSOR_DEVICE_ATTR_RW(prochot2_override, prochot_override, 1);
-static ssize_t show_prochot_interval(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t prochot_interval_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2342,9 +2226,9 @@ static ssize_t show_prochot_interval(struct device *dev,
return sprintf(buf, "%d\n", LM93_INTERVAL_FROM_REG(tmp));
}
-static ssize_t store_prochot_interval(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t prochot_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = dev_get_drvdata(dev);
@@ -2369,10 +2253,8 @@ static ssize_t store_prochot_interval(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR(prochot1_interval, S_IWUSR | S_IRUGO,
- show_prochot_interval, store_prochot_interval, 0);
-static SENSOR_DEVICE_ATTR(prochot2_interval, S_IWUSR | S_IRUGO,
- show_prochot_interval, store_prochot_interval, 1);
+static SENSOR_DEVICE_ATTR_RW(prochot1_interval, prochot_interval, 0);
+static SENSOR_DEVICE_ATTR_RW(prochot2_interval, prochot_interval, 1);
static ssize_t prochot_override_duty_cycle_show(struct device *dev,
struct device_attribute *attr,
@@ -2438,8 +2320,8 @@ static ssize_t prochot_short_store(struct device *dev,
static DEVICE_ATTR_RW(prochot_short);
-static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t vrdhot_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int nr = (to_sensor_dev_attr(attr))->index;
struct lm93_data *data = lm93_update_device(dev);
@@ -2447,8 +2329,8 @@ static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr,
data->block1.host_status_1 & (1 << (nr + 4)) ? 1 : 0);
}
-static SENSOR_DEVICE_ATTR(vrdhot1, S_IRUGO, show_vrdhot, NULL, 0);
-static SENSOR_DEVICE_ATTR(vrdhot2, S_IRUGO, show_vrdhot, NULL, 1);
+static SENSOR_DEVICE_ATTR_RO(vrdhot1, vrdhot, 0);
+static SENSOR_DEVICE_ATTR_RO(vrdhot2, vrdhot, 1);
static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
char *buf)
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 8c573e6e9726..3ff188937158 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -349,19 +349,19 @@ static umode_t lm95241_is_visible(const void *data,
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
- return S_IRUGO | S_IWUSR;
+ return 0644;
}
break;
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_fault:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_min:
case hwmon_temp_max:
case hwmon_temp_type:
- return S_IRUGO | S_IWUSR;
+ return 0644;
}
break;
default:
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
index 996b50246175..e4cac3a04536 100644
--- a/drivers/hwmon/lm95245.c
+++ b/drivers/hwmon/lm95245.c
@@ -421,14 +421,14 @@ static umode_t lm95245_temp_is_visible(const void *data, u32 attr, int channel)
case hwmon_temp_max_hyst:
case hwmon_temp_crit_alarm:
case hwmon_temp_fault:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_type:
case hwmon_temp_max:
case hwmon_temp_crit:
case hwmon_temp_offset:
- return S_IRUGO | S_IWUSR;
+ return 0644;
case hwmon_temp_crit_hyst:
- return (channel == 0) ? S_IRUGO | S_IWUSR : S_IRUGO;
+ return (channel == 0) ? 0644 : 0444;
default:
return 0;
}
@@ -442,7 +442,7 @@ static umode_t lm95245_is_visible(const void *data,
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
- return S_IRUGO | S_IWUSR;
+ return 0644;
default:
return 0;
}
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
index 2aefdc58b242..be4e89645c0b 100644
--- a/drivers/hwmon/ltc2990.c
+++ b/drivers/hwmon/ltc2990.c
@@ -136,7 +136,7 @@ static int ltc2990_get_value(struct i2c_client *i2c, int index, int *result)
return 0;
}
-static ssize_t ltc2990_show_value(struct device *dev,
+static ssize_t ltc2990_value_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -170,26 +170,16 @@ static umode_t ltc2990_attrs_visible(struct kobject *kobj,
return 0;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_TEMP1);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_TEMP2);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_TEMP3);
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_CURR1);
-static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_CURR2);
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_IN0);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_IN1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_IN2);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_IN3);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc2990_show_value, NULL,
- LTC2990_IN4);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, ltc2990_value, LTC2990_TEMP1);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, ltc2990_value, LTC2990_TEMP2);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, ltc2990_value, LTC2990_TEMP3);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc2990_value, LTC2990_CURR1);
+static SENSOR_DEVICE_ATTR_RO(curr2_input, ltc2990_value, LTC2990_CURR2);
+static SENSOR_DEVICE_ATTR_RO(in0_input, ltc2990_value, LTC2990_IN0);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ltc2990_value, LTC2990_IN1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, ltc2990_value, LTC2990_IN2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, ltc2990_value, LTC2990_IN3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, ltc2990_value, LTC2990_IN4);
static struct attribute *ltc2990_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index b904cb547ffb..76c6fda76d95 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -131,7 +131,7 @@ static int ltc4151_get_value(struct ltc4151_data *data, u8 reg)
return val;
}
-static ssize_t ltc4151_show_value(struct device *dev,
+static ssize_t ltc4151_value_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -148,14 +148,11 @@ static ssize_t ltc4151_show_value(struct device *dev,
/*
* Input voltages.
*/
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4151_show_value, NULL,
- LTC4151_VIN_H);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4151_show_value, NULL,
- LTC4151_ADIN_H);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4151_value, LTC4151_VIN_H);
+static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4151_value, LTC4151_ADIN_H);
/* Currents (via sense resistor) */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4151_show_value, NULL,
- LTC4151_SENSE_H);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4151_value, LTC4151_SENSE_H);
/*
* Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c
index 88f747292816..32248f351a6e 100644
--- a/drivers/hwmon/ltc4222.c
+++ b/drivers/hwmon/ltc4222.c
@@ -94,7 +94,7 @@ static int ltc4222_get_value(struct device *dev, u8 reg)
return val;
}
-static ssize_t ltc4222_show_value(struct device *dev,
+static ssize_t ltc4222_value_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -106,7 +106,7 @@ static ssize_t ltc4222_show_value(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
-static ssize_t ltc4222_show_bool(struct device *dev,
+static ssize_t ltc4222_bool_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
@@ -125,45 +125,39 @@ static ssize_t ltc4222_show_bool(struct device *dev,
}
/* Voltages */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_SOURCE1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_ADIN1);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_SOURCE2);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_ADIN2);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4222_value, LTC4222_SOURCE1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4222_value, LTC4222_ADIN1);
+static SENSOR_DEVICE_ATTR_RO(in3_input, ltc4222_value, LTC4222_SOURCE2);
+static SENSOR_DEVICE_ATTR_RO(in4_input, ltc4222_value, LTC4222_ADIN2);
/*
* Voltage alarms
* UV/OV faults are associated with the input voltage, and power bad and fet
* faults are associated with the output voltage.
*/
-static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT1, FAULT_UV);
-static SENSOR_DEVICE_ATTR_2(in1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT1, FAULT_OV);
-static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT1, FAULT_POWER_BAD | FAULT_FET_BAD);
-
-static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT2, FAULT_UV);
-static SENSOR_DEVICE_ATTR_2(in3_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT2, FAULT_OV);
-static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT2, FAULT_POWER_BAD | FAULT_FET_BAD);
+static SENSOR_DEVICE_ATTR_2_RO(in1_min_alarm, ltc4222_bool, LTC4222_FAULT1,
+ FAULT_UV);
+static SENSOR_DEVICE_ATTR_2_RO(in1_max_alarm, ltc4222_bool, LTC4222_FAULT1,
+ FAULT_OV);
+static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, ltc4222_bool, LTC4222_FAULT1,
+ FAULT_POWER_BAD | FAULT_FET_BAD);
+
+static SENSOR_DEVICE_ATTR_2_RO(in3_min_alarm, ltc4222_bool, LTC4222_FAULT2,
+ FAULT_UV);
+static SENSOR_DEVICE_ATTR_2_RO(in3_max_alarm, ltc4222_bool, LTC4222_FAULT2,
+ FAULT_OV);
+static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, ltc4222_bool, LTC4222_FAULT2,
+ FAULT_POWER_BAD | FAULT_FET_BAD);
/* Current (via sense resistor) */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_SENSE1);
-static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4222_show_value, NULL,
- LTC4222_SENSE2);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4222_value, LTC4222_SENSE1);
+static SENSOR_DEVICE_ATTR_RO(curr2_input, ltc4222_value, LTC4222_SENSE2);
/* Overcurrent alarm */
-static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT1, FAULT_OC);
-static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4222_show_bool, NULL,
- LTC4222_FAULT2, FAULT_OC);
+static SENSOR_DEVICE_ATTR_2_RO(curr1_max_alarm, ltc4222_bool, LTC4222_FAULT1,
+ FAULT_OC);
+static SENSOR_DEVICE_ATTR_2_RO(curr2_max_alarm, ltc4222_bool, LTC4222_FAULT2,
+ FAULT_OC);
static struct attribute *ltc4222_attrs[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index 082f0a0bd8a0..34d0653ca607 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -362,11 +362,11 @@ static umode_t ltc4245_is_visible(const void *_data,
case hwmon_in_input:
if (channel > 9 && !data->use_extra_gpios)
return 0;
- return S_IRUGO;
+ return 0444;
case hwmon_in_min_alarm:
if (channel > 8)
return 0;
- return S_IRUGO;
+ return 0444;
default:
return 0;
}
@@ -374,14 +374,14 @@ static umode_t ltc4245_is_visible(const void *_data,
switch (attr) {
case hwmon_curr_input:
case hwmon_curr_max_alarm:
- return S_IRUGO;
+ return 0444;
default:
return 0;
}
case hwmon_power:
switch (attr) {
case hwmon_power_input:
- return S_IRUGO;
+ return 0444;
default:
return 0;
}
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index 0becd69842bb..6eb3415e0639 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -132,7 +132,7 @@ static int ltc4261_get_value(struct ltc4261_data *data, u8 reg)
return val;
}
-static ssize_t ltc4261_show_value(struct device *dev,
+static ssize_t ltc4261_value_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -146,7 +146,7 @@ static ssize_t ltc4261_show_value(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
-static ssize_t ltc4261_show_bool(struct device *dev,
+static ssize_t ltc4261_bool_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -166,10 +166,8 @@ static ssize_t ltc4261_show_bool(struct device *dev,
/*
* Input voltages.
*/
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4261_show_value, NULL,
- LTC4261_ADIN_H);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL,
- LTC4261_ADIN2_H);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4261_value, LTC4261_ADIN_H);
+static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4261_value, LTC4261_ADIN2_H);
/*
* Voltage alarms. The chip has only one set of voltage alarm status bits,
@@ -179,22 +177,16 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL,
* To ensure that the alarm condition is reported to the user, report it
* with both voltage sensors.
*/
-static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
- FAULT_UV);
-static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
- FAULT_OV);
-static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
- FAULT_UV);
-static SENSOR_DEVICE_ATTR(in2_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
- FAULT_OV);
+static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc4261_bool, FAULT_UV);
+static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc4261_bool, FAULT_OV);
+static SENSOR_DEVICE_ATTR_RO(in2_min_alarm, ltc4261_bool, FAULT_UV);
+static SENSOR_DEVICE_ATTR_RO(in2_max_alarm, ltc4261_bool, FAULT_OV);
/* Currents (via sense resistor) */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL,
- LTC4261_SENSE_H);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4261_value, LTC4261_SENSE_H);
/* Overcurrent alarm */
-static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
- FAULT_OC);
+static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc4261_bool, FAULT_OC);
static struct attribute *ltc4261_attrs[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index 162401aaef71..1c372f76cd0b 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -175,7 +175,7 @@ static struct max16065_data *max16065_update_device(struct device *dev)
return data;
}
-static ssize_t max16065_show_alarm(struct device *dev,
+static ssize_t max16065_alarm_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
@@ -193,7 +193,7 @@ static ssize_t max16065_show_alarm(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
}
-static ssize_t max16065_show_input(struct device *dev,
+static ssize_t max16065_input_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
@@ -207,7 +207,7 @@ static ssize_t max16065_show_input(struct device *dev,
ADC_TO_MV(adc, data->range[attr->index]));
}
-static ssize_t max16065_show_current(struct device *dev,
+static ssize_t max16065_current_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct max16065_data *data = max16065_update_device(dev);
@@ -219,9 +219,9 @@ static ssize_t max16065_show_current(struct device *dev,
ADC_TO_CURR(data->curr_sense, data->curr_gain));
}
-static ssize_t max16065_set_limit(struct device *dev,
- struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t max16065_limit_store(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
struct max16065_data *data = dev_get_drvdata(dev);
@@ -246,7 +246,7 @@ static ssize_t max16065_set_limit(struct device *dev,
return count;
}
-static ssize_t max16065_show_limit(struct device *dev,
+static ssize_t max16065_limit_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
@@ -259,154 +259,93 @@ static ssize_t max16065_show_limit(struct device *dev,
/* Construct a sensor_device_attribute structure for each register */
/* Input voltages */
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, max16065_show_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, max16065_show_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, max16065_show_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, max16065_show_input, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, max16065_show_input, NULL, 4);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, max16065_show_input, NULL, 5);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, max16065_show_input, NULL, 6);
-static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, max16065_show_input, NULL, 7);
-static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, max16065_show_input, NULL, 8);
-static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, max16065_show_input, NULL, 9);
-static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, max16065_show_input, NULL, 10);
-static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, max16065_show_input, NULL, 11);
-static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, max16065_show_input, NULL, 12);
+static SENSOR_DEVICE_ATTR_RO(in0_input, max16065_input, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_input, max16065_input, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, max16065_input, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, max16065_input, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, max16065_input, 4);
+static SENSOR_DEVICE_ATTR_RO(in5_input, max16065_input, 5);
+static SENSOR_DEVICE_ATTR_RO(in6_input, max16065_input, 6);
+static SENSOR_DEVICE_ATTR_RO(in7_input, max16065_input, 7);
+static SENSOR_DEVICE_ATTR_RO(in8_input, max16065_input, 8);
+static SENSOR_DEVICE_ATTR_RO(in9_input, max16065_input, 9);
+static SENSOR_DEVICE_ATTR_RO(in10_input, max16065_input, 10);
+static SENSOR_DEVICE_ATTR_RO(in11_input, max16065_input, 11);
+static SENSOR_DEVICE_ATTR_RO(in12_input, max16065_input, 12);
/* Input voltages lcrit */
-static SENSOR_DEVICE_ATTR_2(in0_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 0);
-static SENSOR_DEVICE_ATTR_2(in1_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 1);
-static SENSOR_DEVICE_ATTR_2(in2_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 2);
-static SENSOR_DEVICE_ATTR_2(in3_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 3);
-static SENSOR_DEVICE_ATTR_2(in4_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 4);
-static SENSOR_DEVICE_ATTR_2(in5_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 5);
-static SENSOR_DEVICE_ATTR_2(in6_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 6);
-static SENSOR_DEVICE_ATTR_2(in7_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 7);
-static SENSOR_DEVICE_ATTR_2(in8_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 8);
-static SENSOR_DEVICE_ATTR_2(in9_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 9);
-static SENSOR_DEVICE_ATTR_2(in10_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 10);
-static SENSOR_DEVICE_ATTR_2(in11_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 2, 11);
+static SENSOR_DEVICE_ATTR_2_RW(in0_lcrit, max16065_limit, 2, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_lcrit, max16065_limit, 2, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_lcrit, max16065_limit, 2, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_lcrit, max16065_limit, 2, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_lcrit, max16065_limit, 2, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_lcrit, max16065_limit, 2, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_lcrit, max16065_limit, 2, 6);
+static SENSOR_DEVICE_ATTR_2_RW(in7_lcrit, max16065_limit, 2, 7);
+static SENSOR_DEVICE_ATTR_2_RW(in8_lcrit, max16065_limit, 2, 8);
+static SENSOR_DEVICE_ATTR_2_RW(in9_lcrit, max16065_limit, 2, 9);
+static SENSOR_DEVICE_ATTR_2_RW(in10_lcrit, max16065_limit, 2, 10);
+static SENSOR_DEVICE_ATTR_2_RW(in11_lcrit, max16065_limit, 2, 11);
/* Input voltages crit */
-static SENSOR_DEVICE_ATTR_2(in0_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 0);
-static SENSOR_DEVICE_ATTR_2(in1_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 1);
-static SENSOR_DEVICE_ATTR_2(in2_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 2);
-static SENSOR_DEVICE_ATTR_2(in3_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 3);
-static SENSOR_DEVICE_ATTR_2(in4_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 4);
-static SENSOR_DEVICE_ATTR_2(in5_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 5);
-static SENSOR_DEVICE_ATTR_2(in6_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 6);
-static SENSOR_DEVICE_ATTR_2(in7_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 7);
-static SENSOR_DEVICE_ATTR_2(in8_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 8);
-static SENSOR_DEVICE_ATTR_2(in9_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 9);
-static SENSOR_DEVICE_ATTR_2(in10_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 10);
-static SENSOR_DEVICE_ATTR_2(in11_crit, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 1, 11);
+static SENSOR_DEVICE_ATTR_2_RW(in0_crit, max16065_limit, 1, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_crit, max16065_limit, 1, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_crit, max16065_limit, 1, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_crit, max16065_limit, 1, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_crit, max16065_limit, 1, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_crit, max16065_limit, 1, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_crit, max16065_limit, 1, 6);
+static SENSOR_DEVICE_ATTR_2_RW(in7_crit, max16065_limit, 1, 7);
+static SENSOR_DEVICE_ATTR_2_RW(in8_crit, max16065_limit, 1, 8);
+static SENSOR_DEVICE_ATTR_2_RW(in9_crit, max16065_limit, 1, 9);
+static SENSOR_DEVICE_ATTR_2_RW(in10_crit, max16065_limit, 1, 10);
+static SENSOR_DEVICE_ATTR_2_RW(in11_crit, max16065_limit, 1, 11);
/* Input voltages min */
-static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 0);
-static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 1);
-static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 2);
-static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 3);
-static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 4);
-static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 5);
-static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 6);
-static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 7);
-static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 8);
-static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 9);
-static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 10);
-static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 11);
+static SENSOR_DEVICE_ATTR_2_RW(in0_min, max16065_limit, 0, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_min, max16065_limit, 0, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_min, max16065_limit, 0, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_min, max16065_limit, 0, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_min, max16065_limit, 0, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_min, max16065_limit, 0, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_min, max16065_limit, 0, 6);
+static SENSOR_DEVICE_ATTR_2_RW(in7_min, max16065_limit, 0, 7);
+static SENSOR_DEVICE_ATTR_2_RW(in8_min, max16065_limit, 0, 8);
+static SENSOR_DEVICE_ATTR_2_RW(in9_min, max16065_limit, 0, 9);
+static SENSOR_DEVICE_ATTR_2_RW(in10_min, max16065_limit, 0, 10);
+static SENSOR_DEVICE_ATTR_2_RW(in11_min, max16065_limit, 0, 11);
/* Input voltages max */
-static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 0);
-static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 1);
-static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 2);
-static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 3);
-static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 4);
-static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 5);
-static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 6);
-static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 7);
-static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 8);
-static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 9);
-static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 10);
-static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, max16065_show_limit,
- max16065_set_limit, 0, 11);
+static SENSOR_DEVICE_ATTR_2_RW(in0_max, max16065_limit, 0, 0);
+static SENSOR_DEVICE_ATTR_2_RW(in1_max, max16065_limit, 0, 1);
+static SENSOR_DEVICE_ATTR_2_RW(in2_max, max16065_limit, 0, 2);
+static SENSOR_DEVICE_ATTR_2_RW(in3_max, max16065_limit, 0, 3);
+static SENSOR_DEVICE_ATTR_2_RW(in4_max, max16065_limit, 0, 4);
+static SENSOR_DEVICE_ATTR_2_RW(in5_max, max16065_limit, 0, 5);
+static SENSOR_DEVICE_ATTR_2_RW(in6_max, max16065_limit, 0, 6);
+static SENSOR_DEVICE_ATTR_2_RW(in7_max, max16065_limit, 0, 7);
+static SENSOR_DEVICE_ATTR_2_RW(in8_max, max16065_limit, 0, 8);
+static SENSOR_DEVICE_ATTR_2_RW(in9_max, max16065_limit, 0, 9);
+static SENSOR_DEVICE_ATTR_2_RW(in10_max, max16065_limit, 0, 10);
+static SENSOR_DEVICE_ATTR_2_RW(in11_max, max16065_limit, 0, 11);
/* alarms */
-static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 0);
-static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 1);
-static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 2);
-static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 3);
-static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 4);
-static SENSOR_DEVICE_ATTR_2(in5_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 5);
-static SENSOR_DEVICE_ATTR_2(in6_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 6);
-static SENSOR_DEVICE_ATTR_2(in7_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 0, 7);
-static SENSOR_DEVICE_ATTR_2(in8_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 1, 0);
-static SENSOR_DEVICE_ATTR_2(in9_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 1, 1);
-static SENSOR_DEVICE_ATTR_2(in10_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 1, 2);
-static SENSOR_DEVICE_ATTR_2(in11_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 1, 3);
+static SENSOR_DEVICE_ATTR_2_RO(in0_alarm, max16065_alarm, 0, 0);
+static SENSOR_DEVICE_ATTR_2_RO(in1_alarm, max16065_alarm, 0, 1);
+static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, max16065_alarm, 0, 2);
+static SENSOR_DEVICE_ATTR_2_RO(in3_alarm, max16065_alarm, 0, 3);
+static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, max16065_alarm, 0, 4);
+static SENSOR_DEVICE_ATTR_2_RO(in5_alarm, max16065_alarm, 0, 5);
+static SENSOR_DEVICE_ATTR_2_RO(in6_alarm, max16065_alarm, 0, 6);
+static SENSOR_DEVICE_ATTR_2_RO(in7_alarm, max16065_alarm, 0, 7);
+static SENSOR_DEVICE_ATTR_2_RO(in8_alarm, max16065_alarm, 1, 0);
+static SENSOR_DEVICE_ATTR_2_RO(in9_alarm, max16065_alarm, 1, 1);
+static SENSOR_DEVICE_ATTR_2_RO(in10_alarm, max16065_alarm, 1, 2);
+static SENSOR_DEVICE_ATTR_2_RO(in11_alarm, max16065_alarm, 1, 3);
/* Current and alarm */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, max16065_show_current, NULL, 0);
-static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, max16065_show_alarm, NULL,
- 1, 4);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, max16065_current, 0);
+static SENSOR_DEVICE_ATTR_2_RO(curr1_alarm, max16065_alarm, 1, 4);
/*
* Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 76d966932941..94e345fb2a78 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -145,7 +145,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
* Sysfs stuff
*/
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -154,8 +154,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index]));
}
-static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct max1619_data *data = dev_get_drvdata(dev);
@@ -180,7 +181,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", data->alarms);
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -188,22 +189,18 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input1);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, t_input2);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_low2);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_high2);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp, set_temp,
- t_crit2);
-static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp,
- set_temp, t_hyst2);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input1);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, t_input2);
+static SENSOR_DEVICE_ATTR_RW(temp2_min, temp, t_low2);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, t_high2);
+static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp, t_crit2);
+static SENSOR_DEVICE_ATTR_RW(temp2_crit_hyst, temp, t_hyst2);
static DEVICE_ATTR_RO(alarms);
-static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
static struct attribute *max1619_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c
index 30a100e70a0d..6d169b4271f7 100644
--- a/drivers/hwmon/max31722.c
+++ b/drivers/hwmon/max31722.c
@@ -50,9 +50,8 @@ static int max31722_set_mode(struct max31722_data *data, u8 mode)
return 0;
}
-static ssize_t max31722_show_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t max31722_temp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct max31722_data *data = dev_get_drvdata(dev);
@@ -64,8 +63,7 @@ static ssize_t max31722_show_temp(struct device *dev,
return sprintf(buf, "%d\n", (s16)le16_to_cpu(ret) * 125 / 32);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
- max31722_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, max31722_temp, 0);
static struct attribute *max31722_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c
index 281491cca510..722bcbb9865a 100644
--- a/drivers/hwmon/max31790.c
+++ b/drivers/hwmon/max31790.c
@@ -252,12 +252,12 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel)
case hwmon_fan_fault:
if (channel < NR_CHANNEL ||
(fan_config & MAX31790_FAN_CFG_TACH_INPUT))
- return S_IRUGO;
+ return 0444;
return 0;
case hwmon_fan_target:
if (channel < NR_CHANNEL &&
!(fan_config & MAX31790_FAN_CFG_TACH_INPUT))
- return S_IRUGO | S_IWUSR;
+ return 0644;
return 0;
default:
return 0;
@@ -353,7 +353,7 @@ static umode_t max31790_pwm_is_visible(const void *_data, u32 attr, int channel)
case hwmon_pwm_input:
case hwmon_pwm_enable:
if (!(fan_config & MAX31790_FAN_CFG_TACH_INPUT))
- return S_IRUGO | S_IWUSR;
+ return 0644;
return 0;
default:
return 0;
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index f98a83c79ff1..fc3ed518f478 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -162,7 +162,7 @@ abort:
return ret;
}
-static ssize_t show_temp_input(struct device *dev,
+static ssize_t temp_input_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
long temp;
@@ -176,7 +176,7 @@ static ssize_t show_temp_input(struct device *dev,
return sprintf(buf, "%ld\n", temp);
}
-static ssize_t show_temp_fault(struct device *dev,
+static ssize_t temp_fault_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct max6639_data *data = max6639_update_device(dev);
@@ -188,7 +188,7 @@ static ssize_t show_temp_fault(struct device *dev,
return sprintf(buf, "%d\n", data->temp_fault[attr->index]);
}
-static ssize_t show_temp_max(struct device *dev,
+static ssize_t temp_max_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
@@ -197,9 +197,9 @@ static ssize_t show_temp_max(struct device *dev,
return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000));
}
-static ssize_t set_temp_max(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static ssize_t temp_max_store(struct device *dev,
+ struct device_attribute *dev_attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
@@ -220,7 +220,7 @@ static ssize_t set_temp_max(struct device *dev,
return count;
}
-static ssize_t show_temp_crit(struct device *dev,
+static ssize_t temp_crit_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
@@ -229,9 +229,9 @@ static ssize_t show_temp_crit(struct device *dev,
return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000));
}
-static ssize_t set_temp_crit(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static ssize_t temp_crit_store(struct device *dev,
+ struct device_attribute *dev_attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
@@ -252,7 +252,7 @@ static ssize_t set_temp_crit(struct device *dev,
return count;
}
-static ssize_t show_temp_emergency(struct device *dev,
+static ssize_t temp_emergency_show(struct device *dev,
struct device_attribute *dev_attr,
char *buf)
{
@@ -262,9 +262,9 @@ static ssize_t show_temp_emergency(struct device *dev,
return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000));
}
-static ssize_t set_temp_emergency(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static ssize_t temp_emergency_store(struct device *dev,
+ struct device_attribute *dev_attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
@@ -285,8 +285,8 @@ static ssize_t set_temp_emergency(struct device *dev,
return count;
}
-static ssize_t show_pwm(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static ssize_t pwm_show(struct device *dev, struct device_attribute *dev_attr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
@@ -294,9 +294,9 @@ static ssize_t show_pwm(struct device *dev,
return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120);
}
-static ssize_t set_pwm(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static ssize_t pwm_store(struct device *dev,
+ struct device_attribute *dev_attr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
@@ -319,7 +319,7 @@ static ssize_t set_pwm(struct device *dev,
return count;
}
-static ssize_t show_fan_input(struct device *dev,
+static ssize_t fan_input_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct max6639_data *data = max6639_update_device(dev);
@@ -332,7 +332,7 @@ static ssize_t show_fan_input(struct device *dev,
data->rpm_range));
}
-static ssize_t show_alarm(struct device *dev,
+static ssize_t alarm_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct max6639_data *data = max6639_update_device(dev);
@@ -344,34 +344,28 @@ static ssize_t show_alarm(struct device *dev,
return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index)));
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 1);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit,
- set_temp_crit, 0);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit,
- set_temp_crit, 1);
-static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO,
- show_temp_emergency, set_temp_emergency, 0);
-static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO,
- show_temp_emergency, set_temp_emergency, 1);
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
-static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
+static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
+static SENSOR_DEVICE_ATTR_RW(temp1_emergency, temp_emergency, 0);
+static SENSOR_DEVICE_ATTR_RW(temp2_emergency, temp_emergency, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 7);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(temp1_emergency_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(temp2_emergency_alarm, alarm, 4);
static struct attribute *max6639_attrs[] = {
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
index 6520bc51d02a..084b2685b7a5 100644
--- a/drivers/hwmon/max6642.c
+++ b/drivers/hwmon/max6642.c
@@ -206,7 +206,7 @@ static struct max6642_data *max6642_update_device(struct device *dev)
* Sysfs stuff
*/
-static ssize_t show_temp_max10(struct device *dev,
+static ssize_t temp_max10_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
@@ -216,8 +216,8 @@ static ssize_t show_temp_max10(struct device *dev,
temp_from_reg10(data->temp_input[attr->index]));
}
-static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t temp_max_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
struct max6642_data *data = max6642_update_device(dev);
@@ -225,8 +225,9 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
}
-static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_max_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
struct max6642_data *data = dev_get_drvdata(dev);
@@ -245,7 +246,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
@@ -253,15 +254,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_max10, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_max10, NULL, 1);
-static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH);
-static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_max10, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_max10, 1);
+static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp_max, 0,
+ MAX6642_REG_W_LOCAL_HIGH);
+static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp_max, 1,
+ MAX6642_REG_W_REMOTE_HIGH);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
static struct attribute *max6642_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 4752a9ee9645..61135a2d0cff 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -52,9 +52,9 @@ static int prescaler;
/* clock: The clock frequency of the chip (max6651 can be clocked externally) */
static int clock = 254000;
-module_param(fan_voltage, int, S_IRUGO);
-module_param(prescaler, int, S_IRUGO);
-module_param(clock, int, S_IRUGO);
+module_param(fan_voltage, int, 0444);
+module_param(prescaler, int, 0444);
+module_param(clock, int, 0444);
/*
* MAX 6650/6651 registers
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 825b922a3f92..ff147e5e1b8c 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -63,8 +63,9 @@ static int mc13783_adc_read(struct device *dev,
return 0;
}
-static ssize_t mc13783_adc_read_bp(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t mc13783_adc_bp_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
unsigned val;
struct platform_device *pdev = to_platform_device(dev);
@@ -86,8 +87,9 @@ static ssize_t mc13783_adc_read_bp(struct device *dev,
return sprintf(buf, "%u\n", val);
}
-static ssize_t mc13783_adc_read_gp(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t mc13783_adc_gp_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
unsigned val;
int ret = mc13783_adc_read(dev, devattr, &val);
@@ -104,8 +106,9 @@ static ssize_t mc13783_adc_read_gp(struct device *dev,
return sprintf(buf, "%u\n", val);
}
-static ssize_t mc13783_adc_read_uid(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t mc13783_adc_uid_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
unsigned int val;
struct platform_device *pdev = to_platform_device(dev);
@@ -125,8 +128,9 @@ static ssize_t mc13783_adc_read_uid(struct device *dev,
return sprintf(buf, "%u\n", val);
}
-static ssize_t mc13783_adc_read_temp(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t mc13783_adc_temp_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
unsigned int val;
struct platform_device *pdev = to_platform_device(dev);
@@ -156,21 +160,20 @@ static ssize_t mc13783_adc_read_temp(struct device *dev,
}
static DEVICE_ATTR_RO(name);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read_gp, NULL, 6);
-static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read_gp, NULL, 7);
-static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read_gp, NULL, 8);
-static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read_gp, NULL, 9);
-static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read_gp, NULL, 10);
-static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read_gp, NULL, 11);
-static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12);
-static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13);
-static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14);
-static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15);
-static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, mc13783_adc_read_uid, NULL, 16);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
- mc13783_adc_read_temp, NULL, 17);
+static SENSOR_DEVICE_ATTR_RO(in2_input, mc13783_adc_bp, 2);
+static SENSOR_DEVICE_ATTR_RO(in5_input, mc13783_adc_gp, 5);
+static SENSOR_DEVICE_ATTR_RO(in6_input, mc13783_adc_gp, 6);
+static SENSOR_DEVICE_ATTR_RO(in7_input, mc13783_adc_gp, 7);
+static SENSOR_DEVICE_ATTR_RO(in8_input, mc13783_adc_gp, 8);
+static SENSOR_DEVICE_ATTR_RO(in9_input, mc13783_adc_gp, 9);
+static SENSOR_DEVICE_ATTR_RO(in10_input, mc13783_adc_gp, 10);
+static SENSOR_DEVICE_ATTR_RO(in11_input, mc13783_adc_gp, 11);
+static SENSOR_DEVICE_ATTR_RO(in12_input, mc13783_adc_gp, 12);
+static SENSOR_DEVICE_ATTR_RO(in13_input, mc13783_adc_gp, 13);
+static SENSOR_DEVICE_ATTR_RO(in14_input, mc13783_adc_gp, 14);
+static SENSOR_DEVICE_ATTR_RO(in15_input, mc13783_adc_gp, 15);
+static SENSOR_DEVICE_ATTR_RO(in16_input, mc13783_adc_uid, 16);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, mc13783_adc_temp, 17);
static struct attribute *mc13783_attr_base[] = {
&dev_attr_name.attr,
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index c3040079b1cb..59ee01f3d022 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -44,8 +44,8 @@
* nct6796d 14 7 7 2+6 0xd420 0xc1 0x5ca3
* nct6797d 14 7 7 2+6 0xd450 0xc1 0x5ca3
* (0xd451)
- * nct6798d 14 7 7 2+6 0xd458 0xc1 0x5ca3
- * (0xd459)
+ * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3
+ * (0xd429)
*
* #temp lists the number of monitored temperature sources (first value) plus
* the number of directly connectable temperature sensors (second value).
@@ -138,7 +138,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
#define SIO_NCT6795_ID 0xd350
#define SIO_NCT6796_ID 0xd420
#define SIO_NCT6797_ID 0xd450
-#define SIO_NCT6798_ID 0xd458
+#define SIO_NCT6798_ID 0xd428
#define SIO_ID_MASK 0xFFF8
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -3594,7 +3594,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
fan5pin |= cr1b & BIT(5);
fan5pin |= creb & BIT(5);
- fan6pin = creb & BIT(3);
+ fan6pin = !dsw_en && (cr2d & BIT(1));
+ fan6pin |= creb & BIT(3);
pwm5pin |= cr2d & BIT(7);
pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
@@ -4508,7 +4509,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
if (data->kind == nct6791 || data->kind == nct6792 ||
data->kind == nct6793 || data->kind == nct6795 ||
- data->kind == nct6796)
+ data->kind == nct6796 || data->kind == nct6797 ||
+ data->kind == nct6798)
nct6791_enable_io_mapping(sioreg);
superio_exit(sioreg);
@@ -4644,7 +4646,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
- sio_data->kind == nct6796)
+ sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
+ sio_data->kind == nct6798)
nct6791_enable_io_mapping(sioaddr);
superio_exit(sioaddr);
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
index 7815ddf149f6..82c7de7b4639 100644
--- a/drivers/hwmon/nct7904.c
+++ b/drivers/hwmon/nct7904.c
@@ -182,7 +182,7 @@ static umode_t nct7904_fan_is_visible(const void *_data, u32 attr, int channel)
const struct nct7904_data *data = _data;
if (attr == hwmon_fan_input && data->fanin_mask & (1 << channel))
- return S_IRUGO;
+ return 0444;
return 0;
}
@@ -225,7 +225,7 @@ static umode_t nct7904_in_is_visible(const void *_data, u32 attr, int channel)
if (channel > 0 && attr == hwmon_in_input &&
(data->vsen_mask & BIT(index)))
- return S_IRUGO;
+ return 0444;
return 0;
}
@@ -260,10 +260,10 @@ static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel)
if (attr == hwmon_temp_input) {
if (channel == 0) {
if (data->vsen_mask & BIT(17))
- return S_IRUGO;
+ return 0444;
} else {
if (data->tcpu_mask & BIT(channel - 1))
- return S_IRUGO;
+ return 0444;
}
}
@@ -325,7 +325,7 @@ static umode_t nct7904_pwm_is_visible(const void *_data, u32 attr, int channel)
switch (attr) {
case hwmon_pwm_input:
case hwmon_pwm_enable:
- return S_IRUGO | S_IWUSR;
+ return 0644;
default:
return 0;
}
diff --git a/drivers/hwmon/nsa320-hwmon.c b/drivers/hwmon/nsa320-hwmon.c
index 5a16109cdea8..f952f803faeb 100644
--- a/drivers/hwmon/nsa320-hwmon.c
+++ b/drivers/hwmon/nsa320-hwmon.c
@@ -114,8 +114,8 @@ static s32 nsa320_hwmon_update(struct device *dev)
return mcu_data;
}
-static ssize_t show_label(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t label_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
int channel = to_sensor_dev_attr(attr)->index;
@@ -144,9 +144,9 @@ static ssize_t fan1_input_show(struct device *dev,
return sprintf(buf, "%d\n", ((mcu_data & 0xff0000) >> 16) * 100);
}
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, NSA320_TEMP);
+static SENSOR_DEVICE_ATTR_RO(temp1_label, label, NSA320_TEMP);
static DEVICE_ATTR_RO(temp1_input);
-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, show_label, NULL, NSA320_FAN);
+static SENSOR_DEVICE_ATTR_RO(fan1_label, label, NSA320_FAN);
static DEVICE_ATTR_RO(fan1_input);
static struct attribute *nsa320_attrs[] = {
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 2823aff82c82..e4f9f7ce92fa 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -37,8 +37,6 @@
#include <linux/iio/consumer.h>
#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/thermal.h>
struct ntc_compensation {
int temp_c;
@@ -588,55 +586,87 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
return -EINVAL;
}
-static int ntc_read_temp(void *data, int *temp)
+static int ntc_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
{
+ struct ntc_data *data = dev_get_drvdata(dev);
int ohm;
- ohm = ntc_thermistor_get_ohm(data);
- if (ohm < 0)
- return ohm;
-
- *temp = get_temp_mc(data, ohm);
-
- return 0;
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ ohm = ntc_thermistor_get_ohm(data);
+ if (ohm < 0)
+ return ohm;
+ *val = get_temp_mc(data, ohm);
+ return 0;
+ case hwmon_temp_type:
+ *val = 4;
+ return 0;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return -EINVAL;
}
-static ssize_t ntc_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static umode_t ntc_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
{
- return sprintf(buf, "4\n");
+ if (type == hwmon_temp) {
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_type:
+ return 0444;
+ default:
+ break;
+ }
+ }
+ return 0;
}
-static ssize_t ntc_temp_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ntc_data *data = dev_get_drvdata(dev);
- int ohm;
+static const u32 ntc_chip_config[] = {
+ HWMON_C_REGISTER_TZ,
+ 0
+};
- ohm = ntc_thermistor_get_ohm(data);
- if (ohm < 0)
- return ohm;
+static const struct hwmon_channel_info ntc_chip = {
+ .type = hwmon_chip,
+ .config = ntc_chip_config,
+};
- return sprintf(buf, "%d\n", get_temp_mc(data, ohm));
-}
+static const u32 ntc_temp_config[] = {
+ HWMON_T_INPUT, HWMON_T_TYPE,
+ 0
+};
-static SENSOR_DEVICE_ATTR_RO(temp1_type, ntc_type, 0);
-static SENSOR_DEVICE_ATTR_RO(temp1_input, ntc_temp, 0);
+static const struct hwmon_channel_info ntc_temp = {
+ .type = hwmon_temp,
+ .config = ntc_temp_config,
+};
-static struct attribute *ntc_attrs[] = {
- &sensor_dev_attr_temp1_type.dev_attr.attr,
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- NULL,
+static const struct hwmon_channel_info *ntc_info[] = {
+ &ntc_chip,
+ &ntc_temp,
+ NULL
};
-ATTRIBUTE_GROUPS(ntc);
-static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = {
- .get_temp = ntc_read_temp,
+static const struct hwmon_ops ntc_hwmon_ops = {
+ .is_visible = ntc_is_visible,
+ .read = ntc_read,
+};
+
+static const struct hwmon_chip_info ntc_chip_info = {
+ .ops = &ntc_hwmon_ops,
+ .info = ntc_info,
};
static int ntc_thermistor_probe(struct platform_device *pdev)
{
- struct thermal_zone_device *tz;
struct device *dev = &pdev->dev;
const struct of_device_id *of_id =
of_match_device(of_match_ptr(ntc_match), dev);
@@ -697,8 +727,9 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
data->comp = ntc_type[pdev_id->driver_data].comp;
data->n_comp = ntc_type[pdev_id->driver_data].n_comp;
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, pdev_id->name,
- data, ntc_groups);
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, pdev_id->name,
+ data, &ntc_chip_info,
+ NULL);
if (IS_ERR(hwmon_dev)) {
dev_err(dev, "unable to register as hwmon device.\n");
return PTR_ERR(hwmon_dev);
@@ -707,11 +738,6 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
dev_info(dev, "Thermistor type: %s successfully probed.\n",
pdev_id->name);
- tz = devm_thermal_zone_of_sensor_register(dev, 0, data,
- &ntc_of_thermal_ops);
- if (IS_ERR(tz))
- dev_dbg(dev, "Failed to register to thermal fw.\n");
-
return 0;
}
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 423903f87955..b91a80abf724 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright IBM Corp 2019
#include <linux/device.h>
#include <linux/hwmon.h>
@@ -380,8 +381,8 @@ static ssize_t occ_show_power_1(struct device *dev,
val *= 1000000ULL;
break;
case 2:
- val = get_unaligned_be32(&power->update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->update_tag) *
+ occ->powr_sample_time_us;
break;
case 3:
val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -425,8 +426,8 @@ static ssize_t occ_show_power_2(struct device *dev,
&power->update_tag);
break;
case 2:
- val = get_unaligned_be32(&power->update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->update_tag) *
+ occ->powr_sample_time_us;
break;
case 3:
val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -463,8 +464,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
&power->system.update_tag);
break;
case 2:
- val = get_unaligned_be32(&power->system.update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->system.update_tag) *
+ occ->powr_sample_time_us;
break;
case 3:
val = get_unaligned_be16(&power->system.value) * 1000000ULL;
@@ -477,8 +478,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
&power->proc.update_tag);
break;
case 6:
- val = get_unaligned_be32(&power->proc.update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->proc.update_tag) *
+ occ->powr_sample_time_us;
break;
case 7:
val = get_unaligned_be16(&power->proc.value) * 1000000ULL;
@@ -491,8 +492,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
&power->vdd.update_tag);
break;
case 10:
- val = get_unaligned_be32(&power->vdd.update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
+ occ->powr_sample_time_us;
break;
case 11:
val = get_unaligned_be16(&power->vdd.value) * 1000000ULL;
@@ -505,8 +506,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
&power->vdn.update_tag);
break;
case 14:
- val = get_unaligned_be32(&power->vdn.update_tag) *
- occ->powr_sample_time_us;
+ val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
+ occ->powr_sample_time_us;
break;
case 15:
val = get_unaligned_be16(&power->vdn.value) * 1000000ULL;
diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h
index 7c44df3f5631..ed2cf4245295 100644
--- a/drivers/hwmon/occ/common.h
+++ b/drivers/hwmon/occ/common.h
@@ -1,4 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright IBM Corp 2019 */
#ifndef OCC_COMMON_H
#define OCC_COMMON_H
diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c
index b59efc945e54..76fb7870c7d3 100644
--- a/drivers/hwmon/occ/p8_i2c.c
+++ b/drivers/hwmon/occ/p8_i2c.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright IBM Corp 2019
#include <linux/device.h>
#include <linux/errno.h>
diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index b65c1d1dfb54..f6387cc0b754 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright IBM Corp 2019
#include <linux/device.h>
#include <linux/errno.h>
diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c
index 743b26ec8e54..fe3d15e416e7 100644
--- a/drivers/hwmon/occ/sysfs.c
+++ b/drivers/hwmon/occ/sysfs.c
@@ -1,14 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * OCC hwmon driver sysfs interface
- *
- * Copyright (C) IBM Corporation 2018
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright IBM Corp 2019
#include <linux/bitops.h>
#include <linux/device.h>
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 7e3697727537..56584f9ab803 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -254,7 +254,7 @@ static struct platform_driver pc87360_driver = {
* Sysfs stuff
*/
-static ssize_t show_fan_input(struct device *dev,
+static ssize_t fan_input_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -262,7 +262,7 @@ static ssize_t show_fan_input(struct device *dev,
return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
FAN_DIV_FROM_REG(data->fan_status[attr->index])));
}
-static ssize_t show_fan_min(struct device *dev,
+static ssize_t fan_min_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -270,7 +270,7 @@ static ssize_t show_fan_min(struct device *dev,
return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
FAN_DIV_FROM_REG(data->fan_status[attr->index])));
}
-static ssize_t show_fan_div(struct device *dev,
+static ssize_t fan_div_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -278,7 +278,7 @@ static ssize_t show_fan_div(struct device *dev,
return sprintf(buf, "%u\n",
FAN_DIV_FROM_REG(data->fan_status[attr->index]));
}
-static ssize_t show_fan_status(struct device *dev,
+static ssize_t fan_status_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -286,9 +286,9 @@ static ssize_t show_fan_status(struct device *dev,
return sprintf(buf, "%u\n",
FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
}
-static ssize_t set_fan_min(struct device *dev,
- struct device_attribute *devattr, const char *buf,
- size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -325,24 +325,24 @@ static ssize_t set_fan_min(struct device *dev,
}
static struct sensor_device_attribute fan_input[] = {
- SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0),
- SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1),
- SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2),
+ SENSOR_ATTR_RO(fan1_input, fan_input, 0),
+ SENSOR_ATTR_RO(fan2_input, fan_input, 1),
+ SENSOR_ATTR_RO(fan3_input, fan_input, 2),
};
static struct sensor_device_attribute fan_status[] = {
- SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0),
- SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1),
- SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2),
+ SENSOR_ATTR_RO(fan1_status, fan_status, 0),
+ SENSOR_ATTR_RO(fan2_status, fan_status, 1),
+ SENSOR_ATTR_RO(fan3_status, fan_status, 2),
};
static struct sensor_device_attribute fan_div[] = {
- SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
- SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
- SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
+ SENSOR_ATTR_RO(fan1_div, fan_div, 0),
+ SENSOR_ATTR_RO(fan2_div, fan_div, 1),
+ SENSOR_ATTR_RO(fan3_div, fan_div, 2),
};
static struct sensor_device_attribute fan_min[] = {
- SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0),
- SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1),
- SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
+ SENSOR_ATTR_RW(fan1_min, fan_min, 0),
+ SENSOR_ATTR_RW(fan2_min, fan_min, 1),
+ SENSOR_ATTR_RW(fan3_min, fan_min, 2),
};
#define FAN_UNIT_ATTRS(X) \
@@ -353,7 +353,7 @@ static struct sensor_device_attribute fan_min[] = {
NULL \
}
-static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -363,8 +363,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
FAN_CONFIG_INVERT(data->fan_conf,
attr->index)));
}
-static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -385,9 +385,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
}
static struct sensor_device_attribute pwm[] = {
- SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0),
- SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1),
- SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
+ SENSOR_ATTR_RW(pwm1, pwm, 0),
+ SENSOR_ATTR_RW(pwm2, pwm, 1),
+ SENSOR_ATTR_RW(pwm3, pwm, 2),
};
static struct attribute *pc8736x_fan_attr[][5] = {
@@ -402,7 +402,7 @@ static const struct attribute_group pc8736x_fan_attr_group[] = {
{ .attrs = pc8736x_fan_attr[2], },
};
-static ssize_t show_in_input(struct device *dev,
+static ssize_t in_input_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -410,7 +410,7 @@ static ssize_t show_in_input(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
data->in_vref));
}
-static ssize_t show_in_min(struct device *dev,
+static ssize_t in_min_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -418,7 +418,7 @@ static ssize_t show_in_min(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
data->in_vref));
}
-static ssize_t show_in_max(struct device *dev,
+static ssize_t in_max_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -426,15 +426,16 @@ static ssize_t show_in_max(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
data->in_vref));
}
-static ssize_t show_in_status(struct device *dev,
+static ssize_t in_status_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = pc87360_update_device(dev);
return sprintf(buf, "%u\n", data->in_status[attr->index]);
}
-static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t in_min_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -452,8 +453,9 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
mutex_unlock(&data->update_lock);
return count;
}
-static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t in_max_store(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -474,56 +476,56 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr,
}
static struct sensor_device_attribute in_input[] = {
- SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0),
- SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1),
- SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2),
- SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3),
- SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4),
- SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5),
- SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6),
- SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7),
- SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8),
- SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9),
- SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10),
+ SENSOR_ATTR_RO(in0_input, in_input, 0),
+ SENSOR_ATTR_RO(in1_input, in_input, 1),
+ SENSOR_ATTR_RO(in2_input, in_input, 2),
+ SENSOR_ATTR_RO(in3_input, in_input, 3),
+ SENSOR_ATTR_RO(in4_input, in_input, 4),
+ SENSOR_ATTR_RO(in5_input, in_input, 5),
+ SENSOR_ATTR_RO(in6_input, in_input, 6),
+ SENSOR_ATTR_RO(in7_input, in_input, 7),
+ SENSOR_ATTR_RO(in8_input, in_input, 8),
+ SENSOR_ATTR_RO(in9_input, in_input, 9),
+ SENSOR_ATTR_RO(in10_input, in_input, 10),
};
static struct sensor_device_attribute in_status[] = {
- SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0),
- SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1),
- SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2),
- SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3),
- SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4),
- SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5),
- SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6),
- SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7),
- SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8),
- SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9),
- SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10),
+ SENSOR_ATTR_RO(in0_status, in_status, 0),
+ SENSOR_ATTR_RO(in1_status, in_status, 1),
+ SENSOR_ATTR_RO(in2_status, in_status, 2),
+ SENSOR_ATTR_RO(in3_status, in_status, 3),
+ SENSOR_ATTR_RO(in4_status, in_status, 4),
+ SENSOR_ATTR_RO(in5_status, in_status, 5),
+ SENSOR_ATTR_RO(in6_status, in_status, 6),
+ SENSOR_ATTR_RO(in7_status, in_status, 7),
+ SENSOR_ATTR_RO(in8_status, in_status, 8),
+ SENSOR_ATTR_RO(in9_status, in_status, 9),
+ SENSOR_ATTR_RO(in10_status, in_status, 10),
};
static struct sensor_device_attribute in_min[] = {
- SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0),
- SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1),
- SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2),
- SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3),
- SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4),
- SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5),
- SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6),
- SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7),
- SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8),
- SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9),
- SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10),
+ SENSOR_ATTR_RW(in0_min, in_min, 0),
+ SENSOR_ATTR_RW(in1_min, in_min, 1),
+ SENSOR_ATTR_RW(in2_min, in_min, 2),
+ SENSOR_ATTR_RW(in3_min, in_min, 3),
+ SENSOR_ATTR_RW(in4_min, in_min, 4),
+ SENSOR_ATTR_RW(in5_min, in_min, 5),
+ SENSOR_ATTR_RW(in6_min, in_min, 6),
+ SENSOR_ATTR_RW(in7_min, in_min, 7),
+ SENSOR_ATTR_RW(in8_min, in_min, 8),
+ SENSOR_ATTR_RW(in9_min, in_min, 9),
+ SENSOR_ATTR_RW(in10_min, in_min, 10),
};
static struct sensor_device_attribute in_max[] = {
- SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0),
- SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1),
- SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2),
- SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3),
- SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4),
- SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5),
- SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6),
- SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7),
- SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8),
- SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9),
- SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
+ SENSOR_ATTR_RW(in0_max, in_max, 0),
+ SENSOR_ATTR_RW(in1_max, in_max, 1),
+ SENSOR_ATTR_RW(in2_max, in_max, 2),
+ SENSOR_ATTR_RW(in3_max, in_max, 3),
+ SENSOR_ATTR_RW(in4_max, in_max, 4),
+ SENSOR_ATTR_RW(in5_max, in_max, 5),
+ SENSOR_ATTR_RW(in6_max, in_max, 6),
+ SENSOR_ATTR_RW(in7_max, in_max, 7),
+ SENSOR_ATTR_RW(in8_max, in_max, 8),
+ SENSOR_ATTR_RW(in9_max, in_max, 9),
+ SENSOR_ATTR_RW(in10_max, in_max, 10),
};
/* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */
@@ -537,16 +539,16 @@ static struct sensor_device_attribute in_max[] = {
* 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms)
*/
-static ssize_t show_in_min_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t in_min_alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
}
-static ssize_t show_in_max_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t in_max_alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -555,30 +557,30 @@ static ssize_t show_in_max_alarm(struct device *dev,
}
static struct sensor_device_attribute in_min_alarm[] = {
- SENSOR_ATTR(in0_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 0),
- SENSOR_ATTR(in1_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 1),
- SENSOR_ATTR(in2_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 2),
- SENSOR_ATTR(in3_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 3),
- SENSOR_ATTR(in4_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 4),
- SENSOR_ATTR(in5_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 5),
- SENSOR_ATTR(in6_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 6),
- SENSOR_ATTR(in7_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 7),
- SENSOR_ATTR(in8_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 8),
- SENSOR_ATTR(in9_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 9),
- SENSOR_ATTR(in10_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 10),
+ SENSOR_ATTR_RO(in0_min_alarm, in_min_alarm, 0),
+ SENSOR_ATTR_RO(in1_min_alarm, in_min_alarm, 1),
+ SENSOR_ATTR_RO(in2_min_alarm, in_min_alarm, 2),
+ SENSOR_ATTR_RO(in3_min_alarm, in_min_alarm, 3),
+ SENSOR_ATTR_RO(in4_min_alarm, in_min_alarm, 4),
+ SENSOR_ATTR_RO(in5_min_alarm, in_min_alarm, 5),
+ SENSOR_ATTR_RO(in6_min_alarm, in_min_alarm, 6),
+ SENSOR_ATTR_RO(in7_min_alarm, in_min_alarm, 7),
+ SENSOR_ATTR_RO(in8_min_alarm, in_min_alarm, 8),
+ SENSOR_ATTR_RO(in9_min_alarm, in_min_alarm, 9),
+ SENSOR_ATTR_RO(in10_min_alarm, in_min_alarm, 10),
};
static struct sensor_device_attribute in_max_alarm[] = {
- SENSOR_ATTR(in0_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 0),
- SENSOR_ATTR(in1_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 1),
- SENSOR_ATTR(in2_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 2),
- SENSOR_ATTR(in3_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 3),
- SENSOR_ATTR(in4_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 4),
- SENSOR_ATTR(in5_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 5),
- SENSOR_ATTR(in6_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 6),
- SENSOR_ATTR(in7_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 7),
- SENSOR_ATTR(in8_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 8),
- SENSOR_ATTR(in9_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 9),
- SENSOR_ATTR(in10_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 10),
+ SENSOR_ATTR_RO(in0_max_alarm, in_max_alarm, 0),
+ SENSOR_ATTR_RO(in1_max_alarm, in_max_alarm, 1),
+ SENSOR_ATTR_RO(in2_max_alarm, in_max_alarm, 2),
+ SENSOR_ATTR_RO(in3_max_alarm, in_max_alarm, 3),
+ SENSOR_ATTR_RO(in4_max_alarm, in_max_alarm, 4),
+ SENSOR_ATTR_RO(in5_max_alarm, in_max_alarm, 5),
+ SENSOR_ATTR_RO(in6_max_alarm, in_max_alarm, 6),
+ SENSOR_ATTR_RO(in7_max_alarm, in_max_alarm, 7),
+ SENSOR_ATTR_RO(in8_max_alarm, in_max_alarm, 8),
+ SENSOR_ATTR_RO(in9_max_alarm, in_max_alarm, 9),
+ SENSOR_ATTR_RO(in10_max_alarm, in_max_alarm, 10),
};
#define VIN_UNIT_ATTRS(X) \
@@ -651,7 +653,7 @@ static const struct attribute_group pc8736x_vin_group = {
.attrs = pc8736x_vin_attr_array,
};
-static ssize_t show_therm_input(struct device *dev,
+static ssize_t therm_input_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -659,7 +661,7 @@ static ssize_t show_therm_input(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
data->in_vref));
}
-static ssize_t show_therm_min(struct device *dev,
+static ssize_t therm_min_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -667,7 +669,7 @@ static ssize_t show_therm_min(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
data->in_vref));
}
-static ssize_t show_therm_max(struct device *dev,
+static ssize_t therm_max_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -675,7 +677,7 @@ static ssize_t show_therm_max(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
data->in_vref));
}
-static ssize_t show_therm_crit(struct device *dev,
+static ssize_t therm_crit_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -683,7 +685,7 @@ static ssize_t show_therm_crit(struct device *dev,
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
data->in_vref));
}
-static ssize_t show_therm_status(struct device *dev,
+static ssize_t therm_status_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -691,9 +693,9 @@ static ssize_t show_therm_status(struct device *dev,
return sprintf(buf, "%u\n", data->in_status[attr->index]);
}
-static ssize_t set_therm_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t therm_min_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -712,9 +714,9 @@ static ssize_t set_therm_min(struct device *dev,
return count;
}
-static ssize_t set_therm_max(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t therm_max_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -732,9 +734,9 @@ static ssize_t set_therm_max(struct device *dev,
mutex_unlock(&data->update_lock);
return count;
}
-static ssize_t set_therm_crit(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t therm_crit_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -758,38 +760,29 @@ static ssize_t set_therm_crit(struct device *dev,
* used in the chip to measure voltage across the thermistors
*/
static struct sensor_device_attribute therm_input[] = {
- SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0 + 11),
- SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1 + 11),
- SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2 + 11),
+ SENSOR_ATTR_RO(temp4_input, therm_input, 0 + 11),
+ SENSOR_ATTR_RO(temp5_input, therm_input, 1 + 11),
+ SENSOR_ATTR_RO(temp6_input, therm_input, 2 + 11),
};
static struct sensor_device_attribute therm_status[] = {
- SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0 + 11),
- SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1 + 11),
- SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2 + 11),
+ SENSOR_ATTR_RO(temp4_status, therm_status, 0 + 11),
+ SENSOR_ATTR_RO(temp5_status, therm_status, 1 + 11),
+ SENSOR_ATTR_RO(temp6_status, therm_status, 2 + 11),
};
static struct sensor_device_attribute therm_min[] = {
- SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR,
- show_therm_min, set_therm_min, 0 + 11),
- SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR,
- show_therm_min, set_therm_min, 1 + 11),
- SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR,
- show_therm_min, set_therm_min, 2 + 11),
+ SENSOR_ATTR_RW(temp4_min, therm_min, 0 + 11),
+ SENSOR_ATTR_RW(temp5_min, therm_min, 1 + 11),
+ SENSOR_ATTR_RW(temp6_min, therm_min, 2 + 11),
};
static struct sensor_device_attribute therm_max[] = {
- SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR,
- show_therm_max, set_therm_max, 0 + 11),
- SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR,
- show_therm_max, set_therm_max, 1 + 11),
- SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR,
- show_therm_max, set_therm_max, 2 + 11),
+ SENSOR_ATTR_RW(temp4_max, therm_max, 0 + 11),
+ SENSOR_ATTR_RW(temp5_max, therm_max, 1 + 11),
+ SENSOR_ATTR_RW(temp6_max, therm_max, 2 + 11),
};
static struct sensor_device_attribute therm_crit[] = {
- SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
- show_therm_crit, set_therm_crit, 0 + 11),
- SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR,
- show_therm_crit, set_therm_crit, 1 + 11),
- SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR,
- show_therm_crit, set_therm_crit, 2 + 11),
+ SENSOR_ATTR_RW(temp4_crit, therm_crit, 0 + 11),
+ SENSOR_ATTR_RW(temp5_crit, therm_crit, 1 + 11),
+ SENSOR_ATTR_RW(temp6_crit, therm_crit, 2 + 11),
};
/*
@@ -797,24 +790,27 @@ static struct sensor_device_attribute therm_crit[] = {
* status register (sec 11.5.12)
*/
-static ssize_t show_therm_min_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t therm_min_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
}
-static ssize_t show_therm_max_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t therm_max_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
}
-static ssize_t show_therm_crit_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t therm_crit_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -823,28 +819,19 @@ static ssize_t show_therm_crit_alarm(struct device *dev,
}
static struct sensor_device_attribute therm_min_alarm[] = {
- SENSOR_ATTR(temp4_min_alarm, S_IRUGO,
- show_therm_min_alarm, NULL, 0 + 11),
- SENSOR_ATTR(temp5_min_alarm, S_IRUGO,
- show_therm_min_alarm, NULL, 1 + 11),
- SENSOR_ATTR(temp6_min_alarm, S_IRUGO,
- show_therm_min_alarm, NULL, 2 + 11),
+ SENSOR_ATTR_RO(temp4_min_alarm, therm_min_alarm, 0 + 11),
+ SENSOR_ATTR_RO(temp5_min_alarm, therm_min_alarm, 1 + 11),
+ SENSOR_ATTR_RO(temp6_min_alarm, therm_min_alarm, 2 + 11),
};
static struct sensor_device_attribute therm_max_alarm[] = {
- SENSOR_ATTR(temp4_max_alarm, S_IRUGO,
- show_therm_max_alarm, NULL, 0 + 11),
- SENSOR_ATTR(temp5_max_alarm, S_IRUGO,
- show_therm_max_alarm, NULL, 1 + 11),
- SENSOR_ATTR(temp6_max_alarm, S_IRUGO,
- show_therm_max_alarm, NULL, 2 + 11),
+ SENSOR_ATTR_RO(temp4_max_alarm, therm_max_alarm, 0 + 11),
+ SENSOR_ATTR_RO(temp5_max_alarm, therm_max_alarm, 1 + 11),
+ SENSOR_ATTR_RO(temp6_max_alarm, therm_max_alarm, 2 + 11),
};
static struct sensor_device_attribute therm_crit_alarm[] = {
- SENSOR_ATTR(temp4_crit_alarm, S_IRUGO,
- show_therm_crit_alarm, NULL, 0 + 11),
- SENSOR_ATTR(temp5_crit_alarm, S_IRUGO,
- show_therm_crit_alarm, NULL, 1 + 11),
- SENSOR_ATTR(temp6_crit_alarm, S_IRUGO,
- show_therm_crit_alarm, NULL, 2 + 11),
+ SENSOR_ATTR_RO(temp4_crit_alarm, therm_crit_alarm, 0 + 11),
+ SENSOR_ATTR_RO(temp5_crit_alarm, therm_crit_alarm, 1 + 11),
+ SENSOR_ATTR_RO(temp6_crit_alarm, therm_crit_alarm, 2 + 11),
};
#define THERM_UNIT_ATTRS(X) \
@@ -867,7 +854,7 @@ static const struct attribute_group pc8736x_therm_group = {
.attrs = pc8736x_therm_attr_array,
};
-static ssize_t show_temp_input(struct device *dev,
+static ssize_t temp_input_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -875,7 +862,7 @@ static ssize_t show_temp_input(struct device *dev,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t show_temp_min(struct device *dev,
+static ssize_t temp_min_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -883,7 +870,7 @@ static ssize_t show_temp_min(struct device *dev,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
}
-static ssize_t show_temp_max(struct device *dev,
+static ssize_t temp_max_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -891,7 +878,7 @@ static ssize_t show_temp_max(struct device *dev,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
}
-static ssize_t show_temp_crit(struct device *dev,
+static ssize_t temp_crit_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -900,7 +887,7 @@ static ssize_t show_temp_crit(struct device *dev,
TEMP_FROM_REG(data->temp_crit[attr->index]));
}
-static ssize_t show_temp_status(struct device *dev,
+static ssize_t temp_status_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -908,9 +895,9 @@ static ssize_t show_temp_status(struct device *dev,
return sprintf(buf, "%d\n", data->temp_status[attr->index]);
}
-static ssize_t set_temp_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_min_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -929,9 +916,9 @@ static ssize_t set_temp_min(struct device *dev,
return count;
}
-static ssize_t set_temp_max(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t temp_max_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -950,9 +937,9 @@ static ssize_t set_temp_max(struct device *dev,
return count;
}
-static ssize_t set_temp_crit(struct device *dev,
- struct device_attribute *devattr, const char *buf,
- size_t count)
+static ssize_t temp_crit_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pc87360_data *data = dev_get_drvdata(dev);
@@ -972,38 +959,29 @@ static ssize_t set_temp_crit(struct device *dev,
}
static struct sensor_device_attribute temp_input[] = {
- SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0),
- SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1),
- SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2),
+ SENSOR_ATTR_RO(temp1_input, temp_input, 0),
+ SENSOR_ATTR_RO(temp2_input, temp_input, 1),
+ SENSOR_ATTR_RO(temp3_input, temp_input, 2),
};
static struct sensor_device_attribute temp_status[] = {
- SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0),
- SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1),
- SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2),
+ SENSOR_ATTR_RO(temp1_status, temp_status, 0),
+ SENSOR_ATTR_RO(temp2_status, temp_status, 1),
+ SENSOR_ATTR_RO(temp3_status, temp_status, 2),
};
static struct sensor_device_attribute temp_min[] = {
- SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR,
- show_temp_min, set_temp_min, 0),
- SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR,
- show_temp_min, set_temp_min, 1),
- SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR,
- show_temp_min, set_temp_min, 2),
+ SENSOR_ATTR_RW(temp1_min, temp_min, 0),
+ SENSOR_ATTR_RW(temp2_min, temp_min, 1),
+ SENSOR_ATTR_RW(temp3_min, temp_min, 2),
};
static struct sensor_device_attribute temp_max[] = {
- SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
- show_temp_max, set_temp_max, 0),
- SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
- show_temp_max, set_temp_max, 1),
- SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
- show_temp_max, set_temp_max, 2),
+ SENSOR_ATTR_RW(temp1_max, temp_max, 0),
+ SENSOR_ATTR_RW(temp2_max, temp_max, 1),
+ SENSOR_ATTR_RW(temp3_max, temp_max, 2),
};
static struct sensor_device_attribute temp_crit[] = {
- SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
- show_temp_crit, set_temp_crit, 0),
- SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR,
- show_temp_crit, set_temp_crit, 1),
- SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR,
- show_temp_crit, set_temp_crit, 2),
+ SENSOR_ATTR_RW(temp1_crit, temp_crit, 0),
+ SENSOR_ATTR_RW(temp2_crit, temp_crit, 1),
+ SENSOR_ATTR_RW(temp3_crit, temp_crit, 2),
};
static ssize_t alarms_temp_show(struct device *dev,
@@ -1021,8 +999,9 @@ static DEVICE_ATTR_RO(alarms_temp);
* 12.3.2) that show_temp_alarm() reads (via data->temp_alarms)
*/
-static ssize_t show_temp_min_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_min_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -1030,8 +1009,9 @@ static ssize_t show_temp_min_alarm(struct device *dev,
return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN));
}
-static ssize_t show_temp_max_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_max_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -1039,8 +1019,9 @@ static ssize_t show_temp_max_alarm(struct device *dev,
return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX));
}
-static ssize_t show_temp_crit_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_crit_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -1049,26 +1030,26 @@ static ssize_t show_temp_crit_alarm(struct device *dev,
}
static struct sensor_device_attribute temp_min_alarm[] = {
- SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 0),
- SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1),
- SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2),
+ SENSOR_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0),
+ SENSOR_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1),
+ SENSOR_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2),
};
static struct sensor_device_attribute temp_max_alarm[] = {
- SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0),
- SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1),
- SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2),
+ SENSOR_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0),
+ SENSOR_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1),
+ SENSOR_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2),
};
static struct sensor_device_attribute temp_crit_alarm[] = {
- SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0),
- SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1),
- SENSOR_ATTR(temp3_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 2),
+ SENSOR_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0),
+ SENSOR_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1),
+ SENSOR_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2),
};
#define TEMP_FAULT 0x40 /* open diode */
-static ssize_t show_temp_fault(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
unsigned nr = to_sensor_dev_attr(devattr)->index;
@@ -1076,9 +1057,9 @@ static ssize_t show_temp_fault(struct device *dev,
return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT));
}
static struct sensor_device_attribute temp_fault[] = {
- SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0),
- SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1),
- SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2),
+ SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
+ SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
+ SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
};
#define TEMP_UNIT_ATTRS(X) \
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index dc5a9d5ada51..d1a3f2040c00 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -384,8 +384,8 @@ done:
return data;
}
-static ssize_t show_fan_input(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_input_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -393,8 +393,8 @@ static ssize_t show_fan_input(struct device *dev, struct device_attribute
return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
}
-static ssize_t show_fan_min(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_min_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -402,8 +402,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute
return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
}
-static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -412,8 +412,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
& FAN_STATUS_LOSPD));
}
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -422,8 +422,9 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute
& FAN_STATUS_STALL));
}
-static ssize_t set_fan_min(struct device *dev, struct device_attribute
- *devattr, const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct pc87427_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -449,49 +450,41 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
return count;
}
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
-static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
-static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
-
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 2);
-static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 3);
-static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 4);
-static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 5);
-static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 6);
-static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
- show_fan_min, set_fan_min, 7);
-
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
-
-static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
-static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
-static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_input, fan_input, 3);
+static SENSOR_DEVICE_ATTR_RO(fan5_input, fan_input, 4);
+static SENSOR_DEVICE_ATTR_RO(fan6_input, fan_input, 5);
+static SENSOR_DEVICE_ATTR_RO(fan7_input, fan_input, 6);
+static SENSOR_DEVICE_ATTR_RO(fan8_input, fan_input, 7);
+
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
+static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
+static SENSOR_DEVICE_ATTR_RW(fan5_min, fan_min, 4);
+static SENSOR_DEVICE_ATTR_RW(fan6_min, fan_min, 5);
+static SENSOR_DEVICE_ATTR_RW(fan7_min, fan_min, 6);
+static SENSOR_DEVICE_ATTR_RW(fan8_min, fan_min, 7);
+
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, fan_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, fan_alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_alarm, fan_alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_alarm, fan_alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(fan5_alarm, fan_alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(fan6_alarm, fan_alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(fan7_alarm, fan_alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(fan8_alarm, fan_alarm, 7);
+
+static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan_fault, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_fault, fan_fault, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_fault, fan_fault, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_fault, fan_fault, 3);
+static SENSOR_DEVICE_ATTR_RO(fan5_fault, fan_fault, 4);
+static SENSOR_DEVICE_ATTR_RO(fan6_fault, fan_fault, 5);
+static SENSOR_DEVICE_ATTR_RO(fan7_fault, fan_fault, 6);
+static SENSOR_DEVICE_ATTR_RO(fan8_fault, fan_fault, 7);
static struct attribute *pc87427_attributes_fan[8][5] = {
{
@@ -568,8 +561,8 @@ static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode)
outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE);
}
-static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t pwm_enable_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -581,8 +574,9 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", pwm_enable);
}
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
- *devattr, const char *buf, size_t count)
+static ssize_t pwm_enable_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct pc87427_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -602,8 +596,8 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
return count;
}
-static ssize_t show_pwm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -611,8 +605,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", (int)data->pwm[nr]);
}
-static ssize_t set_pwm(struct device *dev, struct device_attribute
- *devattr, const char *buf, size_t count)
+static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct pc87427_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -657,19 +651,15 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute
return count;
}
-static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, set_pwm_enable, 2);
-static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
- show_pwm_enable, set_pwm_enable, 3);
+static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2);
+static SENSOR_DEVICE_ATTR_RW(pwm4_enable, pwm_enable, 3);
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
-static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
-static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
-static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3);
+static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2);
+static SENSOR_DEVICE_ATTR_RW(pwm4, pwm, 3);
static struct attribute *pc87427_attributes_pwm[4][3] = {
{
@@ -698,8 +688,8 @@ static const struct attribute_group pc87427_group_pwm[4] = {
{ .attrs = pc87427_attributes_pwm[3] },
};
-static ssize_t show_temp_input(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_input_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -707,8 +697,8 @@ static ssize_t show_temp_input(struct device *dev, struct device_attribute
return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
}
-static ssize_t show_temp_min(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_min_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -716,8 +706,8 @@ static ssize_t show_temp_min(struct device *dev, struct device_attribute
return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr]));
}
-static ssize_t show_temp_max(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_max_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -725,8 +715,8 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute
return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr]));
}
-static ssize_t show_temp_crit(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_crit_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -734,8 +724,8 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute
return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr]));
}
-static ssize_t show_temp_type(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_type_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -743,8 +733,9 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute
return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr]));
}
-static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_min_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -753,8 +744,9 @@ static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute
& TEMP_STATUS_LOWFLG));
}
-static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_max_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -763,8 +755,9 @@ static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute
& TEMP_STATUS_HIGHFLG));
}
-static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_crit_alarm_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -773,8 +766,8 @@ static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute
& TEMP_STATUS_CRITFLG));
}
-static ssize_t show_temp_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87427_data *data = pc87427_update_device(dev);
int nr = to_sensor_dev_attr(devattr)->index;
@@ -783,86 +776,68 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute
& TEMP_STATUS_SENSERR));
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO,
- show_temp_min_alarm, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO,
- show_temp_max_alarm, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO,
- show_temp_crit_alarm, NULL, 5);
-
-static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_input, temp_input, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_input, temp_input, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_input, temp_input, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_min, temp_min, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_min, temp_min, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_min, temp_min, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_min, temp_min, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_min, temp_min, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_min, temp_min, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_max, temp_max, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_max, temp_max, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_max, temp_max, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_max, temp_max, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp_crit, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp_crit, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_crit, temp_crit, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp_crit, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_crit, temp_crit, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_crit, temp_crit, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_type, temp_type, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_type, temp_type, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_type, temp_type, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_type, temp_type, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_type, temp_type, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_type, temp_type, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_min_alarm, temp_min_alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_min_alarm, temp_min_alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_min_alarm, temp_min_alarm, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, temp_max_alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_max_alarm, temp_max_alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, temp_max_alarm, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, temp_crit_alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, temp_crit_alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, temp_crit_alarm, 5);
+
+static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_fault, temp_fault, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_fault, temp_fault, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_fault, temp_fault, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_fault, temp_fault, 5);
static struct attribute *pc87427_attributes_temp[6][10] = {
{
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index 7688dab32f6e..f05eaa50535e 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -28,6 +28,11 @@
#include <linux/pmbus.h>
#include "pmbus.h"
+struct pmbus_device_info {
+ int pages;
+ u32 flags;
+};
+
/*
* Find sensor groups and status registers on each page.
*/
@@ -172,13 +177,14 @@ static int pmbus_probe(struct i2c_client *client,
struct pmbus_driver_info *info;
struct pmbus_platform_data *pdata = NULL;
struct device *dev = &client->dev;
+ struct pmbus_device_info *device_info;
info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- if (!strcmp(id->name, "dps460") || !strcmp(id->name, "dps800") ||
- !strcmp(id->name, "sgd009")) {
+ device_info = (struct pmbus_device_info *)id->driver_data;
+ if (device_info->flags & PMBUS_SKIP_STATUS_CHECK) {
pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data),
GFP_KERNEL);
if (!pdata)
@@ -187,36 +193,50 @@ static int pmbus_probe(struct i2c_client *client,
pdata->flags = PMBUS_SKIP_STATUS_CHECK;
}
- info->pages = id->driver_data;
+ info->pages = device_info->pages;
info->identify = pmbus_identify;
dev->platform_data = pdata;
return pmbus_do_probe(client, id, info);
}
+static const struct pmbus_device_info pmbus_info_one = {
+ .pages = 1,
+ .flags = 0
+};
+static const struct pmbus_device_info pmbus_info_zero = {
+ .pages = 0,
+ .flags = 0
+};
+static const struct pmbus_device_info pmbus_info_one_skip = {
+ .pages = 1,
+ .flags = PMBUS_SKIP_STATUS_CHECK
+};
+
/*
* Use driver_data to set the number of pages supported by the chip.
*/
static const struct i2c_device_id pmbus_id[] = {
- {"adp4000", 1},
- {"bmr453", 1},
- {"bmr454", 1},
- {"dps460", 1},
- {"dps800", 1},
- {"mdt040", 1},
- {"ncp4200", 1},
- {"ncp4208", 1},
- {"pdt003", 1},
- {"pdt006", 1},
- {"pdt012", 1},
- {"pmbus", 0},
- {"sgd009", 1},
- {"tps40400", 1},
- {"tps544b20", 1},
- {"tps544b25", 1},
- {"tps544c20", 1},
- {"tps544c25", 1},
- {"udt020", 1},
+ {"adp4000", (kernel_ulong_t)&pmbus_info_one},
+ {"bmr453", (kernel_ulong_t)&pmbus_info_one},
+ {"bmr454", (kernel_ulong_t)&pmbus_info_one},
+ {"dps460", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"dps650ab", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"dps800", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"mdt040", (kernel_ulong_t)&pmbus_info_one},
+ {"ncp4200", (kernel_ulong_t)&pmbus_info_one},
+ {"ncp4208", (kernel_ulong_t)&pmbus_info_one},
+ {"pdt003", (kernel_ulong_t)&pmbus_info_one},
+ {"pdt006", (kernel_ulong_t)&pmbus_info_one},
+ {"pdt012", (kernel_ulong_t)&pmbus_info_one},
+ {"pmbus", (kernel_ulong_t)&pmbus_info_zero},
+ {"sgd009", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"tps40400", (kernel_ulong_t)&pmbus_info_one},
+ {"tps544b20", (kernel_ulong_t)&pmbus_info_one},
+ {"tps544b25", (kernel_ulong_t)&pmbus_info_one},
+ {"tps544c20", (kernel_ulong_t)&pmbus_info_one},
+ {"tps544c25", (kernel_ulong_t)&pmbus_info_one},
+ {"udt020", (kernel_ulong_t)&pmbus_info_one},
{}
};
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index 85b515cd9df0..2bc352c5357f 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -80,7 +80,14 @@ static struct pmbus_driver_info tps53679_info = {
static int tps53679_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- return pmbus_do_probe(client, id, &tps53679_info);
+ struct pmbus_driver_info *info;
+
+ info = devm_kmemdup(&client->dev, &tps53679_info, sizeof(*info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ return pmbus_do_probe(client, id, info);
}
static const struct i2c_device_id tps53679_id[] = {
diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c
index 3014e4ac741e..16c1c98e0e18 100644
--- a/drivers/hwmon/powr1220.c
+++ b/drivers/hwmon/powr1220.c
@@ -177,8 +177,9 @@ exit:
}
/* Shows the voltage associated with the specified ADC channel */
-static ssize_t powr1220_show_voltage(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static ssize_t powr1220_voltage_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
int adc_val = powr1220_read_adc(dev, attr->index);
@@ -190,8 +191,8 @@ static ssize_t powr1220_show_voltage(struct device *dev,
}
/* Shows the maximum setting associated with the specified ADC channel */
-static ssize_t powr1220_show_max(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static ssize_t powr1220_max_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct powr1220_data *data = dev_get_drvdata(dev);
@@ -200,100 +201,59 @@ static ssize_t powr1220_show_max(struct device *dev,
}
/* Shows the label associated with the specified ADC channel */
-static ssize_t powr1220_show_label(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static ssize_t powr1220_label_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
return sprintf(buf, "%s\n", input_names[attr->index]);
}
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON1);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON2);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON3);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON4);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON5);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON6);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON7);
-static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON8);
-static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON9);
-static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON10);
-static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON11);
-static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL,
- VMON12);
-static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL,
- VCCA);
-static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL,
- VCCINP);
-
-static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON1);
-static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON2);
-static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON3);
-static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON4);
-static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON5);
-static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON6);
-static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON7);
-static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON8);
-static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON9);
-static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON10);
-static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON11);
-static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL,
- VMON12);
-static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL,
- VCCA);
-static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL,
- VCCINP);
-
-static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL,
- VMON1);
-static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL,
- VMON2);
-static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL,
- VMON3);
-static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL,
- VMON4);
-static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL,
- VMON5);
-static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL,
- VMON6);
-static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL,
- VMON7);
-static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL,
- VMON8);
-static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL,
- VMON9);
-static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL,
- VMON10);
-static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL,
- VMON11);
-static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL,
- VMON12);
-static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL,
- VCCA);
-static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL,
- VCCINP);
+static SENSOR_DEVICE_ATTR_RO(in0_input, powr1220_voltage, VMON1);
+static SENSOR_DEVICE_ATTR_RO(in1_input, powr1220_voltage, VMON2);
+static SENSOR_DEVICE_ATTR_RO(in2_input, powr1220_voltage, VMON3);
+static SENSOR_DEVICE_ATTR_RO(in3_input, powr1220_voltage, VMON4);
+static SENSOR_DEVICE_ATTR_RO(in4_input, powr1220_voltage, VMON5);
+static SENSOR_DEVICE_ATTR_RO(in5_input, powr1220_voltage, VMON6);
+static SENSOR_DEVICE_ATTR_RO(in6_input, powr1220_voltage, VMON7);
+static SENSOR_DEVICE_ATTR_RO(in7_input, powr1220_voltage, VMON8);
+static SENSOR_DEVICE_ATTR_RO(in8_input, powr1220_voltage, VMON9);
+static SENSOR_DEVICE_ATTR_RO(in9_input, powr1220_voltage, VMON10);
+static SENSOR_DEVICE_ATTR_RO(in10_input, powr1220_voltage, VMON11);
+static SENSOR_DEVICE_ATTR_RO(in11_input, powr1220_voltage, VMON12);
+static SENSOR_DEVICE_ATTR_RO(in12_input, powr1220_voltage, VCCA);
+static SENSOR_DEVICE_ATTR_RO(in13_input, powr1220_voltage, VCCINP);
+
+static SENSOR_DEVICE_ATTR_RO(in0_highest, powr1220_max, VMON1);
+static SENSOR_DEVICE_ATTR_RO(in1_highest, powr1220_max, VMON2);
+static SENSOR_DEVICE_ATTR_RO(in2_highest, powr1220_max, VMON3);
+static SENSOR_DEVICE_ATTR_RO(in3_highest, powr1220_max, VMON4);
+static SENSOR_DEVICE_ATTR_RO(in4_highest, powr1220_max, VMON5);
+static SENSOR_DEVICE_ATTR_RO(in5_highest, powr1220_max, VMON6);
+static SENSOR_DEVICE_ATTR_RO(in6_highest, powr1220_max, VMON7);
+static SENSOR_DEVICE_ATTR_RO(in7_highest, powr1220_max, VMON8);
+static SENSOR_DEVICE_ATTR_RO(in8_highest, powr1220_max, VMON9);
+static SENSOR_DEVICE_ATTR_RO(in9_highest, powr1220_max, VMON10);
+static SENSOR_DEVICE_ATTR_RO(in10_highest, powr1220_max, VMON11);
+static SENSOR_DEVICE_ATTR_RO(in11_highest, powr1220_max, VMON12);
+static SENSOR_DEVICE_ATTR_RO(in12_highest, powr1220_max, VCCA);
+static SENSOR_DEVICE_ATTR_RO(in13_highest, powr1220_max, VCCINP);
+
+static SENSOR_DEVICE_ATTR_RO(in0_label, powr1220_label, VMON1);
+static SENSOR_DEVICE_ATTR_RO(in1_label, powr1220_label, VMON2);
+static SENSOR_DEVICE_ATTR_RO(in2_label, powr1220_label, VMON3);
+static SENSOR_DEVICE_ATTR_RO(in3_label, powr1220_label, VMON4);
+static SENSOR_DEVICE_ATTR_RO(in4_label, powr1220_label, VMON5);
+static SENSOR_DEVICE_ATTR_RO(in5_label, powr1220_label, VMON6);
+static SENSOR_DEVICE_ATTR_RO(in6_label, powr1220_label, VMON7);
+static SENSOR_DEVICE_ATTR_RO(in7_label, powr1220_label, VMON8);
+static SENSOR_DEVICE_ATTR_RO(in8_label, powr1220_label, VMON9);
+static SENSOR_DEVICE_ATTR_RO(in9_label, powr1220_label, VMON10);
+static SENSOR_DEVICE_ATTR_RO(in10_label, powr1220_label, VMON11);
+static SENSOR_DEVICE_ATTR_RO(in11_label, powr1220_label, VMON12);
+static SENSOR_DEVICE_ATTR_RO(in12_label, powr1220_label, VCCA);
+static SENSOR_DEVICE_ATTR_RO(in13_label, powr1220_label, VCCINP);
static struct attribute *powr1220_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 2c944825026f..167221c7628a 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
@@ -31,6 +32,7 @@
struct pwm_fan_ctx {
struct mutex lock;
struct pwm_device *pwm;
+ struct regulator *reg_en;
unsigned int pwm_value;
unsigned int pwm_fan_state;
unsigned int pwm_fan_max_state;
@@ -231,6 +233,21 @@ static int pwm_fan_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ctx);
+ ctx->reg_en = devm_regulator_get_optional(&pdev->dev, "fan");
+ if (IS_ERR(ctx->reg_en)) {
+ if (PTR_ERR(ctx->reg_en) != -ENODEV)
+ return PTR_ERR(ctx->reg_en);
+
+ ctx->reg_en = NULL;
+ } else {
+ ret = regulator_enable(ctx->reg_en);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to enable fan supply: %d\n", ret);
+ return ret;
+ }
+ }
+
ctx->pwm_value = MAX_PWM;
/* Set duty cycle to maximum allowed and enable PWM output */
@@ -241,7 +258,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
ret = pwm_apply_state(ctx->pwm, &state);
if (ret) {
dev_err(&pdev->dev, "Failed to configure PWM\n");
- return ret;
+ goto err_reg_disable;
}
hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
@@ -277,6 +294,10 @@ err_pwm_disable:
state.enabled = false;
pwm_apply_state(ctx->pwm, &state);
+err_reg_disable:
+ if (ctx->reg_en)
+ regulator_disable(ctx->reg_en);
+
return ret;
}
@@ -287,6 +308,10 @@ static int pwm_fan_remove(struct platform_device *pdev)
thermal_cooling_device_unregister(ctx->cdev);
if (ctx->pwm_value)
pwm_disable(ctx->pwm);
+
+ if (ctx->reg_en)
+ regulator_disable(ctx->reg_en);
+
return 0;
}
@@ -307,6 +332,14 @@ static int pwm_fan_suspend(struct device *dev)
pwm_disable(ctx->pwm);
}
+ if (ctx->reg_en) {
+ ret = regulator_disable(ctx->reg_en);
+ if (ret) {
+ dev_err(dev, "Failed to disable fan supply: %d\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
@@ -317,6 +350,14 @@ static int pwm_fan_resume(struct device *dev)
unsigned long duty;
int ret;
+ if (ctx->reg_en) {
+ ret = regulator_enable(ctx->reg_en);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan supply: %d\n", ret);
+ return ret;
+ }
+ }
+
if (ctx->pwm_value == 0)
return 0;
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 91544f2312e6..63cfbc5a86ed 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -211,8 +211,8 @@ static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
}
-static ssize_t show_temp(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = sch5627_update_device(dev);
@@ -225,8 +225,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_temp_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = sch5627_update_device(dev);
@@ -237,8 +237,8 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
}
-static ssize_t show_temp_max(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_max_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = dev_get_drvdata(dev);
@@ -248,8 +248,8 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_temp_crit(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_crit_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = dev_get_drvdata(dev);
@@ -259,8 +259,8 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_fan(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = sch5627_update_device(dev);
@@ -276,8 +276,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = sch5627_update_device(dev);
@@ -289,8 +289,8 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute
data->fan[attr->index] == 0xffff);
}
-static ssize_t show_fan_min(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_min_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = dev_get_drvdata(dev);
@@ -301,8 +301,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_in(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t in_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5627_data *data = sch5627_update_device(dev);
@@ -317,8 +317,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_in_label(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t in_label_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -327,61 +327,61 @@ static ssize_t show_in_label(struct device *dev, struct device_attribute
}
static DEVICE_ATTR_RO(name);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7);
-
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
-static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3);
-
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
-static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_input, temp, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_input, temp, 5);
+static SENSOR_DEVICE_ATTR_RO(temp7_input, temp, 6);
+static SENSOR_DEVICE_ATTR_RO(temp8_input, temp, 7);
+static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_fault, temp_fault, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_fault, temp_fault, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_fault, temp_fault, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_fault, temp_fault, 5);
+static SENSOR_DEVICE_ATTR_RO(temp7_fault, temp_fault, 6);
+static SENSOR_DEVICE_ATTR_RO(temp8_fault, temp_fault, 7);
+static SENSOR_DEVICE_ATTR_RO(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_max, temp_max, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_max, temp_max, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_max, temp_max, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_max, temp_max, 5);
+static SENSOR_DEVICE_ATTR_RO(temp7_max, temp_max, 6);
+static SENSOR_DEVICE_ATTR_RO(temp8_max, temp_max, 7);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp_crit, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp_crit, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_crit, temp_crit, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp_crit, 3);
+static SENSOR_DEVICE_ATTR_RO(temp5_crit, temp_crit, 4);
+static SENSOR_DEVICE_ATTR_RO(temp6_crit, temp_crit, 5);
+static SENSOR_DEVICE_ATTR_RO(temp7_crit, temp_crit, 6);
+static SENSOR_DEVICE_ATTR_RO(temp8_crit, temp_crit, 7);
+
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
+static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan_fault, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_fault, fan_fault, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_fault, fan_fault, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_fault, fan_fault, 3);
+static SENSOR_DEVICE_ATTR_RO(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_min, fan_min, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_min, fan_min, 3);
+
+static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
+static SENSOR_DEVICE_ATTR_RO(in0_label, in_label, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_label, in_label, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_label, in_label, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_label, in_label, 3);
static struct attribute *sch5627_attributes[] = {
&dev_attr_name.attr,
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index d24d7b6047f2..2a3825603a77 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -170,14 +170,14 @@ static int reg_to_rpm(u16 reg)
return 5400540 / reg;
}
-static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
- char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
}
-static ssize_t show_in_value(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t in_value_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -192,8 +192,8 @@ static ssize_t show_in_value(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_in_label(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t in_label_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -201,8 +201,8 @@ static ssize_t show_in_label(struct device *dev, struct device_attribute
SCH5636_IN_LABELS[attr->index]);
}
-static ssize_t show_temp_value(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_value_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -215,8 +215,8 @@ static ssize_t show_temp_value(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_temp_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -229,8 +229,8 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -243,8 +243,8 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_fan_value(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_value_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -260,8 +260,8 @@ static ssize_t show_fan_value(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_fault_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -274,8 +274,8 @@ static ssize_t show_fan_fault(struct device *dev, struct device_attribute
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
-static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_alarm_show(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct sch5636_data *data = sch5636_update_device(dev);
@@ -289,95 +289,95 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
}
static struct sensor_device_attribute sch5636_attr[] = {
- SENSOR_ATTR(name, 0444, show_name, NULL, 0),
- SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
- SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0),
- SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
- SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1),
- SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
- SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2),
- SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3),
- SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3),
- SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4),
- SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4),
+ SENSOR_ATTR_RO(name, name, 0),
+ SENSOR_ATTR_RO(in0_input, in_value, 0),
+ SENSOR_ATTR_RO(in0_label, in_label, 0),
+ SENSOR_ATTR_RO(in1_input, in_value, 1),
+ SENSOR_ATTR_RO(in1_label, in_label, 1),
+ SENSOR_ATTR_RO(in2_input, in_value, 2),
+ SENSOR_ATTR_RO(in2_label, in_label, 2),
+ SENSOR_ATTR_RO(in3_input, in_value, 3),
+ SENSOR_ATTR_RO(in3_label, in_label, 3),
+ SENSOR_ATTR_RO(in4_input, in_value, 4),
+ SENSOR_ATTR_RO(in4_label, in_label, 4),
};
static struct sensor_device_attribute sch5636_temp_attr[] = {
- SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
- SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0),
- SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0),
- SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
- SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1),
- SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1),
- SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2),
- SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2),
- SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2),
- SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3),
- SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3),
- SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3),
- SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4),
- SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
- SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
- SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5),
- SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5),
- SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5),
- SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6),
- SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6),
- SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6),
- SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7),
- SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7),
- SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7),
- SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8),
- SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8),
- SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8),
- SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9),
- SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9),
- SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9),
- SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10),
- SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10),
- SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10),
- SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11),
- SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11),
- SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11),
- SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12),
- SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12),
- SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12),
- SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13),
- SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13),
- SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13),
- SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14),
- SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14),
- SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14),
- SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15),
- SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15),
- SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15),
+ SENSOR_ATTR_RO(temp1_input, temp_value, 0),
+ SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
+ SENSOR_ATTR_RO(temp1_alarm, temp_alarm, 0),
+ SENSOR_ATTR_RO(temp2_input, temp_value, 1),
+ SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
+ SENSOR_ATTR_RO(temp2_alarm, temp_alarm, 1),
+ SENSOR_ATTR_RO(temp3_input, temp_value, 2),
+ SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
+ SENSOR_ATTR_RO(temp3_alarm, temp_alarm, 2),
+ SENSOR_ATTR_RO(temp4_input, temp_value, 3),
+ SENSOR_ATTR_RO(temp4_fault, temp_fault, 3),
+ SENSOR_ATTR_RO(temp4_alarm, temp_alarm, 3),
+ SENSOR_ATTR_RO(temp5_input, temp_value, 4),
+ SENSOR_ATTR_RO(temp5_fault, temp_fault, 4),
+ SENSOR_ATTR_RO(temp5_alarm, temp_alarm, 4),
+ SENSOR_ATTR_RO(temp6_input, temp_value, 5),
+ SENSOR_ATTR_RO(temp6_fault, temp_fault, 5),
+ SENSOR_ATTR_RO(temp6_alarm, temp_alarm, 5),
+ SENSOR_ATTR_RO(temp7_input, temp_value, 6),
+ SENSOR_ATTR_RO(temp7_fault, temp_fault, 6),
+ SENSOR_ATTR_RO(temp7_alarm, temp_alarm, 6),
+ SENSOR_ATTR_RO(temp8_input, temp_value, 7),
+ SENSOR_ATTR_RO(temp8_fault, temp_fault, 7),
+ SENSOR_ATTR_RO(temp8_alarm, temp_alarm, 7),
+ SENSOR_ATTR_RO(temp9_input, temp_value, 8),
+ SENSOR_ATTR_RO(temp9_fault, temp_fault, 8),
+ SENSOR_ATTR_RO(temp9_alarm, temp_alarm, 8),
+ SENSOR_ATTR_RO(temp10_input, temp_value, 9),
+ SENSOR_ATTR_RO(temp10_fault, temp_fault, 9),
+ SENSOR_ATTR_RO(temp10_alarm, temp_alarm, 9),
+ SENSOR_ATTR_RO(temp11_input, temp_value, 10),
+ SENSOR_ATTR_RO(temp11_fault, temp_fault, 10),
+ SENSOR_ATTR_RO(temp11_alarm, temp_alarm, 10),
+ SENSOR_ATTR_RO(temp12_input, temp_value, 11),
+ SENSOR_ATTR_RO(temp12_fault, temp_fault, 11),
+ SENSOR_ATTR_RO(temp12_alarm, temp_alarm, 11),
+ SENSOR_ATTR_RO(temp13_input, temp_value, 12),
+ SENSOR_ATTR_RO(temp13_fault, temp_fault, 12),
+ SENSOR_ATTR_RO(temp13_alarm, temp_alarm, 12),
+ SENSOR_ATTR_RO(temp14_input, temp_value, 13),
+ SENSOR_ATTR_RO(temp14_fault, temp_fault, 13),
+ SENSOR_ATTR_RO(temp14_alarm, temp_alarm, 13),
+ SENSOR_ATTR_RO(temp15_input, temp_value, 14),
+ SENSOR_ATTR_RO(temp15_fault, temp_fault, 14),
+ SENSOR_ATTR_RO(temp15_alarm, temp_alarm, 14),
+ SENSOR_ATTR_RO(temp16_input, temp_value, 15),
+ SENSOR_ATTR_RO(temp16_fault, temp_fault, 15),
+ SENSOR_ATTR_RO(temp16_alarm, temp_alarm, 15),
};
static struct sensor_device_attribute sch5636_fan_attr[] = {
- SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0),
- SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0),
- SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0),
- SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1),
- SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1),
- SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1),
- SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2),
- SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2),
- SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2),
- SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3),
- SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3),
- SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3),
- SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4),
- SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4),
- SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4),
- SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5),
- SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
- SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5),
- SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6),
- SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6),
- SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6),
- SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7),
- SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7),
- SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7),
+ SENSOR_ATTR_RO(fan1_input, fan_value, 0),
+ SENSOR_ATTR_RO(fan1_fault, fan_fault, 0),
+ SENSOR_ATTR_RO(fan1_alarm, fan_alarm, 0),
+ SENSOR_ATTR_RO(fan2_input, fan_value, 1),
+ SENSOR_ATTR_RO(fan2_fault, fan_fault, 1),
+ SENSOR_ATTR_RO(fan2_alarm, fan_alarm, 1),
+ SENSOR_ATTR_RO(fan3_input, fan_value, 2),
+ SENSOR_ATTR_RO(fan3_fault, fan_fault, 2),
+ SENSOR_ATTR_RO(fan3_alarm, fan_alarm, 2),
+ SENSOR_ATTR_RO(fan4_input, fan_value, 3),
+ SENSOR_ATTR_RO(fan4_fault, fan_fault, 3),
+ SENSOR_ATTR_RO(fan4_alarm, fan_alarm, 3),
+ SENSOR_ATTR_RO(fan5_input, fan_value, 4),
+ SENSOR_ATTR_RO(fan5_fault, fan_fault, 4),
+ SENSOR_ATTR_RO(fan5_alarm, fan_alarm, 4),
+ SENSOR_ATTR_RO(fan6_input, fan_value, 5),
+ SENSOR_ATTR_RO(fan6_fault, fan_fault, 5),
+ SENSOR_ATTR_RO(fan6_alarm, fan_alarm, 5),
+ SENSOR_ATTR_RO(fan7_input, fan_value, 6),
+ SENSOR_ATTR_RO(fan7_fault, fan_fault, 6),
+ SENSOR_ATTR_RO(fan7_alarm, fan_alarm, 6),
+ SENSOR_ATTR_RO(fan8_input, fan_value, 7),
+ SENSOR_ATTR_RO(fan8_fault, fan_fault, 7),
+ SENSOR_ATTR_RO(fan8_alarm, fan_alarm, 7),
};
static int sch5636_remove(struct platform_device *pdev)
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
index 2e005edee0c9..a80183a488c5 100644
--- a/drivers/hwmon/scmi-hwmon.c
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -57,7 +57,7 @@ scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
sensor = *(scmi_sensors->info[type] + channel);
if (sensor)
- return S_IRUGO;
+ return 0444;
return 0;
}
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
index 111d521e2189..9bfa228d0eb0 100644
--- a/drivers/hwmon/scpi-hwmon.c
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -226,11 +226,11 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
sensor->scale = scale[sensor->info.class];
- sensor->dev_attr_input.attr.mode = S_IRUGO;
+ sensor->dev_attr_input.attr.mode = 0444;
sensor->dev_attr_input.show = scpi_show_sensor;
sensor->dev_attr_input.attr.name = sensor->input;
- sensor->dev_attr_label.attr.mode = S_IRUGO;
+ sensor->dev_attr_label.attr.mode = 0444;
sensor->dev_attr_label.show = scpi_show_label;
sensor->dev_attr_label.attr.name = sensor->label;
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index c878242f3486..39b41e35c2bf 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -677,9 +677,8 @@ static inline int sht15_calc_humid(struct sht15_data *data)
* and heater_enable sysfs attributes.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t sht15_show_status(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t sht15_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
struct sht15_data *data = dev_get_drvdata(dev);
@@ -700,7 +699,7 @@ static ssize_t sht15_show_status(struct device *dev,
* Will be called on write access to heater_enable sysfs attribute.
* Returns number of bytes actually decoded, negative errno on error.
*/
-static ssize_t sht15_store_heater(struct device *dev,
+static ssize_t sht15_status_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -734,9 +733,8 @@ static ssize_t sht15_store_heater(struct device *dev,
* Will be called on read access to temp1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t sht15_show_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t sht15_temp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
struct sht15_data *data = dev_get_drvdata(dev);
@@ -757,9 +755,8 @@ static ssize_t sht15_show_temp(struct device *dev,
* Will be called on read access to humidity1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t sht15_show_humidity(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t sht15_humidity_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
struct sht15_data *data = dev_get_drvdata(dev);
@@ -777,16 +774,13 @@ static ssize_t name_show(struct device *dev,
return sprintf(buf, "%s\n", pdev->name);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
- sht15_show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO,
- sht15_show_humidity, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, sht15_show_status, NULL,
- SHT15_STATUS_LOW_BATTERY);
-static SENSOR_DEVICE_ATTR(humidity1_fault, S_IRUGO, sht15_show_status, NULL,
- SHT15_STATUS_LOW_BATTERY);
-static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR, sht15_show_status,
- sht15_store_heater, SHT15_STATUS_HEATER);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, sht15_temp, 0);
+static SENSOR_DEVICE_ATTR_RO(humidity1_input, sht15_humidity, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_fault, sht15_status,
+ SHT15_STATUS_LOW_BATTERY);
+static SENSOR_DEVICE_ATTR_RO(humidity1_fault, sht15_status,
+ SHT15_STATUS_LOW_BATTERY);
+static SENSOR_DEVICE_ATTR_RW(heater_enable, sht15_status, SHT15_STATUS_HEATER);
static DEVICE_ATTR_RO(name);
static struct attribute *sht15_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 2c7ba70921f5..df112b73b635 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -135,9 +135,9 @@ out:
* Will be called on read access to temp1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t sht21_show_temperature(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t sht21_temperature_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct sht21 *sht21 = dev_get_drvdata(dev);
int ret;
@@ -157,9 +157,8 @@ static ssize_t sht21_show_temperature(struct device *dev,
* Will be called on read access to humidity1_input sysfs attribute.
* Returns number of bytes written into buffer, negative errno on error.
*/
-static ssize_t sht21_show_humidity(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t sht21_humidity_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sht21 *sht21 = dev_get_drvdata(dev);
int ret;
@@ -251,10 +250,8 @@ static ssize_t eic_show(struct device *dev,
}
/* sysfs attributes */
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
- NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, sht21_temperature, 0);
+static SENSOR_DEVICE_ATTR_RO(humidity1_input, sht21_humidity, 0);
static DEVICE_ATTR_RO(eic);
static struct attribute *sht21_attrs[] = {
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index 370b57dafab7..81ebc96cdec9 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -629,40 +629,22 @@ out:
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp1_input_show, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, humidity1_input_show,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_max);
-static SENSOR_DEVICE_ATTR(humidity1_max, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_max);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_max_hyst);
-static SENSOR_DEVICE_ATTR(humidity1_max_hyst, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_max_hyst);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_min);
-static SENSOR_DEVICE_ATTR(humidity1_min, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_min);
-static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_min_hyst);
-static SENSOR_DEVICE_ATTR(humidity1_min_hyst, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_min_hyst);
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, temp1_alarm_show, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_alarm, S_IRUGO, humidity1_alarm_show,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR,
- heater_enable_show, heater_enable_store, 0);
-static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
- update_interval_show, update_interval_store, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);
+static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max);
+static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max);
+static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst);
+static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit,
+ limit_max_hyst);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min);
+static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min);
+static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst);
+static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit,
+ limit_min_hyst);
+static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0);
+static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0);
+static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0);
static struct attribute *sht3x_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 6bd200756560..c0775084dde0 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -164,18 +164,18 @@ static int temp_from_reg(u8 reg)
return (s8)reg * 1000;
}
-static ssize_t show_temp(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct smsc47b397_data *data = smsc47b397_update_device(dev);
return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index]));
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
+static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3);
/*
* FAN: 1 RPM/bit
@@ -188,17 +188,17 @@ static int fan_from_reg(u16 reg)
return 90000 * 60 / reg;
}
-static ssize_t show_fan(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct smsc47b397_data *data = smsc47b397_update_device(dev);
return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index]));
}
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
+static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
static struct attribute *smsc47b397_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c
index 7fe152d92350..90b60297f2f7 100644
--- a/drivers/hwmon/stts751.c
+++ b/drivers/hwmon/stts751.c
@@ -382,8 +382,8 @@ static int stts751_update(struct stts751_priv *priv)
return 0;
}
-static ssize_t show_max_alarm(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t max_alarm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -399,8 +399,8 @@ static ssize_t show_max_alarm(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->max_alert);
}
-static ssize_t show_min_alarm(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t min_alarm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
int ret;
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -416,7 +416,7 @@ static ssize_t show_min_alarm(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->min_alert);
}
-static ssize_t show_input(struct device *dev, struct device_attribute *attr,
+static ssize_t input_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int ret;
@@ -431,7 +431,7 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->temp);
}
-static ssize_t show_therm(struct device *dev, struct device_attribute *attr,
+static ssize_t therm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -439,8 +439,8 @@ static ssize_t show_therm(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm);
}
-static ssize_t set_therm(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t therm_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
long temp;
@@ -473,7 +473,7 @@ exit:
return count;
}
-static ssize_t show_hyst(struct device *dev, struct device_attribute *attr,
+static ssize_t hyst_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -481,8 +481,8 @@ static ssize_t show_hyst(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->hyst);
}
-static ssize_t set_hyst(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t hyst_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
long temp;
@@ -506,7 +506,7 @@ static ssize_t set_hyst(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t show_therm_trip(struct device *dev,
+static ssize_t therm_trip_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
@@ -521,7 +521,7 @@ static ssize_t show_therm_trip(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm_trip);
}
-static ssize_t show_max(struct device *dev, struct device_attribute *attr,
+static ssize_t max_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -529,8 +529,8 @@ static ssize_t show_max(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_max);
}
-static ssize_t set_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t max_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
long temp;
@@ -555,7 +555,7 @@ exit:
return ret;
}
-static ssize_t show_min(struct device *dev, struct device_attribute *attr,
+static ssize_t min_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -563,8 +563,8 @@ static ssize_t show_min(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_min);
}
-static ssize_t set_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t min_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
long temp;
@@ -589,8 +589,8 @@ exit:
return ret;
}
-static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t interval_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct stts751_priv *priv = dev_get_drvdata(dev);
@@ -598,8 +598,9 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
stts751_intervals[priv->interval]);
}
-static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t interval_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
unsigned long val;
int idx;
@@ -746,16 +747,15 @@ static int stts751_read_chip_config(struct stts751_priv *priv)
return 0;
}
-static SENSOR_DEVICE_ATTR(temp1_input, 0444, show_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_min, 0644, show_min, set_min, 0);
-static SENSOR_DEVICE_ATTR(temp1_max, 0644, show_max, set_max, 0);
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, 0444, show_min_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, 0444, show_max_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_crit, 0644, show_therm, set_therm, 0);
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, 0644, show_hyst, set_hyst, 0);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, 0444, show_therm_trip, NULL, 0);
-static SENSOR_DEVICE_ATTR(update_interval, 0644,
- show_interval, set_interval, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, input, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, min, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, max, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, min_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, max_alarm, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit, therm, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, hyst, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, therm_trip, 0);
+static SENSOR_DEVICE_ATTR_RW(update_interval, interval, 0);
static struct attribute *stts751_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c
index 18136e1f95fd..81dd229d7db4 100644
--- a/drivers/hwmon/tc654.c
+++ b/drivers/hwmon/tc654.c
@@ -200,7 +200,7 @@ out:
* sysfs attributes
*/
-static ssize_t show_fan(struct device *dev, struct device_attribute *da,
+static ssize_t fan_show(struct device *dev, struct device_attribute *da,
char *buf)
{
int nr = to_sensor_dev_attr(da)->index;
@@ -218,7 +218,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da,
return sprintf(buf, "%d\n", val);
}
-static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
+static ssize_t fan_min_show(struct device *dev, struct device_attribute *da,
char *buf)
{
int nr = to_sensor_dev_attr(da)->index;
@@ -231,8 +231,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
TC654_FAN_FAULT_FROM_REG(data->fan_fault[nr]));
}
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(da)->index;
struct tc654_data *data = dev_get_drvdata(dev);
@@ -255,7 +255,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
return ret < 0 ? ret : count;
}
-static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da,
+static ssize_t fan_alarm_show(struct device *dev, struct device_attribute *da,
char *buf)
{
int nr = to_sensor_dev_attr(da)->index;
@@ -275,8 +275,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da,
static const u8 TC654_FAN_PULSE_SHIFT[] = { 1, 3 };
-static ssize_t show_fan_pulses(struct device *dev, struct device_attribute *da,
- char *buf)
+static ssize_t fan_pulses_show(struct device *dev,
+ struct device_attribute *da, char *buf)
{
int nr = to_sensor_dev_attr(da)->index;
struct tc654_data *data = tc654_update_client(dev);
@@ -289,8 +289,9 @@ static ssize_t show_fan_pulses(struct device *dev, struct device_attribute *da,
return sprintf(buf, "%d\n", val);
}
-static ssize_t set_fan_pulses(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t fan_pulses_store(struct device *dev,
+ struct device_attribute *da, const char *buf,
+ size_t count)
{
int nr = to_sensor_dev_attr(da)->index;
struct tc654_data *data = dev_get_drvdata(dev);
@@ -329,8 +330,8 @@ static ssize_t set_fan_pulses(struct device *dev, struct device_attribute *da,
return ret < 0 ? ret : count;
}
-static ssize_t show_pwm_mode(struct device *dev,
- struct device_attribute *da, char *buf)
+static ssize_t pwm_mode_show(struct device *dev, struct device_attribute *da,
+ char *buf)
{
struct tc654_data *data = tc654_update_client(dev);
@@ -340,9 +341,8 @@ static ssize_t show_pwm_mode(struct device *dev,
return sprintf(buf, "%d\n", !!(data->config & TC654_REG_CONFIG_DUTYC));
}
-static ssize_t set_pwm_mode(struct device *dev,
- struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t pwm_mode_store(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
{
struct tc654_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -371,7 +371,7 @@ static ssize_t set_pwm_mode(struct device *dev,
static const int tc654_pwm_map[16] = { 77, 88, 102, 112, 124, 136, 148, 160,
172, 184, 196, 207, 219, 231, 243, 255};
-static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
+static ssize_t pwm_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct tc654_data *data = tc654_update_client(dev);
@@ -388,8 +388,8 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
return sprintf(buf, "%d\n", pwm);
}
-static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t pwm_store(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
{
struct tc654_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
@@ -423,22 +423,16 @@ out:
return ret < 0 ? ret : count;
}
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
- set_fan_pulses, 0);
-static SENSOR_DEVICE_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
- set_fan_pulses, 1);
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
- show_pwm_mode, set_pwm_mode, 0);
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm,
- set_pwm, 0);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, fan_alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, fan_alarm, 1);
+static SENSOR_DEVICE_ATTR_RW(fan1_pulses, fan_pulses, 0);
+static SENSOR_DEVICE_ATTR_RW(fan2_pulses, fan_pulses, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm1_mode, pwm_mode, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
/* Driver data */
static struct attribute *tc654_attrs[] = {
diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c
index d95165158800..fa306bb681bb 100644
--- a/drivers/hwmon/tc74.c
+++ b/drivers/hwmon/tc74.c
@@ -86,7 +86,7 @@ ret_unlock:
return ret;
}
-static ssize_t show_temp_input(struct device *dev,
+static ssize_t temp_input_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tc74_data *data = dev_get_drvdata(dev);
@@ -98,7 +98,7 @@ static ssize_t show_temp_input(struct device *dev,
return sprintf(buf, "%d\n", data->temp_input * 1000);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
static struct attribute *tc74_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 6778283e36f9..35523d315f25 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -141,10 +141,10 @@ static umode_t tmp102_is_visible(const void *data, enum hwmon_sensor_types type,
switch (attr) {
case hwmon_temp_input:
- return S_IRUGO;
+ return 0444;
case hwmon_temp_max_hyst:
case hwmon_temp_max:
- return S_IRUGO | S_IWUSR;
+ return 0644;
default:
return 0;
}
diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c
index 7f85b14544df..bda0fdc1eb53 100644
--- a/drivers/hwmon/tmp103.c
+++ b/drivers/hwmon/tmp103.c
@@ -61,9 +61,8 @@ static inline u8 tmp103_mc_to_reg(int val)
return DIV_ROUND_CLOSEST(val, 1000);
}
-static ssize_t tmp103_show_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t tmp103_temp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct regmap *regmap = dev_get_drvdata(dev);
@@ -77,9 +76,9 @@ static ssize_t tmp103_show_temp(struct device *dev,
return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval));
}
-static ssize_t tmp103_set_temp(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t tmp103_temp_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct regmap *regmap = dev_get_drvdata(dev);
@@ -94,14 +93,11 @@ static ssize_t tmp103_set_temp(struct device *dev,
return ret ? ret : count;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL ,
- TMP103_TEMP_REG);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, tmp103_temp, TMP103_TEMP_REG);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp,
- tmp103_set_temp, TMP103_TLOW_REG);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, tmp103_temp, TMP103_TLOW_REG);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp,
- tmp103_set_temp, TMP103_THIGH_REG);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, tmp103_temp, TMP103_THIGH_REG);
static struct attribute *tmp103_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 8844c9565d2a..2732a71f3b39 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = {
.data = (void *)2
},
{
- .compatible = "ti,tmp422",
+ .compatible = "ti,tmp442",
.data = (void *)3
},
{ },
@@ -187,9 +187,9 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type,
case hwmon_temp_fault:
if (channel == 0)
return 0;
- return S_IRUGO;
+ return 0444;
case hwmon_temp_input:
- return S_IRUGO;
+ return 0444;
default:
return 0;
}
diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c
index 8ba419d343f8..0b84adb5e88e 100644
--- a/drivers/hwmon/vexpress-hwmon.c
+++ b/drivers/hwmon/vexpress-hwmon.c
@@ -92,9 +92,8 @@ struct vexpress_hwmon_type {
};
#if !defined(CONFIG_REGULATOR_VEXPRESS)
-static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
- NULL, 1000);
+static DEVICE_ATTR(in1_label, 0444, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR_RO(in1_input, vexpress_hwmon_u32, 1000);
static struct attribute *vexpress_hwmon_attrs_volt[] = {
&dev_attr_in1_label.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -113,9 +112,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_volt = {
};
#endif
-static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
- NULL, 1000);
+static DEVICE_ATTR(curr1_label, 0444, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, vexpress_hwmon_u32, 1000);
static struct attribute *vexpress_hwmon_attrs_amp[] = {
&dev_attr_curr1_label.attr,
&sensor_dev_attr_curr1_input.dev_attr.attr,
@@ -133,9 +131,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_amp = {
},
};
-static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
- NULL, 1000);
+static DEVICE_ATTR(temp1_label, 0444, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, vexpress_hwmon_u32, 1000);
static struct attribute *vexpress_hwmon_attrs_temp[] = {
&dev_attr_temp1_label.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -153,9 +150,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_temp = {
},
};
-static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
- NULL, 1);
+static DEVICE_ATTR(power1_label, 0444, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR_RO(power1_input, vexpress_hwmon_u32, 1);
static struct attribute *vexpress_hwmon_attrs_power[] = {
&dev_attr_power1_label.attr,
&sensor_dev_attr_power1_input.dev_attr.attr,
@@ -173,9 +169,8 @@ static struct vexpress_hwmon_type vexpress_hwmon_power = {
},
};
-static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
- NULL, 1);
+static DEVICE_ATTR(energy1_label, 0444, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR_RO(energy1_input, vexpress_hwmon_u64, 1);
static struct attribute *vexpress_hwmon_attrs_energy[] = {
&dev_attr_energy1_label.attr,
&sensor_dev_attr_energy1_input.dev_attr.attr,
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 0e81f287d305..cb94e4880014 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -60,8 +60,8 @@ struct via_cputemp_data {
* Sysfs stuff
*/
-static ssize_t show_name(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
int ret;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -74,8 +74,8 @@ static ssize_t show_name(struct device *dev, struct device_attribute
return ret;
}
-static ssize_t show_temp(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct via_cputemp_data *data = dev_get_drvdata(dev);
u32 eax, edx;
@@ -102,10 +102,9 @@ static ssize_t cpu0_vid_show(struct device *dev,
return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm));
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
- SHOW_TEMP);
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, SHOW_TEMP);
+static SENSOR_DEVICE_ATTR_RO(temp1_label, name, SHOW_LABEL);
+static SENSOR_DEVICE_ATTR_RO(name, name, SHOW_NAME);
static struct attribute *via_cputemp_attributes[] = {
&sensor_dev_attr_name.dev_attr.attr,
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 45b2460f3166..e8819d750938 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -668,6 +668,10 @@ static const struct amba_id debug_ids[] = {
.id = 0x000bbd08,
.mask = 0x000fffff,
},
+ { /* Debug for Cortex-A73 */
+ .id = 0x000bbd09,
+ .mask = 0x000fffff,
+ },
{ 0, 0 },
};
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index abe8249b893b..4d5a2b9f9d6a 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -14,6 +14,7 @@
#include <linux/perf_event.h>
#include <linux/percpu-defs.h>
#include <linux/slab.h>
+#include <linux/stringhash.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@@ -30,11 +31,14 @@ static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));
PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS));
PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK));
+/* Sink ID - same for all ETMs */
+PMU_FORMAT_ATTR(sinkid, "config2:0-31");
static struct attribute *etm_config_formats_attr[] = {
&format_attr_cycacc.attr,
&format_attr_timestamp.attr,
&format_attr_retstack.attr,
+ &format_attr_sinkid.attr,
NULL,
};
@@ -43,8 +47,18 @@ static const struct attribute_group etm_pmu_format_group = {
.attrs = etm_config_formats_attr,
};
+static struct attribute *etm_config_sinks_attr[] = {
+ NULL,
+};
+
+static const struct attribute_group etm_pmu_sinks_group = {
+ .name = "sinks",
+ .attrs = etm_config_sinks_attr,
+};
+
static const struct attribute_group *etm_pmu_attr_groups[] = {
&etm_pmu_format_group,
+ &etm_pmu_sinks_group,
NULL,
};
@@ -177,31 +191,28 @@ static void etm_free_aux(void *data)
schedule_work(&event_data->work);
}
-static void *etm_setup_aux(int event_cpu, void **pages,
+static void *etm_setup_aux(struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
- int cpu;
+ u32 id;
+ int cpu = event->cpu;
cpumask_t *mask;
struct coresight_device *sink;
struct etm_event_data *event_data = NULL;
- event_data = alloc_event_data(event_cpu);
+ event_data = alloc_event_data(cpu);
if (!event_data)
return NULL;
INIT_WORK(&event_data->work, free_event_data);
- /*
- * In theory nothing prevent tracers in a trace session from being
- * associated with different sinks, nor having a sink per tracer. But
- * until we have HW with this kind of topology we need to assume tracers
- * in a trace session are using the same sink. Therefore go through
- * the coresight bus and pick the first enabled sink.
- *
- * When operated from sysFS users are responsible to enable the sink
- * while from perf, the perf tools will do it based on the choice made
- * on the cmd line. As such the "enable_sink" flag in sysFS is reset.
- */
- sink = coresight_get_enabled_sink(true);
+ /* First get the selected sink from user space. */
+ if (event->attr.config2) {
+ id = (u32)event->attr.config2;
+ sink = coresight_get_sink_by_id(id);
+ } else {
+ sink = coresight_get_enabled_sink(true);
+ }
+
if (!sink || !sink_ops(sink)->alloc_buffer)
goto err;
@@ -422,15 +433,16 @@ static int etm_addr_filters_validate(struct list_head *filters)
static void etm_addr_filters_sync(struct perf_event *event)
{
struct perf_addr_filters_head *head = perf_event_addr_filters(event);
- unsigned long start, stop, *offs = event->addr_filters_offs;
+ unsigned long start, stop;
+ struct perf_addr_filter_range *fr = event->addr_filter_ranges;
struct etm_filters *filters = event->hw.addr_filters;
struct etm_filter *etm_filter;
struct perf_addr_filter *filter;
int i = 0;
list_for_each_entry(filter, &head->list, entry) {
- start = filter->offset + offs[i];
- stop = start + filter->size;
+ start = fr[i].start;
+ stop = start + fr[i].size;
etm_filter = &filters->etm_filter[i];
switch (filter->action) {
@@ -479,6 +491,77 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link)
return 0;
}
+static ssize_t etm_perf_sink_name_show(struct device *dev,
+ struct device_attribute *dattr,
+ char *buf)
+{
+ struct dev_ext_attribute *ea;
+
+ ea = container_of(dattr, struct dev_ext_attribute, attr);
+ return scnprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)(ea->var));
+}
+
+int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+{
+ int ret;
+ unsigned long hash;
+ const char *name;
+ struct device *pmu_dev = etm_pmu.dev;
+ struct device *pdev = csdev->dev.parent;
+ struct dev_ext_attribute *ea;
+
+ if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+ csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+ return -EINVAL;
+
+ if (csdev->ea != NULL)
+ return -EINVAL;
+
+ if (!etm_perf_up)
+ return -EPROBE_DEFER;
+
+ ea = devm_kzalloc(pdev, sizeof(*ea), GFP_KERNEL);
+ if (!ea)
+ return -ENOMEM;
+
+ name = dev_name(pdev);
+ /* See function coresight_get_sink_by_id() to know where this is used */
+ hash = hashlen_hash(hashlen_string(NULL, name));
+
+ ea->attr.attr.name = devm_kstrdup(pdev, name, GFP_KERNEL);
+ if (!ea->attr.attr.name)
+ return -ENOMEM;
+
+ ea->attr.attr.mode = 0444;
+ ea->attr.show = etm_perf_sink_name_show;
+ ea->var = (unsigned long *)hash;
+
+ ret = sysfs_add_file_to_group(&pmu_dev->kobj,
+ &ea->attr.attr, "sinks");
+
+ if (!ret)
+ csdev->ea = ea;
+
+ return ret;
+}
+
+void etm_perf_del_symlink_sink(struct coresight_device *csdev)
+{
+ struct device *pmu_dev = etm_pmu.dev;
+ struct dev_ext_attribute *ea = csdev->ea;
+
+ if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+ csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+ return;
+
+ if (!ea)
+ return;
+
+ sysfs_remove_file_from_group(&pmu_dev->kobj,
+ &ea->attr.attr, "sinks");
+ csdev->ea = NULL;
+}
+
static int __init etm_perf_init(void)
{
int ret;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
index da7d9336a15c..015213abe00a 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.h
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
@@ -59,6 +59,8 @@ struct etm_event_data {
#ifdef CONFIG_CORESIGHT
int etm_perf_symlink(struct coresight_device *csdev, bool link);
+int etm_perf_add_symlink_sink(struct coresight_device *csdev);
+void etm_perf_del_symlink_sink(struct coresight_device *csdev);
static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
{
struct etm_event_data *data = perf_get_aux(handle);
@@ -70,7 +72,9 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
#else
static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
{ return -EINVAL; }
-
+int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+{ return -EINVAL; }
+void etm_perf_del_symlink_sink(struct coresight_device *csdev) {}
static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
{
return NULL;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 53e2fb6e86f6..fe76b176974a 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -55,7 +55,8 @@ static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
static bool etm4_arch_supported(u8 arch)
{
- switch (arch) {
+ /* Mask out the minor version number */
+ switch (arch & 0xf0) {
case ETM_ARCH_V4:
break;
default:
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 579f34943bf1..b936c6d7e13f 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -147,6 +147,7 @@ void coresight_disable_path(struct list_head *path);
int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data);
struct coresight_device *coresight_get_sink(struct list_head *path);
struct coresight_device *coresight_get_enabled_sink(bool reset);
+struct coresight_device *coresight_get_sink_by_id(u32 id);
struct list_head *coresight_build_path(struct coresight_device *csdev,
struct coresight_device *sink);
void coresight_release_path(struct list_head *path);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index ef339ff22090..f07825df5c7a 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -793,7 +793,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
struct stm_drvdata *drvdata;
struct resource *res = &adev->res;
struct resource ch_res;
- size_t res_size, bitmap_size;
+ size_t bitmap_size;
struct coresight_desc desc = { 0 };
struct device_node *np = adev->dev.of_node;
@@ -833,15 +833,11 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->write_bytes = stm_fundamental_data_size(drvdata);
- if (boot_nr_channel) {
+ if (boot_nr_channel)
drvdata->numsp = boot_nr_channel;
- res_size = min((resource_size_t)(boot_nr_channel *
- BYTES_PER_CHANNEL), resource_size(res));
- } else {
+ else
drvdata->numsp = stm_num_stimulus_port(drvdata);
- res_size = min((resource_size_t)(drvdata->numsp *
- BYTES_PER_CHANNEL), resource_size(res));
- }
+
bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long);
guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL);
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2b0df1a0a8df..29cef898afba 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -11,6 +11,7 @@
#include <linux/err.h>
#include <linux/export.h>
#include <linux/slab.h>
+#include <linux/stringhash.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/coresight.h>
@@ -18,6 +19,7 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include "coresight-etm-perf.h"
#include "coresight-priv.h"
static DEFINE_MUTEX(coresight_mutex);
@@ -540,6 +542,47 @@ struct coresight_device *coresight_get_enabled_sink(bool deactivate)
return dev ? to_coresight_device(dev) : NULL;
}
+static int coresight_sink_by_id(struct device *dev, void *data)
+{
+ struct coresight_device *csdev = to_coresight_device(dev);
+ unsigned long hash;
+
+ if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+ csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+
+ if (!csdev->ea)
+ return 0;
+ /*
+ * See function etm_perf_add_symlink_sink() to know where
+ * this comes from.
+ */
+ hash = (unsigned long)csdev->ea->var;
+
+ if ((u32)hash == *(u32 *)data)
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * coresight_get_sink_by_id - returns the sink that matches the id
+ * @id: Id of the sink to match
+ *
+ * The name of a sink is unique, whether it is found on the AMBA bus or
+ * otherwise. As such the hash of that name can easily be used to identify
+ * a sink.
+ */
+struct coresight_device *coresight_get_sink_by_id(u32 id)
+{
+ struct device *dev = NULL;
+
+ dev = bus_find_device(&coresight_bustype, NULL, &id,
+ coresight_sink_by_id);
+
+ return dev ? to_coresight_device(dev) : NULL;
+}
+
/*
* coresight_grab_device - Power up this device and any of the helper
* devices connected to it for trace operation. Since the helper devices
@@ -1167,6 +1210,22 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto err_out;
}
+ if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+ csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+ ret = etm_perf_add_symlink_sink(csdev);
+
+ if (ret) {
+ device_unregister(&csdev->dev);
+ /*
+ * As with the above, all resources are free'd
+ * explicitly via coresight_device_release() triggered
+ * from put_device(), which is in turn called from
+ * function device_unregister().
+ */
+ goto err_out;
+ }
+ }
+
mutex_lock(&coresight_mutex);
coresight_fixup_device_conns(csdev);
@@ -1185,6 +1244,7 @@ EXPORT_SYMBOL_GPL(coresight_register);
void coresight_unregister(struct coresight_device *csdev)
{
+ etm_perf_del_symlink_sink(csdev);
/* Remove references of that device in the topology */
coresight_remove_conns(csdev);
device_unregister(&csdev->dev);
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
index 89092f83567e..7045930fc958 100644
--- a/drivers/hwtracing/coresight/of_coresight.c
+++ b/drivers/hwtracing/coresight/of_coresight.c
@@ -80,8 +80,8 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
* Skip one-level up to the real device node, if we
* are using the new bindings.
*/
- if (!of_node_cmp(parent->name, "in-ports") ||
- !of_node_cmp(parent->name, "out-ports"))
+ if (of_node_name_eq(parent, "in-ports") ||
+ of_node_name_eq(parent, "out-ports"))
parent = of_get_next_parent(parent);
return parent;
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index fc6b7f8b62fb..7c1acc2f801c 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -422,6 +422,7 @@ static const struct intel_th_subdevice {
unsigned nres;
unsigned type;
unsigned otype;
+ bool mknode;
unsigned scrpd;
int id;
} intel_th_subdevices[] = {
@@ -456,6 +457,7 @@ static const struct intel_th_subdevice {
.name = "msc",
.id = 0,
.type = INTEL_TH_OUTPUT,
+ .mknode = true,
.otype = GTH_MSU,
.scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC0_IS_ENABLED,
},
@@ -476,6 +478,7 @@ static const struct intel_th_subdevice {
.name = "msc",
.id = 1,
.type = INTEL_TH_OUTPUT,
+ .mknode = true,
.otype = GTH_MSU,
.scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC1_IS_ENABLED,
},
@@ -635,7 +638,8 @@ intel_th_subdevice_alloc(struct intel_th *th,
}
if (subdev->type == INTEL_TH_OUTPUT) {
- thdev->dev.devt = MKDEV(th->major, th->num_thdevs);
+ if (subdev->mknode)
+ thdev->dev.devt = MKDEV(th->major, th->num_thdevs);
thdev->output.type = subdev->otype;
thdev->output.port = -1;
thdev->output.scratchpad = subdev->scrpd;
diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c
index 8426b7970c14..edc52d75e6bd 100644
--- a/drivers/hwtracing/intel_th/gth.c
+++ b/drivers/hwtracing/intel_th/gth.c
@@ -607,6 +607,7 @@ static void intel_th_gth_unassign(struct intel_th_device *thdev,
{
struct gth_device *gth = dev_get_drvdata(&thdev->dev);
int port = othdev->output.port;
+ int master;
if (thdev->host_mode)
return;
@@ -615,6 +616,9 @@ static void intel_th_gth_unassign(struct intel_th_device *thdev,
othdev->output.port = -1;
othdev->output.active = false;
gth->output[port].output = NULL;
+ for (master = 0; master <= TH_CONFIGURABLE_MASTERS; master++)
+ if (gth->master[master] == port)
+ gth->master[master] = -1;
spin_unlock(&gth->gth_lock);
}
diff --git a/drivers/hwtracing/intel_th/pti.c b/drivers/hwtracing/intel_th/pti.c
index 56694339cb06..0da6b787f553 100644
--- a/drivers/hwtracing/intel_th/pti.c
+++ b/drivers/hwtracing/intel_th/pti.c
@@ -272,19 +272,17 @@ static ssize_t lpp_dest_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
struct pti_device *pti = dev_get_drvdata(dev);
- ssize_t ret = -EINVAL;
int i;
- for (i = 0; i < ARRAY_SIZE(lpp_dest_str); i++)
- if (sysfs_streq(buf, lpp_dest_str[i]))
- break;
+ i = sysfs_match_string(lpp_dest_str, buf);
+ if (i < 0)
+ return i;
- if (i < ARRAY_SIZE(lpp_dest_str) && pti->lpp_dest_mask & BIT(i)) {
- pti->lpp_dest = i;
- ret = size;
- }
+ if (!(pti->lpp_dest_mask & BIT(i)))
+ return -EINVAL;
- return ret;
+ pti->lpp_dest = i;
+ return size;
}
static DEVICE_ATTR_RW(lpp_dest);
diff --git a/drivers/hwtracing/intel_th/sth.c b/drivers/hwtracing/intel_th/sth.c
index 4b7ae47789d2..3a1f4e650378 100644
--- a/drivers/hwtracing/intel_th/sth.c
+++ b/drivers/hwtracing/intel_th/sth.c
@@ -84,8 +84,12 @@ static ssize_t notrace sth_stm_packet(struct stm_data *stm_data,
/* Global packets (GERR, XSYNC, TRIG) are sent with register writes */
case STP_PACKET_GERR:
reg += 4;
+ /* fall through */
+
case STP_PACKET_XSYNC:
reg += 8;
+ /* fall through */
+
case STP_PACKET_TRIG:
if (flags & STP_PACKET_TIMESTAMPED)
reg += 4;
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 93ce3aa740a9..c7ba8acfd4d5 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -244,6 +244,9 @@ static int find_free_channels(unsigned long *bitmap, unsigned int start,
;
if (i == width)
return pos;
+
+ /* step over [pos..pos+i) to continue search */
+ pos += i;
}
return -1;
@@ -732,7 +735,7 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
struct stm_device *stm = stmf->stm;
struct stp_policy_id *id;
char *ids[] = { NULL, NULL };
- int ret = -EINVAL;
+ int ret = -EINVAL, wlimit = 1;
u32 size;
if (stmf->output.nr_chans)
@@ -760,8 +763,10 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
if (id->__reserved_0 || id->__reserved_1)
goto err_free;
- if (id->width < 1 ||
- id->width > PAGE_SIZE / stm->data->sw_mmiosz)
+ if (stm->data->sw_mmiosz)
+ wlimit = PAGE_SIZE / stm->data->sw_mmiosz;
+
+ if (id->width < 1 || id->width > wlimit)
goto err_free;
ids[0] = id->id;
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index ec6e69aa3a8e..d2fbb4bb4a43 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -183,6 +183,15 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
}
+static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev)
+{
+ i2c_dev->curr_msg = NULL;
+ i2c_dev->num_msgs = 0;
+
+ i2c_dev->msg_buf = NULL;
+ i2c_dev->msg_buf_remaining = 0;
+}
+
/*
* Note about I2C_C_CLEAR on error:
* The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
@@ -283,6 +292,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
time_left = wait_for_completion_timeout(&i2c_dev->completion,
adap->timeout);
+
+ bcm2835_i2c_finish_transfer(i2c_dev);
+
if (!time_left) {
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
BCM2835_I2C_C_CLEAR);
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index b13605718291..d917cefc5a19 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -382,8 +382,10 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
* Check for the message size against FIFO depth and set the
* 'hold bus' bit if it is greater than FIFO depth.
*/
- if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
+ if ((id->recv_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
ctrl_reg |= CDNS_I2C_CR_HOLD;
+ else
+ ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
@@ -440,8 +442,11 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
* Check for the message size against FIFO depth and set the
* 'hold bus' bit if it is greater than FIFO depth.
*/
- if (id->send_count > CDNS_I2C_FIFO_DEPTH)
+ if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
ctrl_reg |= CDNS_I2C_CR_HOLD;
+ else
+ ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
/* Clear the interrupts in interrupt status register. */
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b1086bfb0465..cd9c65f3d404 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1500,8 +1500,7 @@ static int omap_i2c_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int omap_i2c_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev)
{
struct omap_i2c_dev *omap = dev_get_drvdata(dev);
@@ -1527,7 +1526,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)
return 0;
}
-static int omap_i2c_runtime_resume(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_resume(struct device *dev)
{
struct omap_i2c_dev *omap = dev_get_drvdata(dev);
@@ -1542,20 +1541,18 @@ static int omap_i2c_runtime_resume(struct device *dev)
}
static const struct dev_pm_ops omap_i2c_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
omap_i2c_runtime_resume, NULL)
};
-#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
-#else
-#define OMAP_I2C_PM_OPS NULL
-#endif /* CONFIG_PM */
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
.remove = omap_i2c_remove,
.driver = {
.name = "omap_i2c",
- .pm = OMAP_I2C_PM_OPS,
+ .pm = &omap_i2c_pm_ops,
.of_match_table = of_match_ptr(omap_i2c_of_match),
},
};
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index e417ebf7628c..c77adbbea0c7 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -155,6 +155,8 @@ enum msg_end_type {
* @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
* provides additional features and allows for longer messages to
* be transferred in one go.
+ * @quirks: i2c adapter quirks for limiting write/read transfer size and not
+ * allowing 0 length transfers.
*/
struct tegra_i2c_hw_feature {
bool has_continue_xfer_support;
@@ -167,6 +169,7 @@ struct tegra_i2c_hw_feature {
bool has_multi_master_mode;
bool has_slcg_override_reg;
bool has_mst_fifo;
+ const struct i2c_adapter_quirks *quirks;
};
/**
@@ -837,6 +840,10 @@ static const struct i2c_adapter_quirks tegra_i2c_quirks = {
.max_write_len = 4096,
};
+static const struct i2c_adapter_quirks tegra194_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.has_continue_xfer_support = false,
.has_per_pkt_xfer_complete_irq = false,
@@ -848,6 +855,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
.has_mst_fifo = false,
+ .quirks = &tegra_i2c_quirks,
};
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -861,6 +869,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
.has_mst_fifo = false,
+ .quirks = &tegra_i2c_quirks,
};
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -874,6 +883,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
.has_mst_fifo = false,
+ .quirks = &tegra_i2c_quirks,
};
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -887,6 +897,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
.has_multi_master_mode = false,
.has_slcg_override_reg = true,
.has_mst_fifo = false,
+ .quirks = &tegra_i2c_quirks,
};
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -900,6 +911,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
.has_multi_master_mode = true,
.has_slcg_override_reg = true,
.has_mst_fifo = false,
+ .quirks = &tegra_i2c_quirks,
};
static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@@ -913,6 +925,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
.has_multi_master_mode = true,
.has_slcg_override_reg = true,
.has_mst_fifo = true,
+ .quirks = &tegra194_i2c_quirks,
};
/* Match table for of_platform binding */
@@ -964,7 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->base = base;
i2c_dev->div_clk = div_clk;
i2c_dev->adapter.algo = &tegra_i2c_algo;
- i2c_dev->adapter.quirks = &tegra_i2c_quirks;
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev;
@@ -980,6 +992,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->hw = of_device_get_match_data(&pdev->dev);
i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
"nvidia,tegra20-i2c-dvc");
+ i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
init_completion(&i2c_dev->msg_complete);
spin_lock_init(&i2c_dev->xfer_lock);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 1aca742fde4a..ccd76c71af09 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -470,9 +470,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
data_arg.data);
}
case I2C_RETRIES:
+ if (arg > INT_MAX)
+ return -EINVAL;
+
client->adapter->retries = arg;
break;
case I2C_TIMEOUT:
+ if (arg > INT_MAX)
+ return -EINVAL;
+
/* For historical reasons, user-space sets the timeout
* value in units of 10 ms.
*/
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index c39f89d2deba..2dc628d4f1ae 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1828,7 +1828,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
ret = i3c_master_retrieve_dev_info(newdev);
if (ret)
- goto err_free_dev;
+ goto err_detach_dev;
olddev = i3c_master_search_i3c_dev_duplicate(newdev);
if (olddev) {
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index b532e2c9cf5c..59279224e07f 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master,
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
}
-static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
- struct dw_i3c_xfer *xfer)
+static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master,
+ struct dw_i3c_xfer *xfer)
{
- unsigned long flags;
-
- spin_lock_irqsave(&master->xferqueue.lock, flags);
if (master->xferqueue.cur == xfer) {
u32 status;
@@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
} else {
list_del_init(&xfer->node);
}
+}
+
+static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
+ struct dw_i3c_xfer *xfer)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&master->xferqueue.lock, flags);
+ dw_i3c_master_dequeue_xfer_locked(master, xfer);
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
}
@@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
complete(&xfer->comp);
if (ret < 0) {
- dw_i3c_master_dequeue_xfer(master, xfer);
+ dw_i3c_master_dequeue_xfer_locked(master, xfer);
writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
master->regs + DEVICE_CTRL);
}
@@ -596,6 +602,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
ret = dw_i2c_clk_cfg(master);
if (ret)
return ret;
+ /* fall through */
case I3C_BUS_MODE_PURE:
ret = dw_i3c_clk_cfg(master);
if (ret)
@@ -901,9 +908,6 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
master->regs +
DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
- if (!old_dyn_addr)
- return 0;
-
master->addrs[data->index] = dev->info.dyn_addr;
return 0;
@@ -925,11 +929,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
return -ENOMEM;
data->index = pos;
- master->addrs[pos] = dev->info.dyn_addr;
+ master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr;
master->free_pos &= ~BIT(pos);
i3c_dev_set_master_data(dev, data);
- writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr),
+ writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]),
master->regs +
DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index bbd79b8b1a80..8889a4fdb454 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -1556,8 +1556,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
return PTR_ERR(master->pclk);
master->sysclk = devm_clk_get(&pdev->dev, "sysclk");
- if (IS_ERR(master->pclk))
- return PTR_ERR(master->pclk);
+ if (IS_ERR(master->sysclk))
+ return PTR_ERR(master->sysclk);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index da58020a144e..33a28cde126c 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -235,21 +235,28 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);
int ide_queue_sense_rq(ide_drive_t *drive, void *special)
{
- struct request *sense_rq = drive->sense_rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *sense_rq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hwif->lock, flags);
/* deferred failure from ide_prep_sense() */
if (!drive->sense_rq_armed) {
printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
drive->name);
+ spin_unlock_irqrestore(&hwif->lock, flags);
return -ENOMEM;
}
+ sense_rq = drive->sense_rq;
ide_req(sense_rq)->special = special;
drive->sense_rq_armed = false;
drive->hwif->rq = NULL;
ide_insert_request_head(drive, sense_rq);
+ spin_unlock_irqrestore(&hwif->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 8445b484ae69..b137f27a34d5 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -68,8 +68,10 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
}
if (!blk_update_request(rq, error, nr_bytes)) {
- if (rq == drive->sense_rq)
+ if (rq == drive->sense_rq) {
drive->sense_rq = NULL;
+ drive->sense_rq_active = false;
+ }
__blk_mq_end_request(rq, error);
return 0;
@@ -451,16 +453,11 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
}
-/*
- * Issue a new request to a device.
- */
-blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
- const struct blk_mq_queue_data *bd)
+blk_status_t ide_issue_rq(ide_drive_t *drive, struct request *rq,
+ bool local_requeue)
{
- ide_drive_t *drive = hctx->queue->queuedata;
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
struct ide_host *host = hwif->host;
- struct request *rq = bd->rq;
ide_startstop_t startstop;
if (!blk_rq_is_passthrough(rq) && !(rq->rq_flags & RQF_DONTPREP)) {
@@ -474,8 +471,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
if (ide_lock_host(host, hwif))
return BLK_STS_DEV_RESOURCE;
- blk_mq_start_request(rq);
-
spin_lock_irq(&hwif->lock);
if (!ide_lock_port(hwif)) {
@@ -511,18 +506,6 @@ repeat:
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
/*
- * we know that the queue isn't empty, but this can happen
- * if ->prep_rq() decides to kill a request
- */
- if (!rq) {
- rq = bd->rq;
- if (!rq) {
- ide_unlock_port(hwif);
- goto out;
- }
- }
-
- /*
* Sanity: don't accept a request that isn't a PM request
* if we are currently power managed. This is very important as
* blk_stop_queue() doesn't prevent the blk_fetch_request()
@@ -560,9 +543,12 @@ repeat:
}
} else {
plug_device:
+ if (local_requeue)
+ list_add(&rq->queuelist, &drive->rq_list);
spin_unlock_irq(&hwif->lock);
ide_unlock_host(host);
- ide_requeue_and_plug(drive, rq);
+ if (!local_requeue)
+ ide_requeue_and_plug(drive, rq);
return BLK_STS_OK;
}
@@ -573,6 +559,26 @@ out:
return BLK_STS_OK;
}
+/*
+ * Issue a new request to a device.
+ */
+blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *bd)
+{
+ ide_drive_t *drive = hctx->queue->queuedata;
+ ide_hwif_t *hwif = drive->hwif;
+
+ spin_lock_irq(&hwif->lock);
+ if (drive->sense_rq_active) {
+ spin_unlock_irq(&hwif->lock);
+ return BLK_STS_DEV_RESOURCE;
+ }
+ spin_unlock_irq(&hwif->lock);
+
+ blk_mq_start_request(bd->rq);
+ return ide_issue_rq(drive, bd->rq, false);
+}
+
static int drive_is_ready(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
@@ -893,13 +899,8 @@ EXPORT_SYMBOL_GPL(ide_pad_transfer);
void ide_insert_request_head(ide_drive_t *drive, struct request *rq)
{
- ide_hwif_t *hwif = drive->hwif;
- unsigned long flags;
-
- spin_lock_irqsave(&hwif->lock, flags);
+ drive->sense_rq_active = true;
list_add_tail(&rq->queuelist, &drive->rq_list);
- spin_unlock_irqrestore(&hwif->lock, flags);
-
kblockd_schedule_work(&drive->rq_work);
}
EXPORT_SYMBOL_GPL(ide_insert_request_head);
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 102aa3bc3e7f..8af7af6001eb 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -54,7 +54,9 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS;
scsi_req(rq)->cmd_len = 1;
ide_req(rq)->type = ATA_PRIV_MISC;
+ spin_lock_irq(&hwif->lock);
ide_insert_request_head(drive, rq);
+ spin_unlock_irq(&hwif->lock);
out:
return;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 63627be0811a..5aeaca24a28f 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work)
ide_drive_t *drive = container_of(work, ide_drive_t, rq_work);
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
+ blk_status_t ret;
LIST_HEAD(list);
- spin_lock_irq(&hwif->lock);
- if (!list_empty(&drive->rq_list))
- list_splice_init(&drive->rq_list, &list);
- spin_unlock_irq(&hwif->lock);
+ blk_mq_quiesce_queue(drive->queue);
- while (!list_empty(&list)) {
- rq = list_first_entry(&list, struct request, queuelist);
+ ret = BLK_STS_OK;
+ spin_lock_irq(&hwif->lock);
+ while (!list_empty(&drive->rq_list)) {
+ rq = list_first_entry(&drive->rq_list, struct request, queuelist);
list_del_init(&rq->queuelist);
- blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL);
+
+ spin_unlock_irq(&hwif->lock);
+ ret = ide_issue_rq(drive, rq, true);
+ spin_lock_irq(&hwif->lock);
}
+ spin_unlock_irq(&hwif->lock);
+
+ blk_mq_unquiesce_queue(drive->queue);
+
+ if (ret != BLK_STS_OK)
+ kblockd_schedule_work(&drive->rq_work);
}
static const u8 ide_hwif_to_major[] =
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 4c8c7a620d08..a5dc13576394 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -544,7 +544,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
drive->proc = proc_mkdir(drive->name, parent);
if (drive->proc) {
ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
- proc_create_data("setting", S_IFREG|S_IRUSR|S_IWUSR,
+ proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR,
drive->proc, &ide_settings_proc_fops,
drive);
}
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 8b5d85c91e9d..b8647b5c3d4d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1103,6 +1103,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
INTEL_CPU_FAM6(ATOM_GOLDMONT, idle_cpu_bxt),
INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, idle_cpu_bxt),
INTEL_CPU_FAM6(ATOM_GOLDMONT_X, idle_cpu_dnv),
+ INTEL_CPU_FAM6(ATOM_TREMONT_X, idle_cpu_dnv),
{}
};
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 780f87f72338..f03ed00685ea 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -150,8 +150,8 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
}
static int adxl345_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
{
struct adxl345_data *data = iio_priv(indio_dev);
s64 n;
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 421a0a8a1379..302781126bc6 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -31,6 +31,7 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
@@ -107,6 +108,8 @@ struct mma8452_data {
u8 data_cfg;
const struct mma_chip_info *chip_info;
int sleep_val;
+ struct regulator *vdd_reg;
+ struct regulator *vddio_reg;
};
/**
@@ -1534,9 +1537,39 @@ static int mma8452_probe(struct i2c_client *client,
mutex_init(&data->lock);
data->chip_info = match->data;
+ data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(data->vdd_reg)) {
+ if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&client->dev, "failed to get VDD regulator!\n");
+ return PTR_ERR(data->vdd_reg);
+ }
+
+ data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
+ if (IS_ERR(data->vddio_reg)) {
+ if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&client->dev, "failed to get VDDIO regulator!\n");
+ return PTR_ERR(data->vddio_reg);
+ }
+
+ ret = regulator_enable(data->vdd_reg);
+ if (ret) {
+ dev_err(&client->dev, "failed to enable VDD regulator!\n");
+ return ret;
+ }
+
+ ret = regulator_enable(data->vddio_reg);
+ if (ret) {
+ dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
+ goto disable_regulator_vdd;
+ }
+
ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
if (ret < 0)
- return ret;
+ goto disable_regulators;
switch (ret) {
case MMA8451_DEVICE_ID:
@@ -1549,7 +1582,8 @@ static int mma8452_probe(struct i2c_client *client,
break;
/* else: fall through */
default:
- return -ENODEV;
+ ret = -ENODEV;
+ goto disable_regulators;
}
dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
@@ -1566,13 +1600,13 @@ static int mma8452_probe(struct i2c_client *client,
ret = mma8452_reset(client);
if (ret < 0)
- return ret;
+ goto disable_regulators;
data->data_cfg = MMA8452_DATA_CFG_FS_2G;
ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
data->data_cfg);
if (ret < 0)
- return ret;
+ goto disable_regulators;
/*
* By default set transient threshold to max to avoid events if
@@ -1581,7 +1615,7 @@ static int mma8452_probe(struct i2c_client *client,
ret = i2c_smbus_write_byte_data(client, MMA8452_TRANSIENT_THS,
MMA8452_TRANSIENT_THS_MASK);
if (ret < 0)
- return ret;
+ goto disable_regulators;
if (client->irq) {
int irq2;
@@ -1595,7 +1629,7 @@ static int mma8452_probe(struct i2c_client *client,
MMA8452_CTRL_REG5,
data->chip_info->all_events);
if (ret < 0)
- return ret;
+ goto disable_regulators;
dev_dbg(&client->dev, "using interrupt line INT1\n");
}
@@ -1604,11 +1638,11 @@ static int mma8452_probe(struct i2c_client *client,
MMA8452_CTRL_REG4,
data->chip_info->enabled_events);
if (ret < 0)
- return ret;
+ goto disable_regulators;
ret = mma8452_trigger_setup(indio_dev);
if (ret < 0)
- return ret;
+ goto disable_regulators;
}
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
@@ -1661,12 +1695,19 @@ buffer_cleanup:
trigger_cleanup:
mma8452_trigger_cleanup(indio_dev);
+disable_regulators:
+ regulator_disable(data->vddio_reg);
+
+disable_regulator_vdd:
+ regulator_disable(data->vdd_reg);
+
return ret;
}
static int mma8452_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct mma8452_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
@@ -1678,6 +1719,9 @@ static int mma8452_remove(struct i2c_client *client)
mma8452_trigger_cleanup(indio_dev);
mma8452_standby(iio_priv(indio_dev));
+ regulator_disable(data->vddio_reg);
+ regulator_disable(data->vdd_reg);
+
return 0;
}
@@ -1696,6 +1740,18 @@ static int mma8452_runtime_suspend(struct device *dev)
return -EAGAIN;
}
+ ret = regulator_disable(data->vddio_reg);
+ if (ret) {
+ dev_err(dev, "failed to disable VDDIO regulator\n");
+ return ret;
+ }
+
+ ret = regulator_disable(data->vdd_reg);
+ if (ret) {
+ dev_err(dev, "failed to disable VDD regulator\n");
+ return ret;
+ }
+
return 0;
}
@@ -1705,9 +1761,22 @@ static int mma8452_runtime_resume(struct device *dev)
struct mma8452_data *data = iio_priv(indio_dev);
int ret, sleep_val;
+ ret = regulator_enable(data->vdd_reg);
+ if (ret) {
+ dev_err(dev, "failed to enable VDD regulator\n");
+ return ret;
+ }
+
+ ret = regulator_enable(data->vddio_reg);
+ if (ret) {
+ dev_err(dev, "failed to enable VDDIO regulator\n");
+ regulator_disable(data->vdd_reg);
+ return ret;
+ }
+
ret = mma8452_active(data);
if (ret < 0)
- return ret;
+ goto runtime_resume_failed;
ret = mma8452_get_odr_index(data);
sleep_val = 1000 / mma8452_samp_freq[ret][0];
@@ -1717,25 +1786,17 @@ static int mma8452_runtime_resume(struct device *dev)
msleep_interruptible(sleep_val);
return 0;
-}
-#endif
-#ifdef CONFIG_PM_SLEEP
-static int mma8452_suspend(struct device *dev)
-{
- return mma8452_standby(iio_priv(i2c_get_clientdata(
- to_i2c_client(dev))));
-}
+runtime_resume_failed:
+ regulator_disable(data->vddio_reg);
+ regulator_disable(data->vdd_reg);
-static int mma8452_resume(struct device *dev)
-{
- return mma8452_active(iio_priv(i2c_get_clientdata(
- to_i2c_client(dev))));
+ return ret;
}
#endif
static const struct dev_pm_ops mma8452_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(mma8452_runtime_suspend,
mma8452_runtime_resume, NULL)
};
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index f7b471121508..a3c0916479fa 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mutex.h>
@@ -918,12 +919,167 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
#define ST_ACCEL_TRIGGER_OPS NULL
#endif
+static const struct iio_mount_matrix *
+get_mount_matrix(const struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct st_sensor_data *adata = iio_priv(indio_dev);
+
+ return adata->mount_matrix;
+}
+
+static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = {
+ IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, get_mount_matrix),
+ { },
+};
+
+/* Read ST-specific _ONT orientation data from ACPI and generate an
+ * appropriate mount matrix.
+ */
+static int apply_acpi_orientation(struct iio_dev *indio_dev,
+ struct iio_chan_spec *channels)
+{
+#ifdef CONFIG_ACPI
+ struct st_sensor_data *adata = iio_priv(indio_dev);
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_device *adev;
+ union acpi_object *ont;
+ union acpi_object *elements;
+ acpi_status status;
+ int ret = -EINVAL;
+ unsigned int val;
+ int i, j;
+ int final_ont[3][3] = { { 0 }, };
+
+ /* For some reason, ST's _ONT translation does not apply directly
+ * to the data read from the sensor. Another translation must be
+ * performed first, as described by the matrix below. Perhaps
+ * ST required this specific translation for the first product
+ * where the device was mounted?
+ */
+ const int default_ont[3][3] = {
+ { 0, 1, 0 },
+ { -1, 0, 0 },
+ { 0, 0, -1 },
+ };
+
+
+ adev = ACPI_COMPANION(adata->dev);
+ if (!adev)
+ return 0;
+
+ /* Read _ONT data, which should be a package of 6 integers. */
+ status = acpi_evaluate_object(adev->handle, "_ONT", NULL, &buffer);
+ if (status == AE_NOT_FOUND) {
+ return 0;
+ } else if (ACPI_FAILURE(status)) {
+ dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n",
+ status);
+ return status;
+ }
+
+ ont = buffer.pointer;
+ if (ont->type != ACPI_TYPE_PACKAGE || ont->package.count != 6)
+ goto out;
+
+ /* The first 3 integers provide axis order information.
+ * e.g. 0 1 2 would indicate normal X,Y,Z ordering.
+ * e.g. 1 0 2 indicates that data arrives in order Y,X,Z.
+ */
+ elements = ont->package.elements;
+ for (i = 0; i < 3; i++) {
+ if (elements[i].type != ACPI_TYPE_INTEGER)
+ goto out;
+
+ val = elements[i].integer.value;
+ if (val < 0 || val > 2)
+ goto out;
+
+ /* Avoiding full matrix multiplication, we simply reorder the
+ * columns in the default_ont matrix according to the
+ * ordering provided by _ONT.
+ */
+ final_ont[0][i] = default_ont[0][val];
+ final_ont[1][i] = default_ont[1][val];
+ final_ont[2][i] = default_ont[2][val];
+ }
+
+ /* The final 3 integers provide sign flip information.
+ * 0 means no change, 1 means flip.
+ * e.g. 0 0 1 means that Z data should be sign-flipped.
+ * This is applied after the axis reordering from above.
+ */
+ elements += 3;
+ for (i = 0; i < 3; i++) {
+ if (elements[i].type != ACPI_TYPE_INTEGER)
+ goto out;
+
+ val = elements[i].integer.value;
+ if (val != 0 && val != 1)
+ goto out;
+ if (!val)
+ continue;
+
+ /* Flip the values in the indicated column */
+ final_ont[0][i] *= -1;
+ final_ont[1][i] *= -1;
+ final_ont[2][i] *= -1;
+ }
+
+ /* Convert our integer matrix to a string-based iio_mount_matrix */
+ adata->mount_matrix = devm_kmalloc(&indio_dev->dev,
+ sizeof(*adata->mount_matrix),
+ GFP_KERNEL);
+ if (!adata->mount_matrix) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {
+ int matrix_val = final_ont[i][j];
+ char *str_value;
+
+ switch (matrix_val) {
+ case -1:
+ str_value = "-1";
+ break;
+ case 0:
+ str_value = "0";
+ break;
+ case 1:
+ str_value = "1";
+ break;
+ default:
+ goto out;
+ }
+ adata->mount_matrix->rotation[i * 3 + j] = str_value;
+ }
+ }
+
+ /* Expose the mount matrix via ext_info */
+ for (i = 0; i < indio_dev->num_channels; i++)
+ channels[i].ext_info = mount_matrix_ext_info;
+
+ ret = 0;
+ dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n");
+
+out:
+ kfree(buffer.pointer);
+ return ret;
+#else /* !CONFIG_ACPI */
+ return 0;
+#endif
+}
+
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);
+ struct iio_chan_spec *channels;
+ size_t channels_size;
int err;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -942,9 +1098,22 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor_settings->multi_read_bit;
- indio_dev->channels = adata->sensor_settings->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
+ channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec);
+ channels = devm_kmemdup(&indio_dev->dev,
+ adata->sensor_settings->ch,
+ channels_size, GFP_KERNEL);
+ if (!channels) {
+ err = -ENOMEM;
+ goto st_accel_power_off;
+ }
+
+ if (apply_acpi_orientation(indio_dev, channels))
+ dev_warn(&indio_dev->dev,
+ "failed to apply ACPI orientation data: %d\n", err);
+
+ indio_dev->channels = channels;
adata->current_fullscale = (struct st_sensor_fullscale_avl *)
&adata->sensor_settings->fs.fs_avl[0];
adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7a3ca4ec0cb7..5debc67df70a 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -57,18 +57,48 @@ config AD7298
module will be called ad7298.
config AD7476
- tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
+ tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD an TI"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
- Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
- AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
- AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
+ Say yes here to build support for the following SPI analog to
+ digital converters (ADCs):
+ Analog Devices: AD7273, AD7274, AD7276, AD7277, AD7278, AD7475,
+ AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495, AD7910,
+ AD7920.
+ Texas Instruments: ADS7866, ADS7867, ADS7868.
To compile this driver as a module, choose M here: the
module will be called ad7476.
+config AD7606
+ tristate
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+
+config AD7606_IFACE_PARALLEL
+ tristate "Analog Devices AD7606 ADC driver with parallel interface support"
+ depends on HAS_IOMEM
+ select AD7606
+ help
+ Say yes here to build parallel interface support for Analog Devices:
+ ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7606_parallel.
+
+config AD7606_IFACE_SPI
+ tristate "Analog Devices AD7606 ADC driver with spi interface support"
+ depends on SPI
+ select AD7606
+ help
+ Say yes here to build spi interface support for Analog Devices:
+ ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7606_spi.
+
config AD7766
tristate "Analog Devices AD7766/AD7767 ADC driver"
depends on SPI_MASTER
@@ -81,6 +111,19 @@ config AD7766
To compile this driver as a module, choose M here: the module will be
called ad7766.
+config AD7768_1
+ tristate "Analog Devices AD7768-1 ADC driver"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Analog Devices AD7768-1 SPI
+ simultaneously sampling sigma-delta analog to digital converter (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7768-1.
+
config AD7791
tristate "Analog Devices AD7791 ADC driver"
depends on SPI
@@ -367,6 +410,15 @@ config INA2XX_ADC
Say yes here to build support for TI INA2xx family of Power Monitors.
This driver is mutually exclusive with the HWMON version.
+config INGENIC_ADC
+ tristate "Ingenic JZ47xx SoCs ADC driver"
+ depends on MIPS || COMPILE_TEST
+ help
+ Say yes here to build support for the Ingenic JZ47xx SoCs ADC unit.
+
+ This driver can also be built as a module. If so, the module will be
+ called ingenic_adc.
+
config IMX7D_ADC
tristate "Freescale IMX7D ADC driver"
depends on ARCH_MXC || COMPILE_TEST
@@ -576,6 +628,16 @@ config NAU7802
To compile this driver as a module, choose M here: the
module will be called nau7802.
+config NPCM_ADC
+ tristate "Nuvoton NPCM ADC driver"
+ depends on ARCH_NPCM || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ Say yes here to build support for Nuvoton NPCM ADC.
+
+ This driver can also be built as a module. If so, the module
+ will be called npcm_adc.
+
config PALMAS_GPADC
tristate "TI Palmas General Purpose ADC"
depends on MFD_PALMAS
@@ -908,6 +970,16 @@ config TI_ADS8688
This driver can also be built as a module. If so, the module will be
called ti-ads8688.
+config TI_ADS124S08
+ tristate "Texas Instruments ADS124S08"
+ depends on SPI && OF
+ help
+ If you say yes here you get support for Texas Instruments ADS124S08
+ and ADS124S06 ADC chips
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-ads124s08.
+
config TI_AM335X_ADC
tristate "TI's AM335X ADC driver"
depends on MFD_TI_AM335X_TSCADC && HAS_DMA
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 07df37f621bd..d50eb47da484 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -11,7 +11,11 @@ obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7298) += ad7298.o
obj-$(CONFIG_AD7923) += ad7923.o
obj-$(CONFIG_AD7476) += ad7476.o
+obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
+obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
+obj-$(CONFIG_AD7606) += ad7606.o
obj-$(CONFIG_AD7766) += ad7766.o
+obj-$(CONFIG_AD7768_1) += ad7768-1.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
@@ -36,6 +40,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_HX711) += hx711.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
+obj-$(CONFIG_INGENIC_ADC) += ingenic-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
@@ -55,6 +60,7 @@ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
+obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
@@ -81,6 +87,7 @@ obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o
obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
+obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 0549686b9ef8..76747488044b 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -59,6 +59,9 @@ enum ad7476_supported_device_ids {
ID_ADC081S,
ID_ADC101S,
ID_ADC121S,
+ ID_ADS7866,
+ ID_ADS7867,
+ ID_ADS7868,
};
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
@@ -157,6 +160,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
+#define ADS786X_CHAN(bits) _AD7476_CHAN((bits), 12 - (bits), \
+ BIT(IIO_CHAN_INFO_RAW))
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7091R] = {
@@ -209,6 +214,18 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
.channel[0] = ADC081S_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
+ [ID_ADS7866] = {
+ .channel[0] = ADS786X_CHAN(12),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ },
+ [ID_ADS7867] = {
+ .channel[0] = ADS786X_CHAN(10),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ },
+ [ID_ADS7868] = {
+ .channel[0] = ADS786X_CHAN(8),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ },
};
static const struct iio_info ad7476_info = {
@@ -314,6 +331,9 @@ static const struct spi_device_id ad7476_id[] = {
{"adc081s", ID_ADC081S},
{"adc101s", ID_ADC101S},
{"adc121s", ID_ADC121S},
+ {"ads7866", ID_ADS7866},
+ {"ads7867", ID_ADS7867},
+ {"ads7868", ID_ADS7868},
{}
};
MODULE_DEVICE_TABLE(spi, ad7476_id);
diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 7308fa8fbb4c..ebb8de03bbce 100644
--- a/drivers/staging/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -1,28 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* AD7606 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
*/
-#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/util_macros.h>
#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7606.h"
@@ -30,8 +31,12 @@
* Scales are computed as 5000/32768 and 10000/32768 respectively,
* so that when applied to the raw values they provide mV values
*/
-static const unsigned int scale_avail[2][2] = {
- {0, 152588}, {0, 305176}
+static const unsigned int scale_avail[2] = {
+ 152588, 305176
+};
+
+static const unsigned int ad7606_oversampling_avail[7] = {
+ 1, 2, 4, 8, 16, 32, 64,
};
static int ad7606_reset(struct ad7606_state *st)
@@ -82,36 +87,24 @@ static int ad7606_read_samples(struct ad7606_state *st)
static irqreturn_t ad7606_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
- struct ad7606_state *st = iio_priv(pf->indio_dev);
-
- gpiod_set_value(st->gpio_convst, 1);
-
- return IRQ_HANDLED;
-}
-
-/**
- * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer
- * @work_s: the work struct through which this was scheduled
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- * I think the one copy of this at a time was to avoid problems if the
- * trigger was set far too high and the reads then locked up the computer.
- **/
-static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
-{
- struct ad7606_state *st = container_of(work_s, struct ad7606_state,
- poll_work);
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7606_state *st = iio_priv(indio_dev);
int ret;
+ mutex_lock(&st->lock);
+
ret = ad7606_read_samples(st);
if (ret == 0)
iio_push_to_buffers_with_timestamp(indio_dev, st->data,
iio_get_time_ns(indio_dev));
- gpiod_set_value(st->gpio_convst, 0);
iio_trigger_notify_done(indio_dev->trig);
+ /* The rising edge of the CONVST signal starts a new conversion. */
+ gpiod_set_value(st->gpio_convst, 1);
+
+ mutex_unlock(&st->lock);
+
+ return IRQ_HANDLED;
}
static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
@@ -119,12 +112,13 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
struct ad7606_state *st = iio_priv(indio_dev);
int ret;
- st->done = false;
gpiod_set_value(st->gpio_convst, 1);
-
- ret = wait_event_interruptible(st->wq_data_avail, st->done);
- if (ret)
+ ret = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ ret = -ETIMEDOUT;
goto error_ret;
+ }
ret = ad7606_read_samples(st);
if (ret == 0)
@@ -159,8 +153,8 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
*val = (short)ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- *val = scale_avail[st->range][0];
- *val2 = scale_avail[st->range][1];
+ *val = 0;
+ *val2 = scale_avail[st->range];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = st->oversampling;
@@ -176,8 +170,8 @@ static ssize_t in_voltage_scale_available_show(struct device *dev,
int i, len = 0;
for (i = 0; i < ARRAY_SIZE(scale_avail); i++)
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
- scale_avail[i][0], scale_avail[i][1]);
+ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
+ scale_avail[i]);
buf[len - 1] = '\n';
@@ -186,18 +180,6 @@ static ssize_t in_voltage_scale_available_show(struct device *dev,
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
-static int ad7606_oversampling_get_index(unsigned int val)
-{
- unsigned char supported[] = {1, 2, 4, 8, 16, 32, 64};
- int i;
-
- for (i = 0; i < ARRAY_SIZE(supported); i++)
- if (val == supported[i])
- return i;
-
- return -EINVAL;
-}
-
static int ad7606_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
@@ -206,36 +188,29 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
{
struct ad7606_state *st = iio_priv(indio_dev);
DECLARE_BITMAP(values, 3);
- int ret, i;
+ int i;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- ret = -EINVAL;
mutex_lock(&st->lock);
- for (i = 0; i < ARRAY_SIZE(scale_avail); i++)
- if (val2 == scale_avail[i][1]) {
- gpiod_set_value(st->gpio_range, i);
- st->range = i;
-
- ret = 0;
- break;
- }
+ i = find_closest(val2, scale_avail, ARRAY_SIZE(scale_avail));
+ gpiod_set_value(st->gpio_range, i);
+ st->range = i;
mutex_unlock(&st->lock);
- return ret;
+ return 0;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
if (val2)
return -EINVAL;
- ret = ad7606_oversampling_get_index(val);
- if (ret < 0)
- return ret;
+ i = find_closest(val, ad7606_oversampling_avail,
+ ARRAY_SIZE(ad7606_oversampling_avail));
- values[0] = ret;
+ values[0] = i;
mutex_lock(&st->lock);
- gpiod_set_array_value(3, st->gpio_os->desc, st->gpio_os->info,
- values);
- st->oversampling = val;
+ gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc,
+ st->gpio_os->info, values);
+ st->oversampling = ad7606_oversampling_avail[i];
mutex_unlock(&st->lock);
return 0;
@@ -274,8 +249,7 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
-#define AD760X_CHANNEL(num, mask) \
- { \
+#define AD760X_CHANNEL(num, mask) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
@@ -290,7 +264,7 @@ static const struct attribute_group ad7606_attribute_group_range = {
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
- }
+}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, 0)
@@ -319,9 +293,7 @@ static const struct iio_chan_spec ad7606_channels[] = {
};
static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
- /*
- * More devices added in future
- */
+ /* More devices added in future */
[ID_AD7605_4] = {
.channels = ad7605_channels,
.num_channels = 5,
@@ -347,7 +319,7 @@ static int ad7606_request_gpios(struct ad7606_state *st)
{
struct device *dev = st->dev;
- st->gpio_convst = devm_gpiod_get(dev, "conversion-start",
+ st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_convst))
return PTR_ERR(st->gpio_convst);
@@ -356,7 +328,8 @@ static int ad7606_request_gpios(struct ad7606_state *st)
if (IS_ERR(st->gpio_reset))
return PTR_ERR(st->gpio_reset);
- st->gpio_range = devm_gpiod_get_optional(dev, "range", GPIOD_OUT_LOW);
+ st->gpio_range = devm_gpiod_get_optional(dev, "adi,range",
+ GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_range))
return PTR_ERR(st->gpio_range);
@@ -365,7 +338,7 @@ static int ad7606_request_gpios(struct ad7606_state *st)
if (IS_ERR(st->gpio_standby))
return PTR_ERR(st->gpio_standby);
- st->gpio_frstdata = devm_gpiod_get_optional(dev, "first-data",
+ st->gpio_frstdata = devm_gpiod_get_optional(dev, "adi,first-data",
GPIOD_IN);
if (IS_ERR(st->gpio_frstdata))
return PTR_ERR(st->gpio_frstdata);
@@ -373,13 +346,17 @@ static int ad7606_request_gpios(struct ad7606_state *st)
if (!st->chip_info->has_oversampling)
return 0;
- st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio",
+ st->gpio_os = devm_gpiod_get_array_optional(dev,
+ "adi,oversampling-ratio",
GPIOD_OUT_LOW);
return PTR_ERR_OR_ZERO(st->gpio_os);
}
-/**
- * Interrupt handler
+/*
+ * The BUSY signal indicates when conversions are in progress, so when a rising
+ * edge of CONVST is applied, BUSY goes logic high and transitions low at the
+ * end of the entire conversion process. The falling edge of the BUSY signal
+ * triggers this interrupt.
*/
static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
{
@@ -387,37 +364,87 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
struct ad7606_state *st = iio_priv(indio_dev);
if (iio_buffer_enabled(indio_dev)) {
- schedule_work(&st->poll_work);
+ gpiod_set_value(st->gpio_convst, 0);
+ iio_trigger_poll_chained(st->trig);
} else {
- st->done = true;
- wake_up_interruptible(&st->wq_data_avail);
+ complete(&st->completion);
}
return IRQ_HANDLED;
};
+static int ad7606_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ if (st->trig != trig)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ad7606_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ iio_triggered_buffer_postenable(indio_dev);
+ gpiod_set_value(st->gpio_convst, 1);
+
+ return 0;
+}
+
+static int ad7606_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ gpiod_set_value(st->gpio_convst, 0);
+
+ return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
+ .postenable = &ad7606_buffer_postenable,
+ .predisable = &ad7606_buffer_predisable,
+};
+
static const struct iio_info ad7606_info_no_os_or_range = {
.read_raw = &ad7606_read_raw,
+ .validate_trigger = &ad7606_validate_trigger,
};
static const struct iio_info ad7606_info_os_and_range = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os_and_range,
+ .validate_trigger = &ad7606_validate_trigger,
};
static const struct iio_info ad7606_info_os = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os,
+ .validate_trigger = &ad7606_validate_trigger,
};
static const struct iio_info ad7606_info_range = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_range,
+ .validate_trigger = &ad7606_validate_trigger,
+};
+
+static const struct iio_trigger_ops ad7606_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
};
+static void ad7606_regulator_disable(void *data)
+{
+ struct ad7606_state *st = data;
+
+ regulator_disable(st->reg);
+}
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
const char *name, unsigned int id,
const struct ad7606_bus_ops *bops)
@@ -431,6 +458,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
return -ENOMEM;
st = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
st->dev = dev;
mutex_init(&st->lock);
@@ -439,7 +467,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
/* tied to logic low, analog input range is +/- 5V */
st->range = 0;
st->oversampling = 1;
- INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring);
st->reg = devm_regulator_get(dev, "avcc");
if (IS_ERR(st->reg))
@@ -451,11 +478,15 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
return ret;
}
+ ret = devm_add_action_or_reset(dev, ad7606_regulator_disable, st);
+ if (ret)
+ return ret;
+
st->chip_info = &ad7606_chip_info_tbl[id];
ret = ad7606_request_gpios(st);
if (ret)
- goto error_disable_reg;
+ return ret;
indio_dev->dev.parent = dev;
if (st->gpio_os) {
@@ -474,56 +505,45 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- init_waitqueue_head(&st->wq_data_avail);
+ init_completion(&st->completion);
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
- ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name,
- indio_dev);
- if (ret)
- goto error_disable_reg;
-
- ret = iio_triggered_buffer_setup(indio_dev, &ad7606_trigger_handler,
- NULL, NULL);
- if (ret)
- goto error_free_irq;
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!st->trig)
+ return -ENOMEM;
- ret = iio_device_register(indio_dev);
+ st->trig->ops = &ad7606_trigger_ops;
+ st->trig->dev.parent = dev;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, st->trig);
if (ret)
- goto error_unregister_ring;
+ return ret;
- dev_set_drvdata(dev, indio_dev);
+ indio_dev->trig = iio_trigger_get(st->trig);
- return 0;
-error_unregister_ring:
- iio_triggered_buffer_cleanup(indio_dev);
+ ret = devm_request_threaded_irq(dev, irq,
+ NULL,
+ &ad7606_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ name, indio_dev);
+ if (ret)
+ return ret;
-error_free_irq:
- free_irq(irq, indio_dev);
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7606_trigger_handler,
+ &ad7606_buffer_ops);
+ if (ret)
+ return ret;
-error_disable_reg:
- regulator_disable(st->reg);
- return ret;
+ return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_GPL(ad7606_probe);
-int ad7606_remove(struct device *dev, int irq)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad7606_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
-
- free_irq(irq, indio_dev);
- regulator_disable(st->reg);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ad7606_remove);
-
#ifdef CONFIG_PM_SLEEP
static int ad7606_suspend(struct device *dev)
diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 86188054b60b..5d12410f68e1 100644
--- a/drivers/staging/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -1,9 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* AD7606 ADC driver
*
* Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
*/
#ifndef IIO_ADC_AD7606_H_
@@ -15,7 +14,6 @@
* @num_channels: number of channels
* @has_oversampling: whether the device has oversampling support
*/
-
struct ad7606_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
@@ -27,13 +25,9 @@ struct ad7606_chip_info {
* @dev pointer to kernel device
* @chip_info entry in the table of chips that describes this device
* @reg regulator info for the the power supply of the device
- * @poll_work work struct for continuously reading data from the device
- * into an IIO triggered buffer
- * @wq_data_avail wait queue struct for buffer mode
* @bops bus operations (SPI or parallel)
* @range voltage range selection, selects which scale to apply
* @oversampling oversampling selection
- * @done marks whether reading data is done
* @base_address address from where to read data in parallel operation
* @lock protect sensor state from concurrent accesses to GPIOs
* @gpio_convst GPIO descriptor for conversion start signal (CONVST)
@@ -44,19 +38,17 @@ struct ad7606_chip_info {
* @gpio_frstdata GPIO descriptor for reading from device when data
* is being read on the first channel
* @gpio_os GPIO descriptors to control oversampling on the device
+ * @complete completion to indicate end of conversion
+ * @trig The IIO trigger associated with the device.
* @data buffer for reading data from the device
*/
-
struct ad7606_state {
struct device *dev;
const struct ad7606_chip_info *chip_info;
struct regulator *reg;
- struct work_struct poll_work;
- wait_queue_head_t wq_data_avail;
const struct ad7606_bus_ops *bops;
unsigned int range;
unsigned int oversampling;
- bool done;
void __iomem *base_address;
struct mutex lock; /* protect sensor state */
@@ -66,6 +58,8 @@ struct ad7606_state {
struct gpio_desc *gpio_standby;
struct gpio_desc *gpio_frstdata;
struct gpio_descs *gpio_os;
+ struct iio_trigger *trig;
+ struct completion completion;
/*
* DMA (thus cache coherency maintenance) requires the
@@ -87,7 +81,6 @@ struct ad7606_bus_ops {
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
const char *name, unsigned int id,
const struct ad7606_bus_ops *bops);
-int ad7606_remove(struct device *dev, int irq);
enum ad7606_supported_device_ids {
ID_AD7605_4,
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index 8bd86e727b02..1b08028facde 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* AD7606 Parallel Interface ADC driver
*
* Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
*/
#include <linux/module.h>
@@ -27,7 +26,7 @@ static int ad7606_par16_read_block(struct device *dev,
}
static const struct ad7606_bus_ops ad7606_par16_bops = {
- .read_block = ad7606_par16_read_block,
+ .read_block = ad7606_par16_read_block,
};
static int ad7606_par8_read_block(struct device *dev,
@@ -42,7 +41,7 @@ static int ad7606_par8_read_block(struct device *dev,
}
static const struct ad7606_bus_ops ad7606_par8_bops = {
- .read_block = ad7606_par8_read_block,
+ .read_block = ad7606_par8_read_block,
};
static int ad7606_par_probe(struct platform_device *pdev)
@@ -72,40 +71,33 @@ static int ad7606_par_probe(struct platform_device *pdev)
&ad7606_par8_bops);
}
-static int ad7606_par_remove(struct platform_device *pdev)
-{
- return ad7606_remove(&pdev->dev, platform_get_irq(pdev, 0));
-}
-
static const struct platform_device_id ad7606_driver_ids[] = {
- {
- .name = "ad7605-4",
- .driver_data = ID_AD7605_4,
- }, {
- .name = "ad7606-8",
- .driver_data = ID_AD7606_8,
- }, {
- .name = "ad7606-6",
- .driver_data = ID_AD7606_6,
- }, {
- .name = "ad7606-4",
- .driver_data = ID_AD7606_4,
- },
+ { .name = "ad7605-4", .driver_data = ID_AD7605_4, },
+ { .name = "ad7606-4", .driver_data = ID_AD7606_4, },
+ { .name = "ad7606-6", .driver_data = ID_AD7606_6, },
+ { .name = "ad7606-8", .driver_data = ID_AD7606_8, },
{ }
};
-
MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
+static const struct of_device_id ad7606_of_match[] = {
+ { .compatible = "adi,ad7605-4" },
+ { .compatible = "adi,ad7606-4" },
+ { .compatible = "adi,ad7606-6" },
+ { .compatible = "adi,ad7606-8" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ad7606_of_match);
+
static struct platform_driver ad7606_driver = {
.probe = ad7606_par_probe,
- .remove = ad7606_par_remove,
.id_table = ad7606_driver_ids,
.driver = {
- .name = "ad7606",
- .pm = AD7606_PM_OPS,
+ .name = "ad7606",
+ .pm = AD7606_PM_OPS,
+ .of_match_table = ad7606_of_match,
},
};
-
module_platform_driver(ad7606_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index b76ca5a8c059..4fd0ec36a086 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* AD7606 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
*/
#include <linux/module.h>
@@ -37,7 +36,7 @@ static int ad7606_spi_read_block(struct device *dev,
}
static const struct ad7606_bus_ops ad7606_spi_bops = {
- .read_block = ad7606_spi_read_block,
+ .read_block = ad7606_spi_read_block,
};
static int ad7606_spi_probe(struct spi_device *spi)
@@ -49,28 +48,32 @@ static int ad7606_spi_probe(struct spi_device *spi)
&ad7606_spi_bops);
}
-static int ad7606_spi_remove(struct spi_device *spi)
-{
- return ad7606_remove(&spi->dev, spi->irq);
-}
-
-static const struct spi_device_id ad7606_id[] = {
- {"ad7605-4", ID_AD7605_4},
- {"ad7606-8", ID_AD7606_8},
- {"ad7606-6", ID_AD7606_6},
- {"ad7606-4", ID_AD7606_4},
+static const struct spi_device_id ad7606_id_table[] = {
+ { "ad7605-4", ID_AD7605_4 },
+ { "ad7606-4", ID_AD7606_4 },
+ { "ad7606-6", ID_AD7606_6 },
+ { "ad7606-8", ID_AD7606_8 },
{}
};
-MODULE_DEVICE_TABLE(spi, ad7606_id);
+MODULE_DEVICE_TABLE(spi, ad7606_id_table);
+
+static const struct of_device_id ad7606_of_match[] = {
+ { .compatible = "adi,ad7605-4" },
+ { .compatible = "adi,ad7606-4" },
+ { .compatible = "adi,ad7606-6" },
+ { .compatible = "adi,ad7606-8" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ad7606_of_match);
static struct spi_driver ad7606_driver = {
.driver = {
.name = "ad7606",
+ .of_match_table = ad7606_of_match,
.pm = AD7606_PM_OPS,
},
.probe = ad7606_spi_probe,
- .remove = ad7606_spi_remove,
- .id_table = ad7606_id,
+ .id_table = ad7606_id_table,
};
module_spi_driver(ad7606_driver);
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
new file mode 100644
index 000000000000..0d132708c429
--- /dev/null
+++ b/drivers/iio/adc/ad7768-1.c
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices AD7768-1 SPI ADC driver
+ *
+ * Copyright 2017 Analog Devices Inc.
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+/* AD7768 registers definition */
+#define AD7768_REG_CHIP_TYPE 0x3
+#define AD7768_REG_PROD_ID_L 0x4
+#define AD7768_REG_PROD_ID_H 0x5
+#define AD7768_REG_CHIP_GRADE 0x6
+#define AD7768_REG_SCRATCH_PAD 0x0A
+#define AD7768_REG_VENDOR_L 0x0C
+#define AD7768_REG_VENDOR_H 0x0D
+#define AD7768_REG_INTERFACE_FORMAT 0x14
+#define AD7768_REG_POWER_CLOCK 0x15
+#define AD7768_REG_ANALOG 0x16
+#define AD7768_REG_ANALOG2 0x17
+#define AD7768_REG_CONVERSION 0x18
+#define AD7768_REG_DIGITAL_FILTER 0x19
+#define AD7768_REG_SINC3_DEC_RATE_MSB 0x1A
+#define AD7768_REG_SINC3_DEC_RATE_LSB 0x1B
+#define AD7768_REG_DUTY_CYCLE_RATIO 0x1C
+#define AD7768_REG_SYNC_RESET 0x1D
+#define AD7768_REG_GPIO_CONTROL 0x1E
+#define AD7768_REG_GPIO_WRITE 0x1F
+#define AD7768_REG_GPIO_READ 0x20
+#define AD7768_REG_OFFSET_HI 0x21
+#define AD7768_REG_OFFSET_MID 0x22
+#define AD7768_REG_OFFSET_LO 0x23
+#define AD7768_REG_GAIN_HI 0x24
+#define AD7768_REG_GAIN_MID 0x25
+#define AD7768_REG_GAIN_LO 0x26
+#define AD7768_REG_SPI_DIAG_ENABLE 0x28
+#define AD7768_REG_ADC_DIAG_ENABLE 0x29
+#define AD7768_REG_DIG_DIAG_ENABLE 0x2A
+#define AD7768_REG_ADC_DATA 0x2C
+#define AD7768_REG_MASTER_STATUS 0x2D
+#define AD7768_REG_SPI_DIAG_STATUS 0x2E
+#define AD7768_REG_ADC_DIAG_STATUS 0x2F
+#define AD7768_REG_DIG_DIAG_STATUS 0x30
+#define AD7768_REG_MCLK_COUNTER 0x31
+
+/* AD7768_REG_POWER_CLOCK */
+#define AD7768_PWR_MCLK_DIV_MSK GENMASK(5, 4)
+#define AD7768_PWR_MCLK_DIV(x) FIELD_PREP(AD7768_PWR_MCLK_DIV_MSK, x)
+#define AD7768_PWR_PWRMODE_MSK GENMASK(1, 0)
+#define AD7768_PWR_PWRMODE(x) FIELD_PREP(AD7768_PWR_PWRMODE_MSK, x)
+
+/* AD7768_REG_DIGITAL_FILTER */
+#define AD7768_DIG_FIL_FIL_MSK GENMASK(6, 4)
+#define AD7768_DIG_FIL_FIL(x) FIELD_PREP(AD7768_DIG_FIL_FIL_MSK, x)
+#define AD7768_DIG_FIL_DEC_MSK GENMASK(2, 0)
+#define AD7768_DIG_FIL_DEC_RATE(x) FIELD_PREP(AD7768_DIG_FIL_DEC_MSK, x)
+
+/* AD7768_REG_CONVERSION */
+#define AD7768_CONV_MODE_MSK GENMASK(2, 0)
+#define AD7768_CONV_MODE(x) FIELD_PREP(AD7768_CONV_MODE_MSK, x)
+
+#define AD7768_RD_FLAG_MSK(x) (BIT(6) | ((x) & 0x3F))
+#define AD7768_WR_FLAG_MSK(x) ((x) & 0x3F)
+
+enum ad7768_conv_mode {
+ AD7768_CONTINUOUS,
+ AD7768_ONE_SHOT,
+ AD7768_SINGLE,
+ AD7768_PERIODIC,
+ AD7768_STANDBY
+};
+
+enum ad7768_pwrmode {
+ AD7768_ECO_MODE = 0,
+ AD7768_MED_MODE = 2,
+ AD7768_FAST_MODE = 3
+};
+
+enum ad7768_mclk_div {
+ AD7768_MCLK_DIV_16,
+ AD7768_MCLK_DIV_8,
+ AD7768_MCLK_DIV_4,
+ AD7768_MCLK_DIV_2
+};
+
+enum ad7768_dec_rate {
+ AD7768_DEC_RATE_32 = 0,
+ AD7768_DEC_RATE_64 = 1,
+ AD7768_DEC_RATE_128 = 2,
+ AD7768_DEC_RATE_256 = 3,
+ AD7768_DEC_RATE_512 = 4,
+ AD7768_DEC_RATE_1024 = 5,
+ AD7768_DEC_RATE_8 = 9,
+ AD7768_DEC_RATE_16 = 10
+};
+
+struct ad7768_clk_configuration {
+ enum ad7768_mclk_div mclk_div;
+ enum ad7768_dec_rate dec_rate;
+ unsigned int clk_div;
+ enum ad7768_pwrmode pwrmode;
+};
+
+static const struct ad7768_clk_configuration ad7768_clk_config[] = {
+ { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_8, 16, AD7768_FAST_MODE },
+ { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_16, 32, AD7768_FAST_MODE },
+ { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_32, 64, AD7768_FAST_MODE },
+ { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_64, 128, AD7768_FAST_MODE },
+ { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_128, 256, AD7768_FAST_MODE },
+ { AD7768_MCLK_DIV_4, AD7768_DEC_RATE_128, 512, AD7768_MED_MODE },
+ { AD7768_MCLK_DIV_4, AD7768_DEC_RATE_256, 1024, AD7768_MED_MODE },
+ { AD7768_MCLK_DIV_4, AD7768_DEC_RATE_512, 2048, AD7768_MED_MODE },
+ { AD7768_MCLK_DIV_4, AD7768_DEC_RATE_1024, 4096, AD7768_MED_MODE },
+ { AD7768_MCLK_DIV_8, AD7768_DEC_RATE_1024, 8192, AD7768_MED_MODE },
+ { AD7768_MCLK_DIV_16, AD7768_DEC_RATE_1024, 16384, AD7768_ECO_MODE },
+};
+
+static const struct iio_chan_spec ad7768_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .indexed = 1,
+ .channel = 0,
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 32,
+ .shift = 8,
+ .endianness = IIO_BE,
+ },
+ },
+};
+
+struct ad7768_state {
+ struct spi_device *spi;
+ struct regulator *vref;
+ struct mutex lock;
+ struct clk *mclk;
+ unsigned int mclk_freq;
+ unsigned int samp_freq;
+ struct completion completion;
+ struct iio_trigger *trig;
+ struct gpio_desc *gpio_sync_in;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ union {
+ __be32 d32;
+ u8 d8[2];
+ } data ____cacheline_aligned;
+};
+
+static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr,
+ unsigned int len)
+{
+ unsigned int shift;
+ int ret;
+
+ shift = 32 - (8 * len);
+ st->data.d8[0] = AD7768_RD_FLAG_MSK(addr);
+
+ ret = spi_write_then_read(st->spi, st->data.d8, 1,
+ &st->data.d32, len);
+ if (ret < 0)
+ return ret;
+
+ return (be32_to_cpu(st->data.d32) >> shift);
+}
+
+static int ad7768_spi_reg_write(struct ad7768_state *st,
+ unsigned int addr,
+ unsigned int val)
+{
+ st->data.d8[0] = AD7768_WR_FLAG_MSK(addr);
+ st->data.d8[1] = val & 0xFF;
+
+ return spi_write(st->spi, st->data.d8, 2);
+}
+
+static int ad7768_set_mode(struct ad7768_state *st,
+ enum ad7768_conv_mode mode)
+{
+ int regval;
+
+ regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1);
+ if (regval < 0)
+ return regval;
+
+ regval &= ~AD7768_CONV_MODE_MSK;
+ regval |= AD7768_CONV_MODE(mode);
+
+ return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval);
+}
+
+static int ad7768_scan_direct(struct iio_dev *indio_dev)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ int readval, ret;
+
+ reinit_completion(&st->completion);
+
+ ret = ad7768_set_mode(st, AD7768_ONE_SHOT);
+ if (ret < 0)
+ return ret;
+
+ ret = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(1000));
+ if (!ret)
+ return -ETIMEDOUT;
+
+ readval = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
+ if (readval < 0)
+ return readval;
+ /*
+ * Any SPI configuration of the AD7768-1 can only be
+ * performed in continuous conversion mode.
+ */
+ ret = ad7768_set_mode(st, AD7768_CONTINUOUS);
+ if (ret < 0)
+ return ret;
+
+ return readval;
+}
+
+static int ad7768_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&st->lock);
+ if (readval) {
+ ret = ad7768_spi_reg_read(st, reg, 1);
+ if (ret < 0)
+ goto err_unlock;
+ *readval = ret;
+ ret = 0;
+ } else {
+ ret = ad7768_spi_reg_write(st, reg, writeval);
+ }
+err_unlock:
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
+static int ad7768_set_dig_fil(struct ad7768_state *st,
+ enum ad7768_dec_rate dec_rate)
+{
+ unsigned int mode;
+ int ret;
+
+ if (dec_rate == AD7768_DEC_RATE_8 || dec_rate == AD7768_DEC_RATE_16)
+ mode = AD7768_DIG_FIL_FIL(dec_rate);
+ else
+ mode = AD7768_DIG_FIL_DEC_RATE(dec_rate);
+
+ ret = ad7768_spi_reg_write(st, AD7768_REG_DIGITAL_FILTER, mode);
+ if (ret < 0)
+ return ret;
+
+ /* A sync-in pulse is required every time the filter dec rate changes */
+ gpiod_set_value(st->gpio_sync_in, 1);
+ gpiod_set_value(st->gpio_sync_in, 0);
+
+ return 0;
+}
+
+static int ad7768_set_freq(struct ad7768_state *st,
+ unsigned int freq)
+{
+ unsigned int diff_new, diff_old, pwr_mode, i, idx;
+ int res, ret;
+
+ diff_old = U32_MAX;
+ idx = 0;
+
+ res = DIV_ROUND_CLOSEST(st->mclk_freq, freq);
+
+ /* Find the closest match for the desired sampling frequency */
+ for (i = 0; i < ARRAY_SIZE(ad7768_clk_config); i++) {
+ diff_new = abs(res - ad7768_clk_config[i].clk_div);
+ if (diff_new < diff_old) {
+ diff_old = diff_new;
+ idx = i;
+ }
+ }
+
+ /*
+ * Set both the mclk_div and pwrmode with a single write to the
+ * POWER_CLOCK register
+ */
+ pwr_mode = AD7768_PWR_MCLK_DIV(ad7768_clk_config[idx].mclk_div) |
+ AD7768_PWR_PWRMODE(ad7768_clk_config[idx].pwrmode);
+ ret = ad7768_spi_reg_write(st, AD7768_REG_POWER_CLOCK, pwr_mode);
+ if (ret < 0)
+ return ret;
+
+ ret = ad7768_set_dig_fil(st, ad7768_clk_config[idx].dec_rate);
+ if (ret < 0)
+ return ret;
+
+ st->samp_freq = DIV_ROUND_CLOSEST(st->mclk_freq,
+ ad7768_clk_config[idx].clk_div);
+
+ return 0;
+}
+
+static ssize_t ad7768_sampling_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad7768_state *st = iio_priv(indio_dev);
+ unsigned int freq;
+ int i, len = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ad7768_clk_config); i++) {
+ freq = DIV_ROUND_CLOSEST(st->mclk_freq,
+ ad7768_clk_config[i].clk_div);
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", freq);
+ }
+
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(ad7768_sampling_freq_avail);
+
+static int ad7768_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ int scale_uv, ret;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7768_scan_direct(indio_dev);
+ if (ret >= 0)
+ *val = ret;
+
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = regulator_get_voltage(st->vref);
+ if (scale_uv < 0)
+ return scale_uv;
+
+ *val = (scale_uv * 2) / 1000;
+ *val2 = chan->scan_type.realbits;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->samp_freq;
+
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int ad7768_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad7768_set_freq(st, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct attribute *ad7768_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group ad7768_group = {
+ .attrs = ad7768_attributes,
+};
+
+static const struct iio_info ad7768_info = {
+ .attrs = &ad7768_group,
+ .read_raw = &ad7768_read_raw,
+ .write_raw = &ad7768_write_raw,
+ .debugfs_reg_access = &ad7768_reg_access,
+};
+
+static int ad7768_setup(struct ad7768_state *st)
+{
+ int ret;
+
+ /*
+ * Two writes to the SPI_RESET[1:0] bits are required to initiate
+ * a software reset. The bits must first be set to 11, and then
+ * to 10. When the sequence is detected, the reset occurs.
+ * See the datasheet, page 70.
+ */
+ ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x3);
+ if (ret)
+ return ret;
+
+ ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2);
+ if (ret)
+ return ret;
+
+ st->gpio_sync_in = devm_gpiod_get(&st->spi->dev, "adi,sync-in",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->gpio_sync_in))
+ return PTR_ERR(st->gpio_sync_in);
+
+ /* Set the default sampling frequency to 32000 kSPS */
+ return ad7768_set_freq(st, 32000);
+}
+
+static irqreturn_t ad7768_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7768_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&st->lock);
+
+ ret = spi_read(st->spi, &st->data.d32, 3);
+ if (ret < 0)
+ goto err_unlock;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data.d32,
+ iio_get_time_ns(indio_dev));
+
+ iio_trigger_notify_done(indio_dev->trig);
+err_unlock:
+ mutex_unlock(&st->lock);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ad7768_interrupt(int irq, void *dev_id)
+{
+ struct iio_dev *indio_dev = dev_id;
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll(st->trig);
+ else
+ complete(&st->completion);
+
+ return IRQ_HANDLED;
+};
+
+static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ iio_triggered_buffer_postenable(indio_dev);
+ /*
+ * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter
+ * continuous read mode. Subsequent data reads do not require an
+ * initial 8-bit write to query the ADC_DATA register.
+ */
+ return ad7768_spi_reg_write(st, AD7768_REG_INTERFACE_FORMAT, 0x01);
+}
+
+static int ad7768_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ int ret;
+
+ /*
+ * To exit continuous read mode, perform a single read of the ADC_DATA
+ * reg (0x2C), which allows further configuration of the device.
+ */
+ ret = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
+ if (ret < 0)
+ return ret;
+
+ return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
+ .postenable = &ad7768_buffer_postenable,
+ .predisable = &ad7768_buffer_predisable,
+};
+
+static const struct iio_trigger_ops ad7768_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static void ad7768_regulator_disable(void *data)
+{
+ struct ad7768_state *st = data;
+
+ regulator_disable(st->vref);
+}
+
+static void ad7768_clk_disable(void *data)
+{
+ struct ad7768_state *st = data;
+
+ clk_disable_unprepare(st->mclk);
+}
+
+static int ad7768_probe(struct spi_device *spi)
+{
+ struct ad7768_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);
+ st->spi = spi;
+
+ st->vref = devm_regulator_get(&spi->dev, "vref");
+ if (IS_ERR(st->vref))
+ return PTR_ERR(st->vref);
+
+ ret = regulator_enable(st->vref);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable specified vref supply\n");
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&spi->dev, ad7768_regulator_disable, st);
+ if (ret)
+ return ret;
+
+ st->mclk = devm_clk_get(&spi->dev, "mclk");
+ if (IS_ERR(st->mclk))
+ return PTR_ERR(st->mclk);
+
+ ret = clk_prepare_enable(st->mclk);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, ad7768_clk_disable, st);
+ if (ret)
+ return ret;
+
+ st->mclk_freq = clk_get_rate(st->mclk);
+
+ spi_set_drvdata(spi, indio_dev);
+ mutex_init(&st->lock);
+
+ indio_dev->channels = ad7768_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7768_channels);
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad7768_info;
+ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
+
+ ret = ad7768_setup(st);
+ if (ret < 0) {
+ dev_err(&spi->dev, "AD7768 setup failed\n");
+ return ret;
+ }
+
+ st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7768_trigger_ops;
+ st->trig->dev.parent = &spi->dev;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ ret = devm_iio_trigger_register(&spi->dev, st->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ init_completion(&st->completion);
+
+ ret = devm_request_irq(&spi->dev, spi->irq,
+ &ad7768_interrupt,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7768_trigger_handler,
+ &ad7768_buffer_ops);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct spi_device_id ad7768_id_table[] = {
+ { "ad7768-1", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, ad7768_id_table);
+
+static const struct of_device_id ad7768_of_match[] = {
+ { .compatible = "adi,ad7768-1" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ad7768_of_match);
+
+static struct spi_driver ad7768_driver = {
+ .driver = {
+ .name = "ad7768-1",
+ .of_match_table = ad7768_of_match,
+ },
+ .probe = ad7768_probe,
+ .id_table = ad7768_id_table,
+};
+module_spi_driver(ad7768_driver);
+
+MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7768-1 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 031d568b4972..4e339cfd0c54 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -27,9 +27,18 @@
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
-#define AXP288_ADC_EN_MASK 0xF1
-#define AXP288_ADC_TS_PIN_GPADC 0xF2
-#define AXP288_ADC_TS_PIN_ON 0xF3
+/*
+ * This mask enables all ADCs except for the battery temp-sensor (TS), that is
+ * left as-is to avoid breaking charging on devices without a temp-sensor.
+ */
+#define AXP288_ADC_EN_MASK 0xF0
+#define AXP288_ADC_TS_ENABLE 0x01
+
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON (3 << 0)
enum axp288_adc_id {
AXP288_ADC_TS,
@@ -44,6 +53,7 @@ enum axp288_adc_id {
struct axp288_adc_info {
int irq;
struct regmap *regmap;
+ bool ts_enabled;
};
static const struct iio_chan_spec axp288_adc_channels[] = {
@@ -115,21 +125,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
return IIO_VAL_INT;
}
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
- unsigned long address)
+/*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ */
+static int axp288_adc_set_ts(struct axp288_adc_info *info,
+ unsigned int mode, unsigned long address)
{
int ret;
- /* channels other than GPADC do not need to switch TS pin */
+ /* No need to switch the current-source if the TS pin is disabled */
+ if (!info->ts_enabled)
+ return 0;
+
+ /* Channels other than GPADC do not need the current source */
if (address != AXP288_GP_ADC_H)
return 0;
- ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+ ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+ AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode);
if (ret)
return ret;
/* When switching to the GPADC pin give things some time to settle */
- if (mode == AXP288_ADC_TS_PIN_GPADC)
+ if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND)
usleep_range(6000, 10000);
return 0;
@@ -145,14 +167,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+ if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND,
chan->address)) {
dev_err(&indio_dev->dev, "GPADC mode\n");
ret = -EINVAL;
break;
}
ret = axp288_adc_read_channel(val, chan->address, info->regmap);
- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+ if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON,
chan->address))
dev_err(&indio_dev->dev, "TS pin restore\n");
break;
@@ -164,13 +186,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
return ret;
}
-static int axp288_adc_set_state(struct regmap *regmap)
+static int axp288_adc_initialize(struct axp288_adc_info *info)
{
- /* ADC should be always enabled for internal FG to function */
- if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
- return -EIO;
+ int ret, adc_enable_val;
+
+ /*
+ * Determine if the TS pin is enabled and set the TS current-source
+ * accordingly.
+ */
+ ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val);
+ if (ret)
+ return ret;
+
+ if (adc_enable_val & AXP288_ADC_TS_ENABLE) {
+ info->ts_enabled = true;
+ ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+ AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+ AXP288_ADC_TS_CURRENT_ON);
+ } else {
+ info->ts_enabled = false;
+ ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+ AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+ AXP288_ADC_TS_CURRENT_OFF);
+ }
+ if (ret)
+ return ret;
- return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+ /* Turn on the ADC for all channels except TS, leave TS as is */
+ return regmap_update_bits(info->regmap, AXP20X_ADC_EN1,
+ AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK);
}
static const struct iio_info axp288_adc_iio_info = {
@@ -200,7 +244,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
* Set ADC to enabled state at all time, including system suspend.
* otherwise internal fuel gauge functionality may be affected.
*/
- ret = axp288_adc_set_state(axp20x->regmap);
+ ret = axp288_adc_initialize(info);
if (ret) {
dev_err(&pdev->dev, "unable to enable ADC device\n");
return ret;
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index fa2d2b5767f3..1ca2c4d39f87 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -115,6 +115,7 @@
#define MAX_ADC_V2_CHANNELS 10
#define MAX_ADC_V1_CHANNELS 8
#define MAX_EXYNOS3250_ADC_CHANNELS 2
+#define MAX_EXYNOS4212_ADC_CHANNELS 4
#define MAX_S5PV210_ADC_CHANNELS 10
/* Bit definitions common for ADC_V1 and ADC_V2 */
@@ -271,6 +272,19 @@ static void exynos_adc_v1_start_conv(struct exynos_adc *info,
writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
}
+/* Exynos4212 and 4412 is like ADCv1 but with four channels only */
+static const struct exynos_adc_data exynos4212_adc_data = {
+ .num_channels = MAX_EXYNOS4212_ADC_CHANNELS,
+ .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
+ .needs_adc_phy = true,
+ .phy_offset = EXYNOS_ADCV1_PHY_OFFSET,
+
+ .init_hw = exynos_adc_v1_init_hw,
+ .exit_hw = exynos_adc_v1_exit_hw,
+ .clear_irq = exynos_adc_v1_clear_irq,
+ .start_conv = exynos_adc_v1_start_conv,
+};
+
static const struct exynos_adc_data exynos_adc_v1_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
@@ -493,6 +507,9 @@ static const struct of_device_id exynos_adc_match[] = {
.compatible = "samsung,s5pv210-adc",
.data = &exynos_adc_s5pv210_data,
}, {
+ .compatible = "samsung,exynos4212-adc",
+ .data = &exynos4212_adc_data,
+ }, {
.compatible = "samsung,exynos-adc-v1",
.data = &exynos_adc_v1_data,
}, {
@@ -929,7 +946,7 @@ static int exynos_adc_remove(struct platform_device *pdev)
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct exynos_adc *info = iio_priv(indio_dev);
- if (IS_REACHABLE(CONFIG_INPUT)) {
+ if (IS_REACHABLE(CONFIG_INPUT) && info->input) {
free_irq(info->tsirq, info);
input_unregister_device(info->input);
}
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
new file mode 100644
index 000000000000..6ee1673deb0d
--- /dev/null
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ADC driver for the Ingenic JZ47xx SoCs
+ * Copyright (c) 2019 Artur Rojek <contact@artur-rojek.eu>
+ *
+ * based on drivers/mfd/jz4740-adc.c
+ */
+
+#include <dt-bindings/iio/adc/ingenic,adc.h>
+#include <linux/clk.h>
+#include <linux/iio/iio.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#define JZ_ADC_REG_ENABLE 0x00
+#define JZ_ADC_REG_CFG 0x04
+#define JZ_ADC_REG_CTRL 0x08
+#define JZ_ADC_REG_STATUS 0x0c
+#define JZ_ADC_REG_ADTCH 0x18
+#define JZ_ADC_REG_ADBDAT 0x1c
+#define JZ_ADC_REG_ADSDAT 0x20
+
+#define JZ_ADC_REG_CFG_BAT_MD BIT(4)
+
+#define JZ_ADC_AUX_VREF 3300
+#define JZ_ADC_AUX_VREF_BITS 12
+#define JZ_ADC_BATTERY_LOW_VREF 2500
+#define JZ_ADC_BATTERY_LOW_VREF_BITS 12
+#define JZ4725B_ADC_BATTERY_HIGH_VREF 7500
+#define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10
+#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
+#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
+
+struct ingenic_adc_soc_data {
+ unsigned int battery_high_vref;
+ unsigned int battery_high_vref_bits;
+ const int *battery_raw_avail;
+ size_t battery_raw_avail_size;
+ const int *battery_scale_avail;
+ size_t battery_scale_avail_size;
+};
+
+struct ingenic_adc {
+ void __iomem *base;
+ struct clk *clk;
+ struct mutex lock;
+ const struct ingenic_adc_soc_data *soc_data;
+ bool low_vref_mode;
+};
+
+static void ingenic_adc_set_config(struct ingenic_adc *adc,
+ uint32_t mask,
+ uint32_t val)
+{
+ uint32_t cfg;
+
+ clk_enable(adc->clk);
+ mutex_lock(&adc->lock);
+
+ cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask;
+ cfg |= val;
+ writel(cfg, adc->base + JZ_ADC_REG_CFG);
+
+ mutex_unlock(&adc->lock);
+ clk_disable(adc->clk);
+}
+
+static void ingenic_adc_enable(struct ingenic_adc *adc,
+ int engine,
+ bool enabled)
+{
+ u8 val;
+
+ mutex_lock(&adc->lock);
+ val = readb(adc->base + JZ_ADC_REG_ENABLE);
+
+ if (enabled)
+ val |= BIT(engine);
+ else
+ val &= ~BIT(engine);
+
+ writeb(val, adc->base + JZ_ADC_REG_ENABLE);
+ mutex_unlock(&adc->lock);
+}
+
+static int ingenic_adc_capture(struct ingenic_adc *adc,
+ int engine)
+{
+ u8 val;
+ int ret;
+
+ ingenic_adc_enable(adc, engine, true);
+ ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
+ !(val & BIT(engine)), 250, 1000);
+ if (ret)
+ ingenic_adc_enable(adc, engine, false);
+
+ return ret;
+}
+
+static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long m)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+
+ switch (m) {
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->channel) {
+ case INGENIC_ADC_BATTERY:
+ if (val > JZ_ADC_BATTERY_LOW_VREF) {
+ ingenic_adc_set_config(adc,
+ JZ_ADC_REG_CFG_BAT_MD,
+ 0);
+ adc->low_vref_mode = false;
+ } else {
+ ingenic_adc_set_config(adc,
+ JZ_ADC_REG_CFG_BAT_MD,
+ JZ_ADC_REG_CFG_BAT_MD);
+ adc->low_vref_mode = true;
+ }
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const int jz4725b_adc_battery_raw_avail[] = {
+ 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
+};
+
+static const int jz4725b_adc_battery_scale_avail[] = {
+ JZ4725B_ADC_BATTERY_HIGH_VREF, JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
+ JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
+};
+
+static const int jz4740_adc_battery_raw_avail[] = {
+ 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
+};
+
+static const int jz4740_adc_battery_scale_avail[] = {
+ JZ4740_ADC_BATTERY_HIGH_VREF, JZ4740_ADC_BATTERY_HIGH_VREF_BITS,
+ JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
+};
+
+static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
+ .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
+ .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
+ .battery_raw_avail = jz4725b_adc_battery_raw_avail,
+ .battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
+ .battery_scale_avail = jz4725b_adc_battery_scale_avail,
+ .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+};
+
+static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
+ .battery_high_vref = JZ4740_ADC_BATTERY_HIGH_VREF,
+ .battery_high_vref_bits = JZ4740_ADC_BATTERY_HIGH_VREF_BITS,
+ .battery_raw_avail = jz4740_adc_battery_raw_avail,
+ .battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
+ .battery_scale_avail = jz4740_adc_battery_scale_avail,
+ .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+};
+
+static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals,
+ int *type,
+ int *length,
+ long m)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ *type = IIO_VAL_INT;
+ *length = adc->soc_data->battery_raw_avail_size;
+ *vals = adc->soc_data->battery_raw_avail;
+ return IIO_AVAIL_RANGE;
+ case IIO_CHAN_INFO_SCALE:
+ *type = IIO_VAL_FRACTIONAL_LOG2;
+ *length = adc->soc_data->battery_scale_avail_size;
+ *vals = adc->soc_data->battery_scale_avail;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ };
+}
+
+static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+ int ret;
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ clk_enable(adc->clk);
+ ret = ingenic_adc_capture(adc, chan->channel);
+ if (ret) {
+ clk_disable(adc->clk);
+ return ret;
+ }
+
+ switch (chan->channel) {
+ case INGENIC_ADC_AUX:
+ *val = readw(adc->base + JZ_ADC_REG_ADSDAT);
+ break;
+ case INGENIC_ADC_BATTERY:
+ *val = readw(adc->base + JZ_ADC_REG_ADBDAT);
+ break;
+ }
+
+ clk_disable(adc->clk);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->channel) {
+ case INGENIC_ADC_AUX:
+ *val = JZ_ADC_AUX_VREF;
+ *val2 = JZ_ADC_AUX_VREF_BITS;
+ break;
+ case INGENIC_ADC_BATTERY:
+ if (adc->low_vref_mode) {
+ *val = JZ_ADC_BATTERY_LOW_VREF;
+ *val2 = JZ_ADC_BATTERY_LOW_VREF_BITS;
+ } else {
+ *val = adc->soc_data->battery_high_vref;
+ *val2 = adc->soc_data->battery_high_vref_bits;
+ }
+ break;
+ }
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void ingenic_adc_clk_cleanup(void *data)
+{
+ clk_unprepare(data);
+}
+
+static const struct iio_info ingenic_adc_info = {
+ .write_raw = ingenic_adc_write_raw,
+ .read_raw = ingenic_adc_read_raw,
+ .read_avail = ingenic_adc_read_avail,
+};
+
+static const struct iio_chan_spec ingenic_channels[] = {
+ {
+ .extend_name = "aux",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX,
+ },
+ {
+ .extend_name = "battery",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_BATTERY,
+ },
+};
+
+static int ingenic_adc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *iio_dev;
+ struct ingenic_adc *adc;
+ struct resource *mem_base;
+ const struct ingenic_adc_soc_data *soc_data;
+ int ret;
+
+ soc_data = device_get_match_data(dev);
+ if (!soc_data)
+ return -EINVAL;
+
+ iio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
+ if (!iio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(iio_dev);
+ mutex_init(&adc->lock);
+ adc->soc_data = soc_data;
+
+ mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ adc->base = devm_ioremap_resource(dev, mem_base);
+ if (IS_ERR(adc->base)) {
+ dev_err(dev, "Unable to ioremap mmio resource\n");
+ return PTR_ERR(adc->base);
+ }
+
+ adc->clk = devm_clk_get(dev, "adc");
+ if (IS_ERR(adc->clk)) {
+ dev_err(dev, "Unable to get clock\n");
+ return PTR_ERR(adc->clk);
+ }
+
+ ret = clk_prepare_enable(adc->clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable clock\n");
+ return ret;
+ }
+
+ /* Put hardware in a known passive state. */
+ writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
+ writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+ clk_disable(adc->clk);
+
+ ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk);
+ if (ret) {
+ dev_err(dev, "Unable to add action\n");
+ return ret;
+ }
+
+ iio_dev->dev.parent = dev;
+ iio_dev->name = "jz-adc";
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->channels = ingenic_channels;
+ iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
+ iio_dev->info = &ingenic_adc_info;
+
+ ret = devm_iio_device_register(dev, iio_dev);
+ if (ret)
+ dev_err(dev, "Unable to register IIO device\n");
+
+ return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ingenic_adc_of_match[] = {
+ { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
+ { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
+#endif
+
+static struct platform_driver ingenic_adc_driver = {
+ .driver = {
+ .name = "ingenic-adc",
+ .of_match_table = of_match_ptr(ingenic_adc_of_match),
+ },
+ .probe = ingenic_adc_probe,
+};
+module_platform_driver(ingenic_adc_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c
index 20b36690fa4f..e361c1532a75 100644
--- a/drivers/iio/adc/lpc32xx_adc.c
+++ b/drivers/iio/adc/lpc32xx_adc.c
@@ -1,23 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* lpc32xx_adc.c - Support for ADC in LPC32XX
*
* 3-channel, 10-bit ADC
*
* Copyright (C) 2011, 2012 Roland Stigge <stigge@antcom.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 729becb2d3d9..f8600fbcdfe3 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/mfd/syscon.h>
#define MESON_SAR_ADC_REG0 0x00
#define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31)
@@ -174,6 +175,9 @@
#define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0)
#define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7)
+#define MESON_HHI_DPLL_TOP_0 0x318
+#define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9)
+
/* for use with IIO_VAL_INT_PLUS_MICRO */
#define MILLION 1000000
@@ -280,6 +284,7 @@ struct meson_sar_adc_priv {
struct completion done;
int calibbias;
int calibscale;
+ struct regmap *tsc_regmap;
bool temperature_sensor_calibrated;
u8 temperature_sensor_coefficient;
u16 temperature_sensor_adc_val;
@@ -727,6 +732,15 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
return ret;
}
+ priv->tsc_regmap =
+ syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node,
+ "amlogic,hhi-sysctrl");
+ if (IS_ERR(priv->tsc_regmap)) {
+ dev_err(indio_dev->dev.parent,
+ "failed to get amlogic,hhi-sysctrl regmap\n");
+ return PTR_ERR(priv->tsc_regmap);
+ }
+
read_len = MESON_SAR_ADC_EFUSE_BYTES;
buf = nvmem_cell_read(temperature_calib, &read_len);
if (IS_ERR(buf)) {
@@ -861,6 +875,22 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
priv->temperature_sensor_coefficient);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval);
+
+ if (priv->param->temperature_trimming_bits == 5) {
+ if (priv->temperature_sensor_coefficient & BIT(4))
+ regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4;
+ else
+ regval = 0;
+
+ /*
+ * bit [4] (the 5th bit when starting to count at 1)
+ * of the TSC is located in the HHI register area.
+ */
+ regmap_update_bits(priv->tsc_regmap,
+ MESON_HHI_DPLL_TOP_0,
+ MESON_HHI_DPLL_TOP_0_TSC_BIT4,
+ regval);
+ }
} else {
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
MESON_SAR_ADC_DELTA_10_TS_REVE1, 0);
@@ -1064,6 +1094,9 @@ static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = {
.bandgap_reg = MESON_SAR_ADC_DELTA_10,
.regmap_config = &meson_sar_adc_regmap_config_meson8,
.resolution = 10,
+ .temperature_trimming_bits = 5,
+ .temperature_multiplier = 10,
+ .temperature_divider = 32,
};
static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = {
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
new file mode 100644
index 000000000000..9e25bbec9c70
--- /dev/null
+++ b/drivers/iio/adc/npcm_adc.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 Nuvoton Technology corporation.
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/io.h>
+#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+struct npcm_adc {
+ bool int_status;
+ u32 adc_sample_hz;
+ struct device *dev;
+ void __iomem *regs;
+ struct clk *adc_clk;
+ wait_queue_head_t wq;
+ struct regulator *vref;
+ struct regmap *rst_regmap;
+};
+
+/* NPCM7xx reset module */
+#define NPCM7XX_IPSRST1_OFFSET 0x020
+#define NPCM7XX_IPSRST1_ADC_RST BIT(27)
+
+/* ADC registers */
+#define NPCM_ADCCON 0x00
+#define NPCM_ADCDATA 0x04
+
+/* ADCCON Register Bits */
+#define NPCM_ADCCON_ADC_INT_EN BIT(21)
+#define NPCM_ADCCON_REFSEL BIT(19)
+#define NPCM_ADCCON_ADC_INT_ST BIT(18)
+#define NPCM_ADCCON_ADC_EN BIT(17)
+#define NPCM_ADCCON_ADC_RST BIT(16)
+#define NPCM_ADCCON_ADC_CONV BIT(13)
+
+#define NPCM_ADCCON_CH_MASK GENMASK(27, 24)
+#define NPCM_ADCCON_CH(x) ((x) << 24)
+#define NPCM_ADCCON_DIV_SHIFT 1
+#define NPCM_ADCCON_DIV_MASK GENMASK(8, 1)
+#define NPCM_ADC_DATA_MASK(x) ((x) & GENMASK(9, 0))
+
+#define NPCM_ADC_ENABLE (NPCM_ADCCON_ADC_EN | NPCM_ADCCON_ADC_INT_EN)
+
+/* ADC General Definition */
+#define NPCM_RESOLUTION_BITS 10
+#define NPCM_INT_VREF_MV 2000
+
+#define NPCM_ADC_CHAN(ch) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = ch, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+}
+
+static const struct iio_chan_spec npcm_adc_iio_channels[] = {
+ NPCM_ADC_CHAN(0),
+ NPCM_ADC_CHAN(1),
+ NPCM_ADC_CHAN(2),
+ NPCM_ADC_CHAN(3),
+ NPCM_ADC_CHAN(4),
+ NPCM_ADC_CHAN(5),
+ NPCM_ADC_CHAN(6),
+ NPCM_ADC_CHAN(7),
+};
+
+static irqreturn_t npcm_adc_isr(int irq, void *data)
+{
+ u32 regtemp;
+ struct iio_dev *indio_dev = data;
+ struct npcm_adc *info = iio_priv(indio_dev);
+
+ regtemp = ioread32(info->regs + NPCM_ADCCON);
+ if (regtemp & NPCM_ADCCON_ADC_INT_ST) {
+ iowrite32(regtemp, info->regs + NPCM_ADCCON);
+ wake_up_interruptible(&info->wq);
+ info->int_status = true;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
+{
+ int ret;
+ u32 regtemp;
+
+ /* Select ADC channel */
+ regtemp = ioread32(info->regs + NPCM_ADCCON);
+ regtemp &= ~NPCM_ADCCON_CH_MASK;
+ info->int_status = false;
+ iowrite32(regtemp | NPCM_ADCCON_CH(channel) |
+ NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
+
+ ret = wait_event_interruptible_timeout(info->wq, info->int_status,
+ msecs_to_jiffies(10));
+ if (ret == 0) {
+ regtemp = ioread32(info->regs + NPCM_ADCCON);
+ if ((regtemp & NPCM_ADCCON_ADC_CONV) && info->rst_regmap) {
+ /* if conversion failed - reset ADC module */
+ regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET,
+ NPCM7XX_IPSRST1_ADC_RST);
+ msleep(100);
+ regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET,
+ 0x0);
+ msleep(100);
+
+ /* Enable ADC and start conversion module */
+ iowrite32(NPCM_ADC_ENABLE | NPCM_ADCCON_ADC_CONV,
+ info->regs + NPCM_ADCCON);
+ dev_err(info->dev, "RESET ADC Complete\n");
+ }
+ return -ETIMEDOUT;
+ }
+ if (ret < 0)
+ return ret;
+
+ *val = NPCM_ADC_DATA_MASK(ioread32(info->regs + NPCM_ADCDATA));
+
+ return 0;
+}
+
+static int npcm_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int ret;
+ int vref_uv;
+ struct npcm_adc *info = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+ ret = npcm_adc_read(info, val, chan->channel);
+ mutex_unlock(&indio_dev->mlock);
+ if (ret) {
+ dev_err(info->dev, "NPCM ADC read failed\n");
+ return ret;
+ }
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ if (info->vref) {
+ vref_uv = regulator_get_voltage(info->vref);
+ *val = vref_uv / 1000;
+ } else {
+ *val = NPCM_INT_VREF_MV;
+ }
+ *val2 = NPCM_RESOLUTION_BITS;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = info->adc_sample_hz;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct iio_info npcm_adc_iio_info = {
+ .read_raw = &npcm_adc_read_raw,
+};
+
+static const struct of_device_id npcm_adc_match[] = {
+ { .compatible = "nuvoton,npcm750-adc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, npcm_adc_match);
+
+static int npcm_adc_probe(struct platform_device *pdev)
+{
+ int ret;
+ int irq;
+ u32 div;
+ u32 reg_con;
+ struct resource *res;
+ struct npcm_adc *info;
+ struct iio_dev *indio_dev;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+ if (!indio_dev)
+ return -ENOMEM;
+ info = iio_priv(indio_dev);
+
+ info->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ info->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(info->regs))
+ return PTR_ERR(info->regs);
+
+ info->adc_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(info->adc_clk)) {
+ dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
+ return PTR_ERR(info->adc_clk);
+ }
+
+ /* calculate ADC clock sample rate */
+ reg_con = ioread32(info->regs + NPCM_ADCCON);
+ div = reg_con & NPCM_ADCCON_DIV_MASK;
+ div = div >> NPCM_ADCCON_DIV_SHIFT;
+ info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
+
+ if (of_device_is_compatible(np, "nuvoton,npcm750-adc")) {
+ info->rst_regmap = syscon_regmap_lookup_by_compatible
+ ("nuvoton,npcm750-rst");
+ if (IS_ERR(info->rst_regmap)) {
+ dev_err(&pdev->dev, "Failed to find nuvoton,npcm750-rst\n");
+ ret = PTR_ERR(info->rst_regmap);
+ goto err_disable_clk;
+ }
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
+ dev_err(dev, "failed getting interrupt resource\n");
+ ret = -EINVAL;
+ goto err_disable_clk;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0,
+ "NPCM_ADC", indio_dev);
+ if (ret < 0) {
+ dev_err(dev, "failed requesting interrupt\n");
+ goto err_disable_clk;
+ }
+
+ reg_con = ioread32(info->regs + NPCM_ADCCON);
+ info->vref = devm_regulator_get_optional(&pdev->dev, "vref");
+ if (!IS_ERR(info->vref)) {
+ ret = regulator_enable(info->vref);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't enable ADC reference voltage\n");
+ goto err_disable_clk;
+ }
+
+ iowrite32(reg_con & ~NPCM_ADCCON_REFSEL,
+ info->regs + NPCM_ADCCON);
+ } else {
+ /*
+ * Any error which is not ENODEV indicates the regulator
+ * has been specified and so is a failure case.
+ */
+ if (PTR_ERR(info->vref) != -ENODEV) {
+ ret = PTR_ERR(info->vref);
+ goto err_disable_clk;
+ }
+
+ /* Use internal reference */
+ iowrite32(reg_con | NPCM_ADCCON_REFSEL,
+ info->regs + NPCM_ADCCON);
+ }
+
+ init_waitqueue_head(&info->wq);
+
+ reg_con = ioread32(info->regs + NPCM_ADCCON);
+ reg_con |= NPCM_ADC_ENABLE;
+
+ /* Enable the ADC Module */
+ iowrite32(reg_con, info->regs + NPCM_ADCCON);
+
+ /* Start ADC conversion */
+ iowrite32(reg_con | NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
+
+ platform_set_drvdata(pdev, indio_dev);
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->info = &npcm_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = npcm_adc_iio_channels;
+ indio_dev->num_channels = ARRAY_SIZE(npcm_adc_iio_channels);
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't register the device.\n");
+ goto err_iio_register;
+ }
+
+ pr_info("NPCM ADC driver probed\n");
+
+ return 0;
+
+err_iio_register:
+ iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
+ if (!IS_ERR(info->vref))
+ regulator_disable(info->vref);
+err_disable_clk:
+ clk_disable_unprepare(info->adc_clk);
+
+ return ret;
+}
+
+static int npcm_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct npcm_adc *info = iio_priv(indio_dev);
+ u32 regtemp;
+
+ iio_device_unregister(indio_dev);
+
+ regtemp = ioread32(info->regs + NPCM_ADCCON);
+ iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
+ if (!IS_ERR(info->vref))
+ regulator_disable(info->vref);
+ clk_disable_unprepare(info->adc_clk);
+
+ return 0;
+}
+
+static struct platform_driver npcm_adc_driver = {
+ .probe = npcm_adc_probe,
+ .remove = npcm_adc_remove,
+ .driver = {
+ .name = "npcm_adc",
+ .of_match_table = npcm_adc_match,
+ },
+};
+
+module_platform_driver(npcm_adc_driver);
+
+MODULE_DESCRIPTION("Nuvoton NPCM ADC Driver");
+MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index c30c002f1fef..4735f8a1ca9d 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -423,18 +423,14 @@ static irqreturn_t pm8xxx_eoc_irq(int irq, void *d)
static struct pm8xxx_chan_info *
pm8xxx_get_channel(struct pm8xxx_xoadc *adc, u8 chan)
{
- struct pm8xxx_chan_info *ch;
int i;
for (i = 0; i < adc->nchans; i++) {
- ch = &adc->chans[i];
+ struct pm8xxx_chan_info *ch = &adc->chans[i];
if (ch->hwchan->amux_channel == chan)
- break;
+ return ch;
}
- if (i == adc->nchans)
- return NULL;
-
- return ch;
+ return NULL;
}
static int pm8xxx_read_channel_rsv(struct pm8xxx_xoadc *adc,
diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c
new file mode 100644
index 000000000000..53f17e4f2f23
--- /dev/null
+++ b/drivers/iio/adc/ti-ads124s08.c
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: GPL-2.0
+/* TI ADS124S0X chip family driver
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/sysfs.h>
+
+/* Commands */
+#define ADS124S08_CMD_NOP 0x00
+#define ADS124S08_CMD_WAKEUP 0x02
+#define ADS124S08_CMD_PWRDWN 0x04
+#define ADS124S08_CMD_RESET 0x06
+#define ADS124S08_CMD_START 0x08
+#define ADS124S08_CMD_STOP 0x0a
+#define ADS124S08_CMD_SYOCAL 0x16
+#define ADS124S08_CMD_SYGCAL 0x17
+#define ADS124S08_CMD_SFOCAL 0x19
+#define ADS124S08_CMD_RDATA 0x12
+#define ADS124S08_CMD_RREG 0x20
+#define ADS124S08_CMD_WREG 0x40
+
+/* Registers */
+#define ADS124S08_ID_REG 0x00
+#define ADS124S08_STATUS 0x01
+#define ADS124S08_INPUT_MUX 0x02
+#define ADS124S08_PGA 0x03
+#define ADS124S08_DATA_RATE 0x04
+#define ADS124S08_REF 0x05
+#define ADS124S08_IDACMAG 0x06
+#define ADS124S08_IDACMUX 0x07
+#define ADS124S08_VBIAS 0x08
+#define ADS124S08_SYS 0x09
+#define ADS124S08_OFCAL0 0x0a
+#define ADS124S08_OFCAL1 0x0b
+#define ADS124S08_OFCAL2 0x0c
+#define ADS124S08_FSCAL0 0x0d
+#define ADS124S08_FSCAL1 0x0e
+#define ADS124S08_FSCAL2 0x0f
+#define ADS124S08_GPIODAT 0x10
+#define ADS124S08_GPIOCON 0x11
+
+/* ADS124S0x common channels */
+#define ADS124S08_AIN0 0x00
+#define ADS124S08_AIN1 0x01
+#define ADS124S08_AIN2 0x02
+#define ADS124S08_AIN3 0x03
+#define ADS124S08_AIN4 0x04
+#define ADS124S08_AIN5 0x05
+#define ADS124S08_AINCOM 0x0c
+/* ADS124S08 only channels */
+#define ADS124S08_AIN6 0x06
+#define ADS124S08_AIN7 0x07
+#define ADS124S08_AIN8 0x08
+#define ADS124S08_AIN9 0x09
+#define ADS124S08_AIN10 0x0a
+#define ADS124S08_AIN11 0x0b
+#define ADS124S08_MAX_CHANNELS 12
+
+#define ADS124S08_POS_MUX_SHIFT 0x04
+#define ADS124S08_INT_REF 0x09
+
+#define ADS124S08_START_REG_MASK 0x1f
+#define ADS124S08_NUM_BYTES_MASK 0x1f
+
+#define ADS124S08_START_CONV 0x01
+#define ADS124S08_STOP_CONV 0x00
+
+enum ads124s_id {
+ ADS124S08_ID,
+ ADS124S06_ID,
+};
+
+struct ads124s_chip_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+};
+
+struct ads124s_private {
+ const struct ads124s_chip_info *chip_info;
+ struct gpio_desc *reset_gpio;
+ struct spi_device *spi;
+ struct mutex lock;
+ u8 data[5] ____cacheline_aligned;
+};
+
+#define ADS124S08_CHAN(index) \
+{ \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 32, \
+ .storagebits = 32, \
+ }, \
+}
+
+static const struct iio_chan_spec ads124s06_channels[] = {
+ ADS124S08_CHAN(0),
+ ADS124S08_CHAN(1),
+ ADS124S08_CHAN(2),
+ ADS124S08_CHAN(3),
+ ADS124S08_CHAN(4),
+ ADS124S08_CHAN(5),
+};
+
+static const struct iio_chan_spec ads124s08_channels[] = {
+ ADS124S08_CHAN(0),
+ ADS124S08_CHAN(1),
+ ADS124S08_CHAN(2),
+ ADS124S08_CHAN(3),
+ ADS124S08_CHAN(4),
+ ADS124S08_CHAN(5),
+ ADS124S08_CHAN(6),
+ ADS124S08_CHAN(7),
+ ADS124S08_CHAN(8),
+ ADS124S08_CHAN(9),
+ ADS124S08_CHAN(10),
+ ADS124S08_CHAN(11),
+};
+
+static const struct ads124s_chip_info ads124s_chip_info_tbl[] = {
+ [ADS124S08_ID] = {
+ .channels = ads124s08_channels,
+ .num_channels = ARRAY_SIZE(ads124s08_channels),
+ },
+ [ADS124S06_ID] = {
+ .channels = ads124s06_channels,
+ .num_channels = ARRAY_SIZE(ads124s06_channels),
+ },
+};
+
+static int ads124s_write_cmd(struct iio_dev *indio_dev, u8 command)
+{
+ struct ads124s_private *priv = iio_priv(indio_dev);
+
+ priv->data[0] = command;
+
+ return spi_write(priv->spi, &priv->data[0], 1);
+}
+
+static int ads124s_write_reg(struct iio_dev *indio_dev, u8 reg, u8 data)
+{
+ struct ads124s_private *priv = iio_priv(indio_dev);
+
+ priv->data[0] = ADS124S08_CMD_WREG | reg;
+ priv->data[1] = 0x0;
+ priv->data[2] = data;
+
+ return spi_write(priv->spi, &priv->data[0], 3);
+}
+
+static int ads124s_reset(struct iio_dev *indio_dev)
+{
+ struct ads124s_private *priv = iio_priv(indio_dev);
+
+ if (priv->reset_gpio) {
+ gpiod_set_value(priv->reset_gpio, 0);
+ udelay(200);
+ gpiod_set_value(priv->reset_gpio, 1);
+ } else {
+ return ads124s_write_cmd(indio_dev, ADS124S08_CMD_RESET);
+ }
+
+ return 0;
+};
+
+static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan)
+{
+ struct ads124s_private *priv = iio_priv(indio_dev);
+ int ret;
+ u32 tmp;
+ struct spi_transfer t[] = {
+ {
+ .tx_buf = &priv->data[0],
+ .len = 4,
+ .cs_change = 1,
+ }, {
+ .tx_buf = &priv->data[1],
+ .rx_buf = &priv->data[1],
+ .len = 4,
+ },
+ };
+
+ priv->data[0] = ADS124S08_CMD_RDATA;
+ memset(&priv->data[1], ADS124S08_CMD_NOP, sizeof(priv->data));
+
+ ret = spi_sync_transfer(priv->spi, t, ARRAY_SIZE(t));
+ if (ret < 0)
+ return ret;
+
+ tmp = priv->data[2] << 16 | priv->data[3] << 8 | priv->data[4];
+
+ return tmp;
+}
+
+static int ads124s_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long m)
+{
+ struct ads124s_private *priv = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&priv->lock);
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX,
+ chan->channel);
+ if (ret) {
+ dev_err(&priv->spi->dev, "Set ADC CH failed\n");
+ goto out;
+ }
+
+ ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV);
+ if (ret) {
+ dev_err(&priv->spi->dev, "Start conversions failed\n");
+ goto out;
+ }
+
+ ret = ads124s_read(indio_dev, chan->channel);
+ if (ret < 0) {
+ dev_err(&priv->spi->dev, "Read ADC failed\n");
+ goto out;
+ }
+
+ *val = ret;
+
+ ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV);
+ if (ret) {
+ dev_err(&priv->spi->dev, "Stop conversions failed\n");
+ goto out;
+ }
+
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
+static const struct iio_info ads124s_info = {
+ .read_raw = &ads124s_read_raw,
+};
+
+static irqreturn_t ads124s_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ads124s_private *priv = iio_priv(indio_dev);
+ u32 buffer[ADS124S08_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
+ int scan_index, j = 0;
+ int ret;
+
+ for_each_set_bit(scan_index, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX,
+ scan_index);
+ if (ret)
+ dev_err(&priv->spi->dev, "Set ADC CH failed\n");
+
+ ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV);
+ if (ret)
+ dev_err(&priv->spi->dev, "Start ADC conversions failed\n");
+
+ buffer[j] = ads124s_read(indio_dev, scan_index);
+ ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV);
+ if (ret)
+ dev_err(&priv->spi->dev, "Stop ADC conversions failed\n");
+
+ j++;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+ pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int ads124s_probe(struct spi_device *spi)
+{
+ struct ads124s_private *ads124s_priv;
+ struct iio_dev *indio_dev;
+ const struct spi_device_id *spi_id = spi_get_device_id(spi);
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*ads124s_priv));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ ads124s_priv = iio_priv(indio_dev);
+
+ ads124s_priv->reset_gpio = devm_gpiod_get_optional(&spi->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ads124s_priv->reset_gpio))
+ dev_info(&spi->dev, "Reset GPIO not defined\n");
+
+ ads124s_priv->chip_info = &ads124s_chip_info_tbl[spi_id->driver_data];
+
+ spi_set_drvdata(spi, indio_dev);
+
+ ads124s_priv->spi = spi;
+
+ indio_dev->name = spi_id->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->dev.of_node = spi->dev.of_node;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ads124s_priv->chip_info->channels;
+ indio_dev->num_channels = ads124s_priv->chip_info->num_channels;
+ indio_dev->info = &ads124s_info;
+
+ mutex_init(&ads124s_priv->lock);
+
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
+ ads124s_trigger_handler, NULL);
+ if (ret) {
+ dev_err(&spi->dev, "iio triggered buffer setup failed\n");
+ return ret;
+ }
+
+ ads124s_reset(indio_dev);
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct spi_device_id ads124s_id[] = {
+ { "ads124s06", ADS124S06_ID },
+ { "ads124s08", ADS124S08_ID },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ads124s_id);
+
+static const struct of_device_id ads124s_of_table[] = {
+ { .compatible = "ti,ads124s06" },
+ { .compatible = "ti,ads124s08" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ads124s_of_table);
+
+static struct spi_driver ads124s_driver = {
+ .driver = {
+ .name = "ads124s08",
+ .of_match_table = ads124s_of_table,
+ },
+ .probe = ads124s_probe,
+ .id_table = ads124s_id,
+};
+module_spi_driver(ads124s_driver);
+
+MODULE_AUTHOR("Dan Murphy <dmuprhy@ti.com>");
+MODULE_DESCRIPTION("TI TI_ADS12S0X ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c
index 184d686ebd99..8b4568edd5cb 100644
--- a/drivers/iio/adc/ti-ads8688.c
+++ b/drivers/iio/adc/ti-ads8688.c
@@ -41,6 +41,7 @@
#define ADS8688_VREF_MV 4096
#define ADS8688_REALBITS 16
+#define ADS8688_MAX_CHANNELS 8
/*
* enum ads8688_range - ADS8688 reference voltage range
@@ -385,7 +386,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
- u16 buffer[8];
+ u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
int i, j = 0;
for (i = 0; i < indio_dev->masklength; i++) {
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index cafb1dcadc48..9d984f2a8ba7 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -142,7 +142,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
stepconfig |= STEPCONFIG_MODE_SWCNT;
tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
- stepconfig | STEPCONFIG_INP(chan));
+ stepconfig | STEPCONFIG_INP(chan) |
+ STEPCONFIG_INM_ADCREFM |
+ STEPCONFIG_RFP_VREFP |
+ STEPCONFIG_RFM_VREFN);
if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 3f6be5ac049a..b13c61539d46 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1273,8 +1273,10 @@ static int xadc_probe(struct platform_device *pdev)
xadc->threshold[i] = 0xffff;
else
xadc->threshold[i] = 0;
- xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
+ ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
xadc->threshold[i]);
+ if (ret)
+ goto err_free_irq;
}
/* Go to non-buffered mode */
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index b8e005be4f87..d5d146e9e372 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -61,6 +61,27 @@ config IAQCORE
iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds)
sensors
+config PMS7003
+ tristate "Plantower PMS7003 particulate matter sensor"
+ depends on SERIAL_DEV_BUS
+ help
+ Say Y here to build support for the Plantower PMS7003 particulate
+ matter sensor.
+
+ To compile this driver as a module, choose M here: the module will
+ be called pms7003.
+
+config SPS30
+ tristate "SPS30 particulate matter sensor"
+ depends on I2C
+ select CRC8
+ help
+ Say Y here to build support for the Sensirion SPS30 particulate
+ matter sensor.
+
+ To compile this driver as a module, choose M here: the module will
+ be called sps30.
+
config VZ89X
tristate "SGX Sensortech MiCS VZ89X VOC sensor"
depends on I2C
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
index 2f4c4ba4d781..f5d1365acb49 100644
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -9,4 +9,7 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o
obj-$(CONFIG_BME680_SPI) += bme680_spi.o
obj-$(CONFIG_CCS811) += ccs811.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
+obj-$(CONFIG_PMS7003) += pms7003.o
+obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o
+obj-$(CONFIG_SPS30) += sps30.o
obj-$(CONFIG_VZ89X) += vz89x.o
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
index a406ad31b096..3a20cb5d9bff 100644
--- a/drivers/iio/chemical/atlas-ph-sensor.c
+++ b/drivers/iio/chemical/atlas-ph-sensor.c
@@ -444,9 +444,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_TEMP:
- *val = 1; /* 0.01 */
- *val2 = 100;
- break;
+ *val = 10;
+ return IIO_VAL_INT;
case IIO_PH:
*val = 1; /* 0.001 */
*val2 = 1000;
@@ -477,7 +476,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask)
{
struct atlas_data *data = iio_priv(indio_dev);
- __be32 reg = cpu_to_be32(val);
+ __be32 reg = cpu_to_be32(val / 10);
if (val2 != 0 || val < 0 || val > 20000)
return -EINVAL;
diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c
index 06d4be539d2e..b2f805b6b36a 100644
--- a/drivers/iio/chemical/bme680_i2c.c
+++ b/drivers/iio/chemical/bme680_i2c.c
@@ -70,10 +70,17 @@ static const struct acpi_device_id bme680_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, bme680_acpi_match);
+static const struct of_device_id bme680_of_i2c_match[] = {
+ { .compatible = "bosch,bme680", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bme680_of_i2c_match);
+
static struct i2c_driver bme680_i2c_driver = {
.driver = {
.name = "bme680_i2c",
.acpi_match_table = ACPI_PTR(bme680_acpi_match),
+ .of_match_table = bme680_of_i2c_match,
},
.probe = bme680_i2c_probe,
.id_table = bme680_i2c_id,
diff --git a/drivers/iio/chemical/bme680_spi.c b/drivers/iio/chemical/bme680_spi.c
index c9fb05e8d0b9..d0b7bdd3f066 100644
--- a/drivers/iio/chemical/bme680_spi.c
+++ b/drivers/iio/chemical/bme680_spi.c
@@ -6,6 +6,7 @@
*/
#include <linux/acpi.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
@@ -110,10 +111,17 @@ static const struct acpi_device_id bme680_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, bme680_acpi_match);
+static const struct of_device_id bme680_of_spi_match[] = {
+ { .compatible = "bosch,bme680", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bme680_of_spi_match);
+
static struct spi_driver bme680_spi_driver = {
.driver = {
.name = "bme680_spi",
.acpi_match_table = ACPI_PTR(bme680_acpi_match),
+ .of_match_table = bme680_of_spi_match,
},
.probe = bme680_spi_probe,
.id_table = bme680_spi_id,
diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c
new file mode 100644
index 000000000000..db8e7b2327b3
--- /dev/null
+++ b/drivers/iio/chemical/pms7003.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Plantower PMS7003 particulate matter sensor driver
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
+ */
+
+#include <asm/unaligned.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/serdev.h>
+
+#define PMS7003_DRIVER_NAME "pms7003"
+
+#define PMS7003_MAGIC 0x424d
+/* last 2 data bytes hold frame checksum */
+#define PMS7003_MAX_DATA_LENGTH 28
+#define PMS7003_CHECKSUM_LENGTH 2
+#define PMS7003_PM10_OFFSET 10
+#define PMS7003_PM2P5_OFFSET 8
+#define PMS7003_PM1_OFFSET 6
+
+#define PMS7003_TIMEOUT msecs_to_jiffies(6000)
+#define PMS7003_CMD_LENGTH 7
+#define PMS7003_PM_MAX 1000
+#define PMS7003_PM_MIN 0
+
+enum {
+ PM1,
+ PM2P5,
+ PM10,
+};
+
+enum pms7003_cmd {
+ CMD_WAKEUP,
+ CMD_ENTER_PASSIVE_MODE,
+ CMD_READ_PASSIVE,
+ CMD_SLEEP,
+};
+
+/*
+ * commands have following format:
+ *
+ * +------+------+-----+------+-----+-----------+-----------+
+ * | 0x42 | 0x4d | cmd | 0x00 | arg | cksum msb | cksum lsb |
+ * +------+------+-----+------+-----+-----------+-----------+
+ */
+static const u8 pms7003_cmd_tbl[][PMS7003_CMD_LENGTH] = {
+ [CMD_WAKEUP] = { 0x42, 0x4d, 0xe4, 0x00, 0x01, 0x01, 0x74 },
+ [CMD_ENTER_PASSIVE_MODE] = { 0x42, 0x4d, 0xe1, 0x00, 0x00, 0x01, 0x70 },
+ [CMD_READ_PASSIVE] = { 0x42, 0x4d, 0xe2, 0x00, 0x00, 0x01, 0x71 },
+ [CMD_SLEEP] = { 0x42, 0x4d, 0xe4, 0x00, 0x00, 0x01, 0x73 },
+};
+
+struct pms7003_frame {
+ u8 data[PMS7003_MAX_DATA_LENGTH];
+ u16 expected_length;
+ u16 length;
+};
+
+struct pms7003_state {
+ struct serdev_device *serdev;
+ struct pms7003_frame frame;
+ struct completion frame_ready;
+ struct mutex lock; /* must be held whenever state gets touched */
+};
+
+static int pms7003_do_cmd(struct pms7003_state *state, enum pms7003_cmd cmd)
+{
+ int ret;
+
+ ret = serdev_device_write(state->serdev, pms7003_cmd_tbl[cmd],
+ PMS7003_CMD_LENGTH, PMS7003_TIMEOUT);
+ if (ret < PMS7003_CMD_LENGTH)
+ return ret < 0 ? ret : -EIO;
+
+ ret = wait_for_completion_interruptible_timeout(&state->frame_ready,
+ PMS7003_TIMEOUT);
+ if (!ret)
+ ret = -ETIMEDOUT;
+
+ return ret < 0 ? ret : 0;
+}
+
+static u16 pms7003_get_pm(const u8 *data)
+{
+ return clamp_val(get_unaligned_be16(data),
+ PMS7003_PM_MIN, PMS7003_PM_MAX);
+}
+
+static irqreturn_t pms7003_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct pms7003_state *state = iio_priv(indio_dev);
+ struct pms7003_frame *frame = &state->frame;
+ u16 data[3 + 1 + 4]; /* PM1, PM2P5, PM10, padding, timestamp */
+ int ret;
+
+ mutex_lock(&state->lock);
+ ret = pms7003_do_cmd(state, CMD_READ_PASSIVE);
+ if (ret) {
+ mutex_unlock(&state->lock);
+ goto err;
+ }
+
+ data[PM1] = pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
+ data[PM2P5] = pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
+ data[PM10] = pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
+ mutex_unlock(&state->lock);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int pms7003_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct pms7003_state *state = iio_priv(indio_dev);
+ struct pms7003_frame *frame = &state->frame;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_MASSCONCENTRATION:
+ mutex_lock(&state->lock);
+ ret = pms7003_do_cmd(state, CMD_READ_PASSIVE);
+ if (ret) {
+ mutex_unlock(&state->lock);
+ return ret;
+ }
+
+ *val = pms7003_get_pm(frame->data + chan->address);
+ mutex_unlock(&state->lock);
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info pms7003_info = {
+ .read_raw = pms7003_read_raw,
+};
+
+#define PMS7003_CHAN(_index, _mod, _addr) { \
+ .type = IIO_MASSCONCENTRATION, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_ ## _mod, \
+ .address = _addr, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 10, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+static const struct iio_chan_spec pms7003_channels[] = {
+ PMS7003_CHAN(0, PM1, PMS7003_PM1_OFFSET),
+ PMS7003_CHAN(1, PM2P5, PMS7003_PM2P5_OFFSET),
+ PMS7003_CHAN(2, PM10, PMS7003_PM10_OFFSET),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static u16 pms7003_calc_checksum(struct pms7003_frame *frame)
+{
+ u16 checksum = (PMS7003_MAGIC >> 8) + (u8)(PMS7003_MAGIC & 0xff) +
+ (frame->length >> 8) + (u8)frame->length;
+ int i;
+
+ for (i = 0; i < frame->length - PMS7003_CHECKSUM_LENGTH; i++)
+ checksum += frame->data[i];
+
+ return checksum;
+}
+
+static bool pms7003_frame_is_okay(struct pms7003_frame *frame)
+{
+ int offset = frame->length - PMS7003_CHECKSUM_LENGTH;
+ u16 checksum = get_unaligned_be16(frame->data + offset);
+
+ return checksum == pms7003_calc_checksum(frame);
+}
+
+static int pms7003_receive_buf(struct serdev_device *serdev,
+ const unsigned char *buf, size_t size)
+{
+ struct iio_dev *indio_dev = serdev_device_get_drvdata(serdev);
+ struct pms7003_state *state = iio_priv(indio_dev);
+ struct pms7003_frame *frame = &state->frame;
+ int num;
+
+ if (!frame->expected_length) {
+ u16 magic;
+
+ /* wait for SOF and data length */
+ if (size < 4)
+ return 0;
+
+ magic = get_unaligned_be16(buf);
+ if (magic != PMS7003_MAGIC)
+ return 2;
+
+ num = get_unaligned_be16(buf + 2);
+ if (num <= PMS7003_MAX_DATA_LENGTH) {
+ frame->expected_length = num;
+ frame->length = 0;
+ }
+
+ return 4;
+ }
+
+ num = min(size, (size_t)(frame->expected_length - frame->length));
+ memcpy(frame->data + frame->length, buf, num);
+ frame->length += num;
+
+ if (frame->length == frame->expected_length) {
+ if (pms7003_frame_is_okay(frame))
+ complete(&state->frame_ready);
+
+ frame->expected_length = 0;
+ }
+
+ return num;
+}
+
+static const struct serdev_device_ops pms7003_serdev_ops = {
+ .receive_buf = pms7003_receive_buf,
+ .write_wakeup = serdev_device_write_wakeup,
+};
+
+static void pms7003_stop(void *data)
+{
+ struct pms7003_state *state = data;
+
+ pms7003_do_cmd(state, CMD_SLEEP);
+}
+
+static const unsigned long pms7003_scan_masks[] = { 0x07, 0x00 };
+
+static int pms7003_probe(struct serdev_device *serdev)
+{
+ struct pms7003_state *state;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&serdev->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+ serdev_device_set_drvdata(serdev, indio_dev);
+ state->serdev = serdev;
+ indio_dev->dev.parent = &serdev->dev;
+ indio_dev->info = &pms7003_info;
+ indio_dev->name = PMS7003_DRIVER_NAME;
+ indio_dev->channels = pms7003_channels,
+ indio_dev->num_channels = ARRAY_SIZE(pms7003_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->available_scan_masks = pms7003_scan_masks;
+
+ mutex_init(&state->lock);
+ init_completion(&state->frame_ready);
+
+ serdev_device_set_client_ops(serdev, &pms7003_serdev_ops);
+ ret = devm_serdev_device_open(&serdev->dev, serdev);
+ if (ret)
+ return ret;
+
+ serdev_device_set_baudrate(serdev, 9600);
+ serdev_device_set_flow_control(serdev, false);
+
+ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+ if (ret)
+ return ret;
+
+ ret = pms7003_do_cmd(state, CMD_WAKEUP);
+ if (ret) {
+ dev_err(&serdev->dev, "failed to wakeup sensor\n");
+ return ret;
+ }
+
+ ret = pms7003_do_cmd(state, CMD_ENTER_PASSIVE_MODE);
+ if (ret) {
+ dev_err(&serdev->dev, "failed to enter passive mode\n");
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&serdev->dev, pms7003_stop, state);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&serdev->dev, indio_dev, NULL,
+ pms7003_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&serdev->dev, indio_dev);
+}
+
+static const struct of_device_id pms7003_of_match[] = {
+ { .compatible = "plantower,pms7003" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pms7003_of_match);
+
+static struct serdev_device_driver pms7003_driver = {
+ .driver = {
+ .name = PMS7003_DRIVER_NAME,
+ .of_match_table = pms7003_of_match,
+ },
+ .probe = pms7003_probe,
+};
+module_serdev_device_driver(pms7003_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("Plantower PMS7003 particulate matter sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c
new file mode 100644
index 000000000000..8cc8fe5e356d
--- /dev/null
+++ b/drivers/iio/chemical/sgp30.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sgp30.c - Support for Sensirion SGP Gas Sensors
+ *
+ * Copyright (C) 2018 Andreas Brauchli <andreas.brauchli@sensirion.com>
+ *
+ * I2C slave address: 0x58
+ *
+ * Datasheets:
+ * https://www.sensirion.com/file/datasheet_sgp30
+ * https://www.sensirion.com/file/datasheet_sgpc3
+ *
+ * TODO:
+ * - baseline support
+ * - humidity compensation
+ * - power mode switching (SGPC3)
+ */
+
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define SGP_WORD_LEN 2
+#define SGP_CRC8_POLYNOMIAL 0x31
+#define SGP_CRC8_INIT 0xff
+#define SGP_CRC8_LEN 1
+#define SGP_CMD(cmd_word) cpu_to_be16(cmd_word)
+#define SGP_CMD_DURATION_US 12000
+#define SGP_MEASUREMENT_DURATION_US 50000
+#define SGP_CMD_LEN SGP_WORD_LEN
+#define SGP_CMD_MAX_BUF_SIZE (SGP_CMD_LEN + 2 * SGP_WORD_LEN)
+#define SGP_MEASUREMENT_LEN 2
+#define SGP30_MEASURE_INTERVAL_HZ 1
+#define SGPC3_MEASURE_INTERVAL_HZ 2
+#define SGP_VERS_PRODUCT(data) ((((data)->feature_set) & 0xf000) >> 12)
+#define SGP_VERS_RESERVED(data) ((((data)->feature_set) & 0x0800) >> 11)
+#define SGP_VERS_GEN(data) ((((data)->feature_set) & 0x0600) >> 9)
+#define SGP_VERS_ENG_BIT(data) ((((data)->feature_set) & 0x0100) >> 8)
+#define SGP_VERS_MAJOR(data) ((((data)->feature_set) & 0x00e0) >> 5)
+#define SGP_VERS_MINOR(data) (((data)->feature_set) & 0x001f)
+
+DECLARE_CRC8_TABLE(sgp_crc8_table);
+
+enum sgp_product_id {
+ SGP30 = 0,
+ SGPC3,
+};
+
+enum sgp30_channel_idx {
+ SGP30_IAQ_TVOC_IDX = 0,
+ SGP30_IAQ_CO2EQ_IDX,
+ SGP30_SIG_ETOH_IDX,
+ SGP30_SIG_H2_IDX,
+};
+
+enum sgpc3_channel_idx {
+ SGPC3_IAQ_TVOC_IDX = 10,
+ SGPC3_SIG_ETOH_IDX,
+};
+
+enum sgp_cmd {
+ SGP_CMD_IAQ_INIT = SGP_CMD(0x2003),
+ SGP_CMD_IAQ_MEASURE = SGP_CMD(0x2008),
+ SGP_CMD_GET_FEATURE_SET = SGP_CMD(0x202f),
+ SGP_CMD_GET_SERIAL_ID = SGP_CMD(0x3682),
+
+ SGP30_CMD_MEASURE_SIGNAL = SGP_CMD(0x2050),
+
+ SGPC3_CMD_MEASURE_RAW = SGP_CMD(0x2046),
+};
+
+struct sgp_version {
+ u8 major;
+ u8 minor;
+};
+
+struct sgp_crc_word {
+ __be16 value;
+ u8 crc8;
+} __attribute__((__packed__));
+
+union sgp_reading {
+ u8 start;
+ struct sgp_crc_word raw_words[4];
+};
+
+enum _iaq_buffer_state {
+ IAQ_BUFFER_EMPTY = 0,
+ IAQ_BUFFER_DEFAULT_VALS,
+ IAQ_BUFFER_VALID,
+};
+
+struct sgp_data {
+ struct i2c_client *client;
+ struct task_struct *iaq_thread;
+ struct mutex data_lock;
+ unsigned long iaq_init_start_jiffies;
+ unsigned long iaq_defval_skip_jiffies;
+ u16 product_id;
+ u16 feature_set;
+ unsigned long measure_interval_jiffies;
+ enum sgp_cmd iaq_init_cmd;
+ enum sgp_cmd measure_iaq_cmd;
+ enum sgp_cmd measure_gas_signals_cmd;
+ union sgp_reading buffer;
+ union sgp_reading iaq_buffer;
+ enum _iaq_buffer_state iaq_buffer_state;
+};
+
+struct sgp_device {
+ const struct iio_chan_spec *channels;
+ int num_channels;
+};
+
+static const struct sgp_version supported_versions_sgp30[] = {
+ {
+ .major = 1,
+ .minor = 0,
+ },
+};
+
+static const struct sgp_version supported_versions_sgpc3[] = {
+ {
+ .major = 0,
+ .minor = 4,
+ },
+};
+
+static const struct iio_chan_spec sgp30_channels[] = {
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_VOC,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .address = SGP30_IAQ_TVOC_IDX,
+ },
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_CO2,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .address = SGP30_IAQ_CO2EQ_IDX,
+ },
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_ETHANOL,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .address = SGP30_SIG_ETOH_IDX,
+ },
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_H2,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .address = SGP30_SIG_H2_IDX,
+ },
+};
+
+static const struct iio_chan_spec sgpc3_channels[] = {
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_VOC,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .address = SGPC3_IAQ_TVOC_IDX,
+ },
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_ETHANOL,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .address = SGPC3_SIG_ETOH_IDX,
+ },
+};
+
+static const struct sgp_device sgp_devices[] = {
+ [SGP30] = {
+ .channels = sgp30_channels,
+ .num_channels = ARRAY_SIZE(sgp30_channels),
+ },
+ [SGPC3] = {
+ .channels = sgpc3_channels,
+ .num_channels = ARRAY_SIZE(sgpc3_channels),
+ },
+};
+
+/**
+ * sgp_verify_buffer() - verify the checksums of the data buffer words
+ *
+ * @data: SGP data
+ * @buf: Raw data buffer
+ * @word_count: Num data words stored in the buffer, excluding CRC bytes
+ *
+ * Return: 0 on success, negative error otherwise.
+ */
+static int sgp_verify_buffer(const struct sgp_data *data,
+ union sgp_reading *buf, size_t word_count)
+{
+ size_t size = word_count * (SGP_WORD_LEN + SGP_CRC8_LEN);
+ int i;
+ u8 crc;
+ u8 *data_buf = &buf->start;
+
+ for (i = 0; i < size; i += SGP_WORD_LEN + SGP_CRC8_LEN) {
+ crc = crc8(sgp_crc8_table, &data_buf[i], SGP_WORD_LEN,
+ SGP_CRC8_INIT);
+ if (crc != data_buf[i + SGP_WORD_LEN]) {
+ dev_err(&data->client->dev, "CRC error\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * sgp_read_cmd() - reads data from sensor after issuing a command
+ * The caller must hold data->data_lock for the duration of the call.
+ * @data: SGP data
+ * @cmd: SGP Command to issue
+ * @buf: Raw data buffer to use
+ * @word_count: Num words to read, excluding CRC bytes
+ *
+ * Return: 0 on success, negative error otherwise.
+ */
+static int sgp_read_cmd(struct sgp_data *data, enum sgp_cmd cmd,
+ union sgp_reading *buf, size_t word_count,
+ unsigned long duration_us)
+{
+ int ret;
+ struct i2c_client *client = data->client;
+ size_t size = word_count * (SGP_WORD_LEN + SGP_CRC8_LEN);
+ u8 *data_buf;
+
+ ret = i2c_master_send(client, (const char *)&cmd, SGP_CMD_LEN);
+ if (ret != SGP_CMD_LEN)
+ return -EIO;
+ usleep_range(duration_us, duration_us + 1000);
+
+ if (word_count == 0)
+ return 0;
+
+ data_buf = &buf->start;
+ ret = i2c_master_recv(client, data_buf, size);
+ if (ret < 0)
+ return ret;
+ if (ret != size)
+ return -EIO;
+
+ return sgp_verify_buffer(data, buf, word_count);
+}
+
+/**
+ * sgp_measure_iaq() - measure and retrieve IAQ values from sensor
+ * The caller must hold data->data_lock for the duration of the call.
+ * @data: SGP data
+ *
+ * Return: 0 on success, -EBUSY on default values, negative error
+ * otherwise.
+ */
+
+static int sgp_measure_iaq(struct sgp_data *data)
+{
+ int ret;
+ /* data contains default values */
+ bool default_vals = !time_after(jiffies, data->iaq_init_start_jiffies +
+ data->iaq_defval_skip_jiffies);
+
+ ret = sgp_read_cmd(data, data->measure_iaq_cmd, &data->iaq_buffer,
+ SGP_MEASUREMENT_LEN, SGP_MEASUREMENT_DURATION_US);
+ if (ret < 0)
+ return ret;
+
+ data->iaq_buffer_state = IAQ_BUFFER_DEFAULT_VALS;
+
+ if (default_vals)
+ return -EBUSY;
+
+ data->iaq_buffer_state = IAQ_BUFFER_VALID;
+
+ return 0;
+}
+
+static void sgp_iaq_thread_sleep_until(const struct sgp_data *data,
+ unsigned long sleep_jiffies)
+{
+ const long IAQ_POLL = 50000;
+
+ while (!time_after(jiffies, sleep_jiffies)) {
+ usleep_range(IAQ_POLL, IAQ_POLL + 10000);
+ if (kthread_should_stop() || data->iaq_init_start_jiffies == 0)
+ return;
+ }
+}
+
+static int sgp_iaq_threadfn(void *p)
+{
+ struct sgp_data *data = (struct sgp_data *)p;
+ unsigned long next_update_jiffies;
+ int ret;
+
+ while (!kthread_should_stop()) {
+ mutex_lock(&data->data_lock);
+ if (data->iaq_init_start_jiffies == 0) {
+ ret = sgp_read_cmd(data, data->iaq_init_cmd, NULL, 0,
+ SGP_CMD_DURATION_US);
+ if (ret < 0)
+ goto unlock_sleep_continue;
+ data->iaq_init_start_jiffies = jiffies;
+ }
+
+ ret = sgp_measure_iaq(data);
+ if (ret && ret != -EBUSY) {
+ dev_warn(&data->client->dev,
+ "IAQ measurement error [%d]\n", ret);
+ }
+unlock_sleep_continue:
+ next_update_jiffies = jiffies + data->measure_interval_jiffies;
+ mutex_unlock(&data->data_lock);
+ sgp_iaq_thread_sleep_until(data, next_update_jiffies);
+ }
+
+ return 0;
+}
+
+static int sgp_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct sgp_data *data = iio_priv(indio_dev);
+ struct sgp_crc_word *words;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ mutex_lock(&data->data_lock);
+ if (data->iaq_buffer_state != IAQ_BUFFER_VALID) {
+ mutex_unlock(&data->data_lock);
+ return -EBUSY;
+ }
+ words = data->iaq_buffer.raw_words;
+ switch (chan->address) {
+ case SGP30_IAQ_TVOC_IDX:
+ case SGPC3_IAQ_TVOC_IDX:
+ *val = 0;
+ *val2 = be16_to_cpu(words[1].value);
+ ret = IIO_VAL_INT_PLUS_NANO;
+ break;
+ case SGP30_IAQ_CO2EQ_IDX:
+ *val = 0;
+ *val2 = be16_to_cpu(words[0].value);
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ mutex_unlock(&data->data_lock);
+ break;
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&data->data_lock);
+ if (chan->address == SGPC3_SIG_ETOH_IDX) {
+ if (data->iaq_buffer_state == IAQ_BUFFER_EMPTY)
+ ret = -EBUSY;
+ else
+ ret = 0;
+ words = data->iaq_buffer.raw_words;
+ } else {
+ ret = sgp_read_cmd(data, data->measure_gas_signals_cmd,
+ &data->buffer, SGP_MEASUREMENT_LEN,
+ SGP_MEASUREMENT_DURATION_US);
+ words = data->buffer.raw_words;
+ }
+ if (ret) {
+ mutex_unlock(&data->data_lock);
+ return ret;
+ }
+
+ switch (chan->address) {
+ case SGP30_SIG_ETOH_IDX:
+ *val = be16_to_cpu(words[1].value);
+ ret = IIO_VAL_INT;
+ break;
+ case SGPC3_SIG_ETOH_IDX:
+ case SGP30_SIG_H2_IDX:
+ *val = be16_to_cpu(words[0].value);
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ mutex_unlock(&data->data_lock);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int sgp_check_compat(struct sgp_data *data,
+ unsigned int product_id)
+{
+ const struct sgp_version *supported_versions;
+ u16 ix, num_fs;
+ u16 product, generation, major, minor;
+
+ /* driver does not match product */
+ generation = SGP_VERS_GEN(data);
+ if (generation != 0) {
+ dev_err(&data->client->dev,
+ "incompatible product generation %d != 0", generation);
+ return -ENODEV;
+ }
+
+ product = SGP_VERS_PRODUCT(data);
+ if (product != product_id) {
+ dev_err(&data->client->dev,
+ "sensor reports a different product: 0x%04hx\n",
+ product);
+ return -ENODEV;
+ }
+
+ if (SGP_VERS_RESERVED(data))
+ dev_warn(&data->client->dev, "reserved bit is set\n");
+
+ /* engineering samples are not supported: no interface guarantees */
+ if (SGP_VERS_ENG_BIT(data))
+ return -ENODEV;
+
+ switch (product) {
+ case SGP30:
+ supported_versions = supported_versions_sgp30;
+ num_fs = ARRAY_SIZE(supported_versions_sgp30);
+ break;
+ case SGPC3:
+ supported_versions = supported_versions_sgpc3;
+ num_fs = ARRAY_SIZE(supported_versions_sgpc3);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ major = SGP_VERS_MAJOR(data);
+ minor = SGP_VERS_MINOR(data);
+ for (ix = 0; ix < num_fs; ix++) {
+ if (major == supported_versions[ix].major &&
+ minor >= supported_versions[ix].minor)
+ return 0;
+ }
+ dev_err(&data->client->dev, "unsupported sgp version: %d.%d\n",
+ major, minor);
+
+ return -ENODEV;
+}
+
+static void sgp_init(struct sgp_data *data)
+{
+ data->iaq_init_cmd = SGP_CMD_IAQ_INIT;
+ data->iaq_init_start_jiffies = 0;
+ data->iaq_buffer_state = IAQ_BUFFER_EMPTY;
+ switch (SGP_VERS_PRODUCT(data)) {
+ case SGP30:
+ data->measure_interval_jiffies = SGP30_MEASURE_INTERVAL_HZ * HZ;
+ data->measure_iaq_cmd = SGP_CMD_IAQ_MEASURE;
+ data->measure_gas_signals_cmd = SGP30_CMD_MEASURE_SIGNAL;
+ data->product_id = SGP30;
+ data->iaq_defval_skip_jiffies = 15 * HZ;
+ break;
+ case SGPC3:
+ data->measure_interval_jiffies = SGPC3_MEASURE_INTERVAL_HZ * HZ;
+ data->measure_iaq_cmd = SGPC3_CMD_MEASURE_RAW;
+ data->measure_gas_signals_cmd = SGPC3_CMD_MEASURE_RAW;
+ data->product_id = SGPC3;
+ data->iaq_defval_skip_jiffies =
+ 43 * data->measure_interval_jiffies;
+ break;
+ };
+}
+
+static const struct iio_info sgp_info = {
+ .read_raw = sgp_read_raw,
+};
+
+static const struct of_device_id sgp_dt_ids[] = {
+ { .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
+ { .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
+ { }
+};
+
+static int sgp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct iio_dev *indio_dev;
+ struct sgp_data *data;
+ const struct of_device_id *of_id;
+ unsigned long product_id;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ of_id = of_match_device(sgp_dt_ids, &client->dev);
+ if (of_id)
+ product_id = (unsigned long)of_id->data;
+ else
+ product_id = id->driver_data;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ crc8_populate_msb(sgp_crc8_table, SGP_CRC8_POLYNOMIAL);
+ mutex_init(&data->data_lock);
+
+ /* get feature set version and write it to client data */
+ ret = sgp_read_cmd(data, SGP_CMD_GET_FEATURE_SET, &data->buffer, 1,
+ SGP_CMD_DURATION_US);
+ if (ret < 0)
+ return ret;
+
+ data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value);
+
+ ret = sgp_check_compat(data, product_id);
+ if (ret)
+ return ret;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &sgp_info;
+ indio_dev->name = id->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = sgp_devices[product_id].channels;
+ indio_dev->num_channels = sgp_devices[product_id].num_channels;
+
+ sgp_init(data);
+
+ ret = devm_iio_device_register(&client->dev, indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "failed to register iio device\n");
+ return ret;
+ }
+
+ data->iaq_thread = kthread_run(sgp_iaq_threadfn, data,
+ "%s-iaq", data->client->name);
+
+ return 0;
+}
+
+static int sgp_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct sgp_data *data = iio_priv(indio_dev);
+
+ if (data->iaq_thread)
+ kthread_stop(data->iaq_thread);
+
+ return 0;
+}
+
+static const struct i2c_device_id sgp_id[] = {
+ { "sgp30", SGP30 },
+ { "sgpc3", SGPC3 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, sgp_id);
+MODULE_DEVICE_TABLE(of, sgp_dt_ids);
+
+static struct i2c_driver sgp_driver = {
+ .driver = {
+ .name = "sgp30",
+ .of_match_table = of_match_ptr(sgp_dt_ids),
+ },
+ .probe = sgp_probe,
+ .remove = sgp_remove,
+ .id_table = sgp_id,
+};
+module_i2c_driver(sgp_driver);
+
+MODULE_AUTHOR("Andreas Brauchli <andreas.brauchli@sensirion.com>");
+MODULE_AUTHOR("Pascal Sachs <pascal.sachs@sensirion.com>");
+MODULE_DESCRIPTION("Sensirion SGP gas sensors");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c
new file mode 100644
index 000000000000..edbb956e81e8
--- /dev/null
+++ b/drivers/iio/chemical/sps30.c
@@ -0,0 +1,548 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SPS30 particulate matter sensor driver
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
+ *
+ * I2C slave address: 0x69
+ */
+
+#include <asm/unaligned.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define SPS30_CRC8_POLYNOMIAL 0x31
+/* max number of bytes needed to store PM measurements or serial string */
+#define SPS30_MAX_READ_SIZE 48
+/* sensor measures reliably up to 3000 ug / m3 */
+#define SPS30_MAX_PM 3000
+/* minimum and maximum self cleaning periods in seconds */
+#define SPS30_AUTO_CLEANING_PERIOD_MIN 0
+#define SPS30_AUTO_CLEANING_PERIOD_MAX 604800
+
+/* SPS30 commands */
+#define SPS30_START_MEAS 0x0010
+#define SPS30_STOP_MEAS 0x0104
+#define SPS30_RESET 0xd304
+#define SPS30_READ_DATA_READY_FLAG 0x0202
+#define SPS30_READ_DATA 0x0300
+#define SPS30_READ_SERIAL 0xd033
+#define SPS30_START_FAN_CLEANING 0x5607
+#define SPS30_AUTO_CLEANING_PERIOD 0x8004
+/* not a sensor command per se, used only to distinguish write from read */
+#define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005
+
+enum {
+ PM1,
+ PM2P5,
+ PM4,
+ PM10,
+};
+
+enum {
+ RESET,
+ MEASURING,
+};
+
+struct sps30_state {
+ struct i2c_client *client;
+ /*
+ * Guards against concurrent access to sensor registers.
+ * Must be held whenever sequence of commands is to be executed.
+ */
+ struct mutex lock;
+ int state;
+};
+
+DECLARE_CRC8_TABLE(sps30_crc8_table);
+
+static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf,
+ int txsize, u8 *rxbuf, int rxsize)
+{
+ int ret;
+
+ /*
+ * Sensor does not support repeated start so instead of
+ * sending two i2c messages in a row we just send one by one.
+ */
+ ret = i2c_master_send(state->client, txbuf, txsize);
+ if (ret != txsize)
+ return ret < 0 ? ret : -EIO;
+
+ if (!rxbuf)
+ return 0;
+
+ ret = i2c_master_recv(state->client, rxbuf, rxsize);
+ if (ret != rxsize)
+ return ret < 0 ? ret : -EIO;
+
+ return 0;
+}
+
+static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size)
+{
+ /*
+ * Internally sensor stores measurements in a following manner:
+ *
+ * PM1: upper two bytes, crc8, lower two bytes, crc8
+ * PM2P5: upper two bytes, crc8, lower two bytes, crc8
+ * PM4: upper two bytes, crc8, lower two bytes, crc8
+ * PM10: upper two bytes, crc8, lower two bytes, crc8
+ *
+ * What follows next are number concentration measurements and
+ * typical particle size measurement which we omit.
+ */
+ u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd };
+ int i, ret = 0;
+
+ switch (cmd) {
+ case SPS30_START_MEAS:
+ buf[2] = 0x03;
+ buf[3] = 0x00;
+ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE);
+ ret = sps30_write_then_read(state, buf, 5, NULL, 0);
+ break;
+ case SPS30_STOP_MEAS:
+ case SPS30_RESET:
+ case SPS30_START_FAN_CLEANING:
+ ret = sps30_write_then_read(state, buf, 2, NULL, 0);
+ break;
+ case SPS30_READ_AUTO_CLEANING_PERIOD:
+ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
+ buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD;
+ /* fall through */
+ case SPS30_READ_DATA_READY_FLAG:
+ case SPS30_READ_DATA:
+ case SPS30_READ_SERIAL:
+ /* every two data bytes are checksummed */
+ size += size / 2;
+ ret = sps30_write_then_read(state, buf, 2, buf, size);
+ break;
+ case SPS30_AUTO_CLEANING_PERIOD:
+ buf[2] = data[0];
+ buf[3] = data[1];
+ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE);
+ buf[5] = data[2];
+ buf[6] = data[3];
+ buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE);
+ ret = sps30_write_then_read(state, buf, 8, NULL, 0);
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ /* validate received data and strip off crc bytes */
+ for (i = 0; i < size; i += 3) {
+ u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE);
+
+ if (crc != buf[i + 2]) {
+ dev_err(&state->client->dev,
+ "data integrity check failed\n");
+ return -EIO;
+ }
+
+ *data++ = buf[i];
+ *data++ = buf[i + 1];
+ }
+
+ return 0;
+}
+
+static s32 sps30_float_to_int_clamped(const u8 *fp)
+{
+ int val = get_unaligned_be32(fp);
+ int mantissa = val & GENMASK(22, 0);
+ /* this is fine since passed float is always non-negative */
+ int exp = val >> 23;
+ int fraction, shift;
+
+ /* special case 0 */
+ if (!exp && !mantissa)
+ return 0;
+
+ exp -= 127;
+ if (exp < 0) {
+ /* return values ranging from 1 to 99 */
+ return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp);
+ }
+
+ /* return values ranging from 100 to 300000 */
+ shift = 23 - exp;
+ val = (1 << exp) + (mantissa >> shift);
+ if (val >= SPS30_MAX_PM)
+ return SPS30_MAX_PM * 100;
+
+ fraction = mantissa & GENMASK(shift - 1, 0);
+
+ return val * 100 + ((fraction * 100) >> shift);
+}
+
+static int sps30_do_meas(struct sps30_state *state, s32 *data, int size)
+{
+ int i, ret, tries = 5;
+ u8 tmp[16];
+
+ if (state->state == RESET) {
+ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0);
+ if (ret)
+ return ret;
+
+ state->state = MEASURING;
+ }
+
+ while (tries--) {
+ ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2);
+ if (ret)
+ return -EIO;
+
+ /* new measurements ready to be read */
+ if (tmp[1] == 1)
+ break;
+
+ msleep_interruptible(300);
+ }
+
+ if (tries == -1)
+ return -ETIMEDOUT;
+
+ ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < size; i++)
+ data[i] = sps30_float_to_int_clamped(&tmp[4 * i]);
+
+ return 0;
+}
+
+static irqreturn_t sps30_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct sps30_state *state = iio_priv(indio_dev);
+ int ret;
+ s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_meas(state, data, 4);
+ mutex_unlock(&state->lock);
+ if (ret)
+ goto err;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int sps30_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct sps30_state *state = iio_priv(indio_dev);
+ int data[4], ret = -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_MASSCONCENTRATION:
+ mutex_lock(&state->lock);
+ /* read up to the number of bytes actually needed */
+ switch (chan->channel2) {
+ case IIO_MOD_PM1:
+ ret = sps30_do_meas(state, data, 1);
+ break;
+ case IIO_MOD_PM2P5:
+ ret = sps30_do_meas(state, data, 2);
+ break;
+ case IIO_MOD_PM4:
+ ret = sps30_do_meas(state, data, 3);
+ break;
+ case IIO_MOD_PM10:
+ ret = sps30_do_meas(state, data, 4);
+ break;
+ }
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ *val = data[chan->address] / 100;
+ *val2 = (data[chan->address] % 100) * 10000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_MASSCONCENTRATION:
+ switch (chan->channel2) {
+ case IIO_MOD_PM1:
+ case IIO_MOD_PM2P5:
+ case IIO_MOD_PM4:
+ case IIO_MOD_PM10:
+ *val = 0;
+ *val2 = 10000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int sps30_do_cmd_reset(struct sps30_state *state)
+{
+ int ret;
+
+ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0);
+ msleep(300);
+ /*
+ * Power-on-reset causes sensor to produce some glitch on i2c bus and
+ * some controllers end up in error state. Recover simply by placing
+ * some data on the bus, for example STOP_MEAS command, which
+ * is NOP in this case.
+ */
+ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
+ state->state = RESET;
+
+ return ret;
+}
+
+static ssize_t start_cleaning_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ int val, ret;
+
+ if (kstrtoint(buf, 0, &val) || val != 1)
+ return -EINVAL;
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0);
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static ssize_t cleaning_period_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ u8 tmp[4];
+ int ret;
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4);
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", get_unaligned_be32(tmp));
+}
+
+static ssize_t cleaning_period_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ int val, ret;
+ u8 tmp[4];
+
+ if (kstrtoint(buf, 0, &val))
+ return -EINVAL;
+
+ if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) ||
+ (val > SPS30_AUTO_CLEANING_PERIOD_MAX))
+ return -EINVAL;
+
+ put_unaligned_be32(val, tmp);
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0);
+ if (ret) {
+ mutex_unlock(&state->lock);
+ return ret;
+ }
+
+ msleep(20);
+
+ /*
+ * sensor requires reset in order to return up to date self cleaning
+ * period
+ */
+ ret = sps30_do_cmd_reset(state);
+ if (ret)
+ dev_warn(dev,
+ "period changed but reads will return the old value\n");
+
+ mutex_unlock(&state->lock);
+
+ return len;
+}
+
+static ssize_t cleaning_period_available_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n",
+ SPS30_AUTO_CLEANING_PERIOD_MIN, 1,
+ SPS30_AUTO_CLEANING_PERIOD_MAX);
+}
+
+static IIO_DEVICE_ATTR_WO(start_cleaning, 0);
+static IIO_DEVICE_ATTR_RW(cleaning_period, 0);
+static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0);
+
+static struct attribute *sps30_attrs[] = {
+ &iio_dev_attr_start_cleaning.dev_attr.attr,
+ &iio_dev_attr_cleaning_period.dev_attr.attr,
+ &iio_dev_attr_cleaning_period_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group sps30_attr_group = {
+ .attrs = sps30_attrs,
+};
+
+static const struct iio_info sps30_info = {
+ .attrs = &sps30_attr_group,
+ .read_raw = sps30_read_raw,
+};
+
+#define SPS30_CHAN(_index, _mod) { \
+ .type = IIO_MASSCONCENTRATION, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_ ## _mod, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .address = _mod, \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 19, \
+ .storagebits = 32, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+static const struct iio_chan_spec sps30_channels[] = {
+ SPS30_CHAN(0, PM1),
+ SPS30_CHAN(1, PM2P5),
+ SPS30_CHAN(2, PM4),
+ SPS30_CHAN(3, PM10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static void sps30_stop_meas(void *data)
+{
+ struct sps30_state *state = data;
+
+ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
+}
+
+static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 };
+
+static int sps30_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct sps30_state *state;
+ u8 buf[32];
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -EOPNOTSUPP;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ state->client = client;
+ state->state = RESET;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &sps30_info;
+ indio_dev->name = client->name;
+ indio_dev->channels = sps30_channels;
+ indio_dev->num_channels = ARRAY_SIZE(sps30_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->available_scan_masks = sps30_scan_masks;
+
+ mutex_init(&state->lock);
+ crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL);
+
+ ret = sps30_do_cmd_reset(state);
+ if (ret) {
+ dev_err(&client->dev, "failed to reset device\n");
+ return ret;
+ }
+
+ ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf));
+ if (ret) {
+ dev_err(&client->dev, "failed to read serial number\n");
+ return ret;
+ }
+ /* returned serial number is already NUL terminated */
+ dev_info(&client->dev, "serial number: %s\n", buf);
+
+ ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ sps30_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id sps30_id[] = {
+ { "sps30" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sps30_id);
+
+static const struct of_device_id sps30_of_match[] = {
+ { .compatible = "sensirion,sps30" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sps30_of_match);
+
+static struct i2c_driver sps30_driver = {
+ .driver = {
+ .name = "sps30",
+ .of_match_table = sps30_of_match,
+ },
+ .id_table = sps30_id,
+ .probe_new = sps30_probe,
+};
+module_i2c_driver(sps30_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 851b61eaf3da..fbef9107acad 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -148,9 +148,9 @@ config AD5686_SPI
depends on SPI
select AD5686
help
- Say yes here to build support for Analog Devices AD5672R, AD5676,
- AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R.
- Voltage Output Digital to Analog Converter.
+ Say yes here to build support for Analog Devices AD5672R, AD5674R,
+ AD5676, AD5676R, AD5679R, AD5684, AD5684R, AD5684R, AD5685R, AD5686,
+ AD5686R Voltage Output Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5686.
@@ -375,6 +375,16 @@ config TI_DAC7311
If compiled as a module, it will be called ti-dac7311.
+config TI_DAC7612
+ tristate "Texas Instruments 12-bit 2-channel DAC driver"
+ depends on SPI_MASTER && GPIOLIB
+ help
+ Driver for the Texas Instruments DAC7612, DAC7612U, DAC7612UB
+ The driver hand drive the load pin automatically, otherwise
+ it needs to be toggled manually.
+
+ If compiled as a module, it will be called ti-dac7612.
+
config VF610_DAC
tristate "Vybrid vf610 DAC driver"
depends on OF
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index f0a37c93de8e..1369fa1d2f0e 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_STM32_DAC) += stm32-dac.o
obj-$(CONFIG_TI_DAC082S085) += ti-dac082s085.o
obj-$(CONFIG_TI_DAC5571) += ti-dac5571.o
obj-$(CONFIG_TI_DAC7311) += ti-dac7311.o
+obj-$(CONFIG_TI_DAC7612) += ti-dac7612.o
obj-$(CONFIG_VF610_DAC) += vf610_dac.o
diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 665fa6bd9ced..0188ded5137c 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -1,7 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
/*
- * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R,
- * AD5684, AD5684R, AD5685R, AD5686, AD5686R
+ * AD5672R, AD5674R, AD5676, AD5676R, AD5679R,
+ * AD5681R, AD5682R, AD5683, AD5683R, AD5684,
+ * AD5684R, AD5685R, AD5686, AD5686R
* Digital to analog converters driver
*
* Copyright 2018 Analog Devices Inc.
@@ -102,8 +103,10 @@ static int ad5686_spi_remove(struct spi_device *spi)
static const struct spi_device_id ad5686_spi_id[] = {
{"ad5310r", ID_AD5310R},
{"ad5672r", ID_AD5672R},
+ {"ad5674r", ID_AD5674R},
{"ad5676", ID_AD5676},
{"ad5676r", ID_AD5676R},
+ {"ad5679r", ID_AD5679R},
{"ad5681r", ID_AD5681R},
{"ad5682r", ID_AD5682R},
{"ad5683", ID_AD5683},
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index a332b93ca2c4..e06b29c565b9 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
/*
* AD5686R, AD5685R, AD5684R Digital to analog converters driver
*
@@ -71,7 +71,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
int ret;
struct ad5686_state *st = iio_priv(indio_dev);
unsigned int val, ref_bit_msk;
- u8 shift;
+ u8 shift, address = 0;
ret = strtobool(buf, &readin);
if (ret)
@@ -94,6 +94,9 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
case AD5686_REGMAP:
shift = 0;
ref_bit_msk = 0;
+ /* AD5674R/AD5679R have 16 channels and 2 powerdown registers */
+ if (chan->channel > 0x7)
+ address = 0x8;
break;
case AD5693_REGMAP:
shift = 13;
@@ -107,7 +110,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
if (!st->use_internal_vref)
val |= ref_bit_msk;
- ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, val);
+ ret = st->write(st, AD5686_CMD_POWERDOWN_DAC,
+ address, val >> (address * 2));
return ret ? ret : len;
}
@@ -226,10 +230,32 @@ static struct iio_chan_spec name[] = { \
AD5868_CHANNEL(7, 7, bits, _shift), \
}
+#define DECLARE_AD5679_CHANNELS(name, bits, _shift) \
+static struct iio_chan_spec name[] = { \
+ AD5868_CHANNEL(0, 0, bits, _shift), \
+ AD5868_CHANNEL(1, 1, bits, _shift), \
+ AD5868_CHANNEL(2, 2, bits, _shift), \
+ AD5868_CHANNEL(3, 3, bits, _shift), \
+ AD5868_CHANNEL(4, 4, bits, _shift), \
+ AD5868_CHANNEL(5, 5, bits, _shift), \
+ AD5868_CHANNEL(6, 6, bits, _shift), \
+ AD5868_CHANNEL(7, 7, bits, _shift), \
+ AD5868_CHANNEL(8, 8, bits, _shift), \
+ AD5868_CHANNEL(9, 9, bits, _shift), \
+ AD5868_CHANNEL(10, 10, bits, _shift), \
+ AD5868_CHANNEL(11, 11, bits, _shift), \
+ AD5868_CHANNEL(12, 12, bits, _shift), \
+ AD5868_CHANNEL(13, 13, bits, _shift), \
+ AD5868_CHANNEL(14, 14, bits, _shift), \
+ AD5868_CHANNEL(15, 15, bits, _shift), \
+}
+
DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2);
DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6);
DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
+DECLARE_AD5679_CHANNELS(ad5674r_channels, 12, 4);
DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
+DECLARE_AD5679_CHANNELS(ad5679r_channels, 16, 0);
DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
@@ -262,6 +288,12 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+ [ID_AD5674R] = {
+ .channels = ad5674r_channels,
+ .int_vref_mv = 2500,
+ .num_channels = 16,
+ .regmap_type = AD5686_REGMAP,
+ },
[ID_AD5675R] = {
.channels = ad5676_channels,
.int_vref_mv = 2500,
@@ -279,6 +311,12 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+ [ID_AD5679R] = {
+ .channels = ad5679r_channels,
+ .int_vref_mv = 2500,
+ .num_channels = 16,
+ .regmap_type = AD5686_REGMAP,
+ },
[ID_AD5681R] = {
.channels = ad5691r_channels,
.int_vref_mv = 2500,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index 19f6917d4738..70a779939ddb 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file is part of AD5686 DAC driver
*
@@ -54,9 +54,11 @@ enum ad5686_supported_device_ids {
ID_AD5311R,
ID_AD5671R,
ID_AD5672R,
+ ID_AD5674R,
ID_AD5675R,
ID_AD5676,
ID_AD5676R,
+ ID_AD5679R,
ID_AD5681R,
ID_AD5682R,
ID_AD5683,
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index 7350d9806a11..ccf794caef43 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
/*
* AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R,
* AD5694, AD5694R, AD5695R, AD5696, AD5696R
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
index ef41f12bf262..2bdf1b0aee06 100644
--- a/drivers/iio/dac/ad5758.c
+++ b/drivers/iio/dac/ad5758.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
/*
* AD5758 Digital to analog converters driver
*
diff --git a/drivers/iio/dac/ti-dac7612.c b/drivers/iio/dac/ti-dac7612.c
new file mode 100644
index 000000000000..c46805144dd4
--- /dev/null
+++ b/drivers/iio/dac/ti-dac7612.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DAC7612 Dual, 12-Bit Serial input Digital-to-Analog Converter
+ *
+ * Copyright 2019 Qtechnology A/S
+ * 2019 Ricardo Ribalda <ricardo@ribalda.com>
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+
+#define DAC7612_RESOLUTION 12
+#define DAC7612_ADDRESS 4
+#define DAC7612_START 5
+
+struct dac7612 {
+ struct spi_device *spi;
+ struct gpio_desc *loaddacs;
+ uint16_t cache[2];
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ uint8_t data[2] ____cacheline_aligned;
+};
+
+static int dac7612_cmd_single(struct dac7612 *priv, int channel, u16 val)
+{
+ int ret;
+
+ priv->data[0] = BIT(DAC7612_START) | (channel << DAC7612_ADDRESS);
+ priv->data[0] |= val >> 8;
+ priv->data[1] = val & 0xff;
+
+ priv->cache[channel] = val;
+
+ ret = spi_write(priv->spi, priv->data, sizeof(priv->data));
+ if (ret)
+ return ret;
+
+ gpiod_set_value(priv->loaddacs, 1);
+ gpiod_set_value(priv->loaddacs, 0);
+
+ return 0;
+}
+
+#define dac7612_CHANNEL(chan, name) { \
+ .type = IIO_VOLTAGE, \
+ .channel = (chan), \
+ .indexed = 1, \
+ .output = 1, \
+ .datasheet_name = name, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+static const struct iio_chan_spec dac7612_channels[] = {
+ dac7612_CHANNEL(0, "OUTA"),
+ dac7612_CHANNEL(1, "OUTB"),
+};
+
+static int dac7612_read_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct dac7612 *priv;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ priv = iio_priv(iio_dev);
+ *val = priv->cache[chan->channel];
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = 1;
+ return IIO_VAL_INT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int dac7612_write_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int val, int val2, long mask)
+{
+ struct dac7612 *priv = iio_priv(iio_dev);
+ int ret;
+
+ if (mask != IIO_CHAN_INFO_RAW)
+ return -EINVAL;
+
+ if ((val >= BIT(DAC7612_RESOLUTION)) || val < 0 || val2)
+ return -EINVAL;
+
+ if (val == priv->cache[chan->channel])
+ return 0;
+
+ mutex_lock(&iio_dev->mlock);
+ ret = dac7612_cmd_single(priv, chan->channel, val);
+ mutex_unlock(&iio_dev->mlock);
+
+ return ret;
+}
+
+static const struct iio_info dac7612_info = {
+ .read_raw = dac7612_read_raw,
+ .write_raw = dac7612_write_raw,
+};
+
+static int dac7612_probe(struct spi_device *spi)
+{
+ struct iio_dev *iio_dev;
+ struct dac7612 *priv;
+ int i;
+ int ret;
+
+ iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
+ if (!iio_dev)
+ return -ENOMEM;
+
+ priv = iio_priv(iio_dev);
+ /*
+ * LOADDACS pin can be controlled by the driver or externally.
+ * When controlled by the driver, the DAC value is updated after
+ * every write.
+ * When the driver does not control the PIN, the user or an external
+ * event can change the value of all DACs by pulsing down the LOADDACs
+ * pin.
+ */
+ priv->loaddacs = devm_gpiod_get_optional(&spi->dev, "ti,loaddacs",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(priv->loaddacs))
+ return PTR_ERR(priv->loaddacs);
+ priv->spi = spi;
+ spi_set_drvdata(spi, iio_dev);
+ iio_dev->dev.parent = &spi->dev;
+ iio_dev->info = &dac7612_info;
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->channels = dac7612_channels;
+ iio_dev->num_channels = ARRAY_SIZE(priv->cache);
+ iio_dev->name = spi_get_device_id(spi)->name;
+
+ for (i = 0; i < ARRAY_SIZE(priv->cache); i++) {
+ ret = dac7612_cmd_single(priv, i, 0);
+ if (ret)
+ return ret;
+ }
+
+ return devm_iio_device_register(&spi->dev, iio_dev);
+}
+
+static const struct spi_device_id dac7612_id[] = {
+ {"ti-dac7612"},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, dac7612_id);
+
+static const struct of_device_id dac7612_of_match[] = {
+ { .compatible = "ti,dac7612" },
+ { .compatible = "ti,dac7612u" },
+ { .compatible = "ti,dac7612ub" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, dac7612_of_match);
+
+static struct spi_driver dac7612_driver = {
+ .driver = {
+ .name = "ti-dac7612",
+ .of_match_table = dac7612_of_match,
+ },
+ .probe = dac7612_probe,
+ .id_table = dac7612_id,
+};
+module_spi_driver(dac7612_driver);
+
+MODULE_AUTHOR("Ricardo Ribalda <ricardo@ribalda.com>");
+MODULE_DESCRIPTION("Texas Instruments DAC7612 DAC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index f3f94fbdd20a..3f9be69499ec 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -943,11 +943,14 @@ static int ad9523_setup(struct iio_dev *indio_dev)
}
}
- for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN)
- ad9523_write(indio_dev,
+ for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) {
+ ret = ad9523_write(indio_dev,
AD9523_CHANNEL_CLOCK_DIST(i),
AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) |
AD9523_CLK_DIST_PWR_DOWN_EN);
+ if (ret < 0)
+ return ret;
+ }
ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0);
if (ret < 0)
diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h
index 2351049d930b..621f5309d735 100644
--- a/drivers/iio/imu/bmi160/bmi160.h
+++ b/drivers/iio/imu/bmi160/bmi160.h
@@ -2,9 +2,20 @@
#ifndef BMI160_H_
#define BMI160_H_
+#include <linux/iio/iio.h>
+
+struct bmi160_data {
+ struct regmap *regmap;
+ struct iio_trigger *trig;
+};
+
extern const struct regmap_config bmi160_regmap_config;
int bmi160_core_probe(struct device *dev, struct regmap *regmap,
const char *name, bool use_spi);
+int bmi160_enable_irq(struct regmap *regmap, bool enable);
+
+int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type);
+
#endif /* BMI160_H_ */
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index b10330b0f93f..6af65d6f1d28 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -1,26 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* BMI160 - Bosch IMU (accel, gyro plus external magnetometer)
*
* Copyright (c) 2016, Intel Corporation.
- *
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License. See the file COPYING in the main
- * directory of this archive for more details.
+ * Copyright (c) 2019, Martin Kelly.
*
* IIO core driver for BMI160, with support for I2C/SPI busses
*
- * TODO: magnetometer, interrupts, hardware FIFO
+ * TODO: magnetometer, hardware FIFO
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/acpi.h>
#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
#include <linux/iio/iio.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
#include "bmi160.h"
@@ -64,8 +65,32 @@
#define BMI160_CMD_GYRO_PM_FAST_STARTUP 0x17
#define BMI160_CMD_SOFTRESET 0xB6
+#define BMI160_REG_INT_EN 0x51
+#define BMI160_DRDY_INT_EN BIT(4)
+
+#define BMI160_REG_INT_OUT_CTRL 0x53
+#define BMI160_INT_OUT_CTRL_MASK 0x0f
+#define BMI160_INT1_OUT_CTRL_SHIFT 0
+#define BMI160_INT2_OUT_CTRL_SHIFT 4
+#define BMI160_EDGE_TRIGGERED BIT(0)
+#define BMI160_ACTIVE_HIGH BIT(1)
+#define BMI160_OPEN_DRAIN BIT(2)
+#define BMI160_OUTPUT_EN BIT(3)
+
+#define BMI160_REG_INT_LATCH 0x54
+#define BMI160_INT1_LATCH_MASK BIT(4)
+#define BMI160_INT2_LATCH_MASK BIT(5)
+
+/* INT1 and INT2 are in the opposite order as in INT_OUT_CTRL! */
+#define BMI160_REG_INT_MAP 0x56
+#define BMI160_INT1_MAP_DRDY_EN 0x80
+#define BMI160_INT2_MAP_DRDY_EN 0x08
+
#define BMI160_REG_DUMMY 0x7F
+#define BMI160_NORMAL_WRITE_USLEEP 2
+#define BMI160_SUSPENDED_WRITE_USLEEP 450
+
#define BMI160_ACCEL_PMU_MIN_USLEEP 3800
#define BMI160_GYRO_PMU_MIN_USLEEP 80000
#define BMI160_SOFTRESET_USLEEP 1000
@@ -108,8 +133,9 @@ enum bmi160_sensor_type {
BMI160_NUM_SENSORS /* must be last */
};
-struct bmi160_data {
- struct regmap *regmap;
+enum bmi160_int_pin {
+ BMI160_PIN_INT1,
+ BMI160_PIN_INT2
};
const struct regmap_config bmi160_regmap_config = {
@@ -273,7 +299,7 @@ int bmi160_set_mode(struct bmi160_data *data, enum bmi160_sensor_type t,
cmd = bmi160_regs[t].pmu_cmd_suspend;
ret = regmap_write(data->regmap, BMI160_REG_CMD, cmd);
- if (ret < 0)
+ if (ret)
return ret;
usleep_range(bmi160_pmu_time[t], bmi160_pmu_time[t] + 1000);
@@ -305,7 +331,7 @@ int bmi160_get_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
int i, ret, val;
ret = regmap_read(data->regmap, bmi160_regs[t].range, &val);
- if (ret < 0)
+ if (ret)
return ret;
for (i = 0; i < bmi160_scale_table[t].num; i++)
@@ -328,7 +354,7 @@ static int bmi160_get_data(struct bmi160_data *data, int chan_type,
reg = bmi160_regs[t].data + (axis - IIO_MOD_X) * sizeof(sample);
ret = regmap_bulk_read(data->regmap, reg, &sample, sizeof(sample));
- if (ret < 0)
+ if (ret)
return ret;
*val = sign_extend32(le16_to_cpu(sample), 15);
@@ -362,7 +388,7 @@ static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
int i, val, ret;
ret = regmap_read(data->regmap, bmi160_regs[t].config, &val);
- if (ret < 0)
+ if (ret)
return ret;
val &= bmi160_regs[t].config_odr_mask;
@@ -394,13 +420,12 @@ static irqreturn_t bmi160_trigger_handler(int irq, void *p)
indio_dev->masklength) {
ret = regmap_bulk_read(data->regmap, base + i * sizeof(sample),
&sample, sizeof(sample));
- if (ret < 0)
+ if (ret)
goto done;
buf[j++] = sample;
}
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
- iio_get_time_ns(indio_dev));
+ iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@@ -416,18 +441,18 @@ static int bmi160_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = bmi160_get_data(data, chan->type, chan->channel2, val);
- if (ret < 0)
+ if (ret)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
ret = bmi160_get_scale(data,
bmi160_to_sensor(chan->type), val2);
- return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO;
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
ret = bmi160_get_odr(data, bmi160_to_sensor(chan->type),
val, val2);
- return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO;
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@@ -498,6 +523,186 @@ static const char *bmi160_match_acpi_device(struct device *dev)
return dev_name(dev);
}
+static int bmi160_write_conf_reg(struct regmap *regmap, unsigned int reg,
+ unsigned int mask, unsigned int bits,
+ unsigned int write_usleep)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ val = (val & ~mask) | bits;
+
+ ret = regmap_write(regmap, reg, val);
+ if (ret)
+ return ret;
+
+ /*
+ * We need to wait after writing before we can write again. See the
+ * datasheet, page 93.
+ */
+ usleep_range(write_usleep, write_usleep + 1000);
+
+ return 0;
+}
+
+static int bmi160_config_pin(struct regmap *regmap, enum bmi160_int_pin pin,
+ bool open_drain, u8 irq_mask,
+ unsigned long write_usleep)
+{
+ int ret;
+ struct device *dev = regmap_get_device(regmap);
+ u8 int_out_ctrl_shift;
+ u8 int_latch_mask;
+ u8 int_map_mask;
+ u8 int_out_ctrl_mask;
+ u8 int_out_ctrl_bits;
+ const char *pin_name;
+
+ switch (pin) {
+ case BMI160_PIN_INT1:
+ int_out_ctrl_shift = BMI160_INT1_OUT_CTRL_SHIFT;
+ int_latch_mask = BMI160_INT1_LATCH_MASK;
+ int_map_mask = BMI160_INT1_MAP_DRDY_EN;
+ break;
+ case BMI160_PIN_INT2:
+ int_out_ctrl_shift = BMI160_INT2_OUT_CTRL_SHIFT;
+ int_latch_mask = BMI160_INT2_LATCH_MASK;
+ int_map_mask = BMI160_INT2_MAP_DRDY_EN;
+ break;
+ }
+ int_out_ctrl_mask = BMI160_INT_OUT_CTRL_MASK << int_out_ctrl_shift;
+
+ /*
+ * Enable the requested pin with the right settings:
+ * - Push-pull/open-drain
+ * - Active low/high
+ * - Edge/level triggered
+ */
+ int_out_ctrl_bits = BMI160_OUTPUT_EN;
+ if (open_drain)
+ /* Default is push-pull. */
+ int_out_ctrl_bits |= BMI160_OPEN_DRAIN;
+ int_out_ctrl_bits |= irq_mask;
+ int_out_ctrl_bits <<= int_out_ctrl_shift;
+
+ ret = bmi160_write_conf_reg(regmap, BMI160_REG_INT_OUT_CTRL,
+ int_out_ctrl_mask, int_out_ctrl_bits,
+ write_usleep);
+ if (ret)
+ return ret;
+
+ /* Set the pin to input mode with no latching. */
+ ret = bmi160_write_conf_reg(regmap, BMI160_REG_INT_LATCH,
+ int_latch_mask, int_latch_mask,
+ write_usleep);
+ if (ret)
+ return ret;
+
+ /* Map interrupts to the requested pin. */
+ ret = bmi160_write_conf_reg(regmap, BMI160_REG_INT_MAP,
+ int_map_mask, int_map_mask,
+ write_usleep);
+ if (ret) {
+ switch (pin) {
+ case BMI160_PIN_INT1:
+ pin_name = "INT1";
+ break;
+ case BMI160_PIN_INT2:
+ pin_name = "INT2";
+ break;
+ }
+ dev_err(dev, "Failed to configure %s IRQ pin", pin_name);
+ }
+
+ return ret;
+}
+
+int bmi160_enable_irq(struct regmap *regmap, bool enable)
+{
+ unsigned int enable_bit = 0;
+
+ if (enable)
+ enable_bit = BMI160_DRDY_INT_EN;
+
+ return bmi160_write_conf_reg(regmap, BMI160_REG_INT_EN,
+ BMI160_DRDY_INT_EN, enable_bit,
+ BMI160_NORMAL_WRITE_USLEEP);
+}
+EXPORT_SYMBOL(bmi160_enable_irq);
+
+static int bmi160_get_irq(struct device_node *of_node, enum bmi160_int_pin *pin)
+{
+ int irq;
+
+ /* Use INT1 if possible, otherwise fall back to INT2. */
+ irq = of_irq_get_byname(of_node, "INT1");
+ if (irq > 0) {
+ *pin = BMI160_PIN_INT1;
+ return irq;
+ }
+
+ irq = of_irq_get_byname(of_node, "INT2");
+ if (irq > 0)
+ *pin = BMI160_PIN_INT2;
+
+ return irq;
+}
+
+static int bmi160_config_device_irq(struct iio_dev *indio_dev, int irq_type,
+ enum bmi160_int_pin pin)
+{
+ bool open_drain;
+ u8 irq_mask;
+ struct bmi160_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+
+ /* Level-triggered, active-low is the default if we set all zeroes. */
+ if (irq_type == IRQF_TRIGGER_RISING)
+ irq_mask = BMI160_ACTIVE_HIGH | BMI160_EDGE_TRIGGERED;
+ else if (irq_type == IRQF_TRIGGER_FALLING)
+ irq_mask = BMI160_EDGE_TRIGGERED;
+ else if (irq_type == IRQF_TRIGGER_HIGH)
+ irq_mask = BMI160_ACTIVE_HIGH;
+ else if (irq_type == IRQF_TRIGGER_LOW)
+ irq_mask = 0;
+ else {
+ dev_err(&indio_dev->dev,
+ "Invalid interrupt type 0x%x specified\n", irq_type);
+ return -EINVAL;
+ }
+
+ open_drain = of_property_read_bool(dev->of_node, "drive-open-drain");
+
+ return bmi160_config_pin(data->regmap, pin, open_drain, irq_mask,
+ BMI160_NORMAL_WRITE_USLEEP);
+}
+
+static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq,
+ enum bmi160_int_pin pin)
+{
+ struct irq_data *desc;
+ u32 irq_type;
+ int ret;
+
+ desc = irq_get_irq_data(irq);
+ if (!desc) {
+ dev_err(&indio_dev->dev, "Could not find IRQ %d\n", irq);
+ return -EINVAL;
+ }
+
+ irq_type = irqd_get_trigger_type(desc);
+
+ ret = bmi160_config_device_irq(indio_dev, irq_type, pin);
+ if (ret)
+ return ret;
+
+ return bmi160_probe_trigger(indio_dev, irq, irq_type);
+}
+
static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
{
int ret;
@@ -505,7 +710,7 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
struct device *dev = regmap_get_device(data->regmap);
ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET);
- if (ret < 0)
+ if (ret)
return ret;
usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1);
@@ -516,12 +721,12 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
*/
if (use_spi) {
ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val);
- if (ret < 0)
+ if (ret)
return ret;
}
ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val);
- if (ret < 0) {
+ if (ret) {
dev_err(dev, "Error reading chip id\n");
return ret;
}
@@ -532,16 +737,59 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
}
ret = bmi160_set_mode(data, BMI160_ACCEL, true);
- if (ret < 0)
+ if (ret)
return ret;
ret = bmi160_set_mode(data, BMI160_GYRO, true);
- if (ret < 0)
+ if (ret)
return ret;
return 0;
}
+static int bmi160_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool enable)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct bmi160_data *data = iio_priv(indio_dev);
+
+ return bmi160_enable_irq(data->regmap, enable);
+}
+
+static const struct iio_trigger_ops bmi160_trigger_ops = {
+ .set_trigger_state = &bmi160_data_rdy_trigger_set_state,
+};
+
+int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type)
+{
+ struct bmi160_data *data = iio_priv(indio_dev);
+ int ret;
+
+ data->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+
+ if (data->trig == NULL)
+ return -ENOMEM;
+
+ ret = devm_request_irq(&indio_dev->dev, irq,
+ &iio_trigger_generic_data_rdy_poll,
+ irq_type, "bmi160", data->trig);
+ if (ret)
+ return ret;
+
+ data->trig->dev.parent = regmap_get_device(data->regmap);
+ data->trig->ops = &bmi160_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+
+ ret = devm_iio_trigger_register(&indio_dev->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ return 0;
+}
+
static void bmi160_chip_uninit(void *data)
{
struct bmi160_data *bmi_data = data;
@@ -555,6 +803,8 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
{
struct iio_dev *indio_dev;
struct bmi160_data *data;
+ int irq;
+ enum bmi160_int_pin int_pin;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@@ -566,11 +816,11 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
data->regmap = regmap;
ret = bmi160_chip_init(data, use_spi);
- if (ret < 0)
+ if (ret)
return ret;
ret = devm_add_action_or_reset(dev, bmi160_chip_uninit, data);
- if (ret < 0)
+ if (ret)
return ret;
if (!name && ACPI_HANDLE(dev))
@@ -583,16 +833,23 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmi160_info;
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
bmi160_trigger_handler, NULL);
- if (ret < 0)
+ if (ret)
return ret;
- ret = devm_iio_device_register(dev, indio_dev);
- if (ret < 0)
- return ret;
+ irq = bmi160_get_irq(dev->of_node, &int_pin);
+ if (irq > 0) {
+ ret = bmi160_setup_irq(indio_dev, irq, int_pin);
+ if (ret)
+ dev_err(&indio_dev->dev, "Failed to setup IRQ %d\n",
+ irq);
+ } else {
+ dev_info(&indio_dev->dev, "Not setting up IRQ trigger\n");
+ }
- return 0;
+ return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_GPL(bmi160_core_probe);
diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c
index 5b1f7e6af651..e36f5e82d400 100644
--- a/drivers/iio/imu/bmi160/bmi160_i2c.c
+++ b/drivers/iio/imu/bmi160/bmi160_i2c.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* BMI160 - Bosch IMU, I2C bits
*
* Copyright (c) 2016, Intel Corporation.
*
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License. See the file COPYING in the main
- * directory of this archive for more details.
- *
* 7-bit I2C slave address is:
* - 0x68 if SDO is pulled to GND
* - 0x69 if SDO is pulled to VDDIO
diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c
index e521ad14eeac..c19e3df35559 100644
--- a/drivers/iio/imu/bmi160/bmi160_spi.c
+++ b/drivers/iio/imu/bmi160/bmi160_spi.c
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* BMI160 - Bosch IMU, SPI bits
*
* Copyright (c) 2016, Intel Corporation.
*
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License. See the file COPYING in the main
- * directory of this archive for more details.
*/
#include <linux/acpi.h>
#include <linux/module.h>
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index 5483b2ea754d..d2fe9dbddda7 100644
--- a/drivers/iio/imu/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -13,8 +13,8 @@ config INV_MPU6050_I2C
select INV_MPU6050_IIO
select REGMAP_I2C
help
- This driver supports the Invensense MPU6050/6500/9150 and ICM20608
- motion tracking devices over I2C.
+ This driver supports the Invensense MPU6050/6500/9150 and
+ ICM20608/20602 motion tracking devices over I2C.
This driver can be built as a module. The module will be called
inv-mpu6050-i2c.
@@ -24,7 +24,7 @@ config INV_MPU6050_SPI
select INV_MPU6050_IIO
select REGMAP_SPI
help
- This driver supports the Invensense MPU6050/6500/9150 and ICM20608
- motion tracking devices over SPI.
+ This driver supports the Invensense MPU6050/6500/9150 and
+ ICM20608/20602 motion tracking devices over SPI.
This driver can be built as a module. The module will be called
inv-mpu6050-spi.
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 1e428c196a82..650de0fefb7b 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -38,6 +38,29 @@ static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};
*/
static const int accel_scale[] = {598, 1196, 2392, 4785};
+static const struct inv_mpu6050_reg_map reg_set_icm20602 = {
+ .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,
+ .accl_config = INV_MPU6050_REG_ACCEL_CONFIG,
+ .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H,
+ .fifo_r_w = INV_MPU6050_REG_FIFO_R_W,
+ .raw_gyro = INV_MPU6050_REG_RAW_GYRO,
+ .raw_accl = INV_MPU6050_REG_RAW_ACCEL,
+ .temperature = INV_MPU6050_REG_TEMPERATURE,
+ .int_enable = INV_MPU6050_REG_INT_ENABLE,
+ .int_status = INV_MPU6050_REG_INT_STATUS,
+ .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1,
+ .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2,
+ .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG,
+ .accl_offset = INV_MPU6500_REG_ACCEL_OFFSET,
+ .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET,
+ .i2c_if = INV_ICM20602_REG_I2C_IF,
+};
+
static const struct inv_mpu6050_reg_map reg_set_6500 = {
.sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
.lpf = INV_MPU6050_REG_CONFIG,
@@ -58,6 +81,7 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = {
.int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG,
.accl_offset = INV_MPU6500_REG_ACCEL_OFFSET,
.gyro_offset = INV_MPU6050_REG_GYRO_OFFSET,
+ .i2c_if = 0,
};
static const struct inv_mpu6050_reg_map reg_set_6050 = {
@@ -78,6 +102,7 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
.int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG,
.accl_offset = INV_MPU6050_REG_ACCEL_OFFSET,
.gyro_offset = INV_MPU6050_REG_GYRO_OFFSET,
+ .i2c_if = 0,
};
static const struct inv_mpu6050_chip_config chip_config_6050 = {
@@ -140,6 +165,12 @@ static const struct inv_mpu6050_hw hw_info[] = {
.reg = &reg_set_6500,
.config = &chip_config_6050,
},
+ {
+ .whoami = INV_ICM20602_WHOAMI_VALUE,
+ .name = "ICM20602",
+ .reg = &reg_set_icm20602,
+ .config = &chip_config_6050,
+ },
};
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index dd758e3d403d..e46eb4ddea21 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -127,6 +127,7 @@ static int inv_mpu_probe(struct i2c_client *client,
st = iio_priv(dev_get_drvdata(&client->dev));
switch (st->chip_type) {
case INV_ICM20608:
+ case INV_ICM20602:
/* no i2c auxiliary bus on the chip */
break;
default:
@@ -179,6 +180,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"mpu9250", INV_MPU9250},
{"mpu9255", INV_MPU9255},
{"icm20608", INV_ICM20608},
+ {"icm20602", INV_ICM20602},
{}
};
@@ -213,6 +215,10 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,icm20608",
.data = (void *)INV_ICM20608
},
+ {
+ .compatible = "invensense,icm20602",
+ .data = (void *)INV_ICM20602
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 6bcc11fc1b88..325afd9f5f61 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -44,6 +44,7 @@
* @int_pin_cfg; Controls interrupt pin configuration.
* @accl_offset: Controls the accelerometer calibration offset.
* @gyro_offset: Controls the gyroscope calibration offset.
+ * @i2c_if: Controls the i2c interface
*/
struct inv_mpu6050_reg_map {
u8 sample_rate_div;
@@ -65,6 +66,7 @@ struct inv_mpu6050_reg_map {
u8 int_pin_cfg;
u8 accl_offset;
u8 gyro_offset;
+ u8 i2c_if;
};
/*device enum */
@@ -77,6 +79,7 @@ enum inv_devices {
INV_MPU9250,
INV_MPU9255,
INV_ICM20608,
+ INV_ICM20602,
INV_NUM_PARTS
};
@@ -195,6 +198,10 @@ struct inv_mpu6050_state {
#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38
#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07
+/* ICM20602 register */
+#define INV_ICM20602_REG_I2C_IF 0x70
+#define INV_ICM20602_BIT_I2C_IF_DIS 0x40
+
#define INV_MPU6050_REG_FIFO_COUNT_H 0x72
#define INV_MPU6050_REG_FIFO_R_W 0x74
@@ -261,6 +268,7 @@ struct inv_mpu6050_state {
#define INV_MPU9255_WHOAMI_VALUE 0x73
#define INV_MPU6515_WHOAMI_VALUE 0x74
#define INV_ICM20608_WHOAMI_VALUE 0xAF
+#define INV_ICM20602_WHOAMI_VALUE 0x12
/* scan element definition */
enum inv_mpu6050_scan {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 227f50afff22..a112c3f45f74 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -31,9 +31,14 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev)
if (ret)
return ret;
- st->chip_config.user_ctrl |= INV_MPU6050_BIT_I2C_IF_DIS;
- ret = regmap_write(st->map, st->reg->user_ctrl,
- st->chip_config.user_ctrl);
+ if (st->reg->i2c_if) {
+ ret = regmap_write(st->map, st->reg->i2c_if,
+ INV_ICM20602_BIT_I2C_IF_DIS);
+ } else {
+ st->chip_config.user_ctrl |= INV_MPU6050_BIT_I2C_IF_DIS;
+ ret = regmap_write(st->map, st->reg->user_ctrl,
+ st->chip_config.user_ctrl);
+ }
if (ret) {
inv_mpu6050_set_power_itg(st, false);
return ret;
@@ -81,6 +86,7 @@ static const struct spi_device_id inv_mpu_id[] = {
{"mpu9250", INV_MPU9250},
{"mpu9255", INV_MPU9255},
{"icm20608", INV_ICM20608},
+ {"icm20602", INV_ICM20602},
{}
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
index 8e47dccdd40f..66fbcd94642d 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
@@ -105,12 +105,10 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
static int st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 addr,
u8 *data, int len)
{
- const struct st_lsm6dsx_shub_settings *hub_settings;
int err;
mutex_lock(&hw->page_lock);
- hub_settings = &hw->settings->shub_settings;
err = st_lsm6dsx_set_page(hw, true);
if (err < 0)
goto out;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 4f5cd9f60870..4700fd5d8c90 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -87,6 +87,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_GRAVITY] = "gravity",
[IIO_POSITIONRELATIVE] = "positionrelative",
[IIO_PHASE] = "phase",
+ [IIO_MASSCONCENTRATION] = "massconcentration",
};
static const char * const iio_modifier_names[] = {
@@ -127,6 +128,10 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+ [IIO_MOD_PM1] = "pm1",
+ [IIO_MOD_PM2P5] = "pm2p5",
+ [IIO_MOD_PM4] = "pm4",
+ [IIO_MOD_PM10] = "pm10",
};
/* relies on pairs of these shared then separate */
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 36f458433480..5190eacfeb0a 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -299,6 +299,16 @@ config MAX44000
To compile this driver as a module, choose M here:
the module will be called max44000.
+config MAX44009
+ tristate "MAX44009 Ambient Light Sensor"
+ depends on I2C
+ help
+ Say Y here if you want to build support for Maxim Integrated's
+ MAX44009 ambient light sensor device.
+
+ To compile this driver as a module, choose M here:
+ the module will be called max44009.
+
config OPT3001
tristate "Texas Instruments OPT3001 Light Sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 286bf3975372..e40794fbb435 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_LV0104CS) += lv0104cs.o
obj-$(CONFIG_MAX44000) += max44000.o
+obj-$(CONFIG_MAX44009) += max44009.o
obj-$(CONFIG_OPT3001) += opt3001.o
obj-$(CONFIG_PA12203001) += pa12203001.o
obj-$(CONFIG_RPR0521) += rpr0521.o
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index b45400f8fef4..846df4dce48c 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -23,6 +23,7 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -95,6 +96,7 @@ struct isl29018_chip {
struct isl29018_scale scale;
int prox_scheme;
bool suspended;
+ struct regulator *vcc_reg;
};
static int isl29018_set_integration_time(struct isl29018_chip *chip,
@@ -708,6 +710,16 @@ static const char *isl29018_match_acpi_device(struct device *dev, int *data)
return dev_name(dev);
}
+static void isl29018_disable_regulator_action(void *_data)
+{
+ struct isl29018_chip *chip = _data;
+ int err;
+
+ err = regulator_disable(chip->vcc_reg);
+ if (err)
+ pr_err("failed to disable isl29018's VCC regulator!\n");
+}
+
static int isl29018_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -742,6 +754,27 @@ static int isl29018_probe(struct i2c_client *client,
chip->scale = isl29018_scales[chip->int_time][0];
chip->suspended = false;
+ chip->vcc_reg = devm_regulator_get(&client->dev, "vcc");
+ if (IS_ERR(chip->vcc_reg)) {
+ err = PTR_ERR(chip->vcc_reg);
+ if (err != -EPROBE_DEFER)
+ dev_err(&client->dev, "failed to get VCC regulator!\n");
+ return err;
+ }
+
+ err = regulator_enable(chip->vcc_reg);
+ if (err) {
+ dev_err(&client->dev, "failed to enable VCC regulator!\n");
+ return err;
+ }
+
+ err = devm_add_action_or_reset(&client->dev, isl29018_disable_regulator_action,
+ chip);
+ if (err) {
+ dev_err(&client->dev, "failed to setup regulator cleanup action!\n");
+ return err;
+ }
+
chip->regmap = devm_regmap_init_i2c(client,
isl29018_chip_info_tbl[dev_id].regmap_cfg);
if (IS_ERR(chip->regmap)) {
@@ -768,6 +801,7 @@ static int isl29018_probe(struct i2c_client *client,
static int isl29018_suspend(struct device *dev)
{
struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+ int ret;
mutex_lock(&chip->lock);
@@ -777,10 +811,13 @@ static int isl29018_suspend(struct device *dev)
* So we do not have much to do here.
*/
chip->suspended = true;
+ ret = regulator_disable(chip->vcc_reg);
+ if (ret)
+ dev_err(dev, "failed to disable VCC regulator\n");
mutex_unlock(&chip->lock);
- return 0;
+ return ret;
}
static int isl29018_resume(struct device *dev)
@@ -790,6 +827,13 @@ static int isl29018_resume(struct device *dev)
mutex_lock(&chip->lock);
+ err = regulator_enable(chip->vcc_reg);
+ if (err) {
+ dev_err(dev, "failed to enable VCC regulator\n");
+ mutex_unlock(&chip->lock);
+ return err;
+ }
+
err = isl29018_chip_init(chip);
if (!err)
chip->suspended = false;
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
new file mode 100644
index 000000000000..00ba15499638
--- /dev/null
+++ b/drivers/iio/light/max44009.c
@@ -0,0 +1,555 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * max44009.c - Support for MAX44009 Ambient Light Sensor
+ *
+ * Copyright (c) 2019 Robert Eshleman <bobbyeshleman@gmail.com>
+ *
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX44009.pdf
+ *
+ * TODO: Support continuous mode and configuring from manual mode to
+ * automatic mode.
+ *
+ * Default I2C address: 0x4a
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/util_macros.h>
+
+#define MAX44009_DRV_NAME "max44009"
+
+/* Registers in datasheet order */
+#define MAX44009_REG_INT_STATUS 0x0
+#define MAX44009_REG_INT_EN 0x1
+#define MAX44009_REG_CFG 0x2
+#define MAX44009_REG_LUX_HI 0x3
+#define MAX44009_REG_LUX_LO 0x4
+#define MAX44009_REG_UPPER_THR 0x5
+#define MAX44009_REG_LOWER_THR 0x6
+#define MAX44009_REG_THR_TIMER 0x7
+
+#define MAX44009_CFG_TIM_MASK GENMASK(2, 0)
+#define MAX44009_CFG_MAN_MODE_MASK BIT(6)
+
+/* The maximum rising threshold for the max44009 */
+#define MAX44009_MAXIMUM_THRESHOLD 7520256
+
+#define MAX44009_THRESH_EXP_MASK (0xf << 4)
+#define MAX44009_THRESH_EXP_RSHIFT 4
+#define MAX44009_THRESH_MANT_LSHIFT 4
+#define MAX44009_THRESH_MANT_MASK 0xf
+
+#define MAX44009_UPPER_THR_MINIMUM 15
+
+/* The max44009 always scales raw readings by 0.045 and is non-configurable */
+#define MAX44009_SCALE_NUMERATOR 45
+#define MAX44009_SCALE_DENOMINATOR 1000
+
+/* The fixed-point fractional multiplier for de-scaling threshold values */
+#define MAX44009_FRACT_MULT 1000000
+
+static const u32 max44009_int_time_ns_array[] = {
+ 800000000,
+ 400000000,
+ 200000000,
+ 100000000,
+ 50000000, /* Manual mode only */
+ 25000000, /* Manual mode only */
+ 12500000, /* Manual mode only */
+ 6250000, /* Manual mode only */
+};
+
+static const char max44009_int_time_str[] =
+ "0.8 "
+ "0.4 "
+ "0.2 "
+ "0.1 "
+ "0.05 "
+ "0.025 "
+ "0.0125 "
+ "0.00625";
+
+struct max44009_data {
+ struct i2c_client *client;
+ struct mutex lock;
+};
+
+static const struct iio_event_spec max44009_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+static const struct iio_chan_spec max44009_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ .event_spec = max44009_event_spec,
+ .num_event_specs = ARRAY_SIZE(max44009_event_spec),
+ },
+};
+
+static int max44009_read_int_time(struct max44009_data *data)
+{
+
+ int ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_CFG);
+
+ if (ret < 0)
+ return ret;
+
+ return max44009_int_time_ns_array[ret & MAX44009_CFG_TIM_MASK];
+}
+
+static int max44009_write_int_time(struct max44009_data *data,
+ int val, int val2)
+{
+ struct i2c_client *client = data->client;
+ int ret, int_time, config;
+ s64 ns;
+
+ ns = val * NSEC_PER_SEC + val2;
+ int_time = find_closest_descending(
+ ns,
+ max44009_int_time_ns_array,
+ ARRAY_SIZE(max44009_int_time_ns_array));
+
+ ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG);
+ if (ret < 0)
+ return ret;
+
+ config = ret;
+ config &= int_time;
+
+ /*
+ * To set the integration time, the device must also be in manual
+ * mode.
+ */
+ config |= MAX44009_CFG_MAN_MODE_MASK;
+
+ return i2c_smbus_write_byte_data(client, MAX44009_REG_CFG, config);
+}
+
+static int max44009_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) {
+ mutex_lock(&data->lock);
+ ret = max44009_write_int_time(data, val, val2);
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+ return -EINVAL;
+}
+
+static int max44009_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int max44009_lux_raw(u8 hi, u8 lo)
+{
+ int mantissa;
+ int exponent;
+
+ /*
+ * The mantissa consists of the low nibble of the Lux High Byte
+ * and the low nibble of the Lux Low Byte.
+ */
+ mantissa = ((hi & 0xf) << 4) | (lo & 0xf);
+
+ /* The exponent byte is just the upper nibble of the Lux High Byte */
+ exponent = (hi >> 4) & 0xf;
+
+ /*
+ * The exponent value is base 2 to the power of the raw exponent byte.
+ */
+ exponent = 1 << exponent;
+
+ return exponent * mantissa;
+}
+
+#define MAX44009_READ_LUX_XFER_LEN (4)
+
+static int max44009_read_lux_raw(struct max44009_data *data)
+{
+ int ret;
+ u8 hireg = MAX44009_REG_LUX_HI;
+ u8 loreg = MAX44009_REG_LUX_LO;
+ u8 lo = 0;
+ u8 hi = 0;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = data->client->addr,
+ .flags = 0,
+ .len = sizeof(hireg),
+ .buf = &hireg,
+ },
+ {
+ .addr = data->client->addr,
+ .flags = I2C_M_RD,
+ .len = sizeof(hi),
+ .buf = &hi,
+ },
+ {
+ .addr = data->client->addr,
+ .flags = 0,
+ .len = sizeof(loreg),
+ .buf = &loreg,
+ },
+ {
+ .addr = data->client->addr,
+ .flags = I2C_M_RD,
+ .len = sizeof(lo),
+ .buf = &lo,
+ }
+ };
+
+ /*
+ * Use i2c_transfer instead of smbus read because i2c_transfer
+ * does NOT use a stop bit between address write and data read.
+ * Using a stop bit causes disjoint upper/lower byte reads and
+ * reduces accuracy.
+ */
+ ret = i2c_transfer(data->client->adapter,
+ msgs, MAX44009_READ_LUX_XFER_LEN);
+
+ if (ret != MAX44009_READ_LUX_XFER_LEN)
+ return -EIO;
+
+ return max44009_lux_raw(hi, lo);
+}
+
+static int max44009_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+ int lux_raw;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = max44009_read_lux_raw(data);
+ if (ret < 0)
+ return ret;
+ lux_raw = ret;
+
+ *val = lux_raw * MAX44009_SCALE_NUMERATOR;
+ *val2 = MAX44009_SCALE_DENOMINATOR;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_INT_TIME:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = max44009_read_int_time(data);
+ if (ret < 0)
+ return ret;
+
+ *val2 = ret;
+ *val = 0;
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static IIO_CONST_ATTR(illuminance_integration_time_available,
+ max44009_int_time_str);
+
+static struct attribute *max44009_attributes[] = {
+ &iio_const_attr_illuminance_integration_time_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group max44009_attribute_group = {
+ .attrs = max44009_attributes,
+};
+
+static int max44009_threshold_byte_from_fraction(int integral, int fractional)
+{
+ int mantissa, exp;
+
+ if ((integral <= 0 && fractional <= 0) ||
+ integral > MAX44009_MAXIMUM_THRESHOLD ||
+ (integral == MAX44009_MAXIMUM_THRESHOLD && fractional != 0))
+ return -EINVAL;
+
+ /* Reverse scaling of fixed-point integral */
+ mantissa = integral * MAX44009_SCALE_DENOMINATOR;
+ mantissa /= MAX44009_SCALE_NUMERATOR;
+
+ /* Reverse scaling of fixed-point fractional */
+ mantissa += fractional / MAX44009_FRACT_MULT *
+ (MAX44009_SCALE_DENOMINATOR / MAX44009_SCALE_NUMERATOR);
+
+ for (exp = 0; mantissa > 0xff; exp++)
+ mantissa >>= 1;
+
+ mantissa >>= 4;
+ mantissa &= 0xf;
+ exp <<= 4;
+
+ return exp | mantissa;
+}
+
+static int max44009_get_thr_reg(enum iio_event_direction dir)
+{
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return MAX44009_REG_UPPER_THR;
+ case IIO_EV_DIR_FALLING:
+ return MAX44009_REG_LOWER_THR;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int max44009_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+ int reg, threshold;
+
+ if (info != IIO_EV_INFO_VALUE || chan->type != IIO_LIGHT)
+ return -EINVAL;
+
+ threshold = max44009_threshold_byte_from_fraction(val, val2);
+ if (threshold < 0)
+ return threshold;
+
+ reg = max44009_get_thr_reg(dir);
+ if (reg < 0)
+ return reg;
+
+ return i2c_smbus_write_byte_data(data->client, reg, threshold);
+}
+
+static int max44009_read_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+ int byte, reg;
+ int mantissa, exponent;
+
+ reg = max44009_get_thr_reg(dir);
+ if (reg < 0)
+ return reg;
+
+ byte = i2c_smbus_read_byte_data(data->client, reg);
+ if (byte < 0)
+ return byte;
+
+ mantissa = byte & MAX44009_THRESH_MANT_MASK;
+ mantissa <<= MAX44009_THRESH_MANT_LSHIFT;
+
+ /*
+ * To get the upper threshold, always adds the minimum upper threshold
+ * value to the shifted byte value (see datasheet).
+ */
+ if (dir == IIO_EV_DIR_RISING)
+ mantissa += MAX44009_UPPER_THR_MINIMUM;
+
+ /*
+ * Exponent is base 2 to the power of the threshold exponent byte
+ * value
+ */
+ exponent = byte & MAX44009_THRESH_EXP_MASK;
+ exponent >>= MAX44009_THRESH_EXP_RSHIFT;
+
+ return (1 << exponent) * mantissa;
+}
+
+static int max44009_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ int ret;
+ int threshold;
+
+ if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ ret = max44009_read_threshold(indio_dev, dir);
+ if (ret < 0)
+ return ret;
+ threshold = ret;
+
+ *val = threshold * MAX44009_SCALE_NUMERATOR;
+ *val2 = MAX44009_SCALE_DENOMINATOR;
+
+ return IIO_VAL_FRACTIONAL;
+}
+
+static int max44009_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ MAX44009_REG_INT_EN, state);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Set device to trigger interrupt immediately upon exceeding
+ * the threshold limit.
+ */
+ return i2c_smbus_write_byte_data(data->client,
+ MAX44009_REG_THR_TIMER, 0);
+}
+
+static int max44009_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct max44009_data *data = iio_priv(indio_dev);
+
+ if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ return i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_EN);
+}
+
+static const struct iio_info max44009_info = {
+ .read_raw = max44009_read_raw,
+ .write_raw = max44009_write_raw,
+ .write_raw_get_fmt = max44009_write_raw_get_fmt,
+ .read_event_value = max44009_read_event_value,
+ .read_event_config = max44009_read_event_config,
+ .write_event_value = max44009_write_event_value,
+ .write_event_config = max44009_write_event_config,
+ .attrs = &max44009_attribute_group,
+};
+
+static irqreturn_t max44009_threaded_irq_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct max44009_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_STATUS);
+ if (ret) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int max44009_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max44009_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &max44009_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = MAX44009_DRV_NAME;
+ indio_dev->channels = max44009_channels;
+ indio_dev->num_channels = ARRAY_SIZE(max44009_channels);
+ mutex_init(&data->lock);
+
+ /* Clear any stale interrupt bit */
+ ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG);
+ if (ret < 0)
+ return ret;
+
+ if (client->irq > 0) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL,
+ max44009_threaded_irq_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT | IRQF_SHARED,
+ "max44009_event",
+ indio_dev);
+ if (ret < 0)
+ return ret;
+ }
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id max44009_id[] = {
+ { "max44009", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max44009_id);
+
+static struct i2c_driver max44009_driver = {
+ .driver = {
+ .name = MAX44009_DRV_NAME,
+ },
+ .probe = max44009_probe,
+ .id_table = max44009_id,
+};
+module_i2c_driver(max44009_driver);
+
+static const struct of_device_id max44009_of_match[] = {
+ { .compatible = "maxim,max44009" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max44009_of_match);
+
+MODULE_AUTHOR("Robert Eshleman <bobbyeshleman@gmail.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX44009 ambient light sensor driver");
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
index f063355480ba..dd990cdb04a8 100644
--- a/drivers/iio/magnetometer/mag3110.c
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -20,6 +20,7 @@
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
#define MAG3110_STATUS 0x00
#define MAG3110_OUT_X 0x01 /* MSB first */
@@ -56,6 +57,8 @@ struct mag3110_data {
struct mutex lock;
u8 ctrl_reg1;
int sleep_val;
+ struct regulator *vdd_reg;
+ struct regulator *vddio_reg;
};
static int mag3110_request(struct mag3110_data *data)
@@ -469,17 +472,50 @@ static int mag3110_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int ret;
- ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
- if (ret < 0)
- return ret;
- if (ret != MAG3110_DEVICE_ID)
- return -ENODEV;
-
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
+
+ data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(data->vdd_reg)) {
+ if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&client->dev, "failed to get VDD regulator!\n");
+ return PTR_ERR(data->vdd_reg);
+ }
+
+ data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
+ if (IS_ERR(data->vddio_reg)) {
+ if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_err(&client->dev, "failed to get VDDIO regulator!\n");
+ return PTR_ERR(data->vddio_reg);
+ }
+
+ ret = regulator_enable(data->vdd_reg);
+ if (ret) {
+ dev_err(&client->dev, "failed to enable VDD regulator!\n");
+ return ret;
+ }
+
+ ret = regulator_enable(data->vddio_reg);
+ if (ret) {
+ dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
+ goto disable_regulator_vdd;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
+ if (ret < 0)
+ goto disable_regulators;
+ if (ret != MAG3110_DEVICE_ID) {
+ ret = -ENODEV;
+ goto disable_regulators;
+ }
+
data->client = client;
mutex_init(&data->lock);
@@ -499,7 +535,7 @@ static int mag3110_probe(struct i2c_client *client,
ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1);
if (ret < 0)
- return ret;
+ goto disable_regulators;
ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
MAG3110_CTRL_AUTO_MRST_EN);
@@ -520,16 +556,24 @@ buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
standby_on_error:
mag3110_standby(iio_priv(indio_dev));
+disable_regulators:
+ regulator_disable(data->vddio_reg);
+disable_regulator_vdd:
+ regulator_disable(data->vdd_reg);
+
return ret;
}
static int mag3110_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct mag3110_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
mag3110_standby(iio_priv(indio_dev));
+ regulator_disable(data->vddio_reg);
+ regulator_disable(data->vdd_reg);
return 0;
}
@@ -537,14 +581,48 @@ static int mag3110_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
static int mag3110_suspend(struct device *dev)
{
- return mag3110_standby(iio_priv(i2c_get_clientdata(
+ struct mag3110_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ int ret;
+
+ ret = mag3110_standby(iio_priv(i2c_get_clientdata(
to_i2c_client(dev))));
+ if (ret)
+ return ret;
+
+ ret = regulator_disable(data->vddio_reg);
+ if (ret) {
+ dev_err(dev, "failed to disable VDDIO regulator\n");
+ return ret;
+ }
+
+ ret = regulator_disable(data->vdd_reg);
+ if (ret) {
+ dev_err(dev, "failed to disable VDD regulator\n");
+ return ret;
+ }
+
+ return 0;
}
static int mag3110_resume(struct device *dev)
{
struct mag3110_data *data = iio_priv(i2c_get_clientdata(
to_i2c_client(dev)));
+ int ret;
+
+ ret = regulator_enable(data->vdd_reg);
+ if (ret) {
+ dev_err(dev, "failed to enable VDD regulator\n");
+ return ret;
+ }
+
+ ret = regulator_enable(data->vddio_reg);
+ if (ret) {
+ dev_err(dev, "failed to enable VDDIO regulator\n");
+ regulator_disable(data->vdd_reg);
+ return ret;
+ }
return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
data->ctrl_reg1);
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index eaa7cfcb4c2a..efeb89f3df71 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -165,7 +165,7 @@ config IIO_ST_PRESS
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help
Say yes here to build support for STMicroelectronics pressure
- sensors: LPS001WP, LPS25H, LPS331AP, LPS22HB.
+ sensors: LPS001WP, LPS25H, LPS331AP, LPS22HB, LPS22HH.
This driver can also be built as a module. If so, these modules
will be created:
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index e67eb0d971bf..57946605f3ba 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -21,6 +21,7 @@ enum st_press_type {
LPS22HB,
LPS33HW,
LPS35HW,
+ LPS22HH,
ST_PRESS_MAX,
};
@@ -30,6 +31,7 @@ enum st_press_type {
#define LPS22HB_PRESS_DEV_NAME "lps22hb"
#define LPS33HW_PRESS_DEV_NAME "lps33hw"
#define LPS35HW_PRESS_DEV_NAME "lps35hw"
+#define LPS22HH_PRESS_DEV_NAME "lps22hh"
/**
* struct st_sensors_platform_data - default press platform data
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 4ddb6cf7d401..38dcdb7c000e 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -492,6 +492,75 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.multi_read_bit = false,
.bootime = 2,
},
+ {
+ /*
+ * CUSTOM VALUES FOR LPS22HH SENSOR
+ * See LPS22HH datasheet:
+ * http://www2.st.com/resource/en/datasheet/lps22hh.pdf
+ */
+ .wai = 0xb3,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+ .sensors_supported = {
+ [0] = LPS22HH_PRESS_DEV_NAME,
+ },
+ .ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
+ .num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
+ .odr = {
+ .addr = 0x10,
+ .mask = 0x70,
+ .odr_avl = {
+ { .hz = 1, .value = 0x01 },
+ { .hz = 10, .value = 0x02 },
+ { .hz = 25, .value = 0x03 },
+ { .hz = 50, .value = 0x04 },
+ { .hz = 75, .value = 0x05 },
+ { .hz = 100, .value = 0x06 },
+ { .hz = 200, .value = 0x07 },
+ },
+ },
+ .pw = {
+ .addr = 0x10,
+ .mask = 0x70,
+ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+ },
+ .fs = {
+ .fs_avl = {
+ /*
+ * Pressure and temperature sensitivity values
+ * as defined in table 3 of LPS22HH datasheet.
+ */
+ [0] = {
+ .num = ST_PRESS_FS_AVL_1260MB,
+ .gain = ST_PRESS_KPASCAL_NANO_SCALE,
+ .gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS,
+ },
+ },
+ },
+ .bdu = {
+ .addr = 0x10,
+ .mask = BIT(1),
+ },
+ .drdy_irq = {
+ .int1 = {
+ .addr = 0x12,
+ .mask = BIT(2),
+ .addr_od = 0x11,
+ .mask_od = BIT(5),
+ },
+ .addr_ihl = 0x11,
+ .mask_ihl = BIT(6),
+ .stat_drdy = {
+ .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
+ .mask = 0x03,
+ },
+ },
+ .sim = {
+ .addr = 0x10,
+ .value = BIT(0),
+ },
+ .multi_read_bit = false,
+ .bootime = 2,
+ },
};
static int st_press_write_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 2026a1012012..a60849dd4ea7 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -45,6 +45,10 @@ static const struct of_device_id st_press_of_match[] = {
.compatible = "st,lps35hw",
.data = LPS35HW_PRESS_DEV_NAME,
},
+ {
+ .compatible = "st,lps22hh",
+ .data = LPS22HH_PRESS_DEV_NAME,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_press_of_match);
@@ -69,6 +73,7 @@ static const struct i2c_device_id st_press_id_table[] = {
{ LPS22HB_PRESS_DEV_NAME, LPS22HB },
{ LPS33HW_PRESS_DEV_NAME, LPS33HW },
{ LPS35HW_PRESS_DEV_NAME, LPS35HW },
+ { LPS22HH_PRESS_DEV_NAME, LPS22HH },
{},
};
MODULE_DEVICE_TABLE(i2c, st_press_id_table);
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 9a3441b128e7..79a12ed46e54 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -49,6 +49,10 @@ static const struct of_device_id st_press_of_match[] = {
.compatible = "st,lps35hw",
.data = LPS35HW_PRESS_DEV_NAME,
},
+ {
+ .compatible = "st,lps22hh",
+ .data = LPS22HH_PRESS_DEV_NAME,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_press_of_match);
@@ -93,6 +97,7 @@ static const struct spi_device_id st_press_id_table[] = {
{ LPS22HB_PRESS_DEV_NAME },
{ LPS33HW_PRESS_DEV_NAME },
{ LPS35HW_PRESS_DEV_NAME },
+ { LPS22HH_PRESS_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_press_id_table);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 63a7cc00bae0..84f077b2b90a 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
id_priv->id.route.addr.dev_addr.transport =
rdma_node_get_transport(cma_dev->device->node_type);
list_add_tail(&id_priv->list, &cma_dev->id_list);
- rdma_restrack_kadd(&id_priv->res);
+ if (id_priv->res.kern_name)
+ rdma_restrack_kadd(&id_priv->res);
+ else
+ rdma_restrack_uadd(&id_priv->res);
}
static void cma_attach_to_dev(struct rdma_id_private *id_priv,
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 3cd830d52967..616734313f0c 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
#endif
struct ib_device *ib_device_get_by_index(u32 ifindex);
-void ib_device_put(struct ib_device *device);
/* RDMA device netlink */
void nldev_init(void);
void nldev_exit(void);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8872453e26c0..238ec42778ef 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
down_read(&lists_rwsem);
device = __ib_device_get_by_index(index);
if (device) {
- /* Do not return a device if unregistration has started. */
- if (!refcount_inc_not_zero(&device->refcount))
+ if (!ib_device_try_get(device))
device = NULL;
}
up_read(&lists_rwsem);
return device;
}
+/**
+ * ib_device_put - Release IB device reference
+ * @device: device whose reference to be released
+ *
+ * ib_device_put() releases reference to the IB device to allow it to be
+ * unregistered and eventually free.
+ */
void ib_device_put(struct ib_device *device)
{
if (refcount_dec_and_test(&device->refcount))
complete(&device->unreg_completion);
}
+EXPORT_SYMBOL(ib_device_put);
static struct ib_device *__ib_device_get_by_name(const char *name)
{
@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
rwlock_init(&device->client_data_lock);
INIT_LIST_HEAD(&device->client_data_list);
INIT_LIST_HEAD(&device->port_list);
- refcount_set(&device->refcount, 1);
init_completion(&device->unreg_completion);
return device;
@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
goto cg_cleanup;
}
+ refcount_set(&device->refcount, 1);
device->reg_state = IB_DEV_REGISTERED;
list_for_each_entry(client, &client_list, list)
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index e600fc23ae62..3c97a8b6bf1e 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
goto err;
- if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&
- nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
- pd->unsafe_global_rkey))
- goto err;
if (fill_res_name_pid(msg, res))
goto err;
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index be6b8e1257d0..69f8db66925e 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
enum uverbs_obj_access access,
bool commit);
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
+
void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index a4ec43093cb3..acb882f279cb 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
umem->writable = 1;
umem->is_odp = 1;
odp_data->per_mm = per_mm;
+ umem->owning_mm = per_mm->mm;
+ mmgrab(umem->owning_mm);
mutex_init(&odp_data->umem_mutex);
init_completion(&odp_data->notifier_completion);
@@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
out_page_list:
vfree(odp_data->page_list);
out_odp_data:
+ mmdrop(umem->owning_mm);
kfree(odp_data);
return ERR_PTR(ret);
}
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6b12cc5f97b2..3317300ab036 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
{
int ret;
+ if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+ return uverbs_copy_to_struct_or_zero(
+ attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len);
+
if (copy_to_user(attrs->ucore.outbuf, resp,
min(attrs->ucore.outlen, resp_len)))
return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
goto out_put;
}
+ if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+ ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
+
ret = 0;
out_put:
@@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
return -ENOMEM;
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
- if (!qp)
+ if (!qp) {
+ ret = -EINVAL;
goto out;
+ }
is_ud = qp->qp_type == IB_QPT_UD;
sg_ind = 0;
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 8c81ff698052..0ca04d224015 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
0, uattr->len - len);
}
+static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
+ const struct uverbs_attr *attr)
+{
+ struct bundle_priv *pbundle =
+ container_of(bundle, struct bundle_priv, bundle);
+ u16 flags;
+
+ flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
+ UVERBS_ATTR_F_VALID_OUTPUT;
+ if (put_user(flags,
+ &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
+ return -EFAULT;
+ return 0;
+}
+
static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
const struct uverbs_api_attr *attr_uapi,
struct uverbs_objs_arr_attr *attr,
@@ -456,6 +471,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
}
/*
+ * Until the drivers are revised to use the bundle directly we have to
+ * assume that the driver wrote to its UHW_OUT and flag userspace
+ * appropriately.
+ */
+ if (!ret && pbundle->method_elm->has_udata) {
+ const struct uverbs_attr *attr =
+ uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
+
+ if (!IS_ERR(attr))
+ ret = uverbs_set_output(&pbundle->bundle, attr);
+ }
+
+ /*
* EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
* not invoke the method because the request is not supported. No
* other cases should return this code.
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
const void *from, size_t size)
{
- struct bundle_priv *pbundle =
- container_of(bundle, struct bundle_priv, bundle);
const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
- u16 flags;
size_t min_size;
if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
return -EFAULT;
- flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
- UVERBS_ATTR_F_VALID_OUTPUT;
- if (put_user(flags,
- &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
- return -EFAULT;
-
- return 0;
+ return uverbs_set_output(bundle, attr);
}
EXPORT_SYMBOL(uverbs_copy_to);
+
+/*
+ * This is only used if the caller has directly used copy_to_use to write the
+ * data. It signals to user space that the buffer is filled in.
+ */
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx)
+{
+ const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
+
+ if (IS_ERR(attr))
+ return PTR_ERR(attr);
+
+ return uverbs_set_output(bundle, attr);
+}
+
int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
size_t idx, s64 lower_bound, u64 upper_bound,
s64 *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
{
const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
- if (clear_user(u64_to_user_ptr(attr->ptr_attr.data),
- attr->ptr_attr.len))
- return -EFAULT;
+ if (size < attr->ptr_attr.len) {
+ if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
+ attr->ptr_attr.len - size))
+ return -EFAULT;
+ }
return uverbs_copy_to(bundle, idx, from, size);
}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index fb0007aa0c27..5f366838b7ff 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref)
if (atomic_dec_and_test(&file->device->refcount))
ib_uverbs_comp_dev(file->device);
+ if (file->async_file)
+ kref_put(&file->async_file->ref,
+ ib_uverbs_release_async_event_file);
put_device(&file->device->dev);
kfree(file);
}
@@ -690,6 +693,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
buf += sizeof(hdr);
+ memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
bundle.ufile = file;
if (!method_elm->is_ex) {
size_t in_len = hdr.in_words * 4 - sizeof(hdr);
@@ -963,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
/* Get an arbitrary mm pointer that hasn't been cleaned yet */
mutex_lock(&ufile->umap_lock);
- if (!list_empty(&ufile->umaps)) {
- mm = list_first_entry(&ufile->umaps,
- struct rdma_umap_priv, list)
- ->vma->vm_mm;
- mmget(mm);
+ while (!list_empty(&ufile->umaps)) {
+ int ret;
+
+ priv = list_first_entry(&ufile->umaps,
+ struct rdma_umap_priv, list);
+ mm = priv->vma->vm_mm;
+ ret = mmget_not_zero(mm);
+ if (!ret) {
+ list_del_init(&priv->list);
+ mm = NULL;
+ continue;
+ }
+ break;
}
mutex_unlock(&ufile->umap_lock);
if (!mm)
@@ -1095,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
list_del_init(&file->list);
mutex_unlock(&file->device->lists_mutex);
- if (file->async_file)
- kref_put(&file->async_file->ref,
- ib_uverbs_release_async_event_file);
-
kref_put(&file->ref, ib_uverbs_release_file);
return 0;
diff --git a/drivers/infiniband/core/uverbs_std_types_device.c b/drivers/infiniband/core/uverbs_std_types_device.c
index 5030ec480370..2a3f2f01028d 100644
--- a/drivers/infiniband/core/uverbs_std_types_device.c
+++ b/drivers/infiniband/core/uverbs_std_types_device.c
@@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr,
static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
struct uverbs_attr_bundle *attrs)
{
- struct ib_device *ib_dev = attrs->ufile->device->ib_dev;
+ struct ib_device *ib_dev;
struct ib_port_attr attr = {};
struct ib_uverbs_query_port_resp_ex resp = {};
+ struct ib_ucontext *ucontext;
int ret;
u8 port_num;
+ ucontext = ib_uverbs_get_ucontext(attrs);
+ if (IS_ERR(ucontext))
+ return PTR_ERR(ucontext);
+ ib_dev = ucontext->device;
+
/* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
if (!ib_dev->ops.query_port)
return -EOPNOTSUPP;
diff --git a/drivers/infiniband/hw/bnxt_re/Kconfig b/drivers/infiniband/hw/bnxt_re/Kconfig
index 18f5ed082f41..19982a4a9bba 100644
--- a/drivers/infiniband/hw/bnxt_re/Kconfig
+++ b/drivers/infiniband/hw/bnxt_re/Kconfig
@@ -1,7 +1,6 @@
config INFINIBAND_BNXT_RE
tristate "Broadcom Netxtreme HCA support"
depends on ETHERNET && NETDEVICES && PCI && INET && DCB
- depends on MAY_USE_DEVLINK
select NET_VENDOR_BROADCOM
select BNXT
---help---
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 326805461265..19551aa43850 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -766,8 +766,8 @@ struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
return NULL;
sbuf->size = size;
- sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
- &sbuf->dma_addr, GFP_ATOMIC);
+ sbuf->sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf->size,
+ &sbuf->dma_addr, GFP_ATOMIC);
if (!sbuf->sb)
goto bail;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 59eeac55626f..57d4951679cb 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -105,10 +105,10 @@ static int __alloc_pbl(struct pci_dev *pdev, struct bnxt_qplib_pbl *pbl,
if (!sghead) {
for (i = 0; i < pages; i++) {
- pbl->pg_arr[i] = dma_zalloc_coherent(&pdev->dev,
- pbl->pg_size,
- &pbl->pg_map_arr[i],
- GFP_KERNEL);
+ pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
+ pbl->pg_size,
+ &pbl->pg_map_arr[i],
+ GFP_KERNEL);
if (!pbl->pg_arr[i])
goto fail;
pbl->pg_count++;
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index df4f7a3f043d..8ac72ac7cbac 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -291,9 +291,9 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
if (!wq->sq)
goto err3;
- wq->queue = dma_zalloc_coherent(&(rdev_p->rnic_info.pdev->dev),
- depth * sizeof(union t3_wr),
- &(wq->dma_addr), GFP_KERNEL);
+ wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
+ depth * sizeof(union t3_wr),
+ &(wq->dma_addr), GFP_KERNEL);
if (!wq->queue)
goto err4;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index c13c0ba30f63..d499cd61c0e8 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -783,6 +783,7 @@ void c4iw_init_dev_ucontext(struct c4iw_rdev *rdev,
static int c4iw_rdev_open(struct c4iw_rdev *rdev)
{
int err;
+ unsigned int factor;
c4iw_init_dev_ucontext(rdev, &rdev->uctx);
@@ -806,8 +807,18 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
return -EINVAL;
}
- rdev->qpmask = rdev->lldi.udb_density - 1;
- rdev->cqmask = rdev->lldi.ucq_density - 1;
+ /* This implementation requires a sge_host_page_size <= PAGE_SIZE. */
+ if (rdev->lldi.sge_host_page_size > PAGE_SIZE) {
+ pr_err("%s: unsupported sge host page size %u\n",
+ pci_name(rdev->lldi.pdev),
+ rdev->lldi.sge_host_page_size);
+ return -EINVAL;
+ }
+
+ factor = PAGE_SIZE / rdev->lldi.sge_host_page_size;
+ rdev->qpmask = (rdev->lldi.udb_density * factor) - 1;
+ rdev->cqmask = (rdev->lldi.ucq_density * factor) - 1;
+
pr_debug("dev %s stag start 0x%0x size 0x%0x num stags %d pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x qp qid start %u size %u cq qid start %u size %u srq size %u\n",
pci_name(rdev->lldi.pdev), rdev->lldi.vr->stag.start,
rdev->lldi.vr->stag.size, c4iw_num_stags(rdev),
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 981ff5cfb5d1..504cf525508f 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -2564,9 +2564,8 @@ static int alloc_srq_queue(struct c4iw_srq *srq, struct c4iw_dev_ucontext *uctx,
wq->rqt_abs_idx = (wq->rqt_hwaddr - rdev->lldi.vr->rq.start) >>
T4_RQT_ENTRY_SHIFT;
- wq->queue = dma_zalloc_coherent(&rdev->lldi.pdev->dev,
- wq->memsize, &wq->dma_addr,
- GFP_KERNEL);
+ wq->queue = dma_alloc_coherent(&rdev->lldi.pdev->dev, wq->memsize,
+ &wq->dma_addr, GFP_KERNEL);
if (!wq->queue)
goto err_free_rqtpool;
diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c
index 2baf38cc1e23..4fe662c3bbc1 100644
--- a/drivers/infiniband/hw/hfi1/affinity.c
+++ b/drivers/infiniband/hw/hfi1/affinity.c
@@ -48,6 +48,7 @@
#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/numa.h>
#include "hfi.h"
#include "affinity.h"
@@ -777,7 +778,7 @@ void hfi1_dev_affinity_clean_up(struct hfi1_devdata *dd)
_dev_comp_vect_cpu_mask_clean_up(dd, entry);
unlock:
mutex_unlock(&node_affinity.lock);
- dd->node = -1;
+ dd->node = NUMA_NO_NODE;
}
/*
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index c22ebc774a6a..f9a7e9d29c8b 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
vmf = 1;
break;
case STATUS:
- if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+ if (flags & VM_WRITE) {
ret = -EPERM;
goto done;
}
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index 09044905284f..441b06e2a154 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -54,6 +54,7 @@
#include <linux/printk.h>
#include <linux/hrtimer.h>
#include <linux/bitmap.h>
+#include <linux/numa.h>
#include <rdma/rdma_vt.h>
#include "hfi.h"
@@ -899,10 +900,10 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit)
goto done;
/* allocate dummy tail memory for all receive contexts */
- dd->rcvhdrtail_dummy_kvaddr = dma_zalloc_coherent(
- &dd->pcidev->dev, sizeof(u64),
- &dd->rcvhdrtail_dummy_dma,
- GFP_KERNEL);
+ dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+ sizeof(u64),
+ &dd->rcvhdrtail_dummy_dma,
+ GFP_KERNEL);
if (!dd->rcvhdrtail_dummy_kvaddr) {
dd_dev_err(dd, "cannot allocate dummy tail memory\n");
@@ -1303,7 +1304,7 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev,
dd->unit = ret;
list_add(&dd->list, &hfi1_dev_list);
}
- dd->node = -1;
+ dd->node = NUMA_NO_NODE;
spin_unlock_irqrestore(&hfi1_devs_lock, flags);
idr_preload_end();
@@ -1863,9 +1864,9 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
gfp_flags = GFP_KERNEL;
else
gfp_flags = GFP_USER;
- rcd->rcvhdrq = dma_zalloc_coherent(
- &dd->pcidev->dev, amt, &rcd->rcvhdrq_dma,
- gfp_flags | __GFP_COMP);
+ rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt,
+ &rcd->rcvhdrq_dma,
+ gfp_flags | __GFP_COMP);
if (!rcd->rcvhdrq) {
dd_dev_err(dd,
@@ -1876,9 +1877,10 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ||
HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) {
- rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent(
- &dd->pcidev->dev, PAGE_SIZE,
- &rcd->rcvhdrqtailaddr_dma, gfp_flags);
+ rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+ PAGE_SIZE,
+ &rcd->rcvhdrqtailaddr_dma,
+ gfp_flags);
if (!rcd->rcvhdrtail_kvaddr)
goto bail_free;
}
@@ -1974,10 +1976,10 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
while (alloced_bytes < rcd->egrbufs.size &&
rcd->egrbufs.alloced < rcd->egrbufs.count) {
rcd->egrbufs.buffers[idx].addr =
- dma_zalloc_coherent(&dd->pcidev->dev,
- rcd->egrbufs.rcvtid_size,
- &rcd->egrbufs.buffers[idx].dma,
- gfp_flags);
+ dma_alloc_coherent(&dd->pcidev->dev,
+ rcd->egrbufs.rcvtid_size,
+ &rcd->egrbufs.buffers[idx].dma,
+ gfp_flags);
if (rcd->egrbufs.buffers[idx].addr) {
rcd->egrbufs.buffers[idx].len =
rcd->egrbufs.rcvtid_size;
diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
index dd5a5c030066..04126d7e318d 100644
--- a/drivers/infiniband/hw/hfi1/pio.c
+++ b/drivers/infiniband/hw/hfi1/pio.c
@@ -2098,11 +2098,10 @@ int init_credit_return(struct hfi1_devdata *dd)
int bytes = TXE_NUM_CONTEXTS * sizeof(struct credit_return);
set_dev_node(&dd->pcidev->dev, i);
- dd->cr_base[i].va = dma_zalloc_coherent(
- &dd->pcidev->dev,
- bytes,
- &dd->cr_base[i].dma,
- GFP_KERNEL);
+ dd->cr_base[i].va = dma_alloc_coherent(&dd->pcidev->dev,
+ bytes,
+ &dd->cr_base[i].dma,
+ GFP_KERNEL);
if (!dd->cr_base[i].va) {
set_dev_node(&dd->pcidev->dev, dd->node);
dd_dev_err(dd,
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index b84356e1a4c1..96897a91fb0a 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1453,12 +1453,9 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
timer_setup(&sde->err_progress_check_timer,
sdma_err_progress_check, 0);
- sde->descq = dma_zalloc_coherent(
- &dd->pcidev->dev,
- descq_cnt * sizeof(u64[2]),
- &sde->descq_phys,
- GFP_KERNEL
- );
+ sde->descq = dma_alloc_coherent(&dd->pcidev->dev,
+ descq_cnt * sizeof(u64[2]),
+ &sde->descq_phys, GFP_KERNEL);
if (!sde->descq)
goto bail;
sde->tx_ring =
@@ -1471,24 +1468,18 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
dd->sdma_heads_size = L1_CACHE_BYTES * num_engines;
/* Allocate memory for DMA of head registers to memory */
- dd->sdma_heads_dma = dma_zalloc_coherent(
- &dd->pcidev->dev,
- dd->sdma_heads_size,
- &dd->sdma_heads_phys,
- GFP_KERNEL
- );
+ dd->sdma_heads_dma = dma_alloc_coherent(&dd->pcidev->dev,
+ dd->sdma_heads_size,
+ &dd->sdma_heads_phys,
+ GFP_KERNEL);
if (!dd->sdma_heads_dma) {
dd_dev_err(dd, "failed to allocate SendDMA head memory\n");
goto bail;
}
/* Allocate memory for pad */
- dd->sdma_pad_dma = dma_zalloc_coherent(
- &dd->pcidev->dev,
- sizeof(u32),
- &dd->sdma_pad_phys,
- GFP_KERNEL
- );
+ dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32),
+ &dd->sdma_pad_phys, GFP_KERNEL);
if (!dd->sdma_pad_dma) {
dd_dev_err(dd, "failed to allocate SendDMA pad memory\n");
goto bail;
diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c
index 88242fe95eaa..bf96067876c9 100644
--- a/drivers/infiniband/hw/hfi1/ud.c
+++ b/drivers/infiniband/hw/hfi1/ud.c
@@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
wc.ex.imm_data = packet->ohdr->u.ud.imm_data;
wc.wc_flags = IB_WC_WITH_IMM;
- tlen -= sizeof(u32);
} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
wc.ex.imm_data = 0;
wc.wc_flags = 0;
diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c
index 6300033a448f..dac058d3df53 100644
--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
+++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
@@ -197,8 +197,8 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
buf->npages = 1 << order;
buf->page_shift = page_shift;
/* MTT PA must be recorded in 4k alignment, t is 4k aligned */
- buf->direct.buf = dma_zalloc_coherent(dev,
- size, &t, GFP_KERNEL);
+ buf->direct.buf = dma_alloc_coherent(dev, size, &t,
+ GFP_KERNEL);
if (!buf->direct.buf)
return -ENOMEM;
@@ -219,9 +219,10 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
return -ENOMEM;
for (i = 0; i < buf->nbufs; ++i) {
- buf->page_list[i].buf = dma_zalloc_coherent(dev,
- page_size, &t,
- GFP_KERNEL);
+ buf->page_list[i].buf = dma_alloc_coherent(dev,
+ page_size,
+ &t,
+ GFP_KERNEL);
if (!buf->page_list[i].buf)
goto err_free;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 3a669451cf86..543fa1504cd3 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -5091,7 +5091,7 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
eqe_alloc = i * (buf_chk_sz / eq->eqe_size);
size = (eq->entries - eqe_alloc) * eq->eqe_size;
}
- eq->buf[i] = dma_zalloc_coherent(dev, size,
+ eq->buf[i] = dma_alloc_coherent(dev, size,
&(eq->buf_dma[i]),
GFP_KERNEL);
if (!eq->buf[i])
@@ -5126,9 +5126,9 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
size = (eq->entries - eqe_alloc)
* eq->eqe_size;
}
- eq->buf[idx] = dma_zalloc_coherent(dev, size,
- &(eq->buf_dma[idx]),
- GFP_KERNEL);
+ eq->buf[idx] = dma_alloc_coherent(dev, size,
+ &(eq->buf_dma[idx]),
+ GFP_KERNEL);
if (!eq->buf[idx])
goto err_dma_alloc_buf;
@@ -5241,7 +5241,7 @@ static int hns_roce_v2_create_eq(struct hns_roce_dev *hr_dev,
goto free_cmd_mbox;
}
- eq->buf_list->buf = dma_zalloc_coherent(dev, buf_chk_sz,
+ eq->buf_list->buf = dma_alloc_coherent(dev, buf_chk_sz,
&(eq->buf_list->map),
GFP_KERNEL);
if (!eq->buf_list->buf) {
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
index 960b1946c365..12deacf442cf 100644
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
@@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
struct ib_udata *udata)
{
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
+ struct hns_roce_ib_create_srq_resp resp = {};
struct hns_roce_srq *srq;
int srq_desc_size;
int srq_buf_size;
@@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
srq->event = hns_roce_ib_srq_event;
srq->ibsrq.ext.xrc.srq_num = srq->srqn;
+ resp.srqn = srq->srqn;
if (udata) {
- if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
+ if (ib_copy_to_udata(udata, &resp,
+ min(udata->outlen, sizeof(resp)))) {
ret = -EFAULT;
- goto err_wrid;
+ goto err_srqc_alloc;
}
}
return &srq->ibsrq;
+err_srqc_alloc:
+ hns_roce_srq_free(hr_dev, srq);
+
err_wrid:
kvfree(srq->wrid);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c
index a9ea966877f2..59e978141ad4 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_utils.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c
@@ -745,8 +745,8 @@ enum i40iw_status_code i40iw_allocate_dma_mem(struct i40iw_hw *hw,
if (!mem)
return I40IW_ERR_PARAM;
mem->size = ALIGN(size, alignment);
- mem->va = dma_zalloc_coherent(&pcidev->dev, mem->size,
- (dma_addr_t *)&mem->pa, GFP_KERNEL);
+ mem->va = dma_alloc_coherent(&pcidev->dev, mem->size,
+ (dma_addr_t *)&mem->pa, GFP_KERNEL);
if (!mem->va)
return I40IW_ERR_NO_MEMORY;
return 0;
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index d1de3285fd88..4e9936731867 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -2,7 +2,6 @@ config MLX4_INFINIBAND
tristate "Mellanox ConnectX HCA support"
depends on NETDEVICES && ETHERNET && PCI && INET
depends on INFINIBAND_USER_ACCESS || !INFINIBAND_USER_ACCESS
- depends on MAY_USE_DEVLINK
select NET_VENDOR_MELLANOX
select MLX4_CORE
---help---
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 25439da8976c..936ee1314bcd 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
if (sqp->tx_ring[wire_tx_ix].ah)
- rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
+ mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
sqp->tx_ring[wire_tx_ix].ah = ah;
ib_dma_sync_single_for_cpu(&dev->ib_dev,
sqp->tx_ring[wire_tx_ix].buf.map,
@@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
if (wc.status == IB_WC_SUCCESS) {
switch (wc.opcode) {
case IB_WC_SEND:
- rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+ mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
(MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
= NULL;
@@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
" status = %d, wrid = 0x%llx\n",
ctx->slave, wc.status, wc.wr_id);
if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
- rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+ mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
(MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
= NULL;
diff --git a/drivers/infiniband/hw/mlx5/cmd.c b/drivers/infiniband/hw/mlx5/cmd.c
index 356bccc715ee..6bcc63aaa50b 100644
--- a/drivers/infiniband/hw/mlx5/cmd.c
+++ b/drivers/infiniband/hw/mlx5/cmd.c
@@ -345,3 +345,40 @@ int mlx5_cmd_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id,
counter_set_id);
return err;
}
+
+int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
+ u16 opmod, u8 port)
+{
+ int outlen = MLX5_ST_SZ_BYTES(mad_ifc_out);
+ int inlen = MLX5_ST_SZ_BYTES(mad_ifc_in);
+ int err = -ENOMEM;
+ void *data;
+ void *resp;
+ u32 *out;
+ u32 *in;
+
+ in = kzalloc(inlen, GFP_KERNEL);
+ out = kzalloc(outlen, GFP_KERNEL);
+ if (!in || !out)
+ goto out;
+
+ MLX5_SET(mad_ifc_in, in, opcode, MLX5_CMD_OP_MAD_IFC);
+ MLX5_SET(mad_ifc_in, in, op_mod, opmod);
+ MLX5_SET(mad_ifc_in, in, port, port);
+
+ data = MLX5_ADDR_OF(mad_ifc_in, in, mad);
+ memcpy(data, inb, MLX5_FLD_SZ_BYTES(mad_ifc_in, mad));
+
+ err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
+ if (err)
+ goto out;
+
+ resp = MLX5_ADDR_OF(mad_ifc_out, out, response_mad_packet);
+ memcpy(outb, resp,
+ MLX5_FLD_SZ_BYTES(mad_ifc_out, response_mad_packet));
+
+out:
+ kfree(out);
+ kfree(in);
+ return err;
+}
diff --git a/drivers/infiniband/hw/mlx5/cmd.h b/drivers/infiniband/hw/mlx5/cmd.h
index 1e76dc67a369..923a7b93f507 100644
--- a/drivers/infiniband/hw/mlx5/cmd.h
+++ b/drivers/infiniband/hw/mlx5/cmd.h
@@ -63,4 +63,6 @@ int mlx5_cmd_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn, u16 uid);
int mlx5_cmd_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn, u16 uid);
int mlx5_cmd_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id,
u16 uid);
+int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
+ u16 opmod, u8 port);
#endif /* MLX5_IB_CMD_H */
diff --git a/drivers/infiniband/hw/mlx5/flow.c b/drivers/infiniband/hw/mlx5/flow.c
index e8a1e4498e3f..798591a18484 100644
--- a/drivers/infiniband/hw/mlx5/flow.c
+++ b/drivers/infiniband/hw/mlx5/flow.c
@@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = {
UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
UAPI_DEF_CHAIN_OBJ_TREE(
UVERBS_OBJECT_FLOW,
- &mlx5_ib_fs,
- UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
+ &mlx5_ib_fs),
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
&mlx5_ib_flow_actions),
{},
diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c
index 46a9ddc8ca56..4700cffb5a00 100644
--- a/drivers/infiniband/hw/mlx5/ib_rep.c
+++ b/drivers/infiniband/hw/mlx5/ib_rep.c
@@ -3,10 +3,11 @@
* Copyright (c) 2018 Mellanox Technologies. All rights reserved.
*/
+#include <linux/mlx5/vport.h>
#include "ib_rep.h"
#include "srq.h"
-static const struct mlx5_ib_profile rep_profile = {
+static const struct mlx5_ib_profile vf_rep_profile = {
STAGE_CREATE(MLX5_IB_STAGE_INIT,
mlx5_ib_stage_init_init,
mlx5_ib_stage_init_cleanup),
@@ -46,30 +47,16 @@ static const struct mlx5_ib_profile rep_profile = {
};
static int
-mlx5_ib_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
-{
- struct mlx5_ib_dev *ibdev;
-
- ibdev = mlx5_ib_rep_to_dev(rep);
- if (!__mlx5_ib_add(ibdev, ibdev->profile))
- return -EINVAL;
- return 0;
-}
-
-static void
-mlx5_ib_nic_rep_unload(struct mlx5_eswitch_rep *rep)
-{
- struct mlx5_ib_dev *ibdev;
-
- ibdev = mlx5_ib_rep_to_dev(rep);
- __mlx5_ib_remove(ibdev, ibdev->profile, MLX5_IB_STAGE_MAX);
-}
-
-static int
mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
+ const struct mlx5_ib_profile *profile;
struct mlx5_ib_dev *ibdev;
+ if (rep->vport == MLX5_VPORT_UPLINK)
+ profile = &uplink_rep_profile;
+ else
+ profile = &vf_rep_profile;
+
ibdev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*ibdev));
if (!ibdev)
return -ENOMEM;
@@ -78,7 +65,7 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
ibdev->mdev = dev;
ibdev->num_ports = max(MLX5_CAP_GEN(dev, num_ports),
MLX5_CAP_GEN(dev, num_vhca_ports));
- if (!__mlx5_ib_add(ibdev, &rep_profile))
+ if (!__mlx5_ib_add(ibdev, profile))
return -EINVAL;
rep->rep_if[REP_IB].priv = ibdev;
@@ -105,53 +92,23 @@ static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
return mlx5_ib_rep_to_dev(rep);
}
-static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev)
-{
- struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
- int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
- int vport;
-
- for (vport = 1; vport < total_vfs; vport++) {
- struct mlx5_eswitch_rep_if rep_if = {};
-
- rep_if.load = mlx5_ib_vport_rep_load;
- rep_if.unload = mlx5_ib_vport_rep_unload;
- rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
- mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_IB);
- }
-}
-
-static void mlx5_ib_rep_unregister_vf_vports(struct mlx5_ib_dev *dev)
+void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev)
{
- struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
- int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
- int vport;
-
- for (vport = 1; vport < total_vfs; vport++)
- mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB);
-}
-
-void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev)
-{
- struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
struct mlx5_eswitch_rep_if rep_if = {};
- rep_if.load = mlx5_ib_nic_rep_load;
- rep_if.unload = mlx5_ib_nic_rep_unload;
+ rep_if.load = mlx5_ib_vport_rep_load;
+ rep_if.unload = mlx5_ib_vport_rep_unload;
rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
- rep_if.priv = dev;
-
- mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_IB);
- mlx5_ib_rep_register_vf_vports(dev);
+ mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_IB);
}
-void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev)
+void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev)
{
- struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
- mlx5_ib_rep_unregister_vf_vports(dev); /* VFs vports */
- mlx5_eswitch_unregister_vport_rep(esw, 0, REP_IB); /* UPLINK PF*/
+ mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
}
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
diff --git a/drivers/infiniband/hw/mlx5/ib_rep.h b/drivers/infiniband/hw/mlx5/ib_rep.h
index 2ba73636a2fb..798d41e61fb4 100644
--- a/drivers/infiniband/hw/mlx5/ib_rep.h
+++ b/drivers/infiniband/hw/mlx5/ib_rep.h
@@ -10,14 +10,16 @@
#include "mlx5_ib.h"
#ifdef CONFIG_MLX5_ESWITCH
+extern const struct mlx5_ib_profile uplink_rep_profile;
+
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw);
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
int vport_index);
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw);
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
int vport_index);
-void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev);
-void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev);
+void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev);
+void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev);
int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
struct mlx5_ib_sq *sq);
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
@@ -48,8 +50,8 @@ struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
return NULL;
}
-static inline void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev) {}
-static inline void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev) {}
+static inline void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev) {}
+static inline void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev) {}
static inline int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
struct mlx5_ib_sq *sq)
{
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
index 558638468edb..6c529e6f3a01 100644
--- a/drivers/infiniband/hw/mlx5/mad.c
+++ b/drivers/infiniband/hw/mlx5/mad.c
@@ -36,6 +36,7 @@
#include <rdma/ib_smi.h>
#include <rdma/ib_pma.h>
#include "mlx5_ib.h"
+#include "cmd.h"
enum {
MLX5_IB_VENDOR_CLASS1 = 0x9,
@@ -51,9 +52,10 @@ static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u8 port_num,
return dev->mdev->port_caps[port_num - 1].has_smi;
}
-int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
- u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
- const void *in_mad, void *response_mad)
+static int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey,
+ int ignore_bkey, u8 port, const struct ib_wc *in_wc,
+ const struct ib_grh *in_grh, const void *in_mad,
+ void *response_mad)
{
u8 op_modifier = 0;
@@ -68,7 +70,8 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
if (ignore_bkey || !in_wc)
op_modifier |= 0x2;
- return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port);
+ return mlx5_cmd_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier,
+ port);
}
static int process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 94fe253d4956..581ae11e2fc9 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -331,8 +331,8 @@ out:
spin_unlock(&port->mp.mpi_lock);
}
-static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed,
- u8 *active_width)
+static int translate_eth_legacy_proto_oper(u32 eth_proto_oper, u8 *active_speed,
+ u8 *active_width)
{
switch (eth_proto_oper) {
case MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII):
@@ -389,10 +389,66 @@ static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed,
return 0;
}
+static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u8 *active_speed,
+ u8 *active_width)
+{
+ switch (eth_proto_oper) {
+ case MLX5E_PROT_MASK(MLX5E_SGMII_100M):
+ case MLX5E_PROT_MASK(MLX5E_1000BASE_X_SGMII):
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_SDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_5GBASE_R):
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_DDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_10GBASE_XFI_XAUI_1):
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_QDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_40GBASE_XLAUI_4_XLPPI_4):
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_QDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_25GAUI_1_25GBASE_CR_KR):
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_EDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2):
+ case MLX5E_PROT_MASK(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR):
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_HDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_100GAUI_2_100GBASE_CR2_KR2):
+ *active_width = IB_WIDTH_2X;
+ *active_speed = IB_SPEED_HDR;
+ break;
+ case MLX5E_PROT_MASK(MLX5E_200GAUI_4_200GBASE_CR4_KR4):
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_HDR;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed,
+ u8 *active_width, bool ext)
+{
+ return ext ?
+ translate_eth_ext_proto_oper(eth_proto_oper, active_speed,
+ active_width) :
+ translate_eth_legacy_proto_oper(eth_proto_oper, active_speed,
+ active_width);
+}
+
static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
struct ib_port_attr *props)
{
struct mlx5_ib_dev *dev = to_mdev(device);
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
struct mlx5_core_dev *mdev;
struct net_device *ndev, *upper;
enum ib_mtu ndev_ib_mtu;
@@ -400,6 +456,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
u16 qkey_viol_cntr;
u32 eth_prot_oper;
u8 mdev_port_num;
+ bool ext;
int err;
mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
@@ -416,16 +473,18 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
/* Possible bad flows are checked before filling out props so in case
* of an error it will still be zeroed out.
*/
- err = mlx5_query_port_eth_proto_oper(mdev, &eth_prot_oper,
- mdev_port_num);
+ err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN,
+ mdev_port_num);
if (err)
goto out;
+ ext = MLX5_CAP_PCAM_FEATURE(dev->mdev, ptys_extended_ethernet);
+ eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
props->active_width = IB_WIDTH_4X;
props->active_speed = IB_SPEED_QDR;
translate_eth_proto_oper(eth_prot_oper, &props->active_speed,
- &props->active_width);
+ &props->active_width, ext);
props->port_cap_flags |= IB_PORT_CM_SUP;
props->ip_gids = true;
@@ -6386,7 +6445,7 @@ static const struct mlx5_ib_profile pf_profile = {
mlx5_ib_stage_delay_drop_cleanup),
};
-static const struct mlx5_ib_profile nic_rep_profile = {
+const struct mlx5_ib_profile uplink_rep_profile = {
STAGE_CREATE(MLX5_IB_STAGE_INIT,
mlx5_ib_stage_init_init,
mlx5_ib_stage_init_cleanup),
@@ -6479,6 +6538,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
printk_once(KERN_INFO "%s", mlx5_version);
+ if (MLX5_ESWITCH_MANAGER(mdev) &&
+ mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
+ mlx5_ib_register_vport_reps(mdev);
+ return mdev;
+ }
+
port_type_cap = MLX5_CAP_GEN(mdev, port_type);
ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
@@ -6493,14 +6558,6 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
MLX5_CAP_GEN(mdev, num_vhca_ports));
- if (MLX5_ESWITCH_MANAGER(mdev) &&
- mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
- dev->rep = mlx5_ib_vport_rep(mdev->priv.eswitch, 0);
- dev->profile = &nic_rep_profile;
- mlx5_ib_register_vport_reps(dev);
- return dev;
- }
-
return __mlx5_ib_add(dev, &pf_profile);
}
@@ -6509,6 +6566,11 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
struct mlx5_ib_multiport_info *mpi;
struct mlx5_ib_dev *dev;
+ if (MLX5_ESWITCH_MANAGER(mdev) && context == mdev) {
+ mlx5_ib_unregister_vport_reps(mdev);
+ return;
+ }
+
if (mlx5_core_is_mp_slave(mdev)) {
mpi = context;
mutex_lock(&mlx5_ib_multiport_mutex);
@@ -6520,10 +6582,7 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
}
dev = context;
- if (dev->profile == &nic_rep_profile)
- mlx5_ib_unregister_vport_reps(dev);
- else
- __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
+ __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
ib_dealloc_device((struct ib_device *)dev);
}
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index b06d3b1efea8..eedba0d2ec4b 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -587,6 +587,7 @@ struct mlx5_ib_mr {
struct mlx5_ib_mr *parent;
atomic_t num_leaf_free;
wait_queue_head_t q_leaf_free;
+ struct mlx5_async_work cb_work;
};
struct mlx5_ib_mw {
@@ -944,6 +945,7 @@ struct mlx5_ib_dev {
struct mlx5_memic memic;
u16 devx_whitelist_uid;
struct mlx5_srq_table srq_table;
+ struct mlx5_async_ctx async_ctx;
};
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
@@ -1038,9 +1040,6 @@ void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db)
void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
-int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
- u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
- const void *in_mad, void *response_mad);
struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
u32 flags, struct ib_udata *udata);
int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index fd6ea1f75085..bf2b6ea23851 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -123,9 +123,10 @@ static void update_odp_mr(struct mlx5_ib_mr *mr)
}
#endif
-static void reg_mr_callback(int status, void *context)
+static void reg_mr_callback(int status, struct mlx5_async_work *context)
{
- struct mlx5_ib_mr *mr = context;
+ struct mlx5_ib_mr *mr =
+ container_of(context, struct mlx5_ib_mr, cb_work);
struct mlx5_ib_dev *dev = mr->dev;
struct mlx5_mr_cache *cache = &dev->cache;
int c = order2idx(dev, mr->order);
@@ -216,9 +217,9 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
ent->pending++;
spin_unlock_irq(&ent->lock);
err = mlx5_core_create_mkey_cb(dev->mdev, &mr->mmkey,
- in, inlen,
+ &dev->async_ctx, in, inlen,
mr->out, sizeof(mr->out),
- reg_mr_callback, mr);
+ reg_mr_callback, &mr->cb_work);
if (err) {
spin_lock_irq(&ent->lock);
ent->pending--;
@@ -679,6 +680,7 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
return -ENOMEM;
}
+ mlx5_cmd_init_async_ctx(dev->mdev, &dev->async_ctx);
timer_setup(&dev->delay_timer, delay_time_func, 0);
for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
ent = &cache->ent[i];
@@ -725,33 +727,6 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
return 0;
}
-static void wait_for_async_commands(struct mlx5_ib_dev *dev)
-{
- struct mlx5_mr_cache *cache = &dev->cache;
- struct mlx5_cache_ent *ent;
- int total = 0;
- int i;
- int j;
-
- for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
- ent = &cache->ent[i];
- for (j = 0 ; j < 1000; j++) {
- if (!ent->pending)
- break;
- msleep(50);
- }
- }
- for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
- ent = &cache->ent[i];
- total += ent->pending;
- }
-
- if (total)
- mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total);
- else
- mlx5_ib_warn(dev, "done with all pending requests\n");
-}
-
int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
{
int i;
@@ -763,12 +738,12 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
flush_workqueue(dev->cache.wq);
mlx5_mr_cache_debugfs_cleanup(dev);
+ mlx5_cmd_cleanup_async_ctx(&dev->async_ctx);
for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
clean_keys(dev, i);
destroy_workqueue(dev->cache.wq);
- wait_for_async_commands(dev);
del_timer_sync(&dev->delay_timer);
return 0;
diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c
index 01e0f6200631..4ee32964e1dd 100644
--- a/drivers/infiniband/hw/mlx5/odp.c
+++ b/drivers/infiniband/hw/mlx5/odp.c
@@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
struct prefetch_mr_work *w =
container_of(work, struct prefetch_mr_work, work);
- if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
+ if (ib_device_try_get(&w->dev->ib_dev)) {
mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
w->num_sge);
-
+ ib_device_put(&w->dev->ib_dev);
+ }
+ put_device(&w->dev->ib_dev.dev);
kfree(w);
}
@@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
num_sge);
- if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
- return -ENODEV;
-
work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
if (!work)
return -ENOMEM;
memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
+ get_device(&dev->ib_dev.dev);
work->dev = dev;
work->pf_flags = pf_flags;
work->num_sge = num_sge;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index dd2ae640bc84..7db778d96ef5 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
}
if (!check_flags_mask(ucmd.flags,
+ MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
+ MLX5_QP_FLAG_BFREG_INDEX |
+ MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE |
+ MLX5_QP_FLAG_SCATTER_CQE |
MLX5_QP_FLAG_SIGNATURE |
- MLX5_QP_FLAG_SCATTER_CQE |
- MLX5_QP_FLAG_TUNNEL_OFFLOADS |
- MLX5_QP_FLAG_BFREG_INDEX |
- MLX5_QP_FLAG_TYPE_DCT |
- MLX5_QP_FLAG_TYPE_DCI |
- MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
- MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE))
+ MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC |
+ MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC |
+ MLX5_QP_FLAG_TUNNEL_OFFLOADS |
+ MLX5_QP_FLAG_TYPE_DCI |
+ MLX5_QP_FLAG_TYPE_DCT))
return -EINVAL;
err = get_qp_user_index(to_mucontext(pd->uobject->context),
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index cc9c0c8ccba3..112d2f38e0de 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -623,8 +623,9 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
page = dev->db_tab->page + end;
alloc:
- page->db_rec = dma_zalloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
- &page->mapping, GFP_KERNEL);
+ page->db_rec = dma_alloc_coherent(&dev->pdev->dev,
+ MTHCA_ICM_PAGE_SIZE, &page->mapping,
+ GFP_KERNEL);
if (!page->db_rec) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 82cb6b71ac7c..e3e9dd54caa2 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
{
struct mthca_ucontext *context;
- qp = kmalloc(sizeof *qp, GFP_KERNEL);
+ qp = kzalloc(sizeof(*qp), GFP_KERNEL);
if (!qp)
return ERR_PTR(-ENOMEM);
@@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
if (udata)
return ERR_PTR(-EINVAL);
- qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
+ qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
if (!qp)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 241a57a07485..097e5ab2a19f 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -380,8 +380,8 @@ static int ocrdma_alloc_q(struct ocrdma_dev *dev,
q->len = len;
q->entry_size = entry_size;
q->size = len * entry_size;
- q->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, q->size,
- &q->dma, GFP_KERNEL);
+ q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size, &q->dma,
+ GFP_KERNEL);
if (!q->va)
return -ENOMEM;
return 0;
@@ -1819,7 +1819,7 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
return -ENOMEM;
ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ,
OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
- cq->va = dma_zalloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
+ cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
if (!cq->va) {
status = -ENOMEM;
goto mem_err;
@@ -2209,7 +2209,7 @@ static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd,
qp->sq.max_cnt = max_wqe_allocated;
len = (hw_pages * hw_page_size);
- qp->sq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+ qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
if (!qp->sq.va)
return -EINVAL;
qp->sq.len = len;
@@ -2259,7 +2259,7 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd,
qp->rq.max_cnt = max_rqe_allocated;
len = (hw_pages * hw_page_size);
- qp->rq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+ qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
if (!qp->rq.va)
return -ENOMEM;
qp->rq.pa = pa;
@@ -2315,8 +2315,8 @@ static int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd,
if (dev->attr.ird == 0)
return 0;
- qp->ird_q_va = dma_zalloc_coherent(&pdev->dev, ird_q_len, &pa,
- GFP_KERNEL);
+ qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len, &pa,
+ GFP_KERNEL);
if (!qp->ird_q_va)
return -ENOMEM;
ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages,
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
index dd15474b19b7..6be0ea109138 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
@@ -73,8 +73,8 @@ bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev)
mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req),
sizeof(struct ocrdma_rdma_stats_resp));
- mem->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, mem->size,
- &mem->pa, GFP_KERNEL);
+ mem->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, mem->size,
+ &mem->pa, GFP_KERNEL);
if (!mem->va) {
pr_err("%s: stats mbox allocation failed\n", __func__);
return false;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index c46bed0c5513..287c332ff0e6 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -504,8 +504,8 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
INIT_LIST_HEAD(&ctx->mm_head);
mutex_init(&ctx->mm_list_lock);
- ctx->ah_tbl.va = dma_zalloc_coherent(&pdev->dev, map_len,
- &ctx->ah_tbl.pa, GFP_KERNEL);
+ ctx->ah_tbl.va = dma_alloc_coherent(&pdev->dev, map_len,
+ &ctx->ah_tbl.pa, GFP_KERNEL);
if (!ctx->ah_tbl.va) {
kfree(ctx);
return ERR_PTR(-ENOMEM);
@@ -838,7 +838,7 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr)
return -ENOMEM;
for (i = 0; i < mr->num_pbls; i++) {
- va = dma_zalloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
+ va = dma_alloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
if (!va) {
ocrdma_free_mr_pbl_tbl(dev, mr);
status = -ENOMEM;
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index b342a70e2814..e1ccf32b1c3d 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -556,8 +556,8 @@ static struct qedr_pbl *qedr_alloc_pbl_tbl(struct qedr_dev *dev,
return ERR_PTR(-ENOMEM);
for (i = 0; i < pbl_info->num_pbls; i++) {
- va = dma_zalloc_coherent(&pdev->dev, pbl_info->pbl_size,
- &pa, flags);
+ va = dma_alloc_coherent(&pdev->dev, pbl_info->pbl_size, &pa,
+ flags);
if (!va)
goto err;
diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c
index 868da0ece7ba..445ea19a2ec8 100644
--- a/drivers/infiniband/hw/qib/qib_ud.c
+++ b/drivers/infiniband/hw/qib/qib_ud.c
@@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr,
opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
wc.ex.imm_data = ohdr->u.ud.imm_data;
wc.wc_flags = IB_WC_WITH_IMM;
- tlen -= sizeof(u32);
} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
wc.ex.imm_data = 0;
wc.wc_flags = 0;
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
index 42b8685c997e..3c633ab58052 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
@@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
{
- return (enum pvrdma_wr_opcode)op;
+ switch (op) {
+ case IB_WR_RDMA_WRITE:
+ return PVRDMA_WR_RDMA_WRITE;
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ return PVRDMA_WR_RDMA_WRITE_WITH_IMM;
+ case IB_WR_SEND:
+ return PVRDMA_WR_SEND;
+ case IB_WR_SEND_WITH_IMM:
+ return PVRDMA_WR_SEND_WITH_IMM;
+ case IB_WR_RDMA_READ:
+ return PVRDMA_WR_RDMA_READ;
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ return PVRDMA_WR_ATOMIC_CMP_AND_SWP;
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ return PVRDMA_WR_ATOMIC_FETCH_AND_ADD;
+ case IB_WR_LSO:
+ return PVRDMA_WR_LSO;
+ case IB_WR_SEND_WITH_INV:
+ return PVRDMA_WR_SEND_WITH_INV;
+ case IB_WR_RDMA_READ_WITH_INV:
+ return PVRDMA_WR_RDMA_READ_WITH_INV;
+ case IB_WR_LOCAL_INV:
+ return PVRDMA_WR_LOCAL_INV;
+ case IB_WR_REG_MR:
+ return PVRDMA_WR_FAST_REG_MR;
+ case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
+ return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP;
+ case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
+ return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD;
+ case IB_WR_REG_SIG_MR:
+ return PVRDMA_WR_REG_SIG_MR;
+ default:
+ return PVRDMA_WR_ERROR;
+ }
}
static inline enum ib_wc_status pvrdma_wc_status_to_ib(
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
index eaa109dbc96a..39c37b6fd715 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
@@ -890,8 +890,8 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "device version %d, driver version %d\n",
dev->dsr_version, PVRDMA_VERSION);
- dev->dsr = dma_zalloc_coherent(&pdev->dev, sizeof(*dev->dsr),
- &dev->dsrbase, GFP_KERNEL);
+ dev->dsr = dma_alloc_coherent(&pdev->dev, sizeof(*dev->dsr),
+ &dev->dsrbase, GFP_KERNEL);
if (!dev->dsr) {
dev_err(&pdev->dev, "failed to allocate shared region\n");
ret = -ENOMEM;
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
index 3acf74cbe266..1ec3646087ba 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
wqe_hdr->ex.imm_data = wr->ex.imm_data;
+ if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) {
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto out;
+ }
+
switch (qp->ibqp.qp_type) {
case IB_QPT_GSI:
case IB_QPT_UD:
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index a1bd8cfc2c25..c6cc3e4ab71d 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -2910,6 +2910,8 @@ send:
goto op_err;
if (!ret)
goto rnr_nak;
+ if (wqe->length > qp->r_len)
+ goto inv_err;
break;
case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -3078,7 +3080,10 @@ op_err:
goto err;
inv_err:
- send_status = IB_WC_REM_INV_REQ_ERR;
+ send_status =
+ sqp->ibqp.qp_type == IB_QPT_RC ?
+ IB_WC_REM_INV_REQ_ERR :
+ IB_WC_SUCCESS;
wc.status = IB_WC_LOC_QP_OP_ERR;
goto err;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 1da119d901a9..73e808c1e6ad 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -248,7 +248,6 @@ struct ipoib_cm_tx {
struct list_head list;
struct net_device *dev;
struct ipoib_neigh *neigh;
- struct ipoib_path *path;
struct ipoib_tx_buf *tx_ring;
unsigned int tx_head;
unsigned int tx_tail;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 0428e01e8f69..aa9dcfc36cd3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
neigh->cm = tx;
tx->neigh = neigh;
- tx->path = path;
tx->dev = dev;
list_add(&tx->list, &priv->cm.start_list);
set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
@@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
neigh->daddr + QPN_AND_OPTIONS_OFFSET);
goto free_neigh;
}
- memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
+ memcpy(&pathrec, &path->pathrec, sizeof(pathrec));
spin_unlock_irqrestore(&priv->lock, flags);
netif_tx_unlock_bh(dev);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 31d91538bbf4..694324b37480 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3032,7 +3032,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(scmnd->device->host);
struct srp_rdma_ch *ch;
- int i, j;
u8 status;
shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
@@ -3044,15 +3043,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
if (status)
return FAILED;
- for (i = 0; i < target->ch_count; i++) {
- ch = &target->ch[i];
- for (j = 0; j < target->req_ring_size; ++j) {
- struct srp_request *req = &ch->req_ring[j];
-
- srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
- }
- }
-
return SUCCESS;
}
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index cfc8b94527b9..aa4e431cbcd3 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -252,6 +252,8 @@ static const struct xpad_device {
{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
+ { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
+ { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
@@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
+ XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4713957b0cbb..a878351f1643 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -420,7 +420,7 @@ config KEYBOARD_MPR121
config KEYBOARD_SNVS_PWRKEY
tristate "IMX SNVS Power Key Driver"
- depends on SOC_IMX6SX
+ depends on SOC_IMX6SX || SOC_IMX7D
depends on OF
help
This is the snvs powerkey driver for the Freescale i.MX application
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 312916f99597..73686c2460ce 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -75,9 +75,7 @@
struct cap11xx_led {
struct cap11xx_priv *priv;
struct led_classdev cdev;
- struct work_struct work;
u32 reg;
- enum led_brightness new_brightness;
};
#endif
@@ -233,30 +231,21 @@ static void cap11xx_input_close(struct input_dev *idev)
}
#ifdef CONFIG_LEDS_CLASS
-static void cap11xx_led_work(struct work_struct *work)
+static int cap11xx_led_set(struct led_classdev *cdev,
+ enum led_brightness value)
{
- struct cap11xx_led *led = container_of(work, struct cap11xx_led, work);
+ struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
struct cap11xx_priv *priv = led->priv;
- int value = led->new_brightness;
/*
- * All LEDs share the same duty cycle as this is a HW limitation.
- * Brightness levels per LED are either 0 (OFF) and 1 (ON).
+ * All LEDs share the same duty cycle as this is a HW
+ * limitation. Brightness levels per LED are either
+ * 0 (OFF) and 1 (ON).
*/
- regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL,
- BIT(led->reg), value ? BIT(led->reg) : 0);
-}
-
-static void cap11xx_led_set(struct led_classdev *cdev,
- enum led_brightness value)
-{
- struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
-
- if (led->new_brightness == value)
- return;
-
- led->new_brightness = value;
- schedule_work(&led->work);
+ return regmap_update_bits(priv->regmap,
+ CAP11XX_REG_LED_OUTPUT_CONTROL,
+ BIT(led->reg),
+ value ? BIT(led->reg) : 0);
}
static int cap11xx_init_leds(struct device *dev,
@@ -299,7 +288,7 @@ static int cap11xx_init_leds(struct device *dev,
led->cdev.default_trigger =
of_get_property(child, "linux,default-trigger", NULL);
led->cdev.flags = 0;
- led->cdev.brightness_set = cap11xx_led_set;
+ led->cdev.brightness_set_blocking = cap11xx_led_set;
led->cdev.max_brightness = 1;
led->cdev.brightness = LED_OFF;
@@ -312,8 +301,6 @@ static int cap11xx_init_leds(struct device *dev,
led->reg = reg;
led->priv = priv;
- INIT_WORK(&led->work, cap11xx_led_work);
-
error = devm_led_classdev_register(dev, &led->cdev);
if (error) {
of_node_put(child);
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index b20a5d044caa..b4db72f833ca 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -32,10 +32,6 @@
#include <linux/errno.h>
#include <linux/slab.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
#include <linux/platform_data/keyscan-davinci.h>
/* Key scan registers */
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 403452ef00e6..3d1cb7bf5e35 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -222,7 +222,7 @@ static void matrix_keypad_stop(struct input_dev *dev)
keypad->stopped = true;
spin_unlock_irq(&keypad->lock);
- flush_work(&keypad->work.work);
+ flush_delayed_work(&keypad->work);
/*
* matrix_keypad_scan() will leave IRQs enabled;
* we should disable them now.
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 43b86482dda0..d466bc07aebb 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -58,10 +58,9 @@ static unsigned char qt2160_key2code[] = {
struct qt2160_led {
struct qt2160_data *qt2160;
struct led_classdev cdev;
- struct work_struct work;
char name[32];
int id;
- enum led_brightness new_brightness;
+ enum led_brightness brightness;
};
#endif
@@ -74,7 +73,6 @@ struct qt2160_data {
u16 key_matrix;
#ifdef CONFIG_LEDS_CLASS
struct qt2160_led leds[QT2160_NUM_LEDS_X];
- struct mutex led_lock;
#endif
};
@@ -83,46 +81,39 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
#ifdef CONFIG_LEDS_CLASS
-static void qt2160_led_work(struct work_struct *work)
+static int qt2160_led_set(struct led_classdev *cdev,
+ enum led_brightness value)
{
- struct qt2160_led *led = container_of(work, struct qt2160_led, work);
+ struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
struct qt2160_data *qt2160 = led->qt2160;
struct i2c_client *client = qt2160->client;
- int value = led->new_brightness;
u32 drive, pwmen;
- mutex_lock(&qt2160->led_lock);
-
- drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
- pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
- if (value != LED_OFF) {
- drive |= (1 << led->id);
- pwmen |= (1 << led->id);
-
- } else {
- drive &= ~(1 << led->id);
- pwmen &= ~(1 << led->id);
- }
- qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
- qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
+ if (value != led->brightness) {
+ drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
+ pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
+ if (value != LED_OFF) {
+ drive |= BIT(led->id);
+ pwmen |= BIT(led->id);
- /*
- * Changing this register will change the brightness
- * of every LED in the qt2160. It's a HW limitation.
- */
- if (value != LED_OFF)
- qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
+ } else {
+ drive &= ~BIT(led->id);
+ pwmen &= ~BIT(led->id);
+ }
+ qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
+ qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
- mutex_unlock(&qt2160->led_lock);
-}
+ /*
+ * Changing this register will change the brightness
+ * of every LED in the qt2160. It's a HW limitation.
+ */
+ if (value != LED_OFF)
+ qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
-static void qt2160_led_set(struct led_classdev *cdev,
- enum led_brightness value)
-{
- struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
+ led->brightness = value;
+ }
- led->new_brightness = value;
- schedule_work(&led->work);
+ return 0;
}
#endif /* CONFIG_LEDS_CLASS */
@@ -293,20 +284,16 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
int ret;
int i;
- mutex_init(&qt2160->led_lock);
-
for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
struct qt2160_led *led = &qt2160->leds[i];
snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
led->cdev.name = led->name;
- led->cdev.brightness_set = qt2160_led_set;
+ led->cdev.brightness_set_blocking = qt2160_led_set;
led->cdev.brightness = LED_OFF;
led->id = i;
led->qt2160 = qt2160;
- INIT_WORK(&led->work, qt2160_led_work);
-
ret = led_classdev_register(&client->dev, &led->cdev);
if (ret < 0)
return ret;
@@ -324,10 +311,8 @@ static void qt2160_unregister_leds(struct qt2160_data *qt2160)
{
int i;
- for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
+ for (i = 0; i < QT2160_NUM_LEDS_X; i++)
led_classdev_unregister(&qt2160->leds[i].cdev);
- cancel_work_sync(&qt2160->leds[i].work);
- }
}
#else
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index babcfb165e4f..3b85631fde91 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -153,6 +153,8 @@ static int keyscan_probe(struct platform_device *pdev)
input_dev->id.bustype = BUS_HOST;
+ keypad_data->input_dev = input_dev;
+
error = keypad_matrix_key_parse_dt(keypad_data);
if (error)
return error;
@@ -168,8 +170,6 @@ static int keyscan_probe(struct platform_device *pdev)
input_set_drvdata(input_dev, keypad_data);
- keypad_data->input_dev = input_dev;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(keypad_data->base))
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index 094bddf56755..c1e66f45d552 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -22,7 +22,6 @@
#include <linux/io.h>
#include <linux/input-polldev.h>
#include <linux/i2c.h>
-#include <linux/workqueue.h>
#include <linux/leds.h>
#define APANEL_NAME "Fujitsu Application Panel"
@@ -59,8 +58,6 @@ struct apanel {
struct i2c_client *client;
unsigned short keymap[MAX_PANEL_KEYS];
u16 nkeys;
- u16 led_bits;
- struct work_struct led_work;
struct led_classdev mail_led;
};
@@ -109,25 +106,13 @@ static void apanel_poll(struct input_polled_dev *ipdev)
report_key(idev, ap->keymap[i]);
}
-/* Track state changes of LED */
-static void led_update(struct work_struct *work)
-{
- struct apanel *ap = container_of(work, struct apanel, led_work);
-
- i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits);
-}
-
-static void mail_led_set(struct led_classdev *led,
+static int mail_led_set(struct led_classdev *led,
enum led_brightness value)
{
struct apanel *ap = container_of(led, struct apanel, mail_led);
+ u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000;
- if (value != LED_OFF)
- ap->led_bits |= 0x8000;
- else
- ap->led_bits &= ~0x8000;
-
- schedule_work(&ap->led_work);
+ return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
}
static int apanel_remove(struct i2c_client *client)
@@ -179,7 +164,7 @@ static struct apanel apanel = {
},
.mail_led = {
.name = "mail:blue",
- .brightness_set = mail_led_set,
+ .brightness_set_blocking = mail_led_set,
},
};
@@ -235,7 +220,6 @@ static int apanel_probe(struct i2c_client *client,
if (err)
goto out3;
- INIT_WORK(&ap->led_work, led_update);
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
err = led_classdev_register(&client->dev, &ap->mail_led);
if (err)
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 1efcfdf9f8a8..dd9dd4e40827 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
idev->close = bma150_irq_close;
input_set_drvdata(idev, bma150);
+ bma150->input = idev;
+
error = input_register_device(idev);
if (error) {
input_free_device(idev);
return error;
}
- bma150->input = idev;
return 0;
}
@@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
bma150_init_input_device(bma150, ipoll_dev->input);
+ bma150->input_polled = ipoll_dev;
+ bma150->input = ipoll_dev->input;
+
error = input_register_polled_device(ipoll_dev);
if (error) {
input_free_polled_device(ipoll_dev);
return error;
}
- bma150->input_polled = ipoll_dev;
- bma150->input = ipoll_dev->input;
-
return 0;
}
diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c
index 55da191ae550..dbb6d9e1b947 100644
--- a/drivers/input/misc/pwm-vibra.c
+++ b/drivers/input/misc/pwm-vibra.c
@@ -34,6 +34,7 @@ struct pwm_vibrator {
struct work_struct play_work;
u16 level;
u32 direction_duty_cycle;
+ bool vcc_on;
};
static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
@@ -42,10 +43,13 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
struct pwm_state state;
int err;
- err = regulator_enable(vibrator->vcc);
- if (err) {
- dev_err(pdev, "failed to enable regulator: %d", err);
- return err;
+ if (!vibrator->vcc_on) {
+ err = regulator_enable(vibrator->vcc);
+ if (err) {
+ dev_err(pdev, "failed to enable regulator: %d", err);
+ return err;
+ }
+ vibrator->vcc_on = true;
}
pwm_get_state(vibrator->pwm, &state);
@@ -76,11 +80,14 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
{
- regulator_disable(vibrator->vcc);
-
if (vibrator->pwm_dir)
pwm_disable(vibrator->pwm_dir);
pwm_disable(vibrator->pwm);
+
+ if (vibrator->vcc_on) {
+ regulator_disable(vibrator->vcc);
+ vibrator->vcc_on = false;
+ }
}
static void pwm_vibrator_play_work(struct work_struct *work)
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 8ec483e8688b..26ec603fe220 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
+#include <linux/overflow.h>
#include <linux/input/mt.h>
#include "../input-compat.h"
@@ -405,7 +406,7 @@ static int uinput_open(struct inode *inode, struct file *file)
static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
const struct input_absinfo *abs)
{
- int min, max;
+ int min, max, range;
min = abs->minimum;
max = abs->maximum;
@@ -417,7 +418,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
return -EINVAL;
}
- if (abs->flat > max - min) {
+ if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
printk(KERN_DEBUG
"%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
UINPUT_NAME, code, abs->flat, min, max);
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index f322a1768fbb..225ae6980182 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -1336,7 +1336,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
static const struct acpi_device_id elan_acpi_id[] = {
{ "ELAN0000", 0 },
{ "ELAN0100", 0 },
- { "ELAN0501", 0 },
{ "ELAN0600", 0 },
{ "ELAN0602", 0 },
{ "ELAN0605", 0 },
@@ -1346,6 +1345,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
{ "ELAN060C", 0 },
{ "ELAN0611", 0 },
{ "ELAN0612", 0 },
+ { "ELAN0617", 0 },
{ "ELAN0618", 0 },
{ "ELAN061C", 0 },
{ "ELAN061D", 0 },
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 9fe075c137dc..a7f8b1614559 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1119,6 +1119,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
* Asus UX31 0x361f00 20, 15, 0e clickpad
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
* Avatar AVIU-145A2 0x361f00 ? clickpad
+ * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
+ * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
* 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
@@ -1171,6 +1173,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
},
},
+ {
+ /* Fujitsu H780 also has a middle button */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
+ },
+ },
#endif
{ }
};
diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c
index b36084710f69..a7cfab3db9ee 100644
--- a/drivers/input/serio/olpc_apsp.c
+++ b/drivers/input/serio/olpc_apsp.c
@@ -23,7 +23,6 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/clk.h>
/*
* The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
@@ -75,7 +74,6 @@ struct olpc_apsp {
struct serio *kbio;
struct serio *padio;
void __iomem *base;
- struct clk *clk;
int open_count;
int irq;
};
@@ -148,17 +146,11 @@ static int olpc_apsp_open(struct serio *port)
struct olpc_apsp *priv = port->port_data;
unsigned int tmp;
unsigned long l;
- int error;
if (priv->open_count++ == 0) {
- error = clk_prepare_enable(priv->clk);
- if (error)
- return error;
-
l = readl(priv->base + COMMAND_FIFO_STATUS);
if (!(l & CMD_STS_MASK)) {
dev_err(priv->dev, "SP cannot accept commands.\n");
- clk_disable_unprepare(priv->clk);
return -EIO;
}
@@ -179,8 +171,6 @@ static void olpc_apsp_close(struct serio *port)
/* Disable interrupt 0 */
tmp = readl(priv->base + PJ_INTERRUPT_MASK);
writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
-
- clk_disable_unprepare(priv->clk);
}
}
@@ -195,6 +185,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->dev = &pdev->dev;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->base)) {
@@ -206,10 +198,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
if (priv->irq < 0)
return priv->irq;
- priv->clk = devm_clk_get(&pdev->dev, "sp");
- if (IS_ERR(priv->clk))
- return PTR_ERR(priv->clk);
-
/* KEYBOARD */
kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!kb_serio)
@@ -248,7 +236,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
goto err_irq;
}
- priv->dev = &pdev->dev;
device_init_wakeup(priv->dev, 1);
platform_set_drvdata(pdev, priv);
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
index c62cceb97bb1..5e8d8384aa2a 100644
--- a/drivers/input/serio/ps2-gpio.c
+++ b/drivers/input/serio/ps2-gpio.c
@@ -76,6 +76,7 @@ static void ps2_gpio_close(struct serio *serio)
{
struct ps2_gpio_data *drvdata = serio->port_data;
+ flush_delayed_work(&drvdata->tx_work);
disable_irq(drvdata->irq);
}
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index af6027cc7bbf..068dbbc610fc 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -698,7 +698,7 @@ config TOUCHSCREEN_EDT_FT5X06
config TOUCHSCREEN_RASPBERRYPI_FW
tristate "Raspberry Pi's firmware base touch screen support"
- depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+ depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
help
Say Y here if you have the official Raspberry Pi 7 inch screen on
your system.
diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c
index f456c1125bd6..69881265d121 100644
--- a/drivers/input/touchscreen/raspberrypi-ts.c
+++ b/drivers/input/touchscreen/raspberrypi-ts.c
@@ -147,8 +147,8 @@ static int rpi_ts_probe(struct platform_device *pdev)
return -ENOMEM;
ts->pdev = pdev;
- ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
- GFP_KERNEL);
+ ts->fw_regs_va = dma_alloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
+ GFP_KERNEL);
if (!ts->fw_regs_va) {
dev_err(dev, "failed to dma_alloc_coherent\n");
return -ENOMEM;
diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
new file mode 100644
index 000000000000..07a8276fa35a
--- /dev/null
+++ b/drivers/interconnect/Kconfig
@@ -0,0 +1,15 @@
+menuconfig INTERCONNECT
+ tristate "On-Chip Interconnect management support"
+ help
+ Support for management of the on-chip interconnects.
+
+ This framework is designed to provide a generic interface for
+ managing the interconnects in a SoC.
+
+ If unsure, say no.
+
+if INTERCONNECT
+
+source "drivers/interconnect/qcom/Kconfig"
+
+endif
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
new file mode 100644
index 000000000000..28f2ab0824d5
--- /dev/null
+++ b/drivers/interconnect/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+icc-core-objs := core.o
+
+obj-$(CONFIG_INTERCONNECT) += icc-core.o
+obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
new file mode 100644
index 000000000000..6005a1c189f6
--- /dev/null
+++ b/drivers/interconnect/core.c
@@ -0,0 +1,799 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interconnect framework core driver
+ *
+ * Copyright (c) 2017-2019, Linaro Ltd.
+ * Author: Georgi Djakov <georgi.djakov@linaro.org>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/overflow.h>
+
+static DEFINE_IDR(icc_idr);
+static LIST_HEAD(icc_providers);
+static DEFINE_MUTEX(icc_lock);
+static struct dentry *icc_debugfs_dir;
+
+/**
+ * struct icc_req - constraints that are attached to each node
+ * @req_node: entry in list of requests for the particular @node
+ * @node: the interconnect node to which this constraint applies
+ * @dev: reference to the device that sets the constraints
+ * @avg_bw: an integer describing the average bandwidth in kBps
+ * @peak_bw: an integer describing the peak bandwidth in kBps
+ */
+struct icc_req {
+ struct hlist_node req_node;
+ struct icc_node *node;
+ struct device *dev;
+ u32 avg_bw;
+ u32 peak_bw;
+};
+
+/**
+ * struct icc_path - interconnect path structure
+ * @num_nodes: number of hops (nodes)
+ * @reqs: array of the requests applicable to this path of nodes
+ */
+struct icc_path {
+ size_t num_nodes;
+ struct icc_req reqs[];
+};
+
+static void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
+{
+ if (!n)
+ return;
+
+ seq_printf(s, "%-30s %12u %12u\n",
+ n->name, n->avg_bw, n->peak_bw);
+}
+
+static int icc_summary_show(struct seq_file *s, void *data)
+{
+ struct icc_provider *provider;
+
+ seq_puts(s, " node avg peak\n");
+ seq_puts(s, "--------------------------------------------------------\n");
+
+ mutex_lock(&icc_lock);
+
+ list_for_each_entry(provider, &icc_providers, provider_list) {
+ struct icc_node *n;
+
+ list_for_each_entry(n, &provider->nodes, node_list) {
+ struct icc_req *r;
+
+ icc_summary_show_one(s, n);
+ hlist_for_each_entry(r, &n->req_list, req_node) {
+ if (!r->dev)
+ continue;
+
+ seq_printf(s, " %-26s %12u %12u\n",
+ dev_name(r->dev), r->avg_bw,
+ r->peak_bw);
+ }
+ }
+ }
+
+ mutex_unlock(&icc_lock);
+
+ return 0;
+}
+
+static int icc_summary_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, icc_summary_show, inode->i_private);
+}
+
+static const struct file_operations icc_summary_fops = {
+ .open = icc_summary_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct icc_node *node_find(const int id)
+{
+ return idr_find(&icc_idr, id);
+}
+
+static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
+ ssize_t num_nodes)
+{
+ struct icc_node *node = dst;
+ struct icc_path *path;
+ int i;
+
+ path = kzalloc(struct_size(path, reqs, num_nodes), GFP_KERNEL);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+
+ path->num_nodes = num_nodes;
+
+ for (i = num_nodes - 1; i >= 0; i--) {
+ node->provider->users++;
+ hlist_add_head(&path->reqs[i].req_node, &node->req_list);
+ path->reqs[i].node = node;
+ path->reqs[i].dev = dev;
+ /* reference to previous node was saved during path traversal */
+ node = node->reverse;
+ }
+
+ return path;
+}
+
+static struct icc_path *path_find(struct device *dev, struct icc_node *src,
+ struct icc_node *dst)
+{
+ struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
+ struct icc_node *n, *node = NULL;
+ struct list_head traverse_list;
+ struct list_head edge_list;
+ struct list_head visited_list;
+ size_t i, depth = 1;
+ bool found = false;
+
+ INIT_LIST_HEAD(&traverse_list);
+ INIT_LIST_HEAD(&edge_list);
+ INIT_LIST_HEAD(&visited_list);
+
+ list_add(&src->search_list, &traverse_list);
+ src->reverse = NULL;
+
+ do {
+ list_for_each_entry_safe(node, n, &traverse_list, search_list) {
+ if (node == dst) {
+ found = true;
+ list_splice_init(&edge_list, &visited_list);
+ list_splice_init(&traverse_list, &visited_list);
+ break;
+ }
+ for (i = 0; i < node->num_links; i++) {
+ struct icc_node *tmp = node->links[i];
+
+ if (!tmp) {
+ path = ERR_PTR(-ENOENT);
+ goto out;
+ }
+
+ if (tmp->is_traversed)
+ continue;
+
+ tmp->is_traversed = true;
+ tmp->reverse = node;
+ list_add_tail(&tmp->search_list, &edge_list);
+ }
+ }
+
+ if (found)
+ break;
+
+ list_splice_init(&traverse_list, &visited_list);
+ list_splice_init(&edge_list, &traverse_list);
+
+ /* count the hops including the source */
+ depth++;
+
+ } while (!list_empty(&traverse_list));
+
+out:
+
+ /* reset the traversed state */
+ list_for_each_entry_reverse(n, &visited_list, search_list)
+ n->is_traversed = false;
+
+ if (found)
+ path = path_init(dev, dst, depth);
+
+ return path;
+}
+
+/*
+ * We want the path to honor all bandwidth requests, so the average and peak
+ * bandwidth requirements from each consumer are aggregated at each node.
+ * The aggregation is platform specific, so each platform can customize it by
+ * implementing its own aggregate() function.
+ */
+
+static int aggregate_requests(struct icc_node *node)
+{
+ struct icc_provider *p = node->provider;
+ struct icc_req *r;
+
+ node->avg_bw = 0;
+ node->peak_bw = 0;
+
+ hlist_for_each_entry(r, &node->req_list, req_node)
+ p->aggregate(node, r->avg_bw, r->peak_bw,
+ &node->avg_bw, &node->peak_bw);
+
+ return 0;
+}
+
+static int apply_constraints(struct icc_path *path)
+{
+ struct icc_node *next, *prev = NULL;
+ int ret = -EINVAL;
+ int i;
+
+ for (i = 0; i < path->num_nodes; i++) {
+ next = path->reqs[i].node;
+
+ /*
+ * Both endpoints should be valid master-slave pairs of the
+ * same interconnect provider that will be configured.
+ */
+ if (!prev || next->provider != prev->provider) {
+ prev = next;
+ continue;
+ }
+
+ /* set the constraints */
+ ret = next->provider->set(prev, next);
+ if (ret)
+ goto out;
+
+ prev = next;
+ }
+out:
+ return ret;
+}
+
+/* of_icc_xlate_onecell() - Translate function using a single index.
+ * @spec: OF phandle args to map into an interconnect node.
+ * @data: private data (pointer to struct icc_onecell_data)
+ *
+ * This is a generic translate function that can be used to model simple
+ * interconnect providers that have one device tree node and provide
+ * multiple interconnect nodes. A single cell is used as an index into
+ * an array of icc nodes specified in the icc_onecell_data struct when
+ * registering the provider.
+ */
+struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
+ void *data)
+{
+ struct icc_onecell_data *icc_data = data;
+ unsigned int idx = spec->args[0];
+
+ if (idx >= icc_data->num_nodes) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return icc_data->nodes[idx];
+}
+EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
+
+/**
+ * of_icc_get_from_provider() - Look-up interconnect node
+ * @spec: OF phandle args to use for look-up
+ *
+ * Looks for interconnect provider under the node specified by @spec and if
+ * found, uses xlate function of the provider to map phandle args to node.
+ *
+ * Returns a valid pointer to struct icc_node on success or ERR_PTR()
+ * on failure.
+ */
+static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
+{
+ struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
+ struct icc_provider *provider;
+
+ if (!spec || spec->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&icc_lock);
+ list_for_each_entry(provider, &icc_providers, provider_list) {
+ if (provider->dev->of_node == spec->np)
+ node = provider->xlate(spec, provider->data);
+ if (!IS_ERR(node))
+ break;
+ }
+ mutex_unlock(&icc_lock);
+
+ return node;
+}
+
+/**
+ * of_icc_get() - get a path handle from a DT node based on name
+ * @dev: device pointer for the consumer device
+ * @name: interconnect path name
+ *
+ * This function will search for a path between two endpoints and return an
+ * icc_path handle on success. Use icc_put() to release constraints when they
+ * are not needed anymore.
+ * If the interconnect API is disabled, NULL is returned and the consumer
+ * drivers will still build. Drivers are free to handle this specifically,
+ * but they don't have to.
+ *
+ * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned
+ * when the API is disabled or the "interconnects" DT property is missing.
+ */
+struct icc_path *of_icc_get(struct device *dev, const char *name)
+{
+ struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
+ struct icc_node *src_node, *dst_node;
+ struct device_node *np = NULL;
+ struct of_phandle_args src_args, dst_args;
+ int idx = 0;
+ int ret;
+
+ if (!dev || !dev->of_node)
+ return ERR_PTR(-ENODEV);
+
+ np = dev->of_node;
+
+ /*
+ * When the consumer DT node do not have "interconnects" property
+ * return a NULL path to skip setting constraints.
+ */
+ if (!of_find_property(np, "interconnects", NULL))
+ return NULL;
+
+ /*
+ * We use a combination of phandle and specifier for endpoint. For now
+ * lets support only global ids and extend this in the future if needed
+ * without breaking DT compatibility.
+ */
+ if (name) {
+ idx = of_property_match_string(np, "interconnect-names", name);
+ if (idx < 0)
+ return ERR_PTR(idx);
+ }
+
+ ret = of_parse_phandle_with_args(np, "interconnects",
+ "#interconnect-cells", idx * 2,
+ &src_args);
+ if (ret)
+ return ERR_PTR(ret);
+
+ of_node_put(src_args.np);
+
+ ret = of_parse_phandle_with_args(np, "interconnects",
+ "#interconnect-cells", idx * 2 + 1,
+ &dst_args);
+ if (ret)
+ return ERR_PTR(ret);
+
+ of_node_put(dst_args.np);
+
+ src_node = of_icc_get_from_provider(&src_args);
+
+ if (IS_ERR(src_node)) {
+ if (PTR_ERR(src_node) != -EPROBE_DEFER)
+ dev_err(dev, "error finding src node: %ld\n",
+ PTR_ERR(src_node));
+ return ERR_CAST(src_node);
+ }
+
+ dst_node = of_icc_get_from_provider(&dst_args);
+
+ if (IS_ERR(dst_node)) {
+ if (PTR_ERR(dst_node) != -EPROBE_DEFER)
+ dev_err(dev, "error finding dst node: %ld\n",
+ PTR_ERR(dst_node));
+ return ERR_CAST(dst_node);
+ }
+
+ mutex_lock(&icc_lock);
+ path = path_find(dev, src_node, dst_node);
+ if (IS_ERR(path))
+ dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
+ mutex_unlock(&icc_lock);
+
+ return path;
+}
+EXPORT_SYMBOL_GPL(of_icc_get);
+
+/**
+ * icc_set_bw() - set bandwidth constraints on an interconnect path
+ * @path: reference to the path returned by icc_get()
+ * @avg_bw: average bandwidth in kilobytes per second
+ * @peak_bw: peak bandwidth in kilobytes per second
+ *
+ * This function is used by an interconnect consumer to express its own needs
+ * in terms of bandwidth for a previously requested path between two endpoints.
+ * The requests are aggregated and each node is updated accordingly. The entire
+ * path is locked by a mutex to ensure that the set() is completed.
+ * The @path can be NULL when the "interconnects" DT properties is missing,
+ * which will mean that no constraints will be set.
+ *
+ * Returns 0 on success, or an appropriate error code otherwise.
+ */
+int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
+{
+ struct icc_node *node;
+ u32 old_avg, old_peak;
+ size_t i;
+ int ret;
+
+ if (!path || !path->num_nodes)
+ return 0;
+
+ mutex_lock(&icc_lock);
+
+ old_avg = path->reqs[0].avg_bw;
+ old_peak = path->reqs[0].peak_bw;
+
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+
+ /* update the consumer request for this path */
+ path->reqs[i].avg_bw = avg_bw;
+ path->reqs[i].peak_bw = peak_bw;
+
+ /* aggregate requests for this node */
+ aggregate_requests(node);
+ }
+
+ ret = apply_constraints(path);
+ if (ret) {
+ pr_debug("interconnect: error applying constraints (%d)\n",
+ ret);
+
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+ path->reqs[i].avg_bw = old_avg;
+ path->reqs[i].peak_bw = old_peak;
+ aggregate_requests(node);
+ }
+ apply_constraints(path);
+ }
+
+ mutex_unlock(&icc_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(icc_set_bw);
+
+/**
+ * icc_get() - return a handle for path between two endpoints
+ * @dev: the device requesting the path
+ * @src_id: source device port id
+ * @dst_id: destination device port id
+ *
+ * This function will search for a path between two endpoints and return an
+ * icc_path handle on success. Use icc_put() to release
+ * constraints when they are not needed anymore.
+ * If the interconnect API is disabled, NULL is returned and the consumer
+ * drivers will still build. Drivers are free to handle this specifically,
+ * but they don't have to.
+ *
+ * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the
+ * interconnect API is disabled.
+ */
+struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
+{
+ struct icc_node *src, *dst;
+ struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
+
+ mutex_lock(&icc_lock);
+
+ src = node_find(src_id);
+ if (!src)
+ goto out;
+
+ dst = node_find(dst_id);
+ if (!dst)
+ goto out;
+
+ path = path_find(dev, src, dst);
+ if (IS_ERR(path))
+ dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
+
+out:
+ mutex_unlock(&icc_lock);
+ return path;
+}
+EXPORT_SYMBOL_GPL(icc_get);
+
+/**
+ * icc_put() - release the reference to the icc_path
+ * @path: interconnect path
+ *
+ * Use this function to release the constraints on a path when the path is
+ * no longer needed. The constraints will be re-aggregated.
+ */
+void icc_put(struct icc_path *path)
+{
+ struct icc_node *node;
+ size_t i;
+ int ret;
+
+ if (!path || WARN_ON(IS_ERR(path)))
+ return;
+
+ ret = icc_set_bw(path, 0, 0);
+ if (ret)
+ pr_err("%s: error (%d)\n", __func__, ret);
+
+ mutex_lock(&icc_lock);
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+ hlist_del(&path->reqs[i].req_node);
+ if (!WARN_ON(!node->provider->users))
+ node->provider->users--;
+ }
+ mutex_unlock(&icc_lock);
+
+ kfree(path);
+}
+EXPORT_SYMBOL_GPL(icc_put);
+
+static struct icc_node *icc_node_create_nolock(int id)
+{
+ struct icc_node *node;
+
+ /* check if node already exists */
+ node = node_find(id);
+ if (node)
+ return node;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL);
+ if (id < 0) {
+ WARN(1, "%s: couldn't get idr\n", __func__);
+ kfree(node);
+ return ERR_PTR(id);
+ }
+
+ node->id = id;
+
+ return node;
+}
+
+/**
+ * icc_node_create() - create a node
+ * @id: node id
+ *
+ * Return: icc_node pointer on success, or ERR_PTR() on error
+ */
+struct icc_node *icc_node_create(int id)
+{
+ struct icc_node *node;
+
+ mutex_lock(&icc_lock);
+
+ node = icc_node_create_nolock(id);
+
+ mutex_unlock(&icc_lock);
+
+ return node;
+}
+EXPORT_SYMBOL_GPL(icc_node_create);
+
+/**
+ * icc_node_destroy() - destroy a node
+ * @id: node id
+ */
+void icc_node_destroy(int id)
+{
+ struct icc_node *node;
+
+ mutex_lock(&icc_lock);
+
+ node = node_find(id);
+ if (node) {
+ idr_remove(&icc_idr, node->id);
+ WARN_ON(!hlist_empty(&node->req_list));
+ }
+
+ mutex_unlock(&icc_lock);
+
+ kfree(node);
+}
+EXPORT_SYMBOL_GPL(icc_node_destroy);
+
+/**
+ * icc_link_create() - create a link between two nodes
+ * @node: source node id
+ * @dst_id: destination node id
+ *
+ * Create a link between two nodes. The nodes might belong to different
+ * interconnect providers and the @dst_id node might not exist (if the
+ * provider driver has not probed yet). So just create the @dst_id node
+ * and when the actual provider driver is probed, the rest of the node
+ * data is filled.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int icc_link_create(struct icc_node *node, const int dst_id)
+{
+ struct icc_node *dst;
+ struct icc_node **new;
+ int ret = 0;
+
+ if (!node->provider)
+ return -EINVAL;
+
+ mutex_lock(&icc_lock);
+
+ dst = node_find(dst_id);
+ if (!dst) {
+ dst = icc_node_create_nolock(dst_id);
+
+ if (IS_ERR(dst)) {
+ ret = PTR_ERR(dst);
+ goto out;
+ }
+ }
+
+ new = krealloc(node->links,
+ (node->num_links + 1) * sizeof(*node->links),
+ GFP_KERNEL);
+ if (!new) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ node->links = new;
+ node->links[node->num_links++] = dst;
+
+out:
+ mutex_unlock(&icc_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(icc_link_create);
+
+/**
+ * icc_link_destroy() - destroy a link between two nodes
+ * @src: pointer to source node
+ * @dst: pointer to destination node
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int icc_link_destroy(struct icc_node *src, struct icc_node *dst)
+{
+ struct icc_node **new;
+ size_t slot;
+ int ret = 0;
+
+ if (IS_ERR_OR_NULL(src))
+ return -EINVAL;
+
+ if (IS_ERR_OR_NULL(dst))
+ return -EINVAL;
+
+ mutex_lock(&icc_lock);
+
+ for (slot = 0; slot < src->num_links; slot++)
+ if (src->links[slot] == dst)
+ break;
+
+ if (WARN_ON(slot == src->num_links)) {
+ ret = -ENXIO;
+ goto out;
+ }
+
+ src->links[slot] = src->links[--src->num_links];
+
+ new = krealloc(src->links, src->num_links * sizeof(*src->links),
+ GFP_KERNEL);
+ if (new)
+ src->links = new;
+
+out:
+ mutex_unlock(&icc_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(icc_link_destroy);
+
+/**
+ * icc_node_add() - add interconnect node to interconnect provider
+ * @node: pointer to the interconnect node
+ * @provider: pointer to the interconnect provider
+ */
+void icc_node_add(struct icc_node *node, struct icc_provider *provider)
+{
+ mutex_lock(&icc_lock);
+
+ node->provider = provider;
+ list_add_tail(&node->node_list, &provider->nodes);
+
+ mutex_unlock(&icc_lock);
+}
+EXPORT_SYMBOL_GPL(icc_node_add);
+
+/**
+ * icc_node_del() - delete interconnect node from interconnect provider
+ * @node: pointer to the interconnect node
+ */
+void icc_node_del(struct icc_node *node)
+{
+ mutex_lock(&icc_lock);
+
+ list_del(&node->node_list);
+
+ mutex_unlock(&icc_lock);
+}
+EXPORT_SYMBOL_GPL(icc_node_del);
+
+/**
+ * icc_provider_add() - add a new interconnect provider
+ * @provider: the interconnect provider that will be added into topology
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int icc_provider_add(struct icc_provider *provider)
+{
+ if (WARN_ON(!provider->set))
+ return -EINVAL;
+ if (WARN_ON(!provider->xlate))
+ return -EINVAL;
+
+ mutex_lock(&icc_lock);
+
+ INIT_LIST_HEAD(&provider->nodes);
+ list_add_tail(&provider->provider_list, &icc_providers);
+
+ mutex_unlock(&icc_lock);
+
+ dev_dbg(provider->dev, "interconnect provider added to topology\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(icc_provider_add);
+
+/**
+ * icc_provider_del() - delete previously added interconnect provider
+ * @provider: the interconnect provider that will be removed from topology
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int icc_provider_del(struct icc_provider *provider)
+{
+ mutex_lock(&icc_lock);
+ if (provider->users) {
+ pr_warn("interconnect provider still has %d users\n",
+ provider->users);
+ mutex_unlock(&icc_lock);
+ return -EBUSY;
+ }
+
+ if (!list_empty(&provider->nodes)) {
+ pr_warn("interconnect provider still has nodes\n");
+ mutex_unlock(&icc_lock);
+ return -EBUSY;
+ }
+
+ list_del(&provider->provider_list);
+ mutex_unlock(&icc_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(icc_provider_del);
+
+static int __init icc_init(void)
+{
+ icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
+ debugfs_create_file("interconnect_summary", 0444,
+ icc_debugfs_dir, NULL, &icc_summary_fops);
+ return 0;
+}
+
+static void __exit icc_exit(void)
+{
+ debugfs_remove_recursive(icc_debugfs_dir);
+}
+module_init(icc_init);
+module_exit(icc_exit);
+
+MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
+MODULE_DESCRIPTION("Interconnect Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
new file mode 100644
index 000000000000..290d330abe5a
--- /dev/null
+++ b/drivers/interconnect/qcom/Kconfig
@@ -0,0 +1,13 @@
+config INTERCONNECT_QCOM
+ bool "Qualcomm Network-on-Chip interconnect drivers"
+ depends on ARCH_QCOM
+ help
+ Support for Qualcomm's Network-on-Chip interconnect hardware.
+
+config INTERCONNECT_QCOM_SDM845
+ tristate "Qualcomm SDM845 interconnect driver"
+ depends on INTERCONNECT_QCOM
+ depends on (QCOM_RPMH && QCOM_COMMAND_DB && OF) || COMPILE_TEST
+ help
+ This is a driver for the Qualcomm Network-on-Chip on sdm845-based
+ platforms.
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
new file mode 100644
index 000000000000..1c1cea690f92
--- /dev/null
+++ b/drivers/interconnect/qcom/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+qnoc-sdm845-objs := sdm845.o
+
+obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
new file mode 100644
index 000000000000..4915b78da673
--- /dev/null
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -0,0 +1,838 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <asm/div64.h>
+#include <dt-bindings/interconnect/qcom,sdm845.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+
+#include <soc/qcom/cmd-db.h>
+#include <soc/qcom/rpmh.h>
+#include <soc/qcom/tcs.h>
+
+#define BCM_TCS_CMD_COMMIT_SHFT 30
+#define BCM_TCS_CMD_COMMIT_MASK 0x40000000
+#define BCM_TCS_CMD_VALID_SHFT 29
+#define BCM_TCS_CMD_VALID_MASK 0x20000000
+#define BCM_TCS_CMD_VOTE_X_SHFT 14
+#define BCM_TCS_CMD_VOTE_MASK 0x3fff
+#define BCM_TCS_CMD_VOTE_Y_SHFT 0
+#define BCM_TCS_CMD_VOTE_Y_MASK 0xfffc000
+
+#define BCM_TCS_CMD(commit, valid, vote_x, vote_y) \
+ (((commit) << BCM_TCS_CMD_COMMIT_SHFT) | \
+ ((valid) << BCM_TCS_CMD_VALID_SHFT) | \
+ ((cpu_to_le32(vote_x) & \
+ BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) | \
+ ((cpu_to_le32(vote_y) & \
+ BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT))
+
+#define to_qcom_provider(_provider) \
+ container_of(_provider, struct qcom_icc_provider, provider)
+
+struct qcom_icc_provider {
+ struct icc_provider provider;
+ struct device *dev;
+ struct qcom_icc_bcm **bcms;
+ size_t num_bcms;
+};
+
+/**
+ * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM)
+ * @unit: divisor used to convert bytes/sec bw value to an RPMh msg
+ * @width: multiplier used to convert bytes/sec bw value to an RPMh msg
+ * @vcd: virtual clock domain that this bcm belongs to
+ * @reserved: reserved field
+ */
+struct bcm_db {
+ __le32 unit;
+ __le16 width;
+ u8 vcd;
+ u8 reserved;
+};
+
+#define SDM845_MAX_LINKS 43
+#define SDM845_MAX_BCMS 30
+#define SDM845_MAX_BCM_PER_NODE 2
+#define SDM845_MAX_VCD 10
+
+/**
+ * struct qcom_icc_node - Qualcomm specific interconnect nodes
+ * @name: the node name used in debugfs
+ * @links: an array of nodes where we can go next while traversing
+ * @id: a unique node identifier
+ * @num_links: the total number of @links
+ * @channels: num of channels at this node
+ * @buswidth: width of the interconnect between a node and the bus
+ * @sum_avg: current sum aggregate value of all avg bw requests
+ * @max_peak: current max aggregate value of all peak bw requests
+ * @bcms: list of bcms associated with this logical node
+ * @num_bcms: num of @bcms
+ */
+struct qcom_icc_node {
+ const char *name;
+ u16 links[SDM845_MAX_LINKS];
+ u16 id;
+ u16 num_links;
+ u16 channels;
+ u16 buswidth;
+ u64 sum_avg;
+ u64 max_peak;
+ struct qcom_icc_bcm *bcms[SDM845_MAX_BCM_PER_NODE];
+ size_t num_bcms;
+};
+
+/**
+ * struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes
+ * known as Bus Clock Manager (BCM)
+ * @name: the bcm node name used to fetch BCM data from command db
+ * @type: latency or bandwidth bcm
+ * @addr: address offsets used when voting to RPMH
+ * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
+ * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
+ * @dirty: flag used to indicate whether the bcm needs to be committed
+ * @keepalive: flag used to indicate whether a keepalive is required
+ * @aux_data: auxiliary data used when calculating threshold values and
+ * communicating with RPMh
+ * @list: used to link to other bcms when compiling lists for commit
+ * @num_nodes: total number of @num_nodes
+ * @nodes: list of qcom_icc_nodes that this BCM encapsulates
+ */
+struct qcom_icc_bcm {
+ const char *name;
+ u32 type;
+ u32 addr;
+ u64 vote_x;
+ u64 vote_y;
+ bool dirty;
+ bool keepalive;
+ struct bcm_db aux_data;
+ struct list_head list;
+ size_t num_nodes;
+ struct qcom_icc_node *nodes[];
+};
+
+struct qcom_icc_fabric {
+ struct qcom_icc_node **nodes;
+ size_t num_nodes;
+};
+
+struct qcom_icc_desc {
+ struct qcom_icc_node **nodes;
+ size_t num_nodes;
+ struct qcom_icc_bcm **bcms;
+ size_t num_bcms;
+};
+
+#define DEFINE_QNODE(_name, _id, _channels, _buswidth, \
+ _numlinks, ...) \
+ static struct qcom_icc_node _name = { \
+ .id = _id, \
+ .name = #_name, \
+ .channels = _channels, \
+ .buswidth = _buswidth, \
+ .num_links = _numlinks, \
+ .links = { __VA_ARGS__ }, \
+ }
+
+DEFINE_QNODE(qhm_a1noc_cfg, MASTER_A1NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A1NOC);
+DEFINE_QNODE(qhm_qup1, MASTER_BLSP_1, 1, 4, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(qhm_tsif, MASTER_TSIF, 1, 4, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(xm_sdc2, MASTER_SDCC_2, 1, 8, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(xm_sdc4, MASTER_SDCC_4, 1, 8, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(xm_ufs_card, MASTER_UFS_CARD, 1, 8, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(xm_ufs_mem, MASTER_UFS_MEM, 1, 8, 1, SLAVE_A1NOC_SNOC);
+DEFINE_QNODE(xm_pcie_0, MASTER_PCIE_0, 1, 8, 1, SLAVE_ANOC_PCIE_A1NOC_SNOC);
+DEFINE_QNODE(qhm_a2noc_cfg, MASTER_A2NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A2NOC);
+DEFINE_QNODE(qhm_qdss_bam, MASTER_QDSS_BAM, 1, 4, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(qhm_qup2, MASTER_BLSP_2, 1, 4, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(qnm_cnoc, MASTER_CNOC_A2NOC, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(qxm_crypto, MASTER_CRYPTO, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(qxm_ipa, MASTER_IPA, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(xm_pcie3_1, MASTER_PCIE_1, 1, 8, 1, SLAVE_ANOC_PCIE_SNOC);
+DEFINE_QNODE(xm_qdss_etr, MASTER_QDSS_ETR, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(xm_usb3_0, MASTER_USB3_0, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(xm_usb3_1, MASTER_USB3_1, 1, 8, 1, SLAVE_A2NOC_SNOC);
+DEFINE_QNODE(qxm_camnoc_hf0_uncomp, MASTER_CAMNOC_HF0_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(qxm_camnoc_hf1_uncomp, MASTER_CAMNOC_HF1_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(qxm_camnoc_sf_uncomp, MASTER_CAMNOC_SF_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(qhm_spdm, MASTER_SPDM, 1, 4, 1, SLAVE_CNOC_A2NOC);
+DEFINE_QNODE(qhm_tic, MASTER_TIC, 1, 4, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC);
+DEFINE_QNODE(qnm_snoc, MASTER_SNOC_CNOC, 1, 8, 42, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_SERVICE_CNOC);
+DEFINE_QNODE(xm_qdss_dap, MASTER_QDSS_DAP, 1, 8, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC);
+DEFINE_QNODE(qhm_cnoc, MASTER_CNOC_DC_NOC, 1, 4, 2, SLAVE_LLCC_CFG, SLAVE_MEM_NOC_CFG);
+DEFINE_QNODE(acm_l3, MASTER_APPSS_PROC, 1, 16, 3, SLAVE_GNOC_SNOC, SLAVE_GNOC_MEM_NOC, SLAVE_SERVICE_GNOC);
+DEFINE_QNODE(pm_gnoc_cfg, MASTER_GNOC_CFG, 1, 4, 1, SLAVE_SERVICE_GNOC);
+DEFINE_QNODE(llcc_mc, MASTER_LLCC, 4, 4, 1, SLAVE_EBI1);
+DEFINE_QNODE(acm_tcu, MASTER_TCU_0, 1, 8, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
+DEFINE_QNODE(qhm_memnoc_cfg, MASTER_MEM_NOC_CFG, 1, 4, 2, SLAVE_MSS_PROC_MS_MPU_CFG, SLAVE_SERVICE_MEM_NOC);
+DEFINE_QNODE(qnm_apps, MASTER_GNOC_MEM_NOC, 2, 32, 1, SLAVE_LLCC);
+DEFINE_QNODE(qnm_mnoc_hf, MASTER_MNOC_HF_MEM_NOC, 2, 32, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC);
+DEFINE_QNODE(qnm_mnoc_sf, MASTER_MNOC_SF_MEM_NOC, 1, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
+DEFINE_QNODE(qnm_snoc_gc, MASTER_SNOC_GC_MEM_NOC, 1, 8, 1, SLAVE_LLCC);
+DEFINE_QNODE(qnm_snoc_sf, MASTER_SNOC_SF_MEM_NOC, 1, 16, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC);
+DEFINE_QNODE(qxm_gpu, MASTER_GFX3D, 2, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
+DEFINE_QNODE(qhm_mnoc_cfg, MASTER_CNOC_MNOC_CFG, 1, 4, 1, SLAVE_SERVICE_MNOC);
+DEFINE_QNODE(qxm_camnoc_hf0, MASTER_CAMNOC_HF0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(qxm_camnoc_hf1, MASTER_CAMNOC_HF1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(qxm_camnoc_sf, MASTER_CAMNOC_SF, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qxm_mdp0, MASTER_MDP0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(qxm_mdp1, MASTER_MDP1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(qxm_rot, MASTER_ROTATOR, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qxm_venus0, MASTER_VIDEO_P0, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qxm_venus1, MASTER_VIDEO_P1, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qxm_venus_arm9, MASTER_VIDEO_PROC, 1, 8, 1, SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qhm_snoc_cfg, MASTER_SNOC_CFG, 1, 4, 1, SLAVE_SERVICE_SNOC);
+DEFINE_QNODE(qnm_aggre1_noc, MASTER_A1NOC_SNOC, 1, 16, 6, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM);
+DEFINE_QNODE(qnm_aggre2_noc, MASTER_A2NOC_SNOC, 1, 16, 9, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU);
+DEFINE_QNODE(qnm_gladiator_sodv, MASTER_GNOC_SNOC, 1, 8, 8, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU);
+DEFINE_QNODE(qnm_memnoc, MASTER_MEM_NOC_SNOC, 1, 8, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM);
+DEFINE_QNODE(qnm_pcie_anoc, MASTER_ANOC_PCIE_SNOC, 1, 16, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_QDSS_STM);
+DEFINE_QNODE(qxm_pimem, MASTER_PIMEM, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM);
+DEFINE_QNODE(xm_gic, MASTER_GIC, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM);
+DEFINE_QNODE(qns_a1noc_snoc, SLAVE_A1NOC_SNOC, 1, 16, 1, MASTER_A1NOC_SNOC);
+DEFINE_QNODE(srvc_aggre1_noc, SLAVE_SERVICE_A1NOC, 1, 4, 0);
+DEFINE_QNODE(qns_pcie_a1noc_snoc, SLAVE_ANOC_PCIE_A1NOC_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC);
+DEFINE_QNODE(qns_a2noc_snoc, SLAVE_A2NOC_SNOC, 1, 16, 1, MASTER_A2NOC_SNOC);
+DEFINE_QNODE(qns_pcie_snoc, SLAVE_ANOC_PCIE_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC);
+DEFINE_QNODE(srvc_aggre2_noc, SLAVE_SERVICE_A2NOC, 1, 4, 0);
+DEFINE_QNODE(qns_camnoc_uncomp, SLAVE_CAMNOC_UNCOMP, 1, 32, 0);
+DEFINE_QNODE(qhs_a1_noc_cfg, SLAVE_A1NOC_CFG, 1, 4, 1, MASTER_A1NOC_CFG);
+DEFINE_QNODE(qhs_a2_noc_cfg, SLAVE_A2NOC_CFG, 1, 4, 1, MASTER_A2NOC_CFG);
+DEFINE_QNODE(qhs_aop, SLAVE_AOP, 1, 4, 0);
+DEFINE_QNODE(qhs_aoss, SLAVE_AOSS, 1, 4, 0);
+DEFINE_QNODE(qhs_camera_cfg, SLAVE_CAMERA_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_clk_ctl, SLAVE_CLK_CTL, 1, 4, 0);
+DEFINE_QNODE(qhs_compute_dsp_cfg, SLAVE_CDSP_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_cpr_cx, SLAVE_RBCPR_CX_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_crypto0_cfg, SLAVE_CRYPTO_0_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_dcc_cfg, SLAVE_DCC_CFG, 1, 4, 1, MASTER_CNOC_DC_NOC);
+DEFINE_QNODE(qhs_ddrss_cfg, SLAVE_CNOC_DDRSS, 1, 4, 0);
+DEFINE_QNODE(qhs_display_cfg, SLAVE_DISPLAY_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_glm, SLAVE_GLM, 1, 4, 0);
+DEFINE_QNODE(qhs_gpuss_cfg, SLAVE_GFX3D_CFG, 1, 8, 0);
+DEFINE_QNODE(qhs_imem_cfg, SLAVE_IMEM_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_ipa, SLAVE_IPA_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_mnoc_cfg, SLAVE_CNOC_MNOC_CFG, 1, 4, 1, MASTER_CNOC_MNOC_CFG);
+DEFINE_QNODE(qhs_pcie0_cfg, SLAVE_PCIE_0_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_pcie_gen3_cfg, SLAVE_PCIE_1_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_pdm, SLAVE_PDM, 1, 4, 0);
+DEFINE_QNODE(qhs_phy_refgen_south, SLAVE_SOUTH_PHY_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_pimem_cfg, SLAVE_PIMEM_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_prng, SLAVE_PRNG, 1, 4, 0);
+DEFINE_QNODE(qhs_qdss_cfg, SLAVE_QDSS_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_qupv3_north, SLAVE_BLSP_2, 1, 4, 0);
+DEFINE_QNODE(qhs_qupv3_south, SLAVE_BLSP_1, 1, 4, 0);
+DEFINE_QNODE(qhs_sdc2, SLAVE_SDCC_2, 1, 4, 0);
+DEFINE_QNODE(qhs_sdc4, SLAVE_SDCC_4, 1, 4, 0);
+DEFINE_QNODE(qhs_snoc_cfg, SLAVE_SNOC_CFG, 1, 4, 1, MASTER_SNOC_CFG);
+DEFINE_QNODE(qhs_spdm, SLAVE_SPDM_WRAPPER, 1, 4, 0);
+DEFINE_QNODE(qhs_spss_cfg, SLAVE_SPSS_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_tcsr, SLAVE_TCSR, 1, 4, 0);
+DEFINE_QNODE(qhs_tlmm_north, SLAVE_TLMM_NORTH, 1, 4, 0);
+DEFINE_QNODE(qhs_tlmm_south, SLAVE_TLMM_SOUTH, 1, 4, 0);
+DEFINE_QNODE(qhs_tsif, SLAVE_TSIF, 1, 4, 0);
+DEFINE_QNODE(qhs_ufs_card_cfg, SLAVE_UFS_CARD_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_ufs_mem_cfg, SLAVE_UFS_MEM_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_usb3_0, SLAVE_USB3_0, 1, 4, 0);
+DEFINE_QNODE(qhs_usb3_1, SLAVE_USB3_1, 1, 4, 0);
+DEFINE_QNODE(qhs_venus_cfg, SLAVE_VENUS_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_vsense_ctrl_cfg, SLAVE_VSENSE_CTRL_CFG, 1, 4, 0);
+DEFINE_QNODE(qns_cnoc_a2noc, SLAVE_CNOC_A2NOC, 1, 8, 1, MASTER_CNOC_A2NOC);
+DEFINE_QNODE(srvc_cnoc, SLAVE_SERVICE_CNOC, 1, 4, 0);
+DEFINE_QNODE(qhs_llcc, SLAVE_LLCC_CFG, 1, 4, 0);
+DEFINE_QNODE(qhs_memnoc, SLAVE_MEM_NOC_CFG, 1, 4, 1, MASTER_MEM_NOC_CFG);
+DEFINE_QNODE(qns_gladiator_sodv, SLAVE_GNOC_SNOC, 1, 8, 1, MASTER_GNOC_SNOC);
+DEFINE_QNODE(qns_gnoc_memnoc, SLAVE_GNOC_MEM_NOC, 2, 32, 1, MASTER_GNOC_MEM_NOC);
+DEFINE_QNODE(srvc_gnoc, SLAVE_SERVICE_GNOC, 1, 4, 0);
+DEFINE_QNODE(ebi, SLAVE_EBI1, 4, 4, 0);
+DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4, 0);
+DEFINE_QNODE(qns_apps_io, SLAVE_MEM_NOC_GNOC, 1, 32, 0);
+DEFINE_QNODE(qns_llcc, SLAVE_LLCC, 4, 16, 1, MASTER_LLCC);
+DEFINE_QNODE(qns_memnoc_snoc, SLAVE_MEM_NOC_SNOC, 1, 8, 1, MASTER_MEM_NOC_SNOC);
+DEFINE_QNODE(srvc_memnoc, SLAVE_SERVICE_MEM_NOC, 1, 4, 0);
+DEFINE_QNODE(qns2_mem_noc, SLAVE_MNOC_SF_MEM_NOC, 1, 32, 1, MASTER_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(qns_mem_noc_hf, SLAVE_MNOC_HF_MEM_NOC, 2, 32, 1, MASTER_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(srvc_mnoc, SLAVE_SERVICE_MNOC, 1, 4, 0);
+DEFINE_QNODE(qhs_apss, SLAVE_APPSS, 1, 8, 0);
+DEFINE_QNODE(qns_cnoc, SLAVE_SNOC_CNOC, 1, 8, 1, MASTER_SNOC_CNOC);
+DEFINE_QNODE(qns_memnoc_gc, SLAVE_SNOC_MEM_NOC_GC, 1, 8, 1, MASTER_SNOC_GC_MEM_NOC);
+DEFINE_QNODE(qns_memnoc_sf, SLAVE_SNOC_MEM_NOC_SF, 1, 16, 1, MASTER_SNOC_SF_MEM_NOC);
+DEFINE_QNODE(qxs_imem, SLAVE_IMEM, 1, 8, 0);
+DEFINE_QNODE(qxs_pcie, SLAVE_PCIE_0, 1, 8, 0);
+DEFINE_QNODE(qxs_pcie_gen3, SLAVE_PCIE_1, 1, 8, 0);
+DEFINE_QNODE(qxs_pimem, SLAVE_PIMEM, 1, 8, 0);
+DEFINE_QNODE(srvc_snoc, SLAVE_SERVICE_SNOC, 1, 4, 0);
+DEFINE_QNODE(xs_qdss_stm, SLAVE_QDSS_STM, 1, 4, 0);
+DEFINE_QNODE(xs_sys_tcu_cfg, SLAVE_TCU, 1, 8, 0);
+
+#define DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \
+ static struct qcom_icc_bcm _name = { \
+ .name = _bcmname, \
+ .keepalive = _keepalive, \
+ .num_nodes = _numnodes, \
+ .nodes = { __VA_ARGS__ }, \
+ }
+
+DEFINE_QBCM(bcm_acv, "ACV", false, 1, &ebi);
+DEFINE_QBCM(bcm_mc0, "MC0", true, 1, &ebi);
+DEFINE_QBCM(bcm_sh0, "SH0", true, 1, &qns_llcc);
+DEFINE_QBCM(bcm_mm0, "MM0", false, 1, &qns_mem_noc_hf);
+DEFINE_QBCM(bcm_sh1, "SH1", false, 1, &qns_apps_io);
+DEFINE_QBCM(bcm_mm1, "MM1", false, 7, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1);
+DEFINE_QBCM(bcm_sh2, "SH2", false, 1, &qns_memnoc_snoc);
+DEFINE_QBCM(bcm_mm2, "MM2", false, 1, &qns2_mem_noc);
+DEFINE_QBCM(bcm_sh3, "SH3", false, 1, &acm_tcu);
+DEFINE_QBCM(bcm_mm3, "MM3", false, 5, &qxm_camnoc_sf, &qxm_rot, &qxm_venus0, &qxm_venus1, &qxm_venus_arm9);
+DEFINE_QBCM(bcm_sh5, "SH5", false, 1, &qnm_apps);
+DEFINE_QBCM(bcm_sn0, "SN0", true, 1, &qns_memnoc_sf);
+DEFINE_QBCM(bcm_ce0, "CE0", false, 1, &qxm_crypto);
+DEFINE_QBCM(bcm_cn0, "CN0", false, 47, &qhm_spdm, &qhm_tic, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_aop, &qhs_aoss, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_compute_dsp_cfg, &qhs_cpr_cx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_pcie0_cfg, &qhs_pcie_gen3_cfg, &qhs_pdm, &qhs_phy_refgen_south, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qupv3_north, &qhs_qupv3_south, &qhs_sdc2, &qhs_sdc4, &qhs_snoc_cfg, &qhs_spdm, &qhs_spss_cfg, &qhs_tcsr, &qhs_tlmm_north, &qhs_tlmm_south, &qhs_tsif, &qhs_ufs_card_cfg, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_usb3_1, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc, &srvc_cnoc);
+DEFINE_QBCM(bcm_qup0, "QUP0", false, 2, &qhm_qup1, &qhm_qup2);
+DEFINE_QBCM(bcm_sn1, "SN1", false, 1, &qxs_imem);
+DEFINE_QBCM(bcm_sn2, "SN2", false, 1, &qns_memnoc_gc);
+DEFINE_QBCM(bcm_sn3, "SN3", false, 1, &qns_cnoc);
+DEFINE_QBCM(bcm_sn4, "SN4", false, 1, &qxm_pimem);
+DEFINE_QBCM(bcm_sn5, "SN5", false, 1, &xs_qdss_stm);
+DEFINE_QBCM(bcm_sn6, "SN6", false, 3, &qhs_apss, &srvc_snoc, &xs_sys_tcu_cfg);
+DEFINE_QBCM(bcm_sn7, "SN7", false, 1, &qxs_pcie);
+DEFINE_QBCM(bcm_sn8, "SN8", false, 1, &qxs_pcie_gen3);
+DEFINE_QBCM(bcm_sn9, "SN9", false, 2, &srvc_aggre1_noc, &qnm_aggre1_noc);
+DEFINE_QBCM(bcm_sn11, "SN11", false, 2, &srvc_aggre2_noc, &qnm_aggre2_noc);
+DEFINE_QBCM(bcm_sn12, "SN12", false, 2, &qnm_gladiator_sodv, &xm_gic);
+DEFINE_QBCM(bcm_sn14, "SN14", false, 1, &qnm_pcie_anoc);
+DEFINE_QBCM(bcm_sn15, "SN15", false, 1, &qnm_memnoc);
+
+static struct qcom_icc_node *rsc_hlos_nodes[] = {
+ [MASTER_APPSS_PROC] = &acm_l3,
+ [MASTER_TCU_0] = &acm_tcu,
+ [MASTER_LLCC] = &llcc_mc,
+ [MASTER_GNOC_CFG] = &pm_gnoc_cfg,
+ [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg,
+ [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg,
+ [MASTER_CNOC_DC_NOC] = &qhm_cnoc,
+ [MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg,
+ [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_BLSP_1] = &qhm_qup1,
+ [MASTER_BLSP_2] = &qhm_qup2,
+ [MASTER_SNOC_CFG] = &qhm_snoc_cfg,
+ [MASTER_SPDM] = &qhm_spdm,
+ [MASTER_TIC] = &qhm_tic,
+ [MASTER_TSIF] = &qhm_tsif,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_GNOC_MEM_NOC] = &qnm_apps,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc,
+ [MASTER_GNOC_SNOC] = &qnm_gladiator_sodv,
+ [MASTER_MEM_NOC_SNOC] = &qnm_memnoc,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc,
+ [MASTER_SNOC_CNOC] = &qnm_snoc,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0,
+ [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp,
+ [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1,
+ [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp,
+ [MASTER_CAMNOC_SF] = &qxm_camnoc_sf,
+ [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_GFX3D] = &qxm_gpu,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_MDP0] = &qxm_mdp0,
+ [MASTER_MDP1] = &qxm_mdp1,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_ROTATOR] = &qxm_rot,
+ [MASTER_VIDEO_P0] = &qxm_venus0,
+ [MASTER_VIDEO_P1] = &qxm_venus1,
+ [MASTER_VIDEO_PROC] = &qxm_venus_arm9,
+ [MASTER_GIC] = &xm_gic,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [MASTER_PCIE_0] = &xm_pcie_0,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [MASTER_SDCC_4] = &xm_sdc4,
+ [MASTER_UFS_CARD] = &xm_ufs_card,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [MASTER_USB3_1] = &xm_usb3_1,
+ [SLAVE_EBI1] = &ebi,
+ [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg,
+ [SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg,
+ [SLAVE_AOP] = &qhs_aop,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute_dsp_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_DCC_CFG] = &qhs_dcc_cfg,
+ [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_GLM] = &qhs_glm,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+ [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg,
+ [SLAVE_MEM_NOC_CFG] = &qhs_memnoc,
+ [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie_gen3_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_SOUTH_PHY_CFG] = &qhs_phy_refgen_south,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_BLSP_2] = &qhs_qupv3_north,
+ [SLAVE_BLSP_1] = &qhs_qupv3_south,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_SDCC_4] = &qhs_sdc4,
+ [SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
+ [SLAVE_SPDM_WRAPPER] = &qhs_spdm,
+ [SLAVE_SPSS_CFG] = &qhs_spss_cfg,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM_NORTH] = &qhs_tlmm_north,
+ [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south,
+ [SLAVE_TSIF] = &qhs_tsif,
+ [SLAVE_UFS_CARD_CFG] = &qhs_ufs_card_cfg,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_USB3_1] = &qhs_usb3_1,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+ [SLAVE_MEM_NOC_GNOC] = &qns_apps_io,
+ [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
+ [SLAVE_SNOC_CNOC] = &qns_cnoc,
+ [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc,
+ [SLAVE_GNOC_SNOC] = &qns_gladiator_sodv,
+ [SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc,
+ [SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf,
+ [SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc,
+ [SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc,
+ [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PCIE_0] = &qxs_pcie,
+ [SLAVE_PCIE_1] = &qxs_pcie_gen3,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc,
+ [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+ [SLAVE_SERVICE_GNOC] = &srvc_gnoc,
+ [SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static struct qcom_icc_bcm *rsc_hlos_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+ &bcm_sh0,
+ &bcm_mm0,
+ &bcm_sh1,
+ &bcm_mm1,
+ &bcm_sh2,
+ &bcm_mm2,
+ &bcm_sh3,
+ &bcm_mm3,
+ &bcm_sh5,
+ &bcm_sn0,
+ &bcm_ce0,
+ &bcm_cn0,
+ &bcm_qup0,
+ &bcm_sn1,
+ &bcm_sn2,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn5,
+ &bcm_sn6,
+ &bcm_sn7,
+ &bcm_sn8,
+ &bcm_sn9,
+ &bcm_sn11,
+ &bcm_sn12,
+ &bcm_sn14,
+ &bcm_sn15,
+};
+
+static struct qcom_icc_desc sdm845_rsc_hlos = {
+ .nodes = rsc_hlos_nodes,
+ .num_nodes = ARRAY_SIZE(rsc_hlos_nodes),
+ .bcms = rsc_hlos_bcms,
+ .num_bcms = ARRAY_SIZE(rsc_hlos_bcms),
+};
+
+static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
+{
+ struct qcom_icc_node *qn;
+ const struct bcm_db *data;
+ size_t data_count;
+ int i;
+
+ bcm->addr = cmd_db_read_addr(bcm->name);
+ if (!bcm->addr) {
+ dev_err(dev, "%s could not find RPMh address\n",
+ bcm->name);
+ return -EINVAL;
+ }
+
+ data = cmd_db_read_aux_data(bcm->name, &data_count);
+ if (IS_ERR(data)) {
+ dev_err(dev, "%s command db read error (%ld)\n",
+ bcm->name, PTR_ERR(data));
+ return PTR_ERR(data);
+ }
+ if (!data_count) {
+ dev_err(dev, "%s command db missing or partial aux data\n",
+ bcm->name);
+ return -EINVAL;
+ }
+
+ bcm->aux_data.unit = le32_to_cpu(data->unit);
+ bcm->aux_data.width = le16_to_cpu(data->width);
+ bcm->aux_data.vcd = data->vcd;
+ bcm->aux_data.reserved = data->reserved;
+
+ /*
+ * Link Qnodes to their respective BCMs
+ */
+ for (i = 0; i < bcm->num_nodes; i++) {
+ qn = bcm->nodes[i];
+ qn->bcms[qn->num_bcms] = bcm;
+ qn->num_bcms++;
+ }
+
+ return 0;
+}
+
+inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y,
+ u32 addr, bool commit)
+{
+ bool valid = true;
+
+ if (!cmd)
+ return;
+
+ if (vote_x == 0 && vote_y == 0)
+ valid = false;
+
+ if (vote_x > BCM_TCS_CMD_VOTE_MASK)
+ vote_x = BCM_TCS_CMD_VOTE_MASK;
+
+ if (vote_y > BCM_TCS_CMD_VOTE_MASK)
+ vote_y = BCM_TCS_CMD_VOTE_MASK;
+
+ cmd->addr = addr;
+ cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y);
+
+ /*
+ * Set the wait for completion flag on command that need to be completed
+ * before the next command.
+ */
+ if (commit)
+ cmd->wait = true;
+}
+
+static void tcs_list_gen(struct list_head *bcm_list,
+ struct tcs_cmd tcs_list[SDM845_MAX_VCD],
+ int n[SDM845_MAX_VCD])
+{
+ struct qcom_icc_bcm *bcm;
+ bool commit;
+ size_t idx = 0, batch = 0, cur_vcd_size = 0;
+
+ memset(n, 0, sizeof(int) * SDM845_MAX_VCD);
+
+ list_for_each_entry(bcm, bcm_list, list) {
+ commit = false;
+ cur_vcd_size++;
+ if ((list_is_last(&bcm->list, bcm_list)) ||
+ bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) {
+ commit = true;
+ cur_vcd_size = 0;
+ }
+ tcs_cmd_gen(&tcs_list[idx], bcm->vote_x, bcm->vote_y,
+ bcm->addr, commit);
+ idx++;
+ n[batch]++;
+ /*
+ * Batch the BCMs in such a way that we do not split them in
+ * multiple payloads when they are under the same VCD. This is
+ * to ensure that every BCM is committed since we only set the
+ * commit bit on the last BCM request of every VCD.
+ */
+ if (n[batch] >= MAX_RPMH_PAYLOAD) {
+ if (!commit) {
+ n[batch] -= cur_vcd_size;
+ n[batch + 1] = cur_vcd_size;
+ }
+ batch++;
+ }
+ }
+}
+
+static void bcm_aggregate(struct qcom_icc_bcm *bcm)
+{
+ size_t i;
+ u64 agg_avg = 0;
+ u64 agg_peak = 0;
+ u64 temp;
+
+ for (i = 0; i < bcm->num_nodes; i++) {
+ temp = bcm->nodes[i]->sum_avg * bcm->aux_data.width;
+ do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels);
+ agg_avg = max(agg_avg, temp);
+
+ temp = bcm->nodes[i]->max_peak * bcm->aux_data.width;
+ do_div(temp, bcm->nodes[i]->buswidth);
+ agg_peak = max(agg_peak, temp);
+ }
+
+ temp = agg_avg * 1000ULL;
+ do_div(temp, bcm->aux_data.unit);
+ bcm->vote_x = temp;
+
+ temp = agg_peak * 1000ULL;
+ do_div(temp, bcm->aux_data.unit);
+ bcm->vote_y = temp;
+
+ if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) {
+ bcm->vote_x = 1;
+ bcm->vote_y = 1;
+ }
+
+ bcm->dirty = false;
+}
+
+static int qcom_icc_aggregate(struct icc_node *node, u32 avg_bw,
+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+ size_t i;
+ struct qcom_icc_node *qn;
+
+ qn = node->data;
+
+ *agg_avg += avg_bw;
+ *agg_peak = max_t(u32, *agg_peak, peak_bw);
+
+ qn->sum_avg = *agg_avg;
+ qn->max_peak = *agg_peak;
+
+ for (i = 0; i < qn->num_bcms; i++)
+ qn->bcms[i]->dirty = true;
+
+ return 0;
+}
+
+static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+ struct qcom_icc_provider *qp;
+ struct icc_node *node;
+ struct tcs_cmd cmds[SDM845_MAX_BCMS];
+ struct list_head commit_list;
+ int commit_idx[SDM845_MAX_VCD];
+ int ret = 0, i;
+
+ if (!src)
+ node = dst;
+ else
+ node = src;
+
+ qp = to_qcom_provider(node->provider);
+
+ INIT_LIST_HEAD(&commit_list);
+
+ for (i = 0; i < qp->num_bcms; i++) {
+ if (qp->bcms[i]->dirty) {
+ bcm_aggregate(qp->bcms[i]);
+ list_add_tail(&qp->bcms[i]->list, &commit_list);
+ }
+ }
+
+ /*
+ * Construct the command list based on a pre ordered list of BCMs
+ * based on VCD.
+ */
+ tcs_list_gen(&commit_list, cmds, commit_idx);
+
+ if (!commit_idx[0])
+ return ret;
+
+ ret = rpmh_invalidate(qp->dev);
+ if (ret) {
+ pr_err("Error invalidating RPMH client (%d)\n", ret);
+ return ret;
+ }
+
+ ret = rpmh_write_batch(qp->dev, RPMH_ACTIVE_ONLY_STATE,
+ cmds, commit_idx);
+ if (ret) {
+ pr_err("Error sending AMC RPMH requests (%d)\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int cmp_vcd(const void *_l, const void *_r)
+{
+ const struct qcom_icc_bcm **l = (const struct qcom_icc_bcm **)_l;
+ const struct qcom_icc_bcm **r = (const struct qcom_icc_bcm **)_r;
+
+ if (l[0]->aux_data.vcd < r[0]->aux_data.vcd)
+ return -1;
+ else if (l[0]->aux_data.vcd == r[0]->aux_data.vcd)
+ return 0;
+ else
+ return 1;
+}
+
+static int qnoc_probe(struct platform_device *pdev)
+{
+ const struct qcom_icc_desc *desc;
+ struct icc_onecell_data *data;
+ struct icc_provider *provider;
+ struct qcom_icc_node **qnodes;
+ struct qcom_icc_provider *qp;
+ struct icc_node *node;
+ size_t num_nodes, i;
+ int ret;
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ qnodes = desc->nodes;
+ num_nodes = desc->num_nodes;
+
+ qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
+ if (!qp)
+ return -ENOMEM;
+
+ data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ provider = &qp->provider;
+ provider->dev = &pdev->dev;
+ provider->set = qcom_icc_set;
+ provider->aggregate = qcom_icc_aggregate;
+ provider->xlate = of_icc_xlate_onecell;
+ INIT_LIST_HEAD(&provider->nodes);
+ provider->data = data;
+
+ qp->dev = &pdev->dev;
+ qp->bcms = desc->bcms;
+ qp->num_bcms = desc->num_bcms;
+
+ ret = icc_provider_add(provider);
+ if (ret) {
+ dev_err(&pdev->dev, "error adding interconnect provider\n");
+ return ret;
+ }
+
+ for (i = 0; i < num_nodes; i++) {
+ size_t j;
+
+ node = icc_node_create(qnodes[i]->id);
+ if (IS_ERR(node)) {
+ ret = PTR_ERR(node);
+ goto err;
+ }
+
+ node->name = qnodes[i]->name;
+ node->data = qnodes[i];
+ icc_node_add(node, provider);
+
+ dev_dbg(&pdev->dev, "registered node %p %s %d\n", node,
+ qnodes[i]->name, node->id);
+
+ /* populate links */
+ for (j = 0; j < qnodes[i]->num_links; j++)
+ icc_link_create(node, qnodes[i]->links[j]);
+
+ data->nodes[i] = node;
+ }
+ data->num_nodes = num_nodes;
+
+ for (i = 0; i < qp->num_bcms; i++)
+ qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
+ /*
+ * Pre sort the BCMs based on VCD for ease of generating a command list
+ * that groups the BCMs with the same VCD together. VCDs are numbered
+ * with lowest being the most expensive time wise, ensuring that
+ * those commands are being sent the earliest in the queue.
+ */
+ sort(qp->bcms, qp->num_bcms, sizeof(*qp->bcms), cmp_vcd, NULL);
+
+ platform_set_drvdata(pdev, qp);
+
+ dev_dbg(&pdev->dev, "Registered SDM845 ICC\n");
+
+ return ret;
+err:
+ list_for_each_entry(node, &provider->nodes, node_list) {
+ icc_node_del(node);
+ icc_node_destroy(node->id);
+ }
+
+ icc_provider_del(provider);
+ return ret;
+}
+
+static int qnoc_remove(struct platform_device *pdev)
+{
+ struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
+ struct icc_provider *provider = &qp->provider;
+ struct icc_node *n;
+
+ list_for_each_entry(n, &provider->nodes, node_list) {
+ icc_node_del(n);
+ icc_node_destroy(n->id);
+ }
+
+ return icc_provider_del(provider);
+}
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sdm845-rsc-hlos", .data = &sdm845_rsc_hlos },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qnoc_probe,
+ .remove = qnoc_remove,
+ .driver = {
+ .name = "qnoc-sdm845",
+ .of_match_table = qnoc_of_match,
+ },
+};
+module_platform_driver(qnoc_driver);
+
+MODULE_AUTHOR("David Dai <daidavid1@codeaurora.org>");
+MODULE_DESCRIPTION("Qualcomm sdm845 NoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 87ba23a75b38..2a7b78bb98b4 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
static void do_detach(struct iommu_dev_data *dev_data)
{
+ struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
- /* decrease reference counters */
- dev_data->domain->dev_iommu[iommu->index] -= 1;
- dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+ /* Flush IOTLB */
+ domain_flush_tlb_pde(domain);
+
+ /* Wait for the flushes to finish */
+ domain_flush_complete(domain);
+
+ /* decrease reference counters - needs to happen after the flushes */
+ domain->dev_iommu[iommu->index] -= 1;
+ domain->dev_cnt -= 1;
}
/*
@@ -2617,13 +2624,13 @@ out_unmap:
bus_addr = address + s->dma_address + (j << PAGE_SHIFT);
iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
- if (--mapped_pages)
+ if (--mapped_pages == 0)
goto out_free_iova;
}
}
out_free_iova:
- free_iova_fast(&dma_dom->iovad, address, npages);
+ free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
out_err:
return 0;
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index dc9f14811e0f..9c49300e9fb7 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -39,6 +39,7 @@
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <linux/numa.h>
#include <asm/irq_remapping.h>
#include <asm/iommu_table.h>
@@ -144,7 +145,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
- size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+ size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
@@ -477,7 +478,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
if (!node_online(node))
- node = -1;
+ node = NUMA_NO_NODE;
drhd->iommu->node = node;
return 0;
}
@@ -1062,7 +1063,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->msagaw = msagaw;
iommu->segment = drhd->segment;
- iommu->node = -1;
+ iommu->node = NUMA_NO_NODE;
ver = readl(iommu->reg + DMAR_VER_REG);
pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 1bd0cd7168df..05c6bc099d62 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1260,6 +1260,7 @@ static int exynos_iommu_add_device(struct device *dev)
* direct calls to pm_runtime_get/put in this driver.
*/
data->link = device_link_add(dev, data->sysmmu,
+ DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME);
}
iommu_group_put(group);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2bd9ac285c0d..39a33dec4d0b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -47,6 +47,7 @@
#include <linux/dma-contiguous.h>
#include <linux/dma-direct.h>
#include <linux/crash_dump.h>
+#include <linux/numa.h>
#include <asm/irq_remapping.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -363,7 +364,7 @@ static int dmar_map_gfx = 1;
static int dmar_forcedac;
static int intel_iommu_strict;
static int intel_iommu_superpage = 1;
-static int intel_iommu_sm = 1;
+static int intel_iommu_sm;
static int iommu_identity_mapping;
#define IDENTMAP_ALL 1
@@ -456,9 +457,9 @@ static int __init intel_iommu_setup(char *str)
} else if (!strncmp(str, "sp_off", 6)) {
pr_info("Disable supported super page\n");
intel_iommu_superpage = 0;
- } else if (!strncmp(str, "sm_off", 6)) {
- pr_info("Intel-IOMMU: disable scalable mode support\n");
- intel_iommu_sm = 0;
+ } else if (!strncmp(str, "sm_on", 5)) {
+ pr_info("Intel-IOMMU: scalable mode supported\n");
+ intel_iommu_sm = 1;
} else if (!strncmp(str, "tboot_noforce", 13)) {
printk(KERN_INFO
"Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
@@ -1716,7 +1717,7 @@ static struct dmar_domain *alloc_domain(int flags)
return NULL;
memset(domain, 0, sizeof(*domain));
- domain->nid = -1;
+ domain->nid = NUMA_NO_NODE;
domain->flags = flags;
domain->has_iotlb_device = false;
INIT_LIST_HEAD(&domain->devices);
@@ -5294,7 +5295,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
struct iommu_resv_region *entry, *next;
list_for_each_entry_safe(entry, next, head, list) {
- if (entry->type == IOMMU_RESV_RESERVED)
+ if (entry->type == IOMMU_RESV_MSI)
kfree(entry);
}
}
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 6ede4286b835..7e0df67bd3e9 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -232,9 +232,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
spin_lock_init(&dom->pgtlock);
- dom->pgt_va = dma_zalloc_coherent(data->dev,
- M2701_IOMMU_PGT_SIZE,
- &dom->pgt_pa, GFP_KERNEL);
+ dom->pgt_va = dma_alloc_coherent(data->dev, M2701_IOMMU_PGT_SIZE,
+ &dom->pgt_pa, GFP_KERNEL);
if (!dom->pgt_va)
return -ENOMEM;
@@ -442,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev)
iommu_spec.args_count = count;
mtk_iommu_create_mapping(dev, &iommu_spec);
+
+ /* dev->iommu_fwspec might have changed */
+ fwspec = dev_iommu_fwspec_get(dev);
+
of_node_put(iommu_spec.np);
}
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index d8947b28db2d..f04a6df65eb8 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -224,7 +224,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
* If we have reason to believe the IOMMU driver missed the initial
* probe for dev, replay it to get things in order.
*/
- if (dev->bus && !device_iommu_mapped(dev))
+ if (!err && dev->bus && !device_iommu_mapped(dev))
err = iommu_probe_device(dev);
/* Ignore all other errors apart from EPROBE_DEFER */
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c9ba9f377f63..77d4bd93fe4b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1071,7 +1071,8 @@ static int rk_iommu_add_device(struct device *dev)
iommu_group_put(group);
iommu_device_link(&iommu->iommu, dev);
- data->link = device_link_add(dev, iommu->dev, DL_FLAG_PM_RUNTIME);
+ data->link = device_link_add(dev, iommu->dev,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
return 0;
}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3d1e60779078..5438abb1baba 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -129,6 +129,16 @@ config BRCMSTB_L2_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config DAVINCI_AINTC
+ bool
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN
+
+config DAVINCI_CP_INTC
+ bool
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN
+
config DW_APB_ICTL
bool
select GENERIC_IRQ_CHIP
@@ -406,6 +416,15 @@ config IMX_IRQSTEER
help
Support for the i.MX IRQSTEER interrupt multiplexer/remapper.
+config LS1X_IRQ
+ bool "Loongson-1 Interrupt Controller"
+ depends on MACH_LOONGSON32
+ default y
+ select IRQ_DOMAIN
+ select GENERIC_IRQ_CHIP
+ help
+ Support for the Loongson-1 platform Interrupt Controller.
+
endmenu
config SIFIVE_PLIC
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c93713d24b86..85972ae1bd7f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o
obj-$(CONFIG_ATH79) += irq-ath79-misc.o
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
+obj-$(CONFIG_DAVINCI_AINTC) += irq-davinci-aintc.o
+obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o
obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o
obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o
obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o
@@ -94,3 +96,4 @@ obj-$(CONFIG_CSKY_APB_INTC) += irq-csky-apb-intc.o
obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o
obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o
obj-$(CONFIG_MADERA_IRQ) += irq-madera.o
+obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c
index 0e65f609352e..83364fedbf0a 100644
--- a/drivers/irqchip/irq-brcmstb-l2.c
+++ b/drivers/irqchip/irq-brcmstb-l2.c
@@ -129,8 +129,9 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct brcmstb_l2_intc_data *b = gc->private;
+ unsigned long flags;
- irq_gc_lock(gc);
+ irq_gc_lock_irqsave(gc, flags);
/* Save the current mask */
b->saved_mask = irq_reg_readl(gc, ct->regs.mask);
@@ -139,7 +140,7 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
irq_reg_writel(gc, ~gc->wake_active, ct->regs.disable);
irq_reg_writel(gc, gc->wake_active, ct->regs.enable);
}
- irq_gc_unlock(gc);
+ irq_gc_unlock_irqrestore(gc, flags);
}
static void brcmstb_l2_intc_resume(struct irq_data *d)
@@ -147,8 +148,9 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct brcmstb_l2_intc_data *b = gc->private;
+ unsigned long flags;
- irq_gc_lock(gc);
+ irq_gc_lock_irqsave(gc, flags);
if (ct->chip.irq_ack) {
/* Clear unmasked non-wakeup interrupts */
irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active,
@@ -158,7 +160,7 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
/* Restore the saved mask */
irq_reg_writel(gc, b->saved_mask, ct->regs.disable);
irq_reg_writel(gc, ~b->saved_mask, ct->regs.enable);
- irq_gc_unlock(gc);
+ irq_gc_unlock_irqrestore(gc, flags);
}
static int __init brcmstb_l2_intc_of_init(struct device_node *np,
diff --git a/drivers/irqchip/irq-csky-apb-intc.c b/drivers/irqchip/irq-csky-apb-intc.c
index 2543baba8b1f..5a2ec43b7ddd 100644
--- a/drivers/irqchip/irq-csky-apb-intc.c
+++ b/drivers/irqchip/irq-csky-apb-intc.c
@@ -95,7 +95,7 @@ static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr)
/* Setup 64 channel slots */
for (i = 0; i < INTC_IRQS; i += 4)
- writel_relaxed(build_channel_val(i, magic), reg_addr + i);
+ writel(build_channel_val(i, magic), reg_addr + i);
}
static int __init
@@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent)
static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq,
u32 irq_base)
{
- u32 irq;
-
if (hwirq == 0)
return 0;
- while (hwirq) {
- irq = __ffs(hwirq);
- hwirq &= ~BIT(irq);
- handle_domain_irq(root_domain, irq_base + irq, regs);
- }
+ handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs);
return 1;
}
@@ -154,12 +148,16 @@ static void gx_irq_handler(struct pt_regs *regs)
{
bool ret;
- do {
- ret = handle_irq_perbit(regs,
- readl_relaxed(reg_base + GX_INTC_PEN31_00), 0);
- ret |= handle_irq_perbit(regs,
- readl_relaxed(reg_base + GX_INTC_PEN63_32), 32);
- } while (ret);
+retry:
+ ret = handle_irq_perbit(regs,
+ readl(reg_base + GX_INTC_PEN63_32), 32);
+ if (ret)
+ goto retry;
+
+ ret = handle_irq_perbit(regs,
+ readl(reg_base + GX_INTC_PEN31_00), 0);
+ if (ret)
+ goto retry;
}
static int __init
@@ -174,14 +172,14 @@ gx_intc_init(struct device_node *node, struct device_node *parent)
/*
* Initial enable reg to disable all interrupts
*/
- writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00);
- writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32);
+ writel(0x0, reg_base + GX_INTC_NEN31_00);
+ writel(0x0, reg_base + GX_INTC_NEN63_32);
/*
* Initial mask reg with all unmasked, because we only use enalbe reg
*/
- writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00);
- writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32);
+ writel(0x0, reg_base + GX_INTC_NMASK31_00);
+ writel(0x0, reg_base + GX_INTC_NMASK63_32);
setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE);
@@ -204,20 +202,29 @@ static void ck_irq_handler(struct pt_regs *regs)
void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00;
void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32;
- do {
- /* handle 0 - 31 irqs */
- ret = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0);
- ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32);
+retry:
+ /* handle 0 - 63 irqs */
+ ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32);
+ if (ret)
+ goto retry;
- if (nr_irq == INTC_IRQS)
- continue;
+ ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0);
+ if (ret)
+ goto retry;
+
+ if (nr_irq == INTC_IRQS)
+ return;
- /* handle 64 - 127 irqs */
- ret |= handle_irq_perbit(regs,
- readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
- ret |= handle_irq_perbit(regs,
- readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
- } while (ret);
+ /* handle 64 - 127 irqs */
+ ret = handle_irq_perbit(regs,
+ readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
+ if (ret)
+ goto retry;
+
+ ret = handle_irq_perbit(regs,
+ readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
+ if (ret)
+ goto retry;
}
static int __init
@@ -230,11 +237,11 @@ ck_intc_init(struct device_node *node, struct device_node *parent)
return ret;
/* Initial enable reg to disable all interrupts */
- writel_relaxed(0, reg_base + CK_INTC_NEN31_00);
- writel_relaxed(0, reg_base + CK_INTC_NEN63_32);
+ writel(0, reg_base + CK_INTC_NEN31_00);
+ writel(0, reg_base + CK_INTC_NEN63_32);
/* Enable irq intc */
- writel_relaxed(BIT(31), reg_base + CK_INTC_ICR);
+ writel(BIT(31), reg_base + CK_INTC_ICR);
ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0);
ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32);
@@ -260,8 +267,8 @@ ck_dual_intc_init(struct device_node *node, struct device_node *parent)
return ret;
/* Initial enable reg to disable all interrupts */
- writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
- writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
+ writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
+ writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64);
ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96);
diff --git a/drivers/irqchip/irq-davinci-aintc.c b/drivers/irqchip/irq-davinci-aintc.c
new file mode 100644
index 000000000000..810ccc4fe476
--- /dev/null
+++ b/drivers/irqchip/irq-davinci-aintc.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Copyright (C) 2006, 2019 Texas Instruments.
+//
+// Interrupt handler for DaVinci boards.
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/irq-davinci-aintc.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+
+#include <asm/exception.h>
+
+#define DAVINCI_AINTC_FIQ_REG0 0x00
+#define DAVINCI_AINTC_FIQ_REG1 0x04
+#define DAVINCI_AINTC_IRQ_REG0 0x08
+#define DAVINCI_AINTC_IRQ_REG1 0x0c
+#define DAVINCI_AINTC_IRQ_IRQENTRY 0x14
+#define DAVINCI_AINTC_IRQ_ENT_REG0 0x18
+#define DAVINCI_AINTC_IRQ_ENT_REG1 0x1c
+#define DAVINCI_AINTC_IRQ_INCTL_REG 0x20
+#define DAVINCI_AINTC_IRQ_EABASE_REG 0x24
+#define DAVINCI_AINTC_IRQ_INTPRI0_REG 0x30
+#define DAVINCI_AINTC_IRQ_INTPRI7_REG 0x4c
+
+static void __iomem *davinci_aintc_base;
+static struct irq_domain *davinci_aintc_irq_domain;
+
+static inline void davinci_aintc_writel(unsigned long value, int offset)
+{
+ writel_relaxed(value, davinci_aintc_base + offset);
+}
+
+static inline unsigned long davinci_aintc_readl(int offset)
+{
+ return readl_relaxed(davinci_aintc_base + offset);
+}
+
+static __init void
+davinci_aintc_setup_gc(void __iomem *base,
+ unsigned int irq_start, unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_get_domain_generic_chip(davinci_aintc_irq_domain, irq_start);
+ gc->reg_base = base;
+ gc->irq_base = irq_start;
+
+ ct = gc->chip_types;
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+
+ ct->regs.ack = DAVINCI_AINTC_IRQ_REG0;
+ ct->regs.mask = DAVINCI_AINTC_IRQ_ENT_REG0;
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+}
+
+static asmlinkage void __exception_irq_entry
+davinci_aintc_handle_irq(struct pt_regs *regs)
+{
+ int irqnr = davinci_aintc_readl(DAVINCI_AINTC_IRQ_IRQENTRY);
+
+ /*
+ * Use the formula for entry vector index generation from section
+ * 8.3.3 of the manual.
+ */
+ irqnr >>= 2;
+ irqnr -= 1;
+
+ handle_domain_irq(davinci_aintc_irq_domain, irqnr, regs);
+}
+
+/* ARM Interrupt Controller Initialization */
+void __init davinci_aintc_init(const struct davinci_aintc_config *config)
+{
+ unsigned int irq_off, reg_off, prio, shift;
+ void __iomem *req;
+ int ret, irq_base;
+ const u8 *prios;
+
+ req = request_mem_region(config->reg.start,
+ resource_size(&config->reg),
+ "davinci-cp-intc");
+ if (!req) {
+ pr_err("%s: register range busy\n", __func__);
+ return;
+ }
+
+ davinci_aintc_base = ioremap(config->reg.start,
+ resource_size(&config->reg));
+ if (!davinci_aintc_base) {
+ pr_err("%s: unable to ioremap register range\n", __func__);
+ return;
+ }
+
+ /* Clear all interrupt requests */
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG0);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG1);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG0);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG1);
+
+ /* Disable all interrupts */
+ davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_ENT_REG0);
+ davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_ENT_REG1);
+
+ /* Interrupts disabled immediately, IRQ entry reflects all */
+ davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_INCTL_REG);
+
+ /* we don't use the hardware vector table, just its entry addresses */
+ davinci_aintc_writel(0, DAVINCI_AINTC_IRQ_EABASE_REG);
+
+ /* Clear all interrupt requests */
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG0);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG1);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG0);
+ davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG1);
+
+ prios = config->prios;
+ for (reg_off = DAVINCI_AINTC_IRQ_INTPRI0_REG;
+ reg_off <= DAVINCI_AINTC_IRQ_INTPRI7_REG; reg_off += 4) {
+ for (shift = 0, prio = 0; shift < 32; shift += 4, prios++)
+ prio |= (*prios & 0x07) << shift;
+ davinci_aintc_writel(prio, reg_off);
+ }
+
+ irq_base = irq_alloc_descs(-1, 0, config->num_irqs, 0);
+ if (irq_base < 0) {
+ pr_err("%s: unable to allocate interrupt descriptors: %d\n",
+ __func__, irq_base);
+ return;
+ }
+
+ davinci_aintc_irq_domain = irq_domain_add_legacy(NULL,
+ config->num_irqs, irq_base, 0,
+ &irq_domain_simple_ops, NULL);
+ if (!davinci_aintc_irq_domain) {
+ pr_err("%s: unable to create interrupt domain\n", __func__);
+ return;
+ }
+
+ ret = irq_alloc_domain_generic_chips(davinci_aintc_irq_domain, 32, 1,
+ "AINTC", handle_edge_irq,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0, 0);
+ if (ret) {
+ pr_err("%s: unable to allocate generic irq chips for domain\n",
+ __func__);
+ return;
+ }
+
+ for (irq_off = 0, reg_off = 0;
+ irq_off < config->num_irqs;
+ irq_off += 32, reg_off += 0x04)
+ davinci_aintc_setup_gc(davinci_aintc_base + reg_off,
+ irq_base + irq_off, 32);
+
+ set_handle_irq(davinci_aintc_handle_irq);
+}
diff --git a/drivers/irqchip/irq-davinci-cp-intc.c b/drivers/irqchip/irq-davinci-cp-intc.c
new file mode 100644
index 000000000000..276da2772e7f
--- /dev/null
+++ b/drivers/irqchip/irq-davinci-cp-intc.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Author: Steve Chen <schen@mvista.com>
+// Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+// Copyright (C) 2019, Texas Instruments
+//
+// TI Common Platform Interrupt Controller (cp_intc) driver
+
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/irq-davinci-cp-intc.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/exception.h>
+
+#define DAVINCI_CP_INTC_CTRL 0x04
+#define DAVINCI_CP_INTC_HOST_CTRL 0x0c
+#define DAVINCI_CP_INTC_GLOBAL_ENABLE 0x10
+#define DAVINCI_CP_INTC_SYS_STAT_IDX_CLR 0x24
+#define DAVINCI_CP_INTC_SYS_ENABLE_IDX_SET 0x28
+#define DAVINCI_CP_INTC_SYS_ENABLE_IDX_CLR 0x2c
+#define DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET 0x34
+#define DAVINCI_CP_INTC_HOST_ENABLE_IDX_CLR 0x38
+#define DAVINCI_CP_INTC_PRIO_IDX 0x80
+#define DAVINCI_CP_INTC_SYS_STAT_CLR(n) (0x0280 + (n << 2))
+#define DAVINCI_CP_INTC_SYS_ENABLE_CLR(n) (0x0380 + (n << 2))
+#define DAVINCI_CP_INTC_CHAN_MAP(n) (0x0400 + (n << 2))
+#define DAVINCI_CP_INTC_SYS_POLARITY(n) (0x0d00 + (n << 2))
+#define DAVINCI_CP_INTC_SYS_TYPE(n) (0x0d80 + (n << 2))
+#define DAVINCI_CP_INTC_HOST_ENABLE(n) (0x1500 + (n << 2))
+#define DAVINCI_CP_INTC_PRI_INDX_MASK GENMASK(9, 0)
+#define DAVINCI_CP_INTC_GPIR_NONE BIT(31)
+
+static void __iomem *davinci_cp_intc_base;
+static struct irq_domain *davinci_cp_intc_irq_domain;
+
+static inline unsigned int davinci_cp_intc_read(unsigned int offset)
+{
+ return readl_relaxed(davinci_cp_intc_base + offset);
+}
+
+static inline void davinci_cp_intc_write(unsigned long value,
+ unsigned int offset)
+{
+ writel_relaxed(value, davinci_cp_intc_base + offset);
+}
+
+static void davinci_cp_intc_ack_irq(struct irq_data *d)
+{
+ davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_STAT_IDX_CLR);
+}
+
+static void davinci_cp_intc_mask_irq(struct irq_data *d)
+{
+ /* XXX don't know why we need to disable nIRQ here... */
+ davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_CLR);
+ davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_ENABLE_IDX_CLR);
+ davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET);
+}
+
+static void davinci_cp_intc_unmask_irq(struct irq_data *d)
+{
+ davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_ENABLE_IDX_SET);
+}
+
+static int davinci_cp_intc_set_irq_type(struct irq_data *d,
+ unsigned int flow_type)
+{
+ unsigned int reg, mask, polarity, type;
+
+ reg = BIT_WORD(d->hwirq);
+ mask = BIT_MASK(d->hwirq);
+ polarity = davinci_cp_intc_read(DAVINCI_CP_INTC_SYS_POLARITY(reg));
+ type = davinci_cp_intc_read(DAVINCI_CP_INTC_SYS_TYPE(reg));
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_RISING:
+ polarity |= mask;
+ type |= mask;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ polarity &= ~mask;
+ type |= mask;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ polarity |= mask;
+ type &= ~mask;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ polarity &= ~mask;
+ type &= ~mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ davinci_cp_intc_write(polarity, DAVINCI_CP_INTC_SYS_POLARITY(reg));
+ davinci_cp_intc_write(type, DAVINCI_CP_INTC_SYS_TYPE(reg));
+
+ return 0;
+}
+
+static struct irq_chip davinci_cp_intc_irq_chip = {
+ .name = "cp_intc",
+ .irq_ack = davinci_cp_intc_ack_irq,
+ .irq_mask = davinci_cp_intc_mask_irq,
+ .irq_unmask = davinci_cp_intc_unmask_irq,
+ .irq_set_type = davinci_cp_intc_set_irq_type,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static asmlinkage void __exception_irq_entry
+davinci_cp_intc_handle_irq(struct pt_regs *regs)
+{
+ int gpir, irqnr, none;
+
+ /*
+ * The interrupt number is in first ten bits. The NONE field set to 1
+ * indicates a spurious irq.
+ */
+
+ gpir = davinci_cp_intc_read(DAVINCI_CP_INTC_PRIO_IDX);
+ irqnr = gpir & DAVINCI_CP_INTC_PRI_INDX_MASK;
+ none = gpir & DAVINCI_CP_INTC_GPIR_NONE;
+
+ if (unlikely(none)) {
+ pr_err_once("%s: spurious irq!\n", __func__);
+ return;
+ }
+
+ handle_domain_irq(davinci_cp_intc_irq_domain, irqnr, regs);
+}
+
+static int davinci_cp_intc_host_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw);
+
+ irq_set_chip(virq, &davinci_cp_intc_irq_chip);
+ irq_set_probe(virq);
+ irq_set_handler(virq, handle_edge_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops davinci_cp_intc_irq_domain_ops = {
+ .map = davinci_cp_intc_host_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+static int __init
+davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
+ struct device_node *node)
+{
+ unsigned int num_regs = BITS_TO_LONGS(config->num_irqs);
+ int offset, irq_base;
+ void __iomem *req;
+
+ req = request_mem_region(config->reg.start,
+ resource_size(&config->reg),
+ "davinci-cp-intc");
+ if (!req) {
+ pr_err("%s: register range busy\n", __func__);
+ return -EBUSY;
+ }
+
+ davinci_cp_intc_base = ioremap(config->reg.start,
+ resource_size(&config->reg));
+ if (!davinci_cp_intc_base) {
+ pr_err("%s: unable to ioremap register range\n", __func__);
+ return -EINVAL;
+ }
+
+ davinci_cp_intc_write(0, DAVINCI_CP_INTC_GLOBAL_ENABLE);
+
+ /* Disable all host interrupts */
+ davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_ENABLE(0));
+
+ /* Disable system interrupts */
+ for (offset = 0; offset < num_regs; offset++)
+ davinci_cp_intc_write(~0,
+ DAVINCI_CP_INTC_SYS_ENABLE_CLR(offset));
+
+ /* Set to normal mode, no nesting, no priority hold */
+ davinci_cp_intc_write(0, DAVINCI_CP_INTC_CTRL);
+ davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_CTRL);
+
+ /* Clear system interrupt status */
+ for (offset = 0; offset < num_regs; offset++)
+ davinci_cp_intc_write(~0,
+ DAVINCI_CP_INTC_SYS_STAT_CLR(offset));
+
+ /* Enable nIRQ (what about nFIQ?) */
+ davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET);
+
+ /* Default all priorities to channel 7. */
+ num_regs = (config->num_irqs + 3) >> 2; /* 4 channels per register */
+ for (offset = 0; offset < num_regs; offset++)
+ davinci_cp_intc_write(0x07070707,
+ DAVINCI_CP_INTC_CHAN_MAP(offset));
+
+ irq_base = irq_alloc_descs(-1, 0, config->num_irqs, 0);
+ if (irq_base < 0) {
+ pr_err("%s: unable to allocate interrupt descriptors: %d\n",
+ __func__, irq_base);
+ return irq_base;
+ }
+
+ davinci_cp_intc_irq_domain = irq_domain_add_legacy(
+ node, config->num_irqs, irq_base, 0,
+ &davinci_cp_intc_irq_domain_ops, NULL);
+
+ if (!davinci_cp_intc_irq_domain) {
+ pr_err("%s: unable to create an interrupt domain\n", __func__);
+ return -EINVAL;
+ }
+
+ set_handle_irq(davinci_cp_intc_handle_irq);
+
+ /* Enable global interrupt */
+ davinci_cp_intc_write(1, DAVINCI_CP_INTC_GLOBAL_ENABLE);
+
+ return 0;
+}
+
+int __init davinci_cp_intc_init(const struct davinci_cp_intc_config *config)
+{
+ return davinci_cp_intc_do_init(config, NULL);
+}
+
+static int __init davinci_cp_intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct davinci_cp_intc_config config = { };
+ int ret;
+
+ ret = of_address_to_resource(node, 0, &config.reg);
+ if (ret) {
+ pr_err("%s: unable to get the register range from device-tree\n",
+ __func__);
+ return ret;
+ }
+
+ ret = of_property_read_u32(node, "ti,intc-size", &config.num_irqs);
+ if (ret) {
+ pr_err("%s: unable to read the 'ti,intc-size' property\n",
+ __func__);
+ return ret;
+ }
+
+ return davinci_cp_intc_do_init(&config, node);
+}
+IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", davinci_cp_intc_of_init);
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index db20e992a40f..2dd1ff0cf558 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -97,9 +97,14 @@ struct its_device;
* The ITS structure - contains most of the infrastructure, with the
* top-level MSI domain, the command queue, the collections, and the
* list of devices writing to it.
+ *
+ * dev_alloc_lock has to be taken for device allocations, while the
+ * spinlock must be taken to parse data structures such as the device
+ * list.
*/
struct its_node {
raw_spinlock_t lock;
+ struct mutex dev_alloc_lock;
struct list_head entry;
void __iomem *base;
phys_addr_t phys_base;
@@ -156,6 +161,7 @@ struct its_device {
void *itt;
u32 nr_ites;
u32 device_id;
+ bool shared;
};
static struct {
@@ -1580,6 +1586,9 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
nr_irqs /= 2;
} while (nr_irqs > 0);
+ if (!nr_irqs)
+ err = -ENOSPC;
+
if (err)
goto out;
@@ -1737,6 +1746,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
u64 type = GITS_BASER_TYPE(val);
u64 baser_phys, tmp;
u32 alloc_pages;
+ struct page *page;
void *base;
retry_alloc_baser:
@@ -1749,10 +1759,11 @@ retry_alloc_baser:
order = get_order(GITS_BASER_PAGES_MAX * psz);
}
- base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
- if (!base)
+ page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
+ if (!page)
return -ENOMEM;
+ base = (void *)page_address(page);
baser_phys = virt_to_phys(base);
/* Check if the physical address of the memory is above 48bits */
@@ -1946,6 +1957,8 @@ static int its_alloc_tables(struct its_node *its)
indirect = its_parse_indirect_baser(its, baser,
psz, &order,
its->device_ids);
+ break;
+
case GITS_BASER_TYPE_VCPU:
indirect = its_parse_indirect_baser(its, baser,
psz, &order,
@@ -2059,6 +2072,29 @@ static int __init allocate_lpi_tables(void)
return 0;
}
+static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
+{
+ u32 count = 1000000; /* 1s! */
+ bool clean;
+ u64 val;
+
+ val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+ val &= ~GICR_VPENDBASER_Valid;
+ gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+ do {
+ val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+ clean = !(val & GICR_VPENDBASER_Dirty);
+ if (!clean) {
+ count--;
+ cpu_relax();
+ udelay(1);
+ }
+ } while (!clean && count);
+
+ return val;
+}
+
static void its_cpu_init_lpis(void)
{
void __iomem *rbase = gic_data_rdist_rd_base();
@@ -2144,6 +2180,30 @@ static void its_cpu_init_lpis(void)
val |= GICR_CTLR_ENABLE_LPIS;
writel_relaxed(val, rbase + GICR_CTLR);
+ if (gic_rdists->has_vlpis) {
+ void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+
+ /*
+ * It's possible for CPU to receive VLPIs before it is
+ * sheduled as a vPE, especially for the first CPU, and the
+ * VLPI with INTID larger than 2^(IDbits+1) will be considered
+ * as out of range and dropped by GIC.
+ * So we initialize IDbits to known value to avoid VLPI drop.
+ */
+ val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
+ pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
+ smp_processor_id(), val);
+ gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+
+ /*
+ * Also clear Valid bit of GICR_VPENDBASER, in case some
+ * ancient programming gets left in and has possibility of
+ * corrupting memory.
+ */
+ val = its_clear_vpend_valid(vlpi_base);
+ WARN_ON(val & GICR_VPENDBASER_Dirty);
+ }
+
/* Make sure the GIC has seen the above */
dsb(sy);
out:
@@ -2236,7 +2296,8 @@ static struct its_baser *its_get_baser(struct its_node *its, u32 type)
return NULL;
}
-static bool its_alloc_table_entry(struct its_baser *baser, u32 id)
+static bool its_alloc_table_entry(struct its_node *its,
+ struct its_baser *baser, u32 id)
{
struct page *page;
u32 esz, idx;
@@ -2256,7 +2317,8 @@ static bool its_alloc_table_entry(struct its_baser *baser, u32 id)
/* Allocate memory for 2nd level table */
if (!table[idx]) {
- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(baser->psz));
+ page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ get_order(baser->psz));
if (!page)
return false;
@@ -2287,7 +2349,7 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
if (!baser)
return (ilog2(dev_id) < its->device_ids);
- return its_alloc_table_entry(baser, dev_id);
+ return its_alloc_table_entry(its, baser, dev_id);
}
static bool its_alloc_vpe_table(u32 vpe_id)
@@ -2311,7 +2373,7 @@ static bool its_alloc_vpe_table(u32 vpe_id)
if (!baser)
return false;
- if (!its_alloc_table_entry(baser, vpe_id))
+ if (!its_alloc_table_entry(its, baser, vpe_id))
return false;
}
@@ -2345,7 +2407,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
nr_ites = max(2, nvecs);
sz = nr_ites * its->ite_size;
sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
- itt = kzalloc(sz, GFP_KERNEL);
+ itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
@@ -2399,13 +2461,14 @@ static void its_free_device(struct its_device *its_dev)
kfree(its_dev);
}
-static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
{
int idx;
- idx = find_first_zero_bit(dev->event_map.lpi_map,
- dev->event_map.nr_lpis);
- if (idx == dev->event_map.nr_lpis)
+ idx = bitmap_find_free_region(dev->event_map.lpi_map,
+ dev->event_map.nr_lpis,
+ get_count_order(nvecs));
+ if (idx < 0)
return -ENOSPC;
*hwirq = dev->event_map.lpi_base + idx;
@@ -2421,6 +2484,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
struct its_device *its_dev;
struct msi_domain_info *msi_info;
u32 dev_id;
+ int err = 0;
/*
* We ignore "dev" entierely, and rely on the dev_id that has
@@ -2443,6 +2507,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
return -EINVAL;
}
+ mutex_lock(&its->dev_alloc_lock);
its_dev = its_find_device(its, dev_id);
if (its_dev) {
/*
@@ -2450,18 +2515,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
* another alias (PCI bridge of some sort). No need to
* create the device.
*/
+ its_dev->shared = true;
pr_debug("Reusing ITT for devID %x\n", dev_id);
goto out;
}
its_dev = its_create_device(its, dev_id, nvec, true);
- if (!its_dev)
- return -ENOMEM;
+ if (!its_dev) {
+ err = -ENOMEM;
+ goto out;
+ }
pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
out:
+ mutex_unlock(&its->dev_alloc_lock);
info->scratchpad[0].ptr = its_dev;
- return 0;
+ return err;
}
static struct msi_domain_ops its_msi_domain_ops = {
@@ -2501,21 +2570,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
int err;
int i;
- for (i = 0; i < nr_irqs; i++) {
- err = its_alloc_device_irq(its_dev, &hwirq);
- if (err)
- return err;
+ err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
+ if (err)
+ return err;
- err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
+ for (i = 0; i < nr_irqs; i++) {
+ err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
if (err)
return err;
irq_domain_set_hwirq_and_chip(domain, virq + i,
- hwirq, &its_irq_chip, its_dev);
+ hwirq + i, &its_irq_chip, its_dev);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
pr_debug("ID:%d pID:%d vID:%d\n",
- (int)(hwirq - its_dev->event_map.lpi_base),
- (int) hwirq, virq + i);
+ (int)(hwirq + i - its_dev->event_map.lpi_base),
+ (int)(hwirq + i), virq + i);
}
return 0;
@@ -2565,6 +2634,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
{
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+ struct its_node *its = its_dev->its;
int i;
for (i = 0; i < nr_irqs; i++) {
@@ -2579,8 +2649,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
irq_domain_reset_irq_data(data);
}
- /* If all interrupts have been freed, start mopping the floor */
- if (bitmap_empty(its_dev->event_map.lpi_map,
+ mutex_lock(&its->dev_alloc_lock);
+
+ /*
+ * If all interrupts have been freed, start mopping the
+ * floor. This is conditionned on the device not being shared.
+ */
+ if (!its_dev->shared &&
+ bitmap_empty(its_dev->event_map.lpi_map,
its_dev->event_map.nr_lpis)) {
its_lpi_free(its_dev->event_map.lpi_map,
its_dev->event_map.lpi_base,
@@ -2592,6 +2668,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
its_free_device(its_dev);
}
+ mutex_unlock(&its->dev_alloc_lock);
+
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
}
@@ -2754,26 +2832,11 @@ static void its_vpe_schedule(struct its_vpe *vpe)
static void its_vpe_deschedule(struct its_vpe *vpe)
{
void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
- u32 count = 1000000; /* 1s! */
- bool clean;
u64 val;
- /* We're being scheduled out */
- val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
- val &= ~GICR_VPENDBASER_Valid;
- gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+ val = its_clear_vpend_valid(vlpi_base);
- do {
- val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
- clean = !(val & GICR_VPENDBASER_Dirty);
- if (!clean) {
- count--;
- cpu_relax();
- udelay(1);
- }
- } while (!clean && count);
-
- if (unlikely(!clean && !count)) {
+ if (unlikely(val & GICR_VPENDBASER_Dirty)) {
pr_err_ratelimited("ITS virtual pending table not cleaning\n");
vpe->idai = false;
vpe->pending_last = true;
@@ -3486,6 +3549,7 @@ static int __init its_probe_one(struct resource *res,
void __iomem *its_base;
u32 val, ctlr;
u64 baser, tmp, typer;
+ struct page *page;
int err;
its_base = ioremap(res->start, resource_size(res));
@@ -3516,6 +3580,7 @@ static int __init its_probe_one(struct resource *res,
}
raw_spin_lock_init(&its->lock);
+ mutex_init(&its->dev_alloc_lock);
INIT_LIST_HEAD(&its->entry);
INIT_LIST_HEAD(&its->its_device_list);
typer = gic_read_typer(its_base + GITS_TYPER);
@@ -3541,12 +3606,13 @@ static int __init its_probe_one(struct resource *res,
its->numa_node = numa_node;
- its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- get_order(ITS_CMD_QUEUE_SZ));
- if (!its->cmd_base) {
+ page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ get_order(ITS_CMD_QUEUE_SZ));
+ if (!page) {
err = -ENOMEM;
goto out_free_its;
}
+ its->cmd_base = (void *)page_address(page);
its->cmd_write = its->cmd_base;
its->fwnode_handle = handle;
its->get_msi_base = its_irq_get_msi_base;
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
index ad70e7c416e3..fbfa7ff6deb1 100644
--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -24,7 +24,7 @@ struct mbi_range {
unsigned long *bm;
};
-static struct mutex mbi_lock;
+static DEFINE_MUTEX(mbi_lock);
static phys_addr_t mbi_phys_base;
static struct mbi_range *mbi_ranges;
static unsigned int mbi_range_nr;
diff --git a/drivers/irqchip/irq-i8259.c b/drivers/irqchip/irq-i8259.c
index b0d4aab1a58c..d000870d9b6b 100644
--- a/drivers/irqchip/irq-i8259.c
+++ b/drivers/irqchip/irq-i8259.c
@@ -225,14 +225,6 @@ static struct syscore_ops i8259_syscore_ops = {
.shutdown = i8259A_shutdown,
};
-static int __init i8259A_init_sysfs(void)
-{
- register_syscore_ops(&i8259_syscore_ops);
- return 0;
-}
-
-device_initcall(i8259A_init_sysfs);
-
static void init_8259A(int auto_eoi)
{
unsigned long flags;
@@ -332,6 +324,7 @@ struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
panic("Failed to add i8259 IRQ domain");
setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
+ register_syscore_ops(&i8259_syscore_ops);
return domain;
}
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 5b3f1d735685..d1098f4da6a4 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -10,10 +10,11 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/spinlock.h>
-#define CTRL_STRIDE_OFF(_t, _r) (_t * 8 * _r)
+#define CTRL_STRIDE_OFF(_t, _r) (_t * 4 * _r)
#define CHANCTRL 0x0
#define CHANMASK(n, t) (CTRL_STRIDE_OFF(t, 0) + 0x4 * (n) + 0x4)
#define CHANSET(n, t) (CTRL_STRIDE_OFF(t, 1) + 0x4 * (n) + 0x4)
@@ -21,12 +22,15 @@
#define CHAN_MINTDIS(t) (CTRL_STRIDE_OFF(t, 3) + 0x4)
#define CHAN_MASTRSTAT(t) (CTRL_STRIDE_OFF(t, 3) + 0x8)
+#define CHAN_MAX_OUTPUT_INT 0x8
+
struct irqsteer_data {
void __iomem *regs;
struct clk *ipg_clk;
- int irq;
+ int irq[CHAN_MAX_OUTPUT_INT];
+ int irq_count;
raw_spinlock_t lock;
- int irq_groups;
+ int reg_num;
int channel;
struct irq_domain *domain;
u32 *saved_reg;
@@ -35,7 +39,7 @@ struct irqsteer_data {
static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
unsigned long irqnum)
{
- return (data->irq_groups * 2 - irqnum / 32 - 1);
+ return (data->reg_num - irqnum / 32 - 1);
}
static void imx_irqsteer_irq_unmask(struct irq_data *d)
@@ -46,9 +50,9 @@ static void imx_irqsteer_irq_unmask(struct irq_data *d)
u32 val;
raw_spin_lock_irqsave(&data->lock, flags);
- val = readl_relaxed(data->regs + CHANMASK(idx, data->irq_groups));
+ val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
val |= BIT(d->hwirq % 32);
- writel_relaxed(val, data->regs + CHANMASK(idx, data->irq_groups));
+ writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
raw_spin_unlock_irqrestore(&data->lock, flags);
}
@@ -60,9 +64,9 @@ static void imx_irqsteer_irq_mask(struct irq_data *d)
u32 val;
raw_spin_lock_irqsave(&data->lock, flags);
- val = readl_relaxed(data->regs + CHANMASK(idx, data->irq_groups));
+ val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
val &= ~BIT(d->hwirq % 32);
- writel_relaxed(val, data->regs + CHANMASK(idx, data->irq_groups));
+ writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
raw_spin_unlock_irqrestore(&data->lock, flags);
}
@@ -87,23 +91,47 @@ static const struct irq_domain_ops imx_irqsteer_domain_ops = {
.xlate = irq_domain_xlate_onecell,
};
+static int imx_irqsteer_get_hwirq_base(struct irqsteer_data *data, u32 irq)
+{
+ int i;
+
+ for (i = 0; i < data->irq_count; i++) {
+ if (data->irq[i] == irq)
+ return i * 64;
+ }
+
+ return -EINVAL;
+}
+
static void imx_irqsteer_irq_handler(struct irq_desc *desc)
{
struct irqsteer_data *data = irq_desc_get_handler_data(desc);
- int i;
+ int hwirq;
+ int irq, i;
chained_irq_enter(irq_desc_get_chip(desc), desc);
- for (i = 0; i < data->irq_groups * 64; i += 32) {
- int idx = imx_irqsteer_get_reg_index(data, i);
+ irq = irq_desc_get_irq(desc);
+ hwirq = imx_irqsteer_get_hwirq_base(data, irq);
+ if (hwirq < 0) {
+ pr_warn("%s: unable to get hwirq base for irq %d\n",
+ __func__, irq);
+ return;
+ }
+
+ for (i = 0; i < 2; i++, hwirq += 32) {
+ int idx = imx_irqsteer_get_reg_index(data, hwirq);
unsigned long irqmap;
int pos, virq;
+ if (hwirq >= data->reg_num * 32)
+ break;
+
irqmap = readl_relaxed(data->regs +
- CHANSTATUS(idx, data->irq_groups));
+ CHANSTATUS(idx, data->reg_num));
for_each_set_bit(pos, &irqmap, 32) {
- virq = irq_find_mapping(data->domain, pos + i);
+ virq = irq_find_mapping(data->domain, pos + hwirq);
if (virq)
generic_handle_irq(virq);
}
@@ -117,7 +145,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct irqsteer_data *data;
struct resource *res;
- int ret;
+ u32 irqs_num;
+ int i, ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -130,12 +159,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
return PTR_ERR(data->regs);
}
- data->irq = platform_get_irq(pdev, 0);
- if (data->irq <= 0) {
- dev_err(&pdev->dev, "failed to get irq\n");
- return -ENODEV;
- }
-
data->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(data->ipg_clk)) {
ret = PTR_ERR(data->ipg_clk);
@@ -146,12 +169,19 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
raw_spin_lock_init(&data->lock);
- of_property_read_u32(np, "fsl,irq-groups", &data->irq_groups);
+ of_property_read_u32(np, "fsl,num-irqs", &irqs_num);
of_property_read_u32(np, "fsl,channel", &data->channel);
+ /*
+ * There is one output irq for each group of 64 inputs.
+ * One register bit map can represent 32 input interrupts.
+ */
+ data->irq_count = DIV_ROUND_UP(irqs_num, 64);
+ data->reg_num = irqs_num / 32;
+
if (IS_ENABLED(CONFIG_PM_SLEEP)) {
data->saved_reg = devm_kzalloc(&pdev->dev,
- sizeof(u32) * data->irq_groups * 2,
+ sizeof(u32) * data->reg_num,
GFP_KERNEL);
if (!data->saved_reg)
return -ENOMEM;
@@ -166,27 +196,48 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
/* steer all IRQs into configured channel */
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
- data->domain = irq_domain_add_linear(np, data->irq_groups * 64,
+ data->domain = irq_domain_add_linear(np, data->reg_num * 32,
&imx_irqsteer_domain_ops, data);
if (!data->domain) {
dev_err(&pdev->dev, "failed to create IRQ domain\n");
- clk_disable_unprepare(data->ipg_clk);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
+ ret = -EINVAL;
+ goto out;
}
- irq_set_chained_handler_and_data(data->irq, imx_irqsteer_irq_handler,
- data);
+ for (i = 0; i < data->irq_count; i++) {
+ data->irq[i] = irq_of_parse_and_map(np, i);
+ if (!data->irq[i]) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ irq_set_chained_handler_and_data(data->irq[i],
+ imx_irqsteer_irq_handler,
+ data);
+ }
platform_set_drvdata(pdev, data);
return 0;
+out:
+ clk_disable_unprepare(data->ipg_clk);
+ return ret;
}
static int imx_irqsteer_remove(struct platform_device *pdev)
{
struct irqsteer_data *irqsteer_data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < irqsteer_data->irq_count; i++)
+ irq_set_chained_handler_and_data(irqsteer_data->irq[i],
+ NULL, NULL);
- irq_set_chained_handler_and_data(irqsteer_data->irq, NULL, NULL);
irq_domain_remove(irqsteer_data->domain);
clk_disable_unprepare(irqsteer_data->ipg_clk);
@@ -199,9 +250,9 @@ static void imx_irqsteer_save_regs(struct irqsteer_data *data)
{
int i;
- for (i = 0; i < data->irq_groups * 2; i++)
+ for (i = 0; i < data->reg_num; i++)
data->saved_reg[i] = readl_relaxed(data->regs +
- CHANMASK(i, data->irq_groups));
+ CHANMASK(i, data->reg_num));
}
static void imx_irqsteer_restore_regs(struct irqsteer_data *data)
@@ -209,9 +260,9 @@ static void imx_irqsteer_restore_regs(struct irqsteer_data *data)
int i;
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
- for (i = 0; i < data->irq_groups * 2; i++)
+ for (i = 0; i < data->reg_num; i++)
writel_relaxed(data->saved_reg[i],
- data->regs + CHANMASK(i, data->irq_groups));
+ data->regs + CHANMASK(i, data->reg_num));
}
static int imx_irqsteer_suspend(struct device *dev)
diff --git a/drivers/irqchip/irq-ls1x.c b/drivers/irqchip/irq-ls1x.c
new file mode 100644
index 000000000000..86b72fbd3b45
--- /dev/null
+++ b/drivers/irqchip/irq-ls1x.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019, Jiaxun Yang <jiaxun.yang@flygoat.com>
+ * Loongson-1 platform IRQ support
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/irqchip.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
+
+#define LS_REG_INTC_STATUS 0x00
+#define LS_REG_INTC_EN 0x04
+#define LS_REG_INTC_SET 0x08
+#define LS_REG_INTC_CLR 0x0c
+#define LS_REG_INTC_POL 0x10
+#define LS_REG_INTC_EDGE 0x14
+
+/**
+ * struct ls1x_intc_priv - private ls1x-intc data.
+ * @domain: IRQ domain.
+ * @intc_base: IO Base of intc registers.
+ */
+
+struct ls1x_intc_priv {
+ struct irq_domain *domain;
+ void __iomem *intc_base;
+};
+
+
+static void ls1x_chained_handle_irq(struct irq_desc *desc)
+{
+ struct ls1x_intc_priv *priv = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u32 pending;
+
+ chained_irq_enter(chip, desc);
+ pending = readl(priv->intc_base + LS_REG_INTC_STATUS) &
+ readl(priv->intc_base + LS_REG_INTC_EN);
+
+ if (!pending)
+ spurious_interrupt();
+
+ while (pending) {
+ int bit = __ffs(pending);
+
+ generic_handle_irq(irq_find_mapping(priv->domain, bit));
+ pending &= ~BIT(bit);
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void ls_intc_set_bit(struct irq_chip_generic *gc,
+ unsigned int offset,
+ u32 mask, bool set)
+{
+ if (set)
+ writel(readl(gc->reg_base + offset) | mask,
+ gc->reg_base + offset);
+ else
+ writel(readl(gc->reg_base + offset) & ~mask,
+ gc->reg_base + offset);
+}
+
+static int ls_intc_set_type(struct irq_data *data, unsigned int type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ u32 mask = data->mask;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
+ ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
+ ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
+ ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
+ ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ irqd_set_trigger_type(data, type);
+ return irq_setup_alt_chip(data, type);
+}
+
+
+static int __init ls1x_intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ struct ls1x_intc_priv *priv;
+ int parent_irq, err = 0;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->intc_base = of_iomap(node, 0);
+ if (!priv->intc_base) {
+ err = -ENODEV;
+ goto out_free_priv;
+ }
+
+ parent_irq = irq_of_parse_and_map(node, 0);
+ if (!parent_irq) {
+ pr_err("ls1x-irq: unable to get parent irq\n");
+ err = -ENODEV;
+ goto out_iounmap;
+ }
+
+ /* Set up an IRQ domain */
+ priv->domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops,
+ NULL);
+ if (!priv->domain) {
+ pr_err("ls1x-irq: cannot add IRQ domain\n");
+ goto out_iounmap;
+ }
+
+ err = irq_alloc_domain_generic_chips(priv->domain, 32, 2,
+ node->full_name, handle_level_irq,
+ IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN, 0,
+ IRQ_GC_INIT_MASK_CACHE);
+ if (err) {
+ pr_err("ls1x-irq: unable to register IRQ domain\n");
+ goto out_free_domain;
+ }
+
+ /* Mask all irqs */
+ writel(0x0, priv->intc_base + LS_REG_INTC_EN);
+
+ /* Ack all irqs */
+ writel(0xffffffff, priv->intc_base + LS_REG_INTC_CLR);
+
+ /* Set all irqs to high level triggered */
+ writel(0xffffffff, priv->intc_base + LS_REG_INTC_POL);
+
+ gc = irq_get_domain_generic_chip(priv->domain, 0);
+
+ gc->reg_base = priv->intc_base;
+
+ ct = gc->chip_types;
+ ct[0].type = IRQ_TYPE_LEVEL_MASK;
+ ct[0].regs.mask = LS_REG_INTC_EN;
+ ct[0].regs.ack = LS_REG_INTC_CLR;
+ ct[0].chip.irq_unmask = irq_gc_mask_set_bit;
+ ct[0].chip.irq_mask = irq_gc_mask_clr_bit;
+ ct[0].chip.irq_ack = irq_gc_ack_set_bit;
+ ct[0].chip.irq_set_type = ls_intc_set_type;
+ ct[0].handler = handle_level_irq;
+
+ ct[1].type = IRQ_TYPE_EDGE_BOTH;
+ ct[1].regs.mask = LS_REG_INTC_EN;
+ ct[1].regs.ack = LS_REG_INTC_CLR;
+ ct[1].chip.irq_unmask = irq_gc_mask_set_bit;
+ ct[1].chip.irq_mask = irq_gc_mask_clr_bit;
+ ct[1].chip.irq_ack = irq_gc_ack_set_bit;
+ ct[1].chip.irq_set_type = ls_intc_set_type;
+ ct[1].handler = handle_edge_irq;
+
+ irq_set_chained_handler_and_data(parent_irq,
+ ls1x_chained_handle_irq, priv);
+
+ return 0;
+
+out_free_domain:
+ irq_domain_remove(priv->domain);
+out_iounmap:
+ iounmap(priv->intc_base);
+out_free_priv:
+ kfree(priv);
+
+ return err;
+}
+
+IRQCHIP_DECLARE(ls1x_intc, "loongson,ls1x-intc", ls1x_intc_of_init);
diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c
index e9256dee1a45..8b81271c823c 100644
--- a/drivers/irqchip/irq-madera.c
+++ b/drivers/irqchip/irq-madera.c
@@ -7,7 +7,6 @@
*/
#include <linux/module.h>
-#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
@@ -16,7 +15,6 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/irqchip/irq-madera.h>
#include <linux/mfd/madera/core.h>
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
index 25f32e1d7764..3496b61a312a 100644
--- a/drivers/irqchip/irq-mmp.c
+++ b/drivers/irqchip/irq-mmp.c
@@ -34,6 +34,9 @@
#define SEL_INT_PENDING (1 << 6)
#define SEL_INT_NUM_MASK 0x3f
+#define MMP2_ICU_INT_ROUTE_PJ4_IRQ (1 << 5)
+#define MMP2_ICU_INT_ROUTE_PJ4_FIQ (1 << 6)
+
struct icu_chip_data {
int nr_irqs;
unsigned int virq_base;
@@ -190,7 +193,8 @@ static const struct mmp_intc_conf mmp_conf = {
static const struct mmp_intc_conf mmp2_conf = {
.conf_enable = 0x20,
.conf_disable = 0x0,
- .conf_mask = 0x7f,
+ .conf_mask = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
+ MMP2_ICU_INT_ROUTE_PJ4_FIQ,
};
static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 357e9daf94ae..cf755964f2f8 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -59,62 +59,83 @@ static void __iomem *plic_regs;
struct plic_handler {
bool present;
- int ctxid;
+ void __iomem *hart_base;
+ /*
+ * Protect mask operations on the registers given that we can't
+ * assume atomic memory operations work on them.
+ */
+ raw_spinlock_t enable_lock;
+ void __iomem *enable_base;
};
static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
-static inline void __iomem *plic_hart_offset(int ctxid)
-{
- return plic_regs + CONTEXT_BASE + ctxid * CONTEXT_PER_HART;
-}
-
-static inline u32 __iomem *plic_enable_base(int ctxid)
-{
- return plic_regs + ENABLE_BASE + ctxid * ENABLE_PER_HART;
-}
-
-/*
- * Protect mask operations on the registers given that we can't assume that
- * atomic memory operations work on them.
- */
-static DEFINE_RAW_SPINLOCK(plic_toggle_lock);
-
-static inline void plic_toggle(int ctxid, int hwirq, int enable)
+static inline void plic_toggle(struct plic_handler *handler,
+ int hwirq, int enable)
{
- u32 __iomem *reg = plic_enable_base(ctxid) + (hwirq / 32);
+ u32 __iomem *reg = handler->enable_base + (hwirq / 32) * sizeof(u32);
u32 hwirq_mask = 1 << (hwirq % 32);
- raw_spin_lock(&plic_toggle_lock);
+ raw_spin_lock(&handler->enable_lock);
if (enable)
writel(readl(reg) | hwirq_mask, reg);
else
writel(readl(reg) & ~hwirq_mask, reg);
- raw_spin_unlock(&plic_toggle_lock);
+ raw_spin_unlock(&handler->enable_lock);
}
-static inline void plic_irq_toggle(struct irq_data *d, int enable)
+static inline void plic_irq_toggle(const struct cpumask *mask,
+ int hwirq, int enable)
{
int cpu;
- writel(enable, plic_regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
- for_each_cpu(cpu, irq_data_get_affinity_mask(d)) {
+ writel(enable, plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID);
+ for_each_cpu(cpu, mask) {
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
if (handler->present)
- plic_toggle(handler->ctxid, d->hwirq, enable);
+ plic_toggle(handler, hwirq, enable);
}
}
static void plic_irq_enable(struct irq_data *d)
{
- plic_irq_toggle(d, 1);
+ unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
+ cpu_online_mask);
+ if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
+ return;
+ plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
}
static void plic_irq_disable(struct irq_data *d)
{
- plic_irq_toggle(d, 0);
+ plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
}
+#ifdef CONFIG_SMP
+static int plic_set_affinity(struct irq_data *d,
+ const struct cpumask *mask_val, bool force)
+{
+ unsigned int cpu;
+
+ if (force)
+ cpu = cpumask_first(mask_val);
+ else
+ cpu = cpumask_any_and(mask_val, cpu_online_mask);
+
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ if (!irqd_irq_disabled(d)) {
+ plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
+ plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
+ }
+
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+ return IRQ_SET_MASK_OK_DONE;
+}
+#endif
+
static struct irq_chip plic_chip = {
.name = "SiFive PLIC",
/*
@@ -123,6 +144,9 @@ static struct irq_chip plic_chip = {
*/
.irq_enable = plic_irq_enable,
.irq_disable = plic_irq_disable,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = plic_set_affinity,
+#endif
};
static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
@@ -150,7 +174,7 @@ static struct irq_domain *plic_irqdomain;
static void plic_handle_irq(struct pt_regs *regs)
{
struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
- void __iomem *claim = plic_hart_offset(handler->ctxid) + CONTEXT_CLAIM;
+ void __iomem *claim = handler->hart_base + CONTEXT_CLAIM;
irq_hw_number_t hwirq;
WARN_ON_ONCE(!handler->present);
@@ -186,7 +210,7 @@ static int plic_find_hart_id(struct device_node *node)
static int __init plic_init(struct device_node *node,
struct device_node *parent)
{
- int error = 0, nr_handlers, nr_mapped = 0, i;
+ int error = 0, nr_contexts, nr_handlers = 0, i;
u32 nr_irqs;
if (plic_regs) {
@@ -203,10 +227,10 @@ static int __init plic_init(struct device_node *node,
if (WARN_ON(!nr_irqs))
goto out_iounmap;
- nr_handlers = of_irq_count(node);
- if (WARN_ON(!nr_handlers))
+ nr_contexts = of_irq_count(node);
+ if (WARN_ON(!nr_contexts))
goto out_iounmap;
- if (WARN_ON(nr_handlers < num_possible_cpus()))
+ if (WARN_ON(nr_contexts < num_possible_cpus()))
goto out_iounmap;
error = -ENOMEM;
@@ -215,7 +239,7 @@ static int __init plic_init(struct device_node *node,
if (WARN_ON(!plic_irqdomain))
goto out_iounmap;
- for (i = 0; i < nr_handlers; i++) {
+ for (i = 0; i < nr_contexts; i++) {
struct of_phandle_args parent;
struct plic_handler *handler;
irq_hw_number_t hwirq;
@@ -237,19 +261,33 @@ static int __init plic_init(struct device_node *node,
}
cpu = riscv_hartid_to_cpuid(hartid);
+ if (cpu < 0) {
+ pr_warn("Invalid cpuid for context %d\n", i);
+ continue;
+ }
+
handler = per_cpu_ptr(&plic_handlers, cpu);
+ if (handler->present) {
+ pr_warn("handler already present for context %d.\n", i);
+ continue;
+ }
+
handler->present = true;
- handler->ctxid = i;
+ handler->hart_base =
+ plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART;
+ raw_spin_lock_init(&handler->enable_lock);
+ handler->enable_base =
+ plic_regs + ENABLE_BASE + i * ENABLE_PER_HART;
/* priority must be > threshold to trigger an interrupt */
- writel(0, plic_hart_offset(i) + CONTEXT_THRESHOLD);
+ writel(0, handler->hart_base + CONTEXT_THRESHOLD);
for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
- plic_toggle(i, hwirq, 0);
- nr_mapped++;
+ plic_toggle(handler, hwirq, 0);
+ nr_handlers++;
}
- pr_info("mapped %d interrupts to %d (out of %d) handlers.\n",
- nr_irqs, nr_mapped, nr_handlers);
+ pr_info("mapped %d interrupts with %d handlers for %d contexts.\n",
+ nr_irqs, nr_handlers, nr_contexts);
set_handle_irq(plic_handle_irq);
return 0;
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 6edfd4bfa169..a93296b9b45d 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -822,6 +822,7 @@ out_unmap:
static const struct irq_domain_ops stm32_exti_h_domain_ops = {
.alloc = stm32_exti_h_domain_alloc,
.free = irq_domain_free_irqs_common,
+ .xlate = irq_domain_xlate_twocell,
};
static int
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index 5385f5768345..27933338f7b3 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -71,14 +71,17 @@ static void xtensa_mx_irq_mask(struct irq_data *d)
unsigned int mask = 1u << d->hwirq;
if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
- XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
- set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
- HW_IRQ_MX_BASE), MIENG);
- } else {
- mask = __this_cpu_read(cached_irq_mask) & ~mask;
- __this_cpu_write(cached_irq_mask, mask);
- xtensa_set_sr(mask, intenable);
+ XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+ unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+ if (ext_irq >= HW_IRQ_MX_BASE) {
+ set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG);
+ return;
+ }
}
+ mask = __this_cpu_read(cached_irq_mask) & ~mask;
+ __this_cpu_write(cached_irq_mask, mask);
+ xtensa_set_sr(mask, intenable);
}
static void xtensa_mx_irq_unmask(struct irq_data *d)
@@ -86,14 +89,17 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
unsigned int mask = 1u << d->hwirq;
if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
- XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
- set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
- HW_IRQ_MX_BASE), MIENGSET);
- } else {
- mask |= __this_cpu_read(cached_irq_mask);
- __this_cpu_write(cached_irq_mask, mask);
- xtensa_set_sr(mask, intenable);
+ XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+ unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+ if (ext_irq >= HW_IRQ_MX_BASE) {
+ set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET);
+ return;
+ }
}
+ mask |= __this_cpu_read(cached_irq_mask);
+ __this_cpu_write(cached_irq_mask, mask);
+ xtensa_set_sr(mask, intenable);
}
static void xtensa_mx_irq_enable(struct irq_data *d)
@@ -113,7 +119,11 @@ static void xtensa_mx_irq_ack(struct irq_data *d)
static int xtensa_mx_irq_retrigger(struct irq_data *d)
{
- xtensa_set_sr(1 << d->hwirq, intset);
+ unsigned int mask = 1u << d->hwirq;
+
+ if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+ return 0;
+ xtensa_set_sr(mask, intset);
return 1;
}
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
index c200234dd2c9..ab12328be5ee 100644
--- a/drivers/irqchip/irq-xtensa-pic.c
+++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -70,7 +70,11 @@ static void xtensa_irq_ack(struct irq_data *d)
static int xtensa_irq_retrigger(struct irq_data *d)
{
- xtensa_set_sr(1 << d->hwirq, intset);
+ unsigned int mask = 1u << d->hwirq;
+
+ if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+ return 0;
+ xtensa_set_sr(mask, intset);
return 1;
}
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index ab0b63a4d045..e1de8b1a1001 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -633,7 +633,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
flush_send_queue(cs);
break;
}
- /* Pass through */
+ /* fall through */
default:
/* pass through to underlying serial device */
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 4ac378e48902..40ca1e8fa09f 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo)
int i, j;
for (j = 0; j < AVM_MAXVERSION; j++)
- cinfo->version[j] = "\0\0" + 1;
+ cinfo->version[j] = "";
for (i = 0, j = 0;
j < AVM_MAXVERSION && i < cinfo->versionlen;
j++, i += cinfo->versionbuf[i] + 1)
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 6d05946b445e..26e3182bbca8 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -262,8 +262,10 @@ hfcsusb_ph_info(struct hfcsusb *hw)
struct dchannel *dch = &hw->dch;
int i;
- phi = kzalloc(sizeof(struct ph_info) +
- dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC);
+ phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
+ if (!phi)
+ return;
+
phi->dch.ch.protocol = hw->protocol;
phi->dch.ch.Flags = dch->Flags;
phi->dch.state = dch->state;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 81dd465afcf4..71a8312592d6 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -656,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
schedule_event(bcs, B_ACKPENDING);
}
- dev_kfree_skb_any(bcs->tx_skb);
+ dev_consume_skb_any(bcs->tx_skb);
bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index e932a152c405..d7b011c8d692 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -332,7 +332,7 @@ static int make_raw_data_56k(struct BCState *bcs) {
bitcnt = 0;
}
val >>= 1;
- };
+ }
fcs = PPP_INITFCS;
for (i = 0; i < bcs->tx_skb->len; i++) {
val = bcs->tx_skb->data[i];
@@ -415,7 +415,7 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt) {
else { // it's 56K
mask = 0x7f;
bits = 7;
- };
+ }
for (i = 0; i < cnt; i++) {
val = bcs->channel ? ((*p >> 8) & 0xff) : (*p & 0xff);
p++;
@@ -623,7 +623,7 @@ void netjet_fill_dma(struct BCState *bcs)
else { // it's 56k
if (make_raw_data_56k(bcs))
return;
- };
+ }
if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs, "tiger fill_dma2: c%d %4lx", bcs->channel,
bcs->Flag);
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index 298c8dba0321..6b8c3fbe3965 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -598,7 +598,7 @@ prcalling(char *dest, u_char *p)
dp += prbits(dp, *++p, 8, 8);
*dp++ = '\n';
l--;
- };
+ }
p++;
dp += sprintf(dp, " number digits ");
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index 8cd2d8277426..b421b86ca7da 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -512,7 +512,7 @@ static inline const char *ST5481_CMD_string(int evt)
case ST5481_CMD_AR10: return "AR10";
case ST5481_CMD_ARL: return "ARL";
case ST5481_CMD_PDN: return "PDN";
- };
+ }
sprintf(s, "0x%x", evt);
return s;
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 6a5b3f00f9ad..74ee00f5b310 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -166,11 +166,9 @@ isdn_wildmat(char *s, char *p)
for (; *p; s++, p++)
switch (*p) {
case '\\':
- /*
- * Literal match with following character,
- * fall through.
- */
+ /* Literal match with following character. */
p++;
+ /* fall through */
default:
if (*s != *p)
return (*s == '\0') ? 2 : 1;
@@ -729,6 +727,7 @@ isdn_status_callback(isdn_ctrl *c)
if (divert_if)
return (divert_if->stat_callback(c));
#endif /* CONFIG_ISDN_DIVERSION */
+ /* fall through */
default:
return -1;
}
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 1b2239c1d569..43700fc19a31 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1437,15 +1437,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
modem_info *info = (modem_info *) tty->driver_data;
+ mutex_lock(&modem_info_mutex);
if (!old_termios)
isdn_tty_change_speed(info);
else {
if (tty->termios.c_cflag == old_termios->c_cflag &&
tty->termios.c_ispeed == old_termios->c_ispeed &&
- tty->termios.c_ospeed == old_termios->c_ospeed)
+ tty->termios.c_ospeed == old_termios->c_ospeed) {
+ mutex_unlock(&modem_info_mutex);
return;
+ }
isdn_tty_change_speed(info);
}
+ mutex_unlock(&modem_info_mutex);
}
/*
@@ -3638,7 +3642,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info *info)
break;
} else
m->mdmcmdl = 0;
- /* Fall through, check for 'A' */
+ /* Fall through - check for 'A' */
case 0:
if (c == 'A') {
m->mdmcmd[m->mdmcmdl] = c;
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
index 2a5f6668756c..d11fe76f138f 100644
--- a/drivers/isdn/i4l/isdn_v110.c
+++ b/drivers/isdn/i4l/isdn_v110.c
@@ -354,7 +354,7 @@ EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen)
printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
return line;
}
- /* else: fall through */
+ /* fall through */
case 128:
m[line] = 128; /* leftmost -> set byte to 1000000 */
mbit = 64; /* current bit in the matrix line */
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index a4597e96c916..f4253d468ae1 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -72,7 +72,7 @@ isdnloop_bchan_send(isdnloop_card *card, int ch)
printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n");
dev_kfree_skb(skb);
- };
+ }
cmd.command = ISDN_STAT_BSENT;
cmd.parm.length = len;
card->interface.statcallb(&cmd);
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 15d3ca37669a..4ab8b1b6608f 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -103,7 +103,7 @@ mISDN_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
static inline void
mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
{
- struct timeval tv;
+ struct __kernel_old_timeval tv;
if (_pms(sk)->cmask & MISDN_TIME_STAMP) {
skb_get_timestamp(skb, &tv);
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index 211ed6cffd10..578978711887 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -170,8 +170,8 @@ dev_expire_timer(struct timer_list *t)
spin_lock_irqsave(&timer->dev->lock, flags);
if (timer->id >= 0)
list_move_tail(&timer->list, &timer->dev->expired);
- spin_unlock_irqrestore(&timer->dev->lock, flags);
wake_up_interruptible(&timer->dev->wait);
+ spin_unlock_irqrestore(&timer->dev->lock, flags);
}
static int
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index ede4fa0ac2cc..e3da7c03da1b 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -16,7 +16,9 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/rwsem.h>
+#include <linux/slab.h>
#include "leds.h"
DECLARE_RWSEM(leds_list_lock);
@@ -310,6 +312,34 @@ int led_update_brightness(struct led_classdev *led_cdev)
}
EXPORT_SYMBOL_GPL(led_update_brightness);
+u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size)
+{
+ struct device_node *np = dev_of_node(led_cdev->dev);
+ u32 *pattern;
+ int count;
+
+ if (!np)
+ return NULL;
+
+ count = of_property_count_u32_elems(np, "led-pattern");
+ if (count < 0)
+ return NULL;
+
+ pattern = kcalloc(count, sizeof(*pattern), GFP_KERNEL);
+ if (!pattern)
+ return NULL;
+
+ if (of_property_read_u32_array(np, "led-pattern", pattern, count)) {
+ kfree(pattern);
+ return NULL;
+ }
+
+ *size = count;
+
+ return pattern;
+}
+EXPORT_SYMBOL_GPL(led_get_default_pattern);
+
/* Caller must ensure led_cdev->led_access held */
void led_sysfs_disable(struct led_classdev *led_cdev)
{
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index a2e74feee2b2..fd64df5a57a5 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
/* Let the programs run for couple of ms and check the engine status */
usleep_range(3000, 6000);
- lp55xx_read(chip, LP5523_REG_STATUS, &status);
+ ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
+ if (ret)
+ return ret;
status &= LP5523_ENG_STATUS_MASK;
if (status != LP5523_ENG_STATUS_MASK) {
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 3d79a6380761..723f2f17497a 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -201,7 +201,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
if (!fw) {
dev_err(dev, "firmware request failed\n");
- goto out;
+ return;
}
/* handling firmware data is chip dependent */
@@ -214,9 +214,9 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
mutex_unlock(&chip->lock);
-out:
/* firmware should be released for other channel use */
release_firmware(chip->fw);
+ chip->fw = NULL;
}
static int lp55xx_request_firmware(struct lp55xx_chip *chip)
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
index 95c9be4b6e7e..8808f0ad7339 100644
--- a/drivers/leds/trigger/ledtrig-oneshot.c
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -130,6 +130,34 @@ static struct attribute *oneshot_trig_attrs[] = {
};
ATTRIBUTE_GROUPS(oneshot_trig);
+static void pattern_init(struct led_classdev *led_cdev)
+{
+ u32 *pattern;
+ unsigned int size = 0;
+
+ pattern = led_get_default_pattern(led_cdev, &size);
+ if (!pattern)
+ goto out_default;
+
+ if (size != 2) {
+ dev_warn(led_cdev->dev,
+ "Expected 2 but got %u values for delays pattern\n",
+ size);
+ goto out_default;
+ }
+
+ led_cdev->blink_delay_on = pattern[0];
+ led_cdev->blink_delay_off = pattern[1];
+ kfree(pattern);
+
+ return;
+
+out_default:
+ kfree(pattern);
+ led_cdev->blink_delay_on = DEFAULT_DELAY;
+ led_cdev->blink_delay_off = DEFAULT_DELAY;
+}
+
static int oneshot_trig_activate(struct led_classdev *led_cdev)
{
struct oneshot_trig_data *oneshot_data;
@@ -140,8 +168,14 @@ static int oneshot_trig_activate(struct led_classdev *led_cdev)
led_set_trigger_data(led_cdev, oneshot_data);
- led_cdev->blink_delay_on = DEFAULT_DELAY;
- led_cdev->blink_delay_off = DEFAULT_DELAY;
+ if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
+ pattern_init(led_cdev);
+ /*
+ * Mark as initialized even on pattern_init() error because
+ * any consecutive call to it would produce the same error.
+ */
+ led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
+ }
return 0;
}
diff --git a/drivers/leds/trigger/ledtrig-pattern.c b/drivers/leds/trigger/ledtrig-pattern.c
index 1870cf87afe1..718729c89440 100644
--- a/drivers/leds/trigger/ledtrig-pattern.c
+++ b/drivers/leds/trigger/ledtrig-pattern.c
@@ -220,22 +220,10 @@ out:
return count;
}
-static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev,
- const char *buf, size_t count,
- bool hw_pattern)
+static int pattern_trig_store_patterns_string(struct pattern_trig_data *data,
+ const char *buf, size_t count)
{
- struct pattern_trig_data *data = led_cdev->trigger_data;
- int ccount, cr, offset = 0, err = 0;
-
- mutex_lock(&data->lock);
-
- del_timer_sync(&data->timer);
-
- if (data->is_hw_pattern)
- led_cdev->pattern_clear(led_cdev);
-
- data->is_hw_pattern = hw_pattern;
- data->npatterns = 0;
+ int ccount, cr, offset = 0;
while (offset < count - 1 && data->npatterns < MAX_PATTERNS) {
cr = 0;
@@ -244,14 +232,54 @@ static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev,
&data->patterns[data->npatterns].delta_t, &cr);
if (ccount != 2) {
data->npatterns = 0;
- err = -EINVAL;
- goto out;
+ return -EINVAL;
}
offset += cr;
data->npatterns++;
}
+ return 0;
+}
+
+static int pattern_trig_store_patterns_int(struct pattern_trig_data *data,
+ const u32 *buf, size_t count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i += 2) {
+ data->patterns[data->npatterns].brightness = buf[i];
+ data->patterns[data->npatterns].delta_t = buf[i + 1];
+ data->npatterns++;
+ }
+
+ return 0;
+}
+
+static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev,
+ const char *buf, const u32 *buf_int,
+ size_t count, bool hw_pattern)
+{
+ struct pattern_trig_data *data = led_cdev->trigger_data;
+ int err = 0;
+
+ mutex_lock(&data->lock);
+
+ del_timer_sync(&data->timer);
+
+ if (data->is_hw_pattern)
+ led_cdev->pattern_clear(led_cdev);
+
+ data->is_hw_pattern = hw_pattern;
+ data->npatterns = 0;
+
+ if (buf)
+ err = pattern_trig_store_patterns_string(data, buf, count);
+ else
+ err = pattern_trig_store_patterns_int(data, buf_int, count);
+ if (err)
+ goto out;
+
err = pattern_trig_start_pattern(led_cdev);
if (err)
data->npatterns = 0;
@@ -275,7 +303,7 @@ static ssize_t pattern_store(struct device *dev, struct device_attribute *attr,
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
- return pattern_trig_store_patterns(led_cdev, buf, count, false);
+ return pattern_trig_store_patterns(led_cdev, buf, NULL, count, false);
}
static DEVICE_ATTR_RW(pattern);
@@ -295,7 +323,7 @@ static ssize_t hw_pattern_store(struct device *dev,
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
- return pattern_trig_store_patterns(led_cdev, buf, count, true);
+ return pattern_trig_store_patterns(led_cdev, buf, NULL, count, true);
}
static DEVICE_ATTR_RW(hw_pattern);
@@ -331,6 +359,30 @@ static const struct attribute_group *pattern_trig_groups[] = {
NULL,
};
+static void pattern_init(struct led_classdev *led_cdev)
+{
+ unsigned int size = 0;
+ u32 *pattern;
+ int err;
+
+ pattern = led_get_default_pattern(led_cdev, &size);
+ if (!pattern)
+ return;
+
+ if (size % 2) {
+ dev_warn(led_cdev->dev, "Expected pattern of tuples\n");
+ goto out;
+ }
+
+ err = pattern_trig_store_patterns(led_cdev, NULL, pattern, size, false);
+ if (err < 0)
+ dev_warn(led_cdev->dev,
+ "Pattern initialization failed with error %d\n", err);
+
+out:
+ kfree(pattern);
+}
+
static int pattern_trig_activate(struct led_classdev *led_cdev)
{
struct pattern_trig_data *data;
@@ -354,6 +406,15 @@ static int pattern_trig_activate(struct led_classdev *led_cdev)
timer_setup(&data->timer, pattern_trig_timer_function, 0);
led_cdev->activated = true;
+ if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
+ pattern_init(led_cdev);
+ /*
+ * Mark as initialized even on pattern_init() error because
+ * any consecutive call to it would produce the same error.
+ */
+ led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
+ }
+
return 0;
}
diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c
index 7c14983781ee..ca898c1383be 100644
--- a/drivers/leds/trigger/ledtrig-timer.c
+++ b/drivers/leds/trigger/ledtrig-timer.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/ctype.h>
+#include <linux/slab.h>
#include <linux/leds.h>
static ssize_t led_delay_on_show(struct device *dev,
@@ -77,8 +78,41 @@ static struct attribute *timer_trig_attrs[] = {
};
ATTRIBUTE_GROUPS(timer_trig);
+static void pattern_init(struct led_classdev *led_cdev)
+{
+ u32 *pattern;
+ unsigned int size = 0;
+
+ pattern = led_get_default_pattern(led_cdev, &size);
+ if (!pattern)
+ return;
+
+ if (size != 2) {
+ dev_warn(led_cdev->dev,
+ "Expected 2 but got %u values for delays pattern\n",
+ size);
+ goto out;
+ }
+
+ led_cdev->blink_delay_on = pattern[0];
+ led_cdev->blink_delay_off = pattern[1];
+ /* led_blink_set() called by caller */
+
+out:
+ kfree(pattern);
+}
+
static int timer_trig_activate(struct led_classdev *led_cdev)
{
+ if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
+ pattern_init(led_cdev);
+ /*
+ * Mark as initialized even on pattern_init() error because
+ * any consecutive call to it would produce the same error.
+ */
+ led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
+ }
+
led_blink_set(led_cdev, &led_cdev->blink_delay_on,
&led_cdev->blink_delay_off);
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index bbec6ac0a966..3581abfb0c6a 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -569,6 +569,7 @@ cuda_interrupt(int irq, void *arg)
unsigned char ibuf[16];
int ibuf_len = 0;
int complete = 0;
+ bool full;
spin_lock_irqsave(&cuda_lock, flags);
@@ -656,12 +657,13 @@ idle_state:
break;
case reading:
- if (reading_reply ? ARRAY_FULL(current_req->reply, reply_ptr)
- : ARRAY_FULL(cuda_rbuf, reply_ptr))
+ full = reading_reply ? ARRAY_FULL(current_req->reply, reply_ptr)
+ : ARRAY_FULL(cuda_rbuf, reply_ptr);
+ if (full)
(void)in_8(&via[SR]);
else
*reply_ptr++ = in_8(&via[SR]);
- if (!TREQ_asserted(status)) {
+ if (!TREQ_asserted(status) || full) {
if (mcu_is_egret)
assert_TACK();
/* that's all folks */
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index d713271ebf7c..a64116586b4c 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1396,9 +1396,9 @@ static void flexrm_shutdown(struct mbox_chan *chan)
/* Clear ring flush state */
timeout = 1000; /* timeout of 1s */
- writel_relaxed(0x0, ring + RING_CONTROL);
+ writel_relaxed(0x0, ring->regs + RING_CONTROL);
do {
- if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
+ if (!(readl_relaxed(ring->regs + RING_FLUSH_DONE) &
FLUSH_DONE_MASK))
break;
mdelay(1);
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index c6a7d4582dc6..38d9df3fb199 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -310,6 +310,7 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
return ret;
}
+EXPORT_SYMBOL_GPL(mbox_flush);
/**
* mbox_request_channel - Request a mailbox channel.
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 0ff22159a0ca..dd538e6b2748 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
if (IS_ERR(bip))
return PTR_ERR(bip);
- tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
+ tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
bip->bip_iter.bi_size = tag_len;
bip->bip_iter.bi_sector = io->cc->start + io->sector;
@@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
* capi:cipher_api_spec-iv:ivopts
*/
tmp = &cipher_in[strlen("capi:")];
- cipher_api = strsep(&tmp, "-");
- *ivmode = strsep(&tmp, ":");
- *ivopts = tmp;
+
+ /* Separate IV options if present, it can contain another '-' in hash name */
+ *ivopts = strrchr(tmp, ':');
+ if (*ivopts) {
+ **ivopts = '\0';
+ (*ivopts)++;
+ }
+ /* Parse IV mode */
+ *ivmode = strrchr(tmp, '-');
+ if (*ivmode) {
+ **ivmode = '\0';
+ (*ivmode)++;
+ }
+ /* The rest is crypto API spec */
+ cipher_api = tmp;
if (*ivmode && !strcmp(*ivmode, "lmk"))
cc->tfms_count = 64;
@@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
goto bad_mem;
chainmode = strsep(&tmp, "-");
- *ivopts = strsep(&tmp, "-");
- *ivmode = strsep(&*ivopts, ":");
-
- if (tmp)
- DMWARN("Ignoring unexpected additional cipher options");
+ *ivmode = strsep(&tmp, ":");
+ *ivopts = tmp;
/*
* For compatibility with the original dm-crypt mapping format, if
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 4eb5f8c56535..a20531e5f3b4 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -131,7 +131,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
static void rq_completed(struct mapped_device *md)
{
/* nudge anyone waiting on suspend queue */
- if (unlikely(waitqueue_active(&md->wait)))
+ if (unlikely(wq_has_sleeper(&md->wait)))
wake_up(&md->wait);
/*
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 20b0776e39ef..ed3caceaed07 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1678,7 +1678,7 @@ int dm_thin_remove_range(struct dm_thin_device *td,
return r;
}
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
{
int r;
uint32_t ref_count;
@@ -1686,7 +1686,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu
down_read(&pmd->root_lock);
r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
if (!r)
- *result = (ref_count != 0);
+ *result = (ref_count > 1);
up_read(&pmd->root_lock);
return r;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 35e954ea20a9..f6be0d733c20 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index dadd9696340c..e83b63608262 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -257,6 +257,7 @@ struct pool {
spinlock_t lock;
struct bio_list deferred_flush_bios;
+ struct bio_list deferred_flush_completions;
struct list_head prepared_mappings;
struct list_head prepared_discards;
struct list_head prepared_discards_pt2;
@@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
mempool_free(m, &m->tc->pool->mapping_pool);
}
+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
+{
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ /*
+ * If the bio has the REQ_FUA flag set we must commit the metadata
+ * before signaling its completion.
+ */
+ if (!bio_triggers_commit(tc, bio)) {
+ bio_endio(bio);
+ return;
+ }
+
+ /*
+ * Complete bio with an error if earlier I/O caused changes to the
+ * metadata that can't be committed, e.g, due to I/O errors on the
+ * metadata device.
+ */
+ if (dm_thin_aborted_changes(tc->td)) {
+ bio_io_error(bio);
+ return;
+ }
+
+ /*
+ * Batch together any bios that trigger commits and then issue a
+ * single commit for them in process_deferred_bios().
+ */
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_add(&pool->deferred_flush_completions, bio);
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
static void process_prepared_mapping(struct dm_thin_new_mapping *m)
{
struct thin_c *tc = m->tc;
@@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
*/
if (bio) {
inc_remap_and_issue_cell(tc, m->cell, m->data_block);
- bio_endio(bio);
+ complete_overwrite_bio(tc, bio);
} else {
inc_all_io_entry(tc->pool, m->cell->holder);
remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -1048,7 +1082,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
* passdown we have to check that these blocks are now unused.
*/
int r = 0;
- bool used = true;
+ bool shared = true;
struct thin_c *tc = m->tc;
struct pool *pool = tc->pool;
dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin;
@@ -1058,11 +1092,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
while (b != end) {
/* find start of unmapped run */
for (; b < end; b++) {
- r = dm_pool_block_is_used(pool->pmd, b, &used);
+ r = dm_pool_block_is_shared(pool->pmd, b, &shared);
if (r)
goto out;
- if (!used)
+ if (!shared)
break;
}
@@ -1071,11 +1105,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
/* find end of run */
for (e = b + 1; e != end; e++) {
- r = dm_pool_block_is_used(pool->pmd, e, &used);
+ r = dm_pool_block_is_shared(pool->pmd, e, &shared);
if (r)
goto out;
- if (used)
+ if (shared)
break;
}
@@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool)
{
unsigned long flags;
struct bio *bio;
- struct bio_list bios;
+ struct bio_list bios, bio_completions;
struct thin_c *tc;
tc = get_first_thin(pool);
@@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool)
}
/*
- * If there are any deferred flush bios, we must commit
- * the metadata before issuing them.
+ * If there are any deferred flush bios, we must commit the metadata
+ * before issuing them or signaling their completion.
*/
bio_list_init(&bios);
+ bio_list_init(&bio_completions);
+
spin_lock_irqsave(&pool->lock, flags);
bio_list_merge(&bios, &pool->deferred_flush_bios);
bio_list_init(&pool->deferred_flush_bios);
+
+ bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
+ bio_list_init(&pool->deferred_flush_completions);
spin_unlock_irqrestore(&pool->lock, flags);
- if (bio_list_empty(&bios) &&
+ if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
!(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
return;
if (commit(pool)) {
+ bio_list_merge(&bios, &bio_completions);
+
while ((bio = bio_list_pop(&bios)))
bio_io_error(bio);
return;
}
pool->last_commit_jiffies = jiffies;
+ while ((bio = bio_list_pop(&bio_completions)))
+ bio_endio(bio);
+
while ((bio = bio_list_pop(&bios)))
generic_make_request(bio);
}
@@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
spin_lock_init(&pool->lock);
bio_list_init(&pool->deferred_flush_bios);
+ bio_list_init(&pool->deferred_flush_completions);
INIT_LIST_HEAD(&pool->prepared_mappings);
INIT_LIST_HEAD(&pool->prepared_discards);
INIT_LIST_HEAD(&pool->prepared_discards_pt2);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d67c95ef8d7e..515e6af9bed2 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -699,7 +699,7 @@ static void end_io_acct(struct dm_io *io)
true, duration, &io->stats_aux);
/* nudge anyone waiting on suspend queue */
- if (unlikely(waitqueue_active(&md->wait)))
+ if (unlikely(wq_has_sleeper(&md->wait)))
wake_up(&md->wait);
}
@@ -1320,7 +1320,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
__bio_clone_fast(clone, bio);
- if (unlikely(bio_integrity(bio) != NULL)) {
+ if (bio_integrity(bio)) {
int r;
if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
@@ -1339,7 +1339,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
clone->bi_iter.bi_size = to_bytes(len);
- if (unlikely(bio_integrity(bio) != NULL))
+ if (bio_integrity(bio))
bio_integrity_trim(clone);
return 0;
@@ -1588,6 +1588,9 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
ci->sector = bio->bi_iter.bi_sector;
}
+#define __dm_part_stat_sub(part, field, subnd) \
+ (part_stat_get(part, field) -= (subnd))
+
/*
* Entry point to split a bio into clones and submit them to the targets.
*/
@@ -1642,7 +1645,21 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count,
GFP_NOIO, &md->queue->bio_split);
ci.io->orig_bio = b;
+
+ /*
+ * Adjust IO stats for each split, otherwise upon queue
+ * reentry there will be redundant IO accounting.
+ * NOTE: this is a stop-gap fix, a proper fix involves
+ * significant refactoring of DM core's bio splitting
+ * (by eliminating DM's splitting and just using bio_split)
+ */
+ part_stat_lock();
+ __dm_part_stat_sub(&dm_disk(md)->part0,
+ sectors[op_stat_group(bio_op(bio))], ci.sector_count);
+ part_stat_unlock();
+
bio_chain(b, bio);
+ trace_block_split(md->queue, b, bio->bi_iter.bi_sector);
ret = generic_make_request(bio);
break;
}
@@ -1713,6 +1730,15 @@ out:
return ret;
}
+static blk_qc_t dm_process_bio(struct mapped_device *md,
+ struct dm_table *map, struct bio *bio)
+{
+ if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
+ return __process_bio(md, map, bio);
+ else
+ return __split_and_process_bio(md, map, bio);
+}
+
static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
{
struct mapped_device *md = q->queuedata;
@@ -1733,10 +1759,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
return ret;
}
- if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
- ret = __process_bio(md, map, bio);
- else
- ret = __split_and_process_bio(md, map, bio);
+ ret = dm_process_bio(md, map, bio);
dm_put_live_table(md, srcu_idx);
return ret;
@@ -2415,9 +2438,9 @@ static void dm_wq_work(struct work_struct *work)
break;
if (dm_request_based(md))
- generic_make_request(c);
+ (void) generic_make_request(c);
else
- __split_and_process_bio(md, map, c);
+ (void) dm_process_bio(md, map, c);
}
dm_put_live_table(md, srcu_idx);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index fd4af4de03b4..05ffffb8b769 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -207,15 +207,10 @@ static bool create_on_open = true;
struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
struct mddev *mddev)
{
- struct bio *b;
-
if (!mddev || !bioset_initialized(&mddev->bio_set))
return bio_alloc(gfp_mask, nr_iovecs);
- b = bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
- if (!b)
- return NULL;
- return b;
+ return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
}
EXPORT_SYMBOL_GPL(bio_alloc_mddev);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1d54109071cc..fa47249fa3e4 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1863,6 +1863,20 @@ static void end_sync_read(struct bio *bio)
reschedule_retry(r1_bio);
}
+static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
+{
+ sector_t sync_blocks = 0;
+ sector_t s = r1_bio->sector;
+ long sectors_to_go = r1_bio->sectors;
+
+ /* make sure these bits don't get cleared. */
+ do {
+ md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
+ s += sync_blocks;
+ sectors_to_go -= sync_blocks;
+ } while (sectors_to_go > 0);
+}
+
static void end_sync_write(struct bio *bio)
{
int uptodate = !bio->bi_status;
@@ -1874,15 +1888,7 @@ static void end_sync_write(struct bio *bio)
struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
if (!uptodate) {
- sector_t sync_blocks = 0;
- sector_t s = r1_bio->sector;
- long sectors_to_go = r1_bio->sectors;
- /* make sure these bits doesn't get cleared. */
- do {
- md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
- s += sync_blocks;
- sectors_to_go -= sync_blocks;
- } while (sectors_to_go > 0);
+ abort_sync_write(mddev, r1_bio);
set_bit(WriteErrorSeen, &rdev->flags);
if (!test_and_set_bit(WantReplacement, &rdev->flags))
set_bit(MD_RECOVERY_NEEDED, &
@@ -2172,8 +2178,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
(i == r1_bio->read_disk ||
!test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
continue;
- if (test_bit(Faulty, &conf->mirrors[i].rdev->flags))
+ if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+ abort_sync_write(mddev, r1_bio);
continue;
+ }
bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index ec3a5ef7fee0..cbbe6b6535be 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -1935,12 +1935,14 @@ out:
}
static struct stripe_head *
-r5c_recovery_alloc_stripe(struct r5conf *conf,
- sector_t stripe_sect)
+r5c_recovery_alloc_stripe(
+ struct r5conf *conf,
+ sector_t stripe_sect,
+ int noblock)
{
struct stripe_head *sh;
- sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+ sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
if (!sh)
return NULL; /* no more stripe available */
@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
stripe_sect);
if (!sh) {
- sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+ sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
/*
* cannot get stripe from raid5_get_active_stripe
* try replay some stripes
@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
r5c_recovery_replay_stripes(
cached_stripe_list, ctx);
sh = r5c_recovery_alloc_stripe(
- conf, stripe_sect);
+ conf, stripe_sect, 1);
}
if (!sh) {
+ int new_size = conf->min_nr_stripes * 2;
pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
mdname(mddev),
- conf->min_nr_stripes * 2);
- raid5_set_cache_size(mddev,
- conf->min_nr_stripes * 2);
- sh = r5c_recovery_alloc_stripe(conf,
- stripe_sect);
+ new_size);
+ ret = raid5_set_cache_size(mddev, new_size);
+ if (conf->min_nr_stripes <= new_size / 2) {
+ pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
+ mdname(mddev),
+ ret,
+ new_size,
+ conf->min_nr_stripes,
+ conf->max_nr_stripes);
+ return -ENOMEM;
+ }
+ sh = r5c_recovery_alloc_stripe(
+ conf, stripe_sect, 0);
}
if (!sh) {
pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
- mdname(mddev));
+ mdname(mddev));
return -ENOMEM;
}
list_add_tail(&sh->lru, cached_stripe_list);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4990f0319f6c..cecea901ab8c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
int
raid5_set_cache_size(struct mddev *mddev, int size)
{
+ int result = 0;
struct r5conf *conf = mddev->private;
if (size <= 16 || size > 32768)
@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
mutex_lock(&conf->cache_size_mutex);
while (size > conf->max_nr_stripes)
- if (!grow_one_stripe(conf, GFP_KERNEL))
+ if (!grow_one_stripe(conf, GFP_KERNEL)) {
+ conf->min_nr_stripes = conf->max_nr_stripes;
+ result = -ENOMEM;
break;
+ }
mutex_unlock(&conf->cache_size_mutex);
- return 0;
+ return result;
}
EXPORT_SYMBOL(raid5_set_cache_size);
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 447baaebca44..cdb79ae2d8dc 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -218,8 +218,8 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q)
{
struct device *dev = &cio2->pci_dev->dev;
- q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
- GFP_KERNEL);
+ q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
+ GFP_KERNEL);
if (!q->fbpt)
return -ENOMEM;
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 2cc05a9d57ac..a16242a9206f 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -360,13 +360,11 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev)
ss; ss = ss->next, i++)
sprintf(ss->name, "Camera #%d Audio", i);
- ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
G723_PERIOD_BYTES * PERIODS,
G723_PERIOD_BYTES * PERIODS);
- if (ret < 0)
- return ret;
solo_dev->snd_pcm = pcm;
diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c
index a28329698e20..fb0e7573b5ae 100644
--- a/drivers/media/pci/tw686x/tw686x-audio.c
+++ b/drivers/media/pci/tw686x/tw686x-audio.c
@@ -301,11 +301,12 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
ss; ss = ss->next, i++)
snprintf(ss->name, sizeof(ss->name), "vch%u audio", i);
- return snd_pcm_lib_preallocate_pages_for_all(pcm,
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(dev->pci_dev),
TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX);
+ return 0;
}
static void tw686x_audio_dma_free(struct tw686x_dev *dev,
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
index e80123cba406..060c0ad6243a 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -49,7 +49,7 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
struct device *dev = &ctx->dev->plat_dev->dev;
- mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
+ mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
if (!mem->va) {
mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
size);
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index d01821a6906a..89d9c4c21037 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -807,7 +807,9 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
struct vb2_v4l2_buffer *vbuf;
unsigned long flags;
- cancel_delayed_work_sync(&dev->work_run);
+ if (v4l2_m2m_get_curr_priv(dev->m2m_dev) == ctx)
+ cancel_delayed_work_sync(&dev->work_run);
+
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 1441a73ce64c..90aad465f9ed 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -287,6 +287,7 @@ static void v4l_print_format(const void *arg, bool write_only)
const struct v4l2_window *win;
const struct v4l2_sdr_format *sdr;
const struct v4l2_meta_format *meta;
+ u32 planes;
unsigned i;
pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -317,7 +318,8 @@ static void v4l_print_format(const void *arg, bool write_only)
prt_names(mp->field, v4l2_field_names),
mp->colorspace, mp->num_planes, mp->flags,
mp->ycbcr_enc, mp->quantization, mp->xfer_func);
- for (i = 0; i < mp->num_planes; i++)
+ planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES);
+ for (i = 0; i < planes; i++)
printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
mp->plane_fmt[i].bytesperline,
mp->plane_fmt[i].sizeimage);
@@ -1551,8 +1553,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane))
break;
CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+ if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+ break;
for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
- CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+ CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+ bytesperline);
return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
@@ -1581,8 +1586,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane))
break;
CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+ if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+ break;
for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
- CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+ CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+ bytesperline);
return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
@@ -1648,8 +1656,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane))
break;
CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+ if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+ break;
for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
- CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+ CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+ bytesperline);
return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
@@ -1678,8 +1689,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane))
break;
CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+ if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+ break;
for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
- CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+ CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+ bytesperline);
return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8c5dfdce4326..76f9909cf396 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -102,6 +102,7 @@ config MFD_AAT2870_CORE
config MFD_AT91_USART
tristate "AT91 USART Driver"
select MFD_CORE
+ depends on ARCH_AT91 || COMPILE_TEST
help
Select this to get support for AT91 USART IP. This is a wrapper
over at91-usart-serial driver and usart-spi-driver. Only one function
@@ -1418,7 +1419,7 @@ config MFD_TPS65217
config MFD_TPS68470
bool "TI TPS68470 Power Management / LED chips"
- depends on ACPI && I2C=y
+ depends on ACPI && PCI && I2C=y
select MFD_CORE
select REGMAP_I2C
select I2C_DESIGNWARE_PLATFORM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 12980a4ad460..ee6fb6af655e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
+obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 30d09d177171..11ab17f64c64 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
mutex_unlock(&ab8500->lock);
dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
- return ret;
+ return (ret < 0) ? ret : 0;
}
static int ab8500_get_register(struct device *dev, u8 bank,
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index e1450a56fc07..3c97f2c0fdfe 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -641,9 +641,9 @@ static const struct mfd_cell axp221_cells[] = {
static const struct mfd_cell axp223_cells[] = {
{
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp22x_pek_resources),
- .resources = axp22x_pek_resources,
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp22x_pek_resources),
+ .resources = axp22x_pek_resources,
}, {
.name = "axp22x-adc",
.of_compatible = "x-powers,axp221-adc",
@@ -651,7 +651,7 @@ static const struct mfd_cell axp223_cells[] = {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp221-battery-power-supply",
}, {
- .name = "axp20x-regulator",
+ .name = "axp20x-regulator",
}, {
.name = "axp20x-ac-power-supply",
.of_compatible = "x-powers,axp221-ac-power-supply",
@@ -667,9 +667,9 @@ static const struct mfd_cell axp223_cells[] = {
static const struct mfd_cell axp152_cells[] = {
{
- .name = "axp20x-pek",
- .num_resources = ARRAY_SIZE(axp152_pek_resources),
- .resources = axp152_pek_resources,
+ .name = "axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp152_pek_resources),
+ .resources = axp152_pek_resources,
},
};
@@ -698,87 +698,101 @@ static const struct resource axp288_charger_resources[] = {
static const struct mfd_cell axp288_cells[] = {
{
- .name = "axp288_adc",
- .num_resources = ARRAY_SIZE(axp288_adc_resources),
- .resources = axp288_adc_resources,
- },
- {
- .name = "axp288_extcon",
- .num_resources = ARRAY_SIZE(axp288_extcon_resources),
- .resources = axp288_extcon_resources,
- },
- {
- .name = "axp288_charger",
- .num_resources = ARRAY_SIZE(axp288_charger_resources),
- .resources = axp288_charger_resources,
- },
- {
- .name = "axp288_fuel_gauge",
- .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
- .resources = axp288_fuel_gauge_resources,
- },
- {
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp288_power_button_resources),
- .resources = axp288_power_button_resources,
- },
- {
- .name = "axp288_pmic_acpi",
+ .name = "axp288_adc",
+ .num_resources = ARRAY_SIZE(axp288_adc_resources),
+ .resources = axp288_adc_resources,
+ }, {
+ .name = "axp288_extcon",
+ .num_resources = ARRAY_SIZE(axp288_extcon_resources),
+ .resources = axp288_extcon_resources,
+ }, {
+ .name = "axp288_charger",
+ .num_resources = ARRAY_SIZE(axp288_charger_resources),
+ .resources = axp288_charger_resources,
+ }, {
+ .name = "axp288_fuel_gauge",
+ .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
+ .resources = axp288_fuel_gauge_resources,
+ }, {
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp288_power_button_resources),
+ .resources = axp288_power_button_resources,
+ }, {
+ .name = "axp288_pmic_acpi",
},
};
static const struct mfd_cell axp803_cells[] = {
{
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp803_pek_resources),
- .resources = axp803_pek_resources,
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp803_pek_resources),
+ .resources = axp803_pek_resources,
+ }, {
+ .name = "axp20x-gpio",
+ .of_compatible = "x-powers,axp813-gpio",
+ }, {
+ .name = "axp813-adc",
+ .of_compatible = "x-powers,axp813-adc",
+ }, {
+ .name = "axp20x-battery-power-supply",
+ .of_compatible = "x-powers,axp813-battery-power-supply",
+ }, {
+ .name = "axp20x-ac-power-supply",
+ .of_compatible = "x-powers,axp813-ac-power-supply",
+ .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+ .resources = axp20x_ac_power_supply_resources,
},
- { .name = "axp20x-regulator" },
+ { .name = "axp20x-regulator" },
};
static const struct mfd_cell axp806_self_working_cells[] = {
{
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp806_pek_resources),
- .resources = axp806_pek_resources,
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp806_pek_resources),
+ .resources = axp806_pek_resources,
},
- { .name = "axp20x-regulator" },
+ { .name = "axp20x-regulator" },
};
static const struct mfd_cell axp806_cells[] = {
{
- .id = 2,
- .name = "axp20x-regulator",
+ .id = 2,
+ .name = "axp20x-regulator",
},
};
static const struct mfd_cell axp809_cells[] = {
{
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp809_pek_resources),
- .resources = axp809_pek_resources,
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp809_pek_resources),
+ .resources = axp809_pek_resources,
}, {
- .id = 1,
- .name = "axp20x-regulator",
+ .id = 1,
+ .name = "axp20x-regulator",
},
};
static const struct mfd_cell axp813_cells[] = {
{
- .name = "axp221-pek",
- .num_resources = ARRAY_SIZE(axp803_pek_resources),
- .resources = axp803_pek_resources,
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp803_pek_resources),
+ .resources = axp803_pek_resources,
}, {
- .name = "axp20x-regulator",
+ .name = "axp20x-regulator",
}, {
- .name = "axp20x-gpio",
- .of_compatible = "x-powers,axp813-gpio",
+ .name = "axp20x-gpio",
+ .of_compatible = "x-powers,axp813-gpio",
}, {
- .name = "axp813-adc",
- .of_compatible = "x-powers,axp813-adc",
+ .name = "axp813-adc",
+ .of_compatible = "x-powers,axp813-adc",
}, {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp813-battery-power-supply",
+ }, {
+ .name = "axp20x-ac-power-supply",
+ .of_compatible = "x-powers,axp813-ac-power-supply",
+ .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+ .resources = axp20x_ac_power_supply_resources,
},
};
diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c
new file mode 100644
index 000000000000..42fe67f1538e
--- /dev/null
+++ b/drivers/mfd/bcm2835-pm.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PM MFD driver for Broadcom BCM2835
+ *
+ * This driver binds to the PM block and creates the MFD device for
+ * the WDT and power drivers.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/bcm2835-pm.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+static const struct mfd_cell bcm2835_pm_devs[] = {
+ { .name = "bcm2835-wdt" },
+};
+
+static const struct mfd_cell bcm2835_power_devs[] = {
+ { .name = "bcm2835-power" },
+};
+
+static int bcm2835_pm_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct bcm2835_pm *pm;
+ int ret;
+
+ pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
+ if (!pm)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, pm);
+
+ pm->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pm->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pm->base))
+ return PTR_ERR(pm->base);
+
+ ret = devm_mfd_add_devices(dev, -1,
+ bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
+ NULL, 0, NULL);
+ if (ret)
+ return ret;
+
+ /* We'll use the presence of the AXI ASB regs in the
+ * bcm2835-pm binding as the key for whether we can reference
+ * the full PM register range and support power domains.
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ pm->asb = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pm->asb))
+ return PTR_ERR(pm->asb);
+
+ ret = devm_mfd_add_devices(dev, -1,
+ bcm2835_power_devs,
+ ARRAY_SIZE(bcm2835_power_devs),
+ NULL, 0, NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id bcm2835_pm_of_match[] = {
+ { .compatible = "brcm,bcm2835-pm-wdt", },
+ { .compatible = "brcm,bcm2835-pm", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
+
+static struct platform_driver bcm2835_pm_driver = {
+ .probe = bcm2835_pm_probe,
+ .driver = {
+ .name = "bcm2835-pm",
+ .of_match_table = bcm2835_pm_of_match,
+ },
+};
+module_platform_driver(bcm2835_pm_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c
index 503979c81dae..fab3cdc27ed6 100644
--- a/drivers/mfd/bd9571mwv.c
+++ b/drivers/mfd/bd9571mwv.c
@@ -59,6 +59,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = {
};
static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
+ regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index b99a194ce5a4..2d0fee488c5a 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -499,6 +499,7 @@ static int ec_device_remove(struct platform_device *pdev)
cros_ec_debugfs_remove(ec);
+ mfd_remove_devices(ec->dev);
cdev_del(&ec->cdev);
device_unregister(&ec->class_dev);
return 0;
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 5970b8def548..aec20e1c7d3d 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = {
.irq_unmask = prcmu_irq_unmask,
};
-static __init char *fw_project_name(u32 project)
+static char *fw_project_name(u32 project)
{
switch (project) {
case PRCMU_FW_PROJECT_U8500:
@@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
}
-static void __init init_prcm_registers(void)
+static void init_prcm_registers(void)
{
u32 val;
diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c
index ca829f85672f..2713de989f05 100644
--- a/drivers/mfd/exynos-lpass.c
+++ b/drivers/mfd/exynos-lpass.c
@@ -82,11 +82,13 @@ static void exynos_lpass_enable(struct exynos_lpass *lpass)
LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK,
- LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
+ LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S |
+ LPASS_INTR_UART);
exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET);
exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET);
exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET);
+ exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET);
}
static void exynos_lpass_disable(struct exynos_lpass *lpass)
diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c
index 440030cecbbd..2a77988d0462 100644
--- a/drivers/mfd/madera-core.c
+++ b/drivers/mfd/madera-core.c
@@ -15,6 +15,7 @@
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -155,7 +156,7 @@ static int madera_wait_for_boot(struct madera *madera)
usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
MADERA_BOOT_POLL_INTERVAL_USEC);
regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
- };
+ }
if (!(val & MADERA_BOOT_DONE_STS1)) {
dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
@@ -357,6 +358,8 @@ int madera_dev_init(struct madera *madera)
dev_set_drvdata(madera->dev, madera);
BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+ mutex_init(&madera->dapm_ptr_lock);
+
madera_set_micbias_info(madera);
/*
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index d8217366ed36..d8ddd1a6f304 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -280,7 +280,7 @@ static int max77620_config_fps(struct max77620_chip *chip,
for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
sprintf(fps_name, "fps%d", fps_id);
- if (!strcmp(fps_np->name, fps_name))
+ if (of_node_name_eq(fps_np, fps_name))
break;
}
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index f475e848252f..d0bf50e3568d 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
- mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+ ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+ if (ret)
+ goto out;
adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
MC13XXX_ADC0_CHRGRAWDIV;
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 77b64bd64df3..ab24e176ef44 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -329,8 +329,7 @@ static int mt6397_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "unsupported chip: %d\n", id);
- ret = -ENODEV;
- break;
+ return -ENODEV;
}
if (ret) {
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 52fafea06067..8d420c37b2a6 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev)
return -EFAULT;
}
+ writel(fw_version[0], RPM_CTRL_REG(rpm, 0));
+ writel(fw_version[1], RPM_CTRL_REG(rpm, 1));
+ writel(fw_version[2], RPM_CTRL_REG(rpm, 2));
+
dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
fw_version[1],
fw_version[2]);
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 2a8369657e38..26c7b63e008a 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -109,7 +109,7 @@ struct rave_sp_reply {
/**
* struct rave_sp_checksum - Variant specific checksum implementation details
*
- * @length: Caculated checksum length
+ * @length: Calculated checksum length
* @subroutine: Utilized checksum algorithm implementation
*/
struct rave_sp_checksum {
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 566caca4efd8..7569a4be0608 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1302,17 +1302,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
for_each_child_of_node(np, child) {
- if (!strcmp(child->name, "stmpe_gpio")) {
+ if (of_node_name_eq(child, "stmpe_gpio")) {
pdata->blocks |= STMPE_BLOCK_GPIO;
- } else if (!strcmp(child->name, "stmpe_keypad")) {
+ } else if (of_node_name_eq(child, "stmpe_keypad")) {
pdata->blocks |= STMPE_BLOCK_KEYPAD;
- } else if (!strcmp(child->name, "stmpe_touchscreen")) {
+ } else if (of_node_name_eq(child, "stmpe_touchscreen")) {
pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
- } else if (!strcmp(child->name, "stmpe_adc")) {
+ } else if (of_node_name_eq(child, "stmpe_adc")) {
pdata->blocks |= STMPE_BLOCK_ADC;
- } else if (!strcmp(child->name, "stmpe_pwm")) {
+ } else if (of_node_name_eq(child, "stmpe_pwm")) {
pdata->blocks |= STMPE_BLOCK_PWM;
- } else if (!strcmp(child->name, "stmpe_rotator")) {
+ } else if (of_node_name_eq(child, "stmpe_rotator")) {
pdata->blocks |= STMPE_BLOCK_ROTATOR;
}
}
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index c2d47d78705b..fd111296b959 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -264,8 +264,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
cell->pdata_size = sizeof(tscadc);
}
- err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
- tscadc->used_cells, NULL, 0, NULL);
+ err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+ tscadc->cells, tscadc->used_cells, NULL,
+ 0, NULL);
if (err < 0)
goto err_disable_clk;
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index 910f569ff77c..8bcdecf494d0 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -235,9 +235,9 @@ static int tps65218_probe(struct i2c_client *client,
mutex_init(&tps->tps_lock);
- ret = regmap_add_irq_chip(tps->regmap, tps->irq,
- IRQF_ONESHOT, 0, &tps65218_irq_chip,
- &tps->irq_data);
+ ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
+ IRQF_ONESHOT, 0, &tps65218_irq_chip,
+ &tps->irq_data);
if (ret < 0)
return ret;
@@ -253,26 +253,9 @@ static int tps65218_probe(struct i2c_client *client,
ARRAY_SIZE(tps65218_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data));
- if (ret < 0)
- goto err_irq;
-
- return 0;
-
-err_irq:
- regmap_del_irq_chip(tps->irq, tps->irq_data);
-
return ret;
}
-static int tps65218_remove(struct i2c_client *client)
-{
- struct tps65218 *tps = i2c_get_clientdata(client);
-
- regmap_del_irq_chip(tps->irq, tps->irq_data);
-
- return 0;
-}
-
static const struct i2c_device_id tps65218_id_table[] = {
{ "tps65218", TPS65218 },
{ },
@@ -285,7 +268,6 @@ static struct i2c_driver tps65218_driver = {
.of_match_table = of_tps65218_match_table,
},
.probe = tps65218_probe,
- .remove = tps65218_remove,
.id_table = tps65218_id_table,
};
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index b89379782741..9c7925ca13cf 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -592,6 +592,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
return 0;
}
+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
+{
+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+ if (tps6586x->client->irq)
+ disable_irq(tps6586x->client->irq);
+
+ return 0;
+}
+
+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
+{
+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+ if (tps6586x->client->irq)
+ enable_irq(tps6586x->client->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
+ tps6586x_i2c_resume);
+
static const struct i2c_device_id tps6586x_id_table[] = {
{ "tps6586x", 0 },
{ },
@@ -602,6 +625,7 @@ static struct i2c_driver tps6586x_driver = {
.driver = {
.name = "tps6586x",
.of_match_table = of_match_ptr(tps6586x_of_match),
+ .pm = &tps6586x_pm_ops,
},
.probe = tps6586x_i2c_probe,
.remove = tps6586x_i2c_remove,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 4be3d239da9e..299016bc46d9 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
* letting it generate the right frequencies for USB, MADC, and
* other purposes.
*/
-static inline int __init protect_pm_master(void)
+static inline int protect_pm_master(void)
{
int e = 0;
@@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void)
return e;
}
-static inline int __init unprotect_pm_master(void)
+static inline int unprotect_pm_master(void)
{
int e = 0;
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 1ee68bd440fb..16c6e2accfaa 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */
{ 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */
{ 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */
+ { 0x00000EE3, 0x4000 }, /* R3811 - ASRC_RATE2 */
{ 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */
{ 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */
{ 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */
@@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_ASRC_ENABLE:
case ARIZONA_ASRC_STATUS:
case ARIZONA_ASRC_RATE1:
+ case ARIZONA_ASRC_RATE2:
case ARIZONA_ISRC_1_CTRL_1:
case ARIZONA_ISRC_1_CTRL_2:
case ARIZONA_ISRC_1_CTRL_3:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f417b06e11c5..42ab8ec92a04 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -295,6 +295,17 @@ config QCOM_COINCELL
to maintain PMIC register and RTC state in the absence of
external power.
+config QCOM_FASTRPC
+ tristate "Qualcomm FastRPC"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on RPMSG
+ select DMA_SHARED_BUFFER
+ help
+ Provides a communication mechanism that allows for clients to
+ make remote method invocations across processor boundary to
+ applications DSP processor. Say M if you want to enable this
+ module.
+
config SGI_GRU
tristate "SGI GRU driver"
depends on X86_UV && SMP
@@ -535,4 +546,5 @@ source "drivers/misc/echo/Kconfig"
source "drivers/misc/cxl/Kconfig"
source "drivers/misc/ocxl/Kconfig"
source "drivers/misc/cardreader/Kconfig"
+source "drivers/misc/habanalabs/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e39ccbbc1b3a..d5b7d3404dc7 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
+obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
@@ -59,3 +60,4 @@ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
obj-$(CONFIG_OCXL) += ocxl/
obj-y += cardreader/
obj-$(CONFIG_PVPANIC) += pvpanic.o
+obj-$(CONFIG_HABANA_AI) += habanalabs/
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index a0afadefcc49..1f6d008e0036 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -202,22 +202,20 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
return dpot_read_r8d8(dpot, ctrl);
case DPOT_UID(AD5272_ID):
case DPOT_UID(AD5274_ID):
- dpot_write_r8d8(dpot,
+ dpot_write_r8d8(dpot,
(DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
- value = dpot_read_r8d16(dpot,
- DPOT_AD5270_1_2_4_RDAC << 2);
-
- if (value < 0)
- return value;
- /*
- * AD5272/AD5274 returns high byte first, however
- * underling smbus expects low byte first.
- */
- value = swab16(value);
+ value = dpot_read_r8d16(dpot, DPOT_AD5270_1_2_4_RDAC << 2);
+ if (value < 0)
+ return value;
+ /*
+ * AD5272/AD5274 returns high byte first, however
+ * underling smbus expects low byte first.
+ */
+ value = swab16(value);
- if (dpot->uid == DPOT_UID(AD5274_ID))
- value = value >> 2;
+ if (dpot->uid == DPOT_UID(AD5274_ID))
+ value = value >> 2;
return value;
default:
if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
diff --git a/drivers/misc/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c
index 024dcba8d6c8..5c98e2221889 100644
--- a/drivers/misc/cardreader/rts5227.c
+++ b/drivers/misc/cardreader/rts5227.c
@@ -170,35 +170,46 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
{
int err;
+ if (pcr->option.ocp_en)
+ rtsx_pci_enable_ocp(pcr);
+
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
SD_POWER_MASK, SD_PARTIAL_POWER_ON);
+
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x02);
+
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
/* To avoid too large in-rush current */
- udelay(150);
-
+ msleep(20);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
SD_POWER_MASK, SD_POWER_ON);
+
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE,
+ SD_OUTPUT_EN, SD_OUTPUT_EN);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE,
+ MS_OUTPUT_EN, MS_OUTPUT_EN);
return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
{
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK | PMOS_STRG_MASK,
- SD_POWER_OFF | PMOS_STRG_400mA);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0X00);
- return rtsx_pci_send_cmd(pcr, 100);
+ if (pcr->option.ocp_en)
+ rtsx_pci_disable_ocp(pcr);
+
+ rtsx_pci_write_register(pcr, CARD_PWR_CTL, SD_POWER_MASK |
+ PMOS_STRG_MASK, SD_POWER_OFF | PMOS_STRG_400mA);
+ rtsx_pci_write_register(pcr, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0X00);
+
+ return 0;
}
static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
@@ -348,6 +359,32 @@ static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
return 0;
}
+static int rts522a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+ int err;
+
+ if (voltage == OUTPUT_3V3) {
+ err = rtsx_pci_write_phy_register(pcr, 0x08, 0x57E4);
+ if (err < 0)
+ return err;
+ } else if (voltage == OUTPUT_1V8) {
+ err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, 0x08, 0x54A4);
+ if (err < 0)
+ return err;
+ } else {
+ return -EINVAL;
+ }
+
+ /* set pad drive */
+ rtsx_pci_init_cmd(pcr);
+ rts5227_fill_driving(pcr, voltage);
+ return rtsx_pci_send_cmd(pcr, 100);
+}
+
+
/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
*/
static const struct pcr_ops rts522a_pcr_ops = {
@@ -360,7 +397,7 @@ static const struct pcr_ops rts522a_pcr_ops = {
.disable_auto_blink = rts5227_disable_auto_blink,
.card_power_on = rts5227_card_power_on,
.card_power_off = rts5227_card_power_off,
- .switch_output_voltage = rts5227_switch_output_voltage,
+ .switch_output_voltage = rts522a_switch_output_voltage,
.cd_deglitch = NULL,
.conv_clk_and_div_n = NULL,
.force_power_down = rts5227_force_power_down,
@@ -371,4 +408,11 @@ void rts522a_init_params(struct rtsx_pcr *pcr)
rts5227_init_params(pcr);
pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
+
+ pcr->option.ocp_en = 1;
+ if (pcr->option.ocp_en)
+ pcr->hw_param.interrupt_en |= SD_OC_INT_EN;
+ pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M;
+ pcr->option.sd_800mA_ocp_thd = RTS522A_OCP_THD_800;
+
}
diff --git a/drivers/misc/cardreader/rts5249.c b/drivers/misc/cardreader/rts5249.c
index dbe013abdb83..0f72a7e0fdab 100644
--- a/drivers/misc/cardreader/rts5249.c
+++ b/drivers/misc/cardreader/rts5249.c
@@ -284,6 +284,10 @@ static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr)
static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
{
int err;
+ struct rtsx_cr_option *option = &pcr->option;
+
+ if (option->ocp_en)
+ rtsx_pci_enable_ocp(pcr);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
@@ -306,12 +310,15 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
{
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_POWER_OFF);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x00);
- return rtsx_pci_send_cmd(pcr, 100);
+ struct rtsx_cr_option *option = &pcr->option;
+
+ if (option->ocp_en)
+ rtsx_pci_disable_ocp(pcr);
+
+ rtsx_pci_write_register(pcr, CARD_PWR_CTL, SD_POWER_MASK, SD_POWER_OFF);
+
+ rtsx_pci_write_register(pcr, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x00);
+ return 0;
}
static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
@@ -629,6 +636,13 @@ void rts524a_init_params(struct rtsx_pcr *pcr)
pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
pcr->ops = &rts524a_pcr_ops;
+
+ pcr->option.ocp_en = 1;
+ if (pcr->option.ocp_en)
+ pcr->hw_param.interrupt_en |= SD_OC_INT_EN;
+ pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M;
+ pcr->option.sd_800mA_ocp_thd = RTS524A_OCP_THD_800;
+
}
static int rts525a_card_power_on(struct rtsx_pcr *pcr, int card)
@@ -737,4 +751,10 @@ void rts525a_init_params(struct rtsx_pcr *pcr)
pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
pcr->ops = &rts525a_pcr_ops;
+
+ pcr->option.ocp_en = 1;
+ if (pcr->option.ocp_en)
+ pcr->hw_param.interrupt_en |= SD_OC_INT_EN;
+ pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M;
+ pcr->option.sd_800mA_ocp_thd = RTS525A_OCP_THD_800;
}
diff --git a/drivers/misc/cardreader/rts5260.c b/drivers/misc/cardreader/rts5260.c
index a493b01c5bc6..da22bcb62b04 100644
--- a/drivers/misc/cardreader/rts5260.c
+++ b/drivers/misc/cardreader/rts5260.c
@@ -64,11 +64,13 @@ static void rts5260_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
drive_sel = pcr->sd30_drive_sel_1v8;
}
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
+ rtsx_pci_write_register(pcr, SD30_CLK_DRIVE_SEL,
0xFF, driving[drive_sel][0]);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
+
+ rtsx_pci_write_register(pcr, SD30_CMD_DRIVE_SEL,
0xFF, driving[drive_sel][1]);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
+
+ rtsx_pci_write_register(pcr, SD30_CMD_DRIVE_SEL,
0xFF, driving[drive_sel][2]);
}
@@ -193,7 +195,7 @@ static int sd_set_sample_push_timing_sd30(struct rtsx_pcr *pcr)
| SD_ASYNC_FIFO_NOT_RST, SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
rtsx_pci_write_register(pcr, CARD_CLK_SOURCE, 0xFF,
- CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
return 0;
@@ -207,22 +209,16 @@ static int rts5260_card_power_on(struct rtsx_pcr *pcr, int card)
if (option->ocp_en)
rtsx_pci_enable_ocp(pcr);
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CONFIG2,
- DV331812_VDD1, DV331812_VDD1);
- err = rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
- if (err < 0)
- return err;
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_VCC_CFG0,
+ rtsx_pci_write_register(pcr, LDO_CONFIG2, DV331812_VDD1, DV331812_VDD1);
+ rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
RTS5260_DVCC_TUNE_MASK, RTS5260_DVCC_33);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_VCC_CFG1,
- LDO_POW_SDVDD1_MASK, LDO_POW_SDVDD1_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CONFIG2,
- DV331812_POWERON, DV331812_POWERON);
- err = rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
+ rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_POW_SDVDD1_MASK,
+ LDO_POW_SDVDD1_ON);
+
+ rtsx_pci_write_register(pcr, LDO_CONFIG2,
+ DV331812_POWERON, DV331812_POWERON);
msleep(20);
if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50 ||
@@ -242,8 +238,8 @@ static int rts5260_card_power_on(struct rtsx_pcr *pcr, int card)
/* Reset SD_CFG3 register */
rtsx_pci_write_register(pcr, SD_CFG3, SD30_CLK_END_EN, 0);
rtsx_pci_write_register(pcr, REG_SD_STOP_SDCLK_CFG,
- SD30_CLK_STOP_CFG_EN | SD30_CLK_STOP_CFG1 |
- SD30_CLK_STOP_CFG0, 0);
+ SD30_CLK_STOP_CFG_EN | SD30_CLK_STOP_CFG1 |
+ SD30_CLK_STOP_CFG0, 0);
rtsx_pci_write_register(pcr, REG_PRE_RW_MODE, EN_INFINITE_MODE, 0);
@@ -273,9 +269,9 @@ static int rts5260_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
}
/* set pad drive */
- rtsx_pci_init_cmd(pcr);
rts5260_fill_driving(pcr, voltage);
- return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
+
+ return 0;
}
static void rts5260_stop_cmd(struct rtsx_pcr *pcr)
@@ -290,13 +286,9 @@ static void rts5260_stop_cmd(struct rtsx_pcr *pcr)
static void rts5260_card_before_power_off(struct rtsx_pcr *pcr)
{
- struct rtsx_cr_option *option = &pcr->option;
-
rts5260_stop_cmd(pcr);
rts5260_switch_output_voltage(pcr, OUTPUT_3V3);
- if (option->ocp_en)
- rtsx_pci_disable_ocp(pcr);
}
static int rts5260_card_power_off(struct rtsx_pcr *pcr, int card)
@@ -304,13 +296,12 @@ static int rts5260_card_power_off(struct rtsx_pcr *pcr, int card)
int err = 0;
rts5260_card_before_power_off(pcr);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_VCC_CFG1,
+ err = rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
LDO_POW_SDVDD1_MASK, LDO_POW_SDVDD1_OFF);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CONFIG2,
+ err = rtsx_pci_write_register(pcr, LDO_CONFIG2,
DV331812_POWERON, DV331812_POWEROFF);
- err = rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
+ if (pcr->option.ocp_en)
+ rtsx_pci_disable_ocp(pcr);
return err;
}
@@ -322,41 +313,29 @@ static void rts5260_init_ocp(struct rtsx_pcr *pcr)
if (option->ocp_en) {
u8 mask, val;
- rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL,
- RTS5260_DVCC_OCP_EN |
- RTS5260_DVCC_OCP_CL_EN,
- RTS5260_DVCC_OCP_EN |
- RTS5260_DVCC_OCP_CL_EN);
- rtsx_pci_write_register(pcr, RTS5260_DVIO_CTRL,
- RTS5260_DVIO_OCP_EN |
- RTS5260_DVIO_OCP_CL_EN,
- RTS5260_DVIO_OCP_EN |
- RTS5260_DVIO_OCP_CL_EN);
rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL,
- RTS5260_DVCC_OCP_THD_MASK,
- option->sd_400mA_ocp_thd);
-
- rtsx_pci_write_register(pcr, RTS5260_DVIO_CTRL,
- RTS5260_DVIO_OCP_THD_MASK,
- RTS5260_DVIO_OCP_THD_350);
+ RTS5260_DVCC_OCP_THD_MASK,
+ option->sd_800mA_ocp_thd);
rtsx_pci_write_register(pcr, RTS5260_DV331812_CFG,
- RTS5260_DV331812_OCP_THD_MASK,
- RTS5260_DV331812_OCP_THD_210);
+ RTS5260_DV331812_OCP_THD_MASK,
+ RTS5260_DV331812_OCP_THD_270);
- mask = SD_OCP_GLITCH_MASK | SDVIO_OCP_GLITCH_MASK;
+ mask = SD_OCP_GLITCH_MASK;
val = pcr->hw_param.ocp_glitch;
rtsx_pci_write_register(pcr, REG_OCPGLITCH, mask, val);
+ rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL,
+ RTS5260_DVCC_OCP_EN |
+ RTS5260_DVCC_OCP_CL_EN,
+ RTS5260_DVCC_OCP_EN |
+ RTS5260_DVCC_OCP_CL_EN);
rtsx_pci_enable_ocp(pcr);
} else {
rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL,
RTS5260_DVCC_OCP_EN |
RTS5260_DVCC_OCP_CL_EN, 0);
- rtsx_pci_write_register(pcr, RTS5260_DVIO_CTRL,
- RTS5260_DVIO_OCP_EN |
- RTS5260_DVIO_OCP_CL_EN, 0);
}
}
@@ -364,14 +343,9 @@ static void rts5260_enable_ocp(struct rtsx_pcr *pcr)
{
u8 val = 0;
- rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0);
-
val = SD_OCP_INT_EN | SD_DETECT_EN;
- val |= SDVIO_OCP_INT_EN | SDVIO_DETECT_EN;
rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
- rtsx_pci_write_register(pcr, REG_DV3318_OCPCTL,
- DV3318_DETECT_EN | DV3318_OCP_INT_EN,
- DV3318_DETECT_EN | DV3318_OCP_INT_EN);
+
}
static void rts5260_disable_ocp(struct rtsx_pcr *pcr)
@@ -379,15 +353,11 @@ static void rts5260_disable_ocp(struct rtsx_pcr *pcr)
u8 mask = 0;
mask = SD_OCP_INT_EN | SD_DETECT_EN;
- mask |= SDVIO_OCP_INT_EN | SDVIO_DETECT_EN;
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
- rtsx_pci_write_register(pcr, REG_DV3318_OCPCTL,
- DV3318_DETECT_EN | DV3318_OCP_INT_EN, 0);
- rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
- OC_POWER_DOWN);
}
+
static int rts5260_get_ocpstat(struct rtsx_pcr *pcr, u8 *val)
{
return rtsx_pci_read_register(pcr, REG_OCPSTAT, val);
@@ -404,9 +374,7 @@ static void rts5260_clear_ocpstat(struct rtsx_pcr *pcr)
u8 val = 0;
mask = SD_OCP_INT_CLR | SD_OC_CLR;
- mask |= SDVIO_OCP_INT_CLR | SDVIO_OC_CLR;
val = SD_OCP_INT_CLR | SD_OC_CLR;
- val |= SDVIO_OCP_INT_CLR | SDVIO_OC_CLR;
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
rtsx_pci_write_register(pcr, REG_DV3318_OCPCTL,
@@ -425,36 +393,22 @@ static void rts5260_process_ocp(struct rtsx_pcr *pcr)
rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat);
rts5260_get_ocpstat2(pcr, &pcr->ocp_stat2);
- if (pcr->card_exist & SD_EXIST)
- rtsx_sd_power_off_card3v3(pcr);
- else if (pcr->card_exist & MS_EXIST)
- rtsx_ms_power_off_card3v3(pcr);
-
- if (!(pcr->card_exist & MS_EXIST) && !(pcr->card_exist & SD_EXIST)) {
- if ((pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER |
- SDVIO_OC_NOW | SDVIO_OC_EVER)) ||
- (pcr->ocp_stat2 & (DV3318_OCP_NOW | DV3318_OCP_EVER)))
- rtsx_pci_clear_ocpstat(pcr);
+
+ if ((pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) ||
+ (pcr->ocp_stat2 & (DV3318_OCP_NOW | DV3318_OCP_EVER))) {
+ rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+ rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
+ rtsx_pci_clear_ocpstat(pcr);
pcr->ocp_stat = 0;
pcr->ocp_stat2 = 0;
}
- if ((pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER |
- SDVIO_OC_NOW | SDVIO_OC_EVER)) ||
- (pcr->ocp_stat2 & (DV3318_OCP_NOW | DV3318_OCP_EVER))) {
- if (pcr->card_exist & SD_EXIST)
- rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
- else if (pcr->card_exist & MS_EXIST)
- rtsx_pci_write_register(pcr, CARD_OE, MS_OUTPUT_EN, 0);
- }
}
static int rts5260_init_hw(struct rtsx_pcr *pcr)
{
int err;
- rtsx_pci_init_ocp(pcr);
-
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG1,
@@ -483,6 +437,8 @@ static int rts5260_init_hw(struct rtsx_pcr *pcr)
if (err < 0)
return err;
+ rtsx_pci_init_ocp(pcr);
+
return 0;
}
@@ -499,7 +455,13 @@ static void rts5260_pwr_saving_setting(struct rtsx_pcr *pcr)
pcr_dbg(pcr, "Set parameters for L1.2.");
rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL,
0xFF, PCIE_L1_2_EN);
- rtsx_pci_write_register(pcr, PWR_FE_CTL,
+ rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL,
+ RTS5260_DVCC_OCP_EN |
+ RTS5260_DVCC_OCP_CL_EN,
+ RTS5260_DVCC_OCP_EN |
+ RTS5260_DVCC_OCP_CL_EN);
+
+ rtsx_pci_write_register(pcr, PWR_FE_CTL,
0xFF, PCIE_L1_2_PD_FE_EN);
} else if (lss_l1_1) {
pcr_dbg(pcr, "Set parameters for L1.1.");
@@ -742,7 +704,7 @@ void rts5260_init_params(struct rtsx_pcr *pcr)
option->ocp_en = 1;
if (option->ocp_en)
hw_param->interrupt_en |= SD_OC_INT_EN;
- hw_param->ocp_glitch = SD_OCP_GLITCH_10M | SDVIO_OCP_GLITCH_800U;
+ hw_param->ocp_glitch = SDVIO_OCP_GLITCH_800U | SDVIO_OCP_GLITCH_800U;
option->sd_400mA_ocp_thd = RTS5260_DVCC_OCP_THD_550;
option->sd_800mA_ocp_thd = RTS5260_DVCC_OCP_THD_970;
}
diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
index da445223f4cc..0d320e0ab4c9 100644
--- a/drivers/misc/cardreader/rtsx_pcr.c
+++ b/drivers/misc/cardreader/rtsx_pcr.c
@@ -703,7 +703,10 @@ EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
{
- pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
+ struct rtsx_hw_param *hw_param = &pcr->hw_param;
+
+ pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN
+ | hw_param->interrupt_en;
if (pcr->num_slots > 1)
pcr->bier |= MS_INT_EN;
@@ -969,8 +972,19 @@ static void rtsx_pci_card_detect(struct work_struct *work)
static void rtsx_pci_process_ocp(struct rtsx_pcr *pcr)
{
- if (pcr->ops->process_ocp)
+ if (pcr->ops->process_ocp) {
pcr->ops->process_ocp(pcr);
+ } else {
+ if (!pcr->option.ocp_en)
+ return;
+ rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat);
+ if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+ rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+ rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
+ rtsx_pci_clear_ocpstat(pcr);
+ pcr->ocp_stat = 0;
+ }
+ }
}
static int rtsx_pci_process_ocp_interrupt(struct rtsx_pcr *pcr)
@@ -1039,7 +1053,7 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
}
}
- if (pcr->card_inserted || pcr->card_removed)
+ if ((pcr->card_inserted || pcr->card_removed) && !(int_reg & SD_OC_INT))
schedule_delayed_work(&pcr->carddet_work,
msecs_to_jiffies(200));
@@ -1144,10 +1158,12 @@ void rtsx_pci_enable_ocp(struct rtsx_pcr *pcr)
{
u8 val = SD_OCP_INT_EN | SD_DETECT_EN;
- if (pcr->ops->enable_ocp)
+ if (pcr->ops->enable_ocp) {
pcr->ops->enable_ocp(pcr);
- else
+ } else {
+ rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0);
rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
+ }
}
@@ -1155,10 +1171,13 @@ void rtsx_pci_disable_ocp(struct rtsx_pcr *pcr)
{
u8 mask = SD_OCP_INT_EN | SD_DETECT_EN;
- if (pcr->ops->disable_ocp)
+ if (pcr->ops->disable_ocp) {
pcr->ops->disable_ocp(pcr);
- else
+ } else {
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
+ rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
+ OC_POWER_DOWN);
+ }
}
void rtsx_pci_init_ocp(struct rtsx_pcr *pcr)
@@ -1169,7 +1188,7 @@ void rtsx_pci_init_ocp(struct rtsx_pcr *pcr)
struct rtsx_cr_option *option = &(pcr->option);
if (option->ocp_en) {
- u8 val = option->sd_400mA_ocp_thd;
+ u8 val = option->sd_800mA_ocp_thd;
rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0);
rtsx_pci_write_register(pcr, REG_OCPPARA1,
@@ -1204,6 +1223,7 @@ void rtsx_pci_clear_ocpstat(struct rtsx_pcr *pcr)
u8 val = SD_OCP_INT_CLR | SD_OC_CLR;
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
+ udelay(100);
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
}
}
@@ -1213,7 +1233,6 @@ int rtsx_sd_power_off_card3v3(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN |
MS_CLK_EN | SD40_CLK_EN, 0);
rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
-
rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
msleep(50);
@@ -1313,6 +1332,9 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
break;
}
+ /*init ocp*/
+ rtsx_pci_init_ocp(pcr);
+
/* Enable clk_request_n to enable clock power management */
rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
/* Enter L1 when host tx idle */
diff --git a/drivers/misc/cardreader/rtsx_pcr.h b/drivers/misc/cardreader/rtsx_pcr.h
index 6ea1655db0bb..300fc31d8e67 100644
--- a/drivers/misc/cardreader/rtsx_pcr.h
+++ b/drivers/misc/cardreader/rtsx_pcr.h
@@ -46,6 +46,11 @@
#define SSC_CLOCK_STABLE_WAIT 130
+#define RTS524A_OCP_THD_800 0x04
+#define RTS525A_OCP_THD_800 0x05
+#define RTS522A_OCP_THD_800 0x06
+
+
int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 5a17bfeb80d3..74d4fda6c4a7 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -125,9 +125,7 @@ enclosure_register(struct device *dev, const char *name, int components,
struct enclosure_component_callbacks *cb)
{
struct enclosure_device *edev =
- kzalloc(sizeof(struct enclosure_device) +
- sizeof(struct enclosure_component)*components,
- GFP_KERNEL);
+ kzalloc(struct_size(edev, component, components), GFP_KERNEL);
int err, i;
BUG_ON(!cb);
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
new file mode 100644
index 000000000000..39f832d27288
--- /dev/null
+++ b/drivers/misc/fastrpc.c
@@ -0,0 +1,1401 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+// Copyright (c) 2018, Linaro Limited
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/rpmsg.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <uapi/misc/fastrpc.h>
+
+#define ADSP_DOMAIN_ID (0)
+#define MDSP_DOMAIN_ID (1)
+#define SDSP_DOMAIN_ID (2)
+#define CDSP_DOMAIN_ID (3)
+#define FASTRPC_DEV_MAX 4 /* adsp, mdsp, slpi, cdsp*/
+#define FASTRPC_MAX_SESSIONS 9 /*8 compute, 1 cpz*/
+#define FASTRPC_ALIGN 128
+#define FASTRPC_MAX_FDLIST 16
+#define FASTRPC_MAX_CRCLIST 64
+#define FASTRPC_PHYS(p) ((p) & 0xffffffff)
+#define FASTRPC_CTX_MAX (256)
+#define FASTRPC_INIT_HANDLE 1
+#define FASTRPC_CTXID_MASK (0xFF0)
+#define INIT_FILELEN_MAX (2 * 1024 * 1024)
+#define INIT_MEMLEN_MAX (8 * 1024 * 1024)
+#define FASTRPC_DEVICE_NAME "fastrpc"
+
+/* Retrives number of input buffers from the scalars parameter */
+#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0x0ff)
+
+/* Retrives number of output buffers from the scalars parameter */
+#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0x0ff)
+
+/* Retrives number of input handles from the scalars parameter */
+#define REMOTE_SCALARS_INHANDLES(sc) (((sc) >> 4) & 0x0f)
+
+/* Retrives number of output handles from the scalars parameter */
+#define REMOTE_SCALARS_OUTHANDLES(sc) ((sc) & 0x0f)
+
+#define REMOTE_SCALARS_LENGTH(sc) (REMOTE_SCALARS_INBUFS(sc) + \
+ REMOTE_SCALARS_OUTBUFS(sc) + \
+ REMOTE_SCALARS_INHANDLES(sc)+ \
+ REMOTE_SCALARS_OUTHANDLES(sc))
+#define FASTRPC_BUILD_SCALARS(attr, method, in, out, oin, oout) \
+ (((attr & 0x07) << 29) | \
+ ((method & 0x1f) << 24) | \
+ ((in & 0xff) << 16) | \
+ ((out & 0xff) << 8) | \
+ ((oin & 0x0f) << 4) | \
+ (oout & 0x0f))
+
+#define FASTRPC_SCALARS(method, in, out) \
+ FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0)
+
+#define FASTRPC_CREATE_PROCESS_NARGS 6
+/* Remote Method id table */
+#define FASTRPC_RMID_INIT_ATTACH 0
+#define FASTRPC_RMID_INIT_RELEASE 1
+#define FASTRPC_RMID_INIT_CREATE 6
+#define FASTRPC_RMID_INIT_CREATE_ATTR 7
+#define FASTRPC_RMID_INIT_CREATE_STATIC 8
+
+#define miscdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, miscdev)
+
+static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp",
+ "sdsp", "cdsp"};
+struct fastrpc_phy_page {
+ u64 addr; /* physical address */
+ u64 size; /* size of contiguous region */
+};
+
+struct fastrpc_invoke_buf {
+ u32 num; /* number of contiguous regions */
+ u32 pgidx; /* index to start of contiguous region */
+};
+
+struct fastrpc_remote_arg {
+ u64 pv;
+ u64 len;
+};
+
+struct fastrpc_msg {
+ int pid; /* process group id */
+ int tid; /* thread id */
+ u64 ctx; /* invoke caller context */
+ u32 handle; /* handle to invoke */
+ u32 sc; /* scalars structure describing the data */
+ u64 addr; /* physical address */
+ u64 size; /* size of contiguous region */
+};
+
+struct fastrpc_invoke_rsp {
+ u64 ctx; /* invoke caller context */
+ int retval; /* invoke return value */
+};
+
+struct fastrpc_buf {
+ struct fastrpc_user *fl;
+ struct dma_buf *dmabuf;
+ struct device *dev;
+ void *virt;
+ u64 phys;
+ u64 size;
+ /* Lock for dma buf attachments */
+ struct mutex lock;
+ struct list_head attachments;
+};
+
+struct fastrpc_dma_buf_attachment {
+ struct device *dev;
+ struct sg_table sgt;
+ struct list_head node;
+};
+
+struct fastrpc_map {
+ struct list_head node;
+ struct fastrpc_user *fl;
+ int fd;
+ struct dma_buf *buf;
+ struct sg_table *table;
+ struct dma_buf_attachment *attach;
+ u64 phys;
+ u64 size;
+ void *va;
+ u64 len;
+ struct kref refcount;
+};
+
+struct fastrpc_invoke_ctx {
+ int nscalars;
+ int nbufs;
+ int retval;
+ int pid;
+ int tgid;
+ u32 sc;
+ u32 *crc;
+ u64 ctxid;
+ u64 msg_sz;
+ struct kref refcount;
+ struct list_head node; /* list of ctxs */
+ struct completion work;
+ struct fastrpc_msg msg;
+ struct fastrpc_user *fl;
+ struct fastrpc_remote_arg *rpra;
+ struct fastrpc_map **maps;
+ struct fastrpc_buf *buf;
+ struct fastrpc_invoke_args *args;
+ struct fastrpc_channel_ctx *cctx;
+};
+
+struct fastrpc_session_ctx {
+ struct device *dev;
+ int sid;
+ bool used;
+ bool valid;
+};
+
+struct fastrpc_channel_ctx {
+ int domain_id;
+ int sesscount;
+ struct rpmsg_device *rpdev;
+ struct fastrpc_session_ctx session[FASTRPC_MAX_SESSIONS];
+ spinlock_t lock;
+ struct idr ctx_idr;
+ struct list_head users;
+ struct miscdevice miscdev;
+};
+
+struct fastrpc_user {
+ struct list_head user;
+ struct list_head maps;
+ struct list_head pending;
+
+ struct fastrpc_channel_ctx *cctx;
+ struct fastrpc_session_ctx *sctx;
+ struct fastrpc_buf *init_mem;
+
+ int tgid;
+ int pd;
+ /* Lock for lists */
+ spinlock_t lock;
+ /* lock for allocations */
+ struct mutex mutex;
+};
+
+static void fastrpc_free_map(struct kref *ref)
+{
+ struct fastrpc_map *map;
+
+ map = container_of(ref, struct fastrpc_map, refcount);
+
+ if (map->table) {
+ dma_buf_unmap_attachment(map->attach, map->table,
+ DMA_BIDIRECTIONAL);
+ dma_buf_detach(map->buf, map->attach);
+ dma_buf_put(map->buf);
+ }
+
+ kfree(map);
+}
+
+static void fastrpc_map_put(struct fastrpc_map *map)
+{
+ if (map)
+ kref_put(&map->refcount, fastrpc_free_map);
+}
+
+static void fastrpc_map_get(struct fastrpc_map *map)
+{
+ if (map)
+ kref_get(&map->refcount);
+}
+
+static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
+ struct fastrpc_map **ppmap)
+{
+ struct fastrpc_map *map = NULL;
+
+ mutex_lock(&fl->mutex);
+ list_for_each_entry(map, &fl->maps, node) {
+ if (map->fd == fd) {
+ fastrpc_map_get(map);
+ *ppmap = map;
+ mutex_unlock(&fl->mutex);
+ return 0;
+ }
+ }
+ mutex_unlock(&fl->mutex);
+
+ return -ENOENT;
+}
+
+static void fastrpc_buf_free(struct fastrpc_buf *buf)
+{
+ dma_free_coherent(buf->dev, buf->size, buf->virt,
+ FASTRPC_PHYS(buf->phys));
+ kfree(buf);
+}
+
+static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
+ u64 size, struct fastrpc_buf **obuf)
+{
+ struct fastrpc_buf *buf;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&buf->attachments);
+ mutex_init(&buf->lock);
+
+ buf->fl = fl;
+ buf->virt = NULL;
+ buf->phys = 0;
+ buf->size = size;
+ buf->dev = dev;
+
+ buf->virt = dma_alloc_coherent(dev, buf->size, (dma_addr_t *)&buf->phys,
+ GFP_KERNEL);
+ if (!buf->virt)
+ return -ENOMEM;
+
+ if (fl->sctx && fl->sctx->sid)
+ buf->phys += ((u64)fl->sctx->sid << 32);
+
+ *obuf = buf;
+
+ return 0;
+}
+
+static void fastrpc_context_free(struct kref *ref)
+{
+ struct fastrpc_invoke_ctx *ctx;
+ struct fastrpc_channel_ctx *cctx;
+ int i;
+
+ ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount);
+ cctx = ctx->cctx;
+
+ for (i = 0; i < ctx->nscalars; i++)
+ fastrpc_map_put(ctx->maps[i]);
+
+ if (ctx->buf)
+ fastrpc_buf_free(ctx->buf);
+
+ spin_lock(&cctx->lock);
+ idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4);
+ spin_unlock(&cctx->lock);
+
+ kfree(ctx->maps);
+ kfree(ctx);
+}
+
+static void fastrpc_context_get(struct fastrpc_invoke_ctx *ctx)
+{
+ kref_get(&ctx->refcount);
+}
+
+static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx)
+{
+ kref_put(&ctx->refcount, fastrpc_context_free);
+}
+
+static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
+ struct fastrpc_user *user, u32 kernel, u32 sc,
+ struct fastrpc_invoke_args *args)
+{
+ struct fastrpc_channel_ctx *cctx = user->cctx;
+ struct fastrpc_invoke_ctx *ctx = NULL;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&ctx->node);
+ ctx->fl = user;
+ ctx->nscalars = REMOTE_SCALARS_LENGTH(sc);
+ ctx->nbufs = REMOTE_SCALARS_INBUFS(sc) +
+ REMOTE_SCALARS_OUTBUFS(sc);
+
+ if (ctx->nscalars) {
+ ctx->maps = kcalloc(ctx->nscalars,
+ sizeof(*ctx->maps), GFP_KERNEL);
+ if (!ctx->maps) {
+ kfree(ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+ ctx->args = args;
+ }
+
+ ctx->sc = sc;
+ ctx->retval = -1;
+ ctx->pid = current->pid;
+ ctx->tgid = user->tgid;
+ ctx->cctx = cctx;
+ init_completion(&ctx->work);
+
+ spin_lock(&user->lock);
+ list_add_tail(&ctx->node, &user->pending);
+ spin_unlock(&user->lock);
+
+ spin_lock(&cctx->lock);
+ ret = idr_alloc_cyclic(&cctx->ctx_idr, ctx, 1,
+ FASTRPC_CTX_MAX, GFP_ATOMIC);
+ if (ret < 0) {
+ spin_unlock(&cctx->lock);
+ goto err_idr;
+ }
+ ctx->ctxid = ret << 4;
+ spin_unlock(&cctx->lock);
+
+ kref_init(&ctx->refcount);
+
+ return ctx;
+err_idr:
+ spin_lock(&user->lock);
+ list_del(&ctx->node);
+ spin_unlock(&user->lock);
+ kfree(ctx->maps);
+ kfree(ctx);
+
+ return ERR_PTR(ret);
+}
+
+static struct sg_table *
+fastrpc_map_dma_buf(struct dma_buf_attachment *attachment,
+ enum dma_data_direction dir)
+{
+ struct fastrpc_dma_buf_attachment *a = attachment->priv;
+ struct sg_table *table;
+
+ table = &a->sgt;
+
+ if (!dma_map_sg(attachment->dev, table->sgl, table->nents, dir))
+ return ERR_PTR(-ENOMEM);
+
+ return table;
+}
+
+static void fastrpc_unmap_dma_buf(struct dma_buf_attachment *attach,
+ struct sg_table *table,
+ enum dma_data_direction dir)
+{
+ dma_unmap_sg(attach->dev, table->sgl, table->nents, dir);
+}
+
+static void fastrpc_release(struct dma_buf *dmabuf)
+{
+ struct fastrpc_buf *buffer = dmabuf->priv;
+
+ fastrpc_buf_free(buffer);
+}
+
+static int fastrpc_dma_buf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+{
+ struct fastrpc_dma_buf_attachment *a;
+ struct fastrpc_buf *buffer = dmabuf->priv;
+ int ret;
+
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
+ if (!a)
+ return -ENOMEM;
+
+ ret = dma_get_sgtable(buffer->dev, &a->sgt, buffer->virt,
+ FASTRPC_PHYS(buffer->phys), buffer->size);
+ if (ret < 0) {
+ dev_err(buffer->dev, "failed to get scatterlist from DMA API\n");
+ return -EINVAL;
+ }
+
+ a->dev = attachment->dev;
+ INIT_LIST_HEAD(&a->node);
+ attachment->priv = a;
+
+ mutex_lock(&buffer->lock);
+ list_add(&a->node, &buffer->attachments);
+ mutex_unlock(&buffer->lock);
+
+ return 0;
+}
+
+static void fastrpc_dma_buf_detatch(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+{
+ struct fastrpc_dma_buf_attachment *a = attachment->priv;
+ struct fastrpc_buf *buffer = dmabuf->priv;
+
+ mutex_lock(&buffer->lock);
+ list_del(&a->node);
+ mutex_unlock(&buffer->lock);
+ kfree(a);
+}
+
+static void *fastrpc_kmap(struct dma_buf *dmabuf, unsigned long pgnum)
+{
+ struct fastrpc_buf *buf = dmabuf->priv;
+
+ return buf->virt ? buf->virt + pgnum * PAGE_SIZE : NULL;
+}
+
+static void *fastrpc_vmap(struct dma_buf *dmabuf)
+{
+ struct fastrpc_buf *buf = dmabuf->priv;
+
+ return buf->virt;
+}
+
+static int fastrpc_mmap(struct dma_buf *dmabuf,
+ struct vm_area_struct *vma)
+{
+ struct fastrpc_buf *buf = dmabuf->priv;
+ size_t size = vma->vm_end - vma->vm_start;
+
+ return dma_mmap_coherent(buf->dev, vma, buf->virt,
+ FASTRPC_PHYS(buf->phys), size);
+}
+
+static const struct dma_buf_ops fastrpc_dma_buf_ops = {
+ .attach = fastrpc_dma_buf_attach,
+ .detach = fastrpc_dma_buf_detatch,
+ .map_dma_buf = fastrpc_map_dma_buf,
+ .unmap_dma_buf = fastrpc_unmap_dma_buf,
+ .mmap = fastrpc_mmap,
+ .map = fastrpc_kmap,
+ .vmap = fastrpc_vmap,
+ .release = fastrpc_release,
+};
+
+static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
+ u64 len, struct fastrpc_map **ppmap)
+{
+ struct fastrpc_session_ctx *sess = fl->sctx;
+ struct fastrpc_map *map = NULL;
+ int err = 0;
+
+ if (!fastrpc_map_find(fl, fd, ppmap))
+ return 0;
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&map->node);
+ map->fl = fl;
+ map->fd = fd;
+ map->buf = dma_buf_get(fd);
+ if (IS_ERR(map->buf)) {
+ err = PTR_ERR(map->buf);
+ goto get_err;
+ }
+
+ map->attach = dma_buf_attach(map->buf, sess->dev);
+ if (IS_ERR(map->attach)) {
+ dev_err(sess->dev, "Failed to attach dmabuf\n");
+ err = PTR_ERR(map->attach);
+ goto attach_err;
+ }
+
+ map->table = dma_buf_map_attachment(map->attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(map->table)) {
+ err = PTR_ERR(map->table);
+ goto map_err;
+ }
+
+ map->phys = sg_dma_address(map->table->sgl);
+ map->phys += ((u64)fl->sctx->sid << 32);
+ map->size = len;
+ map->va = sg_virt(map->table->sgl);
+ map->len = len;
+ kref_init(&map->refcount);
+
+ spin_lock(&fl->lock);
+ list_add_tail(&map->node, &fl->maps);
+ spin_unlock(&fl->lock);
+ *ppmap = map;
+
+ return 0;
+
+map_err:
+ dma_buf_detach(map->buf, map->attach);
+attach_err:
+ dma_buf_put(map->buf);
+get_err:
+ kfree(map);
+
+ return err;
+}
+
+/*
+ * Fastrpc payload buffer with metadata looks like:
+ *
+ * >>>>>> START of METADATA <<<<<<<<<
+ * +---------------------------------+
+ * | Arguments |
+ * | type:(struct fastrpc_remote_arg)|
+ * | (0 - N) |
+ * +---------------------------------+
+ * | Invoke Buffer list |
+ * | type:(struct fastrpc_invoke_buf)|
+ * | (0 - N) |
+ * +---------------------------------+
+ * | Page info list |
+ * | type:(struct fastrpc_phy_page) |
+ * | (0 - N) |
+ * +---------------------------------+
+ * | Optional info |
+ * |(can be specific to SoC/Firmware)|
+ * +---------------------------------+
+ * >>>>>>>> END of METADATA <<<<<<<<<
+ * +---------------------------------+
+ * | Inline ARGS |
+ * | (0-N) |
+ * +---------------------------------+
+ */
+
+static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx)
+{
+ int size = 0;
+
+ size = (sizeof(struct fastrpc_remote_arg) +
+ sizeof(struct fastrpc_invoke_buf) +
+ sizeof(struct fastrpc_phy_page)) * ctx->nscalars +
+ sizeof(u64) * FASTRPC_MAX_FDLIST +
+ sizeof(u32) * FASTRPC_MAX_CRCLIST;
+
+ return size;
+}
+
+static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen)
+{
+ u64 size = 0;
+ int i;
+
+ size = ALIGN(metalen, FASTRPC_ALIGN);
+ for (i = 0; i < ctx->nscalars; i++) {
+ if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) {
+ size = ALIGN(size, FASTRPC_ALIGN);
+ size += ctx->args[i].length;
+ }
+ }
+
+ return size;
+}
+
+static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
+{
+ struct device *dev = ctx->fl->sctx->dev;
+ int i, err;
+
+ for (i = 0; i < ctx->nscalars; ++i) {
+ /* Make sure reserved field is set to 0 */
+ if (ctx->args[i].reserved)
+ return -EINVAL;
+
+ if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1 ||
+ ctx->args[i].length == 0)
+ continue;
+
+ err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
+ ctx->args[i].length, &ctx->maps[i]);
+ if (err) {
+ dev_err(dev, "Error Creating map %d\n", err);
+ return -EINVAL;
+ }
+
+ }
+ return 0;
+}
+
+static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
+{
+ struct device *dev = ctx->fl->sctx->dev;
+ struct fastrpc_remote_arg *rpra;
+ struct fastrpc_invoke_buf *list;
+ struct fastrpc_phy_page *pages;
+ int inbufs, i, err = 0;
+ u64 rlen, pkt_size;
+ uintptr_t args;
+ int metalen;
+
+
+ inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
+ metalen = fastrpc_get_meta_size(ctx);
+ pkt_size = fastrpc_get_payload_size(ctx, metalen);
+
+ err = fastrpc_create_maps(ctx);
+ if (err)
+ return err;
+
+ ctx->msg_sz = pkt_size;
+
+ err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+ if (err)
+ return err;
+
+ rpra = ctx->buf->virt;
+ list = ctx->buf->virt + ctx->nscalars * sizeof(*rpra);
+ pages = ctx->buf->virt + ctx->nscalars * (sizeof(*list) +
+ sizeof(*rpra));
+ args = (uintptr_t)ctx->buf->virt + metalen;
+ rlen = pkt_size - metalen;
+ ctx->rpra = rpra;
+
+ for (i = 0; i < ctx->nbufs; ++i) {
+ u64 len = ctx->args[i].length;
+
+ rpra[i].pv = 0;
+ rpra[i].len = len;
+ list[i].num = len ? 1 : 0;
+ list[i].pgidx = i;
+
+ if (!len)
+ continue;
+
+ pages[i].size = roundup(len, PAGE_SIZE);
+
+ if (ctx->maps[i]) {
+ rpra[i].pv = (u64) ctx->args[i].ptr;
+ pages[i].addr = ctx->maps[i]->phys;
+ } else {
+ rlen -= ALIGN(args, FASTRPC_ALIGN) - args;
+ args = ALIGN(args, FASTRPC_ALIGN);
+ if (rlen < len)
+ goto bail;
+
+ rpra[i].pv = args;
+ pages[i].addr = ctx->buf->phys + (pkt_size - rlen);
+ pages[i].addr = pages[i].addr & PAGE_MASK;
+ args = args + len;
+ rlen -= len;
+ }
+
+ if (i < inbufs && !ctx->maps[i]) {
+ void *dst = (void *)(uintptr_t)rpra[i].pv;
+ void *src = (void *)(uintptr_t)ctx->args[i].ptr;
+
+ if (!kernel) {
+ if (copy_from_user(dst, (void __user *)src,
+ len)) {
+ err = -EFAULT;
+ goto bail;
+ }
+ } else {
+ memcpy(dst, src, len);
+ }
+ }
+ }
+
+ for (i = ctx->nbufs; i < ctx->nscalars; ++i) {
+ rpra[i].pv = (u64) ctx->args[i].ptr;
+ rpra[i].len = ctx->args[i].length;
+ list[i].num = ctx->args[i].length ? 1 : 0;
+ list[i].pgidx = i;
+ pages[i].addr = ctx->maps[i]->phys;
+ pages[i].size = ctx->maps[i]->size;
+ }
+
+bail:
+ if (err)
+ dev_err(dev, "Error: get invoke args failed:%d\n", err);
+
+ return err;
+}
+
+static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
+ u32 kernel)
+{
+ struct fastrpc_remote_arg *rpra = ctx->rpra;
+ int i, inbufs;
+
+ inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
+
+ for (i = inbufs; i < ctx->nbufs; ++i) {
+ void *src = (void *)(uintptr_t)rpra[i].pv;
+ void *dst = (void *)(uintptr_t)ctx->args[i].ptr;
+ u64 len = rpra[i].len;
+
+ if (!kernel) {
+ if (copy_to_user((void __user *)dst, src, len))
+ return -EFAULT;
+ } else {
+ memcpy(dst, src, len);
+ }
+ }
+
+ return 0;
+}
+
+static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx,
+ struct fastrpc_invoke_ctx *ctx,
+ u32 kernel, uint32_t handle)
+{
+ struct fastrpc_channel_ctx *cctx;
+ struct fastrpc_user *fl = ctx->fl;
+ struct fastrpc_msg *msg = &ctx->msg;
+
+ cctx = fl->cctx;
+ msg->pid = fl->tgid;
+ msg->tid = current->pid;
+
+ if (kernel)
+ msg->pid = 0;
+
+ msg->ctx = ctx->ctxid | fl->pd;
+ msg->handle = handle;
+ msg->sc = ctx->sc;
+ msg->addr = ctx->buf ? ctx->buf->phys : 0;
+ msg->size = roundup(ctx->msg_sz, PAGE_SIZE);
+ fastrpc_context_get(ctx);
+
+ return rpmsg_send(cctx->rpdev->ept, (void *)msg, sizeof(*msg));
+}
+
+static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
+ u32 handle, u32 sc,
+ struct fastrpc_invoke_args *args)
+{
+ struct fastrpc_invoke_ctx *ctx = NULL;
+ int err = 0;
+
+ if (!fl->sctx)
+ return -EINVAL;
+
+ ctx = fastrpc_context_alloc(fl, kernel, sc, args);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ if (ctx->nscalars) {
+ err = fastrpc_get_args(kernel, ctx);
+ if (err)
+ goto bail;
+ }
+ /* Send invoke buffer to remote dsp */
+ err = fastrpc_invoke_send(fl->sctx, ctx, kernel, handle);
+ if (err)
+ goto bail;
+
+ /* Wait for remote dsp to respond or time out */
+ err = wait_for_completion_interruptible(&ctx->work);
+ if (err)
+ goto bail;
+
+ /* Check the response from remote dsp */
+ err = ctx->retval;
+ if (err)
+ goto bail;
+
+ if (ctx->nscalars) {
+ /* populate all the output buffers with results */
+ err = fastrpc_put_args(ctx, kernel);
+ if (err)
+ goto bail;
+ }
+
+bail:
+ /* We are done with this compute context, remove it from pending list */
+ spin_lock(&fl->lock);
+ list_del(&ctx->node);
+ spin_unlock(&fl->lock);
+ fastrpc_context_put(ctx);
+
+ if (err)
+ dev_dbg(fl->sctx->dev, "Error: Invoke Failed %d\n", err);
+
+ return err;
+}
+
+static int fastrpc_init_create_process(struct fastrpc_user *fl,
+ char __user *argp)
+{
+ struct fastrpc_init_create init;
+ struct fastrpc_invoke_args *args;
+ struct fastrpc_phy_page pages[1];
+ struct fastrpc_map *map = NULL;
+ struct fastrpc_buf *imem = NULL;
+ int memlen;
+ int err;
+ struct {
+ int pgid;
+ u32 namelen;
+ u32 filelen;
+ u32 pageslen;
+ u32 attrs;
+ u32 siglen;
+ } inbuf;
+ u32 sc;
+
+ args = kcalloc(FASTRPC_CREATE_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+
+ if (copy_from_user(&init, argp, sizeof(init))) {
+ err = -EFAULT;
+ goto bail;
+ }
+
+ if (init.filelen > INIT_FILELEN_MAX) {
+ err = -EINVAL;
+ goto bail;
+ }
+
+ inbuf.pgid = fl->tgid;
+ inbuf.namelen = strlen(current->comm) + 1;
+ inbuf.filelen = init.filelen;
+ inbuf.pageslen = 1;
+ inbuf.attrs = init.attrs;
+ inbuf.siglen = init.siglen;
+ fl->pd = 1;
+
+ if (init.filelen && init.filefd) {
+ err = fastrpc_map_create(fl, init.filefd, init.filelen, &map);
+ if (err)
+ goto bail;
+ }
+
+ memlen = ALIGN(max(INIT_FILELEN_MAX, (int)init.filelen * 4),
+ 1024 * 1024);
+ err = fastrpc_buf_alloc(fl, fl->sctx->dev, memlen,
+ &imem);
+ if (err) {
+ fastrpc_map_put(map);
+ goto bail;
+ }
+
+ fl->init_mem = imem;
+ args[0].ptr = (u64)(uintptr_t)&inbuf;
+ args[0].length = sizeof(inbuf);
+ args[0].fd = -1;
+
+ args[1].ptr = (u64)(uintptr_t)current->comm;
+ args[1].length = inbuf.namelen;
+ args[1].fd = -1;
+
+ args[2].ptr = (u64) init.file;
+ args[2].length = inbuf.filelen;
+ args[2].fd = init.filefd;
+
+ pages[0].addr = imem->phys;
+ pages[0].size = imem->size;
+
+ args[3].ptr = (u64)(uintptr_t) pages;
+ args[3].length = 1 * sizeof(*pages);
+ args[3].fd = -1;
+
+ args[4].ptr = (u64)(uintptr_t)&inbuf.attrs;
+ args[4].length = sizeof(inbuf.attrs);
+ args[4].fd = -1;
+
+ args[5].ptr = (u64)(uintptr_t) &inbuf.siglen;
+ args[5].length = sizeof(inbuf.siglen);
+ args[5].fd = -1;
+
+ sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
+ if (init.attrs)
+ sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+
+ err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+ sc, args);
+
+ if (err) {
+ fastrpc_map_put(map);
+ fastrpc_buf_free(imem);
+ }
+
+bail:
+ kfree(args);
+
+ return err;
+}
+
+static struct fastrpc_session_ctx *fastrpc_session_alloc(
+ struct fastrpc_channel_ctx *cctx)
+{
+ struct fastrpc_session_ctx *session = NULL;
+ int i;
+
+ spin_lock(&cctx->lock);
+ for (i = 0; i < cctx->sesscount; i++) {
+ if (!cctx->session[i].used && cctx->session[i].valid) {
+ cctx->session[i].used = true;
+ session = &cctx->session[i];
+ break;
+ }
+ }
+ spin_unlock(&cctx->lock);
+
+ return session;
+}
+
+static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
+ struct fastrpc_session_ctx *session)
+{
+ spin_lock(&cctx->lock);
+ session->used = false;
+ spin_unlock(&cctx->lock);
+}
+
+static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
+{
+ struct fastrpc_invoke_args args[1];
+ int tgid = 0;
+ u32 sc;
+
+ tgid = fl->tgid;
+ args[0].ptr = (u64)(uintptr_t) &tgid;
+ args[0].length = sizeof(tgid);
+ args[0].fd = -1;
+ args[0].reserved = 0;
+ sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0);
+
+ return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+ sc, &args[0]);
+}
+
+static int fastrpc_device_release(struct inode *inode, struct file *file)
+{
+ struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
+ struct fastrpc_channel_ctx *cctx = fl->cctx;
+ struct fastrpc_invoke_ctx *ctx, *n;
+ struct fastrpc_map *map, *m;
+
+ fastrpc_release_current_dsp_process(fl);
+
+ spin_lock(&cctx->lock);
+ list_del(&fl->user);
+ spin_unlock(&cctx->lock);
+
+ if (fl->init_mem)
+ fastrpc_buf_free(fl->init_mem);
+
+ list_for_each_entry_safe(ctx, n, &fl->pending, node) {
+ list_del(&ctx->node);
+ fastrpc_context_put(ctx);
+ }
+
+ list_for_each_entry_safe(map, m, &fl->maps, node) {
+ list_del(&map->node);
+ fastrpc_map_put(map);
+ }
+
+ fastrpc_session_free(cctx, fl->sctx);
+
+ mutex_destroy(&fl->mutex);
+ kfree(fl);
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static int fastrpc_device_open(struct inode *inode, struct file *filp)
+{
+ struct fastrpc_channel_ctx *cctx = miscdev_to_cctx(filp->private_data);
+ struct fastrpc_user *fl = NULL;
+
+ fl = kzalloc(sizeof(*fl), GFP_KERNEL);
+ if (!fl)
+ return -ENOMEM;
+
+ filp->private_data = fl;
+ spin_lock_init(&fl->lock);
+ mutex_init(&fl->mutex);
+ INIT_LIST_HEAD(&fl->pending);
+ INIT_LIST_HEAD(&fl->maps);
+ INIT_LIST_HEAD(&fl->user);
+ fl->tgid = current->tgid;
+ fl->cctx = cctx;
+
+ fl->sctx = fastrpc_session_alloc(cctx);
+ if (!fl->sctx) {
+ dev_err(&cctx->rpdev->dev, "No session available\n");
+ mutex_destroy(&fl->mutex);
+ kfree(fl);
+
+ return -EBUSY;
+ }
+
+ spin_lock(&cctx->lock);
+ list_add_tail(&fl->user, &cctx->users);
+ spin_unlock(&cctx->lock);
+
+ return 0;
+}
+
+static int fastrpc_dmabuf_free(struct fastrpc_user *fl, char __user *argp)
+{
+ struct dma_buf *buf;
+ int info;
+
+ if (copy_from_user(&info, argp, sizeof(info)))
+ return -EFAULT;
+
+ buf = dma_buf_get(info);
+ if (IS_ERR_OR_NULL(buf))
+ return -EINVAL;
+ /*
+ * one for the last get and other for the ALLOC_DMA_BUFF ioctl
+ */
+ dma_buf_put(buf);
+ dma_buf_put(buf);
+
+ return 0;
+}
+
+static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
+{
+ struct fastrpc_alloc_dma_buf bp;
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+ struct fastrpc_buf *buf = NULL;
+ int err;
+
+ if (copy_from_user(&bp, argp, sizeof(bp)))
+ return -EFAULT;
+
+ err = fastrpc_buf_alloc(fl, fl->sctx->dev, bp.size, &buf);
+ if (err)
+ return err;
+ exp_info.ops = &fastrpc_dma_buf_ops;
+ exp_info.size = bp.size;
+ exp_info.flags = O_RDWR;
+ exp_info.priv = buf;
+ buf->dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(buf->dmabuf)) {
+ err = PTR_ERR(buf->dmabuf);
+ fastrpc_buf_free(buf);
+ return err;
+ }
+
+ bp.fd = dma_buf_fd(buf->dmabuf, O_ACCMODE);
+ if (bp.fd < 0) {
+ dma_buf_put(buf->dmabuf);
+ return -EINVAL;
+ }
+
+ if (copy_to_user(argp, &bp, sizeof(bp))) {
+ dma_buf_put(buf->dmabuf);
+ return -EFAULT;
+ }
+
+ get_dma_buf(buf->dmabuf);
+
+ return 0;
+}
+
+static int fastrpc_init_attach(struct fastrpc_user *fl)
+{
+ struct fastrpc_invoke_args args[1];
+ int tgid = fl->tgid;
+ u32 sc;
+
+ args[0].ptr = (u64)(uintptr_t) &tgid;
+ args[0].length = sizeof(tgid);
+ args[0].fd = -1;
+ args[0].reserved = 0;
+ sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0);
+ fl->pd = 0;
+
+ return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+ sc, &args[0]);
+}
+
+static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp)
+{
+ struct fastrpc_invoke_args *args = NULL;
+ struct fastrpc_invoke inv;
+ u32 nscalars;
+ int err;
+
+ if (copy_from_user(&inv, argp, sizeof(inv)))
+ return -EFAULT;
+
+ /* nscalars is truncated here to max supported value */
+ nscalars = REMOTE_SCALARS_LENGTH(inv.sc);
+ if (nscalars) {
+ args = kcalloc(nscalars, sizeof(*args), GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+
+ if (copy_from_user(args, (void __user *)(uintptr_t)inv.args,
+ nscalars * sizeof(*args))) {
+ kfree(args);
+ return -EFAULT;
+ }
+ }
+
+ err = fastrpc_internal_invoke(fl, false, inv.handle, inv.sc, args);
+ kfree(args);
+
+ return err;
+}
+
+static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
+ char __user *argp = (char __user *)arg;
+ int err;
+
+ switch (cmd) {
+ case FASTRPC_IOCTL_INVOKE:
+ err = fastrpc_invoke(fl, argp);
+ break;
+ case FASTRPC_IOCTL_INIT_ATTACH:
+ err = fastrpc_init_attach(fl);
+ break;
+ case FASTRPC_IOCTL_INIT_CREATE:
+ err = fastrpc_init_create_process(fl, argp);
+ break;
+ case FASTRPC_IOCTL_FREE_DMA_BUFF:
+ err = fastrpc_dmabuf_free(fl, argp);
+ break;
+ case FASTRPC_IOCTL_ALLOC_DMA_BUFF:
+ err = fastrpc_dmabuf_alloc(fl, argp);
+ break;
+ default:
+ err = -ENOTTY;
+ break;
+ }
+
+ return err;
+}
+
+static const struct file_operations fastrpc_fops = {
+ .open = fastrpc_device_open,
+ .release = fastrpc_device_release,
+ .unlocked_ioctl = fastrpc_device_ioctl,
+ .compat_ioctl = fastrpc_device_ioctl,
+};
+
+static int fastrpc_cb_probe(struct platform_device *pdev)
+{
+ struct fastrpc_channel_ctx *cctx;
+ struct fastrpc_session_ctx *sess;
+ struct device *dev = &pdev->dev;
+ int i, sessions = 0;
+
+ cctx = dev_get_drvdata(dev->parent);
+ if (!cctx)
+ return -EINVAL;
+
+ of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
+
+ spin_lock(&cctx->lock);
+ sess = &cctx->session[cctx->sesscount];
+ sess->used = false;
+ sess->valid = true;
+ sess->dev = dev;
+ dev_set_drvdata(dev, sess);
+
+ if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
+ dev_info(dev, "FastRPC Session ID not specified in DT\n");
+
+ if (sessions > 0) {
+ struct fastrpc_session_ctx *dup_sess;
+
+ for (i = 1; i < sessions; i++) {
+ if (cctx->sesscount++ >= FASTRPC_MAX_SESSIONS)
+ break;
+ dup_sess = &cctx->session[cctx->sesscount];
+ memcpy(dup_sess, sess, sizeof(*dup_sess));
+ }
+ }
+ cctx->sesscount++;
+ spin_unlock(&cctx->lock);
+ dma_set_mask(dev, DMA_BIT_MASK(32));
+
+ return 0;
+}
+
+static int fastrpc_cb_remove(struct platform_device *pdev)
+{
+ struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
+ struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
+ int i;
+
+ spin_lock(&cctx->lock);
+ for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) {
+ if (cctx->session[i].sid == sess->sid) {
+ cctx->session[i].valid = false;
+ cctx->sesscount--;
+ }
+ }
+ spin_unlock(&cctx->lock);
+
+ return 0;
+}
+
+static const struct of_device_id fastrpc_match_table[] = {
+ { .compatible = "qcom,fastrpc-compute-cb", },
+ {}
+};
+
+static struct platform_driver fastrpc_cb_driver = {
+ .probe = fastrpc_cb_probe,
+ .remove = fastrpc_cb_remove,
+ .driver = {
+ .name = "qcom,fastrpc-cb",
+ .of_match_table = fastrpc_match_table,
+ .suppress_bind_attrs = true,
+ },
+};
+
+static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ struct device *rdev = &rpdev->dev;
+ struct fastrpc_channel_ctx *data;
+ int i, err, domain_id = -1;
+ const char *domain;
+
+ data = devm_kzalloc(rdev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = of_property_read_string(rdev->of_node, "label", &domain);
+ if (err) {
+ dev_info(rdev, "FastRPC Domain not specified in DT\n");
+ return err;
+ }
+
+ for (i = 0; i <= CDSP_DOMAIN_ID; i++) {
+ if (!strcmp(domains[i], domain)) {
+ domain_id = i;
+ break;
+ }
+ }
+
+ if (domain_id < 0) {
+ dev_info(rdev, "FastRPC Invalid Domain ID %d\n", domain_id);
+ return -EINVAL;
+ }
+
+ data->miscdev.minor = MISC_DYNAMIC_MINOR;
+ data->miscdev.name = kasprintf(GFP_KERNEL, "fastrpc-%s",
+ domains[domain_id]);
+ data->miscdev.fops = &fastrpc_fops;
+ err = misc_register(&data->miscdev);
+ if (err)
+ return err;
+
+ dev_set_drvdata(&rpdev->dev, data);
+ dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
+ INIT_LIST_HEAD(&data->users);
+ spin_lock_init(&data->lock);
+ idr_init(&data->ctx_idr);
+ data->domain_id = domain_id;
+ data->rpdev = rpdev;
+
+ return of_platform_populate(rdev->of_node, NULL, NULL, rdev);
+}
+
+static void fastrpc_notify_users(struct fastrpc_user *user)
+{
+ struct fastrpc_invoke_ctx *ctx;
+
+ spin_lock(&user->lock);
+ list_for_each_entry(ctx, &user->pending, node)
+ complete(&ctx->work);
+ spin_unlock(&user->lock);
+}
+
+static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+ struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev);
+ struct fastrpc_user *user;
+
+ spin_lock(&cctx->lock);
+ list_for_each_entry(user, &cctx->users, user)
+ fastrpc_notify_users(user);
+ spin_unlock(&cctx->lock);
+
+ misc_deregister(&cctx->miscdev);
+ of_platform_depopulate(&rpdev->dev);
+ kfree(cctx);
+}
+
+static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 addr)
+{
+ struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev);
+ struct fastrpc_invoke_rsp *rsp = data;
+ struct fastrpc_invoke_ctx *ctx;
+ unsigned long flags;
+ unsigned long ctxid;
+
+ if (len < sizeof(*rsp))
+ return -EINVAL;
+
+ ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4);
+
+ spin_lock_irqsave(&cctx->lock, flags);
+ ctx = idr_find(&cctx->ctx_idr, ctxid);
+ spin_unlock_irqrestore(&cctx->lock, flags);
+
+ if (!ctx) {
+ dev_err(&rpdev->dev, "No context ID matches response\n");
+ return -ENOENT;
+ }
+
+ ctx->retval = rsp->retval;
+ complete(&ctx->work);
+ fastrpc_context_put(ctx);
+
+ return 0;
+}
+
+static const struct of_device_id fastrpc_rpmsg_of_match[] = {
+ { .compatible = "qcom,fastrpc" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, fastrpc_rpmsg_of_match);
+
+static struct rpmsg_driver fastrpc_driver = {
+ .probe = fastrpc_rpmsg_probe,
+ .remove = fastrpc_rpmsg_remove,
+ .callback = fastrpc_rpmsg_callback,
+ .drv = {
+ .name = "qcom,fastrpc",
+ .of_match_table = fastrpc_rpmsg_of_match,
+ },
+};
+
+static int fastrpc_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&fastrpc_cb_driver);
+ if (ret < 0) {
+ pr_err("fastrpc: failed to register cb driver\n");
+ return ret;
+ }
+
+ ret = register_rpmsg_driver(&fastrpc_driver);
+ if (ret < 0) {
+ pr_err("fastrpc: failed to register rpmsg driver\n");
+ platform_driver_unregister(&fastrpc_cb_driver);
+ return ret;
+ }
+
+ return 0;
+}
+module_init(fastrpc_init);
+
+static void fastrpc_exit(void)
+{
+ platform_driver_unregister(&fastrpc_cb_driver);
+ unregister_rpmsg_driver(&fastrpc_driver);
+}
+module_exit(fastrpc_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index efe2fb72d54b..25265fd0fd6e 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -218,8 +218,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
if (get_order(size) >= MAX_ORDER)
return NULL;
- return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle,
- GFP_KERNEL);
+ return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
+ GFP_KERNEL);
}
void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
diff --git a/drivers/misc/habanalabs/Kconfig b/drivers/misc/habanalabs/Kconfig
new file mode 100644
index 000000000000..99db2b82ada6
--- /dev/null
+++ b/drivers/misc/habanalabs/Kconfig
@@ -0,0 +1,25 @@
+#
+# HabanaLabs AI accelerators driver
+#
+
+config HABANA_AI
+ tristate "HabanaAI accelerators (habanalabs)"
+ depends on PCI && HAS_IOMEM
+ select FRAME_VECTOR
+ select DMA_SHARED_BUFFER
+ select GENERIC_ALLOCATOR
+ select HWMON
+ help
+ Enables PCIe card driver for Habana's AI Processors (AIP) that are
+ designed to accelerate Deep Learning inference and training workloads.
+
+ The driver manages the PCIe devices and provides IOCTL interface for
+ the user to submit workloads to the devices.
+
+ The user-space interface is described in
+ include/uapi/misc/habanalabs.h
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called habanalabs.
diff --git a/drivers/misc/habanalabs/Makefile b/drivers/misc/habanalabs/Makefile
new file mode 100644
index 000000000000..c6592db59b25
--- /dev/null
+++ b/drivers/misc/habanalabs/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for HabanaLabs AI accelerators driver
+#
+
+obj-m := habanalabs.o
+
+habanalabs-y := habanalabs_drv.o device.o context.o asid.o habanalabs_ioctl.o \
+ command_buffer.o hw_queue.o irq.o sysfs.o hwmon.o memory.o \
+ command_submission.o mmu.o
+
+habanalabs-$(CONFIG_DEBUG_FS) += debugfs.o
+
+include $(src)/goya/Makefile
+habanalabs-y += $(HL_GOYA_FILES)
diff --git a/drivers/misc/habanalabs/asid.c b/drivers/misc/habanalabs/asid.c
new file mode 100644
index 000000000000..f54e7971a762
--- /dev/null
+++ b/drivers/misc/habanalabs/asid.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/slab.h>
+
+int hl_asid_init(struct hl_device *hdev)
+{
+ hdev->asid_bitmap = kcalloc(BITS_TO_LONGS(hdev->asic_prop.max_asid),
+ sizeof(*hdev->asid_bitmap), GFP_KERNEL);
+ if (!hdev->asid_bitmap)
+ return -ENOMEM;
+
+ mutex_init(&hdev->asid_mutex);
+
+ /* ASID 0 is reserved for KMD */
+ set_bit(0, hdev->asid_bitmap);
+
+ return 0;
+}
+
+void hl_asid_fini(struct hl_device *hdev)
+{
+ mutex_destroy(&hdev->asid_mutex);
+ kfree(hdev->asid_bitmap);
+}
+
+unsigned long hl_asid_alloc(struct hl_device *hdev)
+{
+ unsigned long found;
+
+ mutex_lock(&hdev->asid_mutex);
+
+ found = find_first_zero_bit(hdev->asid_bitmap,
+ hdev->asic_prop.max_asid);
+ if (found == hdev->asic_prop.max_asid)
+ found = 0;
+ else
+ set_bit(found, hdev->asid_bitmap);
+
+ mutex_unlock(&hdev->asid_mutex);
+
+ return found;
+}
+
+void hl_asid_free(struct hl_device *hdev, unsigned long asid)
+{
+ if (WARN((asid == 0 || asid >= hdev->asic_prop.max_asid),
+ "Invalid ASID %lu", asid))
+ return;
+ clear_bit(asid, hdev->asid_bitmap);
+}
diff --git a/drivers/misc/habanalabs/command_buffer.c b/drivers/misc/habanalabs/command_buffer.c
new file mode 100644
index 000000000000..85f75806a9a7
--- /dev/null
+++ b/drivers/misc/habanalabs/command_buffer.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include <uapi/misc/habanalabs.h>
+#include "habanalabs.h"
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
+{
+ hdev->asic_funcs->dma_free_coherent(hdev, cb->size,
+ (void *) (uintptr_t) cb->kernel_address,
+ cb->bus_address);
+ kfree(cb);
+}
+
+static void cb_do_release(struct hl_device *hdev, struct hl_cb *cb)
+{
+ if (cb->is_pool) {
+ spin_lock(&hdev->cb_pool_lock);
+ list_add(&cb->pool_list, &hdev->cb_pool);
+ spin_unlock(&hdev->cb_pool_lock);
+ } else {
+ cb_fini(hdev, cb);
+ }
+}
+
+static void cb_release(struct kref *ref)
+{
+ struct hl_device *hdev;
+ struct hl_cb *cb;
+
+ cb = container_of(ref, struct hl_cb, refcount);
+ hdev = cb->hdev;
+
+ hl_debugfs_remove_cb(cb);
+
+ cb_do_release(hdev, cb);
+}
+
+static struct hl_cb *hl_cb_alloc(struct hl_device *hdev, u32 cb_size,
+ int ctx_id)
+{
+ struct hl_cb *cb;
+ void *p;
+
+ /*
+ * We use of GFP_ATOMIC here because this function can be called from
+ * the latency-sensitive code path for command submission. Due to H/W
+ * limitations in some of the ASICs, the kernel must copy the user CB
+ * that is designated for an external queue and actually enqueue
+ * the kernel's copy. Hence, we must never sleep in this code section
+ * and must use GFP_ATOMIC for all memory allocations.
+ */
+ if (ctx_id == HL_KERNEL_ASID_ID)
+ cb = kzalloc(sizeof(*cb), GFP_ATOMIC);
+ else
+ cb = kzalloc(sizeof(*cb), GFP_KERNEL);
+
+ if (!cb)
+ return NULL;
+
+ if (ctx_id == HL_KERNEL_ASID_ID)
+ p = hdev->asic_funcs->dma_alloc_coherent(hdev, cb_size,
+ &cb->bus_address, GFP_ATOMIC);
+ else
+ p = hdev->asic_funcs->dma_alloc_coherent(hdev, cb_size,
+ &cb->bus_address,
+ GFP_USER | __GFP_ZERO);
+ if (!p) {
+ dev_err(hdev->dev,
+ "failed to allocate %d of dma memory for CB\n",
+ cb_size);
+ kfree(cb);
+ return NULL;
+ }
+
+ cb->kernel_address = (u64) (uintptr_t) p;
+ cb->size = cb_size;
+
+ return cb;
+}
+
+int hl_cb_create(struct hl_device *hdev, struct hl_cb_mgr *mgr,
+ u32 cb_size, u64 *handle, int ctx_id)
+{
+ struct hl_cb *cb;
+ bool alloc_new_cb = true;
+ int rc;
+
+ /*
+ * Can't use generic function to check this because of special case
+ * where we create a CB as part of the reset process
+ */
+ if ((hdev->disabled) || ((atomic_read(&hdev->in_reset)) &&
+ (ctx_id != HL_KERNEL_ASID_ID))) {
+ dev_warn_ratelimited(hdev->dev,
+ "Device is disabled or in reset. Can't create new CBs\n");
+ rc = -EBUSY;
+ goto out_err;
+ }
+
+ if (cb_size > HL_MAX_CB_SIZE) {
+ dev_err(hdev->dev,
+ "CB size %d must be less then %d\n",
+ cb_size, HL_MAX_CB_SIZE);
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ /* Minimum allocation must be PAGE SIZE */
+ if (cb_size < PAGE_SIZE)
+ cb_size = PAGE_SIZE;
+
+ if (ctx_id == HL_KERNEL_ASID_ID &&
+ cb_size <= hdev->asic_prop.cb_pool_cb_size) {
+
+ spin_lock(&hdev->cb_pool_lock);
+ if (!list_empty(&hdev->cb_pool)) {
+ cb = list_first_entry(&hdev->cb_pool, typeof(*cb),
+ pool_list);
+ list_del(&cb->pool_list);
+ spin_unlock(&hdev->cb_pool_lock);
+ alloc_new_cb = false;
+ } else {
+ spin_unlock(&hdev->cb_pool_lock);
+ dev_dbg(hdev->dev, "CB pool is empty\n");
+ }
+ }
+
+ if (alloc_new_cb) {
+ cb = hl_cb_alloc(hdev, cb_size, ctx_id);
+ if (!cb) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+ }
+
+ cb->hdev = hdev;
+ cb->ctx_id = ctx_id;
+
+ spin_lock(&mgr->cb_lock);
+ rc = idr_alloc(&mgr->cb_handles, cb, 1, 0, GFP_ATOMIC);
+ spin_unlock(&mgr->cb_lock);
+
+ if (rc < 0) {
+ dev_err(hdev->dev, "Failed to allocate IDR for a new CB\n");
+ goto release_cb;
+ }
+
+ cb->id = rc;
+
+ kref_init(&cb->refcount);
+ spin_lock_init(&cb->lock);
+
+ /*
+ * idr is 32-bit so we can safely OR it with a mask that is above
+ * 32 bit
+ */
+ *handle = cb->id | HL_MMAP_CB_MASK;
+ *handle <<= PAGE_SHIFT;
+
+ hl_debugfs_add_cb(cb);
+
+ return 0;
+
+release_cb:
+ cb_do_release(hdev, cb);
+out_err:
+ *handle = 0;
+
+ return rc;
+}
+
+int hl_cb_destroy(struct hl_device *hdev, struct hl_cb_mgr *mgr, u64 cb_handle)
+{
+ struct hl_cb *cb;
+ u32 handle;
+ int rc = 0;
+
+ /*
+ * handle was given to user to do mmap, I need to shift it back to
+ * how the idr module gave it to me
+ */
+ cb_handle >>= PAGE_SHIFT;
+ handle = (u32) cb_handle;
+
+ spin_lock(&mgr->cb_lock);
+
+ cb = idr_find(&mgr->cb_handles, handle);
+ if (cb) {
+ idr_remove(&mgr->cb_handles, handle);
+ spin_unlock(&mgr->cb_lock);
+ kref_put(&cb->refcount, cb_release);
+ } else {
+ spin_unlock(&mgr->cb_lock);
+ dev_err(hdev->dev,
+ "CB destroy failed, no match to handle 0x%x\n", handle);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int hl_cb_ioctl(struct hl_fpriv *hpriv, void *data)
+{
+ union hl_cb_args *args = data;
+ struct hl_device *hdev = hpriv->hdev;
+ u64 handle;
+ int rc;
+
+ switch (args->in.op) {
+ case HL_CB_OP_CREATE:
+ rc = hl_cb_create(hdev, &hpriv->cb_mgr, args->in.cb_size,
+ &handle, hpriv->ctx->asid);
+ memset(args, 0, sizeof(*args));
+ args->out.cb_handle = handle;
+ break;
+ case HL_CB_OP_DESTROY:
+ rc = hl_cb_destroy(hdev, &hpriv->cb_mgr,
+ args->in.cb_handle);
+ break;
+ default:
+ rc = -ENOTTY;
+ break;
+ }
+
+ return rc;
+}
+
+static void cb_vm_close(struct vm_area_struct *vma)
+{
+ struct hl_cb *cb = (struct hl_cb *) vma->vm_private_data;
+ long new_mmap_size;
+
+ new_mmap_size = cb->mmap_size - (vma->vm_end - vma->vm_start);
+
+ if (new_mmap_size > 0) {
+ cb->mmap_size = new_mmap_size;
+ return;
+ }
+
+ spin_lock(&cb->lock);
+ cb->mmap = false;
+ spin_unlock(&cb->lock);
+
+ hl_cb_put(cb);
+ vma->vm_private_data = NULL;
+}
+
+static const struct vm_operations_struct cb_vm_ops = {
+ .close = cb_vm_close
+};
+
+int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
+{
+ struct hl_device *hdev = hpriv->hdev;
+ struct hl_cb *cb;
+ phys_addr_t address;
+ u32 handle;
+ int rc;
+
+ handle = vma->vm_pgoff;
+
+ /* reference was taken here */
+ cb = hl_cb_get(hdev, &hpriv->cb_mgr, handle);
+ if (!cb) {
+ dev_err(hdev->dev,
+ "CB mmap failed, no match to handle %d\n", handle);
+ return -EINVAL;
+ }
+
+ /* Validation check */
+ if ((vma->vm_end - vma->vm_start) != ALIGN(cb->size, PAGE_SIZE)) {
+ dev_err(hdev->dev,
+ "CB mmap failed, mmap size 0x%lx != 0x%x cb size\n",
+ vma->vm_end - vma->vm_start, cb->size);
+ rc = -EINVAL;
+ goto put_cb;
+ }
+
+ spin_lock(&cb->lock);
+
+ if (cb->mmap) {
+ dev_err(hdev->dev,
+ "CB mmap failed, CB already mmaped to user\n");
+ rc = -EINVAL;
+ goto release_lock;
+ }
+
+ cb->mmap = true;
+
+ spin_unlock(&cb->lock);
+
+ vma->vm_ops = &cb_vm_ops;
+
+ /*
+ * Note: We're transferring the cb reference to
+ * vma->vm_private_data here.
+ */
+
+ vma->vm_private_data = cb;
+
+ /* Calculate address for CB */
+ address = virt_to_phys((void *) (uintptr_t) cb->kernel_address);
+
+ rc = hdev->asic_funcs->cb_mmap(hdev, vma, cb->kernel_address,
+ address, cb->size);
+
+ if (rc) {
+ spin_lock(&cb->lock);
+ cb->mmap = false;
+ goto release_lock;
+ }
+
+ cb->mmap_size = cb->size;
+
+ return 0;
+
+release_lock:
+ spin_unlock(&cb->lock);
+put_cb:
+ hl_cb_put(cb);
+ return rc;
+}
+
+struct hl_cb *hl_cb_get(struct hl_device *hdev, struct hl_cb_mgr *mgr,
+ u32 handle)
+{
+ struct hl_cb *cb;
+
+ spin_lock(&mgr->cb_lock);
+ cb = idr_find(&mgr->cb_handles, handle);
+
+ if (!cb) {
+ spin_unlock(&mgr->cb_lock);
+ dev_warn(hdev->dev,
+ "CB get failed, no match to handle %d\n", handle);
+ return NULL;
+ }
+
+ kref_get(&cb->refcount);
+
+ spin_unlock(&mgr->cb_lock);
+
+ return cb;
+
+}
+
+void hl_cb_put(struct hl_cb *cb)
+{
+ kref_put(&cb->refcount, cb_release);
+}
+
+void hl_cb_mgr_init(struct hl_cb_mgr *mgr)
+{
+ spin_lock_init(&mgr->cb_lock);
+ idr_init(&mgr->cb_handles);
+}
+
+void hl_cb_mgr_fini(struct hl_device *hdev, struct hl_cb_mgr *mgr)
+{
+ struct hl_cb *cb;
+ struct idr *idp;
+ u32 id;
+
+ idp = &mgr->cb_handles;
+
+ idr_for_each_entry(idp, cb, id) {
+ if (kref_put(&cb->refcount, cb_release) != 1)
+ dev_err(hdev->dev,
+ "CB %d for CTX ID %d is still alive\n",
+ id, cb->ctx_id);
+ }
+
+ idr_destroy(&mgr->cb_handles);
+}
+
+struct hl_cb *hl_cb_kernel_create(struct hl_device *hdev, u32 cb_size)
+{
+ u64 cb_handle;
+ struct hl_cb *cb;
+ int rc;
+
+ rc = hl_cb_create(hdev, &hdev->kernel_cb_mgr, cb_size, &cb_handle,
+ HL_KERNEL_ASID_ID);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to allocate CB for KMD %d\n", rc);
+ return NULL;
+ }
+
+ cb_handle >>= PAGE_SHIFT;
+ cb = hl_cb_get(hdev, &hdev->kernel_cb_mgr, (u32) cb_handle);
+ /* hl_cb_get should never fail here so use kernel WARN */
+ WARN(!cb, "Kernel CB handle invalid 0x%x\n", (u32) cb_handle);
+ if (!cb)
+ goto destroy_cb;
+
+ return cb;
+
+destroy_cb:
+ hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, cb_handle << PAGE_SHIFT);
+
+ return NULL;
+}
+
+int hl_cb_pool_init(struct hl_device *hdev)
+{
+ struct hl_cb *cb;
+ int i;
+
+ INIT_LIST_HEAD(&hdev->cb_pool);
+ spin_lock_init(&hdev->cb_pool_lock);
+
+ for (i = 0 ; i < hdev->asic_prop.cb_pool_cb_cnt ; i++) {
+ cb = hl_cb_alloc(hdev, hdev->asic_prop.cb_pool_cb_size,
+ HL_KERNEL_ASID_ID);
+ if (cb) {
+ cb->is_pool = true;
+ list_add(&cb->pool_list, &hdev->cb_pool);
+ } else {
+ hl_cb_pool_fini(hdev);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int hl_cb_pool_fini(struct hl_device *hdev)
+{
+ struct hl_cb *cb, *tmp;
+
+ list_for_each_entry_safe(cb, tmp, &hdev->cb_pool, pool_list) {
+ list_del(&cb->pool_list);
+ cb_fini(hdev, cb);
+ }
+
+ return 0;
+}
diff --git a/drivers/misc/habanalabs/command_submission.c b/drivers/misc/habanalabs/command_submission.c
new file mode 100644
index 000000000000..3525236ed8d9
--- /dev/null
+++ b/drivers/misc/habanalabs/command_submission.c
@@ -0,0 +1,780 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include <uapi/misc/habanalabs.h>
+#include "habanalabs.h"
+
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+static void job_wq_completion(struct work_struct *work);
+static long _hl_cs_wait_ioctl(struct hl_device *hdev,
+ struct hl_ctx *ctx, u64 timeout_us, u64 seq);
+static void cs_do_release(struct kref *ref);
+
+static const char *hl_fence_get_driver_name(struct dma_fence *fence)
+{
+ return "HabanaLabs";
+}
+
+static const char *hl_fence_get_timeline_name(struct dma_fence *fence)
+{
+ struct hl_dma_fence *hl_fence =
+ container_of(fence, struct hl_dma_fence, base_fence);
+
+ return dev_name(hl_fence->hdev->dev);
+}
+
+static bool hl_fence_enable_signaling(struct dma_fence *fence)
+{
+ return true;
+}
+
+static void hl_fence_release(struct dma_fence *fence)
+{
+ struct hl_dma_fence *hl_fence =
+ container_of(fence, struct hl_dma_fence, base_fence);
+
+ kfree_rcu(hl_fence, base_fence.rcu);
+}
+
+static const struct dma_fence_ops hl_fence_ops = {
+ .get_driver_name = hl_fence_get_driver_name,
+ .get_timeline_name = hl_fence_get_timeline_name,
+ .enable_signaling = hl_fence_enable_signaling,
+ .wait = dma_fence_default_wait,
+ .release = hl_fence_release
+};
+
+static void cs_get(struct hl_cs *cs)
+{
+ kref_get(&cs->refcount);
+}
+
+static int cs_get_unless_zero(struct hl_cs *cs)
+{
+ return kref_get_unless_zero(&cs->refcount);
+}
+
+static void cs_put(struct hl_cs *cs)
+{
+ kref_put(&cs->refcount, cs_do_release);
+}
+
+/*
+ * cs_parser - parse the user command submission
+ *
+ * @hpriv : pointer to the private data of the fd
+ * @job : pointer to the job that holds the command submission info
+ *
+ * The function parses the command submission of the user. It calls the
+ * ASIC specific parser, which returns a list of memory blocks to send
+ * to the device as different command buffers
+ *
+ */
+static int cs_parser(struct hl_fpriv *hpriv, struct hl_cs_job *job)
+{
+ struct hl_device *hdev = hpriv->hdev;
+ struct hl_cs_parser parser;
+ int rc;
+
+ parser.ctx_id = job->cs->ctx->asid;
+ parser.cs_sequence = job->cs->sequence;
+ parser.job_id = job->id;
+
+ parser.hw_queue_id = job->hw_queue_id;
+ parser.job_userptr_list = &job->userptr_list;
+ parser.patched_cb = NULL;
+ parser.user_cb = job->user_cb;
+ parser.user_cb_size = job->user_cb_size;
+ parser.ext_queue = job->ext_queue;
+ job->patched_cb = NULL;
+ parser.use_virt_addr = hdev->mmu_enable;
+
+ rc = hdev->asic_funcs->cs_parser(hdev, &parser);
+ if (job->ext_queue) {
+ if (!rc) {
+ job->patched_cb = parser.patched_cb;
+ job->job_cb_size = parser.patched_cb_size;
+
+ spin_lock(&job->patched_cb->lock);
+ job->patched_cb->cs_cnt++;
+ spin_unlock(&job->patched_cb->lock);
+ }
+
+ /*
+ * Whether the parsing worked or not, we don't need the
+ * original CB anymore because it was already parsed and
+ * won't be accessed again for this CS
+ */
+ spin_lock(&job->user_cb->lock);
+ job->user_cb->cs_cnt--;
+ spin_unlock(&job->user_cb->lock);
+ hl_cb_put(job->user_cb);
+ job->user_cb = NULL;
+ }
+
+ return rc;
+}
+
+static void free_job(struct hl_device *hdev, struct hl_cs_job *job)
+{
+ struct hl_cs *cs = job->cs;
+
+ if (job->ext_queue) {
+ hl_userptr_delete_list(hdev, &job->userptr_list);
+
+ /*
+ * We might arrive here from rollback and patched CB wasn't
+ * created, so we need to check it's not NULL
+ */
+ if (job->patched_cb) {
+ spin_lock(&job->patched_cb->lock);
+ job->patched_cb->cs_cnt--;
+ spin_unlock(&job->patched_cb->lock);
+
+ hl_cb_put(job->patched_cb);
+ }
+ }
+
+ /*
+ * This is the only place where there can be multiple threads
+ * modifying the list at the same time
+ */
+ spin_lock(&cs->job_lock);
+ list_del(&job->cs_node);
+ spin_unlock(&cs->job_lock);
+
+ hl_debugfs_remove_job(hdev, job);
+
+ if (job->ext_queue)
+ cs_put(cs);
+
+ kfree(job);
+}
+
+static void cs_do_release(struct kref *ref)
+{
+ struct hl_cs *cs = container_of(ref, struct hl_cs,
+ refcount);
+ struct hl_device *hdev = cs->ctx->hdev;
+ struct hl_cs_job *job, *tmp;
+
+ cs->completed = true;
+
+ /*
+ * Although if we reached here it means that all external jobs have
+ * finished, because each one of them took refcnt to CS, we still
+ * need to go over the internal jobs and free them. Otherwise, we
+ * will have leaked memory and what's worse, the CS object (and
+ * potentially the CTX object) could be released, while the JOB
+ * still holds a pointer to them (but no reference).
+ */
+ list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node)
+ free_job(hdev, job);
+
+ /* We also need to update CI for internal queues */
+ if (cs->submitted) {
+ hl_int_hw_queue_update_ci(cs);
+
+ spin_lock(&hdev->hw_queues_mirror_lock);
+ /* remove CS from hw_queues mirror list */
+ list_del_init(&cs->mirror_node);
+ spin_unlock(&hdev->hw_queues_mirror_lock);
+
+ /*
+ * Don't cancel TDR in case this CS was timedout because we
+ * might be running from the TDR context
+ */
+ if ((!cs->timedout) &&
+ (hdev->timeout_jiffies != MAX_SCHEDULE_TIMEOUT)) {
+ struct hl_cs *next;
+
+ if (cs->tdr_active)
+ cancel_delayed_work_sync(&cs->work_tdr);
+
+ spin_lock(&hdev->hw_queues_mirror_lock);
+
+ /* queue TDR for next CS */
+ next = list_first_entry_or_null(
+ &hdev->hw_queues_mirror_list,
+ struct hl_cs, mirror_node);
+
+ if ((next) && (!next->tdr_active)) {
+ next->tdr_active = true;
+ schedule_delayed_work(&next->work_tdr,
+ hdev->timeout_jiffies);
+ }
+
+ spin_unlock(&hdev->hw_queues_mirror_lock);
+ }
+ }
+
+ /*
+ * Must be called before hl_ctx_put because inside we use ctx to get
+ * the device
+ */
+ hl_debugfs_remove_cs(cs);
+
+ hl_ctx_put(cs->ctx);
+
+ if (cs->timedout)
+ dma_fence_set_error(cs->fence, -ETIMEDOUT);
+ else if (cs->aborted)
+ dma_fence_set_error(cs->fence, -EIO);
+
+ dma_fence_signal(cs->fence);
+ dma_fence_put(cs->fence);
+
+ kfree(cs);
+}
+
+static void cs_timedout(struct work_struct *work)
+{
+ struct hl_device *hdev;
+ int ctx_asid, rc;
+ struct hl_cs *cs = container_of(work, struct hl_cs,
+ work_tdr.work);
+ rc = cs_get_unless_zero(cs);
+ if (!rc)
+ return;
+
+ if ((!cs->submitted) || (cs->completed)) {
+ cs_put(cs);
+ return;
+ }
+
+ /* Mark the CS is timed out so we won't try to cancel its TDR */
+ cs->timedout = true;
+
+ hdev = cs->ctx->hdev;
+ ctx_asid = cs->ctx->asid;
+
+ /* TODO: add information about last signaled seq and last emitted seq */
+ dev_err(hdev->dev, "CS %d.%llu got stuck!\n", ctx_asid, cs->sequence);
+
+ cs_put(cs);
+
+ if (hdev->reset_on_lockup)
+ hl_device_reset(hdev, false, false);
+}
+
+static int allocate_cs(struct hl_device *hdev, struct hl_ctx *ctx,
+ struct hl_cs **cs_new)
+{
+ struct hl_dma_fence *fence;
+ struct dma_fence *other = NULL;
+ struct hl_cs *cs;
+ int rc;
+
+ cs = kzalloc(sizeof(*cs), GFP_ATOMIC);
+ if (!cs)
+ return -ENOMEM;
+
+ cs->ctx = ctx;
+ cs->submitted = false;
+ cs->completed = false;
+ INIT_LIST_HEAD(&cs->job_list);
+ INIT_DELAYED_WORK(&cs->work_tdr, cs_timedout);
+ kref_init(&cs->refcount);
+ spin_lock_init(&cs->job_lock);
+
+ fence = kmalloc(sizeof(*fence), GFP_ATOMIC);
+ if (!fence) {
+ rc = -ENOMEM;
+ goto free_cs;
+ }
+
+ fence->hdev = hdev;
+ spin_lock_init(&fence->lock);
+ cs->fence = &fence->base_fence;
+
+ spin_lock(&ctx->cs_lock);
+
+ fence->cs_seq = ctx->cs_sequence;
+ other = ctx->cs_pending[fence->cs_seq & (HL_MAX_PENDING_CS - 1)];
+ if ((other) && (!dma_fence_is_signaled(other))) {
+ spin_unlock(&ctx->cs_lock);
+ rc = -EAGAIN;
+ goto free_fence;
+ }
+
+ dma_fence_init(&fence->base_fence, &hl_fence_ops, &fence->lock,
+ ctx->asid, ctx->cs_sequence);
+
+ cs->sequence = fence->cs_seq;
+
+ ctx->cs_pending[fence->cs_seq & (HL_MAX_PENDING_CS - 1)] =
+ &fence->base_fence;
+ ctx->cs_sequence++;
+
+ dma_fence_get(&fence->base_fence);
+
+ dma_fence_put(other);
+
+ spin_unlock(&ctx->cs_lock);
+
+ *cs_new = cs;
+
+ return 0;
+
+free_fence:
+ kfree(fence);
+free_cs:
+ kfree(cs);
+ return rc;
+}
+
+static void cs_rollback(struct hl_device *hdev, struct hl_cs *cs)
+{
+ struct hl_cs_job *job, *tmp;
+
+ list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node)
+ free_job(hdev, job);
+}
+
+void hl_cs_rollback_all(struct hl_device *hdev)
+{
+ struct hl_cs *cs, *tmp;
+
+ /* flush all completions */
+ flush_workqueue(hdev->cq_wq);
+
+ /* Make sure we don't have leftovers in the H/W queues mirror list */
+ list_for_each_entry_safe(cs, tmp, &hdev->hw_queues_mirror_list,
+ mirror_node) {
+ cs_get(cs);
+ cs->aborted = true;
+ dev_warn_ratelimited(hdev->dev, "Killing CS %d.%llu\n",
+ cs->ctx->asid, cs->sequence);
+ cs_rollback(hdev, cs);
+ cs_put(cs);
+ }
+}
+
+static void job_wq_completion(struct work_struct *work)
+{
+ struct hl_cs_job *job = container_of(work, struct hl_cs_job,
+ finish_work);
+ struct hl_cs *cs = job->cs;
+ struct hl_device *hdev = cs->ctx->hdev;
+
+ /* job is no longer needed */
+ free_job(hdev, job);
+}
+
+static struct hl_cb *validate_queue_index(struct hl_device *hdev,
+ struct hl_cb_mgr *cb_mgr,
+ struct hl_cs_chunk *chunk,
+ bool *ext_queue)
+{
+ struct asic_fixed_properties *asic = &hdev->asic_prop;
+ struct hw_queue_properties *hw_queue_prop;
+ u32 cb_handle;
+ struct hl_cb *cb;
+
+ /* Assume external queue */
+ *ext_queue = true;
+
+ hw_queue_prop = &asic->hw_queues_props[chunk->queue_index];
+
+ if ((chunk->queue_index >= HL_MAX_QUEUES) ||
+ (hw_queue_prop->type == QUEUE_TYPE_NA)) {
+ dev_err(hdev->dev, "Queue index %d is invalid\n",
+ chunk->queue_index);
+ return NULL;
+ }
+
+ if (hw_queue_prop->kmd_only) {
+ dev_err(hdev->dev, "Queue index %d is restricted for KMD\n",
+ chunk->queue_index);
+ return NULL;
+ } else if (hw_queue_prop->type == QUEUE_TYPE_INT) {
+ *ext_queue = false;
+ return (struct hl_cb *) (uintptr_t) chunk->cb_handle;
+ }
+
+ /* Retrieve CB object */
+ cb_handle = (u32) (chunk->cb_handle >> PAGE_SHIFT);
+
+ cb = hl_cb_get(hdev, cb_mgr, cb_handle);
+ if (!cb) {
+ dev_err(hdev->dev, "CB handle 0x%x invalid\n", cb_handle);
+ return NULL;
+ }
+
+ if ((chunk->cb_size < 8) || (chunk->cb_size > cb->size)) {
+ dev_err(hdev->dev, "CB size %u invalid\n", chunk->cb_size);
+ goto release_cb;
+ }
+
+ spin_lock(&cb->lock);
+ cb->cs_cnt++;
+ spin_unlock(&cb->lock);
+
+ return cb;
+
+release_cb:
+ hl_cb_put(cb);
+ return NULL;
+}
+
+struct hl_cs_job *hl_cs_allocate_job(struct hl_device *hdev, bool ext_queue)
+{
+ struct hl_cs_job *job;
+
+ job = kzalloc(sizeof(*job), GFP_ATOMIC);
+ if (!job)
+ return NULL;
+
+ job->ext_queue = ext_queue;
+
+ if (job->ext_queue) {
+ INIT_LIST_HEAD(&job->userptr_list);
+ INIT_WORK(&job->finish_work, job_wq_completion);
+ }
+
+ return job;
+}
+
+static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
+ u32 num_chunks, u64 *cs_seq)
+{
+ struct hl_device *hdev = hpriv->hdev;
+ struct hl_cs_chunk *cs_chunk_array;
+ struct hl_cs_job *job;
+ struct hl_cs *cs;
+ struct hl_cb *cb;
+ bool ext_queue_present = false;
+ u32 size_to_copy;
+ int rc, i, parse_cnt;
+
+ *cs_seq = ULLONG_MAX;
+
+ if (num_chunks > HL_MAX_JOBS_PER_CS) {
+ dev_err(hdev->dev,
+ "Number of chunks can NOT be larger than %d\n",
+ HL_MAX_JOBS_PER_CS);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ cs_chunk_array = kmalloc_array(num_chunks, sizeof(*cs_chunk_array),
+ GFP_ATOMIC);
+ if (!cs_chunk_array) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ size_to_copy = num_chunks * sizeof(struct hl_cs_chunk);
+ if (copy_from_user(cs_chunk_array, chunks, size_to_copy)) {
+ dev_err(hdev->dev, "Failed to copy cs chunk array from user\n");
+ rc = -EFAULT;
+ goto free_cs_chunk_array;
+ }
+
+ /* increment refcnt for context */
+ hl_ctx_get(hdev, hpriv->ctx);
+
+ rc = allocate_cs(hdev, hpriv->ctx, &cs);
+ if (rc) {
+ hl_ctx_put(hpriv->ctx);
+ goto free_cs_chunk_array;
+ }
+
+ *cs_seq = cs->sequence;
+
+ hl_debugfs_add_cs(cs);
+
+ /* Validate ALL the CS chunks before submitting the CS */
+ for (i = 0, parse_cnt = 0 ; i < num_chunks ; i++, parse_cnt++) {
+ struct hl_cs_chunk *chunk = &cs_chunk_array[i];
+ bool ext_queue;
+
+ cb = validate_queue_index(hdev, &hpriv->cb_mgr, chunk,
+ &ext_queue);
+ if (ext_queue) {
+ ext_queue_present = true;
+ if (!cb) {
+ rc = -EINVAL;
+ goto free_cs_object;
+ }
+ }
+
+ job = hl_cs_allocate_job(hdev, ext_queue);
+ if (!job) {
+ dev_err(hdev->dev, "Failed to allocate a new job\n");
+ rc = -ENOMEM;
+ if (ext_queue)
+ goto release_cb;
+ else
+ goto free_cs_object;
+ }
+
+ job->id = i + 1;
+ job->cs = cs;
+ job->user_cb = cb;
+ job->user_cb_size = chunk->cb_size;
+ if (job->ext_queue)
+ job->job_cb_size = cb->size;
+ else
+ job->job_cb_size = chunk->cb_size;
+ job->hw_queue_id = chunk->queue_index;
+
+ cs->jobs_in_queue_cnt[job->hw_queue_id]++;
+
+ list_add_tail(&job->cs_node, &cs->job_list);
+
+ /*
+ * Increment CS reference. When CS reference is 0, CS is
+ * done and can be signaled to user and free all its resources
+ * Only increment for JOB on external queues, because only
+ * for those JOBs we get completion
+ */
+ if (job->ext_queue)
+ cs_get(cs);
+
+ hl_debugfs_add_job(hdev, job);
+
+ rc = cs_parser(hpriv, job);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to parse JOB %d.%llu.%d, err %d, rejecting the CS\n",
+ cs->ctx->asid, cs->sequence, job->id, rc);
+ goto free_cs_object;
+ }
+ }
+
+ if (!ext_queue_present) {
+ dev_err(hdev->dev,
+ "Reject CS %d.%llu because no external queues jobs\n",
+ cs->ctx->asid, cs->sequence);
+ rc = -EINVAL;
+ goto free_cs_object;
+ }
+
+ rc = hl_hw_queue_schedule_cs(cs);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to submit CS %d.%llu to H/W queues, error %d\n",
+ cs->ctx->asid, cs->sequence, rc);
+ goto free_cs_object;
+ }
+
+ rc = HL_CS_STATUS_SUCCESS;
+ goto put_cs;
+
+release_cb:
+ spin_lock(&cb->lock);
+ cb->cs_cnt--;
+ spin_unlock(&cb->lock);
+ hl_cb_put(cb);
+free_cs_object:
+ cs_rollback(hdev, cs);
+ *cs_seq = ULLONG_MAX;
+ /* The path below is both for good and erroneous exits */
+put_cs:
+ /* We finished with the CS in this function, so put the ref */
+ cs_put(cs);
+free_cs_chunk_array:
+ kfree(cs_chunk_array);
+out:
+ return rc;
+}
+
+int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data)
+{
+ struct hl_device *hdev = hpriv->hdev;
+ union hl_cs_args *args = data;
+ struct hl_ctx *ctx = hpriv->ctx;
+ void __user *chunks;
+ u32 num_chunks;
+ u64 cs_seq = ULONG_MAX;
+ int rc, do_restore;
+ bool need_soft_reset = false;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ dev_warn(hdev->dev,
+ "Device is %s. Can't submit new CS\n",
+ atomic_read(&hdev->in_reset) ? "in_reset" : "disabled");
+ rc = -EBUSY;
+ goto out;
+ }
+
+ do_restore = atomic_cmpxchg(&ctx->thread_restore_token, 1, 0);
+
+ if (do_restore || (args->in.cs_flags & HL_CS_FLAGS_FORCE_RESTORE)) {
+ long ret;
+
+ chunks = (void __user *)(uintptr_t)args->in.chunks_restore;
+ num_chunks = args->in.num_chunks_restore;
+
+ mutex_lock(&hpriv->restore_phase_mutex);
+
+ if (do_restore) {
+ rc = hdev->asic_funcs->context_switch(hdev, ctx->asid);
+ if (rc) {
+ dev_err_ratelimited(hdev->dev,
+ "Failed to switch to context %d, rejecting CS! %d\n",
+ ctx->asid, rc);
+ /*
+ * If we timedout, or if the device is not IDLE
+ * while we want to do context-switch (-EBUSY),
+ * we need to soft-reset because QMAN is
+ * probably stuck. However, we can't call to
+ * reset here directly because of deadlock, so
+ * need to do it at the very end of this
+ * function
+ */
+ if ((rc == -ETIMEDOUT) || (rc == -EBUSY))
+ need_soft_reset = true;
+ mutex_unlock(&hpriv->restore_phase_mutex);
+ goto out;
+ }
+ }
+
+ hdev->asic_funcs->restore_phase_topology(hdev);
+
+ if (num_chunks == 0) {
+ dev_dbg(hdev->dev,
+ "Need to run restore phase but restore CS is empty\n");
+ rc = 0;
+ } else {
+ rc = _hl_cs_ioctl(hpriv, chunks, num_chunks,
+ &cs_seq);
+ }
+
+ mutex_unlock(&hpriv->restore_phase_mutex);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to submit restore CS for context %d (%d)\n",
+ ctx->asid, rc);
+ goto out;
+ }
+
+ /* Need to wait for restore completion before execution phase */
+ if (num_chunks > 0) {
+ ret = _hl_cs_wait_ioctl(hdev, ctx,
+ jiffies_to_usecs(hdev->timeout_jiffies),
+ cs_seq);
+ if (ret <= 0) {
+ dev_err(hdev->dev,
+ "Restore CS for context %d failed to complete %ld\n",
+ ctx->asid, ret);
+ rc = -ENOEXEC;
+ goto out;
+ }
+ }
+
+ ctx->thread_restore_wait_token = 1;
+ } else if (!ctx->thread_restore_wait_token) {
+ u32 tmp;
+
+ rc = hl_poll_timeout_memory(hdev,
+ (u64) (uintptr_t) &ctx->thread_restore_wait_token,
+ jiffies_to_usecs(hdev->timeout_jiffies),
+ &tmp);
+
+ if (rc || !tmp) {
+ dev_err(hdev->dev,
+ "restore phase hasn't finished in time\n");
+ rc = -ETIMEDOUT;
+ goto out;
+ }
+ }
+
+ chunks = (void __user *)(uintptr_t)args->in.chunks_execute;
+ num_chunks = args->in.num_chunks_execute;
+
+ if (num_chunks == 0) {
+ dev_err(hdev->dev,
+ "Got execute CS with 0 chunks, context %d\n",
+ ctx->asid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = _hl_cs_ioctl(hpriv, chunks, num_chunks, &cs_seq);
+
+out:
+ if (rc != -EAGAIN) {
+ memset(args, 0, sizeof(*args));
+ args->out.status = rc;
+ args->out.seq = cs_seq;
+ }
+
+ if (((rc == -ETIMEDOUT) || (rc == -EBUSY)) && (need_soft_reset))
+ hl_device_reset(hdev, false, false);
+
+ return rc;
+}
+
+static long _hl_cs_wait_ioctl(struct hl_device *hdev,
+ struct hl_ctx *ctx, u64 timeout_us, u64 seq)
+{
+ struct dma_fence *fence;
+ unsigned long timeout;
+ long rc;
+
+ if (timeout_us == MAX_SCHEDULE_TIMEOUT)
+ timeout = timeout_us;
+ else
+ timeout = usecs_to_jiffies(timeout_us);
+
+ hl_ctx_get(hdev, ctx);
+
+ fence = hl_ctx_get_fence(ctx, seq);
+ if (IS_ERR(fence)) {
+ rc = PTR_ERR(fence);
+ } else if (fence) {
+ rc = dma_fence_wait_timeout(fence, true, timeout);
+ if (fence->error == -ETIMEDOUT)
+ rc = -ETIMEDOUT;
+ else if (fence->error == -EIO)
+ rc = -EIO;
+ dma_fence_put(fence);
+ } else
+ rc = 1;
+
+ hl_ctx_put(ctx);
+
+ return rc;
+}
+
+int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
+{
+ struct hl_device *hdev = hpriv->hdev;
+ union hl_wait_cs_args *args = data;
+ u64 seq = args->in.seq;
+ long rc;
+
+ rc = _hl_cs_wait_ioctl(hdev, hpriv->ctx, args->in.timeout_us, seq);
+
+ memset(args, 0, sizeof(*args));
+
+ if (rc < 0) {
+ dev_err(hdev->dev, "Error %ld on waiting for CS handle %llu\n",
+ rc, seq);
+ if (rc == -ERESTARTSYS) {
+ args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED;
+ rc = -EINTR;
+ } else if (rc == -ETIMEDOUT) {
+ args->out.status = HL_WAIT_CS_STATUS_TIMEDOUT;
+ } else if (rc == -EIO) {
+ args->out.status = HL_WAIT_CS_STATUS_ABORTED;
+ }
+ return rc;
+ }
+
+ if (rc == 0)
+ args->out.status = HL_WAIT_CS_STATUS_BUSY;
+ else
+ args->out.status = HL_WAIT_CS_STATUS_COMPLETED;
+
+ return 0;
+}
diff --git a/drivers/misc/habanalabs/context.c b/drivers/misc/habanalabs/context.c
new file mode 100644
index 000000000000..619ace1c4ef7
--- /dev/null
+++ b/drivers/misc/habanalabs/context.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/slab.h>
+
+static void hl_ctx_fini(struct hl_ctx *ctx)
+{
+ struct hl_device *hdev = ctx->hdev;
+ int i;
+
+ /*
+ * If we arrived here, there are no jobs waiting for this context
+ * on its queues so we can safely remove it.
+ * This is because for each CS, we increment the ref count and for
+ * every CS that was finished we decrement it and we won't arrive
+ * to this function unless the ref count is 0
+ */
+
+ for (i = 0 ; i < HL_MAX_PENDING_CS ; i++)
+ dma_fence_put(ctx->cs_pending[i]);
+
+ if (ctx->asid != HL_KERNEL_ASID_ID) {
+ hl_vm_ctx_fini(ctx);
+ hl_asid_free(hdev, ctx->asid);
+ }
+}
+
+void hl_ctx_do_release(struct kref *ref)
+{
+ struct hl_ctx *ctx;
+
+ ctx = container_of(ref, struct hl_ctx, refcount);
+
+ hl_ctx_fini(ctx);
+
+ if (ctx->hpriv)
+ hl_hpriv_put(ctx->hpriv);
+
+ kfree(ctx);
+}
+
+int hl_ctx_create(struct hl_device *hdev, struct hl_fpriv *hpriv)
+{
+ struct hl_ctx_mgr *mgr = &hpriv->ctx_mgr;
+ struct hl_ctx *ctx;
+ int rc;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ rc = hl_ctx_init(hdev, ctx, false);
+ if (rc)
+ goto free_ctx;
+
+ hl_hpriv_get(hpriv);
+ ctx->hpriv = hpriv;
+
+ /* TODO: remove for multiple contexts */
+ hpriv->ctx = ctx;
+ hdev->user_ctx = ctx;
+
+ mutex_lock(&mgr->ctx_lock);
+ rc = idr_alloc(&mgr->ctx_handles, ctx, 1, 0, GFP_KERNEL);
+ mutex_unlock(&mgr->ctx_lock);
+
+ if (rc < 0) {
+ dev_err(hdev->dev, "Failed to allocate IDR for a new CTX\n");
+ hl_ctx_free(hdev, ctx);
+ goto out_err;
+ }
+
+ return 0;
+
+free_ctx:
+ kfree(ctx);
+out_err:
+ return rc;
+}
+
+void hl_ctx_free(struct hl_device *hdev, struct hl_ctx *ctx)
+{
+ if (kref_put(&ctx->refcount, hl_ctx_do_release) == 1)
+ return;
+
+ dev_warn(hdev->dev,
+ "Context %d closed or terminated but its CS are executing\n",
+ ctx->asid);
+}
+
+int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
+{
+ int rc = 0;
+
+ ctx->hdev = hdev;
+
+ kref_init(&ctx->refcount);
+
+ ctx->cs_sequence = 1;
+ spin_lock_init(&ctx->cs_lock);
+ atomic_set(&ctx->thread_restore_token, 1);
+ ctx->thread_restore_wait_token = 0;
+
+ if (is_kernel_ctx) {
+ ctx->asid = HL_KERNEL_ASID_ID; /* KMD gets ASID 0 */
+ } else {
+ ctx->asid = hl_asid_alloc(hdev);
+ if (!ctx->asid) {
+ dev_err(hdev->dev, "No free ASID, failed to create context\n");
+ return -ENOMEM;
+ }
+
+ rc = hl_vm_ctx_init(ctx);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to init mem ctx module\n");
+ rc = -ENOMEM;
+ goto mem_ctx_err;
+ }
+ }
+
+ return 0;
+
+mem_ctx_err:
+ if (ctx->asid != HL_KERNEL_ASID_ID)
+ hl_asid_free(hdev, ctx->asid);
+
+ return rc;
+}
+
+void hl_ctx_get(struct hl_device *hdev, struct hl_ctx *ctx)
+{
+ kref_get(&ctx->refcount);
+}
+
+int hl_ctx_put(struct hl_ctx *ctx)
+{
+ return kref_put(&ctx->refcount, hl_ctx_do_release);
+}
+
+struct dma_fence *hl_ctx_get_fence(struct hl_ctx *ctx, u64 seq)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct dma_fence *fence;
+
+ spin_lock(&ctx->cs_lock);
+
+ if (seq >= ctx->cs_sequence) {
+ dev_notice(hdev->dev,
+ "Can't wait on seq %llu because current CS is at seq %llu\n",
+ seq, ctx->cs_sequence);
+ spin_unlock(&ctx->cs_lock);
+ return ERR_PTR(-EINVAL);
+ }
+
+
+ if (seq + HL_MAX_PENDING_CS < ctx->cs_sequence) {
+ dev_dbg(hdev->dev,
+ "Can't wait on seq %llu because current CS is at seq %llu (Fence is gone)\n",
+ seq, ctx->cs_sequence);
+ spin_unlock(&ctx->cs_lock);
+ return NULL;
+ }
+
+ fence = dma_fence_get(
+ ctx->cs_pending[seq & (HL_MAX_PENDING_CS - 1)]);
+ spin_unlock(&ctx->cs_lock);
+
+ return fence;
+}
+
+/*
+ * hl_ctx_mgr_init - initialize the context manager
+ *
+ * @mgr: pointer to context manager structure
+ *
+ * This manager is an object inside the hpriv object of the user process.
+ * The function is called when a user process opens the FD.
+ */
+void hl_ctx_mgr_init(struct hl_ctx_mgr *mgr)
+{
+ mutex_init(&mgr->ctx_lock);
+ idr_init(&mgr->ctx_handles);
+}
+
+/*
+ * hl_ctx_mgr_fini - finalize the context manager
+ *
+ * @hdev: pointer to device structure
+ * @mgr: pointer to context manager structure
+ *
+ * This function goes over all the contexts in the manager and frees them.
+ * It is called when a process closes the FD.
+ */
+void hl_ctx_mgr_fini(struct hl_device *hdev, struct hl_ctx_mgr *mgr)
+{
+ struct hl_ctx *ctx;
+ struct idr *idp;
+ u32 id;
+
+ idp = &mgr->ctx_handles;
+
+ idr_for_each_entry(idp, ctx, id)
+ hl_ctx_free(hdev, ctx);
+
+ idr_destroy(&mgr->ctx_handles);
+ mutex_destroy(&mgr->ctx_lock);
+}
diff --git a/drivers/misc/habanalabs/debugfs.c b/drivers/misc/habanalabs/debugfs.c
new file mode 100644
index 000000000000..a53c12aff6ad
--- /dev/null
+++ b/drivers/misc/habanalabs/debugfs.c
@@ -0,0 +1,1077 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+#include "include/hw_ip/mmu/mmu_general.h"
+
+#include <linux/pci.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#define MMU_ADDR_BUF_SIZE 40
+#define MMU_ASID_BUF_SIZE 10
+#define MMU_KBUF_SIZE (MMU_ADDR_BUF_SIZE + MMU_ASID_BUF_SIZE)
+
+static struct dentry *hl_debug_root;
+
+static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
+ u8 i2c_reg, u32 *val)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -EBUSY;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_I2C_RD <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.i2c_bus = i2c_bus;
+ pkt.i2c_addr = i2c_addr;
+ pkt.i2c_reg = i2c_reg;
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ HL_DEVICE_TIMEOUT_USEC, (long *) val);
+
+ if (rc)
+ dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);
+
+ return rc;
+}
+
+static int hl_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
+ u8 i2c_reg, u32 val)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -EBUSY;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_I2C_WR <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.i2c_bus = i2c_bus;
+ pkt.i2c_addr = i2c_addr;
+ pkt.i2c_reg = i2c_reg;
+ pkt.value = __cpu_to_le64(val);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ HL_DEVICE_TIMEOUT_USEC, NULL);
+
+ if (rc)
+ dev_err(hdev->dev, "Failed to write to I2C, error %d\n", rc);
+
+ return rc;
+}
+
+static void hl_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_LED_SET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.led_index = __cpu_to_le32(led);
+ pkt.value = __cpu_to_le64(state);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ HL_DEVICE_TIMEOUT_USEC, NULL);
+
+ if (rc)
+ dev_err(hdev->dev, "Failed to set LED %d, error %d\n", led, rc);
+}
+
+static int command_buffers_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_cb *cb;
+ bool first = true;
+
+ spin_lock(&dev_entry->cb_spinlock);
+
+ list_for_each_entry(cb, &dev_entry->cb_list, debugfs_list) {
+ if (first) {
+ first = false;
+ seq_puts(s, "\n");
+ seq_puts(s, " CB ID CTX ID CB size CB RefCnt mmap? CS counter\n");
+ seq_puts(s, "---------------------------------------------------------------\n");
+ }
+ seq_printf(s,
+ " %03d %d 0x%08x %d %d %d\n",
+ cb->id, cb->ctx_id, cb->size,
+ kref_read(&cb->refcount),
+ cb->mmap, cb->cs_cnt);
+ }
+
+ spin_unlock(&dev_entry->cb_spinlock);
+
+ if (!first)
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+static int command_submission_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_cs *cs;
+ bool first = true;
+
+ spin_lock(&dev_entry->cs_spinlock);
+
+ list_for_each_entry(cs, &dev_entry->cs_list, debugfs_list) {
+ if (first) {
+ first = false;
+ seq_puts(s, "\n");
+ seq_puts(s, " CS ID CTX ASID CS RefCnt Submitted Completed\n");
+ seq_puts(s, "------------------------------------------------------\n");
+ }
+ seq_printf(s,
+ " %llu %d %d %d %d\n",
+ cs->sequence, cs->ctx->asid,
+ kref_read(&cs->refcount),
+ cs->submitted, cs->completed);
+ }
+
+ spin_unlock(&dev_entry->cs_spinlock);
+
+ if (!first)
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+static int command_submission_jobs_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_cs_job *job;
+ bool first = true;
+
+ spin_lock(&dev_entry->cs_job_spinlock);
+
+ list_for_each_entry(job, &dev_entry->cs_job_list, debugfs_list) {
+ if (first) {
+ first = false;
+ seq_puts(s, "\n");
+ seq_puts(s, " JOB ID CS ID CTX ASID H/W Queue\n");
+ seq_puts(s, "---------------------------------------\n");
+ }
+ if (job->cs)
+ seq_printf(s,
+ " %02d %llu %d %d\n",
+ job->id, job->cs->sequence, job->cs->ctx->asid,
+ job->hw_queue_id);
+ else
+ seq_printf(s,
+ " %02d 0 %d %d\n",
+ job->id, HL_KERNEL_ASID_ID, job->hw_queue_id);
+ }
+
+ spin_unlock(&dev_entry->cs_job_spinlock);
+
+ if (!first)
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+static int userptr_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_userptr *userptr;
+ char dma_dir[4][30] = {"DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
+ "DMA_FROM_DEVICE", "DMA_NONE"};
+ bool first = true;
+
+ spin_lock(&dev_entry->userptr_spinlock);
+
+ list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) {
+ if (first) {
+ first = false;
+ seq_puts(s, "\n");
+ seq_puts(s, " user virtual address size dma dir\n");
+ seq_puts(s, "----------------------------------------------------------\n");
+ }
+ seq_printf(s,
+ " 0x%-14llx %-10u %-30s\n",
+ userptr->addr, userptr->size, dma_dir[userptr->dir]);
+ }
+
+ spin_unlock(&dev_entry->userptr_spinlock);
+
+ if (!first)
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+static int vm_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_ctx *ctx;
+ struct hl_vm *vm;
+ struct hl_vm_hash_node *hnode;
+ struct hl_userptr *userptr;
+ struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
+ enum vm_type_t *vm_type;
+ bool once = true;
+ int i;
+
+ if (!dev_entry->hdev->mmu_enable)
+ return 0;
+
+ spin_lock(&dev_entry->ctx_mem_hash_spinlock);
+
+ list_for_each_entry(ctx, &dev_entry->ctx_mem_hash_list, debugfs_list) {
+ once = false;
+ seq_puts(s, "\n\n----------------------------------------------------");
+ seq_puts(s, "\n----------------------------------------------------\n\n");
+ seq_printf(s, "ctx asid: %u\n", ctx->asid);
+
+ seq_puts(s, "\nmappings:\n\n");
+ seq_puts(s, " virtual address size handle\n");
+ seq_puts(s, "----------------------------------------------------\n");
+ mutex_lock(&ctx->mem_hash_lock);
+ hash_for_each(ctx->mem_hash, i, hnode, node) {
+ vm_type = hnode->ptr;
+
+ if (*vm_type == VM_TYPE_USERPTR) {
+ userptr = hnode->ptr;
+ seq_printf(s,
+ " 0x%-14llx %-10u\n",
+ hnode->vaddr, userptr->size);
+ } else {
+ phys_pg_pack = hnode->ptr;
+ seq_printf(s,
+ " 0x%-14llx %-10u %-4u\n",
+ hnode->vaddr, phys_pg_pack->total_size,
+ phys_pg_pack->handle);
+ }
+ }
+ mutex_unlock(&ctx->mem_hash_lock);
+
+ vm = &ctx->hdev->vm;
+ spin_lock(&vm->idr_lock);
+
+ if (!idr_is_empty(&vm->phys_pg_pack_handles))
+ seq_puts(s, "\n\nallocations:\n");
+
+ idr_for_each_entry(&vm->phys_pg_pack_handles, phys_pg_pack, i) {
+ if (phys_pg_pack->asid != ctx->asid)
+ continue;
+
+ seq_printf(s, "\nhandle: %u\n", phys_pg_pack->handle);
+ seq_printf(s, "page size: %u\n\n",
+ phys_pg_pack->page_size);
+ seq_puts(s, " physical address\n");
+ seq_puts(s, "---------------------\n");
+ for (i = 0 ; i < phys_pg_pack->npages ; i++) {
+ seq_printf(s, " 0x%-14llx\n",
+ phys_pg_pack->pages[i]);
+ }
+ }
+ spin_unlock(&vm->idr_lock);
+
+ }
+
+ spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
+
+ if (!once)
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+/* these inline functions are copied from mmu.c */
+static inline u64 get_hop0_addr(struct hl_ctx *ctx)
+{
+ return ctx->hdev->asic_prop.mmu_pgt_addr +
+ (ctx->asid * ctx->hdev->asic_prop.mmu_hop_table_size);
+}
+
+static inline u64 get_hop0_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & HOP0_MASK) >> HOP0_SHIFT);
+}
+
+static inline u64 get_hop1_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & HOP1_MASK) >> HOP1_SHIFT);
+}
+
+static inline u64 get_hop2_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & HOP2_MASK) >> HOP2_SHIFT);
+}
+
+static inline u64 get_hop3_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & HOP3_MASK) >> HOP3_SHIFT);
+}
+
+static inline u64 get_hop4_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & HOP4_MASK) >> HOP4_SHIFT);
+}
+
+static inline u64 get_next_hop_addr(u64 curr_pte)
+{
+ if (curr_pte & PAGE_PRESENT_MASK)
+ return curr_pte & PHYS_ADDR_MASK;
+ else
+ return ULLONG_MAX;
+}
+
+static int mmu_show(struct seq_file *s, void *data)
+{
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_device *hdev = dev_entry->hdev;
+ struct hl_ctx *ctx = hdev->user_ctx;
+
+ u64 hop0_addr = 0, hop0_pte_addr = 0, hop0_pte = 0,
+ hop1_addr = 0, hop1_pte_addr = 0, hop1_pte = 0,
+ hop2_addr = 0, hop2_pte_addr = 0, hop2_pte = 0,
+ hop3_addr = 0, hop3_pte_addr = 0, hop3_pte = 0,
+ hop4_addr = 0, hop4_pte_addr = 0, hop4_pte = 0,
+ virt_addr = dev_entry->mmu_addr;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ if (!ctx) {
+ dev_err(hdev->dev, "no ctx available\n");
+ return 0;
+ }
+
+ mutex_lock(&ctx->mmu_lock);
+
+ /* the following lookup is copied from unmap() in mmu.c */
+
+ hop0_addr = get_hop0_addr(ctx);
+ hop0_pte_addr = get_hop0_pte_addr(ctx, hop0_addr, virt_addr);
+ hop0_pte = hdev->asic_funcs->read_pte(hdev, hop0_pte_addr);
+ hop1_addr = get_next_hop_addr(hop0_pte);
+
+ if (hop1_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop1_pte_addr = get_hop1_pte_addr(ctx, hop1_addr, virt_addr);
+ hop1_pte = hdev->asic_funcs->read_pte(hdev, hop1_pte_addr);
+ hop2_addr = get_next_hop_addr(hop1_pte);
+
+ if (hop2_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop2_pte_addr = get_hop2_pte_addr(ctx, hop2_addr, virt_addr);
+ hop2_pte = hdev->asic_funcs->read_pte(hdev, hop2_pte_addr);
+ hop3_addr = get_next_hop_addr(hop2_pte);
+
+ if (hop3_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop3_pte_addr = get_hop3_pte_addr(ctx, hop3_addr, virt_addr);
+ hop3_pte = hdev->asic_funcs->read_pte(hdev, hop3_pte_addr);
+
+ if (!(hop3_pte & LAST_MASK)) {
+ hop4_addr = get_next_hop_addr(hop3_pte);
+
+ if (hop4_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop4_pte_addr = get_hop4_pte_addr(ctx, hop4_addr, virt_addr);
+ hop4_pte = hdev->asic_funcs->read_pte(hdev, hop4_pte_addr);
+ if (!(hop4_pte & PAGE_PRESENT_MASK))
+ goto not_mapped;
+ } else {
+ if (!(hop3_pte & PAGE_PRESENT_MASK))
+ goto not_mapped;
+ }
+
+ seq_printf(s, "asid: %u, virt_addr: 0x%llx\n",
+ dev_entry->mmu_asid, dev_entry->mmu_addr);
+
+ seq_printf(s, "hop0_addr: 0x%llx\n", hop0_addr);
+ seq_printf(s, "hop0_pte_addr: 0x%llx\n", hop0_pte_addr);
+ seq_printf(s, "hop0_pte: 0x%llx\n", hop0_pte);
+
+ seq_printf(s, "hop1_addr: 0x%llx\n", hop1_addr);
+ seq_printf(s, "hop1_pte_addr: 0x%llx\n", hop1_pte_addr);
+ seq_printf(s, "hop1_pte: 0x%llx\n", hop1_pte);
+
+ seq_printf(s, "hop2_addr: 0x%llx\n", hop2_addr);
+ seq_printf(s, "hop2_pte_addr: 0x%llx\n", hop2_pte_addr);
+ seq_printf(s, "hop2_pte: 0x%llx\n", hop2_pte);
+
+ seq_printf(s, "hop3_addr: 0x%llx\n", hop3_addr);
+ seq_printf(s, "hop3_pte_addr: 0x%llx\n", hop3_pte_addr);
+ seq_printf(s, "hop3_pte: 0x%llx\n", hop3_pte);
+
+ if (!(hop3_pte & LAST_MASK)) {
+ seq_printf(s, "hop4_addr: 0x%llx\n", hop4_addr);
+ seq_printf(s, "hop4_pte_addr: 0x%llx\n", hop4_pte_addr);
+ seq_printf(s, "hop4_pte: 0x%llx\n", hop4_pte);
+ }
+
+ goto out;
+
+not_mapped:
+ dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n",
+ virt_addr);
+out:
+ mutex_unlock(&ctx->mmu_lock);
+
+ return 0;
+}
+
+static ssize_t mmu_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct seq_file *s = file->private_data;
+ struct hl_debugfs_entry *entry = s->private;
+ struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
+ struct hl_device *hdev = dev_entry->hdev;
+ char kbuf[MMU_KBUF_SIZE], asid_kbuf[MMU_ASID_BUF_SIZE],
+ addr_kbuf[MMU_ADDR_BUF_SIZE];
+ char *c;
+ ssize_t rc;
+
+ if (!hdev->mmu_enable)
+ return count;
+
+ memset(kbuf, 0, sizeof(kbuf));
+ memset(asid_kbuf, 0, sizeof(asid_kbuf));
+ memset(addr_kbuf, 0, sizeof(addr_kbuf));
+
+ if (copy_from_user(kbuf, buf, count))
+ goto err;
+
+ kbuf[MMU_KBUF_SIZE - 1] = 0;
+
+ c = strchr(kbuf, ' ');
+ if (!c)
+ goto err;
+
+ memcpy(asid_kbuf, kbuf, c - kbuf);
+
+ rc = kstrtouint(asid_kbuf, 10, &dev_entry->mmu_asid);
+ if (rc)
+ goto err;
+
+ c = strstr(kbuf, " 0x");
+ if (!c)
+ goto err;
+
+ c += 3;
+ memcpy(addr_kbuf, c, (kbuf + count) - c);
+
+ rc = kstrtoull(addr_kbuf, 16, &dev_entry->mmu_addr);
+ if (rc)
+ goto err;
+
+ return count;
+
+err:
+ dev_err(hdev->dev, "usage: echo <asid> <0xaddr> > mmu\n");
+
+ return -EINVAL;
+}
+
+static ssize_t hl_data_read32(struct file *f, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ char tmp_buf[32];
+ u32 val;
+ ssize_t rc;
+
+ if (*ppos)
+ return 0;
+
+ rc = hdev->asic_funcs->debugfs_read32(hdev, entry->addr, &val);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to read from 0x%010llx\n",
+ entry->addr);
+ return rc;
+ }
+
+ sprintf(tmp_buf, "0x%08x\n", val);
+ rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
+ strlen(tmp_buf) + 1);
+
+ return rc;
+}
+
+static ssize_t hl_data_write32(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 16, &value);
+ if (rc)
+ return rc;
+
+ rc = hdev->asic_funcs->debugfs_write32(hdev, entry->addr, value);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to write 0x%08x to 0x%010llx\n",
+ value, entry->addr);
+ return rc;
+ }
+
+ return count;
+}
+
+static ssize_t hl_get_power_state(struct file *f, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ char tmp_buf[200];
+ ssize_t rc;
+ int i;
+
+ if (*ppos)
+ return 0;
+
+ if (hdev->pdev->current_state == PCI_D0)
+ i = 1;
+ else if (hdev->pdev->current_state == PCI_D3hot)
+ i = 2;
+ else
+ i = 3;
+
+ sprintf(tmp_buf,
+ "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i);
+ rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
+ strlen(tmp_buf) + 1);
+
+ return rc;
+}
+
+static ssize_t hl_set_power_state(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 10, &value);
+ if (rc)
+ return rc;
+
+ if (value == 1) {
+ pci_set_power_state(hdev->pdev, PCI_D0);
+ pci_restore_state(hdev->pdev);
+ rc = pci_enable_device(hdev->pdev);
+ } else if (value == 2) {
+ pci_save_state(hdev->pdev);
+ pci_disable_device(hdev->pdev);
+ pci_set_power_state(hdev->pdev, PCI_D3hot);
+ } else {
+ dev_dbg(hdev->dev, "invalid power state value %u\n", value);
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ char tmp_buf[32];
+ u32 val;
+ ssize_t rc;
+
+ if (*ppos)
+ return 0;
+
+ rc = hl_debugfs_i2c_read(hdev, entry->i2c_bus, entry->i2c_addr,
+ entry->i2c_reg, &val);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to read from I2C bus %d, addr %d, reg %d\n",
+ entry->i2c_bus, entry->i2c_addr, entry->i2c_reg);
+ return rc;
+ }
+
+ sprintf(tmp_buf, "0x%02x\n", val);
+ rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
+ strlen(tmp_buf) + 1);
+
+ return rc;
+}
+
+static ssize_t hl_i2c_data_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 16, &value);
+ if (rc)
+ return rc;
+
+ rc = hl_debugfs_i2c_write(hdev, entry->i2c_bus, entry->i2c_addr,
+ entry->i2c_reg, value);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to write 0x%02x to I2C bus %d, addr %d, reg %d\n",
+ value, entry->i2c_bus, entry->i2c_addr, entry->i2c_reg);
+ return rc;
+ }
+
+ return count;
+}
+
+static ssize_t hl_led0_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 10, &value);
+ if (rc)
+ return rc;
+
+ value = value ? 1 : 0;
+
+ hl_debugfs_led_set(hdev, 0, value);
+
+ return count;
+}
+
+static ssize_t hl_led1_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 10, &value);
+ if (rc)
+ return rc;
+
+ value = value ? 1 : 0;
+
+ hl_debugfs_led_set(hdev, 1, value);
+
+ return count;
+}
+
+static ssize_t hl_led2_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ u32 value;
+ ssize_t rc;
+
+ rc = kstrtouint_from_user(buf, count, 10, &value);
+ if (rc)
+ return rc;
+
+ value = value ? 1 : 0;
+
+ hl_debugfs_led_set(hdev, 2, value);
+
+ return count;
+}
+
+static ssize_t hl_device_read(struct file *f, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmp_buf[200];
+ ssize_t rc;
+
+ if (*ppos)
+ return 0;
+
+ sprintf(tmp_buf,
+ "Valid values: disable, enable, suspend, resume, cpu_timeout\n");
+ rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
+ strlen(tmp_buf) + 1);
+
+ return rc;
+}
+
+static ssize_t hl_device_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
+ struct hl_device *hdev = entry->hdev;
+ char data[30];
+
+ /* don't allow partial writes */
+ if (*ppos != 0)
+ return 0;
+
+ simple_write_to_buffer(data, 29, ppos, buf, count);
+
+ if (strncmp("disable", data, strlen("disable")) == 0) {
+ hdev->disabled = true;
+ } else if (strncmp("enable", data, strlen("enable")) == 0) {
+ hdev->disabled = false;
+ } else if (strncmp("suspend", data, strlen("suspend")) == 0) {
+ hdev->asic_funcs->suspend(hdev);
+ } else if (strncmp("resume", data, strlen("resume")) == 0) {
+ hdev->asic_funcs->resume(hdev);
+ } else if (strncmp("cpu_timeout", data, strlen("cpu_timeout")) == 0) {
+ hdev->device_cpu_disabled = true;
+ } else {
+ dev_err(hdev->dev,
+ "Valid values: disable, enable, suspend, resume, cpu_timeout\n");
+ count = -EINVAL;
+ }
+
+ return count;
+}
+
+static const struct file_operations hl_data32b_fops = {
+ .owner = THIS_MODULE,
+ .read = hl_data_read32,
+ .write = hl_data_write32
+};
+
+static const struct file_operations hl_i2c_data_fops = {
+ .owner = THIS_MODULE,
+ .read = hl_i2c_data_read,
+ .write = hl_i2c_data_write
+};
+
+static const struct file_operations hl_power_fops = {
+ .owner = THIS_MODULE,
+ .read = hl_get_power_state,
+ .write = hl_set_power_state
+};
+
+static const struct file_operations hl_led0_fops = {
+ .owner = THIS_MODULE,
+ .write = hl_led0_write
+};
+
+static const struct file_operations hl_led1_fops = {
+ .owner = THIS_MODULE,
+ .write = hl_led1_write
+};
+
+static const struct file_operations hl_led2_fops = {
+ .owner = THIS_MODULE,
+ .write = hl_led2_write
+};
+
+static const struct file_operations hl_device_fops = {
+ .owner = THIS_MODULE,
+ .read = hl_device_read,
+ .write = hl_device_write
+};
+
+static const struct hl_info_list hl_debugfs_list[] = {
+ {"command_buffers", command_buffers_show, NULL},
+ {"command_submission", command_submission_show, NULL},
+ {"command_submission_jobs", command_submission_jobs_show, NULL},
+ {"userptr", userptr_show, NULL},
+ {"vm", vm_show, NULL},
+ {"mmu", mmu_show, mmu_write},
+};
+
+static int hl_debugfs_open(struct inode *inode, struct file *file)
+{
+ struct hl_debugfs_entry *node = inode->i_private;
+
+ return single_open(file, node->info_ent->show, node);
+}
+
+static ssize_t hl_debugfs_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct hl_debugfs_entry *node = file->f_inode->i_private;
+
+ if (node->info_ent->write)
+ return node->info_ent->write(file, buf, count, f_pos);
+ else
+ return -EINVAL;
+
+}
+
+static const struct file_operations hl_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = hl_debugfs_open,
+ .read = seq_read,
+ .write = hl_debugfs_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void hl_debugfs_add_device(struct hl_device *hdev)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+ int count = ARRAY_SIZE(hl_debugfs_list);
+ struct hl_debugfs_entry *entry;
+ struct dentry *ent;
+ int i;
+
+ dev_entry->hdev = hdev;
+ dev_entry->entry_arr = kmalloc_array(count,
+ sizeof(struct hl_debugfs_entry),
+ GFP_KERNEL);
+ if (!dev_entry->entry_arr)
+ return;
+
+ INIT_LIST_HEAD(&dev_entry->file_list);
+ INIT_LIST_HEAD(&dev_entry->cb_list);
+ INIT_LIST_HEAD(&dev_entry->cs_list);
+ INIT_LIST_HEAD(&dev_entry->cs_job_list);
+ INIT_LIST_HEAD(&dev_entry->userptr_list);
+ INIT_LIST_HEAD(&dev_entry->ctx_mem_hash_list);
+ mutex_init(&dev_entry->file_mutex);
+ spin_lock_init(&dev_entry->cb_spinlock);
+ spin_lock_init(&dev_entry->cs_spinlock);
+ spin_lock_init(&dev_entry->cs_job_spinlock);
+ spin_lock_init(&dev_entry->userptr_spinlock);
+ spin_lock_init(&dev_entry->ctx_mem_hash_spinlock);
+
+ dev_entry->root = debugfs_create_dir(dev_name(hdev->dev),
+ hl_debug_root);
+
+ debugfs_create_x64("addr",
+ 0644,
+ dev_entry->root,
+ &dev_entry->addr);
+
+ debugfs_create_file("data32",
+ 0644,
+ dev_entry->root,
+ dev_entry,
+ &hl_data32b_fops);
+
+ debugfs_create_file("set_power_state",
+ 0200,
+ dev_entry->root,
+ dev_entry,
+ &hl_power_fops);
+
+ debugfs_create_u8("i2c_bus",
+ 0644,
+ dev_entry->root,
+ &dev_entry->i2c_bus);
+
+ debugfs_create_u8("i2c_addr",
+ 0644,
+ dev_entry->root,
+ &dev_entry->i2c_addr);
+
+ debugfs_create_u8("i2c_reg",
+ 0644,
+ dev_entry->root,
+ &dev_entry->i2c_reg);
+
+ debugfs_create_file("i2c_data",
+ 0644,
+ dev_entry->root,
+ dev_entry,
+ &hl_i2c_data_fops);
+
+ debugfs_create_file("led0",
+ 0200,
+ dev_entry->root,
+ dev_entry,
+ &hl_led0_fops);
+
+ debugfs_create_file("led1",
+ 0200,
+ dev_entry->root,
+ dev_entry,
+ &hl_led1_fops);
+
+ debugfs_create_file("led2",
+ 0200,
+ dev_entry->root,
+ dev_entry,
+ &hl_led2_fops);
+
+ debugfs_create_file("device",
+ 0200,
+ dev_entry->root,
+ dev_entry,
+ &hl_device_fops);
+
+ for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
+
+ ent = debugfs_create_file(hl_debugfs_list[i].name,
+ 0444,
+ dev_entry->root,
+ entry,
+ &hl_debugfs_fops);
+ entry->dent = ent;
+ entry->info_ent = &hl_debugfs_list[i];
+ entry->dev_entry = dev_entry;
+ }
+}
+
+void hl_debugfs_remove_device(struct hl_device *hdev)
+{
+ struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;
+
+ debugfs_remove_recursive(entry->root);
+
+ mutex_destroy(&entry->file_mutex);
+ kfree(entry->entry_arr);
+}
+
+void hl_debugfs_add_file(struct hl_fpriv *hpriv)
+{
+ struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
+
+ mutex_lock(&dev_entry->file_mutex);
+ list_add(&hpriv->debugfs_list, &dev_entry->file_list);
+ mutex_unlock(&dev_entry->file_mutex);
+}
+
+void hl_debugfs_remove_file(struct hl_fpriv *hpriv)
+{
+ struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
+
+ mutex_lock(&dev_entry->file_mutex);
+ list_del(&hpriv->debugfs_list);
+ mutex_unlock(&dev_entry->file_mutex);
+}
+
+void hl_debugfs_add_cb(struct hl_cb *cb)
+{
+ struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cb_spinlock);
+ list_add(&cb->debugfs_list, &dev_entry->cb_list);
+ spin_unlock(&dev_entry->cb_spinlock);
+}
+
+void hl_debugfs_remove_cb(struct hl_cb *cb)
+{
+ struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cb_spinlock);
+ list_del(&cb->debugfs_list);
+ spin_unlock(&dev_entry->cb_spinlock);
+}
+
+void hl_debugfs_add_cs(struct hl_cs *cs)
+{
+ struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cs_spinlock);
+ list_add(&cs->debugfs_list, &dev_entry->cs_list);
+ spin_unlock(&dev_entry->cs_spinlock);
+}
+
+void hl_debugfs_remove_cs(struct hl_cs *cs)
+{
+ struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cs_spinlock);
+ list_del(&cs->debugfs_list);
+ spin_unlock(&dev_entry->cs_spinlock);
+}
+
+void hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cs_job_spinlock);
+ list_add(&job->debugfs_list, &dev_entry->cs_job_list);
+ spin_unlock(&dev_entry->cs_job_spinlock);
+}
+
+void hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->cs_job_spinlock);
+ list_del(&job->debugfs_list);
+ spin_unlock(&dev_entry->cs_job_spinlock);
+}
+
+void hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->userptr_spinlock);
+ list_add(&userptr->debugfs_list, &dev_entry->userptr_list);
+ spin_unlock(&dev_entry->userptr_spinlock);
+}
+
+void hl_debugfs_remove_userptr(struct hl_device *hdev,
+ struct hl_userptr *userptr)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->userptr_spinlock);
+ list_del(&userptr->debugfs_list);
+ spin_unlock(&dev_entry->userptr_spinlock);
+}
+
+void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->ctx_mem_hash_spinlock);
+ list_add(&ctx->debugfs_list, &dev_entry->ctx_mem_hash_list);
+ spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
+}
+
+void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ spin_lock(&dev_entry->ctx_mem_hash_spinlock);
+ list_del(&ctx->debugfs_list);
+ spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
+}
+
+void __init hl_debugfs_init(void)
+{
+ hl_debug_root = debugfs_create_dir("habanalabs", NULL);
+}
+
+void hl_debugfs_fini(void)
+{
+ debugfs_remove_recursive(hl_debug_root);
+}
diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c
new file mode 100644
index 000000000000..de46aa6ed154
--- /dev/null
+++ b/drivers/misc/habanalabs/device.c
@@ -0,0 +1,1140 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/pci.h>
+#include <linux/sched/signal.h>
+#include <linux/hwmon.h>
+
+bool hl_device_disabled_or_in_reset(struct hl_device *hdev)
+{
+ if ((hdev->disabled) || (atomic_read(&hdev->in_reset)))
+ return true;
+ else
+ return false;
+}
+
+static void hpriv_release(struct kref *ref)
+{
+ struct hl_fpriv *hpriv;
+ struct hl_device *hdev;
+
+ hpriv = container_of(ref, struct hl_fpriv, refcount);
+
+ hdev = hpriv->hdev;
+
+ put_pid(hpriv->taskpid);
+
+ hl_debugfs_remove_file(hpriv);
+
+ mutex_destroy(&hpriv->restore_phase_mutex);
+
+ kfree(hpriv);
+
+ /* Now the FD is really closed */
+ atomic_dec(&hdev->fd_open_cnt);
+
+ /* This allows a new user context to open the device */
+ hdev->user_ctx = NULL;
+}
+
+void hl_hpriv_get(struct hl_fpriv *hpriv)
+{
+ kref_get(&hpriv->refcount);
+}
+
+void hl_hpriv_put(struct hl_fpriv *hpriv)
+{
+ kref_put(&hpriv->refcount, hpriv_release);
+}
+
+/*
+ * hl_device_release - release function for habanalabs device
+ *
+ * @inode: pointer to inode structure
+ * @filp: pointer to file structure
+ *
+ * Called when process closes an habanalabs device
+ */
+static int hl_device_release(struct inode *inode, struct file *filp)
+{
+ struct hl_fpriv *hpriv = filp->private_data;
+
+ hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
+ hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
+
+ filp->private_data = NULL;
+
+ hl_hpriv_put(hpriv);
+
+ return 0;
+}
+
+/*
+ * hl_mmap - mmap function for habanalabs device
+ *
+ * @*filp: pointer to file structure
+ * @*vma: pointer to vm_area_struct of the process
+ *
+ * Called when process does an mmap on habanalabs device. Call the device's mmap
+ * function at the end of the common code.
+ */
+static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct hl_fpriv *hpriv = filp->private_data;
+
+ if ((vma->vm_pgoff & HL_MMAP_CB_MASK) == HL_MMAP_CB_MASK) {
+ vma->vm_pgoff ^= HL_MMAP_CB_MASK;
+ return hl_cb_mmap(hpriv, vma);
+ }
+
+ return -EINVAL;
+}
+
+static const struct file_operations hl_ops = {
+ .owner = THIS_MODULE,
+ .open = hl_device_open,
+ .release = hl_device_release,
+ .mmap = hl_mmap,
+ .unlocked_ioctl = hl_ioctl,
+ .compat_ioctl = hl_ioctl
+};
+
+/*
+ * device_setup_cdev - setup cdev and device for habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @hclass: pointer to the class object of the device
+ * @minor: minor number of the specific device
+ * @fpos : file operations to install for this device
+ *
+ * Create a cdev and a Linux device for habanalabs's device. Need to be
+ * called at the end of the habanalabs device initialization process,
+ * because this function exposes the device to the user
+ */
+static int device_setup_cdev(struct hl_device *hdev, struct class *hclass,
+ int minor, const struct file_operations *fops)
+{
+ int err, devno = MKDEV(hdev->major, minor);
+ struct cdev *hdev_cdev = &hdev->cdev;
+ char *name;
+
+ name = kasprintf(GFP_KERNEL, "hl%d", hdev->id);
+ if (!name)
+ return -ENOMEM;
+
+ cdev_init(hdev_cdev, fops);
+ hdev_cdev->owner = THIS_MODULE;
+ err = cdev_add(hdev_cdev, devno, 1);
+ if (err) {
+ pr_err("Failed to add char device %s\n", name);
+ goto err_cdev_add;
+ }
+
+ hdev->dev = device_create(hclass, NULL, devno, NULL, "%s", name);
+ if (IS_ERR(hdev->dev)) {
+ pr_err("Failed to create device %s\n", name);
+ err = PTR_ERR(hdev->dev);
+ goto err_device_create;
+ }
+
+ dev_set_drvdata(hdev->dev, hdev);
+
+ kfree(name);
+
+ return 0;
+
+err_device_create:
+ cdev_del(hdev_cdev);
+err_cdev_add:
+ kfree(name);
+ return err;
+}
+
+/*
+ * device_early_init - do some early initialization for the habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Install the relevant function pointers and call the early_init function,
+ * if such a function exists
+ */
+static int device_early_init(struct hl_device *hdev)
+{
+ int rc;
+
+ switch (hdev->asic_type) {
+ case ASIC_GOYA:
+ goya_set_asic_funcs(hdev);
+ strlcpy(hdev->asic_name, "GOYA", sizeof(hdev->asic_name));
+ break;
+ default:
+ dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
+ hdev->asic_type);
+ return -EINVAL;
+ }
+
+ rc = hdev->asic_funcs->early_init(hdev);
+ if (rc)
+ return rc;
+
+ rc = hl_asid_init(hdev);
+ if (rc)
+ goto early_fini;
+
+ hdev->cq_wq = alloc_workqueue("hl-free-jobs", WQ_UNBOUND, 0);
+ if (hdev->cq_wq == NULL) {
+ dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
+ rc = -ENOMEM;
+ goto asid_fini;
+ }
+
+ hdev->eq_wq = alloc_workqueue("hl-events", WQ_UNBOUND, 0);
+ if (hdev->eq_wq == NULL) {
+ dev_err(hdev->dev, "Failed to allocate EQ workqueue\n");
+ rc = -ENOMEM;
+ goto free_cq_wq;
+ }
+
+ hdev->hl_chip_info = kzalloc(sizeof(struct hwmon_chip_info),
+ GFP_KERNEL);
+ if (!hdev->hl_chip_info) {
+ rc = -ENOMEM;
+ goto free_eq_wq;
+ }
+
+ hl_cb_mgr_init(&hdev->kernel_cb_mgr);
+
+ mutex_init(&hdev->fd_open_cnt_lock);
+ mutex_init(&hdev->send_cpu_message_lock);
+ INIT_LIST_HEAD(&hdev->hw_queues_mirror_list);
+ spin_lock_init(&hdev->hw_queues_mirror_lock);
+ atomic_set(&hdev->in_reset, 0);
+ atomic_set(&hdev->fd_open_cnt, 0);
+
+ return 0;
+
+free_eq_wq:
+ destroy_workqueue(hdev->eq_wq);
+free_cq_wq:
+ destroy_workqueue(hdev->cq_wq);
+asid_fini:
+ hl_asid_fini(hdev);
+early_fini:
+ if (hdev->asic_funcs->early_fini)
+ hdev->asic_funcs->early_fini(hdev);
+
+ return rc;
+}
+
+/*
+ * device_early_fini - finalize all that was done in device_early_init
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ */
+static void device_early_fini(struct hl_device *hdev)
+{
+ mutex_destroy(&hdev->send_cpu_message_lock);
+
+ hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr);
+
+ kfree(hdev->hl_chip_info);
+
+ destroy_workqueue(hdev->eq_wq);
+ destroy_workqueue(hdev->cq_wq);
+
+ hl_asid_fini(hdev);
+
+ if (hdev->asic_funcs->early_fini)
+ hdev->asic_funcs->early_fini(hdev);
+
+ mutex_destroy(&hdev->fd_open_cnt_lock);
+}
+
+static void set_freq_to_low_job(struct work_struct *work)
+{
+ struct hl_device *hdev = container_of(work, struct hl_device,
+ work_freq.work);
+
+ if (atomic_read(&hdev->fd_open_cnt) == 0)
+ hl_device_set_frequency(hdev, PLL_LOW);
+
+ schedule_delayed_work(&hdev->work_freq,
+ usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
+}
+
+static void hl_device_heartbeat(struct work_struct *work)
+{
+ struct hl_device *hdev = container_of(work, struct hl_device,
+ work_heartbeat.work);
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ goto reschedule;
+
+ if (!hdev->asic_funcs->send_heartbeat(hdev))
+ goto reschedule;
+
+ dev_err(hdev->dev, "Device heartbeat failed!\n");
+ hl_device_reset(hdev, true, false);
+
+ return;
+
+reschedule:
+ schedule_delayed_work(&hdev->work_heartbeat,
+ usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
+}
+
+/*
+ * device_late_init - do late stuff initialization for the habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Do stuff that either needs the device H/W queues to be active or needs
+ * to happen after all the rest of the initialization is finished
+ */
+static int device_late_init(struct hl_device *hdev)
+{
+ int rc;
+
+ INIT_DELAYED_WORK(&hdev->work_freq, set_freq_to_low_job);
+ hdev->high_pll = hdev->asic_prop.high_pll;
+
+ /* force setting to low frequency */
+ atomic_set(&hdev->curr_pll_profile, PLL_LOW);
+
+ if (hdev->pm_mng_profile == PM_AUTO)
+ hdev->asic_funcs->set_pll_profile(hdev, PLL_LOW);
+ else
+ hdev->asic_funcs->set_pll_profile(hdev, PLL_LAST);
+
+ if (hdev->asic_funcs->late_init) {
+ rc = hdev->asic_funcs->late_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed late initialization for the H/W\n");
+ return rc;
+ }
+ }
+
+ schedule_delayed_work(&hdev->work_freq,
+ usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
+
+ if (hdev->heartbeat) {
+ INIT_DELAYED_WORK(&hdev->work_heartbeat, hl_device_heartbeat);
+ schedule_delayed_work(&hdev->work_heartbeat,
+ usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
+ }
+
+ hdev->late_init_done = true;
+
+ return 0;
+}
+
+/*
+ * device_late_fini - finalize all that was done in device_late_init
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ */
+static void device_late_fini(struct hl_device *hdev)
+{
+ if (!hdev->late_init_done)
+ return;
+
+ cancel_delayed_work_sync(&hdev->work_freq);
+ if (hdev->heartbeat)
+ cancel_delayed_work_sync(&hdev->work_heartbeat);
+
+ if (hdev->asic_funcs->late_fini)
+ hdev->asic_funcs->late_fini(hdev);
+
+ hdev->late_init_done = false;
+}
+
+/*
+ * hl_device_set_frequency - set the frequency of the device
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @freq: the new frequency value
+ *
+ * Change the frequency if needed.
+ * We allose to set PLL to low only if there is no user process
+ * Returns 0 if no change was done, otherwise returns 1;
+ */
+int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq)
+{
+ enum hl_pll_frequency old_freq =
+ (freq == PLL_HIGH) ? PLL_LOW : PLL_HIGH;
+ int ret;
+
+ if (hdev->pm_mng_profile == PM_MANUAL)
+ return 0;
+
+ ret = atomic_cmpxchg(&hdev->curr_pll_profile, old_freq, freq);
+ if (ret == freq)
+ return 0;
+
+ /*
+ * in case we want to lower frequency, check if device is not
+ * opened. We must have a check here to workaround race condition with
+ * hl_device_open
+ */
+ if ((freq == PLL_LOW) && (atomic_read(&hdev->fd_open_cnt) > 0)) {
+ atomic_set(&hdev->curr_pll_profile, PLL_HIGH);
+ return 0;
+ }
+
+ dev_dbg(hdev->dev, "Changing device frequency to %s\n",
+ freq == PLL_HIGH ? "high" : "low");
+
+ hdev->asic_funcs->set_pll_profile(hdev, freq);
+
+ return 1;
+}
+
+/*
+ * hl_device_suspend - initiate device suspend
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Puts the hw in the suspend state (all asics).
+ * Returns 0 for success or an error on failure.
+ * Called at driver suspend.
+ */
+int hl_device_suspend(struct hl_device *hdev)
+{
+ int rc;
+
+ pci_save_state(hdev->pdev);
+
+ rc = hdev->asic_funcs->suspend(hdev);
+ if (rc)
+ dev_err(hdev->dev,
+ "Failed to disable PCI access of device CPU\n");
+
+ /* Shut down the device */
+ pci_disable_device(hdev->pdev);
+ pci_set_power_state(hdev->pdev, PCI_D3hot);
+
+ return 0;
+}
+
+/*
+ * hl_device_resume - initiate device resume
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Bring the hw back to operating state (all asics).
+ * Returns 0 for success or an error on failure.
+ * Called at driver resume.
+ */
+int hl_device_resume(struct hl_device *hdev)
+{
+ int rc;
+
+ pci_set_power_state(hdev->pdev, PCI_D0);
+ pci_restore_state(hdev->pdev);
+ rc = pci_enable_device(hdev->pdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to enable PCI device in resume\n");
+ return rc;
+ }
+
+ rc = hdev->asic_funcs->resume(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to enable PCI access from device CPU\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void hl_device_hard_reset_pending(struct work_struct *work)
+{
+ struct hl_device_reset_work *device_reset_work =
+ container_of(work, struct hl_device_reset_work, reset_work);
+ struct hl_device *hdev = device_reset_work->hdev;
+ u16 pending_cnt = HL_PENDING_RESET_PER_SEC;
+ struct task_struct *task = NULL;
+
+ /* Flush all processes that are inside hl_open */
+ mutex_lock(&hdev->fd_open_cnt_lock);
+
+ while ((atomic_read(&hdev->fd_open_cnt)) && (pending_cnt)) {
+
+ pending_cnt--;
+
+ dev_info(hdev->dev,
+ "Can't HARD reset, waiting for user to close FD\n");
+ ssleep(1);
+ }
+
+ if (atomic_read(&hdev->fd_open_cnt)) {
+ task = get_pid_task(hdev->user_ctx->hpriv->taskpid,
+ PIDTYPE_PID);
+ if (task) {
+ dev_info(hdev->dev, "Killing user processes\n");
+ send_sig(SIGKILL, task, 1);
+ msleep(100);
+
+ put_task_struct(task);
+ }
+ }
+
+ mutex_unlock(&hdev->fd_open_cnt_lock);
+
+ hl_device_reset(hdev, true, true);
+
+ kfree(device_reset_work);
+}
+
+/*
+ * hl_device_reset - reset the device
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @hard_reset: should we do hard reset to all engines or just reset the
+ * compute/dma engines
+ *
+ * Block future CS and wait for pending CS to be enqueued
+ * Call ASIC H/W fini
+ * Flush all completions
+ * Re-initialize all internal data structures
+ * Call ASIC H/W init, late_init
+ * Test queues
+ * Enable device
+ *
+ * Returns 0 for success or an error on failure.
+ */
+int hl_device_reset(struct hl_device *hdev, bool hard_reset,
+ bool from_hard_reset_thread)
+{
+ int i, rc;
+
+ if (!hdev->init_done) {
+ dev_err(hdev->dev,
+ "Can't reset before initialization is done\n");
+ return 0;
+ }
+
+ /*
+ * Prevent concurrency in this function - only one reset should be
+ * done at any given time. Only need to perform this if we didn't
+ * get from the dedicated hard reset thread
+ */
+ if (!from_hard_reset_thread) {
+ /* Block future CS/VM/JOB completion operations */
+ rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
+ if (rc)
+ return 0;
+
+ /* This also blocks future CS/VM/JOB completion operations */
+ hdev->disabled = true;
+
+ /*
+ * Flush anyone that is inside the critical section of enqueue
+ * jobs to the H/W
+ */
+ hdev->asic_funcs->hw_queues_lock(hdev);
+ hdev->asic_funcs->hw_queues_unlock(hdev);
+
+ dev_err(hdev->dev, "Going to RESET device!\n");
+ }
+
+again:
+ if ((hard_reset) && (!from_hard_reset_thread)) {
+ struct hl_device_reset_work *device_reset_work;
+
+ if (!hdev->pdev) {
+ dev_err(hdev->dev,
+ "Reset action is NOT supported in simulator\n");
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ hdev->hard_reset_pending = true;
+
+ device_reset_work = kzalloc(sizeof(*device_reset_work),
+ GFP_ATOMIC);
+ if (!device_reset_work) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ /*
+ * Because the reset function can't run from interrupt or
+ * from heartbeat work, we need to call the reset function
+ * from a dedicated work
+ */
+ INIT_WORK(&device_reset_work->reset_work,
+ hl_device_hard_reset_pending);
+ device_reset_work->hdev = hdev;
+ schedule_work(&device_reset_work->reset_work);
+
+ return 0;
+ }
+
+ if (hard_reset) {
+ device_late_fini(hdev);
+
+ /*
+ * Now that the heartbeat thread is closed, flush processes
+ * which are sending messages to CPU
+ */
+ mutex_lock(&hdev->send_cpu_message_lock);
+ mutex_unlock(&hdev->send_cpu_message_lock);
+ }
+
+ /*
+ * Halt the engines and disable interrupts so we won't get any more
+ * completions from H/W and we won't have any accesses from the
+ * H/W to the host machine
+ */
+ hdev->asic_funcs->halt_engines(hdev, hard_reset);
+
+ /* Go over all the queues, release all CS and their jobs */
+ hl_cs_rollback_all(hdev);
+
+ if (hard_reset) {
+ /* Release kernel context */
+ if (hl_ctx_put(hdev->kernel_ctx) != 1) {
+ dev_err(hdev->dev,
+ "kernel ctx is alive during hard reset\n");
+ rc = -EBUSY;
+ goto out_err;
+ }
+
+ hdev->kernel_ctx = NULL;
+ }
+
+ /* Reset the H/W. It will be in idle state after this returns */
+ hdev->asic_funcs->hw_fini(hdev, hard_reset);
+
+ if (hard_reset) {
+ hl_vm_fini(hdev);
+ hl_eq_reset(hdev, &hdev->event_queue);
+ }
+
+ /* Re-initialize PI,CI to 0 in all queues (hw queue, cq) */
+ hl_hw_queue_reset(hdev, hard_reset);
+ for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
+ hl_cq_reset(hdev, &hdev->completion_queue[i]);
+
+ /* Make sure the setup phase for the user context will run again */
+ if (hdev->user_ctx) {
+ atomic_set(&hdev->user_ctx->thread_restore_token, 1);
+ hdev->user_ctx->thread_restore_wait_token = 0;
+ }
+
+ /* Finished tear-down, starting to re-initialize */
+
+ if (hard_reset) {
+ hdev->device_cpu_disabled = false;
+
+ /* Allocate the kernel context */
+ hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx),
+ GFP_KERNEL);
+ if (!hdev->kernel_ctx) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ hdev->user_ctx = NULL;
+
+ rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to init kernel ctx in hard reset\n");
+ kfree(hdev->kernel_ctx);
+ hdev->kernel_ctx = NULL;
+ goto out_err;
+ }
+ }
+
+ rc = hdev->asic_funcs->hw_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to initialize the H/W after reset\n");
+ goto out_err;
+ }
+
+ hdev->disabled = false;
+
+ /* Check that the communication with the device is working */
+ rc = hdev->asic_funcs->test_queues(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to detect if device is alive after reset\n");
+ goto out_err;
+ }
+
+ if (hard_reset) {
+ rc = device_late_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed late init after hard reset\n");
+ goto out_err;
+ }
+
+ rc = hl_vm_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to init memory module after hard reset\n");
+ goto out_err;
+ }
+
+ hl_set_max_power(hdev, hdev->max_power);
+
+ hdev->hard_reset_pending = false;
+ } else {
+ rc = hdev->asic_funcs->soft_reset_late_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed late init after soft reset\n");
+ goto out_err;
+ }
+ }
+
+ atomic_set(&hdev->in_reset, 0);
+
+ if (hard_reset)
+ hdev->hard_reset_cnt++;
+ else
+ hdev->soft_reset_cnt++;
+
+ return 0;
+
+out_err:
+ hdev->disabled = true;
+
+ if (hard_reset) {
+ dev_err(hdev->dev,
+ "Failed to reset! Device is NOT usable\n");
+ hdev->hard_reset_cnt++;
+ } else {
+ dev_err(hdev->dev,
+ "Failed to do soft-reset, trying hard reset\n");
+ hdev->soft_reset_cnt++;
+ hard_reset = true;
+ goto again;
+ }
+
+ atomic_set(&hdev->in_reset, 0);
+
+ return rc;
+}
+
+/*
+ * hl_device_init - main initialization function for habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Allocate an id for the device, do early initialization and then call the
+ * ASIC specific initialization functions. Finally, create the cdev and the
+ * Linux device to expose it to the user
+ */
+int hl_device_init(struct hl_device *hdev, struct class *hclass)
+{
+ int i, rc, cq_ready_cnt;
+
+ /* Create device */
+ rc = device_setup_cdev(hdev, hclass, hdev->id, &hl_ops);
+
+ if (rc)
+ goto out_disabled;
+
+ /* Initialize ASIC function pointers and perform early init */
+ rc = device_early_init(hdev);
+ if (rc)
+ goto release_device;
+
+ /*
+ * Start calling ASIC initialization. First S/W then H/W and finally
+ * late init
+ */
+ rc = hdev->asic_funcs->sw_init(hdev);
+ if (rc)
+ goto early_fini;
+
+ /*
+ * Initialize the H/W queues. Must be done before hw_init, because
+ * there the addresses of the kernel queue are being written to the
+ * registers of the device
+ */
+ rc = hl_hw_queues_create(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize kernel queues\n");
+ goto sw_fini;
+ }
+
+ /*
+ * Initialize the completion queues. Must be done before hw_init,
+ * because there the addresses of the completion queues are being
+ * passed as arguments to request_irq
+ */
+ hdev->completion_queue =
+ kcalloc(hdev->asic_prop.completion_queues_count,
+ sizeof(*hdev->completion_queue), GFP_KERNEL);
+
+ if (!hdev->completion_queue) {
+ dev_err(hdev->dev, "failed to allocate completion queues\n");
+ rc = -ENOMEM;
+ goto hw_queues_destroy;
+ }
+
+ for (i = 0, cq_ready_cnt = 0;
+ i < hdev->asic_prop.completion_queues_count;
+ i++, cq_ready_cnt++) {
+ rc = hl_cq_init(hdev, &hdev->completion_queue[i], i);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to initialize completion queue\n");
+ goto cq_fini;
+ }
+ }
+
+ /*
+ * Initialize the event queue. Must be done before hw_init,
+ * because there the address of the event queue is being
+ * passed as argument to request_irq
+ */
+ rc = hl_eq_init(hdev, &hdev->event_queue);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize event queue\n");
+ goto cq_fini;
+ }
+
+ /* Allocate the kernel context */
+ hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx), GFP_KERNEL);
+ if (!hdev->kernel_ctx) {
+ rc = -ENOMEM;
+ goto eq_fini;
+ }
+
+ hdev->user_ctx = NULL;
+
+ rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize kernel context\n");
+ goto free_ctx;
+ }
+
+ rc = hl_cb_pool_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize CB pool\n");
+ goto release_ctx;
+ }
+
+ rc = hl_sysfs_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize sysfs\n");
+ goto free_cb_pool;
+ }
+
+ hl_debugfs_add_device(hdev);
+
+ if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
+ dev_info(hdev->dev,
+ "H/W state is dirty, must reset before initializing\n");
+ hdev->asic_funcs->hw_fini(hdev, true);
+ }
+
+ rc = hdev->asic_funcs->hw_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize the H/W\n");
+ rc = 0;
+ goto out_disabled;
+ }
+
+ hdev->disabled = false;
+
+ /* Check that the communication with the device is working */
+ rc = hdev->asic_funcs->test_queues(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to detect if device is alive\n");
+ rc = 0;
+ goto out_disabled;
+ }
+
+ /* After test_queues, KMD can start sending messages to device CPU */
+
+ rc = device_late_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed late initialization\n");
+ rc = 0;
+ goto out_disabled;
+ }
+
+ dev_info(hdev->dev, "Found %s device with %lluGB DRAM\n",
+ hdev->asic_name,
+ hdev->asic_prop.dram_size / 1024 / 1024 / 1024);
+
+ rc = hl_vm_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to initialize memory module\n");
+ rc = 0;
+ goto out_disabled;
+ }
+
+ /*
+ * hl_hwmon_init must be called after device_late_init, because only
+ * there we get the information from the device about which
+ * hwmon-related sensors the device supports
+ */
+ rc = hl_hwmon_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to initialize hwmon\n");
+ rc = 0;
+ goto out_disabled;
+ }
+
+ dev_notice(hdev->dev,
+ "Successfully added device to habanalabs driver\n");
+
+ hdev->init_done = true;
+
+ return 0;
+
+free_cb_pool:
+ hl_cb_pool_fini(hdev);
+release_ctx:
+ if (hl_ctx_put(hdev->kernel_ctx) != 1)
+ dev_err(hdev->dev,
+ "kernel ctx is still alive on initialization failure\n");
+free_ctx:
+ kfree(hdev->kernel_ctx);
+eq_fini:
+ hl_eq_fini(hdev, &hdev->event_queue);
+cq_fini:
+ for (i = 0 ; i < cq_ready_cnt ; i++)
+ hl_cq_fini(hdev, &hdev->completion_queue[i]);
+ kfree(hdev->completion_queue);
+hw_queues_destroy:
+ hl_hw_queues_destroy(hdev);
+sw_fini:
+ hdev->asic_funcs->sw_fini(hdev);
+early_fini:
+ device_early_fini(hdev);
+release_device:
+ device_destroy(hclass, hdev->dev->devt);
+ cdev_del(&hdev->cdev);
+out_disabled:
+ hdev->disabled = true;
+ if (hdev->pdev)
+ dev_err(&hdev->pdev->dev,
+ "Failed to initialize hl%d. Device is NOT usable !\n",
+ hdev->id);
+ else
+ pr_err("Failed to initialize hl%d. Device is NOT usable !\n",
+ hdev->id);
+
+ return rc;
+}
+
+/*
+ * hl_device_fini - main tear-down function for habanalabs device
+ *
+ * @hdev: pointer to habanalabs device structure
+ *
+ * Destroy the device, call ASIC fini functions and release the id
+ */
+void hl_device_fini(struct hl_device *hdev)
+{
+ int i, rc;
+ ktime_t timeout;
+
+ dev_info(hdev->dev, "Removing device\n");
+
+ /*
+ * This function is competing with the reset function, so try to
+ * take the reset atomic and if we are already in middle of reset,
+ * wait until reset function is finished. Reset function is designed
+ * to always finish (could take up to a few seconds in worst case).
+ */
+
+ timeout = ktime_add_us(ktime_get(),
+ HL_PENDING_RESET_PER_SEC * 1000 * 1000 * 4);
+ rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
+ while (rc) {
+ usleep_range(50, 200);
+ rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ WARN(1, "Failed to remove device because reset function did not finish\n");
+ return;
+ }
+ };
+
+ /* Mark device as disabled */
+ hdev->disabled = true;
+
+ hl_hwmon_fini(hdev);
+
+ device_late_fini(hdev);
+
+ hl_debugfs_remove_device(hdev);
+
+ hl_sysfs_fini(hdev);
+
+ /*
+ * Halt the engines and disable interrupts so we won't get any more
+ * completions from H/W and we won't have any accesses from the
+ * H/W to the host machine
+ */
+ hdev->asic_funcs->halt_engines(hdev, true);
+
+ /* Go over all the queues, release all CS and their jobs */
+ hl_cs_rollback_all(hdev);
+
+ hl_cb_pool_fini(hdev);
+
+ /* Release kernel context */
+ if ((hdev->kernel_ctx) && (hl_ctx_put(hdev->kernel_ctx) != 1))
+ dev_err(hdev->dev, "kernel ctx is still alive\n");
+
+ /* Reset the H/W. It will be in idle state after this returns */
+ hdev->asic_funcs->hw_fini(hdev, true);
+
+ hl_vm_fini(hdev);
+
+ hl_eq_fini(hdev, &hdev->event_queue);
+
+ for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
+ hl_cq_fini(hdev, &hdev->completion_queue[i]);
+ kfree(hdev->completion_queue);
+
+ hl_hw_queues_destroy(hdev);
+
+ /* Call ASIC S/W finalize function */
+ hdev->asic_funcs->sw_fini(hdev);
+
+ device_early_fini(hdev);
+
+ /* Hide device from user */
+ device_destroy(hdev->dev->class, hdev->dev->devt);
+ cdev_del(&hdev->cdev);
+
+ pr_info("removed device successfully\n");
+}
+
+/*
+ * hl_poll_timeout_memory - Periodically poll a host memory address
+ * until it is not zero or a timeout occurs
+ * @hdev: pointer to habanalabs device structure
+ * @addr: Address to poll
+ * @timeout_us: timeout in us
+ * @val: Variable to read the value into
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ *
+ * The function sleeps for 100us with timeout value of
+ * timeout_us
+ */
+int hl_poll_timeout_memory(struct hl_device *hdev, u64 addr,
+ u32 timeout_us, u32 *val)
+{
+ /*
+ * address in this function points always to a memory location in the
+ * host's (server's) memory. That location is updated asynchronously
+ * either by the direct access of the device or by another core
+ */
+ u32 *paddr = (u32 *) (uintptr_t) addr;
+ ktime_t timeout = ktime_add_us(ktime_get(), timeout_us);
+
+ might_sleep();
+
+ for (;;) {
+ /*
+ * Flush CPU read/write buffers to make sure we read updates
+ * done by other cores or by the device
+ */
+ mb();
+ *val = *paddr;
+ if (*val)
+ break;
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ *val = *paddr;
+ break;
+ }
+ usleep_range((100 >> 2) + 1, 100);
+ }
+
+ return *val ? 0 : -ETIMEDOUT;
+}
+
+/*
+ * hl_poll_timeout_devicememory - Periodically poll a device memory address
+ * until it is not zero or a timeout occurs
+ * @hdev: pointer to habanalabs device structure
+ * @addr: Device address to poll
+ * @timeout_us: timeout in us
+ * @val: Variable to read the value into
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ *
+ * The function sleeps for 100us with timeout value of
+ * timeout_us
+ */
+int hl_poll_timeout_device_memory(struct hl_device *hdev, void __iomem *addr,
+ u32 timeout_us, u32 *val)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), timeout_us);
+
+ might_sleep();
+
+ for (;;) {
+ *val = readl(addr);
+ if (*val)
+ break;
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ *val = readl(addr);
+ break;
+ }
+ usleep_range((100 >> 2) + 1, 100);
+ }
+
+ return *val ? 0 : -ETIMEDOUT;
+}
+
+/*
+ * MMIO register access helper functions.
+ */
+
+/*
+ * hl_rreg - Read an MMIO register
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @reg: MMIO register offset (in bytes)
+ *
+ * Returns the value of the MMIO register we are asked to read
+ *
+ */
+inline u32 hl_rreg(struct hl_device *hdev, u32 reg)
+{
+ return readl(hdev->rmmio + reg);
+}
+
+/*
+ * hl_wreg - Write to an MMIO register
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @reg: MMIO register offset (in bytes)
+ * @val: 32-bit value
+ *
+ * Writes the 32-bit value into the MMIO register
+ *
+ */
+inline void hl_wreg(struct hl_device *hdev, u32 reg, u32 val)
+{
+ writel(val, hdev->rmmio + reg);
+}
diff --git a/drivers/misc/habanalabs/goya/Makefile b/drivers/misc/habanalabs/goya/Makefile
new file mode 100644
index 000000000000..e458e5ba500b
--- /dev/null
+++ b/drivers/misc/habanalabs/goya/Makefile
@@ -0,0 +1,3 @@
+subdir-ccflags-y += -I$(src)
+
+HL_GOYA_FILES := goya/goya.o goya/goya_security.o goya/goya_hwmgr.o
diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c
new file mode 100644
index 000000000000..238dd57c541b
--- /dev/null
+++ b/drivers/misc/habanalabs/goya/goya.c
@@ -0,0 +1,5391 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "goyaP.h"
+#include "include/hw_ip/mmu/mmu_general.h"
+#include "include/hw_ip/mmu/mmu_v1_0.h"
+#include "include/goya/asic_reg/goya_masks.h"
+
+#include <linux/pci.h>
+#include <linux/genalloc.h>
+#include <linux/firmware.h>
+#include <linux/hwmon.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
+
+/*
+ * GOYA security scheme:
+ *
+ * 1. Host is protected by:
+ * - Range registers (When MMU is enabled, DMA RR does NOT protect host)
+ * - MMU
+ *
+ * 2. DRAM is protected by:
+ * - Range registers (protect the first 512MB)
+ * - MMU (isolation between users)
+ *
+ * 3. Configuration is protected by:
+ * - Range registers
+ * - Protection bits
+ *
+ * When MMU is disabled:
+ *
+ * QMAN DMA: PQ, CQ, CP, DMA are secured.
+ * PQ, CB and the data are on the host.
+ *
+ * QMAN TPC/MME:
+ * PQ, CQ and CP are not secured.
+ * PQ, CB and the data are on the SRAM/DRAM.
+ *
+ * Since QMAN DMA is secured, KMD is parsing the DMA CB:
+ * - KMD checks DMA pointer
+ * - WREG, MSG_PROT are not allowed.
+ * - MSG_LONG/SHORT are allowed.
+ *
+ * A read/write transaction by the QMAN to a protected area will succeed if
+ * and only if the QMAN's CP is secured and MSG_PROT is used
+ *
+ *
+ * When MMU is enabled:
+ *
+ * QMAN DMA: PQ, CQ and CP are secured.
+ * MMU is set to bypass on the Secure props register of the QMAN.
+ * The reasons we don't enable MMU for PQ, CQ and CP are:
+ * - PQ entry is in kernel address space and KMD doesn't map it.
+ * - CP writes to MSIX register and to kernel address space (completion
+ * queue).
+ *
+ * DMA is not secured but because CP is secured, KMD still needs to parse the
+ * CB, but doesn't need to check the DMA addresses.
+ *
+ * For QMAN DMA 0, DMA is also secured because only KMD uses this DMA and KMD
+ * doesn't map memory in MMU.
+ *
+ * QMAN TPC/MME: PQ, CQ and CP aren't secured (no change from MMU disabled mode)
+ *
+ * DMA RR does NOT protect host because DMA is not secured
+ *
+ */
+
+#define GOYA_MMU_REGS_NUM 61
+
+#define GOYA_DMA_POOL_BLK_SIZE 0x100 /* 256 bytes */
+
+#define GOYA_RESET_TIMEOUT_MSEC 500 /* 500ms */
+#define GOYA_PLDM_RESET_TIMEOUT_MSEC 20000 /* 20s */
+#define GOYA_RESET_WAIT_MSEC 1 /* 1ms */
+#define GOYA_CPU_RESET_WAIT_MSEC 100 /* 100ms */
+#define GOYA_PLDM_RESET_WAIT_MSEC 1000 /* 1s */
+#define GOYA_CPU_TIMEOUT_USEC 10000000 /* 10s */
+#define GOYA_TEST_QUEUE_WAIT_USEC 100000 /* 100ms */
+#define GOYA_PLDM_MMU_TIMEOUT_USEC (MMU_CONFIG_TIMEOUT_USEC * 100)
+#define GOYA_PLDM_QMAN0_TIMEOUT_USEC (HL_DEVICE_TIMEOUT_USEC * 30)
+
+#define GOYA_QMAN0_FENCE_VAL 0xD169B243
+
+#define GOYA_MAX_INITIATORS 20
+
+#define GOYA_MAX_STRING_LEN 20
+
+#define GOYA_CB_POOL_CB_CNT 512
+#define GOYA_CB_POOL_CB_SIZE 0x20000 /* 128KB */
+
+static const char goya_irq_name[GOYA_MSIX_ENTRIES][GOYA_MAX_STRING_LEN] = {
+ "goya cq 0", "goya cq 1", "goya cq 2", "goya cq 3",
+ "goya cq 4", "goya cpu eq"
+};
+
+static u16 goya_packet_sizes[MAX_PACKET_ID] = {
+ [PACKET_WREG_32] = sizeof(struct packet_wreg32),
+ [PACKET_WREG_BULK] = sizeof(struct packet_wreg_bulk),
+ [PACKET_MSG_LONG] = sizeof(struct packet_msg_long),
+ [PACKET_MSG_SHORT] = sizeof(struct packet_msg_short),
+ [PACKET_CP_DMA] = sizeof(struct packet_cp_dma),
+ [PACKET_MSG_PROT] = sizeof(struct packet_msg_prot),
+ [PACKET_FENCE] = sizeof(struct packet_fence),
+ [PACKET_LIN_DMA] = sizeof(struct packet_lin_dma),
+ [PACKET_NOP] = sizeof(struct packet_nop),
+ [PACKET_STOP] = sizeof(struct packet_stop)
+};
+
+static u64 goya_mmu_regs[GOYA_MMU_REGS_NUM] = {
+ mmDMA_QM_0_GLBL_NON_SECURE_PROPS,
+ mmDMA_QM_1_GLBL_NON_SECURE_PROPS,
+ mmDMA_QM_2_GLBL_NON_SECURE_PROPS,
+ mmDMA_QM_3_GLBL_NON_SECURE_PROPS,
+ mmDMA_QM_4_GLBL_NON_SECURE_PROPS,
+ mmTPC0_QM_GLBL_SECURE_PROPS,
+ mmTPC0_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC0_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC0_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC0_CFG_ARUSER,
+ mmTPC0_CFG_AWUSER,
+ mmTPC1_QM_GLBL_SECURE_PROPS,
+ mmTPC1_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC1_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC1_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC1_CFG_ARUSER,
+ mmTPC1_CFG_AWUSER,
+ mmTPC2_QM_GLBL_SECURE_PROPS,
+ mmTPC2_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC2_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC2_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC2_CFG_ARUSER,
+ mmTPC2_CFG_AWUSER,
+ mmTPC3_QM_GLBL_SECURE_PROPS,
+ mmTPC3_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC3_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC3_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC3_CFG_ARUSER,
+ mmTPC3_CFG_AWUSER,
+ mmTPC4_QM_GLBL_SECURE_PROPS,
+ mmTPC4_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC4_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC4_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC4_CFG_ARUSER,
+ mmTPC4_CFG_AWUSER,
+ mmTPC5_QM_GLBL_SECURE_PROPS,
+ mmTPC5_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC5_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC5_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC5_CFG_ARUSER,
+ mmTPC5_CFG_AWUSER,
+ mmTPC6_QM_GLBL_SECURE_PROPS,
+ mmTPC6_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC6_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC6_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC6_CFG_ARUSER,
+ mmTPC6_CFG_AWUSER,
+ mmTPC7_QM_GLBL_SECURE_PROPS,
+ mmTPC7_QM_GLBL_NON_SECURE_PROPS,
+ mmTPC7_CMDQ_GLBL_SECURE_PROPS,
+ mmTPC7_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmTPC7_CFG_ARUSER,
+ mmTPC7_CFG_AWUSER,
+ mmMME_QM_GLBL_SECURE_PROPS,
+ mmMME_QM_GLBL_NON_SECURE_PROPS,
+ mmMME_CMDQ_GLBL_SECURE_PROPS,
+ mmMME_CMDQ_GLBL_NON_SECURE_PROPS,
+ mmMME_SBA_CONTROL_DATA,
+ mmMME_SBB_CONTROL_DATA,
+ mmMME_SBC_CONTROL_DATA,
+ mmMME_WBC_CONTROL_DATA
+};
+
+#define GOYA_ASYC_EVENT_GROUP_NON_FATAL_SIZE 121
+
+static u32 goya_non_fatal_events[GOYA_ASYC_EVENT_GROUP_NON_FATAL_SIZE] = {
+ GOYA_ASYNC_EVENT_ID_PCIE_IF,
+ GOYA_ASYNC_EVENT_ID_TPC0_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC1_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC2_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC3_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC4_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC5_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC6_ECC,
+ GOYA_ASYNC_EVENT_ID_TPC7_ECC,
+ GOYA_ASYNC_EVENT_ID_MME_ECC,
+ GOYA_ASYNC_EVENT_ID_MME_ECC_EXT,
+ GOYA_ASYNC_EVENT_ID_MMU_ECC,
+ GOYA_ASYNC_EVENT_ID_DMA_MACRO,
+ GOYA_ASYNC_EVENT_ID_DMA_ECC,
+ GOYA_ASYNC_EVENT_ID_CPU_IF_ECC,
+ GOYA_ASYNC_EVENT_ID_PSOC_MEM,
+ GOYA_ASYNC_EVENT_ID_PSOC_CORESIGHT,
+ GOYA_ASYNC_EVENT_ID_SRAM0,
+ GOYA_ASYNC_EVENT_ID_SRAM1,
+ GOYA_ASYNC_EVENT_ID_SRAM2,
+ GOYA_ASYNC_EVENT_ID_SRAM3,
+ GOYA_ASYNC_EVENT_ID_SRAM4,
+ GOYA_ASYNC_EVENT_ID_SRAM5,
+ GOYA_ASYNC_EVENT_ID_SRAM6,
+ GOYA_ASYNC_EVENT_ID_SRAM7,
+ GOYA_ASYNC_EVENT_ID_SRAM8,
+ GOYA_ASYNC_EVENT_ID_SRAM9,
+ GOYA_ASYNC_EVENT_ID_SRAM10,
+ GOYA_ASYNC_EVENT_ID_SRAM11,
+ GOYA_ASYNC_EVENT_ID_SRAM12,
+ GOYA_ASYNC_EVENT_ID_SRAM13,
+ GOYA_ASYNC_EVENT_ID_SRAM14,
+ GOYA_ASYNC_EVENT_ID_SRAM15,
+ GOYA_ASYNC_EVENT_ID_SRAM16,
+ GOYA_ASYNC_EVENT_ID_SRAM17,
+ GOYA_ASYNC_EVENT_ID_SRAM18,
+ GOYA_ASYNC_EVENT_ID_SRAM19,
+ GOYA_ASYNC_EVENT_ID_SRAM20,
+ GOYA_ASYNC_EVENT_ID_SRAM21,
+ GOYA_ASYNC_EVENT_ID_SRAM22,
+ GOYA_ASYNC_EVENT_ID_SRAM23,
+ GOYA_ASYNC_EVENT_ID_SRAM24,
+ GOYA_ASYNC_EVENT_ID_SRAM25,
+ GOYA_ASYNC_EVENT_ID_SRAM26,
+ GOYA_ASYNC_EVENT_ID_SRAM27,
+ GOYA_ASYNC_EVENT_ID_SRAM28,
+ GOYA_ASYNC_EVENT_ID_SRAM29,
+ GOYA_ASYNC_EVENT_ID_GIC500,
+ GOYA_ASYNC_EVENT_ID_PLL0,
+ GOYA_ASYNC_EVENT_ID_PLL1,
+ GOYA_ASYNC_EVENT_ID_PLL3,
+ GOYA_ASYNC_EVENT_ID_PLL4,
+ GOYA_ASYNC_EVENT_ID_PLL5,
+ GOYA_ASYNC_EVENT_ID_PLL6,
+ GOYA_ASYNC_EVENT_ID_AXI_ECC,
+ GOYA_ASYNC_EVENT_ID_L2_RAM_ECC,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT,
+ GOYA_ASYNC_EVENT_ID_PCIE_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC0_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC1_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC2_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC3_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC4_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC5_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC6_DEC,
+ GOYA_ASYNC_EVENT_ID_TPC7_DEC,
+ GOYA_ASYNC_EVENT_ID_MME_WACS,
+ GOYA_ASYNC_EVENT_ID_MME_WACSD,
+ GOYA_ASYNC_EVENT_ID_CPU_AXI_SPLITTER,
+ GOYA_ASYNC_EVENT_ID_PSOC_AXI_DEC,
+ GOYA_ASYNC_EVENT_ID_PSOC,
+ GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC1_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC2_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC3_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC4_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC5_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC6_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC7_KRN_ERR,
+ GOYA_ASYNC_EVENT_ID_TPC0_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC1_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC2_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC3_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC4_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC5_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC6_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC7_CMDQ,
+ GOYA_ASYNC_EVENT_ID_TPC0_QM,
+ GOYA_ASYNC_EVENT_ID_TPC1_QM,
+ GOYA_ASYNC_EVENT_ID_TPC2_QM,
+ GOYA_ASYNC_EVENT_ID_TPC3_QM,
+ GOYA_ASYNC_EVENT_ID_TPC4_QM,
+ GOYA_ASYNC_EVENT_ID_TPC5_QM,
+ GOYA_ASYNC_EVENT_ID_TPC6_QM,
+ GOYA_ASYNC_EVENT_ID_TPC7_QM,
+ GOYA_ASYNC_EVENT_ID_MME_QM,
+ GOYA_ASYNC_EVENT_ID_MME_CMDQ,
+ GOYA_ASYNC_EVENT_ID_DMA0_QM,
+ GOYA_ASYNC_EVENT_ID_DMA1_QM,
+ GOYA_ASYNC_EVENT_ID_DMA2_QM,
+ GOYA_ASYNC_EVENT_ID_DMA3_QM,
+ GOYA_ASYNC_EVENT_ID_DMA4_QM,
+ GOYA_ASYNC_EVENT_ID_DMA0_CH,
+ GOYA_ASYNC_EVENT_ID_DMA1_CH,
+ GOYA_ASYNC_EVENT_ID_DMA2_CH,
+ GOYA_ASYNC_EVENT_ID_DMA3_CH,
+ GOYA_ASYNC_EVENT_ID_DMA4_CH,
+ GOYA_ASYNC_EVENT_ID_TPC0_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC1_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC2_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC3_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC4_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC5_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC6_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_TPC7_BMON_SPMU,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH0,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH1,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH2,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH3,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH4
+};
+
+static int goya_armcp_info_get(struct hl_device *hdev);
+static void goya_mmu_prepare(struct hl_device *hdev, u32 asid);
+static int goya_mmu_clear_pgt_range(struct hl_device *hdev);
+static int goya_mmu_set_dram_default_page(struct hl_device *hdev);
+static int goya_mmu_update_asid_hop0_addr(struct hl_device *hdev, u32 asid,
+ u64 phys_addr);
+
+static void goya_get_fixed_properties(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ int i;
+
+ for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++) {
+ prop->hw_queues_props[i].type = QUEUE_TYPE_EXT;
+ prop->hw_queues_props[i].kmd_only = 0;
+ }
+
+ for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES ; i++) {
+ prop->hw_queues_props[i].type = QUEUE_TYPE_CPU;
+ prop->hw_queues_props[i].kmd_only = 1;
+ }
+
+ for (; i < NUMBER_OF_EXT_HW_QUEUES + NUMBER_OF_CPU_HW_QUEUES +
+ NUMBER_OF_INT_HW_QUEUES; i++) {
+ prop->hw_queues_props[i].type = QUEUE_TYPE_INT;
+ prop->hw_queues_props[i].kmd_only = 0;
+ }
+
+ for (; i < HL_MAX_QUEUES; i++)
+ prop->hw_queues_props[i].type = QUEUE_TYPE_NA;
+
+ prop->completion_queues_count = NUMBER_OF_CMPLT_QUEUES;
+
+ prop->dram_base_address = DRAM_PHYS_BASE;
+ prop->dram_size = DRAM_PHYS_DEFAULT_SIZE;
+ prop->dram_end_address = prop->dram_base_address + prop->dram_size;
+ prop->dram_user_base_address = DRAM_BASE_ADDR_USER;
+
+ prop->sram_base_address = SRAM_BASE_ADDR;
+ prop->sram_size = SRAM_SIZE;
+ prop->sram_end_address = prop->sram_base_address + prop->sram_size;
+ prop->sram_user_base_address = prop->sram_base_address +
+ SRAM_USER_BASE_OFFSET;
+
+ prop->mmu_pgt_addr = MMU_PAGE_TABLES_ADDR;
+ prop->mmu_dram_default_page_addr = MMU_DRAM_DEFAULT_PAGE_ADDR;
+ if (hdev->pldm)
+ prop->mmu_pgt_size = 0x800000; /* 8MB */
+ else
+ prop->mmu_pgt_size = MMU_PAGE_TABLES_SIZE;
+ prop->mmu_pte_size = HL_PTE_SIZE;
+ prop->mmu_hop_table_size = HOP_TABLE_SIZE;
+ prop->mmu_hop0_tables_total_size = HOP0_TABLES_TOTAL_SIZE;
+ prop->dram_page_size = PAGE_SIZE_2MB;
+
+ prop->host_phys_base_address = HOST_PHYS_BASE;
+ prop->va_space_host_start_address = VA_HOST_SPACE_START;
+ prop->va_space_host_end_address = VA_HOST_SPACE_END;
+ prop->va_space_dram_start_address = VA_DDR_SPACE_START;
+ prop->va_space_dram_end_address = VA_DDR_SPACE_END;
+ prop->dram_size_for_default_page_mapping =
+ prop->va_space_dram_end_address;
+ prop->cfg_size = CFG_SIZE;
+ prop->max_asid = MAX_ASID;
+ prop->num_of_events = GOYA_ASYNC_EVENT_ID_SIZE;
+ prop->cb_pool_cb_cnt = GOYA_CB_POOL_CB_CNT;
+ prop->cb_pool_cb_size = GOYA_CB_POOL_CB_SIZE;
+ prop->max_power_default = MAX_POWER_DEFAULT;
+ prop->tpc_enabled_mask = TPC_ENABLED_MASK;
+
+ prop->high_pll = PLL_HIGH_DEFAULT;
+}
+
+int goya_send_pci_access_msg(struct hl_device *hdev, u32 opcode)
+{
+ struct armcp_packet pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = cpu_to_le32(opcode << ARMCP_PKT_CTL_OPCODE_SHIFT);
+
+ return hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt,
+ sizeof(pkt), HL_DEVICE_TIMEOUT_USEC, NULL);
+}
+
+/*
+ * goya_pci_bars_map - Map PCI BARS of Goya device
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Request PCI regions and map them to kernel virtual addresses.
+ * Returns 0 on success
+ *
+ */
+static int goya_pci_bars_map(struct hl_device *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ int rc;
+
+ rc = pci_request_regions(pdev, HL_NAME);
+ if (rc) {
+ dev_err(hdev->dev, "Cannot obtain PCI resources\n");
+ return rc;
+ }
+
+ hdev->pcie_bar[SRAM_CFG_BAR_ID] =
+ pci_ioremap_bar(pdev, SRAM_CFG_BAR_ID);
+ if (!hdev->pcie_bar[SRAM_CFG_BAR_ID]) {
+ dev_err(hdev->dev, "pci_ioremap_bar failed for CFG\n");
+ rc = -ENODEV;
+ goto err_release_regions;
+ }
+
+ hdev->pcie_bar[MSIX_BAR_ID] = pci_ioremap_bar(pdev, MSIX_BAR_ID);
+ if (!hdev->pcie_bar[MSIX_BAR_ID]) {
+ dev_err(hdev->dev, "pci_ioremap_bar failed for MSIX\n");
+ rc = -ENODEV;
+ goto err_unmap_sram_cfg;
+ }
+
+ hdev->pcie_bar[DDR_BAR_ID] = pci_ioremap_wc_bar(pdev, DDR_BAR_ID);
+ if (!hdev->pcie_bar[DDR_BAR_ID]) {
+ dev_err(hdev->dev, "pci_ioremap_bar failed for DDR\n");
+ rc = -ENODEV;
+ goto err_unmap_msix;
+ }
+
+ hdev->rmmio = hdev->pcie_bar[SRAM_CFG_BAR_ID] +
+ (CFG_BASE - SRAM_BASE_ADDR);
+
+ return 0;
+
+err_unmap_msix:
+ iounmap(hdev->pcie_bar[MSIX_BAR_ID]);
+err_unmap_sram_cfg:
+ iounmap(hdev->pcie_bar[SRAM_CFG_BAR_ID]);
+err_release_regions:
+ pci_release_regions(pdev);
+
+ return rc;
+}
+
+/*
+ * goya_pci_bars_unmap - Unmap PCI BARS of Goya device
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Release all PCI BARS and unmap their virtual addresses
+ *
+ */
+static void goya_pci_bars_unmap(struct hl_device *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+
+ iounmap(hdev->pcie_bar[DDR_BAR_ID]);
+ iounmap(hdev->pcie_bar[MSIX_BAR_ID]);
+ iounmap(hdev->pcie_bar[SRAM_CFG_BAR_ID]);
+ pci_release_regions(pdev);
+}
+
+/*
+ * goya_elbi_write - Write through the ELBI interface
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * return 0 on success, -1 on failure
+ *
+ */
+static int goya_elbi_write(struct hl_device *hdev, u64 addr, u32 data)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ ktime_t timeout;
+ u32 val;
+
+ /* Clear previous status */
+ pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, 0);
+
+ pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_ADDR, (u32) addr);
+ pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_DATA, data);
+ pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_CTRL,
+ PCI_CONFIG_ELBI_CTRL_WRITE);
+
+ timeout = ktime_add_ms(ktime_get(), 10);
+ for (;;) {
+ pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, &val);
+ if (val & PCI_CONFIG_ELBI_STS_MASK)
+ break;
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS,
+ &val);
+ break;
+ }
+ usleep_range(300, 500);
+ }
+
+ if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE)
+ return 0;
+
+ if (val & PCI_CONFIG_ELBI_STS_ERR) {
+ dev_err(hdev->dev, "Error writing to ELBI\n");
+ return -EIO;
+ }
+
+ if (!(val & PCI_CONFIG_ELBI_STS_MASK)) {
+ dev_err(hdev->dev, "ELBI write didn't finish in time\n");
+ return -EIO;
+ }
+
+ dev_err(hdev->dev, "ELBI write has undefined bits in status\n");
+ return -EIO;
+}
+
+/*
+ * goya_iatu_write - iatu write routine
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static int goya_iatu_write(struct hl_device *hdev, u32 addr, u32 data)
+{
+ u32 dbi_offset;
+ int rc;
+
+ dbi_offset = addr & 0xFFF;
+
+ rc = goya_elbi_write(hdev, CFG_BASE + mmPCIE_AUX_DBI, 0x00300000);
+ rc |= goya_elbi_write(hdev, mmPCIE_DBI_BASE + dbi_offset, data);
+
+ if (rc)
+ return -EIO;
+
+ return 0;
+}
+
+static void goya_reset_link_through_bridge(struct hl_device *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ struct pci_dev *parent_port;
+ u16 val;
+
+ parent_port = pdev->bus->self;
+ pci_read_config_word(parent_port, PCI_BRIDGE_CONTROL, &val);
+ val |= PCI_BRIDGE_CTL_BUS_RESET;
+ pci_write_config_word(parent_port, PCI_BRIDGE_CONTROL, val);
+ ssleep(1);
+
+ val &= ~(PCI_BRIDGE_CTL_BUS_RESET);
+ pci_write_config_word(parent_port, PCI_BRIDGE_CONTROL, val);
+ ssleep(3);
+}
+
+/*
+ * goya_set_ddr_bar_base - set DDR bar to map specific device address
+ *
+ * @hdev: pointer to hl_device structure
+ * @addr: address in DDR. Must be aligned to DDR bar size
+ *
+ * This function configures the iATU so that the DDR bar will start at the
+ * specified addr.
+ *
+ */
+static int goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int rc;
+
+ if ((goya) && (goya->ddr_bar_cur_addr == addr))
+ return 0;
+
+ /* Inbound Region 1 - Bar 4 - Point to DDR */
+ rc = goya_iatu_write(hdev, 0x314, lower_32_bits(addr));
+ rc |= goya_iatu_write(hdev, 0x318, upper_32_bits(addr));
+ rc |= goya_iatu_write(hdev, 0x300, 0);
+ /* Enable + Bar match + match enable + Bar 4 */
+ rc |= goya_iatu_write(hdev, 0x304, 0xC0080400);
+
+ /* Return the DBI window to the default location */
+ rc |= goya_elbi_write(hdev, CFG_BASE + mmPCIE_AUX_DBI, 0);
+ rc |= goya_elbi_write(hdev, CFG_BASE + mmPCIE_AUX_DBI_32, 0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to map DDR bar to 0x%08llx\n", addr);
+ return -EIO;
+ }
+
+ if (goya)
+ goya->ddr_bar_cur_addr = addr;
+
+ return 0;
+}
+
+/*
+ * goya_init_iatu - Initialize the iATU unit inside the PCI controller
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * This is needed in case the firmware doesn't initialize the iATU
+ *
+ */
+static int goya_init_iatu(struct hl_device *hdev)
+{
+ int rc;
+
+ /* Inbound Region 0 - Bar 0 - Point to SRAM_BASE_ADDR */
+ rc = goya_iatu_write(hdev, 0x114, lower_32_bits(SRAM_BASE_ADDR));
+ rc |= goya_iatu_write(hdev, 0x118, upper_32_bits(SRAM_BASE_ADDR));
+ rc |= goya_iatu_write(hdev, 0x100, 0);
+ /* Enable + Bar match + match enable */
+ rc |= goya_iatu_write(hdev, 0x104, 0xC0080000);
+
+ /* Inbound Region 1 - Bar 4 - Point to DDR */
+ rc |= goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE);
+
+ /* Outbound Region 0 - Point to Host */
+ rc |= goya_iatu_write(hdev, 0x008, lower_32_bits(HOST_PHYS_BASE));
+ rc |= goya_iatu_write(hdev, 0x00C, upper_32_bits(HOST_PHYS_BASE));
+ rc |= goya_iatu_write(hdev, 0x010,
+ lower_32_bits(HOST_PHYS_BASE + HOST_PHYS_SIZE - 1));
+ rc |= goya_iatu_write(hdev, 0x014, 0);
+ rc |= goya_iatu_write(hdev, 0x018, 0);
+ rc |= goya_iatu_write(hdev, 0x020,
+ upper_32_bits(HOST_PHYS_BASE + HOST_PHYS_SIZE - 1));
+ /* Increase region size */
+ rc |= goya_iatu_write(hdev, 0x000, 0x00002000);
+ /* Enable */
+ rc |= goya_iatu_write(hdev, 0x004, 0x80000000);
+
+ /* Return the DBI window to the default location */
+ rc |= goya_elbi_write(hdev, CFG_BASE + mmPCIE_AUX_DBI, 0);
+ rc |= goya_elbi_write(hdev, CFG_BASE + mmPCIE_AUX_DBI_32, 0);
+
+ if (rc)
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * goya_early_init - GOYA early initialization code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Verify PCI bars
+ * Set DMA masks
+ * PCI controller initialization
+ * Map PCI bars
+ *
+ */
+static int goya_early_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct pci_dev *pdev = hdev->pdev;
+ u32 val;
+ int rc;
+
+ goya_get_fixed_properties(hdev);
+
+ /* Check BAR sizes */
+ if (pci_resource_len(pdev, SRAM_CFG_BAR_ID) != CFG_BAR_SIZE) {
+ dev_err(hdev->dev,
+ "Not " HL_NAME "? BAR %d size %llu, expecting %llu\n",
+ SRAM_CFG_BAR_ID,
+ (unsigned long long) pci_resource_len(pdev,
+ SRAM_CFG_BAR_ID),
+ CFG_BAR_SIZE);
+ return -ENODEV;
+ }
+
+ if (pci_resource_len(pdev, MSIX_BAR_ID) != MSIX_BAR_SIZE) {
+ dev_err(hdev->dev,
+ "Not " HL_NAME "? BAR %d size %llu, expecting %llu\n",
+ MSIX_BAR_ID,
+ (unsigned long long) pci_resource_len(pdev,
+ MSIX_BAR_ID),
+ MSIX_BAR_SIZE);
+ return -ENODEV;
+ }
+
+ prop->dram_pci_bar_size = pci_resource_len(pdev, DDR_BAR_ID);
+
+ /* set DMA mask for GOYA */
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(39));
+ if (rc) {
+ dev_warn(hdev->dev, "Unable to set pci dma mask to 39 bits\n");
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(hdev->dev,
+ "Unable to set pci dma mask to 32 bits\n");
+ return rc;
+ }
+ }
+
+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(39));
+ if (rc) {
+ dev_warn(hdev->dev,
+ "Unable to set pci consistent dma mask to 39 bits\n");
+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(hdev->dev,
+ "Unable to set pci consistent dma mask to 32 bits\n");
+ return rc;
+ }
+ }
+
+ if (hdev->reset_pcilink)
+ goya_reset_link_through_bridge(hdev);
+
+ rc = pci_enable_device_mem(pdev);
+ if (rc) {
+ dev_err(hdev->dev, "can't enable PCI device\n");
+ return rc;
+ }
+
+ pci_set_master(pdev);
+
+ rc = goya_init_iatu(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to initialize iATU\n");
+ goto disable_device;
+ }
+
+ rc = goya_pci_bars_map(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to initialize PCI BARS\n");
+ goto disable_device;
+ }
+
+ if (!hdev->pldm) {
+ val = RREG32(mmPSOC_GLOBAL_CONF_BOOT_STRAP_PINS);
+ if (val & PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_SRIOV_EN_MASK)
+ dev_warn(hdev->dev,
+ "PCI strap is not configured correctly, PCI bus errors may occur\n");
+ }
+
+ return 0;
+
+disable_device:
+ pci_clear_master(pdev);
+ pci_disable_device(pdev);
+
+ return rc;
+}
+
+/*
+ * goya_early_fini - GOYA early finalization code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Unmap PCI bars
+ *
+ */
+static int goya_early_fini(struct hl_device *hdev)
+{
+ goya_pci_bars_unmap(hdev);
+
+ pci_clear_master(hdev->pdev);
+ pci_disable_device(hdev->pdev);
+
+ return 0;
+}
+
+/*
+ * goya_fetch_psoc_frequency - Fetch PSOC frequency values
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static void goya_fetch_psoc_frequency(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+
+ prop->psoc_pci_pll_nr = RREG32(mmPSOC_PCI_PLL_NR);
+ prop->psoc_pci_pll_nf = RREG32(mmPSOC_PCI_PLL_NF);
+ prop->psoc_pci_pll_od = RREG32(mmPSOC_PCI_PLL_OD);
+ prop->psoc_pci_pll_div_factor = RREG32(mmPSOC_PCI_PLL_DIV_FACTOR_1);
+}
+
+/*
+ * goya_late_init - GOYA late initialization code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Get ArmCP info and send message to CPU to enable PCI access
+ */
+static int goya_late_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct goya_device *goya = hdev->asic_specific;
+ int rc;
+
+ rc = goya->armcp_info_get(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to get armcp info\n");
+ return rc;
+ }
+
+ /* Now that we have the DRAM size in ASIC prop, we need to check
+ * its size and configure the DMA_IF DDR wrap protection (which is in
+ * the MMU block) accordingly. The value is the log2 of the DRAM size
+ */
+ WREG32(mmMMU_LOG2_DDR_SIZE, ilog2(prop->dram_size));
+
+ rc = goya_send_pci_access_msg(hdev, ARMCP_PACKET_ENABLE_PCI_ACCESS);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to enable PCI access from CPU\n");
+ return rc;
+ }
+
+ WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
+ GOYA_ASYNC_EVENT_ID_INTS_REGISTER);
+
+ goya_fetch_psoc_frequency(hdev);
+
+ rc = goya_mmu_clear_pgt_range(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to clear MMU page tables range\n");
+ goto disable_pci_access;
+ }
+
+ rc = goya_mmu_set_dram_default_page(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to set DRAM default page\n");
+ goto disable_pci_access;
+ }
+
+ return 0;
+
+disable_pci_access:
+ goya_send_pci_access_msg(hdev, ARMCP_PACKET_DISABLE_PCI_ACCESS);
+
+ return rc;
+}
+
+/*
+ * goya_late_fini - GOYA late tear-down code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Free sensors allocated structures
+ */
+void goya_late_fini(struct hl_device *hdev)
+{
+ const struct hwmon_channel_info **channel_info_arr;
+ int i = 0;
+
+ if (!hdev->hl_chip_info->info)
+ return;
+
+ channel_info_arr = hdev->hl_chip_info->info;
+
+ while (channel_info_arr[i]) {
+ kfree(channel_info_arr[i]->config);
+ kfree(channel_info_arr[i]);
+ i++;
+ }
+
+ kfree(channel_info_arr);
+
+ hdev->hl_chip_info->info = NULL;
+}
+
+/*
+ * goya_sw_init - Goya software initialization code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static int goya_sw_init(struct hl_device *hdev)
+{
+ struct goya_device *goya;
+ int rc;
+
+ /* Allocate device structure */
+ goya = kzalloc(sizeof(*goya), GFP_KERNEL);
+ if (!goya)
+ return -ENOMEM;
+
+ goya->test_cpu_queue = goya_test_cpu_queue;
+ goya->armcp_info_get = goya_armcp_info_get;
+
+ /* according to goya_init_iatu */
+ goya->ddr_bar_cur_addr = DRAM_PHYS_BASE;
+
+ goya->mme_clk = GOYA_PLL_FREQ_LOW;
+ goya->tpc_clk = GOYA_PLL_FREQ_LOW;
+ goya->ic_clk = GOYA_PLL_FREQ_LOW;
+
+ hdev->asic_specific = goya;
+
+ /* Create DMA pool for small allocations */
+ hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
+ &hdev->pdev->dev, GOYA_DMA_POOL_BLK_SIZE, 8, 0);
+ if (!hdev->dma_pool) {
+ dev_err(hdev->dev, "failed to create DMA pool\n");
+ rc = -ENOMEM;
+ goto free_goya_device;
+ }
+
+ hdev->cpu_accessible_dma_mem =
+ hdev->asic_funcs->dma_alloc_coherent(hdev,
+ CPU_ACCESSIBLE_MEM_SIZE,
+ &hdev->cpu_accessible_dma_address,
+ GFP_KERNEL | __GFP_ZERO);
+
+ if (!hdev->cpu_accessible_dma_mem) {
+ dev_err(hdev->dev,
+ "failed to allocate %d of dma memory for CPU accessible memory space\n",
+ CPU_ACCESSIBLE_MEM_SIZE);
+ rc = -ENOMEM;
+ goto free_dma_pool;
+ }
+
+ hdev->cpu_accessible_dma_pool = gen_pool_create(CPU_PKT_SHIFT, -1);
+ if (!hdev->cpu_accessible_dma_pool) {
+ dev_err(hdev->dev,
+ "Failed to create CPU accessible DMA pool\n");
+ rc = -ENOMEM;
+ goto free_cpu_pq_dma_mem;
+ }
+
+ rc = gen_pool_add(hdev->cpu_accessible_dma_pool,
+ (uintptr_t) hdev->cpu_accessible_dma_mem,
+ CPU_ACCESSIBLE_MEM_SIZE, -1);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to add memory to CPU accessible DMA pool\n");
+ rc = -EFAULT;
+ goto free_cpu_pq_pool;
+ }
+
+ spin_lock_init(&goya->hw_queues_lock);
+
+ return 0;
+
+free_cpu_pq_pool:
+ gen_pool_destroy(hdev->cpu_accessible_dma_pool);
+free_cpu_pq_dma_mem:
+ hdev->asic_funcs->dma_free_coherent(hdev, CPU_ACCESSIBLE_MEM_SIZE,
+ hdev->cpu_accessible_dma_mem,
+ hdev->cpu_accessible_dma_address);
+free_dma_pool:
+ dma_pool_destroy(hdev->dma_pool);
+free_goya_device:
+ kfree(goya);
+
+ return rc;
+}
+
+/*
+ * goya_sw_fini - Goya software tear-down code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static int goya_sw_fini(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ gen_pool_destroy(hdev->cpu_accessible_dma_pool);
+
+ hdev->asic_funcs->dma_free_coherent(hdev, CPU_ACCESSIBLE_MEM_SIZE,
+ hdev->cpu_accessible_dma_mem,
+ hdev->cpu_accessible_dma_address);
+
+ dma_pool_destroy(hdev->dma_pool);
+
+ kfree(goya);
+
+ return 0;
+}
+
+static void goya_init_dma_qman(struct hl_device *hdev, int dma_id,
+ dma_addr_t bus_address)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 mtr_base_lo, mtr_base_hi;
+ u32 so_base_lo, so_base_hi;
+ u32 gic_base_lo, gic_base_hi;
+ u32 reg_off = dma_id * (mmDMA_QM_1_PQ_PI - mmDMA_QM_0_PQ_PI);
+
+ mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ WREG32(mmDMA_QM_0_PQ_BASE_LO + reg_off, lower_32_bits(bus_address));
+ WREG32(mmDMA_QM_0_PQ_BASE_HI + reg_off, upper_32_bits(bus_address));
+
+ WREG32(mmDMA_QM_0_PQ_SIZE + reg_off, ilog2(HL_QUEUE_LENGTH));
+ WREG32(mmDMA_QM_0_PQ_PI + reg_off, 0);
+ WREG32(mmDMA_QM_0_PQ_CI + reg_off, 0);
+
+ WREG32(mmDMA_QM_0_CP_MSG_BASE0_ADDR_LO + reg_off, mtr_base_lo);
+ WREG32(mmDMA_QM_0_CP_MSG_BASE0_ADDR_HI + reg_off, mtr_base_hi);
+ WREG32(mmDMA_QM_0_CP_MSG_BASE1_ADDR_LO + reg_off, so_base_lo);
+ WREG32(mmDMA_QM_0_CP_MSG_BASE1_ADDR_HI + reg_off, so_base_hi);
+ WREG32(mmDMA_QM_0_GLBL_ERR_ADDR_LO + reg_off, gic_base_lo);
+ WREG32(mmDMA_QM_0_GLBL_ERR_ADDR_HI + reg_off, gic_base_hi);
+ WREG32(mmDMA_QM_0_GLBL_ERR_WDATA + reg_off,
+ GOYA_ASYNC_EVENT_ID_DMA0_QM + dma_id);
+
+ /* PQ has buffer of 2 cache lines, while CQ has 8 lines */
+ WREG32(mmDMA_QM_0_PQ_CFG1 + reg_off, 0x00020002);
+ WREG32(mmDMA_QM_0_CQ_CFG1 + reg_off, 0x00080008);
+
+ if (goya->hw_cap_initialized & HW_CAP_MMU)
+ WREG32(mmDMA_QM_0_GLBL_PROT + reg_off, QMAN_DMA_PARTLY_TRUSTED);
+ else
+ WREG32(mmDMA_QM_0_GLBL_PROT + reg_off, QMAN_DMA_FULLY_TRUSTED);
+
+ WREG32(mmDMA_QM_0_GLBL_ERR_CFG + reg_off, QMAN_DMA_ERR_MSG_EN);
+ WREG32(mmDMA_QM_0_GLBL_CFG0 + reg_off, QMAN_DMA_ENABLE);
+}
+
+static void goya_init_dma_ch(struct hl_device *hdev, int dma_id)
+{
+ u32 gic_base_lo, gic_base_hi;
+ u64 sob_addr;
+ u32 reg_off = dma_id * (mmDMA_CH_1_CFG1 - mmDMA_CH_0_CFG1);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ WREG32(mmDMA_CH_0_ERRMSG_ADDR_LO + reg_off, gic_base_lo);
+ WREG32(mmDMA_CH_0_ERRMSG_ADDR_HI + reg_off, gic_base_hi);
+ WREG32(mmDMA_CH_0_ERRMSG_WDATA + reg_off,
+ GOYA_ASYNC_EVENT_ID_DMA0_CH + dma_id);
+
+ if (dma_id)
+ sob_addr = CFG_BASE + mmSYNC_MNGR_SOB_OBJ_1000 +
+ (dma_id - 1) * 4;
+ else
+ sob_addr = CFG_BASE + mmSYNC_MNGR_SOB_OBJ_1007;
+
+ WREG32(mmDMA_CH_0_WR_COMP_ADDR_LO + reg_off, lower_32_bits(sob_addr));
+ WREG32(mmDMA_CH_0_WR_COMP_ADDR_HI + reg_off, upper_32_bits(sob_addr));
+ WREG32(mmDMA_CH_0_WR_COMP_WDATA + reg_off, 0x80000001);
+}
+
+/*
+ * goya_init_dma_qmans - Initialize QMAN DMA registers
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Initialize the H/W registers of the QMAN DMA channels
+ *
+ */
+static void goya_init_dma_qmans(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct hl_hw_queue *q;
+ dma_addr_t bus_address;
+ int i;
+
+ if (goya->hw_cap_initialized & HW_CAP_DMA)
+ return;
+
+ q = &hdev->kernel_queues[0];
+
+ for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++, q++) {
+ bus_address = q->bus_address +
+ hdev->asic_prop.host_phys_base_address;
+
+ goya_init_dma_qman(hdev, i, bus_address);
+ goya_init_dma_ch(hdev, i);
+ }
+
+ goya->hw_cap_initialized |= HW_CAP_DMA;
+}
+
+/*
+ * goya_disable_external_queues - Disable external queues
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static void goya_disable_external_queues(struct hl_device *hdev)
+{
+ WREG32(mmDMA_QM_0_GLBL_CFG0, 0);
+ WREG32(mmDMA_QM_1_GLBL_CFG0, 0);
+ WREG32(mmDMA_QM_2_GLBL_CFG0, 0);
+ WREG32(mmDMA_QM_3_GLBL_CFG0, 0);
+ WREG32(mmDMA_QM_4_GLBL_CFG0, 0);
+}
+
+static int goya_stop_queue(struct hl_device *hdev, u32 cfg_reg,
+ u32 cp_sts_reg, u32 glbl_sts0_reg)
+{
+ int rc;
+ u32 status;
+
+ /* use the values of TPC0 as they are all the same*/
+
+ WREG32(cfg_reg, 1 << TPC0_QM_GLBL_CFG1_CP_STOP_SHIFT);
+
+ status = RREG32(cp_sts_reg);
+ if (status & TPC0_QM_CP_STS_FENCE_IN_PROGRESS_MASK) {
+ rc = hl_poll_timeout(
+ hdev,
+ cp_sts_reg,
+ status,
+ !(status & TPC0_QM_CP_STS_FENCE_IN_PROGRESS_MASK),
+ 1000,
+ QMAN_FENCE_TIMEOUT_USEC);
+
+ /* if QMAN is stuck in fence no need to check for stop */
+ if (rc)
+ return 0;
+ }
+
+ rc = hl_poll_timeout(
+ hdev,
+ glbl_sts0_reg,
+ status,
+ (status & TPC0_QM_GLBL_STS0_CP_IS_STOP_MASK),
+ 1000,
+ QMAN_STOP_TIMEOUT_USEC);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Timeout while waiting for QMAN to stop\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * goya_stop_external_queues - Stop external queues
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Returns 0 on success
+ *
+ */
+static int goya_stop_external_queues(struct hl_device *hdev)
+{
+ int rc, retval = 0;
+
+ rc = goya_stop_queue(hdev,
+ mmDMA_QM_0_GLBL_CFG1,
+ mmDMA_QM_0_CP_STS,
+ mmDMA_QM_0_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop DMA QMAN 0\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmDMA_QM_1_GLBL_CFG1,
+ mmDMA_QM_1_CP_STS,
+ mmDMA_QM_1_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop DMA QMAN 1\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmDMA_QM_2_GLBL_CFG1,
+ mmDMA_QM_2_CP_STS,
+ mmDMA_QM_2_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop DMA QMAN 2\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmDMA_QM_3_GLBL_CFG1,
+ mmDMA_QM_3_CP_STS,
+ mmDMA_QM_3_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop DMA QMAN 3\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmDMA_QM_4_GLBL_CFG1,
+ mmDMA_QM_4_CP_STS,
+ mmDMA_QM_4_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop DMA QMAN 4\n");
+ retval = -EIO;
+ }
+
+ return retval;
+}
+
+static void goya_resume_external_queues(struct hl_device *hdev)
+{
+ WREG32(mmDMA_QM_0_GLBL_CFG1, 0);
+ WREG32(mmDMA_QM_1_GLBL_CFG1, 0);
+ WREG32(mmDMA_QM_2_GLBL_CFG1, 0);
+ WREG32(mmDMA_QM_3_GLBL_CFG1, 0);
+ WREG32(mmDMA_QM_4_GLBL_CFG1, 0);
+}
+
+/*
+ * goya_init_cpu_queues - Initialize PQ/CQ/EQ of CPU
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Returns 0 on success
+ *
+ */
+static int goya_init_cpu_queues(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct hl_eq *eq;
+ dma_addr_t bus_address;
+ u32 status;
+ struct hl_hw_queue *cpu_pq = &hdev->kernel_queues[GOYA_QUEUE_ID_CPU_PQ];
+ int err;
+
+ if (!hdev->cpu_queues_enable)
+ return 0;
+
+ if (goya->hw_cap_initialized & HW_CAP_CPU_Q)
+ return 0;
+
+ eq = &hdev->event_queue;
+
+ bus_address = cpu_pq->bus_address +
+ hdev->asic_prop.host_phys_base_address;
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_0, lower_32_bits(bus_address));
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_1, upper_32_bits(bus_address));
+
+ bus_address = eq->bus_address + hdev->asic_prop.host_phys_base_address;
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_2, lower_32_bits(bus_address));
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_3, upper_32_bits(bus_address));
+
+ bus_address = hdev->cpu_accessible_dma_address +
+ hdev->asic_prop.host_phys_base_address;
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_8, lower_32_bits(bus_address));
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_9, upper_32_bits(bus_address));
+
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_5, HL_QUEUE_SIZE_IN_BYTES);
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_4, HL_EQ_SIZE_IN_BYTES);
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_10, CPU_ACCESSIBLE_MEM_SIZE);
+
+ /* Used for EQ CI */
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_6, 0);
+
+ WREG32(mmCPU_IF_PF_PQ_PI, 0);
+
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_7, PQ_INIT_STATUS_READY_FOR_CP);
+
+ WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
+ GOYA_ASYNC_EVENT_ID_PI_UPDATE);
+
+ err = hl_poll_timeout(
+ hdev,
+ mmPSOC_GLOBAL_CONF_SCRATCHPAD_7,
+ status,
+ (status == PQ_INIT_STATUS_READY_FOR_HOST),
+ 1000,
+ GOYA_CPU_TIMEOUT_USEC);
+
+ if (err) {
+ dev_err(hdev->dev,
+ "Failed to communicate with ARM CPU (ArmCP timeout)\n");
+ return -EIO;
+ }
+
+ goya->hw_cap_initialized |= HW_CAP_CPU_Q;
+ return 0;
+}
+
+static void goya_set_pll_refclk(struct hl_device *hdev)
+{
+ WREG32(mmCPU_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmCPU_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmCPU_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmCPU_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmIC_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmIC_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmIC_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmIC_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmMC_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmMC_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmMC_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmMC_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmPSOC_MME_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmPSOC_MME_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmPSOC_MME_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmPSOC_MME_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmPSOC_PCI_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmPSOC_PCI_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmPSOC_PCI_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmPSOC_PCI_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmPSOC_EMMC_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmPSOC_EMMC_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmPSOC_EMMC_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmPSOC_EMMC_PLL_DIV_SEL_3, 0x0);
+
+ WREG32(mmTPC_PLL_DIV_SEL_0, 0x0);
+ WREG32(mmTPC_PLL_DIV_SEL_1, 0x0);
+ WREG32(mmTPC_PLL_DIV_SEL_2, 0x0);
+ WREG32(mmTPC_PLL_DIV_SEL_3, 0x0);
+}
+
+static void goya_disable_clk_rlx(struct hl_device *hdev)
+{
+ WREG32(mmPSOC_MME_PLL_CLK_RLX_0, 0x100010);
+ WREG32(mmIC_PLL_CLK_RLX_0, 0x100010);
+}
+
+static void _goya_tpc_mbist_workaround(struct hl_device *hdev, u8 tpc_id)
+{
+ u64 tpc_eml_address;
+ u32 val, tpc_offset, tpc_eml_offset, tpc_slm_offset;
+ int err, slm_index;
+
+ tpc_offset = tpc_id * 0x40000;
+ tpc_eml_offset = tpc_id * 0x200000;
+ tpc_eml_address = (mmTPC0_EML_CFG_BASE + tpc_eml_offset - CFG_BASE);
+ tpc_slm_offset = tpc_eml_address + 0x100000;
+
+ /*
+ * Workaround for Bug H2 #2443 :
+ * "TPC SB is not initialized on chip reset"
+ */
+
+ val = RREG32(mmTPC0_CFG_FUNC_MBIST_CNTRL + tpc_offset);
+ if (val & TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_ACTIVE_MASK)
+ dev_warn(hdev->dev, "TPC%d MBIST ACTIVE is not cleared\n",
+ tpc_id);
+
+ WREG32(mmTPC0_CFG_FUNC_MBIST_PAT + tpc_offset, val & 0xFFFFF000);
+
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_0 + tpc_offset, 0x37FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_1 + tpc_offset, 0x303F);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_2 + tpc_offset, 0x71FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_3 + tpc_offset, 0x71FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_4 + tpc_offset, 0x70FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_5 + tpc_offset, 0x70FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_6 + tpc_offset, 0x70FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_7 + tpc_offset, 0x70FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_8 + tpc_offset, 0x70FF);
+ WREG32(mmTPC0_CFG_FUNC_MBIST_MEM_9 + tpc_offset, 0x70FF);
+
+ WREG32_OR(mmTPC0_CFG_FUNC_MBIST_CNTRL + tpc_offset,
+ 1 << TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_START_SHIFT);
+
+ err = hl_poll_timeout(
+ hdev,
+ mmTPC0_CFG_FUNC_MBIST_CNTRL + tpc_offset,
+ val,
+ (val & TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_DONE_MASK),
+ 1000,
+ HL_DEVICE_TIMEOUT_USEC);
+
+ if (err)
+ dev_err(hdev->dev,
+ "Timeout while waiting for TPC%d MBIST DONE\n", tpc_id);
+
+ WREG32_OR(mmTPC0_EML_CFG_DBG_CNT + tpc_eml_offset,
+ 1 << TPC0_EML_CFG_DBG_CNT_CORE_RST_SHIFT);
+
+ msleep(GOYA_RESET_WAIT_MSEC);
+
+ WREG32_AND(mmTPC0_EML_CFG_DBG_CNT + tpc_eml_offset,
+ ~(1 << TPC0_EML_CFG_DBG_CNT_CORE_RST_SHIFT));
+
+ msleep(GOYA_RESET_WAIT_MSEC);
+
+ for (slm_index = 0 ; slm_index < 256 ; slm_index++)
+ WREG32(tpc_slm_offset + (slm_index << 2), 0);
+
+ val = RREG32(tpc_slm_offset);
+}
+
+static void goya_tpc_mbist_workaround(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int i;
+
+ if (hdev->pldm)
+ return;
+
+ if (goya->hw_cap_initialized & HW_CAP_TPC_MBIST)
+ return;
+
+ /* Workaround for H2 #2443 */
+
+ for (i = 0 ; i < TPC_MAX_NUM ; i++)
+ _goya_tpc_mbist_workaround(hdev, i);
+
+ goya->hw_cap_initialized |= HW_CAP_TPC_MBIST;
+}
+
+/*
+ * goya_init_golden_registers - Initialize golden registers
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Initialize the H/W registers of the device
+ *
+ */
+static void goya_init_golden_registers(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 polynom[10], tpc_intr_mask, offset;
+ int i;
+
+ if (goya->hw_cap_initialized & HW_CAP_GOLDEN)
+ return;
+
+ polynom[0] = 0x00020080;
+ polynom[1] = 0x00401000;
+ polynom[2] = 0x00200800;
+ polynom[3] = 0x00002000;
+ polynom[4] = 0x00080200;
+ polynom[5] = 0x00040100;
+ polynom[6] = 0x00100400;
+ polynom[7] = 0x00004000;
+ polynom[8] = 0x00010000;
+ polynom[9] = 0x00008000;
+
+ /* Mask all arithmetic interrupts from TPC */
+ tpc_intr_mask = 0x7FFF;
+
+ for (i = 0, offset = 0 ; i < 6 ; i++, offset += 0x20000) {
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_RD_RQ_L_ARB + offset, 0x302);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_RD_RQ_L_ARB + offset, 0x302);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_RD_RQ_L_ARB + offset, 0x302);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_RD_RQ_L_ARB + offset, 0x302);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_RD_RQ_L_ARB + offset, 0x302);
+
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_DATA_L_ARB + offset, 0x204);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_DATA_L_ARB + offset, 0x204);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_DATA_L_ARB + offset, 0x204);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_DATA_L_ARB + offset, 0x204);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_DATA_L_ARB + offset, 0x204);
+
+
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_DATA_E_ARB + offset, 0x206);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_DATA_E_ARB + offset, 0x206);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_DATA_E_ARB + offset, 0x206);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_DATA_E_ARB + offset, 0x207);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_DATA_E_ARB + offset, 0x207);
+
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_DATA_W_ARB + offset, 0x207);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_DATA_W_ARB + offset, 0x207);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_DATA_W_ARB + offset, 0x206);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_DATA_W_ARB + offset, 0x206);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_DATA_W_ARB + offset, 0x206);
+
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_WR_RS_E_ARB + offset, 0x101);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_WR_RS_E_ARB + offset, 0x102);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_WR_RS_E_ARB + offset, 0x103);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_WR_RS_E_ARB + offset, 0x104);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_WR_RS_E_ARB + offset, 0x105);
+
+ WREG32(mmSRAM_Y0_X0_RTR_HBW_WR_RS_W_ARB + offset, 0x105);
+ WREG32(mmSRAM_Y0_X1_RTR_HBW_WR_RS_W_ARB + offset, 0x104);
+ WREG32(mmSRAM_Y0_X2_RTR_HBW_WR_RS_W_ARB + offset, 0x103);
+ WREG32(mmSRAM_Y0_X3_RTR_HBW_WR_RS_W_ARB + offset, 0x102);
+ WREG32(mmSRAM_Y0_X4_RTR_HBW_WR_RS_W_ARB + offset, 0x101);
+ }
+
+ WREG32(mmMME_STORE_MAX_CREDIT, 0x21);
+ WREG32(mmMME_AGU, 0x0f0f0f10);
+ WREG32(mmMME_SEI_MASK, ~0x0);
+
+ WREG32(mmMME6_RTR_HBW_RD_RQ_N_ARB, 0x01010101);
+ WREG32(mmMME5_RTR_HBW_RD_RQ_N_ARB, 0x01040101);
+ WREG32(mmMME4_RTR_HBW_RD_RQ_N_ARB, 0x01030101);
+ WREG32(mmMME3_RTR_HBW_RD_RQ_N_ARB, 0x01020101);
+ WREG32(mmMME2_RTR_HBW_RD_RQ_N_ARB, 0x01010101);
+ WREG32(mmMME1_RTR_HBW_RD_RQ_N_ARB, 0x07010701);
+ WREG32(mmMME6_RTR_HBW_RD_RQ_S_ARB, 0x04010401);
+ WREG32(mmMME5_RTR_HBW_RD_RQ_S_ARB, 0x04050401);
+ WREG32(mmMME4_RTR_HBW_RD_RQ_S_ARB, 0x03070301);
+ WREG32(mmMME3_RTR_HBW_RD_RQ_S_ARB, 0x01030101);
+ WREG32(mmMME2_RTR_HBW_RD_RQ_S_ARB, 0x01040101);
+ WREG32(mmMME1_RTR_HBW_RD_RQ_S_ARB, 0x01050105);
+ WREG32(mmMME6_RTR_HBW_RD_RQ_W_ARB, 0x01010501);
+ WREG32(mmMME5_RTR_HBW_RD_RQ_W_ARB, 0x01010501);
+ WREG32(mmMME4_RTR_HBW_RD_RQ_W_ARB, 0x01040301);
+ WREG32(mmMME3_RTR_HBW_RD_RQ_W_ARB, 0x01030401);
+ WREG32(mmMME2_RTR_HBW_RD_RQ_W_ARB, 0x01040101);
+ WREG32(mmMME1_RTR_HBW_RD_RQ_W_ARB, 0x01050101);
+ WREG32(mmMME6_RTR_HBW_WR_RQ_N_ARB, 0x02020202);
+ WREG32(mmMME5_RTR_HBW_WR_RQ_N_ARB, 0x01070101);
+ WREG32(mmMME4_RTR_HBW_WR_RQ_N_ARB, 0x02020201);
+ WREG32(mmMME3_RTR_HBW_WR_RQ_N_ARB, 0x07020701);
+ WREG32(mmMME2_RTR_HBW_WR_RQ_N_ARB, 0x01020101);
+ WREG32(mmMME1_RTR_HBW_WR_RQ_S_ARB, 0x01010101);
+ WREG32(mmMME6_RTR_HBW_WR_RQ_S_ARB, 0x01070101);
+ WREG32(mmMME5_RTR_HBW_WR_RQ_S_ARB, 0x01070101);
+ WREG32(mmMME4_RTR_HBW_WR_RQ_S_ARB, 0x07020701);
+ WREG32(mmMME3_RTR_HBW_WR_RQ_S_ARB, 0x02020201);
+ WREG32(mmMME2_RTR_HBW_WR_RQ_S_ARB, 0x01070101);
+ WREG32(mmMME1_RTR_HBW_WR_RQ_S_ARB, 0x01020102);
+ WREG32(mmMME6_RTR_HBW_WR_RQ_W_ARB, 0x01020701);
+ WREG32(mmMME5_RTR_HBW_WR_RQ_W_ARB, 0x01020701);
+ WREG32(mmMME4_RTR_HBW_WR_RQ_W_ARB, 0x07020707);
+ WREG32(mmMME3_RTR_HBW_WR_RQ_W_ARB, 0x01020201);
+ WREG32(mmMME2_RTR_HBW_WR_RQ_W_ARB, 0x01070201);
+ WREG32(mmMME1_RTR_HBW_WR_RQ_W_ARB, 0x01070201);
+ WREG32(mmMME6_RTR_HBW_RD_RS_N_ARB, 0x01070102);
+ WREG32(mmMME5_RTR_HBW_RD_RS_N_ARB, 0x01070102);
+ WREG32(mmMME4_RTR_HBW_RD_RS_N_ARB, 0x01060102);
+ WREG32(mmMME3_RTR_HBW_RD_RS_N_ARB, 0x01040102);
+ WREG32(mmMME2_RTR_HBW_RD_RS_N_ARB, 0x01020102);
+ WREG32(mmMME1_RTR_HBW_RD_RS_N_ARB, 0x01020107);
+ WREG32(mmMME6_RTR_HBW_RD_RS_S_ARB, 0x01020106);
+ WREG32(mmMME5_RTR_HBW_RD_RS_S_ARB, 0x01020102);
+ WREG32(mmMME4_RTR_HBW_RD_RS_S_ARB, 0x01040102);
+ WREG32(mmMME3_RTR_HBW_RD_RS_S_ARB, 0x01060102);
+ WREG32(mmMME2_RTR_HBW_RD_RS_S_ARB, 0x01070102);
+ WREG32(mmMME1_RTR_HBW_RD_RS_S_ARB, 0x01070102);
+ WREG32(mmMME6_RTR_HBW_RD_RS_E_ARB, 0x01020702);
+ WREG32(mmMME5_RTR_HBW_RD_RS_E_ARB, 0x01020702);
+ WREG32(mmMME4_RTR_HBW_RD_RS_E_ARB, 0x01040602);
+ WREG32(mmMME3_RTR_HBW_RD_RS_E_ARB, 0x01060402);
+ WREG32(mmMME2_RTR_HBW_RD_RS_E_ARB, 0x01070202);
+ WREG32(mmMME1_RTR_HBW_RD_RS_E_ARB, 0x01070102);
+ WREG32(mmMME6_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME5_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME4_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME3_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME2_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME1_RTR_HBW_RD_RS_W_ARB, 0x01060401);
+ WREG32(mmMME6_RTR_HBW_WR_RS_N_ARB, 0x01050101);
+ WREG32(mmMME5_RTR_HBW_WR_RS_N_ARB, 0x01040101);
+ WREG32(mmMME4_RTR_HBW_WR_RS_N_ARB, 0x01030101);
+ WREG32(mmMME3_RTR_HBW_WR_RS_N_ARB, 0x01020101);
+ WREG32(mmMME2_RTR_HBW_WR_RS_N_ARB, 0x01010101);
+ WREG32(mmMME1_RTR_HBW_WR_RS_N_ARB, 0x01010107);
+ WREG32(mmMME6_RTR_HBW_WR_RS_S_ARB, 0x01010107);
+ WREG32(mmMME5_RTR_HBW_WR_RS_S_ARB, 0x01010101);
+ WREG32(mmMME4_RTR_HBW_WR_RS_S_ARB, 0x01020101);
+ WREG32(mmMME3_RTR_HBW_WR_RS_S_ARB, 0x01030101);
+ WREG32(mmMME2_RTR_HBW_WR_RS_S_ARB, 0x01040101);
+ WREG32(mmMME1_RTR_HBW_WR_RS_S_ARB, 0x01050101);
+ WREG32(mmMME6_RTR_HBW_WR_RS_E_ARB, 0x01010501);
+ WREG32(mmMME5_RTR_HBW_WR_RS_E_ARB, 0x01010501);
+ WREG32(mmMME4_RTR_HBW_WR_RS_E_ARB, 0x01040301);
+ WREG32(mmMME3_RTR_HBW_WR_RS_E_ARB, 0x01030401);
+ WREG32(mmMME2_RTR_HBW_WR_RS_E_ARB, 0x01040101);
+ WREG32(mmMME1_RTR_HBW_WR_RS_E_ARB, 0x01050101);
+ WREG32(mmMME6_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+ WREG32(mmMME5_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+ WREG32(mmMME4_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+ WREG32(mmMME3_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+ WREG32(mmMME2_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+ WREG32(mmMME1_RTR_HBW_WR_RS_W_ARB, 0x01010101);
+
+ WREG32(mmTPC1_RTR_HBW_RD_RQ_N_ARB, 0x01010101);
+ WREG32(mmTPC1_RTR_HBW_RD_RQ_S_ARB, 0x01010101);
+ WREG32(mmTPC1_RTR_HBW_RD_RQ_E_ARB, 0x01060101);
+ WREG32(mmTPC1_RTR_HBW_WR_RQ_N_ARB, 0x02020102);
+ WREG32(mmTPC1_RTR_HBW_WR_RQ_S_ARB, 0x01010101);
+ WREG32(mmTPC1_RTR_HBW_WR_RQ_E_ARB, 0x02070202);
+ WREG32(mmTPC1_RTR_HBW_RD_RS_N_ARB, 0x01020201);
+ WREG32(mmTPC1_RTR_HBW_RD_RS_S_ARB, 0x01070201);
+ WREG32(mmTPC1_RTR_HBW_RD_RS_W_ARB, 0x01070202);
+ WREG32(mmTPC1_RTR_HBW_WR_RS_N_ARB, 0x01010101);
+ WREG32(mmTPC1_RTR_HBW_WR_RS_S_ARB, 0x01050101);
+ WREG32(mmTPC1_RTR_HBW_WR_RS_W_ARB, 0x01050101);
+
+ WREG32(mmTPC2_RTR_HBW_RD_RQ_N_ARB, 0x01020101);
+ WREG32(mmTPC2_RTR_HBW_RD_RQ_S_ARB, 0x01050101);
+ WREG32(mmTPC2_RTR_HBW_RD_RQ_E_ARB, 0x01010201);
+ WREG32(mmTPC2_RTR_HBW_WR_RQ_N_ARB, 0x02040102);
+ WREG32(mmTPC2_RTR_HBW_WR_RQ_S_ARB, 0x01050101);
+ WREG32(mmTPC2_RTR_HBW_WR_RQ_E_ARB, 0x02060202);
+ WREG32(mmTPC2_RTR_HBW_RD_RS_N_ARB, 0x01020201);
+ WREG32(mmTPC2_RTR_HBW_RD_RS_S_ARB, 0x01070201);
+ WREG32(mmTPC2_RTR_HBW_RD_RS_W_ARB, 0x01070202);
+ WREG32(mmTPC2_RTR_HBW_WR_RS_N_ARB, 0x01010101);
+ WREG32(mmTPC2_RTR_HBW_WR_RS_S_ARB, 0x01040101);
+ WREG32(mmTPC2_RTR_HBW_WR_RS_W_ARB, 0x01040101);
+
+ WREG32(mmTPC3_RTR_HBW_RD_RQ_N_ARB, 0x01030101);
+ WREG32(mmTPC3_RTR_HBW_RD_RQ_S_ARB, 0x01040101);
+ WREG32(mmTPC3_RTR_HBW_RD_RQ_E_ARB, 0x01040301);
+ WREG32(mmTPC3_RTR_HBW_WR_RQ_N_ARB, 0x02060102);
+ WREG32(mmTPC3_RTR_HBW_WR_RQ_S_ARB, 0x01040101);
+ WREG32(mmTPC3_RTR_HBW_WR_RQ_E_ARB, 0x01040301);
+ WREG32(mmTPC3_RTR_HBW_RD_RS_N_ARB, 0x01040201);
+ WREG32(mmTPC3_RTR_HBW_RD_RS_S_ARB, 0x01060201);
+ WREG32(mmTPC3_RTR_HBW_RD_RS_W_ARB, 0x01060402);
+ WREG32(mmTPC3_RTR_HBW_WR_RS_N_ARB, 0x01020101);
+ WREG32(mmTPC3_RTR_HBW_WR_RS_S_ARB, 0x01030101);
+ WREG32(mmTPC3_RTR_HBW_WR_RS_W_ARB, 0x01030401);
+
+ WREG32(mmTPC4_RTR_HBW_RD_RQ_N_ARB, 0x01040101);
+ WREG32(mmTPC4_RTR_HBW_RD_RQ_S_ARB, 0x01030101);
+ WREG32(mmTPC4_RTR_HBW_RD_RQ_E_ARB, 0x01030401);
+ WREG32(mmTPC4_RTR_HBW_WR_RQ_N_ARB, 0x02070102);
+ WREG32(mmTPC4_RTR_HBW_WR_RQ_S_ARB, 0x01030101);
+ WREG32(mmTPC4_RTR_HBW_WR_RQ_E_ARB, 0x02060702);
+ WREG32(mmTPC4_RTR_HBW_RD_RS_N_ARB, 0x01060201);
+ WREG32(mmTPC4_RTR_HBW_RD_RS_S_ARB, 0x01040201);
+ WREG32(mmTPC4_RTR_HBW_RD_RS_W_ARB, 0x01040602);
+ WREG32(mmTPC4_RTR_HBW_WR_RS_N_ARB, 0x01030101);
+ WREG32(mmTPC4_RTR_HBW_WR_RS_S_ARB, 0x01020101);
+ WREG32(mmTPC4_RTR_HBW_WR_RS_W_ARB, 0x01040301);
+
+ WREG32(mmTPC5_RTR_HBW_RD_RQ_N_ARB, 0x01050101);
+ WREG32(mmTPC5_RTR_HBW_RD_RQ_S_ARB, 0x01020101);
+ WREG32(mmTPC5_RTR_HBW_RD_RQ_E_ARB, 0x01200501);
+ WREG32(mmTPC5_RTR_HBW_WR_RQ_N_ARB, 0x02070102);
+ WREG32(mmTPC5_RTR_HBW_WR_RQ_S_ARB, 0x01020101);
+ WREG32(mmTPC5_RTR_HBW_WR_RQ_E_ARB, 0x02020602);
+ WREG32(mmTPC5_RTR_HBW_RD_RS_N_ARB, 0x01070201);
+ WREG32(mmTPC5_RTR_HBW_RD_RS_S_ARB, 0x01020201);
+ WREG32(mmTPC5_RTR_HBW_RD_RS_W_ARB, 0x01020702);
+ WREG32(mmTPC5_RTR_HBW_WR_RS_N_ARB, 0x01040101);
+ WREG32(mmTPC5_RTR_HBW_WR_RS_S_ARB, 0x01010101);
+ WREG32(mmTPC5_RTR_HBW_WR_RS_W_ARB, 0x01010501);
+
+ WREG32(mmTPC6_RTR_HBW_RD_RQ_N_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_RD_RQ_S_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_RD_RQ_E_ARB, 0x01010601);
+ WREG32(mmTPC6_RTR_HBW_WR_RQ_N_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_WR_RQ_S_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_WR_RQ_E_ARB, 0x02020702);
+ WREG32(mmTPC6_RTR_HBW_RD_RS_N_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_RD_RS_S_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_RD_RS_W_ARB, 0x01020702);
+ WREG32(mmTPC6_RTR_HBW_WR_RS_N_ARB, 0x01050101);
+ WREG32(mmTPC6_RTR_HBW_WR_RS_S_ARB, 0x01010101);
+ WREG32(mmTPC6_RTR_HBW_WR_RS_W_ARB, 0x01010501);
+
+ for (i = 0, offset = 0 ; i < 10 ; i++, offset += 4) {
+ WREG32(mmMME1_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmMME2_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmMME3_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmMME4_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmMME5_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmMME6_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+
+ WREG32(mmTPC0_NRTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC1_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC2_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC3_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC4_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC5_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC6_RTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmTPC7_NRTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+
+ WREG32(mmPCI_NRTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ WREG32(mmDMA_NRTR_SPLIT_COEF_0 + offset, polynom[i] >> 7);
+ }
+
+ for (i = 0, offset = 0 ; i < 6 ; i++, offset += 0x40000) {
+ WREG32(mmMME1_RTR_SCRAMB_EN + offset,
+ 1 << MME1_RTR_SCRAMB_EN_VAL_SHIFT);
+ WREG32(mmMME1_RTR_NON_LIN_SCRAMB + offset,
+ 1 << MME1_RTR_NON_LIN_SCRAMB_EN_SHIFT);
+ }
+
+ for (i = 0, offset = 0 ; i < 8 ; i++, offset += 0x40000) {
+ /*
+ * Workaround for Bug H2 #2441 :
+ * "ST.NOP set trace event illegal opcode"
+ */
+ WREG32(mmTPC0_CFG_TPC_INTR_MASK + offset, tpc_intr_mask);
+
+ WREG32(mmTPC0_NRTR_SCRAMB_EN + offset,
+ 1 << TPC0_NRTR_SCRAMB_EN_VAL_SHIFT);
+ WREG32(mmTPC0_NRTR_NON_LIN_SCRAMB + offset,
+ 1 << TPC0_NRTR_NON_LIN_SCRAMB_EN_SHIFT);
+ }
+
+ WREG32(mmDMA_NRTR_SCRAMB_EN, 1 << DMA_NRTR_SCRAMB_EN_VAL_SHIFT);
+ WREG32(mmDMA_NRTR_NON_LIN_SCRAMB,
+ 1 << DMA_NRTR_NON_LIN_SCRAMB_EN_SHIFT);
+
+ WREG32(mmPCI_NRTR_SCRAMB_EN, 1 << PCI_NRTR_SCRAMB_EN_VAL_SHIFT);
+ WREG32(mmPCI_NRTR_NON_LIN_SCRAMB,
+ 1 << PCI_NRTR_NON_LIN_SCRAMB_EN_SHIFT);
+
+ /*
+ * Workaround for H2 #HW-23 bug
+ * Set DMA max outstanding read requests to 240 on DMA CH 1. Set it
+ * to 16 on KMD DMA
+ * We need to limit only these DMAs because the user can only read
+ * from Host using DMA CH 1
+ */
+ WREG32(mmDMA_CH_0_CFG0, 0x0fff0010);
+ WREG32(mmDMA_CH_1_CFG0, 0x0fff00F0);
+
+ goya->hw_cap_initialized |= HW_CAP_GOLDEN;
+}
+
+static void goya_init_mme_qman(struct hl_device *hdev)
+{
+ u32 mtr_base_lo, mtr_base_hi;
+ u32 so_base_lo, so_base_hi;
+ u32 gic_base_lo, gic_base_hi;
+ u64 qman_base_addr;
+
+ mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ qman_base_addr = hdev->asic_prop.sram_base_address +
+ MME_QMAN_BASE_OFFSET;
+
+ WREG32(mmMME_QM_PQ_BASE_LO, lower_32_bits(qman_base_addr));
+ WREG32(mmMME_QM_PQ_BASE_HI, upper_32_bits(qman_base_addr));
+ WREG32(mmMME_QM_PQ_SIZE, ilog2(MME_QMAN_LENGTH));
+ WREG32(mmMME_QM_PQ_PI, 0);
+ WREG32(mmMME_QM_PQ_CI, 0);
+ WREG32(mmMME_QM_CP_LDMA_SRC_BASE_LO_OFFSET, 0x10C0);
+ WREG32(mmMME_QM_CP_LDMA_SRC_BASE_HI_OFFSET, 0x10C4);
+ WREG32(mmMME_QM_CP_LDMA_TSIZE_OFFSET, 0x10C8);
+ WREG32(mmMME_QM_CP_LDMA_COMMIT_OFFSET, 0x10CC);
+
+ WREG32(mmMME_QM_CP_MSG_BASE0_ADDR_LO, mtr_base_lo);
+ WREG32(mmMME_QM_CP_MSG_BASE0_ADDR_HI, mtr_base_hi);
+ WREG32(mmMME_QM_CP_MSG_BASE1_ADDR_LO, so_base_lo);
+ WREG32(mmMME_QM_CP_MSG_BASE1_ADDR_HI, so_base_hi);
+
+ /* QMAN CQ has 8 cache lines */
+ WREG32(mmMME_QM_CQ_CFG1, 0x00080008);
+
+ WREG32(mmMME_QM_GLBL_ERR_ADDR_LO, gic_base_lo);
+ WREG32(mmMME_QM_GLBL_ERR_ADDR_HI, gic_base_hi);
+
+ WREG32(mmMME_QM_GLBL_ERR_WDATA, GOYA_ASYNC_EVENT_ID_MME_QM);
+
+ WREG32(mmMME_QM_GLBL_ERR_CFG, QMAN_MME_ERR_MSG_EN);
+
+ WREG32(mmMME_QM_GLBL_PROT, QMAN_MME_ERR_PROT);
+
+ WREG32(mmMME_QM_GLBL_CFG0, QMAN_MME_ENABLE);
+}
+
+static void goya_init_mme_cmdq(struct hl_device *hdev)
+{
+ u32 mtr_base_lo, mtr_base_hi;
+ u32 so_base_lo, so_base_hi;
+ u32 gic_base_lo, gic_base_hi;
+ u64 qman_base_addr;
+
+ mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ qman_base_addr = hdev->asic_prop.sram_base_address +
+ MME_QMAN_BASE_OFFSET;
+
+ WREG32(mmMME_CMDQ_CP_MSG_BASE0_ADDR_LO, mtr_base_lo);
+ WREG32(mmMME_CMDQ_CP_MSG_BASE0_ADDR_HI, mtr_base_hi);
+ WREG32(mmMME_CMDQ_CP_MSG_BASE1_ADDR_LO, so_base_lo);
+ WREG32(mmMME_CMDQ_CP_MSG_BASE1_ADDR_HI, so_base_hi);
+
+ /* CMDQ CQ has 20 cache lines */
+ WREG32(mmMME_CMDQ_CQ_CFG1, 0x00140014);
+
+ WREG32(mmMME_CMDQ_GLBL_ERR_ADDR_LO, gic_base_lo);
+ WREG32(mmMME_CMDQ_GLBL_ERR_ADDR_HI, gic_base_hi);
+
+ WREG32(mmMME_CMDQ_GLBL_ERR_WDATA, GOYA_ASYNC_EVENT_ID_MME_CMDQ);
+
+ WREG32(mmMME_CMDQ_GLBL_ERR_CFG, CMDQ_MME_ERR_MSG_EN);
+
+ WREG32(mmMME_CMDQ_GLBL_PROT, CMDQ_MME_ERR_PROT);
+
+ WREG32(mmMME_CMDQ_GLBL_CFG0, CMDQ_MME_ENABLE);
+}
+
+static void goya_init_mme_qmans(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 so_base_lo, so_base_hi;
+
+ if (goya->hw_cap_initialized & HW_CAP_MME)
+ return;
+
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ WREG32(mmMME_SM_BASE_ADDRESS_LOW, so_base_lo);
+ WREG32(mmMME_SM_BASE_ADDRESS_HIGH, so_base_hi);
+
+ goya_init_mme_qman(hdev);
+ goya_init_mme_cmdq(hdev);
+
+ goya->hw_cap_initialized |= HW_CAP_MME;
+}
+
+static void goya_init_tpc_qman(struct hl_device *hdev, u32 base_off, int tpc_id)
+{
+ u32 mtr_base_lo, mtr_base_hi;
+ u32 so_base_lo, so_base_hi;
+ u32 gic_base_lo, gic_base_hi;
+ u64 qman_base_addr;
+ u32 reg_off = tpc_id * (mmTPC1_QM_PQ_PI - mmTPC0_QM_PQ_PI);
+
+ mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ qman_base_addr = hdev->asic_prop.sram_base_address + base_off;
+
+ WREG32(mmTPC0_QM_PQ_BASE_LO + reg_off, lower_32_bits(qman_base_addr));
+ WREG32(mmTPC0_QM_PQ_BASE_HI + reg_off, upper_32_bits(qman_base_addr));
+ WREG32(mmTPC0_QM_PQ_SIZE + reg_off, ilog2(TPC_QMAN_LENGTH));
+ WREG32(mmTPC0_QM_PQ_PI + reg_off, 0);
+ WREG32(mmTPC0_QM_PQ_CI + reg_off, 0);
+ WREG32(mmTPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET + reg_off, 0x10C0);
+ WREG32(mmTPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET + reg_off, 0x10C4);
+ WREG32(mmTPC0_QM_CP_LDMA_TSIZE_OFFSET + reg_off, 0x10C8);
+ WREG32(mmTPC0_QM_CP_LDMA_COMMIT_OFFSET + reg_off, 0x10CC);
+
+ WREG32(mmTPC0_QM_CP_MSG_BASE0_ADDR_LO + reg_off, mtr_base_lo);
+ WREG32(mmTPC0_QM_CP_MSG_BASE0_ADDR_HI + reg_off, mtr_base_hi);
+ WREG32(mmTPC0_QM_CP_MSG_BASE1_ADDR_LO + reg_off, so_base_lo);
+ WREG32(mmTPC0_QM_CP_MSG_BASE1_ADDR_HI + reg_off, so_base_hi);
+
+ WREG32(mmTPC0_QM_CQ_CFG1 + reg_off, 0x00080008);
+
+ WREG32(mmTPC0_QM_GLBL_ERR_ADDR_LO + reg_off, gic_base_lo);
+ WREG32(mmTPC0_QM_GLBL_ERR_ADDR_HI + reg_off, gic_base_hi);
+
+ WREG32(mmTPC0_QM_GLBL_ERR_WDATA + reg_off,
+ GOYA_ASYNC_EVENT_ID_TPC0_QM + tpc_id);
+
+ WREG32(mmTPC0_QM_GLBL_ERR_CFG + reg_off, QMAN_TPC_ERR_MSG_EN);
+
+ WREG32(mmTPC0_QM_GLBL_PROT + reg_off, QMAN_TPC_ERR_PROT);
+
+ WREG32(mmTPC0_QM_GLBL_CFG0 + reg_off, QMAN_TPC_ENABLE);
+}
+
+static void goya_init_tpc_cmdq(struct hl_device *hdev, int tpc_id)
+{
+ u32 mtr_base_lo, mtr_base_hi;
+ u32 so_base_lo, so_base_hi;
+ u32 gic_base_lo, gic_base_hi;
+ u32 reg_off = tpc_id * (mmTPC1_CMDQ_CQ_CFG1 - mmTPC0_CMDQ_CQ_CFG1);
+
+ mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ gic_base_lo =
+ lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+ gic_base_hi =
+ upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR);
+
+ WREG32(mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_LO + reg_off, mtr_base_lo);
+ WREG32(mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_HI + reg_off, mtr_base_hi);
+ WREG32(mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_LO + reg_off, so_base_lo);
+ WREG32(mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_HI + reg_off, so_base_hi);
+
+ WREG32(mmTPC0_CMDQ_CQ_CFG1 + reg_off, 0x00140014);
+
+ WREG32(mmTPC0_CMDQ_GLBL_ERR_ADDR_LO + reg_off, gic_base_lo);
+ WREG32(mmTPC0_CMDQ_GLBL_ERR_ADDR_HI + reg_off, gic_base_hi);
+
+ WREG32(mmTPC0_CMDQ_GLBL_ERR_WDATA + reg_off,
+ GOYA_ASYNC_EVENT_ID_TPC0_CMDQ + tpc_id);
+
+ WREG32(mmTPC0_CMDQ_GLBL_ERR_CFG + reg_off, CMDQ_TPC_ERR_MSG_EN);
+
+ WREG32(mmTPC0_CMDQ_GLBL_PROT + reg_off, CMDQ_TPC_ERR_PROT);
+
+ WREG32(mmTPC0_CMDQ_GLBL_CFG0 + reg_off, CMDQ_TPC_ENABLE);
+}
+
+static void goya_init_tpc_qmans(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 so_base_lo, so_base_hi;
+ u32 cfg_off = mmTPC1_CFG_SM_BASE_ADDRESS_LOW -
+ mmTPC0_CFG_SM_BASE_ADDRESS_LOW;
+ int i;
+
+ if (goya->hw_cap_initialized & HW_CAP_TPC)
+ return;
+
+ so_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ so_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+
+ for (i = 0 ; i < TPC_MAX_NUM ; i++) {
+ WREG32(mmTPC0_CFG_SM_BASE_ADDRESS_LOW + i * cfg_off,
+ so_base_lo);
+ WREG32(mmTPC0_CFG_SM_BASE_ADDRESS_HIGH + i * cfg_off,
+ so_base_hi);
+ }
+
+ goya_init_tpc_qman(hdev, TPC0_QMAN_BASE_OFFSET, 0);
+ goya_init_tpc_qman(hdev, TPC1_QMAN_BASE_OFFSET, 1);
+ goya_init_tpc_qman(hdev, TPC2_QMAN_BASE_OFFSET, 2);
+ goya_init_tpc_qman(hdev, TPC3_QMAN_BASE_OFFSET, 3);
+ goya_init_tpc_qman(hdev, TPC4_QMAN_BASE_OFFSET, 4);
+ goya_init_tpc_qman(hdev, TPC5_QMAN_BASE_OFFSET, 5);
+ goya_init_tpc_qman(hdev, TPC6_QMAN_BASE_OFFSET, 6);
+ goya_init_tpc_qman(hdev, TPC7_QMAN_BASE_OFFSET, 7);
+
+ for (i = 0 ; i < TPC_MAX_NUM ; i++)
+ goya_init_tpc_cmdq(hdev, i);
+
+ goya->hw_cap_initialized |= HW_CAP_TPC;
+}
+
+/*
+ * goya_disable_internal_queues - Disable internal queues
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ */
+static void goya_disable_internal_queues(struct hl_device *hdev)
+{
+ WREG32(mmMME_QM_GLBL_CFG0, 0);
+ WREG32(mmMME_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC0_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC0_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC1_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC1_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC2_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC2_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC3_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC3_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC4_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC4_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC5_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC5_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC6_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC6_CMDQ_GLBL_CFG0, 0);
+
+ WREG32(mmTPC7_QM_GLBL_CFG0, 0);
+ WREG32(mmTPC7_CMDQ_GLBL_CFG0, 0);
+}
+
+/*
+ * goya_stop_internal_queues - Stop internal queues
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Returns 0 on success
+ *
+ */
+static int goya_stop_internal_queues(struct hl_device *hdev)
+{
+ int rc, retval = 0;
+
+ /*
+ * Each queue (QMAN) is a separate H/W logic. That means that each
+ * QMAN can be stopped independently and failure to stop one does NOT
+ * mandate we should not try to stop other QMANs
+ */
+
+ rc = goya_stop_queue(hdev,
+ mmMME_QM_GLBL_CFG1,
+ mmMME_QM_CP_STS,
+ mmMME_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop MME QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmMME_CMDQ_GLBL_CFG1,
+ mmMME_CMDQ_CP_STS,
+ mmMME_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop MME CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC0_QM_GLBL_CFG1,
+ mmTPC0_QM_CP_STS,
+ mmTPC0_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 0 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC0_CMDQ_GLBL_CFG1,
+ mmTPC0_CMDQ_CP_STS,
+ mmTPC0_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 0 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC1_QM_GLBL_CFG1,
+ mmTPC1_QM_CP_STS,
+ mmTPC1_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 1 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC1_CMDQ_GLBL_CFG1,
+ mmTPC1_CMDQ_CP_STS,
+ mmTPC1_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 1 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC2_QM_GLBL_CFG1,
+ mmTPC2_QM_CP_STS,
+ mmTPC2_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 2 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC2_CMDQ_GLBL_CFG1,
+ mmTPC2_CMDQ_CP_STS,
+ mmTPC2_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 2 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC3_QM_GLBL_CFG1,
+ mmTPC3_QM_CP_STS,
+ mmTPC3_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 3 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC3_CMDQ_GLBL_CFG1,
+ mmTPC3_CMDQ_CP_STS,
+ mmTPC3_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 3 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC4_QM_GLBL_CFG1,
+ mmTPC4_QM_CP_STS,
+ mmTPC4_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 4 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC4_CMDQ_GLBL_CFG1,
+ mmTPC4_CMDQ_CP_STS,
+ mmTPC4_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 4 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC5_QM_GLBL_CFG1,
+ mmTPC5_QM_CP_STS,
+ mmTPC5_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 5 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC5_CMDQ_GLBL_CFG1,
+ mmTPC5_CMDQ_CP_STS,
+ mmTPC5_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 5 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC6_QM_GLBL_CFG1,
+ mmTPC6_QM_CP_STS,
+ mmTPC6_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 6 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC6_CMDQ_GLBL_CFG1,
+ mmTPC6_CMDQ_CP_STS,
+ mmTPC6_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 6 CMDQ\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC7_QM_GLBL_CFG1,
+ mmTPC7_QM_CP_STS,
+ mmTPC7_QM_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 7 QMAN\n");
+ retval = -EIO;
+ }
+
+ rc = goya_stop_queue(hdev,
+ mmTPC7_CMDQ_GLBL_CFG1,
+ mmTPC7_CMDQ_CP_STS,
+ mmTPC7_CMDQ_GLBL_STS0);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop TPC 7 CMDQ\n");
+ retval = -EIO;
+ }
+
+ return retval;
+}
+
+static void goya_resume_internal_queues(struct hl_device *hdev)
+{
+ WREG32(mmMME_QM_GLBL_CFG1, 0);
+ WREG32(mmMME_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC0_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC0_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC1_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC1_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC2_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC2_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC3_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC3_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC4_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC4_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC5_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC5_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC6_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC6_CMDQ_GLBL_CFG1, 0);
+
+ WREG32(mmTPC7_QM_GLBL_CFG1, 0);
+ WREG32(mmTPC7_CMDQ_GLBL_CFG1, 0);
+}
+
+static void goya_dma_stall(struct hl_device *hdev)
+{
+ WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
+ WREG32(mmDMA_QM_1_GLBL_CFG1, 1 << DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT);
+ WREG32(mmDMA_QM_2_GLBL_CFG1, 1 << DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT);
+ WREG32(mmDMA_QM_3_GLBL_CFG1, 1 << DMA_QM_3_GLBL_CFG1_DMA_STOP_SHIFT);
+ WREG32(mmDMA_QM_4_GLBL_CFG1, 1 << DMA_QM_4_GLBL_CFG1_DMA_STOP_SHIFT);
+}
+
+static void goya_tpc_stall(struct hl_device *hdev)
+{
+ WREG32(mmTPC0_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC1_CFG_TPC_STALL, 1 << TPC1_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC2_CFG_TPC_STALL, 1 << TPC2_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC3_CFG_TPC_STALL, 1 << TPC3_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC4_CFG_TPC_STALL, 1 << TPC4_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC5_CFG_TPC_STALL, 1 << TPC5_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC6_CFG_TPC_STALL, 1 << TPC6_CFG_TPC_STALL_V_SHIFT);
+ WREG32(mmTPC7_CFG_TPC_STALL, 1 << TPC7_CFG_TPC_STALL_V_SHIFT);
+}
+
+static void goya_mme_stall(struct hl_device *hdev)
+{
+ WREG32(mmMME_STALL, 0xFFFFFFFF);
+}
+
+static int goya_enable_msix(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int cq_cnt = hdev->asic_prop.completion_queues_count;
+ int rc, i, irq_cnt_init, irq;
+
+ if (goya->hw_cap_initialized & HW_CAP_MSIX)
+ return 0;
+
+ rc = pci_alloc_irq_vectors(hdev->pdev, GOYA_MSIX_ENTRIES,
+ GOYA_MSIX_ENTRIES, PCI_IRQ_MSIX);
+ if (rc < 0) {
+ dev_err(hdev->dev,
+ "MSI-X: Failed to enable support -- %d/%d\n",
+ GOYA_MSIX_ENTRIES, rc);
+ return rc;
+ }
+
+ for (i = 0, irq_cnt_init = 0 ; i < cq_cnt ; i++, irq_cnt_init++) {
+ irq = pci_irq_vector(hdev->pdev, i);
+ rc = request_irq(irq, hl_irq_handler_cq, 0, goya_irq_name[i],
+ &hdev->completion_queue[i]);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to request IRQ %d", irq);
+ goto free_irqs;
+ }
+ }
+
+ irq = pci_irq_vector(hdev->pdev, EVENT_QUEUE_MSIX_IDX);
+
+ rc = request_irq(irq, hl_irq_handler_eq, 0,
+ goya_irq_name[EVENT_QUEUE_MSIX_IDX],
+ &hdev->event_queue);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to request IRQ %d", irq);
+ goto free_irqs;
+ }
+
+ goya->hw_cap_initialized |= HW_CAP_MSIX;
+ return 0;
+
+free_irqs:
+ for (i = 0 ; i < irq_cnt_init ; i++)
+ free_irq(pci_irq_vector(hdev->pdev, i),
+ &hdev->completion_queue[i]);
+
+ pci_free_irq_vectors(hdev->pdev);
+ return rc;
+}
+
+static void goya_sync_irqs(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int i;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MSIX))
+ return;
+
+ /* Wait for all pending IRQs to be finished */
+ for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
+ synchronize_irq(pci_irq_vector(hdev->pdev, i));
+
+ synchronize_irq(pci_irq_vector(hdev->pdev, EVENT_QUEUE_MSIX_IDX));
+}
+
+static void goya_disable_msix(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int i, irq;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MSIX))
+ return;
+
+ goya_sync_irqs(hdev);
+
+ irq = pci_irq_vector(hdev->pdev, EVENT_QUEUE_MSIX_IDX);
+ free_irq(irq, &hdev->event_queue);
+
+ for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) {
+ irq = pci_irq_vector(hdev->pdev, i);
+ free_irq(irq, &hdev->completion_queue[i]);
+ }
+
+ pci_free_irq_vectors(hdev->pdev);
+
+ goya->hw_cap_initialized &= ~HW_CAP_MSIX;
+}
+
+static void goya_halt_engines(struct hl_device *hdev, bool hard_reset)
+{
+ u32 wait_timeout_ms, cpu_timeout_ms;
+
+ dev_info(hdev->dev,
+ "Halting compute engines and disabling interrupts\n");
+
+ if (hdev->pldm) {
+ wait_timeout_ms = GOYA_PLDM_RESET_WAIT_MSEC;
+ cpu_timeout_ms = GOYA_PLDM_RESET_WAIT_MSEC;
+ } else {
+ wait_timeout_ms = GOYA_RESET_WAIT_MSEC;
+ cpu_timeout_ms = GOYA_CPU_RESET_WAIT_MSEC;
+ }
+
+ if (hard_reset) {
+ /*
+ * I don't know what is the state of the CPU so make sure it is
+ * stopped in any means necessary
+ */
+ WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_GOTO_WFE);
+ WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
+ GOYA_ASYNC_EVENT_ID_HALT_MACHINE);
+ msleep(cpu_timeout_ms);
+ }
+
+ goya_stop_external_queues(hdev);
+ goya_stop_internal_queues(hdev);
+
+ msleep(wait_timeout_ms);
+
+ goya_dma_stall(hdev);
+ goya_tpc_stall(hdev);
+ goya_mme_stall(hdev);
+
+ msleep(wait_timeout_ms);
+
+ goya_disable_external_queues(hdev);
+ goya_disable_internal_queues(hdev);
+
+ if (hard_reset)
+ goya_disable_msix(hdev);
+ else
+ goya_sync_irqs(hdev);
+}
+
+/*
+ * goya_push_fw_to_device - Push FW code to device
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Copy fw code from firmware file to device memory.
+ * Returns 0 on success
+ *
+ */
+static int goya_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
+ void __iomem *dst)
+{
+ const struct firmware *fw;
+ const u64 *fw_data;
+ size_t fw_size, i;
+ int rc;
+
+ rc = request_firmware(&fw, fw_name, hdev->dev);
+
+ if (rc) {
+ dev_err(hdev->dev, "Failed to request %s\n", fw_name);
+ goto out;
+ }
+
+ fw_size = fw->size;
+ if ((fw_size % 4) != 0) {
+ dev_err(hdev->dev, "illegal %s firmware size %zu\n",
+ fw_name, fw_size);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
+
+ fw_data = (const u64 *) fw->data;
+
+ if ((fw->size % 8) != 0)
+ fw_size -= 8;
+
+ for (i = 0 ; i < fw_size ; i += 8, fw_data++, dst += 8) {
+ if (!(i & (0x80000 - 1))) {
+ dev_dbg(hdev->dev,
+ "copied so far %zu out of %zu for %s firmware",
+ i, fw_size, fw_name);
+ usleep_range(20, 100);
+ }
+
+ writeq(*fw_data, dst);
+ }
+
+ if ((fw->size % 8) != 0)
+ writel(*(const u32 *) fw_data, dst);
+
+out:
+ release_firmware(fw);
+ return rc;
+}
+
+static int goya_pldm_init_cpu(struct hl_device *hdev)
+{
+ char fw_name[200];
+ void __iomem *dst;
+ u32 val, unit_rst_val;
+ int rc;
+
+ /* Must initialize SRAM scrambler before pushing u-boot to SRAM */
+ goya_init_golden_registers(hdev);
+
+ /* Put ARM cores into reset */
+ WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, CPU_RESET_ASSERT);
+ val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+
+ /* Reset the CA53 MACRO */
+ unit_rst_val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+ WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, CA53_RESET);
+ val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+ WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, unit_rst_val);
+ val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+
+ snprintf(fw_name, sizeof(fw_name), "habanalabs/goya/goya-u-boot.bin");
+ dst = hdev->pcie_bar[SRAM_CFG_BAR_ID] + UBOOT_FW_OFFSET;
+ rc = goya_push_fw_to_device(hdev, fw_name, dst);
+ if (rc)
+ return rc;
+
+ snprintf(fw_name, sizeof(fw_name), "habanalabs/goya/goya-fit.itb");
+ dst = hdev->pcie_bar[DDR_BAR_ID] + LINUX_FW_OFFSET;
+ rc = goya_push_fw_to_device(hdev, fw_name, dst);
+ if (rc)
+ return rc;
+
+ WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_FIT_RDY);
+ WREG32(mmPSOC_GLOBAL_CONF_WARM_REBOOT, CPU_BOOT_STATUS_NA);
+
+ WREG32(mmCPU_CA53_CFG_RST_ADDR_LSB_0,
+ lower_32_bits(SRAM_BASE_ADDR + UBOOT_FW_OFFSET));
+ WREG32(mmCPU_CA53_CFG_RST_ADDR_MSB_0,
+ upper_32_bits(SRAM_BASE_ADDR + UBOOT_FW_OFFSET));
+
+ /* Release ARM core 0 from reset */
+ WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL,
+ CPU_RESET_CORE0_DEASSERT);
+ val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+
+ return 0;
+}
+
+/*
+ * FW component passes an offset from SRAM_BASE_ADDR in SCRATCHPAD_xx.
+ * The version string should be located by that offset.
+ */
+static void goya_read_device_fw_version(struct hl_device *hdev,
+ enum goya_fw_component fwc)
+{
+ const char *name;
+ u32 ver_off;
+ char *dest;
+
+ switch (fwc) {
+ case FW_COMP_UBOOT:
+ ver_off = RREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_29);
+ dest = hdev->asic_prop.uboot_ver;
+ name = "U-Boot";
+ break;
+ case FW_COMP_PREBOOT:
+ ver_off = RREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_28);
+ dest = hdev->asic_prop.preboot_ver;
+ name = "Preboot";
+ break;
+ default:
+ dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc);
+ return;
+ }
+
+ ver_off &= ~((u32)SRAM_BASE_ADDR);
+
+ if (ver_off < SRAM_SIZE - VERSION_MAX_LEN) {
+ memcpy_fromio(dest, hdev->pcie_bar[SRAM_CFG_BAR_ID] + ver_off,
+ VERSION_MAX_LEN);
+ } else {
+ dev_err(hdev->dev, "%s version offset (0x%x) is above SRAM\n",
+ name, ver_off);
+ strcpy(dest, "unavailable");
+ }
+}
+
+static int goya_init_cpu(struct hl_device *hdev, u32 cpu_timeout)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ char fw_name[200];
+ void __iomem *dst;
+ u32 status;
+ int rc;
+
+ if (!hdev->cpu_enable)
+ return 0;
+
+ if (goya->hw_cap_initialized & HW_CAP_CPU)
+ return 0;
+
+ /*
+ * Before pushing u-boot/linux to device, need to set the ddr bar to
+ * base address of dram
+ */
+ rc = goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to map DDR bar to DRAM base address\n");
+ return rc;
+ }
+
+ if (hdev->pldm) {
+ rc = goya_pldm_init_cpu(hdev);
+ if (rc)
+ return rc;
+
+ goto out;
+ }
+
+ /* Make sure CPU boot-loader is running */
+ rc = hl_poll_timeout(
+ hdev,
+ mmPSOC_GLOBAL_CONF_WARM_REBOOT,
+ status,
+ (status == CPU_BOOT_STATUS_DRAM_RDY) ||
+ (status == CPU_BOOT_STATUS_SRAM_AVAIL),
+ 10000,
+ cpu_timeout);
+
+ if (rc) {
+ dev_err(hdev->dev, "Error in ARM u-boot!");
+ switch (status) {
+ case CPU_BOOT_STATUS_NA:
+ dev_err(hdev->dev,
+ "ARM status %d - BTL did NOT run\n", status);
+ break;
+ case CPU_BOOT_STATUS_IN_WFE:
+ dev_err(hdev->dev,
+ "ARM status %d - Inside WFE loop\n", status);
+ break;
+ case CPU_BOOT_STATUS_IN_BTL:
+ dev_err(hdev->dev,
+ "ARM status %d - Stuck in BTL\n", status);
+ break;
+ case CPU_BOOT_STATUS_IN_PREBOOT:
+ dev_err(hdev->dev,
+ "ARM status %d - Stuck in Preboot\n", status);
+ break;
+ case CPU_BOOT_STATUS_IN_SPL:
+ dev_err(hdev->dev,
+ "ARM status %d - Stuck in SPL\n", status);
+ break;
+ case CPU_BOOT_STATUS_IN_UBOOT:
+ dev_err(hdev->dev,
+ "ARM status %d - Stuck in u-boot\n", status);
+ break;
+ case CPU_BOOT_STATUS_DRAM_INIT_FAIL:
+ dev_err(hdev->dev,
+ "ARM status %d - DDR initialization failed\n",
+ status);
+ break;
+ default:
+ dev_err(hdev->dev,
+ "ARM status %d - Invalid status code\n",
+ status);
+ break;
+ }
+ return -EIO;
+ }
+
+ /* Read U-Boot version now in case we will later fail */
+ goya_read_device_fw_version(hdev, FW_COMP_UBOOT);
+ goya_read_device_fw_version(hdev, FW_COMP_PREBOOT);
+
+ if (status == CPU_BOOT_STATUS_SRAM_AVAIL)
+ goto out;
+
+ if (!hdev->fw_loading) {
+ dev_info(hdev->dev, "Skip loading FW\n");
+ goto out;
+ }
+
+ snprintf(fw_name, sizeof(fw_name), "habanalabs/goya/goya-fit.itb");
+ dst = hdev->pcie_bar[DDR_BAR_ID] + LINUX_FW_OFFSET;
+ rc = goya_push_fw_to_device(hdev, fw_name, dst);
+ if (rc)
+ return rc;
+
+ WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_FIT_RDY);
+
+ rc = hl_poll_timeout(
+ hdev,
+ mmPSOC_GLOBAL_CONF_WARM_REBOOT,
+ status,
+ (status == CPU_BOOT_STATUS_SRAM_AVAIL),
+ 10000,
+ cpu_timeout);
+
+ if (rc) {
+ if (status == CPU_BOOT_STATUS_FIT_CORRUPTED)
+ dev_err(hdev->dev,
+ "ARM u-boot reports FIT image is corrupted\n");
+ else
+ dev_err(hdev->dev,
+ "ARM Linux failed to load, %d\n", status);
+ WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_NA);
+ return -EIO;
+ }
+
+ dev_info(hdev->dev, "Successfully loaded firmware to device\n");
+
+out:
+ goya->hw_cap_initialized |= HW_CAP_CPU;
+
+ return 0;
+}
+
+static int goya_mmu_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct goya_device *goya = hdev->asic_specific;
+ u64 hop0_addr;
+ int rc, i;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ if (goya->hw_cap_initialized & HW_CAP_MMU)
+ return 0;
+
+ hdev->dram_supports_virtual_memory = true;
+ hdev->dram_default_page_mapping = true;
+
+ for (i = 0 ; i < prop->max_asid ; i++) {
+ hop0_addr = prop->mmu_pgt_addr +
+ (i * prop->mmu_hop_table_size);
+
+ rc = goya_mmu_update_asid_hop0_addr(hdev, i, hop0_addr);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to set hop0 addr for asid %d\n", i);
+ goto err;
+ }
+ }
+
+ goya->hw_cap_initialized |= HW_CAP_MMU;
+
+ /* init MMU cache manage page */
+ WREG32(mmSTLB_CACHE_INV_BASE_39_8,
+ lower_32_bits(MMU_CACHE_MNG_ADDR >> 8));
+ WREG32(mmSTLB_CACHE_INV_BASE_49_40, MMU_CACHE_MNG_ADDR >> 40);
+
+ /* Remove follower feature due to performance bug */
+ WREG32_AND(mmSTLB_STLB_FEATURE_EN,
+ (~STLB_STLB_FEATURE_EN_FOLLOWER_EN_MASK));
+
+ hdev->asic_funcs->mmu_invalidate_cache(hdev, true);
+
+ WREG32(mmMMU_MMU_ENABLE, 1);
+ WREG32(mmMMU_SPI_MASK, 0xF);
+
+ return 0;
+
+err:
+ return rc;
+}
+
+/*
+ * goya_hw_init - Goya hardware initialization code
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Returns 0 on success
+ *
+ */
+static int goya_hw_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u32 val;
+ int rc;
+
+ dev_info(hdev->dev, "Starting initialization of H/W\n");
+
+ /* Perform read from the device to make sure device is up */
+ val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+
+ /*
+ * Let's mark in the H/W that we have reached this point. We check
+ * this value in the reset_before_init function to understand whether
+ * we need to reset the chip before doing H/W init. This register is
+ * cleared by the H/W upon H/W reset
+ */
+ WREG32(mmPSOC_GLOBAL_CONF_APP_STATUS, HL_DEVICE_HW_STATE_DIRTY);
+
+ rc = goya_init_cpu(hdev, GOYA_CPU_TIMEOUT_USEC);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize CPU\n");
+ return rc;
+ }
+
+ goya_tpc_mbist_workaround(hdev);
+
+ goya_init_golden_registers(hdev);
+
+ /*
+ * After CPU initialization is finished, change DDR bar mapping inside
+ * iATU to point to the start address of the MMU page tables
+ */
+ rc = goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE +
+ (MMU_PAGE_TABLES_ADDR & ~(prop->dram_pci_bar_size - 0x1ull)));
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to map DDR bar to MMU page tables\n");
+ return rc;
+ }
+
+ rc = goya_mmu_init(hdev);
+ if (rc)
+ return rc;
+
+ goya_init_security(hdev);
+
+ goya_init_dma_qmans(hdev);
+
+ goya_init_mme_qmans(hdev);
+
+ goya_init_tpc_qmans(hdev);
+
+ /* MSI-X must be enabled before CPU queues are initialized */
+ rc = goya_enable_msix(hdev);
+ if (rc)
+ goto disable_queues;
+
+ rc = goya_init_cpu_queues(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize CPU H/W queues %d\n",
+ rc);
+ goto disable_msix;
+ }
+
+ /* CPU initialization is finished, we can now move to 48 bit DMA mask */
+ rc = pci_set_dma_mask(hdev->pdev, DMA_BIT_MASK(48));
+ if (rc) {
+ dev_warn(hdev->dev, "Unable to set pci dma mask to 48 bits\n");
+ rc = pci_set_dma_mask(hdev->pdev, DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(hdev->dev,
+ "Unable to set pci dma mask to 32 bits\n");
+ goto disable_pci_access;
+ }
+ }
+
+ rc = pci_set_consistent_dma_mask(hdev->pdev, DMA_BIT_MASK(48));
+ if (rc) {
+ dev_warn(hdev->dev,
+ "Unable to set pci consistent dma mask to 48 bits\n");
+ rc = pci_set_consistent_dma_mask(hdev->pdev, DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(hdev->dev,
+ "Unable to set pci consistent dma mask to 32 bits\n");
+ goto disable_pci_access;
+ }
+ }
+
+ /* Perform read from the device to flush all MSI-X configuration */
+ val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+
+ return 0;
+
+disable_pci_access:
+ goya_send_pci_access_msg(hdev, ARMCP_PACKET_DISABLE_PCI_ACCESS);
+disable_msix:
+ goya_disable_msix(hdev);
+disable_queues:
+ goya_disable_internal_queues(hdev);
+ goya_disable_external_queues(hdev);
+
+ return rc;
+}
+
+/*
+ * goya_hw_fini - Goya hardware tear-down code
+ *
+ * @hdev: pointer to hl_device structure
+ * @hard_reset: should we do hard reset to all engines or just reset the
+ * compute/dma engines
+ */
+static void goya_hw_fini(struct hl_device *hdev, bool hard_reset)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 reset_timeout_ms, status;
+
+ if (hdev->pldm)
+ reset_timeout_ms = GOYA_PLDM_RESET_TIMEOUT_MSEC;
+ else
+ reset_timeout_ms = GOYA_RESET_TIMEOUT_MSEC;
+
+ if (hard_reset) {
+ goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE);
+ goya_disable_clk_rlx(hdev);
+ goya_set_pll_refclk(hdev);
+
+ WREG32(mmPSOC_GLOBAL_CONF_SW_ALL_RST_CFG, RESET_ALL);
+ dev_info(hdev->dev,
+ "Issued HARD reset command, going to wait %dms\n",
+ reset_timeout_ms);
+ } else {
+ WREG32(mmPSOC_GLOBAL_CONF_SW_ALL_RST_CFG, DMA_MME_TPC_RESET);
+ dev_info(hdev->dev,
+ "Issued SOFT reset command, going to wait %dms\n",
+ reset_timeout_ms);
+ }
+
+ /*
+ * After hard reset, we can't poll the BTM_FSM register because the PSOC
+ * itself is in reset. In either reset we need to wait until the reset
+ * is deasserted
+ */
+ msleep(reset_timeout_ms);
+
+ status = RREG32(mmPSOC_GLOBAL_CONF_BTM_FSM);
+ if (status & PSOC_GLOBAL_CONF_BTM_FSM_STATE_MASK)
+ dev_err(hdev->dev,
+ "Timeout while waiting for device to reset 0x%x\n",
+ status);
+
+ if (!hard_reset) {
+ goya->hw_cap_initialized &= ~(HW_CAP_DMA | HW_CAP_MME |
+ HW_CAP_GOLDEN | HW_CAP_TPC);
+ WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
+ GOYA_ASYNC_EVENT_ID_SOFT_RESET);
+ return;
+ }
+
+ /* Chicken bit to re-initiate boot sequencer flow */
+ WREG32(mmPSOC_GLOBAL_CONF_BOOT_SEQ_RE_START,
+ 1 << PSOC_GLOBAL_CONF_BOOT_SEQ_RE_START_IND_SHIFT);
+ /* Move boot manager FSM to pre boot sequencer init state */
+ WREG32(mmPSOC_GLOBAL_CONF_SW_BTM_FSM,
+ 0xA << PSOC_GLOBAL_CONF_SW_BTM_FSM_CTRL_SHIFT);
+
+ goya->hw_cap_initialized &= ~(HW_CAP_CPU | HW_CAP_CPU_Q |
+ HW_CAP_DDR_0 | HW_CAP_DDR_1 |
+ HW_CAP_DMA | HW_CAP_MME |
+ HW_CAP_MMU | HW_CAP_TPC_MBIST |
+ HW_CAP_GOLDEN | HW_CAP_TPC);
+ memset(goya->events_stat, 0, sizeof(goya->events_stat));
+
+ if (!hdev->pldm) {
+ int rc;
+ /* In case we are running inside VM and the VM is
+ * shutting down, we need to make sure CPU boot-loader
+ * is running before we can continue the VM shutdown.
+ * That is because the VM will send an FLR signal that
+ * we must answer
+ */
+ dev_info(hdev->dev,
+ "Going to wait up to %ds for CPU boot loader\n",
+ GOYA_CPU_TIMEOUT_USEC / 1000 / 1000);
+
+ rc = hl_poll_timeout(
+ hdev,
+ mmPSOC_GLOBAL_CONF_WARM_REBOOT,
+ status,
+ (status == CPU_BOOT_STATUS_DRAM_RDY),
+ 10000,
+ GOYA_CPU_TIMEOUT_USEC);
+ if (rc)
+ dev_err(hdev->dev,
+ "failed to wait for CPU boot loader\n");
+ }
+}
+
+int goya_suspend(struct hl_device *hdev)
+{
+ int rc;
+
+ rc = goya_stop_internal_queues(hdev);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop internal queues\n");
+ return rc;
+ }
+
+ rc = goya_stop_external_queues(hdev);
+
+ if (rc) {
+ dev_err(hdev->dev, "failed to stop external queues\n");
+ return rc;
+ }
+
+ rc = goya_send_pci_access_msg(hdev, ARMCP_PACKET_DISABLE_PCI_ACCESS);
+ if (rc)
+ dev_err(hdev->dev, "Failed to disable PCI access from CPU\n");
+
+ return rc;
+}
+
+int goya_resume(struct hl_device *hdev)
+{
+ int rc;
+
+ goya_resume_external_queues(hdev);
+ goya_resume_internal_queues(hdev);
+
+ rc = goya_send_pci_access_msg(hdev, ARMCP_PACKET_ENABLE_PCI_ACCESS);
+ if (rc)
+ dev_err(hdev->dev, "Failed to enable PCI access from CPU\n");
+ return rc;
+}
+
+static int goya_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
+ u64 kaddress, phys_addr_t paddress, u32 size)
+{
+ int rc;
+
+ vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
+ VM_DONTCOPY | VM_NORESERVE;
+
+ rc = remap_pfn_range(vma, vma->vm_start, paddress >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+ if (rc)
+ dev_err(hdev->dev, "remap_pfn_range error %d", rc);
+
+ return rc;
+}
+
+static void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi)
+{
+ u32 db_reg_offset, db_value;
+ bool invalid_queue = false;
+
+ switch (hw_queue_id) {
+ case GOYA_QUEUE_ID_DMA_0:
+ db_reg_offset = mmDMA_QM_0_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_DMA_1:
+ db_reg_offset = mmDMA_QM_1_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_DMA_2:
+ db_reg_offset = mmDMA_QM_2_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_DMA_3:
+ db_reg_offset = mmDMA_QM_3_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_DMA_4:
+ db_reg_offset = mmDMA_QM_4_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_CPU_PQ:
+ if (hdev->cpu_queues_enable)
+ db_reg_offset = mmCPU_IF_PF_PQ_PI;
+ else
+ invalid_queue = true;
+ break;
+
+ case GOYA_QUEUE_ID_MME:
+ db_reg_offset = mmMME_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC0:
+ db_reg_offset = mmTPC0_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC1:
+ db_reg_offset = mmTPC1_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC2:
+ db_reg_offset = mmTPC2_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC3:
+ db_reg_offset = mmTPC3_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC4:
+ db_reg_offset = mmTPC4_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC5:
+ db_reg_offset = mmTPC5_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC6:
+ db_reg_offset = mmTPC6_QM_PQ_PI;
+ break;
+
+ case GOYA_QUEUE_ID_TPC7:
+ db_reg_offset = mmTPC7_QM_PQ_PI;
+ break;
+
+ default:
+ invalid_queue = true;
+ }
+
+ if (invalid_queue) {
+ /* Should never get here */
+ dev_err(hdev->dev, "h/w queue %d is invalid. Can't set pi\n",
+ hw_queue_id);
+ return;
+ }
+
+ db_value = pi;
+
+ /* ring the doorbell */
+ WREG32(db_reg_offset, db_value);
+
+ if (hw_queue_id == GOYA_QUEUE_ID_CPU_PQ)
+ WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
+ GOYA_ASYNC_EVENT_ID_PI_UPDATE);
+}
+
+void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val)
+{
+ /* Not needed in Goya */
+}
+
+static void *goya_dma_alloc_coherent(struct hl_device *hdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags)
+{
+ return dma_alloc_coherent(&hdev->pdev->dev, size, dma_handle, flags);
+}
+
+static void goya_dma_free_coherent(struct hl_device *hdev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ dma_free_coherent(&hdev->pdev->dev, size, cpu_addr, dma_handle);
+}
+
+void *goya_get_int_queue_base(struct hl_device *hdev, u32 queue_id,
+ dma_addr_t *dma_handle, u16 *queue_len)
+{
+ void *base;
+ u32 offset;
+
+ *dma_handle = hdev->asic_prop.sram_base_address;
+
+ base = hdev->pcie_bar[SRAM_CFG_BAR_ID];
+
+ switch (queue_id) {
+ case GOYA_QUEUE_ID_MME:
+ offset = MME_QMAN_BASE_OFFSET;
+ *queue_len = MME_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC0:
+ offset = TPC0_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC1:
+ offset = TPC1_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC2:
+ offset = TPC2_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC3:
+ offset = TPC3_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC4:
+ offset = TPC4_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC5:
+ offset = TPC5_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC6:
+ offset = TPC6_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ case GOYA_QUEUE_ID_TPC7:
+ offset = TPC7_QMAN_BASE_OFFSET;
+ *queue_len = TPC_QMAN_LENGTH;
+ break;
+ default:
+ dev_err(hdev->dev, "Got invalid queue id %d\n", queue_id);
+ return NULL;
+ }
+
+ base += offset;
+ *dma_handle += offset;
+
+ return base;
+}
+
+static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct packet_msg_prot *fence_pkt;
+ u32 *fence_ptr;
+ dma_addr_t fence_dma_addr;
+ struct hl_cb *cb;
+ u32 tmp, timeout;
+ int rc;
+
+ if (hdev->pldm)
+ timeout = GOYA_PLDM_QMAN0_TIMEOUT_USEC;
+ else
+ timeout = HL_DEVICE_TIMEOUT_USEC;
+
+ if (!hdev->asic_funcs->is_device_idle(hdev)) {
+ dev_err_ratelimited(hdev->dev,
+ "Can't send KMD job on QMAN0 if device is not idle\n");
+ return -EBUSY;
+ }
+
+ fence_ptr = hdev->asic_funcs->dma_pool_zalloc(hdev, 4, GFP_KERNEL,
+ &fence_dma_addr);
+ if (!fence_ptr) {
+ dev_err(hdev->dev,
+ "Failed to allocate fence memory for QMAN0\n");
+ return -ENOMEM;
+ }
+
+ *fence_ptr = 0;
+
+ if (goya->hw_cap_initialized & HW_CAP_MMU) {
+ WREG32(mmDMA_QM_0_GLBL_PROT, QMAN_DMA_FULLY_TRUSTED);
+ RREG32(mmDMA_QM_0_GLBL_PROT);
+ }
+
+ /*
+ * goya cs parser saves space for 2xpacket_msg_prot at end of CB. For
+ * synchronized kernel jobs we only need space for 1 packet_msg_prot
+ */
+ job->job_cb_size -= sizeof(struct packet_msg_prot);
+
+ cb = job->patched_cb;
+
+ fence_pkt = (struct packet_msg_prot *) (uintptr_t) (cb->kernel_address +
+ job->job_cb_size - sizeof(struct packet_msg_prot));
+
+ tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
+ (1 << GOYA_PKT_CTL_EB_SHIFT) |
+ (1 << GOYA_PKT_CTL_MB_SHIFT);
+ fence_pkt->ctl = cpu_to_le32(tmp);
+ fence_pkt->value = cpu_to_le32(GOYA_QMAN0_FENCE_VAL);
+ fence_pkt->addr = cpu_to_le64(fence_dma_addr +
+ hdev->asic_prop.host_phys_base_address);
+
+ rc = hl_hw_queue_send_cb_no_cmpl(hdev, GOYA_QUEUE_ID_DMA_0,
+ job->job_cb_size, cb->bus_address);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to send CB on QMAN0, %d\n", rc);
+ goto free_fence_ptr;
+ }
+
+ rc = hl_poll_timeout_memory(hdev, (u64) (uintptr_t) fence_ptr, timeout,
+ &tmp);
+
+ hl_hw_queue_inc_ci_kernel(hdev, GOYA_QUEUE_ID_DMA_0);
+
+ if ((rc) || (tmp != GOYA_QMAN0_FENCE_VAL)) {
+ dev_err(hdev->dev, "QMAN0 Job hasn't finished in time\n");
+ rc = -ETIMEDOUT;
+ }
+
+free_fence_ptr:
+ hdev->asic_funcs->dma_pool_free(hdev, (void *) fence_ptr,
+ fence_dma_addr);
+
+ if (goya->hw_cap_initialized & HW_CAP_MMU) {
+ WREG32(mmDMA_QM_0_GLBL_PROT, QMAN_DMA_PARTLY_TRUSTED);
+ RREG32(mmDMA_QM_0_GLBL_PROT);
+ }
+
+ return rc;
+}
+
+int goya_send_cpu_message(struct hl_device *hdev, u32 *msg, u16 len,
+ u32 timeout, long *result)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct armcp_packet *pkt;
+ dma_addr_t pkt_dma_addr;
+ u32 tmp;
+ int rc = 0;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_CPU_Q)) {
+ if (result)
+ *result = 0;
+ return 0;
+ }
+
+ if (len > CPU_CB_SIZE) {
+ dev_err(hdev->dev, "Invalid CPU message size of %d bytes\n",
+ len);
+ return -ENOMEM;
+ }
+
+ pkt = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, len,
+ &pkt_dma_addr);
+ if (!pkt) {
+ dev_err(hdev->dev,
+ "Failed to allocate DMA memory for packet to CPU\n");
+ return -ENOMEM;
+ }
+
+ memcpy(pkt, msg, len);
+
+ mutex_lock(&hdev->send_cpu_message_lock);
+
+ if (hdev->disabled)
+ goto out;
+
+ if (hdev->device_cpu_disabled) {
+ rc = -EIO;
+ goto out;
+ }
+
+ rc = hl_hw_queue_send_cb_no_cmpl(hdev, GOYA_QUEUE_ID_CPU_PQ, len,
+ pkt_dma_addr);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to send CB on CPU PQ (%d)\n", rc);
+ goto out;
+ }
+
+ rc = hl_poll_timeout_memory(hdev, (u64) (uintptr_t) &pkt->fence,
+ timeout, &tmp);
+
+ hl_hw_queue_inc_ci_kernel(hdev, GOYA_QUEUE_ID_CPU_PQ);
+
+ if (rc == -ETIMEDOUT) {
+ dev_err(hdev->dev, "Timeout while waiting for device CPU\n");
+ hdev->device_cpu_disabled = true;
+ goto out;
+ }
+
+ if (tmp == ARMCP_PACKET_FENCE_VAL) {
+ u32 ctl = le32_to_cpu(pkt->ctl);
+
+ rc = (ctl & ARMCP_PKT_CTL_RC_MASK) >> ARMCP_PKT_CTL_RC_SHIFT;
+ if (rc) {
+ dev_err(hdev->dev,
+ "F/W ERROR %d for CPU packet %d\n",
+ rc, (ctl & ARMCP_PKT_CTL_OPCODE_MASK)
+ >> ARMCP_PKT_CTL_OPCODE_SHIFT);
+ rc = -EINVAL;
+ } else if (result) {
+ *result = (long) le64_to_cpu(pkt->result);
+ }
+ } else {
+ dev_err(hdev->dev, "CPU packet wrong fence value\n");
+ rc = -EINVAL;
+ }
+
+out:
+ mutex_unlock(&hdev->send_cpu_message_lock);
+
+ hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, len, pkt);
+
+ return rc;
+}
+
+int goya_test_queue(struct hl_device *hdev, u32 hw_queue_id)
+{
+ struct packet_msg_prot *fence_pkt;
+ dma_addr_t pkt_dma_addr;
+ u32 fence_val, tmp;
+ dma_addr_t fence_dma_addr;
+ u32 *fence_ptr;
+ int rc;
+
+ fence_val = GOYA_QMAN0_FENCE_VAL;
+
+ fence_ptr = hdev->asic_funcs->dma_pool_zalloc(hdev, 4, GFP_KERNEL,
+ &fence_dma_addr);
+ if (!fence_ptr) {
+ dev_err(hdev->dev,
+ "Failed to allocate memory for queue testing\n");
+ return -ENOMEM;
+ }
+
+ *fence_ptr = 0;
+
+ fence_pkt = hdev->asic_funcs->dma_pool_zalloc(hdev,
+ sizeof(struct packet_msg_prot),
+ GFP_KERNEL, &pkt_dma_addr);
+ if (!fence_pkt) {
+ dev_err(hdev->dev,
+ "Failed to allocate packet for queue testing\n");
+ rc = -ENOMEM;
+ goto free_fence_ptr;
+ }
+
+ tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
+ (1 << GOYA_PKT_CTL_EB_SHIFT) |
+ (1 << GOYA_PKT_CTL_MB_SHIFT);
+ fence_pkt->ctl = cpu_to_le32(tmp);
+ fence_pkt->value = cpu_to_le32(fence_val);
+ fence_pkt->addr = cpu_to_le64(fence_dma_addr +
+ hdev->asic_prop.host_phys_base_address);
+
+ rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id,
+ sizeof(struct packet_msg_prot),
+ pkt_dma_addr);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to send fence packet\n");
+ goto free_pkt;
+ }
+
+ rc = hl_poll_timeout_memory(hdev, (u64) (uintptr_t) fence_ptr,
+ GOYA_TEST_QUEUE_WAIT_USEC, &tmp);
+
+ hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
+
+ if ((!rc) && (tmp == fence_val)) {
+ dev_info(hdev->dev,
+ "queue test on H/W queue %d succeeded\n",
+ hw_queue_id);
+ } else {
+ dev_err(hdev->dev,
+ "H/W queue %d test failed (scratch(0x%08llX) == 0x%08X)\n",
+ hw_queue_id, (unsigned long long) fence_dma_addr, tmp);
+ rc = -EINVAL;
+ }
+
+free_pkt:
+ hdev->asic_funcs->dma_pool_free(hdev, (void *) fence_pkt,
+ pkt_dma_addr);
+free_fence_ptr:
+ hdev->asic_funcs->dma_pool_free(hdev, (void *) fence_ptr,
+ fence_dma_addr);
+ return rc;
+}
+
+int goya_test_cpu_queue(struct hl_device *hdev)
+{
+ struct armcp_packet test_pkt;
+ long result;
+ int rc;
+
+ /* cpu_queues_enable flag is always checked in send cpu message */
+
+ memset(&test_pkt, 0, sizeof(test_pkt));
+
+ test_pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEST <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ test_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &test_pkt,
+ sizeof(test_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
+
+ if (!rc) {
+ if (result == ARMCP_PACKET_FENCE_VAL)
+ dev_info(hdev->dev,
+ "queue test on CPU queue succeeded\n");
+ else
+ dev_err(hdev->dev,
+ "CPU queue test failed (0x%08lX)\n", result);
+ } else {
+ dev_err(hdev->dev, "CPU queue test failed, error %d\n", rc);
+ }
+
+ return rc;
+}
+
+static int goya_test_queues(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int i, rc, ret_val = 0;
+
+ for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++) {
+ rc = goya_test_queue(hdev, i);
+ if (rc)
+ ret_val = -EINVAL;
+ }
+
+ if (hdev->cpu_queues_enable) {
+ rc = goya->test_cpu_queue(hdev);
+ if (rc)
+ ret_val = -EINVAL;
+ }
+
+ return ret_val;
+}
+
+static void *goya_dma_pool_zalloc(struct hl_device *hdev, size_t size,
+ gfp_t mem_flags, dma_addr_t *dma_handle)
+{
+ if (size > GOYA_DMA_POOL_BLK_SIZE)
+ return NULL;
+
+ return dma_pool_zalloc(hdev->dma_pool, mem_flags, dma_handle);
+}
+
+static void goya_dma_pool_free(struct hl_device *hdev, void *vaddr,
+ dma_addr_t dma_addr)
+{
+ dma_pool_free(hdev->dma_pool, vaddr, dma_addr);
+}
+
+static void *goya_cpu_accessible_dma_pool_alloc(struct hl_device *hdev,
+ size_t size, dma_addr_t *dma_handle)
+{
+ u64 kernel_addr;
+
+ /* roundup to CPU_PKT_SIZE */
+ size = (size + (CPU_PKT_SIZE - 1)) & CPU_PKT_MASK;
+
+ kernel_addr = gen_pool_alloc(hdev->cpu_accessible_dma_pool, size);
+
+ *dma_handle = hdev->cpu_accessible_dma_address +
+ (kernel_addr - (u64) (uintptr_t) hdev->cpu_accessible_dma_mem);
+
+ return (void *) (uintptr_t) kernel_addr;
+}
+
+static void goya_cpu_accessible_dma_pool_free(struct hl_device *hdev,
+ size_t size, void *vaddr)
+{
+ /* roundup to CPU_PKT_SIZE */
+ size = (size + (CPU_PKT_SIZE - 1)) & CPU_PKT_MASK;
+
+ gen_pool_free(hdev->cpu_accessible_dma_pool, (u64) (uintptr_t) vaddr,
+ size);
+}
+
+static int goya_dma_map_sg(struct hl_device *hdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ if (!dma_map_sg(&hdev->pdev->dev, sg, nents, dir))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void goya_dma_unmap_sg(struct hl_device *hdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ dma_unmap_sg(&hdev->pdev->dev, sg, nents, dir);
+}
+
+u32 goya_get_dma_desc_list_size(struct hl_device *hdev, struct sg_table *sgt)
+{
+ struct scatterlist *sg, *sg_next_iter;
+ u32 count, dma_desc_cnt;
+ u64 len, len_next;
+ dma_addr_t addr, addr_next;
+
+ dma_desc_cnt = 0;
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, count) {
+
+ len = sg_dma_len(sg);
+ addr = sg_dma_address(sg);
+
+ if (len == 0)
+ break;
+
+ while ((count + 1) < sgt->nents) {
+ sg_next_iter = sg_next(sg);
+ len_next = sg_dma_len(sg_next_iter);
+ addr_next = sg_dma_address(sg_next_iter);
+
+ if (len_next == 0)
+ break;
+
+ if ((addr + len == addr_next) &&
+ (len + len_next <= DMA_MAX_TRANSFER_SIZE)) {
+ len += len_next;
+ count++;
+ sg = sg_next_iter;
+ } else {
+ break;
+ }
+ }
+
+ dma_desc_cnt++;
+ }
+
+ return dma_desc_cnt * sizeof(struct packet_lin_dma);
+}
+
+static int goya_pin_memory_before_cs(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt,
+ u64 addr, enum dma_data_direction dir)
+{
+ struct hl_userptr *userptr;
+ int rc;
+
+ if (hl_userptr_is_pinned(hdev, addr, le32_to_cpu(user_dma_pkt->tsize),
+ parser->job_userptr_list, &userptr))
+ goto already_pinned;
+
+ userptr = kzalloc(sizeof(*userptr), GFP_ATOMIC);
+ if (!userptr)
+ return -ENOMEM;
+
+ rc = hl_pin_host_memory(hdev, addr, le32_to_cpu(user_dma_pkt->tsize),
+ userptr);
+ if (rc)
+ goto free_userptr;
+
+ list_add_tail(&userptr->job_node, parser->job_userptr_list);
+
+ rc = hdev->asic_funcs->asic_dma_map_sg(hdev, userptr->sgt->sgl,
+ userptr->sgt->nents, dir);
+ if (rc) {
+ dev_err(hdev->dev, "failed to map sgt with DMA region\n");
+ goto unpin_memory;
+ }
+
+ userptr->dma_mapped = true;
+ userptr->dir = dir;
+
+already_pinned:
+ parser->patched_cb_size +=
+ goya_get_dma_desc_list_size(hdev, userptr->sgt);
+
+ return 0;
+
+unpin_memory:
+ hl_unpin_host_memory(hdev, userptr);
+free_userptr:
+ kfree(userptr);
+ return rc;
+}
+
+static int goya_validate_dma_pkt_host(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt)
+{
+ u64 device_memory_addr, addr;
+ enum dma_data_direction dir;
+ enum goya_dma_direction user_dir;
+ bool sram_addr = true;
+ bool skip_host_mem_pin = false;
+ bool user_memset;
+ u32 ctl;
+ int rc = 0;
+
+ ctl = le32_to_cpu(user_dma_pkt->ctl);
+
+ user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT;
+
+ user_memset = (ctl & GOYA_PKT_LIN_DMA_CTL_MEMSET_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_MEMSET_SHIFT;
+
+ switch (user_dir) {
+ case DMA_HOST_TO_DRAM:
+ dev_dbg(hdev->dev, "DMA direction is HOST --> DRAM\n");
+ dir = DMA_TO_DEVICE;
+ sram_addr = false;
+ addr = le64_to_cpu(user_dma_pkt->src_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ if (user_memset)
+ skip_host_mem_pin = true;
+ break;
+
+ case DMA_DRAM_TO_HOST:
+ dev_dbg(hdev->dev, "DMA direction is DRAM --> HOST\n");
+ dir = DMA_FROM_DEVICE;
+ sram_addr = false;
+ addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->src_addr);
+ break;
+
+ case DMA_HOST_TO_SRAM:
+ dev_dbg(hdev->dev, "DMA direction is HOST --> SRAM\n");
+ dir = DMA_TO_DEVICE;
+ addr = le64_to_cpu(user_dma_pkt->src_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ if (user_memset)
+ skip_host_mem_pin = true;
+ break;
+
+ case DMA_SRAM_TO_HOST:
+ dev_dbg(hdev->dev, "DMA direction is SRAM --> HOST\n");
+ dir = DMA_FROM_DEVICE;
+ addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->src_addr);
+ break;
+ default:
+ dev_err(hdev->dev, "DMA direction is undefined\n");
+ return -EFAULT;
+ }
+
+ if (parser->ctx_id != HL_KERNEL_ASID_ID) {
+ if (sram_addr) {
+ if (!hl_mem_area_inside_range(device_memory_addr,
+ le32_to_cpu(user_dma_pkt->tsize),
+ hdev->asic_prop.sram_user_base_address,
+ hdev->asic_prop.sram_end_address)) {
+
+ dev_err(hdev->dev,
+ "SRAM address 0x%llx + 0x%x is invalid\n",
+ device_memory_addr,
+ user_dma_pkt->tsize);
+ return -EFAULT;
+ }
+ } else {
+ if (!hl_mem_area_inside_range(device_memory_addr,
+ le32_to_cpu(user_dma_pkt->tsize),
+ hdev->asic_prop.dram_user_base_address,
+ hdev->asic_prop.dram_end_address)) {
+
+ dev_err(hdev->dev,
+ "DRAM address 0x%llx + 0x%x is invalid\n",
+ device_memory_addr,
+ user_dma_pkt->tsize);
+ return -EFAULT;
+ }
+ }
+ }
+
+ if (skip_host_mem_pin)
+ parser->patched_cb_size += sizeof(*user_dma_pkt);
+ else {
+ if ((dir == DMA_TO_DEVICE) &&
+ (parser->hw_queue_id > GOYA_QUEUE_ID_DMA_1)) {
+ dev_err(hdev->dev,
+ "Can't DMA from host on queue other then 1\n");
+ return -EFAULT;
+ }
+
+ rc = goya_pin_memory_before_cs(hdev, parser, user_dma_pkt,
+ addr, dir);
+ }
+
+ return rc;
+}
+
+static int goya_validate_dma_pkt_no_host(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt)
+{
+ u64 sram_memory_addr, dram_memory_addr;
+ enum goya_dma_direction user_dir;
+ u32 ctl;
+
+ ctl = le32_to_cpu(user_dma_pkt->ctl);
+ user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT;
+
+ if (user_dir == DMA_DRAM_TO_SRAM) {
+ dev_dbg(hdev->dev, "DMA direction is DRAM --> SRAM\n");
+ dram_memory_addr = le64_to_cpu(user_dma_pkt->src_addr);
+ sram_memory_addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ } else {
+ dev_dbg(hdev->dev, "DMA direction is SRAM --> DRAM\n");
+ sram_memory_addr = le64_to_cpu(user_dma_pkt->src_addr);
+ dram_memory_addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ }
+
+ if (!hl_mem_area_inside_range(sram_memory_addr,
+ le32_to_cpu(user_dma_pkt->tsize),
+ hdev->asic_prop.sram_user_base_address,
+ hdev->asic_prop.sram_end_address)) {
+ dev_err(hdev->dev, "SRAM address 0x%llx + 0x%x is invalid\n",
+ sram_memory_addr, user_dma_pkt->tsize);
+ return -EFAULT;
+ }
+
+ if (!hl_mem_area_inside_range(dram_memory_addr,
+ le32_to_cpu(user_dma_pkt->tsize),
+ hdev->asic_prop.dram_user_base_address,
+ hdev->asic_prop.dram_end_address)) {
+ dev_err(hdev->dev, "DRAM address 0x%llx + 0x%x is invalid\n",
+ dram_memory_addr, user_dma_pkt->tsize);
+ return -EFAULT;
+ }
+
+ parser->patched_cb_size += sizeof(*user_dma_pkt);
+
+ return 0;
+}
+
+static int goya_validate_dma_pkt_no_mmu(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt)
+{
+ enum goya_dma_direction user_dir;
+ u32 ctl;
+ int rc;
+
+ dev_dbg(hdev->dev, "DMA packet details:\n");
+ dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
+ dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
+ dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+
+ ctl = le32_to_cpu(user_dma_pkt->ctl);
+ user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT;
+
+ /*
+ * Special handling for DMA with size 0. The H/W has a bug where
+ * this can cause the QMAN DMA to get stuck, so block it here.
+ */
+ if (user_dma_pkt->tsize == 0) {
+ dev_err(hdev->dev,
+ "Got DMA with size 0, might reset the device\n");
+ return -EINVAL;
+ }
+
+ if ((user_dir == DMA_DRAM_TO_SRAM) || (user_dir == DMA_SRAM_TO_DRAM))
+ rc = goya_validate_dma_pkt_no_host(hdev, parser, user_dma_pkt);
+ else
+ rc = goya_validate_dma_pkt_host(hdev, parser, user_dma_pkt);
+
+ return rc;
+}
+
+static int goya_validate_dma_pkt_mmu(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt)
+{
+ dev_dbg(hdev->dev, "DMA packet details:\n");
+ dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
+ dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
+ dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+
+ /*
+ * WA for HW-23.
+ * We can't allow user to read from Host using QMANs other than 1.
+ */
+ if (parser->hw_queue_id > GOYA_QUEUE_ID_DMA_1 &&
+ hl_mem_area_inside_range(le64_to_cpu(user_dma_pkt->src_addr),
+ le32_to_cpu(user_dma_pkt->tsize),
+ hdev->asic_prop.va_space_host_start_address,
+ hdev->asic_prop.va_space_host_end_address)) {
+ dev_err(hdev->dev,
+ "Can't DMA from host on queue other then 1\n");
+ return -EFAULT;
+ }
+
+ if (user_dma_pkt->tsize == 0) {
+ dev_err(hdev->dev,
+ "Got DMA with size 0, might reset the device\n");
+ return -EINVAL;
+ }
+
+ parser->patched_cb_size += sizeof(*user_dma_pkt);
+
+ return 0;
+}
+
+static int goya_validate_wreg32(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_wreg32 *wreg_pkt)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 sob_start_addr, sob_end_addr;
+ u16 reg_offset;
+
+ reg_offset = le32_to_cpu(wreg_pkt->ctl) &
+ GOYA_PKT_WREG32_CTL_REG_OFFSET_MASK;
+
+ dev_dbg(hdev->dev, "WREG32 packet details:\n");
+ dev_dbg(hdev->dev, "reg_offset == 0x%x\n", reg_offset);
+ dev_dbg(hdev->dev, "value == 0x%x\n", wreg_pkt->value);
+
+ if (reg_offset != (mmDMA_CH_0_WR_COMP_ADDR_LO & 0x1FFF)) {
+ dev_err(hdev->dev, "WREG32 packet with illegal address 0x%x\n",
+ reg_offset);
+ return -EPERM;
+ }
+
+ /*
+ * With MMU, DMA channels are not secured, so it doesn't matter where
+ * the WR COMP will be written to because it will go out with
+ * non-secured property
+ */
+ if (goya->hw_cap_initialized & HW_CAP_MMU)
+ return 0;
+
+ sob_start_addr = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_0);
+ sob_end_addr = lower_32_bits(CFG_BASE + mmSYNC_MNGR_SOB_OBJ_1023);
+
+ if ((le32_to_cpu(wreg_pkt->value) < sob_start_addr) ||
+ (le32_to_cpu(wreg_pkt->value) > sob_end_addr)) {
+
+ dev_err(hdev->dev, "WREG32 packet with illegal value 0x%x\n",
+ wreg_pkt->value);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int goya_validate_cb(struct hl_device *hdev,
+ struct hl_cs_parser *parser, bool is_mmu)
+{
+ u32 cb_parsed_length = 0;
+ int rc = 0;
+
+ parser->patched_cb_size = 0;
+
+ /* cb_user_size is more than 0 so loop will always be executed */
+ while (cb_parsed_length < parser->user_cb_size) {
+ enum packet_id pkt_id;
+ u16 pkt_size;
+ void *user_pkt;
+
+ user_pkt = (void *) (uintptr_t)
+ (parser->user_cb->kernel_address + cb_parsed_length);
+
+ pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+ PACKET_HEADER_PACKET_ID_MASK) >>
+ PACKET_HEADER_PACKET_ID_SHIFT);
+
+ pkt_size = goya_packet_sizes[pkt_id];
+ cb_parsed_length += pkt_size;
+ if (cb_parsed_length > parser->user_cb_size) {
+ dev_err(hdev->dev,
+ "packet 0x%x is out of CB boundary\n", pkt_id);
+ rc = -EINVAL;
+ break;
+ }
+
+ switch (pkt_id) {
+ case PACKET_WREG_32:
+ /*
+ * Although it is validated after copy in patch_cb(),
+ * need to validate here as well because patch_cb() is
+ * not called in MMU path while this function is called
+ */
+ rc = goya_validate_wreg32(hdev, parser, user_pkt);
+ break;
+
+ case PACKET_WREG_BULK:
+ dev_err(hdev->dev,
+ "User not allowed to use WREG_BULK\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_MSG_PROT:
+ dev_err(hdev->dev,
+ "User not allowed to use MSG_PROT\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_CP_DMA:
+ dev_err(hdev->dev, "User not allowed to use CP_DMA\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_STOP:
+ dev_err(hdev->dev, "User not allowed to use STOP\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_LIN_DMA:
+ if (is_mmu)
+ rc = goya_validate_dma_pkt_mmu(hdev, parser,
+ user_pkt);
+ else
+ rc = goya_validate_dma_pkt_no_mmu(hdev, parser,
+ user_pkt);
+ break;
+
+ case PACKET_MSG_LONG:
+ case PACKET_MSG_SHORT:
+ case PACKET_FENCE:
+ case PACKET_NOP:
+ parser->patched_cb_size += pkt_size;
+ break;
+
+ default:
+ dev_err(hdev->dev, "Invalid packet header 0x%x\n",
+ pkt_id);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc)
+ break;
+ }
+
+ /*
+ * The new CB should have space at the end for two MSG_PROT packets:
+ * 1. A packet that will act as a completion packet
+ * 2. A packet that will generate MSI-X interrupt
+ */
+ parser->patched_cb_size += sizeof(struct packet_msg_prot) * 2;
+
+ return rc;
+}
+
+static int goya_patch_dma_packet(struct hl_device *hdev,
+ struct hl_cs_parser *parser,
+ struct packet_lin_dma *user_dma_pkt,
+ struct packet_lin_dma *new_dma_pkt,
+ u32 *new_dma_pkt_size)
+{
+ struct hl_userptr *userptr;
+ struct scatterlist *sg, *sg_next_iter;
+ u32 count, dma_desc_cnt;
+ u64 len, len_next;
+ dma_addr_t dma_addr, dma_addr_next;
+ enum goya_dma_direction user_dir;
+ u64 device_memory_addr, addr;
+ enum dma_data_direction dir;
+ struct sg_table *sgt;
+ bool skip_host_mem_pin = false;
+ bool user_memset;
+ u32 user_rdcomp_mask, user_wrcomp_mask, ctl;
+
+ ctl = le32_to_cpu(user_dma_pkt->ctl);
+
+ user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT;
+
+ user_memset = (ctl & GOYA_PKT_LIN_DMA_CTL_MEMSET_MASK) >>
+ GOYA_PKT_LIN_DMA_CTL_MEMSET_SHIFT;
+
+ if ((user_dir == DMA_DRAM_TO_SRAM) || (user_dir == DMA_SRAM_TO_DRAM) ||
+ (user_dma_pkt->tsize == 0)) {
+ memcpy(new_dma_pkt, user_dma_pkt, sizeof(*new_dma_pkt));
+ *new_dma_pkt_size = sizeof(*new_dma_pkt);
+ return 0;
+ }
+
+ if ((user_dir == DMA_HOST_TO_DRAM) || (user_dir == DMA_HOST_TO_SRAM)) {
+ addr = le64_to_cpu(user_dma_pkt->src_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ dir = DMA_TO_DEVICE;
+ if (user_memset)
+ skip_host_mem_pin = true;
+ } else {
+ addr = le64_to_cpu(user_dma_pkt->dst_addr);
+ device_memory_addr = le64_to_cpu(user_dma_pkt->src_addr);
+ dir = DMA_FROM_DEVICE;
+ }
+
+ if ((!skip_host_mem_pin) &&
+ (hl_userptr_is_pinned(hdev, addr,
+ le32_to_cpu(user_dma_pkt->tsize),
+ parser->job_userptr_list, &userptr) == false)) {
+ dev_err(hdev->dev, "Userptr 0x%llx + 0x%x NOT mapped\n",
+ addr, user_dma_pkt->tsize);
+ return -EFAULT;
+ }
+
+ if ((user_memset) && (dir == DMA_TO_DEVICE)) {
+ memcpy(new_dma_pkt, user_dma_pkt, sizeof(*user_dma_pkt));
+ *new_dma_pkt_size = sizeof(*user_dma_pkt);
+ return 0;
+ }
+
+ user_rdcomp_mask = ctl & GOYA_PKT_LIN_DMA_CTL_RDCOMP_MASK;
+
+ user_wrcomp_mask = ctl & GOYA_PKT_LIN_DMA_CTL_WRCOMP_MASK;
+
+ sgt = userptr->sgt;
+ dma_desc_cnt = 0;
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, count) {
+ len = sg_dma_len(sg);
+ dma_addr = sg_dma_address(sg);
+
+ if (len == 0)
+ break;
+
+ while ((count + 1) < sgt->nents) {
+ sg_next_iter = sg_next(sg);
+ len_next = sg_dma_len(sg_next_iter);
+ dma_addr_next = sg_dma_address(sg_next_iter);
+
+ if (len_next == 0)
+ break;
+
+ if ((dma_addr + len == dma_addr_next) &&
+ (len + len_next <= DMA_MAX_TRANSFER_SIZE)) {
+ len += len_next;
+ count++;
+ sg = sg_next_iter;
+ } else {
+ break;
+ }
+ }
+
+ ctl = le32_to_cpu(user_dma_pkt->ctl);
+ if (likely(dma_desc_cnt))
+ ctl &= ~GOYA_PKT_CTL_EB_MASK;
+ ctl &= ~(GOYA_PKT_LIN_DMA_CTL_RDCOMP_MASK |
+ GOYA_PKT_LIN_DMA_CTL_WRCOMP_MASK);
+ new_dma_pkt->ctl = cpu_to_le32(ctl);
+ new_dma_pkt->tsize = cpu_to_le32((u32) len);
+
+ dma_addr += hdev->asic_prop.host_phys_base_address;
+
+ if (dir == DMA_TO_DEVICE) {
+ new_dma_pkt->src_addr = cpu_to_le64(dma_addr);
+ new_dma_pkt->dst_addr = cpu_to_le64(device_memory_addr);
+ } else {
+ new_dma_pkt->src_addr = cpu_to_le64(device_memory_addr);
+ new_dma_pkt->dst_addr = cpu_to_le64(dma_addr);
+ }
+
+ if (!user_memset)
+ device_memory_addr += len;
+ dma_desc_cnt++;
+ new_dma_pkt++;
+ }
+
+ if (!dma_desc_cnt) {
+ dev_err(hdev->dev,
+ "Error of 0 SG entries when patching DMA packet\n");
+ return -EFAULT;
+ }
+
+ /* Fix the last dma packet - rdcomp/wrcomp must be as user set them */
+ new_dma_pkt--;
+ new_dma_pkt->ctl |= cpu_to_le32(user_rdcomp_mask | user_wrcomp_mask);
+
+ *new_dma_pkt_size = dma_desc_cnt * sizeof(struct packet_lin_dma);
+
+ return 0;
+}
+
+static int goya_patch_cb(struct hl_device *hdev,
+ struct hl_cs_parser *parser)
+{
+ u32 cb_parsed_length = 0;
+ u32 cb_patched_cur_length = 0;
+ int rc = 0;
+
+ /* cb_user_size is more than 0 so loop will always be executed */
+ while (cb_parsed_length < parser->user_cb_size) {
+ enum packet_id pkt_id;
+ u16 pkt_size;
+ u32 new_pkt_size = 0;
+ void *user_pkt, *kernel_pkt;
+
+ user_pkt = (void *) (uintptr_t)
+ (parser->user_cb->kernel_address + cb_parsed_length);
+ kernel_pkt = (void *) (uintptr_t)
+ (parser->patched_cb->kernel_address +
+ cb_patched_cur_length);
+
+ pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+ PACKET_HEADER_PACKET_ID_MASK) >>
+ PACKET_HEADER_PACKET_ID_SHIFT);
+
+ pkt_size = goya_packet_sizes[pkt_id];
+ cb_parsed_length += pkt_size;
+ if (cb_parsed_length > parser->user_cb_size) {
+ dev_err(hdev->dev,
+ "packet 0x%x is out of CB boundary\n", pkt_id);
+ rc = -EINVAL;
+ break;
+ }
+
+ switch (pkt_id) {
+ case PACKET_LIN_DMA:
+ rc = goya_patch_dma_packet(hdev, parser, user_pkt,
+ kernel_pkt, &new_pkt_size);
+ cb_patched_cur_length += new_pkt_size;
+ break;
+
+ case PACKET_WREG_32:
+ memcpy(kernel_pkt, user_pkt, pkt_size);
+ cb_patched_cur_length += pkt_size;
+ rc = goya_validate_wreg32(hdev, parser, kernel_pkt);
+ break;
+
+ case PACKET_WREG_BULK:
+ dev_err(hdev->dev,
+ "User not allowed to use WREG_BULK\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_MSG_PROT:
+ dev_err(hdev->dev,
+ "User not allowed to use MSG_PROT\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_CP_DMA:
+ dev_err(hdev->dev, "User not allowed to use CP_DMA\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_STOP:
+ dev_err(hdev->dev, "User not allowed to use STOP\n");
+ rc = -EPERM;
+ break;
+
+ case PACKET_MSG_LONG:
+ case PACKET_MSG_SHORT:
+ case PACKET_FENCE:
+ case PACKET_NOP:
+ memcpy(kernel_pkt, user_pkt, pkt_size);
+ cb_patched_cur_length += pkt_size;
+ break;
+
+ default:
+ dev_err(hdev->dev, "Invalid packet header 0x%x\n",
+ pkt_id);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+static int goya_parse_cb_mmu(struct hl_device *hdev,
+ struct hl_cs_parser *parser)
+{
+ u64 patched_cb_handle;
+ u32 patched_cb_size;
+ struct hl_cb *user_cb;
+ int rc;
+
+ /*
+ * The new CB should have space at the end for two MSG_PROT pkt:
+ * 1. A packet that will act as a completion packet
+ * 2. A packet that will generate MSI-X interrupt
+ */
+ parser->patched_cb_size = parser->user_cb_size +
+ sizeof(struct packet_msg_prot) * 2;
+
+ rc = hl_cb_create(hdev, &hdev->kernel_cb_mgr,
+ parser->patched_cb_size,
+ &patched_cb_handle, HL_KERNEL_ASID_ID);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to allocate patched CB for DMA CS %d\n",
+ rc);
+ return rc;
+ }
+
+ patched_cb_handle >>= PAGE_SHIFT;
+ parser->patched_cb = hl_cb_get(hdev, &hdev->kernel_cb_mgr,
+ (u32) patched_cb_handle);
+ /* hl_cb_get should never fail here so use kernel WARN */
+ WARN(!parser->patched_cb, "DMA CB handle invalid 0x%x\n",
+ (u32) patched_cb_handle);
+ if (!parser->patched_cb) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ /*
+ * The check that parser->user_cb_size <= parser->user_cb->size was done
+ * in validate_queue_index().
+ */
+ memcpy((void *) (uintptr_t) parser->patched_cb->kernel_address,
+ (void *) (uintptr_t) parser->user_cb->kernel_address,
+ parser->user_cb_size);
+
+ patched_cb_size = parser->patched_cb_size;
+
+ /* validate patched CB instead of user CB */
+ user_cb = parser->user_cb;
+ parser->user_cb = parser->patched_cb;
+ rc = goya_validate_cb(hdev, parser, true);
+ parser->user_cb = user_cb;
+
+ if (rc) {
+ hl_cb_put(parser->patched_cb);
+ goto out;
+ }
+
+ if (patched_cb_size != parser->patched_cb_size) {
+ dev_err(hdev->dev, "user CB size mismatch\n");
+ hl_cb_put(parser->patched_cb);
+ rc = -EINVAL;
+ goto out;
+ }
+
+out:
+ /*
+ * Always call cb destroy here because we still have 1 reference
+ * to it by calling cb_get earlier. After the job will be completed,
+ * cb_put will release it, but here we want to remove it from the
+ * idr
+ */
+ hl_cb_destroy(hdev, &hdev->kernel_cb_mgr,
+ patched_cb_handle << PAGE_SHIFT);
+
+ return rc;
+}
+
+static int goya_parse_cb_no_mmu(struct hl_device *hdev,
+ struct hl_cs_parser *parser)
+{
+ u64 patched_cb_handle;
+ int rc;
+
+ rc = goya_validate_cb(hdev, parser, false);
+
+ if (rc)
+ goto free_userptr;
+
+ rc = hl_cb_create(hdev, &hdev->kernel_cb_mgr,
+ parser->patched_cb_size,
+ &patched_cb_handle, HL_KERNEL_ASID_ID);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to allocate patched CB for DMA CS %d\n", rc);
+ goto free_userptr;
+ }
+
+ patched_cb_handle >>= PAGE_SHIFT;
+ parser->patched_cb = hl_cb_get(hdev, &hdev->kernel_cb_mgr,
+ (u32) patched_cb_handle);
+ /* hl_cb_get should never fail here so use kernel WARN */
+ WARN(!parser->patched_cb, "DMA CB handle invalid 0x%x\n",
+ (u32) patched_cb_handle);
+ if (!parser->patched_cb) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ rc = goya_patch_cb(hdev, parser);
+
+ if (rc)
+ hl_cb_put(parser->patched_cb);
+
+out:
+ /*
+ * Always call cb destroy here because we still have 1 reference
+ * to it by calling cb_get earlier. After the job will be completed,
+ * cb_put will release it, but here we want to remove it from the
+ * idr
+ */
+ hl_cb_destroy(hdev, &hdev->kernel_cb_mgr,
+ patched_cb_handle << PAGE_SHIFT);
+
+free_userptr:
+ if (rc)
+ hl_userptr_delete_list(hdev, parser->job_userptr_list);
+ return rc;
+}
+
+static int goya_parse_cb_no_ext_quque(struct hl_device *hdev,
+ struct hl_cs_parser *parser)
+{
+ struct asic_fixed_properties *asic_prop = &hdev->asic_prop;
+ struct goya_device *goya = hdev->asic_specific;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU)) {
+ /* For internal queue jobs, just check if cb address is valid */
+ if (hl_mem_area_inside_range(
+ (u64) (uintptr_t) parser->user_cb,
+ parser->user_cb_size,
+ asic_prop->sram_user_base_address,
+ asic_prop->sram_end_address))
+ return 0;
+
+ if (hl_mem_area_inside_range(
+ (u64) (uintptr_t) parser->user_cb,
+ parser->user_cb_size,
+ asic_prop->dram_user_base_address,
+ asic_prop->dram_end_address))
+ return 0;
+
+ dev_err(hdev->dev,
+ "Internal CB address %px + 0x%x is not in SRAM nor in DRAM\n",
+ parser->user_cb, parser->user_cb_size);
+
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ if (!parser->ext_queue)
+ return goya_parse_cb_no_ext_quque(hdev, parser);
+
+ if ((goya->hw_cap_initialized & HW_CAP_MMU) && parser->use_virt_addr)
+ return goya_parse_cb_mmu(hdev, parser);
+ else
+ return goya_parse_cb_no_mmu(hdev, parser);
+}
+
+void goya_add_end_of_cb_packets(u64 kernel_address, u32 len, u64 cq_addr,
+ u32 cq_val, u32 msix_vec)
+{
+ struct packet_msg_prot *cq_pkt;
+ u32 tmp;
+
+ cq_pkt = (struct packet_msg_prot *) (uintptr_t)
+ (kernel_address + len - (sizeof(struct packet_msg_prot) * 2));
+
+ tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
+ (1 << GOYA_PKT_CTL_EB_SHIFT) |
+ (1 << GOYA_PKT_CTL_MB_SHIFT);
+ cq_pkt->ctl = cpu_to_le32(tmp);
+ cq_pkt->value = cpu_to_le32(cq_val);
+ cq_pkt->addr = cpu_to_le64(cq_addr);
+
+ cq_pkt++;
+
+ tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
+ (1 << GOYA_PKT_CTL_MB_SHIFT);
+ cq_pkt->ctl = cpu_to_le32(tmp);
+ cq_pkt->value = cpu_to_le32(msix_vec & 0x7FF);
+ cq_pkt->addr = cpu_to_le64(CFG_BASE + mmPCIE_DBI_MSIX_DOORBELL_OFF);
+}
+
+static void goya_update_eq_ci(struct hl_device *hdev, u32 val)
+{
+ WREG32(mmPSOC_GLOBAL_CONF_SCRATCHPAD_6, val);
+}
+
+static void goya_restore_phase_topology(struct hl_device *hdev)
+{
+ int i, num_of_sob_in_longs, num_of_mon_in_longs;
+
+ num_of_sob_in_longs =
+ ((mmSYNC_MNGR_SOB_OBJ_1023 - mmSYNC_MNGR_SOB_OBJ_0) + 4);
+
+ num_of_mon_in_longs =
+ ((mmSYNC_MNGR_MON_STATUS_255 - mmSYNC_MNGR_MON_STATUS_0) + 4);
+
+ for (i = 0 ; i < num_of_sob_in_longs ; i += 4)
+ WREG32(mmSYNC_MNGR_SOB_OBJ_0 + i, 0);
+
+ for (i = 0 ; i < num_of_mon_in_longs ; i += 4)
+ WREG32(mmSYNC_MNGR_MON_STATUS_0 + i, 0);
+
+ /* Flush all WREG to prevent race */
+ i = RREG32(mmSYNC_MNGR_SOB_OBJ_0);
+}
+
+/*
+ * goya_debugfs_read32 - read a 32bit value from a given device address
+ *
+ * @hdev: pointer to hl_device structure
+ * @addr: address in device
+ * @val: returned value
+ *
+ * In case of DDR address that is not mapped into the default aperture that
+ * the DDR bar exposes, the function will configure the iATU so that the DDR
+ * bar will be positioned at a base address that allows reading from the
+ * required address. Configuring the iATU during normal operation can
+ * lead to undefined behavior and therefore, should be done with extreme care
+ *
+ */
+static int goya_debugfs_read32(struct hl_device *hdev, u64 addr, u32 *val)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ int rc = 0;
+
+ if ((addr >= CFG_BASE) && (addr < CFG_BASE + CFG_SIZE)) {
+ *val = RREG32(addr - CFG_BASE);
+
+ } else if ((addr >= SRAM_BASE_ADDR) &&
+ (addr < SRAM_BASE_ADDR + SRAM_SIZE)) {
+
+ *val = readl(hdev->pcie_bar[SRAM_CFG_BAR_ID] +
+ (addr - SRAM_BASE_ADDR));
+
+ } else if ((addr >= DRAM_PHYS_BASE) &&
+ (addr < DRAM_PHYS_BASE + hdev->asic_prop.dram_size)) {
+
+ u64 bar_base_addr = DRAM_PHYS_BASE +
+ (addr & ~(prop->dram_pci_bar_size - 0x1ull));
+
+ rc = goya_set_ddr_bar_base(hdev, bar_base_addr);
+ if (!rc) {
+ *val = readl(hdev->pcie_bar[DDR_BAR_ID] +
+ (addr - bar_base_addr));
+
+ rc = goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE +
+ (MMU_PAGE_TABLES_ADDR &
+ ~(prop->dram_pci_bar_size - 0x1ull)));
+ }
+ } else {
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+/*
+ * goya_debugfs_write32 - write a 32bit value to a given device address
+ *
+ * @hdev: pointer to hl_device structure
+ * @addr: address in device
+ * @val: returned value
+ *
+ * In case of DDR address that is not mapped into the default aperture that
+ * the DDR bar exposes, the function will configure the iATU so that the DDR
+ * bar will be positioned at a base address that allows writing to the
+ * required address. Configuring the iATU during normal operation can
+ * lead to undefined behavior and therefore, should be done with extreme care
+ *
+ */
+static int goya_debugfs_write32(struct hl_device *hdev, u64 addr, u32 val)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ int rc = 0;
+
+ if ((addr >= CFG_BASE) && (addr < CFG_BASE + CFG_SIZE)) {
+ WREG32(addr - CFG_BASE, val);
+
+ } else if ((addr >= SRAM_BASE_ADDR) &&
+ (addr < SRAM_BASE_ADDR + SRAM_SIZE)) {
+
+ writel(val, hdev->pcie_bar[SRAM_CFG_BAR_ID] +
+ (addr - SRAM_BASE_ADDR));
+
+ } else if ((addr >= DRAM_PHYS_BASE) &&
+ (addr < DRAM_PHYS_BASE + hdev->asic_prop.dram_size)) {
+
+ u64 bar_base_addr = DRAM_PHYS_BASE +
+ (addr & ~(prop->dram_pci_bar_size - 0x1ull));
+
+ rc = goya_set_ddr_bar_base(hdev, bar_base_addr);
+ if (!rc) {
+ writel(val, hdev->pcie_bar[DDR_BAR_ID] +
+ (addr - bar_base_addr));
+
+ rc = goya_set_ddr_bar_base(hdev, DRAM_PHYS_BASE +
+ (MMU_PAGE_TABLES_ADDR &
+ ~(prop->dram_pci_bar_size - 0x1ull)));
+ }
+ } else {
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+static u64 goya_read_pte(struct hl_device *hdev, u64 addr)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ return readq(hdev->pcie_bar[DDR_BAR_ID] +
+ (addr - goya->ddr_bar_cur_addr));
+}
+
+static void goya_write_pte(struct hl_device *hdev, u64 addr, u64 val)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ writeq(val, hdev->pcie_bar[DDR_BAR_ID] +
+ (addr - goya->ddr_bar_cur_addr));
+}
+
+static const char *_goya_get_event_desc(u16 event_type)
+{
+ switch (event_type) {
+ case GOYA_ASYNC_EVENT_ID_PCIE_DEC:
+ return "PCIe_dec";
+ case GOYA_ASYNC_EVENT_ID_TPC0_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC1_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC2_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC3_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC4_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC5_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC6_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC7_DEC:
+ return "TPC%d_dec";
+ case GOYA_ASYNC_EVENT_ID_MME_WACS:
+ return "MME_wacs";
+ case GOYA_ASYNC_EVENT_ID_MME_WACSD:
+ return "MME_wacsd";
+ case GOYA_ASYNC_EVENT_ID_CPU_AXI_SPLITTER:
+ return "CPU_axi_splitter";
+ case GOYA_ASYNC_EVENT_ID_PSOC_AXI_DEC:
+ return "PSOC_axi_dec";
+ case GOYA_ASYNC_EVENT_ID_PSOC:
+ return "PSOC";
+ case GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC1_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC2_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC3_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC4_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC5_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC6_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC7_KRN_ERR:
+ return "TPC%d_krn_err";
+ case GOYA_ASYNC_EVENT_ID_TPC0_CMDQ ... GOYA_ASYNC_EVENT_ID_TPC7_CMDQ:
+ return "TPC%d_cq";
+ case GOYA_ASYNC_EVENT_ID_TPC0_QM ... GOYA_ASYNC_EVENT_ID_TPC7_QM:
+ return "TPC%d_qm";
+ case GOYA_ASYNC_EVENT_ID_MME_QM:
+ return "MME_qm";
+ case GOYA_ASYNC_EVENT_ID_MME_CMDQ:
+ return "MME_cq";
+ case GOYA_ASYNC_EVENT_ID_DMA0_QM ... GOYA_ASYNC_EVENT_ID_DMA4_QM:
+ return "DMA%d_qm";
+ case GOYA_ASYNC_EVENT_ID_DMA0_CH ... GOYA_ASYNC_EVENT_ID_DMA4_CH:
+ return "DMA%d_ch";
+ default:
+ return "N/A";
+ }
+}
+
+static void goya_get_event_desc(u16 event_type, char *desc, size_t size)
+{
+ u8 index;
+
+ switch (event_type) {
+ case GOYA_ASYNC_EVENT_ID_TPC0_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC1_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC2_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC3_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC4_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC5_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC6_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC7_DEC:
+ index = (event_type - GOYA_ASYNC_EVENT_ID_TPC0_DEC) / 3;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ case GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC1_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC2_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC3_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC4_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC5_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC6_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC7_KRN_ERR:
+ index = (event_type - GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR) / 10;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ case GOYA_ASYNC_EVENT_ID_TPC0_CMDQ ... GOYA_ASYNC_EVENT_ID_TPC7_CMDQ:
+ index = event_type - GOYA_ASYNC_EVENT_ID_TPC0_CMDQ;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ case GOYA_ASYNC_EVENT_ID_TPC0_QM ... GOYA_ASYNC_EVENT_ID_TPC7_QM:
+ index = event_type - GOYA_ASYNC_EVENT_ID_TPC0_QM;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ case GOYA_ASYNC_EVENT_ID_DMA0_QM ... GOYA_ASYNC_EVENT_ID_DMA4_QM:
+ index = event_type - GOYA_ASYNC_EVENT_ID_DMA0_QM;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ case GOYA_ASYNC_EVENT_ID_DMA0_CH ... GOYA_ASYNC_EVENT_ID_DMA4_CH:
+ index = event_type - GOYA_ASYNC_EVENT_ID_DMA0_CH;
+ snprintf(desc, size, _goya_get_event_desc(event_type), index);
+ break;
+ default:
+ snprintf(desc, size, _goya_get_event_desc(event_type));
+ break;
+ }
+}
+
+static void goya_print_razwi_info(struct hl_device *hdev)
+{
+ if (RREG32(mmDMA_MACRO_RAZWI_LBW_WT_VLD)) {
+ dev_err(hdev->dev, "Illegal write to LBW\n");
+ WREG32(mmDMA_MACRO_RAZWI_LBW_WT_VLD, 0);
+ }
+
+ if (RREG32(mmDMA_MACRO_RAZWI_LBW_RD_VLD)) {
+ dev_err(hdev->dev, "Illegal read from LBW\n");
+ WREG32(mmDMA_MACRO_RAZWI_LBW_RD_VLD, 0);
+ }
+
+ if (RREG32(mmDMA_MACRO_RAZWI_HBW_WT_VLD)) {
+ dev_err(hdev->dev, "Illegal write to HBW\n");
+ WREG32(mmDMA_MACRO_RAZWI_HBW_WT_VLD, 0);
+ }
+
+ if (RREG32(mmDMA_MACRO_RAZWI_HBW_RD_VLD)) {
+ dev_err(hdev->dev, "Illegal read from HBW\n");
+ WREG32(mmDMA_MACRO_RAZWI_HBW_RD_VLD, 0);
+ }
+}
+
+static void goya_print_mmu_error_info(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u64 addr;
+ u32 val;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return;
+
+ val = RREG32(mmMMU_PAGE_ERROR_CAPTURE);
+ if (val & MMU_PAGE_ERROR_CAPTURE_ENTRY_VALID_MASK) {
+ addr = val & MMU_PAGE_ERROR_CAPTURE_VA_49_32_MASK;
+ addr <<= 32;
+ addr |= RREG32(mmMMU_PAGE_ERROR_CAPTURE_VA);
+
+ dev_err(hdev->dev, "MMU page fault on va 0x%llx\n", addr);
+
+ WREG32(mmMMU_PAGE_ERROR_CAPTURE, 0);
+ }
+}
+
+static void goya_print_irq_info(struct hl_device *hdev, u16 event_type)
+{
+ char desc[20] = "";
+
+ goya_get_event_desc(event_type, desc, sizeof(desc));
+ dev_err(hdev->dev, "Received H/W interrupt %d [\"%s\"]\n",
+ event_type, desc);
+
+ goya_print_razwi_info(hdev);
+ goya_print_mmu_error_info(hdev);
+}
+
+static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
+ size_t irq_arr_size)
+{
+ struct armcp_unmask_irq_arr_packet *pkt;
+ size_t total_pkt_size;
+ long result;
+ int rc;
+
+ total_pkt_size = sizeof(struct armcp_unmask_irq_arr_packet) +
+ irq_arr_size;
+
+ /* data should be aligned to 8 bytes in order to ArmCP to copy it */
+ total_pkt_size = (total_pkt_size + 0x7) & ~0x7;
+
+ /* total_pkt_size is casted to u16 later on */
+ if (total_pkt_size > USHRT_MAX) {
+ dev_err(hdev->dev, "too many elements in IRQ array\n");
+ return -EINVAL;
+ }
+
+ pkt = kzalloc(total_pkt_size, GFP_KERNEL);
+ if (!pkt)
+ return -ENOMEM;
+
+ pkt->length = cpu_to_le32(irq_arr_size / sizeof(irq_arr[0]));
+ memcpy(&pkt->irqs, irq_arr, irq_arr_size);
+
+ pkt->armcp_pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) pkt,
+ total_pkt_size, HL_DEVICE_TIMEOUT_USEC, &result);
+
+ if (rc)
+ dev_err(hdev->dev, "failed to unmask IRQ array\n");
+
+ kfree(pkt);
+
+ return rc;
+}
+
+static int goya_soft_reset_late_init(struct hl_device *hdev)
+{
+ /*
+ * Unmask all IRQs since some could have been received
+ * during the soft reset
+ */
+ return goya_unmask_irq_arr(hdev, goya_non_fatal_events,
+ sizeof(goya_non_fatal_events));
+}
+
+static int goya_unmask_irq(struct hl_device *hdev, u16 event_type)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.value = cpu_to_le64(event_type);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ HL_DEVICE_TIMEOUT_USEC, &result);
+
+ if (rc)
+ dev_err(hdev->dev, "failed to unmask RAZWI IRQ %d", event_type);
+
+ return rc;
+}
+
+void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
+{
+ u32 ctl = le32_to_cpu(eq_entry->hdr.ctl);
+ u16 event_type = ((ctl & EQ_CTL_EVENT_TYPE_MASK)
+ >> EQ_CTL_EVENT_TYPE_SHIFT);
+ struct goya_device *goya = hdev->asic_specific;
+
+ goya->events_stat[event_type]++;
+
+ switch (event_type) {
+ case GOYA_ASYNC_EVENT_ID_PCIE_IF:
+ case GOYA_ASYNC_EVENT_ID_TPC0_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC1_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC2_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC3_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC4_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC5_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC6_ECC:
+ case GOYA_ASYNC_EVENT_ID_TPC7_ECC:
+ case GOYA_ASYNC_EVENT_ID_MME_ECC:
+ case GOYA_ASYNC_EVENT_ID_MME_ECC_EXT:
+ case GOYA_ASYNC_EVENT_ID_MMU_ECC:
+ case GOYA_ASYNC_EVENT_ID_DMA_MACRO:
+ case GOYA_ASYNC_EVENT_ID_DMA_ECC:
+ case GOYA_ASYNC_EVENT_ID_CPU_IF_ECC:
+ case GOYA_ASYNC_EVENT_ID_PSOC_MEM:
+ case GOYA_ASYNC_EVENT_ID_PSOC_CORESIGHT:
+ case GOYA_ASYNC_EVENT_ID_SRAM0 ... GOYA_ASYNC_EVENT_ID_SRAM29:
+ case GOYA_ASYNC_EVENT_ID_GIC500:
+ case GOYA_ASYNC_EVENT_ID_PLL0:
+ case GOYA_ASYNC_EVENT_ID_PLL1:
+ case GOYA_ASYNC_EVENT_ID_PLL3:
+ case GOYA_ASYNC_EVENT_ID_PLL4:
+ case GOYA_ASYNC_EVENT_ID_PLL5:
+ case GOYA_ASYNC_EVENT_ID_PLL6:
+ case GOYA_ASYNC_EVENT_ID_AXI_ECC:
+ case GOYA_ASYNC_EVENT_ID_L2_RAM_ECC:
+ case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET:
+ case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT:
+ dev_err(hdev->dev,
+ "Received H/W interrupt %d, reset the chip\n",
+ event_type);
+ hl_device_reset(hdev, true, false);
+ break;
+
+ case GOYA_ASYNC_EVENT_ID_PCIE_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC0_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC1_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC2_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC3_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC4_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC5_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC6_DEC:
+ case GOYA_ASYNC_EVENT_ID_TPC7_DEC:
+ case GOYA_ASYNC_EVENT_ID_MME_WACS:
+ case GOYA_ASYNC_EVENT_ID_MME_WACSD:
+ case GOYA_ASYNC_EVENT_ID_CPU_AXI_SPLITTER:
+ case GOYA_ASYNC_EVENT_ID_PSOC_AXI_DEC:
+ case GOYA_ASYNC_EVENT_ID_PSOC:
+ case GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC1_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC2_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC3_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC4_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC5_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC6_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC7_KRN_ERR:
+ case GOYA_ASYNC_EVENT_ID_TPC0_CMDQ ... GOYA_ASYNC_EVENT_ID_TPC7_QM:
+ case GOYA_ASYNC_EVENT_ID_MME_QM:
+ case GOYA_ASYNC_EVENT_ID_MME_CMDQ:
+ case GOYA_ASYNC_EVENT_ID_DMA0_QM ... GOYA_ASYNC_EVENT_ID_DMA4_QM:
+ case GOYA_ASYNC_EVENT_ID_DMA0_CH ... GOYA_ASYNC_EVENT_ID_DMA4_CH:
+ goya_print_irq_info(hdev, event_type);
+ goya_unmask_irq(hdev, event_type);
+ break;
+
+ case GOYA_ASYNC_EVENT_ID_TPC0_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC1_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC2_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC3_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC4_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC5_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC6_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_TPC7_BMON_SPMU:
+ case GOYA_ASYNC_EVENT_ID_DMA_BM_CH0:
+ case GOYA_ASYNC_EVENT_ID_DMA_BM_CH1:
+ case GOYA_ASYNC_EVENT_ID_DMA_BM_CH2:
+ case GOYA_ASYNC_EVENT_ID_DMA_BM_CH3:
+ case GOYA_ASYNC_EVENT_ID_DMA_BM_CH4:
+ dev_info(hdev->dev, "Received H/W interrupt %d\n", event_type);
+ break;
+
+ default:
+ dev_err(hdev->dev, "Received invalid H/W interrupt %d\n",
+ event_type);
+ break;
+ }
+}
+
+void *goya_get_events_stat(struct hl_device *hdev, u32 *size)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ *size = (u32) sizeof(goya->events_stat);
+
+ return goya->events_stat;
+}
+
+static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u32 size,
+ u64 val, bool is_dram)
+{
+ struct packet_lin_dma *lin_dma_pkt;
+ struct hl_cs_parser parser;
+ struct hl_cs_job *job;
+ u32 cb_size, ctl;
+ struct hl_cb *cb;
+ int rc;
+
+ cb = hl_cb_kernel_create(hdev, PAGE_SIZE);
+ if (!cb)
+ return -EFAULT;
+
+ lin_dma_pkt = (struct packet_lin_dma *) (uintptr_t) cb->kernel_address;
+
+ memset(lin_dma_pkt, 0, sizeof(*lin_dma_pkt));
+ cb_size = sizeof(*lin_dma_pkt);
+
+ ctl = ((PACKET_LIN_DMA << GOYA_PKT_CTL_OPCODE_SHIFT) |
+ (1 << GOYA_PKT_LIN_DMA_CTL_MEMSET_SHIFT) |
+ (1 << GOYA_PKT_LIN_DMA_CTL_WO_SHIFT) |
+ (1 << GOYA_PKT_CTL_RB_SHIFT) |
+ (1 << GOYA_PKT_CTL_MB_SHIFT));
+ ctl |= (is_dram ? DMA_HOST_TO_DRAM : DMA_HOST_TO_SRAM) <<
+ GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT;
+ lin_dma_pkt->ctl = cpu_to_le32(ctl);
+
+ lin_dma_pkt->src_addr = cpu_to_le64(val);
+ lin_dma_pkt->dst_addr = cpu_to_le64(addr);
+ lin_dma_pkt->tsize = cpu_to_le32(size);
+
+ job = hl_cs_allocate_job(hdev, true);
+ if (!job) {
+ dev_err(hdev->dev, "Failed to allocate a new job\n");
+ rc = -ENOMEM;
+ goto release_cb;
+ }
+
+ job->id = 0;
+ job->user_cb = cb;
+ job->user_cb->cs_cnt++;
+ job->user_cb_size = cb_size;
+ job->hw_queue_id = GOYA_QUEUE_ID_DMA_0;
+
+ hl_debugfs_add_job(hdev, job);
+
+ parser.ctx_id = HL_KERNEL_ASID_ID;
+ parser.cs_sequence = 0;
+ parser.job_id = job->id;
+ parser.hw_queue_id = job->hw_queue_id;
+ parser.job_userptr_list = &job->userptr_list;
+ parser.user_cb = job->user_cb;
+ parser.user_cb_size = job->user_cb_size;
+ parser.ext_queue = job->ext_queue;
+ parser.use_virt_addr = hdev->mmu_enable;
+
+ rc = hdev->asic_funcs->cs_parser(hdev, &parser);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to parse kernel CB\n");
+ goto free_job;
+ }
+
+ job->patched_cb = parser.patched_cb;
+ job->job_cb_size = parser.patched_cb_size;
+ job->patched_cb->cs_cnt++;
+
+ rc = goya_send_job_on_qman0(hdev, job);
+
+ job->patched_cb->cs_cnt--;
+ hl_cb_put(job->patched_cb);
+
+free_job:
+ hl_userptr_delete_list(hdev, &job->userptr_list);
+ hl_debugfs_remove_job(hdev, job);
+ kfree(job);
+ cb->cs_cnt--;
+
+release_cb:
+ hl_cb_put(cb);
+ hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, cb->id << PAGE_SHIFT);
+
+ return rc;
+}
+
+static int goya_context_switch(struct hl_device *hdev, u32 asid)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 addr = prop->sram_base_address;
+ u32 size = hdev->pldm ? 0x10000 : prop->sram_size;
+ u64 val = 0x7777777777777777ull;
+ int rc;
+
+ rc = goya_memset_device_memory(hdev, addr, size, val, false);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to clear SRAM in context switch\n");
+ return rc;
+ }
+
+ goya_mmu_prepare(hdev, asid);
+
+ return 0;
+}
+
+static int goya_mmu_clear_pgt_range(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct goya_device *goya = hdev->asic_specific;
+ u64 addr = prop->mmu_pgt_addr;
+ u32 size = prop->mmu_pgt_size + MMU_DRAM_DEFAULT_PAGE_SIZE +
+ MMU_CACHE_MNG_SIZE;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return 0;
+
+ return goya_memset_device_memory(hdev, addr, size, 0, true);
+}
+
+static int goya_mmu_set_dram_default_page(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u64 addr = hdev->asic_prop.mmu_dram_default_page_addr;
+ u32 size = MMU_DRAM_DEFAULT_PAGE_SIZE;
+ u64 val = 0x9999999999999999ull;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return 0;
+
+ return goya_memset_device_memory(hdev, addr, size, val, true);
+}
+
+static void goya_mmu_prepare(struct hl_device *hdev, u32 asid)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ int i;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return;
+
+ if (asid & ~MME_QM_GLBL_SECURE_PROPS_ASID_MASK) {
+ WARN(1, "asid %u is too big\n", asid);
+ return;
+ }
+
+ /* zero the MMBP and ASID bits and then set the ASID */
+ for (i = 0 ; i < GOYA_MMU_REGS_NUM ; i++) {
+ WREG32_AND(goya_mmu_regs[i], ~0x7FF);
+ WREG32_OR(goya_mmu_regs[i], asid);
+ }
+}
+
+static void goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 status, timeout_usec;
+ int rc;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return;
+
+ /* no need in L1 only invalidation in Goya */
+ if (!is_hard)
+ return;
+
+ if (hdev->pldm)
+ timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC;
+ else
+ timeout_usec = MMU_CONFIG_TIMEOUT_USEC;
+
+ mutex_lock(&hdev->mmu_cache_lock);
+
+ /* L0 & L1 invalidation */
+ WREG32(mmSTLB_INV_ALL_START, 1);
+
+ rc = hl_poll_timeout(
+ hdev,
+ mmSTLB_INV_ALL_START,
+ status,
+ !status,
+ 1000,
+ timeout_usec);
+
+ mutex_unlock(&hdev->mmu_cache_lock);
+
+ if (rc)
+ dev_notice_ratelimited(hdev->dev,
+ "Timeout when waiting for MMU cache invalidation\n");
+}
+
+static void goya_mmu_invalidate_cache_range(struct hl_device *hdev,
+ bool is_hard, u32 asid, u64 va, u64 size)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ u32 status, timeout_usec, inv_data, pi;
+ int rc;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU))
+ return;
+
+ /* no need in L1 only invalidation in Goya */
+ if (!is_hard)
+ return;
+
+ if (hdev->pldm)
+ timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC;
+ else
+ timeout_usec = MMU_CONFIG_TIMEOUT_USEC;
+
+ mutex_lock(&hdev->mmu_cache_lock);
+
+ /*
+ * TODO: currently invalidate entire L0 & L1 as in regular hard
+ * invalidation. Need to apply invalidation of specific cache lines with
+ * mask of ASID & VA & size.
+ * Note that L1 with be flushed entirely in any case.
+ */
+
+ /* L0 & L1 invalidation */
+ inv_data = RREG32(mmSTLB_CACHE_INV);
+ /* PI is 8 bit */
+ pi = ((inv_data & STLB_CACHE_INV_PRODUCER_INDEX_MASK) + 1) & 0xFF;
+ WREG32(mmSTLB_CACHE_INV,
+ (inv_data & STLB_CACHE_INV_INDEX_MASK_MASK) | pi);
+
+ rc = hl_poll_timeout(
+ hdev,
+ mmSTLB_INV_CONSUMER_INDEX,
+ status,
+ status == pi,
+ 1000,
+ timeout_usec);
+
+ mutex_unlock(&hdev->mmu_cache_lock);
+
+ if (rc)
+ dev_notice_ratelimited(hdev->dev,
+ "Timeout when waiting for MMU cache invalidation\n");
+}
+
+static int goya_mmu_update_asid_hop0_addr(struct hl_device *hdev, u32 asid,
+ u64 phys_addr)
+{
+ u32 status, timeout_usec;
+ int rc;
+
+ if (hdev->pldm)
+ timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC;
+ else
+ timeout_usec = MMU_CONFIG_TIMEOUT_USEC;
+
+ WREG32(MMU_HOP0_PA43_12, phys_addr >> MMU_HOP0_PA43_12_SHIFT);
+ WREG32(MMU_HOP0_PA49_44, phys_addr >> MMU_HOP0_PA49_44_SHIFT);
+ WREG32(MMU_ASID_BUSY, 0x80000000 | asid);
+
+ rc = hl_poll_timeout(
+ hdev,
+ MMU_ASID_BUSY,
+ status,
+ !(status & 0x80000000),
+ 1000,
+ timeout_usec);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Timeout during MMU hop0 config of asid %d\n", asid);
+ return rc;
+ }
+
+ return 0;
+}
+
+int goya_send_heartbeat(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct armcp_packet hb_pkt;
+ long result;
+ int rc;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_CPU_Q))
+ return 0;
+
+ memset(&hb_pkt, 0, sizeof(hb_pkt));
+
+ hb_pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEST <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ hb_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &hb_pkt,
+ sizeof(hb_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
+
+ if ((rc) || (result != ARMCP_PACKET_FENCE_VAL))
+ rc = -EIO;
+
+ return rc;
+}
+
+static int goya_armcp_info_get(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct armcp_packet pkt;
+ void *armcp_info_cpu_addr;
+ dma_addr_t armcp_info_dma_addr;
+ u64 dram_size;
+ long result;
+ int rc;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_CPU_Q))
+ return 0;
+
+ armcp_info_cpu_addr =
+ hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
+ sizeof(struct armcp_info), &armcp_info_dma_addr);
+ if (!armcp_info_cpu_addr) {
+ dev_err(hdev->dev,
+ "Failed to allocate DMA memory for ArmCP info packet\n");
+ return -ENOMEM;
+ }
+
+ memset(armcp_info_cpu_addr, 0, sizeof(struct armcp_info));
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = cpu_to_le32(ARMCP_PACKET_INFO_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.addr = cpu_to_le64(armcp_info_dma_addr +
+ prop->host_phys_base_address);
+ pkt.data_max_size = cpu_to_le32(sizeof(struct armcp_info));
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ GOYA_ARMCP_INFO_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to send armcp info pkt, error %d\n", rc);
+ goto out;
+ }
+
+ memcpy(&prop->armcp_info, armcp_info_cpu_addr,
+ sizeof(prop->armcp_info));
+
+ dram_size = le64_to_cpu(prop->armcp_info.dram_size);
+ if (dram_size) {
+ if ((!is_power_of_2(dram_size)) ||
+ (dram_size < DRAM_PHYS_DEFAULT_SIZE)) {
+ dev_err(hdev->dev,
+ "F/W reported invalid DRAM size %llu. Trying to use default size\n",
+ dram_size);
+ dram_size = DRAM_PHYS_DEFAULT_SIZE;
+ }
+
+ prop->dram_size = dram_size;
+ prop->dram_end_address = prop->dram_base_address + dram_size;
+ }
+
+ rc = hl_build_hwmon_channel_info(hdev, prop->armcp_info.sensors);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to build hwmon channel info, error %d\n", rc);
+ rc = -EFAULT;
+ goto out;
+ }
+
+out:
+ hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
+ sizeof(struct armcp_info), armcp_info_cpu_addr);
+
+ return rc;
+}
+
+static void goya_init_clock_gating(struct hl_device *hdev)
+{
+
+}
+
+static void goya_disable_clock_gating(struct hl_device *hdev)
+{
+
+}
+
+static bool goya_is_device_idle(struct hl_device *hdev)
+{
+ u64 offset, dma_qm_reg, tpc_qm_reg, tpc_cmdq_reg, tpc_cfg_reg;
+ int i;
+
+ offset = mmDMA_QM_1_GLBL_STS0 - mmDMA_QM_0_GLBL_STS0;
+
+ for (i = 0 ; i < DMA_MAX_NUM ; i++) {
+ dma_qm_reg = mmDMA_QM_0_GLBL_STS0 + i * offset;
+
+ if ((RREG32(dma_qm_reg) & DMA_QM_IDLE_MASK) !=
+ DMA_QM_IDLE_MASK)
+ return false;
+ }
+
+ offset = mmTPC1_QM_GLBL_STS0 - mmTPC0_QM_GLBL_STS0;
+
+ for (i = 0 ; i < TPC_MAX_NUM ; i++) {
+ tpc_qm_reg = mmTPC0_QM_GLBL_STS0 + i * offset;
+ tpc_cmdq_reg = mmTPC0_CMDQ_GLBL_STS0 + i * offset;
+ tpc_cfg_reg = mmTPC0_CFG_STATUS + i * offset;
+
+ if ((RREG32(tpc_qm_reg) & TPC_QM_IDLE_MASK) !=
+ TPC_QM_IDLE_MASK)
+ return false;
+
+ if ((RREG32(tpc_cmdq_reg) & TPC_CMDQ_IDLE_MASK) !=
+ TPC_CMDQ_IDLE_MASK)
+ return false;
+
+ if ((RREG32(tpc_cfg_reg) & TPC_CFG_IDLE_MASK) !=
+ TPC_CFG_IDLE_MASK)
+ return false;
+ }
+
+ if ((RREG32(mmMME_QM_GLBL_STS0) & MME_QM_IDLE_MASK) !=
+ MME_QM_IDLE_MASK)
+ return false;
+
+ if ((RREG32(mmMME_CMDQ_GLBL_STS0) & MME_CMDQ_IDLE_MASK) !=
+ MME_CMDQ_IDLE_MASK)
+ return false;
+
+ if ((RREG32(mmMME_ARCH_STATUS) & MME_ARCH_IDLE_MASK) !=
+ MME_ARCH_IDLE_MASK)
+ return false;
+
+ if (RREG32(mmMME_SHADOW_0_STATUS) & MME_SHADOW_IDLE_MASK)
+ return false;
+
+ return true;
+}
+
+static void goya_hw_queues_lock(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ spin_lock(&goya->hw_queues_lock);
+}
+
+static void goya_hw_queues_unlock(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ spin_unlock(&goya->hw_queues_lock);
+}
+
+static u32 goya_get_pci_id(struct hl_device *hdev)
+{
+ return hdev->pdev->device;
+}
+
+static int goya_get_eeprom_data(struct hl_device *hdev, void *data,
+ size_t max_size)
+{
+ struct goya_device *goya = hdev->asic_specific;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct armcp_packet pkt;
+ void *eeprom_info_cpu_addr;
+ dma_addr_t eeprom_info_dma_addr;
+ long result;
+ int rc;
+
+ if (!(goya->hw_cap_initialized & HW_CAP_CPU_Q))
+ return 0;
+
+ eeprom_info_cpu_addr =
+ hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
+ max_size, &eeprom_info_dma_addr);
+ if (!eeprom_info_cpu_addr) {
+ dev_err(hdev->dev,
+ "Failed to allocate DMA memory for EEPROM info packet\n");
+ return -ENOMEM;
+ }
+
+ memset(eeprom_info_cpu_addr, 0, max_size);
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = cpu_to_le32(ARMCP_PACKET_EEPROM_DATA_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.addr = cpu_to_le64(eeprom_info_dma_addr +
+ prop->host_phys_base_address);
+ pkt.data_max_size = cpu_to_le32(max_size);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ GOYA_ARMCP_EEPROM_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to send armcp EEPROM pkt, error %d\n", rc);
+ goto out;
+ }
+
+ /* result contains the actual size */
+ memcpy(data, eeprom_info_cpu_addr, min((size_t)result, max_size));
+
+out:
+ hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, max_size,
+ eeprom_info_cpu_addr);
+
+ return rc;
+}
+
+static enum hl_device_hw_state goya_get_hw_state(struct hl_device *hdev)
+{
+ return RREG32(mmPSOC_GLOBAL_CONF_APP_STATUS);
+}
+
+static const struct hl_asic_funcs goya_funcs = {
+ .early_init = goya_early_init,
+ .early_fini = goya_early_fini,
+ .late_init = goya_late_init,
+ .late_fini = goya_late_fini,
+ .sw_init = goya_sw_init,
+ .sw_fini = goya_sw_fini,
+ .hw_init = goya_hw_init,
+ .hw_fini = goya_hw_fini,
+ .halt_engines = goya_halt_engines,
+ .suspend = goya_suspend,
+ .resume = goya_resume,
+ .cb_mmap = goya_cb_mmap,
+ .ring_doorbell = goya_ring_doorbell,
+ .flush_pq_write = goya_flush_pq_write,
+ .dma_alloc_coherent = goya_dma_alloc_coherent,
+ .dma_free_coherent = goya_dma_free_coherent,
+ .get_int_queue_base = goya_get_int_queue_base,
+ .test_queues = goya_test_queues,
+ .dma_pool_zalloc = goya_dma_pool_zalloc,
+ .dma_pool_free = goya_dma_pool_free,
+ .cpu_accessible_dma_pool_alloc = goya_cpu_accessible_dma_pool_alloc,
+ .cpu_accessible_dma_pool_free = goya_cpu_accessible_dma_pool_free,
+ .hl_dma_unmap_sg = goya_dma_unmap_sg,
+ .cs_parser = goya_cs_parser,
+ .asic_dma_map_sg = goya_dma_map_sg,
+ .get_dma_desc_list_size = goya_get_dma_desc_list_size,
+ .add_end_of_cb_packets = goya_add_end_of_cb_packets,
+ .update_eq_ci = goya_update_eq_ci,
+ .context_switch = goya_context_switch,
+ .restore_phase_topology = goya_restore_phase_topology,
+ .debugfs_read32 = goya_debugfs_read32,
+ .debugfs_write32 = goya_debugfs_write32,
+ .add_device_attr = goya_add_device_attr,
+ .handle_eqe = goya_handle_eqe,
+ .set_pll_profile = goya_set_pll_profile,
+ .get_events_stat = goya_get_events_stat,
+ .read_pte = goya_read_pte,
+ .write_pte = goya_write_pte,
+ .mmu_invalidate_cache = goya_mmu_invalidate_cache,
+ .mmu_invalidate_cache_range = goya_mmu_invalidate_cache_range,
+ .send_heartbeat = goya_send_heartbeat,
+ .enable_clock_gating = goya_init_clock_gating,
+ .disable_clock_gating = goya_disable_clock_gating,
+ .is_device_idle = goya_is_device_idle,
+ .soft_reset_late_init = goya_soft_reset_late_init,
+ .hw_queues_lock = goya_hw_queues_lock,
+ .hw_queues_unlock = goya_hw_queues_unlock,
+ .get_pci_id = goya_get_pci_id,
+ .get_eeprom_data = goya_get_eeprom_data,
+ .send_cpu_message = goya_send_cpu_message,
+ .get_hw_state = goya_get_hw_state
+};
+
+/*
+ * goya_set_asic_funcs - set Goya function pointers
+ *
+ * @*hdev: pointer to hl_device structure
+ *
+ */
+void goya_set_asic_funcs(struct hl_device *hdev)
+{
+ hdev->asic_funcs = &goya_funcs;
+}
diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/misc/habanalabs/goya/goyaP.h
new file mode 100644
index 000000000000..830551b6b062
--- /dev/null
+++ b/drivers/misc/habanalabs/goya/goyaP.h
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef GOYAP_H_
+#define GOYAP_H_
+
+#include <uapi/misc/habanalabs.h>
+#include "habanalabs.h"
+#include "include/hl_boot_if.h"
+#include "include/goya/goya_packets.h"
+#include "include/goya/goya.h"
+#include "include/goya/goya_async_events.h"
+#include "include/goya/goya_fw_if.h"
+
+#define NUMBER_OF_CMPLT_QUEUES 5
+#define NUMBER_OF_EXT_HW_QUEUES 5
+#define NUMBER_OF_CPU_HW_QUEUES 1
+#define NUMBER_OF_INT_HW_QUEUES 9
+#define NUMBER_OF_HW_QUEUES (NUMBER_OF_EXT_HW_QUEUES + \
+ NUMBER_OF_CPU_HW_QUEUES + \
+ NUMBER_OF_INT_HW_QUEUES)
+
+/*
+ * Number of MSIX interrupts IDS:
+ * Each completion queue has 1 ID
+ * The event queue has 1 ID
+ */
+#define NUMBER_OF_INTERRUPTS (NUMBER_OF_CMPLT_QUEUES + 1)
+
+#if (NUMBER_OF_HW_QUEUES >= HL_MAX_QUEUES)
+#error "Number of H/W queues must be smaller than HL_MAX_QUEUES"
+#endif
+
+#if (NUMBER_OF_INTERRUPTS > GOYA_MSIX_ENTRIES)
+#error "Number of MSIX interrupts must be smaller or equal to GOYA_MSIX_ENTRIES"
+#endif
+
+#define QMAN_FENCE_TIMEOUT_USEC 10000 /* 10 ms */
+
+#define QMAN_STOP_TIMEOUT_USEC 100000 /* 100 ms */
+
+#define TPC_ENABLED_MASK 0xFF
+
+#define PLL_HIGH_DEFAULT 1575000000 /* 1.575 GHz */
+
+#define MAX_POWER_DEFAULT 200000 /* 200W */
+
+#define GOYA_ARMCP_INFO_TIMEOUT 10000000 /* 10s */
+#define GOYA_ARMCP_EEPROM_TIMEOUT 10000000 /* 10s */
+
+#define DRAM_PHYS_DEFAULT_SIZE 0x100000000ull /* 4GB */
+
+/* DRAM Memory Map */
+
+#define CPU_FW_IMAGE_SIZE 0x10000000 /* 256MB */
+#define MMU_PAGE_TABLES_SIZE 0x0DE00000 /* 222MB */
+#define MMU_DRAM_DEFAULT_PAGE_SIZE 0x00200000 /* 2MB */
+#define MMU_CACHE_MNG_SIZE 0x00001000 /* 4KB */
+#define CPU_PQ_PKT_SIZE 0x00001000 /* 4KB */
+#define CPU_PQ_DATA_SIZE 0x01FFE000 /* 32MB - 8KB */
+
+#define CPU_FW_IMAGE_ADDR DRAM_PHYS_BASE
+#define MMU_PAGE_TABLES_ADDR (CPU_FW_IMAGE_ADDR + CPU_FW_IMAGE_SIZE)
+#define MMU_DRAM_DEFAULT_PAGE_ADDR (MMU_PAGE_TABLES_ADDR + \
+ MMU_PAGE_TABLES_SIZE)
+#define MMU_CACHE_MNG_ADDR (MMU_DRAM_DEFAULT_PAGE_ADDR + \
+ MMU_DRAM_DEFAULT_PAGE_SIZE)
+#define CPU_PQ_PKT_ADDR (MMU_CACHE_MNG_ADDR + \
+ MMU_CACHE_MNG_SIZE)
+#define CPU_PQ_DATA_ADDR (CPU_PQ_PKT_ADDR + CPU_PQ_PKT_SIZE)
+#define DRAM_BASE_ADDR_USER (CPU_PQ_DATA_ADDR + CPU_PQ_DATA_SIZE)
+
+#if (DRAM_BASE_ADDR_USER != 0x20000000)
+#error "KMD must reserve 512MB"
+#endif
+
+/*
+ * SRAM Memory Map for KMD
+ *
+ * KMD occupies KMD_SRAM_SIZE bytes from the start of SRAM. It is used for
+ * MME/TPC QMANs
+ *
+ */
+
+#define MME_QMAN_BASE_OFFSET 0x000000 /* Must be 0 */
+#define MME_QMAN_LENGTH 64
+#define TPC_QMAN_LENGTH 64
+
+#define TPC0_QMAN_BASE_OFFSET (MME_QMAN_BASE_OFFSET + \
+ (MME_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC1_QMAN_BASE_OFFSET (TPC0_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC2_QMAN_BASE_OFFSET (TPC1_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC3_QMAN_BASE_OFFSET (TPC2_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC4_QMAN_BASE_OFFSET (TPC3_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC5_QMAN_BASE_OFFSET (TPC4_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC6_QMAN_BASE_OFFSET (TPC5_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+#define TPC7_QMAN_BASE_OFFSET (TPC6_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+
+#define SRAM_KMD_RES_OFFSET (TPC7_QMAN_BASE_OFFSET + \
+ (TPC_QMAN_LENGTH * QMAN_PQ_ENTRY_SIZE))
+
+#if (SRAM_KMD_RES_OFFSET >= GOYA_KMD_SRAM_RESERVED_SIZE_FROM_START)
+#error "MME/TPC QMANs SRAM space exceeds limit"
+#endif
+
+#define SRAM_USER_BASE_OFFSET GOYA_KMD_SRAM_RESERVED_SIZE_FROM_START
+
+/* Virtual address space */
+#define VA_HOST_SPACE_START 0x1000000000000ull /* 256TB */
+#define VA_HOST_SPACE_END 0x3FF8000000000ull /* 1PB - 1TB */
+#define VA_HOST_SPACE_SIZE (VA_HOST_SPACE_END - \
+ VA_HOST_SPACE_START) /* 767TB */
+
+#define VA_DDR_SPACE_START 0x800000000ull /* 32GB */
+#define VA_DDR_SPACE_END 0x2000000000ull /* 128GB */
+#define VA_DDR_SPACE_SIZE (VA_DDR_SPACE_END - \
+ VA_DDR_SPACE_START) /* 128GB */
+
+#define DMA_MAX_TRANSFER_SIZE U32_MAX
+
+#define HW_CAP_PLL 0x00000001
+#define HW_CAP_DDR_0 0x00000002
+#define HW_CAP_DDR_1 0x00000004
+#define HW_CAP_MME 0x00000008
+#define HW_CAP_CPU 0x00000010
+#define HW_CAP_DMA 0x00000020
+#define HW_CAP_MSIX 0x00000040
+#define HW_CAP_CPU_Q 0x00000080
+#define HW_CAP_MMU 0x00000100
+#define HW_CAP_TPC_MBIST 0x00000200
+#define HW_CAP_GOLDEN 0x00000400
+#define HW_CAP_TPC 0x00000800
+
+#define CPU_PKT_SHIFT 5
+#define CPU_PKT_SIZE (1 << CPU_PKT_SHIFT)
+#define CPU_PKT_MASK (~((1 << CPU_PKT_SHIFT) - 1))
+#define CPU_MAX_PKTS_IN_CB 32
+#define CPU_CB_SIZE (CPU_PKT_SIZE * CPU_MAX_PKTS_IN_CB)
+#define CPU_ACCESSIBLE_MEM_SIZE (HL_QUEUE_LENGTH * CPU_CB_SIZE)
+
+enum goya_fw_component {
+ FW_COMP_UBOOT,
+ FW_COMP_PREBOOT
+};
+
+struct goya_device {
+ int (*test_cpu_queue)(struct hl_device *hdev);
+ int (*armcp_info_get)(struct hl_device *hdev);
+
+ /* TODO: remove hw_queues_lock after moving to scheduler code */
+ spinlock_t hw_queues_lock;
+
+ u64 mme_clk;
+ u64 tpc_clk;
+ u64 ic_clk;
+
+ u64 ddr_bar_cur_addr;
+ u32 events_stat[GOYA_ASYNC_EVENT_ID_SIZE];
+ u32 hw_cap_initialized;
+};
+
+int goya_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus,
+ u8 i2c_addr, u8 i2c_reg, u32 *val);
+int goya_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus,
+ u8 i2c_addr, u8 i2c_reg, u32 val);
+int goya_test_cpu_queue(struct hl_device *hdev);
+int goya_send_cpu_message(struct hl_device *hdev, u32 *msg, u16 len,
+ u32 timeout, long *result);
+long goya_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr);
+long goya_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr);
+long goya_get_current(struct hl_device *hdev, int sensor_index, u32 attr);
+long goya_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr);
+long goya_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr);
+void goya_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
+ long value);
+void goya_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state);
+void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq);
+void goya_add_device_attr(struct hl_device *hdev,
+ struct attribute_group *dev_attr_grp);
+void goya_init_security(struct hl_device *hdev);
+u64 goya_get_max_power(struct hl_device *hdev);
+void goya_set_max_power(struct hl_device *hdev, u64 value);
+
+int goya_send_pci_access_msg(struct hl_device *hdev, u32 opcode);
+void goya_late_fini(struct hl_device *hdev);
+int goya_suspend(struct hl_device *hdev);
+int goya_resume(struct hl_device *hdev);
+void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val);
+void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry);
+void *goya_get_events_stat(struct hl_device *hdev, u32 *size);
+void goya_add_end_of_cb_packets(u64 kernel_address, u32 len, u64 cq_addr,
+ u32 cq_val, u32 msix_vec);
+int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser);
+void *goya_get_int_queue_base(struct hl_device *hdev, u32 queue_id,
+ dma_addr_t *dma_handle, u16 *queue_len);
+u32 goya_get_dma_desc_list_size(struct hl_device *hdev, struct sg_table *sgt);
+int goya_test_queue(struct hl_device *hdev, u32 hw_queue_id);
+int goya_send_heartbeat(struct hl_device *hdev);
+
+#endif /* GOYAP_H_ */
diff --git a/drivers/misc/habanalabs/goya/goya_hwmgr.c b/drivers/misc/habanalabs/goya/goya_hwmgr.c
new file mode 100644
index 000000000000..088692c852b6
--- /dev/null
+++ b/drivers/misc/habanalabs/goya/goya_hwmgr.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "goyaP.h"
+
+void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ switch (freq) {
+ case PLL_HIGH:
+ hl_set_frequency(hdev, MME_PLL, hdev->high_pll);
+ hl_set_frequency(hdev, TPC_PLL, hdev->high_pll);
+ hl_set_frequency(hdev, IC_PLL, hdev->high_pll);
+ break;
+ case PLL_LOW:
+ hl_set_frequency(hdev, MME_PLL, GOYA_PLL_FREQ_LOW);
+ hl_set_frequency(hdev, TPC_PLL, GOYA_PLL_FREQ_LOW);
+ hl_set_frequency(hdev, IC_PLL, GOYA_PLL_FREQ_LOW);
+ break;
+ case PLL_LAST:
+ hl_set_frequency(hdev, MME_PLL, goya->mme_clk);
+ hl_set_frequency(hdev, TPC_PLL, goya->tpc_clk);
+ hl_set_frequency(hdev, IC_PLL, goya->ic_clk);
+ break;
+ default:
+ dev_err(hdev->dev, "unknown frequency setting\n");
+ }
+}
+
+static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, MME_PLL, false);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ struct goya_device *goya = hdev->asic_specific;
+ int rc;
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto fail;
+ }
+
+ if (hdev->pm_mng_profile == PM_AUTO) {
+ count = -EPERM;
+ goto fail;
+ }
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ hl_set_frequency(hdev, MME_PLL, value);
+ goya->mme_clk = value;
+
+fail:
+ return count;
+}
+
+static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, TPC_PLL, false);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ struct goya_device *goya = hdev->asic_specific;
+ int rc;
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto fail;
+ }
+
+ if (hdev->pm_mng_profile == PM_AUTO) {
+ count = -EPERM;
+ goto fail;
+ }
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ hl_set_frequency(hdev, TPC_PLL, value);
+ goya->tpc_clk = value;
+
+fail:
+ return count;
+}
+
+static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, IC_PLL, false);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ struct goya_device *goya = hdev->asic_specific;
+ int rc;
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto fail;
+ }
+
+ if (hdev->pm_mng_profile == PM_AUTO) {
+ count = -EPERM;
+ goto fail;
+ }
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ hl_set_frequency(hdev, IC_PLL, value);
+ goya->ic_clk = value;
+
+fail:
+ return count;
+}
+
+static ssize_t mme_clk_curr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, MME_PLL, true);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static ssize_t tpc_clk_curr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, TPC_PLL, true);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static ssize_t ic_clk_curr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ value = hl_get_frequency(hdev, IC_PLL, true);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%lu\n", value);
+}
+
+static DEVICE_ATTR_RW(ic_clk);
+static DEVICE_ATTR_RO(ic_clk_curr);
+static DEVICE_ATTR_RW(mme_clk);
+static DEVICE_ATTR_RO(mme_clk_curr);
+static DEVICE_ATTR_RW(tpc_clk);
+static DEVICE_ATTR_RO(tpc_clk_curr);
+
+static struct attribute *goya_dev_attrs[] = {
+ &dev_attr_ic_clk.attr,
+ &dev_attr_ic_clk_curr.attr,
+ &dev_attr_mme_clk.attr,
+ &dev_attr_mme_clk_curr.attr,
+ &dev_attr_tpc_clk.attr,
+ &dev_attr_tpc_clk_curr.attr,
+ NULL,
+};
+
+void goya_add_device_attr(struct hl_device *hdev,
+ struct attribute_group *dev_attr_grp)
+{
+ dev_attr_grp->attrs = goya_dev_attrs;
+}
diff --git a/drivers/misc/habanalabs/goya/goya_security.c b/drivers/misc/habanalabs/goya/goya_security.c
new file mode 100644
index 000000000000..575003238401
--- /dev/null
+++ b/drivers/misc/habanalabs/goya/goya_security.c
@@ -0,0 +1,2999 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "goyaP.h"
+
+/*
+ * goya_set_block_as_protected - set the given block as protected
+ *
+ * @hdev: pointer to hl_device structure
+ * @block: block base address
+ *
+ */
+static void goya_pb_set_block(struct hl_device *hdev, u64 base)
+{
+ u32 pb_addr = base - CFG_BASE + PROT_BITS_OFFS;
+
+ while (pb_addr & 0xFFF) {
+ WREG32(pb_addr, 0);
+ pb_addr += 4;
+ }
+}
+
+static void goya_init_mme_protection_bits(struct hl_device *hdev)
+{
+ u32 pb_addr, mask;
+ u8 word_offset;
+
+ /* TODO: change to real reg name when Soc Online is updated */
+ u64 mmMME_SBB_POWER_ECO1 = 0xDFF60,
+ mmMME_SBB_POWER_ECO2 = 0xDFF64;
+
+ goya_pb_set_block(hdev, mmACC_MS_ECC_MEM_0_BASE);
+ goya_pb_set_block(hdev, mmACC_MS_ECC_MEM_1_BASE);
+ goya_pb_set_block(hdev, mmACC_MS_ECC_MEM_2_BASE);
+ goya_pb_set_block(hdev, mmACC_MS_ECC_MEM_3_BASE);
+
+ goya_pb_set_block(hdev, mmSBA_ECC_MEM_BASE);
+ goya_pb_set_block(hdev, mmSBB_ECC_MEM_BASE);
+
+ goya_pb_set_block(hdev, mmMME1_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME1_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME1_WR_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME2_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME2_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME2_WR_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME3_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME3_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME3_WR_REGULATOR_BASE);
+
+ goya_pb_set_block(hdev, mmMME4_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME4_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME4_WR_REGULATOR_BASE);
+
+ goya_pb_set_block(hdev, mmMME5_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME5_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME5_WR_REGULATOR_BASE);
+
+ goya_pb_set_block(hdev, mmMME6_RTR_BASE);
+ goya_pb_set_block(hdev, mmMME6_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmMME6_WR_REGULATOR_BASE);
+
+ pb_addr = (mmMME_DUMMY & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_DUMMY & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_DUMMY & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_RESET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_STALL & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_DBGMEM_ADD & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_DBGMEM_DATA_WR & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_DBGMEM_DATA_RD & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_DBGMEM_CTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_DBGMEM_RC & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_LOG_SHADOW & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_STORE_MAX_CREDIT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_STORE_MAX_CREDIT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_STORE_MAX_CREDIT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_AGU & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBB & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBC & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_WBC & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBA_CONTROL_DATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBB_CONTROL_DATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBC_CONTROL_DATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_WBC_CONTROL_DATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_TE & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_TE2DEC & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_REI_STATUS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_REI_MASK & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SEI_STATUS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SEI_MASK & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SPI_STATUS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SPI_MASK & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_QM_CP_STS & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_QM_CP_STS & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_QM_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_CURRENT_INST_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_PQ_BUF_RDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_QM_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_CMDQ_CQ_IFIFO_CNT &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmMME_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmMME_SBB_POWER_ECO1 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmMME_SBB_POWER_ECO1 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmMME_SBB_POWER_ECO1 & 0x7F) >> 2);
+ mask |= 1 << ((mmMME_SBB_POWER_ECO2 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+}
+
+static void goya_init_dma_protection_bits(struct hl_device *hdev)
+{
+ u32 pb_addr, mask;
+ u8 word_offset;
+
+ goya_pb_set_block(hdev, mmDMA_NRTR_BASE);
+ goya_pb_set_block(hdev, mmDMA_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmDMA_WR_REGULATOR_BASE);
+
+ pb_addr = (mmDMA_QM_0_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_0_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_0_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_0_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_0_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_0_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_0_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_0_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_0_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_0_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmDMA_CH_0_BASE);
+
+ pb_addr = (mmDMA_QM_1_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_1_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_1_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_1_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_1_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_1_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_1_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_1_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_1_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_1_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmDMA_CH_1_BASE);
+
+ pb_addr = (mmDMA_QM_2_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_2_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_2_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_2_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_2_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_2_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_2_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_2_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_2_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_2_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmDMA_CH_2_BASE);
+
+ pb_addr = (mmDMA_QM_3_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_3_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_3_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_3_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_3_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_3_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_3_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_3_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_3_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_3_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmDMA_CH_3_BASE);
+
+ pb_addr = (mmDMA_QM_4_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_4_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_4_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_4_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_4_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_4_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmDMA_QM_4_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmDMA_QM_4_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmDMA_QM_4_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmDMA_QM_4_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmDMA_CH_4_BASE);
+}
+
+static void goya_init_tpc_protection_bits(struct hl_device *hdev)
+{
+ u32 pb_addr, mask;
+ u8 word_offset;
+
+ goya_pb_set_block(hdev, mmTPC0_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC0_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC0_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CFG_FUNC_MBIST_CNTRL &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC0_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC0_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC0_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC0_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC0_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC1_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC1_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC1_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CFG_FUNC_MBIST_CNTRL & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC1_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC1_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC1_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC1_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC1_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC1_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC2_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC2_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC2_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CFG_FUNC_MBIST_CNTRL & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC2_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC2_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC2_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC2_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC2_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC2_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC3_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC3_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC3_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH
+ & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CFG_FUNC_MBIST_CNTRL
+ & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC3_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC3_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC3_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC3_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC3_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC4_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC4_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC4_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CFG_FUNC_MBIST_CNTRL &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC4_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC4_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC4_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC4_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC4_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC5_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC5_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC5_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CFG_FUNC_MBIST_CNTRL &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC5_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC5_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC5_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC5_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC5_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC6_RTR_BASE);
+ goya_pb_set_block(hdev, mmTPC6_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC6_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CFG_FUNC_MBIST_CNTRL &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC6_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC6_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC6_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC6_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC6_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ goya_pb_set_block(hdev, mmTPC7_NRTR_BASE);
+ goya_pb_set_block(hdev, mmTPC7_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmTPC7_WR_REGULATOR_BASE);
+
+ pb_addr = (mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CFG_ARUSER & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CFG_ARUSER & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CFG_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_AWUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CFG_FUNC_MBIST_CNTRL & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CFG_FUNC_MBIST_CNTRL &
+ PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CFG_FUNC_MBIST_CNTRL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_PAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_4 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_5 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_6 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_7 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_8 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CFG_FUNC_MBIST_MEM_9 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_QM_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_QM_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_QM_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_GLBL_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_BASE_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_BASE_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_SIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_PI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_CI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_ARUSER & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_QM_PQ_PUSH0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_QM_PQ_PUSH0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_QM_PQ_PUSH0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_PUSH1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_PUSH2 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_PUSH3 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_PQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_PTR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_PTR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_TSIZE & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_CTL & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_QM_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_QM_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_QM_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_QM_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CMDQ_GLBL_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CMDQ_GLBL_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CMDQ_GLBL_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_PROT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_ERR_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_ERR_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_ERR_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_ERR_WDATA & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_NON_SECURE_PROPS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_GLBL_STS1 & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CMDQ_CQ_CFG0 & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CMDQ_CQ_CFG0 & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CMDQ_CQ_CFG0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_CFG1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_ARUSER & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_PTR_LO_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_PTR_HI_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_TSIZE_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_CTL_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_STS0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_STS1 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_RD_RATE_LIM_EN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_RD_RATE_LIM_SAT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_RD_RATE_LIM_TOUT & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CMDQ_CQ_IFIFO_CNT & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CMDQ_CQ_IFIFO_CNT & PROT_BITS_OFFS) >> 7) << 2;
+ mask = 1 << ((mmTPC7_CMDQ_CQ_IFIFO_CNT & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE0_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE0_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE1_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE1_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE2_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE2_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE3_ADDR_LO & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_MSG_BASE3_ADDR_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_TSIZE_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_LDMA_COMMIT_OFFSET & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_STS & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_CURRENT_INST_LO & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+
+ pb_addr = (mmTPC7_CMDQ_CP_CURRENT_INST_HI & ~0xFFF) + PROT_BITS_OFFS;
+ word_offset = ((mmTPC7_CMDQ_CP_CURRENT_INST_HI & PROT_BITS_OFFS) >> 7)
+ << 2;
+ mask = 1 << ((mmTPC7_CMDQ_CP_CURRENT_INST_HI & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_BARRIER_CFG & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CP_DBG_0 & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_BUF_ADDR & 0x7F) >> 2);
+ mask |= 1 << ((mmTPC7_CMDQ_CQ_BUF_RDATA & 0x7F) >> 2);
+
+ WREG32(pb_addr + word_offset, ~mask);
+}
+
+/*
+ * goya_init_protection_bits - Initialize protection bits for specific registers
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * All protection bits are 1 by default, means not protected. Need to set to 0
+ * each bit that belongs to a protected register.
+ *
+ */
+static void goya_init_protection_bits(struct hl_device *hdev)
+{
+ /*
+ * In each 4K block of registers, the last 128 bytes are protection
+ * bits - total of 1024 bits, one for each register. Each bit is related
+ * to a specific register, by the order of the registers.
+ * So in order to calculate the bit that is related to a given register,
+ * we need to calculate its word offset and then the exact bit inside
+ * the word (which is 4 bytes).
+ *
+ * Register address:
+ *
+ * 31 12 11 7 6 2 1 0
+ * -----------------------------------------------------------------
+ * | Don't | word | bit location | 0 |
+ * | care | offset | inside word | |
+ * -----------------------------------------------------------------
+ *
+ * Bits 7-11 represents the word offset inside the 128 bytes.
+ * Bits 2-6 represents the bit location inside the word.
+ */
+
+ goya_pb_set_block(hdev, mmPCI_NRTR_BASE);
+ goya_pb_set_block(hdev, mmPCI_RD_REGULATOR_BASE);
+ goya_pb_set_block(hdev, mmPCI_WR_REGULATOR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y0_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y0_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y1_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y1_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y2_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y2_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y3_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y3_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y4_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y4_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmSRAM_Y5_X0_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X0_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X1_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X1_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X2_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X2_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X3_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X3_RTR_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X4_BANK_BASE);
+ goya_pb_set_block(hdev, mmSRAM_Y5_X4_RTR_BASE);
+
+ goya_pb_set_block(hdev, mmPCIE_WRAP_BASE);
+ goya_pb_set_block(hdev, mmPCIE_CORE_BASE);
+ goya_pb_set_block(hdev, mmPCIE_DB_CFG_BASE);
+ goya_pb_set_block(hdev, mmPCIE_DB_CMD_BASE);
+ goya_pb_set_block(hdev, mmPCIE_AUX_BASE);
+ goya_pb_set_block(hdev, mmPCIE_DB_RSV_BASE);
+ goya_pb_set_block(hdev, mmPCIE_PHY_BASE);
+
+ goya_init_mme_protection_bits(hdev);
+
+ goya_init_dma_protection_bits(hdev);
+
+ goya_init_tpc_protection_bits(hdev);
+}
+
+/*
+ * goya_init_security - Initialize security model
+ *
+ * @hdev: pointer to hl_device structure
+ *
+ * Initialize the security model of the device
+ * That includes range registers and protection bit per register
+ *
+ */
+void goya_init_security(struct hl_device *hdev)
+{
+ struct goya_device *goya = hdev->asic_specific;
+
+ u32 dram_addr_lo = lower_32_bits(DRAM_PHYS_BASE);
+ u32 dram_addr_hi = upper_32_bits(DRAM_PHYS_BASE);
+
+ u32 lbw_rng0_base = 0xFC440000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng0_mask = 0xFFFF0000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng1_base = 0xFC480000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng1_mask = 0xFFF80000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng2_base = 0xFC600000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng2_mask = 0xFFE00000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng3_base = 0xFC800000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng3_mask = 0xFFF00000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng4_base = 0xFCC02000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng4_mask = 0xFFFFF000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng5_base = 0xFCC40000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng5_mask = 0xFFFF8000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng6_base = 0xFCC48000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng6_mask = 0xFFFFF000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng7_base = 0xFCC4A000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng7_mask = 0xFFFFE000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng8_base = 0xFCC4C000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng8_mask = 0xFFFFC000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng9_base = 0xFCC50000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng9_mask = 0xFFFF0000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng10_base = 0xFCC60000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng10_mask = 0xFFFE0000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng11_base = 0xFCE00000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng11_mask = 0xFFFFC000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng12_base = 0xFE484000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng12_mask = 0xFFFFF000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ u32 lbw_rng13_base = 0xFEC43000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+ u32 lbw_rng13_mask = 0xFFFFF000 & DMA_MACRO_LBW_RANGE_BASE_R_MASK;
+
+ WREG32(mmDMA_MACRO_LBW_RANGE_HIT_BLOCK, 0xFFFF);
+ WREG32(mmDMA_MACRO_HBW_RANGE_HIT_BLOCK, 0xFF);
+
+ if (!(goya->hw_cap_initialized & HW_CAP_MMU)) {
+ WREG32(mmDMA_MACRO_HBW_RANGE_HIT_BLOCK, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmDMA_MACRO_HBW_RANGE_BASE_31_0_0, 0);
+ WREG32(mmDMA_MACRO_HBW_RANGE_BASE_49_32_0, 0);
+ WREG32(mmDMA_MACRO_HBW_RANGE_MASK_31_0_0, 0);
+ WREG32(mmDMA_MACRO_HBW_RANGE_MASK_49_32_0, 0xFFF80);
+ }
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmDMA_MACRO_HBW_RANGE_BASE_31_0_1, dram_addr_lo);
+ WREG32(mmDMA_MACRO_HBW_RANGE_BASE_49_32_1, dram_addr_hi);
+ WREG32(mmDMA_MACRO_HBW_RANGE_MASK_31_0_1, 0xE0000000);
+ WREG32(mmDMA_MACRO_HBW_RANGE_MASK_49_32_1, 0x3FFFF);
+
+ /* Protect registers */
+
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmDMA_MACRO_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmDMA_MACRO_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME1_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmMME2_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmMME3_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmMME4_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmMME5_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmMME6_RTR_LBW_RANGE_HIT, 0xFFFF);
+
+ WREG32(mmMME1_RTR_HBW_RANGE_HIT, 0xFE);
+ WREG32(mmMME2_RTR_HBW_RANGE_HIT, 0xFE);
+ WREG32(mmMME3_RTR_HBW_RANGE_HIT, 0xFE);
+ WREG32(mmMME4_RTR_HBW_RANGE_HIT, 0xFE);
+ WREG32(mmMME5_RTR_HBW_RANGE_HIT, 0xFE);
+ WREG32(mmMME6_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmMME1_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME1_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME1_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME1_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ WREG32(mmMME2_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME2_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME2_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME2_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ WREG32(mmMME3_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME3_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME3_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME3_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ WREG32(mmMME4_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME4_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME4_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME4_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ WREG32(mmMME5_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME5_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME5_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME5_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ WREG32(mmMME6_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmMME6_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmMME6_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmMME6_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmMME1_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME1_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME1_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME1_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME2_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME2_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME2_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME2_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME3_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME3_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME3_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME3_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME4_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME4_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME4_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME4_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME5_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME5_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME5_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME5_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME6_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmMME6_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmMME6_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmMME6_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME1_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME1_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME2_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME2_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME3_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME3_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME4_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME4_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME5_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME5_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmMME6_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmMME6_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC0_NRTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC0_NRTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC0_NRTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC0_NRTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC0_NRTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC1_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC1_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC1_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC1_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC1_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC1_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC1_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC1_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC1_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC1_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC1_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC1_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC2_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC2_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC2_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC2_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC2_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC2_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC2_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC2_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC2_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC2_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC2_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC2_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC3_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC3_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC3_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC3_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC3_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC3_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC3_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC3_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC3_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC3_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC3_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC3_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC4_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC4_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC4_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC4_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC4_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC4_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC4_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC4_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC4_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC4_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC4_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC4_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC5_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC5_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC5_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC5_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC5_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC5_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC5_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC5_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC5_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC5_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC5_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC5_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC6_RTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC6_RTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC6_RTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC6_RTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC6_RTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC6_RTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC6_RTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC6_RTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC6_RTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC6_RTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC6_RTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC6_RTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ WREG32(mmTPC7_NRTR_LBW_RANGE_HIT, 0xFFFF);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_HIT, 0xFE);
+
+ /* Protect HOST */
+ WREG32(mmTPC7_NRTR_HBW_RANGE_BASE_L_0, 0);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_BASE_H_0, 0);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_MASK_L_0, 0);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_MASK_H_0, 0xFFF80);
+
+ /*
+ * Protect DDR @
+ * DRAM_VIRT_BASE : DRAM_VIRT_BASE + DRAM_VIRT_END
+ * The mask protects the first 512MB
+ */
+ WREG32(mmTPC7_NRTR_HBW_RANGE_BASE_L_1, dram_addr_lo);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_BASE_H_1, dram_addr_hi);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_MASK_L_1, 0xE0000000);
+ WREG32(mmTPC7_NRTR_HBW_RANGE_MASK_H_1, 0x3FFFF);
+
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_0, lbw_rng0_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_0, lbw_rng0_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_1, lbw_rng1_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_1, lbw_rng1_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_2, lbw_rng2_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_2, lbw_rng2_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_3, lbw_rng3_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_3, lbw_rng3_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_4, lbw_rng4_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_4, lbw_rng4_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_5, lbw_rng5_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_5, lbw_rng5_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_6, lbw_rng6_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_6, lbw_rng6_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_7, lbw_rng7_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_7, lbw_rng7_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_8, lbw_rng8_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_8, lbw_rng8_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_9, lbw_rng9_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_9, lbw_rng9_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_10, lbw_rng10_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_10, lbw_rng10_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_11, lbw_rng11_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_11, lbw_rng11_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_12, lbw_rng12_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_12, lbw_rng12_mask);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_BASE_13, lbw_rng13_base);
+ WREG32(mmTPC7_NRTR_LBW_RANGE_MASK_13, lbw_rng13_mask);
+
+ goya_init_protection_bits(hdev);
+}
diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h
new file mode 100644
index 000000000000..a7c95e9f9b9a
--- /dev/null
+++ b/drivers/misc/habanalabs/habanalabs.h
@@ -0,0 +1,1464 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef HABANALABSP_H_
+#define HABANALABSP_H_
+
+#include "include/armcp_if.h"
+#include "include/qman_if.h"
+
+#define pr_fmt(fmt) "habanalabs: " fmt
+
+#include <linux/cdev.h>
+#include <linux/iopoll.h>
+#include <linux/irqreturn.h>
+#include <linux/dma-fence.h>
+#include <linux/dma-direction.h>
+#include <linux/scatterlist.h>
+#include <linux/hashtable.h>
+
+#define HL_NAME "habanalabs"
+
+#define HL_MMAP_CB_MASK (0x8000000000000000ull >> PAGE_SHIFT)
+
+#define HL_PENDING_RESET_PER_SEC 5
+
+#define HL_DEVICE_TIMEOUT_USEC 1000000 /* 1 s */
+
+#define HL_HEARTBEAT_PER_USEC 5000000 /* 5 s */
+
+#define HL_PLL_LOW_JOB_FREQ_USEC 5000000 /* 5 s */
+
+#define HL_MAX_QUEUES 128
+
+#define HL_MAX_JOBS_PER_CS 64
+
+/* MUST BE POWER OF 2 and larger than 1 */
+#define HL_MAX_PENDING_CS 64
+
+/* Memory */
+#define MEM_HASH_TABLE_BITS 7 /* 1 << 7 buckets */
+
+/* MMU */
+#define MMU_HASH_TABLE_BITS 7 /* 1 << 7 buckets */
+
+/**
+ * struct pgt_info - MMU hop page info.
+ * @node: hash linked-list node for the pgts hash of pgts.
+ * @addr: physical address of the pgt.
+ * @ctx: pointer to the owner ctx.
+ * @num_of_ptes: indicates how many ptes are used in the pgt.
+ *
+ * The MMU page tables hierarchy is placed on the DRAM. When a new level (hop)
+ * is needed during mapping, a new page is allocated and this structure holds
+ * its essential information. During unmapping, if no valid PTEs remained in the
+ * page, it is freed with its pgt_info structure.
+ */
+struct pgt_info {
+ struct hlist_node node;
+ u64 addr;
+ struct hl_ctx *ctx;
+ int num_of_ptes;
+};
+
+struct hl_device;
+struct hl_fpriv;
+
+/**
+ * enum hl_queue_type - Supported QUEUE types.
+ * @QUEUE_TYPE_NA: queue is not available.
+ * @QUEUE_TYPE_EXT: external queue which is a DMA channel that may access the
+ * host.
+ * @QUEUE_TYPE_INT: internal queue that performs DMA inside the device's
+ * memories and/or operates the compute engines.
+ * @QUEUE_TYPE_CPU: S/W queue for communication with the device's CPU.
+ */
+enum hl_queue_type {
+ QUEUE_TYPE_NA,
+ QUEUE_TYPE_EXT,
+ QUEUE_TYPE_INT,
+ QUEUE_TYPE_CPU
+};
+
+/**
+ * struct hw_queue_properties - queue information.
+ * @type: queue type.
+ * @kmd_only: true if only KMD is allowed to send a job to this queue, false
+ * otherwise.
+ */
+struct hw_queue_properties {
+ enum hl_queue_type type;
+ u8 kmd_only;
+};
+
+/**
+ * enum vm_type_t - virtual memory mapping request information.
+ * @VM_TYPE_USERPTR: mapping of user memory to device virtual address.
+ * @VM_TYPE_PHYS_PACK: mapping of DRAM memory to device virtual address.
+ */
+enum vm_type_t {
+ VM_TYPE_USERPTR,
+ VM_TYPE_PHYS_PACK
+};
+
+/**
+ * enum hl_device_hw_state - H/W device state. use this to understand whether
+ * to do reset before hw_init or not
+ * @HL_DEVICE_HW_STATE_CLEAN: H/W state is clean. i.e. after hard reset
+ * @HL_DEVICE_HW_STATE_DIRTY: H/W state is dirty. i.e. we started to execute
+ * hw_init
+ */
+enum hl_device_hw_state {
+ HL_DEVICE_HW_STATE_CLEAN = 0,
+ HL_DEVICE_HW_STATE_DIRTY
+};
+
+/**
+ * struct asic_fixed_properties - ASIC specific immutable properties.
+ * @hw_queues_props: H/W queues properties.
+ * @armcp_info: received various information from ArmCP regarding the H/W. e.g.
+ * available sensors.
+ * @uboot_ver: F/W U-boot version.
+ * @preboot_ver: F/W Preboot version.
+ * @sram_base_address: SRAM physical start address.
+ * @sram_end_address: SRAM physical end address.
+ * @sram_user_base_address - SRAM physical start address for user access.
+ * @dram_base_address: DRAM physical start address.
+ * @dram_end_address: DRAM physical end address.
+ * @dram_user_base_address: DRAM physical start address for user access.
+ * @dram_size: DRAM total size.
+ * @dram_pci_bar_size: size of PCI bar towards DRAM.
+ * @host_phys_base_address: base physical address of host memory for
+ * transactions that the device generates.
+ * @max_power_default: max power of the device after reset
+ * @va_space_host_start_address: base address of virtual memory range for
+ * mapping host memory.
+ * @va_space_host_end_address: end address of virtual memory range for
+ * mapping host memory.
+ * @va_space_dram_start_address: base address of virtual memory range for
+ * mapping DRAM memory.
+ * @va_space_dram_end_address: end address of virtual memory range for
+ * mapping DRAM memory.
+ * @dram_size_for_default_page_mapping: DRAM size needed to map to avoid page
+ * fault.
+ * @mmu_pgt_addr: base physical address in DRAM of MMU page tables.
+ * @mmu_dram_default_page_addr: DRAM default page physical address.
+ * @mmu_pgt_size: MMU page tables total size.
+ * @mmu_pte_size: PTE size in MMU page tables.
+ * @mmu_hop_table_size: MMU hop table size.
+ * @mmu_hop0_tables_total_size: total size of MMU hop0 tables.
+ * @dram_page_size: page size for MMU DRAM allocation.
+ * @cfg_size: configuration space size on SRAM.
+ * @sram_size: total size of SRAM.
+ * @max_asid: maximum number of open contexts (ASIDs).
+ * @num_of_events: number of possible internal H/W IRQs.
+ * @psoc_pci_pll_nr: PCI PLL NR value.
+ * @psoc_pci_pll_nf: PCI PLL NF value.
+ * @psoc_pci_pll_od: PCI PLL OD value.
+ * @psoc_pci_pll_div_factor: PCI PLL DIV FACTOR 1 value.
+ * @completion_queues_count: number of completion queues.
+ * @high_pll: high PLL frequency used by the device.
+ * @cb_pool_cb_cnt: number of CBs in the CB pool.
+ * @cb_pool_cb_size: size of each CB in the CB pool.
+ * @tpc_enabled_mask: which TPCs are enabled.
+ */
+struct asic_fixed_properties {
+ struct hw_queue_properties hw_queues_props[HL_MAX_QUEUES];
+ struct armcp_info armcp_info;
+ char uboot_ver[VERSION_MAX_LEN];
+ char preboot_ver[VERSION_MAX_LEN];
+ u64 sram_base_address;
+ u64 sram_end_address;
+ u64 sram_user_base_address;
+ u64 dram_base_address;
+ u64 dram_end_address;
+ u64 dram_user_base_address;
+ u64 dram_size;
+ u64 dram_pci_bar_size;
+ u64 host_phys_base_address;
+ u64 max_power_default;
+ u64 va_space_host_start_address;
+ u64 va_space_host_end_address;
+ u64 va_space_dram_start_address;
+ u64 va_space_dram_end_address;
+ u64 dram_size_for_default_page_mapping;
+ u64 mmu_pgt_addr;
+ u64 mmu_dram_default_page_addr;
+ u32 mmu_pgt_size;
+ u32 mmu_pte_size;
+ u32 mmu_hop_table_size;
+ u32 mmu_hop0_tables_total_size;
+ u32 dram_page_size;
+ u32 cfg_size;
+ u32 sram_size;
+ u32 max_asid;
+ u32 num_of_events;
+ u32 psoc_pci_pll_nr;
+ u32 psoc_pci_pll_nf;
+ u32 psoc_pci_pll_od;
+ u32 psoc_pci_pll_div_factor;
+ u32 high_pll;
+ u32 cb_pool_cb_cnt;
+ u32 cb_pool_cb_size;
+ u8 completion_queues_count;
+ u8 tpc_enabled_mask;
+};
+
+/**
+ * struct hl_dma_fence - wrapper for fence object used by command submissions.
+ * @base_fence: kernel fence object.
+ * @lock: spinlock to protect fence.
+ * @hdev: habanalabs device structure.
+ * @cs_seq: command submission sequence number.
+ */
+struct hl_dma_fence {
+ struct dma_fence base_fence;
+ spinlock_t lock;
+ struct hl_device *hdev;
+ u64 cs_seq;
+};
+
+/*
+ * Command Buffers
+ */
+
+#define HL_MAX_CB_SIZE 0x200000 /* 2MB */
+
+/**
+ * struct hl_cb_mgr - describes a Command Buffer Manager.
+ * @cb_lock: protects cb_handles.
+ * @cb_handles: an idr to hold all command buffer handles.
+ */
+struct hl_cb_mgr {
+ spinlock_t cb_lock;
+ struct idr cb_handles; /* protected by cb_lock */
+};
+
+/**
+ * struct hl_cb - describes a Command Buffer.
+ * @refcount: reference counter for usage of the CB.
+ * @hdev: pointer to device this CB belongs to.
+ * @lock: spinlock to protect mmap/cs flows.
+ * @debugfs_list: node in debugfs list of command buffers.
+ * @pool_list: node in pool list of command buffers.
+ * @kernel_address: Holds the CB's kernel virtual address.
+ * @bus_address: Holds the CB's DMA address.
+ * @mmap_size: Holds the CB's size that was mmaped.
+ * @size: holds the CB's size.
+ * @id: the CB's ID.
+ * @cs_cnt: holds number of CS that this CB participates in.
+ * @ctx_id: holds the ID of the owner's context.
+ * @mmap: true if the CB is currently mmaped to user.
+ * @is_pool: true if CB was acquired from the pool, false otherwise.
+ */
+struct hl_cb {
+ struct kref refcount;
+ struct hl_device *hdev;
+ spinlock_t lock;
+ struct list_head debugfs_list;
+ struct list_head pool_list;
+ u64 kernel_address;
+ dma_addr_t bus_address;
+ u32 mmap_size;
+ u32 size;
+ u32 id;
+ u32 cs_cnt;
+ u32 ctx_id;
+ u8 mmap;
+ u8 is_pool;
+};
+
+
+/*
+ * QUEUES
+ */
+
+struct hl_cs_job;
+
+/*
+ * Currently, there are two limitations on the maximum length of a queue:
+ *
+ * 1. The memory footprint of the queue. The current allocated space for the
+ * queue is PAGE_SIZE. Because each entry in the queue is HL_BD_SIZE,
+ * the maximum length of the queue can be PAGE_SIZE / HL_BD_SIZE,
+ * which currently is 4096/16 = 256 entries.
+ *
+ * To increase that, we need either to decrease the size of the
+ * BD (difficult), or allocate more than a single page (easier).
+ *
+ * 2. Because the size of the JOB handle field in the BD CTL / completion queue
+ * is 10-bit, we can have up to 1024 open jobs per hardware queue.
+ * Therefore, each queue can hold up to 1024 entries.
+ *
+ * HL_QUEUE_LENGTH is in units of struct hl_bd.
+ * HL_QUEUE_LENGTH * sizeof(struct hl_bd) should be <= HL_PAGE_SIZE
+ */
+
+#define HL_PAGE_SIZE 4096 /* minimum page size */
+/* Must be power of 2 (HL_PAGE_SIZE / HL_BD_SIZE) */
+#define HL_QUEUE_LENGTH 256
+#define HL_QUEUE_SIZE_IN_BYTES (HL_QUEUE_LENGTH * HL_BD_SIZE)
+
+/*
+ * HL_CQ_LENGTH is in units of struct hl_cq_entry.
+ * HL_CQ_LENGTH should be <= HL_PAGE_SIZE
+ */
+#define HL_CQ_LENGTH HL_QUEUE_LENGTH
+#define HL_CQ_SIZE_IN_BYTES (HL_CQ_LENGTH * HL_CQ_ENTRY_SIZE)
+
+/* Must be power of 2 (HL_PAGE_SIZE / HL_EQ_ENTRY_SIZE) */
+#define HL_EQ_LENGTH 64
+#define HL_EQ_SIZE_IN_BYTES (HL_EQ_LENGTH * HL_EQ_ENTRY_SIZE)
+
+
+/**
+ * struct hl_hw_queue - describes a H/W transport queue.
+ * @shadow_queue: pointer to a shadow queue that holds pointers to jobs.
+ * @queue_type: type of queue.
+ * @kernel_address: holds the queue's kernel virtual address.
+ * @bus_address: holds the queue's DMA address.
+ * @pi: holds the queue's pi value.
+ * @ci: holds the queue's ci value, AS CALCULATED BY THE DRIVER (not real ci).
+ * @hw_queue_id: the id of the H/W queue.
+ * @int_queue_len: length of internal queue (number of entries).
+ * @valid: is the queue valid (we have array of 32 queues, not all of them
+ * exists).
+ */
+struct hl_hw_queue {
+ struct hl_cs_job **shadow_queue;
+ enum hl_queue_type queue_type;
+ u64 kernel_address;
+ dma_addr_t bus_address;
+ u32 pi;
+ u32 ci;
+ u32 hw_queue_id;
+ u16 int_queue_len;
+ u8 valid;
+};
+
+/**
+ * struct hl_cq - describes a completion queue
+ * @hdev: pointer to the device structure
+ * @kernel_address: holds the queue's kernel virtual address
+ * @bus_address: holds the queue's DMA address
+ * @hw_queue_id: the id of the matching H/W queue
+ * @ci: ci inside the queue
+ * @pi: pi inside the queue
+ * @free_slots_cnt: counter of free slots in queue
+ */
+struct hl_cq {
+ struct hl_device *hdev;
+ u64 kernel_address;
+ dma_addr_t bus_address;
+ u32 hw_queue_id;
+ u32 ci;
+ u32 pi;
+ atomic_t free_slots_cnt;
+};
+
+/**
+ * struct hl_eq - describes the event queue (single one per device)
+ * @hdev: pointer to the device structure
+ * @kernel_address: holds the queue's kernel virtual address
+ * @bus_address: holds the queue's DMA address
+ * @ci: ci inside the queue
+ */
+struct hl_eq {
+ struct hl_device *hdev;
+ u64 kernel_address;
+ dma_addr_t bus_address;
+ u32 ci;
+};
+
+
+/*
+ * ASICs
+ */
+
+/**
+ * enum hl_asic_type - supported ASIC types.
+ * @ASIC_AUTO_DETECT: ASIC type will be automatically set.
+ * @ASIC_GOYA: Goya device.
+ * @ASIC_INVALID: Invalid ASIC type.
+ */
+enum hl_asic_type {
+ ASIC_AUTO_DETECT,
+ ASIC_GOYA,
+ ASIC_INVALID
+};
+
+struct hl_cs_parser;
+
+/**
+ * enum hl_pm_mng_profile - power management profile.
+ * @PM_AUTO: internal clock is set by KMD.
+ * @PM_MANUAL: internal clock is set by the user.
+ * @PM_LAST: last power management type.
+ */
+enum hl_pm_mng_profile {
+ PM_AUTO = 1,
+ PM_MANUAL,
+ PM_LAST
+};
+
+/**
+ * enum hl_pll_frequency - PLL frequency.
+ * @PLL_HIGH: high frequency.
+ * @PLL_LOW: low frequency.
+ * @PLL_LAST: last frequency values that were configured by the user.
+ */
+enum hl_pll_frequency {
+ PLL_HIGH = 1,
+ PLL_LOW,
+ PLL_LAST
+};
+
+/**
+ * struct hl_asic_funcs - ASIC specific functions that are can be called from
+ * common code.
+ * @early_init: sets up early driver state (pre sw_init), doesn't configure H/W.
+ * @early_fini: tears down what was done in early_init.
+ * @late_init: sets up late driver/hw state (post hw_init) - Optional.
+ * @late_fini: tears down what was done in late_init (pre hw_fini) - Optional.
+ * @sw_init: sets up driver state, does not configure H/W.
+ * @sw_fini: tears down driver state, does not configure H/W.
+ * @hw_init: sets up the H/W state.
+ * @hw_fini: tears down the H/W state.
+ * @halt_engines: halt engines, needed for reset sequence. This also disables
+ * interrupts from the device. Should be called before
+ * hw_fini and before CS rollback.
+ * @suspend: handles IP specific H/W or SW changes for suspend.
+ * @resume: handles IP specific H/W or SW changes for resume.
+ * @cb_mmap: maps a CB.
+ * @ring_doorbell: increment PI on a given QMAN.
+ * @flush_pq_write: flush PQ entry write if necessary, WARN if flushing failed.
+ * @dma_alloc_coherent: Allocate coherent DMA memory by calling
+ * dma_alloc_coherent(). This is ASIC function because its
+ * implementation is not trivial when the driver is loaded
+ * in simulation mode (not upstreamed).
+ * @dma_free_coherent: Free coherent DMA memory by calling dma_free_coherent().
+ * This is ASIC function because its implementation is not
+ * trivial when the driver is loaded in simulation mode
+ * (not upstreamed).
+ * @get_int_queue_base: get the internal queue base address.
+ * @test_queues: run simple test on all queues for sanity check.
+ * @dma_pool_zalloc: small DMA allocation of coherent memory from DMA pool.
+ * size of allocation is HL_DMA_POOL_BLK_SIZE.
+ * @dma_pool_free: free small DMA allocation from pool.
+ * @cpu_accessible_dma_pool_alloc: allocate CPU PQ packet from DMA pool.
+ * @cpu_accessible_dma_pool_free: free CPU PQ packet from DMA pool.
+ * @hl_dma_unmap_sg: DMA unmap scatter-gather list.
+ * @cs_parser: parse Command Submission.
+ * @asic_dma_map_sg: DMA map scatter-gather list.
+ * @get_dma_desc_list_size: get number of LIN_DMA packets required for CB.
+ * @add_end_of_cb_packets: Add packets to the end of CB, if device requires it.
+ * @update_eq_ci: update event queue CI.
+ * @context_switch: called upon ASID context switch.
+ * @restore_phase_topology: clear all SOBs amd MONs.
+ * @debugfs_read32: debug interface for reading u32 from DRAM/SRAM.
+ * @debugfs_write32: debug interface for writing u32 to DRAM/SRAM.
+ * @add_device_attr: add ASIC specific device attributes.
+ * @handle_eqe: handle event queue entry (IRQ) from ArmCP.
+ * @set_pll_profile: change PLL profile (manual/automatic).
+ * @get_events_stat: retrieve event queue entries histogram.
+ * @read_pte: read MMU page table entry from DRAM.
+ * @write_pte: write MMU page table entry to DRAM.
+ * @mmu_invalidate_cache: flush MMU STLB cache, either with soft (L1 only) or
+ * hard (L0 & L1) flush.
+ * @mmu_invalidate_cache_range: flush specific MMU STLB cache lines with
+ * ASID-VA-size mask.
+ * @send_heartbeat: send is-alive packet to ArmCP and verify response.
+ * @enable_clock_gating: enable clock gating for reducing power consumption.
+ * @disable_clock_gating: disable clock for accessing registers on HBW.
+ * @is_device_idle: return true if device is idle, false otherwise.
+ * @soft_reset_late_init: perform certain actions needed after soft reset.
+ * @hw_queues_lock: acquire H/W queues lock.
+ * @hw_queues_unlock: release H/W queues lock.
+ * @get_pci_id: retrieve PCI ID.
+ * @get_eeprom_data: retrieve EEPROM data from F/W.
+ * @send_cpu_message: send buffer to ArmCP.
+ * @get_hw_state: retrieve the H/W state
+ */
+struct hl_asic_funcs {
+ int (*early_init)(struct hl_device *hdev);
+ int (*early_fini)(struct hl_device *hdev);
+ int (*late_init)(struct hl_device *hdev);
+ void (*late_fini)(struct hl_device *hdev);
+ int (*sw_init)(struct hl_device *hdev);
+ int (*sw_fini)(struct hl_device *hdev);
+ int (*hw_init)(struct hl_device *hdev);
+ void (*hw_fini)(struct hl_device *hdev, bool hard_reset);
+ void (*halt_engines)(struct hl_device *hdev, bool hard_reset);
+ int (*suspend)(struct hl_device *hdev);
+ int (*resume)(struct hl_device *hdev);
+ int (*cb_mmap)(struct hl_device *hdev, struct vm_area_struct *vma,
+ u64 kaddress, phys_addr_t paddress, u32 size);
+ void (*ring_doorbell)(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
+ void (*flush_pq_write)(struct hl_device *hdev, u64 *pq, u64 exp_val);
+ void* (*dma_alloc_coherent)(struct hl_device *hdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag);
+ void (*dma_free_coherent)(struct hl_device *hdev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle);
+ void* (*get_int_queue_base)(struct hl_device *hdev, u32 queue_id,
+ dma_addr_t *dma_handle, u16 *queue_len);
+ int (*test_queues)(struct hl_device *hdev);
+ void* (*dma_pool_zalloc)(struct hl_device *hdev, size_t size,
+ gfp_t mem_flags, dma_addr_t *dma_handle);
+ void (*dma_pool_free)(struct hl_device *hdev, void *vaddr,
+ dma_addr_t dma_addr);
+ void* (*cpu_accessible_dma_pool_alloc)(struct hl_device *hdev,
+ size_t size, dma_addr_t *dma_handle);
+ void (*cpu_accessible_dma_pool_free)(struct hl_device *hdev,
+ size_t size, void *vaddr);
+ void (*hl_dma_unmap_sg)(struct hl_device *hdev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir);
+ int (*cs_parser)(struct hl_device *hdev, struct hl_cs_parser *parser);
+ int (*asic_dma_map_sg)(struct hl_device *hdev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir);
+ u32 (*get_dma_desc_list_size)(struct hl_device *hdev,
+ struct sg_table *sgt);
+ void (*add_end_of_cb_packets)(u64 kernel_address, u32 len, u64 cq_addr,
+ u32 cq_val, u32 msix_num);
+ void (*update_eq_ci)(struct hl_device *hdev, u32 val);
+ int (*context_switch)(struct hl_device *hdev, u32 asid);
+ void (*restore_phase_topology)(struct hl_device *hdev);
+ int (*debugfs_read32)(struct hl_device *hdev, u64 addr, u32 *val);
+ int (*debugfs_write32)(struct hl_device *hdev, u64 addr, u32 val);
+ void (*add_device_attr)(struct hl_device *hdev,
+ struct attribute_group *dev_attr_grp);
+ void (*handle_eqe)(struct hl_device *hdev,
+ struct hl_eq_entry *eq_entry);
+ void (*set_pll_profile)(struct hl_device *hdev,
+ enum hl_pll_frequency freq);
+ void* (*get_events_stat)(struct hl_device *hdev, u32 *size);
+ u64 (*read_pte)(struct hl_device *hdev, u64 addr);
+ void (*write_pte)(struct hl_device *hdev, u64 addr, u64 val);
+ void (*mmu_invalidate_cache)(struct hl_device *hdev, bool is_hard);
+ void (*mmu_invalidate_cache_range)(struct hl_device *hdev, bool is_hard,
+ u32 asid, u64 va, u64 size);
+ int (*send_heartbeat)(struct hl_device *hdev);
+ void (*enable_clock_gating)(struct hl_device *hdev);
+ void (*disable_clock_gating)(struct hl_device *hdev);
+ bool (*is_device_idle)(struct hl_device *hdev);
+ int (*soft_reset_late_init)(struct hl_device *hdev);
+ void (*hw_queues_lock)(struct hl_device *hdev);
+ void (*hw_queues_unlock)(struct hl_device *hdev);
+ u32 (*get_pci_id)(struct hl_device *hdev);
+ int (*get_eeprom_data)(struct hl_device *hdev, void *data,
+ size_t max_size);
+ int (*send_cpu_message)(struct hl_device *hdev, u32 *msg,
+ u16 len, u32 timeout, long *result);
+ enum hl_device_hw_state (*get_hw_state)(struct hl_device *hdev);
+};
+
+
+/*
+ * CONTEXTS
+ */
+
+#define HL_KERNEL_ASID_ID 0
+
+/**
+ * struct hl_va_range - virtual addresses range.
+ * @lock: protects the virtual addresses list.
+ * @list: list of virtual addresses blocks available for mappings.
+ * @start_addr: range start address.
+ * @end_addr: range end address.
+ */
+struct hl_va_range {
+ struct mutex lock;
+ struct list_head list;
+ u64 start_addr;
+ u64 end_addr;
+};
+
+/**
+ * struct hl_ctx - user/kernel context.
+ * @mem_hash: holds mapping from virtual address to virtual memory area
+ * descriptor (hl_vm_phys_pg_list or hl_userptr).
+ * @mmu_hash: holds a mapping from virtual address to pgt_info structure.
+ * @hpriv: pointer to the private (KMD) data of the process (fd).
+ * @hdev: pointer to the device structure.
+ * @refcount: reference counter for the context. Context is released only when
+ * this hits 0l. It is incremented on CS and CS_WAIT.
+ * @cs_pending: array of DMA fence objects representing pending CS.
+ * @host_va_range: holds available virtual addresses for host mappings.
+ * @dram_va_range: holds available virtual addresses for DRAM mappings.
+ * @mem_hash_lock: protects the mem_hash.
+ * @mmu_lock: protects the MMU page tables. Any change to the PGT, modifing the
+ * MMU hash or walking the PGT requires talking this lock
+ * @debugfs_list: node in debugfs list of contexts.
+ * @cs_sequence: sequence number for CS. Value is assigned to a CS and passed
+ * to user so user could inquire about CS. It is used as
+ * index to cs_pending array.
+ * @dram_default_hops: array that holds all hops addresses needed for default
+ * DRAM mapping.
+ * @cs_lock: spinlock to protect cs_sequence.
+ * @dram_phys_mem: amount of used physical DRAM memory by this context.
+ * @thread_restore_token: token to prevent multiple threads of the same context
+ * from running the restore phase. Only one thread
+ * should run it.
+ * @thread_restore_wait_token: token to prevent the threads that didn't run
+ * the restore phase from moving to their execution
+ * phase before the restore phase has finished.
+ * @asid: context's unique address space ID in the device's MMU.
+ */
+struct hl_ctx {
+ DECLARE_HASHTABLE(mem_hash, MEM_HASH_TABLE_BITS);
+ DECLARE_HASHTABLE(mmu_hash, MMU_HASH_TABLE_BITS);
+ struct hl_fpriv *hpriv;
+ struct hl_device *hdev;
+ struct kref refcount;
+ struct dma_fence *cs_pending[HL_MAX_PENDING_CS];
+ struct hl_va_range host_va_range;
+ struct hl_va_range dram_va_range;
+ struct mutex mem_hash_lock;
+ struct mutex mmu_lock;
+ struct list_head debugfs_list;
+ u64 cs_sequence;
+ u64 *dram_default_hops;
+ spinlock_t cs_lock;
+ atomic64_t dram_phys_mem;
+ atomic_t thread_restore_token;
+ u32 thread_restore_wait_token;
+ u32 asid;
+};
+
+/**
+ * struct hl_ctx_mgr - for handling multiple contexts.
+ * @ctx_lock: protects ctx_handles.
+ * @ctx_handles: idr to hold all ctx handles.
+ */
+struct hl_ctx_mgr {
+ struct mutex ctx_lock;
+ struct idr ctx_handles;
+};
+
+
+
+/*
+ * COMMAND SUBMISSIONS
+ */
+
+/**
+ * struct hl_userptr - memory mapping chunk information
+ * @vm_type: type of the VM.
+ * @job_node: linked-list node for hanging the object on the Job's list.
+ * @vec: pointer to the frame vector.
+ * @sgt: pointer to the scatter-gather table that holds the pages.
+ * @dir: for DMA unmapping, the direction must be supplied, so save it.
+ * @debugfs_list: node in debugfs list of command submissions.
+ * @addr: user-space virtual pointer to the start of the memory area.
+ * @size: size of the memory area to pin & map.
+ * @dma_mapped: true if the SG was mapped to DMA addresses, false otherwise.
+ */
+struct hl_userptr {
+ enum vm_type_t vm_type; /* must be first */
+ struct list_head job_node;
+ struct frame_vector *vec;
+ struct sg_table *sgt;
+ enum dma_data_direction dir;
+ struct list_head debugfs_list;
+ u64 addr;
+ u32 size;
+ u8 dma_mapped;
+};
+
+/**
+ * struct hl_cs - command submission.
+ * @jobs_in_queue_cnt: per each queue, maintain counter of submitted jobs.
+ * @ctx: the context this CS belongs to.
+ * @job_list: list of the CS's jobs in the various queues.
+ * @job_lock: spinlock for the CS's jobs list. Needed for free_job.
+ * @refcount: reference counter for usage of the CS.
+ * @fence: pointer to the fence object of this CS.
+ * @work_tdr: delayed work node for TDR.
+ * @mirror_node : node in device mirror list of command submissions.
+ * @debugfs_list: node in debugfs list of command submissions.
+ * @sequence: the sequence number of this CS.
+ * @submitted: true if CS was submitted to H/W.
+ * @completed: true if CS was completed by device.
+ * @timedout : true if CS was timedout.
+ * @tdr_active: true if TDR was activated for this CS (to prevent
+ * double TDR activation).
+ * @aborted: true if CS was aborted due to some device error.
+ */
+struct hl_cs {
+ u8 jobs_in_queue_cnt[HL_MAX_QUEUES];
+ struct hl_ctx *ctx;
+ struct list_head job_list;
+ spinlock_t job_lock;
+ struct kref refcount;
+ struct dma_fence *fence;
+ struct delayed_work work_tdr;
+ struct list_head mirror_node;
+ struct list_head debugfs_list;
+ u64 sequence;
+ u8 submitted;
+ u8 completed;
+ u8 timedout;
+ u8 tdr_active;
+ u8 aborted;
+};
+
+/**
+ * struct hl_cs_job - command submission job.
+ * @cs_node: the node to hang on the CS jobs list.
+ * @cs: the CS this job belongs to.
+ * @user_cb: the CB we got from the user.
+ * @patched_cb: in case of patching, this is internal CB which is submitted on
+ * the queue instead of the CB we got from the IOCTL.
+ * @finish_work: workqueue object to run when job is completed.
+ * @userptr_list: linked-list of userptr mappings that belong to this job and
+ * wait for completion.
+ * @debugfs_list: node in debugfs list of command submission jobs.
+ * @id: the id of this job inside a CS.
+ * @hw_queue_id: the id of the H/W queue this job is submitted to.
+ * @user_cb_size: the actual size of the CB we got from the user.
+ * @job_cb_size: the actual size of the CB that we put on the queue.
+ * @ext_queue: whether the job is for external queue or internal queue.
+ */
+struct hl_cs_job {
+ struct list_head cs_node;
+ struct hl_cs *cs;
+ struct hl_cb *user_cb;
+ struct hl_cb *patched_cb;
+ struct work_struct finish_work;
+ struct list_head userptr_list;
+ struct list_head debugfs_list;
+ u32 id;
+ u32 hw_queue_id;
+ u32 user_cb_size;
+ u32 job_cb_size;
+ u8 ext_queue;
+};
+
+/**
+ * struct hl_cs_parser - command submission paerser properties.
+ * @user_cb: the CB we got from the user.
+ * @patched_cb: in case of patching, this is internal CB which is submitted on
+ * the queue instead of the CB we got from the IOCTL.
+ * @job_userptr_list: linked-list of userptr mappings that belong to the related
+ * job and wait for completion.
+ * @cs_sequence: the sequence number of the related CS.
+ * @ctx_id: the ID of the context the related CS belongs to.
+ * @hw_queue_id: the id of the H/W queue this job is submitted to.
+ * @user_cb_size: the actual size of the CB we got from the user.
+ * @patched_cb_size: the size of the CB after parsing.
+ * @ext_queue: whether the job is for external queue or internal queue.
+ * @job_id: the id of the related job inside the related CS.
+ * @use_virt_addr: whether to treat the addresses in the CB as virtual during
+ * parsing.
+ */
+struct hl_cs_parser {
+ struct hl_cb *user_cb;
+ struct hl_cb *patched_cb;
+ struct list_head *job_userptr_list;
+ u64 cs_sequence;
+ u32 ctx_id;
+ u32 hw_queue_id;
+ u32 user_cb_size;
+ u32 patched_cb_size;
+ u8 ext_queue;
+ u8 job_id;
+ u8 use_virt_addr;
+};
+
+
+/*
+ * MEMORY STRUCTURE
+ */
+
+/**
+ * struct hl_vm_hash_node - hash element from virtual address to virtual
+ * memory area descriptor (hl_vm_phys_pg_list or
+ * hl_userptr).
+ * @node: node to hang on the hash table in context object.
+ * @vaddr: key virtual address.
+ * @ptr: value pointer (hl_vm_phys_pg_list or hl_userptr).
+ */
+struct hl_vm_hash_node {
+ struct hlist_node node;
+ u64 vaddr;
+ void *ptr;
+};
+
+/**
+ * struct hl_vm_phys_pg_pack - physical page pack.
+ * @vm_type: describes the type of the virtual area descriptor.
+ * @pages: the physical page array.
+ * @mapping_cnt: number of shared mappings.
+ * @asid: the context related to this list.
+ * @npages: num physical pages in the pack.
+ * @page_size: size of each page in the pack.
+ * @total_size: total size of all the pages in this list.
+ * @flags: HL_MEM_* flags related to this list.
+ * @handle: the provided handle related to this list.
+ * @offset: offset from the first page.
+ * @contiguous: is contiguous physical memory.
+ * @created_from_userptr: is product of host virtual address.
+ */
+struct hl_vm_phys_pg_pack {
+ enum vm_type_t vm_type; /* must be first */
+ u64 *pages;
+ atomic_t mapping_cnt;
+ u32 asid;
+ u32 npages;
+ u32 page_size;
+ u32 total_size;
+ u32 flags;
+ u32 handle;
+ u32 offset;
+ u8 contiguous;
+ u8 created_from_userptr;
+};
+
+/**
+ * struct hl_vm_va_block - virtual range block information.
+ * @node: node to hang on the virtual range list in context object.
+ * @start: virtual range start address.
+ * @end: virtual range end address.
+ * @size: virtual range size.
+ */
+struct hl_vm_va_block {
+ struct list_head node;
+ u64 start;
+ u64 end;
+ u64 size;
+};
+
+/**
+ * struct hl_vm - virtual memory manager for MMU.
+ * @dram_pg_pool: pool for DRAM physical pages of 2MB.
+ * @dram_pg_pool_refcount: reference counter for the pool usage.
+ * @idr_lock: protects the phys_pg_list_handles.
+ * @phys_pg_pack_handles: idr to hold all device allocations handles.
+ * @init_done: whether initialization was done. We need this because VM
+ * initialization might be skipped during device initialization.
+ */
+struct hl_vm {
+ struct gen_pool *dram_pg_pool;
+ struct kref dram_pg_pool_refcount;
+ spinlock_t idr_lock;
+ struct idr phys_pg_pack_handles;
+ u8 init_done;
+};
+
+/*
+ * FILE PRIVATE STRUCTURE
+ */
+
+/**
+ * struct hl_fpriv - process information stored in FD private data.
+ * @hdev: habanalabs device structure.
+ * @filp: pointer to the given file structure.
+ * @taskpid: current process ID.
+ * @ctx: current executing context.
+ * @ctx_mgr: context manager to handle multiple context for this FD.
+ * @cb_mgr: command buffer manager to handle multiple buffers for this FD.
+ * @debugfs_list: list of relevant ASIC debugfs.
+ * @refcount: number of related contexts.
+ * @restore_phase_mutex: lock for context switch and restore phase.
+ */
+struct hl_fpriv {
+ struct hl_device *hdev;
+ struct file *filp;
+ struct pid *taskpid;
+ struct hl_ctx *ctx; /* TODO: remove for multiple ctx */
+ struct hl_ctx_mgr ctx_mgr;
+ struct hl_cb_mgr cb_mgr;
+ struct list_head debugfs_list;
+ struct kref refcount;
+ struct mutex restore_phase_mutex;
+};
+
+
+/*
+ * DebugFS
+ */
+
+/**
+ * struct hl_info_list - debugfs file ops.
+ * @name: file name.
+ * @show: function to output information.
+ * @write: function to write to the file.
+ */
+struct hl_info_list {
+ const char *name;
+ int (*show)(struct seq_file *s, void *data);
+ ssize_t (*write)(struct file *file, const char __user *buf,
+ size_t count, loff_t *f_pos);
+};
+
+/**
+ * struct hl_debugfs_entry - debugfs dentry wrapper.
+ * @dent: base debugfs entry structure.
+ * @info_ent: dentry realted ops.
+ * @dev_entry: ASIC specific debugfs manager.
+ */
+struct hl_debugfs_entry {
+ struct dentry *dent;
+ const struct hl_info_list *info_ent;
+ struct hl_dbg_device_entry *dev_entry;
+};
+
+/**
+ * struct hl_dbg_device_entry - ASIC specific debugfs manager.
+ * @root: root dentry.
+ * @hdev: habanalabs device structure.
+ * @entry_arr: array of available hl_debugfs_entry.
+ * @file_list: list of available debugfs files.
+ * @file_mutex: protects file_list.
+ * @cb_list: list of available CBs.
+ * @cb_spinlock: protects cb_list.
+ * @cs_list: list of available CSs.
+ * @cs_spinlock: protects cs_list.
+ * @cs_job_list: list of available CB jobs.
+ * @cs_job_spinlock: protects cs_job_list.
+ * @userptr_list: list of available userptrs (virtual memory chunk descriptor).
+ * @userptr_spinlock: protects userptr_list.
+ * @ctx_mem_hash_list: list of available contexts with MMU mappings.
+ * @ctx_mem_hash_spinlock: protects cb_list.
+ * @addr: next address to read/write from/to in read/write32.
+ * @mmu_addr: next virtual address to translate to physical address in mmu_show.
+ * @mmu_asid: ASID to use while translating in mmu_show.
+ * @i2c_bus: generic u8 debugfs file for bus value to use in i2c_data_read.
+ * @i2c_bus: generic u8 debugfs file for address value to use in i2c_data_read.
+ * @i2c_bus: generic u8 debugfs file for register value to use in i2c_data_read.
+ */
+struct hl_dbg_device_entry {
+ struct dentry *root;
+ struct hl_device *hdev;
+ struct hl_debugfs_entry *entry_arr;
+ struct list_head file_list;
+ struct mutex file_mutex;
+ struct list_head cb_list;
+ spinlock_t cb_spinlock;
+ struct list_head cs_list;
+ spinlock_t cs_spinlock;
+ struct list_head cs_job_list;
+ spinlock_t cs_job_spinlock;
+ struct list_head userptr_list;
+ spinlock_t userptr_spinlock;
+ struct list_head ctx_mem_hash_list;
+ spinlock_t ctx_mem_hash_spinlock;
+ u64 addr;
+ u64 mmu_addr;
+ u32 mmu_asid;
+ u8 i2c_bus;
+ u8 i2c_addr;
+ u8 i2c_reg;
+};
+
+
+/*
+ * DEVICES
+ */
+
+/* Theoretical limit only. A single host can only contain up to 4 or 8 PCIe
+ * x16 cards. In extereme cases, there are hosts that can accommodate 16 cards
+ */
+#define HL_MAX_MINORS 256
+
+/*
+ * Registers read & write functions.
+ */
+
+u32 hl_rreg(struct hl_device *hdev, u32 reg);
+void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
+
+#define hl_poll_timeout(hdev, addr, val, cond, sleep_us, timeout_us) \
+ readl_poll_timeout(hdev->rmmio + addr, val, cond, sleep_us, timeout_us)
+
+#define RREG32(reg) hl_rreg(hdev, (reg))
+#define WREG32(reg, v) hl_wreg(hdev, (reg), (v))
+#define DREG32(reg) pr_info("REGISTER: " #reg " : 0x%08X\n", \
+ hl_rreg(hdev, (reg)))
+
+#define WREG32_P(reg, val, mask) \
+ do { \
+ u32 tmp_ = RREG32(reg); \
+ tmp_ &= (mask); \
+ tmp_ |= ((val) & ~(mask)); \
+ WREG32(reg, tmp_); \
+ } while (0)
+#define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
+#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
+
+#define REG_FIELD_SHIFT(reg, field) reg##_##field##_SHIFT
+#define REG_FIELD_MASK(reg, field) reg##_##field##_MASK
+#define WREG32_FIELD(reg, field, val) \
+ WREG32(mm##reg, (RREG32(mm##reg) & ~REG_FIELD_MASK(reg, field)) | \
+ (val) << REG_FIELD_SHIFT(reg, field))
+
+struct hwmon_chip_info;
+
+/**
+ * struct hl_device_reset_work - reset workqueue task wrapper.
+ * @reset_work: reset work to be done.
+ * @hdev: habanalabs device structure.
+ */
+struct hl_device_reset_work {
+ struct work_struct reset_work;
+ struct hl_device *hdev;
+};
+
+/**
+ * struct hl_device - habanalabs device structure.
+ * @pdev: pointer to PCI device, can be NULL in case of simulator device.
+ * @pcie_bar: array of available PCIe bars.
+ * @rmmio: configuration area address on SRAM.
+ * @cdev: related char device.
+ * @dev: realted kernel basic device structure.
+ * @work_freq: delayed work to lower device frequency if possible.
+ * @work_heartbeat: delayed work for ArmCP is-alive check.
+ * @asic_name: ASIC specific nmae.
+ * @asic_type: ASIC specific type.
+ * @completion_queue: array of hl_cq.
+ * @cq_wq: work queue of completion queues for executing work in process context
+ * @eq_wq: work queue of event queue for executing work in process context.
+ * @kernel_ctx: KMD context structure.
+ * @kernel_queues: array of hl_hw_queue.
+ * @hw_queues_mirror_list: CS mirror list for TDR.
+ * @hw_queues_mirror_lock: protects hw_queues_mirror_list.
+ * @kernel_cb_mgr: command buffer manager for creating/destroying/handling CGs.
+ * @event_queue: event queue for IRQ from ArmCP.
+ * @dma_pool: DMA pool for small allocations.
+ * @cpu_accessible_dma_mem: KMD <-> ArmCP shared memory CPU address.
+ * @cpu_accessible_dma_address: KMD <-> ArmCP shared memory DMA address.
+ * @cpu_accessible_dma_pool: KMD <-> ArmCP shared memory pool.
+ * @asid_bitmap: holds used/available ASIDs.
+ * @asid_mutex: protects asid_bitmap.
+ * @fd_open_cnt_lock: lock for updating fd_open_cnt in hl_device_open. Although
+ * fd_open_cnt is atomic, we need this lock to serialize
+ * the open function because the driver currently supports
+ * only a single process at a time. In addition, we need a
+ * lock here so we can flush user processes which are opening
+ * the device while we are trying to hard reset it
+ * @send_cpu_message_lock: enforces only one message in KMD <-> ArmCP queue.
+ * @asic_prop: ASIC specific immutable properties.
+ * @asic_funcs: ASIC specific functions.
+ * @asic_specific: ASIC specific information to use only from ASIC files.
+ * @mmu_pgt_pool: pool of available MMU hops.
+ * @vm: virtual memory manager for MMU.
+ * @mmu_cache_lock: protects MMU cache invalidation as it can serve one context
+ * @hwmon_dev: H/W monitor device.
+ * @pm_mng_profile: current power management profile.
+ * @hl_chip_info: ASIC's sensors information.
+ * @hl_debugfs: device's debugfs manager.
+ * @cb_pool: list of preallocated CBs.
+ * @cb_pool_lock: protects the CB pool.
+ * @user_ctx: current user context executing.
+ * @dram_used_mem: current DRAM memory consumption.
+ * @in_reset: is device in reset flow.
+ * @curr_pll_profile: current PLL profile.
+ * @fd_open_cnt: number of open user processes.
+ * @timeout_jiffies: device CS timeout value.
+ * @max_power: the max power of the device, as configured by the sysadmin. This
+ * value is saved so in case of hard-reset, KMD will restore this
+ * value and update the F/W after the re-initialization
+ * @major: habanalabs KMD major.
+ * @high_pll: high PLL profile frequency.
+ * @soft_reset_cnt: number of soft reset since KMD loading.
+ * @hard_reset_cnt: number of hard reset since KMD loading.
+ * @id: device minor.
+ * @disabled: is device disabled.
+ * @late_init_done: is late init stage was done during initialization.
+ * @hwmon_initialized: is H/W monitor sensors was initialized.
+ * @hard_reset_pending: is there a hard reset work pending.
+ * @heartbeat: is heartbeat sanity check towards ArmCP enabled.
+ * @reset_on_lockup: true if a reset should be done in case of stuck CS, false
+ * otherwise.
+ * @dram_supports_virtual_memory: is MMU enabled towards DRAM.
+ * @dram_default_page_mapping: is DRAM default page mapping enabled.
+ * @init_done: is the initialization of the device done.
+ * @mmu_enable: is MMU enabled.
+ * @device_cpu_disabled: is the device CPU disabled (due to timeouts)
+ */
+struct hl_device {
+ struct pci_dev *pdev;
+ void __iomem *pcie_bar[6];
+ void __iomem *rmmio;
+ struct cdev cdev;
+ struct device *dev;
+ struct delayed_work work_freq;
+ struct delayed_work work_heartbeat;
+ char asic_name[16];
+ enum hl_asic_type asic_type;
+ struct hl_cq *completion_queue;
+ struct workqueue_struct *cq_wq;
+ struct workqueue_struct *eq_wq;
+ struct hl_ctx *kernel_ctx;
+ struct hl_hw_queue *kernel_queues;
+ struct list_head hw_queues_mirror_list;
+ spinlock_t hw_queues_mirror_lock;
+ struct hl_cb_mgr kernel_cb_mgr;
+ struct hl_eq event_queue;
+ struct dma_pool *dma_pool;
+ void *cpu_accessible_dma_mem;
+ dma_addr_t cpu_accessible_dma_address;
+ struct gen_pool *cpu_accessible_dma_pool;
+ unsigned long *asid_bitmap;
+ struct mutex asid_mutex;
+ /* TODO: remove fd_open_cnt_lock for multiple process support */
+ struct mutex fd_open_cnt_lock;
+ struct mutex send_cpu_message_lock;
+ struct asic_fixed_properties asic_prop;
+ const struct hl_asic_funcs *asic_funcs;
+ void *asic_specific;
+ struct gen_pool *mmu_pgt_pool;
+ struct hl_vm vm;
+ struct mutex mmu_cache_lock;
+ struct device *hwmon_dev;
+ enum hl_pm_mng_profile pm_mng_profile;
+ struct hwmon_chip_info *hl_chip_info;
+
+ struct hl_dbg_device_entry hl_debugfs;
+
+ struct list_head cb_pool;
+ spinlock_t cb_pool_lock;
+
+ /* TODO: remove user_ctx for multiple process support */
+ struct hl_ctx *user_ctx;
+
+ atomic64_t dram_used_mem;
+ atomic_t in_reset;
+ atomic_t curr_pll_profile;
+ atomic_t fd_open_cnt;
+ u64 timeout_jiffies;
+ u64 max_power;
+ u32 major;
+ u32 high_pll;
+ u32 soft_reset_cnt;
+ u32 hard_reset_cnt;
+ u16 id;
+ u8 disabled;
+ u8 late_init_done;
+ u8 hwmon_initialized;
+ u8 hard_reset_pending;
+ u8 heartbeat;
+ u8 reset_on_lockup;
+ u8 dram_supports_virtual_memory;
+ u8 dram_default_page_mapping;
+ u8 init_done;
+ u8 device_cpu_disabled;
+
+ /* Parameters for bring-up */
+ u8 mmu_enable;
+ u8 cpu_enable;
+ u8 reset_pcilink;
+ u8 cpu_queues_enable;
+ u8 fw_loading;
+ u8 pldm;
+};
+
+
+/*
+ * IOCTLs
+ */
+
+/**
+ * typedef hl_ioctl_t - typedef for ioctl function in the driver
+ * @hpriv: pointer to the FD's private data, which contains state of
+ * user process
+ * @data: pointer to the input/output arguments structure of the IOCTL
+ *
+ * Return: 0 for success, negative value for error
+ */
+typedef int hl_ioctl_t(struct hl_fpriv *hpriv, void *data);
+
+/**
+ * struct hl_ioctl_desc - describes an IOCTL entry of the driver.
+ * @cmd: the IOCTL code as created by the kernel macros.
+ * @func: pointer to the driver's function that should be called for this IOCTL.
+ */
+struct hl_ioctl_desc {
+ unsigned int cmd;
+ hl_ioctl_t *func;
+};
+
+
+/*
+ * Kernel module functions that can be accessed by entire module
+ */
+
+/**
+ * hl_mem_area_inside_range() - Checks whether address+size are inside a range.
+ * @address: The start address of the area we want to validate.
+ * @size: The size in bytes of the area we want to validate.
+ * @range_start_address: The start address of the valid range.
+ * @range_end_address: The end address of the valid range.
+ *
+ * Return: true if the area is inside the valid range, false otherwise.
+ */
+static inline bool hl_mem_area_inside_range(u64 address, u32 size,
+ u64 range_start_address, u64 range_end_address)
+{
+ u64 end_address = address + size;
+
+ if ((address >= range_start_address) &&
+ (end_address <= range_end_address) &&
+ (end_address > address))
+ return true;
+
+ return false;
+}
+
+/**
+ * hl_mem_area_crosses_range() - Checks whether address+size crossing a range.
+ * @address: The start address of the area we want to validate.
+ * @size: The size in bytes of the area we want to validate.
+ * @range_start_address: The start address of the valid range.
+ * @range_end_address: The end address of the valid range.
+ *
+ * Return: true if the area overlaps part or all of the valid range,
+ * false otherwise.
+ */
+static inline bool hl_mem_area_crosses_range(u64 address, u32 size,
+ u64 range_start_address, u64 range_end_address)
+{
+ u64 end_address = address + size;
+
+ if ((address >= range_start_address) &&
+ (address < range_end_address))
+ return true;
+
+ if ((end_address >= range_start_address) &&
+ (end_address < range_end_address))
+ return true;
+
+ if ((address < range_start_address) &&
+ (end_address >= range_end_address))
+ return true;
+
+ return false;
+}
+
+int hl_device_open(struct inode *inode, struct file *filp);
+bool hl_device_disabled_or_in_reset(struct hl_device *hdev);
+int create_hdev(struct hl_device **dev, struct pci_dev *pdev,
+ enum hl_asic_type asic_type, int minor);
+void destroy_hdev(struct hl_device *hdev);
+int hl_poll_timeout_memory(struct hl_device *hdev, u64 addr, u32 timeout_us,
+ u32 *val);
+int hl_poll_timeout_device_memory(struct hl_device *hdev, void __iomem *addr,
+ u32 timeout_us, u32 *val);
+int hl_hw_queues_create(struct hl_device *hdev);
+void hl_hw_queues_destroy(struct hl_device *hdev);
+int hl_hw_queue_send_cb_no_cmpl(struct hl_device *hdev, u32 hw_queue_id,
+ u32 cb_size, u64 cb_ptr);
+int hl_hw_queue_schedule_cs(struct hl_cs *cs);
+u32 hl_hw_queue_add_ptr(u32 ptr, u16 val);
+void hl_hw_queue_inc_ci_kernel(struct hl_device *hdev, u32 hw_queue_id);
+void hl_int_hw_queue_update_ci(struct hl_cs *cs);
+void hl_hw_queue_reset(struct hl_device *hdev, bool hard_reset);
+
+#define hl_queue_inc_ptr(p) hl_hw_queue_add_ptr(p, 1)
+#define hl_pi_2_offset(pi) ((pi) & (HL_QUEUE_LENGTH - 1))
+
+int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id);
+void hl_cq_fini(struct hl_device *hdev, struct hl_cq *q);
+int hl_eq_init(struct hl_device *hdev, struct hl_eq *q);
+void hl_eq_fini(struct hl_device *hdev, struct hl_eq *q);
+void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q);
+void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q);
+irqreturn_t hl_irq_handler_cq(int irq, void *arg);
+irqreturn_t hl_irq_handler_eq(int irq, void *arg);
+u32 hl_cq_inc_ptr(u32 ptr);
+
+int hl_asid_init(struct hl_device *hdev);
+void hl_asid_fini(struct hl_device *hdev);
+unsigned long hl_asid_alloc(struct hl_device *hdev);
+void hl_asid_free(struct hl_device *hdev, unsigned long asid);
+
+int hl_ctx_create(struct hl_device *hdev, struct hl_fpriv *hpriv);
+void hl_ctx_free(struct hl_device *hdev, struct hl_ctx *ctx);
+int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx);
+void hl_ctx_do_release(struct kref *ref);
+void hl_ctx_get(struct hl_device *hdev, struct hl_ctx *ctx);
+int hl_ctx_put(struct hl_ctx *ctx);
+struct dma_fence *hl_ctx_get_fence(struct hl_ctx *ctx, u64 seq);
+void hl_ctx_mgr_init(struct hl_ctx_mgr *mgr);
+void hl_ctx_mgr_fini(struct hl_device *hdev, struct hl_ctx_mgr *mgr);
+
+int hl_device_init(struct hl_device *hdev, struct class *hclass);
+void hl_device_fini(struct hl_device *hdev);
+int hl_device_suspend(struct hl_device *hdev);
+int hl_device_resume(struct hl_device *hdev);
+int hl_device_reset(struct hl_device *hdev, bool hard_reset,
+ bool from_hard_reset_thread);
+void hl_hpriv_get(struct hl_fpriv *hpriv);
+void hl_hpriv_put(struct hl_fpriv *hpriv);
+int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq);
+
+int hl_build_hwmon_channel_info(struct hl_device *hdev,
+ struct armcp_sensor *sensors_arr);
+
+int hl_sysfs_init(struct hl_device *hdev);
+void hl_sysfs_fini(struct hl_device *hdev);
+
+int hl_hwmon_init(struct hl_device *hdev);
+void hl_hwmon_fini(struct hl_device *hdev);
+
+int hl_cb_create(struct hl_device *hdev, struct hl_cb_mgr *mgr, u32 cb_size,
+ u64 *handle, int ctx_id);
+int hl_cb_destroy(struct hl_device *hdev, struct hl_cb_mgr *mgr, u64 cb_handle);
+int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma);
+struct hl_cb *hl_cb_get(struct hl_device *hdev, struct hl_cb_mgr *mgr,
+ u32 handle);
+void hl_cb_put(struct hl_cb *cb);
+void hl_cb_mgr_init(struct hl_cb_mgr *mgr);
+void hl_cb_mgr_fini(struct hl_device *hdev, struct hl_cb_mgr *mgr);
+struct hl_cb *hl_cb_kernel_create(struct hl_device *hdev, u32 cb_size);
+int hl_cb_pool_init(struct hl_device *hdev);
+int hl_cb_pool_fini(struct hl_device *hdev);
+
+void hl_cs_rollback_all(struct hl_device *hdev);
+struct hl_cs_job *hl_cs_allocate_job(struct hl_device *hdev, bool ext_queue);
+
+void goya_set_asic_funcs(struct hl_device *hdev);
+
+int hl_vm_ctx_init(struct hl_ctx *ctx);
+void hl_vm_ctx_fini(struct hl_ctx *ctx);
+
+int hl_vm_init(struct hl_device *hdev);
+void hl_vm_fini(struct hl_device *hdev);
+
+int hl_pin_host_memory(struct hl_device *hdev, u64 addr, u64 size,
+ struct hl_userptr *userptr);
+int hl_unpin_host_memory(struct hl_device *hdev, struct hl_userptr *userptr);
+void hl_userptr_delete_list(struct hl_device *hdev,
+ struct list_head *userptr_list);
+bool hl_userptr_is_pinned(struct hl_device *hdev, u64 addr, u32 size,
+ struct list_head *userptr_list,
+ struct hl_userptr **userptr);
+
+int hl_mmu_init(struct hl_device *hdev);
+void hl_mmu_fini(struct hl_device *hdev);
+int hl_mmu_ctx_init(struct hl_ctx *ctx);
+void hl_mmu_ctx_fini(struct hl_ctx *ctx);
+int hl_mmu_map(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr, u32 page_size);
+int hl_mmu_unmap(struct hl_ctx *ctx, u64 virt_addr, u32 page_size);
+void hl_mmu_swap_out(struct hl_ctx *ctx);
+void hl_mmu_swap_in(struct hl_ctx *ctx);
+
+long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr);
+void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq);
+long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr);
+long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr);
+long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr);
+long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr);
+long hl_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr);
+void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
+ long value);
+u64 hl_get_max_power(struct hl_device *hdev);
+void hl_set_max_power(struct hl_device *hdev, u64 value);
+
+#ifdef CONFIG_DEBUG_FS
+
+void hl_debugfs_init(void);
+void hl_debugfs_fini(void);
+void hl_debugfs_add_device(struct hl_device *hdev);
+void hl_debugfs_remove_device(struct hl_device *hdev);
+void hl_debugfs_add_file(struct hl_fpriv *hpriv);
+void hl_debugfs_remove_file(struct hl_fpriv *hpriv);
+void hl_debugfs_add_cb(struct hl_cb *cb);
+void hl_debugfs_remove_cb(struct hl_cb *cb);
+void hl_debugfs_add_cs(struct hl_cs *cs);
+void hl_debugfs_remove_cs(struct hl_cs *cs);
+void hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job);
+void hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job);
+void hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr);
+void hl_debugfs_remove_userptr(struct hl_device *hdev,
+ struct hl_userptr *userptr);
+void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx);
+void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx);
+
+#else
+
+static inline void __init hl_debugfs_init(void)
+{
+}
+
+static inline void hl_debugfs_fini(void)
+{
+}
+
+static inline void hl_debugfs_add_device(struct hl_device *hdev)
+{
+}
+
+static inline void hl_debugfs_remove_device(struct hl_device *hdev)
+{
+}
+
+static inline void hl_debugfs_add_file(struct hl_fpriv *hpriv)
+{
+}
+
+static inline void hl_debugfs_remove_file(struct hl_fpriv *hpriv)
+{
+}
+
+static inline void hl_debugfs_add_cb(struct hl_cb *cb)
+{
+}
+
+static inline void hl_debugfs_remove_cb(struct hl_cb *cb)
+{
+}
+
+static inline void hl_debugfs_add_cs(struct hl_cs *cs)
+{
+}
+
+static inline void hl_debugfs_remove_cs(struct hl_cs *cs)
+{
+}
+
+static inline void hl_debugfs_add_job(struct hl_device *hdev,
+ struct hl_cs_job *job)
+{
+}
+
+static inline void hl_debugfs_remove_job(struct hl_device *hdev,
+ struct hl_cs_job *job)
+{
+}
+
+static inline void hl_debugfs_add_userptr(struct hl_device *hdev,
+ struct hl_userptr *userptr)
+{
+}
+
+static inline void hl_debugfs_remove_userptr(struct hl_device *hdev,
+ struct hl_userptr *userptr)
+{
+}
+
+static inline void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev,
+ struct hl_ctx *ctx)
+{
+}
+
+static inline void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev,
+ struct hl_ctx *ctx)
+{
+}
+
+#endif
+
+/* IOCTLs */
+long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+int hl_cb_ioctl(struct hl_fpriv *hpriv, void *data);
+int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data);
+int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data);
+int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data);
+
+#endif /* HABANALABSP_H_ */
diff --git a/drivers/misc/habanalabs/habanalabs_drv.c b/drivers/misc/habanalabs/habanalabs_drv.c
new file mode 100644
index 000000000000..748601463f11
--- /dev/null
+++ b/drivers/misc/habanalabs/habanalabs_drv.c
@@ -0,0 +1,461 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#include "habanalabs.h"
+
+#include <linux/pci.h>
+#include <linux/module.h>
+
+#define HL_DRIVER_AUTHOR "HabanaLabs Kernel Driver Team"
+
+#define HL_DRIVER_DESC "Driver for HabanaLabs's AI Accelerators"
+
+MODULE_AUTHOR(HL_DRIVER_AUTHOR);
+MODULE_DESCRIPTION(HL_DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+
+static int hl_major;
+static struct class *hl_class;
+static DEFINE_IDR(hl_devs_idr);
+static DEFINE_MUTEX(hl_devs_idr_lock);
+
+static int timeout_locked = 5;
+static int reset_on_lockup = 1;
+
+module_param(timeout_locked, int, 0444);
+MODULE_PARM_DESC(timeout_locked,
+ "Device lockup timeout in seconds (0 = disabled, default 5s)");
+
+module_param(reset_on_lockup, int, 0444);
+MODULE_PARM_DESC(reset_on_lockup,
+ "Do device reset on lockup (0 = no, 1 = yes, default yes)");
+
+#define PCI_VENDOR_ID_HABANALABS 0x1da3
+
+#define PCI_IDS_GOYA 0x0001
+
+static const struct pci_device_id ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_HABANALABS, PCI_IDS_GOYA), },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ids);
+
+/*
+ * get_asic_type - translate device id to asic type
+ *
+ * @device: id of the PCI device
+ *
+ * Translate device id to asic type.
+ * In case of unidentified device, return -1
+ */
+static enum hl_asic_type get_asic_type(u16 device)
+{
+ enum hl_asic_type asic_type;
+
+ switch (device) {
+ case PCI_IDS_GOYA:
+ asic_type = ASIC_GOYA;
+ break;
+ default:
+ asic_type = ASIC_INVALID;
+ break;
+ }
+
+ return asic_type;
+}
+
+/*
+ * hl_device_open - open function for habanalabs device
+ *
+ * @inode: pointer to inode structure
+ * @filp: pointer to file structure
+ *
+ * Called when process opens an habanalabs device.
+ */
+int hl_device_open(struct inode *inode, struct file *filp)
+{
+ struct hl_device *hdev;
+ struct hl_fpriv *hpriv;
+ int rc;
+
+ mutex_lock(&hl_devs_idr_lock);
+ hdev = idr_find(&hl_devs_idr, iminor(inode));
+ mutex_unlock(&hl_devs_idr_lock);
+
+ if (!hdev) {
+ pr_err("Couldn't find device %d:%d\n",
+ imajor(inode), iminor(inode));
+ return -ENXIO;
+ }
+
+ mutex_lock(&hdev->fd_open_cnt_lock);
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ dev_err_ratelimited(hdev->dev,
+ "Can't open %s because it is disabled or in reset\n",
+ dev_name(hdev->dev));
+ mutex_unlock(&hdev->fd_open_cnt_lock);
+ return -EPERM;
+ }
+
+ if (atomic_read(&hdev->fd_open_cnt)) {
+ dev_info_ratelimited(hdev->dev,
+ "Device %s is already attached to application\n",
+ dev_name(hdev->dev));
+ mutex_unlock(&hdev->fd_open_cnt_lock);
+ return -EBUSY;
+ }
+
+ atomic_inc(&hdev->fd_open_cnt);
+
+ mutex_unlock(&hdev->fd_open_cnt_lock);
+
+ hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv) {
+ rc = -ENOMEM;
+ goto close_device;
+ }
+
+ hpriv->hdev = hdev;
+ filp->private_data = hpriv;
+ hpriv->filp = filp;
+ mutex_init(&hpriv->restore_phase_mutex);
+ kref_init(&hpriv->refcount);
+ nonseekable_open(inode, filp);
+
+ hl_cb_mgr_init(&hpriv->cb_mgr);
+ hl_ctx_mgr_init(&hpriv->ctx_mgr);
+
+ rc = hl_ctx_create(hdev, hpriv);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to open FD (CTX fail)\n");
+ goto out_err;
+ }
+
+ hpriv->taskpid = find_get_pid(current->pid);
+
+ /*
+ * Device is IDLE at this point so it is legal to change PLLs. There
+ * is no need to check anything because if the PLL is already HIGH, the
+ * set function will return without doing anything
+ */
+ hl_device_set_frequency(hdev, PLL_HIGH);
+
+ hl_debugfs_add_file(hpriv);
+
+ return 0;
+
+out_err:
+ filp->private_data = NULL;
+ hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
+ hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
+ mutex_destroy(&hpriv->restore_phase_mutex);
+ kfree(hpriv);
+
+close_device:
+ atomic_dec(&hdev->fd_open_cnt);
+ return rc;
+}
+
+/*
+ * create_hdev - create habanalabs device instance
+ *
+ * @dev: will hold the pointer to the new habanalabs device structure
+ * @pdev: pointer to the pci device
+ * @asic_type: in case of simulator device, which device is it
+ * @minor: in case of simulator device, the minor of the device
+ *
+ * Allocate memory for habanalabs device and initialize basic fields
+ * Identify the ASIC type
+ * Allocate ID (minor) for the device (only for real devices)
+ */
+int create_hdev(struct hl_device **dev, struct pci_dev *pdev,
+ enum hl_asic_type asic_type, int minor)
+{
+ struct hl_device *hdev;
+ int rc;
+
+ *dev = NULL;
+
+ hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
+ if (!hdev)
+ return -ENOMEM;
+
+ hdev->major = hl_major;
+ hdev->reset_on_lockup = reset_on_lockup;
+
+ /* Parameters for bring-up - set them to defaults */
+ hdev->mmu_enable = 1;
+ hdev->cpu_enable = 1;
+ hdev->reset_pcilink = 0;
+ hdev->cpu_queues_enable = 1;
+ hdev->fw_loading = 1;
+ hdev->pldm = 0;
+ hdev->heartbeat = 1;
+
+ /* If CPU is disabled, no point in loading FW */
+ if (!hdev->cpu_enable)
+ hdev->fw_loading = 0;
+
+ /* If we don't load FW, no need to initialize CPU queues */
+ if (!hdev->fw_loading)
+ hdev->cpu_queues_enable = 0;
+
+ /* If CPU queues not enabled, no way to do heartbeat */
+ if (!hdev->cpu_queues_enable)
+ hdev->heartbeat = 0;
+
+ if (timeout_locked)
+ hdev->timeout_jiffies = msecs_to_jiffies(timeout_locked * 1000);
+ else
+ hdev->timeout_jiffies = MAX_SCHEDULE_TIMEOUT;
+
+ hdev->disabled = true;
+ hdev->pdev = pdev; /* can be NULL in case of simulator device */
+
+ if (asic_type == ASIC_AUTO_DETECT) {
+ hdev->asic_type = get_asic_type(pdev->device);
+ if (hdev->asic_type == ASIC_INVALID) {
+ dev_err(&pdev->dev, "Unsupported ASIC\n");
+ rc = -ENODEV;
+ goto free_hdev;
+ }
+ } else {
+ hdev->asic_type = asic_type;
+ }
+
+ mutex_lock(&hl_devs_idr_lock);
+
+ if (minor == -1) {
+ rc = idr_alloc(&hl_devs_idr, hdev, 0, HL_MAX_MINORS,
+ GFP_KERNEL);
+ } else {
+ void *old_idr = idr_replace(&hl_devs_idr, hdev, minor);
+
+ if (IS_ERR_VALUE(old_idr)) {
+ rc = PTR_ERR(old_idr);
+ pr_err("Error %d when trying to replace minor %d\n",
+ rc, minor);
+ mutex_unlock(&hl_devs_idr_lock);
+ goto free_hdev;
+ }
+ rc = minor;
+ }
+
+ mutex_unlock(&hl_devs_idr_lock);
+
+ if (rc < 0) {
+ if (rc == -ENOSPC) {
+ pr_err("too many devices in the system\n");
+ rc = -EBUSY;
+ }
+ goto free_hdev;
+ }
+
+ hdev->id = rc;
+
+ *dev = hdev;
+
+ return 0;
+
+free_hdev:
+ kfree(hdev);
+ return rc;
+}
+
+/*
+ * destroy_hdev - destroy habanalabs device instance
+ *
+ * @dev: pointer to the habanalabs device structure
+ *
+ */
+void destroy_hdev(struct hl_device *hdev)
+{
+ /* Remove device from the device list */
+ mutex_lock(&hl_devs_idr_lock);
+ idr_remove(&hl_devs_idr, hdev->id);
+ mutex_unlock(&hl_devs_idr_lock);
+
+ kfree(hdev);
+}
+
+static int hl_pmops_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct hl_device *hdev = pci_get_drvdata(pdev);
+
+ pr_debug("Going to suspend PCI device\n");
+
+ if (!hdev) {
+ pr_err("device pointer is NULL in suspend\n");
+ return 0;
+ }
+
+ return hl_device_suspend(hdev);
+}
+
+static int hl_pmops_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct hl_device *hdev = pci_get_drvdata(pdev);
+
+ pr_debug("Going to resume PCI device\n");
+
+ if (!hdev) {
+ pr_err("device pointer is NULL in resume\n");
+ return 0;
+ }
+
+ return hl_device_resume(hdev);
+}
+
+/*
+ * hl_pci_probe - probe PCI habanalabs devices
+ *
+ * @pdev: pointer to pci device
+ * @id: pointer to pci device id structure
+ *
+ * Standard PCI probe function for habanalabs device.
+ * Create a new habanalabs device and initialize it according to the
+ * device's type
+ */
+static int hl_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct hl_device *hdev;
+ int rc;
+
+ dev_info(&pdev->dev, HL_NAME
+ " device found [%04x:%04x] (rev %x)\n",
+ (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
+
+ rc = create_hdev(&hdev, pdev, ASIC_AUTO_DETECT, -1);
+ if (rc)
+ return rc;
+
+ pci_set_drvdata(pdev, hdev);
+
+ rc = hl_device_init(hdev, hl_class);
+ if (rc) {
+ dev_err(&pdev->dev, "Fatal error during habanalabs device init\n");
+ rc = -ENODEV;
+ goto disable_device;
+ }
+
+ return 0;
+
+disable_device:
+ pci_set_drvdata(pdev, NULL);
+ destroy_hdev(hdev);
+
+ return rc;
+}
+
+/*
+ * hl_pci_remove - remove PCI habanalabs devices
+ *
+ * @pdev: pointer to pci device
+ *
+ * Standard PCI remove function for habanalabs device
+ */
+static void hl_pci_remove(struct pci_dev *pdev)
+{
+ struct hl_device *hdev;
+
+ hdev = pci_get_drvdata(pdev);
+ if (!hdev)
+ return;
+
+ hl_device_fini(hdev);
+ pci_set_drvdata(pdev, NULL);
+
+ destroy_hdev(hdev);
+}
+
+static const struct dev_pm_ops hl_pm_ops = {
+ .suspend = hl_pmops_suspend,
+ .resume = hl_pmops_resume,
+};
+
+static struct pci_driver hl_pci_driver = {
+ .name = HL_NAME,
+ .id_table = ids,
+ .probe = hl_pci_probe,
+ .remove = hl_pci_remove,
+ .driver.pm = &hl_pm_ops,
+};
+
+/*
+ * hl_init - Initialize the habanalabs kernel driver
+ */
+static int __init hl_init(void)
+{
+ int rc;
+ dev_t dev;
+
+ pr_info("loading driver\n");
+
+ rc = alloc_chrdev_region(&dev, 0, HL_MAX_MINORS, HL_NAME);
+ if (rc < 0) {
+ pr_err("unable to get major\n");
+ return rc;
+ }
+
+ hl_major = MAJOR(dev);
+
+ hl_class = class_create(THIS_MODULE, HL_NAME);
+ if (IS_ERR(hl_class)) {
+ pr_err("failed to allocate class\n");
+ rc = PTR_ERR(hl_class);
+ goto remove_major;
+ }
+
+ hl_debugfs_init();
+
+ rc = pci_register_driver(&hl_pci_driver);
+ if (rc) {
+ pr_err("failed to register pci device\n");
+ goto remove_debugfs;
+ }
+
+ pr_debug("driver loaded\n");
+
+ return 0;
+
+remove_debugfs:
+ hl_debugfs_fini();
+ class_destroy(hl_class);
+remove_major:
+ unregister_chrdev_region(MKDEV(hl_major, 0), HL_MAX_MINORS);
+ return rc;
+}
+
+/*
+ * hl_exit - Release all resources of the habanalabs kernel driver
+ */
+static void __exit hl_exit(void)
+{
+ pci_unregister_driver(&hl_pci_driver);
+
+ /*
+ * Removing debugfs must be after all devices or simulator devices
+ * have been removed because otherwise we get a bug in the
+ * debugfs module for referencing NULL objects
+ */
+ hl_debugfs_fini();
+
+ class_destroy(hl_class);
+ unregister_chrdev_region(MKDEV(hl_major, 0), HL_MAX_MINORS);
+
+ idr_destroy(&hl_devs_idr);
+
+ pr_debug("driver removed\n");
+}
+
+module_init(hl_init);
+module_exit(hl_exit);
diff --git a/drivers/misc/habanalabs/habanalabs_ioctl.c b/drivers/misc/habanalabs/habanalabs_ioctl.c
new file mode 100644
index 000000000000..2c2739a3c5ec
--- /dev/null
+++ b/drivers/misc/habanalabs/habanalabs_ioctl.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include <uapi/misc/habanalabs.h>
+#include "habanalabs.h"
+
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args)
+{
+ struct hl_info_hw_ip_info hw_ip = {0};
+ u32 size = args->return_size;
+ void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 sram_kmd_size, dram_kmd_size;
+
+ if ((!size) || (!out))
+ return -EINVAL;
+
+ sram_kmd_size = (prop->sram_user_base_address -
+ prop->sram_base_address);
+ dram_kmd_size = (prop->dram_user_base_address -
+ prop->dram_base_address);
+
+ hw_ip.device_id = hdev->asic_funcs->get_pci_id(hdev);
+ hw_ip.sram_base_address = prop->sram_user_base_address;
+ hw_ip.dram_base_address = prop->dram_user_base_address;
+ hw_ip.tpc_enabled_mask = prop->tpc_enabled_mask;
+ hw_ip.sram_size = prop->sram_size - sram_kmd_size;
+ hw_ip.dram_size = prop->dram_size - dram_kmd_size;
+ if (hw_ip.dram_size > 0)
+ hw_ip.dram_enabled = 1;
+ hw_ip.num_of_events = prop->num_of_events;
+ memcpy(hw_ip.armcp_version,
+ prop->armcp_info.armcp_version, VERSION_MAX_LEN);
+ hw_ip.armcp_cpld_version = __le32_to_cpu(prop->armcp_info.cpld_version);
+ hw_ip.psoc_pci_pll_nr = prop->psoc_pci_pll_nr;
+ hw_ip.psoc_pci_pll_nf = prop->psoc_pci_pll_nf;
+ hw_ip.psoc_pci_pll_od = prop->psoc_pci_pll_od;
+ hw_ip.psoc_pci_pll_div_factor = prop->psoc_pci_pll_div_factor;
+
+ return copy_to_user(out, &hw_ip,
+ min((size_t)size, sizeof(hw_ip))) ? -EFAULT : 0;
+}
+
+static int hw_events_info(struct hl_device *hdev, struct hl_info_args *args)
+{
+ u32 size, max_size = args->return_size;
+ void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+ void *arr;
+
+ if ((!max_size) || (!out))
+ return -EINVAL;
+
+ arr = hdev->asic_funcs->get_events_stat(hdev, &size);
+
+ return copy_to_user(out, arr, min(max_size, size)) ? -EFAULT : 0;
+}
+
+static int dram_usage_info(struct hl_device *hdev, struct hl_info_args *args)
+{
+ struct hl_info_dram_usage dram_usage = {0};
+ u32 max_size = args->return_size;
+ void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 dram_kmd_size;
+
+ if ((!max_size) || (!out))
+ return -EINVAL;
+
+ dram_kmd_size = (prop->dram_user_base_address -
+ prop->dram_base_address);
+ dram_usage.dram_free_mem = (prop->dram_size - dram_kmd_size) -
+ atomic64_read(&hdev->dram_used_mem);
+ dram_usage.ctx_dram_mem = atomic64_read(&hdev->user_ctx->dram_phys_mem);
+
+ return copy_to_user(out, &dram_usage,
+ min((size_t) max_size, sizeof(dram_usage))) ? -EFAULT : 0;
+}
+
+static int hw_idle(struct hl_device *hdev, struct hl_info_args *args)
+{
+ struct hl_info_hw_idle hw_idle = {0};
+ u32 max_size = args->return_size;
+ void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+
+ if ((!max_size) || (!out))
+ return -EINVAL;
+
+ hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev);
+
+ return copy_to_user(out, &hw_idle,
+ min((size_t) max_size, sizeof(hw_idle))) ? -EFAULT : 0;
+}
+
+static int hl_info_ioctl(struct hl_fpriv *hpriv, void *data)
+{
+ struct hl_info_args *args = data;
+ struct hl_device *hdev = hpriv->hdev;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ dev_err(hdev->dev,
+ "Device is disabled or in reset. Can't execute INFO IOCTL\n");
+ return -EBUSY;
+ }
+
+ switch (args->op) {
+ case HL_INFO_HW_IP_INFO:
+ rc = hw_ip_info(hdev, args);
+ break;
+
+ case HL_INFO_HW_EVENTS:
+ rc = hw_events_info(hdev, args);
+ break;
+
+ case HL_INFO_DRAM_USAGE:
+ rc = dram_usage_info(hdev, args);
+ break;
+
+ case HL_INFO_HW_IDLE:
+ rc = hw_idle(hdev, args);
+ break;
+
+ default:
+ dev_err(hdev->dev, "Invalid request %d\n", args->op);
+ rc = -ENOTTY;
+ break;
+ }
+
+ return rc;
+}
+
+#define HL_IOCTL_DEF(ioctl, _func) \
+ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func}
+
+static const struct hl_ioctl_desc hl_ioctls[] = {
+ HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl),
+ HL_IOCTL_DEF(HL_IOCTL_CB, hl_cb_ioctl),
+ HL_IOCTL_DEF(HL_IOCTL_CS, hl_cs_ioctl),
+ HL_IOCTL_DEF(HL_IOCTL_WAIT_CS, hl_cs_wait_ioctl),
+ HL_IOCTL_DEF(HL_IOCTL_MEMORY, hl_mem_ioctl)
+};
+
+#define HL_CORE_IOCTL_COUNT ARRAY_SIZE(hl_ioctls)
+
+long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+ struct hl_fpriv *hpriv = filep->private_data;
+ struct hl_device *hdev = hpriv->hdev;
+ hl_ioctl_t *func;
+ const struct hl_ioctl_desc *ioctl = NULL;
+ unsigned int nr = _IOC_NR(cmd);
+ char stack_kdata[128] = {0};
+ char *kdata = NULL;
+ unsigned int usize, asize;
+ int retcode;
+
+ if (hdev->hard_reset_pending) {
+ dev_crit_ratelimited(hdev->dev,
+ "Device HARD reset pending! Please close FD\n");
+ return -ENODEV;
+ }
+
+ if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
+ u32 hl_size;
+
+ ioctl = &hl_ioctls[nr];
+
+ hl_size = _IOC_SIZE(ioctl->cmd);
+ usize = asize = _IOC_SIZE(cmd);
+ if (hl_size > asize)
+ asize = hl_size;
+
+ cmd = ioctl->cmd;
+ } else {
+ dev_err(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n",
+ task_pid_nr(current), nr);
+ return -ENOTTY;
+ }
+
+ /* Do not trust userspace, use our own definition */
+ func = ioctl->func;
+
+ if (unlikely(!func)) {
+ dev_dbg(hdev->dev, "no function\n");
+ retcode = -ENOTTY;
+ goto out_err;
+ }
+
+ if (cmd & (IOC_IN | IOC_OUT)) {
+ if (asize <= sizeof(stack_kdata)) {
+ kdata = stack_kdata;
+ } else {
+ kdata = kzalloc(asize, GFP_KERNEL);
+ if (!kdata) {
+ retcode = -ENOMEM;
+ goto out_err;
+ }
+ }
+ }
+
+ if (cmd & IOC_IN) {
+ if (copy_from_user(kdata, (void __user *)arg, usize)) {
+ retcode = -EFAULT;
+ goto out_err;
+ }
+ } else if (cmd & IOC_OUT) {
+ memset(kdata, 0, usize);
+ }
+
+ retcode = func(hpriv, kdata);
+
+ if (cmd & IOC_OUT)
+ if (copy_to_user((void __user *)arg, kdata, usize))
+ retcode = -EFAULT;
+
+out_err:
+ if (retcode)
+ dev_dbg(hdev->dev,
+ "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
+ task_pid_nr(current), cmd, nr);
+
+ if (kdata != stack_kdata)
+ kfree(kdata);
+
+ return retcode;
+}
diff --git a/drivers/misc/habanalabs/hw_queue.c b/drivers/misc/habanalabs/hw_queue.c
new file mode 100644
index 000000000000..67bece26417c
--- /dev/null
+++ b/drivers/misc/habanalabs/hw_queue.c
@@ -0,0 +1,635 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/slab.h>
+
+/*
+ * hl_queue_add_ptr - add to pi or ci and checks if it wraps around
+ *
+ * @ptr: the current pi/ci value
+ * @val: the amount to add
+ *
+ * Add val to ptr. It can go until twice the queue length.
+ */
+inline u32 hl_hw_queue_add_ptr(u32 ptr, u16 val)
+{
+ ptr += val;
+ ptr &= ((HL_QUEUE_LENGTH << 1) - 1);
+ return ptr;
+}
+
+static inline int queue_free_slots(struct hl_hw_queue *q, u32 queue_len)
+{
+ int delta = (q->pi - q->ci);
+
+ if (delta >= 0)
+ return (queue_len - delta);
+ else
+ return (abs(delta) - queue_len);
+}
+
+void hl_int_hw_queue_update_ci(struct hl_cs *cs)
+{
+ struct hl_device *hdev = cs->ctx->hdev;
+ struct hl_hw_queue *q;
+ int i;
+
+ hdev->asic_funcs->hw_queues_lock(hdev);
+
+ if (hdev->disabled)
+ goto out;
+
+ q = &hdev->kernel_queues[0];
+ for (i = 0 ; i < HL_MAX_QUEUES ; i++, q++) {
+ if (q->queue_type == QUEUE_TYPE_INT) {
+ q->ci += cs->jobs_in_queue_cnt[i];
+ q->ci &= ((q->int_queue_len << 1) - 1);
+ }
+ }
+
+out:
+ hdev->asic_funcs->hw_queues_unlock(hdev);
+}
+
+/*
+ * ext_queue_submit_bd - Submit a buffer descriptor to an external queue
+ *
+ * @hdev: pointer to habanalabs device structure
+ * @q: pointer to habanalabs queue structure
+ * @ctl: BD's control word
+ * @len: BD's length
+ * @ptr: BD's pointer
+ *
+ * This function assumes there is enough space on the queue to submit a new
+ * BD to it. It initializes the next BD and calls the device specific
+ * function to set the pi (and doorbell)
+ *
+ * This function must be called when the scheduler mutex is taken
+ *
+ */
+static void ext_queue_submit_bd(struct hl_device *hdev, struct hl_hw_queue *q,
+ u32 ctl, u32 len, u64 ptr)
+{
+ struct hl_bd *bd;
+
+ bd = (struct hl_bd *) (uintptr_t) q->kernel_address;
+ bd += hl_pi_2_offset(q->pi);
+ bd->ctl = __cpu_to_le32(ctl);
+ bd->len = __cpu_to_le32(len);
+ bd->ptr = __cpu_to_le64(ptr + hdev->asic_prop.host_phys_base_address);
+
+ q->pi = hl_queue_inc_ptr(q->pi);
+ hdev->asic_funcs->ring_doorbell(hdev, q->hw_queue_id, q->pi);
+}
+
+/*
+ * ext_queue_sanity_checks - perform some sanity checks on external queue
+ *
+ * @hdev : pointer to hl_device structure
+ * @q : pointer to hl_hw_queue structure
+ * @num_of_entries : how many entries to check for space
+ * @reserve_cq_entry : whether to reserve an entry in the cq
+ *
+ * H/W queues spinlock should be taken before calling this function
+ *
+ * Perform the following:
+ * - Make sure we have enough space in the h/w queue
+ * - Make sure we have enough space in the completion queue
+ * - Reserve space in the completion queue (needs to be reversed if there
+ * is a failure down the road before the actual submission of work). Only
+ * do this action if reserve_cq_entry is true
+ *
+ */
+static int ext_queue_sanity_checks(struct hl_device *hdev,
+ struct hl_hw_queue *q, int num_of_entries,
+ bool reserve_cq_entry)
+{
+ atomic_t *free_slots =
+ &hdev->completion_queue[q->hw_queue_id].free_slots_cnt;
+ int free_slots_cnt;
+
+ /* Check we have enough space in the queue */
+ free_slots_cnt = queue_free_slots(q, HL_QUEUE_LENGTH);
+
+ if (free_slots_cnt < num_of_entries) {
+ dev_dbg(hdev->dev, "Queue %d doesn't have room for %d CBs\n",
+ q->hw_queue_id, num_of_entries);
+ return -EAGAIN;
+ }
+
+ if (reserve_cq_entry) {
+ /*
+ * Check we have enough space in the completion queue
+ * Add -1 to counter (decrement) unless counter was already 0
+ * In that case, CQ is full so we can't submit a new CB because
+ * we won't get ack on its completion
+ * atomic_add_unless will return 0 if counter was already 0
+ */
+ if (atomic_add_negative(num_of_entries * -1, free_slots)) {
+ dev_dbg(hdev->dev, "No space for %d on CQ %d\n",
+ num_of_entries, q->hw_queue_id);
+ atomic_add(num_of_entries, free_slots);
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * int_queue_sanity_checks - perform some sanity checks on internal queue
+ *
+ * @hdev : pointer to hl_device structure
+ * @q : pointer to hl_hw_queue structure
+ * @num_of_entries : how many entries to check for space
+ *
+ * H/W queues spinlock should be taken before calling this function
+ *
+ * Perform the following:
+ * - Make sure we have enough space in the h/w queue
+ *
+ */
+static int int_queue_sanity_checks(struct hl_device *hdev,
+ struct hl_hw_queue *q,
+ int num_of_entries)
+{
+ int free_slots_cnt;
+
+ /* Check we have enough space in the queue */
+ free_slots_cnt = queue_free_slots(q, q->int_queue_len);
+
+ if (free_slots_cnt < num_of_entries) {
+ dev_dbg(hdev->dev, "Queue %d doesn't have room for %d CBs\n",
+ q->hw_queue_id, num_of_entries);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+/*
+ * hl_hw_queue_send_cb_no_cmpl - send a single CB (not a JOB) without completion
+ *
+ * @hdev: pointer to hl_device structure
+ * @hw_queue_id: Queue's type
+ * @cb_size: size of CB
+ * @cb_ptr: pointer to CB location
+ *
+ * This function sends a single CB, that must NOT generate a completion entry
+ *
+ */
+int hl_hw_queue_send_cb_no_cmpl(struct hl_device *hdev, u32 hw_queue_id,
+ u32 cb_size, u64 cb_ptr)
+{
+ struct hl_hw_queue *q = &hdev->kernel_queues[hw_queue_id];
+ int rc;
+
+ /*
+ * The CPU queue is a synchronous queue with an effective depth of
+ * a single entry (although it is allocated with room for multiple
+ * entries). Therefore, there is a different lock, called
+ * send_cpu_message_lock, that serializes accesses to the CPU queue.
+ * As a result, we don't need to lock the access to the entire H/W
+ * queues module when submitting a JOB to the CPU queue
+ */
+ if (q->queue_type != QUEUE_TYPE_CPU)
+ hdev->asic_funcs->hw_queues_lock(hdev);
+
+ if (hdev->disabled) {
+ rc = -EPERM;
+ goto out;
+ }
+
+ rc = ext_queue_sanity_checks(hdev, q, 1, false);
+ if (rc)
+ goto out;
+
+ ext_queue_submit_bd(hdev, q, 0, cb_size, cb_ptr);
+
+out:
+ if (q->queue_type != QUEUE_TYPE_CPU)
+ hdev->asic_funcs->hw_queues_unlock(hdev);
+
+ return rc;
+}
+
+/*
+ * ext_hw_queue_schedule_job - submit an JOB to an external queue
+ *
+ * @job: pointer to the job that needs to be submitted to the queue
+ *
+ * This function must be called when the scheduler mutex is taken
+ *
+ */
+static void ext_hw_queue_schedule_job(struct hl_cs_job *job)
+{
+ struct hl_device *hdev = job->cs->ctx->hdev;
+ struct hl_hw_queue *q = &hdev->kernel_queues[job->hw_queue_id];
+ struct hl_cq_entry cq_pkt;
+ struct hl_cq *cq;
+ u64 cq_addr;
+ struct hl_cb *cb;
+ u32 ctl;
+ u32 len;
+ u64 ptr;
+
+ /*
+ * Update the JOB ID inside the BD CTL so the device would know what
+ * to write in the completion queue
+ */
+ ctl = ((q->pi << BD_CTL_SHADOW_INDEX_SHIFT) & BD_CTL_SHADOW_INDEX_MASK);
+
+ cb = job->patched_cb;
+ len = job->job_cb_size;
+ ptr = cb->bus_address;
+
+ cq_pkt.data = __cpu_to_le32(
+ ((q->pi << CQ_ENTRY_SHADOW_INDEX_SHIFT)
+ & CQ_ENTRY_SHADOW_INDEX_MASK) |
+ (1 << CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT) |
+ (1 << CQ_ENTRY_READY_SHIFT));
+
+ /*
+ * No need to protect pi_offset because scheduling to the
+ * H/W queues is done under the scheduler mutex
+ *
+ * No need to check if CQ is full because it was already
+ * checked in hl_queue_sanity_checks
+ */
+ cq = &hdev->completion_queue[q->hw_queue_id];
+ cq_addr = cq->bus_address +
+ hdev->asic_prop.host_phys_base_address;
+ cq_addr += cq->pi * sizeof(struct hl_cq_entry);
+
+ hdev->asic_funcs->add_end_of_cb_packets(cb->kernel_address, len,
+ cq_addr,
+ __le32_to_cpu(cq_pkt.data),
+ q->hw_queue_id);
+
+ q->shadow_queue[hl_pi_2_offset(q->pi)] = job;
+
+ cq->pi = hl_cq_inc_ptr(cq->pi);
+
+ ext_queue_submit_bd(hdev, q, ctl, len, ptr);
+}
+
+/*
+ * int_hw_queue_schedule_job - submit an JOB to an internal queue
+ *
+ * @job: pointer to the job that needs to be submitted to the queue
+ *
+ * This function must be called when the scheduler mutex is taken
+ *
+ */
+static void int_hw_queue_schedule_job(struct hl_cs_job *job)
+{
+ struct hl_device *hdev = job->cs->ctx->hdev;
+ struct hl_hw_queue *q = &hdev->kernel_queues[job->hw_queue_id];
+ struct hl_bd bd;
+ u64 *pi, *pbd = (u64 *) &bd;
+
+ bd.ctl = 0;
+ bd.len = __cpu_to_le32(job->job_cb_size);
+ bd.ptr = __cpu_to_le64((u64) (uintptr_t) job->user_cb);
+
+ pi = (u64 *) (uintptr_t) (q->kernel_address +
+ ((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
+
+ pi[0] = pbd[0];
+ pi[1] = pbd[1];
+
+ q->pi++;
+ q->pi &= ((q->int_queue_len << 1) - 1);
+
+ /* Flush PQ entry write. Relevant only for specific ASICs */
+ hdev->asic_funcs->flush_pq_write(hdev, pi, pbd[0]);
+
+ hdev->asic_funcs->ring_doorbell(hdev, q->hw_queue_id, q->pi);
+}
+
+/*
+ * hl_hw_queue_schedule_cs - schedule a command submission
+ *
+ * @job : pointer to the CS
+ *
+ */
+int hl_hw_queue_schedule_cs(struct hl_cs *cs)
+{
+ struct hl_device *hdev = cs->ctx->hdev;
+ struct hl_cs_job *job, *tmp;
+ struct hl_hw_queue *q;
+ int rc = 0, i, cq_cnt;
+
+ hdev->asic_funcs->hw_queues_lock(hdev);
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ dev_err(hdev->dev,
+ "device is disabled or in reset, CS rejected!\n");
+ rc = -EPERM;
+ goto out;
+ }
+
+ q = &hdev->kernel_queues[0];
+ /* This loop assumes all external queues are consecutive */
+ for (i = 0, cq_cnt = 0 ; i < HL_MAX_QUEUES ; i++, q++) {
+ if (q->queue_type == QUEUE_TYPE_EXT) {
+ if (cs->jobs_in_queue_cnt[i]) {
+ rc = ext_queue_sanity_checks(hdev, q,
+ cs->jobs_in_queue_cnt[i], true);
+ if (rc)
+ goto unroll_cq_resv;
+ cq_cnt++;
+ }
+ } else if (q->queue_type == QUEUE_TYPE_INT) {
+ if (cs->jobs_in_queue_cnt[i]) {
+ rc = int_queue_sanity_checks(hdev, q,
+ cs->jobs_in_queue_cnt[i]);
+ if (rc)
+ goto unroll_cq_resv;
+ }
+ }
+ }
+
+ spin_lock(&hdev->hw_queues_mirror_lock);
+ list_add_tail(&cs->mirror_node, &hdev->hw_queues_mirror_list);
+
+ /* Queue TDR if the CS is the first entry and if timeout is wanted */
+ if ((hdev->timeout_jiffies != MAX_SCHEDULE_TIMEOUT) &&
+ (list_first_entry(&hdev->hw_queues_mirror_list,
+ struct hl_cs, mirror_node) == cs)) {
+ cs->tdr_active = true;
+ schedule_delayed_work(&cs->work_tdr, hdev->timeout_jiffies);
+ spin_unlock(&hdev->hw_queues_mirror_lock);
+ } else {
+ spin_unlock(&hdev->hw_queues_mirror_lock);
+ }
+
+ list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node) {
+ if (job->ext_queue)
+ ext_hw_queue_schedule_job(job);
+ else
+ int_hw_queue_schedule_job(job);
+ }
+
+ cs->submitted = true;
+
+ goto out;
+
+unroll_cq_resv:
+ /* This loop assumes all external queues are consecutive */
+ q = &hdev->kernel_queues[0];
+ for (i = 0 ; (i < HL_MAX_QUEUES) && (cq_cnt > 0) ; i++, q++) {
+ if ((q->queue_type == QUEUE_TYPE_EXT) &&
+ (cs->jobs_in_queue_cnt[i])) {
+ atomic_t *free_slots =
+ &hdev->completion_queue[i].free_slots_cnt;
+ atomic_add(cs->jobs_in_queue_cnt[i], free_slots);
+ cq_cnt--;
+ }
+ }
+
+out:
+ hdev->asic_funcs->hw_queues_unlock(hdev);
+
+ return rc;
+}
+
+/*
+ * hl_hw_queue_inc_ci_kernel - increment ci for kernel's queue
+ *
+ * @hdev: pointer to hl_device structure
+ * @hw_queue_id: which queue to increment its ci
+ */
+void hl_hw_queue_inc_ci_kernel(struct hl_device *hdev, u32 hw_queue_id)
+{
+ struct hl_hw_queue *q = &hdev->kernel_queues[hw_queue_id];
+
+ q->ci = hl_queue_inc_ptr(q->ci);
+}
+
+static int ext_and_cpu_hw_queue_init(struct hl_device *hdev,
+ struct hl_hw_queue *q)
+{
+ void *p;
+ int rc;
+
+ p = hdev->asic_funcs->dma_alloc_coherent(hdev,
+ HL_QUEUE_SIZE_IN_BYTES,
+ &q->bus_address, GFP_KERNEL | __GFP_ZERO);
+ if (!p)
+ return -ENOMEM;
+
+ q->kernel_address = (u64) (uintptr_t) p;
+
+ q->shadow_queue = kmalloc_array(HL_QUEUE_LENGTH,
+ sizeof(*q->shadow_queue),
+ GFP_KERNEL);
+ if (!q->shadow_queue) {
+ dev_err(hdev->dev,
+ "Failed to allocate shadow queue for H/W queue %d\n",
+ q->hw_queue_id);
+ rc = -ENOMEM;
+ goto free_queue;
+ }
+
+ /* Make sure read/write pointers are initialized to start of queue */
+ q->ci = 0;
+ q->pi = 0;
+
+ return 0;
+
+free_queue:
+ hdev->asic_funcs->dma_free_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES,
+ (void *) (uintptr_t) q->kernel_address, q->bus_address);
+
+ return rc;
+}
+
+static int int_hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
+{
+ void *p;
+
+ p = hdev->asic_funcs->get_int_queue_base(hdev, q->hw_queue_id,
+ &q->bus_address, &q->int_queue_len);
+ if (!p) {
+ dev_err(hdev->dev,
+ "Failed to get base address for internal queue %d\n",
+ q->hw_queue_id);
+ return -EFAULT;
+ }
+
+ q->kernel_address = (u64) (uintptr_t) p;
+ q->pi = 0;
+ q->ci = 0;
+
+ return 0;
+}
+
+static int cpu_hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
+{
+ return ext_and_cpu_hw_queue_init(hdev, q);
+}
+
+static int ext_hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
+{
+ return ext_and_cpu_hw_queue_init(hdev, q);
+}
+
+/*
+ * hw_queue_init - main initialization function for H/W queue object
+ *
+ * @hdev: pointer to hl_device device structure
+ * @q: pointer to hl_hw_queue queue structure
+ * @hw_queue_id: The id of the H/W queue
+ *
+ * Allocate dma-able memory for the queue and initialize fields
+ * Returns 0 on success
+ */
+static int hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,
+ u32 hw_queue_id)
+{
+ int rc;
+
+ BUILD_BUG_ON(HL_QUEUE_SIZE_IN_BYTES > HL_PAGE_SIZE);
+
+ q->hw_queue_id = hw_queue_id;
+
+ switch (q->queue_type) {
+ case QUEUE_TYPE_EXT:
+ rc = ext_hw_queue_init(hdev, q);
+ break;
+
+ case QUEUE_TYPE_INT:
+ rc = int_hw_queue_init(hdev, q);
+ break;
+
+ case QUEUE_TYPE_CPU:
+ rc = cpu_hw_queue_init(hdev, q);
+ break;
+
+ case QUEUE_TYPE_NA:
+ q->valid = 0;
+ return 0;
+
+ default:
+ dev_crit(hdev->dev, "wrong queue type %d during init\n",
+ q->queue_type);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc)
+ return rc;
+
+ q->valid = 1;
+
+ return 0;
+}
+
+/*
+ * hw_queue_fini - destroy queue
+ *
+ * @hdev: pointer to hl_device device structure
+ * @q: pointer to hl_hw_queue queue structure
+ *
+ * Free the queue memory
+ */
+static void hw_queue_fini(struct hl_device *hdev, struct hl_hw_queue *q)
+{
+ if (!q->valid)
+ return;
+
+ /*
+ * If we arrived here, there are no jobs waiting on this queue
+ * so we can safely remove it.
+ * This is because this function can only called when:
+ * 1. Either a context is deleted, which only can occur if all its
+ * jobs were finished
+ * 2. A context wasn't able to be created due to failure or timeout,
+ * which means there are no jobs on the queue yet
+ *
+ * The only exception are the queues of the kernel context, but
+ * if they are being destroyed, it means that the entire module is
+ * being removed. If the module is removed, it means there is no open
+ * user context. It also means that if a job was submitted by
+ * the kernel driver (e.g. context creation), the job itself was
+ * released by the kernel driver when a timeout occurred on its
+ * Completion. Thus, we don't need to release it again.
+ */
+
+ if (q->queue_type == QUEUE_TYPE_INT)
+ return;
+
+ kfree(q->shadow_queue);
+
+ hdev->asic_funcs->dma_free_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES,
+ (void *) (uintptr_t) q->kernel_address, q->bus_address);
+}
+
+int hl_hw_queues_create(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *asic = &hdev->asic_prop;
+ struct hl_hw_queue *q;
+ int i, rc, q_ready_cnt;
+
+ hdev->kernel_queues = kcalloc(HL_MAX_QUEUES,
+ sizeof(*hdev->kernel_queues), GFP_KERNEL);
+
+ if (!hdev->kernel_queues) {
+ dev_err(hdev->dev, "Not enough memory for H/W queues\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the H/W queues */
+ for (i = 0, q_ready_cnt = 0, q = hdev->kernel_queues;
+ i < HL_MAX_QUEUES ; i++, q_ready_cnt++, q++) {
+
+ q->queue_type = asic->hw_queues_props[i].type;
+ rc = hw_queue_init(hdev, q, i);
+ if (rc) {
+ dev_err(hdev->dev,
+ "failed to initialize queue %d\n", i);
+ goto release_queues;
+ }
+ }
+
+ return 0;
+
+release_queues:
+ for (i = 0, q = hdev->kernel_queues ; i < q_ready_cnt ; i++, q++)
+ hw_queue_fini(hdev, q);
+
+ kfree(hdev->kernel_queues);
+
+ return rc;
+}
+
+void hl_hw_queues_destroy(struct hl_device *hdev)
+{
+ struct hl_hw_queue *q;
+ int i;
+
+ for (i = 0, q = hdev->kernel_queues ; i < HL_MAX_QUEUES ; i++, q++)
+ hw_queue_fini(hdev, q);
+
+ kfree(hdev->kernel_queues);
+}
+
+void hl_hw_queue_reset(struct hl_device *hdev, bool hard_reset)
+{
+ struct hl_hw_queue *q;
+ int i;
+
+ for (i = 0, q = hdev->kernel_queues ; i < HL_MAX_QUEUES ; i++, q++) {
+ if ((!q->valid) ||
+ ((!hard_reset) && (q->queue_type == QUEUE_TYPE_CPU)))
+ continue;
+ q->pi = q->ci = 0;
+ }
+}
diff --git a/drivers/misc/habanalabs/hwmon.c b/drivers/misc/habanalabs/hwmon.c
new file mode 100644
index 000000000000..77facd25c4a2
--- /dev/null
+++ b/drivers/misc/habanalabs/hwmon.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/pci.h>
+#include <linux/hwmon.h>
+
+#define SENSORS_PKT_TIMEOUT 1000000 /* 1s */
+#define HWMON_NR_SENSOR_TYPES (hwmon_pwm + 1)
+
+int hl_build_hwmon_channel_info(struct hl_device *hdev,
+ struct armcp_sensor *sensors_arr)
+{
+ u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
+ u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
+ u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
+ struct hwmon_channel_info **channels_info;
+ u32 num_sensors_for_type, num_active_sensor_types = 0,
+ arr_size = 0, *curr_arr;
+ enum hwmon_sensor_types type;
+ int rc, i, j;
+
+ for (i = 0 ; i < ARMCP_MAX_SENSORS ; i++) {
+ type = __le32_to_cpu(sensors_arr[i].type);
+
+ if ((type == 0) && (sensors_arr[i].flags == 0))
+ break;
+
+ if (type >= HWMON_NR_SENSOR_TYPES) {
+ dev_err(hdev->dev,
+ "Got wrong sensor type %d from device\n", type);
+ return -EINVAL;
+ }
+
+ counts[type]++;
+ arr_size++;
+ }
+
+ for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
+ if (counts[i] == 0)
+ continue;
+
+ num_sensors_for_type = counts[i] + 1;
+ curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
+ GFP_KERNEL);
+ if (!curr_arr) {
+ rc = -ENOMEM;
+ goto sensors_type_err;
+ }
+
+ num_active_sensor_types++;
+ sensors_by_type[i] = curr_arr;
+ }
+
+ for (i = 0 ; i < arr_size ; i++) {
+ type = __le32_to_cpu(sensors_arr[i].type);
+ curr_arr = sensors_by_type[type];
+ curr_arr[sensors_by_type_next_index[type]++] =
+ __le32_to_cpu(sensors_arr[i].flags);
+ }
+
+ channels_info = kcalloc(num_active_sensor_types + 1,
+ sizeof(*channels_info), GFP_KERNEL);
+ if (!channels_info) {
+ rc = -ENOMEM;
+ goto channels_info_array_err;
+ }
+
+ for (i = 0 ; i < num_active_sensor_types ; i++) {
+ channels_info[i] = kzalloc(sizeof(*channels_info[i]),
+ GFP_KERNEL);
+ if (!channels_info[i]) {
+ rc = -ENOMEM;
+ goto channel_info_err;
+ }
+ }
+
+ for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
+ if (!sensors_by_type[i])
+ continue;
+
+ channels_info[j]->type = i;
+ channels_info[j]->config = sensors_by_type[i];
+ j++;
+ }
+
+ hdev->hl_chip_info->info =
+ (const struct hwmon_channel_info **)channels_info;
+
+ return 0;
+
+channel_info_err:
+ for (i = 0 ; i < num_active_sensor_types ; i++)
+ if (channels_info[i]) {
+ kfree(channels_info[i]->config);
+ kfree(channels_info[i]);
+ }
+ kfree(channels_info);
+channels_info_array_err:
+sensors_type_err:
+ for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
+ kfree(sensors_by_type[i]);
+
+ return rc;
+}
+
+static int hl_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_crit_hyst:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = hl_get_temperature(hdev, channel, attr);
+ break;
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_min:
+ case hwmon_in_max:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = hl_get_voltage(hdev, channel, attr);
+ break;
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_input:
+ case hwmon_curr_min:
+ case hwmon_curr_max:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = hl_get_current(hdev, channel, attr);
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_min:
+ case hwmon_fan_max:
+ break;
+ default:
+ return -EINVAL;
+ }
+ *val = hl_get_fan_speed(hdev, channel, attr);
+ break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ case hwmon_pwm_enable:
+ break;
+ default:
+ return -EINVAL;
+ }
+ *val = hl_get_pwm_info(hdev, channel, attr);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int hl_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ switch (type) {
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ case hwmon_pwm_enable:
+ break;
+ default:
+ return -EINVAL;
+ }
+ hl_set_pwm_info(hdev, channel, attr, val);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_crit:
+ case hwmon_temp_crit_hyst:
+ return 0444;
+ }
+ break;
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_min:
+ case hwmon_in_max:
+ return 0444;
+ }
+ break;
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_input:
+ case hwmon_curr_min:
+ case hwmon_curr_max:
+ return 0444;
+ }
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_min:
+ case hwmon_fan_max:
+ return 0444;
+ }
+ break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ case hwmon_pwm_enable:
+ return 0644;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static const struct hwmon_ops hl_hwmon_ops = {
+ .is_visible = hl_is_visible,
+ .read = hl_read,
+ .write = hl_write
+};
+
+long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_TEMPERATURE_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get temperature from sensor %d, error %d\n",
+ sensor_index, rc);
+ result = 0;
+ }
+
+ return result;
+}
+
+long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_VOLTAGE_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get voltage from sensor %d, error %d\n",
+ sensor_index, rc);
+ result = 0;
+ }
+
+ return result;
+}
+
+long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_CURRENT_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get current from sensor %d, error %d\n",
+ sensor_index, rc);
+ result = 0;
+ }
+
+ return result;
+}
+
+long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FAN_SPEED_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get fan speed from sensor %d, error %d\n",
+ sensor_index, rc);
+ result = 0;
+ }
+
+ return result;
+}
+
+long hl_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_PWM_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get pwm info from sensor %d, error %d\n",
+ sensor_index, rc);
+ result = 0;
+ }
+
+ return result;
+}
+
+void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
+ long value)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_PWM_SET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.sensor_index = __cpu_to_le16(sensor_index);
+ pkt.type = __cpu_to_le16(attr);
+ pkt.value = __cpu_to_le64(value);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SENSORS_PKT_TIMEOUT, NULL);
+
+ if (rc)
+ dev_err(hdev->dev,
+ "Failed to set pwm info to sensor %d, error %d\n",
+ sensor_index, rc);
+}
+
+int hl_hwmon_init(struct hl_device *hdev)
+{
+ struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
+ int rc;
+
+ if ((hdev->hwmon_initialized) || !(hdev->fw_loading))
+ return 0;
+
+ if (hdev->hl_chip_info->info) {
+ hdev->hl_chip_info->ops = &hl_hwmon_ops;
+
+ hdev->hwmon_dev = hwmon_device_register_with_info(dev,
+ "habanalabs", hdev, hdev->hl_chip_info, NULL);
+ if (IS_ERR(hdev->hwmon_dev)) {
+ rc = PTR_ERR(hdev->hwmon_dev);
+ dev_err(hdev->dev,
+ "Unable to register hwmon device: %d\n", rc);
+ return rc;
+ }
+
+ dev_info(hdev->dev, "%s: add sensors information\n",
+ dev_name(hdev->hwmon_dev));
+
+ hdev->hwmon_initialized = true;
+ } else {
+ dev_info(hdev->dev, "no available sensors\n");
+ }
+
+ return 0;
+}
+
+void hl_hwmon_fini(struct hl_device *hdev)
+{
+ if (!hdev->hwmon_initialized)
+ return;
+
+ hwmon_device_unregister(hdev->hwmon_dev);
+}
diff --git a/drivers/misc/habanalabs/include/armcp_if.h b/drivers/misc/habanalabs/include/armcp_if.h
new file mode 100644
index 000000000000..9dddb917e72c
--- /dev/null
+++ b/drivers/misc/habanalabs/include/armcp_if.h
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef ARMCP_IF_H
+#define ARMCP_IF_H
+
+#include <linux/types.h>
+
+/*
+ * EVENT QUEUE
+ */
+
+struct hl_eq_header {
+ __le32 reserved;
+ __le32 ctl;
+};
+
+struct hl_eq_entry {
+ struct hl_eq_header hdr;
+ __le64 data[7];
+};
+
+#define HL_EQ_ENTRY_SIZE sizeof(struct hl_eq_entry)
+
+#define EQ_CTL_READY_SHIFT 31
+#define EQ_CTL_READY_MASK 0x80000000
+
+#define EQ_CTL_EVENT_TYPE_SHIFT 16
+#define EQ_CTL_EVENT_TYPE_MASK 0x03FF0000
+
+#define EVENT_QUEUE_MSIX_IDX 5
+
+enum pq_init_status {
+ PQ_INIT_STATUS_NA = 0,
+ PQ_INIT_STATUS_READY_FOR_CP,
+ PQ_INIT_STATUS_READY_FOR_HOST
+};
+
+/*
+ * ArmCP Primary Queue Packets
+ *
+ * During normal operation, KMD needs to send various messages to ArmCP,
+ * usually either to SET some value into a H/W periphery or to GET the current
+ * value of some H/W periphery. For example, SET the frequency of MME/TPC and
+ * GET the value of the thermal sensor.
+ *
+ * These messages can be initiated either by the User application or by KMD
+ * itself, e.g. power management code. In either case, the communication from
+ * KMD to ArmCP will *always* be in synchronous mode, meaning that KMD will
+ * send a single message and poll until the message was acknowledged and the
+ * results are ready (if results are needed).
+ *
+ * This means that only a single message can be sent at a time and KMD must
+ * wait for its result before sending the next message. Having said that,
+ * because these are control messages which are sent in a relatively low
+ * frequency, this limitation seems acceptable. It's important to note that
+ * in case of multiple devices, messages to different devices *can* be sent
+ * at the same time.
+ *
+ * The message, inputs/outputs (if relevant) and fence object will be located
+ * on the device DDR at an address that will be determined by KMD. During
+ * device initialization phase, KMD will pass to ArmCP that address. Most of
+ * the message types will contain inputs/outputs inside the message itself.
+ * The common part of each message will contain the opcode of the message (its
+ * type) and a field representing a fence object.
+ *
+ * When KMD wishes to send a message to ArmCP, it will write the message
+ * contents to the device DDR, clear the fence object and then write the
+ * value 484 to the mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR register to issue
+ * the 484 interrupt-id to the ARM core.
+ *
+ * Upon receiving the 484 interrupt-id, ArmCP will read the message from the
+ * DDR. In case the message is a SET operation, ArmCP will first perform the
+ * operation and then write to the fence object on the device DDR. In case the
+ * message is a GET operation, ArmCP will first fill the results section on the
+ * device DDR and then write to the fence object. If an error occurred, ArmCP
+ * will fill the rc field with the right error code.
+ *
+ * In the meantime, KMD will poll on the fence object. Once KMD sees that the
+ * fence object is signaled, it will read the results from the device DDR
+ * (if relevant) and resume the code execution in KMD.
+ *
+ * To use QMAN packets, the opcode must be the QMAN opcode, shifted by 8
+ * so the value being put by the KMD matches the value read by ArmCP
+ *
+ * Non-QMAN packets should be limited to values 1 through (2^8 - 1)
+ *
+ * Detailed description:
+ *
+ * ARMCP_PACKET_DISABLE_PCI_ACCESS -
+ * After receiving this packet the embedded CPU must NOT issue PCI
+ * transactions (read/write) towards the Host CPU. This also include
+ * sending MSI-X interrupts.
+ * This packet is usually sent before the device is moved to D3Hot state.
+ *
+ * ARMCP_PACKET_ENABLE_PCI_ACCESS -
+ * After receiving this packet the embedded CPU is allowed to issue PCI
+ * transactions towards the Host CPU, including sending MSI-X interrupts.
+ * This packet is usually send after the device is moved to D0 state.
+ *
+ * ARMCP_PACKET_TEMPERATURE_GET -
+ * Fetch the current temperature / Max / Max Hyst / Critical /
+ * Critical Hyst of a specified thermal sensor. The packet's
+ * arguments specify the desired sensor and the field to get.
+ *
+ * ARMCP_PACKET_VOLTAGE_GET -
+ * Fetch the voltage / Max / Min of a specified sensor. The packet's
+ * arguments specify the sensor and type.
+ *
+ * ARMCP_PACKET_CURRENT_GET -
+ * Fetch the current / Max / Min of a specified sensor. The packet's
+ * arguments specify the sensor and type.
+ *
+ * ARMCP_PACKET_FAN_SPEED_GET -
+ * Fetch the speed / Max / Min of a specified fan. The packet's
+ * arguments specify the sensor and type.
+ *
+ * ARMCP_PACKET_PWM_GET -
+ * Fetch the pwm value / mode of a specified pwm. The packet's
+ * arguments specify the sensor and type.
+ *
+ * ARMCP_PACKET_PWM_SET -
+ * Set the pwm value / mode of a specified pwm. The packet's
+ * arguments specify the sensor, type and value.
+ *
+ * ARMCP_PACKET_FREQUENCY_SET -
+ * Set the frequency of a specified PLL. The packet's arguments specify
+ * the PLL and the desired frequency. The actual frequency in the device
+ * might differ from the requested frequency.
+ *
+ * ARMCP_PACKET_FREQUENCY_GET -
+ * Fetch the frequency of a specified PLL. The packet's arguments specify
+ * the PLL.
+ *
+ * ARMCP_PACKET_LED_SET -
+ * Set the state of a specified led. The packet's arguments
+ * specify the led and the desired state.
+ *
+ * ARMCP_PACKET_I2C_WR -
+ * Write 32-bit value to I2C device. The packet's arguments specify the
+ * I2C bus, address and value.
+ *
+ * ARMCP_PACKET_I2C_RD -
+ * Read 32-bit value from I2C device. The packet's arguments specify the
+ * I2C bus and address.
+ *
+ * ARMCP_PACKET_INFO_GET -
+ * Fetch information from the device as specified in the packet's
+ * structure. KMD passes the max size it allows the ArmCP to write to
+ * the structure, to prevent data corruption in case of mismatched
+ * KMD/FW versions.
+ *
+ * ARMCP_PACKET_FLASH_PROGRAM_REMOVED - this packet was removed
+ *
+ * ARMCP_PACKET_UNMASK_RAZWI_IRQ -
+ * Unmask the given IRQ. The IRQ number is specified in the value field.
+ * The packet is sent after receiving an interrupt and printing its
+ * relevant information.
+ *
+ * ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY -
+ * Unmask the given IRQs. The IRQs numbers are specified in an array right
+ * after the armcp_packet structure, where its first element is the array
+ * length. The packet is sent after a soft reset was done in order to
+ * handle any interrupts that were sent during the reset process.
+ *
+ * ARMCP_PACKET_TEST -
+ * Test packet for ArmCP connectivity. The CPU will put the fence value
+ * in the result field.
+ *
+ * ARMCP_PACKET_FREQUENCY_CURR_GET -
+ * Fetch the current frequency of a specified PLL. The packet's arguments
+ * specify the PLL.
+ *
+ * ARMCP_PACKET_MAX_POWER_GET -
+ * Fetch the maximal power of the device.
+ *
+ * ARMCP_PACKET_MAX_POWER_SET -
+ * Set the maximal power of the device. The packet's arguments specify
+ * the power.
+ *
+ * ARMCP_PACKET_EEPROM_DATA_GET -
+ * Get EEPROM data from the ArmCP kernel. The buffer is specified in the
+ * addr field. The CPU will put the returned data size in the result
+ * field. In addition, KMD passes the max size it allows the ArmCP to
+ * write to the structure, to prevent data corruption in case of
+ * mismatched KMD/FW versions.
+ *
+ */
+
+enum armcp_packet_id {
+ ARMCP_PACKET_DISABLE_PCI_ACCESS = 1, /* internal */
+ ARMCP_PACKET_ENABLE_PCI_ACCESS, /* internal */
+ ARMCP_PACKET_TEMPERATURE_GET, /* sysfs */
+ ARMCP_PACKET_VOLTAGE_GET, /* sysfs */
+ ARMCP_PACKET_CURRENT_GET, /* sysfs */
+ ARMCP_PACKET_FAN_SPEED_GET, /* sysfs */
+ ARMCP_PACKET_PWM_GET, /* sysfs */
+ ARMCP_PACKET_PWM_SET, /* sysfs */
+ ARMCP_PACKET_FREQUENCY_SET, /* sysfs */
+ ARMCP_PACKET_FREQUENCY_GET, /* sysfs */
+ ARMCP_PACKET_LED_SET, /* debugfs */
+ ARMCP_PACKET_I2C_WR, /* debugfs */
+ ARMCP_PACKET_I2C_RD, /* debugfs */
+ ARMCP_PACKET_INFO_GET, /* IOCTL */
+ ARMCP_PACKET_FLASH_PROGRAM_REMOVED,
+ ARMCP_PACKET_UNMASK_RAZWI_IRQ, /* internal */
+ ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY, /* internal */
+ ARMCP_PACKET_TEST, /* internal */
+ ARMCP_PACKET_FREQUENCY_CURR_GET, /* sysfs */
+ ARMCP_PACKET_MAX_POWER_GET, /* sysfs */
+ ARMCP_PACKET_MAX_POWER_SET, /* sysfs */
+ ARMCP_PACKET_EEPROM_DATA_GET, /* sysfs */
+};
+
+#define ARMCP_PACKET_FENCE_VAL 0xFE8CE7A5
+
+#define ARMCP_PKT_CTL_RC_SHIFT 12
+#define ARMCP_PKT_CTL_RC_MASK 0x0000F000
+
+#define ARMCP_PKT_CTL_OPCODE_SHIFT 16
+#define ARMCP_PKT_CTL_OPCODE_MASK 0x1FFF0000
+
+struct armcp_packet {
+ union {
+ __le64 value; /* For SET packets */
+ __le64 result; /* For GET packets */
+ __le64 addr; /* For PQ */
+ };
+
+ __le32 ctl;
+
+ __le32 fence; /* Signal to KMD that message is completed */
+
+ union {
+ struct {/* For temperature/current/voltage/fan/pwm get/set */
+ __le16 sensor_index;
+ __le16 type;
+ };
+
+ struct { /* For I2C read/write */
+ __u8 i2c_bus;
+ __u8 i2c_addr;
+ __u8 i2c_reg;
+ __u8 pad; /* unused */
+ };
+
+ /* For frequency get/set */
+ __le32 pll_index;
+
+ /* For led set */
+ __le32 led_index;
+
+ /* For get Armcp info/EEPROM data */
+ __le32 data_max_size;
+ };
+};
+
+struct armcp_unmask_irq_arr_packet {
+ struct armcp_packet armcp_pkt;
+ __le32 length;
+ __le32 irqs[0];
+};
+
+enum armcp_packet_rc {
+ armcp_packet_success,
+ armcp_packet_invalid,
+ armcp_packet_fault
+};
+
+enum armcp_temp_type {
+ armcp_temp_input,
+ armcp_temp_max = 6,
+ armcp_temp_max_hyst,
+ armcp_temp_crit,
+ armcp_temp_crit_hyst
+};
+
+enum armcp_in_attributes {
+ armcp_in_input,
+ armcp_in_min,
+ armcp_in_max
+};
+
+enum armcp_curr_attributes {
+ armcp_curr_input,
+ armcp_curr_min,
+ armcp_curr_max
+};
+
+enum armcp_fan_attributes {
+ armcp_fan_input,
+ armcp_fan_min = 2,
+ armcp_fan_max
+};
+
+enum armcp_pwm_attributes {
+ armcp_pwm_input,
+ armcp_pwm_enable
+};
+
+/* Event Queue Packets */
+
+struct eq_generic_event {
+ __le64 data[7];
+};
+
+/*
+ * ArmCP info
+ */
+
+#define VERSION_MAX_LEN 128
+#define ARMCP_MAX_SENSORS 128
+
+struct armcp_sensor {
+ __le32 type;
+ __le32 flags;
+};
+
+struct armcp_info {
+ struct armcp_sensor sensors[ARMCP_MAX_SENSORS];
+ __u8 kernel_version[VERSION_MAX_LEN];
+ __le32 reserved[3];
+ __le32 cpld_version;
+ __le32 infineon_version;
+ __u8 fuse_version[VERSION_MAX_LEN];
+ __u8 thermal_version[VERSION_MAX_LEN];
+ __u8 armcp_version[VERSION_MAX_LEN];
+ __le64 dram_size;
+};
+
+#endif /* ARMCP_IF_H */
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h
new file mode 100644
index 000000000000..2cf5c46b6e8e
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_masks.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_CPU_CA53_CFG_MASKS_H_
+#define ASIC_REG_CPU_CA53_CFG_MASKS_H_
+
+/*
+ *****************************************
+ * CPU_CA53_CFG (Prototype: CA53_CFG)
+ *****************************************
+ */
+
+/* CPU_CA53_CFG_ARM_CFG */
+#define CPU_CA53_CFG_ARM_CFG_AA64NAA32_SHIFT 0
+#define CPU_CA53_CFG_ARM_CFG_AA64NAA32_MASK 0x3
+#define CPU_CA53_CFG_ARM_CFG_END_SHIFT 4
+#define CPU_CA53_CFG_ARM_CFG_END_MASK 0x30
+#define CPU_CA53_CFG_ARM_CFG_TE_SHIFT 8
+#define CPU_CA53_CFG_ARM_CFG_TE_MASK 0x300
+#define CPU_CA53_CFG_ARM_CFG_VINITHI_SHIFT 12
+#define CPU_CA53_CFG_ARM_CFG_VINITHI_MASK 0x3000
+
+/* CPU_CA53_CFG_RST_ADDR_LSB */
+#define CPU_CA53_CFG_RST_ADDR_LSB_VECTOR_SHIFT 0
+#define CPU_CA53_CFG_RST_ADDR_LSB_VECTOR_MASK 0xFFFFFFFF
+
+/* CPU_CA53_CFG_RST_ADDR_MSB */
+#define CPU_CA53_CFG_RST_ADDR_MSB_VECTOR_SHIFT 0
+#define CPU_CA53_CFG_RST_ADDR_MSB_VECTOR_MASK 0xFF
+
+/* CPU_CA53_CFG_ARM_RST_CONTROL */
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NCPUPORESET_SHIFT 0
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NCPUPORESET_MASK 0x3
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NCORERESET_SHIFT 4
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NCORERESET_MASK 0x30
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NL2RESET_SHIFT 8
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NL2RESET_MASK 0x100
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NPRESETDBG_SHIFT 12
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NPRESETDBG_MASK 0x1000
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NMBISTRESET_SHIFT 16
+#define CPU_CA53_CFG_ARM_RST_CONTROL_NMBISTRESET_MASK 0x10000
+#define CPU_CA53_CFG_ARM_RST_CONTROL_WARMRSTREQ_SHIFT 20
+#define CPU_CA53_CFG_ARM_RST_CONTROL_WARMRSTREQ_MASK 0x300000
+
+/* CPU_CA53_CFG_ARM_AFFINITY */
+#define CPU_CA53_CFG_ARM_AFFINITY_LEVEL_1_SHIFT 0
+#define CPU_CA53_CFG_ARM_AFFINITY_LEVEL_1_MASK 0xFF
+#define CPU_CA53_CFG_ARM_AFFINITY_LEVEL_2_SHIFT 8
+#define CPU_CA53_CFG_ARM_AFFINITY_LEVEL_2_MASK 0xFF00
+
+/* CPU_CA53_CFG_ARM_DISABLE */
+#define CPU_CA53_CFG_ARM_DISABLE_CP15S_SHIFT 0
+#define CPU_CA53_CFG_ARM_DISABLE_CP15S_MASK 0x3
+#define CPU_CA53_CFG_ARM_DISABLE_CRYPTO_SHIFT 4
+#define CPU_CA53_CFG_ARM_DISABLE_CRYPTO_MASK 0x30
+#define CPU_CA53_CFG_ARM_DISABLE_L2_RST_SHIFT 8
+#define CPU_CA53_CFG_ARM_DISABLE_L2_RST_MASK 0x100
+#define CPU_CA53_CFG_ARM_DISABLE_DBG_L1_RST_SHIFT 9
+#define CPU_CA53_CFG_ARM_DISABLE_DBG_L1_RST_MASK 0x200
+
+/* CPU_CA53_CFG_ARM_GIC_PERIPHBASE */
+#define CPU_CA53_CFG_ARM_GIC_PERIPHBASE_PERIPHBASE_SHIFT 0
+#define CPU_CA53_CFG_ARM_GIC_PERIPHBASE_PERIPHBASE_MASK 0x3FFFFF
+
+/* CPU_CA53_CFG_ARM_GIC_IRQ_CFG */
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NREI_SHIFT 0
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NREI_MASK 0x3
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NSEI_SHIFT 4
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NSEI_MASK 0x30
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NIRQ_SHIFT 8
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NIRQ_MASK 0x300
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NFIQ_SHIFT 12
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NFIQ_MASK 0x3000
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVFIQ_SHIFT 16
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVFIQ_MASK 0x30000
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVIRQ_SHIFT 20
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVIRQ_MASK 0x300000
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVSEI_SHIFT 24
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_NVSEI_MASK 0x3000000
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_GIC_EN_SHIFT 31
+#define CPU_CA53_CFG_ARM_GIC_IRQ_CFG_GIC_EN_MASK 0x80000000
+
+/* CPU_CA53_CFG_ARM_PWR_MNG */
+#define CPU_CA53_CFG_ARM_PWR_MNG_CLREXMONREQ_SHIFT 0
+#define CPU_CA53_CFG_ARM_PWR_MNG_CLREXMONREQ_MASK 0x1
+#define CPU_CA53_CFG_ARM_PWR_MNG_EVENTI_SHIFT 1
+#define CPU_CA53_CFG_ARM_PWR_MNG_EVENTI_MASK 0x2
+#define CPU_CA53_CFG_ARM_PWR_MNG_L2FLUSHREQ_SHIFT 2
+#define CPU_CA53_CFG_ARM_PWR_MNG_L2FLUSHREQ_MASK 0x4
+#define CPU_CA53_CFG_ARM_PWR_MNG_L2QREQN_SHIFT 3
+#define CPU_CA53_CFG_ARM_PWR_MNG_L2QREQN_MASK 0x8
+#define CPU_CA53_CFG_ARM_PWR_MNG_CPUQREQN_SHIFT 4
+#define CPU_CA53_CFG_ARM_PWR_MNG_CPUQREQN_MASK 0x30
+#define CPU_CA53_CFG_ARM_PWR_MNG_NEONQREQN_SHIFT 8
+#define CPU_CA53_CFG_ARM_PWR_MNG_NEONQREQN_MASK 0x300
+#define CPU_CA53_CFG_ARM_PWR_MNG_DBGPWRDUP_SHIFT 12
+#define CPU_CA53_CFG_ARM_PWR_MNG_DBGPWRDUP_MASK 0x3000
+
+/* CPU_CA53_CFG_ARB_DBG_ROM_ADDR */
+#define CPU_CA53_CFG_ARB_DBG_ROM_ADDR_DEBUG_ROM_BASE_ADDR_SHIFT 0
+#define CPU_CA53_CFG_ARB_DBG_ROM_ADDR_DEBUG_ROM_BASE_ADDR_MASK 0xFFFFFFF
+#define CPU_CA53_CFG_ARB_DBG_ROM_ADDR_DEBUG_ROM_BASE_ADDR_VALID_SHIFT 31
+#define CPU_CA53_CFG_ARB_DBG_ROM_ADDR_DEBUG_ROM_BASE_ADDR_VALID_MASK 0x80000000
+
+/* CPU_CA53_CFG_ARM_DBG_MODES */
+#define CPU_CA53_CFG_ARM_DBG_MODES_EDBGRQ_SHIFT 0
+#define CPU_CA53_CFG_ARM_DBG_MODES_EDBGRQ_MASK 0x3
+#define CPU_CA53_CFG_ARM_DBG_MODES_DBGEN_SHIFT 4
+#define CPU_CA53_CFG_ARM_DBG_MODES_DBGEN_MASK 0x30
+#define CPU_CA53_CFG_ARM_DBG_MODES_NIDEN_SHIFT 8
+#define CPU_CA53_CFG_ARM_DBG_MODES_NIDEN_MASK 0x300
+#define CPU_CA53_CFG_ARM_DBG_MODES_SPIDEN_SHIFT 12
+#define CPU_CA53_CFG_ARM_DBG_MODES_SPIDEN_MASK 0x3000
+#define CPU_CA53_CFG_ARM_DBG_MODES_SPNIDEN_SHIFT 16
+#define CPU_CA53_CFG_ARM_DBG_MODES_SPNIDEN_MASK 0x30000
+
+/* CPU_CA53_CFG_ARM_PWR_STAT_0 */
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_CLREXMONACK_SHIFT 0
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_CLREXMONACK_MASK 0x1
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_EVENTO_SHIFT 1
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_EVENTO_MASK 0x2
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFI_SHIFT 4
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFI_MASK 0x30
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFE_SHIFT 8
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFE_MASK 0x300
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFIL2_SHIFT 12
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_STANDBYWFIL2_MASK 0x1000
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_L2FLUSHDONE_SHIFT 13
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_L2FLUSHDONE_MASK 0x2000
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_SMPEN_SHIFT 16
+#define CPU_CA53_CFG_ARM_PWR_STAT_0_SMPEN_MASK 0x30000
+
+/* CPU_CA53_CFG_ARM_PWR_STAT_1 */
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQACTIVE_SHIFT 0
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQACTIVE_MASK 0x3
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQDENY_SHIFT 4
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQDENY_MASK 0x30
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQACCEPTN_SHIFT 8
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_CPUQACCEPTN_MASK 0x300
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQACTIVE_SHIFT 12
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQACTIVE_MASK 0x3000
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQDENY_SHIFT 16
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQDENY_MASK 0x30000
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQACCEPTN_SHIFT 20
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_NEONQACCEPTN_MASK 0x300000
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QACTIVE_SHIFT 24
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QACTIVE_MASK 0x1000000
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QDENY_SHIFT 25
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QDENY_MASK 0x2000000
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QACCEPTN_SHIFT 26
+#define CPU_CA53_CFG_ARM_PWR_STAT_1_L2QACCEPTN_MASK 0x4000000
+
+/* CPU_CA53_CFG_ARM_DBG_STATUS */
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGACK_SHIFT 0
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGACK_MASK 0x3
+#define CPU_CA53_CFG_ARM_DBG_STATUS_COMMRX_SHIFT 4
+#define CPU_CA53_CFG_ARM_DBG_STATUS_COMMRX_MASK 0x30
+#define CPU_CA53_CFG_ARM_DBG_STATUS_COMMTX_SHIFT 8
+#define CPU_CA53_CFG_ARM_DBG_STATUS_COMMTX_MASK 0x300
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGRSTREQ_SHIFT 12
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGRSTREQ_MASK 0x3000
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGNOPWRDWN_SHIFT 16
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGNOPWRDWN_MASK 0x30000
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGPWRUPREQ_SHIFT 20
+#define CPU_CA53_CFG_ARM_DBG_STATUS_DBGPWRUPREQ_MASK 0x300000
+
+/* CPU_CA53_CFG_ARM_MEM_ATTR */
+#define CPU_CA53_CFG_ARM_MEM_ATTR_RDMEMATTR_SHIFT 0
+#define CPU_CA53_CFG_ARM_MEM_ATTR_RDMEMATTR_MASK 0xFF
+#define CPU_CA53_CFG_ARM_MEM_ATTR_WRMEMATTR_SHIFT 8
+#define CPU_CA53_CFG_ARM_MEM_ATTR_WRMEMATTR_MASK 0xFF00
+#define CPU_CA53_CFG_ARM_MEM_ATTR_RACKM_SHIFT 16
+#define CPU_CA53_CFG_ARM_MEM_ATTR_RACKM_MASK 0x10000
+#define CPU_CA53_CFG_ARM_MEM_ATTR_WACKM_SHIFT 20
+#define CPU_CA53_CFG_ARM_MEM_ATTR_WACKM_MASK 0x100000
+
+/* CPU_CA53_CFG_ARM_PMU */
+#define CPU_CA53_CFG_ARM_PMU_EVENT_SHIFT 0
+#define CPU_CA53_CFG_ARM_PMU_EVENT_MASK 0x3FFFFFFF
+
+#endif /* ASIC_REG_CPU_CA53_CFG_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h
new file mode 100644
index 000000000000..840ccffa1081
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_ca53_cfg_regs.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_CPU_CA53_CFG_REGS_H_
+#define ASIC_REG_CPU_CA53_CFG_REGS_H_
+
+/*
+ *****************************************
+ * CPU_CA53_CFG (Prototype: CA53_CFG)
+ *****************************************
+ */
+
+#define mmCPU_CA53_CFG_ARM_CFG 0x441100
+
+#define mmCPU_CA53_CFG_RST_ADDR_LSB_0 0x441104
+
+#define mmCPU_CA53_CFG_RST_ADDR_LSB_1 0x441108
+
+#define mmCPU_CA53_CFG_RST_ADDR_MSB_0 0x441114
+
+#define mmCPU_CA53_CFG_RST_ADDR_MSB_1 0x441118
+
+#define mmCPU_CA53_CFG_ARM_RST_CONTROL 0x441124
+
+#define mmCPU_CA53_CFG_ARM_AFFINITY 0x441128
+
+#define mmCPU_CA53_CFG_ARM_DISABLE 0x44112C
+
+#define mmCPU_CA53_CFG_ARM_GIC_PERIPHBASE 0x441130
+
+#define mmCPU_CA53_CFG_ARM_GIC_IRQ_CFG 0x441134
+
+#define mmCPU_CA53_CFG_ARM_PWR_MNG 0x441138
+
+#define mmCPU_CA53_CFG_ARB_DBG_ROM_ADDR 0x44113C
+
+#define mmCPU_CA53_CFG_ARM_DBG_MODES 0x441140
+
+#define mmCPU_CA53_CFG_ARM_PWR_STAT_0 0x441200
+
+#define mmCPU_CA53_CFG_ARM_PWR_STAT_1 0x441204
+
+#define mmCPU_CA53_CFG_ARM_DBG_STATUS 0x441208
+
+#define mmCPU_CA53_CFG_ARM_MEM_ATTR 0x44120C
+
+#define mmCPU_CA53_CFG_ARM_PMU_0 0x441210
+
+#define mmCPU_CA53_CFG_ARM_PMU_1 0x441214
+
+#endif /* ASIC_REG_CPU_CA53_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h
new file mode 100644
index 000000000000..f23cb3e41c30
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_if_regs.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_CPU_IF_REGS_H_
+#define ASIC_REG_CPU_IF_REGS_H_
+
+/*
+ *****************************************
+ * CPU_IF (Prototype: CPU_IF)
+ *****************************************
+ */
+
+#define mmCPU_IF_PF_PQ_PI 0x442100
+
+#define mmCPU_IF_ARUSER_OVR 0x442104
+
+#define mmCPU_IF_ARUSER_OVR_EN 0x442108
+
+#define mmCPU_IF_AWUSER_OVR 0x44210C
+
+#define mmCPU_IF_AWUSER_OVR_EN 0x442110
+
+#define mmCPU_IF_AXCACHE_OVR 0x442114
+
+#define mmCPU_IF_LOCK_OVR 0x442118
+
+#define mmCPU_IF_PROT_OVR 0x44211C
+
+#define mmCPU_IF_MAX_OUTSTANDING 0x442120
+
+#define mmCPU_IF_EARLY_BRESP_EN 0x442124
+
+#define mmCPU_IF_FORCE_RSP_OK 0x442128
+
+#define mmCPU_IF_CPU_MSB_ADDR 0x44212C
+
+#define mmCPU_IF_AXI_SPLIT_INTR 0x442130
+
+#endif /* ASIC_REG_CPU_IF_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h
new file mode 100644
index 000000000000..8fc97f838ada
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/cpu_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_CPU_PLL_REGS_H_
+#define ASIC_REG_CPU_PLL_REGS_H_
+
+/*
+ *****************************************
+ * CPU_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmCPU_PLL_NR 0x4A2100
+
+#define mmCPU_PLL_NF 0x4A2104
+
+#define mmCPU_PLL_OD 0x4A2108
+
+#define mmCPU_PLL_NB 0x4A210C
+
+#define mmCPU_PLL_CFG 0x4A2110
+
+#define mmCPU_PLL_LOSE_MASK 0x4A2120
+
+#define mmCPU_PLL_LOCK_INTR 0x4A2128
+
+#define mmCPU_PLL_LOCK_BYPASS 0x4A212C
+
+#define mmCPU_PLL_DATA_CHNG 0x4A2130
+
+#define mmCPU_PLL_RST 0x4A2134
+
+#define mmCPU_PLL_SLIP_WD_CNTR 0x4A2150
+
+#define mmCPU_PLL_DIV_FACTOR_0 0x4A2200
+
+#define mmCPU_PLL_DIV_FACTOR_1 0x4A2204
+
+#define mmCPU_PLL_DIV_FACTOR_2 0x4A2208
+
+#define mmCPU_PLL_DIV_FACTOR_3 0x4A220C
+
+#define mmCPU_PLL_DIV_FACTOR_CMD_0 0x4A2220
+
+#define mmCPU_PLL_DIV_FACTOR_CMD_1 0x4A2224
+
+#define mmCPU_PLL_DIV_FACTOR_CMD_2 0x4A2228
+
+#define mmCPU_PLL_DIV_FACTOR_CMD_3 0x4A222C
+
+#define mmCPU_PLL_DIV_SEL_0 0x4A2280
+
+#define mmCPU_PLL_DIV_SEL_1 0x4A2284
+
+#define mmCPU_PLL_DIV_SEL_2 0x4A2288
+
+#define mmCPU_PLL_DIV_SEL_3 0x4A228C
+
+#define mmCPU_PLL_DIV_EN_0 0x4A22A0
+
+#define mmCPU_PLL_DIV_EN_1 0x4A22A4
+
+#define mmCPU_PLL_DIV_EN_2 0x4A22A8
+
+#define mmCPU_PLL_DIV_EN_3 0x4A22AC
+
+#define mmCPU_PLL_DIV_FACTOR_BUSY_0 0x4A22C0
+
+#define mmCPU_PLL_DIV_FACTOR_BUSY_1 0x4A22C4
+
+#define mmCPU_PLL_DIV_FACTOR_BUSY_2 0x4A22C8
+
+#define mmCPU_PLL_DIV_FACTOR_BUSY_3 0x4A22CC
+
+#define mmCPU_PLL_CLK_GATER 0x4A2300
+
+#define mmCPU_PLL_CLK_RLX_0 0x4A2310
+
+#define mmCPU_PLL_CLK_RLX_1 0x4A2314
+
+#define mmCPU_PLL_CLK_RLX_2 0x4A2318
+
+#define mmCPU_PLL_CLK_RLX_3 0x4A231C
+
+#define mmCPU_PLL_REF_CNTR_PERIOD 0x4A2400
+
+#define mmCPU_PLL_REF_LOW_THRESHOLD 0x4A2410
+
+#define mmCPU_PLL_REF_HIGH_THRESHOLD 0x4A2420
+
+#define mmCPU_PLL_PLL_NOT_STABLE 0x4A2430
+
+#define mmCPU_PLL_FREQ_CALC_EN 0x4A2440
+
+#endif /* ASIC_REG_CPU_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h
new file mode 100644
index 000000000000..61c8cd9ce58b
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_0_regs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_CH_0_REGS_H_
+#define ASIC_REG_DMA_CH_0_REGS_H_
+
+/*
+ *****************************************
+ * DMA_CH_0 (Prototype: DMA_CH)
+ *****************************************
+ */
+
+#define mmDMA_CH_0_CFG0 0x401000
+
+#define mmDMA_CH_0_CFG1 0x401004
+
+#define mmDMA_CH_0_ERRMSG_ADDR_LO 0x401008
+
+#define mmDMA_CH_0_ERRMSG_ADDR_HI 0x40100C
+
+#define mmDMA_CH_0_ERRMSG_WDATA 0x401010
+
+#define mmDMA_CH_0_RD_COMP_ADDR_LO 0x401014
+
+#define mmDMA_CH_0_RD_COMP_ADDR_HI 0x401018
+
+#define mmDMA_CH_0_RD_COMP_WDATA 0x40101C
+
+#define mmDMA_CH_0_WR_COMP_ADDR_LO 0x401020
+
+#define mmDMA_CH_0_WR_COMP_ADDR_HI 0x401024
+
+#define mmDMA_CH_0_WR_COMP_WDATA 0x401028
+
+#define mmDMA_CH_0_LDMA_SRC_ADDR_LO 0x40102C
+
+#define mmDMA_CH_0_LDMA_SRC_ADDR_HI 0x401030
+
+#define mmDMA_CH_0_LDMA_DST_ADDR_LO 0x401034
+
+#define mmDMA_CH_0_LDMA_DST_ADDR_HI 0x401038
+
+#define mmDMA_CH_0_LDMA_TSIZE 0x40103C
+
+#define mmDMA_CH_0_COMIT_TRANSFER 0x401040
+
+#define mmDMA_CH_0_STS0 0x401044
+
+#define mmDMA_CH_0_STS1 0x401048
+
+#define mmDMA_CH_0_STS2 0x40104C
+
+#define mmDMA_CH_0_STS3 0x401050
+
+#define mmDMA_CH_0_STS4 0x401054
+
+#define mmDMA_CH_0_SRC_ADDR_LO_STS 0x401058
+
+#define mmDMA_CH_0_SRC_ADDR_HI_STS 0x40105C
+
+#define mmDMA_CH_0_SRC_TSIZE_STS 0x401060
+
+#define mmDMA_CH_0_DST_ADDR_LO_STS 0x401064
+
+#define mmDMA_CH_0_DST_ADDR_HI_STS 0x401068
+
+#define mmDMA_CH_0_DST_TSIZE_STS 0x40106C
+
+#define mmDMA_CH_0_RD_RATE_LIM_EN 0x401070
+
+#define mmDMA_CH_0_RD_RATE_LIM_RST_TOKEN 0x401074
+
+#define mmDMA_CH_0_RD_RATE_LIM_SAT 0x401078
+
+#define mmDMA_CH_0_RD_RATE_LIM_TOUT 0x40107C
+
+#define mmDMA_CH_0_WR_RATE_LIM_EN 0x401080
+
+#define mmDMA_CH_0_WR_RATE_LIM_RST_TOKEN 0x401084
+
+#define mmDMA_CH_0_WR_RATE_LIM_SAT 0x401088
+
+#define mmDMA_CH_0_WR_RATE_LIM_TOUT 0x40108C
+
+#define mmDMA_CH_0_CFG2 0x401090
+
+#define mmDMA_CH_0_TDMA_CTL 0x401100
+
+#define mmDMA_CH_0_TDMA_SRC_BASE_ADDR_LO 0x401104
+
+#define mmDMA_CH_0_TDMA_SRC_BASE_ADDR_HI 0x401108
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_BASE_0 0x40110C
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_SIZE_0 0x401110
+
+#define mmDMA_CH_0_TDMA_SRC_VALID_ELEMENTS_0 0x401114
+
+#define mmDMA_CH_0_TDMA_SRC_START_OFFSET_0 0x401118
+
+#define mmDMA_CH_0_TDMA_SRC_STRIDE_0 0x40111C
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_BASE_1 0x401120
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_SIZE_1 0x401124
+
+#define mmDMA_CH_0_TDMA_SRC_VALID_ELEMENTS_1 0x401128
+
+#define mmDMA_CH_0_TDMA_SRC_START_OFFSET_1 0x40112C
+
+#define mmDMA_CH_0_TDMA_SRC_STRIDE_1 0x401130
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_BASE_2 0x401134
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_SIZE_2 0x401138
+
+#define mmDMA_CH_0_TDMA_SRC_VALID_ELEMENTS_2 0x40113C
+
+#define mmDMA_CH_0_TDMA_SRC_START_OFFSET_2 0x401140
+
+#define mmDMA_CH_0_TDMA_SRC_STRIDE_2 0x401144
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_BASE_3 0x401148
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_SIZE_3 0x40114C
+
+#define mmDMA_CH_0_TDMA_SRC_VALID_ELEMENTS_3 0x401150
+
+#define mmDMA_CH_0_TDMA_SRC_START_OFFSET_3 0x401154
+
+#define mmDMA_CH_0_TDMA_SRC_STRIDE_3 0x401158
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_BASE_4 0x40115C
+
+#define mmDMA_CH_0_TDMA_SRC_ROI_SIZE_4 0x401160
+
+#define mmDMA_CH_0_TDMA_SRC_VALID_ELEMENTS_4 0x401164
+
+#define mmDMA_CH_0_TDMA_SRC_START_OFFSET_4 0x401168
+
+#define mmDMA_CH_0_TDMA_SRC_STRIDE_4 0x40116C
+
+#define mmDMA_CH_0_TDMA_DST_BASE_ADDR_LO 0x401170
+
+#define mmDMA_CH_0_TDMA_DST_BASE_ADDR_HI 0x401174
+
+#define mmDMA_CH_0_TDMA_DST_ROI_BASE_0 0x401178
+
+#define mmDMA_CH_0_TDMA_DST_ROI_SIZE_0 0x40117C
+
+#define mmDMA_CH_0_TDMA_DST_VALID_ELEMENTS_0 0x401180
+
+#define mmDMA_CH_0_TDMA_DST_START_OFFSET_0 0x401184
+
+#define mmDMA_CH_0_TDMA_DST_STRIDE_0 0x401188
+
+#define mmDMA_CH_0_TDMA_DST_ROI_BASE_1 0x40118C
+
+#define mmDMA_CH_0_TDMA_DST_ROI_SIZE_1 0x401190
+
+#define mmDMA_CH_0_TDMA_DST_VALID_ELEMENTS_1 0x401194
+
+#define mmDMA_CH_0_TDMA_DST_START_OFFSET_1 0x401198
+
+#define mmDMA_CH_0_TDMA_DST_STRIDE_1 0x40119C
+
+#define mmDMA_CH_0_TDMA_DST_ROI_BASE_2 0x4011A0
+
+#define mmDMA_CH_0_TDMA_DST_ROI_SIZE_2 0x4011A4
+
+#define mmDMA_CH_0_TDMA_DST_VALID_ELEMENTS_2 0x4011A8
+
+#define mmDMA_CH_0_TDMA_DST_START_OFFSET_2 0x4011AC
+
+#define mmDMA_CH_0_TDMA_DST_STRIDE_2 0x4011B0
+
+#define mmDMA_CH_0_TDMA_DST_ROI_BASE_3 0x4011B4
+
+#define mmDMA_CH_0_TDMA_DST_ROI_SIZE_3 0x4011B8
+
+#define mmDMA_CH_0_TDMA_DST_VALID_ELEMENTS_3 0x4011BC
+
+#define mmDMA_CH_0_TDMA_DST_START_OFFSET_3 0x4011C0
+
+#define mmDMA_CH_0_TDMA_DST_STRIDE_3 0x4011C4
+
+#define mmDMA_CH_0_TDMA_DST_ROI_BASE_4 0x4011C8
+
+#define mmDMA_CH_0_TDMA_DST_ROI_SIZE_4 0x4011CC
+
+#define mmDMA_CH_0_TDMA_DST_VALID_ELEMENTS_4 0x4011D0
+
+#define mmDMA_CH_0_TDMA_DST_START_OFFSET_4 0x4011D4
+
+#define mmDMA_CH_0_TDMA_DST_STRIDE_4 0x4011D8
+
+#define mmDMA_CH_0_MEM_INIT_BUSY 0x4011FC
+
+#endif /* ASIC_REG_DMA_CH_0_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h
new file mode 100644
index 000000000000..92960ef5e308
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_1_regs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_CH_1_REGS_H_
+#define ASIC_REG_DMA_CH_1_REGS_H_
+
+/*
+ *****************************************
+ * DMA_CH_1 (Prototype: DMA_CH)
+ *****************************************
+ */
+
+#define mmDMA_CH_1_CFG0 0x409000
+
+#define mmDMA_CH_1_CFG1 0x409004
+
+#define mmDMA_CH_1_ERRMSG_ADDR_LO 0x409008
+
+#define mmDMA_CH_1_ERRMSG_ADDR_HI 0x40900C
+
+#define mmDMA_CH_1_ERRMSG_WDATA 0x409010
+
+#define mmDMA_CH_1_RD_COMP_ADDR_LO 0x409014
+
+#define mmDMA_CH_1_RD_COMP_ADDR_HI 0x409018
+
+#define mmDMA_CH_1_RD_COMP_WDATA 0x40901C
+
+#define mmDMA_CH_1_WR_COMP_ADDR_LO 0x409020
+
+#define mmDMA_CH_1_WR_COMP_ADDR_HI 0x409024
+
+#define mmDMA_CH_1_WR_COMP_WDATA 0x409028
+
+#define mmDMA_CH_1_LDMA_SRC_ADDR_LO 0x40902C
+
+#define mmDMA_CH_1_LDMA_SRC_ADDR_HI 0x409030
+
+#define mmDMA_CH_1_LDMA_DST_ADDR_LO 0x409034
+
+#define mmDMA_CH_1_LDMA_DST_ADDR_HI 0x409038
+
+#define mmDMA_CH_1_LDMA_TSIZE 0x40903C
+
+#define mmDMA_CH_1_COMIT_TRANSFER 0x409040
+
+#define mmDMA_CH_1_STS0 0x409044
+
+#define mmDMA_CH_1_STS1 0x409048
+
+#define mmDMA_CH_1_STS2 0x40904C
+
+#define mmDMA_CH_1_STS3 0x409050
+
+#define mmDMA_CH_1_STS4 0x409054
+
+#define mmDMA_CH_1_SRC_ADDR_LO_STS 0x409058
+
+#define mmDMA_CH_1_SRC_ADDR_HI_STS 0x40905C
+
+#define mmDMA_CH_1_SRC_TSIZE_STS 0x409060
+
+#define mmDMA_CH_1_DST_ADDR_LO_STS 0x409064
+
+#define mmDMA_CH_1_DST_ADDR_HI_STS 0x409068
+
+#define mmDMA_CH_1_DST_TSIZE_STS 0x40906C
+
+#define mmDMA_CH_1_RD_RATE_LIM_EN 0x409070
+
+#define mmDMA_CH_1_RD_RATE_LIM_RST_TOKEN 0x409074
+
+#define mmDMA_CH_1_RD_RATE_LIM_SAT 0x409078
+
+#define mmDMA_CH_1_RD_RATE_LIM_TOUT 0x40907C
+
+#define mmDMA_CH_1_WR_RATE_LIM_EN 0x409080
+
+#define mmDMA_CH_1_WR_RATE_LIM_RST_TOKEN 0x409084
+
+#define mmDMA_CH_1_WR_RATE_LIM_SAT 0x409088
+
+#define mmDMA_CH_1_WR_RATE_LIM_TOUT 0x40908C
+
+#define mmDMA_CH_1_CFG2 0x409090
+
+#define mmDMA_CH_1_TDMA_CTL 0x409100
+
+#define mmDMA_CH_1_TDMA_SRC_BASE_ADDR_LO 0x409104
+
+#define mmDMA_CH_1_TDMA_SRC_BASE_ADDR_HI 0x409108
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_BASE_0 0x40910C
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_SIZE_0 0x409110
+
+#define mmDMA_CH_1_TDMA_SRC_VALID_ELEMENTS_0 0x409114
+
+#define mmDMA_CH_1_TDMA_SRC_START_OFFSET_0 0x409118
+
+#define mmDMA_CH_1_TDMA_SRC_STRIDE_0 0x40911C
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_BASE_1 0x409120
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_SIZE_1 0x409124
+
+#define mmDMA_CH_1_TDMA_SRC_VALID_ELEMENTS_1 0x409128
+
+#define mmDMA_CH_1_TDMA_SRC_START_OFFSET_1 0x40912C
+
+#define mmDMA_CH_1_TDMA_SRC_STRIDE_1 0x409130
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_BASE_2 0x409134
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_SIZE_2 0x409138
+
+#define mmDMA_CH_1_TDMA_SRC_VALID_ELEMENTS_2 0x40913C
+
+#define mmDMA_CH_1_TDMA_SRC_START_OFFSET_2 0x409140
+
+#define mmDMA_CH_1_TDMA_SRC_STRIDE_2 0x409144
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_BASE_3 0x409148
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_SIZE_3 0x40914C
+
+#define mmDMA_CH_1_TDMA_SRC_VALID_ELEMENTS_3 0x409150
+
+#define mmDMA_CH_1_TDMA_SRC_START_OFFSET_3 0x409154
+
+#define mmDMA_CH_1_TDMA_SRC_STRIDE_3 0x409158
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_BASE_4 0x40915C
+
+#define mmDMA_CH_1_TDMA_SRC_ROI_SIZE_4 0x409160
+
+#define mmDMA_CH_1_TDMA_SRC_VALID_ELEMENTS_4 0x409164
+
+#define mmDMA_CH_1_TDMA_SRC_START_OFFSET_4 0x409168
+
+#define mmDMA_CH_1_TDMA_SRC_STRIDE_4 0x40916C
+
+#define mmDMA_CH_1_TDMA_DST_BASE_ADDR_LO 0x409170
+
+#define mmDMA_CH_1_TDMA_DST_BASE_ADDR_HI 0x409174
+
+#define mmDMA_CH_1_TDMA_DST_ROI_BASE_0 0x409178
+
+#define mmDMA_CH_1_TDMA_DST_ROI_SIZE_0 0x40917C
+
+#define mmDMA_CH_1_TDMA_DST_VALID_ELEMENTS_0 0x409180
+
+#define mmDMA_CH_1_TDMA_DST_START_OFFSET_0 0x409184
+
+#define mmDMA_CH_1_TDMA_DST_STRIDE_0 0x409188
+
+#define mmDMA_CH_1_TDMA_DST_ROI_BASE_1 0x40918C
+
+#define mmDMA_CH_1_TDMA_DST_ROI_SIZE_1 0x409190
+
+#define mmDMA_CH_1_TDMA_DST_VALID_ELEMENTS_1 0x409194
+
+#define mmDMA_CH_1_TDMA_DST_START_OFFSET_1 0x409198
+
+#define mmDMA_CH_1_TDMA_DST_STRIDE_1 0x40919C
+
+#define mmDMA_CH_1_TDMA_DST_ROI_BASE_2 0x4091A0
+
+#define mmDMA_CH_1_TDMA_DST_ROI_SIZE_2 0x4091A4
+
+#define mmDMA_CH_1_TDMA_DST_VALID_ELEMENTS_2 0x4091A8
+
+#define mmDMA_CH_1_TDMA_DST_START_OFFSET_2 0x4091AC
+
+#define mmDMA_CH_1_TDMA_DST_STRIDE_2 0x4091B0
+
+#define mmDMA_CH_1_TDMA_DST_ROI_BASE_3 0x4091B4
+
+#define mmDMA_CH_1_TDMA_DST_ROI_SIZE_3 0x4091B8
+
+#define mmDMA_CH_1_TDMA_DST_VALID_ELEMENTS_3 0x4091BC
+
+#define mmDMA_CH_1_TDMA_DST_START_OFFSET_3 0x4091C0
+
+#define mmDMA_CH_1_TDMA_DST_STRIDE_3 0x4091C4
+
+#define mmDMA_CH_1_TDMA_DST_ROI_BASE_4 0x4091C8
+
+#define mmDMA_CH_1_TDMA_DST_ROI_SIZE_4 0x4091CC
+
+#define mmDMA_CH_1_TDMA_DST_VALID_ELEMENTS_4 0x4091D0
+
+#define mmDMA_CH_1_TDMA_DST_START_OFFSET_4 0x4091D4
+
+#define mmDMA_CH_1_TDMA_DST_STRIDE_4 0x4091D8
+
+#define mmDMA_CH_1_MEM_INIT_BUSY 0x4091FC
+
+#endif /* ASIC_REG_DMA_CH_1_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h
new file mode 100644
index 000000000000..4e37871a51bb
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_2_regs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_CH_2_REGS_H_
+#define ASIC_REG_DMA_CH_2_REGS_H_
+
+/*
+ *****************************************
+ * DMA_CH_2 (Prototype: DMA_CH)
+ *****************************************
+ */
+
+#define mmDMA_CH_2_CFG0 0x411000
+
+#define mmDMA_CH_2_CFG1 0x411004
+
+#define mmDMA_CH_2_ERRMSG_ADDR_LO 0x411008
+
+#define mmDMA_CH_2_ERRMSG_ADDR_HI 0x41100C
+
+#define mmDMA_CH_2_ERRMSG_WDATA 0x411010
+
+#define mmDMA_CH_2_RD_COMP_ADDR_LO 0x411014
+
+#define mmDMA_CH_2_RD_COMP_ADDR_HI 0x411018
+
+#define mmDMA_CH_2_RD_COMP_WDATA 0x41101C
+
+#define mmDMA_CH_2_WR_COMP_ADDR_LO 0x411020
+
+#define mmDMA_CH_2_WR_COMP_ADDR_HI 0x411024
+
+#define mmDMA_CH_2_WR_COMP_WDATA 0x411028
+
+#define mmDMA_CH_2_LDMA_SRC_ADDR_LO 0x41102C
+
+#define mmDMA_CH_2_LDMA_SRC_ADDR_HI 0x411030
+
+#define mmDMA_CH_2_LDMA_DST_ADDR_LO 0x411034
+
+#define mmDMA_CH_2_LDMA_DST_ADDR_HI 0x411038
+
+#define mmDMA_CH_2_LDMA_TSIZE 0x41103C
+
+#define mmDMA_CH_2_COMIT_TRANSFER 0x411040
+
+#define mmDMA_CH_2_STS0 0x411044
+
+#define mmDMA_CH_2_STS1 0x411048
+
+#define mmDMA_CH_2_STS2 0x41104C
+
+#define mmDMA_CH_2_STS3 0x411050
+
+#define mmDMA_CH_2_STS4 0x411054
+
+#define mmDMA_CH_2_SRC_ADDR_LO_STS 0x411058
+
+#define mmDMA_CH_2_SRC_ADDR_HI_STS 0x41105C
+
+#define mmDMA_CH_2_SRC_TSIZE_STS 0x411060
+
+#define mmDMA_CH_2_DST_ADDR_LO_STS 0x411064
+
+#define mmDMA_CH_2_DST_ADDR_HI_STS 0x411068
+
+#define mmDMA_CH_2_DST_TSIZE_STS 0x41106C
+
+#define mmDMA_CH_2_RD_RATE_LIM_EN 0x411070
+
+#define mmDMA_CH_2_RD_RATE_LIM_RST_TOKEN 0x411074
+
+#define mmDMA_CH_2_RD_RATE_LIM_SAT 0x411078
+
+#define mmDMA_CH_2_RD_RATE_LIM_TOUT 0x41107C
+
+#define mmDMA_CH_2_WR_RATE_LIM_EN 0x411080
+
+#define mmDMA_CH_2_WR_RATE_LIM_RST_TOKEN 0x411084
+
+#define mmDMA_CH_2_WR_RATE_LIM_SAT 0x411088
+
+#define mmDMA_CH_2_WR_RATE_LIM_TOUT 0x41108C
+
+#define mmDMA_CH_2_CFG2 0x411090
+
+#define mmDMA_CH_2_TDMA_CTL 0x411100
+
+#define mmDMA_CH_2_TDMA_SRC_BASE_ADDR_LO 0x411104
+
+#define mmDMA_CH_2_TDMA_SRC_BASE_ADDR_HI 0x411108
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_BASE_0 0x41110C
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_SIZE_0 0x411110
+
+#define mmDMA_CH_2_TDMA_SRC_VALID_ELEMENTS_0 0x411114
+
+#define mmDMA_CH_2_TDMA_SRC_START_OFFSET_0 0x411118
+
+#define mmDMA_CH_2_TDMA_SRC_STRIDE_0 0x41111C
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_BASE_1 0x411120
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_SIZE_1 0x411124
+
+#define mmDMA_CH_2_TDMA_SRC_VALID_ELEMENTS_1 0x411128
+
+#define mmDMA_CH_2_TDMA_SRC_START_OFFSET_1 0x41112C
+
+#define mmDMA_CH_2_TDMA_SRC_STRIDE_1 0x411130
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_BASE_2 0x411134
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_SIZE_2 0x411138
+
+#define mmDMA_CH_2_TDMA_SRC_VALID_ELEMENTS_2 0x41113C
+
+#define mmDMA_CH_2_TDMA_SRC_START_OFFSET_2 0x411140
+
+#define mmDMA_CH_2_TDMA_SRC_STRIDE_2 0x411144
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_BASE_3 0x411148
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_SIZE_3 0x41114C
+
+#define mmDMA_CH_2_TDMA_SRC_VALID_ELEMENTS_3 0x411150
+
+#define mmDMA_CH_2_TDMA_SRC_START_OFFSET_3 0x411154
+
+#define mmDMA_CH_2_TDMA_SRC_STRIDE_3 0x411158
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_BASE_4 0x41115C
+
+#define mmDMA_CH_2_TDMA_SRC_ROI_SIZE_4 0x411160
+
+#define mmDMA_CH_2_TDMA_SRC_VALID_ELEMENTS_4 0x411164
+
+#define mmDMA_CH_2_TDMA_SRC_START_OFFSET_4 0x411168
+
+#define mmDMA_CH_2_TDMA_SRC_STRIDE_4 0x41116C
+
+#define mmDMA_CH_2_TDMA_DST_BASE_ADDR_LO 0x411170
+
+#define mmDMA_CH_2_TDMA_DST_BASE_ADDR_HI 0x411174
+
+#define mmDMA_CH_2_TDMA_DST_ROI_BASE_0 0x411178
+
+#define mmDMA_CH_2_TDMA_DST_ROI_SIZE_0 0x41117C
+
+#define mmDMA_CH_2_TDMA_DST_VALID_ELEMENTS_0 0x411180
+
+#define mmDMA_CH_2_TDMA_DST_START_OFFSET_0 0x411184
+
+#define mmDMA_CH_2_TDMA_DST_STRIDE_0 0x411188
+
+#define mmDMA_CH_2_TDMA_DST_ROI_BASE_1 0x41118C
+
+#define mmDMA_CH_2_TDMA_DST_ROI_SIZE_1 0x411190
+
+#define mmDMA_CH_2_TDMA_DST_VALID_ELEMENTS_1 0x411194
+
+#define mmDMA_CH_2_TDMA_DST_START_OFFSET_1 0x411198
+
+#define mmDMA_CH_2_TDMA_DST_STRIDE_1 0x41119C
+
+#define mmDMA_CH_2_TDMA_DST_ROI_BASE_2 0x4111A0
+
+#define mmDMA_CH_2_TDMA_DST_ROI_SIZE_2 0x4111A4
+
+#define mmDMA_CH_2_TDMA_DST_VALID_ELEMENTS_2 0x4111A8
+
+#define mmDMA_CH_2_TDMA_DST_START_OFFSET_2 0x4111AC
+
+#define mmDMA_CH_2_TDMA_DST_STRIDE_2 0x4111B0
+
+#define mmDMA_CH_2_TDMA_DST_ROI_BASE_3 0x4111B4
+
+#define mmDMA_CH_2_TDMA_DST_ROI_SIZE_3 0x4111B8
+
+#define mmDMA_CH_2_TDMA_DST_VALID_ELEMENTS_3 0x4111BC
+
+#define mmDMA_CH_2_TDMA_DST_START_OFFSET_3 0x4111C0
+
+#define mmDMA_CH_2_TDMA_DST_STRIDE_3 0x4111C4
+
+#define mmDMA_CH_2_TDMA_DST_ROI_BASE_4 0x4111C8
+
+#define mmDMA_CH_2_TDMA_DST_ROI_SIZE_4 0x4111CC
+
+#define mmDMA_CH_2_TDMA_DST_VALID_ELEMENTS_4 0x4111D0
+
+#define mmDMA_CH_2_TDMA_DST_START_OFFSET_4 0x4111D4
+
+#define mmDMA_CH_2_TDMA_DST_STRIDE_4 0x4111D8
+
+#define mmDMA_CH_2_MEM_INIT_BUSY 0x4111FC
+
+#endif /* ASIC_REG_DMA_CH_2_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h
new file mode 100644
index 000000000000..a2d6aeb32a18
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_3_regs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_CH_3_REGS_H_
+#define ASIC_REG_DMA_CH_3_REGS_H_
+
+/*
+ *****************************************
+ * DMA_CH_3 (Prototype: DMA_CH)
+ *****************************************
+ */
+
+#define mmDMA_CH_3_CFG0 0x419000
+
+#define mmDMA_CH_3_CFG1 0x419004
+
+#define mmDMA_CH_3_ERRMSG_ADDR_LO 0x419008
+
+#define mmDMA_CH_3_ERRMSG_ADDR_HI 0x41900C
+
+#define mmDMA_CH_3_ERRMSG_WDATA 0x419010
+
+#define mmDMA_CH_3_RD_COMP_ADDR_LO 0x419014
+
+#define mmDMA_CH_3_RD_COMP_ADDR_HI 0x419018
+
+#define mmDMA_CH_3_RD_COMP_WDATA 0x41901C
+
+#define mmDMA_CH_3_WR_COMP_ADDR_LO 0x419020
+
+#define mmDMA_CH_3_WR_COMP_ADDR_HI 0x419024
+
+#define mmDMA_CH_3_WR_COMP_WDATA 0x419028
+
+#define mmDMA_CH_3_LDMA_SRC_ADDR_LO 0x41902C
+
+#define mmDMA_CH_3_LDMA_SRC_ADDR_HI 0x419030
+
+#define mmDMA_CH_3_LDMA_DST_ADDR_LO 0x419034
+
+#define mmDMA_CH_3_LDMA_DST_ADDR_HI 0x419038
+
+#define mmDMA_CH_3_LDMA_TSIZE 0x41903C
+
+#define mmDMA_CH_3_COMIT_TRANSFER 0x419040
+
+#define mmDMA_CH_3_STS0 0x419044
+
+#define mmDMA_CH_3_STS1 0x419048
+
+#define mmDMA_CH_3_STS2 0x41904C
+
+#define mmDMA_CH_3_STS3 0x419050
+
+#define mmDMA_CH_3_STS4 0x419054
+
+#define mmDMA_CH_3_SRC_ADDR_LO_STS 0x419058
+
+#define mmDMA_CH_3_SRC_ADDR_HI_STS 0x41905C
+
+#define mmDMA_CH_3_SRC_TSIZE_STS 0x419060
+
+#define mmDMA_CH_3_DST_ADDR_LO_STS 0x419064
+
+#define mmDMA_CH_3_DST_ADDR_HI_STS 0x419068
+
+#define mmDMA_CH_3_DST_TSIZE_STS 0x41906C
+
+#define mmDMA_CH_3_RD_RATE_LIM_EN 0x419070
+
+#define mmDMA_CH_3_RD_RATE_LIM_RST_TOKEN 0x419074
+
+#define mmDMA_CH_3_RD_RATE_LIM_SAT 0x419078
+
+#define mmDMA_CH_3_RD_RATE_LIM_TOUT 0x41907C
+
+#define mmDMA_CH_3_WR_RATE_LIM_EN 0x419080
+
+#define mmDMA_CH_3_WR_RATE_LIM_RST_TOKEN 0x419084
+
+#define mmDMA_CH_3_WR_RATE_LIM_SAT 0x419088
+
+#define mmDMA_CH_3_WR_RATE_LIM_TOUT 0x41908C
+
+#define mmDMA_CH_3_CFG2 0x419090
+
+#define mmDMA_CH_3_TDMA_CTL 0x419100
+
+#define mmDMA_CH_3_TDMA_SRC_BASE_ADDR_LO 0x419104
+
+#define mmDMA_CH_3_TDMA_SRC_BASE_ADDR_HI 0x419108
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_BASE_0 0x41910C
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_SIZE_0 0x419110
+
+#define mmDMA_CH_3_TDMA_SRC_VALID_ELEMENTS_0 0x419114
+
+#define mmDMA_CH_3_TDMA_SRC_START_OFFSET_0 0x419118
+
+#define mmDMA_CH_3_TDMA_SRC_STRIDE_0 0x41911C
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_BASE_1 0x419120
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_SIZE_1 0x419124
+
+#define mmDMA_CH_3_TDMA_SRC_VALID_ELEMENTS_1 0x419128
+
+#define mmDMA_CH_3_TDMA_SRC_START_OFFSET_1 0x41912C
+
+#define mmDMA_CH_3_TDMA_SRC_STRIDE_1 0x419130
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_BASE_2 0x419134
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_SIZE_2 0x419138
+
+#define mmDMA_CH_3_TDMA_SRC_VALID_ELEMENTS_2 0x41913C
+
+#define mmDMA_CH_3_TDMA_SRC_START_OFFSET_2 0x419140
+
+#define mmDMA_CH_3_TDMA_SRC_STRIDE_2 0x419144
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_BASE_3 0x419148
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_SIZE_3 0x41914C
+
+#define mmDMA_CH_3_TDMA_SRC_VALID_ELEMENTS_3 0x419150
+
+#define mmDMA_CH_3_TDMA_SRC_START_OFFSET_3 0x419154
+
+#define mmDMA_CH_3_TDMA_SRC_STRIDE_3 0x419158
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_BASE_4 0x41915C
+
+#define mmDMA_CH_3_TDMA_SRC_ROI_SIZE_4 0x419160
+
+#define mmDMA_CH_3_TDMA_SRC_VALID_ELEMENTS_4 0x419164
+
+#define mmDMA_CH_3_TDMA_SRC_START_OFFSET_4 0x419168
+
+#define mmDMA_CH_3_TDMA_SRC_STRIDE_4 0x41916C
+
+#define mmDMA_CH_3_TDMA_DST_BASE_ADDR_LO 0x419170
+
+#define mmDMA_CH_3_TDMA_DST_BASE_ADDR_HI 0x419174
+
+#define mmDMA_CH_3_TDMA_DST_ROI_BASE_0 0x419178
+
+#define mmDMA_CH_3_TDMA_DST_ROI_SIZE_0 0x41917C
+
+#define mmDMA_CH_3_TDMA_DST_VALID_ELEMENTS_0 0x419180
+
+#define mmDMA_CH_3_TDMA_DST_START_OFFSET_0 0x419184
+
+#define mmDMA_CH_3_TDMA_DST_STRIDE_0 0x419188
+
+#define mmDMA_CH_3_TDMA_DST_ROI_BASE_1 0x41918C
+
+#define mmDMA_CH_3_TDMA_DST_ROI_SIZE_1 0x419190
+
+#define mmDMA_CH_3_TDMA_DST_VALID_ELEMENTS_1 0x419194
+
+#define mmDMA_CH_3_TDMA_DST_START_OFFSET_1 0x419198
+
+#define mmDMA_CH_3_TDMA_DST_STRIDE_1 0x41919C
+
+#define mmDMA_CH_3_TDMA_DST_ROI_BASE_2 0x4191A0
+
+#define mmDMA_CH_3_TDMA_DST_ROI_SIZE_2 0x4191A4
+
+#define mmDMA_CH_3_TDMA_DST_VALID_ELEMENTS_2 0x4191A8
+
+#define mmDMA_CH_3_TDMA_DST_START_OFFSET_2 0x4191AC
+
+#define mmDMA_CH_3_TDMA_DST_STRIDE_2 0x4191B0
+
+#define mmDMA_CH_3_TDMA_DST_ROI_BASE_3 0x4191B4
+
+#define mmDMA_CH_3_TDMA_DST_ROI_SIZE_3 0x4191B8
+
+#define mmDMA_CH_3_TDMA_DST_VALID_ELEMENTS_3 0x4191BC
+
+#define mmDMA_CH_3_TDMA_DST_START_OFFSET_3 0x4191C0
+
+#define mmDMA_CH_3_TDMA_DST_STRIDE_3 0x4191C4
+
+#define mmDMA_CH_3_TDMA_DST_ROI_BASE_4 0x4191C8
+
+#define mmDMA_CH_3_TDMA_DST_ROI_SIZE_4 0x4191CC
+
+#define mmDMA_CH_3_TDMA_DST_VALID_ELEMENTS_4 0x4191D0
+
+#define mmDMA_CH_3_TDMA_DST_START_OFFSET_4 0x4191D4
+
+#define mmDMA_CH_3_TDMA_DST_STRIDE_4 0x4191D8
+
+#define mmDMA_CH_3_MEM_INIT_BUSY 0x4191FC
+
+#endif /* ASIC_REG_DMA_CH_3_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h
new file mode 100644
index 000000000000..400d6fd3acf5
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_ch_4_regs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_CH_4_REGS_H_
+#define ASIC_REG_DMA_CH_4_REGS_H_
+
+/*
+ *****************************************
+ * DMA_CH_4 (Prototype: DMA_CH)
+ *****************************************
+ */
+
+#define mmDMA_CH_4_CFG0 0x421000
+
+#define mmDMA_CH_4_CFG1 0x421004
+
+#define mmDMA_CH_4_ERRMSG_ADDR_LO 0x421008
+
+#define mmDMA_CH_4_ERRMSG_ADDR_HI 0x42100C
+
+#define mmDMA_CH_4_ERRMSG_WDATA 0x421010
+
+#define mmDMA_CH_4_RD_COMP_ADDR_LO 0x421014
+
+#define mmDMA_CH_4_RD_COMP_ADDR_HI 0x421018
+
+#define mmDMA_CH_4_RD_COMP_WDATA 0x42101C
+
+#define mmDMA_CH_4_WR_COMP_ADDR_LO 0x421020
+
+#define mmDMA_CH_4_WR_COMP_ADDR_HI 0x421024
+
+#define mmDMA_CH_4_WR_COMP_WDATA 0x421028
+
+#define mmDMA_CH_4_LDMA_SRC_ADDR_LO 0x42102C
+
+#define mmDMA_CH_4_LDMA_SRC_ADDR_HI 0x421030
+
+#define mmDMA_CH_4_LDMA_DST_ADDR_LO 0x421034
+
+#define mmDMA_CH_4_LDMA_DST_ADDR_HI 0x421038
+
+#define mmDMA_CH_4_LDMA_TSIZE 0x42103C
+
+#define mmDMA_CH_4_COMIT_TRANSFER 0x421040
+
+#define mmDMA_CH_4_STS0 0x421044
+
+#define mmDMA_CH_4_STS1 0x421048
+
+#define mmDMA_CH_4_STS2 0x42104C
+
+#define mmDMA_CH_4_STS3 0x421050
+
+#define mmDMA_CH_4_STS4 0x421054
+
+#define mmDMA_CH_4_SRC_ADDR_LO_STS 0x421058
+
+#define mmDMA_CH_4_SRC_ADDR_HI_STS 0x42105C
+
+#define mmDMA_CH_4_SRC_TSIZE_STS 0x421060
+
+#define mmDMA_CH_4_DST_ADDR_LO_STS 0x421064
+
+#define mmDMA_CH_4_DST_ADDR_HI_STS 0x421068
+
+#define mmDMA_CH_4_DST_TSIZE_STS 0x42106C
+
+#define mmDMA_CH_4_RD_RATE_LIM_EN 0x421070
+
+#define mmDMA_CH_4_RD_RATE_LIM_RST_TOKEN 0x421074
+
+#define mmDMA_CH_4_RD_RATE_LIM_SAT 0x421078
+
+#define mmDMA_CH_4_RD_RATE_LIM_TOUT 0x42107C
+
+#define mmDMA_CH_4_WR_RATE_LIM_EN 0x421080
+
+#define mmDMA_CH_4_WR_RATE_LIM_RST_TOKEN 0x421084
+
+#define mmDMA_CH_4_WR_RATE_LIM_SAT 0x421088
+
+#define mmDMA_CH_4_WR_RATE_LIM_TOUT 0x42108C
+
+#define mmDMA_CH_4_CFG2 0x421090
+
+#define mmDMA_CH_4_TDMA_CTL 0x421100
+
+#define mmDMA_CH_4_TDMA_SRC_BASE_ADDR_LO 0x421104
+
+#define mmDMA_CH_4_TDMA_SRC_BASE_ADDR_HI 0x421108
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_BASE_0 0x42110C
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_SIZE_0 0x421110
+
+#define mmDMA_CH_4_TDMA_SRC_VALID_ELEMENTS_0 0x421114
+
+#define mmDMA_CH_4_TDMA_SRC_START_OFFSET_0 0x421118
+
+#define mmDMA_CH_4_TDMA_SRC_STRIDE_0 0x42111C
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_BASE_1 0x421120
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_SIZE_1 0x421124
+
+#define mmDMA_CH_4_TDMA_SRC_VALID_ELEMENTS_1 0x421128
+
+#define mmDMA_CH_4_TDMA_SRC_START_OFFSET_1 0x42112C
+
+#define mmDMA_CH_4_TDMA_SRC_STRIDE_1 0x421130
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_BASE_2 0x421134
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_SIZE_2 0x421138
+
+#define mmDMA_CH_4_TDMA_SRC_VALID_ELEMENTS_2 0x42113C
+
+#define mmDMA_CH_4_TDMA_SRC_START_OFFSET_2 0x421140
+
+#define mmDMA_CH_4_TDMA_SRC_STRIDE_2 0x421144
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_BASE_3 0x421148
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_SIZE_3 0x42114C
+
+#define mmDMA_CH_4_TDMA_SRC_VALID_ELEMENTS_3 0x421150
+
+#define mmDMA_CH_4_TDMA_SRC_START_OFFSET_3 0x421154
+
+#define mmDMA_CH_4_TDMA_SRC_STRIDE_3 0x421158
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_BASE_4 0x42115C
+
+#define mmDMA_CH_4_TDMA_SRC_ROI_SIZE_4 0x421160
+
+#define mmDMA_CH_4_TDMA_SRC_VALID_ELEMENTS_4 0x421164
+
+#define mmDMA_CH_4_TDMA_SRC_START_OFFSET_4 0x421168
+
+#define mmDMA_CH_4_TDMA_SRC_STRIDE_4 0x42116C
+
+#define mmDMA_CH_4_TDMA_DST_BASE_ADDR_LO 0x421170
+
+#define mmDMA_CH_4_TDMA_DST_BASE_ADDR_HI 0x421174
+
+#define mmDMA_CH_4_TDMA_DST_ROI_BASE_0 0x421178
+
+#define mmDMA_CH_4_TDMA_DST_ROI_SIZE_0 0x42117C
+
+#define mmDMA_CH_4_TDMA_DST_VALID_ELEMENTS_0 0x421180
+
+#define mmDMA_CH_4_TDMA_DST_START_OFFSET_0 0x421184
+
+#define mmDMA_CH_4_TDMA_DST_STRIDE_0 0x421188
+
+#define mmDMA_CH_4_TDMA_DST_ROI_BASE_1 0x42118C
+
+#define mmDMA_CH_4_TDMA_DST_ROI_SIZE_1 0x421190
+
+#define mmDMA_CH_4_TDMA_DST_VALID_ELEMENTS_1 0x421194
+
+#define mmDMA_CH_4_TDMA_DST_START_OFFSET_1 0x421198
+
+#define mmDMA_CH_4_TDMA_DST_STRIDE_1 0x42119C
+
+#define mmDMA_CH_4_TDMA_DST_ROI_BASE_2 0x4211A0
+
+#define mmDMA_CH_4_TDMA_DST_ROI_SIZE_2 0x4211A4
+
+#define mmDMA_CH_4_TDMA_DST_VALID_ELEMENTS_2 0x4211A8
+
+#define mmDMA_CH_4_TDMA_DST_START_OFFSET_2 0x4211AC
+
+#define mmDMA_CH_4_TDMA_DST_STRIDE_2 0x4211B0
+
+#define mmDMA_CH_4_TDMA_DST_ROI_BASE_3 0x4211B4
+
+#define mmDMA_CH_4_TDMA_DST_ROI_SIZE_3 0x4211B8
+
+#define mmDMA_CH_4_TDMA_DST_VALID_ELEMENTS_3 0x4211BC
+
+#define mmDMA_CH_4_TDMA_DST_START_OFFSET_3 0x4211C0
+
+#define mmDMA_CH_4_TDMA_DST_STRIDE_3 0x4211C4
+
+#define mmDMA_CH_4_TDMA_DST_ROI_BASE_4 0x4211C8
+
+#define mmDMA_CH_4_TDMA_DST_ROI_SIZE_4 0x4211CC
+
+#define mmDMA_CH_4_TDMA_DST_VALID_ELEMENTS_4 0x4211D0
+
+#define mmDMA_CH_4_TDMA_DST_START_OFFSET_4 0x4211D4
+
+#define mmDMA_CH_4_TDMA_DST_STRIDE_4 0x4211D8
+
+#define mmDMA_CH_4_MEM_INIT_BUSY 0x4211FC
+
+#endif /* ASIC_REG_DMA_CH_4_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h
new file mode 100644
index 000000000000..8d965443c51e
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_masks.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_MACRO_MASKS_H_
+#define ASIC_REG_DMA_MACRO_MASKS_H_
+
+/*
+ *****************************************
+ * DMA_MACRO (Prototype: DMA_MACRO)
+ *****************************************
+ */
+
+/* DMA_MACRO_LBW_RANGE_HIT_BLOCK */
+#define DMA_MACRO_LBW_RANGE_HIT_BLOCK_R_SHIFT 0
+#define DMA_MACRO_LBW_RANGE_HIT_BLOCK_R_MASK 0xFFFF
+
+/* DMA_MACRO_LBW_RANGE_MASK */
+#define DMA_MACRO_LBW_RANGE_MASK_R_SHIFT 0
+#define DMA_MACRO_LBW_RANGE_MASK_R_MASK 0x3FFFFFF
+
+/* DMA_MACRO_LBW_RANGE_BASE */
+#define DMA_MACRO_LBW_RANGE_BASE_R_SHIFT 0
+#define DMA_MACRO_LBW_RANGE_BASE_R_MASK 0x3FFFFFF
+
+/* DMA_MACRO_HBW_RANGE_HIT_BLOCK */
+#define DMA_MACRO_HBW_RANGE_HIT_BLOCK_R_SHIFT 0
+#define DMA_MACRO_HBW_RANGE_HIT_BLOCK_R_MASK 0xFF
+
+/* DMA_MACRO_HBW_RANGE_MASK_49_32 */
+#define DMA_MACRO_HBW_RANGE_MASK_49_32_R_SHIFT 0
+#define DMA_MACRO_HBW_RANGE_MASK_49_32_R_MASK 0x3FFFF
+
+/* DMA_MACRO_HBW_RANGE_MASK_31_0 */
+#define DMA_MACRO_HBW_RANGE_MASK_31_0_R_SHIFT 0
+#define DMA_MACRO_HBW_RANGE_MASK_31_0_R_MASK 0xFFFFFFFF
+
+/* DMA_MACRO_HBW_RANGE_BASE_49_32 */
+#define DMA_MACRO_HBW_RANGE_BASE_49_32_R_SHIFT 0
+#define DMA_MACRO_HBW_RANGE_BASE_49_32_R_MASK 0x3FFFF
+
+/* DMA_MACRO_HBW_RANGE_BASE_31_0 */
+#define DMA_MACRO_HBW_RANGE_BASE_31_0_R_SHIFT 0
+#define DMA_MACRO_HBW_RANGE_BASE_31_0_R_MASK 0xFFFFFFFF
+
+/* DMA_MACRO_WRITE_EN */
+#define DMA_MACRO_WRITE_EN_R_SHIFT 0
+#define DMA_MACRO_WRITE_EN_R_MASK 0x1
+
+/* DMA_MACRO_WRITE_CREDIT */
+#define DMA_MACRO_WRITE_CREDIT_R_SHIFT 0
+#define DMA_MACRO_WRITE_CREDIT_R_MASK 0x3FF
+
+/* DMA_MACRO_READ_EN */
+#define DMA_MACRO_READ_EN_R_SHIFT 0
+#define DMA_MACRO_READ_EN_R_MASK 0x1
+
+/* DMA_MACRO_READ_CREDIT */
+#define DMA_MACRO_READ_CREDIT_R_SHIFT 0
+#define DMA_MACRO_READ_CREDIT_R_MASK 0x3FF
+
+/* DMA_MACRO_SRAM_BUSY */
+
+/* DMA_MACRO_RAZWI_LBW_WT_VLD */
+#define DMA_MACRO_RAZWI_LBW_WT_VLD_R_SHIFT 0
+#define DMA_MACRO_RAZWI_LBW_WT_VLD_R_MASK 0x1
+
+/* DMA_MACRO_RAZWI_LBW_WT_ID */
+#define DMA_MACRO_RAZWI_LBW_WT_ID_R_SHIFT 0
+#define DMA_MACRO_RAZWI_LBW_WT_ID_R_MASK 0x7FFF
+
+/* DMA_MACRO_RAZWI_LBW_RD_VLD */
+#define DMA_MACRO_RAZWI_LBW_RD_VLD_R_SHIFT 0
+#define DMA_MACRO_RAZWI_LBW_RD_VLD_R_MASK 0x1
+
+/* DMA_MACRO_RAZWI_LBW_RD_ID */
+#define DMA_MACRO_RAZWI_LBW_RD_ID_R_SHIFT 0
+#define DMA_MACRO_RAZWI_LBW_RD_ID_R_MASK 0x7FFF
+
+/* DMA_MACRO_RAZWI_HBW_WT_VLD */
+#define DMA_MACRO_RAZWI_HBW_WT_VLD_R_SHIFT 0
+#define DMA_MACRO_RAZWI_HBW_WT_VLD_R_MASK 0x1
+
+/* DMA_MACRO_RAZWI_HBW_WT_ID */
+#define DMA_MACRO_RAZWI_HBW_WT_ID_R_SHIFT 0
+#define DMA_MACRO_RAZWI_HBW_WT_ID_R_MASK 0x1FFFFFFF
+
+/* DMA_MACRO_RAZWI_HBW_RD_VLD */
+#define DMA_MACRO_RAZWI_HBW_RD_VLD_R_SHIFT 0
+#define DMA_MACRO_RAZWI_HBW_RD_VLD_R_MASK 0x1
+
+/* DMA_MACRO_RAZWI_HBW_RD_ID */
+#define DMA_MACRO_RAZWI_HBW_RD_ID_R_SHIFT 0
+#define DMA_MACRO_RAZWI_HBW_RD_ID_R_MASK 0x1FFFFFFF
+
+#endif /* ASIC_REG_DMA_MACRO_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h
new file mode 100644
index 000000000000..8bfcb001189d
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_macro_regs.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_MACRO_REGS_H_
+#define ASIC_REG_DMA_MACRO_REGS_H_
+
+/*
+ *****************************************
+ * DMA_MACRO (Prototype: DMA_MACRO)
+ *****************************************
+ */
+
+#define mmDMA_MACRO_LBW_RANGE_HIT_BLOCK 0x4B0000
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_0 0x4B0004
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_1 0x4B0008
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_2 0x4B000C
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_3 0x4B0010
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_4 0x4B0014
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_5 0x4B0018
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_6 0x4B001C
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_7 0x4B0020
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_8 0x4B0024
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_9 0x4B0028
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_10 0x4B002C
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_11 0x4B0030
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_12 0x4B0034
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_13 0x4B0038
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_14 0x4B003C
+
+#define mmDMA_MACRO_LBW_RANGE_MASK_15 0x4B0040
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_0 0x4B0044
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_1 0x4B0048
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_2 0x4B004C
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_3 0x4B0050
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_4 0x4B0054
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_5 0x4B0058
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_6 0x4B005C
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_7 0x4B0060
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_8 0x4B0064
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_9 0x4B0068
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_10 0x4B006C
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_11 0x4B0070
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_12 0x4B0074
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_13 0x4B0078
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_14 0x4B007C
+
+#define mmDMA_MACRO_LBW_RANGE_BASE_15 0x4B0080
+
+#define mmDMA_MACRO_HBW_RANGE_HIT_BLOCK 0x4B0084
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_0 0x4B00A8
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_1 0x4B00AC
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_2 0x4B00B0
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_3 0x4B00B4
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_4 0x4B00B8
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_5 0x4B00BC
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_6 0x4B00C0
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_49_32_7 0x4B00C4
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_0 0x4B00C8
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_1 0x4B00CC
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_2 0x4B00D0
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_3 0x4B00D4
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_4 0x4B00D8
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_5 0x4B00DC
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_6 0x4B00E0
+
+#define mmDMA_MACRO_HBW_RANGE_MASK_31_0_7 0x4B00E4
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_0 0x4B00E8
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_1 0x4B00EC
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_2 0x4B00F0
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_3 0x4B00F4
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_4 0x4B00F8
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_5 0x4B00FC
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_6 0x4B0100
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_49_32_7 0x4B0104
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_0 0x4B0108
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_1 0x4B010C
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_2 0x4B0110
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_3 0x4B0114
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_4 0x4B0118
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_5 0x4B011C
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_6 0x4B0120
+
+#define mmDMA_MACRO_HBW_RANGE_BASE_31_0_7 0x4B0124
+
+#define mmDMA_MACRO_WRITE_EN 0x4B0128
+
+#define mmDMA_MACRO_WRITE_CREDIT 0x4B012C
+
+#define mmDMA_MACRO_READ_EN 0x4B0130
+
+#define mmDMA_MACRO_READ_CREDIT 0x4B0134
+
+#define mmDMA_MACRO_SRAM_BUSY 0x4B0138
+
+#define mmDMA_MACRO_RAZWI_LBW_WT_VLD 0x4B013C
+
+#define mmDMA_MACRO_RAZWI_LBW_WT_ID 0x4B0140
+
+#define mmDMA_MACRO_RAZWI_LBW_RD_VLD 0x4B0144
+
+#define mmDMA_MACRO_RAZWI_LBW_RD_ID 0x4B0148
+
+#define mmDMA_MACRO_RAZWI_HBW_WT_VLD 0x4B014C
+
+#define mmDMA_MACRO_RAZWI_HBW_WT_ID 0x4B0150
+
+#define mmDMA_MACRO_RAZWI_HBW_RD_VLD 0x4B0154
+
+#define mmDMA_MACRO_RAZWI_HBW_RD_ID 0x4B0158
+
+#endif /* ASIC_REG_DMA_MACRO_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h
new file mode 100644
index 000000000000..9f33f351a3c1
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_masks.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_NRTR_MASKS_H_
+#define ASIC_REG_DMA_NRTR_MASKS_H_
+
+/*
+ *****************************************
+ * DMA_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+/* DMA_NRTR_HBW_MAX_CRED */
+#define DMA_NRTR_HBW_MAX_CRED_WR_RQ_SHIFT 0
+#define DMA_NRTR_HBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define DMA_NRTR_HBW_MAX_CRED_WR_RS_SHIFT 8
+#define DMA_NRTR_HBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define DMA_NRTR_HBW_MAX_CRED_RD_RQ_SHIFT 16
+#define DMA_NRTR_HBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define DMA_NRTR_HBW_MAX_CRED_RD_RS_SHIFT 24
+#define DMA_NRTR_HBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* DMA_NRTR_LBW_MAX_CRED */
+#define DMA_NRTR_LBW_MAX_CRED_WR_RQ_SHIFT 0
+#define DMA_NRTR_LBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define DMA_NRTR_LBW_MAX_CRED_WR_RS_SHIFT 8
+#define DMA_NRTR_LBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define DMA_NRTR_LBW_MAX_CRED_RD_RQ_SHIFT 16
+#define DMA_NRTR_LBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define DMA_NRTR_LBW_MAX_CRED_RD_RS_SHIFT 24
+#define DMA_NRTR_LBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* DMA_NRTR_DBG_E_ARB */
+#define DMA_NRTR_DBG_E_ARB_W_SHIFT 0
+#define DMA_NRTR_DBG_E_ARB_W_MASK 0x7
+#define DMA_NRTR_DBG_E_ARB_S_SHIFT 8
+#define DMA_NRTR_DBG_E_ARB_S_MASK 0x700
+#define DMA_NRTR_DBG_E_ARB_N_SHIFT 16
+#define DMA_NRTR_DBG_E_ARB_N_MASK 0x70000
+#define DMA_NRTR_DBG_E_ARB_L_SHIFT 24
+#define DMA_NRTR_DBG_E_ARB_L_MASK 0x7000000
+
+/* DMA_NRTR_DBG_W_ARB */
+#define DMA_NRTR_DBG_W_ARB_E_SHIFT 0
+#define DMA_NRTR_DBG_W_ARB_E_MASK 0x7
+#define DMA_NRTR_DBG_W_ARB_S_SHIFT 8
+#define DMA_NRTR_DBG_W_ARB_S_MASK 0x700
+#define DMA_NRTR_DBG_W_ARB_N_SHIFT 16
+#define DMA_NRTR_DBG_W_ARB_N_MASK 0x70000
+#define DMA_NRTR_DBG_W_ARB_L_SHIFT 24
+#define DMA_NRTR_DBG_W_ARB_L_MASK 0x7000000
+
+/* DMA_NRTR_DBG_N_ARB */
+#define DMA_NRTR_DBG_N_ARB_W_SHIFT 0
+#define DMA_NRTR_DBG_N_ARB_W_MASK 0x7
+#define DMA_NRTR_DBG_N_ARB_E_SHIFT 8
+#define DMA_NRTR_DBG_N_ARB_E_MASK 0x700
+#define DMA_NRTR_DBG_N_ARB_S_SHIFT 16
+#define DMA_NRTR_DBG_N_ARB_S_MASK 0x70000
+#define DMA_NRTR_DBG_N_ARB_L_SHIFT 24
+#define DMA_NRTR_DBG_N_ARB_L_MASK 0x7000000
+
+/* DMA_NRTR_DBG_S_ARB */
+#define DMA_NRTR_DBG_S_ARB_W_SHIFT 0
+#define DMA_NRTR_DBG_S_ARB_W_MASK 0x7
+#define DMA_NRTR_DBG_S_ARB_E_SHIFT 8
+#define DMA_NRTR_DBG_S_ARB_E_MASK 0x700
+#define DMA_NRTR_DBG_S_ARB_N_SHIFT 16
+#define DMA_NRTR_DBG_S_ARB_N_MASK 0x70000
+#define DMA_NRTR_DBG_S_ARB_L_SHIFT 24
+#define DMA_NRTR_DBG_S_ARB_L_MASK 0x7000000
+
+/* DMA_NRTR_DBG_L_ARB */
+#define DMA_NRTR_DBG_L_ARB_W_SHIFT 0
+#define DMA_NRTR_DBG_L_ARB_W_MASK 0x7
+#define DMA_NRTR_DBG_L_ARB_E_SHIFT 8
+#define DMA_NRTR_DBG_L_ARB_E_MASK 0x700
+#define DMA_NRTR_DBG_L_ARB_S_SHIFT 16
+#define DMA_NRTR_DBG_L_ARB_S_MASK 0x70000
+#define DMA_NRTR_DBG_L_ARB_N_SHIFT 24
+#define DMA_NRTR_DBG_L_ARB_N_MASK 0x7000000
+
+/* DMA_NRTR_DBG_E_ARB_MAX */
+#define DMA_NRTR_DBG_E_ARB_MAX_CREDIT_SHIFT 0
+#define DMA_NRTR_DBG_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* DMA_NRTR_DBG_W_ARB_MAX */
+#define DMA_NRTR_DBG_W_ARB_MAX_CREDIT_SHIFT 0
+#define DMA_NRTR_DBG_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* DMA_NRTR_DBG_N_ARB_MAX */
+#define DMA_NRTR_DBG_N_ARB_MAX_CREDIT_SHIFT 0
+#define DMA_NRTR_DBG_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* DMA_NRTR_DBG_S_ARB_MAX */
+#define DMA_NRTR_DBG_S_ARB_MAX_CREDIT_SHIFT 0
+#define DMA_NRTR_DBG_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* DMA_NRTR_DBG_L_ARB_MAX */
+#define DMA_NRTR_DBG_L_ARB_MAX_CREDIT_SHIFT 0
+#define DMA_NRTR_DBG_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* DMA_NRTR_SPLIT_COEF */
+#define DMA_NRTR_SPLIT_COEF_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_COEF_VAL_MASK 0xFFFF
+
+/* DMA_NRTR_SPLIT_CFG */
+#define DMA_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_SHIFT 0
+#define DMA_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_MASK 0x1
+#define DMA_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_SHIFT 1
+#define DMA_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_MASK 0x2
+#define DMA_NRTR_SPLIT_CFG_DEFAULT_MESH_SHIFT 2
+#define DMA_NRTR_SPLIT_CFG_DEFAULT_MESH_MASK 0xC
+#define DMA_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_SHIFT 4
+#define DMA_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_MASK 0x10
+#define DMA_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_SHIFT 5
+#define DMA_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_MASK 0x20
+#define DMA_NRTR_SPLIT_CFG_B2B_OPT_SHIFT 6
+#define DMA_NRTR_SPLIT_CFG_B2B_OPT_MASK 0x1C0
+
+/* DMA_NRTR_SPLIT_RD_SAT */
+#define DMA_NRTR_SPLIT_RD_SAT_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_RD_SAT_VAL_MASK 0xFFFF
+
+/* DMA_NRTR_SPLIT_RD_RST_TOKEN */
+#define DMA_NRTR_SPLIT_RD_RST_TOKEN_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_RD_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* DMA_NRTR_SPLIT_RD_TIMEOUT */
+#define DMA_NRTR_SPLIT_RD_TIMEOUT_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_RD_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* DMA_NRTR_SPLIT_WR_SAT */
+#define DMA_NRTR_SPLIT_WR_SAT_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_WR_SAT_VAL_MASK 0xFFFF
+
+/* DMA_NRTR_WPLIT_WR_TST_TOLEN */
+#define DMA_NRTR_WPLIT_WR_TST_TOLEN_VAL_SHIFT 0
+#define DMA_NRTR_WPLIT_WR_TST_TOLEN_VAL_MASK 0xFFFF
+
+/* DMA_NRTR_SPLIT_WR_TIMEOUT */
+#define DMA_NRTR_SPLIT_WR_TIMEOUT_VAL_SHIFT 0
+#define DMA_NRTR_SPLIT_WR_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* DMA_NRTR_HBW_RANGE_HIT */
+#define DMA_NRTR_HBW_RANGE_HIT_IND_SHIFT 0
+#define DMA_NRTR_HBW_RANGE_HIT_IND_MASK 0xFF
+
+/* DMA_NRTR_HBW_RANGE_MASK_L */
+#define DMA_NRTR_HBW_RANGE_MASK_L_VAL_SHIFT 0
+#define DMA_NRTR_HBW_RANGE_MASK_L_VAL_MASK 0xFFFFFFFF
+
+/* DMA_NRTR_HBW_RANGE_MASK_H */
+#define DMA_NRTR_HBW_RANGE_MASK_H_VAL_SHIFT 0
+#define DMA_NRTR_HBW_RANGE_MASK_H_VAL_MASK 0x3FFFF
+
+/* DMA_NRTR_HBW_RANGE_BASE_L */
+#define DMA_NRTR_HBW_RANGE_BASE_L_VAL_SHIFT 0
+#define DMA_NRTR_HBW_RANGE_BASE_L_VAL_MASK 0xFFFFFFFF
+
+/* DMA_NRTR_HBW_RANGE_BASE_H */
+#define DMA_NRTR_HBW_RANGE_BASE_H_VAL_SHIFT 0
+#define DMA_NRTR_HBW_RANGE_BASE_H_VAL_MASK 0x3FFFF
+
+/* DMA_NRTR_LBW_RANGE_HIT */
+#define DMA_NRTR_LBW_RANGE_HIT_IND_SHIFT 0
+#define DMA_NRTR_LBW_RANGE_HIT_IND_MASK 0xFFFF
+
+/* DMA_NRTR_LBW_RANGE_MASK */
+#define DMA_NRTR_LBW_RANGE_MASK_VAL_SHIFT 0
+#define DMA_NRTR_LBW_RANGE_MASK_VAL_MASK 0x3FFFFFF
+
+/* DMA_NRTR_LBW_RANGE_BASE */
+#define DMA_NRTR_LBW_RANGE_BASE_VAL_SHIFT 0
+#define DMA_NRTR_LBW_RANGE_BASE_VAL_MASK 0x3FFFFFF
+
+/* DMA_NRTR_RGLTR */
+#define DMA_NRTR_RGLTR_WR_EN_SHIFT 0
+#define DMA_NRTR_RGLTR_WR_EN_MASK 0x1
+#define DMA_NRTR_RGLTR_RD_EN_SHIFT 4
+#define DMA_NRTR_RGLTR_RD_EN_MASK 0x10
+
+/* DMA_NRTR_RGLTR_WR_RESULT */
+#define DMA_NRTR_RGLTR_WR_RESULT_VAL_SHIFT 0
+#define DMA_NRTR_RGLTR_WR_RESULT_VAL_MASK 0xFF
+
+/* DMA_NRTR_RGLTR_RD_RESULT */
+#define DMA_NRTR_RGLTR_RD_RESULT_VAL_SHIFT 0
+#define DMA_NRTR_RGLTR_RD_RESULT_VAL_MASK 0xFF
+
+/* DMA_NRTR_SCRAMB_EN */
+#define DMA_NRTR_SCRAMB_EN_VAL_SHIFT 0
+#define DMA_NRTR_SCRAMB_EN_VAL_MASK 0x1
+
+/* DMA_NRTR_NON_LIN_SCRAMB */
+#define DMA_NRTR_NON_LIN_SCRAMB_EN_SHIFT 0
+#define DMA_NRTR_NON_LIN_SCRAMB_EN_MASK 0x1
+
+#endif /* ASIC_REG_DMA_NRTR_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h
new file mode 100644
index 000000000000..d8293745a02b
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_nrtr_regs.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_NRTR_REGS_H_
+#define ASIC_REG_DMA_NRTR_REGS_H_
+
+/*
+ *****************************************
+ * DMA_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+#define mmDMA_NRTR_HBW_MAX_CRED 0x1C0100
+
+#define mmDMA_NRTR_LBW_MAX_CRED 0x1C0120
+
+#define mmDMA_NRTR_DBG_E_ARB 0x1C0300
+
+#define mmDMA_NRTR_DBG_W_ARB 0x1C0304
+
+#define mmDMA_NRTR_DBG_N_ARB 0x1C0308
+
+#define mmDMA_NRTR_DBG_S_ARB 0x1C030C
+
+#define mmDMA_NRTR_DBG_L_ARB 0x1C0310
+
+#define mmDMA_NRTR_DBG_E_ARB_MAX 0x1C0320
+
+#define mmDMA_NRTR_DBG_W_ARB_MAX 0x1C0324
+
+#define mmDMA_NRTR_DBG_N_ARB_MAX 0x1C0328
+
+#define mmDMA_NRTR_DBG_S_ARB_MAX 0x1C032C
+
+#define mmDMA_NRTR_DBG_L_ARB_MAX 0x1C0330
+
+#define mmDMA_NRTR_SPLIT_COEF_0 0x1C0400
+
+#define mmDMA_NRTR_SPLIT_COEF_1 0x1C0404
+
+#define mmDMA_NRTR_SPLIT_COEF_2 0x1C0408
+
+#define mmDMA_NRTR_SPLIT_COEF_3 0x1C040C
+
+#define mmDMA_NRTR_SPLIT_COEF_4 0x1C0410
+
+#define mmDMA_NRTR_SPLIT_COEF_5 0x1C0414
+
+#define mmDMA_NRTR_SPLIT_COEF_6 0x1C0418
+
+#define mmDMA_NRTR_SPLIT_COEF_7 0x1C041C
+
+#define mmDMA_NRTR_SPLIT_COEF_8 0x1C0420
+
+#define mmDMA_NRTR_SPLIT_COEF_9 0x1C0424
+
+#define mmDMA_NRTR_SPLIT_CFG 0x1C0440
+
+#define mmDMA_NRTR_SPLIT_RD_SAT 0x1C0444
+
+#define mmDMA_NRTR_SPLIT_RD_RST_TOKEN 0x1C0448
+
+#define mmDMA_NRTR_SPLIT_RD_TIMEOUT_0 0x1C044C
+
+#define mmDMA_NRTR_SPLIT_RD_TIMEOUT_1 0x1C0450
+
+#define mmDMA_NRTR_SPLIT_WR_SAT 0x1C0454
+
+#define mmDMA_NRTR_WPLIT_WR_TST_TOLEN 0x1C0458
+
+#define mmDMA_NRTR_SPLIT_WR_TIMEOUT_0 0x1C045C
+
+#define mmDMA_NRTR_SPLIT_WR_TIMEOUT_1 0x1C0460
+
+#define mmDMA_NRTR_HBW_RANGE_HIT 0x1C0470
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_0 0x1C0480
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_1 0x1C0484
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_2 0x1C0488
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_3 0x1C048C
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_4 0x1C0490
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_5 0x1C0494
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_6 0x1C0498
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_L_7 0x1C049C
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_0 0x1C04A0
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_1 0x1C04A4
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_2 0x1C04A8
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_3 0x1C04AC
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_4 0x1C04B0
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_5 0x1C04B4
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_6 0x1C04B8
+
+#define mmDMA_NRTR_HBW_RANGE_MASK_H_7 0x1C04BC
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_0 0x1C04C0
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_1 0x1C04C4
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_2 0x1C04C8
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_3 0x1C04CC
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_4 0x1C04D0
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_5 0x1C04D4
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_6 0x1C04D8
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_L_7 0x1C04DC
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_0 0x1C04E0
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_1 0x1C04E4
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_2 0x1C04E8
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_3 0x1C04EC
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_4 0x1C04F0
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_5 0x1C04F4
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_6 0x1C04F8
+
+#define mmDMA_NRTR_HBW_RANGE_BASE_H_7 0x1C04FC
+
+#define mmDMA_NRTR_LBW_RANGE_HIT 0x1C0500
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_0 0x1C0510
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_1 0x1C0514
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_2 0x1C0518
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_3 0x1C051C
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_4 0x1C0520
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_5 0x1C0524
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_6 0x1C0528
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_7 0x1C052C
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_8 0x1C0530
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_9 0x1C0534
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_10 0x1C0538
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_11 0x1C053C
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_12 0x1C0540
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_13 0x1C0544
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_14 0x1C0548
+
+#define mmDMA_NRTR_LBW_RANGE_MASK_15 0x1C054C
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_0 0x1C0550
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_1 0x1C0554
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_2 0x1C0558
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_3 0x1C055C
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_4 0x1C0560
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_5 0x1C0564
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_6 0x1C0568
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_7 0x1C056C
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_8 0x1C0570
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_9 0x1C0574
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_10 0x1C0578
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_11 0x1C057C
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_12 0x1C0580
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_13 0x1C0584
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_14 0x1C0588
+
+#define mmDMA_NRTR_LBW_RANGE_BASE_15 0x1C058C
+
+#define mmDMA_NRTR_RGLTR 0x1C0590
+
+#define mmDMA_NRTR_RGLTR_WR_RESULT 0x1C0594
+
+#define mmDMA_NRTR_RGLTR_RD_RESULT 0x1C0598
+
+#define mmDMA_NRTR_SCRAMB_EN 0x1C0600
+
+#define mmDMA_NRTR_NON_LIN_SCRAMB 0x1C0604
+
+#endif /* ASIC_REG_DMA_NRTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h
new file mode 100644
index 000000000000..10619dbb9b17
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_masks.h
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_0_MASKS_H_
+#define ASIC_REG_DMA_QM_0_MASKS_H_
+
+/*
+ *****************************************
+ * DMA_QM_0 (Prototype: QMAN)
+ *****************************************
+ */
+
+/* DMA_QM_0_GLBL_CFG0 */
+#define DMA_QM_0_GLBL_CFG0_PQF_EN_SHIFT 0
+#define DMA_QM_0_GLBL_CFG0_PQF_EN_MASK 0x1
+#define DMA_QM_0_GLBL_CFG0_CQF_EN_SHIFT 1
+#define DMA_QM_0_GLBL_CFG0_CQF_EN_MASK 0x2
+#define DMA_QM_0_GLBL_CFG0_CP_EN_SHIFT 2
+#define DMA_QM_0_GLBL_CFG0_CP_EN_MASK 0x4
+#define DMA_QM_0_GLBL_CFG0_DMA_EN_SHIFT 3
+#define DMA_QM_0_GLBL_CFG0_DMA_EN_MASK 0x8
+
+/* DMA_QM_0_GLBL_CFG1 */
+#define DMA_QM_0_GLBL_CFG1_PQF_STOP_SHIFT 0
+#define DMA_QM_0_GLBL_CFG1_PQF_STOP_MASK 0x1
+#define DMA_QM_0_GLBL_CFG1_CQF_STOP_SHIFT 1
+#define DMA_QM_0_GLBL_CFG1_CQF_STOP_MASK 0x2
+#define DMA_QM_0_GLBL_CFG1_CP_STOP_SHIFT 2
+#define DMA_QM_0_GLBL_CFG1_CP_STOP_MASK 0x4
+#define DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT 3
+#define DMA_QM_0_GLBL_CFG1_DMA_STOP_MASK 0x8
+#define DMA_QM_0_GLBL_CFG1_PQF_FLUSH_SHIFT 8
+#define DMA_QM_0_GLBL_CFG1_PQF_FLUSH_MASK 0x100
+#define DMA_QM_0_GLBL_CFG1_CQF_FLUSH_SHIFT 9
+#define DMA_QM_0_GLBL_CFG1_CQF_FLUSH_MASK 0x200
+#define DMA_QM_0_GLBL_CFG1_CP_FLUSH_SHIFT 10
+#define DMA_QM_0_GLBL_CFG1_CP_FLUSH_MASK 0x400
+#define DMA_QM_0_GLBL_CFG1_DMA_FLUSH_SHIFT 11
+#define DMA_QM_0_GLBL_CFG1_DMA_FLUSH_MASK 0x800
+
+/* DMA_QM_0_GLBL_PROT */
+#define DMA_QM_0_GLBL_PROT_PQF_PROT_SHIFT 0
+#define DMA_QM_0_GLBL_PROT_PQF_PROT_MASK 0x1
+#define DMA_QM_0_GLBL_PROT_CQF_PROT_SHIFT 1
+#define DMA_QM_0_GLBL_PROT_CQF_PROT_MASK 0x2
+#define DMA_QM_0_GLBL_PROT_CP_PROT_SHIFT 2
+#define DMA_QM_0_GLBL_PROT_CP_PROT_MASK 0x4
+#define DMA_QM_0_GLBL_PROT_DMA_PROT_SHIFT 3
+#define DMA_QM_0_GLBL_PROT_DMA_PROT_MASK 0x8
+#define DMA_QM_0_GLBL_PROT_PQF_ERR_PROT_SHIFT 4
+#define DMA_QM_0_GLBL_PROT_PQF_ERR_PROT_MASK 0x10
+#define DMA_QM_0_GLBL_PROT_CQF_ERR_PROT_SHIFT 5
+#define DMA_QM_0_GLBL_PROT_CQF_ERR_PROT_MASK 0x20
+#define DMA_QM_0_GLBL_PROT_CP_ERR_PROT_SHIFT 6
+#define DMA_QM_0_GLBL_PROT_CP_ERR_PROT_MASK 0x40
+#define DMA_QM_0_GLBL_PROT_DMA_ERR_PROT_SHIFT 7
+#define DMA_QM_0_GLBL_PROT_DMA_ERR_PROT_MASK 0x80
+
+/* DMA_QM_0_GLBL_ERR_CFG */
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_ERR_INT_EN_SHIFT 0
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_ERR_INT_EN_MASK 0x1
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT 1
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK 0x2
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT 2
+#define DMA_QM_0_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK 0x4
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_ERR_INT_EN_SHIFT 3
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_ERR_INT_EN_MASK 0x8
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT 4
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_ERR_MSG_EN_MASK 0x10
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT 5
+#define DMA_QM_0_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK 0x20
+#define DMA_QM_0_GLBL_ERR_CFG_CP_ERR_INT_EN_SHIFT 6
+#define DMA_QM_0_GLBL_ERR_CFG_CP_ERR_INT_EN_MASK 0x40
+#define DMA_QM_0_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT 7
+#define DMA_QM_0_GLBL_ERR_CFG_CP_ERR_MSG_EN_MASK 0x80
+#define DMA_QM_0_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT 8
+#define DMA_QM_0_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK 0x100
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_ERR_INT_EN_SHIFT 9
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_ERR_INT_EN_MASK 0x200
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT 10
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_ERR_MSG_EN_MASK 0x400
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT 11
+#define DMA_QM_0_GLBL_ERR_CFG_DMA_STOP_ON_ERR_MASK 0x800
+
+/* DMA_QM_0_GLBL_ERR_ADDR_LO */
+#define DMA_QM_0_GLBL_ERR_ADDR_LO_VAL_SHIFT 0
+#define DMA_QM_0_GLBL_ERR_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_GLBL_ERR_ADDR_HI */
+#define DMA_QM_0_GLBL_ERR_ADDR_HI_VAL_SHIFT 0
+#define DMA_QM_0_GLBL_ERR_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_GLBL_ERR_WDATA */
+#define DMA_QM_0_GLBL_ERR_WDATA_VAL_SHIFT 0
+#define DMA_QM_0_GLBL_ERR_WDATA_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_GLBL_SECURE_PROPS */
+#define DMA_QM_0_GLBL_SECURE_PROPS_ASID_SHIFT 0
+#define DMA_QM_0_GLBL_SECURE_PROPS_ASID_MASK 0x3FF
+#define DMA_QM_0_GLBL_SECURE_PROPS_MMBP_SHIFT 10
+#define DMA_QM_0_GLBL_SECURE_PROPS_MMBP_MASK 0x400
+
+/* DMA_QM_0_GLBL_NON_SECURE_PROPS */
+#define DMA_QM_0_GLBL_NON_SECURE_PROPS_ASID_SHIFT 0
+#define DMA_QM_0_GLBL_NON_SECURE_PROPS_ASID_MASK 0x3FF
+#define DMA_QM_0_GLBL_NON_SECURE_PROPS_MMBP_SHIFT 10
+#define DMA_QM_0_GLBL_NON_SECURE_PROPS_MMBP_MASK 0x400
+
+/* DMA_QM_0_GLBL_STS0 */
+#define DMA_QM_0_GLBL_STS0_PQF_IDLE_SHIFT 0
+#define DMA_QM_0_GLBL_STS0_PQF_IDLE_MASK 0x1
+#define DMA_QM_0_GLBL_STS0_CQF_IDLE_SHIFT 1
+#define DMA_QM_0_GLBL_STS0_CQF_IDLE_MASK 0x2
+#define DMA_QM_0_GLBL_STS0_CP_IDLE_SHIFT 2
+#define DMA_QM_0_GLBL_STS0_CP_IDLE_MASK 0x4
+#define DMA_QM_0_GLBL_STS0_DMA_IDLE_SHIFT 3
+#define DMA_QM_0_GLBL_STS0_DMA_IDLE_MASK 0x8
+#define DMA_QM_0_GLBL_STS0_PQF_IS_STOP_SHIFT 4
+#define DMA_QM_0_GLBL_STS0_PQF_IS_STOP_MASK 0x10
+#define DMA_QM_0_GLBL_STS0_CQF_IS_STOP_SHIFT 5
+#define DMA_QM_0_GLBL_STS0_CQF_IS_STOP_MASK 0x20
+#define DMA_QM_0_GLBL_STS0_CP_IS_STOP_SHIFT 6
+#define DMA_QM_0_GLBL_STS0_CP_IS_STOP_MASK 0x40
+#define DMA_QM_0_GLBL_STS0_DMA_IS_STOP_SHIFT 7
+#define DMA_QM_0_GLBL_STS0_DMA_IS_STOP_MASK 0x80
+
+/* DMA_QM_0_GLBL_STS1 */
+#define DMA_QM_0_GLBL_STS1_PQF_RD_ERR_SHIFT 0
+#define DMA_QM_0_GLBL_STS1_PQF_RD_ERR_MASK 0x1
+#define DMA_QM_0_GLBL_STS1_CQF_RD_ERR_SHIFT 1
+#define DMA_QM_0_GLBL_STS1_CQF_RD_ERR_MASK 0x2
+#define DMA_QM_0_GLBL_STS1_CP_RD_ERR_SHIFT 2
+#define DMA_QM_0_GLBL_STS1_CP_RD_ERR_MASK 0x4
+#define DMA_QM_0_GLBL_STS1_CP_UNDEF_CMD_ERR_SHIFT 3
+#define DMA_QM_0_GLBL_STS1_CP_UNDEF_CMD_ERR_MASK 0x8
+#define DMA_QM_0_GLBL_STS1_CP_STOP_OP_SHIFT 4
+#define DMA_QM_0_GLBL_STS1_CP_STOP_OP_MASK 0x10
+#define DMA_QM_0_GLBL_STS1_CP_MSG_WR_ERR_SHIFT 5
+#define DMA_QM_0_GLBL_STS1_CP_MSG_WR_ERR_MASK 0x20
+#define DMA_QM_0_GLBL_STS1_DMA_RD_ERR_SHIFT 8
+#define DMA_QM_0_GLBL_STS1_DMA_RD_ERR_MASK 0x100
+#define DMA_QM_0_GLBL_STS1_DMA_WR_ERR_SHIFT 9
+#define DMA_QM_0_GLBL_STS1_DMA_WR_ERR_MASK 0x200
+#define DMA_QM_0_GLBL_STS1_DMA_RD_MSG_ERR_SHIFT 10
+#define DMA_QM_0_GLBL_STS1_DMA_RD_MSG_ERR_MASK 0x400
+#define DMA_QM_0_GLBL_STS1_DMA_WR_MSG_ERR_SHIFT 11
+#define DMA_QM_0_GLBL_STS1_DMA_WR_MSG_ERR_MASK 0x800
+
+/* DMA_QM_0_PQ_BASE_LO */
+#define DMA_QM_0_PQ_BASE_LO_VAL_SHIFT 0
+#define DMA_QM_0_PQ_BASE_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_BASE_HI */
+#define DMA_QM_0_PQ_BASE_HI_VAL_SHIFT 0
+#define DMA_QM_0_PQ_BASE_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_SIZE */
+#define DMA_QM_0_PQ_SIZE_VAL_SHIFT 0
+#define DMA_QM_0_PQ_SIZE_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_PI */
+#define DMA_QM_0_PQ_PI_VAL_SHIFT 0
+#define DMA_QM_0_PQ_PI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_CI */
+#define DMA_QM_0_PQ_CI_VAL_SHIFT 0
+#define DMA_QM_0_PQ_CI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_CFG0 */
+#define DMA_QM_0_PQ_CFG0_RESERVED_SHIFT 0
+#define DMA_QM_0_PQ_CFG0_RESERVED_MASK 0x1
+
+/* DMA_QM_0_PQ_CFG1 */
+#define DMA_QM_0_PQ_CFG1_CREDIT_LIM_SHIFT 0
+#define DMA_QM_0_PQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define DMA_QM_0_PQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define DMA_QM_0_PQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* DMA_QM_0_PQ_ARUSER */
+#define DMA_QM_0_PQ_ARUSER_NOSNOOP_SHIFT 0
+#define DMA_QM_0_PQ_ARUSER_NOSNOOP_MASK 0x1
+#define DMA_QM_0_PQ_ARUSER_WORD_SHIFT 1
+#define DMA_QM_0_PQ_ARUSER_WORD_MASK 0x2
+
+/* DMA_QM_0_PQ_PUSH0 */
+#define DMA_QM_0_PQ_PUSH0_PTR_LO_SHIFT 0
+#define DMA_QM_0_PQ_PUSH0_PTR_LO_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_PUSH1 */
+#define DMA_QM_0_PQ_PUSH1_PTR_HI_SHIFT 0
+#define DMA_QM_0_PQ_PUSH1_PTR_HI_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_PUSH2 */
+#define DMA_QM_0_PQ_PUSH2_TSIZE_SHIFT 0
+#define DMA_QM_0_PQ_PUSH2_TSIZE_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_PUSH3 */
+#define DMA_QM_0_PQ_PUSH3_RPT_SHIFT 0
+#define DMA_QM_0_PQ_PUSH3_RPT_MASK 0xFFFF
+#define DMA_QM_0_PQ_PUSH3_CTL_SHIFT 16
+#define DMA_QM_0_PQ_PUSH3_CTL_MASK 0xFFFF0000
+
+/* DMA_QM_0_PQ_STS0 */
+#define DMA_QM_0_PQ_STS0_PQ_CREDIT_CNT_SHIFT 0
+#define DMA_QM_0_PQ_STS0_PQ_CREDIT_CNT_MASK 0xFFFF
+#define DMA_QM_0_PQ_STS0_PQ_FREE_CNT_SHIFT 16
+#define DMA_QM_0_PQ_STS0_PQ_FREE_CNT_MASK 0xFFFF0000
+
+/* DMA_QM_0_PQ_STS1 */
+#define DMA_QM_0_PQ_STS1_PQ_INFLIGHT_CNT_SHIFT 0
+#define DMA_QM_0_PQ_STS1_PQ_INFLIGHT_CNT_MASK 0xFFFF
+#define DMA_QM_0_PQ_STS1_PQ_BUF_EMPTY_SHIFT 30
+#define DMA_QM_0_PQ_STS1_PQ_BUF_EMPTY_MASK 0x40000000
+#define DMA_QM_0_PQ_STS1_PQ_BUSY_SHIFT 31
+#define DMA_QM_0_PQ_STS1_PQ_BUSY_MASK 0x80000000
+
+/* DMA_QM_0_PQ_RD_RATE_LIM_EN */
+#define DMA_QM_0_PQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define DMA_QM_0_PQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* DMA_QM_0_PQ_RD_RATE_LIM_RST_TOKEN */
+#define DMA_QM_0_PQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define DMA_QM_0_PQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* DMA_QM_0_PQ_RD_RATE_LIM_SAT */
+#define DMA_QM_0_PQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define DMA_QM_0_PQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* DMA_QM_0_PQ_RD_RATE_LIM_TOUT */
+#define DMA_QM_0_PQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define DMA_QM_0_PQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* DMA_QM_0_CQ_CFG0 */
+#define DMA_QM_0_CQ_CFG0_RESERVED_SHIFT 0
+#define DMA_QM_0_CQ_CFG0_RESERVED_MASK 0x1
+
+/* DMA_QM_0_CQ_CFG1 */
+#define DMA_QM_0_CQ_CFG1_CREDIT_LIM_SHIFT 0
+#define DMA_QM_0_CQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define DMA_QM_0_CQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define DMA_QM_0_CQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* DMA_QM_0_CQ_ARUSER */
+#define DMA_QM_0_CQ_ARUSER_NOSNOOP_SHIFT 0
+#define DMA_QM_0_CQ_ARUSER_NOSNOOP_MASK 0x1
+#define DMA_QM_0_CQ_ARUSER_WORD_SHIFT 1
+#define DMA_QM_0_CQ_ARUSER_WORD_MASK 0x2
+
+/* DMA_QM_0_CQ_PTR_LO */
+#define DMA_QM_0_CQ_PTR_LO_VAL_SHIFT 0
+#define DMA_QM_0_CQ_PTR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_PTR_HI */
+#define DMA_QM_0_CQ_PTR_HI_VAL_SHIFT 0
+#define DMA_QM_0_CQ_PTR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_TSIZE */
+#define DMA_QM_0_CQ_TSIZE_VAL_SHIFT 0
+#define DMA_QM_0_CQ_TSIZE_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_CTL */
+#define DMA_QM_0_CQ_CTL_RPT_SHIFT 0
+#define DMA_QM_0_CQ_CTL_RPT_MASK 0xFFFF
+#define DMA_QM_0_CQ_CTL_CTL_SHIFT 16
+#define DMA_QM_0_CQ_CTL_CTL_MASK 0xFFFF0000
+
+/* DMA_QM_0_CQ_PTR_LO_STS */
+#define DMA_QM_0_CQ_PTR_LO_STS_VAL_SHIFT 0
+#define DMA_QM_0_CQ_PTR_LO_STS_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_PTR_HI_STS */
+#define DMA_QM_0_CQ_PTR_HI_STS_VAL_SHIFT 0
+#define DMA_QM_0_CQ_PTR_HI_STS_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_TSIZE_STS */
+#define DMA_QM_0_CQ_TSIZE_STS_VAL_SHIFT 0
+#define DMA_QM_0_CQ_TSIZE_STS_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_CTL_STS */
+#define DMA_QM_0_CQ_CTL_STS_RPT_SHIFT 0
+#define DMA_QM_0_CQ_CTL_STS_RPT_MASK 0xFFFF
+#define DMA_QM_0_CQ_CTL_STS_CTL_SHIFT 16
+#define DMA_QM_0_CQ_CTL_STS_CTL_MASK 0xFFFF0000
+
+/* DMA_QM_0_CQ_STS0 */
+#define DMA_QM_0_CQ_STS0_CQ_CREDIT_CNT_SHIFT 0
+#define DMA_QM_0_CQ_STS0_CQ_CREDIT_CNT_MASK 0xFFFF
+#define DMA_QM_0_CQ_STS0_CQ_FREE_CNT_SHIFT 16
+#define DMA_QM_0_CQ_STS0_CQ_FREE_CNT_MASK 0xFFFF0000
+
+/* DMA_QM_0_CQ_STS1 */
+#define DMA_QM_0_CQ_STS1_CQ_INFLIGHT_CNT_SHIFT 0
+#define DMA_QM_0_CQ_STS1_CQ_INFLIGHT_CNT_MASK 0xFFFF
+#define DMA_QM_0_CQ_STS1_CQ_BUF_EMPTY_SHIFT 30
+#define DMA_QM_0_CQ_STS1_CQ_BUF_EMPTY_MASK 0x40000000
+#define DMA_QM_0_CQ_STS1_CQ_BUSY_SHIFT 31
+#define DMA_QM_0_CQ_STS1_CQ_BUSY_MASK 0x80000000
+
+/* DMA_QM_0_CQ_RD_RATE_LIM_EN */
+#define DMA_QM_0_CQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define DMA_QM_0_CQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* DMA_QM_0_CQ_RD_RATE_LIM_RST_TOKEN */
+#define DMA_QM_0_CQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define DMA_QM_0_CQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* DMA_QM_0_CQ_RD_RATE_LIM_SAT */
+#define DMA_QM_0_CQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define DMA_QM_0_CQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* DMA_QM_0_CQ_RD_RATE_LIM_TOUT */
+#define DMA_QM_0_CQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define DMA_QM_0_CQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* DMA_QM_0_CQ_IFIFO_CNT */
+#define DMA_QM_0_CQ_IFIFO_CNT_VAL_SHIFT 0
+#define DMA_QM_0_CQ_IFIFO_CNT_VAL_MASK 0x3
+
+/* DMA_QM_0_CP_MSG_BASE0_ADDR_LO */
+#define DMA_QM_0_CP_MSG_BASE0_ADDR_LO_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE0_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE0_ADDR_HI */
+#define DMA_QM_0_CP_MSG_BASE0_ADDR_HI_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE0_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE1_ADDR_LO */
+#define DMA_QM_0_CP_MSG_BASE1_ADDR_LO_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE1_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE1_ADDR_HI */
+#define DMA_QM_0_CP_MSG_BASE1_ADDR_HI_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE1_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE2_ADDR_LO */
+#define DMA_QM_0_CP_MSG_BASE2_ADDR_LO_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE2_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE2_ADDR_HI */
+#define DMA_QM_0_CP_MSG_BASE2_ADDR_HI_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE2_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE3_ADDR_LO */
+#define DMA_QM_0_CP_MSG_BASE3_ADDR_LO_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE3_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_MSG_BASE3_ADDR_HI */
+#define DMA_QM_0_CP_MSG_BASE3_ADDR_HI_VAL_SHIFT 0
+#define DMA_QM_0_CP_MSG_BASE3_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_TSIZE_OFFSET */
+#define DMA_QM_0_CP_LDMA_TSIZE_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_TSIZE_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_SRC_BASE_LO_OFFSET */
+#define DMA_QM_0_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_SRC_BASE_HI_OFFSET */
+#define DMA_QM_0_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_DST_BASE_LO_OFFSET */
+#define DMA_QM_0_CP_LDMA_DST_BASE_LO_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_DST_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_DST_BASE_HI_OFFSET */
+#define DMA_QM_0_CP_LDMA_DST_BASE_HI_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_DST_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_LDMA_COMMIT_OFFSET */
+#define DMA_QM_0_CP_LDMA_COMMIT_OFFSET_VAL_SHIFT 0
+#define DMA_QM_0_CP_LDMA_COMMIT_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_FENCE0_RDATA */
+#define DMA_QM_0_CP_FENCE0_RDATA_INC_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE0_RDATA_INC_VAL_MASK 0xF
+
+/* DMA_QM_0_CP_FENCE1_RDATA */
+#define DMA_QM_0_CP_FENCE1_RDATA_INC_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE1_RDATA_INC_VAL_MASK 0xF
+
+/* DMA_QM_0_CP_FENCE2_RDATA */
+#define DMA_QM_0_CP_FENCE2_RDATA_INC_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE2_RDATA_INC_VAL_MASK 0xF
+
+/* DMA_QM_0_CP_FENCE3_RDATA */
+#define DMA_QM_0_CP_FENCE3_RDATA_INC_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE3_RDATA_INC_VAL_MASK 0xF
+
+/* DMA_QM_0_CP_FENCE0_CNT */
+#define DMA_QM_0_CP_FENCE0_CNT_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE0_CNT_VAL_MASK 0xFF
+
+/* DMA_QM_0_CP_FENCE1_CNT */
+#define DMA_QM_0_CP_FENCE1_CNT_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE1_CNT_VAL_MASK 0xFF
+
+/* DMA_QM_0_CP_FENCE2_CNT */
+#define DMA_QM_0_CP_FENCE2_CNT_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE2_CNT_VAL_MASK 0xFF
+
+/* DMA_QM_0_CP_FENCE3_CNT */
+#define DMA_QM_0_CP_FENCE3_CNT_VAL_SHIFT 0
+#define DMA_QM_0_CP_FENCE3_CNT_VAL_MASK 0xFF
+
+/* DMA_QM_0_CP_STS */
+#define DMA_QM_0_CP_STS_MSG_INFLIGHT_CNT_SHIFT 0
+#define DMA_QM_0_CP_STS_MSG_INFLIGHT_CNT_MASK 0xFFFF
+#define DMA_QM_0_CP_STS_ERDY_SHIFT 16
+#define DMA_QM_0_CP_STS_ERDY_MASK 0x10000
+#define DMA_QM_0_CP_STS_RRDY_SHIFT 17
+#define DMA_QM_0_CP_STS_RRDY_MASK 0x20000
+#define DMA_QM_0_CP_STS_MRDY_SHIFT 18
+#define DMA_QM_0_CP_STS_MRDY_MASK 0x40000
+#define DMA_QM_0_CP_STS_SW_STOP_SHIFT 19
+#define DMA_QM_0_CP_STS_SW_STOP_MASK 0x80000
+#define DMA_QM_0_CP_STS_FENCE_ID_SHIFT 20
+#define DMA_QM_0_CP_STS_FENCE_ID_MASK 0x300000
+#define DMA_QM_0_CP_STS_FENCE_IN_PROGRESS_SHIFT 22
+#define DMA_QM_0_CP_STS_FENCE_IN_PROGRESS_MASK 0x400000
+
+/* DMA_QM_0_CP_CURRENT_INST_LO */
+#define DMA_QM_0_CP_CURRENT_INST_LO_VAL_SHIFT 0
+#define DMA_QM_0_CP_CURRENT_INST_LO_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_CURRENT_INST_HI */
+#define DMA_QM_0_CP_CURRENT_INST_HI_VAL_SHIFT 0
+#define DMA_QM_0_CP_CURRENT_INST_HI_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CP_BARRIER_CFG */
+#define DMA_QM_0_CP_BARRIER_CFG_EBGUARD_SHIFT 0
+#define DMA_QM_0_CP_BARRIER_CFG_EBGUARD_MASK 0xFFF
+
+/* DMA_QM_0_CP_DBG_0 */
+#define DMA_QM_0_CP_DBG_0_VAL_SHIFT 0
+#define DMA_QM_0_CP_DBG_0_VAL_MASK 0xFF
+
+/* DMA_QM_0_PQ_BUF_ADDR */
+#define DMA_QM_0_PQ_BUF_ADDR_VAL_SHIFT 0
+#define DMA_QM_0_PQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_PQ_BUF_RDATA */
+#define DMA_QM_0_PQ_BUF_RDATA_VAL_SHIFT 0
+#define DMA_QM_0_PQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_BUF_ADDR */
+#define DMA_QM_0_CQ_BUF_ADDR_VAL_SHIFT 0
+#define DMA_QM_0_CQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* DMA_QM_0_CQ_BUF_RDATA */
+#define DMA_QM_0_CQ_BUF_RDATA_VAL_SHIFT 0
+#define DMA_QM_0_CQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_DMA_QM_0_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h
new file mode 100644
index 000000000000..c693bc5dcb22
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_0_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_0_REGS_H_
+#define ASIC_REG_DMA_QM_0_REGS_H_
+
+/*
+ *****************************************
+ * DMA_QM_0 (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmDMA_QM_0_GLBL_CFG0 0x400000
+
+#define mmDMA_QM_0_GLBL_CFG1 0x400004
+
+#define mmDMA_QM_0_GLBL_PROT 0x400008
+
+#define mmDMA_QM_0_GLBL_ERR_CFG 0x40000C
+
+#define mmDMA_QM_0_GLBL_ERR_ADDR_LO 0x400010
+
+#define mmDMA_QM_0_GLBL_ERR_ADDR_HI 0x400014
+
+#define mmDMA_QM_0_GLBL_ERR_WDATA 0x400018
+
+#define mmDMA_QM_0_GLBL_SECURE_PROPS 0x40001C
+
+#define mmDMA_QM_0_GLBL_NON_SECURE_PROPS 0x400020
+
+#define mmDMA_QM_0_GLBL_STS0 0x400024
+
+#define mmDMA_QM_0_GLBL_STS1 0x400028
+
+#define mmDMA_QM_0_PQ_BASE_LO 0x400060
+
+#define mmDMA_QM_0_PQ_BASE_HI 0x400064
+
+#define mmDMA_QM_0_PQ_SIZE 0x400068
+
+#define mmDMA_QM_0_PQ_PI 0x40006C
+
+#define mmDMA_QM_0_PQ_CI 0x400070
+
+#define mmDMA_QM_0_PQ_CFG0 0x400074
+
+#define mmDMA_QM_0_PQ_CFG1 0x400078
+
+#define mmDMA_QM_0_PQ_ARUSER 0x40007C
+
+#define mmDMA_QM_0_PQ_PUSH0 0x400080
+
+#define mmDMA_QM_0_PQ_PUSH1 0x400084
+
+#define mmDMA_QM_0_PQ_PUSH2 0x400088
+
+#define mmDMA_QM_0_PQ_PUSH3 0x40008C
+
+#define mmDMA_QM_0_PQ_STS0 0x400090
+
+#define mmDMA_QM_0_PQ_STS1 0x400094
+
+#define mmDMA_QM_0_PQ_RD_RATE_LIM_EN 0x4000A0
+
+#define mmDMA_QM_0_PQ_RD_RATE_LIM_RST_TOKEN 0x4000A4
+
+#define mmDMA_QM_0_PQ_RD_RATE_LIM_SAT 0x4000A8
+
+#define mmDMA_QM_0_PQ_RD_RATE_LIM_TOUT 0x4000AC
+
+#define mmDMA_QM_0_CQ_CFG0 0x4000B0
+
+#define mmDMA_QM_0_CQ_CFG1 0x4000B4
+
+#define mmDMA_QM_0_CQ_ARUSER 0x4000B8
+
+#define mmDMA_QM_0_CQ_PTR_LO 0x4000C0
+
+#define mmDMA_QM_0_CQ_PTR_HI 0x4000C4
+
+#define mmDMA_QM_0_CQ_TSIZE 0x4000C8
+
+#define mmDMA_QM_0_CQ_CTL 0x4000CC
+
+#define mmDMA_QM_0_CQ_PTR_LO_STS 0x4000D4
+
+#define mmDMA_QM_0_CQ_PTR_HI_STS 0x4000D8
+
+#define mmDMA_QM_0_CQ_TSIZE_STS 0x4000DC
+
+#define mmDMA_QM_0_CQ_CTL_STS 0x4000E0
+
+#define mmDMA_QM_0_CQ_STS0 0x4000E4
+
+#define mmDMA_QM_0_CQ_STS1 0x4000E8
+
+#define mmDMA_QM_0_CQ_RD_RATE_LIM_EN 0x4000F0
+
+#define mmDMA_QM_0_CQ_RD_RATE_LIM_RST_TOKEN 0x4000F4
+
+#define mmDMA_QM_0_CQ_RD_RATE_LIM_SAT 0x4000F8
+
+#define mmDMA_QM_0_CQ_RD_RATE_LIM_TOUT 0x4000FC
+
+#define mmDMA_QM_0_CQ_IFIFO_CNT 0x400108
+
+#define mmDMA_QM_0_CP_MSG_BASE0_ADDR_LO 0x400120
+
+#define mmDMA_QM_0_CP_MSG_BASE0_ADDR_HI 0x400124
+
+#define mmDMA_QM_0_CP_MSG_BASE1_ADDR_LO 0x400128
+
+#define mmDMA_QM_0_CP_MSG_BASE1_ADDR_HI 0x40012C
+
+#define mmDMA_QM_0_CP_MSG_BASE2_ADDR_LO 0x400130
+
+#define mmDMA_QM_0_CP_MSG_BASE2_ADDR_HI 0x400134
+
+#define mmDMA_QM_0_CP_MSG_BASE3_ADDR_LO 0x400138
+
+#define mmDMA_QM_0_CP_MSG_BASE3_ADDR_HI 0x40013C
+
+#define mmDMA_QM_0_CP_LDMA_TSIZE_OFFSET 0x400140
+
+#define mmDMA_QM_0_CP_LDMA_SRC_BASE_LO_OFFSET 0x400144
+
+#define mmDMA_QM_0_CP_LDMA_SRC_BASE_HI_OFFSET 0x400148
+
+#define mmDMA_QM_0_CP_LDMA_DST_BASE_LO_OFFSET 0x40014C
+
+#define mmDMA_QM_0_CP_LDMA_DST_BASE_HI_OFFSET 0x400150
+
+#define mmDMA_QM_0_CP_LDMA_COMMIT_OFFSET 0x400154
+
+#define mmDMA_QM_0_CP_FENCE0_RDATA 0x400158
+
+#define mmDMA_QM_0_CP_FENCE1_RDATA 0x40015C
+
+#define mmDMA_QM_0_CP_FENCE2_RDATA 0x400160
+
+#define mmDMA_QM_0_CP_FENCE3_RDATA 0x400164
+
+#define mmDMA_QM_0_CP_FENCE0_CNT 0x400168
+
+#define mmDMA_QM_0_CP_FENCE1_CNT 0x40016C
+
+#define mmDMA_QM_0_CP_FENCE2_CNT 0x400170
+
+#define mmDMA_QM_0_CP_FENCE3_CNT 0x400174
+
+#define mmDMA_QM_0_CP_STS 0x400178
+
+#define mmDMA_QM_0_CP_CURRENT_INST_LO 0x40017C
+
+#define mmDMA_QM_0_CP_CURRENT_INST_HI 0x400180
+
+#define mmDMA_QM_0_CP_BARRIER_CFG 0x400184
+
+#define mmDMA_QM_0_CP_DBG_0 0x400188
+
+#define mmDMA_QM_0_PQ_BUF_ADDR 0x400300
+
+#define mmDMA_QM_0_PQ_BUF_RDATA 0x400304
+
+#define mmDMA_QM_0_CQ_BUF_ADDR 0x400308
+
+#define mmDMA_QM_0_CQ_BUF_RDATA 0x40030C
+
+#endif /* ASIC_REG_DMA_QM_0_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h
new file mode 100644
index 000000000000..da928390f89c
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_1_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_1_REGS_H_
+#define ASIC_REG_DMA_QM_1_REGS_H_
+
+/*
+ *****************************************
+ * DMA_QM_1 (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmDMA_QM_1_GLBL_CFG0 0x408000
+
+#define mmDMA_QM_1_GLBL_CFG1 0x408004
+
+#define mmDMA_QM_1_GLBL_PROT 0x408008
+
+#define mmDMA_QM_1_GLBL_ERR_CFG 0x40800C
+
+#define mmDMA_QM_1_GLBL_ERR_ADDR_LO 0x408010
+
+#define mmDMA_QM_1_GLBL_ERR_ADDR_HI 0x408014
+
+#define mmDMA_QM_1_GLBL_ERR_WDATA 0x408018
+
+#define mmDMA_QM_1_GLBL_SECURE_PROPS 0x40801C
+
+#define mmDMA_QM_1_GLBL_NON_SECURE_PROPS 0x408020
+
+#define mmDMA_QM_1_GLBL_STS0 0x408024
+
+#define mmDMA_QM_1_GLBL_STS1 0x408028
+
+#define mmDMA_QM_1_PQ_BASE_LO 0x408060
+
+#define mmDMA_QM_1_PQ_BASE_HI 0x408064
+
+#define mmDMA_QM_1_PQ_SIZE 0x408068
+
+#define mmDMA_QM_1_PQ_PI 0x40806C
+
+#define mmDMA_QM_1_PQ_CI 0x408070
+
+#define mmDMA_QM_1_PQ_CFG0 0x408074
+
+#define mmDMA_QM_1_PQ_CFG1 0x408078
+
+#define mmDMA_QM_1_PQ_ARUSER 0x40807C
+
+#define mmDMA_QM_1_PQ_PUSH0 0x408080
+
+#define mmDMA_QM_1_PQ_PUSH1 0x408084
+
+#define mmDMA_QM_1_PQ_PUSH2 0x408088
+
+#define mmDMA_QM_1_PQ_PUSH3 0x40808C
+
+#define mmDMA_QM_1_PQ_STS0 0x408090
+
+#define mmDMA_QM_1_PQ_STS1 0x408094
+
+#define mmDMA_QM_1_PQ_RD_RATE_LIM_EN 0x4080A0
+
+#define mmDMA_QM_1_PQ_RD_RATE_LIM_RST_TOKEN 0x4080A4
+
+#define mmDMA_QM_1_PQ_RD_RATE_LIM_SAT 0x4080A8
+
+#define mmDMA_QM_1_PQ_RD_RATE_LIM_TOUT 0x4080AC
+
+#define mmDMA_QM_1_CQ_CFG0 0x4080B0
+
+#define mmDMA_QM_1_CQ_CFG1 0x4080B4
+
+#define mmDMA_QM_1_CQ_ARUSER 0x4080B8
+
+#define mmDMA_QM_1_CQ_PTR_LO 0x4080C0
+
+#define mmDMA_QM_1_CQ_PTR_HI 0x4080C4
+
+#define mmDMA_QM_1_CQ_TSIZE 0x4080C8
+
+#define mmDMA_QM_1_CQ_CTL 0x4080CC
+
+#define mmDMA_QM_1_CQ_PTR_LO_STS 0x4080D4
+
+#define mmDMA_QM_1_CQ_PTR_HI_STS 0x4080D8
+
+#define mmDMA_QM_1_CQ_TSIZE_STS 0x4080DC
+
+#define mmDMA_QM_1_CQ_CTL_STS 0x4080E0
+
+#define mmDMA_QM_1_CQ_STS0 0x4080E4
+
+#define mmDMA_QM_1_CQ_STS1 0x4080E8
+
+#define mmDMA_QM_1_CQ_RD_RATE_LIM_EN 0x4080F0
+
+#define mmDMA_QM_1_CQ_RD_RATE_LIM_RST_TOKEN 0x4080F4
+
+#define mmDMA_QM_1_CQ_RD_RATE_LIM_SAT 0x4080F8
+
+#define mmDMA_QM_1_CQ_RD_RATE_LIM_TOUT 0x4080FC
+
+#define mmDMA_QM_1_CQ_IFIFO_CNT 0x408108
+
+#define mmDMA_QM_1_CP_MSG_BASE0_ADDR_LO 0x408120
+
+#define mmDMA_QM_1_CP_MSG_BASE0_ADDR_HI 0x408124
+
+#define mmDMA_QM_1_CP_MSG_BASE1_ADDR_LO 0x408128
+
+#define mmDMA_QM_1_CP_MSG_BASE1_ADDR_HI 0x40812C
+
+#define mmDMA_QM_1_CP_MSG_BASE2_ADDR_LO 0x408130
+
+#define mmDMA_QM_1_CP_MSG_BASE2_ADDR_HI 0x408134
+
+#define mmDMA_QM_1_CP_MSG_BASE3_ADDR_LO 0x408138
+
+#define mmDMA_QM_1_CP_MSG_BASE3_ADDR_HI 0x40813C
+
+#define mmDMA_QM_1_CP_LDMA_TSIZE_OFFSET 0x408140
+
+#define mmDMA_QM_1_CP_LDMA_SRC_BASE_LO_OFFSET 0x408144
+
+#define mmDMA_QM_1_CP_LDMA_SRC_BASE_HI_OFFSET 0x408148
+
+#define mmDMA_QM_1_CP_LDMA_DST_BASE_LO_OFFSET 0x40814C
+
+#define mmDMA_QM_1_CP_LDMA_DST_BASE_HI_OFFSET 0x408150
+
+#define mmDMA_QM_1_CP_LDMA_COMMIT_OFFSET 0x408154
+
+#define mmDMA_QM_1_CP_FENCE0_RDATA 0x408158
+
+#define mmDMA_QM_1_CP_FENCE1_RDATA 0x40815C
+
+#define mmDMA_QM_1_CP_FENCE2_RDATA 0x408160
+
+#define mmDMA_QM_1_CP_FENCE3_RDATA 0x408164
+
+#define mmDMA_QM_1_CP_FENCE0_CNT 0x408168
+
+#define mmDMA_QM_1_CP_FENCE1_CNT 0x40816C
+
+#define mmDMA_QM_1_CP_FENCE2_CNT 0x408170
+
+#define mmDMA_QM_1_CP_FENCE3_CNT 0x408174
+
+#define mmDMA_QM_1_CP_STS 0x408178
+
+#define mmDMA_QM_1_CP_CURRENT_INST_LO 0x40817C
+
+#define mmDMA_QM_1_CP_CURRENT_INST_HI 0x408180
+
+#define mmDMA_QM_1_CP_BARRIER_CFG 0x408184
+
+#define mmDMA_QM_1_CP_DBG_0 0x408188
+
+#define mmDMA_QM_1_PQ_BUF_ADDR 0x408300
+
+#define mmDMA_QM_1_PQ_BUF_RDATA 0x408304
+
+#define mmDMA_QM_1_CQ_BUF_ADDR 0x408308
+
+#define mmDMA_QM_1_CQ_BUF_RDATA 0x40830C
+
+#endif /* ASIC_REG_DMA_QM_1_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h
new file mode 100644
index 000000000000..b4f06e9b71d6
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_2_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_2_REGS_H_
+#define ASIC_REG_DMA_QM_2_REGS_H_
+
+/*
+ *****************************************
+ * DMA_QM_2 (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmDMA_QM_2_GLBL_CFG0 0x410000
+
+#define mmDMA_QM_2_GLBL_CFG1 0x410004
+
+#define mmDMA_QM_2_GLBL_PROT 0x410008
+
+#define mmDMA_QM_2_GLBL_ERR_CFG 0x41000C
+
+#define mmDMA_QM_2_GLBL_ERR_ADDR_LO 0x410010
+
+#define mmDMA_QM_2_GLBL_ERR_ADDR_HI 0x410014
+
+#define mmDMA_QM_2_GLBL_ERR_WDATA 0x410018
+
+#define mmDMA_QM_2_GLBL_SECURE_PROPS 0x41001C
+
+#define mmDMA_QM_2_GLBL_NON_SECURE_PROPS 0x410020
+
+#define mmDMA_QM_2_GLBL_STS0 0x410024
+
+#define mmDMA_QM_2_GLBL_STS1 0x410028
+
+#define mmDMA_QM_2_PQ_BASE_LO 0x410060
+
+#define mmDMA_QM_2_PQ_BASE_HI 0x410064
+
+#define mmDMA_QM_2_PQ_SIZE 0x410068
+
+#define mmDMA_QM_2_PQ_PI 0x41006C
+
+#define mmDMA_QM_2_PQ_CI 0x410070
+
+#define mmDMA_QM_2_PQ_CFG0 0x410074
+
+#define mmDMA_QM_2_PQ_CFG1 0x410078
+
+#define mmDMA_QM_2_PQ_ARUSER 0x41007C
+
+#define mmDMA_QM_2_PQ_PUSH0 0x410080
+
+#define mmDMA_QM_2_PQ_PUSH1 0x410084
+
+#define mmDMA_QM_2_PQ_PUSH2 0x410088
+
+#define mmDMA_QM_2_PQ_PUSH3 0x41008C
+
+#define mmDMA_QM_2_PQ_STS0 0x410090
+
+#define mmDMA_QM_2_PQ_STS1 0x410094
+
+#define mmDMA_QM_2_PQ_RD_RATE_LIM_EN 0x4100A0
+
+#define mmDMA_QM_2_PQ_RD_RATE_LIM_RST_TOKEN 0x4100A4
+
+#define mmDMA_QM_2_PQ_RD_RATE_LIM_SAT 0x4100A8
+
+#define mmDMA_QM_2_PQ_RD_RATE_LIM_TOUT 0x4100AC
+
+#define mmDMA_QM_2_CQ_CFG0 0x4100B0
+
+#define mmDMA_QM_2_CQ_CFG1 0x4100B4
+
+#define mmDMA_QM_2_CQ_ARUSER 0x4100B8
+
+#define mmDMA_QM_2_CQ_PTR_LO 0x4100C0
+
+#define mmDMA_QM_2_CQ_PTR_HI 0x4100C4
+
+#define mmDMA_QM_2_CQ_TSIZE 0x4100C8
+
+#define mmDMA_QM_2_CQ_CTL 0x4100CC
+
+#define mmDMA_QM_2_CQ_PTR_LO_STS 0x4100D4
+
+#define mmDMA_QM_2_CQ_PTR_HI_STS 0x4100D8
+
+#define mmDMA_QM_2_CQ_TSIZE_STS 0x4100DC
+
+#define mmDMA_QM_2_CQ_CTL_STS 0x4100E0
+
+#define mmDMA_QM_2_CQ_STS0 0x4100E4
+
+#define mmDMA_QM_2_CQ_STS1 0x4100E8
+
+#define mmDMA_QM_2_CQ_RD_RATE_LIM_EN 0x4100F0
+
+#define mmDMA_QM_2_CQ_RD_RATE_LIM_RST_TOKEN 0x4100F4
+
+#define mmDMA_QM_2_CQ_RD_RATE_LIM_SAT 0x4100F8
+
+#define mmDMA_QM_2_CQ_RD_RATE_LIM_TOUT 0x4100FC
+
+#define mmDMA_QM_2_CQ_IFIFO_CNT 0x410108
+
+#define mmDMA_QM_2_CP_MSG_BASE0_ADDR_LO 0x410120
+
+#define mmDMA_QM_2_CP_MSG_BASE0_ADDR_HI 0x410124
+
+#define mmDMA_QM_2_CP_MSG_BASE1_ADDR_LO 0x410128
+
+#define mmDMA_QM_2_CP_MSG_BASE1_ADDR_HI 0x41012C
+
+#define mmDMA_QM_2_CP_MSG_BASE2_ADDR_LO 0x410130
+
+#define mmDMA_QM_2_CP_MSG_BASE2_ADDR_HI 0x410134
+
+#define mmDMA_QM_2_CP_MSG_BASE3_ADDR_LO 0x410138
+
+#define mmDMA_QM_2_CP_MSG_BASE3_ADDR_HI 0x41013C
+
+#define mmDMA_QM_2_CP_LDMA_TSIZE_OFFSET 0x410140
+
+#define mmDMA_QM_2_CP_LDMA_SRC_BASE_LO_OFFSET 0x410144
+
+#define mmDMA_QM_2_CP_LDMA_SRC_BASE_HI_OFFSET 0x410148
+
+#define mmDMA_QM_2_CP_LDMA_DST_BASE_LO_OFFSET 0x41014C
+
+#define mmDMA_QM_2_CP_LDMA_DST_BASE_HI_OFFSET 0x410150
+
+#define mmDMA_QM_2_CP_LDMA_COMMIT_OFFSET 0x410154
+
+#define mmDMA_QM_2_CP_FENCE0_RDATA 0x410158
+
+#define mmDMA_QM_2_CP_FENCE1_RDATA 0x41015C
+
+#define mmDMA_QM_2_CP_FENCE2_RDATA 0x410160
+
+#define mmDMA_QM_2_CP_FENCE3_RDATA 0x410164
+
+#define mmDMA_QM_2_CP_FENCE0_CNT 0x410168
+
+#define mmDMA_QM_2_CP_FENCE1_CNT 0x41016C
+
+#define mmDMA_QM_2_CP_FENCE2_CNT 0x410170
+
+#define mmDMA_QM_2_CP_FENCE3_CNT 0x410174
+
+#define mmDMA_QM_2_CP_STS 0x410178
+
+#define mmDMA_QM_2_CP_CURRENT_INST_LO 0x41017C
+
+#define mmDMA_QM_2_CP_CURRENT_INST_HI 0x410180
+
+#define mmDMA_QM_2_CP_BARRIER_CFG 0x410184
+
+#define mmDMA_QM_2_CP_DBG_0 0x410188
+
+#define mmDMA_QM_2_PQ_BUF_ADDR 0x410300
+
+#define mmDMA_QM_2_PQ_BUF_RDATA 0x410304
+
+#define mmDMA_QM_2_CQ_BUF_ADDR 0x410308
+
+#define mmDMA_QM_2_CQ_BUF_RDATA 0x41030C
+
+#endif /* ASIC_REG_DMA_QM_2_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h
new file mode 100644
index 000000000000..53e3cd78a06b
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_3_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_3_REGS_H_
+#define ASIC_REG_DMA_QM_3_REGS_H_
+
+/*
+ *****************************************
+ * DMA_QM_3 (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmDMA_QM_3_GLBL_CFG0 0x418000
+
+#define mmDMA_QM_3_GLBL_CFG1 0x418004
+
+#define mmDMA_QM_3_GLBL_PROT 0x418008
+
+#define mmDMA_QM_3_GLBL_ERR_CFG 0x41800C
+
+#define mmDMA_QM_3_GLBL_ERR_ADDR_LO 0x418010
+
+#define mmDMA_QM_3_GLBL_ERR_ADDR_HI 0x418014
+
+#define mmDMA_QM_3_GLBL_ERR_WDATA 0x418018
+
+#define mmDMA_QM_3_GLBL_SECURE_PROPS 0x41801C
+
+#define mmDMA_QM_3_GLBL_NON_SECURE_PROPS 0x418020
+
+#define mmDMA_QM_3_GLBL_STS0 0x418024
+
+#define mmDMA_QM_3_GLBL_STS1 0x418028
+
+#define mmDMA_QM_3_PQ_BASE_LO 0x418060
+
+#define mmDMA_QM_3_PQ_BASE_HI 0x418064
+
+#define mmDMA_QM_3_PQ_SIZE 0x418068
+
+#define mmDMA_QM_3_PQ_PI 0x41806C
+
+#define mmDMA_QM_3_PQ_CI 0x418070
+
+#define mmDMA_QM_3_PQ_CFG0 0x418074
+
+#define mmDMA_QM_3_PQ_CFG1 0x418078
+
+#define mmDMA_QM_3_PQ_ARUSER 0x41807C
+
+#define mmDMA_QM_3_PQ_PUSH0 0x418080
+
+#define mmDMA_QM_3_PQ_PUSH1 0x418084
+
+#define mmDMA_QM_3_PQ_PUSH2 0x418088
+
+#define mmDMA_QM_3_PQ_PUSH3 0x41808C
+
+#define mmDMA_QM_3_PQ_STS0 0x418090
+
+#define mmDMA_QM_3_PQ_STS1 0x418094
+
+#define mmDMA_QM_3_PQ_RD_RATE_LIM_EN 0x4180A0
+
+#define mmDMA_QM_3_PQ_RD_RATE_LIM_RST_TOKEN 0x4180A4
+
+#define mmDMA_QM_3_PQ_RD_RATE_LIM_SAT 0x4180A8
+
+#define mmDMA_QM_3_PQ_RD_RATE_LIM_TOUT 0x4180AC
+
+#define mmDMA_QM_3_CQ_CFG0 0x4180B0
+
+#define mmDMA_QM_3_CQ_CFG1 0x4180B4
+
+#define mmDMA_QM_3_CQ_ARUSER 0x4180B8
+
+#define mmDMA_QM_3_CQ_PTR_LO 0x4180C0
+
+#define mmDMA_QM_3_CQ_PTR_HI 0x4180C4
+
+#define mmDMA_QM_3_CQ_TSIZE 0x4180C8
+
+#define mmDMA_QM_3_CQ_CTL 0x4180CC
+
+#define mmDMA_QM_3_CQ_PTR_LO_STS 0x4180D4
+
+#define mmDMA_QM_3_CQ_PTR_HI_STS 0x4180D8
+
+#define mmDMA_QM_3_CQ_TSIZE_STS 0x4180DC
+
+#define mmDMA_QM_3_CQ_CTL_STS 0x4180E0
+
+#define mmDMA_QM_3_CQ_STS0 0x4180E4
+
+#define mmDMA_QM_3_CQ_STS1 0x4180E8
+
+#define mmDMA_QM_3_CQ_RD_RATE_LIM_EN 0x4180F0
+
+#define mmDMA_QM_3_CQ_RD_RATE_LIM_RST_TOKEN 0x4180F4
+
+#define mmDMA_QM_3_CQ_RD_RATE_LIM_SAT 0x4180F8
+
+#define mmDMA_QM_3_CQ_RD_RATE_LIM_TOUT 0x4180FC
+
+#define mmDMA_QM_3_CQ_IFIFO_CNT 0x418108
+
+#define mmDMA_QM_3_CP_MSG_BASE0_ADDR_LO 0x418120
+
+#define mmDMA_QM_3_CP_MSG_BASE0_ADDR_HI 0x418124
+
+#define mmDMA_QM_3_CP_MSG_BASE1_ADDR_LO 0x418128
+
+#define mmDMA_QM_3_CP_MSG_BASE1_ADDR_HI 0x41812C
+
+#define mmDMA_QM_3_CP_MSG_BASE2_ADDR_LO 0x418130
+
+#define mmDMA_QM_3_CP_MSG_BASE2_ADDR_HI 0x418134
+
+#define mmDMA_QM_3_CP_MSG_BASE3_ADDR_LO 0x418138
+
+#define mmDMA_QM_3_CP_MSG_BASE3_ADDR_HI 0x41813C
+
+#define mmDMA_QM_3_CP_LDMA_TSIZE_OFFSET 0x418140
+
+#define mmDMA_QM_3_CP_LDMA_SRC_BASE_LO_OFFSET 0x418144
+
+#define mmDMA_QM_3_CP_LDMA_SRC_BASE_HI_OFFSET 0x418148
+
+#define mmDMA_QM_3_CP_LDMA_DST_BASE_LO_OFFSET 0x41814C
+
+#define mmDMA_QM_3_CP_LDMA_DST_BASE_HI_OFFSET 0x418150
+
+#define mmDMA_QM_3_CP_LDMA_COMMIT_OFFSET 0x418154
+
+#define mmDMA_QM_3_CP_FENCE0_RDATA 0x418158
+
+#define mmDMA_QM_3_CP_FENCE1_RDATA 0x41815C
+
+#define mmDMA_QM_3_CP_FENCE2_RDATA 0x418160
+
+#define mmDMA_QM_3_CP_FENCE3_RDATA 0x418164
+
+#define mmDMA_QM_3_CP_FENCE0_CNT 0x418168
+
+#define mmDMA_QM_3_CP_FENCE1_CNT 0x41816C
+
+#define mmDMA_QM_3_CP_FENCE2_CNT 0x418170
+
+#define mmDMA_QM_3_CP_FENCE3_CNT 0x418174
+
+#define mmDMA_QM_3_CP_STS 0x418178
+
+#define mmDMA_QM_3_CP_CURRENT_INST_LO 0x41817C
+
+#define mmDMA_QM_3_CP_CURRENT_INST_HI 0x418180
+
+#define mmDMA_QM_3_CP_BARRIER_CFG 0x418184
+
+#define mmDMA_QM_3_CP_DBG_0 0x418188
+
+#define mmDMA_QM_3_PQ_BUF_ADDR 0x418300
+
+#define mmDMA_QM_3_PQ_BUF_RDATA 0x418304
+
+#define mmDMA_QM_3_CQ_BUF_ADDR 0x418308
+
+#define mmDMA_QM_3_CQ_BUF_RDATA 0x41830C
+
+#endif /* ASIC_REG_DMA_QM_3_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h
new file mode 100644
index 000000000000..e0eb5f260201
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/dma_qm_4_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_DMA_QM_4_REGS_H_
+#define ASIC_REG_DMA_QM_4_REGS_H_
+
+/*
+ *****************************************
+ * DMA_QM_4 (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmDMA_QM_4_GLBL_CFG0 0x420000
+
+#define mmDMA_QM_4_GLBL_CFG1 0x420004
+
+#define mmDMA_QM_4_GLBL_PROT 0x420008
+
+#define mmDMA_QM_4_GLBL_ERR_CFG 0x42000C
+
+#define mmDMA_QM_4_GLBL_ERR_ADDR_LO 0x420010
+
+#define mmDMA_QM_4_GLBL_ERR_ADDR_HI 0x420014
+
+#define mmDMA_QM_4_GLBL_ERR_WDATA 0x420018
+
+#define mmDMA_QM_4_GLBL_SECURE_PROPS 0x42001C
+
+#define mmDMA_QM_4_GLBL_NON_SECURE_PROPS 0x420020
+
+#define mmDMA_QM_4_GLBL_STS0 0x420024
+
+#define mmDMA_QM_4_GLBL_STS1 0x420028
+
+#define mmDMA_QM_4_PQ_BASE_LO 0x420060
+
+#define mmDMA_QM_4_PQ_BASE_HI 0x420064
+
+#define mmDMA_QM_4_PQ_SIZE 0x420068
+
+#define mmDMA_QM_4_PQ_PI 0x42006C
+
+#define mmDMA_QM_4_PQ_CI 0x420070
+
+#define mmDMA_QM_4_PQ_CFG0 0x420074
+
+#define mmDMA_QM_4_PQ_CFG1 0x420078
+
+#define mmDMA_QM_4_PQ_ARUSER 0x42007C
+
+#define mmDMA_QM_4_PQ_PUSH0 0x420080
+
+#define mmDMA_QM_4_PQ_PUSH1 0x420084
+
+#define mmDMA_QM_4_PQ_PUSH2 0x420088
+
+#define mmDMA_QM_4_PQ_PUSH3 0x42008C
+
+#define mmDMA_QM_4_PQ_STS0 0x420090
+
+#define mmDMA_QM_4_PQ_STS1 0x420094
+
+#define mmDMA_QM_4_PQ_RD_RATE_LIM_EN 0x4200A0
+
+#define mmDMA_QM_4_PQ_RD_RATE_LIM_RST_TOKEN 0x4200A4
+
+#define mmDMA_QM_4_PQ_RD_RATE_LIM_SAT 0x4200A8
+
+#define mmDMA_QM_4_PQ_RD_RATE_LIM_TOUT 0x4200AC
+
+#define mmDMA_QM_4_CQ_CFG0 0x4200B0
+
+#define mmDMA_QM_4_CQ_CFG1 0x4200B4
+
+#define mmDMA_QM_4_CQ_ARUSER 0x4200B8
+
+#define mmDMA_QM_4_CQ_PTR_LO 0x4200C0
+
+#define mmDMA_QM_4_CQ_PTR_HI 0x4200C4
+
+#define mmDMA_QM_4_CQ_TSIZE 0x4200C8
+
+#define mmDMA_QM_4_CQ_CTL 0x4200CC
+
+#define mmDMA_QM_4_CQ_PTR_LO_STS 0x4200D4
+
+#define mmDMA_QM_4_CQ_PTR_HI_STS 0x4200D8
+
+#define mmDMA_QM_4_CQ_TSIZE_STS 0x4200DC
+
+#define mmDMA_QM_4_CQ_CTL_STS 0x4200E0
+
+#define mmDMA_QM_4_CQ_STS0 0x4200E4
+
+#define mmDMA_QM_4_CQ_STS1 0x4200E8
+
+#define mmDMA_QM_4_CQ_RD_RATE_LIM_EN 0x4200F0
+
+#define mmDMA_QM_4_CQ_RD_RATE_LIM_RST_TOKEN 0x4200F4
+
+#define mmDMA_QM_4_CQ_RD_RATE_LIM_SAT 0x4200F8
+
+#define mmDMA_QM_4_CQ_RD_RATE_LIM_TOUT 0x4200FC
+
+#define mmDMA_QM_4_CQ_IFIFO_CNT 0x420108
+
+#define mmDMA_QM_4_CP_MSG_BASE0_ADDR_LO 0x420120
+
+#define mmDMA_QM_4_CP_MSG_BASE0_ADDR_HI 0x420124
+
+#define mmDMA_QM_4_CP_MSG_BASE1_ADDR_LO 0x420128
+
+#define mmDMA_QM_4_CP_MSG_BASE1_ADDR_HI 0x42012C
+
+#define mmDMA_QM_4_CP_MSG_BASE2_ADDR_LO 0x420130
+
+#define mmDMA_QM_4_CP_MSG_BASE2_ADDR_HI 0x420134
+
+#define mmDMA_QM_4_CP_MSG_BASE3_ADDR_LO 0x420138
+
+#define mmDMA_QM_4_CP_MSG_BASE3_ADDR_HI 0x42013C
+
+#define mmDMA_QM_4_CP_LDMA_TSIZE_OFFSET 0x420140
+
+#define mmDMA_QM_4_CP_LDMA_SRC_BASE_LO_OFFSET 0x420144
+
+#define mmDMA_QM_4_CP_LDMA_SRC_BASE_HI_OFFSET 0x420148
+
+#define mmDMA_QM_4_CP_LDMA_DST_BASE_LO_OFFSET 0x42014C
+
+#define mmDMA_QM_4_CP_LDMA_DST_BASE_HI_OFFSET 0x420150
+
+#define mmDMA_QM_4_CP_LDMA_COMMIT_OFFSET 0x420154
+
+#define mmDMA_QM_4_CP_FENCE0_RDATA 0x420158
+
+#define mmDMA_QM_4_CP_FENCE1_RDATA 0x42015C
+
+#define mmDMA_QM_4_CP_FENCE2_RDATA 0x420160
+
+#define mmDMA_QM_4_CP_FENCE3_RDATA 0x420164
+
+#define mmDMA_QM_4_CP_FENCE0_CNT 0x420168
+
+#define mmDMA_QM_4_CP_FENCE1_CNT 0x42016C
+
+#define mmDMA_QM_4_CP_FENCE2_CNT 0x420170
+
+#define mmDMA_QM_4_CP_FENCE3_CNT 0x420174
+
+#define mmDMA_QM_4_CP_STS 0x420178
+
+#define mmDMA_QM_4_CP_CURRENT_INST_LO 0x42017C
+
+#define mmDMA_QM_4_CP_CURRENT_INST_HI 0x420180
+
+#define mmDMA_QM_4_CP_BARRIER_CFG 0x420184
+
+#define mmDMA_QM_4_CP_DBG_0 0x420188
+
+#define mmDMA_QM_4_PQ_BUF_ADDR 0x420300
+
+#define mmDMA_QM_4_PQ_BUF_RDATA 0x420304
+
+#define mmDMA_QM_4_CQ_BUF_ADDR 0x420308
+
+#define mmDMA_QM_4_CQ_BUF_RDATA 0x42030C
+
+#endif /* ASIC_REG_DMA_QM_4_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h b/drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h
new file mode 100644
index 000000000000..85b15010cd7a
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/goya_blocks.h
@@ -0,0 +1,1372 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef GOYA_BLOCKS_H_
+#define GOYA_BLOCKS_H_
+
+#define mmPCI_NRTR_BASE 0x7FFC000000ull
+#define PCI_NRTR_MAX_OFFSET 0x608
+#define PCI_NRTR_SECTION 0x4000
+#define mmPCI_RD_REGULATOR_BASE 0x7FFC004000ull
+#define PCI_RD_REGULATOR_MAX_OFFSET 0x74
+#define PCI_RD_REGULATOR_SECTION 0x1000
+#define mmPCI_WR_REGULATOR_BASE 0x7FFC005000ull
+#define PCI_WR_REGULATOR_MAX_OFFSET 0x74
+#define PCI_WR_REGULATOR_SECTION 0x3B000
+#define mmMME1_RTR_BASE 0x7FFC040000ull
+#define MME1_RTR_MAX_OFFSET 0x608
+#define MME1_RTR_SECTION 0x4000
+#define mmMME1_RD_REGULATOR_BASE 0x7FFC044000ull
+#define MME1_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME1_RD_REGULATOR_SECTION 0x1000
+#define mmMME1_WR_REGULATOR_BASE 0x7FFC045000ull
+#define MME1_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME1_WR_REGULATOR_SECTION 0x3B000
+#define mmMME2_RTR_BASE 0x7FFC080000ull
+#define MME2_RTR_MAX_OFFSET 0x608
+#define MME2_RTR_SECTION 0x4000
+#define mmMME2_RD_REGULATOR_BASE 0x7FFC084000ull
+#define MME2_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME2_RD_REGULATOR_SECTION 0x1000
+#define mmMME2_WR_REGULATOR_BASE 0x7FFC085000ull
+#define MME2_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME2_WR_REGULATOR_SECTION 0x3B000
+#define mmMME3_RTR_BASE 0x7FFC0C0000ull
+#define MME3_RTR_MAX_OFFSET 0x608
+#define MME3_RTR_SECTION 0x4000
+#define mmMME3_RD_REGULATOR_BASE 0x7FFC0C4000ull
+#define MME3_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME3_RD_REGULATOR_SECTION 0x1000
+#define mmMME3_WR_REGULATOR_BASE 0x7FFC0C5000ull
+#define MME3_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME3_WR_REGULATOR_SECTION 0xB000
+#define mmMME_BASE 0x7FFC0D0000ull
+#define MME_MAX_OFFSET 0xBB0
+#define MME_SECTION 0x8000
+#define mmMME_QM_BASE 0x7FFC0D8000ull
+#define MME_QM_MAX_OFFSET 0x310
+#define MME_QM_SECTION 0x1000
+#define mmMME_CMDQ_BASE 0x7FFC0D9000ull
+#define MME_CMDQ_MAX_OFFSET 0x310
+#define MME_CMDQ_SECTION 0x1000
+#define mmACC_MS_ECC_MEM_0_BASE 0x7FFC0DA000ull
+#define ACC_MS_ECC_MEM_0_MAX_OFFSET 0x0
+#define ACC_MS_ECC_MEM_0_SECTION 0x1000
+#define mmACC_MS_ECC_MEM_1_BASE 0x7FFC0DB000ull
+#define ACC_MS_ECC_MEM_1_MAX_OFFSET 0x0
+#define ACC_MS_ECC_MEM_1_SECTION 0x1000
+#define mmACC_MS_ECC_MEM_2_BASE 0x7FFC0DC000ull
+#define ACC_MS_ECC_MEM_2_MAX_OFFSET 0x0
+#define ACC_MS_ECC_MEM_2_SECTION 0x1000
+#define mmACC_MS_ECC_MEM_3_BASE 0x7FFC0DD000ull
+#define ACC_MS_ECC_MEM_3_MAX_OFFSET 0x0
+#define ACC_MS_ECC_MEM_3_SECTION 0x1000
+#define mmSBA_ECC_MEM_BASE 0x7FFC0DE000ull
+#define SBA_ECC_MEM_MAX_OFFSET 0x0
+#define SBA_ECC_MEM_SECTION 0x1000
+#define mmSBB_ECC_MEM_BASE 0x7FFC0DF000ull
+#define SBB_ECC_MEM_MAX_OFFSET 0x0
+#define SBB_ECC_MEM_SECTION 0x21000
+#define mmMME4_RTR_BASE 0x7FFC100000ull
+#define MME4_RTR_MAX_OFFSET 0x608
+#define MME4_RTR_SECTION 0x4000
+#define mmMME4_RD_REGULATOR_BASE 0x7FFC104000ull
+#define MME4_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME4_RD_REGULATOR_SECTION 0x1000
+#define mmMME4_WR_REGULATOR_BASE 0x7FFC105000ull
+#define MME4_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME4_WR_REGULATOR_SECTION 0xB000
+#define mmSYNC_MNGR_BASE 0x7FFC110000ull
+#define SYNC_MNGR_MAX_OFFSET 0x4400
+#define SYNC_MNGR_SECTION 0x30000
+#define mmMME5_RTR_BASE 0x7FFC140000ull
+#define MME5_RTR_MAX_OFFSET 0x608
+#define MME5_RTR_SECTION 0x4000
+#define mmMME5_RD_REGULATOR_BASE 0x7FFC144000ull
+#define MME5_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME5_RD_REGULATOR_SECTION 0x1000
+#define mmMME5_WR_REGULATOR_BASE 0x7FFC145000ull
+#define MME5_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME5_WR_REGULATOR_SECTION 0x3B000
+#define mmMME6_RTR_BASE 0x7FFC180000ull
+#define MME6_RTR_MAX_OFFSET 0x608
+#define MME6_RTR_SECTION 0x4000
+#define mmMME6_RD_REGULATOR_BASE 0x7FFC184000ull
+#define MME6_RD_REGULATOR_MAX_OFFSET 0x74
+#define MME6_RD_REGULATOR_SECTION 0x1000
+#define mmMME6_WR_REGULATOR_BASE 0x7FFC185000ull
+#define MME6_WR_REGULATOR_MAX_OFFSET 0x74
+#define MME6_WR_REGULATOR_SECTION 0x3B000
+#define mmDMA_NRTR_BASE 0x7FFC1C0000ull
+#define DMA_NRTR_MAX_OFFSET 0x608
+#define DMA_NRTR_SECTION 0x4000
+#define mmDMA_RD_REGULATOR_BASE 0x7FFC1C4000ull
+#define DMA_RD_REGULATOR_MAX_OFFSET 0x74
+#define DMA_RD_REGULATOR_SECTION 0x1000
+#define mmDMA_WR_REGULATOR_BASE 0x7FFC1C5000ull
+#define DMA_WR_REGULATOR_MAX_OFFSET 0x74
+#define DMA_WR_REGULATOR_SECTION 0x3B000
+#define mmSRAM_Y0_X0_BANK_BASE 0x7FFC200000ull
+#define SRAM_Y0_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y0_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y0_X0_RTR_BASE 0x7FFC201000ull
+#define SRAM_Y0_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y0_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y0_X1_BANK_BASE 0x7FFC204000ull
+#define SRAM_Y0_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y0_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y0_X1_RTR_BASE 0x7FFC205000ull
+#define SRAM_Y0_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y0_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y0_X2_BANK_BASE 0x7FFC208000ull
+#define SRAM_Y0_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y0_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y0_X2_RTR_BASE 0x7FFC209000ull
+#define SRAM_Y0_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y0_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y0_X3_BANK_BASE 0x7FFC20C000ull
+#define SRAM_Y0_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y0_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y0_X3_RTR_BASE 0x7FFC20D000ull
+#define SRAM_Y0_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y0_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y0_X4_BANK_BASE 0x7FFC210000ull
+#define SRAM_Y0_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y0_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y0_X4_RTR_BASE 0x7FFC211000ull
+#define SRAM_Y0_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y0_X4_RTR_SECTION 0xF000
+#define mmSRAM_Y1_X0_BANK_BASE 0x7FFC220000ull
+#define SRAM_Y1_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y1_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y1_X0_RTR_BASE 0x7FFC221000ull
+#define SRAM_Y1_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y1_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y1_X1_BANK_BASE 0x7FFC224000ull
+#define SRAM_Y1_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y1_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y1_X1_RTR_BASE 0x7FFC225000ull
+#define SRAM_Y1_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y1_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y1_X2_BANK_BASE 0x7FFC228000ull
+#define SRAM_Y1_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y1_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y1_X2_RTR_BASE 0x7FFC229000ull
+#define SRAM_Y1_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y1_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y1_X3_BANK_BASE 0x7FFC22C000ull
+#define SRAM_Y1_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y1_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y1_X3_RTR_BASE 0x7FFC22D000ull
+#define SRAM_Y1_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y1_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y1_X4_BANK_BASE 0x7FFC230000ull
+#define SRAM_Y1_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y1_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y1_X4_RTR_BASE 0x7FFC231000ull
+#define SRAM_Y1_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y1_X4_RTR_SECTION 0xF000
+#define mmSRAM_Y2_X0_BANK_BASE 0x7FFC240000ull
+#define SRAM_Y2_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y2_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y2_X0_RTR_BASE 0x7FFC241000ull
+#define SRAM_Y2_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y2_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y2_X1_BANK_BASE 0x7FFC244000ull
+#define SRAM_Y2_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y2_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y2_X1_RTR_BASE 0x7FFC245000ull
+#define SRAM_Y2_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y2_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y2_X2_BANK_BASE 0x7FFC248000ull
+#define SRAM_Y2_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y2_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y2_X2_RTR_BASE 0x7FFC249000ull
+#define SRAM_Y2_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y2_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y2_X3_BANK_BASE 0x7FFC24C000ull
+#define SRAM_Y2_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y2_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y2_X3_RTR_BASE 0x7FFC24D000ull
+#define SRAM_Y2_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y2_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y2_X4_BANK_BASE 0x7FFC250000ull
+#define SRAM_Y2_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y2_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y2_X4_RTR_BASE 0x7FFC251000ull
+#define SRAM_Y2_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y2_X4_RTR_SECTION 0xF000
+#define mmSRAM_Y3_X0_BANK_BASE 0x7FFC260000ull
+#define SRAM_Y3_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y3_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y3_X0_RTR_BASE 0x7FFC261000ull
+#define SRAM_Y3_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y3_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y3_X1_BANK_BASE 0x7FFC264000ull
+#define SRAM_Y3_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y3_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y3_X1_RTR_BASE 0x7FFC265000ull
+#define SRAM_Y3_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y3_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y3_X2_BANK_BASE 0x7FFC268000ull
+#define SRAM_Y3_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y3_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y3_X2_RTR_BASE 0x7FFC269000ull
+#define SRAM_Y3_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y3_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y3_X3_BANK_BASE 0x7FFC26C000ull
+#define SRAM_Y3_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y3_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y3_X3_RTR_BASE 0x7FFC26D000ull
+#define SRAM_Y3_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y3_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y3_X4_BANK_BASE 0x7FFC270000ull
+#define SRAM_Y3_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y3_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y3_X4_RTR_BASE 0x7FFC271000ull
+#define SRAM_Y3_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y3_X4_RTR_SECTION 0xF000
+#define mmSRAM_Y4_X0_BANK_BASE 0x7FFC280000ull
+#define SRAM_Y4_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y4_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y4_X0_RTR_BASE 0x7FFC281000ull
+#define SRAM_Y4_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y4_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y4_X1_BANK_BASE 0x7FFC284000ull
+#define SRAM_Y4_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y4_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y4_X1_RTR_BASE 0x7FFC285000ull
+#define SRAM_Y4_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y4_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y4_X2_BANK_BASE 0x7FFC288000ull
+#define SRAM_Y4_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y4_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y4_X2_RTR_BASE 0x7FFC289000ull
+#define SRAM_Y4_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y4_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y4_X3_BANK_BASE 0x7FFC28C000ull
+#define SRAM_Y4_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y4_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y4_X3_RTR_BASE 0x7FFC28D000ull
+#define SRAM_Y4_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y4_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y4_X4_BANK_BASE 0x7FFC290000ull
+#define SRAM_Y4_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y4_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y4_X4_RTR_BASE 0x7FFC291000ull
+#define SRAM_Y4_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y4_X4_RTR_SECTION 0xF000
+#define mmSRAM_Y5_X0_BANK_BASE 0x7FFC2A0000ull
+#define SRAM_Y5_X0_BANK_MAX_OFFSET 0x4
+#define SRAM_Y5_X0_BANK_SECTION 0x1000
+#define mmSRAM_Y5_X0_RTR_BASE 0x7FFC2A1000ull
+#define SRAM_Y5_X0_RTR_MAX_OFFSET 0x334
+#define SRAM_Y5_X0_RTR_SECTION 0x3000
+#define mmSRAM_Y5_X1_BANK_BASE 0x7FFC2A4000ull
+#define SRAM_Y5_X1_BANK_MAX_OFFSET 0x4
+#define SRAM_Y5_X1_BANK_SECTION 0x1000
+#define mmSRAM_Y5_X1_RTR_BASE 0x7FFC2A5000ull
+#define SRAM_Y5_X1_RTR_MAX_OFFSET 0x334
+#define SRAM_Y5_X1_RTR_SECTION 0x3000
+#define mmSRAM_Y5_X2_BANK_BASE 0x7FFC2A8000ull
+#define SRAM_Y5_X2_BANK_MAX_OFFSET 0x4
+#define SRAM_Y5_X2_BANK_SECTION 0x1000
+#define mmSRAM_Y5_X2_RTR_BASE 0x7FFC2A9000ull
+#define SRAM_Y5_X2_RTR_MAX_OFFSET 0x334
+#define SRAM_Y5_X2_RTR_SECTION 0x3000
+#define mmSRAM_Y5_X3_BANK_BASE 0x7FFC2AC000ull
+#define SRAM_Y5_X3_BANK_MAX_OFFSET 0x4
+#define SRAM_Y5_X3_BANK_SECTION 0x1000
+#define mmSRAM_Y5_X3_RTR_BASE 0x7FFC2AD000ull
+#define SRAM_Y5_X3_RTR_MAX_OFFSET 0x334
+#define SRAM_Y5_X3_RTR_SECTION 0x3000
+#define mmSRAM_Y5_X4_BANK_BASE 0x7FFC2B0000ull
+#define SRAM_Y5_X4_BANK_MAX_OFFSET 0x4
+#define SRAM_Y5_X4_BANK_SECTION 0x1000
+#define mmSRAM_Y5_X4_RTR_BASE 0x7FFC2B1000ull
+#define SRAM_Y5_X4_RTR_MAX_OFFSET 0x334
+#define SRAM_Y5_X4_RTR_SECTION 0x14F000
+#define mmDMA_QM_0_BASE 0x7FFC400000ull
+#define DMA_QM_0_MAX_OFFSET 0x310
+#define DMA_QM_0_SECTION 0x1000
+#define mmDMA_CH_0_BASE 0x7FFC401000ull
+#define DMA_CH_0_MAX_OFFSET 0x200
+#define DMA_CH_0_SECTION 0x7000
+#define mmDMA_QM_1_BASE 0x7FFC408000ull
+#define DMA_QM_1_MAX_OFFSET 0x310
+#define DMA_QM_1_SECTION 0x1000
+#define mmDMA_CH_1_BASE 0x7FFC409000ull
+#define DMA_CH_1_MAX_OFFSET 0x200
+#define DMA_CH_1_SECTION 0x7000
+#define mmDMA_QM_2_BASE 0x7FFC410000ull
+#define DMA_QM_2_MAX_OFFSET 0x310
+#define DMA_QM_2_SECTION 0x1000
+#define mmDMA_CH_2_BASE 0x7FFC411000ull
+#define DMA_CH_2_MAX_OFFSET 0x200
+#define DMA_CH_2_SECTION 0x7000
+#define mmDMA_QM_3_BASE 0x7FFC418000ull
+#define DMA_QM_3_MAX_OFFSET 0x310
+#define DMA_QM_3_SECTION 0x1000
+#define mmDMA_CH_3_BASE 0x7FFC419000ull
+#define DMA_CH_3_MAX_OFFSET 0x200
+#define DMA_CH_3_SECTION 0x7000
+#define mmDMA_QM_4_BASE 0x7FFC420000ull
+#define DMA_QM_4_MAX_OFFSET 0x310
+#define DMA_QM_4_SECTION 0x1000
+#define mmDMA_CH_4_BASE 0x7FFC421000ull
+#define DMA_CH_4_MAX_OFFSET 0x200
+#define DMA_CH_4_SECTION 0x20000
+#define mmCPU_CA53_CFG_BASE 0x7FFC441000ull
+#define CPU_CA53_CFG_MAX_OFFSET 0x218
+#define CPU_CA53_CFG_SECTION 0x1000
+#define mmCPU_IF_BASE 0x7FFC442000ull
+#define CPU_IF_MAX_OFFSET 0x134
+#define CPU_IF_SECTION 0x2000
+#define mmCPU_TIMESTAMP_BASE 0x7FFC444000ull
+#define CPU_TIMESTAMP_MAX_OFFSET 0x1000
+#define CPU_TIMESTAMP_SECTION 0x3C000
+#define mmMMU_BASE 0x7FFC480000ull
+#define MMU_MAX_OFFSET 0x44
+#define MMU_SECTION 0x10000
+#define mmSTLB_BASE 0x7FFC490000ull
+#define STLB_MAX_OFFSET 0x50
+#define STLB_SECTION 0x10000
+#define mmNORTH_THERMAL_SENSOR_BASE 0x7FFC4A0000ull
+#define NORTH_THERMAL_SENSOR_MAX_OFFSET 0xE64
+#define NORTH_THERMAL_SENSOR_SECTION 0x1000
+#define mmMC_PLL_BASE 0x7FFC4A1000ull
+#define MC_PLL_MAX_OFFSET 0x444
+#define MC_PLL_SECTION 0x1000
+#define mmCPU_PLL_BASE 0x7FFC4A2000ull
+#define CPU_PLL_MAX_OFFSET 0x444
+#define CPU_PLL_SECTION 0x1000
+#define mmIC_PLL_BASE 0x7FFC4A3000ull
+#define IC_PLL_MAX_OFFSET 0x444
+#define IC_PLL_SECTION 0x1000
+#define mmDMA_PROCESS_MON_BASE 0x7FFC4A4000ull
+#define DMA_PROCESS_MON_MAX_OFFSET 0x4
+#define DMA_PROCESS_MON_SECTION 0xC000
+#define mmDMA_MACRO_BASE 0x7FFC4B0000ull
+#define DMA_MACRO_MAX_OFFSET 0x15C
+#define DMA_MACRO_SECTION 0x150000
+#define mmDDR_PHY_CH0_BASE 0x7FFC600000ull
+#define DDR_PHY_CH0_MAX_OFFSET 0x0
+#define DDR_PHY_CH0_SECTION 0x40000
+#define mmDDR_MC_CH0_BASE 0x7FFC640000ull
+#define DDR_MC_CH0_MAX_OFFSET 0xF34
+#define DDR_MC_CH0_SECTION 0x8000
+#define mmDDR_MISC_CH0_BASE 0x7FFC648000ull
+#define DDR_MISC_CH0_MAX_OFFSET 0x204
+#define DDR_MISC_CH0_SECTION 0xB8000
+#define mmDDR_PHY_CH1_BASE 0x7FFC700000ull
+#define DDR_PHY_CH1_MAX_OFFSET 0x0
+#define DDR_PHY_CH1_SECTION 0x40000
+#define mmDDR_MC_CH1_BASE 0x7FFC740000ull
+#define DDR_MC_CH1_MAX_OFFSET 0xF34
+#define DDR_MC_CH1_SECTION 0x8000
+#define mmDDR_MISC_CH1_BASE 0x7FFC748000ull
+#define DDR_MISC_CH1_MAX_OFFSET 0x204
+#define DDR_MISC_CH1_SECTION 0xB8000
+#define mmGIC_BASE 0x7FFC800000ull
+#define GIC_MAX_OFFSET 0x10000
+#define GIC_SECTION 0x401000
+#define mmPCIE_WRAP_BASE 0x7FFCC01000ull
+#define PCIE_WRAP_MAX_OFFSET 0xDF4
+#define PCIE_WRAP_SECTION 0x1000
+#define mmPCIE_DBI_BASE 0x7FFCC02000ull
+#define PCIE_DBI_MAX_OFFSET 0xC04
+#define PCIE_DBI_SECTION 0x2000
+#define mmPCIE_CORE_BASE 0x7FFCC04000ull
+#define PCIE_CORE_MAX_OFFSET 0x9B8
+#define PCIE_CORE_SECTION 0x1000
+#define mmPCIE_DB_CFG_BASE 0x7FFCC05000ull
+#define PCIE_DB_CFG_MAX_OFFSET 0xE34
+#define PCIE_DB_CFG_SECTION 0x1000
+#define mmPCIE_DB_CMD_BASE 0x7FFCC06000ull
+#define PCIE_DB_CMD_MAX_OFFSET 0x810
+#define PCIE_DB_CMD_SECTION 0x1000
+#define mmPCIE_AUX_BASE 0x7FFCC07000ull
+#define PCIE_AUX_MAX_OFFSET 0x9BC
+#define PCIE_AUX_SECTION 0x1000
+#define mmPCIE_DB_RSV_BASE 0x7FFCC08000ull
+#define PCIE_DB_RSV_MAX_OFFSET 0x800
+#define PCIE_DB_RSV_SECTION 0x8000
+#define mmPCIE_PHY_BASE 0x7FFCC10000ull
+#define PCIE_PHY_MAX_OFFSET 0x924
+#define PCIE_PHY_SECTION 0x30000
+#define mmPSOC_I2C_M0_BASE 0x7FFCC40000ull
+#define PSOC_I2C_M0_MAX_OFFSET 0x100
+#define PSOC_I2C_M0_SECTION 0x1000
+#define mmPSOC_I2C_M1_BASE 0x7FFCC41000ull
+#define PSOC_I2C_M1_MAX_OFFSET 0x100
+#define PSOC_I2C_M1_SECTION 0x1000
+#define mmPSOC_I2C_S_BASE 0x7FFCC42000ull
+#define PSOC_I2C_S_MAX_OFFSET 0x100
+#define PSOC_I2C_S_SECTION 0x1000
+#define mmPSOC_SPI_BASE 0x7FFCC43000ull
+#define PSOC_SPI_MAX_OFFSET 0x100
+#define PSOC_SPI_SECTION 0x1000
+#define mmPSOC_EMMC_BASE 0x7FFCC44000ull
+#define PSOC_EMMC_MAX_OFFSET 0xF70
+#define PSOC_EMMC_SECTION 0x1000
+#define mmPSOC_UART_0_BASE 0x7FFCC45000ull
+#define PSOC_UART_0_MAX_OFFSET 0x1000
+#define PSOC_UART_0_SECTION 0x1000
+#define mmPSOC_UART_1_BASE 0x7FFCC46000ull
+#define PSOC_UART_1_MAX_OFFSET 0x1000
+#define PSOC_UART_1_SECTION 0x1000
+#define mmPSOC_TIMER_BASE 0x7FFCC47000ull
+#define PSOC_TIMER_MAX_OFFSET 0x1000
+#define PSOC_TIMER_SECTION 0x1000
+#define mmPSOC_WDOG_BASE 0x7FFCC48000ull
+#define PSOC_WDOG_MAX_OFFSET 0x1000
+#define PSOC_WDOG_SECTION 0x1000
+#define mmPSOC_TIMESTAMP_BASE 0x7FFCC49000ull
+#define PSOC_TIMESTAMP_MAX_OFFSET 0x1000
+#define PSOC_TIMESTAMP_SECTION 0x1000
+#define mmPSOC_EFUSE_BASE 0x7FFCC4A000ull
+#define PSOC_EFUSE_MAX_OFFSET 0x10C
+#define PSOC_EFUSE_SECTION 0x1000
+#define mmPSOC_GLOBAL_CONF_BASE 0x7FFCC4B000ull
+#define PSOC_GLOBAL_CONF_MAX_OFFSET 0xA48
+#define PSOC_GLOBAL_CONF_SECTION 0x1000
+#define mmPSOC_GPIO0_BASE 0x7FFCC4C000ull
+#define PSOC_GPIO0_MAX_OFFSET 0x1000
+#define PSOC_GPIO0_SECTION 0x1000
+#define mmPSOC_GPIO1_BASE 0x7FFCC4D000ull
+#define PSOC_GPIO1_MAX_OFFSET 0x1000
+#define PSOC_GPIO1_SECTION 0x1000
+#define mmPSOC_BTL_BASE 0x7FFCC4E000ull
+#define PSOC_BTL_MAX_OFFSET 0x124
+#define PSOC_BTL_SECTION 0x1000
+#define mmPSOC_CS_TRACE_BASE 0x7FFCC4F000ull
+#define PSOC_CS_TRACE_MAX_OFFSET 0x0
+#define PSOC_CS_TRACE_SECTION 0x1000
+#define mmPSOC_GPIO2_BASE 0x7FFCC50000ull
+#define PSOC_GPIO2_MAX_OFFSET 0x1000
+#define PSOC_GPIO2_SECTION 0x1000
+#define mmPSOC_GPIO3_BASE 0x7FFCC51000ull
+#define PSOC_GPIO3_MAX_OFFSET 0x1000
+#define PSOC_GPIO3_SECTION 0x1000
+#define mmPSOC_GPIO4_BASE 0x7FFCC52000ull
+#define PSOC_GPIO4_MAX_OFFSET 0x1000
+#define PSOC_GPIO4_SECTION 0x1000
+#define mmPSOC_DFT_EFUSE_BASE 0x7FFCC53000ull
+#define PSOC_DFT_EFUSE_MAX_OFFSET 0x10C
+#define PSOC_DFT_EFUSE_SECTION 0x1000
+#define mmPSOC_PM_BASE 0x7FFCC54000ull
+#define PSOC_PM_MAX_OFFSET 0x4
+#define PSOC_PM_SECTION 0x1000
+#define mmPSOC_TS_BASE 0x7FFCC55000ull
+#define PSOC_TS_MAX_OFFSET 0xE64
+#define PSOC_TS_SECTION 0xB000
+#define mmPSOC_MII_BASE 0x7FFCC60000ull
+#define PSOC_MII_MAX_OFFSET 0x105C
+#define PSOC_MII_SECTION 0x10000
+#define mmPSOC_EMMC_PLL_BASE 0x7FFCC70000ull
+#define PSOC_EMMC_PLL_MAX_OFFSET 0x444
+#define PSOC_EMMC_PLL_SECTION 0x1000
+#define mmPSOC_MME_PLL_BASE 0x7FFCC71000ull
+#define PSOC_MME_PLL_MAX_OFFSET 0x444
+#define PSOC_MME_PLL_SECTION 0x1000
+#define mmPSOC_PCI_PLL_BASE 0x7FFCC72000ull
+#define PSOC_PCI_PLL_MAX_OFFSET 0x444
+#define PSOC_PCI_PLL_SECTION 0x6000
+#define mmPSOC_PWM0_BASE 0x7FFCC78000ull
+#define PSOC_PWM0_MAX_OFFSET 0x58
+#define PSOC_PWM0_SECTION 0x1000
+#define mmPSOC_PWM1_BASE 0x7FFCC79000ull
+#define PSOC_PWM1_MAX_OFFSET 0x58
+#define PSOC_PWM1_SECTION 0x1000
+#define mmPSOC_PWM2_BASE 0x7FFCC7A000ull
+#define PSOC_PWM2_MAX_OFFSET 0x58
+#define PSOC_PWM2_SECTION 0x1000
+#define mmPSOC_PWM3_BASE 0x7FFCC7B000ull
+#define PSOC_PWM3_MAX_OFFSET 0x58
+#define PSOC_PWM3_SECTION 0x185000
+#define mmTPC0_NRTR_BASE 0x7FFCE00000ull
+#define TPC0_NRTR_MAX_OFFSET 0x608
+#define TPC0_NRTR_SECTION 0x1000
+#define mmTPC_PLL_BASE 0x7FFCE01000ull
+#define TPC_PLL_MAX_OFFSET 0x444
+#define TPC_PLL_SECTION 0x1000
+#define mmTPC_THEMAL_SENSOR_BASE 0x7FFCE02000ull
+#define TPC_THEMAL_SENSOR_MAX_OFFSET 0xE64
+#define TPC_THEMAL_SENSOR_SECTION 0x1000
+#define mmTPC_PROCESS_MON_BASE 0x7FFCE03000ull
+#define TPC_PROCESS_MON_MAX_OFFSET 0x4
+#define TPC_PROCESS_MON_SECTION 0x1000
+#define mmTPC0_RD_REGULATOR_BASE 0x7FFCE04000ull
+#define TPC0_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC0_RD_REGULATOR_SECTION 0x1000
+#define mmTPC0_WR_REGULATOR_BASE 0x7FFCE05000ull
+#define TPC0_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC0_WR_REGULATOR_SECTION 0x1000
+#define mmTPC0_CFG_BASE 0x7FFCE06000ull
+#define TPC0_CFG_MAX_OFFSET 0xE30
+#define TPC0_CFG_SECTION 0x2000
+#define mmTPC0_QM_BASE 0x7FFCE08000ull
+#define TPC0_QM_MAX_OFFSET 0x310
+#define TPC0_QM_SECTION 0x1000
+#define mmTPC0_CMDQ_BASE 0x7FFCE09000ull
+#define TPC0_CMDQ_MAX_OFFSET 0x310
+#define TPC0_CMDQ_SECTION 0x37000
+#define mmTPC1_RTR_BASE 0x7FFCE40000ull
+#define TPC1_RTR_MAX_OFFSET 0x608
+#define TPC1_RTR_SECTION 0x4000
+#define mmTPC1_WR_REGULATOR_BASE 0x7FFCE44000ull
+#define TPC1_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC1_WR_REGULATOR_SECTION 0x1000
+#define mmTPC1_RD_REGULATOR_BASE 0x7FFCE45000ull
+#define TPC1_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC1_RD_REGULATOR_SECTION 0x1000
+#define mmTPC1_CFG_BASE 0x7FFCE46000ull
+#define TPC1_CFG_MAX_OFFSET 0xE30
+#define TPC1_CFG_SECTION 0x2000
+#define mmTPC1_QM_BASE 0x7FFCE48000ull
+#define TPC1_QM_MAX_OFFSET 0x310
+#define TPC1_QM_SECTION 0x1000
+#define mmTPC1_CMDQ_BASE 0x7FFCE49000ull
+#define TPC1_CMDQ_MAX_OFFSET 0x310
+#define TPC1_CMDQ_SECTION 0x37000
+#define mmTPC2_RTR_BASE 0x7FFCE80000ull
+#define TPC2_RTR_MAX_OFFSET 0x608
+#define TPC2_RTR_SECTION 0x4000
+#define mmTPC2_RD_REGULATOR_BASE 0x7FFCE84000ull
+#define TPC2_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC2_RD_REGULATOR_SECTION 0x1000
+#define mmTPC2_WR_REGULATOR_BASE 0x7FFCE85000ull
+#define TPC2_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC2_WR_REGULATOR_SECTION 0x1000
+#define mmTPC2_CFG_BASE 0x7FFCE86000ull
+#define TPC2_CFG_MAX_OFFSET 0xE30
+#define TPC2_CFG_SECTION 0x2000
+#define mmTPC2_QM_BASE 0x7FFCE88000ull
+#define TPC2_QM_MAX_OFFSET 0x310
+#define TPC2_QM_SECTION 0x1000
+#define mmTPC2_CMDQ_BASE 0x7FFCE89000ull
+#define TPC2_CMDQ_MAX_OFFSET 0x310
+#define TPC2_CMDQ_SECTION 0x37000
+#define mmTPC3_RTR_BASE 0x7FFCEC0000ull
+#define TPC3_RTR_MAX_OFFSET 0x608
+#define TPC3_RTR_SECTION 0x4000
+#define mmTPC3_RD_REGULATOR_BASE 0x7FFCEC4000ull
+#define TPC3_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC3_RD_REGULATOR_SECTION 0x1000
+#define mmTPC3_WR_REGULATOR_BASE 0x7FFCEC5000ull
+#define TPC3_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC3_WR_REGULATOR_SECTION 0x1000
+#define mmTPC3_CFG_BASE 0x7FFCEC6000ull
+#define TPC3_CFG_MAX_OFFSET 0xE30
+#define TPC3_CFG_SECTION 0x2000
+#define mmTPC3_QM_BASE 0x7FFCEC8000ull
+#define TPC3_QM_MAX_OFFSET 0x310
+#define TPC3_QM_SECTION 0x1000
+#define mmTPC3_CMDQ_BASE 0x7FFCEC9000ull
+#define TPC3_CMDQ_MAX_OFFSET 0x310
+#define TPC3_CMDQ_SECTION 0x37000
+#define mmTPC4_RTR_BASE 0x7FFCF00000ull
+#define TPC4_RTR_MAX_OFFSET 0x608
+#define TPC4_RTR_SECTION 0x4000
+#define mmTPC4_RD_REGULATOR_BASE 0x7FFCF04000ull
+#define TPC4_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC4_RD_REGULATOR_SECTION 0x1000
+#define mmTPC4_WR_REGULATOR_BASE 0x7FFCF05000ull
+#define TPC4_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC4_WR_REGULATOR_SECTION 0x1000
+#define mmTPC4_CFG_BASE 0x7FFCF06000ull
+#define TPC4_CFG_MAX_OFFSET 0xE30
+#define TPC4_CFG_SECTION 0x2000
+#define mmTPC4_QM_BASE 0x7FFCF08000ull
+#define TPC4_QM_MAX_OFFSET 0x310
+#define TPC4_QM_SECTION 0x1000
+#define mmTPC4_CMDQ_BASE 0x7FFCF09000ull
+#define TPC4_CMDQ_MAX_OFFSET 0x310
+#define TPC4_CMDQ_SECTION 0x37000
+#define mmTPC5_RTR_BASE 0x7FFCF40000ull
+#define TPC5_RTR_MAX_OFFSET 0x608
+#define TPC5_RTR_SECTION 0x4000
+#define mmTPC5_RD_REGULATOR_BASE 0x7FFCF44000ull
+#define TPC5_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC5_RD_REGULATOR_SECTION 0x1000
+#define mmTPC5_WR_REGULATOR_BASE 0x7FFCF45000ull
+#define TPC5_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC5_WR_REGULATOR_SECTION 0x1000
+#define mmTPC5_CFG_BASE 0x7FFCF46000ull
+#define TPC5_CFG_MAX_OFFSET 0xE30
+#define TPC5_CFG_SECTION 0x2000
+#define mmTPC5_QM_BASE 0x7FFCF48000ull
+#define TPC5_QM_MAX_OFFSET 0x310
+#define TPC5_QM_SECTION 0x1000
+#define mmTPC5_CMDQ_BASE 0x7FFCF49000ull
+#define TPC5_CMDQ_MAX_OFFSET 0x310
+#define TPC5_CMDQ_SECTION 0x37000
+#define mmTPC6_RTR_BASE 0x7FFCF80000ull
+#define TPC6_RTR_MAX_OFFSET 0x608
+#define TPC6_RTR_SECTION 0x4000
+#define mmTPC6_RD_REGULATOR_BASE 0x7FFCF84000ull
+#define TPC6_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC6_RD_REGULATOR_SECTION 0x1000
+#define mmTPC6_WR_REGULATOR_BASE 0x7FFCF85000ull
+#define TPC6_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC6_WR_REGULATOR_SECTION 0x1000
+#define mmTPC6_CFG_BASE 0x7FFCF86000ull
+#define TPC6_CFG_MAX_OFFSET 0xE30
+#define TPC6_CFG_SECTION 0x2000
+#define mmTPC6_QM_BASE 0x7FFCF88000ull
+#define TPC6_QM_MAX_OFFSET 0x310
+#define TPC6_QM_SECTION 0x1000
+#define mmTPC6_CMDQ_BASE 0x7FFCF89000ull
+#define TPC6_CMDQ_MAX_OFFSET 0x310
+#define TPC6_CMDQ_SECTION 0x37000
+#define mmTPC7_NRTR_BASE 0x7FFCFC0000ull
+#define TPC7_NRTR_MAX_OFFSET 0x608
+#define TPC7_NRTR_SECTION 0x4000
+#define mmTPC7_RD_REGULATOR_BASE 0x7FFCFC4000ull
+#define TPC7_RD_REGULATOR_MAX_OFFSET 0x74
+#define TPC7_RD_REGULATOR_SECTION 0x1000
+#define mmTPC7_WR_REGULATOR_BASE 0x7FFCFC5000ull
+#define TPC7_WR_REGULATOR_MAX_OFFSET 0x74
+#define TPC7_WR_REGULATOR_SECTION 0x1000
+#define mmTPC7_CFG_BASE 0x7FFCFC6000ull
+#define TPC7_CFG_MAX_OFFSET 0xE30
+#define TPC7_CFG_SECTION 0x2000
+#define mmTPC7_QM_BASE 0x7FFCFC8000ull
+#define TPC7_QM_MAX_OFFSET 0x310
+#define TPC7_QM_SECTION 0x1000
+#define mmTPC7_CMDQ_BASE 0x7FFCFC9000ull
+#define TPC7_CMDQ_MAX_OFFSET 0x310
+#define TPC7_CMDQ_SECTION 0x1037000
+#define mmMME_TOP_TABLE_BASE 0x7FFE000000ull
+#define MME_TOP_TABLE_MAX_OFFSET 0x1000
+#define MME_TOP_TABLE_SECTION 0x1000
+#define mmMME0_RTR_FUNNEL_BASE 0x7FFE001000ull
+#define MME0_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME0_RTR_FUNNEL_SECTION 0x40000
+#define mmMME1_RTR_FUNNEL_BASE 0x7FFE041000ull
+#define MME1_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME1_RTR_FUNNEL_SECTION 0x1000
+#define mmMME1_SBA_STM_BASE 0x7FFE042000ull
+#define MME1_SBA_STM_MAX_OFFSET 0x1000
+#define MME1_SBA_STM_SECTION 0x1000
+#define mmMME1_SBA_CTI_BASE 0x7FFE043000ull
+#define MME1_SBA_CTI_MAX_OFFSET 0x1000
+#define MME1_SBA_CTI_SECTION 0x1000
+#define mmMME1_SBA_ETF_BASE 0x7FFE044000ull
+#define MME1_SBA_ETF_MAX_OFFSET 0x1000
+#define MME1_SBA_ETF_SECTION 0x1000
+#define mmMME1_SBA_SPMU_BASE 0x7FFE045000ull
+#define MME1_SBA_SPMU_MAX_OFFSET 0x1000
+#define MME1_SBA_SPMU_SECTION 0x1000
+#define mmMME1_SBA_CTI0_BASE 0x7FFE046000ull
+#define MME1_SBA_CTI0_MAX_OFFSET 0x1000
+#define MME1_SBA_CTI0_SECTION 0x1000
+#define mmMME1_SBA_CTI1_BASE 0x7FFE047000ull
+#define MME1_SBA_CTI1_MAX_OFFSET 0x1000
+#define MME1_SBA_CTI1_SECTION 0x1000
+#define mmMME1_SBA_BMON0_BASE 0x7FFE048000ull
+#define MME1_SBA_BMON0_MAX_OFFSET 0x1000
+#define MME1_SBA_BMON0_SECTION 0x1000
+#define mmMME1_SBA_BMON1_BASE 0x7FFE049000ull
+#define MME1_SBA_BMON1_MAX_OFFSET 0x1000
+#define MME1_SBA_BMON1_SECTION 0x38000
+#define mmMME2_RTR_FUNNEL_BASE 0x7FFE081000ull
+#define MME2_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME2_RTR_FUNNEL_SECTION 0x40000
+#define mmMME3_RTR_FUNNEL_BASE 0x7FFE0C1000ull
+#define MME3_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME3_RTR_FUNNEL_SECTION 0x1000
+#define mmMME3_SBB_STM_BASE 0x7FFE0C2000ull
+#define MME3_SBB_STM_MAX_OFFSET 0x1000
+#define MME3_SBB_STM_SECTION 0x1000
+#define mmMME3_SBB_CTI_BASE 0x7FFE0C3000ull
+#define MME3_SBB_CTI_MAX_OFFSET 0x1000
+#define MME3_SBB_CTI_SECTION 0x1000
+#define mmMME3_SBB_ETF_BASE 0x7FFE0C4000ull
+#define MME3_SBB_ETF_MAX_OFFSET 0x1000
+#define MME3_SBB_ETF_SECTION 0x1000
+#define mmMME3_SBB_SPMU_BASE 0x7FFE0C5000ull
+#define MME3_SBB_SPMU_MAX_OFFSET 0x1000
+#define MME3_SBB_SPMU_SECTION 0x1000
+#define mmMME3_SBB_CTI0_BASE 0x7FFE0C6000ull
+#define MME3_SBB_CTI0_MAX_OFFSET 0x1000
+#define MME3_SBB_CTI0_SECTION 0x1000
+#define mmMME3_SBB_CTI1_BASE 0x7FFE0C7000ull
+#define MME3_SBB_CTI1_MAX_OFFSET 0x1000
+#define MME3_SBB_CTI1_SECTION 0x1000
+#define mmMME3_SBB_BMON0_BASE 0x7FFE0C8000ull
+#define MME3_SBB_BMON0_MAX_OFFSET 0x1000
+#define MME3_SBB_BMON0_SECTION 0x1000
+#define mmMME3_SBB_BMON1_BASE 0x7FFE0C9000ull
+#define MME3_SBB_BMON1_MAX_OFFSET 0x1000
+#define MME3_SBB_BMON1_SECTION 0x38000
+#define mmMME4_RTR_FUNNEL_BASE 0x7FFE101000ull
+#define MME4_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME4_RTR_FUNNEL_SECTION 0x1000
+#define mmMME4_WACS_STM_BASE 0x7FFE102000ull
+#define MME4_WACS_STM_MAX_OFFSET 0x1000
+#define MME4_WACS_STM_SECTION 0x1000
+#define mmMME4_WACS_CTI_BASE 0x7FFE103000ull
+#define MME4_WACS_CTI_MAX_OFFSET 0x1000
+#define MME4_WACS_CTI_SECTION 0x1000
+#define mmMME4_WACS_ETF_BASE 0x7FFE104000ull
+#define MME4_WACS_ETF_MAX_OFFSET 0x1000
+#define MME4_WACS_ETF_SECTION 0x1000
+#define mmMME4_WACS_SPMU_BASE 0x7FFE105000ull
+#define MME4_WACS_SPMU_MAX_OFFSET 0x1000
+#define MME4_WACS_SPMU_SECTION 0x1000
+#define mmMME4_WACS_CTI0_BASE 0x7FFE106000ull
+#define MME4_WACS_CTI0_MAX_OFFSET 0x1000
+#define MME4_WACS_CTI0_SECTION 0x1000
+#define mmMME4_WACS_CTI1_BASE 0x7FFE107000ull
+#define MME4_WACS_CTI1_MAX_OFFSET 0x1000
+#define MME4_WACS_CTI1_SECTION 0x1000
+#define mmMME4_WACS_BMON0_BASE 0x7FFE108000ull
+#define MME4_WACS_BMON0_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON0_SECTION 0x1000
+#define mmMME4_WACS_BMON1_BASE 0x7FFE109000ull
+#define MME4_WACS_BMON1_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON1_SECTION 0x1000
+#define mmMME4_WACS_BMON2_BASE 0x7FFE10A000ull
+#define MME4_WACS_BMON2_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON2_SECTION 0x1000
+#define mmMME4_WACS_BMON3_BASE 0x7FFE10B000ull
+#define MME4_WACS_BMON3_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON3_SECTION 0x1000
+#define mmMME4_WACS_BMON4_BASE 0x7FFE10C000ull
+#define MME4_WACS_BMON4_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON4_SECTION 0x1000
+#define mmMME4_WACS_BMON5_BASE 0x7FFE10D000ull
+#define MME4_WACS_BMON5_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON5_SECTION 0x1000
+#define mmMME4_WACS_BMON6_BASE 0x7FFE10E000ull
+#define MME4_WACS_BMON6_MAX_OFFSET 0x1000
+#define MME4_WACS_BMON6_SECTION 0x4000
+#define mmMME4_WACS2_STM_BASE 0x7FFE112000ull
+#define MME4_WACS2_STM_MAX_OFFSET 0x1000
+#define MME4_WACS2_STM_SECTION 0x1000
+#define mmMME4_WACS2_CTI_BASE 0x7FFE113000ull
+#define MME4_WACS2_CTI_MAX_OFFSET 0x1000
+#define MME4_WACS2_CTI_SECTION 0x1000
+#define mmMME4_WACS2_ETF_BASE 0x7FFE114000ull
+#define MME4_WACS2_ETF_MAX_OFFSET 0x1000
+#define MME4_WACS2_ETF_SECTION 0x1000
+#define mmMME4_WACS2_SPMU_BASE 0x7FFE115000ull
+#define MME4_WACS2_SPMU_MAX_OFFSET 0x1000
+#define MME4_WACS2_SPMU_SECTION 0x1000
+#define mmMME4_WACS2_CTI0_BASE 0x7FFE116000ull
+#define MME4_WACS2_CTI0_MAX_OFFSET 0x1000
+#define MME4_WACS2_CTI0_SECTION 0x1000
+#define mmMME4_WACS2_CTI1_BASE 0x7FFE117000ull
+#define MME4_WACS2_CTI1_MAX_OFFSET 0x1000
+#define MME4_WACS2_CTI1_SECTION 0x1000
+#define mmMME4_WACS2_BMON0_BASE 0x7FFE118000ull
+#define MME4_WACS2_BMON0_MAX_OFFSET 0x1000
+#define MME4_WACS2_BMON0_SECTION 0x1000
+#define mmMME4_WACS2_BMON1_BASE 0x7FFE119000ull
+#define MME4_WACS2_BMON1_MAX_OFFSET 0x1000
+#define MME4_WACS2_BMON1_SECTION 0x1000
+#define mmMME4_WACS2_BMON2_BASE 0x7FFE11A000ull
+#define MME4_WACS2_BMON2_MAX_OFFSET 0x1000
+#define MME4_WACS2_BMON2_SECTION 0x27000
+#define mmMME5_RTR_FUNNEL_BASE 0x7FFE141000ull
+#define MME5_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define MME5_RTR_FUNNEL_SECTION 0x2BF000
+#define mmDMA_ROM_TABLE_BASE 0x7FFE400000ull
+#define DMA_ROM_TABLE_MAX_OFFSET 0x1000
+#define DMA_ROM_TABLE_SECTION 0x1000
+#define mmDMA_CH_0_CS_STM_BASE 0x7FFE401000ull
+#define DMA_CH_0_CS_STM_MAX_OFFSET 0x1000
+#define DMA_CH_0_CS_STM_SECTION 0x1000
+#define mmDMA_CH_0_CS_CTI_BASE 0x7FFE402000ull
+#define DMA_CH_0_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_0_CS_CTI_SECTION 0x1000
+#define mmDMA_CH_0_CS_ETF_BASE 0x7FFE403000ull
+#define DMA_CH_0_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_CH_0_CS_ETF_SECTION 0x1000
+#define mmDMA_CH_0_CS_SPMU_BASE 0x7FFE404000ull
+#define DMA_CH_0_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_CH_0_CS_SPMU_SECTION 0x1000
+#define mmDMA_CH_0_BMON_CTI_BASE 0x7FFE405000ull
+#define DMA_CH_0_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_0_BMON_CTI_SECTION 0x1000
+#define mmDMA_CH_0_USER_CTI_BASE 0x7FFE406000ull
+#define DMA_CH_0_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_0_USER_CTI_SECTION 0x1000
+#define mmDMA_CH_0_BMON_0_BASE 0x7FFE407000ull
+#define DMA_CH_0_BMON_0_MAX_OFFSET 0x1000
+#define DMA_CH_0_BMON_0_SECTION 0x1000
+#define mmDMA_CH_0_BMON_1_BASE 0x7FFE408000ull
+#define DMA_CH_0_BMON_1_MAX_OFFSET 0x1000
+#define DMA_CH_0_BMON_1_SECTION 0x9000
+#define mmDMA_CH_1_CS_STM_BASE 0x7FFE411000ull
+#define DMA_CH_1_CS_STM_MAX_OFFSET 0x1000
+#define DMA_CH_1_CS_STM_SECTION 0x1000
+#define mmDMA_CH_1_CS_CTI_BASE 0x7FFE412000ull
+#define DMA_CH_1_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_1_CS_CTI_SECTION 0x1000
+#define mmDMA_CH_1_CS_ETF_BASE 0x7FFE413000ull
+#define DMA_CH_1_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_CH_1_CS_ETF_SECTION 0x1000
+#define mmDMA_CH_1_CS_SPMU_BASE 0x7FFE414000ull
+#define DMA_CH_1_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_CH_1_CS_SPMU_SECTION 0x1000
+#define mmDMA_CH_1_BMON_CTI_BASE 0x7FFE415000ull
+#define DMA_CH_1_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_1_BMON_CTI_SECTION 0x1000
+#define mmDMA_CH_1_USER_CTI_BASE 0x7FFE416000ull
+#define DMA_CH_1_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_1_USER_CTI_SECTION 0x1000
+#define mmDMA_CH_1_BMON_0_BASE 0x7FFE417000ull
+#define DMA_CH_1_BMON_0_MAX_OFFSET 0x1000
+#define DMA_CH_1_BMON_0_SECTION 0x1000
+#define mmDMA_CH_1_BMON_1_BASE 0x7FFE418000ull
+#define DMA_CH_1_BMON_1_MAX_OFFSET 0x1000
+#define DMA_CH_1_BMON_1_SECTION 0x9000
+#define mmDMA_CH_2_CS_STM_BASE 0x7FFE421000ull
+#define DMA_CH_2_CS_STM_MAX_OFFSET 0x1000
+#define DMA_CH_2_CS_STM_SECTION 0x1000
+#define mmDMA_CH_2_CS_CTI_BASE 0x7FFE422000ull
+#define DMA_CH_2_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_2_CS_CTI_SECTION 0x1000
+#define mmDMA_CH_2_CS_ETF_BASE 0x7FFE423000ull
+#define DMA_CH_2_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_CH_2_CS_ETF_SECTION 0x1000
+#define mmDMA_CH_2_CS_SPMU_BASE 0x7FFE424000ull
+#define DMA_CH_2_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_CH_2_CS_SPMU_SECTION 0x1000
+#define mmDMA_CH_2_BMON_CTI_BASE 0x7FFE425000ull
+#define DMA_CH_2_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_2_BMON_CTI_SECTION 0x1000
+#define mmDMA_CH_2_USER_CTI_BASE 0x7FFE426000ull
+#define DMA_CH_2_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_2_USER_CTI_SECTION 0x1000
+#define mmDMA_CH_2_BMON_0_BASE 0x7FFE427000ull
+#define DMA_CH_2_BMON_0_MAX_OFFSET 0x1000
+#define DMA_CH_2_BMON_0_SECTION 0x1000
+#define mmDMA_CH_2_BMON_1_BASE 0x7FFE428000ull
+#define DMA_CH_2_BMON_1_MAX_OFFSET 0x1000
+#define DMA_CH_2_BMON_1_SECTION 0x9000
+#define mmDMA_CH_3_CS_STM_BASE 0x7FFE431000ull
+#define DMA_CH_3_CS_STM_MAX_OFFSET 0x1000
+#define DMA_CH_3_CS_STM_SECTION 0x1000
+#define mmDMA_CH_3_CS_CTI_BASE 0x7FFE432000ull
+#define DMA_CH_3_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_3_CS_CTI_SECTION 0x1000
+#define mmDMA_CH_3_CS_ETF_BASE 0x7FFE433000ull
+#define DMA_CH_3_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_CH_3_CS_ETF_SECTION 0x1000
+#define mmDMA_CH_3_CS_SPMU_BASE 0x7FFE434000ull
+#define DMA_CH_3_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_CH_3_CS_SPMU_SECTION 0x1000
+#define mmDMA_CH_3_BMON_CTI_BASE 0x7FFE435000ull
+#define DMA_CH_3_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_3_BMON_CTI_SECTION 0x1000
+#define mmDMA_CH_3_USER_CTI_BASE 0x7FFE436000ull
+#define DMA_CH_3_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_3_USER_CTI_SECTION 0x1000
+#define mmDMA_CH_3_BMON_0_BASE 0x7FFE437000ull
+#define DMA_CH_3_BMON_0_MAX_OFFSET 0x1000
+#define DMA_CH_3_BMON_0_SECTION 0x1000
+#define mmDMA_CH_3_BMON_1_BASE 0x7FFE438000ull
+#define DMA_CH_3_BMON_1_MAX_OFFSET 0x1000
+#define DMA_CH_3_BMON_1_SECTION 0x9000
+#define mmDMA_CH_4_CS_STM_BASE 0x7FFE441000ull
+#define DMA_CH_4_CS_STM_MAX_OFFSET 0x1000
+#define DMA_CH_4_CS_STM_SECTION 0x1000
+#define mmDMA_CH_4_CS_CTI_BASE 0x7FFE442000ull
+#define DMA_CH_4_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_4_CS_CTI_SECTION 0x1000
+#define mmDMA_CH_4_CS_ETF_BASE 0x7FFE443000ull
+#define DMA_CH_4_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_CH_4_CS_ETF_SECTION 0x1000
+#define mmDMA_CH_4_CS_SPMU_BASE 0x7FFE444000ull
+#define DMA_CH_4_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_CH_4_CS_SPMU_SECTION 0x1000
+#define mmDMA_CH_4_BMON_CTI_BASE 0x7FFE445000ull
+#define DMA_CH_4_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_4_BMON_CTI_SECTION 0x1000
+#define mmDMA_CH_4_USER_CTI_BASE 0x7FFE446000ull
+#define DMA_CH_4_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_CH_4_USER_CTI_SECTION 0x1000
+#define mmDMA_CH_4_BMON_0_BASE 0x7FFE447000ull
+#define DMA_CH_4_BMON_0_MAX_OFFSET 0x1000
+#define DMA_CH_4_BMON_0_SECTION 0x1000
+#define mmDMA_CH_4_BMON_1_BASE 0x7FFE448000ull
+#define DMA_CH_4_BMON_1_MAX_OFFSET 0x1000
+#define DMA_CH_4_BMON_1_SECTION 0x8000
+#define mmDMA_CH_FUNNEL_6_1_BASE 0x7FFE450000ull
+#define DMA_CH_FUNNEL_6_1_MAX_OFFSET 0x1000
+#define DMA_CH_FUNNEL_6_1_SECTION 0x11000
+#define mmDMA_MACRO_CS_STM_BASE 0x7FFE461000ull
+#define DMA_MACRO_CS_STM_MAX_OFFSET 0x1000
+#define DMA_MACRO_CS_STM_SECTION 0x1000
+#define mmDMA_MACRO_CS_CTI_BASE 0x7FFE462000ull
+#define DMA_MACRO_CS_CTI_MAX_OFFSET 0x1000
+#define DMA_MACRO_CS_CTI_SECTION 0x1000
+#define mmDMA_MACRO_CS_ETF_BASE 0x7FFE463000ull
+#define DMA_MACRO_CS_ETF_MAX_OFFSET 0x1000
+#define DMA_MACRO_CS_ETF_SECTION 0x1000
+#define mmDMA_MACRO_CS_SPMU_BASE 0x7FFE464000ull
+#define DMA_MACRO_CS_SPMU_MAX_OFFSET 0x1000
+#define DMA_MACRO_CS_SPMU_SECTION 0x1000
+#define mmDMA_MACRO_BMON_CTI_BASE 0x7FFE465000ull
+#define DMA_MACRO_BMON_CTI_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_CTI_SECTION 0x1000
+#define mmDMA_MACRO_USER_CTI_BASE 0x7FFE466000ull
+#define DMA_MACRO_USER_CTI_MAX_OFFSET 0x1000
+#define DMA_MACRO_USER_CTI_SECTION 0x1000
+#define mmDMA_MACRO_BMON_0_BASE 0x7FFE467000ull
+#define DMA_MACRO_BMON_0_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_0_SECTION 0x1000
+#define mmDMA_MACRO_BMON_1_BASE 0x7FFE468000ull
+#define DMA_MACRO_BMON_1_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_1_SECTION 0x1000
+#define mmDMA_MACRO_BMON_2_BASE 0x7FFE469000ull
+#define DMA_MACRO_BMON_2_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_2_SECTION 0x1000
+#define mmDMA_MACRO_BMON_3_BASE 0x7FFE46A000ull
+#define DMA_MACRO_BMON_3_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_3_SECTION 0x1000
+#define mmDMA_MACRO_BMON_4_BASE 0x7FFE46B000ull
+#define DMA_MACRO_BMON_4_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_4_SECTION 0x1000
+#define mmDMA_MACRO_BMON_5_BASE 0x7FFE46C000ull
+#define DMA_MACRO_BMON_5_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_5_SECTION 0x1000
+#define mmDMA_MACRO_BMON_6_BASE 0x7FFE46D000ull
+#define DMA_MACRO_BMON_6_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_6_SECTION 0x1000
+#define mmDMA_MACRO_BMON_7_BASE 0x7FFE46E000ull
+#define DMA_MACRO_BMON_7_MAX_OFFSET 0x1000
+#define DMA_MACRO_BMON_7_SECTION 0x2000
+#define mmDMA_MACRO_FUNNEL_3_1_BASE 0x7FFE470000ull
+#define DMA_MACRO_FUNNEL_3_1_MAX_OFFSET 0x1000
+#define DMA_MACRO_FUNNEL_3_1_SECTION 0x10000
+#define mmCPU_ROM_TABLE_BASE 0x7FFE480000ull
+#define CPU_ROM_TABLE_MAX_OFFSET 0x1000
+#define CPU_ROM_TABLE_SECTION 0x1000
+#define mmCPU_ETF_0_BASE 0x7FFE481000ull
+#define CPU_ETF_0_MAX_OFFSET 0x1000
+#define CPU_ETF_0_SECTION 0x1000
+#define mmCPU_ETF_1_BASE 0x7FFE482000ull
+#define CPU_ETF_1_MAX_OFFSET 0x1000
+#define CPU_ETF_1_SECTION 0x2000
+#define mmCPU_CTI_BASE 0x7FFE484000ull
+#define CPU_CTI_MAX_OFFSET 0x1000
+#define CPU_CTI_SECTION 0x1000
+#define mmCPU_FUNNEL_BASE 0x7FFE485000ull
+#define CPU_FUNNEL_MAX_OFFSET 0x1000
+#define CPU_FUNNEL_SECTION 0x1000
+#define mmCPU_STM_BASE 0x7FFE486000ull
+#define CPU_STM_MAX_OFFSET 0x1000
+#define CPU_STM_SECTION 0x1000
+#define mmCPU_CTI_TRACE_BASE 0x7FFE487000ull
+#define CPU_CTI_TRACE_MAX_OFFSET 0x1000
+#define CPU_CTI_TRACE_SECTION 0x1000
+#define mmCPU_ETF_TRACE_BASE 0x7FFE488000ull
+#define CPU_ETF_TRACE_MAX_OFFSET 0x1000
+#define CPU_ETF_TRACE_SECTION 0x1000
+#define mmCPU_WR_BMON_BASE 0x7FFE489000ull
+#define CPU_WR_BMON_MAX_OFFSET 0x1000
+#define CPU_WR_BMON_SECTION 0x1000
+#define mmCPU_RD_BMON_BASE 0x7FFE48A000ull
+#define CPU_RD_BMON_MAX_OFFSET 0x1000
+#define CPU_RD_BMON_SECTION 0x37000
+#define mmMMU_CS_STM_BASE 0x7FFE4C1000ull
+#define MMU_CS_STM_MAX_OFFSET 0x1000
+#define MMU_CS_STM_SECTION 0x1000
+#define mmMMU_CS_CTI_BASE 0x7FFE4C2000ull
+#define MMU_CS_CTI_MAX_OFFSET 0x1000
+#define MMU_CS_CTI_SECTION 0x1000
+#define mmMMU_CS_ETF_BASE 0x7FFE4C3000ull
+#define MMU_CS_ETF_MAX_OFFSET 0x1000
+#define MMU_CS_ETF_SECTION 0x1000
+#define mmMMU_CS_SPMU_BASE 0x7FFE4C4000ull
+#define MMU_CS_SPMU_MAX_OFFSET 0x1000
+#define MMU_CS_SPMU_SECTION 0x1000
+#define mmMMU_BMON_CTI_BASE 0x7FFE4C5000ull
+#define MMU_BMON_CTI_MAX_OFFSET 0x1000
+#define MMU_BMON_CTI_SECTION 0x1000
+#define mmMMU_USER_CTI_BASE 0x7FFE4C6000ull
+#define MMU_USER_CTI_MAX_OFFSET 0x1000
+#define MMU_USER_CTI_SECTION 0x1000
+#define mmMMU_BMON_0_BASE 0x7FFE4C7000ull
+#define MMU_BMON_0_MAX_OFFSET 0x1000
+#define MMU_BMON_0_SECTION 0x1000
+#define mmMMU_BMON_1_BASE 0x7FFE4C8000ull
+#define MMU_BMON_1_MAX_OFFSET 0x1000
+#define MMU_BMON_1_SECTION 0x338000
+#define mmCA53_BASE 0x7FFE800000ull
+#define CA53_MAX_OFFSET 0x1000
+#define CA53_SECTION 0x400000
+#define mmPCI_ROM_TABLE_BASE 0x7FFEC00000ull
+#define PCI_ROM_TABLE_MAX_OFFSET 0x1000
+#define PCI_ROM_TABLE_SECTION 0x1000
+#define mmPCIE_STM_BASE 0x7FFEC01000ull
+#define PCIE_STM_MAX_OFFSET 0x1000
+#define PCIE_STM_SECTION 0x1000
+#define mmPCIE_ETF_BASE 0x7FFEC02000ull
+#define PCIE_ETF_MAX_OFFSET 0x1000
+#define PCIE_ETF_SECTION 0x1000
+#define mmPCIE_CTI_0_BASE 0x7FFEC03000ull
+#define PCIE_CTI_0_MAX_OFFSET 0x1000
+#define PCIE_CTI_0_SECTION 0x1000
+#define mmPCIE_SPMU_BASE 0x7FFEC04000ull
+#define PCIE_SPMU_MAX_OFFSET 0x1000
+#define PCIE_SPMU_SECTION 0x1000
+#define mmPCIE_CTI_1_BASE 0x7FFEC05000ull
+#define PCIE_CTI_1_MAX_OFFSET 0x1000
+#define PCIE_CTI_1_SECTION 0x1000
+#define mmPCIE_FUNNEL_BASE 0x7FFEC06000ull
+#define PCIE_FUNNEL_MAX_OFFSET 0x1000
+#define PCIE_FUNNEL_SECTION 0x1000
+#define mmPCIE_BMON_MSTR_WR_BASE 0x7FFEC07000ull
+#define PCIE_BMON_MSTR_WR_MAX_OFFSET 0x1000
+#define PCIE_BMON_MSTR_WR_SECTION 0x1000
+#define mmPCIE_BMON_MSTR_RD_BASE 0x7FFEC08000ull
+#define PCIE_BMON_MSTR_RD_MAX_OFFSET 0x1000
+#define PCIE_BMON_MSTR_RD_SECTION 0x1000
+#define mmPCIE_BMON_SLV_WR_BASE 0x7FFEC09000ull
+#define PCIE_BMON_SLV_WR_MAX_OFFSET 0x1000
+#define PCIE_BMON_SLV_WR_SECTION 0x1000
+#define mmPCIE_BMON_SLV_RD_BASE 0x7FFEC0A000ull
+#define PCIE_BMON_SLV_RD_MAX_OFFSET 0x1000
+#define PCIE_BMON_SLV_RD_SECTION 0x36000
+#define mmPSOC_CTI_BASE 0x7FFEC40000ull
+#define PSOC_CTI_MAX_OFFSET 0x1000
+#define PSOC_CTI_SECTION 0x1000
+#define mmPSOC_STM_BASE 0x7FFEC41000ull
+#define PSOC_STM_MAX_OFFSET 0x1000
+#define PSOC_STM_SECTION 0x1000
+#define mmPSOC_FUNNEL_BASE 0x7FFEC42000ull
+#define PSOC_FUNNEL_MAX_OFFSET 0x1000
+#define PSOC_FUNNEL_SECTION 0x1000
+#define mmPSOC_ETR_BASE 0x7FFEC43000ull
+#define PSOC_ETR_MAX_OFFSET 0x1000
+#define PSOC_ETR_SECTION 0x1000
+#define mmPSOC_ETF_BASE 0x7FFEC44000ull
+#define PSOC_ETF_MAX_OFFSET 0x1000
+#define PSOC_ETF_SECTION 0x1000
+#define mmPSOC_TS_CTI_BASE 0x7FFEC45000ull
+#define PSOC_TS_CTI_MAX_OFFSET 0x1000
+#define PSOC_TS_CTI_SECTION 0xB000
+#define mmTOP_ROM_TABLE_BASE 0x7FFEC50000ull
+#define TOP_ROM_TABLE_MAX_OFFSET 0x1000
+#define TOP_ROM_TABLE_SECTION 0x1F0000
+#define mmTPC1_RTR_FUNNEL_BASE 0x7FFEE40000ull
+#define TPC1_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC1_RTR_FUNNEL_SECTION 0x40000
+#define mmTPC2_RTR_FUNNEL_BASE 0x7FFEE80000ull
+#define TPC2_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC2_RTR_FUNNEL_SECTION 0x40000
+#define mmTPC3_RTR_FUNNEL_BASE 0x7FFEEC0000ull
+#define TPC3_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC3_RTR_FUNNEL_SECTION 0x40000
+#define mmTPC4_RTR_FUNNEL_BASE 0x7FFEF00000ull
+#define TPC4_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC4_RTR_FUNNEL_SECTION 0x40000
+#define mmTPC5_RTR_FUNNEL_BASE 0x7FFEF40000ull
+#define TPC5_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC5_RTR_FUNNEL_SECTION 0x40000
+#define mmTPC6_RTR_FUNNEL_BASE 0x7FFEF80000ull
+#define TPC6_RTR_FUNNEL_MAX_OFFSET 0x1000
+#define TPC6_RTR_FUNNEL_SECTION 0x81000
+#define mmTPC0_EML_SPMU_BASE 0x7FFF001000ull
+#define TPC0_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC0_EML_SPMU_SECTION 0x1000
+#define mmTPC0_EML_ETF_BASE 0x7FFF002000ull
+#define TPC0_EML_ETF_MAX_OFFSET 0x1000
+#define TPC0_EML_ETF_SECTION 0x1000
+#define mmTPC0_EML_STM_BASE 0x7FFF003000ull
+#define TPC0_EML_STM_MAX_OFFSET 0x1000
+#define TPC0_EML_STM_SECTION 0x1000
+#define mmTPC0_EML_ETM_R4_BASE 0x7FFF004000ull
+#define TPC0_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC0_EML_ETM_R4_SECTION 0x1000
+#define mmTPC0_EML_CTI_BASE 0x7FFF005000ull
+#define TPC0_EML_CTI_MAX_OFFSET 0x1000
+#define TPC0_EML_CTI_SECTION 0x1000
+#define mmTPC0_EML_FUNNEL_BASE 0x7FFF006000ull
+#define TPC0_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC0_EML_FUNNEL_SECTION 0x1000
+#define mmTPC0_EML_BUSMON_0_BASE 0x7FFF007000ull
+#define TPC0_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC0_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC0_EML_BUSMON_1_BASE 0x7FFF008000ull
+#define TPC0_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC0_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC0_EML_BUSMON_2_BASE 0x7FFF009000ull
+#define TPC0_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC0_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC0_EML_BUSMON_3_BASE 0x7FFF00A000ull
+#define TPC0_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC0_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC0_EML_CFG_BASE 0x7FFF040000ull
+#define TPC0_EML_CFG_MAX_OFFSET 0x338
+#define TPC0_EML_CFG_SECTION 0x1BF000
+#define mmTPC0_EML_CS_BASE 0x7FFF1FF000ull
+#define TPC0_EML_CS_MAX_OFFSET 0x1000
+#define TPC0_EML_CS_SECTION 0x2000
+#define mmTPC1_EML_SPMU_BASE 0x7FFF201000ull
+#define TPC1_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC1_EML_SPMU_SECTION 0x1000
+#define mmTPC1_EML_ETF_BASE 0x7FFF202000ull
+#define TPC1_EML_ETF_MAX_OFFSET 0x1000
+#define TPC1_EML_ETF_SECTION 0x1000
+#define mmTPC1_EML_STM_BASE 0x7FFF203000ull
+#define TPC1_EML_STM_MAX_OFFSET 0x1000
+#define TPC1_EML_STM_SECTION 0x1000
+#define mmTPC1_EML_ETM_R4_BASE 0x7FFF204000ull
+#define TPC1_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC1_EML_ETM_R4_SECTION 0x1000
+#define mmTPC1_EML_CTI_BASE 0x7FFF205000ull
+#define TPC1_EML_CTI_MAX_OFFSET 0x1000
+#define TPC1_EML_CTI_SECTION 0x1000
+#define mmTPC1_EML_FUNNEL_BASE 0x7FFF206000ull
+#define TPC1_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC1_EML_FUNNEL_SECTION 0x1000
+#define mmTPC1_EML_BUSMON_0_BASE 0x7FFF207000ull
+#define TPC1_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC1_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC1_EML_BUSMON_1_BASE 0x7FFF208000ull
+#define TPC1_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC1_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC1_EML_BUSMON_2_BASE 0x7FFF209000ull
+#define TPC1_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC1_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC1_EML_BUSMON_3_BASE 0x7FFF20A000ull
+#define TPC1_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC1_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC1_EML_CFG_BASE 0x7FFF240000ull
+#define TPC1_EML_CFG_MAX_OFFSET 0x338
+#define TPC1_EML_CFG_SECTION 0x1BF000
+#define mmTPC1_EML_CS_BASE 0x7FFF3FF000ull
+#define TPC1_EML_CS_MAX_OFFSET 0x1000
+#define TPC1_EML_CS_SECTION 0x2000
+#define mmTPC2_EML_SPMU_BASE 0x7FFF401000ull
+#define TPC2_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC2_EML_SPMU_SECTION 0x1000
+#define mmTPC2_EML_ETF_BASE 0x7FFF402000ull
+#define TPC2_EML_ETF_MAX_OFFSET 0x1000
+#define TPC2_EML_ETF_SECTION 0x1000
+#define mmTPC2_EML_STM_BASE 0x7FFF403000ull
+#define TPC2_EML_STM_MAX_OFFSET 0x1000
+#define TPC2_EML_STM_SECTION 0x1000
+#define mmTPC2_EML_ETM_R4_BASE 0x7FFF404000ull
+#define TPC2_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC2_EML_ETM_R4_SECTION 0x1000
+#define mmTPC2_EML_CTI_BASE 0x7FFF405000ull
+#define TPC2_EML_CTI_MAX_OFFSET 0x1000
+#define TPC2_EML_CTI_SECTION 0x1000
+#define mmTPC2_EML_FUNNEL_BASE 0x7FFF406000ull
+#define TPC2_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC2_EML_FUNNEL_SECTION 0x1000
+#define mmTPC2_EML_BUSMON_0_BASE 0x7FFF407000ull
+#define TPC2_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC2_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC2_EML_BUSMON_1_BASE 0x7FFF408000ull
+#define TPC2_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC2_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC2_EML_BUSMON_2_BASE 0x7FFF409000ull
+#define TPC2_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC2_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC2_EML_BUSMON_3_BASE 0x7FFF40A000ull
+#define TPC2_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC2_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC2_EML_CFG_BASE 0x7FFF440000ull
+#define TPC2_EML_CFG_MAX_OFFSET 0x338
+#define TPC2_EML_CFG_SECTION 0x1BF000
+#define mmTPC2_EML_CS_BASE 0x7FFF5FF000ull
+#define TPC2_EML_CS_MAX_OFFSET 0x1000
+#define TPC2_EML_CS_SECTION 0x2000
+#define mmTPC3_EML_SPMU_BASE 0x7FFF601000ull
+#define TPC3_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC3_EML_SPMU_SECTION 0x1000
+#define mmTPC3_EML_ETF_BASE 0x7FFF602000ull
+#define TPC3_EML_ETF_MAX_OFFSET 0x1000
+#define TPC3_EML_ETF_SECTION 0x1000
+#define mmTPC3_EML_STM_BASE 0x7FFF603000ull
+#define TPC3_EML_STM_MAX_OFFSET 0x1000
+#define TPC3_EML_STM_SECTION 0x1000
+#define mmTPC3_EML_ETM_R4_BASE 0x7FFF604000ull
+#define TPC3_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC3_EML_ETM_R4_SECTION 0x1000
+#define mmTPC3_EML_CTI_BASE 0x7FFF605000ull
+#define TPC3_EML_CTI_MAX_OFFSET 0x1000
+#define TPC3_EML_CTI_SECTION 0x1000
+#define mmTPC3_EML_FUNNEL_BASE 0x7FFF606000ull
+#define TPC3_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC3_EML_FUNNEL_SECTION 0x1000
+#define mmTPC3_EML_BUSMON_0_BASE 0x7FFF607000ull
+#define TPC3_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC3_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC3_EML_BUSMON_1_BASE 0x7FFF608000ull
+#define TPC3_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC3_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC3_EML_BUSMON_2_BASE 0x7FFF609000ull
+#define TPC3_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC3_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC3_EML_BUSMON_3_BASE 0x7FFF60A000ull
+#define TPC3_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC3_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC3_EML_CFG_BASE 0x7FFF640000ull
+#define TPC3_EML_CFG_MAX_OFFSET 0x338
+#define TPC3_EML_CFG_SECTION 0x1BF000
+#define mmTPC3_EML_CS_BASE 0x7FFF7FF000ull
+#define TPC3_EML_CS_MAX_OFFSET 0x1000
+#define TPC3_EML_CS_SECTION 0x2000
+#define mmTPC4_EML_SPMU_BASE 0x7FFF801000ull
+#define TPC4_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC4_EML_SPMU_SECTION 0x1000
+#define mmTPC4_EML_ETF_BASE 0x7FFF802000ull
+#define TPC4_EML_ETF_MAX_OFFSET 0x1000
+#define TPC4_EML_ETF_SECTION 0x1000
+#define mmTPC4_EML_STM_BASE 0x7FFF803000ull
+#define TPC4_EML_STM_MAX_OFFSET 0x1000
+#define TPC4_EML_STM_SECTION 0x1000
+#define mmTPC4_EML_ETM_R4_BASE 0x7FFF804000ull
+#define TPC4_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC4_EML_ETM_R4_SECTION 0x1000
+#define mmTPC4_EML_CTI_BASE 0x7FFF805000ull
+#define TPC4_EML_CTI_MAX_OFFSET 0x1000
+#define TPC4_EML_CTI_SECTION 0x1000
+#define mmTPC4_EML_FUNNEL_BASE 0x7FFF806000ull
+#define TPC4_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC4_EML_FUNNEL_SECTION 0x1000
+#define mmTPC4_EML_BUSMON_0_BASE 0x7FFF807000ull
+#define TPC4_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC4_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC4_EML_BUSMON_1_BASE 0x7FFF808000ull
+#define TPC4_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC4_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC4_EML_BUSMON_2_BASE 0x7FFF809000ull
+#define TPC4_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC4_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC4_EML_BUSMON_3_BASE 0x7FFF80A000ull
+#define TPC4_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC4_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC4_EML_CFG_BASE 0x7FFF840000ull
+#define TPC4_EML_CFG_MAX_OFFSET 0x338
+#define TPC4_EML_CFG_SECTION 0x1BF000
+#define mmTPC4_EML_CS_BASE 0x7FFF9FF000ull
+#define TPC4_EML_CS_MAX_OFFSET 0x1000
+#define TPC4_EML_CS_SECTION 0x2000
+#define mmTPC5_EML_SPMU_BASE 0x7FFFA01000ull
+#define TPC5_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC5_EML_SPMU_SECTION 0x1000
+#define mmTPC5_EML_ETF_BASE 0x7FFFA02000ull
+#define TPC5_EML_ETF_MAX_OFFSET 0x1000
+#define TPC5_EML_ETF_SECTION 0x1000
+#define mmTPC5_EML_STM_BASE 0x7FFFA03000ull
+#define TPC5_EML_STM_MAX_OFFSET 0x1000
+#define TPC5_EML_STM_SECTION 0x1000
+#define mmTPC5_EML_ETM_R4_BASE 0x7FFFA04000ull
+#define TPC5_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC5_EML_ETM_R4_SECTION 0x1000
+#define mmTPC5_EML_CTI_BASE 0x7FFFA05000ull
+#define TPC5_EML_CTI_MAX_OFFSET 0x1000
+#define TPC5_EML_CTI_SECTION 0x1000
+#define mmTPC5_EML_FUNNEL_BASE 0x7FFFA06000ull
+#define TPC5_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC5_EML_FUNNEL_SECTION 0x1000
+#define mmTPC5_EML_BUSMON_0_BASE 0x7FFFA07000ull
+#define TPC5_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC5_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC5_EML_BUSMON_1_BASE 0x7FFFA08000ull
+#define TPC5_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC5_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC5_EML_BUSMON_2_BASE 0x7FFFA09000ull
+#define TPC5_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC5_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC5_EML_BUSMON_3_BASE 0x7FFFA0A000ull
+#define TPC5_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC5_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC5_EML_CFG_BASE 0x7FFFA40000ull
+#define TPC5_EML_CFG_MAX_OFFSET 0x338
+#define TPC5_EML_CFG_SECTION 0x1BF000
+#define mmTPC5_EML_CS_BASE 0x7FFFBFF000ull
+#define TPC5_EML_CS_MAX_OFFSET 0x1000
+#define TPC5_EML_CS_SECTION 0x2000
+#define mmTPC6_EML_SPMU_BASE 0x7FFFC01000ull
+#define TPC6_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC6_EML_SPMU_SECTION 0x1000
+#define mmTPC6_EML_ETF_BASE 0x7FFFC02000ull
+#define TPC6_EML_ETF_MAX_OFFSET 0x1000
+#define TPC6_EML_ETF_SECTION 0x1000
+#define mmTPC6_EML_STM_BASE 0x7FFFC03000ull
+#define TPC6_EML_STM_MAX_OFFSET 0x1000
+#define TPC6_EML_STM_SECTION 0x1000
+#define mmTPC6_EML_ETM_R4_BASE 0x7FFFC04000ull
+#define TPC6_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC6_EML_ETM_R4_SECTION 0x1000
+#define mmTPC6_EML_CTI_BASE 0x7FFFC05000ull
+#define TPC6_EML_CTI_MAX_OFFSET 0x1000
+#define TPC6_EML_CTI_SECTION 0x1000
+#define mmTPC6_EML_FUNNEL_BASE 0x7FFFC06000ull
+#define TPC6_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC6_EML_FUNNEL_SECTION 0x1000
+#define mmTPC6_EML_BUSMON_0_BASE 0x7FFFC07000ull
+#define TPC6_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC6_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC6_EML_BUSMON_1_BASE 0x7FFFC08000ull
+#define TPC6_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC6_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC6_EML_BUSMON_2_BASE 0x7FFFC09000ull
+#define TPC6_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC6_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC6_EML_BUSMON_3_BASE 0x7FFFC0A000ull
+#define TPC6_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC6_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC6_EML_CFG_BASE 0x7FFFC40000ull
+#define TPC6_EML_CFG_MAX_OFFSET 0x338
+#define TPC6_EML_CFG_SECTION 0x1BF000
+#define mmTPC6_EML_CS_BASE 0x7FFFDFF000ull
+#define TPC6_EML_CS_MAX_OFFSET 0x1000
+#define TPC6_EML_CS_SECTION 0x2000
+#define mmTPC7_EML_SPMU_BASE 0x7FFFE01000ull
+#define TPC7_EML_SPMU_MAX_OFFSET 0x1000
+#define TPC7_EML_SPMU_SECTION 0x1000
+#define mmTPC7_EML_ETF_BASE 0x7FFFE02000ull
+#define TPC7_EML_ETF_MAX_OFFSET 0x1000
+#define TPC7_EML_ETF_SECTION 0x1000
+#define mmTPC7_EML_STM_BASE 0x7FFFE03000ull
+#define TPC7_EML_STM_MAX_OFFSET 0x1000
+#define TPC7_EML_STM_SECTION 0x1000
+#define mmTPC7_EML_ETM_R4_BASE 0x7FFFE04000ull
+#define TPC7_EML_ETM_R4_MAX_OFFSET 0x0
+#define TPC7_EML_ETM_R4_SECTION 0x1000
+#define mmTPC7_EML_CTI_BASE 0x7FFFE05000ull
+#define TPC7_EML_CTI_MAX_OFFSET 0x1000
+#define TPC7_EML_CTI_SECTION 0x1000
+#define mmTPC7_EML_FUNNEL_BASE 0x7FFFE06000ull
+#define TPC7_EML_FUNNEL_MAX_OFFSET 0x1000
+#define TPC7_EML_FUNNEL_SECTION 0x1000
+#define mmTPC7_EML_BUSMON_0_BASE 0x7FFFE07000ull
+#define TPC7_EML_BUSMON_0_MAX_OFFSET 0x1000
+#define TPC7_EML_BUSMON_0_SECTION 0x1000
+#define mmTPC7_EML_BUSMON_1_BASE 0x7FFFE08000ull
+#define TPC7_EML_BUSMON_1_MAX_OFFSET 0x1000
+#define TPC7_EML_BUSMON_1_SECTION 0x1000
+#define mmTPC7_EML_BUSMON_2_BASE 0x7FFFE09000ull
+#define TPC7_EML_BUSMON_2_MAX_OFFSET 0x1000
+#define TPC7_EML_BUSMON_2_SECTION 0x1000
+#define mmTPC7_EML_BUSMON_3_BASE 0x7FFFE0A000ull
+#define TPC7_EML_BUSMON_3_MAX_OFFSET 0x1000
+#define TPC7_EML_BUSMON_3_SECTION 0x36000
+#define mmTPC7_EML_CFG_BASE 0x7FFFE40000ull
+#define TPC7_EML_CFG_MAX_OFFSET 0x338
+#define TPC7_EML_CFG_SECTION 0x1BF000
+#define mmTPC7_EML_CS_BASE 0x7FFFFFF000ull
+#define TPC7_EML_CS_MAX_OFFSET 0x1000
+
+#endif /* GOYA_BLOCKS_H_ */
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h
new file mode 100644
index 000000000000..a161ecfe74de
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/goya_masks.h
@@ -0,0 +1,275 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef ASIC_REG_GOYA_MASKS_H_
+#define ASIC_REG_GOYA_MASKS_H_
+
+#include "goya_regs.h"
+
+/* Useful masks for bits in various registers */
+#define QMAN_DMA_ENABLE (\
+ (1 << DMA_QM_0_GLBL_CFG0_PQF_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG0_CQF_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG0_CP_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG0_DMA_EN_SHIFT))
+
+#define QMAN_DMA_FULLY_TRUSTED (\
+ (1 << DMA_QM_0_GLBL_PROT_PQF_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CQF_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CP_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_DMA_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+#define QMAN_DMA_PARTLY_TRUSTED (\
+ (1 << DMA_QM_0_GLBL_PROT_PQF_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CQF_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CP_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+#define QMAN_DMA_STOP (\
+ (1 << DMA_QM_0_GLBL_CFG1_PQF_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG1_CQF_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG1_CP_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT))
+
+#define QMAN_DMA_IS_STOPPED (\
+ (1 << DMA_QM_0_GLBL_STS0_PQF_IS_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_STS0_CQF_IS_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_STS0_CP_IS_STOP_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_STS0_DMA_IS_STOP_SHIFT))
+
+#define QMAN_DMA_ERR_MSG_EN (\
+ (1 << DMA_QM_0_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT) | \
+ (1 << DMA_QM_0_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT))
+
+#define QMAN_MME_ENABLE (\
+ (1 << MME_QM_GLBL_CFG0_PQF_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_CFG0_CQF_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_CFG0_CP_EN_SHIFT))
+
+#define CMDQ_MME_ENABLE (\
+ (1 << MME_CMDQ_GLBL_CFG0_CQF_EN_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_CFG0_CP_EN_SHIFT))
+
+#define QMAN_MME_STOP (\
+ (1 << MME_QM_GLBL_CFG1_PQF_STOP_SHIFT) | \
+ (1 << MME_QM_GLBL_CFG1_CQF_STOP_SHIFT) | \
+ (1 << MME_QM_GLBL_CFG1_CP_STOP_SHIFT))
+
+#define CMDQ_MME_STOP (\
+ (1 << MME_CMDQ_GLBL_CFG1_CQF_STOP_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_CFG1_CP_STOP_SHIFT))
+
+#define QMAN_MME_ERR_MSG_EN (\
+ (1 << MME_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT))
+
+#define CMDQ_MME_ERR_MSG_EN (\
+ (1 << MME_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT))
+
+#define QMAN_MME_ERR_PROT (\
+ (1 << MME_QM_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << MME_QM_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << MME_QM_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << MME_QM_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+#define CMDQ_MME_ERR_PROT (\
+ (1 << MME_CMDQ_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << MME_CMDQ_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+#define QMAN_TPC_ENABLE (\
+ (1 << TPC0_QM_GLBL_CFG0_PQF_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_CFG0_CQF_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_CFG0_CP_EN_SHIFT))
+
+#define CMDQ_TPC_ENABLE (\
+ (1 << TPC0_CMDQ_GLBL_CFG0_CQF_EN_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_CFG0_CP_EN_SHIFT))
+
+#define QMAN_TPC_STOP (\
+ (1 << TPC0_QM_GLBL_CFG1_PQF_STOP_SHIFT) | \
+ (1 << TPC0_QM_GLBL_CFG1_CQF_STOP_SHIFT) | \
+ (1 << TPC0_QM_GLBL_CFG1_CP_STOP_SHIFT))
+
+#define CMDQ_TPC_STOP (\
+ (1 << TPC0_CMDQ_GLBL_CFG1_CQF_STOP_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_CFG1_CP_STOP_SHIFT))
+
+#define QMAN_TPC_ERR_MSG_EN (\
+ (1 << TPC0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT))
+
+#define CMDQ_TPC_ERR_MSG_EN (\
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT))
+
+#define QMAN_TPC_ERR_PROT (\
+ (1 << TPC0_QM_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << TPC0_QM_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << TPC0_QM_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << TPC0_QM_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+#define CMDQ_TPC_ERR_PROT (\
+ (1 << TPC0_CMDQ_GLBL_PROT_PQF_ERR_PROT_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_PROT_CQF_ERR_PROT_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_PROT_CP_ERR_PROT_SHIFT) | \
+ (1 << TPC0_CMDQ_GLBL_PROT_DMA_ERR_PROT_SHIFT))
+
+/* RESETS */
+#define DMA_MME_TPC_RESET (\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_TPC_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MME_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_SHIFT)
+
+#define RESET_ALL (\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_TPC_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MME_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MC_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_CPU_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PSOC_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_IC_IF_SHIFT |\
+ PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_SRAM_MASK |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_SHIFT |\
+ 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_IF_SHIFT)
+
+#define CA53_RESET (\
+ (~\
+ (1 << PSOC_GLOBAL_CONF_UNIT_RST_N_CPU_SHIFT)\
+ ) & 0x7FFFFF)
+
+#define CPU_RESET_ASSERT (\
+ 1 << CPU_CA53_CFG_ARM_RST_CONTROL_NMBISTRESET_SHIFT)
+
+#define CPU_RESET_CORE0_DEASSERT (\
+ 1 << CPU_CA53_CFG_ARM_RST_CONTROL_NCPUPORESET_SHIFT |\
+ 1 << CPU_CA53_CFG_ARM_RST_CONTROL_NCORERESET_SHIFT |\
+ 1 << CPU_CA53_CFG_ARM_RST_CONTROL_NL2RESET_SHIFT |\
+ 1 << CPU_CA53_CFG_ARM_RST_CONTROL_NMBISTRESET_SHIFT)
+
+/* PCI CONFIGURATION SPACE */
+#define mmPCI_CONFIG_ELBI_ADDR 0xFF0
+#define mmPCI_CONFIG_ELBI_DATA 0xFF4
+#define mmPCI_CONFIG_ELBI_CTRL 0xFF8
+#define PCI_CONFIG_ELBI_CTRL_WRITE (1 << 31)
+
+#define mmPCI_CONFIG_ELBI_STS 0xFFC
+#define PCI_CONFIG_ELBI_STS_ERR (1 << 30)
+#define PCI_CONFIG_ELBI_STS_DONE (1 << 31)
+#define PCI_CONFIG_ELBI_STS_MASK (PCI_CONFIG_ELBI_STS_ERR | \
+ PCI_CONFIG_ELBI_STS_DONE)
+
+#define GOYA_IRQ_HBW_ID_MASK 0x1FFF
+#define GOYA_IRQ_HBW_ID_SHIFT 0
+#define GOYA_IRQ_HBW_INTERNAL_ID_MASK 0xE000
+#define GOYA_IRQ_HBW_INTERNAL_ID_SHIFT 13
+#define GOYA_IRQ_HBW_AGENT_ID_MASK 0x1F0000
+#define GOYA_IRQ_HBW_AGENT_ID_SHIFT 16
+#define GOYA_IRQ_HBW_Y_MASK 0xE00000
+#define GOYA_IRQ_HBW_Y_SHIFT 21
+#define GOYA_IRQ_HBW_X_MASK 0x7000000
+#define GOYA_IRQ_HBW_X_SHIFT 24
+#define GOYA_IRQ_LBW_ID_MASK 0xFF
+#define GOYA_IRQ_LBW_ID_SHIFT 0
+#define GOYA_IRQ_LBW_INTERNAL_ID_MASK 0x700
+#define GOYA_IRQ_LBW_INTERNAL_ID_SHIFT 8
+#define GOYA_IRQ_LBW_AGENT_ID_MASK 0xF800
+#define GOYA_IRQ_LBW_AGENT_ID_SHIFT 11
+#define GOYA_IRQ_LBW_Y_MASK 0x70000
+#define GOYA_IRQ_LBW_Y_SHIFT 16
+#define GOYA_IRQ_LBW_X_MASK 0x380000
+#define GOYA_IRQ_LBW_X_SHIFT 19
+
+#define DMA_QM_IDLE_MASK (DMA_QM_0_GLBL_STS0_PQF_IDLE_MASK | \
+ DMA_QM_0_GLBL_STS0_CQF_IDLE_MASK | \
+ DMA_QM_0_GLBL_STS0_CP_IDLE_MASK | \
+ DMA_QM_0_GLBL_STS0_DMA_IDLE_MASK)
+
+#define TPC_QM_IDLE_MASK (TPC0_QM_GLBL_STS0_PQF_IDLE_MASK | \
+ TPC0_QM_GLBL_STS0_CQF_IDLE_MASK | \
+ TPC0_QM_GLBL_STS0_CP_IDLE_MASK)
+
+#define TPC_CMDQ_IDLE_MASK (TPC0_CMDQ_GLBL_STS0_CQF_IDLE_MASK | \
+ TPC0_CMDQ_GLBL_STS0_CP_IDLE_MASK)
+
+#define TPC_CFG_IDLE_MASK (TPC0_CFG_STATUS_SCALAR_PIPE_EMPTY_MASK | \
+ TPC0_CFG_STATUS_VECTOR_PIPE_EMPTY_MASK | \
+ TPC0_CFG_STATUS_IQ_EMPTY_MASK | \
+ TPC0_CFG_STATUS_NO_INFLIGH_MEM_ACCESSES_MASK)
+
+#define MME_QM_IDLE_MASK (MME_QM_GLBL_STS0_PQF_IDLE_MASK | \
+ MME_QM_GLBL_STS0_CQF_IDLE_MASK | \
+ MME_QM_GLBL_STS0_CP_IDLE_MASK)
+
+#define MME_CMDQ_IDLE_MASK (MME_CMDQ_GLBL_STS0_CQF_IDLE_MASK | \
+ MME_CMDQ_GLBL_STS0_CP_IDLE_MASK)
+
+#define MME_ARCH_IDLE_MASK (MME_ARCH_STATUS_SB_A_EMPTY_MASK | \
+ MME_ARCH_STATUS_SB_B_EMPTY_MASK | \
+ MME_ARCH_STATUS_SB_CIN_EMPTY_MASK | \
+ MME_ARCH_STATUS_SB_COUT_EMPTY_MASK)
+
+#define MME_SHADOW_IDLE_MASK (MME_SHADOW_0_STATUS_A_MASK | \
+ MME_SHADOW_0_STATUS_B_MASK | \
+ MME_SHADOW_0_STATUS_CIN_MASK | \
+ MME_SHADOW_0_STATUS_COUT_MASK | \
+ MME_SHADOW_0_STATUS_TE_MASK | \
+ MME_SHADOW_0_STATUS_LD_MASK | \
+ MME_SHADOW_0_STATUS_ST_MASK)
+
+#define TPC1_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC2_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC3_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC4_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC5_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC6_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+#define TPC7_CFG_TPC_STALL_V_SHIFT TPC0_CFG_TPC_STALL_V_SHIFT
+
+#define DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT
+#define DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT
+#define DMA_QM_3_GLBL_CFG1_DMA_STOP_SHIFT DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT
+#define DMA_QM_4_GLBL_CFG1_DMA_STOP_SHIFT DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT
+
+#endif /* ASIC_REG_GOYA_MASKS_H_ */
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h
new file mode 100644
index 000000000000..6cb0b6e54d41
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef ASIC_REG_GOYA_REGS_H_
+#define ASIC_REG_GOYA_REGS_H_
+
+#include "goya_blocks.h"
+#include "stlb_regs.h"
+#include "mmu_regs.h"
+#include "pcie_aux_regs.h"
+#include "psoc_global_conf_regs.h"
+#include "psoc_spi_regs.h"
+#include "psoc_mme_pll_regs.h"
+#include "psoc_pci_pll_regs.h"
+#include "psoc_emmc_pll_regs.h"
+#include "cpu_if_regs.h"
+#include "cpu_ca53_cfg_regs.h"
+#include "cpu_pll_regs.h"
+#include "ic_pll_regs.h"
+#include "mc_pll_regs.h"
+#include "tpc_pll_regs.h"
+#include "dma_qm_0_regs.h"
+#include "dma_qm_1_regs.h"
+#include "dma_qm_2_regs.h"
+#include "dma_qm_3_regs.h"
+#include "dma_qm_4_regs.h"
+#include "dma_ch_0_regs.h"
+#include "dma_ch_1_regs.h"
+#include "dma_ch_2_regs.h"
+#include "dma_ch_3_regs.h"
+#include "dma_ch_4_regs.h"
+#include "dma_macro_regs.h"
+#include "dma_nrtr_regs.h"
+#include "pci_nrtr_regs.h"
+#include "sram_y0_x0_rtr_regs.h"
+#include "sram_y0_x1_rtr_regs.h"
+#include "sram_y0_x2_rtr_regs.h"
+#include "sram_y0_x3_rtr_regs.h"
+#include "sram_y0_x4_rtr_regs.h"
+#include "mme_regs.h"
+#include "mme_qm_regs.h"
+#include "mme_cmdq_regs.h"
+#include "mme1_rtr_regs.h"
+#include "mme2_rtr_regs.h"
+#include "mme3_rtr_regs.h"
+#include "mme4_rtr_regs.h"
+#include "mme5_rtr_regs.h"
+#include "mme6_rtr_regs.h"
+#include "tpc0_cfg_regs.h"
+#include "tpc1_cfg_regs.h"
+#include "tpc2_cfg_regs.h"
+#include "tpc3_cfg_regs.h"
+#include "tpc4_cfg_regs.h"
+#include "tpc5_cfg_regs.h"
+#include "tpc6_cfg_regs.h"
+#include "tpc7_cfg_regs.h"
+#include "tpc0_qm_regs.h"
+#include "tpc1_qm_regs.h"
+#include "tpc2_qm_regs.h"
+#include "tpc3_qm_regs.h"
+#include "tpc4_qm_regs.h"
+#include "tpc5_qm_regs.h"
+#include "tpc6_qm_regs.h"
+#include "tpc7_qm_regs.h"
+#include "tpc0_cmdq_regs.h"
+#include "tpc1_cmdq_regs.h"
+#include "tpc2_cmdq_regs.h"
+#include "tpc3_cmdq_regs.h"
+#include "tpc4_cmdq_regs.h"
+#include "tpc5_cmdq_regs.h"
+#include "tpc6_cmdq_regs.h"
+#include "tpc7_cmdq_regs.h"
+#include "tpc0_nrtr_regs.h"
+#include "tpc1_rtr_regs.h"
+#include "tpc2_rtr_regs.h"
+#include "tpc3_rtr_regs.h"
+#include "tpc4_rtr_regs.h"
+#include "tpc5_rtr_regs.h"
+#include "tpc6_rtr_regs.h"
+#include "tpc7_nrtr_regs.h"
+#include "tpc0_eml_cfg_regs.h"
+
+#include "psoc_global_conf_masks.h"
+#include "dma_macro_masks.h"
+#include "dma_qm_0_masks.h"
+#include "tpc0_qm_masks.h"
+#include "tpc0_cmdq_masks.h"
+#include "mme_qm_masks.h"
+#include "mme_cmdq_masks.h"
+#include "tpc0_cfg_masks.h"
+#include "tpc0_eml_cfg_masks.h"
+#include "mme1_rtr_masks.h"
+#include "tpc0_nrtr_masks.h"
+#include "dma_nrtr_masks.h"
+#include "pci_nrtr_masks.h"
+#include "stlb_masks.h"
+#include "cpu_ca53_cfg_masks.h"
+#include "mmu_masks.h"
+#include "mme_masks.h"
+
+#define mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG 0xC02000
+#define mmPCIE_DBI_MSIX_DOORBELL_OFF 0xC02948
+
+#define mmSYNC_MNGR_MON_PAY_ADDRL_0 0x113000
+#define mmSYNC_MNGR_SOB_OBJ_0 0x112000
+#define mmSYNC_MNGR_SOB_OBJ_1000 0x112FA0
+#define mmSYNC_MNGR_SOB_OBJ_1007 0x112FBC
+#define mmSYNC_MNGR_SOB_OBJ_1023 0x112FFC
+#define mmSYNC_MNGR_MON_STATUS_0 0x114000
+#define mmSYNC_MNGR_MON_STATUS_255 0x1143FC
+
+#define mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR 0x800040
+
+#endif /* ASIC_REG_GOYA_REGS_H_ */
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h
new file mode 100644
index 000000000000..0a743817aad7
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/ic_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_IC_PLL_REGS_H_
+#define ASIC_REG_IC_PLL_REGS_H_
+
+/*
+ *****************************************
+ * IC_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmIC_PLL_NR 0x4A3100
+
+#define mmIC_PLL_NF 0x4A3104
+
+#define mmIC_PLL_OD 0x4A3108
+
+#define mmIC_PLL_NB 0x4A310C
+
+#define mmIC_PLL_CFG 0x4A3110
+
+#define mmIC_PLL_LOSE_MASK 0x4A3120
+
+#define mmIC_PLL_LOCK_INTR 0x4A3128
+
+#define mmIC_PLL_LOCK_BYPASS 0x4A312C
+
+#define mmIC_PLL_DATA_CHNG 0x4A3130
+
+#define mmIC_PLL_RST 0x4A3134
+
+#define mmIC_PLL_SLIP_WD_CNTR 0x4A3150
+
+#define mmIC_PLL_DIV_FACTOR_0 0x4A3200
+
+#define mmIC_PLL_DIV_FACTOR_1 0x4A3204
+
+#define mmIC_PLL_DIV_FACTOR_2 0x4A3208
+
+#define mmIC_PLL_DIV_FACTOR_3 0x4A320C
+
+#define mmIC_PLL_DIV_FACTOR_CMD_0 0x4A3220
+
+#define mmIC_PLL_DIV_FACTOR_CMD_1 0x4A3224
+
+#define mmIC_PLL_DIV_FACTOR_CMD_2 0x4A3228
+
+#define mmIC_PLL_DIV_FACTOR_CMD_3 0x4A322C
+
+#define mmIC_PLL_DIV_SEL_0 0x4A3280
+
+#define mmIC_PLL_DIV_SEL_1 0x4A3284
+
+#define mmIC_PLL_DIV_SEL_2 0x4A3288
+
+#define mmIC_PLL_DIV_SEL_3 0x4A328C
+
+#define mmIC_PLL_DIV_EN_0 0x4A32A0
+
+#define mmIC_PLL_DIV_EN_1 0x4A32A4
+
+#define mmIC_PLL_DIV_EN_2 0x4A32A8
+
+#define mmIC_PLL_DIV_EN_3 0x4A32AC
+
+#define mmIC_PLL_DIV_FACTOR_BUSY_0 0x4A32C0
+
+#define mmIC_PLL_DIV_FACTOR_BUSY_1 0x4A32C4
+
+#define mmIC_PLL_DIV_FACTOR_BUSY_2 0x4A32C8
+
+#define mmIC_PLL_DIV_FACTOR_BUSY_3 0x4A32CC
+
+#define mmIC_PLL_CLK_GATER 0x4A3300
+
+#define mmIC_PLL_CLK_RLX_0 0x4A3310
+
+#define mmIC_PLL_CLK_RLX_1 0x4A3314
+
+#define mmIC_PLL_CLK_RLX_2 0x4A3318
+
+#define mmIC_PLL_CLK_RLX_3 0x4A331C
+
+#define mmIC_PLL_REF_CNTR_PERIOD 0x4A3400
+
+#define mmIC_PLL_REF_LOW_THRESHOLD 0x4A3410
+
+#define mmIC_PLL_REF_HIGH_THRESHOLD 0x4A3420
+
+#define mmIC_PLL_PLL_NOT_STABLE 0x4A3430
+
+#define mmIC_PLL_FREQ_CALC_EN 0x4A3440
+
+#endif /* ASIC_REG_IC_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h
new file mode 100644
index 000000000000..4408188aa067
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mc_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MC_PLL_REGS_H_
+#define ASIC_REG_MC_PLL_REGS_H_
+
+/*
+ *****************************************
+ * MC_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmMC_PLL_NR 0x4A1100
+
+#define mmMC_PLL_NF 0x4A1104
+
+#define mmMC_PLL_OD 0x4A1108
+
+#define mmMC_PLL_NB 0x4A110C
+
+#define mmMC_PLL_CFG 0x4A1110
+
+#define mmMC_PLL_LOSE_MASK 0x4A1120
+
+#define mmMC_PLL_LOCK_INTR 0x4A1128
+
+#define mmMC_PLL_LOCK_BYPASS 0x4A112C
+
+#define mmMC_PLL_DATA_CHNG 0x4A1130
+
+#define mmMC_PLL_RST 0x4A1134
+
+#define mmMC_PLL_SLIP_WD_CNTR 0x4A1150
+
+#define mmMC_PLL_DIV_FACTOR_0 0x4A1200
+
+#define mmMC_PLL_DIV_FACTOR_1 0x4A1204
+
+#define mmMC_PLL_DIV_FACTOR_2 0x4A1208
+
+#define mmMC_PLL_DIV_FACTOR_3 0x4A120C
+
+#define mmMC_PLL_DIV_FACTOR_CMD_0 0x4A1220
+
+#define mmMC_PLL_DIV_FACTOR_CMD_1 0x4A1224
+
+#define mmMC_PLL_DIV_FACTOR_CMD_2 0x4A1228
+
+#define mmMC_PLL_DIV_FACTOR_CMD_3 0x4A122C
+
+#define mmMC_PLL_DIV_SEL_0 0x4A1280
+
+#define mmMC_PLL_DIV_SEL_1 0x4A1284
+
+#define mmMC_PLL_DIV_SEL_2 0x4A1288
+
+#define mmMC_PLL_DIV_SEL_3 0x4A128C
+
+#define mmMC_PLL_DIV_EN_0 0x4A12A0
+
+#define mmMC_PLL_DIV_EN_1 0x4A12A4
+
+#define mmMC_PLL_DIV_EN_2 0x4A12A8
+
+#define mmMC_PLL_DIV_EN_3 0x4A12AC
+
+#define mmMC_PLL_DIV_FACTOR_BUSY_0 0x4A12C0
+
+#define mmMC_PLL_DIV_FACTOR_BUSY_1 0x4A12C4
+
+#define mmMC_PLL_DIV_FACTOR_BUSY_2 0x4A12C8
+
+#define mmMC_PLL_DIV_FACTOR_BUSY_3 0x4A12CC
+
+#define mmMC_PLL_CLK_GATER 0x4A1300
+
+#define mmMC_PLL_CLK_RLX_0 0x4A1310
+
+#define mmMC_PLL_CLK_RLX_1 0x4A1314
+
+#define mmMC_PLL_CLK_RLX_2 0x4A1318
+
+#define mmMC_PLL_CLK_RLX_3 0x4A131C
+
+#define mmMC_PLL_REF_CNTR_PERIOD 0x4A1400
+
+#define mmMC_PLL_REF_LOW_THRESHOLD 0x4A1410
+
+#define mmMC_PLL_REF_HIGH_THRESHOLD 0x4A1420
+
+#define mmMC_PLL_PLL_NOT_STABLE 0x4A1430
+
+#define mmMC_PLL_FREQ_CALC_EN 0x4A1440
+
+#endif /* ASIC_REG_MC_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h
new file mode 100644
index 000000000000..687bca5c5fe3
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_masks.h
@@ -0,0 +1,653 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME1_RTR_MASKS_H_
+#define ASIC_REG_MME1_RTR_MASKS_H_
+
+/*
+ *****************************************
+ * MME1_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+/* MME1_RTR_HBW_RD_RQ_E_ARB */
+#define MME1_RTR_HBW_RD_RQ_E_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_E_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RQ_E_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_E_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_RD_RQ_E_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_E_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RQ_E_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RQ_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RQ_W_ARB */
+#define MME1_RTR_HBW_RD_RQ_W_ARB_E_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_W_ARB_E_MASK 0x7
+#define MME1_RTR_HBW_RD_RQ_W_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_W_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_RD_RQ_W_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_W_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RQ_W_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RQ_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RQ_N_ARB */
+#define MME1_RTR_HBW_RD_RQ_N_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_N_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RQ_N_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_N_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RQ_N_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_N_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_RD_RQ_N_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RQ_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RQ_S_ARB */
+#define MME1_RTR_HBW_RD_RQ_S_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_S_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RQ_S_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_S_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RQ_S_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_S_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RQ_S_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RQ_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RQ_L_ARB */
+#define MME1_RTR_HBW_RD_RQ_L_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_L_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RQ_L_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_L_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RQ_L_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_L_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_RD_RQ_L_ARB_N_SHIFT 24
+#define MME1_RTR_HBW_RD_RQ_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_HBW_E_ARB_MAX */
+#define MME1_RTR_HBW_E_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_HBW_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_HBW_W_ARB_MAX */
+#define MME1_RTR_HBW_W_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_HBW_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_HBW_N_ARB_MAX */
+#define MME1_RTR_HBW_N_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_HBW_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_HBW_S_ARB_MAX */
+#define MME1_RTR_HBW_S_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_HBW_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_HBW_L_ARB_MAX */
+#define MME1_RTR_HBW_L_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_HBW_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_HBW_RD_RS_MAX_CREDIT */
+#define MME1_RTR_HBW_RD_RS_MAX_CREDIT_A_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_MAX_CREDIT_A_MASK 0x3F
+#define MME1_RTR_HBW_RD_RS_MAX_CREDIT_B_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_MAX_CREDIT_B_MASK 0x3F00
+
+/* MME1_RTR_HBW_WR_RQ_MAX_CREDIT */
+#define MME1_RTR_HBW_WR_RQ_MAX_CREDIT_VAL_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_MAX_CREDIT_VAL_MASK 0x3F
+
+/* MME1_RTR_HBW_RD_RQ_MAX_CREDIT */
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_A_SHIFT 0
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_A_MASK 0x3F
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_B_SHIFT 8
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_B_MASK 0x3F00
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_IC_SHIFT 16
+#define MME1_RTR_HBW_RD_RQ_MAX_CREDIT_IC_MASK 0x3F0000
+
+/* MME1_RTR_HBW_RD_RS_E_ARB */
+#define MME1_RTR_HBW_RD_RS_E_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_E_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RS_E_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_E_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_RD_RS_E_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RS_E_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RS_E_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RS_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RS_W_ARB */
+#define MME1_RTR_HBW_RD_RS_W_ARB_E_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_W_ARB_E_MASK 0x7
+#define MME1_RTR_HBW_RD_RS_W_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_W_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_RD_RS_W_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RS_W_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RS_W_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RS_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RS_N_ARB */
+#define MME1_RTR_HBW_RD_RS_N_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_N_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RS_N_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_N_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RS_N_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_RD_RS_N_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_RD_RS_N_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RS_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RS_S_ARB */
+#define MME1_RTR_HBW_RD_RS_S_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_S_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RS_S_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_S_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RS_S_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_RD_RS_S_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_RD_RS_S_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_RD_RS_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_RD_RS_L_ARB */
+#define MME1_RTR_HBW_RD_RS_L_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_RD_RS_L_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_RD_RS_L_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_RD_RS_L_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_RD_RS_L_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_RD_RS_L_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_RD_RS_L_ARB_N_SHIFT 24
+#define MME1_RTR_HBW_RD_RS_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RQ_E_ARB */
+#define MME1_RTR_HBW_WR_RQ_E_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_E_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RQ_E_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_WR_RQ_E_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_WR_RQ_E_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RQ_E_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RQ_E_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RQ_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RQ_W_ARB */
+#define MME1_RTR_HBW_WR_RQ_W_ARB_E_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_W_ARB_E_MASK 0x7
+#define MME1_RTR_HBW_WR_RQ_W_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_WR_RQ_W_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_WR_RQ_W_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RQ_W_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RQ_W_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RQ_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RQ_N_ARB */
+#define MME1_RTR_HBW_WR_RQ_N_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_N_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RQ_N_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RQ_N_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RQ_N_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_WR_RQ_N_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_WR_RQ_N_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RQ_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RQ_S_ARB */
+#define MME1_RTR_HBW_WR_RQ_S_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_S_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RQ_S_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RQ_S_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RQ_S_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RQ_S_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RQ_S_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RQ_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RQ_L_ARB */
+#define MME1_RTR_HBW_WR_RQ_L_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RQ_L_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RQ_L_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RQ_L_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RQ_L_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_WR_RQ_L_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_WR_RQ_L_ARB_N_SHIFT 24
+#define MME1_RTR_HBW_WR_RQ_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RS_E_ARB */
+#define MME1_RTR_HBW_WR_RS_E_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RS_E_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RS_E_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_WR_RS_E_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_WR_RS_E_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RS_E_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RS_E_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RS_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RS_W_ARB */
+#define MME1_RTR_HBW_WR_RS_W_ARB_E_SHIFT 0
+#define MME1_RTR_HBW_WR_RS_W_ARB_E_MASK 0x7
+#define MME1_RTR_HBW_WR_RS_W_ARB_S_SHIFT 8
+#define MME1_RTR_HBW_WR_RS_W_ARB_S_MASK 0x700
+#define MME1_RTR_HBW_WR_RS_W_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RS_W_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RS_W_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RS_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RS_N_ARB */
+#define MME1_RTR_HBW_WR_RS_N_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RS_N_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RS_N_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RS_N_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RS_N_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_WR_RS_N_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_WR_RS_N_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RS_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RS_S_ARB */
+#define MME1_RTR_HBW_WR_RS_S_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RS_S_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RS_S_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RS_S_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RS_S_ARB_N_SHIFT 16
+#define MME1_RTR_HBW_WR_RS_S_ARB_N_MASK 0x70000
+#define MME1_RTR_HBW_WR_RS_S_ARB_L_SHIFT 24
+#define MME1_RTR_HBW_WR_RS_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_HBW_WR_RS_L_ARB */
+#define MME1_RTR_HBW_WR_RS_L_ARB_W_SHIFT 0
+#define MME1_RTR_HBW_WR_RS_L_ARB_W_MASK 0x7
+#define MME1_RTR_HBW_WR_RS_L_ARB_E_SHIFT 8
+#define MME1_RTR_HBW_WR_RS_L_ARB_E_MASK 0x700
+#define MME1_RTR_HBW_WR_RS_L_ARB_S_SHIFT 16
+#define MME1_RTR_HBW_WR_RS_L_ARB_S_MASK 0x70000
+#define MME1_RTR_HBW_WR_RS_L_ARB_N_SHIFT 24
+#define MME1_RTR_HBW_WR_RS_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RQ_E_ARB */
+#define MME1_RTR_LBW_RD_RQ_E_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RQ_E_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RQ_E_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_RD_RQ_E_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_RD_RQ_E_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RQ_E_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RQ_E_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RQ_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RQ_W_ARB */
+#define MME1_RTR_LBW_RD_RQ_W_ARB_E_SHIFT 0
+#define MME1_RTR_LBW_RD_RQ_W_ARB_E_MASK 0x7
+#define MME1_RTR_LBW_RD_RQ_W_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_RD_RQ_W_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_RD_RQ_W_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RQ_W_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RQ_W_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RQ_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RQ_N_ARB */
+#define MME1_RTR_LBW_RD_RQ_N_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RQ_N_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RQ_N_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RQ_N_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RQ_N_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_RD_RQ_N_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_RD_RQ_N_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RQ_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RQ_S_ARB */
+#define MME1_RTR_LBW_RD_RQ_S_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RQ_S_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RQ_S_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RQ_S_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RQ_S_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RQ_S_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RQ_S_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RQ_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RQ_L_ARB */
+#define MME1_RTR_LBW_RD_RQ_L_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RQ_L_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RQ_L_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RQ_L_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RQ_L_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_RD_RQ_L_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_RD_RQ_L_ARB_N_SHIFT 24
+#define MME1_RTR_LBW_RD_RQ_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_LBW_E_ARB_MAX */
+#define MME1_RTR_LBW_E_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_LBW_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_LBW_W_ARB_MAX */
+#define MME1_RTR_LBW_W_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_LBW_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_LBW_N_ARB_MAX */
+#define MME1_RTR_LBW_N_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_LBW_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_LBW_S_ARB_MAX */
+#define MME1_RTR_LBW_S_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_LBW_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_LBW_L_ARB_MAX */
+#define MME1_RTR_LBW_L_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_LBW_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_LBW_SRAM_MAX_CREDIT */
+#define MME1_RTR_LBW_SRAM_MAX_CREDIT_MSTR_SHIFT 0
+#define MME1_RTR_LBW_SRAM_MAX_CREDIT_MSTR_MASK 0x3F
+#define MME1_RTR_LBW_SRAM_MAX_CREDIT_SLV_SHIFT 8
+#define MME1_RTR_LBW_SRAM_MAX_CREDIT_SLV_MASK 0x3F00
+
+/* MME1_RTR_LBW_RD_RS_E_ARB */
+#define MME1_RTR_LBW_RD_RS_E_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RS_E_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RS_E_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_RD_RS_E_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_RD_RS_E_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RS_E_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RS_E_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RS_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RS_W_ARB */
+#define MME1_RTR_LBW_RD_RS_W_ARB_E_SHIFT 0
+#define MME1_RTR_LBW_RD_RS_W_ARB_E_MASK 0x7
+#define MME1_RTR_LBW_RD_RS_W_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_RD_RS_W_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_RD_RS_W_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RS_W_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RS_W_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RS_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RS_N_ARB */
+#define MME1_RTR_LBW_RD_RS_N_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RS_N_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RS_N_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RS_N_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RS_N_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_RD_RS_N_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_RD_RS_N_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RS_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RS_S_ARB */
+#define MME1_RTR_LBW_RD_RS_S_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RS_S_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RS_S_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RS_S_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RS_S_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_RD_RS_S_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_RD_RS_S_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_RD_RS_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_RD_RS_L_ARB */
+#define MME1_RTR_LBW_RD_RS_L_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_RD_RS_L_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_RD_RS_L_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_RD_RS_L_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_RD_RS_L_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_RD_RS_L_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_RD_RS_L_ARB_N_SHIFT 24
+#define MME1_RTR_LBW_RD_RS_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RQ_E_ARB */
+#define MME1_RTR_LBW_WR_RQ_E_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RQ_E_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RQ_E_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_WR_RQ_E_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_WR_RQ_E_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RQ_E_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RQ_E_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RQ_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RQ_W_ARB */
+#define MME1_RTR_LBW_WR_RQ_W_ARB_E_SHIFT 0
+#define MME1_RTR_LBW_WR_RQ_W_ARB_E_MASK 0x7
+#define MME1_RTR_LBW_WR_RQ_W_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_WR_RQ_W_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_WR_RQ_W_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RQ_W_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RQ_W_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RQ_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RQ_N_ARB */
+#define MME1_RTR_LBW_WR_RQ_N_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RQ_N_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RQ_N_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RQ_N_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RQ_N_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_WR_RQ_N_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_WR_RQ_N_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RQ_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RQ_S_ARB */
+#define MME1_RTR_LBW_WR_RQ_S_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RQ_S_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RQ_S_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RQ_S_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RQ_S_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RQ_S_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RQ_S_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RQ_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RQ_L_ARB */
+#define MME1_RTR_LBW_WR_RQ_L_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RQ_L_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RQ_L_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RQ_L_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RQ_L_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_WR_RQ_L_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_WR_RQ_L_ARB_N_SHIFT 24
+#define MME1_RTR_LBW_WR_RQ_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RS_E_ARB */
+#define MME1_RTR_LBW_WR_RS_E_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RS_E_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RS_E_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_WR_RS_E_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_WR_RS_E_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RS_E_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RS_E_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RS_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RS_W_ARB */
+#define MME1_RTR_LBW_WR_RS_W_ARB_E_SHIFT 0
+#define MME1_RTR_LBW_WR_RS_W_ARB_E_MASK 0x7
+#define MME1_RTR_LBW_WR_RS_W_ARB_S_SHIFT 8
+#define MME1_RTR_LBW_WR_RS_W_ARB_S_MASK 0x700
+#define MME1_RTR_LBW_WR_RS_W_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RS_W_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RS_W_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RS_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RS_N_ARB */
+#define MME1_RTR_LBW_WR_RS_N_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RS_N_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RS_N_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RS_N_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RS_N_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_WR_RS_N_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_WR_RS_N_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RS_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RS_S_ARB */
+#define MME1_RTR_LBW_WR_RS_S_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RS_S_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RS_S_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RS_S_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RS_S_ARB_N_SHIFT 16
+#define MME1_RTR_LBW_WR_RS_S_ARB_N_MASK 0x70000
+#define MME1_RTR_LBW_WR_RS_S_ARB_L_SHIFT 24
+#define MME1_RTR_LBW_WR_RS_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_LBW_WR_RS_L_ARB */
+#define MME1_RTR_LBW_WR_RS_L_ARB_W_SHIFT 0
+#define MME1_RTR_LBW_WR_RS_L_ARB_W_MASK 0x7
+#define MME1_RTR_LBW_WR_RS_L_ARB_E_SHIFT 8
+#define MME1_RTR_LBW_WR_RS_L_ARB_E_MASK 0x700
+#define MME1_RTR_LBW_WR_RS_L_ARB_S_SHIFT 16
+#define MME1_RTR_LBW_WR_RS_L_ARB_S_MASK 0x70000
+#define MME1_RTR_LBW_WR_RS_L_ARB_N_SHIFT 24
+#define MME1_RTR_LBW_WR_RS_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_DBG_E_ARB */
+#define MME1_RTR_DBG_E_ARB_W_SHIFT 0
+#define MME1_RTR_DBG_E_ARB_W_MASK 0x7
+#define MME1_RTR_DBG_E_ARB_S_SHIFT 8
+#define MME1_RTR_DBG_E_ARB_S_MASK 0x700
+#define MME1_RTR_DBG_E_ARB_N_SHIFT 16
+#define MME1_RTR_DBG_E_ARB_N_MASK 0x70000
+#define MME1_RTR_DBG_E_ARB_L_SHIFT 24
+#define MME1_RTR_DBG_E_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_DBG_W_ARB */
+#define MME1_RTR_DBG_W_ARB_E_SHIFT 0
+#define MME1_RTR_DBG_W_ARB_E_MASK 0x7
+#define MME1_RTR_DBG_W_ARB_S_SHIFT 8
+#define MME1_RTR_DBG_W_ARB_S_MASK 0x700
+#define MME1_RTR_DBG_W_ARB_N_SHIFT 16
+#define MME1_RTR_DBG_W_ARB_N_MASK 0x70000
+#define MME1_RTR_DBG_W_ARB_L_SHIFT 24
+#define MME1_RTR_DBG_W_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_DBG_N_ARB */
+#define MME1_RTR_DBG_N_ARB_W_SHIFT 0
+#define MME1_RTR_DBG_N_ARB_W_MASK 0x7
+#define MME1_RTR_DBG_N_ARB_E_SHIFT 8
+#define MME1_RTR_DBG_N_ARB_E_MASK 0x700
+#define MME1_RTR_DBG_N_ARB_S_SHIFT 16
+#define MME1_RTR_DBG_N_ARB_S_MASK 0x70000
+#define MME1_RTR_DBG_N_ARB_L_SHIFT 24
+#define MME1_RTR_DBG_N_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_DBG_S_ARB */
+#define MME1_RTR_DBG_S_ARB_W_SHIFT 0
+#define MME1_RTR_DBG_S_ARB_W_MASK 0x7
+#define MME1_RTR_DBG_S_ARB_E_SHIFT 8
+#define MME1_RTR_DBG_S_ARB_E_MASK 0x700
+#define MME1_RTR_DBG_S_ARB_N_SHIFT 16
+#define MME1_RTR_DBG_S_ARB_N_MASK 0x70000
+#define MME1_RTR_DBG_S_ARB_L_SHIFT 24
+#define MME1_RTR_DBG_S_ARB_L_MASK 0x7000000
+
+/* MME1_RTR_DBG_L_ARB */
+#define MME1_RTR_DBG_L_ARB_W_SHIFT 0
+#define MME1_RTR_DBG_L_ARB_W_MASK 0x7
+#define MME1_RTR_DBG_L_ARB_E_SHIFT 8
+#define MME1_RTR_DBG_L_ARB_E_MASK 0x700
+#define MME1_RTR_DBG_L_ARB_S_SHIFT 16
+#define MME1_RTR_DBG_L_ARB_S_MASK 0x70000
+#define MME1_RTR_DBG_L_ARB_N_SHIFT 24
+#define MME1_RTR_DBG_L_ARB_N_MASK 0x7000000
+
+/* MME1_RTR_DBG_E_ARB_MAX */
+#define MME1_RTR_DBG_E_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_DBG_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_DBG_W_ARB_MAX */
+#define MME1_RTR_DBG_W_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_DBG_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_DBG_N_ARB_MAX */
+#define MME1_RTR_DBG_N_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_DBG_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_DBG_S_ARB_MAX */
+#define MME1_RTR_DBG_S_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_DBG_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_DBG_L_ARB_MAX */
+#define MME1_RTR_DBG_L_ARB_MAX_CREDIT_SHIFT 0
+#define MME1_RTR_DBG_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* MME1_RTR_SPLIT_COEF */
+#define MME1_RTR_SPLIT_COEF_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_COEF_VAL_MASK 0xFFFF
+
+/* MME1_RTR_SPLIT_CFG */
+#define MME1_RTR_SPLIT_CFG_FORCE_WAK_ORDER_SHIFT 0
+#define MME1_RTR_SPLIT_CFG_FORCE_WAK_ORDER_MASK 0x1
+#define MME1_RTR_SPLIT_CFG_FORCE_STRONG_ORDER_SHIFT 1
+#define MME1_RTR_SPLIT_CFG_FORCE_STRONG_ORDER_MASK 0x2
+#define MME1_RTR_SPLIT_CFG_DEFAULT_MESH_SHIFT 2
+#define MME1_RTR_SPLIT_CFG_DEFAULT_MESH_MASK 0xC
+#define MME1_RTR_SPLIT_CFG_WR_RATE_LIM_EN_SHIFT 4
+#define MME1_RTR_SPLIT_CFG_WR_RATE_LIM_EN_MASK 0x10
+#define MME1_RTR_SPLIT_CFG_RD_RATE_LIM_EN_SHIFT 5
+#define MME1_RTR_SPLIT_CFG_RD_RATE_LIM_EN_MASK 0x20
+#define MME1_RTR_SPLIT_CFG_B2B_OPT_SHIFT 6
+#define MME1_RTR_SPLIT_CFG_B2B_OPT_MASK 0x1C0
+
+/* MME1_RTR_SPLIT_RD_SAT */
+#define MME1_RTR_SPLIT_RD_SAT_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_RD_SAT_VAL_MASK 0xFFFF
+
+/* MME1_RTR_SPLIT_RD_RST_TOKEN */
+#define MME1_RTR_SPLIT_RD_RST_TOKEN_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_RD_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* MME1_RTR_SPLIT_RD_TIMEOUT */
+#define MME1_RTR_SPLIT_RD_TIMEOUT_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_RD_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* MME1_RTR_SPLIT_WR_SAT */
+#define MME1_RTR_SPLIT_WR_SAT_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_WR_SAT_VAL_MASK 0xFFFF
+
+/* MME1_RTR_WPLIT_WR_TST_TOLEN */
+#define MME1_RTR_WPLIT_WR_TST_TOLEN_VAL_SHIFT 0
+#define MME1_RTR_WPLIT_WR_TST_TOLEN_VAL_MASK 0xFFFF
+
+/* MME1_RTR_SPLIT_WR_TIMEOUT */
+#define MME1_RTR_SPLIT_WR_TIMEOUT_VAL_SHIFT 0
+#define MME1_RTR_SPLIT_WR_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* MME1_RTR_HBW_RANGE_HIT */
+#define MME1_RTR_HBW_RANGE_HIT_IND_SHIFT 0
+#define MME1_RTR_HBW_RANGE_HIT_IND_MASK 0xFF
+
+/* MME1_RTR_HBW_RANGE_MASK_L */
+#define MME1_RTR_HBW_RANGE_MASK_L_VAL_SHIFT 0
+#define MME1_RTR_HBW_RANGE_MASK_L_VAL_MASK 0xFFFFFFFF
+
+/* MME1_RTR_HBW_RANGE_MASK_H */
+#define MME1_RTR_HBW_RANGE_MASK_H_VAL_SHIFT 0
+#define MME1_RTR_HBW_RANGE_MASK_H_VAL_MASK 0x3FFFF
+
+/* MME1_RTR_HBW_RANGE_BASE_L */
+#define MME1_RTR_HBW_RANGE_BASE_L_VAL_SHIFT 0
+#define MME1_RTR_HBW_RANGE_BASE_L_VAL_MASK 0xFFFFFFFF
+
+/* MME1_RTR_HBW_RANGE_BASE_H */
+#define MME1_RTR_HBW_RANGE_BASE_H_VAL_SHIFT 0
+#define MME1_RTR_HBW_RANGE_BASE_H_VAL_MASK 0x3FFFF
+
+/* MME1_RTR_LBW_RANGE_HIT */
+#define MME1_RTR_LBW_RANGE_HIT_IND_SHIFT 0
+#define MME1_RTR_LBW_RANGE_HIT_IND_MASK 0xFFFF
+
+/* MME1_RTR_LBW_RANGE_MASK */
+#define MME1_RTR_LBW_RANGE_MASK_VAL_SHIFT 0
+#define MME1_RTR_LBW_RANGE_MASK_VAL_MASK 0x3FFFFFF
+
+/* MME1_RTR_LBW_RANGE_BASE */
+#define MME1_RTR_LBW_RANGE_BASE_VAL_SHIFT 0
+#define MME1_RTR_LBW_RANGE_BASE_VAL_MASK 0x3FFFFFF
+
+/* MME1_RTR_RGLTR */
+#define MME1_RTR_RGLTR_WR_EN_SHIFT 0
+#define MME1_RTR_RGLTR_WR_EN_MASK 0x1
+#define MME1_RTR_RGLTR_RD_EN_SHIFT 4
+#define MME1_RTR_RGLTR_RD_EN_MASK 0x10
+
+/* MME1_RTR_RGLTR_WR_RESULT */
+#define MME1_RTR_RGLTR_WR_RESULT_VAL_SHIFT 0
+#define MME1_RTR_RGLTR_WR_RESULT_VAL_MASK 0xFF
+
+/* MME1_RTR_RGLTR_RD_RESULT */
+#define MME1_RTR_RGLTR_RD_RESULT_VAL_SHIFT 0
+#define MME1_RTR_RGLTR_RD_RESULT_VAL_MASK 0xFF
+
+/* MME1_RTR_SCRAMB_EN */
+#define MME1_RTR_SCRAMB_EN_VAL_SHIFT 0
+#define MME1_RTR_SCRAMB_EN_VAL_MASK 0x1
+
+/* MME1_RTR_NON_LIN_SCRAMB */
+#define MME1_RTR_NON_LIN_SCRAMB_EN_SHIFT 0
+#define MME1_RTR_NON_LIN_SCRAMB_EN_MASK 0x1
+
+#endif /* ASIC_REG_MME1_RTR_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h
new file mode 100644
index 000000000000..c248339a1cbe
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme1_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME1_RTR_REGS_H_
+#define ASIC_REG_MME1_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME1_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME1_RTR_HBW_RD_RQ_E_ARB 0x40100
+
+#define mmMME1_RTR_HBW_RD_RQ_W_ARB 0x40104
+
+#define mmMME1_RTR_HBW_RD_RQ_N_ARB 0x40108
+
+#define mmMME1_RTR_HBW_RD_RQ_S_ARB 0x4010C
+
+#define mmMME1_RTR_HBW_RD_RQ_L_ARB 0x40110
+
+#define mmMME1_RTR_HBW_E_ARB_MAX 0x40120
+
+#define mmMME1_RTR_HBW_W_ARB_MAX 0x40124
+
+#define mmMME1_RTR_HBW_N_ARB_MAX 0x40128
+
+#define mmMME1_RTR_HBW_S_ARB_MAX 0x4012C
+
+#define mmMME1_RTR_HBW_L_ARB_MAX 0x40130
+
+#define mmMME1_RTR_HBW_RD_RS_MAX_CREDIT 0x40140
+
+#define mmMME1_RTR_HBW_WR_RQ_MAX_CREDIT 0x40144
+
+#define mmMME1_RTR_HBW_RD_RQ_MAX_CREDIT 0x40148
+
+#define mmMME1_RTR_HBW_RD_RS_E_ARB 0x40150
+
+#define mmMME1_RTR_HBW_RD_RS_W_ARB 0x40154
+
+#define mmMME1_RTR_HBW_RD_RS_N_ARB 0x40158
+
+#define mmMME1_RTR_HBW_RD_RS_S_ARB 0x4015C
+
+#define mmMME1_RTR_HBW_RD_RS_L_ARB 0x40160
+
+#define mmMME1_RTR_HBW_WR_RQ_E_ARB 0x40170
+
+#define mmMME1_RTR_HBW_WR_RQ_W_ARB 0x40174
+
+#define mmMME1_RTR_HBW_WR_RQ_N_ARB 0x40178
+
+#define mmMME1_RTR_HBW_WR_RQ_S_ARB 0x4017C
+
+#define mmMME1_RTR_HBW_WR_RQ_L_ARB 0x40180
+
+#define mmMME1_RTR_HBW_WR_RS_E_ARB 0x40190
+
+#define mmMME1_RTR_HBW_WR_RS_W_ARB 0x40194
+
+#define mmMME1_RTR_HBW_WR_RS_N_ARB 0x40198
+
+#define mmMME1_RTR_HBW_WR_RS_S_ARB 0x4019C
+
+#define mmMME1_RTR_HBW_WR_RS_L_ARB 0x401A0
+
+#define mmMME1_RTR_LBW_RD_RQ_E_ARB 0x40200
+
+#define mmMME1_RTR_LBW_RD_RQ_W_ARB 0x40204
+
+#define mmMME1_RTR_LBW_RD_RQ_N_ARB 0x40208
+
+#define mmMME1_RTR_LBW_RD_RQ_S_ARB 0x4020C
+
+#define mmMME1_RTR_LBW_RD_RQ_L_ARB 0x40210
+
+#define mmMME1_RTR_LBW_E_ARB_MAX 0x40220
+
+#define mmMME1_RTR_LBW_W_ARB_MAX 0x40224
+
+#define mmMME1_RTR_LBW_N_ARB_MAX 0x40228
+
+#define mmMME1_RTR_LBW_S_ARB_MAX 0x4022C
+
+#define mmMME1_RTR_LBW_L_ARB_MAX 0x40230
+
+#define mmMME1_RTR_LBW_SRAM_MAX_CREDIT 0x40240
+
+#define mmMME1_RTR_LBW_RD_RS_E_ARB 0x40250
+
+#define mmMME1_RTR_LBW_RD_RS_W_ARB 0x40254
+
+#define mmMME1_RTR_LBW_RD_RS_N_ARB 0x40258
+
+#define mmMME1_RTR_LBW_RD_RS_S_ARB 0x4025C
+
+#define mmMME1_RTR_LBW_RD_RS_L_ARB 0x40260
+
+#define mmMME1_RTR_LBW_WR_RQ_E_ARB 0x40270
+
+#define mmMME1_RTR_LBW_WR_RQ_W_ARB 0x40274
+
+#define mmMME1_RTR_LBW_WR_RQ_N_ARB 0x40278
+
+#define mmMME1_RTR_LBW_WR_RQ_S_ARB 0x4027C
+
+#define mmMME1_RTR_LBW_WR_RQ_L_ARB 0x40280
+
+#define mmMME1_RTR_LBW_WR_RS_E_ARB 0x40290
+
+#define mmMME1_RTR_LBW_WR_RS_W_ARB 0x40294
+
+#define mmMME1_RTR_LBW_WR_RS_N_ARB 0x40298
+
+#define mmMME1_RTR_LBW_WR_RS_S_ARB 0x4029C
+
+#define mmMME1_RTR_LBW_WR_RS_L_ARB 0x402A0
+
+#define mmMME1_RTR_DBG_E_ARB 0x40300
+
+#define mmMME1_RTR_DBG_W_ARB 0x40304
+
+#define mmMME1_RTR_DBG_N_ARB 0x40308
+
+#define mmMME1_RTR_DBG_S_ARB 0x4030C
+
+#define mmMME1_RTR_DBG_L_ARB 0x40310
+
+#define mmMME1_RTR_DBG_E_ARB_MAX 0x40320
+
+#define mmMME1_RTR_DBG_W_ARB_MAX 0x40324
+
+#define mmMME1_RTR_DBG_N_ARB_MAX 0x40328
+
+#define mmMME1_RTR_DBG_S_ARB_MAX 0x4032C
+
+#define mmMME1_RTR_DBG_L_ARB_MAX 0x40330
+
+#define mmMME1_RTR_SPLIT_COEF_0 0x40400
+
+#define mmMME1_RTR_SPLIT_COEF_1 0x40404
+
+#define mmMME1_RTR_SPLIT_COEF_2 0x40408
+
+#define mmMME1_RTR_SPLIT_COEF_3 0x4040C
+
+#define mmMME1_RTR_SPLIT_COEF_4 0x40410
+
+#define mmMME1_RTR_SPLIT_COEF_5 0x40414
+
+#define mmMME1_RTR_SPLIT_COEF_6 0x40418
+
+#define mmMME1_RTR_SPLIT_COEF_7 0x4041C
+
+#define mmMME1_RTR_SPLIT_COEF_8 0x40420
+
+#define mmMME1_RTR_SPLIT_COEF_9 0x40424
+
+#define mmMME1_RTR_SPLIT_CFG 0x40440
+
+#define mmMME1_RTR_SPLIT_RD_SAT 0x40444
+
+#define mmMME1_RTR_SPLIT_RD_RST_TOKEN 0x40448
+
+#define mmMME1_RTR_SPLIT_RD_TIMEOUT_0 0x4044C
+
+#define mmMME1_RTR_SPLIT_RD_TIMEOUT_1 0x40450
+
+#define mmMME1_RTR_SPLIT_WR_SAT 0x40454
+
+#define mmMME1_RTR_WPLIT_WR_TST_TOLEN 0x40458
+
+#define mmMME1_RTR_SPLIT_WR_TIMEOUT_0 0x4045C
+
+#define mmMME1_RTR_SPLIT_WR_TIMEOUT_1 0x40460
+
+#define mmMME1_RTR_HBW_RANGE_HIT 0x40470
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_0 0x40480
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_1 0x40484
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_2 0x40488
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_3 0x4048C
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_4 0x40490
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_5 0x40494
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_6 0x40498
+
+#define mmMME1_RTR_HBW_RANGE_MASK_L_7 0x4049C
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_0 0x404A0
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_1 0x404A4
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_2 0x404A8
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_3 0x404AC
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_4 0x404B0
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_5 0x404B4
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_6 0x404B8
+
+#define mmMME1_RTR_HBW_RANGE_MASK_H_7 0x404BC
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_0 0x404C0
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_1 0x404C4
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_2 0x404C8
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_3 0x404CC
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_4 0x404D0
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_5 0x404D4
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_6 0x404D8
+
+#define mmMME1_RTR_HBW_RANGE_BASE_L_7 0x404DC
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_0 0x404E0
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_1 0x404E4
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_2 0x404E8
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_3 0x404EC
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_4 0x404F0
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_5 0x404F4
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_6 0x404F8
+
+#define mmMME1_RTR_HBW_RANGE_BASE_H_7 0x404FC
+
+#define mmMME1_RTR_LBW_RANGE_HIT 0x40500
+
+#define mmMME1_RTR_LBW_RANGE_MASK_0 0x40510
+
+#define mmMME1_RTR_LBW_RANGE_MASK_1 0x40514
+
+#define mmMME1_RTR_LBW_RANGE_MASK_2 0x40518
+
+#define mmMME1_RTR_LBW_RANGE_MASK_3 0x4051C
+
+#define mmMME1_RTR_LBW_RANGE_MASK_4 0x40520
+
+#define mmMME1_RTR_LBW_RANGE_MASK_5 0x40524
+
+#define mmMME1_RTR_LBW_RANGE_MASK_6 0x40528
+
+#define mmMME1_RTR_LBW_RANGE_MASK_7 0x4052C
+
+#define mmMME1_RTR_LBW_RANGE_MASK_8 0x40530
+
+#define mmMME1_RTR_LBW_RANGE_MASK_9 0x40534
+
+#define mmMME1_RTR_LBW_RANGE_MASK_10 0x40538
+
+#define mmMME1_RTR_LBW_RANGE_MASK_11 0x4053C
+
+#define mmMME1_RTR_LBW_RANGE_MASK_12 0x40540
+
+#define mmMME1_RTR_LBW_RANGE_MASK_13 0x40544
+
+#define mmMME1_RTR_LBW_RANGE_MASK_14 0x40548
+
+#define mmMME1_RTR_LBW_RANGE_MASK_15 0x4054C
+
+#define mmMME1_RTR_LBW_RANGE_BASE_0 0x40550
+
+#define mmMME1_RTR_LBW_RANGE_BASE_1 0x40554
+
+#define mmMME1_RTR_LBW_RANGE_BASE_2 0x40558
+
+#define mmMME1_RTR_LBW_RANGE_BASE_3 0x4055C
+
+#define mmMME1_RTR_LBW_RANGE_BASE_4 0x40560
+
+#define mmMME1_RTR_LBW_RANGE_BASE_5 0x40564
+
+#define mmMME1_RTR_LBW_RANGE_BASE_6 0x40568
+
+#define mmMME1_RTR_LBW_RANGE_BASE_7 0x4056C
+
+#define mmMME1_RTR_LBW_RANGE_BASE_8 0x40570
+
+#define mmMME1_RTR_LBW_RANGE_BASE_9 0x40574
+
+#define mmMME1_RTR_LBW_RANGE_BASE_10 0x40578
+
+#define mmMME1_RTR_LBW_RANGE_BASE_11 0x4057C
+
+#define mmMME1_RTR_LBW_RANGE_BASE_12 0x40580
+
+#define mmMME1_RTR_LBW_RANGE_BASE_13 0x40584
+
+#define mmMME1_RTR_LBW_RANGE_BASE_14 0x40588
+
+#define mmMME1_RTR_LBW_RANGE_BASE_15 0x4058C
+
+#define mmMME1_RTR_RGLTR 0x40590
+
+#define mmMME1_RTR_RGLTR_WR_RESULT 0x40594
+
+#define mmMME1_RTR_RGLTR_RD_RESULT 0x40598
+
+#define mmMME1_RTR_SCRAMB_EN 0x40600
+
+#define mmMME1_RTR_NON_LIN_SCRAMB 0x40604
+
+#endif /* ASIC_REG_MME1_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h
new file mode 100644
index 000000000000..7a2b777bdc4f
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme2_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME2_RTR_REGS_H_
+#define ASIC_REG_MME2_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME2_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME2_RTR_HBW_RD_RQ_E_ARB 0x80100
+
+#define mmMME2_RTR_HBW_RD_RQ_W_ARB 0x80104
+
+#define mmMME2_RTR_HBW_RD_RQ_N_ARB 0x80108
+
+#define mmMME2_RTR_HBW_RD_RQ_S_ARB 0x8010C
+
+#define mmMME2_RTR_HBW_RD_RQ_L_ARB 0x80110
+
+#define mmMME2_RTR_HBW_E_ARB_MAX 0x80120
+
+#define mmMME2_RTR_HBW_W_ARB_MAX 0x80124
+
+#define mmMME2_RTR_HBW_N_ARB_MAX 0x80128
+
+#define mmMME2_RTR_HBW_S_ARB_MAX 0x8012C
+
+#define mmMME2_RTR_HBW_L_ARB_MAX 0x80130
+
+#define mmMME2_RTR_HBW_RD_RS_MAX_CREDIT 0x80140
+
+#define mmMME2_RTR_HBW_WR_RQ_MAX_CREDIT 0x80144
+
+#define mmMME2_RTR_HBW_RD_RQ_MAX_CREDIT 0x80148
+
+#define mmMME2_RTR_HBW_RD_RS_E_ARB 0x80150
+
+#define mmMME2_RTR_HBW_RD_RS_W_ARB 0x80154
+
+#define mmMME2_RTR_HBW_RD_RS_N_ARB 0x80158
+
+#define mmMME2_RTR_HBW_RD_RS_S_ARB 0x8015C
+
+#define mmMME2_RTR_HBW_RD_RS_L_ARB 0x80160
+
+#define mmMME2_RTR_HBW_WR_RQ_E_ARB 0x80170
+
+#define mmMME2_RTR_HBW_WR_RQ_W_ARB 0x80174
+
+#define mmMME2_RTR_HBW_WR_RQ_N_ARB 0x80178
+
+#define mmMME2_RTR_HBW_WR_RQ_S_ARB 0x8017C
+
+#define mmMME2_RTR_HBW_WR_RQ_L_ARB 0x80180
+
+#define mmMME2_RTR_HBW_WR_RS_E_ARB 0x80190
+
+#define mmMME2_RTR_HBW_WR_RS_W_ARB 0x80194
+
+#define mmMME2_RTR_HBW_WR_RS_N_ARB 0x80198
+
+#define mmMME2_RTR_HBW_WR_RS_S_ARB 0x8019C
+
+#define mmMME2_RTR_HBW_WR_RS_L_ARB 0x801A0
+
+#define mmMME2_RTR_LBW_RD_RQ_E_ARB 0x80200
+
+#define mmMME2_RTR_LBW_RD_RQ_W_ARB 0x80204
+
+#define mmMME2_RTR_LBW_RD_RQ_N_ARB 0x80208
+
+#define mmMME2_RTR_LBW_RD_RQ_S_ARB 0x8020C
+
+#define mmMME2_RTR_LBW_RD_RQ_L_ARB 0x80210
+
+#define mmMME2_RTR_LBW_E_ARB_MAX 0x80220
+
+#define mmMME2_RTR_LBW_W_ARB_MAX 0x80224
+
+#define mmMME2_RTR_LBW_N_ARB_MAX 0x80228
+
+#define mmMME2_RTR_LBW_S_ARB_MAX 0x8022C
+
+#define mmMME2_RTR_LBW_L_ARB_MAX 0x80230
+
+#define mmMME2_RTR_LBW_SRAM_MAX_CREDIT 0x80240
+
+#define mmMME2_RTR_LBW_RD_RS_E_ARB 0x80250
+
+#define mmMME2_RTR_LBW_RD_RS_W_ARB 0x80254
+
+#define mmMME2_RTR_LBW_RD_RS_N_ARB 0x80258
+
+#define mmMME2_RTR_LBW_RD_RS_S_ARB 0x8025C
+
+#define mmMME2_RTR_LBW_RD_RS_L_ARB 0x80260
+
+#define mmMME2_RTR_LBW_WR_RQ_E_ARB 0x80270
+
+#define mmMME2_RTR_LBW_WR_RQ_W_ARB 0x80274
+
+#define mmMME2_RTR_LBW_WR_RQ_N_ARB 0x80278
+
+#define mmMME2_RTR_LBW_WR_RQ_S_ARB 0x8027C
+
+#define mmMME2_RTR_LBW_WR_RQ_L_ARB 0x80280
+
+#define mmMME2_RTR_LBW_WR_RS_E_ARB 0x80290
+
+#define mmMME2_RTR_LBW_WR_RS_W_ARB 0x80294
+
+#define mmMME2_RTR_LBW_WR_RS_N_ARB 0x80298
+
+#define mmMME2_RTR_LBW_WR_RS_S_ARB 0x8029C
+
+#define mmMME2_RTR_LBW_WR_RS_L_ARB 0x802A0
+
+#define mmMME2_RTR_DBG_E_ARB 0x80300
+
+#define mmMME2_RTR_DBG_W_ARB 0x80304
+
+#define mmMME2_RTR_DBG_N_ARB 0x80308
+
+#define mmMME2_RTR_DBG_S_ARB 0x8030C
+
+#define mmMME2_RTR_DBG_L_ARB 0x80310
+
+#define mmMME2_RTR_DBG_E_ARB_MAX 0x80320
+
+#define mmMME2_RTR_DBG_W_ARB_MAX 0x80324
+
+#define mmMME2_RTR_DBG_N_ARB_MAX 0x80328
+
+#define mmMME2_RTR_DBG_S_ARB_MAX 0x8032C
+
+#define mmMME2_RTR_DBG_L_ARB_MAX 0x80330
+
+#define mmMME2_RTR_SPLIT_COEF_0 0x80400
+
+#define mmMME2_RTR_SPLIT_COEF_1 0x80404
+
+#define mmMME2_RTR_SPLIT_COEF_2 0x80408
+
+#define mmMME2_RTR_SPLIT_COEF_3 0x8040C
+
+#define mmMME2_RTR_SPLIT_COEF_4 0x80410
+
+#define mmMME2_RTR_SPLIT_COEF_5 0x80414
+
+#define mmMME2_RTR_SPLIT_COEF_6 0x80418
+
+#define mmMME2_RTR_SPLIT_COEF_7 0x8041C
+
+#define mmMME2_RTR_SPLIT_COEF_8 0x80420
+
+#define mmMME2_RTR_SPLIT_COEF_9 0x80424
+
+#define mmMME2_RTR_SPLIT_CFG 0x80440
+
+#define mmMME2_RTR_SPLIT_RD_SAT 0x80444
+
+#define mmMME2_RTR_SPLIT_RD_RST_TOKEN 0x80448
+
+#define mmMME2_RTR_SPLIT_RD_TIMEOUT_0 0x8044C
+
+#define mmMME2_RTR_SPLIT_RD_TIMEOUT_1 0x80450
+
+#define mmMME2_RTR_SPLIT_WR_SAT 0x80454
+
+#define mmMME2_RTR_WPLIT_WR_TST_TOLEN 0x80458
+
+#define mmMME2_RTR_SPLIT_WR_TIMEOUT_0 0x8045C
+
+#define mmMME2_RTR_SPLIT_WR_TIMEOUT_1 0x80460
+
+#define mmMME2_RTR_HBW_RANGE_HIT 0x80470
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_0 0x80480
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_1 0x80484
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_2 0x80488
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_3 0x8048C
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_4 0x80490
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_5 0x80494
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_6 0x80498
+
+#define mmMME2_RTR_HBW_RANGE_MASK_L_7 0x8049C
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_0 0x804A0
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_1 0x804A4
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_2 0x804A8
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_3 0x804AC
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_4 0x804B0
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_5 0x804B4
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_6 0x804B8
+
+#define mmMME2_RTR_HBW_RANGE_MASK_H_7 0x804BC
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_0 0x804C0
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_1 0x804C4
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_2 0x804C8
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_3 0x804CC
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_4 0x804D0
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_5 0x804D4
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_6 0x804D8
+
+#define mmMME2_RTR_HBW_RANGE_BASE_L_7 0x804DC
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_0 0x804E0
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_1 0x804E4
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_2 0x804E8
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_3 0x804EC
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_4 0x804F0
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_5 0x804F4
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_6 0x804F8
+
+#define mmMME2_RTR_HBW_RANGE_BASE_H_7 0x804FC
+
+#define mmMME2_RTR_LBW_RANGE_HIT 0x80500
+
+#define mmMME2_RTR_LBW_RANGE_MASK_0 0x80510
+
+#define mmMME2_RTR_LBW_RANGE_MASK_1 0x80514
+
+#define mmMME2_RTR_LBW_RANGE_MASK_2 0x80518
+
+#define mmMME2_RTR_LBW_RANGE_MASK_3 0x8051C
+
+#define mmMME2_RTR_LBW_RANGE_MASK_4 0x80520
+
+#define mmMME2_RTR_LBW_RANGE_MASK_5 0x80524
+
+#define mmMME2_RTR_LBW_RANGE_MASK_6 0x80528
+
+#define mmMME2_RTR_LBW_RANGE_MASK_7 0x8052C
+
+#define mmMME2_RTR_LBW_RANGE_MASK_8 0x80530
+
+#define mmMME2_RTR_LBW_RANGE_MASK_9 0x80534
+
+#define mmMME2_RTR_LBW_RANGE_MASK_10 0x80538
+
+#define mmMME2_RTR_LBW_RANGE_MASK_11 0x8053C
+
+#define mmMME2_RTR_LBW_RANGE_MASK_12 0x80540
+
+#define mmMME2_RTR_LBW_RANGE_MASK_13 0x80544
+
+#define mmMME2_RTR_LBW_RANGE_MASK_14 0x80548
+
+#define mmMME2_RTR_LBW_RANGE_MASK_15 0x8054C
+
+#define mmMME2_RTR_LBW_RANGE_BASE_0 0x80550
+
+#define mmMME2_RTR_LBW_RANGE_BASE_1 0x80554
+
+#define mmMME2_RTR_LBW_RANGE_BASE_2 0x80558
+
+#define mmMME2_RTR_LBW_RANGE_BASE_3 0x8055C
+
+#define mmMME2_RTR_LBW_RANGE_BASE_4 0x80560
+
+#define mmMME2_RTR_LBW_RANGE_BASE_5 0x80564
+
+#define mmMME2_RTR_LBW_RANGE_BASE_6 0x80568
+
+#define mmMME2_RTR_LBW_RANGE_BASE_7 0x8056C
+
+#define mmMME2_RTR_LBW_RANGE_BASE_8 0x80570
+
+#define mmMME2_RTR_LBW_RANGE_BASE_9 0x80574
+
+#define mmMME2_RTR_LBW_RANGE_BASE_10 0x80578
+
+#define mmMME2_RTR_LBW_RANGE_BASE_11 0x8057C
+
+#define mmMME2_RTR_LBW_RANGE_BASE_12 0x80580
+
+#define mmMME2_RTR_LBW_RANGE_BASE_13 0x80584
+
+#define mmMME2_RTR_LBW_RANGE_BASE_14 0x80588
+
+#define mmMME2_RTR_LBW_RANGE_BASE_15 0x8058C
+
+#define mmMME2_RTR_RGLTR 0x80590
+
+#define mmMME2_RTR_RGLTR_WR_RESULT 0x80594
+
+#define mmMME2_RTR_RGLTR_RD_RESULT 0x80598
+
+#define mmMME2_RTR_SCRAMB_EN 0x80600
+
+#define mmMME2_RTR_NON_LIN_SCRAMB 0x80604
+
+#endif /* ASIC_REG_MME2_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h
new file mode 100644
index 000000000000..b78f8bc387fc
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme3_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME3_RTR_REGS_H_
+#define ASIC_REG_MME3_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME3_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME3_RTR_HBW_RD_RQ_E_ARB 0xC0100
+
+#define mmMME3_RTR_HBW_RD_RQ_W_ARB 0xC0104
+
+#define mmMME3_RTR_HBW_RD_RQ_N_ARB 0xC0108
+
+#define mmMME3_RTR_HBW_RD_RQ_S_ARB 0xC010C
+
+#define mmMME3_RTR_HBW_RD_RQ_L_ARB 0xC0110
+
+#define mmMME3_RTR_HBW_E_ARB_MAX 0xC0120
+
+#define mmMME3_RTR_HBW_W_ARB_MAX 0xC0124
+
+#define mmMME3_RTR_HBW_N_ARB_MAX 0xC0128
+
+#define mmMME3_RTR_HBW_S_ARB_MAX 0xC012C
+
+#define mmMME3_RTR_HBW_L_ARB_MAX 0xC0130
+
+#define mmMME3_RTR_HBW_RD_RS_MAX_CREDIT 0xC0140
+
+#define mmMME3_RTR_HBW_WR_RQ_MAX_CREDIT 0xC0144
+
+#define mmMME3_RTR_HBW_RD_RQ_MAX_CREDIT 0xC0148
+
+#define mmMME3_RTR_HBW_RD_RS_E_ARB 0xC0150
+
+#define mmMME3_RTR_HBW_RD_RS_W_ARB 0xC0154
+
+#define mmMME3_RTR_HBW_RD_RS_N_ARB 0xC0158
+
+#define mmMME3_RTR_HBW_RD_RS_S_ARB 0xC015C
+
+#define mmMME3_RTR_HBW_RD_RS_L_ARB 0xC0160
+
+#define mmMME3_RTR_HBW_WR_RQ_E_ARB 0xC0170
+
+#define mmMME3_RTR_HBW_WR_RQ_W_ARB 0xC0174
+
+#define mmMME3_RTR_HBW_WR_RQ_N_ARB 0xC0178
+
+#define mmMME3_RTR_HBW_WR_RQ_S_ARB 0xC017C
+
+#define mmMME3_RTR_HBW_WR_RQ_L_ARB 0xC0180
+
+#define mmMME3_RTR_HBW_WR_RS_E_ARB 0xC0190
+
+#define mmMME3_RTR_HBW_WR_RS_W_ARB 0xC0194
+
+#define mmMME3_RTR_HBW_WR_RS_N_ARB 0xC0198
+
+#define mmMME3_RTR_HBW_WR_RS_S_ARB 0xC019C
+
+#define mmMME3_RTR_HBW_WR_RS_L_ARB 0xC01A0
+
+#define mmMME3_RTR_LBW_RD_RQ_E_ARB 0xC0200
+
+#define mmMME3_RTR_LBW_RD_RQ_W_ARB 0xC0204
+
+#define mmMME3_RTR_LBW_RD_RQ_N_ARB 0xC0208
+
+#define mmMME3_RTR_LBW_RD_RQ_S_ARB 0xC020C
+
+#define mmMME3_RTR_LBW_RD_RQ_L_ARB 0xC0210
+
+#define mmMME3_RTR_LBW_E_ARB_MAX 0xC0220
+
+#define mmMME3_RTR_LBW_W_ARB_MAX 0xC0224
+
+#define mmMME3_RTR_LBW_N_ARB_MAX 0xC0228
+
+#define mmMME3_RTR_LBW_S_ARB_MAX 0xC022C
+
+#define mmMME3_RTR_LBW_L_ARB_MAX 0xC0230
+
+#define mmMME3_RTR_LBW_SRAM_MAX_CREDIT 0xC0240
+
+#define mmMME3_RTR_LBW_RD_RS_E_ARB 0xC0250
+
+#define mmMME3_RTR_LBW_RD_RS_W_ARB 0xC0254
+
+#define mmMME3_RTR_LBW_RD_RS_N_ARB 0xC0258
+
+#define mmMME3_RTR_LBW_RD_RS_S_ARB 0xC025C
+
+#define mmMME3_RTR_LBW_RD_RS_L_ARB 0xC0260
+
+#define mmMME3_RTR_LBW_WR_RQ_E_ARB 0xC0270
+
+#define mmMME3_RTR_LBW_WR_RQ_W_ARB 0xC0274
+
+#define mmMME3_RTR_LBW_WR_RQ_N_ARB 0xC0278
+
+#define mmMME3_RTR_LBW_WR_RQ_S_ARB 0xC027C
+
+#define mmMME3_RTR_LBW_WR_RQ_L_ARB 0xC0280
+
+#define mmMME3_RTR_LBW_WR_RS_E_ARB 0xC0290
+
+#define mmMME3_RTR_LBW_WR_RS_W_ARB 0xC0294
+
+#define mmMME3_RTR_LBW_WR_RS_N_ARB 0xC0298
+
+#define mmMME3_RTR_LBW_WR_RS_S_ARB 0xC029C
+
+#define mmMME3_RTR_LBW_WR_RS_L_ARB 0xC02A0
+
+#define mmMME3_RTR_DBG_E_ARB 0xC0300
+
+#define mmMME3_RTR_DBG_W_ARB 0xC0304
+
+#define mmMME3_RTR_DBG_N_ARB 0xC0308
+
+#define mmMME3_RTR_DBG_S_ARB 0xC030C
+
+#define mmMME3_RTR_DBG_L_ARB 0xC0310
+
+#define mmMME3_RTR_DBG_E_ARB_MAX 0xC0320
+
+#define mmMME3_RTR_DBG_W_ARB_MAX 0xC0324
+
+#define mmMME3_RTR_DBG_N_ARB_MAX 0xC0328
+
+#define mmMME3_RTR_DBG_S_ARB_MAX 0xC032C
+
+#define mmMME3_RTR_DBG_L_ARB_MAX 0xC0330
+
+#define mmMME3_RTR_SPLIT_COEF_0 0xC0400
+
+#define mmMME3_RTR_SPLIT_COEF_1 0xC0404
+
+#define mmMME3_RTR_SPLIT_COEF_2 0xC0408
+
+#define mmMME3_RTR_SPLIT_COEF_3 0xC040C
+
+#define mmMME3_RTR_SPLIT_COEF_4 0xC0410
+
+#define mmMME3_RTR_SPLIT_COEF_5 0xC0414
+
+#define mmMME3_RTR_SPLIT_COEF_6 0xC0418
+
+#define mmMME3_RTR_SPLIT_COEF_7 0xC041C
+
+#define mmMME3_RTR_SPLIT_COEF_8 0xC0420
+
+#define mmMME3_RTR_SPLIT_COEF_9 0xC0424
+
+#define mmMME3_RTR_SPLIT_CFG 0xC0440
+
+#define mmMME3_RTR_SPLIT_RD_SAT 0xC0444
+
+#define mmMME3_RTR_SPLIT_RD_RST_TOKEN 0xC0448
+
+#define mmMME3_RTR_SPLIT_RD_TIMEOUT_0 0xC044C
+
+#define mmMME3_RTR_SPLIT_RD_TIMEOUT_1 0xC0450
+
+#define mmMME3_RTR_SPLIT_WR_SAT 0xC0454
+
+#define mmMME3_RTR_WPLIT_WR_TST_TOLEN 0xC0458
+
+#define mmMME3_RTR_SPLIT_WR_TIMEOUT_0 0xC045C
+
+#define mmMME3_RTR_SPLIT_WR_TIMEOUT_1 0xC0460
+
+#define mmMME3_RTR_HBW_RANGE_HIT 0xC0470
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_0 0xC0480
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_1 0xC0484
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_2 0xC0488
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_3 0xC048C
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_4 0xC0490
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_5 0xC0494
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_6 0xC0498
+
+#define mmMME3_RTR_HBW_RANGE_MASK_L_7 0xC049C
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_0 0xC04A0
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_1 0xC04A4
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_2 0xC04A8
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_3 0xC04AC
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_4 0xC04B0
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_5 0xC04B4
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_6 0xC04B8
+
+#define mmMME3_RTR_HBW_RANGE_MASK_H_7 0xC04BC
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_0 0xC04C0
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_1 0xC04C4
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_2 0xC04C8
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_3 0xC04CC
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_4 0xC04D0
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_5 0xC04D4
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_6 0xC04D8
+
+#define mmMME3_RTR_HBW_RANGE_BASE_L_7 0xC04DC
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_0 0xC04E0
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_1 0xC04E4
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_2 0xC04E8
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_3 0xC04EC
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_4 0xC04F0
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_5 0xC04F4
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_6 0xC04F8
+
+#define mmMME3_RTR_HBW_RANGE_BASE_H_7 0xC04FC
+
+#define mmMME3_RTR_LBW_RANGE_HIT 0xC0500
+
+#define mmMME3_RTR_LBW_RANGE_MASK_0 0xC0510
+
+#define mmMME3_RTR_LBW_RANGE_MASK_1 0xC0514
+
+#define mmMME3_RTR_LBW_RANGE_MASK_2 0xC0518
+
+#define mmMME3_RTR_LBW_RANGE_MASK_3 0xC051C
+
+#define mmMME3_RTR_LBW_RANGE_MASK_4 0xC0520
+
+#define mmMME3_RTR_LBW_RANGE_MASK_5 0xC0524
+
+#define mmMME3_RTR_LBW_RANGE_MASK_6 0xC0528
+
+#define mmMME3_RTR_LBW_RANGE_MASK_7 0xC052C
+
+#define mmMME3_RTR_LBW_RANGE_MASK_8 0xC0530
+
+#define mmMME3_RTR_LBW_RANGE_MASK_9 0xC0534
+
+#define mmMME3_RTR_LBW_RANGE_MASK_10 0xC0538
+
+#define mmMME3_RTR_LBW_RANGE_MASK_11 0xC053C
+
+#define mmMME3_RTR_LBW_RANGE_MASK_12 0xC0540
+
+#define mmMME3_RTR_LBW_RANGE_MASK_13 0xC0544
+
+#define mmMME3_RTR_LBW_RANGE_MASK_14 0xC0548
+
+#define mmMME3_RTR_LBW_RANGE_MASK_15 0xC054C
+
+#define mmMME3_RTR_LBW_RANGE_BASE_0 0xC0550
+
+#define mmMME3_RTR_LBW_RANGE_BASE_1 0xC0554
+
+#define mmMME3_RTR_LBW_RANGE_BASE_2 0xC0558
+
+#define mmMME3_RTR_LBW_RANGE_BASE_3 0xC055C
+
+#define mmMME3_RTR_LBW_RANGE_BASE_4 0xC0560
+
+#define mmMME3_RTR_LBW_RANGE_BASE_5 0xC0564
+
+#define mmMME3_RTR_LBW_RANGE_BASE_6 0xC0568
+
+#define mmMME3_RTR_LBW_RANGE_BASE_7 0xC056C
+
+#define mmMME3_RTR_LBW_RANGE_BASE_8 0xC0570
+
+#define mmMME3_RTR_LBW_RANGE_BASE_9 0xC0574
+
+#define mmMME3_RTR_LBW_RANGE_BASE_10 0xC0578
+
+#define mmMME3_RTR_LBW_RANGE_BASE_11 0xC057C
+
+#define mmMME3_RTR_LBW_RANGE_BASE_12 0xC0580
+
+#define mmMME3_RTR_LBW_RANGE_BASE_13 0xC0584
+
+#define mmMME3_RTR_LBW_RANGE_BASE_14 0xC0588
+
+#define mmMME3_RTR_LBW_RANGE_BASE_15 0xC058C
+
+#define mmMME3_RTR_RGLTR 0xC0590
+
+#define mmMME3_RTR_RGLTR_WR_RESULT 0xC0594
+
+#define mmMME3_RTR_RGLTR_RD_RESULT 0xC0598
+
+#define mmMME3_RTR_SCRAMB_EN 0xC0600
+
+#define mmMME3_RTR_NON_LIN_SCRAMB 0xC0604
+
+#endif /* ASIC_REG_MME3_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h
new file mode 100644
index 000000000000..d9a4a02cefa3
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme4_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME4_RTR_REGS_H_
+#define ASIC_REG_MME4_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME4_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME4_RTR_HBW_RD_RQ_E_ARB 0x100100
+
+#define mmMME4_RTR_HBW_RD_RQ_W_ARB 0x100104
+
+#define mmMME4_RTR_HBW_RD_RQ_N_ARB 0x100108
+
+#define mmMME4_RTR_HBW_RD_RQ_S_ARB 0x10010C
+
+#define mmMME4_RTR_HBW_RD_RQ_L_ARB 0x100110
+
+#define mmMME4_RTR_HBW_E_ARB_MAX 0x100120
+
+#define mmMME4_RTR_HBW_W_ARB_MAX 0x100124
+
+#define mmMME4_RTR_HBW_N_ARB_MAX 0x100128
+
+#define mmMME4_RTR_HBW_S_ARB_MAX 0x10012C
+
+#define mmMME4_RTR_HBW_L_ARB_MAX 0x100130
+
+#define mmMME4_RTR_HBW_RD_RS_MAX_CREDIT 0x100140
+
+#define mmMME4_RTR_HBW_WR_RQ_MAX_CREDIT 0x100144
+
+#define mmMME4_RTR_HBW_RD_RQ_MAX_CREDIT 0x100148
+
+#define mmMME4_RTR_HBW_RD_RS_E_ARB 0x100150
+
+#define mmMME4_RTR_HBW_RD_RS_W_ARB 0x100154
+
+#define mmMME4_RTR_HBW_RD_RS_N_ARB 0x100158
+
+#define mmMME4_RTR_HBW_RD_RS_S_ARB 0x10015C
+
+#define mmMME4_RTR_HBW_RD_RS_L_ARB 0x100160
+
+#define mmMME4_RTR_HBW_WR_RQ_E_ARB 0x100170
+
+#define mmMME4_RTR_HBW_WR_RQ_W_ARB 0x100174
+
+#define mmMME4_RTR_HBW_WR_RQ_N_ARB 0x100178
+
+#define mmMME4_RTR_HBW_WR_RQ_S_ARB 0x10017C
+
+#define mmMME4_RTR_HBW_WR_RQ_L_ARB 0x100180
+
+#define mmMME4_RTR_HBW_WR_RS_E_ARB 0x100190
+
+#define mmMME4_RTR_HBW_WR_RS_W_ARB 0x100194
+
+#define mmMME4_RTR_HBW_WR_RS_N_ARB 0x100198
+
+#define mmMME4_RTR_HBW_WR_RS_S_ARB 0x10019C
+
+#define mmMME4_RTR_HBW_WR_RS_L_ARB 0x1001A0
+
+#define mmMME4_RTR_LBW_RD_RQ_E_ARB 0x100200
+
+#define mmMME4_RTR_LBW_RD_RQ_W_ARB 0x100204
+
+#define mmMME4_RTR_LBW_RD_RQ_N_ARB 0x100208
+
+#define mmMME4_RTR_LBW_RD_RQ_S_ARB 0x10020C
+
+#define mmMME4_RTR_LBW_RD_RQ_L_ARB 0x100210
+
+#define mmMME4_RTR_LBW_E_ARB_MAX 0x100220
+
+#define mmMME4_RTR_LBW_W_ARB_MAX 0x100224
+
+#define mmMME4_RTR_LBW_N_ARB_MAX 0x100228
+
+#define mmMME4_RTR_LBW_S_ARB_MAX 0x10022C
+
+#define mmMME4_RTR_LBW_L_ARB_MAX 0x100230
+
+#define mmMME4_RTR_LBW_SRAM_MAX_CREDIT 0x100240
+
+#define mmMME4_RTR_LBW_RD_RS_E_ARB 0x100250
+
+#define mmMME4_RTR_LBW_RD_RS_W_ARB 0x100254
+
+#define mmMME4_RTR_LBW_RD_RS_N_ARB 0x100258
+
+#define mmMME4_RTR_LBW_RD_RS_S_ARB 0x10025C
+
+#define mmMME4_RTR_LBW_RD_RS_L_ARB 0x100260
+
+#define mmMME4_RTR_LBW_WR_RQ_E_ARB 0x100270
+
+#define mmMME4_RTR_LBW_WR_RQ_W_ARB 0x100274
+
+#define mmMME4_RTR_LBW_WR_RQ_N_ARB 0x100278
+
+#define mmMME4_RTR_LBW_WR_RQ_S_ARB 0x10027C
+
+#define mmMME4_RTR_LBW_WR_RQ_L_ARB 0x100280
+
+#define mmMME4_RTR_LBW_WR_RS_E_ARB 0x100290
+
+#define mmMME4_RTR_LBW_WR_RS_W_ARB 0x100294
+
+#define mmMME4_RTR_LBW_WR_RS_N_ARB 0x100298
+
+#define mmMME4_RTR_LBW_WR_RS_S_ARB 0x10029C
+
+#define mmMME4_RTR_LBW_WR_RS_L_ARB 0x1002A0
+
+#define mmMME4_RTR_DBG_E_ARB 0x100300
+
+#define mmMME4_RTR_DBG_W_ARB 0x100304
+
+#define mmMME4_RTR_DBG_N_ARB 0x100308
+
+#define mmMME4_RTR_DBG_S_ARB 0x10030C
+
+#define mmMME4_RTR_DBG_L_ARB 0x100310
+
+#define mmMME4_RTR_DBG_E_ARB_MAX 0x100320
+
+#define mmMME4_RTR_DBG_W_ARB_MAX 0x100324
+
+#define mmMME4_RTR_DBG_N_ARB_MAX 0x100328
+
+#define mmMME4_RTR_DBG_S_ARB_MAX 0x10032C
+
+#define mmMME4_RTR_DBG_L_ARB_MAX 0x100330
+
+#define mmMME4_RTR_SPLIT_COEF_0 0x100400
+
+#define mmMME4_RTR_SPLIT_COEF_1 0x100404
+
+#define mmMME4_RTR_SPLIT_COEF_2 0x100408
+
+#define mmMME4_RTR_SPLIT_COEF_3 0x10040C
+
+#define mmMME4_RTR_SPLIT_COEF_4 0x100410
+
+#define mmMME4_RTR_SPLIT_COEF_5 0x100414
+
+#define mmMME4_RTR_SPLIT_COEF_6 0x100418
+
+#define mmMME4_RTR_SPLIT_COEF_7 0x10041C
+
+#define mmMME4_RTR_SPLIT_COEF_8 0x100420
+
+#define mmMME4_RTR_SPLIT_COEF_9 0x100424
+
+#define mmMME4_RTR_SPLIT_CFG 0x100440
+
+#define mmMME4_RTR_SPLIT_RD_SAT 0x100444
+
+#define mmMME4_RTR_SPLIT_RD_RST_TOKEN 0x100448
+
+#define mmMME4_RTR_SPLIT_RD_TIMEOUT_0 0x10044C
+
+#define mmMME4_RTR_SPLIT_RD_TIMEOUT_1 0x100450
+
+#define mmMME4_RTR_SPLIT_WR_SAT 0x100454
+
+#define mmMME4_RTR_WPLIT_WR_TST_TOLEN 0x100458
+
+#define mmMME4_RTR_SPLIT_WR_TIMEOUT_0 0x10045C
+
+#define mmMME4_RTR_SPLIT_WR_TIMEOUT_1 0x100460
+
+#define mmMME4_RTR_HBW_RANGE_HIT 0x100470
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_0 0x100480
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_1 0x100484
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_2 0x100488
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_3 0x10048C
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_4 0x100490
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_5 0x100494
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_6 0x100498
+
+#define mmMME4_RTR_HBW_RANGE_MASK_L_7 0x10049C
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_0 0x1004A0
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_1 0x1004A4
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_2 0x1004A8
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_3 0x1004AC
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_4 0x1004B0
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_5 0x1004B4
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_6 0x1004B8
+
+#define mmMME4_RTR_HBW_RANGE_MASK_H_7 0x1004BC
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_0 0x1004C0
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_1 0x1004C4
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_2 0x1004C8
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_3 0x1004CC
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_4 0x1004D0
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_5 0x1004D4
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_6 0x1004D8
+
+#define mmMME4_RTR_HBW_RANGE_BASE_L_7 0x1004DC
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_0 0x1004E0
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_1 0x1004E4
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_2 0x1004E8
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_3 0x1004EC
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_4 0x1004F0
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_5 0x1004F4
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_6 0x1004F8
+
+#define mmMME4_RTR_HBW_RANGE_BASE_H_7 0x1004FC
+
+#define mmMME4_RTR_LBW_RANGE_HIT 0x100500
+
+#define mmMME4_RTR_LBW_RANGE_MASK_0 0x100510
+
+#define mmMME4_RTR_LBW_RANGE_MASK_1 0x100514
+
+#define mmMME4_RTR_LBW_RANGE_MASK_2 0x100518
+
+#define mmMME4_RTR_LBW_RANGE_MASK_3 0x10051C
+
+#define mmMME4_RTR_LBW_RANGE_MASK_4 0x100520
+
+#define mmMME4_RTR_LBW_RANGE_MASK_5 0x100524
+
+#define mmMME4_RTR_LBW_RANGE_MASK_6 0x100528
+
+#define mmMME4_RTR_LBW_RANGE_MASK_7 0x10052C
+
+#define mmMME4_RTR_LBW_RANGE_MASK_8 0x100530
+
+#define mmMME4_RTR_LBW_RANGE_MASK_9 0x100534
+
+#define mmMME4_RTR_LBW_RANGE_MASK_10 0x100538
+
+#define mmMME4_RTR_LBW_RANGE_MASK_11 0x10053C
+
+#define mmMME4_RTR_LBW_RANGE_MASK_12 0x100540
+
+#define mmMME4_RTR_LBW_RANGE_MASK_13 0x100544
+
+#define mmMME4_RTR_LBW_RANGE_MASK_14 0x100548
+
+#define mmMME4_RTR_LBW_RANGE_MASK_15 0x10054C
+
+#define mmMME4_RTR_LBW_RANGE_BASE_0 0x100550
+
+#define mmMME4_RTR_LBW_RANGE_BASE_1 0x100554
+
+#define mmMME4_RTR_LBW_RANGE_BASE_2 0x100558
+
+#define mmMME4_RTR_LBW_RANGE_BASE_3 0x10055C
+
+#define mmMME4_RTR_LBW_RANGE_BASE_4 0x100560
+
+#define mmMME4_RTR_LBW_RANGE_BASE_5 0x100564
+
+#define mmMME4_RTR_LBW_RANGE_BASE_6 0x100568
+
+#define mmMME4_RTR_LBW_RANGE_BASE_7 0x10056C
+
+#define mmMME4_RTR_LBW_RANGE_BASE_8 0x100570
+
+#define mmMME4_RTR_LBW_RANGE_BASE_9 0x100574
+
+#define mmMME4_RTR_LBW_RANGE_BASE_10 0x100578
+
+#define mmMME4_RTR_LBW_RANGE_BASE_11 0x10057C
+
+#define mmMME4_RTR_LBW_RANGE_BASE_12 0x100580
+
+#define mmMME4_RTR_LBW_RANGE_BASE_13 0x100584
+
+#define mmMME4_RTR_LBW_RANGE_BASE_14 0x100588
+
+#define mmMME4_RTR_LBW_RANGE_BASE_15 0x10058C
+
+#define mmMME4_RTR_RGLTR 0x100590
+
+#define mmMME4_RTR_RGLTR_WR_RESULT 0x100594
+
+#define mmMME4_RTR_RGLTR_RD_RESULT 0x100598
+
+#define mmMME4_RTR_SCRAMB_EN 0x100600
+
+#define mmMME4_RTR_NON_LIN_SCRAMB 0x100604
+
+#endif /* ASIC_REG_MME4_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h
new file mode 100644
index 000000000000..205adc988407
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme5_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME5_RTR_REGS_H_
+#define ASIC_REG_MME5_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME5_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME5_RTR_HBW_RD_RQ_E_ARB 0x140100
+
+#define mmMME5_RTR_HBW_RD_RQ_W_ARB 0x140104
+
+#define mmMME5_RTR_HBW_RD_RQ_N_ARB 0x140108
+
+#define mmMME5_RTR_HBW_RD_RQ_S_ARB 0x14010C
+
+#define mmMME5_RTR_HBW_RD_RQ_L_ARB 0x140110
+
+#define mmMME5_RTR_HBW_E_ARB_MAX 0x140120
+
+#define mmMME5_RTR_HBW_W_ARB_MAX 0x140124
+
+#define mmMME5_RTR_HBW_N_ARB_MAX 0x140128
+
+#define mmMME5_RTR_HBW_S_ARB_MAX 0x14012C
+
+#define mmMME5_RTR_HBW_L_ARB_MAX 0x140130
+
+#define mmMME5_RTR_HBW_RD_RS_MAX_CREDIT 0x140140
+
+#define mmMME5_RTR_HBW_WR_RQ_MAX_CREDIT 0x140144
+
+#define mmMME5_RTR_HBW_RD_RQ_MAX_CREDIT 0x140148
+
+#define mmMME5_RTR_HBW_RD_RS_E_ARB 0x140150
+
+#define mmMME5_RTR_HBW_RD_RS_W_ARB 0x140154
+
+#define mmMME5_RTR_HBW_RD_RS_N_ARB 0x140158
+
+#define mmMME5_RTR_HBW_RD_RS_S_ARB 0x14015C
+
+#define mmMME5_RTR_HBW_RD_RS_L_ARB 0x140160
+
+#define mmMME5_RTR_HBW_WR_RQ_E_ARB 0x140170
+
+#define mmMME5_RTR_HBW_WR_RQ_W_ARB 0x140174
+
+#define mmMME5_RTR_HBW_WR_RQ_N_ARB 0x140178
+
+#define mmMME5_RTR_HBW_WR_RQ_S_ARB 0x14017C
+
+#define mmMME5_RTR_HBW_WR_RQ_L_ARB 0x140180
+
+#define mmMME5_RTR_HBW_WR_RS_E_ARB 0x140190
+
+#define mmMME5_RTR_HBW_WR_RS_W_ARB 0x140194
+
+#define mmMME5_RTR_HBW_WR_RS_N_ARB 0x140198
+
+#define mmMME5_RTR_HBW_WR_RS_S_ARB 0x14019C
+
+#define mmMME5_RTR_HBW_WR_RS_L_ARB 0x1401A0
+
+#define mmMME5_RTR_LBW_RD_RQ_E_ARB 0x140200
+
+#define mmMME5_RTR_LBW_RD_RQ_W_ARB 0x140204
+
+#define mmMME5_RTR_LBW_RD_RQ_N_ARB 0x140208
+
+#define mmMME5_RTR_LBW_RD_RQ_S_ARB 0x14020C
+
+#define mmMME5_RTR_LBW_RD_RQ_L_ARB 0x140210
+
+#define mmMME5_RTR_LBW_E_ARB_MAX 0x140220
+
+#define mmMME5_RTR_LBW_W_ARB_MAX 0x140224
+
+#define mmMME5_RTR_LBW_N_ARB_MAX 0x140228
+
+#define mmMME5_RTR_LBW_S_ARB_MAX 0x14022C
+
+#define mmMME5_RTR_LBW_L_ARB_MAX 0x140230
+
+#define mmMME5_RTR_LBW_SRAM_MAX_CREDIT 0x140240
+
+#define mmMME5_RTR_LBW_RD_RS_E_ARB 0x140250
+
+#define mmMME5_RTR_LBW_RD_RS_W_ARB 0x140254
+
+#define mmMME5_RTR_LBW_RD_RS_N_ARB 0x140258
+
+#define mmMME5_RTR_LBW_RD_RS_S_ARB 0x14025C
+
+#define mmMME5_RTR_LBW_RD_RS_L_ARB 0x140260
+
+#define mmMME5_RTR_LBW_WR_RQ_E_ARB 0x140270
+
+#define mmMME5_RTR_LBW_WR_RQ_W_ARB 0x140274
+
+#define mmMME5_RTR_LBW_WR_RQ_N_ARB 0x140278
+
+#define mmMME5_RTR_LBW_WR_RQ_S_ARB 0x14027C
+
+#define mmMME5_RTR_LBW_WR_RQ_L_ARB 0x140280
+
+#define mmMME5_RTR_LBW_WR_RS_E_ARB 0x140290
+
+#define mmMME5_RTR_LBW_WR_RS_W_ARB 0x140294
+
+#define mmMME5_RTR_LBW_WR_RS_N_ARB 0x140298
+
+#define mmMME5_RTR_LBW_WR_RS_S_ARB 0x14029C
+
+#define mmMME5_RTR_LBW_WR_RS_L_ARB 0x1402A0
+
+#define mmMME5_RTR_DBG_E_ARB 0x140300
+
+#define mmMME5_RTR_DBG_W_ARB 0x140304
+
+#define mmMME5_RTR_DBG_N_ARB 0x140308
+
+#define mmMME5_RTR_DBG_S_ARB 0x14030C
+
+#define mmMME5_RTR_DBG_L_ARB 0x140310
+
+#define mmMME5_RTR_DBG_E_ARB_MAX 0x140320
+
+#define mmMME5_RTR_DBG_W_ARB_MAX 0x140324
+
+#define mmMME5_RTR_DBG_N_ARB_MAX 0x140328
+
+#define mmMME5_RTR_DBG_S_ARB_MAX 0x14032C
+
+#define mmMME5_RTR_DBG_L_ARB_MAX 0x140330
+
+#define mmMME5_RTR_SPLIT_COEF_0 0x140400
+
+#define mmMME5_RTR_SPLIT_COEF_1 0x140404
+
+#define mmMME5_RTR_SPLIT_COEF_2 0x140408
+
+#define mmMME5_RTR_SPLIT_COEF_3 0x14040C
+
+#define mmMME5_RTR_SPLIT_COEF_4 0x140410
+
+#define mmMME5_RTR_SPLIT_COEF_5 0x140414
+
+#define mmMME5_RTR_SPLIT_COEF_6 0x140418
+
+#define mmMME5_RTR_SPLIT_COEF_7 0x14041C
+
+#define mmMME5_RTR_SPLIT_COEF_8 0x140420
+
+#define mmMME5_RTR_SPLIT_COEF_9 0x140424
+
+#define mmMME5_RTR_SPLIT_CFG 0x140440
+
+#define mmMME5_RTR_SPLIT_RD_SAT 0x140444
+
+#define mmMME5_RTR_SPLIT_RD_RST_TOKEN 0x140448
+
+#define mmMME5_RTR_SPLIT_RD_TIMEOUT_0 0x14044C
+
+#define mmMME5_RTR_SPLIT_RD_TIMEOUT_1 0x140450
+
+#define mmMME5_RTR_SPLIT_WR_SAT 0x140454
+
+#define mmMME5_RTR_WPLIT_WR_TST_TOLEN 0x140458
+
+#define mmMME5_RTR_SPLIT_WR_TIMEOUT_0 0x14045C
+
+#define mmMME5_RTR_SPLIT_WR_TIMEOUT_1 0x140460
+
+#define mmMME5_RTR_HBW_RANGE_HIT 0x140470
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_0 0x140480
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_1 0x140484
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_2 0x140488
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_3 0x14048C
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_4 0x140490
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_5 0x140494
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_6 0x140498
+
+#define mmMME5_RTR_HBW_RANGE_MASK_L_7 0x14049C
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_0 0x1404A0
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_1 0x1404A4
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_2 0x1404A8
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_3 0x1404AC
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_4 0x1404B0
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_5 0x1404B4
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_6 0x1404B8
+
+#define mmMME5_RTR_HBW_RANGE_MASK_H_7 0x1404BC
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_0 0x1404C0
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_1 0x1404C4
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_2 0x1404C8
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_3 0x1404CC
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_4 0x1404D0
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_5 0x1404D4
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_6 0x1404D8
+
+#define mmMME5_RTR_HBW_RANGE_BASE_L_7 0x1404DC
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_0 0x1404E0
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_1 0x1404E4
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_2 0x1404E8
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_3 0x1404EC
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_4 0x1404F0
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_5 0x1404F4
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_6 0x1404F8
+
+#define mmMME5_RTR_HBW_RANGE_BASE_H_7 0x1404FC
+
+#define mmMME5_RTR_LBW_RANGE_HIT 0x140500
+
+#define mmMME5_RTR_LBW_RANGE_MASK_0 0x140510
+
+#define mmMME5_RTR_LBW_RANGE_MASK_1 0x140514
+
+#define mmMME5_RTR_LBW_RANGE_MASK_2 0x140518
+
+#define mmMME5_RTR_LBW_RANGE_MASK_3 0x14051C
+
+#define mmMME5_RTR_LBW_RANGE_MASK_4 0x140520
+
+#define mmMME5_RTR_LBW_RANGE_MASK_5 0x140524
+
+#define mmMME5_RTR_LBW_RANGE_MASK_6 0x140528
+
+#define mmMME5_RTR_LBW_RANGE_MASK_7 0x14052C
+
+#define mmMME5_RTR_LBW_RANGE_MASK_8 0x140530
+
+#define mmMME5_RTR_LBW_RANGE_MASK_9 0x140534
+
+#define mmMME5_RTR_LBW_RANGE_MASK_10 0x140538
+
+#define mmMME5_RTR_LBW_RANGE_MASK_11 0x14053C
+
+#define mmMME5_RTR_LBW_RANGE_MASK_12 0x140540
+
+#define mmMME5_RTR_LBW_RANGE_MASK_13 0x140544
+
+#define mmMME5_RTR_LBW_RANGE_MASK_14 0x140548
+
+#define mmMME5_RTR_LBW_RANGE_MASK_15 0x14054C
+
+#define mmMME5_RTR_LBW_RANGE_BASE_0 0x140550
+
+#define mmMME5_RTR_LBW_RANGE_BASE_1 0x140554
+
+#define mmMME5_RTR_LBW_RANGE_BASE_2 0x140558
+
+#define mmMME5_RTR_LBW_RANGE_BASE_3 0x14055C
+
+#define mmMME5_RTR_LBW_RANGE_BASE_4 0x140560
+
+#define mmMME5_RTR_LBW_RANGE_BASE_5 0x140564
+
+#define mmMME5_RTR_LBW_RANGE_BASE_6 0x140568
+
+#define mmMME5_RTR_LBW_RANGE_BASE_7 0x14056C
+
+#define mmMME5_RTR_LBW_RANGE_BASE_8 0x140570
+
+#define mmMME5_RTR_LBW_RANGE_BASE_9 0x140574
+
+#define mmMME5_RTR_LBW_RANGE_BASE_10 0x140578
+
+#define mmMME5_RTR_LBW_RANGE_BASE_11 0x14057C
+
+#define mmMME5_RTR_LBW_RANGE_BASE_12 0x140580
+
+#define mmMME5_RTR_LBW_RANGE_BASE_13 0x140584
+
+#define mmMME5_RTR_LBW_RANGE_BASE_14 0x140588
+
+#define mmMME5_RTR_LBW_RANGE_BASE_15 0x14058C
+
+#define mmMME5_RTR_RGLTR 0x140590
+
+#define mmMME5_RTR_RGLTR_WR_RESULT 0x140594
+
+#define mmMME5_RTR_RGLTR_RD_RESULT 0x140598
+
+#define mmMME5_RTR_SCRAMB_EN 0x140600
+
+#define mmMME5_RTR_NON_LIN_SCRAMB 0x140604
+
+#endif /* ASIC_REG_MME5_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h
new file mode 100644
index 000000000000..fcec68388278
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme6_rtr_regs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME6_RTR_REGS_H_
+#define ASIC_REG_MME6_RTR_REGS_H_
+
+/*
+ *****************************************
+ * MME6_RTR (Prototype: MME_RTR)
+ *****************************************
+ */
+
+#define mmMME6_RTR_HBW_RD_RQ_E_ARB 0x180100
+
+#define mmMME6_RTR_HBW_RD_RQ_W_ARB 0x180104
+
+#define mmMME6_RTR_HBW_RD_RQ_N_ARB 0x180108
+
+#define mmMME6_RTR_HBW_RD_RQ_S_ARB 0x18010C
+
+#define mmMME6_RTR_HBW_RD_RQ_L_ARB 0x180110
+
+#define mmMME6_RTR_HBW_E_ARB_MAX 0x180120
+
+#define mmMME6_RTR_HBW_W_ARB_MAX 0x180124
+
+#define mmMME6_RTR_HBW_N_ARB_MAX 0x180128
+
+#define mmMME6_RTR_HBW_S_ARB_MAX 0x18012C
+
+#define mmMME6_RTR_HBW_L_ARB_MAX 0x180130
+
+#define mmMME6_RTR_HBW_RD_RS_MAX_CREDIT 0x180140
+
+#define mmMME6_RTR_HBW_WR_RQ_MAX_CREDIT 0x180144
+
+#define mmMME6_RTR_HBW_RD_RQ_MAX_CREDIT 0x180148
+
+#define mmMME6_RTR_HBW_RD_RS_E_ARB 0x180150
+
+#define mmMME6_RTR_HBW_RD_RS_W_ARB 0x180154
+
+#define mmMME6_RTR_HBW_RD_RS_N_ARB 0x180158
+
+#define mmMME6_RTR_HBW_RD_RS_S_ARB 0x18015C
+
+#define mmMME6_RTR_HBW_RD_RS_L_ARB 0x180160
+
+#define mmMME6_RTR_HBW_WR_RQ_E_ARB 0x180170
+
+#define mmMME6_RTR_HBW_WR_RQ_W_ARB 0x180174
+
+#define mmMME6_RTR_HBW_WR_RQ_N_ARB 0x180178
+
+#define mmMME6_RTR_HBW_WR_RQ_S_ARB 0x18017C
+
+#define mmMME6_RTR_HBW_WR_RQ_L_ARB 0x180180
+
+#define mmMME6_RTR_HBW_WR_RS_E_ARB 0x180190
+
+#define mmMME6_RTR_HBW_WR_RS_W_ARB 0x180194
+
+#define mmMME6_RTR_HBW_WR_RS_N_ARB 0x180198
+
+#define mmMME6_RTR_HBW_WR_RS_S_ARB 0x18019C
+
+#define mmMME6_RTR_HBW_WR_RS_L_ARB 0x1801A0
+
+#define mmMME6_RTR_LBW_RD_RQ_E_ARB 0x180200
+
+#define mmMME6_RTR_LBW_RD_RQ_W_ARB 0x180204
+
+#define mmMME6_RTR_LBW_RD_RQ_N_ARB 0x180208
+
+#define mmMME6_RTR_LBW_RD_RQ_S_ARB 0x18020C
+
+#define mmMME6_RTR_LBW_RD_RQ_L_ARB 0x180210
+
+#define mmMME6_RTR_LBW_E_ARB_MAX 0x180220
+
+#define mmMME6_RTR_LBW_W_ARB_MAX 0x180224
+
+#define mmMME6_RTR_LBW_N_ARB_MAX 0x180228
+
+#define mmMME6_RTR_LBW_S_ARB_MAX 0x18022C
+
+#define mmMME6_RTR_LBW_L_ARB_MAX 0x180230
+
+#define mmMME6_RTR_LBW_SRAM_MAX_CREDIT 0x180240
+
+#define mmMME6_RTR_LBW_RD_RS_E_ARB 0x180250
+
+#define mmMME6_RTR_LBW_RD_RS_W_ARB 0x180254
+
+#define mmMME6_RTR_LBW_RD_RS_N_ARB 0x180258
+
+#define mmMME6_RTR_LBW_RD_RS_S_ARB 0x18025C
+
+#define mmMME6_RTR_LBW_RD_RS_L_ARB 0x180260
+
+#define mmMME6_RTR_LBW_WR_RQ_E_ARB 0x180270
+
+#define mmMME6_RTR_LBW_WR_RQ_W_ARB 0x180274
+
+#define mmMME6_RTR_LBW_WR_RQ_N_ARB 0x180278
+
+#define mmMME6_RTR_LBW_WR_RQ_S_ARB 0x18027C
+
+#define mmMME6_RTR_LBW_WR_RQ_L_ARB 0x180280
+
+#define mmMME6_RTR_LBW_WR_RS_E_ARB 0x180290
+
+#define mmMME6_RTR_LBW_WR_RS_W_ARB 0x180294
+
+#define mmMME6_RTR_LBW_WR_RS_N_ARB 0x180298
+
+#define mmMME6_RTR_LBW_WR_RS_S_ARB 0x18029C
+
+#define mmMME6_RTR_LBW_WR_RS_L_ARB 0x1802A0
+
+#define mmMME6_RTR_DBG_E_ARB 0x180300
+
+#define mmMME6_RTR_DBG_W_ARB 0x180304
+
+#define mmMME6_RTR_DBG_N_ARB 0x180308
+
+#define mmMME6_RTR_DBG_S_ARB 0x18030C
+
+#define mmMME6_RTR_DBG_L_ARB 0x180310
+
+#define mmMME6_RTR_DBG_E_ARB_MAX 0x180320
+
+#define mmMME6_RTR_DBG_W_ARB_MAX 0x180324
+
+#define mmMME6_RTR_DBG_N_ARB_MAX 0x180328
+
+#define mmMME6_RTR_DBG_S_ARB_MAX 0x18032C
+
+#define mmMME6_RTR_DBG_L_ARB_MAX 0x180330
+
+#define mmMME6_RTR_SPLIT_COEF_0 0x180400
+
+#define mmMME6_RTR_SPLIT_COEF_1 0x180404
+
+#define mmMME6_RTR_SPLIT_COEF_2 0x180408
+
+#define mmMME6_RTR_SPLIT_COEF_3 0x18040C
+
+#define mmMME6_RTR_SPLIT_COEF_4 0x180410
+
+#define mmMME6_RTR_SPLIT_COEF_5 0x180414
+
+#define mmMME6_RTR_SPLIT_COEF_6 0x180418
+
+#define mmMME6_RTR_SPLIT_COEF_7 0x18041C
+
+#define mmMME6_RTR_SPLIT_COEF_8 0x180420
+
+#define mmMME6_RTR_SPLIT_COEF_9 0x180424
+
+#define mmMME6_RTR_SPLIT_CFG 0x180440
+
+#define mmMME6_RTR_SPLIT_RD_SAT 0x180444
+
+#define mmMME6_RTR_SPLIT_RD_RST_TOKEN 0x180448
+
+#define mmMME6_RTR_SPLIT_RD_TIMEOUT_0 0x18044C
+
+#define mmMME6_RTR_SPLIT_RD_TIMEOUT_1 0x180450
+
+#define mmMME6_RTR_SPLIT_WR_SAT 0x180454
+
+#define mmMME6_RTR_WPLIT_WR_TST_TOLEN 0x180458
+
+#define mmMME6_RTR_SPLIT_WR_TIMEOUT_0 0x18045C
+
+#define mmMME6_RTR_SPLIT_WR_TIMEOUT_1 0x180460
+
+#define mmMME6_RTR_HBW_RANGE_HIT 0x180470
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_0 0x180480
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_1 0x180484
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_2 0x180488
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_3 0x18048C
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_4 0x180490
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_5 0x180494
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_6 0x180498
+
+#define mmMME6_RTR_HBW_RANGE_MASK_L_7 0x18049C
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_0 0x1804A0
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_1 0x1804A4
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_2 0x1804A8
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_3 0x1804AC
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_4 0x1804B0
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_5 0x1804B4
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_6 0x1804B8
+
+#define mmMME6_RTR_HBW_RANGE_MASK_H_7 0x1804BC
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_0 0x1804C0
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_1 0x1804C4
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_2 0x1804C8
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_3 0x1804CC
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_4 0x1804D0
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_5 0x1804D4
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_6 0x1804D8
+
+#define mmMME6_RTR_HBW_RANGE_BASE_L_7 0x1804DC
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_0 0x1804E0
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_1 0x1804E4
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_2 0x1804E8
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_3 0x1804EC
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_4 0x1804F0
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_5 0x1804F4
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_6 0x1804F8
+
+#define mmMME6_RTR_HBW_RANGE_BASE_H_7 0x1804FC
+
+#define mmMME6_RTR_LBW_RANGE_HIT 0x180500
+
+#define mmMME6_RTR_LBW_RANGE_MASK_0 0x180510
+
+#define mmMME6_RTR_LBW_RANGE_MASK_1 0x180514
+
+#define mmMME6_RTR_LBW_RANGE_MASK_2 0x180518
+
+#define mmMME6_RTR_LBW_RANGE_MASK_3 0x18051C
+
+#define mmMME6_RTR_LBW_RANGE_MASK_4 0x180520
+
+#define mmMME6_RTR_LBW_RANGE_MASK_5 0x180524
+
+#define mmMME6_RTR_LBW_RANGE_MASK_6 0x180528
+
+#define mmMME6_RTR_LBW_RANGE_MASK_7 0x18052C
+
+#define mmMME6_RTR_LBW_RANGE_MASK_8 0x180530
+
+#define mmMME6_RTR_LBW_RANGE_MASK_9 0x180534
+
+#define mmMME6_RTR_LBW_RANGE_MASK_10 0x180538
+
+#define mmMME6_RTR_LBW_RANGE_MASK_11 0x18053C
+
+#define mmMME6_RTR_LBW_RANGE_MASK_12 0x180540
+
+#define mmMME6_RTR_LBW_RANGE_MASK_13 0x180544
+
+#define mmMME6_RTR_LBW_RANGE_MASK_14 0x180548
+
+#define mmMME6_RTR_LBW_RANGE_MASK_15 0x18054C
+
+#define mmMME6_RTR_LBW_RANGE_BASE_0 0x180550
+
+#define mmMME6_RTR_LBW_RANGE_BASE_1 0x180554
+
+#define mmMME6_RTR_LBW_RANGE_BASE_2 0x180558
+
+#define mmMME6_RTR_LBW_RANGE_BASE_3 0x18055C
+
+#define mmMME6_RTR_LBW_RANGE_BASE_4 0x180560
+
+#define mmMME6_RTR_LBW_RANGE_BASE_5 0x180564
+
+#define mmMME6_RTR_LBW_RANGE_BASE_6 0x180568
+
+#define mmMME6_RTR_LBW_RANGE_BASE_7 0x18056C
+
+#define mmMME6_RTR_LBW_RANGE_BASE_8 0x180570
+
+#define mmMME6_RTR_LBW_RANGE_BASE_9 0x180574
+
+#define mmMME6_RTR_LBW_RANGE_BASE_10 0x180578
+
+#define mmMME6_RTR_LBW_RANGE_BASE_11 0x18057C
+
+#define mmMME6_RTR_LBW_RANGE_BASE_12 0x180580
+
+#define mmMME6_RTR_LBW_RANGE_BASE_13 0x180584
+
+#define mmMME6_RTR_LBW_RANGE_BASE_14 0x180588
+
+#define mmMME6_RTR_LBW_RANGE_BASE_15 0x18058C
+
+#define mmMME6_RTR_RGLTR 0x180590
+
+#define mmMME6_RTR_RGLTR_WR_RESULT 0x180594
+
+#define mmMME6_RTR_RGLTR_RD_RESULT 0x180598
+
+#define mmMME6_RTR_SCRAMB_EN 0x180600
+
+#define mmMME6_RTR_NON_LIN_SCRAMB 0x180604
+
+#endif /* ASIC_REG_MME6_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h
new file mode 100644
index 000000000000..a0d4382fbbd0
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_masks.h
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_CMDQ_MASKS_H_
+#define ASIC_REG_MME_CMDQ_MASKS_H_
+
+/*
+ *****************************************
+ * MME_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+/* MME_CMDQ_GLBL_CFG0 */
+#define MME_CMDQ_GLBL_CFG0_PQF_EN_SHIFT 0
+#define MME_CMDQ_GLBL_CFG0_PQF_EN_MASK 0x1
+#define MME_CMDQ_GLBL_CFG0_CQF_EN_SHIFT 1
+#define MME_CMDQ_GLBL_CFG0_CQF_EN_MASK 0x2
+#define MME_CMDQ_GLBL_CFG0_CP_EN_SHIFT 2
+#define MME_CMDQ_GLBL_CFG0_CP_EN_MASK 0x4
+#define MME_CMDQ_GLBL_CFG0_DMA_EN_SHIFT 3
+#define MME_CMDQ_GLBL_CFG0_DMA_EN_MASK 0x8
+
+/* MME_CMDQ_GLBL_CFG1 */
+#define MME_CMDQ_GLBL_CFG1_PQF_STOP_SHIFT 0
+#define MME_CMDQ_GLBL_CFG1_PQF_STOP_MASK 0x1
+#define MME_CMDQ_GLBL_CFG1_CQF_STOP_SHIFT 1
+#define MME_CMDQ_GLBL_CFG1_CQF_STOP_MASK 0x2
+#define MME_CMDQ_GLBL_CFG1_CP_STOP_SHIFT 2
+#define MME_CMDQ_GLBL_CFG1_CP_STOP_MASK 0x4
+#define MME_CMDQ_GLBL_CFG1_DMA_STOP_SHIFT 3
+#define MME_CMDQ_GLBL_CFG1_DMA_STOP_MASK 0x8
+#define MME_CMDQ_GLBL_CFG1_PQF_FLUSH_SHIFT 8
+#define MME_CMDQ_GLBL_CFG1_PQF_FLUSH_MASK 0x100
+#define MME_CMDQ_GLBL_CFG1_CQF_FLUSH_SHIFT 9
+#define MME_CMDQ_GLBL_CFG1_CQF_FLUSH_MASK 0x200
+#define MME_CMDQ_GLBL_CFG1_CP_FLUSH_SHIFT 10
+#define MME_CMDQ_GLBL_CFG1_CP_FLUSH_MASK 0x400
+#define MME_CMDQ_GLBL_CFG1_DMA_FLUSH_SHIFT 11
+#define MME_CMDQ_GLBL_CFG1_DMA_FLUSH_MASK 0x800
+
+/* MME_CMDQ_GLBL_PROT */
+#define MME_CMDQ_GLBL_PROT_PQF_PROT_SHIFT 0
+#define MME_CMDQ_GLBL_PROT_PQF_PROT_MASK 0x1
+#define MME_CMDQ_GLBL_PROT_CQF_PROT_SHIFT 1
+#define MME_CMDQ_GLBL_PROT_CQF_PROT_MASK 0x2
+#define MME_CMDQ_GLBL_PROT_CP_PROT_SHIFT 2
+#define MME_CMDQ_GLBL_PROT_CP_PROT_MASK 0x4
+#define MME_CMDQ_GLBL_PROT_DMA_PROT_SHIFT 3
+#define MME_CMDQ_GLBL_PROT_DMA_PROT_MASK 0x8
+#define MME_CMDQ_GLBL_PROT_PQF_ERR_PROT_SHIFT 4
+#define MME_CMDQ_GLBL_PROT_PQF_ERR_PROT_MASK 0x10
+#define MME_CMDQ_GLBL_PROT_CQF_ERR_PROT_SHIFT 5
+#define MME_CMDQ_GLBL_PROT_CQF_ERR_PROT_MASK 0x20
+#define MME_CMDQ_GLBL_PROT_CP_ERR_PROT_SHIFT 6
+#define MME_CMDQ_GLBL_PROT_CP_ERR_PROT_MASK 0x40
+#define MME_CMDQ_GLBL_PROT_DMA_ERR_PROT_SHIFT 7
+#define MME_CMDQ_GLBL_PROT_DMA_ERR_PROT_MASK 0x80
+
+/* MME_CMDQ_GLBL_ERR_CFG */
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_ERR_INT_EN_SHIFT 0
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_ERR_INT_EN_MASK 0x1
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT 1
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK 0x2
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT 2
+#define MME_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK 0x4
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_ERR_INT_EN_SHIFT 3
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_ERR_INT_EN_MASK 0x8
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT 4
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_MASK 0x10
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT 5
+#define MME_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK 0x20
+#define MME_CMDQ_GLBL_ERR_CFG_CP_ERR_INT_EN_SHIFT 6
+#define MME_CMDQ_GLBL_ERR_CFG_CP_ERR_INT_EN_MASK 0x40
+#define MME_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT 7
+#define MME_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_MASK 0x80
+#define MME_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT 8
+#define MME_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK 0x100
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_ERR_INT_EN_SHIFT 9
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_ERR_INT_EN_MASK 0x200
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT 10
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_MASK 0x400
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT 11
+#define MME_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_MASK 0x800
+
+/* MME_CMDQ_GLBL_ERR_ADDR_LO */
+#define MME_CMDQ_GLBL_ERR_ADDR_LO_VAL_SHIFT 0
+#define MME_CMDQ_GLBL_ERR_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_GLBL_ERR_ADDR_HI */
+#define MME_CMDQ_GLBL_ERR_ADDR_HI_VAL_SHIFT 0
+#define MME_CMDQ_GLBL_ERR_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_GLBL_ERR_WDATA */
+#define MME_CMDQ_GLBL_ERR_WDATA_VAL_SHIFT 0
+#define MME_CMDQ_GLBL_ERR_WDATA_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_GLBL_SECURE_PROPS */
+#define MME_CMDQ_GLBL_SECURE_PROPS_ASID_SHIFT 0
+#define MME_CMDQ_GLBL_SECURE_PROPS_ASID_MASK 0x3FF
+#define MME_CMDQ_GLBL_SECURE_PROPS_MMBP_SHIFT 10
+#define MME_CMDQ_GLBL_SECURE_PROPS_MMBP_MASK 0x400
+
+/* MME_CMDQ_GLBL_NON_SECURE_PROPS */
+#define MME_CMDQ_GLBL_NON_SECURE_PROPS_ASID_SHIFT 0
+#define MME_CMDQ_GLBL_NON_SECURE_PROPS_ASID_MASK 0x3FF
+#define MME_CMDQ_GLBL_NON_SECURE_PROPS_MMBP_SHIFT 10
+#define MME_CMDQ_GLBL_NON_SECURE_PROPS_MMBP_MASK 0x400
+
+/* MME_CMDQ_GLBL_STS0 */
+#define MME_CMDQ_GLBL_STS0_PQF_IDLE_SHIFT 0
+#define MME_CMDQ_GLBL_STS0_PQF_IDLE_MASK 0x1
+#define MME_CMDQ_GLBL_STS0_CQF_IDLE_SHIFT 1
+#define MME_CMDQ_GLBL_STS0_CQF_IDLE_MASK 0x2
+#define MME_CMDQ_GLBL_STS0_CP_IDLE_SHIFT 2
+#define MME_CMDQ_GLBL_STS0_CP_IDLE_MASK 0x4
+#define MME_CMDQ_GLBL_STS0_DMA_IDLE_SHIFT 3
+#define MME_CMDQ_GLBL_STS0_DMA_IDLE_MASK 0x8
+#define MME_CMDQ_GLBL_STS0_PQF_IS_STOP_SHIFT 4
+#define MME_CMDQ_GLBL_STS0_PQF_IS_STOP_MASK 0x10
+#define MME_CMDQ_GLBL_STS0_CQF_IS_STOP_SHIFT 5
+#define MME_CMDQ_GLBL_STS0_CQF_IS_STOP_MASK 0x20
+#define MME_CMDQ_GLBL_STS0_CP_IS_STOP_SHIFT 6
+#define MME_CMDQ_GLBL_STS0_CP_IS_STOP_MASK 0x40
+#define MME_CMDQ_GLBL_STS0_DMA_IS_STOP_SHIFT 7
+#define MME_CMDQ_GLBL_STS0_DMA_IS_STOP_MASK 0x80
+
+/* MME_CMDQ_GLBL_STS1 */
+#define MME_CMDQ_GLBL_STS1_PQF_RD_ERR_SHIFT 0
+#define MME_CMDQ_GLBL_STS1_PQF_RD_ERR_MASK 0x1
+#define MME_CMDQ_GLBL_STS1_CQF_RD_ERR_SHIFT 1
+#define MME_CMDQ_GLBL_STS1_CQF_RD_ERR_MASK 0x2
+#define MME_CMDQ_GLBL_STS1_CP_RD_ERR_SHIFT 2
+#define MME_CMDQ_GLBL_STS1_CP_RD_ERR_MASK 0x4
+#define MME_CMDQ_GLBL_STS1_CP_UNDEF_CMD_ERR_SHIFT 3
+#define MME_CMDQ_GLBL_STS1_CP_UNDEF_CMD_ERR_MASK 0x8
+#define MME_CMDQ_GLBL_STS1_CP_STOP_OP_SHIFT 4
+#define MME_CMDQ_GLBL_STS1_CP_STOP_OP_MASK 0x10
+#define MME_CMDQ_GLBL_STS1_CP_MSG_WR_ERR_SHIFT 5
+#define MME_CMDQ_GLBL_STS1_CP_MSG_WR_ERR_MASK 0x20
+#define MME_CMDQ_GLBL_STS1_DMA_RD_ERR_SHIFT 8
+#define MME_CMDQ_GLBL_STS1_DMA_RD_ERR_MASK 0x100
+#define MME_CMDQ_GLBL_STS1_DMA_WR_ERR_SHIFT 9
+#define MME_CMDQ_GLBL_STS1_DMA_WR_ERR_MASK 0x200
+#define MME_CMDQ_GLBL_STS1_DMA_RD_MSG_ERR_SHIFT 10
+#define MME_CMDQ_GLBL_STS1_DMA_RD_MSG_ERR_MASK 0x400
+#define MME_CMDQ_GLBL_STS1_DMA_WR_MSG_ERR_SHIFT 11
+#define MME_CMDQ_GLBL_STS1_DMA_WR_MSG_ERR_MASK 0x800
+
+/* MME_CMDQ_CQ_CFG0 */
+#define MME_CMDQ_CQ_CFG0_RESERVED_SHIFT 0
+#define MME_CMDQ_CQ_CFG0_RESERVED_MASK 0x1
+
+/* MME_CMDQ_CQ_CFG1 */
+#define MME_CMDQ_CQ_CFG1_CREDIT_LIM_SHIFT 0
+#define MME_CMDQ_CQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define MME_CMDQ_CQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define MME_CMDQ_CQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* MME_CMDQ_CQ_ARUSER */
+#define MME_CMDQ_CQ_ARUSER_NOSNOOP_SHIFT 0
+#define MME_CMDQ_CQ_ARUSER_NOSNOOP_MASK 0x1
+#define MME_CMDQ_CQ_ARUSER_WORD_SHIFT 1
+#define MME_CMDQ_CQ_ARUSER_WORD_MASK 0x2
+
+/* MME_CMDQ_CQ_PTR_LO */
+#define MME_CMDQ_CQ_PTR_LO_VAL_SHIFT 0
+#define MME_CMDQ_CQ_PTR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_PTR_HI */
+#define MME_CMDQ_CQ_PTR_HI_VAL_SHIFT 0
+#define MME_CMDQ_CQ_PTR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_TSIZE */
+#define MME_CMDQ_CQ_TSIZE_VAL_SHIFT 0
+#define MME_CMDQ_CQ_TSIZE_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_CTL */
+#define MME_CMDQ_CQ_CTL_RPT_SHIFT 0
+#define MME_CMDQ_CQ_CTL_RPT_MASK 0xFFFF
+#define MME_CMDQ_CQ_CTL_CTL_SHIFT 16
+#define MME_CMDQ_CQ_CTL_CTL_MASK 0xFFFF0000
+
+/* MME_CMDQ_CQ_PTR_LO_STS */
+#define MME_CMDQ_CQ_PTR_LO_STS_VAL_SHIFT 0
+#define MME_CMDQ_CQ_PTR_LO_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_PTR_HI_STS */
+#define MME_CMDQ_CQ_PTR_HI_STS_VAL_SHIFT 0
+#define MME_CMDQ_CQ_PTR_HI_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_TSIZE_STS */
+#define MME_CMDQ_CQ_TSIZE_STS_VAL_SHIFT 0
+#define MME_CMDQ_CQ_TSIZE_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_CTL_STS */
+#define MME_CMDQ_CQ_CTL_STS_RPT_SHIFT 0
+#define MME_CMDQ_CQ_CTL_STS_RPT_MASK 0xFFFF
+#define MME_CMDQ_CQ_CTL_STS_CTL_SHIFT 16
+#define MME_CMDQ_CQ_CTL_STS_CTL_MASK 0xFFFF0000
+
+/* MME_CMDQ_CQ_STS0 */
+#define MME_CMDQ_CQ_STS0_CQ_CREDIT_CNT_SHIFT 0
+#define MME_CMDQ_CQ_STS0_CQ_CREDIT_CNT_MASK 0xFFFF
+#define MME_CMDQ_CQ_STS0_CQ_FREE_CNT_SHIFT 16
+#define MME_CMDQ_CQ_STS0_CQ_FREE_CNT_MASK 0xFFFF0000
+
+/* MME_CMDQ_CQ_STS1 */
+#define MME_CMDQ_CQ_STS1_CQ_INFLIGHT_CNT_SHIFT 0
+#define MME_CMDQ_CQ_STS1_CQ_INFLIGHT_CNT_MASK 0xFFFF
+#define MME_CMDQ_CQ_STS1_CQ_BUF_EMPTY_SHIFT 30
+#define MME_CMDQ_CQ_STS1_CQ_BUF_EMPTY_MASK 0x40000000
+#define MME_CMDQ_CQ_STS1_CQ_BUSY_SHIFT 31
+#define MME_CMDQ_CQ_STS1_CQ_BUSY_MASK 0x80000000
+
+/* MME_CMDQ_CQ_RD_RATE_LIM_EN */
+#define MME_CMDQ_CQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define MME_CMDQ_CQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* MME_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN */
+#define MME_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define MME_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* MME_CMDQ_CQ_RD_RATE_LIM_SAT */
+#define MME_CMDQ_CQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define MME_CMDQ_CQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* MME_CMDQ_CQ_RD_RATE_LIM_TOUT */
+#define MME_CMDQ_CQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define MME_CMDQ_CQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* MME_CMDQ_CQ_IFIFO_CNT */
+#define MME_CMDQ_CQ_IFIFO_CNT_VAL_SHIFT 0
+#define MME_CMDQ_CQ_IFIFO_CNT_VAL_MASK 0x3
+
+/* MME_CMDQ_CP_MSG_BASE0_ADDR_LO */
+#define MME_CMDQ_CP_MSG_BASE0_ADDR_LO_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE0_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE0_ADDR_HI */
+#define MME_CMDQ_CP_MSG_BASE0_ADDR_HI_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE0_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE1_ADDR_LO */
+#define MME_CMDQ_CP_MSG_BASE1_ADDR_LO_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE1_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE1_ADDR_HI */
+#define MME_CMDQ_CP_MSG_BASE1_ADDR_HI_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE1_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE2_ADDR_LO */
+#define MME_CMDQ_CP_MSG_BASE2_ADDR_LO_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE2_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE2_ADDR_HI */
+#define MME_CMDQ_CP_MSG_BASE2_ADDR_HI_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE2_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE3_ADDR_LO */
+#define MME_CMDQ_CP_MSG_BASE3_ADDR_LO_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE3_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_MSG_BASE3_ADDR_HI */
+#define MME_CMDQ_CP_MSG_BASE3_ADDR_HI_VAL_SHIFT 0
+#define MME_CMDQ_CP_MSG_BASE3_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_TSIZE_OFFSET */
+#define MME_CMDQ_CP_LDMA_TSIZE_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_TSIZE_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET */
+#define MME_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET */
+#define MME_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET */
+#define MME_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET */
+#define MME_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_LDMA_COMMIT_OFFSET */
+#define MME_CMDQ_CP_LDMA_COMMIT_OFFSET_VAL_SHIFT 0
+#define MME_CMDQ_CP_LDMA_COMMIT_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_FENCE0_RDATA */
+#define MME_CMDQ_CP_FENCE0_RDATA_INC_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE0_RDATA_INC_VAL_MASK 0xF
+
+/* MME_CMDQ_CP_FENCE1_RDATA */
+#define MME_CMDQ_CP_FENCE1_RDATA_INC_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE1_RDATA_INC_VAL_MASK 0xF
+
+/* MME_CMDQ_CP_FENCE2_RDATA */
+#define MME_CMDQ_CP_FENCE2_RDATA_INC_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE2_RDATA_INC_VAL_MASK 0xF
+
+/* MME_CMDQ_CP_FENCE3_RDATA */
+#define MME_CMDQ_CP_FENCE3_RDATA_INC_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE3_RDATA_INC_VAL_MASK 0xF
+
+/* MME_CMDQ_CP_FENCE0_CNT */
+#define MME_CMDQ_CP_FENCE0_CNT_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE0_CNT_VAL_MASK 0xFF
+
+/* MME_CMDQ_CP_FENCE1_CNT */
+#define MME_CMDQ_CP_FENCE1_CNT_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE1_CNT_VAL_MASK 0xFF
+
+/* MME_CMDQ_CP_FENCE2_CNT */
+#define MME_CMDQ_CP_FENCE2_CNT_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE2_CNT_VAL_MASK 0xFF
+
+/* MME_CMDQ_CP_FENCE3_CNT */
+#define MME_CMDQ_CP_FENCE3_CNT_VAL_SHIFT 0
+#define MME_CMDQ_CP_FENCE3_CNT_VAL_MASK 0xFF
+
+/* MME_CMDQ_CP_STS */
+#define MME_CMDQ_CP_STS_MSG_INFLIGHT_CNT_SHIFT 0
+#define MME_CMDQ_CP_STS_MSG_INFLIGHT_CNT_MASK 0xFFFF
+#define MME_CMDQ_CP_STS_ERDY_SHIFT 16
+#define MME_CMDQ_CP_STS_ERDY_MASK 0x10000
+#define MME_CMDQ_CP_STS_RRDY_SHIFT 17
+#define MME_CMDQ_CP_STS_RRDY_MASK 0x20000
+#define MME_CMDQ_CP_STS_MRDY_SHIFT 18
+#define MME_CMDQ_CP_STS_MRDY_MASK 0x40000
+#define MME_CMDQ_CP_STS_SW_STOP_SHIFT 19
+#define MME_CMDQ_CP_STS_SW_STOP_MASK 0x80000
+#define MME_CMDQ_CP_STS_FENCE_ID_SHIFT 20
+#define MME_CMDQ_CP_STS_FENCE_ID_MASK 0x300000
+#define MME_CMDQ_CP_STS_FENCE_IN_PROGRESS_SHIFT 22
+#define MME_CMDQ_CP_STS_FENCE_IN_PROGRESS_MASK 0x400000
+
+/* MME_CMDQ_CP_CURRENT_INST_LO */
+#define MME_CMDQ_CP_CURRENT_INST_LO_VAL_SHIFT 0
+#define MME_CMDQ_CP_CURRENT_INST_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_CURRENT_INST_HI */
+#define MME_CMDQ_CP_CURRENT_INST_HI_VAL_SHIFT 0
+#define MME_CMDQ_CP_CURRENT_INST_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CP_BARRIER_CFG */
+#define MME_CMDQ_CP_BARRIER_CFG_EBGUARD_SHIFT 0
+#define MME_CMDQ_CP_BARRIER_CFG_EBGUARD_MASK 0xFFF
+
+/* MME_CMDQ_CP_DBG_0 */
+#define MME_CMDQ_CP_DBG_0_VAL_SHIFT 0
+#define MME_CMDQ_CP_DBG_0_VAL_MASK 0xFF
+
+/* MME_CMDQ_CQ_BUF_ADDR */
+#define MME_CMDQ_CQ_BUF_ADDR_VAL_SHIFT 0
+#define MME_CMDQ_CQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* MME_CMDQ_CQ_BUF_RDATA */
+#define MME_CMDQ_CQ_BUF_RDATA_VAL_SHIFT 0
+#define MME_CMDQ_CQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_MME_CMDQ_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h
new file mode 100644
index 000000000000..5c2f6b870a58
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_CMDQ_REGS_H_
+#define ASIC_REG_MME_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * MME_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmMME_CMDQ_GLBL_CFG0 0xD9000
+
+#define mmMME_CMDQ_GLBL_CFG1 0xD9004
+
+#define mmMME_CMDQ_GLBL_PROT 0xD9008
+
+#define mmMME_CMDQ_GLBL_ERR_CFG 0xD900C
+
+#define mmMME_CMDQ_GLBL_ERR_ADDR_LO 0xD9010
+
+#define mmMME_CMDQ_GLBL_ERR_ADDR_HI 0xD9014
+
+#define mmMME_CMDQ_GLBL_ERR_WDATA 0xD9018
+
+#define mmMME_CMDQ_GLBL_SECURE_PROPS 0xD901C
+
+#define mmMME_CMDQ_GLBL_NON_SECURE_PROPS 0xD9020
+
+#define mmMME_CMDQ_GLBL_STS0 0xD9024
+
+#define mmMME_CMDQ_GLBL_STS1 0xD9028
+
+#define mmMME_CMDQ_CQ_CFG0 0xD90B0
+
+#define mmMME_CMDQ_CQ_CFG1 0xD90B4
+
+#define mmMME_CMDQ_CQ_ARUSER 0xD90B8
+
+#define mmMME_CMDQ_CQ_PTR_LO 0xD90C0
+
+#define mmMME_CMDQ_CQ_PTR_HI 0xD90C4
+
+#define mmMME_CMDQ_CQ_TSIZE 0xD90C8
+
+#define mmMME_CMDQ_CQ_CTL 0xD90CC
+
+#define mmMME_CMDQ_CQ_PTR_LO_STS 0xD90D4
+
+#define mmMME_CMDQ_CQ_PTR_HI_STS 0xD90D8
+
+#define mmMME_CMDQ_CQ_TSIZE_STS 0xD90DC
+
+#define mmMME_CMDQ_CQ_CTL_STS 0xD90E0
+
+#define mmMME_CMDQ_CQ_STS0 0xD90E4
+
+#define mmMME_CMDQ_CQ_STS1 0xD90E8
+
+#define mmMME_CMDQ_CQ_RD_RATE_LIM_EN 0xD90F0
+
+#define mmMME_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xD90F4
+
+#define mmMME_CMDQ_CQ_RD_RATE_LIM_SAT 0xD90F8
+
+#define mmMME_CMDQ_CQ_RD_RATE_LIM_TOUT 0xD90FC
+
+#define mmMME_CMDQ_CQ_IFIFO_CNT 0xD9108
+
+#define mmMME_CMDQ_CP_MSG_BASE0_ADDR_LO 0xD9120
+
+#define mmMME_CMDQ_CP_MSG_BASE0_ADDR_HI 0xD9124
+
+#define mmMME_CMDQ_CP_MSG_BASE1_ADDR_LO 0xD9128
+
+#define mmMME_CMDQ_CP_MSG_BASE1_ADDR_HI 0xD912C
+
+#define mmMME_CMDQ_CP_MSG_BASE2_ADDR_LO 0xD9130
+
+#define mmMME_CMDQ_CP_MSG_BASE2_ADDR_HI 0xD9134
+
+#define mmMME_CMDQ_CP_MSG_BASE3_ADDR_LO 0xD9138
+
+#define mmMME_CMDQ_CP_MSG_BASE3_ADDR_HI 0xD913C
+
+#define mmMME_CMDQ_CP_LDMA_TSIZE_OFFSET 0xD9140
+
+#define mmMME_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xD9144
+
+#define mmMME_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xD9148
+
+#define mmMME_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xD914C
+
+#define mmMME_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xD9150
+
+#define mmMME_CMDQ_CP_LDMA_COMMIT_OFFSET 0xD9154
+
+#define mmMME_CMDQ_CP_FENCE0_RDATA 0xD9158
+
+#define mmMME_CMDQ_CP_FENCE1_RDATA 0xD915C
+
+#define mmMME_CMDQ_CP_FENCE2_RDATA 0xD9160
+
+#define mmMME_CMDQ_CP_FENCE3_RDATA 0xD9164
+
+#define mmMME_CMDQ_CP_FENCE0_CNT 0xD9168
+
+#define mmMME_CMDQ_CP_FENCE1_CNT 0xD916C
+
+#define mmMME_CMDQ_CP_FENCE2_CNT 0xD9170
+
+#define mmMME_CMDQ_CP_FENCE3_CNT 0xD9174
+
+#define mmMME_CMDQ_CP_STS 0xD9178
+
+#define mmMME_CMDQ_CP_CURRENT_INST_LO 0xD917C
+
+#define mmMME_CMDQ_CP_CURRENT_INST_HI 0xD9180
+
+#define mmMME_CMDQ_CP_BARRIER_CFG 0xD9184
+
+#define mmMME_CMDQ_CP_DBG_0 0xD9188
+
+#define mmMME_CMDQ_CQ_BUF_ADDR 0xD9308
+
+#define mmMME_CMDQ_CQ_BUF_RDATA 0xD930C
+
+#endif /* ASIC_REG_MME_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h
new file mode 100644
index 000000000000..c7b1b0bb3384
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_masks.h
@@ -0,0 +1,1537 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_MASKS_H_
+#define ASIC_REG_MME_MASKS_H_
+
+/*
+ *****************************************
+ * MME (Prototype: MME)
+ *****************************************
+ */
+
+/* MME_ARCH_STATUS */
+#define MME_ARCH_STATUS_A_SHIFT 0
+#define MME_ARCH_STATUS_A_MASK 0x1
+#define MME_ARCH_STATUS_B_SHIFT 1
+#define MME_ARCH_STATUS_B_MASK 0x2
+#define MME_ARCH_STATUS_CIN_SHIFT 2
+#define MME_ARCH_STATUS_CIN_MASK 0x4
+#define MME_ARCH_STATUS_COUT_SHIFT 3
+#define MME_ARCH_STATUS_COUT_MASK 0x8
+#define MME_ARCH_STATUS_TE_SHIFT 4
+#define MME_ARCH_STATUS_TE_MASK 0x10
+#define MME_ARCH_STATUS_LD_SHIFT 5
+#define MME_ARCH_STATUS_LD_MASK 0x20
+#define MME_ARCH_STATUS_ST_SHIFT 6
+#define MME_ARCH_STATUS_ST_MASK 0x40
+#define MME_ARCH_STATUS_SB_A_EMPTY_SHIFT 7
+#define MME_ARCH_STATUS_SB_A_EMPTY_MASK 0x80
+#define MME_ARCH_STATUS_SB_B_EMPTY_SHIFT 8
+#define MME_ARCH_STATUS_SB_B_EMPTY_MASK 0x100
+#define MME_ARCH_STATUS_SB_CIN_EMPTY_SHIFT 9
+#define MME_ARCH_STATUS_SB_CIN_EMPTY_MASK 0x200
+#define MME_ARCH_STATUS_SB_COUT_EMPTY_SHIFT 10
+#define MME_ARCH_STATUS_SB_COUT_EMPTY_MASK 0x400
+#define MME_ARCH_STATUS_SM_IDLE_SHIFT 11
+#define MME_ARCH_STATUS_SM_IDLE_MASK 0x800
+#define MME_ARCH_STATUS_WBC_AXI_IDLE_SHIFT 12
+#define MME_ARCH_STATUS_WBC_AXI_IDLE_MASK 0xF000
+#define MME_ARCH_STATUS_SBC_AXI_IDLE_SHIFT 16
+#define MME_ARCH_STATUS_SBC_AXI_IDLE_MASK 0x30000
+#define MME_ARCH_STATUS_SBB_AXI_IDLE_SHIFT 18
+#define MME_ARCH_STATUS_SBB_AXI_IDLE_MASK 0xC0000
+#define MME_ARCH_STATUS_SBA_AXI_IDLE_SHIFT 20
+#define MME_ARCH_STATUS_SBA_AXI_IDLE_MASK 0x300000
+#define MME_ARCH_STATUS_FREE_ACCUMS_SHIFT 22
+#define MME_ARCH_STATUS_FREE_ACCUMS_MASK 0x1C00000
+
+/* MME_ARCH_A_BASE_ADDR_HIGH */
+#define MME_ARCH_A_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_ARCH_A_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_BASE_ADDR_HIGH */
+#define MME_ARCH_B_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_ARCH_B_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_CIN_BASE_ADDR_HIGH */
+#define MME_ARCH_CIN_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_ARCH_CIN_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_COUT_BASE_ADDR_HIGH */
+#define MME_ARCH_COUT_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_ARCH_COUT_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_BIAS_BASE_ADDR_HIGH */
+#define MME_ARCH_BIAS_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_ARCH_BIAS_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_BASE_ADDR_LOW */
+#define MME_ARCH_A_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_ARCH_A_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_BASE_ADDR_LOW */
+#define MME_ARCH_B_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_ARCH_B_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_CIN_BASE_ADDR_LOW */
+#define MME_ARCH_CIN_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_ARCH_CIN_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_COUT_BASE_ADDR_LOW */
+#define MME_ARCH_COUT_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_ARCH_COUT_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_BIAS_BASE_ADDR_LOW */
+#define MME_ARCH_BIAS_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_ARCH_BIAS_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_HEADER */
+#define MME_ARCH_HEADER_SIGNAL_MASK_SHIFT 0
+#define MME_ARCH_HEADER_SIGNAL_MASK_MASK 0x1F
+#define MME_ARCH_HEADER_SIGNAL_EN_SHIFT 5
+#define MME_ARCH_HEADER_SIGNAL_EN_MASK 0x20
+#define MME_ARCH_HEADER_TRANS_A_SHIFT 6
+#define MME_ARCH_HEADER_TRANS_A_MASK 0x40
+#define MME_ARCH_HEADER_LOWER_A_SHIFT 7
+#define MME_ARCH_HEADER_LOWER_A_MASK 0x80
+#define MME_ARCH_HEADER_ACCUM_MASK_SHIFT 8
+#define MME_ARCH_HEADER_ACCUM_MASK_MASK 0xF00
+#define MME_ARCH_HEADER_LOAD_BIAS_SHIFT 12
+#define MME_ARCH_HEADER_LOAD_BIAS_MASK 0x1000
+#define MME_ARCH_HEADER_LOAD_CIN_SHIFT 13
+#define MME_ARCH_HEADER_LOAD_CIN_MASK 0x2000
+#define MME_ARCH_HEADER_STORE_OUT_SHIFT 15
+#define MME_ARCH_HEADER_STORE_OUT_MASK 0x8000
+#define MME_ARCH_HEADER_ACC_LD_INC_DISABLE_SHIFT 16
+#define MME_ARCH_HEADER_ACC_LD_INC_DISABLE_MASK 0x10000
+#define MME_ARCH_HEADER_ADVANCE_A_SHIFT 17
+#define MME_ARCH_HEADER_ADVANCE_A_MASK 0x20000
+#define MME_ARCH_HEADER_ADVANCE_B_SHIFT 18
+#define MME_ARCH_HEADER_ADVANCE_B_MASK 0x40000
+#define MME_ARCH_HEADER_ADVANCE_CIN_SHIFT 19
+#define MME_ARCH_HEADER_ADVANCE_CIN_MASK 0x80000
+#define MME_ARCH_HEADER_ADVANCE_COUT_SHIFT 20
+#define MME_ARCH_HEADER_ADVANCE_COUT_MASK 0x100000
+#define MME_ARCH_HEADER_COMPRESSED_B_SHIFT 21
+#define MME_ARCH_HEADER_COMPRESSED_B_MASK 0x200000
+#define MME_ARCH_HEADER_MASK_CONV_END_SHIFT 22
+#define MME_ARCH_HEADER_MASK_CONV_END_MASK 0x400000
+#define MME_ARCH_HEADER_ACC_ST_INC_DISABLE_SHIFT 23
+#define MME_ARCH_HEADER_ACC_ST_INC_DISABLE_MASK 0x800000
+#define MME_ARCH_HEADER_AB_DATA_TYPE_SHIFT 24
+#define MME_ARCH_HEADER_AB_DATA_TYPE_MASK 0x3000000
+#define MME_ARCH_HEADER_CIN_DATA_TYPE_SHIFT 26
+#define MME_ARCH_HEADER_CIN_DATA_TYPE_MASK 0x1C000000
+#define MME_ARCH_HEADER_COUT_DATA_TYPE_SHIFT 29
+#define MME_ARCH_HEADER_COUT_DATA_TYPE_MASK 0xE0000000
+
+/* MME_ARCH_KERNEL_SIZE_MINUS_1 */
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_0_SHIFT 0
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_0_MASK 0xFF
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_1_SHIFT 8
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_1_MASK 0xFF00
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_2_SHIFT 16
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_2_MASK 0xFF0000
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_3_SHIFT 24
+#define MME_ARCH_KERNEL_SIZE_MINUS_1_DIM_3_MASK 0xFF000000
+
+/* MME_ARCH_ASSOCIATED_DIMS */
+#define MME_ARCH_ASSOCIATED_DIMS_A_0_SHIFT 0
+#define MME_ARCH_ASSOCIATED_DIMS_A_0_MASK 0x7
+#define MME_ARCH_ASSOCIATED_DIMS_B_0_SHIFT 3
+#define MME_ARCH_ASSOCIATED_DIMS_B_0_MASK 0x38
+#define MME_ARCH_ASSOCIATED_DIMS_CIN_0_SHIFT 6
+#define MME_ARCH_ASSOCIATED_DIMS_CIN_0_MASK 0x1C0
+#define MME_ARCH_ASSOCIATED_DIMS_COUT_0_SHIFT 9
+#define MME_ARCH_ASSOCIATED_DIMS_COUT_0_MASK 0xE00
+#define MME_ARCH_ASSOCIATED_DIMS_A_1_SHIFT 16
+#define MME_ARCH_ASSOCIATED_DIMS_A_1_MASK 0x70000
+#define MME_ARCH_ASSOCIATED_DIMS_B_1_SHIFT 19
+#define MME_ARCH_ASSOCIATED_DIMS_B_1_MASK 0x380000
+#define MME_ARCH_ASSOCIATED_DIMS_CIN_1_SHIFT 22
+#define MME_ARCH_ASSOCIATED_DIMS_CIN_1_MASK 0x1C00000
+#define MME_ARCH_ASSOCIATED_DIMS_COUT_1_SHIFT 25
+#define MME_ARCH_ASSOCIATED_DIMS_COUT_1_MASK 0xE000000
+
+/* MME_ARCH_COUT_SCALE */
+#define MME_ARCH_COUT_SCALE_V_SHIFT 0
+#define MME_ARCH_COUT_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_CIN_SCALE */
+#define MME_ARCH_CIN_SCALE_V_SHIFT 0
+#define MME_ARCH_CIN_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_GEMMLOWP_ZP */
+#define MME_ARCH_GEMMLOWP_ZP_ZP_CIN_SHIFT 0
+#define MME_ARCH_GEMMLOWP_ZP_ZP_CIN_MASK 0x1FF
+#define MME_ARCH_GEMMLOWP_ZP_ZP_COUT_SHIFT 9
+#define MME_ARCH_GEMMLOWP_ZP_ZP_COUT_MASK 0x3FE00
+#define MME_ARCH_GEMMLOWP_ZP_ZP_B_SHIFT 18
+#define MME_ARCH_GEMMLOWP_ZP_ZP_B_MASK 0x7FC0000
+#define MME_ARCH_GEMMLOWP_ZP_GEMMLOWP_EU_EN_SHIFT 27
+#define MME_ARCH_GEMMLOWP_ZP_GEMMLOWP_EU_EN_MASK 0x8000000
+#define MME_ARCH_GEMMLOWP_ZP_ACCUM_SHIFT 28
+#define MME_ARCH_GEMMLOWP_ZP_ACCUM_MASK 0x10000000
+#define MME_ARCH_GEMMLOWP_ZP_ACCUM_BIAS_SHIFT 29
+#define MME_ARCH_GEMMLOWP_ZP_ACCUM_BIAS_MASK 0x20000000
+#define MME_ARCH_GEMMLOWP_ZP_RELU_EN_SHIFT 30
+#define MME_ARCH_GEMMLOWP_ZP_RELU_EN_MASK 0x40000000
+
+/* MME_ARCH_GEMMLOWP_EXPONENT */
+#define MME_ARCH_GEMMLOWP_EXPONENT_EXPONENT_CIN_SHIFT 0
+#define MME_ARCH_GEMMLOWP_EXPONENT_EXPONENT_CIN_MASK 0x3F
+#define MME_ARCH_GEMMLOWP_EXPONENT_EXPONENT_COUT_SHIFT 8
+#define MME_ARCH_GEMMLOWP_EXPONENT_EXPONENT_COUT_MASK 0x3F00
+#define MME_ARCH_GEMMLOWP_EXPONENT_MUL_CIN_EN_SHIFT 16
+#define MME_ARCH_GEMMLOWP_EXPONENT_MUL_CIN_EN_MASK 0x10000
+#define MME_ARCH_GEMMLOWP_EXPONENT_MUL_COUT_EN_SHIFT 17
+#define MME_ARCH_GEMMLOWP_EXPONENT_MUL_COUT_EN_MASK 0x20000
+
+/* MME_ARCH_A_ROI_BASE_OFFSET */
+#define MME_ARCH_A_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_ARCH_A_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_VALID_ELEMENTS */
+#define MME_ARCH_A_VALID_ELEMENTS_V_SHIFT 0
+#define MME_ARCH_A_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_LOOP_STRIDE */
+#define MME_ARCH_A_LOOP_STRIDE_V_SHIFT 0
+#define MME_ARCH_A_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_ROI_SIZE */
+#define MME_ARCH_A_ROI_SIZE_V_SHIFT 0
+#define MME_ARCH_A_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_SPATIAL_START_OFFSET */
+#define MME_ARCH_A_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_ARCH_A_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_SPATIAL_STRIDE */
+#define MME_ARCH_A_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_ARCH_A_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_A_SPATIAL_SIZE_MINUS_1 */
+#define MME_ARCH_A_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_ARCH_A_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_ROI_BASE_OFFSET */
+#define MME_ARCH_B_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_ARCH_B_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_VALID_ELEMENTS */
+#define MME_ARCH_B_VALID_ELEMENTS_V_SHIFT 0
+#define MME_ARCH_B_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_LOOP_STRIDE */
+#define MME_ARCH_B_LOOP_STRIDE_V_SHIFT 0
+#define MME_ARCH_B_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_ROI_SIZE */
+#define MME_ARCH_B_ROI_SIZE_V_SHIFT 0
+#define MME_ARCH_B_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_SPATIAL_START_OFFSET */
+#define MME_ARCH_B_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_ARCH_B_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_SPATIAL_STRIDE */
+#define MME_ARCH_B_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_ARCH_B_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_B_SPATIAL_SIZE_MINUS_1 */
+#define MME_ARCH_B_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_ARCH_B_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_ROI_BASE_OFFSET */
+#define MME_ARCH_C_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_ARCH_C_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_VALID_ELEMENTS */
+#define MME_ARCH_C_VALID_ELEMENTS_V_SHIFT 0
+#define MME_ARCH_C_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_LOOP_STRIDE */
+#define MME_ARCH_C_LOOP_STRIDE_V_SHIFT 0
+#define MME_ARCH_C_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_ROI_SIZE */
+#define MME_ARCH_C_ROI_SIZE_V_SHIFT 0
+#define MME_ARCH_C_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_SPATIAL_START_OFFSET */
+#define MME_ARCH_C_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_ARCH_C_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_SPATIAL_STRIDE */
+#define MME_ARCH_C_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_ARCH_C_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_C_SPATIAL_SIZE_MINUS_1 */
+#define MME_ARCH_C_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_ARCH_C_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_SYNC_OBJECT_MESSAGE */
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define MME_ARCH_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* MME_ARCH_E_PADDING_VALUE_A */
+#define MME_ARCH_E_PADDING_VALUE_A_V_SHIFT 0
+#define MME_ARCH_E_PADDING_VALUE_A_V_MASK 0xFFFF
+
+/* MME_ARCH_E_NUM_ITERATION_MINUS_1 */
+#define MME_ARCH_E_NUM_ITERATION_MINUS_1_V_SHIFT 0
+#define MME_ARCH_E_NUM_ITERATION_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_ARCH_E_BUBBLES_PER_SPLIT */
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_A_SHIFT 0
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_A_MASK 0xFF
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_B_SHIFT 8
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_B_MASK 0xFF00
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_CIN_SHIFT 16
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_CIN_MASK 0xFF0000
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_ID_SHIFT 24
+#define MME_ARCH_E_BUBBLES_PER_SPLIT_ID_MASK 0xFF000000
+
+/* MME_CMD */
+#define MME_CMD_EXECUTE_SHIFT 0
+#define MME_CMD_EXECUTE_MASK 0x1
+
+/* MME_DUMMY */
+#define MME_DUMMY_V_SHIFT 0
+#define MME_DUMMY_V_MASK 0xFFFFFFFF
+
+/* MME_RESET */
+#define MME_RESET_V_SHIFT 0
+#define MME_RESET_V_MASK 0x1
+
+/* MME_STALL */
+#define MME_STALL_V_SHIFT 0
+#define MME_STALL_V_MASK 0xFFFFFFFF
+
+/* MME_SM_BASE_ADDRESS_LOW */
+#define MME_SM_BASE_ADDRESS_LOW_V_SHIFT 0
+#define MME_SM_BASE_ADDRESS_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SM_BASE_ADDRESS_HIGH */
+#define MME_SM_BASE_ADDRESS_HIGH_V_SHIFT 0
+#define MME_SM_BASE_ADDRESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_DBGMEM_ADD */
+#define MME_DBGMEM_ADD_V_SHIFT 0
+#define MME_DBGMEM_ADD_V_MASK 0xFFFFFFFF
+
+/* MME_DBGMEM_DATA_WR */
+#define MME_DBGMEM_DATA_WR_V_SHIFT 0
+#define MME_DBGMEM_DATA_WR_V_MASK 0xFFFFFFFF
+
+/* MME_DBGMEM_DATA_RD */
+#define MME_DBGMEM_DATA_RD_V_SHIFT 0
+#define MME_DBGMEM_DATA_RD_V_MASK 0xFFFFFFFF
+
+/* MME_DBGMEM_CTRL */
+#define MME_DBGMEM_CTRL_WR_NRD_SHIFT 0
+#define MME_DBGMEM_CTRL_WR_NRD_MASK 0x1
+
+/* MME_DBGMEM_RC */
+#define MME_DBGMEM_RC_VALID_SHIFT 0
+#define MME_DBGMEM_RC_VALID_MASK 0x1
+#define MME_DBGMEM_RC_FULL_SHIFT 1
+#define MME_DBGMEM_RC_FULL_MASK 0x2
+
+/* MME_LOG_SHADOW */
+#define MME_LOG_SHADOW_MASK_0_SHIFT 0
+#define MME_LOG_SHADOW_MASK_0_MASK 0x7F
+#define MME_LOG_SHADOW_MASK_1_SHIFT 8
+#define MME_LOG_SHADOW_MASK_1_MASK 0x7F00
+#define MME_LOG_SHADOW_MASK_2_SHIFT 16
+#define MME_LOG_SHADOW_MASK_2_MASK 0x7F0000
+#define MME_LOG_SHADOW_MASK_3_SHIFT 24
+#define MME_LOG_SHADOW_MASK_3_MASK 0x7F000000
+
+/* MME_STORE_MAX_CREDIT */
+#define MME_STORE_MAX_CREDIT_V_SHIFT 0
+#define MME_STORE_MAX_CREDIT_V_MASK 0x3F
+
+/* MME_AGU */
+#define MME_AGU_SBA_MAX_CREDIT_SHIFT 0
+#define MME_AGU_SBA_MAX_CREDIT_MASK 0x1F
+#define MME_AGU_SBB_MAX_CREDIT_SHIFT 8
+#define MME_AGU_SBB_MAX_CREDIT_MASK 0x1F00
+#define MME_AGU_SBC_MAX_CREDIT_SHIFT 16
+#define MME_AGU_SBC_MAX_CREDIT_MASK 0x1F0000
+#define MME_AGU_WBC_MAX_CREDIT_SHIFT 24
+#define MME_AGU_WBC_MAX_CREDIT_MASK 0x3F000000
+
+/* MME_SBA */
+#define MME_SBA_MAX_SIZE_SHIFT 0
+#define MME_SBA_MAX_SIZE_MASK 0x3FF
+#define MME_SBA_EU_MAX_CREDIT_SHIFT 16
+#define MME_SBA_EU_MAX_CREDIT_MASK 0x1F0000
+
+/* MME_SBB */
+#define MME_SBB_MAX_SIZE_SHIFT 0
+#define MME_SBB_MAX_SIZE_MASK 0x3FF
+#define MME_SBB_EU_MAX_CREDIT_SHIFT 16
+#define MME_SBB_EU_MAX_CREDIT_MASK 0x1F0000
+
+/* MME_SBC */
+#define MME_SBC_MAX_SIZE_SHIFT 0
+#define MME_SBC_MAX_SIZE_MASK 0x3FF
+#define MME_SBC_EU_MAX_CREDIT_SHIFT 16
+#define MME_SBC_EU_MAX_CREDIT_MASK 0x1F0000
+
+/* MME_WBC */
+#define MME_WBC_MAX_OUTSTANDING_SHIFT 0
+#define MME_WBC_MAX_OUTSTANDING_MASK 0xFFF
+#define MME_WBC_DISABLE_FAST_END_PE_SHIFT 12
+#define MME_WBC_DISABLE_FAST_END_PE_MASK 0x1000
+#define MME_WBC_LD_INSERT_BUBBLE_DIS_SHIFT 13
+#define MME_WBC_LD_INSERT_BUBBLE_DIS_MASK 0x2000
+
+/* MME_SBA_CONTROL_DATA */
+#define MME_SBA_CONTROL_DATA_ASID_SHIFT 0
+#define MME_SBA_CONTROL_DATA_ASID_MASK 0x3FF
+#define MME_SBA_CONTROL_DATA_MMBP_SHIFT 10
+#define MME_SBA_CONTROL_DATA_MMBP_MASK 0x400
+
+/* MME_SBB_CONTROL_DATA */
+#define MME_SBB_CONTROL_DATA_ASID_SHIFT 0
+#define MME_SBB_CONTROL_DATA_ASID_MASK 0x3FF
+#define MME_SBB_CONTROL_DATA_MMBP_SHIFT 10
+#define MME_SBB_CONTROL_DATA_MMBP_MASK 0x400
+
+/* MME_SBC_CONTROL_DATA */
+#define MME_SBC_CONTROL_DATA_ASID_SHIFT 0
+#define MME_SBC_CONTROL_DATA_ASID_MASK 0x3FF
+#define MME_SBC_CONTROL_DATA_MMBP_SHIFT 10
+#define MME_SBC_CONTROL_DATA_MMBP_MASK 0x400
+
+/* MME_WBC_CONTROL_DATA */
+#define MME_WBC_CONTROL_DATA_ASID_SHIFT 0
+#define MME_WBC_CONTROL_DATA_ASID_MASK 0x3FF
+#define MME_WBC_CONTROL_DATA_MMBP_SHIFT 10
+#define MME_WBC_CONTROL_DATA_MMBP_MASK 0x400
+
+/* MME_TE */
+#define MME_TE_MAX_CREDIT_SHIFT 0
+#define MME_TE_MAX_CREDIT_MASK 0x1F
+#define MME_TE_DESC_MAX_CREDIT_SHIFT 8
+#define MME_TE_DESC_MAX_CREDIT_MASK 0x1F00
+
+/* MME_TE2DEC */
+#define MME_TE2DEC_MAX_CREDIT_SHIFT 0
+#define MME_TE2DEC_MAX_CREDIT_MASK 0x1F
+
+/* MME_REI_STATUS */
+#define MME_REI_STATUS_V_SHIFT 0
+#define MME_REI_STATUS_V_MASK 0xFFFFFFFF
+
+/* MME_REI_MASK */
+#define MME_REI_MASK_V_SHIFT 0
+#define MME_REI_MASK_V_MASK 0xFFFFFFFF
+
+/* MME_SEI_STATUS */
+#define MME_SEI_STATUS_V_SHIFT 0
+#define MME_SEI_STATUS_V_MASK 0xFFFFFFFF
+
+/* MME_SEI_MASK */
+#define MME_SEI_MASK_V_SHIFT 0
+#define MME_SEI_MASK_V_MASK 0xFFFFFFFF
+
+/* MME_SPI_STATUS */
+#define MME_SPI_STATUS_V_SHIFT 0
+#define MME_SPI_STATUS_V_MASK 0xFFFFFFFF
+
+/* MME_SPI_MASK */
+#define MME_SPI_MASK_V_SHIFT 0
+#define MME_SPI_MASK_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_STATUS */
+#define MME_SHADOW_0_STATUS_A_SHIFT 0
+#define MME_SHADOW_0_STATUS_A_MASK 0x1
+#define MME_SHADOW_0_STATUS_B_SHIFT 1
+#define MME_SHADOW_0_STATUS_B_MASK 0x2
+#define MME_SHADOW_0_STATUS_CIN_SHIFT 2
+#define MME_SHADOW_0_STATUS_CIN_MASK 0x4
+#define MME_SHADOW_0_STATUS_COUT_SHIFT 3
+#define MME_SHADOW_0_STATUS_COUT_MASK 0x8
+#define MME_SHADOW_0_STATUS_TE_SHIFT 4
+#define MME_SHADOW_0_STATUS_TE_MASK 0x10
+#define MME_SHADOW_0_STATUS_LD_SHIFT 5
+#define MME_SHADOW_0_STATUS_LD_MASK 0x20
+#define MME_SHADOW_0_STATUS_ST_SHIFT 6
+#define MME_SHADOW_0_STATUS_ST_MASK 0x40
+
+/* MME_SHADOW_0_A_BASE_ADDR_HIGH */
+#define MME_SHADOW_0_A_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_0_A_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_BASE_ADDR_HIGH */
+#define MME_SHADOW_0_B_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_0_B_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_CIN_BASE_ADDR_HIGH */
+#define MME_SHADOW_0_CIN_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_0_CIN_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_COUT_BASE_ADDR_HIGH */
+#define MME_SHADOW_0_COUT_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_0_COUT_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_BIAS_BASE_ADDR_HIGH */
+#define MME_SHADOW_0_BIAS_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_0_BIAS_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_BASE_ADDR_LOW */
+#define MME_SHADOW_0_A_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_0_A_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_BASE_ADDR_LOW */
+#define MME_SHADOW_0_B_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_0_B_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_CIN_BASE_ADDR_LOW */
+#define MME_SHADOW_0_CIN_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_0_CIN_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_COUT_BASE_ADDR_LOW */
+#define MME_SHADOW_0_COUT_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_0_COUT_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_BIAS_BASE_ADDR_LOW */
+#define MME_SHADOW_0_BIAS_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_0_BIAS_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_HEADER */
+#define MME_SHADOW_0_HEADER_SIGNAL_MASK_SHIFT 0
+#define MME_SHADOW_0_HEADER_SIGNAL_MASK_MASK 0x1F
+#define MME_SHADOW_0_HEADER_SIGNAL_EN_SHIFT 5
+#define MME_SHADOW_0_HEADER_SIGNAL_EN_MASK 0x20
+#define MME_SHADOW_0_HEADER_TRANS_A_SHIFT 6
+#define MME_SHADOW_0_HEADER_TRANS_A_MASK 0x40
+#define MME_SHADOW_0_HEADER_LOWER_A_SHIFT 7
+#define MME_SHADOW_0_HEADER_LOWER_A_MASK 0x80
+#define MME_SHADOW_0_HEADER_ACCUM_MASK_SHIFT 8
+#define MME_SHADOW_0_HEADER_ACCUM_MASK_MASK 0xF00
+#define MME_SHADOW_0_HEADER_LOAD_BIAS_SHIFT 12
+#define MME_SHADOW_0_HEADER_LOAD_BIAS_MASK 0x1000
+#define MME_SHADOW_0_HEADER_LOAD_CIN_SHIFT 13
+#define MME_SHADOW_0_HEADER_LOAD_CIN_MASK 0x2000
+#define MME_SHADOW_0_HEADER_STORE_OUT_SHIFT 15
+#define MME_SHADOW_0_HEADER_STORE_OUT_MASK 0x8000
+#define MME_SHADOW_0_HEADER_ACC_LD_INC_DISABLE_SHIFT 16
+#define MME_SHADOW_0_HEADER_ACC_LD_INC_DISABLE_MASK 0x10000
+#define MME_SHADOW_0_HEADER_ADVANCE_A_SHIFT 17
+#define MME_SHADOW_0_HEADER_ADVANCE_A_MASK 0x20000
+#define MME_SHADOW_0_HEADER_ADVANCE_B_SHIFT 18
+#define MME_SHADOW_0_HEADER_ADVANCE_B_MASK 0x40000
+#define MME_SHADOW_0_HEADER_ADVANCE_CIN_SHIFT 19
+#define MME_SHADOW_0_HEADER_ADVANCE_CIN_MASK 0x80000
+#define MME_SHADOW_0_HEADER_ADVANCE_COUT_SHIFT 20
+#define MME_SHADOW_0_HEADER_ADVANCE_COUT_MASK 0x100000
+#define MME_SHADOW_0_HEADER_COMPRESSED_B_SHIFT 21
+#define MME_SHADOW_0_HEADER_COMPRESSED_B_MASK 0x200000
+#define MME_SHADOW_0_HEADER_MASK_CONV_END_SHIFT 22
+#define MME_SHADOW_0_HEADER_MASK_CONV_END_MASK 0x400000
+#define MME_SHADOW_0_HEADER_ACC_ST_INC_DISABLE_SHIFT 23
+#define MME_SHADOW_0_HEADER_ACC_ST_INC_DISABLE_MASK 0x800000
+#define MME_SHADOW_0_HEADER_AB_DATA_TYPE_SHIFT 24
+#define MME_SHADOW_0_HEADER_AB_DATA_TYPE_MASK 0x3000000
+#define MME_SHADOW_0_HEADER_CIN_DATA_TYPE_SHIFT 26
+#define MME_SHADOW_0_HEADER_CIN_DATA_TYPE_MASK 0x1C000000
+#define MME_SHADOW_0_HEADER_COUT_DATA_TYPE_SHIFT 29
+#define MME_SHADOW_0_HEADER_COUT_DATA_TYPE_MASK 0xE0000000
+
+/* MME_SHADOW_0_KERNEL_SIZE_MINUS_1 */
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_0_SHIFT 0
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_0_MASK 0xFF
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_1_SHIFT 8
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_1_MASK 0xFF00
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_2_SHIFT 16
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_2_MASK 0xFF0000
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_3_SHIFT 24
+#define MME_SHADOW_0_KERNEL_SIZE_MINUS_1_DIM_3_MASK 0xFF000000
+
+/* MME_SHADOW_0_ASSOCIATED_DIMS */
+#define MME_SHADOW_0_ASSOCIATED_DIMS_A_0_SHIFT 0
+#define MME_SHADOW_0_ASSOCIATED_DIMS_A_0_MASK 0x7
+#define MME_SHADOW_0_ASSOCIATED_DIMS_B_0_SHIFT 3
+#define MME_SHADOW_0_ASSOCIATED_DIMS_B_0_MASK 0x38
+#define MME_SHADOW_0_ASSOCIATED_DIMS_CIN_0_SHIFT 6
+#define MME_SHADOW_0_ASSOCIATED_DIMS_CIN_0_MASK 0x1C0
+#define MME_SHADOW_0_ASSOCIATED_DIMS_COUT_0_SHIFT 9
+#define MME_SHADOW_0_ASSOCIATED_DIMS_COUT_0_MASK 0xE00
+#define MME_SHADOW_0_ASSOCIATED_DIMS_A_1_SHIFT 16
+#define MME_SHADOW_0_ASSOCIATED_DIMS_A_1_MASK 0x70000
+#define MME_SHADOW_0_ASSOCIATED_DIMS_B_1_SHIFT 19
+#define MME_SHADOW_0_ASSOCIATED_DIMS_B_1_MASK 0x380000
+#define MME_SHADOW_0_ASSOCIATED_DIMS_CIN_1_SHIFT 22
+#define MME_SHADOW_0_ASSOCIATED_DIMS_CIN_1_MASK 0x1C00000
+#define MME_SHADOW_0_ASSOCIATED_DIMS_COUT_1_SHIFT 25
+#define MME_SHADOW_0_ASSOCIATED_DIMS_COUT_1_MASK 0xE000000
+
+/* MME_SHADOW_0_COUT_SCALE */
+#define MME_SHADOW_0_COUT_SCALE_V_SHIFT 0
+#define MME_SHADOW_0_COUT_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_CIN_SCALE */
+#define MME_SHADOW_0_CIN_SCALE_V_SHIFT 0
+#define MME_SHADOW_0_CIN_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_GEMMLOWP_ZP */
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_CIN_SHIFT 0
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_CIN_MASK 0x1FF
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_COUT_SHIFT 9
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_COUT_MASK 0x3FE00
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_B_SHIFT 18
+#define MME_SHADOW_0_GEMMLOWP_ZP_ZP_B_MASK 0x7FC0000
+#define MME_SHADOW_0_GEMMLOWP_ZP_GEMMLOWP_EU_EN_SHIFT 27
+#define MME_SHADOW_0_GEMMLOWP_ZP_GEMMLOWP_EU_EN_MASK 0x8000000
+#define MME_SHADOW_0_GEMMLOWP_ZP_ACCUM_SHIFT 28
+#define MME_SHADOW_0_GEMMLOWP_ZP_ACCUM_MASK 0x10000000
+#define MME_SHADOW_0_GEMMLOWP_ZP_ACCUM_BIAS_SHIFT 29
+#define MME_SHADOW_0_GEMMLOWP_ZP_ACCUM_BIAS_MASK 0x20000000
+#define MME_SHADOW_0_GEMMLOWP_ZP_RELU_EN_SHIFT 30
+#define MME_SHADOW_0_GEMMLOWP_ZP_RELU_EN_MASK 0x40000000
+
+/* MME_SHADOW_0_GEMMLOWP_EXPONENT */
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_EXPONENT_CIN_SHIFT 0
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_EXPONENT_CIN_MASK 0x3F
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_EXPONENT_COUT_SHIFT 8
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_EXPONENT_COUT_MASK 0x3F00
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_MUL_CIN_EN_SHIFT 16
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_MUL_CIN_EN_MASK 0x10000
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_MUL_COUT_EN_SHIFT 17
+#define MME_SHADOW_0_GEMMLOWP_EXPONENT_MUL_COUT_EN_MASK 0x20000
+
+/* MME_SHADOW_0_A_ROI_BASE_OFFSET */
+#define MME_SHADOW_0_A_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_A_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_VALID_ELEMENTS */
+#define MME_SHADOW_0_A_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_0_A_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_LOOP_STRIDE */
+#define MME_SHADOW_0_A_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_A_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_ROI_SIZE */
+#define MME_SHADOW_0_A_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_0_A_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_SPATIAL_START_OFFSET */
+#define MME_SHADOW_0_A_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_A_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_SPATIAL_STRIDE */
+#define MME_SHADOW_0_A_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_A_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_A_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_0_A_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_0_A_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_ROI_BASE_OFFSET */
+#define MME_SHADOW_0_B_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_B_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_VALID_ELEMENTS */
+#define MME_SHADOW_0_B_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_0_B_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_LOOP_STRIDE */
+#define MME_SHADOW_0_B_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_B_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_ROI_SIZE */
+#define MME_SHADOW_0_B_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_0_B_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_SPATIAL_START_OFFSET */
+#define MME_SHADOW_0_B_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_B_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_SPATIAL_STRIDE */
+#define MME_SHADOW_0_B_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_B_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_B_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_0_B_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_0_B_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_ROI_BASE_OFFSET */
+#define MME_SHADOW_0_C_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_C_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_VALID_ELEMENTS */
+#define MME_SHADOW_0_C_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_0_C_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_LOOP_STRIDE */
+#define MME_SHADOW_0_C_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_C_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_ROI_SIZE */
+#define MME_SHADOW_0_C_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_0_C_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_SPATIAL_START_OFFSET */
+#define MME_SHADOW_0_C_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_0_C_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_SPATIAL_STRIDE */
+#define MME_SHADOW_0_C_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_0_C_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_C_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_0_C_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_0_C_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_SYNC_OBJECT_MESSAGE */
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define MME_SHADOW_0_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* MME_SHADOW_0_E_PADDING_VALUE_A */
+#define MME_SHADOW_0_E_PADDING_VALUE_A_V_SHIFT 0
+#define MME_SHADOW_0_E_PADDING_VALUE_A_V_MASK 0xFFFF
+
+/* MME_SHADOW_0_E_NUM_ITERATION_MINUS_1 */
+#define MME_SHADOW_0_E_NUM_ITERATION_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_0_E_NUM_ITERATION_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_0_E_BUBBLES_PER_SPLIT */
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_A_SHIFT 0
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_A_MASK 0xFF
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_B_SHIFT 8
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_B_MASK 0xFF00
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_CIN_SHIFT 16
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_CIN_MASK 0xFF0000
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_ID_SHIFT 24
+#define MME_SHADOW_0_E_BUBBLES_PER_SPLIT_ID_MASK 0xFF000000
+
+/* MME_SHADOW_1_STATUS */
+#define MME_SHADOW_1_STATUS_A_SHIFT 0
+#define MME_SHADOW_1_STATUS_A_MASK 0x1
+#define MME_SHADOW_1_STATUS_B_SHIFT 1
+#define MME_SHADOW_1_STATUS_B_MASK 0x2
+#define MME_SHADOW_1_STATUS_CIN_SHIFT 2
+#define MME_SHADOW_1_STATUS_CIN_MASK 0x4
+#define MME_SHADOW_1_STATUS_COUT_SHIFT 3
+#define MME_SHADOW_1_STATUS_COUT_MASK 0x8
+#define MME_SHADOW_1_STATUS_TE_SHIFT 4
+#define MME_SHADOW_1_STATUS_TE_MASK 0x10
+#define MME_SHADOW_1_STATUS_LD_SHIFT 5
+#define MME_SHADOW_1_STATUS_LD_MASK 0x20
+#define MME_SHADOW_1_STATUS_ST_SHIFT 6
+#define MME_SHADOW_1_STATUS_ST_MASK 0x40
+
+/* MME_SHADOW_1_A_BASE_ADDR_HIGH */
+#define MME_SHADOW_1_A_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_1_A_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_BASE_ADDR_HIGH */
+#define MME_SHADOW_1_B_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_1_B_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_CIN_BASE_ADDR_HIGH */
+#define MME_SHADOW_1_CIN_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_1_CIN_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_COUT_BASE_ADDR_HIGH */
+#define MME_SHADOW_1_COUT_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_1_COUT_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_BIAS_BASE_ADDR_HIGH */
+#define MME_SHADOW_1_BIAS_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_1_BIAS_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_BASE_ADDR_LOW */
+#define MME_SHADOW_1_A_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_1_A_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_BASE_ADDR_LOW */
+#define MME_SHADOW_1_B_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_1_B_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_CIN_BASE_ADDR_LOW */
+#define MME_SHADOW_1_CIN_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_1_CIN_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_COUT_BASE_ADDR_LOW */
+#define MME_SHADOW_1_COUT_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_1_COUT_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_BIAS_BASE_ADDR_LOW */
+#define MME_SHADOW_1_BIAS_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_1_BIAS_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_HEADER */
+#define MME_SHADOW_1_HEADER_SIGNAL_MASK_SHIFT 0
+#define MME_SHADOW_1_HEADER_SIGNAL_MASK_MASK 0x1F
+#define MME_SHADOW_1_HEADER_SIGNAL_EN_SHIFT 5
+#define MME_SHADOW_1_HEADER_SIGNAL_EN_MASK 0x20
+#define MME_SHADOW_1_HEADER_TRANS_A_SHIFT 6
+#define MME_SHADOW_1_HEADER_TRANS_A_MASK 0x40
+#define MME_SHADOW_1_HEADER_LOWER_A_SHIFT 7
+#define MME_SHADOW_1_HEADER_LOWER_A_MASK 0x80
+#define MME_SHADOW_1_HEADER_ACCUM_MASK_SHIFT 8
+#define MME_SHADOW_1_HEADER_ACCUM_MASK_MASK 0xF00
+#define MME_SHADOW_1_HEADER_LOAD_BIAS_SHIFT 12
+#define MME_SHADOW_1_HEADER_LOAD_BIAS_MASK 0x1000
+#define MME_SHADOW_1_HEADER_LOAD_CIN_SHIFT 13
+#define MME_SHADOW_1_HEADER_LOAD_CIN_MASK 0x2000
+#define MME_SHADOW_1_HEADER_STORE_OUT_SHIFT 15
+#define MME_SHADOW_1_HEADER_STORE_OUT_MASK 0x8000
+#define MME_SHADOW_1_HEADER_ACC_LD_INC_DISABLE_SHIFT 16
+#define MME_SHADOW_1_HEADER_ACC_LD_INC_DISABLE_MASK 0x10000
+#define MME_SHADOW_1_HEADER_ADVANCE_A_SHIFT 17
+#define MME_SHADOW_1_HEADER_ADVANCE_A_MASK 0x20000
+#define MME_SHADOW_1_HEADER_ADVANCE_B_SHIFT 18
+#define MME_SHADOW_1_HEADER_ADVANCE_B_MASK 0x40000
+#define MME_SHADOW_1_HEADER_ADVANCE_CIN_SHIFT 19
+#define MME_SHADOW_1_HEADER_ADVANCE_CIN_MASK 0x80000
+#define MME_SHADOW_1_HEADER_ADVANCE_COUT_SHIFT 20
+#define MME_SHADOW_1_HEADER_ADVANCE_COUT_MASK 0x100000
+#define MME_SHADOW_1_HEADER_COMPRESSED_B_SHIFT 21
+#define MME_SHADOW_1_HEADER_COMPRESSED_B_MASK 0x200000
+#define MME_SHADOW_1_HEADER_MASK_CONV_END_SHIFT 22
+#define MME_SHADOW_1_HEADER_MASK_CONV_END_MASK 0x400000
+#define MME_SHADOW_1_HEADER_ACC_ST_INC_DISABLE_SHIFT 23
+#define MME_SHADOW_1_HEADER_ACC_ST_INC_DISABLE_MASK 0x800000
+#define MME_SHADOW_1_HEADER_AB_DATA_TYPE_SHIFT 24
+#define MME_SHADOW_1_HEADER_AB_DATA_TYPE_MASK 0x3000000
+#define MME_SHADOW_1_HEADER_CIN_DATA_TYPE_SHIFT 26
+#define MME_SHADOW_1_HEADER_CIN_DATA_TYPE_MASK 0x1C000000
+#define MME_SHADOW_1_HEADER_COUT_DATA_TYPE_SHIFT 29
+#define MME_SHADOW_1_HEADER_COUT_DATA_TYPE_MASK 0xE0000000
+
+/* MME_SHADOW_1_KERNEL_SIZE_MINUS_1 */
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_0_SHIFT 0
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_0_MASK 0xFF
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_1_SHIFT 8
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_1_MASK 0xFF00
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_2_SHIFT 16
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_2_MASK 0xFF0000
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_3_SHIFT 24
+#define MME_SHADOW_1_KERNEL_SIZE_MINUS_1_DIM_3_MASK 0xFF000000
+
+/* MME_SHADOW_1_ASSOCIATED_DIMS */
+#define MME_SHADOW_1_ASSOCIATED_DIMS_A_0_SHIFT 0
+#define MME_SHADOW_1_ASSOCIATED_DIMS_A_0_MASK 0x7
+#define MME_SHADOW_1_ASSOCIATED_DIMS_B_0_SHIFT 3
+#define MME_SHADOW_1_ASSOCIATED_DIMS_B_0_MASK 0x38
+#define MME_SHADOW_1_ASSOCIATED_DIMS_CIN_0_SHIFT 6
+#define MME_SHADOW_1_ASSOCIATED_DIMS_CIN_0_MASK 0x1C0
+#define MME_SHADOW_1_ASSOCIATED_DIMS_COUT_0_SHIFT 9
+#define MME_SHADOW_1_ASSOCIATED_DIMS_COUT_0_MASK 0xE00
+#define MME_SHADOW_1_ASSOCIATED_DIMS_A_1_SHIFT 16
+#define MME_SHADOW_1_ASSOCIATED_DIMS_A_1_MASK 0x70000
+#define MME_SHADOW_1_ASSOCIATED_DIMS_B_1_SHIFT 19
+#define MME_SHADOW_1_ASSOCIATED_DIMS_B_1_MASK 0x380000
+#define MME_SHADOW_1_ASSOCIATED_DIMS_CIN_1_SHIFT 22
+#define MME_SHADOW_1_ASSOCIATED_DIMS_CIN_1_MASK 0x1C00000
+#define MME_SHADOW_1_ASSOCIATED_DIMS_COUT_1_SHIFT 25
+#define MME_SHADOW_1_ASSOCIATED_DIMS_COUT_1_MASK 0xE000000
+
+/* MME_SHADOW_1_COUT_SCALE */
+#define MME_SHADOW_1_COUT_SCALE_V_SHIFT 0
+#define MME_SHADOW_1_COUT_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_CIN_SCALE */
+#define MME_SHADOW_1_CIN_SCALE_V_SHIFT 0
+#define MME_SHADOW_1_CIN_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_GEMMLOWP_ZP */
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_CIN_SHIFT 0
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_CIN_MASK 0x1FF
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_COUT_SHIFT 9
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_COUT_MASK 0x3FE00
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_B_SHIFT 18
+#define MME_SHADOW_1_GEMMLOWP_ZP_ZP_B_MASK 0x7FC0000
+#define MME_SHADOW_1_GEMMLOWP_ZP_GEMMLOWP_EU_EN_SHIFT 27
+#define MME_SHADOW_1_GEMMLOWP_ZP_GEMMLOWP_EU_EN_MASK 0x8000000
+#define MME_SHADOW_1_GEMMLOWP_ZP_ACCUM_SHIFT 28
+#define MME_SHADOW_1_GEMMLOWP_ZP_ACCUM_MASK 0x10000000
+#define MME_SHADOW_1_GEMMLOWP_ZP_ACCUM_BIAS_SHIFT 29
+#define MME_SHADOW_1_GEMMLOWP_ZP_ACCUM_BIAS_MASK 0x20000000
+#define MME_SHADOW_1_GEMMLOWP_ZP_RELU_EN_SHIFT 30
+#define MME_SHADOW_1_GEMMLOWP_ZP_RELU_EN_MASK 0x40000000
+
+/* MME_SHADOW_1_GEMMLOWP_EXPONENT */
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_EXPONENT_CIN_SHIFT 0
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_EXPONENT_CIN_MASK 0x3F
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_EXPONENT_COUT_SHIFT 8
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_EXPONENT_COUT_MASK 0x3F00
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_MUL_CIN_EN_SHIFT 16
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_MUL_CIN_EN_MASK 0x10000
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_MUL_COUT_EN_SHIFT 17
+#define MME_SHADOW_1_GEMMLOWP_EXPONENT_MUL_COUT_EN_MASK 0x20000
+
+/* MME_SHADOW_1_A_ROI_BASE_OFFSET */
+#define MME_SHADOW_1_A_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_A_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_VALID_ELEMENTS */
+#define MME_SHADOW_1_A_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_1_A_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_LOOP_STRIDE */
+#define MME_SHADOW_1_A_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_A_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_ROI_SIZE */
+#define MME_SHADOW_1_A_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_1_A_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_SPATIAL_START_OFFSET */
+#define MME_SHADOW_1_A_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_A_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_SPATIAL_STRIDE */
+#define MME_SHADOW_1_A_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_A_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_A_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_1_A_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_1_A_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_ROI_BASE_OFFSET */
+#define MME_SHADOW_1_B_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_B_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_VALID_ELEMENTS */
+#define MME_SHADOW_1_B_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_1_B_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_LOOP_STRIDE */
+#define MME_SHADOW_1_B_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_B_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_ROI_SIZE */
+#define MME_SHADOW_1_B_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_1_B_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_SPATIAL_START_OFFSET */
+#define MME_SHADOW_1_B_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_B_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_SPATIAL_STRIDE */
+#define MME_SHADOW_1_B_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_B_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_B_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_1_B_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_1_B_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_ROI_BASE_OFFSET */
+#define MME_SHADOW_1_C_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_C_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_VALID_ELEMENTS */
+#define MME_SHADOW_1_C_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_1_C_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_LOOP_STRIDE */
+#define MME_SHADOW_1_C_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_C_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_ROI_SIZE */
+#define MME_SHADOW_1_C_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_1_C_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_SPATIAL_START_OFFSET */
+#define MME_SHADOW_1_C_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_1_C_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_SPATIAL_STRIDE */
+#define MME_SHADOW_1_C_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_1_C_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_C_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_1_C_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_1_C_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_SYNC_OBJECT_MESSAGE */
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define MME_SHADOW_1_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* MME_SHADOW_1_E_PADDING_VALUE_A */
+#define MME_SHADOW_1_E_PADDING_VALUE_A_V_SHIFT 0
+#define MME_SHADOW_1_E_PADDING_VALUE_A_V_MASK 0xFFFF
+
+/* MME_SHADOW_1_E_NUM_ITERATION_MINUS_1 */
+#define MME_SHADOW_1_E_NUM_ITERATION_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_1_E_NUM_ITERATION_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_1_E_BUBBLES_PER_SPLIT */
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_A_SHIFT 0
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_A_MASK 0xFF
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_B_SHIFT 8
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_B_MASK 0xFF00
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_CIN_SHIFT 16
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_CIN_MASK 0xFF0000
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_ID_SHIFT 24
+#define MME_SHADOW_1_E_BUBBLES_PER_SPLIT_ID_MASK 0xFF000000
+
+/* MME_SHADOW_2_STATUS */
+#define MME_SHADOW_2_STATUS_A_SHIFT 0
+#define MME_SHADOW_2_STATUS_A_MASK 0x1
+#define MME_SHADOW_2_STATUS_B_SHIFT 1
+#define MME_SHADOW_2_STATUS_B_MASK 0x2
+#define MME_SHADOW_2_STATUS_CIN_SHIFT 2
+#define MME_SHADOW_2_STATUS_CIN_MASK 0x4
+#define MME_SHADOW_2_STATUS_COUT_SHIFT 3
+#define MME_SHADOW_2_STATUS_COUT_MASK 0x8
+#define MME_SHADOW_2_STATUS_TE_SHIFT 4
+#define MME_SHADOW_2_STATUS_TE_MASK 0x10
+#define MME_SHADOW_2_STATUS_LD_SHIFT 5
+#define MME_SHADOW_2_STATUS_LD_MASK 0x20
+#define MME_SHADOW_2_STATUS_ST_SHIFT 6
+#define MME_SHADOW_2_STATUS_ST_MASK 0x40
+
+/* MME_SHADOW_2_A_BASE_ADDR_HIGH */
+#define MME_SHADOW_2_A_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_2_A_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_BASE_ADDR_HIGH */
+#define MME_SHADOW_2_B_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_2_B_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_CIN_BASE_ADDR_HIGH */
+#define MME_SHADOW_2_CIN_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_2_CIN_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_COUT_BASE_ADDR_HIGH */
+#define MME_SHADOW_2_COUT_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_2_COUT_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_BIAS_BASE_ADDR_HIGH */
+#define MME_SHADOW_2_BIAS_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_2_BIAS_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_BASE_ADDR_LOW */
+#define MME_SHADOW_2_A_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_2_A_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_BASE_ADDR_LOW */
+#define MME_SHADOW_2_B_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_2_B_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_CIN_BASE_ADDR_LOW */
+#define MME_SHADOW_2_CIN_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_2_CIN_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_COUT_BASE_ADDR_LOW */
+#define MME_SHADOW_2_COUT_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_2_COUT_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_BIAS_BASE_ADDR_LOW */
+#define MME_SHADOW_2_BIAS_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_2_BIAS_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_HEADER */
+#define MME_SHADOW_2_HEADER_SIGNAL_MASK_SHIFT 0
+#define MME_SHADOW_2_HEADER_SIGNAL_MASK_MASK 0x1F
+#define MME_SHADOW_2_HEADER_SIGNAL_EN_SHIFT 5
+#define MME_SHADOW_2_HEADER_SIGNAL_EN_MASK 0x20
+#define MME_SHADOW_2_HEADER_TRANS_A_SHIFT 6
+#define MME_SHADOW_2_HEADER_TRANS_A_MASK 0x40
+#define MME_SHADOW_2_HEADER_LOWER_A_SHIFT 7
+#define MME_SHADOW_2_HEADER_LOWER_A_MASK 0x80
+#define MME_SHADOW_2_HEADER_ACCUM_MASK_SHIFT 8
+#define MME_SHADOW_2_HEADER_ACCUM_MASK_MASK 0xF00
+#define MME_SHADOW_2_HEADER_LOAD_BIAS_SHIFT 12
+#define MME_SHADOW_2_HEADER_LOAD_BIAS_MASK 0x1000
+#define MME_SHADOW_2_HEADER_LOAD_CIN_SHIFT 13
+#define MME_SHADOW_2_HEADER_LOAD_CIN_MASK 0x2000
+#define MME_SHADOW_2_HEADER_STORE_OUT_SHIFT 15
+#define MME_SHADOW_2_HEADER_STORE_OUT_MASK 0x8000
+#define MME_SHADOW_2_HEADER_ACC_LD_INC_DISABLE_SHIFT 16
+#define MME_SHADOW_2_HEADER_ACC_LD_INC_DISABLE_MASK 0x10000
+#define MME_SHADOW_2_HEADER_ADVANCE_A_SHIFT 17
+#define MME_SHADOW_2_HEADER_ADVANCE_A_MASK 0x20000
+#define MME_SHADOW_2_HEADER_ADVANCE_B_SHIFT 18
+#define MME_SHADOW_2_HEADER_ADVANCE_B_MASK 0x40000
+#define MME_SHADOW_2_HEADER_ADVANCE_CIN_SHIFT 19
+#define MME_SHADOW_2_HEADER_ADVANCE_CIN_MASK 0x80000
+#define MME_SHADOW_2_HEADER_ADVANCE_COUT_SHIFT 20
+#define MME_SHADOW_2_HEADER_ADVANCE_COUT_MASK 0x100000
+#define MME_SHADOW_2_HEADER_COMPRESSED_B_SHIFT 21
+#define MME_SHADOW_2_HEADER_COMPRESSED_B_MASK 0x200000
+#define MME_SHADOW_2_HEADER_MASK_CONV_END_SHIFT 22
+#define MME_SHADOW_2_HEADER_MASK_CONV_END_MASK 0x400000
+#define MME_SHADOW_2_HEADER_ACC_ST_INC_DISABLE_SHIFT 23
+#define MME_SHADOW_2_HEADER_ACC_ST_INC_DISABLE_MASK 0x800000
+#define MME_SHADOW_2_HEADER_AB_DATA_TYPE_SHIFT 24
+#define MME_SHADOW_2_HEADER_AB_DATA_TYPE_MASK 0x3000000
+#define MME_SHADOW_2_HEADER_CIN_DATA_TYPE_SHIFT 26
+#define MME_SHADOW_2_HEADER_CIN_DATA_TYPE_MASK 0x1C000000
+#define MME_SHADOW_2_HEADER_COUT_DATA_TYPE_SHIFT 29
+#define MME_SHADOW_2_HEADER_COUT_DATA_TYPE_MASK 0xE0000000
+
+/* MME_SHADOW_2_KERNEL_SIZE_MINUS_1 */
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_0_SHIFT 0
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_0_MASK 0xFF
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_1_SHIFT 8
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_1_MASK 0xFF00
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_2_SHIFT 16
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_2_MASK 0xFF0000
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_3_SHIFT 24
+#define MME_SHADOW_2_KERNEL_SIZE_MINUS_1_DIM_3_MASK 0xFF000000
+
+/* MME_SHADOW_2_ASSOCIATED_DIMS */
+#define MME_SHADOW_2_ASSOCIATED_DIMS_A_0_SHIFT 0
+#define MME_SHADOW_2_ASSOCIATED_DIMS_A_0_MASK 0x7
+#define MME_SHADOW_2_ASSOCIATED_DIMS_B_0_SHIFT 3
+#define MME_SHADOW_2_ASSOCIATED_DIMS_B_0_MASK 0x38
+#define MME_SHADOW_2_ASSOCIATED_DIMS_CIN_0_SHIFT 6
+#define MME_SHADOW_2_ASSOCIATED_DIMS_CIN_0_MASK 0x1C0
+#define MME_SHADOW_2_ASSOCIATED_DIMS_COUT_0_SHIFT 9
+#define MME_SHADOW_2_ASSOCIATED_DIMS_COUT_0_MASK 0xE00
+#define MME_SHADOW_2_ASSOCIATED_DIMS_A_1_SHIFT 16
+#define MME_SHADOW_2_ASSOCIATED_DIMS_A_1_MASK 0x70000
+#define MME_SHADOW_2_ASSOCIATED_DIMS_B_1_SHIFT 19
+#define MME_SHADOW_2_ASSOCIATED_DIMS_B_1_MASK 0x380000
+#define MME_SHADOW_2_ASSOCIATED_DIMS_CIN_1_SHIFT 22
+#define MME_SHADOW_2_ASSOCIATED_DIMS_CIN_1_MASK 0x1C00000
+#define MME_SHADOW_2_ASSOCIATED_DIMS_COUT_1_SHIFT 25
+#define MME_SHADOW_2_ASSOCIATED_DIMS_COUT_1_MASK 0xE000000
+
+/* MME_SHADOW_2_COUT_SCALE */
+#define MME_SHADOW_2_COUT_SCALE_V_SHIFT 0
+#define MME_SHADOW_2_COUT_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_CIN_SCALE */
+#define MME_SHADOW_2_CIN_SCALE_V_SHIFT 0
+#define MME_SHADOW_2_CIN_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_GEMMLOWP_ZP */
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_CIN_SHIFT 0
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_CIN_MASK 0x1FF
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_COUT_SHIFT 9
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_COUT_MASK 0x3FE00
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_B_SHIFT 18
+#define MME_SHADOW_2_GEMMLOWP_ZP_ZP_B_MASK 0x7FC0000
+#define MME_SHADOW_2_GEMMLOWP_ZP_GEMMLOWP_EU_EN_SHIFT 27
+#define MME_SHADOW_2_GEMMLOWP_ZP_GEMMLOWP_EU_EN_MASK 0x8000000
+#define MME_SHADOW_2_GEMMLOWP_ZP_ACCUM_SHIFT 28
+#define MME_SHADOW_2_GEMMLOWP_ZP_ACCUM_MASK 0x10000000
+#define MME_SHADOW_2_GEMMLOWP_ZP_ACCUM_BIAS_SHIFT 29
+#define MME_SHADOW_2_GEMMLOWP_ZP_ACCUM_BIAS_MASK 0x20000000
+#define MME_SHADOW_2_GEMMLOWP_ZP_RELU_EN_SHIFT 30
+#define MME_SHADOW_2_GEMMLOWP_ZP_RELU_EN_MASK 0x40000000
+
+/* MME_SHADOW_2_GEMMLOWP_EXPONENT */
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_EXPONENT_CIN_SHIFT 0
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_EXPONENT_CIN_MASK 0x3F
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_EXPONENT_COUT_SHIFT 8
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_EXPONENT_COUT_MASK 0x3F00
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_MUL_CIN_EN_SHIFT 16
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_MUL_CIN_EN_MASK 0x10000
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_MUL_COUT_EN_SHIFT 17
+#define MME_SHADOW_2_GEMMLOWP_EXPONENT_MUL_COUT_EN_MASK 0x20000
+
+/* MME_SHADOW_2_A_ROI_BASE_OFFSET */
+#define MME_SHADOW_2_A_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_A_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_VALID_ELEMENTS */
+#define MME_SHADOW_2_A_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_2_A_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_LOOP_STRIDE */
+#define MME_SHADOW_2_A_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_A_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_ROI_SIZE */
+#define MME_SHADOW_2_A_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_2_A_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_SPATIAL_START_OFFSET */
+#define MME_SHADOW_2_A_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_A_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_SPATIAL_STRIDE */
+#define MME_SHADOW_2_A_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_A_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_A_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_2_A_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_2_A_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_ROI_BASE_OFFSET */
+#define MME_SHADOW_2_B_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_B_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_VALID_ELEMENTS */
+#define MME_SHADOW_2_B_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_2_B_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_LOOP_STRIDE */
+#define MME_SHADOW_2_B_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_B_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_ROI_SIZE */
+#define MME_SHADOW_2_B_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_2_B_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_SPATIAL_START_OFFSET */
+#define MME_SHADOW_2_B_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_B_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_SPATIAL_STRIDE */
+#define MME_SHADOW_2_B_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_B_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_B_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_2_B_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_2_B_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_ROI_BASE_OFFSET */
+#define MME_SHADOW_2_C_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_C_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_VALID_ELEMENTS */
+#define MME_SHADOW_2_C_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_2_C_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_LOOP_STRIDE */
+#define MME_SHADOW_2_C_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_C_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_ROI_SIZE */
+#define MME_SHADOW_2_C_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_2_C_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_SPATIAL_START_OFFSET */
+#define MME_SHADOW_2_C_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_2_C_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_SPATIAL_STRIDE */
+#define MME_SHADOW_2_C_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_2_C_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_C_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_2_C_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_2_C_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_SYNC_OBJECT_MESSAGE */
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define MME_SHADOW_2_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* MME_SHADOW_2_E_PADDING_VALUE_A */
+#define MME_SHADOW_2_E_PADDING_VALUE_A_V_SHIFT 0
+#define MME_SHADOW_2_E_PADDING_VALUE_A_V_MASK 0xFFFF
+
+/* MME_SHADOW_2_E_NUM_ITERATION_MINUS_1 */
+#define MME_SHADOW_2_E_NUM_ITERATION_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_2_E_NUM_ITERATION_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_2_E_BUBBLES_PER_SPLIT */
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_A_SHIFT 0
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_A_MASK 0xFF
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_B_SHIFT 8
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_B_MASK 0xFF00
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_CIN_SHIFT 16
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_CIN_MASK 0xFF0000
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_ID_SHIFT 24
+#define MME_SHADOW_2_E_BUBBLES_PER_SPLIT_ID_MASK 0xFF000000
+
+/* MME_SHADOW_3_STATUS */
+#define MME_SHADOW_3_STATUS_A_SHIFT 0
+#define MME_SHADOW_3_STATUS_A_MASK 0x1
+#define MME_SHADOW_3_STATUS_B_SHIFT 1
+#define MME_SHADOW_3_STATUS_B_MASK 0x2
+#define MME_SHADOW_3_STATUS_CIN_SHIFT 2
+#define MME_SHADOW_3_STATUS_CIN_MASK 0x4
+#define MME_SHADOW_3_STATUS_COUT_SHIFT 3
+#define MME_SHADOW_3_STATUS_COUT_MASK 0x8
+#define MME_SHADOW_3_STATUS_TE_SHIFT 4
+#define MME_SHADOW_3_STATUS_TE_MASK 0x10
+#define MME_SHADOW_3_STATUS_LD_SHIFT 5
+#define MME_SHADOW_3_STATUS_LD_MASK 0x20
+#define MME_SHADOW_3_STATUS_ST_SHIFT 6
+#define MME_SHADOW_3_STATUS_ST_MASK 0x40
+
+/* MME_SHADOW_3_A_BASE_ADDR_HIGH */
+#define MME_SHADOW_3_A_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_3_A_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_BASE_ADDR_HIGH */
+#define MME_SHADOW_3_B_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_3_B_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_CIN_BASE_ADDR_HIGH */
+#define MME_SHADOW_3_CIN_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_3_CIN_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_COUT_BASE_ADDR_HIGH */
+#define MME_SHADOW_3_COUT_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_3_COUT_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_BIAS_BASE_ADDR_HIGH */
+#define MME_SHADOW_3_BIAS_BASE_ADDR_HIGH_V_SHIFT 0
+#define MME_SHADOW_3_BIAS_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_BASE_ADDR_LOW */
+#define MME_SHADOW_3_A_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_3_A_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_BASE_ADDR_LOW */
+#define MME_SHADOW_3_B_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_3_B_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_CIN_BASE_ADDR_LOW */
+#define MME_SHADOW_3_CIN_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_3_CIN_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_COUT_BASE_ADDR_LOW */
+#define MME_SHADOW_3_COUT_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_3_COUT_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_BIAS_BASE_ADDR_LOW */
+#define MME_SHADOW_3_BIAS_BASE_ADDR_LOW_V_SHIFT 0
+#define MME_SHADOW_3_BIAS_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_HEADER */
+#define MME_SHADOW_3_HEADER_SIGNAL_MASK_SHIFT 0
+#define MME_SHADOW_3_HEADER_SIGNAL_MASK_MASK 0x1F
+#define MME_SHADOW_3_HEADER_SIGNAL_EN_SHIFT 5
+#define MME_SHADOW_3_HEADER_SIGNAL_EN_MASK 0x20
+#define MME_SHADOW_3_HEADER_TRANS_A_SHIFT 6
+#define MME_SHADOW_3_HEADER_TRANS_A_MASK 0x40
+#define MME_SHADOW_3_HEADER_LOWER_A_SHIFT 7
+#define MME_SHADOW_3_HEADER_LOWER_A_MASK 0x80
+#define MME_SHADOW_3_HEADER_ACCUM_MASK_SHIFT 8
+#define MME_SHADOW_3_HEADER_ACCUM_MASK_MASK 0xF00
+#define MME_SHADOW_3_HEADER_LOAD_BIAS_SHIFT 12
+#define MME_SHADOW_3_HEADER_LOAD_BIAS_MASK 0x1000
+#define MME_SHADOW_3_HEADER_LOAD_CIN_SHIFT 13
+#define MME_SHADOW_3_HEADER_LOAD_CIN_MASK 0x2000
+#define MME_SHADOW_3_HEADER_STORE_OUT_SHIFT 15
+#define MME_SHADOW_3_HEADER_STORE_OUT_MASK 0x8000
+#define MME_SHADOW_3_HEADER_ACC_LD_INC_DISABLE_SHIFT 16
+#define MME_SHADOW_3_HEADER_ACC_LD_INC_DISABLE_MASK 0x10000
+#define MME_SHADOW_3_HEADER_ADVANCE_A_SHIFT 17
+#define MME_SHADOW_3_HEADER_ADVANCE_A_MASK 0x20000
+#define MME_SHADOW_3_HEADER_ADVANCE_B_SHIFT 18
+#define MME_SHADOW_3_HEADER_ADVANCE_B_MASK 0x40000
+#define MME_SHADOW_3_HEADER_ADVANCE_CIN_SHIFT 19
+#define MME_SHADOW_3_HEADER_ADVANCE_CIN_MASK 0x80000
+#define MME_SHADOW_3_HEADER_ADVANCE_COUT_SHIFT 20
+#define MME_SHADOW_3_HEADER_ADVANCE_COUT_MASK 0x100000
+#define MME_SHADOW_3_HEADER_COMPRESSED_B_SHIFT 21
+#define MME_SHADOW_3_HEADER_COMPRESSED_B_MASK 0x200000
+#define MME_SHADOW_3_HEADER_MASK_CONV_END_SHIFT 22
+#define MME_SHADOW_3_HEADER_MASK_CONV_END_MASK 0x400000
+#define MME_SHADOW_3_HEADER_ACC_ST_INC_DISABLE_SHIFT 23
+#define MME_SHADOW_3_HEADER_ACC_ST_INC_DISABLE_MASK 0x800000
+#define MME_SHADOW_3_HEADER_AB_DATA_TYPE_SHIFT 24
+#define MME_SHADOW_3_HEADER_AB_DATA_TYPE_MASK 0x3000000
+#define MME_SHADOW_3_HEADER_CIN_DATA_TYPE_SHIFT 26
+#define MME_SHADOW_3_HEADER_CIN_DATA_TYPE_MASK 0x1C000000
+#define MME_SHADOW_3_HEADER_COUT_DATA_TYPE_SHIFT 29
+#define MME_SHADOW_3_HEADER_COUT_DATA_TYPE_MASK 0xE0000000
+
+/* MME_SHADOW_3_KERNEL_SIZE_MINUS_1 */
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_0_SHIFT 0
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_0_MASK 0xFF
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_1_SHIFT 8
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_1_MASK 0xFF00
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_2_SHIFT 16
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_2_MASK 0xFF0000
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_3_SHIFT 24
+#define MME_SHADOW_3_KERNEL_SIZE_MINUS_1_DIM_3_MASK 0xFF000000
+
+/* MME_SHADOW_3_ASSOCIATED_DIMS */
+#define MME_SHADOW_3_ASSOCIATED_DIMS_A_0_SHIFT 0
+#define MME_SHADOW_3_ASSOCIATED_DIMS_A_0_MASK 0x7
+#define MME_SHADOW_3_ASSOCIATED_DIMS_B_0_SHIFT 3
+#define MME_SHADOW_3_ASSOCIATED_DIMS_B_0_MASK 0x38
+#define MME_SHADOW_3_ASSOCIATED_DIMS_CIN_0_SHIFT 6
+#define MME_SHADOW_3_ASSOCIATED_DIMS_CIN_0_MASK 0x1C0
+#define MME_SHADOW_3_ASSOCIATED_DIMS_COUT_0_SHIFT 9
+#define MME_SHADOW_3_ASSOCIATED_DIMS_COUT_0_MASK 0xE00
+#define MME_SHADOW_3_ASSOCIATED_DIMS_A_1_SHIFT 16
+#define MME_SHADOW_3_ASSOCIATED_DIMS_A_1_MASK 0x70000
+#define MME_SHADOW_3_ASSOCIATED_DIMS_B_1_SHIFT 19
+#define MME_SHADOW_3_ASSOCIATED_DIMS_B_1_MASK 0x380000
+#define MME_SHADOW_3_ASSOCIATED_DIMS_CIN_1_SHIFT 22
+#define MME_SHADOW_3_ASSOCIATED_DIMS_CIN_1_MASK 0x1C00000
+#define MME_SHADOW_3_ASSOCIATED_DIMS_COUT_1_SHIFT 25
+#define MME_SHADOW_3_ASSOCIATED_DIMS_COUT_1_MASK 0xE000000
+
+/* MME_SHADOW_3_COUT_SCALE */
+#define MME_SHADOW_3_COUT_SCALE_V_SHIFT 0
+#define MME_SHADOW_3_COUT_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_CIN_SCALE */
+#define MME_SHADOW_3_CIN_SCALE_V_SHIFT 0
+#define MME_SHADOW_3_CIN_SCALE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_GEMMLOWP_ZP */
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_CIN_SHIFT 0
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_CIN_MASK 0x1FF
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_COUT_SHIFT 9
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_COUT_MASK 0x3FE00
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_B_SHIFT 18
+#define MME_SHADOW_3_GEMMLOWP_ZP_ZP_B_MASK 0x7FC0000
+#define MME_SHADOW_3_GEMMLOWP_ZP_GEMMLOWP_EU_EN_SHIFT 27
+#define MME_SHADOW_3_GEMMLOWP_ZP_GEMMLOWP_EU_EN_MASK 0x8000000
+#define MME_SHADOW_3_GEMMLOWP_ZP_ACCUM_SHIFT 28
+#define MME_SHADOW_3_GEMMLOWP_ZP_ACCUM_MASK 0x10000000
+#define MME_SHADOW_3_GEMMLOWP_ZP_ACCUM_BIAS_SHIFT 29
+#define MME_SHADOW_3_GEMMLOWP_ZP_ACCUM_BIAS_MASK 0x20000000
+#define MME_SHADOW_3_GEMMLOWP_ZP_RELU_EN_SHIFT 30
+#define MME_SHADOW_3_GEMMLOWP_ZP_RELU_EN_MASK 0x40000000
+
+/* MME_SHADOW_3_GEMMLOWP_EXPONENT */
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_EXPONENT_CIN_SHIFT 0
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_EXPONENT_CIN_MASK 0x3F
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_EXPONENT_COUT_SHIFT 8
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_EXPONENT_COUT_MASK 0x3F00
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_MUL_CIN_EN_SHIFT 16
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_MUL_CIN_EN_MASK 0x10000
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_MUL_COUT_EN_SHIFT 17
+#define MME_SHADOW_3_GEMMLOWP_EXPONENT_MUL_COUT_EN_MASK 0x20000
+
+/* MME_SHADOW_3_A_ROI_BASE_OFFSET */
+#define MME_SHADOW_3_A_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_A_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_VALID_ELEMENTS */
+#define MME_SHADOW_3_A_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_3_A_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_LOOP_STRIDE */
+#define MME_SHADOW_3_A_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_A_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_ROI_SIZE */
+#define MME_SHADOW_3_A_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_3_A_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_SPATIAL_START_OFFSET */
+#define MME_SHADOW_3_A_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_A_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_SPATIAL_STRIDE */
+#define MME_SHADOW_3_A_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_A_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_A_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_3_A_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_3_A_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_ROI_BASE_OFFSET */
+#define MME_SHADOW_3_B_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_B_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_VALID_ELEMENTS */
+#define MME_SHADOW_3_B_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_3_B_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_LOOP_STRIDE */
+#define MME_SHADOW_3_B_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_B_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_ROI_SIZE */
+#define MME_SHADOW_3_B_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_3_B_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_SPATIAL_START_OFFSET */
+#define MME_SHADOW_3_B_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_B_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_SPATIAL_STRIDE */
+#define MME_SHADOW_3_B_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_B_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_B_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_3_B_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_3_B_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_ROI_BASE_OFFSET */
+#define MME_SHADOW_3_C_ROI_BASE_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_C_ROI_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_VALID_ELEMENTS */
+#define MME_SHADOW_3_C_VALID_ELEMENTS_V_SHIFT 0
+#define MME_SHADOW_3_C_VALID_ELEMENTS_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_LOOP_STRIDE */
+#define MME_SHADOW_3_C_LOOP_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_C_LOOP_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_ROI_SIZE */
+#define MME_SHADOW_3_C_ROI_SIZE_V_SHIFT 0
+#define MME_SHADOW_3_C_ROI_SIZE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_SPATIAL_START_OFFSET */
+#define MME_SHADOW_3_C_SPATIAL_START_OFFSET_V_SHIFT 0
+#define MME_SHADOW_3_C_SPATIAL_START_OFFSET_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_SPATIAL_STRIDE */
+#define MME_SHADOW_3_C_SPATIAL_STRIDE_V_SHIFT 0
+#define MME_SHADOW_3_C_SPATIAL_STRIDE_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_C_SPATIAL_SIZE_MINUS_1 */
+#define MME_SHADOW_3_C_SPATIAL_SIZE_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_3_C_SPATIAL_SIZE_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_SYNC_OBJECT_MESSAGE */
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define MME_SHADOW_3_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* MME_SHADOW_3_E_PADDING_VALUE_A */
+#define MME_SHADOW_3_E_PADDING_VALUE_A_V_SHIFT 0
+#define MME_SHADOW_3_E_PADDING_VALUE_A_V_MASK 0xFFFF
+
+/* MME_SHADOW_3_E_NUM_ITERATION_MINUS_1 */
+#define MME_SHADOW_3_E_NUM_ITERATION_MINUS_1_V_SHIFT 0
+#define MME_SHADOW_3_E_NUM_ITERATION_MINUS_1_V_MASK 0xFFFFFFFF
+
+/* MME_SHADOW_3_E_BUBBLES_PER_SPLIT */
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_A_SHIFT 0
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_A_MASK 0xFF
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_B_SHIFT 8
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_B_MASK 0xFF00
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_CIN_SHIFT 16
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_CIN_MASK 0xFF0000
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_ID_SHIFT 24
+#define MME_SHADOW_3_E_BUBBLES_PER_SPLIT_ID_MASK 0xFF000000
+
+#endif /* ASIC_REG_MME_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h
new file mode 100644
index 000000000000..d4bfa58dce19
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_masks.h
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_QM_MASKS_H_
+#define ASIC_REG_MME_QM_MASKS_H_
+
+/*
+ *****************************************
+ * MME_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+/* MME_QM_GLBL_CFG0 */
+#define MME_QM_GLBL_CFG0_PQF_EN_SHIFT 0
+#define MME_QM_GLBL_CFG0_PQF_EN_MASK 0x1
+#define MME_QM_GLBL_CFG0_CQF_EN_SHIFT 1
+#define MME_QM_GLBL_CFG0_CQF_EN_MASK 0x2
+#define MME_QM_GLBL_CFG0_CP_EN_SHIFT 2
+#define MME_QM_GLBL_CFG0_CP_EN_MASK 0x4
+#define MME_QM_GLBL_CFG0_DMA_EN_SHIFT 3
+#define MME_QM_GLBL_CFG0_DMA_EN_MASK 0x8
+
+/* MME_QM_GLBL_CFG1 */
+#define MME_QM_GLBL_CFG1_PQF_STOP_SHIFT 0
+#define MME_QM_GLBL_CFG1_PQF_STOP_MASK 0x1
+#define MME_QM_GLBL_CFG1_CQF_STOP_SHIFT 1
+#define MME_QM_GLBL_CFG1_CQF_STOP_MASK 0x2
+#define MME_QM_GLBL_CFG1_CP_STOP_SHIFT 2
+#define MME_QM_GLBL_CFG1_CP_STOP_MASK 0x4
+#define MME_QM_GLBL_CFG1_DMA_STOP_SHIFT 3
+#define MME_QM_GLBL_CFG1_DMA_STOP_MASK 0x8
+#define MME_QM_GLBL_CFG1_PQF_FLUSH_SHIFT 8
+#define MME_QM_GLBL_CFG1_PQF_FLUSH_MASK 0x100
+#define MME_QM_GLBL_CFG1_CQF_FLUSH_SHIFT 9
+#define MME_QM_GLBL_CFG1_CQF_FLUSH_MASK 0x200
+#define MME_QM_GLBL_CFG1_CP_FLUSH_SHIFT 10
+#define MME_QM_GLBL_CFG1_CP_FLUSH_MASK 0x400
+#define MME_QM_GLBL_CFG1_DMA_FLUSH_SHIFT 11
+#define MME_QM_GLBL_CFG1_DMA_FLUSH_MASK 0x800
+
+/* MME_QM_GLBL_PROT */
+#define MME_QM_GLBL_PROT_PQF_PROT_SHIFT 0
+#define MME_QM_GLBL_PROT_PQF_PROT_MASK 0x1
+#define MME_QM_GLBL_PROT_CQF_PROT_SHIFT 1
+#define MME_QM_GLBL_PROT_CQF_PROT_MASK 0x2
+#define MME_QM_GLBL_PROT_CP_PROT_SHIFT 2
+#define MME_QM_GLBL_PROT_CP_PROT_MASK 0x4
+#define MME_QM_GLBL_PROT_DMA_PROT_SHIFT 3
+#define MME_QM_GLBL_PROT_DMA_PROT_MASK 0x8
+#define MME_QM_GLBL_PROT_PQF_ERR_PROT_SHIFT 4
+#define MME_QM_GLBL_PROT_PQF_ERR_PROT_MASK 0x10
+#define MME_QM_GLBL_PROT_CQF_ERR_PROT_SHIFT 5
+#define MME_QM_GLBL_PROT_CQF_ERR_PROT_MASK 0x20
+#define MME_QM_GLBL_PROT_CP_ERR_PROT_SHIFT 6
+#define MME_QM_GLBL_PROT_CP_ERR_PROT_MASK 0x40
+#define MME_QM_GLBL_PROT_DMA_ERR_PROT_SHIFT 7
+#define MME_QM_GLBL_PROT_DMA_ERR_PROT_MASK 0x80
+
+/* MME_QM_GLBL_ERR_CFG */
+#define MME_QM_GLBL_ERR_CFG_PQF_ERR_INT_EN_SHIFT 0
+#define MME_QM_GLBL_ERR_CFG_PQF_ERR_INT_EN_MASK 0x1
+#define MME_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT 1
+#define MME_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK 0x2
+#define MME_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT 2
+#define MME_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK 0x4
+#define MME_QM_GLBL_ERR_CFG_CQF_ERR_INT_EN_SHIFT 3
+#define MME_QM_GLBL_ERR_CFG_CQF_ERR_INT_EN_MASK 0x8
+#define MME_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT 4
+#define MME_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_MASK 0x10
+#define MME_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT 5
+#define MME_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK 0x20
+#define MME_QM_GLBL_ERR_CFG_CP_ERR_INT_EN_SHIFT 6
+#define MME_QM_GLBL_ERR_CFG_CP_ERR_INT_EN_MASK 0x40
+#define MME_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT 7
+#define MME_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_MASK 0x80
+#define MME_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT 8
+#define MME_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK 0x100
+#define MME_QM_GLBL_ERR_CFG_DMA_ERR_INT_EN_SHIFT 9
+#define MME_QM_GLBL_ERR_CFG_DMA_ERR_INT_EN_MASK 0x200
+#define MME_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT 10
+#define MME_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_MASK 0x400
+#define MME_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT 11
+#define MME_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_MASK 0x800
+
+/* MME_QM_GLBL_ERR_ADDR_LO */
+#define MME_QM_GLBL_ERR_ADDR_LO_VAL_SHIFT 0
+#define MME_QM_GLBL_ERR_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_GLBL_ERR_ADDR_HI */
+#define MME_QM_GLBL_ERR_ADDR_HI_VAL_SHIFT 0
+#define MME_QM_GLBL_ERR_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_GLBL_ERR_WDATA */
+#define MME_QM_GLBL_ERR_WDATA_VAL_SHIFT 0
+#define MME_QM_GLBL_ERR_WDATA_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_GLBL_SECURE_PROPS */
+#define MME_QM_GLBL_SECURE_PROPS_ASID_SHIFT 0
+#define MME_QM_GLBL_SECURE_PROPS_ASID_MASK 0x3FF
+#define MME_QM_GLBL_SECURE_PROPS_MMBP_SHIFT 10
+#define MME_QM_GLBL_SECURE_PROPS_MMBP_MASK 0x400
+
+/* MME_QM_GLBL_NON_SECURE_PROPS */
+#define MME_QM_GLBL_NON_SECURE_PROPS_ASID_SHIFT 0
+#define MME_QM_GLBL_NON_SECURE_PROPS_ASID_MASK 0x3FF
+#define MME_QM_GLBL_NON_SECURE_PROPS_MMBP_SHIFT 10
+#define MME_QM_GLBL_NON_SECURE_PROPS_MMBP_MASK 0x400
+
+/* MME_QM_GLBL_STS0 */
+#define MME_QM_GLBL_STS0_PQF_IDLE_SHIFT 0
+#define MME_QM_GLBL_STS0_PQF_IDLE_MASK 0x1
+#define MME_QM_GLBL_STS0_CQF_IDLE_SHIFT 1
+#define MME_QM_GLBL_STS0_CQF_IDLE_MASK 0x2
+#define MME_QM_GLBL_STS0_CP_IDLE_SHIFT 2
+#define MME_QM_GLBL_STS0_CP_IDLE_MASK 0x4
+#define MME_QM_GLBL_STS0_DMA_IDLE_SHIFT 3
+#define MME_QM_GLBL_STS0_DMA_IDLE_MASK 0x8
+#define MME_QM_GLBL_STS0_PQF_IS_STOP_SHIFT 4
+#define MME_QM_GLBL_STS0_PQF_IS_STOP_MASK 0x10
+#define MME_QM_GLBL_STS0_CQF_IS_STOP_SHIFT 5
+#define MME_QM_GLBL_STS0_CQF_IS_STOP_MASK 0x20
+#define MME_QM_GLBL_STS0_CP_IS_STOP_SHIFT 6
+#define MME_QM_GLBL_STS0_CP_IS_STOP_MASK 0x40
+#define MME_QM_GLBL_STS0_DMA_IS_STOP_SHIFT 7
+#define MME_QM_GLBL_STS0_DMA_IS_STOP_MASK 0x80
+
+/* MME_QM_GLBL_STS1 */
+#define MME_QM_GLBL_STS1_PQF_RD_ERR_SHIFT 0
+#define MME_QM_GLBL_STS1_PQF_RD_ERR_MASK 0x1
+#define MME_QM_GLBL_STS1_CQF_RD_ERR_SHIFT 1
+#define MME_QM_GLBL_STS1_CQF_RD_ERR_MASK 0x2
+#define MME_QM_GLBL_STS1_CP_RD_ERR_SHIFT 2
+#define MME_QM_GLBL_STS1_CP_RD_ERR_MASK 0x4
+#define MME_QM_GLBL_STS1_CP_UNDEF_CMD_ERR_SHIFT 3
+#define MME_QM_GLBL_STS1_CP_UNDEF_CMD_ERR_MASK 0x8
+#define MME_QM_GLBL_STS1_CP_STOP_OP_SHIFT 4
+#define MME_QM_GLBL_STS1_CP_STOP_OP_MASK 0x10
+#define MME_QM_GLBL_STS1_CP_MSG_WR_ERR_SHIFT 5
+#define MME_QM_GLBL_STS1_CP_MSG_WR_ERR_MASK 0x20
+#define MME_QM_GLBL_STS1_DMA_RD_ERR_SHIFT 8
+#define MME_QM_GLBL_STS1_DMA_RD_ERR_MASK 0x100
+#define MME_QM_GLBL_STS1_DMA_WR_ERR_SHIFT 9
+#define MME_QM_GLBL_STS1_DMA_WR_ERR_MASK 0x200
+#define MME_QM_GLBL_STS1_DMA_RD_MSG_ERR_SHIFT 10
+#define MME_QM_GLBL_STS1_DMA_RD_MSG_ERR_MASK 0x400
+#define MME_QM_GLBL_STS1_DMA_WR_MSG_ERR_SHIFT 11
+#define MME_QM_GLBL_STS1_DMA_WR_MSG_ERR_MASK 0x800
+
+/* MME_QM_PQ_BASE_LO */
+#define MME_QM_PQ_BASE_LO_VAL_SHIFT 0
+#define MME_QM_PQ_BASE_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_BASE_HI */
+#define MME_QM_PQ_BASE_HI_VAL_SHIFT 0
+#define MME_QM_PQ_BASE_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_SIZE */
+#define MME_QM_PQ_SIZE_VAL_SHIFT 0
+#define MME_QM_PQ_SIZE_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_PI */
+#define MME_QM_PQ_PI_VAL_SHIFT 0
+#define MME_QM_PQ_PI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_CI */
+#define MME_QM_PQ_CI_VAL_SHIFT 0
+#define MME_QM_PQ_CI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_CFG0 */
+#define MME_QM_PQ_CFG0_RESERVED_SHIFT 0
+#define MME_QM_PQ_CFG0_RESERVED_MASK 0x1
+
+/* MME_QM_PQ_CFG1 */
+#define MME_QM_PQ_CFG1_CREDIT_LIM_SHIFT 0
+#define MME_QM_PQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define MME_QM_PQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define MME_QM_PQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* MME_QM_PQ_ARUSER */
+#define MME_QM_PQ_ARUSER_NOSNOOP_SHIFT 0
+#define MME_QM_PQ_ARUSER_NOSNOOP_MASK 0x1
+#define MME_QM_PQ_ARUSER_WORD_SHIFT 1
+#define MME_QM_PQ_ARUSER_WORD_MASK 0x2
+
+/* MME_QM_PQ_PUSH0 */
+#define MME_QM_PQ_PUSH0_PTR_LO_SHIFT 0
+#define MME_QM_PQ_PUSH0_PTR_LO_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_PUSH1 */
+#define MME_QM_PQ_PUSH1_PTR_HI_SHIFT 0
+#define MME_QM_PQ_PUSH1_PTR_HI_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_PUSH2 */
+#define MME_QM_PQ_PUSH2_TSIZE_SHIFT 0
+#define MME_QM_PQ_PUSH2_TSIZE_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_PUSH3 */
+#define MME_QM_PQ_PUSH3_RPT_SHIFT 0
+#define MME_QM_PQ_PUSH3_RPT_MASK 0xFFFF
+#define MME_QM_PQ_PUSH3_CTL_SHIFT 16
+#define MME_QM_PQ_PUSH3_CTL_MASK 0xFFFF0000
+
+/* MME_QM_PQ_STS0 */
+#define MME_QM_PQ_STS0_PQ_CREDIT_CNT_SHIFT 0
+#define MME_QM_PQ_STS0_PQ_CREDIT_CNT_MASK 0xFFFF
+#define MME_QM_PQ_STS0_PQ_FREE_CNT_SHIFT 16
+#define MME_QM_PQ_STS0_PQ_FREE_CNT_MASK 0xFFFF0000
+
+/* MME_QM_PQ_STS1 */
+#define MME_QM_PQ_STS1_PQ_INFLIGHT_CNT_SHIFT 0
+#define MME_QM_PQ_STS1_PQ_INFLIGHT_CNT_MASK 0xFFFF
+#define MME_QM_PQ_STS1_PQ_BUF_EMPTY_SHIFT 30
+#define MME_QM_PQ_STS1_PQ_BUF_EMPTY_MASK 0x40000000
+#define MME_QM_PQ_STS1_PQ_BUSY_SHIFT 31
+#define MME_QM_PQ_STS1_PQ_BUSY_MASK 0x80000000
+
+/* MME_QM_PQ_RD_RATE_LIM_EN */
+#define MME_QM_PQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define MME_QM_PQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* MME_QM_PQ_RD_RATE_LIM_RST_TOKEN */
+#define MME_QM_PQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define MME_QM_PQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* MME_QM_PQ_RD_RATE_LIM_SAT */
+#define MME_QM_PQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define MME_QM_PQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* MME_QM_PQ_RD_RATE_LIM_TOUT */
+#define MME_QM_PQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define MME_QM_PQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* MME_QM_CQ_CFG0 */
+#define MME_QM_CQ_CFG0_RESERVED_SHIFT 0
+#define MME_QM_CQ_CFG0_RESERVED_MASK 0x1
+
+/* MME_QM_CQ_CFG1 */
+#define MME_QM_CQ_CFG1_CREDIT_LIM_SHIFT 0
+#define MME_QM_CQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define MME_QM_CQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define MME_QM_CQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* MME_QM_CQ_ARUSER */
+#define MME_QM_CQ_ARUSER_NOSNOOP_SHIFT 0
+#define MME_QM_CQ_ARUSER_NOSNOOP_MASK 0x1
+#define MME_QM_CQ_ARUSER_WORD_SHIFT 1
+#define MME_QM_CQ_ARUSER_WORD_MASK 0x2
+
+/* MME_QM_CQ_PTR_LO */
+#define MME_QM_CQ_PTR_LO_VAL_SHIFT 0
+#define MME_QM_CQ_PTR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_PTR_HI */
+#define MME_QM_CQ_PTR_HI_VAL_SHIFT 0
+#define MME_QM_CQ_PTR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_TSIZE */
+#define MME_QM_CQ_TSIZE_VAL_SHIFT 0
+#define MME_QM_CQ_TSIZE_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_CTL */
+#define MME_QM_CQ_CTL_RPT_SHIFT 0
+#define MME_QM_CQ_CTL_RPT_MASK 0xFFFF
+#define MME_QM_CQ_CTL_CTL_SHIFT 16
+#define MME_QM_CQ_CTL_CTL_MASK 0xFFFF0000
+
+/* MME_QM_CQ_PTR_LO_STS */
+#define MME_QM_CQ_PTR_LO_STS_VAL_SHIFT 0
+#define MME_QM_CQ_PTR_LO_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_PTR_HI_STS */
+#define MME_QM_CQ_PTR_HI_STS_VAL_SHIFT 0
+#define MME_QM_CQ_PTR_HI_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_TSIZE_STS */
+#define MME_QM_CQ_TSIZE_STS_VAL_SHIFT 0
+#define MME_QM_CQ_TSIZE_STS_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_CTL_STS */
+#define MME_QM_CQ_CTL_STS_RPT_SHIFT 0
+#define MME_QM_CQ_CTL_STS_RPT_MASK 0xFFFF
+#define MME_QM_CQ_CTL_STS_CTL_SHIFT 16
+#define MME_QM_CQ_CTL_STS_CTL_MASK 0xFFFF0000
+
+/* MME_QM_CQ_STS0 */
+#define MME_QM_CQ_STS0_CQ_CREDIT_CNT_SHIFT 0
+#define MME_QM_CQ_STS0_CQ_CREDIT_CNT_MASK 0xFFFF
+#define MME_QM_CQ_STS0_CQ_FREE_CNT_SHIFT 16
+#define MME_QM_CQ_STS0_CQ_FREE_CNT_MASK 0xFFFF0000
+
+/* MME_QM_CQ_STS1 */
+#define MME_QM_CQ_STS1_CQ_INFLIGHT_CNT_SHIFT 0
+#define MME_QM_CQ_STS1_CQ_INFLIGHT_CNT_MASK 0xFFFF
+#define MME_QM_CQ_STS1_CQ_BUF_EMPTY_SHIFT 30
+#define MME_QM_CQ_STS1_CQ_BUF_EMPTY_MASK 0x40000000
+#define MME_QM_CQ_STS1_CQ_BUSY_SHIFT 31
+#define MME_QM_CQ_STS1_CQ_BUSY_MASK 0x80000000
+
+/* MME_QM_CQ_RD_RATE_LIM_EN */
+#define MME_QM_CQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define MME_QM_CQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* MME_QM_CQ_RD_RATE_LIM_RST_TOKEN */
+#define MME_QM_CQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define MME_QM_CQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* MME_QM_CQ_RD_RATE_LIM_SAT */
+#define MME_QM_CQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define MME_QM_CQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* MME_QM_CQ_RD_RATE_LIM_TOUT */
+#define MME_QM_CQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define MME_QM_CQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* MME_QM_CQ_IFIFO_CNT */
+#define MME_QM_CQ_IFIFO_CNT_VAL_SHIFT 0
+#define MME_QM_CQ_IFIFO_CNT_VAL_MASK 0x3
+
+/* MME_QM_CP_MSG_BASE0_ADDR_LO */
+#define MME_QM_CP_MSG_BASE0_ADDR_LO_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE0_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE0_ADDR_HI */
+#define MME_QM_CP_MSG_BASE0_ADDR_HI_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE0_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE1_ADDR_LO */
+#define MME_QM_CP_MSG_BASE1_ADDR_LO_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE1_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE1_ADDR_HI */
+#define MME_QM_CP_MSG_BASE1_ADDR_HI_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE1_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE2_ADDR_LO */
+#define MME_QM_CP_MSG_BASE2_ADDR_LO_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE2_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE2_ADDR_HI */
+#define MME_QM_CP_MSG_BASE2_ADDR_HI_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE2_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE3_ADDR_LO */
+#define MME_QM_CP_MSG_BASE3_ADDR_LO_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE3_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_MSG_BASE3_ADDR_HI */
+#define MME_QM_CP_MSG_BASE3_ADDR_HI_VAL_SHIFT 0
+#define MME_QM_CP_MSG_BASE3_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_TSIZE_OFFSET */
+#define MME_QM_CP_LDMA_TSIZE_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_TSIZE_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_SRC_BASE_LO_OFFSET */
+#define MME_QM_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_SRC_BASE_HI_OFFSET */
+#define MME_QM_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_DST_BASE_LO_OFFSET */
+#define MME_QM_CP_LDMA_DST_BASE_LO_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_DST_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_DST_BASE_HI_OFFSET */
+#define MME_QM_CP_LDMA_DST_BASE_HI_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_DST_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_LDMA_COMMIT_OFFSET */
+#define MME_QM_CP_LDMA_COMMIT_OFFSET_VAL_SHIFT 0
+#define MME_QM_CP_LDMA_COMMIT_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_FENCE0_RDATA */
+#define MME_QM_CP_FENCE0_RDATA_INC_VAL_SHIFT 0
+#define MME_QM_CP_FENCE0_RDATA_INC_VAL_MASK 0xF
+
+/* MME_QM_CP_FENCE1_RDATA */
+#define MME_QM_CP_FENCE1_RDATA_INC_VAL_SHIFT 0
+#define MME_QM_CP_FENCE1_RDATA_INC_VAL_MASK 0xF
+
+/* MME_QM_CP_FENCE2_RDATA */
+#define MME_QM_CP_FENCE2_RDATA_INC_VAL_SHIFT 0
+#define MME_QM_CP_FENCE2_RDATA_INC_VAL_MASK 0xF
+
+/* MME_QM_CP_FENCE3_RDATA */
+#define MME_QM_CP_FENCE3_RDATA_INC_VAL_SHIFT 0
+#define MME_QM_CP_FENCE3_RDATA_INC_VAL_MASK 0xF
+
+/* MME_QM_CP_FENCE0_CNT */
+#define MME_QM_CP_FENCE0_CNT_VAL_SHIFT 0
+#define MME_QM_CP_FENCE0_CNT_VAL_MASK 0xFF
+
+/* MME_QM_CP_FENCE1_CNT */
+#define MME_QM_CP_FENCE1_CNT_VAL_SHIFT 0
+#define MME_QM_CP_FENCE1_CNT_VAL_MASK 0xFF
+
+/* MME_QM_CP_FENCE2_CNT */
+#define MME_QM_CP_FENCE2_CNT_VAL_SHIFT 0
+#define MME_QM_CP_FENCE2_CNT_VAL_MASK 0xFF
+
+/* MME_QM_CP_FENCE3_CNT */
+#define MME_QM_CP_FENCE3_CNT_VAL_SHIFT 0
+#define MME_QM_CP_FENCE3_CNT_VAL_MASK 0xFF
+
+/* MME_QM_CP_STS */
+#define MME_QM_CP_STS_MSG_INFLIGHT_CNT_SHIFT 0
+#define MME_QM_CP_STS_MSG_INFLIGHT_CNT_MASK 0xFFFF
+#define MME_QM_CP_STS_ERDY_SHIFT 16
+#define MME_QM_CP_STS_ERDY_MASK 0x10000
+#define MME_QM_CP_STS_RRDY_SHIFT 17
+#define MME_QM_CP_STS_RRDY_MASK 0x20000
+#define MME_QM_CP_STS_MRDY_SHIFT 18
+#define MME_QM_CP_STS_MRDY_MASK 0x40000
+#define MME_QM_CP_STS_SW_STOP_SHIFT 19
+#define MME_QM_CP_STS_SW_STOP_MASK 0x80000
+#define MME_QM_CP_STS_FENCE_ID_SHIFT 20
+#define MME_QM_CP_STS_FENCE_ID_MASK 0x300000
+#define MME_QM_CP_STS_FENCE_IN_PROGRESS_SHIFT 22
+#define MME_QM_CP_STS_FENCE_IN_PROGRESS_MASK 0x400000
+
+/* MME_QM_CP_CURRENT_INST_LO */
+#define MME_QM_CP_CURRENT_INST_LO_VAL_SHIFT 0
+#define MME_QM_CP_CURRENT_INST_LO_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_CURRENT_INST_HI */
+#define MME_QM_CP_CURRENT_INST_HI_VAL_SHIFT 0
+#define MME_QM_CP_CURRENT_INST_HI_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CP_BARRIER_CFG */
+#define MME_QM_CP_BARRIER_CFG_EBGUARD_SHIFT 0
+#define MME_QM_CP_BARRIER_CFG_EBGUARD_MASK 0xFFF
+
+/* MME_QM_CP_DBG_0 */
+#define MME_QM_CP_DBG_0_VAL_SHIFT 0
+#define MME_QM_CP_DBG_0_VAL_MASK 0xFF
+
+/* MME_QM_PQ_BUF_ADDR */
+#define MME_QM_PQ_BUF_ADDR_VAL_SHIFT 0
+#define MME_QM_PQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_PQ_BUF_RDATA */
+#define MME_QM_PQ_BUF_RDATA_VAL_SHIFT 0
+#define MME_QM_PQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_BUF_ADDR */
+#define MME_QM_CQ_BUF_ADDR_VAL_SHIFT 0
+#define MME_QM_CQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* MME_QM_CQ_BUF_RDATA */
+#define MME_QM_CQ_BUF_RDATA_VAL_SHIFT 0
+#define MME_QM_CQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_MME_QM_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h
new file mode 100644
index 000000000000..b5b1c776f6c3
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_QM_REGS_H_
+#define ASIC_REG_MME_QM_REGS_H_
+
+/*
+ *****************************************
+ * MME_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmMME_QM_GLBL_CFG0 0xD8000
+
+#define mmMME_QM_GLBL_CFG1 0xD8004
+
+#define mmMME_QM_GLBL_PROT 0xD8008
+
+#define mmMME_QM_GLBL_ERR_CFG 0xD800C
+
+#define mmMME_QM_GLBL_ERR_ADDR_LO 0xD8010
+
+#define mmMME_QM_GLBL_ERR_ADDR_HI 0xD8014
+
+#define mmMME_QM_GLBL_ERR_WDATA 0xD8018
+
+#define mmMME_QM_GLBL_SECURE_PROPS 0xD801C
+
+#define mmMME_QM_GLBL_NON_SECURE_PROPS 0xD8020
+
+#define mmMME_QM_GLBL_STS0 0xD8024
+
+#define mmMME_QM_GLBL_STS1 0xD8028
+
+#define mmMME_QM_PQ_BASE_LO 0xD8060
+
+#define mmMME_QM_PQ_BASE_HI 0xD8064
+
+#define mmMME_QM_PQ_SIZE 0xD8068
+
+#define mmMME_QM_PQ_PI 0xD806C
+
+#define mmMME_QM_PQ_CI 0xD8070
+
+#define mmMME_QM_PQ_CFG0 0xD8074
+
+#define mmMME_QM_PQ_CFG1 0xD8078
+
+#define mmMME_QM_PQ_ARUSER 0xD807C
+
+#define mmMME_QM_PQ_PUSH0 0xD8080
+
+#define mmMME_QM_PQ_PUSH1 0xD8084
+
+#define mmMME_QM_PQ_PUSH2 0xD8088
+
+#define mmMME_QM_PQ_PUSH3 0xD808C
+
+#define mmMME_QM_PQ_STS0 0xD8090
+
+#define mmMME_QM_PQ_STS1 0xD8094
+
+#define mmMME_QM_PQ_RD_RATE_LIM_EN 0xD80A0
+
+#define mmMME_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xD80A4
+
+#define mmMME_QM_PQ_RD_RATE_LIM_SAT 0xD80A8
+
+#define mmMME_QM_PQ_RD_RATE_LIM_TOUT 0xD80AC
+
+#define mmMME_QM_CQ_CFG0 0xD80B0
+
+#define mmMME_QM_CQ_CFG1 0xD80B4
+
+#define mmMME_QM_CQ_ARUSER 0xD80B8
+
+#define mmMME_QM_CQ_PTR_LO 0xD80C0
+
+#define mmMME_QM_CQ_PTR_HI 0xD80C4
+
+#define mmMME_QM_CQ_TSIZE 0xD80C8
+
+#define mmMME_QM_CQ_CTL 0xD80CC
+
+#define mmMME_QM_CQ_PTR_LO_STS 0xD80D4
+
+#define mmMME_QM_CQ_PTR_HI_STS 0xD80D8
+
+#define mmMME_QM_CQ_TSIZE_STS 0xD80DC
+
+#define mmMME_QM_CQ_CTL_STS 0xD80E0
+
+#define mmMME_QM_CQ_STS0 0xD80E4
+
+#define mmMME_QM_CQ_STS1 0xD80E8
+
+#define mmMME_QM_CQ_RD_RATE_LIM_EN 0xD80F0
+
+#define mmMME_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xD80F4
+
+#define mmMME_QM_CQ_RD_RATE_LIM_SAT 0xD80F8
+
+#define mmMME_QM_CQ_RD_RATE_LIM_TOUT 0xD80FC
+
+#define mmMME_QM_CQ_IFIFO_CNT 0xD8108
+
+#define mmMME_QM_CP_MSG_BASE0_ADDR_LO 0xD8120
+
+#define mmMME_QM_CP_MSG_BASE0_ADDR_HI 0xD8124
+
+#define mmMME_QM_CP_MSG_BASE1_ADDR_LO 0xD8128
+
+#define mmMME_QM_CP_MSG_BASE1_ADDR_HI 0xD812C
+
+#define mmMME_QM_CP_MSG_BASE2_ADDR_LO 0xD8130
+
+#define mmMME_QM_CP_MSG_BASE2_ADDR_HI 0xD8134
+
+#define mmMME_QM_CP_MSG_BASE3_ADDR_LO 0xD8138
+
+#define mmMME_QM_CP_MSG_BASE3_ADDR_HI 0xD813C
+
+#define mmMME_QM_CP_LDMA_TSIZE_OFFSET 0xD8140
+
+#define mmMME_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xD8144
+
+#define mmMME_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xD8148
+
+#define mmMME_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xD814C
+
+#define mmMME_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xD8150
+
+#define mmMME_QM_CP_LDMA_COMMIT_OFFSET 0xD8154
+
+#define mmMME_QM_CP_FENCE0_RDATA 0xD8158
+
+#define mmMME_QM_CP_FENCE1_RDATA 0xD815C
+
+#define mmMME_QM_CP_FENCE2_RDATA 0xD8160
+
+#define mmMME_QM_CP_FENCE3_RDATA 0xD8164
+
+#define mmMME_QM_CP_FENCE0_CNT 0xD8168
+
+#define mmMME_QM_CP_FENCE1_CNT 0xD816C
+
+#define mmMME_QM_CP_FENCE2_CNT 0xD8170
+
+#define mmMME_QM_CP_FENCE3_CNT 0xD8174
+
+#define mmMME_QM_CP_STS 0xD8178
+
+#define mmMME_QM_CP_CURRENT_INST_LO 0xD817C
+
+#define mmMME_QM_CP_CURRENT_INST_HI 0xD8180
+
+#define mmMME_QM_CP_BARRIER_CFG 0xD8184
+
+#define mmMME_QM_CP_DBG_0 0xD8188
+
+#define mmMME_QM_PQ_BUF_ADDR 0xD8300
+
+#define mmMME_QM_PQ_BUF_RDATA 0xD8304
+
+#define mmMME_QM_CQ_BUF_ADDR 0xD8308
+
+#define mmMME_QM_CQ_BUF_RDATA 0xD830C
+
+#endif /* ASIC_REG_MME_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h
new file mode 100644
index 000000000000..9436b1e2705a
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mme_regs.h
@@ -0,0 +1,1153 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MME_REGS_H_
+#define ASIC_REG_MME_REGS_H_
+
+/*
+ *****************************************
+ * MME (Prototype: MME)
+ *****************************************
+ */
+
+#define mmMME_ARCH_STATUS 0xD0000
+
+#define mmMME_ARCH_A_BASE_ADDR_HIGH 0xD0008
+
+#define mmMME_ARCH_B_BASE_ADDR_HIGH 0xD000C
+
+#define mmMME_ARCH_CIN_BASE_ADDR_HIGH 0xD0010
+
+#define mmMME_ARCH_COUT_BASE_ADDR_HIGH 0xD0014
+
+#define mmMME_ARCH_BIAS_BASE_ADDR_HIGH 0xD0018
+
+#define mmMME_ARCH_A_BASE_ADDR_LOW 0xD001C
+
+#define mmMME_ARCH_B_BASE_ADDR_LOW 0xD0020
+
+#define mmMME_ARCH_CIN_BASE_ADDR_LOW 0xD0024
+
+#define mmMME_ARCH_COUT_BASE_ADDR_LOW 0xD0028
+
+#define mmMME_ARCH_BIAS_BASE_ADDR_LOW 0xD002C
+
+#define mmMME_ARCH_HEADER 0xD0030
+
+#define mmMME_ARCH_KERNEL_SIZE_MINUS_1 0xD0034
+
+#define mmMME_ARCH_ASSOCIATED_DIMS_0 0xD0038
+
+#define mmMME_ARCH_ASSOCIATED_DIMS_1 0xD003C
+
+#define mmMME_ARCH_COUT_SCALE 0xD0040
+
+#define mmMME_ARCH_CIN_SCALE 0xD0044
+
+#define mmMME_ARCH_GEMMLOWP_ZP 0xD0048
+
+#define mmMME_ARCH_GEMMLOWP_EXPONENT 0xD004C
+
+#define mmMME_ARCH_A_ROI_BASE_OFFSET_0 0xD0050
+
+#define mmMME_ARCH_A_ROI_BASE_OFFSET_1 0xD0054
+
+#define mmMME_ARCH_A_ROI_BASE_OFFSET_2 0xD0058
+
+#define mmMME_ARCH_A_ROI_BASE_OFFSET_3 0xD005C
+
+#define mmMME_ARCH_A_ROI_BASE_OFFSET_4 0xD0060
+
+#define mmMME_ARCH_A_VALID_ELEMENTS_0 0xD0064
+
+#define mmMME_ARCH_A_VALID_ELEMENTS_1 0xD0068
+
+#define mmMME_ARCH_A_VALID_ELEMENTS_2 0xD006C
+
+#define mmMME_ARCH_A_VALID_ELEMENTS_3 0xD0070
+
+#define mmMME_ARCH_A_VALID_ELEMENTS_4 0xD0074
+
+#define mmMME_ARCH_A_LOOP_STRIDE_0 0xD0078
+
+#define mmMME_ARCH_A_LOOP_STRIDE_1 0xD007C
+
+#define mmMME_ARCH_A_LOOP_STRIDE_2 0xD0080
+
+#define mmMME_ARCH_A_LOOP_STRIDE_3 0xD0084
+
+#define mmMME_ARCH_A_LOOP_STRIDE_4 0xD0088
+
+#define mmMME_ARCH_A_ROI_SIZE_0 0xD008C
+
+#define mmMME_ARCH_A_ROI_SIZE_1 0xD0090
+
+#define mmMME_ARCH_A_ROI_SIZE_2 0xD0094
+
+#define mmMME_ARCH_A_ROI_SIZE_3 0xD0098
+
+#define mmMME_ARCH_A_SPATIAL_START_OFFSET_0 0xD009C
+
+#define mmMME_ARCH_A_SPATIAL_START_OFFSET_1 0xD00A0
+
+#define mmMME_ARCH_A_SPATIAL_START_OFFSET_2 0xD00A4
+
+#define mmMME_ARCH_A_SPATIAL_START_OFFSET_3 0xD00A8
+
+#define mmMME_ARCH_A_SPATIAL_STRIDE_0 0xD00AC
+
+#define mmMME_ARCH_A_SPATIAL_STRIDE_1 0xD00B0
+
+#define mmMME_ARCH_A_SPATIAL_STRIDE_2 0xD00B4
+
+#define mmMME_ARCH_A_SPATIAL_STRIDE_3 0xD00B8
+
+#define mmMME_ARCH_A_SPATIAL_SIZE_MINUS_1 0xD00BC
+
+#define mmMME_ARCH_B_ROI_BASE_OFFSET_0 0xD00C0
+
+#define mmMME_ARCH_B_ROI_BASE_OFFSET_1 0xD00C4
+
+#define mmMME_ARCH_B_ROI_BASE_OFFSET_2 0xD00C8
+
+#define mmMME_ARCH_B_ROI_BASE_OFFSET_3 0xD00CC
+
+#define mmMME_ARCH_B_ROI_BASE_OFFSET_4 0xD00D0
+
+#define mmMME_ARCH_B_VALID_ELEMENTS_0 0xD00D4
+
+#define mmMME_ARCH_B_VALID_ELEMENTS_1 0xD00D8
+
+#define mmMME_ARCH_B_VALID_ELEMENTS_2 0xD00DC
+
+#define mmMME_ARCH_B_VALID_ELEMENTS_3 0xD00E0
+
+#define mmMME_ARCH_B_VALID_ELEMENTS_4 0xD00E4
+
+#define mmMME_ARCH_B_LOOP_STRIDE_0 0xD00E8
+
+#define mmMME_ARCH_B_LOOP_STRIDE_1 0xD00EC
+
+#define mmMME_ARCH_B_LOOP_STRIDE_2 0xD00F0
+
+#define mmMME_ARCH_B_LOOP_STRIDE_3 0xD00F4
+
+#define mmMME_ARCH_B_LOOP_STRIDE_4 0xD00F8
+
+#define mmMME_ARCH_B_ROI_SIZE_0 0xD00FC
+
+#define mmMME_ARCH_B_ROI_SIZE_1 0xD0100
+
+#define mmMME_ARCH_B_ROI_SIZE_2 0xD0104
+
+#define mmMME_ARCH_B_ROI_SIZE_3 0xD0108
+
+#define mmMME_ARCH_B_SPATIAL_START_OFFSET_0 0xD010C
+
+#define mmMME_ARCH_B_SPATIAL_START_OFFSET_1 0xD0110
+
+#define mmMME_ARCH_B_SPATIAL_START_OFFSET_2 0xD0114
+
+#define mmMME_ARCH_B_SPATIAL_START_OFFSET_3 0xD0118
+
+#define mmMME_ARCH_B_SPATIAL_STRIDE_0 0xD011C
+
+#define mmMME_ARCH_B_SPATIAL_STRIDE_1 0xD0120
+
+#define mmMME_ARCH_B_SPATIAL_STRIDE_2 0xD0124
+
+#define mmMME_ARCH_B_SPATIAL_STRIDE_3 0xD0128
+
+#define mmMME_ARCH_B_SPATIAL_SIZE_MINUS_1 0xD012C
+
+#define mmMME_ARCH_C_ROI_BASE_OFFSET_0 0xD0130
+
+#define mmMME_ARCH_C_ROI_BASE_OFFSET_1 0xD0134
+
+#define mmMME_ARCH_C_ROI_BASE_OFFSET_2 0xD0138
+
+#define mmMME_ARCH_C_ROI_BASE_OFFSET_3 0xD013C
+
+#define mmMME_ARCH_C_ROI_BASE_OFFSET_4 0xD0140
+
+#define mmMME_ARCH_C_VALID_ELEMENTS_0 0xD0144
+
+#define mmMME_ARCH_C_VALID_ELEMENTS_1 0xD0148
+
+#define mmMME_ARCH_C_VALID_ELEMENTS_2 0xD014C
+
+#define mmMME_ARCH_C_VALID_ELEMENTS_3 0xD0150
+
+#define mmMME_ARCH_C_VALID_ELEMENTS_4 0xD0154
+
+#define mmMME_ARCH_C_LOOP_STRIDE_0 0xD0158
+
+#define mmMME_ARCH_C_LOOP_STRIDE_1 0xD015C
+
+#define mmMME_ARCH_C_LOOP_STRIDE_2 0xD0160
+
+#define mmMME_ARCH_C_LOOP_STRIDE_3 0xD0164
+
+#define mmMME_ARCH_C_LOOP_STRIDE_4 0xD0168
+
+#define mmMME_ARCH_C_ROI_SIZE_0 0xD016C
+
+#define mmMME_ARCH_C_ROI_SIZE_1 0xD0170
+
+#define mmMME_ARCH_C_ROI_SIZE_2 0xD0174
+
+#define mmMME_ARCH_C_ROI_SIZE_3 0xD0178
+
+#define mmMME_ARCH_C_SPATIAL_START_OFFSET_0 0xD017C
+
+#define mmMME_ARCH_C_SPATIAL_START_OFFSET_1 0xD0180
+
+#define mmMME_ARCH_C_SPATIAL_START_OFFSET_2 0xD0184
+
+#define mmMME_ARCH_C_SPATIAL_START_OFFSET_3 0xD0188
+
+#define mmMME_ARCH_C_SPATIAL_STRIDE_0 0xD018C
+
+#define mmMME_ARCH_C_SPATIAL_STRIDE_1 0xD0190
+
+#define mmMME_ARCH_C_SPATIAL_STRIDE_2 0xD0194
+
+#define mmMME_ARCH_C_SPATIAL_STRIDE_3 0xD0198
+
+#define mmMME_ARCH_C_SPATIAL_SIZE_MINUS_1 0xD019C
+
+#define mmMME_ARCH_SYNC_OBJECT_MESSAGE 0xD01A0
+
+#define mmMME_ARCH_E_PADDING_VALUE_A 0xD01A4
+
+#define mmMME_ARCH_E_NUM_ITERATION_MINUS_1 0xD01A8
+
+#define mmMME_ARCH_E_BUBBLES_PER_SPLIT 0xD01AC
+
+#define mmMME_CMD 0xD0200
+
+#define mmMME_DUMMY 0xD0204
+
+#define mmMME_RESET 0xD0208
+
+#define mmMME_STALL 0xD020C
+
+#define mmMME_SM_BASE_ADDRESS_LOW 0xD0210
+
+#define mmMME_SM_BASE_ADDRESS_HIGH 0xD0214
+
+#define mmMME_DBGMEM_ADD 0xD0218
+
+#define mmMME_DBGMEM_DATA_WR 0xD021C
+
+#define mmMME_DBGMEM_DATA_RD 0xD0220
+
+#define mmMME_DBGMEM_CTRL 0xD0224
+
+#define mmMME_DBGMEM_RC 0xD0228
+
+#define mmMME_LOG_SHADOW 0xD022C
+
+#define mmMME_STORE_MAX_CREDIT 0xD0300
+
+#define mmMME_AGU 0xD0304
+
+#define mmMME_SBA 0xD0308
+
+#define mmMME_SBB 0xD030C
+
+#define mmMME_SBC 0xD0310
+
+#define mmMME_WBC 0xD0314
+
+#define mmMME_SBA_CONTROL_DATA 0xD0318
+
+#define mmMME_SBB_CONTROL_DATA 0xD031C
+
+#define mmMME_SBC_CONTROL_DATA 0xD0320
+
+#define mmMME_WBC_CONTROL_DATA 0xD0324
+
+#define mmMME_TE 0xD0328
+
+#define mmMME_TE2DEC 0xD032C
+
+#define mmMME_REI_STATUS 0xD0330
+
+#define mmMME_REI_MASK 0xD0334
+
+#define mmMME_SEI_STATUS 0xD0338
+
+#define mmMME_SEI_MASK 0xD033C
+
+#define mmMME_SPI_STATUS 0xD0340
+
+#define mmMME_SPI_MASK 0xD0344
+
+#define mmMME_SHADOW_0_STATUS 0xD0400
+
+#define mmMME_SHADOW_0_A_BASE_ADDR_HIGH 0xD0408
+
+#define mmMME_SHADOW_0_B_BASE_ADDR_HIGH 0xD040C
+
+#define mmMME_SHADOW_0_CIN_BASE_ADDR_HIGH 0xD0410
+
+#define mmMME_SHADOW_0_COUT_BASE_ADDR_HIGH 0xD0414
+
+#define mmMME_SHADOW_0_BIAS_BASE_ADDR_HIGH 0xD0418
+
+#define mmMME_SHADOW_0_A_BASE_ADDR_LOW 0xD041C
+
+#define mmMME_SHADOW_0_B_BASE_ADDR_LOW 0xD0420
+
+#define mmMME_SHADOW_0_CIN_BASE_ADDR_LOW 0xD0424
+
+#define mmMME_SHADOW_0_COUT_BASE_ADDR_LOW 0xD0428
+
+#define mmMME_SHADOW_0_BIAS_BASE_ADDR_LOW 0xD042C
+
+#define mmMME_SHADOW_0_HEADER 0xD0430
+
+#define mmMME_SHADOW_0_KERNEL_SIZE_MINUS_1 0xD0434
+
+#define mmMME_SHADOW_0_ASSOCIATED_DIMS_0 0xD0438
+
+#define mmMME_SHADOW_0_ASSOCIATED_DIMS_1 0xD043C
+
+#define mmMME_SHADOW_0_COUT_SCALE 0xD0440
+
+#define mmMME_SHADOW_0_CIN_SCALE 0xD0444
+
+#define mmMME_SHADOW_0_GEMMLOWP_ZP 0xD0448
+
+#define mmMME_SHADOW_0_GEMMLOWP_EXPONENT 0xD044C
+
+#define mmMME_SHADOW_0_A_ROI_BASE_OFFSET_0 0xD0450
+
+#define mmMME_SHADOW_0_A_ROI_BASE_OFFSET_1 0xD0454
+
+#define mmMME_SHADOW_0_A_ROI_BASE_OFFSET_2 0xD0458
+
+#define mmMME_SHADOW_0_A_ROI_BASE_OFFSET_3 0xD045C
+
+#define mmMME_SHADOW_0_A_ROI_BASE_OFFSET_4 0xD0460
+
+#define mmMME_SHADOW_0_A_VALID_ELEMENTS_0 0xD0464
+
+#define mmMME_SHADOW_0_A_VALID_ELEMENTS_1 0xD0468
+
+#define mmMME_SHADOW_0_A_VALID_ELEMENTS_2 0xD046C
+
+#define mmMME_SHADOW_0_A_VALID_ELEMENTS_3 0xD0470
+
+#define mmMME_SHADOW_0_A_VALID_ELEMENTS_4 0xD0474
+
+#define mmMME_SHADOW_0_A_LOOP_STRIDE_0 0xD0478
+
+#define mmMME_SHADOW_0_A_LOOP_STRIDE_1 0xD047C
+
+#define mmMME_SHADOW_0_A_LOOP_STRIDE_2 0xD0480
+
+#define mmMME_SHADOW_0_A_LOOP_STRIDE_3 0xD0484
+
+#define mmMME_SHADOW_0_A_LOOP_STRIDE_4 0xD0488
+
+#define mmMME_SHADOW_0_A_ROI_SIZE_0 0xD048C
+
+#define mmMME_SHADOW_0_A_ROI_SIZE_1 0xD0490
+
+#define mmMME_SHADOW_0_A_ROI_SIZE_2 0xD0494
+
+#define mmMME_SHADOW_0_A_ROI_SIZE_3 0xD0498
+
+#define mmMME_SHADOW_0_A_SPATIAL_START_OFFSET_0 0xD049C
+
+#define mmMME_SHADOW_0_A_SPATIAL_START_OFFSET_1 0xD04A0
+
+#define mmMME_SHADOW_0_A_SPATIAL_START_OFFSET_2 0xD04A4
+
+#define mmMME_SHADOW_0_A_SPATIAL_START_OFFSET_3 0xD04A8
+
+#define mmMME_SHADOW_0_A_SPATIAL_STRIDE_0 0xD04AC
+
+#define mmMME_SHADOW_0_A_SPATIAL_STRIDE_1 0xD04B0
+
+#define mmMME_SHADOW_0_A_SPATIAL_STRIDE_2 0xD04B4
+
+#define mmMME_SHADOW_0_A_SPATIAL_STRIDE_3 0xD04B8
+
+#define mmMME_SHADOW_0_A_SPATIAL_SIZE_MINUS_1 0xD04BC
+
+#define mmMME_SHADOW_0_B_ROI_BASE_OFFSET_0 0xD04C0
+
+#define mmMME_SHADOW_0_B_ROI_BASE_OFFSET_1 0xD04C4
+
+#define mmMME_SHADOW_0_B_ROI_BASE_OFFSET_2 0xD04C8
+
+#define mmMME_SHADOW_0_B_ROI_BASE_OFFSET_3 0xD04CC
+
+#define mmMME_SHADOW_0_B_ROI_BASE_OFFSET_4 0xD04D0
+
+#define mmMME_SHADOW_0_B_VALID_ELEMENTS_0 0xD04D4
+
+#define mmMME_SHADOW_0_B_VALID_ELEMENTS_1 0xD04D8
+
+#define mmMME_SHADOW_0_B_VALID_ELEMENTS_2 0xD04DC
+
+#define mmMME_SHADOW_0_B_VALID_ELEMENTS_3 0xD04E0
+
+#define mmMME_SHADOW_0_B_VALID_ELEMENTS_4 0xD04E4
+
+#define mmMME_SHADOW_0_B_LOOP_STRIDE_0 0xD04E8
+
+#define mmMME_SHADOW_0_B_LOOP_STRIDE_1 0xD04EC
+
+#define mmMME_SHADOW_0_B_LOOP_STRIDE_2 0xD04F0
+
+#define mmMME_SHADOW_0_B_LOOP_STRIDE_3 0xD04F4
+
+#define mmMME_SHADOW_0_B_LOOP_STRIDE_4 0xD04F8
+
+#define mmMME_SHADOW_0_B_ROI_SIZE_0 0xD04FC
+
+#define mmMME_SHADOW_0_B_ROI_SIZE_1 0xD0500
+
+#define mmMME_SHADOW_0_B_ROI_SIZE_2 0xD0504
+
+#define mmMME_SHADOW_0_B_ROI_SIZE_3 0xD0508
+
+#define mmMME_SHADOW_0_B_SPATIAL_START_OFFSET_0 0xD050C
+
+#define mmMME_SHADOW_0_B_SPATIAL_START_OFFSET_1 0xD0510
+
+#define mmMME_SHADOW_0_B_SPATIAL_START_OFFSET_2 0xD0514
+
+#define mmMME_SHADOW_0_B_SPATIAL_START_OFFSET_3 0xD0518
+
+#define mmMME_SHADOW_0_B_SPATIAL_STRIDE_0 0xD051C
+
+#define mmMME_SHADOW_0_B_SPATIAL_STRIDE_1 0xD0520
+
+#define mmMME_SHADOW_0_B_SPATIAL_STRIDE_2 0xD0524
+
+#define mmMME_SHADOW_0_B_SPATIAL_STRIDE_3 0xD0528
+
+#define mmMME_SHADOW_0_B_SPATIAL_SIZE_MINUS_1 0xD052C
+
+#define mmMME_SHADOW_0_C_ROI_BASE_OFFSET_0 0xD0530
+
+#define mmMME_SHADOW_0_C_ROI_BASE_OFFSET_1 0xD0534
+
+#define mmMME_SHADOW_0_C_ROI_BASE_OFFSET_2 0xD0538
+
+#define mmMME_SHADOW_0_C_ROI_BASE_OFFSET_3 0xD053C
+
+#define mmMME_SHADOW_0_C_ROI_BASE_OFFSET_4 0xD0540
+
+#define mmMME_SHADOW_0_C_VALID_ELEMENTS_0 0xD0544
+
+#define mmMME_SHADOW_0_C_VALID_ELEMENTS_1 0xD0548
+
+#define mmMME_SHADOW_0_C_VALID_ELEMENTS_2 0xD054C
+
+#define mmMME_SHADOW_0_C_VALID_ELEMENTS_3 0xD0550
+
+#define mmMME_SHADOW_0_C_VALID_ELEMENTS_4 0xD0554
+
+#define mmMME_SHADOW_0_C_LOOP_STRIDE_0 0xD0558
+
+#define mmMME_SHADOW_0_C_LOOP_STRIDE_1 0xD055C
+
+#define mmMME_SHADOW_0_C_LOOP_STRIDE_2 0xD0560
+
+#define mmMME_SHADOW_0_C_LOOP_STRIDE_3 0xD0564
+
+#define mmMME_SHADOW_0_C_LOOP_STRIDE_4 0xD0568
+
+#define mmMME_SHADOW_0_C_ROI_SIZE_0 0xD056C
+
+#define mmMME_SHADOW_0_C_ROI_SIZE_1 0xD0570
+
+#define mmMME_SHADOW_0_C_ROI_SIZE_2 0xD0574
+
+#define mmMME_SHADOW_0_C_ROI_SIZE_3 0xD0578
+
+#define mmMME_SHADOW_0_C_SPATIAL_START_OFFSET_0 0xD057C
+
+#define mmMME_SHADOW_0_C_SPATIAL_START_OFFSET_1 0xD0580
+
+#define mmMME_SHADOW_0_C_SPATIAL_START_OFFSET_2 0xD0584
+
+#define mmMME_SHADOW_0_C_SPATIAL_START_OFFSET_3 0xD0588
+
+#define mmMME_SHADOW_0_C_SPATIAL_STRIDE_0 0xD058C
+
+#define mmMME_SHADOW_0_C_SPATIAL_STRIDE_1 0xD0590
+
+#define mmMME_SHADOW_0_C_SPATIAL_STRIDE_2 0xD0594
+
+#define mmMME_SHADOW_0_C_SPATIAL_STRIDE_3 0xD0598
+
+#define mmMME_SHADOW_0_C_SPATIAL_SIZE_MINUS_1 0xD059C
+
+#define mmMME_SHADOW_0_SYNC_OBJECT_MESSAGE 0xD05A0
+
+#define mmMME_SHADOW_0_E_PADDING_VALUE_A 0xD05A4
+
+#define mmMME_SHADOW_0_E_NUM_ITERATION_MINUS_1 0xD05A8
+
+#define mmMME_SHADOW_0_E_BUBBLES_PER_SPLIT 0xD05AC
+
+#define mmMME_SHADOW_1_STATUS 0xD0600
+
+#define mmMME_SHADOW_1_A_BASE_ADDR_HIGH 0xD0608
+
+#define mmMME_SHADOW_1_B_BASE_ADDR_HIGH 0xD060C
+
+#define mmMME_SHADOW_1_CIN_BASE_ADDR_HIGH 0xD0610
+
+#define mmMME_SHADOW_1_COUT_BASE_ADDR_HIGH 0xD0614
+
+#define mmMME_SHADOW_1_BIAS_BASE_ADDR_HIGH 0xD0618
+
+#define mmMME_SHADOW_1_A_BASE_ADDR_LOW 0xD061C
+
+#define mmMME_SHADOW_1_B_BASE_ADDR_LOW 0xD0620
+
+#define mmMME_SHADOW_1_CIN_BASE_ADDR_LOW 0xD0624
+
+#define mmMME_SHADOW_1_COUT_BASE_ADDR_LOW 0xD0628
+
+#define mmMME_SHADOW_1_BIAS_BASE_ADDR_LOW 0xD062C
+
+#define mmMME_SHADOW_1_HEADER 0xD0630
+
+#define mmMME_SHADOW_1_KERNEL_SIZE_MINUS_1 0xD0634
+
+#define mmMME_SHADOW_1_ASSOCIATED_DIMS_0 0xD0638
+
+#define mmMME_SHADOW_1_ASSOCIATED_DIMS_1 0xD063C
+
+#define mmMME_SHADOW_1_COUT_SCALE 0xD0640
+
+#define mmMME_SHADOW_1_CIN_SCALE 0xD0644
+
+#define mmMME_SHADOW_1_GEMMLOWP_ZP 0xD0648
+
+#define mmMME_SHADOW_1_GEMMLOWP_EXPONENT 0xD064C
+
+#define mmMME_SHADOW_1_A_ROI_BASE_OFFSET_0 0xD0650
+
+#define mmMME_SHADOW_1_A_ROI_BASE_OFFSET_1 0xD0654
+
+#define mmMME_SHADOW_1_A_ROI_BASE_OFFSET_2 0xD0658
+
+#define mmMME_SHADOW_1_A_ROI_BASE_OFFSET_3 0xD065C
+
+#define mmMME_SHADOW_1_A_ROI_BASE_OFFSET_4 0xD0660
+
+#define mmMME_SHADOW_1_A_VALID_ELEMENTS_0 0xD0664
+
+#define mmMME_SHADOW_1_A_VALID_ELEMENTS_1 0xD0668
+
+#define mmMME_SHADOW_1_A_VALID_ELEMENTS_2 0xD066C
+
+#define mmMME_SHADOW_1_A_VALID_ELEMENTS_3 0xD0670
+
+#define mmMME_SHADOW_1_A_VALID_ELEMENTS_4 0xD0674
+
+#define mmMME_SHADOW_1_A_LOOP_STRIDE_0 0xD0678
+
+#define mmMME_SHADOW_1_A_LOOP_STRIDE_1 0xD067C
+
+#define mmMME_SHADOW_1_A_LOOP_STRIDE_2 0xD0680
+
+#define mmMME_SHADOW_1_A_LOOP_STRIDE_3 0xD0684
+
+#define mmMME_SHADOW_1_A_LOOP_STRIDE_4 0xD0688
+
+#define mmMME_SHADOW_1_A_ROI_SIZE_0 0xD068C
+
+#define mmMME_SHADOW_1_A_ROI_SIZE_1 0xD0690
+
+#define mmMME_SHADOW_1_A_ROI_SIZE_2 0xD0694
+
+#define mmMME_SHADOW_1_A_ROI_SIZE_3 0xD0698
+
+#define mmMME_SHADOW_1_A_SPATIAL_START_OFFSET_0 0xD069C
+
+#define mmMME_SHADOW_1_A_SPATIAL_START_OFFSET_1 0xD06A0
+
+#define mmMME_SHADOW_1_A_SPATIAL_START_OFFSET_2 0xD06A4
+
+#define mmMME_SHADOW_1_A_SPATIAL_START_OFFSET_3 0xD06A8
+
+#define mmMME_SHADOW_1_A_SPATIAL_STRIDE_0 0xD06AC
+
+#define mmMME_SHADOW_1_A_SPATIAL_STRIDE_1 0xD06B0
+
+#define mmMME_SHADOW_1_A_SPATIAL_STRIDE_2 0xD06B4
+
+#define mmMME_SHADOW_1_A_SPATIAL_STRIDE_3 0xD06B8
+
+#define mmMME_SHADOW_1_A_SPATIAL_SIZE_MINUS_1 0xD06BC
+
+#define mmMME_SHADOW_1_B_ROI_BASE_OFFSET_0 0xD06C0
+
+#define mmMME_SHADOW_1_B_ROI_BASE_OFFSET_1 0xD06C4
+
+#define mmMME_SHADOW_1_B_ROI_BASE_OFFSET_2 0xD06C8
+
+#define mmMME_SHADOW_1_B_ROI_BASE_OFFSET_3 0xD06CC
+
+#define mmMME_SHADOW_1_B_ROI_BASE_OFFSET_4 0xD06D0
+
+#define mmMME_SHADOW_1_B_VALID_ELEMENTS_0 0xD06D4
+
+#define mmMME_SHADOW_1_B_VALID_ELEMENTS_1 0xD06D8
+
+#define mmMME_SHADOW_1_B_VALID_ELEMENTS_2 0xD06DC
+
+#define mmMME_SHADOW_1_B_VALID_ELEMENTS_3 0xD06E0
+
+#define mmMME_SHADOW_1_B_VALID_ELEMENTS_4 0xD06E4
+
+#define mmMME_SHADOW_1_B_LOOP_STRIDE_0 0xD06E8
+
+#define mmMME_SHADOW_1_B_LOOP_STRIDE_1 0xD06EC
+
+#define mmMME_SHADOW_1_B_LOOP_STRIDE_2 0xD06F0
+
+#define mmMME_SHADOW_1_B_LOOP_STRIDE_3 0xD06F4
+
+#define mmMME_SHADOW_1_B_LOOP_STRIDE_4 0xD06F8
+
+#define mmMME_SHADOW_1_B_ROI_SIZE_0 0xD06FC
+
+#define mmMME_SHADOW_1_B_ROI_SIZE_1 0xD0700
+
+#define mmMME_SHADOW_1_B_ROI_SIZE_2 0xD0704
+
+#define mmMME_SHADOW_1_B_ROI_SIZE_3 0xD0708
+
+#define mmMME_SHADOW_1_B_SPATIAL_START_OFFSET_0 0xD070C
+
+#define mmMME_SHADOW_1_B_SPATIAL_START_OFFSET_1 0xD0710
+
+#define mmMME_SHADOW_1_B_SPATIAL_START_OFFSET_2 0xD0714
+
+#define mmMME_SHADOW_1_B_SPATIAL_START_OFFSET_3 0xD0718
+
+#define mmMME_SHADOW_1_B_SPATIAL_STRIDE_0 0xD071C
+
+#define mmMME_SHADOW_1_B_SPATIAL_STRIDE_1 0xD0720
+
+#define mmMME_SHADOW_1_B_SPATIAL_STRIDE_2 0xD0724
+
+#define mmMME_SHADOW_1_B_SPATIAL_STRIDE_3 0xD0728
+
+#define mmMME_SHADOW_1_B_SPATIAL_SIZE_MINUS_1 0xD072C
+
+#define mmMME_SHADOW_1_C_ROI_BASE_OFFSET_0 0xD0730
+
+#define mmMME_SHADOW_1_C_ROI_BASE_OFFSET_1 0xD0734
+
+#define mmMME_SHADOW_1_C_ROI_BASE_OFFSET_2 0xD0738
+
+#define mmMME_SHADOW_1_C_ROI_BASE_OFFSET_3 0xD073C
+
+#define mmMME_SHADOW_1_C_ROI_BASE_OFFSET_4 0xD0740
+
+#define mmMME_SHADOW_1_C_VALID_ELEMENTS_0 0xD0744
+
+#define mmMME_SHADOW_1_C_VALID_ELEMENTS_1 0xD0748
+
+#define mmMME_SHADOW_1_C_VALID_ELEMENTS_2 0xD074C
+
+#define mmMME_SHADOW_1_C_VALID_ELEMENTS_3 0xD0750
+
+#define mmMME_SHADOW_1_C_VALID_ELEMENTS_4 0xD0754
+
+#define mmMME_SHADOW_1_C_LOOP_STRIDE_0 0xD0758
+
+#define mmMME_SHADOW_1_C_LOOP_STRIDE_1 0xD075C
+
+#define mmMME_SHADOW_1_C_LOOP_STRIDE_2 0xD0760
+
+#define mmMME_SHADOW_1_C_LOOP_STRIDE_3 0xD0764
+
+#define mmMME_SHADOW_1_C_LOOP_STRIDE_4 0xD0768
+
+#define mmMME_SHADOW_1_C_ROI_SIZE_0 0xD076C
+
+#define mmMME_SHADOW_1_C_ROI_SIZE_1 0xD0770
+
+#define mmMME_SHADOW_1_C_ROI_SIZE_2 0xD0774
+
+#define mmMME_SHADOW_1_C_ROI_SIZE_3 0xD0778
+
+#define mmMME_SHADOW_1_C_SPATIAL_START_OFFSET_0 0xD077C
+
+#define mmMME_SHADOW_1_C_SPATIAL_START_OFFSET_1 0xD0780
+
+#define mmMME_SHADOW_1_C_SPATIAL_START_OFFSET_2 0xD0784
+
+#define mmMME_SHADOW_1_C_SPATIAL_START_OFFSET_3 0xD0788
+
+#define mmMME_SHADOW_1_C_SPATIAL_STRIDE_0 0xD078C
+
+#define mmMME_SHADOW_1_C_SPATIAL_STRIDE_1 0xD0790
+
+#define mmMME_SHADOW_1_C_SPATIAL_STRIDE_2 0xD0794
+
+#define mmMME_SHADOW_1_C_SPATIAL_STRIDE_3 0xD0798
+
+#define mmMME_SHADOW_1_C_SPATIAL_SIZE_MINUS_1 0xD079C
+
+#define mmMME_SHADOW_1_SYNC_OBJECT_MESSAGE 0xD07A0
+
+#define mmMME_SHADOW_1_E_PADDING_VALUE_A 0xD07A4
+
+#define mmMME_SHADOW_1_E_NUM_ITERATION_MINUS_1 0xD07A8
+
+#define mmMME_SHADOW_1_E_BUBBLES_PER_SPLIT 0xD07AC
+
+#define mmMME_SHADOW_2_STATUS 0xD0800
+
+#define mmMME_SHADOW_2_A_BASE_ADDR_HIGH 0xD0808
+
+#define mmMME_SHADOW_2_B_BASE_ADDR_HIGH 0xD080C
+
+#define mmMME_SHADOW_2_CIN_BASE_ADDR_HIGH 0xD0810
+
+#define mmMME_SHADOW_2_COUT_BASE_ADDR_HIGH 0xD0814
+
+#define mmMME_SHADOW_2_BIAS_BASE_ADDR_HIGH 0xD0818
+
+#define mmMME_SHADOW_2_A_BASE_ADDR_LOW 0xD081C
+
+#define mmMME_SHADOW_2_B_BASE_ADDR_LOW 0xD0820
+
+#define mmMME_SHADOW_2_CIN_BASE_ADDR_LOW 0xD0824
+
+#define mmMME_SHADOW_2_COUT_BASE_ADDR_LOW 0xD0828
+
+#define mmMME_SHADOW_2_BIAS_BASE_ADDR_LOW 0xD082C
+
+#define mmMME_SHADOW_2_HEADER 0xD0830
+
+#define mmMME_SHADOW_2_KERNEL_SIZE_MINUS_1 0xD0834
+
+#define mmMME_SHADOW_2_ASSOCIATED_DIMS_0 0xD0838
+
+#define mmMME_SHADOW_2_ASSOCIATED_DIMS_1 0xD083C
+
+#define mmMME_SHADOW_2_COUT_SCALE 0xD0840
+
+#define mmMME_SHADOW_2_CIN_SCALE 0xD0844
+
+#define mmMME_SHADOW_2_GEMMLOWP_ZP 0xD0848
+
+#define mmMME_SHADOW_2_GEMMLOWP_EXPONENT 0xD084C
+
+#define mmMME_SHADOW_2_A_ROI_BASE_OFFSET_0 0xD0850
+
+#define mmMME_SHADOW_2_A_ROI_BASE_OFFSET_1 0xD0854
+
+#define mmMME_SHADOW_2_A_ROI_BASE_OFFSET_2 0xD0858
+
+#define mmMME_SHADOW_2_A_ROI_BASE_OFFSET_3 0xD085C
+
+#define mmMME_SHADOW_2_A_ROI_BASE_OFFSET_4 0xD0860
+
+#define mmMME_SHADOW_2_A_VALID_ELEMENTS_0 0xD0864
+
+#define mmMME_SHADOW_2_A_VALID_ELEMENTS_1 0xD0868
+
+#define mmMME_SHADOW_2_A_VALID_ELEMENTS_2 0xD086C
+
+#define mmMME_SHADOW_2_A_VALID_ELEMENTS_3 0xD0870
+
+#define mmMME_SHADOW_2_A_VALID_ELEMENTS_4 0xD0874
+
+#define mmMME_SHADOW_2_A_LOOP_STRIDE_0 0xD0878
+
+#define mmMME_SHADOW_2_A_LOOP_STRIDE_1 0xD087C
+
+#define mmMME_SHADOW_2_A_LOOP_STRIDE_2 0xD0880
+
+#define mmMME_SHADOW_2_A_LOOP_STRIDE_3 0xD0884
+
+#define mmMME_SHADOW_2_A_LOOP_STRIDE_4 0xD0888
+
+#define mmMME_SHADOW_2_A_ROI_SIZE_0 0xD088C
+
+#define mmMME_SHADOW_2_A_ROI_SIZE_1 0xD0890
+
+#define mmMME_SHADOW_2_A_ROI_SIZE_2 0xD0894
+
+#define mmMME_SHADOW_2_A_ROI_SIZE_3 0xD0898
+
+#define mmMME_SHADOW_2_A_SPATIAL_START_OFFSET_0 0xD089C
+
+#define mmMME_SHADOW_2_A_SPATIAL_START_OFFSET_1 0xD08A0
+
+#define mmMME_SHADOW_2_A_SPATIAL_START_OFFSET_2 0xD08A4
+
+#define mmMME_SHADOW_2_A_SPATIAL_START_OFFSET_3 0xD08A8
+
+#define mmMME_SHADOW_2_A_SPATIAL_STRIDE_0 0xD08AC
+
+#define mmMME_SHADOW_2_A_SPATIAL_STRIDE_1 0xD08B0
+
+#define mmMME_SHADOW_2_A_SPATIAL_STRIDE_2 0xD08B4
+
+#define mmMME_SHADOW_2_A_SPATIAL_STRIDE_3 0xD08B8
+
+#define mmMME_SHADOW_2_A_SPATIAL_SIZE_MINUS_1 0xD08BC
+
+#define mmMME_SHADOW_2_B_ROI_BASE_OFFSET_0 0xD08C0
+
+#define mmMME_SHADOW_2_B_ROI_BASE_OFFSET_1 0xD08C4
+
+#define mmMME_SHADOW_2_B_ROI_BASE_OFFSET_2 0xD08C8
+
+#define mmMME_SHADOW_2_B_ROI_BASE_OFFSET_3 0xD08CC
+
+#define mmMME_SHADOW_2_B_ROI_BASE_OFFSET_4 0xD08D0
+
+#define mmMME_SHADOW_2_B_VALID_ELEMENTS_0 0xD08D4
+
+#define mmMME_SHADOW_2_B_VALID_ELEMENTS_1 0xD08D8
+
+#define mmMME_SHADOW_2_B_VALID_ELEMENTS_2 0xD08DC
+
+#define mmMME_SHADOW_2_B_VALID_ELEMENTS_3 0xD08E0
+
+#define mmMME_SHADOW_2_B_VALID_ELEMENTS_4 0xD08E4
+
+#define mmMME_SHADOW_2_B_LOOP_STRIDE_0 0xD08E8
+
+#define mmMME_SHADOW_2_B_LOOP_STRIDE_1 0xD08EC
+
+#define mmMME_SHADOW_2_B_LOOP_STRIDE_2 0xD08F0
+
+#define mmMME_SHADOW_2_B_LOOP_STRIDE_3 0xD08F4
+
+#define mmMME_SHADOW_2_B_LOOP_STRIDE_4 0xD08F8
+
+#define mmMME_SHADOW_2_B_ROI_SIZE_0 0xD08FC
+
+#define mmMME_SHADOW_2_B_ROI_SIZE_1 0xD0900
+
+#define mmMME_SHADOW_2_B_ROI_SIZE_2 0xD0904
+
+#define mmMME_SHADOW_2_B_ROI_SIZE_3 0xD0908
+
+#define mmMME_SHADOW_2_B_SPATIAL_START_OFFSET_0 0xD090C
+
+#define mmMME_SHADOW_2_B_SPATIAL_START_OFFSET_1 0xD0910
+
+#define mmMME_SHADOW_2_B_SPATIAL_START_OFFSET_2 0xD0914
+
+#define mmMME_SHADOW_2_B_SPATIAL_START_OFFSET_3 0xD0918
+
+#define mmMME_SHADOW_2_B_SPATIAL_STRIDE_0 0xD091C
+
+#define mmMME_SHADOW_2_B_SPATIAL_STRIDE_1 0xD0920
+
+#define mmMME_SHADOW_2_B_SPATIAL_STRIDE_2 0xD0924
+
+#define mmMME_SHADOW_2_B_SPATIAL_STRIDE_3 0xD0928
+
+#define mmMME_SHADOW_2_B_SPATIAL_SIZE_MINUS_1 0xD092C
+
+#define mmMME_SHADOW_2_C_ROI_BASE_OFFSET_0 0xD0930
+
+#define mmMME_SHADOW_2_C_ROI_BASE_OFFSET_1 0xD0934
+
+#define mmMME_SHADOW_2_C_ROI_BASE_OFFSET_2 0xD0938
+
+#define mmMME_SHADOW_2_C_ROI_BASE_OFFSET_3 0xD093C
+
+#define mmMME_SHADOW_2_C_ROI_BASE_OFFSET_4 0xD0940
+
+#define mmMME_SHADOW_2_C_VALID_ELEMENTS_0 0xD0944
+
+#define mmMME_SHADOW_2_C_VALID_ELEMENTS_1 0xD0948
+
+#define mmMME_SHADOW_2_C_VALID_ELEMENTS_2 0xD094C
+
+#define mmMME_SHADOW_2_C_VALID_ELEMENTS_3 0xD0950
+
+#define mmMME_SHADOW_2_C_VALID_ELEMENTS_4 0xD0954
+
+#define mmMME_SHADOW_2_C_LOOP_STRIDE_0 0xD0958
+
+#define mmMME_SHADOW_2_C_LOOP_STRIDE_1 0xD095C
+
+#define mmMME_SHADOW_2_C_LOOP_STRIDE_2 0xD0960
+
+#define mmMME_SHADOW_2_C_LOOP_STRIDE_3 0xD0964
+
+#define mmMME_SHADOW_2_C_LOOP_STRIDE_4 0xD0968
+
+#define mmMME_SHADOW_2_C_ROI_SIZE_0 0xD096C
+
+#define mmMME_SHADOW_2_C_ROI_SIZE_1 0xD0970
+
+#define mmMME_SHADOW_2_C_ROI_SIZE_2 0xD0974
+
+#define mmMME_SHADOW_2_C_ROI_SIZE_3 0xD0978
+
+#define mmMME_SHADOW_2_C_SPATIAL_START_OFFSET_0 0xD097C
+
+#define mmMME_SHADOW_2_C_SPATIAL_START_OFFSET_1 0xD0980
+
+#define mmMME_SHADOW_2_C_SPATIAL_START_OFFSET_2 0xD0984
+
+#define mmMME_SHADOW_2_C_SPATIAL_START_OFFSET_3 0xD0988
+
+#define mmMME_SHADOW_2_C_SPATIAL_STRIDE_0 0xD098C
+
+#define mmMME_SHADOW_2_C_SPATIAL_STRIDE_1 0xD0990
+
+#define mmMME_SHADOW_2_C_SPATIAL_STRIDE_2 0xD0994
+
+#define mmMME_SHADOW_2_C_SPATIAL_STRIDE_3 0xD0998
+
+#define mmMME_SHADOW_2_C_SPATIAL_SIZE_MINUS_1 0xD099C
+
+#define mmMME_SHADOW_2_SYNC_OBJECT_MESSAGE 0xD09A0
+
+#define mmMME_SHADOW_2_E_PADDING_VALUE_A 0xD09A4
+
+#define mmMME_SHADOW_2_E_NUM_ITERATION_MINUS_1 0xD09A8
+
+#define mmMME_SHADOW_2_E_BUBBLES_PER_SPLIT 0xD09AC
+
+#define mmMME_SHADOW_3_STATUS 0xD0A00
+
+#define mmMME_SHADOW_3_A_BASE_ADDR_HIGH 0xD0A08
+
+#define mmMME_SHADOW_3_B_BASE_ADDR_HIGH 0xD0A0C
+
+#define mmMME_SHADOW_3_CIN_BASE_ADDR_HIGH 0xD0A10
+
+#define mmMME_SHADOW_3_COUT_BASE_ADDR_HIGH 0xD0A14
+
+#define mmMME_SHADOW_3_BIAS_BASE_ADDR_HIGH 0xD0A18
+
+#define mmMME_SHADOW_3_A_BASE_ADDR_LOW 0xD0A1C
+
+#define mmMME_SHADOW_3_B_BASE_ADDR_LOW 0xD0A20
+
+#define mmMME_SHADOW_3_CIN_BASE_ADDR_LOW 0xD0A24
+
+#define mmMME_SHADOW_3_COUT_BASE_ADDR_LOW 0xD0A28
+
+#define mmMME_SHADOW_3_BIAS_BASE_ADDR_LOW 0xD0A2C
+
+#define mmMME_SHADOW_3_HEADER 0xD0A30
+
+#define mmMME_SHADOW_3_KERNEL_SIZE_MINUS_1 0xD0A34
+
+#define mmMME_SHADOW_3_ASSOCIATED_DIMS_0 0xD0A38
+
+#define mmMME_SHADOW_3_ASSOCIATED_DIMS_1 0xD0A3C
+
+#define mmMME_SHADOW_3_COUT_SCALE 0xD0A40
+
+#define mmMME_SHADOW_3_CIN_SCALE 0xD0A44
+
+#define mmMME_SHADOW_3_GEMMLOWP_ZP 0xD0A48
+
+#define mmMME_SHADOW_3_GEMMLOWP_EXPONENT 0xD0A4C
+
+#define mmMME_SHADOW_3_A_ROI_BASE_OFFSET_0 0xD0A50
+
+#define mmMME_SHADOW_3_A_ROI_BASE_OFFSET_1 0xD0A54
+
+#define mmMME_SHADOW_3_A_ROI_BASE_OFFSET_2 0xD0A58
+
+#define mmMME_SHADOW_3_A_ROI_BASE_OFFSET_3 0xD0A5C
+
+#define mmMME_SHADOW_3_A_ROI_BASE_OFFSET_4 0xD0A60
+
+#define mmMME_SHADOW_3_A_VALID_ELEMENTS_0 0xD0A64
+
+#define mmMME_SHADOW_3_A_VALID_ELEMENTS_1 0xD0A68
+
+#define mmMME_SHADOW_3_A_VALID_ELEMENTS_2 0xD0A6C
+
+#define mmMME_SHADOW_3_A_VALID_ELEMENTS_3 0xD0A70
+
+#define mmMME_SHADOW_3_A_VALID_ELEMENTS_4 0xD0A74
+
+#define mmMME_SHADOW_3_A_LOOP_STRIDE_0 0xD0A78
+
+#define mmMME_SHADOW_3_A_LOOP_STRIDE_1 0xD0A7C
+
+#define mmMME_SHADOW_3_A_LOOP_STRIDE_2 0xD0A80
+
+#define mmMME_SHADOW_3_A_LOOP_STRIDE_3 0xD0A84
+
+#define mmMME_SHADOW_3_A_LOOP_STRIDE_4 0xD0A88
+
+#define mmMME_SHADOW_3_A_ROI_SIZE_0 0xD0A8C
+
+#define mmMME_SHADOW_3_A_ROI_SIZE_1 0xD0A90
+
+#define mmMME_SHADOW_3_A_ROI_SIZE_2 0xD0A94
+
+#define mmMME_SHADOW_3_A_ROI_SIZE_3 0xD0A98
+
+#define mmMME_SHADOW_3_A_SPATIAL_START_OFFSET_0 0xD0A9C
+
+#define mmMME_SHADOW_3_A_SPATIAL_START_OFFSET_1 0xD0AA0
+
+#define mmMME_SHADOW_3_A_SPATIAL_START_OFFSET_2 0xD0AA4
+
+#define mmMME_SHADOW_3_A_SPATIAL_START_OFFSET_3 0xD0AA8
+
+#define mmMME_SHADOW_3_A_SPATIAL_STRIDE_0 0xD0AAC
+
+#define mmMME_SHADOW_3_A_SPATIAL_STRIDE_1 0xD0AB0
+
+#define mmMME_SHADOW_3_A_SPATIAL_STRIDE_2 0xD0AB4
+
+#define mmMME_SHADOW_3_A_SPATIAL_STRIDE_3 0xD0AB8
+
+#define mmMME_SHADOW_3_A_SPATIAL_SIZE_MINUS_1 0xD0ABC
+
+#define mmMME_SHADOW_3_B_ROI_BASE_OFFSET_0 0xD0AC0
+
+#define mmMME_SHADOW_3_B_ROI_BASE_OFFSET_1 0xD0AC4
+
+#define mmMME_SHADOW_3_B_ROI_BASE_OFFSET_2 0xD0AC8
+
+#define mmMME_SHADOW_3_B_ROI_BASE_OFFSET_3 0xD0ACC
+
+#define mmMME_SHADOW_3_B_ROI_BASE_OFFSET_4 0xD0AD0
+
+#define mmMME_SHADOW_3_B_VALID_ELEMENTS_0 0xD0AD4
+
+#define mmMME_SHADOW_3_B_VALID_ELEMENTS_1 0xD0AD8
+
+#define mmMME_SHADOW_3_B_VALID_ELEMENTS_2 0xD0ADC
+
+#define mmMME_SHADOW_3_B_VALID_ELEMENTS_3 0xD0AE0
+
+#define mmMME_SHADOW_3_B_VALID_ELEMENTS_4 0xD0AE4
+
+#define mmMME_SHADOW_3_B_LOOP_STRIDE_0 0xD0AE8
+
+#define mmMME_SHADOW_3_B_LOOP_STRIDE_1 0xD0AEC
+
+#define mmMME_SHADOW_3_B_LOOP_STRIDE_2 0xD0AF0
+
+#define mmMME_SHADOW_3_B_LOOP_STRIDE_3 0xD0AF4
+
+#define mmMME_SHADOW_3_B_LOOP_STRIDE_4 0xD0AF8
+
+#define mmMME_SHADOW_3_B_ROI_SIZE_0 0xD0AFC
+
+#define mmMME_SHADOW_3_B_ROI_SIZE_1 0xD0B00
+
+#define mmMME_SHADOW_3_B_ROI_SIZE_2 0xD0B04
+
+#define mmMME_SHADOW_3_B_ROI_SIZE_3 0xD0B08
+
+#define mmMME_SHADOW_3_B_SPATIAL_START_OFFSET_0 0xD0B0C
+
+#define mmMME_SHADOW_3_B_SPATIAL_START_OFFSET_1 0xD0B10
+
+#define mmMME_SHADOW_3_B_SPATIAL_START_OFFSET_2 0xD0B14
+
+#define mmMME_SHADOW_3_B_SPATIAL_START_OFFSET_3 0xD0B18
+
+#define mmMME_SHADOW_3_B_SPATIAL_STRIDE_0 0xD0B1C
+
+#define mmMME_SHADOW_3_B_SPATIAL_STRIDE_1 0xD0B20
+
+#define mmMME_SHADOW_3_B_SPATIAL_STRIDE_2 0xD0B24
+
+#define mmMME_SHADOW_3_B_SPATIAL_STRIDE_3 0xD0B28
+
+#define mmMME_SHADOW_3_B_SPATIAL_SIZE_MINUS_1 0xD0B2C
+
+#define mmMME_SHADOW_3_C_ROI_BASE_OFFSET_0 0xD0B30
+
+#define mmMME_SHADOW_3_C_ROI_BASE_OFFSET_1 0xD0B34
+
+#define mmMME_SHADOW_3_C_ROI_BASE_OFFSET_2 0xD0B38
+
+#define mmMME_SHADOW_3_C_ROI_BASE_OFFSET_3 0xD0B3C
+
+#define mmMME_SHADOW_3_C_ROI_BASE_OFFSET_4 0xD0B40
+
+#define mmMME_SHADOW_3_C_VALID_ELEMENTS_0 0xD0B44
+
+#define mmMME_SHADOW_3_C_VALID_ELEMENTS_1 0xD0B48
+
+#define mmMME_SHADOW_3_C_VALID_ELEMENTS_2 0xD0B4C
+
+#define mmMME_SHADOW_3_C_VALID_ELEMENTS_3 0xD0B50
+
+#define mmMME_SHADOW_3_C_VALID_ELEMENTS_4 0xD0B54
+
+#define mmMME_SHADOW_3_C_LOOP_STRIDE_0 0xD0B58
+
+#define mmMME_SHADOW_3_C_LOOP_STRIDE_1 0xD0B5C
+
+#define mmMME_SHADOW_3_C_LOOP_STRIDE_2 0xD0B60
+
+#define mmMME_SHADOW_3_C_LOOP_STRIDE_3 0xD0B64
+
+#define mmMME_SHADOW_3_C_LOOP_STRIDE_4 0xD0B68
+
+#define mmMME_SHADOW_3_C_ROI_SIZE_0 0xD0B6C
+
+#define mmMME_SHADOW_3_C_ROI_SIZE_1 0xD0B70
+
+#define mmMME_SHADOW_3_C_ROI_SIZE_2 0xD0B74
+
+#define mmMME_SHADOW_3_C_ROI_SIZE_3 0xD0B78
+
+#define mmMME_SHADOW_3_C_SPATIAL_START_OFFSET_0 0xD0B7C
+
+#define mmMME_SHADOW_3_C_SPATIAL_START_OFFSET_1 0xD0B80
+
+#define mmMME_SHADOW_3_C_SPATIAL_START_OFFSET_2 0xD0B84
+
+#define mmMME_SHADOW_3_C_SPATIAL_START_OFFSET_3 0xD0B88
+
+#define mmMME_SHADOW_3_C_SPATIAL_STRIDE_0 0xD0B8C
+
+#define mmMME_SHADOW_3_C_SPATIAL_STRIDE_1 0xD0B90
+
+#define mmMME_SHADOW_3_C_SPATIAL_STRIDE_2 0xD0B94
+
+#define mmMME_SHADOW_3_C_SPATIAL_STRIDE_3 0xD0B98
+
+#define mmMME_SHADOW_3_C_SPATIAL_SIZE_MINUS_1 0xD0B9C
+
+#define mmMME_SHADOW_3_SYNC_OBJECT_MESSAGE 0xD0BA0
+
+#define mmMME_SHADOW_3_E_PADDING_VALUE_A 0xD0BA4
+
+#define mmMME_SHADOW_3_E_NUM_ITERATION_MINUS_1 0xD0BA8
+
+#define mmMME_SHADOW_3_E_BUBBLES_PER_SPLIT 0xD0BAC
+
+#endif /* ASIC_REG_MME_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h
new file mode 100644
index 000000000000..3a78078d3c4c
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mmu_masks.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MMU_MASKS_H_
+#define ASIC_REG_MMU_MASKS_H_
+
+/*
+ *****************************************
+ * MMU (Prototype: MMU)
+ *****************************************
+ */
+
+/* MMU_INPUT_FIFO_THRESHOLD */
+#define MMU_INPUT_FIFO_THRESHOLD_PCI_SHIFT 0
+#define MMU_INPUT_FIFO_THRESHOLD_PCI_MASK 0x7
+#define MMU_INPUT_FIFO_THRESHOLD_PSOC_SHIFT 4
+#define MMU_INPUT_FIFO_THRESHOLD_PSOC_MASK 0x70
+#define MMU_INPUT_FIFO_THRESHOLD_DMA_SHIFT 8
+#define MMU_INPUT_FIFO_THRESHOLD_DMA_MASK 0x700
+#define MMU_INPUT_FIFO_THRESHOLD_CPU_SHIFT 12
+#define MMU_INPUT_FIFO_THRESHOLD_CPU_MASK 0x7000
+#define MMU_INPUT_FIFO_THRESHOLD_MME_SHIFT 16
+#define MMU_INPUT_FIFO_THRESHOLD_MME_MASK 0x70000
+#define MMU_INPUT_FIFO_THRESHOLD_TPC_SHIFT 20
+#define MMU_INPUT_FIFO_THRESHOLD_TPC_MASK 0x700000
+#define MMU_INPUT_FIFO_THRESHOLD_OTHER_SHIFT 24
+#define MMU_INPUT_FIFO_THRESHOLD_OTHER_MASK 0x7000000
+
+/* MMU_MMU_ENABLE */
+#define MMU_MMU_ENABLE_R_SHIFT 0
+#define MMU_MMU_ENABLE_R_MASK 0x1
+
+/* MMU_FORCE_ORDERING */
+#define MMU_FORCE_ORDERING_DMA_WEAK_ORDERING_SHIFT 0
+#define MMU_FORCE_ORDERING_DMA_WEAK_ORDERING_MASK 0x1
+#define MMU_FORCE_ORDERING_PSOC_WEAK_ORDERING_SHIFT 1
+#define MMU_FORCE_ORDERING_PSOC_WEAK_ORDERING_MASK 0x2
+#define MMU_FORCE_ORDERING_PCI_WEAK_ORDERING_SHIFT 2
+#define MMU_FORCE_ORDERING_PCI_WEAK_ORDERING_MASK 0x4
+#define MMU_FORCE_ORDERING_CPU_WEAK_ORDERING_SHIFT 3
+#define MMU_FORCE_ORDERING_CPU_WEAK_ORDERING_MASK 0x8
+#define MMU_FORCE_ORDERING_MME_WEAK_ORDERING_SHIFT 4
+#define MMU_FORCE_ORDERING_MME_WEAK_ORDERING_MASK 0x10
+#define MMU_FORCE_ORDERING_TPC_WEAK_ORDERING_SHIFT 5
+#define MMU_FORCE_ORDERING_TPC_WEAK_ORDERING_MASK 0x20
+#define MMU_FORCE_ORDERING_DEFAULT_WEAK_ORDERING_SHIFT 6
+#define MMU_FORCE_ORDERING_DEFAULT_WEAK_ORDERING_MASK 0x40
+#define MMU_FORCE_ORDERING_DMA_STRONG_ORDERING_SHIFT 8
+#define MMU_FORCE_ORDERING_DMA_STRONG_ORDERING_MASK 0x100
+#define MMU_FORCE_ORDERING_PSOC_STRONG_ORDERING_SHIFT 9
+#define MMU_FORCE_ORDERING_PSOC_STRONG_ORDERING_MASK 0x200
+#define MMU_FORCE_ORDERING_PCI_STRONG_ORDERING_SHIFT 10
+#define MMU_FORCE_ORDERING_PCI_STRONG_ORDERING_MASK 0x400
+#define MMU_FORCE_ORDERING_CPU_STRONG_ORDERING_SHIFT 11
+#define MMU_FORCE_ORDERING_CPU_STRONG_ORDERING_MASK 0x800
+#define MMU_FORCE_ORDERING_MME_STRONG_ORDERING_SHIFT 12
+#define MMU_FORCE_ORDERING_MME_STRONG_ORDERING_MASK 0x1000
+#define MMU_FORCE_ORDERING_TPC_STRONG_ORDERING_SHIFT 13
+#define MMU_FORCE_ORDERING_TPC_STRONG_ORDERING_MASK 0x2000
+#define MMU_FORCE_ORDERING_DEFAULT_STRONG_ORDERING_SHIFT 14
+#define MMU_FORCE_ORDERING_DEFAULT_STRONG_ORDERING_MASK 0x4000
+
+/* MMU_FEATURE_ENABLE */
+#define MMU_FEATURE_ENABLE_VA_ORDERING_EN_SHIFT 0
+#define MMU_FEATURE_ENABLE_VA_ORDERING_EN_MASK 0x1
+#define MMU_FEATURE_ENABLE_CLEAN_LINK_LIST_SHIFT 1
+#define MMU_FEATURE_ENABLE_CLEAN_LINK_LIST_MASK 0x2
+#define MMU_FEATURE_ENABLE_HOP_OFFSET_EN_SHIFT 2
+#define MMU_FEATURE_ENABLE_HOP_OFFSET_EN_MASK 0x4
+#define MMU_FEATURE_ENABLE_OBI_ORDERING_EN_SHIFT 3
+#define MMU_FEATURE_ENABLE_OBI_ORDERING_EN_MASK 0x8
+#define MMU_FEATURE_ENABLE_STRONG_ORDERING_READ_EN_SHIFT 4
+#define MMU_FEATURE_ENABLE_STRONG_ORDERING_READ_EN_MASK 0x10
+#define MMU_FEATURE_ENABLE_TRACE_ENABLE_SHIFT 5
+#define MMU_FEATURE_ENABLE_TRACE_ENABLE_MASK 0x20
+
+/* MMU_VA_ORDERING_MASK_31_7 */
+#define MMU_VA_ORDERING_MASK_31_7_R_SHIFT 0
+#define MMU_VA_ORDERING_MASK_31_7_R_MASK 0x1FFFFFF
+
+/* MMU_VA_ORDERING_MASK_49_32 */
+#define MMU_VA_ORDERING_MASK_49_32_R_SHIFT 0
+#define MMU_VA_ORDERING_MASK_49_32_R_MASK 0x3FFFF
+
+/* MMU_LOG2_DDR_SIZE */
+#define MMU_LOG2_DDR_SIZE_R_SHIFT 0
+#define MMU_LOG2_DDR_SIZE_R_MASK 0xFF
+
+/* MMU_SCRAMBLER */
+#define MMU_SCRAMBLER_ADDR_BIT_SHIFT 0
+#define MMU_SCRAMBLER_ADDR_BIT_MASK 0x3F
+#define MMU_SCRAMBLER_SINGLE_DDR_EN_SHIFT 6
+#define MMU_SCRAMBLER_SINGLE_DDR_EN_MASK 0x40
+#define MMU_SCRAMBLER_SINGLE_DDR_ID_SHIFT 7
+#define MMU_SCRAMBLER_SINGLE_DDR_ID_MASK 0x80
+
+/* MMU_MEM_INIT_BUSY */
+#define MMU_MEM_INIT_BUSY_DATA_SHIFT 0
+#define MMU_MEM_INIT_BUSY_DATA_MASK 0x3
+#define MMU_MEM_INIT_BUSY_OBI0_SHIFT 2
+#define MMU_MEM_INIT_BUSY_OBI0_MASK 0x4
+#define MMU_MEM_INIT_BUSY_OBI1_SHIFT 3
+#define MMU_MEM_INIT_BUSY_OBI1_MASK 0x8
+
+/* MMU_SPI_MASK */
+#define MMU_SPI_MASK_R_SHIFT 0
+#define MMU_SPI_MASK_R_MASK 0xFF
+
+/* MMU_SPI_CAUSE */
+#define MMU_SPI_CAUSE_R_SHIFT 0
+#define MMU_SPI_CAUSE_R_MASK 0xFF
+
+/* MMU_PAGE_ERROR_CAPTURE */
+#define MMU_PAGE_ERROR_CAPTURE_VA_49_32_SHIFT 0
+#define MMU_PAGE_ERROR_CAPTURE_VA_49_32_MASK 0x3FFFF
+#define MMU_PAGE_ERROR_CAPTURE_ENTRY_VALID_SHIFT 18
+#define MMU_PAGE_ERROR_CAPTURE_ENTRY_VALID_MASK 0x40000
+
+/* MMU_PAGE_ERROR_CAPTURE_VA */
+#define MMU_PAGE_ERROR_CAPTURE_VA_VA_31_0_SHIFT 0
+#define MMU_PAGE_ERROR_CAPTURE_VA_VA_31_0_MASK 0xFFFFFFFF
+
+/* MMU_ACCESS_ERROR_CAPTURE */
+#define MMU_ACCESS_ERROR_CAPTURE_VA_49_32_SHIFT 0
+#define MMU_ACCESS_ERROR_CAPTURE_VA_49_32_MASK 0x3FFFF
+#define MMU_ACCESS_ERROR_CAPTURE_ENTRY_VALID_SHIFT 18
+#define MMU_ACCESS_ERROR_CAPTURE_ENTRY_VALID_MASK 0x40000
+
+/* MMU_ACCESS_ERROR_CAPTURE_VA */
+#define MMU_ACCESS_ERROR_CAPTURE_VA_VA_31_0_SHIFT 0
+#define MMU_ACCESS_ERROR_CAPTURE_VA_VA_31_0_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_MMU_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h
new file mode 100644
index 000000000000..bec6c014135c
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/mmu_regs.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_MMU_REGS_H_
+#define ASIC_REG_MMU_REGS_H_
+
+/*
+ *****************************************
+ * MMU (Prototype: MMU)
+ *****************************************
+ */
+
+#define mmMMU_INPUT_FIFO_THRESHOLD 0x480000
+
+#define mmMMU_MMU_ENABLE 0x48000C
+
+#define mmMMU_FORCE_ORDERING 0x480010
+
+#define mmMMU_FEATURE_ENABLE 0x480014
+
+#define mmMMU_VA_ORDERING_MASK_31_7 0x480018
+
+#define mmMMU_VA_ORDERING_MASK_49_32 0x48001C
+
+#define mmMMU_LOG2_DDR_SIZE 0x480020
+
+#define mmMMU_SCRAMBLER 0x480024
+
+#define mmMMU_MEM_INIT_BUSY 0x480028
+
+#define mmMMU_SPI_MASK 0x48002C
+
+#define mmMMU_SPI_CAUSE 0x480030
+
+#define mmMMU_PAGE_ERROR_CAPTURE 0x480034
+
+#define mmMMU_PAGE_ERROR_CAPTURE_VA 0x480038
+
+#define mmMMU_ACCESS_ERROR_CAPTURE 0x48003C
+
+#define mmMMU_ACCESS_ERROR_CAPTURE_VA 0x480040
+
+#endif /* ASIC_REG_MMU_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h
new file mode 100644
index 000000000000..209e41402a11
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_masks.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PCI_NRTR_MASKS_H_
+#define ASIC_REG_PCI_NRTR_MASKS_H_
+
+/*
+ *****************************************
+ * PCI_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+/* PCI_NRTR_HBW_MAX_CRED */
+#define PCI_NRTR_HBW_MAX_CRED_WR_RQ_SHIFT 0
+#define PCI_NRTR_HBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define PCI_NRTR_HBW_MAX_CRED_WR_RS_SHIFT 8
+#define PCI_NRTR_HBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define PCI_NRTR_HBW_MAX_CRED_RD_RQ_SHIFT 16
+#define PCI_NRTR_HBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define PCI_NRTR_HBW_MAX_CRED_RD_RS_SHIFT 24
+#define PCI_NRTR_HBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* PCI_NRTR_LBW_MAX_CRED */
+#define PCI_NRTR_LBW_MAX_CRED_WR_RQ_SHIFT 0
+#define PCI_NRTR_LBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define PCI_NRTR_LBW_MAX_CRED_WR_RS_SHIFT 8
+#define PCI_NRTR_LBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define PCI_NRTR_LBW_MAX_CRED_RD_RQ_SHIFT 16
+#define PCI_NRTR_LBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define PCI_NRTR_LBW_MAX_CRED_RD_RS_SHIFT 24
+#define PCI_NRTR_LBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* PCI_NRTR_DBG_E_ARB */
+#define PCI_NRTR_DBG_E_ARB_W_SHIFT 0
+#define PCI_NRTR_DBG_E_ARB_W_MASK 0x7
+#define PCI_NRTR_DBG_E_ARB_S_SHIFT 8
+#define PCI_NRTR_DBG_E_ARB_S_MASK 0x700
+#define PCI_NRTR_DBG_E_ARB_N_SHIFT 16
+#define PCI_NRTR_DBG_E_ARB_N_MASK 0x70000
+#define PCI_NRTR_DBG_E_ARB_L_SHIFT 24
+#define PCI_NRTR_DBG_E_ARB_L_MASK 0x7000000
+
+/* PCI_NRTR_DBG_W_ARB */
+#define PCI_NRTR_DBG_W_ARB_E_SHIFT 0
+#define PCI_NRTR_DBG_W_ARB_E_MASK 0x7
+#define PCI_NRTR_DBG_W_ARB_S_SHIFT 8
+#define PCI_NRTR_DBG_W_ARB_S_MASK 0x700
+#define PCI_NRTR_DBG_W_ARB_N_SHIFT 16
+#define PCI_NRTR_DBG_W_ARB_N_MASK 0x70000
+#define PCI_NRTR_DBG_W_ARB_L_SHIFT 24
+#define PCI_NRTR_DBG_W_ARB_L_MASK 0x7000000
+
+/* PCI_NRTR_DBG_N_ARB */
+#define PCI_NRTR_DBG_N_ARB_W_SHIFT 0
+#define PCI_NRTR_DBG_N_ARB_W_MASK 0x7
+#define PCI_NRTR_DBG_N_ARB_E_SHIFT 8
+#define PCI_NRTR_DBG_N_ARB_E_MASK 0x700
+#define PCI_NRTR_DBG_N_ARB_S_SHIFT 16
+#define PCI_NRTR_DBG_N_ARB_S_MASK 0x70000
+#define PCI_NRTR_DBG_N_ARB_L_SHIFT 24
+#define PCI_NRTR_DBG_N_ARB_L_MASK 0x7000000
+
+/* PCI_NRTR_DBG_S_ARB */
+#define PCI_NRTR_DBG_S_ARB_W_SHIFT 0
+#define PCI_NRTR_DBG_S_ARB_W_MASK 0x7
+#define PCI_NRTR_DBG_S_ARB_E_SHIFT 8
+#define PCI_NRTR_DBG_S_ARB_E_MASK 0x700
+#define PCI_NRTR_DBG_S_ARB_N_SHIFT 16
+#define PCI_NRTR_DBG_S_ARB_N_MASK 0x70000
+#define PCI_NRTR_DBG_S_ARB_L_SHIFT 24
+#define PCI_NRTR_DBG_S_ARB_L_MASK 0x7000000
+
+/* PCI_NRTR_DBG_L_ARB */
+#define PCI_NRTR_DBG_L_ARB_W_SHIFT 0
+#define PCI_NRTR_DBG_L_ARB_W_MASK 0x7
+#define PCI_NRTR_DBG_L_ARB_E_SHIFT 8
+#define PCI_NRTR_DBG_L_ARB_E_MASK 0x700
+#define PCI_NRTR_DBG_L_ARB_S_SHIFT 16
+#define PCI_NRTR_DBG_L_ARB_S_MASK 0x70000
+#define PCI_NRTR_DBG_L_ARB_N_SHIFT 24
+#define PCI_NRTR_DBG_L_ARB_N_MASK 0x7000000
+
+/* PCI_NRTR_DBG_E_ARB_MAX */
+#define PCI_NRTR_DBG_E_ARB_MAX_CREDIT_SHIFT 0
+#define PCI_NRTR_DBG_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* PCI_NRTR_DBG_W_ARB_MAX */
+#define PCI_NRTR_DBG_W_ARB_MAX_CREDIT_SHIFT 0
+#define PCI_NRTR_DBG_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* PCI_NRTR_DBG_N_ARB_MAX */
+#define PCI_NRTR_DBG_N_ARB_MAX_CREDIT_SHIFT 0
+#define PCI_NRTR_DBG_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* PCI_NRTR_DBG_S_ARB_MAX */
+#define PCI_NRTR_DBG_S_ARB_MAX_CREDIT_SHIFT 0
+#define PCI_NRTR_DBG_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* PCI_NRTR_DBG_L_ARB_MAX */
+#define PCI_NRTR_DBG_L_ARB_MAX_CREDIT_SHIFT 0
+#define PCI_NRTR_DBG_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* PCI_NRTR_SPLIT_COEF */
+#define PCI_NRTR_SPLIT_COEF_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_COEF_VAL_MASK 0xFFFF
+
+/* PCI_NRTR_SPLIT_CFG */
+#define PCI_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_SHIFT 0
+#define PCI_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_MASK 0x1
+#define PCI_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_SHIFT 1
+#define PCI_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_MASK 0x2
+#define PCI_NRTR_SPLIT_CFG_DEFAULT_MESH_SHIFT 2
+#define PCI_NRTR_SPLIT_CFG_DEFAULT_MESH_MASK 0xC
+#define PCI_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_SHIFT 4
+#define PCI_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_MASK 0x10
+#define PCI_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_SHIFT 5
+#define PCI_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_MASK 0x20
+#define PCI_NRTR_SPLIT_CFG_B2B_OPT_SHIFT 6
+#define PCI_NRTR_SPLIT_CFG_B2B_OPT_MASK 0x1C0
+
+/* PCI_NRTR_SPLIT_RD_SAT */
+#define PCI_NRTR_SPLIT_RD_SAT_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_RD_SAT_VAL_MASK 0xFFFF
+
+/* PCI_NRTR_SPLIT_RD_RST_TOKEN */
+#define PCI_NRTR_SPLIT_RD_RST_TOKEN_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_RD_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* PCI_NRTR_SPLIT_RD_TIMEOUT */
+#define PCI_NRTR_SPLIT_RD_TIMEOUT_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_RD_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* PCI_NRTR_SPLIT_WR_SAT */
+#define PCI_NRTR_SPLIT_WR_SAT_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_WR_SAT_VAL_MASK 0xFFFF
+
+/* PCI_NRTR_WPLIT_WR_TST_TOLEN */
+#define PCI_NRTR_WPLIT_WR_TST_TOLEN_VAL_SHIFT 0
+#define PCI_NRTR_WPLIT_WR_TST_TOLEN_VAL_MASK 0xFFFF
+
+/* PCI_NRTR_SPLIT_WR_TIMEOUT */
+#define PCI_NRTR_SPLIT_WR_TIMEOUT_VAL_SHIFT 0
+#define PCI_NRTR_SPLIT_WR_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* PCI_NRTR_HBW_RANGE_HIT */
+#define PCI_NRTR_HBW_RANGE_HIT_IND_SHIFT 0
+#define PCI_NRTR_HBW_RANGE_HIT_IND_MASK 0xFF
+
+/* PCI_NRTR_HBW_RANGE_MASK_L */
+#define PCI_NRTR_HBW_RANGE_MASK_L_VAL_SHIFT 0
+#define PCI_NRTR_HBW_RANGE_MASK_L_VAL_MASK 0xFFFFFFFF
+
+/* PCI_NRTR_HBW_RANGE_MASK_H */
+#define PCI_NRTR_HBW_RANGE_MASK_H_VAL_SHIFT 0
+#define PCI_NRTR_HBW_RANGE_MASK_H_VAL_MASK 0x3FFFF
+
+/* PCI_NRTR_HBW_RANGE_BASE_L */
+#define PCI_NRTR_HBW_RANGE_BASE_L_VAL_SHIFT 0
+#define PCI_NRTR_HBW_RANGE_BASE_L_VAL_MASK 0xFFFFFFFF
+
+/* PCI_NRTR_HBW_RANGE_BASE_H */
+#define PCI_NRTR_HBW_RANGE_BASE_H_VAL_SHIFT 0
+#define PCI_NRTR_HBW_RANGE_BASE_H_VAL_MASK 0x3FFFF
+
+/* PCI_NRTR_LBW_RANGE_HIT */
+#define PCI_NRTR_LBW_RANGE_HIT_IND_SHIFT 0
+#define PCI_NRTR_LBW_RANGE_HIT_IND_MASK 0xFFFF
+
+/* PCI_NRTR_LBW_RANGE_MASK */
+#define PCI_NRTR_LBW_RANGE_MASK_VAL_SHIFT 0
+#define PCI_NRTR_LBW_RANGE_MASK_VAL_MASK 0x3FFFFFF
+
+/* PCI_NRTR_LBW_RANGE_BASE */
+#define PCI_NRTR_LBW_RANGE_BASE_VAL_SHIFT 0
+#define PCI_NRTR_LBW_RANGE_BASE_VAL_MASK 0x3FFFFFF
+
+/* PCI_NRTR_RGLTR */
+#define PCI_NRTR_RGLTR_WR_EN_SHIFT 0
+#define PCI_NRTR_RGLTR_WR_EN_MASK 0x1
+#define PCI_NRTR_RGLTR_RD_EN_SHIFT 4
+#define PCI_NRTR_RGLTR_RD_EN_MASK 0x10
+
+/* PCI_NRTR_RGLTR_WR_RESULT */
+#define PCI_NRTR_RGLTR_WR_RESULT_VAL_SHIFT 0
+#define PCI_NRTR_RGLTR_WR_RESULT_VAL_MASK 0xFF
+
+/* PCI_NRTR_RGLTR_RD_RESULT */
+#define PCI_NRTR_RGLTR_RD_RESULT_VAL_SHIFT 0
+#define PCI_NRTR_RGLTR_RD_RESULT_VAL_MASK 0xFF
+
+/* PCI_NRTR_SCRAMB_EN */
+#define PCI_NRTR_SCRAMB_EN_VAL_SHIFT 0
+#define PCI_NRTR_SCRAMB_EN_VAL_MASK 0x1
+
+/* PCI_NRTR_NON_LIN_SCRAMB */
+#define PCI_NRTR_NON_LIN_SCRAMB_EN_SHIFT 0
+#define PCI_NRTR_NON_LIN_SCRAMB_EN_MASK 0x1
+
+#endif /* ASIC_REG_PCI_NRTR_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h
new file mode 100644
index 000000000000..447e5d4e7dc8
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/pci_nrtr_regs.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PCI_NRTR_REGS_H_
+#define ASIC_REG_PCI_NRTR_REGS_H_
+
+/*
+ *****************************************
+ * PCI_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+#define mmPCI_NRTR_HBW_MAX_CRED 0x100
+
+#define mmPCI_NRTR_LBW_MAX_CRED 0x120
+
+#define mmPCI_NRTR_DBG_E_ARB 0x300
+
+#define mmPCI_NRTR_DBG_W_ARB 0x304
+
+#define mmPCI_NRTR_DBG_N_ARB 0x308
+
+#define mmPCI_NRTR_DBG_S_ARB 0x30C
+
+#define mmPCI_NRTR_DBG_L_ARB 0x310
+
+#define mmPCI_NRTR_DBG_E_ARB_MAX 0x320
+
+#define mmPCI_NRTR_DBG_W_ARB_MAX 0x324
+
+#define mmPCI_NRTR_DBG_N_ARB_MAX 0x328
+
+#define mmPCI_NRTR_DBG_S_ARB_MAX 0x32C
+
+#define mmPCI_NRTR_DBG_L_ARB_MAX 0x330
+
+#define mmPCI_NRTR_SPLIT_COEF_0 0x400
+
+#define mmPCI_NRTR_SPLIT_COEF_1 0x404
+
+#define mmPCI_NRTR_SPLIT_COEF_2 0x408
+
+#define mmPCI_NRTR_SPLIT_COEF_3 0x40C
+
+#define mmPCI_NRTR_SPLIT_COEF_4 0x410
+
+#define mmPCI_NRTR_SPLIT_COEF_5 0x414
+
+#define mmPCI_NRTR_SPLIT_COEF_6 0x418
+
+#define mmPCI_NRTR_SPLIT_COEF_7 0x41C
+
+#define mmPCI_NRTR_SPLIT_COEF_8 0x420
+
+#define mmPCI_NRTR_SPLIT_COEF_9 0x424
+
+#define mmPCI_NRTR_SPLIT_CFG 0x440
+
+#define mmPCI_NRTR_SPLIT_RD_SAT 0x444
+
+#define mmPCI_NRTR_SPLIT_RD_RST_TOKEN 0x448
+
+#define mmPCI_NRTR_SPLIT_RD_TIMEOUT_0 0x44C
+
+#define mmPCI_NRTR_SPLIT_RD_TIMEOUT_1 0x450
+
+#define mmPCI_NRTR_SPLIT_WR_SAT 0x454
+
+#define mmPCI_NRTR_WPLIT_WR_TST_TOLEN 0x458
+
+#define mmPCI_NRTR_SPLIT_WR_TIMEOUT_0 0x45C
+
+#define mmPCI_NRTR_SPLIT_WR_TIMEOUT_1 0x460
+
+#define mmPCI_NRTR_HBW_RANGE_HIT 0x470
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_0 0x480
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_1 0x484
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_2 0x488
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_3 0x48C
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_4 0x490
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_5 0x494
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_6 0x498
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_L_7 0x49C
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_0 0x4A0
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_1 0x4A4
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_2 0x4A8
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_3 0x4AC
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_4 0x4B0
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_5 0x4B4
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_6 0x4B8
+
+#define mmPCI_NRTR_HBW_RANGE_MASK_H_7 0x4BC
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_0 0x4C0
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_1 0x4C4
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_2 0x4C8
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_3 0x4CC
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_4 0x4D0
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_5 0x4D4
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_6 0x4D8
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_L_7 0x4DC
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_0 0x4E0
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_1 0x4E4
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_2 0x4E8
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_3 0x4EC
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_4 0x4F0
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_5 0x4F4
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_6 0x4F8
+
+#define mmPCI_NRTR_HBW_RANGE_BASE_H_7 0x4FC
+
+#define mmPCI_NRTR_LBW_RANGE_HIT 0x500
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_0 0x510
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_1 0x514
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_2 0x518
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_3 0x51C
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_4 0x520
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_5 0x524
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_6 0x528
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_7 0x52C
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_8 0x530
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_9 0x534
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_10 0x538
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_11 0x53C
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_12 0x540
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_13 0x544
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_14 0x548
+
+#define mmPCI_NRTR_LBW_RANGE_MASK_15 0x54C
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_0 0x550
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_1 0x554
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_2 0x558
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_3 0x55C
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_4 0x560
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_5 0x564
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_6 0x568
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_7 0x56C
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_8 0x570
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_9 0x574
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_10 0x578
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_11 0x57C
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_12 0x580
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_13 0x584
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_14 0x588
+
+#define mmPCI_NRTR_LBW_RANGE_BASE_15 0x58C
+
+#define mmPCI_NRTR_RGLTR 0x590
+
+#define mmPCI_NRTR_RGLTR_WR_RESULT 0x594
+
+#define mmPCI_NRTR_RGLTR_RD_RESULT 0x598
+
+#define mmPCI_NRTR_SCRAMB_EN 0x600
+
+#define mmPCI_NRTR_NON_LIN_SCRAMB 0x604
+
+#endif /* ASIC_REG_PCI_NRTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h
new file mode 100644
index 000000000000..daaf5d9079dc
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/pcie_aux_regs.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PCIE_AUX_REGS_H_
+#define ASIC_REG_PCIE_AUX_REGS_H_
+
+/*
+ *****************************************
+ * PCIE_AUX (Prototype: PCIE_AUX)
+ *****************************************
+ */
+
+#define mmPCIE_AUX_APB_TIMEOUT 0xC07004
+
+#define mmPCIE_AUX_PHY_INIT 0xC07100
+
+#define mmPCIE_AUX_LTR_MAX_LATENCY 0xC07138
+
+#define mmPCIE_AUX_BAR0_START_L 0xC07160
+
+#define mmPCIE_AUX_BAR0_START_H 0xC07164
+
+#define mmPCIE_AUX_BAR1_START 0xC07168
+
+#define mmPCIE_AUX_BAR2_START_L 0xC0716C
+
+#define mmPCIE_AUX_BAR2_START_H 0xC07170
+
+#define mmPCIE_AUX_BAR3_START 0xC07174
+
+#define mmPCIE_AUX_BAR4_START_L 0xC07178
+
+#define mmPCIE_AUX_BAR4_START_H 0xC0717C
+
+#define mmPCIE_AUX_BAR5_START 0xC07180
+
+#define mmPCIE_AUX_BAR0_LIMIT_L 0xC07184
+
+#define mmPCIE_AUX_BAR0_LIMIT_H 0xC07188
+
+#define mmPCIE_AUX_BAR1_LIMIT 0xC0718C
+
+#define mmPCIE_AUX_BAR2_LIMIT_L 0xC07190
+
+#define mmPCIE_AUX_BAR2_LIMIT_H 0xC07194
+
+#define mmPCIE_AUX_BAR3_LIMIT 0xC07198
+
+#define mmPCIE_AUX_BAR4_LIMIT_L 0xC0719C
+
+#define mmPCIE_AUX_BAR4_LIMIT_H 0xC07200
+
+#define mmPCIE_AUX_BAR5_LIMIT 0xC07204
+
+#define mmPCIE_AUX_BUS_MASTER_EN 0xC07208
+
+#define mmPCIE_AUX_MEM_SPACE_EN 0xC0720C
+
+#define mmPCIE_AUX_MAX_RD_REQ_SIZE 0xC07210
+
+#define mmPCIE_AUX_MAX_PAYLOAD_SIZE 0xC07214
+
+#define mmPCIE_AUX_EXT_TAG_EN 0xC07218
+
+#define mmPCIE_AUX_RCB 0xC0721C
+
+#define mmPCIE_AUX_PM_NO_SOFT_RST 0xC07220
+
+#define mmPCIE_AUX_PBUS_NUM 0xC07224
+
+#define mmPCIE_AUX_PBUS_DEV_NUM 0xC07228
+
+#define mmPCIE_AUX_NO_SNOOP_EN 0xC0722C
+
+#define mmPCIE_AUX_RELAX_ORDER_EN 0xC07230
+
+#define mmPCIE_AUX_HP_SLOT_CTRL_ACCESS 0xC07234
+
+#define mmPCIE_AUX_DLL_STATE_CHGED_EN 0xC07238
+
+#define mmPCIE_AUX_CMP_CPLED_INT_EN 0xC0723C
+
+#define mmPCIE_AUX_HP_INT_EN 0xC07340
+
+#define mmPCIE_AUX_PRE_DET_CHGEN_EN 0xC07344
+
+#define mmPCIE_AUX_MRL_SENSOR_CHGED_EN 0xC07348
+
+#define mmPCIE_AUX_PWR_FAULT_DET_EN 0xC0734C
+
+#define mmPCIE_AUX_ATTEN_BUTTON_PRESSED_EN 0xC07350
+
+#define mmPCIE_AUX_PF_FLR_ACTIVE 0xC07360
+
+#define mmPCIE_AUX_PF_FLR_DONE 0xC07364
+
+#define mmPCIE_AUX_FLR_INT 0xC07390
+
+#define mmPCIE_AUX_LTR_M_EN 0xC073B0
+
+#define mmPCIE_AUX_LTSSM_EN 0xC07428
+
+#define mmPCIE_AUX_SYS_INTR 0xC07440
+
+#define mmPCIE_AUX_INT_DISABLE 0xC07444
+
+#define mmPCIE_AUX_SMLH_LINK_UP 0xC07448
+
+#define mmPCIE_AUX_PM_CURR_STATE 0xC07450
+
+#define mmPCIE_AUX_RDLH_LINK_UP 0xC07458
+
+#define mmPCIE_AUX_BRDG_SLV_XFER_PENDING 0xC0745C
+
+#define mmPCIE_AUX_BRDG_DBI_XFER_PENDING 0xC07460
+
+#define mmPCIE_AUX_AUTO_SP_DIS 0xC07478
+
+#define mmPCIE_AUX_DBI 0xC07490
+
+#define mmPCIE_AUX_DBI_32 0xC07494
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_0 0xC074A4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_1 0xC074A8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_2 0xC074AC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_3 0xC074B0
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_4 0xC074B4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_5 0xC074B8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_6 0xC074BC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_7 0xC074C0
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_8 0xC074C4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_9 0xC074C8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_10 0xC074CC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_11 0xC074D0
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_12 0xC074D4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_13 0xC074D8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_14 0xC074DC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_15 0xC074E0
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_16 0xC074E4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_17 0xC074E8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_18 0xC074EC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_19 0xC074F0
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_20 0xC074F4
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_21 0xC074F8
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_22 0xC074FC
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_23 0xC07500
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_24 0xC07504
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_25 0xC07508
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_26 0xC0750C
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_27 0xC07510
+
+#define mmPCIE_AUX_DIAG_STATUS_BUS_28 0xC07514
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_0 0xC07640
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_1 0xC07644
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_2 0xC07648
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_3 0xC0764C
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_4 0xC07650
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_5 0xC07654
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_6 0xC07658
+
+#define mmPCIE_AUX_CDM_RAS_DES_EC_INFO_7 0xC0765C
+
+#define mmPCIE_AUX_CDM_RAS_DES_SD_COMMON_0 0xC07744
+
+#define mmPCIE_AUX_CDM_RAS_DES_SD_COMMON_1 0xC07748
+
+#define mmPCIE_AUX_CDM_RAS_DES_SD_COMMON_2 0xC0774C
+
+#define mmPCIE_AUX_APP_RAS_DES_TBA_CTRL 0xC07774
+
+#define mmPCIE_AUX_PM_DSTATE 0xC07840
+
+#define mmPCIE_AUX_PM_PME_EN 0xC07844
+
+#define mmPCIE_AUX_PM_LINKST_IN_L0S 0xC07848
+
+#define mmPCIE_AUX_PM_LINKST_IN_L1 0xC0784C
+
+#define mmPCIE_AUX_PM_LINKST_IN_L2 0xC07850
+
+#define mmPCIE_AUX_PM_LINKST_L2_EXIT 0xC07854
+
+#define mmPCIE_AUX_PM_STATUS 0xC07858
+
+#define mmPCIE_AUX_APP_READY_ENTER_L23 0xC0785C
+
+#define mmPCIE_AUX_APP_XFER_PENDING 0xC07860
+
+#define mmPCIE_AUX_APP_REQ_L1 0xC07930
+
+#define mmPCIE_AUX_AUX_PM_EN 0xC07934
+
+#define mmPCIE_AUX_APPS_PM_XMT_PME 0xC07938
+
+#define mmPCIE_AUX_OUTBAND_PWRUP_CMD 0xC07940
+
+#define mmPCIE_AUX_PERST 0xC079B8
+
+#endif /* ASIC_REG_PCIE_AUX_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h
new file mode 100644
index 000000000000..8eda4de58788
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_emmc_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_EMMC_PLL_REGS_H_
+#define ASIC_REG_PSOC_EMMC_PLL_REGS_H_
+
+/*
+ *****************************************
+ * PSOC_EMMC_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmPSOC_EMMC_PLL_NR 0xC70100
+
+#define mmPSOC_EMMC_PLL_NF 0xC70104
+
+#define mmPSOC_EMMC_PLL_OD 0xC70108
+
+#define mmPSOC_EMMC_PLL_NB 0xC7010C
+
+#define mmPSOC_EMMC_PLL_CFG 0xC70110
+
+#define mmPSOC_EMMC_PLL_LOSE_MASK 0xC70120
+
+#define mmPSOC_EMMC_PLL_LOCK_INTR 0xC70128
+
+#define mmPSOC_EMMC_PLL_LOCK_BYPASS 0xC7012C
+
+#define mmPSOC_EMMC_PLL_DATA_CHNG 0xC70130
+
+#define mmPSOC_EMMC_PLL_RST 0xC70134
+
+#define mmPSOC_EMMC_PLL_SLIP_WD_CNTR 0xC70150
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_0 0xC70200
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_1 0xC70204
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_2 0xC70208
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_3 0xC7020C
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_CMD_0 0xC70220
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_CMD_1 0xC70224
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_CMD_2 0xC70228
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_CMD_3 0xC7022C
+
+#define mmPSOC_EMMC_PLL_DIV_SEL_0 0xC70280
+
+#define mmPSOC_EMMC_PLL_DIV_SEL_1 0xC70284
+
+#define mmPSOC_EMMC_PLL_DIV_SEL_2 0xC70288
+
+#define mmPSOC_EMMC_PLL_DIV_SEL_3 0xC7028C
+
+#define mmPSOC_EMMC_PLL_DIV_EN_0 0xC702A0
+
+#define mmPSOC_EMMC_PLL_DIV_EN_1 0xC702A4
+
+#define mmPSOC_EMMC_PLL_DIV_EN_2 0xC702A8
+
+#define mmPSOC_EMMC_PLL_DIV_EN_3 0xC702AC
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_BUSY_0 0xC702C0
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_BUSY_1 0xC702C4
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_BUSY_2 0xC702C8
+
+#define mmPSOC_EMMC_PLL_DIV_FACTOR_BUSY_3 0xC702CC
+
+#define mmPSOC_EMMC_PLL_CLK_GATER 0xC70300
+
+#define mmPSOC_EMMC_PLL_CLK_RLX_0 0xC70310
+
+#define mmPSOC_EMMC_PLL_CLK_RLX_1 0xC70314
+
+#define mmPSOC_EMMC_PLL_CLK_RLX_2 0xC70318
+
+#define mmPSOC_EMMC_PLL_CLK_RLX_3 0xC7031C
+
+#define mmPSOC_EMMC_PLL_REF_CNTR_PERIOD 0xC70400
+
+#define mmPSOC_EMMC_PLL_REF_LOW_THRESHOLD 0xC70410
+
+#define mmPSOC_EMMC_PLL_REF_HIGH_THRESHOLD 0xC70420
+
+#define mmPSOC_EMMC_PLL_PLL_NOT_STABLE 0xC70430
+
+#define mmPSOC_EMMC_PLL_FREQ_CALC_EN 0xC70440
+
+#endif /* ASIC_REG_PSOC_EMMC_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h
new file mode 100644
index 000000000000..d4bf0e1db4df
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_masks.h
@@ -0,0 +1,447 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_GLOBAL_CONF_MASKS_H_
+#define ASIC_REG_PSOC_GLOBAL_CONF_MASKS_H_
+
+/*
+ *****************************************
+ * PSOC_GLOBAL_CONF (Prototype: GLOBAL_CONF)
+ *****************************************
+ */
+
+/* PSOC_GLOBAL_CONF_NON_RST_FLOPS */
+#define PSOC_GLOBAL_CONF_NON_RST_FLOPS_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_NON_RST_FLOPS_VAL_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_PCI_FW_FSM */
+#define PSOC_GLOBAL_CONF_PCI_FW_FSM_EN_SHIFT 0
+#define PSOC_GLOBAL_CONF_PCI_FW_FSM_EN_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_BOOT_SEQ_RE_START */
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_RE_START_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_RE_START_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_BTM_FSM */
+#define PSOC_GLOBAL_CONF_BTM_FSM_STATE_SHIFT 0
+#define PSOC_GLOBAL_CONF_BTM_FSM_STATE_MASK 0xF
+
+/* PSOC_GLOBAL_CONF_SW_BTM_FSM */
+#define PSOC_GLOBAL_CONF_SW_BTM_FSM_CTRL_SHIFT 0
+#define PSOC_GLOBAL_CONF_SW_BTM_FSM_CTRL_MASK 0xF
+
+/* PSOC_GLOBAL_CONF_SW_BOOT_SEQ_FSM */
+#define PSOC_GLOBAL_CONF_SW_BOOT_SEQ_FSM_CTRL_SHIFT 0
+#define PSOC_GLOBAL_CONF_SW_BOOT_SEQ_FSM_CTRL_MASK 0xF
+
+/* PSOC_GLOBAL_CONF_BOOT_SEQ_TIMEOUT */
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_TIMEOUT_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_SPI_MEM_EN */
+#define PSOC_GLOBAL_CONF_SPI_MEM_EN_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_SPI_MEM_EN_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_PRSTN */
+#define PSOC_GLOBAL_CONF_PRSTN_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_PRSTN_VAL_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_PCIE_EN */
+#define PSOC_GLOBAL_CONF_PCIE_EN_MASK_SHIFT 0
+#define PSOC_GLOBAL_CONF_PCIE_EN_MASK_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_SPI_IMG_STS */
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PRI_SHIFT 0
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PRI_MASK 0x1
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_SEC_SHIFT 1
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_SEC_MASK 0x2
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PRSTN_SHIFT 2
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PRSTN_MASK 0x4
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PCI_SHIFT 3
+#define PSOC_GLOBAL_CONF_SPI_IMG_STS_PCI_MASK 0x8
+
+/* PSOC_GLOBAL_CONF_BOOT_SEQ_FSM */
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_IDLE_SHIFT 0
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_IDLE_MASK 0x1
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_BOOT_INIT_SHIFT 1
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_BOOT_INIT_MASK 0x2
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PRI_SHIFT 2
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PRI_MASK 0x4
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_SEC_SHIFT 3
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_SEC_MASK 0x8
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PRSTN_SHIFT 4
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PRSTN_MASK 0x10
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PCIE_SHIFT 5
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_SPI_PCIE_MASK 0x20
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_ROM_SHIFT 6
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_ROM_MASK 0x40
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_PCLK_READY_SHIFT 7
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_PCLK_READY_MASK 0x80
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_LTSSM_EN_SHIFT 8
+#define PSOC_GLOBAL_CONF_BOOT_SEQ_FSM_LTSSM_EN_MASK 0x100
+
+/* PSOC_GLOBAL_CONF_SCRATCHPAD */
+#define PSOC_GLOBAL_CONF_SCRATCHPAD_REG_SHIFT 0
+#define PSOC_GLOBAL_CONF_SCRATCHPAD_REG_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_SEMAPHORE */
+#define PSOC_GLOBAL_CONF_SEMAPHORE_REG_SHIFT 0
+#define PSOC_GLOBAL_CONF_SEMAPHORE_REG_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_WARM_REBOOT */
+#define PSOC_GLOBAL_CONF_WARM_REBOOT_CNTR_SHIFT 0
+#define PSOC_GLOBAL_CONF_WARM_REBOOT_CNTR_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_UBOOT_MAGIC */
+#define PSOC_GLOBAL_CONF_UBOOT_MAGIC_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_UBOOT_MAGIC_VAL_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_SPL_SOURCE */
+#define PSOC_GLOBAL_CONF_SPL_SOURCE_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_SPL_SOURCE_VAL_MASK 0x7
+
+/* PSOC_GLOBAL_CONF_I2C_MSTR1_DBG */
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_S_GEN_SHIFT 0
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_S_GEN_MASK 0x1
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_P_GEN_SHIFT 1
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_P_GEN_MASK 0x2
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_DATA_SHIFT 2
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_DATA_MASK 0x4
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_ADDR_SHIFT 3
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_ADDR_MASK 0x8
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_RD_SHIFT 4
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_RD_MASK 0x10
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_WR_SHIFT 5
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_WR_MASK 0x20
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_HS_SHIFT 6
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_HS_MASK 0x40
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_MASTER_ACT_SHIFT 7
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_MASTER_ACT_MASK 0x80
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_SLAVE_ACT_SHIFT 8
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_SLAVE_ACT_MASK 0x100
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_ADDR_10BIT_SHIFT 9
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_ADDR_10BIT_MASK 0x200
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_MST_CSTATE_SHIFT 10
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_MST_CSTATE_MASK 0x7C00
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_SLV_CSTATE_SHIFT 15
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_SLV_CSTATE_MASK 0x78000
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_IC_EN_SHIFT 19
+#define PSOC_GLOBAL_CONF_I2C_MSTR1_DBG_IC_EN_MASK 0x80000
+
+/* PSOC_GLOBAL_CONF_I2C_SLV */
+#define PSOC_GLOBAL_CONF_I2C_SLV_CPU_CTRL_SHIFT 0
+#define PSOC_GLOBAL_CONF_I2C_SLV_CPU_CTRL_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_I2C_SLV_INTR_MASK */
+#define PSOC_GLOBAL_CONF_I2C_SLV_INTR_MASK_FLD_INT_SHIFT 0
+#define PSOC_GLOBAL_CONF_I2C_SLV_INTR_MASK_FLD_INT_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_APP_STATUS */
+#define PSOC_GLOBAL_CONF_APP_STATUS_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_APP_STATUS_IND_MASK 0xFFFFFFFF
+
+/* PSOC_GLOBAL_CONF_BTL_STS */
+#define PSOC_GLOBAL_CONF_BTL_STS_DONE_SHIFT 0
+#define PSOC_GLOBAL_CONF_BTL_STS_DONE_MASK 0x1
+#define PSOC_GLOBAL_CONF_BTL_STS_FAIL_SHIFT 4
+#define PSOC_GLOBAL_CONF_BTL_STS_FAIL_MASK 0x10
+#define PSOC_GLOBAL_CONF_BTL_STS_FAIL_CODE_SHIFT 8
+#define PSOC_GLOBAL_CONF_BTL_STS_FAIL_CODE_MASK 0xF00
+
+/* PSOC_GLOBAL_CONF_TIMEOUT_INTR */
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_0_SHIFT 0
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_0_MASK 0x1
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_1_SHIFT 1
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_1_MASK 0x2
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_2_SHIFT 2
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_2_MASK 0x4
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_3_SHIFT 3
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_3_MASK 0x8
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_4_SHIFT 4
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_GPIO_4_MASK 0x10
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_TIMER_SHIFT 5
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_TIMER_MASK 0x20
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_UART_0_SHIFT 6
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_UART_0_MASK 0x40
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_UART_1_SHIFT 7
+#define PSOC_GLOBAL_CONF_TIMEOUT_INTR_UART_1_MASK 0x80
+
+/* PSOC_GLOBAL_CONF_COMB_TIMEOUT_INTR */
+#define PSOC_GLOBAL_CONF_COMB_TIMEOUT_INTR_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_COMB_TIMEOUT_INTR_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_PERIPH_INTR */
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_TX_SHIFT 0
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_TX_MASK 0x1
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_RX_SHIFT 1
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_RX_MASK 0x2
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_TXOVR_SHIFT 2
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_TXOVR_MASK 0x4
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_RXOVR_SHIFT 3
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_0_RXOVR_MASK 0x8
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_TX_SHIFT 4
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_TX_MASK 0x10
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_RX_SHIFT 5
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_RX_MASK 0x20
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_TXOVR_SHIFT 6
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_TXOVR_MASK 0x40
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_RXOVR_SHIFT 7
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_UART_1_RXOVR_MASK 0x80
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_EMMC_SHIFT 12
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_EMMC_MASK 0x1000
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_EMMC_WAKEUP_SHIFT 13
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_EMMC_WAKEUP_MASK 0x2000
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_MII_SHIFT 16
+#define PSOC_GLOBAL_CONF_PERIPH_INTR_MII_MASK 0x10000
+
+/* PSOC_GLOBAL_CONF_COMB_PERIPH_INTR */
+#define PSOC_GLOBAL_CONF_COMB_PERIPH_INTR_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_COMB_PERIPH_INTR_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_AXI_ERR_INTR */
+#define PSOC_GLOBAL_CONF_AXI_ERR_INTR_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_AXI_ERR_INTR_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_TARGETID */
+#define PSOC_GLOBAL_CONF_TARGETID_TDESIGNER_SHIFT 1
+#define PSOC_GLOBAL_CONF_TARGETID_TDESIGNER_MASK 0xFFE
+#define PSOC_GLOBAL_CONF_TARGETID_TPARTNO_SHIFT 12
+#define PSOC_GLOBAL_CONF_TARGETID_TPARTNO_MASK 0xFFFF000
+#define PSOC_GLOBAL_CONF_TARGETID_TREVISION_SHIFT 28
+#define PSOC_GLOBAL_CONF_TARGETID_TREVISION_MASK 0xF0000000
+
+/* PSOC_GLOBAL_CONF_EMMC_INT_VOL_STABLE */
+#define PSOC_GLOBAL_CONF_EMMC_INT_VOL_STABLE_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_EMMC_INT_VOL_STABLE_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_MII_ADDR */
+#define PSOC_GLOBAL_CONF_MII_ADDR_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_MII_ADDR_VAL_MASK 0xFF
+
+/* PSOC_GLOBAL_CONF_MII_SPEED */
+#define PSOC_GLOBAL_CONF_MII_SPEED_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_MII_SPEED_VAL_MASK 0x3
+
+/* PSOC_GLOBAL_CONF_BOOT_STRAP_PINS */
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_CPOL_SHIFT 0
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_CPOL_MASK 0x1
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_CPHA_SHIFT 1
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_CPHA_MASK 0x2
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BTL_EN_SHIFT 2
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BTL_EN_MASK 0x4
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BTL_ROM_EN_SHIFT 3
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BTL_ROM_EN_MASK 0x8
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PCIE_EN_SHIFT 4
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PCIE_EN_MASK 0x10
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_I2C_SLV_ADDR_SHIFT 5
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_I2C_SLV_ADDR_MASK 0xFE0
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BOOT_STG2_SRC_SHIFT 12
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_BOOT_STG2_SRC_MASK 0x3000
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PLL_BPS_SHIFT 14
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PLL_BPS_MASK 0x1FC000
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_SRIOV_EN_SHIFT 21
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_SRIOV_EN_MASK 0x200000
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PLL_CFG_SHIFT 22
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_PLL_CFG_MASK 0x1C00000
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_MEM_REPAIR_BPS_SHIFT 25
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_MEM_REPAIR_BPS_MASK 0x2000000
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_SPARE_SHIFT 26
+#define PSOC_GLOBAL_CONF_BOOT_STRAP_PINS_SPARE_MASK 0x1C000000
+
+/* PSOC_GLOBAL_CONF_MEM_REPAIR_CTRL */
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_CTRL_SET_SHIFT 0
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_CTRL_SET_MASK 0x1
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_CTRL_CLR_SHIFT 1
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_CTRL_CLR_MASK 0x2
+
+/* PSOC_GLOBAL_CONF_MEM_REPAIR_STS */
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_STS_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_MEM_REPAIR_STS_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_OUTSTANT_TRANS */
+#define PSOC_GLOBAL_CONF_OUTSTANT_TRANS_RD_SHIFT 0
+#define PSOC_GLOBAL_CONF_OUTSTANT_TRANS_RD_MASK 0x1
+#define PSOC_GLOBAL_CONF_OUTSTANT_TRANS_WR_SHIFT 1
+#define PSOC_GLOBAL_CONF_OUTSTANT_TRANS_WR_MASK 0x2
+
+/* PSOC_GLOBAL_CONF_MASK_REQ */
+#define PSOC_GLOBAL_CONF_MASK_REQ_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_MASK_REQ_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_PRSTN_RST_CFG */
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PCI_SHIFT 0
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PCI_MASK 0x1
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PCI_IF_SHIFT 1
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PCI_IF_MASK 0x2
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PLL_SHIFT 2
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PLL_MASK 0x1FC
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_TPC_SHIFT 9
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_TPC_MASK 0x200
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_MME_SHIFT 10
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_MME_MASK 0x400
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_MC_SHIFT 11
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_MC_MASK 0x800
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_CPU_SHIFT 12
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_CPU_MASK 0x1000
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_IC_IF_SHIFT 13
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_IC_IF_MASK 0x2000
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PSOC_SHIFT 14
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_PSOC_MASK 0x4000
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_SRAM_SHIFT 15
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_SRAM_MASK 0x1F8000
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_DMA_SHIFT 21
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_DMA_MASK 0x200000
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_DMA_IF_SHIFT 22
+#define PSOC_GLOBAL_CONF_PRSTN_RST_CFG_DMA_IF_MASK 0x400000
+
+/* PSOC_GLOBAL_CONF_SW_ALL_RST_CFG */
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PCI_SHIFT 0
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PCI_MASK 0x1
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PCI_IF_SHIFT 1
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PCI_IF_MASK 0x2
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PLL_SHIFT 2
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PLL_MASK 0x1FC
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_TPC_SHIFT 9
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_TPC_MASK 0x200
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MME_SHIFT 10
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MME_MASK 0x400
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MC_SHIFT 11
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_MC_MASK 0x800
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_CPU_SHIFT 12
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_CPU_MASK 0x1000
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_IC_IF_SHIFT 13
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_IC_IF_MASK 0x2000
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PSOC_SHIFT 14
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_PSOC_MASK 0x4000
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_SRAM_SHIFT 15
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_SRAM_MASK 0x1F8000
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_SHIFT 21
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_MASK 0x200000
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_IF_SHIFT 22
+#define PSOC_GLOBAL_CONF_SW_ALL_RST_CFG_DMA_IF_MASK 0x400000
+
+/* PSOC_GLOBAL_CONF_WD_RST_CFG */
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PCI_SHIFT 0
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PCI_MASK 0x1
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PCI_IF_SHIFT 1
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PCI_IF_MASK 0x2
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PLL_SHIFT 2
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PLL_MASK 0x1FC
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_TPC_SHIFT 9
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_TPC_MASK 0x200
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_MME_SHIFT 10
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_MME_MASK 0x400
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_MC_SHIFT 11
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_MC_MASK 0x800
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_CPU_SHIFT 12
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_CPU_MASK 0x1000
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_IC_IF_SHIFT 13
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_IC_IF_MASK 0x2000
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PSOC_SHIFT 14
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_PSOC_MASK 0x4000
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_SRAM_SHIFT 15
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_SRAM_MASK 0x1F8000
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_DMA_SHIFT 21
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_DMA_MASK 0x200000
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_DMA_IF_SHIFT 22
+#define PSOC_GLOBAL_CONF_WD_RST_CFG_DMA_IF_MASK 0x400000
+
+/* PSOC_GLOBAL_CONF_MNL_RST_CFG */
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PCI_SHIFT 0
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PCI_MASK 0x1
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PCI_IF_SHIFT 1
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PCI_IF_MASK 0x2
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PLL_SHIFT 2
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PLL_MASK 0x1FC
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_TPC_SHIFT 9
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_TPC_MASK 0x200
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_MME_SHIFT 10
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_MME_MASK 0x400
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_MC_SHIFT 11
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_MC_MASK 0x800
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_CPU_SHIFT 12
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_CPU_MASK 0x1000
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_IC_IF_SHIFT 13
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_IC_IF_MASK 0x2000
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PSOC_SHIFT 14
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_PSOC_MASK 0x4000
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_SRAM_SHIFT 15
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_SRAM_MASK 0x1F8000
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_DMA_SHIFT 21
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_DMA_MASK 0x200000
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_DMA_IF_SHIFT 22
+#define PSOC_GLOBAL_CONF_MNL_RST_CFG_DMA_IF_MASK 0x400000
+
+/* PSOC_GLOBAL_CONF_UNIT_RST_N */
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PCI_SHIFT 0
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PCI_MASK 0x1
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PCI_IF_SHIFT 1
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PCI_IF_MASK 0x2
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PLL_SHIFT 2
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PLL_MASK 0x1FC
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_TPC_SHIFT 9
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_TPC_MASK 0x200
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_MME_SHIFT 10
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_MME_MASK 0x400
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_MC_SHIFT 11
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_MC_MASK 0x800
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_CPU_SHIFT 12
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_CPU_MASK 0x1000
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_IC_IF_SHIFT 13
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_IC_IF_MASK 0x2000
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PSOC_SHIFT 14
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_PSOC_MASK 0x4000
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_SRAM_SHIFT 15
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_SRAM_MASK 0x1F8000
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_DMA_SHIFT 21
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_DMA_MASK 0x200000
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_DMA_IF_SHIFT 22
+#define PSOC_GLOBAL_CONF_UNIT_RST_N_DMA_IF_MASK 0x400000
+
+/* PSOC_GLOBAL_CONF_PRSTN_MASK */
+#define PSOC_GLOBAL_CONF_PRSTN_MASK_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_PRSTN_MASK_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_WD_MASK */
+#define PSOC_GLOBAL_CONF_WD_MASK_IND_SHIFT 0
+#define PSOC_GLOBAL_CONF_WD_MASK_IND_MASK 0x1
+
+/* PSOC_GLOBAL_CONF_RST_SRC */
+#define PSOC_GLOBAL_CONF_RST_SRC_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_RST_SRC_VAL_MASK 0xF
+
+/* PSOC_GLOBAL_CONF_PAD_1V8_CFG */
+#define PSOC_GLOBAL_CONF_PAD_1V8_CFG_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_PAD_1V8_CFG_VAL_MASK 0x7F
+
+/* PSOC_GLOBAL_CONF_PAD_3V3_CFG */
+#define PSOC_GLOBAL_CONF_PAD_3V3_CFG_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_PAD_3V3_CFG_VAL_MASK 0x7F
+
+/* PSOC_GLOBAL_CONF_PAD_1V8_INPUT */
+#define PSOC_GLOBAL_CONF_PAD_1V8_INPUT_CFG_SHIFT 0
+#define PSOC_GLOBAL_CONF_PAD_1V8_INPUT_CFG_MASK 0x7
+
+/* PSOC_GLOBAL_CONF_BNK3V3_MS */
+#define PSOC_GLOBAL_CONF_BNK3V3_MS_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_BNK3V3_MS_VAL_MASK 0x3
+
+/* PSOC_GLOBAL_CONF_PAD_DEFAULT */
+#define PSOC_GLOBAL_CONF_PAD_DEFAULT_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_PAD_DEFAULT_VAL_MASK 0xF
+
+/* PSOC_GLOBAL_CONF_PAD_SEL */
+#define PSOC_GLOBAL_CONF_PAD_SEL_VAL_SHIFT 0
+#define PSOC_GLOBAL_CONF_PAD_SEL_VAL_MASK 0x3
+
+#endif /* ASIC_REG_PSOC_GLOBAL_CONF_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h
new file mode 100644
index 000000000000..cfbdd2c9c5c7
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_global_conf_regs.h
@@ -0,0 +1,745 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_GLOBAL_CONF_REGS_H_
+#define ASIC_REG_PSOC_GLOBAL_CONF_REGS_H_
+
+/*
+ *****************************************
+ * PSOC_GLOBAL_CONF (Prototype: GLOBAL_CONF)
+ *****************************************
+ */
+
+#define mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_0 0xC4B000
+
+#define mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_1 0xC4B004
+
+#define mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_2 0xC4B008
+
+#define mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_3 0xC4B00C
+
+#define mmPSOC_GLOBAL_CONF_PCI_FW_FSM 0xC4B020
+
+#define mmPSOC_GLOBAL_CONF_BOOT_SEQ_RE_START 0xC4B024
+
+#define mmPSOC_GLOBAL_CONF_BTM_FSM 0xC4B028
+
+#define mmPSOC_GLOBAL_CONF_SW_BTM_FSM 0xC4B030
+
+#define mmPSOC_GLOBAL_CONF_SW_BOOT_SEQ_FSM 0xC4B034
+
+#define mmPSOC_GLOBAL_CONF_BOOT_SEQ_TIMEOUT 0xC4B038
+
+#define mmPSOC_GLOBAL_CONF_SPI_MEM_EN 0xC4B040
+
+#define mmPSOC_GLOBAL_CONF_PRSTN 0xC4B044
+
+#define mmPSOC_GLOBAL_CONF_PCIE_EN 0xC4B048
+
+#define mmPSOC_GLOBAL_CONF_SPI_IMG_STS 0xC4B050
+
+#define mmPSOC_GLOBAL_CONF_BOOT_SEQ_FSM 0xC4B054
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_0 0xC4B100
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_1 0xC4B104
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_2 0xC4B108
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_3 0xC4B10C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_4 0xC4B110
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_5 0xC4B114
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_6 0xC4B118
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_7 0xC4B11C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_8 0xC4B120
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_9 0xC4B124
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_10 0xC4B128
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_11 0xC4B12C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_12 0xC4B130
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_13 0xC4B134
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_14 0xC4B138
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_15 0xC4B13C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_16 0xC4B140
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_17 0xC4B144
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_18 0xC4B148
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_19 0xC4B14C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_20 0xC4B150
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_21 0xC4B154
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_22 0xC4B158
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_23 0xC4B15C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_24 0xC4B160
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_25 0xC4B164
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_26 0xC4B168
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_27 0xC4B16C
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_28 0xC4B170
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_29 0xC4B174
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_30 0xC4B178
+
+#define mmPSOC_GLOBAL_CONF_SCRATCHPAD_31 0xC4B17C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_0 0xC4B200
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_1 0xC4B204
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_2 0xC4B208
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_3 0xC4B20C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_4 0xC4B210
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_5 0xC4B214
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_6 0xC4B218
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_7 0xC4B21C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_8 0xC4B220
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_9 0xC4B224
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_10 0xC4B228
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_11 0xC4B22C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_12 0xC4B230
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_13 0xC4B234
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_14 0xC4B238
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_15 0xC4B23C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_16 0xC4B240
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_17 0xC4B244
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_18 0xC4B248
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_19 0xC4B24C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_20 0xC4B250
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_21 0xC4B254
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_22 0xC4B258
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_23 0xC4B25C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_24 0xC4B260
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_25 0xC4B264
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_26 0xC4B268
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_27 0xC4B26C
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_28 0xC4B270
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_29 0xC4B274
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_30 0xC4B278
+
+#define mmPSOC_GLOBAL_CONF_SEMAPHORE_31 0xC4B27C
+
+#define mmPSOC_GLOBAL_CONF_WARM_REBOOT 0xC4B300
+
+#define mmPSOC_GLOBAL_CONF_UBOOT_MAGIC 0xC4B304
+
+#define mmPSOC_GLOBAL_CONF_SPL_SOURCE 0xC4B308
+
+#define mmPSOC_GLOBAL_CONF_I2C_MSTR1_DBG 0xC4B30C
+
+#define mmPSOC_GLOBAL_CONF_I2C_SLV 0xC4B310
+
+#define mmPSOC_GLOBAL_CONF_I2C_SLV_INTR_MASK 0xC4B314
+
+#define mmPSOC_GLOBAL_CONF_APP_STATUS 0xC4B320
+
+#define mmPSOC_GLOBAL_CONF_BTL_STS 0xC4B340
+
+#define mmPSOC_GLOBAL_CONF_TIMEOUT_INTR 0xC4B350
+
+#define mmPSOC_GLOBAL_CONF_COMB_TIMEOUT_INTR 0xC4B354
+
+#define mmPSOC_GLOBAL_CONF_PERIPH_INTR 0xC4B358
+
+#define mmPSOC_GLOBAL_CONF_COMB_PERIPH_INTR 0xC4B35C
+
+#define mmPSOC_GLOBAL_CONF_AXI_ERR_INTR 0xC4B360
+
+#define mmPSOC_GLOBAL_CONF_TARGETID 0xC4B400
+
+#define mmPSOC_GLOBAL_CONF_EMMC_INT_VOL_STABLE 0xC4B420
+
+#define mmPSOC_GLOBAL_CONF_MII_ADDR 0xC4B424
+
+#define mmPSOC_GLOBAL_CONF_MII_SPEED 0xC4B428
+
+#define mmPSOC_GLOBAL_CONF_BOOT_STRAP_PINS 0xC4B430
+
+#define mmPSOC_GLOBAL_CONF_MEM_REPAIR_CTRL 0xC4B450
+
+#define mmPSOC_GLOBAL_CONF_MEM_REPAIR_STS 0xC4B454
+
+#define mmPSOC_GLOBAL_CONF_OUTSTANT_TRANS 0xC4B458
+
+#define mmPSOC_GLOBAL_CONF_MASK_REQ 0xC4B45C
+
+#define mmPSOC_GLOBAL_CONF_PRSTN_RST_CFG 0xC4B470
+
+#define mmPSOC_GLOBAL_CONF_SW_ALL_RST_CFG 0xC4B474
+
+#define mmPSOC_GLOBAL_CONF_WD_RST_CFG 0xC4B478
+
+#define mmPSOC_GLOBAL_CONF_MNL_RST_CFG 0xC4B47C
+
+#define mmPSOC_GLOBAL_CONF_UNIT_RST_N 0xC4B480
+
+#define mmPSOC_GLOBAL_CONF_PRSTN_MASK 0xC4B484
+
+#define mmPSOC_GLOBAL_CONF_WD_MASK 0xC4B488
+
+#define mmPSOC_GLOBAL_CONF_RST_SRC 0xC4B490
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_0 0xC4B500
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_1 0xC4B504
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_2 0xC4B508
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_3 0xC4B50C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_4 0xC4B510
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_5 0xC4B514
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_6 0xC4B518
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_7 0xC4B51C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_8 0xC4B520
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_9 0xC4B524
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_10 0xC4B528
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_11 0xC4B52C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_12 0xC4B530
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_13 0xC4B534
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_14 0xC4B538
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_15 0xC4B53C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_16 0xC4B540
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_17 0xC4B544
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_18 0xC4B548
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_19 0xC4B54C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_20 0xC4B550
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_21 0xC4B554
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_22 0xC4B558
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_23 0xC4B55C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_24 0xC4B560
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_25 0xC4B564
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_26 0xC4B568
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_27 0xC4B56C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_28 0xC4B570
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_29 0xC4B574
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_30 0xC4B578
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_31 0xC4B57C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_32 0xC4B580
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_33 0xC4B584
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_34 0xC4B588
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_35 0xC4B58C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_36 0xC4B590
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_37 0xC4B594
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_38 0xC4B598
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_39 0xC4B59C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_40 0xC4B5A0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_41 0xC4B5A4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_42 0xC4B5A8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_43 0xC4B5AC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_44 0xC4B5B0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_45 0xC4B5B4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_46 0xC4B5B8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_47 0xC4B5BC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_48 0xC4B5C0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_49 0xC4B5C4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_50 0xC4B5C8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_51 0xC4B5CC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_52 0xC4B5D0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_53 0xC4B5D4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_54 0xC4B5D8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_55 0xC4B5DC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_56 0xC4B5E0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_57 0xC4B5E4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_58 0xC4B5E8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_59 0xC4B5EC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_60 0xC4B5F0
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_61 0xC4B5F4
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_62 0xC4B5F8
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_63 0xC4B5FC
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_64 0xC4B600
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_65 0xC4B604
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_66 0xC4B608
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_67 0xC4B60C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_CFG_68 0xC4B610
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_0 0xC4B640
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_1 0xC4B644
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_2 0xC4B648
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_3 0xC4B64C
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_4 0xC4B650
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_5 0xC4B654
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_6 0xC4B658
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_7 0xC4B65C
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_8 0xC4B660
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_9 0xC4B664
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_10 0xC4B668
+
+#define mmPSOC_GLOBAL_CONF_PAD_3V3_CFG_11 0xC4B66C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_0 0xC4B680
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_1 0xC4B684
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_2 0xC4B688
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_3 0xC4B68C
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_4 0xC4B690
+
+#define mmPSOC_GLOBAL_CONF_PAD_1V8_INPUT_5 0xC4B694
+
+#define mmPSOC_GLOBAL_CONF_BNK3V3_MS 0xC4B6E0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_0 0xC4B700
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_1 0xC4B704
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_2 0xC4B708
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_3 0xC4B70C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_4 0xC4B710
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_5 0xC4B714
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_6 0xC4B718
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_7 0xC4B71C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_8 0xC4B720
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_9 0xC4B724
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_10 0xC4B728
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_11 0xC4B72C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_12 0xC4B730
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_13 0xC4B734
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_14 0xC4B738
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_15 0xC4B73C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_16 0xC4B740
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_17 0xC4B744
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_18 0xC4B748
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_19 0xC4B74C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_20 0xC4B750
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_21 0xC4B754
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_22 0xC4B758
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_23 0xC4B75C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_24 0xC4B760
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_25 0xC4B764
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_26 0xC4B768
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_27 0xC4B76C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_28 0xC4B770
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_29 0xC4B774
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_30 0xC4B778
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_31 0xC4B77C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_32 0xC4B780
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_33 0xC4B784
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_34 0xC4B788
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_35 0xC4B78C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_36 0xC4B790
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_37 0xC4B794
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_38 0xC4B798
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_39 0xC4B79C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_40 0xC4B7A0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_41 0xC4B7A4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_42 0xC4B7A8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_43 0xC4B7AC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_44 0xC4B7B0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_45 0xC4B7B4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_46 0xC4B7B8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_47 0xC4B7BC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_48 0xC4B7C0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_49 0xC4B7C4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_50 0xC4B7C8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_51 0xC4B7CC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_52 0xC4B7D0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_53 0xC4B7D4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_54 0xC4B7D8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_55 0xC4B7DC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_56 0xC4B7E0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_57 0xC4B7E4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_58 0xC4B7E8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_59 0xC4B7EC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_60 0xC4B7F0
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_61 0xC4B7F4
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_62 0xC4B7F8
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_63 0xC4B7FC
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_64 0xC4B800
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_65 0xC4B804
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_66 0xC4B808
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_67 0xC4B80C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_68 0xC4B810
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_69 0xC4B814
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_70 0xC4B818
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_71 0xC4B81C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_72 0xC4B820
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_73 0xC4B824
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_74 0xC4B828
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_75 0xC4B82C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_76 0xC4B830
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_77 0xC4B834
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_78 0xC4B838
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_79 0xC4B83C
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_80 0xC4B840
+
+#define mmPSOC_GLOBAL_CONF_PAD_DEFAULT_81 0xC4B844
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_0 0xC4B900
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_1 0xC4B904
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_2 0xC4B908
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_3 0xC4B90C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_4 0xC4B910
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_5 0xC4B914
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_6 0xC4B918
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_7 0xC4B91C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_8 0xC4B920
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_9 0xC4B924
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_10 0xC4B928
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_11 0xC4B92C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_12 0xC4B930
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_13 0xC4B934
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_14 0xC4B938
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_15 0xC4B93C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_16 0xC4B940
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_17 0xC4B944
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_18 0xC4B948
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_19 0xC4B94C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_20 0xC4B950
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_21 0xC4B954
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_22 0xC4B958
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_23 0xC4B95C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_24 0xC4B960
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_25 0xC4B964
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_26 0xC4B968
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_27 0xC4B96C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_28 0xC4B970
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_29 0xC4B974
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_30 0xC4B978
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_31 0xC4B97C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_32 0xC4B980
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_33 0xC4B984
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_34 0xC4B988
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_35 0xC4B98C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_36 0xC4B990
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_37 0xC4B994
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_38 0xC4B998
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_39 0xC4B99C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_40 0xC4B9A0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_41 0xC4B9A4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_42 0xC4B9A8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_43 0xC4B9AC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_44 0xC4B9B0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_45 0xC4B9B4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_46 0xC4B9B8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_47 0xC4B9BC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_48 0xC4B9C0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_49 0xC4B9C4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_50 0xC4B9C8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_51 0xC4B9CC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_52 0xC4B9D0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_53 0xC4B9D4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_54 0xC4B9D8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_55 0xC4B9DC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_56 0xC4B9E0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_57 0xC4B9E4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_58 0xC4B9E8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_59 0xC4B9EC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_60 0xC4B9F0
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_61 0xC4B9F4
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_62 0xC4B9F8
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_63 0xC4B9FC
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_64 0xC4BA00
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_65 0xC4BA04
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_66 0xC4BA08
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_67 0xC4BA0C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_68 0xC4BA10
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_69 0xC4BA14
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_70 0xC4BA18
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_71 0xC4BA1C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_72 0xC4BA20
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_73 0xC4BA24
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_74 0xC4BA28
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_75 0xC4BA2C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_76 0xC4BA30
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_77 0xC4BA34
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_78 0xC4BA38
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_79 0xC4BA3C
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_80 0xC4BA40
+
+#define mmPSOC_GLOBAL_CONF_PAD_SEL_81 0xC4BA44
+
+#endif /* ASIC_REG_PSOC_GLOBAL_CONF_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h
new file mode 100644
index 000000000000..6723d8f76f30
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_mme_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_MME_PLL_REGS_H_
+#define ASIC_REG_PSOC_MME_PLL_REGS_H_
+
+/*
+ *****************************************
+ * PSOC_MME_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmPSOC_MME_PLL_NR 0xC71100
+
+#define mmPSOC_MME_PLL_NF 0xC71104
+
+#define mmPSOC_MME_PLL_OD 0xC71108
+
+#define mmPSOC_MME_PLL_NB 0xC7110C
+
+#define mmPSOC_MME_PLL_CFG 0xC71110
+
+#define mmPSOC_MME_PLL_LOSE_MASK 0xC71120
+
+#define mmPSOC_MME_PLL_LOCK_INTR 0xC71128
+
+#define mmPSOC_MME_PLL_LOCK_BYPASS 0xC7112C
+
+#define mmPSOC_MME_PLL_DATA_CHNG 0xC71130
+
+#define mmPSOC_MME_PLL_RST 0xC71134
+
+#define mmPSOC_MME_PLL_SLIP_WD_CNTR 0xC71150
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_0 0xC71200
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_1 0xC71204
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_2 0xC71208
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_3 0xC7120C
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_CMD_0 0xC71220
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_CMD_1 0xC71224
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_CMD_2 0xC71228
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_CMD_3 0xC7122C
+
+#define mmPSOC_MME_PLL_DIV_SEL_0 0xC71280
+
+#define mmPSOC_MME_PLL_DIV_SEL_1 0xC71284
+
+#define mmPSOC_MME_PLL_DIV_SEL_2 0xC71288
+
+#define mmPSOC_MME_PLL_DIV_SEL_3 0xC7128C
+
+#define mmPSOC_MME_PLL_DIV_EN_0 0xC712A0
+
+#define mmPSOC_MME_PLL_DIV_EN_1 0xC712A4
+
+#define mmPSOC_MME_PLL_DIV_EN_2 0xC712A8
+
+#define mmPSOC_MME_PLL_DIV_EN_3 0xC712AC
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_BUSY_0 0xC712C0
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_BUSY_1 0xC712C4
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_BUSY_2 0xC712C8
+
+#define mmPSOC_MME_PLL_DIV_FACTOR_BUSY_3 0xC712CC
+
+#define mmPSOC_MME_PLL_CLK_GATER 0xC71300
+
+#define mmPSOC_MME_PLL_CLK_RLX_0 0xC71310
+
+#define mmPSOC_MME_PLL_CLK_RLX_1 0xC71314
+
+#define mmPSOC_MME_PLL_CLK_RLX_2 0xC71318
+
+#define mmPSOC_MME_PLL_CLK_RLX_3 0xC7131C
+
+#define mmPSOC_MME_PLL_REF_CNTR_PERIOD 0xC71400
+
+#define mmPSOC_MME_PLL_REF_LOW_THRESHOLD 0xC71410
+
+#define mmPSOC_MME_PLL_REF_HIGH_THRESHOLD 0xC71420
+
+#define mmPSOC_MME_PLL_PLL_NOT_STABLE 0xC71430
+
+#define mmPSOC_MME_PLL_FREQ_CALC_EN 0xC71440
+
+#endif /* ASIC_REG_PSOC_MME_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h
new file mode 100644
index 000000000000..abcded0531c9
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_pci_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_PCI_PLL_REGS_H_
+#define ASIC_REG_PSOC_PCI_PLL_REGS_H_
+
+/*
+ *****************************************
+ * PSOC_PCI_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmPSOC_PCI_PLL_NR 0xC72100
+
+#define mmPSOC_PCI_PLL_NF 0xC72104
+
+#define mmPSOC_PCI_PLL_OD 0xC72108
+
+#define mmPSOC_PCI_PLL_NB 0xC7210C
+
+#define mmPSOC_PCI_PLL_CFG 0xC72110
+
+#define mmPSOC_PCI_PLL_LOSE_MASK 0xC72120
+
+#define mmPSOC_PCI_PLL_LOCK_INTR 0xC72128
+
+#define mmPSOC_PCI_PLL_LOCK_BYPASS 0xC7212C
+
+#define mmPSOC_PCI_PLL_DATA_CHNG 0xC72130
+
+#define mmPSOC_PCI_PLL_RST 0xC72134
+
+#define mmPSOC_PCI_PLL_SLIP_WD_CNTR 0xC72150
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_0 0xC72200
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_1 0xC72204
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_2 0xC72208
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_3 0xC7220C
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_CMD_0 0xC72220
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_CMD_1 0xC72224
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_CMD_2 0xC72228
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_CMD_3 0xC7222C
+
+#define mmPSOC_PCI_PLL_DIV_SEL_0 0xC72280
+
+#define mmPSOC_PCI_PLL_DIV_SEL_1 0xC72284
+
+#define mmPSOC_PCI_PLL_DIV_SEL_2 0xC72288
+
+#define mmPSOC_PCI_PLL_DIV_SEL_3 0xC7228C
+
+#define mmPSOC_PCI_PLL_DIV_EN_0 0xC722A0
+
+#define mmPSOC_PCI_PLL_DIV_EN_1 0xC722A4
+
+#define mmPSOC_PCI_PLL_DIV_EN_2 0xC722A8
+
+#define mmPSOC_PCI_PLL_DIV_EN_3 0xC722AC
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_BUSY_0 0xC722C0
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_BUSY_1 0xC722C4
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_BUSY_2 0xC722C8
+
+#define mmPSOC_PCI_PLL_DIV_FACTOR_BUSY_3 0xC722CC
+
+#define mmPSOC_PCI_PLL_CLK_GATER 0xC72300
+
+#define mmPSOC_PCI_PLL_CLK_RLX_0 0xC72310
+
+#define mmPSOC_PCI_PLL_CLK_RLX_1 0xC72314
+
+#define mmPSOC_PCI_PLL_CLK_RLX_2 0xC72318
+
+#define mmPSOC_PCI_PLL_CLK_RLX_3 0xC7231C
+
+#define mmPSOC_PCI_PLL_REF_CNTR_PERIOD 0xC72400
+
+#define mmPSOC_PCI_PLL_REF_LOW_THRESHOLD 0xC72410
+
+#define mmPSOC_PCI_PLL_REF_HIGH_THRESHOLD 0xC72420
+
+#define mmPSOC_PCI_PLL_PLL_NOT_STABLE 0xC72430
+
+#define mmPSOC_PCI_PLL_FREQ_CALC_EN 0xC72440
+
+#endif /* ASIC_REG_PSOC_PCI_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h
new file mode 100644
index 000000000000..5925c7477c25
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_spi_regs.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_SPI_REGS_H_
+#define ASIC_REG_PSOC_SPI_REGS_H_
+
+/*
+ *****************************************
+ * PSOC_SPI (Prototype: SPI)
+ *****************************************
+ */
+
+#define mmPSOC_SPI_CTRLR0 0xC43000
+
+#define mmPSOC_SPI_CTRLR1 0xC43004
+
+#define mmPSOC_SPI_SSIENR 0xC43008
+
+#define mmPSOC_SPI_MWCR 0xC4300C
+
+#define mmPSOC_SPI_SER 0xC43010
+
+#define mmPSOC_SPI_BAUDR 0xC43014
+
+#define mmPSOC_SPI_TXFTLR 0xC43018
+
+#define mmPSOC_SPI_RXFTLR 0xC4301C
+
+#define mmPSOC_SPI_TXFLR 0xC43020
+
+#define mmPSOC_SPI_RXFLR 0xC43024
+
+#define mmPSOC_SPI_SR 0xC43028
+
+#define mmPSOC_SPI_IMR 0xC4302C
+
+#define mmPSOC_SPI_ISR 0xC43030
+
+#define mmPSOC_SPI_RISR 0xC43034
+
+#define mmPSOC_SPI_TXOICR 0xC43038
+
+#define mmPSOC_SPI_RXOICR 0xC4303C
+
+#define mmPSOC_SPI_RXUICR 0xC43040
+
+#define mmPSOC_SPI_MSTICR 0xC43044
+
+#define mmPSOC_SPI_ICR 0xC43048
+
+#define mmPSOC_SPI_IDR 0xC43058
+
+#define mmPSOC_SPI_SSI_VERSION_ID 0xC4305C
+
+#define mmPSOC_SPI_DR0 0xC43060
+
+#define mmPSOC_SPI_DR1 0xC43064
+
+#define mmPSOC_SPI_DR2 0xC43068
+
+#define mmPSOC_SPI_DR3 0xC4306C
+
+#define mmPSOC_SPI_DR4 0xC43070
+
+#define mmPSOC_SPI_DR5 0xC43074
+
+#define mmPSOC_SPI_DR6 0xC43078
+
+#define mmPSOC_SPI_DR7 0xC4307C
+
+#define mmPSOC_SPI_DR8 0xC43080
+
+#define mmPSOC_SPI_DR9 0xC43084
+
+#define mmPSOC_SPI_DR10 0xC43088
+
+#define mmPSOC_SPI_DR11 0xC4308C
+
+#define mmPSOC_SPI_DR12 0xC43090
+
+#define mmPSOC_SPI_DR13 0xC43094
+
+#define mmPSOC_SPI_DR14 0xC43098
+
+#define mmPSOC_SPI_DR15 0xC4309C
+
+#define mmPSOC_SPI_DR16 0xC430A0
+
+#define mmPSOC_SPI_DR17 0xC430A4
+
+#define mmPSOC_SPI_DR18 0xC430A8
+
+#define mmPSOC_SPI_DR19 0xC430AC
+
+#define mmPSOC_SPI_DR20 0xC430B0
+
+#define mmPSOC_SPI_DR21 0xC430B4
+
+#define mmPSOC_SPI_DR22 0xC430B8
+
+#define mmPSOC_SPI_DR23 0xC430BC
+
+#define mmPSOC_SPI_DR24 0xC430C0
+
+#define mmPSOC_SPI_DR25 0xC430C4
+
+#define mmPSOC_SPI_DR26 0xC430C8
+
+#define mmPSOC_SPI_DR27 0xC430CC
+
+#define mmPSOC_SPI_DR28 0xC430D0
+
+#define mmPSOC_SPI_DR29 0xC430D4
+
+#define mmPSOC_SPI_DR30 0xC430D8
+
+#define mmPSOC_SPI_DR31 0xC430DC
+
+#define mmPSOC_SPI_DR32 0xC430E0
+
+#define mmPSOC_SPI_DR33 0xC430E4
+
+#define mmPSOC_SPI_DR34 0xC430E8
+
+#define mmPSOC_SPI_DR35 0xC430EC
+
+#define mmPSOC_SPI_RX_SAMPLE_DLY 0xC430F0
+
+#define mmPSOC_SPI_RSVD_1 0xC430F8
+
+#define mmPSOC_SPI_RSVD_2 0xC430FC
+
+#endif /* ASIC_REG_PSOC_SPI_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h
new file mode 100644
index 000000000000..d56c9fa0e7ba
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x0_rtr_regs.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_SRAM_Y0_X0_RTR_REGS_H_
+#define ASIC_REG_SRAM_Y0_X0_RTR_REGS_H_
+
+/*
+ *****************************************
+ * SRAM_Y0_X0_RTR (Prototype: IC_RTR)
+ *****************************************
+ */
+
+#define mmSRAM_Y0_X0_RTR_HBW_RD_RQ_E_ARB 0x201100
+
+#define mmSRAM_Y0_X0_RTR_HBW_RD_RQ_W_ARB 0x201104
+
+#define mmSRAM_Y0_X0_RTR_HBW_RD_RQ_L_ARB 0x201110
+
+#define mmSRAM_Y0_X0_RTR_HBW_E_ARB_MAX 0x201120
+
+#define mmSRAM_Y0_X0_RTR_HBW_W_ARB_MAX 0x201124
+
+#define mmSRAM_Y0_X0_RTR_HBW_L_ARB_MAX 0x201130
+
+#define mmSRAM_Y0_X0_RTR_HBW_DATA_E_ARB 0x201140
+
+#define mmSRAM_Y0_X0_RTR_HBW_DATA_W_ARB 0x201144
+
+#define mmSRAM_Y0_X0_RTR_HBW_DATA_L_ARB 0x201148
+
+#define mmSRAM_Y0_X0_RTR_HBW_WR_RS_E_ARB 0x201160
+
+#define mmSRAM_Y0_X0_RTR_HBW_WR_RS_W_ARB 0x201164
+
+#define mmSRAM_Y0_X0_RTR_HBW_WR_RS_L_ARB 0x201168
+
+#define mmSRAM_Y0_X0_RTR_LBW_RD_RQ_E_ARB 0x201200
+
+#define mmSRAM_Y0_X0_RTR_LBW_RD_RQ_W_ARB 0x201204
+
+#define mmSRAM_Y0_X0_RTR_LBW_RD_RQ_L_ARB 0x201210
+
+#define mmSRAM_Y0_X0_RTR_LBW_E_ARB_MAX 0x201220
+
+#define mmSRAM_Y0_X0_RTR_LBW_W_ARB_MAX 0x201224
+
+#define mmSRAM_Y0_X0_RTR_LBW_L_ARB_MAX 0x201230
+
+#define mmSRAM_Y0_X0_RTR_LBW_DATA_E_ARB 0x201240
+
+#define mmSRAM_Y0_X0_RTR_LBW_DATA_W_ARB 0x201244
+
+#define mmSRAM_Y0_X0_RTR_LBW_DATA_L_ARB 0x201248
+
+#define mmSRAM_Y0_X0_RTR_LBW_WR_RS_E_ARB 0x201260
+
+#define mmSRAM_Y0_X0_RTR_LBW_WR_RS_W_ARB 0x201264
+
+#define mmSRAM_Y0_X0_RTR_LBW_WR_RS_L_ARB 0x201268
+
+#define mmSRAM_Y0_X0_RTR_DBG_E_ARB 0x201300
+
+#define mmSRAM_Y0_X0_RTR_DBG_W_ARB 0x201304
+
+#define mmSRAM_Y0_X0_RTR_DBG_L_ARB 0x201310
+
+#define mmSRAM_Y0_X0_RTR_DBG_E_ARB_MAX 0x201320
+
+#define mmSRAM_Y0_X0_RTR_DBG_W_ARB_MAX 0x201324
+
+#define mmSRAM_Y0_X0_RTR_DBG_L_ARB_MAX 0x201330
+
+#endif /* ASIC_REG_SRAM_Y0_X0_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h
new file mode 100644
index 000000000000..5624544303ca
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x1_rtr_regs.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_SRAM_Y0_X1_RTR_REGS_H_
+#define ASIC_REG_SRAM_Y0_X1_RTR_REGS_H_
+
+/*
+ *****************************************
+ * SRAM_Y0_X1_RTR (Prototype: IC_RTR)
+ *****************************************
+ */
+
+#define mmSRAM_Y0_X1_RTR_HBW_RD_RQ_E_ARB 0x205100
+
+#define mmSRAM_Y0_X1_RTR_HBW_RD_RQ_W_ARB 0x205104
+
+#define mmSRAM_Y0_X1_RTR_HBW_RD_RQ_L_ARB 0x205110
+
+#define mmSRAM_Y0_X1_RTR_HBW_E_ARB_MAX 0x205120
+
+#define mmSRAM_Y0_X1_RTR_HBW_W_ARB_MAX 0x205124
+
+#define mmSRAM_Y0_X1_RTR_HBW_L_ARB_MAX 0x205130
+
+#define mmSRAM_Y0_X1_RTR_HBW_DATA_E_ARB 0x205140
+
+#define mmSRAM_Y0_X1_RTR_HBW_DATA_W_ARB 0x205144
+
+#define mmSRAM_Y0_X1_RTR_HBW_DATA_L_ARB 0x205148
+
+#define mmSRAM_Y0_X1_RTR_HBW_WR_RS_E_ARB 0x205160
+
+#define mmSRAM_Y0_X1_RTR_HBW_WR_RS_W_ARB 0x205164
+
+#define mmSRAM_Y0_X1_RTR_HBW_WR_RS_L_ARB 0x205168
+
+#define mmSRAM_Y0_X1_RTR_LBW_RD_RQ_E_ARB 0x205200
+
+#define mmSRAM_Y0_X1_RTR_LBW_RD_RQ_W_ARB 0x205204
+
+#define mmSRAM_Y0_X1_RTR_LBW_RD_RQ_L_ARB 0x205210
+
+#define mmSRAM_Y0_X1_RTR_LBW_E_ARB_MAX 0x205220
+
+#define mmSRAM_Y0_X1_RTR_LBW_W_ARB_MAX 0x205224
+
+#define mmSRAM_Y0_X1_RTR_LBW_L_ARB_MAX 0x205230
+
+#define mmSRAM_Y0_X1_RTR_LBW_DATA_E_ARB 0x205240
+
+#define mmSRAM_Y0_X1_RTR_LBW_DATA_W_ARB 0x205244
+
+#define mmSRAM_Y0_X1_RTR_LBW_DATA_L_ARB 0x205248
+
+#define mmSRAM_Y0_X1_RTR_LBW_WR_RS_E_ARB 0x205260
+
+#define mmSRAM_Y0_X1_RTR_LBW_WR_RS_W_ARB 0x205264
+
+#define mmSRAM_Y0_X1_RTR_LBW_WR_RS_L_ARB 0x205268
+
+#define mmSRAM_Y0_X1_RTR_DBG_E_ARB 0x205300
+
+#define mmSRAM_Y0_X1_RTR_DBG_W_ARB 0x205304
+
+#define mmSRAM_Y0_X1_RTR_DBG_L_ARB 0x205310
+
+#define mmSRAM_Y0_X1_RTR_DBG_E_ARB_MAX 0x205320
+
+#define mmSRAM_Y0_X1_RTR_DBG_W_ARB_MAX 0x205324
+
+#define mmSRAM_Y0_X1_RTR_DBG_L_ARB_MAX 0x205330
+
+#endif /* ASIC_REG_SRAM_Y0_X1_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h
new file mode 100644
index 000000000000..3322bc0bd1df
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x2_rtr_regs.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_SRAM_Y0_X2_RTR_REGS_H_
+#define ASIC_REG_SRAM_Y0_X2_RTR_REGS_H_
+
+/*
+ *****************************************
+ * SRAM_Y0_X2_RTR (Prototype: IC_RTR)
+ *****************************************
+ */
+
+#define mmSRAM_Y0_X2_RTR_HBW_RD_RQ_E_ARB 0x209100
+
+#define mmSRAM_Y0_X2_RTR_HBW_RD_RQ_W_ARB 0x209104
+
+#define mmSRAM_Y0_X2_RTR_HBW_RD_RQ_L_ARB 0x209110
+
+#define mmSRAM_Y0_X2_RTR_HBW_E_ARB_MAX 0x209120
+
+#define mmSRAM_Y0_X2_RTR_HBW_W_ARB_MAX 0x209124
+
+#define mmSRAM_Y0_X2_RTR_HBW_L_ARB_MAX 0x209130
+
+#define mmSRAM_Y0_X2_RTR_HBW_DATA_E_ARB 0x209140
+
+#define mmSRAM_Y0_X2_RTR_HBW_DATA_W_ARB 0x209144
+
+#define mmSRAM_Y0_X2_RTR_HBW_DATA_L_ARB 0x209148
+
+#define mmSRAM_Y0_X2_RTR_HBW_WR_RS_E_ARB 0x209160
+
+#define mmSRAM_Y0_X2_RTR_HBW_WR_RS_W_ARB 0x209164
+
+#define mmSRAM_Y0_X2_RTR_HBW_WR_RS_L_ARB 0x209168
+
+#define mmSRAM_Y0_X2_RTR_LBW_RD_RQ_E_ARB 0x209200
+
+#define mmSRAM_Y0_X2_RTR_LBW_RD_RQ_W_ARB 0x209204
+
+#define mmSRAM_Y0_X2_RTR_LBW_RD_RQ_L_ARB 0x209210
+
+#define mmSRAM_Y0_X2_RTR_LBW_E_ARB_MAX 0x209220
+
+#define mmSRAM_Y0_X2_RTR_LBW_W_ARB_MAX 0x209224
+
+#define mmSRAM_Y0_X2_RTR_LBW_L_ARB_MAX 0x209230
+
+#define mmSRAM_Y0_X2_RTR_LBW_DATA_E_ARB 0x209240
+
+#define mmSRAM_Y0_X2_RTR_LBW_DATA_W_ARB 0x209244
+
+#define mmSRAM_Y0_X2_RTR_LBW_DATA_L_ARB 0x209248
+
+#define mmSRAM_Y0_X2_RTR_LBW_WR_RS_E_ARB 0x209260
+
+#define mmSRAM_Y0_X2_RTR_LBW_WR_RS_W_ARB 0x209264
+
+#define mmSRAM_Y0_X2_RTR_LBW_WR_RS_L_ARB 0x209268
+
+#define mmSRAM_Y0_X2_RTR_DBG_E_ARB 0x209300
+
+#define mmSRAM_Y0_X2_RTR_DBG_W_ARB 0x209304
+
+#define mmSRAM_Y0_X2_RTR_DBG_L_ARB 0x209310
+
+#define mmSRAM_Y0_X2_RTR_DBG_E_ARB_MAX 0x209320
+
+#define mmSRAM_Y0_X2_RTR_DBG_W_ARB_MAX 0x209324
+
+#define mmSRAM_Y0_X2_RTR_DBG_L_ARB_MAX 0x209330
+
+#endif /* ASIC_REG_SRAM_Y0_X2_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h
new file mode 100644
index 000000000000..81e393db2027
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x3_rtr_regs.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_SRAM_Y0_X3_RTR_REGS_H_
+#define ASIC_REG_SRAM_Y0_X3_RTR_REGS_H_
+
+/*
+ *****************************************
+ * SRAM_Y0_X3_RTR (Prototype: IC_RTR)
+ *****************************************
+ */
+
+#define mmSRAM_Y0_X3_RTR_HBW_RD_RQ_E_ARB 0x20D100
+
+#define mmSRAM_Y0_X3_RTR_HBW_RD_RQ_W_ARB 0x20D104
+
+#define mmSRAM_Y0_X3_RTR_HBW_RD_RQ_L_ARB 0x20D110
+
+#define mmSRAM_Y0_X3_RTR_HBW_E_ARB_MAX 0x20D120
+
+#define mmSRAM_Y0_X3_RTR_HBW_W_ARB_MAX 0x20D124
+
+#define mmSRAM_Y0_X3_RTR_HBW_L_ARB_MAX 0x20D130
+
+#define mmSRAM_Y0_X3_RTR_HBW_DATA_E_ARB 0x20D140
+
+#define mmSRAM_Y0_X3_RTR_HBW_DATA_W_ARB 0x20D144
+
+#define mmSRAM_Y0_X3_RTR_HBW_DATA_L_ARB 0x20D148
+
+#define mmSRAM_Y0_X3_RTR_HBW_WR_RS_E_ARB 0x20D160
+
+#define mmSRAM_Y0_X3_RTR_HBW_WR_RS_W_ARB 0x20D164
+
+#define mmSRAM_Y0_X3_RTR_HBW_WR_RS_L_ARB 0x20D168
+
+#define mmSRAM_Y0_X3_RTR_LBW_RD_RQ_E_ARB 0x20D200
+
+#define mmSRAM_Y0_X3_RTR_LBW_RD_RQ_W_ARB 0x20D204
+
+#define mmSRAM_Y0_X3_RTR_LBW_RD_RQ_L_ARB 0x20D210
+
+#define mmSRAM_Y0_X3_RTR_LBW_E_ARB_MAX 0x20D220
+
+#define mmSRAM_Y0_X3_RTR_LBW_W_ARB_MAX 0x20D224
+
+#define mmSRAM_Y0_X3_RTR_LBW_L_ARB_MAX 0x20D230
+
+#define mmSRAM_Y0_X3_RTR_LBW_DATA_E_ARB 0x20D240
+
+#define mmSRAM_Y0_X3_RTR_LBW_DATA_W_ARB 0x20D244
+
+#define mmSRAM_Y0_X3_RTR_LBW_DATA_L_ARB 0x20D248
+
+#define mmSRAM_Y0_X3_RTR_LBW_WR_RS_E_ARB 0x20D260
+
+#define mmSRAM_Y0_X3_RTR_LBW_WR_RS_W_ARB 0x20D264
+
+#define mmSRAM_Y0_X3_RTR_LBW_WR_RS_L_ARB 0x20D268
+
+#define mmSRAM_Y0_X3_RTR_DBG_E_ARB 0x20D300
+
+#define mmSRAM_Y0_X3_RTR_DBG_W_ARB 0x20D304
+
+#define mmSRAM_Y0_X3_RTR_DBG_L_ARB 0x20D310
+
+#define mmSRAM_Y0_X3_RTR_DBG_E_ARB_MAX 0x20D320
+
+#define mmSRAM_Y0_X3_RTR_DBG_W_ARB_MAX 0x20D324
+
+#define mmSRAM_Y0_X3_RTR_DBG_L_ARB_MAX 0x20D330
+
+#endif /* ASIC_REG_SRAM_Y0_X3_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h
new file mode 100644
index 000000000000..b2e11b1de385
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/sram_y0_x4_rtr_regs.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_SRAM_Y0_X4_RTR_REGS_H_
+#define ASIC_REG_SRAM_Y0_X4_RTR_REGS_H_
+
+/*
+ *****************************************
+ * SRAM_Y0_X4_RTR (Prototype: IC_RTR)
+ *****************************************
+ */
+
+#define mmSRAM_Y0_X4_RTR_HBW_RD_RQ_E_ARB 0x211100
+
+#define mmSRAM_Y0_X4_RTR_HBW_RD_RQ_W_ARB 0x211104
+
+#define mmSRAM_Y0_X4_RTR_HBW_RD_RQ_L_ARB 0x211110
+
+#define mmSRAM_Y0_X4_RTR_HBW_E_ARB_MAX 0x211120
+
+#define mmSRAM_Y0_X4_RTR_HBW_W_ARB_MAX 0x211124
+
+#define mmSRAM_Y0_X4_RTR_HBW_L_ARB_MAX 0x211130
+
+#define mmSRAM_Y0_X4_RTR_HBW_DATA_E_ARB 0x211140
+
+#define mmSRAM_Y0_X4_RTR_HBW_DATA_W_ARB 0x211144
+
+#define mmSRAM_Y0_X4_RTR_HBW_DATA_L_ARB 0x211148
+
+#define mmSRAM_Y0_X4_RTR_HBW_WR_RS_E_ARB 0x211160
+
+#define mmSRAM_Y0_X4_RTR_HBW_WR_RS_W_ARB 0x211164
+
+#define mmSRAM_Y0_X4_RTR_HBW_WR_RS_L_ARB 0x211168
+
+#define mmSRAM_Y0_X4_RTR_LBW_RD_RQ_E_ARB 0x211200
+
+#define mmSRAM_Y0_X4_RTR_LBW_RD_RQ_W_ARB 0x211204
+
+#define mmSRAM_Y0_X4_RTR_LBW_RD_RQ_L_ARB 0x211210
+
+#define mmSRAM_Y0_X4_RTR_LBW_E_ARB_MAX 0x211220
+
+#define mmSRAM_Y0_X4_RTR_LBW_W_ARB_MAX 0x211224
+
+#define mmSRAM_Y0_X4_RTR_LBW_L_ARB_MAX 0x211230
+
+#define mmSRAM_Y0_X4_RTR_LBW_DATA_E_ARB 0x211240
+
+#define mmSRAM_Y0_X4_RTR_LBW_DATA_W_ARB 0x211244
+
+#define mmSRAM_Y0_X4_RTR_LBW_DATA_L_ARB 0x211248
+
+#define mmSRAM_Y0_X4_RTR_LBW_WR_RS_E_ARB 0x211260
+
+#define mmSRAM_Y0_X4_RTR_LBW_WR_RS_W_ARB 0x211264
+
+#define mmSRAM_Y0_X4_RTR_LBW_WR_RS_L_ARB 0x211268
+
+#define mmSRAM_Y0_X4_RTR_DBG_E_ARB 0x211300
+
+#define mmSRAM_Y0_X4_RTR_DBG_W_ARB 0x211304
+
+#define mmSRAM_Y0_X4_RTR_DBG_L_ARB 0x211310
+
+#define mmSRAM_Y0_X4_RTR_DBG_E_ARB_MAX 0x211320
+
+#define mmSRAM_Y0_X4_RTR_DBG_W_ARB_MAX 0x211324
+
+#define mmSRAM_Y0_X4_RTR_DBG_L_ARB_MAX 0x211330
+
+#endif /* ASIC_REG_SRAM_Y0_X4_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h
new file mode 100644
index 000000000000..b4ea8cae2757
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/stlb_masks.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_STLB_MASKS_H_
+#define ASIC_REG_STLB_MASKS_H_
+
+/*
+ *****************************************
+ * STLB (Prototype: STLB)
+ *****************************************
+ */
+
+/* STLB_CACHE_INV */
+#define STLB_CACHE_INV_PRODUCER_INDEX_SHIFT 0
+#define STLB_CACHE_INV_PRODUCER_INDEX_MASK 0xFF
+#define STLB_CACHE_INV_INDEX_MASK_SHIFT 8
+#define STLB_CACHE_INV_INDEX_MASK_MASK 0xFF00
+
+/* STLB_CACHE_INV_BASE_39_8 */
+#define STLB_CACHE_INV_BASE_39_8_PA_SHIFT 0
+#define STLB_CACHE_INV_BASE_39_8_PA_MASK 0xFFFFFFFF
+
+/* STLB_CACHE_INV_BASE_49_40 */
+#define STLB_CACHE_INV_BASE_49_40_PA_SHIFT 0
+#define STLB_CACHE_INV_BASE_49_40_PA_MASK 0x3FF
+
+/* STLB_STLB_FEATURE_EN */
+#define STLB_STLB_FEATURE_EN_STLB_CTRL_MULTI_PAGE_SIZE_EN_SHIFT 0
+#define STLB_STLB_FEATURE_EN_STLB_CTRL_MULTI_PAGE_SIZE_EN_MASK 0x1
+#define STLB_STLB_FEATURE_EN_MULTI_PAGE_SIZE_EN_SHIFT 1
+#define STLB_STLB_FEATURE_EN_MULTI_PAGE_SIZE_EN_MASK 0x2
+#define STLB_STLB_FEATURE_EN_LOOKUP_EN_SHIFT 2
+#define STLB_STLB_FEATURE_EN_LOOKUP_EN_MASK 0x4
+#define STLB_STLB_FEATURE_EN_BYPASS_SHIFT 3
+#define STLB_STLB_FEATURE_EN_BYPASS_MASK 0x8
+#define STLB_STLB_FEATURE_EN_BANK_STOP_SHIFT 4
+#define STLB_STLB_FEATURE_EN_BANK_STOP_MASK 0x10
+#define STLB_STLB_FEATURE_EN_TRACE_EN_SHIFT 5
+#define STLB_STLB_FEATURE_EN_TRACE_EN_MASK 0x20
+#define STLB_STLB_FEATURE_EN_FOLLOWER_EN_SHIFT 6
+#define STLB_STLB_FEATURE_EN_FOLLOWER_EN_MASK 0x40
+#define STLB_STLB_FEATURE_EN_CACHING_EN_SHIFT 7
+#define STLB_STLB_FEATURE_EN_CACHING_EN_MASK 0xF80
+
+/* STLB_STLB_AXI_CACHE */
+#define STLB_STLB_AXI_CACHE_STLB_CTRL_ARCACHE_SHIFT 0
+#define STLB_STLB_AXI_CACHE_STLB_CTRL_ARCACHE_MASK 0xF
+#define STLB_STLB_AXI_CACHE_STLB_CTRL_AWCACHE_SHIFT 4
+#define STLB_STLB_AXI_CACHE_STLB_CTRL_AWCACHE_MASK 0xF0
+#define STLB_STLB_AXI_CACHE_INV_ARCACHE_SHIFT 8
+#define STLB_STLB_AXI_CACHE_INV_ARCACHE_MASK 0xF00
+
+/* STLB_HOP_CONFIGURATION */
+#define STLB_HOP_CONFIGURATION_FIRST_HOP_SHIFT 0
+#define STLB_HOP_CONFIGURATION_FIRST_HOP_MASK 0x7
+#define STLB_HOP_CONFIGURATION_FIRST_LOOKUP_HOP_SHIFT 4
+#define STLB_HOP_CONFIGURATION_FIRST_LOOKUP_HOP_MASK 0x70
+#define STLB_HOP_CONFIGURATION_LAST_HOP_SHIFT 8
+#define STLB_HOP_CONFIGURATION_LAST_HOP_MASK 0x700
+
+/* STLB_LINK_LIST_LOOKUP_MASK_49_32 */
+#define STLB_LINK_LIST_LOOKUP_MASK_49_32_R_SHIFT 0
+#define STLB_LINK_LIST_LOOKUP_MASK_49_32_R_MASK 0x3FFFF
+
+/* STLB_LINK_LIST_LOOKUP_MASK_31_0 */
+#define STLB_LINK_LIST_LOOKUP_MASK_31_0_R_SHIFT 0
+#define STLB_LINK_LIST_LOOKUP_MASK_31_0_R_MASK 0xFFFFFFFF
+
+/* STLB_LINK_LIST */
+#define STLB_LINK_LIST_CLEAR_SHIFT 0
+#define STLB_LINK_LIST_CLEAR_MASK 0x1
+#define STLB_LINK_LIST_EN_SHIFT 1
+#define STLB_LINK_LIST_EN_MASK 0x2
+
+/* STLB_INV_ALL_START */
+#define STLB_INV_ALL_START_R_SHIFT 0
+#define STLB_INV_ALL_START_R_MASK 0x1
+
+/* STLB_INV_ALL_SET */
+#define STLB_INV_ALL_SET_R_SHIFT 0
+#define STLB_INV_ALL_SET_R_MASK 0xFF
+
+/* STLB_INV_PS */
+#define STLB_INV_PS_R_SHIFT 0
+#define STLB_INV_PS_R_MASK 0x3
+
+/* STLB_INV_CONSUMER_INDEX */
+#define STLB_INV_CONSUMER_INDEX_R_SHIFT 0
+#define STLB_INV_CONSUMER_INDEX_R_MASK 0xFF
+
+/* STLB_INV_HIT_COUNT */
+#define STLB_INV_HIT_COUNT_R_SHIFT 0
+#define STLB_INV_HIT_COUNT_R_MASK 0x7FF
+
+/* STLB_INV_SET */
+#define STLB_INV_SET_R_SHIFT 0
+#define STLB_INV_SET_R_MASK 0xFF
+
+/* STLB_SRAM_INIT */
+#define STLB_SRAM_INIT_BUSY_TAG_SHIFT 0
+#define STLB_SRAM_INIT_BUSY_TAG_MASK 0x3
+#define STLB_SRAM_INIT_BUSY_SLICE_SHIFT 2
+#define STLB_SRAM_INIT_BUSY_SLICE_MASK 0xC
+#define STLB_SRAM_INIT_BUSY_DATA_SHIFT 4
+#define STLB_SRAM_INIT_BUSY_DATA_MASK 0x10
+
+#endif /* ASIC_REG_STLB_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h
new file mode 100644
index 000000000000..0f5281d3e65b
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/stlb_regs.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_STLB_REGS_H_
+#define ASIC_REG_STLB_REGS_H_
+
+/*
+ *****************************************
+ * STLB (Prototype: STLB)
+ *****************************************
+ */
+
+#define mmSTLB_CACHE_INV 0x490010
+
+#define mmSTLB_CACHE_INV_BASE_39_8 0x490014
+
+#define mmSTLB_CACHE_INV_BASE_49_40 0x490018
+
+#define mmSTLB_STLB_FEATURE_EN 0x49001C
+
+#define mmSTLB_STLB_AXI_CACHE 0x490020
+
+#define mmSTLB_HOP_CONFIGURATION 0x490024
+
+#define mmSTLB_LINK_LIST_LOOKUP_MASK_49_32 0x490028
+
+#define mmSTLB_LINK_LIST_LOOKUP_MASK_31_0 0x49002C
+
+#define mmSTLB_LINK_LIST 0x490030
+
+#define mmSTLB_INV_ALL_START 0x490034
+
+#define mmSTLB_INV_ALL_SET 0x490038
+
+#define mmSTLB_INV_PS 0x49003C
+
+#define mmSTLB_INV_CONSUMER_INDEX 0x490040
+
+#define mmSTLB_INV_HIT_COUNT 0x490044
+
+#define mmSTLB_INV_SET 0x490048
+
+#define mmSTLB_SRAM_INIT 0x49004C
+
+#endif /* ASIC_REG_STLB_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h
new file mode 100644
index 000000000000..e5587b49eecd
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_masks.h
@@ -0,0 +1,1607 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_CFG_MASKS_H_
+#define ASIC_REG_TPC0_CFG_MASKS_H_
+
+/*
+ *****************************************
+ * TPC0_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+/* TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_0_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_1_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_2_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_3_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_4_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_5_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_6_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW */
+#define TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH */
+#define TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_PADDING_VALUE */
+#define TPC0_CFG_KERNEL_TENSOR_7_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG */
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_0_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_1_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_2_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_3_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_4_SIZE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW */
+#define TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW_V_SHIFT 0
+#define TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH */
+#define TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH_V_SHIFT 0
+#define TPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_BASE_DIM_0 */
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_0_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_0_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_SIZE_DIM_0 */
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_0_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_0_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_BASE_DIM_1 */
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_1_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_1_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_SIZE_DIM_1 */
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_1_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_1_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_BASE_DIM_2 */
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_2_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_2_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_SIZE_DIM_2 */
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_2_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_2_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_BASE_DIM_3 */
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_3_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_3_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_SIZE_DIM_3 */
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_3_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_3_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_BASE_DIM_4 */
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_4_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_BASE_DIM_4_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_TID_SIZE_DIM_4 */
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_4_V_SHIFT 0
+#define TPC0_CFG_KERNEL_TID_SIZE_DIM_4_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_SRF */
+#define TPC0_CFG_KERNEL_SRF_V_SHIFT 0
+#define TPC0_CFG_KERNEL_SRF_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_KERNEL_KERNEL_CONFIG */
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_SMALL_VLM_SHIFT 0
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_SMALL_VLM_MASK 0x1
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_ASO_EVICT_L0_SHIFT 1
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_ASO_EVICT_L0_MASK 0x2
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_NUM_VALID_SRFS_SHIFT 8
+#define TPC0_CFG_KERNEL_KERNEL_CONFIG_NUM_VALID_SRFS_MASK 0x3F00
+
+/* TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE */
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define TPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* TPC0_CFG_RESERVED_DESC_END */
+#define TPC0_CFG_RESERVED_DESC_END_V_SHIFT 0
+#define TPC0_CFG_RESERVED_DESC_END_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_ROUND_CSR */
+#define TPC0_CFG_ROUND_CSR_MODE_SHIFT 0
+#define TPC0_CFG_ROUND_CSR_MODE_MASK 0x7
+
+/* TPC0_CFG_TBUF_BASE_ADDR_LOW */
+#define TPC0_CFG_TBUF_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_TBUF_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_TBUF_BASE_ADDR_HIGH */
+#define TPC0_CFG_TBUF_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_TBUF_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_SEMAPHORE */
+#define TPC0_CFG_SEMAPHORE_V_SHIFT 0
+#define TPC0_CFG_SEMAPHORE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_VFLAGS */
+#define TPC0_CFG_VFLAGS_V_SHIFT 0
+#define TPC0_CFG_VFLAGS_V_MASK 0xF
+
+/* TPC0_CFG_SFLAGS */
+#define TPC0_CFG_SFLAGS_V_SHIFT 0
+#define TPC0_CFG_SFLAGS_V_MASK 0xF
+
+/* TPC0_CFG_LFSR_POLYNOM */
+#define TPC0_CFG_LFSR_POLYNOM_V_SHIFT 0
+#define TPC0_CFG_LFSR_POLYNOM_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_STATUS */
+#define TPC0_CFG_STATUS_SCALAR_PIPE_EMPTY_SHIFT 1
+#define TPC0_CFG_STATUS_SCALAR_PIPE_EMPTY_MASK 0x2
+#define TPC0_CFG_STATUS_VECTOR_PIPE_EMPTY_SHIFT 2
+#define TPC0_CFG_STATUS_VECTOR_PIPE_EMPTY_MASK 0x4
+#define TPC0_CFG_STATUS_IQ_EMPTY_SHIFT 3
+#define TPC0_CFG_STATUS_IQ_EMPTY_MASK 0x8
+#define TPC0_CFG_STATUS_NO_INFLIGH_MEM_ACCESSES_SHIFT 4
+#define TPC0_CFG_STATUS_NO_INFLIGH_MEM_ACCESSES_MASK 0x10
+
+/* TPC0_CFG_CFG_BASE_ADDRESS_HIGH */
+#define TPC0_CFG_CFG_BASE_ADDRESS_HIGH_V_SHIFT 0
+#define TPC0_CFG_CFG_BASE_ADDRESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_CFG_SUBTRACT_VALUE */
+#define TPC0_CFG_CFG_SUBTRACT_VALUE_V_SHIFT 0
+#define TPC0_CFG_CFG_SUBTRACT_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_SM_BASE_ADDRESS_LOW */
+#define TPC0_CFG_SM_BASE_ADDRESS_LOW_V_SHIFT 0
+#define TPC0_CFG_SM_BASE_ADDRESS_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_SM_BASE_ADDRESS_HIGH */
+#define TPC0_CFG_SM_BASE_ADDRESS_HIGH_V_SHIFT 0
+#define TPC0_CFG_SM_BASE_ADDRESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_TPC_CMD */
+#define TPC0_CFG_TPC_CMD_ICACHE_INVALIDATE_SHIFT 0
+#define TPC0_CFG_TPC_CMD_ICACHE_INVALIDATE_MASK 0x1
+#define TPC0_CFG_TPC_CMD_DCACHE_INVALIDATE_SHIFT 1
+#define TPC0_CFG_TPC_CMD_DCACHE_INVALIDATE_MASK 0x2
+#define TPC0_CFG_TPC_CMD_LCACHE_INVALIDATE_SHIFT 2
+#define TPC0_CFG_TPC_CMD_LCACHE_INVALIDATE_MASK 0x4
+#define TPC0_CFG_TPC_CMD_TCACHE_INVALIDATE_SHIFT 3
+#define TPC0_CFG_TPC_CMD_TCACHE_INVALIDATE_MASK 0x8
+#define TPC0_CFG_TPC_CMD_ICACHE_PREFETCH_64KB_SHIFT 4
+#define TPC0_CFG_TPC_CMD_ICACHE_PREFETCH_64KB_MASK 0x10
+#define TPC0_CFG_TPC_CMD_ICACHE_PREFETCH_32KB_SHIFT 5
+#define TPC0_CFG_TPC_CMD_ICACHE_PREFETCH_32KB_MASK 0x20
+#define TPC0_CFG_TPC_CMD_QMAN_STOP_SHIFT 6
+#define TPC0_CFG_TPC_CMD_QMAN_STOP_MASK 0x40
+
+/* TPC0_CFG_TPC_EXECUTE */
+#define TPC0_CFG_TPC_EXECUTE_V_SHIFT 0
+#define TPC0_CFG_TPC_EXECUTE_V_MASK 0x1
+
+/* TPC0_CFG_TPC_STALL */
+#define TPC0_CFG_TPC_STALL_V_SHIFT 0
+#define TPC0_CFG_TPC_STALL_V_MASK 0x1
+
+/* TPC0_CFG_ICACHE_BASE_ADDERESS_LOW */
+#define TPC0_CFG_ICACHE_BASE_ADDERESS_LOW_V_SHIFT 0
+#define TPC0_CFG_ICACHE_BASE_ADDERESS_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_ICACHE_BASE_ADDERESS_HIGH */
+#define TPC0_CFG_ICACHE_BASE_ADDERESS_HIGH_V_SHIFT 0
+#define TPC0_CFG_ICACHE_BASE_ADDERESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_MSS_CONFIG */
+#define TPC0_CFG_MSS_CONFIG_AWCACHE_SHIFT 0
+#define TPC0_CFG_MSS_CONFIG_AWCACHE_MASK 0xF
+#define TPC0_CFG_MSS_CONFIG_ARCACHE_SHIFT 4
+#define TPC0_CFG_MSS_CONFIG_ARCACHE_MASK 0xF0
+#define TPC0_CFG_MSS_CONFIG_ICACHE_FETCH_LINE_NUM_SHIFT 8
+#define TPC0_CFG_MSS_CONFIG_ICACHE_FETCH_LINE_NUM_MASK 0x300
+#define TPC0_CFG_MSS_CONFIG_EXPOSED_PIPE_DIS_SHIFT 10
+#define TPC0_CFG_MSS_CONFIG_EXPOSED_PIPE_DIS_MASK 0x400
+
+/* TPC0_CFG_TPC_INTR_CAUSE */
+#define TPC0_CFG_TPC_INTR_CAUSE_CAUSE_SHIFT 0
+#define TPC0_CFG_TPC_INTR_CAUSE_CAUSE_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_TPC_INTR_MASK */
+#define TPC0_CFG_TPC_INTR_MASK_MASK_SHIFT 0
+#define TPC0_CFG_TPC_INTR_MASK_MASK_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_TSB_CONFIG */
+#define TPC0_CFG_TSB_CONFIG_TSB_AGU_MAX_CREDIT_SHIFT 0
+#define TPC0_CFG_TSB_CONFIG_TSB_AGU_MAX_CREDIT_MASK 0x1F
+#define TPC0_CFG_TSB_CONFIG_TSB_EU_MAX_CREDIT_SHIFT 5
+#define TPC0_CFG_TSB_CONFIG_TSB_EU_MAX_CREDIT_MASK 0x3E0
+#define TPC0_CFG_TSB_CONFIG_MAX_OUTSTANDING_SHIFT 10
+#define TPC0_CFG_TSB_CONFIG_MAX_OUTSTANDING_MASK 0xFFC00
+#define TPC0_CFG_TSB_CONFIG_MAX_SIZE_SHIFT 20
+#define TPC0_CFG_TSB_CONFIG_MAX_SIZE_MASK 0x3FF00000
+
+/* TPC0_CFG_QM_TENSOR_0_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_0_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_0_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_0_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_1_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_1_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_1_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_2_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_2_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_2_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_3_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_3_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_3_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_4_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_4_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_4_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_5_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_5_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_5_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_6_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_6_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_6_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_BASE_ADDR_LOW */
+#define TPC0_CFG_QM_TENSOR_7_BASE_ADDR_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_BASE_ADDR_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_BASE_ADDR_HIGH */
+#define TPC0_CFG_QM_TENSOR_7_BASE_ADDR_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_BASE_ADDR_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_PADDING_VALUE */
+#define TPC0_CFG_QM_TENSOR_7_PADDING_VALUE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_PADDING_VALUE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG */
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_DATA_TYPE_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_DATA_TYPE_MASK 0x3
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_VALID_DIM_MASK_SHIFT 8
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_VALID_DIM_MASK_MASK 0x1F00
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_LAST_DIM_SHIFT 16
+#define TPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG_LAST_DIM_MASK 0x70000
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_0_SIZE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_0_STRIDE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_1_SIZE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_1_STRIDE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_2_SIZE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_2_STRIDE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_3_SIZE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_3_STRIDE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_4_SIZE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_SIZE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_SIZE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_4_STRIDE */
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_STRIDE_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_STRIDE_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET */
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET_V_SHIFT 0
+#define TPC0_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_KERNEL_BASE_ADDRESS_LOW */
+#define TPC0_CFG_QM_KERNEL_BASE_ADDRESS_LOW_V_SHIFT 0
+#define TPC0_CFG_QM_KERNEL_BASE_ADDRESS_LOW_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_KERNEL_BASE_ADDRESS_HIGH */
+#define TPC0_CFG_QM_KERNEL_BASE_ADDRESS_HIGH_V_SHIFT 0
+#define TPC0_CFG_QM_KERNEL_BASE_ADDRESS_HIGH_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_BASE_DIM_0 */
+#define TPC0_CFG_QM_TID_BASE_DIM_0_V_SHIFT 0
+#define TPC0_CFG_QM_TID_BASE_DIM_0_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_SIZE_DIM_0 */
+#define TPC0_CFG_QM_TID_SIZE_DIM_0_V_SHIFT 0
+#define TPC0_CFG_QM_TID_SIZE_DIM_0_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_BASE_DIM_1 */
+#define TPC0_CFG_QM_TID_BASE_DIM_1_V_SHIFT 0
+#define TPC0_CFG_QM_TID_BASE_DIM_1_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_SIZE_DIM_1 */
+#define TPC0_CFG_QM_TID_SIZE_DIM_1_V_SHIFT 0
+#define TPC0_CFG_QM_TID_SIZE_DIM_1_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_BASE_DIM_2 */
+#define TPC0_CFG_QM_TID_BASE_DIM_2_V_SHIFT 0
+#define TPC0_CFG_QM_TID_BASE_DIM_2_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_SIZE_DIM_2 */
+#define TPC0_CFG_QM_TID_SIZE_DIM_2_V_SHIFT 0
+#define TPC0_CFG_QM_TID_SIZE_DIM_2_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_BASE_DIM_3 */
+#define TPC0_CFG_QM_TID_BASE_DIM_3_V_SHIFT 0
+#define TPC0_CFG_QM_TID_BASE_DIM_3_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_SIZE_DIM_3 */
+#define TPC0_CFG_QM_TID_SIZE_DIM_3_V_SHIFT 0
+#define TPC0_CFG_QM_TID_SIZE_DIM_3_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_BASE_DIM_4 */
+#define TPC0_CFG_QM_TID_BASE_DIM_4_V_SHIFT 0
+#define TPC0_CFG_QM_TID_BASE_DIM_4_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_TID_SIZE_DIM_4 */
+#define TPC0_CFG_QM_TID_SIZE_DIM_4_V_SHIFT 0
+#define TPC0_CFG_QM_TID_SIZE_DIM_4_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_SRF */
+#define TPC0_CFG_QM_SRF_V_SHIFT 0
+#define TPC0_CFG_QM_SRF_V_MASK 0xFFFFFFFF
+
+/* TPC0_CFG_QM_KERNEL_CONFIG */
+#define TPC0_CFG_QM_KERNEL_CONFIG_SMALL_VLM_SHIFT 0
+#define TPC0_CFG_QM_KERNEL_CONFIG_SMALL_VLM_MASK 0x1
+#define TPC0_CFG_QM_KERNEL_CONFIG_ASO_EVICT_L0_SHIFT 1
+#define TPC0_CFG_QM_KERNEL_CONFIG_ASO_EVICT_L0_MASK 0x2
+#define TPC0_CFG_QM_KERNEL_CONFIG_NUM_VALID_SRFS_SHIFT 8
+#define TPC0_CFG_QM_KERNEL_CONFIG_NUM_VALID_SRFS_MASK 0x3F00
+
+/* TPC0_CFG_QM_SYNC_OBJECT_MESSAGE */
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_SHIFT 0
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_WRITE_VALUE_MASK 0xFFFF
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_SHIFT 16
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_ADDRESS_OFFSET_MASK 0x7FFF0000
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_OPERATION_SHIFT 31
+#define TPC0_CFG_QM_SYNC_OBJECT_MESSAGE_SO_OPERATION_MASK 0x80000000
+
+/* TPC0_CFG_ARUSER */
+#define TPC0_CFG_ARUSER_ASID_SHIFT 0
+#define TPC0_CFG_ARUSER_ASID_MASK 0x3FF
+#define TPC0_CFG_ARUSER_MMBP_SHIFT 10
+#define TPC0_CFG_ARUSER_MMBP_MASK 0x400
+#define TPC0_CFG_ARUSER_V_SHIFT 11
+#define TPC0_CFG_ARUSER_V_MASK 0xFFFFF800
+
+/* TPC0_CFG_AWUSER */
+#define TPC0_CFG_AWUSER_ASID_SHIFT 0
+#define TPC0_CFG_AWUSER_ASID_MASK 0x3FF
+#define TPC0_CFG_AWUSER_MMBP_SHIFT 10
+#define TPC0_CFG_AWUSER_MMBP_MASK 0x400
+#define TPC0_CFG_AWUSER_V_SHIFT 11
+#define TPC0_CFG_AWUSER_V_MASK 0xFFFFF800
+
+/* TPC0_CFG_FUNC_MBIST_CNTRL */
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_START_SHIFT 0
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_START_MASK 0x1
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_DONE_SHIFT 1
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_DONE_MASK 0x2
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_ACTIVE_SHIFT 2
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_ACTIVE_MASK 0x4
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_FAILED_SHIFT 16
+#define TPC0_CFG_FUNC_MBIST_CNTRL_MBIST_FAILED_MASK 0x3FF0000
+
+/* TPC0_CFG_FUNC_MBIST_PAT */
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN0_EVEN_SHIFT 0
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN0_EVEN_MASK 0x3
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN0_ODD_SHIFT 2
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN0_ODD_MASK 0xC
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN1_EVEN_SHIFT 4
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN1_EVEN_MASK 0x30
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN1_ODD_SHIFT 6
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN1_ODD_MASK 0xC0
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN2_EVEN_SHIFT 8
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN2_EVEN_MASK 0x300
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN2_ODD_SHIFT 10
+#define TPC0_CFG_FUNC_MBIST_PAT_MBIST_PATTERN2_ODD_MASK 0xC00
+
+/* TPC0_CFG_FUNC_MBIST_MEM */
+#define TPC0_CFG_FUNC_MBIST_MEM_MAX_ADDR_SHIFT 0
+#define TPC0_CFG_FUNC_MBIST_MEM_MAX_ADDR_MASK 0x7FF
+#define TPC0_CFG_FUNC_MBIST_MEM_PATTERN_EN_SHIFT 12
+#define TPC0_CFG_FUNC_MBIST_MEM_PATTERN_EN_MASK 0x7000
+#define TPC0_CFG_FUNC_MBIST_MEM_LAST_FAILED_ADDR_SHIFT 16
+#define TPC0_CFG_FUNC_MBIST_MEM_LAST_FAILED_ADDR_MASK 0x7FF0000
+#define TPC0_CFG_FUNC_MBIST_MEM_LAST_FAILED_PATTERN_SHIFT 28
+#define TPC0_CFG_FUNC_MBIST_MEM_LAST_FAILED_PATTERN_MASK 0x70000000
+
+#endif /* ASIC_REG_TPC0_CFG_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h
new file mode 100644
index 000000000000..2be28a63c50a
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_CFG_REGS_H_
+#define ASIC_REG_TPC0_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC0_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xE06400
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xE06404
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xE06408
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xE0640C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xE06410
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xE06414
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xE06418
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xE0641C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xE06420
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xE06424
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xE06428
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xE0642C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xE06430
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xE06434
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xE06438
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xE0643C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xE06440
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xE06444
+
+#define mmTPC0_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xE06448
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xE0644C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xE06450
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xE06454
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xE06458
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xE0645C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xE06460
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xE06464
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xE06468
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xE0646C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xE06470
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xE06474
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xE06478
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xE0647C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xE06480
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xE06484
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xE06488
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xE0648C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xE06490
+
+#define mmTPC0_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xE06494
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xE06498
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xE0649C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xE064A0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xE064A4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xE064A8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xE064AC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xE064B0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xE064B4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xE064B8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xE064BC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xE064C0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xE064C4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xE064C8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xE064CC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xE064D0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xE064D4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xE064D8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xE064DC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xE064E0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xE064E4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xE064E8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xE064EC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xE064F0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xE064F4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xE064F8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xE064FC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xE06500
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xE06504
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xE06508
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xE0650C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xE06510
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xE06514
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xE06518
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xE0651C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xE06520
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xE06524
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xE06528
+
+#define mmTPC0_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xE0652C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xE06530
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xE06534
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xE06538
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xE0653C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xE06540
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xE06544
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xE06548
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xE0654C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xE06550
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xE06554
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xE06558
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xE0655C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xE06560
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xE06564
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xE06568
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xE0656C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xE06570
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xE06574
+
+#define mmTPC0_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xE06578
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xE0657C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xE06580
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xE06584
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xE06588
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xE0658C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xE06590
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xE06594
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xE06598
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xE0659C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xE065A0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xE065A4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xE065A8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xE065AC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xE065B0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xE065B4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xE065B8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xE065BC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xE065C0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xE065C4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xE065C8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xE065CC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xE065D0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xE065D4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xE065D8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xE065DC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xE065E0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xE065E4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xE065E8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xE065EC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xE065F0
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xE065F4
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xE065F8
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xE065FC
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xE06600
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xE06604
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xE06608
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xE0660C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xE06610
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xE06614
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xE06618
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xE0661C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xE06620
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xE06624
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xE06628
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xE0662C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xE06630
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xE06634
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xE06638
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xE0663C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xE06640
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xE06644
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xE06648
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xE0664C
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xE06650
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xE06654
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xE06658
+
+#define mmTPC0_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xE0665C
+
+#define mmTPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xE06660
+
+#define mmTPC0_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xE06664
+
+#define mmTPC0_CFG_KERNEL_TID_BASE_DIM_0 0xE06668
+
+#define mmTPC0_CFG_KERNEL_TID_SIZE_DIM_0 0xE0666C
+
+#define mmTPC0_CFG_KERNEL_TID_BASE_DIM_1 0xE06670
+
+#define mmTPC0_CFG_KERNEL_TID_SIZE_DIM_1 0xE06674
+
+#define mmTPC0_CFG_KERNEL_TID_BASE_DIM_2 0xE06678
+
+#define mmTPC0_CFG_KERNEL_TID_SIZE_DIM_2 0xE0667C
+
+#define mmTPC0_CFG_KERNEL_TID_BASE_DIM_3 0xE06680
+
+#define mmTPC0_CFG_KERNEL_TID_SIZE_DIM_3 0xE06684
+
+#define mmTPC0_CFG_KERNEL_TID_BASE_DIM_4 0xE06688
+
+#define mmTPC0_CFG_KERNEL_TID_SIZE_DIM_4 0xE0668C
+
+#define mmTPC0_CFG_KERNEL_SRF_0 0xE06690
+
+#define mmTPC0_CFG_KERNEL_SRF_1 0xE06694
+
+#define mmTPC0_CFG_KERNEL_SRF_2 0xE06698
+
+#define mmTPC0_CFG_KERNEL_SRF_3 0xE0669C
+
+#define mmTPC0_CFG_KERNEL_SRF_4 0xE066A0
+
+#define mmTPC0_CFG_KERNEL_SRF_5 0xE066A4
+
+#define mmTPC0_CFG_KERNEL_SRF_6 0xE066A8
+
+#define mmTPC0_CFG_KERNEL_SRF_7 0xE066AC
+
+#define mmTPC0_CFG_KERNEL_SRF_8 0xE066B0
+
+#define mmTPC0_CFG_KERNEL_SRF_9 0xE066B4
+
+#define mmTPC0_CFG_KERNEL_SRF_10 0xE066B8
+
+#define mmTPC0_CFG_KERNEL_SRF_11 0xE066BC
+
+#define mmTPC0_CFG_KERNEL_SRF_12 0xE066C0
+
+#define mmTPC0_CFG_KERNEL_SRF_13 0xE066C4
+
+#define mmTPC0_CFG_KERNEL_SRF_14 0xE066C8
+
+#define mmTPC0_CFG_KERNEL_SRF_15 0xE066CC
+
+#define mmTPC0_CFG_KERNEL_SRF_16 0xE066D0
+
+#define mmTPC0_CFG_KERNEL_SRF_17 0xE066D4
+
+#define mmTPC0_CFG_KERNEL_SRF_18 0xE066D8
+
+#define mmTPC0_CFG_KERNEL_SRF_19 0xE066DC
+
+#define mmTPC0_CFG_KERNEL_SRF_20 0xE066E0
+
+#define mmTPC0_CFG_KERNEL_SRF_21 0xE066E4
+
+#define mmTPC0_CFG_KERNEL_SRF_22 0xE066E8
+
+#define mmTPC0_CFG_KERNEL_SRF_23 0xE066EC
+
+#define mmTPC0_CFG_KERNEL_SRF_24 0xE066F0
+
+#define mmTPC0_CFG_KERNEL_SRF_25 0xE066F4
+
+#define mmTPC0_CFG_KERNEL_SRF_26 0xE066F8
+
+#define mmTPC0_CFG_KERNEL_SRF_27 0xE066FC
+
+#define mmTPC0_CFG_KERNEL_SRF_28 0xE06700
+
+#define mmTPC0_CFG_KERNEL_SRF_29 0xE06704
+
+#define mmTPC0_CFG_KERNEL_SRF_30 0xE06708
+
+#define mmTPC0_CFG_KERNEL_SRF_31 0xE0670C
+
+#define mmTPC0_CFG_KERNEL_KERNEL_CONFIG 0xE06710
+
+#define mmTPC0_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xE06714
+
+#define mmTPC0_CFG_RESERVED_DESC_END 0xE06738
+
+#define mmTPC0_CFG_ROUND_CSR 0xE067FC
+
+#define mmTPC0_CFG_TBUF_BASE_ADDR_LOW 0xE06800
+
+#define mmTPC0_CFG_TBUF_BASE_ADDR_HIGH 0xE06804
+
+#define mmTPC0_CFG_SEMAPHORE 0xE06808
+
+#define mmTPC0_CFG_VFLAGS 0xE0680C
+
+#define mmTPC0_CFG_SFLAGS 0xE06810
+
+#define mmTPC0_CFG_LFSR_POLYNOM 0xE06818
+
+#define mmTPC0_CFG_STATUS 0xE0681C
+
+#define mmTPC0_CFG_CFG_BASE_ADDRESS_HIGH 0xE06820
+
+#define mmTPC0_CFG_CFG_SUBTRACT_VALUE 0xE06824
+
+#define mmTPC0_CFG_SM_BASE_ADDRESS_LOW 0xE06828
+
+#define mmTPC0_CFG_SM_BASE_ADDRESS_HIGH 0xE0682C
+
+#define mmTPC0_CFG_TPC_CMD 0xE06830
+
+#define mmTPC0_CFG_TPC_EXECUTE 0xE06838
+
+#define mmTPC0_CFG_TPC_STALL 0xE0683C
+
+#define mmTPC0_CFG_ICACHE_BASE_ADDERESS_LOW 0xE06840
+
+#define mmTPC0_CFG_ICACHE_BASE_ADDERESS_HIGH 0xE06844
+
+#define mmTPC0_CFG_MSS_CONFIG 0xE06854
+
+#define mmTPC0_CFG_TPC_INTR_CAUSE 0xE06858
+
+#define mmTPC0_CFG_TPC_INTR_MASK 0xE0685C
+
+#define mmTPC0_CFG_TSB_CONFIG 0xE06860
+
+#define mmTPC0_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xE06A00
+
+#define mmTPC0_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xE06A04
+
+#define mmTPC0_CFG_QM_TENSOR_0_PADDING_VALUE 0xE06A08
+
+#define mmTPC0_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xE06A0C
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_0_SIZE 0xE06A10
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xE06A14
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xE06A18
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_1_SIZE 0xE06A1C
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xE06A20
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xE06A24
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_2_SIZE 0xE06A28
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xE06A2C
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xE06A30
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_3_SIZE 0xE06A34
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xE06A38
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xE06A3C
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_4_SIZE 0xE06A40
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xE06A44
+
+#define mmTPC0_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xE06A48
+
+#define mmTPC0_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xE06A4C
+
+#define mmTPC0_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xE06A50
+
+#define mmTPC0_CFG_QM_TENSOR_1_PADDING_VALUE 0xE06A54
+
+#define mmTPC0_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xE06A58
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_0_SIZE 0xE06A5C
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xE06A60
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xE06A64
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_1_SIZE 0xE06A68
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xE06A6C
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xE06A70
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_2_SIZE 0xE06A74
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xE06A78
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xE06A7C
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_3_SIZE 0xE06A80
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xE06A84
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xE06A88
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_4_SIZE 0xE06A8C
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xE06A90
+
+#define mmTPC0_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xE06A94
+
+#define mmTPC0_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xE06A98
+
+#define mmTPC0_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xE06A9C
+
+#define mmTPC0_CFG_QM_TENSOR_2_PADDING_VALUE 0xE06AA0
+
+#define mmTPC0_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xE06AA4
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_0_SIZE 0xE06AA8
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xE06AAC
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xE06AB0
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_1_SIZE 0xE06AB4
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xE06AB8
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xE06ABC
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_2_SIZE 0xE06AC0
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xE06AC4
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xE06AC8
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_3_SIZE 0xE06ACC
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xE06AD0
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xE06AD4
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_4_SIZE 0xE06AD8
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xE06ADC
+
+#define mmTPC0_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xE06AE0
+
+#define mmTPC0_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xE06AE4
+
+#define mmTPC0_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xE06AE8
+
+#define mmTPC0_CFG_QM_TENSOR_3_PADDING_VALUE 0xE06AEC
+
+#define mmTPC0_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xE06AF0
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_0_SIZE 0xE06AF4
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xE06AF8
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xE06AFC
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_1_SIZE 0xE06B00
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xE06B04
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xE06B08
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_2_SIZE 0xE06B0C
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xE06B10
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xE06B14
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_3_SIZE 0xE06B18
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xE06B1C
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xE06B20
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_4_SIZE 0xE06B24
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xE06B28
+
+#define mmTPC0_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xE06B2C
+
+#define mmTPC0_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xE06B30
+
+#define mmTPC0_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xE06B34
+
+#define mmTPC0_CFG_QM_TENSOR_4_PADDING_VALUE 0xE06B38
+
+#define mmTPC0_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xE06B3C
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_0_SIZE 0xE06B40
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xE06B44
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xE06B48
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_1_SIZE 0xE06B4C
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xE06B50
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xE06B54
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_2_SIZE 0xE06B58
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xE06B5C
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xE06B60
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_3_SIZE 0xE06B64
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xE06B68
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xE06B6C
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_4_SIZE 0xE06B70
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xE06B74
+
+#define mmTPC0_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xE06B78
+
+#define mmTPC0_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xE06B7C
+
+#define mmTPC0_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xE06B80
+
+#define mmTPC0_CFG_QM_TENSOR_5_PADDING_VALUE 0xE06B84
+
+#define mmTPC0_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xE06B88
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_0_SIZE 0xE06B8C
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xE06B90
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xE06B94
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_1_SIZE 0xE06B98
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xE06B9C
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xE06BA0
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_2_SIZE 0xE06BA4
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xE06BA8
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xE06BAC
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_3_SIZE 0xE06BB0
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xE06BB4
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xE06BB8
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_4_SIZE 0xE06BBC
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xE06BC0
+
+#define mmTPC0_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xE06BC4
+
+#define mmTPC0_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xE06BC8
+
+#define mmTPC0_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xE06BCC
+
+#define mmTPC0_CFG_QM_TENSOR_6_PADDING_VALUE 0xE06BD0
+
+#define mmTPC0_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xE06BD4
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_0_SIZE 0xE06BD8
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xE06BDC
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xE06BE0
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_1_SIZE 0xE06BE4
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xE06BE8
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xE06BEC
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_2_SIZE 0xE06BF0
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xE06BF4
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xE06BF8
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_3_SIZE 0xE06BFC
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xE06C00
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xE06C04
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_4_SIZE 0xE06C08
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xE06C0C
+
+#define mmTPC0_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xE06C10
+
+#define mmTPC0_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xE06C14
+
+#define mmTPC0_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xE06C18
+
+#define mmTPC0_CFG_QM_TENSOR_7_PADDING_VALUE 0xE06C1C
+
+#define mmTPC0_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xE06C20
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_0_SIZE 0xE06C24
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xE06C28
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xE06C2C
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_1_SIZE 0xE06C30
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xE06C34
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xE06C38
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_2_SIZE 0xE06C3C
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xE06C40
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xE06C44
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_3_SIZE 0xE06C48
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xE06C4C
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xE06C50
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_4_SIZE 0xE06C54
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xE06C58
+
+#define mmTPC0_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xE06C5C
+
+#define mmTPC0_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xE06C60
+
+#define mmTPC0_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xE06C64
+
+#define mmTPC0_CFG_QM_TID_BASE_DIM_0 0xE06C68
+
+#define mmTPC0_CFG_QM_TID_SIZE_DIM_0 0xE06C6C
+
+#define mmTPC0_CFG_QM_TID_BASE_DIM_1 0xE06C70
+
+#define mmTPC0_CFG_QM_TID_SIZE_DIM_1 0xE06C74
+
+#define mmTPC0_CFG_QM_TID_BASE_DIM_2 0xE06C78
+
+#define mmTPC0_CFG_QM_TID_SIZE_DIM_2 0xE06C7C
+
+#define mmTPC0_CFG_QM_TID_BASE_DIM_3 0xE06C80
+
+#define mmTPC0_CFG_QM_TID_SIZE_DIM_3 0xE06C84
+
+#define mmTPC0_CFG_QM_TID_BASE_DIM_4 0xE06C88
+
+#define mmTPC0_CFG_QM_TID_SIZE_DIM_4 0xE06C8C
+
+#define mmTPC0_CFG_QM_SRF_0 0xE06C90
+
+#define mmTPC0_CFG_QM_SRF_1 0xE06C94
+
+#define mmTPC0_CFG_QM_SRF_2 0xE06C98
+
+#define mmTPC0_CFG_QM_SRF_3 0xE06C9C
+
+#define mmTPC0_CFG_QM_SRF_4 0xE06CA0
+
+#define mmTPC0_CFG_QM_SRF_5 0xE06CA4
+
+#define mmTPC0_CFG_QM_SRF_6 0xE06CA8
+
+#define mmTPC0_CFG_QM_SRF_7 0xE06CAC
+
+#define mmTPC0_CFG_QM_SRF_8 0xE06CB0
+
+#define mmTPC0_CFG_QM_SRF_9 0xE06CB4
+
+#define mmTPC0_CFG_QM_SRF_10 0xE06CB8
+
+#define mmTPC0_CFG_QM_SRF_11 0xE06CBC
+
+#define mmTPC0_CFG_QM_SRF_12 0xE06CC0
+
+#define mmTPC0_CFG_QM_SRF_13 0xE06CC4
+
+#define mmTPC0_CFG_QM_SRF_14 0xE06CC8
+
+#define mmTPC0_CFG_QM_SRF_15 0xE06CCC
+
+#define mmTPC0_CFG_QM_SRF_16 0xE06CD0
+
+#define mmTPC0_CFG_QM_SRF_17 0xE06CD4
+
+#define mmTPC0_CFG_QM_SRF_18 0xE06CD8
+
+#define mmTPC0_CFG_QM_SRF_19 0xE06CDC
+
+#define mmTPC0_CFG_QM_SRF_20 0xE06CE0
+
+#define mmTPC0_CFG_QM_SRF_21 0xE06CE4
+
+#define mmTPC0_CFG_QM_SRF_22 0xE06CE8
+
+#define mmTPC0_CFG_QM_SRF_23 0xE06CEC
+
+#define mmTPC0_CFG_QM_SRF_24 0xE06CF0
+
+#define mmTPC0_CFG_QM_SRF_25 0xE06CF4
+
+#define mmTPC0_CFG_QM_SRF_26 0xE06CF8
+
+#define mmTPC0_CFG_QM_SRF_27 0xE06CFC
+
+#define mmTPC0_CFG_QM_SRF_28 0xE06D00
+
+#define mmTPC0_CFG_QM_SRF_29 0xE06D04
+
+#define mmTPC0_CFG_QM_SRF_30 0xE06D08
+
+#define mmTPC0_CFG_QM_SRF_31 0xE06D0C
+
+#define mmTPC0_CFG_QM_KERNEL_CONFIG 0xE06D10
+
+#define mmTPC0_CFG_QM_SYNC_OBJECT_MESSAGE 0xE06D14
+
+#define mmTPC0_CFG_ARUSER 0xE06D18
+
+#define mmTPC0_CFG_AWUSER 0xE06D1C
+
+#define mmTPC0_CFG_FUNC_MBIST_CNTRL 0xE06E00
+
+#define mmTPC0_CFG_FUNC_MBIST_PAT 0xE06E04
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_0 0xE06E08
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_1 0xE06E0C
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_2 0xE06E10
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_3 0xE06E14
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_4 0xE06E18
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_5 0xE06E1C
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_6 0xE06E20
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_7 0xE06E24
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_8 0xE06E28
+
+#define mmTPC0_CFG_FUNC_MBIST_MEM_9 0xE06E2C
+
+#endif /* ASIC_REG_TPC0_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h
new file mode 100644
index 000000000000..9aa2d8b53207
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_masks.h
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_CMDQ_MASKS_H_
+#define ASIC_REG_TPC0_CMDQ_MASKS_H_
+
+/*
+ *****************************************
+ * TPC0_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+/* TPC0_CMDQ_GLBL_CFG0 */
+#define TPC0_CMDQ_GLBL_CFG0_PQF_EN_SHIFT 0
+#define TPC0_CMDQ_GLBL_CFG0_PQF_EN_MASK 0x1
+#define TPC0_CMDQ_GLBL_CFG0_CQF_EN_SHIFT 1
+#define TPC0_CMDQ_GLBL_CFG0_CQF_EN_MASK 0x2
+#define TPC0_CMDQ_GLBL_CFG0_CP_EN_SHIFT 2
+#define TPC0_CMDQ_GLBL_CFG0_CP_EN_MASK 0x4
+#define TPC0_CMDQ_GLBL_CFG0_DMA_EN_SHIFT 3
+#define TPC0_CMDQ_GLBL_CFG0_DMA_EN_MASK 0x8
+
+/* TPC0_CMDQ_GLBL_CFG1 */
+#define TPC0_CMDQ_GLBL_CFG1_PQF_STOP_SHIFT 0
+#define TPC0_CMDQ_GLBL_CFG1_PQF_STOP_MASK 0x1
+#define TPC0_CMDQ_GLBL_CFG1_CQF_STOP_SHIFT 1
+#define TPC0_CMDQ_GLBL_CFG1_CQF_STOP_MASK 0x2
+#define TPC0_CMDQ_GLBL_CFG1_CP_STOP_SHIFT 2
+#define TPC0_CMDQ_GLBL_CFG1_CP_STOP_MASK 0x4
+#define TPC0_CMDQ_GLBL_CFG1_DMA_STOP_SHIFT 3
+#define TPC0_CMDQ_GLBL_CFG1_DMA_STOP_MASK 0x8
+#define TPC0_CMDQ_GLBL_CFG1_PQF_FLUSH_SHIFT 8
+#define TPC0_CMDQ_GLBL_CFG1_PQF_FLUSH_MASK 0x100
+#define TPC0_CMDQ_GLBL_CFG1_CQF_FLUSH_SHIFT 9
+#define TPC0_CMDQ_GLBL_CFG1_CQF_FLUSH_MASK 0x200
+#define TPC0_CMDQ_GLBL_CFG1_CP_FLUSH_SHIFT 10
+#define TPC0_CMDQ_GLBL_CFG1_CP_FLUSH_MASK 0x400
+#define TPC0_CMDQ_GLBL_CFG1_DMA_FLUSH_SHIFT 11
+#define TPC0_CMDQ_GLBL_CFG1_DMA_FLUSH_MASK 0x800
+
+/* TPC0_CMDQ_GLBL_PROT */
+#define TPC0_CMDQ_GLBL_PROT_PQF_PROT_SHIFT 0
+#define TPC0_CMDQ_GLBL_PROT_PQF_PROT_MASK 0x1
+#define TPC0_CMDQ_GLBL_PROT_CQF_PROT_SHIFT 1
+#define TPC0_CMDQ_GLBL_PROT_CQF_PROT_MASK 0x2
+#define TPC0_CMDQ_GLBL_PROT_CP_PROT_SHIFT 2
+#define TPC0_CMDQ_GLBL_PROT_CP_PROT_MASK 0x4
+#define TPC0_CMDQ_GLBL_PROT_DMA_PROT_SHIFT 3
+#define TPC0_CMDQ_GLBL_PROT_DMA_PROT_MASK 0x8
+#define TPC0_CMDQ_GLBL_PROT_PQF_ERR_PROT_SHIFT 4
+#define TPC0_CMDQ_GLBL_PROT_PQF_ERR_PROT_MASK 0x10
+#define TPC0_CMDQ_GLBL_PROT_CQF_ERR_PROT_SHIFT 5
+#define TPC0_CMDQ_GLBL_PROT_CQF_ERR_PROT_MASK 0x20
+#define TPC0_CMDQ_GLBL_PROT_CP_ERR_PROT_SHIFT 6
+#define TPC0_CMDQ_GLBL_PROT_CP_ERR_PROT_MASK 0x40
+#define TPC0_CMDQ_GLBL_PROT_DMA_ERR_PROT_SHIFT 7
+#define TPC0_CMDQ_GLBL_PROT_DMA_ERR_PROT_MASK 0x80
+
+/* TPC0_CMDQ_GLBL_ERR_CFG */
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_ERR_INT_EN_SHIFT 0
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_ERR_INT_EN_MASK 0x1
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT 1
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK 0x2
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT 2
+#define TPC0_CMDQ_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK 0x4
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_ERR_INT_EN_SHIFT 3
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_ERR_INT_EN_MASK 0x8
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT 4
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_ERR_MSG_EN_MASK 0x10
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT 5
+#define TPC0_CMDQ_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK 0x20
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_ERR_INT_EN_SHIFT 6
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_ERR_INT_EN_MASK 0x40
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT 7
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_ERR_MSG_EN_MASK 0x80
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT 8
+#define TPC0_CMDQ_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK 0x100
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_ERR_INT_EN_SHIFT 9
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_ERR_INT_EN_MASK 0x200
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT 10
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_ERR_MSG_EN_MASK 0x400
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT 11
+#define TPC0_CMDQ_GLBL_ERR_CFG_DMA_STOP_ON_ERR_MASK 0x800
+
+/* TPC0_CMDQ_GLBL_ERR_ADDR_LO */
+#define TPC0_CMDQ_GLBL_ERR_ADDR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_GLBL_ERR_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_GLBL_ERR_ADDR_HI */
+#define TPC0_CMDQ_GLBL_ERR_ADDR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_GLBL_ERR_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_GLBL_ERR_WDATA */
+#define TPC0_CMDQ_GLBL_ERR_WDATA_VAL_SHIFT 0
+#define TPC0_CMDQ_GLBL_ERR_WDATA_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_GLBL_SECURE_PROPS */
+#define TPC0_CMDQ_GLBL_SECURE_PROPS_ASID_SHIFT 0
+#define TPC0_CMDQ_GLBL_SECURE_PROPS_ASID_MASK 0x3FF
+#define TPC0_CMDQ_GLBL_SECURE_PROPS_MMBP_SHIFT 10
+#define TPC0_CMDQ_GLBL_SECURE_PROPS_MMBP_MASK 0x400
+
+/* TPC0_CMDQ_GLBL_NON_SECURE_PROPS */
+#define TPC0_CMDQ_GLBL_NON_SECURE_PROPS_ASID_SHIFT 0
+#define TPC0_CMDQ_GLBL_NON_SECURE_PROPS_ASID_MASK 0x3FF
+#define TPC0_CMDQ_GLBL_NON_SECURE_PROPS_MMBP_SHIFT 10
+#define TPC0_CMDQ_GLBL_NON_SECURE_PROPS_MMBP_MASK 0x400
+
+/* TPC0_CMDQ_GLBL_STS0 */
+#define TPC0_CMDQ_GLBL_STS0_PQF_IDLE_SHIFT 0
+#define TPC0_CMDQ_GLBL_STS0_PQF_IDLE_MASK 0x1
+#define TPC0_CMDQ_GLBL_STS0_CQF_IDLE_SHIFT 1
+#define TPC0_CMDQ_GLBL_STS0_CQF_IDLE_MASK 0x2
+#define TPC0_CMDQ_GLBL_STS0_CP_IDLE_SHIFT 2
+#define TPC0_CMDQ_GLBL_STS0_CP_IDLE_MASK 0x4
+#define TPC0_CMDQ_GLBL_STS0_DMA_IDLE_SHIFT 3
+#define TPC0_CMDQ_GLBL_STS0_DMA_IDLE_MASK 0x8
+#define TPC0_CMDQ_GLBL_STS0_PQF_IS_STOP_SHIFT 4
+#define TPC0_CMDQ_GLBL_STS0_PQF_IS_STOP_MASK 0x10
+#define TPC0_CMDQ_GLBL_STS0_CQF_IS_STOP_SHIFT 5
+#define TPC0_CMDQ_GLBL_STS0_CQF_IS_STOP_MASK 0x20
+#define TPC0_CMDQ_GLBL_STS0_CP_IS_STOP_SHIFT 6
+#define TPC0_CMDQ_GLBL_STS0_CP_IS_STOP_MASK 0x40
+#define TPC0_CMDQ_GLBL_STS0_DMA_IS_STOP_SHIFT 7
+#define TPC0_CMDQ_GLBL_STS0_DMA_IS_STOP_MASK 0x80
+
+/* TPC0_CMDQ_GLBL_STS1 */
+#define TPC0_CMDQ_GLBL_STS1_PQF_RD_ERR_SHIFT 0
+#define TPC0_CMDQ_GLBL_STS1_PQF_RD_ERR_MASK 0x1
+#define TPC0_CMDQ_GLBL_STS1_CQF_RD_ERR_SHIFT 1
+#define TPC0_CMDQ_GLBL_STS1_CQF_RD_ERR_MASK 0x2
+#define TPC0_CMDQ_GLBL_STS1_CP_RD_ERR_SHIFT 2
+#define TPC0_CMDQ_GLBL_STS1_CP_RD_ERR_MASK 0x4
+#define TPC0_CMDQ_GLBL_STS1_CP_UNDEF_CMD_ERR_SHIFT 3
+#define TPC0_CMDQ_GLBL_STS1_CP_UNDEF_CMD_ERR_MASK 0x8
+#define TPC0_CMDQ_GLBL_STS1_CP_STOP_OP_SHIFT 4
+#define TPC0_CMDQ_GLBL_STS1_CP_STOP_OP_MASK 0x10
+#define TPC0_CMDQ_GLBL_STS1_CP_MSG_WR_ERR_SHIFT 5
+#define TPC0_CMDQ_GLBL_STS1_CP_MSG_WR_ERR_MASK 0x20
+#define TPC0_CMDQ_GLBL_STS1_DMA_RD_ERR_SHIFT 8
+#define TPC0_CMDQ_GLBL_STS1_DMA_RD_ERR_MASK 0x100
+#define TPC0_CMDQ_GLBL_STS1_DMA_WR_ERR_SHIFT 9
+#define TPC0_CMDQ_GLBL_STS1_DMA_WR_ERR_MASK 0x200
+#define TPC0_CMDQ_GLBL_STS1_DMA_RD_MSG_ERR_SHIFT 10
+#define TPC0_CMDQ_GLBL_STS1_DMA_RD_MSG_ERR_MASK 0x400
+#define TPC0_CMDQ_GLBL_STS1_DMA_WR_MSG_ERR_SHIFT 11
+#define TPC0_CMDQ_GLBL_STS1_DMA_WR_MSG_ERR_MASK 0x800
+
+/* TPC0_CMDQ_CQ_CFG0 */
+#define TPC0_CMDQ_CQ_CFG0_RESERVED_SHIFT 0
+#define TPC0_CMDQ_CQ_CFG0_RESERVED_MASK 0x1
+
+/* TPC0_CMDQ_CQ_CFG1 */
+#define TPC0_CMDQ_CQ_CFG1_CREDIT_LIM_SHIFT 0
+#define TPC0_CMDQ_CQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define TPC0_CMDQ_CQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define TPC0_CMDQ_CQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* TPC0_CMDQ_CQ_ARUSER */
+#define TPC0_CMDQ_CQ_ARUSER_NOSNOOP_SHIFT 0
+#define TPC0_CMDQ_CQ_ARUSER_NOSNOOP_MASK 0x1
+#define TPC0_CMDQ_CQ_ARUSER_WORD_SHIFT 1
+#define TPC0_CMDQ_CQ_ARUSER_WORD_MASK 0x2
+
+/* TPC0_CMDQ_CQ_PTR_LO */
+#define TPC0_CMDQ_CQ_PTR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_PTR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_PTR_HI */
+#define TPC0_CMDQ_CQ_PTR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_PTR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_TSIZE */
+#define TPC0_CMDQ_CQ_TSIZE_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_TSIZE_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_CTL */
+#define TPC0_CMDQ_CQ_CTL_RPT_SHIFT 0
+#define TPC0_CMDQ_CQ_CTL_RPT_MASK 0xFFFF
+#define TPC0_CMDQ_CQ_CTL_CTL_SHIFT 16
+#define TPC0_CMDQ_CQ_CTL_CTL_MASK 0xFFFF0000
+
+/* TPC0_CMDQ_CQ_PTR_LO_STS */
+#define TPC0_CMDQ_CQ_PTR_LO_STS_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_PTR_LO_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_PTR_HI_STS */
+#define TPC0_CMDQ_CQ_PTR_HI_STS_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_PTR_HI_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_TSIZE_STS */
+#define TPC0_CMDQ_CQ_TSIZE_STS_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_TSIZE_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_CTL_STS */
+#define TPC0_CMDQ_CQ_CTL_STS_RPT_SHIFT 0
+#define TPC0_CMDQ_CQ_CTL_STS_RPT_MASK 0xFFFF
+#define TPC0_CMDQ_CQ_CTL_STS_CTL_SHIFT 16
+#define TPC0_CMDQ_CQ_CTL_STS_CTL_MASK 0xFFFF0000
+
+/* TPC0_CMDQ_CQ_STS0 */
+#define TPC0_CMDQ_CQ_STS0_CQ_CREDIT_CNT_SHIFT 0
+#define TPC0_CMDQ_CQ_STS0_CQ_CREDIT_CNT_MASK 0xFFFF
+#define TPC0_CMDQ_CQ_STS0_CQ_FREE_CNT_SHIFT 16
+#define TPC0_CMDQ_CQ_STS0_CQ_FREE_CNT_MASK 0xFFFF0000
+
+/* TPC0_CMDQ_CQ_STS1 */
+#define TPC0_CMDQ_CQ_STS1_CQ_INFLIGHT_CNT_SHIFT 0
+#define TPC0_CMDQ_CQ_STS1_CQ_INFLIGHT_CNT_MASK 0xFFFF
+#define TPC0_CMDQ_CQ_STS1_CQ_BUF_EMPTY_SHIFT 30
+#define TPC0_CMDQ_CQ_STS1_CQ_BUF_EMPTY_MASK 0x40000000
+#define TPC0_CMDQ_CQ_STS1_CQ_BUSY_SHIFT 31
+#define TPC0_CMDQ_CQ_STS1_CQ_BUSY_MASK 0x80000000
+
+/* TPC0_CMDQ_CQ_RD_RATE_LIM_EN */
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* TPC0_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN */
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* TPC0_CMDQ_CQ_RD_RATE_LIM_SAT */
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* TPC0_CMDQ_CQ_RD_RATE_LIM_TOUT */
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* TPC0_CMDQ_CQ_IFIFO_CNT */
+#define TPC0_CMDQ_CQ_IFIFO_CNT_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_IFIFO_CNT_VAL_MASK 0x3
+
+/* TPC0_CMDQ_CP_MSG_BASE0_ADDR_LO */
+#define TPC0_CMDQ_CP_MSG_BASE0_ADDR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE0_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE0_ADDR_HI */
+#define TPC0_CMDQ_CP_MSG_BASE0_ADDR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE0_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE1_ADDR_LO */
+#define TPC0_CMDQ_CP_MSG_BASE1_ADDR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE1_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE1_ADDR_HI */
+#define TPC0_CMDQ_CP_MSG_BASE1_ADDR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE1_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE2_ADDR_LO */
+#define TPC0_CMDQ_CP_MSG_BASE2_ADDR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE2_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE2_ADDR_HI */
+#define TPC0_CMDQ_CP_MSG_BASE2_ADDR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE2_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE3_ADDR_LO */
+#define TPC0_CMDQ_CP_MSG_BASE3_ADDR_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE3_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_MSG_BASE3_ADDR_HI */
+#define TPC0_CMDQ_CP_MSG_BASE3_ADDR_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_MSG_BASE3_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_TSIZE_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_TSIZE_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_TSIZE_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_LDMA_COMMIT_OFFSET */
+#define TPC0_CMDQ_CP_LDMA_COMMIT_OFFSET_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_LDMA_COMMIT_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_FENCE0_RDATA */
+#define TPC0_CMDQ_CP_FENCE0_RDATA_INC_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE0_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_CMDQ_CP_FENCE1_RDATA */
+#define TPC0_CMDQ_CP_FENCE1_RDATA_INC_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE1_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_CMDQ_CP_FENCE2_RDATA */
+#define TPC0_CMDQ_CP_FENCE2_RDATA_INC_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE2_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_CMDQ_CP_FENCE3_RDATA */
+#define TPC0_CMDQ_CP_FENCE3_RDATA_INC_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE3_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_CMDQ_CP_FENCE0_CNT */
+#define TPC0_CMDQ_CP_FENCE0_CNT_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE0_CNT_VAL_MASK 0xFF
+
+/* TPC0_CMDQ_CP_FENCE1_CNT */
+#define TPC0_CMDQ_CP_FENCE1_CNT_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE1_CNT_VAL_MASK 0xFF
+
+/* TPC0_CMDQ_CP_FENCE2_CNT */
+#define TPC0_CMDQ_CP_FENCE2_CNT_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE2_CNT_VAL_MASK 0xFF
+
+/* TPC0_CMDQ_CP_FENCE3_CNT */
+#define TPC0_CMDQ_CP_FENCE3_CNT_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_FENCE3_CNT_VAL_MASK 0xFF
+
+/* TPC0_CMDQ_CP_STS */
+#define TPC0_CMDQ_CP_STS_MSG_INFLIGHT_CNT_SHIFT 0
+#define TPC0_CMDQ_CP_STS_MSG_INFLIGHT_CNT_MASK 0xFFFF
+#define TPC0_CMDQ_CP_STS_ERDY_SHIFT 16
+#define TPC0_CMDQ_CP_STS_ERDY_MASK 0x10000
+#define TPC0_CMDQ_CP_STS_RRDY_SHIFT 17
+#define TPC0_CMDQ_CP_STS_RRDY_MASK 0x20000
+#define TPC0_CMDQ_CP_STS_MRDY_SHIFT 18
+#define TPC0_CMDQ_CP_STS_MRDY_MASK 0x40000
+#define TPC0_CMDQ_CP_STS_SW_STOP_SHIFT 19
+#define TPC0_CMDQ_CP_STS_SW_STOP_MASK 0x80000
+#define TPC0_CMDQ_CP_STS_FENCE_ID_SHIFT 20
+#define TPC0_CMDQ_CP_STS_FENCE_ID_MASK 0x300000
+#define TPC0_CMDQ_CP_STS_FENCE_IN_PROGRESS_SHIFT 22
+#define TPC0_CMDQ_CP_STS_FENCE_IN_PROGRESS_MASK 0x400000
+
+/* TPC0_CMDQ_CP_CURRENT_INST_LO */
+#define TPC0_CMDQ_CP_CURRENT_INST_LO_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_CURRENT_INST_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_CURRENT_INST_HI */
+#define TPC0_CMDQ_CP_CURRENT_INST_HI_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_CURRENT_INST_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CP_BARRIER_CFG */
+#define TPC0_CMDQ_CP_BARRIER_CFG_EBGUARD_SHIFT 0
+#define TPC0_CMDQ_CP_BARRIER_CFG_EBGUARD_MASK 0xFFF
+
+/* TPC0_CMDQ_CP_DBG_0 */
+#define TPC0_CMDQ_CP_DBG_0_VAL_SHIFT 0
+#define TPC0_CMDQ_CP_DBG_0_VAL_MASK 0xFF
+
+/* TPC0_CMDQ_CQ_BUF_ADDR */
+#define TPC0_CMDQ_CQ_BUF_ADDR_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_CMDQ_CQ_BUF_RDATA */
+#define TPC0_CMDQ_CQ_BUF_RDATA_VAL_SHIFT 0
+#define TPC0_CMDQ_CQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_TPC0_CMDQ_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h
new file mode 100644
index 000000000000..3572752ba66e
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_CMDQ_REGS_H_
+#define ASIC_REG_TPC0_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC0_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC0_CMDQ_GLBL_CFG0 0xE09000
+
+#define mmTPC0_CMDQ_GLBL_CFG1 0xE09004
+
+#define mmTPC0_CMDQ_GLBL_PROT 0xE09008
+
+#define mmTPC0_CMDQ_GLBL_ERR_CFG 0xE0900C
+
+#define mmTPC0_CMDQ_GLBL_ERR_ADDR_LO 0xE09010
+
+#define mmTPC0_CMDQ_GLBL_ERR_ADDR_HI 0xE09014
+
+#define mmTPC0_CMDQ_GLBL_ERR_WDATA 0xE09018
+
+#define mmTPC0_CMDQ_GLBL_SECURE_PROPS 0xE0901C
+
+#define mmTPC0_CMDQ_GLBL_NON_SECURE_PROPS 0xE09020
+
+#define mmTPC0_CMDQ_GLBL_STS0 0xE09024
+
+#define mmTPC0_CMDQ_GLBL_STS1 0xE09028
+
+#define mmTPC0_CMDQ_CQ_CFG0 0xE090B0
+
+#define mmTPC0_CMDQ_CQ_CFG1 0xE090B4
+
+#define mmTPC0_CMDQ_CQ_ARUSER 0xE090B8
+
+#define mmTPC0_CMDQ_CQ_PTR_LO 0xE090C0
+
+#define mmTPC0_CMDQ_CQ_PTR_HI 0xE090C4
+
+#define mmTPC0_CMDQ_CQ_TSIZE 0xE090C8
+
+#define mmTPC0_CMDQ_CQ_CTL 0xE090CC
+
+#define mmTPC0_CMDQ_CQ_PTR_LO_STS 0xE090D4
+
+#define mmTPC0_CMDQ_CQ_PTR_HI_STS 0xE090D8
+
+#define mmTPC0_CMDQ_CQ_TSIZE_STS 0xE090DC
+
+#define mmTPC0_CMDQ_CQ_CTL_STS 0xE090E0
+
+#define mmTPC0_CMDQ_CQ_STS0 0xE090E4
+
+#define mmTPC0_CMDQ_CQ_STS1 0xE090E8
+
+#define mmTPC0_CMDQ_CQ_RD_RATE_LIM_EN 0xE090F0
+
+#define mmTPC0_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xE090F4
+
+#define mmTPC0_CMDQ_CQ_RD_RATE_LIM_SAT 0xE090F8
+
+#define mmTPC0_CMDQ_CQ_RD_RATE_LIM_TOUT 0xE090FC
+
+#define mmTPC0_CMDQ_CQ_IFIFO_CNT 0xE09108
+
+#define mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_LO 0xE09120
+
+#define mmTPC0_CMDQ_CP_MSG_BASE0_ADDR_HI 0xE09124
+
+#define mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_LO 0xE09128
+
+#define mmTPC0_CMDQ_CP_MSG_BASE1_ADDR_HI 0xE0912C
+
+#define mmTPC0_CMDQ_CP_MSG_BASE2_ADDR_LO 0xE09130
+
+#define mmTPC0_CMDQ_CP_MSG_BASE2_ADDR_HI 0xE09134
+
+#define mmTPC0_CMDQ_CP_MSG_BASE3_ADDR_LO 0xE09138
+
+#define mmTPC0_CMDQ_CP_MSG_BASE3_ADDR_HI 0xE0913C
+
+#define mmTPC0_CMDQ_CP_LDMA_TSIZE_OFFSET 0xE09140
+
+#define mmTPC0_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xE09144
+
+#define mmTPC0_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xE09148
+
+#define mmTPC0_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xE0914C
+
+#define mmTPC0_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xE09150
+
+#define mmTPC0_CMDQ_CP_LDMA_COMMIT_OFFSET 0xE09154
+
+#define mmTPC0_CMDQ_CP_FENCE0_RDATA 0xE09158
+
+#define mmTPC0_CMDQ_CP_FENCE1_RDATA 0xE0915C
+
+#define mmTPC0_CMDQ_CP_FENCE2_RDATA 0xE09160
+
+#define mmTPC0_CMDQ_CP_FENCE3_RDATA 0xE09164
+
+#define mmTPC0_CMDQ_CP_FENCE0_CNT 0xE09168
+
+#define mmTPC0_CMDQ_CP_FENCE1_CNT 0xE0916C
+
+#define mmTPC0_CMDQ_CP_FENCE2_CNT 0xE09170
+
+#define mmTPC0_CMDQ_CP_FENCE3_CNT 0xE09174
+
+#define mmTPC0_CMDQ_CP_STS 0xE09178
+
+#define mmTPC0_CMDQ_CP_CURRENT_INST_LO 0xE0917C
+
+#define mmTPC0_CMDQ_CP_CURRENT_INST_HI 0xE09180
+
+#define mmTPC0_CMDQ_CP_BARRIER_CFG 0xE09184
+
+#define mmTPC0_CMDQ_CP_DBG_0 0xE09188
+
+#define mmTPC0_CMDQ_CQ_BUF_ADDR 0xE09308
+
+#define mmTPC0_CMDQ_CQ_BUF_RDATA 0xE0930C
+
+#endif /* ASIC_REG_TPC0_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h
new file mode 100644
index 000000000000..ed866d93c440
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_masks.h
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_EML_CFG_MASKS_H_
+#define ASIC_REG_TPC0_EML_CFG_MASKS_H_
+
+/*
+ *****************************************
+ * TPC0_EML_CFG (Prototype: TPC_EML_CFG)
+ *****************************************
+ */
+
+/* TPC0_EML_CFG_DBG_CNT */
+#define TPC0_EML_CFG_DBG_CNT_DBG_ENTER_SHIFT 0
+#define TPC0_EML_CFG_DBG_CNT_DBG_ENTER_MASK 0x1
+#define TPC0_EML_CFG_DBG_CNT_DBG_EN_SHIFT 1
+#define TPC0_EML_CFG_DBG_CNT_DBG_EN_MASK 0x2
+#define TPC0_EML_CFG_DBG_CNT_CORE_RST_SHIFT 2
+#define TPC0_EML_CFG_DBG_CNT_CORE_RST_MASK 0x4
+#define TPC0_EML_CFG_DBG_CNT_DCACHE_INV_SHIFT 4
+#define TPC0_EML_CFG_DBG_CNT_DCACHE_INV_MASK 0x10
+#define TPC0_EML_CFG_DBG_CNT_ICACHE_INV_SHIFT 5
+#define TPC0_EML_CFG_DBG_CNT_ICACHE_INV_MASK 0x20
+#define TPC0_EML_CFG_DBG_CNT_DBG_EXIT_SHIFT 6
+#define TPC0_EML_CFG_DBG_CNT_DBG_EXIT_MASK 0x40
+#define TPC0_EML_CFG_DBG_CNT_SNG_STEP_SHIFT 7
+#define TPC0_EML_CFG_DBG_CNT_SNG_STEP_MASK 0x80
+#define TPC0_EML_CFG_DBG_CNT_BP_DBGSW_EN_SHIFT 16
+#define TPC0_EML_CFG_DBG_CNT_BP_DBGSW_EN_MASK 0x10000
+
+/* TPC0_EML_CFG_DBG_STS */
+#define TPC0_EML_CFG_DBG_STS_DBG_MODE_SHIFT 0
+#define TPC0_EML_CFG_DBG_STS_DBG_MODE_MASK 0x1
+#define TPC0_EML_CFG_DBG_STS_CORE_READY_SHIFT 1
+#define TPC0_EML_CFG_DBG_STS_CORE_READY_MASK 0x2
+#define TPC0_EML_CFG_DBG_STS_DURING_KERNEL_SHIFT 2
+#define TPC0_EML_CFG_DBG_STS_DURING_KERNEL_MASK 0x4
+#define TPC0_EML_CFG_DBG_STS_ICACHE_IDLE_SHIFT 3
+#define TPC0_EML_CFG_DBG_STS_ICACHE_IDLE_MASK 0x8
+#define TPC0_EML_CFG_DBG_STS_DCACHE_IDLE_SHIFT 4
+#define TPC0_EML_CFG_DBG_STS_DCACHE_IDLE_MASK 0x10
+#define TPC0_EML_CFG_DBG_STS_QM_IDLE_SHIFT 5
+#define TPC0_EML_CFG_DBG_STS_QM_IDLE_MASK 0x20
+#define TPC0_EML_CFG_DBG_STS_WQ_IDLE_SHIFT 6
+#define TPC0_EML_CFG_DBG_STS_WQ_IDLE_MASK 0x40
+#define TPC0_EML_CFG_DBG_STS_MSS_IDLE_SHIFT 7
+#define TPC0_EML_CFG_DBG_STS_MSS_IDLE_MASK 0x80
+#define TPC0_EML_CFG_DBG_STS_DBG_CAUSE_SHIFT 8
+#define TPC0_EML_CFG_DBG_STS_DBG_CAUSE_MASK 0xFFFFFF00
+
+/* TPC0_EML_CFG_DBG_PADD */
+#define TPC0_EML_CFG_DBG_PADD_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_PADD_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_PADD_COUNT */
+#define TPC0_EML_CFG_DBG_PADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_PADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_PADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_PADD_COUNT_MATCH_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_PADD_COUNT_MATCH_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_PADD_EN */
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE2_SHIFT 2
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE2_MASK 0x4
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE3_SHIFT 3
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE3_MASK 0x8
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE4_SHIFT 4
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE4_MASK 0x10
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE5_SHIFT 5
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE5_MASK 0x20
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE6_SHIFT 6
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE6_MASK 0x40
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE7_SHIFT 7
+#define TPC0_EML_CFG_DBG_PADD_EN_ENABLE7_MASK 0x80
+
+/* TPC0_EML_CFG_DBG_VPADD_HIGH */
+#define TPC0_EML_CFG_DBG_VPADD_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_VPADD_HIGH_ADDRESS_MASK 0x1FF
+
+/* TPC0_EML_CFG_DBG_VPADD_LOW */
+#define TPC0_EML_CFG_DBG_VPADD_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_VPADD_LOW_ADDRESS_MASK 0x1FF
+
+/* TPC0_EML_CFG_DBG_VPADD_COUNT */
+#define TPC0_EML_CFG_DBG_VPADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_VPADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_VPADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_VPADD_COUNT_MATCH_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_VPADD_COUNT_MATCH_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_VPADD_EN */
+#define TPC0_EML_CFG_DBG_VPADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_VPADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_VPADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_VPADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_VPADD_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_VPADD_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_VPADD_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_VPADD_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_SPADD_HIGH */
+#define TPC0_EML_CFG_DBG_SPADD_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPADD_HIGH_ADDRESS_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPADD_LOW */
+#define TPC0_EML_CFG_DBG_SPADD_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPADD_LOW_ADDRESS_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPADD_COUNT */
+#define TPC0_EML_CFG_DBG_SPADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_SPADD_COUNT_MATCH_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPADD_COUNT_MATCH_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPADD_EN */
+#define TPC0_EML_CFG_DBG_SPADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_SPADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_SPADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_SPADD_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_SPADD_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_SPADD_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_SPADD_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_AGUADD_MSB_HIGH */
+#define TPC0_EML_CFG_DBG_AGUADD_MSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_MSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_MSB_LOW */
+#define TPC0_EML_CFG_DBG_AGUADD_MSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_MSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_LSB_HIGH */
+#define TPC0_EML_CFG_DBG_AGUADD_LSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_LSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_LSB_LOW */
+#define TPC0_EML_CFG_DBG_AGUADD_LSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_LSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_COUNT */
+#define TPC0_EML_CFG_DBG_AGUADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_AGUADD_COUNT_MATCH_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_COUNT_MATCH_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AGUADD_EN */
+#define TPC0_EML_CFG_DBG_AGUADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_AGUADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_AGUADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_AGUADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_AGUADD_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_AGUADD_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_AGUADD_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_AGUADD_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_MSB_HIGH */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_MSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_MSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_MSB_LOW */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_MSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_MSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_LSB_HIGH */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_LSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_LSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_LSB_LOW */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_LSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_LSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_COUNT */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_COUNT_MATCH_MATCH_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_COUNT_MATCH_MATCH_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWADD_EN */
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_AXIHBWADD_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_MSB_HIGH */
+#define TPC0_EML_CFG_DBG_AXILBWADD_MSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_MSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_MSB_LOW */
+#define TPC0_EML_CFG_DBG_AXILBWADD_MSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_MSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_LSB_HIGH */
+#define TPC0_EML_CFG_DBG_AXILBWADD_LSB_HIGH_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_LSB_HIGH_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_LSB_LOW */
+#define TPC0_EML_CFG_DBG_AXILBWADD_LSB_LOW_ADDRESS_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_LSB_LOW_ADDRESS_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_COUNT */
+#define TPC0_EML_CFG_DBG_AXILBWADD_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_AXILBWADD_COUNT_MATCH_MATCH_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_COUNT_MATCH_MATCH_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXILBWADD_EN */
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_AXILBWADD_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_SPDATA */
+#define TPC0_EML_CFG_DBG_SPDATA_DATA_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPDATA_DATA_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_SPDATA_COUNT */
+#define TPC0_EML_CFG_DBG_SPDATA_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPDATA_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPDATA_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_SPDATA_COUNT_MATCH_MATCH_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPDATA_COUNT_MATCH_MATCH_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_SPDATA_EN */
+#define TPC0_EML_CFG_DBG_SPDATA_EN_ENABLE0_SHIFT 0
+#define TPC0_EML_CFG_DBG_SPDATA_EN_ENABLE0_MASK 0x1
+#define TPC0_EML_CFG_DBG_SPDATA_EN_ENABLE1_SHIFT 1
+#define TPC0_EML_CFG_DBG_SPDATA_EN_ENABLE1_MASK 0x2
+#define TPC0_EML_CFG_DBG_SPDATA_EN_RW_N0_SHIFT 2
+#define TPC0_EML_CFG_DBG_SPDATA_EN_RW_N0_MASK 0x4
+#define TPC0_EML_CFG_DBG_SPDATA_EN_RW_N1_SHIFT 3
+#define TPC0_EML_CFG_DBG_SPDATA_EN_RW_N1_MASK 0x8
+
+/* TPC0_EML_CFG_DBG_AXIHBWDATA */
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_DATA_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_DATA_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWDATA_COUNT */
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWDAT_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_AXIHBWDAT_COUNT_MATCH_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWDAT_COUNT_MATCH_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXIHBWDATA_EN */
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_EN_ENABLE_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_EN_ENABLE_MASK 0x1
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_EN_RW_N_SHIFT 1
+#define TPC0_EML_CFG_DBG_AXIHBWDATA_EN_RW_N_MASK 0x2
+
+/* TPC0_EML_CFG_DBG_AXILBWDATA */
+#define TPC0_EML_CFG_DBG_AXILBWDATA_DATA_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWDATA_DATA_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_AXILBWDATA_COUNT */
+#define TPC0_EML_CFG_DBG_AXILBWDATA_COUNT_COUNT_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWDATA_COUNT_COUNT_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXILBWDAT_COUNT_MATCH */
+#define TPC0_EML_CFG_DBG_AXILBWDAT_COUNT_MATCH_MATCH_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWDAT_COUNT_MATCH_MATCH_MASK 0xFF
+
+/* TPC0_EML_CFG_DBG_AXILBWDATA_EN */
+#define TPC0_EML_CFG_DBG_AXILBWDATA_EN_ENABLE_SHIFT 0
+#define TPC0_EML_CFG_DBG_AXILBWDATA_EN_ENABLE_MASK 0x1
+#define TPC0_EML_CFG_DBG_AXILBWDATA_EN_RW_N_SHIFT 1
+#define TPC0_EML_CFG_DBG_AXILBWDATA_EN_RW_N_MASK 0x2
+
+/* TPC0_EML_CFG_DBG_D0_PC */
+#define TPC0_EML_CFG_DBG_D0_PC_PC_SHIFT 0
+#define TPC0_EML_CFG_DBG_D0_PC_PC_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_RTTCONFIG */
+#define TPC0_EML_CFG_RTTCONFIG_TR_EN_SHIFT 0
+#define TPC0_EML_CFG_RTTCONFIG_TR_EN_MASK 0x1
+#define TPC0_EML_CFG_RTTCONFIG_PRIO_SHIFT 1
+#define TPC0_EML_CFG_RTTCONFIG_PRIO_MASK 0x2
+
+/* TPC0_EML_CFG_RTTPREDICATE */
+#define TPC0_EML_CFG_RTTPREDICATE_TR_EN_SHIFT 0
+#define TPC0_EML_CFG_RTTPREDICATE_TR_EN_MASK 0x1
+#define TPC0_EML_CFG_RTTPREDICATE_GEN_SHIFT 1
+#define TPC0_EML_CFG_RTTPREDICATE_GEN_MASK 0x2
+#define TPC0_EML_CFG_RTTPREDICATE_USE_INTERVAL_SHIFT 2
+#define TPC0_EML_CFG_RTTPREDICATE_USE_INTERVAL_MASK 0x4
+#define TPC0_EML_CFG_RTTPREDICATE_SPRF_MASK_SHIFT 16
+#define TPC0_EML_CFG_RTTPREDICATE_SPRF_MASK_MASK 0xFFFF0000
+
+/* TPC0_EML_CFG_RTTPREDICATE_INTV */
+#define TPC0_EML_CFG_RTTPREDICATE_INTV_INTERVAL_SHIFT 0
+#define TPC0_EML_CFG_RTTPREDICATE_INTV_INTERVAL_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_RTTTS */
+#define TPC0_EML_CFG_RTTTS_TR_EN_SHIFT 0
+#define TPC0_EML_CFG_RTTTS_TR_EN_MASK 0x1
+#define TPC0_EML_CFG_RTTTS_GEN_SHIFT 1
+#define TPC0_EML_CFG_RTTTS_GEN_MASK 0x2
+#define TPC0_EML_CFG_RTTTS_COMPRESS_EN_SHIFT 2
+#define TPC0_EML_CFG_RTTTS_COMPRESS_EN_MASK 0x4
+
+/* TPC0_EML_CFG_RTTTS_INTV */
+#define TPC0_EML_CFG_RTTTS_INTV_INTERVAL_SHIFT 0
+#define TPC0_EML_CFG_RTTTS_INTV_INTERVAL_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_INST_INSERT */
+#define TPC0_EML_CFG_DBG_INST_INSERT_INST_SHIFT 0
+#define TPC0_EML_CFG_DBG_INST_INSERT_INST_MASK 0xFFFFFFFF
+
+/* TPC0_EML_CFG_DBG_INST_INSERT_CTL */
+#define TPC0_EML_CFG_DBG_INST_INSERT_CTL_INSERT_SHIFT 0
+#define TPC0_EML_CFG_DBG_INST_INSERT_CTL_INSERT_MASK 0x1
+
+#endif /* ASIC_REG_TPC0_EML_CFG_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h
new file mode 100644
index 000000000000..f1a1b4fa4841
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_eml_cfg_regs.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_EML_CFG_REGS_H_
+#define ASIC_REG_TPC0_EML_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC0_EML_CFG (Prototype: TPC_EML_CFG)
+ *****************************************
+ */
+
+#define mmTPC0_EML_CFG_DBG_CNT 0x3040000
+
+#define mmTPC0_EML_CFG_DBG_STS 0x3040004
+
+#define mmTPC0_EML_CFG_DBG_PADD_0 0x3040008
+
+#define mmTPC0_EML_CFG_DBG_PADD_1 0x304000C
+
+#define mmTPC0_EML_CFG_DBG_PADD_2 0x3040010
+
+#define mmTPC0_EML_CFG_DBG_PADD_3 0x3040014
+
+#define mmTPC0_EML_CFG_DBG_PADD_4 0x3040018
+
+#define mmTPC0_EML_CFG_DBG_PADD_5 0x304001C
+
+#define mmTPC0_EML_CFG_DBG_PADD_6 0x3040020
+
+#define mmTPC0_EML_CFG_DBG_PADD_7 0x3040024
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_0 0x3040028
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_1 0x304002C
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_2 0x3040030
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_3 0x3040034
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_4 0x3040038
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_5 0x304003C
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_6 0x3040040
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_7 0x3040044
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_0 0x3040048
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_1 0x304004C
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_2 0x3040050
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_3 0x3040054
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_4 0x3040058
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_5 0x304005C
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_6 0x3040060
+
+#define mmTPC0_EML_CFG_DBG_PADD_COUNT_MATCH_7 0x3040064
+
+#define mmTPC0_EML_CFG_DBG_PADD_EN 0x3040068
+
+#define mmTPC0_EML_CFG_DBG_VPADD_HIGH_0 0x304006C
+
+#define mmTPC0_EML_CFG_DBG_VPADD_HIGH_1 0x3040070
+
+#define mmTPC0_EML_CFG_DBG_VPADD_LOW_0 0x3040074
+
+#define mmTPC0_EML_CFG_DBG_VPADD_LOW_1 0x3040078
+
+#define mmTPC0_EML_CFG_DBG_VPADD_COUNT_0 0x304007C
+
+#define mmTPC0_EML_CFG_DBG_VPADD_COUNT_1 0x3040080
+
+#define mmTPC0_EML_CFG_DBG_VPADD_COUNT_MATCH_0 0x3040084
+
+#define mmTPC0_EML_CFG_DBG_VPADD_COUNT_MATCH_1 0x3040088
+
+#define mmTPC0_EML_CFG_DBG_VPADD_EN 0x304008C
+
+#define mmTPC0_EML_CFG_DBG_SPADD_HIGH_0 0x3040090
+
+#define mmTPC0_EML_CFG_DBG_SPADD_HIGH_1 0x3040094
+
+#define mmTPC0_EML_CFG_DBG_SPADD_LOW_0 0x3040098
+
+#define mmTPC0_EML_CFG_DBG_SPADD_LOW_1 0x304009C
+
+#define mmTPC0_EML_CFG_DBG_SPADD_COUNT_0 0x30400A0
+
+#define mmTPC0_EML_CFG_DBG_SPADD_COUNT_1 0x30400A4
+
+#define mmTPC0_EML_CFG_DBG_SPADD_COUNT_MATCH_0 0x30400A8
+
+#define mmTPC0_EML_CFG_DBG_SPADD_COUNT_MATCH_1 0x30400AC
+
+#define mmTPC0_EML_CFG_DBG_SPADD_EN 0x30400B0
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_MSB_HIGH_0 0x30400B4
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_MSB_HIGH_1 0x30400B8
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_MSB_LOW_0 0x30400BC
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_MSB_LOW_1 0x30400C0
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_LSB_HIGH_0 0x30400C4
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_LSB_HIGH_1 0x30400C8
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_LSB_LOW_0 0x30400CC
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_LSB_LOW_1 0x30400D0
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_COUNT_0 0x30400D4
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_COUNT_1 0x30400D8
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_COUNT_MATCH_0 0x30400DC
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_COUNT_MATCH_1 0x30400E0
+
+#define mmTPC0_EML_CFG_DBG_AGUADD_EN 0x30400E4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_MSB_HIGH_0 0x30400E8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_MSB_HIGH_1 0x30400EC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_MSB_LOW_0 0x30400F0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_MSB_LOW_1 0x30400F4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_LSB_HIGH_0 0x30400F8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_LSB_HIGH_1 0x30400FC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_LSB_LOW_0 0x3040100
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_LSB_LOW_1 0x3040104
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_COUNT_0 0x3040108
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_COUNT_1 0x304010C
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_COUNT_MATCH_0 0x3040110
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_COUNT_MATCH_1 0x3040114
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWADD_EN 0x3040118
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_MSB_HIGH_0 0x304011C
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_MSB_HIGH_1 0x3040120
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_MSB_LOW_0 0x3040124
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_MSB_LOW_1 0x3040128
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_LSB_HIGH_0 0x304012C
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_LSB_HIGH_1 0x3040130
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_LSB_LOW_0 0x3040134
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_LSB_LOW_1 0x3040138
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_COUNT_0 0x304013C
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_COUNT_1 0x3040140
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_COUNT_MATCH_0 0x3040144
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_COUNT_MATCH_1 0x3040148
+
+#define mmTPC0_EML_CFG_DBG_AXILBWADD_EN 0x304014C
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_0 0x3040150
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_1 0x3040154
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_COUNT_0 0x3040158
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_COUNT_1 0x304015C
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_COUNT_MATCH_0 0x3040160
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_COUNT_MATCH_1 0x3040164
+
+#define mmTPC0_EML_CFG_DBG_SPDATA_EN 0x3040168
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_0 0x304016C
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_1 0x3040170
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_2 0x3040174
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_3 0x3040178
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_4 0x304017C
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_5 0x3040180
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_6 0x3040184
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_7 0x3040188
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_8 0x304018C
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_9 0x3040190
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_10 0x3040194
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_11 0x3040198
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_12 0x304019C
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_13 0x30401A0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_14 0x30401A4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_15 0x30401A8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_16 0x30401AC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_17 0x30401B0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_18 0x30401B4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_19 0x30401B8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_20 0x30401BC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_21 0x30401C0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_22 0x30401C4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_23 0x30401C8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_24 0x30401CC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_25 0x30401D0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_26 0x30401D4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_27 0x30401D8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_28 0x30401DC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_29 0x30401E0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_30 0x30401E4
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_31 0x30401E8
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_COUNT 0x30401EC
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDAT_COUNT_MATCH 0x30401F0
+
+#define mmTPC0_EML_CFG_DBG_AXIHBWDATA_EN 0x30401F4
+
+#define mmTPC0_EML_CFG_DBG_AXILBWDATA 0x30401F8
+
+#define mmTPC0_EML_CFG_DBG_AXILBWDATA_COUNT 0x30401FC
+
+#define mmTPC0_EML_CFG_DBG_AXILBWDAT_COUNT_MATCH 0x3040200
+
+#define mmTPC0_EML_CFG_DBG_AXILBWDATA_EN 0x3040204
+
+#define mmTPC0_EML_CFG_DBG_D0_PC 0x3040208
+
+#define mmTPC0_EML_CFG_RTTCONFIG 0x3040300
+
+#define mmTPC0_EML_CFG_RTTPREDICATE 0x3040304
+
+#define mmTPC0_EML_CFG_RTTPREDICATE_INTV 0x3040308
+
+#define mmTPC0_EML_CFG_RTTTS 0x304030C
+
+#define mmTPC0_EML_CFG_RTTTS_INTV 0x3040310
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_0 0x3040314
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_1 0x3040318
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_2 0x304031C
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_3 0x3040320
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_4 0x3040324
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_5 0x3040328
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_6 0x304032C
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_7 0x3040330
+
+#define mmTPC0_EML_CFG_DBG_INST_INSERT_CTL 0x3040334
+
+#endif /* ASIC_REG_TPC0_EML_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h
new file mode 100644
index 000000000000..7f86621179a5
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_masks.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_NRTR_MASKS_H_
+#define ASIC_REG_TPC0_NRTR_MASKS_H_
+
+/*
+ *****************************************
+ * TPC0_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+/* TPC0_NRTR_HBW_MAX_CRED */
+#define TPC0_NRTR_HBW_MAX_CRED_WR_RQ_SHIFT 0
+#define TPC0_NRTR_HBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define TPC0_NRTR_HBW_MAX_CRED_WR_RS_SHIFT 8
+#define TPC0_NRTR_HBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define TPC0_NRTR_HBW_MAX_CRED_RD_RQ_SHIFT 16
+#define TPC0_NRTR_HBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define TPC0_NRTR_HBW_MAX_CRED_RD_RS_SHIFT 24
+#define TPC0_NRTR_HBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* TPC0_NRTR_LBW_MAX_CRED */
+#define TPC0_NRTR_LBW_MAX_CRED_WR_RQ_SHIFT 0
+#define TPC0_NRTR_LBW_MAX_CRED_WR_RQ_MASK 0x3F
+#define TPC0_NRTR_LBW_MAX_CRED_WR_RS_SHIFT 8
+#define TPC0_NRTR_LBW_MAX_CRED_WR_RS_MASK 0x3F00
+#define TPC0_NRTR_LBW_MAX_CRED_RD_RQ_SHIFT 16
+#define TPC0_NRTR_LBW_MAX_CRED_RD_RQ_MASK 0x3F0000
+#define TPC0_NRTR_LBW_MAX_CRED_RD_RS_SHIFT 24
+#define TPC0_NRTR_LBW_MAX_CRED_RD_RS_MASK 0x3F000000
+
+/* TPC0_NRTR_DBG_E_ARB */
+#define TPC0_NRTR_DBG_E_ARB_W_SHIFT 0
+#define TPC0_NRTR_DBG_E_ARB_W_MASK 0x7
+#define TPC0_NRTR_DBG_E_ARB_S_SHIFT 8
+#define TPC0_NRTR_DBG_E_ARB_S_MASK 0x700
+#define TPC0_NRTR_DBG_E_ARB_N_SHIFT 16
+#define TPC0_NRTR_DBG_E_ARB_N_MASK 0x70000
+#define TPC0_NRTR_DBG_E_ARB_L_SHIFT 24
+#define TPC0_NRTR_DBG_E_ARB_L_MASK 0x7000000
+
+/* TPC0_NRTR_DBG_W_ARB */
+#define TPC0_NRTR_DBG_W_ARB_E_SHIFT 0
+#define TPC0_NRTR_DBG_W_ARB_E_MASK 0x7
+#define TPC0_NRTR_DBG_W_ARB_S_SHIFT 8
+#define TPC0_NRTR_DBG_W_ARB_S_MASK 0x700
+#define TPC0_NRTR_DBG_W_ARB_N_SHIFT 16
+#define TPC0_NRTR_DBG_W_ARB_N_MASK 0x70000
+#define TPC0_NRTR_DBG_W_ARB_L_SHIFT 24
+#define TPC0_NRTR_DBG_W_ARB_L_MASK 0x7000000
+
+/* TPC0_NRTR_DBG_N_ARB */
+#define TPC0_NRTR_DBG_N_ARB_W_SHIFT 0
+#define TPC0_NRTR_DBG_N_ARB_W_MASK 0x7
+#define TPC0_NRTR_DBG_N_ARB_E_SHIFT 8
+#define TPC0_NRTR_DBG_N_ARB_E_MASK 0x700
+#define TPC0_NRTR_DBG_N_ARB_S_SHIFT 16
+#define TPC0_NRTR_DBG_N_ARB_S_MASK 0x70000
+#define TPC0_NRTR_DBG_N_ARB_L_SHIFT 24
+#define TPC0_NRTR_DBG_N_ARB_L_MASK 0x7000000
+
+/* TPC0_NRTR_DBG_S_ARB */
+#define TPC0_NRTR_DBG_S_ARB_W_SHIFT 0
+#define TPC0_NRTR_DBG_S_ARB_W_MASK 0x7
+#define TPC0_NRTR_DBG_S_ARB_E_SHIFT 8
+#define TPC0_NRTR_DBG_S_ARB_E_MASK 0x700
+#define TPC0_NRTR_DBG_S_ARB_N_SHIFT 16
+#define TPC0_NRTR_DBG_S_ARB_N_MASK 0x70000
+#define TPC0_NRTR_DBG_S_ARB_L_SHIFT 24
+#define TPC0_NRTR_DBG_S_ARB_L_MASK 0x7000000
+
+/* TPC0_NRTR_DBG_L_ARB */
+#define TPC0_NRTR_DBG_L_ARB_W_SHIFT 0
+#define TPC0_NRTR_DBG_L_ARB_W_MASK 0x7
+#define TPC0_NRTR_DBG_L_ARB_E_SHIFT 8
+#define TPC0_NRTR_DBG_L_ARB_E_MASK 0x700
+#define TPC0_NRTR_DBG_L_ARB_S_SHIFT 16
+#define TPC0_NRTR_DBG_L_ARB_S_MASK 0x70000
+#define TPC0_NRTR_DBG_L_ARB_N_SHIFT 24
+#define TPC0_NRTR_DBG_L_ARB_N_MASK 0x7000000
+
+/* TPC0_NRTR_DBG_E_ARB_MAX */
+#define TPC0_NRTR_DBG_E_ARB_MAX_CREDIT_SHIFT 0
+#define TPC0_NRTR_DBG_E_ARB_MAX_CREDIT_MASK 0x3F
+
+/* TPC0_NRTR_DBG_W_ARB_MAX */
+#define TPC0_NRTR_DBG_W_ARB_MAX_CREDIT_SHIFT 0
+#define TPC0_NRTR_DBG_W_ARB_MAX_CREDIT_MASK 0x3F
+
+/* TPC0_NRTR_DBG_N_ARB_MAX */
+#define TPC0_NRTR_DBG_N_ARB_MAX_CREDIT_SHIFT 0
+#define TPC0_NRTR_DBG_N_ARB_MAX_CREDIT_MASK 0x3F
+
+/* TPC0_NRTR_DBG_S_ARB_MAX */
+#define TPC0_NRTR_DBG_S_ARB_MAX_CREDIT_SHIFT 0
+#define TPC0_NRTR_DBG_S_ARB_MAX_CREDIT_MASK 0x3F
+
+/* TPC0_NRTR_DBG_L_ARB_MAX */
+#define TPC0_NRTR_DBG_L_ARB_MAX_CREDIT_SHIFT 0
+#define TPC0_NRTR_DBG_L_ARB_MAX_CREDIT_MASK 0x3F
+
+/* TPC0_NRTR_SPLIT_COEF */
+#define TPC0_NRTR_SPLIT_COEF_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_COEF_VAL_MASK 0xFFFF
+
+/* TPC0_NRTR_SPLIT_CFG */
+#define TPC0_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_SHIFT 0
+#define TPC0_NRTR_SPLIT_CFG_FORCE_WAK_ORDER_MASK 0x1
+#define TPC0_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_SHIFT 1
+#define TPC0_NRTR_SPLIT_CFG_FORCE_STRONG_ORDER_MASK 0x2
+#define TPC0_NRTR_SPLIT_CFG_DEFAULT_MESH_SHIFT 2
+#define TPC0_NRTR_SPLIT_CFG_DEFAULT_MESH_MASK 0xC
+#define TPC0_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_SHIFT 4
+#define TPC0_NRTR_SPLIT_CFG_RD_RATE_LIM_EN_MASK 0x10
+#define TPC0_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_SHIFT 5
+#define TPC0_NRTR_SPLIT_CFG_WR_RATE_LIM_EN_MASK 0x20
+#define TPC0_NRTR_SPLIT_CFG_B2B_OPT_SHIFT 6
+#define TPC0_NRTR_SPLIT_CFG_B2B_OPT_MASK 0x1C0
+
+/* TPC0_NRTR_SPLIT_RD_SAT */
+#define TPC0_NRTR_SPLIT_RD_SAT_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_RD_SAT_VAL_MASK 0xFFFF
+
+/* TPC0_NRTR_SPLIT_RD_RST_TOKEN */
+#define TPC0_NRTR_SPLIT_RD_RST_TOKEN_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_RD_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* TPC0_NRTR_SPLIT_RD_TIMEOUT */
+#define TPC0_NRTR_SPLIT_RD_TIMEOUT_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_RD_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_NRTR_SPLIT_WR_SAT */
+#define TPC0_NRTR_SPLIT_WR_SAT_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_WR_SAT_VAL_MASK 0xFFFF
+
+/* TPC0_NRTR_WPLIT_WR_TST_TOLEN */
+#define TPC0_NRTR_WPLIT_WR_TST_TOLEN_VAL_SHIFT 0
+#define TPC0_NRTR_WPLIT_WR_TST_TOLEN_VAL_MASK 0xFFFF
+
+/* TPC0_NRTR_SPLIT_WR_TIMEOUT */
+#define TPC0_NRTR_SPLIT_WR_TIMEOUT_VAL_SHIFT 0
+#define TPC0_NRTR_SPLIT_WR_TIMEOUT_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_NRTR_HBW_RANGE_HIT */
+#define TPC0_NRTR_HBW_RANGE_HIT_IND_SHIFT 0
+#define TPC0_NRTR_HBW_RANGE_HIT_IND_MASK 0xFF
+
+/* TPC0_NRTR_HBW_RANGE_MASK_L */
+#define TPC0_NRTR_HBW_RANGE_MASK_L_VAL_SHIFT 0
+#define TPC0_NRTR_HBW_RANGE_MASK_L_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_NRTR_HBW_RANGE_MASK_H */
+#define TPC0_NRTR_HBW_RANGE_MASK_H_VAL_SHIFT 0
+#define TPC0_NRTR_HBW_RANGE_MASK_H_VAL_MASK 0x3FFFF
+
+/* TPC0_NRTR_HBW_RANGE_BASE_L */
+#define TPC0_NRTR_HBW_RANGE_BASE_L_VAL_SHIFT 0
+#define TPC0_NRTR_HBW_RANGE_BASE_L_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_NRTR_HBW_RANGE_BASE_H */
+#define TPC0_NRTR_HBW_RANGE_BASE_H_VAL_SHIFT 0
+#define TPC0_NRTR_HBW_RANGE_BASE_H_VAL_MASK 0x3FFFF
+
+/* TPC0_NRTR_LBW_RANGE_HIT */
+#define TPC0_NRTR_LBW_RANGE_HIT_IND_SHIFT 0
+#define TPC0_NRTR_LBW_RANGE_HIT_IND_MASK 0xFFFF
+
+/* TPC0_NRTR_LBW_RANGE_MASK */
+#define TPC0_NRTR_LBW_RANGE_MASK_VAL_SHIFT 0
+#define TPC0_NRTR_LBW_RANGE_MASK_VAL_MASK 0x3FFFFFF
+
+/* TPC0_NRTR_LBW_RANGE_BASE */
+#define TPC0_NRTR_LBW_RANGE_BASE_VAL_SHIFT 0
+#define TPC0_NRTR_LBW_RANGE_BASE_VAL_MASK 0x3FFFFFF
+
+/* TPC0_NRTR_RGLTR */
+#define TPC0_NRTR_RGLTR_WR_EN_SHIFT 0
+#define TPC0_NRTR_RGLTR_WR_EN_MASK 0x1
+#define TPC0_NRTR_RGLTR_RD_EN_SHIFT 4
+#define TPC0_NRTR_RGLTR_RD_EN_MASK 0x10
+
+/* TPC0_NRTR_RGLTR_WR_RESULT */
+#define TPC0_NRTR_RGLTR_WR_RESULT_VAL_SHIFT 0
+#define TPC0_NRTR_RGLTR_WR_RESULT_VAL_MASK 0xFF
+
+/* TPC0_NRTR_RGLTR_RD_RESULT */
+#define TPC0_NRTR_RGLTR_RD_RESULT_VAL_SHIFT 0
+#define TPC0_NRTR_RGLTR_RD_RESULT_VAL_MASK 0xFF
+
+/* TPC0_NRTR_SCRAMB_EN */
+#define TPC0_NRTR_SCRAMB_EN_VAL_SHIFT 0
+#define TPC0_NRTR_SCRAMB_EN_VAL_MASK 0x1
+
+/* TPC0_NRTR_NON_LIN_SCRAMB */
+#define TPC0_NRTR_NON_LIN_SCRAMB_EN_SHIFT 0
+#define TPC0_NRTR_NON_LIN_SCRAMB_EN_MASK 0x1
+
+#endif /* ASIC_REG_TPC0_NRTR_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h
new file mode 100644
index 000000000000..dc280f4e6608
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_nrtr_regs.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_NRTR_REGS_H_
+#define ASIC_REG_TPC0_NRTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC0_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+#define mmTPC0_NRTR_HBW_MAX_CRED 0xE00100
+
+#define mmTPC0_NRTR_LBW_MAX_CRED 0xE00120
+
+#define mmTPC0_NRTR_DBG_E_ARB 0xE00300
+
+#define mmTPC0_NRTR_DBG_W_ARB 0xE00304
+
+#define mmTPC0_NRTR_DBG_N_ARB 0xE00308
+
+#define mmTPC0_NRTR_DBG_S_ARB 0xE0030C
+
+#define mmTPC0_NRTR_DBG_L_ARB 0xE00310
+
+#define mmTPC0_NRTR_DBG_E_ARB_MAX 0xE00320
+
+#define mmTPC0_NRTR_DBG_W_ARB_MAX 0xE00324
+
+#define mmTPC0_NRTR_DBG_N_ARB_MAX 0xE00328
+
+#define mmTPC0_NRTR_DBG_S_ARB_MAX 0xE0032C
+
+#define mmTPC0_NRTR_DBG_L_ARB_MAX 0xE00330
+
+#define mmTPC0_NRTR_SPLIT_COEF_0 0xE00400
+
+#define mmTPC0_NRTR_SPLIT_COEF_1 0xE00404
+
+#define mmTPC0_NRTR_SPLIT_COEF_2 0xE00408
+
+#define mmTPC0_NRTR_SPLIT_COEF_3 0xE0040C
+
+#define mmTPC0_NRTR_SPLIT_COEF_4 0xE00410
+
+#define mmTPC0_NRTR_SPLIT_COEF_5 0xE00414
+
+#define mmTPC0_NRTR_SPLIT_COEF_6 0xE00418
+
+#define mmTPC0_NRTR_SPLIT_COEF_7 0xE0041C
+
+#define mmTPC0_NRTR_SPLIT_COEF_8 0xE00420
+
+#define mmTPC0_NRTR_SPLIT_COEF_9 0xE00424
+
+#define mmTPC0_NRTR_SPLIT_CFG 0xE00440
+
+#define mmTPC0_NRTR_SPLIT_RD_SAT 0xE00444
+
+#define mmTPC0_NRTR_SPLIT_RD_RST_TOKEN 0xE00448
+
+#define mmTPC0_NRTR_SPLIT_RD_TIMEOUT_0 0xE0044C
+
+#define mmTPC0_NRTR_SPLIT_RD_TIMEOUT_1 0xE00450
+
+#define mmTPC0_NRTR_SPLIT_WR_SAT 0xE00454
+
+#define mmTPC0_NRTR_WPLIT_WR_TST_TOLEN 0xE00458
+
+#define mmTPC0_NRTR_SPLIT_WR_TIMEOUT_0 0xE0045C
+
+#define mmTPC0_NRTR_SPLIT_WR_TIMEOUT_1 0xE00460
+
+#define mmTPC0_NRTR_HBW_RANGE_HIT 0xE00470
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_0 0xE00480
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_1 0xE00484
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_2 0xE00488
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_3 0xE0048C
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_4 0xE00490
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_5 0xE00494
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_6 0xE00498
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_L_7 0xE0049C
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_0 0xE004A0
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_1 0xE004A4
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_2 0xE004A8
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_3 0xE004AC
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_4 0xE004B0
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_5 0xE004B4
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_6 0xE004B8
+
+#define mmTPC0_NRTR_HBW_RANGE_MASK_H_7 0xE004BC
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_0 0xE004C0
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_1 0xE004C4
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_2 0xE004C8
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_3 0xE004CC
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_4 0xE004D0
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_5 0xE004D4
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_6 0xE004D8
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_L_7 0xE004DC
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_0 0xE004E0
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_1 0xE004E4
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_2 0xE004E8
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_3 0xE004EC
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_4 0xE004F0
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_5 0xE004F4
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_6 0xE004F8
+
+#define mmTPC0_NRTR_HBW_RANGE_BASE_H_7 0xE004FC
+
+#define mmTPC0_NRTR_LBW_RANGE_HIT 0xE00500
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_0 0xE00510
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_1 0xE00514
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_2 0xE00518
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_3 0xE0051C
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_4 0xE00520
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_5 0xE00524
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_6 0xE00528
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_7 0xE0052C
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_8 0xE00530
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_9 0xE00534
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_10 0xE00538
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_11 0xE0053C
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_12 0xE00540
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_13 0xE00544
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_14 0xE00548
+
+#define mmTPC0_NRTR_LBW_RANGE_MASK_15 0xE0054C
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_0 0xE00550
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_1 0xE00554
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_2 0xE00558
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_3 0xE0055C
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_4 0xE00560
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_5 0xE00564
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_6 0xE00568
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_7 0xE0056C
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_8 0xE00570
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_9 0xE00574
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_10 0xE00578
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_11 0xE0057C
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_12 0xE00580
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_13 0xE00584
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_14 0xE00588
+
+#define mmTPC0_NRTR_LBW_RANGE_BASE_15 0xE0058C
+
+#define mmTPC0_NRTR_RGLTR 0xE00590
+
+#define mmTPC0_NRTR_RGLTR_WR_RESULT 0xE00594
+
+#define mmTPC0_NRTR_RGLTR_RD_RESULT 0xE00598
+
+#define mmTPC0_NRTR_SCRAMB_EN 0xE00600
+
+#define mmTPC0_NRTR_NON_LIN_SCRAMB 0xE00604
+
+#endif /* ASIC_REG_TPC0_NRTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h
new file mode 100644
index 000000000000..80d97ee3d8d6
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_masks.h
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_QM_MASKS_H_
+#define ASIC_REG_TPC0_QM_MASKS_H_
+
+/*
+ *****************************************
+ * TPC0_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+/* TPC0_QM_GLBL_CFG0 */
+#define TPC0_QM_GLBL_CFG0_PQF_EN_SHIFT 0
+#define TPC0_QM_GLBL_CFG0_PQF_EN_MASK 0x1
+#define TPC0_QM_GLBL_CFG0_CQF_EN_SHIFT 1
+#define TPC0_QM_GLBL_CFG0_CQF_EN_MASK 0x2
+#define TPC0_QM_GLBL_CFG0_CP_EN_SHIFT 2
+#define TPC0_QM_GLBL_CFG0_CP_EN_MASK 0x4
+#define TPC0_QM_GLBL_CFG0_DMA_EN_SHIFT 3
+#define TPC0_QM_GLBL_CFG0_DMA_EN_MASK 0x8
+
+/* TPC0_QM_GLBL_CFG1 */
+#define TPC0_QM_GLBL_CFG1_PQF_STOP_SHIFT 0
+#define TPC0_QM_GLBL_CFG1_PQF_STOP_MASK 0x1
+#define TPC0_QM_GLBL_CFG1_CQF_STOP_SHIFT 1
+#define TPC0_QM_GLBL_CFG1_CQF_STOP_MASK 0x2
+#define TPC0_QM_GLBL_CFG1_CP_STOP_SHIFT 2
+#define TPC0_QM_GLBL_CFG1_CP_STOP_MASK 0x4
+#define TPC0_QM_GLBL_CFG1_DMA_STOP_SHIFT 3
+#define TPC0_QM_GLBL_CFG1_DMA_STOP_MASK 0x8
+#define TPC0_QM_GLBL_CFG1_PQF_FLUSH_SHIFT 8
+#define TPC0_QM_GLBL_CFG1_PQF_FLUSH_MASK 0x100
+#define TPC0_QM_GLBL_CFG1_CQF_FLUSH_SHIFT 9
+#define TPC0_QM_GLBL_CFG1_CQF_FLUSH_MASK 0x200
+#define TPC0_QM_GLBL_CFG1_CP_FLUSH_SHIFT 10
+#define TPC0_QM_GLBL_CFG1_CP_FLUSH_MASK 0x400
+#define TPC0_QM_GLBL_CFG1_DMA_FLUSH_SHIFT 11
+#define TPC0_QM_GLBL_CFG1_DMA_FLUSH_MASK 0x800
+
+/* TPC0_QM_GLBL_PROT */
+#define TPC0_QM_GLBL_PROT_PQF_PROT_SHIFT 0
+#define TPC0_QM_GLBL_PROT_PQF_PROT_MASK 0x1
+#define TPC0_QM_GLBL_PROT_CQF_PROT_SHIFT 1
+#define TPC0_QM_GLBL_PROT_CQF_PROT_MASK 0x2
+#define TPC0_QM_GLBL_PROT_CP_PROT_SHIFT 2
+#define TPC0_QM_GLBL_PROT_CP_PROT_MASK 0x4
+#define TPC0_QM_GLBL_PROT_DMA_PROT_SHIFT 3
+#define TPC0_QM_GLBL_PROT_DMA_PROT_MASK 0x8
+#define TPC0_QM_GLBL_PROT_PQF_ERR_PROT_SHIFT 4
+#define TPC0_QM_GLBL_PROT_PQF_ERR_PROT_MASK 0x10
+#define TPC0_QM_GLBL_PROT_CQF_ERR_PROT_SHIFT 5
+#define TPC0_QM_GLBL_PROT_CQF_ERR_PROT_MASK 0x20
+#define TPC0_QM_GLBL_PROT_CP_ERR_PROT_SHIFT 6
+#define TPC0_QM_GLBL_PROT_CP_ERR_PROT_MASK 0x40
+#define TPC0_QM_GLBL_PROT_DMA_ERR_PROT_SHIFT 7
+#define TPC0_QM_GLBL_PROT_DMA_ERR_PROT_MASK 0x80
+
+/* TPC0_QM_GLBL_ERR_CFG */
+#define TPC0_QM_GLBL_ERR_CFG_PQF_ERR_INT_EN_SHIFT 0
+#define TPC0_QM_GLBL_ERR_CFG_PQF_ERR_INT_EN_MASK 0x1
+#define TPC0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_SHIFT 1
+#define TPC0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK 0x2
+#define TPC0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_SHIFT 2
+#define TPC0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK 0x4
+#define TPC0_QM_GLBL_ERR_CFG_CQF_ERR_INT_EN_SHIFT 3
+#define TPC0_QM_GLBL_ERR_CFG_CQF_ERR_INT_EN_MASK 0x8
+#define TPC0_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_SHIFT 4
+#define TPC0_QM_GLBL_ERR_CFG_CQF_ERR_MSG_EN_MASK 0x10
+#define TPC0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_SHIFT 5
+#define TPC0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK 0x20
+#define TPC0_QM_GLBL_ERR_CFG_CP_ERR_INT_EN_SHIFT 6
+#define TPC0_QM_GLBL_ERR_CFG_CP_ERR_INT_EN_MASK 0x40
+#define TPC0_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_SHIFT 7
+#define TPC0_QM_GLBL_ERR_CFG_CP_ERR_MSG_EN_MASK 0x80
+#define TPC0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_SHIFT 8
+#define TPC0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK 0x100
+#define TPC0_QM_GLBL_ERR_CFG_DMA_ERR_INT_EN_SHIFT 9
+#define TPC0_QM_GLBL_ERR_CFG_DMA_ERR_INT_EN_MASK 0x200
+#define TPC0_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_SHIFT 10
+#define TPC0_QM_GLBL_ERR_CFG_DMA_ERR_MSG_EN_MASK 0x400
+#define TPC0_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT 11
+#define TPC0_QM_GLBL_ERR_CFG_DMA_STOP_ON_ERR_MASK 0x800
+
+/* TPC0_QM_GLBL_ERR_ADDR_LO */
+#define TPC0_QM_GLBL_ERR_ADDR_LO_VAL_SHIFT 0
+#define TPC0_QM_GLBL_ERR_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_GLBL_ERR_ADDR_HI */
+#define TPC0_QM_GLBL_ERR_ADDR_HI_VAL_SHIFT 0
+#define TPC0_QM_GLBL_ERR_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_GLBL_ERR_WDATA */
+#define TPC0_QM_GLBL_ERR_WDATA_VAL_SHIFT 0
+#define TPC0_QM_GLBL_ERR_WDATA_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_GLBL_SECURE_PROPS */
+#define TPC0_QM_GLBL_SECURE_PROPS_ASID_SHIFT 0
+#define TPC0_QM_GLBL_SECURE_PROPS_ASID_MASK 0x3FF
+#define TPC0_QM_GLBL_SECURE_PROPS_MMBP_SHIFT 10
+#define TPC0_QM_GLBL_SECURE_PROPS_MMBP_MASK 0x400
+
+/* TPC0_QM_GLBL_NON_SECURE_PROPS */
+#define TPC0_QM_GLBL_NON_SECURE_PROPS_ASID_SHIFT 0
+#define TPC0_QM_GLBL_NON_SECURE_PROPS_ASID_MASK 0x3FF
+#define TPC0_QM_GLBL_NON_SECURE_PROPS_MMBP_SHIFT 10
+#define TPC0_QM_GLBL_NON_SECURE_PROPS_MMBP_MASK 0x400
+
+/* TPC0_QM_GLBL_STS0 */
+#define TPC0_QM_GLBL_STS0_PQF_IDLE_SHIFT 0
+#define TPC0_QM_GLBL_STS0_PQF_IDLE_MASK 0x1
+#define TPC0_QM_GLBL_STS0_CQF_IDLE_SHIFT 1
+#define TPC0_QM_GLBL_STS0_CQF_IDLE_MASK 0x2
+#define TPC0_QM_GLBL_STS0_CP_IDLE_SHIFT 2
+#define TPC0_QM_GLBL_STS0_CP_IDLE_MASK 0x4
+#define TPC0_QM_GLBL_STS0_DMA_IDLE_SHIFT 3
+#define TPC0_QM_GLBL_STS0_DMA_IDLE_MASK 0x8
+#define TPC0_QM_GLBL_STS0_PQF_IS_STOP_SHIFT 4
+#define TPC0_QM_GLBL_STS0_PQF_IS_STOP_MASK 0x10
+#define TPC0_QM_GLBL_STS0_CQF_IS_STOP_SHIFT 5
+#define TPC0_QM_GLBL_STS0_CQF_IS_STOP_MASK 0x20
+#define TPC0_QM_GLBL_STS0_CP_IS_STOP_SHIFT 6
+#define TPC0_QM_GLBL_STS0_CP_IS_STOP_MASK 0x40
+#define TPC0_QM_GLBL_STS0_DMA_IS_STOP_SHIFT 7
+#define TPC0_QM_GLBL_STS0_DMA_IS_STOP_MASK 0x80
+
+/* TPC0_QM_GLBL_STS1 */
+#define TPC0_QM_GLBL_STS1_PQF_RD_ERR_SHIFT 0
+#define TPC0_QM_GLBL_STS1_PQF_RD_ERR_MASK 0x1
+#define TPC0_QM_GLBL_STS1_CQF_RD_ERR_SHIFT 1
+#define TPC0_QM_GLBL_STS1_CQF_RD_ERR_MASK 0x2
+#define TPC0_QM_GLBL_STS1_CP_RD_ERR_SHIFT 2
+#define TPC0_QM_GLBL_STS1_CP_RD_ERR_MASK 0x4
+#define TPC0_QM_GLBL_STS1_CP_UNDEF_CMD_ERR_SHIFT 3
+#define TPC0_QM_GLBL_STS1_CP_UNDEF_CMD_ERR_MASK 0x8
+#define TPC0_QM_GLBL_STS1_CP_STOP_OP_SHIFT 4
+#define TPC0_QM_GLBL_STS1_CP_STOP_OP_MASK 0x10
+#define TPC0_QM_GLBL_STS1_CP_MSG_WR_ERR_SHIFT 5
+#define TPC0_QM_GLBL_STS1_CP_MSG_WR_ERR_MASK 0x20
+#define TPC0_QM_GLBL_STS1_DMA_RD_ERR_SHIFT 8
+#define TPC0_QM_GLBL_STS1_DMA_RD_ERR_MASK 0x100
+#define TPC0_QM_GLBL_STS1_DMA_WR_ERR_SHIFT 9
+#define TPC0_QM_GLBL_STS1_DMA_WR_ERR_MASK 0x200
+#define TPC0_QM_GLBL_STS1_DMA_RD_MSG_ERR_SHIFT 10
+#define TPC0_QM_GLBL_STS1_DMA_RD_MSG_ERR_MASK 0x400
+#define TPC0_QM_GLBL_STS1_DMA_WR_MSG_ERR_SHIFT 11
+#define TPC0_QM_GLBL_STS1_DMA_WR_MSG_ERR_MASK 0x800
+
+/* TPC0_QM_PQ_BASE_LO */
+#define TPC0_QM_PQ_BASE_LO_VAL_SHIFT 0
+#define TPC0_QM_PQ_BASE_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_BASE_HI */
+#define TPC0_QM_PQ_BASE_HI_VAL_SHIFT 0
+#define TPC0_QM_PQ_BASE_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_SIZE */
+#define TPC0_QM_PQ_SIZE_VAL_SHIFT 0
+#define TPC0_QM_PQ_SIZE_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_PI */
+#define TPC0_QM_PQ_PI_VAL_SHIFT 0
+#define TPC0_QM_PQ_PI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_CI */
+#define TPC0_QM_PQ_CI_VAL_SHIFT 0
+#define TPC0_QM_PQ_CI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_CFG0 */
+#define TPC0_QM_PQ_CFG0_RESERVED_SHIFT 0
+#define TPC0_QM_PQ_CFG0_RESERVED_MASK 0x1
+
+/* TPC0_QM_PQ_CFG1 */
+#define TPC0_QM_PQ_CFG1_CREDIT_LIM_SHIFT 0
+#define TPC0_QM_PQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define TPC0_QM_PQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define TPC0_QM_PQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* TPC0_QM_PQ_ARUSER */
+#define TPC0_QM_PQ_ARUSER_NOSNOOP_SHIFT 0
+#define TPC0_QM_PQ_ARUSER_NOSNOOP_MASK 0x1
+#define TPC0_QM_PQ_ARUSER_WORD_SHIFT 1
+#define TPC0_QM_PQ_ARUSER_WORD_MASK 0x2
+
+/* TPC0_QM_PQ_PUSH0 */
+#define TPC0_QM_PQ_PUSH0_PTR_LO_SHIFT 0
+#define TPC0_QM_PQ_PUSH0_PTR_LO_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_PUSH1 */
+#define TPC0_QM_PQ_PUSH1_PTR_HI_SHIFT 0
+#define TPC0_QM_PQ_PUSH1_PTR_HI_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_PUSH2 */
+#define TPC0_QM_PQ_PUSH2_TSIZE_SHIFT 0
+#define TPC0_QM_PQ_PUSH2_TSIZE_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_PUSH3 */
+#define TPC0_QM_PQ_PUSH3_RPT_SHIFT 0
+#define TPC0_QM_PQ_PUSH3_RPT_MASK 0xFFFF
+#define TPC0_QM_PQ_PUSH3_CTL_SHIFT 16
+#define TPC0_QM_PQ_PUSH3_CTL_MASK 0xFFFF0000
+
+/* TPC0_QM_PQ_STS0 */
+#define TPC0_QM_PQ_STS0_PQ_CREDIT_CNT_SHIFT 0
+#define TPC0_QM_PQ_STS0_PQ_CREDIT_CNT_MASK 0xFFFF
+#define TPC0_QM_PQ_STS0_PQ_FREE_CNT_SHIFT 16
+#define TPC0_QM_PQ_STS0_PQ_FREE_CNT_MASK 0xFFFF0000
+
+/* TPC0_QM_PQ_STS1 */
+#define TPC0_QM_PQ_STS1_PQ_INFLIGHT_CNT_SHIFT 0
+#define TPC0_QM_PQ_STS1_PQ_INFLIGHT_CNT_MASK 0xFFFF
+#define TPC0_QM_PQ_STS1_PQ_BUF_EMPTY_SHIFT 30
+#define TPC0_QM_PQ_STS1_PQ_BUF_EMPTY_MASK 0x40000000
+#define TPC0_QM_PQ_STS1_PQ_BUSY_SHIFT 31
+#define TPC0_QM_PQ_STS1_PQ_BUSY_MASK 0x80000000
+
+/* TPC0_QM_PQ_RD_RATE_LIM_EN */
+#define TPC0_QM_PQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define TPC0_QM_PQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* TPC0_QM_PQ_RD_RATE_LIM_RST_TOKEN */
+#define TPC0_QM_PQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define TPC0_QM_PQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* TPC0_QM_PQ_RD_RATE_LIM_SAT */
+#define TPC0_QM_PQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define TPC0_QM_PQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* TPC0_QM_PQ_RD_RATE_LIM_TOUT */
+#define TPC0_QM_PQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define TPC0_QM_PQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* TPC0_QM_CQ_CFG0 */
+#define TPC0_QM_CQ_CFG0_RESERVED_SHIFT 0
+#define TPC0_QM_CQ_CFG0_RESERVED_MASK 0x1
+
+/* TPC0_QM_CQ_CFG1 */
+#define TPC0_QM_CQ_CFG1_CREDIT_LIM_SHIFT 0
+#define TPC0_QM_CQ_CFG1_CREDIT_LIM_MASK 0xFFFF
+#define TPC0_QM_CQ_CFG1_MAX_INFLIGHT_SHIFT 16
+#define TPC0_QM_CQ_CFG1_MAX_INFLIGHT_MASK 0xFFFF0000
+
+/* TPC0_QM_CQ_ARUSER */
+#define TPC0_QM_CQ_ARUSER_NOSNOOP_SHIFT 0
+#define TPC0_QM_CQ_ARUSER_NOSNOOP_MASK 0x1
+#define TPC0_QM_CQ_ARUSER_WORD_SHIFT 1
+#define TPC0_QM_CQ_ARUSER_WORD_MASK 0x2
+
+/* TPC0_QM_CQ_PTR_LO */
+#define TPC0_QM_CQ_PTR_LO_VAL_SHIFT 0
+#define TPC0_QM_CQ_PTR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_PTR_HI */
+#define TPC0_QM_CQ_PTR_HI_VAL_SHIFT 0
+#define TPC0_QM_CQ_PTR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_TSIZE */
+#define TPC0_QM_CQ_TSIZE_VAL_SHIFT 0
+#define TPC0_QM_CQ_TSIZE_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_CTL */
+#define TPC0_QM_CQ_CTL_RPT_SHIFT 0
+#define TPC0_QM_CQ_CTL_RPT_MASK 0xFFFF
+#define TPC0_QM_CQ_CTL_CTL_SHIFT 16
+#define TPC0_QM_CQ_CTL_CTL_MASK 0xFFFF0000
+
+/* TPC0_QM_CQ_PTR_LO_STS */
+#define TPC0_QM_CQ_PTR_LO_STS_VAL_SHIFT 0
+#define TPC0_QM_CQ_PTR_LO_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_PTR_HI_STS */
+#define TPC0_QM_CQ_PTR_HI_STS_VAL_SHIFT 0
+#define TPC0_QM_CQ_PTR_HI_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_TSIZE_STS */
+#define TPC0_QM_CQ_TSIZE_STS_VAL_SHIFT 0
+#define TPC0_QM_CQ_TSIZE_STS_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_CTL_STS */
+#define TPC0_QM_CQ_CTL_STS_RPT_SHIFT 0
+#define TPC0_QM_CQ_CTL_STS_RPT_MASK 0xFFFF
+#define TPC0_QM_CQ_CTL_STS_CTL_SHIFT 16
+#define TPC0_QM_CQ_CTL_STS_CTL_MASK 0xFFFF0000
+
+/* TPC0_QM_CQ_STS0 */
+#define TPC0_QM_CQ_STS0_CQ_CREDIT_CNT_SHIFT 0
+#define TPC0_QM_CQ_STS0_CQ_CREDIT_CNT_MASK 0xFFFF
+#define TPC0_QM_CQ_STS0_CQ_FREE_CNT_SHIFT 16
+#define TPC0_QM_CQ_STS0_CQ_FREE_CNT_MASK 0xFFFF0000
+
+/* TPC0_QM_CQ_STS1 */
+#define TPC0_QM_CQ_STS1_CQ_INFLIGHT_CNT_SHIFT 0
+#define TPC0_QM_CQ_STS1_CQ_INFLIGHT_CNT_MASK 0xFFFF
+#define TPC0_QM_CQ_STS1_CQ_BUF_EMPTY_SHIFT 30
+#define TPC0_QM_CQ_STS1_CQ_BUF_EMPTY_MASK 0x40000000
+#define TPC0_QM_CQ_STS1_CQ_BUSY_SHIFT 31
+#define TPC0_QM_CQ_STS1_CQ_BUSY_MASK 0x80000000
+
+/* TPC0_QM_CQ_RD_RATE_LIM_EN */
+#define TPC0_QM_CQ_RD_RATE_LIM_EN_VAL_SHIFT 0
+#define TPC0_QM_CQ_RD_RATE_LIM_EN_VAL_MASK 0x1
+
+/* TPC0_QM_CQ_RD_RATE_LIM_RST_TOKEN */
+#define TPC0_QM_CQ_RD_RATE_LIM_RST_TOKEN_VAL_SHIFT 0
+#define TPC0_QM_CQ_RD_RATE_LIM_RST_TOKEN_VAL_MASK 0xFFFF
+
+/* TPC0_QM_CQ_RD_RATE_LIM_SAT */
+#define TPC0_QM_CQ_RD_RATE_LIM_SAT_VAL_SHIFT 0
+#define TPC0_QM_CQ_RD_RATE_LIM_SAT_VAL_MASK 0xFFFF
+
+/* TPC0_QM_CQ_RD_RATE_LIM_TOUT */
+#define TPC0_QM_CQ_RD_RATE_LIM_TOUT_VAL_SHIFT 0
+#define TPC0_QM_CQ_RD_RATE_LIM_TOUT_VAL_MASK 0x7FFFFFFF
+
+/* TPC0_QM_CQ_IFIFO_CNT */
+#define TPC0_QM_CQ_IFIFO_CNT_VAL_SHIFT 0
+#define TPC0_QM_CQ_IFIFO_CNT_VAL_MASK 0x3
+
+/* TPC0_QM_CP_MSG_BASE0_ADDR_LO */
+#define TPC0_QM_CP_MSG_BASE0_ADDR_LO_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE0_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE0_ADDR_HI */
+#define TPC0_QM_CP_MSG_BASE0_ADDR_HI_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE0_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE1_ADDR_LO */
+#define TPC0_QM_CP_MSG_BASE1_ADDR_LO_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE1_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE1_ADDR_HI */
+#define TPC0_QM_CP_MSG_BASE1_ADDR_HI_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE1_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE2_ADDR_LO */
+#define TPC0_QM_CP_MSG_BASE2_ADDR_LO_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE2_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE2_ADDR_HI */
+#define TPC0_QM_CP_MSG_BASE2_ADDR_HI_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE2_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE3_ADDR_LO */
+#define TPC0_QM_CP_MSG_BASE3_ADDR_LO_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE3_ADDR_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_MSG_BASE3_ADDR_HI */
+#define TPC0_QM_CP_MSG_BASE3_ADDR_HI_VAL_SHIFT 0
+#define TPC0_QM_CP_MSG_BASE3_ADDR_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_TSIZE_OFFSET */
+#define TPC0_QM_CP_LDMA_TSIZE_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_TSIZE_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET */
+#define TPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET */
+#define TPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET */
+#define TPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_DST_BASE_HI_OFFSET */
+#define TPC0_QM_CP_LDMA_DST_BASE_HI_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_DST_BASE_HI_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_LDMA_COMMIT_OFFSET */
+#define TPC0_QM_CP_LDMA_COMMIT_OFFSET_VAL_SHIFT 0
+#define TPC0_QM_CP_LDMA_COMMIT_OFFSET_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_FENCE0_RDATA */
+#define TPC0_QM_CP_FENCE0_RDATA_INC_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE0_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_QM_CP_FENCE1_RDATA */
+#define TPC0_QM_CP_FENCE1_RDATA_INC_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE1_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_QM_CP_FENCE2_RDATA */
+#define TPC0_QM_CP_FENCE2_RDATA_INC_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE2_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_QM_CP_FENCE3_RDATA */
+#define TPC0_QM_CP_FENCE3_RDATA_INC_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE3_RDATA_INC_VAL_MASK 0xF
+
+/* TPC0_QM_CP_FENCE0_CNT */
+#define TPC0_QM_CP_FENCE0_CNT_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE0_CNT_VAL_MASK 0xFF
+
+/* TPC0_QM_CP_FENCE1_CNT */
+#define TPC0_QM_CP_FENCE1_CNT_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE1_CNT_VAL_MASK 0xFF
+
+/* TPC0_QM_CP_FENCE2_CNT */
+#define TPC0_QM_CP_FENCE2_CNT_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE2_CNT_VAL_MASK 0xFF
+
+/* TPC0_QM_CP_FENCE3_CNT */
+#define TPC0_QM_CP_FENCE3_CNT_VAL_SHIFT 0
+#define TPC0_QM_CP_FENCE3_CNT_VAL_MASK 0xFF
+
+/* TPC0_QM_CP_STS */
+#define TPC0_QM_CP_STS_MSG_INFLIGHT_CNT_SHIFT 0
+#define TPC0_QM_CP_STS_MSG_INFLIGHT_CNT_MASK 0xFFFF
+#define TPC0_QM_CP_STS_ERDY_SHIFT 16
+#define TPC0_QM_CP_STS_ERDY_MASK 0x10000
+#define TPC0_QM_CP_STS_RRDY_SHIFT 17
+#define TPC0_QM_CP_STS_RRDY_MASK 0x20000
+#define TPC0_QM_CP_STS_MRDY_SHIFT 18
+#define TPC0_QM_CP_STS_MRDY_MASK 0x40000
+#define TPC0_QM_CP_STS_SW_STOP_SHIFT 19
+#define TPC0_QM_CP_STS_SW_STOP_MASK 0x80000
+#define TPC0_QM_CP_STS_FENCE_ID_SHIFT 20
+#define TPC0_QM_CP_STS_FENCE_ID_MASK 0x300000
+#define TPC0_QM_CP_STS_FENCE_IN_PROGRESS_SHIFT 22
+#define TPC0_QM_CP_STS_FENCE_IN_PROGRESS_MASK 0x400000
+
+/* TPC0_QM_CP_CURRENT_INST_LO */
+#define TPC0_QM_CP_CURRENT_INST_LO_VAL_SHIFT 0
+#define TPC0_QM_CP_CURRENT_INST_LO_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_CURRENT_INST_HI */
+#define TPC0_QM_CP_CURRENT_INST_HI_VAL_SHIFT 0
+#define TPC0_QM_CP_CURRENT_INST_HI_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CP_BARRIER_CFG */
+#define TPC0_QM_CP_BARRIER_CFG_EBGUARD_SHIFT 0
+#define TPC0_QM_CP_BARRIER_CFG_EBGUARD_MASK 0xFFF
+
+/* TPC0_QM_CP_DBG_0 */
+#define TPC0_QM_CP_DBG_0_VAL_SHIFT 0
+#define TPC0_QM_CP_DBG_0_VAL_MASK 0xFF
+
+/* TPC0_QM_PQ_BUF_ADDR */
+#define TPC0_QM_PQ_BUF_ADDR_VAL_SHIFT 0
+#define TPC0_QM_PQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_PQ_BUF_RDATA */
+#define TPC0_QM_PQ_BUF_RDATA_VAL_SHIFT 0
+#define TPC0_QM_PQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_BUF_ADDR */
+#define TPC0_QM_CQ_BUF_ADDR_VAL_SHIFT 0
+#define TPC0_QM_CQ_BUF_ADDR_VAL_MASK 0xFFFFFFFF
+
+/* TPC0_QM_CQ_BUF_RDATA */
+#define TPC0_QM_CQ_BUF_RDATA_VAL_SHIFT 0
+#define TPC0_QM_CQ_BUF_RDATA_VAL_MASK 0xFFFFFFFF
+
+#endif /* ASIC_REG_TPC0_QM_MASKS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h
new file mode 100644
index 000000000000..7552d4ba61fe
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc0_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC0_QM_REGS_H_
+#define ASIC_REG_TPC0_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC0_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC0_QM_GLBL_CFG0 0xE08000
+
+#define mmTPC0_QM_GLBL_CFG1 0xE08004
+
+#define mmTPC0_QM_GLBL_PROT 0xE08008
+
+#define mmTPC0_QM_GLBL_ERR_CFG 0xE0800C
+
+#define mmTPC0_QM_GLBL_ERR_ADDR_LO 0xE08010
+
+#define mmTPC0_QM_GLBL_ERR_ADDR_HI 0xE08014
+
+#define mmTPC0_QM_GLBL_ERR_WDATA 0xE08018
+
+#define mmTPC0_QM_GLBL_SECURE_PROPS 0xE0801C
+
+#define mmTPC0_QM_GLBL_NON_SECURE_PROPS 0xE08020
+
+#define mmTPC0_QM_GLBL_STS0 0xE08024
+
+#define mmTPC0_QM_GLBL_STS1 0xE08028
+
+#define mmTPC0_QM_PQ_BASE_LO 0xE08060
+
+#define mmTPC0_QM_PQ_BASE_HI 0xE08064
+
+#define mmTPC0_QM_PQ_SIZE 0xE08068
+
+#define mmTPC0_QM_PQ_PI 0xE0806C
+
+#define mmTPC0_QM_PQ_CI 0xE08070
+
+#define mmTPC0_QM_PQ_CFG0 0xE08074
+
+#define mmTPC0_QM_PQ_CFG1 0xE08078
+
+#define mmTPC0_QM_PQ_ARUSER 0xE0807C
+
+#define mmTPC0_QM_PQ_PUSH0 0xE08080
+
+#define mmTPC0_QM_PQ_PUSH1 0xE08084
+
+#define mmTPC0_QM_PQ_PUSH2 0xE08088
+
+#define mmTPC0_QM_PQ_PUSH3 0xE0808C
+
+#define mmTPC0_QM_PQ_STS0 0xE08090
+
+#define mmTPC0_QM_PQ_STS1 0xE08094
+
+#define mmTPC0_QM_PQ_RD_RATE_LIM_EN 0xE080A0
+
+#define mmTPC0_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xE080A4
+
+#define mmTPC0_QM_PQ_RD_RATE_LIM_SAT 0xE080A8
+
+#define mmTPC0_QM_PQ_RD_RATE_LIM_TOUT 0xE080AC
+
+#define mmTPC0_QM_CQ_CFG0 0xE080B0
+
+#define mmTPC0_QM_CQ_CFG1 0xE080B4
+
+#define mmTPC0_QM_CQ_ARUSER 0xE080B8
+
+#define mmTPC0_QM_CQ_PTR_LO 0xE080C0
+
+#define mmTPC0_QM_CQ_PTR_HI 0xE080C4
+
+#define mmTPC0_QM_CQ_TSIZE 0xE080C8
+
+#define mmTPC0_QM_CQ_CTL 0xE080CC
+
+#define mmTPC0_QM_CQ_PTR_LO_STS 0xE080D4
+
+#define mmTPC0_QM_CQ_PTR_HI_STS 0xE080D8
+
+#define mmTPC0_QM_CQ_TSIZE_STS 0xE080DC
+
+#define mmTPC0_QM_CQ_CTL_STS 0xE080E0
+
+#define mmTPC0_QM_CQ_STS0 0xE080E4
+
+#define mmTPC0_QM_CQ_STS1 0xE080E8
+
+#define mmTPC0_QM_CQ_RD_RATE_LIM_EN 0xE080F0
+
+#define mmTPC0_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xE080F4
+
+#define mmTPC0_QM_CQ_RD_RATE_LIM_SAT 0xE080F8
+
+#define mmTPC0_QM_CQ_RD_RATE_LIM_TOUT 0xE080FC
+
+#define mmTPC0_QM_CQ_IFIFO_CNT 0xE08108
+
+#define mmTPC0_QM_CP_MSG_BASE0_ADDR_LO 0xE08120
+
+#define mmTPC0_QM_CP_MSG_BASE0_ADDR_HI 0xE08124
+
+#define mmTPC0_QM_CP_MSG_BASE1_ADDR_LO 0xE08128
+
+#define mmTPC0_QM_CP_MSG_BASE1_ADDR_HI 0xE0812C
+
+#define mmTPC0_QM_CP_MSG_BASE2_ADDR_LO 0xE08130
+
+#define mmTPC0_QM_CP_MSG_BASE2_ADDR_HI 0xE08134
+
+#define mmTPC0_QM_CP_MSG_BASE3_ADDR_LO 0xE08138
+
+#define mmTPC0_QM_CP_MSG_BASE3_ADDR_HI 0xE0813C
+
+#define mmTPC0_QM_CP_LDMA_TSIZE_OFFSET 0xE08140
+
+#define mmTPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xE08144
+
+#define mmTPC0_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xE08148
+
+#define mmTPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xE0814C
+
+#define mmTPC0_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xE08150
+
+#define mmTPC0_QM_CP_LDMA_COMMIT_OFFSET 0xE08154
+
+#define mmTPC0_QM_CP_FENCE0_RDATA 0xE08158
+
+#define mmTPC0_QM_CP_FENCE1_RDATA 0xE0815C
+
+#define mmTPC0_QM_CP_FENCE2_RDATA 0xE08160
+
+#define mmTPC0_QM_CP_FENCE3_RDATA 0xE08164
+
+#define mmTPC0_QM_CP_FENCE0_CNT 0xE08168
+
+#define mmTPC0_QM_CP_FENCE1_CNT 0xE0816C
+
+#define mmTPC0_QM_CP_FENCE2_CNT 0xE08170
+
+#define mmTPC0_QM_CP_FENCE3_CNT 0xE08174
+
+#define mmTPC0_QM_CP_STS 0xE08178
+
+#define mmTPC0_QM_CP_CURRENT_INST_LO 0xE0817C
+
+#define mmTPC0_QM_CP_CURRENT_INST_HI 0xE08180
+
+#define mmTPC0_QM_CP_BARRIER_CFG 0xE08184
+
+#define mmTPC0_QM_CP_DBG_0 0xE08188
+
+#define mmTPC0_QM_PQ_BUF_ADDR 0xE08300
+
+#define mmTPC0_QM_PQ_BUF_RDATA 0xE08304
+
+#define mmTPC0_QM_CQ_BUF_ADDR 0xE08308
+
+#define mmTPC0_QM_CQ_BUF_RDATA 0xE0830C
+
+#endif /* ASIC_REG_TPC0_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h
new file mode 100644
index 000000000000..19894413474a
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC1_CFG_REGS_H_
+#define ASIC_REG_TPC1_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC1_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xE46400
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xE46404
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xE46408
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xE4640C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xE46410
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xE46414
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xE46418
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xE4641C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xE46420
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xE46424
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xE46428
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xE4642C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xE46430
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xE46434
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xE46438
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xE4643C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xE46440
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xE46444
+
+#define mmTPC1_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xE46448
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xE4644C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xE46450
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xE46454
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xE46458
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xE4645C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xE46460
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xE46464
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xE46468
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xE4646C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xE46470
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xE46474
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xE46478
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xE4647C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xE46480
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xE46484
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xE46488
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xE4648C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xE46490
+
+#define mmTPC1_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xE46494
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xE46498
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xE4649C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xE464A0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xE464A4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xE464A8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xE464AC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xE464B0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xE464B4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xE464B8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xE464BC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xE464C0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xE464C4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xE464C8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xE464CC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xE464D0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xE464D4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xE464D8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xE464DC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xE464E0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xE464E4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xE464E8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xE464EC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xE464F0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xE464F4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xE464F8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xE464FC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xE46500
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xE46504
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xE46508
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xE4650C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xE46510
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xE46514
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xE46518
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xE4651C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xE46520
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xE46524
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xE46528
+
+#define mmTPC1_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xE4652C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xE46530
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xE46534
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xE46538
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xE4653C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xE46540
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xE46544
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xE46548
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xE4654C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xE46550
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xE46554
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xE46558
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xE4655C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xE46560
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xE46564
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xE46568
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xE4656C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xE46570
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xE46574
+
+#define mmTPC1_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xE46578
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xE4657C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xE46580
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xE46584
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xE46588
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xE4658C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xE46590
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xE46594
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xE46598
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xE4659C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xE465A0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xE465A4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xE465A8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xE465AC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xE465B0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xE465B4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xE465B8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xE465BC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xE465C0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xE465C4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xE465C8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xE465CC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xE465D0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xE465D4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xE465D8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xE465DC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xE465E0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xE465E4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xE465E8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xE465EC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xE465F0
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xE465F4
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xE465F8
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xE465FC
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xE46600
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xE46604
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xE46608
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xE4660C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xE46610
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xE46614
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xE46618
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xE4661C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xE46620
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xE46624
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xE46628
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xE4662C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xE46630
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xE46634
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xE46638
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xE4663C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xE46640
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xE46644
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xE46648
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xE4664C
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xE46650
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xE46654
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xE46658
+
+#define mmTPC1_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xE4665C
+
+#define mmTPC1_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xE46660
+
+#define mmTPC1_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xE46664
+
+#define mmTPC1_CFG_KERNEL_TID_BASE_DIM_0 0xE46668
+
+#define mmTPC1_CFG_KERNEL_TID_SIZE_DIM_0 0xE4666C
+
+#define mmTPC1_CFG_KERNEL_TID_BASE_DIM_1 0xE46670
+
+#define mmTPC1_CFG_KERNEL_TID_SIZE_DIM_1 0xE46674
+
+#define mmTPC1_CFG_KERNEL_TID_BASE_DIM_2 0xE46678
+
+#define mmTPC1_CFG_KERNEL_TID_SIZE_DIM_2 0xE4667C
+
+#define mmTPC1_CFG_KERNEL_TID_BASE_DIM_3 0xE46680
+
+#define mmTPC1_CFG_KERNEL_TID_SIZE_DIM_3 0xE46684
+
+#define mmTPC1_CFG_KERNEL_TID_BASE_DIM_4 0xE46688
+
+#define mmTPC1_CFG_KERNEL_TID_SIZE_DIM_4 0xE4668C
+
+#define mmTPC1_CFG_KERNEL_SRF_0 0xE46690
+
+#define mmTPC1_CFG_KERNEL_SRF_1 0xE46694
+
+#define mmTPC1_CFG_KERNEL_SRF_2 0xE46698
+
+#define mmTPC1_CFG_KERNEL_SRF_3 0xE4669C
+
+#define mmTPC1_CFG_KERNEL_SRF_4 0xE466A0
+
+#define mmTPC1_CFG_KERNEL_SRF_5 0xE466A4
+
+#define mmTPC1_CFG_KERNEL_SRF_6 0xE466A8
+
+#define mmTPC1_CFG_KERNEL_SRF_7 0xE466AC
+
+#define mmTPC1_CFG_KERNEL_SRF_8 0xE466B0
+
+#define mmTPC1_CFG_KERNEL_SRF_9 0xE466B4
+
+#define mmTPC1_CFG_KERNEL_SRF_10 0xE466B8
+
+#define mmTPC1_CFG_KERNEL_SRF_11 0xE466BC
+
+#define mmTPC1_CFG_KERNEL_SRF_12 0xE466C0
+
+#define mmTPC1_CFG_KERNEL_SRF_13 0xE466C4
+
+#define mmTPC1_CFG_KERNEL_SRF_14 0xE466C8
+
+#define mmTPC1_CFG_KERNEL_SRF_15 0xE466CC
+
+#define mmTPC1_CFG_KERNEL_SRF_16 0xE466D0
+
+#define mmTPC1_CFG_KERNEL_SRF_17 0xE466D4
+
+#define mmTPC1_CFG_KERNEL_SRF_18 0xE466D8
+
+#define mmTPC1_CFG_KERNEL_SRF_19 0xE466DC
+
+#define mmTPC1_CFG_KERNEL_SRF_20 0xE466E0
+
+#define mmTPC1_CFG_KERNEL_SRF_21 0xE466E4
+
+#define mmTPC1_CFG_KERNEL_SRF_22 0xE466E8
+
+#define mmTPC1_CFG_KERNEL_SRF_23 0xE466EC
+
+#define mmTPC1_CFG_KERNEL_SRF_24 0xE466F0
+
+#define mmTPC1_CFG_KERNEL_SRF_25 0xE466F4
+
+#define mmTPC1_CFG_KERNEL_SRF_26 0xE466F8
+
+#define mmTPC1_CFG_KERNEL_SRF_27 0xE466FC
+
+#define mmTPC1_CFG_KERNEL_SRF_28 0xE46700
+
+#define mmTPC1_CFG_KERNEL_SRF_29 0xE46704
+
+#define mmTPC1_CFG_KERNEL_SRF_30 0xE46708
+
+#define mmTPC1_CFG_KERNEL_SRF_31 0xE4670C
+
+#define mmTPC1_CFG_KERNEL_KERNEL_CONFIG 0xE46710
+
+#define mmTPC1_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xE46714
+
+#define mmTPC1_CFG_RESERVED_DESC_END 0xE46738
+
+#define mmTPC1_CFG_ROUND_CSR 0xE467FC
+
+#define mmTPC1_CFG_TBUF_BASE_ADDR_LOW 0xE46800
+
+#define mmTPC1_CFG_TBUF_BASE_ADDR_HIGH 0xE46804
+
+#define mmTPC1_CFG_SEMAPHORE 0xE46808
+
+#define mmTPC1_CFG_VFLAGS 0xE4680C
+
+#define mmTPC1_CFG_SFLAGS 0xE46810
+
+#define mmTPC1_CFG_LFSR_POLYNOM 0xE46818
+
+#define mmTPC1_CFG_STATUS 0xE4681C
+
+#define mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH 0xE46820
+
+#define mmTPC1_CFG_CFG_SUBTRACT_VALUE 0xE46824
+
+#define mmTPC1_CFG_SM_BASE_ADDRESS_LOW 0xE46828
+
+#define mmTPC1_CFG_SM_BASE_ADDRESS_HIGH 0xE4682C
+
+#define mmTPC1_CFG_TPC_CMD 0xE46830
+
+#define mmTPC1_CFG_TPC_EXECUTE 0xE46838
+
+#define mmTPC1_CFG_TPC_STALL 0xE4683C
+
+#define mmTPC1_CFG_ICACHE_BASE_ADDERESS_LOW 0xE46840
+
+#define mmTPC1_CFG_ICACHE_BASE_ADDERESS_HIGH 0xE46844
+
+#define mmTPC1_CFG_MSS_CONFIG 0xE46854
+
+#define mmTPC1_CFG_TPC_INTR_CAUSE 0xE46858
+
+#define mmTPC1_CFG_TPC_INTR_MASK 0xE4685C
+
+#define mmTPC1_CFG_TSB_CONFIG 0xE46860
+
+#define mmTPC1_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xE46A00
+
+#define mmTPC1_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xE46A04
+
+#define mmTPC1_CFG_QM_TENSOR_0_PADDING_VALUE 0xE46A08
+
+#define mmTPC1_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xE46A0C
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_0_SIZE 0xE46A10
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xE46A14
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xE46A18
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_1_SIZE 0xE46A1C
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xE46A20
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xE46A24
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_2_SIZE 0xE46A28
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xE46A2C
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xE46A30
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_3_SIZE 0xE46A34
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xE46A38
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xE46A3C
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_4_SIZE 0xE46A40
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xE46A44
+
+#define mmTPC1_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xE46A48
+
+#define mmTPC1_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xE46A4C
+
+#define mmTPC1_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xE46A50
+
+#define mmTPC1_CFG_QM_TENSOR_1_PADDING_VALUE 0xE46A54
+
+#define mmTPC1_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xE46A58
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_0_SIZE 0xE46A5C
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xE46A60
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xE46A64
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_1_SIZE 0xE46A68
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xE46A6C
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xE46A70
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_2_SIZE 0xE46A74
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xE46A78
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xE46A7C
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_3_SIZE 0xE46A80
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xE46A84
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xE46A88
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_4_SIZE 0xE46A8C
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xE46A90
+
+#define mmTPC1_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xE46A94
+
+#define mmTPC1_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xE46A98
+
+#define mmTPC1_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xE46A9C
+
+#define mmTPC1_CFG_QM_TENSOR_2_PADDING_VALUE 0xE46AA0
+
+#define mmTPC1_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xE46AA4
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_0_SIZE 0xE46AA8
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xE46AAC
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xE46AB0
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_1_SIZE 0xE46AB4
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xE46AB8
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xE46ABC
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_2_SIZE 0xE46AC0
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xE46AC4
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xE46AC8
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_3_SIZE 0xE46ACC
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xE46AD0
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xE46AD4
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_4_SIZE 0xE46AD8
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xE46ADC
+
+#define mmTPC1_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xE46AE0
+
+#define mmTPC1_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xE46AE4
+
+#define mmTPC1_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xE46AE8
+
+#define mmTPC1_CFG_QM_TENSOR_3_PADDING_VALUE 0xE46AEC
+
+#define mmTPC1_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xE46AF0
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_0_SIZE 0xE46AF4
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xE46AF8
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xE46AFC
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_1_SIZE 0xE46B00
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xE46B04
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xE46B08
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_2_SIZE 0xE46B0C
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xE46B10
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xE46B14
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_3_SIZE 0xE46B18
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xE46B1C
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xE46B20
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_4_SIZE 0xE46B24
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xE46B28
+
+#define mmTPC1_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xE46B2C
+
+#define mmTPC1_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xE46B30
+
+#define mmTPC1_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xE46B34
+
+#define mmTPC1_CFG_QM_TENSOR_4_PADDING_VALUE 0xE46B38
+
+#define mmTPC1_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xE46B3C
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_0_SIZE 0xE46B40
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xE46B44
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xE46B48
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_1_SIZE 0xE46B4C
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xE46B50
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xE46B54
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_2_SIZE 0xE46B58
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xE46B5C
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xE46B60
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_3_SIZE 0xE46B64
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xE46B68
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xE46B6C
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_4_SIZE 0xE46B70
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xE46B74
+
+#define mmTPC1_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xE46B78
+
+#define mmTPC1_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xE46B7C
+
+#define mmTPC1_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xE46B80
+
+#define mmTPC1_CFG_QM_TENSOR_5_PADDING_VALUE 0xE46B84
+
+#define mmTPC1_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xE46B88
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_0_SIZE 0xE46B8C
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xE46B90
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xE46B94
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_1_SIZE 0xE46B98
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xE46B9C
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xE46BA0
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_2_SIZE 0xE46BA4
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xE46BA8
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xE46BAC
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_3_SIZE 0xE46BB0
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xE46BB4
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xE46BB8
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_4_SIZE 0xE46BBC
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xE46BC0
+
+#define mmTPC1_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xE46BC4
+
+#define mmTPC1_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xE46BC8
+
+#define mmTPC1_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xE46BCC
+
+#define mmTPC1_CFG_QM_TENSOR_6_PADDING_VALUE 0xE46BD0
+
+#define mmTPC1_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xE46BD4
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_0_SIZE 0xE46BD8
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xE46BDC
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xE46BE0
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_1_SIZE 0xE46BE4
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xE46BE8
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xE46BEC
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_2_SIZE 0xE46BF0
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xE46BF4
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xE46BF8
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_3_SIZE 0xE46BFC
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xE46C00
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xE46C04
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_4_SIZE 0xE46C08
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xE46C0C
+
+#define mmTPC1_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xE46C10
+
+#define mmTPC1_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xE46C14
+
+#define mmTPC1_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xE46C18
+
+#define mmTPC1_CFG_QM_TENSOR_7_PADDING_VALUE 0xE46C1C
+
+#define mmTPC1_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xE46C20
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_0_SIZE 0xE46C24
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xE46C28
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xE46C2C
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_1_SIZE 0xE46C30
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xE46C34
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xE46C38
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_2_SIZE 0xE46C3C
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xE46C40
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xE46C44
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_3_SIZE 0xE46C48
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xE46C4C
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xE46C50
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_4_SIZE 0xE46C54
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xE46C58
+
+#define mmTPC1_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xE46C5C
+
+#define mmTPC1_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xE46C60
+
+#define mmTPC1_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xE46C64
+
+#define mmTPC1_CFG_QM_TID_BASE_DIM_0 0xE46C68
+
+#define mmTPC1_CFG_QM_TID_SIZE_DIM_0 0xE46C6C
+
+#define mmTPC1_CFG_QM_TID_BASE_DIM_1 0xE46C70
+
+#define mmTPC1_CFG_QM_TID_SIZE_DIM_1 0xE46C74
+
+#define mmTPC1_CFG_QM_TID_BASE_DIM_2 0xE46C78
+
+#define mmTPC1_CFG_QM_TID_SIZE_DIM_2 0xE46C7C
+
+#define mmTPC1_CFG_QM_TID_BASE_DIM_3 0xE46C80
+
+#define mmTPC1_CFG_QM_TID_SIZE_DIM_3 0xE46C84
+
+#define mmTPC1_CFG_QM_TID_BASE_DIM_4 0xE46C88
+
+#define mmTPC1_CFG_QM_TID_SIZE_DIM_4 0xE46C8C
+
+#define mmTPC1_CFG_QM_SRF_0 0xE46C90
+
+#define mmTPC1_CFG_QM_SRF_1 0xE46C94
+
+#define mmTPC1_CFG_QM_SRF_2 0xE46C98
+
+#define mmTPC1_CFG_QM_SRF_3 0xE46C9C
+
+#define mmTPC1_CFG_QM_SRF_4 0xE46CA0
+
+#define mmTPC1_CFG_QM_SRF_5 0xE46CA4
+
+#define mmTPC1_CFG_QM_SRF_6 0xE46CA8
+
+#define mmTPC1_CFG_QM_SRF_7 0xE46CAC
+
+#define mmTPC1_CFG_QM_SRF_8 0xE46CB0
+
+#define mmTPC1_CFG_QM_SRF_9 0xE46CB4
+
+#define mmTPC1_CFG_QM_SRF_10 0xE46CB8
+
+#define mmTPC1_CFG_QM_SRF_11 0xE46CBC
+
+#define mmTPC1_CFG_QM_SRF_12 0xE46CC0
+
+#define mmTPC1_CFG_QM_SRF_13 0xE46CC4
+
+#define mmTPC1_CFG_QM_SRF_14 0xE46CC8
+
+#define mmTPC1_CFG_QM_SRF_15 0xE46CCC
+
+#define mmTPC1_CFG_QM_SRF_16 0xE46CD0
+
+#define mmTPC1_CFG_QM_SRF_17 0xE46CD4
+
+#define mmTPC1_CFG_QM_SRF_18 0xE46CD8
+
+#define mmTPC1_CFG_QM_SRF_19 0xE46CDC
+
+#define mmTPC1_CFG_QM_SRF_20 0xE46CE0
+
+#define mmTPC1_CFG_QM_SRF_21 0xE46CE4
+
+#define mmTPC1_CFG_QM_SRF_22 0xE46CE8
+
+#define mmTPC1_CFG_QM_SRF_23 0xE46CEC
+
+#define mmTPC1_CFG_QM_SRF_24 0xE46CF0
+
+#define mmTPC1_CFG_QM_SRF_25 0xE46CF4
+
+#define mmTPC1_CFG_QM_SRF_26 0xE46CF8
+
+#define mmTPC1_CFG_QM_SRF_27 0xE46CFC
+
+#define mmTPC1_CFG_QM_SRF_28 0xE46D00
+
+#define mmTPC1_CFG_QM_SRF_29 0xE46D04
+
+#define mmTPC1_CFG_QM_SRF_30 0xE46D08
+
+#define mmTPC1_CFG_QM_SRF_31 0xE46D0C
+
+#define mmTPC1_CFG_QM_KERNEL_CONFIG 0xE46D10
+
+#define mmTPC1_CFG_QM_SYNC_OBJECT_MESSAGE 0xE46D14
+
+#define mmTPC1_CFG_ARUSER 0xE46D18
+
+#define mmTPC1_CFG_AWUSER 0xE46D1C
+
+#define mmTPC1_CFG_FUNC_MBIST_CNTRL 0xE46E00
+
+#define mmTPC1_CFG_FUNC_MBIST_PAT 0xE46E04
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_0 0xE46E08
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_1 0xE46E0C
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_2 0xE46E10
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_3 0xE46E14
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_4 0xE46E18
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_5 0xE46E1C
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_6 0xE46E20
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_7 0xE46E24
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_8 0xE46E28
+
+#define mmTPC1_CFG_FUNC_MBIST_MEM_9 0xE46E2C
+
+#endif /* ASIC_REG_TPC1_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h
new file mode 100644
index 000000000000..9099ebd7ab23
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC1_CMDQ_REGS_H_
+#define ASIC_REG_TPC1_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC1_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC1_CMDQ_GLBL_CFG0 0xE49000
+
+#define mmTPC1_CMDQ_GLBL_CFG1 0xE49004
+
+#define mmTPC1_CMDQ_GLBL_PROT 0xE49008
+
+#define mmTPC1_CMDQ_GLBL_ERR_CFG 0xE4900C
+
+#define mmTPC1_CMDQ_GLBL_ERR_ADDR_LO 0xE49010
+
+#define mmTPC1_CMDQ_GLBL_ERR_ADDR_HI 0xE49014
+
+#define mmTPC1_CMDQ_GLBL_ERR_WDATA 0xE49018
+
+#define mmTPC1_CMDQ_GLBL_SECURE_PROPS 0xE4901C
+
+#define mmTPC1_CMDQ_GLBL_NON_SECURE_PROPS 0xE49020
+
+#define mmTPC1_CMDQ_GLBL_STS0 0xE49024
+
+#define mmTPC1_CMDQ_GLBL_STS1 0xE49028
+
+#define mmTPC1_CMDQ_CQ_CFG0 0xE490B0
+
+#define mmTPC1_CMDQ_CQ_CFG1 0xE490B4
+
+#define mmTPC1_CMDQ_CQ_ARUSER 0xE490B8
+
+#define mmTPC1_CMDQ_CQ_PTR_LO 0xE490C0
+
+#define mmTPC1_CMDQ_CQ_PTR_HI 0xE490C4
+
+#define mmTPC1_CMDQ_CQ_TSIZE 0xE490C8
+
+#define mmTPC1_CMDQ_CQ_CTL 0xE490CC
+
+#define mmTPC1_CMDQ_CQ_PTR_LO_STS 0xE490D4
+
+#define mmTPC1_CMDQ_CQ_PTR_HI_STS 0xE490D8
+
+#define mmTPC1_CMDQ_CQ_TSIZE_STS 0xE490DC
+
+#define mmTPC1_CMDQ_CQ_CTL_STS 0xE490E0
+
+#define mmTPC1_CMDQ_CQ_STS0 0xE490E4
+
+#define mmTPC1_CMDQ_CQ_STS1 0xE490E8
+
+#define mmTPC1_CMDQ_CQ_RD_RATE_LIM_EN 0xE490F0
+
+#define mmTPC1_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xE490F4
+
+#define mmTPC1_CMDQ_CQ_RD_RATE_LIM_SAT 0xE490F8
+
+#define mmTPC1_CMDQ_CQ_RD_RATE_LIM_TOUT 0xE490FC
+
+#define mmTPC1_CMDQ_CQ_IFIFO_CNT 0xE49108
+
+#define mmTPC1_CMDQ_CP_MSG_BASE0_ADDR_LO 0xE49120
+
+#define mmTPC1_CMDQ_CP_MSG_BASE0_ADDR_HI 0xE49124
+
+#define mmTPC1_CMDQ_CP_MSG_BASE1_ADDR_LO 0xE49128
+
+#define mmTPC1_CMDQ_CP_MSG_BASE1_ADDR_HI 0xE4912C
+
+#define mmTPC1_CMDQ_CP_MSG_BASE2_ADDR_LO 0xE49130
+
+#define mmTPC1_CMDQ_CP_MSG_BASE2_ADDR_HI 0xE49134
+
+#define mmTPC1_CMDQ_CP_MSG_BASE3_ADDR_LO 0xE49138
+
+#define mmTPC1_CMDQ_CP_MSG_BASE3_ADDR_HI 0xE4913C
+
+#define mmTPC1_CMDQ_CP_LDMA_TSIZE_OFFSET 0xE49140
+
+#define mmTPC1_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xE49144
+
+#define mmTPC1_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xE49148
+
+#define mmTPC1_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xE4914C
+
+#define mmTPC1_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xE49150
+
+#define mmTPC1_CMDQ_CP_LDMA_COMMIT_OFFSET 0xE49154
+
+#define mmTPC1_CMDQ_CP_FENCE0_RDATA 0xE49158
+
+#define mmTPC1_CMDQ_CP_FENCE1_RDATA 0xE4915C
+
+#define mmTPC1_CMDQ_CP_FENCE2_RDATA 0xE49160
+
+#define mmTPC1_CMDQ_CP_FENCE3_RDATA 0xE49164
+
+#define mmTPC1_CMDQ_CP_FENCE0_CNT 0xE49168
+
+#define mmTPC1_CMDQ_CP_FENCE1_CNT 0xE4916C
+
+#define mmTPC1_CMDQ_CP_FENCE2_CNT 0xE49170
+
+#define mmTPC1_CMDQ_CP_FENCE3_CNT 0xE49174
+
+#define mmTPC1_CMDQ_CP_STS 0xE49178
+
+#define mmTPC1_CMDQ_CP_CURRENT_INST_LO 0xE4917C
+
+#define mmTPC1_CMDQ_CP_CURRENT_INST_HI 0xE49180
+
+#define mmTPC1_CMDQ_CP_BARRIER_CFG 0xE49184
+
+#define mmTPC1_CMDQ_CP_DBG_0 0xE49188
+
+#define mmTPC1_CMDQ_CQ_BUF_ADDR 0xE49308
+
+#define mmTPC1_CMDQ_CQ_BUF_RDATA 0xE4930C
+
+#endif /* ASIC_REG_TPC1_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h
new file mode 100644
index 000000000000..bc8b9a10391f
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC1_QM_REGS_H_
+#define ASIC_REG_TPC1_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC1_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC1_QM_GLBL_CFG0 0xE48000
+
+#define mmTPC1_QM_GLBL_CFG1 0xE48004
+
+#define mmTPC1_QM_GLBL_PROT 0xE48008
+
+#define mmTPC1_QM_GLBL_ERR_CFG 0xE4800C
+
+#define mmTPC1_QM_GLBL_ERR_ADDR_LO 0xE48010
+
+#define mmTPC1_QM_GLBL_ERR_ADDR_HI 0xE48014
+
+#define mmTPC1_QM_GLBL_ERR_WDATA 0xE48018
+
+#define mmTPC1_QM_GLBL_SECURE_PROPS 0xE4801C
+
+#define mmTPC1_QM_GLBL_NON_SECURE_PROPS 0xE48020
+
+#define mmTPC1_QM_GLBL_STS0 0xE48024
+
+#define mmTPC1_QM_GLBL_STS1 0xE48028
+
+#define mmTPC1_QM_PQ_BASE_LO 0xE48060
+
+#define mmTPC1_QM_PQ_BASE_HI 0xE48064
+
+#define mmTPC1_QM_PQ_SIZE 0xE48068
+
+#define mmTPC1_QM_PQ_PI 0xE4806C
+
+#define mmTPC1_QM_PQ_CI 0xE48070
+
+#define mmTPC1_QM_PQ_CFG0 0xE48074
+
+#define mmTPC1_QM_PQ_CFG1 0xE48078
+
+#define mmTPC1_QM_PQ_ARUSER 0xE4807C
+
+#define mmTPC1_QM_PQ_PUSH0 0xE48080
+
+#define mmTPC1_QM_PQ_PUSH1 0xE48084
+
+#define mmTPC1_QM_PQ_PUSH2 0xE48088
+
+#define mmTPC1_QM_PQ_PUSH3 0xE4808C
+
+#define mmTPC1_QM_PQ_STS0 0xE48090
+
+#define mmTPC1_QM_PQ_STS1 0xE48094
+
+#define mmTPC1_QM_PQ_RD_RATE_LIM_EN 0xE480A0
+
+#define mmTPC1_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xE480A4
+
+#define mmTPC1_QM_PQ_RD_RATE_LIM_SAT 0xE480A8
+
+#define mmTPC1_QM_PQ_RD_RATE_LIM_TOUT 0xE480AC
+
+#define mmTPC1_QM_CQ_CFG0 0xE480B0
+
+#define mmTPC1_QM_CQ_CFG1 0xE480B4
+
+#define mmTPC1_QM_CQ_ARUSER 0xE480B8
+
+#define mmTPC1_QM_CQ_PTR_LO 0xE480C0
+
+#define mmTPC1_QM_CQ_PTR_HI 0xE480C4
+
+#define mmTPC1_QM_CQ_TSIZE 0xE480C8
+
+#define mmTPC1_QM_CQ_CTL 0xE480CC
+
+#define mmTPC1_QM_CQ_PTR_LO_STS 0xE480D4
+
+#define mmTPC1_QM_CQ_PTR_HI_STS 0xE480D8
+
+#define mmTPC1_QM_CQ_TSIZE_STS 0xE480DC
+
+#define mmTPC1_QM_CQ_CTL_STS 0xE480E0
+
+#define mmTPC1_QM_CQ_STS0 0xE480E4
+
+#define mmTPC1_QM_CQ_STS1 0xE480E8
+
+#define mmTPC1_QM_CQ_RD_RATE_LIM_EN 0xE480F0
+
+#define mmTPC1_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xE480F4
+
+#define mmTPC1_QM_CQ_RD_RATE_LIM_SAT 0xE480F8
+
+#define mmTPC1_QM_CQ_RD_RATE_LIM_TOUT 0xE480FC
+
+#define mmTPC1_QM_CQ_IFIFO_CNT 0xE48108
+
+#define mmTPC1_QM_CP_MSG_BASE0_ADDR_LO 0xE48120
+
+#define mmTPC1_QM_CP_MSG_BASE0_ADDR_HI 0xE48124
+
+#define mmTPC1_QM_CP_MSG_BASE1_ADDR_LO 0xE48128
+
+#define mmTPC1_QM_CP_MSG_BASE1_ADDR_HI 0xE4812C
+
+#define mmTPC1_QM_CP_MSG_BASE2_ADDR_LO 0xE48130
+
+#define mmTPC1_QM_CP_MSG_BASE2_ADDR_HI 0xE48134
+
+#define mmTPC1_QM_CP_MSG_BASE3_ADDR_LO 0xE48138
+
+#define mmTPC1_QM_CP_MSG_BASE3_ADDR_HI 0xE4813C
+
+#define mmTPC1_QM_CP_LDMA_TSIZE_OFFSET 0xE48140
+
+#define mmTPC1_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xE48144
+
+#define mmTPC1_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xE48148
+
+#define mmTPC1_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xE4814C
+
+#define mmTPC1_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xE48150
+
+#define mmTPC1_QM_CP_LDMA_COMMIT_OFFSET 0xE48154
+
+#define mmTPC1_QM_CP_FENCE0_RDATA 0xE48158
+
+#define mmTPC1_QM_CP_FENCE1_RDATA 0xE4815C
+
+#define mmTPC1_QM_CP_FENCE2_RDATA 0xE48160
+
+#define mmTPC1_QM_CP_FENCE3_RDATA 0xE48164
+
+#define mmTPC1_QM_CP_FENCE0_CNT 0xE48168
+
+#define mmTPC1_QM_CP_FENCE1_CNT 0xE4816C
+
+#define mmTPC1_QM_CP_FENCE2_CNT 0xE48170
+
+#define mmTPC1_QM_CP_FENCE3_CNT 0xE48174
+
+#define mmTPC1_QM_CP_STS 0xE48178
+
+#define mmTPC1_QM_CP_CURRENT_INST_LO 0xE4817C
+
+#define mmTPC1_QM_CP_CURRENT_INST_HI 0xE48180
+
+#define mmTPC1_QM_CP_BARRIER_CFG 0xE48184
+
+#define mmTPC1_QM_CP_DBG_0 0xE48188
+
+#define mmTPC1_QM_PQ_BUF_ADDR 0xE48300
+
+#define mmTPC1_QM_PQ_BUF_RDATA 0xE48304
+
+#define mmTPC1_QM_CQ_BUF_ADDR 0xE48308
+
+#define mmTPC1_QM_CQ_BUF_RDATA 0xE4830C
+
+#endif /* ASIC_REG_TPC1_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h
new file mode 100644
index 000000000000..ae267f8f457e
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc1_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC1_RTR_REGS_H_
+#define ASIC_REG_TPC1_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC1_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC1_RTR_HBW_RD_RQ_E_ARB 0xE40100
+
+#define mmTPC1_RTR_HBW_RD_RQ_W_ARB 0xE40104
+
+#define mmTPC1_RTR_HBW_RD_RQ_N_ARB 0xE40108
+
+#define mmTPC1_RTR_HBW_RD_RQ_S_ARB 0xE4010C
+
+#define mmTPC1_RTR_HBW_RD_RQ_L_ARB 0xE40110
+
+#define mmTPC1_RTR_HBW_E_ARB_MAX 0xE40120
+
+#define mmTPC1_RTR_HBW_W_ARB_MAX 0xE40124
+
+#define mmTPC1_RTR_HBW_N_ARB_MAX 0xE40128
+
+#define mmTPC1_RTR_HBW_S_ARB_MAX 0xE4012C
+
+#define mmTPC1_RTR_HBW_L_ARB_MAX 0xE40130
+
+#define mmTPC1_RTR_HBW_RD_RS_E_ARB 0xE40140
+
+#define mmTPC1_RTR_HBW_RD_RS_W_ARB 0xE40144
+
+#define mmTPC1_RTR_HBW_RD_RS_N_ARB 0xE40148
+
+#define mmTPC1_RTR_HBW_RD_RS_S_ARB 0xE4014C
+
+#define mmTPC1_RTR_HBW_RD_RS_L_ARB 0xE40150
+
+#define mmTPC1_RTR_HBW_WR_RQ_E_ARB 0xE40170
+
+#define mmTPC1_RTR_HBW_WR_RQ_W_ARB 0xE40174
+
+#define mmTPC1_RTR_HBW_WR_RQ_N_ARB 0xE40178
+
+#define mmTPC1_RTR_HBW_WR_RQ_S_ARB 0xE4017C
+
+#define mmTPC1_RTR_HBW_WR_RQ_L_ARB 0xE40180
+
+#define mmTPC1_RTR_HBW_WR_RS_E_ARB 0xE40190
+
+#define mmTPC1_RTR_HBW_WR_RS_W_ARB 0xE40194
+
+#define mmTPC1_RTR_HBW_WR_RS_N_ARB 0xE40198
+
+#define mmTPC1_RTR_HBW_WR_RS_S_ARB 0xE4019C
+
+#define mmTPC1_RTR_HBW_WR_RS_L_ARB 0xE401A0
+
+#define mmTPC1_RTR_LBW_RD_RQ_E_ARB 0xE40200
+
+#define mmTPC1_RTR_LBW_RD_RQ_W_ARB 0xE40204
+
+#define mmTPC1_RTR_LBW_RD_RQ_N_ARB 0xE40208
+
+#define mmTPC1_RTR_LBW_RD_RQ_S_ARB 0xE4020C
+
+#define mmTPC1_RTR_LBW_RD_RQ_L_ARB 0xE40210
+
+#define mmTPC1_RTR_LBW_E_ARB_MAX 0xE40220
+
+#define mmTPC1_RTR_LBW_W_ARB_MAX 0xE40224
+
+#define mmTPC1_RTR_LBW_N_ARB_MAX 0xE40228
+
+#define mmTPC1_RTR_LBW_S_ARB_MAX 0xE4022C
+
+#define mmTPC1_RTR_LBW_L_ARB_MAX 0xE40230
+
+#define mmTPC1_RTR_LBW_RD_RS_E_ARB 0xE40250
+
+#define mmTPC1_RTR_LBW_RD_RS_W_ARB 0xE40254
+
+#define mmTPC1_RTR_LBW_RD_RS_N_ARB 0xE40258
+
+#define mmTPC1_RTR_LBW_RD_RS_S_ARB 0xE4025C
+
+#define mmTPC1_RTR_LBW_RD_RS_L_ARB 0xE40260
+
+#define mmTPC1_RTR_LBW_WR_RQ_E_ARB 0xE40270
+
+#define mmTPC1_RTR_LBW_WR_RQ_W_ARB 0xE40274
+
+#define mmTPC1_RTR_LBW_WR_RQ_N_ARB 0xE40278
+
+#define mmTPC1_RTR_LBW_WR_RQ_S_ARB 0xE4027C
+
+#define mmTPC1_RTR_LBW_WR_RQ_L_ARB 0xE40280
+
+#define mmTPC1_RTR_LBW_WR_RS_E_ARB 0xE40290
+
+#define mmTPC1_RTR_LBW_WR_RS_W_ARB 0xE40294
+
+#define mmTPC1_RTR_LBW_WR_RS_N_ARB 0xE40298
+
+#define mmTPC1_RTR_LBW_WR_RS_S_ARB 0xE4029C
+
+#define mmTPC1_RTR_LBW_WR_RS_L_ARB 0xE402A0
+
+#define mmTPC1_RTR_DBG_E_ARB 0xE40300
+
+#define mmTPC1_RTR_DBG_W_ARB 0xE40304
+
+#define mmTPC1_RTR_DBG_N_ARB 0xE40308
+
+#define mmTPC1_RTR_DBG_S_ARB 0xE4030C
+
+#define mmTPC1_RTR_DBG_L_ARB 0xE40310
+
+#define mmTPC1_RTR_DBG_E_ARB_MAX 0xE40320
+
+#define mmTPC1_RTR_DBG_W_ARB_MAX 0xE40324
+
+#define mmTPC1_RTR_DBG_N_ARB_MAX 0xE40328
+
+#define mmTPC1_RTR_DBG_S_ARB_MAX 0xE4032C
+
+#define mmTPC1_RTR_DBG_L_ARB_MAX 0xE40330
+
+#define mmTPC1_RTR_SPLIT_COEF_0 0xE40400
+
+#define mmTPC1_RTR_SPLIT_COEF_1 0xE40404
+
+#define mmTPC1_RTR_SPLIT_COEF_2 0xE40408
+
+#define mmTPC1_RTR_SPLIT_COEF_3 0xE4040C
+
+#define mmTPC1_RTR_SPLIT_COEF_4 0xE40410
+
+#define mmTPC1_RTR_SPLIT_COEF_5 0xE40414
+
+#define mmTPC1_RTR_SPLIT_COEF_6 0xE40418
+
+#define mmTPC1_RTR_SPLIT_COEF_7 0xE4041C
+
+#define mmTPC1_RTR_SPLIT_COEF_8 0xE40420
+
+#define mmTPC1_RTR_SPLIT_COEF_9 0xE40424
+
+#define mmTPC1_RTR_SPLIT_CFG 0xE40440
+
+#define mmTPC1_RTR_SPLIT_RD_SAT 0xE40444
+
+#define mmTPC1_RTR_SPLIT_RD_RST_TOKEN 0xE40448
+
+#define mmTPC1_RTR_SPLIT_RD_TIMEOUT_0 0xE4044C
+
+#define mmTPC1_RTR_SPLIT_RD_TIMEOUT_1 0xE40450
+
+#define mmTPC1_RTR_SPLIT_WR_SAT 0xE40454
+
+#define mmTPC1_RTR_WPLIT_WR_TST_TOLEN 0xE40458
+
+#define mmTPC1_RTR_SPLIT_WR_TIMEOUT_0 0xE4045C
+
+#define mmTPC1_RTR_SPLIT_WR_TIMEOUT_1 0xE40460
+
+#define mmTPC1_RTR_HBW_RANGE_HIT 0xE40470
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_0 0xE40480
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_1 0xE40484
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_2 0xE40488
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_3 0xE4048C
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_4 0xE40490
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_5 0xE40494
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_6 0xE40498
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_L_7 0xE4049C
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_0 0xE404A0
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_1 0xE404A4
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_2 0xE404A8
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_3 0xE404AC
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_4 0xE404B0
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_5 0xE404B4
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_6 0xE404B8
+
+#define mmTPC1_RTR_HBW_RANGE_MASK_H_7 0xE404BC
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_0 0xE404C0
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_1 0xE404C4
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_2 0xE404C8
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_3 0xE404CC
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_4 0xE404D0
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_5 0xE404D4
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_6 0xE404D8
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_L_7 0xE404DC
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_0 0xE404E0
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_1 0xE404E4
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_2 0xE404E8
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_3 0xE404EC
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_4 0xE404F0
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_5 0xE404F4
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_6 0xE404F8
+
+#define mmTPC1_RTR_HBW_RANGE_BASE_H_7 0xE404FC
+
+#define mmTPC1_RTR_LBW_RANGE_HIT 0xE40500
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_0 0xE40510
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_1 0xE40514
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_2 0xE40518
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_3 0xE4051C
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_4 0xE40520
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_5 0xE40524
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_6 0xE40528
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_7 0xE4052C
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_8 0xE40530
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_9 0xE40534
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_10 0xE40538
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_11 0xE4053C
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_12 0xE40540
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_13 0xE40544
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_14 0xE40548
+
+#define mmTPC1_RTR_LBW_RANGE_MASK_15 0xE4054C
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_0 0xE40550
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_1 0xE40554
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_2 0xE40558
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_3 0xE4055C
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_4 0xE40560
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_5 0xE40564
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_6 0xE40568
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_7 0xE4056C
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_8 0xE40570
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_9 0xE40574
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_10 0xE40578
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_11 0xE4057C
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_12 0xE40580
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_13 0xE40584
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_14 0xE40588
+
+#define mmTPC1_RTR_LBW_RANGE_BASE_15 0xE4058C
+
+#define mmTPC1_RTR_RGLTR 0xE40590
+
+#define mmTPC1_RTR_RGLTR_WR_RESULT 0xE40594
+
+#define mmTPC1_RTR_RGLTR_RD_RESULT 0xE40598
+
+#define mmTPC1_RTR_SCRAMB_EN 0xE40600
+
+#define mmTPC1_RTR_NON_LIN_SCRAMB 0xE40604
+
+#endif /* ASIC_REG_TPC1_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h
new file mode 100644
index 000000000000..9c33fc039036
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC2_CFG_REGS_H_
+#define ASIC_REG_TPC2_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC2_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xE86400
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xE86404
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xE86408
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xE8640C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xE86410
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xE86414
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xE86418
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xE8641C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xE86420
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xE86424
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xE86428
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xE8642C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xE86430
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xE86434
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xE86438
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xE8643C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xE86440
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xE86444
+
+#define mmTPC2_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xE86448
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xE8644C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xE86450
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xE86454
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xE86458
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xE8645C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xE86460
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xE86464
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xE86468
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xE8646C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xE86470
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xE86474
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xE86478
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xE8647C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xE86480
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xE86484
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xE86488
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xE8648C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xE86490
+
+#define mmTPC2_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xE86494
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xE86498
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xE8649C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xE864A0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xE864A4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xE864A8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xE864AC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xE864B0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xE864B4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xE864B8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xE864BC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xE864C0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xE864C4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xE864C8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xE864CC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xE864D0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xE864D4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xE864D8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xE864DC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xE864E0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xE864E4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xE864E8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xE864EC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xE864F0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xE864F4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xE864F8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xE864FC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xE86500
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xE86504
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xE86508
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xE8650C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xE86510
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xE86514
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xE86518
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xE8651C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xE86520
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xE86524
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xE86528
+
+#define mmTPC2_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xE8652C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xE86530
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xE86534
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xE86538
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xE8653C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xE86540
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xE86544
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xE86548
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xE8654C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xE86550
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xE86554
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xE86558
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xE8655C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xE86560
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xE86564
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xE86568
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xE8656C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xE86570
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xE86574
+
+#define mmTPC2_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xE86578
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xE8657C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xE86580
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xE86584
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xE86588
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xE8658C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xE86590
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xE86594
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xE86598
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xE8659C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xE865A0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xE865A4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xE865A8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xE865AC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xE865B0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xE865B4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xE865B8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xE865BC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xE865C0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xE865C4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xE865C8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xE865CC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xE865D0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xE865D4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xE865D8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xE865DC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xE865E0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xE865E4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xE865E8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xE865EC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xE865F0
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xE865F4
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xE865F8
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xE865FC
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xE86600
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xE86604
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xE86608
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xE8660C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xE86610
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xE86614
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xE86618
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xE8661C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xE86620
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xE86624
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xE86628
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xE8662C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xE86630
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xE86634
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xE86638
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xE8663C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xE86640
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xE86644
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xE86648
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xE8664C
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xE86650
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xE86654
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xE86658
+
+#define mmTPC2_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xE8665C
+
+#define mmTPC2_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xE86660
+
+#define mmTPC2_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xE86664
+
+#define mmTPC2_CFG_KERNEL_TID_BASE_DIM_0 0xE86668
+
+#define mmTPC2_CFG_KERNEL_TID_SIZE_DIM_0 0xE8666C
+
+#define mmTPC2_CFG_KERNEL_TID_BASE_DIM_1 0xE86670
+
+#define mmTPC2_CFG_KERNEL_TID_SIZE_DIM_1 0xE86674
+
+#define mmTPC2_CFG_KERNEL_TID_BASE_DIM_2 0xE86678
+
+#define mmTPC2_CFG_KERNEL_TID_SIZE_DIM_2 0xE8667C
+
+#define mmTPC2_CFG_KERNEL_TID_BASE_DIM_3 0xE86680
+
+#define mmTPC2_CFG_KERNEL_TID_SIZE_DIM_3 0xE86684
+
+#define mmTPC2_CFG_KERNEL_TID_BASE_DIM_4 0xE86688
+
+#define mmTPC2_CFG_KERNEL_TID_SIZE_DIM_4 0xE8668C
+
+#define mmTPC2_CFG_KERNEL_SRF_0 0xE86690
+
+#define mmTPC2_CFG_KERNEL_SRF_1 0xE86694
+
+#define mmTPC2_CFG_KERNEL_SRF_2 0xE86698
+
+#define mmTPC2_CFG_KERNEL_SRF_3 0xE8669C
+
+#define mmTPC2_CFG_KERNEL_SRF_4 0xE866A0
+
+#define mmTPC2_CFG_KERNEL_SRF_5 0xE866A4
+
+#define mmTPC2_CFG_KERNEL_SRF_6 0xE866A8
+
+#define mmTPC2_CFG_KERNEL_SRF_7 0xE866AC
+
+#define mmTPC2_CFG_KERNEL_SRF_8 0xE866B0
+
+#define mmTPC2_CFG_KERNEL_SRF_9 0xE866B4
+
+#define mmTPC2_CFG_KERNEL_SRF_10 0xE866B8
+
+#define mmTPC2_CFG_KERNEL_SRF_11 0xE866BC
+
+#define mmTPC2_CFG_KERNEL_SRF_12 0xE866C0
+
+#define mmTPC2_CFG_KERNEL_SRF_13 0xE866C4
+
+#define mmTPC2_CFG_KERNEL_SRF_14 0xE866C8
+
+#define mmTPC2_CFG_KERNEL_SRF_15 0xE866CC
+
+#define mmTPC2_CFG_KERNEL_SRF_16 0xE866D0
+
+#define mmTPC2_CFG_KERNEL_SRF_17 0xE866D4
+
+#define mmTPC2_CFG_KERNEL_SRF_18 0xE866D8
+
+#define mmTPC2_CFG_KERNEL_SRF_19 0xE866DC
+
+#define mmTPC2_CFG_KERNEL_SRF_20 0xE866E0
+
+#define mmTPC2_CFG_KERNEL_SRF_21 0xE866E4
+
+#define mmTPC2_CFG_KERNEL_SRF_22 0xE866E8
+
+#define mmTPC2_CFG_KERNEL_SRF_23 0xE866EC
+
+#define mmTPC2_CFG_KERNEL_SRF_24 0xE866F0
+
+#define mmTPC2_CFG_KERNEL_SRF_25 0xE866F4
+
+#define mmTPC2_CFG_KERNEL_SRF_26 0xE866F8
+
+#define mmTPC2_CFG_KERNEL_SRF_27 0xE866FC
+
+#define mmTPC2_CFG_KERNEL_SRF_28 0xE86700
+
+#define mmTPC2_CFG_KERNEL_SRF_29 0xE86704
+
+#define mmTPC2_CFG_KERNEL_SRF_30 0xE86708
+
+#define mmTPC2_CFG_KERNEL_SRF_31 0xE8670C
+
+#define mmTPC2_CFG_KERNEL_KERNEL_CONFIG 0xE86710
+
+#define mmTPC2_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xE86714
+
+#define mmTPC2_CFG_RESERVED_DESC_END 0xE86738
+
+#define mmTPC2_CFG_ROUND_CSR 0xE867FC
+
+#define mmTPC2_CFG_TBUF_BASE_ADDR_LOW 0xE86800
+
+#define mmTPC2_CFG_TBUF_BASE_ADDR_HIGH 0xE86804
+
+#define mmTPC2_CFG_SEMAPHORE 0xE86808
+
+#define mmTPC2_CFG_VFLAGS 0xE8680C
+
+#define mmTPC2_CFG_SFLAGS 0xE86810
+
+#define mmTPC2_CFG_LFSR_POLYNOM 0xE86818
+
+#define mmTPC2_CFG_STATUS 0xE8681C
+
+#define mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH 0xE86820
+
+#define mmTPC2_CFG_CFG_SUBTRACT_VALUE 0xE86824
+
+#define mmTPC2_CFG_SM_BASE_ADDRESS_LOW 0xE86828
+
+#define mmTPC2_CFG_SM_BASE_ADDRESS_HIGH 0xE8682C
+
+#define mmTPC2_CFG_TPC_CMD 0xE86830
+
+#define mmTPC2_CFG_TPC_EXECUTE 0xE86838
+
+#define mmTPC2_CFG_TPC_STALL 0xE8683C
+
+#define mmTPC2_CFG_ICACHE_BASE_ADDERESS_LOW 0xE86840
+
+#define mmTPC2_CFG_ICACHE_BASE_ADDERESS_HIGH 0xE86844
+
+#define mmTPC2_CFG_MSS_CONFIG 0xE86854
+
+#define mmTPC2_CFG_TPC_INTR_CAUSE 0xE86858
+
+#define mmTPC2_CFG_TPC_INTR_MASK 0xE8685C
+
+#define mmTPC2_CFG_TSB_CONFIG 0xE86860
+
+#define mmTPC2_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xE86A00
+
+#define mmTPC2_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xE86A04
+
+#define mmTPC2_CFG_QM_TENSOR_0_PADDING_VALUE 0xE86A08
+
+#define mmTPC2_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xE86A0C
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_0_SIZE 0xE86A10
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xE86A14
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xE86A18
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_1_SIZE 0xE86A1C
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xE86A20
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xE86A24
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_2_SIZE 0xE86A28
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xE86A2C
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xE86A30
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_3_SIZE 0xE86A34
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xE86A38
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xE86A3C
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_4_SIZE 0xE86A40
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xE86A44
+
+#define mmTPC2_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xE86A48
+
+#define mmTPC2_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xE86A4C
+
+#define mmTPC2_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xE86A50
+
+#define mmTPC2_CFG_QM_TENSOR_1_PADDING_VALUE 0xE86A54
+
+#define mmTPC2_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xE86A58
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_0_SIZE 0xE86A5C
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xE86A60
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xE86A64
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_1_SIZE 0xE86A68
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xE86A6C
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xE86A70
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_2_SIZE 0xE86A74
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xE86A78
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xE86A7C
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_3_SIZE 0xE86A80
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xE86A84
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xE86A88
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_4_SIZE 0xE86A8C
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xE86A90
+
+#define mmTPC2_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xE86A94
+
+#define mmTPC2_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xE86A98
+
+#define mmTPC2_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xE86A9C
+
+#define mmTPC2_CFG_QM_TENSOR_2_PADDING_VALUE 0xE86AA0
+
+#define mmTPC2_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xE86AA4
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_0_SIZE 0xE86AA8
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xE86AAC
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xE86AB0
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_1_SIZE 0xE86AB4
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xE86AB8
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xE86ABC
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_2_SIZE 0xE86AC0
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xE86AC4
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xE86AC8
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_3_SIZE 0xE86ACC
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xE86AD0
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xE86AD4
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_4_SIZE 0xE86AD8
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xE86ADC
+
+#define mmTPC2_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xE86AE0
+
+#define mmTPC2_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xE86AE4
+
+#define mmTPC2_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xE86AE8
+
+#define mmTPC2_CFG_QM_TENSOR_3_PADDING_VALUE 0xE86AEC
+
+#define mmTPC2_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xE86AF0
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_0_SIZE 0xE86AF4
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xE86AF8
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xE86AFC
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_1_SIZE 0xE86B00
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xE86B04
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xE86B08
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_2_SIZE 0xE86B0C
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xE86B10
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xE86B14
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_3_SIZE 0xE86B18
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xE86B1C
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xE86B20
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_4_SIZE 0xE86B24
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xE86B28
+
+#define mmTPC2_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xE86B2C
+
+#define mmTPC2_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xE86B30
+
+#define mmTPC2_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xE86B34
+
+#define mmTPC2_CFG_QM_TENSOR_4_PADDING_VALUE 0xE86B38
+
+#define mmTPC2_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xE86B3C
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_0_SIZE 0xE86B40
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xE86B44
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xE86B48
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_1_SIZE 0xE86B4C
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xE86B50
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xE86B54
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_2_SIZE 0xE86B58
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xE86B5C
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xE86B60
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_3_SIZE 0xE86B64
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xE86B68
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xE86B6C
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_4_SIZE 0xE86B70
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xE86B74
+
+#define mmTPC2_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xE86B78
+
+#define mmTPC2_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xE86B7C
+
+#define mmTPC2_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xE86B80
+
+#define mmTPC2_CFG_QM_TENSOR_5_PADDING_VALUE 0xE86B84
+
+#define mmTPC2_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xE86B88
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_0_SIZE 0xE86B8C
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xE86B90
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xE86B94
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_1_SIZE 0xE86B98
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xE86B9C
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xE86BA0
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_2_SIZE 0xE86BA4
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xE86BA8
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xE86BAC
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_3_SIZE 0xE86BB0
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xE86BB4
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xE86BB8
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_4_SIZE 0xE86BBC
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xE86BC0
+
+#define mmTPC2_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xE86BC4
+
+#define mmTPC2_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xE86BC8
+
+#define mmTPC2_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xE86BCC
+
+#define mmTPC2_CFG_QM_TENSOR_6_PADDING_VALUE 0xE86BD0
+
+#define mmTPC2_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xE86BD4
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_0_SIZE 0xE86BD8
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xE86BDC
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xE86BE0
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_1_SIZE 0xE86BE4
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xE86BE8
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xE86BEC
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_2_SIZE 0xE86BF0
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xE86BF4
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xE86BF8
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_3_SIZE 0xE86BFC
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xE86C00
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xE86C04
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_4_SIZE 0xE86C08
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xE86C0C
+
+#define mmTPC2_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xE86C10
+
+#define mmTPC2_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xE86C14
+
+#define mmTPC2_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xE86C18
+
+#define mmTPC2_CFG_QM_TENSOR_7_PADDING_VALUE 0xE86C1C
+
+#define mmTPC2_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xE86C20
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_0_SIZE 0xE86C24
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xE86C28
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xE86C2C
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_1_SIZE 0xE86C30
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xE86C34
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xE86C38
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_2_SIZE 0xE86C3C
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xE86C40
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xE86C44
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_3_SIZE 0xE86C48
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xE86C4C
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xE86C50
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_4_SIZE 0xE86C54
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xE86C58
+
+#define mmTPC2_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xE86C5C
+
+#define mmTPC2_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xE86C60
+
+#define mmTPC2_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xE86C64
+
+#define mmTPC2_CFG_QM_TID_BASE_DIM_0 0xE86C68
+
+#define mmTPC2_CFG_QM_TID_SIZE_DIM_0 0xE86C6C
+
+#define mmTPC2_CFG_QM_TID_BASE_DIM_1 0xE86C70
+
+#define mmTPC2_CFG_QM_TID_SIZE_DIM_1 0xE86C74
+
+#define mmTPC2_CFG_QM_TID_BASE_DIM_2 0xE86C78
+
+#define mmTPC2_CFG_QM_TID_SIZE_DIM_2 0xE86C7C
+
+#define mmTPC2_CFG_QM_TID_BASE_DIM_3 0xE86C80
+
+#define mmTPC2_CFG_QM_TID_SIZE_DIM_3 0xE86C84
+
+#define mmTPC2_CFG_QM_TID_BASE_DIM_4 0xE86C88
+
+#define mmTPC2_CFG_QM_TID_SIZE_DIM_4 0xE86C8C
+
+#define mmTPC2_CFG_QM_SRF_0 0xE86C90
+
+#define mmTPC2_CFG_QM_SRF_1 0xE86C94
+
+#define mmTPC2_CFG_QM_SRF_2 0xE86C98
+
+#define mmTPC2_CFG_QM_SRF_3 0xE86C9C
+
+#define mmTPC2_CFG_QM_SRF_4 0xE86CA0
+
+#define mmTPC2_CFG_QM_SRF_5 0xE86CA4
+
+#define mmTPC2_CFG_QM_SRF_6 0xE86CA8
+
+#define mmTPC2_CFG_QM_SRF_7 0xE86CAC
+
+#define mmTPC2_CFG_QM_SRF_8 0xE86CB0
+
+#define mmTPC2_CFG_QM_SRF_9 0xE86CB4
+
+#define mmTPC2_CFG_QM_SRF_10 0xE86CB8
+
+#define mmTPC2_CFG_QM_SRF_11 0xE86CBC
+
+#define mmTPC2_CFG_QM_SRF_12 0xE86CC0
+
+#define mmTPC2_CFG_QM_SRF_13 0xE86CC4
+
+#define mmTPC2_CFG_QM_SRF_14 0xE86CC8
+
+#define mmTPC2_CFG_QM_SRF_15 0xE86CCC
+
+#define mmTPC2_CFG_QM_SRF_16 0xE86CD0
+
+#define mmTPC2_CFG_QM_SRF_17 0xE86CD4
+
+#define mmTPC2_CFG_QM_SRF_18 0xE86CD8
+
+#define mmTPC2_CFG_QM_SRF_19 0xE86CDC
+
+#define mmTPC2_CFG_QM_SRF_20 0xE86CE0
+
+#define mmTPC2_CFG_QM_SRF_21 0xE86CE4
+
+#define mmTPC2_CFG_QM_SRF_22 0xE86CE8
+
+#define mmTPC2_CFG_QM_SRF_23 0xE86CEC
+
+#define mmTPC2_CFG_QM_SRF_24 0xE86CF0
+
+#define mmTPC2_CFG_QM_SRF_25 0xE86CF4
+
+#define mmTPC2_CFG_QM_SRF_26 0xE86CF8
+
+#define mmTPC2_CFG_QM_SRF_27 0xE86CFC
+
+#define mmTPC2_CFG_QM_SRF_28 0xE86D00
+
+#define mmTPC2_CFG_QM_SRF_29 0xE86D04
+
+#define mmTPC2_CFG_QM_SRF_30 0xE86D08
+
+#define mmTPC2_CFG_QM_SRF_31 0xE86D0C
+
+#define mmTPC2_CFG_QM_KERNEL_CONFIG 0xE86D10
+
+#define mmTPC2_CFG_QM_SYNC_OBJECT_MESSAGE 0xE86D14
+
+#define mmTPC2_CFG_ARUSER 0xE86D18
+
+#define mmTPC2_CFG_AWUSER 0xE86D1C
+
+#define mmTPC2_CFG_FUNC_MBIST_CNTRL 0xE86E00
+
+#define mmTPC2_CFG_FUNC_MBIST_PAT 0xE86E04
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_0 0xE86E08
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_1 0xE86E0C
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_2 0xE86E10
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_3 0xE86E14
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_4 0xE86E18
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_5 0xE86E1C
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_6 0xE86E20
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_7 0xE86E24
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_8 0xE86E28
+
+#define mmTPC2_CFG_FUNC_MBIST_MEM_9 0xE86E2C
+
+#endif /* ASIC_REG_TPC2_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h
new file mode 100644
index 000000000000..7a643887d6e1
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC2_CMDQ_REGS_H_
+#define ASIC_REG_TPC2_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC2_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC2_CMDQ_GLBL_CFG0 0xE89000
+
+#define mmTPC2_CMDQ_GLBL_CFG1 0xE89004
+
+#define mmTPC2_CMDQ_GLBL_PROT 0xE89008
+
+#define mmTPC2_CMDQ_GLBL_ERR_CFG 0xE8900C
+
+#define mmTPC2_CMDQ_GLBL_ERR_ADDR_LO 0xE89010
+
+#define mmTPC2_CMDQ_GLBL_ERR_ADDR_HI 0xE89014
+
+#define mmTPC2_CMDQ_GLBL_ERR_WDATA 0xE89018
+
+#define mmTPC2_CMDQ_GLBL_SECURE_PROPS 0xE8901C
+
+#define mmTPC2_CMDQ_GLBL_NON_SECURE_PROPS 0xE89020
+
+#define mmTPC2_CMDQ_GLBL_STS0 0xE89024
+
+#define mmTPC2_CMDQ_GLBL_STS1 0xE89028
+
+#define mmTPC2_CMDQ_CQ_CFG0 0xE890B0
+
+#define mmTPC2_CMDQ_CQ_CFG1 0xE890B4
+
+#define mmTPC2_CMDQ_CQ_ARUSER 0xE890B8
+
+#define mmTPC2_CMDQ_CQ_PTR_LO 0xE890C0
+
+#define mmTPC2_CMDQ_CQ_PTR_HI 0xE890C4
+
+#define mmTPC2_CMDQ_CQ_TSIZE 0xE890C8
+
+#define mmTPC2_CMDQ_CQ_CTL 0xE890CC
+
+#define mmTPC2_CMDQ_CQ_PTR_LO_STS 0xE890D4
+
+#define mmTPC2_CMDQ_CQ_PTR_HI_STS 0xE890D8
+
+#define mmTPC2_CMDQ_CQ_TSIZE_STS 0xE890DC
+
+#define mmTPC2_CMDQ_CQ_CTL_STS 0xE890E0
+
+#define mmTPC2_CMDQ_CQ_STS0 0xE890E4
+
+#define mmTPC2_CMDQ_CQ_STS1 0xE890E8
+
+#define mmTPC2_CMDQ_CQ_RD_RATE_LIM_EN 0xE890F0
+
+#define mmTPC2_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xE890F4
+
+#define mmTPC2_CMDQ_CQ_RD_RATE_LIM_SAT 0xE890F8
+
+#define mmTPC2_CMDQ_CQ_RD_RATE_LIM_TOUT 0xE890FC
+
+#define mmTPC2_CMDQ_CQ_IFIFO_CNT 0xE89108
+
+#define mmTPC2_CMDQ_CP_MSG_BASE0_ADDR_LO 0xE89120
+
+#define mmTPC2_CMDQ_CP_MSG_BASE0_ADDR_HI 0xE89124
+
+#define mmTPC2_CMDQ_CP_MSG_BASE1_ADDR_LO 0xE89128
+
+#define mmTPC2_CMDQ_CP_MSG_BASE1_ADDR_HI 0xE8912C
+
+#define mmTPC2_CMDQ_CP_MSG_BASE2_ADDR_LO 0xE89130
+
+#define mmTPC2_CMDQ_CP_MSG_BASE2_ADDR_HI 0xE89134
+
+#define mmTPC2_CMDQ_CP_MSG_BASE3_ADDR_LO 0xE89138
+
+#define mmTPC2_CMDQ_CP_MSG_BASE3_ADDR_HI 0xE8913C
+
+#define mmTPC2_CMDQ_CP_LDMA_TSIZE_OFFSET 0xE89140
+
+#define mmTPC2_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xE89144
+
+#define mmTPC2_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xE89148
+
+#define mmTPC2_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xE8914C
+
+#define mmTPC2_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xE89150
+
+#define mmTPC2_CMDQ_CP_LDMA_COMMIT_OFFSET 0xE89154
+
+#define mmTPC2_CMDQ_CP_FENCE0_RDATA 0xE89158
+
+#define mmTPC2_CMDQ_CP_FENCE1_RDATA 0xE8915C
+
+#define mmTPC2_CMDQ_CP_FENCE2_RDATA 0xE89160
+
+#define mmTPC2_CMDQ_CP_FENCE3_RDATA 0xE89164
+
+#define mmTPC2_CMDQ_CP_FENCE0_CNT 0xE89168
+
+#define mmTPC2_CMDQ_CP_FENCE1_CNT 0xE8916C
+
+#define mmTPC2_CMDQ_CP_FENCE2_CNT 0xE89170
+
+#define mmTPC2_CMDQ_CP_FENCE3_CNT 0xE89174
+
+#define mmTPC2_CMDQ_CP_STS 0xE89178
+
+#define mmTPC2_CMDQ_CP_CURRENT_INST_LO 0xE8917C
+
+#define mmTPC2_CMDQ_CP_CURRENT_INST_HI 0xE89180
+
+#define mmTPC2_CMDQ_CP_BARRIER_CFG 0xE89184
+
+#define mmTPC2_CMDQ_CP_DBG_0 0xE89188
+
+#define mmTPC2_CMDQ_CQ_BUF_ADDR 0xE89308
+
+#define mmTPC2_CMDQ_CQ_BUF_RDATA 0xE8930C
+
+#endif /* ASIC_REG_TPC2_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h
new file mode 100644
index 000000000000..f3e32c018064
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC2_QM_REGS_H_
+#define ASIC_REG_TPC2_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC2_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC2_QM_GLBL_CFG0 0xE88000
+
+#define mmTPC2_QM_GLBL_CFG1 0xE88004
+
+#define mmTPC2_QM_GLBL_PROT 0xE88008
+
+#define mmTPC2_QM_GLBL_ERR_CFG 0xE8800C
+
+#define mmTPC2_QM_GLBL_ERR_ADDR_LO 0xE88010
+
+#define mmTPC2_QM_GLBL_ERR_ADDR_HI 0xE88014
+
+#define mmTPC2_QM_GLBL_ERR_WDATA 0xE88018
+
+#define mmTPC2_QM_GLBL_SECURE_PROPS 0xE8801C
+
+#define mmTPC2_QM_GLBL_NON_SECURE_PROPS 0xE88020
+
+#define mmTPC2_QM_GLBL_STS0 0xE88024
+
+#define mmTPC2_QM_GLBL_STS1 0xE88028
+
+#define mmTPC2_QM_PQ_BASE_LO 0xE88060
+
+#define mmTPC2_QM_PQ_BASE_HI 0xE88064
+
+#define mmTPC2_QM_PQ_SIZE 0xE88068
+
+#define mmTPC2_QM_PQ_PI 0xE8806C
+
+#define mmTPC2_QM_PQ_CI 0xE88070
+
+#define mmTPC2_QM_PQ_CFG0 0xE88074
+
+#define mmTPC2_QM_PQ_CFG1 0xE88078
+
+#define mmTPC2_QM_PQ_ARUSER 0xE8807C
+
+#define mmTPC2_QM_PQ_PUSH0 0xE88080
+
+#define mmTPC2_QM_PQ_PUSH1 0xE88084
+
+#define mmTPC2_QM_PQ_PUSH2 0xE88088
+
+#define mmTPC2_QM_PQ_PUSH3 0xE8808C
+
+#define mmTPC2_QM_PQ_STS0 0xE88090
+
+#define mmTPC2_QM_PQ_STS1 0xE88094
+
+#define mmTPC2_QM_PQ_RD_RATE_LIM_EN 0xE880A0
+
+#define mmTPC2_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xE880A4
+
+#define mmTPC2_QM_PQ_RD_RATE_LIM_SAT 0xE880A8
+
+#define mmTPC2_QM_PQ_RD_RATE_LIM_TOUT 0xE880AC
+
+#define mmTPC2_QM_CQ_CFG0 0xE880B0
+
+#define mmTPC2_QM_CQ_CFG1 0xE880B4
+
+#define mmTPC2_QM_CQ_ARUSER 0xE880B8
+
+#define mmTPC2_QM_CQ_PTR_LO 0xE880C0
+
+#define mmTPC2_QM_CQ_PTR_HI 0xE880C4
+
+#define mmTPC2_QM_CQ_TSIZE 0xE880C8
+
+#define mmTPC2_QM_CQ_CTL 0xE880CC
+
+#define mmTPC2_QM_CQ_PTR_LO_STS 0xE880D4
+
+#define mmTPC2_QM_CQ_PTR_HI_STS 0xE880D8
+
+#define mmTPC2_QM_CQ_TSIZE_STS 0xE880DC
+
+#define mmTPC2_QM_CQ_CTL_STS 0xE880E0
+
+#define mmTPC2_QM_CQ_STS0 0xE880E4
+
+#define mmTPC2_QM_CQ_STS1 0xE880E8
+
+#define mmTPC2_QM_CQ_RD_RATE_LIM_EN 0xE880F0
+
+#define mmTPC2_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xE880F4
+
+#define mmTPC2_QM_CQ_RD_RATE_LIM_SAT 0xE880F8
+
+#define mmTPC2_QM_CQ_RD_RATE_LIM_TOUT 0xE880FC
+
+#define mmTPC2_QM_CQ_IFIFO_CNT 0xE88108
+
+#define mmTPC2_QM_CP_MSG_BASE0_ADDR_LO 0xE88120
+
+#define mmTPC2_QM_CP_MSG_BASE0_ADDR_HI 0xE88124
+
+#define mmTPC2_QM_CP_MSG_BASE1_ADDR_LO 0xE88128
+
+#define mmTPC2_QM_CP_MSG_BASE1_ADDR_HI 0xE8812C
+
+#define mmTPC2_QM_CP_MSG_BASE2_ADDR_LO 0xE88130
+
+#define mmTPC2_QM_CP_MSG_BASE2_ADDR_HI 0xE88134
+
+#define mmTPC2_QM_CP_MSG_BASE3_ADDR_LO 0xE88138
+
+#define mmTPC2_QM_CP_MSG_BASE3_ADDR_HI 0xE8813C
+
+#define mmTPC2_QM_CP_LDMA_TSIZE_OFFSET 0xE88140
+
+#define mmTPC2_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xE88144
+
+#define mmTPC2_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xE88148
+
+#define mmTPC2_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xE8814C
+
+#define mmTPC2_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xE88150
+
+#define mmTPC2_QM_CP_LDMA_COMMIT_OFFSET 0xE88154
+
+#define mmTPC2_QM_CP_FENCE0_RDATA 0xE88158
+
+#define mmTPC2_QM_CP_FENCE1_RDATA 0xE8815C
+
+#define mmTPC2_QM_CP_FENCE2_RDATA 0xE88160
+
+#define mmTPC2_QM_CP_FENCE3_RDATA 0xE88164
+
+#define mmTPC2_QM_CP_FENCE0_CNT 0xE88168
+
+#define mmTPC2_QM_CP_FENCE1_CNT 0xE8816C
+
+#define mmTPC2_QM_CP_FENCE2_CNT 0xE88170
+
+#define mmTPC2_QM_CP_FENCE3_CNT 0xE88174
+
+#define mmTPC2_QM_CP_STS 0xE88178
+
+#define mmTPC2_QM_CP_CURRENT_INST_LO 0xE8817C
+
+#define mmTPC2_QM_CP_CURRENT_INST_HI 0xE88180
+
+#define mmTPC2_QM_CP_BARRIER_CFG 0xE88184
+
+#define mmTPC2_QM_CP_DBG_0 0xE88188
+
+#define mmTPC2_QM_PQ_BUF_ADDR 0xE88300
+
+#define mmTPC2_QM_PQ_BUF_RDATA 0xE88304
+
+#define mmTPC2_QM_CQ_BUF_ADDR 0xE88308
+
+#define mmTPC2_QM_CQ_BUF_RDATA 0xE8830C
+
+#endif /* ASIC_REG_TPC2_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h
new file mode 100644
index 000000000000..0eb0cd1fbd19
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc2_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC2_RTR_REGS_H_
+#define ASIC_REG_TPC2_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC2_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC2_RTR_HBW_RD_RQ_E_ARB 0xE80100
+
+#define mmTPC2_RTR_HBW_RD_RQ_W_ARB 0xE80104
+
+#define mmTPC2_RTR_HBW_RD_RQ_N_ARB 0xE80108
+
+#define mmTPC2_RTR_HBW_RD_RQ_S_ARB 0xE8010C
+
+#define mmTPC2_RTR_HBW_RD_RQ_L_ARB 0xE80110
+
+#define mmTPC2_RTR_HBW_E_ARB_MAX 0xE80120
+
+#define mmTPC2_RTR_HBW_W_ARB_MAX 0xE80124
+
+#define mmTPC2_RTR_HBW_N_ARB_MAX 0xE80128
+
+#define mmTPC2_RTR_HBW_S_ARB_MAX 0xE8012C
+
+#define mmTPC2_RTR_HBW_L_ARB_MAX 0xE80130
+
+#define mmTPC2_RTR_HBW_RD_RS_E_ARB 0xE80140
+
+#define mmTPC2_RTR_HBW_RD_RS_W_ARB 0xE80144
+
+#define mmTPC2_RTR_HBW_RD_RS_N_ARB 0xE80148
+
+#define mmTPC2_RTR_HBW_RD_RS_S_ARB 0xE8014C
+
+#define mmTPC2_RTR_HBW_RD_RS_L_ARB 0xE80150
+
+#define mmTPC2_RTR_HBW_WR_RQ_E_ARB 0xE80170
+
+#define mmTPC2_RTR_HBW_WR_RQ_W_ARB 0xE80174
+
+#define mmTPC2_RTR_HBW_WR_RQ_N_ARB 0xE80178
+
+#define mmTPC2_RTR_HBW_WR_RQ_S_ARB 0xE8017C
+
+#define mmTPC2_RTR_HBW_WR_RQ_L_ARB 0xE80180
+
+#define mmTPC2_RTR_HBW_WR_RS_E_ARB 0xE80190
+
+#define mmTPC2_RTR_HBW_WR_RS_W_ARB 0xE80194
+
+#define mmTPC2_RTR_HBW_WR_RS_N_ARB 0xE80198
+
+#define mmTPC2_RTR_HBW_WR_RS_S_ARB 0xE8019C
+
+#define mmTPC2_RTR_HBW_WR_RS_L_ARB 0xE801A0
+
+#define mmTPC2_RTR_LBW_RD_RQ_E_ARB 0xE80200
+
+#define mmTPC2_RTR_LBW_RD_RQ_W_ARB 0xE80204
+
+#define mmTPC2_RTR_LBW_RD_RQ_N_ARB 0xE80208
+
+#define mmTPC2_RTR_LBW_RD_RQ_S_ARB 0xE8020C
+
+#define mmTPC2_RTR_LBW_RD_RQ_L_ARB 0xE80210
+
+#define mmTPC2_RTR_LBW_E_ARB_MAX 0xE80220
+
+#define mmTPC2_RTR_LBW_W_ARB_MAX 0xE80224
+
+#define mmTPC2_RTR_LBW_N_ARB_MAX 0xE80228
+
+#define mmTPC2_RTR_LBW_S_ARB_MAX 0xE8022C
+
+#define mmTPC2_RTR_LBW_L_ARB_MAX 0xE80230
+
+#define mmTPC2_RTR_LBW_RD_RS_E_ARB 0xE80250
+
+#define mmTPC2_RTR_LBW_RD_RS_W_ARB 0xE80254
+
+#define mmTPC2_RTR_LBW_RD_RS_N_ARB 0xE80258
+
+#define mmTPC2_RTR_LBW_RD_RS_S_ARB 0xE8025C
+
+#define mmTPC2_RTR_LBW_RD_RS_L_ARB 0xE80260
+
+#define mmTPC2_RTR_LBW_WR_RQ_E_ARB 0xE80270
+
+#define mmTPC2_RTR_LBW_WR_RQ_W_ARB 0xE80274
+
+#define mmTPC2_RTR_LBW_WR_RQ_N_ARB 0xE80278
+
+#define mmTPC2_RTR_LBW_WR_RQ_S_ARB 0xE8027C
+
+#define mmTPC2_RTR_LBW_WR_RQ_L_ARB 0xE80280
+
+#define mmTPC2_RTR_LBW_WR_RS_E_ARB 0xE80290
+
+#define mmTPC2_RTR_LBW_WR_RS_W_ARB 0xE80294
+
+#define mmTPC2_RTR_LBW_WR_RS_N_ARB 0xE80298
+
+#define mmTPC2_RTR_LBW_WR_RS_S_ARB 0xE8029C
+
+#define mmTPC2_RTR_LBW_WR_RS_L_ARB 0xE802A0
+
+#define mmTPC2_RTR_DBG_E_ARB 0xE80300
+
+#define mmTPC2_RTR_DBG_W_ARB 0xE80304
+
+#define mmTPC2_RTR_DBG_N_ARB 0xE80308
+
+#define mmTPC2_RTR_DBG_S_ARB 0xE8030C
+
+#define mmTPC2_RTR_DBG_L_ARB 0xE80310
+
+#define mmTPC2_RTR_DBG_E_ARB_MAX 0xE80320
+
+#define mmTPC2_RTR_DBG_W_ARB_MAX 0xE80324
+
+#define mmTPC2_RTR_DBG_N_ARB_MAX 0xE80328
+
+#define mmTPC2_RTR_DBG_S_ARB_MAX 0xE8032C
+
+#define mmTPC2_RTR_DBG_L_ARB_MAX 0xE80330
+
+#define mmTPC2_RTR_SPLIT_COEF_0 0xE80400
+
+#define mmTPC2_RTR_SPLIT_COEF_1 0xE80404
+
+#define mmTPC2_RTR_SPLIT_COEF_2 0xE80408
+
+#define mmTPC2_RTR_SPLIT_COEF_3 0xE8040C
+
+#define mmTPC2_RTR_SPLIT_COEF_4 0xE80410
+
+#define mmTPC2_RTR_SPLIT_COEF_5 0xE80414
+
+#define mmTPC2_RTR_SPLIT_COEF_6 0xE80418
+
+#define mmTPC2_RTR_SPLIT_COEF_7 0xE8041C
+
+#define mmTPC2_RTR_SPLIT_COEF_8 0xE80420
+
+#define mmTPC2_RTR_SPLIT_COEF_9 0xE80424
+
+#define mmTPC2_RTR_SPLIT_CFG 0xE80440
+
+#define mmTPC2_RTR_SPLIT_RD_SAT 0xE80444
+
+#define mmTPC2_RTR_SPLIT_RD_RST_TOKEN 0xE80448
+
+#define mmTPC2_RTR_SPLIT_RD_TIMEOUT_0 0xE8044C
+
+#define mmTPC2_RTR_SPLIT_RD_TIMEOUT_1 0xE80450
+
+#define mmTPC2_RTR_SPLIT_WR_SAT 0xE80454
+
+#define mmTPC2_RTR_WPLIT_WR_TST_TOLEN 0xE80458
+
+#define mmTPC2_RTR_SPLIT_WR_TIMEOUT_0 0xE8045C
+
+#define mmTPC2_RTR_SPLIT_WR_TIMEOUT_1 0xE80460
+
+#define mmTPC2_RTR_HBW_RANGE_HIT 0xE80470
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_0 0xE80480
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_1 0xE80484
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_2 0xE80488
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_3 0xE8048C
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_4 0xE80490
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_5 0xE80494
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_6 0xE80498
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_L_7 0xE8049C
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_0 0xE804A0
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_1 0xE804A4
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_2 0xE804A8
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_3 0xE804AC
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_4 0xE804B0
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_5 0xE804B4
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_6 0xE804B8
+
+#define mmTPC2_RTR_HBW_RANGE_MASK_H_7 0xE804BC
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_0 0xE804C0
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_1 0xE804C4
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_2 0xE804C8
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_3 0xE804CC
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_4 0xE804D0
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_5 0xE804D4
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_6 0xE804D8
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_L_7 0xE804DC
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_0 0xE804E0
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_1 0xE804E4
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_2 0xE804E8
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_3 0xE804EC
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_4 0xE804F0
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_5 0xE804F4
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_6 0xE804F8
+
+#define mmTPC2_RTR_HBW_RANGE_BASE_H_7 0xE804FC
+
+#define mmTPC2_RTR_LBW_RANGE_HIT 0xE80500
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_0 0xE80510
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_1 0xE80514
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_2 0xE80518
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_3 0xE8051C
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_4 0xE80520
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_5 0xE80524
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_6 0xE80528
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_7 0xE8052C
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_8 0xE80530
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_9 0xE80534
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_10 0xE80538
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_11 0xE8053C
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_12 0xE80540
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_13 0xE80544
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_14 0xE80548
+
+#define mmTPC2_RTR_LBW_RANGE_MASK_15 0xE8054C
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_0 0xE80550
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_1 0xE80554
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_2 0xE80558
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_3 0xE8055C
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_4 0xE80560
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_5 0xE80564
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_6 0xE80568
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_7 0xE8056C
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_8 0xE80570
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_9 0xE80574
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_10 0xE80578
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_11 0xE8057C
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_12 0xE80580
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_13 0xE80584
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_14 0xE80588
+
+#define mmTPC2_RTR_LBW_RANGE_BASE_15 0xE8058C
+
+#define mmTPC2_RTR_RGLTR 0xE80590
+
+#define mmTPC2_RTR_RGLTR_WR_RESULT 0xE80594
+
+#define mmTPC2_RTR_RGLTR_RD_RESULT 0xE80598
+
+#define mmTPC2_RTR_SCRAMB_EN 0xE80600
+
+#define mmTPC2_RTR_NON_LIN_SCRAMB 0xE80604
+
+#endif /* ASIC_REG_TPC2_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h
new file mode 100644
index 000000000000..0baf63c69b25
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC3_CFG_REGS_H_
+#define ASIC_REG_TPC3_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC3_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xEC6400
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xEC6404
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xEC6408
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xEC640C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xEC6410
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xEC6414
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xEC6418
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xEC641C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xEC6420
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xEC6424
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xEC6428
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xEC642C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xEC6430
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xEC6434
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xEC6438
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xEC643C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xEC6440
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xEC6444
+
+#define mmTPC3_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xEC6448
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xEC644C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xEC6450
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xEC6454
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xEC6458
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xEC645C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xEC6460
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xEC6464
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xEC6468
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xEC646C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xEC6470
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xEC6474
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xEC6478
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xEC647C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xEC6480
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xEC6484
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xEC6488
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xEC648C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xEC6490
+
+#define mmTPC3_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xEC6494
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xEC6498
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xEC649C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xEC64A0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xEC64A4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xEC64A8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xEC64AC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xEC64B0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xEC64B4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xEC64B8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xEC64BC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xEC64C0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xEC64C4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xEC64C8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xEC64CC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xEC64D0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xEC64D4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xEC64D8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xEC64DC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xEC64E0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xEC64E4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xEC64E8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xEC64EC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xEC64F0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xEC64F4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xEC64F8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xEC64FC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xEC6500
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xEC6504
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xEC6508
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xEC650C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xEC6510
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xEC6514
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xEC6518
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xEC651C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xEC6520
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xEC6524
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xEC6528
+
+#define mmTPC3_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xEC652C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xEC6530
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xEC6534
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xEC6538
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xEC653C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xEC6540
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xEC6544
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xEC6548
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xEC654C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xEC6550
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xEC6554
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xEC6558
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xEC655C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xEC6560
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xEC6564
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xEC6568
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xEC656C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xEC6570
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xEC6574
+
+#define mmTPC3_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xEC6578
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xEC657C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xEC6580
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xEC6584
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xEC6588
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xEC658C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xEC6590
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xEC6594
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xEC6598
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xEC659C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xEC65A0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xEC65A4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xEC65A8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xEC65AC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xEC65B0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xEC65B4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xEC65B8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xEC65BC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xEC65C0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xEC65C4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xEC65C8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xEC65CC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xEC65D0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xEC65D4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xEC65D8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xEC65DC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xEC65E0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xEC65E4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xEC65E8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xEC65EC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xEC65F0
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xEC65F4
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xEC65F8
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xEC65FC
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xEC6600
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xEC6604
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xEC6608
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xEC660C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xEC6610
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xEC6614
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xEC6618
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xEC661C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xEC6620
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xEC6624
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xEC6628
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xEC662C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xEC6630
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xEC6634
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xEC6638
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xEC663C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xEC6640
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xEC6644
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xEC6648
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xEC664C
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xEC6650
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xEC6654
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xEC6658
+
+#define mmTPC3_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xEC665C
+
+#define mmTPC3_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xEC6660
+
+#define mmTPC3_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xEC6664
+
+#define mmTPC3_CFG_KERNEL_TID_BASE_DIM_0 0xEC6668
+
+#define mmTPC3_CFG_KERNEL_TID_SIZE_DIM_0 0xEC666C
+
+#define mmTPC3_CFG_KERNEL_TID_BASE_DIM_1 0xEC6670
+
+#define mmTPC3_CFG_KERNEL_TID_SIZE_DIM_1 0xEC6674
+
+#define mmTPC3_CFG_KERNEL_TID_BASE_DIM_2 0xEC6678
+
+#define mmTPC3_CFG_KERNEL_TID_SIZE_DIM_2 0xEC667C
+
+#define mmTPC3_CFG_KERNEL_TID_BASE_DIM_3 0xEC6680
+
+#define mmTPC3_CFG_KERNEL_TID_SIZE_DIM_3 0xEC6684
+
+#define mmTPC3_CFG_KERNEL_TID_BASE_DIM_4 0xEC6688
+
+#define mmTPC3_CFG_KERNEL_TID_SIZE_DIM_4 0xEC668C
+
+#define mmTPC3_CFG_KERNEL_SRF_0 0xEC6690
+
+#define mmTPC3_CFG_KERNEL_SRF_1 0xEC6694
+
+#define mmTPC3_CFG_KERNEL_SRF_2 0xEC6698
+
+#define mmTPC3_CFG_KERNEL_SRF_3 0xEC669C
+
+#define mmTPC3_CFG_KERNEL_SRF_4 0xEC66A0
+
+#define mmTPC3_CFG_KERNEL_SRF_5 0xEC66A4
+
+#define mmTPC3_CFG_KERNEL_SRF_6 0xEC66A8
+
+#define mmTPC3_CFG_KERNEL_SRF_7 0xEC66AC
+
+#define mmTPC3_CFG_KERNEL_SRF_8 0xEC66B0
+
+#define mmTPC3_CFG_KERNEL_SRF_9 0xEC66B4
+
+#define mmTPC3_CFG_KERNEL_SRF_10 0xEC66B8
+
+#define mmTPC3_CFG_KERNEL_SRF_11 0xEC66BC
+
+#define mmTPC3_CFG_KERNEL_SRF_12 0xEC66C0
+
+#define mmTPC3_CFG_KERNEL_SRF_13 0xEC66C4
+
+#define mmTPC3_CFG_KERNEL_SRF_14 0xEC66C8
+
+#define mmTPC3_CFG_KERNEL_SRF_15 0xEC66CC
+
+#define mmTPC3_CFG_KERNEL_SRF_16 0xEC66D0
+
+#define mmTPC3_CFG_KERNEL_SRF_17 0xEC66D4
+
+#define mmTPC3_CFG_KERNEL_SRF_18 0xEC66D8
+
+#define mmTPC3_CFG_KERNEL_SRF_19 0xEC66DC
+
+#define mmTPC3_CFG_KERNEL_SRF_20 0xEC66E0
+
+#define mmTPC3_CFG_KERNEL_SRF_21 0xEC66E4
+
+#define mmTPC3_CFG_KERNEL_SRF_22 0xEC66E8
+
+#define mmTPC3_CFG_KERNEL_SRF_23 0xEC66EC
+
+#define mmTPC3_CFG_KERNEL_SRF_24 0xEC66F0
+
+#define mmTPC3_CFG_KERNEL_SRF_25 0xEC66F4
+
+#define mmTPC3_CFG_KERNEL_SRF_26 0xEC66F8
+
+#define mmTPC3_CFG_KERNEL_SRF_27 0xEC66FC
+
+#define mmTPC3_CFG_KERNEL_SRF_28 0xEC6700
+
+#define mmTPC3_CFG_KERNEL_SRF_29 0xEC6704
+
+#define mmTPC3_CFG_KERNEL_SRF_30 0xEC6708
+
+#define mmTPC3_CFG_KERNEL_SRF_31 0xEC670C
+
+#define mmTPC3_CFG_KERNEL_KERNEL_CONFIG 0xEC6710
+
+#define mmTPC3_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xEC6714
+
+#define mmTPC3_CFG_RESERVED_DESC_END 0xEC6738
+
+#define mmTPC3_CFG_ROUND_CSR 0xEC67FC
+
+#define mmTPC3_CFG_TBUF_BASE_ADDR_LOW 0xEC6800
+
+#define mmTPC3_CFG_TBUF_BASE_ADDR_HIGH 0xEC6804
+
+#define mmTPC3_CFG_SEMAPHORE 0xEC6808
+
+#define mmTPC3_CFG_VFLAGS 0xEC680C
+
+#define mmTPC3_CFG_SFLAGS 0xEC6810
+
+#define mmTPC3_CFG_LFSR_POLYNOM 0xEC6818
+
+#define mmTPC3_CFG_STATUS 0xEC681C
+
+#define mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH 0xEC6820
+
+#define mmTPC3_CFG_CFG_SUBTRACT_VALUE 0xEC6824
+
+#define mmTPC3_CFG_SM_BASE_ADDRESS_LOW 0xEC6828
+
+#define mmTPC3_CFG_SM_BASE_ADDRESS_HIGH 0xEC682C
+
+#define mmTPC3_CFG_TPC_CMD 0xEC6830
+
+#define mmTPC3_CFG_TPC_EXECUTE 0xEC6838
+
+#define mmTPC3_CFG_TPC_STALL 0xEC683C
+
+#define mmTPC3_CFG_ICACHE_BASE_ADDERESS_LOW 0xEC6840
+
+#define mmTPC3_CFG_ICACHE_BASE_ADDERESS_HIGH 0xEC6844
+
+#define mmTPC3_CFG_MSS_CONFIG 0xEC6854
+
+#define mmTPC3_CFG_TPC_INTR_CAUSE 0xEC6858
+
+#define mmTPC3_CFG_TPC_INTR_MASK 0xEC685C
+
+#define mmTPC3_CFG_TSB_CONFIG 0xEC6860
+
+#define mmTPC3_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xEC6A00
+
+#define mmTPC3_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xEC6A04
+
+#define mmTPC3_CFG_QM_TENSOR_0_PADDING_VALUE 0xEC6A08
+
+#define mmTPC3_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xEC6A0C
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_0_SIZE 0xEC6A10
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xEC6A14
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xEC6A18
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_1_SIZE 0xEC6A1C
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xEC6A20
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xEC6A24
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_2_SIZE 0xEC6A28
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xEC6A2C
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xEC6A30
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_3_SIZE 0xEC6A34
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xEC6A38
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xEC6A3C
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_4_SIZE 0xEC6A40
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xEC6A44
+
+#define mmTPC3_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xEC6A48
+
+#define mmTPC3_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xEC6A4C
+
+#define mmTPC3_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xEC6A50
+
+#define mmTPC3_CFG_QM_TENSOR_1_PADDING_VALUE 0xEC6A54
+
+#define mmTPC3_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xEC6A58
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_0_SIZE 0xEC6A5C
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xEC6A60
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xEC6A64
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_1_SIZE 0xEC6A68
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xEC6A6C
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xEC6A70
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_2_SIZE 0xEC6A74
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xEC6A78
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xEC6A7C
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_3_SIZE 0xEC6A80
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xEC6A84
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xEC6A88
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_4_SIZE 0xEC6A8C
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xEC6A90
+
+#define mmTPC3_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xEC6A94
+
+#define mmTPC3_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xEC6A98
+
+#define mmTPC3_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xEC6A9C
+
+#define mmTPC3_CFG_QM_TENSOR_2_PADDING_VALUE 0xEC6AA0
+
+#define mmTPC3_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xEC6AA4
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_0_SIZE 0xEC6AA8
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xEC6AAC
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xEC6AB0
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_1_SIZE 0xEC6AB4
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xEC6AB8
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xEC6ABC
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_2_SIZE 0xEC6AC0
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xEC6AC4
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xEC6AC8
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_3_SIZE 0xEC6ACC
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xEC6AD0
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xEC6AD4
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_4_SIZE 0xEC6AD8
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xEC6ADC
+
+#define mmTPC3_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xEC6AE0
+
+#define mmTPC3_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xEC6AE4
+
+#define mmTPC3_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xEC6AE8
+
+#define mmTPC3_CFG_QM_TENSOR_3_PADDING_VALUE 0xEC6AEC
+
+#define mmTPC3_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xEC6AF0
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_0_SIZE 0xEC6AF4
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xEC6AF8
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xEC6AFC
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_1_SIZE 0xEC6B00
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xEC6B04
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xEC6B08
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_2_SIZE 0xEC6B0C
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xEC6B10
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xEC6B14
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_3_SIZE 0xEC6B18
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xEC6B1C
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xEC6B20
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_4_SIZE 0xEC6B24
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xEC6B28
+
+#define mmTPC3_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xEC6B2C
+
+#define mmTPC3_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xEC6B30
+
+#define mmTPC3_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xEC6B34
+
+#define mmTPC3_CFG_QM_TENSOR_4_PADDING_VALUE 0xEC6B38
+
+#define mmTPC3_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xEC6B3C
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_0_SIZE 0xEC6B40
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xEC6B44
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xEC6B48
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_1_SIZE 0xEC6B4C
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xEC6B50
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xEC6B54
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_2_SIZE 0xEC6B58
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xEC6B5C
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xEC6B60
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_3_SIZE 0xEC6B64
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xEC6B68
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xEC6B6C
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_4_SIZE 0xEC6B70
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xEC6B74
+
+#define mmTPC3_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xEC6B78
+
+#define mmTPC3_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xEC6B7C
+
+#define mmTPC3_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xEC6B80
+
+#define mmTPC3_CFG_QM_TENSOR_5_PADDING_VALUE 0xEC6B84
+
+#define mmTPC3_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xEC6B88
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_0_SIZE 0xEC6B8C
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xEC6B90
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xEC6B94
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_1_SIZE 0xEC6B98
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xEC6B9C
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xEC6BA0
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_2_SIZE 0xEC6BA4
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xEC6BA8
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xEC6BAC
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_3_SIZE 0xEC6BB0
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xEC6BB4
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xEC6BB8
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_4_SIZE 0xEC6BBC
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xEC6BC0
+
+#define mmTPC3_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xEC6BC4
+
+#define mmTPC3_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xEC6BC8
+
+#define mmTPC3_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xEC6BCC
+
+#define mmTPC3_CFG_QM_TENSOR_6_PADDING_VALUE 0xEC6BD0
+
+#define mmTPC3_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xEC6BD4
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_0_SIZE 0xEC6BD8
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xEC6BDC
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xEC6BE0
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_1_SIZE 0xEC6BE4
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xEC6BE8
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xEC6BEC
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_2_SIZE 0xEC6BF0
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xEC6BF4
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xEC6BF8
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_3_SIZE 0xEC6BFC
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xEC6C00
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xEC6C04
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_4_SIZE 0xEC6C08
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xEC6C0C
+
+#define mmTPC3_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xEC6C10
+
+#define mmTPC3_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xEC6C14
+
+#define mmTPC3_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xEC6C18
+
+#define mmTPC3_CFG_QM_TENSOR_7_PADDING_VALUE 0xEC6C1C
+
+#define mmTPC3_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xEC6C20
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_0_SIZE 0xEC6C24
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xEC6C28
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xEC6C2C
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_1_SIZE 0xEC6C30
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xEC6C34
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xEC6C38
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_2_SIZE 0xEC6C3C
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xEC6C40
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xEC6C44
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_3_SIZE 0xEC6C48
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xEC6C4C
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xEC6C50
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_4_SIZE 0xEC6C54
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xEC6C58
+
+#define mmTPC3_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xEC6C5C
+
+#define mmTPC3_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xEC6C60
+
+#define mmTPC3_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xEC6C64
+
+#define mmTPC3_CFG_QM_TID_BASE_DIM_0 0xEC6C68
+
+#define mmTPC3_CFG_QM_TID_SIZE_DIM_0 0xEC6C6C
+
+#define mmTPC3_CFG_QM_TID_BASE_DIM_1 0xEC6C70
+
+#define mmTPC3_CFG_QM_TID_SIZE_DIM_1 0xEC6C74
+
+#define mmTPC3_CFG_QM_TID_BASE_DIM_2 0xEC6C78
+
+#define mmTPC3_CFG_QM_TID_SIZE_DIM_2 0xEC6C7C
+
+#define mmTPC3_CFG_QM_TID_BASE_DIM_3 0xEC6C80
+
+#define mmTPC3_CFG_QM_TID_SIZE_DIM_3 0xEC6C84
+
+#define mmTPC3_CFG_QM_TID_BASE_DIM_4 0xEC6C88
+
+#define mmTPC3_CFG_QM_TID_SIZE_DIM_4 0xEC6C8C
+
+#define mmTPC3_CFG_QM_SRF_0 0xEC6C90
+
+#define mmTPC3_CFG_QM_SRF_1 0xEC6C94
+
+#define mmTPC3_CFG_QM_SRF_2 0xEC6C98
+
+#define mmTPC3_CFG_QM_SRF_3 0xEC6C9C
+
+#define mmTPC3_CFG_QM_SRF_4 0xEC6CA0
+
+#define mmTPC3_CFG_QM_SRF_5 0xEC6CA4
+
+#define mmTPC3_CFG_QM_SRF_6 0xEC6CA8
+
+#define mmTPC3_CFG_QM_SRF_7 0xEC6CAC
+
+#define mmTPC3_CFG_QM_SRF_8 0xEC6CB0
+
+#define mmTPC3_CFG_QM_SRF_9 0xEC6CB4
+
+#define mmTPC3_CFG_QM_SRF_10 0xEC6CB8
+
+#define mmTPC3_CFG_QM_SRF_11 0xEC6CBC
+
+#define mmTPC3_CFG_QM_SRF_12 0xEC6CC0
+
+#define mmTPC3_CFG_QM_SRF_13 0xEC6CC4
+
+#define mmTPC3_CFG_QM_SRF_14 0xEC6CC8
+
+#define mmTPC3_CFG_QM_SRF_15 0xEC6CCC
+
+#define mmTPC3_CFG_QM_SRF_16 0xEC6CD0
+
+#define mmTPC3_CFG_QM_SRF_17 0xEC6CD4
+
+#define mmTPC3_CFG_QM_SRF_18 0xEC6CD8
+
+#define mmTPC3_CFG_QM_SRF_19 0xEC6CDC
+
+#define mmTPC3_CFG_QM_SRF_20 0xEC6CE0
+
+#define mmTPC3_CFG_QM_SRF_21 0xEC6CE4
+
+#define mmTPC3_CFG_QM_SRF_22 0xEC6CE8
+
+#define mmTPC3_CFG_QM_SRF_23 0xEC6CEC
+
+#define mmTPC3_CFG_QM_SRF_24 0xEC6CF0
+
+#define mmTPC3_CFG_QM_SRF_25 0xEC6CF4
+
+#define mmTPC3_CFG_QM_SRF_26 0xEC6CF8
+
+#define mmTPC3_CFG_QM_SRF_27 0xEC6CFC
+
+#define mmTPC3_CFG_QM_SRF_28 0xEC6D00
+
+#define mmTPC3_CFG_QM_SRF_29 0xEC6D04
+
+#define mmTPC3_CFG_QM_SRF_30 0xEC6D08
+
+#define mmTPC3_CFG_QM_SRF_31 0xEC6D0C
+
+#define mmTPC3_CFG_QM_KERNEL_CONFIG 0xEC6D10
+
+#define mmTPC3_CFG_QM_SYNC_OBJECT_MESSAGE 0xEC6D14
+
+#define mmTPC3_CFG_ARUSER 0xEC6D18
+
+#define mmTPC3_CFG_AWUSER 0xEC6D1C
+
+#define mmTPC3_CFG_FUNC_MBIST_CNTRL 0xEC6E00
+
+#define mmTPC3_CFG_FUNC_MBIST_PAT 0xEC6E04
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_0 0xEC6E08
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_1 0xEC6E0C
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_2 0xEC6E10
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_3 0xEC6E14
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_4 0xEC6E18
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_5 0xEC6E1C
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_6 0xEC6E20
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_7 0xEC6E24
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_8 0xEC6E28
+
+#define mmTPC3_CFG_FUNC_MBIST_MEM_9 0xEC6E2C
+
+#endif /* ASIC_REG_TPC3_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h
new file mode 100644
index 000000000000..82a5261e852f
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC3_CMDQ_REGS_H_
+#define ASIC_REG_TPC3_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC3_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC3_CMDQ_GLBL_CFG0 0xEC9000
+
+#define mmTPC3_CMDQ_GLBL_CFG1 0xEC9004
+
+#define mmTPC3_CMDQ_GLBL_PROT 0xEC9008
+
+#define mmTPC3_CMDQ_GLBL_ERR_CFG 0xEC900C
+
+#define mmTPC3_CMDQ_GLBL_ERR_ADDR_LO 0xEC9010
+
+#define mmTPC3_CMDQ_GLBL_ERR_ADDR_HI 0xEC9014
+
+#define mmTPC3_CMDQ_GLBL_ERR_WDATA 0xEC9018
+
+#define mmTPC3_CMDQ_GLBL_SECURE_PROPS 0xEC901C
+
+#define mmTPC3_CMDQ_GLBL_NON_SECURE_PROPS 0xEC9020
+
+#define mmTPC3_CMDQ_GLBL_STS0 0xEC9024
+
+#define mmTPC3_CMDQ_GLBL_STS1 0xEC9028
+
+#define mmTPC3_CMDQ_CQ_CFG0 0xEC90B0
+
+#define mmTPC3_CMDQ_CQ_CFG1 0xEC90B4
+
+#define mmTPC3_CMDQ_CQ_ARUSER 0xEC90B8
+
+#define mmTPC3_CMDQ_CQ_PTR_LO 0xEC90C0
+
+#define mmTPC3_CMDQ_CQ_PTR_HI 0xEC90C4
+
+#define mmTPC3_CMDQ_CQ_TSIZE 0xEC90C8
+
+#define mmTPC3_CMDQ_CQ_CTL 0xEC90CC
+
+#define mmTPC3_CMDQ_CQ_PTR_LO_STS 0xEC90D4
+
+#define mmTPC3_CMDQ_CQ_PTR_HI_STS 0xEC90D8
+
+#define mmTPC3_CMDQ_CQ_TSIZE_STS 0xEC90DC
+
+#define mmTPC3_CMDQ_CQ_CTL_STS 0xEC90E0
+
+#define mmTPC3_CMDQ_CQ_STS0 0xEC90E4
+
+#define mmTPC3_CMDQ_CQ_STS1 0xEC90E8
+
+#define mmTPC3_CMDQ_CQ_RD_RATE_LIM_EN 0xEC90F0
+
+#define mmTPC3_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xEC90F4
+
+#define mmTPC3_CMDQ_CQ_RD_RATE_LIM_SAT 0xEC90F8
+
+#define mmTPC3_CMDQ_CQ_RD_RATE_LIM_TOUT 0xEC90FC
+
+#define mmTPC3_CMDQ_CQ_IFIFO_CNT 0xEC9108
+
+#define mmTPC3_CMDQ_CP_MSG_BASE0_ADDR_LO 0xEC9120
+
+#define mmTPC3_CMDQ_CP_MSG_BASE0_ADDR_HI 0xEC9124
+
+#define mmTPC3_CMDQ_CP_MSG_BASE1_ADDR_LO 0xEC9128
+
+#define mmTPC3_CMDQ_CP_MSG_BASE1_ADDR_HI 0xEC912C
+
+#define mmTPC3_CMDQ_CP_MSG_BASE2_ADDR_LO 0xEC9130
+
+#define mmTPC3_CMDQ_CP_MSG_BASE2_ADDR_HI 0xEC9134
+
+#define mmTPC3_CMDQ_CP_MSG_BASE3_ADDR_LO 0xEC9138
+
+#define mmTPC3_CMDQ_CP_MSG_BASE3_ADDR_HI 0xEC913C
+
+#define mmTPC3_CMDQ_CP_LDMA_TSIZE_OFFSET 0xEC9140
+
+#define mmTPC3_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xEC9144
+
+#define mmTPC3_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xEC9148
+
+#define mmTPC3_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xEC914C
+
+#define mmTPC3_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xEC9150
+
+#define mmTPC3_CMDQ_CP_LDMA_COMMIT_OFFSET 0xEC9154
+
+#define mmTPC3_CMDQ_CP_FENCE0_RDATA 0xEC9158
+
+#define mmTPC3_CMDQ_CP_FENCE1_RDATA 0xEC915C
+
+#define mmTPC3_CMDQ_CP_FENCE2_RDATA 0xEC9160
+
+#define mmTPC3_CMDQ_CP_FENCE3_RDATA 0xEC9164
+
+#define mmTPC3_CMDQ_CP_FENCE0_CNT 0xEC9168
+
+#define mmTPC3_CMDQ_CP_FENCE1_CNT 0xEC916C
+
+#define mmTPC3_CMDQ_CP_FENCE2_CNT 0xEC9170
+
+#define mmTPC3_CMDQ_CP_FENCE3_CNT 0xEC9174
+
+#define mmTPC3_CMDQ_CP_STS 0xEC9178
+
+#define mmTPC3_CMDQ_CP_CURRENT_INST_LO 0xEC917C
+
+#define mmTPC3_CMDQ_CP_CURRENT_INST_HI 0xEC9180
+
+#define mmTPC3_CMDQ_CP_BARRIER_CFG 0xEC9184
+
+#define mmTPC3_CMDQ_CP_DBG_0 0xEC9188
+
+#define mmTPC3_CMDQ_CQ_BUF_ADDR 0xEC9308
+
+#define mmTPC3_CMDQ_CQ_BUF_RDATA 0xEC930C
+
+#endif /* ASIC_REG_TPC3_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h
new file mode 100644
index 000000000000..b05b1e18e664
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC3_QM_REGS_H_
+#define ASIC_REG_TPC3_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC3_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC3_QM_GLBL_CFG0 0xEC8000
+
+#define mmTPC3_QM_GLBL_CFG1 0xEC8004
+
+#define mmTPC3_QM_GLBL_PROT 0xEC8008
+
+#define mmTPC3_QM_GLBL_ERR_CFG 0xEC800C
+
+#define mmTPC3_QM_GLBL_ERR_ADDR_LO 0xEC8010
+
+#define mmTPC3_QM_GLBL_ERR_ADDR_HI 0xEC8014
+
+#define mmTPC3_QM_GLBL_ERR_WDATA 0xEC8018
+
+#define mmTPC3_QM_GLBL_SECURE_PROPS 0xEC801C
+
+#define mmTPC3_QM_GLBL_NON_SECURE_PROPS 0xEC8020
+
+#define mmTPC3_QM_GLBL_STS0 0xEC8024
+
+#define mmTPC3_QM_GLBL_STS1 0xEC8028
+
+#define mmTPC3_QM_PQ_BASE_LO 0xEC8060
+
+#define mmTPC3_QM_PQ_BASE_HI 0xEC8064
+
+#define mmTPC3_QM_PQ_SIZE 0xEC8068
+
+#define mmTPC3_QM_PQ_PI 0xEC806C
+
+#define mmTPC3_QM_PQ_CI 0xEC8070
+
+#define mmTPC3_QM_PQ_CFG0 0xEC8074
+
+#define mmTPC3_QM_PQ_CFG1 0xEC8078
+
+#define mmTPC3_QM_PQ_ARUSER 0xEC807C
+
+#define mmTPC3_QM_PQ_PUSH0 0xEC8080
+
+#define mmTPC3_QM_PQ_PUSH1 0xEC8084
+
+#define mmTPC3_QM_PQ_PUSH2 0xEC8088
+
+#define mmTPC3_QM_PQ_PUSH3 0xEC808C
+
+#define mmTPC3_QM_PQ_STS0 0xEC8090
+
+#define mmTPC3_QM_PQ_STS1 0xEC8094
+
+#define mmTPC3_QM_PQ_RD_RATE_LIM_EN 0xEC80A0
+
+#define mmTPC3_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xEC80A4
+
+#define mmTPC3_QM_PQ_RD_RATE_LIM_SAT 0xEC80A8
+
+#define mmTPC3_QM_PQ_RD_RATE_LIM_TOUT 0xEC80AC
+
+#define mmTPC3_QM_CQ_CFG0 0xEC80B0
+
+#define mmTPC3_QM_CQ_CFG1 0xEC80B4
+
+#define mmTPC3_QM_CQ_ARUSER 0xEC80B8
+
+#define mmTPC3_QM_CQ_PTR_LO 0xEC80C0
+
+#define mmTPC3_QM_CQ_PTR_HI 0xEC80C4
+
+#define mmTPC3_QM_CQ_TSIZE 0xEC80C8
+
+#define mmTPC3_QM_CQ_CTL 0xEC80CC
+
+#define mmTPC3_QM_CQ_PTR_LO_STS 0xEC80D4
+
+#define mmTPC3_QM_CQ_PTR_HI_STS 0xEC80D8
+
+#define mmTPC3_QM_CQ_TSIZE_STS 0xEC80DC
+
+#define mmTPC3_QM_CQ_CTL_STS 0xEC80E0
+
+#define mmTPC3_QM_CQ_STS0 0xEC80E4
+
+#define mmTPC3_QM_CQ_STS1 0xEC80E8
+
+#define mmTPC3_QM_CQ_RD_RATE_LIM_EN 0xEC80F0
+
+#define mmTPC3_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xEC80F4
+
+#define mmTPC3_QM_CQ_RD_RATE_LIM_SAT 0xEC80F8
+
+#define mmTPC3_QM_CQ_RD_RATE_LIM_TOUT 0xEC80FC
+
+#define mmTPC3_QM_CQ_IFIFO_CNT 0xEC8108
+
+#define mmTPC3_QM_CP_MSG_BASE0_ADDR_LO 0xEC8120
+
+#define mmTPC3_QM_CP_MSG_BASE0_ADDR_HI 0xEC8124
+
+#define mmTPC3_QM_CP_MSG_BASE1_ADDR_LO 0xEC8128
+
+#define mmTPC3_QM_CP_MSG_BASE1_ADDR_HI 0xEC812C
+
+#define mmTPC3_QM_CP_MSG_BASE2_ADDR_LO 0xEC8130
+
+#define mmTPC3_QM_CP_MSG_BASE2_ADDR_HI 0xEC8134
+
+#define mmTPC3_QM_CP_MSG_BASE3_ADDR_LO 0xEC8138
+
+#define mmTPC3_QM_CP_MSG_BASE3_ADDR_HI 0xEC813C
+
+#define mmTPC3_QM_CP_LDMA_TSIZE_OFFSET 0xEC8140
+
+#define mmTPC3_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xEC8144
+
+#define mmTPC3_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xEC8148
+
+#define mmTPC3_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xEC814C
+
+#define mmTPC3_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xEC8150
+
+#define mmTPC3_QM_CP_LDMA_COMMIT_OFFSET 0xEC8154
+
+#define mmTPC3_QM_CP_FENCE0_RDATA 0xEC8158
+
+#define mmTPC3_QM_CP_FENCE1_RDATA 0xEC815C
+
+#define mmTPC3_QM_CP_FENCE2_RDATA 0xEC8160
+
+#define mmTPC3_QM_CP_FENCE3_RDATA 0xEC8164
+
+#define mmTPC3_QM_CP_FENCE0_CNT 0xEC8168
+
+#define mmTPC3_QM_CP_FENCE1_CNT 0xEC816C
+
+#define mmTPC3_QM_CP_FENCE2_CNT 0xEC8170
+
+#define mmTPC3_QM_CP_FENCE3_CNT 0xEC8174
+
+#define mmTPC3_QM_CP_STS 0xEC8178
+
+#define mmTPC3_QM_CP_CURRENT_INST_LO 0xEC817C
+
+#define mmTPC3_QM_CP_CURRENT_INST_HI 0xEC8180
+
+#define mmTPC3_QM_CP_BARRIER_CFG 0xEC8184
+
+#define mmTPC3_QM_CP_DBG_0 0xEC8188
+
+#define mmTPC3_QM_PQ_BUF_ADDR 0xEC8300
+
+#define mmTPC3_QM_PQ_BUF_RDATA 0xEC8304
+
+#define mmTPC3_QM_CQ_BUF_ADDR 0xEC8308
+
+#define mmTPC3_QM_CQ_BUF_RDATA 0xEC830C
+
+#endif /* ASIC_REG_TPC3_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h
new file mode 100644
index 000000000000..5a2fd7652650
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc3_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC3_RTR_REGS_H_
+#define ASIC_REG_TPC3_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC3_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC3_RTR_HBW_RD_RQ_E_ARB 0xEC0100
+
+#define mmTPC3_RTR_HBW_RD_RQ_W_ARB 0xEC0104
+
+#define mmTPC3_RTR_HBW_RD_RQ_N_ARB 0xEC0108
+
+#define mmTPC3_RTR_HBW_RD_RQ_S_ARB 0xEC010C
+
+#define mmTPC3_RTR_HBW_RD_RQ_L_ARB 0xEC0110
+
+#define mmTPC3_RTR_HBW_E_ARB_MAX 0xEC0120
+
+#define mmTPC3_RTR_HBW_W_ARB_MAX 0xEC0124
+
+#define mmTPC3_RTR_HBW_N_ARB_MAX 0xEC0128
+
+#define mmTPC3_RTR_HBW_S_ARB_MAX 0xEC012C
+
+#define mmTPC3_RTR_HBW_L_ARB_MAX 0xEC0130
+
+#define mmTPC3_RTR_HBW_RD_RS_E_ARB 0xEC0140
+
+#define mmTPC3_RTR_HBW_RD_RS_W_ARB 0xEC0144
+
+#define mmTPC3_RTR_HBW_RD_RS_N_ARB 0xEC0148
+
+#define mmTPC3_RTR_HBW_RD_RS_S_ARB 0xEC014C
+
+#define mmTPC3_RTR_HBW_RD_RS_L_ARB 0xEC0150
+
+#define mmTPC3_RTR_HBW_WR_RQ_E_ARB 0xEC0170
+
+#define mmTPC3_RTR_HBW_WR_RQ_W_ARB 0xEC0174
+
+#define mmTPC3_RTR_HBW_WR_RQ_N_ARB 0xEC0178
+
+#define mmTPC3_RTR_HBW_WR_RQ_S_ARB 0xEC017C
+
+#define mmTPC3_RTR_HBW_WR_RQ_L_ARB 0xEC0180
+
+#define mmTPC3_RTR_HBW_WR_RS_E_ARB 0xEC0190
+
+#define mmTPC3_RTR_HBW_WR_RS_W_ARB 0xEC0194
+
+#define mmTPC3_RTR_HBW_WR_RS_N_ARB 0xEC0198
+
+#define mmTPC3_RTR_HBW_WR_RS_S_ARB 0xEC019C
+
+#define mmTPC3_RTR_HBW_WR_RS_L_ARB 0xEC01A0
+
+#define mmTPC3_RTR_LBW_RD_RQ_E_ARB 0xEC0200
+
+#define mmTPC3_RTR_LBW_RD_RQ_W_ARB 0xEC0204
+
+#define mmTPC3_RTR_LBW_RD_RQ_N_ARB 0xEC0208
+
+#define mmTPC3_RTR_LBW_RD_RQ_S_ARB 0xEC020C
+
+#define mmTPC3_RTR_LBW_RD_RQ_L_ARB 0xEC0210
+
+#define mmTPC3_RTR_LBW_E_ARB_MAX 0xEC0220
+
+#define mmTPC3_RTR_LBW_W_ARB_MAX 0xEC0224
+
+#define mmTPC3_RTR_LBW_N_ARB_MAX 0xEC0228
+
+#define mmTPC3_RTR_LBW_S_ARB_MAX 0xEC022C
+
+#define mmTPC3_RTR_LBW_L_ARB_MAX 0xEC0230
+
+#define mmTPC3_RTR_LBW_RD_RS_E_ARB 0xEC0250
+
+#define mmTPC3_RTR_LBW_RD_RS_W_ARB 0xEC0254
+
+#define mmTPC3_RTR_LBW_RD_RS_N_ARB 0xEC0258
+
+#define mmTPC3_RTR_LBW_RD_RS_S_ARB 0xEC025C
+
+#define mmTPC3_RTR_LBW_RD_RS_L_ARB 0xEC0260
+
+#define mmTPC3_RTR_LBW_WR_RQ_E_ARB 0xEC0270
+
+#define mmTPC3_RTR_LBW_WR_RQ_W_ARB 0xEC0274
+
+#define mmTPC3_RTR_LBW_WR_RQ_N_ARB 0xEC0278
+
+#define mmTPC3_RTR_LBW_WR_RQ_S_ARB 0xEC027C
+
+#define mmTPC3_RTR_LBW_WR_RQ_L_ARB 0xEC0280
+
+#define mmTPC3_RTR_LBW_WR_RS_E_ARB 0xEC0290
+
+#define mmTPC3_RTR_LBW_WR_RS_W_ARB 0xEC0294
+
+#define mmTPC3_RTR_LBW_WR_RS_N_ARB 0xEC0298
+
+#define mmTPC3_RTR_LBW_WR_RS_S_ARB 0xEC029C
+
+#define mmTPC3_RTR_LBW_WR_RS_L_ARB 0xEC02A0
+
+#define mmTPC3_RTR_DBG_E_ARB 0xEC0300
+
+#define mmTPC3_RTR_DBG_W_ARB 0xEC0304
+
+#define mmTPC3_RTR_DBG_N_ARB 0xEC0308
+
+#define mmTPC3_RTR_DBG_S_ARB 0xEC030C
+
+#define mmTPC3_RTR_DBG_L_ARB 0xEC0310
+
+#define mmTPC3_RTR_DBG_E_ARB_MAX 0xEC0320
+
+#define mmTPC3_RTR_DBG_W_ARB_MAX 0xEC0324
+
+#define mmTPC3_RTR_DBG_N_ARB_MAX 0xEC0328
+
+#define mmTPC3_RTR_DBG_S_ARB_MAX 0xEC032C
+
+#define mmTPC3_RTR_DBG_L_ARB_MAX 0xEC0330
+
+#define mmTPC3_RTR_SPLIT_COEF_0 0xEC0400
+
+#define mmTPC3_RTR_SPLIT_COEF_1 0xEC0404
+
+#define mmTPC3_RTR_SPLIT_COEF_2 0xEC0408
+
+#define mmTPC3_RTR_SPLIT_COEF_3 0xEC040C
+
+#define mmTPC3_RTR_SPLIT_COEF_4 0xEC0410
+
+#define mmTPC3_RTR_SPLIT_COEF_5 0xEC0414
+
+#define mmTPC3_RTR_SPLIT_COEF_6 0xEC0418
+
+#define mmTPC3_RTR_SPLIT_COEF_7 0xEC041C
+
+#define mmTPC3_RTR_SPLIT_COEF_8 0xEC0420
+
+#define mmTPC3_RTR_SPLIT_COEF_9 0xEC0424
+
+#define mmTPC3_RTR_SPLIT_CFG 0xEC0440
+
+#define mmTPC3_RTR_SPLIT_RD_SAT 0xEC0444
+
+#define mmTPC3_RTR_SPLIT_RD_RST_TOKEN 0xEC0448
+
+#define mmTPC3_RTR_SPLIT_RD_TIMEOUT_0 0xEC044C
+
+#define mmTPC3_RTR_SPLIT_RD_TIMEOUT_1 0xEC0450
+
+#define mmTPC3_RTR_SPLIT_WR_SAT 0xEC0454
+
+#define mmTPC3_RTR_WPLIT_WR_TST_TOLEN 0xEC0458
+
+#define mmTPC3_RTR_SPLIT_WR_TIMEOUT_0 0xEC045C
+
+#define mmTPC3_RTR_SPLIT_WR_TIMEOUT_1 0xEC0460
+
+#define mmTPC3_RTR_HBW_RANGE_HIT 0xEC0470
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_0 0xEC0480
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_1 0xEC0484
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_2 0xEC0488
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_3 0xEC048C
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_4 0xEC0490
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_5 0xEC0494
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_6 0xEC0498
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_L_7 0xEC049C
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_0 0xEC04A0
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_1 0xEC04A4
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_2 0xEC04A8
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_3 0xEC04AC
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_4 0xEC04B0
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_5 0xEC04B4
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_6 0xEC04B8
+
+#define mmTPC3_RTR_HBW_RANGE_MASK_H_7 0xEC04BC
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_0 0xEC04C0
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_1 0xEC04C4
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_2 0xEC04C8
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_3 0xEC04CC
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_4 0xEC04D0
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_5 0xEC04D4
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_6 0xEC04D8
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_L_7 0xEC04DC
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_0 0xEC04E0
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_1 0xEC04E4
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_2 0xEC04E8
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_3 0xEC04EC
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_4 0xEC04F0
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_5 0xEC04F4
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_6 0xEC04F8
+
+#define mmTPC3_RTR_HBW_RANGE_BASE_H_7 0xEC04FC
+
+#define mmTPC3_RTR_LBW_RANGE_HIT 0xEC0500
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_0 0xEC0510
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_1 0xEC0514
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_2 0xEC0518
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_3 0xEC051C
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_4 0xEC0520
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_5 0xEC0524
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_6 0xEC0528
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_7 0xEC052C
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_8 0xEC0530
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_9 0xEC0534
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_10 0xEC0538
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_11 0xEC053C
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_12 0xEC0540
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_13 0xEC0544
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_14 0xEC0548
+
+#define mmTPC3_RTR_LBW_RANGE_MASK_15 0xEC054C
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_0 0xEC0550
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_1 0xEC0554
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_2 0xEC0558
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_3 0xEC055C
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_4 0xEC0560
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_5 0xEC0564
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_6 0xEC0568
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_7 0xEC056C
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_8 0xEC0570
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_9 0xEC0574
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_10 0xEC0578
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_11 0xEC057C
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_12 0xEC0580
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_13 0xEC0584
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_14 0xEC0588
+
+#define mmTPC3_RTR_LBW_RANGE_BASE_15 0xEC058C
+
+#define mmTPC3_RTR_RGLTR 0xEC0590
+
+#define mmTPC3_RTR_RGLTR_WR_RESULT 0xEC0594
+
+#define mmTPC3_RTR_RGLTR_RD_RESULT 0xEC0598
+
+#define mmTPC3_RTR_SCRAMB_EN 0xEC0600
+
+#define mmTPC3_RTR_NON_LIN_SCRAMB 0xEC0604
+
+#endif /* ASIC_REG_TPC3_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h
new file mode 100644
index 000000000000..d64a100075f2
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC4_CFG_REGS_H_
+#define ASIC_REG_TPC4_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC4_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xF06400
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xF06404
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xF06408
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xF0640C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xF06410
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xF06414
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xF06418
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xF0641C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xF06420
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xF06424
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xF06428
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xF0642C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xF06430
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xF06434
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xF06438
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xF0643C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xF06440
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xF06444
+
+#define mmTPC4_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xF06448
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xF0644C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xF06450
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xF06454
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xF06458
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xF0645C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xF06460
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xF06464
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xF06468
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xF0646C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xF06470
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xF06474
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xF06478
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xF0647C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xF06480
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xF06484
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xF06488
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xF0648C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xF06490
+
+#define mmTPC4_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xF06494
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xF06498
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xF0649C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xF064A0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xF064A4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xF064A8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xF064AC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xF064B0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xF064B4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xF064B8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xF064BC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xF064C0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xF064C4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xF064C8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xF064CC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xF064D0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xF064D4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xF064D8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xF064DC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xF064E0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xF064E4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xF064E8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xF064EC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xF064F0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xF064F4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xF064F8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xF064FC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xF06500
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xF06504
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xF06508
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xF0650C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xF06510
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xF06514
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xF06518
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xF0651C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xF06520
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xF06524
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xF06528
+
+#define mmTPC4_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xF0652C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xF06530
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xF06534
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xF06538
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xF0653C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xF06540
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xF06544
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xF06548
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xF0654C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xF06550
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xF06554
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xF06558
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xF0655C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xF06560
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xF06564
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xF06568
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xF0656C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xF06570
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xF06574
+
+#define mmTPC4_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xF06578
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xF0657C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xF06580
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xF06584
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xF06588
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xF0658C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xF06590
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xF06594
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xF06598
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xF0659C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xF065A0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xF065A4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xF065A8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xF065AC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xF065B0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xF065B4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xF065B8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xF065BC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xF065C0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xF065C4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xF065C8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xF065CC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xF065D0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xF065D4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xF065D8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xF065DC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xF065E0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xF065E4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xF065E8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xF065EC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xF065F0
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xF065F4
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xF065F8
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xF065FC
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xF06600
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xF06604
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xF06608
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xF0660C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xF06610
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xF06614
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xF06618
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xF0661C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xF06620
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xF06624
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xF06628
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xF0662C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xF06630
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xF06634
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xF06638
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xF0663C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xF06640
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xF06644
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xF06648
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xF0664C
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xF06650
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xF06654
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xF06658
+
+#define mmTPC4_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xF0665C
+
+#define mmTPC4_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xF06660
+
+#define mmTPC4_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xF06664
+
+#define mmTPC4_CFG_KERNEL_TID_BASE_DIM_0 0xF06668
+
+#define mmTPC4_CFG_KERNEL_TID_SIZE_DIM_0 0xF0666C
+
+#define mmTPC4_CFG_KERNEL_TID_BASE_DIM_1 0xF06670
+
+#define mmTPC4_CFG_KERNEL_TID_SIZE_DIM_1 0xF06674
+
+#define mmTPC4_CFG_KERNEL_TID_BASE_DIM_2 0xF06678
+
+#define mmTPC4_CFG_KERNEL_TID_SIZE_DIM_2 0xF0667C
+
+#define mmTPC4_CFG_KERNEL_TID_BASE_DIM_3 0xF06680
+
+#define mmTPC4_CFG_KERNEL_TID_SIZE_DIM_3 0xF06684
+
+#define mmTPC4_CFG_KERNEL_TID_BASE_DIM_4 0xF06688
+
+#define mmTPC4_CFG_KERNEL_TID_SIZE_DIM_4 0xF0668C
+
+#define mmTPC4_CFG_KERNEL_SRF_0 0xF06690
+
+#define mmTPC4_CFG_KERNEL_SRF_1 0xF06694
+
+#define mmTPC4_CFG_KERNEL_SRF_2 0xF06698
+
+#define mmTPC4_CFG_KERNEL_SRF_3 0xF0669C
+
+#define mmTPC4_CFG_KERNEL_SRF_4 0xF066A0
+
+#define mmTPC4_CFG_KERNEL_SRF_5 0xF066A4
+
+#define mmTPC4_CFG_KERNEL_SRF_6 0xF066A8
+
+#define mmTPC4_CFG_KERNEL_SRF_7 0xF066AC
+
+#define mmTPC4_CFG_KERNEL_SRF_8 0xF066B0
+
+#define mmTPC4_CFG_KERNEL_SRF_9 0xF066B4
+
+#define mmTPC4_CFG_KERNEL_SRF_10 0xF066B8
+
+#define mmTPC4_CFG_KERNEL_SRF_11 0xF066BC
+
+#define mmTPC4_CFG_KERNEL_SRF_12 0xF066C0
+
+#define mmTPC4_CFG_KERNEL_SRF_13 0xF066C4
+
+#define mmTPC4_CFG_KERNEL_SRF_14 0xF066C8
+
+#define mmTPC4_CFG_KERNEL_SRF_15 0xF066CC
+
+#define mmTPC4_CFG_KERNEL_SRF_16 0xF066D0
+
+#define mmTPC4_CFG_KERNEL_SRF_17 0xF066D4
+
+#define mmTPC4_CFG_KERNEL_SRF_18 0xF066D8
+
+#define mmTPC4_CFG_KERNEL_SRF_19 0xF066DC
+
+#define mmTPC4_CFG_KERNEL_SRF_20 0xF066E0
+
+#define mmTPC4_CFG_KERNEL_SRF_21 0xF066E4
+
+#define mmTPC4_CFG_KERNEL_SRF_22 0xF066E8
+
+#define mmTPC4_CFG_KERNEL_SRF_23 0xF066EC
+
+#define mmTPC4_CFG_KERNEL_SRF_24 0xF066F0
+
+#define mmTPC4_CFG_KERNEL_SRF_25 0xF066F4
+
+#define mmTPC4_CFG_KERNEL_SRF_26 0xF066F8
+
+#define mmTPC4_CFG_KERNEL_SRF_27 0xF066FC
+
+#define mmTPC4_CFG_KERNEL_SRF_28 0xF06700
+
+#define mmTPC4_CFG_KERNEL_SRF_29 0xF06704
+
+#define mmTPC4_CFG_KERNEL_SRF_30 0xF06708
+
+#define mmTPC4_CFG_KERNEL_SRF_31 0xF0670C
+
+#define mmTPC4_CFG_KERNEL_KERNEL_CONFIG 0xF06710
+
+#define mmTPC4_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xF06714
+
+#define mmTPC4_CFG_RESERVED_DESC_END 0xF06738
+
+#define mmTPC4_CFG_ROUND_CSR 0xF067FC
+
+#define mmTPC4_CFG_TBUF_BASE_ADDR_LOW 0xF06800
+
+#define mmTPC4_CFG_TBUF_BASE_ADDR_HIGH 0xF06804
+
+#define mmTPC4_CFG_SEMAPHORE 0xF06808
+
+#define mmTPC4_CFG_VFLAGS 0xF0680C
+
+#define mmTPC4_CFG_SFLAGS 0xF06810
+
+#define mmTPC4_CFG_LFSR_POLYNOM 0xF06818
+
+#define mmTPC4_CFG_STATUS 0xF0681C
+
+#define mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH 0xF06820
+
+#define mmTPC4_CFG_CFG_SUBTRACT_VALUE 0xF06824
+
+#define mmTPC4_CFG_SM_BASE_ADDRESS_LOW 0xF06828
+
+#define mmTPC4_CFG_SM_BASE_ADDRESS_HIGH 0xF0682C
+
+#define mmTPC4_CFG_TPC_CMD 0xF06830
+
+#define mmTPC4_CFG_TPC_EXECUTE 0xF06838
+
+#define mmTPC4_CFG_TPC_STALL 0xF0683C
+
+#define mmTPC4_CFG_ICACHE_BASE_ADDERESS_LOW 0xF06840
+
+#define mmTPC4_CFG_ICACHE_BASE_ADDERESS_HIGH 0xF06844
+
+#define mmTPC4_CFG_MSS_CONFIG 0xF06854
+
+#define mmTPC4_CFG_TPC_INTR_CAUSE 0xF06858
+
+#define mmTPC4_CFG_TPC_INTR_MASK 0xF0685C
+
+#define mmTPC4_CFG_TSB_CONFIG 0xF06860
+
+#define mmTPC4_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xF06A00
+
+#define mmTPC4_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xF06A04
+
+#define mmTPC4_CFG_QM_TENSOR_0_PADDING_VALUE 0xF06A08
+
+#define mmTPC4_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xF06A0C
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_0_SIZE 0xF06A10
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xF06A14
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xF06A18
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_1_SIZE 0xF06A1C
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xF06A20
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xF06A24
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_2_SIZE 0xF06A28
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xF06A2C
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xF06A30
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_3_SIZE 0xF06A34
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xF06A38
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xF06A3C
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_4_SIZE 0xF06A40
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xF06A44
+
+#define mmTPC4_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xF06A48
+
+#define mmTPC4_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xF06A4C
+
+#define mmTPC4_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xF06A50
+
+#define mmTPC4_CFG_QM_TENSOR_1_PADDING_VALUE 0xF06A54
+
+#define mmTPC4_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xF06A58
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_0_SIZE 0xF06A5C
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xF06A60
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xF06A64
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_1_SIZE 0xF06A68
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xF06A6C
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xF06A70
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_2_SIZE 0xF06A74
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xF06A78
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xF06A7C
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_3_SIZE 0xF06A80
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xF06A84
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xF06A88
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_4_SIZE 0xF06A8C
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xF06A90
+
+#define mmTPC4_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xF06A94
+
+#define mmTPC4_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xF06A98
+
+#define mmTPC4_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xF06A9C
+
+#define mmTPC4_CFG_QM_TENSOR_2_PADDING_VALUE 0xF06AA0
+
+#define mmTPC4_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xF06AA4
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_0_SIZE 0xF06AA8
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xF06AAC
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xF06AB0
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_1_SIZE 0xF06AB4
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xF06AB8
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xF06ABC
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_2_SIZE 0xF06AC0
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xF06AC4
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xF06AC8
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_3_SIZE 0xF06ACC
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xF06AD0
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xF06AD4
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_4_SIZE 0xF06AD8
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xF06ADC
+
+#define mmTPC4_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xF06AE0
+
+#define mmTPC4_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xF06AE4
+
+#define mmTPC4_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xF06AE8
+
+#define mmTPC4_CFG_QM_TENSOR_3_PADDING_VALUE 0xF06AEC
+
+#define mmTPC4_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xF06AF0
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_0_SIZE 0xF06AF4
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xF06AF8
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xF06AFC
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_1_SIZE 0xF06B00
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xF06B04
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xF06B08
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_2_SIZE 0xF06B0C
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xF06B10
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xF06B14
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_3_SIZE 0xF06B18
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xF06B1C
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xF06B20
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_4_SIZE 0xF06B24
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xF06B28
+
+#define mmTPC4_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xF06B2C
+
+#define mmTPC4_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xF06B30
+
+#define mmTPC4_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xF06B34
+
+#define mmTPC4_CFG_QM_TENSOR_4_PADDING_VALUE 0xF06B38
+
+#define mmTPC4_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xF06B3C
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_0_SIZE 0xF06B40
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xF06B44
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xF06B48
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_1_SIZE 0xF06B4C
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xF06B50
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xF06B54
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_2_SIZE 0xF06B58
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xF06B5C
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xF06B60
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_3_SIZE 0xF06B64
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xF06B68
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xF06B6C
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_4_SIZE 0xF06B70
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xF06B74
+
+#define mmTPC4_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xF06B78
+
+#define mmTPC4_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xF06B7C
+
+#define mmTPC4_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xF06B80
+
+#define mmTPC4_CFG_QM_TENSOR_5_PADDING_VALUE 0xF06B84
+
+#define mmTPC4_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xF06B88
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_0_SIZE 0xF06B8C
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xF06B90
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xF06B94
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_1_SIZE 0xF06B98
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xF06B9C
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xF06BA0
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_2_SIZE 0xF06BA4
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xF06BA8
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xF06BAC
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_3_SIZE 0xF06BB0
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xF06BB4
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xF06BB8
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_4_SIZE 0xF06BBC
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xF06BC0
+
+#define mmTPC4_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xF06BC4
+
+#define mmTPC4_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xF06BC8
+
+#define mmTPC4_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xF06BCC
+
+#define mmTPC4_CFG_QM_TENSOR_6_PADDING_VALUE 0xF06BD0
+
+#define mmTPC4_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xF06BD4
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_0_SIZE 0xF06BD8
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xF06BDC
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xF06BE0
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_1_SIZE 0xF06BE4
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xF06BE8
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xF06BEC
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_2_SIZE 0xF06BF0
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xF06BF4
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xF06BF8
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_3_SIZE 0xF06BFC
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xF06C00
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xF06C04
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_4_SIZE 0xF06C08
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xF06C0C
+
+#define mmTPC4_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xF06C10
+
+#define mmTPC4_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xF06C14
+
+#define mmTPC4_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xF06C18
+
+#define mmTPC4_CFG_QM_TENSOR_7_PADDING_VALUE 0xF06C1C
+
+#define mmTPC4_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xF06C20
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_0_SIZE 0xF06C24
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xF06C28
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xF06C2C
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_1_SIZE 0xF06C30
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xF06C34
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xF06C38
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_2_SIZE 0xF06C3C
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xF06C40
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xF06C44
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_3_SIZE 0xF06C48
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xF06C4C
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xF06C50
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_4_SIZE 0xF06C54
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xF06C58
+
+#define mmTPC4_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xF06C5C
+
+#define mmTPC4_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xF06C60
+
+#define mmTPC4_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xF06C64
+
+#define mmTPC4_CFG_QM_TID_BASE_DIM_0 0xF06C68
+
+#define mmTPC4_CFG_QM_TID_SIZE_DIM_0 0xF06C6C
+
+#define mmTPC4_CFG_QM_TID_BASE_DIM_1 0xF06C70
+
+#define mmTPC4_CFG_QM_TID_SIZE_DIM_1 0xF06C74
+
+#define mmTPC4_CFG_QM_TID_BASE_DIM_2 0xF06C78
+
+#define mmTPC4_CFG_QM_TID_SIZE_DIM_2 0xF06C7C
+
+#define mmTPC4_CFG_QM_TID_BASE_DIM_3 0xF06C80
+
+#define mmTPC4_CFG_QM_TID_SIZE_DIM_3 0xF06C84
+
+#define mmTPC4_CFG_QM_TID_BASE_DIM_4 0xF06C88
+
+#define mmTPC4_CFG_QM_TID_SIZE_DIM_4 0xF06C8C
+
+#define mmTPC4_CFG_QM_SRF_0 0xF06C90
+
+#define mmTPC4_CFG_QM_SRF_1 0xF06C94
+
+#define mmTPC4_CFG_QM_SRF_2 0xF06C98
+
+#define mmTPC4_CFG_QM_SRF_3 0xF06C9C
+
+#define mmTPC4_CFG_QM_SRF_4 0xF06CA0
+
+#define mmTPC4_CFG_QM_SRF_5 0xF06CA4
+
+#define mmTPC4_CFG_QM_SRF_6 0xF06CA8
+
+#define mmTPC4_CFG_QM_SRF_7 0xF06CAC
+
+#define mmTPC4_CFG_QM_SRF_8 0xF06CB0
+
+#define mmTPC4_CFG_QM_SRF_9 0xF06CB4
+
+#define mmTPC4_CFG_QM_SRF_10 0xF06CB8
+
+#define mmTPC4_CFG_QM_SRF_11 0xF06CBC
+
+#define mmTPC4_CFG_QM_SRF_12 0xF06CC0
+
+#define mmTPC4_CFG_QM_SRF_13 0xF06CC4
+
+#define mmTPC4_CFG_QM_SRF_14 0xF06CC8
+
+#define mmTPC4_CFG_QM_SRF_15 0xF06CCC
+
+#define mmTPC4_CFG_QM_SRF_16 0xF06CD0
+
+#define mmTPC4_CFG_QM_SRF_17 0xF06CD4
+
+#define mmTPC4_CFG_QM_SRF_18 0xF06CD8
+
+#define mmTPC4_CFG_QM_SRF_19 0xF06CDC
+
+#define mmTPC4_CFG_QM_SRF_20 0xF06CE0
+
+#define mmTPC4_CFG_QM_SRF_21 0xF06CE4
+
+#define mmTPC4_CFG_QM_SRF_22 0xF06CE8
+
+#define mmTPC4_CFG_QM_SRF_23 0xF06CEC
+
+#define mmTPC4_CFG_QM_SRF_24 0xF06CF0
+
+#define mmTPC4_CFG_QM_SRF_25 0xF06CF4
+
+#define mmTPC4_CFG_QM_SRF_26 0xF06CF8
+
+#define mmTPC4_CFG_QM_SRF_27 0xF06CFC
+
+#define mmTPC4_CFG_QM_SRF_28 0xF06D00
+
+#define mmTPC4_CFG_QM_SRF_29 0xF06D04
+
+#define mmTPC4_CFG_QM_SRF_30 0xF06D08
+
+#define mmTPC4_CFG_QM_SRF_31 0xF06D0C
+
+#define mmTPC4_CFG_QM_KERNEL_CONFIG 0xF06D10
+
+#define mmTPC4_CFG_QM_SYNC_OBJECT_MESSAGE 0xF06D14
+
+#define mmTPC4_CFG_ARUSER 0xF06D18
+
+#define mmTPC4_CFG_AWUSER 0xF06D1C
+
+#define mmTPC4_CFG_FUNC_MBIST_CNTRL 0xF06E00
+
+#define mmTPC4_CFG_FUNC_MBIST_PAT 0xF06E04
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_0 0xF06E08
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_1 0xF06E0C
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_2 0xF06E10
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_3 0xF06E14
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_4 0xF06E18
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_5 0xF06E1C
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_6 0xF06E20
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_7 0xF06E24
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_8 0xF06E28
+
+#define mmTPC4_CFG_FUNC_MBIST_MEM_9 0xF06E2C
+
+#endif /* ASIC_REG_TPC4_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h
new file mode 100644
index 000000000000..565b42885b0d
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC4_CMDQ_REGS_H_
+#define ASIC_REG_TPC4_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC4_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC4_CMDQ_GLBL_CFG0 0xF09000
+
+#define mmTPC4_CMDQ_GLBL_CFG1 0xF09004
+
+#define mmTPC4_CMDQ_GLBL_PROT 0xF09008
+
+#define mmTPC4_CMDQ_GLBL_ERR_CFG 0xF0900C
+
+#define mmTPC4_CMDQ_GLBL_ERR_ADDR_LO 0xF09010
+
+#define mmTPC4_CMDQ_GLBL_ERR_ADDR_HI 0xF09014
+
+#define mmTPC4_CMDQ_GLBL_ERR_WDATA 0xF09018
+
+#define mmTPC4_CMDQ_GLBL_SECURE_PROPS 0xF0901C
+
+#define mmTPC4_CMDQ_GLBL_NON_SECURE_PROPS 0xF09020
+
+#define mmTPC4_CMDQ_GLBL_STS0 0xF09024
+
+#define mmTPC4_CMDQ_GLBL_STS1 0xF09028
+
+#define mmTPC4_CMDQ_CQ_CFG0 0xF090B0
+
+#define mmTPC4_CMDQ_CQ_CFG1 0xF090B4
+
+#define mmTPC4_CMDQ_CQ_ARUSER 0xF090B8
+
+#define mmTPC4_CMDQ_CQ_PTR_LO 0xF090C0
+
+#define mmTPC4_CMDQ_CQ_PTR_HI 0xF090C4
+
+#define mmTPC4_CMDQ_CQ_TSIZE 0xF090C8
+
+#define mmTPC4_CMDQ_CQ_CTL 0xF090CC
+
+#define mmTPC4_CMDQ_CQ_PTR_LO_STS 0xF090D4
+
+#define mmTPC4_CMDQ_CQ_PTR_HI_STS 0xF090D8
+
+#define mmTPC4_CMDQ_CQ_TSIZE_STS 0xF090DC
+
+#define mmTPC4_CMDQ_CQ_CTL_STS 0xF090E0
+
+#define mmTPC4_CMDQ_CQ_STS0 0xF090E4
+
+#define mmTPC4_CMDQ_CQ_STS1 0xF090E8
+
+#define mmTPC4_CMDQ_CQ_RD_RATE_LIM_EN 0xF090F0
+
+#define mmTPC4_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xF090F4
+
+#define mmTPC4_CMDQ_CQ_RD_RATE_LIM_SAT 0xF090F8
+
+#define mmTPC4_CMDQ_CQ_RD_RATE_LIM_TOUT 0xF090FC
+
+#define mmTPC4_CMDQ_CQ_IFIFO_CNT 0xF09108
+
+#define mmTPC4_CMDQ_CP_MSG_BASE0_ADDR_LO 0xF09120
+
+#define mmTPC4_CMDQ_CP_MSG_BASE0_ADDR_HI 0xF09124
+
+#define mmTPC4_CMDQ_CP_MSG_BASE1_ADDR_LO 0xF09128
+
+#define mmTPC4_CMDQ_CP_MSG_BASE1_ADDR_HI 0xF0912C
+
+#define mmTPC4_CMDQ_CP_MSG_BASE2_ADDR_LO 0xF09130
+
+#define mmTPC4_CMDQ_CP_MSG_BASE2_ADDR_HI 0xF09134
+
+#define mmTPC4_CMDQ_CP_MSG_BASE3_ADDR_LO 0xF09138
+
+#define mmTPC4_CMDQ_CP_MSG_BASE3_ADDR_HI 0xF0913C
+
+#define mmTPC4_CMDQ_CP_LDMA_TSIZE_OFFSET 0xF09140
+
+#define mmTPC4_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xF09144
+
+#define mmTPC4_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xF09148
+
+#define mmTPC4_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xF0914C
+
+#define mmTPC4_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xF09150
+
+#define mmTPC4_CMDQ_CP_LDMA_COMMIT_OFFSET 0xF09154
+
+#define mmTPC4_CMDQ_CP_FENCE0_RDATA 0xF09158
+
+#define mmTPC4_CMDQ_CP_FENCE1_RDATA 0xF0915C
+
+#define mmTPC4_CMDQ_CP_FENCE2_RDATA 0xF09160
+
+#define mmTPC4_CMDQ_CP_FENCE3_RDATA 0xF09164
+
+#define mmTPC4_CMDQ_CP_FENCE0_CNT 0xF09168
+
+#define mmTPC4_CMDQ_CP_FENCE1_CNT 0xF0916C
+
+#define mmTPC4_CMDQ_CP_FENCE2_CNT 0xF09170
+
+#define mmTPC4_CMDQ_CP_FENCE3_CNT 0xF09174
+
+#define mmTPC4_CMDQ_CP_STS 0xF09178
+
+#define mmTPC4_CMDQ_CP_CURRENT_INST_LO 0xF0917C
+
+#define mmTPC4_CMDQ_CP_CURRENT_INST_HI 0xF09180
+
+#define mmTPC4_CMDQ_CP_BARRIER_CFG 0xF09184
+
+#define mmTPC4_CMDQ_CP_DBG_0 0xF09188
+
+#define mmTPC4_CMDQ_CQ_BUF_ADDR 0xF09308
+
+#define mmTPC4_CMDQ_CQ_BUF_RDATA 0xF0930C
+
+#endif /* ASIC_REG_TPC4_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h
new file mode 100644
index 000000000000..196da3f12710
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC4_QM_REGS_H_
+#define ASIC_REG_TPC4_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC4_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC4_QM_GLBL_CFG0 0xF08000
+
+#define mmTPC4_QM_GLBL_CFG1 0xF08004
+
+#define mmTPC4_QM_GLBL_PROT 0xF08008
+
+#define mmTPC4_QM_GLBL_ERR_CFG 0xF0800C
+
+#define mmTPC4_QM_GLBL_ERR_ADDR_LO 0xF08010
+
+#define mmTPC4_QM_GLBL_ERR_ADDR_HI 0xF08014
+
+#define mmTPC4_QM_GLBL_ERR_WDATA 0xF08018
+
+#define mmTPC4_QM_GLBL_SECURE_PROPS 0xF0801C
+
+#define mmTPC4_QM_GLBL_NON_SECURE_PROPS 0xF08020
+
+#define mmTPC4_QM_GLBL_STS0 0xF08024
+
+#define mmTPC4_QM_GLBL_STS1 0xF08028
+
+#define mmTPC4_QM_PQ_BASE_LO 0xF08060
+
+#define mmTPC4_QM_PQ_BASE_HI 0xF08064
+
+#define mmTPC4_QM_PQ_SIZE 0xF08068
+
+#define mmTPC4_QM_PQ_PI 0xF0806C
+
+#define mmTPC4_QM_PQ_CI 0xF08070
+
+#define mmTPC4_QM_PQ_CFG0 0xF08074
+
+#define mmTPC4_QM_PQ_CFG1 0xF08078
+
+#define mmTPC4_QM_PQ_ARUSER 0xF0807C
+
+#define mmTPC4_QM_PQ_PUSH0 0xF08080
+
+#define mmTPC4_QM_PQ_PUSH1 0xF08084
+
+#define mmTPC4_QM_PQ_PUSH2 0xF08088
+
+#define mmTPC4_QM_PQ_PUSH3 0xF0808C
+
+#define mmTPC4_QM_PQ_STS0 0xF08090
+
+#define mmTPC4_QM_PQ_STS1 0xF08094
+
+#define mmTPC4_QM_PQ_RD_RATE_LIM_EN 0xF080A0
+
+#define mmTPC4_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xF080A4
+
+#define mmTPC4_QM_PQ_RD_RATE_LIM_SAT 0xF080A8
+
+#define mmTPC4_QM_PQ_RD_RATE_LIM_TOUT 0xF080AC
+
+#define mmTPC4_QM_CQ_CFG0 0xF080B0
+
+#define mmTPC4_QM_CQ_CFG1 0xF080B4
+
+#define mmTPC4_QM_CQ_ARUSER 0xF080B8
+
+#define mmTPC4_QM_CQ_PTR_LO 0xF080C0
+
+#define mmTPC4_QM_CQ_PTR_HI 0xF080C4
+
+#define mmTPC4_QM_CQ_TSIZE 0xF080C8
+
+#define mmTPC4_QM_CQ_CTL 0xF080CC
+
+#define mmTPC4_QM_CQ_PTR_LO_STS 0xF080D4
+
+#define mmTPC4_QM_CQ_PTR_HI_STS 0xF080D8
+
+#define mmTPC4_QM_CQ_TSIZE_STS 0xF080DC
+
+#define mmTPC4_QM_CQ_CTL_STS 0xF080E0
+
+#define mmTPC4_QM_CQ_STS0 0xF080E4
+
+#define mmTPC4_QM_CQ_STS1 0xF080E8
+
+#define mmTPC4_QM_CQ_RD_RATE_LIM_EN 0xF080F0
+
+#define mmTPC4_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xF080F4
+
+#define mmTPC4_QM_CQ_RD_RATE_LIM_SAT 0xF080F8
+
+#define mmTPC4_QM_CQ_RD_RATE_LIM_TOUT 0xF080FC
+
+#define mmTPC4_QM_CQ_IFIFO_CNT 0xF08108
+
+#define mmTPC4_QM_CP_MSG_BASE0_ADDR_LO 0xF08120
+
+#define mmTPC4_QM_CP_MSG_BASE0_ADDR_HI 0xF08124
+
+#define mmTPC4_QM_CP_MSG_BASE1_ADDR_LO 0xF08128
+
+#define mmTPC4_QM_CP_MSG_BASE1_ADDR_HI 0xF0812C
+
+#define mmTPC4_QM_CP_MSG_BASE2_ADDR_LO 0xF08130
+
+#define mmTPC4_QM_CP_MSG_BASE2_ADDR_HI 0xF08134
+
+#define mmTPC4_QM_CP_MSG_BASE3_ADDR_LO 0xF08138
+
+#define mmTPC4_QM_CP_MSG_BASE3_ADDR_HI 0xF0813C
+
+#define mmTPC4_QM_CP_LDMA_TSIZE_OFFSET 0xF08140
+
+#define mmTPC4_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xF08144
+
+#define mmTPC4_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xF08148
+
+#define mmTPC4_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xF0814C
+
+#define mmTPC4_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xF08150
+
+#define mmTPC4_QM_CP_LDMA_COMMIT_OFFSET 0xF08154
+
+#define mmTPC4_QM_CP_FENCE0_RDATA 0xF08158
+
+#define mmTPC4_QM_CP_FENCE1_RDATA 0xF0815C
+
+#define mmTPC4_QM_CP_FENCE2_RDATA 0xF08160
+
+#define mmTPC4_QM_CP_FENCE3_RDATA 0xF08164
+
+#define mmTPC4_QM_CP_FENCE0_CNT 0xF08168
+
+#define mmTPC4_QM_CP_FENCE1_CNT 0xF0816C
+
+#define mmTPC4_QM_CP_FENCE2_CNT 0xF08170
+
+#define mmTPC4_QM_CP_FENCE3_CNT 0xF08174
+
+#define mmTPC4_QM_CP_STS 0xF08178
+
+#define mmTPC4_QM_CP_CURRENT_INST_LO 0xF0817C
+
+#define mmTPC4_QM_CP_CURRENT_INST_HI 0xF08180
+
+#define mmTPC4_QM_CP_BARRIER_CFG 0xF08184
+
+#define mmTPC4_QM_CP_DBG_0 0xF08188
+
+#define mmTPC4_QM_PQ_BUF_ADDR 0xF08300
+
+#define mmTPC4_QM_PQ_BUF_RDATA 0xF08304
+
+#define mmTPC4_QM_CQ_BUF_ADDR 0xF08308
+
+#define mmTPC4_QM_CQ_BUF_RDATA 0xF0830C
+
+#endif /* ASIC_REG_TPC4_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h
new file mode 100644
index 000000000000..8b54041d144a
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc4_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC4_RTR_REGS_H_
+#define ASIC_REG_TPC4_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC4_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC4_RTR_HBW_RD_RQ_E_ARB 0xF00100
+
+#define mmTPC4_RTR_HBW_RD_RQ_W_ARB 0xF00104
+
+#define mmTPC4_RTR_HBW_RD_RQ_N_ARB 0xF00108
+
+#define mmTPC4_RTR_HBW_RD_RQ_S_ARB 0xF0010C
+
+#define mmTPC4_RTR_HBW_RD_RQ_L_ARB 0xF00110
+
+#define mmTPC4_RTR_HBW_E_ARB_MAX 0xF00120
+
+#define mmTPC4_RTR_HBW_W_ARB_MAX 0xF00124
+
+#define mmTPC4_RTR_HBW_N_ARB_MAX 0xF00128
+
+#define mmTPC4_RTR_HBW_S_ARB_MAX 0xF0012C
+
+#define mmTPC4_RTR_HBW_L_ARB_MAX 0xF00130
+
+#define mmTPC4_RTR_HBW_RD_RS_E_ARB 0xF00140
+
+#define mmTPC4_RTR_HBW_RD_RS_W_ARB 0xF00144
+
+#define mmTPC4_RTR_HBW_RD_RS_N_ARB 0xF00148
+
+#define mmTPC4_RTR_HBW_RD_RS_S_ARB 0xF0014C
+
+#define mmTPC4_RTR_HBW_RD_RS_L_ARB 0xF00150
+
+#define mmTPC4_RTR_HBW_WR_RQ_E_ARB 0xF00170
+
+#define mmTPC4_RTR_HBW_WR_RQ_W_ARB 0xF00174
+
+#define mmTPC4_RTR_HBW_WR_RQ_N_ARB 0xF00178
+
+#define mmTPC4_RTR_HBW_WR_RQ_S_ARB 0xF0017C
+
+#define mmTPC4_RTR_HBW_WR_RQ_L_ARB 0xF00180
+
+#define mmTPC4_RTR_HBW_WR_RS_E_ARB 0xF00190
+
+#define mmTPC4_RTR_HBW_WR_RS_W_ARB 0xF00194
+
+#define mmTPC4_RTR_HBW_WR_RS_N_ARB 0xF00198
+
+#define mmTPC4_RTR_HBW_WR_RS_S_ARB 0xF0019C
+
+#define mmTPC4_RTR_HBW_WR_RS_L_ARB 0xF001A0
+
+#define mmTPC4_RTR_LBW_RD_RQ_E_ARB 0xF00200
+
+#define mmTPC4_RTR_LBW_RD_RQ_W_ARB 0xF00204
+
+#define mmTPC4_RTR_LBW_RD_RQ_N_ARB 0xF00208
+
+#define mmTPC4_RTR_LBW_RD_RQ_S_ARB 0xF0020C
+
+#define mmTPC4_RTR_LBW_RD_RQ_L_ARB 0xF00210
+
+#define mmTPC4_RTR_LBW_E_ARB_MAX 0xF00220
+
+#define mmTPC4_RTR_LBW_W_ARB_MAX 0xF00224
+
+#define mmTPC4_RTR_LBW_N_ARB_MAX 0xF00228
+
+#define mmTPC4_RTR_LBW_S_ARB_MAX 0xF0022C
+
+#define mmTPC4_RTR_LBW_L_ARB_MAX 0xF00230
+
+#define mmTPC4_RTR_LBW_RD_RS_E_ARB 0xF00250
+
+#define mmTPC4_RTR_LBW_RD_RS_W_ARB 0xF00254
+
+#define mmTPC4_RTR_LBW_RD_RS_N_ARB 0xF00258
+
+#define mmTPC4_RTR_LBW_RD_RS_S_ARB 0xF0025C
+
+#define mmTPC4_RTR_LBW_RD_RS_L_ARB 0xF00260
+
+#define mmTPC4_RTR_LBW_WR_RQ_E_ARB 0xF00270
+
+#define mmTPC4_RTR_LBW_WR_RQ_W_ARB 0xF00274
+
+#define mmTPC4_RTR_LBW_WR_RQ_N_ARB 0xF00278
+
+#define mmTPC4_RTR_LBW_WR_RQ_S_ARB 0xF0027C
+
+#define mmTPC4_RTR_LBW_WR_RQ_L_ARB 0xF00280
+
+#define mmTPC4_RTR_LBW_WR_RS_E_ARB 0xF00290
+
+#define mmTPC4_RTR_LBW_WR_RS_W_ARB 0xF00294
+
+#define mmTPC4_RTR_LBW_WR_RS_N_ARB 0xF00298
+
+#define mmTPC4_RTR_LBW_WR_RS_S_ARB 0xF0029C
+
+#define mmTPC4_RTR_LBW_WR_RS_L_ARB 0xF002A0
+
+#define mmTPC4_RTR_DBG_E_ARB 0xF00300
+
+#define mmTPC4_RTR_DBG_W_ARB 0xF00304
+
+#define mmTPC4_RTR_DBG_N_ARB 0xF00308
+
+#define mmTPC4_RTR_DBG_S_ARB 0xF0030C
+
+#define mmTPC4_RTR_DBG_L_ARB 0xF00310
+
+#define mmTPC4_RTR_DBG_E_ARB_MAX 0xF00320
+
+#define mmTPC4_RTR_DBG_W_ARB_MAX 0xF00324
+
+#define mmTPC4_RTR_DBG_N_ARB_MAX 0xF00328
+
+#define mmTPC4_RTR_DBG_S_ARB_MAX 0xF0032C
+
+#define mmTPC4_RTR_DBG_L_ARB_MAX 0xF00330
+
+#define mmTPC4_RTR_SPLIT_COEF_0 0xF00400
+
+#define mmTPC4_RTR_SPLIT_COEF_1 0xF00404
+
+#define mmTPC4_RTR_SPLIT_COEF_2 0xF00408
+
+#define mmTPC4_RTR_SPLIT_COEF_3 0xF0040C
+
+#define mmTPC4_RTR_SPLIT_COEF_4 0xF00410
+
+#define mmTPC4_RTR_SPLIT_COEF_5 0xF00414
+
+#define mmTPC4_RTR_SPLIT_COEF_6 0xF00418
+
+#define mmTPC4_RTR_SPLIT_COEF_7 0xF0041C
+
+#define mmTPC4_RTR_SPLIT_COEF_8 0xF00420
+
+#define mmTPC4_RTR_SPLIT_COEF_9 0xF00424
+
+#define mmTPC4_RTR_SPLIT_CFG 0xF00440
+
+#define mmTPC4_RTR_SPLIT_RD_SAT 0xF00444
+
+#define mmTPC4_RTR_SPLIT_RD_RST_TOKEN 0xF00448
+
+#define mmTPC4_RTR_SPLIT_RD_TIMEOUT_0 0xF0044C
+
+#define mmTPC4_RTR_SPLIT_RD_TIMEOUT_1 0xF00450
+
+#define mmTPC4_RTR_SPLIT_WR_SAT 0xF00454
+
+#define mmTPC4_RTR_WPLIT_WR_TST_TOLEN 0xF00458
+
+#define mmTPC4_RTR_SPLIT_WR_TIMEOUT_0 0xF0045C
+
+#define mmTPC4_RTR_SPLIT_WR_TIMEOUT_1 0xF00460
+
+#define mmTPC4_RTR_HBW_RANGE_HIT 0xF00470
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_0 0xF00480
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_1 0xF00484
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_2 0xF00488
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_3 0xF0048C
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_4 0xF00490
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_5 0xF00494
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_6 0xF00498
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_L_7 0xF0049C
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_0 0xF004A0
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_1 0xF004A4
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_2 0xF004A8
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_3 0xF004AC
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_4 0xF004B0
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_5 0xF004B4
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_6 0xF004B8
+
+#define mmTPC4_RTR_HBW_RANGE_MASK_H_7 0xF004BC
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_0 0xF004C0
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_1 0xF004C4
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_2 0xF004C8
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_3 0xF004CC
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_4 0xF004D0
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_5 0xF004D4
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_6 0xF004D8
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_L_7 0xF004DC
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_0 0xF004E0
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_1 0xF004E4
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_2 0xF004E8
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_3 0xF004EC
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_4 0xF004F0
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_5 0xF004F4
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_6 0xF004F8
+
+#define mmTPC4_RTR_HBW_RANGE_BASE_H_7 0xF004FC
+
+#define mmTPC4_RTR_LBW_RANGE_HIT 0xF00500
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_0 0xF00510
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_1 0xF00514
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_2 0xF00518
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_3 0xF0051C
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_4 0xF00520
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_5 0xF00524
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_6 0xF00528
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_7 0xF0052C
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_8 0xF00530
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_9 0xF00534
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_10 0xF00538
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_11 0xF0053C
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_12 0xF00540
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_13 0xF00544
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_14 0xF00548
+
+#define mmTPC4_RTR_LBW_RANGE_MASK_15 0xF0054C
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_0 0xF00550
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_1 0xF00554
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_2 0xF00558
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_3 0xF0055C
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_4 0xF00560
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_5 0xF00564
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_6 0xF00568
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_7 0xF0056C
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_8 0xF00570
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_9 0xF00574
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_10 0xF00578
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_11 0xF0057C
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_12 0xF00580
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_13 0xF00584
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_14 0xF00588
+
+#define mmTPC4_RTR_LBW_RANGE_BASE_15 0xF0058C
+
+#define mmTPC4_RTR_RGLTR 0xF00590
+
+#define mmTPC4_RTR_RGLTR_WR_RESULT 0xF00594
+
+#define mmTPC4_RTR_RGLTR_RD_RESULT 0xF00598
+
+#define mmTPC4_RTR_SCRAMB_EN 0xF00600
+
+#define mmTPC4_RTR_NON_LIN_SCRAMB 0xF00604
+
+#endif /* ASIC_REG_TPC4_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h
new file mode 100644
index 000000000000..3f00954fcdba
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC5_CFG_REGS_H_
+#define ASIC_REG_TPC5_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC5_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xF46400
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xF46404
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xF46408
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xF4640C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xF46410
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xF46414
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xF46418
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xF4641C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xF46420
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xF46424
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xF46428
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xF4642C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xF46430
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xF46434
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xF46438
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xF4643C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xF46440
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xF46444
+
+#define mmTPC5_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xF46448
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xF4644C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xF46450
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xF46454
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xF46458
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xF4645C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xF46460
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xF46464
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xF46468
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xF4646C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xF46470
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xF46474
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xF46478
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xF4647C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xF46480
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xF46484
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xF46488
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xF4648C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xF46490
+
+#define mmTPC5_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xF46494
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xF46498
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xF4649C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xF464A0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xF464A4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xF464A8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xF464AC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xF464B0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xF464B4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xF464B8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xF464BC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xF464C0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xF464C4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xF464C8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xF464CC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xF464D0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xF464D4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xF464D8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xF464DC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xF464E0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xF464E4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xF464E8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xF464EC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xF464F0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xF464F4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xF464F8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xF464FC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xF46500
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xF46504
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xF46508
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xF4650C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xF46510
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xF46514
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xF46518
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xF4651C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xF46520
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xF46524
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xF46528
+
+#define mmTPC5_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xF4652C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xF46530
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xF46534
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xF46538
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xF4653C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xF46540
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xF46544
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xF46548
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xF4654C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xF46550
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xF46554
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xF46558
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xF4655C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xF46560
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xF46564
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xF46568
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xF4656C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xF46570
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xF46574
+
+#define mmTPC5_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xF46578
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xF4657C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xF46580
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xF46584
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xF46588
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xF4658C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xF46590
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xF46594
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xF46598
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xF4659C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xF465A0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xF465A4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xF465A8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xF465AC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xF465B0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xF465B4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xF465B8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xF465BC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xF465C0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xF465C4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xF465C8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xF465CC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xF465D0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xF465D4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xF465D8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xF465DC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xF465E0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xF465E4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xF465E8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xF465EC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xF465F0
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xF465F4
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xF465F8
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xF465FC
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xF46600
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xF46604
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xF46608
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xF4660C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xF46610
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xF46614
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xF46618
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xF4661C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xF46620
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xF46624
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xF46628
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xF4662C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xF46630
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xF46634
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xF46638
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xF4663C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xF46640
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xF46644
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xF46648
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xF4664C
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xF46650
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xF46654
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xF46658
+
+#define mmTPC5_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xF4665C
+
+#define mmTPC5_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xF46660
+
+#define mmTPC5_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xF46664
+
+#define mmTPC5_CFG_KERNEL_TID_BASE_DIM_0 0xF46668
+
+#define mmTPC5_CFG_KERNEL_TID_SIZE_DIM_0 0xF4666C
+
+#define mmTPC5_CFG_KERNEL_TID_BASE_DIM_1 0xF46670
+
+#define mmTPC5_CFG_KERNEL_TID_SIZE_DIM_1 0xF46674
+
+#define mmTPC5_CFG_KERNEL_TID_BASE_DIM_2 0xF46678
+
+#define mmTPC5_CFG_KERNEL_TID_SIZE_DIM_2 0xF4667C
+
+#define mmTPC5_CFG_KERNEL_TID_BASE_DIM_3 0xF46680
+
+#define mmTPC5_CFG_KERNEL_TID_SIZE_DIM_3 0xF46684
+
+#define mmTPC5_CFG_KERNEL_TID_BASE_DIM_4 0xF46688
+
+#define mmTPC5_CFG_KERNEL_TID_SIZE_DIM_4 0xF4668C
+
+#define mmTPC5_CFG_KERNEL_SRF_0 0xF46690
+
+#define mmTPC5_CFG_KERNEL_SRF_1 0xF46694
+
+#define mmTPC5_CFG_KERNEL_SRF_2 0xF46698
+
+#define mmTPC5_CFG_KERNEL_SRF_3 0xF4669C
+
+#define mmTPC5_CFG_KERNEL_SRF_4 0xF466A0
+
+#define mmTPC5_CFG_KERNEL_SRF_5 0xF466A4
+
+#define mmTPC5_CFG_KERNEL_SRF_6 0xF466A8
+
+#define mmTPC5_CFG_KERNEL_SRF_7 0xF466AC
+
+#define mmTPC5_CFG_KERNEL_SRF_8 0xF466B0
+
+#define mmTPC5_CFG_KERNEL_SRF_9 0xF466B4
+
+#define mmTPC5_CFG_KERNEL_SRF_10 0xF466B8
+
+#define mmTPC5_CFG_KERNEL_SRF_11 0xF466BC
+
+#define mmTPC5_CFG_KERNEL_SRF_12 0xF466C0
+
+#define mmTPC5_CFG_KERNEL_SRF_13 0xF466C4
+
+#define mmTPC5_CFG_KERNEL_SRF_14 0xF466C8
+
+#define mmTPC5_CFG_KERNEL_SRF_15 0xF466CC
+
+#define mmTPC5_CFG_KERNEL_SRF_16 0xF466D0
+
+#define mmTPC5_CFG_KERNEL_SRF_17 0xF466D4
+
+#define mmTPC5_CFG_KERNEL_SRF_18 0xF466D8
+
+#define mmTPC5_CFG_KERNEL_SRF_19 0xF466DC
+
+#define mmTPC5_CFG_KERNEL_SRF_20 0xF466E0
+
+#define mmTPC5_CFG_KERNEL_SRF_21 0xF466E4
+
+#define mmTPC5_CFG_KERNEL_SRF_22 0xF466E8
+
+#define mmTPC5_CFG_KERNEL_SRF_23 0xF466EC
+
+#define mmTPC5_CFG_KERNEL_SRF_24 0xF466F0
+
+#define mmTPC5_CFG_KERNEL_SRF_25 0xF466F4
+
+#define mmTPC5_CFG_KERNEL_SRF_26 0xF466F8
+
+#define mmTPC5_CFG_KERNEL_SRF_27 0xF466FC
+
+#define mmTPC5_CFG_KERNEL_SRF_28 0xF46700
+
+#define mmTPC5_CFG_KERNEL_SRF_29 0xF46704
+
+#define mmTPC5_CFG_KERNEL_SRF_30 0xF46708
+
+#define mmTPC5_CFG_KERNEL_SRF_31 0xF4670C
+
+#define mmTPC5_CFG_KERNEL_KERNEL_CONFIG 0xF46710
+
+#define mmTPC5_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xF46714
+
+#define mmTPC5_CFG_RESERVED_DESC_END 0xF46738
+
+#define mmTPC5_CFG_ROUND_CSR 0xF467FC
+
+#define mmTPC5_CFG_TBUF_BASE_ADDR_LOW 0xF46800
+
+#define mmTPC5_CFG_TBUF_BASE_ADDR_HIGH 0xF46804
+
+#define mmTPC5_CFG_SEMAPHORE 0xF46808
+
+#define mmTPC5_CFG_VFLAGS 0xF4680C
+
+#define mmTPC5_CFG_SFLAGS 0xF46810
+
+#define mmTPC5_CFG_LFSR_POLYNOM 0xF46818
+
+#define mmTPC5_CFG_STATUS 0xF4681C
+
+#define mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH 0xF46820
+
+#define mmTPC5_CFG_CFG_SUBTRACT_VALUE 0xF46824
+
+#define mmTPC5_CFG_SM_BASE_ADDRESS_LOW 0xF46828
+
+#define mmTPC5_CFG_SM_BASE_ADDRESS_HIGH 0xF4682C
+
+#define mmTPC5_CFG_TPC_CMD 0xF46830
+
+#define mmTPC5_CFG_TPC_EXECUTE 0xF46838
+
+#define mmTPC5_CFG_TPC_STALL 0xF4683C
+
+#define mmTPC5_CFG_ICACHE_BASE_ADDERESS_LOW 0xF46840
+
+#define mmTPC5_CFG_ICACHE_BASE_ADDERESS_HIGH 0xF46844
+
+#define mmTPC5_CFG_MSS_CONFIG 0xF46854
+
+#define mmTPC5_CFG_TPC_INTR_CAUSE 0xF46858
+
+#define mmTPC5_CFG_TPC_INTR_MASK 0xF4685C
+
+#define mmTPC5_CFG_TSB_CONFIG 0xF46860
+
+#define mmTPC5_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xF46A00
+
+#define mmTPC5_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xF46A04
+
+#define mmTPC5_CFG_QM_TENSOR_0_PADDING_VALUE 0xF46A08
+
+#define mmTPC5_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xF46A0C
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_0_SIZE 0xF46A10
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xF46A14
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xF46A18
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_1_SIZE 0xF46A1C
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xF46A20
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xF46A24
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_2_SIZE 0xF46A28
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xF46A2C
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xF46A30
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_3_SIZE 0xF46A34
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xF46A38
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xF46A3C
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_4_SIZE 0xF46A40
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xF46A44
+
+#define mmTPC5_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xF46A48
+
+#define mmTPC5_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xF46A4C
+
+#define mmTPC5_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xF46A50
+
+#define mmTPC5_CFG_QM_TENSOR_1_PADDING_VALUE 0xF46A54
+
+#define mmTPC5_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xF46A58
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_0_SIZE 0xF46A5C
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xF46A60
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xF46A64
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_1_SIZE 0xF46A68
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xF46A6C
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xF46A70
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_2_SIZE 0xF46A74
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xF46A78
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xF46A7C
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_3_SIZE 0xF46A80
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xF46A84
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xF46A88
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_4_SIZE 0xF46A8C
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xF46A90
+
+#define mmTPC5_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xF46A94
+
+#define mmTPC5_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xF46A98
+
+#define mmTPC5_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xF46A9C
+
+#define mmTPC5_CFG_QM_TENSOR_2_PADDING_VALUE 0xF46AA0
+
+#define mmTPC5_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xF46AA4
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_0_SIZE 0xF46AA8
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xF46AAC
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xF46AB0
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_1_SIZE 0xF46AB4
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xF46AB8
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xF46ABC
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_2_SIZE 0xF46AC0
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xF46AC4
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xF46AC8
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_3_SIZE 0xF46ACC
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xF46AD0
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xF46AD4
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_4_SIZE 0xF46AD8
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xF46ADC
+
+#define mmTPC5_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xF46AE0
+
+#define mmTPC5_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xF46AE4
+
+#define mmTPC5_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xF46AE8
+
+#define mmTPC5_CFG_QM_TENSOR_3_PADDING_VALUE 0xF46AEC
+
+#define mmTPC5_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xF46AF0
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_0_SIZE 0xF46AF4
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xF46AF8
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xF46AFC
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_1_SIZE 0xF46B00
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xF46B04
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xF46B08
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_2_SIZE 0xF46B0C
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xF46B10
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xF46B14
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_3_SIZE 0xF46B18
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xF46B1C
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xF46B20
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_4_SIZE 0xF46B24
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xF46B28
+
+#define mmTPC5_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xF46B2C
+
+#define mmTPC5_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xF46B30
+
+#define mmTPC5_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xF46B34
+
+#define mmTPC5_CFG_QM_TENSOR_4_PADDING_VALUE 0xF46B38
+
+#define mmTPC5_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xF46B3C
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_0_SIZE 0xF46B40
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xF46B44
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xF46B48
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_1_SIZE 0xF46B4C
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xF46B50
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xF46B54
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_2_SIZE 0xF46B58
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xF46B5C
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xF46B60
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_3_SIZE 0xF46B64
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xF46B68
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xF46B6C
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_4_SIZE 0xF46B70
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xF46B74
+
+#define mmTPC5_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xF46B78
+
+#define mmTPC5_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xF46B7C
+
+#define mmTPC5_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xF46B80
+
+#define mmTPC5_CFG_QM_TENSOR_5_PADDING_VALUE 0xF46B84
+
+#define mmTPC5_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xF46B88
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_0_SIZE 0xF46B8C
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xF46B90
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xF46B94
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_1_SIZE 0xF46B98
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xF46B9C
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xF46BA0
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_2_SIZE 0xF46BA4
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xF46BA8
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xF46BAC
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_3_SIZE 0xF46BB0
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xF46BB4
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xF46BB8
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_4_SIZE 0xF46BBC
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xF46BC0
+
+#define mmTPC5_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xF46BC4
+
+#define mmTPC5_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xF46BC8
+
+#define mmTPC5_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xF46BCC
+
+#define mmTPC5_CFG_QM_TENSOR_6_PADDING_VALUE 0xF46BD0
+
+#define mmTPC5_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xF46BD4
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_0_SIZE 0xF46BD8
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xF46BDC
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xF46BE0
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_1_SIZE 0xF46BE4
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xF46BE8
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xF46BEC
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_2_SIZE 0xF46BF0
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xF46BF4
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xF46BF8
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_3_SIZE 0xF46BFC
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xF46C00
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xF46C04
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_4_SIZE 0xF46C08
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xF46C0C
+
+#define mmTPC5_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xF46C10
+
+#define mmTPC5_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xF46C14
+
+#define mmTPC5_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xF46C18
+
+#define mmTPC5_CFG_QM_TENSOR_7_PADDING_VALUE 0xF46C1C
+
+#define mmTPC5_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xF46C20
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_0_SIZE 0xF46C24
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xF46C28
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xF46C2C
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_1_SIZE 0xF46C30
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xF46C34
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xF46C38
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_2_SIZE 0xF46C3C
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xF46C40
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xF46C44
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_3_SIZE 0xF46C48
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xF46C4C
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xF46C50
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_4_SIZE 0xF46C54
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xF46C58
+
+#define mmTPC5_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xF46C5C
+
+#define mmTPC5_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xF46C60
+
+#define mmTPC5_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xF46C64
+
+#define mmTPC5_CFG_QM_TID_BASE_DIM_0 0xF46C68
+
+#define mmTPC5_CFG_QM_TID_SIZE_DIM_0 0xF46C6C
+
+#define mmTPC5_CFG_QM_TID_BASE_DIM_1 0xF46C70
+
+#define mmTPC5_CFG_QM_TID_SIZE_DIM_1 0xF46C74
+
+#define mmTPC5_CFG_QM_TID_BASE_DIM_2 0xF46C78
+
+#define mmTPC5_CFG_QM_TID_SIZE_DIM_2 0xF46C7C
+
+#define mmTPC5_CFG_QM_TID_BASE_DIM_3 0xF46C80
+
+#define mmTPC5_CFG_QM_TID_SIZE_DIM_3 0xF46C84
+
+#define mmTPC5_CFG_QM_TID_BASE_DIM_4 0xF46C88
+
+#define mmTPC5_CFG_QM_TID_SIZE_DIM_4 0xF46C8C
+
+#define mmTPC5_CFG_QM_SRF_0 0xF46C90
+
+#define mmTPC5_CFG_QM_SRF_1 0xF46C94
+
+#define mmTPC5_CFG_QM_SRF_2 0xF46C98
+
+#define mmTPC5_CFG_QM_SRF_3 0xF46C9C
+
+#define mmTPC5_CFG_QM_SRF_4 0xF46CA0
+
+#define mmTPC5_CFG_QM_SRF_5 0xF46CA4
+
+#define mmTPC5_CFG_QM_SRF_6 0xF46CA8
+
+#define mmTPC5_CFG_QM_SRF_7 0xF46CAC
+
+#define mmTPC5_CFG_QM_SRF_8 0xF46CB0
+
+#define mmTPC5_CFG_QM_SRF_9 0xF46CB4
+
+#define mmTPC5_CFG_QM_SRF_10 0xF46CB8
+
+#define mmTPC5_CFG_QM_SRF_11 0xF46CBC
+
+#define mmTPC5_CFG_QM_SRF_12 0xF46CC0
+
+#define mmTPC5_CFG_QM_SRF_13 0xF46CC4
+
+#define mmTPC5_CFG_QM_SRF_14 0xF46CC8
+
+#define mmTPC5_CFG_QM_SRF_15 0xF46CCC
+
+#define mmTPC5_CFG_QM_SRF_16 0xF46CD0
+
+#define mmTPC5_CFG_QM_SRF_17 0xF46CD4
+
+#define mmTPC5_CFG_QM_SRF_18 0xF46CD8
+
+#define mmTPC5_CFG_QM_SRF_19 0xF46CDC
+
+#define mmTPC5_CFG_QM_SRF_20 0xF46CE0
+
+#define mmTPC5_CFG_QM_SRF_21 0xF46CE4
+
+#define mmTPC5_CFG_QM_SRF_22 0xF46CE8
+
+#define mmTPC5_CFG_QM_SRF_23 0xF46CEC
+
+#define mmTPC5_CFG_QM_SRF_24 0xF46CF0
+
+#define mmTPC5_CFG_QM_SRF_25 0xF46CF4
+
+#define mmTPC5_CFG_QM_SRF_26 0xF46CF8
+
+#define mmTPC5_CFG_QM_SRF_27 0xF46CFC
+
+#define mmTPC5_CFG_QM_SRF_28 0xF46D00
+
+#define mmTPC5_CFG_QM_SRF_29 0xF46D04
+
+#define mmTPC5_CFG_QM_SRF_30 0xF46D08
+
+#define mmTPC5_CFG_QM_SRF_31 0xF46D0C
+
+#define mmTPC5_CFG_QM_KERNEL_CONFIG 0xF46D10
+
+#define mmTPC5_CFG_QM_SYNC_OBJECT_MESSAGE 0xF46D14
+
+#define mmTPC5_CFG_ARUSER 0xF46D18
+
+#define mmTPC5_CFG_AWUSER 0xF46D1C
+
+#define mmTPC5_CFG_FUNC_MBIST_CNTRL 0xF46E00
+
+#define mmTPC5_CFG_FUNC_MBIST_PAT 0xF46E04
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_0 0xF46E08
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_1 0xF46E0C
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_2 0xF46E10
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_3 0xF46E14
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_4 0xF46E18
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_5 0xF46E1C
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_6 0xF46E20
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_7 0xF46E24
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_8 0xF46E28
+
+#define mmTPC5_CFG_FUNC_MBIST_MEM_9 0xF46E2C
+
+#endif /* ASIC_REG_TPC5_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h
new file mode 100644
index 000000000000..d8e72a8e18d7
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC5_CMDQ_REGS_H_
+#define ASIC_REG_TPC5_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC5_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC5_CMDQ_GLBL_CFG0 0xF49000
+
+#define mmTPC5_CMDQ_GLBL_CFG1 0xF49004
+
+#define mmTPC5_CMDQ_GLBL_PROT 0xF49008
+
+#define mmTPC5_CMDQ_GLBL_ERR_CFG 0xF4900C
+
+#define mmTPC5_CMDQ_GLBL_ERR_ADDR_LO 0xF49010
+
+#define mmTPC5_CMDQ_GLBL_ERR_ADDR_HI 0xF49014
+
+#define mmTPC5_CMDQ_GLBL_ERR_WDATA 0xF49018
+
+#define mmTPC5_CMDQ_GLBL_SECURE_PROPS 0xF4901C
+
+#define mmTPC5_CMDQ_GLBL_NON_SECURE_PROPS 0xF49020
+
+#define mmTPC5_CMDQ_GLBL_STS0 0xF49024
+
+#define mmTPC5_CMDQ_GLBL_STS1 0xF49028
+
+#define mmTPC5_CMDQ_CQ_CFG0 0xF490B0
+
+#define mmTPC5_CMDQ_CQ_CFG1 0xF490B4
+
+#define mmTPC5_CMDQ_CQ_ARUSER 0xF490B8
+
+#define mmTPC5_CMDQ_CQ_PTR_LO 0xF490C0
+
+#define mmTPC5_CMDQ_CQ_PTR_HI 0xF490C4
+
+#define mmTPC5_CMDQ_CQ_TSIZE 0xF490C8
+
+#define mmTPC5_CMDQ_CQ_CTL 0xF490CC
+
+#define mmTPC5_CMDQ_CQ_PTR_LO_STS 0xF490D4
+
+#define mmTPC5_CMDQ_CQ_PTR_HI_STS 0xF490D8
+
+#define mmTPC5_CMDQ_CQ_TSIZE_STS 0xF490DC
+
+#define mmTPC5_CMDQ_CQ_CTL_STS 0xF490E0
+
+#define mmTPC5_CMDQ_CQ_STS0 0xF490E4
+
+#define mmTPC5_CMDQ_CQ_STS1 0xF490E8
+
+#define mmTPC5_CMDQ_CQ_RD_RATE_LIM_EN 0xF490F0
+
+#define mmTPC5_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xF490F4
+
+#define mmTPC5_CMDQ_CQ_RD_RATE_LIM_SAT 0xF490F8
+
+#define mmTPC5_CMDQ_CQ_RD_RATE_LIM_TOUT 0xF490FC
+
+#define mmTPC5_CMDQ_CQ_IFIFO_CNT 0xF49108
+
+#define mmTPC5_CMDQ_CP_MSG_BASE0_ADDR_LO 0xF49120
+
+#define mmTPC5_CMDQ_CP_MSG_BASE0_ADDR_HI 0xF49124
+
+#define mmTPC5_CMDQ_CP_MSG_BASE1_ADDR_LO 0xF49128
+
+#define mmTPC5_CMDQ_CP_MSG_BASE1_ADDR_HI 0xF4912C
+
+#define mmTPC5_CMDQ_CP_MSG_BASE2_ADDR_LO 0xF49130
+
+#define mmTPC5_CMDQ_CP_MSG_BASE2_ADDR_HI 0xF49134
+
+#define mmTPC5_CMDQ_CP_MSG_BASE3_ADDR_LO 0xF49138
+
+#define mmTPC5_CMDQ_CP_MSG_BASE3_ADDR_HI 0xF4913C
+
+#define mmTPC5_CMDQ_CP_LDMA_TSIZE_OFFSET 0xF49140
+
+#define mmTPC5_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xF49144
+
+#define mmTPC5_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xF49148
+
+#define mmTPC5_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xF4914C
+
+#define mmTPC5_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xF49150
+
+#define mmTPC5_CMDQ_CP_LDMA_COMMIT_OFFSET 0xF49154
+
+#define mmTPC5_CMDQ_CP_FENCE0_RDATA 0xF49158
+
+#define mmTPC5_CMDQ_CP_FENCE1_RDATA 0xF4915C
+
+#define mmTPC5_CMDQ_CP_FENCE2_RDATA 0xF49160
+
+#define mmTPC5_CMDQ_CP_FENCE3_RDATA 0xF49164
+
+#define mmTPC5_CMDQ_CP_FENCE0_CNT 0xF49168
+
+#define mmTPC5_CMDQ_CP_FENCE1_CNT 0xF4916C
+
+#define mmTPC5_CMDQ_CP_FENCE2_CNT 0xF49170
+
+#define mmTPC5_CMDQ_CP_FENCE3_CNT 0xF49174
+
+#define mmTPC5_CMDQ_CP_STS 0xF49178
+
+#define mmTPC5_CMDQ_CP_CURRENT_INST_LO 0xF4917C
+
+#define mmTPC5_CMDQ_CP_CURRENT_INST_HI 0xF49180
+
+#define mmTPC5_CMDQ_CP_BARRIER_CFG 0xF49184
+
+#define mmTPC5_CMDQ_CP_DBG_0 0xF49188
+
+#define mmTPC5_CMDQ_CQ_BUF_ADDR 0xF49308
+
+#define mmTPC5_CMDQ_CQ_BUF_RDATA 0xF4930C
+
+#endif /* ASIC_REG_TPC5_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h
new file mode 100644
index 000000000000..be2e68624709
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC5_QM_REGS_H_
+#define ASIC_REG_TPC5_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC5_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC5_QM_GLBL_CFG0 0xF48000
+
+#define mmTPC5_QM_GLBL_CFG1 0xF48004
+
+#define mmTPC5_QM_GLBL_PROT 0xF48008
+
+#define mmTPC5_QM_GLBL_ERR_CFG 0xF4800C
+
+#define mmTPC5_QM_GLBL_ERR_ADDR_LO 0xF48010
+
+#define mmTPC5_QM_GLBL_ERR_ADDR_HI 0xF48014
+
+#define mmTPC5_QM_GLBL_ERR_WDATA 0xF48018
+
+#define mmTPC5_QM_GLBL_SECURE_PROPS 0xF4801C
+
+#define mmTPC5_QM_GLBL_NON_SECURE_PROPS 0xF48020
+
+#define mmTPC5_QM_GLBL_STS0 0xF48024
+
+#define mmTPC5_QM_GLBL_STS1 0xF48028
+
+#define mmTPC5_QM_PQ_BASE_LO 0xF48060
+
+#define mmTPC5_QM_PQ_BASE_HI 0xF48064
+
+#define mmTPC5_QM_PQ_SIZE 0xF48068
+
+#define mmTPC5_QM_PQ_PI 0xF4806C
+
+#define mmTPC5_QM_PQ_CI 0xF48070
+
+#define mmTPC5_QM_PQ_CFG0 0xF48074
+
+#define mmTPC5_QM_PQ_CFG1 0xF48078
+
+#define mmTPC5_QM_PQ_ARUSER 0xF4807C
+
+#define mmTPC5_QM_PQ_PUSH0 0xF48080
+
+#define mmTPC5_QM_PQ_PUSH1 0xF48084
+
+#define mmTPC5_QM_PQ_PUSH2 0xF48088
+
+#define mmTPC5_QM_PQ_PUSH3 0xF4808C
+
+#define mmTPC5_QM_PQ_STS0 0xF48090
+
+#define mmTPC5_QM_PQ_STS1 0xF48094
+
+#define mmTPC5_QM_PQ_RD_RATE_LIM_EN 0xF480A0
+
+#define mmTPC5_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xF480A4
+
+#define mmTPC5_QM_PQ_RD_RATE_LIM_SAT 0xF480A8
+
+#define mmTPC5_QM_PQ_RD_RATE_LIM_TOUT 0xF480AC
+
+#define mmTPC5_QM_CQ_CFG0 0xF480B0
+
+#define mmTPC5_QM_CQ_CFG1 0xF480B4
+
+#define mmTPC5_QM_CQ_ARUSER 0xF480B8
+
+#define mmTPC5_QM_CQ_PTR_LO 0xF480C0
+
+#define mmTPC5_QM_CQ_PTR_HI 0xF480C4
+
+#define mmTPC5_QM_CQ_TSIZE 0xF480C8
+
+#define mmTPC5_QM_CQ_CTL 0xF480CC
+
+#define mmTPC5_QM_CQ_PTR_LO_STS 0xF480D4
+
+#define mmTPC5_QM_CQ_PTR_HI_STS 0xF480D8
+
+#define mmTPC5_QM_CQ_TSIZE_STS 0xF480DC
+
+#define mmTPC5_QM_CQ_CTL_STS 0xF480E0
+
+#define mmTPC5_QM_CQ_STS0 0xF480E4
+
+#define mmTPC5_QM_CQ_STS1 0xF480E8
+
+#define mmTPC5_QM_CQ_RD_RATE_LIM_EN 0xF480F0
+
+#define mmTPC5_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xF480F4
+
+#define mmTPC5_QM_CQ_RD_RATE_LIM_SAT 0xF480F8
+
+#define mmTPC5_QM_CQ_RD_RATE_LIM_TOUT 0xF480FC
+
+#define mmTPC5_QM_CQ_IFIFO_CNT 0xF48108
+
+#define mmTPC5_QM_CP_MSG_BASE0_ADDR_LO 0xF48120
+
+#define mmTPC5_QM_CP_MSG_BASE0_ADDR_HI 0xF48124
+
+#define mmTPC5_QM_CP_MSG_BASE1_ADDR_LO 0xF48128
+
+#define mmTPC5_QM_CP_MSG_BASE1_ADDR_HI 0xF4812C
+
+#define mmTPC5_QM_CP_MSG_BASE2_ADDR_LO 0xF48130
+
+#define mmTPC5_QM_CP_MSG_BASE2_ADDR_HI 0xF48134
+
+#define mmTPC5_QM_CP_MSG_BASE3_ADDR_LO 0xF48138
+
+#define mmTPC5_QM_CP_MSG_BASE3_ADDR_HI 0xF4813C
+
+#define mmTPC5_QM_CP_LDMA_TSIZE_OFFSET 0xF48140
+
+#define mmTPC5_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xF48144
+
+#define mmTPC5_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xF48148
+
+#define mmTPC5_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xF4814C
+
+#define mmTPC5_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xF48150
+
+#define mmTPC5_QM_CP_LDMA_COMMIT_OFFSET 0xF48154
+
+#define mmTPC5_QM_CP_FENCE0_RDATA 0xF48158
+
+#define mmTPC5_QM_CP_FENCE1_RDATA 0xF4815C
+
+#define mmTPC5_QM_CP_FENCE2_RDATA 0xF48160
+
+#define mmTPC5_QM_CP_FENCE3_RDATA 0xF48164
+
+#define mmTPC5_QM_CP_FENCE0_CNT 0xF48168
+
+#define mmTPC5_QM_CP_FENCE1_CNT 0xF4816C
+
+#define mmTPC5_QM_CP_FENCE2_CNT 0xF48170
+
+#define mmTPC5_QM_CP_FENCE3_CNT 0xF48174
+
+#define mmTPC5_QM_CP_STS 0xF48178
+
+#define mmTPC5_QM_CP_CURRENT_INST_LO 0xF4817C
+
+#define mmTPC5_QM_CP_CURRENT_INST_HI 0xF48180
+
+#define mmTPC5_QM_CP_BARRIER_CFG 0xF48184
+
+#define mmTPC5_QM_CP_DBG_0 0xF48188
+
+#define mmTPC5_QM_PQ_BUF_ADDR 0xF48300
+
+#define mmTPC5_QM_PQ_BUF_RDATA 0xF48304
+
+#define mmTPC5_QM_CQ_BUF_ADDR 0xF48308
+
+#define mmTPC5_QM_CQ_BUF_RDATA 0xF4830C
+
+#endif /* ASIC_REG_TPC5_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h
new file mode 100644
index 000000000000..6f301c7bbc2f
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc5_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC5_RTR_REGS_H_
+#define ASIC_REG_TPC5_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC5_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC5_RTR_HBW_RD_RQ_E_ARB 0xF40100
+
+#define mmTPC5_RTR_HBW_RD_RQ_W_ARB 0xF40104
+
+#define mmTPC5_RTR_HBW_RD_RQ_N_ARB 0xF40108
+
+#define mmTPC5_RTR_HBW_RD_RQ_S_ARB 0xF4010C
+
+#define mmTPC5_RTR_HBW_RD_RQ_L_ARB 0xF40110
+
+#define mmTPC5_RTR_HBW_E_ARB_MAX 0xF40120
+
+#define mmTPC5_RTR_HBW_W_ARB_MAX 0xF40124
+
+#define mmTPC5_RTR_HBW_N_ARB_MAX 0xF40128
+
+#define mmTPC5_RTR_HBW_S_ARB_MAX 0xF4012C
+
+#define mmTPC5_RTR_HBW_L_ARB_MAX 0xF40130
+
+#define mmTPC5_RTR_HBW_RD_RS_E_ARB 0xF40140
+
+#define mmTPC5_RTR_HBW_RD_RS_W_ARB 0xF40144
+
+#define mmTPC5_RTR_HBW_RD_RS_N_ARB 0xF40148
+
+#define mmTPC5_RTR_HBW_RD_RS_S_ARB 0xF4014C
+
+#define mmTPC5_RTR_HBW_RD_RS_L_ARB 0xF40150
+
+#define mmTPC5_RTR_HBW_WR_RQ_E_ARB 0xF40170
+
+#define mmTPC5_RTR_HBW_WR_RQ_W_ARB 0xF40174
+
+#define mmTPC5_RTR_HBW_WR_RQ_N_ARB 0xF40178
+
+#define mmTPC5_RTR_HBW_WR_RQ_S_ARB 0xF4017C
+
+#define mmTPC5_RTR_HBW_WR_RQ_L_ARB 0xF40180
+
+#define mmTPC5_RTR_HBW_WR_RS_E_ARB 0xF40190
+
+#define mmTPC5_RTR_HBW_WR_RS_W_ARB 0xF40194
+
+#define mmTPC5_RTR_HBW_WR_RS_N_ARB 0xF40198
+
+#define mmTPC5_RTR_HBW_WR_RS_S_ARB 0xF4019C
+
+#define mmTPC5_RTR_HBW_WR_RS_L_ARB 0xF401A0
+
+#define mmTPC5_RTR_LBW_RD_RQ_E_ARB 0xF40200
+
+#define mmTPC5_RTR_LBW_RD_RQ_W_ARB 0xF40204
+
+#define mmTPC5_RTR_LBW_RD_RQ_N_ARB 0xF40208
+
+#define mmTPC5_RTR_LBW_RD_RQ_S_ARB 0xF4020C
+
+#define mmTPC5_RTR_LBW_RD_RQ_L_ARB 0xF40210
+
+#define mmTPC5_RTR_LBW_E_ARB_MAX 0xF40220
+
+#define mmTPC5_RTR_LBW_W_ARB_MAX 0xF40224
+
+#define mmTPC5_RTR_LBW_N_ARB_MAX 0xF40228
+
+#define mmTPC5_RTR_LBW_S_ARB_MAX 0xF4022C
+
+#define mmTPC5_RTR_LBW_L_ARB_MAX 0xF40230
+
+#define mmTPC5_RTR_LBW_RD_RS_E_ARB 0xF40250
+
+#define mmTPC5_RTR_LBW_RD_RS_W_ARB 0xF40254
+
+#define mmTPC5_RTR_LBW_RD_RS_N_ARB 0xF40258
+
+#define mmTPC5_RTR_LBW_RD_RS_S_ARB 0xF4025C
+
+#define mmTPC5_RTR_LBW_RD_RS_L_ARB 0xF40260
+
+#define mmTPC5_RTR_LBW_WR_RQ_E_ARB 0xF40270
+
+#define mmTPC5_RTR_LBW_WR_RQ_W_ARB 0xF40274
+
+#define mmTPC5_RTR_LBW_WR_RQ_N_ARB 0xF40278
+
+#define mmTPC5_RTR_LBW_WR_RQ_S_ARB 0xF4027C
+
+#define mmTPC5_RTR_LBW_WR_RQ_L_ARB 0xF40280
+
+#define mmTPC5_RTR_LBW_WR_RS_E_ARB 0xF40290
+
+#define mmTPC5_RTR_LBW_WR_RS_W_ARB 0xF40294
+
+#define mmTPC5_RTR_LBW_WR_RS_N_ARB 0xF40298
+
+#define mmTPC5_RTR_LBW_WR_RS_S_ARB 0xF4029C
+
+#define mmTPC5_RTR_LBW_WR_RS_L_ARB 0xF402A0
+
+#define mmTPC5_RTR_DBG_E_ARB 0xF40300
+
+#define mmTPC5_RTR_DBG_W_ARB 0xF40304
+
+#define mmTPC5_RTR_DBG_N_ARB 0xF40308
+
+#define mmTPC5_RTR_DBG_S_ARB 0xF4030C
+
+#define mmTPC5_RTR_DBG_L_ARB 0xF40310
+
+#define mmTPC5_RTR_DBG_E_ARB_MAX 0xF40320
+
+#define mmTPC5_RTR_DBG_W_ARB_MAX 0xF40324
+
+#define mmTPC5_RTR_DBG_N_ARB_MAX 0xF40328
+
+#define mmTPC5_RTR_DBG_S_ARB_MAX 0xF4032C
+
+#define mmTPC5_RTR_DBG_L_ARB_MAX 0xF40330
+
+#define mmTPC5_RTR_SPLIT_COEF_0 0xF40400
+
+#define mmTPC5_RTR_SPLIT_COEF_1 0xF40404
+
+#define mmTPC5_RTR_SPLIT_COEF_2 0xF40408
+
+#define mmTPC5_RTR_SPLIT_COEF_3 0xF4040C
+
+#define mmTPC5_RTR_SPLIT_COEF_4 0xF40410
+
+#define mmTPC5_RTR_SPLIT_COEF_5 0xF40414
+
+#define mmTPC5_RTR_SPLIT_COEF_6 0xF40418
+
+#define mmTPC5_RTR_SPLIT_COEF_7 0xF4041C
+
+#define mmTPC5_RTR_SPLIT_COEF_8 0xF40420
+
+#define mmTPC5_RTR_SPLIT_COEF_9 0xF40424
+
+#define mmTPC5_RTR_SPLIT_CFG 0xF40440
+
+#define mmTPC5_RTR_SPLIT_RD_SAT 0xF40444
+
+#define mmTPC5_RTR_SPLIT_RD_RST_TOKEN 0xF40448
+
+#define mmTPC5_RTR_SPLIT_RD_TIMEOUT_0 0xF4044C
+
+#define mmTPC5_RTR_SPLIT_RD_TIMEOUT_1 0xF40450
+
+#define mmTPC5_RTR_SPLIT_WR_SAT 0xF40454
+
+#define mmTPC5_RTR_WPLIT_WR_TST_TOLEN 0xF40458
+
+#define mmTPC5_RTR_SPLIT_WR_TIMEOUT_0 0xF4045C
+
+#define mmTPC5_RTR_SPLIT_WR_TIMEOUT_1 0xF40460
+
+#define mmTPC5_RTR_HBW_RANGE_HIT 0xF40470
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_0 0xF40480
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_1 0xF40484
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_2 0xF40488
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_3 0xF4048C
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_4 0xF40490
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_5 0xF40494
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_6 0xF40498
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_L_7 0xF4049C
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_0 0xF404A0
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_1 0xF404A4
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_2 0xF404A8
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_3 0xF404AC
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_4 0xF404B0
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_5 0xF404B4
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_6 0xF404B8
+
+#define mmTPC5_RTR_HBW_RANGE_MASK_H_7 0xF404BC
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_0 0xF404C0
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_1 0xF404C4
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_2 0xF404C8
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_3 0xF404CC
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_4 0xF404D0
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_5 0xF404D4
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_6 0xF404D8
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_L_7 0xF404DC
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_0 0xF404E0
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_1 0xF404E4
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_2 0xF404E8
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_3 0xF404EC
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_4 0xF404F0
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_5 0xF404F4
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_6 0xF404F8
+
+#define mmTPC5_RTR_HBW_RANGE_BASE_H_7 0xF404FC
+
+#define mmTPC5_RTR_LBW_RANGE_HIT 0xF40500
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_0 0xF40510
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_1 0xF40514
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_2 0xF40518
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_3 0xF4051C
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_4 0xF40520
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_5 0xF40524
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_6 0xF40528
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_7 0xF4052C
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_8 0xF40530
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_9 0xF40534
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_10 0xF40538
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_11 0xF4053C
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_12 0xF40540
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_13 0xF40544
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_14 0xF40548
+
+#define mmTPC5_RTR_LBW_RANGE_MASK_15 0xF4054C
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_0 0xF40550
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_1 0xF40554
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_2 0xF40558
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_3 0xF4055C
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_4 0xF40560
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_5 0xF40564
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_6 0xF40568
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_7 0xF4056C
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_8 0xF40570
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_9 0xF40574
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_10 0xF40578
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_11 0xF4057C
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_12 0xF40580
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_13 0xF40584
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_14 0xF40588
+
+#define mmTPC5_RTR_LBW_RANGE_BASE_15 0xF4058C
+
+#define mmTPC5_RTR_RGLTR 0xF40590
+
+#define mmTPC5_RTR_RGLTR_WR_RESULT 0xF40594
+
+#define mmTPC5_RTR_RGLTR_RD_RESULT 0xF40598
+
+#define mmTPC5_RTR_SCRAMB_EN 0xF40600
+
+#define mmTPC5_RTR_NON_LIN_SCRAMB 0xF40604
+
+#endif /* ASIC_REG_TPC5_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h
new file mode 100644
index 000000000000..1e1168601c41
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC6_CFG_REGS_H_
+#define ASIC_REG_TPC6_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC6_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xF86400
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xF86404
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xF86408
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xF8640C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xF86410
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xF86414
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xF86418
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xF8641C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xF86420
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xF86424
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xF86428
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xF8642C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xF86430
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xF86434
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xF86438
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xF8643C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xF86440
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xF86444
+
+#define mmTPC6_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xF86448
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xF8644C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xF86450
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xF86454
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xF86458
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xF8645C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xF86460
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xF86464
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xF86468
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xF8646C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xF86470
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xF86474
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xF86478
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xF8647C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xF86480
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xF86484
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xF86488
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xF8648C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xF86490
+
+#define mmTPC6_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xF86494
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xF86498
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xF8649C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xF864A0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xF864A4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xF864A8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xF864AC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xF864B0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xF864B4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xF864B8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xF864BC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xF864C0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xF864C4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xF864C8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xF864CC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xF864D0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xF864D4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xF864D8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xF864DC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xF864E0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xF864E4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xF864E8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xF864EC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xF864F0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xF864F4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xF864F8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xF864FC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xF86500
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xF86504
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xF86508
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xF8650C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xF86510
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xF86514
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xF86518
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xF8651C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xF86520
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xF86524
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xF86528
+
+#define mmTPC6_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xF8652C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xF86530
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xF86534
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xF86538
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xF8653C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xF86540
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xF86544
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xF86548
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xF8654C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xF86550
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xF86554
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xF86558
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xF8655C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xF86560
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xF86564
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xF86568
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xF8656C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xF86570
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xF86574
+
+#define mmTPC6_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xF86578
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xF8657C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xF86580
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xF86584
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xF86588
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xF8658C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xF86590
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xF86594
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xF86598
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xF8659C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xF865A0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xF865A4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xF865A8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xF865AC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xF865B0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xF865B4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xF865B8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xF865BC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xF865C0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xF865C4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xF865C8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xF865CC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xF865D0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xF865D4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xF865D8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xF865DC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xF865E0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xF865E4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xF865E8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xF865EC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xF865F0
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xF865F4
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xF865F8
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xF865FC
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xF86600
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xF86604
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xF86608
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xF8660C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xF86610
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xF86614
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xF86618
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xF8661C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xF86620
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xF86624
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xF86628
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xF8662C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xF86630
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xF86634
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xF86638
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xF8663C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xF86640
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xF86644
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xF86648
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xF8664C
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xF86650
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xF86654
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xF86658
+
+#define mmTPC6_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xF8665C
+
+#define mmTPC6_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xF86660
+
+#define mmTPC6_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xF86664
+
+#define mmTPC6_CFG_KERNEL_TID_BASE_DIM_0 0xF86668
+
+#define mmTPC6_CFG_KERNEL_TID_SIZE_DIM_0 0xF8666C
+
+#define mmTPC6_CFG_KERNEL_TID_BASE_DIM_1 0xF86670
+
+#define mmTPC6_CFG_KERNEL_TID_SIZE_DIM_1 0xF86674
+
+#define mmTPC6_CFG_KERNEL_TID_BASE_DIM_2 0xF86678
+
+#define mmTPC6_CFG_KERNEL_TID_SIZE_DIM_2 0xF8667C
+
+#define mmTPC6_CFG_KERNEL_TID_BASE_DIM_3 0xF86680
+
+#define mmTPC6_CFG_KERNEL_TID_SIZE_DIM_3 0xF86684
+
+#define mmTPC6_CFG_KERNEL_TID_BASE_DIM_4 0xF86688
+
+#define mmTPC6_CFG_KERNEL_TID_SIZE_DIM_4 0xF8668C
+
+#define mmTPC6_CFG_KERNEL_SRF_0 0xF86690
+
+#define mmTPC6_CFG_KERNEL_SRF_1 0xF86694
+
+#define mmTPC6_CFG_KERNEL_SRF_2 0xF86698
+
+#define mmTPC6_CFG_KERNEL_SRF_3 0xF8669C
+
+#define mmTPC6_CFG_KERNEL_SRF_4 0xF866A0
+
+#define mmTPC6_CFG_KERNEL_SRF_5 0xF866A4
+
+#define mmTPC6_CFG_KERNEL_SRF_6 0xF866A8
+
+#define mmTPC6_CFG_KERNEL_SRF_7 0xF866AC
+
+#define mmTPC6_CFG_KERNEL_SRF_8 0xF866B0
+
+#define mmTPC6_CFG_KERNEL_SRF_9 0xF866B4
+
+#define mmTPC6_CFG_KERNEL_SRF_10 0xF866B8
+
+#define mmTPC6_CFG_KERNEL_SRF_11 0xF866BC
+
+#define mmTPC6_CFG_KERNEL_SRF_12 0xF866C0
+
+#define mmTPC6_CFG_KERNEL_SRF_13 0xF866C4
+
+#define mmTPC6_CFG_KERNEL_SRF_14 0xF866C8
+
+#define mmTPC6_CFG_KERNEL_SRF_15 0xF866CC
+
+#define mmTPC6_CFG_KERNEL_SRF_16 0xF866D0
+
+#define mmTPC6_CFG_KERNEL_SRF_17 0xF866D4
+
+#define mmTPC6_CFG_KERNEL_SRF_18 0xF866D8
+
+#define mmTPC6_CFG_KERNEL_SRF_19 0xF866DC
+
+#define mmTPC6_CFG_KERNEL_SRF_20 0xF866E0
+
+#define mmTPC6_CFG_KERNEL_SRF_21 0xF866E4
+
+#define mmTPC6_CFG_KERNEL_SRF_22 0xF866E8
+
+#define mmTPC6_CFG_KERNEL_SRF_23 0xF866EC
+
+#define mmTPC6_CFG_KERNEL_SRF_24 0xF866F0
+
+#define mmTPC6_CFG_KERNEL_SRF_25 0xF866F4
+
+#define mmTPC6_CFG_KERNEL_SRF_26 0xF866F8
+
+#define mmTPC6_CFG_KERNEL_SRF_27 0xF866FC
+
+#define mmTPC6_CFG_KERNEL_SRF_28 0xF86700
+
+#define mmTPC6_CFG_KERNEL_SRF_29 0xF86704
+
+#define mmTPC6_CFG_KERNEL_SRF_30 0xF86708
+
+#define mmTPC6_CFG_KERNEL_SRF_31 0xF8670C
+
+#define mmTPC6_CFG_KERNEL_KERNEL_CONFIG 0xF86710
+
+#define mmTPC6_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xF86714
+
+#define mmTPC6_CFG_RESERVED_DESC_END 0xF86738
+
+#define mmTPC6_CFG_ROUND_CSR 0xF867FC
+
+#define mmTPC6_CFG_TBUF_BASE_ADDR_LOW 0xF86800
+
+#define mmTPC6_CFG_TBUF_BASE_ADDR_HIGH 0xF86804
+
+#define mmTPC6_CFG_SEMAPHORE 0xF86808
+
+#define mmTPC6_CFG_VFLAGS 0xF8680C
+
+#define mmTPC6_CFG_SFLAGS 0xF86810
+
+#define mmTPC6_CFG_LFSR_POLYNOM 0xF86818
+
+#define mmTPC6_CFG_STATUS 0xF8681C
+
+#define mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH 0xF86820
+
+#define mmTPC6_CFG_CFG_SUBTRACT_VALUE 0xF86824
+
+#define mmTPC6_CFG_SM_BASE_ADDRESS_LOW 0xF86828
+
+#define mmTPC6_CFG_SM_BASE_ADDRESS_HIGH 0xF8682C
+
+#define mmTPC6_CFG_TPC_CMD 0xF86830
+
+#define mmTPC6_CFG_TPC_EXECUTE 0xF86838
+
+#define mmTPC6_CFG_TPC_STALL 0xF8683C
+
+#define mmTPC6_CFG_ICACHE_BASE_ADDERESS_LOW 0xF86840
+
+#define mmTPC6_CFG_ICACHE_BASE_ADDERESS_HIGH 0xF86844
+
+#define mmTPC6_CFG_MSS_CONFIG 0xF86854
+
+#define mmTPC6_CFG_TPC_INTR_CAUSE 0xF86858
+
+#define mmTPC6_CFG_TPC_INTR_MASK 0xF8685C
+
+#define mmTPC6_CFG_TSB_CONFIG 0xF86860
+
+#define mmTPC6_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xF86A00
+
+#define mmTPC6_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xF86A04
+
+#define mmTPC6_CFG_QM_TENSOR_0_PADDING_VALUE 0xF86A08
+
+#define mmTPC6_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xF86A0C
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_0_SIZE 0xF86A10
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xF86A14
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xF86A18
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_1_SIZE 0xF86A1C
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xF86A20
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xF86A24
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_2_SIZE 0xF86A28
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xF86A2C
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xF86A30
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_3_SIZE 0xF86A34
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xF86A38
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xF86A3C
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_4_SIZE 0xF86A40
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xF86A44
+
+#define mmTPC6_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xF86A48
+
+#define mmTPC6_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xF86A4C
+
+#define mmTPC6_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xF86A50
+
+#define mmTPC6_CFG_QM_TENSOR_1_PADDING_VALUE 0xF86A54
+
+#define mmTPC6_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xF86A58
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_0_SIZE 0xF86A5C
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xF86A60
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xF86A64
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_1_SIZE 0xF86A68
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xF86A6C
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xF86A70
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_2_SIZE 0xF86A74
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xF86A78
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xF86A7C
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_3_SIZE 0xF86A80
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xF86A84
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xF86A88
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_4_SIZE 0xF86A8C
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xF86A90
+
+#define mmTPC6_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xF86A94
+
+#define mmTPC6_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xF86A98
+
+#define mmTPC6_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xF86A9C
+
+#define mmTPC6_CFG_QM_TENSOR_2_PADDING_VALUE 0xF86AA0
+
+#define mmTPC6_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xF86AA4
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_0_SIZE 0xF86AA8
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xF86AAC
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xF86AB0
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_1_SIZE 0xF86AB4
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xF86AB8
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xF86ABC
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_2_SIZE 0xF86AC0
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xF86AC4
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xF86AC8
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_3_SIZE 0xF86ACC
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xF86AD0
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xF86AD4
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_4_SIZE 0xF86AD8
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xF86ADC
+
+#define mmTPC6_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xF86AE0
+
+#define mmTPC6_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xF86AE4
+
+#define mmTPC6_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xF86AE8
+
+#define mmTPC6_CFG_QM_TENSOR_3_PADDING_VALUE 0xF86AEC
+
+#define mmTPC6_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xF86AF0
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_0_SIZE 0xF86AF4
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xF86AF8
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xF86AFC
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_1_SIZE 0xF86B00
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xF86B04
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xF86B08
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_2_SIZE 0xF86B0C
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xF86B10
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xF86B14
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_3_SIZE 0xF86B18
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xF86B1C
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xF86B20
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_4_SIZE 0xF86B24
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xF86B28
+
+#define mmTPC6_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xF86B2C
+
+#define mmTPC6_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xF86B30
+
+#define mmTPC6_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xF86B34
+
+#define mmTPC6_CFG_QM_TENSOR_4_PADDING_VALUE 0xF86B38
+
+#define mmTPC6_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xF86B3C
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_0_SIZE 0xF86B40
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xF86B44
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xF86B48
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_1_SIZE 0xF86B4C
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xF86B50
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xF86B54
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_2_SIZE 0xF86B58
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xF86B5C
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xF86B60
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_3_SIZE 0xF86B64
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xF86B68
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xF86B6C
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_4_SIZE 0xF86B70
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xF86B74
+
+#define mmTPC6_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xF86B78
+
+#define mmTPC6_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xF86B7C
+
+#define mmTPC6_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xF86B80
+
+#define mmTPC6_CFG_QM_TENSOR_5_PADDING_VALUE 0xF86B84
+
+#define mmTPC6_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xF86B88
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_0_SIZE 0xF86B8C
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xF86B90
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xF86B94
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_1_SIZE 0xF86B98
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xF86B9C
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xF86BA0
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_2_SIZE 0xF86BA4
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xF86BA8
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xF86BAC
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_3_SIZE 0xF86BB0
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xF86BB4
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xF86BB8
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_4_SIZE 0xF86BBC
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xF86BC0
+
+#define mmTPC6_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xF86BC4
+
+#define mmTPC6_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xF86BC8
+
+#define mmTPC6_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xF86BCC
+
+#define mmTPC6_CFG_QM_TENSOR_6_PADDING_VALUE 0xF86BD0
+
+#define mmTPC6_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xF86BD4
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_0_SIZE 0xF86BD8
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xF86BDC
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xF86BE0
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_1_SIZE 0xF86BE4
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xF86BE8
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xF86BEC
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_2_SIZE 0xF86BF0
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xF86BF4
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xF86BF8
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_3_SIZE 0xF86BFC
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xF86C00
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xF86C04
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_4_SIZE 0xF86C08
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xF86C0C
+
+#define mmTPC6_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xF86C10
+
+#define mmTPC6_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xF86C14
+
+#define mmTPC6_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xF86C18
+
+#define mmTPC6_CFG_QM_TENSOR_7_PADDING_VALUE 0xF86C1C
+
+#define mmTPC6_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xF86C20
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_0_SIZE 0xF86C24
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xF86C28
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xF86C2C
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_1_SIZE 0xF86C30
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xF86C34
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xF86C38
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_2_SIZE 0xF86C3C
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xF86C40
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xF86C44
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_3_SIZE 0xF86C48
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xF86C4C
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xF86C50
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_4_SIZE 0xF86C54
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xF86C58
+
+#define mmTPC6_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xF86C5C
+
+#define mmTPC6_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xF86C60
+
+#define mmTPC6_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xF86C64
+
+#define mmTPC6_CFG_QM_TID_BASE_DIM_0 0xF86C68
+
+#define mmTPC6_CFG_QM_TID_SIZE_DIM_0 0xF86C6C
+
+#define mmTPC6_CFG_QM_TID_BASE_DIM_1 0xF86C70
+
+#define mmTPC6_CFG_QM_TID_SIZE_DIM_1 0xF86C74
+
+#define mmTPC6_CFG_QM_TID_BASE_DIM_2 0xF86C78
+
+#define mmTPC6_CFG_QM_TID_SIZE_DIM_2 0xF86C7C
+
+#define mmTPC6_CFG_QM_TID_BASE_DIM_3 0xF86C80
+
+#define mmTPC6_CFG_QM_TID_SIZE_DIM_3 0xF86C84
+
+#define mmTPC6_CFG_QM_TID_BASE_DIM_4 0xF86C88
+
+#define mmTPC6_CFG_QM_TID_SIZE_DIM_4 0xF86C8C
+
+#define mmTPC6_CFG_QM_SRF_0 0xF86C90
+
+#define mmTPC6_CFG_QM_SRF_1 0xF86C94
+
+#define mmTPC6_CFG_QM_SRF_2 0xF86C98
+
+#define mmTPC6_CFG_QM_SRF_3 0xF86C9C
+
+#define mmTPC6_CFG_QM_SRF_4 0xF86CA0
+
+#define mmTPC6_CFG_QM_SRF_5 0xF86CA4
+
+#define mmTPC6_CFG_QM_SRF_6 0xF86CA8
+
+#define mmTPC6_CFG_QM_SRF_7 0xF86CAC
+
+#define mmTPC6_CFG_QM_SRF_8 0xF86CB0
+
+#define mmTPC6_CFG_QM_SRF_9 0xF86CB4
+
+#define mmTPC6_CFG_QM_SRF_10 0xF86CB8
+
+#define mmTPC6_CFG_QM_SRF_11 0xF86CBC
+
+#define mmTPC6_CFG_QM_SRF_12 0xF86CC0
+
+#define mmTPC6_CFG_QM_SRF_13 0xF86CC4
+
+#define mmTPC6_CFG_QM_SRF_14 0xF86CC8
+
+#define mmTPC6_CFG_QM_SRF_15 0xF86CCC
+
+#define mmTPC6_CFG_QM_SRF_16 0xF86CD0
+
+#define mmTPC6_CFG_QM_SRF_17 0xF86CD4
+
+#define mmTPC6_CFG_QM_SRF_18 0xF86CD8
+
+#define mmTPC6_CFG_QM_SRF_19 0xF86CDC
+
+#define mmTPC6_CFG_QM_SRF_20 0xF86CE0
+
+#define mmTPC6_CFG_QM_SRF_21 0xF86CE4
+
+#define mmTPC6_CFG_QM_SRF_22 0xF86CE8
+
+#define mmTPC6_CFG_QM_SRF_23 0xF86CEC
+
+#define mmTPC6_CFG_QM_SRF_24 0xF86CF0
+
+#define mmTPC6_CFG_QM_SRF_25 0xF86CF4
+
+#define mmTPC6_CFG_QM_SRF_26 0xF86CF8
+
+#define mmTPC6_CFG_QM_SRF_27 0xF86CFC
+
+#define mmTPC6_CFG_QM_SRF_28 0xF86D00
+
+#define mmTPC6_CFG_QM_SRF_29 0xF86D04
+
+#define mmTPC6_CFG_QM_SRF_30 0xF86D08
+
+#define mmTPC6_CFG_QM_SRF_31 0xF86D0C
+
+#define mmTPC6_CFG_QM_KERNEL_CONFIG 0xF86D10
+
+#define mmTPC6_CFG_QM_SYNC_OBJECT_MESSAGE 0xF86D14
+
+#define mmTPC6_CFG_ARUSER 0xF86D18
+
+#define mmTPC6_CFG_AWUSER 0xF86D1C
+
+#define mmTPC6_CFG_FUNC_MBIST_CNTRL 0xF86E00
+
+#define mmTPC6_CFG_FUNC_MBIST_PAT 0xF86E04
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_0 0xF86E08
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_1 0xF86E0C
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_2 0xF86E10
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_3 0xF86E14
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_4 0xF86E18
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_5 0xF86E1C
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_6 0xF86E20
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_7 0xF86E24
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_8 0xF86E28
+
+#define mmTPC6_CFG_FUNC_MBIST_MEM_9 0xF86E2C
+
+#endif /* ASIC_REG_TPC6_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h
new file mode 100644
index 000000000000..fbca6b47284e
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC6_CMDQ_REGS_H_
+#define ASIC_REG_TPC6_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC6_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC6_CMDQ_GLBL_CFG0 0xF89000
+
+#define mmTPC6_CMDQ_GLBL_CFG1 0xF89004
+
+#define mmTPC6_CMDQ_GLBL_PROT 0xF89008
+
+#define mmTPC6_CMDQ_GLBL_ERR_CFG 0xF8900C
+
+#define mmTPC6_CMDQ_GLBL_ERR_ADDR_LO 0xF89010
+
+#define mmTPC6_CMDQ_GLBL_ERR_ADDR_HI 0xF89014
+
+#define mmTPC6_CMDQ_GLBL_ERR_WDATA 0xF89018
+
+#define mmTPC6_CMDQ_GLBL_SECURE_PROPS 0xF8901C
+
+#define mmTPC6_CMDQ_GLBL_NON_SECURE_PROPS 0xF89020
+
+#define mmTPC6_CMDQ_GLBL_STS0 0xF89024
+
+#define mmTPC6_CMDQ_GLBL_STS1 0xF89028
+
+#define mmTPC6_CMDQ_CQ_CFG0 0xF890B0
+
+#define mmTPC6_CMDQ_CQ_CFG1 0xF890B4
+
+#define mmTPC6_CMDQ_CQ_ARUSER 0xF890B8
+
+#define mmTPC6_CMDQ_CQ_PTR_LO 0xF890C0
+
+#define mmTPC6_CMDQ_CQ_PTR_HI 0xF890C4
+
+#define mmTPC6_CMDQ_CQ_TSIZE 0xF890C8
+
+#define mmTPC6_CMDQ_CQ_CTL 0xF890CC
+
+#define mmTPC6_CMDQ_CQ_PTR_LO_STS 0xF890D4
+
+#define mmTPC6_CMDQ_CQ_PTR_HI_STS 0xF890D8
+
+#define mmTPC6_CMDQ_CQ_TSIZE_STS 0xF890DC
+
+#define mmTPC6_CMDQ_CQ_CTL_STS 0xF890E0
+
+#define mmTPC6_CMDQ_CQ_STS0 0xF890E4
+
+#define mmTPC6_CMDQ_CQ_STS1 0xF890E8
+
+#define mmTPC6_CMDQ_CQ_RD_RATE_LIM_EN 0xF890F0
+
+#define mmTPC6_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xF890F4
+
+#define mmTPC6_CMDQ_CQ_RD_RATE_LIM_SAT 0xF890F8
+
+#define mmTPC6_CMDQ_CQ_RD_RATE_LIM_TOUT 0xF890FC
+
+#define mmTPC6_CMDQ_CQ_IFIFO_CNT 0xF89108
+
+#define mmTPC6_CMDQ_CP_MSG_BASE0_ADDR_LO 0xF89120
+
+#define mmTPC6_CMDQ_CP_MSG_BASE0_ADDR_HI 0xF89124
+
+#define mmTPC6_CMDQ_CP_MSG_BASE1_ADDR_LO 0xF89128
+
+#define mmTPC6_CMDQ_CP_MSG_BASE1_ADDR_HI 0xF8912C
+
+#define mmTPC6_CMDQ_CP_MSG_BASE2_ADDR_LO 0xF89130
+
+#define mmTPC6_CMDQ_CP_MSG_BASE2_ADDR_HI 0xF89134
+
+#define mmTPC6_CMDQ_CP_MSG_BASE3_ADDR_LO 0xF89138
+
+#define mmTPC6_CMDQ_CP_MSG_BASE3_ADDR_HI 0xF8913C
+
+#define mmTPC6_CMDQ_CP_LDMA_TSIZE_OFFSET 0xF89140
+
+#define mmTPC6_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xF89144
+
+#define mmTPC6_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xF89148
+
+#define mmTPC6_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xF8914C
+
+#define mmTPC6_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xF89150
+
+#define mmTPC6_CMDQ_CP_LDMA_COMMIT_OFFSET 0xF89154
+
+#define mmTPC6_CMDQ_CP_FENCE0_RDATA 0xF89158
+
+#define mmTPC6_CMDQ_CP_FENCE1_RDATA 0xF8915C
+
+#define mmTPC6_CMDQ_CP_FENCE2_RDATA 0xF89160
+
+#define mmTPC6_CMDQ_CP_FENCE3_RDATA 0xF89164
+
+#define mmTPC6_CMDQ_CP_FENCE0_CNT 0xF89168
+
+#define mmTPC6_CMDQ_CP_FENCE1_CNT 0xF8916C
+
+#define mmTPC6_CMDQ_CP_FENCE2_CNT 0xF89170
+
+#define mmTPC6_CMDQ_CP_FENCE3_CNT 0xF89174
+
+#define mmTPC6_CMDQ_CP_STS 0xF89178
+
+#define mmTPC6_CMDQ_CP_CURRENT_INST_LO 0xF8917C
+
+#define mmTPC6_CMDQ_CP_CURRENT_INST_HI 0xF89180
+
+#define mmTPC6_CMDQ_CP_BARRIER_CFG 0xF89184
+
+#define mmTPC6_CMDQ_CP_DBG_0 0xF89188
+
+#define mmTPC6_CMDQ_CQ_BUF_ADDR 0xF89308
+
+#define mmTPC6_CMDQ_CQ_BUF_RDATA 0xF8930C
+
+#endif /* ASIC_REG_TPC6_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h
new file mode 100644
index 000000000000..bf32465dabcb
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC6_QM_REGS_H_
+#define ASIC_REG_TPC6_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC6_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC6_QM_GLBL_CFG0 0xF88000
+
+#define mmTPC6_QM_GLBL_CFG1 0xF88004
+
+#define mmTPC6_QM_GLBL_PROT 0xF88008
+
+#define mmTPC6_QM_GLBL_ERR_CFG 0xF8800C
+
+#define mmTPC6_QM_GLBL_ERR_ADDR_LO 0xF88010
+
+#define mmTPC6_QM_GLBL_ERR_ADDR_HI 0xF88014
+
+#define mmTPC6_QM_GLBL_ERR_WDATA 0xF88018
+
+#define mmTPC6_QM_GLBL_SECURE_PROPS 0xF8801C
+
+#define mmTPC6_QM_GLBL_NON_SECURE_PROPS 0xF88020
+
+#define mmTPC6_QM_GLBL_STS0 0xF88024
+
+#define mmTPC6_QM_GLBL_STS1 0xF88028
+
+#define mmTPC6_QM_PQ_BASE_LO 0xF88060
+
+#define mmTPC6_QM_PQ_BASE_HI 0xF88064
+
+#define mmTPC6_QM_PQ_SIZE 0xF88068
+
+#define mmTPC6_QM_PQ_PI 0xF8806C
+
+#define mmTPC6_QM_PQ_CI 0xF88070
+
+#define mmTPC6_QM_PQ_CFG0 0xF88074
+
+#define mmTPC6_QM_PQ_CFG1 0xF88078
+
+#define mmTPC6_QM_PQ_ARUSER 0xF8807C
+
+#define mmTPC6_QM_PQ_PUSH0 0xF88080
+
+#define mmTPC6_QM_PQ_PUSH1 0xF88084
+
+#define mmTPC6_QM_PQ_PUSH2 0xF88088
+
+#define mmTPC6_QM_PQ_PUSH3 0xF8808C
+
+#define mmTPC6_QM_PQ_STS0 0xF88090
+
+#define mmTPC6_QM_PQ_STS1 0xF88094
+
+#define mmTPC6_QM_PQ_RD_RATE_LIM_EN 0xF880A0
+
+#define mmTPC6_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xF880A4
+
+#define mmTPC6_QM_PQ_RD_RATE_LIM_SAT 0xF880A8
+
+#define mmTPC6_QM_PQ_RD_RATE_LIM_TOUT 0xF880AC
+
+#define mmTPC6_QM_CQ_CFG0 0xF880B0
+
+#define mmTPC6_QM_CQ_CFG1 0xF880B4
+
+#define mmTPC6_QM_CQ_ARUSER 0xF880B8
+
+#define mmTPC6_QM_CQ_PTR_LO 0xF880C0
+
+#define mmTPC6_QM_CQ_PTR_HI 0xF880C4
+
+#define mmTPC6_QM_CQ_TSIZE 0xF880C8
+
+#define mmTPC6_QM_CQ_CTL 0xF880CC
+
+#define mmTPC6_QM_CQ_PTR_LO_STS 0xF880D4
+
+#define mmTPC6_QM_CQ_PTR_HI_STS 0xF880D8
+
+#define mmTPC6_QM_CQ_TSIZE_STS 0xF880DC
+
+#define mmTPC6_QM_CQ_CTL_STS 0xF880E0
+
+#define mmTPC6_QM_CQ_STS0 0xF880E4
+
+#define mmTPC6_QM_CQ_STS1 0xF880E8
+
+#define mmTPC6_QM_CQ_RD_RATE_LIM_EN 0xF880F0
+
+#define mmTPC6_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xF880F4
+
+#define mmTPC6_QM_CQ_RD_RATE_LIM_SAT 0xF880F8
+
+#define mmTPC6_QM_CQ_RD_RATE_LIM_TOUT 0xF880FC
+
+#define mmTPC6_QM_CQ_IFIFO_CNT 0xF88108
+
+#define mmTPC6_QM_CP_MSG_BASE0_ADDR_LO 0xF88120
+
+#define mmTPC6_QM_CP_MSG_BASE0_ADDR_HI 0xF88124
+
+#define mmTPC6_QM_CP_MSG_BASE1_ADDR_LO 0xF88128
+
+#define mmTPC6_QM_CP_MSG_BASE1_ADDR_HI 0xF8812C
+
+#define mmTPC6_QM_CP_MSG_BASE2_ADDR_LO 0xF88130
+
+#define mmTPC6_QM_CP_MSG_BASE2_ADDR_HI 0xF88134
+
+#define mmTPC6_QM_CP_MSG_BASE3_ADDR_LO 0xF88138
+
+#define mmTPC6_QM_CP_MSG_BASE3_ADDR_HI 0xF8813C
+
+#define mmTPC6_QM_CP_LDMA_TSIZE_OFFSET 0xF88140
+
+#define mmTPC6_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xF88144
+
+#define mmTPC6_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xF88148
+
+#define mmTPC6_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xF8814C
+
+#define mmTPC6_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xF88150
+
+#define mmTPC6_QM_CP_LDMA_COMMIT_OFFSET 0xF88154
+
+#define mmTPC6_QM_CP_FENCE0_RDATA 0xF88158
+
+#define mmTPC6_QM_CP_FENCE1_RDATA 0xF8815C
+
+#define mmTPC6_QM_CP_FENCE2_RDATA 0xF88160
+
+#define mmTPC6_QM_CP_FENCE3_RDATA 0xF88164
+
+#define mmTPC6_QM_CP_FENCE0_CNT 0xF88168
+
+#define mmTPC6_QM_CP_FENCE1_CNT 0xF8816C
+
+#define mmTPC6_QM_CP_FENCE2_CNT 0xF88170
+
+#define mmTPC6_QM_CP_FENCE3_CNT 0xF88174
+
+#define mmTPC6_QM_CP_STS 0xF88178
+
+#define mmTPC6_QM_CP_CURRENT_INST_LO 0xF8817C
+
+#define mmTPC6_QM_CP_CURRENT_INST_HI 0xF88180
+
+#define mmTPC6_QM_CP_BARRIER_CFG 0xF88184
+
+#define mmTPC6_QM_CP_DBG_0 0xF88188
+
+#define mmTPC6_QM_PQ_BUF_ADDR 0xF88300
+
+#define mmTPC6_QM_PQ_BUF_RDATA 0xF88304
+
+#define mmTPC6_QM_CQ_BUF_ADDR 0xF88308
+
+#define mmTPC6_QM_CQ_BUF_RDATA 0xF8830C
+
+#endif /* ASIC_REG_TPC6_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h
new file mode 100644
index 000000000000..609bb90e1046
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc6_rtr_regs.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC6_RTR_REGS_H_
+#define ASIC_REG_TPC6_RTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC6_RTR (Prototype: TPC_RTR)
+ *****************************************
+ */
+
+#define mmTPC6_RTR_HBW_RD_RQ_E_ARB 0xF80100
+
+#define mmTPC6_RTR_HBW_RD_RQ_W_ARB 0xF80104
+
+#define mmTPC6_RTR_HBW_RD_RQ_N_ARB 0xF80108
+
+#define mmTPC6_RTR_HBW_RD_RQ_S_ARB 0xF8010C
+
+#define mmTPC6_RTR_HBW_RD_RQ_L_ARB 0xF80110
+
+#define mmTPC6_RTR_HBW_E_ARB_MAX 0xF80120
+
+#define mmTPC6_RTR_HBW_W_ARB_MAX 0xF80124
+
+#define mmTPC6_RTR_HBW_N_ARB_MAX 0xF80128
+
+#define mmTPC6_RTR_HBW_S_ARB_MAX 0xF8012C
+
+#define mmTPC6_RTR_HBW_L_ARB_MAX 0xF80130
+
+#define mmTPC6_RTR_HBW_RD_RS_E_ARB 0xF80140
+
+#define mmTPC6_RTR_HBW_RD_RS_W_ARB 0xF80144
+
+#define mmTPC6_RTR_HBW_RD_RS_N_ARB 0xF80148
+
+#define mmTPC6_RTR_HBW_RD_RS_S_ARB 0xF8014C
+
+#define mmTPC6_RTR_HBW_RD_RS_L_ARB 0xF80150
+
+#define mmTPC6_RTR_HBW_WR_RQ_E_ARB 0xF80170
+
+#define mmTPC6_RTR_HBW_WR_RQ_W_ARB 0xF80174
+
+#define mmTPC6_RTR_HBW_WR_RQ_N_ARB 0xF80178
+
+#define mmTPC6_RTR_HBW_WR_RQ_S_ARB 0xF8017C
+
+#define mmTPC6_RTR_HBW_WR_RQ_L_ARB 0xF80180
+
+#define mmTPC6_RTR_HBW_WR_RS_E_ARB 0xF80190
+
+#define mmTPC6_RTR_HBW_WR_RS_W_ARB 0xF80194
+
+#define mmTPC6_RTR_HBW_WR_RS_N_ARB 0xF80198
+
+#define mmTPC6_RTR_HBW_WR_RS_S_ARB 0xF8019C
+
+#define mmTPC6_RTR_HBW_WR_RS_L_ARB 0xF801A0
+
+#define mmTPC6_RTR_LBW_RD_RQ_E_ARB 0xF80200
+
+#define mmTPC6_RTR_LBW_RD_RQ_W_ARB 0xF80204
+
+#define mmTPC6_RTR_LBW_RD_RQ_N_ARB 0xF80208
+
+#define mmTPC6_RTR_LBW_RD_RQ_S_ARB 0xF8020C
+
+#define mmTPC6_RTR_LBW_RD_RQ_L_ARB 0xF80210
+
+#define mmTPC6_RTR_LBW_E_ARB_MAX 0xF80220
+
+#define mmTPC6_RTR_LBW_W_ARB_MAX 0xF80224
+
+#define mmTPC6_RTR_LBW_N_ARB_MAX 0xF80228
+
+#define mmTPC6_RTR_LBW_S_ARB_MAX 0xF8022C
+
+#define mmTPC6_RTR_LBW_L_ARB_MAX 0xF80230
+
+#define mmTPC6_RTR_LBW_RD_RS_E_ARB 0xF80250
+
+#define mmTPC6_RTR_LBW_RD_RS_W_ARB 0xF80254
+
+#define mmTPC6_RTR_LBW_RD_RS_N_ARB 0xF80258
+
+#define mmTPC6_RTR_LBW_RD_RS_S_ARB 0xF8025C
+
+#define mmTPC6_RTR_LBW_RD_RS_L_ARB 0xF80260
+
+#define mmTPC6_RTR_LBW_WR_RQ_E_ARB 0xF80270
+
+#define mmTPC6_RTR_LBW_WR_RQ_W_ARB 0xF80274
+
+#define mmTPC6_RTR_LBW_WR_RQ_N_ARB 0xF80278
+
+#define mmTPC6_RTR_LBW_WR_RQ_S_ARB 0xF8027C
+
+#define mmTPC6_RTR_LBW_WR_RQ_L_ARB 0xF80280
+
+#define mmTPC6_RTR_LBW_WR_RS_E_ARB 0xF80290
+
+#define mmTPC6_RTR_LBW_WR_RS_W_ARB 0xF80294
+
+#define mmTPC6_RTR_LBW_WR_RS_N_ARB 0xF80298
+
+#define mmTPC6_RTR_LBW_WR_RS_S_ARB 0xF8029C
+
+#define mmTPC6_RTR_LBW_WR_RS_L_ARB 0xF802A0
+
+#define mmTPC6_RTR_DBG_E_ARB 0xF80300
+
+#define mmTPC6_RTR_DBG_W_ARB 0xF80304
+
+#define mmTPC6_RTR_DBG_N_ARB 0xF80308
+
+#define mmTPC6_RTR_DBG_S_ARB 0xF8030C
+
+#define mmTPC6_RTR_DBG_L_ARB 0xF80310
+
+#define mmTPC6_RTR_DBG_E_ARB_MAX 0xF80320
+
+#define mmTPC6_RTR_DBG_W_ARB_MAX 0xF80324
+
+#define mmTPC6_RTR_DBG_N_ARB_MAX 0xF80328
+
+#define mmTPC6_RTR_DBG_S_ARB_MAX 0xF8032C
+
+#define mmTPC6_RTR_DBG_L_ARB_MAX 0xF80330
+
+#define mmTPC6_RTR_SPLIT_COEF_0 0xF80400
+
+#define mmTPC6_RTR_SPLIT_COEF_1 0xF80404
+
+#define mmTPC6_RTR_SPLIT_COEF_2 0xF80408
+
+#define mmTPC6_RTR_SPLIT_COEF_3 0xF8040C
+
+#define mmTPC6_RTR_SPLIT_COEF_4 0xF80410
+
+#define mmTPC6_RTR_SPLIT_COEF_5 0xF80414
+
+#define mmTPC6_RTR_SPLIT_COEF_6 0xF80418
+
+#define mmTPC6_RTR_SPLIT_COEF_7 0xF8041C
+
+#define mmTPC6_RTR_SPLIT_COEF_8 0xF80420
+
+#define mmTPC6_RTR_SPLIT_COEF_9 0xF80424
+
+#define mmTPC6_RTR_SPLIT_CFG 0xF80440
+
+#define mmTPC6_RTR_SPLIT_RD_SAT 0xF80444
+
+#define mmTPC6_RTR_SPLIT_RD_RST_TOKEN 0xF80448
+
+#define mmTPC6_RTR_SPLIT_RD_TIMEOUT_0 0xF8044C
+
+#define mmTPC6_RTR_SPLIT_RD_TIMEOUT_1 0xF80450
+
+#define mmTPC6_RTR_SPLIT_WR_SAT 0xF80454
+
+#define mmTPC6_RTR_WPLIT_WR_TST_TOLEN 0xF80458
+
+#define mmTPC6_RTR_SPLIT_WR_TIMEOUT_0 0xF8045C
+
+#define mmTPC6_RTR_SPLIT_WR_TIMEOUT_1 0xF80460
+
+#define mmTPC6_RTR_HBW_RANGE_HIT 0xF80470
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_0 0xF80480
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_1 0xF80484
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_2 0xF80488
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_3 0xF8048C
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_4 0xF80490
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_5 0xF80494
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_6 0xF80498
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_L_7 0xF8049C
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_0 0xF804A0
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_1 0xF804A4
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_2 0xF804A8
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_3 0xF804AC
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_4 0xF804B0
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_5 0xF804B4
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_6 0xF804B8
+
+#define mmTPC6_RTR_HBW_RANGE_MASK_H_7 0xF804BC
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_0 0xF804C0
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_1 0xF804C4
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_2 0xF804C8
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_3 0xF804CC
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_4 0xF804D0
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_5 0xF804D4
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_6 0xF804D8
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_L_7 0xF804DC
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_0 0xF804E0
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_1 0xF804E4
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_2 0xF804E8
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_3 0xF804EC
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_4 0xF804F0
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_5 0xF804F4
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_6 0xF804F8
+
+#define mmTPC6_RTR_HBW_RANGE_BASE_H_7 0xF804FC
+
+#define mmTPC6_RTR_LBW_RANGE_HIT 0xF80500
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_0 0xF80510
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_1 0xF80514
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_2 0xF80518
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_3 0xF8051C
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_4 0xF80520
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_5 0xF80524
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_6 0xF80528
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_7 0xF8052C
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_8 0xF80530
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_9 0xF80534
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_10 0xF80538
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_11 0xF8053C
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_12 0xF80540
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_13 0xF80544
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_14 0xF80548
+
+#define mmTPC6_RTR_LBW_RANGE_MASK_15 0xF8054C
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_0 0xF80550
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_1 0xF80554
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_2 0xF80558
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_3 0xF8055C
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_4 0xF80560
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_5 0xF80564
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_6 0xF80568
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_7 0xF8056C
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_8 0xF80570
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_9 0xF80574
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_10 0xF80578
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_11 0xF8057C
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_12 0xF80580
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_13 0xF80584
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_14 0xF80588
+
+#define mmTPC6_RTR_LBW_RANGE_BASE_15 0xF8058C
+
+#define mmTPC6_RTR_RGLTR 0xF80590
+
+#define mmTPC6_RTR_RGLTR_WR_RESULT 0xF80594
+
+#define mmTPC6_RTR_RGLTR_RD_RESULT 0xF80598
+
+#define mmTPC6_RTR_SCRAMB_EN 0xF80600
+
+#define mmTPC6_RTR_NON_LIN_SCRAMB 0xF80604
+
+#endif /* ASIC_REG_TPC6_RTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h
new file mode 100644
index 000000000000..bf2fd0f73906
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cfg_regs.h
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC7_CFG_REGS_H_
+#define ASIC_REG_TPC7_CFG_REGS_H_
+
+/*
+ *****************************************
+ * TPC7_CFG (Prototype: TPC)
+ *****************************************
+ */
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_BASE_ADDR_LOW 0xFC6400
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_BASE_ADDR_HIGH 0xFC6404
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_PADDING_VALUE 0xFC6408
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_TENSOR_CONFIG 0xFC640C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_0_SIZE 0xFC6410
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_0_STRIDE 0xFC6414
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_0_BASE_OFFSET 0xFC6418
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_1_SIZE 0xFC641C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_1_STRIDE 0xFC6420
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_1_BASE_OFFSET 0xFC6424
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_2_SIZE 0xFC6428
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_2_STRIDE 0xFC642C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_2_BASE_OFFSET 0xFC6430
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_3_SIZE 0xFC6434
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_3_STRIDE 0xFC6438
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_3_BASE_OFFSET 0xFC643C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_4_SIZE 0xFC6440
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_4_STRIDE 0xFC6444
+
+#define mmTPC7_CFG_KERNEL_TENSOR_0_DIM_4_BASE_OFFSET 0xFC6448
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_BASE_ADDR_LOW 0xFC644C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_BASE_ADDR_HIGH 0xFC6450
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_PADDING_VALUE 0xFC6454
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_TENSOR_CONFIG 0xFC6458
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_0_SIZE 0xFC645C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_0_STRIDE 0xFC6460
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_0_BASE_OFFSET 0xFC6464
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_1_SIZE 0xFC6468
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_1_STRIDE 0xFC646C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_1_BASE_OFFSET 0xFC6470
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_2_SIZE 0xFC6474
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_2_STRIDE 0xFC6478
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_2_BASE_OFFSET 0xFC647C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_3_SIZE 0xFC6480
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_3_STRIDE 0xFC6484
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_3_BASE_OFFSET 0xFC6488
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_4_SIZE 0xFC648C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_4_STRIDE 0xFC6490
+
+#define mmTPC7_CFG_KERNEL_TENSOR_1_DIM_4_BASE_OFFSET 0xFC6494
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_BASE_ADDR_LOW 0xFC6498
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_BASE_ADDR_HIGH 0xFC649C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_PADDING_VALUE 0xFC64A0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_TENSOR_CONFIG 0xFC64A4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_0_SIZE 0xFC64A8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_0_STRIDE 0xFC64AC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_0_BASE_OFFSET 0xFC64B0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_1_SIZE 0xFC64B4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_1_STRIDE 0xFC64B8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_1_BASE_OFFSET 0xFC64BC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_2_SIZE 0xFC64C0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_2_STRIDE 0xFC64C4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_2_BASE_OFFSET 0xFC64C8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_3_SIZE 0xFC64CC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_3_STRIDE 0xFC64D0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_3_BASE_OFFSET 0xFC64D4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_4_SIZE 0xFC64D8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_4_STRIDE 0xFC64DC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_2_DIM_4_BASE_OFFSET 0xFC64E0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_BASE_ADDR_LOW 0xFC64E4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_BASE_ADDR_HIGH 0xFC64E8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_PADDING_VALUE 0xFC64EC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_TENSOR_CONFIG 0xFC64F0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_0_SIZE 0xFC64F4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_0_STRIDE 0xFC64F8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_0_BASE_OFFSET 0xFC64FC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_1_SIZE 0xFC6500
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_1_STRIDE 0xFC6504
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_1_BASE_OFFSET 0xFC6508
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_2_SIZE 0xFC650C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_2_STRIDE 0xFC6510
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_2_BASE_OFFSET 0xFC6514
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_3_SIZE 0xFC6518
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_3_STRIDE 0xFC651C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_3_BASE_OFFSET 0xFC6520
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_4_SIZE 0xFC6524
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_4_STRIDE 0xFC6528
+
+#define mmTPC7_CFG_KERNEL_TENSOR_3_DIM_4_BASE_OFFSET 0xFC652C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_BASE_ADDR_LOW 0xFC6530
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_BASE_ADDR_HIGH 0xFC6534
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_PADDING_VALUE 0xFC6538
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_TENSOR_CONFIG 0xFC653C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_0_SIZE 0xFC6540
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_0_STRIDE 0xFC6544
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_0_BASE_OFFSET 0xFC6548
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_1_SIZE 0xFC654C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_1_STRIDE 0xFC6550
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_1_BASE_OFFSET 0xFC6554
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_2_SIZE 0xFC6558
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_2_STRIDE 0xFC655C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_2_BASE_OFFSET 0xFC6560
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_3_SIZE 0xFC6564
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_3_STRIDE 0xFC6568
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_3_BASE_OFFSET 0xFC656C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_4_SIZE 0xFC6570
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_4_STRIDE 0xFC6574
+
+#define mmTPC7_CFG_KERNEL_TENSOR_4_DIM_4_BASE_OFFSET 0xFC6578
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_BASE_ADDR_LOW 0xFC657C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_BASE_ADDR_HIGH 0xFC6580
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_PADDING_VALUE 0xFC6584
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_TENSOR_CONFIG 0xFC6588
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_0_SIZE 0xFC658C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_0_STRIDE 0xFC6590
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_0_BASE_OFFSET 0xFC6594
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_1_SIZE 0xFC6598
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_1_STRIDE 0xFC659C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_1_BASE_OFFSET 0xFC65A0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_2_SIZE 0xFC65A4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_2_STRIDE 0xFC65A8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_2_BASE_OFFSET 0xFC65AC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_3_SIZE 0xFC65B0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_3_STRIDE 0xFC65B4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_3_BASE_OFFSET 0xFC65B8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_4_SIZE 0xFC65BC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_4_STRIDE 0xFC65C0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_5_DIM_4_BASE_OFFSET 0xFC65C4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_BASE_ADDR_LOW 0xFC65C8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_BASE_ADDR_HIGH 0xFC65CC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_PADDING_VALUE 0xFC65D0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_TENSOR_CONFIG 0xFC65D4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_0_SIZE 0xFC65D8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_0_STRIDE 0xFC65DC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_0_BASE_OFFSET 0xFC65E0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_1_SIZE 0xFC65E4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_1_STRIDE 0xFC65E8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_1_BASE_OFFSET 0xFC65EC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_2_SIZE 0xFC65F0
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_2_STRIDE 0xFC65F4
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_2_BASE_OFFSET 0xFC65F8
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_3_SIZE 0xFC65FC
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_3_STRIDE 0xFC6600
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_3_BASE_OFFSET 0xFC6604
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_4_SIZE 0xFC6608
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_4_STRIDE 0xFC660C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_6_DIM_4_BASE_OFFSET 0xFC6610
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_BASE_ADDR_LOW 0xFC6614
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_BASE_ADDR_HIGH 0xFC6618
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_PADDING_VALUE 0xFC661C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_TENSOR_CONFIG 0xFC6620
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_0_SIZE 0xFC6624
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_0_STRIDE 0xFC6628
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_0_BASE_OFFSET 0xFC662C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_1_SIZE 0xFC6630
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_1_STRIDE 0xFC6634
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_1_BASE_OFFSET 0xFC6638
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_2_SIZE 0xFC663C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_2_STRIDE 0xFC6640
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_2_BASE_OFFSET 0xFC6644
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_3_SIZE 0xFC6648
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_3_STRIDE 0xFC664C
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_3_BASE_OFFSET 0xFC6650
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_4_SIZE 0xFC6654
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_4_STRIDE 0xFC6658
+
+#define mmTPC7_CFG_KERNEL_TENSOR_7_DIM_4_BASE_OFFSET 0xFC665C
+
+#define mmTPC7_CFG_KERNEL_KERNEL_BASE_ADDRESS_LOW 0xFC6660
+
+#define mmTPC7_CFG_KERNEL_KERNEL_BASE_ADDRESS_HIGH 0xFC6664
+
+#define mmTPC7_CFG_KERNEL_TID_BASE_DIM_0 0xFC6668
+
+#define mmTPC7_CFG_KERNEL_TID_SIZE_DIM_0 0xFC666C
+
+#define mmTPC7_CFG_KERNEL_TID_BASE_DIM_1 0xFC6670
+
+#define mmTPC7_CFG_KERNEL_TID_SIZE_DIM_1 0xFC6674
+
+#define mmTPC7_CFG_KERNEL_TID_BASE_DIM_2 0xFC6678
+
+#define mmTPC7_CFG_KERNEL_TID_SIZE_DIM_2 0xFC667C
+
+#define mmTPC7_CFG_KERNEL_TID_BASE_DIM_3 0xFC6680
+
+#define mmTPC7_CFG_KERNEL_TID_SIZE_DIM_3 0xFC6684
+
+#define mmTPC7_CFG_KERNEL_TID_BASE_DIM_4 0xFC6688
+
+#define mmTPC7_CFG_KERNEL_TID_SIZE_DIM_4 0xFC668C
+
+#define mmTPC7_CFG_KERNEL_SRF_0 0xFC6690
+
+#define mmTPC7_CFG_KERNEL_SRF_1 0xFC6694
+
+#define mmTPC7_CFG_KERNEL_SRF_2 0xFC6698
+
+#define mmTPC7_CFG_KERNEL_SRF_3 0xFC669C
+
+#define mmTPC7_CFG_KERNEL_SRF_4 0xFC66A0
+
+#define mmTPC7_CFG_KERNEL_SRF_5 0xFC66A4
+
+#define mmTPC7_CFG_KERNEL_SRF_6 0xFC66A8
+
+#define mmTPC7_CFG_KERNEL_SRF_7 0xFC66AC
+
+#define mmTPC7_CFG_KERNEL_SRF_8 0xFC66B0
+
+#define mmTPC7_CFG_KERNEL_SRF_9 0xFC66B4
+
+#define mmTPC7_CFG_KERNEL_SRF_10 0xFC66B8
+
+#define mmTPC7_CFG_KERNEL_SRF_11 0xFC66BC
+
+#define mmTPC7_CFG_KERNEL_SRF_12 0xFC66C0
+
+#define mmTPC7_CFG_KERNEL_SRF_13 0xFC66C4
+
+#define mmTPC7_CFG_KERNEL_SRF_14 0xFC66C8
+
+#define mmTPC7_CFG_KERNEL_SRF_15 0xFC66CC
+
+#define mmTPC7_CFG_KERNEL_SRF_16 0xFC66D0
+
+#define mmTPC7_CFG_KERNEL_SRF_17 0xFC66D4
+
+#define mmTPC7_CFG_KERNEL_SRF_18 0xFC66D8
+
+#define mmTPC7_CFG_KERNEL_SRF_19 0xFC66DC
+
+#define mmTPC7_CFG_KERNEL_SRF_20 0xFC66E0
+
+#define mmTPC7_CFG_KERNEL_SRF_21 0xFC66E4
+
+#define mmTPC7_CFG_KERNEL_SRF_22 0xFC66E8
+
+#define mmTPC7_CFG_KERNEL_SRF_23 0xFC66EC
+
+#define mmTPC7_CFG_KERNEL_SRF_24 0xFC66F0
+
+#define mmTPC7_CFG_KERNEL_SRF_25 0xFC66F4
+
+#define mmTPC7_CFG_KERNEL_SRF_26 0xFC66F8
+
+#define mmTPC7_CFG_KERNEL_SRF_27 0xFC66FC
+
+#define mmTPC7_CFG_KERNEL_SRF_28 0xFC6700
+
+#define mmTPC7_CFG_KERNEL_SRF_29 0xFC6704
+
+#define mmTPC7_CFG_KERNEL_SRF_30 0xFC6708
+
+#define mmTPC7_CFG_KERNEL_SRF_31 0xFC670C
+
+#define mmTPC7_CFG_KERNEL_KERNEL_CONFIG 0xFC6710
+
+#define mmTPC7_CFG_KERNEL_SYNC_OBJECT_MESSAGE 0xFC6714
+
+#define mmTPC7_CFG_RESERVED_DESC_END 0xFC6738
+
+#define mmTPC7_CFG_ROUND_CSR 0xFC67FC
+
+#define mmTPC7_CFG_TBUF_BASE_ADDR_LOW 0xFC6800
+
+#define mmTPC7_CFG_TBUF_BASE_ADDR_HIGH 0xFC6804
+
+#define mmTPC7_CFG_SEMAPHORE 0xFC6808
+
+#define mmTPC7_CFG_VFLAGS 0xFC680C
+
+#define mmTPC7_CFG_SFLAGS 0xFC6810
+
+#define mmTPC7_CFG_LFSR_POLYNOM 0xFC6818
+
+#define mmTPC7_CFG_STATUS 0xFC681C
+
+#define mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH 0xFC6820
+
+#define mmTPC7_CFG_CFG_SUBTRACT_VALUE 0xFC6824
+
+#define mmTPC7_CFG_SM_BASE_ADDRESS_LOW 0xFC6828
+
+#define mmTPC7_CFG_SM_BASE_ADDRESS_HIGH 0xFC682C
+
+#define mmTPC7_CFG_TPC_CMD 0xFC6830
+
+#define mmTPC7_CFG_TPC_EXECUTE 0xFC6838
+
+#define mmTPC7_CFG_TPC_STALL 0xFC683C
+
+#define mmTPC7_CFG_ICACHE_BASE_ADDERESS_LOW 0xFC6840
+
+#define mmTPC7_CFG_ICACHE_BASE_ADDERESS_HIGH 0xFC6844
+
+#define mmTPC7_CFG_MSS_CONFIG 0xFC6854
+
+#define mmTPC7_CFG_TPC_INTR_CAUSE 0xFC6858
+
+#define mmTPC7_CFG_TPC_INTR_MASK 0xFC685C
+
+#define mmTPC7_CFG_TSB_CONFIG 0xFC6860
+
+#define mmTPC7_CFG_QM_TENSOR_0_BASE_ADDR_LOW 0xFC6A00
+
+#define mmTPC7_CFG_QM_TENSOR_0_BASE_ADDR_HIGH 0xFC6A04
+
+#define mmTPC7_CFG_QM_TENSOR_0_PADDING_VALUE 0xFC6A08
+
+#define mmTPC7_CFG_QM_TENSOR_0_TENSOR_CONFIG 0xFC6A0C
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_0_SIZE 0xFC6A10
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_0_STRIDE 0xFC6A14
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_0_BASE_OFFSET 0xFC6A18
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_1_SIZE 0xFC6A1C
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_1_STRIDE 0xFC6A20
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_1_BASE_OFFSET 0xFC6A24
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_2_SIZE 0xFC6A28
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_2_STRIDE 0xFC6A2C
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_2_BASE_OFFSET 0xFC6A30
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_3_SIZE 0xFC6A34
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_3_STRIDE 0xFC6A38
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_3_BASE_OFFSET 0xFC6A3C
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_4_SIZE 0xFC6A40
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_4_STRIDE 0xFC6A44
+
+#define mmTPC7_CFG_QM_TENSOR_0_DIM_4_BASE_OFFSET 0xFC6A48
+
+#define mmTPC7_CFG_QM_TENSOR_1_BASE_ADDR_LOW 0xFC6A4C
+
+#define mmTPC7_CFG_QM_TENSOR_1_BASE_ADDR_HIGH 0xFC6A50
+
+#define mmTPC7_CFG_QM_TENSOR_1_PADDING_VALUE 0xFC6A54
+
+#define mmTPC7_CFG_QM_TENSOR_1_TENSOR_CONFIG 0xFC6A58
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_0_SIZE 0xFC6A5C
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_0_STRIDE 0xFC6A60
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_0_BASE_OFFSET 0xFC6A64
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_1_SIZE 0xFC6A68
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_1_STRIDE 0xFC6A6C
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_1_BASE_OFFSET 0xFC6A70
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_2_SIZE 0xFC6A74
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_2_STRIDE 0xFC6A78
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_2_BASE_OFFSET 0xFC6A7C
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_3_SIZE 0xFC6A80
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_3_STRIDE 0xFC6A84
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_3_BASE_OFFSET 0xFC6A88
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_4_SIZE 0xFC6A8C
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_4_STRIDE 0xFC6A90
+
+#define mmTPC7_CFG_QM_TENSOR_1_DIM_4_BASE_OFFSET 0xFC6A94
+
+#define mmTPC7_CFG_QM_TENSOR_2_BASE_ADDR_LOW 0xFC6A98
+
+#define mmTPC7_CFG_QM_TENSOR_2_BASE_ADDR_HIGH 0xFC6A9C
+
+#define mmTPC7_CFG_QM_TENSOR_2_PADDING_VALUE 0xFC6AA0
+
+#define mmTPC7_CFG_QM_TENSOR_2_TENSOR_CONFIG 0xFC6AA4
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_0_SIZE 0xFC6AA8
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_0_STRIDE 0xFC6AAC
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_0_BASE_OFFSET 0xFC6AB0
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_1_SIZE 0xFC6AB4
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_1_STRIDE 0xFC6AB8
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_1_BASE_OFFSET 0xFC6ABC
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_2_SIZE 0xFC6AC0
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_2_STRIDE 0xFC6AC4
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_2_BASE_OFFSET 0xFC6AC8
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_3_SIZE 0xFC6ACC
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_3_STRIDE 0xFC6AD0
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_3_BASE_OFFSET 0xFC6AD4
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_4_SIZE 0xFC6AD8
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_4_STRIDE 0xFC6ADC
+
+#define mmTPC7_CFG_QM_TENSOR_2_DIM_4_BASE_OFFSET 0xFC6AE0
+
+#define mmTPC7_CFG_QM_TENSOR_3_BASE_ADDR_LOW 0xFC6AE4
+
+#define mmTPC7_CFG_QM_TENSOR_3_BASE_ADDR_HIGH 0xFC6AE8
+
+#define mmTPC7_CFG_QM_TENSOR_3_PADDING_VALUE 0xFC6AEC
+
+#define mmTPC7_CFG_QM_TENSOR_3_TENSOR_CONFIG 0xFC6AF0
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_0_SIZE 0xFC6AF4
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_0_STRIDE 0xFC6AF8
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_0_BASE_OFFSET 0xFC6AFC
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_1_SIZE 0xFC6B00
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_1_STRIDE 0xFC6B04
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_1_BASE_OFFSET 0xFC6B08
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_2_SIZE 0xFC6B0C
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_2_STRIDE 0xFC6B10
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_2_BASE_OFFSET 0xFC6B14
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_3_SIZE 0xFC6B18
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_3_STRIDE 0xFC6B1C
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_3_BASE_OFFSET 0xFC6B20
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_4_SIZE 0xFC6B24
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_4_STRIDE 0xFC6B28
+
+#define mmTPC7_CFG_QM_TENSOR_3_DIM_4_BASE_OFFSET 0xFC6B2C
+
+#define mmTPC7_CFG_QM_TENSOR_4_BASE_ADDR_LOW 0xFC6B30
+
+#define mmTPC7_CFG_QM_TENSOR_4_BASE_ADDR_HIGH 0xFC6B34
+
+#define mmTPC7_CFG_QM_TENSOR_4_PADDING_VALUE 0xFC6B38
+
+#define mmTPC7_CFG_QM_TENSOR_4_TENSOR_CONFIG 0xFC6B3C
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_0_SIZE 0xFC6B40
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_0_STRIDE 0xFC6B44
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_0_BASE_OFFSET 0xFC6B48
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_1_SIZE 0xFC6B4C
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_1_STRIDE 0xFC6B50
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_1_BASE_OFFSET 0xFC6B54
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_2_SIZE 0xFC6B58
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_2_STRIDE 0xFC6B5C
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_2_BASE_OFFSET 0xFC6B60
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_3_SIZE 0xFC6B64
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_3_STRIDE 0xFC6B68
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_3_BASE_OFFSET 0xFC6B6C
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_4_SIZE 0xFC6B70
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_4_STRIDE 0xFC6B74
+
+#define mmTPC7_CFG_QM_TENSOR_4_DIM_4_BASE_OFFSET 0xFC6B78
+
+#define mmTPC7_CFG_QM_TENSOR_5_BASE_ADDR_LOW 0xFC6B7C
+
+#define mmTPC7_CFG_QM_TENSOR_5_BASE_ADDR_HIGH 0xFC6B80
+
+#define mmTPC7_CFG_QM_TENSOR_5_PADDING_VALUE 0xFC6B84
+
+#define mmTPC7_CFG_QM_TENSOR_5_TENSOR_CONFIG 0xFC6B88
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_0_SIZE 0xFC6B8C
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_0_STRIDE 0xFC6B90
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_0_BASE_OFFSET 0xFC6B94
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_1_SIZE 0xFC6B98
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_1_STRIDE 0xFC6B9C
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_1_BASE_OFFSET 0xFC6BA0
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_2_SIZE 0xFC6BA4
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_2_STRIDE 0xFC6BA8
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_2_BASE_OFFSET 0xFC6BAC
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_3_SIZE 0xFC6BB0
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_3_STRIDE 0xFC6BB4
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_3_BASE_OFFSET 0xFC6BB8
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_4_SIZE 0xFC6BBC
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_4_STRIDE 0xFC6BC0
+
+#define mmTPC7_CFG_QM_TENSOR_5_DIM_4_BASE_OFFSET 0xFC6BC4
+
+#define mmTPC7_CFG_QM_TENSOR_6_BASE_ADDR_LOW 0xFC6BC8
+
+#define mmTPC7_CFG_QM_TENSOR_6_BASE_ADDR_HIGH 0xFC6BCC
+
+#define mmTPC7_CFG_QM_TENSOR_6_PADDING_VALUE 0xFC6BD0
+
+#define mmTPC7_CFG_QM_TENSOR_6_TENSOR_CONFIG 0xFC6BD4
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_0_SIZE 0xFC6BD8
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_0_STRIDE 0xFC6BDC
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_0_BASE_OFFSET 0xFC6BE0
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_1_SIZE 0xFC6BE4
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_1_STRIDE 0xFC6BE8
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_1_BASE_OFFSET 0xFC6BEC
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_2_SIZE 0xFC6BF0
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_2_STRIDE 0xFC6BF4
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_2_BASE_OFFSET 0xFC6BF8
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_3_SIZE 0xFC6BFC
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_3_STRIDE 0xFC6C00
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_3_BASE_OFFSET 0xFC6C04
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_4_SIZE 0xFC6C08
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_4_STRIDE 0xFC6C0C
+
+#define mmTPC7_CFG_QM_TENSOR_6_DIM_4_BASE_OFFSET 0xFC6C10
+
+#define mmTPC7_CFG_QM_TENSOR_7_BASE_ADDR_LOW 0xFC6C14
+
+#define mmTPC7_CFG_QM_TENSOR_7_BASE_ADDR_HIGH 0xFC6C18
+
+#define mmTPC7_CFG_QM_TENSOR_7_PADDING_VALUE 0xFC6C1C
+
+#define mmTPC7_CFG_QM_TENSOR_7_TENSOR_CONFIG 0xFC6C20
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_0_SIZE 0xFC6C24
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_0_STRIDE 0xFC6C28
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_0_BASE_OFFSET 0xFC6C2C
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_1_SIZE 0xFC6C30
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_1_STRIDE 0xFC6C34
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_1_BASE_OFFSET 0xFC6C38
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_2_SIZE 0xFC6C3C
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_2_STRIDE 0xFC6C40
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_2_BASE_OFFSET 0xFC6C44
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_3_SIZE 0xFC6C48
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_3_STRIDE 0xFC6C4C
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_3_BASE_OFFSET 0xFC6C50
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_4_SIZE 0xFC6C54
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_4_STRIDE 0xFC6C58
+
+#define mmTPC7_CFG_QM_TENSOR_7_DIM_4_BASE_OFFSET 0xFC6C5C
+
+#define mmTPC7_CFG_QM_KERNEL_BASE_ADDRESS_LOW 0xFC6C60
+
+#define mmTPC7_CFG_QM_KERNEL_BASE_ADDRESS_HIGH 0xFC6C64
+
+#define mmTPC7_CFG_QM_TID_BASE_DIM_0 0xFC6C68
+
+#define mmTPC7_CFG_QM_TID_SIZE_DIM_0 0xFC6C6C
+
+#define mmTPC7_CFG_QM_TID_BASE_DIM_1 0xFC6C70
+
+#define mmTPC7_CFG_QM_TID_SIZE_DIM_1 0xFC6C74
+
+#define mmTPC7_CFG_QM_TID_BASE_DIM_2 0xFC6C78
+
+#define mmTPC7_CFG_QM_TID_SIZE_DIM_2 0xFC6C7C
+
+#define mmTPC7_CFG_QM_TID_BASE_DIM_3 0xFC6C80
+
+#define mmTPC7_CFG_QM_TID_SIZE_DIM_3 0xFC6C84
+
+#define mmTPC7_CFG_QM_TID_BASE_DIM_4 0xFC6C88
+
+#define mmTPC7_CFG_QM_TID_SIZE_DIM_4 0xFC6C8C
+
+#define mmTPC7_CFG_QM_SRF_0 0xFC6C90
+
+#define mmTPC7_CFG_QM_SRF_1 0xFC6C94
+
+#define mmTPC7_CFG_QM_SRF_2 0xFC6C98
+
+#define mmTPC7_CFG_QM_SRF_3 0xFC6C9C
+
+#define mmTPC7_CFG_QM_SRF_4 0xFC6CA0
+
+#define mmTPC7_CFG_QM_SRF_5 0xFC6CA4
+
+#define mmTPC7_CFG_QM_SRF_6 0xFC6CA8
+
+#define mmTPC7_CFG_QM_SRF_7 0xFC6CAC
+
+#define mmTPC7_CFG_QM_SRF_8 0xFC6CB0
+
+#define mmTPC7_CFG_QM_SRF_9 0xFC6CB4
+
+#define mmTPC7_CFG_QM_SRF_10 0xFC6CB8
+
+#define mmTPC7_CFG_QM_SRF_11 0xFC6CBC
+
+#define mmTPC7_CFG_QM_SRF_12 0xFC6CC0
+
+#define mmTPC7_CFG_QM_SRF_13 0xFC6CC4
+
+#define mmTPC7_CFG_QM_SRF_14 0xFC6CC8
+
+#define mmTPC7_CFG_QM_SRF_15 0xFC6CCC
+
+#define mmTPC7_CFG_QM_SRF_16 0xFC6CD0
+
+#define mmTPC7_CFG_QM_SRF_17 0xFC6CD4
+
+#define mmTPC7_CFG_QM_SRF_18 0xFC6CD8
+
+#define mmTPC7_CFG_QM_SRF_19 0xFC6CDC
+
+#define mmTPC7_CFG_QM_SRF_20 0xFC6CE0
+
+#define mmTPC7_CFG_QM_SRF_21 0xFC6CE4
+
+#define mmTPC7_CFG_QM_SRF_22 0xFC6CE8
+
+#define mmTPC7_CFG_QM_SRF_23 0xFC6CEC
+
+#define mmTPC7_CFG_QM_SRF_24 0xFC6CF0
+
+#define mmTPC7_CFG_QM_SRF_25 0xFC6CF4
+
+#define mmTPC7_CFG_QM_SRF_26 0xFC6CF8
+
+#define mmTPC7_CFG_QM_SRF_27 0xFC6CFC
+
+#define mmTPC7_CFG_QM_SRF_28 0xFC6D00
+
+#define mmTPC7_CFG_QM_SRF_29 0xFC6D04
+
+#define mmTPC7_CFG_QM_SRF_30 0xFC6D08
+
+#define mmTPC7_CFG_QM_SRF_31 0xFC6D0C
+
+#define mmTPC7_CFG_QM_KERNEL_CONFIG 0xFC6D10
+
+#define mmTPC7_CFG_QM_SYNC_OBJECT_MESSAGE 0xFC6D14
+
+#define mmTPC7_CFG_ARUSER 0xFC6D18
+
+#define mmTPC7_CFG_AWUSER 0xFC6D1C
+
+#define mmTPC7_CFG_FUNC_MBIST_CNTRL 0xFC6E00
+
+#define mmTPC7_CFG_FUNC_MBIST_PAT 0xFC6E04
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_0 0xFC6E08
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_1 0xFC6E0C
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_2 0xFC6E10
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_3 0xFC6E14
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_4 0xFC6E18
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_5 0xFC6E1C
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_6 0xFC6E20
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_7 0xFC6E24
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_8 0xFC6E28
+
+#define mmTPC7_CFG_FUNC_MBIST_MEM_9 0xFC6E2C
+
+#endif /* ASIC_REG_TPC7_CFG_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h
new file mode 100644
index 000000000000..65d83043bf63
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_cmdq_regs.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC7_CMDQ_REGS_H_
+#define ASIC_REG_TPC7_CMDQ_REGS_H_
+
+/*
+ *****************************************
+ * TPC7_CMDQ (Prototype: CMDQ)
+ *****************************************
+ */
+
+#define mmTPC7_CMDQ_GLBL_CFG0 0xFC9000
+
+#define mmTPC7_CMDQ_GLBL_CFG1 0xFC9004
+
+#define mmTPC7_CMDQ_GLBL_PROT 0xFC9008
+
+#define mmTPC7_CMDQ_GLBL_ERR_CFG 0xFC900C
+
+#define mmTPC7_CMDQ_GLBL_ERR_ADDR_LO 0xFC9010
+
+#define mmTPC7_CMDQ_GLBL_ERR_ADDR_HI 0xFC9014
+
+#define mmTPC7_CMDQ_GLBL_ERR_WDATA 0xFC9018
+
+#define mmTPC7_CMDQ_GLBL_SECURE_PROPS 0xFC901C
+
+#define mmTPC7_CMDQ_GLBL_NON_SECURE_PROPS 0xFC9020
+
+#define mmTPC7_CMDQ_GLBL_STS0 0xFC9024
+
+#define mmTPC7_CMDQ_GLBL_STS1 0xFC9028
+
+#define mmTPC7_CMDQ_CQ_CFG0 0xFC90B0
+
+#define mmTPC7_CMDQ_CQ_CFG1 0xFC90B4
+
+#define mmTPC7_CMDQ_CQ_ARUSER 0xFC90B8
+
+#define mmTPC7_CMDQ_CQ_PTR_LO 0xFC90C0
+
+#define mmTPC7_CMDQ_CQ_PTR_HI 0xFC90C4
+
+#define mmTPC7_CMDQ_CQ_TSIZE 0xFC90C8
+
+#define mmTPC7_CMDQ_CQ_CTL 0xFC90CC
+
+#define mmTPC7_CMDQ_CQ_PTR_LO_STS 0xFC90D4
+
+#define mmTPC7_CMDQ_CQ_PTR_HI_STS 0xFC90D8
+
+#define mmTPC7_CMDQ_CQ_TSIZE_STS 0xFC90DC
+
+#define mmTPC7_CMDQ_CQ_CTL_STS 0xFC90E0
+
+#define mmTPC7_CMDQ_CQ_STS0 0xFC90E4
+
+#define mmTPC7_CMDQ_CQ_STS1 0xFC90E8
+
+#define mmTPC7_CMDQ_CQ_RD_RATE_LIM_EN 0xFC90F0
+
+#define mmTPC7_CMDQ_CQ_RD_RATE_LIM_RST_TOKEN 0xFC90F4
+
+#define mmTPC7_CMDQ_CQ_RD_RATE_LIM_SAT 0xFC90F8
+
+#define mmTPC7_CMDQ_CQ_RD_RATE_LIM_TOUT 0xFC90FC
+
+#define mmTPC7_CMDQ_CQ_IFIFO_CNT 0xFC9108
+
+#define mmTPC7_CMDQ_CP_MSG_BASE0_ADDR_LO 0xFC9120
+
+#define mmTPC7_CMDQ_CP_MSG_BASE0_ADDR_HI 0xFC9124
+
+#define mmTPC7_CMDQ_CP_MSG_BASE1_ADDR_LO 0xFC9128
+
+#define mmTPC7_CMDQ_CP_MSG_BASE1_ADDR_HI 0xFC912C
+
+#define mmTPC7_CMDQ_CP_MSG_BASE2_ADDR_LO 0xFC9130
+
+#define mmTPC7_CMDQ_CP_MSG_BASE2_ADDR_HI 0xFC9134
+
+#define mmTPC7_CMDQ_CP_MSG_BASE3_ADDR_LO 0xFC9138
+
+#define mmTPC7_CMDQ_CP_MSG_BASE3_ADDR_HI 0xFC913C
+
+#define mmTPC7_CMDQ_CP_LDMA_TSIZE_OFFSET 0xFC9140
+
+#define mmTPC7_CMDQ_CP_LDMA_SRC_BASE_LO_OFFSET 0xFC9144
+
+#define mmTPC7_CMDQ_CP_LDMA_SRC_BASE_HI_OFFSET 0xFC9148
+
+#define mmTPC7_CMDQ_CP_LDMA_DST_BASE_LO_OFFSET 0xFC914C
+
+#define mmTPC7_CMDQ_CP_LDMA_DST_BASE_HI_OFFSET 0xFC9150
+
+#define mmTPC7_CMDQ_CP_LDMA_COMMIT_OFFSET 0xFC9154
+
+#define mmTPC7_CMDQ_CP_FENCE0_RDATA 0xFC9158
+
+#define mmTPC7_CMDQ_CP_FENCE1_RDATA 0xFC915C
+
+#define mmTPC7_CMDQ_CP_FENCE2_RDATA 0xFC9160
+
+#define mmTPC7_CMDQ_CP_FENCE3_RDATA 0xFC9164
+
+#define mmTPC7_CMDQ_CP_FENCE0_CNT 0xFC9168
+
+#define mmTPC7_CMDQ_CP_FENCE1_CNT 0xFC916C
+
+#define mmTPC7_CMDQ_CP_FENCE2_CNT 0xFC9170
+
+#define mmTPC7_CMDQ_CP_FENCE3_CNT 0xFC9174
+
+#define mmTPC7_CMDQ_CP_STS 0xFC9178
+
+#define mmTPC7_CMDQ_CP_CURRENT_INST_LO 0xFC917C
+
+#define mmTPC7_CMDQ_CP_CURRENT_INST_HI 0xFC9180
+
+#define mmTPC7_CMDQ_CP_BARRIER_CFG 0xFC9184
+
+#define mmTPC7_CMDQ_CP_DBG_0 0xFC9188
+
+#define mmTPC7_CMDQ_CQ_BUF_ADDR 0xFC9308
+
+#define mmTPC7_CMDQ_CQ_BUF_RDATA 0xFC930C
+
+#endif /* ASIC_REG_TPC7_CMDQ_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h
new file mode 100644
index 000000000000..3d5848d87304
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_nrtr_regs.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC7_NRTR_REGS_H_
+#define ASIC_REG_TPC7_NRTR_REGS_H_
+
+/*
+ *****************************************
+ * TPC7_NRTR (Prototype: IF_NRTR)
+ *****************************************
+ */
+
+#define mmTPC7_NRTR_HBW_MAX_CRED 0xFC0100
+
+#define mmTPC7_NRTR_LBW_MAX_CRED 0xFC0120
+
+#define mmTPC7_NRTR_DBG_E_ARB 0xFC0300
+
+#define mmTPC7_NRTR_DBG_W_ARB 0xFC0304
+
+#define mmTPC7_NRTR_DBG_N_ARB 0xFC0308
+
+#define mmTPC7_NRTR_DBG_S_ARB 0xFC030C
+
+#define mmTPC7_NRTR_DBG_L_ARB 0xFC0310
+
+#define mmTPC7_NRTR_DBG_E_ARB_MAX 0xFC0320
+
+#define mmTPC7_NRTR_DBG_W_ARB_MAX 0xFC0324
+
+#define mmTPC7_NRTR_DBG_N_ARB_MAX 0xFC0328
+
+#define mmTPC7_NRTR_DBG_S_ARB_MAX 0xFC032C
+
+#define mmTPC7_NRTR_DBG_L_ARB_MAX 0xFC0330
+
+#define mmTPC7_NRTR_SPLIT_COEF_0 0xFC0400
+
+#define mmTPC7_NRTR_SPLIT_COEF_1 0xFC0404
+
+#define mmTPC7_NRTR_SPLIT_COEF_2 0xFC0408
+
+#define mmTPC7_NRTR_SPLIT_COEF_3 0xFC040C
+
+#define mmTPC7_NRTR_SPLIT_COEF_4 0xFC0410
+
+#define mmTPC7_NRTR_SPLIT_COEF_5 0xFC0414
+
+#define mmTPC7_NRTR_SPLIT_COEF_6 0xFC0418
+
+#define mmTPC7_NRTR_SPLIT_COEF_7 0xFC041C
+
+#define mmTPC7_NRTR_SPLIT_COEF_8 0xFC0420
+
+#define mmTPC7_NRTR_SPLIT_COEF_9 0xFC0424
+
+#define mmTPC7_NRTR_SPLIT_CFG 0xFC0440
+
+#define mmTPC7_NRTR_SPLIT_RD_SAT 0xFC0444
+
+#define mmTPC7_NRTR_SPLIT_RD_RST_TOKEN 0xFC0448
+
+#define mmTPC7_NRTR_SPLIT_RD_TIMEOUT_0 0xFC044C
+
+#define mmTPC7_NRTR_SPLIT_RD_TIMEOUT_1 0xFC0450
+
+#define mmTPC7_NRTR_SPLIT_WR_SAT 0xFC0454
+
+#define mmTPC7_NRTR_WPLIT_WR_TST_TOLEN 0xFC0458
+
+#define mmTPC7_NRTR_SPLIT_WR_TIMEOUT_0 0xFC045C
+
+#define mmTPC7_NRTR_SPLIT_WR_TIMEOUT_1 0xFC0460
+
+#define mmTPC7_NRTR_HBW_RANGE_HIT 0xFC0470
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_0 0xFC0480
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_1 0xFC0484
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_2 0xFC0488
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_3 0xFC048C
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_4 0xFC0490
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_5 0xFC0494
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_6 0xFC0498
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_L_7 0xFC049C
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_0 0xFC04A0
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_1 0xFC04A4
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_2 0xFC04A8
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_3 0xFC04AC
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_4 0xFC04B0
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_5 0xFC04B4
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_6 0xFC04B8
+
+#define mmTPC7_NRTR_HBW_RANGE_MASK_H_7 0xFC04BC
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_0 0xFC04C0
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_1 0xFC04C4
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_2 0xFC04C8
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_3 0xFC04CC
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_4 0xFC04D0
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_5 0xFC04D4
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_6 0xFC04D8
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_L_7 0xFC04DC
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_0 0xFC04E0
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_1 0xFC04E4
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_2 0xFC04E8
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_3 0xFC04EC
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_4 0xFC04F0
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_5 0xFC04F4
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_6 0xFC04F8
+
+#define mmTPC7_NRTR_HBW_RANGE_BASE_H_7 0xFC04FC
+
+#define mmTPC7_NRTR_LBW_RANGE_HIT 0xFC0500
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_0 0xFC0510
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_1 0xFC0514
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_2 0xFC0518
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_3 0xFC051C
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_4 0xFC0520
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_5 0xFC0524
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_6 0xFC0528
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_7 0xFC052C
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_8 0xFC0530
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_9 0xFC0534
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_10 0xFC0538
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_11 0xFC053C
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_12 0xFC0540
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_13 0xFC0544
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_14 0xFC0548
+
+#define mmTPC7_NRTR_LBW_RANGE_MASK_15 0xFC054C
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_0 0xFC0550
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_1 0xFC0554
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_2 0xFC0558
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_3 0xFC055C
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_4 0xFC0560
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_5 0xFC0564
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_6 0xFC0568
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_7 0xFC056C
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_8 0xFC0570
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_9 0xFC0574
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_10 0xFC0578
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_11 0xFC057C
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_12 0xFC0580
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_13 0xFC0584
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_14 0xFC0588
+
+#define mmTPC7_NRTR_LBW_RANGE_BASE_15 0xFC058C
+
+#define mmTPC7_NRTR_RGLTR 0xFC0590
+
+#define mmTPC7_NRTR_RGLTR_WR_RESULT 0xFC0594
+
+#define mmTPC7_NRTR_RGLTR_RD_RESULT 0xFC0598
+
+#define mmTPC7_NRTR_SCRAMB_EN 0xFC0600
+
+#define mmTPC7_NRTR_NON_LIN_SCRAMB 0xFC0604
+
+#endif /* ASIC_REG_TPC7_NRTR_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h
new file mode 100644
index 000000000000..25f5095f68fb
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc7_qm_regs.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC7_QM_REGS_H_
+#define ASIC_REG_TPC7_QM_REGS_H_
+
+/*
+ *****************************************
+ * TPC7_QM (Prototype: QMAN)
+ *****************************************
+ */
+
+#define mmTPC7_QM_GLBL_CFG0 0xFC8000
+
+#define mmTPC7_QM_GLBL_CFG1 0xFC8004
+
+#define mmTPC7_QM_GLBL_PROT 0xFC8008
+
+#define mmTPC7_QM_GLBL_ERR_CFG 0xFC800C
+
+#define mmTPC7_QM_GLBL_ERR_ADDR_LO 0xFC8010
+
+#define mmTPC7_QM_GLBL_ERR_ADDR_HI 0xFC8014
+
+#define mmTPC7_QM_GLBL_ERR_WDATA 0xFC8018
+
+#define mmTPC7_QM_GLBL_SECURE_PROPS 0xFC801C
+
+#define mmTPC7_QM_GLBL_NON_SECURE_PROPS 0xFC8020
+
+#define mmTPC7_QM_GLBL_STS0 0xFC8024
+
+#define mmTPC7_QM_GLBL_STS1 0xFC8028
+
+#define mmTPC7_QM_PQ_BASE_LO 0xFC8060
+
+#define mmTPC7_QM_PQ_BASE_HI 0xFC8064
+
+#define mmTPC7_QM_PQ_SIZE 0xFC8068
+
+#define mmTPC7_QM_PQ_PI 0xFC806C
+
+#define mmTPC7_QM_PQ_CI 0xFC8070
+
+#define mmTPC7_QM_PQ_CFG0 0xFC8074
+
+#define mmTPC7_QM_PQ_CFG1 0xFC8078
+
+#define mmTPC7_QM_PQ_ARUSER 0xFC807C
+
+#define mmTPC7_QM_PQ_PUSH0 0xFC8080
+
+#define mmTPC7_QM_PQ_PUSH1 0xFC8084
+
+#define mmTPC7_QM_PQ_PUSH2 0xFC8088
+
+#define mmTPC7_QM_PQ_PUSH3 0xFC808C
+
+#define mmTPC7_QM_PQ_STS0 0xFC8090
+
+#define mmTPC7_QM_PQ_STS1 0xFC8094
+
+#define mmTPC7_QM_PQ_RD_RATE_LIM_EN 0xFC80A0
+
+#define mmTPC7_QM_PQ_RD_RATE_LIM_RST_TOKEN 0xFC80A4
+
+#define mmTPC7_QM_PQ_RD_RATE_LIM_SAT 0xFC80A8
+
+#define mmTPC7_QM_PQ_RD_RATE_LIM_TOUT 0xFC80AC
+
+#define mmTPC7_QM_CQ_CFG0 0xFC80B0
+
+#define mmTPC7_QM_CQ_CFG1 0xFC80B4
+
+#define mmTPC7_QM_CQ_ARUSER 0xFC80B8
+
+#define mmTPC7_QM_CQ_PTR_LO 0xFC80C0
+
+#define mmTPC7_QM_CQ_PTR_HI 0xFC80C4
+
+#define mmTPC7_QM_CQ_TSIZE 0xFC80C8
+
+#define mmTPC7_QM_CQ_CTL 0xFC80CC
+
+#define mmTPC7_QM_CQ_PTR_LO_STS 0xFC80D4
+
+#define mmTPC7_QM_CQ_PTR_HI_STS 0xFC80D8
+
+#define mmTPC7_QM_CQ_TSIZE_STS 0xFC80DC
+
+#define mmTPC7_QM_CQ_CTL_STS 0xFC80E0
+
+#define mmTPC7_QM_CQ_STS0 0xFC80E4
+
+#define mmTPC7_QM_CQ_STS1 0xFC80E8
+
+#define mmTPC7_QM_CQ_RD_RATE_LIM_EN 0xFC80F0
+
+#define mmTPC7_QM_CQ_RD_RATE_LIM_RST_TOKEN 0xFC80F4
+
+#define mmTPC7_QM_CQ_RD_RATE_LIM_SAT 0xFC80F8
+
+#define mmTPC7_QM_CQ_RD_RATE_LIM_TOUT 0xFC80FC
+
+#define mmTPC7_QM_CQ_IFIFO_CNT 0xFC8108
+
+#define mmTPC7_QM_CP_MSG_BASE0_ADDR_LO 0xFC8120
+
+#define mmTPC7_QM_CP_MSG_BASE0_ADDR_HI 0xFC8124
+
+#define mmTPC7_QM_CP_MSG_BASE1_ADDR_LO 0xFC8128
+
+#define mmTPC7_QM_CP_MSG_BASE1_ADDR_HI 0xFC812C
+
+#define mmTPC7_QM_CP_MSG_BASE2_ADDR_LO 0xFC8130
+
+#define mmTPC7_QM_CP_MSG_BASE2_ADDR_HI 0xFC8134
+
+#define mmTPC7_QM_CP_MSG_BASE3_ADDR_LO 0xFC8138
+
+#define mmTPC7_QM_CP_MSG_BASE3_ADDR_HI 0xFC813C
+
+#define mmTPC7_QM_CP_LDMA_TSIZE_OFFSET 0xFC8140
+
+#define mmTPC7_QM_CP_LDMA_SRC_BASE_LO_OFFSET 0xFC8144
+
+#define mmTPC7_QM_CP_LDMA_SRC_BASE_HI_OFFSET 0xFC8148
+
+#define mmTPC7_QM_CP_LDMA_DST_BASE_LO_OFFSET 0xFC814C
+
+#define mmTPC7_QM_CP_LDMA_DST_BASE_HI_OFFSET 0xFC8150
+
+#define mmTPC7_QM_CP_LDMA_COMMIT_OFFSET 0xFC8154
+
+#define mmTPC7_QM_CP_FENCE0_RDATA 0xFC8158
+
+#define mmTPC7_QM_CP_FENCE1_RDATA 0xFC815C
+
+#define mmTPC7_QM_CP_FENCE2_RDATA 0xFC8160
+
+#define mmTPC7_QM_CP_FENCE3_RDATA 0xFC8164
+
+#define mmTPC7_QM_CP_FENCE0_CNT 0xFC8168
+
+#define mmTPC7_QM_CP_FENCE1_CNT 0xFC816C
+
+#define mmTPC7_QM_CP_FENCE2_CNT 0xFC8170
+
+#define mmTPC7_QM_CP_FENCE3_CNT 0xFC8174
+
+#define mmTPC7_QM_CP_STS 0xFC8178
+
+#define mmTPC7_QM_CP_CURRENT_INST_LO 0xFC817C
+
+#define mmTPC7_QM_CP_CURRENT_INST_HI 0xFC8180
+
+#define mmTPC7_QM_CP_BARRIER_CFG 0xFC8184
+
+#define mmTPC7_QM_CP_DBG_0 0xFC8188
+
+#define mmTPC7_QM_PQ_BUF_ADDR 0xFC8300
+
+#define mmTPC7_QM_PQ_BUF_RDATA 0xFC8304
+
+#define mmTPC7_QM_CQ_BUF_ADDR 0xFC8308
+
+#define mmTPC7_QM_CQ_BUF_RDATA 0xFC830C
+
+#endif /* ASIC_REG_TPC7_QM_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h
new file mode 100644
index 000000000000..920231d0afa5
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/asic_reg/tpc_pll_regs.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ ** DO NOT EDIT BELOW **
+ ************************************/
+
+#ifndef ASIC_REG_TPC_PLL_REGS_H_
+#define ASIC_REG_TPC_PLL_REGS_H_
+
+/*
+ *****************************************
+ * TPC_PLL (Prototype: PLL)
+ *****************************************
+ */
+
+#define mmTPC_PLL_NR 0xE01100
+
+#define mmTPC_PLL_NF 0xE01104
+
+#define mmTPC_PLL_OD 0xE01108
+
+#define mmTPC_PLL_NB 0xE0110C
+
+#define mmTPC_PLL_CFG 0xE01110
+
+#define mmTPC_PLL_LOSE_MASK 0xE01120
+
+#define mmTPC_PLL_LOCK_INTR 0xE01128
+
+#define mmTPC_PLL_LOCK_BYPASS 0xE0112C
+
+#define mmTPC_PLL_DATA_CHNG 0xE01130
+
+#define mmTPC_PLL_RST 0xE01134
+
+#define mmTPC_PLL_SLIP_WD_CNTR 0xE01150
+
+#define mmTPC_PLL_DIV_FACTOR_0 0xE01200
+
+#define mmTPC_PLL_DIV_FACTOR_1 0xE01204
+
+#define mmTPC_PLL_DIV_FACTOR_2 0xE01208
+
+#define mmTPC_PLL_DIV_FACTOR_3 0xE0120C
+
+#define mmTPC_PLL_DIV_FACTOR_CMD_0 0xE01220
+
+#define mmTPC_PLL_DIV_FACTOR_CMD_1 0xE01224
+
+#define mmTPC_PLL_DIV_FACTOR_CMD_2 0xE01228
+
+#define mmTPC_PLL_DIV_FACTOR_CMD_3 0xE0122C
+
+#define mmTPC_PLL_DIV_SEL_0 0xE01280
+
+#define mmTPC_PLL_DIV_SEL_1 0xE01284
+
+#define mmTPC_PLL_DIV_SEL_2 0xE01288
+
+#define mmTPC_PLL_DIV_SEL_3 0xE0128C
+
+#define mmTPC_PLL_DIV_EN_0 0xE012A0
+
+#define mmTPC_PLL_DIV_EN_1 0xE012A4
+
+#define mmTPC_PLL_DIV_EN_2 0xE012A8
+
+#define mmTPC_PLL_DIV_EN_3 0xE012AC
+
+#define mmTPC_PLL_DIV_FACTOR_BUSY_0 0xE012C0
+
+#define mmTPC_PLL_DIV_FACTOR_BUSY_1 0xE012C4
+
+#define mmTPC_PLL_DIV_FACTOR_BUSY_2 0xE012C8
+
+#define mmTPC_PLL_DIV_FACTOR_BUSY_3 0xE012CC
+
+#define mmTPC_PLL_CLK_GATER 0xE01300
+
+#define mmTPC_PLL_CLK_RLX_0 0xE01310
+
+#define mmTPC_PLL_CLK_RLX_1 0xE01314
+
+#define mmTPC_PLL_CLK_RLX_2 0xE01318
+
+#define mmTPC_PLL_CLK_RLX_3 0xE0131C
+
+#define mmTPC_PLL_REF_CNTR_PERIOD 0xE01400
+
+#define mmTPC_PLL_REF_LOW_THRESHOLD 0xE01410
+
+#define mmTPC_PLL_REF_HIGH_THRESHOLD 0xE01420
+
+#define mmTPC_PLL_PLL_NOT_STABLE 0xE01430
+
+#define mmTPC_PLL_FREQ_CALC_EN 0xE01440
+
+#endif /* ASIC_REG_TPC_PLL_REGS_H_ */
+
diff --git a/drivers/misc/habanalabs/include/goya/goya.h b/drivers/misc/habanalabs/include/goya/goya.h
new file mode 100644
index 000000000000..614149efa412
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/goya.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef GOYA_H
+#define GOYA_H
+
+#include "asic_reg/goya_regs.h"
+
+#include <linux/types.h>
+
+#define SRAM_CFG_BAR_ID 0
+#define MSIX_BAR_ID 2
+#define DDR_BAR_ID 4
+
+#define CFG_BAR_SIZE 0x10000000ull /* 256MB */
+#define MSIX_BAR_SIZE 0x1000ull /* 4KB */
+
+#define CFG_BASE 0x7FFC000000ull
+#define CFG_SIZE 0x4000000 /* 32MB CFG + 32MB DBG*/
+
+#define SRAM_BASE_ADDR 0x7FF0000000ull
+#define SRAM_SIZE 0x32A0000 /* 50.625MB */
+
+#define DRAM_PHYS_BASE 0x0ull
+
+#define HOST_PHYS_BASE 0x8000000000ull /* 0.5TB */
+#define HOST_PHYS_SIZE 0x1000000000000ull /* 0.25PB (48 bits) */
+
+#define GOYA_MSIX_ENTRIES 8
+
+#define QMAN_PQ_ENTRY_SIZE 16 /* Bytes */
+
+#define MAX_ASID 1024
+
+#define PROT_BITS_OFFS 0xF80
+
+#define DMA_MAX_NUM 5
+
+#define TPC_MAX_NUM 8
+
+#endif /* GOYA_H */
diff --git a/drivers/misc/habanalabs/include/goya/goya_async_events.h b/drivers/misc/habanalabs/include/goya/goya_async_events.h
new file mode 100644
index 000000000000..497937a17ee9
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/goya_async_events.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef __GOYA_ASYNC_EVENTS_H_
+#define __GOYA_ASYNC_EVENTS_H_
+
+enum goya_async_event_id {
+ GOYA_ASYNC_EVENT_ID_PCIE_IF = 33,
+ GOYA_ASYNC_EVENT_ID_TPC0_ECC = 36,
+ GOYA_ASYNC_EVENT_ID_TPC1_ECC = 39,
+ GOYA_ASYNC_EVENT_ID_TPC2_ECC = 42,
+ GOYA_ASYNC_EVENT_ID_TPC3_ECC = 45,
+ GOYA_ASYNC_EVENT_ID_TPC4_ECC = 48,
+ GOYA_ASYNC_EVENT_ID_TPC5_ECC = 51,
+ GOYA_ASYNC_EVENT_ID_TPC6_ECC = 54,
+ GOYA_ASYNC_EVENT_ID_TPC7_ECC = 57,
+ GOYA_ASYNC_EVENT_ID_MME_ECC = 60,
+ GOYA_ASYNC_EVENT_ID_MME_ECC_EXT = 61,
+ GOYA_ASYNC_EVENT_ID_MMU_ECC = 63,
+ GOYA_ASYNC_EVENT_ID_DMA_MACRO = 64,
+ GOYA_ASYNC_EVENT_ID_DMA_ECC = 66,
+ GOYA_ASYNC_EVENT_ID_CPU_IF_ECC = 75,
+ GOYA_ASYNC_EVENT_ID_PSOC_MEM = 78,
+ GOYA_ASYNC_EVENT_ID_PSOC_CORESIGHT = 79,
+ GOYA_ASYNC_EVENT_ID_SRAM0 = 81,
+ GOYA_ASYNC_EVENT_ID_SRAM1 = 82,
+ GOYA_ASYNC_EVENT_ID_SRAM2 = 83,
+ GOYA_ASYNC_EVENT_ID_SRAM3 = 84,
+ GOYA_ASYNC_EVENT_ID_SRAM4 = 85,
+ GOYA_ASYNC_EVENT_ID_SRAM5 = 86,
+ GOYA_ASYNC_EVENT_ID_SRAM6 = 87,
+ GOYA_ASYNC_EVENT_ID_SRAM7 = 88,
+ GOYA_ASYNC_EVENT_ID_SRAM8 = 89,
+ GOYA_ASYNC_EVENT_ID_SRAM9 = 90,
+ GOYA_ASYNC_EVENT_ID_SRAM10 = 91,
+ GOYA_ASYNC_EVENT_ID_SRAM11 = 92,
+ GOYA_ASYNC_EVENT_ID_SRAM12 = 93,
+ GOYA_ASYNC_EVENT_ID_SRAM13 = 94,
+ GOYA_ASYNC_EVENT_ID_SRAM14 = 95,
+ GOYA_ASYNC_EVENT_ID_SRAM15 = 96,
+ GOYA_ASYNC_EVENT_ID_SRAM16 = 97,
+ GOYA_ASYNC_EVENT_ID_SRAM17 = 98,
+ GOYA_ASYNC_EVENT_ID_SRAM18 = 99,
+ GOYA_ASYNC_EVENT_ID_SRAM19 = 100,
+ GOYA_ASYNC_EVENT_ID_SRAM20 = 101,
+ GOYA_ASYNC_EVENT_ID_SRAM21 = 102,
+ GOYA_ASYNC_EVENT_ID_SRAM22 = 103,
+ GOYA_ASYNC_EVENT_ID_SRAM23 = 104,
+ GOYA_ASYNC_EVENT_ID_SRAM24 = 105,
+ GOYA_ASYNC_EVENT_ID_SRAM25 = 106,
+ GOYA_ASYNC_EVENT_ID_SRAM26 = 107,
+ GOYA_ASYNC_EVENT_ID_SRAM27 = 108,
+ GOYA_ASYNC_EVENT_ID_SRAM28 = 109,
+ GOYA_ASYNC_EVENT_ID_SRAM29 = 110,
+ GOYA_ASYNC_EVENT_ID_GIC500 = 112,
+ GOYA_ASYNC_EVENT_ID_PCIE_DEC = 115,
+ GOYA_ASYNC_EVENT_ID_TPC0_DEC = 117,
+ GOYA_ASYNC_EVENT_ID_TPC1_DEC = 120,
+ GOYA_ASYNC_EVENT_ID_TPC2_DEC = 123,
+ GOYA_ASYNC_EVENT_ID_TPC3_DEC = 126,
+ GOYA_ASYNC_EVENT_ID_TPC4_DEC = 129,
+ GOYA_ASYNC_EVENT_ID_TPC5_DEC = 132,
+ GOYA_ASYNC_EVENT_ID_TPC6_DEC = 135,
+ GOYA_ASYNC_EVENT_ID_TPC7_DEC = 138,
+ GOYA_ASYNC_EVENT_ID_AXI_ECC = 139,
+ GOYA_ASYNC_EVENT_ID_L2_RAM_ECC = 140,
+ GOYA_ASYNC_EVENT_ID_MME_WACS = 141,
+ GOYA_ASYNC_EVENT_ID_MME_WACSD = 142,
+ GOYA_ASYNC_EVENT_ID_PLL0 = 143,
+ GOYA_ASYNC_EVENT_ID_PLL1 = 144,
+ GOYA_ASYNC_EVENT_ID_PLL3 = 146,
+ GOYA_ASYNC_EVENT_ID_PLL4 = 147,
+ GOYA_ASYNC_EVENT_ID_PLL5 = 148,
+ GOYA_ASYNC_EVENT_ID_PLL6 = 149,
+ GOYA_ASYNC_EVENT_ID_CPU_AXI_SPLITTER = 155,
+ GOYA_ASYNC_EVENT_ID_PSOC_AXI_DEC = 159,
+ GOYA_ASYNC_EVENT_ID_PSOC = 160,
+ GOYA_ASYNC_EVENT_ID_PCIE_FLR = 171,
+ GOYA_ASYNC_EVENT_ID_PCIE_HOT_RESET = 172,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID0_ENG0 = 174,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID0_ENG1 = 175,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID0_ENG2 = 176,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID0_ENG3 = 177,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID1_ENG0 = 178,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID1_ENG1 = 179,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID1_ENG2 = 180,
+ GOYA_ASYNC_EVENT_ID_PCIE_QID1_ENG3 = 181,
+ GOYA_ASYNC_EVENT_ID_PCIE_APB = 182,
+ GOYA_ASYNC_EVENT_ID_PCIE_QDB = 183,
+ GOYA_ASYNC_EVENT_ID_PCIE_BM_D_P_WR = 184,
+ GOYA_ASYNC_EVENT_ID_PCIE_BM_D_RD = 185,
+ GOYA_ASYNC_EVENT_ID_PCIE_BM_U_P_WR = 186,
+ GOYA_ASYNC_EVENT_ID_PCIE_BM_U_RD = 187,
+ GOYA_ASYNC_EVENT_ID_TPC0_BMON_SPMU = 190,
+ GOYA_ASYNC_EVENT_ID_TPC0_KRN_ERR = 191,
+ GOYA_ASYNC_EVENT_ID_TPC1_BMON_SPMU = 200,
+ GOYA_ASYNC_EVENT_ID_TPC1_KRN_ERR = 201,
+ GOYA_ASYNC_EVENT_ID_TPC2_BMON_SPMU = 210,
+ GOYA_ASYNC_EVENT_ID_TPC2_KRN_ERR = 211,
+ GOYA_ASYNC_EVENT_ID_TPC3_BMON_SPMU = 220,
+ GOYA_ASYNC_EVENT_ID_TPC3_KRN_ERR = 221,
+ GOYA_ASYNC_EVENT_ID_TPC4_BMON_SPMU = 230,
+ GOYA_ASYNC_EVENT_ID_TPC4_KRN_ERR = 231,
+ GOYA_ASYNC_EVENT_ID_TPC5_BMON_SPMU = 240,
+ GOYA_ASYNC_EVENT_ID_TPC5_KRN_ERR = 241,
+ GOYA_ASYNC_EVENT_ID_TPC6_BMON_SPMU = 250,
+ GOYA_ASYNC_EVENT_ID_TPC6_KRN_ERR = 251,
+ GOYA_ASYNC_EVENT_ID_TPC7_BMON_SPMU = 260,
+ GOYA_ASYNC_EVENT_ID_TPC7_KRN_ERR = 261,
+ GOYA_ASYNC_EVENT_ID_MMU_SBA_SPMU0 = 270,
+ GOYA_ASYNC_EVENT_ID_MMU_SBA_SPMU1 = 271,
+ GOYA_ASYNC_EVENT_ID_MME_WACS_UP = 272,
+ GOYA_ASYNC_EVENT_ID_MME_WACS_DOWN = 273,
+ GOYA_ASYNC_EVENT_ID_MMU_PAGE_FAULT = 280,
+ GOYA_ASYNC_EVENT_ID_MMU_WR_PERM = 281,
+ GOYA_ASYNC_EVENT_ID_MMU_DBG_BM = 282,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH0 = 290,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH1 = 291,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH2 = 292,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH3 = 293,
+ GOYA_ASYNC_EVENT_ID_DMA_BM_CH4 = 294,
+ GOYA_ASYNC_EVENT_ID_DDR0_PHY_DFI = 300,
+ GOYA_ASYNC_EVENT_ID_DDR0_ECC_SCRUB = 301,
+ GOYA_ASYNC_EVENT_ID_DDR0_DB_ECC = 302,
+ GOYA_ASYNC_EVENT_ID_DDR0_SB_ECC = 303,
+ GOYA_ASYNC_EVENT_ID_DDR0_SB_ECC_MC = 304,
+ GOYA_ASYNC_EVENT_ID_DDR0_AXI_RD = 305,
+ GOYA_ASYNC_EVENT_ID_DDR0_AXI_WR = 306,
+ GOYA_ASYNC_EVENT_ID_DDR1_PHY_DFI = 310,
+ GOYA_ASYNC_EVENT_ID_DDR1_ECC_SCRUB = 311,
+ GOYA_ASYNC_EVENT_ID_DDR1_DB_ECC = 312,
+ GOYA_ASYNC_EVENT_ID_DDR1_SB_ECC = 313,
+ GOYA_ASYNC_EVENT_ID_DDR1_SB_ECC_MC = 314,
+ GOYA_ASYNC_EVENT_ID_DDR1_AXI_RD = 315,
+ GOYA_ASYNC_EVENT_ID_DDR1_AXI_WR = 316,
+ GOYA_ASYNC_EVENT_ID_CPU_BMON = 320,
+ GOYA_ASYNC_EVENT_ID_TS_EAST = 322,
+ GOYA_ASYNC_EVENT_ID_TS_WEST = 323,
+ GOYA_ASYNC_EVENT_ID_TS_NORTH = 324,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_U16_0 = 330,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_U16_1 = 331,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_U16_2 = 332,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET = 356,
+ GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT = 361,
+ GOYA_ASYNC_EVENT_ID_TPC0_CMDQ = 430,
+ GOYA_ASYNC_EVENT_ID_TPC1_CMDQ = 431,
+ GOYA_ASYNC_EVENT_ID_TPC2_CMDQ = 432,
+ GOYA_ASYNC_EVENT_ID_TPC3_CMDQ = 433,
+ GOYA_ASYNC_EVENT_ID_TPC4_CMDQ = 434,
+ GOYA_ASYNC_EVENT_ID_TPC5_CMDQ = 435,
+ GOYA_ASYNC_EVENT_ID_TPC6_CMDQ = 436,
+ GOYA_ASYNC_EVENT_ID_TPC7_CMDQ = 437,
+ GOYA_ASYNC_EVENT_ID_TPC0_QM = 438,
+ GOYA_ASYNC_EVENT_ID_TPC1_QM = 439,
+ GOYA_ASYNC_EVENT_ID_TPC2_QM = 440,
+ GOYA_ASYNC_EVENT_ID_TPC3_QM = 441,
+ GOYA_ASYNC_EVENT_ID_TPC4_QM = 442,
+ GOYA_ASYNC_EVENT_ID_TPC5_QM = 443,
+ GOYA_ASYNC_EVENT_ID_TPC6_QM = 444,
+ GOYA_ASYNC_EVENT_ID_TPC7_QM = 445,
+ GOYA_ASYNC_EVENT_ID_MME_QM = 447,
+ GOYA_ASYNC_EVENT_ID_MME_CMDQ = 448,
+ GOYA_ASYNC_EVENT_ID_DMA0_QM = 449,
+ GOYA_ASYNC_EVENT_ID_DMA1_QM = 450,
+ GOYA_ASYNC_EVENT_ID_DMA2_QM = 451,
+ GOYA_ASYNC_EVENT_ID_DMA3_QM = 452,
+ GOYA_ASYNC_EVENT_ID_DMA4_QM = 453,
+ GOYA_ASYNC_EVENT_ID_DMA_ON_HBW = 454,
+ GOYA_ASYNC_EVENT_ID_DMA0_CH = 455,
+ GOYA_ASYNC_EVENT_ID_DMA1_CH = 456,
+ GOYA_ASYNC_EVENT_ID_DMA2_CH = 457,
+ GOYA_ASYNC_EVENT_ID_DMA3_CH = 458,
+ GOYA_ASYNC_EVENT_ID_DMA4_CH = 459,
+ GOYA_ASYNC_EVENT_ID_PI_UPDATE = 484,
+ GOYA_ASYNC_EVENT_ID_HALT_MACHINE = 485,
+ GOYA_ASYNC_EVENT_ID_INTS_REGISTER = 486,
+ GOYA_ASYNC_EVENT_ID_SOFT_RESET = 487,
+ GOYA_ASYNC_EVENT_ID_LAST_VALID_ID = 1023,
+ GOYA_ASYNC_EVENT_ID_SIZE
+};
+
+#endif /* __GOYA_ASYNC_EVENTS_H_ */
diff --git a/drivers/misc/habanalabs/include/goya/goya_fw_if.h b/drivers/misc/habanalabs/include/goya/goya_fw_if.h
new file mode 100644
index 000000000000..a9920cb4a07b
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/goya_fw_if.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef GOYA_FW_IF_H
+#define GOYA_FW_IF_H
+
+#define CPU_BOOT_ADDR 0x7FF8040000ull
+
+#define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */
+#define LINUX_FW_OFFSET 0x800000 /* 8MB in DDR */
+
+enum goya_pll_index {
+ CPU_PLL = 0,
+ IC_PLL,
+ MC_PLL,
+ MME_PLL,
+ PCI_PLL,
+ EMMC_PLL,
+ TPC_PLL
+};
+
+#define GOYA_PLL_FREQ_LOW 50000000 /* 50 MHz */
+
+#endif /* GOYA_FW_IF_H */
diff --git a/drivers/misc/habanalabs/include/goya/goya_packets.h b/drivers/misc/habanalabs/include/goya/goya_packets.h
new file mode 100644
index 000000000000..a14407b975e4
--- /dev/null
+++ b/drivers/misc/habanalabs/include/goya/goya_packets.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2017-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef GOYA_PACKETS_H
+#define GOYA_PACKETS_H
+
+#include <linux/types.h>
+
+#define PACKET_HEADER_PACKET_ID_SHIFT 56
+#define PACKET_HEADER_PACKET_ID_MASK 0x1F00000000000000ull
+
+enum packet_id {
+ PACKET_WREG_32 = 0x1,
+ PACKET_WREG_BULK = 0x2,
+ PACKET_MSG_LONG = 0x3,
+ PACKET_MSG_SHORT = 0x4,
+ PACKET_CP_DMA = 0x5,
+ PACKET_MSG_PROT = 0x7,
+ PACKET_FENCE = 0x8,
+ PACKET_LIN_DMA = 0x9,
+ PACKET_NOP = 0xA,
+ PACKET_STOP = 0xB,
+ MAX_PACKET_ID = (PACKET_HEADER_PACKET_ID_MASK >>
+ PACKET_HEADER_PACKET_ID_SHIFT) + 1
+};
+
+enum goya_dma_direction {
+ DMA_HOST_TO_DRAM,
+ DMA_HOST_TO_SRAM,
+ DMA_DRAM_TO_SRAM,
+ DMA_SRAM_TO_DRAM,
+ DMA_SRAM_TO_HOST,
+ DMA_DRAM_TO_HOST,
+ DMA_DRAM_TO_DRAM,
+ DMA_SRAM_TO_SRAM,
+ DMA_ENUM_MAX
+};
+
+#define GOYA_PKT_CTL_OPCODE_SHIFT 24
+#define GOYA_PKT_CTL_OPCODE_MASK 0x1F000000
+
+#define GOYA_PKT_CTL_EB_SHIFT 29
+#define GOYA_PKT_CTL_EB_MASK 0x20000000
+
+#define GOYA_PKT_CTL_RB_SHIFT 30
+#define GOYA_PKT_CTL_RB_MASK 0x40000000
+
+#define GOYA_PKT_CTL_MB_SHIFT 31
+#define GOYA_PKT_CTL_MB_MASK 0x80000000
+
+struct packet_nop {
+ __le32 reserved;
+ __le32 ctl;
+};
+
+struct packet_stop {
+ __le32 reserved;
+ __le32 ctl;
+};
+
+#define GOYA_PKT_WREG32_CTL_REG_OFFSET_SHIFT 0
+#define GOYA_PKT_WREG32_CTL_REG_OFFSET_MASK 0x0000FFFF
+
+struct packet_wreg32 {
+ __le32 value;
+ __le32 ctl;
+};
+
+struct packet_wreg_bulk {
+ __le32 size64;
+ __le32 ctl;
+ __le64 values[0]; /* data starts here */
+};
+
+struct packet_msg_long {
+ __le32 value;
+ __le32 ctl;
+ __le64 addr;
+};
+
+struct packet_msg_short {
+ __le32 value;
+ __le32 ctl;
+};
+
+struct packet_msg_prot {
+ __le32 value;
+ __le32 ctl;
+ __le64 addr;
+};
+
+struct packet_fence {
+ __le32 cfg;
+ __le32 ctl;
+};
+
+#define GOYA_PKT_LIN_DMA_CTL_WO_SHIFT 0
+#define GOYA_PKT_LIN_DMA_CTL_WO_MASK 0x00000001
+
+#define GOYA_PKT_LIN_DMA_CTL_RDCOMP_SHIFT 1
+#define GOYA_PKT_LIN_DMA_CTL_RDCOMP_MASK 0x00000002
+
+#define GOYA_PKT_LIN_DMA_CTL_WRCOMP_SHIFT 2
+#define GOYA_PKT_LIN_DMA_CTL_WRCOMP_MASK 0x00000004
+
+#define GOYA_PKT_LIN_DMA_CTL_MEMSET_SHIFT 6
+#define GOYA_PKT_LIN_DMA_CTL_MEMSET_MASK 0x00000040
+
+#define GOYA_PKT_LIN_DMA_CTL_DMA_DIR_SHIFT 20
+#define GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK 0x00700000
+
+struct packet_lin_dma {
+ __le32 tsize;
+ __le32 ctl;
+ __le64 src_addr;
+ __le64 dst_addr;
+};
+
+struct packet_cp_dma {
+ __le32 tsize;
+ __le32 ctl;
+ __le64 src_addr;
+};
+
+#endif /* GOYA_PACKETS_H */
diff --git a/drivers/misc/habanalabs/include/hl_boot_if.h b/drivers/misc/habanalabs/include/hl_boot_if.h
new file mode 100644
index 000000000000..7475732b9996
--- /dev/null
+++ b/drivers/misc/habanalabs/include/hl_boot_if.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef HL_BOOT_IF_H
+#define HL_BOOT_IF_H
+
+enum cpu_boot_status {
+ CPU_BOOT_STATUS_NA = 0, /* Default value after reset of chip */
+ CPU_BOOT_STATUS_IN_WFE,
+ CPU_BOOT_STATUS_DRAM_RDY,
+ CPU_BOOT_STATUS_SRAM_AVAIL,
+ CPU_BOOT_STATUS_IN_BTL, /* BTL is H/W FSM */
+ CPU_BOOT_STATUS_IN_PREBOOT,
+ CPU_BOOT_STATUS_IN_SPL,
+ CPU_BOOT_STATUS_IN_UBOOT,
+ CPU_BOOT_STATUS_DRAM_INIT_FAIL,
+ CPU_BOOT_STATUS_FIT_CORRUPTED
+};
+
+enum kmd_msg {
+ KMD_MSG_NA = 0,
+ KMD_MSG_GOTO_WFE,
+ KMD_MSG_FIT_RDY
+};
+
+#endif /* HL_BOOT_IF_H */
diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h b/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h
new file mode 100644
index 000000000000..b680052ee3f0
--- /dev/null
+++ b/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_general.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef INCLUDE_MMU_GENERAL_H_
+#define INCLUDE_MMU_GENERAL_H_
+
+#define PAGE_SHIFT_4KB 12
+#define PAGE_SHIFT_2MB 21
+#define PAGE_SIZE_2MB (_AC(1, UL) << PAGE_SHIFT_2MB)
+#define PAGE_SIZE_4KB (_AC(1, UL) << PAGE_SHIFT_4KB)
+#define PAGE_MASK_2MB (~(PAGE_SIZE_2MB - 1))
+
+#define PAGE_PRESENT_MASK 0x0000000000001
+#define SWAP_OUT_MASK 0x0000000000004
+#define LAST_MASK 0x0000000000800
+#define PHYS_ADDR_MASK 0x3FFFFFFFFF000ull
+#define HOP0_MASK 0x3000000000000ull
+#define HOP1_MASK 0x0FF8000000000ull
+#define HOP2_MASK 0x0007FC0000000ull
+#define HOP3_MASK 0x000003FE00000
+#define HOP4_MASK 0x00000001FF000
+#define OFFSET_MASK 0x0000000000FFF
+
+#define HOP0_SHIFT 48
+#define HOP1_SHIFT 39
+#define HOP2_SHIFT 30
+#define HOP3_SHIFT 21
+#define HOP4_SHIFT 12
+
+#define PTE_PHYS_ADDR_SHIFT 12
+#define PTE_PHYS_ADDR_MASK ~0xFFF
+
+#define HL_PTE_SIZE sizeof(u64)
+#define HOP_TABLE_SIZE PAGE_SIZE_4KB
+#define PTE_ENTRIES_IN_HOP (HOP_TABLE_SIZE / HL_PTE_SIZE)
+#define HOP0_TABLES_TOTAL_SIZE (HOP_TABLE_SIZE * MAX_ASID)
+
+#define MMU_HOP0_PA43_12_SHIFT 12
+#define MMU_HOP0_PA49_44_SHIFT (12 + 32)
+
+#define MMU_CONFIG_TIMEOUT_USEC 2000 /* 2 ms */
+
+#endif /* INCLUDE_MMU_GENERAL_H_ */
diff --git a/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h b/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h
new file mode 100644
index 000000000000..8539dd041f2c
--- /dev/null
+++ b/drivers/misc/habanalabs/include/hw_ip/mmu/mmu_v1_0.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef INCLUDE_MMU_V1_0_H_
+#define INCLUDE_MMU_V1_0_H_
+
+#define MMU_HOP0_PA43_12 0x490004
+#define MMU_HOP0_PA49_44 0x490008
+#define MMU_ASID_BUSY 0x490000
+
+#endif /* INCLUDE_MMU_V1_0_H_ */
diff --git a/drivers/misc/habanalabs/include/qman_if.h b/drivers/misc/habanalabs/include/qman_if.h
new file mode 100644
index 000000000000..bf59bbe27fdc
--- /dev/null
+++ b/drivers/misc/habanalabs/include/qman_if.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#ifndef QMAN_IF_H
+#define QMAN_IF_H
+
+#include <linux/types.h>
+
+/*
+ * PRIMARY QUEUE
+ */
+
+struct hl_bd {
+ __le64 ptr;
+ __le32 len;
+ __le32 ctl;
+};
+
+#define HL_BD_SIZE sizeof(struct hl_bd)
+
+/*
+ * BD_CTL_REPEAT_VALID tells the CP whether the repeat field in the BD CTL is
+ * valid. 1 means the repeat field is valid, 0 means not-valid,
+ * i.e. repeat == 1
+ */
+#define BD_CTL_REPEAT_VALID_SHIFT 24
+#define BD_CTL_REPEAT_VALID_MASK 0x01000000
+
+#define BD_CTL_SHADOW_INDEX_SHIFT 0
+#define BD_CTL_SHADOW_INDEX_MASK 0x00000FFF
+
+/*
+ * COMPLETION QUEUE
+ */
+
+struct hl_cq_entry {
+ __le32 data;
+};
+
+#define HL_CQ_ENTRY_SIZE sizeof(struct hl_cq_entry)
+
+#define CQ_ENTRY_READY_SHIFT 31
+#define CQ_ENTRY_READY_MASK 0x80000000
+
+#define CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT 30
+#define CQ_ENTRY_SHADOW_INDEX_VALID_MASK 0x40000000
+
+#define CQ_ENTRY_SHADOW_INDEX_SHIFT BD_CTL_SHADOW_INDEX_SHIFT
+#define CQ_ENTRY_SHADOW_INDEX_MASK BD_CTL_SHADOW_INDEX_MASK
+
+
+#endif /* QMAN_IF_H */
diff --git a/drivers/misc/habanalabs/irq.c b/drivers/misc/habanalabs/irq.c
new file mode 100644
index 000000000000..e69a09c10e3f
--- /dev/null
+++ b/drivers/misc/habanalabs/irq.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/slab.h>
+
+/**
+ * This structure is used to schedule work of EQ entry and armcp_reset event
+ *
+ * @eq_work - workqueue object to run when EQ entry is received
+ * @hdev - pointer to device structure
+ * @eq_entry - copy of the EQ entry
+ */
+struct hl_eqe_work {
+ struct work_struct eq_work;
+ struct hl_device *hdev;
+ struct hl_eq_entry eq_entry;
+};
+
+/*
+ * hl_cq_inc_ptr - increment ci or pi of cq
+ *
+ * @ptr: the current ci or pi value of the completion queue
+ *
+ * Increment ptr by 1. If it reaches the number of completion queue
+ * entries, set it to 0
+ */
+inline u32 hl_cq_inc_ptr(u32 ptr)
+{
+ ptr++;
+ if (unlikely(ptr == HL_CQ_LENGTH))
+ ptr = 0;
+ return ptr;
+}
+
+/*
+ * hl_eq_inc_ptr - increment ci of eq
+ *
+ * @ptr: the current ci value of the event queue
+ *
+ * Increment ptr by 1. If it reaches the number of event queue
+ * entries, set it to 0
+ */
+inline u32 hl_eq_inc_ptr(u32 ptr)
+{
+ ptr++;
+ if (unlikely(ptr == HL_EQ_LENGTH))
+ ptr = 0;
+ return ptr;
+}
+
+static void irq_handle_eqe(struct work_struct *work)
+{
+ struct hl_eqe_work *eqe_work = container_of(work, struct hl_eqe_work,
+ eq_work);
+ struct hl_device *hdev = eqe_work->hdev;
+
+ hdev->asic_funcs->handle_eqe(hdev, &eqe_work->eq_entry);
+
+ kfree(eqe_work);
+}
+
+/*
+ * hl_irq_handler_cq - irq handler for completion queue
+ *
+ * @irq: irq number
+ * @arg: pointer to completion queue structure
+ *
+ */
+irqreturn_t hl_irq_handler_cq(int irq, void *arg)
+{
+ struct hl_cq *cq = arg;
+ struct hl_device *hdev = cq->hdev;
+ struct hl_hw_queue *queue;
+ struct hl_cs_job *job;
+ bool shadow_index_valid;
+ u16 shadow_index;
+ u32 *cq_entry;
+ u32 *cq_base;
+
+ if (hdev->disabled) {
+ dev_dbg(hdev->dev,
+ "Device disabled but received IRQ %d for CQ %d\n",
+ irq, cq->hw_queue_id);
+ return IRQ_HANDLED;
+ }
+
+ cq_base = (u32 *) (uintptr_t) cq->kernel_address;
+
+ while (1) {
+ bool entry_ready = ((cq_base[cq->ci] & CQ_ENTRY_READY_MASK)
+ >> CQ_ENTRY_READY_SHIFT);
+
+ if (!entry_ready)
+ break;
+
+ cq_entry = (u32 *) &cq_base[cq->ci];
+
+ /*
+ * Make sure we read CQ entry contents after we've
+ * checked the ownership bit.
+ */
+ dma_rmb();
+
+ shadow_index_valid =
+ ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
+ >> CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT);
+
+ shadow_index = (u16)
+ ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_MASK)
+ >> CQ_ENTRY_SHADOW_INDEX_SHIFT);
+
+ queue = &hdev->kernel_queues[cq->hw_queue_id];
+
+ if ((shadow_index_valid) && (!hdev->disabled)) {
+ job = queue->shadow_queue[hl_pi_2_offset(shadow_index)];
+ queue_work(hdev->cq_wq, &job->finish_work);
+ }
+
+ /*
+ * Update ci of the context's queue. There is no
+ * need to protect it with spinlock because this update is
+ * done only inside IRQ and there is a different IRQ per
+ * queue
+ */
+ queue->ci = hl_queue_inc_ptr(queue->ci);
+
+ /* Clear CQ entry ready bit */
+ cq_base[cq->ci] &= ~CQ_ENTRY_READY_MASK;
+
+ cq->ci = hl_cq_inc_ptr(cq->ci);
+
+ /* Increment free slots */
+ atomic_inc(&cq->free_slots_cnt);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * hl_irq_handler_eq - irq handler for event queue
+ *
+ * @irq: irq number
+ * @arg: pointer to event queue structure
+ *
+ */
+irqreturn_t hl_irq_handler_eq(int irq, void *arg)
+{
+ struct hl_eq *eq = arg;
+ struct hl_device *hdev = eq->hdev;
+ struct hl_eq_entry *eq_entry;
+ struct hl_eq_entry *eq_base;
+ struct hl_eqe_work *handle_eqe_work;
+
+ eq_base = (struct hl_eq_entry *) (uintptr_t) eq->kernel_address;
+
+ while (1) {
+ bool entry_ready =
+ ((__le32_to_cpu(eq_base[eq->ci].hdr.ctl) &
+ EQ_CTL_READY_MASK) >> EQ_CTL_READY_SHIFT);
+
+ if (!entry_ready)
+ break;
+
+ eq_entry = &eq_base[eq->ci];
+
+ /*
+ * Make sure we read EQ entry contents after we've
+ * checked the ownership bit.
+ */
+ dma_rmb();
+
+ if (hdev->disabled) {
+ dev_warn(hdev->dev,
+ "Device disabled but received IRQ %d for EQ\n",
+ irq);
+ goto skip_irq;
+ }
+
+ handle_eqe_work = kmalloc(sizeof(*handle_eqe_work), GFP_ATOMIC);
+ if (handle_eqe_work) {
+ INIT_WORK(&handle_eqe_work->eq_work, irq_handle_eqe);
+ handle_eqe_work->hdev = hdev;
+
+ memcpy(&handle_eqe_work->eq_entry, eq_entry,
+ sizeof(*eq_entry));
+
+ queue_work(hdev->eq_wq, &handle_eqe_work->eq_work);
+ }
+skip_irq:
+ /* Clear EQ entry ready bit */
+ eq_entry->hdr.ctl =
+ __cpu_to_le32(__le32_to_cpu(eq_entry->hdr.ctl) &
+ ~EQ_CTL_READY_MASK);
+
+ eq->ci = hl_eq_inc_ptr(eq->ci);
+
+ hdev->asic_funcs->update_eq_ci(hdev, eq->ci);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * hl_cq_init - main initialization function for an cq object
+ *
+ * @hdev: pointer to device structure
+ * @q: pointer to cq structure
+ * @hw_queue_id: The H/W queue ID this completion queue belongs to
+ *
+ * Allocate dma-able memory for the completion queue and initialize fields
+ * Returns 0 on success
+ */
+int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id)
+{
+ void *p;
+
+ BUILD_BUG_ON(HL_CQ_SIZE_IN_BYTES > HL_PAGE_SIZE);
+
+ p = hdev->asic_funcs->dma_alloc_coherent(hdev, HL_CQ_SIZE_IN_BYTES,
+ &q->bus_address, GFP_KERNEL | __GFP_ZERO);
+ if (!p)
+ return -ENOMEM;
+
+ q->hdev = hdev;
+ q->kernel_address = (u64) (uintptr_t) p;
+ q->hw_queue_id = hw_queue_id;
+ q->ci = 0;
+ q->pi = 0;
+
+ atomic_set(&q->free_slots_cnt, HL_CQ_LENGTH);
+
+ return 0;
+}
+
+/*
+ * hl_cq_fini - destroy completion queue
+ *
+ * @hdev: pointer to device structure
+ * @q: pointer to cq structure
+ *
+ * Free the completion queue memory
+ */
+void hl_cq_fini(struct hl_device *hdev, struct hl_cq *q)
+{
+ hdev->asic_funcs->dma_free_coherent(hdev, HL_CQ_SIZE_IN_BYTES,
+ (void *) (uintptr_t) q->kernel_address, q->bus_address);
+}
+
+void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q)
+{
+ q->ci = 0;
+ q->pi = 0;
+
+ atomic_set(&q->free_slots_cnt, HL_CQ_LENGTH);
+
+ /*
+ * It's not enough to just reset the PI/CI because the H/W may have
+ * written valid completion entries before it was halted and therefore
+ * we need to clean the actual queues so we won't process old entries
+ * when the device is operational again
+ */
+
+ memset((void *) (uintptr_t) q->kernel_address, 0, HL_CQ_SIZE_IN_BYTES);
+}
+
+/*
+ * hl_eq_init - main initialization function for an event queue object
+ *
+ * @hdev: pointer to device structure
+ * @q: pointer to eq structure
+ *
+ * Allocate dma-able memory for the event queue and initialize fields
+ * Returns 0 on success
+ */
+int hl_eq_init(struct hl_device *hdev, struct hl_eq *q)
+{
+ void *p;
+
+ BUILD_BUG_ON(HL_EQ_SIZE_IN_BYTES > HL_PAGE_SIZE);
+
+ p = hdev->asic_funcs->dma_alloc_coherent(hdev, HL_EQ_SIZE_IN_BYTES,
+ &q->bus_address, GFP_KERNEL | __GFP_ZERO);
+ if (!p)
+ return -ENOMEM;
+
+ q->hdev = hdev;
+ q->kernel_address = (u64) (uintptr_t) p;
+ q->ci = 0;
+
+ return 0;
+}
+
+/*
+ * hl_eq_fini - destroy event queue
+ *
+ * @hdev: pointer to device structure
+ * @q: pointer to eq structure
+ *
+ * Free the event queue memory
+ */
+void hl_eq_fini(struct hl_device *hdev, struct hl_eq *q)
+{
+ flush_workqueue(hdev->eq_wq);
+
+ hdev->asic_funcs->dma_free_coherent(hdev, HL_EQ_SIZE_IN_BYTES,
+ (void *) (uintptr_t) q->kernel_address, q->bus_address);
+}
+
+void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q)
+{
+ q->ci = 0;
+
+ /*
+ * It's not enough to just reset the PI/CI because the H/W may have
+ * written valid completion entries before it was halted and therefore
+ * we need to clean the actual queues so we won't process old entries
+ * when the device is operational again
+ */
+
+ memset((void *) (uintptr_t) q->kernel_address, 0, HL_EQ_SIZE_IN_BYTES);
+}
diff --git a/drivers/misc/habanalabs/memory.c b/drivers/misc/habanalabs/memory.c
new file mode 100644
index 000000000000..3a12fd1a5274
--- /dev/null
+++ b/drivers/misc/habanalabs/memory.c
@@ -0,0 +1,1723 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include <uapi/misc/habanalabs.h>
+#include "habanalabs.h"
+#include "include/hw_ip/mmu/mmu_general.h"
+
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+#define PGS_IN_2MB_PAGE (PAGE_SIZE_2MB >> PAGE_SHIFT)
+#define HL_MMU_DEBUG 0
+
+/*
+ * The va ranges in context object contain a list with the available chunks of
+ * device virtual memory.
+ * There is one range for host allocations and one for DRAM allocations.
+ *
+ * On initialization each range contains one chunk of all of its available
+ * virtual range which is a half of the total device virtual range.
+ *
+ * On each mapping of physical pages, a suitable virtual range chunk (with a
+ * minimum size) is selected from the list. If the chunk size equals the
+ * requested size, the chunk is returned. Otherwise, the chunk is split into
+ * two chunks - one to return as result and a remainder to stay in the list.
+ *
+ * On each Unmapping of a virtual address, the relevant virtual chunk is
+ * returned to the list. The chunk is added to the list and if its edges match
+ * the edges of the adjacent chunks (means a contiguous chunk can be created),
+ * the chunks are merged.
+ *
+ * On finish, the list is checked to have only one chunk of all the relevant
+ * virtual range (which is a half of the device total virtual range).
+ * If not (means not all mappings were unmapped), a warning is printed.
+ */
+
+/*
+ * alloc_device_memory - allocate device memory
+ *
+ * @ctx : current context
+ * @args : host parameters containing the requested size
+ * @ret_handle : result handle
+ *
+ * This function does the following:
+ * - Allocate the requested size rounded up to 2MB pages
+ * - Return unique handle
+ */
+static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
+ u32 *ret_handle)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm *vm = &hdev->vm;
+ struct hl_vm_phys_pg_pack *phys_pg_pack;
+ u64 paddr = 0;
+ u32 total_size, num_pgs, num_curr_pgs, page_size, page_shift;
+ int handle, rc, i;
+ bool contiguous;
+
+ num_curr_pgs = 0;
+ page_size = hdev->asic_prop.dram_page_size;
+ page_shift = __ffs(page_size);
+ num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift;
+ total_size = num_pgs << page_shift;
+
+ contiguous = args->flags & HL_MEM_CONTIGUOUS;
+
+ if (contiguous) {
+ paddr = (u64) gen_pool_alloc(vm->dram_pg_pool, total_size);
+ if (!paddr) {
+ dev_err(hdev->dev,
+ "failed to allocate %u huge contiguous pages\n",
+ num_pgs);
+ return -ENOMEM;
+ }
+ }
+
+ phys_pg_pack = kzalloc(sizeof(*phys_pg_pack), GFP_KERNEL);
+ if (!phys_pg_pack) {
+ rc = -ENOMEM;
+ goto pages_pack_err;
+ }
+
+ phys_pg_pack->vm_type = VM_TYPE_PHYS_PACK;
+ phys_pg_pack->asid = ctx->asid;
+ phys_pg_pack->npages = num_pgs;
+ phys_pg_pack->page_size = page_size;
+ phys_pg_pack->total_size = total_size;
+ phys_pg_pack->flags = args->flags;
+ phys_pg_pack->contiguous = contiguous;
+
+ phys_pg_pack->pages = kcalloc(num_pgs, sizeof(u64), GFP_KERNEL);
+ if (!phys_pg_pack->pages) {
+ rc = -ENOMEM;
+ goto pages_arr_err;
+ }
+
+ if (phys_pg_pack->contiguous) {
+ for (i = 0 ; i < num_pgs ; i++)
+ phys_pg_pack->pages[i] = paddr + i * page_size;
+ } else {
+ for (i = 0 ; i < num_pgs ; i++) {
+ phys_pg_pack->pages[i] = (u64) gen_pool_alloc(
+ vm->dram_pg_pool,
+ page_size);
+ if (!phys_pg_pack->pages[i]) {
+ dev_err(hdev->dev,
+ "ioctl failed to allocate page\n");
+ rc = -ENOMEM;
+ goto page_err;
+ }
+
+ num_curr_pgs++;
+ }
+ }
+
+ spin_lock(&vm->idr_lock);
+ handle = idr_alloc(&vm->phys_pg_pack_handles, phys_pg_pack, 1, 0,
+ GFP_ATOMIC);
+ spin_unlock(&vm->idr_lock);
+
+ if (handle < 0) {
+ dev_err(hdev->dev, "Failed to get handle for page\n");
+ rc = -EFAULT;
+ goto idr_err;
+ }
+
+ for (i = 0 ; i < num_pgs ; i++)
+ kref_get(&vm->dram_pg_pool_refcount);
+
+ phys_pg_pack->handle = handle;
+
+ atomic64_add(phys_pg_pack->total_size, &ctx->dram_phys_mem);
+ atomic64_add(phys_pg_pack->total_size, &hdev->dram_used_mem);
+
+ *ret_handle = handle;
+
+ return 0;
+
+idr_err:
+page_err:
+ if (!phys_pg_pack->contiguous)
+ for (i = 0 ; i < num_curr_pgs ; i++)
+ gen_pool_free(vm->dram_pg_pool, phys_pg_pack->pages[i],
+ page_size);
+
+ kfree(phys_pg_pack->pages);
+pages_arr_err:
+ kfree(phys_pg_pack);
+pages_pack_err:
+ if (contiguous)
+ gen_pool_free(vm->dram_pg_pool, paddr, total_size);
+
+ return rc;
+}
+
+/*
+ * get_userptr_from_host_va - initialize userptr structure from given host
+ * virtual address
+ *
+ * @hdev : habanalabs device structure
+ * @args : parameters containing the virtual address and size
+ * @p_userptr : pointer to result userptr structure
+ *
+ * This function does the following:
+ * - Allocate userptr structure
+ * - Pin the given host memory using the userptr structure
+ * - Perform DMA mapping to have the DMA addresses of the pages
+ */
+static int get_userptr_from_host_va(struct hl_device *hdev,
+ struct hl_mem_in *args, struct hl_userptr **p_userptr)
+{
+ struct hl_userptr *userptr;
+ int rc;
+
+ userptr = kzalloc(sizeof(*userptr), GFP_KERNEL);
+ if (!userptr) {
+ rc = -ENOMEM;
+ goto userptr_err;
+ }
+
+ rc = hl_pin_host_memory(hdev, args->map_host.host_virt_addr,
+ args->map_host.mem_size, userptr);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to pin host memory\n");
+ goto pin_err;
+ }
+
+ rc = hdev->asic_funcs->asic_dma_map_sg(hdev, userptr->sgt->sgl,
+ userptr->sgt->nents, DMA_BIDIRECTIONAL);
+ if (rc) {
+ dev_err(hdev->dev, "failed to map sgt with DMA region\n");
+ goto dma_map_err;
+ }
+
+ userptr->dma_mapped = true;
+ userptr->dir = DMA_BIDIRECTIONAL;
+ userptr->vm_type = VM_TYPE_USERPTR;
+
+ *p_userptr = userptr;
+
+ return 0;
+
+dma_map_err:
+ hl_unpin_host_memory(hdev, userptr);
+pin_err:
+ kfree(userptr);
+userptr_err:
+
+ return rc;
+}
+
+/*
+ * free_userptr - free userptr structure
+ *
+ * @hdev : habanalabs device structure
+ * @userptr : userptr to free
+ *
+ * This function does the following:
+ * - Unpins the physical pages
+ * - Frees the userptr structure
+ */
+static void free_userptr(struct hl_device *hdev, struct hl_userptr *userptr)
+{
+ hl_unpin_host_memory(hdev, userptr);
+ kfree(userptr);
+}
+
+/*
+ * dram_pg_pool_do_release - free DRAM pages pool
+ *
+ * @ref : pointer to reference object
+ *
+ * This function does the following:
+ * - Frees the idr structure of physical pages handles
+ * - Frees the generic pool of DRAM physical pages
+ */
+static void dram_pg_pool_do_release(struct kref *ref)
+{
+ struct hl_vm *vm = container_of(ref, struct hl_vm,
+ dram_pg_pool_refcount);
+
+ /*
+ * free the idr here as only here we know for sure that there are no
+ * allocated physical pages and hence there are no handles in use
+ */
+ idr_destroy(&vm->phys_pg_pack_handles);
+ gen_pool_destroy(vm->dram_pg_pool);
+}
+
+/*
+ * free_phys_pg_pack - free physical page pack
+ *
+ * @hdev : habanalabs device structure
+ * @phys_pg_pack : physical page pack to free
+ *
+ * This function does the following:
+ * - For DRAM memory only, iterate over the pack and free each physical block
+ * structure by returning it to the general pool
+ * - Free the hl_vm_phys_pg_pack structure
+ */
+static void free_phys_pg_pack(struct hl_device *hdev,
+ struct hl_vm_phys_pg_pack *phys_pg_pack)
+{
+ struct hl_vm *vm = &hdev->vm;
+ int i;
+
+ if (!phys_pg_pack->created_from_userptr) {
+ if (phys_pg_pack->contiguous) {
+ gen_pool_free(vm->dram_pg_pool, phys_pg_pack->pages[0],
+ phys_pg_pack->total_size);
+
+ for (i = 0; i < phys_pg_pack->npages ; i++)
+ kref_put(&vm->dram_pg_pool_refcount,
+ dram_pg_pool_do_release);
+ } else {
+ for (i = 0 ; i < phys_pg_pack->npages ; i++) {
+ gen_pool_free(vm->dram_pg_pool,
+ phys_pg_pack->pages[i],
+ phys_pg_pack->page_size);
+ kref_put(&vm->dram_pg_pool_refcount,
+ dram_pg_pool_do_release);
+ }
+ }
+ }
+
+ kfree(phys_pg_pack->pages);
+ kfree(phys_pg_pack);
+}
+
+/*
+ * free_device_memory - free device memory
+ *
+ * @ctx : current context
+ * @handle : handle of the memory chunk to free
+ *
+ * This function does the following:
+ * - Free the device memory related to the given handle
+ */
+static int free_device_memory(struct hl_ctx *ctx, u32 handle)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm *vm = &hdev->vm;
+ struct hl_vm_phys_pg_pack *phys_pg_pack;
+
+ spin_lock(&vm->idr_lock);
+ phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, handle);
+ if (phys_pg_pack) {
+ if (atomic_read(&phys_pg_pack->mapping_cnt) > 0) {
+ dev_err(hdev->dev, "handle %u is mapped, cannot free\n",
+ handle);
+ spin_unlock(&vm->idr_lock);
+ return -EINVAL;
+ }
+
+ /*
+ * must remove from idr before the freeing of the physical
+ * pages as the refcount of the pool is also the trigger of the
+ * idr destroy
+ */
+ idr_remove(&vm->phys_pg_pack_handles, handle);
+ spin_unlock(&vm->idr_lock);
+
+ atomic64_sub(phys_pg_pack->total_size, &ctx->dram_phys_mem);
+ atomic64_sub(phys_pg_pack->total_size, &hdev->dram_used_mem);
+
+ free_phys_pg_pack(hdev, phys_pg_pack);
+ } else {
+ spin_unlock(&vm->idr_lock);
+ dev_err(hdev->dev,
+ "free device memory failed, no match for handle %u\n",
+ handle);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * clear_va_list_locked - free virtual addresses list
+ *
+ * @hdev : habanalabs device structure
+ * @va_list : list of virtual addresses to free
+ *
+ * This function does the following:
+ * - Iterate over the list and free each virtual addresses block
+ *
+ * This function should be called only when va_list lock is taken
+ */
+static void clear_va_list_locked(struct hl_device *hdev,
+ struct list_head *va_list)
+{
+ struct hl_vm_va_block *va_block, *tmp;
+
+ list_for_each_entry_safe(va_block, tmp, va_list, node) {
+ list_del(&va_block->node);
+ kfree(va_block);
+ }
+}
+
+/*
+ * print_va_list_locked - print virtual addresses list
+ *
+ * @hdev : habanalabs device structure
+ * @va_list : list of virtual addresses to print
+ *
+ * This function does the following:
+ * - Iterate over the list and print each virtual addresses block
+ *
+ * This function should be called only when va_list lock is taken
+ */
+static void print_va_list_locked(struct hl_device *hdev,
+ struct list_head *va_list)
+{
+#if HL_MMU_DEBUG
+ struct hl_vm_va_block *va_block;
+
+ dev_dbg(hdev->dev, "print va list:\n");
+
+ list_for_each_entry(va_block, va_list, node)
+ dev_dbg(hdev->dev,
+ "va block, start: 0x%llx, end: 0x%llx, size: %llu\n",
+ va_block->start, va_block->end, va_block->size);
+#endif
+}
+
+/*
+ * merge_va_blocks_locked - merge a virtual block if possible
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @va_list : pointer to the virtual addresses block list
+ * @va_block : virtual block to merge with adjacent blocks
+ *
+ * This function does the following:
+ * - Merge the given blocks with the adjacent blocks if their virtual ranges
+ * create a contiguous virtual range
+ *
+ * This Function should be called only when va_list lock is taken
+ */
+static void merge_va_blocks_locked(struct hl_device *hdev,
+ struct list_head *va_list, struct hl_vm_va_block *va_block)
+{
+ struct hl_vm_va_block *prev, *next;
+
+ prev = list_prev_entry(va_block, node);
+ if (&prev->node != va_list && prev->end + 1 == va_block->start) {
+ prev->end = va_block->end;
+ prev->size = prev->end - prev->start;
+ list_del(&va_block->node);
+ kfree(va_block);
+ va_block = prev;
+ }
+
+ next = list_next_entry(va_block, node);
+ if (&next->node != va_list && va_block->end + 1 == next->start) {
+ next->start = va_block->start;
+ next->size = next->end - next->start;
+ list_del(&va_block->node);
+ kfree(va_block);
+ }
+}
+
+/*
+ * add_va_block_locked - add a virtual block to the virtual addresses list
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @va_list : pointer to the virtual addresses block list
+ * @start : start virtual address
+ * @end : end virtual address
+ *
+ * This function does the following:
+ * - Add the given block to the virtual blocks list and merge with other
+ * blocks if a contiguous virtual block can be created
+ *
+ * This Function should be called only when va_list lock is taken
+ */
+static int add_va_block_locked(struct hl_device *hdev,
+ struct list_head *va_list, u64 start, u64 end)
+{
+ struct hl_vm_va_block *va_block, *res = NULL;
+ u64 size = end - start;
+
+ print_va_list_locked(hdev, va_list);
+
+ list_for_each_entry(va_block, va_list, node) {
+ /* TODO: remove upon matureness */
+ if (hl_mem_area_crosses_range(start, size, va_block->start,
+ va_block->end)) {
+ dev_err(hdev->dev,
+ "block crossing ranges at start 0x%llx, end 0x%llx\n",
+ va_block->start, va_block->end);
+ return -EINVAL;
+ }
+
+ if (va_block->end < start)
+ res = va_block;
+ }
+
+ va_block = kmalloc(sizeof(*va_block), GFP_KERNEL);
+ if (!va_block)
+ return -ENOMEM;
+
+ va_block->start = start;
+ va_block->end = end;
+ va_block->size = size;
+
+ if (!res)
+ list_add(&va_block->node, va_list);
+ else
+ list_add(&va_block->node, &res->node);
+
+ merge_va_blocks_locked(hdev, va_list, va_block);
+
+ print_va_list_locked(hdev, va_list);
+
+ return 0;
+}
+
+/*
+ * add_va_block - wrapper for add_va_block_locked
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @va_list : pointer to the virtual addresses block list
+ * @start : start virtual address
+ * @end : end virtual address
+ *
+ * This function does the following:
+ * - Takes the list lock and calls add_va_block_locked
+ */
+static inline int add_va_block(struct hl_device *hdev,
+ struct hl_va_range *va_range, u64 start, u64 end)
+{
+ int rc;
+
+ mutex_lock(&va_range->lock);
+ rc = add_va_block_locked(hdev, &va_range->list, start, end);
+ mutex_unlock(&va_range->lock);
+
+ return rc;
+}
+
+/*
+ * get_va_block - get a virtual block with the requested size
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @va_range : pointer to the virtual addresses range
+ * @size : requested block size
+ * @hint_addr : hint for request address by the user
+ * @is_userptr : is host or DRAM memory
+ *
+ * This function does the following:
+ * - Iterate on the virtual block list to find a suitable virtual block for the
+ * requested size
+ * - Reserve the requested block and update the list
+ * - Return the start address of the virtual block
+ */
+static u64 get_va_block(struct hl_device *hdev,
+ struct hl_va_range *va_range, u32 size, u64 hint_addr,
+ bool is_userptr)
+{
+ struct hl_vm_va_block *va_block, *new_va_block = NULL;
+ u64 valid_start, valid_size, prev_start, prev_end, page_mask,
+ res_valid_start = 0, res_valid_size = 0;
+ u32 page_size;
+ bool add_prev = false;
+
+ if (is_userptr) {
+ /*
+ * We cannot know if the user allocated memory with huge pages
+ * or not, hence we continue with the biggest possible
+ * granularity.
+ */
+ page_size = PAGE_SIZE_2MB;
+ page_mask = PAGE_MASK_2MB;
+ } else {
+ page_size = hdev->asic_prop.dram_page_size;
+ page_mask = ~((u64)page_size - 1);
+ }
+
+ mutex_lock(&va_range->lock);
+
+ print_va_list_locked(hdev, &va_range->list);
+
+ list_for_each_entry(va_block, &va_range->list, node) {
+ /* calc the first possible aligned addr */
+ valid_start = va_block->start;
+
+
+ if (valid_start & (page_size - 1)) {
+ valid_start &= page_mask;
+ valid_start += page_size;
+ if (valid_start > va_block->end)
+ continue;
+ }
+
+ valid_size = va_block->end - valid_start;
+
+ if (valid_size >= size &&
+ (!new_va_block || valid_size < res_valid_size)) {
+
+ new_va_block = va_block;
+ res_valid_start = valid_start;
+ res_valid_size = valid_size;
+ }
+
+ if (hint_addr && hint_addr >= valid_start &&
+ ((hint_addr + size) <= va_block->end)) {
+ new_va_block = va_block;
+ res_valid_start = hint_addr;
+ res_valid_size = valid_size;
+ break;
+ }
+ }
+
+ if (!new_va_block) {
+ dev_err(hdev->dev, "no available va block for size %u\n", size);
+ goto out;
+ }
+
+ if (res_valid_start > new_va_block->start) {
+ prev_start = new_va_block->start;
+ prev_end = res_valid_start - 1;
+
+ new_va_block->start = res_valid_start;
+ new_va_block->size = res_valid_size;
+
+ add_prev = true;
+ }
+
+ if (new_va_block->size > size) {
+ new_va_block->start += size;
+ new_va_block->size = new_va_block->end - new_va_block->start;
+ } else {
+ list_del(&new_va_block->node);
+ kfree(new_va_block);
+ }
+
+ if (add_prev)
+ add_va_block_locked(hdev, &va_range->list, prev_start,
+ prev_end);
+
+ print_va_list_locked(hdev, &va_range->list);
+out:
+ mutex_unlock(&va_range->lock);
+
+ return res_valid_start;
+}
+
+/*
+ * get_sg_info - get number of pages and the DMA address from SG list
+ *
+ * @sg : the SG list
+ * @dma_addr : pointer to DMA address to return
+ *
+ * Calculate the number of consecutive pages described by the SG list. Take the
+ * offset of the address in the first page, add to it the length and round it up
+ * to the number of needed pages.
+ */
+static u32 get_sg_info(struct scatterlist *sg, dma_addr_t *dma_addr)
+{
+ *dma_addr = sg_dma_address(sg);
+
+ return ((((*dma_addr) & (PAGE_SIZE - 1)) + sg_dma_len(sg)) +
+ (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+}
+
+/*
+ * init_phys_pg_pack_from_userptr - initialize physical page pack from host
+ * memory
+ *
+ * @ctx : current context
+ * @userptr : userptr to initialize from
+ * @pphys_pg_pack : res pointer
+ *
+ * This function does the following:
+ * - Pin the physical pages related to the given virtual block
+ * - Create a physical page pack from the physical pages related to the given
+ * virtual block
+ */
+static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
+ struct hl_userptr *userptr,
+ struct hl_vm_phys_pg_pack **pphys_pg_pack)
+{
+ struct hl_vm_phys_pg_pack *phys_pg_pack;
+ struct scatterlist *sg;
+ dma_addr_t dma_addr;
+ u64 page_mask;
+ u32 npages, total_npages, page_size = PAGE_SIZE;
+ bool first = true, is_huge_page_opt = true;
+ int rc, i, j;
+
+ phys_pg_pack = kzalloc(sizeof(*phys_pg_pack), GFP_KERNEL);
+ if (!phys_pg_pack)
+ return -ENOMEM;
+
+ phys_pg_pack->vm_type = userptr->vm_type;
+ phys_pg_pack->created_from_userptr = true;
+ phys_pg_pack->asid = ctx->asid;
+ atomic_set(&phys_pg_pack->mapping_cnt, 1);
+
+ /* Only if all dma_addrs are aligned to 2MB and their
+ * sizes is at least 2MB, we can use huge page mapping.
+ * We limit the 2MB optimization to this condition,
+ * since later on we acquire the related VA range as one
+ * consecutive block.
+ */
+ total_npages = 0;
+ for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
+ npages = get_sg_info(sg, &dma_addr);
+
+ total_npages += npages;
+
+ if (first) {
+ first = false;
+ dma_addr &= PAGE_MASK_2MB;
+ }
+
+ if ((npages % PGS_IN_2MB_PAGE) ||
+ (dma_addr & (PAGE_SIZE_2MB - 1)))
+ is_huge_page_opt = false;
+ }
+
+ if (is_huge_page_opt) {
+ page_size = PAGE_SIZE_2MB;
+ total_npages /= PGS_IN_2MB_PAGE;
+ }
+
+ page_mask = ~(((u64) page_size) - 1);
+
+ phys_pg_pack->pages = kcalloc(total_npages, sizeof(u64), GFP_KERNEL);
+ if (!phys_pg_pack->pages) {
+ rc = -ENOMEM;
+ goto page_pack_arr_mem_err;
+ }
+
+ phys_pg_pack->npages = total_npages;
+ phys_pg_pack->page_size = page_size;
+ phys_pg_pack->total_size = total_npages * page_size;
+
+ j = 0;
+ first = true;
+ for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
+ npages = get_sg_info(sg, &dma_addr);
+
+ /* align down to physical page size and save the offset */
+ if (first) {
+ first = false;
+ phys_pg_pack->offset = dma_addr & (page_size - 1);
+ dma_addr &= page_mask;
+ }
+
+ while (npages) {
+ phys_pg_pack->pages[j++] = dma_addr;
+ dma_addr += page_size;
+
+ if (is_huge_page_opt)
+ npages -= PGS_IN_2MB_PAGE;
+ else
+ npages--;
+ }
+ }
+
+ *pphys_pg_pack = phys_pg_pack;
+
+ return 0;
+
+page_pack_arr_mem_err:
+ kfree(phys_pg_pack);
+
+ return rc;
+}
+
+/*
+ * map_phys_page_pack - maps the physical page pack
+ *
+ * @ctx : current context
+ * @vaddr : start address of the virtual area to map from
+ * @phys_pg_pack : the pack of physical pages to map to
+ *
+ * This function does the following:
+ * - Maps each chunk of virtual memory to matching physical chunk
+ * - Stores number of successful mappings in the given argument
+ * - Returns 0 on success, error code otherwise.
+ */
+static int map_phys_page_pack(struct hl_ctx *ctx, u64 vaddr,
+ struct hl_vm_phys_pg_pack *phys_pg_pack)
+{
+ struct hl_device *hdev = ctx->hdev;
+ u64 next_vaddr = vaddr, paddr;
+ u32 page_size = phys_pg_pack->page_size;
+ int i, rc = 0, mapped_pg_cnt = 0;
+
+ for (i = 0 ; i < phys_pg_pack->npages ; i++) {
+ paddr = phys_pg_pack->pages[i];
+
+ /* For accessing the host we need to turn on bit 39 */
+ if (phys_pg_pack->created_from_userptr)
+ paddr += hdev->asic_prop.host_phys_base_address;
+
+ rc = hl_mmu_map(ctx, next_vaddr, paddr, page_size);
+ if (rc) {
+ dev_err(hdev->dev,
+ "map failed for handle %u, npages: %d, mapped: %d",
+ phys_pg_pack->handle, phys_pg_pack->npages,
+ mapped_pg_cnt);
+ goto err;
+ }
+
+ mapped_pg_cnt++;
+ next_vaddr += page_size;
+ }
+
+ return 0;
+
+err:
+ next_vaddr = vaddr;
+ for (i = 0 ; i < mapped_pg_cnt ; i++) {
+ if (hl_mmu_unmap(ctx, next_vaddr, page_size))
+ dev_warn_ratelimited(hdev->dev,
+ "failed to unmap handle %u, va: 0x%llx, pa: 0x%llx, page size: %u\n",
+ phys_pg_pack->handle, next_vaddr,
+ phys_pg_pack->pages[i], page_size);
+
+ next_vaddr += page_size;
+ }
+
+ return rc;
+}
+
+static int get_paddr_from_handle(struct hl_ctx *ctx, struct hl_mem_in *args,
+ u64 *paddr)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm *vm = &hdev->vm;
+ struct hl_vm_phys_pg_pack *phys_pg_pack;
+ u32 handle;
+
+ handle = lower_32_bits(args->map_device.handle);
+ spin_lock(&vm->idr_lock);
+ phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, handle);
+ if (!phys_pg_pack) {
+ spin_unlock(&vm->idr_lock);
+ dev_err(hdev->dev, "no match for handle %u\n", handle);
+ return -EINVAL;
+ }
+
+ *paddr = phys_pg_pack->pages[0];
+
+ spin_unlock(&vm->idr_lock);
+
+ return 0;
+}
+
+/*
+ * map_device_va - map the given memory
+ *
+ * @ctx : current context
+ * @args : host parameters with handle/host virtual address
+ * @device_addr : pointer to result device virtual address
+ *
+ * This function does the following:
+ * - If given a physical device memory handle, map to a device virtual block
+ * and return the start address of this block
+ * - If given a host virtual address and size, find the related physical pages,
+ * map a device virtual block to this pages and return the start address of
+ * this block
+ */
+static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
+ u64 *device_addr)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm *vm = &hdev->vm;
+ struct hl_vm_phys_pg_pack *phys_pg_pack;
+ struct hl_userptr *userptr = NULL;
+ struct hl_vm_hash_node *hnode;
+ enum vm_type_t *vm_type;
+ u64 ret_vaddr, hint_addr;
+ u32 handle = 0;
+ int rc;
+ bool is_userptr = args->flags & HL_MEM_USERPTR;
+
+ /* Assume failure */
+ *device_addr = 0;
+
+ if (is_userptr) {
+ rc = get_userptr_from_host_va(hdev, args, &userptr);
+ if (rc) {
+ dev_err(hdev->dev, "failed to get userptr from va\n");
+ return rc;
+ }
+
+ rc = init_phys_pg_pack_from_userptr(ctx, userptr,
+ &phys_pg_pack);
+ if (rc) {
+ dev_err(hdev->dev,
+ "unable to init page pack for vaddr 0x%llx\n",
+ args->map_host.host_virt_addr);
+ goto init_page_pack_err;
+ }
+
+ vm_type = (enum vm_type_t *) userptr;
+ hint_addr = args->map_host.hint_addr;
+ } else {
+ handle = lower_32_bits(args->map_device.handle);
+
+ spin_lock(&vm->idr_lock);
+ phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, handle);
+ if (!phys_pg_pack) {
+ spin_unlock(&vm->idr_lock);
+ dev_err(hdev->dev,
+ "no match for handle %u\n", handle);
+ return -EINVAL;
+ }
+
+ /* increment now to avoid freeing device memory while mapping */
+ atomic_inc(&phys_pg_pack->mapping_cnt);
+
+ spin_unlock(&vm->idr_lock);
+
+ vm_type = (enum vm_type_t *) phys_pg_pack;
+
+ hint_addr = args->map_device.hint_addr;
+ }
+
+ /*
+ * relevant for mapping device physical memory only, as host memory is
+ * implicitly shared
+ */
+ if (!is_userptr && !(phys_pg_pack->flags & HL_MEM_SHARED) &&
+ phys_pg_pack->asid != ctx->asid) {
+ dev_err(hdev->dev,
+ "Failed to map memory, handle %u is not shared\n",
+ handle);
+ rc = -EPERM;
+ goto shared_err;
+ }
+
+ hnode = kzalloc(sizeof(*hnode), GFP_KERNEL);
+ if (!hnode) {
+ rc = -ENOMEM;
+ goto hnode_err;
+ }
+
+ ret_vaddr = get_va_block(hdev,
+ is_userptr ? &ctx->host_va_range : &ctx->dram_va_range,
+ phys_pg_pack->total_size, hint_addr, is_userptr);
+ if (!ret_vaddr) {
+ dev_err(hdev->dev, "no available va block for handle %u\n",
+ handle);
+ rc = -ENOMEM;
+ goto va_block_err;
+ }
+
+ mutex_lock(&ctx->mmu_lock);
+
+ rc = map_phys_page_pack(ctx, ret_vaddr, phys_pg_pack);
+ if (rc) {
+ mutex_unlock(&ctx->mmu_lock);
+ dev_err(hdev->dev, "mapping page pack failed for handle %u\n",
+ handle);
+ goto map_err;
+ }
+
+ hdev->asic_funcs->mmu_invalidate_cache(hdev, false);
+
+ mutex_unlock(&ctx->mmu_lock);
+
+ ret_vaddr += phys_pg_pack->offset;
+
+ hnode->ptr = vm_type;
+ hnode->vaddr = ret_vaddr;
+
+ mutex_lock(&ctx->mem_hash_lock);
+ hash_add(ctx->mem_hash, &hnode->node, ret_vaddr);
+ mutex_unlock(&ctx->mem_hash_lock);
+
+ *device_addr = ret_vaddr;
+
+ if (is_userptr)
+ free_phys_pg_pack(hdev, phys_pg_pack);
+
+ return 0;
+
+map_err:
+ if (add_va_block(hdev,
+ is_userptr ? &ctx->host_va_range : &ctx->dram_va_range,
+ ret_vaddr,
+ ret_vaddr + phys_pg_pack->total_size - 1))
+ dev_warn(hdev->dev,
+ "release va block failed for handle 0x%x, vaddr: 0x%llx\n",
+ handle, ret_vaddr);
+
+va_block_err:
+ kfree(hnode);
+hnode_err:
+shared_err:
+ atomic_dec(&phys_pg_pack->mapping_cnt);
+ if (is_userptr)
+ free_phys_pg_pack(hdev, phys_pg_pack);
+init_page_pack_err:
+ if (is_userptr)
+ free_userptr(hdev, userptr);
+
+ return rc;
+}
+
+/*
+ * unmap_device_va - unmap the given device virtual address
+ *
+ * @ctx : current context
+ * @vaddr : device virtual address to unmap
+ *
+ * This function does the following:
+ * - Unmap the physical pages related to the given virtual address
+ * - return the device virtual block to the virtual block list
+ */
+static int unmap_device_va(struct hl_ctx *ctx, u64 vaddr)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
+ struct hl_vm_hash_node *hnode = NULL;
+ struct hl_userptr *userptr = NULL;
+ enum vm_type_t *vm_type;
+ u64 next_vaddr;
+ u32 page_size;
+ bool is_userptr;
+ int i, rc;
+
+ /* protect from double entrance */
+ mutex_lock(&ctx->mem_hash_lock);
+ hash_for_each_possible(ctx->mem_hash, hnode, node, (unsigned long)vaddr)
+ if (vaddr == hnode->vaddr)
+ break;
+
+ if (!hnode) {
+ mutex_unlock(&ctx->mem_hash_lock);
+ dev_err(hdev->dev,
+ "unmap failed, no mem hnode for vaddr 0x%llx\n",
+ vaddr);
+ return -EINVAL;
+ }
+
+ hash_del(&hnode->node);
+ mutex_unlock(&ctx->mem_hash_lock);
+
+ vm_type = hnode->ptr;
+
+ if (*vm_type == VM_TYPE_USERPTR) {
+ is_userptr = true;
+ userptr = hnode->ptr;
+ rc = init_phys_pg_pack_from_userptr(ctx, userptr,
+ &phys_pg_pack);
+ if (rc) {
+ dev_err(hdev->dev,
+ "unable to init page pack for vaddr 0x%llx\n",
+ vaddr);
+ goto vm_type_err;
+ }
+ } else if (*vm_type == VM_TYPE_PHYS_PACK) {
+ is_userptr = false;
+ phys_pg_pack = hnode->ptr;
+ } else {
+ dev_warn(hdev->dev,
+ "unmap failed, unknown vm desc for vaddr 0x%llx\n",
+ vaddr);
+ rc = -EFAULT;
+ goto vm_type_err;
+ }
+
+ if (atomic_read(&phys_pg_pack->mapping_cnt) == 0) {
+ dev_err(hdev->dev, "vaddr 0x%llx is not mapped\n", vaddr);
+ rc = -EINVAL;
+ goto mapping_cnt_err;
+ }
+
+ page_size = phys_pg_pack->page_size;
+ vaddr &= ~(((u64) page_size) - 1);
+
+ next_vaddr = vaddr;
+
+ mutex_lock(&ctx->mmu_lock);
+
+ for (i = 0 ; i < phys_pg_pack->npages ; i++, next_vaddr += page_size)
+ if (hl_mmu_unmap(ctx, next_vaddr, page_size))
+ dev_warn_ratelimited(hdev->dev,
+ "unmap failed for vaddr: 0x%llx\n", next_vaddr);
+
+ hdev->asic_funcs->mmu_invalidate_cache(hdev, true);
+
+ mutex_unlock(&ctx->mmu_lock);
+
+ if (add_va_block(hdev,
+ is_userptr ? &ctx->host_va_range : &ctx->dram_va_range,
+ vaddr,
+ vaddr + phys_pg_pack->total_size - 1))
+ dev_warn(hdev->dev, "add va block failed for vaddr: 0x%llx\n",
+ vaddr);
+
+ atomic_dec(&phys_pg_pack->mapping_cnt);
+ kfree(hnode);
+
+ if (is_userptr) {
+ free_phys_pg_pack(hdev, phys_pg_pack);
+ free_userptr(hdev, userptr);
+ }
+
+ return 0;
+
+mapping_cnt_err:
+ if (is_userptr)
+ free_phys_pg_pack(hdev, phys_pg_pack);
+vm_type_err:
+ mutex_lock(&ctx->mem_hash_lock);
+ hash_add(ctx->mem_hash, &hnode->node, vaddr);
+ mutex_unlock(&ctx->mem_hash_lock);
+
+ return rc;
+}
+
+int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data)
+{
+ union hl_mem_args *args = data;
+ struct hl_device *hdev = hpriv->hdev;
+ struct hl_ctx *ctx = hpriv->ctx;
+ u64 device_addr = 0;
+ u32 handle = 0;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ dev_warn_ratelimited(hdev->dev,
+ "Device is disabled or in reset. Can't execute memory IOCTL\n");
+ return -EBUSY;
+ }
+
+ if (hdev->mmu_enable) {
+ switch (args->in.op) {
+ case HL_MEM_OP_ALLOC:
+ if (!hdev->dram_supports_virtual_memory) {
+ dev_err(hdev->dev,
+ "DRAM alloc is not supported\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ if (args->in.alloc.mem_size == 0) {
+ dev_err(hdev->dev,
+ "alloc size must be larger than 0\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = alloc_device_memory(ctx, &args->in, &handle);
+
+ memset(args, 0, sizeof(*args));
+ args->out.handle = (__u64) handle;
+ break;
+
+ case HL_MEM_OP_FREE:
+ if (!hdev->dram_supports_virtual_memory) {
+ dev_err(hdev->dev,
+ "DRAM free is not supported\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = free_device_memory(ctx, args->in.free.handle);
+ break;
+
+ case HL_MEM_OP_MAP:
+ rc = map_device_va(ctx, &args->in, &device_addr);
+
+ memset(args, 0, sizeof(*args));
+ args->out.device_virt_addr = device_addr;
+ break;
+
+ case HL_MEM_OP_UNMAP:
+ rc = unmap_device_va(ctx,
+ args->in.unmap.device_virt_addr);
+ break;
+
+ default:
+ dev_err(hdev->dev, "Unknown opcode for memory IOCTL\n");
+ rc = -ENOTTY;
+ break;
+ }
+ } else {
+ switch (args->in.op) {
+ case HL_MEM_OP_ALLOC:
+ if (args->in.alloc.mem_size == 0) {
+ dev_err(hdev->dev,
+ "alloc size must be larger than 0\n");
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Force contiguous as there are no real MMU
+ * translations to overcome physical memory gaps
+ */
+ args->in.flags |= HL_MEM_CONTIGUOUS;
+ rc = alloc_device_memory(ctx, &args->in, &handle);
+
+ memset(args, 0, sizeof(*args));
+ args->out.handle = (__u64) handle;
+ break;
+
+ case HL_MEM_OP_FREE:
+ rc = free_device_memory(ctx, args->in.free.handle);
+ break;
+
+ case HL_MEM_OP_MAP:
+ if (args->in.flags & HL_MEM_USERPTR) {
+ device_addr = args->in.map_host.host_virt_addr;
+ rc = 0;
+ } else {
+ rc = get_paddr_from_handle(ctx, &args->in,
+ &device_addr);
+ }
+
+ memset(args, 0, sizeof(*args));
+ args->out.device_virt_addr = device_addr;
+ break;
+
+ case HL_MEM_OP_UNMAP:
+ rc = 0;
+ break;
+
+ default:
+ dev_err(hdev->dev, "Unknown opcode for memory IOCTL\n");
+ rc = -ENOTTY;
+ break;
+ }
+ }
+
+out:
+ return rc;
+}
+
+/*
+ * hl_pin_host_memory - pins a chunk of host memory
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @addr : the user-space virtual address of the memory area
+ * @size : the size of the memory area
+ * @userptr : pointer to hl_userptr structure
+ *
+ * This function does the following:
+ * - Pins the physical pages
+ * - Create a SG list from those pages
+ */
+int hl_pin_host_memory(struct hl_device *hdev, u64 addr, u64 size,
+ struct hl_userptr *userptr)
+{
+ u64 start, end;
+ u32 npages, offset;
+ int rc;
+
+ if (!size) {
+ dev_err(hdev->dev, "size to pin is invalid - %llu\n", size);
+ return -EINVAL;
+ }
+
+ if (!access_ok((void __user *) (uintptr_t) addr, size)) {
+ dev_err(hdev->dev, "user pointer is invalid - 0x%llx\n", addr);
+ return -EFAULT;
+ }
+
+ /*
+ * If the combination of the address and size requested for this memory
+ * region causes an integer overflow, return error.
+ */
+ if (((addr + size) < addr) ||
+ PAGE_ALIGN(addr + size) < (addr + size)) {
+ dev_err(hdev->dev,
+ "user pointer 0x%llx + %llu causes integer overflow\n",
+ addr, size);
+ return -EINVAL;
+ }
+
+ start = addr & PAGE_MASK;
+ offset = addr & ~PAGE_MASK;
+ end = PAGE_ALIGN(addr + size);
+ npages = (end - start) >> PAGE_SHIFT;
+
+ userptr->size = size;
+ userptr->addr = addr;
+ userptr->dma_mapped = false;
+ INIT_LIST_HEAD(&userptr->job_node);
+
+ userptr->vec = frame_vector_create(npages);
+ if (!userptr->vec) {
+ dev_err(hdev->dev, "Failed to create frame vector\n");
+ return -ENOMEM;
+ }
+
+ rc = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE,
+ userptr->vec);
+
+ if (rc != npages) {
+ dev_err(hdev->dev,
+ "Failed to map host memory, user ptr probably wrong\n");
+ if (rc < 0)
+ goto destroy_framevec;
+ rc = -EFAULT;
+ goto put_framevec;
+ }
+
+ if (frame_vector_to_pages(userptr->vec) < 0) {
+ dev_err(hdev->dev,
+ "Failed to translate frame vector to pages\n");
+ rc = -EFAULT;
+ goto put_framevec;
+ }
+
+ userptr->sgt = kzalloc(sizeof(*userptr->sgt), GFP_ATOMIC);
+ if (!userptr->sgt) {
+ rc = -ENOMEM;
+ goto put_framevec;
+ }
+
+ rc = sg_alloc_table_from_pages(userptr->sgt,
+ frame_vector_pages(userptr->vec),
+ npages, offset, size, GFP_ATOMIC);
+ if (rc < 0) {
+ dev_err(hdev->dev, "failed to create SG table from pages\n");
+ goto free_sgt;
+ }
+
+ hl_debugfs_add_userptr(hdev, userptr);
+
+ return 0;
+
+free_sgt:
+ kfree(userptr->sgt);
+put_framevec:
+ put_vaddr_frames(userptr->vec);
+destroy_framevec:
+ frame_vector_destroy(userptr->vec);
+ return rc;
+}
+
+/*
+ * hl_unpin_host_memory - unpins a chunk of host memory
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @userptr : pointer to hl_userptr structure
+ *
+ * This function does the following:
+ * - Unpins the physical pages related to the host memory
+ * - Free the SG list
+ */
+int hl_unpin_host_memory(struct hl_device *hdev, struct hl_userptr *userptr)
+{
+ struct page **pages;
+
+ hl_debugfs_remove_userptr(hdev, userptr);
+
+ if (userptr->dma_mapped)
+ hdev->asic_funcs->hl_dma_unmap_sg(hdev,
+ userptr->sgt->sgl,
+ userptr->sgt->nents,
+ userptr->dir);
+
+ pages = frame_vector_pages(userptr->vec);
+ if (!IS_ERR(pages)) {
+ int i;
+
+ for (i = 0; i < frame_vector_count(userptr->vec); i++)
+ set_page_dirty_lock(pages[i]);
+ }
+ put_vaddr_frames(userptr->vec);
+ frame_vector_destroy(userptr->vec);
+
+ list_del(&userptr->job_node);
+
+ sg_free_table(userptr->sgt);
+ kfree(userptr->sgt);
+
+ return 0;
+}
+
+/*
+ * hl_userptr_delete_list - clear userptr list
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @userptr_list : pointer to the list to clear
+ *
+ * This function does the following:
+ * - Iterates over the list and unpins the host memory and frees the userptr
+ * structure.
+ */
+void hl_userptr_delete_list(struct hl_device *hdev,
+ struct list_head *userptr_list)
+{
+ struct hl_userptr *userptr, *tmp;
+
+ list_for_each_entry_safe(userptr, tmp, userptr_list, job_node) {
+ hl_unpin_host_memory(hdev, userptr);
+ kfree(userptr);
+ }
+
+ INIT_LIST_HEAD(userptr_list);
+}
+
+/*
+ * hl_userptr_is_pinned - returns whether the given userptr is pinned
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @userptr_list : pointer to the list to clear
+ * @userptr : pointer to userptr to check
+ *
+ * This function does the following:
+ * - Iterates over the list and checks if the given userptr is in it, means is
+ * pinned. If so, returns true, otherwise returns false.
+ */
+bool hl_userptr_is_pinned(struct hl_device *hdev, u64 addr,
+ u32 size, struct list_head *userptr_list,
+ struct hl_userptr **userptr)
+{
+ list_for_each_entry((*userptr), userptr_list, job_node) {
+ if ((addr == (*userptr)->addr) && (size == (*userptr)->size))
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * hl_va_range_init - initialize virtual addresses range
+ *
+ * @hdev : pointer to the habanalabs device structure
+ * @va_range : pointer to the range to initialize
+ * @start : range start address
+ * @end : range end address
+ *
+ * This function does the following:
+ * - Initializes the virtual addresses list of the given range with the given
+ * addresses.
+ */
+static int hl_va_range_init(struct hl_device *hdev,
+ struct hl_va_range *va_range, u64 start, u64 end)
+{
+ int rc;
+
+ INIT_LIST_HEAD(&va_range->list);
+
+ /* PAGE_SIZE alignment */
+
+ if (start & (PAGE_SIZE - 1)) {
+ start &= PAGE_MASK;
+ start += PAGE_SIZE;
+ }
+
+ if (end & (PAGE_SIZE - 1))
+ end &= PAGE_MASK;
+
+ if (start >= end) {
+ dev_err(hdev->dev, "too small vm range for va list\n");
+ return -EFAULT;
+ }
+
+ rc = add_va_block(hdev, va_range, start, end);
+
+ if (rc) {
+ dev_err(hdev->dev, "Failed to init host va list\n");
+ return rc;
+ }
+
+ va_range->start_addr = start;
+ va_range->end_addr = end;
+
+ return 0;
+}
+
+/*
+ * hl_vm_ctx_init_with_ranges - initialize virtual memory for context
+ *
+ * @ctx : pointer to the habanalabs context structure
+ * @host_range_start : host virtual addresses range start
+ * @host_range_end : host virtual addresses range end
+ * @dram_range_start : dram virtual addresses range start
+ * @dram_range_end : dram virtual addresses range end
+ *
+ * This function initializes the following:
+ * - MMU for context
+ * - Virtual address to area descriptor hashtable
+ * - Virtual block list of available virtual memory
+ */
+static int hl_vm_ctx_init_with_ranges(struct hl_ctx *ctx, u64 host_range_start,
+ u64 host_range_end, u64 dram_range_start,
+ u64 dram_range_end)
+{
+ struct hl_device *hdev = ctx->hdev;
+ int rc;
+
+ rc = hl_mmu_ctx_init(ctx);
+ if (rc) {
+ dev_err(hdev->dev, "failed to init context %d\n", ctx->asid);
+ return rc;
+ }
+
+ mutex_init(&ctx->mem_hash_lock);
+ hash_init(ctx->mem_hash);
+
+ mutex_init(&ctx->host_va_range.lock);
+
+ rc = hl_va_range_init(hdev, &ctx->host_va_range, host_range_start,
+ host_range_end);
+ if (rc) {
+ dev_err(hdev->dev, "failed to init host vm range\n");
+ goto host_vm_err;
+ }
+
+ mutex_init(&ctx->dram_va_range.lock);
+
+ rc = hl_va_range_init(hdev, &ctx->dram_va_range, dram_range_start,
+ dram_range_end);
+ if (rc) {
+ dev_err(hdev->dev, "failed to init dram vm range\n");
+ goto dram_vm_err;
+ }
+
+ hl_debugfs_add_ctx_mem_hash(hdev, ctx);
+
+ return 0;
+
+dram_vm_err:
+ mutex_destroy(&ctx->dram_va_range.lock);
+
+ mutex_lock(&ctx->host_va_range.lock);
+ clear_va_list_locked(hdev, &ctx->host_va_range.list);
+ mutex_unlock(&ctx->host_va_range.lock);
+host_vm_err:
+ mutex_destroy(&ctx->host_va_range.lock);
+ mutex_destroy(&ctx->mem_hash_lock);
+ hl_mmu_ctx_fini(ctx);
+
+ return rc;
+}
+
+int hl_vm_ctx_init(struct hl_ctx *ctx)
+{
+ struct asic_fixed_properties *prop = &ctx->hdev->asic_prop;
+ u64 host_range_start, host_range_end, dram_range_start,
+ dram_range_end;
+
+ atomic64_set(&ctx->dram_phys_mem, 0);
+
+ /*
+ * - If MMU is enabled, init the ranges as usual.
+ * - If MMU is disabled, in case of host mapping, the returned address
+ * is the given one.
+ * In case of DRAM mapping, the returned address is the physical
+ * address of the memory related to the given handle.
+ */
+ if (ctx->hdev->mmu_enable) {
+ dram_range_start = prop->va_space_dram_start_address;
+ dram_range_end = prop->va_space_dram_end_address;
+ host_range_start = prop->va_space_host_start_address;
+ host_range_end = prop->va_space_host_end_address;
+ } else {
+ dram_range_start = prop->dram_user_base_address;
+ dram_range_end = prop->dram_end_address;
+ host_range_start = prop->dram_user_base_address;
+ host_range_end = prop->dram_end_address;
+ }
+
+ return hl_vm_ctx_init_with_ranges(ctx, host_range_start, host_range_end,
+ dram_range_start, dram_range_end);
+}
+
+/*
+ * hl_va_range_fini - clear a virtual addresses range
+ *
+ * @hdev : pointer to the habanalabs structure
+ * va_range : pointer to virtual addresses range
+ *
+ * This function initializes the following:
+ * - Checks that the given range contains the whole initial range
+ * - Frees the virtual addresses block list and its lock
+ */
+static void hl_va_range_fini(struct hl_device *hdev,
+ struct hl_va_range *va_range)
+{
+ struct hl_vm_va_block *va_block;
+
+ if (list_empty(&va_range->list)) {
+ dev_warn(hdev->dev,
+ "va list should not be empty on cleanup!\n");
+ goto out;
+ }
+
+ if (!list_is_singular(&va_range->list)) {
+ dev_warn(hdev->dev,
+ "va list should not contain multiple blocks on cleanup!\n");
+ goto free_va_list;
+ }
+
+ va_block = list_first_entry(&va_range->list, typeof(*va_block), node);
+
+ if (va_block->start != va_range->start_addr ||
+ va_block->end != va_range->end_addr) {
+ dev_warn(hdev->dev,
+ "wrong va block on cleanup, from 0x%llx to 0x%llx\n",
+ va_block->start, va_block->end);
+ goto free_va_list;
+ }
+
+free_va_list:
+ mutex_lock(&va_range->lock);
+ clear_va_list_locked(hdev, &va_range->list);
+ mutex_unlock(&va_range->lock);
+
+out:
+ mutex_destroy(&va_range->lock);
+}
+
+/*
+ * hl_vm_ctx_fini - virtual memory teardown of context
+ *
+ * @ctx : pointer to the habanalabs context structure
+ *
+ * This function perform teardown the following:
+ * - Virtual block list of available virtual memory
+ * - Virtual address to area descriptor hashtable
+ * - MMU for context
+ *
+ * In addition this function does the following:
+ * - Unmaps the existing hashtable nodes if the hashtable is not empty. The
+ * hashtable should be empty as no valid mappings should exist at this
+ * point.
+ * - Frees any existing physical page list from the idr which relates to the
+ * current context asid.
+ * - This function checks the virtual block list for correctness. At this point
+ * the list should contain one element which describes the whole virtual
+ * memory range of the context. Otherwise, a warning is printed.
+ */
+void hl_vm_ctx_fini(struct hl_ctx *ctx)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct hl_vm *vm = &hdev->vm;
+ struct hl_vm_phys_pg_pack *phys_pg_list;
+ struct hl_vm_hash_node *hnode;
+ struct hlist_node *tmp_node;
+ int i;
+
+ hl_debugfs_remove_ctx_mem_hash(hdev, ctx);
+
+ if (!hash_empty(ctx->mem_hash))
+ dev_notice(hdev->dev, "ctx is freed while it has va in use\n");
+
+ hash_for_each_safe(ctx->mem_hash, i, tmp_node, hnode, node) {
+ dev_dbg(hdev->dev,
+ "hl_mem_hash_node of vaddr 0x%llx of asid %d is still alive\n",
+ hnode->vaddr, ctx->asid);
+ unmap_device_va(ctx, hnode->vaddr);
+ }
+
+ spin_lock(&vm->idr_lock);
+ idr_for_each_entry(&vm->phys_pg_pack_handles, phys_pg_list, i)
+ if (phys_pg_list->asid == ctx->asid) {
+ dev_dbg(hdev->dev,
+ "page list 0x%p of asid %d is still alive\n",
+ phys_pg_list, ctx->asid);
+ free_phys_pg_pack(hdev, phys_pg_list);
+ idr_remove(&vm->phys_pg_pack_handles, i);
+ }
+ spin_unlock(&vm->idr_lock);
+
+ hl_va_range_fini(hdev, &ctx->dram_va_range);
+ hl_va_range_fini(hdev, &ctx->host_va_range);
+
+ mutex_destroy(&ctx->mem_hash_lock);
+ hl_mmu_ctx_fini(ctx);
+}
+
+/*
+ * hl_vm_init - initialize virtual memory module
+ *
+ * @hdev : pointer to the habanalabs device structure
+ *
+ * This function initializes the following:
+ * - MMU module
+ * - DRAM physical pages pool of 2MB
+ * - Idr for device memory allocation handles
+ */
+int hl_vm_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct hl_vm *vm = &hdev->vm;
+ int rc;
+
+ rc = hl_mmu_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to init MMU\n");
+ return rc;
+ }
+
+ vm->dram_pg_pool = gen_pool_create(__ffs(prop->dram_page_size), -1);
+ if (!vm->dram_pg_pool) {
+ dev_err(hdev->dev, "Failed to create dram page pool\n");
+ rc = -ENOMEM;
+ goto pool_create_err;
+ }
+
+ kref_init(&vm->dram_pg_pool_refcount);
+
+ rc = gen_pool_add(vm->dram_pg_pool, prop->dram_user_base_address,
+ prop->dram_end_address - prop->dram_user_base_address,
+ -1);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to add memory to dram page pool %d\n", rc);
+ goto pool_add_err;
+ }
+
+ spin_lock_init(&vm->idr_lock);
+ idr_init(&vm->phys_pg_pack_handles);
+
+ atomic64_set(&hdev->dram_used_mem, 0);
+
+ vm->init_done = true;
+
+ return 0;
+
+pool_add_err:
+ gen_pool_destroy(vm->dram_pg_pool);
+pool_create_err:
+ hl_mmu_fini(hdev);
+
+ return rc;
+}
+
+/*
+ * hl_vm_fini - virtual memory module teardown
+ *
+ * @hdev : pointer to the habanalabs device structure
+ *
+ * This function perform teardown to the following:
+ * - Idr for device memory allocation handles
+ * - DRAM physical pages pool of 2MB
+ * - MMU module
+ */
+void hl_vm_fini(struct hl_device *hdev)
+{
+ struct hl_vm *vm = &hdev->vm;
+
+ if (!vm->init_done)
+ return;
+
+ /*
+ * At this point all the contexts should be freed and hence no DRAM
+ * memory should be in use. Hence the DRAM pool should be freed here.
+ */
+ if (kref_put(&vm->dram_pg_pool_refcount, dram_pg_pool_do_release) != 1)
+ dev_warn(hdev->dev, "dram_pg_pool was not destroyed on %s\n",
+ __func__);
+
+ hl_mmu_fini(hdev);
+
+ vm->init_done = false;
+}
diff --git a/drivers/misc/habanalabs/mmu.c b/drivers/misc/habanalabs/mmu.c
new file mode 100644
index 000000000000..2f2e99cb2743
--- /dev/null
+++ b/drivers/misc/habanalabs/mmu.c
@@ -0,0 +1,906 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+#include "include/hw_ip/mmu/mmu_general.h"
+
+#include <linux/genalloc.h>
+#include <linux/slab.h>
+
+static struct pgt_info *get_pgt_info(struct hl_ctx *ctx, u64 addr)
+{
+ struct pgt_info *pgt_info = NULL;
+
+ hash_for_each_possible(ctx->mmu_hash, pgt_info, node,
+ (unsigned long) addr)
+ if (addr == pgt_info->addr)
+ break;
+
+ return pgt_info;
+}
+
+static void free_hop(struct hl_ctx *ctx, u64 hop_addr)
+{
+ struct pgt_info *pgt_info = get_pgt_info(ctx, hop_addr);
+
+ gen_pool_free(pgt_info->ctx->hdev->mmu_pgt_pool, pgt_info->addr,
+ ctx->hdev->asic_prop.mmu_hop_table_size);
+ hash_del(&pgt_info->node);
+
+ kfree(pgt_info);
+}
+
+static u64 alloc_hop(struct hl_ctx *ctx)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct pgt_info *pgt_info;
+ u64 addr;
+
+ pgt_info = kmalloc(sizeof(*pgt_info), GFP_KERNEL);
+ if (!pgt_info)
+ return ULLONG_MAX;
+
+ addr = (u64) gen_pool_alloc(hdev->mmu_pgt_pool,
+ hdev->asic_prop.mmu_hop_table_size);
+ if (!addr) {
+ dev_err(hdev->dev, "failed to allocate page\n");
+ kfree(pgt_info);
+ return ULLONG_MAX;
+ }
+
+ pgt_info->addr = addr;
+ pgt_info->ctx = ctx;
+ pgt_info->num_of_ptes = 0;
+ hash_add(ctx->mmu_hash, &pgt_info->node, addr);
+
+ return addr;
+}
+
+static inline void clear_pte(struct hl_device *hdev, u64 pte_addr)
+{
+ /* clear the last and present bits */
+ hdev->asic_funcs->write_pte(hdev, pte_addr, 0);
+}
+
+static inline void get_pte(struct hl_ctx *ctx, u64 hop_addr)
+{
+ get_pgt_info(ctx, hop_addr)->num_of_ptes++;
+}
+
+/*
+ * put_pte - decrement the num of ptes and free the hop if possible
+ *
+ * @ctx: pointer to the context structure
+ * @hop_addr: addr of the hop
+ *
+ * This function returns the number of ptes left on this hop. If the number is
+ * 0, it means the pte was freed.
+ */
+static inline int put_pte(struct hl_ctx *ctx, u64 hop_addr)
+{
+ struct pgt_info *pgt_info = get_pgt_info(ctx, hop_addr);
+ int num_of_ptes_left;
+
+ pgt_info->num_of_ptes--;
+
+ /*
+ * Need to save the number of ptes left because free_hop might free
+ * the pgt_info
+ */
+ num_of_ptes_left = pgt_info->num_of_ptes;
+ if (!num_of_ptes_left)
+ free_hop(ctx, hop_addr);
+
+ return num_of_ptes_left;
+}
+
+static inline u64 get_hop0_addr(struct hl_ctx *ctx)
+{
+ return ctx->hdev->asic_prop.mmu_pgt_addr +
+ (ctx->asid * ctx->hdev->asic_prop.mmu_hop_table_size);
+}
+
+static inline u64 get_hopN_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
+ u64 virt_addr, u64 mask, u64 shift)
+{
+ return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
+ ((virt_addr & mask) >> shift);
+}
+
+static inline u64 get_hop0_pte_addr(struct hl_ctx *ctx, u64 hop_addr, u64 vaddr)
+{
+ return get_hopN_pte_addr(ctx, hop_addr, vaddr, HOP0_MASK, HOP0_SHIFT);
+}
+
+static inline u64 get_hop1_pte_addr(struct hl_ctx *ctx, u64 hop_addr, u64 vaddr)
+{
+ return get_hopN_pte_addr(ctx, hop_addr, vaddr, HOP1_MASK, HOP1_SHIFT);
+}
+
+static inline u64 get_hop2_pte_addr(struct hl_ctx *ctx, u64 hop_addr, u64 vaddr)
+{
+ return get_hopN_pte_addr(ctx, hop_addr, vaddr, HOP2_MASK, HOP2_SHIFT);
+}
+
+static inline u64 get_hop3_pte_addr(struct hl_ctx *ctx, u64 hop_addr, u64 vaddr)
+{
+ return get_hopN_pte_addr(ctx, hop_addr, vaddr, HOP3_MASK, HOP3_SHIFT);
+}
+
+static inline u64 get_hop4_pte_addr(struct hl_ctx *ctx, u64 hop_addr, u64 vaddr)
+{
+ return get_hopN_pte_addr(ctx, hop_addr, vaddr, HOP4_MASK, HOP4_SHIFT);
+}
+
+static inline u64 get_next_hop_addr(u64 curr_pte)
+{
+ if (curr_pte & PAGE_PRESENT_MASK)
+ return curr_pte & PHYS_ADDR_MASK;
+ else
+ return ULLONG_MAX;
+}
+
+static inline u64 get_alloc_next_hop_addr(struct hl_ctx *ctx, u64 curr_pte,
+ bool *is_new_hop)
+{
+ u64 hop_addr = get_next_hop_addr(curr_pte);
+
+ if (hop_addr == ULLONG_MAX) {
+ hop_addr = alloc_hop(ctx);
+ *is_new_hop = (hop_addr != ULLONG_MAX);
+ }
+
+ return hop_addr;
+}
+
+/*
+ * hl_mmu_init - init the mmu module
+ *
+ * @hdev: pointer to the habanalabs device structure
+ *
+ * This function does the following:
+ * - Allocate max_asid zeroed hop0 pgts so no mapping is available
+ * - Enable mmu in hw
+ * - Invalidate the mmu cache
+ * - Create a pool of pages for pgts
+ * - Returns 0 on success
+ *
+ * This function depends on DMA QMAN to be working!
+ */
+int hl_mmu_init(struct hl_device *hdev)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ int rc;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ /* MMU HW init was already done in device hw_init() */
+
+ mutex_init(&hdev->mmu_cache_lock);
+
+ hdev->mmu_pgt_pool =
+ gen_pool_create(__ffs(prop->mmu_hop_table_size), -1);
+
+ if (!hdev->mmu_pgt_pool) {
+ dev_err(hdev->dev, "Failed to create page gen pool\n");
+ rc = -ENOMEM;
+ goto err_pool_create;
+ }
+
+ rc = gen_pool_add(hdev->mmu_pgt_pool, prop->mmu_pgt_addr +
+ prop->mmu_hop0_tables_total_size,
+ prop->mmu_pgt_size - prop->mmu_hop0_tables_total_size,
+ -1);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to add memory to page gen pool\n");
+ goto err_pool_add;
+ }
+
+ return 0;
+
+err_pool_add:
+ gen_pool_destroy(hdev->mmu_pgt_pool);
+err_pool_create:
+ mutex_destroy(&hdev->mmu_cache_lock);
+
+ return rc;
+}
+
+/*
+ * hl_mmu_fini - release the mmu module.
+ *
+ * @hdev: pointer to the habanalabs device structure
+ *
+ * This function does the following:
+ * - Disable mmu in hw
+ * - free the pgts pool
+ *
+ * All ctxs should be freed before calling this func
+ */
+void hl_mmu_fini(struct hl_device *hdev)
+{
+ if (!hdev->mmu_enable)
+ return;
+
+ gen_pool_destroy(hdev->mmu_pgt_pool);
+
+ mutex_destroy(&hdev->mmu_cache_lock);
+
+ /* MMU HW fini will be done in device hw_fini() */
+}
+
+/**
+ * hl_mmu_ctx_init() - initialize a context for using the MMU module.
+ * @ctx: pointer to the context structure to initialize.
+ *
+ * Initialize a mutex to protect the concurrent mapping flow, a hash to hold all
+ * page tables hops related to this context and an optional DRAM default page
+ * mapping.
+ * Return: 0 on success, non-zero otherwise.
+ */
+int hl_mmu_ctx_init(struct hl_ctx *ctx)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 num_of_hop3, total_hops, hop1_addr, hop2_addr, hop2_pte_addr,
+ hop3_pte_addr, pte_val;
+ int rc, i, j, hop3_allocated = 0;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ mutex_init(&ctx->mmu_lock);
+ hash_init(ctx->mmu_hash);
+
+ if (!hdev->dram_supports_virtual_memory ||
+ !hdev->dram_default_page_mapping)
+ return 0;
+
+ num_of_hop3 = prop->dram_size_for_default_page_mapping;
+ do_div(num_of_hop3, prop->dram_page_size);
+ do_div(num_of_hop3, PTE_ENTRIES_IN_HOP);
+
+ /* add hop1 and hop2 */
+ total_hops = num_of_hop3 + 2;
+
+ ctx->dram_default_hops = kzalloc(HL_PTE_SIZE * total_hops, GFP_KERNEL);
+ if (!ctx->dram_default_hops) {
+ rc = -ENOMEM;
+ goto alloc_err;
+ }
+
+ hop1_addr = alloc_hop(ctx);
+ if (hop1_addr == ULLONG_MAX) {
+ dev_err(hdev->dev, "failed to alloc hop 1\n");
+ rc = -ENOMEM;
+ goto hop1_err;
+ }
+
+ ctx->dram_default_hops[total_hops - 1] = hop1_addr;
+
+ hop2_addr = alloc_hop(ctx);
+ if (hop2_addr == ULLONG_MAX) {
+ dev_err(hdev->dev, "failed to alloc hop 2\n");
+ rc = -ENOMEM;
+ goto hop2_err;
+ }
+
+ ctx->dram_default_hops[total_hops - 2] = hop2_addr;
+
+ for (i = 0 ; i < num_of_hop3 ; i++) {
+ ctx->dram_default_hops[i] = alloc_hop(ctx);
+ if (ctx->dram_default_hops[i] == ULLONG_MAX) {
+ dev_err(hdev->dev, "failed to alloc hop 3, i: %d\n", i);
+ rc = -ENOMEM;
+ goto hop3_err;
+ }
+ hop3_allocated++;
+ }
+
+ /* need only pte 0 in hops 0 and 1 */
+ pte_val = (hop1_addr & PTE_PHYS_ADDR_MASK) | PAGE_PRESENT_MASK;
+ hdev->asic_funcs->write_pte(hdev, get_hop0_addr(ctx), pte_val);
+
+ pte_val = (hop2_addr & PTE_PHYS_ADDR_MASK) | PAGE_PRESENT_MASK;
+ hdev->asic_funcs->write_pte(hdev, hop1_addr, pte_val);
+ get_pte(ctx, hop1_addr);
+
+ hop2_pte_addr = hop2_addr;
+ for (i = 0 ; i < num_of_hop3 ; i++) {
+ pte_val = (ctx->dram_default_hops[i] & PTE_PHYS_ADDR_MASK) |
+ PAGE_PRESENT_MASK;
+ hdev->asic_funcs->write_pte(hdev, hop2_pte_addr, pte_val);
+ get_pte(ctx, hop2_addr);
+ hop2_pte_addr += HL_PTE_SIZE;
+ }
+
+ pte_val = (prop->mmu_dram_default_page_addr & PTE_PHYS_ADDR_MASK) |
+ LAST_MASK | PAGE_PRESENT_MASK;
+
+ for (i = 0 ; i < num_of_hop3 ; i++) {
+ hop3_pte_addr = ctx->dram_default_hops[i];
+ for (j = 0 ; j < PTE_ENTRIES_IN_HOP ; j++) {
+ hdev->asic_funcs->write_pte(hdev, hop3_pte_addr,
+ pte_val);
+ get_pte(ctx, ctx->dram_default_hops[i]);
+ hop3_pte_addr += HL_PTE_SIZE;
+ }
+ }
+
+ /* flush all writes to reach PCI */
+ mb();
+ hdev->asic_funcs->read_pte(hdev, hop2_addr);
+
+ return 0;
+
+hop3_err:
+ for (i = 0 ; i < hop3_allocated ; i++)
+ free_hop(ctx, ctx->dram_default_hops[i]);
+ free_hop(ctx, hop2_addr);
+hop2_err:
+ free_hop(ctx, hop1_addr);
+hop1_err:
+ kfree(ctx->dram_default_hops);
+alloc_err:
+ mutex_destroy(&ctx->mmu_lock);
+
+ return rc;
+}
+
+/*
+ * hl_mmu_ctx_fini - disable a ctx from using the mmu module
+ *
+ * @ctx: pointer to the context structure
+ *
+ * This function does the following:
+ * - Free any pgts which were not freed yet
+ * - Free the mutex
+ * - Free DRAM default page mapping hops
+ */
+void hl_mmu_ctx_fini(struct hl_ctx *ctx)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct pgt_info *pgt_info;
+ struct hlist_node *tmp;
+ u64 num_of_hop3, total_hops, hop1_addr, hop2_addr, hop2_pte_addr,
+ hop3_pte_addr;
+ int i, j;
+
+ if (!ctx->hdev->mmu_enable)
+ return;
+
+ if (hdev->dram_supports_virtual_memory &&
+ hdev->dram_default_page_mapping) {
+
+ num_of_hop3 = prop->dram_size_for_default_page_mapping;
+ do_div(num_of_hop3, prop->dram_page_size);
+ do_div(num_of_hop3, PTE_ENTRIES_IN_HOP);
+
+ /* add hop1 and hop2 */
+ total_hops = num_of_hop3 + 2;
+ hop1_addr = ctx->dram_default_hops[total_hops - 1];
+ hop2_addr = ctx->dram_default_hops[total_hops - 2];
+
+ for (i = 0 ; i < num_of_hop3 ; i++) {
+ hop3_pte_addr = ctx->dram_default_hops[i];
+ for (j = 0 ; j < PTE_ENTRIES_IN_HOP ; j++) {
+ clear_pte(hdev, hop3_pte_addr);
+ put_pte(ctx, ctx->dram_default_hops[i]);
+ hop3_pte_addr += HL_PTE_SIZE;
+ }
+ }
+
+ hop2_pte_addr = hop2_addr;
+ for (i = 0 ; i < num_of_hop3 ; i++) {
+ clear_pte(hdev, hop2_pte_addr);
+ put_pte(ctx, hop2_addr);
+ hop2_pte_addr += HL_PTE_SIZE;
+ }
+
+ clear_pte(hdev, hop1_addr);
+ put_pte(ctx, hop1_addr);
+ clear_pte(hdev, get_hop0_addr(ctx));
+
+ kfree(ctx->dram_default_hops);
+
+ /* flush all writes to reach PCI */
+ mb();
+ hdev->asic_funcs->read_pte(hdev, hop2_addr);
+ }
+
+ if (!hash_empty(ctx->mmu_hash))
+ dev_err(hdev->dev, "ctx is freed while it has pgts in use\n");
+
+ hash_for_each_safe(ctx->mmu_hash, i, tmp, pgt_info, node) {
+ dev_err(hdev->dev,
+ "pgt_info of addr 0x%llx of asid %d was not destroyed, num_ptes: %d\n",
+ pgt_info->addr, ctx->asid, pgt_info->num_of_ptes);
+ free_hop(ctx, pgt_info->addr);
+ }
+
+ mutex_destroy(&ctx->mmu_lock);
+}
+
+static int _hl_mmu_unmap(struct hl_ctx *ctx, u64 virt_addr)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 hop0_addr = 0, hop0_pte_addr = 0,
+ hop1_addr = 0, hop1_pte_addr = 0,
+ hop2_addr = 0, hop2_pte_addr = 0,
+ hop3_addr = 0, hop3_pte_addr = 0,
+ hop4_addr = 0, hop4_pte_addr = 0,
+ curr_pte;
+ int clear_hop3 = 1;
+ bool is_dram_addr, is_huge, is_dram_default_page_mapping;
+
+ is_dram_addr = hl_mem_area_inside_range(virt_addr, PAGE_SIZE_2MB,
+ prop->va_space_dram_start_address,
+ prop->va_space_dram_end_address);
+
+ hop0_addr = get_hop0_addr(ctx);
+
+ hop0_pte_addr = get_hop0_pte_addr(ctx, hop0_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop0_pte_addr);
+
+ hop1_addr = get_next_hop_addr(curr_pte);
+
+ if (hop1_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop1_pte_addr = get_hop1_pte_addr(ctx, hop1_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop1_pte_addr);
+
+ hop2_addr = get_next_hop_addr(curr_pte);
+
+ if (hop2_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop2_pte_addr = get_hop2_pte_addr(ctx, hop2_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop2_pte_addr);
+
+ hop3_addr = get_next_hop_addr(curr_pte);
+
+ if (hop3_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop3_pte_addr = get_hop3_pte_addr(ctx, hop3_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop3_pte_addr);
+
+ is_huge = curr_pte & LAST_MASK;
+
+ if (is_dram_addr && !is_huge) {
+ dev_err(hdev->dev,
+ "DRAM unmapping should use huge pages only\n");
+ return -EFAULT;
+ }
+
+ is_dram_default_page_mapping =
+ hdev->dram_default_page_mapping && is_dram_addr;
+
+ if (!is_huge) {
+ hop4_addr = get_next_hop_addr(curr_pte);
+
+ if (hop4_addr == ULLONG_MAX)
+ goto not_mapped;
+
+ hop4_pte_addr = get_hop4_pte_addr(ctx, hop4_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop4_pte_addr);
+
+ clear_hop3 = 0;
+ }
+
+ if (is_dram_default_page_mapping) {
+ u64 zero_pte = (prop->mmu_dram_default_page_addr &
+ PTE_PHYS_ADDR_MASK) | LAST_MASK |
+ PAGE_PRESENT_MASK;
+ if (curr_pte == zero_pte) {
+ dev_err(hdev->dev,
+ "DRAM: hop3 PTE points to zero page, can't unmap, va: 0x%llx\n",
+ virt_addr);
+ goto not_mapped;
+ }
+
+ if (!(curr_pte & PAGE_PRESENT_MASK)) {
+ dev_err(hdev->dev,
+ "DRAM: hop3 PTE is cleared! can't unmap, va: 0x%llx\n",
+ virt_addr);
+ goto not_mapped;
+ }
+
+ hdev->asic_funcs->write_pte(hdev, hop3_pte_addr, zero_pte);
+ put_pte(ctx, hop3_addr);
+ } else {
+ if (!(curr_pte & PAGE_PRESENT_MASK))
+ goto not_mapped;
+
+ clear_pte(hdev, hop4_addr ? hop4_pte_addr : hop3_pte_addr);
+
+ if (hop4_addr && !put_pte(ctx, hop4_addr))
+ clear_hop3 = 1;
+
+ if (!clear_hop3)
+ goto flush;
+ clear_pte(hdev, hop3_pte_addr);
+
+ if (put_pte(ctx, hop3_addr))
+ goto flush;
+ clear_pte(hdev, hop2_pte_addr);
+
+ if (put_pte(ctx, hop2_addr))
+ goto flush;
+ clear_pte(hdev, hop1_pte_addr);
+
+ if (put_pte(ctx, hop1_addr))
+ goto flush;
+ clear_pte(hdev, hop0_pte_addr);
+ }
+
+flush:
+ /* flush all writes from all cores to reach PCI */
+ mb();
+
+ hdev->asic_funcs->read_pte(hdev,
+ hop4_addr ? hop4_pte_addr : hop3_pte_addr);
+
+ return 0;
+
+not_mapped:
+ dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n",
+ virt_addr);
+
+ return -EINVAL;
+}
+
+/*
+ * hl_mmu_unmap - unmaps a virtual addr
+ *
+ * @ctx: pointer to the context structure
+ * @virt_addr: virt addr to map from
+ * @page_size: size of the page to unmap
+ *
+ * This function does the following:
+ * - Check that the virt addr is mapped
+ * - Unmap the virt addr and frees pgts if possible
+ * - Returns 0 on success, -EINVAL if the given addr is not mapped
+ *
+ * Because this function changes the page tables in the device and because it
+ * changes the MMU hash, it must be protected by a lock.
+ * However, because it maps only a single page, the lock should be implemented
+ * in a higher level in order to protect the entire mapping of the memory area
+ */
+int hl_mmu_unmap(struct hl_ctx *ctx, u64 virt_addr, u32 page_size)
+{
+ struct hl_device *hdev = ctx->hdev;
+ u64 real_virt_addr;
+ u32 real_page_size, npages;
+ int i, rc;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ /*
+ * The H/W handles mapping of 4KB/2MB page. Hence if the host page size
+ * is bigger, we break it to sub-pages and unmap them separately.
+ */
+ if ((page_size % PAGE_SIZE_2MB) == 0) {
+ real_page_size = PAGE_SIZE_2MB;
+ } else if ((page_size % PAGE_SIZE_4KB) == 0) {
+ real_page_size = PAGE_SIZE_4KB;
+ } else {
+ dev_err(hdev->dev,
+ "page size of %u is not 4KB nor 2MB aligned, can't unmap\n",
+ page_size);
+
+ return -EFAULT;
+ }
+
+ npages = page_size / real_page_size;
+ real_virt_addr = virt_addr;
+
+ for (i = 0 ; i < npages ; i++) {
+ rc = _hl_mmu_unmap(ctx, real_virt_addr);
+ if (rc)
+ return rc;
+
+ real_virt_addr += real_page_size;
+ }
+
+ return 0;
+}
+
+static int _hl_mmu_map(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr,
+ u32 page_size)
+{
+ struct hl_device *hdev = ctx->hdev;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ u64 hop0_addr = 0, hop0_pte_addr = 0,
+ hop1_addr = 0, hop1_pte_addr = 0,
+ hop2_addr = 0, hop2_pte_addr = 0,
+ hop3_addr = 0, hop3_pte_addr = 0,
+ hop4_addr = 0, hop4_pte_addr = 0,
+ curr_pte = 0;
+ bool hop1_new = false, hop2_new = false, hop3_new = false,
+ hop4_new = false, is_huge, is_dram_addr,
+ is_dram_default_page_mapping;
+ int rc = -ENOMEM;
+
+ /*
+ * This mapping function can map a 4KB/2MB page. For 2MB page there are
+ * only 3 hops rather than 4. Currently the DRAM allocation uses 2MB
+ * pages only but user memory could have been allocated with one of the
+ * two page sizes. Since this is a common code for all the three cases,
+ * we need this hugs page check.
+ */
+ is_huge = page_size == PAGE_SIZE_2MB;
+
+ is_dram_addr = hl_mem_area_inside_range(virt_addr, page_size,
+ prop->va_space_dram_start_address,
+ prop->va_space_dram_end_address);
+
+ if (is_dram_addr && !is_huge) {
+ dev_err(hdev->dev, "DRAM mapping should use huge pages only\n");
+ return -EFAULT;
+ }
+
+ is_dram_default_page_mapping =
+ hdev->dram_default_page_mapping && is_dram_addr;
+
+ hop0_addr = get_hop0_addr(ctx);
+
+ hop0_pte_addr = get_hop0_pte_addr(ctx, hop0_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop0_pte_addr);
+
+ hop1_addr = get_alloc_next_hop_addr(ctx, curr_pte, &hop1_new);
+
+ if (hop1_addr == ULLONG_MAX)
+ goto err;
+
+ hop1_pte_addr = get_hop1_pte_addr(ctx, hop1_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop1_pte_addr);
+
+ hop2_addr = get_alloc_next_hop_addr(ctx, curr_pte, &hop2_new);
+
+ if (hop2_addr == ULLONG_MAX)
+ goto err;
+
+ hop2_pte_addr = get_hop2_pte_addr(ctx, hop2_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop2_pte_addr);
+
+ hop3_addr = get_alloc_next_hop_addr(ctx, curr_pte, &hop3_new);
+
+ if (hop3_addr == ULLONG_MAX)
+ goto err;
+
+ hop3_pte_addr = get_hop3_pte_addr(ctx, hop3_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop3_pte_addr);
+
+ if (!is_huge) {
+ hop4_addr = get_alloc_next_hop_addr(ctx, curr_pte, &hop4_new);
+
+ if (hop4_addr == ULLONG_MAX)
+ goto err;
+
+ hop4_pte_addr = get_hop4_pte_addr(ctx, hop4_addr, virt_addr);
+
+ curr_pte = hdev->asic_funcs->read_pte(hdev, hop4_pte_addr);
+ }
+
+ if (is_dram_default_page_mapping) {
+ u64 zero_pte = (prop->mmu_dram_default_page_addr &
+ PTE_PHYS_ADDR_MASK) | LAST_MASK |
+ PAGE_PRESENT_MASK;
+
+ if (curr_pte != zero_pte) {
+ dev_err(hdev->dev,
+ "DRAM: mapping already exists for virt_addr 0x%llx\n",
+ virt_addr);
+ rc = -EINVAL;
+ goto err;
+ }
+
+ if (hop1_new || hop2_new || hop3_new || hop4_new) {
+ dev_err(hdev->dev,
+ "DRAM mapping should not allocate more hops\n");
+ rc = -EFAULT;
+ goto err;
+ }
+ } else if (curr_pte & PAGE_PRESENT_MASK) {
+ dev_err(hdev->dev,
+ "mapping already exists for virt_addr 0x%llx\n",
+ virt_addr);
+
+ dev_dbg(hdev->dev, "hop0 pte: 0x%llx (0x%llx)\n",
+ hdev->asic_funcs->read_pte(hdev, hop0_pte_addr),
+ hop0_pte_addr);
+ dev_dbg(hdev->dev, "hop1 pte: 0x%llx (0x%llx)\n",
+ hdev->asic_funcs->read_pte(hdev, hop1_pte_addr),
+ hop1_pte_addr);
+ dev_dbg(hdev->dev, "hop2 pte: 0x%llx (0x%llx)\n",
+ hdev->asic_funcs->read_pte(hdev, hop2_pte_addr),
+ hop2_pte_addr);
+ dev_dbg(hdev->dev, "hop3 pte: 0x%llx (0x%llx)\n",
+ hdev->asic_funcs->read_pte(hdev, hop3_pte_addr),
+ hop3_pte_addr);
+
+ if (!is_huge)
+ dev_dbg(hdev->dev, "hop4 pte: 0x%llx (0x%llx)\n",
+ hdev->asic_funcs->read_pte(hdev,
+ hop4_pte_addr),
+ hop4_pte_addr);
+
+ rc = -EINVAL;
+ goto err;
+ }
+
+ curr_pte = (phys_addr & PTE_PHYS_ADDR_MASK) | LAST_MASK
+ | PAGE_PRESENT_MASK;
+
+ hdev->asic_funcs->write_pte(hdev,
+ is_huge ? hop3_pte_addr : hop4_pte_addr,
+ curr_pte);
+
+ if (hop1_new) {
+ curr_pte = (hop1_addr & PTE_PHYS_ADDR_MASK) |
+ PAGE_PRESENT_MASK;
+ ctx->hdev->asic_funcs->write_pte(ctx->hdev, hop0_pte_addr,
+ curr_pte);
+ }
+ if (hop2_new) {
+ curr_pte = (hop2_addr & PTE_PHYS_ADDR_MASK) |
+ PAGE_PRESENT_MASK;
+ ctx->hdev->asic_funcs->write_pte(ctx->hdev, hop1_pte_addr,
+ curr_pte);
+ get_pte(ctx, hop1_addr);
+ }
+ if (hop3_new) {
+ curr_pte = (hop3_addr & PTE_PHYS_ADDR_MASK) |
+ PAGE_PRESENT_MASK;
+ ctx->hdev->asic_funcs->write_pte(ctx->hdev, hop2_pte_addr,
+ curr_pte);
+ get_pte(ctx, hop2_addr);
+ }
+
+ if (!is_huge) {
+ if (hop4_new) {
+ curr_pte = (hop4_addr & PTE_PHYS_ADDR_MASK) |
+ PAGE_PRESENT_MASK;
+ ctx->hdev->asic_funcs->write_pte(ctx->hdev,
+ hop3_pte_addr, curr_pte);
+ get_pte(ctx, hop3_addr);
+ }
+
+ get_pte(ctx, hop4_addr);
+ } else {
+ get_pte(ctx, hop3_addr);
+ }
+
+ /* flush all writes from all cores to reach PCI */
+ mb();
+
+ hdev->asic_funcs->read_pte(hdev,
+ is_huge ? hop3_pte_addr : hop4_pte_addr);
+
+ return 0;
+
+err:
+ if (hop4_new)
+ free_hop(ctx, hop4_addr);
+ if (hop3_new)
+ free_hop(ctx, hop3_addr);
+ if (hop2_new)
+ free_hop(ctx, hop2_addr);
+ if (hop1_new)
+ free_hop(ctx, hop1_addr);
+
+ return rc;
+}
+
+/*
+ * hl_mmu_map - maps a virtual addr to physical addr
+ *
+ * @ctx: pointer to the context structure
+ * @virt_addr: virt addr to map from
+ * @phys_addr: phys addr to map to
+ * @page_size: physical page size
+ *
+ * This function does the following:
+ * - Check that the virt addr is not mapped
+ * - Allocate pgts as necessary in order to map the virt addr to the phys
+ * - Returns 0 on success, -EINVAL if addr is already mapped, or -ENOMEM.
+ *
+ * Because this function changes the page tables in the device and because it
+ * changes the MMU hash, it must be protected by a lock.
+ * However, because it maps only a single page, the lock should be implemented
+ * in a higher level in order to protect the entire mapping of the memory area
+ */
+int hl_mmu_map(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr, u32 page_size)
+{
+ struct hl_device *hdev = ctx->hdev;
+ u64 real_virt_addr;
+ u32 real_page_size, npages;
+ int i, rc, mapped_cnt = 0;
+
+ if (!hdev->mmu_enable)
+ return 0;
+
+ /*
+ * The H/W handles mapping of 4KB/2MB page. Hence if the host page size
+ * is bigger, we break it to sub-pages and map them separately.
+ */
+ if ((page_size % PAGE_SIZE_2MB) == 0) {
+ real_page_size = PAGE_SIZE_2MB;
+ } else if ((page_size % PAGE_SIZE_4KB) == 0) {
+ real_page_size = PAGE_SIZE_4KB;
+ } else {
+ dev_err(hdev->dev,
+ "page size of %u is not 4KB nor 2MB aligned, can't map\n",
+ page_size);
+
+ return -EFAULT;
+ }
+
+ npages = page_size / real_page_size;
+ real_virt_addr = virt_addr;
+
+ for (i = 0 ; i < npages ; i++) {
+ rc = _hl_mmu_map(ctx, real_virt_addr, phys_addr,
+ real_page_size);
+ if (rc)
+ goto err;
+
+ real_virt_addr += real_page_size;
+ mapped_cnt++;
+ }
+
+ return 0;
+
+err:
+ real_virt_addr = virt_addr;
+ for (i = 0 ; i < mapped_cnt ; i++) {
+ if (_hl_mmu_unmap(ctx, real_virt_addr))
+ dev_warn_ratelimited(hdev->dev,
+ "failed to unmap va: 0x%llx\n", real_virt_addr);
+
+ real_virt_addr += real_page_size;
+ }
+
+ return rc;
+}
+
+/*
+ * hl_mmu_swap_out - marks all mapping of the given ctx as swapped out
+ *
+ * @ctx: pointer to the context structure
+ *
+ */
+void hl_mmu_swap_out(struct hl_ctx *ctx)
+{
+
+}
+
+/*
+ * hl_mmu_swap_in - marks all mapping of the given ctx as swapped in
+ *
+ * @ctx: pointer to the context structure
+ *
+ */
+void hl_mmu_swap_in(struct hl_ctx *ctx)
+{
+
+}
diff --git a/drivers/misc/habanalabs/sysfs.c b/drivers/misc/habanalabs/sysfs.c
new file mode 100644
index 000000000000..c900ab15cceb
--- /dev/null
+++ b/drivers/misc/habanalabs/sysfs.c
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2016-2019 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ */
+
+#include "habanalabs.h"
+
+#include <linux/pci.h>
+
+#define SET_CLK_PKT_TIMEOUT 1000000 /* 1s */
+#define SET_PWR_PKT_TIMEOUT 1000000 /* 1s */
+
+long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ if (curr)
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_CURR_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ else
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.pll_index = __cpu_to_le32(pll_index);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SET_CLK_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to get frequency of PLL %d, error %d\n",
+ pll_index, rc);
+ result = rc;
+ }
+
+ return result;
+}
+
+void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_SET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.pll_index = __cpu_to_le32(pll_index);
+ pkt.value = __cpu_to_le64(freq);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SET_CLK_PKT_TIMEOUT, NULL);
+
+ if (rc)
+ dev_err(hdev->dev,
+ "Failed to set frequency to PLL %d, error %d\n",
+ pll_index, rc);
+}
+
+u64 hl_get_max_power(struct hl_device *hdev)
+{
+ struct armcp_packet pkt;
+ long result;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_MAX_POWER_GET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SET_PWR_PKT_TIMEOUT, &result);
+
+ if (rc) {
+ dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
+ result = rc;
+ }
+
+ return result;
+}
+
+void hl_set_max_power(struct hl_device *hdev, u64 value)
+{
+ struct armcp_packet pkt;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.ctl = __cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
+ ARMCP_PKT_CTL_OPCODE_SHIFT);
+ pkt.value = __cpu_to_le64(value);
+
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+ SET_PWR_PKT_TIMEOUT, NULL);
+
+ if (rc)
+ dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
+}
+
+static ssize_t pm_mng_profile_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n",
+ (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
+ (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
+ "unknown");
+}
+
+static ssize_t pm_mng_profile_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto out;
+ }
+
+ mutex_lock(&hdev->fd_open_cnt_lock);
+
+ if (atomic_read(&hdev->fd_open_cnt) > 0) {
+ dev_err(hdev->dev,
+ "Can't change PM profile while user process is opened on the device\n");
+ count = -EPERM;
+ goto unlock_mutex;
+ }
+
+ if (strncmp("auto", buf, strlen("auto")) == 0) {
+ /* Make sure we are in LOW PLL when changing modes */
+ if (hdev->pm_mng_profile == PM_MANUAL) {
+ atomic_set(&hdev->curr_pll_profile, PLL_HIGH);
+ hl_device_set_frequency(hdev, PLL_LOW);
+ hdev->pm_mng_profile = PM_AUTO;
+ }
+ } else if (strncmp("manual", buf, strlen("manual")) == 0) {
+ /* Make sure we are in LOW PLL when changing modes */
+ if (hdev->pm_mng_profile == PM_AUTO) {
+ flush_delayed_work(&hdev->work_freq);
+ hdev->pm_mng_profile = PM_MANUAL;
+ }
+ } else {
+ dev_err(hdev->dev, "value should be auto or manual\n");
+ count = -EINVAL;
+ goto unlock_mutex;
+ }
+
+unlock_mutex:
+ mutex_unlock(&hdev->fd_open_cnt_lock);
+out:
+ return count;
+}
+
+static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ return sprintf(buf, "%u\n", hdev->high_pll);
+}
+
+static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto out;
+ }
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto out;
+ }
+
+ hdev->high_pll = value;
+
+out:
+ return count;
+}
+
+static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
+}
+
+static ssize_t armcp_kernel_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s", hdev->asic_prop.armcp_info.kernel_version);
+}
+
+static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.armcp_version);
+}
+
+static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "0x%08x\n",
+ hdev->asic_prop.armcp_info.cpld_version);
+}
+
+static ssize_t infineon_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "0x%04x\n",
+ hdev->asic_prop.armcp_info.infineon_version);
+}
+
+static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.fuse_version);
+}
+
+static ssize_t thermal_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s", hdev->asic_prop.armcp_info.thermal_version);
+}
+
+static ssize_t preboot_btl_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
+}
+
+static ssize_t soft_reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+ int rc;
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto out;
+ }
+
+ hl_device_reset(hdev, false, false);
+
+out:
+ return count;
+}
+
+static ssize_t hard_reset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long value;
+ int rc;
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto out;
+ }
+
+ hl_device_reset(hdev, true, false);
+
+out:
+ return count;
+}
+
+static ssize_t device_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ char *str;
+
+ switch (hdev->asic_type) {
+ case ASIC_GOYA:
+ str = "GOYA";
+ break;
+ default:
+ dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
+ hdev->asic_type);
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%s\n", str);
+}
+
+static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ /* Use dummy, fixed address for simulator */
+ if (!hdev->pdev)
+ return sprintf(buf, "0000:%02d:00.0\n", hdev->id);
+
+ return sprintf(buf, "%04x:%02x:%02x.%x\n",
+ pci_domain_nr(hdev->pdev->bus),
+ hdev->pdev->bus->number,
+ PCI_SLOT(hdev->pdev->devfn),
+ PCI_FUNC(hdev->pdev->devfn));
+}
+
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ char *str;
+
+ if (atomic_read(&hdev->in_reset))
+ str = "In reset";
+ else if (hdev->disabled)
+ str = "Malfunction";
+ else
+ str = "Operational";
+
+ return sprintf(buf, "%s\n", str);
+}
+
+static ssize_t write_open_cnt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", hdev->user_ctx ? 1 : 0);
+}
+
+static ssize_t soft_reset_cnt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
+}
+
+static ssize_t hard_reset_cnt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
+}
+
+static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ long val;
+
+ if (hl_device_disabled_or_in_reset(hdev))
+ return -ENODEV;
+
+ val = hl_get_max_power(hdev);
+
+ return sprintf(buf, "%lu\n", val);
+}
+
+static ssize_t max_power_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ unsigned long value;
+ int rc;
+
+ if (hl_device_disabled_or_in_reset(hdev)) {
+ count = -ENODEV;
+ goto out;
+ }
+
+ rc = kstrtoul(buf, 0, &value);
+
+ if (rc) {
+ count = -EINVAL;
+ goto out;
+ }
+
+ hdev->max_power = value;
+ hl_set_max_power(hdev, value);
+
+out:
+ return count;
+}
+
+static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset,
+ size_t max_size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct hl_device *hdev = dev_get_drvdata(dev);
+ char *data;
+ int rc;
+
+ if (!max_size)
+ return -EINVAL;
+
+ data = kzalloc(max_size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
+ if (rc)
+ goto out;
+
+ memcpy(buf, data, max_size);
+
+out:
+ kfree(data);
+
+ return max_size;
+}
+
+static DEVICE_ATTR_RO(armcp_kernel_ver);
+static DEVICE_ATTR_RO(armcp_ver);
+static DEVICE_ATTR_RO(cpld_ver);
+static DEVICE_ATTR_RO(device_type);
+static DEVICE_ATTR_RO(fuse_ver);
+static DEVICE_ATTR_WO(hard_reset);
+static DEVICE_ATTR_RO(hard_reset_cnt);
+static DEVICE_ATTR_RW(high_pll);
+static DEVICE_ATTR_RO(infineon_ver);
+static DEVICE_ATTR_RW(max_power);
+static DEVICE_ATTR_RO(pci_addr);
+static DEVICE_ATTR_RW(pm_mng_profile);
+static DEVICE_ATTR_RO(preboot_btl_ver);
+static DEVICE_ATTR_WO(soft_reset);
+static DEVICE_ATTR_RO(soft_reset_cnt);
+static DEVICE_ATTR_RO(status);
+static DEVICE_ATTR_RO(thermal_ver);
+static DEVICE_ATTR_RO(uboot_ver);
+static DEVICE_ATTR_RO(write_open_cnt);
+
+static struct bin_attribute bin_attr_eeprom = {
+ .attr = {.name = "eeprom", .mode = (0444)},
+ .size = PAGE_SIZE,
+ .read = eeprom_read_handler
+};
+
+static struct attribute *hl_dev_attrs[] = {
+ &dev_attr_armcp_kernel_ver.attr,
+ &dev_attr_armcp_ver.attr,
+ &dev_attr_cpld_ver.attr,
+ &dev_attr_device_type.attr,
+ &dev_attr_fuse_ver.attr,
+ &dev_attr_hard_reset.attr,
+ &dev_attr_hard_reset_cnt.attr,
+ &dev_attr_high_pll.attr,
+ &dev_attr_infineon_ver.attr,
+ &dev_attr_max_power.attr,
+ &dev_attr_pci_addr.attr,
+ &dev_attr_pm_mng_profile.attr,
+ &dev_attr_preboot_btl_ver.attr,
+ &dev_attr_soft_reset.attr,
+ &dev_attr_soft_reset_cnt.attr,
+ &dev_attr_status.attr,
+ &dev_attr_thermal_ver.attr,
+ &dev_attr_uboot_ver.attr,
+ &dev_attr_write_open_cnt.attr,
+ NULL,
+};
+
+static struct bin_attribute *hl_dev_bin_attrs[] = {
+ &bin_attr_eeprom,
+ NULL
+};
+
+static struct attribute_group hl_dev_attr_group = {
+ .attrs = hl_dev_attrs,
+ .bin_attrs = hl_dev_bin_attrs,
+};
+
+static struct attribute_group hl_dev_clks_attr_group;
+
+static const struct attribute_group *hl_dev_attr_groups[] = {
+ &hl_dev_attr_group,
+ &hl_dev_clks_attr_group,
+ NULL,
+};
+
+int hl_sysfs_init(struct hl_device *hdev)
+{
+ int rc;
+
+ hdev->pm_mng_profile = PM_AUTO;
+ hdev->max_power = hdev->asic_prop.max_power_default;
+
+ hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
+
+ rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
+ if (rc) {
+ dev_err(hdev->dev,
+ "Failed to add groups to device, error %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+void hl_sysfs_fini(struct hl_device *hdev)
+{
+ device_remove_groups(hdev->dev, hl_dev_attr_groups);
+}
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index e9c9ef52c76a..927309b86bab 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -29,6 +29,13 @@ static struct class *ilo_class;
static unsigned int ilo_major;
static unsigned int max_ccb = 16;
static char ilo_hwdev[MAX_ILO_DEV];
+static const struct pci_device_id ilo_blacklist[] = {
+ /* auxiliary iLO */
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3307, PCI_VENDOR_ID_HP, 0x1979)},
+ /* CL */
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3307, PCI_VENDOR_ID_HP_3PAR, 0x0289)},
+ {}
+};
static inline int get_entry_id(int entry)
{
@@ -763,9 +770,10 @@ static int ilo_probe(struct pci_dev *pdev,
int devnum, minor, start, error = 0;
struct ilo_hwinfo *ilo_hw;
- /* Ignore subsystem_device = 0x1979 (set by BIOS) */
- if (pdev->subsystem_device == 0x1979)
- return 0;
+ if (pci_match_id(ilo_blacklist, pdev)) {
+ dev_dbg(&pdev->dev, "Not supported on this device\n");
+ return -ENODEV;
+ }
if (max_ccb > MAX_CCB)
max_ccb = MAX_CCB;
diff --git a/drivers/misc/ibmvmc.c b/drivers/misc/ibmvmc.c
index b8aaa684c397..2ed23c99f59f 100644
--- a/drivers/misc/ibmvmc.c
+++ b/drivers/misc/ibmvmc.c
@@ -820,21 +820,24 @@ static int ibmvmc_send_msg(struct crq_server_adapter *adapter,
*
* Return:
* 0 - Success
+ * Non-zero - Failure
*/
static int ibmvmc_open(struct inode *inode, struct file *file)
{
struct ibmvmc_file_session *session;
- int rc = 0;
pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__,
(unsigned long)inode, (unsigned long)file,
ibmvmc.state);
session = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ return -ENOMEM;
+
session->file = file;
file->private_data = session;
- return rc;
+ return 0;
}
/**
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c
index 81a0541ef3ac..294fb2f66bfe 100644
--- a/drivers/misc/ics932s401.c
+++ b/drivers/misc/ics932s401.c
@@ -146,6 +146,8 @@ static struct ics932s401_data *ics932s401_update_device(struct device *dev)
*/
for (i = 0; i < NUM_MIRRORED_REGS; i++) {
temp = i2c_smbus_read_word_data(client, regs_to_copy[i]);
+ if (temp < 0)
+ data->regs[regs_to_copy[i]] = 0;
data->regs[regs_to_copy[i]] = temp >> 8;
}
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index 2837dc77478e..b51cf182b031 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -37,16 +37,9 @@
#include <linux/kprobes.h>
#include <linux/list.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
#include <linux/slab.h>
-#include <scsi/scsi_cmnd.h>
#include <linux/debugfs.h>
-#ifdef CONFIG_IDE
-#include <linux/ide.h>
-#endif
-
#define DEFAULT_COUNT 10
static int lkdtm_debugfs_open(struct inode *inode, struct file *file);
@@ -102,9 +95,7 @@ static struct crashpoint crashpoints[] = {
CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"),
CRASHPOINT("TIMERADD", "hrtimer_start"),
CRASHPOINT("SCSI_DISPATCH_CMD", "scsi_dispatch_cmd"),
-# ifdef CONFIG_IDE
CRASHPOINT("IDE_CORE_CP", "generic_ide_ioctl"),
-# endif
#endif
};
@@ -152,7 +143,9 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(EXEC_VMALLOC),
CRASHTYPE(EXEC_RODATA),
CRASHTYPE(EXEC_USERSPACE),
+ CRASHTYPE(EXEC_NULL),
CRASHTYPE(ACCESS_USERSPACE),
+ CRASHTYPE(ACCESS_NULL),
CRASHTYPE(WRITE_RO),
CRASHTYPE(WRITE_RO_AFTER_INIT),
CRASHTYPE(WRITE_KERN),
@@ -347,9 +340,9 @@ static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
+ n = scnprintf(buf, PAGE_SIZE, "Available crash types:\n");
for (i = 0; i < ARRAY_SIZE(crashtypes); i++) {
- n += snprintf(buf + n, PAGE_SIZE - n, "%s\n",
+ n += scnprintf(buf + n, PAGE_SIZE - n, "%s\n",
crashtypes[i].name);
}
buf[n] = '\0';
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 3c6fd327e166..b69ee004a3f7 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -45,7 +45,9 @@ void lkdtm_EXEC_KMALLOC(void);
void lkdtm_EXEC_VMALLOC(void);
void lkdtm_EXEC_RODATA(void);
void lkdtm_EXEC_USERSPACE(void);
+void lkdtm_EXEC_NULL(void);
void lkdtm_ACCESS_USERSPACE(void);
+void lkdtm_ACCESS_NULL(void);
/* lkdtm_refcount.c */
void lkdtm_REFCOUNT_INC_OVERFLOW(void);
diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c
index 53b85c9d16b8..62f76d506f04 100644
--- a/drivers/misc/lkdtm/perms.c
+++ b/drivers/misc/lkdtm/perms.c
@@ -47,7 +47,7 @@ static noinline void execute_location(void *dst, bool write)
{
void (*func)(void) = dst;
- pr_info("attempting ok execution at %p\n", do_nothing);
+ pr_info("attempting ok execution at %px\n", do_nothing);
do_nothing();
if (write == CODE_WRITE) {
@@ -55,7 +55,7 @@ static noinline void execute_location(void *dst, bool write)
flush_icache_range((unsigned long)dst,
(unsigned long)dst + EXEC_SIZE);
}
- pr_info("attempting bad execution at %p\n", func);
+ pr_info("attempting bad execution at %px\n", func);
func();
}
@@ -66,14 +66,14 @@ static void execute_user_location(void *dst)
/* Intentionally crossing kernel/user memory boundary. */
void (*func)(void) = dst;
- pr_info("attempting ok execution at %p\n", do_nothing);
+ pr_info("attempting ok execution at %px\n", do_nothing);
do_nothing();
copied = access_process_vm(current, (unsigned long)dst, do_nothing,
EXEC_SIZE, FOLL_WRITE);
if (copied < EXEC_SIZE)
return;
- pr_info("attempting bad execution at %p\n", func);
+ pr_info("attempting bad execution at %px\n", func);
func();
}
@@ -82,7 +82,7 @@ void lkdtm_WRITE_RO(void)
/* Explicitly cast away "const" for the test. */
unsigned long *ptr = (unsigned long *)&rodata;
- pr_info("attempting bad rodata write at %p\n", ptr);
+ pr_info("attempting bad rodata write at %px\n", ptr);
*ptr ^= 0xabcd1234;
}
@@ -100,7 +100,7 @@ void lkdtm_WRITE_RO_AFTER_INIT(void)
return;
}
- pr_info("attempting bad ro_after_init write at %p\n", ptr);
+ pr_info("attempting bad ro_after_init write at %px\n", ptr);
*ptr ^= 0xabcd1234;
}
@@ -112,7 +112,7 @@ void lkdtm_WRITE_KERN(void)
size = (unsigned long)do_overwritten - (unsigned long)do_nothing;
ptr = (unsigned char *)do_overwritten;
- pr_info("attempting bad %zu byte write at %p\n", size, ptr);
+ pr_info("attempting bad %zu byte write at %px\n", size, ptr);
memcpy(ptr, (unsigned char *)do_nothing, size);
flush_icache_range((unsigned long)ptr, (unsigned long)(ptr + size));
@@ -164,6 +164,11 @@ void lkdtm_EXEC_USERSPACE(void)
vm_munmap(user_addr, PAGE_SIZE);
}
+void lkdtm_EXEC_NULL(void)
+{
+ execute_location(NULL, CODE_AS_IS);
+}
+
void lkdtm_ACCESS_USERSPACE(void)
{
unsigned long user_addr, tmp = 0;
@@ -185,16 +190,29 @@ void lkdtm_ACCESS_USERSPACE(void)
ptr = (unsigned long *)user_addr;
- pr_info("attempting bad read at %p\n", ptr);
+ pr_info("attempting bad read at %px\n", ptr);
tmp = *ptr;
tmp += 0xc0dec0de;
- pr_info("attempting bad write at %p\n", ptr);
+ pr_info("attempting bad write at %px\n", ptr);
*ptr = tmp;
vm_munmap(user_addr, PAGE_SIZE);
}
+void lkdtm_ACCESS_NULL(void)
+{
+ unsigned long tmp;
+ unsigned long *ptr = (unsigned long *)NULL;
+
+ pr_info("attempting bad read at %px\n", ptr);
+ tmp = *ptr;
+ tmp += 0xc0dec0de;
+
+ pr_info("attempting bad write at %px\n", ptr);
+ *ptr = tmp;
+}
+
void __init lkdtm_perms_init(void)
{
/* Make sure we can write to __ro_after_init values during __init */
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index c49e1d2269af..74e2c667dce0 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -43,3 +43,13 @@ config INTEL_MEI_TXE
Supported SoCs:
Intel Bay Trail
+
+config INTEL_MEI_HDCP
+ tristate "Intel HDCP2.2 services of ME Interface"
+ select INTEL_MEI_ME
+ depends on DRM_I915
+ help
+ MEI Support for HDCP2.2 Services on Intel platforms.
+
+ Enables the ME FW services required for HDCP2.2 support through
+ I915 display driver of Intel.
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index d9215fc4e499..8c2d9565a4cb 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -24,3 +24,5 @@ mei-txe-objs += hw-txe.o
mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
CFLAGS_mei-trace.o = -I$(src)
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 80215c312f0e..5fcac02233af 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -40,6 +40,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
#define MEI_UUID_MKHIF_FIX UUID_LE(0x55213584, 0x9a29, 0x4916, \
0xba, 0xdf, 0xf, 0xb7, 0xed, 0x68, 0x2a, 0xeb)
+#define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, \
+ 0xA5, 0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04)
+
#define MEI_UUID_ANY NULL_UUID_LE
/**
@@ -71,6 +74,18 @@ static void blacklist(struct mei_cl_device *cldev)
cldev->do_match = 0;
}
+/**
+ * whitelist - forcefully whitelist client
+ *
+ * @cldev: me clients device
+ */
+static void whitelist(struct mei_cl_device *cldev)
+{
+ dev_dbg(&cldev->dev, "running hook %s\n", __func__);
+
+ cldev->do_match = 1;
+}
+
#define OSTYPE_LINUX 2
struct mei_os_ver {
__le16 build;
@@ -472,6 +487,7 @@ static struct mei_fixup {
MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc),
MEI_FIXUP(MEI_UUID_WD, mei_wd),
MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
+ MEI_FIXUP(MEI_UUID_HDCP, whitelist),
};
/**
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc3872fe7b25..65bec998eb6e 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -28,7 +28,6 @@
#include "client.h"
#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
-#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
/**
* __mei_cl_send - internal client send (write)
@@ -541,17 +540,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
goto out;
}
- if (!mei_cl_bus_module_get(cldev)) {
- dev_err(&cldev->dev, "get hw module failed");
- ret = -ENODEV;
- goto out;
- }
-
ret = mei_cl_connect(cl, cldev->me_cl, NULL);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&cldev->dev, "cannot connect\n");
- mei_cl_bus_module_put(cldev);
- }
out:
mutex_unlock(&bus->device_lock);
@@ -614,7 +605,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
if (err < 0)
dev_err(bus->dev, "Could not disconnect from the ME client\n");
- mei_cl_bus_module_put(cldev);
out:
/* Flush queues and remove any pending read */
mei_cl_flush_queues(cl, NULL);
@@ -725,9 +715,16 @@ static int mei_cl_device_probe(struct device *dev)
if (!id)
return -ENODEV;
+ if (!mei_cl_bus_module_get(cldev)) {
+ dev_err(&cldev->dev, "get hw module failed");
+ return -ENODEV;
+ }
+
ret = cldrv->probe(cldev, id);
- if (ret)
+ if (ret) {
+ mei_cl_bus_module_put(cldev);
return ret;
+ }
__module_get(THIS_MODULE);
return 0;
@@ -755,6 +752,7 @@ static int mei_cl_device_remove(struct device *dev)
mei_cldev_unregister_callbacks(cldev);
+ mei_cl_bus_module_put(cldev);
module_put(THIS_MODULE);
dev->driver = NULL;
return ret;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 1fc8ea0f519b..ca4c9cc218a2 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head,
struct mei_cl_cb *cb, *next;
list_for_each_entry_safe(cb, next, head, list) {
- if (cl == cb->cl)
+ if (cl == cb->cl) {
list_del_init(&cb->list);
+ if (cb->fop_type == MEI_FOP_READ)
+ mei_io_cb_free(cb);
+ }
}
}
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 78c26cebf5d4..e6207f614816 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -1029,29 +1029,36 @@ static void mei_hbm_config_features(struct mei_device *dev)
dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
dev->hbm_f_pg_supported = 1;
+ dev->hbm_f_dc_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
dev->hbm_f_dc_supported = 1;
+ dev->hbm_f_ie_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_IE)
dev->hbm_f_ie_supported = 1;
/* disconnect on connect timeout instead of link reset */
+ dev->hbm_f_dot_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
dev->hbm_f_dot_supported = 1;
/* Notification Event Support */
+ dev->hbm_f_ev_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
dev->hbm_f_ev_supported = 1;
/* Fixed Address Client Support */
+ dev->hbm_f_fa_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
dev->hbm_f_fa_supported = 1;
/* OS ver message Support */
+ dev->hbm_f_os_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
dev->hbm_f_os_supported = 1;
/* DMA Ring Support */
+ dev->hbm_f_dr_supported = 0;
if (dev->version.major_version > HBM_MAJOR_VERSION_DR ||
(dev->version.major_version == HBM_MAJOR_VERSION_DR &&
dev->version.minor_version >= HBM_MINOR_VERSION_DR))
@@ -1187,9 +1194,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
if (dma_setup_res->status) {
- dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
- dma_setup_res->status,
- mei_hbm_status_str(dma_setup_res->status));
+ u8 status = dma_setup_res->status;
+
+ if (status == MEI_HBMS_NOT_ALLOWED) {
+ dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
+ } else {
+ dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
+ status,
+ mei_hbm_status_str(status));
+ }
dev->hbm_f_dr_supported = 0;
mei_dmam_ring_free(dev);
}
diff --git a/drivers/misc/mei/hdcp/Makefile b/drivers/misc/mei/hdcp/Makefile
new file mode 100644
index 000000000000..adbe7506282d
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2019, Intel Corporation.
+#
+# Makefile - HDCP client driver for Intel MEI Bus Driver.
+
+obj-$(CONFIG_INTEL_MEI_HDCP) += mei_hdcp.o
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
new file mode 100644
index 000000000000..90b6ae8e9dae
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -0,0 +1,849 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Mei_hdcp.c: HDCP client driver for mei bus
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+/**
+ * DOC: MEI_HDCP Client Driver
+ *
+ * This is a client driver to the mei_bus to make the HDCP2.2 services of
+ * ME FW available for the interested consumers like I915.
+ *
+ * This module will act as a translation layer between HDCP protocol
+ * implementor(I915) and ME FW by translating HDCP2.2 authentication
+ * messages to ME FW command payloads and vice versa.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <linux/mei_cl_bus.h>
+#include <linux/component.h>
+#include <drm/drm_connector.h>
+#include <drm/i915_component.h>
+#include <drm/i915_mei_hdcp_interface.h>
+
+#include "mei_hdcp.h"
+
+static inline u8 mei_get_ddi_index(enum port port)
+{
+ switch (port) {
+ case PORT_A:
+ return MEI_DDI_A;
+ case PORT_B ... PORT_F:
+ return (u8)port;
+ default:
+ return MEI_DDI_INVALID_PORT;
+ }
+}
+
+/**
+ * mei_hdcp_initiate_session() - Initiate a Wired HDCP2.2 Tx Session in ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @ake_data: AKE_Init msg output.
+ *
+ * Return: 0 on Success, <0 on Failure.
+ */
+static int
+mei_hdcp_initiate_session(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_init *ake_data)
+{
+ struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
+ struct wired_cmd_initiate_hdcp2_session_out
+ session_init_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !ake_data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ session_init_in.header.api_version = HDCP_API_VERSION;
+ session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
+ session_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ session_init_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
+
+ session_init_in.port.integrated_port_type = data->port_type;
+ session_init_in.port.physical_port = mei_get_ddi_index(data->port);
+ session_init_in.protocol = data->protocol;
+
+ byte = mei_cldev_send(cldev, (u8 *)&session_init_in,
+ sizeof(session_init_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&session_init_out,
+ sizeof(session_init_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (session_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_INITIATE_HDCP2_SESSION,
+ session_init_out.header.status);
+ return -EIO;
+ }
+
+ ake_data->msg_id = HDCP_2_2_AKE_INIT;
+ ake_data->tx_caps = session_init_out.tx_caps;
+ memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_verify_receiver_cert_prepare_km() - Verify the Receiver Certificate
+ * AKE_Send_Cert and prepare AKE_Stored_Km/AKE_No_Stored_Km
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @rx_cert: AKE_Send_Cert for verification
+ * @km_stored: Pairing status flag output
+ * @ek_pub_km: AKE_Stored_Km/AKE_No_Stored_Km output msg
+ * @msg_sz : size of AKE_XXXXX_Km output msg
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_verify_receiver_cert_prepare_km(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ake_send_cert *rx_cert,
+ bool *km_stored,
+ struct hdcp2_ake_no_stored_km
+ *ek_pub_km,
+ size_t *msg_sz)
+{
+ struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
+ struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ verify_rxcert_in.header.api_version = HDCP_API_VERSION;
+ verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
+ verify_rxcert_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ verify_rxcert_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
+
+ verify_rxcert_in.port.integrated_port_type = data->port_type;
+ verify_rxcert_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ verify_rxcert_in.cert_rx = rx_cert->cert_rx;
+ memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
+ memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_rxcert_in,
+ sizeof(verify_rxcert_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed: %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&verify_rxcert_out,
+ sizeof(verify_rxcert_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed: %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_rxcert_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_VERIFY_RECEIVER_CERT,
+ verify_rxcert_out.header.status);
+ return -EIO;
+ }
+
+ *km_stored = !!verify_rxcert_out.km_stored;
+ if (verify_rxcert_out.km_stored) {
+ ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
+ *msg_sz = sizeof(struct hdcp2_ake_stored_km);
+ } else {
+ ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
+ *msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
+ }
+
+ memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
+ sizeof(verify_rxcert_out.ekm_buff));
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_verify_hprime() - Verify AKE_Send_H_prime at ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @rx_hprime: AKE_Send_H_prime msg for ME FW verification
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_verify_hprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime)
+{
+ struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
+ struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_hprime)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ send_hprime_in.header.api_version = HDCP_API_VERSION;
+ send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
+ send_hprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
+
+ send_hprime_in.port.integrated_port_type = data->port_type;
+ send_hprime_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
+ HDCP_2_2_H_PRIME_LEN);
+
+ byte = mei_cldev_send(cldev, (u8 *)&send_hprime_in,
+ sizeof(send_hprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&send_hprime_out,
+ sizeof(send_hprime_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (send_hprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_store_pairing_info() - Store pairing info received at ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @pairing_info: AKE_Send_Pairing_Info msg input to ME FW
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+ struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
+ struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !pairing_info)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ pairing_info_in.header.api_version = HDCP_API_VERSION;
+ pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
+ pairing_info_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ pairing_info_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
+
+ pairing_info_in.port.integrated_port_type = data->port_type;
+ pairing_info_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
+ HDCP_2_2_E_KH_KM_LEN);
+
+ byte = mei_cldev_send(cldev, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&pairing_info_out,
+ sizeof(pairing_info_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (pairing_info_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. Status: 0x%X\n",
+ WIRED_AKE_SEND_PAIRING_INFO,
+ pairing_info_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_initiate_locality_check() - Prepare LC_Init
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @lc_init_data: LC_Init msg output
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_initiate_locality_check(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_lc_init *lc_init_data)
+{
+ struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };
+ struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !lc_init_data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ lc_init_in.header.api_version = HDCP_API_VERSION;
+ lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
+ lc_init_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
+
+ lc_init_in.port.integrated_port_type = data->port_type;
+ lc_init_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ byte = mei_cldev_send(cldev, (u8 *)&lc_init_in, sizeof(lc_init_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&lc_init_out, sizeof(lc_init_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (lc_init_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X Failed. status: 0x%X\n",
+ WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
+ return -EIO;
+ }
+
+ lc_init_data->msg_id = HDCP_2_2_LC_INIT;
+ memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_verify_lprime() - Verify lprime.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @rx_lprime: LC_Send_L_prime msg for ME FW verification
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_verify_lprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime)
+{
+ struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } };
+ struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_lprime)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ verify_lprime_in.header.api_version = HDCP_API_VERSION;
+ verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
+ verify_lprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ verify_lprime_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;
+
+ verify_lprime_in.port.integrated_port_type = data->port_type;
+ verify_lprime_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
+ HDCP_2_2_L_PRIME_LEN);
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_lprime_in,
+ sizeof(verify_lprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&verify_lprime_out,
+ sizeof(verify_lprime_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_lprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_VALIDATE_LOCALITY,
+ verify_lprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_get_session_key() - Prepare SKE_Send_Eks.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @ske_data: SKE_Send_Eks msg output from ME FW.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_hdcp_get_session_key(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ske_send_eks *ske_data)
+{
+ struct wired_cmd_get_session_key_in get_skey_in = { { 0 } };
+ struct wired_cmd_get_session_key_out get_skey_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data || !ske_data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ get_skey_in.header.api_version = HDCP_API_VERSION;
+ get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
+ get_skey_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;
+
+ get_skey_in.port.integrated_port_type = data->port_type;
+ get_skey_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ byte = mei_cldev_send(cldev, (u8 *)&get_skey_in, sizeof(get_skey_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&get_skey_out, sizeof(get_skey_out));
+
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (get_skey_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_GET_SESSION_KEY, get_skey_out.header.status);
+ return -EIO;
+ }
+
+ ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
+ memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
+ HDCP_2_2_E_DKEY_KS_LEN);
+ memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_repeater_check_flow_prepare_ack() - Validate the Downstream topology
+ * and prepare rep_ack.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @rep_topology: Receiver ID List to be validated
+ * @rep_send_ack : repeater ack from ME FW.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_repeater_check_flow_prepare_ack(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack
+ *rep_send_ack)
+{
+ struct wired_cmd_verify_repeater_in verify_repeater_in = { { 0 } };
+ struct wired_cmd_verify_repeater_out verify_repeater_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !rep_topology || !rep_send_ack || !data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ verify_repeater_in.header.api_version = HDCP_API_VERSION;
+ verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
+ verify_repeater_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ verify_repeater_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;
+
+ verify_repeater_in.port.integrated_port_type = data->port_type;
+ verify_repeater_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,
+ HDCP_2_2_RXINFO_LEN);
+ memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,
+ HDCP_2_2_SEQ_NUM_LEN);
+ memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,
+ HDCP_2_2_V_PRIME_HALF_LEN);
+ memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
+ HDCP_2_2_RECEIVER_IDS_MAX_LEN);
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_repeater_in,
+ sizeof(verify_repeater_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&verify_repeater_out,
+ sizeof(verify_repeater_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_repeater_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_VERIFY_REPEATER,
+ verify_repeater_out.header.status);
+ return -EIO;
+ }
+
+ memcpy(rep_send_ack->v, verify_repeater_out.v,
+ HDCP_2_2_V_PRIME_HALF_LEN);
+ rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_verify_mprime() - Verify mprime.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ * @stream_ready: RepeaterAuth_Stream_Ready msg for ME FW verification.
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_hdcp_verify_mprime(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready)
+{
+ struct wired_cmd_repeater_auth_stream_req_in
+ verify_mprime_in = { { 0 } };
+ struct wired_cmd_repeater_auth_stream_req_out
+ verify_mprime_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !stream_ready || !data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ verify_mprime_in.header.api_version = HDCP_API_VERSION;
+ verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+ verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ verify_mprime_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
+
+ verify_mprime_in.port.integrated_port_type = data->port_type;
+ verify_mprime_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
+ HDCP_2_2_MPRIME_LEN);
+ drm_hdcp2_u32_to_seq_num(verify_mprime_in.seq_num_m, data->seq_num_m);
+ memcpy(verify_mprime_in.streams, data->streams,
+ (data->k * sizeof(struct hdcp2_streamid_type)));
+
+ verify_mprime_in.k = cpu_to_be16(data->k);
+
+ byte = mei_cldev_send(cldev, (u8 *)&verify_mprime_in,
+ sizeof(verify_mprime_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&verify_mprime_out,
+ sizeof(verify_mprime_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_mprime_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_REPEATER_AUTH_STREAM_REQ,
+ verify_mprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_enable_authentication() - Mark a port as authenticated
+ * through ME FW
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int mei_hdcp_enable_authentication(struct device *dev,
+ struct hdcp_port_data *data)
+{
+ struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
+ struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ enable_auth_in.header.api_version = HDCP_API_VERSION;
+ enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
+ enable_auth_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;
+
+ enable_auth_in.port.integrated_port_type = data->port_type;
+ enable_auth_in.port.physical_port = mei_get_ddi_index(data->port);
+ enable_auth_in.stream_type = data->streams[0].stream_type;
+
+ byte = mei_cldev_send(cldev, (u8 *)&enable_auth_in,
+ sizeof(enable_auth_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&enable_auth_out,
+ sizeof(enable_auth_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (enable_auth_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "ME cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_ENABLE_AUTH, enable_auth_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * mei_hdcp_close_session() - Close the Wired HDCP Tx session of ME FW per port.
+ * This also disables the authenticated state of the port.
+ * @dev: device corresponding to the mei_cl_device
+ * @data: Intel HW specific hdcp data
+ *
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_hdcp_close_session(struct device *dev, struct hdcp_port_data *data)
+{
+ struct wired_cmd_close_session_in session_close_in = { { 0 } };
+ struct wired_cmd_close_session_out session_close_out = { { 0 } };
+ struct mei_cl_device *cldev;
+ ssize_t byte;
+
+ if (!dev || !data)
+ return -EINVAL;
+
+ cldev = to_mei_cl_device(dev);
+
+ session_close_in.header.api_version = HDCP_API_VERSION;
+ session_close_in.header.command_id = WIRED_CLOSE_SESSION;
+ session_close_in.header.status = ME_HDCP_STATUS_SUCCESS;
+ session_close_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;
+
+ session_close_in.port.integrated_port_type = data->port_type;
+ session_close_in.port.physical_port = mei_get_ddi_index(data->port);
+
+ byte = mei_cldev_send(cldev, (u8 *)&session_close_in,
+ sizeof(session_close_in));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&session_close_out,
+ sizeof(session_close_out));
+ if (byte < 0) {
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (session_close_out.header.status != ME_HDCP_STATUS_SUCCESS) {
+ dev_dbg(dev, "Session Close Failed. status: 0x%X\n",
+ session_close_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const struct i915_hdcp_component_ops mei_hdcp_ops = {
+ .owner = THIS_MODULE,
+ .initiate_hdcp2_session = mei_hdcp_initiate_session,
+ .verify_receiver_cert_prepare_km =
+ mei_hdcp_verify_receiver_cert_prepare_km,
+ .verify_hprime = mei_hdcp_verify_hprime,
+ .store_pairing_info = mei_hdcp_store_pairing_info,
+ .initiate_locality_check = mei_hdcp_initiate_locality_check,
+ .verify_lprime = mei_hdcp_verify_lprime,
+ .get_session_key = mei_hdcp_get_session_key,
+ .repeater_check_flow_prepare_ack =
+ mei_hdcp_repeater_check_flow_prepare_ack,
+ .verify_mprime = mei_hdcp_verify_mprime,
+ .enable_hdcp_authentication = mei_hdcp_enable_authentication,
+ .close_hdcp_session = mei_hdcp_close_session,
+};
+
+static int mei_component_master_bind(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct i915_hdcp_comp_master *comp_master =
+ mei_cldev_get_drvdata(cldev);
+ int ret;
+
+ dev_dbg(dev, "%s\n", __func__);
+ comp_master->ops = &mei_hdcp_ops;
+ comp_master->mei_dev = dev;
+ ret = component_bind_all(dev, comp_master);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void mei_component_master_unbind(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct i915_hdcp_comp_master *comp_master =
+ mei_cldev_get_drvdata(cldev);
+
+ dev_dbg(dev, "%s\n", __func__);
+ component_unbind_all(dev, comp_master);
+}
+
+static const struct component_master_ops mei_component_master_ops = {
+ .bind = mei_component_master_bind,
+ .unbind = mei_component_master_unbind,
+};
+
+static int mei_hdcp_component_match(struct device *dev, int subcomponent,
+ void *data)
+{
+ return !strcmp(dev->driver->name, "i915") &&
+ subcomponent == I915_COMPONENT_HDCP;
+}
+
+static int mei_hdcp_probe(struct mei_cl_device *cldev,
+ const struct mei_cl_device_id *id)
+{
+ struct i915_hdcp_comp_master *comp_master;
+ struct component_match *master_match;
+ int ret;
+
+ ret = mei_cldev_enable(cldev);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ goto enable_err_exit;
+ }
+
+ comp_master = kzalloc(sizeof(*comp_master), GFP_KERNEL);
+ if (!comp_master) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ master_match = NULL;
+ component_match_add_typed(&cldev->dev, &master_match,
+ mei_hdcp_component_match, comp_master);
+ if (IS_ERR_OR_NULL(master_match)) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ mei_cldev_set_drvdata(cldev, comp_master);
+ ret = component_master_add_with_match(&cldev->dev,
+ &mei_component_master_ops,
+ master_match);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ mei_cldev_set_drvdata(cldev, NULL);
+ kfree(comp_master);
+ mei_cldev_disable(cldev);
+enable_err_exit:
+ return ret;
+}
+
+static int mei_hdcp_remove(struct mei_cl_device *cldev)
+{
+ struct i915_hdcp_comp_master *comp_master =
+ mei_cldev_get_drvdata(cldev);
+
+ component_master_del(&cldev->dev, &mei_component_master_ops);
+ kfree(comp_master);
+ mei_cldev_set_drvdata(cldev, NULL);
+
+ return mei_cldev_disable(cldev);
+}
+
+#define MEI_UUID_HDCP GUID_INIT(0xB638AB7E, 0x94E2, 0x4EA2, 0xA5, \
+ 0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04)
+
+static struct mei_cl_device_id mei_hdcp_tbl[] = {
+ { .uuid = MEI_UUID_HDCP, .version = MEI_CL_VERSION_ANY },
+ { }
+};
+MODULE_DEVICE_TABLE(mei, mei_hdcp_tbl);
+
+static struct mei_cl_driver mei_hdcp_driver = {
+ .id_table = mei_hdcp_tbl,
+ .name = KBUILD_MODNAME,
+ .probe = mei_hdcp_probe,
+ .remove = mei_hdcp_remove,
+};
+
+module_mei_cl_driver(mei_hdcp_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MEI HDCP");
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
new file mode 100644
index 000000000000..5f74b908e486
--- /dev/null
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -0,0 +1,377 @@
+/* SPDX-License-Identifier: (GPL-2.0+) */
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef __MEI_HDCP_H__
+#define __MEI_HDCP_H__
+
+#include <drm/drm_hdcp.h>
+
+/* me_hdcp_status: Enumeration of all HDCP Status Codes */
+enum me_hdcp_status {
+ ME_HDCP_STATUS_SUCCESS = 0x0000,
+
+ /* WiDi Generic Status Codes */
+ ME_HDCP_STATUS_INTERNAL_ERROR = 0x1000,
+ ME_HDCP_STATUS_UNKNOWN_ERROR = 0x1001,
+ ME_HDCP_STATUS_INCORRECT_API_VERSION = 0x1002,
+ ME_HDCP_STATUS_INVALID_FUNCTION = 0x1003,
+ ME_HDCP_STATUS_INVALID_BUFFER_LENGTH = 0x1004,
+ ME_HDCP_STATUS_INVALID_PARAMS = 0x1005,
+ ME_HDCP_STATUS_AUTHENTICATION_FAILED = 0x1006,
+
+ /* WiDi Status Codes */
+ ME_HDCP_INVALID_SESSION_STATE = 0x6000,
+ ME_HDCP_SRM_FRAGMENT_UNEXPECTED = 0x6001,
+ ME_HDCP_SRM_INVALID_LENGTH = 0x6002,
+ ME_HDCP_SRM_FRAGMENT_OFFSET_INVALID = 0x6003,
+ ME_HDCP_SRM_VERIFICATION_FAILED = 0x6004,
+ ME_HDCP_SRM_VERSION_TOO_OLD = 0x6005,
+ ME_HDCP_RX_CERT_VERIFICATION_FAILED = 0x6006,
+ ME_HDCP_RX_REVOKED = 0x6007,
+ ME_HDCP_H_VERIFICATION_FAILED = 0x6008,
+ ME_HDCP_REPEATER_CHECK_UNEXPECTED = 0x6009,
+ ME_HDCP_TOPOLOGY_MAX_EXCEEDED = 0x600A,
+ ME_HDCP_V_VERIFICATION_FAILED = 0x600B,
+ ME_HDCP_L_VERIFICATION_FAILED = 0x600C,
+ ME_HDCP_STREAM_KEY_ALLOC_FAILED = 0x600D,
+ ME_HDCP_BASE_KEY_RESET_FAILED = 0x600E,
+ ME_HDCP_NONCE_GENERATION_FAILED = 0x600F,
+ ME_HDCP_STATUS_INVALID_E_KEY_STATE = 0x6010,
+ ME_HDCP_STATUS_INVALID_CS_ICV = 0x6011,
+ ME_HDCP_STATUS_INVALID_KB_KEY_STATE = 0x6012,
+ ME_HDCP_STATUS_INVALID_PAVP_MODE_ICV = 0x6013,
+ ME_HDCP_STATUS_INVALID_PAVP_MODE = 0x6014,
+ ME_HDCP_STATUS_LC_MAX_ATTEMPTS = 0x6015,
+
+ /* New status for HDCP 2.1 */
+ ME_HDCP_STATUS_MISMATCH_IN_M = 0x6016,
+
+ /* New status code for HDCP 2.2 Rx */
+ ME_HDCP_STATUS_RX_PROV_NOT_ALLOWED = 0x6017,
+ ME_HDCP_STATUS_RX_PROV_WRONG_SUBJECT = 0x6018,
+ ME_HDCP_RX_NEEDS_PROVISIONING = 0x6019,
+ ME_HDCP_BKSV_ICV_AUTH_FAILED = 0x6020,
+ ME_HDCP_STATUS_INVALID_STREAM_ID = 0x6021,
+ ME_HDCP_STATUS_CHAIN_NOT_INITIALIZED = 0x6022,
+ ME_HDCP_FAIL_NOT_EXPECTED = 0x6023,
+ ME_HDCP_FAIL_HDCP_OFF = 0x6024,
+ ME_HDCP_FAIL_INVALID_PAVP_MEMORY_MODE = 0x6025,
+ ME_HDCP_FAIL_AES_ECB_FAILURE = 0x6026,
+ ME_HDCP_FEATURE_NOT_SUPPORTED = 0x6027,
+ ME_HDCP_DMA_READ_ERROR = 0x6028,
+ ME_HDCP_DMA_WRITE_ERROR = 0x6029,
+ ME_HDCP_FAIL_INVALID_PACKET_SIZE = 0x6030,
+ ME_HDCP_H264_PARSING_ERROR = 0x6031,
+ ME_HDCP_HDCP2_ERRATA_VIDEO_VIOLATION = 0x6032,
+ ME_HDCP_HDCP2_ERRATA_AUDIO_VIOLATION = 0x6033,
+ ME_HDCP_TX_ACTIVE_ERROR = 0x6034,
+ ME_HDCP_MODE_CHANGE_ERROR = 0x6035,
+ ME_HDCP_STREAM_TYPE_ERROR = 0x6036,
+ ME_HDCP_STREAM_MANAGE_NOT_POSSIBLE = 0x6037,
+
+ ME_HDCP_STATUS_PORT_INVALID_COMMAND = 0x6038,
+ ME_HDCP_STATUS_UNSUPPORTED_PROTOCOL = 0x6039,
+ ME_HDCP_STATUS_INVALID_PORT_INDEX = 0x603a,
+ ME_HDCP_STATUS_TX_AUTH_NEEDED = 0x603b,
+ ME_HDCP_STATUS_NOT_INTEGRATED_PORT = 0x603c,
+ ME_HDCP_STATUS_SESSION_MAX_REACHED = 0x603d,
+
+ /* hdcp capable bit is not set in rx_caps(error is unique to DP) */
+ ME_HDCP_STATUS_NOT_HDCP_CAPABLE = 0x6041,
+
+ ME_HDCP_STATUS_INVALID_STREAM_COUNT = 0x6042,
+};
+
+#define HDCP_API_VERSION 0x00010000
+
+#define HDCP_M_LEN 16
+#define HDCP_KH_LEN 16
+
+/* Payload Buffer size(Excluding Header) for CMDs and corresponding response */
+/* Wired_Tx_AKE */
+#define WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN (4 + 1)
+#define WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_OUT (4 + 8 + 3)
+
+#define WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN (4 + 522 + 8 + 3)
+#define WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_MIN_OUT (4 + 1 + 3 + 16 + 16)
+#define WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_MAX_OUT (4 + 1 + 3 + 128)
+
+#define WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN (4 + 32)
+#define WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_OUT (4)
+
+#define WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN (4 + 16)
+#define WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_OUT (4)
+
+#define WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN (4)
+#define WIRED_CMD_BUF_LEN_CLOSE_SESSION_OUT (4)
+
+/* Wired_Tx_LC */
+#define WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN (4)
+#define WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_OUT (4 + 8)
+
+#define WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN (4 + 32)
+#define WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_OUT (4)
+
+/* Wired_Tx_SKE */
+#define WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN (4)
+#define WIRED_CMD_BUF_LEN_GET_SESSION_KEY_OUT (4 + 16 + 8)
+
+/* Wired_Tx_SKE */
+#define WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN (4 + 1)
+#define WIRED_CMD_BUF_LEN_ENABLE_AUTH_OUT (4)
+
+/* Wired_Tx_Repeater */
+#define WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN (4 + 2 + 3 + 16 + 155)
+#define WIRED_CMD_BUF_LEN_VERIFY_REPEATER_OUT (4 + 1 + 16)
+
+#define WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN (4 + 3 + \
+ 32 + 2 + 2)
+
+#define WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_OUT (4)
+
+/* hdcp_command_id: Enumeration of all WIRED HDCP Command IDs */
+enum hdcp_command_id {
+ _WIDI_COMMAND_BASE = 0x00030000,
+ WIDI_INITIATE_HDCP2_SESSION = _WIDI_COMMAND_BASE,
+ HDCP_GET_SRM_STATUS,
+ HDCP_SEND_SRM_FRAGMENT,
+
+ /* The wired HDCP Tx commands */
+ _WIRED_COMMAND_BASE = 0x00031000,
+ WIRED_INITIATE_HDCP2_SESSION = _WIRED_COMMAND_BASE,
+ WIRED_VERIFY_RECEIVER_CERT,
+ WIRED_AKE_SEND_HPRIME,
+ WIRED_AKE_SEND_PAIRING_INFO,
+ WIRED_INIT_LOCALITY_CHECK,
+ WIRED_VALIDATE_LOCALITY,
+ WIRED_GET_SESSION_KEY,
+ WIRED_ENABLE_AUTH,
+ WIRED_VERIFY_REPEATER,
+ WIRED_REPEATER_AUTH_STREAM_REQ,
+ WIRED_CLOSE_SESSION,
+
+ _WIRED_COMMANDS_COUNT,
+};
+
+union encrypted_buff {
+ u8 e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
+ u8 e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+ struct {
+ u8 e_kh_km[HDCP_KH_LEN];
+ u8 m[HDCP_M_LEN];
+ } __packed;
+};
+
+/* HDCP HECI message header. All header values are little endian. */
+struct hdcp_cmd_header {
+ u32 api_version;
+ u32 command_id;
+ enum me_hdcp_status status;
+ /* Length of the HECI message (excluding the header) */
+ u32 buffer_len;
+} __packed;
+
+/* Empty command request or response. No data follows the header. */
+struct hdcp_cmd_no_data {
+ struct hdcp_cmd_header header;
+} __packed;
+
+/* Uniquely identifies the hdcp port being addressed for a given command. */
+struct hdcp_port_id {
+ u8 integrated_port_type;
+ u8 physical_port;
+ u16 reserved;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in
+ * support of the AKE protocol
+ */
+/* HECI struct for integrated wired HDCP Tx session initiation. */
+struct wired_cmd_initiate_hdcp2_session_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 protocol; /* for HDMI vs DP */
+} __packed;
+
+struct wired_cmd_initiate_hdcp2_session_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 r_tx[HDCP_2_2_RTX_LEN];
+ struct hdcp2_tx_caps tx_caps;
+} __packed;
+
+/* HECI struct for ending an integrated wired HDCP Tx session. */
+struct wired_cmd_close_session_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+struct wired_cmd_close_session_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+/* HECI struct for integrated wired HDCP Tx Rx Cert verification. */
+struct wired_cmd_verify_receiver_cert_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ struct hdcp2_cert_rx cert_rx;
+ u8 r_rx[HDCP_2_2_RRX_LEN];
+ u8 rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct wired_cmd_verify_receiver_cert_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 km_stored;
+ u8 reserved[3];
+ union encrypted_buff ekm_buff;
+} __packed;
+
+/* HECI struct for verification of Rx's Hprime in a HDCP Tx session */
+struct wired_cmd_ake_send_hprime_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct wired_cmd_ake_send_hprime_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+/*
+ * HECI struct for sending in AKE pairing data generated by the Rx in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_ake_send_pairing_info_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct wired_cmd_ake_send_pairing_info_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+/* Data structures for integrated wired HDCP2 Tx in support of the LC protocol*/
+/*
+ * HECI struct for initiating locality check with an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_init_locality_check_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+struct wired_cmd_init_locality_check_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+/*
+ * HECI struct for validating an Rx's LPrime value in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_validate_locality_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct wired_cmd_validate_locality_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in support of the
+ * SKE protocol
+ */
+/* HECI struct for creating session key */
+struct wired_cmd_get_session_key_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+struct wired_cmd_get_session_key_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ u8 r_iv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+/* HECI struct for the Tx enable authentication command */
+struct wired_cmd_enable_auth_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 stream_type;
+} __packed;
+
+struct wired_cmd_enable_auth_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+/*
+ * Data structures for integrated wired HDCP2 Tx in support of
+ * the repeater protocols
+ */
+/*
+ * HECI struct for verifying the downstream repeater's HDCP topology in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_verify_repeater_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 rx_info[HDCP_2_2_RXINFO_LEN];
+ u8 seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ u8 v_prime[HDCP_2_2_V_PRIME_HALF_LEN];
+ u8 receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct wired_cmd_verify_repeater_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 content_type_supported;
+ u8 v[HDCP_2_2_V_PRIME_HALF_LEN];
+} __packed;
+
+/*
+ * HECI struct in support of stream management in an
+ * integrated wired HDCP Tx session.
+ */
+struct wired_cmd_repeater_auth_stream_req_in {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+ u8 seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ u8 m_prime[HDCP_2_2_MPRIME_LEN];
+ __be16 k;
+ struct hdcp2_streamid_type streams[1];
+} __packed;
+
+struct wired_cmd_repeater_auth_stream_req_out {
+ struct hdcp_cmd_header header;
+ struct hdcp_port_id port;
+} __packed;
+
+enum mei_fw_ddi {
+ MEI_DDI_INVALID_PORT = 0x0,
+
+ MEI_DDI_B = 1,
+ MEI_DDI_C,
+ MEI_DDI_D,
+ MEI_DDI_E,
+ MEI_DDI_F,
+ MEI_DDI_A = 7,
+ MEI_DDI_RANGE_END = MEI_DDI_A,
+};
+#endif /* __MEI_HDCP_H__ */
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index e4b10b2d1a08..bb1ee9834a02 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -127,6 +127,8 @@
#define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */
#define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */
+#define MEI_DEV_ID_DNV_IE 0x19E5 /* Denverton IE */
+
#define MEI_DEV_ID_GLK 0x319A /* Gemini Lake */
#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */
@@ -137,6 +139,8 @@
#define MEI_DEV_ID_CNP_H 0xA360 /* Cannon Point H */
#define MEI_DEV_ID_CNP_H_4 0xA364 /* Cannon Point H 4 (iTouch) */
+#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
+
/*
* MEI HW Section
*/
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 2b7f7677f8cc..b7d2487b8409 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -311,7 +311,8 @@ struct mei_client_properties {
u8 protocol_version;
u8 max_number_of_connections;
u8 fixed_address;
- u8 single_recv_buf;
+ u8 single_recv_buf:1;
+ u8 reserved:7;
u32 max_msg_length;
} __packed;
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 73ace2d59dea..3ab946ad3257 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -88,11 +88,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
+
{MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
@@ -103,6 +105,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+
/* required last entry */
{0, }
};
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index 227cc7443671..242dcee14689 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -38,7 +38,6 @@ comment "VOP Bus Driver"
config VOP_BUS
tristate "VOP Bus Driver"
- depends on 64BIT && PCI && X86 && X86_DEV_DMA_OPS
help
This option is selected by any driver which registers a
device or driver on the VOP Bus, such as CONFIG_INTEL_MIC_HOST
@@ -132,7 +131,7 @@ comment "VOP Driver"
config VOP
tristate "VOP Driver"
- depends on 64BIT && PCI && X86 && VOP_BUS
+ depends on VOP_BUS
select VHOST_RING
select VIRTIO
help
diff --git a/drivers/misc/mic/bus/scif_bus.h b/drivers/misc/mic/bus/scif_bus.h
index ff59568219ad..377a4f38cd7e 100644
--- a/drivers/misc/mic/bus/scif_bus.h
+++ b/drivers/misc/mic/bus/scif_bus.h
@@ -88,8 +88,8 @@ struct scif_driver {
* @send_intr: Send an interrupt to the remote node on a specified doorbell.
* @send_p2p_intr: Send an interrupt to the peer node on a specified doorbell
* which is specifically targeted for a peer to peer node.
- * @ioremap: Map a buffer with the specified physical address and length.
- * @iounmap: Unmap a buffer previously mapped.
+ * @remap: Map a buffer with the specified physical address and length.
+ * @unmap: Unmap a buffer previously mapped.
*/
struct scif_hw_ops {
int (*next_db)(struct scif_hw_dev *sdev);
@@ -104,9 +104,9 @@ struct scif_hw_ops {
void (*send_intr)(struct scif_hw_dev *sdev, int db);
void (*send_p2p_intr)(struct scif_hw_dev *sdev, int db,
struct mic_mw *mw);
- void __iomem * (*ioremap)(struct scif_hw_dev *sdev,
+ void __iomem * (*remap)(struct scif_hw_dev *sdev,
phys_addr_t pa, size_t len);
- void (*iounmap)(struct scif_hw_dev *sdev, void __iomem *va);
+ void (*unmap)(struct scif_hw_dev *sdev, void __iomem *va);
};
int scif_register_driver(struct scif_driver *driver);
diff --git a/drivers/misc/mic/bus/vop_bus.h b/drivers/misc/mic/bus/vop_bus.h
index fff7a865d721..cf5f3fae573c 100644
--- a/drivers/misc/mic/bus/vop_bus.h
+++ b/drivers/misc/mic/bus/vop_bus.h
@@ -87,8 +87,8 @@ struct vop_driver {
* @get_dp: Get access to the virtio device page used by the self
* node to add/remove/configure virtio devices.
* @send_intr: Send an interrupt to the peer node on a specified doorbell.
- * @ioremap: Map a buffer with the specified DMA address and length.
- * @iounmap: Unmap a buffer previously mapped.
+ * @remap: Map a buffer with the specified DMA address and length.
+ * @unmap: Unmap a buffer previously mapped.
* @dma_filter: The DMA filter function to use for obtaining access to
* a DMA channel on the peer node.
*/
@@ -104,9 +104,9 @@ struct vop_hw_ops {
void __iomem * (*get_remote_dp)(struct vop_device *vpdev);
void * (*get_dp)(struct vop_device *vpdev);
void (*send_intr)(struct vop_device *vpdev, int db);
- void __iomem * (*ioremap)(struct vop_device *vpdev,
+ void __iomem * (*remap)(struct vop_device *vpdev,
dma_addr_t pa, size_t len);
- void (*iounmap)(struct vop_device *vpdev, void __iomem *va);
+ void (*unmap)(struct vop_device *vpdev, void __iomem *va);
};
struct vop_device *
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
index e749af48f736..dcd07ef29801 100644
--- a/drivers/misc/mic/card/mic_device.c
+++ b/drivers/misc/mic/card/mic_device.c
@@ -245,8 +245,8 @@ static struct scif_hw_ops scif_hw_ops = {
.next_db = ___mic_next_db,
.send_intr = ___mic_send_intr,
.send_p2p_intr = ___mic_send_p2p_intr,
- .ioremap = ___mic_ioremap,
- .iounmap = ___mic_iounmap,
+ .remap = ___mic_ioremap,
+ .unmap = ___mic_iounmap,
};
static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev)
@@ -316,8 +316,8 @@ static struct vop_hw_ops vop_hw_ops = {
.next_db = __mic_next_db,
.get_remote_dp = __mic_get_remote_dp,
.send_intr = __mic_send_intr,
- .ioremap = __mic_ioremap,
- .iounmap = __mic_iounmap,
+ .remap = __mic_ioremap,
+ .unmap = __mic_iounmap,
};
static int mic_request_dma_chans(struct mic_driver *mdrv)
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index 6479435ac96b..079c36f0ce6e 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -133,8 +133,8 @@ static struct vop_hw_ops vop_hw_ops = {
.get_dp = __mic_get_dp,
.get_remote_dp = __mic_get_remote_dp,
.send_intr = __mic_send_intr,
- .ioremap = __mic_ioremap,
- .iounmap = __mic_iounmap,
+ .remap = __mic_ioremap,
+ .unmap = __mic_iounmap,
};
static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
@@ -315,8 +315,8 @@ static struct scif_hw_ops scif_hw_ops = {
.ack_interrupt = ___mic_ack_interrupt,
.next_db = ___mic_next_db,
.send_intr = ___mic_send_intr,
- .ioremap = ___mic_ioremap,
- .iounmap = ___mic_iounmap,
+ .remap = ___mic_ioremap,
+ .unmap = ___mic_iounmap,
};
static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
diff --git a/drivers/misc/mic/scif/scif_map.h b/drivers/misc/mic/scif/scif_map.h
index 3e86360ba5a6..7b380534eba1 100644
--- a/drivers/misc/mic/scif/scif_map.h
+++ b/drivers/misc/mic/scif/scif_map.h
@@ -97,7 +97,7 @@ scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev)
out_virt = phys_to_virt(phys);
else
out_virt = (void __force *)
- sdev->hw_ops->ioremap(sdev, phys, size);
+ sdev->hw_ops->remap(sdev, phys, size);
return out_virt;
}
@@ -107,7 +107,7 @@ scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
if (!scifdev_self(scifdev)) {
struct scif_hw_dev *sdev = scifdev->sdev;
- sdev->hw_ops->iounmap(sdev, (void __force __iomem *)virt);
+ sdev->hw_ops->unmap(sdev, (void __force __iomem *)virt);
}
}
diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c
index 749321eb91ae..f62216628fa6 100644
--- a/drivers/misc/mic/scif/scif_rma.c
+++ b/drivers/misc/mic/scif/scif_rma.c
@@ -672,8 +672,8 @@ int scif_unregister_window(struct scif_window *window)
{
window->unreg_state = OP_IN_PROGRESS;
send_msg = true;
- /* fall through */
}
+ /* fall through */
case OP_IN_PROGRESS:
{
scif_get_window(window, 1);
diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c
index 6b212c8b78e7..e37b2c2152a2 100644
--- a/drivers/misc/mic/vop/vop_main.c
+++ b/drivers/misc/mic/vop/vop_main.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "vop_main.h"
@@ -47,7 +48,8 @@
* @dc: Virtio device control
* @vpdev: VOP device which is the parent for this virtio device
* @vr: Buffer for accessing the VRING
- * @used: Buffer for used
+ * @used_virt: Virtual address of used ring
+ * @used: DMA address of used ring
* @used_size: Size of the used buffer
* @reset_done: Track whether VOP reset is complete
* @virtio_cookie: Cookie returned upon requesting a interrupt
@@ -61,6 +63,7 @@ struct _vop_vdev {
struct mic_device_ctrl __iomem *dc;
struct vop_device *vpdev;
void __iomem *vr[VOP_MAX_VRINGS];
+ void *used_virt[VOP_MAX_VRINGS];
dma_addr_t used[VOP_MAX_VRINGS];
int used_size[VOP_MAX_VRINGS];
struct completion reset_done;
@@ -116,7 +119,7 @@ _vop_total_desc_size(struct mic_device_desc __iomem *desc)
static u64 vop_get_features(struct virtio_device *vdev)
{
unsigned int i, bits;
- u32 features = 0;
+ u64 features = 0;
struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
u8 __iomem *in_features = _vop_vq_features(desc);
int feature_len = ioread8(&desc->feature_len);
@@ -124,7 +127,7 @@ static u64 vop_get_features(struct virtio_device *vdev)
bits = min_t(unsigned, feature_len, sizeof(vdev->features)) * 8;
for (i = 0; i < bits; i++)
if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
- features |= BIT(i);
+ features |= BIT_ULL(i);
return features;
}
@@ -226,7 +229,7 @@ static void vop_reset_inform_host(struct virtio_device *dev)
if (ioread8(&dc->host_ack))
break;
msleep(100);
- };
+ }
dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
@@ -260,14 +263,14 @@ static bool vop_notify(struct virtqueue *vq)
static void vop_del_vq(struct virtqueue *vq, int n)
{
struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
- struct vring *vr = (struct vring *)(vq + 1);
struct vop_device *vpdev = vdev->vpdev;
dma_unmap_single(&vpdev->dev, vdev->used[n],
vdev->used_size[n], DMA_BIDIRECTIONAL);
- free_pages((unsigned long)vr->used, get_order(vdev->used_size[n]));
+ free_pages((unsigned long)vdev->used_virt[n],
+ get_order(vdev->used_size[n]));
vring_del_virtqueue(vq);
- vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]);
+ vpdev->hw_ops->unmap(vpdev, vdev->vr[n]);
vdev->vr[n] = NULL;
}
@@ -283,6 +286,26 @@ static void vop_del_vqs(struct virtio_device *dev)
vop_del_vq(vq, idx++);
}
+static struct virtqueue *vop_new_virtqueue(unsigned int index,
+ unsigned int num,
+ struct virtio_device *vdev,
+ bool context,
+ void *pages,
+ bool (*notify)(struct virtqueue *vq),
+ void (*callback)(struct virtqueue *vq),
+ const char *name,
+ void *used)
+{
+ bool weak_barriers = false;
+ struct vring vring;
+
+ vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
+ vring.used = used;
+
+ return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+ notify, callback, name);
+}
+
/*
* This routine will assign vring's allocated in host/io memory. Code in
* virtio_ring.c however continues to access this io memory as if it were local
@@ -302,7 +325,6 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
struct _mic_vring_info __iomem *info;
void *used;
int vr_size, _vr_size, err, magic;
- struct vring *vr;
u8 type = ioread8(&vdev->desc->type);
if (index >= ioread8(&vdev->desc->num_vq))
@@ -316,23 +338,12 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
memcpy_fromio(&config, vqconfig, sizeof(config));
_vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN);
vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
- va = vpdev->hw_ops->ioremap(vpdev, le64_to_cpu(config.address),
- vr_size);
+ va = vpdev->hw_ops->remap(vpdev, le64_to_cpu(config.address), vr_size);
if (!va)
return ERR_PTR(-ENOMEM);
vdev->vr[index] = va;
memset_io(va, 0x0, _vr_size);
- vq = vring_new_virtqueue(
- index,
- le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
- dev,
- false,
- ctx,
- (void __force *)va, vop_notify, callback, name);
- if (!vq) {
- err = -ENOMEM;
- goto unmap;
- }
+
info = va + _vr_size;
magic = ioread32(&info->magic);
@@ -341,18 +352,27 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
goto unmap;
}
- /* Allocate and reassign used ring now */
vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
sizeof(struct vring_used_elem) *
le16_to_cpu(config.num));
used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(vdev->used_size[index]));
+ vdev->used_virt[index] = used;
if (!used) {
err = -ENOMEM;
dev_err(_vop_dev(vdev), "%s %d err %d\n",
__func__, __LINE__, err);
- goto del_vq;
+ goto unmap;
+ }
+
+ vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
+ (void __force *)va, vop_notify, callback,
+ name, used);
+ if (!vq) {
+ err = -ENOMEM;
+ goto free_used;
}
+
vdev->used[index] = dma_map_single(&vpdev->dev, used,
vdev->used_size[index],
DMA_BIDIRECTIONAL);
@@ -360,28 +380,19 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
err = -ENOMEM;
dev_err(_vop_dev(vdev), "%s %d err %d\n",
__func__, __LINE__, err);
- goto free_used;
+ goto del_vq;
}
writeq(vdev->used[index], &vqconfig->used_address);
- /*
- * To reassign the used ring here we are directly accessing
- * struct vring_virtqueue which is a private data structure
- * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
- * vring_new_virtqueue() would ensure that
- * (&vq->vring == (struct vring *) (&vq->vq + 1));
- */
- vr = (struct vring *)(vq + 1);
- vr->used = used;
vq->priv = vdev;
return vq;
+del_vq:
+ vring_del_virtqueue(vq);
free_used:
free_pages((unsigned long)used,
get_order(vdev->used_size[index]));
-del_vq:
- vring_del_virtqueue(vq);
unmap:
- vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]);
+ vpdev->hw_ops->unmap(vpdev, vdev->vr[index]);
return ERR_PTR(err);
}
@@ -394,16 +405,21 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
struct _vop_vdev *vdev = to_vopvdev(dev);
struct vop_device *vpdev = vdev->vpdev;
struct mic_device_ctrl __iomem *dc = vdev->dc;
- int i, err, retry;
+ int i, err, retry, queue_idx = 0;
/* We must have this many virtqueues. */
if (nvqs > ioread8(&vdev->desc->num_vq))
return -ENOENT;
for (i = 0; i < nvqs; ++i) {
+ if (!names[i]) {
+ vqs[i] = NULL;
+ continue;
+ }
+
dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
__func__, i, names[i]);
- vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+ vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
err = PTR_ERR(vqs[i]);
@@ -421,7 +437,7 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
if (!ioread8(&dc->used_address_updated))
break;
msleep(100);
- };
+ }
dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
if (!retry) {
@@ -497,7 +513,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d,
vdev->desc = d;
vdev->dc = (void __iomem *)d + _vop_aligned_desc_size(d);
vdev->dnode = dnode;
- vdev->vdev.priv = (void *)(u64)dnode;
+ vdev->vdev.priv = (void *)(unsigned long)dnode;
init_completion(&vdev->reset_done);
vdev->h2c_vdev_db = vpdev->hw_ops->next_db(vpdev);
@@ -519,7 +535,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d,
offset, type);
goto free_irq;
}
- writeq((u64)vdev, &vdev->dc->vdev);
+ writeq((unsigned long)vdev, &vdev->dc->vdev);
dev_dbg(_vop_dev(vdev), "%s: registered vop device %u type %u vdev %p\n",
__func__, offset, type, vdev);
@@ -546,13 +562,18 @@ static int vop_match_desc(struct device *dev, void *data)
return vdev->desc == (void __iomem *)data;
}
+static struct _vop_vdev *vop_dc_to_vdev(struct mic_device_ctrl *dc)
+{
+ return (struct _vop_vdev *)(unsigned long)readq(&dc->vdev);
+}
+
static void _vop_handle_config_change(struct mic_device_desc __iomem *d,
unsigned int offset,
struct vop_device *vpdev)
{
struct mic_device_ctrl __iomem *dc
= (void __iomem *)d + _vop_aligned_desc_size(d);
- struct _vop_vdev *vdev = (struct _vop_vdev *)readq(&dc->vdev);
+ struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED)
return;
@@ -571,11 +592,13 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
{
struct mic_device_ctrl __iomem *dc
= (void __iomem *)d + _vop_aligned_desc_size(d);
- struct _vop_vdev *vdev = (struct _vop_vdev *)readq(&dc->vdev);
+ struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
u8 status;
int ret = -1;
if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+ struct device *dev = get_device(&vdev->vdev.dev);
+
dev_dbg(&vpdev->dev,
"%s %d config_change %d type %d vdev %p\n",
__func__, __LINE__,
@@ -587,7 +610,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
iowrite8(-1, &dc->h2c_vdev_db);
if (status & VIRTIO_CONFIG_S_DRIVER_OK)
wait_for_completion(&vdev->reset_done);
- put_device(&vdev->vdev.dev);
+ put_device(dev);
iowrite8(1, &dc->guest_ack);
dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
__func__, __LINE__, ioread8(&dc->guest_ack));
diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c
index cbc8ebcff5cf..3632fce40590 100644
--- a/drivers/misc/mic/vop/vop_vringh.c
+++ b/drivers/misc/mic/vop/vop_vringh.c
@@ -80,7 +80,7 @@ static void vop_virtio_init_post(struct vop_vdev *vdev)
continue;
}
vdev->vvr[i].vrh.vring.used =
- (void __force *)vpdev->hw_ops->ioremap(
+ (void __force *)vpdev->hw_ops->remap(
vpdev,
le64_to_cpu(vqconfig[i].used_address),
used_size);
@@ -528,15 +528,15 @@ static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
int vr_idx)
{
struct vop_device *vpdev = vdev->vpdev;
- void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len);
+ void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
struct vop_vringh *vvr = &vdev->vvr[vr_idx];
struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
- size_t dma_alignment = 1 << vi->dma_ch->device->copy_align;
- bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+ size_t dma_alignment;
+ bool x200;
size_t dma_offset, partlen;
int err;
- if (!VOP_USE_DMA) {
+ if (!VOP_USE_DMA || !vi->dma_ch) {
if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
err = -EFAULT;
dev_err(vop_dev(vdev), "%s %d err %d\n",
@@ -548,6 +548,9 @@ static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
goto err;
}
+ dma_alignment = 1 << vi->dma_ch->device->copy_align;
+ x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+
dma_offset = daddr - round_down(daddr, dma_alignment);
daddr -= dma_offset;
len += dma_offset;
@@ -585,9 +588,9 @@ static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
}
err = 0;
err:
- vpdev->hw_ops->iounmap(vpdev, dbuf);
+ vpdev->hw_ops->unmap(vpdev, dbuf);
dev_dbg(vop_dev(vdev),
- "%s: ubuf %p dbuf %p len 0x%lx vr_idx 0x%x\n",
+ "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
__func__, ubuf, dbuf, len, vr_idx);
return err;
}
@@ -603,21 +606,26 @@ static int vop_virtio_copy_from_user(struct vop_vdev *vdev, void __user *ubuf,
int vr_idx)
{
struct vop_device *vpdev = vdev->vpdev;
- void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len);
+ void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
struct vop_vringh *vvr = &vdev->vvr[vr_idx];
struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
- size_t dma_alignment = 1 << vi->dma_ch->device->copy_align;
- bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+ size_t dma_alignment;
+ bool x200;
size_t partlen;
- bool dma = VOP_USE_DMA;
+ bool dma = VOP_USE_DMA && vi->dma_ch;
int err = 0;
- if (daddr & (dma_alignment - 1)) {
- vdev->tx_dst_unaligned += len;
- dma = false;
- } else if (ALIGN(len, dma_alignment) > dlen) {
- vdev->tx_len_unaligned += len;
- dma = false;
+ if (dma) {
+ dma_alignment = 1 << vi->dma_ch->device->copy_align;
+ x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+
+ if (daddr & (dma_alignment - 1)) {
+ vdev->tx_dst_unaligned += len;
+ dma = false;
+ } else if (ALIGN(len, dma_alignment) > dlen) {
+ vdev->tx_len_unaligned += len;
+ dma = false;
+ }
}
if (!dma)
@@ -668,9 +676,9 @@ memcpy:
vdev->out_bytes += len;
err = 0;
err:
- vpdev->hw_ops->iounmap(vpdev, dbuf);
+ vpdev->hw_ops->unmap(vpdev, dbuf);
dev_dbg(vop_dev(vdev),
- "%s: ubuf %p dbuf %p len 0x%lx vr_idx 0x%x\n",
+ "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
__func__, ubuf, dbuf, len, vr_idx);
return err;
}
@@ -704,16 +712,17 @@ static int vop_vringh_copy(struct vop_vdev *vdev, struct vringh_kiov *iov,
while (len && iov->i < iov->used) {
struct kvec *kiov = &iov->iov[iov->i];
+ unsigned long daddr = (unsigned long)kiov->iov_base;
partlen = min(kiov->iov_len, len);
if (read)
ret = vop_virtio_copy_to_user(vdev, ubuf, partlen,
- (u64)kiov->iov_base,
+ daddr,
kiov->iov_len,
vr_idx);
else
ret = vop_virtio_copy_from_user(vdev, ubuf, partlen,
- (u64)kiov->iov_base,
+ daddr,
kiov->iov_len,
vr_idx);
if (ret) {
diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c
index 595ac065b401..95ff7c5a1dfb 100644
--- a/drivers/misc/pvpanic.c
+++ b/drivers/misc/pvpanic.c
@@ -70,8 +70,12 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context)
struct resource r;
if (acpi_dev_resource_io(res, &r)) {
+#ifdef CONFIG_HAS_IOPORT_MAP
base = ioport_map(r.start, resource_size(&r));
return AE_OK;
+#else
+ return AE_ERROR;
+#endif
} else if (acpi_dev_resource_memory(res, &r)) {
base = ioremap(r.start, resource_size(&r));
return AE_OK;
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 93be82fc338a..2ec5808ba464 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -616,8 +616,8 @@ irqreturn_t gru_intr_mblade(int irq, void *dev_id)
for_each_possible_blade(blade) {
if (uv_blade_nr_possible_cpus(blade))
continue;
- gru_intr(0, blade);
- gru_intr(1, blade);
+ gru_intr(0, blade);
+ gru_intr(1, blade);
}
return IRQ_HANDLED;
}
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 0441abe87880..9e443df44b3b 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/numa.h>
#include <asm/uv/uv_hub.h>
#if defined CONFIG_X86_64
#include <asm/uv/bios.h>
@@ -61,7 +62,7 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
XPC_NOTIFY_MSG_SIZE_UV)
#define XPC_NOTIFY_IRQ_NAME "xpc_notify"
-static int xpc_mq_node = -1;
+static int xpc_mq_node = NUMA_NO_NODE;
static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index f8240b87df22..ad807d5a3141 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -34,7 +34,6 @@
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.5.0.0-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
@@ -73,15 +72,26 @@ enum vmwballoon_capabilities {
VMW_BALLOON_BATCHED_CMDS = (1 << 2),
VMW_BALLOON_BATCHED_2M_CMDS = (1 << 3),
VMW_BALLOON_SIGNALLED_WAKEUP_CMD = (1 << 4),
+ VMW_BALLOON_64_BIT_TARGET = (1 << 5)
};
-#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
+#define VMW_BALLOON_CAPABILITIES_COMMON (VMW_BALLOON_BASIC_CMDS \
| VMW_BALLOON_BATCHED_CMDS \
| VMW_BALLOON_BATCHED_2M_CMDS \
| VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
#define VMW_BALLOON_2M_ORDER (PMD_SHIFT - PAGE_SHIFT)
+/*
+ * 64-bit targets are only supported in 64-bit
+ */
+#ifdef CONFIG_64BIT
+#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_CAPABILITIES_COMMON \
+ | VMW_BALLOON_64_BIT_TARGET)
+#else
+#define VMW_BALLOON_CAPABILITIES VMW_BALLOON_CAPABILITIES_COMMON
+#endif
+
enum vmballoon_page_size_type {
VMW_BALLOON_4K_PAGE,
VMW_BALLOON_2M_PAGE,
@@ -557,6 +567,36 @@ vmballoon_page_in_frames(enum vmballoon_page_size_type page_size)
}
/**
+ * vmballoon_mark_page_offline() - mark a page as offline
+ * @page: pointer for the page.
+ * @page_size: the size of the page.
+ */
+static void
+vmballoon_mark_page_offline(struct page *page,
+ enum vmballoon_page_size_type page_size)
+{
+ int i;
+
+ for (i = 0; i < vmballoon_page_in_frames(page_size); i++)
+ __SetPageOffline(page + i);
+}
+
+/**
+ * vmballoon_mark_page_online() - mark a page as online
+ * @page: pointer for the page.
+ * @page_size: the size of the page.
+ */
+static void
+vmballoon_mark_page_online(struct page *page,
+ enum vmballoon_page_size_type page_size)
+{
+ int i;
+
+ for (i = 0; i < vmballoon_page_in_frames(page_size); i++)
+ __ClearPageOffline(page + i);
+}
+
+/**
* vmballoon_send_get_target() - Retrieve desired balloon size from the host.
*
* @b: pointer to the balloon.
@@ -572,8 +612,9 @@ static int vmballoon_send_get_target(struct vmballoon *b)
limit = totalram_pages();
- /* Ensure limit fits in 32-bits */
- if (limit != (u32)limit)
+ /* Ensure limit fits in 32-bits if 64-bit targets are not supported */
+ if (!(b->capabilities & VMW_BALLOON_64_BIT_TARGET) &&
+ limit != (u32)limit)
return -EINVAL;
status = vmballoon_cmd(b, VMW_BALLOON_CMD_GET_TARGET, limit, 0);
@@ -612,6 +653,7 @@ static int vmballoon_alloc_page_list(struct vmballoon *b,
ctl->page_size);
if (page) {
+ vmballoon_mark_page_offline(page, ctl->page_size);
/* Success. Add the page to the list and continue. */
list_add(&page->lru, &ctl->pages);
continue;
@@ -850,6 +892,7 @@ static void vmballoon_release_page_list(struct list_head *page_list,
list_for_each_entry_safe(page, tmp, page_list, lru) {
list_del(&page->lru);
+ vmballoon_mark_page_online(page, page_size);
__free_pages(page, vmballoon_page_order(page_size));
}
@@ -1287,7 +1330,7 @@ static void vmballoon_reset(struct vmballoon *b)
vmballoon_pop(b);
if (vmballoon_send_start(b, VMW_BALLOON_CAPABILITIES))
- return;
+ goto unlock;
if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
if (vmballoon_init_batching(b)) {
@@ -1298,7 +1341,7 @@ static void vmballoon_reset(struct vmballoon *b)
* The guest will retry in one second.
*/
vmballoon_send_start(b, 0);
- return;
+ goto unlock;
}
} else if ((b->capabilities & VMW_BALLOON_BASIC_CMDS) != 0) {
vmballoon_deinit_batching(b);
@@ -1314,6 +1357,7 @@ static void vmballoon_reset(struct vmballoon *b)
if (vmballoon_send_guest_id(b))
pr_err("failed to send guest ID to the host\n");
+unlock:
up_write(&b->conf_sem);
}
diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c b/drivers/misc/vmw_vmci/vmci_doorbell.c
index b3fa738ae005..7824c7494916 100644
--- a/drivers/misc/vmw_vmci/vmci_doorbell.c
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -330,7 +330,7 @@ int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
/*
* Register the notification bitmap with the host.
*/
-bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn)
+bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn)
{
int result;
struct vmci_notify_bm_set_msg bitmap_set_msg;
@@ -340,11 +340,14 @@ bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn)
bitmap_set_msg.hdr.src = VMCI_ANON_SRC_HANDLE;
bitmap_set_msg.hdr.payload_size = sizeof(bitmap_set_msg) -
VMCI_DG_HEADERSIZE;
- bitmap_set_msg.bitmap_ppn = bitmap_ppn;
+ if (vmci_use_ppn64())
+ bitmap_set_msg.bitmap_ppn64 = bitmap_ppn;
+ else
+ bitmap_set_msg.bitmap_ppn32 = (u32) bitmap_ppn;
result = vmci_send_datagram(&bitmap_set_msg.hdr);
if (result != VMCI_SUCCESS) {
- pr_devel("Failed to register (PPN=%u) as notification bitmap (error=%d)\n",
+ pr_devel("Failed to register (PPN=%llu) as notification bitmap (error=%d)\n",
bitmap_ppn, result);
return false;
}
diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.h b/drivers/misc/vmw_vmci/vmci_doorbell.h
index e4c0b17486a5..410a21f8436f 100644
--- a/drivers/misc/vmw_vmci/vmci_doorbell.h
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.h
@@ -45,7 +45,7 @@ struct dbell_cpt_state {
int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle);
int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags);
-bool vmci_dbell_register_notification_bitmap(u32 bitmap_ppn);
+bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn);
void vmci_dbell_scan_notification_entries(u8 *bitmap);
#endif /* VMCI_DOORBELL_H */
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h b/drivers/misc/vmw_vmci/vmci_driver.h
index cee9e977d318..2fbf4a0ac657 100644
--- a/drivers/misc/vmw_vmci/vmci_driver.h
+++ b/drivers/misc/vmw_vmci/vmci_driver.h
@@ -54,4 +54,6 @@ void vmci_guest_exit(void);
bool vmci_guest_code_active(void);
u32 vmci_get_vm_context_id(void);
+bool vmci_use_ppn64(void);
+
#endif /* _VMCI_DRIVER_H_ */
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
index dad5abee656e..928708128177 100644
--- a/drivers/misc/vmw_vmci/vmci_guest.c
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -64,6 +64,13 @@ struct vmci_guest_device {
dma_addr_t notification_base;
};
+static bool use_ppn64;
+
+bool vmci_use_ppn64(void)
+{
+ return use_ppn64;
+}
+
/* vmci_dev singleton device and supporting data*/
struct pci_dev *vmci_pdev;
static struct vmci_guest_device *vmci_dev_g;
@@ -432,6 +439,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
struct vmci_guest_device *vmci_dev;
void __iomem *iobase;
unsigned int capabilities;
+ unsigned int caps_in_use;
unsigned long cmd;
int vmci_err;
int error;
@@ -496,6 +504,23 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
error = -ENXIO;
goto err_free_data_buffer;
}
+ caps_in_use = VMCI_CAPS_DATAGRAM;
+
+ /*
+ * Use 64-bit PPNs if the device supports.
+ *
+ * There is no check for the return value of dma_set_mask_and_coherent
+ * since this driver can handle the default mask values if
+ * dma_set_mask_and_coherent fails.
+ */
+ if (capabilities & VMCI_CAPS_PPN64) {
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ use_ppn64 = true;
+ caps_in_use |= VMCI_CAPS_PPN64;
+ } else {
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
+ use_ppn64 = false;
+ }
/*
* If the hardware supports notifications, we will use that as
@@ -510,14 +535,14 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
"Unable to allocate notification bitmap\n");
} else {
memset(vmci_dev->notification_bitmap, 0, PAGE_SIZE);
- capabilities |= VMCI_CAPS_NOTIFICATIONS;
+ caps_in_use |= VMCI_CAPS_NOTIFICATIONS;
}
}
- dev_info(&pdev->dev, "Using capabilities 0x%x\n", capabilities);
+ dev_info(&pdev->dev, "Using capabilities 0x%x\n", caps_in_use);
/* Let the host know which capabilities we intend to use. */
- iowrite32(capabilities, vmci_dev->iobase + VMCI_CAPS_ADDR);
+ iowrite32(caps_in_use, vmci_dev->iobase + VMCI_CAPS_ADDR);
/* Set up global device so that we can start sending datagrams */
spin_lock_irq(&vmci_dev_spinlock);
@@ -529,13 +554,13 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
* Register notification bitmap with device if that capability is
* used.
*/
- if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
+ if (caps_in_use & VMCI_CAPS_NOTIFICATIONS) {
unsigned long bitmap_ppn =
vmci_dev->notification_base >> PAGE_SHIFT;
if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) {
dev_warn(&pdev->dev,
- "VMCI device unable to register notification bitmap with PPN 0x%x\n",
- (u32) bitmap_ppn);
+ "VMCI device unable to register notification bitmap with PPN 0x%lx\n",
+ bitmap_ppn);
error = -ENXIO;
goto err_remove_vmci_dev_g;
}
@@ -611,7 +636,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
/* Enable specific interrupt bits. */
cmd = VMCI_IMR_DATAGRAM;
- if (capabilities & VMCI_CAPS_NOTIFICATIONS)
+ if (caps_in_use & VMCI_CAPS_NOTIFICATIONS)
cmd |= VMCI_IMR_NOTIFICATION;
iowrite32(cmd, vmci_dev->iobase + VMCI_IMR_ADDR);
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 264f4ed8eef2..f5f1aac9d163 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -435,8 +435,8 @@ static int qp_alloc_ppn_set(void *prod_q,
void *cons_q,
u64 num_consume_pages, struct ppn_set *ppn_set)
{
- u32 *produce_ppns;
- u32 *consume_ppns;
+ u64 *produce_ppns;
+ u64 *consume_ppns;
struct vmci_queue *produce_q = prod_q;
struct vmci_queue *consume_q = cons_q;
u64 i;
@@ -462,31 +462,13 @@ static int qp_alloc_ppn_set(void *prod_q,
return VMCI_ERROR_NO_MEM;
}
- for (i = 0; i < num_produce_pages; i++) {
- unsigned long pfn;
-
+ for (i = 0; i < num_produce_pages; i++)
produce_ppns[i] =
produce_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
- pfn = produce_ppns[i];
-
- /* Fail allocation if PFN isn't supported by hypervisor. */
- if (sizeof(pfn) > sizeof(*produce_ppns)
- && pfn != produce_ppns[i])
- goto ppn_error;
- }
-
- for (i = 0; i < num_consume_pages; i++) {
- unsigned long pfn;
+ for (i = 0; i < num_consume_pages; i++)
consume_ppns[i] =
consume_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT;
- pfn = consume_ppns[i];
-
- /* Fail allocation if PFN isn't supported by hypervisor. */
- if (sizeof(pfn) > sizeof(*consume_ppns)
- && pfn != consume_ppns[i])
- goto ppn_error;
- }
ppn_set->num_produce_pages = num_produce_pages;
ppn_set->num_consume_pages = num_consume_pages;
@@ -494,11 +476,6 @@ static int qp_alloc_ppn_set(void *prod_q,
ppn_set->consume_ppns = consume_ppns;
ppn_set->initialized = true;
return VMCI_SUCCESS;
-
- ppn_error:
- kfree(produce_ppns);
- kfree(consume_ppns);
- return VMCI_ERROR_INVALID_ARGS;
}
/*
@@ -520,12 +497,28 @@ static void qp_free_ppn_set(struct ppn_set *ppn_set)
*/
static int qp_populate_ppn_set(u8 *call_buf, const struct ppn_set *ppn_set)
{
- memcpy(call_buf, ppn_set->produce_ppns,
- ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns));
- memcpy(call_buf +
- ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns),
- ppn_set->consume_ppns,
- ppn_set->num_consume_pages * sizeof(*ppn_set->consume_ppns));
+ if (vmci_use_ppn64()) {
+ memcpy(call_buf, ppn_set->produce_ppns,
+ ppn_set->num_produce_pages *
+ sizeof(*ppn_set->produce_ppns));
+ memcpy(call_buf +
+ ppn_set->num_produce_pages *
+ sizeof(*ppn_set->produce_ppns),
+ ppn_set->consume_ppns,
+ ppn_set->num_consume_pages *
+ sizeof(*ppn_set->consume_ppns));
+ } else {
+ int i;
+ u32 *ppns = (u32 *) call_buf;
+
+ for (i = 0; i < ppn_set->num_produce_pages; i++)
+ ppns[i] = (u32) ppn_set->produce_ppns[i];
+
+ ppns = &ppns[ppn_set->num_produce_pages];
+
+ for (i = 0; i < ppn_set->num_consume_pages; i++)
+ ppns[i] = (u32) ppn_set->consume_ppns[i];
+ }
return VMCI_SUCCESS;
}
@@ -951,13 +944,15 @@ static int qp_alloc_hypercall(const struct qp_guest_endpoint *entry)
{
struct vmci_qp_alloc_msg *alloc_msg;
size_t msg_size;
+ size_t ppn_size;
int result;
if (!entry || entry->num_ppns <= 2)
return VMCI_ERROR_INVALID_ARGS;
+ ppn_size = vmci_use_ppn64() ? sizeof(u64) : sizeof(u32);
msg_size = sizeof(*alloc_msg) +
- (size_t) entry->num_ppns * sizeof(u32);
+ (size_t) entry->num_ppns * ppn_size;
alloc_msg = kmalloc(msg_size, GFP_KERNEL);
if (!alloc_msg)
return VMCI_ERROR_NO_MEM;
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.h b/drivers/misc/vmw_vmci/vmci_queue_pair.h
index ed177f04ef24..46c0b6c7bafb 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.h
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.h
@@ -28,8 +28,8 @@ typedef int (*vmci_event_release_cb) (void *client_data);
struct ppn_set {
u64 num_produce_pages;
u64 num_consume_pages;
- u32 *produce_ppns;
- u32 *consume_ppns;
+ u64 *produce_ppns;
+ u64 *consume_ppns;
bool initialized;
};
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index abba078f7f49..95ffe008ebdf 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -8,7 +8,7 @@ mmc_core-y := core.o bus.o host.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
sdio_cis.o sdio_io.o sdio_irq.o \
- slot-gpio.o
+ slot-gpio.o regulator.o
mmc_core-$(CONFIG_OF) += pwrseq.o
obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o
obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index aef1185f383d..2c71a434c915 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1124,7 +1124,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
- unsigned int from, nr, arg;
+ unsigned int from, nr;
int err = 0, type = MMC_BLK_DISCARD;
blk_status_t status = BLK_STS_OK;
@@ -1136,24 +1136,18 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
- if (mmc_can_discard(card))
- arg = MMC_DISCARD_ARG;
- else if (mmc_can_trim(card))
- arg = MMC_TRIM_ARG;
- else
- arg = MMC_ERASE_ARG;
do {
err = 0;
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
- arg == MMC_TRIM_ARG ?
+ card->erase_arg == MMC_TRIM_ARG ?
INAND_CMD38_ARG_TRIM :
INAND_CMD38_ARG_ERASE,
0);
}
if (!err)
- err = mmc_erase(card, from, nr, arg);
+ err = mmc_erase(card, from, nr, card->erase_arg);
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
if (err)
status = BLK_STS_IOERR;
@@ -2112,7 +2106,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq)
if (waiting)
wake_up(&mq->wait);
else
- kblockd_schedule_work(&mq->complete_work);
+ queue_work(mq->card->complete_wq, &mq->complete_work);
return;
}
@@ -2380,12 +2374,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
"mmcblk%u%s", card->host->index, subname ? subname : "");
- if (mmc_card_mmc(card))
- blk_queue_logical_block_size(md->queue.queue,
- card->ext_csd.data_sector_size);
- else
- blk_queue_logical_block_size(md->queue.queue, 512);
-
set_capacity(md->disk, size);
if (mmc_host_cmd23(card->host)) {
@@ -2774,8 +2762,8 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
return ret;
}
-DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
- NULL, "%08llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
+ NULL, "%08llx\n");
/* That is two digits * 512 + 1 for newline */
#define EXT_CSD_STR_LEN 1025
@@ -2863,8 +2851,9 @@ static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
if (mmc_card_mmc(card) || mmc_card_sd(card)) {
md->status_dentry =
- debugfs_create_file("status", S_IRUSR, root, card,
- &mmc_dbg_card_status_fops);
+ debugfs_create_file_unsafe("status", 0400, root,
+ card,
+ &mmc_dbg_card_status_fops);
if (!md->status_dentry)
return -EIO;
}
@@ -2924,6 +2913,13 @@ static int mmc_blk_probe(struct mmc_card *card)
mmc_fixup_device(card, mmc_blk_fixups);
+ card->complete_wq = alloc_workqueue("mmc_complete",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ if (unlikely(!card->complete_wq)) {
+ pr_err("Failed to create mmc completion workqueue");
+ return -ENOMEM;
+ }
+
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
@@ -2987,6 +2983,7 @@ static void mmc_blk_remove(struct mmc_card *card)
pm_runtime_put_noidle(&card->dev);
mmc_blk_remove_req(md);
dev_set_drvdata(&card->dev, NULL);
+ destroy_workqueue(card->complete_wq);
}
static int _mmc_blk_suspend(struct mmc_card *card)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5bd58b95d318..6db36dc870b5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -21,7 +21,6 @@
#include <linux/leds.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
-#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeup.h>
#include <linux/suspend.h>
@@ -52,6 +51,7 @@
/* The max erase timeout, used when host->max_busy_timeout isn't specified */
#define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */
+#define SD_DISCARD_TIMEOUT_MS (250)
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
@@ -95,7 +95,7 @@ static void mmc_should_fail_request(struct mmc_host *host,
if (!data)
return;
- if (cmd->error || data->error ||
+ if ((cmd && cmd->error) || data->error ||
!should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
return;
@@ -758,33 +758,6 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_set_data_timeout);
-/**
- * mmc_align_data_size - pads a transfer size to a more optimal value
- * @card: the MMC card associated with the data transfer
- * @sz: original transfer size
- *
- * Pads the original data size with a number of extra bytes in
- * order to avoid controller bugs and/or performance hits
- * (e.g. some controllers revert to PIO for certain sizes).
- *
- * Returns the improved size, which might be unmodified.
- *
- * Note that this function is only relevant when issuing a
- * single scatter gather entry.
- */
-unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
-{
- /*
- * FIXME: We don't have a system for the controller to tell
- * the core about its problems yet, so for now we just 32-bit
- * align the size.
- */
- sz = ((sz + 3) / 4) * 4;
-
- return sz;
-}
-EXPORT_SYMBOL(mmc_align_data_size);
-
/*
* Allow claiming an already claimed host if the context is the same or there is
* no context but the task is the same.
@@ -1112,55 +1085,6 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
return mask;
}
-EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
-
-#ifdef CONFIG_OF
-
-/**
- * mmc_of_parse_voltage - return mask of supported voltages
- * @np: The device node need to be parsed.
- * @mask: mask of voltages available for MMC/SD/SDIO
- *
- * Parse the "voltage-ranges" DT property, returning zero if it is not
- * found, negative errno if the voltage-range specification is invalid,
- * or one if the voltage-range is specified and successfully parsed.
- */
-int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
-{
- const u32 *voltage_ranges;
- int num_ranges, i;
-
- voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
- num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
- if (!voltage_ranges) {
- pr_debug("%pOF: voltage-ranges unspecified\n", np);
- return 0;
- }
- if (!num_ranges) {
- pr_err("%pOF: voltage-ranges empty\n", np);
- return -EINVAL;
- }
-
- for (i = 0; i < num_ranges; i++) {
- const int j = i * 2;
- u32 ocr_mask;
-
- ocr_mask = mmc_vddrange_to_ocrmask(
- be32_to_cpu(voltage_ranges[j]),
- be32_to_cpu(voltage_ranges[j + 1]));
- if (!ocr_mask) {
- pr_err("%pOF: voltage-range #%d is invalid\n",
- np, i);
- return -EINVAL;
- }
- *mask |= ocr_mask;
- }
-
- return 1;
-}
-EXPORT_SYMBOL(mmc_of_parse_voltage);
-
-#endif /* CONFIG_OF */
static int mmc_of_get_func_num(struct device_node *node)
{
@@ -1190,246 +1114,6 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host,
return NULL;
}
-#ifdef CONFIG_REGULATOR
-
-/**
- * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage
- * @vdd_bit: OCR bit number
- * @min_uV: minimum voltage value (mV)
- * @max_uV: maximum voltage value (mV)
- *
- * This function returns the voltage range according to the provided OCR
- * bit number. If conversion is not possible a negative errno value returned.
- */
-static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV)
-{
- int tmp;
-
- if (!vdd_bit)
- return -EINVAL;
-
- /*
- * REVISIT mmc_vddrange_to_ocrmask() may have set some
- * bits this regulator doesn't quite support ... don't
- * be too picky, most cards and regulators are OK with
- * a 0.1V range goof (it's a small error percentage).
- */
- tmp = vdd_bit - ilog2(MMC_VDD_165_195);
- if (tmp == 0) {
- *min_uV = 1650 * 1000;
- *max_uV = 1950 * 1000;
- } else {
- *min_uV = 1900 * 1000 + tmp * 100 * 1000;
- *max_uV = *min_uV + 100 * 1000;
- }
-
- return 0;
-}
-
-/**
- * mmc_regulator_get_ocrmask - return mask of supported voltages
- * @supply: regulator to use
- *
- * This returns either a negative errno, or a mask of voltages that
- * can be provided to MMC/SD/SDIO devices using the specified voltage
- * regulator. This would normally be called before registering the
- * MMC host adapter.
- */
-int mmc_regulator_get_ocrmask(struct regulator *supply)
-{
- int result = 0;
- int count;
- int i;
- int vdd_uV;
- int vdd_mV;
-
- count = regulator_count_voltages(supply);
- if (count < 0)
- return count;
-
- for (i = 0; i < count; i++) {
- vdd_uV = regulator_list_voltage(supply, i);
- if (vdd_uV <= 0)
- continue;
-
- vdd_mV = vdd_uV / 1000;
- result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
- }
-
- if (!result) {
- vdd_uV = regulator_get_voltage(supply);
- if (vdd_uV <= 0)
- return vdd_uV;
-
- vdd_mV = vdd_uV / 1000;
- result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
- }
-
- return result;
-}
-EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);
-
-/**
- * mmc_regulator_set_ocr - set regulator to match host->ios voltage
- * @mmc: the host to regulate
- * @supply: regulator to use
- * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
- *
- * Returns zero on success, else negative errno.
- *
- * MMC host drivers may use this to enable or disable a regulator using
- * a particular supply voltage. This would normally be called from the
- * set_ios() method.
- */
-int mmc_regulator_set_ocr(struct mmc_host *mmc,
- struct regulator *supply,
- unsigned short vdd_bit)
-{
- int result = 0;
- int min_uV, max_uV;
-
- if (vdd_bit) {
- mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV);
-
- result = regulator_set_voltage(supply, min_uV, max_uV);
- if (result == 0 && !mmc->regulator_enabled) {
- result = regulator_enable(supply);
- if (!result)
- mmc->regulator_enabled = true;
- }
- } else if (mmc->regulator_enabled) {
- result = regulator_disable(supply);
- if (result == 0)
- mmc->regulator_enabled = false;
- }
-
- if (result)
- dev_err(mmc_dev(mmc),
- "could not set regulator OCR (%d)\n", result);
- return result;
-}
-EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
-
-static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
- int min_uV, int target_uV,
- int max_uV)
-{
- /*
- * Check if supported first to avoid errors since we may try several
- * signal levels during power up and don't want to show errors.
- */
- if (!regulator_is_supported_voltage(regulator, min_uV, max_uV))
- return -EINVAL;
-
- return regulator_set_voltage_triplet(regulator, min_uV, target_uV,
- max_uV);
-}
-
-/**
- * mmc_regulator_set_vqmmc - Set VQMMC as per the ios
- *
- * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
- * That will match the behavior of old boards where VQMMC and VMMC were supplied
- * by the same supply. The Bus Operating conditions for 3.3V signaling in the
- * SD card spec also define VQMMC in terms of VMMC.
- * If this is not possible we'll try the full 2.7-3.6V of the spec.
- *
- * For 1.2V and 1.8V signaling we'll try to get as close as possible to the
- * requested voltage. This is definitely a good idea for UHS where there's a
- * separate regulator on the card that's trying to make 1.8V and it's best if
- * we match.
- *
- * This function is expected to be used by a controller's
- * start_signal_voltage_switch() function.
- */
-int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
-{
- struct device *dev = mmc_dev(mmc);
- int ret, volt, min_uV, max_uV;
-
- /* If no vqmmc supply then we can't change the voltage */
- if (IS_ERR(mmc->supply.vqmmc))
- return -EINVAL;
-
- switch (ios->signal_voltage) {
- case MMC_SIGNAL_VOLTAGE_120:
- return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
- 1100000, 1200000, 1300000);
- case MMC_SIGNAL_VOLTAGE_180:
- return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
- 1700000, 1800000, 1950000);
- case MMC_SIGNAL_VOLTAGE_330:
- ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV);
- if (ret < 0)
- return ret;
-
- dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n",
- __func__, volt, max_uV);
-
- min_uV = max(volt - 300000, 2700000);
- max_uV = min(max_uV + 200000, 3600000);
-
- /*
- * Due to a limitation in the current implementation of
- * regulator_set_voltage_triplet() which is taking the lowest
- * voltage possible if below the target, search for a suitable
- * voltage in two steps and try to stay close to vmmc
- * with a 0.3V tolerance at first.
- */
- if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
- min_uV, volt, max_uV))
- return 0;
-
- return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
- 2700000, volt, 3600000);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
-
-#endif /* CONFIG_REGULATOR */
-
-/**
- * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host
- * @mmc: the host to regulate
- *
- * Returns 0 or errno. errno should be handled, it is either a critical error
- * or -EPROBE_DEFER. 0 means no critical error but it does not mean all
- * regulators have been found because they all are optional. If you require
- * certain regulators, you need to check separately in your driver if they got
- * populated after calling this function.
- */
-int mmc_regulator_get_supply(struct mmc_host *mmc)
-{
- struct device *dev = mmc_dev(mmc);
- int ret;
-
- mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
- mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
-
- if (IS_ERR(mmc->supply.vmmc)) {
- if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- dev_dbg(dev, "No vmmc regulator found\n");
- } else {
- ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
- if (ret > 0)
- mmc->ocr_avail = ret;
- else
- dev_warn(dev, "Failed getting OCR mask: %d\n", ret);
- }
-
- if (IS_ERR(mmc->supply.vqmmc)) {
- if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- dev_dbg(dev, "No vqmmc regulator found\n");
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
-
/*
* Mask off any voltages we don't support and select
* the lowest voltage
@@ -1936,6 +1620,12 @@ static unsigned int mmc_sd_erase_timeout(struct mmc_card *card,
{
unsigned int erase_timeout;
+ /* for DISCARD none of the below calculation applies.
+ * the busy timeout is 250msec per discard command.
+ */
+ if (arg == SD_DISCARD_ARG)
+ return SD_DISCARD_TIMEOUT_MS;
+
if (card->ssr.erase_timeout) {
/* Erase timeout specified in SD Status Register (SSR) */
erase_timeout = card->ssr.erase_timeout * qty +
@@ -2164,7 +1854,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card,
* @card: card to erase
* @from: first sector to erase
* @nr: number of sectors to erase
- * @arg: erase command argument (SD supports only %MMC_ERASE_ARG)
+ * @arg: erase command argument
*
* Caller must claim host before calling this function.
*/
@@ -2181,14 +1871,14 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
if (!card->erase_size)
return -EOPNOTSUPP;
- if (mmc_card_sd(card) && arg != MMC_ERASE_ARG)
+ if (mmc_card_sd(card) && arg != SD_ERASE_ARG && arg != SD_DISCARD_ARG)
return -EOPNOTSUPP;
- if ((arg & MMC_SECURE_ARGS) &&
+ if (mmc_card_mmc(card) && (arg & MMC_SECURE_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
return -EOPNOTSUPP;
- if ((arg & MMC_TRIM_ARGS) &&
+ if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
return -EOPNOTSUPP;
@@ -2381,9 +2071,9 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
return card->pref_erase;
max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
- if (max_discard && mmc_can_trim(card)) {
+ if (mmc_can_trim(card)) {
max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG);
- if (max_trim < max_discard)
+ if (max_trim < max_discard || max_discard == 0)
max_discard = max_trim;
} else if (max_discard < card->erase_size) {
max_discard = 0;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 8fb6bc37f808..b5083b13d594 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -59,6 +59,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr);
void mmc_power_off(struct mmc_host *host);
void mmc_power_cycle(struct mmc_host *host, u32 ocr);
void mmc_set_initial_state(struct mmc_host *host);
+u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
static inline void mmc_delay(unsigned int ms)
{
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index f57f5de54206..3a4402a79904 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -194,7 +194,7 @@ int mmc_of_parse(struct mmc_host *host)
switch (bus_width) {
case 8:
host->caps |= MMC_CAP_8_BIT_DATA;
- /* Hosts capable of 8-bit transfers can also do 4 bits */
+ /* fall through - Hosts capable of 8-bit can also do 4 bits */
case 4:
host->caps |= MMC_CAP_4_BIT_DATA;
break;
@@ -234,7 +234,7 @@ int mmc_of_parse(struct mmc_host *host)
if (device_property_read_bool(dev, "broken-cd"))
host->caps |= MMC_CAP_NEEDS_POLL;
- ret = mmc_gpiod_request_cd(host, "cd", 0, true,
+ ret = mmc_gpiod_request_cd(host, "cd", 0, false,
cd_debounce_delay_ms * 1000,
&cd_gpio_invert);
if (!ret)
@@ -260,7 +260,7 @@ int mmc_of_parse(struct mmc_host *host)
/* Parse Write Protection */
ro_cap_invert = device_property_read_bool(dev, "wp-inverted");
- ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
+ ret = mmc_gpiod_request_ro(host, "wp", 0, 0, &ro_gpio_invert);
if (!ret)
dev_info(host->parent, "Got WP GPIO\n");
else if (ret != -ENOENT && ret != -ENOSYS)
@@ -349,6 +349,50 @@ int mmc_of_parse(struct mmc_host *host)
EXPORT_SYMBOL(mmc_of_parse);
/**
+ * mmc_of_parse_voltage - return mask of supported voltages
+ * @np: The device node need to be parsed.
+ * @mask: mask of voltages available for MMC/SD/SDIO
+ *
+ * Parse the "voltage-ranges" DT property, returning zero if it is not
+ * found, negative errno if the voltage-range specification is invalid,
+ * or one if the voltage-range is specified and successfully parsed.
+ */
+int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
+{
+ const u32 *voltage_ranges;
+ int num_ranges, i;
+
+ voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+ num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+ if (!voltage_ranges) {
+ pr_debug("%pOF: voltage-ranges unspecified\n", np);
+ return 0;
+ }
+ if (!num_ranges) {
+ pr_err("%pOF: voltage-ranges empty\n", np);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_ranges; i++) {
+ const int j = i * 2;
+ u32 ocr_mask;
+
+ ocr_mask = mmc_vddrange_to_ocrmask(
+ be32_to_cpu(voltage_ranges[j]),
+ be32_to_cpu(voltage_ranges[j + 1]));
+ if (!ocr_mask) {
+ pr_err("%pOF: voltage-range #%d is invalid\n",
+ np, i);
+ return -EINVAL;
+ }
+ *mask |= ocr_mask;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL(mmc_of_parse_voltage);
+
+/**
* mmc_alloc_host - initialise the per-host structure.
* @extra: sizeof private data structure
* @dev: pointer to host device model structure
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index da892a599524..3e786ba204c3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1594,6 +1594,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
err = -ENOENT;
goto err;
}
@@ -1743,6 +1745,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
}
+ /* set erase_arg */
+ if (mmc_can_discard(card))
+ card->erase_arg = MMC_DISCARD_ARG;
+ else if (mmc_can_trim(card))
+ card->erase_arg = MMC_TRIM_ARG;
+ else
+ card->erase_arg = MMC_ERASE_ARG;
+
/*
* Select timing interface
*/
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 9054329fe903..c5208fb312ae 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -562,7 +562,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
- err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+ err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
goto out;
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 35cc138b096d..15a45ec6518d 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -355,6 +355,7 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
{
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
+ unsigned block_size = 512;
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
@@ -368,7 +369,13 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
blk_queue_max_hw_sectors(mq->queue,
min(host->max_blk_count, host->max_req_size / 512));
blk_queue_max_segments(mq->queue, host->max_segs);
- blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+ if (mmc_card_mmc(card))
+ block_size = card->ext_csd.data_sector_size;
+
+ blk_queue_logical_block_size(mq->queue, block_size);
+ blk_queue_max_segment_size(mq->queue,
+ round_down(host->max_seg_size, block_size));
INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler);
INIT_WORK(&mq->complete_work, mmc_blk_mq_complete_work);
diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c
new file mode 100644
index 000000000000..b6febbcf8978
--- /dev/null
+++ b/drivers/mmc/core/regulator.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Helper functions for MMC regulators.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/log2.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "host.h"
+
+#ifdef CONFIG_REGULATOR
+
+/**
+ * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage
+ * @vdd_bit: OCR bit number
+ * @min_uV: minimum voltage value (mV)
+ * @max_uV: maximum voltage value (mV)
+ *
+ * This function returns the voltage range according to the provided OCR
+ * bit number. If conversion is not possible a negative errno value returned.
+ */
+static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV)
+{
+ int tmp;
+
+ if (!vdd_bit)
+ return -EINVAL;
+
+ /*
+ * REVISIT mmc_vddrange_to_ocrmask() may have set some
+ * bits this regulator doesn't quite support ... don't
+ * be too picky, most cards and regulators are OK with
+ * a 0.1V range goof (it's a small error percentage).
+ */
+ tmp = vdd_bit - ilog2(MMC_VDD_165_195);
+ if (tmp == 0) {
+ *min_uV = 1650 * 1000;
+ *max_uV = 1950 * 1000;
+ } else {
+ *min_uV = 1900 * 1000 + tmp * 100 * 1000;
+ *max_uV = *min_uV + 100 * 1000;
+ }
+
+ return 0;
+}
+
+/**
+ * mmc_regulator_get_ocrmask - return mask of supported voltages
+ * @supply: regulator to use
+ *
+ * This returns either a negative errno, or a mask of voltages that
+ * can be provided to MMC/SD/SDIO devices using the specified voltage
+ * regulator. This would normally be called before registering the
+ * MMC host adapter.
+ */
+static int mmc_regulator_get_ocrmask(struct regulator *supply)
+{
+ int result = 0;
+ int count;
+ int i;
+ int vdd_uV;
+ int vdd_mV;
+
+ count = regulator_count_voltages(supply);
+ if (count < 0)
+ return count;
+
+ for (i = 0; i < count; i++) {
+ vdd_uV = regulator_list_voltage(supply, i);
+ if (vdd_uV <= 0)
+ continue;
+
+ vdd_mV = vdd_uV / 1000;
+ result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
+ }
+
+ if (!result) {
+ vdd_uV = regulator_get_voltage(supply);
+ if (vdd_uV <= 0)
+ return vdd_uV;
+
+ vdd_mV = vdd_uV / 1000;
+ result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
+ }
+
+ return result;
+}
+
+/**
+ * mmc_regulator_set_ocr - set regulator to match host->ios voltage
+ * @mmc: the host to regulate
+ * @supply: regulator to use
+ * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * MMC host drivers may use this to enable or disable a regulator using
+ * a particular supply voltage. This would normally be called from the
+ * set_ios() method.
+ */
+int mmc_regulator_set_ocr(struct mmc_host *mmc,
+ struct regulator *supply,
+ unsigned short vdd_bit)
+{
+ int result = 0;
+ int min_uV, max_uV;
+
+ if (vdd_bit) {
+ mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV);
+
+ result = regulator_set_voltage(supply, min_uV, max_uV);
+ if (result == 0 && !mmc->regulator_enabled) {
+ result = regulator_enable(supply);
+ if (!result)
+ mmc->regulator_enabled = true;
+ }
+ } else if (mmc->regulator_enabled) {
+ result = regulator_disable(supply);
+ if (result == 0)
+ mmc->regulator_enabled = false;
+ }
+
+ if (result)
+ dev_err(mmc_dev(mmc),
+ "could not set regulator OCR (%d)\n", result);
+ return result;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
+
+static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
+ int min_uV, int target_uV,
+ int max_uV)
+{
+ /*
+ * Check if supported first to avoid errors since we may try several
+ * signal levels during power up and don't want to show errors.
+ */
+ if (!regulator_is_supported_voltage(regulator, min_uV, max_uV))
+ return -EINVAL;
+
+ return regulator_set_voltage_triplet(regulator, min_uV, target_uV,
+ max_uV);
+}
+
+/**
+ * mmc_regulator_set_vqmmc - Set VQMMC as per the ios
+ *
+ * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
+ * That will match the behavior of old boards where VQMMC and VMMC were supplied
+ * by the same supply. The Bus Operating conditions for 3.3V signaling in the
+ * SD card spec also define VQMMC in terms of VMMC.
+ * If this is not possible we'll try the full 2.7-3.6V of the spec.
+ *
+ * For 1.2V and 1.8V signaling we'll try to get as close as possible to the
+ * requested voltage. This is definitely a good idea for UHS where there's a
+ * separate regulator on the card that's trying to make 1.8V and it's best if
+ * we match.
+ *
+ * This function is expected to be used by a controller's
+ * start_signal_voltage_switch() function.
+ */
+int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct device *dev = mmc_dev(mmc);
+ int ret, volt, min_uV, max_uV;
+
+ /* If no vqmmc supply then we can't change the voltage */
+ if (IS_ERR(mmc->supply.vqmmc))
+ return -EINVAL;
+
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_120:
+ return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
+ 1100000, 1200000, 1300000);
+ case MMC_SIGNAL_VOLTAGE_180:
+ return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
+ 1700000, 1800000, 1950000);
+ case MMC_SIGNAL_VOLTAGE_330:
+ ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n",
+ __func__, volt, max_uV);
+
+ min_uV = max(volt - 300000, 2700000);
+ max_uV = min(max_uV + 200000, 3600000);
+
+ /*
+ * Due to a limitation in the current implementation of
+ * regulator_set_voltage_triplet() which is taking the lowest
+ * voltage possible if below the target, search for a suitable
+ * voltage in two steps and try to stay close to vmmc
+ * with a 0.3V tolerance at first.
+ */
+ if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
+ min_uV, volt, max_uV))
+ return 0;
+
+ return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc,
+ 2700000, volt, 3600000);
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
+
+#else
+
+static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
+{
+ return 0;
+}
+
+#endif /* CONFIG_REGULATOR */
+
+/**
+ * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host
+ * @mmc: the host to regulate
+ *
+ * Returns 0 or errno. errno should be handled, it is either a critical error
+ * or -EPROBE_DEFER. 0 means no critical error but it does not mean all
+ * regulators have been found because they all are optional. If you require
+ * certain regulators, you need to check separately in your driver if they got
+ * populated after calling this function.
+ */
+int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+ struct device *dev = mmc_dev(mmc);
+ int ret;
+
+ mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
+ mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
+
+ if (IS_ERR(mmc->supply.vmmc)) {
+ if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_dbg(dev, "No vmmc regulator found\n");
+ } else {
+ ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
+ if (ret > 0)
+ mmc->ocr_avail = ret;
+ else
+ dev_warn(dev, "Failed getting OCR mask: %d\n", ret);
+ }
+
+ if (IS_ERR(mmc->supply.vqmmc)) {
+ if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_dbg(dev, "No vqmmc regulator found\n");
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index d0d9f90e7cdf..265e1aeeb9d8 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -209,6 +209,11 @@ static int mmc_decode_scr(struct mmc_card *card)
/* Check if Physical Layer Spec v3.0 is supported */
scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1);
+ if (scr->sda_spec3) {
+ scr->sda_spec4 = UNSTUFF_BITS(resp, 42, 1);
+ scr->sda_specx = UNSTUFF_BITS(resp, 38, 4);
+ }
+
if (UNSTUFF_BITS(resp, 55, 1))
card->erased_byte = 0xFF;
else
@@ -226,6 +231,8 @@ static int mmc_read_ssr(struct mmc_card *card)
{
unsigned int au, es, et, eo;
__be32 *raw_ssr;
+ u32 resp[4] = {};
+ u8 discard_support;
int i;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@@ -271,6 +278,14 @@ static int mmc_read_ssr(struct mmc_card *card)
}
}
+ /*
+ * starting SD5.1 discard is supported if DISCARD_SUPPORT (b313) is set
+ */
+ resp[3] = card->raw_ssr[6];
+ discard_support = UNSTUFF_BITS(resp, 313 - 288, 1);
+ card->erase_arg = (card->scr.sda_specx && discard_support) ?
+ SD_DISCARD_ARG : SD_ERASE_ARG;
+
return 0;
}
@@ -936,8 +951,11 @@ retry:
return err;
if (oldcard) {
- if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+ if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
return -ENOENT;
+ }
card = oldcard;
} else {
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 47056d8d1bac..0bb0b8419016 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -52,36 +52,17 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
}
EXPORT_SYMBOL_GPL(mmc_app_cmd);
-/**
- * mmc_wait_for_app_cmd - start an application command and wait for
- completion
- * @host: MMC host to start command
- * @card: Card to send MMC_APP_CMD to
- * @cmd: MMC command to start
- * @retries: maximum number of retries
- *
- * Sends a MMC_APP_CMD, checks the card response, sends the command
- * in the parameter and waits for it to complete. Return any error
- * that occurred while the command was executing. Do not attempt to
- * parse the response.
- */
-int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
- struct mmc_command *cmd, int retries)
+static int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
+ struct mmc_command *cmd)
{
struct mmc_request mrq = {};
-
- int i, err;
-
- if (retries < 0)
- retries = MMC_CMD_RETRIES;
-
- err = -EIO;
+ int i, err = -EIO;
/*
* We have to resend MMC_APP_CMD for each attempt so
* we cannot use the retries field in mmc_command.
*/
- for (i = 0;i <= retries;i++) {
+ for (i = 0; i <= MMC_CMD_RETRIES; i++) {
err = mmc_app_cmd(host, card);
if (err) {
/* no point in retrying; no APP commands allowed */
@@ -116,8 +97,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
return err;
}
-EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-
int mmc_app_set_bus_width(struct mmc_card *card, int width)
{
struct mmc_command cmd = {};
@@ -136,7 +115,7 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width)
return -EINVAL;
}
- return mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
+ return mmc_wait_for_app_cmd(card->host, card, &cmd);
}
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
@@ -152,7 +131,7 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
- err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
+ err = mmc_wait_for_app_cmd(host, NULL, &cmd);
if (err)
break;
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index 0e6c3d51e66d..ffaed5cacc88 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -16,7 +16,6 @@
struct mmc_card;
struct mmc_host;
-struct mmc_command;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
@@ -27,8 +26,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
-int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
- struct mmc_command *cmd, int retries);
#endif
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index d8e17ea6126d..6718fc8bb40f 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -617,6 +617,8 @@ try_again:
if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {
mmc_remove_card(card);
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
return -ENOENT;
}
} else {
@@ -624,6 +626,8 @@ try_again:
if (oldcard && oldcard->type != MMC_TYPE_SDIO) {
mmc_remove_card(card);
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
return -ENOENT;
}
}
@@ -736,8 +740,11 @@ try_again:
int same = (card->cis.vendor == oldcard->cis.vendor &&
card->cis.device == oldcard->cis.device);
mmc_remove_card(card);
- if (!same)
+ if (!same) {
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
return -ENOENT;
+ }
card = oldcard;
}
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index b6d8203e46eb..62b0f5ecc7f7 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -179,7 +179,6 @@ static int sdio_bus_remove(struct device *dev)
{
struct sdio_driver *drv = to_sdio_driver(dev->driver);
struct sdio_func *func = dev_to_sdio_func(dev);
- int ret = 0;
/* Make sure card is powered before invoking ->remove() */
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
@@ -205,7 +204,7 @@ static int sdio_bus_remove(struct device *dev)
dev_pm_domain_detach(dev, false);
- return ret;
+ return 0;
}
static const struct dev_pm_ops sdio_bus_pm_ops = {
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index d40744bbafa9..3f67fbbe0d75 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -10,6 +10,7 @@
*/
#include <linux/export.h>
+#include <linux/kernel.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
@@ -203,6 +204,21 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
return min(mval, 512u); /* maximum size for byte mode */
}
+/*
+ * This is legacy code, which needs to be re-worked some day. Basically we need
+ * to take into account the properties of the host, as to enable the SDIO func
+ * driver layer to allocate optimal buffers.
+ */
+static inline unsigned int _sdio_align_size(unsigned int sz)
+{
+ /*
+ * FIXME: We don't have a system for the controller to tell
+ * the core about its problems yet, so for now we just 32-bit
+ * align the size.
+ */
+ return ALIGN(sz, 4);
+}
+
/**
* sdio_align_size - pads a transfer size to a more optimal value
* @func: SDIO function
@@ -230,7 +246,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* wants to increase the size up to a point where it
* might need more than one block.
*/
- sz = mmc_align_data_size(func->card, sz);
+ sz = _sdio_align_size(sz);
/*
* If we can still do this with just a byte transfer, then
@@ -252,7 +268,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
*/
blk_sz = ((sz + func->cur_blksize - 1) /
func->cur_blksize) * func->cur_blksize;
- blk_sz = mmc_align_data_size(func->card, blk_sz);
+ blk_sz = _sdio_align_size(blk_sz);
/*
* This value is only good if it is still just
@@ -265,8 +281,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* We failed to do one request, but at least try to
* pad the remainder properly.
*/
- byte_sz = mmc_align_data_size(func->card,
- sz % func->cur_blksize);
+ byte_sz = _sdio_align_size(sz % func->cur_blksize);
if (byte_sz <= sdio_max_byte_size(func)) {
blk_sz = sz / func->cur_blksize;
return blk_sz * func->cur_blksize + byte_sz;
@@ -276,16 +291,14 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
* We need multiple requests, so first check that the
* controller can handle the chunk size;
*/
- chunk_sz = mmc_align_data_size(func->card,
- sdio_max_byte_size(func));
+ chunk_sz = _sdio_align_size(sdio_max_byte_size(func));
if (chunk_sz == sdio_max_byte_size(func)) {
/*
* Fix up the size of the remainder (if any)
*/
byte_sz = orig_sz % chunk_sz;
if (byte_sz) {
- byte_sz = mmc_align_data_size(func->card,
- byte_sz);
+ byte_sz = _sdio_align_size(byte_sz);
}
return (orig_sz / chunk_sz) * chunk_sz + byte_sz;
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index 96945cafbf0b..1f6d0447ea0f 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -25,7 +25,6 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
int sdio_reset(struct mmc_host *host);
-unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz);
void sdio_irq_work(struct work_struct *work);
static inline bool sdio_is_io_busy(u32 opcode, u32 arg)
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 319ccd93383d..4afc6b87b465 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -22,7 +22,6 @@
struct mmc_gpio {
struct gpio_desc *ro_gpio;
struct gpio_desc *cd_gpio;
- bool override_ro_active_level;
bool override_cd_active_level;
irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);
char *ro_label;
@@ -71,10 +70,6 @@ int mmc_gpio_get_ro(struct mmc_host *host)
if (!ctx || !ctx->ro_gpio)
return -ENOSYS;
- if (ctx->override_ro_active_level)
- return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^
- !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
-
return gpiod_get_value_cansleep(ctx->ro_gpio);
}
EXPORT_SYMBOL(mmc_gpio_get_ro);
@@ -225,7 +220,6 @@ EXPORT_SYMBOL(mmc_can_gpio_cd);
* @host: mmc host
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
- * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
* @debounce: debounce time in microseconds
* @gpio_invert: will return whether the GPIO line is inverted or not,
* set to NULL to ignore
@@ -233,7 +227,7 @@ EXPORT_SYMBOL(mmc_can_gpio_cd);
* Returns zero on success, else an error.
*/
int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
- unsigned int idx, bool override_active_level,
+ unsigned int idx,
unsigned int debounce, bool *gpio_invert)
{
struct mmc_gpio *ctx = host->slot.handler_priv;
@@ -253,7 +247,6 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
if (gpio_invert)
*gpio_invert = !gpiod_is_active_low(desc);
- ctx->override_ro_active_level = override_active_level;
ctx->ro_gpio = desc;
return 0;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index e26b8145efb3..28fcd8f580a1 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -116,7 +116,7 @@ config MMC_RICOH_MMC
config MMC_SDHCI_ACPI
tristate "SDHCI support for ACPI enumerated SDHCI controllers"
- depends on MMC_SDHCI && ACPI
+ depends on MMC_SDHCI && ACPI && PCI
select IOSF_MBI if X86
help
This selects support for ACPI enumerated SDHCI controllers,
@@ -224,6 +224,7 @@ config MMC_SDHCI_ESDHC_IMX
depends on ARCH_MXC
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
+ select MMC_CQHCI
help
This selects the Freescale eSDHC/uSDHC controller support
found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@@ -250,6 +251,7 @@ config MMC_SDHCI_TEGRA
depends on ARCH_TEGRA
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
+ select MMC_CQHCI
help
This selects the Tegra SD/MMC controller. If you have a Tegra
platform with SD or MMC devices, say Y or M here.
@@ -978,7 +980,7 @@ config MMC_SDHCI_OMAP
tristate "TI SDHCI Controller Support"
depends on MMC_SDHCI_PLTFM && OF
select THERMAL
- select TI_SOC_THERMAL
+ imply TI_SOC_THERMAL
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's DRA7 SOCs. The controller supports
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 47189f9ed4e2..735aa5871358 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1410,6 +1410,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_BUS_WIDTH_4:
slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
break;
+ case MMC_BUS_WIDTH_8:
+ slot->sdc_reg |= ATMCI_SDCBUS_8BIT;
+ break;
}
if (ios->clock) {
@@ -2275,8 +2278,11 @@ static int atmci_init_slot(struct atmel_mci *host,
* use only one bit for data to prevent fifo underruns and overruns
* which will corrupt data.
*/
- if ((slot_data->bus_width >= 4) && host->caps.has_rwproof)
+ if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) {
mmc->caps |= MMC_CAP_4_BIT_DATA;
+ if (slot_data->bus_width >= 8)
+ mmc->caps |= MMC_CAP_8_BIT_DATA;
+ }
if (atmci_get_version(host) < 0x200) {
mmc->max_segs = 256;
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 50293529d6de..7e0d3a49c06d 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -148,7 +148,6 @@ struct bcm2835_host {
void __iomem *ioaddr;
u32 phys_addr;
- struct mmc_host *mmc;
struct platform_device *pdev;
int clock; /* Current clock speed */
@@ -618,7 +617,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
"failed to terminate DMA (%d)\n", err);
}
- mmc_request_done(host->mmc, mrq);
+ mmc_request_done(mmc_from_priv(host), mrq);
}
static
@@ -837,7 +836,7 @@ static void bcm2835_timeout(struct work_struct *work)
dev_err(dev, "timeout waiting for hardware interrupt.\n");
bcm2835_dumpregs(host);
- bcm2835_reset(host->mmc);
+ bcm2835_reset(mmc_from_priv(host));
if (host->data) {
host->data->error = -ETIMEDOUT;
@@ -1100,6 +1099,7 @@ static void bcm2835_dma_complete_work(struct work_struct *work)
static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
{
+ struct mmc_host *mmc = mmc_from_priv(host);
int div;
/* The SDCDIV register has 11 bits, and holds (div - 2). But
@@ -1143,18 +1143,18 @@ static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
div = SDCDIV_MAX_CDIV;
clock = host->max_clk / (div + 2);
- host->mmc->actual_clock = clock;
+ mmc->actual_clock = clock;
/* Calibrate some delays */
host->ns_per_fifo_word = (1000000000 / clock) *
- ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
+ ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
host->cdiv = div;
writel(host->cdiv, host->ioaddr + SDCDIV);
/* Set the timeout to 500ms */
- writel(host->mmc->actual_clock / 2, host->ioaddr + SDTOUT);
+ writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT);
}
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1264,7 +1264,7 @@ static const struct mmc_host_ops bcm2835_ops = {
static int bcm2835_add_host(struct bcm2835_host *host)
{
- struct mmc_host *mmc = host->mmc;
+ struct mmc_host *mmc = mmc_from_priv(host);
struct device *dev = &host->pdev->dev;
char pio_limit_string[20];
int ret;
@@ -1286,7 +1286,7 @@ static int bcm2835_add_host(struct bcm2835_host *host)
spin_lock_init(&host->lock);
mutex_init(&host->mutex);
- if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) {
+ if (!host->dma_chan_rxtx) {
dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n");
host->use_dma = false;
} else {
@@ -1370,7 +1370,6 @@ static int bcm2835_probe(struct platform_device *pdev)
mmc->ops = &bcm2835_ops;
host = mmc_priv(mmc);
- host->mmc = mmc;
host->pdev = pdev;
spin_lock_init(&host->lock);
@@ -1431,6 +1430,8 @@ static int bcm2835_probe(struct platform_device *pdev)
err:
dev_dbg(dev, "%s -> err %d\n", __func__, ret);
+ if (host->dma_chan_rxtx)
+ dma_release_channel(host->dma_chan_rxtx);
mmc_free_host(mmc);
return ret;
@@ -1439,8 +1440,9 @@ err:
static int bcm2835_remove(struct platform_device *pdev)
{
struct bcm2835_host *host = platform_get_drvdata(pdev);
+ struct mmc_host *mmc = mmc_from_priv(host);
- mmc_remove_host(host->mmc);
+ mmc_remove_host(mmc);
writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
@@ -1452,8 +1454,7 @@ static int bcm2835_remove(struct platform_device *pdev)
if (host->dma_chan_rxtx)
dma_release_channel(host->dma_chan_rxtx);
- mmc_free_host(host->mmc);
- platform_set_drvdata(pdev, NULL);
+ mmc_free_host(mmc);
return 0;
}
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 1087b4c79cd6..4c477dcd2ada 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -566,30 +566,32 @@ static void cb710_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
cb710_mmc_select_clock_divider(mmc, ios->clock);
- if (ios->power_mode != reader->last_power_mode)
- switch (ios->power_mode) {
- case MMC_POWER_ON:
- err = cb710_mmc_powerup(slot);
- if (err) {
- dev_warn(cb710_slot_dev(slot),
- "powerup failed (%d)- retrying\n", err);
- cb710_mmc_powerdown(slot);
- udelay(1);
+ if (ios->power_mode != reader->last_power_mode) {
+ switch (ios->power_mode) {
+ case MMC_POWER_ON:
err = cb710_mmc_powerup(slot);
- if (err)
+ if (err) {
dev_warn(cb710_slot_dev(slot),
- "powerup retry failed (%d) - expect errors\n",
+ "powerup failed (%d)- retrying\n", err);
+ cb710_mmc_powerdown(slot);
+ udelay(1);
+ err = cb710_mmc_powerup(slot);
+ if (err)
+ dev_warn(cb710_slot_dev(slot),
+ "powerup retry failed (%d) - expect errors\n",
err);
+ }
+ reader->last_power_mode = MMC_POWER_ON;
+ break;
+ case MMC_POWER_OFF:
+ cb710_mmc_powerdown(slot);
+ reader->last_power_mode = MMC_POWER_OFF;
+ break;
+ case MMC_POWER_UP:
+ default:
+ /* ignore */
+ break;
}
- reader->last_power_mode = MMC_POWER_ON;
- break;
- case MMC_POWER_OFF:
- cb710_mmc_powerdown(slot);
- reader->last_power_mode = MMC_POWER_OFF;
- break;
- case MMC_POWER_UP:
- default:
- /* ignore */;
}
cb710_mmc_enable_4bit_data(slot, ios->bus_width != MMC_BUS_WIDTH_1);
diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
index 159270e947cf..a8af682a9182 100644
--- a/drivers/mmc/host/cqhci.c
+++ b/drivers/mmc/host/cqhci.c
@@ -201,7 +201,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)
cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots;
cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs *
- (cq_host->num_slots - 1);
+ cq_host->mmc->cqe_qdepth;
pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n",
mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size,
@@ -217,12 +217,21 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)
cq_host->desc_size,
&cq_host->desc_dma_base,
GFP_KERNEL);
+ if (!cq_host->desc_base)
+ return -ENOMEM;
+
cq_host->trans_desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc),
cq_host->data_size,
&cq_host->trans_desc_dma_base,
GFP_KERNEL);
- if (!cq_host->desc_base || !cq_host->trans_desc_base)
+ if (!cq_host->trans_desc_base) {
+ dmam_free_coherent(mmc_dev(cq_host->mmc), cq_host->desc_size,
+ cq_host->desc_base,
+ cq_host->desc_dma_base);
+ cq_host->desc_base = NULL;
+ cq_host->desc_dma_base = 0;
return -ENOMEM;
+ }
pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n",
mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 9e68c3645e22..49e0daf2ef5e 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -1193,7 +1193,7 @@ static int mmc_davinci_parse_pdata(struct mmc_host *mmc)
else if (ret)
mmc->caps |= MMC_CAP_NEEDS_POLL;
- ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+ ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret == -EPROBE_DEFER)
return ret;
diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c
index ed8f2254b66a..aa38b1a8017e 100644
--- a/drivers/mmc/host/dw_mmc-bluefield.c
+++ b/drivers/mmc/host/dw_mmc-bluefield.c
@@ -1,11 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Mellanox Technologies.
- *
- * 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/bitfield.h>
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 33215d66afa2..63303022669c 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -21,7 +21,6 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -36,7 +35,6 @@
#include <asm/cacheflush.h>
#include <asm/mach-jz4740/dma.h>
-#include <asm/mach-jz4740/jz4740_mmc.h>
#define JZ_REG_MMC_STRPCL 0x00
#define JZ_REG_MMC_STATUS 0x04
@@ -148,9 +146,7 @@ enum jz4780_cookie {
struct jz4740_mmc_host {
struct mmc_host *mmc;
struct platform_device *pdev;
- struct jz4740_mmc_platform_data *pdata;
struct clk *clk;
- struct gpio_desc *power;
enum jz4740_mmc_version version;
@@ -743,6 +739,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
break;
jz_mmc_prepare_data_transfer(host);
+ /* fall through */
case JZ4740_MMC_STATE_TRANSFER_DATA:
if (host->use_dma) {
@@ -777,6 +774,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
break;
}
jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE);
+ /* fall through */
case JZ4740_MMC_STATE_SEND_STOP:
if (!req->stop)
@@ -894,16 +892,16 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_UP:
jz4740_mmc_reset(host);
- if (host->power)
- gpiod_set_value(host->power, 1);
+ if (!IS_ERR(mmc->supply.vmmc))
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
host->cmdat |= JZ_MMC_CMDAT_INIT;
clk_prepare_enable(host->clk);
break;
case MMC_POWER_ON:
break;
default:
- if (host->power)
- gpiod_set_value(host->power, 0);
+ if (!IS_ERR(mmc->supply.vmmc))
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
clk_disable_unprepare(host->clk);
break;
}
@@ -936,38 +934,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
};
-static int jz4740_mmc_request_gpios(struct jz4740_mmc_host *host,
- struct mmc_host *mmc,
- struct platform_device *pdev)
-{
- struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev);
- int ret = 0;
-
- if (!pdata)
- return 0;
-
- if (!pdata->card_detect_active_low)
- mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
- if (!pdata->read_only_active_low)
- mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
-
- /*
- * Get optional card detect and write protect GPIOs,
- * only back out on probe deferral.
- */
- ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- host->power = devm_gpiod_get_optional(&pdev->dev, "power",
- GPIOD_OUT_HIGH);
- return PTR_ERR_OR_ZERO(host->power);
-}
-
static const struct of_device_id jz4740_mmc_of_match[] = {
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
{ .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
@@ -982,9 +948,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
struct mmc_host *mmc;
struct jz4740_mmc_host *host;
const struct of_device_id *match;
- struct jz4740_mmc_platform_data *pdata;
-
- pdata = dev_get_platdata(&pdev->dev);
mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev);
if (!mmc) {
@@ -993,29 +956,25 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
}
host = mmc_priv(mmc);
- host->pdata = pdata;
match = of_match_device(jz4740_mmc_of_match, &pdev->dev);
if (match) {
host->version = (enum jz4740_mmc_version)match->data;
- ret = mmc_of_parse(mmc);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "could not parse of data: %d\n", ret);
- goto err_free_host;
- }
} else {
/* JZ4740 should be the only one using legacy probe */
host->version = JZ_MMC_JZ4740;
- mmc->caps |= MMC_CAP_SDIO_IRQ;
- if (!(pdata && pdata->data_1bit))
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- ret = jz4740_mmc_request_gpios(host, mmc, pdev);
- if (ret)
- goto err_free_host;
}
+ ret = mmc_of_parse(mmc);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "could not parse device properties: %d\n", ret);
+ goto err_free_host;
+ }
+
+ mmc_regulator_get_supply(mmc);
+
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index c2690c1a50ff..2eba507790e4 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -179,6 +179,8 @@ struct meson_host {
struct sd_emmc_desc *descs;
dma_addr_t descs_dma_addr;
+ int irq;
+
bool vqmmc_enabled;
};
@@ -738,6 +740,11 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct meson_host *host = mmc_priv(mmc);
+ int adj = 0;
+
+ /* enable signal resampling w/o delay */
+ adj = ADJUST_ADJ_EN;
+ writel(adj, host->regs + host->data->adjust);
return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
}
@@ -768,6 +775,9 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+ /* disable signal resampling */
+ writel(0, host->regs + host->data->adjust);
+
/* Reset rx phase */
clk_set_phase(host->rx_clk, 0);
@@ -1166,7 +1176,7 @@ static int meson_mmc_get_cd(struct mmc_host *mmc)
static void meson_mmc_cfg_init(struct meson_host *host)
{
- u32 cfg = 0, adj = 0;
+ u32 cfg = 0;
cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK,
ilog2(SD_EMMC_CFG_RESP_TIMEOUT));
@@ -1177,10 +1187,6 @@ static void meson_mmc_cfg_init(struct meson_host *host)
cfg |= CFG_ERR_ABORT;
writel(cfg, host->regs + SD_EMMC_CFG);
-
- /* enable signal resampling w/o delay */
- adj = ADJUST_ADJ_EN;
- writel(adj, host->regs + host->data->adjust);
}
static int meson_mmc_card_busy(struct mmc_host *mmc)
@@ -1231,7 +1237,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
struct resource *res;
struct meson_host *host;
struct mmc_host *mmc;
- int ret, irq;
+ int ret;
mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
if (!mmc)
@@ -1276,8 +1282,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
goto free_host;
}
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq <= 0) {
dev_err(&pdev->dev, "failed to get interrupt resource.\n");
ret = -EINVAL;
goto free_host;
@@ -1331,9 +1337,9 @@ static int meson_mmc_probe(struct platform_device *pdev)
writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
host->regs + SD_EMMC_IRQ_EN);
- ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
- meson_mmc_irq_thread, IRQF_SHARED,
- NULL, host);
+ ret = request_threaded_irq(host->irq, meson_mmc_irq,
+ meson_mmc_irq_thread, IRQF_SHARED,
+ dev_name(&pdev->dev), host);
if (ret)
goto err_init_clk;
@@ -1351,7 +1357,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
if (host->bounce_buf == NULL) {
dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
ret = -ENOMEM;
- goto err_init_clk;
+ goto err_free_irq;
}
host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
@@ -1370,6 +1376,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
err_bounce_buf:
dma_free_coherent(host->dev, host->bounce_buf_size,
host->bounce_buf, host->bounce_dma_addr);
+err_free_irq:
+ free_irq(host->irq, host);
err_init_clk:
clk_disable_unprepare(host->mmc_clk);
err_core_clk:
@@ -1387,6 +1395,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
/* disable interrupts */
writel(0, host->regs + SD_EMMC_IRQ_EN);
+ free_irq(host->irq, host);
dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
host->descs, host->descs_dma_addr);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 10ba46b728e8..1b1498805972 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1450,9 +1450,10 @@ static int mmc_spi_probe(struct spi_device *spi)
mmc->caps &= ~MMC_CAP_NEEDS_POLL;
mmc_gpiod_request_cd_irq(mmc);
}
+ mmc_detect_change(mmc, 0);
/* Index 1 is write protect/read only */
- status = mmc_gpiod_request_ro(mmc, NULL, 1, false, 0, NULL);
+ status = mmc_gpiod_request_ro(mmc, NULL, 1, 0, NULL);
if (status == -EPROBE_DEFER)
goto fail_add_host;
if (!status)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index e352f5ad5801..387ff14587b8 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
writel(c, base + MMCICOMMAND);
}
+static void mmci_stop_command(struct mmci_host *host)
+{
+ host->stop_abort.error = 0;
+ mmci_start_command(host, &host->stop_abort, 0);
+}
+
static void
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
unsigned int status)
@@ -1196,10 +1202,16 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
/* The error clause is handled above, success! */
data->bytes_xfered = data->blksz * data->blocks;
- if (!data->stop || (host->mrq->sbc && !data->error))
+ if (!data->stop) {
+ if (host->variant->cmdreg_stop && data->error)
+ mmci_stop_command(host);
+ else
+ mmci_request_end(host, data->mrq);
+ } else if (host->mrq->sbc && !data->error) {
mmci_request_end(host, data->mrq);
- else
+ } else {
mmci_start_command(host, data->stop, 0);
+ }
}
}
@@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
mmci_dma_error(host);
mmci_stop_data(host);
+ if (host->variant->cmdreg_stop && cmd->error) {
+ mmci_stop_command(host);
+ return;
+ }
}
mmci_request_end(host, host->mrq);
} else if (sbc) {
@@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev,
mmc->max_busy_timeout = 0;
}
+ /* Prepare a CMD12 - needed to clear the DPSM on some variants. */
+ host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
+ host->stop_abort.arg = 0;
+ host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
mmc->ops = &mmci_ops;
/* We support these PM capabilities. */
@@ -2011,7 +2032,7 @@ static int mmci_probe(struct amba_device *dev,
if (ret == -EPROBE_DEFER)
goto clk_disable;
- ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+ ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret == -EPROBE_DEFER)
goto clk_disable;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 24229097d05c..14df81054438 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -377,6 +377,7 @@ struct mmci_host {
void __iomem *base;
struct mmc_request *mrq;
struct mmc_command *cmd;
+ struct mmc_command stop_abort;
struct mmc_data *data;
struct mmc_host *mmc;
struct clk *clk;
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 8afeaf81ae66..833ef0590af8 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
if (timing == MMC_TIMING_MMC_HS400 &&
host->dev_comp->hs400_tune)
- sdr_set_field(host->base + PAD_CMD_TUNE,
+ sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRRDLY,
host->hs400_cmd_int_delay);
dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock,
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 4d17032d15ee..d54612257b06 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -31,14 +31,12 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
-#include <linux/of_gpio.h>
#include <linux/mmc/slot-gpio.h>
#include <asm/dma.h>
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index add1e70195ea..4f06fb03c0a2 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -25,7 +25,6 @@
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -39,7 +38,6 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
-#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/stmp_device.h>
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index b294b221f225..8a274b91804e 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -61,9 +61,6 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
struct device *dev = &spi->dev;
struct device_node *np = dev->of_node;
struct of_mmc_spi *oms;
- const __be32 *voltage_ranges;
- int num_ranges;
- int i;
if (dev->platform_data || !np)
return dev->platform_data;
@@ -72,25 +69,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
if (!oms)
return NULL;
- voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
- num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
- if (!voltage_ranges || !num_ranges) {
- dev_err(dev, "OF: voltage-ranges unspecified\n");
+ if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0)
goto err_ocr;
- }
-
- for (i = 0; i < num_ranges; i++) {
- const int j = i * 2;
- u32 mask;
-
- mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
- be32_to_cpu(voltage_ranges[j + 1]));
- if (!mask) {
- dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
- goto err_ocr;
- }
- oms->pdata.ocr_mask |= mask;
- }
oms->detect_irq = irq_of_parse_and_map(np, 0);
if (oms->detect_irq != 0) {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index c60a7625b1fa..b2873a2432b6 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -920,7 +920,7 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
reg &= ~(1 << 5);
OMAP_MMC_WRITE(host, SDIO, reg);
/* Set maximum timeout */
- OMAP_MMC_WRITE(host, CTO, 0xff);
+ OMAP_MMC_WRITE(host, CTO, 0xfd);
}
static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 8779bbaa6b69..c907bf502a12 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -743,7 +743,7 @@ static int pxamci_probe(struct platform_device *pdev)
goto out;
}
- ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+ ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
if (ret && ret != -ENOENT) {
dev_err(dev, "Failed requesting gpio_ro\n");
goto out;
diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index da1e49c45bec..8394a7bb1fc1 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -15,6 +15,7 @@
struct renesas_sdhi_scc {
unsigned long clk_rate; /* clock rate for SDR104 */
u32 tap; /* sampling clock position for SDR104 */
+ u32 tap_hs400; /* sampling clock position for HS400 */
};
struct renesas_sdhi_of_data {
@@ -49,6 +50,7 @@ struct renesas_sdhi {
struct pinctrl_state *pins_default, *pins_uhs;
void __iomem *scc_ctl;
u32 scc_tappos;
+ u32 scc_tappos_hs400;
};
#define host_to_priv(host) \
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 31a351a20dc0..71e13844df6c 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -337,6 +337,10 @@ static void renesas_sdhi_hs400_complete(struct tmio_mmc_host *host)
/* Set HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 |
sd_ctrl_read16(host, CTL_SDIF_MODE));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF,
+ priv->scc_tappos_hs400);
+
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
@@ -396,6 +400,9 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host,
/* Reset HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 &
sd_ctrl_read16(host, CTL_SDIF_MODE));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos);
+
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) &
@@ -723,6 +730,13 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->ops.start_signal_voltage_switch =
renesas_sdhi_start_signal_voltage_switch;
host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27;
+
+ /* SDR and HS200/400 registers requires HW reset */
+ if (of_data && of_data->scc_offset) {
+ priv->scc_ctl = host->ctl + of_data->scc_offset;
+ host->mmc->caps |= MMC_CAP_HW_RESET;
+ host->hw_reset = renesas_sdhi_hw_reset;
+ }
}
/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@@ -775,12 +789,11 @@ int renesas_sdhi_probe(struct platform_device *pdev,
const struct renesas_sdhi_scc *taps = of_data->taps;
bool hit = false;
- host->mmc->caps |= MMC_CAP_HW_RESET;
-
for (i = 0; i < of_data->taps_num; i++) {
if (taps[i].clk_rate == 0 ||
taps[i].clk_rate == host->mmc->f_max) {
priv->scc_tappos = taps->tap;
+ priv->scc_tappos_hs400 = taps->tap_hs400;
hit = true;
break;
}
@@ -789,12 +802,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
if (!hit)
dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
- priv->scc_ctl = host->ctl + of_data->scc_offset;
host->init_tuning = renesas_sdhi_init_tuning;
host->prepare_tuning = renesas_sdhi_prepare_tuning;
host->select_tuning = renesas_sdhi_select_tuning;
host->check_scc_error = renesas_sdhi_check_scc_error;
- host->hw_reset = renesas_sdhi_hw_reset;
host->prepare_hs400_tuning =
renesas_sdhi_prepare_hs400_tuning;
host->hs400_downgrade = renesas_sdhi_disable_scc;
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 92c9b15252da..9dfafa2a90a3 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -81,6 +81,7 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
{
.clk_rate = 0,
.tap = 0x00000300,
+ .tap_hs400 = 0x00000704,
},
};
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index 8471160316e0..02cd878e209f 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -65,6 +65,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {
.scc_offset = 0x0300,
.taps = rcar_gen2_scc_taps,
.taps_num = ARRAY_SIZE(rcar_gen2_scc_taps),
+ .max_blk_count = 0xffffffff,
};
/* Definitions for sampling clocks */
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 10f5219b3b40..f31333e831a7 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1530,7 +1530,7 @@ static int s3cmci_probe_pdata(struct s3cmci_host *host)
return ret;
}
- ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL);
+ ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL);
if (ret != -ENOENT) {
dev_err(&pdev->dev, "error requesting GPIO for WP %d\n",
ret);
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index bdbd4897c0f7..a6c2bd202b45 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -18,12 +18,10 @@
#include <linux/platform_device.h>
#include <linux/mmc/host.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/mmc/slot-gpio.h>
#include "sdhci-pltfm.h"
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 552bddc5096c..1cd10356fc14 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -55,7 +55,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
}
sdhci_get_of_property(pdev);
- mmc_of_parse(host->mmc);
+ res = mmc_of_parse(host->mmc);
+ if (res)
+ goto err;
/*
* Supply the existing CAPS, but clear the UHS modes. This
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index d0d319398a54..8dbbc1f62b70 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -25,6 +25,7 @@
#include <linux/pm_runtime.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
+#include "cqhci.h"
#define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f
#define ESDHC_CTRL_D3CD 0x08
@@ -50,6 +51,7 @@
#define ESDHC_MIX_CTRL_AUTO_TUNE_EN (1 << 24)
#define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25)
#define ESDHC_MIX_CTRL_HS400_EN (1 << 26)
+#define ESDHC_MIX_CTRL_HS400_ES_EN (1 << 27)
/* Bits 3 and 6 are not SDHCI standard definitions */
#define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7
/* Tuning bits */
@@ -76,6 +78,9 @@
#define ESDHC_STROBE_DLL_STS_REF_LOCK (1 << 1)
#define ESDHC_STROBE_DLL_STS_SLV_LOCK 0x1
+#define ESDHC_VEND_SPEC2 0xc8
+#define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8)
+
#define ESDHC_TUNING_CTRL 0xcc
#define ESDHC_STD_TUNING_EN (1 << 24)
/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
@@ -103,6 +108,9 @@
*/
#define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28)
+/* the address offset of CQHCI */
+#define ESDHC_CQHCI_ADDR_OFFSET 0x100
+
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
* "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -138,51 +146,71 @@
#define ESDHC_FLAG_HS200 BIT(8)
/* The IP supports HS400 mode */
#define ESDHC_FLAG_HS400 BIT(9)
-
-/* A clock frequency higher than this rate requires strobe dll control */
-#define ESDHC_STROBE_DLL_CLK_FREQ 100000000
+/*
+ * The IP has errata ERR010450
+ * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
+ * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
+ */
+#define ESDHC_FLAG_ERR010450 BIT(10)
+/* The IP supports HS400ES mode */
+#define ESDHC_FLAG_HS400_ES BIT(11)
+/* The IP has Host Controller Interface for Command Queuing */
+#define ESDHC_FLAG_CQHCI BIT(12)
struct esdhc_soc_data {
u32 flags;
};
-static struct esdhc_soc_data esdhc_imx25_data = {
+static const struct esdhc_soc_data esdhc_imx25_data = {
.flags = ESDHC_FLAG_ERR004536,
};
-static struct esdhc_soc_data esdhc_imx35_data = {
+static const struct esdhc_soc_data esdhc_imx35_data = {
.flags = ESDHC_FLAG_ERR004536,
};
-static struct esdhc_soc_data esdhc_imx51_data = {
+static const struct esdhc_soc_data esdhc_imx51_data = {
.flags = 0,
};
-static struct esdhc_soc_data esdhc_imx53_data = {
+static const struct esdhc_soc_data esdhc_imx53_data = {
.flags = ESDHC_FLAG_MULTIBLK_NO_INT,
};
-static struct esdhc_soc_data usdhc_imx6q_data = {
+static const struct esdhc_soc_data usdhc_imx6q_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING,
};
-static struct esdhc_soc_data usdhc_imx6sl_data = {
+static const struct esdhc_soc_data usdhc_imx6sl_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
| ESDHC_FLAG_HS200,
};
-static struct esdhc_soc_data usdhc_imx6sx_data = {
+static const struct esdhc_soc_data usdhc_imx6sx_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
};
-static struct esdhc_soc_data usdhc_imx7d_data = {
+static const struct esdhc_soc_data usdhc_imx6ull_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_ERR010450,
+};
+
+static const struct esdhc_soc_data usdhc_imx7d_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400,
};
+static struct esdhc_soc_data usdhc_imx8qxp_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
+ | ESDHC_FLAG_CQHCI,
+};
+
struct pltfm_imx_data {
u32 scratchpad;
struct pinctrl *pinctrl;
@@ -227,7 +255,9 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
+ { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, },
{ .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
+ { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -733,6 +763,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
+ unsigned int max_clock;
+
+ max_clock = imx_data->is_ddr ? 45000000 : 150000000;
+
+ clock = min(clock, max_clock);
+ }
+
while (host_clock / (16 * pre_div * ddr_pre_div) > clock &&
pre_div < 256)
pre_div *= 2;
@@ -801,6 +839,20 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
SDHCI_HOST_CONTROL);
}
+static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ /*
+ * i.MX uSDHC internally already uses a fixed optimized timing for
+ * DDR50, normally does not require tuning for DDR50 mode.
+ */
+ if (host->timing == MMC_TIMING_UHS_DDR50)
+ return 0;
+
+ return sdhci_execute_tuning(mmc, opcode);
+}
+
static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
{
u32 reg;
@@ -864,6 +916,19 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
return ret;
}
+static void esdhc_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u32 m;
+
+ m = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ if (ios->enhanced_strobe)
+ m |= ESDHC_MIX_CTRL_HS400_ES_EN;
+ else
+ m &= ~ESDHC_MIX_CTRL_HS400_ES_EN;
+ writel(m, host->ioaddr + ESDHC_MIX_CTRL);
+}
+
static int esdhc_change_pinstate(struct sdhci_host *host,
unsigned int uhs)
{
@@ -905,39 +970,35 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
* edge of data_strobe line. Due to the time delay between CLK line and
* data_strobe line, if the delay time is larger than one clock cycle,
* then CLK and data_strobe line will be misaligned, read error shows up.
- * So when the CLK is higher than 100MHz, each clock cycle is short enough,
- * host should configure the delay target.
*/
static void esdhc_set_strobe_dll(struct sdhci_host *host)
{
u32 v;
- if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
- /* disable clock before enabling strobe dll */
- writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
- ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
- host->ioaddr + ESDHC_VENDOR_SPEC);
+ /* disable clock before enabling strobe dll */
+ writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
+ ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
+ host->ioaddr + ESDHC_VENDOR_SPEC);
- /* force a reset on strobe dll */
- writel(ESDHC_STROBE_DLL_CTRL_RESET,
- host->ioaddr + ESDHC_STROBE_DLL_CTRL);
- /*
- * enable strobe dll ctrl and adjust the delay target
- * for the uSDHC loopback read clock
- */
- v = ESDHC_STROBE_DLL_CTRL_ENABLE |
- (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
- writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
- /* wait 1us to make sure strobe dll status register stable */
- udelay(1);
- v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
- if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
- dev_warn(mmc_dev(host->mmc),
- "warning! HS400 strobe DLL status REF not lock!\n");
- if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
- dev_warn(mmc_dev(host->mmc),
- "warning! HS400 strobe DLL status SLV not lock!\n");
- }
+ /* force a reset on strobe dll */
+ writel(ESDHC_STROBE_DLL_CTRL_RESET,
+ host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+ /*
+ * enable strobe dll ctrl and adjust the delay target
+ * for the uSDHC loopback read clock
+ */
+ v = ESDHC_STROBE_DLL_CTRL_ENABLE |
+ (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
+ writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+ /* wait 1us to make sure strobe dll status register stable */
+ udelay(1);
+ v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
+ if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
+ dev_warn(mmc_dev(host->mmc),
+ "warning! HS400 strobe DLL status REF not lock!\n");
+ if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
+ dev_warn(mmc_dev(host->mmc),
+ "warning! HS400 strobe DLL status SLV not lock!\n");
}
static void esdhc_reset_tuning(struct sdhci_host *host)
@@ -979,6 +1040,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
case MMC_TIMING_UHS_SDR25:
case MMC_TIMING_UHS_SDR50:
case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_MMC_HS:
case MMC_TIMING_MMC_HS200:
writel(m, host->ioaddr + ESDHC_MIX_CTRL);
break;
@@ -1042,6 +1104,19 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
SDHCI_TIMEOUT_CONTROL);
}
+static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask)
+{
+ int cmd_error = 0;
+ int data_error = 0;
+
+ if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
+ return intmask;
+
+ cqhci_irq(host->mmc, intmask, cmd_error, data_error);
+
+ return 0;
+}
+
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -1058,6 +1133,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.set_bus_width = esdhc_pltfm_set_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling,
.reset = esdhc_reset,
+ .irq = esdhc_cqhci_irq,
};
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -1095,16 +1171,34 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
| ESDHC_BURST_LEN_EN_INCR,
host->ioaddr + SDHCI_HOST_CONTROL);
+
/*
- * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
- * TO1.1, it's harmless for MX6SL
- */
- writel(readl(host->ioaddr + 0x6c) | BIT(7),
+ * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
+ * TO1.1, it's harmless for MX6SL
+ */
+ writel(readl(host->ioaddr + 0x6c) & ~BIT(7),
host->ioaddr + 0x6c);
/* disable DLL_CTRL delay line settings */
writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
+ /*
+ * For the case of command with busy, if set the bit
+ * ESDHC_VEND_SPEC2_EN_BUSY_IRQ, USDHC will generate a
+ * transfer complete interrupt when busy is deasserted.
+ * When CQHCI use DCMD to send a CMD need R1b respons,
+ * CQHCI require to set ESDHC_VEND_SPEC2_EN_BUSY_IRQ,
+ * otherwise DCMD will always meet timeout waiting for
+ * hardware interrupt issue.
+ */
+ if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) {
+ tmp = readl(host->ioaddr + ESDHC_VEND_SPEC2);
+ tmp |= ESDHC_VEND_SPEC2_EN_BUSY_IRQ;
+ writel(tmp, host->ioaddr + ESDHC_VEND_SPEC2);
+
+ host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+ }
+
if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
tmp |= ESDHC_STD_TUNING_EN |
@@ -1120,10 +1214,81 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
<< ESDHC_TUNING_STEP_SHIFT;
}
writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
+ } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
+ /*
+ * ESDHC_STD_TUNING_EN may be configed in bootloader
+ * or ROM code, so clear this bit here to make sure
+ * the manual tuning can work.
+ */
+ tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+ tmp &= ~ESDHC_STD_TUNING_EN;
+ writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
}
}
}
+static void esdhc_cqe_enable(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct cqhci_host *cq_host = mmc->cqe_private;
+ u32 reg;
+ u16 mode;
+ int count = 10;
+
+ /*
+ * CQE gets stuck if it sees Buffer Read Enable bit set, which can be
+ * the case after tuning, so ensure the buffer is drained.
+ */
+ reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ while (reg & SDHCI_DATA_AVAILABLE) {
+ sdhci_readl(host, SDHCI_BUFFER);
+ reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ if (count-- == 0) {
+ dev_warn(mmc_dev(host->mmc),
+ "CQE may get stuck because the Buffer Read Enable bit is set\n");
+ break;
+ }
+ mdelay(1);
+ }
+
+ /*
+ * Runtime resume will reset the entire host controller, which
+ * will also clear the DMAEN/BCEN of register ESDHC_MIX_CTRL.
+ * Here set DMAEN and BCEN when enable CMDQ.
+ */
+ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
+ if (host->flags & SDHCI_REQ_USE_DMA)
+ mode |= SDHCI_TRNS_DMA;
+ if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE))
+ mode |= SDHCI_TRNS_BLK_CNT_EN;
+ sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
+
+ /*
+ * Though Runtime resume reset the entire host controller,
+ * but do not impact the CQHCI side, need to clear the
+ * HALT bit, avoid CQHCI stuck in the first request when
+ * system resume back.
+ */
+ cqhci_writel(cq_host, 0, CQHCI_CTL);
+ if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT)
+ dev_err(mmc_dev(host->mmc),
+ "failed to exit halt state when enable CQE\n");
+
+
+ sdhci_cqe_enable(mmc);
+}
+
+static void esdhc_sdhci_dumpregs(struct mmc_host *mmc)
+{
+ sdhci_dumpregs(mmc_priv(mmc));
+}
+
+static const struct cqhci_host_ops esdhc_cqhci_ops = {
+ .enable = esdhc_cqe_enable,
+ .disable = sdhci_cqe_disable,
+ .dumpregs = esdhc_sdhci_dumpregs,
+};
+
#ifdef CONFIG_OF
static int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
@@ -1200,7 +1365,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
host->mmc->parent->platform_data);
/* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) {
- err = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL);
+ err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request write-protect gpio!\n");
@@ -1255,6 +1420,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
+ struct cqhci_host *cq_host;
int err;
struct pltfm_imx_data *imx_data;
@@ -1321,6 +1487,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS);
writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+
+ /*
+ * Link usdhc specific mmc_host_ops execute_tuning function,
+ * to replace the standard one in sdhci_ops.
+ */
+ host->mmc_host_ops.execute_tuning = usdhc_execute_tuning;
}
if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
@@ -1333,6 +1505,28 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
+ if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
+ host->mmc->caps2 |= MMC_CAP2_HS400_ES;
+ host->mmc_host_ops.hs400_enhanced_strobe =
+ esdhc_hs400_enhanced_strobe;
+ }
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_CQHCI) {
+ host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
+ cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL);
+ if (!cq_host) {
+ err = -ENOMEM;
+ goto disable_ahb_clk;
+ }
+
+ cq_host->mmio = host->ioaddr + ESDHC_CQHCI_ADDR_OFFSET;
+ cq_host->ops = &esdhc_cqhci_ops;
+
+ err = cqhci_init(cq_host, host->mmc, false);
+ if (err)
+ goto disable_ahb_clk;
+ }
+
if (of_id)
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
else
@@ -1340,6 +1534,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (err)
goto disable_ahb_clk;
+ host->tuning_delay = 1;
+
sdhci_esdhc_imx_hwinit(host);
err = sdhci_add_host(host);
@@ -1391,6 +1587,13 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
static int sdhci_esdhc_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ int ret;
+
+ if (host->mmc->caps2 & MMC_CAP2_CQE) {
+ ret = cqhci_suspend(host->mmc);
+ if (ret)
+ return ret;
+ }
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
mmc_retune_needed(host->mmc);
@@ -1401,11 +1604,19 @@ static int sdhci_esdhc_suspend(struct device *dev)
static int sdhci_esdhc_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ int ret;
/* re-initialize hw state in case it's lost in low power mode */
sdhci_esdhc_imx_hwinit(host);
- return sdhci_resume_host(host);
+ ret = sdhci_resume_host(host);
+ if (ret)
+ return ret;
+
+ if (host->mmc->caps2 & MMC_CAP2_CQE)
+ ret = cqhci_resume(host->mmc);
+
+ return ret;
}
#endif
@@ -1417,6 +1628,12 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int ret;
+ if (host->mmc->caps2 & MMC_CAP2_CQE) {
+ ret = cqhci_suspend(host->mmc);
+ if (ret)
+ return ret;
+ }
+
ret = sdhci_runtime_suspend_host(host);
if (ret)
return ret;
@@ -1460,7 +1677,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
if (err)
goto disable_ipg_clk;
- return 0;
+ if (host->mmc->caps2 & MMC_CAP2_CQE)
+ err = cqhci_resume(host->mmc);
+
+ return err;
disable_ipg_clk:
if (!sdhci_sdio_irq_enabled(host))
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 0db99057c44f..9d12c06c7fd6 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -296,7 +296,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
iproc_host->data = iproc_data;
- mmc_of_parse(host->mmc);
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ goto err;
+
sdhci_get_property(pdev);
host->mmc->caps |= iproc_host->data->mmc_caps;
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index c11c18a9aacb..b1a66ca3821a 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -1097,7 +1097,6 @@ static int sdhci_omap_probe(struct platform_device *pdev)
goto err_put_sync;
}
- host->mmc_host_ops.get_ro = mmc_gpio_get_ro;
host->mmc_host_ops.start_signal_voltage_switch =
sdhci_omap_start_signal_voltage_switch;
host->mmc_host_ops.set_ios = sdhci_omap_set_ios;
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 2a6eba74b94e..99b0fec2836b 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1257,16 +1257,6 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
}
#endif
-static const struct sdhci_pci_fixes sdhci_o2 = {
- .probe = sdhci_pci_o2_probe,
- .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
- .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD,
- .probe_slot = sdhci_pci_o2_probe_slot,
-#ifdef CONFIG_PM_SLEEP
- .resume = sdhci_pci_o2_resume,
-#endif
-};
-
static const struct sdhci_pci_fixes sdhci_jmicron = {
.probe = jmicron_probe,
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index cc3ffeffd7a2..05a012a694b2 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -60,6 +60,13 @@
#define O2_SD_VENDOR_SETTING2 0x1C8
#define O2_SD_HW_TUNING_DISABLE BIT(4)
+#define O2_PLL_WDT_CONTROL1 0x1CC
+#define O2_PLL_FORCE_ACTIVE BIT(18)
+#define O2_PLL_LOCK_STATUS BIT(14)
+#define O2_PLL_SOFT_RESET BIT(12)
+
+#define O2_SD_DETECT_SETTING 0x324
+
static void sdhci_o2_set_tuning_mode(struct sdhci_host *host)
{
u16 reg;
@@ -283,6 +290,113 @@ static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip,
host->irq = pci_irq_vector(chip->pdev, 0);
}
+static void sdhci_o2_wait_card_detect_stable(struct sdhci_host *host)
+{
+ ktime_t timeout;
+ u32 scratch32;
+
+ /* Wait max 50 ms */
+ timeout = ktime_add_ms(ktime_get(), 50);
+ while (1) {
+ bool timedout = ktime_after(ktime_get(), timeout);
+
+ scratch32 = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ if ((scratch32 & SDHCI_CARD_PRESENT) >> SDHCI_CARD_PRES_SHIFT
+ == (scratch32 & SDHCI_CD_LVL) >> SDHCI_CD_LVL_SHIFT)
+ break;
+
+ if (timedout) {
+ pr_err("%s: Card Detect debounce never finished.\n",
+ mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return;
+ }
+ udelay(10);
+ }
+}
+
+static void sdhci_o2_enable_internal_clock(struct sdhci_host *host)
+{
+ ktime_t timeout;
+ u16 scratch;
+ u32 scratch32;
+
+ /* PLL software reset */
+ scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1);
+ scratch32 |= O2_PLL_SOFT_RESET;
+ sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
+ udelay(1);
+ scratch32 &= ~(O2_PLL_SOFT_RESET);
+ sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
+
+ /* PLL force active */
+ scratch32 |= O2_PLL_FORCE_ACTIVE;
+ sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
+
+ /* Wait max 20 ms */
+ timeout = ktime_add_ms(ktime_get(), 20);
+ while (1) {
+ bool timedout = ktime_after(ktime_get(), timeout);
+
+ scratch = sdhci_readw(host, O2_PLL_WDT_CONTROL1);
+ if (scratch & O2_PLL_LOCK_STATUS)
+ break;
+ if (timedout) {
+ pr_err("%s: Internal clock never stabilised.\n",
+ mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ goto out;
+ }
+ udelay(10);
+ }
+
+ /* Wait for card detect finish */
+ udelay(1);
+ sdhci_o2_wait_card_detect_stable(host);
+
+out:
+ /* Cancel PLL force active */
+ scratch32 = sdhci_readl(host, O2_PLL_WDT_CONTROL1);
+ scratch32 &= ~O2_PLL_FORCE_ACTIVE;
+ sdhci_writel(host, scratch32, O2_PLL_WDT_CONTROL1);
+}
+
+static int sdhci_o2_get_cd(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_o2_enable_internal_clock(host);
+
+ return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+}
+
+static void sdhci_o2_enable_clk(struct sdhci_host *host, u16 clk)
+{
+ /* Enable internal clock */
+ clk |= SDHCI_CLOCK_INT_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+ if (sdhci_o2_get_cd(host->mmc)) {
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ }
+}
+
+void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ u16 clk;
+
+ host->mmc->actual_clock = 0;
+
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ return;
+
+ clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+ sdhci_o2_enable_clk(host, clk);
+}
+
int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
{
struct sdhci_pci_chip *chip;
@@ -314,9 +428,14 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
mmc_hostname(host->mmc));
host->flags &= ~SDHCI_SIGNALING_330;
host->flags |= SDHCI_SIGNALING_180;
+ host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
host->mmc->caps2 |= MMC_CAP2_NO_SD;
host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+ pci_write_config_dword(chip->pdev,
+ O2_SD_DETECT_SETTING, 3);
}
+
+ slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
}
host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
@@ -490,9 +609,6 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
break;
case PCI_DEVICE_ID_O2_SEABIRD0:
- if (chip->pdev->revision == 0x01)
- chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
- /* fall through */
case PCI_DEVICE_ID_O2_SEABIRD1:
/* UnLock WP */
ret = pci_read_config_byte(chip->pdev,
@@ -550,3 +666,21 @@ int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
return sdhci_pci_resume_host(chip);
}
#endif
+
+static const struct sdhci_ops sdhci_pci_o2_ops = {
+ .set_clock = sdhci_pci_o2_set_clock,
+ .enable_dma = sdhci_pci_enable_dma,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+const struct sdhci_pci_fixes sdhci_o2 = {
+ .probe = sdhci_pci_o2_probe,
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .probe_slot = sdhci_pci_o2_probe_slot,
+#ifdef CONFIG_PM_SLEEP
+ .resume = sdhci_pci_o2_resume,
+#endif
+ .ops = &sdhci_pci_o2_ops,
+};
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 2ef0bdca9197..4ddb69a15cd7 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -179,13 +179,9 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot)
int sdhci_pci_resume_host(struct sdhci_pci_chip *chip);
#endif
int sdhci_pci_enable_dma(struct sdhci_host *host);
-int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot);
-int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip);
-#ifdef CONFIG_PM_SLEEP
-int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip);
-#endif
extern const struct sdhci_pci_fixes sdhci_arasan;
extern const struct sdhci_pci_fixes sdhci_snps;
+extern const struct sdhci_pci_fixes sdhci_o2;
#endif /* __SDHCI_PCI_H */
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 2c3827f54927..cdc8e16b4567 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/platform_data/pxa_sdhci.h>
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e6ace31e2a41..32e62904c0d3 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -33,6 +33,7 @@
#include <linux/ktime.h>
#include "sdhci-pltfm.h"
+#include "cqhci.h"
/* Tegra SDHOST controller vendor register definitions */
#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
@@ -75,6 +76,7 @@
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK 0x0000000f
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL 0x7
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD BIT(31)
+#define SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK 0x07FFF000
#define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec
#define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
@@ -89,6 +91,9 @@
#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
+/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
+#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
+
struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
u32 nvquirks;
@@ -121,6 +126,8 @@ struct sdhci_tegra {
struct pinctrl *pinctrl_sdmmc;
struct pinctrl_state *pinctrl_state_3v3;
struct pinctrl_state *pinctrl_state_1v8;
+ struct pinctrl_state *pinctrl_state_3v3_drv;
+ struct pinctrl_state *pinctrl_state_1v8_drv;
struct sdhci_tegra_autocal_offsets autocal_offsets;
ktime_t last_calib;
@@ -128,6 +135,7 @@ struct sdhci_tegra {
u32 default_tap;
u32 default_trim;
u32 dqs_trim;
+ bool enable_hwcq;
};
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -237,11 +245,6 @@ static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
}
}
-static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
-{
- return mmc_gpio_get_ro(host->mmc);
-}
-
static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -411,6 +414,76 @@ static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
}
+static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage,
+ bool state_drvupdn)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+ struct sdhci_tegra_autocal_offsets *offsets =
+ &tegra_host->autocal_offsets;
+ struct pinctrl_state *pinctrl_drvupdn = NULL;
+ int ret = 0;
+ u8 drvup = 0, drvdn = 0;
+ u32 reg;
+
+ if (!state_drvupdn) {
+ /* PADS Drive Strength */
+ if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+ if (tegra_host->pinctrl_state_1v8_drv) {
+ pinctrl_drvupdn =
+ tegra_host->pinctrl_state_1v8_drv;
+ } else {
+ drvup = offsets->pull_up_1v8_timeout;
+ drvdn = offsets->pull_down_1v8_timeout;
+ }
+ } else {
+ if (tegra_host->pinctrl_state_3v3_drv) {
+ pinctrl_drvupdn =
+ tegra_host->pinctrl_state_3v3_drv;
+ } else {
+ drvup = offsets->pull_up_3v3_timeout;
+ drvdn = offsets->pull_down_3v3_timeout;
+ }
+ }
+
+ if (pinctrl_drvupdn != NULL) {
+ ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+ pinctrl_drvupdn);
+ if (ret < 0)
+ dev_err(mmc_dev(host->mmc),
+ "failed pads drvupdn, ret: %d\n", ret);
+ } else if ((drvup) || (drvdn)) {
+ reg = sdhci_readl(host,
+ SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+ reg &= ~SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK;
+ reg |= (drvup << 20) | (drvdn << 12);
+ sdhci_writel(host, reg,
+ SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+ }
+
+ } else {
+ /* Dual Voltage PADS Voltage selection */
+ if (!tegra_host->pad_control_available)
+ return 0;
+
+ if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+ ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+ tegra_host->pinctrl_state_1v8);
+ if (ret < 0)
+ dev_err(mmc_dev(host->mmc),
+ "setting 1.8V failed, ret: %d\n", ret);
+ } else {
+ ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+ tegra_host->pinctrl_state_3v3);
+ if (ret < 0)
+ dev_err(mmc_dev(host->mmc),
+ "setting 3.3V failed, ret: %d\n", ret);
+ }
+ }
+
+ return ret;
+}
+
static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -437,6 +510,7 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
}
+ /* Set initial offset before auto-calibration */
tegra_sdhci_set_pad_autocal_offset(host, pdpu);
card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
@@ -460,19 +534,15 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
if (ret) {
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
- if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
- pdpu = offsets.pull_down_1v8_timeout << 8 |
- offsets.pull_up_1v8_timeout;
- else
- pdpu = offsets.pull_down_3v3_timeout << 8 |
- offsets.pull_up_3v3_timeout;
-
- /* Disable automatic calibration and use fixed offsets */
+ /* Disable automatic cal and use fixed Drive Strengths */
reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
reg &= ~SDHCI_AUTO_CAL_ENABLE;
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
- tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+ ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, false);
+ if (ret < 0)
+ dev_err(mmc_dev(host->mmc),
+ "Setting drive strengths failed: %d\n", ret);
}
}
@@ -511,26 +581,46 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-3v3-timeout",
&autocal->pull_up_3v3_timeout);
- if (err)
+ if (err) {
+ if (!IS_ERR(tegra_host->pinctrl_state_3v3) &&
+ (tegra_host->pinctrl_state_3v3_drv == NULL))
+ pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n",
+ mmc_hostname(host->mmc));
autocal->pull_up_3v3_timeout = 0;
+ }
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-down-offset-3v3-timeout",
&autocal->pull_down_3v3_timeout);
- if (err)
+ if (err) {
+ if (!IS_ERR(tegra_host->pinctrl_state_3v3) &&
+ (tegra_host->pinctrl_state_3v3_drv == NULL))
+ pr_warn("%s: Missing autocal timeout 3v3-pad drvs\n",
+ mmc_hostname(host->mmc));
autocal->pull_down_3v3_timeout = 0;
+ }
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-1v8-timeout",
&autocal->pull_up_1v8_timeout);
- if (err)
+ if (err) {
+ if (!IS_ERR(tegra_host->pinctrl_state_1v8) &&
+ (tegra_host->pinctrl_state_1v8_drv == NULL))
+ pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n",
+ mmc_hostname(host->mmc));
autocal->pull_up_1v8_timeout = 0;
+ }
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-down-offset-1v8-timeout",
&autocal->pull_down_1v8_timeout);
- if (err)
+ if (err) {
+ if (!IS_ERR(tegra_host->pinctrl_state_1v8) &&
+ (tegra_host->pinctrl_state_1v8_drv == NULL))
+ pr_warn("%s: Missing autocal timeout 1v8-pad drvs\n",
+ mmc_hostname(host->mmc));
autocal->pull_down_1v8_timeout = 0;
+ }
err = device_property_read_u32(host->mmc->parent,
"nvidia,pad-autocal-pull-up-offset-sdr104",
@@ -595,6 +685,20 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)
tegra_host->dqs_trim = 0x11;
}
+static void tegra_sdhci_parse_dt(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+
+ if (device_property_read_bool(host->mmc->parent, "supports-cqe"))
+ tegra_host->enable_hwcq = true;
+ else
+ tegra_host->enable_hwcq = false;
+
+ tegra_sdhci_parse_pad_autocal_dt(host);
+ tegra_sdhci_parse_tap_and_trim(host);
+}
+
static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -743,32 +847,6 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
}
-static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
- int ret;
-
- if (!tegra_host->pad_control_available)
- return 0;
-
- if (voltage == MMC_SIGNAL_VOLTAGE_180) {
- ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
- tegra_host->pinctrl_state_1v8);
- if (ret < 0)
- dev_err(mmc_dev(host->mmc),
- "setting 1.8V failed, ret: %d\n", ret);
- } else {
- ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
- tegra_host->pinctrl_state_3v3);
- if (ret < 0)
- dev_err(mmc_dev(host->mmc),
- "setting 3.3V failed, ret: %d\n", ret);
- }
-
- return ret;
-}
-
static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
{
@@ -778,7 +856,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
int ret = 0;
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
- ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+ ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true);
if (ret < 0)
return ret;
ret = sdhci_start_signal_voltage_switch(mmc, ios);
@@ -786,7 +864,7 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
ret = sdhci_start_signal_voltage_switch(mmc, ios);
if (ret < 0)
return ret;
- ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+ ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage, true);
}
if (tegra_host->pad_calib_required)
@@ -805,6 +883,20 @@ static int tegra_sdhci_init_pinctrl_info(struct device *dev,
return -1;
}
+ tegra_host->pinctrl_state_1v8_drv = pinctrl_lookup_state(
+ tegra_host->pinctrl_sdmmc, "sdmmc-1v8-drv");
+ if (IS_ERR(tegra_host->pinctrl_state_1v8_drv)) {
+ if (PTR_ERR(tegra_host->pinctrl_state_1v8_drv) == -ENODEV)
+ tegra_host->pinctrl_state_1v8_drv = NULL;
+ }
+
+ tegra_host->pinctrl_state_3v3_drv = pinctrl_lookup_state(
+ tegra_host->pinctrl_sdmmc, "sdmmc-3v3-drv");
+ if (IS_ERR(tegra_host->pinctrl_state_3v3_drv)) {
+ if (PTR_ERR(tegra_host->pinctrl_state_3v3_drv) == -ENODEV)
+ tegra_host->pinctrl_state_3v3_drv = NULL;
+ }
+
tegra_host->pinctrl_state_3v3 =
pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3");
if (IS_ERR(tegra_host->pinctrl_state_3v3)) {
@@ -836,8 +928,50 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
tegra_host->pad_calib_required = true;
}
+static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)
+{
+ struct cqhci_host *cq_host = mmc->cqe_private;
+ u32 cqcfg = 0;
+
+ /*
+ * Tegra SDMMC Controller design prevents write access to BLOCK_COUNT
+ * registers when CQE is enabled.
+ */
+ cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
+ if (cqcfg & CQHCI_ENABLE)
+ cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG);
+
+ sdhci_cqe_enable(mmc);
+
+ if (cqcfg & CQHCI_ENABLE)
+ cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
+}
+
+static void sdhci_tegra_dumpregs(struct mmc_host *mmc)
+{
+ sdhci_dumpregs(mmc_priv(mmc));
+}
+
+static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask)
+{
+ int cmd_error = 0;
+ int data_error = 0;
+
+ if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
+ return intmask;
+
+ cqhci_irq(host->mmc, intmask, cmd_error, data_error);
+
+ return 0;
+}
+
+static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
+ .enable = sdhci_tegra_cqe_enable,
+ .disable = sdhci_cqe_disable,
+ .dumpregs = sdhci_tegra_dumpregs,
+};
+
static const struct sdhci_ops tegra_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
@@ -893,7 +1027,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
};
static const struct sdhci_ops tegra114_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra_sdhci_writew,
.write_l = tegra_sdhci_writel,
@@ -947,7 +1080,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
};
static const struct sdhci_ops tegra210_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_w = tegra210_sdhci_writew,
.write_l = tegra_sdhci_writel,
@@ -980,7 +1112,6 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
};
static const struct sdhci_ops tegra186_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_clock = tegra_sdhci_set_clock,
@@ -989,6 +1120,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = {
.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
.voltage_switch = tegra_sdhci_voltage_switch,
.get_max_clock = tegra_sdhci_get_max_clock,
+ .irq = sdhci_tegra_cqhci_irq,
};
static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -1030,6 +1162,54 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
+static int sdhci_tegra_add_host(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+ struct cqhci_host *cq_host;
+ bool dma64;
+ int ret;
+
+ if (!tegra_host->enable_hwcq)
+ return sdhci_add_host(host);
+
+ sdhci_enable_v4_mode(host);
+
+ ret = sdhci_setup_host(host);
+ if (ret)
+ return ret;
+
+ host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
+
+ cq_host = devm_kzalloc(host->mmc->parent,
+ sizeof(*cq_host), GFP_KERNEL);
+ if (!cq_host) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR;
+ cq_host->ops = &sdhci_tegra_cqhci_ops;
+
+ dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
+ if (dma64)
+ cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
+
+ ret = cqhci_init(cq_host, host->mmc, dma64);
+ if (ret)
+ goto cleanup;
+
+ ret = __sdhci_add_host(host);
+ if (ret)
+ goto cleanup;
+
+ return 0;
+
+cleanup:
+ sdhci_cleanup_host(host);
+ return ret;
+}
+
static int sdhci_tegra_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -1077,9 +1257,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
host->mmc->caps |= MMC_CAP_1_8V_DDR;
- tegra_sdhci_parse_pad_autocal_dt(host);
-
- tegra_sdhci_parse_tap_and_trim(host);
+ tegra_sdhci_parse_dt(host);
tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
GPIOD_OUT_HIGH);
@@ -1117,7 +1295,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
usleep_range(2000, 4000);
- rc = sdhci_add_host(host);
+ rc = sdhci_tegra_add_host(host);
if (rc)
goto err_add_host;
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
index 5b5eb53a63d2..8d07ee1b8f08 100644
--- a/drivers/mmc/host/sdhci-xenon-phy.c
+++ b/drivers/mmc/host/sdhci-xenon-phy.c
@@ -530,7 +530,7 @@ static bool xenon_emmc_phy_slow_mode(struct sdhci_host *host,
ret = true;
break;
}
- /* else: fall through */
+ /* fall through */
default:
reg &= ~XENON_TIMING_ADJUST_SLOW_MODE;
ret = false;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a22e11a65658..a8141ff9be03 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -883,7 +883,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
bool *too_big)
{
u8 count;
- struct mmc_data *data = cmd->data;
+ struct mmc_data *data;
unsigned target_timeout, current_timeout;
*too_big = true;
@@ -897,6 +897,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
return 0xE;
+ /* Unspecified command, asume max */
+ if (cmd == NULL)
+ return 0xE;
+
+ data = cmd->data;
/* Unspecified timeout, assume max */
if (!data && !cmd->busy_timeout)
return 0xE;
@@ -2048,6 +2053,8 @@ static int sdhci_check_ro(struct sdhci_host *host)
is_readonly = 0;
else if (host->ops->get_ro)
is_readonly = host->ops->get_ro(host);
+ else if (mmc_can_gpio_ro(host->mmc))
+ is_readonly = mmc_gpio_get_ro(host->mmc);
else
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
& SDHCI_WRITE_PROTECT);
@@ -2376,6 +2383,10 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
return -ETIMEDOUT;
}
+ /* Spec does not require a delay between tuning cycles */
+ if (host->tuning_delay > 0)
+ mdelay(host->tuning_delay);
+
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
if (ctrl & SDHCI_CTRL_TUNED_CLK)
@@ -2383,9 +2394,6 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
break;
}
- /* Spec does not require a delay between tuning cycles */
- if (host->tuning_delay > 0)
- mdelay(host->tuning_delay);
}
pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
@@ -3353,7 +3361,14 @@ void sdhci_cqe_enable(struct mmc_host *mmc)
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
ctrl &= ~SDHCI_CTRL_DMA_MASK;
- if (host->flags & SDHCI_USE_64_BIT_DMA)
+ /*
+ * Host from V4.10 supports ADMA3 DMA type.
+ * ADMA3 performs integrated descriptor which is more suitable
+ * for cmd queuing to fetch both command and transfer descriptors.
+ */
+ if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3))
+ ctrl |= SDHCI_CTRL_ADMA3;
+ else if (host->flags & SDHCI_USE_64_BIT_DMA)
ctrl |= SDHCI_CTRL_ADMA64;
else
ctrl |= SDHCI_CTRL_ADMA32;
@@ -3363,7 +3378,7 @@ void sdhci_cqe_enable(struct mmc_host *mmc)
SDHCI_BLOCK_SIZE);
/* Set maximum timeout */
- sdhci_writeb(host, 0xE, SDHCI_TIMEOUT_CONTROL);
+ sdhci_set_timeout(host, NULL);
host->ier = host->cqe_ier;
@@ -3763,8 +3778,9 @@ int sdhci_setup_host(struct sdhci_host *host)
* Use zalloc to zero the reserved high 32-bits of 128-bit
* descriptors so that they never need to be written.
*/
- buf = dma_zalloc_coherent(mmc_dev(mmc), host->align_buffer_sz +
- host->adma_table_sz, &dma, GFP_KERNEL);
+ buf = dma_alloc_coherent(mmc_dev(mmc),
+ host->align_buffer_sz + host->adma_table_sz,
+ &dma, GFP_KERNEL);
if (!buf) {
pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
mmc_hostname(mmc));
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 6cc9a3c2ac66..01002cba1359 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -73,6 +73,10 @@
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
+#define SDHCI_CARD_PRES_SHIFT 16
+#define SDHCI_CD_STABLE 0x00020000
+#define SDHCI_CD_LVL 0x00040000
+#define SDHCI_CD_LVL_SHIFT 18
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_DATA_LVL_MASK 0x00F00000
#define SDHCI_DATA_LVL_SHIFT 20
@@ -88,6 +92,7 @@
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
+#define SDHCI_CTRL_ADMA3 0x18
#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_CTRL_CDTEST_INS 0x40
#define SDHCI_CTRL_CDTEST_EN 0x80
@@ -230,6 +235,7 @@
#define SDHCI_RETUNING_MODE_SHIFT 14
#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
#define SDHCI_CLOCK_MUL_SHIFT 16
+#define SDHCI_CAN_DO_ADMA3 0x08000000
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
#define SDHCI_CAPABILITIES_1 0x44
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index 8c05879850a0..eea183e90f1b 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -158,7 +158,7 @@ static void sdhci_am654_set_power(struct sdhci_host *host, unsigned char mode,
sdhci_set_power_noreg(host, mode, vdd);
}
-struct sdhci_ops sdhci_am654_ops = {
+static struct sdhci_ops sdhci_am654_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
.set_uhs_signaling = sdhci_set_uhs_signaling,
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 279e326e397e..2901a5773d83 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -32,7 +31,6 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -1399,13 +1397,37 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
- if (host->cfg->clk_delays || host->use_new_timings)
+ /*
+ * Some H5 devices do not have signal traces precise enough to
+ * use HS DDR mode for their eMMC chips.
+ *
+ * We still enable HS DDR modes for all the other controller
+ * variants that support them.
+ */
+ if ((host->cfg->clk_delays || host->use_new_timings) &&
+ !of_device_is_compatible(pdev->dev.of_node,
+ "allwinner,sun50i-h5-emmc"))
mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR;
ret = mmc_of_parse(mmc);
if (ret)
goto error_free_dma;
+ /*
+ * If we don't support delay chains in the SoC, we can't use any
+ * of the higher speed modes. Mask them out in case the device
+ * tree specifies the properties for them, which gets added to
+ * the caps by mmc_of_parse() above.
+ */
+ if (!(host->cfg->clk_delays || host->use_new_timings)) {
+ mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR |
+ MMC_CAP_1_2V_DDR | MMC_CAP_UHS);
+ mmc->caps2 &= ~MMC_CAP2_HS200;
+ }
+
+ /* TODO: This driver doesn't support HS400 mode yet */
+ mmc->caps2 &= ~MMC_CAP2_HS400;
+
ret = sunxi_mmc_init_host(host);
if (ret)
goto error_free_dma;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index c03529e3f01a..2adb0d24360f 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -277,6 +277,11 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host,
iowrite16(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
}
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+ iowrite32(val, host->ctl + (addr << host->bus_shift));
+}
+
static inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr,
const u32 *buf, int count)
{
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index 085a0fab769c..595949f1f001 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -43,6 +43,7 @@
#include <linux/regulator/consumer.h>
#include <linux/mmc/sdio.h>
#include <linux/scatterlist.h>
+#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/swiotlb.h>
#include <linux/workqueue.h>
@@ -629,7 +630,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, int ireg,
return false;
}
-static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
+static bool __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
{
struct mmc_host *mmc = host->mmc;
struct tmio_mmc_data *pdata = host->pdata;
@@ -637,7 +638,7 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
unsigned int sdio_status;
if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
- return;
+ return false;
status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask;
@@ -650,6 +651,8 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
mmc_signal_sdio_irq(mmc);
+
+ return ireg;
}
irqreturn_t tmio_mmc_irq(int irq, void *devid)
@@ -668,9 +671,10 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
if (__tmio_mmc_sdcard_irq(host, ireg, status))
return IRQ_HANDLED;
- __tmio_mmc_sdio_irq(host);
+ if (__tmio_mmc_sdio_irq(host))
+ return IRQ_HANDLED;
- return IRQ_HANDLED;
+ return IRQ_NONE;
}
EXPORT_SYMBOL_GPL(tmio_mmc_irq);
@@ -700,7 +704,10 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
/* Set transfer length / blocksize */
sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
- sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
+ if (host->mmc->max_blk_count >= SZ_64K)
+ sd_ctrl_write32(host, CTL_XFER_BLK_COUNT, data->blocks);
+ else
+ sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
tmio_mmc_start_dma(host, data);
@@ -1066,7 +1073,7 @@ static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
/* use ocr_mask if no regulator */
if (!mmc->ocr_avail)
- mmc->ocr_avail = pdata->ocr_mask;
+ mmc->ocr_avail = pdata->ocr_mask;
/*
* try again.
@@ -1287,6 +1294,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
cancel_delayed_work_sync(&host->delayed_reset_work);
tmio_mmc_release_dma(host);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index 3ba42f508014..4fd6da29489e 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
-#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of.h>
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 6e8e7b1bb34b..79a53cb8507b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -756,7 +756,8 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
}
numvirtchips = cfi->numchips * numparts;
- newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
+ newcfi = kmalloc(struct_size(newcfi, chips, numvirtchips),
+ GFP_KERNEL);
if (!newcfi)
return -ENOMEM;
shared = kmalloc_array(cfi->numchips,
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 837b04ab96a9..839ed40625d6 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -135,7 +135,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
* our caller, and copy the appropriate data into them.
*/
- retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
+ retcfi = kmalloc(struct_size(retcfi, chips, cfi.numchips), GFP_KERNEL);
if (!retcfi) {
kfree(cfi.cfiq);
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 4c94fc096696..7754803e3463 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1767,8 +1767,8 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
switch (chip_id) {
case DOC_CHIPID_G3:
- mtd->name = kasprintf(GFP_KERNEL, "docg3.%d",
- docg3->device_id);
+ mtd->name = devm_kasprintf(docg3->dev, GFP_KERNEL, "docg3.%d",
+ docg3->device_id);
if (!mtd->name)
return -ENOMEM;
docg3->max_block = 2047;
@@ -1872,7 +1872,7 @@ nomem3:
nomem2:
kfree(docg3);
nomem1:
- return ERR_PTR(ret);
+ return ret ? ERR_PTR(ret) : NULL;
}
/**
@@ -1886,7 +1886,6 @@ static void doc_release_device(struct mtd_info *mtd)
mtd_device_unregister(mtd);
kfree(docg3->bbt);
kfree(docg3);
- kfree(mtd->name);
kfree(mtd);
}
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index c4a1d04b8c80..651bab6d4e31 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -195,7 +195,14 @@ static int m25p_probe(struct spi_mem *spimem)
spi_mem_set_drvdata(spimem, flash);
flash->spimem = spimem;
- if (spi->mode & SPI_RX_QUAD) {
+ if (spi->mode & SPI_RX_OCTAL) {
+ hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
+
+ if (spi->mode & SPI_TX_OCTAL)
+ hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 |
+ SNOR_HWCAPS_PP_1_1_8 |
+ SNOR_HWCAPS_PP_1_8_8);
+ } else if (spi->mode & SPI_RX_QUAD) {
hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
if (spi->mode & SPI_TX_QUAD)
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index 46238796145f..1c97fabc4bf9 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -24,14 +24,12 @@ static unsigned long writebuf_size = 64;
#define MTDRAM_TOTAL_SIZE (total_size * 1024)
#define MTDRAM_ERASE_SIZE (erase_size * 1024)
-#ifdef MODULE
module_param(total_size, ulong, 0);
MODULE_PARM_DESC(total_size, "Total device size in KiB");
module_param(erase_size, ulong, 0);
MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
module_param(writebuf_size, ulong, 0);
MODULE_PARM_DESC(writebuf_size, "Device write buf size in Bytes (Default: 64)");
-#endif
// We could store these in the mtd structure, but we only support 1 device..
static struct mtd_info *mtd_info;
diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c
index 22f753e555ac..83f88b8b5d9f 100644
--- a/drivers/mtd/devices/powernv_flash.c
+++ b/drivers/mtd/devices/powernv_flash.c
@@ -212,7 +212,7 @@ static int powernv_flash_set_driver_info(struct device *dev,
* Going to have to check what details I need to set and how to
* get them
*/
- mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node);
+ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
mtd->type = MTD_NORFLASH;
mtd->flags = MTD_WRITEABLE;
mtd->size = size;
diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c
index 69f2112340b1..175bdc3b72f4 100644
--- a/drivers/mtd/lpddr/qinfo_probe.c
+++ b/drivers/mtd/lpddr/qinfo_probe.c
@@ -181,8 +181,8 @@ static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
lpddr.numchips = 1;
numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
- retlpddr = kzalloc(sizeof(struct lpddr_private) +
- numvirtchips * sizeof(struct flchip), GFP_KERNEL);
+ retlpddr = kzalloc(struct_size(retlpddr, chips, numvirtchips),
+ GFP_KERNEL);
if (!retlpddr)
return NULL;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 21e3cdc04036..76b4264936ff 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -155,7 +155,6 @@ static ssize_t mtd_flags_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
-
}
static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
@@ -166,7 +165,6 @@ static ssize_t mtd_size_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)mtd->size);
-
}
static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
@@ -176,7 +174,6 @@ static ssize_t mtd_erasesize_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
-
}
static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
@@ -186,7 +183,6 @@ static ssize_t mtd_writesize_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
-
}
static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
@@ -197,7 +193,6 @@ static ssize_t mtd_subpagesize_show(struct device *dev,
unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
-
}
static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
@@ -207,7 +202,6 @@ static ssize_t mtd_oobsize_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
-
}
static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
@@ -226,7 +220,6 @@ static ssize_t mtd_numeraseregions_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
-
}
static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
NULL);
@@ -237,7 +230,6 @@ static ssize_t mtd_name_show(struct device *dev,
struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
-
}
static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
@@ -507,6 +499,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
{
struct nvmem_config config = {};
+ config.id = -1;
config.dev = &mtd->dev;
config.name = mtd->name;
config.owner = THIS_MODULE;
@@ -522,7 +515,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
mtd->nvmem = nvmem_register(&config);
if (IS_ERR(mtd->nvmem)) {
/* Just ignore if there is no NVMEM support in the kernel */
- if (PTR_ERR(mtd->nvmem) == -ENOSYS) {
+ if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) {
mtd->nvmem = NULL;
} else {
dev_err(&mtd->dev, "Failed to register NVMEM device\n");
@@ -559,6 +552,14 @@ int add_mtd_device(struct mtd_info *mtd)
BUG_ON(mtd->writesize == 0);
+ /*
+ * MTD drivers should implement ->_{write,read}() or
+ * ->_{write,read}_oob(), but not both.
+ */
+ if (WARN_ON((mtd->_write && mtd->_write_oob) ||
+ (mtd->_read && mtd->_read_oob)))
+ return -EINVAL;
+
if (WARN_ON((!mtd->erasesize || !mtd->_erase) &&
!(mtd->flags & MTD_NO_ERASE)))
return -EINVAL;
@@ -1089,67 +1090,32 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf)
{
- int ret_code;
- *retlen = 0;
- if (from < 0 || from >= mtd->size || len > mtd->size - from)
- return -EINVAL;
- if (!len)
- return 0;
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .datbuf = buf,
+ };
+ int ret;
- ledtrig_mtd_activity();
- /*
- * In the absence of an error, drivers return a non-negative integer
- * representing the maximum number of bitflips that were corrected on
- * any one ecc region (if applicable; zero otherwise).
- */
- if (mtd->_read) {
- ret_code = mtd->_read(mtd, from, len, retlen, buf);
- } else if (mtd->_read_oob) {
- struct mtd_oob_ops ops = {
- .len = len,
- .datbuf = buf,
- };
-
- ret_code = mtd->_read_oob(mtd, from, &ops);
- *retlen = ops.retlen;
- } else {
- return -ENOTSUPP;
- }
+ ret = mtd_read_oob(mtd, from, &ops);
+ *retlen = ops.retlen;
- if (unlikely(ret_code < 0))
- return ret_code;
- if (mtd->ecc_strength == 0)
- return 0; /* device lacks ecc */
- return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(mtd_read);
int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf)
{
- *retlen = 0;
- if (to < 0 || to >= mtd->size || len > mtd->size - to)
- return -EINVAL;
- if ((!mtd->_write && !mtd->_write_oob) ||
- !(mtd->flags & MTD_WRITEABLE))
- return -EROFS;
- if (!len)
- return 0;
- ledtrig_mtd_activity();
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .datbuf = (u8 *)buf,
+ };
+ int ret;
- if (!mtd->_write) {
- struct mtd_oob_ops ops = {
- .len = len,
- .datbuf = (u8 *)buf,
- };
- int ret;
+ ret = mtd_write_oob(mtd, to, &ops);
+ *retlen = ops.retlen;
- ret = mtd->_write_oob(mtd, to, &ops);
- *retlen = ops.retlen;
- return ret;
- }
-
- return mtd->_write(mtd, to, len, retlen, buf);
+ return ret;
}
EXPORT_SYMBOL_GPL(mtd_write);
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index 9887bda317cd..b31c868019ad 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -7,7 +7,7 @@
extern struct mutex mtd_table_mutex;
struct mtd_info *__mtd_next_device(int i);
-int add_mtd_device(struct mtd_info *mtd);
+int __must_check add_mtd_device(struct mtd_info *mtd);
int del_mtd_device(struct mtd_info *mtd);
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
int del_mtd_partitions(struct mtd_info *);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b6af41b04622..37f174ccbcec 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -480,6 +480,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
/* let's register it anyway to preserve ordering */
slave->offset = 0;
slave->mtd.size = 0;
+
+ /* Initialize ->erasesize to make add_mtd_device() happy. */
+ slave->mtd.erasesize = parent->erasesize;
+
printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
part->name);
goto out_register;
@@ -618,10 +622,21 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
list_add(&new->list, &mtd_partitions);
mutex_unlock(&mtd_partitions_mutex);
- add_mtd_device(&new->mtd);
+ ret = add_mtd_device(&new->mtd);
+ if (ret)
+ goto err_remove_part;
mtd_add_partition_attrs(new);
+ return 0;
+
+err_remove_part:
+ mutex_lock(&mtd_partitions_mutex);
+ list_del(&new->list);
+ mutex_unlock(&mtd_partitions_mutex);
+
+ free_partition(new);
+
return ret;
}
EXPORT_SYMBOL_GPL(mtd_add_partition);
@@ -712,22 +727,31 @@ int add_mtd_partitions(struct mtd_info *master,
{
struct mtd_part *slave;
uint64_t cur_offset = 0;
- int i;
+ int i, ret;
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i < nbparts; i++) {
slave = allocate_partition(master, parts + i, i, cur_offset);
if (IS_ERR(slave)) {
- del_mtd_partitions(master);
- return PTR_ERR(slave);
+ ret = PTR_ERR(slave);
+ goto err_del_partitions;
}
mutex_lock(&mtd_partitions_mutex);
list_add(&slave->list, &mtd_partitions);
mutex_unlock(&mtd_partitions_mutex);
- add_mtd_device(&slave->mtd);
+ ret = add_mtd_device(&slave->mtd);
+ if (ret) {
+ mutex_lock(&mtd_partitions_mutex);
+ list_del(&slave->list);
+ mutex_unlock(&mtd_partitions_mutex);
+
+ free_partition(slave);
+ goto err_del_partitions;
+ }
+
mtd_add_partition_attrs(slave);
/* Look for subpartitions */
parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
@@ -736,6 +760,11 @@ int add_mtd_partitions(struct mtd_info *master,
}
return 0;
+
+err_del_partitions:
+ del_mtd_partitions(master);
+
+ return ret;
}
static DEFINE_SPINLOCK(part_parser_lock);
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 1a55d3e3d4c5..e604625e2dfa 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -541,4 +541,21 @@ config MTD_NAND_TEGRA
is supported. Extra OOB bytes when using HW ECC are currently
not supported.
+config MTD_NAND_STM32_FMC2
+ tristate "Support for NAND controller on STM32MP SoCs"
+ depends on MACH_STM32MP157 || COMPILE_TEST
+ help
+ Enables support for NAND Flash chips on SoCs containing the FMC2
+ NAND controller. This controller is found on STM32MP SoCs.
+ The controller supports a maximum 8k page size and supports
+ a maximum 8-bit correction error per sector of 512 bytes.
+
+config MTD_NAND_MESON
+ tristate "Support for NAND controller on Amlogic's Meson SoCs"
+ depends on ARCH_MESON || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ Enables support for NAND controller on Amlogic's Meson SoCs.
+ This controller is found on Meson SoCs.
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 57159b349054..5a5a72f0793e 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -56,6 +56,8 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/
obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o
obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o
+obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o
+obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o
nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
index 555a74e15269..9d3997840889 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.c
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -876,23 +876,32 @@ static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev,
{
struct platform_device *pdev;
struct atmel_pmecc *pmecc, **ptr;
+ int ret;
pdev = of_find_device_by_node(np);
- if (!pdev || !platform_get_drvdata(pdev))
+ if (!pdev)
return ERR_PTR(-EPROBE_DEFER);
+ pmecc = platform_get_drvdata(pdev);
+ if (!pmecc) {
+ ret = -EPROBE_DEFER;
+ goto err_put_device;
+ }
ptr = devres_alloc(devm_atmel_pmecc_put, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- get_device(&pdev->dev);
- pmecc = platform_get_drvdata(pdev);
+ if (!ptr) {
+ ret = -ENOMEM;
+ goto err_put_device;
+ }
*ptr = pmecc;
devres_add(userdev, ptr);
return pmecc;
+
+err_put_device:
+ put_device(&pdev->dev);
+ return ERR_PTR(ret);
}
static const int atmel_pmecc_strengths[] = { 2, 4, 8, 12, 24, 32 };
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index eebac35304c6..24aeafc67cd4 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -37,9 +37,6 @@
#define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1) /* address cycle */
#define DENALI_MAP11_DATA ((DENALI_MAP11) | 2) /* data cycle */
-/* MAP10 commands */
-#define DENALI_ERASE 0x01
-
#define DENALI_BANK(denali) ((denali)->active_bank << 24)
#define DENALI_INVALID_BANK -1
@@ -476,7 +473,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali,
}
static int denali_pio_read(struct denali_nand_info *denali, void *buf,
- size_t size, int page, int raw)
+ size_t size, int page)
{
u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page;
uint32_t *buf32 = (uint32_t *)buf;
@@ -504,7 +501,7 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf,
}
static int denali_pio_write(struct denali_nand_info *denali,
- const void *buf, size_t size, int page, int raw)
+ const void *buf, size_t size, int page)
{
u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page;
const uint32_t *buf32 = (uint32_t *)buf;
@@ -525,16 +522,16 @@ static int denali_pio_write(struct denali_nand_info *denali,
}
static int denali_pio_xfer(struct denali_nand_info *denali, void *buf,
- size_t size, int page, int raw, int write)
+ size_t size, int page, int write)
{
if (write)
- return denali_pio_write(denali, buf, size, page, raw);
+ return denali_pio_write(denali, buf, size, page);
else
- return denali_pio_read(denali, buf, size, page, raw);
+ return denali_pio_read(denali, buf, size, page);
}
static int denali_dma_xfer(struct denali_nand_info *denali, void *buf,
- size_t size, int page, int raw, int write)
+ size_t size, int page, int write)
{
dma_addr_t dma_addr;
uint32_t irq_mask, irq_status, ecc_err_mask;
@@ -544,7 +541,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf,
dma_addr = dma_map_single(denali->dev, buf, size, dir);
if (dma_mapping_error(denali->dev, dma_addr)) {
dev_dbg(denali->dev, "Failed to DMA-map buffer. Trying PIO.\n");
- return denali_pio_xfer(denali, buf, size, page, raw, write);
+ return denali_pio_xfer(denali, buf, size, page, write);
}
if (write) {
@@ -598,9 +595,9 @@ static int denali_data_xfer(struct denali_nand_info *denali, void *buf,
denali->reg + TRANSFER_SPARE_REG);
if (denali->dma_avail)
- return denali_dma_xfer(denali, buf, size, page, raw, write);
+ return denali_dma_xfer(denali, buf, size, page, write);
else
- return denali_pio_xfer(denali, buf, size, page, raw, write);
+ return denali_pio_xfer(denali, buf, size, page, write);
}
static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
@@ -754,9 +751,6 @@ static int denali_read_oob(struct nand_chip *chip, int page)
static int denali_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
- struct denali_nand_info *denali = mtd_to_denali(mtd);
-
- denali_reset_irq(denali);
denali_oob_xfer(mtd, chip, page, 1);
@@ -903,23 +897,6 @@ static int denali_waitfunc(struct nand_chip *chip)
return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL;
}
-static int denali_erase(struct nand_chip *chip, int page)
-{
- struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
- uint32_t irq_status;
-
- denali_reset_irq(denali);
-
- denali->host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page,
- DENALI_ERASE);
-
- /* wait for erase to complete or failure to occur */
- irq_status = denali_wait_for_irq(denali,
- INTR__ERASE_COMP | INTR__ERASE_FAIL);
-
- return irq_status & INTR__ERASE_COMP ? 0 : -EIO;
-}
-
static int denali_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf)
{
@@ -1244,7 +1221,6 @@ static int denali_attach_chip(struct nand_chip *chip)
chip->ecc.write_page_raw = denali_write_page_raw;
chip->ecc.read_oob = denali_read_oob;
chip->ecc.write_oob = denali_write_oob;
- chip->legacy.erase = denali_erase;
ret = denali_multidev_fixup(denali);
if (ret)
@@ -1322,7 +1298,7 @@ int denali_init(struct denali_nand_info *denali)
}
/* clk rate info is needed for setup_data_interface */
- if (denali->clk_rate && denali->clk_x_rate)
+ if (!denali->clk_rate || !denali->clk_x_rate)
chip->options |= NAND_KEEP_TIMINGS;
chip->legacy.dummy_controller.ops = &denali_controller_ops;
diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h
index 25c00601b8b3..c8c2620fc736 100644
--- a/drivers/mtd/nand/raw/denali.h
+++ b/drivers/mtd/nand/raw/denali.h
@@ -304,7 +304,6 @@ struct denali_nand_info {
u32 irq_status; /* interrupts that have happened */
int irq;
void *buf; /* for syndrome layout conversion */
- dma_addr_t dma_addr;
int dma_avail; /* can support DMA? */
int devs_per_cs; /* devices connected in parallel */
int oob_skip_bytes; /* number of bytes reserved for BBM */
diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
index 7c6a8a426606..0b5ae2418815 100644
--- a/drivers/mtd/nand/raw/denali_dt.c
+++ b/drivers/mtd/nand/raw/denali_dt.c
@@ -109,25 +109,17 @@ static int denali_dt_probe(struct platform_device *pdev)
if (IS_ERR(denali->host))
return PTR_ERR(denali->host);
- /*
- * A single anonymous clock is supported for the backward compatibility.
- * New platforms should support all the named clocks.
- */
dt->clk = devm_clk_get(dev, "nand");
if (IS_ERR(dt->clk))
- dt->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(dt->clk)) {
- dev_err(dev, "no clk available\n");
return PTR_ERR(dt->clk);
- }
dt->clk_x = devm_clk_get(dev, "nand_x");
if (IS_ERR(dt->clk_x))
- dt->clk_x = NULL;
+ return PTR_ERR(dt->clk_x);
dt->clk_ecc = devm_clk_get(dev, "ecc");
if (IS_ERR(dt->clk_ecc))
- dt->clk_ecc = NULL;
+ return PTR_ERR(dt->clk_ecc);
ret = clk_prepare_enable(dt->clk);
if (ret)
@@ -141,19 +133,8 @@ static int denali_dt_probe(struct platform_device *pdev)
if (ret)
goto out_disable_clk_x;
- if (dt->clk_x) {
- denali->clk_rate = clk_get_rate(dt->clk);
- denali->clk_x_rate = clk_get_rate(dt->clk_x);
- } else {
- /*
- * Hardcode the clock rates for the backward compatibility.
- * This works for both SOCFPGA and UniPhier.
- */
- dev_notice(dev,
- "necessary clock is missing. default clock rates are used.\n");
- denali->clk_rate = 50000000;
- denali->clk_x_rate = 200000000;
- }
+ denali->clk_rate = clk_get_rate(dt->clk);
+ denali->clk_x_rate = clk_get_rate(dt->clk_x);
ret = denali_init(denali);
if (ret)
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 325b4414dccc..6c7ca41354be 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -593,23 +593,6 @@ static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf,
dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
}
-/* fsmc_select_chip - assert or deassert nCE */
-static void fsmc_ce_ctrl(struct fsmc_nand_data *host, bool assert)
-{
- u32 pc = readl(host->regs_va + FSMC_PC);
-
- if (!assert)
- writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC);
- else
- writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC);
-
- /*
- * nCE line changes must be applied before returning from this
- * function.
- */
- mb();
-}
-
/*
* fsmc_exec_op - hook called by the core to execute NAND operations
*
@@ -627,8 +610,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
- fsmc_ce_ctrl(host, true);
-
for (op_id = 0; op_id < op->ninstrs; op_id++) {
instr = &op->instrs[op_id];
@@ -686,8 +667,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
}
}
- fsmc_ce_ctrl(host, false);
-
return ret;
}
@@ -986,6 +965,19 @@ static const struct nand_controller_ops fsmc_nand_controller_ops = {
.setup_data_interface = fsmc_setup_data_interface,
};
+/**
+ * fsmc_nand_disable() - Disables the NAND bank
+ * @host: The instance to disable
+ */
+static void fsmc_nand_disable(struct fsmc_nand_data *host)
+{
+ u32 val;
+
+ val = readl(host->regs_va + FSMC_PC);
+ val &= ~FSMC_ENABLE;
+ writel(val, host->regs_va + FSMC_PC);
+}
+
/*
* fsmc_nand_probe - Probe function
* @pdev: platform device structure
@@ -1141,6 +1133,7 @@ release_dma_read_chan:
if (host->mode == USE_DMA_ACCESS)
dma_release_channel(host->read_dma_chan);
disable_clk:
+ fsmc_nand_disable(host);
clk_disable_unprepare(host->clk);
return ret;
@@ -1155,6 +1148,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
if (host) {
nand_release(&host->nand);
+ fsmc_nand_disable(host);
if (host->mode == USE_DMA_ACCESS) {
dma_release_channel(host->write_dma_chan);
@@ -1185,6 +1179,7 @@ static int fsmc_nand_resume(struct device *dev)
clk_prepare_enable(host->clk);
if (host->dev_timings)
fsmc_nand_setup(host, host->dev_timings);
+ nand_reset(&host->nand, 0);
}
return 0;
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index bd4cfac6b5aa..a4768df5083f 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
@@ -155,9 +155,10 @@ int gpmi_init(struct gpmi_nand_data *this)
/*
* Reset BCH here, too. We got failures otherwise :(
- * See later BCH reset for explanation of MX23 handling
+ * See later BCH reset for explanation of MX23 and MX28 handling
*/
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+ ret = gpmi_reset_block(r->bch_regs,
+ GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
if (ret)
goto err_out;
@@ -263,12 +264,10 @@ int bch_set_geometry(struct gpmi_nand_data *this)
/*
* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
* chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
- * On the other hand, the MX28 needs the reset, because one case has been
- * seen where the BCH produced ECC errors constantly after 10000
- * consecutive reboots. The latter case has not been seen on the MX23
- * yet, still we don't know if it could happen there as well.
+ * and MX28.
*/
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+ ret = gpmi_reset_block(r->bch_regs,
+ GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
if (ret)
goto err_out;
diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
index f92ae5aa2a54..9526d5b23c80 100644
--- a/drivers/mtd/nand/raw/jz4740_nand.c
+++ b/drivers/mtd/nand/raw/jz4740_nand.c
@@ -260,7 +260,7 @@ static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat,
}
static int jz_nand_ioremap_resource(struct platform_device *pdev,
- const char *name, struct resource **res, void *__iomem *base)
+ const char *name, struct resource **res, void __iomem **base)
{
int ret;
diff --git a/drivers/mtd/nand/raw/jz4780_bch.c b/drivers/mtd/nand/raw/jz4780_bch.c
index 7201827809e9..c5f74ed85862 100644
--- a/drivers/mtd/nand/raw/jz4780_bch.c
+++ b/drivers/mtd/nand/raw/jz4780_bch.c
@@ -281,12 +281,15 @@ static struct jz4780_bch *jz4780_bch_get(struct device_node *np)
struct jz4780_bch *bch;
pdev = of_find_device_by_node(np);
- if (!pdev || !platform_get_drvdata(pdev))
+ if (!pdev)
return ERR_PTR(-EPROBE_DEFER);
- get_device(&pdev->dev);
-
bch = platform_get_drvdata(pdev);
+ if (!bch) {
+ put_device(&pdev->dev);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
clk_prepare_enable(bch->clk);
return bch;
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 84283c6bb0ff..f38e5c1b87e4 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -2550,9 +2550,8 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
}
/* Alloc the nand chip structure */
- marvell_nand = devm_kzalloc(dev, sizeof(*marvell_nand) +
- (nsels *
- sizeof(struct marvell_nand_chip_sel)),
+ marvell_nand = devm_kzalloc(dev,
+ struct_size(marvell_nand, sels, nsels),
GFP_KERNEL);
if (!marvell_nand) {
dev_err(dev, "could not allocate chip structure\n");
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
new file mode 100644
index 000000000000..3e8aa71407b5
--- /dev/null
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -0,0 +1,1464 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Amlogic Meson Nand Flash Controller Driver
+ *
+ * Copyright (c) 2018 Amlogic, inc.
+ * Author: Liang Yang <liang.yang@amlogic.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sched/task_stack.h>
+
+#define NFC_REG_CMD 0x00
+#define NFC_CMD_IDLE (0xc << 14)
+#define NFC_CMD_CLE (0x5 << 14)
+#define NFC_CMD_ALE (0x6 << 14)
+#define NFC_CMD_ADL ((0 << 16) | (3 << 20))
+#define NFC_CMD_ADH ((1 << 16) | (3 << 20))
+#define NFC_CMD_AIL ((2 << 16) | (3 << 20))
+#define NFC_CMD_AIH ((3 << 16) | (3 << 20))
+#define NFC_CMD_SEED ((8 << 16) | (3 << 20))
+#define NFC_CMD_M2N ((0 << 17) | (2 << 20))
+#define NFC_CMD_N2M ((1 << 17) | (2 << 20))
+#define NFC_CMD_RB BIT(20)
+#define NFC_CMD_SCRAMBLER_ENABLE BIT(19)
+#define NFC_CMD_SCRAMBLER_DISABLE 0
+#define NFC_CMD_SHORTMODE_DISABLE 0
+#define NFC_CMD_RB_INT BIT(14)
+
+#define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0))
+
+#define NFC_REG_CFG 0x04
+#define NFC_REG_DADR 0x08
+#define NFC_REG_IADR 0x0c
+#define NFC_REG_BUF 0x10
+#define NFC_REG_INFO 0x14
+#define NFC_REG_DC 0x18
+#define NFC_REG_ADR 0x1c
+#define NFC_REG_DL 0x20
+#define NFC_REG_DH 0x24
+#define NFC_REG_CADR 0x28
+#define NFC_REG_SADR 0x2c
+#define NFC_REG_PINS 0x30
+#define NFC_REG_VER 0x38
+
+#define NFC_RB_IRQ_EN BIT(21)
+
+#define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \
+ ( \
+ (cmd_dir) | \
+ ((ran) << 19) | \
+ ((bch) << 14) | \
+ ((short_mode) << 13) | \
+ (((page_size) & 0x7f) << 6) | \
+ ((pages) & 0x3f) \
+ )
+
+#define GENCMDDADDRL(adl, addr) ((adl) | ((addr) & 0xffff))
+#define GENCMDDADDRH(adh, addr) ((adh) | (((addr) >> 16) & 0xffff))
+#define GENCMDIADDRL(ail, addr) ((ail) | ((addr) & 0xffff))
+#define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff))
+
+#define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N)
+
+#define ECC_CHECK_RETURN_FF (-1)
+
+#define NAND_CE0 (0xe << 10)
+#define NAND_CE1 (0xd << 10)
+
+#define DMA_BUSY_TIMEOUT 0x100000
+#define CMD_FIFO_EMPTY_TIMEOUT 1000
+
+#define MAX_CE_NUM 2
+
+/* eMMC clock register, misc control */
+#define CLK_SELECT_NAND BIT(31)
+
+#define NFC_CLK_CYCLE 6
+
+/* nand flash controller delay 3 ns */
+#define NFC_DEFAULT_DELAY 3000
+
+#define ROW_ADDER(page, index) (((page) >> (8 * (index))) & 0xff)
+#define MAX_CYCLE_ADDRS 5
+#define DIRREAD 1
+#define DIRWRITE 0
+
+#define ECC_PARITY_BCH8_512B 14
+#define ECC_COMPLETE BIT(31)
+#define ECC_ERR_CNT(x) (((x) >> 24) & GENMASK(5, 0))
+#define ECC_ZERO_CNT(x) (((x) >> 16) & GENMASK(5, 0))
+#define ECC_UNCORRECTABLE 0x3f
+
+#define PER_INFO_BYTE 8
+
+struct meson_nfc_nand_chip {
+ struct list_head node;
+ struct nand_chip nand;
+ unsigned long clk_rate;
+ unsigned long level1_divider;
+ u32 bus_timing;
+ u32 twb;
+ u32 tadl;
+ u32 tbers_max;
+
+ u32 bch_mode;
+ u8 *data_buf;
+ __le64 *info_buf;
+ u32 nsels;
+ u8 sels[0];
+};
+
+struct meson_nand_ecc {
+ u32 bch;
+ u32 strength;
+};
+
+struct meson_nfc_data {
+ const struct nand_ecc_caps *ecc_caps;
+};
+
+struct meson_nfc_param {
+ u32 chip_select;
+ u32 rb_select;
+};
+
+struct nand_rw_cmd {
+ u32 cmd0;
+ u32 addrs[MAX_CYCLE_ADDRS];
+ u32 cmd1;
+};
+
+struct nand_timing {
+ u32 twb;
+ u32 tadl;
+ u32 tbers_max;
+};
+
+struct meson_nfc {
+ struct nand_controller controller;
+ struct clk *core_clk;
+ struct clk *device_clk;
+ struct clk *phase_tx;
+ struct clk *phase_rx;
+
+ unsigned long clk_rate;
+ u32 bus_timing;
+
+ struct device *dev;
+ void __iomem *reg_base;
+ struct regmap *reg_clk;
+ struct completion completion;
+ struct list_head chips;
+ const struct meson_nfc_data *data;
+ struct meson_nfc_param param;
+ struct nand_timing timing;
+ union {
+ int cmd[32];
+ struct nand_rw_cmd rw;
+ } cmdfifo;
+
+ dma_addr_t daddr;
+ dma_addr_t iaddr;
+
+ unsigned long assigned_cs;
+};
+
+enum {
+ NFC_ECC_BCH8_1K = 2,
+ NFC_ECC_BCH24_1K,
+ NFC_ECC_BCH30_1K,
+ NFC_ECC_BCH40_1K,
+ NFC_ECC_BCH50_1K,
+ NFC_ECC_BCH60_1K,
+};
+
+#define MESON_ECC_DATA(b, s) { .bch = (b), .strength = (s)}
+
+static struct meson_nand_ecc meson_ecc[] = {
+ MESON_ECC_DATA(NFC_ECC_BCH8_1K, 8),
+ MESON_ECC_DATA(NFC_ECC_BCH24_1K, 24),
+ MESON_ECC_DATA(NFC_ECC_BCH30_1K, 30),
+ MESON_ECC_DATA(NFC_ECC_BCH40_1K, 40),
+ MESON_ECC_DATA(NFC_ECC_BCH50_1K, 50),
+ MESON_ECC_DATA(NFC_ECC_BCH60_1K, 60),
+};
+
+static int meson_nand_calc_ecc_bytes(int step_size, int strength)
+{
+ int ecc_bytes;
+
+ if (step_size == 512 && strength == 8)
+ return ECC_PARITY_BCH8_512B;
+
+ ecc_bytes = DIV_ROUND_UP(strength * fls(step_size * 8), 8);
+ ecc_bytes = ALIGN(ecc_bytes, 2);
+
+ return ecc_bytes;
+}
+
+NAND_ECC_CAPS_SINGLE(meson_gxl_ecc_caps,
+ meson_nand_calc_ecc_bytes, 1024, 8, 24, 30, 40, 50, 60);
+NAND_ECC_CAPS_SINGLE(meson_axg_ecc_caps,
+ meson_nand_calc_ecc_bytes, 1024, 8);
+
+static struct meson_nfc_nand_chip *to_meson_nand(struct nand_chip *nand)
+{
+ return container_of(nand, struct meson_nfc_nand_chip, nand);
+}
+
+static void meson_nfc_select_chip(struct nand_chip *nand, int chip)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ int ret, value;
+
+ if (chip < 0 || WARN_ON_ONCE(chip >= meson_chip->nsels))
+ return;
+
+ nfc->param.chip_select = meson_chip->sels[chip] ? NAND_CE1 : NAND_CE0;
+ nfc->param.rb_select = nfc->param.chip_select;
+ nfc->timing.twb = meson_chip->twb;
+ nfc->timing.tadl = meson_chip->tadl;
+ nfc->timing.tbers_max = meson_chip->tbers_max;
+
+ if (nfc->clk_rate != meson_chip->clk_rate) {
+ ret = clk_set_rate(nfc->device_clk, meson_chip->clk_rate);
+ if (ret) {
+ dev_err(nfc->dev, "failed to set clock rate\n");
+ return;
+ }
+ nfc->clk_rate = meson_chip->clk_rate;
+ }
+ if (nfc->bus_timing != meson_chip->bus_timing) {
+ value = (NFC_CLK_CYCLE - 1) | (meson_chip->bus_timing << 5);
+ writel(value, nfc->reg_base + NFC_REG_CFG);
+ writel((1 << 31), nfc->reg_base + NFC_REG_CMD);
+ nfc->bus_timing = meson_chip->bus_timing;
+ }
+}
+
+static void meson_nfc_cmd_idle(struct meson_nfc *nfc, u32 time)
+{
+ writel(nfc->param.chip_select | NFC_CMD_IDLE | (time & 0x3ff),
+ nfc->reg_base + NFC_REG_CMD);
+}
+
+static void meson_nfc_cmd_seed(struct meson_nfc *nfc, u32 seed)
+{
+ writel(NFC_CMD_SEED | (0xc2 + (seed & 0x7fff)),
+ nfc->reg_base + NFC_REG_CMD);
+}
+
+static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir,
+ int scrambler)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ u32 bch = meson_chip->bch_mode, cmd;
+ int len = mtd->writesize, pagesize, pages;
+
+ pagesize = nand->ecc.size;
+
+ if (raw) {
+ len = mtd->writesize + mtd->oobsize;
+ cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir);
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ return;
+ }
+
+ pages = len / nand->ecc.size;
+
+ cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch,
+ NFC_CMD_SHORTMODE_DISABLE, pagesize, pages);
+
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+}
+
+static void meson_nfc_drain_cmd(struct meson_nfc *nfc)
+{
+ /*
+ * Insert two commands to make sure all valid commands are finished.
+ *
+ * The Nand flash controller is designed as two stages pipleline -
+ * a) fetch and b) excute.
+ * There might be cases when the driver see command queue is empty,
+ * but the Nand flash controller still has two commands buffered,
+ * one is fetched into NFC request queue (ready to run), and another
+ * is actively executing. So pushing 2 "IDLE" commands guarantees that
+ * the pipeline is emptied.
+ */
+ meson_nfc_cmd_idle(nfc, 0);
+ meson_nfc_cmd_idle(nfc, 0);
+}
+
+static int meson_nfc_wait_cmd_finish(struct meson_nfc *nfc,
+ unsigned int timeout_ms)
+{
+ u32 cmd_size = 0;
+ int ret;
+
+ /* wait cmd fifo is empty */
+ ret = readl_relaxed_poll_timeout(nfc->reg_base + NFC_REG_CMD, cmd_size,
+ !NFC_CMD_GET_SIZE(cmd_size),
+ 10, timeout_ms * 1000);
+ if (ret)
+ dev_err(nfc->dev, "wait for empty CMD FIFO time out\n");
+
+ return ret;
+}
+
+static int meson_nfc_wait_dma_finish(struct meson_nfc *nfc)
+{
+ meson_nfc_drain_cmd(nfc);
+
+ return meson_nfc_wait_cmd_finish(nfc, DMA_BUSY_TIMEOUT);
+}
+
+static u8 *meson_nfc_oob_ptr(struct nand_chip *nand, int i)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ int len;
+
+ len = nand->ecc.size * (i + 1) + (nand->ecc.bytes + 2) * i;
+
+ return meson_chip->data_buf + len;
+}
+
+static u8 *meson_nfc_data_ptr(struct nand_chip *nand, int i)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ int len, temp;
+
+ temp = nand->ecc.size + nand->ecc.bytes;
+ len = (temp + 2) * i;
+
+ return meson_chip->data_buf + len;
+}
+
+static void meson_nfc_get_data_oob(struct nand_chip *nand,
+ u8 *buf, u8 *oobbuf)
+{
+ int i, oob_len = 0;
+ u8 *dsrc, *osrc;
+
+ oob_len = nand->ecc.bytes + 2;
+ for (i = 0; i < nand->ecc.steps; i++) {
+ if (buf) {
+ dsrc = meson_nfc_data_ptr(nand, i);
+ memcpy(buf, dsrc, nand->ecc.size);
+ buf += nand->ecc.size;
+ }
+ osrc = meson_nfc_oob_ptr(nand, i);
+ memcpy(oobbuf, osrc, oob_len);
+ oobbuf += oob_len;
+ }
+}
+
+static void meson_nfc_set_data_oob(struct nand_chip *nand,
+ const u8 *buf, u8 *oobbuf)
+{
+ int i, oob_len = 0;
+ u8 *dsrc, *osrc;
+
+ oob_len = nand->ecc.bytes + 2;
+ for (i = 0; i < nand->ecc.steps; i++) {
+ if (buf) {
+ dsrc = meson_nfc_data_ptr(nand, i);
+ memcpy(dsrc, buf, nand->ecc.size);
+ buf += nand->ecc.size;
+ }
+ osrc = meson_nfc_oob_ptr(nand, i);
+ memcpy(osrc, oobbuf, oob_len);
+ oobbuf += oob_len;
+ }
+}
+
+static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
+{
+ u32 cmd, cfg;
+ int ret = 0;
+
+ meson_nfc_cmd_idle(nfc, nfc->timing.twb);
+ meson_nfc_drain_cmd(nfc);
+ meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT);
+
+ cfg = readl(nfc->reg_base + NFC_REG_CFG);
+ cfg |= NFC_RB_IRQ_EN;
+ writel(cfg, nfc->reg_base + NFC_REG_CFG);
+
+ init_completion(&nfc->completion);
+
+ /* use the max erase time as the maximum clock for waiting R/B */
+ cmd = NFC_CMD_RB | NFC_CMD_RB_INT
+ | nfc->param.chip_select | nfc->timing.tbers_max;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ ret = wait_for_completion_timeout(&nfc->completion,
+ msecs_to_jiffies(timeout_ms));
+ if (ret == 0)
+ ret = -1;
+
+ return ret;
+}
+
+static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ __le64 *info;
+ int i, count;
+
+ for (i = 0, count = 0; i < nand->ecc.steps; i++, count += 2) {
+ info = &meson_chip->info_buf[i];
+ *info |= oob_buf[count];
+ *info |= oob_buf[count + 1] << 8;
+ }
+}
+
+static void meson_nfc_get_user_byte(struct nand_chip *nand, u8 *oob_buf)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ __le64 *info;
+ int i, count;
+
+ for (i = 0, count = 0; i < nand->ecc.steps; i++, count += 2) {
+ info = &meson_chip->info_buf[i];
+ oob_buf[count] = *info;
+ oob_buf[count + 1] = *info >> 8;
+ }
+}
+
+static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips,
+ u64 *correct_bitmap)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ __le64 *info;
+ int ret = 0, i;
+
+ for (i = 0; i < nand->ecc.steps; i++) {
+ info = &meson_chip->info_buf[i];
+ if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) {
+ mtd->ecc_stats.corrected += ECC_ERR_CNT(*info);
+ *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info));
+ *correct_bitmap |= 1 >> i;
+ continue;
+ }
+ if ((nand->options & NAND_NEED_SCRAMBLING) &&
+ ECC_ZERO_CNT(*info) < nand->ecc.strength) {
+ mtd->ecc_stats.corrected += ECC_ZERO_CNT(*info);
+ *bitflips = max_t(u32, *bitflips,
+ ECC_ZERO_CNT(*info));
+ ret = ECC_CHECK_RETURN_FF;
+ } else {
+ ret = -EBADMSG;
+ }
+ }
+ return ret;
+}
+
+static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, u8 *databuf,
+ int datalen, u8 *infobuf, int infolen,
+ enum dma_data_direction dir)
+{
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ u32 cmd;
+ int ret = 0;
+
+ nfc->daddr = dma_map_single(nfc->dev, (void *)databuf, datalen, dir);
+ ret = dma_mapping_error(nfc->dev, nfc->daddr);
+ if (ret) {
+ dev_err(nfc->dev, "DMA mapping error\n");
+ return ret;
+ }
+ cmd = GENCMDDADDRL(NFC_CMD_ADL, nfc->daddr);
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ cmd = GENCMDDADDRH(NFC_CMD_ADH, nfc->daddr);
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ if (infobuf) {
+ nfc->iaddr = dma_map_single(nfc->dev, infobuf, infolen, dir);
+ ret = dma_mapping_error(nfc->dev, nfc->iaddr);
+ if (ret) {
+ dev_err(nfc->dev, "DMA mapping error\n");
+ dma_unmap_single(nfc->dev,
+ nfc->daddr, datalen, dir);
+ return ret;
+ }
+ cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr);
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ cmd = GENCMDIADDRH(NFC_CMD_AIH, nfc->iaddr);
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ }
+
+ return ret;
+}
+
+static void meson_nfc_dma_buffer_release(struct nand_chip *nand,
+ int infolen, int datalen,
+ enum dma_data_direction dir)
+{
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+
+ dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir);
+ if (infolen)
+ dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir);
+}
+
+static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
+{
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ int ret = 0;
+ u32 cmd;
+ u8 *info;
+
+ info = kzalloc(PER_INFO_BYTE, GFP_KERNEL);
+ ret = meson_nfc_dma_buffer_setup(nand, buf, len, info,
+ PER_INFO_BYTE, DMA_FROM_DEVICE);
+ if (ret)
+ return ret;
+
+ cmd = NFC_CMD_N2M | (len & GENMASK(5, 0));
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ meson_nfc_drain_cmd(nfc);
+ meson_nfc_wait_cmd_finish(nfc, 1000);
+ meson_nfc_dma_buffer_release(nand, len, PER_INFO_BYTE, DMA_FROM_DEVICE);
+ kfree(info);
+
+ return ret;
+}
+
+static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
+{
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ int ret = 0;
+ u32 cmd;
+
+ ret = meson_nfc_dma_buffer_setup(nand, buf, len, NULL,
+ 0, DMA_TO_DEVICE);
+ if (ret)
+ return ret;
+
+ cmd = NFC_CMD_M2N | (len & GENMASK(5, 0));
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ meson_nfc_drain_cmd(nfc);
+ meson_nfc_wait_cmd_finish(nfc, 1000);
+ meson_nfc_dma_buffer_release(nand, len, 0, DMA_TO_DEVICE);
+
+ return ret;
+}
+
+static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
+ int page, bool in)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ const struct nand_sdr_timings *sdr =
+ nand_get_sdr_timings(&nand->data_interface);
+ u32 *addrs = nfc->cmdfifo.rw.addrs;
+ u32 cs = nfc->param.chip_select;
+ u32 cmd0, cmd_num, row_start;
+ int ret = 0, i;
+
+ cmd_num = sizeof(struct nand_rw_cmd) / sizeof(int);
+
+ cmd0 = in ? NAND_CMD_READ0 : NAND_CMD_SEQIN;
+ nfc->cmdfifo.rw.cmd0 = cs | NFC_CMD_CLE | cmd0;
+
+ addrs[0] = cs | NFC_CMD_ALE | 0;
+ if (mtd->writesize <= 512) {
+ cmd_num--;
+ row_start = 1;
+ } else {
+ addrs[1] = cs | NFC_CMD_ALE | 0;
+ row_start = 2;
+ }
+
+ addrs[row_start] = cs | NFC_CMD_ALE | ROW_ADDER(page, 0);
+ addrs[row_start + 1] = cs | NFC_CMD_ALE | ROW_ADDER(page, 1);
+
+ if (nand->options & NAND_ROW_ADDR_3)
+ addrs[row_start + 2] =
+ cs | NFC_CMD_ALE | ROW_ADDER(page, 2);
+ else
+ cmd_num--;
+
+ /* subtract cmd1 */
+ cmd_num--;
+
+ for (i = 0; i < cmd_num; i++)
+ writel_relaxed(nfc->cmdfifo.cmd[i],
+ nfc->reg_base + NFC_REG_CMD);
+
+ if (in) {
+ nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART;
+ writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD);
+ meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max));
+ } else {
+ meson_nfc_cmd_idle(nfc, nfc->timing.tadl);
+ }
+
+ return ret;
+}
+
+static int meson_nfc_write_page_sub(struct nand_chip *nand,
+ int page, int raw)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ const struct nand_sdr_timings *sdr =
+ nand_get_sdr_timings(&nand->data_interface);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ int data_len, info_len;
+ u32 cmd;
+ int ret;
+
+ meson_nfc_select_chip(nand, nand->cur_cs);
+
+ data_len = mtd->writesize + mtd->oobsize;
+ info_len = nand->ecc.steps * PER_INFO_BYTE;
+
+ ret = meson_nfc_rw_cmd_prepare_and_execute(nand, page, DIRWRITE);
+ if (ret)
+ return ret;
+
+ ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf,
+ data_len, (u8 *)meson_chip->info_buf,
+ info_len, DMA_TO_DEVICE);
+ if (ret)
+ return ret;
+
+ if (nand->options & NAND_NEED_SCRAMBLING) {
+ meson_nfc_cmd_seed(nfc, page);
+ meson_nfc_cmd_access(nand, raw, DIRWRITE,
+ NFC_CMD_SCRAMBLER_ENABLE);
+ } else {
+ meson_nfc_cmd_access(nand, raw, DIRWRITE,
+ NFC_CMD_SCRAMBLER_DISABLE);
+ }
+
+ cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max));
+
+ meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE);
+
+ return ret;
+}
+
+static int meson_nfc_write_page_raw(struct nand_chip *nand, const u8 *buf,
+ int oob_required, int page)
+{
+ u8 *oob_buf = nand->oob_poi;
+
+ meson_nfc_set_data_oob(nand, buf, oob_buf);
+
+ return meson_nfc_write_page_sub(nand, page, 1);
+}
+
+static int meson_nfc_write_page_hwecc(struct nand_chip *nand,
+ const u8 *buf, int oob_required, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ u8 *oob_buf = nand->oob_poi;
+
+ memcpy(meson_chip->data_buf, buf, mtd->writesize);
+ memset(meson_chip->info_buf, 0, nand->ecc.steps * PER_INFO_BYTE);
+ meson_nfc_set_user_byte(nand, oob_buf);
+
+ return meson_nfc_write_page_sub(nand, page, 0);
+}
+
+static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc,
+ struct nand_chip *nand, int raw)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ __le64 *info;
+ u32 neccpages;
+ int ret;
+
+ neccpages = raw ? 1 : nand->ecc.steps;
+ info = &meson_chip->info_buf[neccpages - 1];
+ do {
+ usleep_range(10, 15);
+ /* info is updated by nfc dma engine*/
+ smp_rmb();
+ ret = *info & ECC_COMPLETE;
+ } while (!ret);
+}
+
+static int meson_nfc_read_page_sub(struct nand_chip *nand,
+ int page, int raw)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ int data_len, info_len;
+ int ret;
+
+ meson_nfc_select_chip(nand, nand->cur_cs);
+
+ data_len = mtd->writesize + mtd->oobsize;
+ info_len = nand->ecc.steps * PER_INFO_BYTE;
+
+ ret = meson_nfc_rw_cmd_prepare_and_execute(nand, page, DIRREAD);
+ if (ret)
+ return ret;
+
+ ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf,
+ data_len, (u8 *)meson_chip->info_buf,
+ info_len, DMA_FROM_DEVICE);
+ if (ret)
+ return ret;
+
+ if (nand->options & NAND_NEED_SCRAMBLING) {
+ meson_nfc_cmd_seed(nfc, page);
+ meson_nfc_cmd_access(nand, raw, DIRREAD,
+ NFC_CMD_SCRAMBLER_ENABLE);
+ } else {
+ meson_nfc_cmd_access(nand, raw, DIRREAD,
+ NFC_CMD_SCRAMBLER_DISABLE);
+ }
+
+ ret = meson_nfc_wait_dma_finish(nfc);
+ meson_nfc_check_ecc_pages_valid(nfc, nand, raw);
+
+ meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_FROM_DEVICE);
+
+ return ret;
+}
+
+static int meson_nfc_read_page_raw(struct nand_chip *nand, u8 *buf,
+ int oob_required, int page)
+{
+ u8 *oob_buf = nand->oob_poi;
+ int ret;
+
+ ret = meson_nfc_read_page_sub(nand, page, 1);
+ if (ret)
+ return ret;
+
+ meson_nfc_get_data_oob(nand, buf, oob_buf);
+
+ return 0;
+}
+
+static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf,
+ int oob_required, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
+ u64 correct_bitmap = 0;
+ u32 bitflips = 0;
+ u8 *oob_buf = nand->oob_poi;
+ int ret, i;
+
+ ret = meson_nfc_read_page_sub(nand, page, 0);
+ if (ret)
+ return ret;
+
+ meson_nfc_get_user_byte(nand, oob_buf);
+ ret = meson_nfc_ecc_correct(nand, &bitflips, &correct_bitmap);
+ if (ret == ECC_CHECK_RETURN_FF) {
+ if (buf)
+ memset(buf, 0xff, mtd->writesize);
+ memset(oob_buf, 0xff, mtd->oobsize);
+ } else if (ret < 0) {
+ if ((nand->options & NAND_NEED_SCRAMBLING) || !buf) {
+ mtd->ecc_stats.failed++;
+ return bitflips;
+ }
+ ret = meson_nfc_read_page_raw(nand, buf, 0, page);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nand->ecc.steps ; i++) {
+ u8 *data = buf + i * ecc->size;
+ u8 *oob = nand->oob_poi + i * (ecc->bytes + 2);
+
+ if (correct_bitmap & (1 << i))
+ continue;
+ ret = nand_check_erased_ecc_chunk(data, ecc->size,
+ oob, ecc->bytes + 2,
+ NULL, 0,
+ ecc->strength);
+ if (ret < 0) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += ret;
+ bitflips = max_t(u32, bitflips, ret);
+ }
+ }
+ } else if (buf && buf != meson_chip->data_buf) {
+ memcpy(buf, meson_chip->data_buf, mtd->writesize);
+ }
+
+ return bitflips;
+}
+
+static int meson_nfc_read_oob_raw(struct nand_chip *nand, int page)
+{
+ return meson_nfc_read_page_raw(nand, NULL, 1, page);
+}
+
+static int meson_nfc_read_oob(struct nand_chip *nand, int page)
+{
+ return meson_nfc_read_page_hwecc(nand, NULL, 1, page);
+}
+
+static bool meson_nfc_is_buffer_dma_safe(const void *buffer)
+{
+ if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer)))
+ return true;
+ return false;
+}
+
+static void *
+meson_nand_op_get_dma_safe_input_buf(const struct nand_op_instr *instr)
+{
+ if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR))
+ return NULL;
+
+ if (meson_nfc_is_buffer_dma_safe(instr->ctx.data.buf.in))
+ return instr->ctx.data.buf.in;
+
+ return kzalloc(instr->ctx.data.len, GFP_KERNEL);
+}
+
+static void
+meson_nand_op_put_dma_safe_input_buf(const struct nand_op_instr *instr,
+ void *buf)
+{
+ if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR) ||
+ WARN_ON(!buf))
+ return;
+
+ if (buf == instr->ctx.data.buf.in)
+ return;
+
+ memcpy(instr->ctx.data.buf.in, buf, instr->ctx.data.len);
+ kfree(buf);
+}
+
+static void *
+meson_nand_op_get_dma_safe_output_buf(const struct nand_op_instr *instr)
+{
+ if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR))
+ return NULL;
+
+ if (meson_nfc_is_buffer_dma_safe(instr->ctx.data.buf.out))
+ return (void *)instr->ctx.data.buf.out;
+
+ return kmemdup(instr->ctx.data.buf.out,
+ instr->ctx.data.len, GFP_KERNEL);
+}
+
+static void
+meson_nand_op_put_dma_safe_output_buf(const struct nand_op_instr *instr,
+ const void *buf)
+{
+ if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR) ||
+ WARN_ON(!buf))
+ return;
+
+ if (buf != instr->ctx.data.buf.out)
+ kfree(buf);
+}
+
+static int meson_nfc_exec_op(struct nand_chip *nand,
+ const struct nand_operation *op, bool check_only)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ const struct nand_op_instr *instr = NULL;
+ void *buf;
+ u32 op_id, delay_idle, cmd;
+ int i;
+
+ meson_nfc_select_chip(nand, op->cs);
+ for (op_id = 0; op_id < op->ninstrs; op_id++) {
+ instr = &op->instrs[op_id];
+ delay_idle = DIV_ROUND_UP(PSEC_TO_NSEC(instr->delay_ns),
+ meson_chip->level1_divider *
+ NFC_CLK_CYCLE);
+ switch (instr->type) {
+ case NAND_OP_CMD_INSTR:
+ cmd = nfc->param.chip_select | NFC_CMD_CLE;
+ cmd |= instr->ctx.cmd.opcode & 0xff;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ meson_nfc_cmd_idle(nfc, delay_idle);
+ break;
+
+ case NAND_OP_ADDR_INSTR:
+ for (i = 0; i < instr->ctx.addr.naddrs; i++) {
+ cmd = nfc->param.chip_select | NFC_CMD_ALE;
+ cmd |= instr->ctx.addr.addrs[i] & 0xff;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+ }
+ meson_nfc_cmd_idle(nfc, delay_idle);
+ break;
+
+ case NAND_OP_DATA_IN_INSTR:
+ buf = meson_nand_op_get_dma_safe_input_buf(instr);
+ if (!buf)
+ return -ENOMEM;
+ meson_nfc_read_buf(nand, buf, instr->ctx.data.len);
+ meson_nand_op_put_dma_safe_input_buf(instr, buf);
+ break;
+
+ case NAND_OP_DATA_OUT_INSTR:
+ buf = meson_nand_op_get_dma_safe_output_buf(instr);
+ if (!buf)
+ return -ENOMEM;
+ meson_nfc_write_buf(nand, buf, instr->ctx.data.len);
+ meson_nand_op_put_dma_safe_output_buf(instr, buf);
+ break;
+
+ case NAND_OP_WAITRDY_INSTR:
+ meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms);
+ if (instr->delay_ns)
+ meson_nfc_cmd_idle(nfc, delay_idle);
+ break;
+ }
+ }
+ meson_nfc_wait_cmd_finish(nfc, 1000);
+ return 0;
+}
+
+static int meson_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section >= nand->ecc.steps)
+ return -ERANGE;
+
+ oobregion->offset = 2 + (section * (2 + nand->ecc.bytes));
+ oobregion->length = nand->ecc.bytes;
+
+ return 0;
+}
+
+static int meson_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section >= nand->ecc.steps)
+ return -ERANGE;
+
+ oobregion->offset = section * (2 + nand->ecc.bytes);
+ oobregion->length = 2;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
+ .ecc = meson_ooblayout_ecc,
+ .free = meson_ooblayout_free,
+};
+
+static int meson_nfc_clk_init(struct meson_nfc *nfc)
+{
+ int ret;
+
+ /* request core clock */
+ nfc->core_clk = devm_clk_get(nfc->dev, "core");
+ if (IS_ERR(nfc->core_clk)) {
+ dev_err(nfc->dev, "failed to get core clock\n");
+ return PTR_ERR(nfc->core_clk);
+ }
+
+ nfc->device_clk = devm_clk_get(nfc->dev, "device");
+ if (IS_ERR(nfc->device_clk)) {
+ dev_err(nfc->dev, "failed to get device clock\n");
+ return PTR_ERR(nfc->device_clk);
+ }
+
+ nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
+ if (IS_ERR(nfc->phase_tx)) {
+ dev_err(nfc->dev, "failed to get TX clk\n");
+ return PTR_ERR(nfc->phase_tx);
+ }
+
+ nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
+ if (IS_ERR(nfc->phase_rx)) {
+ dev_err(nfc->dev, "failed to get RX clk\n");
+ return PTR_ERR(nfc->phase_rx);
+ }
+
+ /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+ regmap_update_bits(nfc->reg_clk,
+ 0, CLK_SELECT_NAND, CLK_SELECT_NAND);
+
+ ret = clk_prepare_enable(nfc->core_clk);
+ if (ret) {
+ dev_err(nfc->dev, "failed to enable core clock\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(nfc->device_clk);
+ if (ret) {
+ dev_err(nfc->dev, "failed to enable device clock\n");
+ goto err_device_clk;
+ }
+
+ ret = clk_prepare_enable(nfc->phase_tx);
+ if (ret) {
+ dev_err(nfc->dev, "failed to enable TX clock\n");
+ goto err_phase_tx;
+ }
+
+ ret = clk_prepare_enable(nfc->phase_rx);
+ if (ret) {
+ dev_err(nfc->dev, "failed to enable RX clock\n");
+ goto err_phase_rx;
+ }
+
+ ret = clk_set_rate(nfc->device_clk, 24000000);
+ if (ret)
+ goto err_phase_rx;
+
+ return 0;
+err_phase_rx:
+ clk_disable_unprepare(nfc->phase_tx);
+err_phase_tx:
+ clk_disable_unprepare(nfc->device_clk);
+err_device_clk:
+ clk_disable_unprepare(nfc->core_clk);
+ return ret;
+}
+
+static void meson_nfc_disable_clk(struct meson_nfc *nfc)
+{
+ clk_disable_unprepare(nfc->phase_rx);
+ clk_disable_unprepare(nfc->phase_tx);
+ clk_disable_unprepare(nfc->device_clk);
+ clk_disable_unprepare(nfc->core_clk);
+}
+
+static void meson_nfc_free_buffer(struct nand_chip *nand)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+
+ kfree(meson_chip->info_buf);
+ kfree(meson_chip->data_buf);
+}
+
+static int meson_chip_buffer_init(struct nand_chip *nand)
+{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ u32 page_bytes, info_bytes, nsectors;
+
+ nsectors = mtd->writesize / nand->ecc.size;
+
+ page_bytes = mtd->writesize + mtd->oobsize;
+ info_bytes = nsectors * PER_INFO_BYTE;
+
+ meson_chip->data_buf = kmalloc(page_bytes, GFP_KERNEL);
+ if (!meson_chip->data_buf)
+ return -ENOMEM;
+
+ meson_chip->info_buf = kmalloc(info_bytes, GFP_KERNEL);
+ if (!meson_chip->info_buf) {
+ kfree(meson_chip->data_buf);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static
+int meson_nfc_setup_data_interface(struct nand_chip *nand, int csline,
+ const struct nand_data_interface *conf)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ const struct nand_sdr_timings *timings;
+ u32 div, bt_min, bt_max, tbers_clocks;
+
+ timings = nand_get_sdr_timings(conf);
+ if (IS_ERR(timings))
+ return -ENOTSUPP;
+
+ if (csline == NAND_DATA_IFACE_CHECK_ONLY)
+ return 0;
+
+ div = DIV_ROUND_UP((timings->tRC_min / 1000), NFC_CLK_CYCLE);
+ bt_min = (timings->tREA_max + NFC_DEFAULT_DELAY) / div;
+ bt_max = (NFC_DEFAULT_DELAY + timings->tRHOH_min +
+ timings->tRC_min / 2) / div;
+
+ meson_chip->twb = DIV_ROUND_UP(PSEC_TO_NSEC(timings->tWB_max),
+ div * NFC_CLK_CYCLE);
+ meson_chip->tadl = DIV_ROUND_UP(PSEC_TO_NSEC(timings->tADL_min),
+ div * NFC_CLK_CYCLE);
+ tbers_clocks = DIV_ROUND_UP_ULL(PSEC_TO_NSEC(timings->tBERS_max),
+ div * NFC_CLK_CYCLE);
+ meson_chip->tbers_max = ilog2(tbers_clocks);
+ if (!is_power_of_2(tbers_clocks))
+ meson_chip->tbers_max++;
+
+ bt_min = DIV_ROUND_UP(bt_min, 1000);
+ bt_max = DIV_ROUND_UP(bt_max, 1000);
+
+ if (bt_max < bt_min)
+ return -EINVAL;
+
+ meson_chip->level1_divider = div;
+ meson_chip->clk_rate = 1000000000 / meson_chip->level1_divider;
+ meson_chip->bus_timing = (bt_min + bt_max) / 2 + 1;
+
+ return 0;
+}
+
+static int meson_nand_bch_mode(struct nand_chip *nand)
+{
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ int i;
+
+ if (nand->ecc.strength > 60 || nand->ecc.strength < 8)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(meson_ecc); i++) {
+ if (meson_ecc[i].strength == nand->ecc.strength) {
+ meson_chip->bch_mode = meson_ecc[i].bch;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static void meson_nand_detach_chip(struct nand_chip *nand)
+{
+ meson_nfc_free_buffer(nand);
+}
+
+static int meson_nand_attach_chip(struct nand_chip *nand)
+{
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ int nsectors = mtd->writesize / 1024;
+ int ret;
+
+ if (!mtd->name) {
+ mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
+ "%s:nand%d",
+ dev_name(nfc->dev),
+ meson_chip->sels[0]);
+ if (!mtd->name)
+ return -ENOMEM;
+ }
+
+ if (nand->bbt_options & NAND_BBT_USE_FLASH)
+ nand->bbt_options |= NAND_BBT_NO_OOB;
+
+ nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+ ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps,
+ mtd->oobsize - 2 * nsectors);
+ if (ret) {
+ dev_err(nfc->dev, "failed to ECC init\n");
+ return -EINVAL;
+ }
+
+ ret = meson_nand_bch_mode(nand);
+ if (ret)
+ return -EINVAL;
+
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.write_page_raw = meson_nfc_write_page_raw;
+ nand->ecc.write_page = meson_nfc_write_page_hwecc;
+ nand->ecc.write_oob_raw = nand_write_oob_std;
+ nand->ecc.write_oob = nand_write_oob_std;
+
+ nand->ecc.read_page_raw = meson_nfc_read_page_raw;
+ nand->ecc.read_page = meson_nfc_read_page_hwecc;
+ nand->ecc.read_oob_raw = meson_nfc_read_oob_raw;
+ nand->ecc.read_oob = meson_nfc_read_oob;
+
+ if (nand->options & NAND_BUSWIDTH_16) {
+ dev_err(nfc->dev, "16bits bus width not supported");
+ return -EINVAL;
+ }
+ ret = meson_chip_buffer_init(nand);
+ if (ret)
+ return -ENOMEM;
+
+ return ret;
+}
+
+static const struct nand_controller_ops meson_nand_controller_ops = {
+ .attach_chip = meson_nand_attach_chip,
+ .detach_chip = meson_nand_detach_chip,
+ .setup_data_interface = meson_nfc_setup_data_interface,
+ .exec_op = meson_nfc_exec_op,
+};
+
+static int
+meson_nfc_nand_chip_init(struct device *dev,
+ struct meson_nfc *nfc, struct device_node *np)
+{
+ struct meson_nfc_nand_chip *meson_chip;
+ struct nand_chip *nand;
+ struct mtd_info *mtd;
+ int ret, i;
+ u32 tmp, nsels;
+
+ if (!of_get_property(np, "reg", &nsels))
+ return -EINVAL;
+
+ nsels /= sizeof(u32);
+ if (!nsels || nsels > MAX_CE_NUM) {
+ dev_err(dev, "invalid register property size\n");
+ return -EINVAL;
+ }
+
+ meson_chip = devm_kzalloc(dev,
+ sizeof(*meson_chip) + (nsels * sizeof(u8)),
+ GFP_KERNEL);
+ if (!meson_chip)
+ return -ENOMEM;
+
+ meson_chip->nsels = nsels;
+
+ for (i = 0; i < nsels; i++) {
+ ret = of_property_read_u32_index(np, "reg", i, &tmp);
+ if (ret) {
+ dev_err(dev, "could not retrieve register property: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
+ dev_err(dev, "CS %d already assigned\n", tmp);
+ return -EINVAL;
+ }
+ }
+
+ nand = &meson_chip->nand;
+ nand->controller = &nfc->controller;
+ nand->controller->ops = &meson_nand_controller_ops;
+ nand_set_flash_node(nand, np);
+ nand_set_controller_data(nand, nfc);
+
+ nand->options |= NAND_USE_BOUNCE_BUFFER;
+ mtd = nand_to_mtd(nand);
+ mtd->owner = THIS_MODULE;
+ mtd->dev.parent = dev;
+
+ ret = nand_scan(nand, nsels);
+ if (ret)
+ return ret;
+
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret) {
+ dev_err(dev, "failed to register MTD device: %d\n", ret);
+ nand_cleanup(nand);
+ return ret;
+ }
+
+ list_add_tail(&meson_chip->node, &nfc->chips);
+
+ return 0;
+}
+
+static int meson_nfc_nand_chip_cleanup(struct meson_nfc *nfc)
+{
+ struct meson_nfc_nand_chip *meson_chip;
+ struct mtd_info *mtd;
+ int ret;
+
+ while (!list_empty(&nfc->chips)) {
+ meson_chip = list_first_entry(&nfc->chips,
+ struct meson_nfc_nand_chip, node);
+ mtd = nand_to_mtd(&meson_chip->nand);
+ ret = mtd_device_unregister(mtd);
+ if (ret)
+ return ret;
+
+ meson_nfc_free_buffer(&meson_chip->nand);
+ nand_cleanup(&meson_chip->nand);
+ list_del(&meson_chip->node);
+ }
+
+ return 0;
+}
+
+static int meson_nfc_nand_chips_init(struct device *dev,
+ struct meson_nfc *nfc)
+{
+ struct device_node *np = dev->of_node;
+ struct device_node *nand_np;
+ int ret;
+
+ for_each_child_of_node(np, nand_np) {
+ ret = meson_nfc_nand_chip_init(dev, nfc, nand_np);
+ if (ret) {
+ meson_nfc_nand_chip_cleanup(nfc);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t meson_nfc_irq(int irq, void *id)
+{
+ struct meson_nfc *nfc = id;
+ u32 cfg;
+
+ cfg = readl(nfc->reg_base + NFC_REG_CFG);
+ if (!(cfg & NFC_RB_IRQ_EN))
+ return IRQ_NONE;
+
+ cfg &= ~(NFC_RB_IRQ_EN);
+ writel(cfg, nfc->reg_base + NFC_REG_CFG);
+
+ complete(&nfc->completion);
+ return IRQ_HANDLED;
+}
+
+static const struct meson_nfc_data meson_gxl_data = {
+ .ecc_caps = &meson_gxl_ecc_caps,
+};
+
+static const struct meson_nfc_data meson_axg_data = {
+ .ecc_caps = &meson_axg_ecc_caps,
+};
+
+static const struct of_device_id meson_nfc_id_table[] = {
+ {
+ .compatible = "amlogic,meson-gxl-nfc",
+ .data = &meson_gxl_data,
+ }, {
+ .compatible = "amlogic,meson-axg-nfc",
+ .data = &meson_axg_data,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, meson_nfc_id_table);
+
+static int meson_nfc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_nfc *nfc;
+ struct resource *res;
+ int ret, irq;
+
+ nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc)
+ return -ENOMEM;
+
+ nfc->data = of_device_get_match_data(&pdev->dev);
+ if (!nfc->data)
+ return -ENODEV;
+
+ nand_controller_init(&nfc->controller);
+ INIT_LIST_HEAD(&nfc->chips);
+
+ nfc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nfc->reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(nfc->reg_base))
+ return PTR_ERR(nfc->reg_base);
+
+ nfc->reg_clk =
+ syscon_regmap_lookup_by_phandle(dev->of_node,
+ "amlogic,mmc-syscon");
+ if (IS_ERR(nfc->reg_clk)) {
+ dev_err(dev, "Failed to lookup clock base\n");
+ return PTR_ERR(nfc->reg_clk);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no NFC IRQ resource\n");
+ return -EINVAL;
+ }
+
+ ret = meson_nfc_clk_init(nfc);
+ if (ret) {
+ dev_err(dev, "failed to initialize NAND clock\n");
+ return ret;
+ }
+
+ writel(0, nfc->reg_base + NFC_REG_CFG);
+ ret = devm_request_irq(dev, irq, meson_nfc_irq, 0, dev_name(dev), nfc);
+ if (ret) {
+ dev_err(dev, "failed to request NFC IRQ\n");
+ ret = -EINVAL;
+ goto err_clk;
+ }
+
+ ret = dma_set_mask(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(dev, "failed to set DMA mask\n");
+ goto err_clk;
+ }
+
+ platform_set_drvdata(pdev, nfc);
+
+ ret = meson_nfc_nand_chips_init(dev, nfc);
+ if (ret) {
+ dev_err(dev, "failed to init NAND chips\n");
+ goto err_clk;
+ }
+
+ return 0;
+err_clk:
+ meson_nfc_disable_clk(nfc);
+ return ret;
+}
+
+static int meson_nfc_remove(struct platform_device *pdev)
+{
+ struct meson_nfc *nfc = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = meson_nfc_nand_chip_cleanup(nfc);
+ if (ret)
+ return ret;
+
+ meson_nfc_disable_clk(nfc);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver meson_nfc_driver = {
+ .probe = meson_nfc_probe,
+ .remove = meson_nfc_remove,
+ .driver = {
+ .name = "meson-nand",
+ .of_match_table = meson_nfc_id_table,
+ },
+};
+module_platform_driver(meson_nfc_driver);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_AUTHOR("Liang Yang <liang.yang@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic's Meson NAND Flash Controller driver");
diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
index 6432bd70c3b3..05b0c19d72d9 100644
--- a/drivers/mtd/nand/raw/mtk_ecc.c
+++ b/drivers/mtd/nand/raw/mtk_ecc.c
@@ -267,11 +267,15 @@ static struct mtk_ecc *mtk_ecc_get(struct device_node *np)
struct mtk_ecc *ecc;
pdev = of_find_device_by_node(np);
- if (!pdev || !platform_get_drvdata(pdev))
+ if (!pdev)
return ERR_PTR(-EPROBE_DEFER);
- get_device(&pdev->dev);
ecc = platform_get_drvdata(pdev);
+ if (!ecc) {
+ put_device(&pdev->dev);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
clk_prepare_enable(ecc->clk);
mtk_ecc_hw_init(ecc);
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index b6b4602f5132..2c0e09187773 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -1451,8 +1451,7 @@ static int mtk_nfc_probe(struct platform_device *pdev)
if (!nfc)
return -ENOMEM;
- spin_lock_init(&nfc->controller.lock);
- init_waitqueue_head(&nfc->controller.wq);
+ nand_controller_init(&nfc->controller);
INIT_LIST_HEAD(&nfc->chips);
nfc->controller.ops = &mtk_nfc_controller_ops;
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index cca4b24d2ffa..ddd396e93e32 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -278,11 +278,8 @@ EXPORT_SYMBOL_GPL(nand_deselect_target);
static void nand_release_device(struct nand_chip *chip)
{
/* Release the controller and the chip */
- spin_lock(&chip->controller->lock);
- chip->controller->active = NULL;
- chip->state = FL_READY;
- wake_up(&chip->controller->wq);
- spin_unlock(&chip->controller->lock);
+ mutex_unlock(&chip->controller->lock);
+ mutex_unlock(&chip->lock);
}
/**
@@ -331,57 +328,23 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
}
/**
- * panic_nand_get_device - [GENERIC] Get chip for selected access
- * @chip: the nand chip descriptor
- * @new_state: the state which is requested
- *
- * Used when in panic, no locks are taken.
- */
-static void panic_nand_get_device(struct nand_chip *chip, int new_state)
-{
- /* Hardware controller shared among independent devices */
- chip->controller->active = chip;
- chip->state = new_state;
-}
-
-/**
* nand_get_device - [GENERIC] Get chip for selected access
* @chip: NAND chip structure
- * @new_state: the state which is requested
*
- * Get the device and lock it for exclusive access
+ * Lock the device and its controller for exclusive access
+ *
+ * Return: -EBUSY if the chip has been suspended, 0 otherwise
*/
-static int
-nand_get_device(struct nand_chip *chip, int new_state)
+static int nand_get_device(struct nand_chip *chip)
{
- spinlock_t *lock = &chip->controller->lock;
- wait_queue_head_t *wq = &chip->controller->wq;
- DECLARE_WAITQUEUE(wait, current);
-retry:
- spin_lock(lock);
-
- /* Hardware controller shared among independent devices */
- if (!chip->controller->active)
- chip->controller->active = chip;
-
- if (chip->controller->active == chip && chip->state == FL_READY) {
- chip->state = new_state;
- spin_unlock(lock);
- return 0;
- }
- if (new_state == FL_PM_SUSPENDED) {
- if (chip->controller->active->state == FL_PM_SUSPENDED) {
- chip->state = FL_PM_SUSPENDED;
- spin_unlock(lock);
- return 0;
- }
+ mutex_lock(&chip->lock);
+ if (chip->suspended) {
+ mutex_unlock(&chip->lock);
+ return -EBUSY;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(wq, &wait);
- spin_unlock(lock);
- schedule();
- remove_wait_queue(wq, &wait);
- goto retry;
+ mutex_lock(&chip->controller->lock);
+
+ return 0;
}
/**
@@ -410,6 +373,7 @@ static int nand_check_wp(struct nand_chip *chip)
/**
* nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @chip: NAND chip object
* @oob: oob data buffer
* @len: oob data write length
* @ops: oob ops structure
@@ -457,7 +421,7 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
struct mtd_oob_ops *ops)
{
struct mtd_info *mtd = nand_to_mtd(chip);
- int chipnr, page, status, len;
+ int chipnr, page, status, len, ret;
pr_debug("%s: to = 0x%08x, len = %i\n",
__func__, (unsigned int)to, (int)ops->ooblen);
@@ -479,7 +443,9 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
* if we don't do this. I have no clue why, but I seem to have 'fixed'
* it in the doc2000 driver in August 1999. dwmw2.
*/
- nand_reset(chip, chipnr);
+ ret = nand_reset(chip, chipnr);
+ if (ret)
+ return ret;
nand_select_target(chip, chipnr);
@@ -602,7 +568,10 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
nand_erase_nand(chip, &einfo, 0);
/* Write bad block marker to OOB */
- nand_get_device(chip, FL_WRITING);
+ ret = nand_get_device(chip);
+ if (ret)
+ return ret;
+
ret = nand_markbad_bbm(chip, ofs);
nand_release_device(chip);
}
@@ -3580,7 +3549,9 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
ops->mode != MTD_OPS_RAW)
return -ENOTSUPP;
- nand_get_device(chip, FL_READING);
+ ret = nand_get_device(chip);
+ if (ret)
+ return ret;
if (!ops->datbuf)
ret = nand_do_read_oob(chip, from, ops);
@@ -4099,9 +4070,6 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
struct mtd_oob_ops ops;
int ret;
- /* Grab the device */
- panic_nand_get_device(chip, FL_WRITING);
-
nand_select_target(chip, chipnr);
/* Wait for the device to get ready */
@@ -4132,7 +4100,9 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
ops->retlen = 0;
- nand_get_device(chip, FL_WRITING);
+ ret = nand_get_device(chip);
+ if (ret)
+ return ret;
switch (ops->mode) {
case MTD_OPS_PLACE_OOB:
@@ -4155,23 +4125,6 @@ out:
}
/**
- * single_erase - [GENERIC] NAND standard block erase command function
- * @chip: NAND chip object
- * @page: the page address of the block which will be erased
- *
- * Standard erase command for NAND chips. Returns NAND status.
- */
-static int single_erase(struct nand_chip *chip, int page)
-{
- unsigned int eraseblock;
-
- /* Send commands to erase a block */
- eraseblock = page >> (chip->phys_erase_shift - chip->page_shift);
-
- return nand_erase_op(chip, eraseblock);
-}
-
-/**
* nand_erase - [MTD Interface] erase block(s)
* @mtd: MTD device structure
* @instr: erase instruction
@@ -4194,7 +4147,7 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
int allowbbt)
{
- int page, status, pages_per_block, ret, chipnr;
+ int page, pages_per_block, ret, chipnr;
loff_t len;
pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -4205,7 +4158,9 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
return -EINVAL;
/* Grab the lock and see if the device is available */
- nand_get_device(chip, FL_ERASING);
+ ret = nand_get_device(chip);
+ if (ret)
+ return ret;
/* Shift to get first page */
page = (int)(instr->addr >> chip->page_shift);
@@ -4246,17 +4201,11 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
(page + pages_per_block))
chip->pagebuf = -1;
- if (chip->legacy.erase)
- status = chip->legacy.erase(chip,
- page & chip->pagemask);
- else
- status = single_erase(chip, page & chip->pagemask);
-
- /* See if block erase succeeded */
- if (status) {
+ ret = nand_erase_op(chip, (page & chip->pagemask) >>
+ (chip->phys_erase_shift - chip->page_shift));
+ if (ret) {
pr_debug("%s: failed erase, page 0x%08x\n",
__func__, page);
- ret = -EIO;
instr->fail_addr =
((loff_t)page << chip->page_shift);
goto erase_exit;
@@ -4298,7 +4247,7 @@ static void nand_sync(struct mtd_info *mtd)
pr_debug("%s: called\n", __func__);
/* Grab the lock and see if the device is available */
- nand_get_device(chip, FL_SYNCING);
+ WARN_ON(nand_get_device(chip));
/* Release it and go back */
nand_release_device(chip);
}
@@ -4315,7 +4264,10 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
int ret;
/* Select the NAND device */
- nand_get_device(chip, FL_READING);
+ ret = nand_get_device(chip);
+ if (ret)
+ return ret;
+
nand_select_target(chip, chipnr);
ret = nand_block_checkbad(chip, offs, 0);
@@ -4388,7 +4340,13 @@ static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
*/
static int nand_suspend(struct mtd_info *mtd)
{
- return nand_get_device(mtd_to_nand(mtd), FL_PM_SUSPENDED);
+ struct nand_chip *chip = mtd_to_nand(mtd);
+
+ mutex_lock(&chip->lock);
+ chip->suspended = 1;
+ mutex_unlock(&chip->lock);
+
+ return 0;
}
/**
@@ -4399,11 +4357,13 @@ static void nand_resume(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- if (chip->state == FL_PM_SUSPENDED)
- nand_release_device(chip);
+ mutex_lock(&chip->lock);
+ if (chip->suspended)
+ chip->suspended = 0;
else
pr_err("%s called for a chip which is not in suspended state\n",
__func__);
+ mutex_unlock(&chip->lock);
}
/**
@@ -4413,7 +4373,7 @@ static void nand_resume(struct mtd_info *mtd)
*/
static void nand_shutdown(struct mtd_info *mtd)
{
- nand_get_device(mtd_to_nand(mtd), FL_PM_SUSPENDED);
+ nand_suspend(mtd);
}
/* Set default functions */
@@ -5018,6 +4978,8 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
/* Assume all dies are deselected when we enter nand_scan_ident(). */
chip->cur_cs = -1;
+ mutex_init(&chip->lock);
+
/* Enforce the right timings for reset/detection */
onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
@@ -5060,11 +5022,15 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
u8 id[2];
/* See comment in nand_get_flash_type for reset */
- nand_reset(chip, i);
+ ret = nand_reset(chip, i);
+ if (ret)
+ break;
nand_select_target(chip, i);
/* Send the command for reading device ID */
- nand_readid_op(chip, 0, id, sizeof(id));
+ ret = nand_readid_op(chip, 0, id, sizeof(id));
+ if (ret)
+ break;
/* Read manufacturer and device IDs */
if (nand_maf_id != id[0] || nand_dev_id != id[1]) {
nand_deselect_target(chip);
@@ -5555,6 +5521,7 @@ static int nand_scan_tail(struct nand_chip *chip)
}
if (!ecc->read_page)
ecc->read_page = nand_read_page_hwecc_oob_first;
+ /* fall through */
case NAND_ECC_HW:
/* Use standard hwecc read page function? */
@@ -5574,6 +5541,7 @@ static int nand_scan_tail(struct nand_chip *chip)
ecc->read_subpage = nand_read_subpage;
if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
ecc->write_subpage = nand_write_subpage_hwecc;
+ /* fall through */
case NAND_ECC_HW_SYNDROME:
if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
@@ -5611,6 +5579,7 @@ static int nand_scan_tail(struct nand_chip *chip)
ecc->size, mtd->writesize);
ecc->mode = NAND_ECC_SOFT;
ecc->algo = NAND_ECC_HAMMING;
+ /* fall through */
case NAND_ECC_SOFT:
ret = nand_set_ecc_soft_ops(chip);
@@ -5717,9 +5686,6 @@ static int nand_scan_tail(struct nand_chip *chip)
}
chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
- /* Initialize state */
- chip->state = FL_READY;
-
/* Invalidate the pagebuffer reference */
chip->pagebuf = -1;
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 1b722fe9213c..19a2b563acdf 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -158,7 +158,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
/**
* read_bbt - [GENERIC] Read the bad block table starting from page
- * @chip: NAND chip object
+ * @this: NAND chip object
* @buf: temporary buffer
* @page: the starting page
* @num: the number of bbt descriptors to read
diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
index 43575943f13b..f2526ec616a6 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -331,6 +331,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command,
*/
if (column == -1 && page_addr == -1)
return;
+ /* fall through */
default:
/*
@@ -483,7 +484,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command,
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
- /* This applies to read commands */
+ /* fall through - This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index 68e8b9f7f372..8f280a2962c8 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -994,12 +994,9 @@ static int omap_wait(struct nand_chip *this)
{
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(this));
unsigned long timeo = jiffies;
- int status, state = this->state;
+ int status;
- if (state == FL_ERASING)
- timeo += msecs_to_jiffies(400);
- else
- timeo += msecs_to_jiffies(20);
+ timeo += msecs_to_jiffies(400);
writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
while (time_before(jiffies, timeo)) {
@@ -2173,11 +2170,8 @@ static const struct nand_controller_ops omap_nand_controller_ops = {
};
/* Shared among all NAND instances to synchronize access to the ECC Engine */
-static struct nand_controller omap_gpmc_controller = {
- .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock),
- .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq),
- .ops = &omap_nand_controller_ops,
-};
+static struct nand_controller omap_gpmc_controller;
+static bool omap_gpmc_controller_initialized;
static int omap_nand_probe(struct platform_device *pdev)
{
@@ -2227,6 +2221,12 @@ static int omap_nand_probe(struct platform_device *pdev)
info->phys_base = res->start;
+ if (!omap_gpmc_controller_initialized) {
+ omap_gpmc_controller.ops = &omap_nand_controller_ops;
+ nand_controller_init(&omap_gpmc_controller);
+ omap_gpmc_controller_initialized = true;
+ }
+
nand_chip->controller = &omap_gpmc_controller;
nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R;
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index 46c62a31fa46..920e7375084f 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2833,6 +2833,16 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
if (ret)
return ret;
+ if (nandc->props->is_bam) {
+ free_bam_transaction(nandc);
+ nandc->bam_txn = alloc_bam_transaction(nandc);
+ if (!nandc->bam_txn) {
+ dev_err(nandc->dev,
+ "failed to allocate bam transaction\n");
+ return -ENOMEM;
+ }
+ }
+
ret = mtd_device_register(mtd, NULL, 0);
if (ret)
nand_cleanup(chip);
@@ -2847,16 +2857,6 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
struct qcom_nand_host *host;
int ret;
- if (nandc->props->is_bam) {
- free_bam_transaction(nandc);
- nandc->bam_txn = alloc_bam_transaction(nandc);
- if (!nandc->bam_txn) {
- dev_err(nandc->dev,
- "failed to allocate bam transaction\n");
- return -ENOMEM;
- }
- }
-
for_each_available_child_of_node(dn, child) {
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
if (!host) {
diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
index c01422d953dd..86456216fb93 100644
--- a/drivers/mtd/nand/raw/r852.c
+++ b/drivers/mtd/nand/raw/r852.c
@@ -369,8 +369,7 @@ static int r852_wait(struct nand_chip *chip)
unsigned long timeout;
u8 status;
- timeout = jiffies + (chip->state == FL_ERASING ?
- msecs_to_jiffies(400) : msecs_to_jiffies(20));
+ timeout = jiffies + msecs_to_jiffies(400);
while (time_before(jiffies, timeout))
if (chip->legacy.dev_ready(chip))
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
new file mode 100644
index 000000000000..999ca6a66036
--- /dev/null
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -0,0 +1,2073 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018
+ * Author: Christophe Kerello <christophe.kerello@st.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* Bad block marker length */
+#define FMC2_BBM_LEN 2
+
+/* ECC step size */
+#define FMC2_ECC_STEP_SIZE 512
+
+/* BCHDSRx registers length */
+#define FMC2_BCHDSRS_LEN 20
+
+/* HECCR length */
+#define FMC2_HECCR_LEN 4
+
+/* Max requests done for a 8k nand page size */
+#define FMC2_MAX_SG 16
+
+/* Max chip enable */
+#define FMC2_MAX_CE 2
+
+/* Max ECC buffer length */
+#define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
+
+/* Timings */
+#define FMC2_THIZ 1
+#define FMC2_TIO 8000
+#define FMC2_TSYNC 3000
+#define FMC2_PCR_TIMING_MASK 0xf
+#define FMC2_PMEM_PATT_TIMING_MASK 0xff
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1 0x0
+#define FMC2_PCR 0x80
+#define FMC2_SR 0x84
+#define FMC2_PMEM 0x88
+#define FMC2_PATT 0x8c
+#define FMC2_HECCR 0x94
+#define FMC2_CSQCR 0x200
+#define FMC2_CSQCFGR1 0x204
+#define FMC2_CSQCFGR2 0x208
+#define FMC2_CSQCFGR3 0x20c
+#define FMC2_CSQAR1 0x210
+#define FMC2_CSQAR2 0x214
+#define FMC2_CSQIER 0x220
+#define FMC2_CSQISR 0x224
+#define FMC2_CSQICR 0x228
+#define FMC2_CSQEMSR 0x230
+#define FMC2_BCHIER 0x250
+#define FMC2_BCHISR 0x254
+#define FMC2_BCHICR 0x258
+#define FMC2_BCHPBR1 0x260
+#define FMC2_BCHPBR2 0x264
+#define FMC2_BCHPBR3 0x268
+#define FMC2_BCHPBR4 0x26c
+#define FMC2_BCHDSR0 0x27c
+#define FMC2_BCHDSR1 0x280
+#define FMC2_BCHDSR2 0x284
+#define FMC2_BCHDSR3 0x288
+#define FMC2_BCHDSR4 0x28c
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_FMC2EN BIT(31)
+
+/* Register: FMC2_PCR */
+#define FMC2_PCR_PWAITEN BIT(1)
+#define FMC2_PCR_PBKEN BIT(2)
+#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
+#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
+#define FMC2_PCR_PWID_BUSWIDTH_8 0
+#define FMC2_PCR_PWID_BUSWIDTH_16 1
+#define FMC2_PCR_ECCEN BIT(6)
+#define FMC2_PCR_ECCALG BIT(8)
+#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
+#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR_DEFAULT 0xf
+#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
+#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
+#define FMC2_PCR_TAR_DEFAULT 0xf
+#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
+#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS_512 1
+#define FMC2_PCR_ECCSS_2048 3
+#define FMC2_PCR_BCHECC BIT(24)
+#define FMC2_PCR_WEN BIT(25)
+
+/* Register: FMC2_SR */
+#define FMC2_SR_NWRF BIT(6)
+
+/* Register: FMC2_PMEM */
+#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
+#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
+#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
+#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PMEM_DEFAULT 0x0a0a0a0a
+
+/* Register: FMC2_PATT */
+#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
+#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
+#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
+#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PATT_DEFAULT 0x0a0a0a0a
+
+/* Register: FMC2_CSQCR */
+#define FMC2_CSQCR_CSQSTART BIT(0)
+
+/* Register: FMC2_CSQCFGR1 */
+#define FMC2_CSQCFGR1_CMD2EN BIT(1)
+#define FMC2_CSQCFGR1_DMADEN BIT(2)
+#define FMC2_CSQCFGR1_ACYNBR(x) (((x) & 0x7) << 4)
+#define FMC2_CSQCFGR1_CMD1(x) (((x) & 0xff) << 8)
+#define FMC2_CSQCFGR1_CMD2(x) (((x) & 0xff) << 16)
+#define FMC2_CSQCFGR1_CMD1T BIT(24)
+#define FMC2_CSQCFGR1_CMD2T BIT(25)
+
+/* Register: FMC2_CSQCFGR2 */
+#define FMC2_CSQCFGR2_SQSDTEN BIT(0)
+#define FMC2_CSQCFGR2_RCMD2EN BIT(1)
+#define FMC2_CSQCFGR2_DMASEN BIT(2)
+#define FMC2_CSQCFGR2_RCMD1(x) (((x) & 0xff) << 8)
+#define FMC2_CSQCFGR2_RCMD2(x) (((x) & 0xff) << 16)
+#define FMC2_CSQCFGR2_RCMD1T BIT(24)
+#define FMC2_CSQCFGR2_RCMD2T BIT(25)
+
+/* Register: FMC2_CSQCFGR3 */
+#define FMC2_CSQCFGR3_SNBR(x) (((x) & 0x1f) << 8)
+#define FMC2_CSQCFGR3_AC1T BIT(16)
+#define FMC2_CSQCFGR3_AC2T BIT(17)
+#define FMC2_CSQCFGR3_AC3T BIT(18)
+#define FMC2_CSQCFGR3_AC4T BIT(19)
+#define FMC2_CSQCFGR3_AC5T BIT(20)
+#define FMC2_CSQCFGR3_SDT BIT(21)
+#define FMC2_CSQCFGR3_RAC1T BIT(22)
+#define FMC2_CSQCFGR3_RAC2T BIT(23)
+
+/* Register: FMC2_CSQCAR1 */
+#define FMC2_CSQCAR1_ADDC1(x) (((x) & 0xff) << 0)
+#define FMC2_CSQCAR1_ADDC2(x) (((x) & 0xff) << 8)
+#define FMC2_CSQCAR1_ADDC3(x) (((x) & 0xff) << 16)
+#define FMC2_CSQCAR1_ADDC4(x) (((x) & 0xff) << 24)
+
+/* Register: FMC2_CSQCAR2 */
+#define FMC2_CSQCAR2_ADDC5(x) (((x) & 0xff) << 0)
+#define FMC2_CSQCAR2_NANDCEN(x) (((x) & 0x3) << 10)
+#define FMC2_CSQCAR2_SAO(x) (((x) & 0xffff) << 16)
+
+/* Register: FMC2_CSQIER */
+#define FMC2_CSQIER_TCIE BIT(0)
+
+/* Register: FMC2_CSQICR */
+#define FMC2_CSQICR_CLEAR_IRQ GENMASK(4, 0)
+
+/* Register: FMC2_CSQEMSR */
+#define FMC2_CSQEMSR_SEM GENMASK(15, 0)
+
+/* Register: FMC2_BCHIER */
+#define FMC2_BCHIER_DERIE BIT(1)
+#define FMC2_BCHIER_EPBRIE BIT(4)
+
+/* Register: FMC2_BCHICR */
+#define FMC2_BCHICR_CLEAR_IRQ GENMASK(4, 0)
+
+/* Register: FMC2_BCHDSR0 */
+#define FMC2_BCHDSR0_DUE BIT(0)
+#define FMC2_BCHDSR0_DEF BIT(1)
+#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
+#define FMC2_BCHDSR0_DEN_SHIFT 4
+
+/* Register: FMC2_BCHDSR1 */
+#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
+#define FMC2_BCHDSR1_EBP2_SHIFT 16
+
+/* Register: FMC2_BCHDSR2 */
+#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
+#define FMC2_BCHDSR2_EBP4_SHIFT 16
+
+/* Register: FMC2_BCHDSR3 */
+#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
+#define FMC2_BCHDSR3_EBP6_SHIFT 16
+
+/* Register: FMC2_BCHDSR4 */
+#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
+#define FMC2_BCHDSR4_EBP8_SHIFT 16
+
+enum stm32_fmc2_ecc {
+ FMC2_ECC_HAM = 1,
+ FMC2_ECC_BCH4 = 4,
+ FMC2_ECC_BCH8 = 8
+};
+
+enum stm32_fmc2_irq_state {
+ FMC2_IRQ_UNKNOWN = 0,
+ FMC2_IRQ_BCH,
+ FMC2_IRQ_SEQ
+};
+
+struct stm32_fmc2_timings {
+ u8 tclr;
+ u8 tar;
+ u8 thiz;
+ u8 twait;
+ u8 thold_mem;
+ u8 tset_mem;
+ u8 thold_att;
+ u8 tset_att;
+};
+
+struct stm32_fmc2_nand {
+ struct nand_chip chip;
+ struct stm32_fmc2_timings timings;
+ int ncs;
+ int cs_used[FMC2_MAX_CE];
+};
+
+static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
+{
+ return container_of(chip, struct stm32_fmc2_nand, chip);
+}
+
+struct stm32_fmc2_nfc {
+ struct nand_controller base;
+ struct stm32_fmc2_nand nand;
+ struct device *dev;
+ void __iomem *io_base;
+ void __iomem *data_base[FMC2_MAX_CE];
+ void __iomem *cmd_base[FMC2_MAX_CE];
+ void __iomem *addr_base[FMC2_MAX_CE];
+ phys_addr_t io_phys_addr;
+ phys_addr_t data_phys_addr[FMC2_MAX_CE];
+ struct clk *clk;
+ u8 irq_state;
+
+ struct dma_chan *dma_tx_ch;
+ struct dma_chan *dma_rx_ch;
+ struct dma_chan *dma_ecc_ch;
+ struct sg_table dma_data_sg;
+ struct sg_table dma_ecc_sg;
+ u8 *ecc_buf;
+ int dma_ecc_len;
+
+ struct completion complete;
+ struct completion dma_data_complete;
+ struct completion dma_ecc_complete;
+
+ u8 cs_assigned;
+ int cs_sel;
+};
+
+static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base)
+{
+ return container_of(base, struct stm32_fmc2_nfc, base);
+}
+
+/* Timings configuration */
+static void stm32_fmc2_timings_init(struct nand_chip *chip)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+ struct stm32_fmc2_timings *timings = &nand->timings;
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+ u32 pmem, patt;
+
+ /* Set tclr/tar timings */
+ pcr &= ~FMC2_PCR_TCLR_MASK;
+ pcr |= FMC2_PCR_TCLR(timings->tclr);
+ pcr &= ~FMC2_PCR_TAR_MASK;
+ pcr |= FMC2_PCR_TAR(timings->tar);
+
+ /* Set tset/twait/thold/thiz timings in common bank */
+ pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
+ pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
+ pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
+ pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+
+ /* Set tset/twait/thold/thiz timings in attribut bank */
+ patt = FMC2_PATT_ATTSET(timings->tset_att);
+ patt |= FMC2_PATT_ATTWAIT(timings->twait);
+ patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
+ patt |= FMC2_PATT_ATTHIZ(timings->thiz);
+
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+ writel_relaxed(pmem, fmc2->io_base + FMC2_PMEM);
+ writel_relaxed(patt, fmc2->io_base + FMC2_PATT);
+}
+
+/* Controller configuration */
+static void stm32_fmc2_setup(struct nand_chip *chip)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+
+ /* Configure ECC algorithm (default configuration is Hamming) */
+ pcr &= ~FMC2_PCR_ECCALG;
+ pcr &= ~FMC2_PCR_BCHECC;
+ if (chip->ecc.strength == FMC2_ECC_BCH8) {
+ pcr |= FMC2_PCR_ECCALG;
+ pcr |= FMC2_PCR_BCHECC;
+ } else if (chip->ecc.strength == FMC2_ECC_BCH4) {
+ pcr |= FMC2_PCR_ECCALG;
+ }
+
+ /* Set buswidth */
+ pcr &= ~FMC2_PCR_PWID_MASK;
+ if (chip->options & NAND_BUSWIDTH_16)
+ pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+
+ /* Set ECC sector size */
+ pcr &= ~FMC2_PCR_ECCSS_MASK;
+ pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Select target */
+static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+ struct dma_slave_config dma_cfg;
+ int ret;
+
+ if (nand->cs_used[chipnr] == fmc2->cs_sel)
+ return 0;
+
+ fmc2->cs_sel = nand->cs_used[chipnr];
+
+ /* FMC2 setup routine */
+ stm32_fmc2_setup(chip);
+
+ /* Apply timings */
+ stm32_fmc2_timings_init(chip);
+
+ if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) {
+ memset(&dma_cfg, 0, sizeof(dma_cfg));
+ dma_cfg.src_addr = fmc2->data_phys_addr[fmc2->cs_sel];
+ dma_cfg.dst_addr = fmc2->data_phys_addr[fmc2->cs_sel];
+ dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_cfg.src_maxburst = 32;
+ dma_cfg.dst_maxburst = 32;
+
+ ret = dmaengine_slave_config(fmc2->dma_tx_ch, &dma_cfg);
+ if (ret) {
+ dev_err(fmc2->dev, "tx DMA engine slave config failed\n");
+ return ret;
+ }
+
+ ret = dmaengine_slave_config(fmc2->dma_rx_ch, &dma_cfg);
+ if (ret) {
+ dev_err(fmc2->dev, "rx DMA engine slave config failed\n");
+ return ret;
+ }
+ }
+
+ if (fmc2->dma_ecc_ch) {
+ /*
+ * Hamming: we read HECCR register
+ * BCH4/BCH8: we read BCHDSRSx registers
+ */
+ memset(&dma_cfg, 0, sizeof(dma_cfg));
+ dma_cfg.src_addr = fmc2->io_phys_addr;
+ dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ?
+ FMC2_HECCR : FMC2_BCHDSR0;
+ dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+ ret = dmaengine_slave_config(fmc2->dma_ecc_ch, &dma_cfg);
+ if (ret) {
+ dev_err(fmc2->dev, "ECC DMA engine slave config failed\n");
+ return ret;
+ }
+
+ /* Calculate ECC length needed for one sector */
+ fmc2->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ?
+ FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN;
+ }
+
+ return 0;
+}
+
+/* Set bus width to 16-bit or 8-bit */
+static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+{
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+
+ pcr &= ~FMC2_PCR_PWID_MASK;
+ if (set)
+ pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Enable/disable ECC */
+static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+{
+ u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+
+ pcr &= ~FMC2_PCR_ECCEN;
+ if (enable)
+ pcr |= FMC2_PCR_ECCEN;
+ writel(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Enable irq sources in case of the sequencer is used */
+static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2)
+{
+ u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
+
+ csqier |= FMC2_CSQIER_TCIE;
+
+ fmc2->irq_state = FMC2_IRQ_SEQ;
+
+ writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
+}
+
+/* Disable irq sources in case of the sequencer is used */
+static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2)
+{
+ u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
+
+ csqier &= ~FMC2_CSQIER_TCIE;
+
+ writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
+
+ fmc2->irq_state = FMC2_IRQ_UNKNOWN;
+}
+
+/* Clear irq sources in case of the sequencer is used */
+static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2)
+{
+ writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR);
+}
+
+/* Enable irq sources in case of bch is used */
+static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2,
+ int mode)
+{
+ u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
+
+ if (mode == NAND_ECC_WRITE)
+ bchier |= FMC2_BCHIER_EPBRIE;
+ else
+ bchier |= FMC2_BCHIER_DERIE;
+
+ fmc2->irq_state = FMC2_IRQ_BCH;
+
+ writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
+}
+
+/* Disable irq sources in case of bch is used */
+static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2)
+{
+ u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
+
+ bchier &= ~FMC2_BCHIER_DERIE;
+ bchier &= ~FMC2_BCHIER_EPBRIE;
+
+ writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
+
+ fmc2->irq_state = FMC2_IRQ_UNKNOWN;
+}
+
+/* Clear irq sources in case of bch is used */
+static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+{
+ writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+}
+
+/*
+ * Enable ECC logic and reset syndrome/parity bits previously calculated
+ * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
+ */
+static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+
+ stm32_fmc2_set_ecc(fmc2, false);
+
+ if (chip->ecc.strength != FMC2_ECC_HAM) {
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+
+ if (mode == NAND_ECC_WRITE)
+ pcr |= FMC2_PCR_WEN;
+ else
+ pcr &= ~FMC2_PCR_WEN;
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+
+ reinit_completion(&fmc2->complete);
+ stm32_fmc2_clear_bch_irq(fmc2);
+ stm32_fmc2_enable_bch_irq(fmc2, mode);
+ }
+
+ stm32_fmc2_set_ecc(fmc2, true);
+}
+
+/*
+ * ECC Hamming calculation
+ * ECC is 3 bytes for 512 bytes of data (supports error correction up to
+ * max of 1-bit)
+ */
+static inline void stm32_fmc2_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
+{
+ ecc[0] = ecc_sta;
+ ecc[1] = ecc_sta >> 8;
+ ecc[2] = ecc_sta >> 16;
+}
+
+static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
+ u8 *ecc)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ u32 sr, heccr;
+ int ret;
+
+ ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
+ sr, sr & FMC2_SR_NWRF, 10, 1000);
+ if (ret) {
+ dev_err(fmc2->dev, "ham timeout\n");
+ return ret;
+ }
+
+ heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR);
+
+ stm32_fmc2_ham_set_ecc(heccr, ecc);
+
+ /* Disable ECC */
+ stm32_fmc2_set_ecc(fmc2, false);
+
+ return 0;
+}
+
+static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
+{
+ u8 bit_position = 0, b0, b1, b2;
+ u32 byte_addr = 0, b;
+ u32 i, shifting = 1;
+
+ /* Indicate which bit and byte is faulty (if any) */
+ b0 = read_ecc[0] ^ calc_ecc[0];
+ b1 = read_ecc[1] ^ calc_ecc[1];
+ b2 = read_ecc[2] ^ calc_ecc[2];
+ b = b0 | (b1 << 8) | (b2 << 16);
+
+ /* No errors */
+ if (likely(!b))
+ return 0;
+
+ /* Calculate bit position */
+ for (i = 0; i < 3; i++) {
+ switch (b % 4) {
+ case 2:
+ bit_position += shifting;
+ case 1:
+ break;
+ default:
+ return -EBADMSG;
+ }
+ shifting <<= 1;
+ b >>= 2;
+ }
+
+ /* Calculate byte position */
+ shifting = 1;
+ for (i = 0; i < 9; i++) {
+ switch (b % 4) {
+ case 2:
+ byte_addr += shifting;
+ case 1:
+ break;
+ default:
+ return -EBADMSG;
+ }
+ shifting <<= 1;
+ b >>= 2;
+ }
+
+ /* Flip the bit */
+ dat[byte_addr] ^= (1 << bit_position);
+
+ return 1;
+}
+
+/*
+ * ECC BCH calculation and correction
+ * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to
+ * max of 4-bit/8-bit)
+ */
+static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
+ u8 *ecc)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ u32 bchpbr;
+
+ /* Wait until the BCH code is ready */
+ if (!wait_for_completion_timeout(&fmc2->complete,
+ msecs_to_jiffies(1000))) {
+ dev_err(fmc2->dev, "bch timeout\n");
+ stm32_fmc2_disable_bch_irq(fmc2);
+ return -ETIMEDOUT;
+ }
+
+ /* Read parity bits */
+ bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR1);
+ ecc[0] = bchpbr;
+ ecc[1] = bchpbr >> 8;
+ ecc[2] = bchpbr >> 16;
+ ecc[3] = bchpbr >> 24;
+
+ bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR2);
+ ecc[4] = bchpbr;
+ ecc[5] = bchpbr >> 8;
+ ecc[6] = bchpbr >> 16;
+
+ if (chip->ecc.strength == FMC2_ECC_BCH8) {
+ ecc[7] = bchpbr >> 24;
+
+ bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR3);
+ ecc[8] = bchpbr;
+ ecc[9] = bchpbr >> 8;
+ ecc[10] = bchpbr >> 16;
+ ecc[11] = bchpbr >> 24;
+
+ bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR4);
+ ecc[12] = bchpbr;
+ }
+
+ /* Disable ECC */
+ stm32_fmc2_set_ecc(fmc2, false);
+
+ return 0;
+}
+
+/* BCH algorithm correction */
+static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
+{
+ u32 bchdsr0 = ecc_sta[0];
+ u32 bchdsr1 = ecc_sta[1];
+ u32 bchdsr2 = ecc_sta[2];
+ u32 bchdsr3 = ecc_sta[3];
+ u32 bchdsr4 = ecc_sta[4];
+ u16 pos[8];
+ int i, den;
+ unsigned int nb_errs = 0;
+
+ /* No errors found */
+ if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
+ return 0;
+
+ /* Too many errors detected */
+ if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
+ return -EBADMSG;
+
+ pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
+ pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
+ pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
+ pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
+ pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
+ pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
+ pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
+ pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+
+ den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+ for (i = 0; i < den; i++) {
+ if (pos[i] < eccsize * 8) {
+ change_bit(pos[i], (unsigned long *)dat);
+ nb_errs++;
+ }
+ }
+
+ return nb_errs;
+}
+
+static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ u32 ecc_sta[5];
+
+ /* Wait until the decoding error is ready */
+ if (!wait_for_completion_timeout(&fmc2->complete,
+ msecs_to_jiffies(1000))) {
+ dev_err(fmc2->dev, "bch timeout\n");
+ stm32_fmc2_disable_bch_irq(fmc2);
+ return -ETIMEDOUT;
+ }
+
+ ecc_sta[0] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR0);
+ ecc_sta[1] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR1);
+ ecc_sta[2] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR2);
+ ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3);
+ ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4);
+
+ /* Disable ECC */
+ stm32_fmc2_set_ecc(fmc2, false);
+
+ return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta);
+}
+
+static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf,
+ int oob_required, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret, i, s, stat, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ int eccstrength = chip->ecc.strength;
+ u8 *p = buf;
+ u8 *ecc_calc = chip->ecc.calc_buf;
+ u8 *ecc_code = chip->ecc.code_buf;
+ unsigned int max_bitflips = 0;
+
+ ret = nand_read_page_op(chip, page, 0, NULL, 0);
+ if (ret)
+ return ret;
+
+ for (i = mtd->writesize + FMC2_BBM_LEN, s = 0; s < eccsteps;
+ s++, i += eccbytes, p += eccsize) {
+ chip->ecc.hwctl(chip, NAND_ECC_READ);
+
+ /* Read the nand page sector (512 bytes) */
+ ret = nand_change_read_column_op(chip, s * eccsize, p,
+ eccsize, false);
+ if (ret)
+ return ret;
+
+ /* Read the corresponding ECC bytes */
+ ret = nand_change_read_column_op(chip, i, ecc_code,
+ eccbytes, false);
+ if (ret)
+ return ret;
+
+ /* Correct the data */
+ stat = chip->ecc.correct(chip, p, ecc_code, ecc_calc);
+ if (stat == -EBADMSG)
+ /* Check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(p, eccsize,
+ ecc_code, eccbytes,
+ NULL, 0,
+ eccstrength);
+
+ if (stat < 0) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
+ }
+
+ /* Read oob */
+ if (oob_required) {
+ ret = nand_change_read_column_op(chip, mtd->writesize,
+ chip->oob_poi, mtd->oobsize,
+ false);
+ if (ret)
+ return ret;
+ }
+
+ return max_bitflips;
+}
+
+/* Sequencer read/write configuration */
+static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page,
+ int raw, bool write_data)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ u32 csqcfgr1, csqcfgr2, csqcfgr3;
+ u32 csqar1, csqar2;
+ u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+
+ if (write_data)
+ pcr |= FMC2_PCR_WEN;
+ else
+ pcr &= ~FMC2_PCR_WEN;
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+
+ /*
+ * - Set Program Page/Page Read command
+ * - Enable DMA request data
+ * - Set timings
+ */
+ csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T;
+ if (write_data)
+ csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_SEQIN);
+ else
+ csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_READ0) |
+ FMC2_CSQCFGR1_CMD2EN |
+ FMC2_CSQCFGR1_CMD2(NAND_CMD_READSTART) |
+ FMC2_CSQCFGR1_CMD2T;
+
+ /*
+ * - Set Random Data Input/Random Data Read command
+ * - Enable the sequencer to access the Spare data area
+ * - Enable DMA request status decoding for read
+ * - Set timings
+ */
+ if (write_data)
+ csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDIN);
+ else
+ csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDOUT) |
+ FMC2_CSQCFGR2_RCMD2EN |
+ FMC2_CSQCFGR2_RCMD2(NAND_CMD_RNDOUTSTART) |
+ FMC2_CSQCFGR2_RCMD1T |
+ FMC2_CSQCFGR2_RCMD2T;
+ if (!raw) {
+ csqcfgr2 |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN;
+ csqcfgr2 |= FMC2_CSQCFGR2_SQSDTEN;
+ }
+
+ /*
+ * - Set the number of sectors to be written
+ * - Set timings
+ */
+ csqcfgr3 = FMC2_CSQCFGR3_SNBR(chip->ecc.steps - 1);
+ if (write_data) {
+ csqcfgr3 |= FMC2_CSQCFGR3_RAC2T;
+ if (chip->options & NAND_ROW_ADDR_3)
+ csqcfgr3 |= FMC2_CSQCFGR3_AC5T;
+ else
+ csqcfgr3 |= FMC2_CSQCFGR3_AC4T;
+ }
+
+ /*
+ * Set the fourth first address cycles
+ * Byte 1 and byte 2 => column, we start at 0x0
+ * Byte 3 and byte 4 => page
+ */
+ csqar1 = FMC2_CSQCAR1_ADDC3(page);
+ csqar1 |= FMC2_CSQCAR1_ADDC4(page >> 8);
+
+ /*
+ * - Set chip enable number
+ * - Set ECC byte offset in the spare area
+ * - Calculate the number of address cycles to be issued
+ * - Set byte 5 of address cycle if needed
+ */
+ csqar2 = FMC2_CSQCAR2_NANDCEN(fmc2->cs_sel);
+ if (chip->options & NAND_BUSWIDTH_16)
+ csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1);
+ else
+ csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset);
+ if (chip->options & NAND_ROW_ADDR_3) {
+ csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(5);
+ csqar2 |= FMC2_CSQCAR2_ADDC5(page >> 16);
+ } else {
+ csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4);
+ }
+
+ writel_relaxed(csqcfgr1, fmc2->io_base + FMC2_CSQCFGR1);
+ writel_relaxed(csqcfgr2, fmc2->io_base + FMC2_CSQCFGR2);
+ writel_relaxed(csqcfgr3, fmc2->io_base + FMC2_CSQCFGR3);
+ writel_relaxed(csqar1, fmc2->io_base + FMC2_CSQAR1);
+ writel_relaxed(csqar2, fmc2->io_base + FMC2_CSQAR2);
+}
+
+static void stm32_fmc2_dma_callback(void *arg)
+{
+ complete((struct completion *)arg);
+}
+
+/* Read/write data from/to a page */
+static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
+ int raw, bool write_data)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct dma_async_tx_descriptor *desc_data, *desc_ecc;
+ struct scatterlist *sg;
+ struct dma_chan *dma_ch = fmc2->dma_rx_ch;
+ enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE;
+ enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM;
+ u32 csqcr = readl_relaxed(fmc2->io_base + FMC2_CSQCR);
+ int eccsteps = chip->ecc.steps;
+ int eccsize = chip->ecc.size;
+ const u8 *p = buf;
+ int s, ret;
+
+ /* Configure DMA data */
+ if (write_data) {
+ dma_data_dir = DMA_TO_DEVICE;
+ dma_transfer_dir = DMA_MEM_TO_DEV;
+ dma_ch = fmc2->dma_tx_ch;
+ }
+
+ for_each_sg(fmc2->dma_data_sg.sgl, sg, eccsteps, s) {
+ sg_set_buf(sg, p, eccsize);
+ p += eccsize;
+ }
+
+ ret = dma_map_sg(fmc2->dev, fmc2->dma_data_sg.sgl,
+ eccsteps, dma_data_dir);
+ if (ret < 0)
+ return ret;
+
+ desc_data = dmaengine_prep_slave_sg(dma_ch, fmc2->dma_data_sg.sgl,
+ eccsteps, dma_transfer_dir,
+ DMA_PREP_INTERRUPT);
+ if (!desc_data) {
+ ret = -ENOMEM;
+ goto err_unmap_data;
+ }
+
+ reinit_completion(&fmc2->dma_data_complete);
+ reinit_completion(&fmc2->complete);
+ desc_data->callback = stm32_fmc2_dma_callback;
+ desc_data->callback_param = &fmc2->dma_data_complete;
+ ret = dma_submit_error(dmaengine_submit(desc_data));
+ if (ret)
+ goto err_unmap_data;
+
+ dma_async_issue_pending(dma_ch);
+
+ if (!write_data && !raw) {
+ /* Configure DMA ECC status */
+ p = fmc2->ecc_buf;
+ for_each_sg(fmc2->dma_ecc_sg.sgl, sg, eccsteps, s) {
+ sg_set_buf(sg, p, fmc2->dma_ecc_len);
+ p += fmc2->dma_ecc_len;
+ }
+
+ ret = dma_map_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
+ eccsteps, dma_data_dir);
+ if (ret < 0)
+ goto err_unmap_data;
+
+ desc_ecc = dmaengine_prep_slave_sg(fmc2->dma_ecc_ch,
+ fmc2->dma_ecc_sg.sgl,
+ eccsteps, dma_transfer_dir,
+ DMA_PREP_INTERRUPT);
+ if (!desc_ecc) {
+ ret = -ENOMEM;
+ goto err_unmap_ecc;
+ }
+
+ reinit_completion(&fmc2->dma_ecc_complete);
+ desc_ecc->callback = stm32_fmc2_dma_callback;
+ desc_ecc->callback_param = &fmc2->dma_ecc_complete;
+ ret = dma_submit_error(dmaengine_submit(desc_ecc));
+ if (ret)
+ goto err_unmap_ecc;
+
+ dma_async_issue_pending(fmc2->dma_ecc_ch);
+ }
+
+ stm32_fmc2_clear_seq_irq(fmc2);
+ stm32_fmc2_enable_seq_irq(fmc2);
+
+ /* Start the transfer */
+ csqcr |= FMC2_CSQCR_CSQSTART;
+ writel_relaxed(csqcr, fmc2->io_base + FMC2_CSQCR);
+
+ /* Wait end of sequencer transfer */
+ if (!wait_for_completion_timeout(&fmc2->complete,
+ msecs_to_jiffies(1000))) {
+ dev_err(fmc2->dev, "seq timeout\n");
+ stm32_fmc2_disable_seq_irq(fmc2);
+ dmaengine_terminate_all(dma_ch);
+ if (!write_data && !raw)
+ dmaengine_terminate_all(fmc2->dma_ecc_ch);
+ ret = -ETIMEDOUT;
+ goto err_unmap_ecc;
+ }
+
+ /* Wait DMA data transfer completion */
+ if (!wait_for_completion_timeout(&fmc2->dma_data_complete,
+ msecs_to_jiffies(100))) {
+ dev_err(fmc2->dev, "data DMA timeout\n");
+ dmaengine_terminate_all(dma_ch);
+ ret = -ETIMEDOUT;
+ }
+
+ /* Wait DMA ECC transfer completion */
+ if (!write_data && !raw) {
+ if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete,
+ msecs_to_jiffies(100))) {
+ dev_err(fmc2->dev, "ECC DMA timeout\n");
+ dmaengine_terminate_all(fmc2->dma_ecc_ch);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+err_unmap_ecc:
+ if (!write_data && !raw)
+ dma_unmap_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
+ eccsteps, dma_data_dir);
+
+err_unmap_data:
+ dma_unmap_sg(fmc2->dev, fmc2->dma_data_sg.sgl, eccsteps, dma_data_dir);
+
+ return ret;
+}
+
+static int stm32_fmc2_sequencer_write(struct nand_chip *chip,
+ const u8 *buf, int oob_required,
+ int page, int raw)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret;
+
+ /* Configure the sequencer */
+ stm32_fmc2_rw_page_init(chip, page, raw, true);
+
+ /* Write the page */
+ ret = stm32_fmc2_xfer(chip, buf, raw, true);
+ if (ret)
+ return ret;
+
+ /* Write oob */
+ if (oob_required) {
+ ret = nand_change_write_column_op(chip, mtd->writesize,
+ chip->oob_poi, mtd->oobsize,
+ false);
+ if (ret)
+ return ret;
+ }
+
+ return nand_prog_page_end_op(chip);
+}
+
+static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip,
+ const u8 *buf,
+ int oob_required,
+ int page)
+{
+ int ret;
+
+ /* Select the target */
+ ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+ if (ret)
+ return ret;
+
+ return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, false);
+}
+
+static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip,
+ const u8 *buf,
+ int oob_required,
+ int page)
+{
+ int ret;
+
+ /* Select the target */
+ ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+ if (ret)
+ return ret;
+
+ return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, true);
+}
+
+/* Get a status indicating which sectors have errors */
+static inline u16 stm32_fmc2_get_mapping_status(struct stm32_fmc2_nfc *fmc2)
+{
+ u32 csqemsr = readl_relaxed(fmc2->io_base + FMC2_CSQEMSR);
+
+ return csqemsr & FMC2_CSQEMSR_SEM;
+}
+
+static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ int eccstrength = chip->ecc.strength;
+ int i, s, eccsize = chip->ecc.size;
+ u32 *ecc_sta = (u32 *)fmc2->ecc_buf;
+ u16 sta_map = stm32_fmc2_get_mapping_status(fmc2);
+ unsigned int max_bitflips = 0;
+
+ for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, dat += eccsize) {
+ int stat = 0;
+
+ if (eccstrength == FMC2_ECC_HAM) {
+ /* Ecc_sta = FMC2_HECCR */
+ if (sta_map & BIT(s)) {
+ stm32_fmc2_ham_set_ecc(*ecc_sta, &calc_ecc[i]);
+ stat = stm32_fmc2_ham_correct(chip, dat,
+ &read_ecc[i],
+ &calc_ecc[i]);
+ }
+ ecc_sta++;
+ } else {
+ /*
+ * Ecc_sta[0] = FMC2_BCHDSR0
+ * Ecc_sta[1] = FMC2_BCHDSR1
+ * Ecc_sta[2] = FMC2_BCHDSR2
+ * Ecc_sta[3] = FMC2_BCHDSR3
+ * Ecc_sta[4] = FMC2_BCHDSR4
+ */
+ if (sta_map & BIT(s))
+ stat = stm32_fmc2_bch_decode(eccsize, dat,
+ ecc_sta);
+ ecc_sta += 5;
+ }
+
+ if (stat == -EBADMSG)
+ /* Check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(dat, eccsize,
+ &read_ecc[i],
+ eccbytes,
+ NULL, 0,
+ eccstrength);
+
+ if (stat < 0) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
+ }
+
+ return max_bitflips;
+}
+
+static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf,
+ int oob_required, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ u8 *ecc_calc = chip->ecc.calc_buf;
+ u8 *ecc_code = chip->ecc.code_buf;
+ u16 sta_map;
+ int ret;
+
+ /* Select the target */
+ ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+ if (ret)
+ return ret;
+
+ /* Configure the sequencer */
+ stm32_fmc2_rw_page_init(chip, page, 0, false);
+
+ /* Read the page */
+ ret = stm32_fmc2_xfer(chip, buf, 0, false);
+ if (ret)
+ return ret;
+
+ sta_map = stm32_fmc2_get_mapping_status(fmc2);
+
+ /* Check if errors happen */
+ if (likely(!sta_map)) {
+ if (oob_required)
+ return nand_change_read_column_op(chip, mtd->writesize,
+ chip->oob_poi,
+ mtd->oobsize, false);
+
+ return 0;
+ }
+
+ /* Read oob */
+ ret = nand_change_read_column_op(chip, mtd->writesize,
+ chip->oob_poi, mtd->oobsize, false);
+ if (ret)
+ return ret;
+
+ ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
+ chip->ecc.total);
+ if (ret)
+ return ret;
+
+ /* Correct data */
+ return chip->ecc.correct(chip, buf, ecc_code, ecc_calc);
+}
+
+static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf,
+ int oob_required, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret;
+
+ /* Select the target */
+ ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+ if (ret)
+ return ret;
+
+ /* Configure the sequencer */
+ stm32_fmc2_rw_page_init(chip, page, 1, false);
+
+ /* Read the page */
+ ret = stm32_fmc2_xfer(chip, buf, 1, false);
+ if (ret)
+ return ret;
+
+ /* Read oob */
+ if (oob_required)
+ return nand_change_read_column_op(chip, mtd->writesize,
+ chip->oob_poi, mtd->oobsize,
+ false);
+
+ return 0;
+}
+
+static irqreturn_t stm32_fmc2_irq(int irq, void *dev_id)
+{
+ struct stm32_fmc2_nfc *fmc2 = (struct stm32_fmc2_nfc *)dev_id;
+
+ if (fmc2->irq_state == FMC2_IRQ_SEQ)
+ /* Sequencer is used */
+ stm32_fmc2_disable_seq_irq(fmc2);
+ else if (fmc2->irq_state == FMC2_IRQ_BCH)
+ /* BCH is used */
+ stm32_fmc2_disable_bch_irq(fmc2);
+
+ complete(&fmc2->complete);
+
+ return IRQ_HANDLED;
+}
+
+static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf,
+ unsigned int len, bool force_8bit)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ void __iomem *io_addr_r = fmc2->data_base[fmc2->cs_sel];
+
+ if (force_8bit && chip->options & NAND_BUSWIDTH_16)
+ /* Reconfigure bus width to 8-bit */
+ stm32_fmc2_set_buswidth_16(fmc2, false);
+
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
+ *(u8 *)buf = readb_relaxed(io_addr_r);
+ buf += sizeof(u8);
+ len -= sizeof(u8);
+ }
+
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) &&
+ len >= sizeof(u16)) {
+ *(u16 *)buf = readw_relaxed(io_addr_r);
+ buf += sizeof(u16);
+ len -= sizeof(u16);
+ }
+ }
+
+ /* Buf is aligned */
+ while (len >= sizeof(u32)) {
+ *(u32 *)buf = readl_relaxed(io_addr_r);
+ buf += sizeof(u32);
+ len -= sizeof(u32);
+ }
+
+ /* Read remaining bytes */
+ if (len >= sizeof(u16)) {
+ *(u16 *)buf = readw_relaxed(io_addr_r);
+ buf += sizeof(u16);
+ len -= sizeof(u16);
+ }
+
+ if (len)
+ *(u8 *)buf = readb_relaxed(io_addr_r);
+
+ if (force_8bit && chip->options & NAND_BUSWIDTH_16)
+ /* Reconfigure bus width to 16-bit */
+ stm32_fmc2_set_buswidth_16(fmc2, true);
+}
+
+static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
+ unsigned int len, bool force_8bit)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ void __iomem *io_addr_w = fmc2->data_base[fmc2->cs_sel];
+
+ if (force_8bit && chip->options & NAND_BUSWIDTH_16)
+ /* Reconfigure bus width to 8-bit */
+ stm32_fmc2_set_buswidth_16(fmc2, false);
+
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
+ writeb_relaxed(*(u8 *)buf, io_addr_w);
+ buf += sizeof(u8);
+ len -= sizeof(u8);
+ }
+
+ if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) &&
+ len >= sizeof(u16)) {
+ writew_relaxed(*(u16 *)buf, io_addr_w);
+ buf += sizeof(u16);
+ len -= sizeof(u16);
+ }
+ }
+
+ /* Buf is aligned */
+ while (len >= sizeof(u32)) {
+ writel_relaxed(*(u32 *)buf, io_addr_w);
+ buf += sizeof(u32);
+ len -= sizeof(u32);
+ }
+
+ /* Write remaining bytes */
+ if (len >= sizeof(u16)) {
+ writew_relaxed(*(u16 *)buf, io_addr_w);
+ buf += sizeof(u16);
+ len -= sizeof(u16);
+ }
+
+ if (len)
+ writeb_relaxed(*(u8 *)buf, io_addr_w);
+
+ if (force_8bit && chip->options & NAND_BUSWIDTH_16)
+ /* Reconfigure bus width to 16-bit */
+ stm32_fmc2_set_buswidth_16(fmc2, true);
+}
+
+static int stm32_fmc2_exec_op(struct nand_chip *chip,
+ const struct nand_operation *op,
+ bool check_only)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ const struct nand_op_instr *instr = NULL;
+ unsigned int op_id, i;
+ int ret;
+
+ ret = stm32_fmc2_select_chip(chip, op->cs);
+ if (ret)
+ return ret;
+
+ if (check_only)
+ return ret;
+
+ for (op_id = 0; op_id < op->ninstrs; op_id++) {
+ instr = &op->instrs[op_id];
+
+ switch (instr->type) {
+ case NAND_OP_CMD_INSTR:
+ writeb_relaxed(instr->ctx.cmd.opcode,
+ fmc2->cmd_base[fmc2->cs_sel]);
+ break;
+
+ case NAND_OP_ADDR_INSTR:
+ for (i = 0; i < instr->ctx.addr.naddrs; i++)
+ writeb_relaxed(instr->ctx.addr.addrs[i],
+ fmc2->addr_base[fmc2->cs_sel]);
+ break;
+
+ case NAND_OP_DATA_IN_INSTR:
+ stm32_fmc2_read_data(chip, instr->ctx.data.buf.in,
+ instr->ctx.data.len,
+ instr->ctx.data.force_8bit);
+ break;
+
+ case NAND_OP_DATA_OUT_INSTR:
+ stm32_fmc2_write_data(chip, instr->ctx.data.buf.out,
+ instr->ctx.data.len,
+ instr->ctx.data.force_8bit);
+ break;
+
+ case NAND_OP_WAITRDY_INSTR:
+ ret = nand_soft_waitrdy(chip,
+ instr->ctx.waitrdy.timeout_ms);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* Controller initialization */
+static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+{
+ u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+ u32 bcr1 = readl_relaxed(fmc2->io_base + FMC2_BCR1);
+
+ /* Set CS used to undefined */
+ fmc2->cs_sel = -1;
+
+ /* Enable wait feature and nand flash memory bank */
+ pcr |= FMC2_PCR_PWAITEN;
+ pcr |= FMC2_PCR_PBKEN;
+
+ /* Set buswidth to 8 bits mode for identification */
+ pcr &= ~FMC2_PCR_PWID_MASK;
+
+ /* ECC logic is disabled */
+ pcr &= ~FMC2_PCR_ECCEN;
+
+ /* Default mode */
+ pcr &= ~FMC2_PCR_ECCALG;
+ pcr &= ~FMC2_PCR_BCHECC;
+ pcr &= ~FMC2_PCR_WEN;
+
+ /* Set default ECC sector size */
+ pcr &= ~FMC2_PCR_ECCSS_MASK;
+ pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+
+ /* Set default tclr/tar timings */
+ pcr &= ~FMC2_PCR_TCLR_MASK;
+ pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
+ pcr &= ~FMC2_PCR_TAR_MASK;
+ pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+
+ /* Enable FMC2 controller */
+ bcr1 |= FMC2_BCR1_FMC2EN;
+
+ writel_relaxed(bcr1, fmc2->io_base + FMC2_BCR1);
+ writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+ writel_relaxed(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
+ writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+}
+
+/* Controller timings */
+static void stm32_fmc2_calc_timings(struct nand_chip *chip,
+ const struct nand_sdr_timings *sdrt)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+ struct stm32_fmc2_timings *tims = &nand->timings;
+ unsigned long hclk = clk_get_rate(fmc2->clk);
+ unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
+ int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att;
+
+ tar = hclkp;
+ if (tar < sdrt->tAR_min)
+ tar = sdrt->tAR_min;
+ tims->tar = DIV_ROUND_UP(tar, hclkp) - 1;
+ if (tims->tar > FMC2_PCR_TIMING_MASK)
+ tims->tar = FMC2_PCR_TIMING_MASK;
+
+ tclr = hclkp;
+ if (tclr < sdrt->tCLR_min)
+ tclr = sdrt->tCLR_min;
+ tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1;
+ if (tims->tclr > FMC2_PCR_TIMING_MASK)
+ tims->tclr = FMC2_PCR_TIMING_MASK;
+
+ tims->thiz = FMC2_THIZ;
+ thiz = (tims->thiz + 1) * hclkp;
+
+ /*
+ * tWAIT > tRP
+ * tWAIT > tWP
+ * tWAIT > tREA + tIO
+ */
+ twait = hclkp;
+ if (twait < sdrt->tRP_min)
+ twait = sdrt->tRP_min;
+ if (twait < sdrt->tWP_min)
+ twait = sdrt->tWP_min;
+ if (twait < sdrt->tREA_max + FMC2_TIO)
+ twait = sdrt->tREA_max + FMC2_TIO;
+ tims->twait = DIV_ROUND_UP(twait, hclkp);
+ if (tims->twait == 0)
+ tims->twait = 1;
+ else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK)
+ tims->twait = FMC2_PMEM_PATT_TIMING_MASK;
+
+ /*
+ * tSETUP_MEM > tCS - tWAIT
+ * tSETUP_MEM > tALS - tWAIT
+ * tSETUP_MEM > tDS - (tWAIT - tHIZ)
+ */
+ tset_mem = hclkp;
+ if (sdrt->tCS_min > twait && (tset_mem < sdrt->tCS_min - twait))
+ tset_mem = sdrt->tCS_min - twait;
+ if (sdrt->tALS_min > twait && (tset_mem < sdrt->tALS_min - twait))
+ tset_mem = sdrt->tALS_min - twait;
+ if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
+ (tset_mem < sdrt->tDS_min - (twait - thiz)))
+ tset_mem = sdrt->tDS_min - (twait - thiz);
+ tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp);
+ if (tims->tset_mem == 0)
+ tims->tset_mem = 1;
+ else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK)
+ tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK;
+
+ /*
+ * tHOLD_MEM > tCH
+ * tHOLD_MEM > tREH - tSETUP_MEM
+ * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
+ */
+ thold_mem = hclkp;
+ if (thold_mem < sdrt->tCH_min)
+ thold_mem = sdrt->tCH_min;
+ if (sdrt->tREH_min > tset_mem &&
+ (thold_mem < sdrt->tREH_min - tset_mem))
+ thold_mem = sdrt->tREH_min - tset_mem;
+ if ((sdrt->tRC_min > tset_mem + twait) &&
+ (thold_mem < sdrt->tRC_min - (tset_mem + twait)))
+ thold_mem = sdrt->tRC_min - (tset_mem + twait);
+ if ((sdrt->tWC_min > tset_mem + twait) &&
+ (thold_mem < sdrt->tWC_min - (tset_mem + twait)))
+ thold_mem = sdrt->tWC_min - (tset_mem + twait);
+ tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp);
+ if (tims->thold_mem == 0)
+ tims->thold_mem = 1;
+ else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK)
+ tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK;
+
+ /*
+ * tSETUP_ATT > tCS - tWAIT
+ * tSETUP_ATT > tCLS - tWAIT
+ * tSETUP_ATT > tALS - tWAIT
+ * tSETUP_ATT > tRHW - tHOLD_MEM
+ * tSETUP_ATT > tDS - (tWAIT - tHIZ)
+ */
+ tset_att = hclkp;
+ if (sdrt->tCS_min > twait && (tset_att < sdrt->tCS_min - twait))
+ tset_att = sdrt->tCS_min - twait;
+ if (sdrt->tCLS_min > twait && (tset_att < sdrt->tCLS_min - twait))
+ tset_att = sdrt->tCLS_min - twait;
+ if (sdrt->tALS_min > twait && (tset_att < sdrt->tALS_min - twait))
+ tset_att = sdrt->tALS_min - twait;
+ if (sdrt->tRHW_min > thold_mem &&
+ (tset_att < sdrt->tRHW_min - thold_mem))
+ tset_att = sdrt->tRHW_min - thold_mem;
+ if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
+ (tset_att < sdrt->tDS_min - (twait - thiz)))
+ tset_att = sdrt->tDS_min - (twait - thiz);
+ tims->tset_att = DIV_ROUND_UP(tset_att, hclkp);
+ if (tims->tset_att == 0)
+ tims->tset_att = 1;
+ else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK)
+ tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK;
+
+ /*
+ * tHOLD_ATT > tALH
+ * tHOLD_ATT > tCH
+ * tHOLD_ATT > tCLH
+ * tHOLD_ATT > tCOH
+ * tHOLD_ATT > tDH
+ * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM
+ * tHOLD_ATT > tADL - tSETUP_MEM
+ * tHOLD_ATT > tWH - tSETUP_MEM
+ * tHOLD_ATT > tWHR - tSETUP_MEM
+ * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
+ * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
+ */
+ thold_att = hclkp;
+ if (thold_att < sdrt->tALH_min)
+ thold_att = sdrt->tALH_min;
+ if (thold_att < sdrt->tCH_min)
+ thold_att = sdrt->tCH_min;
+ if (thold_att < sdrt->tCLH_min)
+ thold_att = sdrt->tCLH_min;
+ if (thold_att < sdrt->tCOH_min)
+ thold_att = sdrt->tCOH_min;
+ if (thold_att < sdrt->tDH_min)
+ thold_att = sdrt->tDH_min;
+ if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) &&
+ (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem))
+ thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem;
+ if (sdrt->tADL_min > tset_mem &&
+ (thold_att < sdrt->tADL_min - tset_mem))
+ thold_att = sdrt->tADL_min - tset_mem;
+ if (sdrt->tWH_min > tset_mem &&
+ (thold_att < sdrt->tWH_min - tset_mem))
+ thold_att = sdrt->tWH_min - tset_mem;
+ if (sdrt->tWHR_min > tset_mem &&
+ (thold_att < sdrt->tWHR_min - tset_mem))
+ thold_att = sdrt->tWHR_min - tset_mem;
+ if ((sdrt->tRC_min > tset_att + twait) &&
+ (thold_att < sdrt->tRC_min - (tset_att + twait)))
+ thold_att = sdrt->tRC_min - (tset_att + twait);
+ if ((sdrt->tWC_min > tset_att + twait) &&
+ (thold_att < sdrt->tWC_min - (tset_att + twait)))
+ thold_att = sdrt->tWC_min - (tset_att + twait);
+ tims->thold_att = DIV_ROUND_UP(thold_att, hclkp);
+ if (tims->thold_att == 0)
+ tims->thold_att = 1;
+ else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK)
+ tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK;
+}
+
+static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
+ const struct nand_data_interface *conf)
+{
+ const struct nand_sdr_timings *sdrt;
+
+ sdrt = nand_get_sdr_timings(conf);
+ if (IS_ERR(sdrt))
+ return PTR_ERR(sdrt);
+
+ if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
+ return 0;
+
+ stm32_fmc2_calc_timings(chip, sdrt);
+
+ /* Apply timings */
+ stm32_fmc2_timings_init(chip);
+
+ return 0;
+}
+
+/* DMA configuration */
+static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
+{
+ int ret;
+
+ fmc2->dma_tx_ch = dma_request_slave_channel(fmc2->dev, "tx");
+ fmc2->dma_rx_ch = dma_request_slave_channel(fmc2->dev, "rx");
+ fmc2->dma_ecc_ch = dma_request_slave_channel(fmc2->dev, "ecc");
+
+ if (!fmc2->dma_tx_ch || !fmc2->dma_rx_ch || !fmc2->dma_ecc_ch) {
+ dev_warn(fmc2->dev, "DMAs not defined in the device tree, polling mode is used\n");
+ return 0;
+ }
+
+ ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ /* Allocate a buffer to store ECC status registers */
+ fmc2->ecc_buf = devm_kzalloc(fmc2->dev, FMC2_MAX_ECC_BUF_LEN,
+ GFP_KERNEL);
+ if (!fmc2->ecc_buf)
+ return -ENOMEM;
+
+ ret = sg_alloc_table(&fmc2->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ init_completion(&fmc2->dma_data_complete);
+ init_completion(&fmc2->dma_ecc_complete);
+
+ return 0;
+}
+
+/* NAND callbacks setup */
+static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+
+ /*
+ * Specific callbacks to read/write a page depending on
+ * the mode (polling/sequencer) and the algo used (Hamming, BCH).
+ */
+ if (fmc2->dma_tx_ch && fmc2->dma_rx_ch && fmc2->dma_ecc_ch) {
+ /* DMA => use sequencer mode callbacks */
+ chip->ecc.correct = stm32_fmc2_sequencer_correct;
+ chip->ecc.write_page = stm32_fmc2_sequencer_write_page;
+ chip->ecc.read_page = stm32_fmc2_sequencer_read_page;
+ chip->ecc.write_page_raw = stm32_fmc2_sequencer_write_page_raw;
+ chip->ecc.read_page_raw = stm32_fmc2_sequencer_read_page_raw;
+ } else {
+ /* No DMA => use polling mode callbacks */
+ chip->ecc.hwctl = stm32_fmc2_hwctl;
+ if (chip->ecc.strength == FMC2_ECC_HAM) {
+ /* Hamming is used */
+ chip->ecc.calculate = stm32_fmc2_ham_calculate;
+ chip->ecc.correct = stm32_fmc2_ham_correct;
+ chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
+ } else {
+ /* BCH is used */
+ chip->ecc.calculate = stm32_fmc2_bch_calculate;
+ chip->ecc.correct = stm32_fmc2_bch_correct;
+ chip->ecc.read_page = stm32_fmc2_read_page;
+ }
+ }
+
+ /* Specific configurations depending on the algo used */
+ if (chip->ecc.strength == FMC2_ECC_HAM)
+ chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
+ else if (chip->ecc.strength == FMC2_ECC_BCH8)
+ chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
+ else
+ chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
+}
+
+/* FMC2 layout */
+static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->length = ecc->total;
+ oobregion->offset = FMC2_BBM_LEN;
+
+ return 0;
+}
+
+static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->length = mtd->oobsize - ecc->total - FMC2_BBM_LEN;
+ oobregion->offset = ecc->total + FMC2_BBM_LEN;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops stm32_fmc2_nand_ooblayout_ops = {
+ .ecc = stm32_fmc2_nand_ooblayout_ecc,
+ .free = stm32_fmc2_nand_ooblayout_free,
+};
+
+/* FMC2 caps */
+static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+{
+ /* Hamming */
+ if (strength == FMC2_ECC_HAM)
+ return 4;
+
+ /* BCH8 */
+ if (strength == FMC2_ECC_BCH8)
+ return 14;
+
+ /* BCH4 */
+ return 8;
+}
+
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+ FMC2_ECC_STEP_SIZE,
+ FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
+
+/* FMC2 controller ops */
+static int stm32_fmc2_attach_chip(struct nand_chip *chip)
+{
+ struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret;
+
+ /*
+ * Only NAND_ECC_HW mode is actually supported
+ * Hamming => ecc.strength = 1
+ * BCH4 => ecc.strength = 4
+ * BCH8 => ecc.strength = 8
+ * ECC sector size = 512
+ */
+ if (chip->ecc.mode != NAND_ECC_HW) {
+ dev_err(fmc2->dev, "nand_ecc_mode is not well defined in the DT\n");
+ return -EINVAL;
+ }
+
+ ret = nand_ecc_choose_conf(chip, &stm32_fmc2_ecc_caps,
+ mtd->oobsize - FMC2_BBM_LEN);
+ if (ret) {
+ dev_err(fmc2->dev, "no valid ECC settings set\n");
+ return ret;
+ }
+
+ if (mtd->writesize / chip->ecc.size > FMC2_MAX_SG) {
+ dev_err(fmc2->dev, "nand page size is not supported\n");
+ return -EINVAL;
+ }
+
+ if (chip->bbt_options & NAND_BBT_USE_FLASH)
+ chip->bbt_options |= NAND_BBT_NO_OOB;
+
+ /* NAND callbacks setup */
+ stm32_fmc2_nand_callbacks_setup(chip);
+
+ /* Define ECC layout */
+ mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops);
+
+ /* Configure bus width to 16-bit */
+ if (chip->options & NAND_BUSWIDTH_16)
+ stm32_fmc2_set_buswidth_16(fmc2, true);
+
+ return 0;
+}
+
+static const struct nand_controller_ops stm32_fmc2_nand_controller_ops = {
+ .attach_chip = stm32_fmc2_attach_chip,
+ .exec_op = stm32_fmc2_exec_op,
+ .setup_data_interface = stm32_fmc2_setup_interface,
+};
+
+/* FMC2 probe */
+static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
+ struct device_node *dn)
+{
+ struct stm32_fmc2_nand *nand = &fmc2->nand;
+ u32 cs;
+ int ret, i;
+
+ if (!of_get_property(dn, "reg", &nand->ncs))
+ return -EINVAL;
+
+ nand->ncs /= sizeof(u32);
+ if (!nand->ncs) {
+ dev_err(fmc2->dev, "invalid reg property size\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nand->ncs; i++) {
+ ret = of_property_read_u32_index(dn, "reg", i, &cs);
+ if (ret) {
+ dev_err(fmc2->dev, "could not retrieve reg property: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (cs > FMC2_MAX_CE) {
+ dev_err(fmc2->dev, "invalid reg value: %d\n", cs);
+ return -EINVAL;
+ }
+
+ if (fmc2->cs_assigned & BIT(cs)) {
+ dev_err(fmc2->dev, "cs already assigned: %d\n", cs);
+ return -EINVAL;
+ }
+
+ fmc2->cs_assigned |= BIT(cs);
+ nand->cs_used[i] = cs;
+ }
+
+ nand_set_flash_node(&nand->chip, dn);
+
+ return 0;
+}
+
+static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2)
+{
+ struct device_node *dn = fmc2->dev->of_node;
+ struct device_node *child;
+ int nchips = of_get_child_count(dn);
+ int ret = 0;
+
+ if (!nchips) {
+ dev_err(fmc2->dev, "NAND chip not defined\n");
+ return -EINVAL;
+ }
+
+ if (nchips > 1) {
+ dev_err(fmc2->dev, "too many NAND chips defined\n");
+ return -EINVAL;
+ }
+
+ for_each_child_of_node(dn, child) {
+ ret = stm32_fmc2_parse_child(fmc2, child);
+ if (ret < 0) {
+ of_node_put(child);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int stm32_fmc2_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct reset_control *rstc;
+ struct stm32_fmc2_nfc *fmc2;
+ struct stm32_fmc2_nand *nand;
+ struct resource *res;
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ int chip_cs, mem_region, ret, irq;
+
+ fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
+ if (!fmc2)
+ return -ENOMEM;
+
+ fmc2->dev = dev;
+ nand_controller_init(&fmc2->base);
+ fmc2->base.ops = &stm32_fmc2_nand_controller_ops;
+
+ ret = stm32_fmc2_parse_dt(fmc2);
+ if (ret)
+ return ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ fmc2->io_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc2->io_base))
+ return PTR_ERR(fmc2->io_base);
+
+ fmc2->io_phys_addr = res->start;
+
+ for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+ chip_cs++, mem_region += 3) {
+ if (!(fmc2->cs_assigned & BIT(chip_cs)))
+ continue;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region);
+ fmc2->data_base[chip_cs] = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc2->data_base[chip_cs]))
+ return PTR_ERR(fmc2->data_base[chip_cs]);
+
+ fmc2->data_phys_addr[chip_cs] = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM,
+ mem_region + 1);
+ fmc2->cmd_base[chip_cs] = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc2->cmd_base[chip_cs]))
+ return PTR_ERR(fmc2->cmd_base[chip_cs]);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM,
+ mem_region + 2);
+ fmc2->addr_base[chip_cs] = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc2->addr_base[chip_cs]))
+ return PTR_ERR(fmc2->addr_base[chip_cs]);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
+ dev_name(dev), fmc2);
+ if (ret) {
+ dev_err(dev, "failed to request irq\n");
+ return ret;
+ }
+
+ init_completion(&fmc2->complete);
+
+ fmc2->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(fmc2->clk))
+ return PTR_ERR(fmc2->clk);
+
+ ret = clk_prepare_enable(fmc2->clk);
+ if (ret) {
+ dev_err(dev, "can not enable the clock\n");
+ return ret;
+ }
+
+ rstc = devm_reset_control_get(dev, NULL);
+ if (!IS_ERR(rstc)) {
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+ }
+
+ /* DMA setup */
+ ret = stm32_fmc2_dma_setup(fmc2);
+ if (ret)
+ return ret;
+
+ /* FMC2 init routine */
+ stm32_fmc2_init(fmc2);
+
+ nand = &fmc2->nand;
+ chip = &nand->chip;
+ mtd = nand_to_mtd(chip);
+ mtd->dev.parent = dev;
+
+ chip->controller = &fmc2->base;
+ chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
+ NAND_USE_BOUNCE_BUFFER;
+
+ /* Default ECC settings */
+ chip->ecc.mode = NAND_ECC_HW;
+ chip->ecc.size = FMC2_ECC_STEP_SIZE;
+ chip->ecc.strength = FMC2_ECC_BCH8;
+
+ /* Scan to find existence of the device */
+ ret = nand_scan(chip, nand->ncs);
+ if (ret)
+ goto err_scan;
+
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret)
+ goto err_device_register;
+
+ platform_set_drvdata(pdev, fmc2);
+
+ return 0;
+
+err_device_register:
+ nand_cleanup(chip);
+
+err_scan:
+ if (fmc2->dma_ecc_ch)
+ dma_release_channel(fmc2->dma_ecc_ch);
+ if (fmc2->dma_tx_ch)
+ dma_release_channel(fmc2->dma_tx_ch);
+ if (fmc2->dma_rx_ch)
+ dma_release_channel(fmc2->dma_rx_ch);
+
+ sg_free_table(&fmc2->dma_data_sg);
+ sg_free_table(&fmc2->dma_ecc_sg);
+
+ clk_disable_unprepare(fmc2->clk);
+
+ return ret;
+}
+
+static int stm32_fmc2_remove(struct platform_device *pdev)
+{
+ struct stm32_fmc2_nfc *fmc2 = platform_get_drvdata(pdev);
+ struct stm32_fmc2_nand *nand = &fmc2->nand;
+
+ nand_release(&nand->chip);
+
+ if (fmc2->dma_ecc_ch)
+ dma_release_channel(fmc2->dma_ecc_ch);
+ if (fmc2->dma_tx_ch)
+ dma_release_channel(fmc2->dma_tx_ch);
+ if (fmc2->dma_rx_ch)
+ dma_release_channel(fmc2->dma_rx_ch);
+
+ sg_free_table(&fmc2->dma_data_sg);
+ sg_free_table(&fmc2->dma_ecc_sg);
+
+ clk_disable_unprepare(fmc2->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_fmc2_suspend(struct device *dev)
+{
+ struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(fmc2->clk);
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_fmc2_resume(struct device *dev)
+{
+ struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
+ struct stm32_fmc2_nand *nand = &fmc2->nand;
+ int chip_cs, ret;
+
+ pinctrl_pm_select_default_state(dev);
+
+ ret = clk_prepare_enable(fmc2->clk);
+ if (ret) {
+ dev_err(dev, "can not enable the clock\n");
+ return ret;
+ }
+
+ stm32_fmc2_init(fmc2);
+
+ for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
+ if (!(fmc2->cs_assigned & BIT(chip_cs)))
+ continue;
+
+ nand_reset(&nand->chip, chip_cs);
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend,
+ stm32_fmc2_resume);
+
+static const struct of_device_id stm32_fmc2_match[] = {
+ {.compatible = "st,stm32mp15-fmc2"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, stm32_fmc2_match);
+
+static struct platform_driver stm32_fmc2_driver = {
+ .probe = stm32_fmc2_probe,
+ .remove = stm32_fmc2_remove,
+ .driver = {
+ .name = "stm32_fmc2_nand",
+ .of_match_table = stm32_fmc2_match,
+ .pm = &stm32_fmc2_pm_ops,
+ },
+};
+module_platform_driver(stm32_fmc2_driver);
+
+MODULE_ALIAS("platform:stm32_fmc2_nand");
+MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index e828ee50a201..4282bc477761 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
*
@@ -10,16 +11,6 @@
*
* Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
* Copyright (C) 2013 Sergey Lapin <slapin@ossfans.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/dma-mapping.h>
@@ -163,38 +154,36 @@
#define NFC_MAX_CS 7
-/*
- * Chip Select structure: stores information related to NAND Chip Select
+/**
+ * struct sunxi_nand_chip_sel - stores information related to NAND Chip Select
*
- * @cs: the NAND CS id used to communicate with a NAND Chip
- * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the
- * NFC
+ * @cs: the NAND CS id used to communicate with a NAND Chip
+ * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the NFC
*/
struct sunxi_nand_chip_sel {
u8 cs;
s8 rb;
};
-/*
- * sunxi HW ECC infos: stores information related to HW ECC support
+/**
+ * struct sunxi_nand_hw_ecc - stores information related to HW ECC support
*
- * @mode: the sunxi ECC mode field deduced from ECC requirements
+ * @mode: the sunxi ECC mode field deduced from ECC requirements
*/
struct sunxi_nand_hw_ecc {
int mode;
};
-/*
- * NAND chip structure: stores NAND chip device related information
+/**
+ * struct sunxi_nand_chip - stores NAND chip device related information
*
- * @node: used to store NAND chips into a list
- * @nand: base NAND chip structure
- * @mtd: base MTD structure
- * @clk_rate: clk_rate required for this NAND chip
- * @timing_cfg TIMING_CFG register value for this NAND chip
- * @selected: current active CS
- * @nsels: number of CS lines required by the NAND chip
- * @sels: array of CS lines descriptions
+ * @node: used to store NAND chips into a list
+ * @nand: base NAND chip structure
+ * @clk_rate: clk_rate required for this NAND chip
+ * @timing_cfg: TIMING_CFG register value for this NAND chip
+ * @timing_ctl: TIMING_CTL register value for this NAND chip
+ * @nsels: number of CS lines required by the NAND chip
+ * @sels: array of CS lines descriptions
*/
struct sunxi_nand_chip {
struct list_head node;
@@ -202,11 +191,6 @@ struct sunxi_nand_chip {
unsigned long clk_rate;
u32 timing_cfg;
u32 timing_ctl;
- int selected;
- int addr_cycles;
- u32 addr[2];
- int cmd_cycles;
- u8 cmd[2];
int nsels;
struct sunxi_nand_chip_sel sels[0];
};
@@ -216,20 +200,21 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
return container_of(nand, struct sunxi_nand_chip, nand);
}
-/*
- * NAND Controller structure: stores sunxi NAND controller information
+/**
+ * struct sunxi_nfc - stores sunxi NAND controller information
*
- * @controller: base controller structure
- * @dev: parent device (used to print error messages)
- * @regs: NAND controller registers
- * @ahb_clk: NAND Controller AHB clock
- * @mod_clk: NAND Controller mod clock
- * @assigned_cs: bitmask describing already assigned CS lines
- * @clk_rate: NAND controller current clock rate
- * @chips: a list containing all the NAND chips attached to
- * this NAND controller
- * @complete: a completion object used to wait for NAND
- * controller events
+ * @controller: base controller structure
+ * @dev: parent device (used to print error messages)
+ * @regs: NAND controller registers
+ * @ahb_clk: NAND controller AHB clock
+ * @mod_clk: NAND controller mod clock
+ * @reset: NAND controller reset line
+ * @assigned_cs: bitmask describing already assigned CS lines
+ * @clk_rate: NAND controller current clock rate
+ * @chips: a list containing all the NAND chips attached to this NAND
+ * controller
+ * @complete: a completion object used to wait for NAND controller events
+ * @dmac: the DMA channel attached to the NAND controller
*/
struct sunxi_nfc {
struct nand_controller controller;
@@ -339,13 +324,11 @@ static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
return ret;
}
-static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
+static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf,
int chunksize, int nchunks,
enum dma_data_direction ddir,
struct scatterlist *sg)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct dma_async_tx_descriptor *dmad;
enum dma_transfer_direction tdir;
dma_cookie_t dmat;
@@ -388,38 +371,16 @@ err_unmap_buf:
return ret;
}
-static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
+static void sunxi_nfc_dma_op_cleanup(struct sunxi_nfc *nfc,
enum dma_data_direction ddir,
struct scatterlist *sg)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
-
dma_unmap_sg(nfc->dev, sg, 1, ddir);
writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
nfc->regs + NFC_REG_CTL);
}
-static int sunxi_nfc_dev_ready(struct nand_chip *nand)
-{
- struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
- struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
- u32 mask;
-
- if (sunxi_nand->selected < 0)
- return 0;
-
- if (sunxi_nand->sels[sunxi_nand->selected].rb < 0) {
- dev_err(nfc->dev, "cannot check R/B NAND status!\n");
- return 0;
- }
-
- mask = NFC_RB_STATE(sunxi_nand->sels[sunxi_nand->selected].rb);
-
- return !!(readl(nfc->regs + NFC_REG_ST) & mask);
-}
-
-static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip)
+static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs)
{
struct mtd_info *mtd = nand_to_mtd(nand);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
@@ -427,40 +388,27 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip)
struct sunxi_nand_chip_sel *sel;
u32 ctl;
- if (chip > 0 && chip >= sunxi_nand->nsels)
- return;
-
- if (chip == sunxi_nand->selected)
+ if (cs > 0 && cs >= sunxi_nand->nsels)
return;
ctl = readl(nfc->regs + NFC_REG_CTL) &
~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
- if (chip >= 0) {
- sel = &sunxi_nand->sels[chip];
+ sel = &sunxi_nand->sels[cs];
+ ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | NFC_PAGE_SHIFT(nand->page_shift);
+ if (sel->rb >= 0)
+ ctl |= NFC_RB_SEL(sel->rb);
- ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
- NFC_PAGE_SHIFT(nand->page_shift);
- if (sel->rb < 0) {
- nand->legacy.dev_ready = NULL;
- } else {
- nand->legacy.dev_ready = sunxi_nfc_dev_ready;
- ctl |= NFC_RB_SEL(sel->rb);
- }
-
- writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
+ writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
- if (nfc->clk_rate != sunxi_nand->clk_rate) {
- clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
- nfc->clk_rate = sunxi_nand->clk_rate;
- }
+ if (nfc->clk_rate != sunxi_nand->clk_rate) {
+ clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
+ nfc->clk_rate = sunxi_nand->clk_rate;
}
writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
writel(ctl, nfc->regs + NFC_REG_CTL);
-
- sunxi_nand->selected = chip;
}
static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
@@ -537,71 +485,6 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
}
}
-static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand)
-{
- uint8_t ret = 0;
-
- sunxi_nfc_read_buf(nand, &ret, 1);
-
- return ret;
-}
-
-static void sunxi_nfc_cmd_ctrl(struct nand_chip *nand, int dat,
- unsigned int ctrl)
-{
- struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
- struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
- int ret;
-
- if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
- !(ctrl & (NAND_CLE | NAND_ALE))) {
- u32 cmd = 0;
-
- if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
- return;
-
- if (sunxi_nand->cmd_cycles--)
- cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
-
- if (sunxi_nand->cmd_cycles--) {
- cmd |= NFC_SEND_CMD2;
- writel(sunxi_nand->cmd[1],
- nfc->regs + NFC_REG_RCMD_SET);
- }
-
- sunxi_nand->cmd_cycles = 0;
-
- if (sunxi_nand->addr_cycles) {
- cmd |= NFC_SEND_ADR |
- NFC_ADR_NUM(sunxi_nand->addr_cycles);
- writel(sunxi_nand->addr[0],
- nfc->regs + NFC_REG_ADDR_LOW);
- }
-
- if (sunxi_nand->addr_cycles > 4)
- writel(sunxi_nand->addr[1],
- nfc->regs + NFC_REG_ADDR_HIGH);
-
- ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
- if (ret)
- return;
-
- writel(cmd, nfc->regs + NFC_REG_CMD);
- sunxi_nand->addr[0] = 0;
- sunxi_nand->addr[1] = 0;
- sunxi_nand->addr_cycles = 0;
- sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
- }
-
- if (ctrl & NAND_CLE) {
- sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
- } else if (ctrl & NAND_ALE) {
- sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
- dat << ((sunxi_nand->addr_cycles % 4) * 8);
- sunxi_nand->addr_cycles++;
- }
-}
-
/* These seed values have been extracted from Allwinner's BSP */
static const u16 sunxi_nfc_randomizer_page_seeds[] = {
0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
@@ -684,8 +567,10 @@ static u16 sunxi_nfc_randomizer_step(u16 state, int count)
return state;
}
-static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
+static u16 sunxi_nfc_randomizer_state(struct nand_chip *nand, int page,
+ bool ecc)
{
+ struct mtd_info *mtd = nand_to_mtd(nand);
const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
int mod = mtd_div_by_ws(mtd->erasesize, mtd);
@@ -702,10 +587,9 @@ static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
return seeds[page % mod];
}
-static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
- int page, bool ecc)
+static void sunxi_nfc_randomizer_config(struct nand_chip *nand, int page,
+ bool ecc)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
u16 state;
@@ -714,14 +598,13 @@ static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
return;
ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
- state = sunxi_nfc_randomizer_state(mtd, page, ecc);
+ state = sunxi_nfc_randomizer_state(nand, page, ecc);
ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
}
-static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
+static void sunxi_nfc_randomizer_enable(struct nand_chip *nand)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
if (!(nand->options & NAND_NEED_SCRAMBLING))
@@ -731,9 +614,8 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
nfc->regs + NFC_REG_ECC_CTL);
}
-static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
+static void sunxi_nfc_randomizer_disable(struct nand_chip *nand)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
if (!(nand->options & NAND_NEED_SCRAMBLING))
@@ -743,36 +625,35 @@ static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
nfc->regs + NFC_REG_ECC_CTL);
}
-static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
+static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm)
{
- u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
+ u16 state = sunxi_nfc_randomizer_state(nand, page, true);
bbm[0] ^= state;
bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
}
-static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
+static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand,
const uint8_t *buf, int len,
bool ecc, int page)
{
- sunxi_nfc_randomizer_config(mtd, page, ecc);
- sunxi_nfc_randomizer_enable(mtd);
- sunxi_nfc_write_buf(mtd_to_nand(mtd), buf, len);
- sunxi_nfc_randomizer_disable(mtd);
+ sunxi_nfc_randomizer_config(nand, page, ecc);
+ sunxi_nfc_randomizer_enable(nand);
+ sunxi_nfc_write_buf(nand, buf, len);
+ sunxi_nfc_randomizer_disable(nand);
}
-static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
+static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf,
int len, bool ecc, int page)
{
- sunxi_nfc_randomizer_config(mtd, page, ecc);
- sunxi_nfc_randomizer_enable(mtd);
- sunxi_nfc_read_buf(mtd_to_nand(mtd), buf, len);
- sunxi_nfc_randomizer_disable(mtd);
+ sunxi_nfc_randomizer_config(nand, page, ecc);
+ sunxi_nfc_randomizer_enable(nand);
+ sunxi_nfc_read_buf(nand, buf, len);
+ sunxi_nfc_randomizer_disable(nand);
}
-static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
+static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
u32 ecc_ctl;
@@ -789,9 +670,8 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
}
-static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
+static void sunxi_nfc_hw_ecc_disable(struct nand_chip *nand)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
@@ -811,10 +691,9 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
}
-static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
+static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
int step, bool bbm, int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
@@ -822,21 +701,20 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
/* De-randomize the Bad Block Marker. */
if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
- sunxi_nfc_randomize_bbm(mtd, page, oob);
+ sunxi_nfc_randomize_bbm(nand, page, oob);
}
-static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
+static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
const u8 *oob, int step,
bool bbm, int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
u8 user_data[4];
/* Randomize the Bad Block Marker. */
if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
memcpy(user_data, oob, sizeof(user_data));
- sunxi_nfc_randomize_bbm(mtd, page, user_data);
+ sunxi_nfc_randomize_bbm(nand, page, user_data);
oob = user_data;
}
@@ -844,9 +722,11 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
nfc->regs + NFC_REG_USER_DATA(step));
}
-static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
+static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand,
unsigned int *max_bitflips, int ret)
{
+ struct mtd_info *mtd = nand_to_mtd(nand);
+
if (ret < 0) {
mtd->ecc_stats.failed++;
} else {
@@ -855,10 +735,9 @@ static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
}
}
-static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
+static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
int step, u32 status, bool *erased)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = &nand->ecc;
u32 tmp;
@@ -892,14 +771,13 @@ static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
return NFC_ECC_ERR_CNT(step, tmp);
}
-static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
+static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
u8 *data, int data_off,
u8 *oob, int oob_off,
int *cur_off,
unsigned int *max_bitflips,
bool bbm, bool oob_required, int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int raw_mode = 0;
@@ -909,7 +787,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
if (*cur_off != data_off)
nand_change_read_column_op(nand, data_off, NULL, 0, false);
- sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
+ sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page);
if (data_off + ecc->size != oob_off)
nand_change_read_column_op(nand, oob_off, NULL, 0, false);
@@ -918,18 +796,18 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
if (ret)
return ret;
- sunxi_nfc_randomizer_enable(mtd);
+ sunxi_nfc_randomizer_enable(nand);
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
nfc->regs + NFC_REG_CMD);
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
- sunxi_nfc_randomizer_disable(mtd);
+ sunxi_nfc_randomizer_disable(nand);
if (ret)
return ret;
*cur_off = oob_off + ecc->bytes + 4;
- ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0,
+ ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0,
readl(nfc->regs + NFC_REG_ECC_ST),
&erased);
if (erased)
@@ -961,24 +839,24 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
if (oob_required) {
nand_change_read_column_op(nand, oob_off, NULL, 0,
false);
- sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
+ sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4,
true, page);
- sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
+ sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, 0,
bbm, page);
}
}
- sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret);
+ sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret);
return raw_mode;
}
-static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
+static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand,
u8 *oob, int *cur_off,
bool randomize, int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int offset = ((ecc->bytes + 4) * ecc->steps);
int len = mtd->oobsize - offset;
@@ -993,20 +871,20 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
if (!randomize)
sunxi_nfc_read_buf(nand, oob + offset, len);
else
- sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
+ sunxi_nfc_randomizer_read_buf(nand, oob + offset, len,
false, page);
if (cur_off)
*cur_off = mtd->oobsize + mtd->writesize;
}
-static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
+static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf,
int oob_required, int page,
int nchunks)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
bool randomized = nand->options & NAND_NEED_SCRAMBLING;
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
unsigned int max_bitflips = 0;
int ret, i, raw_mode = 0;
@@ -1017,14 +895,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
if (ret)
return ret;
- ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, nchunks,
+ ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks,
DMA_FROM_DEVICE, &sg);
if (ret)
return ret;
- sunxi_nfc_hw_ecc_enable(mtd);
- sunxi_nfc_randomizer_config(mtd, page, false);
- sunxi_nfc_randomizer_enable(mtd);
+ sunxi_nfc_hw_ecc_enable(nand);
+ sunxi_nfc_randomizer_config(nand, page, false);
+ sunxi_nfc_randomizer_enable(nand);
writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) |
NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET);
@@ -1038,10 +916,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
if (ret)
dmaengine_terminate_all(nfc->dmac);
- sunxi_nfc_randomizer_disable(mtd);
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_randomizer_disable(nand);
+ sunxi_nfc_hw_ecc_disable(nand);
- sunxi_nfc_dma_op_cleanup(mtd, DMA_FROM_DEVICE, &sg);
+ sunxi_nfc_dma_op_cleanup(nfc, DMA_FROM_DEVICE, &sg);
if (ret)
return ret;
@@ -1055,7 +933,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
u8 *oob = nand->oob_poi + oob_off;
bool erased;
- ret = sunxi_nfc_hw_ecc_correct(mtd, randomized ? data : NULL,
+ ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL,
oob_required ? oob : NULL,
i, status, &erased);
@@ -1069,14 +947,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
mtd->writesize + oob_off,
oob, ecc->bytes + 4, false);
- sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i,
+ sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i,
!i, page);
}
if (erased)
raw_mode = 1;
- sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
+ sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret);
}
if (status & NFC_ECC_ERR_MSK) {
@@ -1111,25 +989,24 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
if (ret >= 0)
raw_mode = 1;
- sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
+ sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret);
}
}
if (oob_required)
- sunxi_nfc_hw_ecc_read_extra_oob(mtd, nand->oob_poi,
+ sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi,
NULL, !raw_mode,
page);
return max_bitflips;
}
-static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
+static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
const u8 *data, int data_off,
const u8 *oob, int oob_off,
int *cur_off, bool bbm,
int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret;
@@ -1137,7 +1014,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
if (data_off != *cur_off)
nand_change_write_column_op(nand, data_off, NULL, 0, false);
- sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
+ sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page);
if (data_off + ecc->size != oob_off)
nand_change_write_column_op(nand, oob_off, NULL, 0, false);
@@ -1146,15 +1023,15 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
if (ret)
return ret;
- sunxi_nfc_randomizer_enable(mtd);
- sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page);
+ sunxi_nfc_randomizer_enable(nand);
+ sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
NFC_ACCESS_DIR | NFC_ECC_OP,
nfc->regs + NFC_REG_CMD);
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
- sunxi_nfc_randomizer_disable(mtd);
+ sunxi_nfc_randomizer_disable(nand);
if (ret)
return ret;
@@ -1163,11 +1040,11 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
return 0;
}
-static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
+static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
u8 *oob, int *cur_off,
int page)
{
- struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
int offset = ((ecc->bytes + 4) * ecc->steps);
int len = mtd->oobsize - offset;
@@ -1179,32 +1056,34 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
nand_change_write_column_op(nand, offset + mtd->writesize,
NULL, 0, false);
- sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
+ sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page);
if (cur_off)
*cur_off = mtd->oobsize + mtd->writesize;
}
-static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
+static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
int oob_required, int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
unsigned int max_bitflips = 0;
int ret, i, cur_off = 0;
bool raw_mode = false;
- nand_read_page_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
+ nand_read_page_op(nand, page, 0, NULL, 0);
- sunxi_nfc_hw_ecc_enable(mtd);
+ sunxi_nfc_hw_ecc_enable(nand);
for (i = 0; i < ecc->steps; i++) {
int data_off = i * ecc->size;
int oob_off = i * (ecc->bytes + 4);
u8 *data = buf + data_off;
- u8 *oob = chip->oob_poi + oob_off;
+ u8 *oob = nand->oob_poi + oob_off;
- ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
+ ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob,
oob_off + mtd->writesize,
&cur_off, &max_bitflips,
!i, oob_required, page);
@@ -1215,52 +1094,55 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
}
if (oob_required)
- sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
+ sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off,
!raw_mode, page);
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_hw_ecc_disable(nand);
return max_bitflips;
}
-static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *chip, u8 *buf,
+static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf,
int oob_required, int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
- nand_read_page_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
+ nand_read_page_op(nand, page, 0, NULL, 0);
- ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page,
- chip->ecc.steps);
+ ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page,
+ nand->ecc.steps);
if (ret >= 0)
return ret;
/* Fallback to PIO mode */
- return sunxi_nfc_hw_ecc_read_page(chip, buf, oob_required, page);
+ return sunxi_nfc_hw_ecc_read_page(nand, buf, oob_required, page);
}
-static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip,
+static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand,
u32 data_offs, u32 readlen,
u8 *bufpoi, int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret, i, cur_off = 0;
unsigned int max_bitflips = 0;
- nand_read_page_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
+ nand_read_page_op(nand, page, 0, NULL, 0);
- sunxi_nfc_hw_ecc_enable(mtd);
+ sunxi_nfc_hw_ecc_enable(nand);
for (i = data_offs / ecc->size;
i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
int data_off = i * ecc->size;
int oob_off = i * (ecc->bytes + 4);
u8 *data = bufpoi + data_off;
- u8 *oob = chip->oob_poi + oob_off;
+ u8 *oob = nand->oob_poi + oob_off;
- ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
+ ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off,
oob,
oob_off + mtd->writesize,
&cur_off, &max_bitflips, !i,
@@ -1269,113 +1151,118 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip,
return ret;
}
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_hw_ecc_disable(nand);
return max_bitflips;
}
-static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip,
+static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand,
u32 data_offs, u32 readlen,
u8 *buf, int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size);
+ int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size);
int ret;
- nand_read_page_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
+ nand_read_page_op(nand, page, 0, NULL, 0);
- ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks);
+ ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks);
if (ret >= 0)
return ret;
/* Fallback to PIO mode */
- return sunxi_nfc_hw_ecc_read_subpage(chip, data_offs, readlen,
+ return sunxi_nfc_hw_ecc_read_subpage(nand, data_offs, readlen,
buf, page);
}
-static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *chip,
+static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
const uint8_t *buf, int oob_required,
int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret, i, cur_off = 0;
- nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
+ nand_prog_page_begin_op(nand, page, 0, NULL, 0);
- sunxi_nfc_hw_ecc_enable(mtd);
+ sunxi_nfc_hw_ecc_enable(nand);
for (i = 0; i < ecc->steps; i++) {
int data_off = i * ecc->size;
int oob_off = i * (ecc->bytes + 4);
const u8 *data = buf + data_off;
- const u8 *oob = chip->oob_poi + oob_off;
+ const u8 *oob = nand->oob_poi + oob_off;
- ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+ ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob,
oob_off + mtd->writesize,
&cur_off, !i, page);
if (ret)
return ret;
}
- if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
- sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
+ if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
+ sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
&cur_off, page);
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_hw_ecc_disable(nand);
- return nand_prog_page_end_op(chip);
+ return nand_prog_page_end_op(nand);
}
-static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *chip,
+static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand,
u32 data_offs, u32 data_len,
const u8 *buf, int oob_required,
int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct mtd_info *mtd = nand_to_mtd(nand);
+ struct nand_ecc_ctrl *ecc = &nand->ecc;
int ret, i, cur_off = 0;
- nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
- sunxi_nfc_hw_ecc_enable(mtd);
+ nand_prog_page_begin_op(nand, page, 0, NULL, 0);
+
+ sunxi_nfc_hw_ecc_enable(nand);
for (i = data_offs / ecc->size;
i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
int data_off = i * ecc->size;
int oob_off = i * (ecc->bytes + 4);
const u8 *data = buf + data_off;
- const u8 *oob = chip->oob_poi + oob_off;
+ const u8 *oob = nand->oob_poi + oob_off;
- ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+ ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob,
oob_off + mtd->writesize,
&cur_off, !i, page);
if (ret)
return ret;
}
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_hw_ecc_disable(nand);
- return nand_prog_page_end_op(chip);
+ return nand_prog_page_end_op(nand);
}
-static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip,
+static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
const u8 *buf,
int oob_required,
int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = &nand->ecc;
struct scatterlist sg;
int ret, i;
+ sunxi_nfc_select_chip(nand, nand->cur_cs);
+
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
if (ret)
return ret;
- ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, ecc->steps,
+ ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps,
DMA_TO_DEVICE, &sg);
if (ret)
goto pio_fallback;
@@ -1383,14 +1270,14 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip,
for (i = 0; i < ecc->steps; i++) {
const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
- sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page);
+ sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
}
- nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+ nand_prog_page_begin_op(nand, page, 0, NULL, 0);
- sunxi_nfc_hw_ecc_enable(mtd);
- sunxi_nfc_randomizer_config(mtd, page, false);
- sunxi_nfc_randomizer_enable(mtd);
+ sunxi_nfc_hw_ecc_enable(nand);
+ sunxi_nfc_randomizer_config(nand, page, false);
+ sunxi_nfc_randomizer_enable(nand);
writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG,
nfc->regs + NFC_REG_WCMD_SET);
@@ -1405,46 +1292,46 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip,
if (ret)
dmaengine_terminate_all(nfc->dmac);
- sunxi_nfc_randomizer_disable(mtd);
- sunxi_nfc_hw_ecc_disable(mtd);
+ sunxi_nfc_randomizer_disable(nand);
+ sunxi_nfc_hw_ecc_disable(nand);
- sunxi_nfc_dma_op_cleanup(mtd, DMA_TO_DEVICE, &sg);
+ sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg);
if (ret)
return ret;
- if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
+ if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
/* TODO: use DMA to transfer extra OOB bytes ? */
- sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
+ sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
NULL, page);
- return nand_prog_page_end_op(chip);
+ return nand_prog_page_end_op(nand);
pio_fallback:
- return sunxi_nfc_hw_ecc_write_page(chip, buf, oob_required, page);
+ return sunxi_nfc_hw_ecc_write_page(nand, buf, oob_required, page);
}
-static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page)
+static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page)
{
- chip->pagebuf = -1;
+ nand->pagebuf = -1;
- return chip->ecc.read_page(chip, chip->data_buf, 1, page);
+ return nand->ecc.read_page(nand, nand->data_buf, 1, page);
}
-static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *chip, int page)
+static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
+ struct mtd_info *mtd = nand_to_mtd(nand);
int ret;
- chip->pagebuf = -1;
+ nand->pagebuf = -1;
- memset(chip->data_buf, 0xff, mtd->writesize);
- ret = chip->ecc.write_page(chip, chip->data_buf, 1, page);
+ memset(nand->data_buf, 0xff, mtd->writesize);
+ ret = nand->ecc.write_page(nand, nand->data_buf, 1, page);
if (ret)
return ret;
/* Send command to program the OOB data */
- return nand_prog_page_end_op(chip);
+ return nand_prog_page_end_op(nand);
}
static const s32 tWB_lut[] = {6, 12, 16, 20};
@@ -1471,8 +1358,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
const struct nand_data_interface *conf)
{
- struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
- struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+ struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
const struct nand_sdr_timings *timings;
u32 min_clk_period = 0;
s32 tWB, tADL, tWHR, tRHW, tCAD;
@@ -1555,6 +1442,20 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
if (timings->tRHW_min > (min_clk_period * 20))
min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
+ /*
+ * In non-EDO, tREA should be less than tRP to guarantee that the
+ * controller does not sample the IO lines too early. Unfortunately,
+ * the sunxi NAND controller does not allow us to have different
+ * values for tRP and tREH (tRP = tREH = tRW / 2).
+ *
+ * We have 2 options to overcome this limitation:
+ *
+ * 1/ Extend tRC to fulfil the tREA <= tRC / 2 constraint
+ * 2/ Use EDO mode (only works if timings->tRLOH > 0)
+ */
+ if (timings->tREA_max > min_clk_period && !timings->tRLOH_min)
+ min_clk_period = timings->tREA_max;
+
tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
min_clk_period);
if (tWB < 0) {
@@ -1591,7 +1492,7 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
tCAD = 0x7;
/* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
- chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
+ sunxi_nand->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
/* Convert min_clk_period from picoseconds to nanoseconds */
min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
@@ -1602,21 +1503,24 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
* This new formula was verified with a scope and validated by
* Allwinner engineers.
*/
- chip->clk_rate = NSEC_PER_SEC / min_clk_period;
- real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
+ sunxi_nand->clk_rate = NSEC_PER_SEC / min_clk_period;
+ real_clk_rate = clk_round_rate(nfc->mod_clk, sunxi_nand->clk_rate);
if (real_clk_rate <= 0) {
- dev_err(nfc->dev, "Unable to round clk %lu\n", chip->clk_rate);
+ dev_err(nfc->dev, "Unable to round clk %lu\n",
+ sunxi_nand->clk_rate);
return -EINVAL;
}
+ sunxi_nand->timing_ctl = 0;
+
/*
* ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
* output cycle timings shall be used if the host drives tRC less than
- * 30 ns.
+ * 30 ns. We should also use EDO mode if tREA is bigger than tRP.
*/
min_clk_period = NSEC_PER_SEC / real_clk_rate;
- chip->timing_ctl = ((min_clk_period * 2) < 30) ?
- NFC_TIMING_CTL_EDO : 0;
+ if (min_clk_period * 2 < 30 || min_clk_period * 1000 < timings->tREA_max)
+ sunxi_nand->timing_ctl = NFC_TIMING_CTL_EDO;
return 0;
}
@@ -1677,14 +1581,13 @@ static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
kfree(ecc->priv);
}
-static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
+static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
struct nand_ecc_ctrl *ecc,
struct device_node *np)
{
static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
- struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ struct mtd_info *mtd = nand_to_mtd(nand);
struct sunxi_nand_hw_ecc *data;
int nsectors;
int ret;
@@ -1808,7 +1711,6 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
static int sunxi_nand_attach_chip(struct nand_chip *nand)
{
- struct mtd_info *mtd = nand_to_mtd(nand);
struct nand_ecc_ctrl *ecc = &nand->ecc;
struct device_node *np = nand_get_flash_node(nand);
int ret;
@@ -1831,7 +1733,7 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand)
switch (ecc->mode) {
case NAND_ECC_HW:
- ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
+ ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np);
if (ret)
return ret;
break;
@@ -1845,15 +1747,165 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand)
return 0;
}
+static int sunxi_nfc_exec_subop(struct nand_chip *nand,
+ const struct nand_subop *subop)
+{
+ struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ u32 cmd = 0, extcmd = 0, cnt = 0, addrs[2] = { };
+ unsigned int i, j, remaining, start;
+ void *inbuf = NULL;
+ int ret;
+
+ for (i = 0; i < subop->ninstrs; i++) {
+ const struct nand_op_instr *instr = &subop->instrs[i];
+
+ switch (instr->type) {
+ case NAND_OP_CMD_INSTR:
+ if (cmd & NFC_SEND_CMD1) {
+ if (WARN_ON(cmd & NFC_SEND_CMD2))
+ return -EINVAL;
+
+ cmd |= NFC_SEND_CMD2;
+ extcmd |= instr->ctx.cmd.opcode;
+ } else {
+ cmd |= NFC_SEND_CMD1 |
+ NFC_CMD(instr->ctx.cmd.opcode);
+ }
+ break;
+
+ case NAND_OP_ADDR_INSTR:
+ remaining = nand_subop_get_num_addr_cyc(subop, i);
+ start = nand_subop_get_addr_start_off(subop, i);
+ for (j = 0; j < 8 && j + start < remaining; j++) {
+ u32 addr = instr->ctx.addr.addrs[j + start];
+
+ addrs[j / 4] |= addr << (j % 4) * 8;
+ }
+
+ if (j)
+ cmd |= NFC_SEND_ADR | NFC_ADR_NUM(j);
+
+ break;
+
+ case NAND_OP_DATA_IN_INSTR:
+ case NAND_OP_DATA_OUT_INSTR:
+ start = nand_subop_get_data_start_off(subop, i);
+ remaining = nand_subop_get_data_len(subop, i);
+ cnt = min_t(u32, remaining, NFC_SRAM_SIZE);
+ cmd |= NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
+
+ if (instr->type == NAND_OP_DATA_OUT_INSTR) {
+ cmd |= NFC_ACCESS_DIR;
+ memcpy_toio(nfc->regs + NFC_RAM0_BASE,
+ instr->ctx.data.buf.out + start,
+ cnt);
+ } else {
+ inbuf = instr->ctx.data.buf.in + start;
+ }
+
+ break;
+
+ case NAND_OP_WAITRDY_INSTR:
+ cmd |= NFC_WAIT_FLAG;
+ break;
+ }
+ }
+
+ ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+ if (ret)
+ return ret;
+
+ if (cmd & NFC_SEND_ADR) {
+ writel(addrs[0], nfc->regs + NFC_REG_ADDR_LOW);
+ writel(addrs[1], nfc->regs + NFC_REG_ADDR_HIGH);
+ }
+
+ if (cmd & NFC_SEND_CMD2)
+ writel(extcmd,
+ nfc->regs +
+ (cmd & NFC_ACCESS_DIR ?
+ NFC_REG_WCMD_SET : NFC_REG_RCMD_SET));
+
+ if (cmd & NFC_DATA_TRANS)
+ writel(cnt, nfc->regs + NFC_REG_CNT);
+
+ writel(cmd, nfc->regs + NFC_REG_CMD);
+
+ ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG,
+ !(cmd & NFC_WAIT_FLAG) && cnt < 64,
+ 0);
+ if (ret)
+ return ret;
+
+ if (inbuf)
+ memcpy_fromio(inbuf, nfc->regs + NFC_RAM0_BASE, cnt);
+
+ return 0;
+}
+
+static int sunxi_nfc_soft_waitrdy(struct nand_chip *nand,
+ const struct nand_subop *subop)
+{
+ return nand_soft_waitrdy(nand,
+ subop->instrs[0].ctx.waitrdy.timeout_ms);
+}
+
+static const struct nand_op_parser sunxi_nfc_op_parser = NAND_OP_PARSER(
+ NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop,
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8),
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_WAITRDY_ELEM(true),
+ NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 1024)),
+ NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop,
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8),
+ NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, 1024),
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
+);
+
+static const struct nand_op_parser sunxi_nfc_norb_op_parser = NAND_OP_PARSER(
+ NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop,
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8),
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 1024)),
+ NAND_OP_PARSER_PATTERN(sunxi_nfc_exec_subop,
+ NAND_OP_PARSER_PAT_CMD_ELEM(true),
+ NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8),
+ NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, 1024),
+ NAND_OP_PARSER_PAT_CMD_ELEM(true)),
+ NAND_OP_PARSER_PATTERN(sunxi_nfc_soft_waitrdy,
+ NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
+);
+
+static int sunxi_nfc_exec_op(struct nand_chip *nand,
+ const struct nand_operation *op, bool check_only)
+{
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+ const struct nand_op_parser *parser;
+
+ sunxi_nfc_select_chip(nand, op->cs);
+
+ if (sunxi_nand->sels[op->cs].rb >= 0)
+ parser = &sunxi_nfc_op_parser;
+ else
+ parser = &sunxi_nfc_norb_op_parser;
+
+ return nand_op_parser_exec_op(nand, parser, op, check_only);
+}
+
static const struct nand_controller_ops sunxi_nand_controller_ops = {
.attach_chip = sunxi_nand_attach_chip,
.setup_data_interface = sunxi_nfc_setup_data_interface,
+ .exec_op = sunxi_nfc_exec_op,
};
static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
struct device_node *np)
{
- struct sunxi_nand_chip *chip;
+ struct sunxi_nand_chip *sunxi_nand;
struct mtd_info *mtd;
struct nand_chip *nand;
int nsels;
@@ -1870,17 +1922,14 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
return -EINVAL;
}
- chip = devm_kzalloc(dev,
- sizeof(*chip) +
- (nsels * sizeof(struct sunxi_nand_chip_sel)),
- GFP_KERNEL);
- if (!chip) {
+ sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels),
+ GFP_KERNEL);
+ if (!sunxi_nand) {
dev_err(dev, "could not allocate chip\n");
return -ENOMEM;
}
- chip->nsels = nsels;
- chip->selected = -1;
+ sunxi_nand->nsels = nsels;
for (i = 0; i < nsels; i++) {
ret = of_property_read_u32_index(np, "reg", i, &tmp);
@@ -1902,18 +1951,17 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
return -EINVAL;
}
- chip->sels[i].cs = tmp;
+ sunxi_nand->sels[i].cs = tmp;
if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
tmp < 2)
- chip->sels[i].rb = tmp;
+ sunxi_nand->sels[i].rb = tmp;
else
- chip->sels[i].rb = -1;
+ sunxi_nand->sels[i].rb = -1;
}
- nand = &chip->nand;
+ nand = &sunxi_nand->nand;
/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
- nand->legacy.chip_delay = 200;
nand->controller = &nfc->controller;
nand->controller->ops = &sunxi_nand_controller_ops;
@@ -1923,11 +1971,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
*/
nand->ecc.mode = NAND_ECC_HW;
nand_set_flash_node(nand, np);
- nand->legacy.select_chip = sunxi_nfc_select_chip;
- nand->legacy.cmd_ctrl = sunxi_nfc_cmd_ctrl;
- nand->legacy.read_buf = sunxi_nfc_read_buf;
- nand->legacy.write_buf = sunxi_nfc_write_buf;
- nand->legacy.read_byte = sunxi_nfc_read_byte;
mtd = nand_to_mtd(nand);
mtd->dev.parent = dev;
@@ -1943,7 +1986,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
return ret;
}
- list_add_tail(&chip->node, &nfc->chips);
+ list_add_tail(&sunxi_nand->node, &nfc->chips);
return 0;
}
@@ -1973,14 +2016,15 @@ static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
{
- struct sunxi_nand_chip *chip;
+ struct sunxi_nand_chip *sunxi_nand;
while (!list_empty(&nfc->chips)) {
- chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
- node);
- nand_release(&chip->nand);
- sunxi_nand_ecc_cleanup(&chip->nand.ecc);
- list_del(&chip->node);
+ sunxi_nand = list_first_entry(&nfc->chips,
+ struct sunxi_nand_chip,
+ node);
+ nand_release(&sunxi_nand->nand);
+ sunxi_nand_ecc_cleanup(&sunxi_nand->nand.ecc);
+ list_del(&sunxi_nand->node);
}
}
@@ -2124,7 +2168,7 @@ static struct platform_driver sunxi_nfc_driver = {
};
module_platform_driver(sunxi_nfc_driver);
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
MODULE_AUTHOR("Boris BREZILLON");
MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
MODULE_ALIAS("platform:sunxi_nand");
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index f3b59e649b7d..db030f1701ee 100644
--- a/drivers/mtd/nand/raw/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
@@ -104,6 +104,7 @@
struct tmio_nand {
struct nand_chip chip;
+ struct completion comp;
struct platform_device *dev;
@@ -168,15 +169,11 @@ static int tmio_nand_dev_ready(struct nand_chip *chip)
static irqreturn_t tmio_irq(int irq, void *__tmio)
{
struct tmio_nand *tmio = __tmio;
- struct nand_chip *nand_chip = &tmio->chip;
/* disable RDYREQ interrupt */
tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
+ complete(&tmio->comp);
- if (unlikely(!waitqueue_active(&nand_chip->controller->wq)))
- dev_warn(&tmio->dev->dev, "spurious interrupt\n");
-
- wake_up(&nand_chip->controller->wq);
return IRQ_HANDLED;
}
@@ -193,18 +190,18 @@ static int tmio_nand_wait(struct nand_chip *nand_chip)
u8 status;
/* enable RDYREQ interrupt */
+
tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR);
+ reinit_completion(&tmio->comp);
tmio_iowrite8(0x81, tmio->fcr + FCR_IMR);
- timeout = wait_event_timeout(nand_chip->controller->wq,
- tmio_nand_dev_ready(nand_chip),
- msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20));
+ timeout = 400;
+ timeout = wait_for_completion_timeout(&tmio->comp,
+ msecs_to_jiffies(timeout));
if (unlikely(!tmio_nand_dev_ready(nand_chip))) {
tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
- dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n",
- nand_chip->state == FL_ERASING ? "erase" : "program",
- nand_chip->state == FL_ERASING ? 400 : 20);
+ dev_warn(&tmio->dev->dev, "still busy after 400 ms\n");
} else if (unlikely(!timeout)) {
tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
@@ -378,6 +375,8 @@ static int tmio_probe(struct platform_device *dev)
if (!tmio)
return -ENOMEM;
+ init_completion(&tmio->comp);
+
tmio->dev = dev;
platform_set_drvdata(dev, tmio);
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 479c2f2cf17f..fa87ae28cdfe 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -304,24 +304,30 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
struct nand_device *nand = spinand_to_nand(spinand);
struct mtd_info *mtd = nanddev_to_mtd(nand);
struct nand_page_io_req adjreq = *req;
- unsigned int nbytes = 0;
- void *buf = NULL;
+ void *buf = spinand->databuf;
+ unsigned int nbytes;
u16 column = 0;
int ret;
- memset(spinand->databuf, 0xff,
- nanddev_page_size(nand) +
- nanddev_per_page_oobsize(nand));
+ /*
+ * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
+ * the cache content to 0xFF (depends on vendor implementation), so we
+ * must fill the page cache entirely even if we only want to program
+ * the data portion of the page, otherwise we might corrupt the BBM or
+ * user data previously programmed in OOB area.
+ */
+ nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
+ memset(spinand->databuf, 0xff, nbytes);
+ adjreq.dataoffs = 0;
+ adjreq.datalen = nanddev_page_size(nand);
+ adjreq.databuf.out = spinand->databuf;
+ adjreq.ooblen = nanddev_per_page_oobsize(nand);
+ adjreq.ooboffs = 0;
+ adjreq.oobbuf.out = spinand->oobbuf;
- if (req->datalen) {
+ if (req->datalen)
memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
req->datalen);
- adjreq.dataoffs = 0;
- adjreq.datalen = nanddev_page_size(nand);
- adjreq.databuf.out = spinand->databuf;
- nbytes = adjreq.datalen;
- buf = spinand->databuf;
- }
if (req->ooblen) {
if (req->mode == MTD_OPS_AUTO_OOB)
@@ -332,14 +338,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
else
memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
req->ooblen);
-
- adjreq.ooblen = nanddev_per_page_oobsize(nand);
- adjreq.ooboffs = 0;
- nbytes += nanddev_per_page_oobsize(nand);
- if (!buf) {
- buf = spinand->oobbuf;
- column = nanddev_page_size(nand);
- }
}
spinand_cache_op_adjust_colum(spinand, &adjreq, &column);
@@ -370,8 +368,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
/*
* We need to use the RANDOM LOAD CACHE operation if there's
- * more than one iteration, because the LOAD operation resets
- * the cache to 0xff.
+ * more than one iteration, because the LOAD operation might
+ * reset the cache to 0xff.
*/
if (nbytes) {
column = op.addr.val;
@@ -1018,11 +1016,11 @@ static int spinand_init(struct spinand_device *spinand)
for (i = 0; i < nand->memorg.ntargets; i++) {
ret = spinand_select_target(spinand, i);
if (ret)
- goto err_free_bufs;
+ goto err_manuf_cleanup;
ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
if (ret)
- goto err_free_bufs;
+ goto err_manuf_cleanup;
}
ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
index e4141c20947a..0b49d8264bef 100644
--- a/drivers/mtd/nand/spi/gigadevice.c
+++ b/drivers/mtd/nand/spi/gigadevice.c
@@ -12,6 +12,8 @@
#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
+#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -81,11 +83,83 @@ static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
return -EINVAL;
}
+static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ region->offset = 64;
+ region->length = 64;
+
+ return 0;
+}
+
+static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ /* Reserve 1 bytes for the BBM. */
+ region->offset = 1;
+ region->length = 63;
+
+ return 0;
+}
+
+static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ u8 status2;
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2,
+ &status2);
+ int ret;
+
+ switch (status & STATUS_ECC_MASK) {
+ case STATUS_ECC_NO_BITFLIPS:
+ return 0;
+
+ case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
+ /*
+ * Read status2 register to determine a more fine grained
+ * bit error status
+ */
+ ret = spi_mem_exec_op(spinand->spimem, &op);
+ if (ret)
+ return ret;
+
+ /*
+ * 4 ... 7 bits are flipped (1..4 can't be detected, so
+ * report the maximum of 4 in this case
+ */
+ /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
+ return ((status & STATUS_ECC_MASK) >> 2) |
+ ((status2 & STATUS_ECC_MASK) >> 4);
+
+ case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
+ return 8;
+
+ case STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
.ecc = gd5fxgq4xa_ooblayout_ecc,
.free = gd5fxgq4xa_ooblayout_free,
};
+static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = {
+ .ecc = gd5fxgq4uexxg_ooblayout_ecc,
+ .free = gd5fxgq4uexxg_ooblayout_free,
+};
+
static const struct spinand_info gigadevice_spinand_table[] = {
SPINAND_INFO("GD5F1GQ4xA", 0xF1,
NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
@@ -114,6 +188,15 @@ static const struct spinand_info gigadevice_spinand_table[] = {
0,
SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
gd5fxgq4xa_ecc_get_status)),
+ SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&gd5fxgq4uexxg_ooblayout,
+ gd5fxgq4uexxg_ecc_get_status)),
};
static int gigadevice_spinand_detect(struct spinand_device *spinand)
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index 98f6b9c4b684..d16b57081c95 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -10,6 +10,7 @@
#include <linux/mtd/spinand.h>
#define SPINAND_MFR_MACRONIX 0xC2
+#define MACRONIX_ECCSR_MASK 0x0F
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -55,7 +56,12 @@ static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
SPI_MEM_OP_DUMMY(1, 1),
SPI_MEM_OP_DATA_IN(1, eccsr, 1));
- return spi_mem_exec_op(spinand->spimem, &op);
+ int ret = spi_mem_exec_op(spinand->spimem, &op);
+ if (ret)
+ return ret;
+
+ *eccsr &= MACRONIX_ECCSR_MASK;
+ return 0;
}
static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
index 081265557e70..db8021da45b5 100644
--- a/drivers/mtd/nand/spi/toshiba.c
+++ b/drivers/mtd/nand/spi/toshiba.c
@@ -25,19 +25,19 @@ static SPINAND_OP_VARIANTS(write_cache_variants,
static SPINAND_OP_VARIANTS(update_cache_variants,
SPINAND_PROG_LOAD(false, 0, NULL, 0));
-static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section,
+static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *region)
{
- if (section > 7)
+ if (section > 0)
return -ERANGE;
- region->offset = 128 + 16 * section;
- region->length = 16;
+ region->offset = mtd->oobsize / 2;
+ region->length = mtd->oobsize / 2;
return 0;
}
-static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
+static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *region)
{
if (section > 0)
@@ -45,17 +45,17 @@ static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
/* 2 bytes reserved for BBM */
region->offset = 2;
- region->length = 126;
+ region->length = (mtd->oobsize / 2) - 2;
return 0;
}
-static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = {
- .ecc = tc58cvg2s0h_ooblayout_ecc,
- .free = tc58cvg2s0h_ooblayout_free,
+static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = {
+ .ecc = tc58cxgxsx_ooblayout_ecc,
+ .free = tc58cxgxsx_ooblayout_free,
};
-static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
+static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
u8 status)
{
struct nand_device *nand = spinand_to_nand(spinand);
@@ -94,15 +94,66 @@ static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
}
static const struct spinand_info toshiba_spinand_table[] = {
- SPINAND_INFO("TC58CVG2S0H", 0xCD,
+ /* 3.3V 1Gb */
+ SPINAND_INFO("TC58CVG0S3", 0xC2,
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
+ /* 3.3V 2Gb */
+ SPINAND_INFO("TC58CVG1S3", 0xCB,
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
+ /* 3.3V 4Gb */
+ SPINAND_INFO("TC58CVG2S0", 0xCD,
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
+ /* 1.8V 1Gb */
+ SPINAND_INFO("TC58CYG0S3", 0xB2,
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
+ /* 1.8V 2Gb */
+ SPINAND_INFO("TC58CYG1S3", 0xBB,
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
+ /* 1.8V 4Gb */
+ SPINAND_INFO("TC58CYG2S0", 0xBD,
NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- SPINAND_HAS_QE_BIT,
- SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout,
- tc58cvg2s0h_ecc_get_status)),
+ 0,
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+ tc58cxgxsx_ecc_get_status)),
};
static int toshiba_spinand_detect(struct spinand_device *spinand)
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 44fe8018733c..dab986691267 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -7,14 +7,6 @@ menuconfig MTD_SPI_NOR
if MTD_SPI_NOR
-config MTD_MT81xx_NOR
- tristate "Mediatek MT81xx SPI NOR flash controller"
- depends on HAS_IOMEM
- help
- This enables access to SPI NOR flash, using MT81xx SPI NOR flash
- controller. This controller does not support generic SPI BUS, it only
- supports SPI NOR Flash.
-
config MTD_SPI_NOR_USE_4K_SECTORS
bool "Use small 4096 B erase sectors"
default y
@@ -50,15 +42,6 @@ config SPI_CADENCE_QUADSPI
device with a Cadence QSPI controller and want to access the
Flash as an MTD device.
-config SPI_FSL_QUADSPI
- tristate "Freescale Quad SPI controller"
- depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
- depends on HAS_IOMEM
- help
- This enables support for the Quad SPI controller in master mode.
- This controller does not support generic SPI. It only supports
- SPI NOR.
-
config SPI_HISI_SFC
tristate "Hisilicon SPI-NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST
@@ -66,6 +49,14 @@ config SPI_HISI_SFC
help
This enables support for hisilicon SPI-NOR flash controller.
+config SPI_MTK_QUADSPI
+ tristate "MediaTek Quad SPI controller"
+ depends on HAS_IOMEM
+ help
+ This enables support for the Quad SPI controller in master mode.
+ This controller does not support generic SPI. It only supports
+ SPI NOR.
+
config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index a552efd22958..189a15cca3ec 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -2,9 +2,8 @@
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
-obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
-obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
+obj-$(CONFIG_SPI_MTK_QUADSPI) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
index 04cedd3a2bf6..792628750eec 100644
--- a/drivers/mtd/spi-nor/cadence-quadspi.c
+++ b/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -44,6 +44,12 @@
/* Quirks */
#define CQSPI_NEEDS_WR_DELAY BIT(0)
+/* Capabilities mask */
+#define CQSPI_BASE_HWCAPS_MASK \
+ (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST | \
+ SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_READ_1_1_4 | \
+ SNOR_HWCAPS_PP)
+
struct cqspi_st;
struct cqspi_flash_pdata {
@@ -93,6 +99,11 @@ struct cqspi_st {
struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
};
+struct cqspi_driver_platdata {
+ u32 hwcaps_mask;
+ u8 quirks;
+};
+
/* Operation timeout value */
#define CQSPI_TIMEOUT_MS 500
#define CQSPI_READ_TIMEOUT_MS 10
@@ -101,6 +112,7 @@ struct cqspi_st {
#define CQSPI_INST_TYPE_SINGLE 0
#define CQSPI_INST_TYPE_DUAL 1
#define CQSPI_INST_TYPE_QUAD 2
+#define CQSPI_INST_TYPE_OCTAL 3
#define CQSPI_DUMMY_CLKS_PER_BYTE 8
#define CQSPI_DUMMY_BYTES_MAX 4
@@ -418,9 +430,10 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode,
void __iomem *reg_base = cqspi->iobase;
unsigned int reg;
unsigned int data;
+ u32 write_len;
int ret;
- if (n_tx > 4 || (n_tx && !txbuf)) {
+ if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) {
dev_err(nor->dev,
"Invalid input argument, cmdlen %d txbuf 0x%p\n",
n_tx, txbuf);
@@ -433,10 +446,18 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode,
reg |= ((n_tx - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
<< CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
data = 0;
- memcpy(&data, txbuf, n_tx);
+ write_len = (n_tx > 4) ? 4 : n_tx;
+ memcpy(&data, txbuf, write_len);
+ txbuf += write_len;
writel(data, reg_base + CQSPI_REG_CMDWRITEDATALOWER);
- }
+ if (n_tx > 4) {
+ data = 0;
+ write_len = n_tx - 4;
+ memcpy(&data, txbuf, write_len);
+ writel(data, reg_base + CQSPI_REG_CMDWRITEDATAUPPER);
+ }
+ }
ret = cqspi_exec_flash_cmd(cqspi, reg);
return ret;
}
@@ -911,6 +932,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read)
case SNOR_PROTO_1_1_4:
f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
break;
+ case SNOR_PROTO_1_1_8:
+ f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+ break;
default:
return -EINVAL;
}
@@ -1213,21 +1237,23 @@ static void cqspi_request_mmap_dma(struct cqspi_st *cqspi)
static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
{
- const struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ |
- SNOR_HWCAPS_READ_FAST |
- SNOR_HWCAPS_READ_1_1_2 |
- SNOR_HWCAPS_READ_1_1_4 |
- SNOR_HWCAPS_PP,
- };
struct platform_device *pdev = cqspi->pdev;
struct device *dev = &pdev->dev;
+ const struct cqspi_driver_platdata *ddata;
+ struct spi_nor_hwcaps hwcaps;
struct cqspi_flash_pdata *f_pdata;
struct spi_nor *nor;
struct mtd_info *mtd;
unsigned int cs;
int i, ret;
+ ddata = of_device_get_match_data(dev);
+ if (!ddata) {
+ dev_err(dev, "Couldn't find driver data\n");
+ return -EINVAL;
+ }
+ hwcaps.mask = ddata->hwcaps_mask;
+
/* Get flash device data */
for_each_available_child_of_node(dev->of_node, np) {
ret = of_property_read_u32(np, "reg", &cs);
@@ -1310,7 +1336,7 @@ static int cqspi_probe(struct platform_device *pdev)
struct cqspi_st *cqspi;
struct resource *res;
struct resource *res_ahb;
- unsigned long data;
+ const struct cqspi_driver_platdata *ddata;
int ret;
int irq;
@@ -1377,8 +1403,8 @@ static int cqspi_probe(struct platform_device *pdev)
}
cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
- data = (unsigned long)of_device_get_match_data(dev);
- if (data & CQSPI_NEEDS_WR_DELAY)
+ ddata = of_device_get_match_data(dev);
+ if (ddata && (ddata->quirks & CQSPI_NEEDS_WR_DELAY))
cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC,
cqspi->master_ref_clk_hz);
@@ -1460,14 +1486,32 @@ static const struct dev_pm_ops cqspi__dev_pm_ops = {
#define CQSPI_DEV_PM_OPS NULL
#endif
+static const struct cqspi_driver_platdata cdns_qspi = {
+ .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK,
+};
+
+static const struct cqspi_driver_platdata k2g_qspi = {
+ .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK,
+ .quirks = CQSPI_NEEDS_WR_DELAY,
+};
+
+static const struct cqspi_driver_platdata am654_ospi = {
+ .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK | SNOR_HWCAPS_READ_1_1_8,
+ .quirks = CQSPI_NEEDS_WR_DELAY,
+};
+
static const struct of_device_id cqspi_dt_ids[] = {
{
.compatible = "cdns,qspi-nor",
- .data = (void *)0,
+ .data = &cdns_qspi,
},
{
.compatible = "ti,k2g-qspi",
- .data = (void *)CQSPI_NEEDS_WR_DELAY,
+ .data = &k2g_qspi,
+ },
+ {
+ .compatible = "ti,am654-ospi",
+ .data = &am654_ospi,
},
{ /* end of table */ }
};
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
deleted file mode 100644
index 1ff3430f82c8..000000000000
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Freescale QuadSPI driver.
- *
- * Copyright (C) 2013 Freescale Semiconductor, 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/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/completion.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/spi-nor.h>
-#include <linux/mutex.h>
-#include <linux/pm_qos.h>
-#include <linux/sizes.h>
-
-/* Controller needs driver to swap endian */
-#define QUADSPI_QUIRK_SWAP_ENDIAN (1 << 0)
-/* Controller needs 4x internal clock */
-#define QUADSPI_QUIRK_4X_INT_CLK (1 << 1)
-/*
- * TKT253890, Controller needs driver to fill txfifo till 16 byte to
- * trigger data transfer even though extern data will not transferred.
- */
-#define QUADSPI_QUIRK_TKT253890 (1 << 2)
-/* Controller cannot wake up from wait mode, TKT245618 */
-#define QUADSPI_QUIRK_TKT245618 (1 << 3)
-
-/* The registers */
-#define QUADSPI_MCR 0x00
-#define QUADSPI_MCR_RESERVED_SHIFT 16
-#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT)
-#define QUADSPI_MCR_MDIS_SHIFT 14
-#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT)
-#define QUADSPI_MCR_CLR_TXF_SHIFT 11
-#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT)
-#define QUADSPI_MCR_CLR_RXF_SHIFT 10
-#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT)
-#define QUADSPI_MCR_DDR_EN_SHIFT 7
-#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT)
-#define QUADSPI_MCR_END_CFG_SHIFT 2
-#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT)
-#define QUADSPI_MCR_SWRSTHD_SHIFT 1
-#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT)
-#define QUADSPI_MCR_SWRSTSD_SHIFT 0
-#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT)
-
-#define QUADSPI_IPCR 0x08
-#define QUADSPI_IPCR_SEQID_SHIFT 24
-#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT)
-
-#define QUADSPI_BUF0CR 0x10
-#define QUADSPI_BUF1CR 0x14
-#define QUADSPI_BUF2CR 0x18
-#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe
-
-#define QUADSPI_BUF3CR 0x1c
-#define QUADSPI_BUF3CR_ALLMST_SHIFT 31
-#define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT)
-#define QUADSPI_BUF3CR_ADATSZ_SHIFT 8
-#define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT)
-
-#define QUADSPI_BFGENCR 0x20
-#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16
-#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT))
-#define QUADSPI_BFGENCR_SEQID_SHIFT 12
-#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT)
-
-#define QUADSPI_BUF0IND 0x30
-#define QUADSPI_BUF1IND 0x34
-#define QUADSPI_BUF2IND 0x38
-#define QUADSPI_SFAR 0x100
-
-#define QUADSPI_SMPR 0x108
-#define QUADSPI_SMPR_DDRSMP_SHIFT 16
-#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT)
-#define QUADSPI_SMPR_FSDLY_SHIFT 6
-#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT)
-#define QUADSPI_SMPR_FSPHS_SHIFT 5
-#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT)
-#define QUADSPI_SMPR_HSENA_SHIFT 0
-#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT)
-
-#define QUADSPI_RBSR 0x10c
-#define QUADSPI_RBSR_RDBFL_SHIFT 8
-#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT)
-
-#define QUADSPI_RBCT 0x110
-#define QUADSPI_RBCT_WMRK_MASK 0x1F
-#define QUADSPI_RBCT_RXBRD_SHIFT 8
-#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT)
-
-#define QUADSPI_TBSR 0x150
-#define QUADSPI_TBDR 0x154
-#define QUADSPI_SR 0x15c
-#define QUADSPI_SR_IP_ACC_SHIFT 1
-#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT)
-#define QUADSPI_SR_AHB_ACC_SHIFT 2
-#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT)
-
-#define QUADSPI_FR 0x160
-#define QUADSPI_FR_TFF_MASK 0x1
-
-#define QUADSPI_SFA1AD 0x180
-#define QUADSPI_SFA2AD 0x184
-#define QUADSPI_SFB1AD 0x188
-#define QUADSPI_SFB2AD 0x18c
-#define QUADSPI_RBDR 0x200
-
-#define QUADSPI_LUTKEY 0x300
-#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0
-
-#define QUADSPI_LCKCR 0x304
-#define QUADSPI_LCKER_LOCK 0x1
-#define QUADSPI_LCKER_UNLOCK 0x2
-
-#define QUADSPI_RSER 0x164
-#define QUADSPI_RSER_TFIE (0x1 << 0)
-
-#define QUADSPI_LUT_BASE 0x310
-
-/*
- * The definition of the LUT register shows below:
- *
- * ---------------------------------------------------
- * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
- * ---------------------------------------------------
- */
-#define OPRND0_SHIFT 0
-#define PAD0_SHIFT 8
-#define INSTR0_SHIFT 10
-#define OPRND1_SHIFT 16
-
-/* Instruction set for the LUT register. */
-#define LUT_STOP 0
-#define LUT_CMD 1
-#define LUT_ADDR 2
-#define LUT_DUMMY 3
-#define LUT_MODE 4
-#define LUT_MODE2 5
-#define LUT_MODE4 6
-#define LUT_FSL_READ 7
-#define LUT_FSL_WRITE 8
-#define LUT_JMP_ON_CS 9
-#define LUT_ADDR_DDR 10
-#define LUT_MODE_DDR 11
-#define LUT_MODE2_DDR 12
-#define LUT_MODE4_DDR 13
-#define LUT_FSL_READ_DDR 14
-#define LUT_FSL_WRITE_DDR 15
-#define LUT_DATA_LEARN 16
-
-/*
- * The PAD definitions for LUT register.
- *
- * The pad stands for the lines number of IO[0:3].
- * For example, the Quad read need four IO lines, so you should
- * set LUT_PAD4 which means we use four IO lines.
- */
-#define LUT_PAD1 0
-#define LUT_PAD2 1
-#define LUT_PAD4 2
-
-/* Oprands for the LUT register. */
-#define ADDR24BIT 0x18
-#define ADDR32BIT 0x20
-
-/* Macros for constructing the LUT register. */
-#define LUT0(ins, pad, opr) \
- (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \
- ((LUT_##ins) << INSTR0_SHIFT))
-
-#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT)
-
-/* other macros for LUT register. */
-#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4)
-#define QUADSPI_LUT_NUM 64
-
-/* SEQID -- we can have 16 seqids at most. */
-#define SEQID_READ 0
-#define SEQID_WREN 1
-#define SEQID_WRDI 2
-#define SEQID_RDSR 3
-#define SEQID_SE 4
-#define SEQID_CHIP_ERASE 5
-#define SEQID_PP 6
-#define SEQID_RDID 7
-#define SEQID_WRSR 8
-#define SEQID_RDCR 9
-#define SEQID_EN4B 10
-#define SEQID_BRWR 11
-
-#define QUADSPI_MIN_IOMAP SZ_4M
-
-enum fsl_qspi_devtype {
- FSL_QUADSPI_VYBRID,
- FSL_QUADSPI_IMX6SX,
- FSL_QUADSPI_IMX7D,
- FSL_QUADSPI_IMX6UL,
- FSL_QUADSPI_LS1021A,
- FSL_QUADSPI_LS2080A,
-};
-
-struct fsl_qspi_devtype_data {
- enum fsl_qspi_devtype devtype;
- int rxfifo;
- int txfifo;
- int ahb_buf_size;
- int driver_data;
-};
-
-static const struct fsl_qspi_devtype_data vybrid_data = {
- .devtype = FSL_QUADSPI_VYBRID,
- .rxfifo = 128,
- .txfifo = 64,
- .ahb_buf_size = 1024,
- .driver_data = QUADSPI_QUIRK_SWAP_ENDIAN,
-};
-
-static const struct fsl_qspi_devtype_data imx6sx_data = {
- .devtype = FSL_QUADSPI_IMX6SX,
- .rxfifo = 128,
- .txfifo = 512,
- .ahb_buf_size = 1024,
- .driver_data = QUADSPI_QUIRK_4X_INT_CLK
- | QUADSPI_QUIRK_TKT245618,
-};
-
-static const struct fsl_qspi_devtype_data imx7d_data = {
- .devtype = FSL_QUADSPI_IMX7D,
- .rxfifo = 512,
- .txfifo = 512,
- .ahb_buf_size = 1024,
- .driver_data = QUADSPI_QUIRK_TKT253890
- | QUADSPI_QUIRK_4X_INT_CLK,
-};
-
-static const struct fsl_qspi_devtype_data imx6ul_data = {
- .devtype = FSL_QUADSPI_IMX6UL,
- .rxfifo = 128,
- .txfifo = 512,
- .ahb_buf_size = 1024,
- .driver_data = QUADSPI_QUIRK_TKT253890
- | QUADSPI_QUIRK_4X_INT_CLK,
-};
-
-static struct fsl_qspi_devtype_data ls1021a_data = {
- .devtype = FSL_QUADSPI_LS1021A,
- .rxfifo = 128,
- .txfifo = 64,
- .ahb_buf_size = 1024,
- .driver_data = 0,
-};
-
-static const struct fsl_qspi_devtype_data ls2080a_data = {
- .devtype = FSL_QUADSPI_LS2080A,
- .rxfifo = 128,
- .txfifo = 64,
- .ahb_buf_size = 1024,
- .driver_data = QUADSPI_QUIRK_TKT253890,
-};
-
-
-#define FSL_QSPI_MAX_CHIP 4
-struct fsl_qspi {
- struct spi_nor nor[FSL_QSPI_MAX_CHIP];
- void __iomem *iobase;
- void __iomem *ahb_addr;
- u32 memmap_phy;
- u32 memmap_offs;
- u32 memmap_len;
- struct clk *clk, *clk_en;
- struct device *dev;
- struct completion c;
- const struct fsl_qspi_devtype_data *devtype_data;
- u32 nor_size;
- u32 nor_num;
- u32 clk_rate;
- unsigned int chip_base_addr; /* We may support two chips. */
- bool has_second_chip;
- bool big_endian;
- struct mutex lock;
- struct pm_qos_request pm_qos_req;
-};
-
-static inline int needs_swap_endian(struct fsl_qspi *q)
-{
- return q->devtype_data->driver_data & QUADSPI_QUIRK_SWAP_ENDIAN;
-}
-
-static inline int needs_4x_clock(struct fsl_qspi *q)
-{
- return q->devtype_data->driver_data & QUADSPI_QUIRK_4X_INT_CLK;
-}
-
-static inline int needs_fill_txfifo(struct fsl_qspi *q)
-{
- return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT253890;
-}
-
-static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
-{
- return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618;
-}
-
-/*
- * R/W functions for big- or little-endian registers:
- * The qSPI controller's endian is independent of the CPU core's endian.
- * So far, although the CPU core is little-endian but the qSPI have two
- * versions for big-endian and little-endian.
- */
-static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr)
-{
- if (q->big_endian)
- iowrite32be(val, addr);
- else
- iowrite32(val, addr);
-}
-
-static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr)
-{
- if (q->big_endian)
- return ioread32be(addr);
- else
- return ioread32(addr);
-}
-
-/*
- * An IC bug makes us to re-arrange the 32-bit data.
- * The following chips, such as IMX6SLX, have fixed this bug.
- */
-static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a)
-{
- return needs_swap_endian(q) ? __swab32(a) : a;
-}
-
-static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q)
-{
- qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
- qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
-}
-
-static inline void fsl_qspi_lock_lut(struct fsl_qspi *q)
-{
- qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
- qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
-}
-
-static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id)
-{
- struct fsl_qspi *q = dev_id;
- u32 reg;
-
- /* clear interrupt */
- reg = qspi_readl(q, q->iobase + QUADSPI_FR);
- qspi_writel(q, reg, q->iobase + QUADSPI_FR);
-
- if (reg & QUADSPI_FR_TFF_MASK)
- complete(&q->c);
-
- dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", q->chip_base_addr, reg);
- return IRQ_HANDLED;
-}
-
-static void fsl_qspi_init_lut(struct fsl_qspi *q)
-{
- void __iomem *base = q->iobase;
- int rxfifo = q->devtype_data->rxfifo;
- u32 lut_base;
- int i;
-
- struct spi_nor *nor = &q->nor[0];
- u8 addrlen = (nor->addr_width == 3) ? ADDR24BIT : ADDR32BIT;
- u8 read_op = nor->read_opcode;
- u8 read_dm = nor->read_dummy;
-
- fsl_qspi_unlock_lut(q);
-
- /* Clear all the LUT table */
- for (i = 0; i < QUADSPI_LUT_NUM; i++)
- qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4);
-
- /* Read */
- lut_base = SEQID_READ * 4;
-
- qspi_writel(q, LUT0(CMD, PAD1, read_op) | LUT1(ADDR, PAD1, addrlen),
- base + QUADSPI_LUT(lut_base));
- qspi_writel(q, LUT0(DUMMY, PAD1, read_dm) |
- LUT1(FSL_READ, PAD4, rxfifo),
- base + QUADSPI_LUT(lut_base + 1));
-
- /* Write enable */
- lut_base = SEQID_WREN * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN),
- base + QUADSPI_LUT(lut_base));
-
- /* Page Program */
- lut_base = SEQID_PP * 4;
-
- qspi_writel(q, LUT0(CMD, PAD1, nor->program_opcode) |
- LUT1(ADDR, PAD1, addrlen),
- base + QUADSPI_LUT(lut_base));
- qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0),
- base + QUADSPI_LUT(lut_base + 1));
-
- /* Read Status */
- lut_base = SEQID_RDSR * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) |
- LUT1(FSL_READ, PAD1, 0x1),
- base + QUADSPI_LUT(lut_base));
-
- /* Erase a sector */
- lut_base = SEQID_SE * 4;
-
- qspi_writel(q, LUT0(CMD, PAD1, nor->erase_opcode) |
- LUT1(ADDR, PAD1, addrlen),
- base + QUADSPI_LUT(lut_base));
-
- /* Erase the whole chip */
- lut_base = SEQID_CHIP_ERASE * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
- base + QUADSPI_LUT(lut_base));
-
- /* READ ID */
- lut_base = SEQID_RDID * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) |
- LUT1(FSL_READ, PAD1, 0x8),
- base + QUADSPI_LUT(lut_base));
-
- /* Write Register */
- lut_base = SEQID_WRSR * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) |
- LUT1(FSL_WRITE, PAD1, 0x2),
- base + QUADSPI_LUT(lut_base));
-
- /* Read Configuration Register */
- lut_base = SEQID_RDCR * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) |
- LUT1(FSL_READ, PAD1, 0x1),
- base + QUADSPI_LUT(lut_base));
-
- /* Write disable */
- lut_base = SEQID_WRDI * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI),
- base + QUADSPI_LUT(lut_base));
-
- /* Enter 4 Byte Mode (Micron) */
- lut_base = SEQID_EN4B * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B),
- base + QUADSPI_LUT(lut_base));
-
- /* Enter 4 Byte Mode (Spansion) */
- lut_base = SEQID_BRWR * 4;
- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR),
- base + QUADSPI_LUT(lut_base));
-
- fsl_qspi_lock_lut(q);
-}
-
-/* Get the SEQID for the command */
-static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
-{
- switch (cmd) {
- case SPINOR_OP_READ_1_1_4:
- case SPINOR_OP_READ_1_1_4_4B:
- return SEQID_READ;
- case SPINOR_OP_WREN:
- return SEQID_WREN;
- case SPINOR_OP_WRDI:
- return SEQID_WRDI;
- case SPINOR_OP_RDSR:
- return SEQID_RDSR;
- case SPINOR_OP_SE:
- return SEQID_SE;
- case SPINOR_OP_CHIP_ERASE:
- return SEQID_CHIP_ERASE;
- case SPINOR_OP_PP:
- return SEQID_PP;
- case SPINOR_OP_RDID:
- return SEQID_RDID;
- case SPINOR_OP_WRSR:
- return SEQID_WRSR;
- case SPINOR_OP_RDCR:
- return SEQID_RDCR;
- case SPINOR_OP_EN4B:
- return SEQID_EN4B;
- case SPINOR_OP_BRWR:
- return SEQID_BRWR;
- default:
- if (cmd == q->nor[0].erase_opcode)
- return SEQID_SE;
- dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd);
- break;
- }
- return -EINVAL;
-}
-
-static int
-fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len)
-{
- void __iomem *base = q->iobase;
- int seqid;
- u32 reg, reg2;
- int err;
-
- init_completion(&q->c);
- dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n",
- q->chip_base_addr, addr, len, cmd);
-
- /* save the reg */
- reg = qspi_readl(q, base + QUADSPI_MCR);
-
- qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr,
- base + QUADSPI_SFAR);
- qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
- base + QUADSPI_RBCT);
- qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
-
- do {
- reg2 = qspi_readl(q, base + QUADSPI_SR);
- if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) {
- udelay(1);
- dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2);
- continue;
- }
- break;
- } while (1);
-
- /* trigger the LUT now */
- seqid = fsl_qspi_get_seqid(q, cmd);
- if (seqid < 0)
- return seqid;
-
- qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len,
- base + QUADSPI_IPCR);
-
- /* Wait for the interrupt. */
- if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) {
- dev_err(q->dev,
- "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n",
- cmd, addr, qspi_readl(q, base + QUADSPI_FR),
- qspi_readl(q, base + QUADSPI_SR));
- err = -ETIMEDOUT;
- } else {
- err = 0;
- }
-
- /* restore the MCR */
- qspi_writel(q, reg, base + QUADSPI_MCR);
-
- return err;
-}
-
-/* Read out the data from the QUADSPI_RBDR buffer registers. */
-static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf)
-{
- u32 tmp;
- int i = 0;
-
- while (len > 0) {
- tmp = qspi_readl(q, q->iobase + QUADSPI_RBDR + i * 4);
- tmp = fsl_qspi_endian_xchg(q, tmp);
- dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n",
- q->chip_base_addr, tmp);
-
- if (len >= 4) {
- *((u32 *)rxbuf) = tmp;
- rxbuf += 4;
- } else {
- memcpy(rxbuf, &tmp, len);
- break;
- }
-
- len -= 4;
- i++;
- }
-}
-
-/*
- * If we have changed the content of the flash by writing or erasing,
- * we need to invalidate the AHB buffer. If we do not do so, we may read out
- * the wrong data. The spec tells us reset the AHB domain and Serial Flash
- * domain at the same time.
- */
-static inline void fsl_qspi_invalid(struct fsl_qspi *q)
-{
- u32 reg;
-
- reg = qspi_readl(q, q->iobase + QUADSPI_MCR);
- reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
- qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
-
- /*
- * The minimum delay : 1 AHB + 2 SFCK clocks.
- * Delay 1 us is enough.
- */
- udelay(1);
-
- reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
- qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
-}
-
-static ssize_t fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
- u8 opcode, unsigned int to, u32 *txbuf,
- unsigned count)
-{
- int ret, i, j;
- u32 tmp;
-
- dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n",
- q->chip_base_addr, to, count);
-
- /* clear the TX FIFO. */
- tmp = qspi_readl(q, q->iobase + QUADSPI_MCR);
- qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
-
- /* fill the TX data to the FIFO */
- for (j = 0, i = ((count + 3) / 4); j < i; j++) {
- tmp = fsl_qspi_endian_xchg(q, *txbuf);
- qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
- txbuf++;
- }
-
- /* fill the TXFIFO upto 16 bytes for i.MX7d */
- if (needs_fill_txfifo(q))
- for (; i < 4; i++)
- qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
-
- /* Trigger it */
- ret = fsl_qspi_runcmd(q, opcode, to, count);
-
- if (ret == 0)
- return count;
-
- return ret;
-}
-
-static void fsl_qspi_set_map_addr(struct fsl_qspi *q)
-{
- int nor_size = q->nor_size;
- void __iomem *base = q->iobase;
-
- qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
- qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
- qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
- qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
-}
-
-/*
- * There are two different ways to read out the data from the flash:
- * the "IP Command Read" and the "AHB Command Read".
- *
- * The IC guy suggests we use the "AHB Command Read" which is faster
- * then the "IP Command Read". (What's more is that there is a bug in
- * the "IP Command Read" in the Vybrid.)
- *
- * After we set up the registers for the "AHB Command Read", we can use
- * the memcpy to read the data directly. A "missed" access to the buffer
- * causes the controller to clear the buffer, and use the sequence pointed
- * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
- */
-static int fsl_qspi_init_ahb_read(struct fsl_qspi *q)
-{
- void __iomem *base = q->iobase;
- int seqid;
-
- /* AHB configuration for access buffer 0/1/2 .*/
- qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
- qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
- qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
- /*
- * Set ADATSZ with the maximum AHB buffer size to improve the
- * read performance.
- */
- qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
- ((q->devtype_data->ahb_buf_size / 8)
- << QUADSPI_BUF3CR_ADATSZ_SHIFT),
- base + QUADSPI_BUF3CR);
-
- /* We only use the buffer3 */
- qspi_writel(q, 0, base + QUADSPI_BUF0IND);
- qspi_writel(q, 0, base + QUADSPI_BUF1IND);
- qspi_writel(q, 0, base + QUADSPI_BUF2IND);
-
- /* Set the default lut sequence for AHB Read. */
- seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode);
- if (seqid < 0)
- return seqid;
-
- qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
- q->iobase + QUADSPI_BFGENCR);
-
- return 0;
-}
-
-/* This function was used to prepare and enable QSPI clock */
-static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q)
-{
- int ret;
-
- ret = clk_prepare_enable(q->clk_en);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(q->clk);
- if (ret) {
- clk_disable_unprepare(q->clk_en);
- return ret;
- }
-
- if (needs_wakeup_wait_mode(q))
- pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0);
-
- return 0;
-}
-
-/* This function was used to disable and unprepare QSPI clock */
-static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q)
-{
- if (needs_wakeup_wait_mode(q))
- pm_qos_remove_request(&q->pm_qos_req);
-
- clk_disable_unprepare(q->clk);
- clk_disable_unprepare(q->clk_en);
-
-}
-
-/* We use this function to do some basic init for spi_nor_scan(). */
-static int fsl_qspi_nor_setup(struct fsl_qspi *q)
-{
- void __iomem *base = q->iobase;
- u32 reg;
- int ret;
-
- /* disable and unprepare clock to avoid glitch pass to controller */
- fsl_qspi_clk_disable_unprep(q);
-
- /* the default frequency, we will change it in the future. */
- ret = clk_set_rate(q->clk, 66000000);
- if (ret)
- return ret;
-
- ret = fsl_qspi_clk_prep_enable(q);
- if (ret)
- return ret;
-
- /* Reset the module */
- qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
- base + QUADSPI_MCR);
- udelay(1);
-
- /* Init the LUT table. */
- fsl_qspi_init_lut(q);
-
- /* Disable the module */
- qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
- base + QUADSPI_MCR);
-
- reg = qspi_readl(q, base + QUADSPI_SMPR);
- qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK
- | QUADSPI_SMPR_FSPHS_MASK
- | QUADSPI_SMPR_HSENA_MASK
- | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
-
- /* Enable the module */
- qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
- base + QUADSPI_MCR);
-
- /* clear all interrupt status */
- qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR);
-
- /* enable the interrupt */
- qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
-
- return 0;
-}
-
-static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
-{
- unsigned long rate = q->clk_rate;
- int ret;
-
- if (needs_4x_clock(q))
- rate *= 4;
-
- /* disable and unprepare clock to avoid glitch pass to controller */
- fsl_qspi_clk_disable_unprep(q);
-
- ret = clk_set_rate(q->clk, rate);
- if (ret)
- return ret;
-
- ret = fsl_qspi_clk_prep_enable(q);
- if (ret)
- return ret;
-
- /* Init the LUT table again. */
- fsl_qspi_init_lut(q);
-
- /* Init for AHB read */
- return fsl_qspi_init_ahb_read(q);
-}
-
-static const struct of_device_id fsl_qspi_dt_ids[] = {
- { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, },
- { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, },
- { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, },
- { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
- { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, },
- { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);
-
-static void fsl_qspi_set_base_addr(struct fsl_qspi *q, struct spi_nor *nor)
-{
- q->chip_base_addr = q->nor_size * (nor - q->nor);
-}
-
-static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
-{
- int ret;
- struct fsl_qspi *q = nor->priv;
-
- ret = fsl_qspi_runcmd(q, opcode, 0, len);
- if (ret)
- return ret;
-
- fsl_qspi_read_data(q, len, buf);
- return 0;
-}
-
-static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
-{
- struct fsl_qspi *q = nor->priv;
- int ret;
-
- if (!buf) {
- ret = fsl_qspi_runcmd(q, opcode, 0, 1);
- if (ret)
- return ret;
-
- if (opcode == SPINOR_OP_CHIP_ERASE)
- fsl_qspi_invalid(q);
-
- } else if (len > 0) {
- ret = fsl_qspi_nor_write(q, nor, opcode, 0,
- (u32 *)buf, len);
- if (ret > 0)
- return 0;
- } else {
- dev_err(q->dev, "invalid cmd %d\n", opcode);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static ssize_t fsl_qspi_write(struct spi_nor *nor, loff_t to,
- size_t len, const u_char *buf)
-{
- struct fsl_qspi *q = nor->priv;
- ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to,
- (u32 *)buf, len);
-
- /* invalid the data in the AHB buffer. */
- fsl_qspi_invalid(q);
- return ret;
-}
-
-static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
- size_t len, u_char *buf)
-{
- struct fsl_qspi *q = nor->priv;
- u8 cmd = nor->read_opcode;
-
- /* if necessary,ioremap buffer before AHB read, */
- if (!q->ahb_addr) {
- q->memmap_offs = q->chip_base_addr + from;
- q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP;
-
- q->ahb_addr = ioremap_nocache(
- q->memmap_phy + q->memmap_offs,
- q->memmap_len);
- if (!q->ahb_addr) {
- dev_err(q->dev, "ioremap failed\n");
- return -ENOMEM;
- }
- /* ioremap if the data requested is out of range */
- } else if (q->chip_base_addr + from < q->memmap_offs
- || q->chip_base_addr + from + len >
- q->memmap_offs + q->memmap_len) {
- iounmap(q->ahb_addr);
-
- q->memmap_offs = q->chip_base_addr + from;
- q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP;
- q->ahb_addr = ioremap_nocache(
- q->memmap_phy + q->memmap_offs,
- q->memmap_len);
- if (!q->ahb_addr) {
- dev_err(q->dev, "ioremap failed\n");
- return -ENOMEM;
- }
- }
-
- dev_dbg(q->dev, "cmd [%x],read from %p, len:%zd\n",
- cmd, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
- len);
-
- /* Read out the data directly from the AHB buffer.*/
- memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
- len);
-
- return len;
-}
-
-static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs)
-{
- struct fsl_qspi *q = nor->priv;
- int ret;
-
- dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n",
- nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs);
-
- ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0);
- if (ret)
- return ret;
-
- fsl_qspi_invalid(q);
- return 0;
-}
-
-static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
-{
- struct fsl_qspi *q = nor->priv;
- int ret;
-
- mutex_lock(&q->lock);
-
- ret = fsl_qspi_clk_prep_enable(q);
- if (ret)
- goto err_mutex;
-
- fsl_qspi_set_base_addr(q, nor);
- return 0;
-
-err_mutex:
- mutex_unlock(&q->lock);
- return ret;
-}
-
-static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
-{
- struct fsl_qspi *q = nor->priv;
-
- fsl_qspi_clk_disable_unprep(q);
- mutex_unlock(&q->lock);
-}
-
-static int fsl_qspi_probe(struct platform_device *pdev)
-{
- const struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ_1_1_4 |
- SNOR_HWCAPS_PP,
- };
- struct device_node *np = pdev->dev.of_node;
- struct device *dev = &pdev->dev;
- struct fsl_qspi *q;
- struct resource *res;
- struct spi_nor *nor;
- struct mtd_info *mtd;
- int ret, i = 0;
-
- q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL);
- if (!q)
- return -ENOMEM;
-
- q->nor_num = of_get_child_count(dev->of_node);
- if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP)
- return -ENODEV;
-
- q->dev = dev;
- q->devtype_data = of_device_get_match_data(dev);
- if (!q->devtype_data)
- return -ENODEV;
- platform_set_drvdata(pdev, q);
-
- /* find the resources */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
- q->iobase = devm_ioremap_resource(dev, res);
- if (IS_ERR(q->iobase))
- return PTR_ERR(q->iobase);
-
- q->big_endian = of_property_read_bool(np, "big-endian");
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "QuadSPI-memory");
- if (!devm_request_mem_region(dev, res->start, resource_size(res),
- res->name)) {
- dev_err(dev, "can't request region for resource %pR\n", res);
- return -EBUSY;
- }
-
- q->memmap_phy = res->start;
-
- /* find the clocks */
- q->clk_en = devm_clk_get(dev, "qspi_en");
- if (IS_ERR(q->clk_en))
- return PTR_ERR(q->clk_en);
-
- q->clk = devm_clk_get(dev, "qspi");
- if (IS_ERR(q->clk))
- return PTR_ERR(q->clk);
-
- ret = fsl_qspi_clk_prep_enable(q);
- if (ret) {
- dev_err(dev, "can not enable the clock\n");
- goto clk_failed;
- }
-
- /* find the irq */
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "failed to get the irq: %d\n", ret);
- goto irq_failed;
- }
-
- ret = devm_request_irq(dev, ret,
- fsl_qspi_irq_handler, 0, pdev->name, q);
- if (ret) {
- dev_err(dev, "failed to request irq: %d\n", ret);
- goto irq_failed;
- }
-
- ret = fsl_qspi_nor_setup(q);
- if (ret)
- goto irq_failed;
-
- if (of_get_property(np, "fsl,qspi-has-second-chip", NULL))
- q->has_second_chip = true;
-
- mutex_init(&q->lock);
-
- /* iterate the subnodes. */
- for_each_available_child_of_node(dev->of_node, np) {
- /* skip the holes */
- if (!q->has_second_chip)
- i *= 2;
-
- nor = &q->nor[i];
- mtd = &nor->mtd;
-
- nor->dev = dev;
- spi_nor_set_flash_node(nor, np);
- nor->priv = q;
-
- if (q->nor_num > 1 && !mtd->name) {
- int spiflash_idx;
-
- ret = of_property_read_u32(np, "reg", &spiflash_idx);
- if (!ret) {
- mtd->name = devm_kasprintf(dev, GFP_KERNEL,
- "%s-%d",
- dev_name(dev),
- spiflash_idx);
- if (!mtd->name) {
- ret = -ENOMEM;
- goto mutex_failed;
- }
- } else {
- dev_warn(dev, "reg property is missing\n");
- }
- }
-
- /* fill the hooks */
- nor->read_reg = fsl_qspi_read_reg;
- nor->write_reg = fsl_qspi_write_reg;
- nor->read = fsl_qspi_read;
- nor->write = fsl_qspi_write;
- nor->erase = fsl_qspi_erase;
-
- nor->prepare = fsl_qspi_prep;
- nor->unprepare = fsl_qspi_unprep;
-
- ret = of_property_read_u32(np, "spi-max-frequency",
- &q->clk_rate);
- if (ret < 0)
- goto mutex_failed;
-
- /* set the chip address for READID */
- fsl_qspi_set_base_addr(q, nor);
-
- ret = spi_nor_scan(nor, NULL, &hwcaps);
- if (ret)
- goto mutex_failed;
-
- ret = mtd_device_register(mtd, NULL, 0);
- if (ret)
- goto mutex_failed;
-
- /* Set the correct NOR size now. */
- if (q->nor_size == 0) {
- q->nor_size = mtd->size;
-
- /* Map the SPI NOR to accessiable address */
- fsl_qspi_set_map_addr(q);
- }
-
- /*
- * The TX FIFO is 64 bytes in the Vybrid, but the Page Program
- * may writes 265 bytes per time. The write is working in the
- * unit of the TX FIFO, not in the unit of the SPI NOR's page
- * size.
- *
- * So shrink the spi_nor->page_size if it is larger then the
- * TX FIFO.
- */
- if (nor->page_size > q->devtype_data->txfifo)
- nor->page_size = q->devtype_data->txfifo;
-
- i++;
- }
-
- /* finish the rest init. */
- ret = fsl_qspi_nor_setup_last(q);
- if (ret)
- goto last_init_failed;
-
- fsl_qspi_clk_disable_unprep(q);
- return 0;
-
-last_init_failed:
- for (i = 0; i < q->nor_num; i++) {
- /* skip the holes */
- if (!q->has_second_chip)
- i *= 2;
- mtd_device_unregister(&q->nor[i].mtd);
- }
-mutex_failed:
- mutex_destroy(&q->lock);
-irq_failed:
- fsl_qspi_clk_disable_unprep(q);
-clk_failed:
- dev_err(dev, "Freescale QuadSPI probe failed\n");
- return ret;
-}
-
-static int fsl_qspi_remove(struct platform_device *pdev)
-{
- struct fsl_qspi *q = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < q->nor_num; i++) {
- /* skip the holes */
- if (!q->has_second_chip)
- i *= 2;
- mtd_device_unregister(&q->nor[i].mtd);
- }
-
- /* disable the hardware */
- qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
- qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
-
- mutex_destroy(&q->lock);
-
- if (q->ahb_addr)
- iounmap(q->ahb_addr);
-
- return 0;
-}
-
-static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- return 0;
-}
-
-static int fsl_qspi_resume(struct platform_device *pdev)
-{
- int ret;
- struct fsl_qspi *q = platform_get_drvdata(pdev);
-
- ret = fsl_qspi_clk_prep_enable(q);
- if (ret)
- return ret;
-
- fsl_qspi_nor_setup(q);
- fsl_qspi_set_map_addr(q);
- fsl_qspi_nor_setup_last(q);
-
- fsl_qspi_clk_disable_unprep(q);
-
- return 0;
-}
-
-static struct platform_driver fsl_qspi_driver = {
- .driver = {
- .name = "fsl-quadspi",
- .of_match_table = fsl_qspi_dt_ids,
- },
- .probe = fsl_qspi_probe,
- .remove = fsl_qspi_remove,
- .suspend = fsl_qspi_suspend,
- .resume = fsl_qspi_resume,
-};
-module_platform_driver(fsl_qspi_driver);
-
-MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver");
-MODULE_AUTHOR("Freescale Semiconductor Inc.");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c
index 5442993b71ff..d9eed6844ba1 100644
--- a/drivers/mtd/spi-nor/mtk-quadspi.c
+++ b/drivers/mtd/spi-nor/mtk-quadspi.c
@@ -431,7 +431,8 @@ static int mtk_nor_init(struct mtk_nor *mtk_nor,
struct device_node *flash_node)
{
const struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ_FAST |
+ .mask = SNOR_HWCAPS_READ |
+ SNOR_HWCAPS_READ_FAST |
SNOR_HWCAPS_READ_1_1_2 |
SNOR_HWCAPS_PP,
};
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 6e13bbd1aaa5..fae147452aff 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -68,7 +68,7 @@ enum spi_nor_read_command_index {
SNOR_CMD_READ_4_4_4,
SNOR_CMD_READ_1_4_4_DTR,
- /* Octo SPI */
+ /* Octal SPI */
SNOR_CMD_READ_1_1_8,
SNOR_CMD_READ_1_8_8,
SNOR_CMD_READ_8_8_8,
@@ -85,7 +85,7 @@ enum spi_nor_pp_command_index {
SNOR_CMD_PP_1_4_4,
SNOR_CMD_PP_4_4_4,
- /* Octo SPI */
+ /* Octal SPI */
SNOR_CMD_PP_1_1_8,
SNOR_CMD_PP_1_8_8,
SNOR_CMD_PP_8_8_8,
@@ -278,6 +278,7 @@ struct flash_info {
#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR BIT(14) /* use CLSR command */
+#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */
/* Part specific fixup hooks. */
const struct spi_nor_fixups *fixups;
@@ -398,6 +399,8 @@ static u8 spi_nor_convert_3to4_read(u8 opcode)
{ SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B },
{ SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B },
{ SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B },
+ { SPINOR_OP_READ_1_1_8, SPINOR_OP_READ_1_1_8_4B },
+ { SPINOR_OP_READ_1_8_8, SPINOR_OP_READ_1_8_8_4B },
{ SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B },
{ SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B },
@@ -414,6 +417,8 @@ static u8 spi_nor_convert_3to4_program(u8 opcode)
{ SPINOR_OP_PP, SPINOR_OP_PP_4B },
{ SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B },
{ SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B },
+ { SPINOR_OP_PP_1_1_8, SPINOR_OP_PP_1_1_8_4B },
+ { SPINOR_OP_PP_1_8_8, SPINOR_OP_PP_1_8_8_4B },
};
return spi_nor_convert_opcode(opcode, spi_nor_3to4_program,
@@ -1740,7 +1745,11 @@ static const struct flash_info spi_nor_ids[] = {
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ) },
{ "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) },
+ { "en25qh64", INFO(0x1c7017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ) },
{ "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
{ "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
@@ -1836,6 +1845,8 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
{ "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
+ { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
{ "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) },
{ "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
@@ -1847,6 +1858,8 @@ static const struct flash_info spi_nor_ids[] = {
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
.fixups = &mx25l25635_fixups },
{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
+ { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
@@ -1872,7 +1885,8 @@ static const struct flash_info spi_nor_ids[] = {
/* Micron */
{
"mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
- SECT_4K | USE_FSR | SPI_NOR_4B_OPCODES)
+ SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+ SPI_NOR_4B_OPCODES)
},
/* PMC */
@@ -1885,13 +1899,17 @@ static const struct flash_info spi_nor_ids[] = {
*/
{ "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+ { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+ { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+ { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
@@ -3591,6 +3609,13 @@ static int spi_nor_init_params(struct spi_nor *nor,
SNOR_PROTO_1_1_4);
}
+ if (info->flags & SPI_NOR_OCTAL_READ) {
+ params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
+ spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],
+ 0, 8, SPINOR_OP_READ_1_1_8,
+ SNOR_PROTO_1_1_8);
+ }
+
/* Page Program settings. */
params->hwcaps.mask |= SNOR_HWCAPS_PP;
spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6371958dd170..5e4ca082cfcd 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -145,13 +145,16 @@ config MACVTAP
To compile this driver as a module, choose M here: the module
will be called macvtap.
+config IPVLAN_L3S
+ depends on NETFILTER
+ depends on IPVLAN
+ def_bool y
+ select NET_L3_MASTER_DEV
config IPVLAN
tristate "IP-VLAN support"
depends on INET
depends on IPV6 || !IPV6
- depends on NETFILTER
- select NET_L3_MASTER_DEV
---help---
This allows one to create virtual devices off of a main interface
and packets will be delivered based on the dest L3 (IPv6/IPv4 addr)
@@ -197,9 +200,9 @@ config VXLAN
config GENEVE
tristate "Generic Network Virtualization Encapsulation"
- depends on INET && NET_UDP_TUNNEL
+ depends on INET
depends on IPV6 || !IPV6
- select NET_IP_TUNNEL
+ select NET_UDP_TUNNEL
select GRO_CELLS
---help---
This allows one to create geneve virtual interfaces that provide
@@ -502,7 +505,6 @@ source "drivers/net/hyperv/Kconfig"
config NETDEVSIM
tristate "Simulated networking device"
depends on DEBUG_FS
- depends on MAY_USE_DEVLINK
help
This driver is a developer testing tool and software model that can
be used to test various control path networking APIs, especially
@@ -519,7 +521,7 @@ config NET_FAILOVER
and destroy a failover master netdev and manages a primary and
standby slave netdevs that get registered via the generic failover
infrastructure. This can be used by paravirtual drivers to enable
- an alternate low latency datapath. It alsoenables live migration of
+ an alternate low latency datapath. It also enables live migration of
a VM with direct attached VF by failing over to the paravirtual
datapath when the VF is unplugged.
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index f90bb723985f..b3c63d2f16aa 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -301,7 +301,7 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
dev->irq = cops_irq(ioaddr, board);
if (dev->irq)
break;
- /* No IRQ found on this port, fallthrough */
+ /* fall through - Once no IRQ found on this port. */
case 1:
retval = -EINVAL;
goto err_out;
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7c46d9f4fefd..9274dcc6e9b0 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -31,6 +31,7 @@
#include <net/net_namespace.h>
#include <net/bonding.h>
#include <net/bond_3ad.h>
+#include <net/netlink.h>
/* General definitions */
#define AD_SHORT_TIMEOUT 1
@@ -851,6 +852,9 @@ static int ad_lacpdu_send(struct port *port)
if (!skb)
return -ENOMEM;
+ atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_tx);
+ atomic64_inc(&BOND_AD_INFO(slave->bond).stats.lacpdu_tx);
+
skb->dev = slave->dev;
skb_reset_mac_header(skb);
skb->network_header = skb->mac_header + ETH_HLEN;
@@ -892,6 +896,17 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
if (!skb)
return -ENOMEM;
+ switch (marker->tlv_type) {
+ case AD_MARKER_INFORMATION_SUBTYPE:
+ atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_tx);
+ atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_tx);
+ break;
+ case AD_MARKER_RESPONSE_SUBTYPE:
+ atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_resp_tx);
+ atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_resp_tx);
+ break;
+ }
+
skb_reserve(skb, 16);
skb->dev = slave->dev;
@@ -1086,6 +1101,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
*/
last_state = port->sm_rx_state;
+ if (lacpdu) {
+ atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.lacpdu_rx);
+ atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.lacpdu_rx);
+ }
/* check if state machine should change state */
/* first, check if port was reinitialized */
@@ -1922,6 +1941,9 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
{
struct bond_marker marker;
+ atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_rx);
+ atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_rx);
+
/* copy the received marker data to the response marker */
memcpy(&marker, marker_info, sizeof(struct bond_marker));
/* change the marker subtype to marker response */
@@ -1946,6 +1968,9 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
static void ad_marker_response_received(struct bond_marker *marker,
struct port *port)
{
+ atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_resp_rx);
+ atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_resp_rx);
+
/* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */
}
@@ -2348,66 +2373,68 @@ re_arm:
* bond_3ad_rx_indication - handle a received frame
* @lacpdu: received lacpdu
* @slave: slave struct to work on
- * @length: length of the data received
*
* It is assumed that frames that were sent on this NIC don't returned as new
* received frames (loopback). Since only the payload is given to this
* function, it check for loopback.
*/
-static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
- u16 length)
+static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave)
{
- struct port *port;
+ struct bonding *bond = slave->bond;
int ret = RX_HANDLER_ANOTHER;
+ struct bond_marker *marker;
+ struct port *port;
+ atomic64_t *stat;
- if (length >= sizeof(struct lacpdu)) {
-
- port = &(SLAVE_AD_INFO(slave)->port);
-
- if (!port->slave) {
- net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
- slave->dev->name, slave->bond->dev->name);
- return ret;
- }
+ port = &(SLAVE_AD_INFO(slave)->port);
+ if (!port->slave) {
+ net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
+ slave->dev->name, slave->bond->dev->name);
+ return ret;
+ }
- switch (lacpdu->subtype) {
- case AD_TYPE_LACPDU:
- ret = RX_HANDLER_CONSUMED;
- netdev_dbg(slave->bond->dev,
- "Received LACPDU on port %d slave %s\n",
- port->actor_port_number,
- slave->dev->name);
- /* Protect against concurrent state machines */
- spin_lock(&slave->bond->mode_lock);
- ad_rx_machine(lacpdu, port);
- spin_unlock(&slave->bond->mode_lock);
+ switch (lacpdu->subtype) {
+ case AD_TYPE_LACPDU:
+ ret = RX_HANDLER_CONSUMED;
+ netdev_dbg(slave->bond->dev,
+ "Received LACPDU on port %d slave %s\n",
+ port->actor_port_number, slave->dev->name);
+ /* Protect against concurrent state machines */
+ spin_lock(&slave->bond->mode_lock);
+ ad_rx_machine(lacpdu, port);
+ spin_unlock(&slave->bond->mode_lock);
+ break;
+ case AD_TYPE_MARKER:
+ ret = RX_HANDLER_CONSUMED;
+ /* No need to convert fields to Little Endian since we
+ * don't use the marker's fields.
+ */
+ marker = (struct bond_marker *)lacpdu;
+ switch (marker->tlv_type) {
+ case AD_MARKER_INFORMATION_SUBTYPE:
+ netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
+ port->actor_port_number);
+ ad_marker_info_received(marker, port);
break;
-
- case AD_TYPE_MARKER:
- ret = RX_HANDLER_CONSUMED;
- /* No need to convert fields to Little Endian since we
- * don't use the marker's fields.
- */
-
- switch (((struct bond_marker *)lacpdu)->tlv_type) {
- case AD_MARKER_INFORMATION_SUBTYPE:
- netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
- port->actor_port_number);
- ad_marker_info_received((struct bond_marker *)lacpdu, port);
- break;
-
- case AD_MARKER_RESPONSE_SUBTYPE:
- netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
- port->actor_port_number);
- ad_marker_response_received((struct bond_marker *)lacpdu, port);
- break;
-
- default:
- netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
- port->actor_port_number);
- }
+ case AD_MARKER_RESPONSE_SUBTYPE:
+ netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
+ port->actor_port_number);
+ ad_marker_response_received(marker, port);
+ break;
+ default:
+ netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
+ port->actor_port_number);
+ stat = &SLAVE_AD_INFO(slave)->stats.marker_unknown_rx;
+ atomic64_inc(stat);
+ stat = &BOND_AD_INFO(bond).stats.marker_unknown_rx;
+ atomic64_inc(stat);
}
+ break;
+ default:
+ atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_unknown_rx);
+ atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_unknown_rx);
}
+
return ret;
}
@@ -2643,10 +2670,13 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
return RX_HANDLER_ANOTHER;
lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu);
- if (!lacpdu)
+ if (!lacpdu) {
+ atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_illegal_rx);
+ atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_illegal_rx);
return RX_HANDLER_ANOTHER;
+ }
- return bond_3ad_rx_indication(lacpdu, slave, skb->len);
+ return bond_3ad_rx_indication(lacpdu, slave);
}
/**
@@ -2678,3 +2708,61 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
}
spin_unlock_bh(&bond->mode_lock);
}
+
+size_t bond_3ad_stats_size(void)
+{
+ return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_TX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_UNKNOWN_RX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_ILLEGAL_RX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_TX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_RX */
+ nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_TX */
+ nla_total_size_64bit(sizeof(u64)); /* BOND_3AD_STAT_MARKER_UNKNOWN_RX */
+}
+
+int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats)
+{
+ u64 val;
+
+ val = atomic64_read(&stats->lacpdu_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->lacpdu_tx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_TX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->lacpdu_unknown_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_UNKNOWN_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->lacpdu_illegal_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_ILLEGAL_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+
+ val = atomic64_read(&stats->marker_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->marker_tx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_TX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->marker_resp_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->marker_resp_tx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_TX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+ val = atomic64_read(&stats->marker_unknown_rx);
+ if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_UNKNOWN_RX, val,
+ BOND_3AD_STAT_PAD))
+ return -EMSGSIZE;
+
+ return 0;
+}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a9d597f28023..b59708c35faf 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -77,7 +77,6 @@
#include <net/pkt_sched.h>
#include <linux/rculist.h>
#include <net/flow_dissector.h>
-#include <net/switchdev.h>
#include <net/bonding.h>
#include <net/bond_3ad.h>
#include <net/bond_alb.h>
@@ -1183,29 +1182,22 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
}
}
- /* Link-local multicast packets should be passed to the
- * stack on the link they arrive as well as pass them to the
- * bond-master device. These packets are mostly usable when
- * stack receives it with the link on which they arrive
- * (e.g. LLDP) they also must be available on master. Some of
- * the use cases include (but are not limited to): LLDP agents
- * that must be able to operate both on enslaved interfaces as
- * well as on bonds themselves; linux bridges that must be able
- * to process/pass BPDUs from attached bonds when any kind of
- * STP version is enabled on the network.
+ /*
+ * For packets determined by bond_should_deliver_exact_match() call to
+ * be suppressed we want to make an exception for link-local packets.
+ * This is necessary for e.g. LLDP daemons to be able to monitor
+ * inactive slave links without being forced to bind to them
+ * explicitly.
+ *
+ * At the same time, packets that are passed to the bonding master
+ * (including link-local ones) can have their originating interface
+ * determined via PACKET_ORIGDEV socket option.
*/
- if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) {
- struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
-
- if (nskb) {
- nskb->dev = bond->dev;
- nskb->queue_mapping = 0;
- netif_rx(nskb);
- }
- return RX_HANDLER_PASS;
- }
- if (bond_should_deliver_exact_match(skb, slave, bond))
+ if (bond_should_deliver_exact_match(skb, slave, bond)) {
+ if (is_link_local_ether_addr(eth_hdr(skb)->h_dest))
+ return RX_HANDLER_PASS;
return RX_HANDLER_EXACT;
+ }
skb->dev = bond->dev;
@@ -1963,6 +1955,9 @@ static int __bond_release_one(struct net_device *bond_dev,
if (!bond_has_slaves(bond)) {
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
+ bond->nest_level = SINGLE_DEPTH_NESTING;
+ } else {
+ bond->nest_level = dev_get_nest_level(bond_dev) + 1;
}
unblock_netpoll_tx();
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 6b9ad8673218..b286f591242e 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -675,6 +675,71 @@ nla_put_failure:
return -EMSGSIZE;
}
+static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr)
+{
+ switch (attr) {
+ case IFLA_STATS_LINK_XSTATS:
+ case IFLA_STATS_LINK_XSTATS_SLAVE:
+ break;
+ default:
+ return 0;
+ }
+
+ return bond_3ad_stats_size() + nla_total_size(0);
+}
+
+static int bond_fill_linkxstats(struct sk_buff *skb,
+ const struct net_device *dev,
+ int *prividx, int attr)
+{
+ struct nlattr *nla __maybe_unused;
+ struct slave *slave = NULL;
+ struct nlattr *nest, *nest2;
+ struct bonding *bond;
+
+ switch (attr) {
+ case IFLA_STATS_LINK_XSTATS:
+ bond = netdev_priv(dev);
+ break;
+ case IFLA_STATS_LINK_XSTATS_SLAVE:
+ slave = bond_slave_get_rtnl(dev);
+ if (!slave)
+ return 0;
+ bond = slave->bond;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ nest = nla_nest_start(skb, LINK_XSTATS_TYPE_BOND);
+ if (!nest)
+ return -EMSGSIZE;
+ if (BOND_MODE(bond) == BOND_MODE_8023AD) {
+ struct bond_3ad_stats *stats;
+
+ if (slave)
+ stats = &SLAVE_AD_INFO(slave)->stats;
+ else
+ stats = &BOND_AD_INFO(bond).stats;
+
+ nest2 = nla_nest_start(skb, BOND_XSTATS_3AD);
+ if (!nest2) {
+ nla_nest_end(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ if (bond_3ad_stats_fill(skb, stats)) {
+ nla_nest_cancel(skb, nest2);
+ nla_nest_end(skb, nest);
+ return -EMSGSIZE;
+ }
+ nla_nest_end(skb, nest2);
+ }
+ nla_nest_end(skb, nest);
+
+ return 0;
+}
+
struct rtnl_link_ops bond_link_ops __read_mostly = {
.kind = "bond",
.priv_size = sizeof(struct bonding),
@@ -689,6 +754,8 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
.get_num_tx_queues = bond_get_num_tx_queues,
.get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
as for TX queues */
+ .fill_linkxstats = bond_fill_linkxstats,
+ .get_linkxstats_size = bond_get_linkxstats_size,
.slave_maxtype = IFLA_BOND_SLAVE_MAX,
.slave_policy = bond_slave_policy,
.slave_changelink = bond_slave_changelink,
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 4d5d01cb8141..da1fc17295d9 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1375,6 +1375,7 @@ static int bond_option_slaves_set(struct bonding *bond,
sscanf(newval->string, "%16s", command); /* IFNAMSIZ*/
ifname = command + 1;
if ((strlen(command) <= 1) ||
+ (command[0] != '+' && command[0] != '-') ||
!dev_valid_name(ifname))
goto err_no_cmd;
@@ -1398,6 +1399,7 @@ static int bond_option_slaves_set(struct bonding *bond,
break;
default:
+ /* should not run here. */
goto err_no_cmd;
}
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index a0f954f36c09..44e6c7b1b222 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -257,10 +257,7 @@ static int handle_tx(struct ser_device *ser)
if (skb->len == 0) {
struct sk_buff *tmp = skb_dequeue(&ser->head);
WARN_ON(tmp != skb);
- if (in_interrupt())
- dev_kfree_skb_irq(skb);
- else
- kfree_skb(skb);
+ dev_consume_skb_any(skb);
}
}
/* Send flow off if queue is empty */
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index d28a1398c091..7608bc3e00df 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -73,35 +73,37 @@ MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment.");
#define LOW_WATER_MARK 100
#define HIGH_WATER_MARK (LOW_WATER_MARK*5)
-#ifdef CONFIG_UML
+#ifndef CONFIG_HAS_DMA
/*
* We sometimes use UML for debugging, but it cannot handle
* dma_alloc_coherent so we have to wrap it.
*/
-static inline void *dma_alloc(dma_addr_t *daddr)
+static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
{
return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL);
}
-static inline void dma_free(void *cpu_addr, dma_addr_t handle)
+static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
+ dma_addr_t handle)
{
kfree(cpu_addr);
}
#else
-static inline void *dma_alloc(dma_addr_t *daddr)
+static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
{
- return dma_alloc_coherent(NULL, SPI_DMA_BUF_LEN, daddr,
+ return dma_alloc_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, daddr,
GFP_KERNEL);
}
-static inline void dma_free(void *cpu_addr, dma_addr_t handle)
+static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
+ dma_addr_t handle)
{
- dma_free_coherent(NULL, SPI_DMA_BUF_LEN, cpu_addr, handle);
+ dma_free_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, cpu_addr, handle);
}
-#endif /* CONFIG_UML */
+#endif /* CONFIG_HAS_DMA */
#ifdef CONFIG_DEBUG_FS
@@ -610,13 +612,13 @@ static int cfspi_init(struct net_device *dev)
}
/* Allocate DMA buffers. */
- cfspi->xfer.va_tx[0] = dma_alloc(&cfspi->xfer.pa_tx[0]);
+ cfspi->xfer.va_tx[0] = dma_alloc(cfspi, &cfspi->xfer.pa_tx[0]);
if (!cfspi->xfer.va_tx[0]) {
res = -ENODEV;
goto err_dma_alloc_tx_0;
}
- cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
+ cfspi->xfer.va_rx = dma_alloc(cfspi, &cfspi->xfer.pa_rx);
if (!cfspi->xfer.va_rx) {
res = -ENODEV;
@@ -665,9 +667,9 @@ static int cfspi_init(struct net_device *dev)
return 0;
err_create_wq:
- dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
+ dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
err_dma_alloc_rx:
- dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
+ dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
err_dma_alloc_tx_0:
return res;
}
@@ -683,8 +685,8 @@ static void cfspi_uninit(struct net_device *dev)
cfspi->ndev = NULL;
/* Free DMA buffers. */
- dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
- dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
+ dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
+ dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
set_bit(SPI_TERMINATE, &cfspi->state);
wake_up_interruptible(&cfspi->wait);
destroy_workqueue(cfspi->wq);
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 3b3f88ffab53..c05e4d50d43d 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
{
struct can_priv *priv = netdev_priv(dev);
- struct sk_buff *skb = priv->echo_skb[idx];
- struct canfd_frame *cf;
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
return NULL;
}
- if (!skb) {
- netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
- __func__, idx);
- return NULL;
- }
+ if (priv->echo_skb[idx]) {
+ /* Using "struct canfd_frame::len" for the frame
+ * length is supported on both CAN and CANFD frames.
+ */
+ struct sk_buff *skb = priv->echo_skb[idx];
+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+ u8 len = cf->len;
- /* Using "struct canfd_frame::len" for the frame
- * length is supported on both CAN and CANFD frames.
- */
- cf = (struct canfd_frame *)skb->data;
- *len_ptr = cf->len;
- priv->echo_skb[idx] = NULL;
+ *len_ptr = len;
+ priv->echo_skb[idx] = NULL;
- return skb;
+ return skb;
+ }
+
+ return NULL;
}
/*
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 0f36eafe3ac1..1c66fb2ad76b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev)
}
} else {
/* clear and invalidate unused mailboxes first */
- for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) {
+ for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) {
mb = flexcan_get_mb(priv, i);
priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
&mb->can_ctrl);
@@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
gpr_np = of_find_node_by_phandle(phandle);
if (!gpr_np) {
dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
- return PTR_ERR(gpr_np);
+ return -ENODEV;
}
priv = netdev_priv(dev);
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 0e4bbdcc614f..0852e5e08177 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -344,7 +344,8 @@ static void b53_set_forwarding(struct b53_device *dev, int enable)
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
}
-static void b53_enable_vlan(struct b53_device *dev, bool enable)
+static void b53_enable_vlan(struct b53_device *dev, bool enable,
+ bool enable_filtering)
{
u8 mgmt, vc0, vc1, vc4 = 0, vc5;
@@ -369,8 +370,13 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID;
vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN;
vc4 &= ~VC4_ING_VID_CHECK_MASK;
- vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
- vc5 |= VC5_DROP_VTABLE_MISS;
+ if (enable_filtering) {
+ vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
+ vc5 |= VC5_DROP_VTABLE_MISS;
+ } else {
+ vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S;
+ vc5 &= ~VC5_DROP_VTABLE_MISS;
+ }
if (is5325(dev))
vc0 &= ~VC0_RESERVED_1;
@@ -420,6 +426,9 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
}
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
+
+ dev->vlan_enabled = enable;
+ dev->vlan_filtering_enabled = enable_filtering;
}
static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100)
@@ -534,7 +543,7 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
}
EXPORT_SYMBOL(b53_enable_port);
-void b53_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
+void b53_disable_port(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;
u8 reg;
@@ -632,25 +641,35 @@ static void b53_enable_mib(struct b53_device *dev)
b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc);
}
+static u16 b53_default_pvid(struct b53_device *dev)
+{
+ if (is5325(dev) || is5365(dev))
+ return 1;
+ else
+ return 0;
+}
+
int b53_configure_vlan(struct dsa_switch *ds)
{
struct b53_device *dev = ds->priv;
struct b53_vlan vl = { 0 };
- int i;
+ int i, def_vid;
+
+ def_vid = b53_default_pvid(dev);
/* clear all vlan entries */
if (is5325(dev) || is5365(dev)) {
- for (i = 1; i < dev->num_vlans; i++)
+ for (i = def_vid; i < dev->num_vlans; i++)
b53_set_vlan_entry(dev, i, &vl);
} else {
b53_do_vlan_op(dev, VTA_CMD_CLEAR);
}
- b53_enable_vlan(dev, false);
+ b53_enable_vlan(dev, false, dev->vlan_filtering_enabled);
b53_for_each_port(dev, i)
b53_write16(dev, B53_VLAN_PAGE,
- B53_VLAN_PORT_DEF_TAG(i), 1);
+ B53_VLAN_PORT_DEF_TAG(i), def_vid);
if (!is5325(dev) && !is5365(dev))
b53_set_jumbo(dev, dev->enable_jumbo, false);
@@ -944,7 +963,7 @@ static int b53_setup(struct dsa_switch *ds)
if (dsa_is_cpu_port(ds, port))
b53_enable_cpu_port(dev, port);
else if (dsa_is_unused_port(ds, port))
- b53_disable_port(ds, port, NULL);
+ b53_disable_port(ds, port);
}
return ret;
@@ -1255,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
{
+ struct b53_device *dev = ds->priv;
+ struct net_device *bridge_dev;
+ unsigned int i;
+ u16 pvid, new_pvid;
+
+ /* Handle the case were multiple bridges span the same switch device
+ * and one of them has a different setting than what is being requested
+ * which would be breaking filtering semantics for any of the other
+ * bridge devices.
+ */
+ b53_for_each_port(dev, i) {
+ bridge_dev = dsa_to_port(ds, i)->bridge_dev;
+ if (bridge_dev &&
+ bridge_dev != dsa_to_port(ds, port)->bridge_dev &&
+ br_vlan_enabled(bridge_dev) != vlan_filtering) {
+ netdev_err(bridge_dev,
+ "VLAN filtering is global to the switch!\n");
+ return -EINVAL;
+ }
+ }
+
+ b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
+ new_pvid = pvid;
+ if (dev->vlan_filtering_enabled && !vlan_filtering) {
+ /* Filtering is currently enabled, use the default PVID since
+ * the bridge does not expect tagging anymore
+ */
+ dev->ports[port].pvid = pvid;
+ new_pvid = b53_default_pvid(dev);
+ } else if (!dev->vlan_filtering_enabled && vlan_filtering) {
+ /* Filtering is currently disabled, restore the previous PVID */
+ new_pvid = dev->ports[port].pvid;
+ }
+
+ if (pvid != new_pvid)
+ b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
+ new_pvid);
+
+ b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);
+
return 0;
}
EXPORT_SYMBOL(b53_vlan_filtering);
@@ -1270,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
if (vlan->vid_end > dev->num_vlans)
return -ERANGE;
- b53_enable_vlan(dev, true);
+ b53_enable_vlan(dev, true, dev->vlan_filtering_enabled);
return 0;
}
@@ -1300,7 +1359,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
b53_fast_age_vlan(dev, vid);
}
- if (pvid) {
+ if (pvid && !dsa_is_cpu_port(ds, port)) {
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
vlan->vid_end);
b53_fast_age_vlan(dev, vid);
@@ -1326,12 +1385,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
vl->members &= ~BIT(port);
- if (pvid == vid) {
- if (is5325(dev) || is5365(dev))
- pvid = 1;
- else
- pvid = 0;
- }
+ if (pvid == vid)
+ pvid = b53_default_pvid(dev);
if (untagged && !dsa_is_cpu_port(ds, port))
vl->untag &= ~(BIT(port));
@@ -1644,10 +1699,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
dev->ports[port].vlan_ctl_mask = pvlan;
- if (is5325(dev) || is5365(dev))
- pvid = 1;
- else
- pvid = 0;
+ pvid = b53_default_pvid(dev);
/* Make this port join all VLANs without VLAN entries */
if (is58xx(dev)) {
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index ec796482792d..e3441dcf2d21 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -91,6 +91,7 @@ enum {
struct b53_port {
u16 vlan_ctl_mask;
struct ethtool_eee eee;
+ u16 pvid;
};
struct b53_vlan {
@@ -137,6 +138,8 @@ struct b53_device {
unsigned int num_vlans;
struct b53_vlan *vlans;
+ bool vlan_enabled;
+ bool vlan_filtering_enabled;
unsigned int num_ports;
struct b53_port *ports;
};
@@ -353,7 +356,7 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port);
void b53_mirror_del(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror);
int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
-void b53_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
+void b53_disable_port(struct dsa_switch *ds, int port);
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port);
void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable);
int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy);
diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
index 90f514252987..d9c56a779c08 100644
--- a/drivers/net/dsa/b53/b53_srab.c
+++ b/drivers/net/dsa/b53/b53_srab.c
@@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev)
/* Clear all pending interrupts */
writel(0xffffffff, priv->regs + B53_SRAB_INTR);
- if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID)
- return;
-
for (i = 0; i < B53_N_PORTS; i++) {
port = &priv->port_intrs[i];
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 361fbde76654..c8e3f05e1d72 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -221,8 +221,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
return b53_enable_port(ds, port, phy);
}
-static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+static void bcm_sf2_port_disable(struct dsa_switch *ds, int port)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
u32 reg;
@@ -241,7 +240,7 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1)
bcm_sf2_gphy_enable_set(ds, false);
- b53_disable_port(ds, port, phy);
+ b53_disable_port(ds, port);
/* Power down the port memory */
reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
@@ -690,9 +689,9 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
* port, the other ones have already been disabled during
* bcm_sf2_sw_setup
*/
- for (port = 0; port < DSA_MAX_PORTS; port++) {
+ for (port = 0; port < ds->num_ports; port++) {
if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port))
- bcm_sf2_port_disable(ds, port, NULL);
+ bcm_sf2_port_disable(ds, port);
}
return 0;
@@ -726,10 +725,11 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
{
struct net_device *p = ds->ports[port].cpu_dp->master;
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- struct ethtool_wolinfo pwol;
+ struct ethtool_wolinfo pwol = { };
/* Get the parent device WoL settings */
- p->ethtool_ops->get_wol(p, &pwol);
+ if (p->ethtool_ops->get_wol)
+ p->ethtool_ops->get_wol(p, &pwol);
/* Advertise the parent device supported settings */
wol->supported = pwol.supported;
@@ -750,9 +750,10 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
struct net_device *p = ds->ports[port].cpu_dp->master;
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
s8 cpu_port = ds->ports[port].cpu_dp->index;
- struct ethtool_wolinfo pwol;
+ struct ethtool_wolinfo pwol = { };
- p->ethtool_ops->get_wol(p, &pwol);
+ if (p->ethtool_ops->get_wol)
+ p->ethtool_ops->get_wol(p, &pwol);
if (wol->wolopts & ~pwol.supported)
return -EINVAL;
@@ -786,7 +787,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
else if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(ds, port);
else
- bcm_sf2_port_disable(ds, port, NULL);
+ bcm_sf2_port_disable(ds, port);
}
b53_configure_vlan(ds);
@@ -894,12 +895,44 @@ static const struct b53_io_ops bcm_sf2_io_ops = {
.write64 = bcm_sf2_core_write64,
};
+static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *data)
+{
+ int cnt = b53_get_sset_count(ds, port, stringset);
+
+ b53_get_strings(ds, port, stringset, data);
+ bcm_sf2_cfp_get_strings(ds, port, stringset,
+ data + cnt * ETH_GSTRING_LEN);
+}
+
+static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *data)
+{
+ int cnt = b53_get_sset_count(ds, port, ETH_SS_STATS);
+
+ b53_get_ethtool_stats(ds, port, data);
+ bcm_sf2_cfp_get_ethtool_stats(ds, port, data + cnt);
+}
+
+static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds, int port,
+ int sset)
+{
+ int cnt = b53_get_sset_count(ds, port, sset);
+
+ if (cnt < 0)
+ return cnt;
+
+ cnt += bcm_sf2_cfp_get_sset_count(ds, port, sset);
+
+ return cnt;
+}
+
static const struct dsa_switch_ops bcm_sf2_ops = {
.get_tag_protocol = b53_get_tag_protocol,
.setup = bcm_sf2_sw_setup,
- .get_strings = b53_get_strings,
- .get_ethtool_stats = b53_get_ethtool_stats,
- .get_sset_count = b53_get_sset_count,
+ .get_strings = bcm_sf2_sw_get_strings,
+ .get_ethtool_stats = bcm_sf2_sw_get_ethtool_stats,
+ .get_sset_count = bcm_sf2_sw_get_sset_count,
.get_ethtool_phy_stats = b53_get_ethtool_phy_stats,
.get_phy_flags = bcm_sf2_sw_get_phy_flags,
.phylink_validate = bcm_sf2_sw_validate,
@@ -1062,7 +1095,6 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, priv);
spin_lock_init(&priv->indir_lock);
- mutex_init(&priv->stats_mutex);
mutex_init(&priv->cfp.lock);
INIT_LIST_HEAD(&priv->cfp.rules_list);
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index faaef320ec48..eb3655bea467 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -87,9 +87,6 @@ struct bcm_sf2_priv {
/* Backing b53_device */
struct b53_device *dev;
- /* Mutex protecting access to the MIB counters */
- struct mutex stats_mutex;
-
struct bcm_sf2_hw_params hw_params;
struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS];
@@ -216,5 +213,10 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv);
void bcm_sf2_cfp_exit(struct dsa_switch *ds);
int bcm_sf2_cfp_resume(struct dsa_switch *ds);
+void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *data);
+void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *data);
+int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset);
#endif /* __BCM_SF2_H */
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index e14663ab6dbc..e6234d209787 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include <net/dsa.h>
#include <linux/bitmap.h>
+#include <net/flow_offload.h>
#include "bcm_sf2.h"
#include "bcm_sf2_regs.h"
@@ -212,6 +213,7 @@ static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv)
static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
unsigned int rule_index,
+ int src_port,
unsigned int port_num,
unsigned int queue_num,
bool fwd_map_change)
@@ -229,6 +231,10 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
else
reg = 0;
+ /* Enable looping back to the original port */
+ if (src_port == port_num)
+ reg |= LOOP_BK_EN;
+
core_writel(priv, reg, CORE_ACT_POL_DATA0);
/* Set classification ID that needs to be put in Broadcom tag */
@@ -257,7 +263,8 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
}
static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
- struct ethtool_tcpip4_spec *v4_spec,
+ struct flow_dissector_key_ipv4_addrs *addrs,
+ struct flow_dissector_key_ports *ports,
unsigned int slice_num,
bool mask)
{
@@ -278,7 +285,7 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
* UDF_n_A6 [23:8]
* UDF_n_A5 [7:0]
*/
- reg = be16_to_cpu(v4_spec->pdst) >> 8;
+ reg = be16_to_cpu(ports->dst) >> 8;
if (mask)
offset = CORE_CFP_MASK_PORT(3);
else
@@ -289,9 +296,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
* UDF_n_A4 [23:8]
* UDF_n_A3 [7:0]
*/
- reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 |
- (u32)be16_to_cpu(v4_spec->psrc) << 8 |
- (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8;
+ reg = (be16_to_cpu(ports->dst) & 0xff) << 24 |
+ (u32)be16_to_cpu(ports->src) << 8 |
+ (be32_to_cpu(addrs->dst) & 0x0000ff00) >> 8;
if (mask)
offset = CORE_CFP_MASK_PORT(2);
else
@@ -302,9 +309,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
* UDF_n_A2 [23:8]
* UDF_n_A1 [7:0]
*/
- reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 |
- (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 |
- (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8;
+ reg = (u32)(be32_to_cpu(addrs->dst) & 0xff) << 24 |
+ (u32)(be32_to_cpu(addrs->dst) >> 16) << 8 |
+ (be32_to_cpu(addrs->src) & 0x0000ff00) >> 8;
if (mask)
offset = CORE_CFP_MASK_PORT(1);
else
@@ -317,8 +324,8 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
* Slice ID [3:2]
* Slice valid [1:0]
*/
- reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 |
- (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 |
+ reg = (u32)(be32_to_cpu(addrs->src) & 0xff) << 24 |
+ (u32)(be32_to_cpu(addrs->src) >> 16) << 8 |
SLICE_NUM(slice_num) | SLICE_VALID;
if (mask)
offset = CORE_CFP_MASK_PORT(0);
@@ -332,9 +339,13 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
unsigned int queue_num,
struct ethtool_rx_flow_spec *fs)
{
- struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
+ struct ethtool_rx_flow_spec_input input = {};
const struct cfp_udf_layout *layout;
unsigned int slice_num, rule_index;
+ struct ethtool_rx_flow_rule *flow;
+ struct flow_match_ipv4_addrs ipv4;
+ struct flow_match_ports ports;
+ struct flow_match_ip ip;
u8 ip_proto, ip_frag;
u8 num_udf;
u32 reg;
@@ -343,13 +354,9 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
switch (fs->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
ip_proto = IPPROTO_TCP;
- v4_spec = &fs->h_u.tcp_ip4_spec;
- v4_m_spec = &fs->m_u.tcp_ip4_spec;
break;
case UDP_V4_FLOW:
ip_proto = IPPROTO_UDP;
- v4_spec = &fs->h_u.udp_ip4_spec;
- v4_m_spec = &fs->m_u.udp_ip4_spec;
break;
default:
return -EINVAL;
@@ -367,11 +374,22 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
if (rule_index > bcm_sf2_cfp_rule_size(priv))
return -ENOSPC;
+ input.fs = fs;
+ flow = ethtool_rx_flow_rule_create(&input);
+ if (IS_ERR(flow))
+ return PTR_ERR(flow);
+
+ flow_rule_match_ipv4_addrs(flow->rule, &ipv4);
+ flow_rule_match_ports(flow->rule, &ports);
+ flow_rule_match_ip(flow->rule, &ip);
+
layout = &udf_tcpip4_layout;
/* We only use one UDF slice for now */
slice_num = bcm_sf2_get_slice_number(layout, 0);
- if (slice_num == UDF_NUM_SLICES)
- return -EINVAL;
+ if (slice_num == UDF_NUM_SLICES) {
+ ret = -EINVAL;
+ goto out_err_flow_rule;
+ }
num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
@@ -398,7 +416,7 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
* Reserved [1]
* UDF_Valid[8] [0]
*/
- core_writel(priv, v4_spec->tos << IPTOS_SHIFT |
+ core_writel(priv, ip.key->tos << IPTOS_SHIFT |
ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
udf_upper_bits(num_udf),
CORE_CFP_DATA_PORT(6));
@@ -417,8 +435,8 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
/* Program the match and the mask */
- bcm_sf2_cfp_slice_ipv4(priv, v4_spec, slice_num, false);
- bcm_sf2_cfp_slice_ipv4(priv, v4_m_spec, SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv4(priv, ipv4.key, ports.key, slice_num, false);
+ bcm_sf2_cfp_slice_ipv4(priv, ipv4.mask, ports.mask, SLICE_NUM_MASK, true);
/* Insert into TCAM now */
bcm_sf2_cfp_rule_addr_set(priv, rule_index);
@@ -426,14 +444,14 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
if (ret) {
pr_err("TCAM entry at addr %d failed\n", rule_index);
- return ret;
+ goto out_err_flow_rule;
}
/* Insert into Action and policer RAMs now */
- ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port_num,
+ ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port, port_num,
queue_num, true);
if (ret)
- return ret;
+ goto out_err_flow_rule;
/* Turn on CFP for this rule now */
reg = core_readl(priv, CORE_CFP_CTL_REG);
@@ -446,6 +464,10 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
fs->location = rule_index;
return 0;
+
+out_err_flow_rule:
+ ethtool_rx_flow_rule_destroy(flow);
+ return ret;
}
static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
@@ -581,9 +603,12 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
unsigned int queue_num,
struct ethtool_rx_flow_spec *fs)
{
- struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec;
+ struct ethtool_rx_flow_spec_input input = {};
unsigned int slice_num, rule_index[2];
const struct cfp_udf_layout *layout;
+ struct ethtool_rx_flow_rule *flow;
+ struct flow_match_ipv6_addrs ipv6;
+ struct flow_match_ports ports;
u8 ip_proto, ip_frag;
int ret = 0;
u8 num_udf;
@@ -592,13 +617,9 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
switch (fs->flow_type & ~FLOW_EXT) {
case TCP_V6_FLOW:
ip_proto = IPPROTO_TCP;
- v6_spec = &fs->h_u.tcp_ip6_spec;
- v6_m_spec = &fs->m_u.tcp_ip6_spec;
break;
case UDP_V6_FLOW:
ip_proto = IPPROTO_UDP;
- v6_spec = &fs->h_u.udp_ip6_spec;
- v6_m_spec = &fs->m_u.udp_ip6_spec;
break;
default:
return -EINVAL;
@@ -645,6 +666,15 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
goto out_err;
}
+ input.fs = fs;
+ flow = ethtool_rx_flow_rule_create(&input);
+ if (IS_ERR(flow)) {
+ ret = PTR_ERR(flow);
+ goto out_err;
+ }
+ flow_rule_match_ipv6_addrs(flow->rule, &ipv6);
+ flow_rule_match_ports(flow->rule, &ports);
+
/* Apply the UDF layout for this filter */
bcm_sf2_cfp_udf_set(priv, layout, slice_num);
@@ -688,10 +718,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
/* Slice the IPv6 source address and port */
- bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc,
- slice_num, false);
- bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc,
- SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->src.in6_u.u6_addr32,
+ ports.key->src, slice_num, false);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->src.in6_u.u6_addr32,
+ ports.mask->src, SLICE_NUM_MASK, true);
/* Insert into TCAM now because we need to insert a second rule */
bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]);
@@ -699,20 +729,20 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
if (ret) {
pr_err("TCAM entry at addr %d failed\n", rule_index[0]);
- goto out_err;
+ goto out_err_flow_rule;
}
/* Insert into Action and policer RAMs now */
- ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num,
+ ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port, port_num,
queue_num, false);
if (ret)
- goto out_err;
+ goto out_err_flow_rule;
/* Now deal with the second slice to chain this rule */
slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1);
if (slice_num == UDF_NUM_SLICES) {
ret = -EINVAL;
- goto out_err;
+ goto out_err_flow_rule;
}
num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
@@ -748,10 +778,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
/* Mask all */
core_writel(priv, 0, CORE_CFP_MASK_PORT(5));
- bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num,
- false);
- bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst,
- SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->dst.in6_u.u6_addr32,
+ ports.key->dst, slice_num, false);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->dst.in6_u.u6_addr32,
+ ports.key->dst, SLICE_NUM_MASK, true);
/* Insert into TCAM now */
bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]);
@@ -759,16 +789,16 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
if (ret) {
pr_err("TCAM entry at addr %d failed\n", rule_index[1]);
- goto out_err;
+ goto out_err_flow_rule;
}
/* Insert into Action and policer RAMs now, set chain ID to
* the one we are chained to
*/
- ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num,
+ ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port, port_num,
queue_num, true);
if (ret)
- goto out_err;
+ goto out_err_flow_rule;
/* Turn on CFP for this rule now */
reg = core_readl(priv, CORE_CFP_CTL_REG);
@@ -784,6 +814,8 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
return ret;
+out_err_flow_rule:
+ ethtool_rx_flow_rule_destroy(flow);
out_err:
clear_bit(rule_index[1], priv->cfp.used);
return ret;
@@ -1169,3 +1201,91 @@ int bcm_sf2_cfp_resume(struct dsa_switch *ds)
return ret;
}
+
+static const struct bcm_sf2_cfp_stat {
+ unsigned int offset;
+ unsigned int ram_loc;
+ const char *name;
+} bcm_sf2_cfp_stats[] = {
+ {
+ .offset = CORE_STAT_GREEN_CNTR,
+ .ram_loc = GREEN_STAT_RAM,
+ .name = "Green"
+ },
+ {
+ .offset = CORE_STAT_YELLOW_CNTR,
+ .ram_loc = YELLOW_STAT_RAM,
+ .name = "Yellow"
+ },
+ {
+ .offset = CORE_STAT_RED_CNTR,
+ .ram_loc = RED_STAT_RAM,
+ .name = "Red"
+ },
+};
+
+void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *data)
+{
+ struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
+ char buf[ETH_GSTRING_LEN];
+ unsigned int i, j, iter;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 1; i < priv->num_cfp_rules; i++) {
+ for (j = 0; j < s; j++) {
+ snprintf(buf, sizeof(buf),
+ "CFP%03d_%sCntr",
+ i, bcm_sf2_cfp_stats[j].name);
+ iter = (i - 1) * s + j;
+ strlcpy(data + iter * ETH_GSTRING_LEN,
+ buf, ETH_GSTRING_LEN);
+ }
+ }
+}
+
+void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *data)
+{
+ struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
+ const struct bcm_sf2_cfp_stat *stat;
+ unsigned int i, j, iter;
+ struct cfp_rule *rule;
+ int ret;
+
+ mutex_lock(&priv->cfp.lock);
+ for (i = 1; i < priv->num_cfp_rules; i++) {
+ rule = bcm_sf2_cfp_rule_find(priv, port, i);
+ if (!rule)
+ continue;
+
+ for (j = 0; j < s; j++) {
+ stat = &bcm_sf2_cfp_stats[j];
+
+ bcm_sf2_cfp_rule_addr_set(priv, i);
+ ret = bcm_sf2_cfp_op(priv, stat->ram_loc | OP_SEL_READ);
+ if (ret)
+ continue;
+
+ iter = (i - 1) * s + j;
+ data[iter] = core_readl(priv, stat->offset);
+ }
+
+ }
+ mutex_unlock(&priv->cfp.lock);
+}
+
+int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+ struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+ /* 3 counters per CFP rules */
+ return (priv->num_cfp_rules - 1) * ARRAY_SIZE(bcm_sf2_cfp_stats);
+}
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index 0a1e530d52b7..67f056206f37 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -400,6 +400,10 @@ enum bcm_sf2_reg_offs {
#define CORE_RATE_METER6 0x281e0
#define CIR_REF_CNT_MASK 0x7ffff
+#define CORE_STAT_GREEN_CNTR 0x28200
+#define CORE_STAT_YELLOW_CNTR 0x28210
+#define CORE_STAT_RED_CNTR 0x28220
+
#define CORE_CFP_CTL_REG 0x28400
#define CFP_EN_MAP_MASK 0x1ff
diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c
index 816f34d64736..17482ae09aa5 100644
--- a/drivers/net/dsa/dsa_loop.c
+++ b/drivers/net/dsa/dsa_loop.c
@@ -343,7 +343,7 @@ static int __init dsa_loop_init(void)
unsigned int i;
for (i = 0; i < NUM_FIXED_PHYS; i++)
- phydevs[i] = fixed_phy_register(PHY_POLL, &status, -1, NULL);
+ phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
return mdio_driver_register(&dsa_loop_drv);
}
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index b4f6e1a67dd9..2ffab7ee3d80 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1091,8 +1091,7 @@ static int lan9303_port_enable(struct dsa_switch *ds, int port,
return lan9303_enable_processing_port(chip, port);
}
-static void lan9303_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+static void lan9303_port_disable(struct dsa_switch *ds, int port)
{
struct lan9303 *chip = ds->priv;
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index 693a67f45bef..d8328866908c 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -480,8 +480,7 @@ static int gswip_port_enable(struct dsa_switch *ds, int port,
return 0;
}
-static void gswip_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+static void gswip_port_disable(struct dsa_switch *ds, int port)
{
struct gswip_priv *priv = ds->priv;
@@ -549,7 +548,7 @@ static int gswip_setup(struct dsa_switch *ds)
/* disable port fetch/store dma on all ports */
for (i = 0; i < priv->hw_info->max_ports; i++)
- gswip_port_disable(ds, i, NULL);
+ gswip_port_disable(ds, i);
/* enable Switch */
gswip_mdio_mask(priv, 0, GSWIP_MDIO_GLOB_ENABLE, GSWIP_MDIO_GLOB);
@@ -1069,10 +1068,10 @@ static int gswip_probe(struct platform_device *pdev)
version = gswip_switch_r(priv, GSWIP_VERSION);
/* bring up the mdio bus */
- gphy_fw_np = of_find_compatible_node(pdev->dev.of_node, NULL,
- "lantiq,gphy-fw");
+ gphy_fw_np = of_get_compatible_child(dev->of_node, "lantiq,gphy-fw");
if (gphy_fw_np) {
err = gswip_gphy_fw_list(priv, gphy_fw_np, version);
+ of_node_put(gphy_fw_np);
if (err) {
dev_err(dev, "gphy fw probe failed\n");
return err;
@@ -1080,13 +1079,12 @@ static int gswip_probe(struct platform_device *pdev)
}
/* bring up the mdio bus */
- mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL,
- "lantiq,xrx200-mdio");
+ mdio_np = of_get_compatible_child(dev->of_node, "lantiq,xrx200-mdio");
if (mdio_np) {
err = gswip_mdio(priv, mdio_np);
if (err) {
dev_err(dev, "mdio probe failed\n");
- goto gphy_fw;
+ goto put_mdio_node;
}
}
@@ -1099,7 +1097,7 @@ static int gswip_probe(struct platform_device *pdev)
dev_err(dev, "wrong CPU port defined, HW only supports port: %i",
priv->hw_info->cpu_port);
err = -EINVAL;
- goto mdio_bus;
+ goto disable_switch;
}
platform_set_drvdata(pdev, priv);
@@ -1109,10 +1107,14 @@ static int gswip_probe(struct platform_device *pdev)
(version & GSWIP_VERSION_MOD_MASK) >> GSWIP_VERSION_MOD_SHIFT);
return 0;
+disable_switch:
+ gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
+ dsa_unregister_switch(priv->ds);
mdio_bus:
if (mdio_np)
mdiobus_unregister(priv->ds->slave_mii_bus);
-gphy_fw:
+put_mdio_node:
+ of_node_put(mdio_np);
for (i = 0; i < priv->num_gphy_fw; i++)
gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
return err;
@@ -1123,16 +1125,15 @@ static int gswip_remove(struct platform_device *pdev)
struct gswip_priv *priv = platform_get_drvdata(pdev);
int i;
- if (!priv)
- return 0;
-
/* disable the switch */
gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
dsa_unregister_switch(priv->ds);
- if (priv->ds->slave_mii_bus)
+ if (priv->ds->slave_mii_bus) {
mdiobus_unregister(priv->ds->slave_mii_bus);
+ of_node_put(priv->ds->slave_mii_bus->dev.of_node);
+ }
for (i = 0; i < priv->num_gphy_fw; i++)
gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
@@ -1162,6 +1163,12 @@ static struct platform_driver gswip_driver = {
module_platform_driver(gswip_driver);
+MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin");
+MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin");
+MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin");
+MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin");
+MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin");
+MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin");
MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
MODULE_DESCRIPTION("Lantiq / Intel GSWIP driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 89ed059bb576..f16e1d7d8615 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -2,24 +2,26 @@
/*
* Microchip KSZ9477 switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/iopoll.h>
#include <linux/platform_data/microchip-ksz.h>
#include <linux/phy.h>
-#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <net/dsa.h>
#include <net/switchdev.h>
#include "ksz_priv.h"
-#include "ksz_common.h"
#include "ksz9477_reg.h"
+#include "ksz_common.h"
+
+/* Used with variable features to indicate capabilities. */
+#define GBIT_SUPPORT BIT(0)
+#define NEW_XMII BIT(1)
+#define IS_9893 BIT(2)
static const struct {
int index;
@@ -259,10 +261,84 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
return 0;
}
+static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
+ u64 *cnt)
+{
+ struct ksz_poll_ctx ctx = {
+ .dev = dev,
+ .port = port,
+ .offset = REG_PORT_MIB_CTRL_STAT__4,
+ };
+ struct ksz_port *p = &dev->ports[port];
+ u32 data;
+ int ret;
+
+ /* retain the flush/freeze bit */
+ data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ data |= MIB_COUNTER_READ;
+ data |= (addr << MIB_COUNTER_INDEX_S);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
+
+ ret = readx_poll_timeout(ksz_pread32_poll, &ctx, data,
+ !(data & MIB_COUNTER_READ), 10, 1000);
+
+ /* failed to read MIB. get out of loop */
+ if (ret < 0) {
+ dev_dbg(dev->dev, "Failed to get MIB\n");
+ return;
+ }
+
+ /* count resets upon read */
+ ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
+ *cnt += data;
+}
+
+static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+ u64 *dropped, u64 *cnt)
+{
+ addr = ksz9477_mib_names[addr].index;
+ ksz9477_r_mib_cnt(dev, port, addr, cnt);
+}
+
+static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
+{
+ u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ struct ksz_port *p = &dev->ports[port];
+
+ /* enable/disable the port for flush/freeze function */
+ mutex_lock(&p->mib.cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
+
+ /* used by MIB counter reading code to know freeze is enabled */
+ p->freeze = freeze;
+ mutex_unlock(&p->mib.cnt_mutex);
+}
+
+static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+
+ /* flush all enabled port MIB counters */
+ mutex_lock(&mib->cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
+ MIB_COUNTER_FLUSH_FREEZE);
+ ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
+ mutex_unlock(&mib->cnt_mutex);
+
+ mib->cnt_ptr = 0;
+ memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
+}
+
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
int port)
{
- return DSA_TAG_PROTO_KSZ9477;
+ enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477;
+ struct ksz_device *dev = ds->priv;
+
+ if (dev->features & IS_9893)
+ proto = DSA_TAG_PROTO_KSZ9893;
+ return proto;
}
static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
@@ -323,6 +399,10 @@ static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
/* No real PHY after this. */
if (addr >= dev->phy_port_cnt)
return 0;
+
+ /* No gigabit support. Do not write to this register. */
+ if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
+ return 0;
ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
return 0;
@@ -342,47 +422,6 @@ static void ksz9477_get_strings(struct dsa_switch *ds, int port,
}
}
-static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *buf)
-{
- struct ksz_device *dev = ds->priv;
- int i;
- u32 data;
- int timeout;
-
- mutex_lock(&dev->stats_mutex);
-
- for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
- data = MIB_COUNTER_READ;
- data |= ((ksz9477_mib_names[i].index & 0xFF) <<
- MIB_COUNTER_INDEX_S);
- ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
-
- timeout = 1000;
- do {
- ksz_pread32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
- &data);
- usleep_range(1, 10);
- if (!(data & MIB_COUNTER_READ))
- break;
- } while (timeout-- > 0);
-
- /* failed to read MIB. get out of loop */
- if (!timeout) {
- dev_dbg(dev->dev, "Failed to get MIB\n");
- break;
- }
-
- /* count resets upon read */
- ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
-
- dev->mib_value[i] += (uint64_t)data;
- buf[i] = dev->mib_value[i];
- }
-
- mutex_unlock(&dev->stats_mutex);
-}
-
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
u8 member)
{
@@ -397,6 +436,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
struct ksz_port *p = &dev->ports[port];
u8 data;
int member = -1;
+ int forward = dev->member;
ksz_pread8(dev, port, P_STP_CTRL, &data);
data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
@@ -424,12 +464,14 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
break;
member = dev->host_mask | p->vid_member;
+ mutex_lock(&dev->dev_mutex);
/* Port is a member of a bridge. */
if (dev->br_member & (1 << port)) {
dev->member |= (1 << port);
member = dev->member;
}
+ mutex_unlock(&dev->dev_mutex);
break;
case BR_STATE_BLOCKING:
data |= PORT_LEARN_DISABLE;
@@ -444,6 +486,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
ksz_pwrite8(dev, port, P_STP_CTRL, data);
p->stp_state = state;
+ mutex_lock(&dev->dev_mutex);
if (data & PORT_RX_ENABLE)
dev->rx_ports |= (1 << port);
else
@@ -464,10 +507,11 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
}
/* When topology has changed the function ksz_update_port_member
- * should be called to modify port forwarding behavior. However
- * as the offload_fwd_mark indication cannot be reported here
- * the switch forwarding function is not enabled.
+ * should be called to modify port forwarding behavior.
*/
+ if (forward != dev->member)
+ ksz_update_port_member(dev, port);
+ mutex_unlock(&dev->dev_mutex);
}
static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
@@ -965,6 +1009,161 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
PORT_MIRROR_SNIFFER, false);
}
+static void ksz9477_phy_setup(struct ksz_device *dev, int port,
+ struct phy_device *phy)
+{
+ /* Only apply to port with PHY. */
+ if (port >= dev->phy_port_cnt)
+ return;
+
+ /* The MAC actually cannot run in 1000 half-duplex mode. */
+ phy_remove_link_mode(phy,
+ ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+
+ /* PHY does not support gigabit. */
+ if (!(dev->features & GBIT_SUPPORT))
+ phy_remove_link_mode(phy,
+ ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
+}
+
+static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
+{
+ bool gbit;
+
+ if (dev->features & NEW_XMII)
+ gbit = !(data & PORT_MII_NOT_1GBIT);
+ else
+ gbit = !!(data & PORT_MII_1000MBIT_S1);
+ return gbit;
+}
+
+static void ksz9477_set_gbit(struct ksz_device *dev, bool gbit, u8 *data)
+{
+ if (dev->features & NEW_XMII) {
+ if (gbit)
+ *data &= ~PORT_MII_NOT_1GBIT;
+ else
+ *data |= PORT_MII_NOT_1GBIT;
+ } else {
+ if (gbit)
+ *data |= PORT_MII_1000MBIT_S1;
+ else
+ *data &= ~PORT_MII_1000MBIT_S1;
+ }
+}
+
+static int ksz9477_get_xmii(struct ksz_device *dev, u8 data)
+{
+ int mode;
+
+ if (dev->features & NEW_XMII) {
+ switch (data & PORT_MII_SEL_M) {
+ case PORT_MII_SEL:
+ mode = 0;
+ break;
+ case PORT_RMII_SEL:
+ mode = 1;
+ break;
+ case PORT_GMII_SEL:
+ mode = 2;
+ break;
+ default:
+ mode = 3;
+ }
+ } else {
+ switch (data & PORT_MII_SEL_M) {
+ case PORT_MII_SEL_S1:
+ mode = 0;
+ break;
+ case PORT_RMII_SEL_S1:
+ mode = 1;
+ break;
+ case PORT_GMII_SEL_S1:
+ mode = 2;
+ break;
+ default:
+ mode = 3;
+ }
+ }
+ return mode;
+}
+
+static void ksz9477_set_xmii(struct ksz_device *dev, int mode, u8 *data)
+{
+ u8 xmii;
+
+ if (dev->features & NEW_XMII) {
+ switch (mode) {
+ case 0:
+ xmii = PORT_MII_SEL;
+ break;
+ case 1:
+ xmii = PORT_RMII_SEL;
+ break;
+ case 2:
+ xmii = PORT_GMII_SEL;
+ break;
+ default:
+ xmii = PORT_RGMII_SEL;
+ break;
+ }
+ } else {
+ switch (mode) {
+ case 0:
+ xmii = PORT_MII_SEL_S1;
+ break;
+ case 1:
+ xmii = PORT_RMII_SEL_S1;
+ break;
+ case 2:
+ xmii = PORT_GMII_SEL_S1;
+ break;
+ default:
+ xmii = PORT_RGMII_SEL_S1;
+ break;
+ }
+ }
+ *data &= ~PORT_MII_SEL_M;
+ *data |= xmii;
+}
+
+static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
+{
+ phy_interface_t interface;
+ bool gbit;
+ int mode;
+ u8 data8;
+
+ if (port < dev->phy_port_cnt)
+ return PHY_INTERFACE_MODE_NA;
+ ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
+ gbit = ksz9477_get_gbit(dev, data8);
+ mode = ksz9477_get_xmii(dev, data8);
+ switch (mode) {
+ case 2:
+ interface = PHY_INTERFACE_MODE_GMII;
+ if (gbit)
+ break;
+ case 0:
+ interface = PHY_INTERFACE_MODE_MII;
+ break;
+ case 1:
+ interface = PHY_INTERFACE_MODE_RMII;
+ break;
+ default:
+ interface = PHY_INTERFACE_MODE_RGMII;
+ if (data8 & PORT_RGMII_ID_EG_ENABLE)
+ interface = PHY_INTERFACE_MODE_RGMII_TXID;
+ if (data8 & PORT_RGMII_ID_IG_ENABLE) {
+ interface = PHY_INTERFACE_MODE_RGMII_RXID;
+ if (data8 & PORT_RGMII_ID_EG_ENABLE)
+ interface = PHY_INTERFACE_MODE_RGMII_ID;
+ }
+ break;
+ }
+ return interface;
+}
+
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
u8 data8;
@@ -1011,24 +1210,25 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* configure MAC to 1G & RGMII mode */
ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
- data8 &= ~PORT_MII_NOT_1GBIT;
- data8 &= ~PORT_MII_SEL_M;
switch (dev->interface) {
case PHY_INTERFACE_MODE_MII:
- data8 |= PORT_MII_NOT_1GBIT;
- data8 |= PORT_MII_SEL;
+ ksz9477_set_xmii(dev, 0, &data8);
+ ksz9477_set_gbit(dev, false, &data8);
p->phydev.speed = SPEED_100;
break;
case PHY_INTERFACE_MODE_RMII:
- data8 |= PORT_MII_NOT_1GBIT;
- data8 |= PORT_RMII_SEL;
+ ksz9477_set_xmii(dev, 1, &data8);
+ ksz9477_set_gbit(dev, false, &data8);
p->phydev.speed = SPEED_100;
break;
case PHY_INTERFACE_MODE_GMII:
- data8 |= PORT_GMII_SEL;
+ ksz9477_set_xmii(dev, 2, &data8);
+ ksz9477_set_gbit(dev, true, &data8);
p->phydev.speed = SPEED_1000;
break;
default:
+ ksz9477_set_xmii(dev, 3, &data8);
+ ksz9477_set_gbit(dev, true, &data8);
data8 &= ~PORT_RGMII_ID_IG_ENABLE;
data8 &= ~PORT_RGMII_ID_EG_ENABLE;
if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
@@ -1037,13 +1237,13 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
dev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
data8 |= PORT_RGMII_ID_EG_ENABLE;
- data8 |= PORT_RGMII_SEL;
p->phydev.speed = SPEED_1000;
break;
}
ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8);
p->phydev.duplex = 1;
}
+ mutex_lock(&dev->dev_mutex);
if (cpu_port) {
member = dev->port_mask;
dev->on_ports = dev->host_mask;
@@ -1056,6 +1256,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
if (p->phydev.link)
dev->live_ports |= (1 << port);
}
+ mutex_unlock(&dev->dev_mutex);
ksz9477_cfg_port_member(dev, port, member);
/* clear pending interrupts */
@@ -1073,10 +1274,25 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
for (i = 0; i < dev->port_cnt; i++) {
if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
+ phy_interface_t interface;
+
dev->cpu_port = i;
dev->host_mask = (1 << dev->cpu_port);
dev->port_mask |= dev->host_mask;
+ /* Read from XMII register to determine host port
+ * interface. If set specifically in device tree
+ * note the difference to help debugging.
+ */
+ interface = ksz9477_get_interface(dev, i);
+ if (!dev->interface)
+ dev->interface = interface;
+ if (interface && interface != dev->interface)
+ dev_info(dev->dev,
+ "use %s instead of %s\n",
+ phy_modes(dev->interface),
+ phy_modes(interface));
+
/* enable cpu port */
ksz9477_port_setup(dev, i, true);
p = &dev->ports[dev->cpu_port];
@@ -1130,6 +1346,9 @@ static int ksz9477_setup(struct dsa_switch *ds)
ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY,
true);
+ /* Do not work correctly with tail tagging. */
+ ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false);
+
/* accept packet up to 2000bytes */
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true);
@@ -1140,9 +1359,14 @@ static int ksz9477_setup(struct dsa_switch *ds)
/* queue based egress rate limit */
ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
+ /* enable global MIB counter freeze function */
+ ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
+
/* start switch */
ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
+ ksz_init_mib_timer(dev);
+
return 0;
}
@@ -1151,6 +1375,7 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.setup = ksz9477_setup,
.phy_read = ksz9477_phy_read16,
.phy_write = ksz9477_phy_write16,
+ .adjust_link = ksz_adjust_link,
.port_enable = ksz_enable_port,
.port_disable = ksz_disable_port,
.get_strings = ksz9477_get_strings,
@@ -1182,6 +1407,8 @@ static u32 ksz9477_get_port_addr(int port, int offset)
static int ksz9477_switch_detect(struct ksz_device *dev)
{
u8 data8;
+ u8 id_hi;
+ u8 id_lo;
u32 id32;
int ret;
@@ -1199,11 +1426,40 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);
if (ret)
return ret;
+ ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
+ if (ret)
+ return ret;
/* Number of ports can be reduced depending on chip. */
dev->mib_port_cnt = TOTAL_PORT_NUM;
dev->phy_port_cnt = 5;
+ /* Default capability is gigabit capable. */
+ dev->features = GBIT_SUPPORT;
+
+ id_hi = (u8)(id32 >> 16);
+ id_lo = (u8)(id32 >> 8);
+ if ((id_lo & 0xf) == 3) {
+ /* Chip is from KSZ9893 design. */
+ dev->features |= IS_9893;
+
+ /* Chip does not support gigabit. */
+ if (data8 & SW_QW_ABLE)
+ dev->features &= ~GBIT_SUPPORT;
+ dev->mib_port_cnt = 3;
+ dev->phy_port_cnt = 2;
+ } else {
+ /* Chip uses new XMII register definitions. */
+ dev->features |= NEW_XMII;
+
+ /* Chip does not support gigabit. */
+ if (!(data8 & SW_GIGABIT_ABLE))
+ dev->features &= ~GBIT_SUPPORT;
+ }
+
+ /* Change chip id to known ones so it can be matched against them. */
+ id32 = (id_hi << 16) | (id_lo << 8);
+
dev->chip_id = id32;
return 0;
@@ -1238,6 +1494,15 @@ static const struct ksz_chip_data ksz9477_switch_chips[] = {
.cpu_ports = 0x7F, /* can be configured as cpu port */
.port_cnt = 7, /* total physical port count */
},
+ {
+ .chip_id = 0x00989300,
+ .dev_name = "KSZ9893",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x07, /* can be configured as cpu port */
+ .port_cnt = 3, /* total port count */
+ },
};
static int ksz9477_switch_init(struct ksz_device *dev)
@@ -1276,6 +1541,7 @@ static int ksz9477_switch_init(struct ksz_device *dev)
if (!dev->ports)
return -ENOMEM;
for (i = 0; i < dev->mib_port_cnt; i++) {
+ mutex_init(&dev->ports[i].mib.cnt_mutex);
dev->ports[i].mib.counters =
devm_kzalloc(dev->dev,
sizeof(u64) *
@@ -1284,7 +1550,6 @@ static int ksz9477_switch_init(struct ksz_device *dev)
if (!dev->ports[i].mib.counters)
return -ENOMEM;
}
- dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
return 0;
}
@@ -1298,7 +1563,12 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
.get_port_addr = ksz9477_get_port_addr,
.cfg_port_member = ksz9477_cfg_port_member,
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
+ .phy_setup = ksz9477_phy_setup,
.port_setup = ksz9477_port_setup,
+ .r_mib_cnt = ksz9477_r_mib_cnt,
+ .r_mib_pkt = ksz9477_r_mib_pkt,
+ .freeze_mib = ksz9477_freeze_mib,
+ .port_init_cnt = ksz9477_port_init_cnt,
.shutdown = ksz9477_reset_switch,
.detect = ksz9477_switch_detect,
.init = ksz9477_switch_init,
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index d757ba151cb1..75178624d3f5 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 series register access through SPI
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <asm/unaligned.h>
@@ -155,6 +155,8 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)
static const struct of_device_id ksz9477_dt_ids[] = {
{ .compatible = "microchip,ksz9477" },
{ .compatible = "microchip,ksz9897" },
+ { .compatible = "microchip,ksz9893" },
+ { .compatible = "microchip,ksz9563" },
{},
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 3b12e2dcff31..39dace8e3512 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2,12 +2,11 @@
/*
* Microchip switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <linux/delay.h>
#include <linux/export.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -15,13 +14,22 @@
#include <linux/phy.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
-#include <linux/of_gpio.h>
#include <linux/of_net.h>
#include <net/dsa.h>
#include <net/switchdev.h>
#include "ksz_priv.h"
+void ksz_port_cleanup(struct ksz_device *dev, int port)
+{
+ /* Common code for port cleanup. */
+ mutex_lock(&dev->dev_mutex);
+ dev->on_ports &= ~(1 << port);
+ dev->live_ports &= ~(1 << port);
+ mutex_unlock(&dev->dev_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_port_cleanup);
+
void ksz_update_port_member(struct ksz_device *dev, int port)
{
struct ksz_port *p;
@@ -42,6 +50,85 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
}
EXPORT_SYMBOL_GPL(ksz_update_port_member);
+static void port_r_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+ u64 *dropped;
+
+ /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->reg_mib_cnt) {
+ dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
+ &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+
+ /* last one in storage */
+ dropped = &mib->counters[dev->mib_cnt];
+
+ /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->mib_cnt) {
+ dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
+ dropped, &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+ mib->cnt_ptr = 0;
+}
+
+static void ksz_mib_read_work(struct work_struct *work)
+{
+ struct ksz_device *dev = container_of(work, struct ksz_device,
+ mib_read);
+ struct ksz_port_mib *mib;
+ struct ksz_port *p;
+ int i;
+
+ for (i = 0; i < dev->mib_port_cnt; i++) {
+ p = &dev->ports[i];
+ mib = &p->mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Only read MIB counters when the port is told to do.
+ * If not, read only dropped counters when link is not up.
+ */
+ if (!p->read) {
+ const struct dsa_port *dp = dsa_to_port(dev->ds, i);
+
+ if (!netif_carrier_ok(dp->slave))
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ }
+ port_r_cnt(dev, i);
+ p->read = false;
+ mutex_unlock(&mib->cnt_mutex);
+ }
+}
+
+static void mib_monitor(struct timer_list *t)
+{
+ struct ksz_device *dev = from_timer(dev, t, mib_read_timer);
+
+ mod_timer(&dev->mib_read_timer, jiffies + dev->mib_read_interval);
+ schedule_work(&dev->mib_read);
+}
+
+void ksz_init_mib_timer(struct ksz_device *dev)
+{
+ int i;
+
+ /* Read MIB counters every 30 seconds to avoid overflow. */
+ dev->mib_read_interval = msecs_to_jiffies(30000);
+
+ INIT_WORK(&dev->mib_read, ksz_mib_read_work);
+ timer_setup(&dev->mib_read_timer, mib_monitor, 0);
+
+ for (i = 0; i < dev->mib_port_cnt; i++)
+ dev->dev_ops->port_init_cnt(dev, i);
+
+ /* Start the timer 2 seconds later. */
+ dev->mib_read_timer.expires = jiffies + msecs_to_jiffies(2000);
+ add_timer(&dev->mib_read_timer);
+}
+EXPORT_SYMBOL_GPL(ksz_init_mib_timer);
+
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
{
struct ksz_device *dev = ds->priv;
@@ -63,6 +150,27 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
}
EXPORT_SYMBOL_GPL(ksz_phy_write16);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port *p = &dev->ports[port];
+
+ /* Read all MIB counters when the link is going down. */
+ if (!phydev->link) {
+ p->read = true;
+ schedule_work(&dev->mib_read);
+ }
+ mutex_lock(&dev->dev_mutex);
+ if (!phydev->link)
+ dev->live_ports &= ~(1 << port);
+ else
+ /* Remember which port is connected and active. */
+ dev->live_ports |= (1 << port) & dev->on_ports;
+ mutex_unlock(&dev->dev_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_adjust_link);
+
int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
{
struct ksz_device *dev = ds->priv;
@@ -74,12 +182,32 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
}
EXPORT_SYMBOL_GPL(ksz_sset_count);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
+{
+ const struct dsa_port *dp = dsa_to_port(ds, port);
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port_mib *mib;
+
+ mib = &dev->ports[port].mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Only read dropped counters if no link. */
+ if (!netif_carrier_ok(dp->slave))
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ port_r_cnt(dev, port);
+ memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64));
+ mutex_unlock(&mib->cnt_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
+
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br)
{
struct ksz_device *dev = ds->priv;
+ mutex_lock(&dev->dev_mutex);
dev->br_member |= (1 << port);
+ mutex_unlock(&dev->dev_mutex);
/* port_stp_state_set() will be called after to put the port in
* appropriate state so there is no need to do anything.
@@ -94,8 +222,10 @@ void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
{
struct ksz_device *dev = ds->priv;
+ mutex_lock(&dev->dev_mutex);
dev->br_member &= ~(1 << port);
dev->member &= ~(1 << port);
+ mutex_unlock(&dev->dev_mutex);
/* port_stp_state_set() will be called after to put the port in
* forwarding state so there is no need to do anything.
@@ -240,6 +370,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
/* setup slave port */
dev->dev_ops->port_setup(dev, port, false);
+ dev->dev_ops->phy_setup(dev, port, phy);
/* port_stp_state_set() will be called after to enable the port so
* there is no need to do anything.
@@ -249,7 +380,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
}
EXPORT_SYMBOL_GPL(ksz_enable_port);
-void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
+void ksz_disable_port(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
@@ -307,6 +438,7 @@ int ksz_switch_register(struct ksz_device *dev,
gpiod_set_value(dev->reset_gpio, 0);
}
+ mutex_init(&dev->dev_mutex);
mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex);
mutex_init(&dev->alu_mutex);
@@ -321,7 +453,9 @@ int ksz_switch_register(struct ksz_device *dev,
if (ret)
return ret;
- dev->interface = PHY_INTERFACE_MODE_MII;
+ /* Host port interface will be self detected, or specifically set in
+ * device tree.
+ */
if (dev->dev->of_node) {
ret = of_get_phy_mode(dev->dev->of_node);
if (ret >= 0)
@@ -340,6 +474,12 @@ EXPORT_SYMBOL(ksz_switch_register);
void ksz_switch_remove(struct ksz_device *dev)
{
+ /* timer started */
+ if (dev->mib_read_timer.expires) {
+ del_timer_sync(&dev->mib_read_timer);
+ flush_work(&dev->mib_read);
+ }
+
dev->dev_ops->exit(dev);
dsa_unregister_switch(dev->ds);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 2dd832de0d52..21cd794e18f1 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -1,19 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0
* Microchip switch driver common header
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
+void ksz_port_cleanup(struct ksz_device *dev, int port);
void ksz_update_port_member(struct ksz_device *dev, int port);
+void ksz_init_mib_timer(struct ksz_device *dev);
/* Common DSA access functions */
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br);
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
@@ -30,7 +35,7 @@ void ksz_port_mdb_add(struct dsa_switch *ds, int port,
int ksz_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
-void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
+void ksz_disable_port(struct dsa_switch *ds, int port);
/* Common register access functions */
@@ -211,4 +216,18 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
ksz_write8(dev, addr, data);
}
+struct ksz_poll_ctx {
+ struct ksz_device *dev;
+ int port;
+ int offset;
+};
+
+static inline u32 ksz_pread32_poll(struct ksz_poll_ctx *ctx)
+{
+ u32 data;
+
+ ksz_pread32(ctx->dev, ctx->port, ctx->offset, &data);
+ return data;
+}
+
#endif
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 60b49010904b..b52e5ca17ab4 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -2,7 +2,7 @@
*
* Microchip KSZ series switch common definitions
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_PRIV_H
@@ -14,8 +14,6 @@
#include <linux/etherdevice.h>
#include <net/dsa.h>
-#include "ksz9477_reg.h"
-
struct ksz_io_ops;
struct vlan_table {
@@ -23,6 +21,7 @@ struct vlan_table {
};
struct ksz_port_mib {
+ struct mutex cnt_mutex; /* structure access */
u8 cnt_ptr;
u64 *counters;
};
@@ -38,7 +37,8 @@ struct ksz_port {
u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1;
- u32 link_just_down:1; /* link just goes down */
+ u32 read:1; /* read MIB counters in background */
+ u32 freeze:1; /* MIB counter freeze is enabled */
struct ksz_port_mib mib;
};
@@ -48,6 +48,7 @@ struct ksz_device {
struct ksz_platform_data *pdata;
const char *name;
+ struct mutex dev_mutex; /* device access */
struct mutex reg_mutex; /* register access */
struct mutex stats_mutex; /* status access */
struct mutex alu_mutex; /* ALU access */
@@ -79,8 +80,6 @@ struct ksz_device {
struct vlan_table *vlan_cache;
- u64 mib_value[TOTAL_SWITCH_COUNTER_NUM];
-
u8 *txbuf;
struct ksz_port *ports;
@@ -137,6 +136,9 @@ struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
+ void (*phy_setup)(struct ksz_device *dev, int port,
+ struct phy_device *phy);
+ void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
@@ -151,6 +153,7 @@ struct ksz_dev_ops {
u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
+ void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
void (*port_init_cnt)(struct ksz_device *dev, int port);
int (*shutdown)(struct ksz_device *dev);
int (*detect)(struct ksz_device *dev);
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 74547f43b938..7357b4fc0185 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -18,7 +18,6 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
@@ -622,17 +621,19 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port,
struct mt7530_priv *priv = ds->priv;
if (phy_is_pseudo_fixed_link(phydev)) {
- dev_dbg(priv->dev, "phy-mode for master device = %x\n",
- phydev->interface);
-
- /* Setup TX circuit incluing relevant PAD and driving */
- mt7530_pad_clk_setup(ds, phydev->interface);
-
- /* Setup RX circuit, relevant PAD and driving on the host
- * which must be placed after the setup on the device side is
- * all finished.
- */
- mt7623_pad_clk_setup(ds);
+ if (priv->id == ID_MT7530) {
+ dev_dbg(priv->dev, "phy-mode for master device = %x\n",
+ phydev->interface);
+
+ /* Setup TX circuit incluing relevant PAD and driving */
+ mt7530_pad_clk_setup(ds, phydev->interface);
+
+ /* Setup RX circuit, relevant PAD and driving on the
+ * host which must be placed after the setup on the
+ * device side is all finished.
+ */
+ mt7623_pad_clk_setup(ds);
+ }
} else {
u16 lcl_adv = 0, rmt_adv = 0;
u8 flowctrl;
@@ -645,7 +646,7 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port,
case SPEED_100:
mcr |= PMCR_FORCE_SPEED_100;
break;
- };
+ }
if (phydev->link)
mcr |= PMCR_FORCE_LNK;
@@ -688,6 +689,10 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
/* Unknown unicast frame fordwarding to the cpu port */
mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port)));
+ /* Set CPU port number */
+ if (priv->id == ID_MT7621)
+ mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
+
/* CPU port gets connected to all user ports of
* the switch
*/
@@ -724,8 +729,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
}
static void
-mt7530_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+mt7530_port_disable(struct dsa_switch *ds, int port)
{
struct mt7530_priv *priv = ds->priv;
@@ -1220,24 +1224,27 @@ mt7530_setup(struct dsa_switch *ds)
* as two netdev instances.
*/
dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent;
- priv->ethernet = syscon_node_to_regmap(dn);
- if (IS_ERR(priv->ethernet))
- return PTR_ERR(priv->ethernet);
- regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
- ret = regulator_enable(priv->core_pwr);
- if (ret < 0) {
- dev_err(priv->dev,
- "Failed to enable core power: %d\n", ret);
- return ret;
- }
+ if (priv->id == ID_MT7530) {
+ priv->ethernet = syscon_node_to_regmap(dn);
+ if (IS_ERR(priv->ethernet))
+ return PTR_ERR(priv->ethernet);
+
+ regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
+ ret = regulator_enable(priv->core_pwr);
+ if (ret < 0) {
+ dev_err(priv->dev,
+ "Failed to enable core power: %d\n", ret);
+ return ret;
+ }
- regulator_set_voltage(priv->io_pwr, 3300000, 3300000);
- ret = regulator_enable(priv->io_pwr);
- if (ret < 0) {
- dev_err(priv->dev, "Failed to enable io pwr: %d\n",
- ret);
- return ret;
+ regulator_set_voltage(priv->io_pwr, 3300000, 3300000);
+ ret = regulator_enable(priv->io_pwr);
+ if (ret < 0) {
+ dev_err(priv->dev, "Failed to enable io pwr: %d\n",
+ ret);
+ return ret;
+ }
}
/* Reset whole chip through gpio pin or memory-mapped registers for
@@ -1293,7 +1300,7 @@ mt7530_setup(struct dsa_switch *ds)
if (dsa_is_cpu_port(ds, i))
mt7530_cpu_port_enable(priv, i);
else
- mt7530_port_disable(ds, i, NULL);
+ mt7530_port_disable(ds, i);
}
/* Flush the FDB table */
@@ -1327,6 +1334,13 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
.port_vlan_del = mt7530_port_vlan_del,
};
+static const struct of_device_id mt7530_of_match[] = {
+ { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, },
+ { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt7530_of_match);
+
static int
mt7530_probe(struct mdio_device *mdiodev)
{
@@ -1357,13 +1371,21 @@ mt7530_probe(struct mdio_device *mdiodev)
}
}
- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
- if (IS_ERR(priv->core_pwr))
- return PTR_ERR(priv->core_pwr);
+ /* Get the hardware identifier from the devicetree node.
+ * We will need it for some of the clock and regulator setup.
+ */
+ priv->id = (unsigned int)(unsigned long)
+ of_device_get_match_data(&mdiodev->dev);
+
+ if (priv->id == ID_MT7530) {
+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
+ if (IS_ERR(priv->core_pwr))
+ return PTR_ERR(priv->core_pwr);
- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
- if (IS_ERR(priv->io_pwr))
- return PTR_ERR(priv->io_pwr);
+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
+ if (IS_ERR(priv->io_pwr))
+ return PTR_ERR(priv->io_pwr);
+ }
/* Not MCM that indicates switch works as the remote standalone
* integrated circuit so the GPIO pin would be used to complete
@@ -1409,12 +1431,6 @@ mt7530_remove(struct mdio_device *mdiodev)
mutex_destroy(&priv->reg_mutex);
}
-static const struct of_device_id mt7530_of_match[] = {
- { .compatible = "mediatek,mt7530" },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mt7530_of_match);
-
static struct mdio_driver mt7530_mdio_driver = {
.probe = mt7530_probe,
.remove = mt7530_remove,
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index d9b407a22a58..a95ed958df5b 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -19,6 +19,11 @@
#define MT7530_NUM_FDB_RECORDS 2048
#define MT7530_ALL_MEMBERS 0xff
+enum {
+ ID_MT7530 = 0,
+ ID_MT7621 = 1,
+};
+
#define NUM_TRGMII_CTRL 5
#define TRGMII_BASE(x) (0x10000 + (x))
@@ -36,6 +41,9 @@
#define UNM_FFP(x) (((x) & 0xff) << 16)
#define UNU_FFP(x) (((x) & 0xff) << 8)
#define UNU_FFP_MASK UNU_FFP(~0)
+#define CPU_EN BIT(7)
+#define CPU_PORT(x) ((x) << 4)
+#define CPU_MASK (0xf << 4)
/* Registers for address table access */
#define MT7530_ATA1 0x74
@@ -430,6 +438,7 @@ struct mt7530_priv {
struct regulator *core_pwr;
struct regulator *io_pwr;
struct gpio_desc *reset;
+ unsigned int id;
bool mcm;
struct mt7530_port ports[MT7530_NUM_PORTS];
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8a517d8fb9d1..96728d1e9824 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -261,6 +261,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
unsigned int sub_irq;
unsigned int n;
u16 reg;
+ u16 ctl1;
int err;
mutex_lock(&chip->reg_lock);
@@ -270,13 +271,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
if (err)
goto out;
- for (n = 0; n < chip->g1_irq.nirqs; ++n) {
- if (reg & (1 << n)) {
- sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
- handle_nested_irq(sub_irq);
- ++nhandled;
+ do {
+ for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+ if (reg & (1 << n)) {
+ sub_irq = irq_find_mapping(chip->g1_irq.domain,
+ n);
+ handle_nested_irq(sub_irq);
+ ++nhandled;
+ }
}
- }
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
+ if (err)
+ goto unlock;
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
+unlock:
+ mutex_unlock(&chip->reg_lock);
+ if (err)
+ goto out;
+ ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
+ } while (reg & ctl1);
+
out:
return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
}
@@ -426,16 +442,26 @@ out_mapping:
static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
{
+ static struct lock_class_key lock_key;
+ static struct lock_class_key request_key;
int err;
err = mv88e6xxx_g1_irq_setup_common(chip);
if (err)
return err;
+ /* These lock classes tells lockdep that global 1 irqs are in
+ * a different category than their parent GPIO, so it won't
+ * report false recursion.
+ */
+ irq_set_lockdep_class(chip->irq, &lock_key, &request_key);
+
+ mutex_unlock(&chip->reg_lock);
err = request_threaded_irq(chip->irq, NULL,
mv88e6xxx_g1_irq_thread_fn,
IRQF_ONESHOT | IRQF_SHARED,
dev_name(chip->dev), chip);
+ mutex_lock(&chip->reg_lock);
if (err)
mv88e6xxx_g1_irq_free_common(chip);
@@ -464,7 +490,7 @@ static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
kthread_init_delayed_work(&chip->irq_poll_work,
mv88e6xxx_irq_poll);
- chip->kworker = kthread_create_worker(0, dev_name(chip->dev));
+ chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev));
if (IS_ERR(chip->kworker))
return PTR_ERR(chip->kworker);
@@ -523,9 +549,9 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
return mv88e6xxx_write(chip, addr, reg, val);
}
-static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
- int link, int speed, int duplex, int pause,
- phy_interface_t mode)
+int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
+ int speed, int duplex, int pause,
+ phy_interface_t mode)
{
int err;
@@ -632,6 +658,20 @@ static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port,
mv88e6065_phylink_validate(chip, port, mask, state);
}
+static void mv88e6341_phylink_validate(struct mv88e6xxx_chip *chip, int port,
+ unsigned long *mask,
+ struct phylink_link_state *state)
+{
+ if (port >= 5)
+ phylink_set(mask, 2500baseX_Full);
+
+ /* No ethtool bits for 200Mbps */
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+
+ mv88e6065_phylink_validate(chip, port, mask, state);
+}
+
static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port,
unsigned long *mask,
struct phylink_link_state *state)
@@ -647,8 +687,10 @@ static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port,
unsigned long *mask,
struct phylink_link_state *state)
{
- if (port >= 9)
+ if (port >= 9) {
phylink_set(mask, 2500baseX_Full);
+ phylink_set(mask, 2500baseT_Full);
+ }
/* No ethtool bits for 200Mbps */
phylink_set(mask, 1000baseT_Full);
@@ -880,7 +922,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
default:
return U64_MAX;
}
- value = (((u64)high) << 16) | low;
+ value = (((u64)high) << 32) | low;
return value;
}
@@ -2360,8 +2402,7 @@ static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
return err;
}
-static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phydev)
+static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_chip *chip = ds->priv;
@@ -2403,6 +2444,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_stats_clear(chip);
}
+/* The mv88e6390 has some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
+ int reg, u16 val)
+{
+ u16 ctrl;
+ int err;
+
+ err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
+ PORT_RESERVED_1A, val);
+ if (err)
+ return err;
+
+ ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
+ PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+ PORT_RESERVED_1A, ctrl);
+}
+
+static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
+ PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+}
+
+
+static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
+ int reg, u16 *val)
+{
+ u16 ctrl;
+ int err;
+
+ ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
+ PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+ PORT_RESERVED_1A, ctrl);
+ if (err)
+ return err;
+
+ err = mv88e6390_hidden_wait(chip);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
+ PORT_RESERVED_1A, val);
+}
+
+/* Check if the errata has already been applied. */
+static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
+{
+ int port;
+ int err;
+ u16 val;
+
+ for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+ err = mv88e6390_hidden_read(chip, port, 0, &val);
+ if (err) {
+ dev_err(chip->dev,
+ "Error reading hidden register: %d\n", err);
+ return false;
+ }
+ if (val != 0x01c0)
+ return false;
+ }
+
+ return true;
+}
+
+/* The 6390 copper ports have an errata which require poking magic
+ * values into undocumented hidden registers and then performing a
+ * software reset.
+ */
+static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
+{
+ int port;
+ int err;
+
+ if (mv88e6390_setup_errata_applied(chip))
+ return 0;
+
+ /* Set the ports into blocking mode */
+ for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+ err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
+ if (err)
+ return err;
+ }
+
+ for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+ err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+ if (err)
+ return err;
+ }
+
+ return mv88e6xxx_software_reset(chip);
+}
+
static int mv88e6xxx_setup(struct dsa_switch *ds)
{
struct mv88e6xxx_chip *chip = ds->priv;
@@ -2415,6 +2557,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
mutex_lock(&chip->reg_lock);
+ if (chip->info->ops->setup_errata) {
+ err = chip->info->ops->setup_errata(chip);
+ if (err)
+ goto unlock;
+ }
+
/* Cache the cmode of each port. */
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
if (chip->info->ops->port_get_cmode) {
@@ -2945,7 +3093,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
.serdes_power = mv88e6341_serdes_power,
.gpio_ops = &mv88e6352_gpio_ops,
- .phylink_validate = mv88e6390_phylink_validate,
+ .phylink_validate = mv88e6341_phylink_validate,
};
static const struct mv88e6xxx_ops mv88e6161_ops = {
@@ -2970,7 +3118,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
- .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
@@ -3226,6 +3374,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
static const struct mv88e6xxx_ops mv88e6190_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3269,6 +3418,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
static const struct mv88e6xxx_ops mv88e6190x_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3312,6 +3462,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
static const struct mv88e6xxx_ops mv88e6191_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3404,6 +3555,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
static const struct mv88e6xxx_ops mv88e6290_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3573,7 +3725,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
- .phylink_validate = mv88e6390_phylink_validate,
+ .phylink_validate = mv88e6341_phylink_validate,
};
static const struct mv88e6xxx_ops mv88e6350_ops = {
@@ -3709,6 +3861,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
static const struct mv88e6xxx_ops mv88e6390_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3756,6 +3909,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
static const struct mv88e6xxx_ops mv88e6390x_ops = {
/* MV88E6XXX_FAMILY_6390 */
+ .setup_errata = mv88e6390_setup_errata,
.irl_init_all = mv88e6390_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -4093,7 +4247,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6190",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.num_gpio = 16,
.max_vid = 8191,
.port_base_addr = 0x0,
@@ -4116,7 +4270,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6190X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.num_gpio = 16,
.max_vid = 8191,
.port_base_addr = 0x0,
@@ -4139,7 +4293,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6191",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.max_vid = 8191,
.port_base_addr = 0x0,
.phy_base_addr = 0x0,
@@ -4186,7 +4340,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6290",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.num_gpio = 16,
.max_vid = 8191,
.port_base_addr = 0x0,
@@ -4348,7 +4502,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6390",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.num_gpio = 16,
.max_vid = 8191,
.port_base_addr = 0x0,
@@ -4371,7 +4525,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6390X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 11,
+ .num_internal_phys = 9,
.num_gpio = 16,
.max_vid = 8191,
.port_base_addr = 0x0,
@@ -4466,6 +4620,14 @@ static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
return 0;
}
+static void mv88e6xxx_ports_cmode_init(struct mv88e6xxx_chip *chip)
+{
+ int i;
+
+ for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
+ chip->ports[i].cmode = MV88E6XXX_PORT_STS_CMODE_INVALID;
+}
+
static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
int port)
{
@@ -4502,6 +4664,8 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
if (err)
goto free;
+ mv88e6xxx_ports_cmode_init(chip);
+
mutex_lock(&chip->reg_lock);
err = mv88e6xxx_switch_reset(chip);
mutex_unlock(&chip->reg_lock);
@@ -4561,6 +4725,22 @@ static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
return err;
}
+static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
+ bool unicast, bool multicast)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = -EOPNOTSUPP;
+
+ mutex_lock(&chip->reg_lock);
+ if (chip->info->ops->port_set_egress_floods)
+ err = chip->info->ops->port_set_egress_floods(chip, port,
+ unicast,
+ multicast);
+ mutex_unlock(&chip->reg_lock);
+
+ return err;
+}
+
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
.probe = mv88e6xxx_drv_probe,
@@ -4588,6 +4768,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.set_ageing_time = mv88e6xxx_set_ageing_time,
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
+ .port_egress_floods = mv88e6xxx_port_egress_floods,
.port_stp_state_set = mv88e6xxx_port_stp_state_set,
.port_fast_age = mv88e6xxx_port_fast_age,
.port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
@@ -4651,6 +4832,21 @@ static const void *pdata_device_get_match_data(struct device *dev)
return NULL;
}
+/* There is no suspend to RAM support at DSA level yet, the switch configuration
+ * would be lost after a power cycle so prevent it to be suspended.
+ */
+static int __maybe_unused mv88e6xxx_suspend(struct device *dev)
+{
+ return -EOPNOTSUPP;
+}
+
+static int __maybe_unused mv88e6xxx_resume(struct device *dev)
+{
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume);
+
static int mv88e6xxx_probe(struct mdio_device *mdiodev)
{
struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
@@ -4708,6 +4904,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
if (err)
goto out;
+ mv88e6xxx_ports_cmode_init(chip);
mv88e6xxx_phy_init(chip);
if (chip->info->ops->get_eeprom) {
@@ -4835,6 +5032,7 @@ static struct mdio_driver mv88e6xxx_driver = {
.mdiodrv.driver = {
.name = "mv88e6085",
.of_match_table = mv88e6xxx_of_match,
+ .pm = &mv88e6xxx_pm_ops,
},
};
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index f9ecb7872d32..adcf60779895 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -300,6 +300,11 @@ struct mv88e6xxx_mdio_bus {
};
struct mv88e6xxx_ops {
+ /* Switch Setup Errata, called early in the switch setup to
+ * allow any errata actions to be performed
+ */
+ int (*setup_errata)(struct mv88e6xxx_chip *chip);
+
int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
@@ -574,6 +579,9 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 update);
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
+int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
+ int speed, int duplex, int pause,
+ phy_interface_t mode);
struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip);
#endif /* _MV88E6XXX_CHIP_H */
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index 5200e4bdce93..ea243840ee0f 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -314,6 +314,7 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
{
struct mv88e6xxx_chip *chip = dev_id;
struct mv88e6xxx_atu_entry entry;
+ int spid;
int err;
u16 val;
@@ -336,6 +337,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
if (err)
goto out;
+ spid = entry.state;
+
if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
dev_err_ratelimited(chip->dev,
"ATU age out violation for %pM\n",
@@ -344,23 +347,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
dev_err_ratelimited(chip->dev,
- "ATU member violation for %pM portvec %x\n",
- entry.mac, entry.portvec);
- chip->ports[entry.portvec].atu_member_violation++;
+ "ATU member violation for %pM portvec %x spid %d\n",
+ entry.mac, entry.portvec, spid);
+ chip->ports[spid].atu_member_violation++;
}
if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
dev_err_ratelimited(chip->dev,
- "ATU miss violation for %pM portvec %x\n",
- entry.mac, entry.portvec);
- chip->ports[entry.portvec].atu_miss_violation++;
+ "ATU miss violation for %pM portvec %x spid %d\n",
+ entry.mac, entry.portvec, spid);
+ chip->ports[spid].atu_miss_violation++;
}
if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
dev_err_ratelimited(chip->dev,
- "ATU full violation for %pM portvec %x\n",
- entry.mac, entry.portvec);
- chip->ports[entry.portvec].atu_full_violation++;
+ "ATU full violation for %pM portvec %x spid %d\n",
+ entry.mac, entry.portvec, spid);
+ chip->ports[spid].atu_full_violation++;
}
mutex_unlock(&chip->reg_lock);
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index ebd26b6a93e6..0796c6feec55 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -190,7 +190,7 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
/* normal duplex detection */
break;
default:
- return -EINVAL;
+ return -EOPNOTSUPP;
}
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
@@ -398,6 +398,10 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
cmode = 0;
}
+ /* cmode doesn't change, nothing to do for us */
+ if (cmode == chip->ports[port].cmode)
+ return 0;
+
lane = mv88e6390x_serdes_get_lane(chip, port);
if (lane < 0)
return lane;
@@ -408,7 +412,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return err;
}
- err = mv88e6390_serdes_power(chip, port, false);
+ err = mv88e6390x_serdes_power(chip, port, false);
if (err)
return err;
@@ -424,7 +428,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
- err = mv88e6390_serdes_power(chip, port, true);
+ err = mv88e6390x_serdes_power(chip, port, true);
if (err)
return err;
@@ -444,6 +448,8 @@ int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode)
{
switch (mode) {
+ case PHY_INTERFACE_MODE_NA:
+ return 0;
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_RXAUI:
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 0d81866d0e4a..4aadf321edb7 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -52,6 +52,7 @@
#define MV88E6185_PORT_STS_CMODE_1000BASE_X 0x0005
#define MV88E6185_PORT_STS_CMODE_PHY 0x0006
#define MV88E6185_PORT_STS_CMODE_DISABLED 0x0007
+#define MV88E6XXX_PORT_STS_CMODE_INVALID 0xff
/* Offset 0x01: MAC (or PCS or Physical) Control Register */
#define MV88E6XXX_PORT_MAC_CTL 0x01
@@ -251,6 +252,16 @@
/* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19
+/* Offset 0x1a: Magic undocumented errata register */
+#define PORT_RESERVED_1A 0x1a
+#define PORT_RESERVED_1A_BUSY BIT(15)
+#define PORT_RESERVED_1A_WRITE BIT(14)
+#define PORT_RESERVED_1A_READ 0
+#define PORT_RESERVED_1A_PORT_SHIFT 5
+#define PORT_RESERVED_1A_BLOCK (0xf << 10)
+#define PORT_RESERVED_1A_CTRL_PORT 4
+#define PORT_RESERVED_1A_DATA_PORT 5
+
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
u16 *val);
int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index 4b336d8d4c67..42872d21857b 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -400,7 +400,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->ptp_clock_info.owner = THIS_MODULE;
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
- dev_name(chip->dev));
+ "%s", dev_name(chip->dev));
chip->ptp_clock_info.max_adj = 1000000;
chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 2caa8c8b4b55..6a5de1b72f6c 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -510,21 +510,48 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
int port, int lane)
{
struct dsa_switch *ds = chip->ds;
+ int duplex = DUPLEX_UNKNOWN;
+ int speed = SPEED_UNKNOWN;
+ int link, err;
u16 status;
- bool up;
- mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
- MV88E6390_SGMII_STATUS, &status);
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
+ MV88E6390_SGMII_PHY_STATUS, &status);
+ if (err) {
+ dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err);
+ return;
+ }
- /* Status must be read twice in order to give the current link
- * status. Otherwise the change in link status since the last
- * read of the register is returned.
- */
- mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
- MV88E6390_SGMII_STATUS, &status);
- up = status & MV88E6390_SGMII_STATUS_LINK;
+ link = status & MV88E6390_SGMII_PHY_STATUS_LINK ?
+ LINK_FORCED_UP : LINK_FORCED_DOWN;
+
+ if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
+ duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
+ DUPLEX_FULL : DUPLEX_HALF;
+
+ switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
+ case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
+ speed = SPEED_1000;
+ break;
+ case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
+ speed = SPEED_100;
+ break;
+ case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
+ speed = SPEED_10;
+ break;
+ default:
+ dev_err(chip->dev, "invalid PHY speed\n");
+ return;
+ }
+ }
- dsa_port_phylink_mac_change(ds, port, up);
+ err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
+ PAUSE_OFF, PHY_INTERFACE_MODE_NA);
+ if (err)
+ dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
+ err);
+ else
+ dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP);
}
static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
@@ -664,7 +691,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
if (port < 9)
return 0;
- return mv88e6390_serdes_irq_setup(chip, port);
+ return mv88e6390x_serdes_irq_setup(chip, port);
}
void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 573dce8b1eb4..c2e7eedfa9b9 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -69,6 +69,14 @@
#define MV88E6390_SGMII_INT_SYMBOL_ERROR BIT(8)
#define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7)
#define MV88E6390_SGMII_INT_STATUS 0xa002
+#define MV88E6390_SGMII_PHY_STATUS 0xa003
+#define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK GENMASK(15, 14)
+#define MV88E6390_SGMII_PHY_STATUS_SPEED_1000 0x8000
+#define MV88E6390_SGMII_PHY_STATUS_SPEED_100 0x4000
+#define MV88E6390_SGMII_PHY_STATUS_SPEED_10 0x0000
+#define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL BIT(13)
+#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
+#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10)
int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 7e97e620bd44..576b37d12a63 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -420,7 +420,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
static int
qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode)
{
- u32 reg;
+ u32 reg, val;
switch (port) {
case 0:
@@ -439,15 +439,19 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode)
*/
switch (mode) {
case PHY_INTERFACE_MODE_RGMII:
- qca8k_write(priv, reg,
- QCA8K_PORT_PAD_RGMII_EN |
- QCA8K_PORT_PAD_RGMII_TX_DELAY(3) |
- QCA8K_PORT_PAD_RGMII_RX_DELAY(3));
-
- /* According to the datasheet, RGMII delay is enabled through
+ /* RGMII mode means no delay so don't enable the delay */
+ val = QCA8K_PORT_PAD_RGMII_EN;
+ qca8k_write(priv, reg, val);
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ /* RGMII_ID needs internal delay. This is enabled through
* PORT5_PAD_CTRL for all ports, rather than individual port
* registers
*/
+ qca8k_write(priv, reg,
+ QCA8K_PORT_PAD_RGMII_EN |
+ QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
+ QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
break;
@@ -797,8 +801,7 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
}
static void
-qca8k_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+qca8k_port_disable(struct dsa_switch *ds, int port)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index 613fe5c50236..d146e54c8a6c 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -40,6 +40,7 @@
((0x8 + (x & 0x3)) << 22)
#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \
((0x10 + (x & 0x3)) << 20)
+#define QCA8K_MAX_DELAY 3
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24)
#define QCA8K_PORT_PAD_SGMII_EN BIT(7)
#define QCA8K_REG_MODULE_EN 0x030
diff --git a/drivers/net/dsa/realtek-smi.c b/drivers/net/dsa/realtek-smi.c
index b4b839a1d095..ad41ec63cc9f 100644
--- a/drivers/net/dsa/realtek-smi.c
+++ b/drivers/net/dsa/realtek-smi.c
@@ -347,16 +347,17 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
struct device_node *mdio_np;
int ret;
- mdio_np = of_find_compatible_node(smi->dev->of_node, NULL,
- "realtek,smi-mdio");
+ mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
if (!mdio_np) {
dev_err(smi->dev, "no MDIO bus node\n");
return -ENODEV;
}
smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
- if (!smi->slave_mii_bus)
- return -ENOMEM;
+ if (!smi->slave_mii_bus) {
+ ret = -ENOMEM;
+ goto err_put_node;
+ }
smi->slave_mii_bus->priv = smi;
smi->slave_mii_bus->name = "SMI slave MII";
smi->slave_mii_bus->read = realtek_smi_mdio_read;
@@ -371,10 +372,15 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
if (ret) {
dev_err(smi->dev, "unable to register MDIO bus %s\n",
smi->slave_mii_bus->id);
- of_node_put(mdio_np);
+ goto err_put_node;
}
return 0;
+
+err_put_node:
+ of_node_put(mdio_np);
+
+ return ret;
}
static int realtek_smi_probe(struct platform_device *pdev)
@@ -457,6 +463,8 @@ static int realtek_smi_remove(struct platform_device *pdev)
struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
dsa_unregister_switch(smi->ds);
+ if (smi->slave_mii_bus)
+ of_node_put(smi->slave_mii_bus->dev.of_node);
gpiod_set_value(smi->reset, 1);
return 0;
diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c
index a4d5049df692..40b3974970c6 100644
--- a/drivers/net/dsa/rtl8366rb.c
+++ b/drivers/net/dsa/rtl8366rb.c
@@ -1073,8 +1073,7 @@ rtl8366rb_port_enable(struct dsa_switch *ds, int port,
}
static void
-rtl8366rb_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+rtl8366rb_port_disable(struct dsa_switch *ds, int port)
{
struct realtek_smi *smi = ds->priv;
int ret;
diff --git a/drivers/net/dsa/vitesse-vsc73xx.c b/drivers/net/dsa/vitesse-vsc73xx.c
index 9f1b5f2e8a64..d4780610ea8a 100644
--- a/drivers/net/dsa/vitesse-vsc73xx.c
+++ b/drivers/net/dsa/vitesse-vsc73xx.c
@@ -1013,8 +1013,7 @@ static int vsc73xx_port_enable(struct dsa_switch *ds, int port,
return 0;
}
-static void vsc73xx_port_disable(struct dsa_switch *ds, int port,
- struct phy_device *phy)
+static void vsc73xx_port_disable(struct dsa_switch *ds, int port)
{
struct vsc73xx *vsc = ds->priv;
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index b223769d6a5e..3da97996bdf3 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -1266,12 +1266,14 @@ el3_up(struct net_device *dev)
pr_cont("Forcing 3c5x9b full-duplex mode");
break;
}
+ /* fall through */
case 8:
/* set full-duplex mode based on eeprom config setting */
if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
break;
}
+ /* fall through */
default:
/* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c
index b648e3f95c01..808abb6b3671 100644
--- a/drivers/net/ethernet/3com/3c515.c
+++ b/drivers/net/ethernet/3com/3c515.c
@@ -1177,7 +1177,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
if (inl(ioaddr + DownListPtr) == isa_virt_to_bus(&lp->tx_ring[entry]))
break; /* It still hasn't been processed. */
if (lp->tx_skbuff[entry]) {
- dev_kfree_skb_irq(lp->tx_skbuff[entry]);
+ dev_consume_skb_irq(lp->tx_skbuff[entry]);
lp->tx_skbuff[entry] = NULL;
}
dirty_tx++;
@@ -1192,7 +1192,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
#ifdef VORTEX_BUS_MASTER
if (status & DMADone) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- dev_kfree_skb_irq(lp->tx_skb); /* Release the transferred buffer */
+ dev_consume_skb_irq(lp->tx_skb); /* Release the transferred buffer */
netif_wake_queue(dev);
}
#endif
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 40f421dbdf57..147051404194 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -2307,7 +2307,7 @@ _vortex_interrupt(int irq, struct net_device *dev)
dma_unmap_single(vp->gendev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, DMA_TO_DEVICE);
pkts_compl++;
bytes_compl += vp->tx_skb->len;
- dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
+ dev_consume_skb_irq(vp->tx_skb); /* Release the transferred buffer */
if (ioread16(ioaddr + TxFree) > 1536) {
/*
* AKPM: FIXME: I don't think we need this. If the queue was stopped due to
@@ -2449,7 +2449,7 @@ _boomerang_interrupt(int irq, struct net_device *dev)
#endif
pkts_compl++;
bytes_compl += skb->len;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
vp->tx_skbuff[entry] = NULL;
} else {
pr_debug("boomerang_interrupt: no skb!\n");
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 097467f44b0d..816540e6beac 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -1390,7 +1390,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
}
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
np->tx_done_q[np->tx_done].status = 0;
np->tx_done = (np->tx_done + 1) % DONE_Q_SIZE;
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 91fc64c1145e..47e5984f16fb 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1433,18 +1433,18 @@ static int greth_of_probe(struct platform_device *ofdev)
}
/* Allocate TX descriptor ring in coherent memory */
- greth->tx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
- &greth->tx_bd_base_phys,
- GFP_KERNEL);
+ greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+ &greth->tx_bd_base_phys,
+ GFP_KERNEL);
if (!greth->tx_bd_base) {
err = -ENOMEM;
goto error3;
}
/* Allocate RX descriptor ring in coherent memory */
- greth->rx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
- &greth->rx_bd_base_phys,
- GFP_KERNEL);
+ greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+ &greth->rx_bd_base_phys,
+ GFP_KERNEL);
if (!greth->rx_bd_base) {
err = -ENOMEM;
goto error4;
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
index 0b60921c392f..16477aa6d61f 100644
--- a/drivers/net/ethernet/alacritech/slicoss.c
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -795,8 +795,8 @@ static int slic_init_stat_queue(struct slic_device *sdev)
size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
- descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
- GFP_KERNEL);
+ descs = dma_alloc_coherent(&sdev->pdev->dev, size, &paddr,
+ GFP_KERNEL);
if (!descs) {
netdev_err(sdev->netdev,
"failed to allocate status descriptors\n");
@@ -1240,8 +1240,8 @@ static int slic_init_shmem(struct slic_device *sdev)
struct slic_shmem_data *sm_data;
dma_addr_t paddr;
- sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
- &paddr, GFP_KERNEL);
+ sm_data = dma_alloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+ &paddr, GFP_KERNEL);
if (!sm_data) {
dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
return -ENOMEM;
@@ -1621,8 +1621,8 @@ static int slic_read_eeprom(struct slic_device *sdev)
int err = 0;
u8 *mac[2];
- eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
- &paddr, GFP_KERNEL);
+ eeprom = dma_alloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+ &paddr, GFP_KERNEL);
if (!eeprom)
return -ENOMEM;
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 4f11f98347ed..1827ef1f6d55 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -2059,7 +2059,7 @@ static inline void ace_tx_int(struct net_device *dev,
if (skb) {
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
info->skb = NULL;
}
diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c
index 0fb986ba3290..0ae723f75341 100644
--- a/drivers/net/ethernet/altera/altera_msgdma.c
+++ b/drivers/net/ethernet/altera/altera_msgdma.c
@@ -145,7 +145,8 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
& 0xffff;
if (inuse) { /* Tx FIFO is not empty */
- ready = priv->tx_prod - priv->tx_cons - inuse - 1;
+ ready = max_t(int,
+ priv->tx_prod - priv->tx_cons - inuse - 1, 0);
} else {
/* Check for buffered last packet */
status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status));
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 02921d877c08..aa1d1f5339d2 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
priv->phy_iface);
- if (IS_ERR(phydev))
+ if (IS_ERR(phydev)) {
netdev_err(dev, "Could not attach to PHY\n");
+ phydev = NULL;
+ }
} else {
int ret;
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
index 420cede41ca4..b17d435de09f 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -111,8 +111,8 @@ static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue)
struct ena_com_admin_sq *sq = &queue->sq;
u16 size = ADMIN_SQ_SIZE(queue->q_depth);
- sq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
- GFP_KERNEL);
+ sq->entries = dma_alloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
+ GFP_KERNEL);
if (!sq->entries) {
pr_err("memory allocation failed");
@@ -133,8 +133,8 @@ static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue)
struct ena_com_admin_cq *cq = &queue->cq;
u16 size = ADMIN_CQ_SIZE(queue->q_depth);
- cq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
- GFP_KERNEL);
+ cq->entries = dma_alloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
+ GFP_KERNEL);
if (!cq->entries) {
pr_err("memory allocation failed");
@@ -156,8 +156,8 @@ static int ena_com_admin_init_aenq(struct ena_com_dev *dev,
dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH;
size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH);
- aenq->entries = dma_zalloc_coherent(dev->dmadev, size, &aenq->dma_addr,
- GFP_KERNEL);
+ aenq->entries = dma_alloc_coherent(dev->dmadev, size, &aenq->dma_addr,
+ GFP_KERNEL);
if (!aenq->entries) {
pr_err("memory allocation failed");
@@ -344,15 +344,15 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
dev_node = dev_to_node(ena_dev->dmadev);
set_dev_node(ena_dev->dmadev, ctx->numa_node);
io_sq->desc_addr.virt_addr =
- dma_zalloc_coherent(ena_dev->dmadev, size,
- &io_sq->desc_addr.phys_addr,
- GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, size,
+ &io_sq->desc_addr.phys_addr,
+ GFP_KERNEL);
set_dev_node(ena_dev->dmadev, dev_node);
if (!io_sq->desc_addr.virt_addr) {
io_sq->desc_addr.virt_addr =
- dma_zalloc_coherent(ena_dev->dmadev, size,
- &io_sq->desc_addr.phys_addr,
- GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, size,
+ &io_sq->desc_addr.phys_addr,
+ GFP_KERNEL);
}
if (!io_sq->desc_addr.virt_addr) {
@@ -425,14 +425,14 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
prev_node = dev_to_node(ena_dev->dmadev);
set_dev_node(ena_dev->dmadev, ctx->numa_node);
io_cq->cdesc_addr.virt_addr =
- dma_zalloc_coherent(ena_dev->dmadev, size,
- &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, size,
+ &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
set_dev_node(ena_dev->dmadev, prev_node);
if (!io_cq->cdesc_addr.virt_addr) {
io_cq->cdesc_addr.virt_addr =
- dma_zalloc_coherent(ena_dev->dmadev, size,
- &io_cq->cdesc_addr.phys_addr,
- GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, size,
+ &io_cq->cdesc_addr.phys_addr,
+ GFP_KERNEL);
}
if (!io_cq->cdesc_addr.virt_addr) {
@@ -1026,8 +1026,8 @@ static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
struct ena_rss *rss = &ena_dev->rss;
rss->hash_key =
- dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
- &rss->hash_key_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
+ &rss->hash_key_dma_addr, GFP_KERNEL);
if (unlikely(!rss->hash_key))
return -ENOMEM;
@@ -1050,8 +1050,8 @@ static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev)
struct ena_rss *rss = &ena_dev->rss;
rss->hash_ctrl =
- dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
- &rss->hash_ctrl_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
+ &rss->hash_ctrl_dma_addr, GFP_KERNEL);
if (unlikely(!rss->hash_ctrl))
return -ENOMEM;
@@ -1094,8 +1094,8 @@ static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev,
sizeof(struct ena_admin_rss_ind_table_entry);
rss->rss_ind_tbl =
- dma_zalloc_coherent(ena_dev->dmadev, tbl_size,
- &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, tbl_size,
+ &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
if (unlikely(!rss->rss_ind_tbl))
goto mem_err1;
@@ -1649,9 +1649,9 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
spin_lock_init(&mmio_read->lock);
mmio_read->read_resp =
- dma_zalloc_coherent(ena_dev->dmadev,
- sizeof(*mmio_read->read_resp),
- &mmio_read->read_resp_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev,
+ sizeof(*mmio_read->read_resp),
+ &mmio_read->read_resp_dma_addr, GFP_KERNEL);
if (unlikely(!mmio_read->read_resp))
goto err;
@@ -2623,8 +2623,8 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev)
struct ena_host_attribute *host_attr = &ena_dev->host_attr;
host_attr->host_info =
- dma_zalloc_coherent(ena_dev->dmadev, SZ_4K,
- &host_attr->host_info_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, SZ_4K,
+ &host_attr->host_info_dma_addr, GFP_KERNEL);
if (unlikely(!host_attr->host_info))
return -ENOMEM;
@@ -2641,8 +2641,9 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
struct ena_host_attribute *host_attr = &ena_dev->host_attr;
host_attr->debug_area_virt_addr =
- dma_zalloc_coherent(ena_dev->dmadev, debug_area_size,
- &host_attr->debug_area_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ena_dev->dmadev, debug_area_size,
+ &host_attr->debug_area_dma_addr,
+ GFP_KERNEL);
if (unlikely(!host_attr->debug_area_virt_addr)) {
host_attr->debug_area_size = 0;
return -ENOMEM;
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index a70bb1bb90e7..a6eacf2099c3 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -2663,11 +2663,6 @@ static int ena_restore_device(struct ena_adapter *adapter)
goto err_device_destroy;
}
- clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
- /* Make sure we don't have a race with AENQ Links state handler */
- if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
- netif_carrier_on(adapter->netdev);
-
rc = ena_enable_msix_and_set_admin_interrupts(adapter,
adapter->num_queues);
if (rc) {
@@ -2684,6 +2679,11 @@ static int ena_restore_device(struct ena_adapter *adapter)
}
set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
+
+ clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
+ if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
+ netif_carrier_on(adapter->netdev);
+
mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
dev_err(&pdev->dev,
"Device reset completed successfully, Driver info: %s\n",
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h
index dc8b6173d8d8..63870072cbbd 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 2
#define DRV_MODULE_VER_MINOR 0
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 3
#define DRV_MODULE_NAME "ena"
#ifndef DRV_MODULE_VERSION
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index a90080f12e67..145fe71fd155 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -435,7 +435,7 @@ static int amd8111e_restart(struct net_device *dev)
int i,reg_val;
/* stop the chip */
- writel(RUN, mmio + CMD0);
+ writel(RUN, mmio + CMD0);
if(amd8111e_init_ring(dev))
return -ENOMEM;
@@ -666,7 +666,7 @@ static int amd8111e_tx(struct net_device *dev)
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
lp->tx_skbuff[tx_index]->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
+ dev_consume_skb_irq(lp->tx_skbuff[tx_index]);
lp->tx_skbuff[tx_index] = NULL;
lp->tx_dma_addr[tx_index] = 0;
}
@@ -1720,7 +1720,7 @@ static void amd8111e_config_ipg(struct timer_list *t)
writew((u32)tmp_ipg, mmio + IPG);
writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1);
}
- mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES);
+ mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES);
return;
}
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index e833d1b3fe18..e5073aeea06a 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1167,7 +1167,7 @@ static int au1000_probe(struct platform_device *pdev)
/* Allocate the data buffers
* Snooping works fine with eth on all au1xxx
*/
- aup->vaddr = (u32)dma_alloc_attrs(NULL, MAX_BUF_SIZE *
+ aup->vaddr = (u32)dma_alloc_attrs(&pdev->dev, MAX_BUF_SIZE *
(NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0,
DMA_ATTR_NON_CONSISTENT);
@@ -1349,7 +1349,7 @@ err_remap3:
err_remap2:
iounmap(aup->mac);
err_remap1:
- dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+ dma_free_attrs(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
(void *)aup->vaddr, aup->dma_addr,
DMA_ATTR_NON_CONSISTENT);
err_vaddr:
@@ -1383,7 +1383,7 @@ static int au1000_remove(struct platform_device *pdev)
if (aup->tx_db_inuse[i])
au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
- dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+ dma_free_attrs(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
(void *)aup->vaddr, aup->dma_addr,
DMA_ATTR_NON_CONSISTENT);
diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c
index b56d84c7df46..f90b454b1642 100644
--- a/drivers/net/ethernet/amd/lance.c
+++ b/drivers/net/ethernet/amd/lance.c
@@ -1084,7 +1084,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id)
/* We must free the original skb if it's not a data-only copy
in the bounce buffer. */
if (lp->tx_skbuff[entry]) {
- dev_kfree_skb_irq(lp->tx_skbuff[entry]);
+ dev_consume_skb_irq(lp->tx_skbuff[entry]);
lp->tx_skbuff[entry] = NULL;
}
dirty_tx++;
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index 8931ce6bab7b..87ff5d6d1b22 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -1028,7 +1028,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0)
#ifdef XMT_VIA_SKB
if(p->tmd_skb[p->tmdlast]) {
- dev_kfree_skb_irq(p->tmd_skb[p->tmdlast]);
+ dev_consume_skb_irq(p->tmd_skb[p->tmdlast]);
p->tmd_skb[p->tmdlast] = NULL;
}
#endif
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index d272dc6984ac..b40d4377cc71 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -431,8 +431,6 @@
#define MAC_MDIOSCAR_PA_WIDTH 5
#define MAC_MDIOSCAR_RA_INDEX 0
#define MAC_MDIOSCAR_RA_WIDTH 16
-#define MAC_MDIOSCAR_REG_INDEX 0
-#define MAC_MDIOSCAR_REG_WIDTH 21
#define MAC_MDIOSCCDR_BUSY_INDEX 22
#define MAC_MDIOSCCDR_BUSY_WIDTH 1
#define MAC_MDIOSCCDR_CMD_INDEX 16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 1e929a1e4ca7..4666084eda16 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
}
}
+static unsigned int xgbe_create_mdio_sca(int port, int reg)
+{
+ unsigned int mdio_sca, da;
+
+ da = (reg & MII_ADDR_C45) ? reg >> 16 : 0;
+
+ mdio_sca = 0;
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
+ XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+
+ return mdio_sca;
+}
+
static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
int reg, u16 val)
{
@@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
reinit_completion(&pdata->mdio_complete);
- mdio_sca = 0;
- XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
- XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+ mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0;
@@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
reinit_completion(&pdata->mdio_complete);
- mdio_sca = 0;
- XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
- XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+ mdio_sca = xgbe_create_mdio_sca(addr, reg);
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
mdio_sccd = 0;
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index 0f2ad50f3bd7..87b142a312e0 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -206,8 +206,8 @@ static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
/* Packet buffers should be 64B aligned */
- pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
- GFP_ATOMIC);
+ pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
+ GFP_ATOMIC);
if (unlikely(!pkt_buf)) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -428,8 +428,8 @@ static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
ring->ndev = ndev;
size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
- ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma_addr,
- GFP_KERNEL);
+ ring->desc_addr = dma_alloc_coherent(dev, size, &ring->dma_addr,
+ GFP_KERNEL);
if (!ring->desc_addr)
goto err;
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
index 6a8e2567f2bd..4d3855ceb500 100644
--- a/drivers/net/ethernet/apple/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -777,7 +777,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
if (bp->tx_bufs[bp->tx_empty]) {
++dev->stats.tx_packets;
- dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
+ dev_consume_skb_irq(bp->tx_bufs[bp->tx_empty]);
}
bp->tx_bufs[bp->tx_empty] = NULL;
bp->tx_fullup = 0;
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
index 68b9ee489489..4d9819d2894d 100644
--- a/drivers/net/ethernet/apple/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -764,7 +764,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
dev->stats.tx_bytes += mp->tx_bufs[i]->len;
++dev->stats.tx_packets;
}
- dev_kfree_skb_irq(mp->tx_bufs[i]);
+ dev_consume_skb_irq(mp->tx_bufs[i]);
--mp->tx_active;
if (++i >= N_TX_RING)
i = 0;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index 38e87eed76b9..a718d7a1f76c 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -138,7 +138,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
u8 *p = data;
if (stringset == ETH_SS_STATS) {
- memcpy(p, *aq_ethtool_stat_names,
+ memcpy(p, aq_ethtool_stat_names,
sizeof(aq_ethtool_stat_names));
p = p + sizeof(aq_ethtool_stat_names);
for (i = 0; i < cfg->vecs; i++) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
index dc88a1221f1d..bc711238ca0c 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
@@ -14,6 +14,8 @@
#ifndef AQ_HW_UTILS_H
#define AQ_HW_UTILS_H
+#include <linux/iopoll.h>
+
#include "aq_common.h"
#ifndef HIDWORD
@@ -23,18 +25,6 @@
#define AQ_HW_SLEEP(_US_) mdelay(_US_)
-#define AQ_HW_WAIT_FOR(_B_, _US_, _N_) \
-do { \
- unsigned int AQ_HW_WAIT_FOR_i; \
- for (AQ_HW_WAIT_FOR_i = _N_; (!(_B_)) && (AQ_HW_WAIT_FOR_i);\
- --AQ_HW_WAIT_FOR_i) {\
- udelay(_US_); \
- } \
- if (!AQ_HW_WAIT_FOR_i) {\
- err = -ETIME; \
- } \
-} while (0)
-
#define aq_pr_err(...) pr_err(AQ_CFG_DRV_NAME ": " __VA_ARGS__)
#define aq_pr_trace(...) pr_info(AQ_CFG_DRV_NAME ": " __VA_ARGS__)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 0147c037ca96..ff83667410bd 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -986,4 +986,4 @@ void aq_nic_shutdown(struct aq_nic_s *self)
err_exit:
rtnl_unlock();
-} \ No newline at end of file
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index c8b44cdb91c1..0217ff4669a4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -170,6 +170,8 @@ void aq_pci_func_free_irqs(struct aq_nic_s *self)
for (i = 32U; i--;) {
if (!((1U << i) & self->msix_entry_mask))
continue;
+ if (i >= AQ_CFG_VECS_MAX)
+ continue;
if (pdev->msix_enabled)
irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index 2469ed4d86b9..f6f8338153a2 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -85,6 +85,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = {
static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
{
int err = 0;
+ u32 val;
hw_atl_glb_glb_reg_res_dis_set(self, 1U);
hw_atl_pci_pci_reg_res_dis_set(self, 0U);
@@ -95,7 +96,9 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
hw_atl_glb_soft_res_set(self, 1);
/* check 10 times by 1ms */
- AQ_HW_WAIT_FOR(hw_atl_glb_soft_res_get(self) == 0, 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_glb_soft_res_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
@@ -103,7 +106,9 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
hw_atl_itr_res_irq_set(self, 1U);
/* check 10 times by 1ms */
- AQ_HW_WAIT_FOR(hw_atl_itr_res_irq_get(self) == 0, 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_itr_res_irq_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
@@ -181,6 +186,7 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self,
int err = 0;
unsigned int i = 0U;
unsigned int addr = 0U;
+ u32 val;
for (i = 10, addr = 0U; i--; ++addr) {
u32 key_data = cfg->is_rss ?
@@ -188,8 +194,9 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self,
hw_atl_rpf_rss_key_wr_data_set(self, key_data);
hw_atl_rpf_rss_key_addr_set(self, addr);
hw_atl_rpf_rss_key_wr_en_set(self, 1U);
- AQ_HW_WAIT_FOR(hw_atl_rpf_rss_key_wr_en_get(self) == 0,
- 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_rpf_rss_key_wr_en_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
}
@@ -207,8 +214,9 @@ static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self,
u32 i = 0U;
u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues);
int err = 0;
- u16 bitary[(HW_ATL_A0_RSS_REDIRECTION_MAX *
- HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)];
+ u16 bitary[1 + (HW_ATL_A0_RSS_REDIRECTION_MAX *
+ HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)];
+ u32 val;
memset(bitary, 0, sizeof(bitary));
@@ -222,8 +230,9 @@ static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self,
hw_atl_rpf_rss_redir_tbl_wr_data_set(self, bitary[i]);
hw_atl_rpf_rss_redir_tbl_addr_set(self, i);
hw_atl_rpf_rss_redir_wr_en_set(self, 1U);
- AQ_HW_WAIT_FOR(hw_atl_rpf_rss_redir_wr_en_get(self) == 0,
- 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_rpf_rss_redir_wr_en_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
}
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index b58ca7cb8e9d..b31dba1b1a55 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -173,6 +173,7 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
int err = 0;
unsigned int i = 0U;
unsigned int addr = 0U;
+ u32 val;
for (i = 10, addr = 0U; i--; ++addr) {
u32 key_data = cfg->is_rss ?
@@ -180,8 +181,9 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self,
hw_atl_rpf_rss_key_wr_data_set(self, key_data);
hw_atl_rpf_rss_key_addr_set(self, addr);
hw_atl_rpf_rss_key_wr_en_set(self, 1U);
- AQ_HW_WAIT_FOR(hw_atl_rpf_rss_key_wr_en_get(self) == 0,
- 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_rpf_rss_key_wr_en_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
}
@@ -199,8 +201,9 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
u32 i = 0U;
u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues);
int err = 0;
- u16 bitary[(HW_ATL_B0_RSS_REDIRECTION_MAX *
- HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)];
+ u16 bitary[1 + (HW_ATL_B0_RSS_REDIRECTION_MAX *
+ HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)];
+ u32 val;
memset(bitary, 0, sizeof(bitary));
@@ -214,8 +217,9 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
hw_atl_rpf_rss_redir_tbl_wr_data_set(self, bitary[i]);
hw_atl_rpf_rss_redir_tbl_addr_set(self, i);
hw_atl_rpf_rss_redir_wr_en_set(self, 1U);
- AQ_HW_WAIT_FOR(hw_atl_rpf_rss_redir_wr_en_get(self) == 0,
- 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_rpf_rss_redir_wr_en_get,
+ self, val, val == 0,
+ 1000U, 10000U);
if (err < 0)
goto err_exit;
}
@@ -275,6 +279,9 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
{
+ /* Tx TC/Queue number config */
+ hw_atl_rpb_tps_tx_tc_mode_set(self, 1U);
+
hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U);
hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U);
hw_atl_thm_lso_tcp_flag_of_last_pkt_set(self, 0x0F7FU);
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
index 939f77e2e117..0722b8e01964 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
@@ -1274,6 +1274,15 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en)
HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en);
}
+void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
+ u32 tx_traf_class_mode)
+{
+ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR,
+ HW_ATL_TPB_TX_TC_MODE_MSK,
+ HW_ATL_TPB_TX_TC_MODE_SHIFT,
+ tx_traf_class_mode);
+}
+
void hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(struct aq_hw_s *aq_hw,
u32 tx_buff_hi_threshold_per_tc,
u32 buffer)
@@ -1585,3 +1594,24 @@ void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
HW_ATL_RPF_L3_DSTA_ADR(location + i),
ipv6_dest[i]);
}
+
+u32 hw_atl_sem_ram_get(struct aq_hw_s *self)
+{
+ return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
+}
+
+u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp)
+{
+ return aq_hw_read_reg(aq_hw,
+ HW_ATL_GLB_CPU_SCRATCH_SCP_ADR(scratch_scp));
+}
+
+u32 hw_atl_scrpad12_get(struct aq_hw_s *self)
+{
+ return hw_atl_scrpad_get(self, 0xB);
+}
+
+u32 hw_atl_scrpad25_get(struct aq_hw_s *self)
+{
+ return hw_atl_scrpad_get(self, 0x18);
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
index 03c570d115fe..d46351890b16 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
@@ -605,6 +605,10 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw,
/* tpb */
+/* set TX Traffic Class Mode */
+void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
+ u32 tx_traf_class_mode);
+
/* set tx buffer enable */
void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en);
@@ -752,4 +756,16 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_dest);
+/* get global microprocessor ram semaphore */
+u32 hw_atl_sem_ram_get(struct aq_hw_s *self);
+
+/* get global microprocessor scratch pad register */
+u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp);
+
+/* get global microprocessor scratch pad 12 register */
+u32 hw_atl_scrpad12_get(struct aq_hw_s *self);
+
+/* get global microprocessor scratch pad 25 register */
+u32 hw_atl_scrpad25_get(struct aq_hw_s *self);
+
#endif /* HW_ATL_LLH_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
index 8470d92db812..fb45bc2d99cf 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
@@ -1948,6 +1948,19 @@
/* default value of bitfield tx_buf_en */
#define HW_ATL_TPB_TX_BUF_EN_DEFAULT 0x0
+/* register address for bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_ADDR 0x00007900
+/* bitmask for bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_MSK 0x00000100
+/* inverted bitmask for bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_MSKN 0xFFFFFEFF
+/* lower bit position of bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_SHIFT 8
+/* width of bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_WIDTH 1
+/* default value of bitfield tx_tc_mode */
+#define HW_ATL_TPB_TX_TC_MODE_DEFAULT 0x0
+
/* tx tx{b}_hi_thresh[c:0] bitfield definitions
* preprocessor definitions for the bitfield "tx{b}_hi_thresh[c:0]".
* parameter: buffer {b} | stride size 0x10 | range [0, 7]
@@ -2519,4 +2532,6 @@
/* Default value of bitfield l3_da0[1F:0] */
#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0
+#define HW_ATL_FW_SM_RAM 0x2U
+
#endif /* HW_ATL_LLH_INTERNAL_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 9b74a3197d7f..eb4b99d56081 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -25,7 +25,9 @@
#define HW_ATL_MIF_ADDR 0x0208U
#define HW_ATL_MIF_VAL 0x020CU
-#define HW_ATL_FW_SM_RAM 0x2U
+#define HW_ATL_RPC_CONTROL_ADR 0x0338U
+#define HW_ATL_RPC_STATE_ADR 0x033CU
+
#define HW_ATL_MPI_FW_VERSION 0x18
#define HW_ATL_MPI_CONTROL_ADR 0x0368U
#define HW_ATL_MPI_STATE_ADR 0x036CU
@@ -53,6 +55,12 @@ static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state);
+static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
+static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
+static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
+static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
+static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
+
int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
{
int err = 0;
@@ -234,6 +242,7 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self)
{
int k;
u32 boot_exit_code = 0;
+ u32 val;
for (k = 0; k < 1000; ++k) {
u32 flb_status = aq_hw_read_reg(self,
@@ -260,9 +269,11 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self)
int err = 0;
hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
- AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR) &
- HW_ATL_MPI_STATE_MSK) == MPI_DEINIT,
- 10, 1000U);
+ err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
+ self, val,
+ (val & HW_ATL_MPI_STATE_MSK) ==
+ MPI_DEINIT,
+ 10, 10000U);
if (err)
return err;
}
@@ -277,16 +288,17 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt)
{
int err = 0;
+ u32 val;
- AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self,
- HW_ATL_FW_SM_RAM) == 1U,
- 1U, 10000U);
+ err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
+ self, val, val == 1U,
+ 1U, 10000U);
if (err < 0) {
bool is_locked;
hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
- is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
+ is_locked = hw_atl_sem_ram_get(self);
if (!is_locked) {
err = -ETIME;
goto err_exit;
@@ -299,13 +311,14 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
if (IS_CHIP_FEATURE(REVISION_B1))
- AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
- HW_ATL_MIF_ADDR),
- 1, 1000U);
+ err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
+ self, val, val != a,
+ 1U, 1000U);
else
- AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
- HW_ATL_MIF_CMD)),
- 1, 1000U);
+ err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
+ self, val,
+ !(val & 0x100),
+ 1U, 1000U);
*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
a += 4;
@@ -320,10 +333,11 @@ err_exit:
static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
u32 cnt)
{
+ u32 val;
int err = 0;
bool is_locked;
- is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
+ is_locked = hw_atl_sem_ram_get(self);
if (!is_locked) {
err = -ETIME;
goto err_exit;
@@ -337,10 +351,11 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
(0x80000000 | (0xFFFF & (offset * 4))));
hw_atl_mcp_up_force_intr_set(self, 1);
/* 1000 times by 10us = 10ms */
- AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
- 0x32C) & 0xF0000000) !=
- 0x80000000,
- 10, 1000);
+ err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
+ self, val,
+ (val & 0xF0000000) ==
+ 0x80000000,
+ 10U, 10000U);
}
} else {
u32 offset = 0;
@@ -351,8 +366,10 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
aq_hw_write_reg(self, 0x20C, p[offset]);
aq_hw_write_reg(self, 0x200, 0xC000);
- AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U) &
- 0x100) == 0, 10, 1000);
+ err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
+ self, val,
+ (val & 0x100) == 0,
+ 1000U, 10000U);
}
}
@@ -395,15 +412,14 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
/* check 10 times by 1ms */
- AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
- aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
+ err = readx_poll_timeout_atomic(hw_atl_scrpad25_get,
+ self, self->mbox_addr,
+ self->mbox_addr != 0U,
+ 1000U, 10000U);
return err;
}
-#define HW_ATL_RPC_CONTROL_ADR 0x0338U
-#define HW_ATL_RPC_STATE_ADR 0x033CU
-
struct aq_hw_atl_utils_fw_rpc_tid_s {
union {
u32 val;
@@ -452,10 +468,10 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
self->rpc_tid = sw.tid;
- AQ_HW_WAIT_FOR(sw.tid ==
- (fw.val =
- aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
- fw.tid), 1000U, 100U);
+ err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get,
+ self, fw.val,
+ sw.tid == fw.tid,
+ 1000U, 100000U);
if (fw.len == 0xFFFFU) {
err = hw_atl_utils_fw_rpc_call(self, sw.len);
@@ -559,10 +575,11 @@ static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
transaction_id = mbox.transaction_id;
- AQ_HW_WAIT_FOR(transaction_id !=
- (hw_atl_utils_mpi_read_mbox(self, &mbox),
- mbox.transaction_id),
- 1000U, 100U);
+ err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid,
+ self, mbox.transaction_id,
+ transaction_id !=
+ mbox.transaction_id,
+ 1000U, 100000U);
if (err < 0)
goto err_exit;
}
@@ -585,7 +602,7 @@ err_exit:
int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
{
- u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
+ u32 cp0x036C = hw_atl_utils_mpi_get_state(self);
u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
struct aq_hw_link_status_s *link_status = &self->aq_link_status;
@@ -905,6 +922,35 @@ err_exit:
return err;
}
+static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self)
+{
+ struct hw_atl_utils_mbox_header mbox;
+
+ hw_atl_utils_mpi_read_mbox(self, &mbox);
+
+ return mbox.transaction_id;
+}
+
+static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
+}
+
+static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_MIF_CMD);
+}
+
+static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_MIF_ADDR);
+}
+
+static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
+}
+
const struct aq_fw_ops aq_fw_1x_ops = {
.init = hw_atl_utils_mpi_create,
.deinit = hw_atl_fw1x_deinit,
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
index 7de3220d9cab..fe6c5658e016 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
@@ -20,15 +20,14 @@
#include "hw_atl_utils.h"
#include "hw_atl_llh.h"
-#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364
-#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360
#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334
+#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360
+#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364
#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368
#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C
-
#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
-#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
+#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
#define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE)
#define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE)
@@ -72,17 +71,24 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
static int aq_fw2x_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state);
+static u32 aq_fw2x_mbox_get(struct aq_hw_s *self);
+static u32 aq_fw2x_rpc_get(struct aq_hw_s *self);
+static u32 aq_fw2x_state2_get(struct aq_hw_s *self);
+
static int aq_fw2x_init(struct aq_hw_s *self)
{
int err = 0;
/* check 10 times by 1ms */
- AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
- aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)),
- 1000U, 10U);
- AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
- aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)),
- 1000U, 100U);
+ err = readx_poll_timeout_atomic(aq_fw2x_mbox_get,
+ self, self->mbox_addr,
+ self->mbox_addr != 0U,
+ 1000U, 10000U);
+
+ err = readx_poll_timeout_atomic(aq_fw2x_rpc_get,
+ self, self->rpc_addr,
+ self->rpc_addr != 0U,
+ 1000U, 100000U);
return err;
}
@@ -286,16 +292,18 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self)
int err = 0;
u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
+ u32 stats_val;
/* Toggle statistics bit for FW to update */
mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
/* Wait FW to report back */
- AQ_HW_WAIT_FOR(orig_stats_val !=
- (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
- BIT(CAPS_HI_STATISTICS)),
- 1U, 10000U);
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
+ self, stats_val,
+ orig_stats_val != (stats_val &
+ BIT(CAPS_HI_STATISTICS)),
+ 1U, 10000U);
if (err)
return err;
@@ -309,6 +317,7 @@ static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
unsigned int rpc_size = 0U;
u32 mpi_opts;
int err = 0;
+ u32 val;
rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg);
@@ -337,8 +346,10 @@ static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
mpi_opts |= HW_ATL_FW2X_CTRL_SLEEP_PROXY;
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
- AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
- HW_ATL_FW2X_CTRL_SLEEP_PROXY), 1U, 10000U);
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
+ self, val,
+ val & HW_ATL_FW2X_CTRL_SLEEP_PROXY,
+ 1U, 10000U);
err_exit:
return err;
@@ -350,6 +361,7 @@ static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
struct fw2x_msg_wol *msg = NULL;
u32 mpi_opts;
int err = 0;
+ u32 val;
err = hw_atl_utils_fw_rpc_wait(self, &rpc);
if (err < 0)
@@ -374,8 +386,9 @@ static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
mpi_opts |= HW_ATL_FW2X_CTRL_WOL;
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
- AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
- HW_ATL_FW2X_CTRL_WOL), 1U, 10000U);
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
+ self, val, val & HW_ATL_FW2X_CTRL_WOL,
+ 1U, 10000U);
err_exit:
return err;
@@ -425,7 +438,7 @@ static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
*supported_rates = fw2x_to_eee_mask(caps_hi);
- mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
+ mpi_state = aq_fw2x_state2_get(self);
*rate = fw2x_to_eee_mask(mpi_state);
return err;
@@ -455,7 +468,7 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
{
- u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
+ u32 mpi_state = aq_fw2x_state2_get(self);
if (mpi_state & HW_ATL_FW2X_CAP_PAUSE)
if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
@@ -471,6 +484,21 @@ static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
return 0;
}
+static u32 aq_fw2x_mbox_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR);
+}
+
+static u32 aq_fw2x_rpc_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR);
+}
+
+static u32 aq_fw2x_state2_get(struct aq_hw_s *self)
+{
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
+}
+
const struct aq_fw_ops aq_fw_2x_ops = {
.init = aq_fw2x_init,
.deinit = aq_fw2x_deinit,
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index 4406325fdd9f..ff3d68532f5f 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -148,7 +148,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
dma_unmap_len(tx_buff, len), DMA_TO_DEVICE);
/* return the sk_buff to system */
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
txbd->data = 0;
txbd->info = 0;
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index c131cfc1b79d..e3538ba7d0e7 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -660,10 +660,9 @@ static int alx_alloc_rings(struct alx_priv *alx)
alx->num_txq +
sizeof(struct alx_rrd) * alx->rx_ringsz +
sizeof(struct alx_rfd) * alx->rx_ringsz;
- alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
- alx->descmem.size,
- &alx->descmem.dma,
- GFP_KERNEL);
+ alx->descmem.virt = dma_alloc_coherent(&alx->hw.pdev->dev,
+ alx->descmem.size,
+ &alx->descmem.dma, GFP_KERNEL);
if (!alx->descmem.virt)
return -ENOMEM;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 7087b88550db..0f1eb1981469 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -1019,8 +1019,8 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
8 * 4;
- ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size,
- &ring_header->dma, GFP_KERNEL);
+ ring_header->desc = dma_alloc_coherent(&pdev->dev, ring_header->size,
+ &ring_header->dma, GFP_KERNEL);
if (unlikely(!ring_header->desc)) {
dev_err(&pdev->dev, "could not get memory for DMA buffer\n");
goto err_nomem;
@@ -1833,10 +1833,10 @@ rrs_checked:
atl1c_clean_rrd(rrd_ring, rrs, rfd_num);
if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) {
atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
- if (netif_msg_rx_err(adapter))
- dev_warn(&pdev->dev,
- "wrong packet! rrs word3 is %x\n",
- rrs->word3);
+ if (netif_msg_rx_err(adapter))
+ dev_warn(&pdev->dev,
+ "wrong packet! rrs word3 is %x\n",
+ rrs->word3);
continue;
}
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 3164aad29bcf..9dfe6a9431e6 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1259,7 +1259,7 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
}
if (tx_buffer->skb) {
- dev_kfree_skb_irq(tx_buffer->skb);
+ dev_consume_skb_irq(tx_buffer->skb);
tx_buffer->skb = NULL;
}
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 63edc5706c09..9e07b469066a 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2088,7 +2088,7 @@ static int atl1_intr_tx(struct atl1_adapter *adapter)
}
if (buffer_info->skb) {
- dev_kfree_skb_irq(buffer_info->skb);
+ dev_consume_skb_irq(buffer_info->skb);
buffer_info->skb = NULL;
}
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index bb41becb6609..d99317b3d891 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -909,7 +909,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb,
(adapter->txd_write_ptr >> 2));
mmiowb();
- dev_kfree_skb_any(skb);
+ dev_consume_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -1335,13 +1335,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl2_adapter *adapter;
- static int cards_found;
+ static int cards_found = 0;
unsigned long mmio_start;
int mmio_len;
int err;
- cards_found = 0;
-
err = pci_enable_device(pdev);
if (err)
return err;
@@ -2946,7 +2944,7 @@ static int atl2_validate_option(int *value, struct atl2_option *opt)
if (*value == ent->i) {
if (ent->str[0] != '\0')
printk(KERN_INFO "%s\n", ent->str);
- return 0;
+ return 0;
}
}
break;
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index c1d3ee9baf7e..716bfbba59cf 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -194,7 +194,6 @@ config SYSTEMPORT
config BNXT
tristate "Broadcom NetXtreme-C/E support"
depends on PCI
- depends on MAY_USE_DEVLINK
select FW_LOADER
select LIBCRC32C
---help---
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index f44808959ff3..97ab0dd25552 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -638,7 +638,7 @@ static void b44_tx(struct b44 *bp)
bytes_compl += skb->len;
pkts_compl++;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
netdev_completed_queue(bp->dev, pkts_compl, bytes_compl);
@@ -1012,7 +1012,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
- dev_kfree_skb_any(skb);
+ dev_consume_skb_any(skb);
skb = bounce_skb;
}
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 6bae973d4dce..09cd188826b1 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -936,7 +936,7 @@ static int bcm_enet_open(struct net_device *dev)
/* allocate rx dma ring */
size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
if (!p) {
ret = -ENOMEM;
goto out_freeirq_tx;
@@ -947,7 +947,7 @@ static int bcm_enet_open(struct net_device *dev)
/* allocate tx dma ring */
size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
if (!p) {
ret = -ENOMEM;
goto out_free_rx_ring;
@@ -2120,7 +2120,7 @@ static int bcm_enetsw_open(struct net_device *dev)
/* allocate rx dma ring */
size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
if (!p) {
dev_err(kdev, "cannot allocate rx ring %u\n", size);
ret = -ENOMEM;
@@ -2132,7 +2132,7 @@ static int bcm_enetsw_open(struct net_device *dev)
/* allocate tx dma ring */
size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
if (!p) {
dev_err(kdev, "cannot allocate tx ring\n");
ret = -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 4574275ef445..bc3ac369cbe3 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -134,6 +134,10 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
reg = rxchk_readl(priv, RXCHK_CONTROL);
+ /* Clear L2 header checks, which would prevent BPDUs
+ * from being received.
+ */
+ reg &= ~RXCHK_L2_HDR_DIS;
if (priv->rx_chk_en)
reg |= RXCHK_EN;
else
@@ -520,7 +524,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
- u32 reg;
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
wol->wolopts = priv->wolopts;
@@ -528,11 +531,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
if (!(priv->wolopts & WAKE_MAGICSECURE))
return;
- /* Return the programmed SecureOn password */
- reg = umac_readl(priv, UMAC_PSW_MS);
- put_unaligned_be16(reg, &wol->sopass[0]);
- reg = umac_readl(priv, UMAC_PSW_LS);
- put_unaligned_be32(reg, &wol->sopass[2]);
+ memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
}
static int bcm_sysport_set_wol(struct net_device *dev,
@@ -548,13 +547,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
if (wol->wolopts & ~supported)
return -EINVAL;
- /* Program the SecureOn password */
- if (wol->wolopts & WAKE_MAGICSECURE) {
- umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
- UMAC_PSW_MS);
- umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
- UMAC_PSW_LS);
- }
+ if (wol->wolopts & WAKE_MAGICSECURE)
+ memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
/* Flag the device and relevant IRQ as wakeup capable */
if (wol->wolopts) {
@@ -1506,8 +1500,8 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
/* We just need one DMA descriptor which is DMA-able, since writing to
* the port will allocate a new descriptor in its internal linked-list
*/
- p = dma_zalloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
- GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
+ GFP_KERNEL);
if (!p) {
netif_err(priv, hw, priv->netdev, "DMA alloc failed\n");
return -ENOMEM;
@@ -2649,13 +2643,18 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
unsigned int index, i = 0;
u32 reg;
- /* Password has already been programmed */
reg = umac_readl(priv, UMAC_MPD_CTRL);
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
reg |= MPD_EN;
reg &= ~PSW_EN;
- if (priv->wolopts & WAKE_MAGICSECURE)
+ if (priv->wolopts & WAKE_MAGICSECURE) {
+ /* Program the SecureOn password */
+ umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+ UMAC_PSW_MS);
+ umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+ UMAC_PSW_LS);
reg |= PSW_EN;
+ }
umac_writel(priv, reg, UMAC_MPD_CTRL);
if (priv->wolopts & WAKE_FILTER) {
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 0887e6356649..0b192fea9c5d 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -12,6 +12,7 @@
#define __BCM_SYSPORT_H
#include <linux/bitmap.h>
+#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/net_dim.h>
@@ -778,6 +779,7 @@ struct bcm_sysport_priv {
unsigned int crc_fwd:1;
u16 rev;
u32 wolopts;
+ u8 sopass[SOPASS_MAX];
unsigned int wol_irq_disabled:1;
/* MIB related fields */
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index cabc8e49ad24..4632dd5dbad1 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -634,9 +634,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
/* Alloc ring of descriptors */
size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
- ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
- &ring->dma_base,
- GFP_KERNEL);
+ ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+ &ring->dma_base,
+ GFP_KERNEL);
if (!ring->cpu_base) {
dev_err(bgmac->dev, "Allocation of TX ring 0x%X failed\n",
ring->mmio_base);
@@ -659,9 +659,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
/* Alloc ring of descriptors */
size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
- ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
- &ring->dma_base,
- GFP_KERNEL);
+ ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+ &ring->dma_base,
+ GFP_KERNEL);
if (!ring->cpu_base) {
dev_err(bgmac->dev, "Allocation of RX ring 0x%X failed\n",
ring->mmio_base);
@@ -1446,7 +1446,7 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac)
struct phy_device *phy_dev;
int err;
- phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
+ phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
if (!phy_dev || IS_ERR(phy_dev)) {
dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index bbb247116045..d63371d70bce 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -844,8 +844,8 @@ bnx2_alloc_stats_blk(struct net_device *dev)
BNX2_SBLK_MSIX_ALIGN_SIZE);
bp->status_stats_size = status_blk_size +
sizeof(struct statistics_block);
- status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size,
- &bp->status_blk_mapping, GFP_KERNEL);
+ status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
+ &bp->status_blk_mapping, GFP_KERNEL);
if (!status_blk)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 5cd3135dfe30..6026b53137aa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -32,7 +32,7 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.712.30-0"
+#define DRV_MODULE_VERSION "1.713.36-0"
#define DRV_MODULE_RELDATE "2014/02/10"
#define BNX2X_BC_VER 0x040200
@@ -2081,7 +2081,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
bool is_pf);
#define BNX2X_ILT_ZALLOC(x, y, size) \
- x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
+ x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
#define BNX2X_ILT_FREE(x, y, size) \
do { \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 142bc11b9fbb..2462e7aa0c5d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -52,7 +52,7 @@ extern int bnx2x_num_queues;
#define BNX2X_PCI_ALLOC(y, size) \
({ \
- void *x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
+ void *x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
if (x) \
DP(NETIF_MSG_HW, \
"BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n", \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
index 46ee2c01f4c5..066765fbef06 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
@@ -449,7 +449,7 @@ static inline void bnx2x_init_fw_wrr(const struct cmng_init_input *input_data,
ccd[cos] =
(u32)input_data->cos_min_rate[cos] * 100 *
(T_FAIR_COEF / (8 * 100 * cosWeightSum));
- if (ccd[cos] < pdata->fair_vars.fair_threshold
+ if (ccd[cos] < pdata->fair_vars.fair_threshold
+ MIN_ABOVE_THRESH) {
ccd[cos] =
pdata->fair_vars.fair_threshold +
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 98d4c5a3ff21..d581d0ae6584 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -837,49 +837,45 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
switch (cos_entry) {
case 0:
- nig_reg_adress_crd_weight =
- (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
- pbf_reg_adress_crd_weight = (port) ?
- PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
- break;
+ nig_reg_adress_crd_weight =
+ (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
+ break;
case 1:
- nig_reg_adress_crd_weight = (port) ?
- NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
- pbf_reg_adress_crd_weight = (port) ?
- PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
- break;
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
+ break;
case 2:
- nig_reg_adress_crd_weight = (port) ?
- NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
+ nig_reg_adress_crd_weight = (port) ?
+ NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+ NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
- pbf_reg_adress_crd_weight = (port) ?
- PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
- break;
+ pbf_reg_adress_crd_weight = (port) ?
+ PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
+ break;
case 3:
- if (port)
+ if (port)
return -EINVAL;
- nig_reg_adress_crd_weight =
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
- pbf_reg_adress_crd_weight =
- PBF_REG_COS3_WEIGHT_P0;
- break;
+ nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
+ pbf_reg_adress_crd_weight = PBF_REG_COS3_WEIGHT_P0;
+ break;
case 4:
- if (port)
- return -EINVAL;
- nig_reg_adress_crd_weight =
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
- pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
- break;
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
+ pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
+ break;
case 5:
- if (port)
- return -EINVAL;
- nig_reg_adress_crd_weight =
- NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
- pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
- break;
+ if (port)
+ return -EINVAL;
+ nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
+ pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
+ break;
}
REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
@@ -966,7 +962,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
if (pri >= max_num_of_cos) {
DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
"parameter Illegal strict priority\n");
- return -EINVAL;
+ return -EINVAL;
}
if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
@@ -1845,28 +1841,28 @@ static int bnx2x_emac_enable(struct link_params *params,
bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
EMAC_TX_MODE_RESET);
- /* pause enable/disable */
- bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
- EMAC_RX_MODE_FLOW_EN);
+ /* pause enable/disable */
+ bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
+ EMAC_RX_MODE_FLOW_EN);
- bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
- (EMAC_TX_MODE_EXT_PAUSE_EN |
- EMAC_TX_MODE_FLOW_EN));
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_PFC_ENABLED)) {
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
- bnx2x_bits_en(bp, emac_base +
- EMAC_REG_EMAC_RX_MODE,
- EMAC_RX_MODE_FLOW_EN);
-
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
- bnx2x_bits_en(bp, emac_base +
- EMAC_REG_EMAC_TX_MODE,
- (EMAC_TX_MODE_EXT_PAUSE_EN |
- EMAC_TX_MODE_FLOW_EN));
- } else
- bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
- EMAC_TX_MODE_FLOW_EN);
+ bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
+ (EMAC_TX_MODE_EXT_PAUSE_EN |
+ EMAC_TX_MODE_FLOW_EN));
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_PFC_ENABLED)) {
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ bnx2x_bits_en(bp, emac_base +
+ EMAC_REG_EMAC_RX_MODE,
+ EMAC_RX_MODE_FLOW_EN);
+
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ bnx2x_bits_en(bp, emac_base +
+ EMAC_REG_EMAC_TX_MODE,
+ (EMAC_TX_MODE_EXT_PAUSE_EN |
+ EMAC_TX_MODE_FLOW_EN));
+ } else
+ bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
+ EMAC_TX_MODE_FLOW_EN);
/* KEEP_VLAN_TAG, promiscuous */
val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
@@ -6339,7 +6335,7 @@ int bnx2x_set_led(struct link_params *params,
*/
if (!vars->link_up)
break;
- /* else: fall through */
+ /* fall through */
case LED_MODE_ON:
if (((params->phy[EXT_PHY1].type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
@@ -6478,9 +6474,9 @@ int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
MDIO_REG_BANK_GP_STATUS,
MDIO_GP_STATUS_TOP_AN_STATUS1,
&gp_status);
- /* Link is up only if both local phy and external phy are up */
- if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
- return -ESRCH;
+ /* Link is up only if both local phy and external phy are up */
+ if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
+ return -ESRCH;
}
/* In XGXS loopback mode, do not check external PHY */
if (params->loopback_mode == LOOPBACK_XGXS)
@@ -7293,8 +7289,8 @@ static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
DP(NETIF_MSG_LINK,
"XAUI workaround has completed\n");
return 0;
- }
- usleep_range(3000, 6000);
+ }
+ usleep_range(3000, 6000);
}
break;
}
@@ -12675,39 +12671,39 @@ static void bnx2x_init_bmac_loopback(struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- vars->link_up = 1;
- vars->line_speed = SPEED_10000;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->mac_type = MAC_TYPE_BMAC;
+ vars->link_up = 1;
+ vars->line_speed = SPEED_10000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_BMAC;
- vars->phy_flags = PHY_XGXS_FLAG;
+ vars->phy_flags = PHY_XGXS_FLAG;
- bnx2x_xgxs_deassert(params);
+ bnx2x_xgxs_deassert(params);
- /* Set bmac loopback */
- bnx2x_bmac_enable(params, vars, 1, 1);
+ /* Set bmac loopback */
+ bnx2x_bmac_enable(params, vars, 1, 1);
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0);
}
static void bnx2x_init_emac_loopback(struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- vars->link_up = 1;
- vars->line_speed = SPEED_1000;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->mac_type = MAC_TYPE_EMAC;
+ vars->link_up = 1;
+ vars->line_speed = SPEED_1000;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->mac_type = MAC_TYPE_EMAC;
- vars->phy_flags = PHY_XGXS_FLAG;
+ vars->phy_flags = PHY_XGXS_FLAG;
- bnx2x_xgxs_deassert(params);
- /* Set bmac loopback */
- bnx2x_emac_enable(params, vars, 1);
- bnx2x_emac_program(params, vars);
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+ bnx2x_xgxs_deassert(params);
+ /* Set bmac loopback */
+ bnx2x_emac_enable(params, vars, 1);
+ bnx2x_emac_program(params, vars);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0);
}
static void bnx2x_init_xmac_loopback(struct link_params *params,
@@ -13073,12 +13069,12 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
}
- if (!CHIP_IS_E3(bp)) {
- bnx2x_set_bmac_rx(bp, params->chip_id, port, 0);
- } else {
- bnx2x_set_xmac_rxtx(params, 0);
- bnx2x_set_umac_rxtx(params, 0);
- }
+ if (!CHIP_IS_E3(bp)) {
+ bnx2x_set_bmac_rx(bp, params->chip_id, port, 0);
+ } else {
+ bnx2x_set_xmac_rxtx(params, 0);
+ bnx2x_set_umac_rxtx(params, 0);
+ }
/* Disable emac */
if (!CHIP_IS_E3(bp))
REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 3b5b47e98c73..626b491f7674 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -11298,7 +11298,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
dev_info.port_hw_config[port].external_phy_config),
SHMEM_RD(bp,
dev_info.port_hw_config[port].external_phy_config2));
- return;
+ return;
}
if (CHIP_IS_E3(bp))
@@ -11998,7 +11998,7 @@ static void validate_set_si_mode(struct bnx2x *bp)
static int bnx2x_get_hwinfo(struct bnx2x *bp)
{
int /*abs*/func = BP_ABS_FUNC(bp);
- int vn, mfw_vn;
+ int vn;
u32 val = 0, val2 = 0;
int rc = 0;
@@ -12083,12 +12083,10 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
/*
* Initialize MF configuration
*/
-
bp->mf_ov = 0;
bp->mf_mode = 0;
bp->mf_sub_mode = 0;
vn = BP_VN(bp);
- mfw_vn = BP_FW_MB_IDX(bp);
if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index a9eaaf3e73a4..7b22a6d8514c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -2977,8 +2977,8 @@ static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
cmd_pos->data.macs_num--;
- DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
- cmd_pos->data.macs_num, cnt);
+ DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
+ cmd_pos->data.macs_num, cnt);
/* Break if we reached the maximum
* number of rules.
@@ -3597,8 +3597,8 @@ static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
/* RESTORE command will restore the entire multicast configuration */
case BNX2X_MCAST_CMD_RESTORE:
p->mcast_list_len = reg_sz;
- DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
- cmd, p->mcast_list_len);
+ DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
+ cmd, p->mcast_list_len);
break;
case BNX2X_MCAST_CMD_ADD:
@@ -3735,8 +3735,8 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1(
i++;
- DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
- cfg_data.mac);
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+ cfg_data.mac);
}
*rdata_idx = i;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index c835f6c7ecd0..c97b642e6537 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -2230,7 +2230,7 @@ int bnx2x_vf_free(struct bnx2x *bp, struct bnx2x_virtf *vf)
rc = bnx2x_vf_close(bp, vf);
if (rc)
goto op_err;
- /* Fallthrough to release resources */
+ /* Fall through - to release resources */
case VF_ACQUIRED:
DP(BNX2X_MSG_IOV, "about to free resources\n");
bnx2x_vf_free_resc(bp, vf);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 8e0a317b31f7..a9bdc21873d3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -1654,13 +1654,9 @@ static int bnx2x_vf_mbx_macvlan_list(struct bnx2x *bp,
{
int i, j;
struct bnx2x_vf_mac_vlan_filters *fl = NULL;
- size_t fsz;
- fsz = tlv->n_mac_vlan_filters *
- sizeof(struct bnx2x_vf_mac_vlan_filter) +
- sizeof(struct bnx2x_vf_mac_vlan_filters);
-
- fl = kzalloc(fsz, GFP_KERNEL);
+ fl = kzalloc(struct_size(fl, filters, tlv->n_mac_vlan_filters),
+ GFP_KERNEL);
if (!fl)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 3aa80da973d7..0bb9d7b3a2b6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1,7 +1,7 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2016 Broadcom Corporation
- * Copyright (c) 2016-2018 Broadcom Limited
+ * Copyright (c) 2016-2019 Broadcom Limited
*
* 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
@@ -31,6 +31,7 @@
#include <asm/page.h>
#include <linux/time.h>
#include <linux/mii.h>
+#include <linux/mdio.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/if_bridge.h>
@@ -112,6 +113,7 @@ enum board_idx {
BCM57454,
BCM5745x_NPAR,
BCM57508,
+ BCM57504,
BCM58802,
BCM58804,
BCM58808,
@@ -155,6 +157,7 @@ static const struct {
[BCM57454] = { "Broadcom BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" },
[BCM5745x_NPAR] = { "Broadcom BCM5745x NetXtreme-E Ethernet Partition" },
[BCM57508] = { "Broadcom BCM57508 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" },
+ [BCM57504] = { "Broadcom BCM57504 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" },
[BCM58802] = { "Broadcom BCM58802 NetXtreme-S 10Gb/25Gb/40Gb/50Gb Ethernet" },
[BCM58804] = { "Broadcom BCM58804 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" },
[BCM58808] = { "Broadcom BCM58808 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" },
@@ -201,6 +204,7 @@ static const struct pci_device_id bnxt_pci_tbl[] = {
{ PCI_VDEVICE(BROADCOM, 0x16f0), .driver_data = BCM58808 },
{ PCI_VDEVICE(BROADCOM, 0x16f1), .driver_data = BCM57452 },
{ PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 },
+ { PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 },
{ PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 },
{ PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 },
#ifdef CONFIG_BNXT_SRIOV
@@ -500,6 +504,12 @@ normal_tx:
}
length >>= 9;
+ if (unlikely(length >= ARRAY_SIZE(bnxt_lhint_arr))) {
+ dev_warn_ratelimited(&pdev->dev, "Dropped oversize %d bytes TX packet.\n",
+ skb->len);
+ i = 0;
+ goto tx_dma_error;
+ }
flags |= bnxt_lhint_arr[length];
txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
@@ -3449,10 +3459,10 @@ alloc_ext_stats:
goto alloc_tx_ext_stats;
bp->hw_rx_port_stats_ext =
- dma_zalloc_coherent(&pdev->dev,
- sizeof(struct rx_port_stats_ext),
- &bp->hw_rx_port_stats_ext_map,
- GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev,
+ sizeof(struct rx_port_stats_ext),
+ &bp->hw_rx_port_stats_ext_map,
+ GFP_KERNEL);
if (!bp->hw_rx_port_stats_ext)
return 0;
@@ -3462,10 +3472,10 @@ alloc_tx_ext_stats:
if (bp->hwrm_spec_code >= 0x10902) {
bp->hw_tx_port_stats_ext =
- dma_zalloc_coherent(&pdev->dev,
- sizeof(struct tx_port_stats_ext),
- &bp->hw_tx_port_stats_ext_map,
- GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev,
+ sizeof(struct tx_port_stats_ext),
+ &bp->hw_tx_port_stats_ext_map,
+ GFP_KERNEL);
}
bp->flags |= BNXT_FLAG_PORT_STATS_EXT;
}
@@ -3903,7 +3913,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
if (len)
break;
/* on first few passes, just barely sleep */
- if (i < DFLT_HWRM_CMD_TIMEOUT)
+ if (i < HWRM_SHORT_TIMEOUT_COUNTER)
usleep_range(HWRM_SHORT_MIN_TIMEOUT,
HWRM_SHORT_MAX_TIMEOUT);
else
@@ -3926,7 +3936,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
dma_rmb();
if (*valid)
break;
- udelay(1);
+ usleep_range(1, 5);
}
if (j >= HWRM_VALID_BIT_DELAY_USEC) {
@@ -4973,12 +4983,18 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
u32 map_idx = ring->map_idx;
+ unsigned int vector;
+ vector = bp->irq_tbl[map_idx].vector;
+ disable_irq_nosync(vector);
rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
- if (rc)
+ if (rc) {
+ enable_irq(vector);
goto err_out;
+ }
bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id);
bnxt_db_nq(bp, &cpr->cp_db, cpr->cp_raw_cons);
+ enable_irq(vector);
bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
if (!i) {
@@ -5601,7 +5617,8 @@ static int bnxt_hwrm_check_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings,
FUNC_CFG_REQ_FLAGS_STAT_CTX_ASSETS_TEST |
FUNC_CFG_REQ_FLAGS_VNIC_ASSETS_TEST;
if (bp->flags & BNXT_FLAG_CHIP_P5)
- flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST;
+ flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST |
+ FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST;
else
flags |= FUNC_CFG_REQ_FLAGS_RING_GRP_ASSETS_TEST;
}
@@ -6221,9 +6238,12 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i];
rmem->depth = 1;
rmem->nr_pages = MAX_CTX_PAGES;
- if (i == (nr_tbls - 1))
- rmem->nr_pages = ctx_pg->nr_pages %
- MAX_CTX_PAGES;
+ if (i == (nr_tbls - 1)) {
+ int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;
+
+ if (rem)
+ rmem->nr_pages = rem;
+ }
rc = bnxt_alloc_ctx_mem_blk(bp, pg_tbl);
if (rc)
break;
@@ -6670,6 +6690,10 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
VER_GET_RESP_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE;
+ if (dev_caps_cfg &
+ VER_GET_RESP_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED)
+ bp->fw_cap |= BNXT_FW_CAP_TRUSTED_VF;
+
hwrm_ver_get_exit:
mutex_unlock(&bp->hwrm_cmd_lock);
return rc;
@@ -8604,24 +8628,88 @@ static int bnxt_close(struct net_device *dev)
return 0;
}
+static int bnxt_hwrm_port_phy_read(struct bnxt *bp, u16 phy_addr, u16 reg,
+ u16 *val)
+{
+ struct hwrm_port_phy_mdio_read_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_port_phy_mdio_read_input req = {0};
+ int rc;
+
+ if (bp->hwrm_spec_code < 0x10a00)
+ return -EOPNOTSUPP;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_MDIO_READ, -1, -1);
+ req.port_id = cpu_to_le16(bp->pf.port_id);
+ req.phy_addr = phy_addr;
+ req.reg_addr = cpu_to_le16(reg & 0x1f);
+ if (bp->link_info.support_speeds & BNXT_LINK_SPEED_MSK_10GB) {
+ req.cl45_mdio = 1;
+ req.phy_addr = mdio_phy_id_prtad(phy_addr);
+ req.dev_addr = mdio_phy_id_devad(phy_addr);
+ req.reg_addr = cpu_to_le16(reg);
+ }
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (!rc)
+ *val = le16_to_cpu(resp->reg_data);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
+static int bnxt_hwrm_port_phy_write(struct bnxt *bp, u16 phy_addr, u16 reg,
+ u16 val)
+{
+ struct hwrm_port_phy_mdio_write_input req = {0};
+
+ if (bp->hwrm_spec_code < 0x10a00)
+ return -EOPNOTSUPP;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_MDIO_WRITE, -1, -1);
+ req.port_id = cpu_to_le16(bp->pf.port_id);
+ req.phy_addr = phy_addr;
+ req.reg_addr = cpu_to_le16(reg & 0x1f);
+ if (bp->link_info.support_speeds & BNXT_LINK_SPEED_MSK_10GB) {
+ req.cl45_mdio = 1;
+ req.phy_addr = mdio_phy_id_prtad(phy_addr);
+ req.dev_addr = mdio_phy_id_devad(phy_addr);
+ req.reg_addr = cpu_to_le16(reg);
+ }
+ req.reg_data = cpu_to_le16(val);
+
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
/* rtnl_lock held */
static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
+ struct mii_ioctl_data *mdio = if_mii(ifr);
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+
switch (cmd) {
case SIOCGMIIPHY:
+ mdio->phy_id = bp->link_info.phy_addr;
+
/* fallthru */
case SIOCGMIIREG: {
+ u16 mii_regval = 0;
+
if (!netif_running(dev))
return -EAGAIN;
- return 0;
+ rc = bnxt_hwrm_port_phy_read(bp, mdio->phy_id, mdio->reg_num,
+ &mii_regval);
+ mdio->val_out = mii_regval;
+ return rc;
}
case SIOCSMIIREG:
if (!netif_running(dev))
return -EAGAIN;
- return 0;
+ return bnxt_hwrm_port_phy_write(bp, mdio->phy_id, mdio->reg_num,
+ mdio->val_in);
default:
/* do nothing */
@@ -9977,8 +10065,11 @@ static int bnxt_get_phys_port_name(struct net_device *dev, char *buf,
return 0;
}
-int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr)
+int bnxt_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
+ struct bnxt *bp = netdev_priv(dev);
+
if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
return -EOPNOTSUPP;
@@ -9986,27 +10077,12 @@ int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr)
if (!BNXT_PF(bp))
return -EOPNOTSUPP;
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(bp->switch_id);
- memcpy(attr->u.ppid.id, bp->switch_id, attr->u.ppid.id_len);
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
+ ppid->id_len = sizeof(bp->switch_id);
+ memcpy(ppid->id, bp->switch_id, ppid->id_len);
-static int bnxt_swdev_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- return bnxt_port_attr_get(netdev_priv(dev), attr);
+ return 0;
}
-static const struct switchdev_ops bnxt_switchdev_ops = {
- .switchdev_port_attr_get = bnxt_swdev_port_attr_get
-};
-
static const struct net_device_ops bnxt_netdev_ops = {
.ndo_open = bnxt_open,
.ndo_start_xmit = bnxt_start_xmit,
@@ -10038,6 +10114,7 @@ static const struct net_device_ops bnxt_netdev_ops = {
.ndo_bpf = bnxt_xdp,
.ndo_bridge_getlink = bnxt_bridge_getlink,
.ndo_bridge_setlink = bnxt_bridge_setlink,
+ .ndo_get_port_parent_id = bnxt_get_port_parent_id,
.ndo_get_phys_port_name = bnxt_get_phys_port_name
};
@@ -10396,7 +10473,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->netdev_ops = &bnxt_netdev_ops;
dev->watchdog_timeo = BNXT_TX_TIMEOUT;
dev->ethtool_ops = &bnxt_ethtool_ops;
- SWITCHDEV_SET_OPS(dev, &bnxt_switchdev_ops);
pci_set_drvdata(pdev, dev);
rc = bnxt_alloc_hwrm_resources(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index a451796deefe..cf81ace7a6e6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -22,7 +22,6 @@
#include <linux/rhashtable.h>
#include <net/devlink.h>
#include <net/dst_metadata.h>
-#include <net/switchdev.h>
#include <net/xdp.h>
#include <linux/net_dim.h>
@@ -582,7 +581,7 @@ struct nqe_cn {
(HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT + \
((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT))
-#define HWRM_VALID_BIT_DELAY_USEC 20
+#define HWRM_VALID_BIT_DELAY_USEC 150
#define BNXT_HWRM_CHNL_CHIMP 0
#define BNXT_HWRM_CHNL_KONG 1
@@ -946,6 +945,7 @@ struct bnxt_vf_info {
* stored by PF.
*/
u16 vlan;
+ u16 func_qcfg_flags;
u32 flags;
#define BNXT_VF_QOS 0x1
#define BNXT_VF_SPOOFCHK 0x2
@@ -1479,6 +1479,7 @@ struct bnxt {
#define BNXT_FW_CAP_IF_CHANGE 0x00000010
#define BNXT_FW_CAP_KONG_MB_CHNL 0x00000080
#define BNXT_FW_CAP_OVS_64BIT_HANDLE 0x00000400
+ #define BNXT_FW_CAP_TRUSTED_VF 0x00000800
#define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
u32 hwrm_spec_code;
@@ -1609,6 +1610,7 @@ struct bnxt {
/* devlink interface and vf-rep structs */
struct devlink *dl;
+ struct devlink_port dl_port;
enum devlink_eswitch_mode eswitch_mode;
struct bnxt_vf_rep **vf_reps; /* array of vf-rep ptrs */
u16 *cfa_code_map; /* cfa_code -> vf_idx map */
@@ -1794,7 +1796,8 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
int bnxt_restore_pf_fw_resources(struct bnxt *bp);
-int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr);
+int bnxt_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid);
void bnxt_dim_work(struct work_struct *work);
int bnxt_hwrm_set_ring_coal(struct bnxt *bp, struct bnxt_napi *bnapi);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
index 15c7041e937b..70775158c8c4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
@@ -316,8 +316,8 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
n = IEEE_8021QAZ_MAX_TCS;
data_len = sizeof(*data) + sizeof(*fw_app) * n;
- data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping,
- GFP_KERNEL);
+ data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
+ GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 140dbd62106d..e1feb97bcd81 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -85,8 +85,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
return -EFAULT;
}
- data_addr = dma_zalloc_coherent(&bp->pdev->dev, bytesize,
- &data_dma_addr, GFP_KERNEL);
+ data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
+ &data_dma_addr, GFP_KERNEL);
if (!data_addr)
return -ENOMEM;
@@ -188,6 +188,9 @@ static const struct devlink_param bnxt_dl_params[] = {
NULL),
};
+static const struct devlink_param bnxt_dl_port_params[] = {
+};
+
int bnxt_dl_register(struct bnxt *bp)
{
struct devlink *dl;
@@ -225,8 +228,29 @@ int bnxt_dl_register(struct bnxt *bp)
goto err_dl_unreg;
}
+ rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
+ if (rc) {
+ netdev_err(bp->dev, "devlink_port_register failed");
+ goto err_dl_param_unreg;
+ }
+ devlink_port_type_eth_set(&bp->dl_port, bp->dev);
+
+ rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
+ ARRAY_SIZE(bnxt_dl_port_params));
+ if (rc) {
+ netdev_err(bp->dev, "devlink_port_params_register failed");
+ goto err_dl_port_unreg;
+ }
+
+ devlink_params_publish(dl);
+
return 0;
+err_dl_port_unreg:
+ devlink_port_unregister(&bp->dl_port);
+err_dl_param_unreg:
+ devlink_params_unregister(dl, bnxt_dl_params,
+ ARRAY_SIZE(bnxt_dl_params));
err_dl_unreg:
devlink_unregister(dl);
err_dl_free:
@@ -242,6 +266,9 @@ void bnxt_dl_unregister(struct bnxt *bp)
if (!dl)
return;
+ devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
+ ARRAY_SIZE(bnxt_dl_port_params));
+ devlink_port_unregister(&bp->dl_port);
devlink_params_unregister(dl, bnxt_dl_params,
ARRAY_SIZE(bnxt_dl_params));
devlink_unregister(dl);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
index f1aaac8e6268..b6c610339501 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -1,7 +1,7 @@
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2014-2016 Broadcom Corporation
- * Copyright (c) 2016-2018 Broadcom Limited
+ * Copyright (c) 2016-2019 Broadcom Limited
*
* 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
@@ -98,6 +98,7 @@ struct hwrm_short_input {
struct cmd_nums {
__le16 req_type;
#define HWRM_VER_GET 0x0UL
+ #define HWRM_ERROR_RECOVERY_QCFG 0xcUL
#define HWRM_FUNC_DRV_IF_CHANGE 0xdUL
#define HWRM_FUNC_BUF_UNRGTR 0xeUL
#define HWRM_FUNC_VF_CFG 0xfUL
@@ -221,6 +222,7 @@ struct cmd_nums {
#define HWRM_CFA_METER_PROFILE_CFG 0xf7UL
#define HWRM_CFA_METER_INSTANCE_ALLOC 0xf8UL
#define HWRM_CFA_METER_INSTANCE_FREE 0xf9UL
+ #define HWRM_CFA_METER_INSTANCE_CFG 0xfaUL
#define HWRM_CFA_VFR_ALLOC 0xfdUL
#define HWRM_CFA_VFR_FREE 0xfeUL
#define HWRM_CFA_VF_PAIR_ALLOC 0x100UL
@@ -269,6 +271,7 @@ struct cmd_nums {
#define HWRM_ENGINE_CKV_FLUSH 0x133UL
#define HWRM_ENGINE_CKV_RNG_GET 0x134UL
#define HWRM_ENGINE_CKV_KEY_GEN 0x135UL
+ #define HWRM_ENGINE_CKV_KEY_LABEL_CFG 0x136UL
#define HWRM_ENGINE_QG_CONFIG_QUERY 0x13cUL
#define HWRM_ENGINE_QG_QUERY 0x13dUL
#define HWRM_ENGINE_QG_METER_PROFILE_CONFIG_QUERY 0x13eUL
@@ -296,6 +299,7 @@ struct cmd_nums {
#define HWRM_ENGINE_NQ_ALLOC 0x162UL
#define HWRM_ENGINE_NQ_FREE 0x163UL
#define HWRM_ENGINE_ON_DIE_RQE_CREDITS 0x164UL
+ #define HWRM_ENGINE_FUNC_QCFG 0x165UL
#define HWRM_FUNC_RESOURCE_QCAPS 0x190UL
#define HWRM_FUNC_VF_RESOURCE_CFG 0x191UL
#define HWRM_FUNC_BACKING_STORE_QCAPS 0x192UL
@@ -379,15 +383,15 @@ struct hwrm_err_output {
};
#define HWRM_NA_SIGNATURE ((__le32)(-1))
#define HWRM_MAX_REQ_LEN 128
-#define HWRM_MAX_RESP_LEN 280
+#define HWRM_MAX_RESP_LEN 704
#define HW_HASH_INDEX_SIZE 0x80
#define HW_HASH_KEY_SIZE 40
#define HWRM_RESP_VALID_KEY 1
#define HWRM_VERSION_MAJOR 1
#define HWRM_VERSION_MINOR 10
#define HWRM_VERSION_UPDATE 0
-#define HWRM_VERSION_RSVD 33
-#define HWRM_VERSION_STR "1.10.0.33"
+#define HWRM_VERSION_RSVD 47
+#define HWRM_VERSION_STR "1.10.0.47"
/* hwrm_ver_get_input (size:192b/24B) */
struct hwrm_ver_get_input {
@@ -580,6 +584,7 @@ struct hwrm_async_event_cmpl {
#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
#define ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE 0x7UL
#define ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY 0x8UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY 0x9UL
#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
@@ -595,6 +600,9 @@ struct hwrm_async_event_cmpl {
#define ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION 0x37UL
#define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CACHE_FLUSH_REQ 0x38UL
#define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CACHE_FLUSH_DONE 0x39UL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_TCP_FLAG_ACTION_CHANGE 0x3aUL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_FLOW_ACTIVE 0x3bUL
+ #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CFG_CHANGE 0x3cUL
#define ASYNC_EVENT_CMPL_EVENT_ID_FW_TRACE_MSG 0xfeUL
#define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL
#define ASYNC_EVENT_CMPL_EVENT_ID_LAST ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR
@@ -724,6 +732,30 @@ struct hwrm_async_event_cmpl_reset_notify {
#define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_SFT 16
};
+/* hwrm_async_event_cmpl_error_recovery (size:128b/16B) */
+struct hwrm_async_event_cmpl_error_recovery {
+ __le16 type;
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_LAST ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_HWRM_ASYNC_EVENT
+ __le16 event_id;
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_ERROR_RECOVERY 0x9UL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_LAST ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_ERROR_RECOVERY
+ __le32 event_data2;
+ u8 opaque_v;
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_V 0x1UL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_OPAQUE_SFT 1
+ u8 timestamp_lo;
+ __le16 timestamp_hi;
+ __le32 event_data1;
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASK 0xffUL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_SFT 0
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASTER_FUNC 0x1UL
+ #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED 0x2UL
+};
+
/* hwrm_async_event_cmpl_vf_cfg_change (size:128b/16B) */
struct hwrm_async_event_cmpl_vf_cfg_change {
__le16 type;
@@ -1014,6 +1046,7 @@ struct hwrm_func_qcaps_output {
#define FUNC_QCAPS_RESP_FLAGS_WCB_PUSH_MODE 0x100000UL
#define FUNC_QCAPS_RESP_FLAGS_DYNAMIC_TX_RING_ALLOC 0x200000UL
#define FUNC_QCAPS_RESP_FLAGS_HOT_RESET_CAPABLE 0x400000UL
+ #define FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE 0x800000UL
u8 mac_address[6];
__le16 max_rsscos_ctx;
__le16 max_cmpl_rings;
@@ -1184,6 +1217,8 @@ struct hwrm_func_cfg_input {
#define FUNC_CFG_REQ_FLAGS_L2_CTX_ASSETS_TEST 0x100000UL
#define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE 0x200000UL
#define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC 0x400000UL
+ #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST 0x800000UL
+ #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE 0x1000000UL
__le32 enables;
#define FUNC_CFG_REQ_ENABLES_MTU 0x1UL
#define FUNC_CFG_REQ_ENABLES_MRU 0x2UL
@@ -1389,6 +1424,7 @@ struct hwrm_func_drv_rgtr_input {
#define FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE 0x4UL
#define FUNC_DRV_RGTR_REQ_FLAGS_FLOW_HANDLE_64BIT_MODE 0x8UL
#define FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT 0x10UL
+ #define FUNC_DRV_RGTR_REQ_FLAGS_ERROR_RECOVERY_SUPPORT 0x20UL
__le32 enables;
#define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE 0x1UL
#define FUNC_DRV_RGTR_REQ_ENABLES_VER 0x2UL
@@ -2023,6 +2059,89 @@ struct hwrm_func_backing_store_cfg_output {
u8 valid;
};
+/* hwrm_error_recovery_qcfg_input (size:192b/24B) */
+struct hwrm_error_recovery_qcfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 unused_0[8];
+};
+
+/* hwrm_error_recovery_qcfg_output (size:1664b/208B) */
+struct hwrm_error_recovery_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 flags;
+ #define ERROR_RECOVERY_QCFG_RESP_FLAGS_HOST 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU 0x2UL
+ __le32 driver_polling_freq;
+ __le32 master_func_wait_period;
+ __le32 normal_func_wait_period;
+ __le32 master_func_wait_period_after_reset;
+ __le32 max_bailout_time_after_reset;
+ __le32 fw_health_status_reg;
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_MASK 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_SFT 0
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_GRC 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR0 0x2UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR1 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR1
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_MASK 0xfffffffcUL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SFT 2
+ __le32 fw_heartbeat_reg;
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_MASK 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_SFT 0
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_GRC 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR0 0x2UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR1 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR1
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_MASK 0xfffffffcUL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SFT 2
+ __le32 fw_reset_cnt_reg;
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_MASK 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_SFT 0
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_GRC 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR0 0x2UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR1 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR1
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_MASK 0xfffffffcUL
+ #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SFT 2
+ __le32 reset_inprogress_reg;
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_MASK 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_SFT 0
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_GRC 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR0 0x2UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR1 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR1
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_MASK 0xfffffffcUL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SFT 2
+ __le32 reset_inprogress_reg_mask;
+ u8 unused_0[3];
+ u8 reg_array_cnt;
+ __le32 reset_reg[16];
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_MASK 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_SFT 0
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_GRC 0x1UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR0 0x2UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR1 0x3UL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR1
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_MASK 0xfffffffcUL
+ #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SFT 2
+ __le32 reset_reg_val[16];
+ u8 delay_after_reset[16];
+ u8 unused_1[7];
+ u8 valid;
+};
+
/* hwrm_func_drv_if_change_input (size:192b/24B) */
struct hwrm_func_drv_if_change_input {
__le16 req_type;
@@ -2954,6 +3073,7 @@ struct hwrm_port_phy_qcaps_output {
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_100GB 0x800UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MBHD 0x1000UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MB 0x2000UL
+ #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_200GB 0x4000UL
__le16 supported_speeds_auto_mode;
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MBHD 0x1UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MB 0x2UL
@@ -2969,6 +3089,7 @@ struct hwrm_port_phy_qcaps_output {
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100GB 0x800UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MBHD 0x1000UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MB 0x2000UL
+ #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_200GB 0x4000UL
__le16 supported_speeds_eee_mode;
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD1 0x1UL
#define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_100MB 0x2UL
@@ -4918,6 +5039,35 @@ struct hwrm_ring_free_output {
u8 valid;
};
+/* hwrm_ring_reset_input (size:192b/24B) */
+struct hwrm_ring_reset_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ u8 ring_type;
+ #define RING_RESET_REQ_RING_TYPE_L2_CMPL 0x0UL
+ #define RING_RESET_REQ_RING_TYPE_TX 0x1UL
+ #define RING_RESET_REQ_RING_TYPE_RX 0x2UL
+ #define RING_RESET_REQ_RING_TYPE_ROCE_CMPL 0x3UL
+ #define RING_RESET_REQ_RING_TYPE_LAST RING_RESET_REQ_RING_TYPE_ROCE_CMPL
+ u8 unused_0;
+ __le16 ring_id;
+ u8 unused_1[4];
+};
+
+/* hwrm_ring_reset_output (size:128b/16B) */
+struct hwrm_ring_reset_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 unused_0[4];
+ u8 consumer_idx[3];
+ u8 valid;
+};
+
/* hwrm_ring_aggint_qcaps_input (size:128b/16B) */
struct hwrm_ring_aggint_qcaps_input {
__le16 req_type;
@@ -5445,19 +5595,21 @@ struct hwrm_cfa_encap_record_alloc_input {
__le64 resp_addr;
__le32 flags;
#define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_EXTERNAL 0x2UL
u8 encap_type;
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN 0x1UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE 0x2UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE 0x3UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP 0x4UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE 0x5UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS 0x6UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN 0x7UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE 0x8UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_V4 0x9UL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE_V1 0xaUL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE 0xbUL
- #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_LAST CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN 0x1UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE 0x2UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE 0x3UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP 0x4UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE 0x5UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS 0x6UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN 0x7UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE 0x8UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_V4 0x9UL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE_V1 0xaUL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE 0xbUL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_GPE_V6 0xcUL
+ #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_LAST CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_GPE_V6
u8 unused_0[3];
__le32 encap_data[20];
};
@@ -5505,6 +5657,7 @@ struct hwrm_cfa_ntuple_filter_alloc_input {
#define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL
#define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP 0x2UL
#define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_METER 0x4UL
+ #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_FID 0x8UL
__le32 enables;
#define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL
#define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE 0x2UL
@@ -5626,7 +5779,8 @@ struct hwrm_cfa_ntuple_filter_cfg_input {
#define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_DST_ID 0x1UL
#define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_MIRROR_VNIC_ID 0x2UL
#define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_METER_INSTANCE_ID 0x4UL
- u8 unused_0[4];
+ __le32 flags;
+ #define CFA_NTUPLE_FILTER_CFG_REQ_FLAGS_DEST_FID 0x1UL
__le64 ntuple_filter_id;
__le32 new_dst_id;
__le32 new_mirror_vnic_id;
@@ -5891,13 +6045,15 @@ struct hwrm_cfa_flow_info_input {
__le64 ext_flow_handle;
};
-/* hwrm_cfa_flow_info_output (size:448b/56B) */
+/* hwrm_cfa_flow_info_output (size:5632b/704B) */
struct hwrm_cfa_flow_info_output {
__le16 error_code;
__le16 req_type;
__le16 seq_id;
__le16 resp_len;
u8 flags;
+ #define CFA_FLOW_INFO_RESP_FLAGS_PATH_TX 0x1UL
+ #define CFA_FLOW_INFO_RESP_FLAGS_PATH_RX 0x2UL
u8 profile;
__le16 src_fid;
__le16 dst_fid;
@@ -5909,7 +6065,10 @@ struct hwrm_cfa_flow_info_output {
__le16 flow_handle;
__le32 tunnel_handle;
__le16 flow_timer;
- u8 unused_0[5];
+ u8 unused_0[6];
+ __le32 flow_key_data[130];
+ __le32 flow_action_info[30];
+ u8 unused_1[7];
u8 valid;
};
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
index d80f5c981d90..2b90a2bb1a1d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -121,6 +121,54 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
return rc;
}
+static int bnxt_hwrm_func_qcfg_flags(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_func_qcfg_input req = {0};
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
+ req.fid = cpu_to_le16(vf->fw_fid);
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc) {
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return -EIO;
+ }
+ vf->func_qcfg_flags = le16_to_cpu(resp->flags);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return 0;
+}
+
+static bool bnxt_is_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF))
+ return !!(vf->flags & BNXT_VF_TRUST);
+
+ bnxt_hwrm_func_qcfg_flags(bp, vf);
+ return !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF);
+}
+
+static int bnxt_hwrm_set_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf)
+{
+ struct hwrm_func_cfg_input req = {0};
+ int rc;
+
+ if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF))
+ return 0;
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+ req.fid = cpu_to_le16(vf->fw_fid);
+ if (vf->flags & BNXT_VF_TRUST)
+ req.flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE);
+ else
+ req.flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE);
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ if (rc)
+ return -EIO;
+ return 0;
+}
+
int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted)
{
struct bnxt *bp = netdev_priv(dev);
@@ -135,6 +183,7 @@ int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted)
else
vf->flags &= ~BNXT_VF_TRUST;
+ bnxt_hwrm_set_trusted_vf(bp, vf);
return 0;
}
@@ -164,7 +213,7 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id,
else
ivi->qos = 0;
ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK);
- ivi->trusted = !!(vf->flags & BNXT_VF_TRUST);
+ ivi->trusted = bnxt_is_trusted_vf(bp, vf);
if (!(vf->flags & BNXT_VF_LINK_FORCED))
ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
else if (vf->flags & BNXT_VF_LINK_UP)
@@ -935,9 +984,10 @@ static int bnxt_vf_configure_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
* if the PF assigned MAC address is zero
*/
if (req->enables & cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)) {
+ bool trust = bnxt_is_trusted_vf(bp, vf);
+
if (is_valid_ether_addr(req->dflt_mac_addr) &&
- ((vf->flags & BNXT_VF_TRUST) ||
- !is_valid_ether_addr(vf->mac_addr) ||
+ (trust || !is_valid_ether_addr(vf->mac_addr) ||
ether_addr_equal(req->dflt_mac_addr, vf->mac_addr))) {
ether_addr_copy(vf->vf_mac_addr, req->dflt_mac_addr);
return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size);
@@ -962,7 +1012,7 @@ static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
* Otherwise, it must match the VF MAC address if firmware spec >=
* 1.2.2
*/
- if (vf->flags & BNXT_VF_TRUST) {
+ if (bnxt_is_trusted_vf(bp, vf)) {
mac_ok = true;
} else if (is_valid_ether_addr(vf->mac_addr)) {
if (ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr))
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index c683b5e96b1d..44d6c5743fb9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -45,7 +45,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev)
struct bnxt *bp;
/* check if dev belongs to the same switch */
- if (!switchdev_port_same_parent_id(pf_bp->dev, dev)) {
+ if (!netdev_port_same_parent_id(pf_bp->dev, dev)) {
netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch",
dev->ifindex);
return BNXT_FID_INVALID;
@@ -61,9 +61,9 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev)
static int bnxt_tc_parse_redir(struct bnxt *bp,
struct bnxt_tc_actions *actions,
- const struct tc_action *tc_act)
+ const struct flow_action_entry *act)
{
- struct net_device *dev = tcf_mirred_dev(tc_act);
+ struct net_device *dev = act->dev;
if (!dev) {
netdev_info(bp->dev, "no dev in mirred action");
@@ -77,16 +77,16 @@ static int bnxt_tc_parse_redir(struct bnxt *bp,
static int bnxt_tc_parse_vlan(struct bnxt *bp,
struct bnxt_tc_actions *actions,
- const struct tc_action *tc_act)
+ const struct flow_action_entry *act)
{
- switch (tcf_vlan_action(tc_act)) {
- case TCA_VLAN_ACT_POP:
+ switch (act->id) {
+ case FLOW_ACTION_VLAN_POP:
actions->flags |= BNXT_TC_ACTION_FLAG_POP_VLAN;
break;
- case TCA_VLAN_ACT_PUSH:
+ case FLOW_ACTION_VLAN_PUSH:
actions->flags |= BNXT_TC_ACTION_FLAG_PUSH_VLAN;
- actions->push_vlan_tci = htons(tcf_vlan_push_vid(tc_act));
- actions->push_vlan_tpid = tcf_vlan_push_proto(tc_act);
+ actions->push_vlan_tci = htons(act->vlan.vid);
+ actions->push_vlan_tpid = act->vlan.proto;
break;
default:
return -EOPNOTSUPP;
@@ -96,10 +96,10 @@ static int bnxt_tc_parse_vlan(struct bnxt *bp,
static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
struct bnxt_tc_actions *actions,
- const struct tc_action *tc_act)
+ const struct flow_action_entry *act)
{
- struct ip_tunnel_info *tun_info = tcf_tunnel_info(tc_act);
- struct ip_tunnel_key *tun_key = &tun_info->key;
+ const struct ip_tunnel_info *tun_info = act->tunnel;
+ const struct ip_tunnel_key *tun_key = &tun_info->key;
if (ip_tunnel_info_af(tun_info) != AF_INET) {
netdev_info(bp->dev, "only IPv4 tunnel-encap is supported");
@@ -113,51 +113,43 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
static int bnxt_tc_parse_actions(struct bnxt *bp,
struct bnxt_tc_actions *actions,
- struct tcf_exts *tc_exts)
+ struct flow_action *flow_action)
{
- const struct tc_action *tc_act;
+ struct flow_action_entry *act;
int i, rc;
- if (!tcf_exts_has_actions(tc_exts)) {
+ if (!flow_action_has_entries(flow_action)) {
netdev_info(bp->dev, "no actions");
return -EINVAL;
}
- tcf_exts_for_each_action(i, tc_act, tc_exts) {
- /* Drop action */
- if (is_tcf_gact_shot(tc_act)) {
+ flow_action_for_each(i, act, flow_action) {
+ switch (act->id) {
+ case FLOW_ACTION_DROP:
actions->flags |= BNXT_TC_ACTION_FLAG_DROP;
return 0; /* don't bother with other actions */
- }
-
- /* Redirect action */
- if (is_tcf_mirred_egress_redirect(tc_act)) {
- rc = bnxt_tc_parse_redir(bp, actions, tc_act);
+ case FLOW_ACTION_REDIRECT:
+ rc = bnxt_tc_parse_redir(bp, actions, act);
if (rc)
return rc;
- continue;
- }
-
- /* Push/pop VLAN */
- if (is_tcf_vlan(tc_act)) {
- rc = bnxt_tc_parse_vlan(bp, actions, tc_act);
+ break;
+ case FLOW_ACTION_VLAN_POP:
+ case FLOW_ACTION_VLAN_PUSH:
+ case FLOW_ACTION_VLAN_MANGLE:
+ rc = bnxt_tc_parse_vlan(bp, actions, act);
if (rc)
return rc;
- continue;
- }
-
- /* Tunnel encap */
- if (is_tcf_tunnel_set(tc_act)) {
- rc = bnxt_tc_parse_tunnel_set(bp, actions, tc_act);
+ break;
+ case FLOW_ACTION_TUNNEL_ENCAP:
+ rc = bnxt_tc_parse_tunnel_set(bp, actions, act);
if (rc)
return rc;
- continue;
- }
-
- /* Tunnel decap */
- if (is_tcf_tunnel_release(tc_act)) {
+ break;
+ case FLOW_ACTION_TUNNEL_DECAP:
actions->flags |= BNXT_TC_ACTION_FLAG_TUNNEL_DECAP;
- continue;
+ break;
+ default:
+ break;
}
}
@@ -177,18 +169,12 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
return 0;
}
-#define GET_KEY(flow_cmd, key_type) \
- skb_flow_dissector_target((flow_cmd)->dissector, key_type,\
- (flow_cmd)->key)
-#define GET_MASK(flow_cmd, key_type) \
- skb_flow_dissector_target((flow_cmd)->dissector, key_type,\
- (flow_cmd)->mask)
-
static int bnxt_tc_parse_flow(struct bnxt *bp,
struct tc_cls_flower_offload *tc_flow_cmd,
struct bnxt_tc_flow *flow)
{
- struct flow_dissector *dissector = tc_flow_cmd->dissector;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(tc_flow_cmd);
+ struct flow_dissector *dissector = rule->match.dissector;
/* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
@@ -198,143 +184,123 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
return -EOPNOTSUPP;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_BASIC);
- struct flow_dissector_key_basic *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_BASIC);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- flow->l2_key.ether_type = key->n_proto;
- flow->l2_mask.ether_type = mask->n_proto;
+ flow_rule_match_basic(rule, &match);
+ flow->l2_key.ether_type = match.key->n_proto;
+ flow->l2_mask.ether_type = match.mask->n_proto;
- if (key->n_proto == htons(ETH_P_IP) ||
- key->n_proto == htons(ETH_P_IPV6)) {
- flow->l4_key.ip_proto = key->ip_proto;
- flow->l4_mask.ip_proto = mask->ip_proto;
+ if (match.key->n_proto == htons(ETH_P_IP) ||
+ match.key->n_proto == htons(ETH_P_IPV6)) {
+ flow->l4_key.ip_proto = match.key->ip_proto;
+ flow->l4_mask.ip_proto = match.mask->ip_proto;
}
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ETH_ADDRS);
- struct flow_dissector_key_eth_addrs *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ETH_ADDRS);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
+ flow_rule_match_eth_addrs(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_ETH_ADDRS;
- ether_addr_copy(flow->l2_key.dmac, key->dst);
- ether_addr_copy(flow->l2_mask.dmac, mask->dst);
- ether_addr_copy(flow->l2_key.smac, key->src);
- ether_addr_copy(flow->l2_mask.smac, mask->src);
+ ether_addr_copy(flow->l2_key.dmac, match.key->dst);
+ ether_addr_copy(flow->l2_mask.dmac, match.mask->dst);
+ ether_addr_copy(flow->l2_key.smac, match.key->src);
+ ether_addr_copy(flow->l2_mask.smac, match.mask->src);
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_VLAN);
- struct flow_dissector_key_vlan *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_VLAN);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
+ flow_rule_match_vlan(rule, &match);
flow->l2_key.inner_vlan_tci =
- cpu_to_be16(VLAN_TCI(key->vlan_id, key->vlan_priority));
+ cpu_to_be16(VLAN_TCI(match.key->vlan_id,
+ match.key->vlan_priority));
flow->l2_mask.inner_vlan_tci =
- cpu_to_be16((VLAN_TCI(mask->vlan_id, mask->vlan_priority)));
+ cpu_to_be16((VLAN_TCI(match.mask->vlan_id,
+ match.mask->vlan_priority)));
flow->l2_key.inner_vlan_tpid = htons(ETH_P_8021Q);
flow->l2_mask.inner_vlan_tpid = htons(0xffff);
flow->l2_key.num_vlans = 1;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
- struct flow_dissector_key_ipv4_addrs *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
- struct flow_dissector_key_ipv4_addrs *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
+ struct flow_match_ipv4_addrs match;
+ flow_rule_match_ipv4_addrs(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_IPV4_ADDRS;
- flow->l3_key.ipv4.daddr.s_addr = key->dst;
- flow->l3_mask.ipv4.daddr.s_addr = mask->dst;
- flow->l3_key.ipv4.saddr.s_addr = key->src;
- flow->l3_mask.ipv4.saddr.s_addr = mask->src;
- } else if (dissector_uses_key(dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
- struct flow_dissector_key_ipv6_addrs *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
- struct flow_dissector_key_ipv6_addrs *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
-
+ flow->l3_key.ipv4.daddr.s_addr = match.key->dst;
+ flow->l3_mask.ipv4.daddr.s_addr = match.mask->dst;
+ flow->l3_key.ipv4.saddr.s_addr = match.key->src;
+ flow->l3_mask.ipv4.saddr.s_addr = match.mask->src;
+ } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
+ struct flow_match_ipv6_addrs match;
+
+ flow_rule_match_ipv6_addrs(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_IPV6_ADDRS;
- flow->l3_key.ipv6.daddr = key->dst;
- flow->l3_mask.ipv6.daddr = mask->dst;
- flow->l3_key.ipv6.saddr = key->src;
- flow->l3_mask.ipv6.saddr = mask->src;
+ flow->l3_key.ipv6.daddr = match.key->dst;
+ flow->l3_mask.ipv6.daddr = match.mask->dst;
+ flow->l3_key.ipv6.saddr = match.key->src;
+ flow->l3_mask.ipv6.saddr = match.mask->src;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_PORTS);
- struct flow_dissector_key_ports *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_PORTS);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
+ flow_rule_match_ports(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_PORTS;
- flow->l4_key.ports.dport = key->dst;
- flow->l4_mask.ports.dport = mask->dst;
- flow->l4_key.ports.sport = key->src;
- flow->l4_mask.ports.sport = mask->src;
+ flow->l4_key.ports.dport = match.key->dst;
+ flow->l4_mask.ports.dport = match.mask->dst;
+ flow->l4_key.ports.sport = match.key->src;
+ flow->l4_mask.ports.sport = match.mask->src;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ICMP)) {
- struct flow_dissector_key_icmp *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ICMP);
- struct flow_dissector_key_icmp *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ICMP);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
+ struct flow_match_icmp match;
+ flow_rule_match_icmp(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_ICMP;
- flow->l4_key.icmp.type = key->type;
- flow->l4_key.icmp.code = key->code;
- flow->l4_mask.icmp.type = mask->type;
- flow->l4_mask.icmp.code = mask->code;
+ flow->l4_key.icmp.type = match.key->type;
+ flow->l4_key.icmp.code = match.key->code;
+ flow->l4_mask.icmp.type = match.mask->type;
+ flow->l4_mask.icmp.code = match.mask->code;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
- struct flow_dissector_key_ipv4_addrs *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS);
- struct flow_dissector_key_ipv4_addrs *mask =
- GET_MASK(tc_flow_cmd,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
+ struct flow_match_ipv4_addrs match;
+ flow_rule_match_enc_ipv4_addrs(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS;
- flow->tun_key.u.ipv4.dst = key->dst;
- flow->tun_mask.u.ipv4.dst = mask->dst;
- flow->tun_key.u.ipv4.src = key->src;
- flow->tun_mask.u.ipv4.src = mask->src;
- } else if (dissector_uses_key(dissector,
+ flow->tun_key.u.ipv4.dst = match.key->dst;
+ flow->tun_mask.u.ipv4.dst = match.mask->dst;
+ flow->tun_key.u.ipv4.src = match.key->src;
+ flow->tun_mask.u.ipv4.src = match.mask->src;
+ } else if (flow_rule_match_key(rule,
FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
return -EOPNOTSUPP;
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_KEYID);
- struct flow_dissector_key_keyid *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_KEYID);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid match;
+ flow_rule_match_enc_keyid(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_ID;
- flow->tun_key.tun_id = key32_to_tunnel_id(key->keyid);
- flow->tun_mask.tun_id = key32_to_tunnel_id(mask->keyid);
+ flow->tun_key.tun_id = key32_to_tunnel_id(match.key->keyid);
+ flow->tun_mask.tun_id = key32_to_tunnel_id(match.mask->keyid);
}
- if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
- struct flow_dissector_key_ports *key =
- GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_PORTS);
- struct flow_dissector_key_ports *mask =
- GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_PORTS);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
+ struct flow_match_ports match;
+ flow_rule_match_enc_ports(rule, &match);
flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_PORTS;
- flow->tun_key.tp_dst = key->dst;
- flow->tun_mask.tp_dst = mask->dst;
- flow->tun_key.tp_src = key->src;
- flow->tun_mask.tp_src = mask->src;
+ flow->tun_key.tp_dst = match.key->dst;
+ flow->tun_mask.tp_dst = match.mask->dst;
+ flow->tun_key.tp_src = match.key->src;
+ flow->tun_mask.tp_src = match.mask->src;
}
- return bnxt_tc_parse_actions(bp, &flow->actions, tc_flow_cmd->exts);
+ return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action);
}
static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
@@ -1324,7 +1290,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
bnxt_tc_set_flow_dir(bp, flow, src_fid);
if (!bnxt_tc_can_offload(bp, flow)) {
- rc = -ENOSPC;
+ rc = -EOPNOTSUPP;
goto free_node;
}
@@ -1422,8 +1388,8 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp,
lastused = flow->lastused;
spin_unlock(&flow->stats_lock);
- tcf_exts_stats_update(tc_flow_cmd->exts, stats.bytes, stats.packets,
- lastused);
+ flow_stats_update(&tc_flow_cmd->stats, stats.bytes, stats.packets,
+ lastused);
return 0;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 9a25c05aa571..2bdd2da9aac7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -237,21 +237,17 @@ static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
}
-static int bnxt_vf_rep_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
+static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
/* as only PORT_PARENT_ID is supported currently use common code
* between PF and VF-rep for now.
*/
- return bnxt_port_attr_get(vf_rep->bp, attr);
+ return bnxt_get_port_parent_id(vf_rep->bp->dev, ppid);
}
-static const struct switchdev_ops bnxt_vf_rep_switchdev_ops = {
- .switchdev_port_attr_get = bnxt_vf_rep_port_attr_get
-};
-
static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {
.get_drvinfo = bnxt_vf_rep_get_drvinfo
};
@@ -262,6 +258,7 @@ static const struct net_device_ops bnxt_vf_rep_netdev_ops = {
.ndo_start_xmit = bnxt_vf_rep_xmit,
.ndo_get_stats64 = bnxt_vf_rep_get_stats64,
.ndo_setup_tc = bnxt_vf_rep_setup_tc,
+ .ndo_get_port_parent_id = bnxt_vf_rep_get_port_parent_id,
.ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name
};
@@ -392,7 +389,6 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
- SWITCHDEV_SET_OPS(dev, &bnxt_vf_rep_switchdev_ops);
/* Just inherit all the featues of the parent PF as the VF-R
* uses the RX/TX rings of the parent PF
*/
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index aceb9b7b55bd..51880d83131a 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -525,7 +525,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
.asym_pause = 0,
};
- phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
+ phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
if (!phydev || IS_ERR(phydev)) {
dev_err(kdev, "failed to register fixed PHY device\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index 5db9f4158e62..134ae2862efa 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -1288,7 +1288,7 @@ static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
* for transmits, we just free buffers.
*/
- dev_kfree_skb_irq(sb);
+ dev_consume_skb_irq(sb);
/*
* .. and advance to the next buffer.
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 3b1397af81f7..328373e0578f 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -721,7 +721,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
case TG3_APE_LOCK_GPIO:
if (tg3_asic_rev(tp) == ASIC_REV_5761)
return 0;
- /* else: fall through */
+ /* fall through */
case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
if (!tp->pci_fn)
@@ -782,7 +782,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
case TG3_APE_LOCK_GPIO:
if (tg3_asic_rev(tp) == ASIC_REV_5761)
return;
- /* else: fall through */
+ /* fall through */
case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
if (!tp->pci_fn)
@@ -8712,10 +8712,10 @@ static int tg3_mem_rx_acquire(struct tg3 *tp)
if (!i && tg3_flag(tp, ENABLE_RSS))
continue;
- tnapi->rx_rcb = dma_zalloc_coherent(&tp->pdev->dev,
- TG3_RX_RCB_RING_BYTES(tp),
- &tnapi->rx_rcb_mapping,
- GFP_KERNEL);
+ tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
+ TG3_RX_RCB_RING_BYTES(tp),
+ &tnapi->rx_rcb_mapping,
+ GFP_KERNEL);
if (!tnapi->rx_rcb)
goto err_out;
}
@@ -8768,9 +8768,9 @@ static int tg3_alloc_consistent(struct tg3 *tp)
{
int i;
- tp->hw_stats = dma_zalloc_coherent(&tp->pdev->dev,
- sizeof(struct tg3_hw_stats),
- &tp->stats_mapping, GFP_KERNEL);
+ tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
+ sizeof(struct tg3_hw_stats),
+ &tp->stats_mapping, GFP_KERNEL);
if (!tp->hw_stats)
goto err_out;
@@ -8778,10 +8778,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
struct tg3_napi *tnapi = &tp->napi[i];
struct tg3_hw_status *sblk;
- tnapi->hw_status = dma_zalloc_coherent(&tp->pdev->dev,
- TG3_HW_STATUS_SIZE,
- &tnapi->status_mapping,
- GFP_KERNEL);
+ tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
+ TG3_HW_STATUS_SIZE,
+ &tnapi->status_mapping,
+ GFP_KERNEL);
if (!tnapi->hw_status)
goto err_out;
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index a36e38676640..84741d288ffa 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -743,7 +743,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
case IOCPF_E_TIMEOUT:
bfa_nw_ioc_hw_sem_release(ioc);
- bfa_ioc_pf_failed(ioc);
+ bfa_ioc_pf_failed(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
@@ -788,9 +788,8 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
case IOCPF_E_INITFAIL:
del_timer(&ioc->iocpf_timer);
- /*
- * !!! fall through !!!
- */
+ /* fall through */
+
case IOCPF_E_TIMEOUT:
bfa_nw_ioc_hw_sem_release(ioc);
if (event == IOCPF_E_TIMEOUT)
@@ -858,9 +857,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
case IOCPF_E_FAIL:
del_timer(&ioc->iocpf_timer);
- /*
- * !!! fall through !!!
- */
+ /* fall through*/
case IOCPF_E_TIMEOUT:
bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 3d45f4c92cf6..acc66a7e7b95 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -643,6 +643,7 @@
#define MACB_CAPS_JUMBO 0x00000020
#define MACB_CAPS_GEM_HAS_PTP 0x00000040
#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
+#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
#define MACB_CAPS_FIFO_MODE 0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
#define MACB_CAPS_SG_DISABLED 0x40000000
@@ -714,6 +715,8 @@
__v; \
})
+#define MACB_READ_NSR(bp) macb_readl(bp, NSR)
+
/* struct macb_dma_desc - Hardware DMA descriptor
* @addr: DMA address of data buffer
* @ctrl: Control and status bits
@@ -1082,7 +1085,7 @@ struct macb_config {
unsigned int dma_burst_length;
int (*clk_init)(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk,
- struct clk **rx_clk);
+ struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev);
int jumbo_max_len;
};
@@ -1162,6 +1165,7 @@ struct macb {
struct clk *hclk;
struct clk *tx_clk;
struct clk *rx_clk;
+ struct clk *tsu_clk;
struct net_device *dev;
union {
struct macb_stats macb;
@@ -1214,6 +1218,8 @@ struct macb {
int rx_bd_rd_prefetch;
int tx_bd_rd_prefetch;
+
+ u32 rx_intr_mask;
};
#ifdef CONFIG_MACB_USE_HWSTAMP
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index b126926ef7f5..ad099fd01b45 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -36,6 +36,8 @@
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
+#include <linux/iopoll.h>
+#include <linux/pm_runtime.h>
#include "macb.h"
#define MACB_RX_BUFFER_SIZE 128
@@ -56,8 +58,7 @@
/* level of occupied TX descriptors under which we wake up TX process */
#define MACB_TX_WAKEUP_THRESH(bp) (3 * (bp)->tx_ring_size / 4)
-#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
- | MACB_BIT(ISR_ROVR))
+#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))
#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \
| MACB_BIT(ISR_RLE) \
| MACB_BIT(TXERR))
@@ -80,6 +81,10 @@
*/
#define MACB_HALT_TIMEOUT 1230
+#define MACB_PM_TIMEOUT 100 /* ms */
+
+#define MACB_MDIO_TIMEOUT 1000000 /* in usecs */
+
/* DMA buffer descriptor might be different size
* depends on hardware configuration:
*
@@ -319,10 +324,26 @@ static void macb_get_hwaddr(struct macb *bp)
eth_hw_addr_random(bp->dev);
}
+static int macb_mdio_wait_for_idle(struct macb *bp)
+{
+ u32 val;
+
+ return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE),
+ 1, MACB_MDIO_TIMEOUT);
+}
+
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
struct macb *bp = bus->priv;
- int value;
+ int status;
+
+ status = pm_runtime_get_sync(&bp->pdev->dev);
+ if (status < 0)
+ goto mdio_pm_exit;
+
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_read_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_READ)
@@ -330,19 +351,32 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_CODE)));
- /* wait for end of transfer */
- while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
- cpu_relax();
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_read_exit;
- value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
+ status = MACB_BFEXT(DATA, macb_readl(bp, MAN));
- return value;
+mdio_read_exit:
+ pm_runtime_mark_last_busy(&bp->pdev->dev);
+ pm_runtime_put_autosuspend(&bp->pdev->dev);
+mdio_pm_exit:
+ return status;
}
static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
{
struct macb *bp = bus->priv;
+ int status;
+
+ status = pm_runtime_get_sync(&bp->pdev->dev);
+ if (status < 0)
+ goto mdio_pm_exit;
+
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_write_exit;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_WRITE)
@@ -351,11 +385,15 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
| MACB_BF(CODE, MACB_MAN_CODE)
| MACB_BF(DATA, value)));
- /* wait for end of transfer */
- while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
- cpu_relax();
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_write_exit;
- return 0;
+mdio_write_exit:
+ pm_runtime_mark_last_busy(&bp->pdev->dev);
+ pm_runtime_put_autosuspend(&bp->pdev->dev);
+mdio_pm_exit:
+ return status;
}
/**
@@ -1270,7 +1308,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
queue_writel(queue, ISR, MACB_BIT(RCOMP));
napi_reschedule(napi);
} else {
- queue_writel(queue, IER, MACB_RX_INT_FLAGS);
+ queue_writel(queue, IER, bp->rx_intr_mask);
}
}
@@ -1288,7 +1326,7 @@ static void macb_hresp_error_task(unsigned long data)
u32 ctrl;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+ queue_writel(queue, IDR, bp->rx_intr_mask |
MACB_TX_INT_FLAGS |
MACB_BIT(HRESP));
}
@@ -1318,7 +1356,7 @@ static void macb_hresp_error_task(unsigned long data)
/* Enable interrupts */
queue_writel(queue, IER,
- MACB_RX_INT_FLAGS |
+ bp->rx_intr_mask |
MACB_TX_INT_FLAGS |
MACB_BIT(HRESP));
}
@@ -1372,14 +1410,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
(unsigned int)(queue - bp->queues),
(unsigned long)status);
- if (status & MACB_RX_INT_FLAGS) {
+ if (status & bp->rx_intr_mask) {
/* There's no point taking any more interrupts
* until we have processed the buffers. The
* scheduling call may fail if the poll routine
* is already scheduled, so disable interrupts
* now.
*/
- queue_writel(queue, IDR, MACB_RX_INT_FLAGS);
+ queue_writel(queue, IDR, bp->rx_intr_mask);
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
queue_writel(queue, ISR, MACB_BIT(RCOMP));
@@ -1412,8 +1450,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
/* There is a hardware issue under heavy load where DMA can
* stop, this causes endless "used buffer descriptor read"
* interrupts but it can be cleared by re-enabling RX. See
- * the at91 manual, section 41.3.1 or the Zynq manual
- * section 16.7.4 for details.
+ * the at91rm9200 manual, section 41.3.1 or the Zynq manual
+ * section 16.7.4 for details. RXUBR is only enabled for
+ * these two versions.
*/
if (status & MACB_BIT(RXUBR)) {
ctrl = macb_readl(bp, NCR);
@@ -1734,16 +1773,12 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
if (!nskb)
return -ENOMEM;
- dev_kfree_skb_any(*skb);
+ dev_consume_skb_any(*skb);
*skb = nskb;
}
- if (padlen) {
- if (padlen >= ETH_FCS_LEN)
- skb_put_zero(*skb, padlen - ETH_FCS_LEN);
- else
- skb_trim(*skb, ETH_FCS_LEN - padlen);
- }
+ if (padlen > ETH_FCS_LEN)
+ skb_put_zero(*skb, padlen - ETH_FCS_LEN);
add_fcs:
/* set FCS to packet */
@@ -2263,7 +2298,7 @@ static void macb_init_hw(struct macb *bp)
/* Enable interrupts */
queue_writel(queue, IER,
- MACB_RX_INT_FLAGS |
+ bp->rx_intr_mask |
MACB_TX_INT_FLAGS |
MACB_BIT(HRESP));
}
@@ -2401,12 +2436,18 @@ static int macb_open(struct net_device *dev)
netdev_dbg(bp->dev, "open\n");
+ err = pm_runtime_get_sync(&bp->pdev->dev);
+ if (err < 0)
+ goto pm_exit;
+
/* carrier starts down */
netif_carrier_off(dev);
/* if the phy is not yet register, retry later*/
- if (!dev->phydev)
- return -EAGAIN;
+ if (!dev->phydev) {
+ err = -EAGAIN;
+ goto pm_exit;
+ }
/* RX buffers initialization */
macb_init_rx_buffer_size(bp, bufsz);
@@ -2415,7 +2456,7 @@ static int macb_open(struct net_device *dev)
if (err) {
netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
err);
- return err;
+ goto pm_exit;
}
bp->macbgem_ops.mog_init_rings(bp);
@@ -2432,6 +2473,11 @@ static int macb_open(struct net_device *dev)
if (bp->ptp_info)
bp->ptp_info->ptp_init(dev);
+pm_exit:
+ if (err) {
+ pm_runtime_put_sync(&bp->pdev->dev);
+ return err;
+ }
return 0;
}
@@ -2460,6 +2506,8 @@ static int macb_close(struct net_device *dev)
if (bp->ptp_info)
bp->ptp_info->ptp_remove(dev);
+ pm_runtime_put(&bp->pdev->dev);
+
return 0;
}
@@ -3308,7 +3356,7 @@ static void macb_probe_queues(void __iomem *mem,
static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk,
- struct clk **rx_clk)
+ struct clk **rx_clk, struct clk **tsu_clk)
{
struct macb_platform_data *pdata;
int err;
@@ -3342,6 +3390,10 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
if (IS_ERR(*rx_clk))
*rx_clk = NULL;
+ *tsu_clk = devm_clk_get(&pdev->dev, "tsu_clk");
+ if (IS_ERR(*tsu_clk))
+ *tsu_clk = NULL;
+
err = clk_prepare_enable(*pclk);
if (err) {
dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
@@ -3366,8 +3418,17 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
goto err_disable_txclk;
}
+ err = clk_prepare_enable(*tsu_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable tsu_clk (%u)\n", err);
+ goto err_disable_rxclk;
+ }
+
return 0;
+err_disable_rxclk:
+ clk_disable_unprepare(*rx_clk);
+
err_disable_txclk:
clk_disable_unprepare(*tx_clk);
@@ -3677,9 +3738,9 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,
/* Store packet information (to free when Tx completed) */
lp->skb = skb;
lp->skb_length = skb->len;
- lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(NULL, lp->skb_physaddr)) {
+ lp->skb_physaddr = dma_map_single(&lp->pdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(&lp->pdev->dev, lp->skb_physaddr)) {
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++;
netdev_err(dev, "%s: DMA mapping error\n", __func__);
@@ -3767,9 +3828,9 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
dev->stats.tx_errors++;
if (lp->skb) {
- dev_kfree_skb_irq(lp->skb);
+ dev_consume_skb_irq(lp->skb);
lp->skb = NULL;
- dma_unmap_single(NULL, lp->skb_physaddr,
+ dma_unmap_single(&lp->pdev->dev, lp->skb_physaddr,
lp->skb_length, DMA_TO_DEVICE);
dev->stats.tx_packets++;
dev->stats.tx_bytes += lp->skb_length;
@@ -3818,13 +3879,14 @@ static const struct net_device_ops at91ether_netdev_ops = {
static int at91ether_clk_init(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk,
- struct clk **rx_clk)
+ struct clk **rx_clk, struct clk **tsu_clk)
{
int err;
*hclk = NULL;
*tx_clk = NULL;
*rx_clk = NULL;
+ *tsu_clk = NULL;
*pclk = devm_clk_get(&pdev->dev, "ether_clk");
if (IS_ERR(*pclk))
@@ -3911,6 +3973,7 @@ static const struct macb_config sama5d4_config = {
};
static const struct macb_config emac_config = {
+ .caps = MACB_CAPS_NEEDS_RSTONUBR,
.clk_init = at91ether_clk_init,
.init = at91ether_init,
};
@@ -3932,7 +3995,8 @@ static const struct macb_config zynqmp_config = {
};
static const struct macb_config zynq_config = {
- .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF,
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF |
+ MACB_CAPS_NEEDS_RSTONUBR,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
@@ -3945,6 +4009,7 @@ static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,np4-macb", .data = &np4_config },
{ .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
{ .compatible = "cdns,gem", .data = &pc302gem_config },
+ { .compatible = "cdns,sam9x60-macb", .data = &at91sam9260_config },
{ .compatible = "atmel,sama5d2-gem", .data = &sama5d2_config },
{ .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config },
{ .compatible = "atmel,sama5d3-macb", .data = &sama5d3macb_config },
@@ -3972,11 +4037,12 @@ static int macb_probe(struct platform_device *pdev)
{
const struct macb_config *macb_config = &default_gem_config;
int (*clk_init)(struct platform_device *, struct clk **,
- struct clk **, struct clk **, struct clk **)
- = macb_config->clk_init;
+ struct clk **, struct clk **, struct clk **,
+ struct clk **) = macb_config->clk_init;
int (*init)(struct platform_device *) = macb_config->init;
struct device_node *np = pdev->dev.of_node;
struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
+ struct clk *tsu_clk = NULL;
unsigned int queue_mask, num_queues;
struct macb_platform_data *pdata;
bool native_io;
@@ -4004,10 +4070,15 @@ static int macb_probe(struct platform_device *pdev)
}
}
- err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk);
+ err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk, &tsu_clk);
if (err)
return err;
+ pm_runtime_set_autosuspend_delay(&pdev->dev, MACB_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
native_io = hw_is_native_io(mem);
macb_probe_queues(mem, native_io, &queue_mask, &num_queues);
@@ -4041,6 +4112,7 @@ static int macb_probe(struct platform_device *pdev)
bp->hclk = hclk;
bp->tx_clk = tx_clk;
bp->rx_clk = rx_clk;
+ bp->tsu_clk = tsu_clk;
if (macb_config)
bp->jumbo_max_len = macb_config->jumbo_max_len;
@@ -4087,6 +4159,10 @@ static int macb_probe(struct platform_device *pdev)
macb_dma_desc_get_size(bp);
}
+ bp->rx_intr_mask = MACB_RX_INT_FLAGS;
+ if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
+ bp->rx_intr_mask |= MACB_BIT(RXUBR);
+
mac = of_get_mac_address(np);
if (mac) {
ether_addr_copy(bp->dev->dev_addr, mac);
@@ -4138,6 +4214,9 @@ static int macb_probe(struct platform_device *pdev)
macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
dev->base_addr, dev->irq, dev->dev_addr);
+ pm_runtime_mark_last_busy(&bp->pdev->dev);
+ pm_runtime_put_autosuspend(&bp->pdev->dev);
+
return 0;
err_out_unregister_mdio:
@@ -4156,6 +4235,10 @@ err_disable_clocks:
clk_disable_unprepare(hclk);
clk_disable_unprepare(pclk);
clk_disable_unprepare(rx_clk);
+ clk_disable_unprepare(tsu_clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
return err;
}
@@ -4179,10 +4262,16 @@ static int macb_remove(struct platform_device *pdev)
mdiobus_free(bp->mii_bus);
unregister_netdev(dev);
- clk_disable_unprepare(bp->tx_clk);
- clk_disable_unprepare(bp->hclk);
- clk_disable_unprepare(bp->pclk);
- clk_disable_unprepare(bp->rx_clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ if (!pm_runtime_suspended(&pdev->dev)) {
+ clk_disable_unprepare(bp->tx_clk);
+ clk_disable_unprepare(bp->hclk);
+ clk_disable_unprepare(bp->pclk);
+ clk_disable_unprepare(bp->rx_clk);
+ clk_disable_unprepare(bp->tsu_clk);
+ pm_runtime_set_suspended(&pdev->dev);
+ }
of_node_put(bp->phy_node);
free_netdev(dev);
}
@@ -4194,21 +4283,36 @@ static int __maybe_unused macb_suspend(struct device *dev)
{
struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev);
+ struct macb_queue *queue = bp->queues;
+ unsigned long flags;
+ unsigned int q;
+
+ if (!netif_running(netdev))
+ return 0;
- netif_carrier_off(netdev);
- netif_device_detach(netdev);
if (bp->wol & MACB_WOL_ENABLED) {
macb_writel(bp, IER, MACB_BIT(WOL));
macb_writel(bp, WOL, MACB_BIT(MAG));
enable_irq_wake(bp->queues[0].irq);
+ netif_device_detach(netdev);
} else {
- clk_disable_unprepare(bp->tx_clk);
- clk_disable_unprepare(bp->hclk);
- clk_disable_unprepare(bp->pclk);
- clk_disable_unprepare(bp->rx_clk);
+ netif_device_detach(netdev);
+ for (q = 0, queue = bp->queues; q < bp->num_queues;
+ ++q, ++queue)
+ napi_disable(&queue->napi);
+ phy_stop(netdev->phydev);
+ phy_suspend(netdev->phydev);
+ spin_lock_irqsave(&bp->lock, flags);
+ macb_reset_hw(bp);
+ spin_unlock_irqrestore(&bp->lock, flags);
}
+ netif_carrier_off(netdev);
+ if (bp->ptp_info)
+ bp->ptp_info->ptp_remove(netdev);
+ pm_runtime_force_suspend(dev);
+
return 0;
}
@@ -4216,24 +4320,76 @@ static int __maybe_unused macb_resume(struct device *dev)
{
struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev);
+ struct macb_queue *queue = bp->queues;
+ unsigned int q;
+
+ if (!netif_running(netdev))
+ return 0;
+
+ pm_runtime_force_resume(dev);
if (bp->wol & MACB_WOL_ENABLED) {
macb_writel(bp, IDR, MACB_BIT(WOL));
macb_writel(bp, WOL, 0);
disable_irq_wake(bp->queues[0].irq);
} else {
+ macb_writel(bp, NCR, MACB_BIT(MPE));
+ for (q = 0, queue = bp->queues; q < bp->num_queues;
+ ++q, ++queue)
+ napi_enable(&queue->napi);
+ phy_resume(netdev->phydev);
+ phy_init_hw(netdev->phydev);
+ phy_start(netdev->phydev);
+ }
+
+ bp->macbgem_ops.mog_init_rings(bp);
+ macb_init_hw(bp);
+ macb_set_rx_mode(netdev);
+ netif_device_attach(netdev);
+ if (bp->ptp_info)
+ bp->ptp_info->ptp_init(netdev);
+
+ return 0;
+}
+
+static int __maybe_unused macb_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *netdev = platform_get_drvdata(pdev);
+ struct macb *bp = netdev_priv(netdev);
+
+ if (!(device_may_wakeup(&bp->dev->dev))) {
+ clk_disable_unprepare(bp->tx_clk);
+ clk_disable_unprepare(bp->hclk);
+ clk_disable_unprepare(bp->pclk);
+ clk_disable_unprepare(bp->rx_clk);
+ }
+ clk_disable_unprepare(bp->tsu_clk);
+
+ return 0;
+}
+
+static int __maybe_unused macb_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *netdev = platform_get_drvdata(pdev);
+ struct macb *bp = netdev_priv(netdev);
+
+ if (!(device_may_wakeup(&bp->dev->dev))) {
clk_prepare_enable(bp->pclk);
clk_prepare_enable(bp->hclk);
clk_prepare_enable(bp->tx_clk);
clk_prepare_enable(bp->rx_clk);
}
-
- netif_device_attach(netdev);
+ clk_prepare_enable(bp->tsu_clk);
return 0;
}
-static SIMPLE_DEV_PM_OPS(macb_pm_ops, macb_suspend, macb_resume);
+static const struct dev_pm_ops macb_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(macb_suspend, macb_resume)
+ SET_RUNTIME_PM_OPS(macb_runtime_suspend, macb_runtime_resume, NULL)
+};
static struct platform_driver macb_driver = {
.probe = macb_probe,
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 5f03199a3acf..6650e2a5f171 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -54,7 +54,6 @@ config CAVIUM_PTP
tristate "Cavium PTP coprocessor as PTP clock"
depends on 64BIT && PCI
imply PTP_1588_CLOCK
- default y
---help---
This driver adds support for the Precision Time Protocol Clocks and
Timestamping coprocessor (PTP) found on Cavium processors.
@@ -65,7 +64,6 @@ config CAVIUM_PTP
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT && PCI
- depends on MAY_USE_DEVLINK
depends on PCI
imply PTP_1588_CLOCK
select FW_LOADER
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index 9f4f3c1d5043..43d11c38b38a 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -1450,7 +1450,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
mbox_cmd.recv_len = 0;
mbox_cmd.recv_status = 0;
mbox_cmd.fn = NULL;
- mbox_cmd.fn_arg = 0;
+ mbox_cmd.fn_arg = NULL;
ether_addr_copy(mbox_cmd.msg.s.params, mac);
mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf;
octeon_mbox_write(oct, &mbox_cmd);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 825a28e5b544..e21bf3724611 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -661,7 +661,8 @@ liquidio_push_packet(u32 octeon_id __attribute__((unused)),
(((rh->r_dh.encap_on) &&
(rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) ||
(!(rh->r_dh.encap_on) &&
- (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED))))
+ ((rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED) ==
+ CNNIC_CSUM_VERIFIED))))
/* checksum has already been verified */
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 3d24133e5e49..9b7819fdc9de 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -21,7 +21,6 @@
#include <linux/firmware.h>
#include <net/vxlan.h>
#include <linux/kthread.h>
-#include <net/switchdev.h>
#include "liquidio_common.h"
#include "octeon_droq.h"
#include "octeon_iq.h"
@@ -2908,7 +2907,7 @@ static int liquidio_set_vf_spoofchk(struct net_device *netdev, int vfidx,
nctrl.ncmd.s.param2 = enable;
nctrl.ncmd.s.more = 0;
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
- nctrl.cb_fn = 0;
+ nctrl.cb_fn = NULL;
retval = octnet_send_nic_ctrl_pkt(oct, &nctrl);
@@ -3184,7 +3183,8 @@ static const struct devlink_ops liquidio_devlink_ops = {
};
static int
-lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+liquidio_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
struct lio *lio = GET_LIO(dev);
struct octeon_device *oct = lio->oct_dev;
@@ -3192,24 +3192,12 @@ lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr)
if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
return -EOPNOTSUPP;
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = ETH_ALEN;
- ether_addr_copy(attr->u.ppid.id,
- (void *)&lio->linfo.hw_addr + 2);
- break;
-
- default:
- return -EOPNOTSUPP;
- }
+ ppid->id_len = ETH_ALEN;
+ ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2);
return 0;
}
-static const struct switchdev_ops lio_pf_switchdev_ops = {
- .switchdev_port_attr_get = lio_pf_switchdev_attr_get,
-};
-
static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx,
struct ifla_vf_stats *vf_stats)
{
@@ -3259,6 +3247,7 @@ static const struct net_device_ops lionetdevops = {
.ndo_set_vf_trust = liquidio_set_vf_trust,
.ndo_set_vf_link_state = liquidio_set_vf_link_state,
.ndo_get_vf_stats = liquidio_get_vf_stats,
+ .ndo_get_port_parent_id = liquidio_get_port_parent_id,
};
/** \brief Entry point for the liquidio module
@@ -3534,7 +3523,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
* netdev tasks.
*/
netdev->netdev_ops = &lionetdevops;
- SWITCHDEV_SET_OPS(netdev, &lio_pf_switchdev_ops);
retval = netif_set_real_num_rx_queues(netdev, num_oqueues);
if (retval) {
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
index de61060721c4..f3f2e71431ac 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
@@ -25,7 +25,6 @@
#include "octeon_nic.h"
#include "octeon_main.h"
#include "octeon_network.h"
-#include <net/switchdev.h>
#include "lio_vf_rep.h"
static int lio_vf_rep_open(struct net_device *ndev);
@@ -38,6 +37,8 @@ static int lio_vf_rep_phys_port_name(struct net_device *dev,
static void lio_vf_rep_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats64);
static int lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu);
+static int lio_vf_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid);
static const struct net_device_ops lio_vf_rep_ndev_ops = {
.ndo_open = lio_vf_rep_open,
@@ -47,6 +48,7 @@ static const struct net_device_ops lio_vf_rep_ndev_ops = {
.ndo_get_phys_port_name = lio_vf_rep_phys_port_name,
.ndo_get_stats64 = lio_vf_rep_get_stats64,
.ndo_change_mtu = lio_vf_rep_change_mtu,
+ .ndo_get_port_parent_id = lio_vf_get_port_parent_id,
};
static int
@@ -443,31 +445,19 @@ xmit_failed:
return NETDEV_TX_OK;
}
-static int
-lio_vf_rep_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+static int lio_vf_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);
struct net_device *parent_ndev = vf_rep->parent_ndev;
struct lio *lio = GET_LIO(parent_ndev);
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = ETH_ALEN;
- ether_addr_copy(attr->u.ppid.id,
- (void *)&lio->linfo.hw_addr + 2);
- break;
-
- default:
- return -EOPNOTSUPP;
- }
+ ppid->id_len = ETH_ALEN;
+ ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2);
return 0;
}
-static const struct switchdev_ops lio_vf_rep_switchdev_ops = {
- .switchdev_port_attr_get = lio_vf_rep_attr_get,
-};
-
static void
lio_vf_rep_fetch_stats(struct work_struct *work)
{
@@ -524,7 +514,6 @@ lio_vf_rep_create(struct octeon_device *oct)
ndev->min_mtu = LIO_MIN_MTU_SIZE;
ndev->max_mtu = LIO_MAX_MTU_SIZE;
ndev->netdev_ops = &lio_vf_rep_ndev_ops;
- SWITCHDEV_SET_OPS(ndev, &lio_vf_rep_switchdev_ops);
vf_rep = netdev_priv(ndev);
memset(vf_rep, 0, sizeof(*vf_rep));
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index f4d81765221e..62636c1ed141 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -271,7 +271,7 @@ struct xcast_addr_list {
};
struct nicvf_work {
- struct delayed_work work;
+ struct work_struct work;
u8 mode;
struct xcast_addr_list *mc;
};
@@ -327,7 +327,11 @@ struct nicvf {
struct nicvf_work rx_mode_work;
/* spinlock to protect workqueue arguments from concurrent access */
spinlock_t rx_mode_wq_lock;
-
+ /* workqueue for handling kernel ndo_set_rx_mode() calls */
+ struct workqueue_struct *nicvf_rx_mode_wq;
+ /* mutex to protect VF's mailbox contents from concurrent access */
+ struct mutex rx_mode_mtx;
+ struct delayed_work link_change_work;
/* PTP timestamp */
struct cavium_ptp *ptp_clock;
/* Inbound timestamping is on */
@@ -575,10 +579,8 @@ struct set_ptp {
struct xcast {
u8 msg;
- union {
- u8 mode;
- u64 mac;
- } data;
+ u8 mode;
+ u64 mac:48;
};
/* 128 bit shared memory between PF and each VF */
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 6c8dcb65ff03..c90252829ed3 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -57,14 +57,8 @@ struct nicpf {
#define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF)
#define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF)
u8 *vf_lmac_map;
- struct delayed_work dwork;
- struct workqueue_struct *check_link;
- u8 *link;
- u8 *duplex;
- u32 *speed;
u16 cpi_base[MAX_NUM_VFS_SUPPORTED];
u16 rssi_base[MAX_NUM_VFS_SUPPORTED];
- bool mbx_lock[MAX_NUM_VFS_SUPPORTED];
/* MSI-X */
u8 num_vec;
@@ -929,6 +923,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
}
+/* Get BGX LMAC link status and update corresponding VF
+ * if there is a change, valid only if internal L2 switch
+ * is not present otherwise VF link is always treated as up
+ */
+static void nic_link_status_get(struct nicpf *nic, u8 vf)
+{
+ union nic_mbx mbx = {};
+ struct bgx_link_status link;
+ u8 bgx, lmac;
+
+ mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
+
+ /* Get BGX, LMAC indices for the VF */
+ bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+ /* Get interface link status */
+ bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
+
+ /* Send a mbox message to VF with current link status */
+ mbx.link_status.link_up = link.link_up;
+ mbx.link_status.duplex = link.duplex;
+ mbx.link_status.speed = link.speed;
+ mbx.link_status.mac_type = link.mac_type;
+
+ /* reply with link status */
+ nic_send_msg_to_vf(nic, vf, &mbx);
+}
+
/* Interrupt handler to handle mailbox messages from VFs */
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
{
@@ -941,8 +964,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
int i;
int ret = 0;
- nic->mbx_lock[vf] = true;
-
mbx_addr = nic_get_mbx_addr(vf);
mbx_data = (u64 *)&mbx;
@@ -957,12 +978,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
switch (mbx.msg.msg) {
case NIC_MBOX_MSG_READY:
nic_mbx_send_ready(nic, vf);
- if (vf < nic->num_vf_en) {
- nic->link[vf] = 0;
- nic->duplex[vf] = 0;
- nic->speed[vf] = 0;
- }
- goto unlock;
+ return;
case NIC_MBOX_MSG_QS_CFG:
reg_addr = NIC_PF_QSET_0_127_CFG |
(mbx.qs.num << NIC_QS_ID_SHIFT);
@@ -1031,7 +1047,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
break;
case NIC_MBOX_MSG_RSS_SIZE:
nic_send_rss_size(nic, vf);
- goto unlock;
+ return;
case NIC_MBOX_MSG_RSS_CFG:
case NIC_MBOX_MSG_RSS_CFG_CONT:
nic_config_rss(nic, &mbx.rss_cfg);
@@ -1039,7 +1055,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
case NIC_MBOX_MSG_CFG_DONE:
/* Last message of VF config msg sequence */
nic_enable_vf(nic, vf, true);
- goto unlock;
+ break;
case NIC_MBOX_MSG_SHUTDOWN:
/* First msg in VF teardown sequence */
if (vf >= nic->num_vf_en)
@@ -1049,19 +1065,19 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
break;
case NIC_MBOX_MSG_ALLOC_SQS:
nic_alloc_sqs(nic, &mbx.sqs_alloc);
- goto unlock;
+ return;
case NIC_MBOX_MSG_NICVF_PTR:
nic->nicvf[vf] = mbx.nicvf.nicvf;
break;
case NIC_MBOX_MSG_PNICVF_PTR:
nic_send_pnicvf(nic, vf);
- goto unlock;
+ return;
case NIC_MBOX_MSG_SNICVF_PTR:
nic_send_snicvf(nic, &mbx.nicvf);
- goto unlock;
+ return;
case NIC_MBOX_MSG_BGX_STATS:
nic_get_bgx_stats(nic, &mbx.bgx_stats);
- goto unlock;
+ return;
case NIC_MBOX_MSG_LOOPBACK:
ret = nic_config_loopback(nic, &mbx.lbk);
break;
@@ -1070,7 +1086,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
break;
case NIC_MBOX_MSG_PFC:
nic_pause_frame(nic, vf, &mbx.pfc);
- goto unlock;
+ return;
case NIC_MBOX_MSG_PTP_CFG:
nic_config_timestamp(nic, vf, &mbx.ptp);
break;
@@ -1094,7 +1110,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_set_dmac_cam_filter(nic->node, bgx, lmac,
- mbx.xcast.data.mac,
+ mbx.xcast.mac,
vf < NIC_VF_PER_MBX_REG ? vf :
vf - NIC_VF_PER_MBX_REG);
break;
@@ -1106,8 +1122,15 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
}
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
- bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.data.mode);
+ bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode);
break;
+ case NIC_MBOX_MSG_BGX_LINK_CHANGE:
+ if (vf >= nic->num_vf_en) {
+ ret = -1; /* NACK */
+ break;
+ }
+ nic_link_status_get(nic, vf);
+ return;
default:
dev_err(&nic->pdev->dev,
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1121,8 +1144,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
mbx.msg.msg, vf);
nic_mbx_send_nack(nic, vf);
}
-unlock:
- nic->mbx_lock[vf] = false;
}
static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq)
@@ -1270,52 +1291,6 @@ static int nic_sriov_init(struct pci_dev *pdev, struct nicpf *nic)
return 0;
}
-/* Poll for BGX LMAC link status and update corresponding VF
- * if there is a change, valid only if internal L2 switch
- * is not present otherwise VF link is always treated as up
- */
-static void nic_poll_for_link(struct work_struct *work)
-{
- union nic_mbx mbx = {};
- struct nicpf *nic;
- struct bgx_link_status link;
- u8 vf, bgx, lmac;
-
- nic = container_of(work, struct nicpf, dwork.work);
-
- mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
-
- for (vf = 0; vf < nic->num_vf_en; vf++) {
- /* Poll only if VF is UP */
- if (!nic->vf_enabled[vf])
- continue;
-
- /* Get BGX, LMAC indices for the VF */
- bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
- lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
- /* Get interface link status */
- bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
-
- /* Inform VF only if link status changed */
- if (nic->link[vf] == link.link_up)
- continue;
-
- if (!nic->mbx_lock[vf]) {
- nic->link[vf] = link.link_up;
- nic->duplex[vf] = link.duplex;
- nic->speed[vf] = link.speed;
-
- /* Send a mbox message to VF with current link status */
- mbx.link_status.link_up = link.link_up;
- mbx.link_status.duplex = link.duplex;
- mbx.link_status.speed = link.speed;
- mbx.link_status.mac_type = link.mac_type;
- nic_send_msg_to_vf(nic, vf, &mbx);
- }
- }
- queue_delayed_work(nic->check_link, &nic->dwork, HZ * 2);
-}
-
static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
@@ -1384,18 +1359,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!nic->vf_lmac_map)
goto err_release_regions;
- nic->link = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL);
- if (!nic->link)
- goto err_release_regions;
-
- nic->duplex = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL);
- if (!nic->duplex)
- goto err_release_regions;
-
- nic->speed = devm_kmalloc_array(dev, max_lmac, sizeof(u32), GFP_KERNEL);
- if (!nic->speed)
- goto err_release_regions;
-
/* Initialize hardware */
nic_init_hw(nic);
@@ -1411,22 +1374,8 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_unregister_interrupts;
- /* Register a physical link status poll fn() */
- nic->check_link = alloc_workqueue("check_link_status",
- WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
- if (!nic->check_link) {
- err = -ENOMEM;
- goto err_disable_sriov;
- }
-
- INIT_DELAYED_WORK(&nic->dwork, nic_poll_for_link);
- queue_delayed_work(nic->check_link, &nic->dwork, 0);
-
return 0;
-err_disable_sriov:
- if (nic->flags & NIC_SRIOV_ENABLED)
- pci_disable_sriov(pdev);
err_unregister_interrupts:
nic_unregister_interrupts(nic);
err_release_regions:
@@ -1447,12 +1396,6 @@ static void nic_remove(struct pci_dev *pdev)
if (nic->flags & NIC_SRIOV_ENABLED)
pci_disable_sriov(pdev);
- if (nic->check_link) {
- /* Destroy work Queue */
- cancel_delayed_work_sync(&nic->dwork);
- destroy_workqueue(nic->check_link);
- }
-
nic_unregister_interrupts(nic);
pci_release_regions(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 88f8a8fa93cd..503cfadff4ac 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -68,9 +68,6 @@ module_param(cpi_alg, int, 0444);
MODULE_PARM_DESC(cpi_alg,
"PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
-/* workqueue for handling kernel ndo_set_rx_mode() calls */
-static struct workqueue_struct *nicvf_rx_mode_wq;
-
static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx)
{
if (nic->sqs_mode)
@@ -127,6 +124,9 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
{
int timeout = NIC_MBOX_MSG_TIMEOUT;
int sleep = 10;
+ int ret = 0;
+
+ mutex_lock(&nic->rx_mode_mtx);
nic->pf_acked = false;
nic->pf_nacked = false;
@@ -139,7 +139,8 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
netdev_err(nic->netdev,
"PF NACK to mbox msg 0x%02x from VF%d\n",
(mbx->msg.msg & 0xFF), nic->vf_id);
- return -EINVAL;
+ ret = -EINVAL;
+ break;
}
msleep(sleep);
if (nic->pf_acked)
@@ -149,10 +150,12 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
netdev_err(nic->netdev,
"PF didn't ACK to mbox msg 0x%02x from VF%d\n",
(mbx->msg.msg & 0xFF), nic->vf_id);
- return -EBUSY;
+ ret = -EBUSY;
+ break;
}
}
- return 0;
+ mutex_unlock(&nic->rx_mode_mtx);
+ return ret;
}
/* Checks if VF is able to comminicate with PF
@@ -172,6 +175,17 @@ static int nicvf_check_pf_ready(struct nicvf *nic)
return 1;
}
+static void nicvf_send_cfg_done(struct nicvf *nic)
+{
+ union nic_mbx mbx = {};
+
+ mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
+ if (nicvf_send_msg_to_pf(nic, &mbx)) {
+ netdev_err(nic->netdev,
+ "PF didn't respond to CFG DONE msg\n");
+ }
+}
+
static void nicvf_read_bgx_stats(struct nicvf *nic, struct bgx_stats_msg *bgx)
{
if (bgx->rx)
@@ -228,21 +242,24 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
break;
case NIC_MBOX_MSG_BGX_LINK_CHANGE:
nic->pf_acked = true;
- nic->link_up = mbx.link_status.link_up;
- nic->duplex = mbx.link_status.duplex;
- nic->speed = mbx.link_status.speed;
- nic->mac_type = mbx.link_status.mac_type;
- if (nic->link_up) {
- netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n",
- nic->speed,
- nic->duplex == DUPLEX_FULL ?
- "Full" : "Half");
- netif_carrier_on(nic->netdev);
- netif_tx_start_all_queues(nic->netdev);
- } else {
- netdev_info(nic->netdev, "Link is Down\n");
- netif_carrier_off(nic->netdev);
- netif_tx_stop_all_queues(nic->netdev);
+ if (nic->link_up != mbx.link_status.link_up) {
+ nic->link_up = mbx.link_status.link_up;
+ nic->duplex = mbx.link_status.duplex;
+ nic->speed = mbx.link_status.speed;
+ nic->mac_type = mbx.link_status.mac_type;
+ if (nic->link_up) {
+ netdev_info(nic->netdev,
+ "Link is Up %d Mbps %s duplex\n",
+ nic->speed,
+ nic->duplex == DUPLEX_FULL ?
+ "Full" : "Half");
+ netif_carrier_on(nic->netdev);
+ netif_tx_start_all_queues(nic->netdev);
+ } else {
+ netdev_info(nic->netdev, "Link is Down\n");
+ netif_carrier_off(nic->netdev);
+ netif_tx_stop_all_queues(nic->netdev);
+ }
}
break;
case NIC_MBOX_MSG_ALLOC_SQS:
@@ -1311,6 +1328,11 @@ int nicvf_stop(struct net_device *netdev)
struct nicvf_cq_poll *cq_poll = NULL;
union nic_mbx mbx = {};
+ cancel_delayed_work_sync(&nic->link_change_work);
+
+ /* wait till all queued set_rx_mode tasks completes */
+ drain_workqueue(nic->nicvf_rx_mode_wq);
+
mbx.msg.msg = NIC_MBOX_MSG_SHUTDOWN;
nicvf_send_msg_to_pf(nic, &mbx);
@@ -1410,13 +1432,27 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
return nicvf_send_msg_to_pf(nic, &mbx);
}
+static void nicvf_link_status_check_task(struct work_struct *work_arg)
+{
+ struct nicvf *nic = container_of(work_arg,
+ struct nicvf,
+ link_change_work.work);
+ union nic_mbx mbx = {};
+ mbx.msg.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
+ nicvf_send_msg_to_pf(nic, &mbx);
+ queue_delayed_work(nic->nicvf_rx_mode_wq,
+ &nic->link_change_work, 2 * HZ);
+}
+
int nicvf_open(struct net_device *netdev)
{
int cpu, err, qidx;
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
struct nicvf_cq_poll *cq_poll = NULL;
- union nic_mbx mbx = {};
+
+ /* wait till all queued set_rx_mode tasks completes if any */
+ drain_workqueue(nic->nicvf_rx_mode_wq);
netif_carrier_off(netdev);
@@ -1512,8 +1548,12 @@ int nicvf_open(struct net_device *netdev)
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
/* Send VF config done msg to PF */
- mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
- nicvf_write_to_mbx(nic, &mbx);
+ nicvf_send_cfg_done(nic);
+
+ INIT_DELAYED_WORK(&nic->link_change_work,
+ nicvf_link_status_check_task);
+ queue_delayed_work(nic->nicvf_rx_mode_wq,
+ &nic->link_change_work, 0);
return 0;
cleanup:
@@ -1941,15 +1981,17 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
/* flush DMAC filters and reset RX mode */
mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST;
- nicvf_send_msg_to_pf(nic, &mbx);
+ if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+ goto free_mc;
if (mode & BGX_XCAST_MCAST_FILTER) {
/* once enabling filtering, we need to signal to PF to add
* its' own LMAC to the filter to accept packets for it.
*/
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
- mbx.xcast.data.mac = 0;
- nicvf_send_msg_to_pf(nic, &mbx);
+ mbx.xcast.mac = 0;
+ if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+ goto free_mc;
}
/* check if we have any specific MACs to be added to PF DMAC filter */
@@ -1957,23 +1999,25 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
/* now go through kernel list of MACs and add them one by one */
for (idx = 0; idx < mc_addrs->count; idx++) {
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
- mbx.xcast.data.mac = mc_addrs->mc[idx];
- nicvf_send_msg_to_pf(nic, &mbx);
+ mbx.xcast.mac = mc_addrs->mc[idx];
+ if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+ goto free_mc;
}
- kfree(mc_addrs);
}
/* and finally set rx mode for PF accordingly */
mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST;
- mbx.xcast.data.mode = mode;
+ mbx.xcast.mode = mode;
nicvf_send_msg_to_pf(nic, &mbx);
+free_mc:
+ kfree(mc_addrs);
}
static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
{
struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
- work.work);
+ work);
struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
u8 mode;
struct xcast_addr_list *mc;
@@ -2030,7 +2074,7 @@ static void nicvf_set_rx_mode(struct net_device *netdev)
kfree(nic->rx_mode_work.mc);
nic->rx_mode_work.mc = mc_list;
nic->rx_mode_work.mode = mode;
- queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 0);
+ queue_work(nic->nicvf_rx_mode_wq, &nic->rx_mode_work.work);
spin_unlock(&nic->rx_mode_wq_lock);
}
@@ -2187,8 +2231,12 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&nic->reset_task, nicvf_reset_task);
- INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
+ nic->nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_rx_mode_wq_VF%d",
+ WQ_MEM_RECLAIM,
+ nic->vf_id);
+ INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
spin_lock_init(&nic->rx_mode_wq_lock);
+ mutex_init(&nic->rx_mode_mtx);
err = register_netdev(netdev);
if (err) {
@@ -2228,13 +2276,15 @@ static void nicvf_remove(struct pci_dev *pdev)
nic = netdev_priv(netdev);
pnetdev = nic->pnicvf->netdev;
- cancel_delayed_work_sync(&nic->rx_mode_work.work);
-
/* Check if this Qset is assigned to different VF.
* If yes, clean primary and all secondary Qsets.
*/
if (pnetdev && (pnetdev->reg_state == NETREG_REGISTERED))
unregister_netdev(pnetdev);
+ if (nic->nicvf_rx_mode_wq) {
+ destroy_workqueue(nic->nicvf_rx_mode_wq);
+ nic->nicvf_rx_mode_wq = NULL;
+ }
nicvf_unregister_interrupts(nic);
pci_set_drvdata(pdev, NULL);
if (nic->drv_stats)
@@ -2261,17 +2311,11 @@ static struct pci_driver nicvf_driver = {
static int __init nicvf_init_module(void)
{
pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION);
- nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_generic",
- WQ_MEM_RECLAIM);
return pci_register_driver(&nicvf_driver);
}
static void __exit nicvf_cleanup_module(void)
{
- if (nicvf_rx_mode_wq) {
- destroy_workqueue(nicvf_rx_mode_wq);
- nicvf_rx_mode_wq = NULL;
- }
pci_unregister_driver(&nicvf_driver);
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index fcaf18fa3904..5b4d3badcb73 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -59,7 +59,7 @@ static int nicvf_alloc_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem,
dmem->q_len = q_len;
dmem->size = (desc_size * q_len) + align_bytes;
/* Save address, need it while freeing */
- dmem->unalign_base = dma_zalloc_coherent(&nic->pdev->dev, dmem->size,
+ dmem->unalign_base = dma_alloc_coherent(&nic->pdev->dev, dmem->size,
&dmem->dma, GFP_KERNEL);
if (!dmem->unalign_base)
return -ENOMEM;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index e337da6ba2a4..673c57b8023f 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1217,7 +1217,7 @@ static void bgx_init_hw(struct bgx *bgx)
/* Disable MAC steering (NCSI traffic) */
for (i = 0; i < RX_TRAFFIC_STEER_RULE_COUNT; i++)
- bgx_reg_write(bgx, 0, BGX_CMR_RX_STREERING + (i * 8), 0x00);
+ bgx_reg_write(bgx, 0, BGX_CMR_RX_STEERING + (i * 8), 0x00);
}
static u8 bgx_get_lane2sds_cfg(struct bgx *bgx, struct lmac *lmac)
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index cbdd20b9ee6f..5cbc54e9eb19 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -60,7 +60,7 @@
#define RX_DMACX_CAM_EN BIT_ULL(48)
#define RX_DMACX_CAM_LMACID(x) (((u64)x) << 49)
#define RX_DMAC_COUNT 32
-#define BGX_CMR_RX_STREERING 0x300
+#define BGX_CMR_RX_STEERING 0x300
#define RX_TRAFFIC_STEER_RULE_COUNT 8
#define BGX_CMR_CHAN_MSK_AND 0x450
#define BGX_CMR_BIST_STATUS 0x460
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 30de26ef3da4..47b5c8e2104b 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -585,8 +585,7 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
sizeof(struct cpl_rx_data) +
sge->freelQ[!sge->jumbo_fl].dma_offset;
- size = (16 * 1024) -
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ size = (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
sge->freelQ[sge->jumbo_fl].rx_buffer_size = size;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index 20b6e1b3f5e3..89db739b7819 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -620,7 +620,7 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
{
size_t len = nelem * elem_size;
void *s = NULL;
- void *p = dma_zalloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
+ void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
if (!p)
return NULL;
@@ -2381,7 +2381,7 @@ no_mem:
lro_add_page(adap, qs, fl,
G_RSPD_LEN(len),
flags & F_RSPD_EOP);
- goto next_fl;
+ goto next_fl;
}
skb = get_packet_pg(adap, fl, q,
@@ -3214,11 +3214,13 @@ void t3_start_sge_timers(struct adapter *adap)
for (i = 0; i < SGE_QSETS; ++i) {
struct sge_qset *q = &adap->sge.qs[i];
- if (q->tx_reclaim_timer.function)
- mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+ if (q->tx_reclaim_timer.function)
+ mod_timer(&q->tx_reclaim_timer,
+ jiffies + TX_RECLAIM_PERIOD);
- if (q->rx_reclaim_timer.function)
- mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
+ if (q->rx_reclaim_timer.function)
+ mod_timer(&q->rx_reclaim_timer,
+ jiffies + RX_RECLAIM_PERIOD);
}
}
diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
index 080918af773c..0a9f2c596624 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
@@ -1082,7 +1082,7 @@ int t3_check_fw_version(struct adapter *adapter)
CH_WARN(adapter, "found newer FW version(%u.%u), "
"driver compiled for version %u.%u\n", major, minor,
FW_VERSION_MAJOR, FW_VERSION_MINOR);
- return 0;
+ return 0;
}
return -EINVAL;
}
@@ -3619,7 +3619,7 @@ int t3_reset_adapter(struct adapter *adapter)
static int init_parity(struct adapter *adap)
{
- int i, err, addr;
+ int i, err, addr;
if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
return -EBUSY;
@@ -3806,6 +3806,6 @@ int t3_replay_prep_adapter(struct adapter *adapter)
p->phy.ops->power_down(&p->phy, 1);
}
-return 0;
+ return 0;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
index 5701272aa7f7..ce28820c57c9 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
@@ -289,8 +289,7 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
if (clipt_size < CLIPT_MIN_HASH_BUCKETS)
return NULL;
- ctbl = kvzalloc(sizeof(*ctbl) +
- clipt_size*sizeof(struct list_head), GFP_KERNEL);
+ ctbl = kvzalloc(struct_size(ctbl, hash_list, clipt_size), GFP_KERNEL);
if (!ctbl)
return NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
index 127b1f624413..7c5bfc931128 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
@@ -81,7 +81,7 @@ static int is_fw_attached(struct cudbg_init *pdbg_init)
{
struct adapter *padap = pdbg_init->adap;
- if (!(padap->flags & FW_OK) || padap->use_bd)
+ if (!(padap->flags & CXGB4_FW_OK) || padap->use_bd)
return 0;
return 1;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 2d1ca920601e..956219c178e1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -568,7 +568,7 @@ struct sge_rspq;
struct port_info {
struct adapter *adapter;
u16 viid;
- s16 xact_addr_filt; /* index of exact MAC address filter */
+ int xact_addr_filt; /* index of exact MAC address filter */
u16 rss_size; /* size of VI's RSS table slice */
s8 mdio_addr;
enum fw_port_type port_type;
@@ -606,17 +606,18 @@ struct dentry;
struct work_struct;
enum { /* adapter flags */
- FULL_INIT_DONE = (1 << 0),
- DEV_ENABLED = (1 << 1),
- USING_MSI = (1 << 2),
- USING_MSIX = (1 << 3),
- FW_OK = (1 << 4),
- RSS_TNLALLLOOKUP = (1 << 5),
- USING_SOFT_PARAMS = (1 << 6),
- MASTER_PF = (1 << 7),
- FW_OFLD_CONN = (1 << 9),
- ROOT_NO_RELAXED_ORDERING = (1 << 10),
- SHUTTING_DOWN = (1 << 11),
+ CXGB4_FULL_INIT_DONE = (1 << 0),
+ CXGB4_DEV_ENABLED = (1 << 1),
+ CXGB4_USING_MSI = (1 << 2),
+ CXGB4_USING_MSIX = (1 << 3),
+ CXGB4_FW_OK = (1 << 4),
+ CXGB4_RSS_TNLALLLOOKUP = (1 << 5),
+ CXGB4_USING_SOFT_PARAMS = (1 << 6),
+ CXGB4_MASTER_PF = (1 << 7),
+ CXGB4_FW_OFLD_CONN = (1 << 9),
+ CXGB4_ROOT_NO_RELAXED_ORDERING = (1 << 10),
+ CXGB4_SHUTTING_DOWN = (1 << 11),
+ CXGB4_SGE_DBQ_TIMER = (1 << 12),
};
enum {
@@ -756,6 +757,8 @@ struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
#ifdef CONFIG_CHELSIO_T4_DCB
u8 dcb_prio; /* DCB Priority bound to queue */
#endif
+ u8 dbqt; /* SGE Doorbell Queue Timer in use */
+ unsigned int dbqtimerix; /* SGE Doorbell Queue Timer Index */
unsigned long tso; /* # of TSO requests */
unsigned long tx_cso; /* # of Tx checksum offloads */
unsigned long vlan_ins; /* # of Tx VLAN insertions */
@@ -816,6 +819,8 @@ struct sge {
u16 nqs_per_uld; /* # of Rx queues per ULD */
u16 timer_val[SGE_NTIMERS];
u8 counter_val[SGE_NCOUNTERS];
+ u16 dbqtimer_tick;
+ u16 dbqtimer_val[SGE_NDBQTIMERS];
u32 fl_pg_order; /* large page allocation size */
u32 stat_len; /* length of status page at ring end */
u32 pktshift; /* padding between CPL & packet data */
@@ -860,6 +865,7 @@ struct doorbell_stats {
struct hash_mac_addr {
struct list_head list;
u8 addr[ETH_ALEN];
+ unsigned int iface_mac;
};
struct uld_msix_bmap {
@@ -879,6 +885,7 @@ struct vf_info {
unsigned int tx_rate;
bool pf_set_mac;
u16 vlan;
+ int link_state;
};
enum {
@@ -1401,7 +1408,7 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
rspq_flush_handler_t flush_handler, int cong);
int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
struct net_device *dev, struct netdev_queue *netdevq,
- unsigned int iqid);
+ unsigned int iqid, u8 dbqt);
int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
struct net_device *dev, unsigned int iqid,
unsigned int cmplqid);
@@ -1414,6 +1421,8 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
int t4_sge_init(struct adapter *adap);
void t4_sge_start(struct adapter *adap);
void t4_sge_stop(struct adapter *adap);
+int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *q,
+ int maxreclaim);
void cxgb4_set_ethtool_ops(struct net_device *netdev);
int cxgb4_write_rss(const struct port_info *pi, const u16 *queues);
enum cpl_tx_tnl_lso_type cxgb_encap_offload_supported(struct sk_buff *skb);
@@ -1820,6 +1829,8 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int eqid);
int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type);
+int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers,
+ u16 *dbqtimers);
void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl);
int t4_update_port_info(struct port_info *pi);
int t4_get_link_params(struct port_info *pi, unsigned int *link_okp,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index b0ff9fa183f4..3130b43bba52 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -3143,7 +3143,7 @@ static int tid_info_show(struct seq_file *seq, void *v)
seq_printf(seq, ", in use: %u/%u\n",
atomic_read(&t->tids_in_use),
atomic_read(&t->hash_tids_in_use));
- } else if (adap->flags & FW_OFLD_CONN) {
+ } else if (adap->flags & CXGB4_FW_OFLD_CONN) {
seq_printf(seq, "TID range: %u..%u/%u..%u",
t->aftid_base,
t->aftid_end,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
index d07230c892a5..bec4711005cc 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
@@ -446,8 +446,10 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
unsigned long *link_mode_mask)
{
#define SET_LMM(__lmm_name) \
- __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
- link_mode_mask)
+ do { \
+ __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
+ link_mode_mask); \
+ } while (0)
#define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \
do { \
@@ -541,7 +543,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
case FW_PORT_TYPE_CR4_QSFP:
SET_LMM(FIBRE);
FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
- FW_CAPS_TO_LMM(SPEED_10G, 10000baseSR_Full);
+ FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
@@ -552,6 +554,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
break;
}
+ if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) {
+ FW_CAPS_TO_LMM(FEC_RS, FEC_RS);
+ FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER);
+ } else {
+ SET_LMM(FEC_NONE);
+ }
+
FW_CAPS_TO_LMM(ANEG, Autoneg);
FW_CAPS_TO_LMM(802_3_PAUSE, Pause);
FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause);
@@ -679,18 +688,15 @@ static int set_link_ksettings(struct net_device *dev,
base->autoneg == AUTONEG_DISABLE) {
fw_caps = speed_to_fw_caps(base->speed);
- /* Must only specify a single speed which must be supported
- * as part of the Physical Port Capabilities.
- */
- if ((fw_caps & (fw_caps - 1)) != 0 ||
- !(lc->pcaps & fw_caps))
+ /* Speed must be supported by Physical Port Capabilities. */
+ if (!(lc->pcaps & fw_caps))
return -EINVAL;
lc->speed_caps = fw_caps;
lc->acaps = fw_caps;
} else {
fw_caps =
- lmm_to_fw_caps(link_ksettings->link_modes.advertising);
+ lmm_to_fw_caps(link_ksettings->link_modes.advertising);
if (!(lc->pcaps & fw_caps))
return -EINVAL;
lc->speed_caps = 0;
@@ -869,7 +875,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
e->rx_pending < MIN_FL_ENTRIES || e->tx_pending < MIN_TXQ_ENTRIES)
return -EINVAL;
- if (adapter->flags & FULL_INIT_DONE)
+ if (adapter->flags & CXGB4_FULL_INIT_DONE)
return -EBUSY;
for (i = 0; i < pi->nqsets; ++i) {
@@ -926,11 +932,190 @@ static int get_adaptive_rx_setting(struct net_device *dev)
return q->rspq.adaptive_rx;
}
-static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+/* Return the current global Adapter SGE Doorbell Queue Timer Tick for all
+ * Ethernet TX Queues.
+ */
+static int get_dbqtimer_tick(struct net_device *dev)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+
+ if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
+ return 0;
+
+ return adap->sge.dbqtimer_tick;
+}
+
+/* Return the SGE Doorbell Queue Timer Value for the Ethernet TX Queues
+ * associated with a Network Device.
+ */
+static int get_dbqtimer(struct net_device *dev)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ struct sge_eth_txq *txq;
+
+ txq = &adap->sge.ethtxq[pi->first_qset];
+
+ if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
+ return 0;
+
+ /* all of the TX Queues use the same Timer Index */
+ return adap->sge.dbqtimer_val[txq->dbqtimerix];
+}
+
+/* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX
+ * Queues. This is the fundamental "Tick" that sets the scale of values which
+ * can be used. Individual Ethernet TX Queues index into a relatively small
+ * array of Tick Multipliers. Changing the base Tick will thus change all of
+ * the resulting Timer Values associated with those multipliers for all
+ * Ethernet TX Queues.
+ */
+static int set_dbqtimer_tick(struct net_device *dev, int usecs)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ struct sge *s = &adap->sge;
+ u32 param, val;
+ int ret;
+
+ if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
+ return 0;
+
+ /* return early if it's the same Timer Tick we're already using */
+ if (s->dbqtimer_tick == usecs)
+ return 0;
+
+ /* attempt to set the new Timer Tick value */
+ param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK));
+ val = usecs;
+ ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param, &val);
+ if (ret)
+ return ret;
+ s->dbqtimer_tick = usecs;
+
+ /* if successful, reread resulting dependent Timer values */
+ ret = t4_read_sge_dbqtimers(adap, ARRAY_SIZE(s->dbqtimer_val),
+ s->dbqtimer_val);
+ return ret;
+}
+
+/* Set the SGE Doorbell Queue Timer Value for the Ethernet TX Queues
+ * associated with a Network Device. There is a relatively small array of
+ * possible Timer Values so we need to pick the closest value available.
+ */
+static int set_dbqtimer(struct net_device *dev, int usecs)
+{
+ int qix, timerix, min_timerix, delta, min_delta;
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ struct sge *s = &adap->sge;
+ struct sge_eth_txq *txq;
+ u32 param, val;
+ int ret;
+
+ if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
+ return 0;
+
+ /* Find the SGE Doorbell Timer Value that's closest to the requested
+ * value.
+ */
+ min_delta = INT_MAX;
+ min_timerix = 0;
+ for (timerix = 0; timerix < ARRAY_SIZE(s->dbqtimer_val); timerix++) {
+ delta = s->dbqtimer_val[timerix] - usecs;
+ if (delta < 0)
+ delta = -delta;
+ if (delta < min_delta) {
+ min_delta = delta;
+ min_timerix = timerix;
+ }
+ }
+
+ /* Return early if it's the same Timer Index we're already using.
+ * We use the same Timer Index for all of the TX Queues for an
+ * interface so it's only necessary to check the first one.
+ */
+ txq = &s->ethtxq[pi->first_qset];
+ if (txq->dbqtimerix == min_timerix)
+ return 0;
+
+ for (qix = 0; qix < pi->nqsets; qix++, txq++) {
+ if (adap->flags & CXGB4_FULL_INIT_DONE) {
+ param =
+ (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX) |
+ FW_PARAMS_PARAM_YZ_V(txq->q.cntxt_id));
+ val = min_timerix;
+ ret = t4_set_params(adap, adap->mbox, adap->pf, 0,
+ 1, &param, &val);
+ if (ret)
+ return ret;
+ }
+ txq->dbqtimerix = min_timerix;
+ }
+ return 0;
+}
+
+/* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX
+ * Queues and the Timer Value for the Ethernet TX Queues associated with a
+ * Network Device. Since changing the global Tick changes all of the
+ * available Timer Values, we need to do this first before selecting the
+ * resulting closest Timer Value. Moreover, since the Tick is global,
+ * changing it affects the Timer Values for all Network Devices on the
+ * adapter. So, before changing the Tick, we grab all of the current Timer
+ * Values for other Network Devices on this Adapter and then attempt to select
+ * new Timer Values which are close to the old values ...
+ */
+static int set_dbqtimer_tickval(struct net_device *dev,
+ int tick_usecs, int timer_usecs)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ int timer[MAX_NPORTS];
+ unsigned int port;
+ int ret;
+
+ /* Grab the other adapter Network Interface current timers and fill in
+ * the new one for this Network Interface.
+ */
+ for_each_port(adap, port)
+ if (port == pi->port_id)
+ timer[port] = timer_usecs;
+ else
+ timer[port] = get_dbqtimer(adap->port[port]);
+
+ /* Change the global Tick first ... */
+ ret = set_dbqtimer_tick(dev, tick_usecs);
+ if (ret)
+ return ret;
+
+ /* ... and then set all of the Network Interface Timer Values ... */
+ for_each_port(adap, port) {
+ ret = set_dbqtimer(adap->port[port], timer[port]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coalesce)
{
- set_adaptive_rx_setting(dev, c->use_adaptive_rx_coalesce);
- return set_rx_intr_params(dev, c->rx_coalesce_usecs,
- c->rx_max_coalesced_frames);
+ int ret;
+
+ set_adaptive_rx_setting(dev, coalesce->use_adaptive_rx_coalesce);
+
+ ret = set_rx_intr_params(dev, coalesce->rx_coalesce_usecs,
+ coalesce->rx_max_coalesced_frames);
+ if (ret)
+ return ret;
+
+ return set_dbqtimer_tickval(dev,
+ coalesce->tx_coalesce_usecs_irq,
+ coalesce->tx_coalesce_usecs);
}
static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
@@ -943,6 +1128,8 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
c->rx_max_coalesced_frames = (rq->intr_params & QINTR_CNT_EN_F) ?
adap->sge.counter_val[rq->pktcnt_idx] : 0;
c->use_adaptive_rx_coalesce = get_adaptive_rx_setting(dev);
+ c->tx_coalesce_usecs_irq = get_dbqtimer_tick(dev);
+ c->tx_coalesce_usecs = get_dbqtimer(dev);
return 0;
}
@@ -1076,7 +1263,7 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
* firmware image otherwise we'll try to do the entire job from the
* host ... and we always "force" the operation in this path.
*/
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
mbox = adap->mbox;
ret = t4_fw_upgrade(adap, mbox, fw->data, fw->size, 1);
@@ -1155,7 +1342,7 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
return 0;
/* Interface must be brought up atleast once */
- if (pi->adapter->flags & FULL_INIT_DONE) {
+ if (pi->adapter->flags & CXGB4_FULL_INIT_DONE) {
for (i = 0; i < pi->rss_size; i++)
pi->rss[i] = p[i];
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
index 6c8a62eefe51..33b2c0c45509 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
@@ -74,7 +74,7 @@ int cxgb_fcoe_enable(struct net_device *netdev)
if (is_t4(adap->params.chip))
return -EINVAL;
- if (!(adap->flags & FULL_INIT_DONE))
+ if (!(adap->flags & CXGB4_FULL_INIT_DONE))
return -EINVAL;
dev_info(adap->pdev_dev, "Enabling FCoE offload features\n");
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
index 7dddb9e748b8..5afb43000049 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -524,7 +524,7 @@ static int del_filter_wr(struct adapter *adapter, int fidx)
return -ENOMEM;
fwr = __skb_put(skb, len);
- t4_mk_filtdelwr(f->tid, fwr, (adapter->flags & SHUTTING_DOWN) ? -1
+ t4_mk_filtdelwr(f->tid, fwr, (adapter->flags & CXGB4_SHUTTING_DOWN) ? -1
: adapter->sge.fw_evtq.abs_id);
/* Mark the filter as "pending" and ship off the Filter Work Request.
@@ -1569,7 +1569,7 @@ int cxgb4_del_filter(struct net_device *dev, int filter_id,
int ret;
/* If we are shutting down the adapter do not wait for completion */
- if (netdev2adap(dev)->flags & SHUTTING_DOWN)
+ if (netdev2adap(dev)->flags & CXGB4_SHUTTING_DOWN)
return __cxgb4_del_filter(dev, filter_id, fs, NULL);
init_completion(&ctx.completion);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 6ba9099ca7fe..89179e316687 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -433,6 +433,60 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
}
/**
+ * cxgb4_change_mac - Update match filter for a MAC address.
+ * @pi: the port_info
+ * @viid: the VI id
+ * @tcam_idx: TCAM index of existing filter for old value of MAC address,
+ * or -1
+ * @addr: the new MAC address value
+ * @persist: whether a new MAC allocation should be persistent
+ * @add_smt: if true also add the address to the HW SMT
+ *
+ * Modifies an MPS filter and sets it to the new MAC address if
+ * @tcam_idx >= 0, or adds the MAC address to a new filter if
+ * @tcam_idx < 0. In the latter case the address is added persistently
+ * if @persist is %true.
+ * Addresses are programmed to hash region, if tcam runs out of entries.
+ *
+ */
+static int cxgb4_change_mac(struct port_info *pi, unsigned int viid,
+ int *tcam_idx, const u8 *addr, bool persist,
+ u8 *smt_idx)
+{
+ struct adapter *adapter = pi->adapter;
+ struct hash_mac_addr *entry, *new_entry;
+ int ret;
+
+ ret = t4_change_mac(adapter, adapter->mbox, viid,
+ *tcam_idx, addr, persist, smt_idx);
+ /* We ran out of TCAM entries. try programming hash region. */
+ if (ret == -ENOMEM) {
+ /* If the MAC address to be updated is in the hash addr
+ * list, update it from the list
+ */
+ list_for_each_entry(entry, &adapter->mac_hlist, list) {
+ if (entry->iface_mac) {
+ ether_addr_copy(entry->addr, addr);
+ goto set_hash;
+ }
+ }
+ new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+ if (!new_entry)
+ return -ENOMEM;
+ ether_addr_copy(new_entry->addr, addr);
+ new_entry->iface_mac = true;
+ list_add_tail(&new_entry->list, &adapter->mac_hlist);
+set_hash:
+ ret = cxgb4_set_addr_hash(pi);
+ } else if (ret >= 0) {
+ *tcam_idx = ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
* link_start - enable a port
* @dev: the port to enable
*
@@ -450,15 +504,9 @@ static int link_start(struct net_device *dev)
*/
ret = t4_set_rxmode(pi->adapter, mb, pi->viid, dev->mtu, -1, -1, -1,
!!(dev->features & NETIF_F_HW_VLAN_CTAG_RX), true);
- if (ret == 0) {
- ret = t4_change_mac(pi->adapter, mb, pi->viid,
- pi->xact_addr_filt, dev->dev_addr, true,
- &pi->smt_idx);
- if (ret >= 0) {
- pi->xact_addr_filt = ret;
- ret = 0;
- }
- }
+ if (ret == 0)
+ ret = cxgb4_change_mac(pi, pi->viid, &pi->xact_addr_filt,
+ dev->dev_addr, true, &pi->smt_idx);
if (ret == 0)
ret = t4_link_l1cfg(pi->adapter, mb, pi->tx_chan,
&pi->link_cfg);
@@ -527,7 +575,7 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
struct sge_eth_txq *eq;
eq = container_of(txq, struct sge_eth_txq, q);
- netif_tx_wake_queue(eq->txq);
+ t4_sge_eth_txq_egress_update(q->adap, eq, -1);
} else {
struct sge_uld_txq *oq;
@@ -603,12 +651,12 @@ out:
static void disable_msi(struct adapter *adapter)
{
- if (adapter->flags & USING_MSIX) {
+ if (adapter->flags & CXGB4_USING_MSIX) {
pci_disable_msix(adapter->pdev);
- adapter->flags &= ~USING_MSIX;
- } else if (adapter->flags & USING_MSI) {
+ adapter->flags &= ~CXGB4_USING_MSIX;
+ } else if (adapter->flags & CXGB4_USING_MSI) {
pci_disable_msi(adapter->pdev);
- adapter->flags &= ~USING_MSI;
+ adapter->flags &= ~CXGB4_USING_MSI;
}
}
@@ -624,7 +672,7 @@ static irqreturn_t t4_nondata_intr(int irq, void *cookie)
adap->swintr = 1;
t4_write_reg(adap, MYPF_REG(PL_PF_INT_CAUSE_A), v);
}
- if (adap->flags & MASTER_PF)
+ if (adap->flags & CXGB4_MASTER_PF)
t4_slow_intr_handler(adap);
return IRQ_HANDLED;
}
@@ -789,9 +837,9 @@ static void quiesce_rx(struct adapter *adap)
/* Disable interrupt and napi handler */
static void disable_interrupts(struct adapter *adap)
{
- if (adap->flags & FULL_INIT_DONE) {
+ if (adap->flags & CXGB4_FULL_INIT_DONE) {
t4_intr_disable(adap);
- if (adap->flags & USING_MSIX) {
+ if (adap->flags & CXGB4_USING_MSIX) {
free_msix_queue_irqs(adap);
free_irq(adap->msix_info[0].vec, adap);
} else {
@@ -832,7 +880,7 @@ static int setup_fw_sge_queues(struct adapter *adap)
bitmap_zero(s->starving_fl, s->egr_sz);
bitmap_zero(s->txq_maperr, s->egr_sz);
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
adap->msi_idx = 1; /* vector 0 is for non-queue interrupts */
else {
err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
@@ -885,10 +933,13 @@ static int setup_sge_queues(struct adapter *adap)
q->rspq.idx = j;
memset(&q->stats, 0, sizeof(q->stats));
}
- for (j = 0; j < pi->nqsets; j++, t++) {
+
+ q = &s->ethrxq[pi->first_qset];
+ for (j = 0; j < pi->nqsets; j++, t++, q++) {
err = t4_sge_alloc_eth_txq(adap, t, dev,
netdev_get_tx_queue(dev, j),
- s->fw_evtq.cntxt_id);
+ q->rspq.cntxt_id,
+ !!(adap->flags & CXGB4_SGE_DBQ_TIMER));
if (err)
goto freeout;
}
@@ -910,7 +961,7 @@ static int setup_sge_queues(struct adapter *adap)
if (!is_t4(adap->params.chip)) {
err = t4_sge_alloc_eth_txq(adap, &s->ptptxq, adap->port[0],
netdev_get_tx_queue(adap->port[0], 0)
- , s->fw_evtq.cntxt_id);
+ , s->fw_evtq.cntxt_id, false);
if (err)
goto freeout;
}
@@ -2229,7 +2280,7 @@ static int cxgb_up(struct adapter *adap)
if (err)
goto freeq;
- if (adap->flags & USING_MSIX) {
+ if (adap->flags & CXGB4_USING_MSIX) {
name_msix_vecs(adap);
err = request_irq(adap->msix_info[0].vec, t4_nondata_intr, 0,
adap->msix_info[0].desc, adap);
@@ -2242,7 +2293,8 @@ static int cxgb_up(struct adapter *adap)
}
} else {
err = request_irq(adap->pdev->irq, t4_intr_handler(adap),
- (adap->flags & USING_MSI) ? 0 : IRQF_SHARED,
+ (adap->flags & CXGB4_USING_MSI) ? 0
+ : IRQF_SHARED,
adap->port[0]->name, adap);
if (err)
goto irq_err;
@@ -2251,7 +2303,7 @@ static int cxgb_up(struct adapter *adap)
enable_rx(adap);
t4_sge_start(adap);
t4_intr_enable(adap);
- adap->flags |= FULL_INIT_DONE;
+ adap->flags |= CXGB4_FULL_INIT_DONE;
mutex_unlock(&uld_mutex);
notify_ulds(adap, CXGB4_STATE_UP);
@@ -2280,7 +2332,7 @@ static void cxgb_down(struct adapter *adapter)
t4_sge_stop(adapter);
t4_free_sge_resources(adapter);
- adapter->flags &= ~FULL_INIT_DONE;
+ adapter->flags &= ~CXGB4_FULL_INIT_DONE;
}
/*
@@ -2294,7 +2346,7 @@ static int cxgb_open(struct net_device *dev)
netif_carrier_off(dev);
- if (!(adapter->flags & FULL_INIT_DONE)) {
+ if (!(adapter->flags & CXGB4_FULL_INIT_DONE)) {
err = cxgb_up(adapter);
if (err < 0)
return err;
@@ -2689,6 +2741,7 @@ static int cxgb4_mgmt_get_vf_config(struct net_device *dev,
ivi->min_tx_rate = 0;
ether_addr_copy(ivi->mac, vfinfo->vf_mac_addr);
ivi->vlan = vfinfo->vlan;
+ ivi->linkstate = vfinfo->link_state;
return 0;
}
@@ -2828,6 +2881,49 @@ static int cxgb4_mgmt_set_vf_vlan(struct net_device *dev, int vf,
ret, (vlan ? "setting" : "clearing"), adap->pf, vf);
return ret;
}
+
+static int cxgb4_mgmt_set_vf_link_state(struct net_device *dev, int vf,
+ int link)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ u32 param, val;
+ int ret = 0;
+
+ if (vf >= adap->num_vfs)
+ return -EINVAL;
+
+ switch (link) {
+ case IFLA_VF_LINK_STATE_AUTO:
+ val = FW_VF_LINK_STATE_AUTO;
+ break;
+
+ case IFLA_VF_LINK_STATE_ENABLE:
+ val = FW_VF_LINK_STATE_ENABLE;
+ break;
+
+ case IFLA_VF_LINK_STATE_DISABLE:
+ val = FW_VF_LINK_STATE_DISABLE;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_LINK_STATE));
+ ret = t4_set_params(adap, adap->mbox, adap->pf, vf + 1, 1,
+ &param, &val);
+ if (ret) {
+ dev_err(adap->pdev_dev,
+ "Error %d in setting PF %d VF %d link state\n",
+ ret, adap->pf, vf);
+ return -EINVAL;
+ }
+
+ adap->vfinfo[vf].link_state = link;
+ return ret;
+}
#endif /* CONFIG_PCI_IOV */
static int cxgb_set_mac_addr(struct net_device *dev, void *p)
@@ -2839,9 +2935,8 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- ret = t4_change_mac(pi->adapter, pi->adapter->pf, pi->viid,
- pi->xact_addr_filt, addr->sa_data, true,
- &pi->smt_idx);
+ ret = cxgb4_change_mac(pi, pi->viid, &pi->xact_addr_filt,
+ addr->sa_data, true, &pi->smt_idx);
if (ret < 0)
return ret;
@@ -2856,7 +2951,7 @@ static void cxgb_netpoll(struct net_device *dev)
struct port_info *pi = netdev_priv(dev);
struct adapter *adap = pi->adapter;
- if (adap->flags & USING_MSIX) {
+ if (adap->flags & CXGB4_USING_MSIX) {
int i;
struct sge_eth_rxq *rx = &adap->sge.ethrxq[pi->first_qset];
@@ -2883,7 +2978,7 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
if (index < 0 || index > pi->nqsets - 1)
return -EINVAL;
- if (!(adap->flags & FULL_INIT_DONE)) {
+ if (!(adap->flags & CXGB4_FULL_INIT_DONE)) {
dev_err(adap->pdev_dev,
"Failed to rate limit on queue %d. Link Down?\n",
index);
@@ -2984,7 +3079,7 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
- if (!(adap->flags & FULL_INIT_DONE)) {
+ if (!(adap->flags & CXGB4_FULL_INIT_DONE)) {
dev_err(adap->pdev_dev,
"Failed to setup tc on port %d. Link Down?\n",
pi->port_id);
@@ -3244,12 +3339,13 @@ static const struct net_device_ops cxgb4_netdev_ops = {
#ifdef CONFIG_PCI_IOV
static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
- .ndo_open = cxgb4_mgmt_open,
- .ndo_set_vf_mac = cxgb4_mgmt_set_vf_mac,
- .ndo_get_vf_config = cxgb4_mgmt_get_vf_config,
- .ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate,
- .ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id,
- .ndo_set_vf_vlan = cxgb4_mgmt_set_vf_vlan,
+ .ndo_open = cxgb4_mgmt_open,
+ .ndo_set_vf_mac = cxgb4_mgmt_set_vf_mac,
+ .ndo_get_vf_config = cxgb4_mgmt_get_vf_config,
+ .ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate,
+ .ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id,
+ .ndo_set_vf_vlan = cxgb4_mgmt_set_vf_vlan,
+ .ndo_set_vf_link_state = cxgb4_mgmt_set_vf_link_state,
};
#endif
@@ -4115,7 +4211,7 @@ static int adap_init0(struct adapter *adap)
return ret;
}
if (ret == adap->mbox)
- adap->flags |= MASTER_PF;
+ adap->flags |= CXGB4_MASTER_PF;
/*
* If we're the Master PF Driver and the device is uninitialized,
@@ -4130,7 +4226,7 @@ static int adap_init0(struct adapter *adap)
/* If firmware is too old (not supported by driver) force an update. */
if (ret)
state = DEV_STATE_UNINIT;
- if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
+ if ((adap->flags & CXGB4_MASTER_PF) && state != DEV_STATE_INIT) {
struct fw_info *fw_info;
struct fw_hdr *card_fw;
const struct firmware *fw;
@@ -4192,7 +4288,7 @@ static int adap_init0(struct adapter *adap)
ret);
dev_info(adap->pdev_dev, "Coming up as %s: "\
"Adapter already initialized\n",
- adap->flags & MASTER_PF ? "MASTER" : "SLAVE");
+ adap->flags & CXGB4_MASTER_PF ? "MASTER" : "SLAVE");
} else {
dev_info(adap->pdev_dev, "Coming up as MASTER: "\
"Initializing adapter\n");
@@ -4278,6 +4374,24 @@ static int adap_init0(struct adapter *adap)
if (ret < 0)
goto bye;
+ /* Grab the SGE Doorbell Queue Timer values. If successful, that
+ * indicates that the Firmware and Hardware support this.
+ */
+ params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK));
+ ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
+ 1, params, val);
+
+ if (!ret) {
+ adap->sge.dbqtimer_tick = val[0];
+ ret = t4_read_sge_dbqtimers(adap,
+ ARRAY_SIZE(adap->sge.dbqtimer_val),
+ adap->sge.dbqtimer_val);
+ }
+
+ if (!ret)
+ adap->flags |= CXGB4_SGE_DBQ_TIMER;
+
if (is_bypass_device(adap->pdev->device))
adap->params.bypass = 1;
@@ -4400,7 +4514,7 @@ static int adap_init0(struct adapter *adap)
* offload connection through firmware work request
*/
if ((val[0] != val[1]) && (ret >= 0)) {
- adap->flags |= FW_OFLD_CONN;
+ adap->flags |= CXGB4_FW_OFLD_CONN;
adap->tids.aftid_base = val[0];
adap->tids.aftid_end = val[1];
}
@@ -4493,7 +4607,7 @@ static int adap_init0(struct adapter *adap)
* 2. Server filter: This are special filters which are used
* to redirect SYN packets to offload queue.
*/
- if (adap->flags & FW_OFLD_CONN && !is_bypass(adap)) {
+ if (adap->flags & CXGB4_FW_OFLD_CONN && !is_bypass(adap)) {
adap->tids.sftid_base = adap->tids.ftid_base +
DIV_ROUND_UP(adap->tids.nftids, 3);
adap->tids.nsftids = adap->tids.nftids -
@@ -4672,7 +4786,7 @@ static int adap_init0(struct adapter *adap)
adap->params.b_wnd);
}
t4_init_sge_params(adap);
- adap->flags |= FW_OK;
+ adap->flags |= CXGB4_FW_OK;
t4_init_tp_params(adap, true);
return 0;
@@ -4707,7 +4821,7 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
goto out;
rtnl_lock();
- adap->flags &= ~FW_OK;
+ adap->flags &= ~CXGB4_FW_OK;
notify_ulds(adap, CXGB4_STATE_START_RECOVERY);
spin_lock(&adap->stats_lock);
for_each_port(adap, i) {
@@ -4719,12 +4833,12 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
}
spin_unlock(&adap->stats_lock);
disable_interrupts(adap);
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
cxgb_down(adap);
rtnl_unlock();
- if ((adap->flags & DEV_ENABLED)) {
+ if ((adap->flags & CXGB4_DEV_ENABLED)) {
pci_disable_device(pdev);
- adap->flags &= ~DEV_ENABLED;
+ adap->flags &= ~CXGB4_DEV_ENABLED;
}
out: return state == pci_channel_io_perm_failure ?
PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
@@ -4742,13 +4856,13 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
return PCI_ERS_RESULT_RECOVERED;
}
- if (!(adap->flags & DEV_ENABLED)) {
+ if (!(adap->flags & CXGB4_DEV_ENABLED)) {
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev, "Cannot reenable PCI "
"device after reset\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- adap->flags |= DEV_ENABLED;
+ adap->flags |= CXGB4_DEV_ENABLED;
}
pci_set_master(pdev);
@@ -4759,7 +4873,7 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
return PCI_ERS_RESULT_DISCONNECT;
if (t4_fw_hello(adap, adap->mbox, adap->pf, MASTER_MUST, NULL) < 0)
return PCI_ERS_RESULT_DISCONNECT;
- adap->flags |= FW_OK;
+ adap->flags |= CXGB4_FW_OK;
if (adap_init1(adap, &c))
return PCI_ERS_RESULT_DISCONNECT;
@@ -4871,7 +4985,7 @@ static int cfg_queues(struct adapter *adap)
* at all is problematic ...
*/
niqflint = adap->params.pfres.niqflint - 1;
- if (!(adap->flags & USING_MSIX))
+ if (!(adap->flags & CXGB4_USING_MSIX))
niqflint--;
neq = adap->params.pfres.neq / 2;
avail_eth_qsets = min(niqflint, neq);
@@ -5153,8 +5267,8 @@ static void print_adapter_info(struct adapter *adapter)
/* Software/Hardware configuration */
dev_info(adapter->pdev_dev, "Configuration: %sNIC %s, %s capable\n",
is_offload(adapter) ? "R" : "",
- ((adapter->flags & USING_MSIX) ? "MSI-X" :
- (adapter->flags & USING_MSI) ? "MSI" : ""),
+ ((adapter->flags & CXGB4_USING_MSIX) ? "MSI-X" :
+ (adapter->flags & CXGB4_USING_MSI) ? "MSI" : ""),
is_offload(adapter) ? "Offload" : "non-Offload");
}
@@ -5229,13 +5343,13 @@ static void free_some_resources(struct adapter *adapter)
kfree(adap2pinfo(adapter, i)->rss);
free_netdev(adapter->port[i]);
}
- if (adapter->flags & FW_OK)
+ if (adapter->flags & CXGB4_FW_OK)
t4_fw_bye(adapter, adapter->pf);
}
#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
- NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+ NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
#define SEGMENT_SIZE 128
static int t4_get_chip_type(struct adapter *adap, int ver)
@@ -5533,7 +5647,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* PCI device has been enabled */
- adapter->flags |= DEV_ENABLED;
+ adapter->flags |= CXGB4_DEV_ENABLED;
memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
/* If possible, we use PCIe Relaxed Ordering Attribute to deliver
@@ -5551,7 +5665,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* using Relaxed Ordering.
*/
if (!pcie_relaxed_ordering_enabled(pdev))
- adapter->flags |= ROOT_NO_RELAXED_ORDERING;
+ adapter->flags |= CXGB4_ROOT_NO_RELAXED_ORDERING;
spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->tid_release_lock);
@@ -5642,7 +5756,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_RXCSUM | NETIF_F_RXHASH |
+ NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_GRO |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_TC;
@@ -5651,9 +5765,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_IPV6_CSUM |
NETIF_F_RXCSUM |
NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
- netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+ netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_HW_TLS_RECORD;
}
if (highdma)
@@ -5680,7 +5797,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, adapter);
- if (adapter->flags & FW_OK) {
+ if (adapter->flags & CXGB4_FW_OK) {
err = t4_port_init(adapter, func, func, 0);
if (err)
goto out_free_dev;
@@ -5702,7 +5819,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
- if (!(adapter->flags & FW_OK))
+ if (!(adapter->flags & CXGB4_FW_OK))
goto fw_attach_fail;
/* Configure queues and allocate tables now, they can be needed as
@@ -5796,9 +5913,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* See what interrupts we'll be using */
if (msi > 1 && enable_msix(adapter) == 0)
- adapter->flags |= USING_MSIX;
+ adapter->flags |= CXGB4_USING_MSIX;
else if (msi > 0 && pci_enable_msi(pdev) == 0) {
- adapter->flags |= USING_MSI;
+ adapter->flags |= CXGB4_USING_MSI;
if (msi > 1)
free_msix_info(adapter);
}
@@ -5866,7 +5983,7 @@ fw_attach_fail:
cxgb4_ptp_init(adapter);
if (IS_REACHABLE(CONFIG_THERMAL) &&
- !is_t4(adapter->params.chip) && (adapter->flags & FW_OK))
+ !is_t4(adapter->params.chip) && (adapter->flags & CXGB4_FW_OK))
cxgb4_thermal_init(adapter);
print_adapter_info(adapter);
@@ -5875,7 +5992,7 @@ fw_attach_fail:
out_free_dev:
t4_free_sge_resources(adapter);
free_some_resources(adapter);
- if (adapter->flags & USING_MSIX)
+ if (adapter->flags & CXGB4_USING_MSIX)
free_msix_info(adapter);
if (adapter->num_uld || adapter->num_ofld_uld)
t4_uld_mem_free(adapter);
@@ -5908,7 +6025,7 @@ static void remove_one(struct pci_dev *pdev)
return;
}
- adapter->flags |= SHUTTING_DOWN;
+ adapter->flags |= CXGB4_SHUTTING_DOWN;
if (adapter->pf == 4) {
int i;
@@ -5943,10 +6060,10 @@ static void remove_one(struct pci_dev *pdev)
*/
clear_all_filters(adapter);
- if (adapter->flags & FULL_INIT_DONE)
+ if (adapter->flags & CXGB4_FULL_INIT_DONE)
cxgb_down(adapter);
- if (adapter->flags & USING_MSIX)
+ if (adapter->flags & CXGB4_USING_MSIX)
free_msix_info(adapter);
if (adapter->num_uld || adapter->num_ofld_uld)
t4_uld_mem_free(adapter);
@@ -5970,9 +6087,9 @@ static void remove_one(struct pci_dev *pdev)
#endif
iounmap(adapter->regs);
pci_disable_pcie_error_reporting(pdev);
- if ((adapter->flags & DEV_ENABLED)) {
+ if ((adapter->flags & CXGB4_DEV_ENABLED)) {
pci_disable_device(pdev);
- adapter->flags &= ~DEV_ENABLED;
+ adapter->flags &= ~CXGB4_DEV_ENABLED;
}
pci_release_regions(pdev);
kfree(adapter->mbox_log);
@@ -5998,7 +6115,7 @@ static void shutdown_one(struct pci_dev *pdev)
return;
}
- adapter->flags |= SHUTTING_DOWN;
+ adapter->flags |= CXGB4_SHUTTING_DOWN;
if (adapter->pf == 4) {
int i;
@@ -6016,7 +6133,7 @@ static void shutdown_one(struct pci_dev *pdev)
disable_msi(adapter);
t4_sge_stop(adapter);
- if (adapter->flags & FW_OK)
+ if (adapter->flags & CXGB4_FW_OK)
t4_fw_bye(adapter, adapter->mbox);
}
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
index 9f9d6cae39d5..58a039c3224a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
@@ -378,10 +378,10 @@ static void cxgb4_init_ptp_timer(struct adapter *adapter)
int err;
memset(&c, 0, sizeof(c));
- c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
- FW_CMD_REQUEST_F |
- FW_CMD_WRITE_F |
- FW_PTP_CMD_PORTID_V(0));
+ c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
+ FW_CMD_REQUEST_F |
+ FW_CMD_WRITE_F |
+ FW_PTP_CMD_PORTID_V(0));
c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
c.u.scmd.sc = FW_PTP_SC_INIT_TIMER;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index c116f96956fe..82a8d1970060 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -83,28 +83,23 @@ static void cxgb4_process_flow_match(struct net_device *dev,
struct tc_cls_flower_offload *cls,
struct ch_filter_specification *fs)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls);
u16 addr_type = 0;
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- cls->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
- addr_type = key->addr_type;
+ flow_rule_match_control(rule, &match);
+ addr_type = match.key->addr_type;
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- cls->key);
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- cls->mask);
- u16 ethtype_key = ntohs(key->n_proto);
- u16 ethtype_mask = ntohs(mask->n_proto);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
+ u16 ethtype_key, ethtype_mask;
+
+ flow_rule_match_basic(rule, &match);
+ ethtype_key = ntohs(match.key->n_proto);
+ ethtype_mask = ntohs(match.mask->n_proto);
if (ethtype_key == ETH_P_ALL) {
ethtype_key = 0;
@@ -116,115 +111,89 @@ static void cxgb4_process_flow_match(struct net_device *dev,
fs->val.ethtype = ethtype_key;
fs->mask.ethtype = ethtype_mask;
- fs->val.proto = key->ip_proto;
- fs->mask.proto = mask->ip_proto;
+ fs->val.proto = match.key->ip_proto;
+ fs->mask.proto = match.mask->ip_proto;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- cls->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- cls->mask);
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_ipv4_addrs(rule, &match);
fs->type = 0;
- memcpy(&fs->val.lip[0], &key->dst, sizeof(key->dst));
- memcpy(&fs->val.fip[0], &key->src, sizeof(key->src));
- memcpy(&fs->mask.lip[0], &mask->dst, sizeof(mask->dst));
- memcpy(&fs->mask.fip[0], &mask->src, sizeof(mask->src));
+ memcpy(&fs->val.lip[0], &match.key->dst, sizeof(match.key->dst));
+ memcpy(&fs->val.fip[0], &match.key->src, sizeof(match.key->src));
+ memcpy(&fs->mask.lip[0], &match.mask->dst, sizeof(match.mask->dst));
+ memcpy(&fs->mask.fip[0], &match.mask->src, sizeof(match.mask->src));
/* also initialize nat_lip/fip to same values */
- memcpy(&fs->nat_lip[0], &key->dst, sizeof(key->dst));
- memcpy(&fs->nat_fip[0], &key->src, sizeof(key->src));
-
+ memcpy(&fs->nat_lip[0], &match.key->dst, sizeof(match.key->dst));
+ memcpy(&fs->nat_fip[0], &match.key->src, sizeof(match.key->src));
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- cls->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- cls->mask);
+ struct flow_match_ipv6_addrs match;
+ flow_rule_match_ipv6_addrs(rule, &match);
fs->type = 1;
- memcpy(&fs->val.lip[0], key->dst.s6_addr, sizeof(key->dst));
- memcpy(&fs->val.fip[0], key->src.s6_addr, sizeof(key->src));
- memcpy(&fs->mask.lip[0], mask->dst.s6_addr, sizeof(mask->dst));
- memcpy(&fs->mask.fip[0], mask->src.s6_addr, sizeof(mask->src));
+ memcpy(&fs->val.lip[0], match.key->dst.s6_addr,
+ sizeof(match.key->dst));
+ memcpy(&fs->val.fip[0], match.key->src.s6_addr,
+ sizeof(match.key->src));
+ memcpy(&fs->mask.lip[0], match.mask->dst.s6_addr,
+ sizeof(match.mask->dst));
+ memcpy(&fs->mask.fip[0], match.mask->src.s6_addr,
+ sizeof(match.mask->src));
/* also initialize nat_lip/fip to same values */
- memcpy(&fs->nat_lip[0], key->dst.s6_addr, sizeof(key->dst));
- memcpy(&fs->nat_fip[0], key->src.s6_addr, sizeof(key->src));
+ memcpy(&fs->nat_lip[0], match.key->dst.s6_addr,
+ sizeof(match.key->dst));
+ memcpy(&fs->nat_fip[0], match.key->src.s6_addr,
+ sizeof(match.key->src));
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key, *mask;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
- key = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- cls->key);
- mask = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- cls->mask);
- fs->val.lport = cpu_to_be16(key->dst);
- fs->mask.lport = cpu_to_be16(mask->dst);
- fs->val.fport = cpu_to_be16(key->src);
- fs->mask.fport = cpu_to_be16(mask->src);
+ flow_rule_match_ports(rule, &match);
+ fs->val.lport = cpu_to_be16(match.key->dst);
+ fs->mask.lport = cpu_to_be16(match.mask->dst);
+ fs->val.fport = cpu_to_be16(match.key->src);
+ fs->mask.fport = cpu_to_be16(match.mask->src);
/* also initialize nat_lport/fport to same values */
- fs->nat_lport = cpu_to_be16(key->dst);
- fs->nat_fport = cpu_to_be16(key->src);
+ fs->nat_lport = cpu_to_be16(match.key->dst);
+ fs->nat_fport = cpu_to_be16(match.key->src);
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) {
- struct flow_dissector_key_ip *key, *mask;
-
- key = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IP,
- cls->key);
- mask = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IP,
- cls->mask);
- fs->val.tos = key->tos;
- fs->mask.tos = mask->tos;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
+ struct flow_match_ip match;
+
+ flow_rule_match_ip(rule, &match);
+ fs->val.tos = match.key->tos;
+ fs->mask.tos = match.mask->tos;
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *key, *mask;
-
- key = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- cls->key);
- mask = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- cls->mask);
- fs->val.vni = be32_to_cpu(key->keyid);
- fs->mask.vni = be32_to_cpu(mask->keyid);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid match;
+
+ flow_rule_match_enc_keyid(rule, &match);
+ fs->val.vni = be32_to_cpu(match.key->keyid);
+ fs->mask.vni = be32_to_cpu(match.mask->keyid);
if (fs->mask.vni) {
fs->val.encap_vld = 1;
fs->mask.encap_vld = 1;
}
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key, *mask;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
u16 vlan_tci, vlan_tci_mask;
- key = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- cls->key);
- mask = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- cls->mask);
- vlan_tci = key->vlan_id | (key->vlan_priority <<
- VLAN_PRIO_SHIFT);
- vlan_tci_mask = mask->vlan_id | (mask->vlan_priority <<
- VLAN_PRIO_SHIFT);
+ flow_rule_match_vlan(rule, &match);
+ vlan_tci = match.key->vlan_id | (match.key->vlan_priority <<
+ VLAN_PRIO_SHIFT);
+ vlan_tci_mask = match.mask->vlan_id | (match.mask->vlan_priority <<
+ VLAN_PRIO_SHIFT);
fs->val.ivlan = vlan_tci;
fs->mask.ivlan = vlan_tci_mask;
@@ -255,10 +224,12 @@ static void cxgb4_process_flow_match(struct net_device *dev,
static int cxgb4_validate_flow_match(struct net_device *dev,
struct tc_cls_flower_offload *cls)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls);
+ struct flow_dissector *dissector = rule->match.dissector;
u16 ethtype_mask = 0;
u16 ethtype_key = 0;
- if (cls->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
@@ -268,36 +239,29 @@ static int cxgb4_validate_flow_match(struct net_device *dev,
BIT(FLOW_DISSECTOR_KEY_VLAN) |
BIT(FLOW_DISSECTOR_KEY_IP))) {
netdev_warn(dev, "Unsupported key used: 0x%x\n",
- cls->dissector->used_keys);
+ dissector->used_keys);
return -EOPNOTSUPP;
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- cls->key);
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- cls->mask);
- ethtype_key = ntohs(key->n_proto);
- ethtype_mask = ntohs(mask->n_proto);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
+
+ flow_rule_match_basic(rule, &match);
+ ethtype_key = ntohs(match.key->n_proto);
+ ethtype_mask = ntohs(match.mask->n_proto);
}
- if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
u16 eth_ip_type = ethtype_key & ethtype_mask;
- struct flow_dissector_key_ip *mask;
+ struct flow_match_ip match;
if (eth_ip_type != ETH_P_IP && eth_ip_type != ETH_P_IPV6) {
netdev_err(dev, "IP Key supported only with IPv4/v6");
return -EINVAL;
}
- mask = skb_flow_dissector_target(cls->dissector,
- FLOW_DISSECTOR_KEY_IP,
- cls->mask);
- if (mask->ttl) {
+ flow_rule_match_ip(rule, &match);
+ if (match.mask->ttl) {
netdev_warn(dev, "ttl match unsupported for offload");
return -EOPNOTSUPP;
}
@@ -328,7 +292,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
u32 mask, u32 offset, u8 htype)
{
switch (htype) {
- case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
+ case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
switch (offset) {
case PEDIT_ETH_DMAC_31_0:
fs->newdmac = 1;
@@ -346,7 +310,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
offload_pedit(fs, val, mask, ETH_SMAC_47_16);
}
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
+ case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
switch (offset) {
case PEDIT_IP4_SRC:
offload_pedit(fs, val, mask, IP4_SRC);
@@ -356,7 +320,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
}
fs->nat_mode = NAT_MODE_ALL;
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
+ case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
switch (offset) {
case PEDIT_IP6_SRC_31_0:
offload_pedit(fs, val, mask, IP6_SRC_31_0);
@@ -384,7 +348,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
}
fs->nat_mode = NAT_MODE_ALL;
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
+ case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
switch (offset) {
case PEDIT_TCP_SPORT_DPORT:
if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
@@ -397,7 +361,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
}
fs->nat_mode = NAT_MODE_ALL;
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
+ case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
switch (offset) {
case PEDIT_UDP_SPORT_DPORT:
if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
@@ -416,56 +380,63 @@ static void cxgb4_process_flow_actions(struct net_device *in,
struct tc_cls_flower_offload *cls,
struct ch_filter_specification *fs)
{
- const struct tc_action *a;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls);
+ struct flow_action_entry *act;
int i;
- tcf_exts_for_each_action(i, a, cls->exts) {
- if (is_tcf_gact_ok(a)) {
+ flow_action_for_each(i, act, &rule->action) {
+ switch (act->id) {
+ case FLOW_ACTION_ACCEPT:
fs->action = FILTER_PASS;
- } else if (is_tcf_gact_shot(a)) {
+ break;
+ case FLOW_ACTION_DROP:
fs->action = FILTER_DROP;
- } else if (is_tcf_mirred_egress_redirect(a)) {
- struct net_device *out = tcf_mirred_dev(a);
+ break;
+ case FLOW_ACTION_REDIRECT: {
+ struct net_device *out = act->dev;
struct port_info *pi = netdev_priv(out);
fs->action = FILTER_SWITCH;
fs->eport = pi->port_id;
- } else if (is_tcf_vlan(a)) {
- u32 vlan_action = tcf_vlan_action(a);
- u8 prio = tcf_vlan_push_prio(a);
- u16 vid = tcf_vlan_push_vid(a);
+ }
+ break;
+ case FLOW_ACTION_VLAN_POP:
+ case FLOW_ACTION_VLAN_PUSH:
+ case FLOW_ACTION_VLAN_MANGLE: {
+ u8 prio = act->vlan.prio;
+ u16 vid = act->vlan.vid;
u16 vlan_tci = (prio << VLAN_PRIO_SHIFT) | vid;
-
- switch (vlan_action) {
- case TCA_VLAN_ACT_POP:
+ switch (act->id) {
+ case FLOW_ACTION_VLAN_POP:
fs->newvlan |= VLAN_REMOVE;
break;
- case TCA_VLAN_ACT_PUSH:
+ case FLOW_ACTION_VLAN_PUSH:
fs->newvlan |= VLAN_INSERT;
fs->vlan = vlan_tci;
break;
- case TCA_VLAN_ACT_MODIFY:
+ case FLOW_ACTION_VLAN_MANGLE:
fs->newvlan |= VLAN_REWRITE;
fs->vlan = vlan_tci;
break;
default:
break;
}
- } else if (is_tcf_pedit(a)) {
+ }
+ break;
+ case FLOW_ACTION_MANGLE: {
u32 mask, val, offset;
- int nkeys, i;
u8 htype;
- nkeys = tcf_pedit_nkeys(a);
- for (i = 0; i < nkeys; i++) {
- htype = tcf_pedit_htype(a, i);
- mask = tcf_pedit_mask(a, i);
- val = tcf_pedit_val(a, i);
- offset = tcf_pedit_offset(a, i);
+ htype = act->mangle.htype;
+ mask = act->mangle.mask;
+ val = act->mangle.val;
+ offset = act->mangle.offset;
- process_pedit_field(fs, val, mask, offset,
- htype);
+ process_pedit_field(fs, val, mask, offset, htype);
}
+ break;
+ default:
+ break;
}
}
}
@@ -484,101 +455,89 @@ static bool valid_l4_mask(u32 mask)
}
static bool valid_pedit_action(struct net_device *dev,
- const struct tc_action *a)
+ const struct flow_action_entry *act)
{
u32 mask, offset;
- u8 cmd, htype;
- int nkeys, i;
-
- nkeys = tcf_pedit_nkeys(a);
- for (i = 0; i < nkeys; i++) {
- htype = tcf_pedit_htype(a, i);
- cmd = tcf_pedit_cmd(a, i);
- mask = tcf_pedit_mask(a, i);
- offset = tcf_pedit_offset(a, i);
-
- if (cmd != TCA_PEDIT_KEY_EX_CMD_SET) {
- netdev_err(dev, "%s: Unsupported pedit cmd\n",
+ u8 htype;
+
+ htype = act->mangle.htype;
+ mask = act->mangle.mask;
+ offset = act->mangle.offset;
+
+ switch (htype) {
+ case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
+ switch (offset) {
+ case PEDIT_ETH_DMAC_31_0:
+ case PEDIT_ETH_DMAC_47_32_SMAC_15_0:
+ case PEDIT_ETH_SMAC_47_16:
+ break;
+ default:
+ netdev_err(dev, "%s: Unsupported pedit field\n",
__func__);
return false;
}
-
- switch (htype) {
- case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
- switch (offset) {
- case PEDIT_ETH_DMAC_31_0:
- case PEDIT_ETH_DMAC_47_32_SMAC_15_0:
- case PEDIT_ETH_SMAC_47_16:
- break;
- default:
- netdev_err(dev, "%s: Unsupported pedit field\n",
- __func__);
- return false;
- }
- break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
- switch (offset) {
- case PEDIT_IP4_SRC:
- case PEDIT_IP4_DST:
- break;
- default:
- netdev_err(dev, "%s: Unsupported pedit field\n",
- __func__);
- return false;
- }
+ break;
+ case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
+ switch (offset) {
+ case PEDIT_IP4_SRC:
+ case PEDIT_IP4_DST:
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
- switch (offset) {
- case PEDIT_IP6_SRC_31_0:
- case PEDIT_IP6_SRC_63_32:
- case PEDIT_IP6_SRC_95_64:
- case PEDIT_IP6_SRC_127_96:
- case PEDIT_IP6_DST_31_0:
- case PEDIT_IP6_DST_63_32:
- case PEDIT_IP6_DST_95_64:
- case PEDIT_IP6_DST_127_96:
- break;
- default:
- netdev_err(dev, "%s: Unsupported pedit field\n",
- __func__);
- return false;
- }
+ default:
+ netdev_err(dev, "%s: Unsupported pedit field\n",
+ __func__);
+ return false;
+ }
+ break;
+ case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
+ switch (offset) {
+ case PEDIT_IP6_SRC_31_0:
+ case PEDIT_IP6_SRC_63_32:
+ case PEDIT_IP6_SRC_95_64:
+ case PEDIT_IP6_SRC_127_96:
+ case PEDIT_IP6_DST_31_0:
+ case PEDIT_IP6_DST_63_32:
+ case PEDIT_IP6_DST_95_64:
+ case PEDIT_IP6_DST_127_96:
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
- switch (offset) {
- case PEDIT_TCP_SPORT_DPORT:
- if (!valid_l4_mask(~mask)) {
- netdev_err(dev, "%s: Unsupported mask for TCP L4 ports\n",
- __func__);
- return false;
- }
- break;
- default:
- netdev_err(dev, "%s: Unsupported pedit field\n",
+ default:
+ netdev_err(dev, "%s: Unsupported pedit field\n",
+ __func__);
+ return false;
+ }
+ break;
+ case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
+ switch (offset) {
+ case PEDIT_TCP_SPORT_DPORT:
+ if (!valid_l4_mask(~mask)) {
+ netdev_err(dev, "%s: Unsupported mask for TCP L4 ports\n",
__func__);
return false;
}
break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
- switch (offset) {
- case PEDIT_UDP_SPORT_DPORT:
- if (!valid_l4_mask(~mask)) {
- netdev_err(dev, "%s: Unsupported mask for UDP L4 ports\n",
- __func__);
- return false;
- }
- break;
- default:
- netdev_err(dev, "%s: Unsupported pedit field\n",
+ default:
+ netdev_err(dev, "%s: Unsupported pedit field\n",
+ __func__);
+ return false;
+ }
+ break;
+ case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
+ switch (offset) {
+ case PEDIT_UDP_SPORT_DPORT:
+ if (!valid_l4_mask(~mask)) {
+ netdev_err(dev, "%s: Unsupported mask for UDP L4 ports\n",
__func__);
return false;
}
break;
default:
- netdev_err(dev, "%s: Unsupported pedit type\n",
+ netdev_err(dev, "%s: Unsupported pedit field\n",
__func__);
return false;
}
+ break;
+ default:
+ netdev_err(dev, "%s: Unsupported pedit type\n", __func__);
+ return false;
}
return true;
}
@@ -586,24 +545,26 @@ static bool valid_pedit_action(struct net_device *dev,
static int cxgb4_validate_flow_actions(struct net_device *dev,
struct tc_cls_flower_offload *cls)
{
- const struct tc_action *a;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls);
+ struct flow_action_entry *act;
bool act_redir = false;
bool act_pedit = false;
bool act_vlan = false;
int i;
- tcf_exts_for_each_action(i, a, cls->exts) {
- if (is_tcf_gact_ok(a)) {
- /* Do nothing */
- } else if (is_tcf_gact_shot(a)) {
+ flow_action_for_each(i, act, &rule->action) {
+ switch (act->id) {
+ case FLOW_ACTION_ACCEPT:
+ case FLOW_ACTION_DROP:
/* Do nothing */
- } else if (is_tcf_mirred_egress_redirect(a)) {
+ break;
+ case FLOW_ACTION_REDIRECT: {
struct adapter *adap = netdev2adap(dev);
struct net_device *n_dev, *target_dev;
unsigned int i;
bool found = false;
- target_dev = tcf_mirred_dev(a);
+ target_dev = act->dev;
for_each_port(adap, i) {
n_dev = adap->port[i];
if (target_dev == n_dev) {
@@ -621,15 +582,18 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
return -EINVAL;
}
act_redir = true;
- } else if (is_tcf_vlan(a)) {
- u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
- u32 vlan_action = tcf_vlan_action(a);
+ }
+ break;
+ case FLOW_ACTION_VLAN_POP:
+ case FLOW_ACTION_VLAN_PUSH:
+ case FLOW_ACTION_VLAN_MANGLE: {
+ u16 proto = be16_to_cpu(act->vlan.proto);
- switch (vlan_action) {
- case TCA_VLAN_ACT_POP:
+ switch (act->id) {
+ case FLOW_ACTION_VLAN_POP:
break;
- case TCA_VLAN_ACT_PUSH:
- case TCA_VLAN_ACT_MODIFY:
+ case FLOW_ACTION_VLAN_PUSH:
+ case FLOW_ACTION_VLAN_MANGLE:
if (proto != ETH_P_8021Q) {
netdev_err(dev, "%s: Unsupported vlan proto\n",
__func__);
@@ -642,13 +606,17 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
return -EOPNOTSUPP;
}
act_vlan = true;
- } else if (is_tcf_pedit(a)) {
- bool pedit_valid = valid_pedit_action(dev, a);
+ }
+ break;
+ case FLOW_ACTION_MANGLE: {
+ bool pedit_valid = valid_pedit_action(dev, act);
if (!pedit_valid)
return -EOPNOTSUPP;
act_pedit = true;
- } else {
+ }
+ break;
+ default:
netdev_err(dev, "%s: Unsupported action\n", __func__);
return -EOPNOTSUPP;
}
@@ -843,9 +811,9 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
if (ofld_stats->packet_count != packets) {
if (ofld_stats->prev_packet_count != packets)
ofld_stats->last_used = jiffies;
- tcf_exts_stats_update(cls->exts, bytes - ofld_stats->byte_count,
- packets - ofld_stats->packet_count,
- ofld_stats->last_used);
+ flow_stats_update(&cls->stats, bytes - ofld_stats->byte_count,
+ packets - ofld_stats->packet_count,
+ ofld_stats->last_used);
ofld_stats->packet_count = packets;
ofld_stats->byte_count = bytes;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
index c7d2b4dc7568..02fc63fa7f25 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
@@ -444,8 +444,7 @@ struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
if (!max_tids)
return NULL;
- t = kvzalloc(sizeof(*t) +
- (max_tids * sizeof(struct cxgb4_link)), GFP_KERNEL);
+ t = kvzalloc(struct_size(t, table, max_tids), GFP_KERNEL);
if (!t)
return NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
index 9a6065a3fa46..6c685b920713 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -78,7 +78,7 @@ static void free_msix_idx_in_bmap(struct adapter *adap, unsigned int msix_idx)
unsigned long flags;
spin_lock_irqsave(&bmap->lock, flags);
- __clear_bit(msix_idx, bmap->msix_bmap);
+ __clear_bit(msix_idx, bmap->msix_bmap);
spin_unlock_irqrestore(&bmap->lock, flags);
}
@@ -147,7 +147,7 @@ static int alloc_uld_rxqs(struct adapter *adap,
per_chan = rxq_info->nrxq / adap->params.nports;
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
msi_idx = 1;
else
msi_idx = -((int)s->intrq.abs_id + 1);
@@ -195,7 +195,7 @@ setup_sge_queues_uld(struct adapter *adap, unsigned int uld_type, bool lro)
struct sge_uld_rxq_info *rxq_info = adap->sge.uld_rxq_info[uld_type];
int i, ret = 0;
- if (adap->flags & USING_MSIX) {
+ if (adap->flags & CXGB4_USING_MSIX) {
rxq_info->msix_tbl = kcalloc((rxq_info->nrxq + rxq_info->nciq),
sizeof(unsigned short),
GFP_KERNEL);
@@ -206,7 +206,7 @@ setup_sge_queues_uld(struct adapter *adap, unsigned int uld_type, bool lro)
ret = !(!alloc_uld_rxqs(adap, rxq_info, lro));
/* Tell uP to route control queue completions to rdma rspq */
- if (adap->flags & FULL_INIT_DONE &&
+ if (adap->flags & CXGB4_FULL_INIT_DONE &&
!ret && uld_type == CXGB4_ULD_RDMA) {
struct sge *s = &adap->sge;
unsigned int cmplqid;
@@ -239,7 +239,7 @@ static void free_sge_queues_uld(struct adapter *adap, unsigned int uld_type)
{
struct sge_uld_rxq_info *rxq_info = adap->sge.uld_rxq_info[uld_type];
- if (adap->flags & FULL_INIT_DONE && uld_type == CXGB4_ULD_RDMA) {
+ if (adap->flags & CXGB4_FULL_INIT_DONE && uld_type == CXGB4_ULD_RDMA) {
struct sge *s = &adap->sge;
u32 param, cmdop, cmplqid = 0;
int i;
@@ -258,7 +258,7 @@ static void free_sge_queues_uld(struct adapter *adap, unsigned int uld_type)
t4_free_uld_rxqs(adap, rxq_info->nciq,
rxq_info->uldrxq + rxq_info->nrxq);
t4_free_uld_rxqs(adap, rxq_info->nrxq, rxq_info->uldrxq);
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
kfree(rxq_info->msix_tbl);
}
@@ -273,7 +273,7 @@ static int cfg_queues_uld(struct adapter *adap, unsigned int uld_type,
if (!rxq_info)
return -ENOMEM;
- if (adap->flags & USING_MSIX && uld_info->nrxq > s->nqs_per_uld) {
+ if (adap->flags & CXGB4_USING_MSIX && uld_info->nrxq > s->nqs_per_uld) {
i = s->nqs_per_uld;
rxq_info->nrxq = roundup(i, adap->params.nports);
} else {
@@ -284,7 +284,7 @@ static int cfg_queues_uld(struct adapter *adap, unsigned int uld_type,
if (!uld_info->ciq) {
rxq_info->nciq = 0;
} else {
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
rxq_info->nciq = min_t(int, s->nqs_per_uld,
num_online_cpus());
else
@@ -611,10 +611,10 @@ static void cxgb4_shutdown_uld_adapter(struct adapter *adap, enum cxgb4_uld type
adap->uld[type].add = NULL;
release_sge_txq_uld(adap, type);
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
quiesce_rx_uld(adap, type);
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
free_msix_queue_irqs_uld(adap, type);
free_sge_queues_uld(adap, type);
@@ -660,6 +660,7 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
lld->cclk_ps = 1000000000 / adap->params.vpd.cclk;
lld->udb_density = 1 << adap->params.sge.eq_qpp;
lld->ucq_density = 1 << adap->params.sge.iq_qpp;
+ lld->sge_host_page_size = 1 << (adap->params.sge.hps + 10);
lld->filt_mode = adap->params.tp.vlan_pri_map;
/* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
for (i = 0; i < NCHAN; i++)
@@ -672,7 +673,7 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
lld->sge_egrstatuspagesize = adap->sge.stat_len;
lld->sge_pktshift = adap->sge.pktshift;
lld->ulp_crypto = adap->params.crypto;
- lld->enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
+ lld->enable_fw_ofld_conn = adap->flags & CXGB4_FW_OFLD_CONN;
lld->max_ordird_qp = adap->params.max_ordird_qp;
lld->max_ird_adapter = adap->params.max_ird_adapter;
lld->ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl;
@@ -701,7 +702,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
adap->uld[uld].handle = handle;
t4_register_netevent_notifier();
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
adap->uld[uld].state_change(handle, CXGB4_STATE_UP);
}
@@ -736,13 +737,13 @@ void cxgb4_register_uld(enum cxgb4_uld type,
ret = setup_sge_queues_uld(adap, type, p->lro);
if (ret)
goto free_queues;
- if (adap->flags & USING_MSIX) {
+ if (adap->flags & CXGB4_USING_MSIX) {
name_msix_vecs_uld(adap, type);
ret = request_msix_queue_irqs_uld(adap, type);
if (ret)
goto free_rxq;
}
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
enable_rx_uld(adap, type);
if (adap->uld[type].add)
goto free_irq;
@@ -753,9 +754,9 @@ void cxgb4_register_uld(enum cxgb4_uld type,
uld_attach(adap, type);
continue;
free_irq:
- if (adap->flags & FULL_INIT_DONE)
+ if (adap->flags & CXGB4_FULL_INIT_DONE)
quiesce_rx_uld(adap, type);
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
free_msix_queue_irqs_uld(adap, type);
free_rxq:
free_sge_queues_uld(adap, type);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 5fa9a2d5fc4b..21da34a4ca24 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -336,6 +336,7 @@ struct cxgb4_lld_info {
unsigned int cclk_ps; /* Core clock period in psec */
unsigned short udb_density; /* # of user DB/page */
unsigned short ucq_density; /* # of user CQs/page */
+ unsigned int sge_host_page_size; /* SGE host page size */
unsigned short filt_mode; /* filter optional components */
unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */
/* scheduler queue */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 4852febbfec3..1a407d3c1d67 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -646,7 +646,7 @@ struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end)
if (l2t_size < L2T_MIN_HASH_BUCKETS)
return NULL;
- d = kvzalloc(sizeof(*d) + l2t_size * sizeof(struct l2t_entry), GFP_KERNEL);
+ d = kvzalloc(struct_size(d, l2tab, l2t_size), GFP_KERNEL);
if (!d)
return NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sched.c b/drivers/net/ethernet/chelsio/cxgb4/sched.c
index 52edb688942b..ba6c153ee45c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sched.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sched.c
@@ -478,7 +478,7 @@ struct sched_table *t4_init_sched(unsigned int sched_size)
struct sched_table *s;
unsigned int i;
- s = kvzalloc(sizeof(*s) + sched_size * sizeof(struct sched_class), GFP_KERNEL);
+ s = kvzalloc(struct_size(s, tab, sched_size), GFP_KERNEL);
if (!s)
return NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index b90188401d4a..88773ca58e6b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -80,9 +80,10 @@
* Max number of Tx descriptors we clean up at a time. Should be modest as
* freeing skbs isn't cheap and it happens while holding locks. We just need
* to free packets faster than they arrive, we eventually catch up and keep
- * the amortized cost reasonable. Must be >= 2 * TXQ_STOP_THRES.
+ * the amortized cost reasonable. Must be >= 2 * TXQ_STOP_THRES. It should
+ * also match the CIDX Flush Threshold.
*/
-#define MAX_TX_RECLAIM 16
+#define MAX_TX_RECLAIM 32
/*
* Max number of Rx buffers we replenish at a time. Again keep this modest,
@@ -401,31 +402,52 @@ static inline int reclaimable(const struct sge_txq *q)
}
/**
- * cxgb4_reclaim_completed_tx - reclaims completed Tx descriptors
+ * reclaim_completed_tx - reclaims completed TX Descriptors
* @adap: the adapter
* @q: the Tx queue to reclaim completed descriptors from
+ * @maxreclaim: the maximum number of TX Descriptors to reclaim or -1
* @unmap: whether the buffers should be unmapped for DMA
*
- * Reclaims Tx descriptors that the SGE has indicated it has processed,
- * and frees the associated buffers if possible. Called with the Tx
- * queue locked.
+ * Reclaims Tx Descriptors that the SGE has indicated it has processed,
+ * and frees the associated buffers if possible. If @max == -1, then
+ * we'll use a defaiult maximum. Called with the TX Queue locked.
*/
-inline void cxgb4_reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
- bool unmap)
+static inline int reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
+ int maxreclaim, bool unmap)
{
- int avail = reclaimable(q);
+ int reclaim = reclaimable(q);
- if (avail) {
+ if (reclaim) {
/*
* Limit the amount of clean up work we do at a time to keep
* the Tx lock hold time O(1).
*/
- if (avail > MAX_TX_RECLAIM)
- avail = MAX_TX_RECLAIM;
+ if (maxreclaim < 0)
+ maxreclaim = MAX_TX_RECLAIM;
+ if (reclaim > maxreclaim)
+ reclaim = maxreclaim;
- free_tx_desc(adap, q, avail, unmap);
- q->in_use -= avail;
+ free_tx_desc(adap, q, reclaim, unmap);
+ q->in_use -= reclaim;
}
+
+ return reclaim;
+}
+
+/**
+ * cxgb4_reclaim_completed_tx - reclaims completed Tx descriptors
+ * @adap: the adapter
+ * @q: the Tx queue to reclaim completed descriptors from
+ * @unmap: whether the buffers should be unmapped for DMA
+ *
+ * Reclaims Tx descriptors that the SGE has indicated it has processed,
+ * and frees the associated buffers if possible. Called with the Tx
+ * queue locked.
+ */
+void cxgb4_reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
+ bool unmap)
+{
+ (void)reclaim_completed_tx(adap, q, -1, unmap);
}
EXPORT_SYMBOL(cxgb4_reclaim_completed_tx);
@@ -694,7 +716,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
{
size_t len = nelem * elem_size + stat_size;
void *s = NULL;
- void *p = dma_zalloc_coherent(dev, len, phys, GFP_KERNEL);
+ void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL);
if (!p)
return NULL;
@@ -1288,6 +1310,44 @@ static inline void t6_fill_tnl_lso(struct sk_buff *skb,
}
/**
+ * t4_sge_eth_txq_egress_update - handle Ethernet TX Queue update
+ * @adap: the adapter
+ * @eq: the Ethernet TX Queue
+ * @maxreclaim: the maximum number of TX Descriptors to reclaim or -1
+ *
+ * We're typically called here to update the state of an Ethernet TX
+ * Queue with respect to the hardware's progress in consuming the TX
+ * Work Requests that we've put on that Egress Queue. This happens
+ * when we get Egress Queue Update messages and also prophylactically
+ * in regular timer-based Ethernet TX Queue maintenance.
+ */
+int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq,
+ int maxreclaim)
+{
+ struct sge_txq *q = &eq->q;
+ unsigned int reclaimed;
+
+ if (!q->in_use || !__netif_tx_trylock(eq->txq))
+ return 0;
+
+ /* Reclaim pending completed TX Descriptors. */
+ reclaimed = reclaim_completed_tx(adap, &eq->q, maxreclaim, true);
+
+ /* If the TX Queue is currently stopped and there's now more than half
+ * the queue available, restart it. Otherwise bail out since the rest
+ * of what we want do here is with the possibility of shipping any
+ * currently buffered Coalesced TX Work Request.
+ */
+ if (netif_tx_queue_stopped(eq->txq) && txq_avail(q) > (q->size / 2)) {
+ netif_tx_wake_queue(eq->txq);
+ eq->q.restarts++;
+ }
+
+ __netif_tx_unlock(eq->txq);
+ return reclaimed;
+}
+
+/**
* cxgb4_eth_xmit - add a packet to an Ethernet Tx queue
* @skb: the packet
* @dev: the egress net device
@@ -1357,7 +1417,7 @@ out_free: dev_kfree_skb_any(skb);
}
skb_tx_timestamp(skb);
- cxgb4_reclaim_completed_tx(adap, &q->q, true);
+ reclaim_completed_tx(adap, &q->q, -1, true);
cntrl = TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F;
#ifdef CONFIG_CHELSIO_T4_FCOE
@@ -1400,8 +1460,25 @@ out_free: dev_kfree_skb_any(skb);
wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2));
if (unlikely(credits < ETHTXQ_STOP_THRES)) {
+ /* After we're done injecting the Work Request for this
+ * packet, we'll be below our "stop threshold" so stop the TX
+ * Queue now and schedule a request for an SGE Egress Queue
+ * Update message. The queue will get started later on when
+ * the firmware processes this Work Request and sends us an
+ * Egress Queue Status Update message indicating that space
+ * has opened up.
+ */
eth_txq_stop(q);
- wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+
+ /* If we're using the SGE Doorbell Queue Timer facility, we
+ * don't need to ask the Firmware to send us Egress Queue CIDX
+ * Updates: the Hardware will do this automatically. And
+ * since we send the Ingress Queue CIDX Updates to the
+ * corresponding Ethernet Response Queue, we'll get them very
+ * quickly.
+ */
+ if (!q->dbqt)
+ wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
}
wr = (void *)&q->q.desc[q->q.pidx];
@@ -1671,7 +1748,7 @@ static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb,
/* Take this opportunity to reclaim any TX Descriptors whose DMA
* transfers have completed.
*/
- cxgb4_reclaim_completed_tx(adapter, &txq->q, true);
+ reclaim_completed_tx(adapter, &txq->q, -1, true);
/* Calculate the number of flits and TX Descriptors we're going to
* need along with how many TX Descriptors will be left over after
@@ -1715,7 +1792,16 @@ static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb,
* has opened up.
*/
eth_txq_stop(txq);
- wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+
+ /* If we're using the SGE Doorbell Queue Timer facility, we
+ * don't need to ask the Firmware to send us Egress Queue CIDX
+ * Updates: the Hardware will do this automatically. And
+ * since we send the Ingress Queue CIDX Updates to the
+ * corresponding Ethernet Response Queue, we'll get them very
+ * quickly.
+ */
+ if (!txq->dbqt)
+ wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
}
/* Start filling in our Work Request. Note that we do _not_ handle
@@ -2794,6 +2880,74 @@ static int t4_tx_hststamp(struct adapter *adapter, struct sk_buff *skb,
}
/**
+ * t4_tx_completion_handler - handle CPL_SGE_EGR_UPDATE messages
+ * @rspq: Ethernet RX Response Queue associated with Ethernet TX Queue
+ * @rsp: Response Entry pointer into Response Queue
+ * @gl: Gather List pointer
+ *
+ * For adapters which support the SGE Doorbell Queue Timer facility,
+ * we configure the Ethernet TX Queues to send CIDX Updates to the
+ * Associated Ethernet RX Response Queue with CPL_SGE_EGR_UPDATE
+ * messages. This adds a small load to PCIe Link RX bandwidth and,
+ * potentially, higher CPU Interrupt load, but allows us to respond
+ * much more quickly to the CIDX Updates. This is important for
+ * Upper Layer Software which isn't willing to have a large amount
+ * of TX Data outstanding before receiving DMA Completions.
+ */
+static void t4_tx_completion_handler(struct sge_rspq *rspq,
+ const __be64 *rsp,
+ const struct pkt_gl *gl)
+{
+ u8 opcode = ((const struct rss_header *)rsp)->opcode;
+ struct port_info *pi = netdev_priv(rspq->netdev);
+ struct adapter *adapter = rspq->adap;
+ struct sge *s = &adapter->sge;
+ struct sge_eth_txq *txq;
+
+ /* skip RSS header */
+ rsp++;
+
+ /* FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG.
+ */
+ if (unlikely(opcode == CPL_FW4_MSG &&
+ ((const struct cpl_fw4_msg *)rsp)->type ==
+ FW_TYPE_RSSCPL)) {
+ rsp++;
+ opcode = ((const struct rss_header *)rsp)->opcode;
+ rsp++;
+ }
+
+ if (unlikely(opcode != CPL_SGE_EGR_UPDATE)) {
+ pr_info("%s: unexpected FW4/CPL %#x on Rx queue\n",
+ __func__, opcode);
+ return;
+ }
+
+ txq = &s->ethtxq[pi->first_qset + rspq->idx];
+
+ /* We've got the Hardware Consumer Index Update in the Egress Update
+ * message. If we're using the SGE Doorbell Queue Timer mechanism,
+ * these Egress Update messages will be our sole CIDX Updates we get
+ * since we don't want to chew up PCIe bandwidth for both Ingress
+ * Messages and Status Page writes. However, The code which manages
+ * reclaiming successfully DMA'ed TX Work Requests uses the CIDX value
+ * stored in the Status Page at the end of the TX Queue. It's easiest
+ * to simply copy the CIDX Update value from the Egress Update message
+ * to the Status Page. Also note that no Endian issues need to be
+ * considered here since both are Big Endian and we're just copying
+ * bytes consistently ...
+ */
+ if (txq->dbqt) {
+ struct cpl_sge_egr_update *egr;
+
+ egr = (struct cpl_sge_egr_update *)rsp;
+ WRITE_ONCE(txq->q.stat->cidx, egr->cidx);
+ }
+
+ t4_sge_eth_txq_egress_update(adapter, txq, -1);
+}
+
+/**
* t4_ethrx_handler - process an ingress ethernet packet
* @q: the response queue that received the packet
* @rsp: the response queue descriptor holding the RX_PKT message
@@ -2816,6 +2970,15 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
struct port_info *pi;
int ret = 0;
+ /* If we're looking at TX Queue CIDX Update, handle that separately
+ * and return.
+ */
+ if (unlikely((*(u8 *)rsp == CPL_FW4_MSG) ||
+ (*(u8 *)rsp == CPL_SGE_EGR_UPDATE))) {
+ t4_tx_completion_handler(q, rsp, si);
+ return 0;
+ }
+
if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
return handle_trace_pkt(q->adap, si);
@@ -3212,7 +3375,7 @@ static irqreturn_t t4_intr_msi(int irq, void *cookie)
{
struct adapter *adap = cookie;
- if (adap->flags & MASTER_PF)
+ if (adap->flags & CXGB4_MASTER_PF)
t4_slow_intr_handler(adap);
process_intrq(adap);
return IRQ_HANDLED;
@@ -3228,7 +3391,7 @@ static irqreturn_t t4_intr_intx(int irq, void *cookie)
struct adapter *adap = cookie;
t4_write_reg(adap, MYPF_REG(PCIE_PF_CLI_A), 0);
- if (((adap->flags & MASTER_PF) && t4_slow_intr_handler(adap)) |
+ if (((adap->flags & CXGB4_MASTER_PF) && t4_slow_intr_handler(adap)) |
process_intrq(adap))
return IRQ_HANDLED;
return IRQ_NONE; /* probably shared interrupt */
@@ -3243,9 +3406,9 @@ static irqreturn_t t4_intr_intx(int irq, void *cookie)
*/
irq_handler_t t4_intr_handler(struct adapter *adap)
{
- if (adap->flags & USING_MSIX)
+ if (adap->flags & CXGB4_USING_MSIX)
return t4_sge_intr_msix;
- if (adap->flags & USING_MSI)
+ if (adap->flags & CXGB4_USING_MSI)
return t4_intr_msi;
return t4_intr_intx;
}
@@ -3278,7 +3441,7 @@ static void sge_rx_timer_cb(struct timer_list *t)
* global Master PF activities like checking for chip ingress stalls,
* etc.
*/
- if (!(adap->flags & MASTER_PF))
+ if (!(adap->flags & CXGB4_MASTER_PF))
goto done;
t4_idma_monitor(adap, &s->idma_monitor, HZ, RX_QCHECK_PERIOD);
@@ -3289,10 +3452,10 @@ done:
static void sge_tx_timer_cb(struct timer_list *t)
{
- unsigned long m;
- unsigned int i, budget;
struct adapter *adap = from_timer(adap, t, sge.tx_timer);
struct sge *s = &adap->sge;
+ unsigned long m, period;
+ unsigned int i, budget;
for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
for (m = s->txq_maperr[i]; m; m &= m - 1) {
@@ -3320,29 +3483,29 @@ static void sge_tx_timer_cb(struct timer_list *t)
budget = MAX_TIMER_TX_RECLAIM;
i = s->ethtxq_rover;
do {
- struct sge_eth_txq *q = &s->ethtxq[i];
-
- if (q->q.in_use &&
- time_after_eq(jiffies, q->txq->trans_start + HZ / 100) &&
- __netif_tx_trylock(q->txq)) {
- int avail = reclaimable(&q->q);
-
- if (avail) {
- if (avail > budget)
- avail = budget;
-
- free_tx_desc(adap, &q->q, avail, true);
- q->q.in_use -= avail;
- budget -= avail;
- }
- __netif_tx_unlock(q->txq);
- }
+ budget -= t4_sge_eth_txq_egress_update(adap, &s->ethtxq[i],
+ budget);
+ if (!budget)
+ break;
if (++i >= s->ethqsets)
i = 0;
- } while (budget && i != s->ethtxq_rover);
+ } while (i != s->ethtxq_rover);
s->ethtxq_rover = i;
- mod_timer(&s->tx_timer, jiffies + (budget ? TX_QCHECK_PERIOD : 2));
+
+ if (budget == 0) {
+ /* If we found too many reclaimable packets schedule a timer
+ * in the near future to continue where we left off.
+ */
+ period = 2;
+ } else {
+ /* We reclaimed all reclaimable TX Descriptors, so reschedule
+ * at the normal period.
+ */
+ period = TX_QCHECK_PERIOD;
+ }
+
+ mod_timer(&s->tx_timer, jiffies + period);
}
/**
@@ -3386,7 +3549,7 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
struct fw_iq_cmd c;
struct sge *s = &adap->sge;
struct port_info *pi = netdev_priv(dev);
- int relaxed = !(adap->flags & ROOT_NO_RELAXED_ORDERING);
+ int relaxed = !(adap->flags & CXGB4_ROOT_NO_RELAXED_ORDERING);
/* Size needs to be multiple of 16, including status entry. */
iq->size = roundup(iq->size, 16);
@@ -3421,7 +3584,8 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
: FW_IQ_IQTYPE_OFLD));
if (fl) {
- enum chip_type chip = CHELSIO_CHIP_VERSION(adap->params.chip);
+ unsigned int chip_ver =
+ CHELSIO_CHIP_VERSION(adap->params.chip);
/* Allocate the ring for the hardware free list (with space
* for its status page) along with the associated software
@@ -3459,10 +3623,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
* the smaller 64-byte value there).
*/
c.fl0dcaen_to_fl0cidxfthresh =
- htons(FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ?
+ htons(FW_IQ_CMD_FL0FBMIN_V(chip_ver <= CHELSIO_T5 ?
FETCHBURSTMIN_128B_X :
- FETCHBURSTMIN_64B_X) |
- FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ?
+ FETCHBURSTMIN_64B_T6_X) |
+ FW_IQ_CMD_FL0FBMAX_V((chip_ver <= CHELSIO_T5) ?
FETCHBURSTMAX_512B_X :
FETCHBURSTMAX_256B_X));
c.fl0size = htons(flsz);
@@ -3584,14 +3748,24 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
adap->sge.egr_map[id - adap->sge.egr_start] = q;
}
+/**
+ * t4_sge_alloc_eth_txq - allocate an Ethernet TX Queue
+ * @adap: the adapter
+ * @txq: the SGE Ethernet TX Queue to initialize
+ * @dev: the Linux Network Device
+ * @netdevq: the corresponding Linux TX Queue
+ * @iqid: the Ingress Queue to which to deliver CIDX Update messages
+ * @dbqt: whether this TX Queue will use the SGE Doorbell Queue Timers
+ */
int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
struct net_device *dev, struct netdev_queue *netdevq,
- unsigned int iqid)
+ unsigned int iqid, u8 dbqt)
{
- int ret, nentries;
- struct fw_eq_eth_cmd c;
- struct sge *s = &adap->sge;
+ unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
struct port_info *pi = netdev_priv(dev);
+ struct sge *s = &adap->sge;
+ struct fw_eq_eth_cmd c;
+ int ret, nentries;
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@ -3610,19 +3784,47 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
FW_EQ_ETH_CMD_VFN_V(0));
c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC_F |
FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(c));
- c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F |
- FW_EQ_ETH_CMD_VIID_V(pi->viid));
+
+ /* For TX Ethernet Queues using the SGE Doorbell Queue Timer
+ * mechanism, we use Ingress Queue messages for Hardware Consumer
+ * Index Updates on the TX Queue. Otherwise we have the Hardware
+ * write the CIDX Updates into the Status Page at the end of the
+ * TX Queue.
+ */
+ c.autoequiqe_to_viid = htonl((dbqt
+ ? FW_EQ_ETH_CMD_AUTOEQUIQE_F
+ : FW_EQ_ETH_CMD_AUTOEQUEQE_F) |
+ FW_EQ_ETH_CMD_VIID_V(pi->viid));
+
c.fetchszm_to_iqid =
- htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) |
+ htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(dbqt
+ ? HOSTFCMODE_INGRESS_QUEUE_X
+ : HOSTFCMODE_STATUS_PAGE_X) |
FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) |
FW_EQ_ETH_CMD_FETCHRO_F | FW_EQ_ETH_CMD_IQID_V(iqid));
+
+ /* Note that the CIDX Flush Threshold should match MAX_TX_RECLAIM. */
c.dcaen_to_eqsize =
- htonl(FW_EQ_ETH_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) |
+ htonl(FW_EQ_ETH_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
+ ? FETCHBURSTMIN_64B_X
+ : FETCHBURSTMIN_64B_T6_X) |
FW_EQ_ETH_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
FW_EQ_ETH_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
FW_EQ_ETH_CMD_EQSIZE_V(nentries));
+
c.eqaddr = cpu_to_be64(txq->q.phys_addr);
+ /* If we're using the SGE Doorbell Queue Timer mechanism, pass in the
+ * currently configured Timer Index. THis can be changed later via an
+ * ethtool -C tx-usecs {Timer Val} command. Note that the SGE
+ * Doorbell Queue mode is currently automatically enabled in the
+ * Firmware by setting either AUTOEQUEQE or AUTOEQUIQE ...
+ */
+ if (dbqt)
+ c.timeren_timerix =
+ cpu_to_be32(FW_EQ_ETH_CMD_TIMEREN_F |
+ FW_EQ_ETH_CMD_TIMERIX_V(txq->dbqtimerix));
+
ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
if (ret) {
kfree(txq->q.sdesc);
@@ -3639,6 +3841,8 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
txq->txq = netdevq;
txq->tso = txq->tx_cso = txq->vlan_ins = 0;
txq->mapping_err = 0;
+ txq->dbqt = dbqt;
+
return 0;
}
@@ -3646,10 +3850,11 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
struct net_device *dev, unsigned int iqid,
unsigned int cmplqid)
{
- int ret, nentries;
- struct fw_eq_ctrl_cmd c;
- struct sge *s = &adap->sge;
+ unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
struct port_info *pi = netdev_priv(dev);
+ struct sge *s = &adap->sge;
+ struct fw_eq_ctrl_cmd c;
+ int ret, nentries;
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@ -3673,7 +3878,9 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
FW_EQ_CTRL_CMD_PCIECHN_V(pi->tx_chan) |
FW_EQ_CTRL_CMD_FETCHRO_F | FW_EQ_CTRL_CMD_IQID_V(iqid));
c.dcaen_to_eqsize =
- htonl(FW_EQ_CTRL_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) |
+ htonl(FW_EQ_CTRL_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
+ ? FETCHBURSTMIN_64B_X
+ : FETCHBURSTMIN_64B_T6_X) |
FW_EQ_CTRL_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
FW_EQ_CTRL_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
FW_EQ_CTRL_CMD_EQSIZE_V(nentries));
@@ -3713,6 +3920,7 @@ int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
struct net_device *dev, unsigned int iqid,
unsigned int uld_type)
{
+ unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
int ret, nentries;
struct fw_eq_ofld_cmd c;
struct sge *s = &adap->sge;
@@ -3743,7 +3951,9 @@ int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
FW_EQ_OFLD_CMD_PCIECHN_V(pi->tx_chan) |
FW_EQ_OFLD_CMD_FETCHRO_F | FW_EQ_OFLD_CMD_IQID_V(iqid));
c.dcaen_to_eqsize =
- htonl(FW_EQ_OFLD_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) |
+ htonl(FW_EQ_OFLD_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
+ ? FETCHBURSTMIN_64B_X
+ : FETCHBURSTMIN_64B_T6_X) |
FW_EQ_OFLD_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
FW_EQ_OFLD_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
FW_EQ_OFLD_CMD_EQSIZE_V(nentries));
diff --git a/drivers/net/ethernet/chelsio/cxgb4/smt.c b/drivers/net/ethernet/chelsio/cxgb4/smt.c
index 7b2207a2a130..eaf1fb74689c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/smt.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/smt.c
@@ -47,8 +47,7 @@ struct smt_data *t4_init_smt(void)
smt_size = SMT_SIZE;
- s = kvzalloc(sizeof(*s) + smt_size * sizeof(struct smt_entry),
- GFP_KERNEL);
+ s = kvzalloc(struct_size(s, smtab, smt_size), GFP_KERNEL);
if (!s)
return NULL;
s->smt_size = smt_size;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/srq.c b/drivers/net/ethernet/chelsio/cxgb4/srq.c
index 82b70a565e24..9a54302bb046 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/srq.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/srq.c
@@ -77,7 +77,7 @@ int cxgb4_get_srq_entry(struct net_device *dev,
adap = netdev2adap(dev);
s = adap->srq;
- if (!(adap->flags & FULL_INIT_DONE) || !s)
+ if (!(adap->flags & CXGB4_FULL_INIT_DONE) || !s)
goto out;
skb = alloc_skb(sizeof(*req), GFP_KERNEL);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index e8c34292a0ec..a3544041ad32 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -198,7 +198,7 @@ static void t4_report_fw_error(struct adapter *adap)
if (pcie_fw & PCIE_FW_ERR_F) {
dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n",
reason[PCIE_FW_EVAL_G(pcie_fw)]);
- adap->flags &= ~FW_OK;
+ adap->flags &= ~CXGB4_FW_OK;
}
}
@@ -3794,7 +3794,7 @@ int t4_load_phy_fw(struct adapter *adap,
/* If we have version number support, then check to see if the adapter
* already has up-to-date PHY firmware loaded.
*/
- if (phy_fw_version) {
+ if (phy_fw_version) {
new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size);
ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
if (ret < 0)
@@ -4105,6 +4105,9 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
* @mbox: the Firmware Mailbox to use
* @port: the Port ID
* @lc: the Port's Link Configuration
+ * @sleep_ok: if true we may sleep while awaiting command completion
+ * @timeout: time to wait for command to finish before timing out
+ * (negative implies @sleep_ok=false)
*
* Set up a port's MAC and PHY according to a desired link configuration.
* - If the PHY can auto-negotiate first decide what to advertise, then
@@ -4124,6 +4127,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
int ret;
fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps);
+
/* Convert driver coding of Pause Frame Flow Control settings into the
* Firmware's API.
*/
@@ -4143,8 +4147,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
fw_fec = cc_to_fwcap_fec(cc_fec);
/* Figure out what our Requested Port Capabilities are going to be.
+ * Note parallel structure in t4_handle_get_port_info() and
+ * init_link_config().
*/
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
+ if (lc->autoneg == AUTONEG_ENABLE)
+ return -EINVAL;
+
rcap = lc->acaps | fw_fc | fw_fec;
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec;
@@ -4156,7 +4165,11 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
}
- /* Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so
+ /* Some Requested Port Capabilities are trivially wrong if they exceed
+ * the Physical Port Capabilities. We can check that here and provide
+ * moderately useful feedback in the system log.
+ *
+ * Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so
* we need to exclude this from this check in order to maintain
* compatibility ...
*/
@@ -4185,6 +4198,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL,
sleep_ok, timeout);
+
+ /* Unfortunately, even if the Requested Port Capabilities "fit" within
+ * the Physical Port Capabilities, some combinations of features may
+ * still not be leagal. For example, 40Gb/s and Reed-Solomon Forward
+ * Error Correction. So if the Firmware rejects the L1 Configure
+ * request, flag that here.
+ */
if (ret) {
dev_err(adapter->pdev_dev,
"Requested Port Capabilities %#x rejected, error %d\n",
@@ -4942,7 +4962,13 @@ static void pl_intr_handler(struct adapter *adap)
*/
int t4_slow_intr_handler(struct adapter *adapter)
{
- u32 cause = t4_read_reg(adapter, PL_INT_CAUSE_A);
+ /* There are rare cases where a PL_INT_CAUSE bit may end up getting
+ * set when the corresponding PL_INT_ENABLE bit isn't set. It's
+ * easiest just to mask that case here.
+ */
+ u32 raw_cause = t4_read_reg(adapter, PL_INT_CAUSE_A);
+ u32 enable = t4_read_reg(adapter, PL_INT_ENABLE_A);
+ u32 cause = raw_cause & enable;
if (!(cause & GLBL_INTR_MASK))
return 0;
@@ -4994,7 +5020,7 @@ int t4_slow_intr_handler(struct adapter *adapter)
ulptx_intr_handler(adapter);
/* Clear the interrupts just processed for which we are the master. */
- t4_write_reg(adapter, PL_INT_CAUSE_A, cause & GLBL_INTR_MASK);
+ t4_write_reg(adapter, PL_INT_CAUSE_A, raw_cause & GLBL_INTR_MASK);
(void)t4_read_reg(adapter, PL_INT_CAUSE_A); /* flush */
return 1;
}
@@ -5217,7 +5243,7 @@ int t4_read_rss(struct adapter *adapter, u16 *map)
static unsigned int t4_use_ldst(struct adapter *adap)
{
- return (adap->flags & FW_OK) && !adap->use_bd;
+ return (adap->flags & CXGB4_FW_OK) && !adap->use_bd;
}
/**
@@ -6106,7 +6132,7 @@ unsigned int t4_get_mps_bg_map(struct adapter *adapter, int pidx)
* ( MPSBGMAP[Port 1] << 8 ) |
* ( MPSBGMAP[Port 0] << 0 ))
*/
- if (adapter->flags & FW_OK) {
+ if (adapter->flags & CXGB4_FW_OK) {
u32 param, val;
int ret;
@@ -6693,6 +6719,47 @@ int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type)
}
/**
+ * t4_read_sge_dbqtimers - reag SGE Doorbell Queue Timer values
+ * @adap - the adapter
+ * @ndbqtimers: size of the provided SGE Doorbell Queue Timer table
+ * @dbqtimers: SGE Doorbell Queue Timer table
+ *
+ * Reads the SGE Doorbell Queue Timer values into the provided table.
+ * Returns 0 on success (Firmware and Hardware support this feature),
+ * an error on failure.
+ */
+int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers,
+ u16 *dbqtimers)
+{
+ int ret, dbqtimerix;
+
+ ret = 0;
+ dbqtimerix = 0;
+ while (dbqtimerix < ndbqtimers) {
+ int nparams, param;
+ u32 params[7], vals[7];
+
+ nparams = ndbqtimers - dbqtimerix;
+ if (nparams > ARRAY_SIZE(params))
+ nparams = ARRAY_SIZE(params);
+
+ for (param = 0; param < nparams; param++)
+ params[param] =
+ (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMER) |
+ FW_PARAMS_PARAM_Y_V(dbqtimerix + param));
+ ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
+ nparams, params, vals);
+ if (ret)
+ break;
+
+ for (param = 0; param < nparams; param++)
+ dbqtimers[dbqtimerix++] = vals[param];
+ }
+ return ret;
+}
+
+/**
* t4_fw_hello - establish communication with FW
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -7026,10 +7093,10 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
if (!t4_fw_matches_chip(adap, fw_hdr))
return -EINVAL;
- /* Disable FW_OK flag so that mbox commands with FW_OK flag set
- * wont be sent when we are flashing FW.
+ /* Disable CXGB4_FW_OK flag so that mbox commands with CXGB4_FW_OK flag
+ * set wont be sent when we are flashing FW.
*/
- adap->flags &= ~FW_OK;
+ adap->flags &= ~CXGB4_FW_OK;
ret = t4_fw_halt(adap, mbox, force);
if (ret < 0 && !force)
@@ -7068,7 +7135,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
*/
(void)t4_init_devlog_params(adap);
out:
- adap->flags |= FW_OK;
+ adap->flags |= CXGB4_FW_OK;
return ret;
}
@@ -8461,6 +8528,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
fc = fwcap_to_cc_pause(linkattr);
speed = fwcap_to_speed(linkattr);
+ /* Reset state for communicating new Transceiver Module status and
+ * whether the OS-dependent layer wants us to redo the current
+ * "sticky" L1 Configure Link Parameters.
+ */
lc->new_module = false;
lc->redo_l1cfg = false;
@@ -8497,9 +8568,15 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
*/
pi->port_type = port_type;
+ /* Record new Module Type information.
+ */
pi->mod_type = mod_type;
+ /* Let the OS-dependent layer know if we have a new
+ * Transceiver Module inserted.
+ */
lc->new_module = t4_is_inserted_mod_type(mod_type);
+
t4_os_portmod_changed(adapter, pi->port_id);
}
@@ -8507,8 +8584,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
fc != lc->fc || fec != lc->fec) { /* something changed */
if (!link_ok && lc->link_ok) {
lc->link_down_rc = linkdnrc;
- dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n",
- pi->tx_chan, t4_link_down_rc_str(linkdnrc));
+ dev_warn_ratelimited(adapter->pdev_dev,
+ "Port %d link down, reason: %s\n",
+ pi->tx_chan,
+ t4_link_down_rc_str(linkdnrc));
}
lc->link_ok = link_ok;
lc->speed = speed;
@@ -8518,6 +8597,11 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
lc->lpacaps = lpacaps;
lc->acaps = acaps & ADVERT_MASK;
+ /* If we're not physically capable of Auto-Negotiation, note
+ * this as Auto-Negotiation disabled. Otherwise, we track
+ * what Auto-Negotiation settings we have. Note parallel
+ * structure in t4_link_l1cfg_core() and init_link_config().
+ */
if (!(lc->acaps & FW_PORT_CAP32_ANEG)) {
lc->autoneg = AUTONEG_DISABLE;
} else if (lc->acaps & FW_PORT_CAP32_ANEG) {
@@ -8535,6 +8619,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
t4_os_link_changed(adapter, pi->port_id, link_ok);
}
+ /* If we have a new Transceiver Module and the OS-dependent code has
+ * told us that it wants us to redo whatever "sticky" L1 Configuration
+ * Link Parameters are set, do that now.
+ */
if (lc->new_module && lc->redo_l1cfg) {
struct link_config old_lc;
int ret;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 361d5032c288..002fc62ea726 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -91,6 +91,7 @@ enum {
SGE_CTXT_SIZE = 24, /* size of SGE context */
SGE_NTIMERS = 6, /* # of interrupt holdoff timer values */
SGE_NCOUNTERS = 4, /* # of interrupt packet counter values */
+ SGE_NDBQTIMERS = 8, /* # of Doorbell Queue Timer values */
SGE_MAX_IQ_SIZE = 65520,
SGE_TIMER_RSTRT_CNTR = 6, /* restart RX packet threshold counter */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
index bf7325f6d553..0c5373462ced 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
@@ -218,6 +218,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
CH_PCI_ID_TABLE_FENTRY(0x6088), /* Custom T62100-CR */
CH_PCI_ID_TABLE_FENTRY(0x6089), /* Custom T62100-KR */
CH_PCI_ID_TABLE_FENTRY(0x608a), /* Custom T62100-CR */
+ CH_PCI_ID_TABLE_FENTRY(0x608b), /* Custom T6225-CR */
CH_PCI_DEVICE_ID_TABLE_DEFINE_END;
#endif /* __T4_PCI_ID_TBL_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
index f6558cbfc54e..eb1aa82149db 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
@@ -71,12 +71,18 @@
#define FETCHBURSTMIN_64B_X 2
#define FETCHBURSTMIN_128B_X 3
+/* T6 and later use a single-bit encoding for FetchBurstMin */
+#define FETCHBURSTMIN_64B_T6_X 0
+#define FETCHBURSTMIN_128B_T6_X 1
+
#define FETCHBURSTMAX_256B_X 2
#define FETCHBURSTMAX_512B_X 3
+#define HOSTFCMODE_INGRESS_QUEUE_X 1
#define HOSTFCMODE_STATUS_PAGE_X 2
#define CIDXFLUSHTHRESH_32_X 5
+#define CIDXFLUSHTHRESH_128_X 7
#define UPDATEDELIVERY_INTERRUPT_X 1
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 1d9b3e1e5f94..b2a618e72fcf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1254,6 +1254,8 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_RDMA_WRITE_WITH_IMM = 0x21,
FW_PARAMS_PARAM_DEV_RI_WRITE_CMPL_WR = 0x24,
FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27,
+ FW_PARAMS_PARAM_DEV_DBQ_TIMER = 0x29,
+ FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK = 0x2A,
};
/*
@@ -1310,6 +1312,14 @@ enum fw_params_param_pfvf {
FW_PARAMS_PARAM_PFVF_RAWF_END = 0x37,
FW_PARAMS_PARAM_PFVF_NCRYPTO_LOOKASIDE = 0x39,
FW_PARAMS_PARAM_PFVF_PORT_CAPS32 = 0x3A,
+ FW_PARAMS_PARAM_PFVF_LINK_STATE = 0x40,
+};
+
+/* Virtual link state as seen by the specified VF */
+enum vf_link_states {
+ FW_VF_LINK_STATE_AUTO = 0x00,
+ FW_VF_LINK_STATE_ENABLE = 0x01,
+ FW_VF_LINK_STATE_DISABLE = 0x02,
};
/*
@@ -1322,6 +1332,7 @@ enum fw_params_param_dmaq {
FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11,
FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12,
FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13,
+ FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX = 0x15,
FW_PARAMS_PARAM_DMAQ_CONM_CTXT = 0x20,
};
@@ -1751,8 +1762,8 @@ struct fw_eq_eth_cmd {
__be32 fetchszm_to_iqid;
__be32 dcaen_to_eqsize;
__be64 eqaddr;
- __be32 viid_pkd;
- __be32 r8_lo;
+ __be32 autoequiqe_to_viid;
+ __be32 timeren_timerix;
__be64 r9;
};
@@ -1847,6 +1858,10 @@ struct fw_eq_eth_cmd {
#define FW_EQ_ETH_CMD_EQSIZE_S 0
#define FW_EQ_ETH_CMD_EQSIZE_V(x) ((x) << FW_EQ_ETH_CMD_EQSIZE_S)
+#define FW_EQ_ETH_CMD_AUTOEQUIQE_S 31
+#define FW_EQ_ETH_CMD_AUTOEQUIQE_V(x) ((x) << FW_EQ_ETH_CMD_AUTOEQUIQE_S)
+#define FW_EQ_ETH_CMD_AUTOEQUIQE_F FW_EQ_ETH_CMD_AUTOEQUIQE_V(1U)
+
#define FW_EQ_ETH_CMD_AUTOEQUEQE_S 30
#define FW_EQ_ETH_CMD_AUTOEQUEQE_V(x) ((x) << FW_EQ_ETH_CMD_AUTOEQUEQE_S)
#define FW_EQ_ETH_CMD_AUTOEQUEQE_F FW_EQ_ETH_CMD_AUTOEQUEQE_V(1U)
@@ -1854,6 +1869,19 @@ struct fw_eq_eth_cmd {
#define FW_EQ_ETH_CMD_VIID_S 16
#define FW_EQ_ETH_CMD_VIID_V(x) ((x) << FW_EQ_ETH_CMD_VIID_S)
+#define FW_EQ_ETH_CMD_TIMEREN_S 3
+#define FW_EQ_ETH_CMD_TIMEREN_M 0x1
+#define FW_EQ_ETH_CMD_TIMEREN_V(x) ((x) << FW_EQ_ETH_CMD_TIMEREN_S)
+#define FW_EQ_ETH_CMD_TIMEREN_G(x) \
+ (((x) >> FW_EQ_ETH_CMD_TIMEREN_S) & FW_EQ_ETH_CMD_TIMEREN_M)
+#define FW_EQ_ETH_CMD_TIMEREN_F FW_EQ_ETH_CMD_TIMEREN_V(1U)
+
+#define FW_EQ_ETH_CMD_TIMERIX_S 0
+#define FW_EQ_ETH_CMD_TIMERIX_M 0x7
+#define FW_EQ_ETH_CMD_TIMERIX_V(x) ((x) << FW_EQ_ETH_CMD_TIMERIX_S)
+#define FW_EQ_ETH_CMD_TIMERIX_G(x) \
+ (((x) >> FW_EQ_ETH_CMD_TIMERIX_S) & FW_EQ_ETH_CMD_TIMERIX_M)
+
struct fw_eq_ctrl_cmd {
__be32 op_to_vfn;
__be32 alloc_to_len16;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
index a844296135b4..9125ddd89dd1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
@@ -36,8 +36,8 @@
#define __T4FW_VERSION_H__
#define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x14
-#define T4FW_VERSION_MICRO 0x08
+#define T4FW_VERSION_MINOR 0x16
+#define T4FW_VERSION_MICRO 0x09
#define T4FW_VERSION_BUILD 0x00
#define T4FW_MIN_VERSION_MAJOR 0x01
@@ -45,8 +45,8 @@
#define T4FW_MIN_VERSION_MICRO 0x00
#define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x14
-#define T5FW_VERSION_MICRO 0x08
+#define T5FW_VERSION_MINOR 0x16
+#define T5FW_VERSION_MICRO 0x09
#define T5FW_VERSION_BUILD 0x00
#define T5FW_MIN_VERSION_MAJOR 0x00
@@ -54,8 +54,8 @@
#define T5FW_MIN_VERSION_MICRO 0x00
#define T6FW_VERSION_MAJOR 0x01
-#define T6FW_VERSION_MINOR 0x14
-#define T6FW_VERSION_MICRO 0x08
+#define T6FW_VERSION_MINOR 0x16
+#define T6FW_VERSION_MICRO 0x09
#define T6FW_VERSION_BUILD 0x00
#define T6FW_MIN_VERSION_MAJOR 0x00
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
index 5883f09e3804..3782e48dada2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
@@ -94,7 +94,7 @@ struct port_info {
struct adapter *adapter; /* our adapter */
u32 vlan_id; /* vlan id for VST */
u16 viid; /* virtual interface ID */
- s16 xact_addr_filt; /* index of our MAC address filter */
+ int xact_addr_filt; /* index of our MAC address filter */
u16 rss_size; /* size of VI's RSS table slice */
u8 pidx; /* index into adapter port[] */
s8 mdio_addr;
@@ -352,6 +352,7 @@ struct sge {
struct hash_mac_addr {
struct list_head list;
u8 addr[ETH_ALEN];
+ unsigned int iface_mac;
};
struct mbox_list {
@@ -405,11 +406,12 @@ struct adapter {
};
enum { /* adapter flags */
- FULL_INIT_DONE = (1UL << 0),
- USING_MSI = (1UL << 1),
- USING_MSIX = (1UL << 2),
- QUEUES_BOUND = (1UL << 3),
- ROOT_NO_RELAXED_ORDERING = (1UL << 4),
+ CXGB4VF_FULL_INIT_DONE = (1UL << 0),
+ CXGB4VF_USING_MSI = (1UL << 1),
+ CXGB4VF_USING_MSIX = (1UL << 2),
+ CXGB4VF_QUEUES_BOUND = (1UL << 3),
+ CXGB4VF_ROOT_NO_RELAXED_ORDERING = (1UL << 4),
+ CXGB4VF_FW_OK = (1UL << 5),
};
/*
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 2fab87e86561..adc4d481815b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -155,6 +155,8 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
const char *fc;
const struct port_info *pi = netdev_priv(dev);
+ netif_carrier_on(dev);
+
switch (pi->link_cfg.speed) {
case 100:
s = "100Mbps";
@@ -200,6 +202,7 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, fc);
} else {
+ netif_carrier_off(dev);
netdev_info(dev, "link down\n");
}
}
@@ -236,6 +239,73 @@ void t4vf_os_portmod_changed(struct adapter *adapter, int pidx)
"inserted\n", dev->name, pi->mod_type);
}
+static int cxgb4vf_set_addr_hash(struct port_info *pi)
+{
+ struct adapter *adapter = pi->adapter;
+ u64 vec = 0;
+ bool ucast = false;
+ struct hash_mac_addr *entry;
+
+ /* Calculate the hash vector for the updated list and program it */
+ list_for_each_entry(entry, &adapter->mac_hlist, list) {
+ ucast |= is_unicast_ether_addr(entry->addr);
+ vec |= (1ULL << hash_mac_addr(entry->addr));
+ }
+ return t4vf_set_addr_hash(adapter, pi->viid, ucast, vec, false);
+}
+
+/**
+ * cxgb4vf_change_mac - Update match filter for a MAC address.
+ * @pi: the port_info
+ * @viid: the VI id
+ * @tcam_idx: TCAM index of existing filter for old value of MAC address,
+ * or -1
+ * @addr: the new MAC address value
+ * @persist: whether a new MAC allocation should be persistent
+ * @add_smt: if true also add the address to the HW SMT
+ *
+ * Modifies an MPS filter and sets it to the new MAC address if
+ * @tcam_idx >= 0, or adds the MAC address to a new filter if
+ * @tcam_idx < 0. In the latter case the address is added persistently
+ * if @persist is %true.
+ * Addresses are programmed to hash region, if tcam runs out of entries.
+ *
+ */
+static int cxgb4vf_change_mac(struct port_info *pi, unsigned int viid,
+ int *tcam_idx, const u8 *addr, bool persistent)
+{
+ struct hash_mac_addr *new_entry, *entry;
+ struct adapter *adapter = pi->adapter;
+ int ret;
+
+ ret = t4vf_change_mac(adapter, viid, *tcam_idx, addr, persistent);
+ /* We ran out of TCAM entries. try programming hash region. */
+ if (ret == -ENOMEM) {
+ /* If the MAC address to be updated is in the hash addr
+ * list, update it from the list
+ */
+ list_for_each_entry(entry, &adapter->mac_hlist, list) {
+ if (entry->iface_mac) {
+ ether_addr_copy(entry->addr, addr);
+ goto set_hash;
+ }
+ }
+ new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+ if (!new_entry)
+ return -ENOMEM;
+ ether_addr_copy(new_entry->addr, addr);
+ new_entry->iface_mac = true;
+ list_add_tail(&new_entry->list, &adapter->mac_hlist);
+set_hash:
+ ret = cxgb4vf_set_addr_hash(pi);
+ } else if (ret >= 0) {
+ *tcam_idx = ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
/*
* Net device operations.
* ======================
@@ -259,14 +329,10 @@ static int link_start(struct net_device *dev)
*/
ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, 1,
true);
- if (ret == 0) {
- ret = t4vf_change_mac(pi->adapter, pi->viid,
- pi->xact_addr_filt, dev->dev_addr, true);
- if (ret >= 0) {
- pi->xact_addr_filt = ret;
- ret = 0;
- }
- }
+ if (ret == 0)
+ ret = cxgb4vf_change_mac(pi, pi->viid,
+ &pi->xact_addr_filt,
+ dev->dev_addr, true);
/*
* We don't need to actually "start the link" itself since the
@@ -276,16 +342,6 @@ static int link_start(struct net_device *dev)
if (ret == 0)
ret = t4vf_enable_pi(pi->adapter, pi, true, true);
- /* The Virtual Interfaces are connected to an internal switch on the
- * chip which allows VIs attached to the same port to talk to each
- * other even when the port link is down. As a result, we generally
- * want to always report a VI's link as being "up", provided there are
- * no errors in enabling vi.
- */
-
- if (ret == 0)
- netif_carrier_on(dev);
-
return ret;
}
@@ -406,7 +462,7 @@ static void enable_rx(struct adapter *adapter)
* The interrupt queue doesn't use NAPI so we do the 0-increment of
* its Going To Sleep register here to get it started.
*/
- if (adapter->flags & USING_MSI)
+ if (adapter->flags & CXGB4VF_USING_MSI)
t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
CIDXINC_V(0) |
SEINTARM_V(s->intrq.intr_params) |
@@ -550,7 +606,7 @@ static int setup_sge_queues(struct adapter *adapter)
* the intrq's queue ID as the interrupt forwarding queue for the
* subsequent calls ...
*/
- if (adapter->flags & USING_MSI) {
+ if (adapter->flags & CXGB4VF_USING_MSI) {
err = t4vf_sge_alloc_rxq(adapter, &s->intrq, false,
adapter->port[0], 0, NULL, NULL);
if (err)
@@ -710,7 +766,7 @@ static int adapter_up(struct adapter *adapter)
* adapter setup. Once we've done this, many of our adapter
* parameters can no longer be changed ...
*/
- if ((adapter->flags & FULL_INIT_DONE) == 0) {
+ if ((adapter->flags & CXGB4VF_FULL_INIT_DONE) == 0) {
err = setup_sge_queues(adapter);
if (err)
return err;
@@ -720,17 +776,18 @@ static int adapter_up(struct adapter *adapter)
return err;
}
- if (adapter->flags & USING_MSIX)
+ if (adapter->flags & CXGB4VF_USING_MSIX)
name_msix_vecs(adapter);
- adapter->flags |= FULL_INIT_DONE;
+ adapter->flags |= CXGB4VF_FULL_INIT_DONE;
}
/*
* Acquire our interrupt resources. We only support MSI-X and MSI.
*/
- BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
- if (adapter->flags & USING_MSIX)
+ BUG_ON((adapter->flags &
+ (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0);
+ if (adapter->flags & CXGB4VF_USING_MSIX)
err = request_msix_queue_irqs(adapter);
else
err = request_irq(adapter->pdev->irq,
@@ -761,7 +818,7 @@ static void adapter_down(struct adapter *adapter)
/*
* Free interrupt resources.
*/
- if (adapter->flags & USING_MSIX)
+ if (adapter->flags & CXGB4VF_USING_MSIX)
free_msix_queue_irqs(adapter);
else
free_irq(adapter->pdev->irq, adapter);
@@ -782,6 +839,13 @@ static int cxgb4vf_open(struct net_device *dev)
struct adapter *adapter = pi->adapter;
/*
+ * If we don't have a connection to the firmware there's nothing we
+ * can do.
+ */
+ if (!(adapter->flags & CXGB4VF_FW_OK))
+ return -ENXIO;
+
+ /*
* If this is the first interface that we're opening on the "adapter",
* bring the "adapter" up now.
*/
@@ -791,6 +855,13 @@ static int cxgb4vf_open(struct net_device *dev)
return err;
}
+ /* It's possible that the basic port information could have
+ * changed since we first read it.
+ */
+ err = t4vf_update_port_info(pi);
+ if (err < 0)
+ return err;
+
/*
* Note that this interface is up and start everything up ...
*/
@@ -863,21 +934,6 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
return ns;
}
-static inline int cxgb4vf_set_addr_hash(struct port_info *pi)
-{
- struct adapter *adapter = pi->adapter;
- u64 vec = 0;
- bool ucast = false;
- struct hash_mac_addr *entry;
-
- /* Calculate the hash vector for the updated list and program it */
- list_for_each_entry(entry, &adapter->mac_hlist, list) {
- ucast |= is_unicast_ether_addr(entry->addr);
- vec |= (1ULL << hash_mac_addr(entry->addr));
- }
- return t4vf_set_addr_hash(adapter, pi->viid, ucast, vec, false);
-}
-
static int cxgb4vf_mac_sync(struct net_device *netdev, const u8 *mac_addr)
{
struct port_info *pi = netdev_priv(netdev);
@@ -1159,13 +1215,12 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- ret = t4vf_change_mac(pi->adapter, pi->viid, pi->xact_addr_filt,
- addr->sa_data, true);
+ ret = cxgb4vf_change_mac(pi, pi->viid, &pi->xact_addr_filt,
+ addr->sa_data, true);
if (ret < 0)
return ret;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- pi->xact_addr_filt = ret;
return 0;
}
@@ -1179,7 +1234,7 @@ static void cxgb4vf_poll_controller(struct net_device *dev)
struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter;
- if (adapter->flags & USING_MSIX) {
+ if (adapter->flags & CXGB4VF_USING_MSIX) {
struct sge_eth_rxq *rxq;
int nqsets;
@@ -1354,7 +1409,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
case FW_PORT_TYPE_CR4_QSFP:
SET_LMM(FIBRE);
FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
- FW_CAPS_TO_LMM(SPEED_10G, 10000baseSR_Full);
+ FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
@@ -1365,6 +1420,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
break;
}
+ if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) {
+ FW_CAPS_TO_LMM(FEC_RS, FEC_RS);
+ FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER);
+ } else {
+ SET_LMM(FEC_NONE);
+ }
+
FW_CAPS_TO_LMM(ANEG, Autoneg);
FW_CAPS_TO_LMM(802_3_PAUSE, Pause);
FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause);
@@ -1587,7 +1649,7 @@ static int cxgb4vf_set_ringparam(struct net_device *dev,
rp->tx_pending < MIN_TXQ_ENTRIES)
return -EINVAL;
- if (adapter->flags & FULL_INIT_DONE)
+ if (adapter->flags & CXGB4VF_FULL_INIT_DONE)
return -EBUSY;
for (qs = pi->first_qset; qs < pi->first_qset + pi->nqsets; qs++) {
@@ -1871,6 +1933,8 @@ static void cxgb4vf_get_wol(struct net_device *dev,
* TCP Segmentation Offload flags which we support.
*/
#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
+ NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
static const struct ethtool_ops cxgb4vf_ethtool_ops = {
.get_link_ksettings = cxgb4vf_get_link_ksettings,
@@ -2102,7 +2166,7 @@ static int sge_qinfo_show(struct seq_file *seq, void *v)
static int sge_queue_entries(const struct adapter *adapter)
{
return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 +
- ((adapter->flags & USING_MSI) != 0);
+ ((adapter->flags & CXGB4VF_USING_MSI) != 0);
}
static void *sge_queue_start(struct seq_file *seq, loff_t *pos)
@@ -2248,7 +2312,7 @@ static int sge_qstats_show(struct seq_file *seq, void *v)
static int sge_qstats_entries(const struct adapter *adapter)
{
return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 +
- ((adapter->flags & USING_MSI) != 0);
+ ((adapter->flags & CXGB4VF_USING_MSI) != 0);
}
static void *sge_qstats_start(struct seq_file *seq, loff_t *pos)
@@ -2657,6 +2721,7 @@ static int adap_init0(struct adapter *adapter)
*/
size_nports_qsets(adapter);
+ adapter->flags |= CXGB4VF_FW_OK;
return 0;
}
@@ -2691,7 +2756,8 @@ static void cfg_queues(struct adapter *adapter)
* support. In particular, this means that we need to know what kind
* of interrupts we'll be using ...
*/
- BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
+ BUG_ON((adapter->flags &
+ (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0);
/*
* Count the number of 10GbE Virtual Interfaces that we have.
@@ -3017,11 +3083,13 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
* using Relaxed Ordering.
*/
if (!pcie_relaxed_ordering_enabled(pdev))
- adapter->flags |= ROOT_NO_RELAXED_ORDERING;
+ adapter->flags |= CXGB4VF_ROOT_NO_RELAXED_ORDERING;
err = adap_init0(adapter);
if (err)
- goto err_unmap_bar;
+ dev_err(&pdev->dev,
+ "Adapter initialization failed, error %d. Continuing in debug mode\n",
+ err);
/* Initialize hash mac addr list */
INIT_LIST_HEAD(&adapter->mac_hlist);
@@ -3046,13 +3114,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
break;
port_id = ffs(pmask) - 1;
pmask &= ~(1 << port_id);
- viid = t4vf_alloc_vi(adapter, port_id);
- if (viid < 0) {
- dev_err(&pdev->dev, "cannot allocate VI for port %d:"
- " err=%d\n", port_id, viid);
- err = viid;
- goto err_free_dev;
- }
/*
* Allocate our network device and stitch things together.
@@ -3060,7 +3121,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
netdev = alloc_etherdev_mq(sizeof(struct port_info),
MAX_PORT_QSETS);
if (netdev == NULL) {
- t4vf_free_vi(adapter, viid);
err = -ENOMEM;
goto err_free_dev;
}
@@ -3070,26 +3130,21 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
pi->adapter = adapter;
pi->pidx = pidx;
pi->port_id = port_id;
- pi->viid = viid;
/*
* Initialize the starting state of our "port" and register
* it.
*/
pi->xact_addr_filt = -1;
- netif_carrier_off(netdev);
netdev->irq = pdev->irq;
- netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_RXCSUM;
- netdev->vlan_features = NETIF_F_SG | TSO_FLAGS |
- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_HIGHDMA;
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_CTAG_TX;
+ netdev->hw_features = NETIF_F_SG | TSO_FLAGS | NETIF_F_GRO |
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+ netdev->features = netdev->hw_features;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features = netdev->features & VLAN_FEAT;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->min_mtu = 81;
@@ -3100,6 +3155,23 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
netdev->dev_port = pi->port_id;
/*
+ * If we haven't been able to contact the firmware, there's
+ * nothing else we can do for this "port" ...
+ */
+ if (!(adapter->flags & CXGB4VF_FW_OK))
+ continue;
+
+ viid = t4vf_alloc_vi(adapter, port_id);
+ if (viid < 0) {
+ dev_err(&pdev->dev,
+ "cannot allocate VI for port %d: err=%d\n",
+ port_id, viid);
+ err = viid;
+ goto err_free_dev;
+ }
+ pi->viid = viid;
+
+ /*
* Initialize the hardware/software state for the port.
*/
err = t4vf_port_init(adapter, pidx);
@@ -3136,7 +3208,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
* get MSI interrupts we bail with the error.
*/
if (msi == MSI_MSIX && enable_msix(adapter) == 0)
- adapter->flags |= USING_MSIX;
+ adapter->flags |= CXGB4VF_USING_MSIX;
else {
if (msi == MSI_MSIX) {
dev_info(adapter->pdev_dev,
@@ -3156,7 +3228,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
" err=%d\n", err);
goto err_free_dev;
}
- adapter->flags |= USING_MSI;
+ adapter->flags |= CXGB4VF_USING_MSI;
}
/* Now that we know how many "ports" we have and what interrupt
@@ -3186,6 +3258,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
continue;
}
+ netif_carrier_off(netdev);
set_bit(pidx, &adapter->registered_device_map);
}
if (adapter->registered_device_map == 0) {
@@ -3214,8 +3287,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
for_each_port(adapter, pidx) {
dev_info(adapter->pdev_dev, "%s: Chelsio VF NIC PCIe %s\n",
adapter->port[pidx]->name,
- (adapter->flags & USING_MSIX) ? "MSI-X" :
- (adapter->flags & USING_MSI) ? "MSI" : "");
+ (adapter->flags & CXGB4VF_USING_MSIX) ? "MSI-X" :
+ (adapter->flags & CXGB4VF_USING_MSI) ? "MSI" : "");
}
/*
@@ -3228,12 +3301,12 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
* so far and return the error.
*/
err_disable_interrupts:
- if (adapter->flags & USING_MSIX) {
+ if (adapter->flags & CXGB4VF_USING_MSIX) {
pci_disable_msix(adapter->pdev);
- adapter->flags &= ~USING_MSIX;
- } else if (adapter->flags & USING_MSI) {
+ adapter->flags &= ~CXGB4VF_USING_MSIX;
+ } else if (adapter->flags & CXGB4VF_USING_MSI) {
pci_disable_msi(adapter->pdev);
- adapter->flags &= ~USING_MSI;
+ adapter->flags &= ~CXGB4VF_USING_MSI;
}
err_free_dev:
@@ -3242,13 +3315,13 @@ err_free_dev:
if (netdev == NULL)
continue;
pi = netdev_priv(netdev);
- t4vf_free_vi(adapter, pi->viid);
+ if (pi->viid)
+ t4vf_free_vi(adapter, pi->viid);
if (test_bit(pidx, &adapter->registered_device_map))
unregister_netdev(netdev);
free_netdev(netdev);
}
-err_unmap_bar:
if (!is_t4(adapter->params.chip))
iounmap(adapter->bar2);
@@ -3293,12 +3366,12 @@ static void cxgb4vf_pci_remove(struct pci_dev *pdev)
if (test_bit(pidx, &adapter->registered_device_map))
unregister_netdev(adapter->port[pidx]);
t4vf_sge_stop(adapter);
- if (adapter->flags & USING_MSIX) {
+ if (adapter->flags & CXGB4VF_USING_MSIX) {
pci_disable_msix(adapter->pdev);
- adapter->flags &= ~USING_MSIX;
- } else if (adapter->flags & USING_MSI) {
+ adapter->flags &= ~CXGB4VF_USING_MSIX;
+ } else if (adapter->flags & CXGB4VF_USING_MSI) {
pci_disable_msi(adapter->pdev);
- adapter->flags &= ~USING_MSI;
+ adapter->flags &= ~CXGB4VF_USING_MSI;
}
/*
@@ -3321,7 +3394,8 @@ static void cxgb4vf_pci_remove(struct pci_dev *pdev)
continue;
pi = netdev_priv(netdev);
- t4vf_free_vi(adapter, pi->viid);
+ if (pi->viid)
+ t4vf_free_vi(adapter, pi->viid);
free_netdev(netdev);
}
iounmap(adapter->regs);
@@ -3369,12 +3443,12 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
* Interrupts allowing various internal pathways to drain.
*/
t4vf_sge_stop(adapter);
- if (adapter->flags & USING_MSIX) {
+ if (adapter->flags & CXGB4VF_USING_MSIX) {
pci_disable_msix(adapter->pdev);
- adapter->flags &= ~USING_MSIX;
- } else if (adapter->flags & USING_MSI) {
+ adapter->flags &= ~CXGB4VF_USING_MSIX;
+ } else if (adapter->flags & CXGB4VF_USING_MSI) {
pci_disable_msi(adapter->pdev);
- adapter->flags &= ~USING_MSI;
+ adapter->flags &= ~CXGB4VF_USING_MSI;
}
/*
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index 3007e1ac1e61..f71c973398ec 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -756,7 +756,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize,
* Allocate the hardware ring and PCI DMA bus address space for said.
*/
size_t hwlen = nelem * hwsize + stat_size;
- void *hwring = dma_zalloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
+ void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
if (!hwring)
return NULL;
@@ -2044,8 +2044,9 @@ static irqreturn_t t4vf_intr_msi(int irq, void *cookie)
*/
irq_handler_t t4vf_intr_handler(struct adapter *adapter)
{
- BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
- if (adapter->flags & USING_MSIX)
+ BUG_ON((adapter->flags &
+ (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0);
+ if (adapter->flags & CXGB4VF_USING_MSIX)
return t4vf_sge_intr_msix;
else
return t4vf_intr_msi;
@@ -2209,7 +2210,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
struct port_info *pi = netdev_priv(dev);
struct fw_iq_cmd cmd, rpl;
int ret, iqandst, flsz = 0;
- int relaxed = !(adapter->flags & ROOT_NO_RELAXED_ORDERING);
+ int relaxed = !(adapter->flags & CXGB4VF_ROOT_NO_RELAXED_ORDERING);
/*
* If we're using MSI interrupts and we're not initializing the
@@ -2218,7 +2219,8 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
* the Forwarded Interrupt Queue must be set up before any other
* ingress queue ...
*/
- if ((adapter->flags & USING_MSI) && rspq != &adapter->sge.intrq) {
+ if ((adapter->flags & CXGB4VF_USING_MSI) &&
+ rspq != &adapter->sge.intrq) {
iqandst = SGE_INTRDST_IQ;
intr_dest = adapter->sge.intrq.abs_id;
} else
@@ -2268,7 +2270,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
cmd.iqaddr = cpu_to_be64(rspq->phys_addr);
if (fl) {
- enum chip_type chip =
+ unsigned int chip_ver =
CHELSIO_CHIP_VERSION(adapter->params.chip);
/*
* Allocate the ring for the hardware free list (with space
@@ -2319,10 +2321,10 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
*/
cmd.fl0dcaen_to_fl0cidxfthresh =
cpu_to_be16(
- FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ?
- FETCHBURSTMIN_128B_X :
- FETCHBURSTMIN_64B_X) |
- FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ?
+ FW_IQ_CMD_FL0FBMIN_V(chip_ver <= CHELSIO_T5
+ ? FETCHBURSTMIN_128B_X
+ : FETCHBURSTMIN_64B_T6_X) |
+ FW_IQ_CMD_FL0FBMAX_V((chip_ver <= CHELSIO_T5) ?
FETCHBURSTMAX_512B_X :
FETCHBURSTMAX_256B_X));
cmd.fl0size = cpu_to_be16(flsz);
@@ -2411,10 +2413,11 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
struct net_device *dev, struct netdev_queue *devq,
unsigned int iqid)
{
+ unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip);
+ struct port_info *pi = netdev_priv(dev);
+ struct fw_eq_eth_cmd cmd, rpl;
struct sge *s = &adapter->sge;
int ret, nentries;
- struct fw_eq_eth_cmd cmd, rpl;
- struct port_info *pi = netdev_priv(dev);
/*
* Calculate the size of the hardware TX Queue (including the Status
@@ -2448,17 +2451,19 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC_F |
FW_EQ_ETH_CMD_EQSTART_F |
FW_LEN16(cmd));
- cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE_F |
- FW_EQ_ETH_CMD_VIID_V(pi->viid));
+ cmd.autoequiqe_to_viid = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE_F |
+ FW_EQ_ETH_CMD_VIID_V(pi->viid));
cmd.fetchszm_to_iqid =
cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE_V(SGE_HOSTFCMODE_STPG) |
FW_EQ_ETH_CMD_PCIECHN_V(pi->port_id) |
FW_EQ_ETH_CMD_IQID_V(iqid));
cmd.dcaen_to_eqsize =
- cpu_to_be32(FW_EQ_ETH_CMD_FBMIN_V(SGE_FETCHBURSTMIN_64B) |
- FW_EQ_ETH_CMD_FBMAX_V(SGE_FETCHBURSTMAX_512B) |
+ cpu_to_be32(FW_EQ_ETH_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
+ ? FETCHBURSTMIN_64B_X
+ : FETCHBURSTMIN_64B_T6_X) |
+ FW_EQ_ETH_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
FW_EQ_ETH_CMD_CIDXFTHRESH_V(
- SGE_CIDXFLUSHTHRESH_32) |
+ CIDXFLUSHTHRESH_32_X) |
FW_EQ_ETH_CMD_EQSIZE_V(nentries));
cmd.eqaddr = cpu_to_be64(txq->q.phys_addr);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index 5b8c08cf523f..84dff74ca9cd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -2005,8 +2005,10 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
fc != lc->fc || fec != lc->fec) { /* something changed */
if (!link_ok && lc->link_ok) {
lc->link_down_rc = linkdnrc;
- dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n",
- pi->port_id, t4vf_link_down_rc_str(linkdnrc));
+ dev_warn_ratelimited(adapter->pdev_dev,
+ "Port %d link down, reason: %s\n",
+ pi->port_id,
+ t4vf_link_down_rc_str(linkdnrc));
}
lc->link_ok = link_ok;
lc->speed = speed;
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c
index 99038dfc7fbe..9900993b6aea 100644
--- a/drivers/net/ethernet/cisco/enic/enic_clsf.c
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c
@@ -32,7 +32,8 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
break;
default:
return -EPROTONOSUPPORT;
- };
+ }
+
data.type = FILTER_IPV4_5TUPLE;
data.u.ipv4.src_addr = ntohl(keys->addrs.v4addrs.src);
data.u.ipv4.dst_addr = ntohl(keys->addrs.v4addrs.dst);
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 60641e202534..9a7f70db20c7 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1434,7 +1434,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
* csum is correct or is zero.
*/
if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
- tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) {
+ tcp_udp_csum_ok && outer_csum_ok &&
+ (ipv4_csum_ok || ipv6)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->csum_level = encap;
}
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 0a82fcf16d35..c2586f44c29d 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -395,6 +395,7 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
case 3:
dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");
+ /* fall through */
case 2:
db->dumpblk = dm9000_dumpblk_16bit;
db->outblk = dm9000_outblk_16bit;
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 13430f75496c..f1a2da15dd0a 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -585,7 +585,7 @@ static void de_tx (struct de_private *de)
netif_dbg(de, tx_done, de->dev,
"tx done, slot %d\n", tx_tail);
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
next:
diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
index 1812f4916917..ba0a69b363f8 100644
--- a/drivers/net/ethernet/dec/tulip/eeprom.c
+++ b/drivers/net/ethernet/dec/tulip/eeprom.c
@@ -224,9 +224,7 @@ subsequent_board:
return;
}
- mtable = kmalloc(sizeof(struct mediatable) +
- count * sizeof(struct medialeaf),
- GFP_KERNEL);
+ mtable = kmalloc(struct_size(mtable, mleaf, count), GFP_KERNEL);
if (mtable == NULL)
return; /* Horrible, impossible failure. */
last_mediatable = tp->mtable = mtable;
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index d8d423f22c4f..cfcdfee718b0 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -843,9 +843,9 @@ rio_free_tx (struct net_device *dev, int irq)
desc_to_dma(&np->tx_ring[entry]),
skb->len, PCI_DMA_TODEVICE);
if (irq)
- dev_kfree_skb_irq (skb);
+ dev_consume_skb_irq(skb);
else
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
np->tx_skbuff[entry] = NULL;
entry = (entry + 1) % TX_RING_SIZE;
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 1a27176381fb..4a37a69764ce 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -1193,7 +1193,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
int handled = 0;
int i;
-
do {
int intr_status = ioread16(ioaddr + IntrStatus);
iowrite16(intr_status, ioaddr + IntrStatus);
@@ -1286,7 +1285,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[entry].frag[0].addr),
skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq (np->tx_skbuff[entry]);
+ dev_consume_skb_irq(np->tx_skbuff[entry]);
np->tx_skbuff[entry] = NULL;
np->tx_ring[entry].frag[0].addr = 0;
np->tx_ring[entry].frag[0].length = 0;
@@ -1305,7 +1304,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[entry].frag[0].addr),
skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq (np->tx_skbuff[entry]);
+ dev_consume_skb_irq(np->tx_skbuff[entry]);
np->tx_skbuff[entry] = NULL;
np->tx_ring[entry].frag[0].addr = 0;
np->tx_ring[entry].frag[0].length = 0;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 1e9d882c04ef..59a7f0b99069 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1808,9 +1808,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
total_size = buf_len;
get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
- get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- get_fat_cmd.size,
- &get_fat_cmd.dma, GFP_ATOMIC);
+ get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ get_fat_cmd.size,
+ &get_fat_cmd.dma, GFP_ATOMIC);
if (!get_fat_cmd.va)
return -ENOMEM;
@@ -2302,8 +2302,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
return -EINVAL;
cmd.size = sizeof(struct be_cmd_resp_port_type);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va) {
dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
return -ENOMEM;
@@ -3066,8 +3066,8 @@ int lancer_fw_download(struct be_adapter *adapter,
flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
+ LANCER_FW_DOWNLOAD_CHUNK;
- flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
- &flash_cmd.dma, GFP_KERNEL);
+ flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+ GFP_KERNEL);
if (!flash_cmd.va)
return -ENOMEM;
@@ -3184,8 +3184,8 @@ int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
}
flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
- flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
- GFP_KERNEL);
+ flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+ GFP_KERNEL);
if (!flash_cmd.va)
return -ENOMEM;
@@ -3435,8 +3435,8 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
goto err;
}
cmd.size = sizeof(struct be_cmd_req_get_phy_info);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va) {
dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
status = -ENOMEM;
@@ -3522,9 +3522,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
- attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- attribs_cmd.size,
- &attribs_cmd.dma, GFP_ATOMIC);
+ attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ attribs_cmd.size,
+ &attribs_cmd.dma, GFP_ATOMIC);
if (!attribs_cmd.va) {
dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
status = -ENOMEM;
@@ -3699,10 +3699,10 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
- get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- get_mac_list_cmd.size,
- &get_mac_list_cmd.dma,
- GFP_ATOMIC);
+ get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ get_mac_list_cmd.size,
+ &get_mac_list_cmd.dma,
+ GFP_ATOMIC);
if (!get_mac_list_cmd.va) {
dev_err(&adapter->pdev->dev,
@@ -3829,8 +3829,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_req_set_mac_list);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_KERNEL);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_KERNEL);
if (!cmd.va)
return -ENOMEM;
@@ -4035,8 +4035,8 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va) {
dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
status = -ENOMEM;
@@ -4089,9 +4089,9 @@ int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
- extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- extfat_cmd.size, &extfat_cmd.dma,
- GFP_ATOMIC);
+ extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ extfat_cmd.size, &extfat_cmd.dma,
+ GFP_ATOMIC);
if (!extfat_cmd.va)
return -ENOMEM;
@@ -4127,9 +4127,9 @@ int be_cmd_get_fw_log_level(struct be_adapter *adapter)
memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
- extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- extfat_cmd.size, &extfat_cmd.dma,
- GFP_ATOMIC);
+ extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ extfat_cmd.size, &extfat_cmd.dma,
+ GFP_ATOMIC);
if (!extfat_cmd.va) {
dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
@@ -4354,8 +4354,8 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_get_func_config);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va) {
dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
status = -ENOMEM;
@@ -4452,8 +4452,8 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va)
return -ENOMEM;
@@ -4539,8 +4539,8 @@ static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_req_set_profile_config);
- cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_ATOMIC);
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+ GFP_ATOMIC);
if (!cmd.va)
return -ENOMEM;
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 3f6749fc889f..4c218341c51b 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -274,8 +274,8 @@ static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,
int status = 0;
read_cmd.size = LANCER_READ_FILE_CHUNK;
- read_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, read_cmd.size,
- &read_cmd.dma, GFP_ATOMIC);
+ read_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, read_cmd.size,
+ &read_cmd.dma, GFP_ATOMIC);
if (!read_cmd.va) {
dev_err(&adapter->pdev->dev,
@@ -815,7 +815,7 @@ static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
}
cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
- cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
+ cmd.va = dma_alloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
if (!cmd.va)
return -ENOMEM;
@@ -851,9 +851,9 @@ static int be_test_ddr_dma(struct be_adapter *adapter)
};
ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
- ddrdma_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- ddrdma_cmd.size, &ddrdma_cmd.dma,
- GFP_KERNEL);
+ ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ ddrdma_cmd.size, &ddrdma_cmd.dma,
+ GFP_KERNEL);
if (!ddrdma_cmd.va)
return -ENOMEM;
@@ -1014,9 +1014,9 @@ static int be_read_eeprom(struct net_device *netdev,
memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
- eeprom_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
- eeprom_cmd.size, &eeprom_cmd.dma,
- GFP_KERNEL);
+ eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+ eeprom_cmd.size, &eeprom_cmd.dma,
+ GFP_KERNEL);
if (!eeprom_cmd.va)
return -ENOMEM;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 852f5bfe5f6d..3c7c04406a2b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -167,8 +167,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
q->len = len;
q->entry_size = entry_size;
mem->size = len * entry_size;
- mem->va = dma_zalloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
- GFP_KERNEL);
+ mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
+ &mem->dma, GFP_KERNEL);
if (!mem->va)
return -ENOMEM;
return 0;
@@ -1270,10 +1270,6 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo)
#define is_arp_allowed_on_bmc(adapter, skb) \
(is_arp(skb) && is_arp_filt_enabled(adapter))
-#define is_broadcast_packet(eh, adapter) \
- (is_multicast_ether_addr(eh->h_dest) && \
- !compare_ether_addr(eh->h_dest, adapter->netdev->broadcast))
-
#define is_arp(skb) (skb->protocol == htons(ETH_P_ARP))
#define is_arp_filt_enabled(adapter) \
@@ -5766,9 +5762,9 @@ static int be_drv_init(struct be_adapter *adapter)
int status = 0;
mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
- mbox_mem_alloc->va = dma_zalloc_coherent(dev, mbox_mem_alloc->size,
- &mbox_mem_alloc->dma,
- GFP_KERNEL);
+ mbox_mem_alloc->va = dma_alloc_coherent(dev, mbox_mem_alloc->size,
+ &mbox_mem_alloc->dma,
+ GFP_KERNEL);
if (!mbox_mem_alloc->va)
return -ENOMEM;
@@ -5777,8 +5773,8 @@ static int be_drv_init(struct be_adapter *adapter)
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
- rx_filter->va = dma_zalloc_coherent(dev, rx_filter->size,
- &rx_filter->dma, GFP_KERNEL);
+ rx_filter->va = dma_alloc_coherent(dev, rx_filter->size,
+ &rx_filter->dma, GFP_KERNEL);
if (!rx_filter->va) {
status = -ENOMEM;
goto free_mbox;
@@ -5792,8 +5788,8 @@ static int be_drv_init(struct be_adapter *adapter)
stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
else
stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
- stats_cmd->va = dma_zalloc_coherent(dev, stats_cmd->size,
- &stats_cmd->dma, GFP_KERNEL);
+ stats_cmd->va = dma_alloc_coherent(dev, stats_cmd->size,
+ &stats_cmd->dma, GFP_KERNEL);
if (!stats_cmd->va) {
status = -ENOMEM;
goto free_rx_filter;
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 4d673225ed3e..b17b79e612a3 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -935,16 +935,14 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
return -ENOMEM;
/* Allocate descriptors */
- priv->rxdes = dma_zalloc_coherent(priv->dev,
- MAX_RX_QUEUE_ENTRIES *
- sizeof(struct ftgmac100_rxdes),
- &priv->rxdes_dma, GFP_KERNEL);
+ priv->rxdes = dma_alloc_coherent(priv->dev,
+ MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes),
+ &priv->rxdes_dma, GFP_KERNEL);
if (!priv->rxdes)
return -ENOMEM;
- priv->txdes = dma_zalloc_coherent(priv->dev,
- MAX_TX_QUEUE_ENTRIES *
- sizeof(struct ftgmac100_txdes),
- &priv->txdes_dma, GFP_KERNEL);
+ priv->txdes = dma_alloc_coherent(priv->dev,
+ MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes),
+ &priv->txdes_dma, GFP_KERNEL);
if (!priv->txdes)
return -ENOMEM;
@@ -1639,7 +1637,7 @@ static int ftgmac100_setup_mdio(struct net_device *netdev)
reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR);
reg &= ~FTGMAC100_REVR_NEW_MDIO_INTERFACE;
iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR);
- };
+ }
/* Get PHY mode from device-tree */
if (np) {
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index 084f24daf2b5..2a0e820526dc 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -734,10 +734,9 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv)
{
int i;
- priv->descs = dma_zalloc_coherent(priv->dev,
- sizeof(struct ftmac100_descs),
- &priv->descs_dma_addr,
- GFP_KERNEL);
+ priv->descs = dma_alloc_coherent(priv->dev,
+ sizeof(struct ftmac100_descs),
+ &priv->descs_dma_addr, GFP_KERNEL);
if (!priv->descs)
return -ENOMEM;
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index ae55da60ed0e..c24fd56a2c71 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -1531,7 +1531,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
/* Free the original skb. */
pci_unmap_single(np->pci_dev, np->cur_tx->buffer,
np->cur_tx->skbuff->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(np->cur_tx->skbuff);
+ dev_consume_skb_irq(np->cur_tx->skbuff);
np->cur_tx->skbuff = NULL;
--np->really_tx_count;
if (np->cur_tx->control & TXLD) {
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index d3a62bc1f1c6..71793e03c3c8 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -97,5 +97,6 @@ config GIANFAR
source "drivers/net/ethernet/freescale/dpaa/Kconfig"
source "drivers/net/ethernet/freescale/dpaa2/Kconfig"
+source "drivers/net/ethernet/freescale/enetc/Kconfig"
endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 3b4ff08e3841..6a93293d31e0 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -23,3 +23,6 @@ obj-$(CONFIG_FSL_FMAN) += fman/
obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/
obj-$(CONFIG_FSL_DPAA2_ETH) += dpaa2/
+
+obj-$(CONFIG_FSL_ENETC) += enetc/
+obj-$(CONFIG_FSL_ENETC_VF) += enetc/
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index f53090cde041..dfebc30c4841 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2051,6 +2051,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
bool nonlinear = skb_is_nonlinear(skb);
struct rtnl_link_stats64 *percpu_stats;
struct dpaa_percpu_priv *percpu_priv;
+ struct netdev_queue *txq;
struct dpaa_priv *priv;
struct qm_fd fd;
int offset = 0;
@@ -2100,6 +2101,11 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
if (unlikely(err < 0))
goto skb_to_fd_failed;
+ txq = netdev_get_tx_queue(net_dev, queue_mapping);
+
+ /* LLTX requires to do our own update of trans_start */
+ txq->trans_start = jiffies;
+
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index 62497119c85f..bdee441bc3b7 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -501,7 +501,7 @@ static int dpaa_get_ts_info(struct net_device *net_dev,
struct device_node *mac_node = dev->of_node;
struct device_node *fman_node = NULL, *ptp_node = NULL;
struct platform_device *ptp_dev = NULL;
- struct qoriq_ptp *ptp = NULL;
+ struct ptp_qoriq *ptp = NULL;
info->phc_index = -1;
diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig
index 809a155eb193..f6d244c663fd 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
@@ -9,8 +9,9 @@ config FSL_DPAA2_ETH
config FSL_DPAA2_PTP_CLOCK
tristate "Freescale DPAA2 PTP Clock"
- depends on FSL_DPAA2_ETH && POSIX_TIMERS
- select PTP_1588_CLOCK
+ depends on FSL_DPAA2_ETH
+ imply PTP_1588_CLOCK
+ default y
help
This driver adds support for using the DPAA2 1588 timer module
as a PTP clock.
diff --git a/drivers/net/ethernet/freescale/dpaa2/Makefile b/drivers/net/ethernet/freescale/dpaa2/Makefile
index 2f424e0a8225..d1e78cdd512f 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Makefile
+++ b/drivers/net/ethernet/freescale/dpaa2/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK) += fsl-dpaa2-ptp.o
fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o
+fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
# Needed by the tracing framework
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c
new file mode 100644
index 000000000000..a027f4a9d0cc
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2015 Freescale Semiconductor Inc.
+ * Copyright 2018-2019 NXP
+ */
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include "dpaa2-eth.h"
+#include "dpaa2-eth-debugfs.h"
+
+#define DPAA2_ETH_DBG_ROOT "dpaa2-eth"
+
+static struct dentry *dpaa2_dbg_root;
+
+static int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset)
+{
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+ struct rtnl_link_stats64 *stats;
+ struct dpaa2_eth_drv_stats *extras;
+ int i;
+
+ seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name);
+ seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s%16s\n",
+ "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf",
+ "Tx SG", "Tx realloc", "Enq busy");
+
+ for_each_online_cpu(i) {
+ stats = per_cpu_ptr(priv->percpu_stats, i);
+ extras = per_cpu_ptr(priv->percpu_extras, i);
+ seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n",
+ i,
+ stats->rx_packets,
+ stats->rx_errors,
+ extras->rx_sg_frames,
+ stats->tx_packets,
+ stats->tx_errors,
+ extras->tx_conf_frames,
+ extras->tx_sg_frames,
+ extras->tx_reallocs,
+ extras->tx_portal_busy);
+ }
+
+ return 0;
+}
+
+static int dpaa2_dbg_cpu_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+ err = single_open(file, dpaa2_dbg_cpu_show, priv);
+ if (err < 0)
+ netdev_err(priv->net_dev, "single_open() failed\n");
+
+ return err;
+}
+
+static const struct file_operations dpaa2_dbg_cpu_ops = {
+ .open = dpaa2_dbg_cpu_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static char *fq_type_to_str(struct dpaa2_eth_fq *fq)
+{
+ switch (fq->type) {
+ case DPAA2_RX_FQ:
+ return "Rx";
+ case DPAA2_TX_CONF_FQ:
+ return "Tx conf";
+ default:
+ return "N/A";
+ }
+}
+
+static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
+{
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+ struct dpaa2_eth_fq *fq;
+ u32 fcnt, bcnt;
+ int i, err;
+
+ seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
+ seq_printf(file, "%s%16s%16s%16s%16s\n",
+ "VFQID", "CPU", "Type", "Frames", "Pending frames");
+
+ for (i = 0; i < priv->num_fqs; i++) {
+ fq = &priv->fq[i];
+ err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
+ if (err)
+ fcnt = 0;
+
+ seq_printf(file, "%5d%16d%16s%16llu%16u\n",
+ fq->fqid,
+ fq->target_cpu,
+ fq_type_to_str(fq),
+ fq->stats.frames,
+ fcnt);
+ }
+
+ return 0;
+}
+
+static int dpaa2_dbg_fqs_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+ err = single_open(file, dpaa2_dbg_fqs_show, priv);
+ if (err < 0)
+ netdev_err(priv->net_dev, "single_open() failed\n");
+
+ return err;
+}
+
+static const struct file_operations dpaa2_dbg_fq_ops = {
+ .open = dpaa2_dbg_fqs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int dpaa2_dbg_ch_show(struct seq_file *file, void *offset)
+{
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+ struct dpaa2_eth_channel *ch;
+ int i;
+
+ seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
+ seq_printf(file, "%s%16s%16s%16s%16s\n",
+ "CHID", "CPU", "Deq busy", "CDANs", "Buf count");
+
+ for (i = 0; i < priv->num_channels; i++) {
+ ch = priv->channel[i];
+ seq_printf(file, "%4d%16d%16llu%16llu%16d\n",
+ ch->ch_id,
+ ch->nctx.desired_cpu,
+ ch->stats.dequeue_portal_busy,
+ ch->stats.cdan,
+ ch->buf_count);
+ }
+
+ return 0;
+}
+
+static int dpaa2_dbg_ch_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+ err = single_open(file, dpaa2_dbg_ch_show, priv);
+ if (err < 0)
+ netdev_err(priv->net_dev, "single_open() failed\n");
+
+ return err;
+}
+
+static const struct file_operations dpaa2_dbg_ch_ops = {
+ .open = dpaa2_dbg_ch_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void dpaa2_dbg_add(struct dpaa2_eth_priv *priv)
+{
+ if (!dpaa2_dbg_root)
+ return;
+
+ /* Create a directory for the interface */
+ priv->dbg.dir = debugfs_create_dir(priv->net_dev->name,
+ dpaa2_dbg_root);
+ if (!priv->dbg.dir) {
+ netdev_err(priv->net_dev, "debugfs_create_dir() failed\n");
+ return;
+ }
+
+ /* per-cpu stats file */
+ priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", 0444,
+ priv->dbg.dir, priv,
+ &dpaa2_dbg_cpu_ops);
+ if (!priv->dbg.cpu_stats) {
+ netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+ goto err_cpu_stats;
+ }
+
+ /* per-fq stats file */
+ priv->dbg.fq_stats = debugfs_create_file("fq_stats", 0444,
+ priv->dbg.dir, priv,
+ &dpaa2_dbg_fq_ops);
+ if (!priv->dbg.fq_stats) {
+ netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+ goto err_fq_stats;
+ }
+
+ /* per-fq stats file */
+ priv->dbg.ch_stats = debugfs_create_file("ch_stats", 0444,
+ priv->dbg.dir, priv,
+ &dpaa2_dbg_ch_ops);
+ if (!priv->dbg.fq_stats) {
+ netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+ goto err_ch_stats;
+ }
+
+ return;
+
+err_ch_stats:
+ debugfs_remove(priv->dbg.fq_stats);
+err_fq_stats:
+ debugfs_remove(priv->dbg.cpu_stats);
+err_cpu_stats:
+ debugfs_remove(priv->dbg.dir);
+}
+
+void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv)
+{
+ debugfs_remove(priv->dbg.fq_stats);
+ debugfs_remove(priv->dbg.ch_stats);
+ debugfs_remove(priv->dbg.cpu_stats);
+ debugfs_remove(priv->dbg.dir);
+}
+
+void dpaa2_eth_dbg_init(void)
+{
+ dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL);
+ if (!dpaa2_dbg_root) {
+ pr_err("DPAA2-ETH: debugfs create failed\n");
+ return;
+ }
+
+ pr_debug("DPAA2-ETH: debugfs created\n");
+}
+
+void dpaa2_eth_dbg_exit(void)
+{
+ debugfs_remove(dpaa2_dbg_root);
+}
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h
new file mode 100644
index 000000000000..4f63de997a26
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2015 Freescale Semiconductor Inc.
+ * Copyright 2018-2019 NXP
+ */
+#ifndef DPAA2_ETH_DEBUGFS_H
+#define DPAA2_ETH_DEBUGFS_H
+
+#include <linux/dcache.h>
+
+struct dpaa2_eth_priv;
+
+struct dpaa2_debugfs {
+ struct dentry *dir;
+ struct dentry *fq_stats;
+ struct dentry *ch_stats;
+ struct dentry *cpu_stats;
+};
+
+#ifdef CONFIG_DEBUG_FS
+void dpaa2_eth_dbg_init(void);
+void dpaa2_eth_dbg_exit(void);
+void dpaa2_dbg_add(struct dpaa2_eth_priv *priv);
+void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv);
+#else
+static inline void dpaa2_eth_dbg_init(void) {}
+static inline void dpaa2_eth_dbg_exit(void) {}
+static inline void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) {}
+static inline void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) {}
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* DPAA2_ETH_DEBUGFS_H */
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 1ca9a18139ec..2ba49e959c3f 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -86,16 +86,16 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
for (i = 1; 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_BIDIRECTIONAL);
+ dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
- skb_free_frag(sg_vaddr);
+ free_pages((unsigned long)sg_vaddr, 0);
if (dpaa2_sg_is_final(&sgt[i]))
break;
}
free_buf:
- skb_free_frag(vaddr);
+ free_pages((unsigned long)vaddr, 0);
}
/* Build a linear skb based on a single-buffer frame descriptor */
@@ -109,7 +109,7 @@ static struct sk_buff *build_linear_skb(struct dpaa2_eth_channel *ch,
ch->buf_count--;
- skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE);
+ skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
if (unlikely(!skb))
return NULL;
@@ -144,19 +144,19 @@ 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_BIDIRECTIONAL);
+ dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
sg_length = dpaa2_sg_get_len(sge);
if (i == 0) {
/* We build the skb around the first data buffer */
- skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE);
+ skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
if (unlikely(!skb)) {
/* Free the first SG entry now, since we already
* unmapped it and obtained the virtual address
*/
- skb_free_frag(sg_vaddr);
+ free_pages((unsigned long)sg_vaddr, 0);
/* We still need to subtract the buffers used
* by this FD from our software counter
@@ -211,9 +211,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
for (i = 0; i < count; i++) {
vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
- dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
- DMA_BIDIRECTIONAL);
- skb_free_frag(vaddr);
+ dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
+ free_pages((unsigned long)vaddr, 0);
}
}
@@ -264,9 +264,7 @@ static int xdp_enqueue(struct dpaa2_eth_priv *priv, struct dpaa2_fd *fd,
fq = &priv->fq[queue_id];
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
- err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
- priv->tx_qdid, 0,
- fq->tx_qdbin, fd);
+ err = priv->enqueue(priv, fq, fd, 0);
if (err != -EBUSY)
break;
}
@@ -298,6 +296,7 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv,
xdp.data_end = xdp.data + dpaa2_fd_get_len(fd);
xdp.data_hard_start = xdp.data - XDP_PACKET_HEADROOM;
xdp_set_data_meta_invalid(&xdp);
+ xdp.rxq = &ch->xdp_rxq;
xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp);
@@ -330,8 +329,20 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv,
xdp_release_buf(priv, ch, addr);
ch->stats.xdp_drop++;
break;
+ case XDP_REDIRECT:
+ dma_unmap_page(priv->net_dev->dev.parent, addr,
+ DPAA2_ETH_RX_BUF_SIZE, DMA_BIDIRECTIONAL);
+ ch->buf_count--;
+ xdp.data_hard_start = vaddr;
+ err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog);
+ if (unlikely(err))
+ ch->stats.xdp_drop++;
+ else
+ ch->stats.xdp_redirect++;
+ break;
}
+ ch->xdp.res |= xdp_act;
out:
rcu_read_unlock();
return xdp_act;
@@ -378,16 +389,16 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
return;
}
- dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
skb = build_linear_skb(ch, fd, vaddr);
} else if (fd_format == dpaa2_fd_sg) {
WARN_ON(priv->xdp_prog);
- dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
skb = build_frag_skb(priv, ch, buf_data);
- skb_free_frag(vaddr);
+ free_pages((unsigned long)vaddr, 0);
percpu_extras->rx_sg_frames++;
percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
} else {
@@ -573,10 +584,11 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
* all of them on Tx Conf.
*/
swa = (struct dpaa2_eth_swa *)sgt_buf;
- swa->skb = skb;
- swa->scl = scl;
- swa->num_sg = num_sg;
- swa->sgt_size = sgt_buf_size;
+ swa->type = DPAA2_ETH_SWA_SG;
+ swa->sg.skb = skb;
+ swa->sg.scl = scl;
+ swa->sg.num_sg = num_sg;
+ swa->sg.sgt_size = sgt_buf_size;
/* Separately map the SGT buffer */
addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL);
@@ -611,7 +623,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
{
struct device *dev = priv->net_dev->dev.parent;
u8 *buffer_start, *aligned_start;
- struct sk_buff **skbh;
+ struct dpaa2_eth_swa *swa;
dma_addr_t addr;
buffer_start = skb->data - dpaa2_eth_needed_headroom(priv, skb);
@@ -628,8 +640,9 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
* (in the private data area) such that we can release it
* on Tx confirm
*/
- skbh = (struct sk_buff **)buffer_start;
- *skbh = skb;
+ swa = (struct dpaa2_eth_swa *)buffer_start;
+ swa->type = DPAA2_ETH_SWA_SINGLE;
+ swa->single.skb = skb;
addr = dma_map_single(dev, buffer_start,
skb_tail_pointer(skb) - buffer_start,
@@ -657,47 +670,65 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
* dpaa2_eth_tx().
*/
static void free_tx_fd(const struct dpaa2_eth_priv *priv,
- const struct dpaa2_fd *fd)
+ struct dpaa2_eth_fq *fq,
+ const struct dpaa2_fd *fd, bool in_napi)
{
struct device *dev = priv->net_dev->dev.parent;
dma_addr_t fd_addr;
- struct sk_buff **skbh, *skb;
+ struct sk_buff *skb = NULL;
unsigned char *buffer_start;
struct dpaa2_eth_swa *swa;
u8 fd_format = dpaa2_fd_get_format(fd);
+ u32 fd_len = dpaa2_fd_get_len(fd);
fd_addr = dpaa2_fd_get_addr(fd);
- skbh = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+ buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+ swa = (struct dpaa2_eth_swa *)buffer_start;
if (fd_format == dpaa2_fd_single) {
- skb = *skbh;
- buffer_start = (unsigned char *)skbh;
- /* Accessing the skb buffer is safe before dma unmap, because
- * we didn't map the actual skb shell.
- */
- dma_unmap_single(dev, fd_addr,
- skb_tail_pointer(skb) - buffer_start,
- DMA_BIDIRECTIONAL);
+ if (swa->type == DPAA2_ETH_SWA_SINGLE) {
+ skb = swa->single.skb;
+ /* Accessing the skb buffer is safe before dma unmap,
+ * because we didn't map the actual skb shell.
+ */
+ dma_unmap_single(dev, fd_addr,
+ skb_tail_pointer(skb) - buffer_start,
+ DMA_BIDIRECTIONAL);
+ } else {
+ WARN_ONCE(swa->type != DPAA2_ETH_SWA_XDP, "Wrong SWA type");
+ dma_unmap_single(dev, fd_addr, swa->xdp.dma_size,
+ DMA_BIDIRECTIONAL);
+ }
} else if (fd_format == dpaa2_fd_sg) {
- swa = (struct dpaa2_eth_swa *)skbh;
- skb = swa->skb;
+ skb = swa->sg.skb;
/* Unmap the scatterlist */
- dma_unmap_sg(dev, swa->scl, swa->num_sg, DMA_BIDIRECTIONAL);
- kfree(swa->scl);
+ dma_unmap_sg(dev, swa->sg.scl, swa->sg.num_sg,
+ DMA_BIDIRECTIONAL);
+ kfree(swa->sg.scl);
/* Unmap the SGT buffer */
- dma_unmap_single(dev, fd_addr, swa->sgt_size,
+ dma_unmap_single(dev, fd_addr, swa->sg.sgt_size,
DMA_BIDIRECTIONAL);
} else {
netdev_dbg(priv->net_dev, "Invalid FD format\n");
return;
}
+ if (swa->type != DPAA2_ETH_SWA_XDP && in_napi) {
+ fq->dq_frames++;
+ fq->dq_bytes += fd_len;
+ }
+
+ if (swa->type == DPAA2_ETH_SWA_XDP) {
+ xdp_return_frame(swa->xdp.xdpf);
+ return;
+ }
+
/* Get the timestamp value */
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
struct skb_shared_hwtstamps shhwtstamps;
- __le64 *ts = dpaa2_get_ts(skbh, true);
+ __le64 *ts = dpaa2_get_ts(buffer_start, true);
u64 ns;
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -709,10 +740,10 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
/* Free SGT buffer allocated on tx */
if (fd_format != dpaa2_fd_single)
- skb_free_frag(skbh);
+ skb_free_frag(buffer_start);
/* Move on with skb release */
- dev_kfree_skb(skb);
+ napi_consume_skb(skb, in_napi);
}
static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
@@ -785,9 +816,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
queue_mapping = skb_get_queue_mapping(skb);
fq = &priv->fq[queue_mapping];
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
- err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
- priv->tx_qdid, 0,
- fq->tx_qdbin, &fd);
+ err = priv->enqueue(priv, fq, &fd, 0);
if (err != -EBUSY)
break;
}
@@ -795,7 +824,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
if (unlikely(err < 0)) {
percpu_stats->tx_errors++;
/* Clean up everything, including freeing the skb */
- free_tx_fd(priv, &fd);
+ free_tx_fd(priv, fq, &fd, false);
} else {
fd_len = dpaa2_fd_get_len(&fd);
percpu_stats->tx_packets++;
@@ -832,12 +861,9 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
percpu_extras->tx_conf_frames++;
percpu_extras->tx_conf_bytes += fd_len;
- fq->dq_frames++;
- fq->dq_bytes += fd_len;
-
/* Check frame errors in the FD field */
fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
- free_tx_fd(priv, fd);
+ free_tx_fd(priv, fq, fd, true);
if (likely(!fd_errors))
return;
@@ -903,7 +929,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
{
struct device *dev = priv->net_dev->dev.parent;
u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
- void *buf;
+ struct page *page;
dma_addr_t addr;
int i, err;
@@ -911,14 +937,16 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
/* Allocate buffer visible to WRIOP + skb shared info +
* alignment padding
*/
- buf = napi_alloc_frag(dpaa2_eth_buf_raw_size(priv));
- if (unlikely(!buf))
+ /* allocate one page for each Rx buffer. WRIOP sees
+ * the entire page except for a tailroom reserved for
+ * skb shared info
+ */
+ page = dev_alloc_pages(0);
+ if (!page)
goto err_alloc;
- buf = PTR_ALIGN(buf, priv->rx_buf_align);
-
- addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE,
- DMA_BIDIRECTIONAL);
+ addr = dma_map_page(dev, page, 0, DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(dev, addr)))
goto err_map;
@@ -926,7 +954,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
/* tracing point */
trace_dpaa2_eth_buf_seed(priv->net_dev,
- buf, dpaa2_eth_buf_raw_size(priv),
+ page, DPAA2_ETH_RX_BUF_RAW_SIZE,
addr, DPAA2_ETH_RX_BUF_SIZE,
bpid);
}
@@ -948,7 +976,7 @@ release_bufs:
return i;
err_map:
- skb_free_frag(buf);
+ __free_pages(page, 0);
err_alloc:
/* If we managed to allocate at least some buffers,
* release them to hardware
@@ -1083,6 +1111,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
int err;
ch = container_of(napi, struct dpaa2_eth_channel, napi);
+ ch->xdp.res = 0;
priv = ch->priv;
do {
@@ -1128,7 +1157,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
work_done = max(rx_cleaned, 1);
out:
- if (txc_fq) {
+ if (txc_fq && txc_fq->dq_frames) {
nq = netdev_get_tx_queue(priv->net_dev, txc_fq->flowid);
netdev_tx_completed_queue(nq, txc_fq->dq_frames,
txc_fq->dq_bytes);
@@ -1136,6 +1165,9 @@ out:
txc_fq->dq_bytes = 0;
}
+ if (ch->xdp.res & XDP_REDIRECT)
+ xdp_do_flush_map();
+
return work_done;
}
@@ -1243,34 +1275,36 @@ enable_err:
return err;
}
-/* The DPIO store must be empty when we call this,
- * at the end of every NAPI cycle.
- */
-static u32 drain_channel(struct dpaa2_eth_channel *ch)
+/* Total number of in-flight frames on ingress queues */
+static u32 ingress_fq_count(struct dpaa2_eth_priv *priv)
{
- u32 drained = 0, total = 0;
+ struct dpaa2_eth_fq *fq;
+ u32 fcnt = 0, bcnt = 0, total = 0;
+ int i, err;
- do {
- pull_channel(ch);
- drained = consume_frames(ch, NULL);
- total += drained;
- } while (drained);
+ for (i = 0; i < priv->num_fqs; i++) {
+ fq = &priv->fq[i];
+ err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
+ if (err) {
+ netdev_warn(priv->net_dev, "query_fq_count failed");
+ break;
+ }
+ total += fcnt;
+ }
return total;
}
-static u32 drain_ingress_frames(struct dpaa2_eth_priv *priv)
+static void wait_for_fq_empty(struct dpaa2_eth_priv *priv)
{
- struct dpaa2_eth_channel *ch;
- int i;
- u32 drained = 0;
-
- for (i = 0; i < priv->num_channels; i++) {
- ch = priv->channel[i];
- drained += drain_channel(ch);
- }
+ int retries = 10;
+ u32 pending;
- return drained;
+ do {
+ pending = ingress_fq_count(priv);
+ if (pending)
+ msleep(100);
+ } while (pending && --retries);
}
static int dpaa2_eth_stop(struct net_device *net_dev)
@@ -1278,14 +1312,22 @@ static int dpaa2_eth_stop(struct net_device *net_dev)
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
int dpni_enabled = 0;
int retries = 10;
- u32 drained;
netif_tx_stop_all_queues(net_dev);
netif_carrier_off(net_dev);
- /* Loop while dpni_disable() attempts to drain the egress FQs
- * and confirm them back to us.
+ /* On dpni_disable(), the MC firmware will:
+ * - stop MAC Rx and wait for all Rx frames to be enqueued to software
+ * - cut off WRIOP dequeues from egress FQs and wait until transmission
+ * of all in flight Tx frames is finished (and corresponding Tx conf
+ * frames are enqueued back to software)
+ *
+ * Before calling dpni_disable(), we wait for all Tx frames to arrive
+ * on WRIOP. After it finishes, wait until all remaining frames on Rx
+ * and Tx conf queues are consumed on NAPI poll.
*/
+ msleep(500);
+
do {
dpni_disable(priv->mc_io, 0, priv->mc_token);
dpni_is_enabled(priv->mc_io, 0, priv->mc_token, &dpni_enabled);
@@ -1300,19 +1342,9 @@ static int dpaa2_eth_stop(struct net_device *net_dev)
*/
}
- /* Wait for NAPI to complete on every core and disable it.
- * In particular, this will also prevent NAPI from being rescheduled if
- * a new CDAN is serviced, effectively discarding the CDAN. We therefore
- * don't even need to disarm the channels, except perhaps for the case
- * of a huge coalescing value.
- */
+ wait_for_fq_empty(priv);
disable_ch_napi(priv);
- /* Manually drain the Rx and TxConf queues */
- drained = drain_ingress_frames(priv);
- if (drained)
- netdev_dbg(net_dev, "Drained %d frames.\n", drained);
-
/* Empty the buffer pool */
drain_pool(priv);
@@ -1730,6 +1762,105 @@ static int dpaa2_eth_xdp(struct net_device *dev, struct netdev_bpf *xdp)
return 0;
}
+static int dpaa2_eth_xdp_xmit_frame(struct net_device *net_dev,
+ struct xdp_frame *xdpf)
+{
+ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+ struct device *dev = net_dev->dev.parent;
+ struct rtnl_link_stats64 *percpu_stats;
+ struct dpaa2_eth_drv_stats *percpu_extras;
+ unsigned int needed_headroom;
+ struct dpaa2_eth_swa *swa;
+ struct dpaa2_eth_fq *fq;
+ struct dpaa2_fd fd;
+ void *buffer_start, *aligned_start;
+ dma_addr_t addr;
+ int err, i;
+
+ /* We require a minimum headroom to be able to transmit the frame.
+ * Otherwise return an error and let the original net_device handle it
+ */
+ needed_headroom = dpaa2_eth_needed_headroom(priv, NULL);
+ if (xdpf->headroom < needed_headroom)
+ return -EINVAL;
+
+ percpu_stats = this_cpu_ptr(priv->percpu_stats);
+ percpu_extras = this_cpu_ptr(priv->percpu_extras);
+
+ /* Setup the FD fields */
+ memset(&fd, 0, sizeof(fd));
+
+ /* Align FD address, if possible */
+ buffer_start = xdpf->data - needed_headroom;
+ aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN,
+ DPAA2_ETH_TX_BUF_ALIGN);
+ if (aligned_start >= xdpf->data - xdpf->headroom)
+ buffer_start = aligned_start;
+
+ swa = (struct dpaa2_eth_swa *)buffer_start;
+ /* fill in necessary fields here */
+ swa->type = DPAA2_ETH_SWA_XDP;
+ swa->xdp.dma_size = xdpf->data + xdpf->len - buffer_start;
+ swa->xdp.xdpf = xdpf;
+
+ addr = dma_map_single(dev, buffer_start,
+ swa->xdp.dma_size,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(dev, addr))) {
+ percpu_stats->tx_dropped++;
+ return -ENOMEM;
+ }
+
+ dpaa2_fd_set_addr(&fd, addr);
+ dpaa2_fd_set_offset(&fd, xdpf->data - buffer_start);
+ dpaa2_fd_set_len(&fd, xdpf->len);
+ dpaa2_fd_set_format(&fd, dpaa2_fd_single);
+ dpaa2_fd_set_ctrl(&fd, FD_CTRL_PTA);
+
+ fq = &priv->fq[smp_processor_id()];
+ for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
+ err = priv->enqueue(priv, fq, &fd, 0);
+ if (err != -EBUSY)
+ break;
+ }
+ percpu_extras->tx_portal_busy += i;
+ if (unlikely(err < 0)) {
+ percpu_stats->tx_errors++;
+ /* let the Rx device handle the cleanup */
+ return err;
+ }
+
+ percpu_stats->tx_packets++;
+ percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
+
+ return 0;
+}
+
+static int dpaa2_eth_xdp_xmit(struct net_device *net_dev, int n,
+ struct xdp_frame **frames, u32 flags)
+{
+ int drops = 0;
+ int i, err;
+
+ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+ return -EINVAL;
+
+ if (!netif_running(net_dev))
+ return -ENETDOWN;
+
+ for (i = 0; i < n; i++) {
+ struct xdp_frame *xdpf = frames[i];
+
+ err = dpaa2_eth_xdp_xmit_frame(net_dev, xdpf);
+ if (err) {
+ xdp_return_frame_rx_napi(xdpf);
+ drops++;
+ }
+ }
+
+ return n - drops;
+}
+
static const struct net_device_ops dpaa2_eth_ops = {
.ndo_open = dpaa2_eth_open,
.ndo_start_xmit = dpaa2_eth_tx,
@@ -1741,6 +1872,7 @@ static const struct net_device_ops dpaa2_eth_ops = {
.ndo_do_ioctl = dpaa2_eth_ioctl,
.ndo_change_mtu = dpaa2_eth_change_mtu,
.ndo_bpf = dpaa2_eth_xdp,
+ .ndo_xdp_xmit = dpaa2_eth_xdp_xmit,
};
static void cdan_cb(struct dpaa2_io_notification_ctx *ctx)
@@ -1902,7 +2034,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
/* Register the new context */
channel->dpio = dpaa2_io_service_select(i);
- err = dpaa2_io_service_register(channel->dpio, nctx);
+ err = dpaa2_io_service_register(channel->dpio, nctx, dev);
if (err) {
dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
/* If no affine DPIO for this core, there's probably
@@ -1942,7 +2074,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
return 0;
err_set_cdan:
- dpaa2_io_service_deregister(channel->dpio, nctx);
+ dpaa2_io_service_deregister(channel->dpio, nctx, dev);
err_service_reg:
free_channel(priv, channel);
err_alloc_ch:
@@ -1962,13 +2094,14 @@ err_alloc_ch:
static void free_dpio(struct dpaa2_eth_priv *priv)
{
- int i;
+ struct device *dev = priv->net_dev->dev.parent;
struct dpaa2_eth_channel *ch;
+ int i;
/* deregister CDAN notifications and free channels */
for (i = 0; i < priv->num_channels; i++) {
ch = priv->channel[i];
- dpaa2_io_service_deregister(ch->dpio, &ch->nctx);
+ dpaa2_io_service_deregister(ch->dpio, &ch->nctx, dev);
free_channel(priv, ch);
}
}
@@ -2134,6 +2267,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
{
struct device *dev = priv->net_dev->dev.parent;
struct dpni_buffer_layout buf_layout = {0};
+ u16 rx_buf_align;
int err;
/* We need to check for WRIOP version 1.0.0, but depending on the MC
@@ -2142,9 +2276,9 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
*/
if (priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(0, 0, 0) ||
priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(1, 0, 0))
- priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
+ rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
else
- priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
+ rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
/* tx buffer */
buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
@@ -2184,7 +2318,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
/* rx buffer */
buf_layout.pass_frame_status = true;
buf_layout.pass_parser_result = true;
- buf_layout.data_align = priv->rx_buf_align;
+ buf_layout.data_align = rx_buf_align;
buf_layout.data_head_room = dpaa2_eth_rx_head_room(priv);
buf_layout.private_data_size = 0;
buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
@@ -2202,6 +2336,36 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
return 0;
}
+#define DPNI_ENQUEUE_FQID_VER_MAJOR 7
+#define DPNI_ENQUEUE_FQID_VER_MINOR 9
+
+static inline int dpaa2_eth_enqueue_qd(struct dpaa2_eth_priv *priv,
+ struct dpaa2_eth_fq *fq,
+ struct dpaa2_fd *fd, u8 prio)
+{
+ return dpaa2_io_service_enqueue_qd(fq->channel->dpio,
+ priv->tx_qdid, prio,
+ fq->tx_qdbin, fd);
+}
+
+static inline int dpaa2_eth_enqueue_fq(struct dpaa2_eth_priv *priv,
+ struct dpaa2_eth_fq *fq,
+ struct dpaa2_fd *fd,
+ u8 prio __always_unused)
+{
+ return dpaa2_io_service_enqueue_fq(fq->channel->dpio,
+ fq->tx_fqid, fd);
+}
+
+static void set_enqueue_mode(struct dpaa2_eth_priv *priv)
+{
+ if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR,
+ DPNI_ENQUEUE_FQID_VER_MINOR) < 0)
+ priv->enqueue = dpaa2_eth_enqueue_qd;
+ else
+ priv->enqueue = dpaa2_eth_enqueue_fq;
+}
+
/* Configure the DPNI object this interface is associated with */
static int setup_dpni(struct fsl_mc_device *ls_dev)
{
@@ -2255,6 +2419,8 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
if (err)
goto close;
+ set_enqueue_mode(priv);
+
priv->cls_rules = devm_kzalloc(dev, sizeof(struct dpaa2_eth_cls_rule) *
dpaa2_eth_fs_count(priv), GFP_KERNEL);
if (!priv->cls_rules)
@@ -2302,9 +2468,14 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv,
queue.destination.type = DPNI_DEST_DPCON;
queue.destination.priority = 1;
queue.user_context = (u64)(uintptr_t)fq;
+ queue.flc.stash_control = 1;
+ queue.flc.value &= 0xFFFFFFFFFFFFFFC0;
+ /* 01 01 00 - data, annotation, flow context */
+ queue.flc.value |= 0x14;
err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
DPNI_QUEUE_RX, 0, fq->flowid,
- DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
+ DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST |
+ DPNI_QUEUE_OPT_FLC,
&queue);
if (err) {
dev_err(dev, "dpni_set_queue(RX) failed\n");
@@ -2320,6 +2491,21 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv,
return err;
}
+ /* xdp_rxq setup */
+ err = xdp_rxq_info_reg(&fq->channel->xdp_rxq, priv->net_dev,
+ fq->flowid);
+ if (err) {
+ dev_err(dev, "xdp_rxq_info_reg failed\n");
+ return err;
+ }
+
+ err = xdp_rxq_info_reg_mem_model(&fq->channel->xdp_rxq,
+ MEM_TYPE_PAGE_ORDER0, NULL);
+ if (err) {
+ dev_err(dev, "xdp_rxq_info_reg_mem_model failed\n");
+ return err;
+ }
+
return 0;
}
@@ -2339,6 +2525,7 @@ static int setup_tx_flow(struct dpaa2_eth_priv *priv,
}
fq->tx_qdbin = qid.qdbin;
+ fq->tx_fqid = qid.fqid;
err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid,
@@ -3083,6 +3270,10 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
goto err_netdev_reg;
}
+#ifdef CONFIG_DEBUG_FS
+ dpaa2_dbg_add(priv);
+#endif
+
dev_info(dev, "Probed interface %s\n", net_dev->name);
return 0;
@@ -3126,6 +3317,9 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
net_dev = dev_get_drvdata(dev);
priv = netdev_priv(net_dev);
+#ifdef CONFIG_DEBUG_FS
+ dpaa2_dbg_remove(priv);
+#endif
unregister_netdev(net_dev);
if (priv->do_link_poll)
@@ -3170,4 +3364,25 @@ static struct fsl_mc_driver dpaa2_eth_driver = {
.match_id_table = dpaa2_eth_match_id_table
};
-module_fsl_mc_driver(dpaa2_eth_driver);
+static int __init dpaa2_eth_driver_init(void)
+{
+ int err;
+
+ dpaa2_eth_dbg_init();
+ err = fsl_mc_driver_register(&dpaa2_eth_driver);
+ if (err) {
+ dpaa2_eth_dbg_exit();
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit dpaa2_eth_driver_exit(void)
+{
+ dpaa2_eth_dbg_exit();
+ fsl_mc_driver_unregister(&dpaa2_eth_driver);
+}
+
+module_init(dpaa2_eth_driver_init);
+module_exit(dpaa2_eth_driver_exit);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
index 69c965de192b..7879622aa3e6 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
@@ -16,6 +16,7 @@
#include "dpni-cmd.h"
#include "dpaa2-eth-trace.h"
+#include "dpaa2-eth-debugfs.h"
#define DPAA2_WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0)
@@ -52,7 +53,8 @@
*/
#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE (DPAA2_ETH_TAILDROP_THRESH / 64)
#define DPAA2_ETH_NUM_BUFS (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
-#define DPAA2_ETH_REFILL_THRESH DPAA2_ETH_MAX_FRAMES_PER_QUEUE
+#define DPAA2_ETH_REFILL_THRESH \
+ (DPAA2_ETH_NUM_BUFS - DPAA2_ETH_BUFS_PER_CMD)
/* Maximum number of buffers that can be acquired/released through a single
* QBMan command
@@ -62,9 +64,11 @@
/* Hardware requires alignment for ingress/egress buffer addresses */
#define DPAA2_ETH_TX_BUF_ALIGN 64
-#define DPAA2_ETH_RX_BUF_SIZE 2048
-#define DPAA2_ETH_SKB_SIZE \
- (DPAA2_ETH_RX_BUF_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+#define DPAA2_ETH_RX_BUF_RAW_SIZE PAGE_SIZE
+#define DPAA2_ETH_RX_BUF_TAILROOM \
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
+#define DPAA2_ETH_RX_BUF_SIZE \
+ (DPAA2_ETH_RX_BUF_RAW_SIZE - DPAA2_ETH_RX_BUF_TAILROOM)
/* Hardware annotation area in RX/TX buffers */
#define DPAA2_ETH_RX_HWA_SIZE 64
@@ -85,12 +89,33 @@
*/
#define DPAA2_ETH_SWA_SIZE 64
+/* We store different information in the software annotation area of a Tx frame
+ * based on what type of frame it is
+ */
+enum dpaa2_eth_swa_type {
+ DPAA2_ETH_SWA_SINGLE,
+ DPAA2_ETH_SWA_SG,
+ DPAA2_ETH_SWA_XDP,
+};
+
/* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */
struct dpaa2_eth_swa {
- struct sk_buff *skb;
- struct scatterlist *scl;
- int num_sg;
- int sgt_size;
+ enum dpaa2_eth_swa_type type;
+ union {
+ struct {
+ struct sk_buff *skb;
+ } single;
+ struct {
+ struct sk_buff *skb;
+ struct scatterlist *scl;
+ int num_sg;
+ int sgt_size;
+ } sg;
+ struct {
+ int dma_size;
+ struct xdp_frame *xdpf;
+ } xdp;
+ };
};
/* Annotation valid bits in FD FRC */
@@ -253,6 +278,7 @@ struct dpaa2_eth_ch_stats {
__u64 xdp_drop;
__u64 xdp_tx;
__u64 xdp_tx_err;
+ __u64 xdp_redirect;
};
/* Maximum number of queues associated with a DPNI */
@@ -273,6 +299,7 @@ struct dpaa2_eth_priv;
struct dpaa2_eth_fq {
u32 fqid;
u32 tx_qdbin;
+ u32 tx_fqid;
u16 flowid;
int target_cpu;
u32 dq_frames;
@@ -291,6 +318,7 @@ struct dpaa2_eth_ch_xdp {
struct bpf_prog *prog;
u64 drop_bufs[DPAA2_ETH_BUFS_PER_CMD];
int drop_cnt;
+ unsigned int res;
};
struct dpaa2_eth_channel {
@@ -305,6 +333,7 @@ struct dpaa2_eth_channel {
int buf_count;
struct dpaa2_eth_ch_stats stats;
struct dpaa2_eth_ch_xdp xdp;
+ struct xdp_rxq_info xdp_rxq;
};
struct dpaa2_eth_dist_fields {
@@ -325,6 +354,9 @@ struct dpaa2_eth_priv {
u8 num_fqs;
struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES];
+ int (*enqueue)(struct dpaa2_eth_priv *priv,
+ struct dpaa2_eth_fq *fq,
+ struct dpaa2_fd *fd, u8 prio);
u8 num_channels;
struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
@@ -342,7 +374,6 @@ struct dpaa2_eth_priv {
bool rx_tstamp; /* Rx timestamping enabled */
u16 tx_qdid;
- u16 rx_buf_align;
struct fsl_mc_io *mc_io;
/* Cores which have an affine DPIO/DPCON.
* This is the cpu set on which Rx and Tx conf frames are processed
@@ -365,6 +396,9 @@ struct dpaa2_eth_priv {
struct dpaa2_eth_cls_rule *cls_rules;
u8 rx_cls_enabled;
struct bpf_prog *xdp_prog;
+#ifdef CONFIG_DEBUG_FS
+ struct dpaa2_debugfs dbg;
+#endif
};
#define DPAA2_RXH_SUPPORTED (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \
@@ -405,26 +439,27 @@ static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv,
#define dpaa2_eth_fs_count(priv) \
((priv)->dpni_attrs.fs_entries)
+/* We have exactly one {Rx, Tx conf} queue per channel */
+#define dpaa2_eth_queue_count(priv) \
+ ((priv)->num_channels)
+
enum dpaa2_eth_rx_dist {
DPAA2_ETH_RX_DIST_HASH,
DPAA2_ETH_RX_DIST_CLS
};
-/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around
- * the buffer also needs space for its shared info struct, and we need
- * to allocate enough to accommodate hardware alignment restrictions
- */
-static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv)
-{
- return DPAA2_ETH_SKB_SIZE + priv->rx_buf_align;
-}
-
static inline
unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
struct sk_buff *skb)
{
unsigned int headroom = DPAA2_ETH_SWA_SIZE;
+ /* If we don't have an skb (e.g. XDP buffer), we only need space for
+ * the software annotation area
+ */
+ if (!skb)
+ return headroom;
+
/* For non-linear skbs we have no headroom requirement, as we build a
* SG frame with a newly allocated SGT buffer
*/
@@ -443,14 +478,7 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
*/
static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv)
{
- return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN -
- DPAA2_ETH_RX_HWA_SIZE;
-}
-
-/* We have exactly one {Rx, Tx conf} queue per channel */
-static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
-{
- return priv->num_channels;
+ return priv->tx_data_offset - DPAA2_ETH_RX_HWA_SIZE;
}
int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
index a7389e722c49..591dfcf76adb 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
@@ -48,6 +48,7 @@ static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
"[drv] xdp drop",
"[drv] xdp tx",
"[drv] xdp tx errors",
+ "[drv] xdp redirect",
/* FQ stats */
"[qbman] rx pending frames",
"[qbman] rx pending bytes",
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
new file mode 100644
index 000000000000..8429f5c1d810
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0
+config FSL_ENETC
+ tristate "ENETC PF driver"
+ depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+ help
+ This driver supports NXP ENETC gigabit ethernet controller PCIe
+ physical function (PF) devices, managing ENETC Ports at a privileged
+ level.
+
+ If compiled as module (M), the module name is fsl-enetc.
+
+config FSL_ENETC_VF
+ tristate "ENETC VF driver"
+ depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+ help
+ This driver supports NXP ENETC gigabit ethernet controller PCIe
+ virtual function (VF) devices enabled by the ENETC PF driver.
+
+ If compiled as module (M), the module name is fsl-enetc-vf.
+
+config FSL_ENETC_PTP_CLOCK
+ tristate "ENETC PTP clock driver"
+ depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF)
+ default y
+ help
+ This driver adds support for using the ENETC 1588 timer
+ as a PTP clock. This clock is only useful if your PTP
+ programs are getting hardware time stamps on the PTP Ethernet
+ packets using the SO_TIMESTAMPING API.
+
+ If compiled as module (M), the module name is fsl-enetc-ptp.
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
new file mode 100644
index 000000000000..7139e414dccf
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
+fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o \
+ enetc_mdio.o
+fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
+fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y)
+
+obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
+
+ifeq ($(CONFIG_FSL_ENETC)$(CONFIG_FSL_ENETC_VF), yy)
+fsl-enetc-vf-objs := enetc_vf.o
+else
+fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \
+ enetc_ethtool.o
+fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y)
+endif
+
+obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o
+fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
new file mode 100644
index 000000000000..5bb9eb35d76d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -0,0 +1,1604 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include "enetc.h"
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/of_mdio.h>
+#include <linux/vmalloc.h>
+
+/* ENETC overhead: optional extension BD + 1 BD gap */
+#define ENETC_TXBDS_NEEDED(val) ((val) + 2)
+/* max # of chained Tx BDs is 15, including head and extension BD */
+#define ENETC_MAX_SKB_FRAGS 13
+#define ENETC_TXBDS_MAX_NEEDED ENETC_TXBDS_NEEDED(ENETC_MAX_SKB_FRAGS + 1)
+
+static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb);
+
+netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_bdr *tx_ring;
+ int count;
+
+ tx_ring = priv->tx_ring[skb->queue_mapping];
+
+ if (unlikely(skb_shinfo(skb)->nr_frags > ENETC_MAX_SKB_FRAGS))
+ if (unlikely(skb_linearize(skb)))
+ goto drop_packet_err;
+
+ count = skb_shinfo(skb)->nr_frags + 1; /* fragments + head */
+ if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_NEEDED(count)) {
+ netif_stop_subqueue(ndev, tx_ring->index);
+ return NETDEV_TX_BUSY;
+ }
+
+ count = enetc_map_tx_buffs(tx_ring, skb);
+ if (unlikely(!count))
+ goto drop_packet_err;
+
+ if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED)
+ netif_stop_subqueue(ndev, tx_ring->index);
+
+ return NETDEV_TX_OK;
+
+drop_packet_err:
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static bool enetc_tx_csum(struct sk_buff *skb, union enetc_tx_bd *txbd)
+{
+ int l3_start, l3_hsize;
+ u16 l3_flags, l4_flags;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return false;
+
+ switch (skb->csum_offset) {
+ case offsetof(struct tcphdr, check):
+ l4_flags = ENETC_TXBD_L4_TCP;
+ break;
+ case offsetof(struct udphdr, check):
+ l4_flags = ENETC_TXBD_L4_UDP;
+ break;
+ default:
+ skb_checksum_help(skb);
+ return false;
+ }
+
+ l3_start = skb_network_offset(skb);
+ l3_hsize = skb_network_header_len(skb);
+
+ l3_flags = 0;
+ if (skb->protocol == htons(ETH_P_IPV6))
+ l3_flags = ENETC_TXBD_L3_IPV6;
+
+ /* write BD fields */
+ txbd->l3_csoff = enetc_txbd_l3_csoff(l3_start, l3_hsize, l3_flags);
+ txbd->l4_csoff = l4_flags;
+
+ return true;
+}
+
+static void enetc_unmap_tx_buff(struct enetc_bdr *tx_ring,
+ struct enetc_tx_swbd *tx_swbd)
+{
+ if (tx_swbd->is_dma_page)
+ dma_unmap_page(tx_ring->dev, tx_swbd->dma,
+ tx_swbd->len, DMA_TO_DEVICE);
+ else
+ dma_unmap_single(tx_ring->dev, tx_swbd->dma,
+ tx_swbd->len, DMA_TO_DEVICE);
+ tx_swbd->dma = 0;
+}
+
+static void enetc_free_tx_skb(struct enetc_bdr *tx_ring,
+ struct enetc_tx_swbd *tx_swbd)
+{
+ if (tx_swbd->dma)
+ enetc_unmap_tx_buff(tx_ring, tx_swbd);
+
+ if (tx_swbd->skb) {
+ dev_kfree_skb_any(tx_swbd->skb);
+ tx_swbd->skb = NULL;
+ }
+}
+
+static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
+{
+ struct enetc_tx_swbd *tx_swbd;
+ struct skb_frag_struct *frag;
+ int len = skb_headlen(skb);
+ union enetc_tx_bd temp_bd;
+ union enetc_tx_bd *txbd;
+ bool do_vlan, do_tstamp;
+ int i, count = 0;
+ unsigned int f;
+ dma_addr_t dma;
+ u8 flags = 0;
+
+ i = tx_ring->next_to_use;
+ txbd = ENETC_TXBD(*tx_ring, i);
+ prefetchw(txbd);
+
+ dma = dma_map_single(tx_ring->dev, skb->data, len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(tx_ring->dev, dma)))
+ goto dma_err;
+
+ temp_bd.addr = cpu_to_le64(dma);
+ temp_bd.buf_len = cpu_to_le16(len);
+ temp_bd.lstatus = 0;
+
+ tx_swbd = &tx_ring->tx_swbd[i];
+ tx_swbd->dma = dma;
+ tx_swbd->len = len;
+ tx_swbd->is_dma_page = 0;
+ count++;
+
+ do_vlan = skb_vlan_tag_present(skb);
+ do_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
+
+ if (do_vlan || do_tstamp)
+ flags |= ENETC_TXBD_FLAGS_EX;
+
+ if (enetc_tx_csum(skb, &temp_bd))
+ flags |= ENETC_TXBD_FLAGS_CSUM | ENETC_TXBD_FLAGS_L4CS;
+
+ /* first BD needs frm_len and offload flags set */
+ temp_bd.frm_len = cpu_to_le16(skb->len);
+ temp_bd.flags = flags;
+
+ if (flags & ENETC_TXBD_FLAGS_EX) {
+ u8 e_flags = 0;
+ *txbd = temp_bd;
+ enetc_clear_tx_bd(&temp_bd);
+
+ /* add extension BD for VLAN and/or timestamping */
+ flags = 0;
+ tx_swbd++;
+ txbd++;
+ i++;
+ if (unlikely(i == tx_ring->bd_count)) {
+ i = 0;
+ tx_swbd = tx_ring->tx_swbd;
+ txbd = ENETC_TXBD(*tx_ring, 0);
+ }
+ prefetchw(txbd);
+
+ if (do_vlan) {
+ temp_bd.ext.vid = cpu_to_le16(skb_vlan_tag_get(skb));
+ temp_bd.ext.tpid = 0; /* < C-TAG */
+ e_flags |= ENETC_TXBD_E_FLAGS_VLAN_INS;
+ }
+
+ if (do_tstamp) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ e_flags |= ENETC_TXBD_E_FLAGS_TWO_STEP_PTP;
+ }
+
+ temp_bd.ext.e_flags = e_flags;
+ count++;
+ }
+
+ frag = &skb_shinfo(skb)->frags[0];
+ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++, frag++) {
+ len = skb_frag_size(frag);
+ dma = skb_frag_dma_map(tx_ring->dev, frag, 0, len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(tx_ring->dev, dma))
+ goto dma_err;
+
+ *txbd = temp_bd;
+ enetc_clear_tx_bd(&temp_bd);
+
+ flags = 0;
+ tx_swbd++;
+ txbd++;
+ i++;
+ if (unlikely(i == tx_ring->bd_count)) {
+ i = 0;
+ tx_swbd = tx_ring->tx_swbd;
+ txbd = ENETC_TXBD(*tx_ring, 0);
+ }
+ prefetchw(txbd);
+
+ temp_bd.addr = cpu_to_le64(dma);
+ temp_bd.buf_len = cpu_to_le16(len);
+
+ tx_swbd->dma = dma;
+ tx_swbd->len = len;
+ tx_swbd->is_dma_page = 1;
+ count++;
+ }
+
+ /* last BD needs 'F' bit set */
+ flags |= ENETC_TXBD_FLAGS_F;
+ temp_bd.flags = flags;
+ *txbd = temp_bd;
+
+ tx_ring->tx_swbd[i].skb = skb;
+
+ enetc_bdr_idx_inc(tx_ring, &i);
+ tx_ring->next_to_use = i;
+
+ /* let H/W know BD ring has been updated */
+ enetc_wr_reg(tx_ring->tpir, i); /* includes wmb() */
+
+ return count;
+
+dma_err:
+ dev_err(tx_ring->dev, "DMA map error");
+
+ do {
+ tx_swbd = &tx_ring->tx_swbd[i];
+ enetc_free_tx_skb(tx_ring, tx_swbd);
+ if (i == 0)
+ i = tx_ring->bd_count;
+ i--;
+ } while (count--);
+
+ return 0;
+}
+
+static irqreturn_t enetc_msix(int irq, void *data)
+{
+ struct enetc_int_vector *v = data;
+ int i;
+
+ /* disable interrupts */
+ enetc_wr_reg(v->rbier, 0);
+
+ for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+ enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), 0);
+
+ napi_schedule_irqoff(&v->napi);
+
+ return IRQ_HANDLED;
+}
+
+static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget);
+static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
+ struct napi_struct *napi, int work_limit);
+
+static int enetc_poll(struct napi_struct *napi, int budget)
+{
+ struct enetc_int_vector
+ *v = container_of(napi, struct enetc_int_vector, napi);
+ bool complete = true;
+ int work_done;
+ int i;
+
+ for (i = 0; i < v->count_tx_rings; i++)
+ if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
+ complete = false;
+
+ work_done = enetc_clean_rx_ring(&v->rx_ring, napi, budget);
+ if (work_done == budget)
+ complete = false;
+
+ if (!complete)
+ return budget;
+
+ napi_complete_done(napi, work_done);
+
+ /* enable interrupts */
+ enetc_wr_reg(v->rbier, ENETC_RBIER_RXTIE);
+
+ for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+ enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i),
+ ENETC_TBIER_TXTIE);
+
+ return work_done;
+}
+
+static int enetc_bd_ready_count(struct enetc_bdr *tx_ring, int ci)
+{
+ int pi = enetc_rd_reg(tx_ring->tcir) & ENETC_TBCIR_IDX_MASK;
+
+ return pi >= ci ? pi - ci : tx_ring->bd_count - ci + pi;
+}
+
+static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
+{
+ struct net_device *ndev = tx_ring->ndev;
+ int tx_frm_cnt = 0, tx_byte_cnt = 0;
+ struct enetc_tx_swbd *tx_swbd;
+ int i, bds_to_clean;
+
+ i = tx_ring->next_to_clean;
+ tx_swbd = &tx_ring->tx_swbd[i];
+ bds_to_clean = enetc_bd_ready_count(tx_ring, i);
+
+ while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) {
+ bool is_eof = !!tx_swbd->skb;
+
+ enetc_unmap_tx_buff(tx_ring, tx_swbd);
+ if (is_eof) {
+ napi_consume_skb(tx_swbd->skb, napi_budget);
+ tx_swbd->skb = NULL;
+ }
+
+ tx_byte_cnt += tx_swbd->len;
+
+ bds_to_clean--;
+ tx_swbd++;
+ i++;
+ if (unlikely(i == tx_ring->bd_count)) {
+ i = 0;
+ tx_swbd = tx_ring->tx_swbd;
+ }
+
+ /* BD iteration loop end */
+ if (is_eof) {
+ tx_frm_cnt++;
+ /* re-arm interrupt source */
+ enetc_wr_reg(tx_ring->idr, BIT(tx_ring->index) |
+ BIT(16 + tx_ring->index));
+ }
+
+ if (unlikely(!bds_to_clean))
+ bds_to_clean = enetc_bd_ready_count(tx_ring, i);
+ }
+
+ tx_ring->next_to_clean = i;
+ tx_ring->stats.packets += tx_frm_cnt;
+ tx_ring->stats.bytes += tx_byte_cnt;
+
+ if (unlikely(tx_frm_cnt && netif_carrier_ok(ndev) &&
+ __netif_subqueue_stopped(ndev, tx_ring->index) &&
+ (enetc_bd_unused(tx_ring) >= ENETC_TXBDS_MAX_NEEDED))) {
+ netif_wake_subqueue(ndev, tx_ring->index);
+ }
+
+ return tx_frm_cnt != ENETC_DEFAULT_TX_WORK;
+}
+
+static bool enetc_new_page(struct enetc_bdr *rx_ring,
+ struct enetc_rx_swbd *rx_swbd)
+{
+ struct page *page;
+ dma_addr_t addr;
+
+ page = dev_alloc_page();
+ if (unlikely(!page))
+ return false;
+
+ addr = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(rx_ring->dev, addr))) {
+ __free_page(page);
+
+ return false;
+ }
+
+ rx_swbd->dma = addr;
+ rx_swbd->page = page;
+ rx_swbd->page_offset = ENETC_RXB_PAD;
+
+ return true;
+}
+
+static int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
+{
+ struct enetc_rx_swbd *rx_swbd;
+ union enetc_rx_bd *rxbd;
+ int i, j;
+
+ i = rx_ring->next_to_use;
+ rx_swbd = &rx_ring->rx_swbd[i];
+ rxbd = ENETC_RXBD(*rx_ring, i);
+
+ for (j = 0; j < buff_cnt; j++) {
+ /* try reuse page */
+ if (unlikely(!rx_swbd->page)) {
+ if (unlikely(!enetc_new_page(rx_ring, rx_swbd))) {
+ rx_ring->stats.rx_alloc_errs++;
+ break;
+ }
+ }
+
+ /* update RxBD */
+ rxbd->w.addr = cpu_to_le64(rx_swbd->dma +
+ rx_swbd->page_offset);
+ /* clear 'R" as well */
+ rxbd->r.lstatus = 0;
+
+ rx_swbd++;
+ rxbd++;
+ i++;
+ if (unlikely(i == rx_ring->bd_count)) {
+ i = 0;
+ rx_swbd = rx_ring->rx_swbd;
+ rxbd = ENETC_RXBD(*rx_ring, 0);
+ }
+ }
+
+ if (likely(j)) {
+ rx_ring->next_to_alloc = i; /* keep track from page reuse */
+ rx_ring->next_to_use = i;
+ /* update ENETC's consumer index */
+ enetc_wr_reg(rx_ring->rcir, i);
+ }
+
+ return j;
+}
+
+static void enetc_get_offloads(struct enetc_bdr *rx_ring,
+ union enetc_rx_bd *rxbd, struct sk_buff *skb)
+{
+ /* TODO: add tstamp, hashing */
+ if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
+ u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
+
+ skb->csum = csum_unfold((__force __sum16)~htons(inet_csum));
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+
+ /* copy VLAN to skb, if one is extracted, for now we assume it's a
+ * standard TPID, but HW also supports custom values
+ */
+ if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ le16_to_cpu(rxbd->r.vlan_opt));
+}
+
+static void enetc_process_skb(struct enetc_bdr *rx_ring,
+ struct sk_buff *skb)
+{
+ skb_record_rx_queue(skb, rx_ring->index);
+ skb->protocol = eth_type_trans(skb, rx_ring->ndev);
+}
+
+static bool enetc_page_reusable(struct page *page)
+{
+ return (!page_is_pfmemalloc(page) && page_ref_count(page) == 1);
+}
+
+static void enetc_reuse_page(struct enetc_bdr *rx_ring,
+ struct enetc_rx_swbd *old)
+{
+ struct enetc_rx_swbd *new;
+
+ new = &rx_ring->rx_swbd[rx_ring->next_to_alloc];
+
+ /* next buf that may reuse a page */
+ enetc_bdr_idx_inc(rx_ring, &rx_ring->next_to_alloc);
+
+ /* copy page reference */
+ *new = *old;
+}
+
+static struct enetc_rx_swbd *enetc_get_rx_buff(struct enetc_bdr *rx_ring,
+ int i, u16 size)
+{
+ struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[i];
+
+ dma_sync_single_range_for_cpu(rx_ring->dev, rx_swbd->dma,
+ rx_swbd->page_offset,
+ size, DMA_FROM_DEVICE);
+ return rx_swbd;
+}
+
+static void enetc_put_rx_buff(struct enetc_bdr *rx_ring,
+ struct enetc_rx_swbd *rx_swbd)
+{
+ if (likely(enetc_page_reusable(rx_swbd->page))) {
+ rx_swbd->page_offset ^= ENETC_RXB_TRUESIZE;
+ page_ref_inc(rx_swbd->page);
+
+ enetc_reuse_page(rx_ring, rx_swbd);
+
+ /* sync for use by the device */
+ dma_sync_single_range_for_device(rx_ring->dev, rx_swbd->dma,
+ rx_swbd->page_offset,
+ ENETC_RXB_DMA_SIZE,
+ DMA_FROM_DEVICE);
+ } else {
+ dma_unmap_page(rx_ring->dev, rx_swbd->dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ }
+
+ rx_swbd->page = NULL;
+}
+
+static struct sk_buff *enetc_map_rx_buff_to_skb(struct enetc_bdr *rx_ring,
+ int i, u16 size)
+{
+ struct enetc_rx_swbd *rx_swbd = enetc_get_rx_buff(rx_ring, i, size);
+ struct sk_buff *skb;
+ void *ba;
+
+ ba = page_address(rx_swbd->page) + rx_swbd->page_offset;
+ skb = build_skb(ba - ENETC_RXB_PAD, ENETC_RXB_TRUESIZE);
+ if (unlikely(!skb)) {
+ rx_ring->stats.rx_alloc_errs++;
+ return NULL;
+ }
+
+ skb_reserve(skb, ENETC_RXB_PAD);
+ __skb_put(skb, size);
+
+ enetc_put_rx_buff(rx_ring, rx_swbd);
+
+ return skb;
+}
+
+static void enetc_add_rx_buff_to_skb(struct enetc_bdr *rx_ring, int i,
+ u16 size, struct sk_buff *skb)
+{
+ struct enetc_rx_swbd *rx_swbd = enetc_get_rx_buff(rx_ring, i, size);
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_swbd->page,
+ rx_swbd->page_offset, size, ENETC_RXB_TRUESIZE);
+
+ enetc_put_rx_buff(rx_ring, rx_swbd);
+}
+
+#define ENETC_RXBD_BUNDLE 16 /* # of BDs to update at once */
+
+static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
+ struct napi_struct *napi, int work_limit)
+{
+ int rx_frm_cnt = 0, rx_byte_cnt = 0;
+ int cleaned_cnt, i;
+
+ cleaned_cnt = enetc_bd_unused(rx_ring);
+ /* next descriptor to process */
+ i = rx_ring->next_to_clean;
+
+ while (likely(rx_frm_cnt < work_limit)) {
+ union enetc_rx_bd *rxbd;
+ struct sk_buff *skb;
+ u32 bd_status;
+ u16 size;
+
+ if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
+ int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
+
+ cleaned_cnt -= count;
+ }
+
+ rxbd = ENETC_RXBD(*rx_ring, i);
+ bd_status = le32_to_cpu(rxbd->r.lstatus);
+ if (!bd_status)
+ break;
+
+ enetc_wr_reg(rx_ring->idr, BIT(rx_ring->index));
+ dma_rmb(); /* for reading other rxbd fields */
+ size = le16_to_cpu(rxbd->r.buf_len);
+ skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
+ if (!skb)
+ break;
+
+ enetc_get_offloads(rx_ring, rxbd, skb);
+
+ cleaned_cnt++;
+ rxbd++;
+ i++;
+ if (unlikely(i == rx_ring->bd_count)) {
+ i = 0;
+ rxbd = ENETC_RXBD(*rx_ring, 0);
+ }
+
+ if (unlikely(bd_status &
+ ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
+ dev_kfree_skb(skb);
+ while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
+ dma_rmb();
+ bd_status = le32_to_cpu(rxbd->r.lstatus);
+ rxbd++;
+ i++;
+ if (unlikely(i == rx_ring->bd_count)) {
+ i = 0;
+ rxbd = ENETC_RXBD(*rx_ring, 0);
+ }
+ }
+
+ rx_ring->ndev->stats.rx_dropped++;
+ rx_ring->ndev->stats.rx_errors++;
+
+ break;
+ }
+
+ /* not last BD in frame? */
+ while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
+ bd_status = le32_to_cpu(rxbd->r.lstatus);
+ size = ENETC_RXB_DMA_SIZE;
+
+ if (bd_status & ENETC_RXBD_LSTATUS_F) {
+ dma_rmb();
+ size = le16_to_cpu(rxbd->r.buf_len);
+ }
+
+ enetc_add_rx_buff_to_skb(rx_ring, i, size, skb);
+
+ cleaned_cnt++;
+ rxbd++;
+ i++;
+ if (unlikely(i == rx_ring->bd_count)) {
+ i = 0;
+ rxbd = ENETC_RXBD(*rx_ring, 0);
+ }
+ }
+
+ rx_byte_cnt += skb->len;
+
+ enetc_process_skb(rx_ring, skb);
+
+ napi_gro_receive(napi, skb);
+
+ rx_frm_cnt++;
+ }
+
+ rx_ring->next_to_clean = i;
+
+ rx_ring->stats.packets += rx_frm_cnt;
+ rx_ring->stats.bytes += rx_byte_cnt;
+
+ return rx_frm_cnt;
+}
+
+/* Probing and Init */
+#define ENETC_MAX_RFS_SIZE 64
+void enetc_get_si_caps(struct enetc_si *si)
+{
+ struct enetc_hw *hw = &si->hw;
+ u32 val;
+
+ /* find out how many of various resources we have to work with */
+ val = enetc_rd(hw, ENETC_SICAPR0);
+ si->num_rx_rings = (val >> 16) & 0xff;
+ si->num_tx_rings = val & 0xff;
+
+ val = enetc_rd(hw, ENETC_SIRFSCAPR);
+ si->num_fs_entries = ENETC_SIRFSCAPR_GET_NUM_RFS(val);
+ si->num_fs_entries = min(si->num_fs_entries, ENETC_MAX_RFS_SIZE);
+
+ si->num_rss = 0;
+ val = enetc_rd(hw, ENETC_SIPCAPR0);
+ if (val & ENETC_SIPCAPR0_RSS) {
+ val = enetc_rd(hw, ENETC_SIRSSCAPR);
+ si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(val);
+ }
+}
+
+static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size)
+{
+ r->bd_base = dma_alloc_coherent(r->dev, r->bd_count * bd_size,
+ &r->bd_dma_base, GFP_KERNEL);
+ if (!r->bd_base)
+ return -ENOMEM;
+
+ /* h/w requires 128B alignment */
+ if (!IS_ALIGNED(r->bd_dma_base, 128)) {
+ dma_free_coherent(r->dev, r->bd_count * bd_size, r->bd_base,
+ r->bd_dma_base);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int enetc_alloc_txbdr(struct enetc_bdr *txr)
+{
+ int err;
+
+ txr->tx_swbd = vzalloc(txr->bd_count * sizeof(struct enetc_tx_swbd));
+ if (!txr->tx_swbd)
+ return -ENOMEM;
+
+ err = enetc_dma_alloc_bdr(txr, sizeof(union enetc_tx_bd));
+ if (err) {
+ vfree(txr->tx_swbd);
+ return err;
+ }
+
+ txr->next_to_clean = 0;
+ txr->next_to_use = 0;
+
+ return 0;
+}
+
+static void enetc_free_txbdr(struct enetc_bdr *txr)
+{
+ int size, i;
+
+ for (i = 0; i < txr->bd_count; i++)
+ enetc_free_tx_skb(txr, &txr->tx_swbd[i]);
+
+ size = txr->bd_count * sizeof(union enetc_tx_bd);
+
+ dma_free_coherent(txr->dev, size, txr->bd_base, txr->bd_dma_base);
+ txr->bd_base = NULL;
+
+ vfree(txr->tx_swbd);
+ txr->tx_swbd = NULL;
+}
+
+static int enetc_alloc_tx_resources(struct enetc_ndev_priv *priv)
+{
+ int i, err;
+
+ for (i = 0; i < priv->num_tx_rings; i++) {
+ err = enetc_alloc_txbdr(priv->tx_ring[i]);
+
+ if (err)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ while (i-- > 0)
+ enetc_free_txbdr(priv->tx_ring[i]);
+
+ return err;
+}
+
+static void enetc_free_tx_resources(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ enetc_free_txbdr(priv->tx_ring[i]);
+}
+
+static int enetc_alloc_rxbdr(struct enetc_bdr *rxr)
+{
+ int err;
+
+ rxr->rx_swbd = vzalloc(rxr->bd_count * sizeof(struct enetc_rx_swbd));
+ if (!rxr->rx_swbd)
+ return -ENOMEM;
+
+ err = enetc_dma_alloc_bdr(rxr, sizeof(union enetc_rx_bd));
+ if (err) {
+ vfree(rxr->rx_swbd);
+ return err;
+ }
+
+ rxr->next_to_clean = 0;
+ rxr->next_to_use = 0;
+ rxr->next_to_alloc = 0;
+
+ return 0;
+}
+
+static void enetc_free_rxbdr(struct enetc_bdr *rxr)
+{
+ int size;
+
+ size = rxr->bd_count * sizeof(union enetc_rx_bd);
+
+ dma_free_coherent(rxr->dev, size, rxr->bd_base, rxr->bd_dma_base);
+ rxr->bd_base = NULL;
+
+ vfree(rxr->rx_swbd);
+ rxr->rx_swbd = NULL;
+}
+
+static int enetc_alloc_rx_resources(struct enetc_ndev_priv *priv)
+{
+ int i, err;
+
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ err = enetc_alloc_rxbdr(priv->rx_ring[i]);
+
+ if (err)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ while (i-- > 0)
+ enetc_free_rxbdr(priv->rx_ring[i]);
+
+ return err;
+}
+
+static void enetc_free_rx_resources(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ enetc_free_rxbdr(priv->rx_ring[i]);
+}
+
+static void enetc_free_tx_ring(struct enetc_bdr *tx_ring)
+{
+ int i;
+
+ if (!tx_ring->tx_swbd)
+ return;
+
+ for (i = 0; i < tx_ring->bd_count; i++) {
+ struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i];
+
+ enetc_free_tx_skb(tx_ring, tx_swbd);
+ }
+
+ tx_ring->next_to_clean = 0;
+ tx_ring->next_to_use = 0;
+}
+
+static void enetc_free_rx_ring(struct enetc_bdr *rx_ring)
+{
+ int i;
+
+ if (!rx_ring->rx_swbd)
+ return;
+
+ for (i = 0; i < rx_ring->bd_count; i++) {
+ struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[i];
+
+ if (!rx_swbd->page)
+ continue;
+
+ dma_unmap_page(rx_ring->dev, rx_swbd->dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ __free_page(rx_swbd->page);
+ rx_swbd->page = NULL;
+ }
+
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+ rx_ring->next_to_alloc = 0;
+}
+
+static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ enetc_free_rx_ring(priv->rx_ring[i]);
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ enetc_free_tx_ring(priv->tx_ring[i]);
+}
+
+static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+{
+ int size = cbdr->bd_count * sizeof(struct enetc_cbd);
+
+ cbdr->bd_base = dma_alloc_coherent(dev, size, &cbdr->bd_dma_base,
+ GFP_KERNEL);
+ if (!cbdr->bd_base)
+ return -ENOMEM;
+
+ /* h/w requires 128B alignment */
+ if (!IS_ALIGNED(cbdr->bd_dma_base, 128)) {
+ dma_free_coherent(dev, size, cbdr->bd_base, cbdr->bd_dma_base);
+ return -EINVAL;
+ }
+
+ cbdr->next_to_clean = 0;
+ cbdr->next_to_use = 0;
+
+ return 0;
+}
+
+static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+{
+ int size = cbdr->bd_count * sizeof(struct enetc_cbd);
+
+ dma_free_coherent(dev, size, cbdr->bd_base, cbdr->bd_dma_base);
+ cbdr->bd_base = NULL;
+}
+
+static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
+{
+ /* set CBDR cache attributes */
+ enetc_wr(hw, ENETC_SICAR2,
+ ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+
+ enetc_wr(hw, ENETC_SICBDRBAR0, lower_32_bits(cbdr->bd_dma_base));
+ enetc_wr(hw, ENETC_SICBDRBAR1, upper_32_bits(cbdr->bd_dma_base));
+ enetc_wr(hw, ENETC_SICBDRLENR, ENETC_RTBLENR_LEN(cbdr->bd_count));
+
+ enetc_wr(hw, ENETC_SICBDRPIR, 0);
+ enetc_wr(hw, ENETC_SICBDRCIR, 0);
+
+ /* enable ring */
+ enetc_wr(hw, ENETC_SICBDRMR, BIT(31));
+
+ cbdr->pir = hw->reg + ENETC_SICBDRPIR;
+ cbdr->cir = hw->reg + ENETC_SICBDRCIR;
+}
+
+static void enetc_clear_cbdr(struct enetc_hw *hw)
+{
+ enetc_wr(hw, ENETC_SICBDRMR, 0);
+}
+
+static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
+{
+ int *rss_table;
+ int i;
+
+ rss_table = kmalloc_array(si->num_rss, sizeof(*rss_table), GFP_KERNEL);
+ if (!rss_table)
+ return -ENOMEM;
+
+ /* Set up RSS table defaults */
+ for (i = 0; i < si->num_rss; i++)
+ rss_table[i] = i % num_groups;
+
+ enetc_set_rss_table(si, rss_table, si->num_rss);
+
+ kfree(rss_table);
+
+ return 0;
+}
+
+static int enetc_configure_si(struct enetc_ndev_priv *priv)
+{
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
+ int err;
+
+ enetc_setup_cbdr(hw, &si->cbd_ring);
+ /* set SI cache attributes */
+ enetc_wr(hw, ENETC_SICAR0,
+ ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+ enetc_wr(hw, ENETC_SICAR1, ENETC_SICAR_MSI);
+ /* enable SI */
+ enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);
+
+ if (si->num_rss) {
+ err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+void enetc_init_si_rings_params(struct enetc_ndev_priv *priv)
+{
+ struct enetc_si *si = priv->si;
+ int cpus = num_online_cpus();
+
+ priv->tx_bd_count = ENETC_BDR_DEFAULT_SIZE;
+ priv->rx_bd_count = ENETC_BDR_DEFAULT_SIZE;
+
+ /* Enable all available TX rings in order to configure as many
+ * priorities as possible, when needed.
+ * TODO: Make # of TX rings run-time configurable
+ */
+ priv->num_rx_rings = min_t(int, cpus, si->num_rx_rings);
+ priv->num_tx_rings = si->num_tx_rings;
+ priv->bdr_int_num = cpus;
+
+ /* SI specific */
+ si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
+}
+
+int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
+{
+ struct enetc_si *si = priv->si;
+ int err;
+
+ err = enetc_alloc_cbdr(priv->dev, &si->cbd_ring);
+ if (err)
+ return err;
+
+ priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
+ GFP_KERNEL);
+ if (!priv->cls_rules) {
+ err = -ENOMEM;
+ goto err_alloc_cls;
+ }
+
+ err = enetc_configure_si(priv);
+ if (err)
+ goto err_config_si;
+
+ return 0;
+
+err_config_si:
+ kfree(priv->cls_rules);
+err_alloc_cls:
+ enetc_clear_cbdr(&si->hw);
+ enetc_free_cbdr(priv->dev, &si->cbd_ring);
+
+ return err;
+}
+
+void enetc_free_si_resources(struct enetc_ndev_priv *priv)
+{
+ struct enetc_si *si = priv->si;
+
+ enetc_clear_cbdr(&si->hw);
+ enetc_free_cbdr(priv->dev, &si->cbd_ring);
+
+ kfree(priv->cls_rules);
+}
+
+static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+{
+ int idx = tx_ring->index;
+ u32 tbmr;
+
+ enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
+ lower_32_bits(tx_ring->bd_dma_base));
+
+ enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
+ upper_32_bits(tx_ring->bd_dma_base));
+
+ WARN_ON(!IS_ALIGNED(tx_ring->bd_count, 64)); /* multiple of 64 */
+ enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
+ ENETC_RTBLENR_LEN(tx_ring->bd_count));
+
+ /* clearing PI/CI registers for Tx not supported, adjust sw indexes */
+ tx_ring->next_to_use = enetc_txbdr_rd(hw, idx, ENETC_TBPIR);
+ tx_ring->next_to_clean = enetc_txbdr_rd(hw, idx, ENETC_TBCIR);
+
+ /* enable Tx ints by setting pkt thr to 1 */
+ enetc_txbdr_wr(hw, idx, ENETC_TBICIR0, ENETC_TBICIR0_ICEN | 0x1);
+
+ tbmr = ENETC_TBMR_EN;
+ if (tx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
+ tbmr |= ENETC_TBMR_VIH;
+
+ /* enable ring */
+ enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr);
+
+ tx_ring->tpir = hw->reg + ENETC_BDR(TX, idx, ENETC_TBPIR);
+ tx_ring->tcir = hw->reg + ENETC_BDR(TX, idx, ENETC_TBCIR);
+ tx_ring->idr = hw->reg + ENETC_SITXIDR;
+}
+
+static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
+{
+ int idx = rx_ring->index;
+ u32 rbmr;
+
+ enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
+ lower_32_bits(rx_ring->bd_dma_base));
+
+ enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
+ upper_32_bits(rx_ring->bd_dma_base));
+
+ WARN_ON(!IS_ALIGNED(rx_ring->bd_count, 64)); /* multiple of 64 */
+ enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
+ ENETC_RTBLENR_LEN(rx_ring->bd_count));
+
+ enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, ENETC_RXB_DMA_SIZE);
+
+ enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
+
+ /* enable Rx ints by setting pkt thr to 1 */
+ enetc_rxbdr_wr(hw, idx, ENETC_RBICIR0, ENETC_RBICIR0_ICEN | 0x1);
+
+ rbmr = ENETC_RBMR_EN;
+ if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+ rbmr |= ENETC_RBMR_VTE;
+
+ rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR);
+ rx_ring->idr = hw->reg + ENETC_SIRXIDR;
+
+ enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
+
+ /* enable ring */
+ enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
+}
+
+static void enetc_setup_bdrs(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ enetc_setup_txbdr(&priv->si->hw, priv->tx_ring[i]);
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ enetc_setup_rxbdr(&priv->si->hw, priv->rx_ring[i]);
+}
+
+static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
+{
+ int idx = rx_ring->index;
+
+ /* disable EN bit on ring */
+ enetc_rxbdr_wr(hw, idx, ENETC_RBMR, 0);
+}
+
+static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+{
+ int delay = 8, timeout = 100;
+ int idx = tx_ring->index;
+
+ /* disable EN bit on ring */
+ enetc_txbdr_wr(hw, idx, ENETC_TBMR, 0);
+
+ /* wait for busy to clear */
+ while (delay < timeout &&
+ enetc_txbdr_rd(hw, idx, ENETC_TBSR) & ENETC_TBSR_BUSY) {
+ msleep(delay);
+ delay *= 2;
+ }
+
+ if (delay >= timeout)
+ netdev_warn(tx_ring->ndev, "timeout for tx ring #%d clear\n",
+ idx);
+}
+
+static void enetc_clear_bdrs(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ enetc_clear_txbdr(&priv->si->hw, priv->tx_ring[i]);
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ enetc_clear_rxbdr(&priv->si->hw, priv->rx_ring[i]);
+
+ udelay(1);
+}
+
+static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
+{
+ struct pci_dev *pdev = priv->si->pdev;
+ cpumask_t cpu_mask;
+ int i, j, err;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i);
+ struct enetc_int_vector *v = priv->int_vector[i];
+ int entry = ENETC_BDR_INT_BASE_IDX + i;
+ struct enetc_hw *hw = &priv->si->hw;
+
+ snprintf(v->name, sizeof(v->name), "%s-rxtx%d",
+ priv->ndev->name, i);
+ err = request_irq(irq, enetc_msix, 0, v->name, v);
+ if (err) {
+ dev_err(priv->dev, "request_irq() failed!\n");
+ goto irq_err;
+ }
+
+ v->tbier_base = hw->reg + ENETC_BDR(TX, 0, ENETC_TBIER);
+ v->rbier = hw->reg + ENETC_BDR(RX, i, ENETC_RBIER);
+
+ enetc_wr(hw, ENETC_SIMSIRRV(i), entry);
+
+ for (j = 0; j < v->count_tx_rings; j++) {
+ int idx = v->tx_ring[j].index;
+
+ enetc_wr(hw, ENETC_SIMSITRV(idx), entry);
+ }
+ cpumask_clear(&cpu_mask);
+ cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
+ irq_set_affinity_hint(irq, &cpu_mask);
+ }
+
+ return 0;
+
+irq_err:
+ while (i--) {
+ int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i);
+
+ irq_set_affinity_hint(irq, NULL);
+ free_irq(irq, priv->int_vector[i]);
+ }
+
+ return err;
+}
+
+static void enetc_free_irqs(struct enetc_ndev_priv *priv)
+{
+ struct pci_dev *pdev = priv->si->pdev;
+ int i;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i);
+
+ irq_set_affinity_hint(irq, NULL);
+ free_irq(irq, priv->int_vector[i]);
+ }
+}
+
+static void enetc_enable_interrupts(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ /* enable Tx & Rx event indication */
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ enetc_rxbdr_wr(&priv->si->hw, i,
+ ENETC_RBIER, ENETC_RBIER_RXTIE);
+ }
+
+ for (i = 0; i < priv->num_tx_rings; i++) {
+ enetc_txbdr_wr(&priv->si->hw, i,
+ ENETC_TBIER, ENETC_TBIER_TXTIE);
+ }
+}
+
+static void enetc_disable_interrupts(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ enetc_txbdr_wr(&priv->si->hw, i, ENETC_TBIER, 0);
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ enetc_rxbdr_wr(&priv->si->hw, i, ENETC_RBIER, 0);
+}
+
+static void adjust_link(struct net_device *ndev)
+{
+ struct phy_device *phydev = ndev->phydev;
+
+ phy_print_status(phydev);
+}
+
+static int enetc_phy_connect(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct phy_device *phydev;
+
+ if (!priv->phy_node)
+ return 0; /* phy-less mode */
+
+ phydev = of_phy_connect(ndev, priv->phy_node, &adjust_link,
+ 0, priv->if_mode);
+ if (!phydev) {
+ dev_err(&ndev->dev, "could not attach to PHY\n");
+ return -ENODEV;
+ }
+
+ phy_attached_info(phydev);
+
+ return 0;
+}
+
+int enetc_open(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int i, err;
+
+ err = enetc_setup_irqs(priv);
+ if (err)
+ return err;
+
+ err = enetc_phy_connect(ndev);
+ if (err)
+ goto err_phy_connect;
+
+ err = enetc_alloc_tx_resources(priv);
+ if (err)
+ goto err_alloc_tx;
+
+ err = enetc_alloc_rx_resources(priv);
+ if (err)
+ goto err_alloc_rx;
+
+ enetc_setup_bdrs(priv);
+
+ err = netif_set_real_num_tx_queues(ndev, priv->num_tx_rings);
+ if (err)
+ goto err_set_queues;
+
+ err = netif_set_real_num_rx_queues(ndev, priv->num_rx_rings);
+ if (err)
+ goto err_set_queues;
+
+ for (i = 0; i < priv->bdr_int_num; i++)
+ napi_enable(&priv->int_vector[i]->napi);
+
+ enetc_enable_interrupts(priv);
+
+ if (ndev->phydev)
+ phy_start(ndev->phydev);
+ else
+ netif_carrier_on(ndev);
+
+ netif_tx_start_all_queues(ndev);
+
+ return 0;
+
+err_set_queues:
+ enetc_free_rx_resources(priv);
+err_alloc_rx:
+ enetc_free_tx_resources(priv);
+err_alloc_tx:
+ if (ndev->phydev)
+ phy_disconnect(ndev->phydev);
+err_phy_connect:
+ enetc_free_irqs(priv);
+
+ return err;
+}
+
+int enetc_close(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int i;
+
+ netif_tx_stop_all_queues(ndev);
+
+ if (ndev->phydev) {
+ phy_stop(ndev->phydev);
+ phy_disconnect(ndev->phydev);
+ } else {
+ netif_carrier_off(ndev);
+ }
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ napi_synchronize(&priv->int_vector[i]->napi);
+ napi_disable(&priv->int_vector[i]->napi);
+ }
+
+ enetc_disable_interrupts(priv);
+ enetc_clear_bdrs(priv);
+
+ enetc_free_rxtx_rings(priv);
+ enetc_free_rx_resources(priv);
+ enetc_free_tx_resources(priv);
+ enetc_free_irqs(priv);
+
+ return 0;
+}
+
+struct net_device_stats *enetc_get_stats(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct net_device_stats *stats = &ndev->stats;
+ unsigned long packets = 0, bytes = 0;
+ int i;
+
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ packets += priv->rx_ring[i]->stats.packets;
+ bytes += priv->rx_ring[i]->stats.bytes;
+ }
+
+ stats->rx_packets = packets;
+ stats->rx_bytes = bytes;
+ bytes = 0;
+ packets = 0;
+
+ for (i = 0; i < priv->num_tx_rings; i++) {
+ packets += priv->tx_ring[i]->stats.packets;
+ bytes += priv->tx_ring[i]->stats.bytes;
+ }
+
+ stats->tx_packets = packets;
+ stats->tx_bytes = bytes;
+
+ return stats;
+}
+
+static int enetc_set_rss(struct net_device *ndev, int en)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 reg;
+
+ enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+ reg = enetc_rd(hw, ENETC_SIMR);
+ reg &= ~ENETC_SIMR_RSSE;
+ reg |= (en) ? ENETC_SIMR_RSSE : 0;
+ enetc_wr(hw, ENETC_SIMR, reg);
+
+ return 0;
+}
+
+int enetc_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ netdev_features_t changed = ndev->features ^ features;
+
+ if (changed & NETIF_F_RXHASH)
+ enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
+
+ return 0;
+}
+
+int enetc_alloc_msix(struct enetc_ndev_priv *priv)
+{
+ struct pci_dev *pdev = priv->si->pdev;
+ int size, v_tx_rings;
+ int i, n, err, nvec;
+
+ nvec = ENETC_BDR_INT_BASE_IDX + priv->bdr_int_num;
+ /* allocate MSIX for both messaging and Rx/Tx interrupts */
+ n = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX);
+
+ if (n < 0)
+ return n;
+
+ if (n != nvec)
+ return -EPERM;
+
+ /* # of tx rings per int vector */
+ v_tx_rings = priv->num_tx_rings / priv->bdr_int_num;
+ size = sizeof(struct enetc_int_vector) +
+ sizeof(struct enetc_bdr) * v_tx_rings;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ struct enetc_int_vector *v;
+ struct enetc_bdr *bdr;
+ int j;
+
+ v = kzalloc(size, GFP_KERNEL);
+ if (!v) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ priv->int_vector[i] = v;
+
+ netif_napi_add(priv->ndev, &v->napi, enetc_poll,
+ NAPI_POLL_WEIGHT);
+ v->count_tx_rings = v_tx_rings;
+
+ for (j = 0; j < v_tx_rings; j++) {
+ int idx;
+
+ /* default tx ring mapping policy */
+ if (priv->bdr_int_num == ENETC_MAX_BDR_INT)
+ idx = 2 * j + i; /* 2 CPUs */
+ else
+ idx = j + i * v_tx_rings; /* default */
+
+ __set_bit(idx, &v->tx_rings_map);
+ bdr = &v->tx_ring[j];
+ bdr->index = idx;
+ bdr->ndev = priv->ndev;
+ bdr->dev = priv->dev;
+ bdr->bd_count = priv->tx_bd_count;
+ priv->tx_ring[idx] = bdr;
+ }
+
+ bdr = &v->rx_ring;
+ bdr->index = i;
+ bdr->ndev = priv->ndev;
+ bdr->dev = priv->dev;
+ bdr->bd_count = priv->rx_bd_count;
+ priv->rx_ring[i] = bdr;
+ }
+
+ return 0;
+
+fail:
+ while (i--) {
+ netif_napi_del(&priv->int_vector[i]->napi);
+ kfree(priv->int_vector[i]);
+ }
+
+ pci_free_irq_vectors(pdev);
+
+ return err;
+}
+
+void enetc_free_msix(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ struct enetc_int_vector *v = priv->int_vector[i];
+
+ netif_napi_del(&v->napi);
+ }
+
+ for (i = 0; i < priv->num_rx_rings; i++)
+ priv->rx_ring[i] = NULL;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ priv->tx_ring[i] = NULL;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+ kfree(priv->int_vector[i]);
+ priv->int_vector[i] = NULL;
+ }
+
+ /* disable all MSIX for this device */
+ pci_free_irq_vectors(priv->si->pdev);
+}
+
+static void enetc_kfree_si(struct enetc_si *si)
+{
+ char *p = (char *)si - si->pad;
+
+ kfree(p);
+}
+
+static void enetc_detect_errata(struct enetc_si *si)
+{
+ if (si->pdev->revision == ENETC_REV1)
+ si->errata = ENETC_ERR_TXCSUM | ENETC_ERR_VLAN_ISOL |
+ ENETC_ERR_UCMCSWP;
+}
+
+int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv)
+{
+ struct enetc_si *si, *p;
+ struct enetc_hw *hw;
+ size_t alloc_size;
+ int err, len;
+
+ pcie_flr(pdev);
+ err = pci_enable_device_mem(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "device enable failed\n");
+ return err;
+ }
+
+ /* set up for high or low dma */
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (err) {
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA configuration failed: 0x%x\n", err);
+ goto err_dma;
+ }
+ }
+
+ err = pci_request_mem_regions(pdev, name);
+ if (err) {
+ dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
+ goto err_pci_mem_reg;
+ }
+
+ pci_set_master(pdev);
+
+ alloc_size = sizeof(struct enetc_si);
+ if (sizeof_priv) {
+ /* align priv to 32B */
+ alloc_size = ALIGN(alloc_size, ENETC_SI_ALIGN);
+ alloc_size += sizeof_priv;
+ }
+ /* force 32B alignment for enetc_si */
+ alloc_size += ENETC_SI_ALIGN - 1;
+
+ p = kzalloc(alloc_size, GFP_KERNEL);
+ if (!p) {
+ err = -ENOMEM;
+ goto err_alloc_si;
+ }
+
+ si = PTR_ALIGN(p, ENETC_SI_ALIGN);
+ si->pad = (char *)si - (char *)p;
+
+ pci_set_drvdata(pdev, si);
+ si->pdev = pdev;
+ hw = &si->hw;
+
+ len = pci_resource_len(pdev, ENETC_BAR_REGS);
+ hw->reg = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
+ if (!hw->reg) {
+ err = -ENXIO;
+ dev_err(&pdev->dev, "ioremap() failed\n");
+ goto err_ioremap;
+ }
+ if (len > ENETC_PORT_BASE)
+ hw->port = hw->reg + ENETC_PORT_BASE;
+ if (len > ENETC_GLOBAL_BASE)
+ hw->global = hw->reg + ENETC_GLOBAL_BASE;
+
+ enetc_detect_errata(si);
+
+ return 0;
+
+err_ioremap:
+ enetc_kfree_si(si);
+err_alloc_si:
+ pci_release_mem_regions(pdev);
+err_pci_mem_reg:
+err_dma:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+void enetc_pci_remove(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+ struct enetc_hw *hw = &si->hw;
+
+ iounmap(hw->reg);
+ enetc_kfree_si(si);
+ pci_release_mem_regions(pdev);
+ pci_disable_device(pdev);
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
new file mode 100644
index 000000000000..b274135c5103
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2017-2019 NXP */
+
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+
+#include "enetc_hw.h"
+
+#define ENETC_MAC_MAXFRM_SIZE 9600
+#define ENETC_MAX_MTU (ENETC_MAC_MAXFRM_SIZE - \
+ (ETH_FCS_LEN + ETH_HLEN + VLAN_HLEN))
+
+struct enetc_tx_swbd {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ u16 len;
+ u16 is_dma_page;
+};
+
+#define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE
+#define ENETC_RXB_TRUESIZE 2048 /* PAGE_SIZE >> 1 */
+#define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */
+#define ENETC_RXB_DMA_SIZE \
+ (SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - ENETC_RXB_PAD)
+
+struct enetc_rx_swbd {
+ dma_addr_t dma;
+ struct page *page;
+ u16 page_offset;
+};
+
+struct enetc_ring_stats {
+ unsigned int packets;
+ unsigned int bytes;
+ unsigned int rx_alloc_errs;
+};
+
+#define ENETC_BDR_DEFAULT_SIZE 1024
+#define ENETC_DEFAULT_TX_WORK 256
+
+struct enetc_bdr {
+ struct device *dev; /* for DMA mapping */
+ struct net_device *ndev;
+ void *bd_base; /* points to Rx or Tx BD ring */
+ union {
+ void __iomem *tpir;
+ void __iomem *rcir;
+ };
+ u16 index;
+ int bd_count; /* # of BDs */
+ int next_to_use;
+ int next_to_clean;
+ union {
+ struct enetc_tx_swbd *tx_swbd;
+ struct enetc_rx_swbd *rx_swbd;
+ };
+ union {
+ void __iomem *tcir; /* Tx */
+ int next_to_alloc; /* Rx */
+ };
+ void __iomem *idr; /* Interrupt Detect Register pointer */
+
+ struct enetc_ring_stats stats;
+
+ dma_addr_t bd_dma_base;
+} ____cacheline_aligned_in_smp;
+
+static inline void enetc_bdr_idx_inc(struct enetc_bdr *bdr, int *i)
+{
+ if (unlikely(++*i == bdr->bd_count))
+ *i = 0;
+}
+
+static inline int enetc_bd_unused(struct enetc_bdr *bdr)
+{
+ if (bdr->next_to_clean > bdr->next_to_use)
+ return bdr->next_to_clean - bdr->next_to_use - 1;
+
+ return bdr->bd_count + bdr->next_to_clean - bdr->next_to_use - 1;
+}
+
+/* Control BD ring */
+#define ENETC_CBDR_DEFAULT_SIZE 64
+struct enetc_cbdr {
+ void *bd_base; /* points to Rx or Tx BD ring */
+ void __iomem *pir;
+ void __iomem *cir;
+
+ int bd_count; /* # of BDs */
+ int next_to_use;
+ int next_to_clean;
+
+ dma_addr_t bd_dma_base;
+};
+
+#define ENETC_TXBD(BDR, i) (&(((union enetc_tx_bd *)((BDR).bd_base))[i]))
+#define ENETC_RXBD(BDR, i) (&(((union enetc_rx_bd *)((BDR).bd_base))[i]))
+
+struct enetc_msg_swbd {
+ void *vaddr;
+ dma_addr_t dma;
+ int size;
+};
+
+#define ENETC_REV1 0x1
+enum enetc_errata {
+ ENETC_ERR_TXCSUM = BIT(0),
+ ENETC_ERR_VLAN_ISOL = BIT(1),
+ ENETC_ERR_UCMCSWP = BIT(2),
+};
+
+/* PCI IEP device data */
+struct enetc_si {
+ struct pci_dev *pdev;
+ struct enetc_hw hw;
+ enum enetc_errata errata;
+
+ struct net_device *ndev; /* back ref. */
+
+ struct enetc_cbdr cbd_ring;
+
+ int num_rx_rings; /* how many rings are available in the SI */
+ int num_tx_rings;
+ int num_fs_entries;
+ int num_rss; /* number of RSS buckets */
+ unsigned short pad;
+};
+
+#define ENETC_SI_ALIGN 32
+
+static inline void *enetc_si_priv(const struct enetc_si *si)
+{
+ return (char *)si + ALIGN(sizeof(struct enetc_si), ENETC_SI_ALIGN);
+}
+
+static inline bool enetc_si_is_pf(struct enetc_si *si)
+{
+ return !!(si->hw.port);
+}
+
+#define ENETC_MAX_NUM_TXQS 8
+#define ENETC_INT_NAME_MAX (IFNAMSIZ + 8)
+
+struct enetc_int_vector {
+ void __iomem *rbier;
+ void __iomem *tbier_base;
+ unsigned long tx_rings_map;
+ int count_tx_rings;
+ struct napi_struct napi;
+ char name[ENETC_INT_NAME_MAX];
+
+ struct enetc_bdr rx_ring ____cacheline_aligned_in_smp;
+ struct enetc_bdr tx_ring[0];
+};
+
+struct enetc_cls_rule {
+ struct ethtool_rx_flow_spec fs;
+ int used;
+};
+
+#define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */
+
+struct enetc_ndev_priv {
+ struct net_device *ndev;
+ struct device *dev; /* dma-mapping device */
+ struct enetc_si *si;
+
+ int bdr_int_num; /* number of Rx/Tx ring interrupts */
+ struct enetc_int_vector *int_vector[ENETC_MAX_BDR_INT];
+ u16 num_rx_rings, num_tx_rings;
+ u16 rx_bd_count, tx_bd_count;
+
+ u16 msg_enable;
+
+ struct enetc_bdr *tx_ring[16];
+ struct enetc_bdr *rx_ring[16];
+
+ struct enetc_cls_rule *cls_rules;
+
+ struct device_node *phy_node;
+ phy_interface_t if_mode;
+};
+
+/* Messaging */
+
+/* VF-PF set primary MAC address message format */
+struct enetc_msg_cmd_set_primary_mac {
+ struct enetc_msg_cmd_header header;
+ struct sockaddr mac;
+};
+
+#define ENETC_CBD(R, i) (&(((struct enetc_cbd *)((R).bd_base))[i]))
+
+#define ENETC_CBDR_TIMEOUT 1000 /* usecs */
+
+/* SI common */
+int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv);
+void enetc_pci_remove(struct pci_dev *pdev);
+int enetc_alloc_msix(struct enetc_ndev_priv *priv);
+void enetc_free_msix(struct enetc_ndev_priv *priv);
+void enetc_get_si_caps(struct enetc_si *si);
+void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
+int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
+void enetc_free_si_resources(struct enetc_ndev_priv *priv);
+
+int enetc_open(struct net_device *ndev);
+int enetc_close(struct net_device *ndev);
+netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev);
+struct net_device_stats *enetc_get_stats(struct net_device *ndev);
+int enetc_set_features(struct net_device *ndev,
+ netdev_features_t features);
+/* ethtool */
+void enetc_set_ethtool_ops(struct net_device *ndev);
+
+/* control buffer descriptor ring (CBDR) */
+int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
+ char *mac_addr, int si_map);
+int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
+int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
+ int index);
+void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
new file mode 100644
index 000000000000..de466b71bf8f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include "enetc.h"
+
+static void enetc_clean_cbdr(struct enetc_si *si)
+{
+ struct enetc_cbdr *ring = &si->cbd_ring;
+ struct enetc_cbd *dest_cbd;
+ int i, status;
+
+ i = ring->next_to_clean;
+
+ while (enetc_rd_reg(ring->cir) != i) {
+ dest_cbd = ENETC_CBD(*ring, i);
+ status = dest_cbd->status_flags & ENETC_CBD_STATUS_MASK;
+ if (status)
+ dev_warn(&si->pdev->dev, "CMD err %04x for cmd %04x\n",
+ status, dest_cbd->cmd);
+
+ memset(dest_cbd, 0, sizeof(*dest_cbd));
+
+ i = (i + 1) % ring->bd_count;
+ }
+
+ ring->next_to_clean = i;
+}
+
+static int enetc_cbd_unused(struct enetc_cbdr *r)
+{
+ return (r->next_to_clean - r->next_to_use - 1 + r->bd_count) %
+ r->bd_count;
+}
+
+static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd)
+{
+ struct enetc_cbdr *ring = &si->cbd_ring;
+ int timeout = ENETC_CBDR_TIMEOUT;
+ struct enetc_cbd *dest_cbd;
+ int i;
+
+ if (unlikely(!ring->bd_base))
+ return -EIO;
+
+ if (unlikely(!enetc_cbd_unused(ring)))
+ enetc_clean_cbdr(si);
+
+ i = ring->next_to_use;
+ dest_cbd = ENETC_CBD(*ring, i);
+
+ /* copy command to the ring */
+ *dest_cbd = *cbd;
+ i = (i + 1) % ring->bd_count;
+
+ ring->next_to_use = i;
+ /* let H/W know BD ring has been updated */
+ enetc_wr_reg(ring->pir, i);
+
+ do {
+ if (enetc_rd_reg(ring->cir) == i)
+ break;
+ udelay(10); /* cannot sleep, rtnl_lock() */
+ timeout -= 10;
+ } while (timeout);
+
+ if (!timeout)
+ return -EBUSY;
+
+ enetc_clean_cbdr(si);
+
+ return 0;
+}
+
+int enetc_clear_mac_flt_entry(struct enetc_si *si, int index)
+{
+ struct enetc_cbd cbd;
+
+ memset(&cbd, 0, sizeof(cbd));
+
+ cbd.cls = 1;
+ cbd.status_flags = ENETC_CBD_FLAGS_SF;
+ cbd.index = cpu_to_le16(index);
+
+ return enetc_send_cmd(si, &cbd);
+}
+
+int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
+ char *mac_addr, int si_map)
+{
+ struct enetc_cbd cbd;
+ u32 upper;
+ u16 lower;
+
+ memset(&cbd, 0, sizeof(cbd));
+
+ /* fill up the "set" descriptor */
+ cbd.cls = 1;
+ cbd.status_flags = ENETC_CBD_FLAGS_SF;
+ cbd.index = cpu_to_le16(index);
+ cbd.opt[3] = cpu_to_le32(si_map);
+ /* enable entry */
+ cbd.opt[0] = cpu_to_le32(BIT(31));
+
+ upper = *(const u32 *)mac_addr;
+ lower = *(const u16 *)(mac_addr + 4);
+ cbd.addr[0] = cpu_to_le32(upper);
+ cbd.addr[1] = cpu_to_le32(lower);
+
+ return enetc_send_cmd(si, &cbd);
+}
+
+#define RFSE_ALIGN 64
+/* Set entry in RFS table */
+int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
+ int index)
+{
+ struct enetc_cbd cbd = {.cmd = 0};
+ dma_addr_t dma, dma_align;
+ void *tmp, *tmp_align;
+ int err;
+
+ /* fill up the "set" descriptor */
+ cbd.cmd = 0;
+ cbd.cls = 4;
+ cbd.index = cpu_to_le16(index);
+ cbd.length = cpu_to_le16(sizeof(*rfse));
+ cbd.opt[3] = cpu_to_le32(0); /* SI */
+
+ tmp = dma_alloc_coherent(&si->pdev->dev, sizeof(*rfse) + RFSE_ALIGN,
+ &dma, GFP_KERNEL);
+ if (!tmp) {
+ dev_err(&si->pdev->dev, "DMA mapping of RFS entry failed!\n");
+ return -ENOMEM;
+ }
+
+ dma_align = ALIGN(dma, RFSE_ALIGN);
+ tmp_align = PTR_ALIGN(tmp, RFSE_ALIGN);
+ memcpy(tmp_align, rfse, sizeof(*rfse));
+
+ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
+ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+
+ err = enetc_send_cmd(si, &cbd);
+ if (err)
+ dev_err(&si->pdev->dev, "FS entry add failed (%d)!", err);
+
+ dma_free_coherent(&si->pdev->dev, sizeof(*rfse) + RFSE_ALIGN,
+ tmp, dma);
+
+ return err;
+}
+
+#define RSSE_ALIGN 64
+static int enetc_cmd_rss_table(struct enetc_si *si, u32 *table, int count,
+ bool read)
+{
+ struct enetc_cbd cbd = {.cmd = 0};
+ dma_addr_t dma, dma_align;
+ u8 *tmp, *tmp_align;
+ int err, i;
+
+ if (count < RSSE_ALIGN)
+ /* HW only takes in a full 64 entry table */
+ return -EINVAL;
+
+ tmp = dma_alloc_coherent(&si->pdev->dev, count + RSSE_ALIGN,
+ &dma, GFP_KERNEL);
+ if (!tmp) {
+ dev_err(&si->pdev->dev, "DMA mapping of RSS table failed!\n");
+ return -ENOMEM;
+ }
+ dma_align = ALIGN(dma, RSSE_ALIGN);
+ tmp_align = PTR_ALIGN(tmp, RSSE_ALIGN);
+
+ if (!read)
+ for (i = 0; i < count; i++)
+ tmp_align[i] = (u8)(table[i]);
+
+ /* fill up the descriptor */
+ cbd.cmd = read ? 2 : 1;
+ cbd.cls = 3;
+ cbd.length = cpu_to_le16(count);
+
+ cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align));
+ cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align));
+
+ err = enetc_send_cmd(si, &cbd);
+ if (err)
+ dev_err(&si->pdev->dev, "RSS cmd failed (%d)!", err);
+
+ if (read)
+ for (i = 0; i < count; i++)
+ table[i] = tmp_align[i];
+
+ dma_free_coherent(&si->pdev->dev, count + RSSE_ALIGN, tmp, dma);
+
+ return err;
+}
+
+/* Get RSS table */
+int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+ return enetc_cmd_rss_table(si, table, count, true);
+}
+
+/* Set RSS table */
+int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count)
+{
+ return enetc_cmd_rss_table(si, (u32 *)table, count, false);
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
new file mode 100644
index 000000000000..1ecad9ffabae
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include <linux/net_tstamp.h>
+#include <linux/module.h>
+#include "enetc.h"
+
+static const u32 enetc_si_regs[] = {
+ ENETC_SIMR, ENETC_SIPMAR0, ENETC_SIPMAR1, ENETC_SICBDRMR,
+ ENETC_SICBDRSR, ENETC_SICBDRBAR0, ENETC_SICBDRBAR1, ENETC_SICBDRPIR,
+ ENETC_SICBDRCIR, ENETC_SICBDRLENR, ENETC_SICAPR0, ENETC_SICAPR1,
+ ENETC_SIUEFDCR
+};
+
+static const u32 enetc_txbdr_regs[] = {
+ ENETC_TBMR, ENETC_TBSR, ENETC_TBBAR0, ENETC_TBBAR1,
+ ENETC_TBPIR, ENETC_TBCIR, ENETC_TBLENR, ENETC_TBIER
+};
+
+static const u32 enetc_rxbdr_regs[] = {
+ ENETC_RBMR, ENETC_RBSR, ENETC_RBBSR, ENETC_RBCIR, ENETC_RBBAR0,
+ ENETC_RBBAR1, ENETC_RBPIR, ENETC_RBLENR, ENETC_RBICIR0, ENETC_RBIER
+};
+
+static const u32 enetc_port_regs[] = {
+ ENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0),
+ ENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1,
+ ENETC_PSICFGR0(0), ENETC_PRFSCAPR, ENETC_PTCMSDUR(0),
+ ENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE
+};
+
+static int enetc_get_reglen(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ int len;
+
+ len = ARRAY_SIZE(enetc_si_regs);
+ len += ARRAY_SIZE(enetc_txbdr_regs) * priv->num_tx_rings;
+ len += ARRAY_SIZE(enetc_rxbdr_regs) * priv->num_rx_rings;
+
+ if (hw->port)
+ len += ARRAY_SIZE(enetc_port_regs);
+
+ len *= sizeof(u32) * 2; /* store 2 entries per reg: addr and value */
+
+ return len;
+}
+
+static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs,
+ void *regbuf)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 *buf = (u32 *)regbuf;
+ int i, j;
+ u32 addr;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_si_regs); i++) {
+ *buf++ = enetc_si_regs[i];
+ *buf++ = enetc_rd(hw, enetc_si_regs[i]);
+ }
+
+ for (i = 0; i < priv->num_tx_rings; i++) {
+ for (j = 0; j < ARRAY_SIZE(enetc_txbdr_regs); j++) {
+ addr = ENETC_BDR(TX, i, enetc_txbdr_regs[j]);
+
+ *buf++ = addr;
+ *buf++ = enetc_rd(hw, addr);
+ }
+ }
+
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ for (j = 0; j < ARRAY_SIZE(enetc_rxbdr_regs); j++) {
+ addr = ENETC_BDR(RX, i, enetc_rxbdr_regs[j]);
+
+ *buf++ = addr;
+ *buf++ = enetc_rd(hw, addr);
+ }
+ }
+
+ if (!hw->port)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_port_regs); i++) {
+ addr = ENETC_PORT_BASE + enetc_port_regs[i];
+ *buf++ = addr;
+ *buf++ = enetc_rd(hw, addr);
+ }
+}
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN];
+} enetc_si_counters[] = {
+ { ENETC_SIROCT, "SI rx octets" },
+ { ENETC_SIRFRM, "SI rx frames" },
+ { ENETC_SIRUCA, "SI rx u-cast frames" },
+ { ENETC_SIRMCA, "SI rx m-cast frames" },
+ { ENETC_SITOCT, "SI tx octets" },
+ { ENETC_SITFRM, "SI tx frames" },
+ { ENETC_SITUCA, "SI tx u-cast frames" },
+ { ENETC_SITMCA, "SI tx m-cast frames" },
+ { ENETC_RBDCR(0), "Rx ring 0 discarded frames" },
+ { ENETC_RBDCR(1), "Rx ring 1 discarded frames" },
+ { ENETC_RBDCR(2), "Rx ring 2 discarded frames" },
+ { ENETC_RBDCR(3), "Rx ring 3 discarded frames" },
+ { ENETC_RBDCR(4), "Rx ring 4 discarded frames" },
+ { ENETC_RBDCR(5), "Rx ring 5 discarded frames" },
+ { ENETC_RBDCR(6), "Rx ring 6 discarded frames" },
+ { ENETC_RBDCR(7), "Rx ring 7 discarded frames" },
+ { ENETC_RBDCR(8), "Rx ring 8 discarded frames" },
+ { ENETC_RBDCR(9), "Rx ring 9 discarded frames" },
+ { ENETC_RBDCR(10), "Rx ring 10 discarded frames" },
+ { ENETC_RBDCR(11), "Rx ring 11 discarded frames" },
+ { ENETC_RBDCR(12), "Rx ring 12 discarded frames" },
+ { ENETC_RBDCR(13), "Rx ring 13 discarded frames" },
+ { ENETC_RBDCR(14), "Rx ring 14 discarded frames" },
+ { ENETC_RBDCR(15), "Rx ring 15 discarded frames" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN];
+} enetc_port_counters[] = {
+ { ENETC_PM0_REOCT, "MAC rx ethernet octets" },
+ { ENETC_PM0_RALN, "MAC rx alignment errors" },
+ { ENETC_PM0_RXPF, "MAC rx valid pause frames" },
+ { ENETC_PM0_RFRM, "MAC rx valid frames" },
+ { ENETC_PM0_RFCS, "MAC rx fcs errors" },
+ { ENETC_PM0_RVLAN, "MAC rx VLAN frames" },
+ { ENETC_PM0_RERR, "MAC rx frame errors" },
+ { ENETC_PM0_RUCA, "MAC rx unicast frames" },
+ { ENETC_PM0_RMCA, "MAC rx multicast frames" },
+ { ENETC_PM0_RBCA, "MAC rx broadcast frames" },
+ { ENETC_PM0_RDRP, "MAC rx dropped packets" },
+ { ENETC_PM0_RPKT, "MAC rx packets" },
+ { ENETC_PM0_RUND, "MAC rx undersized packets" },
+ { ENETC_PM0_R64, "MAC rx 64 byte packets" },
+ { ENETC_PM0_R127, "MAC rx 65-127 byte packets" },
+ { ENETC_PM0_R255, "MAC rx 128-255 byte packets" },
+ { ENETC_PM0_R511, "MAC rx 256-511 byte packets" },
+ { ENETC_PM0_R1023, "MAC rx 512-1023 byte packets" },
+ { ENETC_PM0_R1518, "MAC rx 1024-1518 byte packets" },
+ { ENETC_PM0_R1519X, "MAC rx 1519 to max-octet packets" },
+ { ENETC_PM0_ROVR, "MAC rx oversized packets" },
+ { ENETC_PM0_RJBR, "MAC rx jabber packets" },
+ { ENETC_PM0_RFRG, "MAC rx fragment packets" },
+ { ENETC_PM0_RCNP, "MAC rx control packets" },
+ { ENETC_PM0_RDRNTP, "MAC rx fifo drop" },
+ { ENETC_PM0_TEOCT, "MAC tx ethernet octets" },
+ { ENETC_PM0_TOCT, "MAC tx octets" },
+ { ENETC_PM0_TCRSE, "MAC tx carrier sense errors" },
+ { ENETC_PM0_TXPF, "MAC tx valid pause frames" },
+ { ENETC_PM0_TFRM, "MAC tx frames" },
+ { ENETC_PM0_TFCS, "MAC tx fcs errors" },
+ { ENETC_PM0_TVLAN, "MAC tx VLAN frames" },
+ { ENETC_PM0_TERR, "MAC tx frames" },
+ { ENETC_PM0_TUCA, "MAC tx unicast frames" },
+ { ENETC_PM0_TMCA, "MAC tx multicast frames" },
+ { ENETC_PM0_TBCA, "MAC tx broadcast frames" },
+ { ENETC_PM0_TPKT, "MAC tx packets" },
+ { ENETC_PM0_TUND, "MAC tx undersized packets" },
+ { ENETC_PM0_T127, "MAC tx 65-127 byte packets" },
+ { ENETC_PM0_T1023, "MAC tx 512-1023 byte packets" },
+ { ENETC_PM0_T1518, "MAC tx 1024-1518 byte packets" },
+ { ENETC_PM0_TCNP, "MAC tx control packets" },
+ { ENETC_PM0_TDFR, "MAC tx deferred packets" },
+ { ENETC_PM0_TMCOL, "MAC tx multiple collisions" },
+ { ENETC_PM0_TSCOL, "MAC tx single collisions" },
+ { ENETC_PM0_TLCOL, "MAC tx late collisions" },
+ { ENETC_PM0_TECOL, "MAC tx excessive collisions" },
+ { ENETC_UFDMF, "SI MAC nomatch u-cast discards" },
+ { ENETC_MFDMF, "SI MAC nomatch m-cast discards" },
+ { ENETC_PBFDSIR, "SI MAC nomatch b-cast discards" },
+ { ENETC_PUFDVFR, "SI VLAN nomatch u-cast discards" },
+ { ENETC_PMFDVFR, "SI VLAN nomatch m-cast discards" },
+ { ENETC_PBFDVFR, "SI VLAN nomatch b-cast discards" },
+ { ENETC_PFDMSAPR, "SI pruning discarded frames" },
+ { ENETC_PICDR(0), "ICM DR0 discarded frames" },
+ { ENETC_PICDR(1), "ICM DR1 discarded frames" },
+ { ENETC_PICDR(2), "ICM DR2 discarded frames" },
+ { ENETC_PICDR(3), "ICM DR3 discarded frames" },
+};
+
+static const char rx_ring_stats[][ETH_GSTRING_LEN] = {
+ "Rx ring %2d frames",
+ "Rx ring %2d alloc errors",
+};
+
+static const char tx_ring_stats[][ETH_GSTRING_LEN] = {
+ "Tx ring %2d frames",
+};
+
+static int enetc_get_sset_count(struct net_device *ndev, int sset)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ if (sset == ETH_SS_STATS)
+ return ARRAY_SIZE(enetc_si_counters) +
+ ARRAY_SIZE(tx_ring_stats) * priv->num_tx_rings +
+ ARRAY_SIZE(rx_ring_stats) * priv->num_rx_rings +
+ (enetc_si_is_pf(priv->si) ?
+ ARRAY_SIZE(enetc_port_counters) : 0);
+
+ return -EOPNOTSUPP;
+}
+
+static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ u8 *p = data;
+ int i, j;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) {
+ strlcpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < priv->num_tx_rings; i++) {
+ for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++) {
+ snprintf(p, ETH_GSTRING_LEN, tx_ring_stats[j],
+ i);
+ p += ETH_GSTRING_LEN;
+ }
+ }
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++) {
+ snprintf(p, ETH_GSTRING_LEN, rx_ring_stats[j],
+ i);
+ p += ETH_GSTRING_LEN;
+ }
+ }
+
+ if (!enetc_si_is_pf(priv->si))
+ break;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) {
+ strlcpy(p, enetc_port_counters[i].name,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+}
+
+static void enetc_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ int i, o = 0;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++)
+ data[o++] = enetc_rd64(hw, enetc_si_counters[i].reg);
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ data[o++] = priv->tx_ring[i]->stats.packets;
+
+ for (i = 0; i < priv->num_rx_rings; i++) {
+ data[o++] = priv->rx_ring[i]->stats.packets;
+ data[o++] = priv->rx_ring[i]->stats.rx_alloc_errs;
+ }
+
+ if (!enetc_si_is_pf(priv->si))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
+}
+
+#define ENETC_RSSHASH_L3 (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO | RXH_IP_SRC | \
+ RXH_IP_DST)
+#define ENETC_RSSHASH_L4 (ENETC_RSSHASH_L3 | RXH_L4_B_0_1 | RXH_L4_B_2_3)
+static int enetc_get_rsshash(struct ethtool_rxnfc *rxnfc)
+{
+ static const u32 rsshash[] = {
+ [TCP_V4_FLOW] = ENETC_RSSHASH_L4,
+ [UDP_V4_FLOW] = ENETC_RSSHASH_L4,
+ [SCTP_V4_FLOW] = ENETC_RSSHASH_L4,
+ [AH_ESP_V4_FLOW] = ENETC_RSSHASH_L3,
+ [IPV4_FLOW] = ENETC_RSSHASH_L3,
+ [TCP_V6_FLOW] = ENETC_RSSHASH_L4,
+ [UDP_V6_FLOW] = ENETC_RSSHASH_L4,
+ [SCTP_V6_FLOW] = ENETC_RSSHASH_L4,
+ [AH_ESP_V6_FLOW] = ENETC_RSSHASH_L3,
+ [IPV6_FLOW] = ENETC_RSSHASH_L3,
+ [ETHER_FLOW] = 0,
+ };
+
+ if (rxnfc->flow_type >= ARRAY_SIZE(rsshash))
+ return -EINVAL;
+
+ rxnfc->data = rsshash[rxnfc->flow_type];
+
+ return 0;
+}
+
+/* current HW spec does byte reversal on everything including MAC addresses */
+static void ether_addr_copy_swap(u8 *dst, const u8 *src)
+{
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dst[i] = src[ETH_ALEN - i - 1];
+}
+
+static int enetc_set_cls_entry(struct enetc_si *si,
+ struct ethtool_rx_flow_spec *fs, bool en)
+{
+ struct ethtool_tcpip4_spec *l4ip4_h, *l4ip4_m;
+ struct ethtool_usrip4_spec *l3ip4_h, *l3ip4_m;
+ struct ethhdr *eth_h, *eth_m;
+ struct enetc_cmd_rfse rfse = { {0} };
+
+ if (!en)
+ goto done;
+
+ switch (fs->flow_type & 0xff) {
+ case TCP_V4_FLOW:
+ l4ip4_h = &fs->h_u.tcp_ip4_spec;
+ l4ip4_m = &fs->m_u.tcp_ip4_spec;
+ goto l4ip4;
+ case UDP_V4_FLOW:
+ l4ip4_h = &fs->h_u.udp_ip4_spec;
+ l4ip4_m = &fs->m_u.udp_ip4_spec;
+ goto l4ip4;
+ case SCTP_V4_FLOW:
+ l4ip4_h = &fs->h_u.sctp_ip4_spec;
+ l4ip4_m = &fs->m_u.sctp_ip4_spec;
+l4ip4:
+ rfse.sip_h[0] = l4ip4_h->ip4src;
+ rfse.sip_m[0] = l4ip4_m->ip4src;
+ rfse.dip_h[0] = l4ip4_h->ip4dst;
+ rfse.dip_m[0] = l4ip4_m->ip4dst;
+ rfse.sport_h = ntohs(l4ip4_h->psrc);
+ rfse.sport_m = ntohs(l4ip4_m->psrc);
+ rfse.dport_h = ntohs(l4ip4_h->pdst);
+ rfse.dport_m = ntohs(l4ip4_m->pdst);
+ if (l4ip4_m->tos)
+ netdev_warn(si->ndev, "ToS field is not supported and was ignored\n");
+ rfse.ethtype_h = ETH_P_IP; /* IPv4 */
+ rfse.ethtype_m = 0xffff;
+ break;
+ case IP_USER_FLOW:
+ l3ip4_h = &fs->h_u.usr_ip4_spec;
+ l3ip4_m = &fs->m_u.usr_ip4_spec;
+
+ rfse.sip_h[0] = l3ip4_h->ip4src;
+ rfse.sip_m[0] = l3ip4_m->ip4src;
+ rfse.dip_h[0] = l3ip4_h->ip4dst;
+ rfse.dip_m[0] = l3ip4_m->ip4dst;
+ if (l3ip4_m->tos)
+ netdev_warn(si->ndev, "ToS field is not supported and was ignored\n");
+ rfse.ethtype_h = ETH_P_IP; /* IPv4 */
+ rfse.ethtype_m = 0xffff;
+ break;
+ case ETHER_FLOW:
+ eth_h = &fs->h_u.ether_spec;
+ eth_m = &fs->m_u.ether_spec;
+
+ ether_addr_copy_swap(rfse.smac_h, eth_h->h_source);
+ ether_addr_copy_swap(rfse.smac_m, eth_m->h_source);
+ ether_addr_copy_swap(rfse.dmac_h, eth_h->h_dest);
+ ether_addr_copy_swap(rfse.dmac_m, eth_m->h_dest);
+ rfse.ethtype_h = ntohs(eth_h->h_proto);
+ rfse.ethtype_m = ntohs(eth_m->h_proto);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ rfse.mode |= ENETC_RFSE_EN;
+ if (fs->ring_cookie != RX_CLS_FLOW_DISC) {
+ rfse.mode |= ENETC_RFSE_MODE_BD;
+ rfse.result = fs->ring_cookie;
+ }
+done:
+ return enetc_set_fs_entry(si, &rfse, fs->location);
+}
+
+static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
+ u32 *rule_locs)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int i, j;
+
+ switch (rxnfc->cmd) {
+ case ETHTOOL_GRXRINGS:
+ rxnfc->data = priv->num_rx_rings;
+ break;
+ case ETHTOOL_GRXFH:
+ /* get RSS hash config */
+ return enetc_get_rsshash(rxnfc);
+ case ETHTOOL_GRXCLSRLCNT:
+ /* total number of entries */
+ rxnfc->data = priv->si->num_fs_entries;
+ /* number of entries in use */
+ rxnfc->rule_cnt = 0;
+ for (i = 0; i < priv->si->num_fs_entries; i++)
+ if (priv->cls_rules[i].used)
+ rxnfc->rule_cnt++;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ if (rxnfc->fs.location >= priv->si->num_fs_entries)
+ return -EINVAL;
+
+ /* get entry x */
+ rxnfc->fs = priv->cls_rules[rxnfc->fs.location].fs;
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ /* total number of entries */
+ rxnfc->data = priv->si->num_fs_entries;
+ /* array of indexes of used entries */
+ j = 0;
+ for (i = 0; i < priv->si->num_fs_entries; i++) {
+ if (!priv->cls_rules[i].used)
+ continue;
+ if (j == rxnfc->rule_cnt)
+ return -EMSGSIZE;
+ rule_locs[j++] = i;
+ }
+ /* number of entries in use */
+ rxnfc->rule_cnt = j;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int err;
+
+ switch (rxnfc->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ if (rxnfc->fs.location >= priv->si->num_fs_entries)
+ return -EINVAL;
+
+ if (rxnfc->fs.ring_cookie >= priv->num_rx_rings &&
+ rxnfc->fs.ring_cookie != RX_CLS_FLOW_DISC)
+ return -EINVAL;
+
+ err = enetc_set_cls_entry(priv->si, &rxnfc->fs, true);
+ if (err)
+ return err;
+ priv->cls_rules[rxnfc->fs.location].fs = rxnfc->fs;
+ priv->cls_rules[rxnfc->fs.location].used = 1;
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ if (rxnfc->fs.location >= priv->si->num_fs_entries)
+ return -EINVAL;
+
+ err = enetc_set_cls_entry(priv->si, &rxnfc->fs, false);
+ if (err)
+ return err;
+ priv->cls_rules[rxnfc->fs.location].used = 0;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static u32 enetc_get_rxfh_key_size(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ /* return the size of the RX flow hash key. PF only */
+ return (priv->si->hw.port) ? ENETC_RSSHASH_KEY_SIZE : 0;
+}
+
+static u32 enetc_get_rxfh_indir_size(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ /* return the size of the RX flow hash indirection table */
+ return priv->si->num_rss;
+}
+
+static int enetc_get_rxfh(struct net_device *ndev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ int err = 0, i;
+
+ /* return hash function */
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+
+ /* return hash key */
+ if (key && hw->port)
+ for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+ ((u32 *)key)[i] = enetc_port_rd(hw, ENETC_PRSSK(i));
+
+ /* return RSS table */
+ if (indir)
+ err = enetc_get_rss_table(priv->si, indir, priv->si->num_rss);
+
+ return err;
+}
+
+void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+{
+ int i;
+
+ for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+ enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+}
+
+static int enetc_set_rxfh(struct net_device *ndev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ int err = 0;
+
+ /* set hash key, if PF */
+ if (key && hw->port)
+ enetc_set_rss_key(hw, key);
+
+ /* set RSS table */
+ if (indir)
+ err = enetc_set_rss_table(priv->si, indir, priv->si->num_rss);
+
+ return err;
+}
+
+static void enetc_get_ringparam(struct net_device *ndev,
+ struct ethtool_ringparam *ring)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ ring->rx_pending = priv->rx_bd_count;
+ ring->tx_pending = priv->tx_bd_count;
+
+ /* do some h/w sanity checks for BDR length */
+ if (netif_running(ndev)) {
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 val = enetc_rxbdr_rd(hw, 0, ENETC_RBLENR);
+
+ if (val != priv->rx_bd_count)
+ netif_err(priv, hw, ndev, "RxBDR[RBLENR] = %d!\n", val);
+
+ val = enetc_txbdr_rd(hw, 0, ENETC_TBLENR);
+
+ if (val != priv->tx_bd_count)
+ netif_err(priv, hw, ndev, "TxBDR[TBLENR] = %d!\n", val);
+ }
+}
+
+static const struct ethtool_ops enetc_pf_ethtool_ops = {
+ .get_regs_len = enetc_get_reglen,
+ .get_regs = enetc_get_regs,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
+ .get_rxnfc = enetc_get_rxnfc,
+ .set_rxnfc = enetc_set_rxnfc,
+ .get_rxfh_key_size = enetc_get_rxfh_key_size,
+ .get_rxfh_indir_size = enetc_get_rxfh_indir_size,
+ .get_rxfh = enetc_get_rxfh,
+ .set_rxfh = enetc_set_rxfh,
+ .get_ringparam = enetc_get_ringparam,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
+};
+
+static const struct ethtool_ops enetc_vf_ethtool_ops = {
+ .get_regs_len = enetc_get_reglen,
+ .get_regs = enetc_get_regs,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
+ .get_rxnfc = enetc_get_rxnfc,
+ .set_rxnfc = enetc_set_rxnfc,
+ .get_rxfh_indir_size = enetc_get_rxfh_indir_size,
+ .get_rxfh = enetc_get_rxfh,
+ .set_rxfh = enetc_set_rxfh,
+ .get_ringparam = enetc_get_ringparam,
+};
+
+void enetc_set_ethtool_ops(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ if (enetc_si_is_pf(priv->si))
+ ndev->ethtool_ops = &enetc_pf_ethtool_ops;
+ else
+ ndev->ethtool_ops = &enetc_vf_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
new file mode 100644
index 000000000000..df8eb8882d92
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -0,0 +1,533 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2017-2019 NXP */
+
+#include <linux/bitops.h>
+
+/* ENETC device IDs */
+#define ENETC_DEV_ID_PF 0xe100
+#define ENETC_DEV_ID_VF 0xef00
+#define ENETC_DEV_ID_PTP 0xee02
+
+/* ENETC register block BAR */
+#define ENETC_BAR_REGS 0
+
+/** SI regs, offset: 0h */
+#define ENETC_SIMR 0
+#define ENETC_SIMR_EN BIT(31)
+#define ENETC_SIMR_RSSE BIT(0)
+#define ENETC_SICTR0 0x18
+#define ENETC_SICTR1 0x1c
+#define ENETC_SIPCAPR0 0x20
+#define ENETC_SIPCAPR0_RSS BIT(8)
+#define ENETC_SIPCAPR1 0x24
+#define ENETC_SITGTGR 0x30
+#define ENETC_SIRBGCR 0x38
+/* cache attribute registers for transactions initiated by ENETC */
+#define ENETC_SICAR0 0x40
+#define ENETC_SICAR1 0x44
+#define ENETC_SICAR2 0x48
+/* rd snoop, no alloc
+ * wr snoop, no alloc, partial cache line update for BDs and full cache line
+ * update for data
+ */
+#define ENETC_SICAR_RD_COHERENT 0x2b2b0000
+#define ENETC_SICAR_WR_COHERENT 0x00006727
+#define ENETC_SICAR_MSI 0x00300030 /* rd/wr device, no snoop, no alloc */
+
+#define ENETC_SIPMAR0 0x80
+#define ENETC_SIPMAR1 0x84
+
+/* VF-PF Message passing */
+#define ENETC_DEFAULT_MSG_SIZE 1024 /* and max size */
+/* msg size encoding: default and max msg value of 1024B encoded as 0 */
+static inline u32 enetc_vsi_set_msize(u32 size)
+{
+ return size < ENETC_DEFAULT_MSG_SIZE ? size >> 5 : 0;
+}
+
+#define ENETC_PSIMSGRR 0x204
+#define ENETC_PSIMSGRR_MR_MASK GENMASK(2, 1)
+#define ENETC_PSIMSGRR_MR(n) BIT((n) + 1) /* n = VSI index */
+#define ENETC_PSIVMSGRCVAR0(n) (0x210 + (n) * 0x8) /* n = VSI index */
+#define ENETC_PSIVMSGRCVAR1(n) (0x214 + (n) * 0x8)
+
+#define ENETC_VSIMSGSR 0x204 /* RO */
+#define ENETC_VSIMSGSR_MB BIT(0)
+#define ENETC_VSIMSGSR_MS BIT(1)
+#define ENETC_VSIMSGSNDAR0 0x210
+#define ENETC_VSIMSGSNDAR1 0x214
+
+#define ENETC_SIMSGSR_SET_MC(val) ((val) << 16)
+#define ENETC_SIMSGSR_GET_MC(val) ((val) >> 16)
+
+/* SI statistics */
+#define ENETC_SIROCT 0x300
+#define ENETC_SIRFRM 0x308
+#define ENETC_SIRUCA 0x310
+#define ENETC_SIRMCA 0x318
+#define ENETC_SITOCT 0x320
+#define ENETC_SITFRM 0x328
+#define ENETC_SITUCA 0x330
+#define ENETC_SITMCA 0x338
+#define ENETC_RBDCR(n) (0x8180 + (n) * 0x200)
+
+/* Control BDR regs */
+#define ENETC_SICBDRMR 0x800
+#define ENETC_SICBDRSR 0x804 /* RO */
+#define ENETC_SICBDRBAR0 0x810
+#define ENETC_SICBDRBAR1 0x814
+#define ENETC_SICBDRPIR 0x818
+#define ENETC_SICBDRCIR 0x81c
+#define ENETC_SICBDRLENR 0x820
+
+#define ENETC_SICAPR0 0x900
+#define ENETC_SICAPR1 0x904
+
+#define ENETC_PSIIER 0xa00
+#define ENETC_PSIIER_MR_MASK GENMASK(2, 1)
+#define ENETC_PSIIDR 0xa08
+#define ENETC_SITXIDR 0xa18
+#define ENETC_SIRXIDR 0xa28
+#define ENETC_SIMSIVR 0xa30
+
+#define ENETC_SIMSITRV(n) (0xB00 + (n) * 0x4)
+#define ENETC_SIMSIRRV(n) (0xB80 + (n) * 0x4)
+
+#define ENETC_SIUEFDCR 0xe28
+
+#define ENETC_SIRFSCAPR 0x1200
+#define ENETC_SIRFSCAPR_GET_NUM_RFS(val) ((val) & 0x7f)
+#define ENETC_SIRSSCAPR 0x1600
+#define ENETC_SIRSSCAPR_GET_NUM_RSS(val) (BIT((val) & 0xf) * 32)
+
+/** SI BDR sub-blocks, n = 0..7 */
+enum enetc_bdr_type {TX, RX};
+#define ENETC_BDR_OFF(i) ((i) * 0x200)
+#define ENETC_BDR(t, i, r) (0x8000 + (t) * 0x100 + ENETC_BDR_OFF(i) + (r))
+/* RX BDR reg offsets */
+#define ENETC_RBMR 0
+#define ENETC_RBMR_BDS BIT(2)
+#define ENETC_RBMR_VTE BIT(5)
+#define ENETC_RBMR_EN BIT(31)
+#define ENETC_RBSR 0x4
+#define ENETC_RBBSR 0x8
+#define ENETC_RBCIR 0xc
+#define ENETC_RBBAR0 0x10
+#define ENETC_RBBAR1 0x14
+#define ENETC_RBPIR 0x18
+#define ENETC_RBLENR 0x20
+#define ENETC_RBIER 0xa0
+#define ENETC_RBIER_RXTIE BIT(0)
+#define ENETC_RBIDR 0xa4
+#define ENETC_RBICIR0 0xa8
+#define ENETC_RBICIR0_ICEN BIT(31)
+
+/* TX BDR reg offsets */
+#define ENETC_TBMR 0
+#define ENETC_TBSR_BUSY BIT(0)
+#define ENETC_TBMR_VIH BIT(9)
+#define ENETC_TBMR_PRIO_MASK GENMASK(2, 0)
+#define ENETC_TBMR_PRIO_SET(val) val
+#define ENETC_TBMR_EN BIT(31)
+#define ENETC_TBSR 0x4
+#define ENETC_TBBAR0 0x10
+#define ENETC_TBBAR1 0x14
+#define ENETC_TBPIR 0x18
+#define ENETC_TBCIR 0x1c
+#define ENETC_TBCIR_IDX_MASK 0xffff
+#define ENETC_TBLENR 0x20
+#define ENETC_TBIER 0xa0
+#define ENETC_TBIER_TXTIE BIT(0)
+#define ENETC_TBIDR 0xa4
+#define ENETC_TBICIR0 0xa8
+#define ENETC_TBICIR0_ICEN BIT(31)
+
+#define ENETC_RTBLENR_LEN(n) ((n) & ~0x7)
+
+/* Port regs, offset: 1_0000h */
+#define ENETC_PORT_BASE 0x10000
+#define ENETC_PMR 0x0000
+#define ENETC_PMR_EN GENMASK(18, 16)
+#define ENETC_PSR 0x0004 /* RO */
+#define ENETC_PSIPMR 0x0018
+#define ENETC_PSIPMR_SET_UP(n) BIT(n) /* n = SI index */
+#define ENETC_PSIPMR_SET_MP(n) BIT((n) + 16)
+#define ENETC_PSIPVMR 0x001c
+#define ENETC_VLAN_PROMISC_MAP_ALL 0x7
+#define ENETC_PSIPVMR_SET_VP(simap) ((simap) & 0x7)
+#define ENETC_PSIPVMR_SET_VUTA(simap) (((simap) & 0x7) << 16)
+#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */
+#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8)
+#define ENETC_PVCLCTR 0x0208
+#define ENETC_VLAN_TYPE_C BIT(0)
+#define ENETC_VLAN_TYPE_S BIT(1)
+#define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */
+#define ENETC_PSIVLANR(n) (0x0240 + (n) * 4) /* n = SI index */
+#define ENETC_PSIVLAN_EN BIT(31)
+#define ENETC_PSIVLAN_SET_QOS(val) ((u32)(val) << 12)
+#define ENETC_PTXMBAR 0x0608
+#define ENETC_PCAPR0 0x0900
+#define ENETC_PCAPR0_RXBDR(val) ((val) >> 24)
+#define ENETC_PCAPR0_TXBDR(val) (((val) >> 16) & 0xff)
+#define ENETC_PCAPR1 0x0904
+#define ENETC_PSICFGR0(n) (0x0940 + (n) * 0xc) /* n = SI index */
+#define ENETC_PSICFGR0_SET_TXBDR(val) ((val) & 0xff)
+#define ENETC_PSICFGR0_SET_RXBDR(val) (((val) & 0xff) << 16)
+#define ENETC_PSICFGR0_VTE BIT(12)
+#define ENETC_PSICFGR0_SIVIE BIT(14)
+#define ENETC_PSICFGR0_ASE BIT(15)
+#define ENETC_PSICFGR0_SIVC(bmp) (((bmp) & 0xff) << 24) /* VLAN_TYPE */
+
+#define ENETC_PTCCBSR0(n) (0x1110 + (n) * 8) /* n = 0 to 7*/
+#define ENETC_PTCCBSR1(n) (0x1114 + (n) * 8) /* n = 0 to 7*/
+#define ENETC_RSSHASH_KEY_SIZE 40
+#define ENETC_PRSSK(n) (0x1410 + (n) * 4) /* n = [0..9] */
+#define ENETC_PSIVLANFMR 0x1700
+#define ENETC_PSIVLANFMR_VS BIT(0)
+#define ENETC_PRFSMR 0x1800
+#define ENETC_PRFSMR_RFSE BIT(31)
+#define ENETC_PRFSCAPR 0x1804
+#define ENETC_PRFSCAPR_GET_NUM_RFS(val) ((((val) & 0xf) + 1) * 16)
+#define ENETC_PSIRFSCFGR(n) (0x1814 + (n) * 4) /* n = SI index */
+#define ENETC_PFPMR 0x1900
+#define ENETC_PFPMR_PMACE BIT(1)
+#define ENETC_PFPMR_MWLM BIT(0)
+#define ENETC_PSIUMHFR0(n, err) (((err) ? 0x1d08 : 0x1d00) + (n) * 0x10)
+#define ENETC_PSIUMHFR1(n) (0x1d04 + (n) * 0x10)
+#define ENETC_PSIMMHFR0(n, err) (((err) ? 0x1d00 : 0x1d08) + (n) * 0x10)
+#define ENETC_PSIMMHFR1(n) (0x1d0c + (n) * 0x10)
+#define ENETC_PSIVHFR0(n) (0x1e00 + (n) * 8) /* n = SI index */
+#define ENETC_PSIVHFR1(n) (0x1e04 + (n) * 8) /* n = SI index */
+#define ENETC_MMCSR 0x1f00
+#define ENETC_MMCSR_ME BIT(16)
+#define ENETC_PTCMSDUR(n) (0x2020 + (n) * 4) /* n = TC index [0..7] */
+
+#define ENETC_PM0_CMD_CFG 0x8008
+#define ENETC_PM1_CMD_CFG 0x9008
+#define ENETC_PM0_TX_EN BIT(0)
+#define ENETC_PM0_RX_EN BIT(1)
+#define ENETC_PM0_PROMISC BIT(4)
+#define ENETC_PM0_CMD_XGLP BIT(10)
+#define ENETC_PM0_CMD_TXP BIT(11)
+#define ENETC_PM0_CMD_PHY_TX_EN BIT(15)
+#define ENETC_PM0_CMD_SFD BIT(21)
+#define ENETC_PM0_MAXFRM 0x8014
+#define ENETC_SET_TX_MTU(val) ((val) << 16)
+#define ENETC_SET_MAXFRM(val) ((val) & 0xffff)
+#define ENETC_PM0_IF_MODE 0x8300
+#define ENETC_PMO_IFM_RG BIT(2)
+#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
+#define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
+#define ENETC_PM0_IFM_XGMII BIT(12)
+
+/* MAC counters */
+#define ENETC_PM0_REOCT 0x8100
+#define ENETC_PM0_RALN 0x8110
+#define ENETC_PM0_RXPF 0x8118
+#define ENETC_PM0_RFRM 0x8120
+#define ENETC_PM0_RFCS 0x8128
+#define ENETC_PM0_RVLAN 0x8130
+#define ENETC_PM0_RERR 0x8138
+#define ENETC_PM0_RUCA 0x8140
+#define ENETC_PM0_RMCA 0x8148
+#define ENETC_PM0_RBCA 0x8150
+#define ENETC_PM0_RDRP 0x8158
+#define ENETC_PM0_RPKT 0x8160
+#define ENETC_PM0_RUND 0x8168
+#define ENETC_PM0_R64 0x8170
+#define ENETC_PM0_R127 0x8178
+#define ENETC_PM0_R255 0x8180
+#define ENETC_PM0_R511 0x8188
+#define ENETC_PM0_R1023 0x8190
+#define ENETC_PM0_R1518 0x8198
+#define ENETC_PM0_R1519X 0x81A0
+#define ENETC_PM0_ROVR 0x81A8
+#define ENETC_PM0_RJBR 0x81B0
+#define ENETC_PM0_RFRG 0x81B8
+#define ENETC_PM0_RCNP 0x81C0
+#define ENETC_PM0_RDRNTP 0x81C8
+#define ENETC_PM0_TEOCT 0x8200
+#define ENETC_PM0_TOCT 0x8208
+#define ENETC_PM0_TCRSE 0x8210
+#define ENETC_PM0_TXPF 0x8218
+#define ENETC_PM0_TFRM 0x8220
+#define ENETC_PM0_TFCS 0x8228
+#define ENETC_PM0_TVLAN 0x8230
+#define ENETC_PM0_TERR 0x8238
+#define ENETC_PM0_TUCA 0x8240
+#define ENETC_PM0_TMCA 0x8248
+#define ENETC_PM0_TBCA 0x8250
+#define ENETC_PM0_TPKT 0x8260
+#define ENETC_PM0_TUND 0x8268
+#define ENETC_PM0_T127 0x8278
+#define ENETC_PM0_T1023 0x8290
+#define ENETC_PM0_T1518 0x8298
+#define ENETC_PM0_TCNP 0x82C0
+#define ENETC_PM0_TDFR 0x82D0
+#define ENETC_PM0_TMCOL 0x82D8
+#define ENETC_PM0_TSCOL 0x82E0
+#define ENETC_PM0_TLCOL 0x82E8
+#define ENETC_PM0_TECOL 0x82F0
+
+/* Port counters */
+#define ENETC_PICDR(n) (0x0700 + (n) * 8) /* n = [0..3] */
+#define ENETC_PBFDSIR 0x0810
+#define ENETC_PFDMSAPR 0x0814
+#define ENETC_UFDMF 0x1680
+#define ENETC_MFDMF 0x1684
+#define ENETC_PUFDVFR 0x1780
+#define ENETC_PMFDVFR 0x1784
+#define ENETC_PBFDVFR 0x1788
+
+/** Global regs, offset: 2_0000h */
+#define ENETC_GLOBAL_BASE 0x20000
+#define ENETC_G_EIPBRR0 0x0bf8
+#define ENETC_G_EIPBRR1 0x0bfc
+#define ENETC_G_EPFBLPR(n) (0xd00 + 4 * (n))
+#define ENETC_G_EPFBLPR1_XGMII 0x80000000
+
+/* PCI device info */
+struct enetc_hw {
+ /* SI registers, used by all PCI functions */
+ void __iomem *reg;
+ /* Port registers, PF only */
+ void __iomem *port;
+ /* IP global registers, PF only */
+ void __iomem *global;
+};
+
+/* general register accessors */
+#define enetc_rd_reg(reg) ioread32((reg))
+#define enetc_wr_reg(reg, val) iowrite32((val), (reg))
+#ifdef ioread64
+#define enetc_rd_reg64(reg) ioread64((reg))
+#else
+/* using this to read out stats on 32b systems */
+static inline u64 enetc_rd_reg64(void __iomem *reg)
+{
+ u32 low, high, tmp;
+
+ do {
+ high = ioread32(reg + 4);
+ low = ioread32(reg);
+ tmp = ioread32(reg + 4);
+ } while (high != tmp);
+
+ return le64_to_cpu((__le64)high << 32 | low);
+}
+#endif
+
+#define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off))
+#define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val)
+#define enetc_rd64(hw, off) enetc_rd_reg64((hw)->reg + (off))
+/* port register accessors - PF only */
+#define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off))
+#define enetc_port_wr(hw, off, val) enetc_wr_reg((hw)->port + (off), val)
+/* global register accessors - PF only */
+#define enetc_global_rd(hw, off) enetc_rd_reg((hw)->global + (off))
+#define enetc_global_wr(hw, off, val) enetc_wr_reg((hw)->global + (off), val)
+/* BDR register accessors, see ENETC_BDR() */
+#define enetc_bdr_rd(hw, t, n, off) \
+ enetc_rd(hw, ENETC_BDR(t, n, off))
+#define enetc_bdr_wr(hw, t, n, off, val) \
+ enetc_wr(hw, ENETC_BDR(t, n, off), val)
+#define enetc_txbdr_rd(hw, n, off) enetc_bdr_rd(hw, TX, n, off)
+#define enetc_rxbdr_rd(hw, n, off) enetc_bdr_rd(hw, RX, n, off)
+#define enetc_txbdr_wr(hw, n, off, val) \
+ enetc_bdr_wr(hw, TX, n, off, val)
+#define enetc_rxbdr_wr(hw, n, off, val) \
+ enetc_bdr_wr(hw, RX, n, off, val)
+
+/* Buffer Descriptors (BD) */
+union enetc_tx_bd {
+ struct {
+ __le64 addr;
+ __le16 buf_len;
+ __le16 frm_len;
+ union {
+ struct {
+ __le16 l3_csoff;
+ u8 l4_csoff;
+ u8 flags;
+ }; /* default layout */
+ __le32 lstatus;
+ };
+ };
+ struct {
+ __le32 tstamp;
+ __le16 tpid;
+ __le16 vid;
+ u8 reserved[6];
+ u8 e_flags;
+ u8 flags;
+ } ext; /* Tx BD extension */
+};
+
+#define ENETC_TXBD_FLAGS_L4CS BIT(0)
+#define ENETC_TXBD_FLAGS_W BIT(2)
+#define ENETC_TXBD_FLAGS_CSUM BIT(3)
+#define ENETC_TXBD_FLAGS_EX BIT(6)
+#define ENETC_TXBD_FLAGS_F BIT(7)
+
+static inline void enetc_clear_tx_bd(union enetc_tx_bd *txbd)
+{
+ memset(txbd, 0, sizeof(*txbd));
+}
+
+/* L3 csum flags */
+#define ENETC_TXBD_L3_IPCS BIT(7)
+#define ENETC_TXBD_L3_IPV6 BIT(15)
+
+#define ENETC_TXBD_L3_START_MASK GENMASK(6, 0)
+#define ENETC_TXBD_L3_SET_HSIZE(val) ((((val) >> 2) & 0x7f) << 8)
+
+/* Extension flags */
+#define ENETC_TXBD_E_FLAGS_VLAN_INS BIT(0)
+#define ENETC_TXBD_E_FLAGS_TWO_STEP_PTP BIT(2)
+
+static inline __le16 enetc_txbd_l3_csoff(int start, int hdr_sz, u16 l3_flags)
+{
+ return cpu_to_le16(l3_flags | ENETC_TXBD_L3_SET_HSIZE(hdr_sz) |
+ (start & ENETC_TXBD_L3_START_MASK));
+}
+
+/* L4 csum flags */
+#define ENETC_TXBD_L4_UDP BIT(5)
+#define ENETC_TXBD_L4_TCP BIT(6)
+
+union enetc_rx_bd {
+ struct {
+ __le64 addr;
+ u8 reserved[8];
+ } w;
+ struct {
+ __le16 inet_csum;
+ __le16 parse_summary;
+ __le32 rss_hash;
+ __le16 buf_len;
+ __le16 vlan_opt;
+ union {
+ struct {
+ __le16 flags;
+ __le16 error;
+ };
+ __le32 lstatus;
+ };
+ } r;
+};
+
+#define ENETC_RXBD_LSTATUS_R BIT(30)
+#define ENETC_RXBD_LSTATUS_F BIT(31)
+#define ENETC_RXBD_ERR_MASK 0xff
+#define ENETC_RXBD_LSTATUS(flags) ((flags) << 16)
+#define ENETC_RXBD_FLAG_VLAN BIT(9)
+#define ENETC_RXBD_FLAG_TSTMP BIT(10)
+
+#define ENETC_MAC_ADDR_FILT_CNT 8 /* # of supported entries per port */
+#define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */
+#define ENETC_MAX_NUM_VFS 2
+
+struct enetc_cbd {
+ union {
+ struct {
+ __le32 addr[2];
+ __le32 opt[4];
+ };
+ __le32 data[6];
+ };
+ __le16 index;
+ __le16 length;
+ u8 cmd;
+ u8 cls;
+ u8 _res;
+ u8 status_flags;
+};
+
+#define ENETC_CBD_FLAGS_SF BIT(7) /* short format */
+#define ENETC_CBD_STATUS_MASK 0xf
+
+struct enetc_cmd_rfse {
+ u8 smac_h[6];
+ u8 smac_m[6];
+ u8 dmac_h[6];
+ u8 dmac_m[6];
+ u32 sip_h[4];
+ u32 sip_m[4];
+ u32 dip_h[4];
+ u32 dip_m[4];
+ u16 ethtype_h;
+ u16 ethtype_m;
+ u16 ethtype4_h;
+ u16 ethtype4_m;
+ u16 sport_h;
+ u16 sport_m;
+ u16 dport_h;
+ u16 dport_m;
+ u16 vlan_h;
+ u16 vlan_m;
+ u8 proto_h;
+ u8 proto_m;
+ u16 flags;
+ u16 result;
+ u16 mode;
+};
+
+#define ENETC_RFSE_EN BIT(15)
+#define ENETC_RFSE_MODE_BD 2
+
+static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr)
+{
+ *(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0);
+ *(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1);
+}
+
+#define ENETC_SI_INT_IDX 0
+/* base index for Rx/Tx interrupts */
+#define ENETC_BDR_INT_BASE_IDX 1
+
+/* Messaging */
+
+/* Command completion status */
+enum enetc_msg_cmd_status {
+ ENETC_MSG_CMD_STATUS_OK,
+ ENETC_MSG_CMD_STATUS_FAIL
+};
+
+/* VSI-PSI command message types */
+enum enetc_msg_cmd_type {
+ ENETC_MSG_CMD_MNG_MAC = 1, /* manage MAC address */
+ ENETC_MSG_CMD_MNG_RX_MAC_FILTER,/* manage RX MAC table */
+ ENETC_MSG_CMD_MNG_RX_VLAN_FILTER /* manage RX VLAN table */
+};
+
+/* VSI-PSI command action types */
+enum enetc_msg_cmd_action_type {
+ ENETC_MSG_CMD_MNG_ADD = 1,
+ ENETC_MSG_CMD_MNG_REMOVE
+};
+
+/* PSI-VSI command header format */
+struct enetc_msg_cmd_header {
+ u16 type; /* command class type */
+ u16 id; /* denotes the specific required action */
+};
+
+/* Common H/W utility functions */
+
+static inline void enetc_enable_rxvlan(struct enetc_hw *hw, int si_idx,
+ bool en)
+{
+ u32 val = enetc_rxbdr_rd(hw, si_idx, ENETC_RBMR);
+
+ val = (val & ~ENETC_RBMR_VTE) | (en ? ENETC_RBMR_VTE : 0);
+ enetc_rxbdr_wr(hw, si_idx, ENETC_RBMR, val);
+}
+
+static inline void enetc_enable_txvlan(struct enetc_hw *hw, int si_idx,
+ bool en)
+{
+ u32 val = enetc_txbdr_rd(hw, si_idx, ENETC_TBMR);
+
+ val = (val & ~ENETC_TBMR_VIH) | (en ? ENETC_TBMR_VIH : 0);
+ enetc_txbdr_wr(hw, si_idx, ENETC_TBMR, val);
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
new file mode 100644
index 000000000000..77b9cd10ba2b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2019 NXP */
+
+#include <linux/mdio.h>
+#include <linux/of_mdio.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+
+#include "enetc_pf.h"
+
+struct enetc_mdio_regs {
+ u32 mdio_cfg; /* MDIO configuration and status */
+ u32 mdio_ctl; /* MDIO control */
+ u32 mdio_data; /* MDIO data */
+ u32 mdio_addr; /* MDIO address */
+};
+
+#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv)
+
+#define ENETC_MDIO_REG_OFFSET 0x1c00
+#define ENETC_MDC_DIV 258
+
+#define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
+#define MDIO_CFG_BSY BIT(0)
+#define MDIO_CFG_RD_ER BIT(1)
+#define MDIO_CFG_ENC45 BIT(6)
+ /* external MDIO only - driven on neg MDC edge */
+#define MDIO_CFG_NEG BIT(23)
+
+#define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
+#define MDIO_CTL_READ BIT(15)
+#define MDIO_DATA(x) ((x) & 0xffff)
+
+#define TIMEOUT 1000
+static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs)
+{
+ u32 val;
+
+ return readx_poll_timeout(enetc_rd_reg, &regs->mdio_cfg, val,
+ !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
+}
+
+static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
+ u16 value)
+{
+ struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ u32 mdio_ctl, mdio_cfg;
+ u16 dev_addr;
+ int ret;
+
+ mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
+ if (regnum & MII_ADDR_C45) {
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_cfg |= MDIO_CFG_ENC45;
+ } else {
+ /* clause 22 (ie 1G) */
+ dev_addr = regnum & 0x1f;
+ mdio_cfg &= ~MDIO_CFG_ENC45;
+ }
+
+ enetc_wr_reg(&regs->mdio_cfg, mdio_cfg);
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+
+ /* set port and dev addr */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ enetc_wr_reg(&regs->mdio_ctl, mdio_ctl);
+
+ /* set the register address */
+ if (regnum & MII_ADDR_C45) {
+ enetc_wr_reg(&regs->mdio_addr, regnum & 0xffff);
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+ }
+
+ /* write the value */
+ enetc_wr_reg(&regs->mdio_data, MDIO_DATA(value));
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+ struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ u32 mdio_ctl, mdio_cfg;
+ u16 dev_addr, value;
+ int ret;
+
+ mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
+ if (regnum & MII_ADDR_C45) {
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_cfg |= MDIO_CFG_ENC45;
+ } else {
+ dev_addr = regnum & 0x1f;
+ mdio_cfg &= ~MDIO_CFG_ENC45;
+ }
+
+ enetc_wr_reg(&regs->mdio_cfg, mdio_cfg);
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+
+ /* set port and device addr */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ enetc_wr_reg(&regs->mdio_ctl, mdio_ctl);
+
+ /* set the register address */
+ if (regnum & MII_ADDR_C45) {
+ enetc_wr_reg(&regs->mdio_addr, regnum & 0xffff);
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+ }
+
+ /* initiate the read */
+ enetc_wr_reg(&regs->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
+
+ ret = enetc_mdio_wait_complete(regs);
+ if (ret)
+ return ret;
+
+ /* return all Fs if nothing was there */
+ if (enetc_rd_reg(&regs->mdio_cfg) & MDIO_CFG_RD_ER) {
+ dev_dbg(&bus->dev,
+ "Error while reading PHY%d reg at %d.%hhu\n",
+ phy_id, dev_addr, regnum);
+ return 0xffff;
+ }
+
+ value = enetc_rd_reg(&regs->mdio_data) & 0xffff;
+
+ return value;
+}
+
+int enetc_mdio_probe(struct enetc_pf *pf)
+{
+ struct device *dev = &pf->si->pdev->dev;
+ struct enetc_mdio_regs __iomem *regs;
+ struct device_node *np;
+ struct mii_bus *bus;
+ int ret;
+
+ bus = mdiobus_alloc_size(sizeof(regs));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "Freescale ENETC MDIO Bus";
+ bus->read = enetc_mdio_read;
+ bus->write = enetc_mdio_write;
+ bus->parent = dev;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+ /* store the enetc mdio base address for this bus */
+ regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET;
+ bus->priv = regs;
+
+ np = of_get_child_by_name(dev->of_node, "mdio");
+ if (!np) {
+ dev_err(dev, "MDIO node missing\n");
+ ret = -EINVAL;
+ goto err_registration;
+ }
+
+ ret = of_mdiobus_register(bus, np);
+ if (ret) {
+ of_node_put(np);
+ dev_err(dev, "cannot register MDIO bus\n");
+ goto err_registration;
+ }
+
+ of_node_put(np);
+ pf->mdio = bus;
+
+ return 0;
+
+err_registration:
+ mdiobus_free(bus);
+
+ return ret;
+}
+
+void enetc_mdio_remove(struct enetc_pf *pf)
+{
+ if (pf->mdio) {
+ mdiobus_unregister(pf->mdio);
+ mdiobus_free(pf->mdio);
+ }
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_msg.c b/drivers/net/ethernet/freescale/enetc/enetc_msg.c
new file mode 100644
index 000000000000..40d22ebe9224
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_msg.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include "enetc_pf.h"
+
+static void enetc_msg_disable_mr_int(struct enetc_hw *hw)
+{
+ u32 psiier = enetc_rd(hw, ENETC_PSIIER);
+ /* disable MR int source(s) */
+ enetc_wr(hw, ENETC_PSIIER, psiier & ~ENETC_PSIIER_MR_MASK);
+}
+
+static void enetc_msg_enable_mr_int(struct enetc_hw *hw)
+{
+ u32 psiier = enetc_rd(hw, ENETC_PSIIER);
+
+ enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK);
+}
+
+static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
+{
+ struct enetc_si *si = (struct enetc_si *)data;
+ struct enetc_pf *pf = enetc_si_priv(si);
+
+ enetc_msg_disable_mr_int(&si->hw);
+ schedule_work(&pf->msg_task);
+
+ return IRQ_HANDLED;
+}
+
+static void enetc_msg_task(struct work_struct *work)
+{
+ struct enetc_pf *pf = container_of(work, struct enetc_pf, msg_task);
+ struct enetc_hw *hw = &pf->si->hw;
+ unsigned long mr_mask;
+ int i;
+
+ for (;;) {
+ mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK;
+ if (!mr_mask) {
+ /* re-arm MR interrupts, w1c the IDR reg */
+ enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIIER_MR_MASK);
+ enetc_msg_enable_mr_int(hw);
+ return;
+ }
+
+ for (i = 0; i < pf->num_vfs; i++) {
+ u32 psimsgrr;
+ u16 msg_code;
+
+ if (!(ENETC_PSIMSGRR_MR(i) & mr_mask))
+ continue;
+
+ enetc_msg_handle_rxmsg(pf, i, &msg_code);
+
+ psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
+ psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */
+ enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
+ }
+ }
+}
+
+/* Init */
+static int enetc_msg_alloc_mbx(struct enetc_si *si, int idx)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct device *dev = &si->pdev->dev;
+ struct enetc_hw *hw = &si->hw;
+ struct enetc_msg_swbd *msg;
+ u32 val;
+
+ msg = &pf->rxmsg[idx];
+ /* allocate and set receive buffer */
+ msg->size = ENETC_DEFAULT_MSG_SIZE;
+
+ msg->vaddr = dma_alloc_coherent(dev, msg->size, &msg->dma,
+ GFP_KERNEL);
+ if (!msg->vaddr) {
+ dev_err(dev, "msg: fail to alloc dma buffer of size: %d\n",
+ msg->size);
+ return -ENOMEM;
+ }
+
+ /* set multiple of 32 bytes */
+ val = lower_32_bits(msg->dma);
+ enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), val);
+ val = upper_32_bits(msg->dma);
+ enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), val);
+
+ return 0;
+}
+
+static void enetc_msg_free_mbx(struct enetc_si *si, int idx)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_hw *hw = &si->hw;
+ struct enetc_msg_swbd *msg;
+
+ msg = &pf->rxmsg[idx];
+ dma_free_coherent(&si->pdev->dev, msg->size, msg->vaddr, msg->dma);
+ memset(msg, 0, sizeof(*msg));
+
+ enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0);
+ enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0);
+}
+
+int enetc_msg_psi_init(struct enetc_pf *pf)
+{
+ struct enetc_si *si = pf->si;
+ int vector, i, err;
+
+ /* register message passing interrupt handler */
+ snprintf(pf->msg_int_name, sizeof(pf->msg_int_name), "%s-vfmsg",
+ si->ndev->name);
+ vector = pci_irq_vector(si->pdev, ENETC_SI_INT_IDX);
+ err = request_irq(vector, enetc_msg_psi_msix, 0, pf->msg_int_name, si);
+ if (err) {
+ dev_err(&si->pdev->dev,
+ "PSI messaging: request_irq() failed!\n");
+ return err;
+ }
+
+ /* set one IRQ entry for PSI message receive notification (SI int) */
+ enetc_wr(&si->hw, ENETC_SIMSIVR, ENETC_SI_INT_IDX);
+
+ /* initialize PSI mailbox */
+ INIT_WORK(&pf->msg_task, enetc_msg_task);
+
+ for (i = 0; i < pf->num_vfs; i++) {
+ err = enetc_msg_alloc_mbx(si, i);
+ if (err)
+ goto err_init_mbx;
+ }
+
+ /* enable MR interrupts */
+ enetc_msg_enable_mr_int(&si->hw);
+
+ return 0;
+
+err_init_mbx:
+ for (i--; i >= 0; i--)
+ enetc_msg_free_mbx(si, i);
+
+ free_irq(vector, si);
+
+ return err;
+}
+
+void enetc_msg_psi_free(struct enetc_pf *pf)
+{
+ struct enetc_si *si = pf->si;
+ int i;
+
+ cancel_work_sync(&pf->msg_task);
+
+ /* disable MR interrupts */
+ enetc_msg_disable_mr_int(&si->hw);
+
+ for (i = 0; i < pf->num_vfs; i++)
+ enetc_msg_free_mbx(si, i);
+
+ /* de-register message passing interrupt handler */
+ free_irq(pci_irq_vector(si->pdev, ENETC_SI_INT_IDX), si);
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
new file mode 100644
index 000000000000..15876a6e7598
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -0,0 +1,943 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include "enetc_pf.h"
+
+#define ENETC_DRV_VER_MAJ 1
+#define ENETC_DRV_VER_MIN 0
+
+#define ENETC_DRV_VER_STR __stringify(ENETC_DRV_VER_MAJ) "." \
+ __stringify(ENETC_DRV_VER_MIN)
+static const char enetc_drv_ver[] = ENETC_DRV_VER_STR;
+#define ENETC_DRV_NAME_STR "ENETC PF driver"
+static const char enetc_drv_name[] = ENETC_DRV_NAME_STR;
+
+static void enetc_pf_get_primary_mac_addr(struct enetc_hw *hw, int si, u8 *addr)
+{
+ u32 upper = __raw_readl(hw->port + ENETC_PSIPMAR0(si));
+ u16 lower = __raw_readw(hw->port + ENETC_PSIPMAR1(si));
+
+ *(u32 *)addr = upper;
+ *(u16 *)(addr + 4) = lower;
+}
+
+static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si,
+ const u8 *addr)
+{
+ u32 upper = *(const u32 *)addr;
+ u16 lower = *(const u16 *)(addr + 4);
+
+ __raw_writel(upper, hw->port + ENETC_PSIPMAR0(si));
+ __raw_writew(lower, hw->port + ENETC_PSIPMAR1(si));
+}
+
+static int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct sockaddr *saddr = addr;
+
+ if (!is_valid_ether_addr(saddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(ndev->dev_addr, saddr->sa_data, ndev->addr_len);
+ enetc_pf_set_primary_mac_addr(&priv->si->hw, 0, saddr->sa_data);
+
+ return 0;
+}
+
+static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
+{
+ u32 val = enetc_port_rd(hw, ENETC_PSIPVMR);
+
+ val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL);
+ enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val);
+}
+
+static bool enetc_si_vlan_promisc_is_on(struct enetc_pf *pf, int si_idx)
+{
+ return pf->vlan_promisc_simap & BIT(si_idx);
+}
+
+static bool enetc_vlan_filter_is_on(struct enetc_pf *pf)
+{
+ int i;
+
+ for_each_set_bit(i, pf->active_vlans, VLAN_N_VID)
+ return true;
+
+ return false;
+}
+
+static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
+{
+ pf->vlan_promisc_simap |= BIT(si_idx);
+ enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
+}
+
+static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
+{
+ pf->vlan_promisc_simap &= ~BIT(si_idx);
+ enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
+}
+
+static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
+{
+ u32 val = 0;
+
+ if (vlan)
+ val = ENETC_PSIVLAN_EN | ENETC_PSIVLAN_SET_QOS(qos) | vlan;
+
+ enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
+}
+
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+ u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+ u64 mask = 0;
+ int res = 0;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ mask |= BIT_ULL(i * 6);
+
+ for (i = 0; i < 6; i++)
+ res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+ return res;
+}
+
+static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+ filter->mac_addr_cnt = 0;
+
+ bitmap_zero(filter->mac_hash_table,
+ ENETC_MADDR_HASH_TBL_SZ);
+}
+
+static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+ /* add exact match addr */
+ ether_addr_copy(filter->mac_addr, addr);
+ filter->mac_addr_cnt++;
+}
+
+static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+ int idx = enetc_mac_addr_hash_idx(addr);
+
+ /* add hash table entry */
+ __set_bit(idx, filter->mac_hash_table);
+ filter->mac_addr_cnt++;
+}
+
+static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)
+{
+ bool err = si->errata & ENETC_ERR_UCMCSWP;
+
+ if (type == UC) {
+ enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), 0);
+ enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), 0);
+ } else { /* MC */
+ enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), 0);
+ enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), 0);
+ }
+}
+
+static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,
+ u32 *hash)
+{
+ bool err = si->errata & ENETC_ERR_UCMCSWP;
+
+ if (type == UC) {
+ enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), *hash);
+ enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), *(hash + 1));
+ } else { /* MC */
+ enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), *hash);
+ enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), *(hash + 1));
+ }
+}
+
+static void enetc_sync_mac_filters(struct enetc_pf *pf)
+{
+ struct enetc_mac_filter *f = pf->mac_filter;
+ struct enetc_si *si = pf->si;
+ int i, pos;
+
+ pos = EMETC_MAC_ADDR_FILT_RES;
+
+ for (i = 0; i < MADDR_TYPE; i++, f++) {
+ bool em = (f->mac_addr_cnt == 1) && (i == UC);
+ bool clear = !f->mac_addr_cnt;
+
+ if (clear) {
+ if (i == UC)
+ enetc_clear_mac_flt_entry(si, pos);
+
+ enetc_clear_mac_ht_flt(si, 0, i);
+ continue;
+ }
+
+ /* exact match filter */
+ if (em) {
+ int err;
+
+ enetc_clear_mac_ht_flt(si, 0, UC);
+
+ err = enetc_set_mac_flt_entry(si, pos, f->mac_addr,
+ BIT(0));
+ if (!err)
+ continue;
+
+ /* fallback to HT filtering */
+ dev_warn(&si->pdev->dev, "fallback to HT filt (%d)\n",
+ err);
+ }
+
+ /* hash table filter, clear EM filter for UC entries */
+ if (i == UC)
+ enetc_clear_mac_flt_entry(si, pos);
+
+ enetc_set_mac_ht_flt(si, 0, i, (u32 *)f->mac_hash_table);
+ }
+}
+
+static void enetc_pf_set_rx_mode(struct net_device *ndev)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct enetc_hw *hw = &priv->si->hw;
+ bool uprom = false, mprom = false;
+ struct enetc_mac_filter *filter;
+ struct netdev_hw_addr *ha;
+ u32 psipmr = 0;
+ bool em;
+
+ if (ndev->flags & IFF_PROMISC) {
+ /* enable promisc mode for SI0 (PF) */
+ psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
+ uprom = true;
+ mprom = true;
+ /* enable VLAN promisc mode for SI0 */
+ if (!enetc_si_vlan_promisc_is_on(pf, 0))
+ enetc_enable_si_vlan_promisc(pf, 0);
+
+ } else if (ndev->flags & IFF_ALLMULTI) {
+ /* enable multi cast promisc mode for SI0 (PF) */
+ psipmr = ENETC_PSIPMR_SET_MP(0);
+ mprom = true;
+ }
+
+ /* first 2 filter entries belong to PF */
+ if (!uprom) {
+ /* Update unicast filters */
+ filter = &pf->mac_filter[UC];
+ enetc_reset_mac_addr_filter(filter);
+
+ em = (netdev_uc_count(ndev) == 1);
+ netdev_for_each_uc_addr(ha, ndev) {
+ if (em) {
+ enetc_add_mac_addr_em_filter(filter, ha->addr);
+ break;
+ }
+
+ enetc_add_mac_addr_ht_filter(filter, ha->addr);
+ }
+ }
+
+ if (!mprom) {
+ /* Update multicast filters */
+ filter = &pf->mac_filter[MC];
+ enetc_reset_mac_addr_filter(filter);
+
+ netdev_for_each_mc_addr(ha, ndev) {
+ if (!is_multicast_ether_addr(ha->addr))
+ continue;
+
+ enetc_add_mac_addr_ht_filter(filter, ha->addr);
+ }
+ }
+
+ if (!uprom || !mprom)
+ /* update PF entries */
+ enetc_sync_mac_filters(pf);
+
+ psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) &
+ ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));
+ enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
+}
+
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
+ u32 *hash)
+{
+ enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), *hash);
+ enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), *(hash + 1));
+}
+
+static int enetc_vid_hash_idx(unsigned int vid)
+{
+ int res = 0;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+ return res;
+}
+
+static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
+{
+ int i;
+
+ if (rehash) {
+ bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+
+ for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+ int hidx = enetc_vid_hash_idx(i);
+
+ __set_bit(hidx, pf->vlan_ht_filter);
+ }
+ }
+
+ enetc_set_vlan_ht_filter(&pf->si->hw, 0, (u32 *)pf->vlan_ht_filter);
+}
+
+static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ int idx;
+
+ if (enetc_si_vlan_promisc_is_on(pf, 0))
+ enetc_disable_si_vlan_promisc(pf, 0);
+
+ __set_bit(vid, pf->active_vlans);
+
+ idx = enetc_vid_hash_idx(vid);
+ if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
+ enetc_sync_vlan_ht_filter(pf, false);
+
+ return 0;
+}
+
+static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+
+ __clear_bit(vid, pf->active_vlans);
+ enetc_sync_vlan_ht_filter(pf, true);
+
+ if (!enetc_vlan_filter_is_on(pf))
+ enetc_enable_si_vlan_promisc(pf, 0);
+
+ return 0;
+}
+
+static void enetc_set_loopback(struct net_device *ndev, bool en)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 reg;
+
+ reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
+ if (reg & ENETC_PMO_IFM_RG) {
+ /* RGMII mode */
+ reg = (reg & ~ENETC_PM0_IFM_RLP) |
+ (en ? ENETC_PM0_IFM_RLP : 0);
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, reg);
+ } else {
+ /* assume SGMII mode */
+ reg = enetc_port_rd(hw, ENETC_PM0_CMD_CFG);
+ reg = (reg & ~ENETC_PM0_CMD_XGLP) |
+ (en ? ENETC_PM0_CMD_XGLP : 0);
+ reg = (reg & ~ENETC_PM0_CMD_PHY_TX_EN) |
+ (en ? ENETC_PM0_CMD_PHY_TX_EN : 0);
+ enetc_port_wr(hw, ENETC_PM0_CMD_CFG, reg);
+ enetc_port_wr(hw, ENETC_PM1_CMD_CFG, reg);
+ }
+}
+
+static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct enetc_vf_state *vf_state;
+
+ if (vf >= pf->total_vfs)
+ return -EINVAL;
+
+ if (!is_valid_ether_addr(mac))
+ return -EADDRNOTAVAIL;
+
+ vf_state = &pf->vf_state[vf];
+ vf_state->flags |= ENETC_VF_FLAG_PF_SET_MAC;
+ enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac);
+ return 0;
+}
+
+static int enetc_pf_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan,
+ u8 qos, __be16 proto)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+
+ if (priv->si->errata & ENETC_ERR_VLAN_ISOL)
+ return -EOPNOTSUPP;
+
+ if (vf >= pf->total_vfs)
+ return -EINVAL;
+
+ if (proto != htons(ETH_P_8021Q))
+ /* only C-tags supported for now */
+ return -EPROTONOSUPPORT;
+
+ enetc_set_isol_vlan(&priv->si->hw, vf + 1, vlan, qos);
+ return 0;
+}
+
+static int enetc_pf_set_vf_spoofchk(struct net_device *ndev, int vf, bool en)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ u32 cfgr;
+
+ if (vf >= pf->total_vfs)
+ return -EINVAL;
+
+ cfgr = enetc_port_rd(&priv->si->hw, ENETC_PSICFGR0(vf + 1));
+ cfgr = (cfgr & ~ENETC_PSICFGR0_ASE) | (en ? ENETC_PSICFGR0_ASE : 0);
+ enetc_port_wr(&priv->si->hw, ENETC_PSICFGR0(vf + 1), cfgr);
+
+ return 0;
+}
+
+static void enetc_port_setup_primary_mac_address(struct enetc_si *si)
+{
+ unsigned char mac_addr[MAX_ADDR_LEN];
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_hw *hw = &si->hw;
+ int i;
+
+ /* check MAC addresses for PF and all VFs, if any is 0 set it ro rand */
+ for (i = 0; i < pf->total_vfs + 1; i++) {
+ enetc_pf_get_primary_mac_addr(hw, i, mac_addr);
+ if (!is_zero_ether_addr(mac_addr))
+ continue;
+ eth_random_addr(mac_addr);
+ dev_info(&si->pdev->dev, "no MAC address specified for SI%d, using %pM\n",
+ i, mac_addr);
+ enetc_pf_set_primary_mac_addr(hw, i, mac_addr);
+ }
+}
+
+static void enetc_port_assign_rfs_entries(struct enetc_si *si)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_hw *hw = &si->hw;
+ int num_entries, vf_entries, i;
+ u32 val;
+
+ /* split RFS entries between functions */
+ val = enetc_port_rd(hw, ENETC_PRFSCAPR);
+ num_entries = ENETC_PRFSCAPR_GET_NUM_RFS(val);
+ vf_entries = num_entries / (pf->total_vfs + 1);
+
+ for (i = 0; i < pf->total_vfs; i++)
+ enetc_port_wr(hw, ENETC_PSIRFSCFGR(i + 1), vf_entries);
+ enetc_port_wr(hw, ENETC_PSIRFSCFGR(0),
+ num_entries - vf_entries * pf->total_vfs);
+
+ /* enable RFS on port */
+ enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE);
+}
+
+static void enetc_port_si_configure(struct enetc_si *si)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_hw *hw = &si->hw;
+ int num_rings, i;
+ u32 val;
+
+ val = enetc_port_rd(hw, ENETC_PCAPR0);
+ num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val));
+
+ val = ENETC_PSICFGR0_SET_TXBDR(ENETC_PF_NUM_RINGS);
+ val |= ENETC_PSICFGR0_SET_RXBDR(ENETC_PF_NUM_RINGS);
+
+ if (unlikely(num_rings < ENETC_PF_NUM_RINGS)) {
+ val = ENETC_PSICFGR0_SET_TXBDR(num_rings);
+ val |= ENETC_PSICFGR0_SET_RXBDR(num_rings);
+
+ dev_warn(&si->pdev->dev, "Found %d rings, expected %d!\n",
+ num_rings, ENETC_PF_NUM_RINGS);
+
+ num_rings = 0;
+ }
+
+ /* Add default one-time settings for SI0 (PF) */
+ val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
+
+ enetc_port_wr(hw, ENETC_PSICFGR0(0), val);
+
+ if (num_rings)
+ num_rings -= ENETC_PF_NUM_RINGS;
+
+ /* Configure the SIs for each available VF */
+ val = ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
+ val |= ENETC_PSICFGR0_VTE | ENETC_PSICFGR0_SIVIE;
+
+ if (num_rings) {
+ num_rings /= pf->total_vfs;
+ val |= ENETC_PSICFGR0_SET_TXBDR(num_rings);
+ val |= ENETC_PSICFGR0_SET_RXBDR(num_rings);
+ }
+
+ for (i = 0; i < pf->total_vfs; i++)
+ enetc_port_wr(hw, ENETC_PSICFGR0(i + 1), val);
+
+ /* Port level VLAN settings */
+ val = ENETC_PVCLCTR_OVTPIDL(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
+ enetc_port_wr(hw, ENETC_PVCLCTR, val);
+ /* use outer tag for VLAN filtering */
+ enetc_port_wr(hw, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS);
+}
+
+static void enetc_configure_port_mac(struct enetc_hw *hw)
+{
+ enetc_port_wr(hw, ENETC_PM0_MAXFRM,
+ ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE));
+
+ enetc_port_wr(hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE);
+ enetc_port_wr(hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE);
+
+ enetc_port_wr(hw, ENETC_PM0_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
+ ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC |
+ ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
+
+ enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
+ ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC |
+ ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
+ /* set auto-speed for RGMII */
+ if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG)
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO);
+ if (enetc_global_rd(hw, ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII)
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII);
+}
+
+static void enetc_configure_port_pmac(struct enetc_hw *hw)
+{
+ u32 temp;
+
+ /* Set pMAC step lock */
+ temp = enetc_port_rd(hw, ENETC_PFPMR);
+ enetc_port_wr(hw, ENETC_PFPMR,
+ temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM);
+
+ temp = enetc_port_rd(hw, ENETC_MMCSR);
+ enetc_port_wr(hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME);
+}
+
+static void enetc_configure_port(struct enetc_pf *pf)
+{
+ u8 hash_key[ENETC_RSSHASH_KEY_SIZE];
+ struct enetc_hw *hw = &pf->si->hw;
+
+ enetc_configure_port_pmac(hw);
+
+ enetc_configure_port_mac(hw);
+
+ enetc_port_si_configure(pf->si);
+
+ /* set up hash key */
+ get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
+ enetc_set_rss_key(hw, hash_key);
+
+ /* split up RFS entries */
+ enetc_port_assign_rfs_entries(pf->si);
+
+ /* fix-up primary MAC addresses, if not set already */
+ enetc_port_setup_primary_mac_address(pf->si);
+
+ /* enforce VLAN promisc mode for all SIs */
+ pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL;
+ enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap);
+
+ enetc_port_wr(hw, ENETC_PSIPMR, 0);
+
+ /* enable port */
+ enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN);
+}
+
+/* Messaging */
+static u16 enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf *pf,
+ int vf_id)
+{
+ struct enetc_vf_state *vf_state = &pf->vf_state[vf_id];
+ struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
+ struct enetc_msg_cmd_set_primary_mac *cmd;
+ struct device *dev = &pf->si->pdev->dev;
+ u16 cmd_id;
+ char *addr;
+
+ cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
+ cmd_id = cmd->header.id;
+ if (cmd_id != ENETC_MSG_CMD_MNG_ADD)
+ return ENETC_MSG_CMD_STATUS_FAIL;
+
+ addr = cmd->mac.sa_data;
+ if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC)
+ dev_warn(dev, "Attempt to override PF set mac addr for VF%d\n",
+ vf_id);
+ else
+ enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr);
+
+ return ENETC_MSG_CMD_STATUS_OK;
+}
+
+void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id, u16 *status)
+{
+ struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
+ struct device *dev = &pf->si->pdev->dev;
+ struct enetc_msg_cmd_header *cmd_hdr;
+ u16 cmd_type;
+
+ *status = ENETC_MSG_CMD_STATUS_OK;
+ cmd_hdr = (struct enetc_msg_cmd_header *)msg->vaddr;
+ cmd_type = cmd_hdr->type;
+
+ switch (cmd_type) {
+ case ENETC_MSG_CMD_MNG_MAC:
+ *status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id);
+ break;
+ default:
+ dev_err(dev, "command not supported (cmd_type: 0x%x)\n",
+ cmd_type);
+ }
+}
+
+#ifdef CONFIG_PCI_IOV
+static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+ struct enetc_pf *pf = enetc_si_priv(si);
+ int err;
+
+ if (!num_vfs) {
+ enetc_msg_psi_free(pf);
+ kfree(pf->vf_state);
+ pf->num_vfs = 0;
+ pci_disable_sriov(pdev);
+ } else {
+ pf->num_vfs = num_vfs;
+
+ pf->vf_state = kcalloc(num_vfs, sizeof(struct enetc_vf_state),
+ GFP_KERNEL);
+ if (!pf->vf_state) {
+ pf->num_vfs = 0;
+ return -ENOMEM;
+ }
+
+ err = enetc_msg_psi_init(pf);
+ if (err) {
+ dev_err(&pdev->dev, "enetc_msg_psi_init (%d)\n", err);
+ goto err_msg_psi;
+ }
+
+ err = pci_enable_sriov(pdev, num_vfs);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_sriov err %d\n", err);
+ goto err_en_sriov;
+ }
+ }
+
+ return num_vfs;
+
+err_en_sriov:
+ enetc_msg_psi_free(pf);
+err_msg_psi:
+ kfree(pf->vf_state);
+ pf->num_vfs = 0;
+
+ return err;
+}
+#else
+#define enetc_sriov_configure(pdev, num_vfs) (void)0
+#endif
+
+static int enetc_pf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ netdev_features_t changed = ndev->features ^ features;
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+ enetc_enable_rxvlan(&priv->si->hw, 0,
+ !!(features & NETIF_F_HW_VLAN_CTAG_RX));
+
+ if (changed & NETIF_F_HW_VLAN_CTAG_TX)
+ enetc_enable_txvlan(&priv->si->hw, 0,
+ !!(features & NETIF_F_HW_VLAN_CTAG_TX));
+
+ if (changed & NETIF_F_LOOPBACK)
+ enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
+ return enetc_set_features(ndev, features);
+}
+
+static const struct net_device_ops enetc_ndev_ops = {
+ .ndo_open = enetc_open,
+ .ndo_stop = enetc_close,
+ .ndo_start_xmit = enetc_xmit,
+ .ndo_get_stats = enetc_get_stats,
+ .ndo_set_mac_address = enetc_pf_set_mac_addr,
+ .ndo_set_rx_mode = enetc_pf_set_rx_mode,
+ .ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = enetc_vlan_rx_del_vid,
+ .ndo_set_vf_mac = enetc_pf_set_vf_mac,
+ .ndo_set_vf_vlan = enetc_pf_set_vf_vlan,
+ .ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk,
+ .ndo_set_features = enetc_pf_set_features,
+};
+
+static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
+ const struct net_device_ops *ndev_ops)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ SET_NETDEV_DEV(ndev, &si->pdev->dev);
+ priv->ndev = ndev;
+ priv->si = si;
+ priv->dev = &si->pdev->dev;
+ si->ndev = ndev;
+
+ priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
+ ndev->netdev_ops = ndev_ops;
+ enetc_set_ethtool_ops(ndev);
+ ndev->watchdog_timeo = 5 * HZ;
+ ndev->max_mtu = ENETC_MAX_MTU;
+
+ ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_LOOPBACK;
+ ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG |
+ NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER;
+
+ if (si->num_rss)
+ ndev->hw_features |= NETIF_F_RXHASH;
+
+ if (si->errata & ENETC_ERR_TXCSUM) {
+ ndev->hw_features &= ~NETIF_F_HW_CSUM;
+ ndev->features &= ~NETIF_F_HW_CSUM;
+ }
+
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+
+ /* pick up primary MAC address from SI */
+ enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
+}
+
+static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
+{
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct device_node *np = priv->dev->of_node;
+ int err;
+
+ if (!np) {
+ dev_err(priv->dev, "missing ENETC port node\n");
+ return -ENODEV;
+ }
+
+ priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (!priv->phy_node) {
+ if (!of_phy_is_fixed_link(np)) {
+ dev_err(priv->dev, "PHY not specified\n");
+ return -ENODEV;
+ }
+
+ err = of_phy_register_fixed_link(np);
+ if (err < 0) {
+ dev_err(priv->dev, "fixed link registration failed\n");
+ return err;
+ }
+
+ priv->phy_node = of_node_get(np);
+ }
+
+ if (!of_phy_is_fixed_link(np)) {
+ err = enetc_mdio_probe(pf);
+ if (err) {
+ of_node_put(priv->phy_node);
+ return err;
+ }
+ }
+
+ priv->if_mode = of_get_phy_mode(np);
+ if (priv->if_mode < 0) {
+ dev_err(priv->dev, "missing phy type\n");
+ of_node_put(priv->phy_node);
+ if (of_phy_is_fixed_link(np))
+ of_phy_deregister_fixed_link(np);
+ else
+ enetc_mdio_remove(pf);
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void enetc_of_put_phy(struct enetc_ndev_priv *priv)
+{
+ struct device_node *np = priv->dev->of_node;
+
+ if (np && of_phy_is_fixed_link(np))
+ of_phy_deregister_fixed_link(np);
+ if (priv->phy_node)
+ of_node_put(priv->phy_node);
+}
+
+static int enetc_pf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct enetc_ndev_priv *priv;
+ struct net_device *ndev;
+ struct enetc_si *si;
+ struct enetc_pf *pf;
+ int err;
+
+ if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
+ dev_info(&pdev->dev, "device is disabled, skipping\n");
+ return -ENODEV;
+ }
+
+ err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
+ if (err) {
+ dev_err(&pdev->dev, "PCI probing failed\n");
+ return err;
+ }
+
+ si = pci_get_drvdata(pdev);
+ if (!si->hw.port || !si->hw.global) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
+ goto err_map_pf_space;
+ }
+
+ pf = enetc_si_priv(si);
+ pf->si = si;
+ pf->total_vfs = pci_sriov_get_totalvfs(pdev);
+
+ enetc_configure_port(pf);
+
+ enetc_get_si_caps(si);
+
+ ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
+ if (!ndev) {
+ err = -ENOMEM;
+ dev_err(&pdev->dev, "netdev creation failed\n");
+ goto err_alloc_netdev;
+ }
+
+ enetc_pf_netdev_setup(si, ndev, &enetc_ndev_ops);
+
+ priv = netdev_priv(ndev);
+
+ enetc_init_si_rings_params(priv);
+
+ err = enetc_alloc_si_resources(priv);
+ if (err) {
+ dev_err(&pdev->dev, "SI resource alloc failed\n");
+ goto err_alloc_si_res;
+ }
+
+ err = enetc_alloc_msix(priv);
+ if (err) {
+ dev_err(&pdev->dev, "MSIX alloc failed\n");
+ goto err_alloc_msix;
+ }
+
+ err = enetc_of_get_phy(priv);
+ if (err)
+ dev_warn(&pdev->dev, "Fallback to PHY-less operation\n");
+
+ err = register_netdev(ndev);
+ if (err)
+ goto err_reg_netdev;
+
+ netif_carrier_off(ndev);
+
+ netif_info(priv, probe, ndev, "%s v%s\n",
+ enetc_drv_name, enetc_drv_ver);
+
+ return 0;
+
+err_reg_netdev:
+ enetc_of_put_phy(priv);
+ enetc_free_msix(priv);
+err_alloc_msix:
+ enetc_free_si_resources(priv);
+err_alloc_si_res:
+ si->ndev = NULL;
+ free_netdev(ndev);
+err_alloc_netdev:
+err_map_pf_space:
+ enetc_pci_remove(pdev);
+
+ return err;
+}
+
+static void enetc_pf_remove(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+ struct enetc_pf *pf = enetc_si_priv(si);
+ struct enetc_ndev_priv *priv;
+
+ if (pf->num_vfs)
+ enetc_sriov_configure(pdev, 0);
+
+ priv = netdev_priv(si->ndev);
+ netif_info(priv, drv, si->ndev, "%s v%s remove\n",
+ enetc_drv_name, enetc_drv_ver);
+
+ unregister_netdev(si->ndev);
+
+ enetc_mdio_remove(pf);
+ enetc_of_put_phy(priv);
+
+ enetc_free_msix(priv);
+
+ enetc_free_si_resources(priv);
+
+ free_netdev(si->ndev);
+
+ enetc_pci_remove(pdev);
+}
+
+static const struct pci_device_id enetc_pf_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc_pf_id_table);
+
+static struct pci_driver enetc_pf_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = enetc_pf_id_table,
+ .probe = enetc_pf_probe,
+ .remove = enetc_pf_remove,
+#ifdef CONFIG_PCI_IOV
+ .sriov_configure = enetc_sriov_configure,
+#endif
+};
+module_pci_driver(enetc_pf_driver);
+
+MODULE_DESCRIPTION(ENETC_DRV_NAME_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(ENETC_DRV_VER_STR);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
new file mode 100644
index 000000000000..10dd1b53bb08
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2017-2019 NXP */
+
+#include "enetc.h"
+
+#define ENETC_PF_NUM_RINGS 8
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+#define ENETC_MAX_NUM_MAC_FLT ((ENETC_MAX_NUM_VFS + 1) * MADDR_TYPE)
+
+#define ENETC_MADDR_HASH_TBL_SZ 64
+struct enetc_mac_filter {
+ union {
+ char mac_addr[ETH_ALEN];
+ DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+ };
+ int mac_addr_cnt;
+};
+
+#define ENETC_VLAN_HT_SIZE 64
+
+enum enetc_vf_flags {
+ ENETC_VF_FLAG_PF_SET_MAC = BIT(0),
+};
+
+struct enetc_vf_state {
+ enum enetc_vf_flags flags;
+};
+
+struct enetc_pf {
+ struct enetc_si *si;
+ int num_vfs; /* number of active VFs, after sriov_init */
+ int total_vfs; /* max number of VFs, set for PF at probe */
+ struct enetc_vf_state *vf_state;
+
+ struct enetc_mac_filter mac_filter[ENETC_MAX_NUM_MAC_FLT];
+
+ struct enetc_msg_swbd rxmsg[ENETC_MAX_NUM_VFS];
+ struct work_struct msg_task;
+ char msg_int_name[ENETC_INT_NAME_MAX];
+
+ char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */
+ DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ DECLARE_BITMAP(active_vlans, VLAN_N_VID);
+
+ struct mii_bus *mdio; /* saved for cleanup */
+};
+
+int enetc_msg_psi_init(struct enetc_pf *pf);
+void enetc_msg_psi_free(struct enetc_pf *pf);
+void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int mbox_id, u16 *status);
+
+/* MDIO */
+int enetc_mdio_probe(struct enetc_pf *pf);
+void enetc_mdio_remove(struct enetc_pf *pf);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
new file mode 100644
index 000000000000..8c1497e7d9c5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2019 NXP */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/fsl/ptp_qoriq.h>
+
+#include "enetc.h"
+
+static struct ptp_clock_info enetc_ptp_caps = {
+ .owner = THIS_MODULE,
+ .name = "ENETC PTP clock",
+ .max_adj = 512000,
+ .n_alarm = 0,
+ .n_ext_ts = 2,
+ .n_per_out = 0,
+ .n_pins = 0,
+ .pps = 1,
+ .adjfine = ptp_qoriq_adjfine,
+ .adjtime = ptp_qoriq_adjtime,
+ .gettime64 = ptp_qoriq_gettime,
+ .settime64 = ptp_qoriq_settime,
+ .enable = ptp_qoriq_enable,
+};
+
+static int enetc_ptp_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct ptp_qoriq *ptp_qoriq;
+ void __iomem *base;
+ int err, len, n;
+
+ if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
+ dev_info(&pdev->dev, "device is disabled, skipping\n");
+ return -ENODEV;
+ }
+
+ err = pci_enable_device_mem(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "device enable failed\n");
+ return err;
+ }
+
+ /* set up for high or low dma */
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (err) {
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA configuration failed: 0x%x\n", err);
+ goto err_dma;
+ }
+ }
+
+ err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
+ if (err) {
+ dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
+ goto err_pci_mem_reg;
+ }
+
+ pci_set_master(pdev);
+
+ ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
+ if (!ptp_qoriq) {
+ err = -ENOMEM;
+ goto err_alloc_ptp;
+ }
+
+ len = pci_resource_len(pdev, ENETC_BAR_REGS);
+
+ base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
+ if (!base) {
+ err = -ENXIO;
+ dev_err(&pdev->dev, "ioremap() failed\n");
+ goto err_ioremap;
+ }
+
+ /* Allocate 1 interrupt */
+ n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
+ if (n != 1) {
+ err = -EPERM;
+ goto err_irq;
+ }
+
+ ptp_qoriq->irq = pci_irq_vector(pdev, 0);
+
+ err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq);
+ if (err) {
+ dev_err(&pdev->dev, "request_irq() failed!\n");
+ goto err_irq;
+ }
+
+ ptp_qoriq->dev = &pdev->dev;
+
+ err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps);
+ if (err)
+ goto err_no_clock;
+
+ pci_set_drvdata(pdev, ptp_qoriq);
+
+ return 0;
+
+err_no_clock:
+ free_irq(ptp_qoriq->irq, ptp_qoriq);
+err_irq:
+ iounmap(base);
+err_ioremap:
+ kfree(ptp_qoriq);
+err_alloc_ptp:
+ pci_release_mem_regions(pdev);
+err_pci_mem_reg:
+err_dma:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void enetc_ptp_remove(struct pci_dev *pdev)
+{
+ struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
+
+ ptp_qoriq_free(ptp_qoriq);
+ kfree(ptp_qoriq);
+
+ pci_release_mem_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static const struct pci_device_id enetc_ptp_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
+
+static struct pci_driver enetc_ptp_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = enetc_ptp_id_table,
+ .probe = enetc_ptp_probe,
+ .remove = enetc_ptp_remove,
+};
+module_pci_driver(enetc_ptp_driver);
+
+MODULE_DESCRIPTION("ENETC PTP clock driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
new file mode 100644
index 000000000000..64bebee9f52a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2017-2019 NXP */
+
+#include <linux/module.h>
+#include "enetc.h"
+
+#define ENETC_DRV_VER_MAJ 1
+#define ENETC_DRV_VER_MIN 0
+
+#define ENETC_DRV_VER_STR __stringify(ENETC_DRV_VER_MAJ) "." \
+ __stringify(ENETC_DRV_VER_MIN)
+static const char enetc_drv_ver[] = ENETC_DRV_VER_STR;
+#define ENETC_DRV_NAME_STR "ENETC VF driver"
+static const char enetc_drv_name[] = ENETC_DRV_NAME_STR;
+
+/* Messaging */
+static void enetc_msg_vsi_write_msg(struct enetc_hw *hw,
+ struct enetc_msg_swbd *msg)
+{
+ u32 val;
+
+ val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);
+ enetc_wr(hw, ENETC_VSIMSGSNDAR1, upper_32_bits(msg->dma));
+ enetc_wr(hw, ENETC_VSIMSGSNDAR0, val);
+}
+
+static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg)
+{
+ int timeout = 100;
+ u32 vsimsgsr;
+
+ enetc_msg_vsi_write_msg(&si->hw, msg);
+
+ do {
+ vsimsgsr = enetc_rd(&si->hw, ENETC_VSIMSGSR);
+ if (!(vsimsgsr & ENETC_VSIMSGSR_MB))
+ break;
+
+ usleep_range(1000, 2000);
+ } while (--timeout);
+
+ if (!timeout)
+ return -ETIMEDOUT;
+
+ /* check for message delivery error */
+ if (vsimsgsr & ENETC_VSIMSGSR_MS) {
+ dev_err(&si->pdev->dev, "VSI command execute error: %d\n",
+ ENETC_SIMSGSR_GET_MC(vsimsgsr));
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv,
+ struct sockaddr *saddr)
+{
+ struct enetc_msg_cmd_set_primary_mac *cmd;
+ struct enetc_msg_swbd msg;
+ int err;
+
+ msg.size = ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac), 64);
+ msg.vaddr = dma_alloc_coherent(priv->dev, msg.size, &msg.dma,
+ GFP_KERNEL);
+ if (!msg.vaddr) {
+ dev_err(priv->dev, "Failed to alloc Tx msg (size: %d)\n",
+ msg.size);
+ return -ENOMEM;
+ }
+
+ cmd = (struct enetc_msg_cmd_set_primary_mac *)msg.vaddr;
+ cmd->header.type = ENETC_MSG_CMD_MNG_MAC;
+ cmd->header.id = ENETC_MSG_CMD_MNG_ADD;
+ memcpy(&cmd->mac, saddr, sizeof(struct sockaddr));
+
+ /* send the command and wait */
+ err = enetc_msg_vsi_send(priv->si, &msg);
+
+ dma_free_coherent(priv->dev, msg.size, msg.vaddr, msg.dma);
+
+ return err;
+}
+
+static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct sockaddr *saddr = addr;
+ int err;
+
+ if (!is_valid_ether_addr(saddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ err = enetc_msg_vsi_set_primary_mac_addr(priv, saddr);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int enetc_vf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ return enetc_set_features(ndev, features);
+}
+
+/* Probing/ Init */
+static const struct net_device_ops enetc_ndev_ops = {
+ .ndo_open = enetc_open,
+ .ndo_stop = enetc_close,
+ .ndo_start_xmit = enetc_xmit,
+ .ndo_get_stats = enetc_get_stats,
+ .ndo_set_mac_address = enetc_vf_set_mac_addr,
+ .ndo_set_features = enetc_vf_set_features,
+};
+
+static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
+ const struct net_device_ops *ndev_ops)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ SET_NETDEV_DEV(ndev, &si->pdev->dev);
+ priv->ndev = ndev;
+ priv->si = si;
+ priv->dev = &si->pdev->dev;
+ si->ndev = ndev;
+
+ priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
+ ndev->netdev_ops = ndev_ops;
+ enetc_set_ethtool_ops(ndev);
+ ndev->watchdog_timeo = 5 * HZ;
+ ndev->max_mtu = ENETC_MAX_MTU;
+
+ ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX;
+ ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG |
+ NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX;
+
+ if (si->num_rss)
+ ndev->hw_features |= NETIF_F_RXHASH;
+
+ if (si->errata & ENETC_ERR_TXCSUM) {
+ ndev->hw_features &= ~NETIF_F_HW_CSUM;
+ ndev->features &= ~NETIF_F_HW_CSUM;
+ }
+
+ /* pick up primary MAC address from SI */
+ enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
+}
+
+static int enetc_vf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct enetc_ndev_priv *priv;
+ struct net_device *ndev;
+ struct enetc_si *si;
+ int err;
+
+ err = enetc_pci_probe(pdev, KBUILD_MODNAME, 0);
+ if (err) {
+ dev_err(&pdev->dev, "PCI probing failed\n");
+ return err;
+ }
+
+ si = pci_get_drvdata(pdev);
+
+ enetc_get_si_caps(si);
+
+ ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
+ if (!ndev) {
+ err = -ENOMEM;
+ dev_err(&pdev->dev, "netdev creation failed\n");
+ goto err_alloc_netdev;
+ }
+
+ enetc_vf_netdev_setup(si, ndev, &enetc_ndev_ops);
+
+ priv = netdev_priv(ndev);
+
+ enetc_init_si_rings_params(priv);
+
+ err = enetc_alloc_si_resources(priv);
+ if (err) {
+ dev_err(&pdev->dev, "SI resource alloc failed\n");
+ goto err_alloc_si_res;
+ }
+
+ err = enetc_alloc_msix(priv);
+ if (err) {
+ dev_err(&pdev->dev, "MSIX alloc failed\n");
+ goto err_alloc_msix;
+ }
+
+ err = register_netdev(ndev);
+ if (err)
+ goto err_reg_netdev;
+
+ netif_carrier_off(ndev);
+
+ netif_info(priv, probe, ndev, "%s v%s\n",
+ enetc_drv_name, enetc_drv_ver);
+
+ return 0;
+
+err_reg_netdev:
+ enetc_free_msix(priv);
+err_alloc_msix:
+ enetc_free_si_resources(priv);
+err_alloc_si_res:
+ si->ndev = NULL;
+ free_netdev(ndev);
+err_alloc_netdev:
+ enetc_pci_remove(pdev);
+
+ return err;
+}
+
+static void enetc_vf_remove(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+ struct enetc_ndev_priv *priv;
+
+ priv = netdev_priv(si->ndev);
+ netif_info(priv, drv, si->ndev, "%s v%s remove\n",
+ enetc_drv_name, enetc_drv_ver);
+ unregister_netdev(si->ndev);
+
+ enetc_free_msix(priv);
+
+ enetc_free_si_resources(priv);
+
+ free_netdev(si->ndev);
+
+ enetc_pci_remove(pdev);
+}
+
+static const struct pci_device_id enetc_vf_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc_vf_id_table);
+
+static struct pci_driver enetc_vf_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = enetc_vf_id_table,
+ .probe = enetc_vf_probe,
+ .remove = enetc_vf_remove,
+};
+module_pci_driver(enetc_vf_driver);
+
+MODULE_DESCRIPTION(ENETC_DRV_NAME_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(ENETC_DRV_VER_STR);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index ae0f88bce9aa..697c2427f2b7 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2098,6 +2098,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST)
+static __u32 fec_enet_register_version = 2;
static u32 fec_enet_register_offset[] = {
FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2128,6 +2129,7 @@ static u32 fec_enet_register_offset[] = {
IEEE_R_FDXFC, IEEE_R_OCTETS_OK
};
#else
+static __u32 fec_enet_register_version = 1;
static u32 fec_enet_register_offset[] = {
FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0,
FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0,
@@ -2149,6 +2151,8 @@ static void fec_enet_get_regs(struct net_device *ndev,
u32 *buf = (u32 *)regbuf;
u32 i, off;
+ regs->version = fec_enet_register_version;
+
memset(buf, 0, regs->len);
for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) {
@@ -3467,7 +3471,7 @@ fec_probe(struct platform_device *pdev)
if (ret)
goto failed_clk_ipg;
- fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
+ fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy");
if (!IS_ERR(fep->reg_phy)) {
ret = regulator_enable(fep->reg_phy);
if (ret) {
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index b90bab72efdb..c1968b3ecec8 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -369,7 +369,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len,
DMA_TO_DEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
spin_unlock(&priv->lock);
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 71f4205f14e7..3c21486c6c84 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -855,9 +855,7 @@ static int mac_probe(struct platform_device *_of_dev)
if (err < 0)
dev_err(dev, "fman_set_mac_active_pause() = %d\n", err);
- dev_info(dev, "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
- mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2],
- mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]);
+ dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
if (IS_ERR(priv->eth_dev)) {
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 241325c35cb4..27ed995f439a 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1492,7 +1492,7 @@ static int gfar_get_ts_info(struct net_device *dev,
struct gfar_private *priv = netdev_priv(dev);
struct platform_device *ptp_dev;
struct device_node *ptp_node;
- struct qoriq_ptp *ptp = NULL;
+ struct ptp_qoriq *ptp = NULL;
info->phc_index = -1;
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index c3d539e209ed..eb3e65e8868f 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -1879,6 +1879,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
u16 i, j;
u8 __iomem *bd;
+ netdev_reset_queue(ugeth->ndev);
+
ug_info = ugeth->ug_info;
uf_info = &ug_info->uf_info;
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index 471805ea363b..e5d853b7b454 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -1006,8 +1006,8 @@ static int hix5hd2_init_hw_desc_queue(struct hix5hd2_priv *priv)
for (i = 0; i < QUEUE_NUMS; i++) {
size = priv->pool[i].count * sizeof(struct hix5hd2_desc);
- virt_addr = dma_zalloc_coherent(dev, size, &phys_addr,
- GFP_KERNEL);
+ virt_addr = dma_alloc_coherent(dev, size, &phys_addr,
+ GFP_KERNEL);
if (virt_addr == NULL)
goto error_free_pool;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index ad1779fc410e..a78bfafd212c 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
int i;
- vf_cb->mac_cb = NULL;
-
- kfree(vf_cb);
-
for (i = 0; i < handle->q_num; i++)
hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
+
+ kfree(vf_cb);
}
static int hns_ae_wait_flow_down(struct hnae_handle *handle)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 3b9e74be5fbd..ac55db065f16 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -3081,6 +3081,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
dsaf_dev = dev_get_drvdata(&pdev->dev);
if (!dsaf_dev) {
dev_err(&pdev->dev, "dsaf_dev is NULL\n");
+ put_device(&pdev->dev);
return -ENODEV;
}
@@ -3088,6 +3089,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
dsaf_dev->ae_dev.name);
+ put_device(&pdev->dev);
return -ENODEV;
}
@@ -3126,6 +3128,9 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 1);
dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
}
+
+ put_device(&pdev->dev);
+
return 0;
}
EXPORT_SYMBOL(hns_dsaf_roce_reset);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
index 0942e4916d9d..3d07c8a7639d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -83,8 +83,9 @@ static int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index)
else
ppe_num = HNS_PPE_DEBUG_NW_ENGINE_NUM;
- ppe_common = devm_kzalloc(dsaf_dev->dev, sizeof(*ppe_common) +
- ppe_num * sizeof(struct hns_ppe_cb), GFP_KERNEL);
+ ppe_common = devm_kzalloc(dsaf_dev->dev,
+ struct_size(ppe_common, ppe_cb, ppe_num),
+ GFP_KERNEL);
if (!ppe_common)
return -ENOMEM;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index 5d64519b9b1d..6bf346c11b25 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -788,8 +788,9 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev,
int ring_num = hns_rcb_get_ring_num(dsaf_dev);
rcb_common =
- devm_kzalloc(dsaf_dev->dev, sizeof(*rcb_common) +
- ring_num * sizeof(struct ring_pair_cb), GFP_KERNEL);
+ devm_kzalloc(dsaf_dev->dev,
+ struct_size(rcb_common, ring_pair_cb, ring_num),
+ GFP_KERNEL);
if (!rcb_common) {
dev_err(dsaf_dev->dev, "rcb common devm_kzalloc fail!\n");
return -ENOMEM;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 5748d3f722f6..60e7d7ae3787 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1170,6 +1170,13 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
if (!h->phy_dev)
return 0;
+ ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
+ linkmode_and(phy_dev->supported, phy_dev->supported, supported);
+ linkmode_copy(phy_dev->advertising, phy_dev->supported);
+
+ if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
+ phy_dev->autoneg = false;
+
if (h->phy_if != PHY_INTERFACE_MODE_XGMII) {
phy_dev->dev_flags = 0;
@@ -1181,16 +1188,6 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
if (unlikely(ret))
return -ENODEV;
- ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
- linkmode_and(phy_dev->supported, phy_dev->supported, supported);
- linkmode_copy(phy_dev->advertising, phy_dev->supported);
-
- if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
- phy_dev->autoneg = false;
-
- if (h->phy_if == PHY_INTERFACE_MODE_SGMII)
- phy_stop(phy_dev);
-
return 0;
}
@@ -2421,6 +2418,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
out_notify_fail:
(void)cancel_work_sync(&priv->service_task);
out_read_prop_fail:
+ /* safe for ACPI FW */
+ of_node_put(to_of_node(priv->fwnode));
free_netdev(ndev);
return ret;
}
@@ -2450,6 +2449,9 @@ static int hns_nic_dev_remove(struct platform_device *pdev)
set_bit(NIC_STATE_REMOVING, &priv->state);
(void)cancel_work_sync(&priv->service_task);
+ /* safe for ACPI FW */
+ of_node_put(to_of_node(priv->fwnode));
+
free_netdev(ndev);
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 8e9b95871d30..ce15d2350db9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -1157,16 +1157,18 @@ static int hns_get_regs_len(struct net_device *net_dev)
*/
static int hns_nic_nway_reset(struct net_device *netdev)
{
- int ret = 0;
struct phy_device *phy = netdev->phydev;
- if (netif_running(netdev)) {
- /* if autoneg is disabled, don't restart auto-negotiation */
- if (phy && phy->autoneg == AUTONEG_ENABLE)
- ret = genphy_restart_aneg(phy);
- }
+ if (!netif_running(netdev))
+ return 0;
- return ret;
+ if (!phy)
+ return -EOPNOTSUPP;
+
+ if (phy->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ return genphy_restart_aneg(phy);
}
static u32
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
index 691d12174902..299b277bc7ae 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
@@ -21,6 +21,7 @@ enum HCLGE_MBX_OPCODE {
HCLGE_MBX_SET_MACVLAN, /* (VF -> PF) set unicast filter */
HCLGE_MBX_API_NEGOTIATE, /* (VF -> PF) negotiate API version */
HCLGE_MBX_GET_QINFO, /* (VF -> PF) get queue config */
+ HCLGE_MBX_GET_QDEPTH, /* (VF -> PF) get queue depth */
HCLGE_MBX_GET_TCINFO, /* (VF -> PF) get TC config */
HCLGE_MBX_GET_RETA, /* (VF -> PF) get RETA */
HCLGE_MBX_GET_RSS_KEY, /* (VF -> PF) get RSS key */
@@ -40,6 +41,10 @@ enum HCLGE_MBX_OPCODE {
HCLGE_MBX_SET_ALIVE, /* (VF -> PF) set alive state */
HCLGE_MBX_SET_MTU, /* (VF -> PF) set mtu */
HCLGE_MBX_GET_QID_IN_PF, /* (VF -> PF) get queue id in pf */
+ HCLGE_MBX_LINK_STAT_MODE, /* (PF -> VF) link mode has changed */
+ HCLGE_MBX_GET_LINK_MODE, /* (VF -> PF) get the link mode of pf */
+
+ HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
};
/* below are per-VF mac-vlan subcodes */
@@ -60,7 +65,7 @@ enum hclge_mbx_vlan_cfg_subcode {
};
#define HCLGE_MBX_MAX_MSG_SIZE 16
-#define HCLGE_MBX_MAX_RESP_DATA_SIZE 8
+#define HCLGE_MBX_MAX_RESP_DATA_SIZE 16
#define HCLGE_MBX_RING_MAP_BASIC_MSG_NUM 3
#define HCLGE_MBX_RING_NODE_VARIABLE_NUM 3
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
index 781e5dee3c70..17ab4f4af6ad 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
@@ -32,6 +32,9 @@ static bool hnae3_client_match(enum hnae3_client_type client_type,
void hnae3_set_client_init_flag(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev, int inited)
{
+ if (!client || !ae_dev)
+ return;
+
switch (client->type) {
case HNAE3_CLIENT_KNIC:
hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
@@ -109,6 +112,9 @@ int hnae3_register_client(struct hnae3_client *client)
struct hnae3_ae_dev *ae_dev;
int ret = 0;
+ if (!client)
+ return -ENODEV;
+
mutex_lock(&hnae3_common_lock);
/* one system should only have one client for every type */
list_for_each_entry(client_tmp, &hnae3_client_list, node) {
@@ -141,6 +147,9 @@ void hnae3_unregister_client(struct hnae3_client *client)
{
struct hnae3_ae_dev *ae_dev;
+ if (!client)
+ return;
+
mutex_lock(&hnae3_common_lock);
/* un-initialize the client on every matched port */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
@@ -163,6 +172,9 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
struct hnae3_client *client;
int ret = 0;
+ if (!ae_algo)
+ return;
+
mutex_lock(&hnae3_common_lock);
list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
@@ -173,8 +185,12 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
if (!id)
continue;
- /* ae_dev init should set flag */
+ if (!ae_algo->ops) {
+ dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
+ continue;
+ }
ae_dev->ops = ae_algo->ops;
+
ret = ae_algo->ops->init_ae_dev(ae_dev);
if (ret) {
dev_err(&ae_dev->pdev->dev,
@@ -182,6 +198,7 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
continue;
}
+ /* ae_dev init should set flag */
hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
/* check the client list for the match with this ae_dev type and
@@ -209,6 +226,9 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
struct hnae3_ae_dev *ae_dev;
struct hnae3_client *client;
+ if (!ae_algo)
+ return;
+
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_dev */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
@@ -238,13 +258,16 @@ EXPORT_SYMBOL(hnae3_unregister_ae_algo);
* @ae_dev: the AE device
* NOTE: the duplicated name will not be checked
*/
-void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
+int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
{
const struct pci_device_id *id;
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
int ret = 0;
+ if (!ae_dev)
+ return -ENODEV;
+
mutex_lock(&hnae3_common_lock);
list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
@@ -255,14 +278,13 @@ void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
if (!id)
continue;
- ae_dev->ops = ae_algo->ops;
-
- if (!ae_dev->ops) {
- dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
+ if (!ae_algo->ops) {
+ dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
+ ret = -EOPNOTSUPP;
goto out_err;
}
+ ae_dev->ops = ae_algo->ops;
- /* ae_dev init should set flag */
ret = ae_dev->ops->init_ae_dev(ae_dev);
if (ret) {
dev_err(&ae_dev->pdev->dev,
@@ -270,6 +292,7 @@ void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
goto out_err;
}
+ /* ae_dev init should set flag */
hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
break;
}
@@ -285,8 +308,15 @@ void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
ret);
}
+ mutex_unlock(&hnae3_common_lock);
+
+ return 0;
+
out_err:
+ list_del(&ae_dev->node);
mutex_unlock(&hnae3_common_lock);
+
+ return ret;
}
EXPORT_SYMBOL(hnae3_register_ae_dev);
@@ -299,6 +329,9 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
+ if (!ae_dev)
+ return;
+
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_algo */
list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 36eab37d8a40..66d7a8b80e76 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -87,7 +87,8 @@ struct hnae3_queue {
struct hnae3_handle *handle;
int tqp_index; /* index in a handle */
u32 buf_size; /* size for hnae_desc->addr, preset by AE */
- u16 desc_num; /* total number of desc */
+ u16 tx_desc_num;/* total number of tx desc */
+ u16 rx_desc_num;/* total number of rx desc */
};
/*hnae3 loop mode*/
@@ -124,6 +125,7 @@ enum hnae3_reset_notify_type {
HNAE3_DOWN_CLIENT,
HNAE3_INIT_CLIENT,
HNAE3_UNINIT_CLIENT,
+ HNAE3_RESTORE_CLIENT,
};
enum hnae3_reset_type {
@@ -432,7 +434,8 @@ struct hnae3_ae_ops {
struct ethtool_channels *ch);
void (*get_tqps_and_rss_info)(struct hnae3_handle *h,
u16 *alloc_tqps, u16 *max_rss_size);
- int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num);
+ int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num,
+ bool rxfh_configured);
void (*get_flowctrl_adv)(struct hnae3_handle *handle,
u32 *flowctrl_adv);
int (*set_led_id)(struct hnae3_handle *handle,
@@ -459,9 +462,11 @@ struct hnae3_ae_ops {
bool (*get_hw_reset_stat)(struct hnae3_handle *handle);
bool (*ae_dev_resetting)(struct hnae3_handle *handle);
unsigned long (*ae_dev_reset_cnt)(struct hnae3_handle *handle);
- int (*set_gro_en)(struct hnae3_handle *handle, int enable);
+ int (*set_gro_en)(struct hnae3_handle *handle, bool enable);
u16 (*get_global_queue_id)(struct hnae3_handle *handle, u16 queue_id);
void (*set_timer_task)(struct hnae3_handle *handle, bool enable);
+ int (*mac_connect_phy)(struct hnae3_handle *handle);
+ void (*mac_disconnect_phy)(struct hnae3_handle *handle);
};
struct hnae3_dcb_ops {
@@ -475,7 +480,6 @@ struct hnae3_dcb_ops {
u8 (*getdcbx)(struct hnae3_handle *);
u8 (*setdcbx)(struct hnae3_handle *, u8);
- int (*map_update)(struct hnae3_handle *);
int (*setup_tc)(struct hnae3_handle *, u8, u8 *);
};
@@ -500,8 +504,10 @@ struct hnae3_tc_info {
struct hnae3_knic_private_info {
struct net_device *netdev; /* Set by KNIC client when init instance */
u16 rss_size; /* Allocated RSS queues */
+ u16 req_rss_size;
u16 rx_buf_len;
- u16 num_desc;
+ u16 num_tx_desc;
+ u16 num_rx_desc;
u8 num_tc; /* Total number of enabled TCs */
u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */
@@ -533,7 +539,9 @@ struct hnae3_roce_private_info {
struct hnae3_unic_private_info {
struct net_device *netdev;
u16 rx_buf_len;
- u16 num_desc;
+ u16 num_tx_desc;
+ u16 num_rx_desc;
+
u16 num_tqps; /* total number of tqps in this handle */
struct hnae3_queue **tqp; /* array base of all TQPs of this instance */
};
@@ -585,7 +593,7 @@ struct hnae3_handle {
#define hnae3_get_bit(origin, shift) \
hnae3_get_field((origin), (0x1 << (shift)), (shift))
-void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
+int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 07cd58798083..3cb43b1f1c2e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -21,6 +21,8 @@
#include "hnae3.h"
#include "hns3_enet.h"
+#define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift)))
+
static void hns3_clear_all_ring(struct hnae3_handle *h);
static void hns3_force_clear_all_rx_ring(struct hnae3_handle *h);
static void hns3_remove_hw_addr(struct net_device *netdev);
@@ -348,6 +350,8 @@ static int hns3_nic_net_up(struct net_device *netdev)
return ret;
}
+ clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
+
/* enable the vectors */
for (i = 0; i < priv->vector_num; i++)
hns3_vector_enable(&priv->tqp_vector[i]);
@@ -361,11 +365,10 @@ static int hns3_nic_net_up(struct net_device *netdev)
if (ret)
goto out_start_err;
- clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
-
return 0;
out_start_err:
+ set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
while (j--)
hns3_tqp_disable(h->kinfo.tqp[j]);
@@ -377,6 +380,29 @@ out_start_err:
return ret;
}
+static void hns3_config_xps(struct hns3_nic_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->vector_num; i++) {
+ struct hns3_enet_tqp_vector *tqp_vector = &priv->tqp_vector[i];
+ struct hns3_enet_ring *ring = tqp_vector->tx_group.ring;
+
+ while (ring) {
+ int ret;
+
+ ret = netif_set_xps_queue(priv->netdev,
+ &tqp_vector->affinity_mask,
+ ring->tqp->tqp_index);
+ if (ret)
+ netdev_warn(priv->netdev,
+ "set xps queue failed: %d", ret);
+
+ ring = ring->next;
+ }
+ }
+}
+
static int hns3_nic_net_open(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -409,6 +435,7 @@ static int hns3_nic_net_open(struct net_device *netdev)
if (h->ae_algo->ops->set_timer_task)
h->ae_algo->ops->set_timer_task(priv->ae_handle, true);
+ hns3_config_xps(priv);
return 0;
}
@@ -506,7 +533,7 @@ static u8 hns3_get_netdev_flags(struct net_device *netdev)
u8 flags = 0;
if (netdev->flags & IFF_PROMISC) {
- flags = HNAE3_USER_UPE | HNAE3_USER_MPE;
+ flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE;
} else {
flags |= HNAE3_VLAN_FLTR;
if (netdev->flags & IFF_ALLMULTI)
@@ -541,13 +568,13 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev)
}
}
- hns3_update_promisc_mode(netdev, new_flags);
/* User mode Promisc mode enable and vlan filtering is disabled to
* let all packets in. MAC-VLAN Table overflow Promisc enabled and
* vlan fitering is enabled
*/
hns3_enable_vlan_filter(netdev, new_flags & HNAE3_VLAN_FLTR);
h->netdev_flags = new_flags;
+ hns3_update_promisc_mode(netdev, new_flags);
}
int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
@@ -594,7 +621,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
return 0;
ret = skb_cow_head(skb, 0);
- if (ret)
+ if (unlikely(ret))
return ret;
l3.hdr = skb_network_header(skb);
@@ -633,7 +660,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
/* normal or tunnel packet*/
l4_offset = l4.hdr - skb->data;
- hdr_len = (l4.tcp->doff * 4) + l4_offset;
+ hdr_len = (l4.tcp->doff << 2) + l4_offset;
/* remove payload length from inner pseudo checksum when tso*/
l4_paylen = skb->len - l4_offset;
@@ -642,8 +669,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
/* find the txbd field values */
*paylen = skb->len - hdr_len;
- hnae3_set_bit(*type_cs_vlan_tso,
- HNS3_TXD_TSO_B, 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_TSO_B, 1);
/* get MSS for TSO */
*mss = skb_shinfo(skb)->gso_size;
@@ -654,11 +680,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto,
u8 *il4_proto)
{
- union {
- struct iphdr *v4;
- struct ipv6hdr *v6;
- unsigned char *hdr;
- } l3;
+ union l3_hdr_info l3;
unsigned char *l4_hdr;
unsigned char *exthdr;
u8 l4_proto_tmp;
@@ -711,17 +733,8 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
u8 il4_proto, u32 *type_cs_vlan_tso,
u32 *ol_type_vlan_len_msec)
{
- union {
- struct iphdr *v4;
- struct ipv6hdr *v6;
- unsigned char *hdr;
- } l3;
- union {
- struct tcphdr *tcp;
- struct udphdr *udp;
- struct gre_base_hdr *gre;
- unsigned char *hdr;
- } l4;
+ union l3_hdr_info l3;
+ union l4_hdr_info l4;
unsigned char *l2_hdr;
u8 l4_proto = ol4_proto;
u32 ol2_len;
@@ -735,21 +748,19 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
/* compute L2 header size for normal packet, defined in 2 Bytes */
l2_len = l3.hdr - skb->data;
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_M,
- HNS3_TXD_L2LEN_S, l2_len >> 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S, l2_len >> 1);
/* tunnel packet*/
if (skb->encapsulation) {
/* compute OL2 header size, defined in 2 Bytes */
ol2_len = l2_len;
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_L2LEN_M,
- HNS3_TXD_L2LEN_S, ol2_len >> 1);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_L2LEN_S, ol2_len >> 1);
/* compute OL3 header size, defined in 4 Bytes */
ol3_len = l4.hdr - l3.hdr;
- hnae3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_M,
- HNS3_TXD_L3LEN_S, ol3_len >> 2);
+ hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_S,
+ ol3_len >> 2);
/* MAC in UDP, MAC in GRE (0x6558)*/
if ((ol4_proto == IPPROTO_UDP) || (ol4_proto == IPPROTO_GRE)) {
@@ -758,17 +769,16 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
/* compute OL4 header size, defined in 4 Bytes. */
ol4_len = l2_hdr - l4.hdr;
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
- ol4_len >> 2);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_L4LEN_S, ol4_len >> 2);
/* switch IP header ptr from outer to inner header */
l3.hdr = skb_inner_network_header(skb);
/* compute inner l2 header size, defined in 2 Bytes. */
l2_len = l3.hdr - l2_hdr;
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_M,
- HNS3_TXD_L2LEN_S, l2_len >> 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S,
+ l2_len >> 1);
} else {
/* skb packet types not supported by hardware,
* txbd len fild doesn't be filled.
@@ -784,24 +794,21 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
/* compute inner(/normal) L3 header size, defined in 4 Bytes */
l3_len = l4.hdr - l3.hdr;
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_M,
- HNS3_TXD_L3LEN_S, l3_len >> 2);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_S, l3_len >> 2);
/* compute inner(/normal) L4 header size, defined in 4 Bytes */
switch (l4_proto) {
case IPPROTO_TCP:
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M,
- HNS3_TXD_L4LEN_S, l4.tcp->doff);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
+ l4.tcp->doff);
break;
case IPPROTO_SCTP:
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M,
- HNS3_TXD_L4LEN_S,
- (sizeof(struct sctphdr) >> 2));
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
+ (sizeof(struct sctphdr) >> 2));
break;
case IPPROTO_UDP:
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M,
- HNS3_TXD_L4LEN_S,
- (sizeof(struct udphdr) >> 2));
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
+ (sizeof(struct udphdr) >> 2));
break;
default:
/* skb packet types not supported by hardware,
@@ -820,12 +827,7 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
{
#define IANA_VXLAN_PORT 4789
- union {
- struct tcphdr *tcp;
- struct udphdr *udp;
- struct gre_base_hdr *gre;
- unsigned char *hdr;
- } l4;
+ union l4_hdr_info l4;
l4.hdr = skb_transport_header(skb);
@@ -841,11 +843,7 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
u8 il4_proto, u32 *type_cs_vlan_tso,
u32 *ol_type_vlan_len_msec)
{
- union {
- struct iphdr *v4;
- struct ipv6hdr *v6;
- unsigned char *hdr;
- } l3;
+ union l3_hdr_info l3;
u32 l4_proto = ol4_proto;
l3.hdr = skb_network_header(skb);
@@ -855,34 +853,30 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
/* define outer network header type.*/
if (skb->protocol == htons(ETH_P_IP)) {
if (skb_is_gso(skb))
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_OL3T_M,
- HNS3_TXD_OL3T_S,
- HNS3_OL3T_IPV4_CSUM);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_OL3T_S,
+ HNS3_OL3T_IPV4_CSUM);
else
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_OL3T_M,
- HNS3_TXD_OL3T_S,
- HNS3_OL3T_IPV4_NO_CSUM);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_OL3T_S,
+ HNS3_OL3T_IPV4_NO_CSUM);
} else if (skb->protocol == htons(ETH_P_IPV6)) {
- hnae3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_M,
- HNS3_TXD_OL3T_S, HNS3_OL3T_IPV6);
+ hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S,
+ HNS3_OL3T_IPV6);
}
/* define tunnel type(OL4).*/
switch (l4_proto) {
case IPPROTO_UDP:
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_TUNTYPE_M,
- HNS3_TXD_TUNTYPE_S,
- HNS3_TUN_MAC_IN_UDP);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_TUNTYPE_S,
+ HNS3_TUN_MAC_IN_UDP);
break;
case IPPROTO_GRE:
- hnae3_set_field(*ol_type_vlan_len_msec,
- HNS3_TXD_TUNTYPE_M,
- HNS3_TXD_TUNTYPE_S,
- HNS3_TUN_NVGRE);
+ hns3_set_field(*ol_type_vlan_len_msec,
+ HNS3_TXD_TUNTYPE_S,
+ HNS3_TUN_NVGRE);
break;
default:
/* drop the skb tunnel packet if hardware don't support,
@@ -903,43 +897,37 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
}
if (l3.v4->version == 4) {
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_M,
- HNS3_TXD_L3T_S, HNS3_L3T_IPV4);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
+ HNS3_L3T_IPV4);
/* the stack computes the IP header already, the only time we
* need the hardware to recompute it is in the case of TSO.
*/
if (skb_is_gso(skb))
- hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1);
} else if (l3.v6->version == 6) {
- hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_M,
- HNS3_TXD_L3T_S, HNS3_L3T_IPV6);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
+ HNS3_L3T_IPV6);
}
switch (l4_proto) {
case IPPROTO_TCP:
- hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
- hnae3_set_field(*type_cs_vlan_tso,
- HNS3_TXD_L4T_M,
- HNS3_TXD_L4T_S,
- HNS3_L4T_TCP);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
+ HNS3_L4T_TCP);
break;
case IPPROTO_UDP:
if (hns3_tunnel_csum_bug(skb))
break;
- hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
- hnae3_set_field(*type_cs_vlan_tso,
- HNS3_TXD_L4T_M,
- HNS3_TXD_L4T_S,
- HNS3_L4T_UDP);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
+ HNS3_L4T_UDP);
break;
case IPPROTO_SCTP:
- hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
- hnae3_set_field(*type_cs_vlan_tso,
- HNS3_TXD_L4T_M,
- HNS3_TXD_L4T_S,
- HNS3_L4T_SCTP);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
+ hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
+ HNS3_L4T_SCTP);
break;
default:
/* drop the skb tunnel packet if hardware don't support,
@@ -961,11 +949,8 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end)
{
/* Config bd buffer end */
- hnae3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_BDTYPE_M,
- HNS3_TXD_BDTYPE_S, 0);
- hnae3_set_bit(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, !!frag_end);
- hnae3_set_bit(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1);
- hnae3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_SC_M, HNS3_TXD_SC_S, 0);
+ hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, !!frag_end);
+ hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1);
}
static int hns3_fill_desc_vtags(struct sk_buff *skb,
@@ -998,10 +983,10 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb,
* and use inner_vtag in one tag case.
*/
if (skb->protocol == htons(ETH_P_8021Q)) {
- hnae3_set_bit(*out_vlan_flag, HNS3_TXD_OVLAN_B, 1);
+ hns3_set_field(*out_vlan_flag, HNS3_TXD_OVLAN_B, 1);
*out_vtag = vlan_tag;
} else {
- hnae3_set_bit(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1);
+ hns3_set_field(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1);
*inner_vtag = vlan_tag;
}
} else if (skb->protocol == htons(ETH_P_8021Q)) {
@@ -1009,7 +994,7 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb,
int rc;
rc = skb_cow_head(skb, 0);
- if (rc < 0)
+ if (unlikely(rc < 0))
return rc;
vhdr = (struct vlan_ethhdr *)skb->data;
vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority & 0x7)
@@ -1026,26 +1011,21 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
struct hns3_desc *desc = &ring->desc[ring->next_to_use];
struct device *dev = ring_to_dev(ring);
- u32 ol_type_vlan_len_msec = 0;
u16 bdtp_fe_sc_vld_ra_ri = 0;
struct skb_frag_struct *frag;
unsigned int frag_buf_num;
- u32 type_cs_vlan_tso = 0;
- struct sk_buff *skb;
- u16 inner_vtag = 0;
- u16 out_vtag = 0;
- unsigned int k;
- int sizeoflast;
- u32 paylen = 0;
+ int k, sizeoflast;
dma_addr_t dma;
- u16 mss = 0;
- u8 ol4_proto;
- u8 il4_proto;
- int ret;
if (type == DESC_TYPE_SKB) {
- skb = (struct sk_buff *)priv;
- paylen = skb->len;
+ struct sk_buff *skb = (struct sk_buff *)priv;
+ u32 ol_type_vlan_len_msec = 0;
+ u32 type_cs_vlan_tso = 0;
+ u32 paylen = skb->len;
+ u16 inner_vtag = 0;
+ u16 out_vtag = 0;
+ u16 mss = 0;
+ int ret;
ret = hns3_fill_desc_vtags(skb, ring, &type_cs_vlan_tso,
&ol_type_vlan_len_msec,
@@ -1054,10 +1034,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
return ret;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 ol4_proto, il4_proto;
+
skb_reset_mac_len(skb);
ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto);
- if (ret)
+ if (unlikely(ret))
return ret;
hns3_set_l2l3l4_len(skb, ol4_proto, il4_proto,
&type_cs_vlan_tso,
@@ -1065,12 +1047,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
ret = hns3_set_l3l4_type_csum(skb, ol4_proto, il4_proto,
&type_cs_vlan_tso,
&ol_type_vlan_len_msec);
- if (ret)
+ if (unlikely(ret))
return ret;
ret = hns3_set_tso(skb, &paylen, &mss,
&type_cs_vlan_tso);
- if (ret)
+ if (unlikely(ret))
return ret;
}
@@ -1090,15 +1072,15 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
}
- if (dma_mapping_error(ring->dev, dma)) {
+ if (unlikely(dma_mapping_error(ring->dev, dma))) {
ring->stats.sw_err_cnt++;
return -ENOMEM;
}
desc_cb->length = size;
- frag_buf_num = (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE;
- sizeoflast = size % HNS3_MAX_BD_SIZE;
+ frag_buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET;
+ sizeoflast = size & HNS3_TX_LAST_SIZE_M;
sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE;
/* When frag size is bigger than hardware limit, split this frag */
@@ -1133,6 +1115,7 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum,
struct hns3_enet_ring *ring)
{
struct sk_buff *skb = *out_skb;
+ struct sk_buff *new_skb = NULL;
struct skb_frag_struct *frag;
int bdnum_for_frag;
int frag_num;
@@ -1141,21 +1124,34 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum,
int i;
size = skb_headlen(skb);
- buf_num = (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE;
+ buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET;
frag_num = skb_shinfo(skb)->nr_frags;
for (i = 0; i < frag_num; i++) {
frag = &skb_shinfo(skb)->frags[i];
size = skb_frag_size(frag);
- bdnum_for_frag =
- (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE;
- if (bdnum_for_frag > HNS3_MAX_BD_PER_FRAG)
+ bdnum_for_frag = (size + HNS3_MAX_BD_SIZE - 1) >>
+ HNS3_MAX_BD_SIZE_OFFSET;
+ if (unlikely(bdnum_for_frag > HNS3_MAX_BD_PER_FRAG))
return -ENOMEM;
buf_num += bdnum_for_frag;
}
- if (buf_num > ring_space(ring))
+ if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) {
+ buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) >>
+ HNS3_MAX_BD_SIZE_OFFSET;
+ if (ring_space(ring) < buf_num)
+ return -EBUSY;
+ /* manual split the send packet */
+ new_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!new_skb)
+ return -ENOMEM;
+ dev_kfree_skb_any(skb);
+ *out_skb = new_skb;
+ }
+
+ if (unlikely(ring_space(ring) < buf_num))
return -EBUSY;
*bnum = buf_num;
@@ -1166,11 +1162,24 @@ static int hns3_nic_maybe_stop_tx(struct sk_buff **out_skb, int *bnum,
struct hns3_enet_ring *ring)
{
struct sk_buff *skb = *out_skb;
+ struct sk_buff *new_skb = NULL;
int buf_num;
/* No. of segments (plus a header) */
buf_num = skb_shinfo(skb)->nr_frags + 1;
+ if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) {
+ buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE;
+ if (ring_space(ring) < buf_num)
+ return -EBUSY;
+ /* manual split the send packet */
+ new_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!new_skb)
+ return -ENOMEM;
+ dev_kfree_skb_any(skb);
+ *out_skb = new_skb;
+ }
+
if (unlikely(ring_space(ring) < buf_num))
return -EBUSY;
@@ -1252,9 +1261,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
next_to_use_head = ring->next_to_use;
- ret = priv->ops.fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0,
- DESC_TYPE_SKB);
- if (ret)
+ ret = hns3_fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0,
+ DESC_TYPE_SKB);
+ if (unlikely(ret))
goto head_fill_err;
next_to_use_frag = ring->next_to_use;
@@ -1263,11 +1272,11 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
frag = &skb_shinfo(skb)->frags[i - 1];
size = skb_frag_size(frag);
- ret = priv->ops.fill_desc(ring, frag, size,
- seg_num - 1 == i ? 1 : 0,
- DESC_TYPE_PAGE);
+ ret = hns3_fill_desc(ring, frag, size,
+ seg_num - 1 == i ? 1 : 0,
+ DESC_TYPE_PAGE);
- if (ret)
+ if (unlikely(ret))
goto frag_fill_err;
}
@@ -1344,6 +1353,7 @@ static int hns3_nic_set_features(struct net_device *netdev,
netdev_features_t changed = netdev->features ^ features;
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
+ bool enable;
int ret;
if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) {
@@ -1354,38 +1364,29 @@ static int hns3_nic_set_features(struct net_device *netdev,
}
if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) {
- if (features & NETIF_F_GRO_HW)
- ret = h->ae_algo->ops->set_gro_en(h, true);
- else
- ret = h->ae_algo->ops->set_gro_en(h, false);
+ enable = !!(features & NETIF_F_GRO_HW);
+ ret = h->ae_algo->ops->set_gro_en(h, enable);
if (ret)
return ret;
}
if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) &&
h->ae_algo->ops->enable_vlan_filter) {
- if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
- h->ae_algo->ops->enable_vlan_filter(h, true);
- else
- h->ae_algo->ops->enable_vlan_filter(h, false);
+ enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+ h->ae_algo->ops->enable_vlan_filter(h, enable);
}
if ((changed & NETIF_F_HW_VLAN_CTAG_RX) &&
h->ae_algo->ops->enable_hw_strip_rxvtag) {
- if (features & NETIF_F_HW_VLAN_CTAG_RX)
- ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, true);
- else
- ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, false);
-
+ enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
+ ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable);
if (ret)
return ret;
}
if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) {
- if (features & NETIF_F_NTUPLE)
- h->ae_algo->ops->enable_fd(h, true);
- else
- h->ae_algo->ops->enable_fd(h, false);
+ enable = !!(features & NETIF_F_NTUPLE);
+ h->ae_algo->ops->enable_fd(h, enable);
}
netdev->features = features;
@@ -1399,7 +1400,12 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
int queue_num = priv->ae_handle->kinfo.num_tqps;
struct hnae3_handle *handle = priv->ae_handle;
struct hns3_enet_ring *ring;
+ u64 rx_length_errors = 0;
+ u64 rx_crc_errors = 0;
+ u64 rx_multicast = 0;
unsigned int start;
+ u64 tx_errors = 0;
+ u64 rx_errors = 0;
unsigned int idx;
u64 tx_bytes = 0;
u64 rx_bytes = 0;
@@ -1420,8 +1426,8 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
start = u64_stats_fetch_begin_irq(&ring->syncp);
tx_bytes += ring->stats.tx_bytes;
tx_pkts += ring->stats.tx_pkts;
- tx_drop += ring->stats.tx_busy;
tx_drop += ring->stats.sw_err_cnt;
+ tx_errors += ring->stats.sw_err_cnt;
} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
/* fetch the rx stats */
@@ -1431,8 +1437,13 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
rx_bytes += ring->stats.rx_bytes;
rx_pkts += ring->stats.rx_pkts;
rx_drop += ring->stats.non_vld_descs;
- rx_drop += ring->stats.err_pkt_len;
rx_drop += ring->stats.l2_err;
+ rx_errors += ring->stats.non_vld_descs;
+ rx_errors += ring->stats.l2_err;
+ rx_crc_errors += ring->stats.l2_err;
+ rx_crc_errors += ring->stats.l3l4_csum_err;
+ rx_multicast += ring->stats.rx_multicast;
+ rx_length_errors += ring->stats.err_pkt_len;
} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
}
@@ -1441,15 +1452,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
stats->rx_bytes = rx_bytes;
stats->rx_packets = rx_pkts;
- stats->rx_errors = netdev->stats.rx_errors;
- stats->multicast = netdev->stats.multicast;
- stats->rx_length_errors = netdev->stats.rx_length_errors;
- stats->rx_crc_errors = netdev->stats.rx_crc_errors;
+ stats->rx_errors = rx_errors;
+ stats->multicast = rx_multicast;
+ stats->rx_length_errors = rx_length_errors;
+ stats->rx_crc_errors = rx_crc_errors;
stats->rx_missed_errors = netdev->stats.rx_missed_errors;
- stats->tx_errors = netdev->stats.tx_errors;
- stats->rx_dropped = rx_drop + netdev->stats.rx_dropped;
- stats->tx_dropped = tx_drop + netdev->stats.tx_dropped;
+ stats->tx_errors = tx_errors;
+ stats->rx_dropped = rx_drop;
+ stats->tx_dropped = tx_drop;
stats->collisions = netdev->stats.collisions;
stats->rx_over_errors = netdev->stats.rx_over_errors;
stats->rx_frame_errors = netdev->stats.rx_frame_errors;
@@ -1472,8 +1483,6 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data)
u8 tc = mqprio_qopt->qopt.num_tc;
u16 mode = mqprio_qopt->mode;
u8 hw = mqprio_qopt->qopt.hw;
- bool if_running;
- int ret;
if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS &&
mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0)))
@@ -1485,24 +1494,8 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data)
if (!netdev)
return -EINVAL;
- if_running = netif_running(netdev);
- if (if_running) {
- hns3_nic_net_stop(netdev);
- msleep(100);
- }
-
- ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
+ return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
- if (ret)
- goto out;
-
- ret = hns3_nic_set_real_num_queue(netdev);
-
-out:
- if (if_running)
- hns3_nic_net_open(netdev);
-
- return ret;
}
static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -1755,9 +1748,13 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hns3_get_dev_capability(pdev, ae_dev);
pci_set_drvdata(pdev, ae_dev);
- hnae3_register_ae_dev(ae_dev);
+ ret = hnae3_register_ae_dev(ae_dev);
+ if (ret) {
+ devm_kfree(&pdev->dev, ae_dev);
+ pci_set_drvdata(pdev, NULL);
+ }
- return 0;
+ return ret;
}
/* hns3_remove - Device removal routine
@@ -1771,6 +1768,7 @@ static void hns3_remove(struct pci_dev *pdev)
hns3_disable_sriov(pdev);
hnae3_unregister_ae_dev(ae_dev);
+ pci_set_drvdata(pdev, NULL);
}
/**
@@ -1935,8 +1933,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
if (pdev->revision >= 0x21) {
- netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER |
- NETIF_F_GRO_HW;
+ netdev->hw_features |= NETIF_F_GRO_HW;
netdev->features |= NETIF_F_GRO_HW;
if (!(h->flags & HNAE3_SUPPORT_VF)) {
@@ -2041,9 +2038,8 @@ static int hns3_alloc_desc(struct hns3_enet_ring *ring)
{
int size = ring->desc_num * sizeof(ring->desc[0]);
- ring->desc = dma_zalloc_coherent(ring_to_dev(ring), size,
- &ring->desc_dma_addr,
- GFP_KERNEL);
+ ring->desc = dma_alloc_coherent(ring_to_dev(ring), size,
+ &ring->desc_dma_addr, GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
@@ -2322,13 +2318,12 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
}
/* check if hardware has done checksum */
- if (!hnae3_get_bit(bd_base_info, HNS3_RXD_L3L4P_B))
+ if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B)))
return;
- if (unlikely(hnae3_get_bit(l234info, HNS3_RXD_L3E_B) ||
- hnae3_get_bit(l234info, HNS3_RXD_L4E_B) ||
- hnae3_get_bit(l234info, HNS3_RXD_OL3E_B) ||
- hnae3_get_bit(l234info, HNS3_RXD_OL4E_B))) {
+ if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) ||
+ BIT(HNS3_RXD_OL3E_B) ||
+ BIT(HNS3_RXD_OL4E_B)))) {
u64_stats_update_begin(&ring->syncp);
ring->stats.l3l4_csum_err++;
u64_stats_update_end(&ring->syncp);
@@ -2336,11 +2331,6 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
return;
}
- l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
- HNS3_RXD_L3ID_S);
- l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M,
- HNS3_RXD_L4ID_S);
-
ol4_type = hnae3_get_field(l234info, HNS3_RXD_OL4ID_M,
HNS3_RXD_OL4ID_S);
switch (ol4_type) {
@@ -2349,6 +2339,11 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
skb->csum_level = 1;
/* fall through */
case HNS3_OL4_TYPE_NO_TUN:
+ l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
+ HNS3_RXD_L3ID_S);
+ l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M,
+ HNS3_RXD_L4ID_S);
+
/* Can checksum ipv4 or ipv6 + UDP/TCP/SCTP packets */
if ((l3_type == HNS3_L3_TYPE_IPV4 ||
l3_type == HNS3_L3_TYPE_IPV6) &&
@@ -2473,11 +2468,11 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc,
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
}
- while (!hnae3_get_bit(bd_base_info, HNS3_RXD_FE_B)) {
+ while (!(bd_base_info & BIT(HNS3_RXD_FE_B))) {
desc = &ring->desc[ring->next_to_clean];
desc_cb = &ring->desc_cb[ring->next_to_clean];
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
- if (!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))
+ if (!(bd_base_info & BIT(HNS3_RXD_VLD_B)))
return -ENXIO;
if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) {
@@ -2573,6 +2568,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
struct sk_buff **out_skb)
{
struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
+ enum hns3_pkt_l2t_type l2_frame_type;
struct sk_buff *skb = ring->skb;
struct hns3_desc_cb *desc_cb;
struct hns3_desc *desc;
@@ -2590,7 +2586,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
/* Check valid BD */
- if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B)))
+ if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B))))
return -ENXIO;
if (!skb)
@@ -2653,7 +2649,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
vlan_tag);
}
- if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))) {
+ if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B)))) {
u64_stats_update_begin(&ring->syncp);
ring->stats.non_vld_descs++;
u64_stats_update_end(&ring->syncp);
@@ -2663,25 +2659,26 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
}
if (unlikely((!desc->rx.pkt_len) ||
- hnae3_get_bit(l234info, HNS3_RXD_TRUNCAT_B))) {
+ (l234info & (BIT(HNS3_RXD_TRUNCAT_B) |
+ BIT(HNS3_RXD_L2E_B))))) {
u64_stats_update_begin(&ring->syncp);
- ring->stats.err_pkt_len++;
+ if (l234info & BIT(HNS3_RXD_L2E_B))
+ ring->stats.l2_err++;
+ else
+ ring->stats.err_pkt_len++;
u64_stats_update_end(&ring->syncp);
dev_kfree_skb_any(skb);
return -EFAULT;
}
- if (unlikely(hnae3_get_bit(l234info, HNS3_RXD_L2E_B))) {
- u64_stats_update_begin(&ring->syncp);
- ring->stats.l2_err++;
- u64_stats_update_end(&ring->syncp);
-
- dev_kfree_skb_any(skb);
- return -EFAULT;
- }
+ l2_frame_type = hnae3_get_field(l234info, HNS3_RXD_DMAC_M,
+ HNS3_RXD_DMAC_S);
u64_stats_update_begin(&ring->syncp);
+ if (l2_frame_type == HNS3_L2_TYPE_MULTICAST)
+ ring->stats.rx_multicast++;
+
ring->stats.rx_pkts++;
ring->stats.rx_bytes += skb->len;
u64_stats_update_end(&ring->syncp);
@@ -2770,7 +2767,7 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group)
u32 time_passed_ms;
u16 new_int_gl;
- if (!ring_group->coal.int_gl || !tqp_vector->last_jiffies)
+ if (!tqp_vector->last_jiffies)
return false;
if (ring_group->total_packets == 0) {
@@ -2873,7 +2870,7 @@ static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector)
}
if (tx_group->coal.gl_adapt_enable) {
- tx_update = hns3_get_new_int_gl(&tqp_vector->tx_group);
+ tx_update = hns3_get_new_int_gl(tx_group);
if (tx_update)
hns3_set_vector_coalesce_tx_gl(tqp_vector,
tx_group->coal.int_gl);
@@ -3176,25 +3173,23 @@ static void hns3_clear_ring_group(struct hns3_enet_ring_group *group)
group->count = 0;
}
-static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv)
+static void hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv)
{
struct hnae3_ring_chain_node vector_ring_chain;
struct hnae3_handle *h = priv->ae_handle;
struct hns3_enet_tqp_vector *tqp_vector;
- int i, ret;
+ int i;
for (i = 0; i < priv->vector_num; i++) {
tqp_vector = &priv->tqp_vector[i];
- ret = hns3_get_vector_ring_chain(tqp_vector,
- &vector_ring_chain);
- if (ret)
- return ret;
+ if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring)
+ continue;
+
+ hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain);
- ret = h->ae_algo->ops->unmap_ring_from_vector(h,
+ h->ae_algo->ops->unmap_ring_from_vector(h,
tqp_vector->vector_irq, &vector_ring_chain);
- if (ret)
- return ret;
hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
@@ -3206,13 +3201,10 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv)
tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED;
}
- priv->ring_data[i].ring->irq_init_flag = HNS3_VECTOR_NOT_INITED;
hns3_clear_ring_group(&tqp_vector->rx_group);
hns3_clear_ring_group(&tqp_vector->tx_group);
netif_napi_del(&priv->tqp_vector[i].napi);
}
-
- return 0;
}
static int hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
@@ -3241,16 +3233,19 @@ static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
int queue_num = priv->ae_handle->kinfo.num_tqps;
struct pci_dev *pdev = priv->ae_handle->pdev;
struct hns3_enet_ring *ring;
+ int desc_num;
ring = devm_kzalloc(&pdev->dev, sizeof(*ring), GFP_KERNEL);
if (!ring)
return -ENOMEM;
if (ring_type == HNAE3_RING_TYPE_TX) {
+ desc_num = priv->ae_handle->kinfo.num_tx_desc;
ring_data[q->tqp_index].ring = ring;
ring_data[q->tqp_index].queue_index = q->tqp_index;
ring->io_base = (u8 __iomem *)q->io_base + HNS3_TX_REG_OFFSET;
} else {
+ desc_num = priv->ae_handle->kinfo.num_rx_desc;
ring_data[q->tqp_index + queue_num].ring = ring;
ring_data[q->tqp_index + queue_num].queue_index = q->tqp_index;
ring->io_base = q->io_base;
@@ -3264,7 +3259,7 @@ static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
ring->dev = priv->dev;
ring->desc_dma_addr = 0;
ring->buf_size = q->buf_size;
- ring->desc_num = q->desc_num;
+ ring->desc_num = desc_num;
ring->next_to_use = 0;
ring->next_to_clean = 0;
@@ -3376,6 +3371,11 @@ static void hns3_fini_ring(struct hns3_enet_ring *ring)
ring->desc_cb = NULL;
ring->next_to_clean = 0;
ring->next_to_use = 0;
+ ring->pending_buf = 0;
+ if (ring->skb) {
+ dev_kfree_skb_any(ring->skb);
+ ring->skb = NULL;
+ }
}
static int hns3_buf_size2type(u32 buf_size)
@@ -3516,6 +3516,25 @@ static int hns3_init_mac_addr(struct net_device *netdev, bool init)
return ret;
}
+static int hns3_init_phy(struct net_device *netdev)
+{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+ int ret = 0;
+
+ if (h->ae_algo->ops->mac_connect_phy)
+ ret = h->ae_algo->ops->mac_connect_phy(h);
+
+ return ret;
+}
+
+static void hns3_uninit_phy(struct net_device *netdev)
+{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+
+ if (h->ae_algo->ops->mac_disconnect_phy)
+ h->ae_algo->ops->mac_disconnect_phy(h);
+}
+
static int hns3_restore_fd_rules(struct net_device *netdev)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
@@ -3539,7 +3558,6 @@ static void hns3_nic_set_priv_ops(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
- priv->ops.fill_desc = hns3_fill_desc;
if ((netdev->features & NETIF_F_TSO) ||
(netdev->features & NETIF_F_TSO6))
priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tso;
@@ -3582,6 +3600,7 @@ static int hns3_client_init(struct hnae3_handle *handle)
priv->netdev = netdev;
priv->ae_handle = handle;
priv->tx_timeout_count = 0;
+ set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
handle->kinfo.netdev = netdev;
handle->priv = (void *)priv;
@@ -3624,6 +3643,10 @@ static int hns3_client_init(struct hnae3_handle *handle)
goto out_init_ring_data;
}
+ ret = hns3_init_phy(netdev);
+ if (ret)
+ goto out_init_phy;
+
ret = register_netdev(netdev);
if (ret) {
dev_err(priv->dev, "probe register netdev fail!\n");
@@ -3633,7 +3656,7 @@ static int hns3_client_init(struct hnae3_handle *handle)
ret = hns3_client_start(handle);
if (ret) {
dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
- goto out_reg_netdev_fail;
+ goto out_client_start;
}
hns3_dcbnl_setup(handle);
@@ -3647,9 +3670,14 @@ static int hns3_client_init(struct hnae3_handle *handle)
return ret;
+out_client_start:
+ unregister_netdev(netdev);
out_reg_netdev_fail:
+ hns3_uninit_phy(netdev);
+out_init_phy:
+ hns3_uninit_all_ring(priv);
out_init_ring_data:
- (void)hns3_nic_uninit_vector_data(priv);
+ hns3_nic_uninit_vector_data(priv);
out_init_vector_data:
hns3_nic_dealloc_vector_data(priv);
out_alloc_vector_data:
@@ -3682,9 +3710,9 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
hns3_force_clear_all_rx_ring(handle);
- ret = hns3_nic_uninit_vector_data(priv);
- if (ret)
- netdev_err(netdev, "uninit vector error\n");
+ hns3_uninit_phy(netdev);
+
+ hns3_nic_uninit_vector_data(priv);
ret = hns3_nic_dealloc_vector_data(priv);
if (ret)
@@ -3726,8 +3754,6 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
struct net_device *ndev = kinfo->netdev;
- bool if_running;
- int ret;
if (tc > HNAE3_MAX_TC)
return -EINVAL;
@@ -3735,25 +3761,7 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
if (!ndev)
return -ENODEV;
- if_running = netif_running(ndev);
-
- if (if_running) {
- (void)hns3_nic_net_stop(ndev);
- msleep(100);
- }
-
- ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ?
- kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP;
- if (ret)
- goto err_out;
-
- ret = hns3_nic_set_real_num_queue(ndev);
-
-err_out:
- if (if_running)
- (void)hns3_nic_net_open(ndev);
-
- return ret;
+ return hns3_nic_set_real_num_queue(ndev);
}
static int hns3_recover_hw_addr(struct net_device *ndev)
@@ -4014,41 +4022,18 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
{
struct net_device *netdev = handle->kinfo.netdev;
struct hns3_nic_priv *priv = netdev_priv(netdev);
- bool vlan_filter_enable;
int ret;
- ret = hns3_init_mac_addr(netdev, false);
- if (ret)
- return ret;
-
- ret = hns3_recover_hw_addr(netdev);
- if (ret)
- return ret;
-
- ret = hns3_update_promisc_mode(netdev, handle->netdev_flags);
- if (ret)
- return ret;
-
- vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true;
- hns3_enable_vlan_filter(netdev, vlan_filter_enable);
-
- /* Hardware table is only clear when pf resets */
- if (!(handle->flags & HNAE3_SUPPORT_VF)) {
- ret = hns3_restore_vlan(netdev);
- if (ret)
- return ret;
- }
+ /* Carrier off reporting is important to ethtool even BEFORE open */
+ netif_carrier_off(netdev);
- ret = hns3_restore_fd_rules(netdev);
+ ret = hns3_get_ring_config(priv);
if (ret)
return ret;
- /* Carrier off reporting is important to ethtool even BEFORE open */
- netif_carrier_off(netdev);
-
ret = hns3_nic_alloc_vector_data(priv);
if (ret)
- return ret;
+ goto err_put_ring;
hns3_restore_coal(priv);
@@ -4069,10 +4054,44 @@ err_uninit_vector:
priv->ring_data = NULL;
err_dealloc_vector:
hns3_nic_dealloc_vector_data(priv);
+err_put_ring:
+ hns3_put_ring_config(priv);
+ priv->ring_data = NULL;
return ret;
}
+static int hns3_reset_notify_restore_enet(struct hnae3_handle *handle)
+{
+ struct net_device *netdev = handle->kinfo.netdev;
+ bool vlan_filter_enable;
+ int ret;
+
+ ret = hns3_init_mac_addr(netdev, false);
+ if (ret)
+ return ret;
+
+ ret = hns3_recover_hw_addr(netdev);
+ if (ret)
+ return ret;
+
+ ret = hns3_update_promisc_mode(netdev, handle->netdev_flags);
+ if (ret)
+ return ret;
+
+ vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true;
+ hns3_enable_vlan_filter(netdev, vlan_filter_enable);
+
+ /* Hardware table is only clear when pf resets */
+ if (!(handle->flags & HNAE3_SUPPORT_VF)) {
+ ret = hns3_restore_vlan(netdev);
+ if (ret)
+ return ret;
+ }
+
+ return hns3_restore_fd_rules(netdev);
+}
+
static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
{
struct net_device *netdev = handle->kinfo.netdev;
@@ -4086,11 +4105,7 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
hns3_force_clear_all_rx_ring(handle);
- ret = hns3_nic_uninit_vector_data(priv);
- if (ret) {
- netdev_err(netdev, "uninit vector error\n");
- return ret;
- }
+ hns3_nic_uninit_vector_data(priv);
hns3_store_coal(priv);
@@ -4102,6 +4117,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
if (ret)
netdev_err(netdev, "uninit ring error\n");
+ hns3_put_ring_config(priv);
+ priv->ring_data = NULL;
+
clear_bit(HNS3_NIC_STATE_INITED, &priv->state);
return ret;
@@ -4125,6 +4143,9 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
case HNAE3_UNINIT_CLIENT:
ret = hns3_reset_notify_uninit_enet(handle);
break;
+ case HNAE3_RESTORE_CLIENT:
+ ret = hns3_reset_notify_restore_enet(handle);
+ break;
default:
break;
}
@@ -4132,57 +4153,12 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
return ret;
}
-static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num)
-{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = hns3_get_handle(netdev);
- int ret;
-
- ret = h->ae_algo->ops->set_channels(h, new_tqp_num);
- if (ret)
- return ret;
-
- ret = hns3_get_ring_config(priv);
- if (ret)
- return ret;
-
- ret = hns3_nic_alloc_vector_data(priv);
- if (ret)
- goto err_alloc_vector;
-
- hns3_restore_coal(priv);
-
- ret = hns3_nic_init_vector_data(priv);
- if (ret)
- goto err_uninit_vector;
-
- ret = hns3_init_all_ring(priv);
- if (ret)
- goto err_put_ring;
-
- return 0;
-
-err_put_ring:
- hns3_put_ring_config(priv);
-err_uninit_vector:
- hns3_nic_uninit_vector_data(priv);
-err_alloc_vector:
- hns3_nic_dealloc_vector_data(priv);
- return ret;
-}
-
-static int hns3_adjust_tqps_num(u8 num_tc, u32 new_tqp_num)
-{
- return (new_tqp_num / num_tc) * num_tc;
-}
-
int hns3_set_channels(struct net_device *netdev,
struct ethtool_channels *ch)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = hns3_get_handle(netdev);
struct hnae3_knic_private_info *kinfo = &h->kinfo;
- bool if_running = netif_running(netdev);
+ bool rxfh_configured = netif_is_rxfh_configured(netdev);
u32 new_tqp_num = ch->combined_count;
u16 org_tqp_num;
int ret;
@@ -4191,39 +4167,29 @@ int hns3_set_channels(struct net_device *netdev,
return -EINVAL;
if (new_tqp_num > hns3_get_max_available_channels(h) ||
- new_tqp_num < kinfo->num_tc) {
+ new_tqp_num < 1) {
dev_err(&netdev->dev,
- "Change tqps fail, the tqp range is from %d to %d",
- kinfo->num_tc,
+ "Change tqps fail, the tqp range is from 1 to %d",
hns3_get_max_available_channels(h));
return -EINVAL;
}
- new_tqp_num = hns3_adjust_tqps_num(kinfo->num_tc, new_tqp_num);
- if (kinfo->num_tqps == new_tqp_num)
+ if (kinfo->rss_size == new_tqp_num)
return 0;
- if (if_running)
- hns3_nic_net_stop(netdev);
-
- ret = hns3_nic_uninit_vector_data(priv);
- if (ret) {
- dev_err(&netdev->dev,
- "Unbind vector with tqp fail, nothing is changed");
- goto open_netdev;
- }
-
- hns3_store_coal(priv);
-
- hns3_nic_dealloc_vector_data(priv);
+ ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT);
+ if (ret)
+ return ret;
- hns3_uninit_all_ring(priv);
- hns3_put_ring_config(priv);
+ ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT);
+ if (ret)
+ return ret;
org_tqp_num = h->kinfo.num_tqps;
- ret = hns3_modify_tqp_num(netdev, new_tqp_num);
+ ret = h->ae_algo->ops->set_channels(h, new_tqp_num, rxfh_configured);
if (ret) {
- ret = hns3_modify_tqp_num(netdev, org_tqp_num);
+ ret = h->ae_algo->ops->set_channels(h, org_tqp_num,
+ rxfh_configured);
if (ret) {
/* If revert to old tqp failed, fatal error occurred */
dev_err(&netdev->dev,
@@ -4233,12 +4199,11 @@ int hns3_set_channels(struct net_device *netdev,
dev_info(&netdev->dev,
"Change tqp num fail, Revert to old tqp num");
}
+ ret = hns3_reset_notify(h, HNAE3_INIT_CLIENT);
+ if (ret)
+ return ret;
-open_netdev:
- if (if_running)
- hns3_nic_net_open(netdev);
-
- return ret;
+ return hns3_reset_notify(h, HNAE3_UP_CLIENT);
}
static const struct hnae3_client_ops client_ops = {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index e55995e93bb0..1db0bd41d209 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -74,7 +74,7 @@ enum hns3_nic_state {
#define HNS3_RING_NAME_LEN 16
#define HNS3_BUFFER_SIZE_2048 2048
#define HNS3_RING_MAX_PENDING 32768
-#define HNS3_RING_MIN_PENDING 8
+#define HNS3_RING_MIN_PENDING 24
#define HNS3_RING_BD_MULTIPLE 8
/* max frame size of mac */
#define HNS3_MAC_MAX_FRAME 9728
@@ -184,6 +184,8 @@ enum hns3_nic_state {
#define HNS3_TXD_MSS_S 0
#define HNS3_TXD_MSS_M (0x3fff << HNS3_TXD_MSS_S)
+#define HNS3_TX_LAST_SIZE_M 0xffff
+
#define HNS3_VECTOR_TX_IRQ BIT_ULL(0)
#define HNS3_VECTOR_RX_IRQ BIT_ULL(1)
@@ -191,6 +193,7 @@ enum hns3_nic_state {
#define HNS3_VECTOR_INITED 1
#define HNS3_MAX_BD_SIZE 65535
+#define HNS3_MAX_BD_SIZE_OFFSET 16
#define HNS3_MAX_BD_PER_FRAG 8
#define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS
@@ -202,6 +205,13 @@ enum hns3_nic_state {
#define HNS3_RING_EN_B 0
+enum hns3_pkt_l2t_type {
+ HNS3_L2_TYPE_UNICAST,
+ HNS3_L2_TYPE_MULTICAST,
+ HNS3_L2_TYPE_BROADCAST,
+ HNS3_L2_TYPE_INVALID,
+};
+
enum hns3_pkt_l3t_type {
HNS3_L3T_NONE,
HNS3_L3T_IPV6,
@@ -376,6 +386,7 @@ struct ring_stats {
u64 err_bd_num;
u64 l2_err;
u64 l3l4_csum_err;
+ u64 rx_multicast;
};
};
};
@@ -412,7 +423,6 @@ struct hns3_enet_ring {
unsigned char *va; /* first buffer address for current packet */
u32 flag; /* ring attribute */
- int irq_init_flag;
int numa_node;
cpumask_t affinity_mask;
@@ -434,11 +444,8 @@ struct hns3_nic_ring_data {
};
struct hns3_nic_ops {
- int (*fill_desc)(struct hns3_enet_ring *ring, void *priv,
- int size, int frag_end, enum hns_desc_type type);
int (*maybe_stop_tx)(struct sk_buff **out_skb,
int *bnum, struct hns3_enet_ring *ring);
- void (*get_rxd_bnum)(u32 bnum_flag, int *out_bnum);
};
enum hns3_flow_level_range {
@@ -567,6 +574,7 @@ union l3_hdr_info {
union l4_hdr_info {
struct tcphdr *tcp;
struct udphdr *udp;
+ struct gre_base_hdr *gre;
unsigned char *hdr;
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index e678b6939da3..359d4731fb2d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -47,6 +47,7 @@ static const struct hns3_stats hns3_rxq_stats[] = {
HNS3_TQP_STAT("err_bd_num", err_bd_num),
HNS3_TQP_STAT("l2_err", l2_err),
HNS3_TQP_STAT("l3l4_csum_err", l3l4_csum_err),
+ HNS3_TQP_STAT("multicast", rx_multicast),
};
#define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats)
@@ -116,7 +117,7 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode)
ret = hns3_lp_setup(ndev, loop_mode, true);
usleep_range(10000, 20000);
- return 0;
+ return ret;
}
static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode)
@@ -333,10 +334,10 @@ static void hns3_self_test(struct net_device *ndev,
continue;
data[test_index] = hns3_lp_up(ndev, loop_type);
- if (!data[test_index]) {
+ if (!data[test_index])
data[test_index] = hns3_lp_run_test(ndev, loop_type);
- hns3_lp_down(ndev, loop_type);
- }
+
+ hns3_lp_down(ndev, loop_type);
if (data[test_index])
eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -620,12 +621,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
hns3_get_ksettings(h, cmd);
break;
case HNAE3_MEDIA_TYPE_COPPER:
- if (!netdev->phydev)
- return -EOPNOTSUPP;
-
cmd->base.port = PORT_TP;
- phy_ethtool_ksettings_get(netdev->phydev, cmd);
-
+ if (!netdev->phydev)
+ hns3_get_ksettings(h, cmd);
+ else
+ phy_ethtool_ksettings_get(netdev->phydev, cmd);
break;
default:
@@ -748,15 +748,19 @@ static int hns3_get_rxnfc(struct net_device *netdev,
}
static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
- u32 new_desc_num)
+ u32 tx_desc_num, u32 rx_desc_num)
{
struct hnae3_handle *h = priv->ae_handle;
int i;
- h->kinfo.num_desc = new_desc_num;
+ h->kinfo.num_tx_desc = tx_desc_num;
+ h->kinfo.num_rx_desc = rx_desc_num;
- for (i = 0; i < h->kinfo.num_tqps * 2; i++)
- priv->ring_data[i].ring->desc_num = new_desc_num;
+ for (i = 0; i < h->kinfo.num_tqps; i++) {
+ priv->ring_data[i].ring->desc_num = tx_desc_num;
+ priv->ring_data[i + h->kinfo.num_tqps].ring->desc_num =
+ rx_desc_num;
+ }
return hns3_init_all_ring(priv);
}
@@ -767,7 +771,9 @@ static int hns3_set_ringparam(struct net_device *ndev,
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
bool if_running = netif_running(ndev);
- u32 old_desc_num, new_desc_num;
+ u32 old_tx_desc_num, new_tx_desc_num;
+ u32 old_rx_desc_num, new_rx_desc_num;
+ int queue_num = h->kinfo.num_tqps;
int ret;
if (hns3_nic_resetting(ndev))
@@ -776,43 +782,41 @@ static int hns3_set_ringparam(struct net_device *ndev,
if (param->rx_mini_pending || param->rx_jumbo_pending)
return -EINVAL;
- if (param->tx_pending != param->rx_pending) {
- netdev_err(ndev,
- "Descriptors of tx and rx must be equal");
- return -EINVAL;
- }
-
if (param->tx_pending > HNS3_RING_MAX_PENDING ||
- param->tx_pending < HNS3_RING_MIN_PENDING) {
- netdev_err(ndev,
- "Descriptors requested (Tx/Rx: %d) out of range [%d-%d]\n",
- param->tx_pending, HNS3_RING_MIN_PENDING,
- HNS3_RING_MAX_PENDING);
+ param->tx_pending < HNS3_RING_MIN_PENDING ||
+ param->rx_pending > HNS3_RING_MAX_PENDING ||
+ param->rx_pending < HNS3_RING_MIN_PENDING) {
+ netdev_err(ndev, "Queue depth out of range [%d-%d]\n",
+ HNS3_RING_MIN_PENDING, HNS3_RING_MAX_PENDING);
return -EINVAL;
}
- new_desc_num = param->tx_pending;
-
/* Hardware requires that its descriptors must be multiple of eight */
- new_desc_num = ALIGN(new_desc_num, HNS3_RING_BD_MULTIPLE);
- old_desc_num = h->kinfo.num_desc;
- if (old_desc_num == new_desc_num)
+ new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE);
+ new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE);
+ old_tx_desc_num = priv->ring_data[0].ring->desc_num;
+ old_rx_desc_num = priv->ring_data[queue_num].ring->desc_num;
+ if (old_tx_desc_num == new_tx_desc_num &&
+ old_rx_desc_num == new_rx_desc_num)
return 0;
netdev_info(ndev,
- "Changing descriptor count from %d to %d.\n",
- old_desc_num, new_desc_num);
+ "Changing Tx/Rx ring depth from %d/%d to %d/%d\n",
+ old_tx_desc_num, old_rx_desc_num,
+ new_tx_desc_num, new_rx_desc_num);
if (if_running)
- dev_close(ndev);
+ ndev->netdev_ops->ndo_stop(ndev);
ret = hns3_uninit_all_ring(priv);
if (ret)
return ret;
- ret = hns3_change_all_ring_bd_num(priv, new_desc_num);
+ ret = hns3_change_all_ring_bd_num(priv, new_tx_desc_num,
+ new_rx_desc_num);
if (ret) {
- ret = hns3_change_all_ring_bd_num(priv, old_desc_num);
+ ret = hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
+ old_rx_desc_num);
if (ret) {
netdev_err(ndev,
"Revert to old bd num fail, ret=%d.\n", ret);
@@ -821,7 +825,7 @@ static int hns3_set_ringparam(struct net_device *ndev,
}
if (if_running)
- ret = dev_open(ndev, NULL);
+ ret = ndev->netdev_ops->ndo_open(ndev);
return ret;
}
@@ -1114,6 +1118,8 @@ static const struct ethtool_ops hns3vf_ethtool_ops = {
.get_channels = hns3_get_channels,
.get_coalesce = hns3_get_coalesce,
.set_coalesce = hns3_set_coalesce,
+ .get_regs_len = hns3_get_regs_len,
+ .get_regs = hns3_get_regs,
.get_link = hns3_get_link,
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 8af0cef5609b..3a093a92eac5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -39,9 +39,8 @@ static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
{
int size = ring->desc_num * sizeof(struct hclge_desc);
- ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
- size, &ring->desc_dma_addr,
- GFP_KERNEL);
+ ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+ &ring->desc_dma_addr, GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
@@ -171,8 +170,12 @@ static bool hclge_is_special_opcode(u16 opcode)
/* these commands have several descriptors,
* and use the first one to save opcode and return value
*/
- u16 spec_opcode[3] = {HCLGE_OPC_STATS_64_BIT,
- HCLGE_OPC_STATS_32_BIT, HCLGE_OPC_STATS_MAC};
+ u16 spec_opcode[] = {HCLGE_OPC_STATS_64_BIT,
+ HCLGE_OPC_STATS_32_BIT,
+ HCLGE_OPC_STATS_MAC,
+ HCLGE_OPC_STATS_MAC_ALL,
+ HCLGE_OPC_QUERY_32_BIT_REG,
+ HCLGE_OPC_QUERY_64_BIT_REG};
int i;
for (i = 0; i < ARRAY_SIZE(spec_opcode); i++) {
@@ -183,6 +186,38 @@ static bool hclge_is_special_opcode(u16 opcode)
return false;
}
+static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc,
+ int num, int ntc)
+{
+ u16 opcode, desc_ret;
+ int handle;
+ int retval;
+
+ opcode = le16_to_cpu(desc[0].opcode);
+ for (handle = 0; handle < num; handle++) {
+ desc[handle] = hw->cmq.csq.desc[ntc];
+ ntc++;
+ if (ntc >= hw->cmq.csq.desc_num)
+ ntc = 0;
+ }
+ if (likely(!hclge_is_special_opcode(opcode)))
+ desc_ret = le16_to_cpu(desc[num - 1].retval);
+ else
+ desc_ret = le16_to_cpu(desc[0].retval);
+
+ if (desc_ret == HCLGE_CMD_EXEC_SUCCESS)
+ retval = 0;
+ else if (desc_ret == HCLGE_CMD_NO_AUTH)
+ retval = -EPERM;
+ else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED)
+ retval = -EOPNOTSUPP;
+ else
+ retval = -EIO;
+ hw->cmq.last_status = desc_ret;
+
+ return retval;
+}
+
/**
* hclge_cmd_send - send command to command queue
* @hw: pointer to the hw struct
@@ -200,7 +235,6 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
u32 timeout = 0;
int handle = 0;
int retval = 0;
- u16 opcode, desc_ret;
int ntc;
spin_lock_bh(&hw->cmq.csq.lock);
@@ -216,12 +250,11 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
* which will be use for hardware to write back
*/
ntc = hw->cmq.csq.next_to_use;
- opcode = le16_to_cpu(desc[0].opcode);
while (handle < num) {
desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
*desc_to_use = desc[handle];
(hw->cmq.csq.next_to_use)++;
- if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
+ if (hw->cmq.csq.next_to_use >= hw->cmq.csq.desc_num)
hw->cmq.csq.next_to_use = 0;
handle++;
}
@@ -247,27 +280,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
if (!complete) {
retval = -EAGAIN;
} else {
- handle = 0;
- while (handle < num) {
- /* Get the result of hardware write back */
- desc_to_use = &hw->cmq.csq.desc[ntc];
- desc[handle] = *desc_to_use;
-
- if (likely(!hclge_is_special_opcode(opcode)))
- desc_ret = le16_to_cpu(desc[handle].retval);
- else
- desc_ret = le16_to_cpu(desc[0].retval);
-
- if (desc_ret == HCLGE_CMD_EXEC_SUCCESS)
- retval = 0;
- else
- retval = -EIO;
- hw->cmq.last_status = desc_ret;
- ntc++;
- handle++;
- if (ntc == hw->cmq.csq.desc_num)
- ntc = 0;
- }
+ retval = hclge_cmd_check_retval(hw, desc, num, ntc);
}
/* Clean the command send queue */
@@ -377,6 +390,20 @@ int hclge_cmd_init(struct hclge_dev *hdev)
return 0;
}
+static void hclge_cmd_uninit_regs(struct hclge_hw *hw)
+{
+ hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_L_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
+ hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
+}
+
static void hclge_destroy_queue(struct hclge_cmq_ring *ring)
{
spin_lock(&ring->lock);
@@ -389,3 +416,15 @@ void hclge_destroy_cmd_queue(struct hclge_hw *hw)
hclge_destroy_queue(&hw->cmq.csq);
hclge_destroy_queue(&hw->cmq.crq);
}
+
+void hclge_cmd_uninit(struct hclge_dev *hdev)
+{
+ spin_lock_bh(&hdev->hw.cmq.csq.lock);
+ spin_lock(&hdev->hw.cmq.crq.lock);
+ set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
+ hclge_cmd_uninit_regs(&hdev->hw);
+ spin_unlock(&hdev->hw.cmq.crq.lock);
+ spin_unlock_bh(&hdev->hw.cmq.csq.lock);
+
+ hclge_destroy_cmd_queue(&hdev->hw);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index f23042b24c09..3714733c96d9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -39,7 +39,7 @@ struct hclge_cmq_ring {
enum hclge_cmd_return_status {
HCLGE_CMD_EXEC_SUCCESS = 0,
HCLGE_CMD_NO_AUTH = 1,
- HCLGE_CMD_NOT_EXEC = 2,
+ HCLGE_CMD_NOT_SUPPORTED = 2,
HCLGE_CMD_QUEUE_FULL = 3,
};
@@ -82,6 +82,8 @@ enum hclge_opcode_type {
HCLGE_OPC_STATS_64_BIT = 0x0030,
HCLGE_OPC_STATS_32_BIT = 0x0031,
HCLGE_OPC_STATS_MAC = 0x0032,
+ HCLGE_OPC_QUERY_MAC_REG_NUM = 0x0033,
+ HCLGE_OPC_STATS_MAC_ALL = 0x0034,
HCLGE_OPC_QUERY_REG_NUM = 0x0040,
HCLGE_OPC_QUERY_32_BIT_REG = 0x0041,
@@ -310,16 +312,16 @@ struct hclge_ctrl_vector_chain_cmd {
u8 rsv;
};
-#define HCLGE_TC_NUM 8
+#define HCLGE_MAX_TC_NUM 8
#define HCLGE_TC0_PRI_BUF_EN_B 15 /* Bit 15 indicate enable or not */
#define HCLGE_BUF_UNIT_S 7 /* Buf size is united by 128 bytes */
struct hclge_tx_buff_alloc_cmd {
- __le16 tx_pkt_buff[HCLGE_TC_NUM];
+ __le16 tx_pkt_buff[HCLGE_MAX_TC_NUM];
u8 tx_buff_rsv[8];
};
struct hclge_rx_priv_buff_cmd {
- __le16 buf_num[HCLGE_TC_NUM];
+ __le16 buf_num[HCLGE_MAX_TC_NUM];
__le16 shared_buf;
u8 rsv[6];
};
@@ -365,7 +367,6 @@ struct hclge_priv_buf {
u32 enable; /* Enable TC private buffer or not */
};
-#define HCLGE_MAX_TC_NUM 8
struct hclge_shared_buf {
struct hclge_waterline self;
struct hclge_tc_thrd tc_thrd[HCLGE_MAX_TC_NUM];
@@ -692,7 +693,9 @@ struct hclge_mac_vlan_remove_cmd {
struct hclge_vlan_filter_ctrl_cmd {
u8 vlan_type;
u8 vlan_fe;
- u8 rsv[22];
+ u8 rsv1[2];
+ u8 vf_id;
+ u8 rsv2[19];
};
struct hclge_vlan_filter_pf_cfg_cmd {
@@ -974,6 +977,6 @@ enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw,
enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw,
struct hclge_desc *desc);
-void hclge_destroy_cmd_queue(struct hclge_hw *hw);
+void hclge_cmd_uninit(struct hclge_dev *hdev);
int hclge_cmd_queue_init(struct hclge_dev *hdev);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
index f6323b2501dc..1161361a973b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
@@ -93,13 +93,11 @@ static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc,
}
}
- for (i = 0; i < hdev->num_alloc_vport; i++) {
- if (num_tc > hdev->vport[i].alloc_tqps) {
- dev_err(&hdev->pdev->dev,
- "allocated tqp(%u) checking failed, %u > tqp(%u)\n",
- i, num_tc, hdev->vport[i].alloc_tqps);
- return -EINVAL;
- }
+ if (num_tc > hdev->vport[0].alloc_tqps) {
+ dev_err(&hdev->pdev->dev,
+ "allocated tqp checking failed, %u > tqp(%u)\n",
+ num_tc, hdev->vport[0].alloc_tqps);
+ return -EINVAL;
}
return 0;
@@ -156,21 +154,15 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
return 0;
}
-static int hclge_map_update(struct hnae3_handle *h)
+static int hclge_map_update(struct hclge_dev *hdev)
{
- struct hclge_vport *vport = hclge_get_vport(h);
- struct hclge_dev *hdev = vport->back;
int ret;
- ret = hclge_tm_map_cfg(hdev);
+ ret = hclge_tm_schd_setup_hw(hdev);
if (ret)
return ret;
- ret = hclge_tm_schd_mode_hw(hdev);
- if (ret)
- return ret;
-
- ret = hclge_pause_setup_hw(hdev);
+ ret = hclge_pause_setup_hw(hdev, false);
if (ret)
return ret;
@@ -222,19 +214,51 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
if (ret)
return ret;
+ if (map_changed) {
+ ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
+ if (ret)
+ return ret;
+
+ ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
+ if (ret)
+ return ret;
+ }
+
hclge_tm_schd_info_update(hdev, num_tc);
ret = hclge_ieee_ets_to_tm_info(hdev, ets);
if (ret)
- return ret;
+ goto err_out;
if (map_changed) {
+ ret = hclge_map_update(hdev);
+ if (ret)
+ goto err_out;
+
ret = hclge_client_setup_tc(hdev);
if (ret)
+ goto err_out;
+
+ ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
+ if (ret)
+ return ret;
+
+ ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ if (ret)
return ret;
}
return hclge_tm_dwrr_cfg(hdev);
+
+err_out:
+ if (!map_changed)
+ return ret;
+
+ if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT))
+ return ret;
+
+ hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ return ret;
}
static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
@@ -283,6 +307,9 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
return -EINVAL;
+ if (pfc->pfc_en == hdev->tm_info.pfc_en)
+ return 0;
+
prio_tc = hdev->tm_info.prio_tc;
pfc_map = 0;
@@ -295,12 +322,10 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
}
}
- if (pfc_map == hdev->tm_info.hw_pfc_map)
- return 0;
-
hdev->tm_info.hw_pfc_map = pfc_map;
+ hdev->tm_info.pfc_en = pfc->pfc_en;
- return hclge_pause_setup_hw(hdev);
+ return hclge_pause_setup_hw(hdev, false);
}
/* DCBX configuration */
@@ -345,12 +370,24 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc)
if (ret)
return -EINVAL;
+ ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
+ if (ret)
+ return ret;
+
+ ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
+ if (ret)
+ return ret;
+
hclge_tm_schd_info_update(hdev, tc);
hclge_tm_prio_tc_info_update(hdev, prio_tc);
- ret = hclge_tm_init_hw(hdev);
+ ret = hclge_tm_init_hw(hdev, false);
if (ret)
- return ret;
+ goto err_out;
+
+ ret = hclge_client_setup_tc(hdev);
+ if (ret)
+ goto err_out;
hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
@@ -359,7 +396,18 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc)
else
hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE;
- return 0;
+ ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
+ if (ret)
+ return ret;
+
+ return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+
+err_out:
+ if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT))
+ return ret;
+
+ hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ return ret;
}
static const struct hnae3_dcb_ops hns3_dcb_ops = {
@@ -369,7 +417,6 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = {
.ieee_setpfc = hclge_ieee_setpfc,
.getdcbx = hclge_getdcbx,
.setdcbx = hclge_setdcbx,
- .map_update = hclge_map_update,
.setup_tc = hclge_setup_tc,
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 26d80504c730..1192cf6f2321 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -691,7 +691,7 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
dev_info(&hdev->pdev->dev, "dump qos buf cfg\n");
tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc[0].data;
- for (i = 0; i < HCLGE_TC_NUM; i++)
+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++)
dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i,
tx_buf_cmd->tx_pkt_buff[i]);
@@ -703,7 +703,7 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
dev_info(&hdev->pdev->dev, "\n");
rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc[0].data;
- for (i = 0; i < HCLGE_TC_NUM; i++)
+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++)
dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i,
rx_buf_cmd->buf_num[i]);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
index d0f654123b9b..1feceff1477c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -80,7 +80,7 @@ static const struct hclge_hw_error hclge_ppp_mpf_abnormal_int_st1[] = {
{ .int_msk = BIT(3), .msg = "umv_key_mem1_ecc_mbit_err" },
{ .int_msk = BIT(4), .msg = "umv_key_mem2_ecc_mbit_err" },
{ .int_msk = BIT(5), .msg = "umv_key_mem3_ecc_mbit_err" },
- { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_erre" },
+ { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_err" },
{ .int_msk = BIT(7), .msg = "rss_tc_mode_mem_ecc_mbit_err" },
{ .int_msk = BIT(8), .msg = "rss_idt_mem0_ecc_mbit_err" },
{ .int_msk = BIT(9), .msg = "rss_idt_mem1_ecc_mbit_err" },
@@ -219,6 +219,12 @@ static const struct hclge_hw_error hclge_mac_afifo_tnl_int[] = {
{ .int_msk = BIT(5), .msg = "cge_igu_afifo_ecc_mbit_err" },
{ .int_msk = BIT(6), .msg = "lge_igu_afifo_ecc_1bit_err" },
{ .int_msk = BIT(7), .msg = "lge_igu_afifo_ecc_mbit_err" },
+ { .int_msk = BIT(8), .msg = "cge_igu_afifo_overflow_err" },
+ { .int_msk = BIT(9), .msg = "lge_igu_afifo_overflow_err" },
+ { .int_msk = BIT(10), .msg = "egu_cge_afifo_underrun_err" },
+ { .int_msk = BIT(11), .msg = "egu_lge_afifo_underrun_err" },
+ { .int_msk = BIT(12), .msg = "egu_ge_afifo_underrun_err" },
+ { .int_msk = BIT(13), .msg = "ge_igu_afifo_overflow_err" },
{ /* sentinel */ }
};
@@ -277,6 +283,45 @@ static const struct hclge_hw_error hclge_ssu_com_err_int[] = {
{ /* sentinel */ }
};
+#define HCLGE_SSU_MEM_ECC_ERR(x) \
+ { .int_msk = BIT(x), .msg = "ssu_mem" #x "_ecc_mbit_err" }
+
+static const struct hclge_hw_error hclge_ssu_mem_ecc_err_int[] = {
+ HCLGE_SSU_MEM_ECC_ERR(0),
+ HCLGE_SSU_MEM_ECC_ERR(1),
+ HCLGE_SSU_MEM_ECC_ERR(2),
+ HCLGE_SSU_MEM_ECC_ERR(3),
+ HCLGE_SSU_MEM_ECC_ERR(4),
+ HCLGE_SSU_MEM_ECC_ERR(5),
+ HCLGE_SSU_MEM_ECC_ERR(6),
+ HCLGE_SSU_MEM_ECC_ERR(7),
+ HCLGE_SSU_MEM_ECC_ERR(8),
+ HCLGE_SSU_MEM_ECC_ERR(9),
+ HCLGE_SSU_MEM_ECC_ERR(10),
+ HCLGE_SSU_MEM_ECC_ERR(11),
+ HCLGE_SSU_MEM_ECC_ERR(12),
+ HCLGE_SSU_MEM_ECC_ERR(13),
+ HCLGE_SSU_MEM_ECC_ERR(14),
+ HCLGE_SSU_MEM_ECC_ERR(15),
+ HCLGE_SSU_MEM_ECC_ERR(16),
+ HCLGE_SSU_MEM_ECC_ERR(17),
+ HCLGE_SSU_MEM_ECC_ERR(18),
+ HCLGE_SSU_MEM_ECC_ERR(19),
+ HCLGE_SSU_MEM_ECC_ERR(20),
+ HCLGE_SSU_MEM_ECC_ERR(21),
+ HCLGE_SSU_MEM_ECC_ERR(22),
+ HCLGE_SSU_MEM_ECC_ERR(23),
+ HCLGE_SSU_MEM_ECC_ERR(24),
+ HCLGE_SSU_MEM_ECC_ERR(25),
+ HCLGE_SSU_MEM_ECC_ERR(26),
+ HCLGE_SSU_MEM_ECC_ERR(27),
+ HCLGE_SSU_MEM_ECC_ERR(28),
+ HCLGE_SSU_MEM_ECC_ERR(29),
+ HCLGE_SSU_MEM_ECC_ERR(30),
+ HCLGE_SSU_MEM_ECC_ERR(31),
+ { /* sentinel */ }
+};
+
static const struct hclge_hw_error hclge_ssu_port_based_err_int[] = {
{ .int_msk = BIT(0), .msg = "roc_pkt_without_key_port" },
{ .int_msk = BIT(1), .msg = "tpu_pkt_without_key_port" },
@@ -835,13 +880,15 @@ static int hclge_handle_mpf_ras_error(struct hclge_dev *hdev,
desc_data = (__le32 *)&desc[2];
status = le32_to_cpu(*(desc_data + 2));
if (status) {
- dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_0 ssu_ecc_mbit_int[31:0]\n");
+ hclge_log_error(dev, "SSU_ECC_MULTI_BIT_INT_0",
+ &hclge_ssu_mem_ecc_err_int[0], status);
HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_CORE_RESET);
}
status = le32_to_cpu(*(desc_data + 3)) & BIT(0);
if (status) {
- dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_1 ssu_ecc_mbit_int[32]\n");
+ dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_1 ssu_mem32_ecc_mbit_err found [error status=0x%x]\n",
+ status);
HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_CORE_RESET);
}
@@ -997,6 +1044,13 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev,
hclge_log_error(dev, "IGU_EGU_TNL_INT_STS",
&hclge_igu_egu_tnl_int[0], status);
+ /* log PPU(RCB) errors */
+ desc_data = (__le32 *)&desc[3];
+ status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_RAS_MASK;
+ if (status)
+ hclge_log_error(dev, "PPU_PF_ABNORMAL_INT_ST0",
+ &hclge_ppu_pf_abnormal_int[0], status);
+
/* clear all PF RAS errors */
hclge_cmd_reuse_desc(&desc[0], false);
desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
@@ -1094,10 +1148,10 @@ static int hclge_log_rocee_ovf_error(struct hclge_dev *hdev)
return 0;
}
-static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev)
+static enum hnae3_reset_type
+hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev)
{
- enum hnae3_reset_type reset_type = HNAE3_FUNC_RESET;
- struct hnae3_ae_dev *ae_dev = hdev->ae_dev;
+ enum hnae3_reset_type reset_type = HNAE3_NONE_RESET;
struct device *dev = &hdev->pdev->dev;
struct hclge_desc desc[2];
unsigned int status;
@@ -1110,17 +1164,20 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev)
if (ret) {
dev_err(dev, "failed(%d) to query ROCEE RAS INT SRC\n", ret);
/* reset everything for now */
- HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_GLOBAL_RESET);
- return ret;
+ return HNAE3_GLOBAL_RESET;
}
status = le32_to_cpu(desc[0].data[0]);
- if (status & HCLGE_ROCEE_RERR_INT_MASK)
+ if (status & HCLGE_ROCEE_RERR_INT_MASK) {
dev_warn(dev, "ROCEE RAS AXI rresp error\n");
+ reset_type = HNAE3_FUNC_RESET;
+ }
- if (status & HCLGE_ROCEE_BERR_INT_MASK)
+ if (status & HCLGE_ROCEE_BERR_INT_MASK) {
dev_warn(dev, "ROCEE RAS AXI bresp error\n");
+ reset_type = HNAE3_FUNC_RESET;
+ }
if (status & HCLGE_ROCEE_ECC_INT_MASK) {
dev_warn(dev, "ROCEE RAS 2bit ECC error\n");
@@ -1132,9 +1189,9 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev)
if (ret) {
dev_err(dev, "failed(%d) to process ovf error\n", ret);
/* reset everything for now */
- HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_GLOBAL_RESET);
- return ret;
+ return HNAE3_GLOBAL_RESET;
}
+ reset_type = HNAE3_FUNC_RESET;
}
/* clear error status */
@@ -1143,12 +1200,10 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev)
if (ret) {
dev_err(dev, "failed(%d) to clear ROCEE RAS error\n", ret);
/* reset everything for now */
- reset_type = HNAE3_GLOBAL_RESET;
+ return HNAE3_GLOBAL_RESET;
}
- HCLGE_SET_DEFAULT_RESET_REQUEST(reset_type);
-
- return ret;
+ return reset_type;
}
static int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en)
@@ -1178,15 +1233,18 @@ static int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en)
return ret;
}
-static int hclge_handle_rocee_ras_error(struct hnae3_ae_dev *ae_dev)
+static void hclge_handle_rocee_ras_error(struct hnae3_ae_dev *ae_dev)
{
+ enum hnae3_reset_type reset_type = HNAE3_NONE_RESET;
struct hclge_dev *hdev = ae_dev->priv;
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) ||
hdev->pdev->revision < 0x21)
- return HNAE3_NONE_RESET;
+ return;
- return hclge_log_and_clear_rocee_ras_error(hdev);
+ reset_type = hclge_log_and_clear_rocee_ras_error(hdev);
+ if (reset_type != HNAE3_NONE_RESET)
+ HCLGE_SET_DEFAULT_RESET_REQUEST(reset_type);
}
static const struct hclge_hw_blk hw_blk[] = {
@@ -1332,14 +1390,13 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev,
set_bit(HNAE3_GLOBAL_RESET, reset_requests);
}
- /* log PPU(RCB) errors */
+ /* log PPU(RCB) MPF errors */
desc_data = (__le32 *)&desc[5];
status = le32_to_cpu(*(desc_data + 2)) &
HCLGE_PPU_MPF_INT_ST2_MSIX_MASK;
if (status) {
- dev_warn(dev,
- "PPU_MPF_ABNORMAL_INT_ST2[28:29], err_status(0x%x)\n",
- status);
+ hclge_log_error(dev, "PPU_MPF_ABNORMAL_INT_ST2",
+ &hclge_ppu_mpf_abnormal_int_st2[0], status);
set_bit(HNAE3_CORE_RESET, reset_requests);
}
@@ -1386,7 +1443,7 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev,
hclge_log_error(dev, "PPP_PF_ABNORMAL_INT_ST0",
&hclge_ppp_pf_abnormal_int[0], status);
- /* PPU(RCB) PF errors */
+ /* log PPU(RCB) PF errors */
desc_data = (__le32 *)&desc[3];
status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_MSIX_MASK;
if (status)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
index 51a7d4eb066a..fc068280d391 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
@@ -45,8 +45,8 @@
#define HCLGE_TM_QCN_MEM_ERR_INT_EN 0xFFFFFF
#define HCLGE_NCSI_ERR_INT_EN 0x3
#define HCLGE_NCSI_ERR_INT_TYPE 0x9
-#define HCLGE_MAC_COMMON_ERR_INT_EN GENMASK(7, 0)
-#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK GENMASK(7, 0)
+#define HCLGE_MAC_COMMON_ERR_INT_EN 0x107FF
+#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK 0x107FF
#define HCLGE_PPU_MPF_ABNORMAL_INT0_EN GENMASK(31, 0)
#define HCLGE_PPU_MPF_ABNORMAL_INT0_EN_MASK GENMASK(31, 0)
#define HCLGE_PPU_MPF_ABNORMAL_INT1_EN GENMASK(31, 0)
@@ -79,6 +79,7 @@
#define HCLGE_PPP_MPF_INT_ST3_MASK GENMASK(5, 0)
#define HCLGE_PPU_MPF_INT_ST3_MASK GENMASK(7, 0)
#define HCLGE_PPU_MPF_INT_ST2_MSIX_MASK GENMASK(29, 28)
+#define HCLGE_PPU_PF_INT_RAS_MASK 0x18
#define HCLGE_PPU_PF_INT_MSIX_MASK 0x27
#define HCLGE_QCN_FIFO_INT_MASK GENMASK(17, 0)
#define HCLGE_QCN_ECC_INT_MASK GENMASK(21, 0)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index f7637c08bb3a..deda606c51e7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -118,6 +118,12 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_mac_pause_num)},
{"mac_rx_mac_pause_num",
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_mac_pause_num)},
+ {"mac_tx_control_pkt_num",
+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_ctrl_pkt_num)},
+ {"mac_rx_control_pkt_num",
+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_ctrl_pkt_num)},
+ {"mac_tx_pfc_pkt_num",
+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pause_pkt_num)},
{"mac_tx_pfc_pri0_pkt_num",
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num)},
{"mac_tx_pfc_pri1_pkt_num",
@@ -134,6 +140,8 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num)},
{"mac_tx_pfc_pri7_pkt_num",
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num)},
+ {"mac_rx_pfc_pkt_num",
+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pause_pkt_num)},
{"mac_rx_pfc_pri0_pkt_num",
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num)},
{"mac_rx_pfc_pri1_pkt_num",
@@ -287,10 +295,17 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = {
},
};
-static int hclge_mac_update_stats(struct hclge_dev *hdev)
+static const u8 hclge_hash_key[] = {
+ 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
+ 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
+ 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
+ 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
+ 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA
+};
+
+static int hclge_mac_update_stats_defective(struct hclge_dev *hdev)
{
#define HCLGE_MAC_CMD_NUM 21
-#define HCLGE_RTN_DATA_NUM 4
u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
struct hclge_desc desc[HCLGE_MAC_CMD_NUM];
@@ -308,15 +323,18 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev)
}
for (i = 0; i < HCLGE_MAC_CMD_NUM; i++) {
+ /* for special opcode 0032, only the first desc has the head */
if (unlikely(i == 0)) {
desc_data = (__le64 *)(&desc[i].data[0]);
- n = HCLGE_RTN_DATA_NUM - 2;
+ n = HCLGE_RD_FIRST_STATS_NUM;
} else {
desc_data = (__le64 *)(&desc[i]);
- n = HCLGE_RTN_DATA_NUM;
+ n = HCLGE_RD_OTHER_STATS_NUM;
}
+
for (k = 0; k < n; k++) {
- *data++ += le64_to_cpu(*desc_data);
+ *data += le64_to_cpu(*desc_data);
+ data++;
desc_data++;
}
}
@@ -324,6 +342,85 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev)
return 0;
}
+static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num)
+{
+ u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
+ struct hclge_desc *desc;
+ __le64 *desc_data;
+ u16 i, k, n;
+ int ret;
+
+ desc = kcalloc(desc_num, sizeof(struct hclge_desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC_ALL, true);
+ ret = hclge_cmd_send(&hdev->hw, desc, desc_num);
+ if (ret) {
+ kfree(desc);
+ return ret;
+ }
+
+ for (i = 0; i < desc_num; i++) {
+ /* for special opcode 0034, only the first desc has the head */
+ if (i == 0) {
+ desc_data = (__le64 *)(&desc[i].data[0]);
+ n = HCLGE_RD_FIRST_STATS_NUM;
+ } else {
+ desc_data = (__le64 *)(&desc[i]);
+ n = HCLGE_RD_OTHER_STATS_NUM;
+ }
+
+ for (k = 0; k < n; k++) {
+ *data += le64_to_cpu(*desc_data);
+ data++;
+ desc_data++;
+ }
+ }
+
+ kfree(desc);
+
+ return 0;
+}
+
+static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num)
+{
+ struct hclge_desc desc;
+ __le32 *desc_data;
+ u32 reg_num;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_REG_NUM, true);
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret)
+ return ret;
+
+ desc_data = (__le32 *)(&desc.data[0]);
+ reg_num = le32_to_cpu(*desc_data);
+
+ *desc_num = 1 + ((reg_num - 3) >> 2) +
+ (u32)(((reg_num - 3) & 0x3) ? 1 : 0);
+
+ return 0;
+}
+
+static int hclge_mac_update_stats(struct hclge_dev *hdev)
+{
+ u32 desc_num;
+ int ret;
+
+ ret = hclge_mac_query_reg_num(hdev, &desc_num);
+
+ /* The firmware supports the new statistics acquisition method */
+ if (!ret)
+ ret = hclge_mac_update_stats_complete(hdev, desc_num);
+ else if (ret == -EOPNOTSUPP)
+ ret = hclge_mac_update_stats_defective(hdev);
+ else
+ dev_err(&hdev->pdev->dev, "query mac reg num fail!\n");
+
+ return ret;
+}
+
static int hclge_tqps_update_stats(struct hnae3_handle *handle)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
@@ -461,26 +558,6 @@ static u8 *hclge_comm_get_strings(u32 stringset,
return (u8 *)buff;
}
-static void hclge_update_netstat(struct hclge_hw_stats *hw_stats,
- struct net_device_stats *net_stats)
-{
- net_stats->tx_dropped = 0;
- net_stats->rx_errors = hw_stats->mac_stats.mac_rx_oversize_pkt_num;
- net_stats->rx_errors += hw_stats->mac_stats.mac_rx_undersize_pkt_num;
- net_stats->rx_errors += hw_stats->mac_stats.mac_rx_fcs_err_pkt_num;
-
- net_stats->multicast = hw_stats->mac_stats.mac_tx_multi_pkt_num;
- net_stats->multicast += hw_stats->mac_stats.mac_rx_multi_pkt_num;
-
- net_stats->rx_crc_errors = hw_stats->mac_stats.mac_rx_fcs_err_pkt_num;
- net_stats->rx_length_errors =
- hw_stats->mac_stats.mac_rx_undersize_pkt_num;
- net_stats->rx_length_errors +=
- hw_stats->mac_stats.mac_rx_oversize_pkt_num;
- net_stats->rx_over_errors =
- hw_stats->mac_stats.mac_rx_oversize_pkt_num;
-}
-
static void hclge_update_stats_for_all(struct hclge_dev *hdev)
{
struct hnae3_handle *handle;
@@ -500,8 +577,6 @@ static void hclge_update_stats_for_all(struct hclge_dev *hdev)
if (status)
dev_err(&hdev->pdev->dev,
"Update MAC stats fail, status = %d.\n", status);
-
- hclge_update_netstat(&hdev->hw_stats, &handle->kinfo.netdev->stats);
}
static void hclge_update_stats(struct hnae3_handle *handle,
@@ -509,7 +584,6 @@ static void hclge_update_stats(struct hnae3_handle *handle,
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- struct hclge_hw_stats *hw_stats = &hdev->hw_stats;
int status;
if (test_and_set_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state))
@@ -527,8 +601,6 @@ static void hclge_update_stats(struct hnae3_handle *handle,
"Update TQPS stats fail, status = %d.\n",
status);
- hclge_update_netstat(hw_stats, net_stats);
-
clear_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state);
}
@@ -767,37 +839,67 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev,
unsigned long *supported = hdev->hw.mac.supported;
if (speed_ability & HCLGE_SUPPORT_1G_BIT)
- set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_10G_BIT)
- set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_25G_BIT)
- set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_50G_BIT)
- set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_100G_BIT)
- set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+ supported);
+
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
+}
+
+static void hclge_parse_copper_link_mode(struct hclge_dev *hdev,
+ u8 speed_ability)
+{
+ unsigned long *supported = hdev->hw.mac.supported;
+
+ /* default to support all speed for GE port */
+ if (!speed_ability)
+ speed_ability = HCLGE_SUPPORT_GE;
+
+ if (speed_ability & HCLGE_SUPPORT_1G_BIT)
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ supported);
+
+ if (speed_ability & HCLGE_SUPPORT_100M_BIT) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ supported);
+ }
+
+ if (speed_ability & HCLGE_SUPPORT_10M_BIT) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported);
+ }
- set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
- set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
}
static void hclge_parse_link_mode(struct hclge_dev *hdev, u8 speed_ability)
{
u8 media_type = hdev->hw.mac.media_type;
- if (media_type != HNAE3_MEDIA_TYPE_FIBER)
- return;
-
- hclge_parse_fiber_link_mode(hdev, speed_ability);
+ if (media_type == HNAE3_MEDIA_TYPE_FIBER)
+ hclge_parse_fiber_link_mode(hdev, speed_ability);
+ else if (media_type == HNAE3_MEDIA_TYPE_COPPER)
+ hclge_parse_copper_link_mode(hdev, speed_ability);
}
static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
@@ -931,12 +1033,16 @@ static int hclge_configure(struct hclge_dev *hdev)
ether_addr_copy(hdev->hw.mac.mac_addr, cfg.mac_addr);
hdev->hw.mac.media_type = cfg.media_type;
hdev->hw.mac.phy_addr = cfg.phy_addr;
- hdev->num_desc = cfg.tqp_desc_num;
+ hdev->num_tx_desc = cfg.tqp_desc_num;
+ hdev->num_rx_desc = cfg.tqp_desc_num;
hdev->tm_info.num_pg = 1;
hdev->tc_max = cfg.tc_num;
hdev->tm_info.hw_pfc_map = 0;
hdev->wanted_umv_size = cfg.umv_space;
+ if (hnae3_dev_fd_supported(hdev))
+ hdev->fd_en = true;
+
ret = hclge_parse_speed(cfg.default_speed, &hdev->hw.mac.speed);
if (ret) {
dev_err(&hdev->pdev->dev, "Get wrong speed ret=%d.\n", ret);
@@ -1035,7 +1141,8 @@ static int hclge_alloc_tqps(struct hclge_dev *hdev)
tqp->q.ae_algo = &ae_algo;
tqp->q.buf_size = hdev->rx_buf_len;
- tqp->q.desc_num = hdev->num_desc;
+ tqp->q.tx_desc_num = hdev->num_tx_desc;
+ tqp->q.rx_desc_num = hdev->num_rx_desc;
tqp->q.io_base = hdev->hw.io_base + HCLGE_TQP_REG_OFFSET +
i * HCLGE_TQP_REG_SIZE;
@@ -1068,64 +1175,51 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id,
return ret;
}
-static int hclge_assign_tqp(struct hclge_vport *vport)
+static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps)
{
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
struct hclge_dev *hdev = vport->back;
int i, alloced;
for (i = 0, alloced = 0; i < hdev->num_tqps &&
- alloced < kinfo->num_tqps; i++) {
+ alloced < num_tqps; i++) {
if (!hdev->htqp[i].alloced) {
hdev->htqp[i].q.handle = &vport->nic;
hdev->htqp[i].q.tqp_index = alloced;
- hdev->htqp[i].q.desc_num = kinfo->num_desc;
+ hdev->htqp[i].q.tx_desc_num = kinfo->num_tx_desc;
+ hdev->htqp[i].q.rx_desc_num = kinfo->num_rx_desc;
kinfo->tqp[alloced] = &hdev->htqp[i].q;
hdev->htqp[i].alloced = true;
alloced++;
}
}
- vport->alloc_tqps = kinfo->num_tqps;
+ vport->alloc_tqps = alloced;
+ kinfo->rss_size = min_t(u16, hdev->rss_size_max,
+ vport->alloc_tqps / hdev->tm_info.num_tc);
return 0;
}
-static int hclge_knic_setup(struct hclge_vport *vport,
- u16 num_tqps, u16 num_desc)
+static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps,
+ u16 num_tx_desc, u16 num_rx_desc)
+
{
struct hnae3_handle *nic = &vport->nic;
struct hnae3_knic_private_info *kinfo = &nic->kinfo;
struct hclge_dev *hdev = vport->back;
- int i, ret;
+ int ret;
- kinfo->num_desc = num_desc;
- kinfo->rx_buf_len = hdev->rx_buf_len;
- kinfo->num_tc = min_t(u16, num_tqps, hdev->tm_info.num_tc);
- kinfo->rss_size
- = min_t(u16, hdev->rss_size_max, num_tqps / kinfo->num_tc);
- kinfo->num_tqps = kinfo->rss_size * kinfo->num_tc;
+ kinfo->num_tx_desc = num_tx_desc;
+ kinfo->num_rx_desc = num_rx_desc;
- for (i = 0; i < HNAE3_MAX_TC; i++) {
- if (hdev->hw_tc_map & BIT(i)) {
- kinfo->tc_info[i].enable = true;
- kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
- kinfo->tc_info[i].tqp_count = kinfo->rss_size;
- kinfo->tc_info[i].tc = i;
- } else {
- /* Set to default queue if TC is disable */
- kinfo->tc_info[i].enable = false;
- kinfo->tc_info[i].tqp_offset = 0;
- kinfo->tc_info[i].tqp_count = 1;
- kinfo->tc_info[i].tc = 0;
- }
- }
+ kinfo->rx_buf_len = hdev->rx_buf_len;
- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
+ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, num_tqps,
sizeof(struct hnae3_queue *), GFP_KERNEL);
if (!kinfo->tqp)
return -ENOMEM;
- ret = hclge_assign_tqp(vport);
+ ret = hclge_assign_tqp(vport, num_tqps);
if (ret)
dev_err(&hdev->pdev->dev, "fail to assign TQPs %d.\n", ret);
@@ -1140,7 +1234,7 @@ static int hclge_map_tqp_to_vport(struct hclge_dev *hdev,
u16 i;
kinfo = &nic->kinfo;
- for (i = 0; i < kinfo->num_tqps; i++) {
+ for (i = 0; i < vport->alloc_tqps; i++) {
struct hclge_tqp *q =
container_of(kinfo->tqp[i], struct hclge_tqp, q);
bool is_pf;
@@ -1191,7 +1285,9 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps)
nic->numa_node_mask = hdev->numa_node_mask;
if (hdev->ae_dev->dev_type == HNAE3_DEV_KNIC) {
- ret = hclge_knic_setup(vport, num_tqps, hdev->num_desc);
+ ret = hclge_knic_setup(vport, num_tqps,
+ hdev->num_tx_desc, hdev->num_rx_desc);
+
if (ret) {
dev_err(&hdev->pdev->dev, "knic setup failed %d\n",
ret);
@@ -1241,6 +1337,9 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
vport->back = hdev;
vport->vport_id = i;
vport->mps = HCLGE_MAC_DEFAULT_FRAME;
+ INIT_LIST_HEAD(&vport->vlan_list);
+ INIT_LIST_HEAD(&vport->uc_mac_list);
+ INIT_LIST_HEAD(&vport->mc_mac_list);
if (i == 0)
ret = hclge_vport_setup(vport, tqp_main_vport);
@@ -1273,7 +1372,7 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev,
req = (struct hclge_tx_buff_alloc_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
- for (i = 0; i < HCLGE_TC_NUM; i++) {
+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
u32 buf_size = buf_alloc->priv_buf[i].tx_buf_size;
req->tx_pkt_buff[i] =
@@ -1448,13 +1547,14 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev,
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i];
- if (total_size < hdev->tx_buf_size)
- return -ENOMEM;
+ if (hdev->hw_tc_map & BIT(i)) {
+ if (total_size < hdev->tx_buf_size)
+ return -ENOMEM;
- if (hdev->hw_tc_map & BIT(i))
priv->tx_buf_size = hdev->tx_buf_size;
- else
+ } else {
priv->tx_buf_size = 0;
+ }
total_size -= priv->tx_buf_size;
}
@@ -1462,66 +1562,15 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev,
return 0;
}
-/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs
- * @hdev: pointer to struct hclge_dev
- * @buf_alloc: pointer to buffer calculation data
- * @return: 0: calculate sucessful, negative: fail
- */
-static int hclge_rx_buffer_calc(struct hclge_dev *hdev,
- struct hclge_pkt_buf_alloc *buf_alloc)
+static bool hclge_rx_buf_calc_all(struct hclge_dev *hdev, bool max,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
- u32 rx_all = hdev->pkt_buf_size, aligned_mps;
- int no_pfc_priv_num, pfc_priv_num;
- struct hclge_priv_buf *priv;
+ u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc);
+ u32 aligned_mps = round_up(hdev->mps, HCLGE_BUF_SIZE_UNIT);
int i;
- aligned_mps = round_up(hdev->mps, HCLGE_BUF_SIZE_UNIT);
- rx_all -= hclge_get_tx_buff_alloced(buf_alloc);
-
- /* When DCB is not supported, rx private
- * buffer is not allocated.
- */
- if (!hnae3_dev_dcb_supported(hdev)) {
- if (!hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
- return -ENOMEM;
-
- return 0;
- }
-
- /* step 1, try to alloc private buffer for all enabled tc */
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &buf_alloc->priv_buf[i];
- if (hdev->hw_tc_map & BIT(i)) {
- priv->enable = 1;
- if (hdev->tm_info.hw_pfc_map & BIT(i)) {
- priv->wl.low = aligned_mps;
- priv->wl.high =
- roundup(priv->wl.low + aligned_mps,
- HCLGE_BUF_SIZE_UNIT);
- priv->buf_size = priv->wl.high +
- hdev->dv_buf_size;
- } else {
- priv->wl.low = 0;
- priv->wl.high = 2 * aligned_mps;
- priv->buf_size = priv->wl.high +
- hdev->dv_buf_size;
- }
- } else {
- priv->enable = 0;
- priv->wl.low = 0;
- priv->wl.high = 0;
- priv->buf_size = 0;
- }
- }
-
- if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
- return 0;
-
- /* step 2, try to decrease the buffer size of
- * no pfc TC's private buffer
- */
- for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &buf_alloc->priv_buf[i];
+ struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i];
priv->enable = 0;
priv->wl.low = 0;
@@ -1534,28 +1583,30 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev,
priv->enable = 1;
if (hdev->tm_info.hw_pfc_map & BIT(i)) {
- priv->wl.low = 256;
- priv->wl.high = priv->wl.low + aligned_mps;
- priv->buf_size = priv->wl.high + hdev->dv_buf_size;
+ priv->wl.low = max ? aligned_mps : 256;
+ priv->wl.high = roundup(priv->wl.low + aligned_mps,
+ HCLGE_BUF_SIZE_UNIT);
} else {
priv->wl.low = 0;
- priv->wl.high = aligned_mps;
- priv->buf_size = priv->wl.high + hdev->dv_buf_size;
+ priv->wl.high = max ? (aligned_mps * 2) : aligned_mps;
}
+
+ priv->buf_size = priv->wl.high + hdev->dv_buf_size;
}
- if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
- return 0;
+ return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all);
+}
- /* step 3, try to reduce the number of pfc disabled TCs,
- * which have private buffer
- */
- /* get the total no pfc enable TC number, which have private buffer */
- no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev, buf_alloc);
+static bool hclge_drop_nopfc_buf_till_fit(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
+{
+ u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc);
+ int no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev, buf_alloc);
+ int i;
/* let the last to be cleared first */
for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) {
- priv = &buf_alloc->priv_buf[i];
+ struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i) &&
!(hdev->tm_info.hw_pfc_map & BIT(i))) {
@@ -1572,17 +1623,19 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev,
break;
}
- if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
- return 0;
+ return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all);
+}
- /* step 4, try to reduce the number of pfc enabled TCs
- * which have private buffer.
- */
- pfc_priv_num = hclge_get_pfc_priv_num(hdev, buf_alloc);
+static bool hclge_drop_pfc_buf_till_fit(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
+{
+ u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc);
+ int pfc_priv_num = hclge_get_pfc_priv_num(hdev, buf_alloc);
+ int i;
/* let the last to be cleared first */
for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) {
- priv = &buf_alloc->priv_buf[i];
+ struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i) &&
hdev->tm_info.hw_pfc_map & BIT(i)) {
@@ -1598,7 +1651,40 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev,
pfc_priv_num == 0)
break;
}
- if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
+
+ return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all);
+}
+
+/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs
+ * @hdev: pointer to struct hclge_dev
+ * @buf_alloc: pointer to buffer calculation data
+ * @return: 0: calculate sucessful, negative: fail
+ */
+static int hclge_rx_buffer_calc(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
+{
+ /* When DCB is not supported, rx private buffer is not allocated. */
+ if (!hnae3_dev_dcb_supported(hdev)) {
+ u32 rx_all = hdev->pkt_buf_size;
+
+ rx_all -= hclge_get_tx_buff_alloced(buf_alloc);
+ if (!hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ if (hclge_rx_buf_calc_all(hdev, true, buf_alloc))
+ return 0;
+
+ /* try to decrease the buffer size */
+ if (hclge_rx_buf_calc_all(hdev, false, buf_alloc))
+ return 0;
+
+ if (hclge_drop_nopfc_buf_till_fit(hdev, buf_alloc))
+ return 0;
+
+ if (hclge_drop_pfc_buf_till_fit(hdev, buf_alloc))
return 0;
return -ENOMEM;
@@ -2122,7 +2208,9 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev)
static void hclge_update_link_status(struct hclge_dev *hdev)
{
+ struct hnae3_client *rclient = hdev->roce_client;
struct hnae3_client *client = hdev->nic_client;
+ struct hnae3_handle *rhandle;
struct hnae3_handle *handle;
int state;
int i;
@@ -2134,6 +2222,10 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
handle = &hdev->vport[i].nic;
client->ops->link_status_change(handle, state);
+ rhandle = &hdev->vport[i].roce;
+ if (rclient && rclient->ops->link_status_change)
+ rclient->ops->link_status_change(rhandle,
+ state);
}
hdev->hw.mac.link = state;
}
@@ -2418,8 +2510,8 @@ static void hclge_misc_irq_uninit(struct hclge_dev *hdev)
hclge_free_vector(hdev, 0);
}
-static int hclge_notify_client(struct hclge_dev *hdev,
- enum hnae3_reset_notify_type type)
+int hclge_notify_client(struct hclge_dev *hdev,
+ enum hnae3_reset_notify_type type)
{
struct hnae3_client *client = hdev->nic_client;
u16 i;
@@ -2548,7 +2640,7 @@ static int hclge_set_vf_rst(struct hclge_dev *hdev, int func_id, bool reset)
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
-int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
+static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
{
int i;
@@ -2883,6 +2975,10 @@ static void hclge_reset(struct hclge_dev *hdev)
if (ret)
goto err_reset_lock;
+ ret = hclge_notify_client(hdev, HNAE3_RESTORE_CLIENT);
+ if (ret)
+ goto err_reset_lock;
+
hclge_clear_reset_cause(hdev);
ret = hclge_reset_prepare_up(hdev);
@@ -3597,8 +3693,11 @@ void hclge_rss_indir_init_cfg(struct hclge_dev *hdev)
static void hclge_rss_init_cfg(struct hclge_dev *hdev)
{
+ int i, rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
struct hclge_vport *vport = hdev->vport;
- int i;
+
+ if (hdev->pdev->revision >= 0x21)
+ rss_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
vport[i].rss_tuple_sets.ipv4_tcp_en =
@@ -3618,9 +3717,10 @@ static void hclge_rss_init_cfg(struct hclge_dev *hdev)
vport[i].rss_tuple_sets.ipv6_fragment_en =
HCLGE_RSS_INPUT_TUPLE_OTHER;
- vport[i].rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
+ vport[i].rss_algo = rss_algo;
- netdev_rss_key_fill(vport[i].rss_hash_key, HCLGE_RSS_KEY_SIZE);
+ memcpy(vport[i].rss_hash_key, hclge_hash_key,
+ HCLGE_RSS_KEY_SIZE);
}
hclge_rss_indir_init_cfg(hdev);
@@ -3788,8 +3888,16 @@ static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_promisc_param param;
+ bool en_bc_pmc = true;
- hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, true,
+ /* For revision 0x20, if broadcast promisc enabled, vlan filter is
+ * always bypassed. So broadcast promisc should be disabled until
+ * user enable promisc mode
+ */
+ if (handle->pdev->revision == 0x20)
+ en_bc_pmc = handle->netdev_flags & HNAE3_BPE ? true : false;
+
+ hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, en_bc_pmc,
vport->vport_id);
return hclge_cmd_set_promisc_mode(hdev, &param);
}
@@ -3898,7 +4006,6 @@ static int hclge_init_fd_config(struct hclge_dev *hdev)
return -EOPNOTSUPP;
}
- hdev->fd_cfg.fd_en = true;
hdev->fd_cfg.proto_support =
TCP_V4_FLOW | UDP_V4_FLOW | SCTP_V4_FLOW | TCP_V6_FLOW |
UDP_V6_FLOW | SCTP_V6_FLOW | IPV4_USER_FLOW | IPV6_USER_FLOW;
@@ -4656,7 +4763,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
if (!hnae3_dev_fd_supported(hdev))
return -EOPNOTSUPP;
- if (!hdev->fd_cfg.fd_en) {
+ if (!hdev->fd_en) {
dev_warn(&hdev->pdev->dev,
"Please enable flow director first\n");
return -EOPNOTSUPP;
@@ -4809,7 +4916,7 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
return 0;
/* if fd is disabled, should not restore it when reset */
- if (!hdev->fd_cfg.fd_en)
+ if (!hdev->fd_en)
return 0;
hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) {
@@ -5095,7 +5202,7 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- hdev->fd_cfg.fd_en = enable;
+ hdev->fd_en = enable;
if (!enable)
hclge_del_all_fd_entries(handle, false);
else
@@ -5174,8 +5281,15 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
{
#define HCLGE_SERDES_RETRY_MS 10
#define HCLGE_SERDES_RETRY_NUM 100
+
+#define HCLGE_MAC_LINK_STATUS_MS 20
+#define HCLGE_MAC_LINK_STATUS_NUM 10
+#define HCLGE_MAC_LINK_STATUS_DOWN 0
+#define HCLGE_MAC_LINK_STATUS_UP 1
+
struct hclge_serdes_lb_cmd *req;
struct hclge_desc desc;
+ int mac_link_ret = 0;
int ret, i = 0;
u8 loop_mode_b;
@@ -5198,8 +5312,10 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
if (en) {
req->enable = loop_mode_b;
req->mask = loop_mode_b;
+ mac_link_ret = HCLGE_MAC_LINK_STATUS_UP;
} else {
req->mask = loop_mode_b;
+ mac_link_ret = HCLGE_MAC_LINK_STATUS_DOWN;
}
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -5231,7 +5347,19 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
}
hclge_cfg_mac_mode(hdev, en);
- return 0;
+
+ i = 0;
+ do {
+ /* serdes Internal loopback, independent of the network cable.*/
+ msleep(HCLGE_MAC_LINK_STATUS_MS);
+ ret = hclge_get_mac_link_status(hdev);
+ if (ret == mac_link_ret)
+ return 0;
+ } while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+
+ dev_err(&hdev->pdev->dev, "config mac mode timeout\n");
+
+ return -EBUSY;
}
static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id,
@@ -5258,6 +5386,7 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
enum hnae3_loop loop_mode, bool en)
{
struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hnae3_knic_private_info *kinfo;
struct hclge_dev *hdev = vport->back;
int i, ret;
@@ -5276,7 +5405,11 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
break;
}
- for (i = 0; i < vport->alloc_tqps; i++) {
+ if (ret)
+ return ret;
+
+ kinfo = &vport->nic.kinfo;
+ for (i = 0; i < kinfo->num_tqps; i++) {
ret = hclge_tqp_enable(hdev, i, 0, en);
if (ret)
return ret;
@@ -5288,11 +5421,13 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
static void hclge_reset_tqp_stats(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hnae3_knic_private_info *kinfo;
struct hnae3_queue *queue;
struct hclge_tqp *tqp;
int i;
- for (i = 0; i < vport->alloc_tqps; i++) {
+ kinfo = &vport->nic.kinfo;
+ for (i = 0; i < kinfo->num_tqps; i++) {
queue = handle->kinfo.tqp[i];
tqp = container_of(queue, struct hclge_tqp, q);
memset(&tqp->tqp_stats, 0, sizeof(tqp->tqp_stats));
@@ -5493,13 +5628,19 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc)
}
static void hclge_prepare_mac_addr(struct hclge_mac_vlan_tbl_entry_cmd *new_req,
- const u8 *addr)
+ const u8 *addr, bool is_mc)
{
const unsigned char *mac_addr = addr;
u32 high_val = mac_addr[2] << 16 | (mac_addr[3] << 24) |
(mac_addr[0]) | (mac_addr[1] << 8);
u32 low_val = mac_addr[4] | (mac_addr[5] << 8);
+ hnae3_set_bit(new_req->flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
+ if (is_mc) {
+ hnae3_set_bit(new_req->entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1);
+ hnae3_set_bit(new_req->mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
+ }
+
new_req->mac_addr_hi32 = cpu_to_le32(high_val);
new_req->mac_addr_lo16 = cpu_to_le16(low_val & 0xffff);
}
@@ -5730,9 +5871,12 @@ static void hclge_update_umv_space(struct hclge_vport *vport, bool is_free)
if (is_free) {
if (vport->used_umv_num > hdev->priv_umv_size)
hdev->share_umv_size++;
- vport->used_umv_num--;
+
+ if (vport->used_umv_num > 0)
+ vport->used_umv_num--;
} else {
- if (vport->used_umv_num >= hdev->priv_umv_size)
+ if (vport->used_umv_num >= hdev->priv_umv_size &&
+ hdev->share_umv_size > 0)
hdev->share_umv_size--;
vport->used_umv_num++;
}
@@ -5770,14 +5914,13 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport,
}
memset(&req, 0, sizeof(req));
- hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
hnae3_set_field(egress_port, HCLGE_MAC_EPORT_VFID_M,
HCLGE_MAC_EPORT_VFID_S, vport->vport_id);
req.egress_port = cpu_to_le16(egress_port);
- hclge_prepare_mac_addr(&req, addr);
+ hclge_prepare_mac_addr(&req, addr, false);
/* Lookup the mac address in the mac_vlan table, and add
* it if the entry is inexistent. Repeated unicast entry
@@ -5835,9 +5978,8 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport,
}
memset(&req, 0, sizeof(req));
- hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
- hclge_prepare_mac_addr(&req, addr);
+ hclge_prepare_mac_addr(&req, addr, false);
ret = hclge_remove_mac_vlan_tbl(vport, &req);
if (!ret)
hclge_update_umv_space(vport, true);
@@ -5869,11 +6011,8 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport,
return -EINVAL;
}
memset(&req, 0, sizeof(req));
- hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
- hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1);
- hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
- hclge_prepare_mac_addr(&req, addr);
+ hclge_prepare_mac_addr(&req, addr, true);
status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
if (!status) {
/* This mac addr exist, update VFID for it */
@@ -5919,11 +6058,8 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
}
memset(&req, 0, sizeof(req));
- hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
- hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1);
- hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
- hclge_prepare_mac_addr(&req, addr);
+ hclge_prepare_mac_addr(&req, addr, true);
status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
if (!status) {
/* This mac addr exist, remove this handle's VFID for it */
@@ -5949,6 +6085,103 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
return status;
}
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg;
+ struct list_head *list;
+
+ if (!vport->vport_id)
+ return;
+
+ mac_cfg = kzalloc(sizeof(*mac_cfg), GFP_KERNEL);
+ if (!mac_cfg)
+ return;
+
+ mac_cfg->hd_tbl_status = true;
+ memcpy(mac_cfg->mac_addr, mac_addr, ETH_ALEN);
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ list_add_tail(&mac_cfg->node, list);
+}
+
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ bool is_write_tbl,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+ struct list_head *list;
+ bool uc_flag, mc_flag;
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ uc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_UC;
+ mc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_MC;
+
+ list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+ if (strncmp(mac_cfg->mac_addr, mac_addr, ETH_ALEN) == 0) {
+ if (uc_flag && mac_cfg->hd_tbl_status)
+ hclge_rm_uc_addr_common(vport, mac_addr);
+
+ if (mc_flag && mac_cfg->hd_tbl_status)
+ hclge_rm_mc_addr_common(vport, mac_addr);
+
+ list_del(&mac_cfg->node);
+ kfree(mac_cfg);
+ break;
+ }
+ }
+}
+
+void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+ struct list_head *list;
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+ if (mac_type == HCLGE_MAC_ADDR_UC && mac_cfg->hd_tbl_status)
+ hclge_rm_uc_addr_common(vport, mac_cfg->mac_addr);
+
+ if (mac_type == HCLGE_MAC_ADDR_MC && mac_cfg->hd_tbl_status)
+ hclge_rm_mc_addr_common(vport, mac_cfg->mac_addr);
+
+ mac_cfg->hd_tbl_status = false;
+ if (is_del_list) {
+ list_del(&mac_cfg->node);
+ kfree(mac_cfg);
+ }
+ }
+}
+
+void hclge_uninit_vport_mac_table(struct hclge_dev *hdev)
+{
+ struct hclge_vport_mac_addr_cfg *mac, *tmp;
+ struct hclge_vport *vport;
+ int i;
+
+ mutex_lock(&hdev->vport_cfg_mutex);
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ vport = &hdev->vport[i];
+ list_for_each_entry_safe(mac, tmp, &vport->uc_mac_list, node) {
+ list_del(&mac->node);
+ kfree(mac);
+ }
+
+ list_for_each_entry_safe(mac, tmp, &vport->mc_mac_list, node) {
+ list_del(&mac->node);
+ kfree(mac);
+ }
+ }
+ mutex_unlock(&hdev->vport_cfg_mutex);
+}
+
static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
u16 cmdq_resp, u8 resp_code)
{
@@ -6104,7 +6337,7 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr,
}
static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type,
- u8 fe_type, bool filter_en)
+ u8 fe_type, bool filter_en, u8 vf_id)
{
struct hclge_vlan_filter_ctrl_cmd *req;
struct hclge_desc desc;
@@ -6115,6 +6348,7 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type,
req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data;
req->vlan_type = vlan_type;
req->vlan_fe = filter_en ? fe_type : 0;
+ req->vf_id = vf_id;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
@@ -6143,12 +6377,13 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
if (hdev->pdev->revision >= 0x21) {
hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
- HCLGE_FILTER_FE_EGRESS, enable);
+ HCLGE_FILTER_FE_EGRESS, enable, 0);
hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT,
- HCLGE_FILTER_FE_INGRESS, enable);
+ HCLGE_FILTER_FE_INGRESS, enable, 0);
} else {
hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
- HCLGE_FILTER_FE_EGRESS_V1_B, enable);
+ HCLGE_FILTER_FE_EGRESS_V1_B, enable,
+ 0);
}
if (enable)
handle->netdev_flags |= HNAE3_VLAN_FLTR;
@@ -6456,19 +6691,27 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
int i;
if (hdev->pdev->revision >= 0x21) {
- ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
- HCLGE_FILTER_FE_EGRESS, true);
- if (ret)
- return ret;
+ /* for revision 0x21, vf vlan filter is per function */
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ vport = &hdev->vport[i];
+ ret = hclge_set_vlan_filter_ctrl(hdev,
+ HCLGE_FILTER_TYPE_VF,
+ HCLGE_FILTER_FE_EGRESS,
+ true,
+ vport->vport_id);
+ if (ret)
+ return ret;
+ }
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT,
- HCLGE_FILTER_FE_INGRESS, true);
+ HCLGE_FILTER_FE_INGRESS, true,
+ 0);
if (ret)
return ret;
} else {
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
HCLGE_FILTER_FE_EGRESS_V1_B,
- true);
+ true, 0);
if (ret)
return ret;
}
@@ -6522,6 +6765,84 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
}
+void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id)
+{
+ struct hclge_vport_vlan_cfg *vlan;
+
+ /* vlan 0 is reserved */
+ if (!vlan_id)
+ return;
+
+ vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
+ if (!vlan)
+ return;
+
+ vlan->hd_tbl_status = true;
+ vlan->vlan_id = vlan_id;
+
+ list_add_tail(&vlan->node, &vport->vlan_list);
+}
+
+void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+ bool is_write_tbl)
+{
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
+ struct hclge_dev *hdev = vport->back;
+
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ if (vlan->vlan_id == vlan_id) {
+ if (is_write_tbl && vlan->hd_tbl_status)
+ hclge_set_vlan_filter_hw(hdev,
+ htons(ETH_P_8021Q),
+ vport->vport_id,
+ vlan_id, 0,
+ true);
+
+ list_del(&vlan->node);
+ kfree(vlan);
+ break;
+ }
+ }
+}
+
+void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
+{
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
+ struct hclge_dev *hdev = vport->back;
+
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ if (vlan->hd_tbl_status)
+ hclge_set_vlan_filter_hw(hdev,
+ htons(ETH_P_8021Q),
+ vport->vport_id,
+ vlan->vlan_id, 0,
+ true);
+
+ vlan->hd_tbl_status = false;
+ if (is_del_list) {
+ list_del(&vlan->node);
+ kfree(vlan);
+ }
+ }
+}
+
+void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
+{
+ struct hclge_vport_vlan_cfg *vlan, *tmp;
+ struct hclge_vport *vport;
+ int i;
+
+ mutex_lock(&hdev->vport_cfg_mutex);
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ vport = &hdev->vport[i];
+ list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+ list_del(&vlan->node);
+ kfree(vlan);
+ }
+ }
+ mutex_unlock(&hdev->vport_cfg_mutex);
+}
+
int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
@@ -6959,16 +7280,6 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle,
*tp_mdix = ETH_TP_MDI;
}
-static int hclge_init_instance_hw(struct hclge_dev *hdev)
-{
- return hclge_mac_connect_phy(hdev);
-}
-
-static void hclge_uninit_instance_hw(struct hclge_dev *hdev)
-{
- hclge_mac_disconnect_phy(hdev);
-}
-
static int hclge_init_client_instance(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev)
{
@@ -6988,13 +7299,6 @@ static int hclge_init_client_instance(struct hnae3_client *client,
if (ret)
goto clear_nic;
- ret = hclge_init_instance_hw(hdev);
- if (ret) {
- client->ops->uninit_instance(&vport->nic,
- 0);
- goto clear_nic;
- }
-
hnae3_set_client_init_flag(client, ae_dev, 1);
if (hdev->roce_client &&
@@ -7079,7 +7383,6 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
if (client->type == HNAE3_CLIENT_ROCE)
return;
if (hdev->nic_client && client->ops->uninit_instance) {
- hclge_uninit_instance_hw(hdev);
client->ops->uninit_instance(&vport->nic, 0);
hdev->nic_client = NULL;
vport->nic.client = NULL;
@@ -7222,6 +7525,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
mutex_init(&hdev->vport_lock);
+ mutex_init(&hdev->vport_cfg_mutex);
ret = hclge_pci_init(hdev);
if (ret) {
@@ -7298,7 +7602,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
ret = hclge_init_umv_space(hdev);
if (ret) {
dev_err(&pdev->dev, "umv space init error, ret=%d.\n", ret);
- goto err_msi_irq_uninit;
+ goto err_mdiobus_unreg;
}
ret = hclge_mac_init(hdev);
@@ -7383,7 +7687,7 @@ err_msi_irq_uninit:
err_msi_uninit:
pci_free_irq_vectors(pdev);
err_cmd_uninit:
- hclge_destroy_cmd_queue(&hdev->hw);
+ hclge_cmd_uninit(hdev);
err_pci_uninit:
pcim_iounmap(pdev, hdev->hw.io_base);
pci_clear_master(pdev);
@@ -7456,7 +7760,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
return ret;
}
- ret = hclge_tm_init_hw(hdev);
+ ret = hclge_tm_init_hw(hdev, true);
if (ret) {
dev_err(&pdev->dev, "tm init hw fail, ret =%d\n", ret);
return ret;
@@ -7510,10 +7814,13 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
synchronize_irq(hdev->misc_vector.vector_irq);
hclge_hw_error_set_state(hdev, false);
- hclge_destroy_cmd_queue(&hdev->hw);
+ hclge_cmd_uninit(hdev);
hclge_misc_irq_uninit(hdev);
hclge_pci_uninit(hdev);
mutex_destroy(&hdev->vport_lock);
+ hclge_uninit_vport_mac_table(hdev);
+ hclge_uninit_vport_vlan_table(hdev);
+ mutex_destroy(&hdev->vport_cfg_mutex);
ae_dev->priv = NULL;
}
@@ -7523,18 +7830,17 @@ static u32 hclge_get_max_channels(struct hnae3_handle *handle)
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- return min_t(u32, hdev->rss_size_max * kinfo->num_tc, hdev->num_tqps);
+ return min_t(u32, hdev->rss_size_max,
+ vport->alloc_tqps / kinfo->num_tc);
}
static void hclge_get_channels(struct hnae3_handle *handle,
struct ethtool_channels *ch)
{
- struct hclge_vport *vport = hclge_get_vport(handle);
-
ch->max_combined = hclge_get_max_channels(handle);
ch->other_count = 1;
ch->max_other = 1;
- ch->combined_count = vport->alloc_tqps;
+ ch->combined_count = handle->kinfo.rss_size;
}
static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle,
@@ -7547,26 +7853,8 @@ static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle,
*max_rss_size = hdev->rss_size_max;
}
-static void hclge_release_tqp(struct hclge_vport *vport)
-{
- struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
- struct hclge_dev *hdev = vport->back;
- int i;
-
- for (i = 0; i < kinfo->num_tqps; i++) {
- struct hclge_tqp *tqp =
- container_of(kinfo->tqp[i], struct hclge_tqp, q);
-
- tqp->q.handle = NULL;
- tqp->q.tqp_index = 0;
- tqp->alloced = false;
- }
-
- devm_kfree(&hdev->pdev->dev, kinfo->tqp);
- kinfo->tqp = NULL;
-}
-
-static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
+static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
+ bool rxfh_configured)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
@@ -7580,24 +7868,11 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
u32 *rss_indir;
int ret, i;
- /* Free old tqps, and reallocate with new tqp number when nic setup */
- hclge_release_tqp(vport);
-
- ret = hclge_knic_setup(vport, new_tqps_num, kinfo->num_desc);
- if (ret) {
- dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret);
- return ret;
- }
-
- ret = hclge_map_tqp_to_vport(hdev, vport);
- if (ret) {
- dev_err(&hdev->pdev->dev, "map vport tqp fail, ret =%d\n", ret);
- return ret;
- }
+ kinfo->req_rss_size = new_tqps_num;
- ret = hclge_tm_schd_init(hdev);
+ ret = hclge_tm_vport_map_update(hdev);
if (ret) {
- dev_err(&hdev->pdev->dev, "tm schd init fail, ret =%d\n", ret);
+ dev_err(&hdev->pdev->dev, "tm vport map fail, ret =%d\n", ret);
return ret;
}
@@ -7618,6 +7893,10 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
if (ret)
return ret;
+ /* RSS indirection table has been configuared by user */
+ if (rxfh_configured)
+ goto out;
+
/* Reinitializes the rss indirect table according to the new RSS size */
rss_indir = kcalloc(HCLGE_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL);
if (!rss_indir)
@@ -7633,6 +7912,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
kfree(rss_indir);
+out:
if (!ret)
dev_info(&hdev->pdev->dev,
"Channels changed, rss_size from %d to %d, tqps from %d to %d",
@@ -7927,7 +8207,7 @@ static void hclge_get_link_mode(struct hnae3_handle *handle,
}
}
-static int hclge_gro_en(struct hnae3_handle *handle, int enable)
+static int hclge_gro_en(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
@@ -8012,6 +8292,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.set_gro_en = hclge_gro_en,
.get_global_queue_id = hclge_covert_handle_qid_global,
.set_timer_task = hclge_set_timer_task,
+ .mac_connect_phy = hclge_mac_connect_phy,
+ .mac_disconnect_phy = hclge_mac_disconnect_phy,
};
static struct hnae3_ae_algo ae_algo = {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 6615b85a1c52..b57ac4beb313 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -16,6 +16,9 @@
#define HCLGE_MAX_PF_NUM 8
+#define HCLGE_RD_FIRST_STATS_NUM 2
+#define HCLGE_RD_OTHER_STATS_NUM 4
+
#define HCLGE_INVALID_VPORT 0xffff
#define HCLGE_PF_CFG_BLOCK_SIZE 32
@@ -185,6 +188,10 @@ enum HLCGE_PORT_TYPE {
#define HCLGE_SUPPORT_25G_BIT BIT(2)
#define HCLGE_SUPPORT_50G_BIT BIT(3)
#define HCLGE_SUPPORT_100G_BIT BIT(4)
+#define HCLGE_SUPPORT_100M_BIT BIT(6)
+#define HCLGE_SUPPORT_10M_BIT BIT(7)
+#define HCLGE_SUPPORT_GE \
+ (HCLGE_SUPPORT_1G_BIT | HCLGE_SUPPORT_100M_BIT | HCLGE_SUPPORT_10M_BIT)
enum HCLGE_DEV_STATE {
HCLGE_STATE_REINITING,
@@ -322,6 +329,7 @@ struct hclge_tm_info {
struct hclge_tc_info tc_info[HNAE3_MAX_TC];
enum hclge_fc_mode fc_mode;
u8 hw_pfc_map; /* Allow for packet drop or not on this TC */
+ u8 pfc_en; /* PFC enabled or not for user priority */
};
struct hclge_comm_stats_str {
@@ -415,6 +423,10 @@ struct hclge_mac_stats {
u64 mac_rx_fcs_err_pkt_num;
u64 mac_rx_send_app_good_pkt_num;
u64 mac_rx_send_app_bad_pkt_num;
+ u64 mac_tx_pfc_pause_pkt_num;
+ u64 mac_rx_pfc_pause_pkt_num;
+ u64 mac_tx_ctrl_pkt_num;
+ u64 mac_rx_ctrl_pkt_num;
};
#define HCLGE_STATS_TIMER_INTERVAL (60 * 5)
@@ -575,7 +587,6 @@ struct hclge_fd_key_cfg {
struct hclge_fd_cfg {
u8 fd_mode;
- u8 fd_en;
u16 max_key_length;
u32 proto_support;
u32 rule_num[2]; /* rule entry number */
@@ -621,6 +632,23 @@ struct hclge_fd_ad_data {
u16 rule_id;
};
+struct hclge_vport_mac_addr_cfg {
+ struct list_head node;
+ int hd_tbl_status;
+ u8 mac_addr[ETH_ALEN];
+};
+
+enum HCLGE_MAC_ADDR_TYPE {
+ HCLGE_MAC_ADDR_UC,
+ HCLGE_MAC_ADDR_MC
+};
+
+struct hclge_vport_vlan_cfg {
+ struct list_head node;
+ int hd_tbl_status;
+ u16 vlan_id;
+};
+
/* For each bit of TCAM entry, it uses a pair of 'x' and
* 'y' to indicate which value to match, like below:
* ----------------------------------
@@ -678,7 +706,8 @@ struct hclge_dev {
u16 num_alloc_vport; /* Num vports this driver supports */
u32 numa_node_mask;
u16 rx_buf_len;
- u16 num_desc;
+ u16 num_tx_desc; /* desc num of per tx queue */
+ u16 num_rx_desc; /* desc num of per rx queue */
u8 hw_tc_map;
u8 tc_num_last_time;
enum hclge_fc_mode fc_mode_last_time;
@@ -750,6 +779,7 @@ struct hclge_dev {
struct hclge_fd_cfg fd_cfg;
struct hlist_head fd_rule_list;
u16 hclge_fd_rule_num;
+ u8 fd_en;
u16 wanted_umv_size;
/* max available unicast mac vlan space */
@@ -759,6 +789,8 @@ struct hclge_dev {
/* unicast mac vlan space shared by PF and its VFs */
u16 share_umv_size;
struct mutex umv_mutex; /* protect share_umv_size */
+
+ struct mutex vport_cfg_mutex; /* Protect stored vf table */
};
/* VPort level vlan tag configuration for TX direction */
@@ -826,6 +858,10 @@ struct hclge_vport {
unsigned long state;
unsigned long last_active_jiffies;
u32 mps; /* Max packet size */
+
+ struct list_head uc_mac_list; /* Store VF unicast table */
+ struct list_head mc_mac_list; /* Store VF multicast table */
+ struct list_head vlan_list; /* Store VF vlan table */
};
void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
@@ -878,4 +914,19 @@ void hclge_vport_stop(struct hclge_vport *vport);
int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu);
int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf);
u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id);
+int hclge_notify_client(struct hclge_dev *hdev,
+ enum hnae3_reset_notify_type type);
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ bool is_write_tbl,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_uninit_vport_mac_table(struct hclge_dev *hdev);
+void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id);
+void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+ bool is_write_tbl);
+void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
+void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
index a1de451a85df..306a23e486de 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
@@ -203,12 +203,11 @@ static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en,
static int hclge_set_vf_promisc_mode(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *req)
{
- bool en_uc = req->msg[1] ? true : false;
- bool en_mc = req->msg[2] ? true : false;
+ bool en_bc = req->msg[1] ? true : false;
struct hclge_promisc_param param;
- /* always enable broadcast promisc bit */
- hclge_promisc_param_init(&param, en_uc, en_mc, true, vport->vport_id);
+ /* vf is not allowed to enable unicast/multicast broadcast */
+ hclge_promisc_param_init(&param, false, false, en_bc, vport->vport_id);
return hclge_cmd_set_promisc_mode(vport->back, &param);
}
@@ -225,12 +224,24 @@ static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport,
hclge_rm_uc_addr_common(vport, old_addr);
status = hclge_add_uc_addr_common(vport, mac_addr);
- if (status)
+ if (status) {
hclge_add_uc_addr_common(vport, old_addr);
+ } else {
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_UC);
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_UC);
+ }
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) {
status = hclge_add_uc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_UC);
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) {
status = hclge_rm_uc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_UC);
} else {
dev_err(&hdev->pdev->dev,
"failed to set unicast mac addr, unknown subcode %d\n",
@@ -256,8 +267,14 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport,
if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_ADD) {
status = hclge_add_mc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_MC);
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_REMOVE) {
status = hclge_rm_mc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_MC);
} else {
dev_err(&hdev->pdev->dev,
"failed to set mcast mac addr, unknown subcode %d\n",
@@ -288,6 +305,9 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
memcpy(&proto, &mbx_req->msg[5], sizeof(proto));
status = hclge_set_vlan_filter(handle, cpu_to_be16(proto),
vlan, is_kill);
+ if (!status)
+ is_kill ? hclge_rm_vport_vlan_table(vport, vlan, false)
+ : hclge_add_vport_vlan_table(vport, vlan);
} else if (mbx_req->msg[1] == HCLGE_MBX_VLAN_RX_OFF_CFG) {
struct hnae3_handle *handle = &vport->nic;
bool en = mbx_req->msg[2] ? true : false;
@@ -320,10 +340,14 @@ static int hclge_get_vf_tcinfo(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req,
bool gen_resp)
{
- struct hclge_dev *hdev = vport->back;
- int ret;
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ u8 vf_tc_map = 0;
+ int i, ret;
- ret = hclge_gen_resp_to_vf(vport, mbx_req, 0, &hdev->hw_tc_map,
+ for (i = 0; i < kinfo->num_tc; i++)
+ vf_tc_map |= BIT(i);
+
+ ret = hclge_gen_resp_to_vf(vport, mbx_req, 0, &vf_tc_map,
sizeof(u8));
return ret;
@@ -333,35 +357,52 @@ static int hclge_get_vf_queue_info(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req,
bool gen_resp)
{
-#define HCLGE_TQPS_RSS_INFO_LEN 8
+#define HCLGE_TQPS_RSS_INFO_LEN 6
u8 resp_data[HCLGE_TQPS_RSS_INFO_LEN];
struct hclge_dev *hdev = vport->back;
/* get the queue related info */
memcpy(&resp_data[0], &vport->alloc_tqps, sizeof(u16));
memcpy(&resp_data[2], &vport->nic.kinfo.rss_size, sizeof(u16));
- memcpy(&resp_data[4], &hdev->num_desc, sizeof(u16));
- memcpy(&resp_data[6], &hdev->rx_buf_len, sizeof(u16));
+ memcpy(&resp_data[4], &hdev->rx_buf_len, sizeof(u16));
return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data,
HCLGE_TQPS_RSS_INFO_LEN);
}
+static int hclge_get_vf_queue_depth(struct hclge_vport *vport,
+ struct hclge_mbx_vf_to_pf_cmd *mbx_req,
+ bool gen_resp)
+{
+#define HCLGE_TQPS_DEPTH_INFO_LEN 4
+ u8 resp_data[HCLGE_TQPS_DEPTH_INFO_LEN];
+ struct hclge_dev *hdev = vport->back;
+
+ /* get the queue depth info */
+ memcpy(&resp_data[0], &hdev->num_tx_desc, sizeof(u16));
+ memcpy(&resp_data[2], &hdev->num_rx_desc, sizeof(u16));
+ return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data,
+ HCLGE_TQPS_DEPTH_INFO_LEN);
+}
+
static int hclge_get_link_info(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
struct hclge_dev *hdev = vport->back;
u16 link_status;
- u8 msg_data[8];
+ u8 msg_data[10];
+ u16 media_type;
u8 dest_vfid;
u16 duplex;
/* mac.link can only be 0 or 1 */
link_status = (u16)hdev->hw.mac.link;
duplex = hdev->hw.mac.duplex;
+ media_type = hdev->hw.mac.media_type;
memcpy(&msg_data[0], &link_status, sizeof(u16));
memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32));
memcpy(&msg_data[6], &duplex, sizeof(u16));
+ memcpy(&msg_data[8], &media_type, sizeof(u16));
dest_vfid = mbx_req->mbx_src_vfid;
/* send this requested info to VF */
@@ -369,6 +410,29 @@ static int hclge_get_link_info(struct hclge_vport *vport,
HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid);
}
+static void hclge_get_link_mode(struct hclge_vport *vport,
+ struct hclge_mbx_vf_to_pf_cmd *mbx_req)
+{
+#define HCLGE_SUPPORTED 1
+ struct hclge_dev *hdev = vport->back;
+ unsigned long advertising;
+ unsigned long supported;
+ unsigned long send_data;
+ u8 msg_data[10];
+ u8 dest_vfid;
+
+ advertising = hdev->hw.mac.advertising[0];
+ supported = hdev->hw.mac.supported[0];
+ dest_vfid = mbx_req->mbx_src_vfid;
+ msg_data[0] = mbx_req->msg[2];
+
+ send_data = msg_data[0] == HCLGE_SUPPORTED ? supported : advertising;
+
+ memcpy(&msg_data[2], &send_data, sizeof(unsigned long));
+ hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
+ HCLGE_MBX_LINK_STAT_MODE, dest_vfid);
+}
+
static void hclge_mbx_reset_vf_queue(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
@@ -426,6 +490,24 @@ static int hclge_get_queue_id_in_pf(struct hclge_vport *vport,
return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, 2);
}
+static int hclge_get_rss_key(struct hclge_vport *vport,
+ struct hclge_mbx_vf_to_pf_cmd *mbx_req)
+{
+#define HCLGE_RSS_MBX_RESP_LEN 8
+ u8 resp_data[HCLGE_RSS_MBX_RESP_LEN];
+ struct hclge_dev *hdev = vport->back;
+ u8 index;
+
+ index = mbx_req->msg[2];
+
+ memcpy(&resp_data[0],
+ &hdev->vport[0].rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN],
+ HCLGE_RSS_MBX_RESP_LEN);
+
+ return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data,
+ HCLGE_RSS_MBX_RESP_LEN);
+}
+
static bool hclge_cmd_crq_empty(struct hclge_hw *hw)
{
u32 tail = hclge_read_dev(hw, HCLGE_NIC_CRQ_TAIL_REG);
@@ -517,6 +599,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
"PF failed(%d) to get Q info for VF\n",
ret);
break;
+ case HCLGE_MBX_GET_QDEPTH:
+ ret = hclge_get_vf_queue_depth(vport, req, true);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "PF failed(%d) to get Q depth for VF\n",
+ ret);
+ break;
+
case HCLGE_MBX_GET_TCINFO:
ret = hclge_get_vf_tcinfo(vport, req, true);
if (ret)
@@ -553,6 +643,25 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
"PF failed(%d) to get qid for VF\n",
ret);
break;
+ case HCLGE_MBX_GET_RSS_KEY:
+ ret = hclge_get_rss_key(vport, req);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "PF fail(%d) to get rss key for VF\n",
+ ret);
+ break;
+ case HCLGE_MBX_GET_LINK_MODE:
+ hclge_get_link_mode(vport, req);
+ break;
+ case HCLGE_MBX_GET_VF_FLR_STATUS:
+ mutex_lock(&hdev->vport_cfg_mutex);
+ hclge_rm_vport_all_mac_table(vport, true,
+ HCLGE_MAC_ADDR_UC);
+ hclge_rm_vport_all_mac_table(vport, true,
+ HCLGE_MAC_ADDR_MC);
+ hclge_rm_vport_all_vlan_table(vport, true);
+ mutex_unlock(&hdev->vport_cfg_mutex);
+ break;
default:
dev_err(&hdev->pdev->dev,
"un-supported mailbox message, code = %d\n",
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index dabb8437f8dc..48eda2c6fdae 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -8,12 +8,6 @@
#include "hclge_main.h"
#include "hclge_mdio.h"
-#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
- SUPPORTED_TP | \
- PHY_10BT_FEATURES | \
- PHY_100BT_FEATURES | \
- SUPPORTED_1000baseT_Full)
-
enum hclge_mdio_c22_op_seq {
HCLGE_MDIO_C22_WRITE = 1,
HCLGE_MDIO_C22_READ = 2
@@ -195,8 +189,10 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
netdev_err(netdev, "failed to configure flow control.\n");
}
-int hclge_mac_connect_phy(struct hclge_dev *hdev)
+int hclge_mac_connect_phy(struct hnae3_handle *handle)
{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
struct net_device *netdev = hdev->vport[0].nic.netdev;
struct phy_device *phydev = hdev->hw.mac.phydev;
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
@@ -215,22 +211,17 @@ int hclge_mac_connect_phy(struct hclge_dev *hdev)
return ret;
}
- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask);
- linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask);
- linkmode_set_bit_array(phy_10_100_features_array,
- ARRAY_SIZE(phy_10_100_features_array),
- mask);
- linkmode_set_bit_array(phy_gbit_features_array,
- ARRAY_SIZE(phy_gbit_features_array),
- mask);
+ linkmode_copy(mask, hdev->hw.mac.supported);
linkmode_and(phydev->supported, phydev->supported, mask);
- phy_support_asym_pause(phydev);
+ linkmode_copy(phydev->advertising, phydev->supported);
return 0;
}
-void hclge_mac_disconnect_phy(struct hclge_dev *hdev)
+void hclge_mac_disconnect_phy(struct hnae3_handle *handle)
{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
struct phy_device *phydev = hdev->hw.mac.phydev;
if (!phydev)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
index 5fbf7dddb5d9..ef095d9c566f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
@@ -5,8 +5,8 @@
#define __HCLGE_MDIO_H
int hclge_mac_mdio_config(struct hclge_dev *hdev);
-int hclge_mac_connect_phy(struct hclge_dev *hdev);
-void hclge_mac_disconnect_phy(struct hclge_dev *hdev);
+int hclge_mac_connect_phy(struct hnae3_handle *handle);
+void hclge_mac_disconnect_phy(struct hnae3_handle *handle);
void hclge_mac_start_phy(struct hclge_dev *hdev);
void hclge_mac_stop_phy(struct hclge_dev *hdev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 00458da67503..aafc69f4bfdd 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -517,20 +517,39 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
{
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
struct hclge_dev *hdev = vport->back;
+ u16 max_rss_size;
u8 i;
- vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
- kinfo->num_tc =
- min_t(u16, kinfo->num_tqps, hdev->tm_info.num_tc);
- kinfo->rss_size
- = min_t(u16, hdev->rss_size_max,
- kinfo->num_tqps / kinfo->num_tc);
- vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id;
+ /* TC configuration is shared by PF/VF in one port, only allow
+ * one tc for VF for simplicity. VF's vport_id is non zero.
+ */
+ kinfo->num_tc = vport->vport_id ? 1 :
+ min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc);
+ vport->qs_offset = (vport->vport_id ? hdev->tm_info.num_tc : 0) +
+ (vport->vport_id ? (vport->vport_id - 1) : 0);
+
+ max_rss_size = min_t(u16, hdev->rss_size_max,
+ vport->alloc_tqps / kinfo->num_tc);
+
+ if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
+ kinfo->req_rss_size <= max_rss_size) {
+ dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n",
+ kinfo->rss_size, kinfo->req_rss_size);
+ kinfo->rss_size = kinfo->req_rss_size;
+ } else if (kinfo->rss_size > max_rss_size ||
+ (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) {
+ dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n",
+ kinfo->rss_size, max_rss_size);
+ kinfo->rss_size = max_rss_size;
+ }
+
+ kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size;
vport->dwrr = 100; /* 100 percent as init */
vport->alloc_rss_size = kinfo->rss_size;
+ vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
- for (i = 0; i < kinfo->num_tc; i++) {
- if (hdev->hw_tc_map & BIT(i)) {
+ for (i = 0; i < HNAE3_MAX_TC; i++) {
+ if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) {
kinfo->tc_info[i].enable = true;
kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
kinfo->tc_info[i].tqp_count = kinfo->rss_size;
@@ -753,13 +772,17 @@ static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
/* Cfg qs -> pri mapping, one by one mapping */
- for (k = 0; k < hdev->num_alloc_vport; k++)
- for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ for (k = 0; k < hdev->num_alloc_vport; k++) {
+ struct hnae3_knic_private_info *kinfo =
+ &vport[k].nic.kinfo;
+
+ for (i = 0; i < kinfo->num_tc; i++) {
ret = hclge_tm_qs_to_pri_map_cfg(
hdev, vport[k].qs_offset + i, i);
if (ret)
return ret;
}
+ }
} else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) {
/* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */
for (k = 0; k < hdev->num_alloc_vport; k++)
@@ -934,6 +957,36 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
return 0;
}
+static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev)
+{
+#define DEFAULT_TC_WEIGHT 1
+#define DEFAULT_TC_OFFSET 14
+
+ struct hclge_ets_tc_weight_cmd *ets_weight;
+ struct hclge_desc desc;
+ int i;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false);
+ ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data;
+
+ for (i = 0; i < HNAE3_MAX_TC; i++) {
+ struct hclge_pg_info *pg_info;
+
+ ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT;
+
+ if (!(hdev->hw_tc_map & BIT(i)))
+ continue;
+
+ pg_info =
+ &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
+ ets_weight->tc_weight[i] = pg_info->tc_dwrr[i];
+ }
+
+ ets_weight->weight_offset = DEFAULT_TC_OFFSET;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport)
{
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
@@ -983,6 +1036,19 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev);
if (ret)
return ret;
+
+ if (!hnae3_dev_dcb_supported(hdev))
+ return 0;
+
+ ret = hclge_tm_ets_tc_dwrr_cfg(hdev);
+ if (ret == -EOPNOTSUPP) {
+ dev_warn(&hdev->pdev->dev,
+ "fw %08x does't support ets tc weight cmd\n",
+ hdev->fw_version);
+ ret = 0;
+ }
+
+ return ret;
} else {
ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev);
if (ret)
@@ -992,7 +1058,7 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
return 0;
}
-int hclge_tm_map_cfg(struct hclge_dev *hdev)
+static int hclge_tm_map_cfg(struct hclge_dev *hdev)
{
int ret;
@@ -1107,7 +1173,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
return 0;
}
-int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
+static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
{
int ret;
@@ -1118,7 +1184,7 @@ int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
return hclge_tm_lvl34_schd_mode_cfg(hdev);
}
-static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
+int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
{
int ret;
@@ -1159,7 +1225,7 @@ static int hclge_pfc_setup_hw(struct hclge_dev *hdev)
HCLGE_RX_MAC_PAUSE_EN_MSK;
return hclge_pfc_pause_en_cfg(hdev, enable_bitmap,
- hdev->tm_info.hw_pfc_map);
+ hdev->tm_info.pfc_en);
}
/* Each Tc has a 1024 queue sets to backpress, it divides to
@@ -1228,10 +1294,23 @@ static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en);
}
-int hclge_pause_setup_hw(struct hclge_dev *hdev)
+static int hclge_tm_bp_setup(struct hclge_dev *hdev)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ ret = hclge_bp_setup_hw(hdev, i);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init)
{
int ret;
- u8 i;
ret = hclge_pause_param_setup_hw(hdev);
if (ret)
@@ -1245,18 +1324,17 @@ int hclge_pause_setup_hw(struct hclge_dev *hdev)
if (!hnae3_dev_dcb_supported(hdev))
return 0;
- /* When MAC is GE Mode, hdev does not support pfc setting */
+ /* GE MAC does not support PFC, when driver is initializing and MAC
+ * is in GE Mode, ignore the error here, otherwise initialization
+ * will fail.
+ */
ret = hclge_pfc_setup_hw(hdev);
- if (ret)
- dev_warn(&hdev->pdev->dev, "set pfc pause failed:%d\n", ret);
-
- for (i = 0; i < hdev->tm_info.num_tc; i++) {
- ret = hclge_bp_setup_hw(hdev, i);
- if (ret)
- return ret;
- }
+ if (init && ret == -EOPNOTSUPP)
+ dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n");
+ else
+ return ret;
- return 0;
+ return hclge_tm_bp_setup(hdev);
}
void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
@@ -1294,7 +1372,7 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
hclge_tm_schd_info_init(hdev);
}
-int hclge_tm_init_hw(struct hclge_dev *hdev)
+int hclge_tm_init_hw(struct hclge_dev *hdev, bool init)
{
int ret;
@@ -1306,7 +1384,7 @@ int hclge_tm_init_hw(struct hclge_dev *hdev)
if (ret)
return ret;
- ret = hclge_pause_setup_hw(hdev);
+ ret = hclge_pause_setup_hw(hdev, init);
if (ret)
return ret;
@@ -1325,5 +1403,22 @@ int hclge_tm_schd_init(struct hclge_dev *hdev)
if (ret)
return ret;
- return hclge_tm_init_hw(hdev);
+ return hclge_tm_init_hw(hdev, true);
+}
+
+int hclge_tm_vport_map_update(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ int ret;
+
+ hclge_tm_vport_tc_info_update(vport);
+
+ ret = hclge_vport_q_to_qs_map(hdev, vport);
+ if (ret)
+ return ret;
+
+ if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE))
+ return 0;
+
+ return hclge_tm_bp_setup(hdev);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index b6496a439304..f60e540c7a62 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -142,13 +142,13 @@ struct hclge_port_shapping_cmd {
(HCLGE_TM_SHAP_##string##_LSH))
int hclge_tm_schd_init(struct hclge_dev *hdev);
-int hclge_pause_setup_hw(struct hclge_dev *hdev);
-int hclge_tm_schd_mode_hw(struct hclge_dev *hdev);
+int hclge_tm_vport_map_update(struct hclge_dev *hdev);
+int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init);
+int hclge_tm_schd_setup_hw(struct hclge_dev *hdev);
void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc);
void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
-int hclge_tm_map_cfg(struct hclge_dev *hdev);
-int hclge_tm_init_hw(struct hclge_dev *hdev);
+int hclge_tm_init_hw(struct hclge_dev *hdev, bool init);
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
index d5765c8cf3a3..9441b453d38d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
@@ -115,9 +115,8 @@ static int hclgevf_alloc_cmd_desc(struct hclgevf_cmq_ring *ring)
{
int size = ring->desc_num * sizeof(struct hclgevf_desc);
- ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
- size, &ring->desc_dma_addr,
- GFP_KERNEL);
+ ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+ &ring->desc_dma_addr, GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
@@ -363,8 +362,28 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev)
return 0;
}
+static void hclgevf_cmd_uninit_regs(struct hclgevf_hw *hw)
+{
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_L_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_L_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_DEPTH_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_HEAD_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_TAIL_REG, 0);
+}
+
void hclgevf_cmd_uninit(struct hclgevf_dev *hdev)
{
+ spin_lock_bh(&hdev->hw.cmq.csq.lock);
+ spin_lock(&hdev->hw.cmq.crq.lock);
+ clear_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
+ hclgevf_cmd_uninit_regs(&hdev->hw);
+ spin_unlock(&hdev->hw.cmq.crq.lock);
+ spin_unlock_bh(&hdev->hw.cmq.csq.lock);
hclgevf_free_cmd_desc(&hdev->hw.cmq.csq);
hclgevf_free_cmd_desc(&hdev->hw.cmq.crq);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 82103d5fa815..8bc28e6f465f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -21,6 +21,14 @@ static const struct pci_device_id ae_algovf_pci_tbl[] = {
{0, }
};
+static const u8 hclgevf_hash_key[] = {
+ 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
+ 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
+ 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
+ 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
+ 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA
+};
+
MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl);
static const u32 cmdq_reg_addr_list[] = {HCLGEVF_CMDQ_TX_ADDR_L_REG,
@@ -78,7 +86,12 @@ static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG,
static inline struct hclgevf_dev *hclgevf_ae_get_hdev(
struct hnae3_handle *handle)
{
- return container_of(handle, struct hclgevf_dev, nic);
+ if (!handle->client)
+ return container_of(handle, struct hclgevf_dev, nic);
+ else if (handle->client->type == HNAE3_CLIENT_ROCE)
+ return container_of(handle, struct hclgevf_dev, roce);
+ else
+ return container_of(handle, struct hclgevf_dev, nic);
}
static int hclgevf_tqps_update_stats(struct hnae3_handle *handle)
@@ -234,7 +247,7 @@ static int hclgevf_get_tc_info(struct hclgevf_dev *hdev)
static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
{
-#define HCLGEVF_TQPS_RSS_INFO_LEN 8
+#define HCLGEVF_TQPS_RSS_INFO_LEN 6
u8 resp_msg[HCLGEVF_TQPS_RSS_INFO_LEN];
int status;
@@ -250,8 +263,29 @@ static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
memcpy(&hdev->num_tqps, &resp_msg[0], sizeof(u16));
memcpy(&hdev->rss_size_max, &resp_msg[2], sizeof(u16));
- memcpy(&hdev->num_desc, &resp_msg[4], sizeof(u16));
- memcpy(&hdev->rx_buf_len, &resp_msg[6], sizeof(u16));
+ memcpy(&hdev->rx_buf_len, &resp_msg[4], sizeof(u16));
+
+ return 0;
+}
+
+static int hclgevf_get_queue_depth(struct hclgevf_dev *hdev)
+{
+#define HCLGEVF_TQPS_DEPTH_INFO_LEN 4
+ u8 resp_msg[HCLGEVF_TQPS_DEPTH_INFO_LEN];
+ int ret;
+
+ ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_QDEPTH, 0, NULL, 0,
+ true, resp_msg,
+ HCLGEVF_TQPS_DEPTH_INFO_LEN);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "VF request to get tqp depth info from PF failed %d",
+ ret);
+ return ret;
+ }
+
+ memcpy(&hdev->num_tx_desc, &resp_msg[0], sizeof(u16));
+ memcpy(&hdev->num_rx_desc, &resp_msg[2], sizeof(u16));
return 0;
}
@@ -291,7 +325,8 @@ static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev)
tqp->q.ae_algo = &ae_algovf;
tqp->q.buf_size = hdev->rx_buf_len;
- tqp->q.desc_num = hdev->num_desc;
+ tqp->q.tx_desc_num = hdev->num_tx_desc;
+ tqp->q.rx_desc_num = hdev->num_rx_desc;
tqp->q.io_base = hdev->hw.io_base + HCLGEVF_TQP_REG_OFFSET +
i * HCLGEVF_TQP_REG_SIZE;
@@ -310,7 +345,8 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
kinfo = &nic->kinfo;
kinfo->num_tc = 0;
- kinfo->num_desc = hdev->num_desc;
+ kinfo->num_tx_desc = hdev->num_tx_desc;
+ kinfo->num_rx_desc = hdev->num_rx_desc;
kinfo->rx_buf_len = hdev->rx_buf_len;
for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++)
if (hdev->hw_tc_map & BIT(i))
@@ -349,20 +385,40 @@ static void hclgevf_request_link_info(struct hclgevf_dev *hdev)
void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state)
{
+ struct hnae3_handle *rhandle = &hdev->roce;
struct hnae3_handle *handle = &hdev->nic;
+ struct hnae3_client *rclient;
struct hnae3_client *client;
client = handle->client;
+ rclient = hdev->roce_client;
link_state =
test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state;
if (link_state != hdev->hw.mac.link) {
client->ops->link_status_change(handle, !!link_state);
+ if (rclient && rclient->ops->link_status_change)
+ rclient->ops->link_status_change(rhandle, !!link_state);
hdev->hw.mac.link = link_state;
}
}
+void hclgevf_update_link_mode(struct hclgevf_dev *hdev)
+{
+#define HCLGEVF_ADVERTISING 0
+#define HCLGEVF_SUPPORTED 1
+ u8 send_msg;
+ u8 resp_msg;
+
+ send_msg = HCLGEVF_ADVERTISING;
+ hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_LINK_MODE, 0, &send_msg,
+ sizeof(u8), false, &resp_msg, sizeof(u8));
+ send_msg = HCLGEVF_SUPPORTED;
+ hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_LINK_MODE, 0, &send_msg,
+ sizeof(u8), false, &resp_msg, sizeof(u8));
+}
+
static int hclgevf_set_handle_info(struct hclgevf_dev *hdev)
{
struct hnae3_handle *nic = &hdev->nic;
@@ -564,12 +620,50 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size)
return status;
}
+/* for revision 0x20, vf shared the same rss config with pf */
+static int hclgevf_get_rss_hash_key(struct hclgevf_dev *hdev)
+{
+#define HCLGEVF_RSS_MBX_RESP_LEN 8
+
+ struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
+ u8 resp_msg[HCLGEVF_RSS_MBX_RESP_LEN];
+ u16 msg_num, hash_key_index;
+ u8 index;
+ int ret;
+
+ msg_num = (HCLGEVF_RSS_KEY_SIZE + HCLGEVF_RSS_MBX_RESP_LEN - 1) /
+ HCLGEVF_RSS_MBX_RESP_LEN;
+ for (index = 0; index < msg_num; index++) {
+ ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_RSS_KEY, 0,
+ &index, sizeof(index),
+ true, resp_msg,
+ HCLGEVF_RSS_MBX_RESP_LEN);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "VF get rss hash key from PF failed, ret=%d",
+ ret);
+ return ret;
+ }
+
+ hash_key_index = HCLGEVF_RSS_MBX_RESP_LEN * index;
+ if (index == msg_num - 1)
+ memcpy(&rss_cfg->rss_hash_key[hash_key_index],
+ &resp_msg[0],
+ HCLGEVF_RSS_KEY_SIZE - hash_key_index);
+ else
+ memcpy(&rss_cfg->rss_hash_key[hash_key_index],
+ &resp_msg[0], HCLGEVF_RSS_MBX_RESP_LEN);
+ }
+
+ return 0;
+}
+
static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
u8 *hfunc)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
- int i;
+ int i, ret;
if (handle->pdev->revision >= 0x21) {
/* Get hash algorithm */
@@ -591,6 +685,16 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
if (key)
memcpy(key, rss_cfg->rss_hash_key,
HCLGEVF_RSS_KEY_SIZE);
+ } else {
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+ if (key) {
+ ret = hclgevf_get_rss_hash_key(hdev);
+ if (ret)
+ return ret;
+ memcpy(key, rss_cfg->rss_hash_key,
+ HCLGEVF_RSS_KEY_SIZE);
+ }
}
if (indir)
@@ -964,33 +1068,29 @@ static int hclgevf_put_vector(struct hnae3_handle *handle, int vector)
}
static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
- bool en_uc_pmc, bool en_mc_pmc)
+ bool en_bc_pmc)
{
struct hclge_mbx_vf_to_pf_cmd *req;
struct hclgevf_desc desc;
- int status;
+ int ret;
req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data;
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_VF_TO_PF, false);
req->msg[0] = HCLGE_MBX_SET_PROMISC_MODE;
- req->msg[1] = en_uc_pmc ? 1 : 0;
- req->msg[2] = en_mc_pmc ? 1 : 0;
+ req->msg[1] = en_bc_pmc ? 1 : 0;
- status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
- if (status)
+ ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
+ if (ret)
dev_err(&hdev->pdev->dev,
- "Set promisc mode fail, status is %d.\n", status);
+ "Set promisc mode fail, status is %d.\n", ret);
- return status;
+ return ret;
}
-static int hclgevf_set_promisc_mode(struct hnae3_handle *handle,
- bool en_uc_pmc, bool en_mc_pmc)
+static int hclgevf_set_promisc_mode(struct hclgevf_dev *hdev, bool en_bc_pmc)
{
- struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
-
- return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc);
+ return hclgevf_cmd_set_promisc_mode(hdev, en_bc_pmc);
}
static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, int tqp_id,
@@ -1264,7 +1364,7 @@ static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
if (ret)
return ret;
- return 0;
+ return hclgevf_notify_client(hdev, HNAE3_RESTORE_CLIENT);
}
static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
@@ -1610,6 +1710,10 @@ static void hclgevf_keep_alive_task(struct work_struct *work)
int ret;
hdev = container_of(work, struct hclgevf_dev, keep_alive_task);
+
+ if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
+ return;
+
ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_KEEP_ALIVE, 0, NULL,
0, false, &respmsg, sizeof(u8));
if (ret)
@@ -1628,6 +1732,8 @@ static void hclgevf_service_task(struct work_struct *work)
*/
hclgevf_request_link_info(hdev);
+ hclgevf_update_link_mode(hdev);
+
hclgevf_deferred_task_schedule(hdev);
clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);
@@ -1708,12 +1814,16 @@ static int hclgevf_configure(struct hclgevf_dev *hdev)
{
int ret;
- hdev->hw.mac.media_type = HNAE3_MEDIA_TYPE_NONE;
-
/* get queue configuration from PF */
ret = hclgevf_get_queue_info(hdev);
if (ret)
return ret;
+
+ /* get queue depth info from PF */
+ ret = hclgevf_get_queue_depth(hdev);
+ if (ret)
+ return ret;
+
/* get tc configuration from PF */
return hclgevf_get_tc_info(hdev);
}
@@ -1788,9 +1898,9 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
rss_cfg->rss_size = hdev->rss_size_max;
if (hdev->pdev->revision >= 0x21) {
- rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
- netdev_rss_key_fill(rss_cfg->rss_hash_key,
- HCLGEVF_RSS_KEY_SIZE);
+ rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
+ memcpy(rss_cfg->rss_hash_key, hclgevf_hash_key,
+ HCLGEVF_RSS_KEY_SIZE);
ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
rss_cfg->rss_hash_key);
@@ -1862,6 +1972,8 @@ static int hclgevf_ae_start(struct hnae3_handle *handle)
hclgevf_request_link_info(hdev);
+ hclgevf_update_link_mode(hdev);
+
clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
return 0;
@@ -2377,6 +2489,15 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
if (ret)
goto err_config;
+ /* vf is not allowed to enable unicast/multicast promisc mode.
+ * For revision 0x20, default to disable broadcast promisc mode,
+ * firmware makes sure broadcast packets can be accepted.
+ * For revision 0x21, default to enable broadcast promisc mode.
+ */
+ ret = hclgevf_set_promisc_mode(hdev, true);
+ if (ret)
+ goto err_config;
+
/* Initialize RSS for this VF */
ret = hclgevf_rss_init_hw(hdev);
if (ret) {
@@ -2461,7 +2582,8 @@ static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
struct hnae3_handle *nic = &hdev->nic;
struct hnae3_knic_private_info *kinfo = &nic->kinfo;
- return min_t(u32, hdev->rss_size_max * kinfo->num_tc, hdev->num_tqps);
+ return min_t(u32, hdev->rss_size_max,
+ hdev->num_tqps / kinfo->num_tc);
}
/**
@@ -2482,7 +2604,7 @@ static void hclgevf_get_channels(struct hnae3_handle *handle,
ch->max_combined = hclgevf_get_max_channels(hdev);
ch->other_count = 0;
ch->max_other = 0;
- ch->combined_count = hdev->num_tqps;
+ ch->combined_count = handle->kinfo.rss_size;
}
static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle,
@@ -2522,7 +2644,7 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
hdev->hw.mac.duplex = duplex;
}
-static int hclgevf_gro_en(struct hnae3_handle *handle, int enable)
+static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
@@ -2558,6 +2680,16 @@ static unsigned long hclgevf_ae_dev_reset_cnt(struct hnae3_handle *handle)
return hdev->reset_count;
}
+static void hclgevf_get_link_mode(struct hnae3_handle *handle,
+ unsigned long *supported,
+ unsigned long *advertising)
+{
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+
+ *supported = hdev->hw.mac.supported;
+ *advertising = hdev->hw.mac.advertising;
+}
+
#define MAX_SEPARATE_NUM 4
#define SEPARATOR_VALUE 0xFFFFFFFF
#define REG_NUM_PER_LINE 4
@@ -2640,7 +2772,6 @@ static const struct hnae3_ae_ops hclgevf_ops = {
.get_vector = hclgevf_get_vector,
.put_vector = hclgevf_put_vector,
.reset_queue = hclgevf_reset_tqp,
- .set_promisc_mode = hclgevf_set_promisc_mode,
.get_mac_addr = hclgevf_get_mac_addr,
.set_mac_addr = hclgevf_set_mac_addr,
.add_uc_addr = hclgevf_add_uc_addr,
@@ -2677,6 +2808,7 @@ static const struct hnae3_ae_ops hclgevf_ops = {
.set_mtu = hclgevf_set_mtu,
.get_global_queue_id = hclgevf_get_qid_global,
.set_timer_task = hclgevf_set_timer_task,
+ .get_link_mode = hclgevf_get_link_mode,
};
static struct hnae3_ae_algo ae_algovf = {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
index 787bc06944e5..c128863ee7d0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -145,6 +145,8 @@ struct hclgevf_mac {
int link;
u8 duplex;
u32 speed;
+ u64 supported;
+ u64 advertising;
};
struct hclgevf_hw {
@@ -237,7 +239,8 @@ struct hclgevf_dev {
u16 num_alloc_vport; /* num vports this driver supports */
u32 numa_node_mask;
u16 rx_buf_len;
- u16 num_desc;
+ u16 num_tx_desc; /* desc num of per tx queue */
+ u16 num_rx_desc; /* desc num of per rx queue */
u8 hw_tc_map;
u16 num_msi;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
index 84653f58b2d1..7dc3c9f79169 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
@@ -197,6 +197,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
break;
case HCLGE_MBX_LINK_STAT_CHANGE:
case HCLGE_MBX_ASSERTING_RESET:
+ case HCLGE_MBX_LINK_STAT_MODE:
/* set this mbx event as pending. This is required as we
* might loose interrupt event when mbx task is busy
* handling. This shall be cleared when mbx task just
@@ -247,6 +248,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
u8 duplex;
u32 speed;
u32 tail;
+ u8 idx;
/* we can safely clear it now as we are at start of the async message
* processing
@@ -270,12 +272,22 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
link_status = le16_to_cpu(msg_q[1]);
memcpy(&speed, &msg_q[2], sizeof(speed));
duplex = (u8)le16_to_cpu(msg_q[4]);
+ hdev->hw.mac.media_type = (u8)le16_to_cpu(msg_q[5]);
/* update upper layer with new link link status */
hclgevf_update_link_status(hdev, link_status);
hclgevf_update_speed_duplex(hdev, speed, duplex);
break;
+ case HCLGE_MBX_LINK_STAT_MODE:
+ idx = (u8)le16_to_cpu(msg_q[1]);
+ if (idx)
+ memcpy(&hdev->hw.mac.supported, &msg_q[2],
+ sizeof(unsigned long));
+ else
+ memcpy(&hdev->hw.mac.advertising, &msg_q[2],
+ sizeof(unsigned long));
+ break;
case HCLGE_MBX_ASSERTING_RESET:
/* PF has asserted reset hence VF should go in pending
* state and poll for the hardware reset status till it
diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
index 017e08452d8c..baf5cc251f32 100644
--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -321,7 +321,7 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
}
hns_mdio_cmd_write(mdio_dev, is_c45,
- MDIO_C45_WRITE_ADDR, phy_id, devad);
+ MDIO_C45_READ, phy_id, devad);
}
/* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
index c40603a183df..b4fefb4c3064 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
@@ -613,8 +613,8 @@ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,
u8 *cmd_vaddr;
int err = 0;
- cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
- &cmd_paddr, GFP_KERNEL);
+ cmd_vaddr = dma_alloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
+ &cmd_paddr, GFP_KERNEL);
if (!cmd_vaddr) {
dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n");
return -ENOMEM;
@@ -663,8 +663,8 @@ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,
dma_addr_t node_paddr;
int err;
- node = dma_zalloc_coherent(&pdev->dev, chain->cell_size,
- &node_paddr, GFP_KERNEL);
+ node = dma_alloc_coherent(&pdev->dev, chain->cell_size, &node_paddr,
+ GFP_KERNEL);
if (!node) {
dev_err(&pdev->dev, "Failed to allocate dma API CMD cell\n");
return -ENOMEM;
@@ -821,10 +821,10 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain,
if (!chain->cell_ctxt)
return -ENOMEM;
- chain->wb_status = dma_zalloc_coherent(&pdev->dev,
- sizeof(*chain->wb_status),
- &chain->wb_status_paddr,
- GFP_KERNEL);
+ chain->wb_status = dma_alloc_coherent(&pdev->dev,
+ sizeof(*chain->wb_status),
+ &chain->wb_status_paddr,
+ GFP_KERNEL);
if (!chain->wb_status) {
dev_err(&pdev->dev, "Failed to allocate DMA wb status\n");
return -ENOMEM;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
index 6b19607a4caa..3875f39f43bb 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
@@ -1008,3 +1008,16 @@ int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
&hw_ci, sizeof(hw_ci), NULL,
NULL, HINIC_MGMT_MSG_SYNC);
}
+
+/**
+ * hinic_hwdev_set_msix_state- set msix state
+ * @hwdev: the NIC HW device
+ * @msix_index: IRQ corresponding index number
+ * @flag: msix state
+ *
+ **/
+void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index,
+ enum hinic_msix_state flag)
+{
+ hinic_set_msix_state(hwdev->hwif, msix_index, flag);
+}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index d1a7d2522d82..c9e621e19dd0 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -240,4 +240,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
u8 pending_limit, u8 coalesc_timer);
+void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index,
+ enum hinic_msix_state flag);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
index 7cb8b9b94726..683e67515016 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
@@ -593,10 +593,10 @@ static int alloc_eq_pages(struct hinic_eq *eq)
}
for (pg = 0; pg < eq->num_pages; pg++) {
- eq->virt_addr[pg] = dma_zalloc_coherent(&pdev->dev,
- eq->page_size,
- &eq->dma_addr[pg],
- GFP_KERNEL);
+ eq->virt_addr[pg] = dma_alloc_coherent(&pdev->dev,
+ eq->page_size,
+ &eq->dma_addr[pg],
+ GFP_KERNEL);
if (!eq->virt_addr[pg]) {
err = -ENOMEM;
goto err_dma_alloc;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
index 823a17061a97..9b160f076904 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
@@ -168,6 +168,22 @@ void hinic_db_state_set(struct hinic_hwif *hwif,
hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
}
+void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx,
+ enum hinic_msix_state flag)
+{
+ u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE +
+ HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL;
+ u32 mask_bits;
+
+ mask_bits = readl(hwif->intr_regs_base + offset);
+ mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+
+ if (flag)
+ mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+
+ writel(mask_bits, hwif->intr_regs_base + offset);
+}
+
/**
* hwif_ready - test if the HW is ready for use
* @hwif: the HW interface of a pci function device
@@ -321,6 +337,13 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
return -ENOMEM;
}
+ hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR);
+ if (!hwif->intr_regs_base) {
+ dev_err(&pdev->dev, "Failed to map configuration regs\n");
+ err = -ENOMEM;
+ goto err_map_intr_bar;
+ }
+
err = hwif_ready(hwif);
if (err) {
dev_err(&pdev->dev, "HW interface is not ready\n");
@@ -337,7 +360,11 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
return 0;
err_hwif_ready:
+ iounmap(hwif->intr_regs_base);
+
+err_map_intr_bar:
iounmap(hwif->cfg_regs_bar);
+
return err;
}
@@ -347,5 +374,6 @@ err_hwif_ready:
**/
void hinic_free_hwif(struct hinic_hwif *hwif)
{
+ iounmap(hwif->intr_regs_base);
iounmap(hwif->cfg_regs_bar);
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
index 5b4760c0e9f5..22ec7f73e0a6 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
@@ -152,6 +152,7 @@
#define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF)
#define HINIC_PCI_CFG_REGS_BAR 0
+#define HINIC_PCI_INTR_REGS_BAR 2
#define HINIC_PCI_DB_BAR 4
#define HINIC_PCIE_ST_DISABLE 0
@@ -164,6 +165,10 @@
#define HINIC_EQ_MSIX_LLI_CREDIT_LIMIT_DEFAULT 0 /* Disabled */
#define HINIC_EQ_MSIX_RESEND_TIMER_DEFAULT 7 /* max */
+#define HINIC_PCI_MSIX_ENTRY_SIZE 16
+#define HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#define HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+
enum hinic_pcie_nosnoop {
HINIC_PCIE_SNOOP = 0,
HINIC_PCIE_NO_SNOOP = 1,
@@ -207,6 +212,11 @@ enum hinic_db_state {
HINIC_DB_DISABLE = 1,
};
+enum hinic_msix_state {
+ HINIC_MSIX_ENABLE,
+ HINIC_MSIX_DISABLE,
+};
+
struct hinic_func_attr {
u16 func_idx;
u8 pf_idx;
@@ -226,6 +236,7 @@ struct hinic_func_attr {
struct hinic_hwif {
struct pci_dev *pdev;
void __iomem *cfg_regs_bar;
+ void __iomem *intr_regs_base;
struct hinic_func_attr attr;
};
@@ -251,6 +262,9 @@ int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index,
u8 *lli_timer, u8 *lli_credit_limit,
u8 *resend_timer);
+void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx,
+ enum hinic_msix_state flag);
+
int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index);
void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
index 8e5897669a3a..a322a22d9357 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c
@@ -355,9 +355,9 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
goto err_sq_db;
}
- ci_addr_base = dma_zalloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
- &func_to_io->ci_dma_base,
- GFP_KERNEL);
+ ci_addr_base = dma_alloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
+ &func_to_io->ci_dma_base,
+ GFP_KERNEL);
if (!ci_addr_base) {
dev_err(&pdev->dev, "Failed to allocate CI area\n");
err = -ENOMEM;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
index bbf9bdd0ee3e..d62cf509646a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
@@ -336,9 +336,9 @@ static int alloc_rq_cqe(struct hinic_rq *rq)
goto err_cqe_dma_arr_alloc;
for (i = 0; i < wq->q_depth; i++) {
- rq->cqe[i] = dma_zalloc_coherent(&pdev->dev,
- sizeof(*rq->cqe[i]),
- &rq->cqe_dma[i], GFP_KERNEL);
+ rq->cqe[i] = dma_alloc_coherent(&pdev->dev,
+ sizeof(*rq->cqe[i]),
+ &rq->cqe_dma[i], GFP_KERNEL);
if (!rq->cqe[i])
goto err_cqe_alloc;
}
@@ -415,8 +415,8 @@ int hinic_init_rq(struct hinic_rq *rq, struct hinic_hwif *hwif,
/* HW requirements: Must be at least 32 bit */
pi_size = ALIGN(sizeof(*rq->pi_virt_addr), sizeof(u32));
- rq->pi_virt_addr = dma_zalloc_coherent(&pdev->dev, pi_size,
- &rq->pi_dma_addr, GFP_KERNEL);
+ rq->pi_virt_addr = dma_alloc_coherent(&pdev->dev, pi_size,
+ &rq->pi_dma_addr, GFP_KERNEL);
if (!rq->pi_virt_addr) {
dev_err(&pdev->dev, "Failed to allocate PI address\n");
err = -ENOMEM;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
index 1dfa7eb05c10..cb66e7024659 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
@@ -114,8 +114,8 @@ static int queue_alloc_page(struct hinic_hwif *hwif, u64 **vaddr, u64 *paddr,
struct pci_dev *pdev = hwif->pdev;
dma_addr_t dma_addr;
- *vaddr = dma_zalloc_coherent(&pdev->dev, page_sz, &dma_addr,
- GFP_KERNEL);
+ *vaddr = dma_alloc_coherent(&pdev->dev, page_sz, &dma_addr,
+ GFP_KERNEL);
if (!*vaddr) {
dev_err(&pdev->dev, "Failed to allocate dma for wqs page\n");
return -ENOMEM;
@@ -482,8 +482,8 @@ static int alloc_wq_pages(struct hinic_wq *wq, struct hinic_hwif *hwif,
u64 *paddr = &wq->block_vaddr[i];
dma_addr_t dma_addr;
- *vaddr = dma_zalloc_coherent(&pdev->dev, wq->wq_page_size,
- &dma_addr, GFP_KERNEL);
+ *vaddr = dma_alloc_coherent(&pdev->dev, wq->wq_page_size,
+ &dma_addr, GFP_KERNEL);
if (!*vaddr) {
dev_err(&pdev->dev, "Failed to allocate wq page\n");
goto err_alloc_wq_pages;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index da323b9e1f62..e64bc664f687 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -51,9 +51,10 @@ static unsigned int rx_weight = 64;
module_param(rx_weight, uint, 0644);
MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
-#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822
-#define HINIC_DEV_ID_DUAL_PORT_25GE 0x0200
-#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0201
+#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822
+#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0200
+#define HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ 0x0205
+#define HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ 0x0210
#define HINIC_WQ_NAME "hinic_dev"
@@ -1113,8 +1114,9 @@ static void hinic_shutdown(struct pci_dev *pdev)
static const struct pci_device_id hinic_pci_table[] = {
{ PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE), 0},
- { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_25GE), 0},
{ PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE), 0},
+ { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ), 0},
+ { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ), 0},
{ 0, 0}
};
MODULE_DEVICE_TABLE(pci, hinic_pci_table);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
index 0098b206e7e9..b6d218768ec1 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -381,6 +381,7 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget)
static int rx_poll(struct napi_struct *napi, int budget)
{
struct hinic_rxq *rxq = container_of(napi, struct hinic_rxq, napi);
+ struct hinic_dev *nic_dev = netdev_priv(rxq->netdev);
struct hinic_rq *rq = rxq->rq;
int pkts;
@@ -389,7 +390,10 @@ static int rx_poll(struct napi_struct *napi, int budget)
return budget;
napi_complete(napi);
- enable_irq(rq->irq);
+ hinic_hwdev_set_msix_state(nic_dev->hwdev,
+ rq->msix_entry,
+ HINIC_MSIX_ENABLE);
+
return pkts;
}
@@ -414,7 +418,10 @@ static irqreturn_t rx_irq(int irq, void *data)
struct hinic_dev *nic_dev;
/* Disable the interrupt until napi will be completed */
- disable_irq_nosync(rq->irq);
+ nic_dev = netdev_priv(rxq->netdev);
+ hinic_hwdev_set_msix_state(nic_dev->hwdev,
+ rq->msix_entry,
+ HINIC_MSIX_DISABLE);
nic_dev = netdev_priv(rxq->netdev);
hinic_hwdev_msix_cnt_set(nic_dev->hwdev, rq->msix_entry);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
index 11e73e67358d..e17bf33eba0c 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
@@ -655,7 +655,9 @@ static int free_tx_poll(struct napi_struct *napi, int budget)
if (pkts < budget) {
napi_complete(napi);
- enable_irq(sq->irq);
+ hinic_hwdev_set_msix_state(nic_dev->hwdev,
+ sq->msix_entry,
+ HINIC_MSIX_ENABLE);
return pkts;
}
@@ -682,7 +684,9 @@ static irqreturn_t tx_irq(int irq, void *data)
nic_dev = netdev_priv(txq->netdev);
/* Disable the interrupt until napi will be completed */
- disable_irq_nosync(txq->sq->irq);
+ hinic_hwdev_set_msix_state(nic_dev->hwdev,
+ txq->sq->msix_entry,
+ HINIC_MSIX_DISABLE);
hinic_hwdev_msix_cnt_set(nic_dev->hwdev, txq->sq->msix_entry);
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index d719668a6684..92929750f832 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1310,7 +1310,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
dev->stats.tx_aborted_errors++;
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
tx_cmd->cmd.command = 0; /* Mark free */
break;
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index 2f7ae118217f..1274ad24d6af 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1194,7 +1194,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
dma_unmap_single(dev->dev.parent,
tx_cmd->dma_addr,
skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
tx_cmd->cmd.command = 0; /* Mark free */
break;
diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig
index 90d49191beb3..eacf7e141fdc 100644
--- a/drivers/net/ethernet/ibm/emac/Kconfig
+++ b/drivers/net/ethernet/ibm/emac/Kconfig
@@ -28,18 +28,6 @@ config IBM_EMAC_RX_COPY_THRESHOLD
depends on IBM_EMAC
default "256"
-config IBM_EMAC_RX_SKB_HEADROOM
- int "Additional RX skb headroom (bytes)"
- depends on IBM_EMAC
- default "0"
- help
- Additional receive skb headroom. Note, that driver
- will always reserve at least 2 bytes to make IP header
- aligned, so usually there is no need to add any additional
- headroom.
-
- If unsure, set to 0.
-
config IBM_EMAC_DEBUG
bool "Debugging"
depends on IBM_EMAC
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 209255495bc9..3c2a5759844a 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1071,7 +1071,9 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
/* Second pass, allocate new skbs */
for (i = 0; i < NUM_RX_BUFF; ++i) {
- struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC);
+ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb_ip_align(dev->ndev, rx_skb_size);
if (!skb) {
ret = -ENOMEM;
goto oom;
@@ -1080,10 +1082,10 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
BUG_ON(!dev->rx_skb[i]);
dev_kfree_skb(dev->rx_skb[i]);
- skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
dev->rx_desc[i].data_ptr =
- dma_map_single(&dev->ofdev->dev, skb->data - 2, rx_sync_size,
- DMA_FROM_DEVICE) + 2;
+ dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
+ rx_sync_size, DMA_FROM_DEVICE)
+ + NET_IP_ALIGN;
dev->rx_skb[i] = skb;
}
skip:
@@ -1174,20 +1176,18 @@ static void emac_clean_rx_ring(struct emac_instance *dev)
}
}
-static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot,
- gfp_t flags)
+static int
+__emac_prepare_rx_skb(struct sk_buff *skb, struct emac_instance *dev, int slot)
{
- struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags);
if (unlikely(!skb))
return -ENOMEM;
dev->rx_skb[slot] = skb;
dev->rx_desc[slot].data_len = 0;
- skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
dev->rx_desc[slot].data_ptr =
- dma_map_single(&dev->ofdev->dev, skb->data - 2, dev->rx_sync_size,
- DMA_FROM_DEVICE) + 2;
+ dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
+ dev->rx_sync_size, DMA_FROM_DEVICE) + NET_IP_ALIGN;
wmb();
dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY |
(slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
@@ -1195,6 +1195,27 @@ static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot,
return 0;
}
+static int
+emac_alloc_rx_skb(struct emac_instance *dev, int slot)
+{
+ struct sk_buff *skb;
+
+ skb = __netdev_alloc_skb_ip_align(dev->ndev, dev->rx_skb_size,
+ GFP_KERNEL);
+
+ return __emac_prepare_rx_skb(skb, dev, slot);
+}
+
+static int
+emac_alloc_rx_skb_napi(struct emac_instance *dev, int slot)
+{
+ struct sk_buff *skb;
+
+ skb = napi_alloc_skb(&dev->mal->napi, dev->rx_skb_size);
+
+ return __emac_prepare_rx_skb(skb, dev, slot);
+}
+
static void emac_print_link_status(struct emac_instance *dev)
{
if (netif_carrier_ok(dev->ndev))
@@ -1225,7 +1246,7 @@ static int emac_open(struct net_device *ndev)
/* Allocate RX ring */
for (i = 0; i < NUM_RX_BUFF; ++i)
- if (emac_alloc_rx_skb(dev, i, GFP_KERNEL)) {
+ if (emac_alloc_rx_skb(dev, i)) {
printk(KERN_ERR "%s: failed to allocate RX ring\n",
ndev->name);
goto oom;
@@ -1660,8 +1681,9 @@ static inline void emac_recycle_rx_skb(struct emac_instance *dev, int slot,
DBG2(dev, "recycle %d %d" NL, slot, len);
if (len)
- dma_map_single(&dev->ofdev->dev, skb->data - 2,
- EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE);
+ dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN,
+ SKB_DATA_ALIGN(len + NET_IP_ALIGN),
+ DMA_FROM_DEVICE);
dev->rx_desc[slot].data_len = 0;
wmb();
@@ -1713,7 +1735,7 @@ static inline int emac_rx_sg_append(struct emac_instance *dev, int slot)
int len = dev->rx_desc[slot].data_len;
int tot_len = dev->rx_sg_skb->len + len;
- if (unlikely(tot_len + 2 > dev->rx_skb_size)) {
+ if (unlikely(tot_len + NET_IP_ALIGN > dev->rx_skb_size)) {
++dev->estats.rx_dropped_mtu;
dev_kfree_skb(dev->rx_sg_skb);
dev->rx_sg_skb = NULL;
@@ -1769,16 +1791,18 @@ static int emac_poll_rx(void *param, int budget)
}
if (len && len < EMAC_RX_COPY_THRESH) {
- struct sk_buff *copy_skb =
- alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC);
+ struct sk_buff *copy_skb;
+
+ copy_skb = napi_alloc_skb(&dev->mal->napi, len);
if (unlikely(!copy_skb))
goto oom;
- skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
- memcpy(copy_skb->data - 2, skb->data - 2, len + 2);
+ memcpy(copy_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ len + NET_IP_ALIGN);
emac_recycle_rx_skb(dev, slot, len);
skb = copy_skb;
- } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC)))
+ } else if (unlikely(emac_alloc_rx_skb_napi(dev, slot)))
goto oom;
skb_put(skb, len);
@@ -1799,7 +1823,7 @@ static int emac_poll_rx(void *param, int budget)
sg:
if (ctrl & MAL_RX_CTRL_FIRST) {
BUG_ON(dev->rx_sg_skb);
- if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) {
+ if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) {
DBG(dev, "rx OOM %d" NL, slot);
++dev->estats.rx_dropped_oom;
emac_recycle_rx_skb(dev, slot, 0);
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index 84caa4a3fc52..187689cd8212 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -68,22 +68,18 @@ static inline int emac_rx_size(int mtu)
return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD);
}
-#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment())
-
-#define EMAC_RX_SKB_HEADROOM \
- EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
-
/* Size of RX skb for the given MTU */
static inline int emac_rx_skb_size(int mtu)
{
int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu));
- return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM;
+
+ return SKB_DATA_ALIGN(size + NET_IP_ALIGN) + NET_SKB_PAD;
}
/* RX DMA sync size */
static inline int emac_rx_sync_size(int mtu)
{
- return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2);
+ return SKB_DATA_ALIGN(emac_rx_size(mtu) + NET_IP_ALIGN);
}
/* Driver statistcs is split into two parts to make it more cache friendly:
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index fff09dcf9e34..787d5aca5278 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -636,8 +636,8 @@ static int mal_probe(struct platform_device *ofdev)
bd_size = sizeof(struct mal_descriptor) *
(NUM_TX_BUFF * mal->num_tx_chans +
NUM_RX_BUFF * mal->num_rx_chans);
- mal->bd_virt = dma_zalloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
- GFP_KERNEL);
+ mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
+ GFP_KERNEL);
if (mal->bd_virt == NULL) {
err = -ENOMEM;
goto fail_unmap;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 098d8764c0ea..dd71d5db7274 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1313,7 +1313,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
unsigned long lpar_rc;
u16 mss = 0;
-restart_poll:
while (frames_processed < budget) {
if (!ibmveth_rxq_pending_buffer(adapter))
break;
@@ -1401,7 +1400,6 @@ restart_poll:
napi_reschedule(napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_DISABLE);
- goto restart_poll;
}
}
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 31fb76ee9d82..a1246e89aad4 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -159,7 +159,7 @@ config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
depends on PCI
select MDIO
- select MDIO_DEVICE
+ select PHYLIB
imply PTP_1588_CLOCK
---help---
This driver supports Intel(R) 10GbE PCI Express family of
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 2569a168334c..a41008523c98 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -993,8 +993,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
txdr->size = ALIGN(txdr->size, 4096);
- txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
- GFP_KERNEL);
+ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+ GFP_KERNEL);
if (!txdr->desc) {
ret_val = 2;
goto err_nomem;
@@ -1051,8 +1051,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
}
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
- GFP_KERNEL);
+ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+ GFP_KERNEL);
if (!rxdr->desc) {
ret_val = 6;
goto err_nomem;
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index 257bd59bc9c6..f86d55657959 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -696,11 +696,16 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
ret_val =
e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
&kum_reg_data);
- if (ret_val)
- return ret_val;
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ e_dbg("Error disabling far-end loopback\n");
+ } else {
+ e_dbg("Error disabling far-end loopback\n");
+ }
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val)
@@ -754,11 +759,19 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
return ret_val;
/* Disable IBIST slave mode (far-end loopback) */
- e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- &kum_reg_data);
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ ret_val =
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ e_dbg("Error disabling far-end loopback\n");
+ } else {
+ e_dbg("Error disabling far-end loopback\n");
+ }
/* Set the transmit descriptor write-back policy */
reg_data = er32(TXDCTL(0));
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 308c006cb41d..7acc61e4f645 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2106,7 +2106,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
if (strlen(netdev->name) < (IFNAMSIZ - 5))
snprintf(adapter->rx_ring->name,
sizeof(adapter->rx_ring->name) - 1,
- "%s-rx-0", netdev->name);
+ "%.14s-rx-0", netdev->name);
else
memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
@@ -2122,7 +2122,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
if (strlen(netdev->name) < (IFNAMSIZ - 5))
snprintf(adapter->tx_ring->name,
sizeof(adapter->tx_ring->name) - 1,
- "%s-tx-0", netdev->name);
+ "%.14s-tx-0", netdev->name);
else
memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
@@ -2305,8 +2305,8 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter,
{
struct pci_dev *pdev = adapter->pdev;
- ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma,
- GFP_KERNEL);
+ ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma,
+ GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
@@ -5309,8 +5309,13 @@ static void e1000_watchdog_task(struct work_struct *work)
/* 8000ES2LAN requires a Rx packet buffer work-around
* on link down event; reset the controller to flush
* the Rx packet buffer.
+ *
+ * If the link is lost the controller stops DMA, but
+ * if there is queued Tx work it cannot be done. So
+ * reset the controller to flush the Tx packet buffers.
*/
- if (adapter->flags & FLAG_RX_NEEDS_RESTART)
+ if ((adapter->flags & FLAG_RX_NEEDS_RESTART) ||
+ e1000_desc_unused(tx_ring) + 1 < tx_ring->count)
adapter->flags |= FLAG_RESTART_NOW;
else
pm_schedule_suspend(netdev->dev.parent,
@@ -5333,14 +5338,6 @@ link_up:
adapter->gotc_old = adapter->stats.gotc;
spin_unlock(&adapter->stats64_lock);
- /* If the link is lost the controller stops DMA, but
- * if there is queued Tx work it cannot be done. So
- * reset the controller to flush the Tx packet buffers.
- */
- if (!netif_carrier_ok(netdev) &&
- (e1000_desc_unused(tx_ring) + 1 < tx_ring->count))
- adapter->flags |= FLAG_RESTART_NOW;
-
/* If reset is necessary, do it outside of interrupt context. */
if (adapter->flags & FLAG_RESTART_NOW) {
schedule_work(&adapter->reset_task);
@@ -7351,6 +7348,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
e1000_print_device_info(adapter);
+ dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP);
+
if (pci_dev_run_wake(pdev))
pm_runtime_put_noidle(&pdev->dev);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index 6fd15a734324..5a0419421511 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -1603,14 +1603,12 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
{
struct fm10k_q_vector *q_vector;
struct fm10k_ring *ring;
- int ring_count, size;
+ int ring_count;
ring_count = txr_count + rxr_count;
- size = sizeof(struct fm10k_q_vector) +
- (sizeof(struct fm10k_ring) * ring_count);
/* allocate q_vector and rings */
- q_vector = kzalloc(size, GFP_KERNEL);
+ q_vector = kzalloc(struct_size(q_vector, ring, ring_count), GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
index 8f0a99b6a537..cb4d02629b86 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
@@ -1148,7 +1148,7 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw,
* @results: Pointer array to message, results[0] is pointer to message
* @mbx: Pointer to mailbox information structure
*
- * This function is a default handler for MSI-X requests from the VF. The
+ * This function is a default handler for MSI-X requests from the VF. The
* assumption is that in this case it is acceptable to just directly
* hand off the message from the VF to the underlying shared code.
**/
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 8de9085bba9e..d684998ba2b0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -34,6 +34,7 @@
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
+#include <net/xdp_sock.h>
#include "i40e_type.h"
#include "i40e_prototype.h"
#include "i40e_client.h"
@@ -523,6 +524,8 @@ struct i40e_pf {
#define I40E_FLAG_FD_SB_INACTIVE BIT(22)
#define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT(23)
#define I40E_FLAG_DISABLE_FW_LLDP BIT(24)
+#define I40E_FLAG_RS_FEC BIT(25)
+#define I40E_FLAG_BASE_R_FEC BIT(26)
struct i40e_client_instance *cinst;
bool stat_offsets_loaded;
@@ -787,11 +790,6 @@ struct i40e_vsi {
/* VSI specific handlers */
irqreturn_t (*irq_handler)(int irq, void *data);
-
- /* AF_XDP zero-copy */
- struct xdp_umem **xsk_umems;
- u16 num_xsk_umems_used;
- u16 num_xsk_umems;
} ____cacheline_internodealigned_in_smp;
struct i40e_netdev_priv {
@@ -1091,6 +1089,8 @@ i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
i40e_status i40e_commit_partition_bw_setting(struct i40e_pf *pf);
void i40e_print_link_message(struct i40e_vsi *vsi, bool isup);
+void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags);
+
static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
{
return !!vsi->xdp_prog;
@@ -1104,10 +1104,10 @@ static inline struct xdp_umem *i40e_xsk_umem(struct i40e_ring *ring)
if (ring_is_xdp(ring))
qid -= ring->vsi->alloc_queue_pairs;
- if (!ring->vsi->xsk_umems || !ring->vsi->xsk_umems[qid] || !xdp_on)
+ if (!xdp_on)
return NULL;
- return ring->vsi->xsk_umems[qid];
+ return xdp_get_umem_from_qid(ring->vsi->netdev, qid);
}
int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index a20d1cf058ad..c67d485d6f99 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -1642,30 +1642,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
count = buf_tmp - i40e_dbg_netdev_ops_buf + 1;
}
- if (strncmp(i40e_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
- cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i", &vsi_seid);
- if (cnt != 1) {
- dev_info(&pf->pdev->dev, "tx_timeout <vsi_seid>\n");
- goto netdev_ops_write_done;
- }
- vsi = i40e_dbg_find_vsi(pf, vsi_seid);
- if (!vsi) {
- dev_info(&pf->pdev->dev,
- "tx_timeout: VSI %d not found\n", vsi_seid);
- } else if (!vsi->netdev) {
- dev_info(&pf->pdev->dev, "tx_timeout: no netdev for VSI %d\n",
- vsi_seid);
- } else if (test_bit(__I40E_VSI_DOWN, vsi->state)) {
- dev_info(&pf->pdev->dev, "tx_timeout: VSI %d not UP\n",
- vsi_seid);
- } else if (rtnl_trylock()) {
- vsi->netdev->netdev_ops->ndo_tx_timeout(vsi->netdev);
- rtnl_unlock();
- dev_info(&pf->pdev->dev, "tx_timeout called\n");
- } else {
- dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n");
- }
- } else if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) {
+ if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) {
int mtu;
cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i",
@@ -1733,7 +1710,6 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
dev_info(&pf->pdev->dev, "unknown command '%s'\n",
i40e_dbg_netdev_ops_buf);
dev_info(&pf->pdev->dev, "available commands\n");
- dev_info(&pf->pdev->dev, " tx_timeout <vsi_seid>\n");
dev_info(&pf->pdev->dev, " change_mtu <vsi_seid> <mtu>\n");
dev_info(&pf->pdev->dev, " set_rx_mode <vsi_seid>\n");
dev_info(&pf->pdev->dev, " napi <vsi_seid>\n");
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index a6bc7847346b..4c885801fa26 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -438,6 +438,8 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
I40E_PRIV_FLAG("disable-source-pruning",
I40E_FLAG_SOURCE_PRUNING_DISABLED, 0),
I40E_PRIV_FLAG("disable-fw-lldp", I40E_FLAG_DISABLE_FW_LLDP, 0),
+ I40E_PRIV_FLAG("rs-fec", I40E_FLAG_RS_FEC, 0),
+ I40E_PRIV_FLAG("base-r-fec", I40E_FLAG_BASE_R_FEC, 0),
};
#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags)
@@ -606,6 +608,24 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf,
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
}
+ if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC) {
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
+ if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) {
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_BASER);
+ }
+ }
/* need to add new 10G PHY types */
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU) {
@@ -721,6 +741,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
25000baseSR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseSR_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_BASER);
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
@@ -825,6 +852,9 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
40000baseKR4_Full);
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseKR_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
ethtool_link_ksettings_add_link_mode(ks, supported,
20000baseKR2_Full);
ethtool_link_ksettings_add_link_mode(ks, supported,
@@ -838,6 +868,10 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
40000baseKR4_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseKR_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_BASER);
ethtool_link_ksettings_add_link_mode(ks, advertising,
20000baseKR2_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
@@ -855,6 +889,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
25000baseCR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_BASER);
break;
case I40E_PHY_TYPE_25GBASE_AOC:
case I40E_PHY_TYPE_25GBASE_ACC:
@@ -862,9 +903,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
-
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ FEC_BASER);
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseCR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
@@ -1261,6 +1308,154 @@ done:
return err;
}
+static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ i40e_status status = 0;
+ u32 flags = 0;
+ int err = 0;
+
+ flags = READ_ONCE(pf->flags);
+ i40e_set_fec_in_flags(fec_cfg, &flags);
+
+ /* Get the current phy config */
+ memset(&abilities, 0, sizeof(abilities));
+ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+ NULL);
+ if (status) {
+ err = -EAGAIN;
+ goto done;
+ }
+
+ if (abilities.fec_cfg_curr_mod_ext_info != fec_cfg) {
+ struct i40e_aq_set_phy_config config;
+
+ memset(&config, 0, sizeof(config));
+ config.phy_type = abilities.phy_type;
+ config.abilities = abilities.abilities;
+ config.phy_type_ext = abilities.phy_type_ext;
+ config.link_speed = abilities.link_speed;
+ config.eee_capability = abilities.eee_capability;
+ config.eeer = abilities.eeer_val;
+ config.low_power_ctrl = abilities.d3_lpan;
+ config.fec_config = fec_cfg & I40E_AQ_PHY_FEC_CONFIG_MASK;
+ status = i40e_aq_set_phy_config(hw, &config, NULL);
+ if (status) {
+ netdev_info(netdev,
+ "Set phy config failed, err %s aq_err %s\n",
+ i40e_stat_str(hw, status),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ err = -EAGAIN;
+ goto done;
+ }
+ pf->flags = flags;
+ status = i40e_update_link_info(hw);
+ if (status)
+ /* debug level message only due to relation to the link
+ * itself rather than to the FEC settings
+ * (e.g. no physical connection etc.)
+ */
+ netdev_dbg(netdev,
+ "Updating link info failed with err %s aq_err %s\n",
+ i40e_stat_str(hw, status),
+ i40e_aq_str(hw, hw->aq.asq_last_status));
+ }
+
+done:
+ return err;
+}
+
+static int i40e_get_fec_param(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ i40e_status status = 0;
+ int err = 0;
+
+ /* Get the current phy config */
+ memset(&abilities, 0, sizeof(abilities));
+ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+ NULL);
+ if (status) {
+ err = -EAGAIN;
+ goto done;
+ }
+
+ fecparam->fec = 0;
+ if (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_AUTO)
+ fecparam->fec |= ETHTOOL_FEC_AUTO;
+ if ((abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_SET_FEC_REQUEST_RS) ||
+ (abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_SET_FEC_ABILITY_RS))
+ fecparam->fec |= ETHTOOL_FEC_RS;
+ if ((abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_SET_FEC_REQUEST_KR) ||
+ (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_ABILITY_KR))
+ fecparam->fec |= ETHTOOL_FEC_BASER;
+ if (abilities.fec_cfg_curr_mod_ext_info == 0)
+ fecparam->fec |= ETHTOOL_FEC_OFF;
+
+ if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_KR_ENA)
+ fecparam->active_fec = ETHTOOL_FEC_BASER;
+ else if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_RS_ENA)
+ fecparam->active_fec = ETHTOOL_FEC_RS;
+ else
+ fecparam->active_fec = ETHTOOL_FEC_OFF;
+done:
+ return err;
+}
+
+static int i40e_set_fec_param(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ u8 fec_cfg = 0;
+ int err = 0;
+
+ if (hw->device_id != I40E_DEV_ID_25G_SFP28 &&
+ hw->device_id != I40E_DEV_ID_25G_B) {
+ err = -EPERM;
+ goto done;
+ }
+
+ switch (fecparam->fec) {
+ case ETHTOOL_FEC_AUTO:
+ fec_cfg = I40E_AQ_SET_FEC_AUTO;
+ break;
+ case ETHTOOL_FEC_RS:
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS |
+ I40E_AQ_SET_FEC_ABILITY_RS);
+ break;
+ case ETHTOOL_FEC_BASER:
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR |
+ I40E_AQ_SET_FEC_ABILITY_KR);
+ break;
+ case ETHTOOL_FEC_OFF:
+ case ETHTOOL_FEC_NONE:
+ fec_cfg = 0;
+ break;
+ default:
+ dev_warn(&pf->pdev->dev, "Unsupported FEC mode: %d",
+ fecparam->fec);
+ err = -EINVAL;
+ goto done;
+ }
+
+ err = i40e_set_fec_cfg(netdev, fec_cfg);
+
+done:
+ return err;
+}
+
static int i40e_nway_reset(struct net_device *netdev)
{
/* restart autonegotiation */
@@ -1376,7 +1571,7 @@ static int i40e_set_pauseparam(struct net_device *netdev,
else if (!pause->rx_pause && !pause->tx_pause)
hw->fc.requested_mode = I40E_FC_NONE;
else
- return -EINVAL;
+ return -EINVAL;
/* Tell the OS link is going down, the link will go back up when fw
* says it is ready asynchronously
@@ -2175,7 +2370,7 @@ static int i40e_get_ts_info(struct net_device *dev,
return 0;
}
-static int i40e_link_test(struct net_device *netdev, u64 *data)
+static u64 i40e_link_test(struct net_device *netdev, u64 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
@@ -2198,7 +2393,7 @@ static int i40e_link_test(struct net_device *netdev, u64 *data)
return *data;
}
-static int i40e_reg_test(struct net_device *netdev, u64 *data)
+static u64 i40e_reg_test(struct net_device *netdev, u64 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
@@ -2209,7 +2404,7 @@ static int i40e_reg_test(struct net_device *netdev, u64 *data)
return *data;
}
-static int i40e_eeprom_test(struct net_device *netdev, u64 *data)
+static u64 i40e_eeprom_test(struct net_device *netdev, u64 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
@@ -2223,7 +2418,7 @@ static int i40e_eeprom_test(struct net_device *netdev, u64 *data)
return *data;
}
-static int i40e_intr_test(struct net_device *netdev, u64 *data)
+static u64 i40e_intr_test(struct net_device *netdev, u64 *data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
@@ -2440,10 +2635,10 @@ static int i40e_set_phys_id(struct net_device *netdev,
default:
break;
}
- if (ret)
- return -ENOENT;
- else
- return 0;
+ if (ret)
+ return -ENOENT;
+ else
+ return 0;
}
/* NOTE: i40e hardware uses a conversion factor of 2 for Interrupt
@@ -4676,6 +4871,15 @@ flags_complete:
}
}
+ if (((changed_flags & I40E_FLAG_RS_FEC) ||
+ (changed_flags & I40E_FLAG_BASE_R_FEC)) &&
+ pf->hw.device_id != I40E_DEV_ID_25G_SFP28 &&
+ pf->hw.device_id != I40E_DEV_ID_25G_B) {
+ dev_warn(&pf->pdev->dev,
+ "Device does not support changing FEC configuration\n");
+ return -EOPNOTSUPP;
+ }
+
/* Now that we've checked to ensure that the new flags are valid, load
* them into place. Since we only modify flags either (a) during
* initialization or (b) while holding the RTNL lock, we don't need
@@ -4714,6 +4918,24 @@ flags_complete:
}
}
+ if ((changed_flags & I40E_FLAG_RS_FEC) ||
+ (changed_flags & I40E_FLAG_BASE_R_FEC)) {
+ u8 fec_cfg = 0;
+
+ if (pf->flags & I40E_FLAG_RS_FEC &&
+ pf->flags & I40E_FLAG_BASE_R_FEC) {
+ fec_cfg = I40E_AQ_SET_FEC_AUTO;
+ } else if (pf->flags & I40E_FLAG_RS_FEC) {
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS |
+ I40E_AQ_SET_FEC_ABILITY_RS);
+ } else if (pf->flags & I40E_FLAG_BASE_R_FEC) {
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR |
+ I40E_AQ_SET_FEC_ABILITY_KR);
+ }
+ if (i40e_set_fec_cfg(dev, fec_cfg))
+ dev_warn(&pf->pdev->dev, "Cannot change FEC config\n");
+ }
+
if ((changed_flags & pf->flags &
I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) &&
(pf->flags & I40E_FLAG_MFP_ENABLED))
@@ -4948,6 +5170,8 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.set_per_queue_coalesce = i40e_set_per_queue_coalesce,
.get_link_ksettings = i40e_get_link_ksettings,
.set_link_ksettings = i40e_set_link_ksettings,
+ .get_fecparam = i40e_get_fec_param,
+ .set_fecparam = i40e_set_fec_param,
};
void i40e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 4d40878e395a..da62218eb70a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -26,8 +26,8 @@ static const char i40e_driver_string[] =
#define DRV_KERN "-k"
#define DRV_VERSION_MAJOR 2
-#define DRV_VERSION_MINOR 7
-#define DRV_VERSION_BUILD 6
+#define DRV_VERSION_MINOR 8
+#define DRV_VERSION_BUILD 10
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@@ -109,8 +109,8 @@ int i40e_allocate_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem,
struct i40e_pf *pf = (struct i40e_pf *)hw->back;
mem->size = ALIGN(size, alignment);
- mem->va = dma_zalloc_coherent(&pf->pdev->dev, mem->size,
- &mem->pa, GFP_KERNEL);
+ mem->va = dma_alloc_coherent(&pf->pdev->dev, mem->size, &mem->pa,
+ GFP_KERNEL);
if (!mem->va)
return -ENOMEM;
@@ -3289,8 +3289,11 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
i40e_alloc_rx_buffers_zc(ring, I40E_DESC_UNUSED(ring)) :
!i40e_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
if (!ok) {
+ /* Log this in case the user has forgotten to give the kernel
+ * any buffers, even later in the application.
+ */
dev_info(&vsi->back->pdev->dev,
- "Failed allocate some buffers on %sRx ring %d (pf_q %d)\n",
+ "Failed to allocate some buffers on %sRx ring %d (pf_q %d)\n",
ring->xsk_umem ? "UMEM enabled " : "",
ring->queue_index, pf_q);
}
@@ -3610,7 +3613,7 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
(I40E_QUEUE_TYPE_TX
<< I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT);
- wr32(hw, I40E_QINT_TQCTL(nextqp), val);
+ wr32(hw, I40E_QINT_TQCTL(nextqp), val);
}
val = I40E_QINT_TQCTL_CAUSE_ENA_MASK |
@@ -6725,8 +6728,13 @@ void i40e_down(struct i40e_vsi *vsi)
for (i = 0; i < vsi->num_queue_pairs; i++) {
i40e_clean_tx_ring(vsi->tx_rings[i]);
- if (i40e_enabled_xdp_vsi(vsi))
+ if (i40e_enabled_xdp_vsi(vsi)) {
+ /* Make sure that in-progress ndo_xdp_xmit
+ * calls are completed.
+ */
+ synchronize_rcu();
i40e_clean_tx_ring(vsi->xdp_rings[i]);
+ }
i40e_clean_rx_ring(vsi->rx_rings[i]);
}
@@ -7169,11 +7177,13 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi,
struct tc_cls_flower_offload *f,
struct i40e_cloud_filter *filter)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_dissector *dissector = rule->match.dissector;
u16 n_proto_mask = 0, n_proto_key = 0, addr_type = 0;
struct i40e_pf *pf = vsi->back;
u8 field_flags = 0;
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -7183,143 +7193,109 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi,
BIT(FLOW_DISSECTOR_KEY_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) {
dev_err(&pf->pdev->dev, "Unsupported key used: 0x%x\n",
- f->dissector->used_keys);
+ dissector->used_keys);
return -EOPNOTSUPP;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid match;
- struct flow_dissector_key_keyid *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->mask);
-
- if (mask->keyid != 0)
+ flow_rule_match_enc_keyid(rule, &match);
+ if (match.mask->keyid != 0)
field_flags |= I40E_CLOUD_FIELD_TEN_ID;
- filter->tenant_id = be32_to_cpu(key->keyid);
+ filter->tenant_id = be32_to_cpu(match.key->keyid);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
-
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- n_proto_key = ntohs(key->n_proto);
- n_proto_mask = ntohs(mask->n_proto);
+ flow_rule_match_basic(rule, &match);
+ n_proto_key = ntohs(match.key->n_proto);
+ n_proto_mask = ntohs(match.mask->n_proto);
if (n_proto_key == ETH_P_ALL) {
n_proto_key = 0;
n_proto_mask = 0;
}
filter->n_proto = n_proto_key & n_proto_mask;
- filter->ip_proto = key->ip_proto;
+ filter->ip_proto = match.key->ip_proto;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
- struct flow_dissector_key_eth_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
+ flow_rule_match_eth_addrs(rule, &match);
/* use is_broadcast and is_zero to check for all 0xf or 0 */
- if (!is_zero_ether_addr(mask->dst)) {
- if (is_broadcast_ether_addr(mask->dst)) {
+ if (!is_zero_ether_addr(match.mask->dst)) {
+ if (is_broadcast_ether_addr(match.mask->dst)) {
field_flags |= I40E_CLOUD_FIELD_OMAC;
} else {
dev_err(&pf->pdev->dev, "Bad ether dest mask %pM\n",
- mask->dst);
+ match.mask->dst);
return I40E_ERR_CONFIG;
}
}
- if (!is_zero_ether_addr(mask->src)) {
- if (is_broadcast_ether_addr(mask->src)) {
+ if (!is_zero_ether_addr(match.mask->src)) {
+ if (is_broadcast_ether_addr(match.mask->src)) {
field_flags |= I40E_CLOUD_FIELD_IMAC;
} else {
dev_err(&pf->pdev->dev, "Bad ether src mask %pM\n",
- mask->src);
+ match.mask->src);
return I40E_ERR_CONFIG;
}
}
- ether_addr_copy(filter->dst_mac, key->dst);
- ether_addr_copy(filter->src_mac, key->src);
+ ether_addr_copy(filter->dst_mac, match.key->dst);
+ ether_addr_copy(filter->src_mac, match.key->src);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
- if (mask->vlan_id) {
- if (mask->vlan_id == VLAN_VID_MASK) {
+ flow_rule_match_vlan(rule, &match);
+ if (match.mask->vlan_id) {
+ if (match.mask->vlan_id == VLAN_VID_MASK) {
field_flags |= I40E_CLOUD_FIELD_IVLAN;
} else {
dev_err(&pf->pdev->dev, "Bad vlan mask 0x%04x\n",
- mask->vlan_id);
+ match.mask->vlan_id);
return I40E_ERR_CONFIG;
}
}
- filter->vlan_id = cpu_to_be16(key->vlan_id);
+ filter->vlan_id = cpu_to_be16(match.key->vlan_id);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
- addr_type = key->addr_type;
+ flow_rule_match_control(rule, &match);
+ addr_type = match.key->addr_type;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
-
- if (mask->dst) {
- if (mask->dst == cpu_to_be32(0xffffffff)) {
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_ipv4_addrs(rule, &match);
+ if (match.mask->dst) {
+ if (match.mask->dst == cpu_to_be32(0xffffffff)) {
field_flags |= I40E_CLOUD_FIELD_IIP;
} else {
dev_err(&pf->pdev->dev, "Bad ip dst mask %pI4b\n",
- &mask->dst);
+ &match.mask->dst);
return I40E_ERR_CONFIG;
}
}
- if (mask->src) {
- if (mask->src == cpu_to_be32(0xffffffff)) {
+ if (match.mask->src) {
+ if (match.mask->src == cpu_to_be32(0xffffffff)) {
field_flags |= I40E_CLOUD_FIELD_IIP;
} else {
dev_err(&pf->pdev->dev, "Bad ip src mask %pI4b\n",
- &mask->src);
+ &match.mask->src);
return I40E_ERR_CONFIG;
}
}
@@ -7328,70 +7304,60 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi,
dev_err(&pf->pdev->dev, "Tenant id not allowed for ip filter\n");
return I40E_ERR_CONFIG;
}
- filter->dst_ipv4 = key->dst;
- filter->src_ipv4 = key->src;
+ filter->dst_ipv4 = match.key->dst;
+ filter->src_ipv4 = match.key->src;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
+ struct flow_match_ipv6_addrs match;
+
+ flow_rule_match_ipv6_addrs(rule, &match);
/* src and dest IPV6 address should not be LOOPBACK
* (0:0:0:0:0:0:0:1), which can be represented as ::1
*/
- if (ipv6_addr_loopback(&key->dst) ||
- ipv6_addr_loopback(&key->src)) {
+ if (ipv6_addr_loopback(&match.key->dst) ||
+ ipv6_addr_loopback(&match.key->src)) {
dev_err(&pf->pdev->dev,
"Bad ipv6, addr is LOOPBACK\n");
return I40E_ERR_CONFIG;
}
- if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src))
+ if (!ipv6_addr_any(&match.mask->dst) ||
+ !ipv6_addr_any(&match.mask->src))
field_flags |= I40E_CLOUD_FIELD_IIP;
- memcpy(&filter->src_ipv6, &key->src.s6_addr32,
+ memcpy(&filter->src_ipv6, &match.key->src.s6_addr32,
sizeof(filter->src_ipv6));
- memcpy(&filter->dst_ipv6, &key->dst.s6_addr32,
+ memcpy(&filter->dst_ipv6, &match.key->dst.s6_addr32,
sizeof(filter->dst_ipv6));
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- struct flow_dissector_key_ports *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
- if (mask->src) {
- if (mask->src == cpu_to_be16(0xffff)) {
+ flow_rule_match_ports(rule, &match);
+ if (match.mask->src) {
+ if (match.mask->src == cpu_to_be16(0xffff)) {
field_flags |= I40E_CLOUD_FIELD_IIP;
} else {
dev_err(&pf->pdev->dev, "Bad src port mask 0x%04x\n",
- be16_to_cpu(mask->src));
+ be16_to_cpu(match.mask->src));
return I40E_ERR_CONFIG;
}
}
- if (mask->dst) {
- if (mask->dst == cpu_to_be16(0xffff)) {
+ if (match.mask->dst) {
+ if (match.mask->dst == cpu_to_be16(0xffff)) {
field_flags |= I40E_CLOUD_FIELD_IIP;
} else {
dev_err(&pf->pdev->dev, "Bad dst port mask 0x%04x\n",
- be16_to_cpu(mask->dst));
+ be16_to_cpu(match.mask->dst));
return I40E_ERR_CONFIG;
}
}
- filter->dst_port = key->dst;
- filter->src_port = key->src;
+ filter->dst_port = match.key->dst;
+ filter->src_port = match.key->src;
switch (filter->ip_proto) {
case IPPROTO_TCP:
@@ -8131,8 +8097,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
i40e_service_event_schedule(pf);
} else {
i40e_pf_unquiesce_all_vsi(pf);
- set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state);
- set_bit(__I40E_CLIENT_L2_CHANGE, pf->state);
+ set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state);
+ set_bit(__I40E_CLIENT_L2_CHANGE, pf->state);
}
exit:
@@ -11042,6 +11008,7 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
if (!(pf->flags & I40E_FLAG_RSS_ENABLED))
return 0;
+ queue_count = min_t(int, queue_count, num_online_cpus());
new_rss_size = min_t(int, queue_count, pf->rss_size_max);
if (queue_count != vsi->num_queue_pairs) {
@@ -11644,7 +11611,8 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags)
+ u16 flags,
+ struct netlink_ext_ack *extack)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_pf *pf = np->vsi->back;
@@ -11895,6 +11863,14 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,
if (old_prog)
bpf_prog_put(old_prog);
+ /* Kick start the NAPI context if there is an AF_XDP socket open
+ * on that queue id. This so that receiving will start.
+ */
+ if (need_reset && prog)
+ for (i = 0; i < vsi->num_queue_pairs; i++)
+ if (vsi->xdp_rings[i]->xsk_umem)
+ (void)i40e_xsk_async_xmit(vsi->netdev, i);
+
return 0;
}
@@ -11955,8 +11931,13 @@ static void i40e_queue_pair_reset_stats(struct i40e_vsi *vsi, int queue_pair)
static void i40e_queue_pair_clean_rings(struct i40e_vsi *vsi, int queue_pair)
{
i40e_clean_tx_ring(vsi->tx_rings[queue_pair]);
- if (i40e_enabled_xdp_vsi(vsi))
+ if (i40e_enabled_xdp_vsi(vsi)) {
+ /* Make sure that in-progress ndo_xdp_xmit calls are
+ * completed.
+ */
+ synchronize_rcu();
i40e_clean_tx_ring(vsi->xdp_rings[queue_pair]);
+ }
i40e_clean_rx_ring(vsi->rx_rings[queue_pair]);
}
@@ -12168,9 +12149,6 @@ static int i40e_xdp(struct net_device *dev,
case XDP_QUERY_PROG:
xdp->prog_id = vsi->xdp_prog ? vsi->xdp_prog->aux->id : 0;
return 0;
- case XDP_QUERY_XSK_UMEM:
- return i40e_xsk_umem_query(vsi, &xdp->xsk.umem,
- xdp->xsk.queue_id);
case XDP_SETUP_XSK_UMEM:
return i40e_xsk_umem_setup(vsi, xdp->xsk.umem,
xdp->xsk.queue_id);
@@ -13859,6 +13837,29 @@ static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
}
/**
+ * i40e_set_fec_in_flags - helper function for setting FEC options in flags
+ * @fec_cfg: FEC option to set in flags
+ * @flags: ptr to flags in which we set FEC option
+ **/
+void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags)
+{
+ if (fec_cfg & I40E_AQ_SET_FEC_AUTO)
+ *flags |= I40E_FLAG_RS_FEC | I40E_FLAG_BASE_R_FEC;
+ if ((fec_cfg & I40E_AQ_SET_FEC_REQUEST_RS) ||
+ (fec_cfg & I40E_AQ_SET_FEC_ABILITY_RS)) {
+ *flags |= I40E_FLAG_RS_FEC;
+ *flags &= ~I40E_FLAG_BASE_R_FEC;
+ }
+ if ((fec_cfg & I40E_AQ_SET_FEC_REQUEST_KR) ||
+ (fec_cfg & I40E_AQ_SET_FEC_ABILITY_KR)) {
+ *flags |= I40E_FLAG_BASE_R_FEC;
+ *flags &= ~I40E_FLAG_RS_FEC;
+ }
+ if (fec_cfg == 0)
+ *flags &= ~(I40E_FLAG_RS_FEC | I40E_FLAG_BASE_R_FEC);
+}
+
+/**
* i40e_probe - Device initialization routine
* @pdev: PCI device information struct
* @ent: entry in i40e_pci_tbl
@@ -14349,6 +14350,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
pf->hw.phy.link_info.requested_speeds = abilities.link_speed;
+ /* set the FEC config due to the board capabilities */
+ i40e_set_fec_in_flags(abilities.fec_cfg_curr_mod_ext_info, &pf->flags);
+
/* get the supported phy types from the fw */
err = i40e_aq_get_phy_capabilities(hw, false, true, &abilities, NULL);
if (err)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index a7e14e98889f..6c97667d20ef 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -3709,6 +3709,7 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
struct i40e_netdev_priv *np = netdev_priv(dev);
unsigned int queue_index = smp_processor_id();
struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
struct i40e_ring *xdp_ring;
int drops = 0;
int i;
@@ -3716,7 +3717,8 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
if (test_bit(__I40E_VSI_DOWN, vsi->state))
return -ENETDOWN;
- if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
+ if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs ||
+ test_bit(__I40E_CONFIG_BUSY, pf->state))
return -ENXIO;
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 2ac23ebfbf31..831d52bc3c9a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2069,6 +2069,11 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
goto error_param;
}
+ if (qci->num_queue_pairs > I40E_MAX_VF_QUEUES) {
+ aq_ret = I40E_ERR_PARAM;
+ goto error_param;
+ }
+
for (i = 0; i < qci->num_queue_pairs; i++) {
qpi = &qci->qpair[i];
@@ -3384,8 +3389,8 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
dev_info(&pf->pdev->dev,
"VF %d: Invalid input/s, can't apply cloud filter\n",
vf->vf_id);
- aq_ret = I40E_ERR_PARAM;
- goto err;
+ aq_ret = I40E_ERR_PARAM;
+ goto err;
}
cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL);
@@ -3656,7 +3661,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
int ret;
pf->vf_aq_requests++;
- if (local_vf_id >= pf->num_alloc_vfs)
+ if (local_vf_id < 0 || local_vf_id >= pf->num_alloc_vfs)
return -EINVAL;
vf = &(pf->vf[local_vf_id]);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index 870cf654e436..b5c182e688e3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -10,69 +10,6 @@
#include "i40e_xsk.h"
/**
- * i40e_alloc_xsk_umems - Allocate an array to store per ring UMEMs
- * @vsi: Current VSI
- *
- * Returns 0 on success, <0 on failure
- **/
-static int i40e_alloc_xsk_umems(struct i40e_vsi *vsi)
-{
- if (vsi->xsk_umems)
- return 0;
-
- vsi->num_xsk_umems_used = 0;
- vsi->num_xsk_umems = vsi->alloc_queue_pairs;
- vsi->xsk_umems = kcalloc(vsi->num_xsk_umems, sizeof(*vsi->xsk_umems),
- GFP_KERNEL);
- if (!vsi->xsk_umems) {
- vsi->num_xsk_umems = 0;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/**
- * i40e_add_xsk_umem - Store a UMEM for a certain ring/qid
- * @vsi: Current VSI
- * @umem: UMEM to store
- * @qid: Ring/qid to associate with the UMEM
- *
- * Returns 0 on success, <0 on failure
- **/
-static int i40e_add_xsk_umem(struct i40e_vsi *vsi, struct xdp_umem *umem,
- u16 qid)
-{
- int err;
-
- err = i40e_alloc_xsk_umems(vsi);
- if (err)
- return err;
-
- vsi->xsk_umems[qid] = umem;
- vsi->num_xsk_umems_used++;
-
- return 0;
-}
-
-/**
- * i40e_remove_xsk_umem - Remove a UMEM for a certain ring/qid
- * @vsi: Current VSI
- * @qid: Ring/qid associated with the UMEM
- **/
-static void i40e_remove_xsk_umem(struct i40e_vsi *vsi, u16 qid)
-{
- vsi->xsk_umems[qid] = NULL;
- vsi->num_xsk_umems_used--;
-
- if (vsi->num_xsk_umems == 0) {
- kfree(vsi->xsk_umems);
- vsi->xsk_umems = NULL;
- vsi->num_xsk_umems = 0;
- }
-}
-
-/**
* i40e_xsk_umem_dma_map - DMA maps all UMEM memory for the netdev
* @vsi: Current VSI
* @umem: UMEM to DMA map
@@ -140,6 +77,7 @@ static void i40e_xsk_umem_dma_unmap(struct i40e_vsi *vsi, struct xdp_umem *umem)
static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
u16 qid)
{
+ struct net_device *netdev = vsi->netdev;
struct xdp_umem_fq_reuse *reuseq;
bool if_running;
int err;
@@ -150,12 +88,9 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
if (qid >= vsi->num_queue_pairs)
return -EINVAL;
- if (vsi->xsk_umems) {
- if (qid >= vsi->num_xsk_umems)
- return -EINVAL;
- if (vsi->xsk_umems[qid])
- return -EBUSY;
- }
+ if (qid >= netdev->real_num_rx_queues ||
+ qid >= netdev->real_num_tx_queues)
+ return -EINVAL;
reuseq = xsk_reuseq_prepare(vsi->rx_rings[0]->count);
if (!reuseq)
@@ -173,16 +108,15 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
err = i40e_queue_pair_disable(vsi, qid);
if (err)
return err;
- }
- err = i40e_add_xsk_umem(vsi, umem, qid);
- if (err)
- return err;
-
- if (if_running) {
err = i40e_queue_pair_enable(vsi, qid);
if (err)
return err;
+
+ /* Kick start the NAPI context so that receiving will start */
+ err = i40e_xsk_async_xmit(vsi->netdev, qid);
+ if (err)
+ return err;
}
return 0;
@@ -197,11 +131,13 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
**/
static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
{
+ struct net_device *netdev = vsi->netdev;
+ struct xdp_umem *umem;
bool if_running;
int err;
- if (!vsi->xsk_umems || qid >= vsi->num_xsk_umems ||
- !vsi->xsk_umems[qid])
+ umem = xdp_get_umem_from_qid(netdev, qid);
+ if (!umem)
return -EINVAL;
if_running = netif_running(vsi->netdev) && i40e_enabled_xdp_vsi(vsi);
@@ -212,8 +148,7 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
return err;
}
- i40e_xsk_umem_dma_unmap(vsi, vsi->xsk_umems[qid]);
- i40e_remove_xsk_umem(vsi, qid);
+ i40e_xsk_umem_dma_unmap(vsi, umem);
if (if_running) {
err = i40e_queue_pair_enable(vsi, qid);
@@ -225,36 +160,6 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
}
/**
- * i40e_xsk_umem_query - Queries a certain ring/qid for its UMEM
- * @vsi: Current VSI
- * @umem: UMEM associated to the ring, if any
- * @qid: Rx ring to associate UMEM to
- *
- * This function will store, if any, the UMEM associated to certain ring.
- *
- * Returns 0 on success, <0 on failure
- **/
-int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem,
- u16 qid)
-{
- if (vsi->type != I40E_VSI_MAIN)
- return -EINVAL;
-
- if (qid >= vsi->num_queue_pairs)
- return -EINVAL;
-
- if (vsi->xsk_umems) {
- if (qid >= vsi->num_xsk_umems)
- return -EINVAL;
- *umem = vsi->xsk_umems[qid];
- return 0;
- }
-
- *umem = NULL;
- return 0;
-}
-
-/**
* i40e_xsk_umem_setup - Enable/disassociate a UMEM to/from a ring/qid
* @vsi: Current VSI
* @umem: UMEM to enable/associate to a ring, or NULL to disable
@@ -945,13 +850,11 @@ void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring)
**/
bool i40e_xsk_any_rx_ring_enabled(struct i40e_vsi *vsi)
{
+ struct net_device *netdev = vsi->netdev;
int i;
- if (!vsi->xsk_umems)
- return false;
-
for (i = 0; i < vsi->num_queue_pairs; i++) {
- if (vsi->xsk_umems[i])
+ if (xdp_get_umem_from_qid(netdev, i))
return true;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.h b/drivers/net/ethernet/intel/i40e/i40e_xsk.h
index 9038c5d5cf08..8cc0a2e7d9a2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.h
@@ -10,8 +10,6 @@ struct zero_copy_allocator;
int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair);
int i40e_queue_pair_enable(struct i40e_vsi *vsi, int queue_pair);
-int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem,
- u16 qid);
int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem,
u16 qid);
void i40e_zca_free(struct zero_copy_allocator *alloc, unsigned long handle);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 9f2b7b7adf6b..4569d69a2b55 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2439,6 +2439,8 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
struct tc_cls_flower_offload *f,
struct iavf_cloud_filter *filter)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_dissector *dissector = rule->match.dissector;
u16 n_proto_mask = 0;
u16 n_proto_key = 0;
u8 field_flags = 0;
@@ -2447,7 +2449,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
int i = 0;
struct virtchnl_filter *vf = &filter->f;
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -2457,32 +2459,24 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
BIT(FLOW_DISSECTOR_KEY_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) {
dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
- f->dissector->used_keys);
+ dissector->used_keys);
return -EOPNOTSUPP;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid match;
- if (mask->keyid != 0)
+ flow_rule_match_enc_keyid(rule, &match);
+ if (match.mask->keyid != 0)
field_flags |= IAVF_CLOUD_FIELD_TEN_ID;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
- n_proto_key = ntohs(key->n_proto);
- n_proto_mask = ntohs(mask->n_proto);
+ flow_rule_match_basic(rule, &match);
+ n_proto_key = ntohs(match.key->n_proto);
+ n_proto_mask = ntohs(match.mask->n_proto);
if (n_proto_key == ETH_P_ALL) {
n_proto_key = 0;
@@ -2496,122 +2490,103 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
vf->flow_type = VIRTCHNL_TCP_V6_FLOW;
}
- if (key->ip_proto != IPPROTO_TCP) {
+ if (match.key->ip_proto != IPPROTO_TCP) {
dev_info(&adapter->pdev->dev, "Only TCP transport is supported\n");
return -EINVAL;
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
+
+ flow_rule_match_eth_addrs(rule, &match);
- struct flow_dissector_key_eth_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
/* use is_broadcast and is_zero to check for all 0xf or 0 */
- if (!is_zero_ether_addr(mask->dst)) {
- if (is_broadcast_ether_addr(mask->dst)) {
+ if (!is_zero_ether_addr(match.mask->dst)) {
+ if (is_broadcast_ether_addr(match.mask->dst)) {
field_flags |= IAVF_CLOUD_FIELD_OMAC;
} else {
dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n",
- mask->dst);
+ match.mask->dst);
return I40E_ERR_CONFIG;
}
}
- if (!is_zero_ether_addr(mask->src)) {
- if (is_broadcast_ether_addr(mask->src)) {
+ if (!is_zero_ether_addr(match.mask->src)) {
+ if (is_broadcast_ether_addr(match.mask->src)) {
field_flags |= IAVF_CLOUD_FIELD_IMAC;
} else {
dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n",
- mask->src);
+ match.mask->src);
return I40E_ERR_CONFIG;
}
}
- if (!is_zero_ether_addr(key->dst))
- if (is_valid_ether_addr(key->dst) ||
- is_multicast_ether_addr(key->dst)) {
+ if (!is_zero_ether_addr(match.key->dst))
+ if (is_valid_ether_addr(match.key->dst) ||
+ is_multicast_ether_addr(match.key->dst)) {
/* set the mask if a valid dst_mac address */
for (i = 0; i < ETH_ALEN; i++)
vf->mask.tcp_spec.dst_mac[i] |= 0xff;
ether_addr_copy(vf->data.tcp_spec.dst_mac,
- key->dst);
+ match.key->dst);
}
- if (!is_zero_ether_addr(key->src))
- if (is_valid_ether_addr(key->src) ||
- is_multicast_ether_addr(key->src)) {
+ if (!is_zero_ether_addr(match.key->src))
+ if (is_valid_ether_addr(match.key->src) ||
+ is_multicast_ether_addr(match.key->src)) {
/* set the mask if a valid dst_mac address */
for (i = 0; i < ETH_ALEN; i++)
vf->mask.tcp_spec.src_mac[i] |= 0xff;
ether_addr_copy(vf->data.tcp_spec.src_mac,
- key->src);
+ match.key->src);
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
- if (mask->vlan_id) {
- if (mask->vlan_id == VLAN_VID_MASK) {
+ flow_rule_match_vlan(rule, &match);
+ if (match.mask->vlan_id) {
+ if (match.mask->vlan_id == VLAN_VID_MASK) {
field_flags |= IAVF_CLOUD_FIELD_IVLAN;
} else {
dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n",
- mask->vlan_id);
+ match.mask->vlan_id);
return I40E_ERR_CONFIG;
}
}
vf->mask.tcp_spec.vlan_id |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.vlan_id = cpu_to_be16(key->vlan_id);
+ vf->data.tcp_spec.vlan_id = cpu_to_be16(match.key->vlan_id);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
- addr_type = key->addr_type;
+ flow_rule_match_control(rule, &match);
+ addr_type = match.key->addr_type;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
-
- if (mask->dst) {
- if (mask->dst == cpu_to_be32(0xffffffff)) {
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_ipv4_addrs(rule, &match);
+ if (match.mask->dst) {
+ if (match.mask->dst == cpu_to_be32(0xffffffff)) {
field_flags |= IAVF_CLOUD_FIELD_IIP;
} else {
dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n",
- be32_to_cpu(mask->dst));
+ be32_to_cpu(match.mask->dst));
return I40E_ERR_CONFIG;
}
}
- if (mask->src) {
- if (mask->src == cpu_to_be32(0xffffffff)) {
+ if (match.mask->src) {
+ if (match.mask->src == cpu_to_be32(0xffffffff)) {
field_flags |= IAVF_CLOUD_FIELD_IIP;
} else {
dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n",
- be32_to_cpu(mask->dst));
+ be32_to_cpu(match.mask->dst));
return I40E_ERR_CONFIG;
}
}
@@ -2620,28 +2595,23 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
dev_info(&adapter->pdev->dev, "Tenant id not allowed for ip filter\n");
return I40E_ERR_CONFIG;
}
- if (key->dst) {
+ if (match.key->dst) {
vf->mask.tcp_spec.dst_ip[0] |= cpu_to_be32(0xffffffff);
- vf->data.tcp_spec.dst_ip[0] = key->dst;
+ vf->data.tcp_spec.dst_ip[0] = match.key->dst;
}
- if (key->src) {
+ if (match.key->src) {
vf->mask.tcp_spec.src_ip[0] |= cpu_to_be32(0xffffffff);
- vf->data.tcp_spec.src_ip[0] = key->src;
+ vf->data.tcp_spec.src_ip[0] = match.key->src;
}
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
+ struct flow_match_ipv6_addrs match;
+
+ flow_rule_match_ipv6_addrs(rule, &match);
/* validate mask, make sure it is not IPV6_ADDR_ANY */
- if (ipv6_addr_any(&mask->dst)) {
+ if (ipv6_addr_any(&match.mask->dst)) {
dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",
IPV6_ADDR_ANY);
return I40E_ERR_CONFIG;
@@ -2650,61 +2620,56 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter,
/* src and dest IPv6 address should not be LOOPBACK
* (0:0:0:0:0:0:0:1) which can be represented as ::1
*/
- if (ipv6_addr_loopback(&key->dst) ||
- ipv6_addr_loopback(&key->src)) {
+ if (ipv6_addr_loopback(&match.key->dst) ||
+ ipv6_addr_loopback(&match.key->src)) {
dev_err(&adapter->pdev->dev,
"ipv6 addr should not be loopback\n");
return I40E_ERR_CONFIG;
}
- if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src))
+ if (!ipv6_addr_any(&match.mask->dst) ||
+ !ipv6_addr_any(&match.mask->src))
field_flags |= IAVF_CLOUD_FIELD_IIP;
for (i = 0; i < 4; i++)
vf->mask.tcp_spec.dst_ip[i] |= cpu_to_be32(0xffffffff);
- memcpy(&vf->data.tcp_spec.dst_ip, &key->dst.s6_addr32,
+ memcpy(&vf->data.tcp_spec.dst_ip, &match.key->dst.s6_addr32,
sizeof(vf->data.tcp_spec.dst_ip));
for (i = 0; i < 4; i++)
vf->mask.tcp_spec.src_ip[i] |= cpu_to_be32(0xffffffff);
- memcpy(&vf->data.tcp_spec.src_ip, &key->src.s6_addr32,
+ memcpy(&vf->data.tcp_spec.src_ip, &match.key->src.s6_addr32,
sizeof(vf->data.tcp_spec.src_ip));
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- struct flow_dissector_key_ports *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
-
- if (mask->src) {
- if (mask->src == cpu_to_be16(0xffff)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
+
+ flow_rule_match_ports(rule, &match);
+ if (match.mask->src) {
+ if (match.mask->src == cpu_to_be16(0xffff)) {
field_flags |= IAVF_CLOUD_FIELD_IIP;
} else {
dev_err(&adapter->pdev->dev, "Bad src port mask %u\n",
- be16_to_cpu(mask->src));
+ be16_to_cpu(match.mask->src));
return I40E_ERR_CONFIG;
}
}
- if (mask->dst) {
- if (mask->dst == cpu_to_be16(0xffff)) {
+ if (match.mask->dst) {
+ if (match.mask->dst == cpu_to_be16(0xffff)) {
field_flags |= IAVF_CLOUD_FIELD_IIP;
} else {
dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n",
- be16_to_cpu(mask->dst));
+ be16_to_cpu(match.mask->dst));
return I40E_ERR_CONFIG;
}
}
- if (key->dst) {
+ if (match.key->dst) {
vf->mask.tcp_spec.dst_port |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.dst_port = key->dst;
+ vf->data.tcp_spec.dst_port = match.key->dst;
}
- if (key->src) {
+ if (match.key->src) {
vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.src_port = key->src;
+ vf->data.tcp_spec.src_port = match.key->src;
}
}
vf->field_flags = field_flags;
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index a385575600f6..89440775aea1 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -26,6 +26,7 @@
#include <linux/bitmap.h>
#include <linux/log2.h>
#include <linux/ip.h>
+#include <linux/sctp.h>
#include <linux/ipv6.h>
#include <linux/if_bridge.h>
#include <linux/avf/virtchnl.h>
@@ -82,7 +83,7 @@ extern const char ice_drv_ver[];
#define ICE_DFLT_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
#define ICE_MAX_MTU (ICE_AQ_SET_MAC_FRAME_SIZE_MAX - \
- ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
+ (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2)))
#define ICE_UP_TABLE_TRANSLATE(val, i) \
(((val) << ICE_AQ_VSI_UP_TABLE_UP##i##_S) & \
@@ -110,6 +111,9 @@ extern const char ice_drv_ver[];
#define ice_for_each_alloc_rxq(vsi, i) \
for ((i) = 0; (i) < (vsi)->alloc_rxq; (i)++)
+#define ice_for_each_q_vector(vsi, i) \
+ for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)
+
struct ice_tc_info {
u16 qoffset;
u16 qcount_tx;
@@ -129,6 +133,17 @@ struct ice_res_tracker {
u16 list[1];
};
+struct ice_qs_cfg {
+ struct mutex *qs_mutex; /* will be assgined to &pf->avail_q_mutex */
+ unsigned long *pf_map;
+ unsigned long pf_map_size;
+ unsigned int q_count;
+ unsigned int scatter_count;
+ u16 *vsi_map;
+ u16 vsi_map_offset;
+ u8 mapping_mode;
+};
+
struct ice_sw {
struct ice_pf *pf;
u16 sw_id; /* switch ID for this switch */
@@ -270,6 +285,7 @@ enum ice_pf_flags {
ICE_FLAG_RSS_ENA,
ICE_FLAG_SRIOV_ENA,
ICE_FLAG_SRIOV_CAPABLE,
+ ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA,
ICE_PF_FLAGS_NBITS /* must be last */
};
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index fcdcd80b18e7..242c78469181 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -657,8 +657,13 @@ struct ice_aqc_get_topo {
/* Update TSE (indirect 0x0403)
* Get TSE (indirect 0x0404)
+ * Add TSE (indirect 0x0401)
+ * Delete TSE (indirect 0x040F)
+ * Move TSE (indirect 0x0408)
+ * Suspend Nodes (indirect 0x0409)
+ * Resume Nodes (indirect 0x040A)
*/
-struct ice_aqc_get_cfg_elem {
+struct ice_aqc_sched_elem_cmd {
__le16 num_elem_req; /* Used by commands */
__le16 num_elem_resp; /* Used by responses */
__le32 reserved;
@@ -674,18 +679,6 @@ struct ice_aqc_suspend_resume_elem {
__le32 teid[1];
};
-/* Add TSE (indirect 0x0401)
- * Delete TSE (indirect 0x040F)
- * Move TSE (indirect 0x0408)
- */
-struct ice_aqc_add_move_delete_elem {
- __le16 num_grps_req;
- __le16 num_grps_updated;
- __le32 reserved;
- __le32 addr_high;
- __le32 addr_low;
-};
-
struct ice_aqc_elem_info_bw {
__le16 bw_profile_idx;
__le16 bw_alloc;
@@ -854,11 +847,46 @@ struct ice_aqc_get_phy_caps {
#define ICE_PHY_TYPE_LOW_40GBASE_KR4 BIT_ULL(33)
#define ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC BIT_ULL(34)
#define ICE_PHY_TYPE_LOW_40G_XLAUI BIT_ULL(35)
+#define ICE_PHY_TYPE_LOW_50GBASE_CR2 BIT_ULL(36)
+#define ICE_PHY_TYPE_LOW_50GBASE_SR2 BIT_ULL(37)
+#define ICE_PHY_TYPE_LOW_50GBASE_LR2 BIT_ULL(38)
+#define ICE_PHY_TYPE_LOW_50GBASE_KR2 BIT_ULL(39)
+#define ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC BIT_ULL(40)
+#define ICE_PHY_TYPE_LOW_50G_LAUI2 BIT_ULL(41)
+#define ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC BIT_ULL(42)
+#define ICE_PHY_TYPE_LOW_50G_AUI2 BIT_ULL(43)
+#define ICE_PHY_TYPE_LOW_50GBASE_CP BIT_ULL(44)
+#define ICE_PHY_TYPE_LOW_50GBASE_SR BIT_ULL(45)
+#define ICE_PHY_TYPE_LOW_50GBASE_FR BIT_ULL(46)
+#define ICE_PHY_TYPE_LOW_50GBASE_LR BIT_ULL(47)
+#define ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4 BIT_ULL(48)
+#define ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC BIT_ULL(49)
+#define ICE_PHY_TYPE_LOW_50G_AUI1 BIT_ULL(50)
+#define ICE_PHY_TYPE_LOW_100GBASE_CR4 BIT_ULL(51)
+#define ICE_PHY_TYPE_LOW_100GBASE_SR4 BIT_ULL(52)
+#define ICE_PHY_TYPE_LOW_100GBASE_LR4 BIT_ULL(53)
+#define ICE_PHY_TYPE_LOW_100GBASE_KR4 BIT_ULL(54)
+#define ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC BIT_ULL(55)
+#define ICE_PHY_TYPE_LOW_100G_CAUI4 BIT_ULL(56)
+#define ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC BIT_ULL(57)
+#define ICE_PHY_TYPE_LOW_100G_AUI4 BIT_ULL(58)
+#define ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 BIT_ULL(59)
+#define ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 BIT_ULL(60)
+#define ICE_PHY_TYPE_LOW_100GBASE_CP2 BIT_ULL(61)
+#define ICE_PHY_TYPE_LOW_100GBASE_SR2 BIT_ULL(62)
+#define ICE_PHY_TYPE_LOW_100GBASE_DR BIT_ULL(63)
#define ICE_PHY_TYPE_LOW_MAX_INDEX 63
+/* The second set of defines is for phy_type_high. */
+#define ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4 BIT_ULL(0)
+#define ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC BIT_ULL(1)
+#define ICE_PHY_TYPE_HIGH_100G_CAUI2 BIT_ULL(2)
+#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC BIT_ULL(3)
+#define ICE_PHY_TYPE_HIGH_100G_AUI2 BIT_ULL(4)
+#define ICE_PHY_TYPE_HIGH_MAX_INDEX 19
struct ice_aqc_get_phy_caps_data {
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
- __le64 reserved;
+ __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
u8 caps;
#define ICE_AQC_PHY_EN_TX_LINK_PAUSE BIT(0)
#define ICE_AQC_PHY_EN_RX_LINK_PAUSE BIT(1)
@@ -923,7 +951,7 @@ struct ice_aqc_set_phy_cfg {
/* Set PHY config command data structure */
struct ice_aqc_set_phy_cfg_data {
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
- __le64 rsvd0;
+ __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
u8 caps;
#define ICE_AQ_PHY_ENA_TX_PAUSE_ABILITY BIT(0)
#define ICE_AQ_PHY_ENA_RX_PAUSE_ABILITY BIT(1)
@@ -1032,10 +1060,12 @@ struct ice_aqc_get_link_status_data {
#define ICE_AQ_LINK_SPEED_20GB BIT(6)
#define ICE_AQ_LINK_SPEED_25GB BIT(7)
#define ICE_AQ_LINK_SPEED_40GB BIT(8)
+#define ICE_AQ_LINK_SPEED_50GB BIT(9)
+#define ICE_AQ_LINK_SPEED_100GB BIT(10)
#define ICE_AQ_LINK_SPEED_UNKNOWN BIT(15)
__le32 reserved3; /* Aligns next field to 8-byte boundary */
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
- __le64 reserved4;
+ __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
};
/* Set event mask command (direct 0x0613) */
@@ -1055,6 +1085,16 @@ struct ice_aqc_set_event_mask {
u8 reserved1[6];
};
+/* Set Port Identification LED (direct, 0x06E9) */
+struct ice_aqc_set_port_id_led {
+ u8 lport_num;
+ u8 lport_num_valid;
+ u8 ident_mode;
+#define ICE_AQC_PORT_IDENT_LED_BLINK BIT(0)
+#define ICE_AQC_PORT_IDENT_LED_ORIG 0
+ u8 rsvd[13];
+};
+
/* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703)
@@ -1341,12 +1381,12 @@ struct ice_aq_desc {
struct ice_aqc_get_phy_caps get_phy;
struct ice_aqc_set_phy_cfg set_phy;
struct ice_aqc_restart_an restart_an;
+ struct ice_aqc_set_port_id_led set_port_id_led;
struct ice_aqc_get_sw_cfg get_sw_conf;
struct ice_aqc_sw_rules sw_rules;
struct ice_aqc_get_topo get_topo;
- struct ice_aqc_get_cfg_elem get_update_elem;
+ struct ice_aqc_sched_elem_cmd sched_elem_cmd;
struct ice_aqc_query_txsched_res query_sched_res;
- struct ice_aqc_add_move_delete_elem add_move_delete_elem;
struct ice_aqc_nvm nvm;
struct ice_aqc_pf_vf_msg virt;
struct ice_aqc_get_set_rss_lut get_set_rss_lut;
@@ -1442,6 +1482,7 @@ enum ice_adminq_opc {
ice_aqc_opc_restart_an = 0x0605,
ice_aqc_opc_get_link_status = 0x0607,
ice_aqc_opc_set_event_mask = 0x0613,
+ ice_aqc_opc_set_port_id_led = 0x06E9,
/* NVM commands */
ice_aqc_opc_nvm_read = 0x0701,
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 4c1d35da940d..63f003441300 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -165,8 +165,10 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
cmd->param0 |= cpu_to_le16(report_mode);
status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd);
- if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP)
+ if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
+ pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
+ }
return status;
}
@@ -183,6 +185,9 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
return ICE_MEDIA_UNKNOWN;
hw_link_info = &pi->phy.link_info;
+ if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
+ /* If more than one media type is selected, report unknown */
+ return ICE_MEDIA_UNKNOWN;
if (hw_link_info->phy_type_low) {
switch (hw_link_info->phy_type_low) {
@@ -196,6 +201,15 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
case ICE_PHY_TYPE_LOW_40GBASE_SR4:
case ICE_PHY_TYPE_LOW_40GBASE_LR4:
+ case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_SR:
+ case ICE_PHY_TYPE_LOW_50GBASE_FR:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR:
+ case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+ case ICE_PHY_TYPE_LOW_100GBASE_DR:
return ICE_MEDIA_FIBER;
case ICE_PHY_TYPE_LOW_100BASE_TX:
case ICE_PHY_TYPE_LOW_1000BASE_T:
@@ -209,6 +223,11 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
case ICE_PHY_TYPE_LOW_25GBASE_CR1:
case ICE_PHY_TYPE_LOW_40GBASE_CR4:
+ case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_CP:
+ case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+ case ICE_PHY_TYPE_LOW_100GBASE_CP2:
return ICE_MEDIA_DA;
case ICE_PHY_TYPE_LOW_1000BASE_KX:
case ICE_PHY_TYPE_LOW_2500BASE_KX:
@@ -219,10 +238,18 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
case ICE_PHY_TYPE_LOW_25GBASE_KR1:
case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
case ICE_PHY_TYPE_LOW_40GBASE_KR4:
+ case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+ case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+ case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+ return ICE_MEDIA_BACKPLANE;
+ }
+ } else {
+ switch (hw_link_info->phy_type_high) {
+ case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
return ICE_MEDIA_BACKPLANE;
}
}
-
return ICE_MEDIA_UNKNOWN;
}
@@ -274,6 +301,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
/* update current link status information */
hw_link_info->link_speed = le16_to_cpu(link_data.link_speed);
hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low);
+ hw_link_info->phy_type_high = le64_to_cpu(link_data.phy_type_high);
*hw_media_type = ice_get_media_type(pi);
hw_link_info->link_info = link_data.link_info;
hw_link_info->an_info = link_data.an_info;
@@ -750,6 +778,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
status = ICE_ERR_CFG;
goto err_unroll_sched;
}
+ INIT_LIST_HEAD(&hw->agg_list);
status = ice_init_fltr_mgmt_struct(hw);
if (status)
@@ -800,6 +829,7 @@ void ice_deinit_hw(struct ice_hw *hw)
ice_cleanup_fltr_mgmt_struct(hw);
ice_sched_cleanup_all(hw);
+ ice_sched_clear_agg(hw);
if (hw->port_info) {
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
@@ -1655,7 +1685,7 @@ enum ice_status ice_get_caps(struct ice_hw *hw)
* This function is used to write MAC address to the NVM (0x0108).
*/
enum ice_status
-ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags,
+ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
struct ice_sq_cd *cd)
{
struct ice_aqc_manage_mac_write *cmd;
@@ -1667,8 +1697,8 @@ ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags,
cmd->flags = flags;
/* Prep values for flags, sah, sal */
- cmd->sah = htons(*((u16 *)mac_addr));
- cmd->sal = htonl(*((u32 *)(mac_addr + 2)));
+ cmd->sah = htons(*((const u16 *)mac_addr));
+ cmd->sal = htonl(*((const u32 *)(mac_addr + 2)));
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
@@ -1705,16 +1735,20 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
/**
* ice_get_link_speed_based_on_phy_type - returns link speed
* @phy_type_low: lower part of phy_type
+ * @phy_type_high: higher part of phy_type
*
- * This helper function will convert a phy_type_low to its corresponding link
+ * This helper function will convert an entry in phy type structure
+ * [phy_type_low, phy_type_high] to its corresponding link speed.
+ * Note: In the structure of [phy_type_low, phy_type_high], there should
+ * be one bit set, as this function will convert one phy type to its
* speed.
- * Note: In the structure of phy_type_low, there should be one bit set, as
- * this function will convert one phy type to its speed.
* If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
* If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
*/
-static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low)
+static u16
+ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
{
+ u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
switch (phy_type_low) {
@@ -1768,41 +1802,110 @@ static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low)
case ICE_PHY_TYPE_LOW_40G_XLAUI:
speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
break;
+ case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+ case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_LAUI2:
+ case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_AUI2:
+ case ICE_PHY_TYPE_LOW_50GBASE_CP:
+ case ICE_PHY_TYPE_LOW_50GBASE_SR:
+ case ICE_PHY_TYPE_LOW_50GBASE_FR:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR:
+ case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+ case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_AUI1:
+ speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+ case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_100G_CAUI4:
+ case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_100G_AUI4:
+ case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+ case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+ case ICE_PHY_TYPE_LOW_100GBASE_CP2:
+ case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+ case ICE_PHY_TYPE_LOW_100GBASE_DR:
+ speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
+ break;
default:
speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
break;
}
- return speed_phy_type_low;
+ switch (phy_type_high) {
+ case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
+ case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
+ case ICE_PHY_TYPE_HIGH_100G_CAUI2:
+ case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
+ case ICE_PHY_TYPE_HIGH_100G_AUI2:
+ speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
+ break;
+ default:
+ speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
+ break;
+ }
+
+ if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
+ speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
+ return ICE_AQ_LINK_SPEED_UNKNOWN;
+ else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
+ speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
+ return ICE_AQ_LINK_SPEED_UNKNOWN;
+ else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
+ speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
+ return speed_phy_type_low;
+ else
+ return speed_phy_type_high;
}
/**
* ice_update_phy_type
* @phy_type_low: pointer to the lower part of phy_type
+ * @phy_type_high: pointer to the higher part of phy_type
* @link_speeds_bitmap: targeted link speeds bitmap
*
* Note: For the link_speeds_bitmap structure, you can check it at
* [ice_aqc_get_link_status->link_speed]. Caller can pass in
* link_speeds_bitmap include multiple speeds.
*
- * The value of phy_type_low will present a certain link speed. This helper
- * function will turn on bits in the phy_type_low based on the value of
+ * Each entry in this [phy_type_low, phy_type_high] structure will
+ * present a certain link speed. This helper function will turn on bits
+ * in [phy_type_low, phy_type_high] structure based on the value of
* link_speeds_bitmap input parameter.
*/
-void ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap)
+void
+ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
+ u16 link_speeds_bitmap)
{
u16 speed = ICE_AQ_LINK_SPEED_UNKNOWN;
+ u64 pt_high;
u64 pt_low;
int index;
/* We first check with low part of phy_type */
for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
pt_low = BIT_ULL(index);
- speed = ice_get_link_speed_based_on_phy_type(pt_low);
+ speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
if (link_speeds_bitmap & speed)
*phy_type_low |= BIT_ULL(index);
}
+
+ /* We then check with high part of phy_type */
+ for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
+ pt_high = BIT_ULL(index);
+ speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
+
+ if (link_speeds_bitmap & speed)
+ *phy_type_high |= BIT_ULL(index);
+ }
}
/**
@@ -1934,6 +2037,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
if (ena_auto_link_update)
cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
/* Copy over all the old settings */
+ cfg.phy_type_high = pcaps->phy_type_high;
cfg.phy_type_low = pcaps->phy_type_low;
cfg.low_power_ctrl = pcaps->low_power_ctrl;
cfg.eee_cap = pcaps->eee_cap;
@@ -2032,6 +2136,34 @@ ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
}
/**
+ * ice_aq_set_port_id_led
+ * @pi: pointer to the port information
+ * @is_orig_mode: is this LED set to original mode (by the net-list)
+ * @cd: pointer to command details structure or NULL
+ *
+ * Set LED value for the given port (0x06e9)
+ */
+enum ice_status
+ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_set_port_id_led *cmd;
+ struct ice_hw *hw = pi->hw;
+ struct ice_aq_desc desc;
+
+ cmd = &desc.params.set_port_id_led;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
+
+ if (is_orig_mode)
+ cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
+ else
+ cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
* __ice_aq_get_set_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: VSI FW index
@@ -2318,6 +2450,7 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
{
struct ice_aqc_dis_txqs *cmd;
struct ice_aq_desc desc;
+ enum ice_status status;
u16 i, sz = 0;
cmd = &desc.params.dis_txqs;
@@ -2353,6 +2486,8 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
break;
}
+ /* flush pipe on time out */
+ cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
/* If no queue group info, we are in a reset flow. Issue the AQ */
if (!qg_list)
goto do_aq;
@@ -2378,7 +2513,17 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
return ICE_ERR_PARAM;
do_aq:
- return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
+ status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
+ if (status) {
+ if (!qg_list)
+ ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
+ vmvf_num, hw->adminq.sq_last_status);
+ else
+ ice_debug(hw, ICE_DBG_SCHED, "disable Q %d failed %d\n",
+ le16_to_cpu(qg_list[0].q_id[0]),
+ hw->adminq.sq_last_status);
+ }
+ return status;
}
/* End of FW Admin Queue command wrappers */
@@ -2664,8 +2809,12 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_qgrps,
/* add the lan q */
status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
- if (status)
+ if (status) {
+ ice_debug(hw, ICE_DBG_SCHED, "enable Q %d failed %d\n",
+ le16_to_cpu(buf->txqs[0].txq_id),
+ hw->adminq.sq_last_status);
goto ena_txq_exit;
+ }
node.node_teid = buf->txqs[0].q_teid;
node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h
index cf760c24a6aa..d7c7c2ed8823 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.h
+++ b/drivers/net/ethernet/intel/ice/ice_common.h
@@ -28,6 +28,8 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
enum ice_aq_res_access_type access, u32 timeout);
void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
enum ice_status ice_init_nvm(struct ice_hw *hw);
+enum ice_status ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words,
+ u16 *data);
enum ice_status
ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
struct ice_aq_desc *desc, void *buf, u16 buf_size,
@@ -70,9 +72,10 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
struct ice_aqc_get_phy_caps_data *caps,
struct ice_sq_cd *cd);
void
-ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap);
+ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
+ u16 link_speeds_bitmap);
enum ice_status
-ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags,
+ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
struct ice_sq_cd *cd);
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
enum ice_status
@@ -86,6 +89,10 @@ enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
enum ice_status
+ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
+ struct ice_sq_cd *cd);
+
+enum ice_status
ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids,
u32 *q_teids, enum ice_disq_rst_src rst_src, u16 vmvf_num,
struct ice_sq_cd *cmd_details);
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 3b6e387f5440..eb8d149e317c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -63,45 +63,45 @@ static const struct ice_stats ice_gstrings_vsi_stats[] = {
* is queried on the base PF netdev.
*/
static const struct ice_stats ice_gstrings_pf_stats[] = {
- ICE_PF_STAT("tx_bytes", stats.eth.tx_bytes),
- ICE_PF_STAT("rx_bytes", stats.eth.rx_bytes),
- ICE_PF_STAT("tx_unicast", stats.eth.tx_unicast),
- ICE_PF_STAT("rx_unicast", stats.eth.rx_unicast),
- ICE_PF_STAT("tx_multicast", stats.eth.tx_multicast),
- ICE_PF_STAT("rx_multicast", stats.eth.rx_multicast),
- ICE_PF_STAT("tx_broadcast", stats.eth.tx_broadcast),
- ICE_PF_STAT("rx_broadcast", stats.eth.rx_broadcast),
- ICE_PF_STAT("tx_errors", stats.eth.tx_errors),
- ICE_PF_STAT("tx_size_64", stats.tx_size_64),
- ICE_PF_STAT("rx_size_64", stats.rx_size_64),
- ICE_PF_STAT("tx_size_127", stats.tx_size_127),
- ICE_PF_STAT("rx_size_127", stats.rx_size_127),
- ICE_PF_STAT("tx_size_255", stats.tx_size_255),
- ICE_PF_STAT("rx_size_255", stats.rx_size_255),
- ICE_PF_STAT("tx_size_511", stats.tx_size_511),
- ICE_PF_STAT("rx_size_511", stats.rx_size_511),
- ICE_PF_STAT("tx_size_1023", stats.tx_size_1023),
- ICE_PF_STAT("rx_size_1023", stats.rx_size_1023),
- ICE_PF_STAT("tx_size_1522", stats.tx_size_1522),
- ICE_PF_STAT("rx_size_1522", stats.rx_size_1522),
- ICE_PF_STAT("tx_size_big", stats.tx_size_big),
- ICE_PF_STAT("rx_size_big", stats.rx_size_big),
- ICE_PF_STAT("link_xon_tx", stats.link_xon_tx),
- ICE_PF_STAT("link_xon_rx", stats.link_xon_rx),
- ICE_PF_STAT("link_xoff_tx", stats.link_xoff_tx),
- ICE_PF_STAT("link_xoff_rx", stats.link_xoff_rx),
- ICE_PF_STAT("tx_dropped_link_down", stats.tx_dropped_link_down),
- ICE_PF_STAT("rx_undersize", stats.rx_undersize),
- ICE_PF_STAT("rx_fragments", stats.rx_fragments),
- ICE_PF_STAT("rx_oversize", stats.rx_oversize),
- ICE_PF_STAT("rx_jabber", stats.rx_jabber),
- ICE_PF_STAT("rx_csum_bad", hw_csum_rx_error),
- ICE_PF_STAT("rx_length_errors", stats.rx_len_errors),
- ICE_PF_STAT("rx_dropped", stats.eth.rx_discards),
- ICE_PF_STAT("rx_crc_errors", stats.crc_errors),
- ICE_PF_STAT("illegal_bytes", stats.illegal_bytes),
- ICE_PF_STAT("mac_local_faults", stats.mac_local_faults),
- ICE_PF_STAT("mac_remote_faults", stats.mac_remote_faults),
+ ICE_PF_STAT("port.tx_bytes", stats.eth.tx_bytes),
+ ICE_PF_STAT("port.rx_bytes", stats.eth.rx_bytes),
+ ICE_PF_STAT("port.tx_unicast", stats.eth.tx_unicast),
+ ICE_PF_STAT("port.rx_unicast", stats.eth.rx_unicast),
+ ICE_PF_STAT("port.tx_multicast", stats.eth.tx_multicast),
+ ICE_PF_STAT("port.rx_multicast", stats.eth.rx_multicast),
+ ICE_PF_STAT("port.tx_broadcast", stats.eth.tx_broadcast),
+ ICE_PF_STAT("port.rx_broadcast", stats.eth.rx_broadcast),
+ ICE_PF_STAT("port.tx_errors", stats.eth.tx_errors),
+ ICE_PF_STAT("port.tx_size_64", stats.tx_size_64),
+ ICE_PF_STAT("port.rx_size_64", stats.rx_size_64),
+ ICE_PF_STAT("port.tx_size_127", stats.tx_size_127),
+ ICE_PF_STAT("port.rx_size_127", stats.rx_size_127),
+ ICE_PF_STAT("port.tx_size_255", stats.tx_size_255),
+ ICE_PF_STAT("port.rx_size_255", stats.rx_size_255),
+ ICE_PF_STAT("port.tx_size_511", stats.tx_size_511),
+ ICE_PF_STAT("port.rx_size_511", stats.rx_size_511),
+ ICE_PF_STAT("port.tx_size_1023", stats.tx_size_1023),
+ ICE_PF_STAT("port.rx_size_1023", stats.rx_size_1023),
+ ICE_PF_STAT("port.tx_size_1522", stats.tx_size_1522),
+ ICE_PF_STAT("port.rx_size_1522", stats.rx_size_1522),
+ ICE_PF_STAT("port.tx_size_big", stats.tx_size_big),
+ ICE_PF_STAT("port.rx_size_big", stats.rx_size_big),
+ ICE_PF_STAT("port.link_xon_tx", stats.link_xon_tx),
+ ICE_PF_STAT("port.link_xon_rx", stats.link_xon_rx),
+ ICE_PF_STAT("port.link_xoff_tx", stats.link_xoff_tx),
+ ICE_PF_STAT("port.link_xoff_rx", stats.link_xoff_rx),
+ ICE_PF_STAT("port.tx_dropped_link_down", stats.tx_dropped_link_down),
+ ICE_PF_STAT("port.rx_undersize", stats.rx_undersize),
+ ICE_PF_STAT("port.rx_fragments", stats.rx_fragments),
+ ICE_PF_STAT("port.rx_oversize", stats.rx_oversize),
+ ICE_PF_STAT("port.rx_jabber", stats.rx_jabber),
+ ICE_PF_STAT("port.rx_csum_bad", hw_csum_rx_error),
+ ICE_PF_STAT("port.rx_length_errors", stats.rx_len_errors),
+ ICE_PF_STAT("port.rx_dropped", stats.eth.rx_discards),
+ ICE_PF_STAT("port.rx_crc_errors", stats.crc_errors),
+ ICE_PF_STAT("port.illegal_bytes", stats.illegal_bytes),
+ ICE_PF_STAT("port.mac_local_faults", stats.mac_local_faults),
+ ICE_PF_STAT("port.mac_remote_faults", stats.mac_remote_faults),
};
static const u32 ice_regs_dump_list[] = {
@@ -114,6 +114,22 @@ static const u32 ice_regs_dump_list[] = {
QRX_ITR(0),
};
+struct ice_priv_flag {
+ char name[ETH_GSTRING_LEN];
+ u32 bitno; /* bit position in pf->flags */
+};
+
+#define ICE_PRIV_FLAG(_name, _bitno) { \
+ .name = _name, \
+ .bitno = _bitno, \
+}
+
+static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
+ ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA),
+};
+
+#define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags)
+
/**
* ice_nvm_version_str - format the NVM version strings
* @hw: ptr to the hardware info
@@ -152,6 +168,7 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
sizeof(drvinfo->bus_info));
+ drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE;
}
static int ice_get_regs_len(struct net_device __always_unused *netdev)
@@ -203,6 +220,55 @@ static void ice_set_msglevel(struct net_device *netdev, u32 data)
#endif /* !CONFIG_DYNAMIC_DEBUG */
}
+static int ice_get_eeprom_len(struct net_device *netdev)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ struct ice_pf *pf = np->vsi->back;
+
+ return (int)(pf->hw.nvm.sr_words * sizeof(u16));
+}
+
+static int
+ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
+ u8 *bytes)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ u16 first_word, last_word, nwords;
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+ struct ice_hw *hw = &pf->hw;
+ enum ice_status status;
+ struct device *dev;
+ int ret = 0;
+ u16 *buf;
+
+ dev = &pf->pdev->dev;
+
+ eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+ nwords = last_word - first_word + 1;
+
+ buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ status = ice_read_sr_buf(hw, first_word, &nwords, buf);
+ if (status) {
+ dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n",
+ status, hw->adminq.sq_last_status);
+ eeprom->len = sizeof(u16) * nwords;
+ ret = -EIO;
+ goto out;
+ }
+
+ memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len);
+out:
+ devm_kfree(dev, buf);
+ return ret;
+}
+
static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -238,17 +304,105 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
return;
for (i = 0; i < ICE_PF_STATS_LEN; i++) {
- snprintf(p, ETH_GSTRING_LEN, "port.%s",
+ snprintf(p, ETH_GSTRING_LEN, "%s",
ice_gstrings_pf_stats[i].stat_string);
p += ETH_GSTRING_LEN;
}
break;
+ case ETH_SS_PRIV_FLAGS:
+ for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "%s",
+ ice_gstrings_priv_flags[i].name);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
default:
break;
}
}
+static int
+ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ bool led_active;
+
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ led_active = true;
+ break;
+ case ETHTOOL_ID_INACTIVE:
+ led_active = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ice_aq_set_port_id_led(np->vsi->port_info, !led_active, NULL))
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * ice_get_priv_flags - report device private flags
+ * @netdev: network interface device structure
+ *
+ * The get string set count and the string set should be matched for each
+ * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags
+ * array.
+ *
+ * Returns a u32 bitmap of flags.
+ */
+static u32 ice_get_priv_flags(struct net_device *netdev)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+ u32 i, ret_flags = 0;
+
+ for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
+ const struct ice_priv_flag *priv_flag;
+
+ priv_flag = &ice_gstrings_priv_flags[i];
+
+ if (test_bit(priv_flag->bitno, pf->flags))
+ ret_flags |= BIT(i);
+ }
+
+ return ret_flags;
+}
+
+/**
+ * ice_set_priv_flags - set private flags
+ * @netdev: network interface device structure
+ * @flags: bit flags to be set
+ */
+static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+ u32 i;
+
+ if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE))
+ return -EINVAL;
+
+ for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {
+ const struct ice_priv_flag *priv_flag;
+
+ priv_flag = &ice_gstrings_priv_flags[i];
+
+ if (flags & BIT(i))
+ set_bit(priv_flag->bitno, pf->flags);
+ else
+ clear_bit(priv_flag->bitno, pf->flags);
+ }
+
+ return 0;
+}
+
static int ice_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
@@ -272,6 +426,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)
* not safe.
*/
return ICE_ALL_STATS_LEN(netdev);
+ case ETH_SS_PRIV_FLAGS:
+ return ICE_PRIV_FLAG_ARRAY_SIZE;
default:
return -EOPNOTSUPP;
}
@@ -337,16 +493,20 @@ ice_get_ethtool_stats(struct net_device *netdev,
* @netdev: network interface device structure
* @ks: ethtool link ksettings struct to fill out
*/
-static void ice_phy_type_to_ethtool(struct net_device *netdev,
- struct ethtool_link_ksettings *ks)
+static void
+ice_phy_type_to_ethtool(struct net_device *netdev,
+ struct ethtool_link_ksettings *ks)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_link_status *hw_link_info;
+ bool need_add_adv_mode = false;
struct ice_vsi *vsi = np->vsi;
+ u64 phy_types_high;
u64 phy_types_low;
hw_link_info = &vsi->port_info->phy.link_info;
phy_types_low = vsi->port_info->phy.phy_type_low;
+ phy_types_high = vsi->port_info->phy.phy_type_high;
ethtool_link_ksettings_zero_link_mode(ks, supported);
ethtool_link_ksettings_zero_link_mode(ks, advertising);
@@ -495,6 +655,95 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseLR4_Full);
}
+ if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseCR2_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 50000baseCR2_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseKR2_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 50000baseKR2_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseSR2_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 50000baseSR2_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 ||
+ phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC ||
+ phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 ||
+ phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC ||
+ phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseCR4_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+ need_add_adv_mode = true;
+ }
+ if (need_add_adv_mode) {
+ need_add_adv_mode = false;
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseCR4_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseSR4_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+ need_add_adv_mode = true;
+ }
+ if (need_add_adv_mode) {
+ need_add_adv_mode = false;
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseSR4_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseLR4_ER4_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+ need_add_adv_mode = true;
+ }
+ if (need_add_adv_mode) {
+ need_add_adv_mode = false;
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseLR4_ER4_Full);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 ||
+ phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseKR4_Full);
+ if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+ need_add_adv_mode = true;
+ }
+ if (need_add_adv_mode)
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseKR4_Full);
/* Autoneg PHY types */
if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
@@ -520,6 +769,24 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
ethtool_link_ksettings_add_link_mode(ks, advertising,
Autoneg);
}
+ if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP ||
+ phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ Autoneg);
+ }
+ if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 ||
+ phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) {
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ Autoneg);
+ }
}
#define TEST_SET_BITS_TIMEOUT 50
@@ -531,13 +798,15 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
* @ks: ethtool ksettings to fill in
* @netdev: network interface device structure
*/
-static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
- struct net_device *netdev)
+static void
+ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
+ struct net_device *netdev)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ethtool_link_ksettings cap_ksettings;
struct ice_link_status *link_info;
struct ice_vsi *vsi = np->vsi;
+ bool unrecog_phy_high = false;
bool unrecog_phy_low = false;
link_info = &vsi->port_info->phy.link_info;
@@ -699,25 +968,133 @@ static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseKR4_Full);
break;
+ case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_CP:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseCR2_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 50000baseCR2_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_LAUI2:
+ case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_AUI2:
+ case ICE_PHY_TYPE_LOW_50GBASE_SR:
+ case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_50G_AUI1:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseCR2_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseKR2_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 50000baseKR2_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+ case ICE_PHY_TYPE_LOW_50GBASE_FR:
+ case ICE_PHY_TYPE_LOW_50GBASE_LR:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseSR2_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseCR4_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseCR4_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_100G_CAUI4:
+ case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
+ case ICE_PHY_TYPE_LOW_100G_AUI4:
+ case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseCR4_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_CP2:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseCR4_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseCR4_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseSR4_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_DR:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseLR4_ER4_Full);
+ break;
+ case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+ case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseKR4_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseKR4_Full);
+ break;
default:
unrecog_phy_low = true;
}
- if (unrecog_phy_low) {
+ switch (link_info->phy_type_high) {
+ case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseKR4_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+ ethtool_link_ksettings_add_link_mode(ks, advertising,
+ 100000baseKR4_Full);
+ break;
+ case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
+ case ICE_PHY_TYPE_HIGH_100G_CAUI2:
+ case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
+ case ICE_PHY_TYPE_HIGH_100G_AUI2:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 100000baseCR4_Full);
+ break;
+ default:
+ unrecog_phy_high = true;
+ }
+
+ if (unrecog_phy_low && unrecog_phy_high) {
/* if we got here and link is up something bad is afoot */
- netdev_info(netdev, "WARNING: Unrecognized PHY_Low (0x%llx).\n",
+ netdev_info(netdev,
+ "WARNING: Unrecognized PHY_Low (0x%llx).\n",
(u64)link_info->phy_type_low);
+ netdev_info(netdev,
+ "WARNING: Unrecognized PHY_High (0x%llx).\n",
+ (u64)link_info->phy_type_high);
}
/* Now that we've worked out everything that could be supported by the
* current PHY type, get what is supported by the NVM and intersect
* them to get what is truly supported
*/
- memset(&cap_ksettings, 0, sizeof(struct ethtool_link_ksettings));
+ memset(&cap_ksettings, 0, sizeof(cap_ksettings));
ice_phy_type_to_ethtool(netdev, &cap_ksettings);
ethtool_intersect_link_masks(ks, &cap_ksettings);
switch (link_info->link_speed) {
+ case ICE_AQ_LINK_SPEED_100GB:
+ ks->base.speed = SPEED_100000;
+ break;
+ case ICE_AQ_LINK_SPEED_50GB:
+ ks->base.speed = SPEED_50000;
+ break;
case ICE_AQ_LINK_SPEED_40GB:
ks->base.speed = SPEED_40000;
break;
@@ -911,6 +1288,23 @@ ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks)
ethtool_link_ksettings_test_link_mode(ks, advertising,
40000baseKR4_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_40GB;
+ if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 50000baseCR2_Full) ||
+ ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 50000baseKR2_Full))
+ adv_link_speed |= ICE_AQ_LINK_SPEED_50GB;
+ if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 50000baseSR2_Full))
+ adv_link_speed |= ICE_AQ_LINK_SPEED_50GB;
+ if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 100000baseCR4_Full) ||
+ ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 100000baseSR4_Full) ||
+ ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 100000baseLR4_ER4_Full) ||
+ ethtool_link_ksettings_test_link_mode(ks, advertising,
+ 100000baseKR4_Full))
+ adv_link_speed |= ICE_AQ_LINK_SPEED_100GB;
return adv_link_speed;
}
@@ -981,8 +1375,9 @@ ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks,
*
* Set speed/duplex per media_types advertised/forced
*/
-static int ice_set_link_ksettings(struct net_device *netdev,
- const struct ethtool_link_ksettings *ks)
+static int
+ice_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *ks)
{
u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0;
struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -994,6 +1389,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
struct ice_port_info *p;
u8 autoneg_changed = 0;
enum ice_status status;
+ u64 phy_type_high;
u64 phy_type_low;
int err = 0;
bool linkup;
@@ -1020,7 +1416,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
return -EOPNOTSUPP;
/* copy the ksettings to copy_ks to avoid modifying the original */
- memcpy(&copy_ks, ks, sizeof(struct ethtool_link_ksettings));
+ memcpy(&copy_ks, ks, sizeof(copy_ks));
/* save autoneg out of ksettings */
autoneg = copy_ks.base.autoneg;
@@ -1039,7 +1435,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
return -EINVAL;
/* get our own copy of the bits to check against */
- memset(&safe_ks, 0, sizeof(struct ethtool_link_ksettings));
+ memset(&safe_ks, 0, sizeof(safe_ks));
safe_ks.base.cmd = copy_ks.base.cmd;
safe_ks.base.link_mode_masks_nwords =
copy_ks.base.link_mode_masks_nwords;
@@ -1053,8 +1449,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
/* If copy_ks.base and safe_ks.base are not the same now, then they are
* trying to set something that we do not support.
*/
- if (memcmp(&copy_ks.base, &safe_ks.base,
- sizeof(struct ethtool_link_settings)))
+ if (memcmp(&copy_ks.base, &safe_ks.base, sizeof(copy_ks.base)))
return -EOPNOTSUPP;
while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) {
@@ -1078,7 +1473,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
}
/* Copy abilities to config in case autoneg is not set below */
- memset(&config, 0, sizeof(struct ice_aqc_set_phy_cfg_data));
+ memset(&config, 0, sizeof(config));
config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE;
if (abilities->caps & ICE_AQC_PHY_AN_MODE)
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
@@ -1109,7 +1504,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
adv_link_speed = curr_link_speed;
/* Convert the advertise link speeds to their corresponded PHY_TYPE */
- ice_update_phy_type(&phy_type_low, adv_link_speed);
+ ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed);
if (!autoneg_changed && adv_link_speed == curr_link_speed) {
netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
@@ -1128,7 +1523,9 @@ static int ice_set_link_ksettings(struct net_device *netdev,
/* set link and auto negotiation so changes take effect */
config.caps |= ICE_AQ_PHY_ENA_LINK;
- if (phy_type_low) {
+ if (phy_type_low || phy_type_high) {
+ config.phy_type_high = cpu_to_le64(phy_type_high) &
+ abilities->phy_type_high;
config.phy_type_low = cpu_to_le64(phy_type_low) &
abilities->phy_type_low;
} else {
@@ -1270,7 +1667,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
vsi->tx_rings[0]->count, new_tx_cnt);
tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq,
- sizeof(struct ice_ring), GFP_KERNEL);
+ sizeof(*tx_rings), GFP_KERNEL);
if (!tx_rings) {
err = -ENOMEM;
goto done;
@@ -1302,7 +1699,7 @@ process_rx:
vsi->rx_rings[0]->count, new_rx_cnt);
rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq,
- sizeof(struct ice_ring), GFP_KERNEL);
+ sizeof(*rx_rings), GFP_KERNEL);
if (!rx_rings) {
err = -ENOMEM;
goto done;
@@ -1421,21 +1818,36 @@ static void
ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
- struct ice_port_info *pi;
+ struct ice_port_info *pi = np->vsi->port_info;
+ struct ice_aqc_get_phy_caps_data *pcaps;
+ struct ice_vsi *vsi = np->vsi;
+ enum ice_status status;
- pi = np->vsi->port_info;
- pause->autoneg =
- ((pi->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) ?
- AUTONEG_ENABLE : AUTONEG_DISABLE);
+ /* Initialize pause params */
+ pause->rx_pause = 0;
+ pause->tx_pause = 0;
- if (pi->fc.current_mode == ICE_FC_RX_PAUSE) {
- pause->rx_pause = 1;
- } else if (pi->fc.current_mode == ICE_FC_TX_PAUSE) {
+ pcaps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*pcaps),
+ GFP_KERNEL);
+ if (!pcaps)
+ return;
+
+ /* Get current phy config */
+ status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
+ NULL);
+ if (status)
+ goto out;
+
+ pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ?
+ AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+ if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
pause->tx_pause = 1;
- } else if (pi->fc.current_mode == ICE_FC_FULL) {
+ if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
pause->rx_pause = 1;
- pause->tx_pause = 1;
- }
+
+out:
+ devm_kfree(&vsi->back->pdev->dev, pcaps);
}
/**
@@ -1667,6 +2079,258 @@ static int ice_set_rxfh(struct net_device *netdev, const u32 *indir,
return 0;
}
+enum ice_container_type {
+ ICE_RX_CONTAINER,
+ ICE_TX_CONTAINER,
+};
+
+/**
+ * ice_get_rc_coalesce - get ITR values for specific ring container
+ * @ec: ethtool structure to fill with driver's coalesce settings
+ * @c_type: container type, RX or TX
+ * @rc: ring container that the ITR values will come from
+ *
+ * Query the device for ice_ring_container specific ITR values. This is
+ * done per ice_ring_container because each q_vector can have 1 or more rings
+ * and all of said ring(s) will have the same ITR values.
+ *
+ * Returns 0 on success, negative otherwise.
+ */
+static int
+ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type,
+ struct ice_ring_container *rc)
+{
+ struct ice_pf *pf = rc->ring->vsi->back;
+
+ switch (c_type) {
+ case ICE_RX_CONTAINER:
+ ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting);
+ ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC;
+ break;
+ case ICE_TX_CONTAINER:
+ ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting);
+ ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC;
+ break;
+ default:
+ dev_dbg(&pf->pdev->dev, "Invalid c_type %d\n", c_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * __ice_get_coalesce - get ITR/INTRL values for the device
+ * @netdev: pointer to the netdev associated with this query
+ * @ec: ethtool structure to fill with driver's coalesce settings
+ * @q_num: queue number to get the coalesce settings for
+ */
+static int
+__ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec,
+ int q_num)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ int tx = -EINVAL, rx = -EINVAL;
+ struct ice_vsi *vsi = np->vsi;
+
+ if (q_num < 0) {
+ rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER,
+ &vsi->rx_rings[0]->q_vector->rx);
+ tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER,
+ &vsi->tx_rings[0]->q_vector->tx);
+
+ goto update_coalesced_frames;
+ }
+
+ if (q_num < vsi->num_rxq && q_num < vsi->num_txq) {
+ rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER,
+ &vsi->rx_rings[q_num]->q_vector->rx);
+ tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER,
+ &vsi->tx_rings[q_num]->q_vector->tx);
+ } else if (q_num < vsi->num_rxq) {
+ rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER,
+ &vsi->rx_rings[q_num]->q_vector->rx);
+ } else if (q_num < vsi->num_txq) {
+ tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER,
+ &vsi->tx_rings[q_num]->q_vector->tx);
+ } else {
+ /* q_num is invalid for both Rx and Tx queues */
+ return -EINVAL;
+ }
+
+update_coalesced_frames:
+ /* either q_num is invalid for both Rx and Tx queues or setting coalesce
+ * failed completely
+ */
+ if (tx && rx)
+ return -EINVAL;
+
+ if (q_num < vsi->num_txq)
+ ec->tx_max_coalesced_frames_irq = vsi->work_lmt;
+
+ if (q_num < vsi->num_rxq)
+ ec->rx_max_coalesced_frames_irq = vsi->work_lmt;
+
+ return 0;
+}
+
+static int
+ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
+{
+ return __ice_get_coalesce(netdev, ec, -1);
+}
+
+static int ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num,
+ struct ethtool_coalesce *ec)
+{
+ return __ice_get_coalesce(netdev, ec, q_num);
+}
+
+/**
+ * ice_set_rc_coalesce - set ITR values for specific ring container
+ * @c_type: container type, RX or TX
+ * @ec: ethtool structure from user to update ITR settings
+ * @rc: ring container that the ITR values will come from
+ * @vsi: VSI associated to the ring container
+ *
+ * Set specific ITR values. This is done per ice_ring_container because each
+ * q_vector can have 1 or more rings and all of said ring(s) will have the same
+ * ITR values.
+ *
+ * Returns 0 on success, negative otherwise.
+ */
+static int
+ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
+ struct ice_ring_container *rc, struct ice_vsi *vsi)
+{
+ struct ice_pf *pf = vsi->back;
+ u16 itr_setting;
+
+ if (!rc->ring)
+ return -EINVAL;
+
+ itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC;
+
+ switch (c_type) {
+ case ICE_RX_CONTAINER:
+ if (ec->rx_coalesce_usecs != itr_setting &&
+ ec->use_adaptive_rx_coalesce) {
+ netdev_info(vsi->netdev,
+ "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n");
+ return -EINVAL;
+ }
+
+ if (ec->rx_coalesce_usecs > ICE_ITR_MAX) {
+ netdev_info(vsi->netdev,
+ "Invalid value, rx-usecs range is 0-%d\n",
+ ICE_ITR_MAX);
+ return -EINVAL;
+ }
+
+ if (ec->use_adaptive_rx_coalesce) {
+ rc->itr_setting |= ICE_ITR_DYNAMIC;
+ } else {
+ rc->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
+ rc->target_itr = ITR_TO_REG(rc->itr_setting);
+ }
+ break;
+ case ICE_TX_CONTAINER:
+ if (ec->tx_coalesce_usecs != itr_setting &&
+ ec->use_adaptive_tx_coalesce) {
+ netdev_info(vsi->netdev,
+ "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n");
+ return -EINVAL;
+ }
+
+ if (ec->tx_coalesce_usecs > ICE_ITR_MAX) {
+ netdev_info(vsi->netdev,
+ "Invalid value, tx-usecs range is 0-%d\n",
+ ICE_ITR_MAX);
+ return -EINVAL;
+ }
+
+ if (ec->use_adaptive_tx_coalesce) {
+ rc->itr_setting |= ICE_ITR_DYNAMIC;
+ } else {
+ rc->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);
+ rc->target_itr = ITR_TO_REG(rc->itr_setting);
+ }
+ break;
+ default:
+ dev_dbg(&pf->pdev->dev, "Invalid container type %d\n", c_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+__ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec,
+ int q_num)
+{
+ struct ice_netdev_priv *np = netdev_priv(netdev);
+ int rx = -EINVAL, tx = -EINVAL;
+ struct ice_vsi *vsi = np->vsi;
+
+ if (q_num < 0) {
+ int i;
+
+ ice_for_each_q_vector(vsi, i) {
+ struct ice_q_vector *q_vector = vsi->q_vectors[i];
+
+ if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec,
+ &q_vector->rx, vsi) ||
+ ice_set_rc_coalesce(ICE_TX_CONTAINER, ec,
+ &q_vector->tx, vsi))
+ return -EINVAL;
+ }
+
+ goto set_work_lmt;
+ }
+
+ if (q_num < vsi->num_rxq && q_num < vsi->num_txq) {
+ rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec,
+ &vsi->rx_rings[q_num]->q_vector->rx,
+ vsi);
+ tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec,
+ &vsi->tx_rings[q_num]->q_vector->tx,
+ vsi);
+ } else if (q_num < vsi->num_rxq) {
+ rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec,
+ &vsi->rx_rings[q_num]->q_vector->rx,
+ vsi);
+ } else if (q_num < vsi->num_txq) {
+ tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec,
+ &vsi->tx_rings[q_num]->q_vector->tx,
+ vsi);
+ }
+
+ /* either q_num is invalid for both Rx and Tx queues or setting coalesce
+ * failed completely
+ */
+ if (rx && tx)
+ return -EINVAL;
+
+set_work_lmt:
+ if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
+ vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq,
+ ec->rx_max_coalesced_frames_irq);
+
+ return 0;
+}
+
+static int
+ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
+{
+ return __ice_set_coalesce(netdev, ec, -1);
+}
+
+static int ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num,
+ struct ethtool_coalesce *ec)
+{
+ return __ice_set_coalesce(netdev, ec, q_num);
+}
+
static const struct ethtool_ops ice_ethtool_ops = {
.get_link_ksettings = ice_get_link_ksettings,
.set_link_ksettings = ice_set_link_ksettings,
@@ -1676,8 +2340,15 @@ static const struct ethtool_ops ice_ethtool_ops = {
.get_msglevel = ice_get_msglevel,
.set_msglevel = ice_set_msglevel,
.get_link = ethtool_op_get_link,
+ .get_eeprom_len = ice_get_eeprom_len,
+ .get_eeprom = ice_get_eeprom,
+ .get_coalesce = ice_get_coalesce,
+ .set_coalesce = ice_set_coalesce,
.get_strings = ice_get_strings,
+ .set_phys_id = ice_set_phys_id,
.get_ethtool_stats = ice_get_ethtool_stats,
+ .get_priv_flags = ice_get_priv_flags,
+ .set_priv_flags = ice_set_priv_flags,
.get_sset_count = ice_get_sset_count,
.get_rxnfc = ice_get_rxnfc,
.get_ringparam = ice_get_ringparam,
@@ -1689,6 +2360,9 @@ static const struct ethtool_ops ice_ethtool_ops = {
.get_rxfh_indir_size = ice_get_rxfh_indir_size,
.get_rxfh = ice_get_rxfh,
.set_rxfh = ice_set_rxfh,
+ .get_ts_info = ethtool_op_get_ts_info,
+ .get_per_queue_coalesce = ice_get_per_q_coalesce,
+ .set_per_queue_coalesce = ice_set_per_q_coalesce,
};
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
index 5507928c8fbe..6bf5cc064270 100644
--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -30,6 +30,7 @@
#define PF_FW_ATQLEN_ATQVFE_M BIT(28)
#define PF_FW_ATQLEN_ATQOVFL_M BIT(29)
#define PF_FW_ATQLEN_ATQCRIT_M BIT(30)
+#define VF_MBX_ARQLEN(_VF) (0x0022BC00 + ((_VF) * 4))
#define PF_FW_ATQLEN_ATQENABLE_M BIT(31)
#define PF_FW_ATQT 0x00080400
#define PF_MBX_ARQBAH 0x0022E400
@@ -110,6 +111,7 @@
#define GLINT_DYN_CTL_CLEARPBA_M BIT(1)
#define GLINT_DYN_CTL_SWINT_TRIG_M BIT(2)
#define GLINT_DYN_CTL_ITR_INDX_S 3
+#define GLINT_DYN_CTL_INTERVAL_S 5
#define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25)
#define GLINT_DYN_CTL_INTENA_MSK_M BIT(31)
#define GLINT_ITR(_i, _INT) (0x00154000 + ((_i) * 8192 + (_INT) * 4))
diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
index bb51dd7defb5..ef4c79b5aa32 100644
--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
+++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
@@ -346,6 +346,7 @@ enum ice_tx_desc_cmd_bits {
ICE_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */
+ ICE_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */
};
@@ -488,5 +489,7 @@ static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
#define ICE_LINK_SPEED_20000MBPS 20000
#define ICE_LINK_SPEED_25000MBPS 25000
#define ICE_LINK_SPEED_40000MBPS 40000
+#define ICE_LINK_SPEED_50000MBPS 50000
+#define ICE_LINK_SPEED_100000MBPS 100000
#endif /* _ICE_LAN_TX_RX_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 29b1dcfd4331..fa61203bee26 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -249,12 +249,12 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors)
/* allocate memory for both Tx and Rx ring pointers */
vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq,
- sizeof(struct ice_ring *), GFP_KERNEL);
+ sizeof(*vsi->tx_rings), GFP_KERNEL);
if (!vsi->tx_rings)
goto err_txrings;
vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq,
- sizeof(struct ice_ring *), GFP_KERNEL);
+ sizeof(*vsi->rx_rings), GFP_KERNEL);
if (!vsi->rx_rings)
goto err_rxrings;
@@ -262,7 +262,7 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors)
/* allocate memory for q_vector pointers */
vsi->q_vectors = devm_kcalloc(&pf->pdev->dev,
vsi->num_q_vectors,
- sizeof(struct ice_q_vector *),
+ sizeof(*vsi->q_vectors),
GFP_KERNEL);
if (!vsi->q_vectors)
goto err_vectors;
@@ -348,19 +348,25 @@ static int ice_get_free_slot(void *array, int size, int curr)
void ice_vsi_delete(struct ice_vsi *vsi)
{
struct ice_pf *pf = vsi->back;
- struct ice_vsi_ctx ctxt;
+ struct ice_vsi_ctx *ctxt;
enum ice_status status;
+ ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return;
+
if (vsi->type == ICE_VSI_VF)
- ctxt.vf_num = vsi->vf_id;
- ctxt.vsi_num = vsi->vsi_num;
+ ctxt->vf_num = vsi->vf_id;
+ ctxt->vsi_num = vsi->vsi_num;
- memcpy(&ctxt.info, &vsi->info, sizeof(struct ice_aqc_vsi_props));
+ memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
- status = ice_free_vsi(&pf->hw, vsi->idx, &ctxt, false, NULL);
+ status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL);
if (status)
dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n",
vsi->vsi_num);
+
+ devm_kfree(&pf->pdev->dev, ctxt);
}
/**
@@ -514,110 +520,89 @@ unlock_pf:
}
/**
- * ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI
- * @vsi: the VSI getting queues
+ * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI
+ * @qs_cfg: gathered variables needed for PF->VSI queues assignment
*
- * Return 0 on success and a negative value on error
+ * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap
*/
-static int ice_vsi_get_qs_contig(struct ice_vsi *vsi)
+static int __ice_vsi_get_qs_contig(struct ice_qs_cfg *qs_cfg)
{
- struct ice_pf *pf = vsi->back;
- int offset, ret = 0;
+ int offset, i;
- mutex_lock(&pf->avail_q_mutex);
- /* look for contiguous block of queues for Tx */
- offset = bitmap_find_next_zero_area(pf->avail_txqs, ICE_MAX_TXQS,
- 0, vsi->alloc_txq, 0);
- if (offset < ICE_MAX_TXQS) {
- int i;
-
- bitmap_set(pf->avail_txqs, offset, vsi->alloc_txq);
- for (i = 0; i < vsi->alloc_txq; i++)
- vsi->txq_map[i] = i + offset;
- } else {
- ret = -ENOMEM;
- vsi->tx_mapping_mode = ICE_VSI_MAP_SCATTER;
+ mutex_lock(qs_cfg->qs_mutex);
+ offset = bitmap_find_next_zero_area(qs_cfg->pf_map, qs_cfg->pf_map_size,
+ 0, qs_cfg->q_count, 0);
+ if (offset >= qs_cfg->pf_map_size) {
+ mutex_unlock(qs_cfg->qs_mutex);
+ return -ENOMEM;
}
- /* look for contiguous block of queues for Rx */
- offset = bitmap_find_next_zero_area(pf->avail_rxqs, ICE_MAX_RXQS,
- 0, vsi->alloc_rxq, 0);
- if (offset < ICE_MAX_RXQS) {
- int i;
-
- bitmap_set(pf->avail_rxqs, offset, vsi->alloc_rxq);
- for (i = 0; i < vsi->alloc_rxq; i++)
- vsi->rxq_map[i] = i + offset;
- } else {
- ret = -ENOMEM;
- vsi->rx_mapping_mode = ICE_VSI_MAP_SCATTER;
- }
- mutex_unlock(&pf->avail_q_mutex);
+ bitmap_set(qs_cfg->pf_map, offset, qs_cfg->q_count);
+ for (i = 0; i < qs_cfg->q_count; i++)
+ qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = i + offset;
+ mutex_unlock(qs_cfg->qs_mutex);
- return ret;
+ return 0;
}
/**
- * ice_vsi_get_qs_scatter - Assign a scattered queues to VSI
- * @vsi: the VSI getting queues
+ * __ice_vsi_get_qs_sc - Assign a scattered queues from PF to VSI
+ * @qs_cfg: gathered variables needed for PF->VSI queues assignment
*
- * Return 0 on success and a negative value on error
+ * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap
*/
-static int ice_vsi_get_qs_scatter(struct ice_vsi *vsi)
+static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg)
{
- struct ice_pf *pf = vsi->back;
int i, index = 0;
- mutex_lock(&pf->avail_q_mutex);
-
- if (vsi->tx_mapping_mode == ICE_VSI_MAP_SCATTER) {
- for (i = 0; i < vsi->alloc_txq; i++) {
- index = find_next_zero_bit(pf->avail_txqs,
- ICE_MAX_TXQS, index);
- if (index < ICE_MAX_TXQS) {
- set_bit(index, pf->avail_txqs);
- vsi->txq_map[i] = index;
- } else {
- goto err_scatter_tx;
- }
- }
- }
-
- if (vsi->rx_mapping_mode == ICE_VSI_MAP_SCATTER) {
- for (i = 0; i < vsi->alloc_rxq; i++) {
- index = find_next_zero_bit(pf->avail_rxqs,
- ICE_MAX_RXQS, index);
- if (index < ICE_MAX_RXQS) {
- set_bit(index, pf->avail_rxqs);
- vsi->rxq_map[i] = index;
- } else {
- goto err_scatter_rx;
- }
- }
+ mutex_lock(qs_cfg->qs_mutex);
+ for (i = 0; i < qs_cfg->q_count; i++) {
+ index = find_next_zero_bit(qs_cfg->pf_map,
+ qs_cfg->pf_map_size, index);
+ if (index >= qs_cfg->pf_map_size)
+ goto err_scatter;
+ set_bit(index, qs_cfg->pf_map);
+ qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = index;
}
+ mutex_unlock(qs_cfg->qs_mutex);
- mutex_unlock(&pf->avail_q_mutex);
return 0;
-
-err_scatter_rx:
- /* unflag any queues we have grabbed (i is failed position) */
- for (index = 0; index < i; index++) {
- clear_bit(vsi->rxq_map[index], pf->avail_rxqs);
- vsi->rxq_map[index] = 0;
- }
- i = vsi->alloc_txq;
-err_scatter_tx:
- /* i is either position of failed attempt or vsi->alloc_txq */
+err_scatter:
for (index = 0; index < i; index++) {
- clear_bit(vsi->txq_map[index], pf->avail_txqs);
- vsi->txq_map[index] = 0;
+ clear_bit(qs_cfg->vsi_map[index], qs_cfg->pf_map);
+ qs_cfg->vsi_map[index + qs_cfg->vsi_map_offset] = 0;
}
+ mutex_unlock(qs_cfg->qs_mutex);
- mutex_unlock(&pf->avail_q_mutex);
return -ENOMEM;
}
/**
+ * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI
+ * @qs_cfg: gathered variables needed for PF->VSI queues assignment
+ *
+ * This is an internal function for assigning queues from the PF to VSI and
+ * initially tries to find contiguous space. If it is not successful to find
+ * contiguous space, then it tries with the scatter approach.
+ *
+ * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap
+ */
+static int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg)
+{
+ int ret = 0;
+
+ ret = __ice_vsi_get_qs_contig(qs_cfg);
+ if (ret) {
+ /* contig failed, so try with scatter approach */
+ qs_cfg->mapping_mode = ICE_VSI_MAP_SCATTER;
+ qs_cfg->q_count = min_t(u16, qs_cfg->q_count,
+ qs_cfg->scatter_count);
+ ret = __ice_vsi_get_qs_sc(qs_cfg);
+ }
+ return ret;
+}
+
+/**
* ice_vsi_get_qs - Assign queues from PF to VSI
* @vsi: the VSI to assign queues to
*
@@ -625,25 +610,35 @@ err_scatter_tx:
*/
static int ice_vsi_get_qs(struct ice_vsi *vsi)
{
+ struct ice_pf *pf = vsi->back;
+ struct ice_qs_cfg tx_qs_cfg = {
+ .qs_mutex = &pf->avail_q_mutex,
+ .pf_map = pf->avail_txqs,
+ .pf_map_size = ICE_MAX_TXQS,
+ .q_count = vsi->alloc_txq,
+ .scatter_count = ICE_MAX_SCATTER_TXQS,
+ .vsi_map = vsi->txq_map,
+ .vsi_map_offset = 0,
+ .mapping_mode = vsi->tx_mapping_mode
+ };
+ struct ice_qs_cfg rx_qs_cfg = {
+ .qs_mutex = &pf->avail_q_mutex,
+ .pf_map = pf->avail_rxqs,
+ .pf_map_size = ICE_MAX_RXQS,
+ .q_count = vsi->alloc_rxq,
+ .scatter_count = ICE_MAX_SCATTER_RXQS,
+ .vsi_map = vsi->rxq_map,
+ .vsi_map_offset = 0,
+ .mapping_mode = vsi->rx_mapping_mode
+ };
int ret = 0;
vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG;
vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG;
- /* NOTE: ice_vsi_get_qs_contig() will set the Rx/Tx mapping
- * modes individually to scatter if assigning contiguous queues
- * to Rx or Tx fails
- */
- ret = ice_vsi_get_qs_contig(vsi);
- if (ret < 0) {
- if (vsi->tx_mapping_mode == ICE_VSI_MAP_SCATTER)
- vsi->alloc_txq = max_t(u16, vsi->alloc_txq,
- ICE_MAX_SCATTER_TXQS);
- if (vsi->rx_mapping_mode == ICE_VSI_MAP_SCATTER)
- vsi->alloc_rxq = max_t(u16, vsi->alloc_rxq,
- ICE_MAX_SCATTER_RXQS);
- ret = ice_vsi_get_qs_scatter(vsi);
- }
+ ret = __ice_vsi_get_qs(&tx_qs_cfg);
+ if (!ret)
+ ret = __ice_vsi_get_qs(&rx_qs_cfg);
return ret;
}
@@ -919,37 +914,41 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
*/
static int ice_vsi_init(struct ice_vsi *vsi)
{
- struct ice_vsi_ctx ctxt = { 0 };
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
+ struct ice_vsi_ctx *ctxt;
int ret = 0;
+ ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return -ENOMEM;
+
switch (vsi->type) {
case ICE_VSI_PF:
- ctxt.flags = ICE_AQ_VSI_TYPE_PF;
+ ctxt->flags = ICE_AQ_VSI_TYPE_PF;
break;
case ICE_VSI_VF:
- ctxt.flags = ICE_AQ_VSI_TYPE_VF;
+ ctxt->flags = ICE_AQ_VSI_TYPE_VF;
/* VF number here is the absolute VF number (0-255) */
- ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
+ ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
break;
default:
return -ENODEV;
}
- ice_set_dflt_vsi_ctx(&ctxt);
+ ice_set_dflt_vsi_ctx(ctxt);
/* if the switch is in VEB mode, allow VSI loopback */
if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
- ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
+ ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
/* Set LUT type and HASH type if RSS is enabled */
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
- ice_set_rss_vsi_ctx(&ctxt, vsi);
+ ice_set_rss_vsi_ctx(ctxt, vsi);
- ctxt.info.sw_id = vsi->port_info->sw_id;
- ice_vsi_setup_q_map(vsi, &ctxt);
+ ctxt->info.sw_id = vsi->port_info->sw_id;
+ ice_vsi_setup_q_map(vsi, ctxt);
- ret = ice_add_vsi(hw, vsi->idx, &ctxt, NULL);
+ ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
if (ret) {
dev_err(&pf->pdev->dev,
"Add VSI failed, err %d\n", ret);
@@ -957,11 +956,12 @@ static int ice_vsi_init(struct ice_vsi *vsi)
}
/* keep context for update VSI operations */
- vsi->info = ctxt.info;
+ vsi->info = ctxt->info;
/* record VSI number returned */
- vsi->vsi_num = ctxt.vsi_num;
+ vsi->vsi_num = ctxt->vsi_num;
+ devm_kfree(&pf->pdev->dev, ctxt);
return ret;
}
@@ -1614,11 +1614,14 @@ setup_rings:
/**
* ice_vsi_cfg_txqs - Configure the VSI for Tx
* @vsi: the VSI being configured
+ * @rings: Tx ring array to be configured
+ * @offset: offset within vsi->txq_map
*
* Return 0 on success and a negative value on error
* Configure the Tx VSI for operation.
*/
-int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
+static int
+ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset)
{
struct ice_aqc_add_tx_qgrp *qg_buf;
struct ice_aqc_add_txqs_perq *txq;
@@ -1626,9 +1629,9 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
u8 num_q_grps, q_idx = 0;
enum ice_status status;
u16 buf_len, i, pf_q;
- int err = 0, tc = 0;
+ int err = 0, tc;
- buf_len = sizeof(struct ice_aqc_add_tx_qgrp);
+ buf_len = sizeof(*qg_buf);
qg_buf = devm_kzalloc(&pf->pdev->dev, buf_len, GFP_KERNEL);
if (!qg_buf)
return -ENOMEM;
@@ -1644,9 +1647,8 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) {
struct ice_tlan_ctx tlan_ctx = { 0 };
- pf_q = vsi->txq_map[q_idx];
- ice_setup_tx_ctx(vsi->tx_rings[q_idx], &tlan_ctx,
- pf_q);
+ pf_q = vsi->txq_map[q_idx + offset];
+ ice_setup_tx_ctx(rings[q_idx], &tlan_ctx, pf_q);
/* copy context contents into the qg_buf */
qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q);
ice_set_ctx((u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx,
@@ -1655,7 +1657,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
/* init queue specific tail reg. It is referred as
* transmit comm scheduler queue doorbell.
*/
- vsi->tx_rings[q_idx]->tail =
+ rings[q_idx]->tail =
pf->hw.hw_addr + QTX_COMM_DBELL(pf_q);
status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc,
num_q_grps, qg_buf, buf_len,
@@ -1674,7 +1676,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
*/
txq = &qg_buf->txqs[0];
if (pf_q == le16_to_cpu(txq->txq_id))
- vsi->tx_rings[q_idx]->txq_teid =
+ rings[q_idx]->txq_teid =
le32_to_cpu(txq->q_teid);
q_idx++;
@@ -1686,6 +1688,18 @@ err_cfg_txqs:
}
/**
+ * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
+ * @vsi: the VSI being configured
+ *
+ * Return 0 on success and a negative value on error
+ * Configure the Tx VSI for operation.
+ */
+int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
+{
+ return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, 0);
+}
+
+/**
* ice_intrl_usec_to_reg - convert interrupt rate limit to register value
* @intrl: interrupt rate limit in usecs
* @gran: interrupt rate limit granularity in usecs
@@ -1714,22 +1728,34 @@ static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
static void
ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector, u16 vector)
{
- u8 itr_gran = hw->itr_gran;
-
if (q_vector->num_ring_rx) {
struct ice_ring_container *rc = &q_vector->rx;
- rc->itr = ITR_TO_REG(ICE_DFLT_RX_ITR, itr_gran);
+ /* if this value is set then don't overwrite with default */
+ if (!rc->itr_setting)
+ rc->itr_setting = ICE_DFLT_RX_ITR;
+
+ rc->target_itr = ITR_TO_REG(rc->itr_setting);
+ rc->next_update = jiffies + 1;
+ rc->current_itr = rc->target_itr;
rc->latency_range = ICE_LOW_LATENCY;
- wr32(hw, GLINT_ITR(rc->itr_idx, vector), rc->itr);
+ wr32(hw, GLINT_ITR(rc->itr_idx, vector),
+ ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S);
}
if (q_vector->num_ring_tx) {
struct ice_ring_container *rc = &q_vector->tx;
- rc->itr = ITR_TO_REG(ICE_DFLT_TX_ITR, itr_gran);
+ /* if this value is set then don't overwrite with default */
+ if (!rc->itr_setting)
+ rc->itr_setting = ICE_DFLT_TX_ITR;
+
+ rc->target_itr = ITR_TO_REG(rc->itr_setting);
+ rc->next_update = jiffies + 1;
+ rc->current_itr = rc->target_itr;
rc->latency_range = ICE_LOW_LATENCY;
- wr32(hw, GLINT_ITR(rc->itr_idx, vector), rc->itr);
+ wr32(hw, GLINT_ITR(rc->itr_idx, vector),
+ ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S);
}
}
@@ -1808,26 +1834,34 @@ int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
{
struct device *dev = &vsi->back->pdev->dev;
struct ice_hw *hw = &vsi->back->hw;
- struct ice_vsi_ctx ctxt = { 0 };
+ struct ice_vsi_ctx *ctxt;
enum ice_status status;
+ int ret = 0;
+
+ ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return -ENOMEM;
/* Here we are configuring the VSI to let the driver add VLAN tags by
* setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
* insertion happens in the Tx hot path, in ice_tx_map.
*/
- ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
+ ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
- ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
+ ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
- status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
+ status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (status) {
dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- vsi->info.vlan_flags = ctxt.info.vlan_flags;
- return 0;
+ vsi->info.vlan_flags = ctxt->info.vlan_flags;
+out:
+ devm_kfree(dev, ctxt);
+ return ret;
}
/**
@@ -1839,35 +1873,42 @@ int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
{
struct device *dev = &vsi->back->pdev->dev;
struct ice_hw *hw = &vsi->back->hw;
- struct ice_vsi_ctx ctxt = { 0 };
+ struct ice_vsi_ctx *ctxt;
enum ice_status status;
+ int ret = 0;
+
+ ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return -ENOMEM;
/* Here we are configuring what the VSI should do with the VLAN tag in
* the Rx packet. We can either leave the tag in the packet or put it in
* the Rx descriptor.
*/
- if (ena) {
+ if (ena)
/* Strip VLAN tag from Rx packet and put it in the desc */
- ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
- } else {
+ ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
+ else
/* Disable stripping. Leave tag in packet */
- ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
- }
+ ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
/* Allow all packets untagged/tagged */
- ctxt.info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
+ ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
- ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
+ ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
- status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
+ status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (status) {
dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n",
ena, status, hw->adminq.sq_last_status);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- vsi->info.vlan_flags = ctxt.info.vlan_flags;
- return 0;
+ vsi->info.vlan_flags = ctxt->info.vlan_flags;
+out:
+ devm_kfree(dev, ctxt);
+ return ret;
}
/**
@@ -1897,9 +1938,12 @@ int ice_vsi_stop_rx_rings(struct ice_vsi *vsi)
* @vsi: the VSI being configured
* @rst_src: reset source
* @rel_vmvf_num: Relative id of VF/VM
+ * @rings: Tx ring array to be stopped
+ * @offset: offset within vsi->txq_map
*/
-int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
- u16 rel_vmvf_num)
+static int
+ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
+ u16 rel_vmvf_num, struct ice_ring **rings, int offset)
{
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
@@ -1927,19 +1971,18 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
ice_for_each_txq(vsi, i) {
u16 v_idx;
- if (!vsi->tx_rings || !vsi->tx_rings[i] ||
- !vsi->tx_rings[i]->q_vector) {
+ if (!rings || !rings[i] || !rings[i]->q_vector) {
err = -EINVAL;
goto err_out;
}
- q_ids[i] = vsi->txq_map[i];
- q_teids[i] = vsi->tx_rings[i]->txq_teid;
+ q_ids[i] = vsi->txq_map[i + offset];
+ q_teids[i] = rings[i]->txq_teid;
/* clear cause_ena bit for disabled queues */
- val = rd32(hw, QINT_TQCTL(vsi->tx_rings[i]->reg_idx));
+ val = rd32(hw, QINT_TQCTL(rings[i]->reg_idx));
val &= ~QINT_TQCTL_CAUSE_ENA_M;
- wr32(hw, QINT_TQCTL(vsi->tx_rings[i]->reg_idx), val);
+ wr32(hw, QINT_TQCTL(rings[i]->reg_idx), val);
/* software is expected to wait for 100 ns */
ndelay(100);
@@ -1947,7 +1990,7 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
/* trigger a software interrupt for the vector associated to
* the queue to schedule NAPI handler
*/
- v_idx = vsi->tx_rings[i]->q_vector->v_idx;
+ v_idx = rings[i]->q_vector->v_idx;
wr32(hw, GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),
GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M);
}
@@ -1977,6 +2020,19 @@ err_alloc_q_ids:
}
/**
+ * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings
+ * @vsi: the VSI being configured
+ * @rst_src: reset source
+ * @rel_vmvf_num: Relative id of VF/VM
+ */
+int ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi,
+ enum ice_disq_rst_src rst_src, u16 rel_vmvf_num)
+{
+ return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings,
+ 0);
+}
+
+/**
* ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
* @vsi: VSI to enable or disable VLAN pruning on
* @ena: set to true to enable VLAN pruning and false to disable it
@@ -2462,13 +2518,15 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
*/
int ice_vsi_release(struct ice_vsi *vsi)
{
+ struct ice_vf *vf = NULL;
struct ice_pf *pf;
- struct ice_vf *vf;
if (!vsi->back)
return -ENODEV;
pf = vsi->back;
- vf = &pf->vf[vsi->vf_id];
+
+ if (vsi->type == ICE_VSI_VF)
+ vf = &pf->vf[vsi->vf_id];
/* do not unregister and free netdevs while driver is in the reset
* recovery pending state. Since reset/rebuild happens through PF
* service task workqueue, its not a good idea to unregister netdev
@@ -2581,6 +2639,12 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)
goto err_vectors;
ice_vsi_map_rings_to_vectors(vsi);
+ /* Do not exit if configuring RSS had an issue, at least
+ * receive traffic on first queue. Hence no need to capture
+ * return value
+ */
+ if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags))
+ ice_vsi_cfg_rss_lut_key(vsi);
break;
case ICE_VSI_VF:
ret = ice_vsi_alloc_q_vectors(vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 3831b4f0960a..7988a53729a9 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -15,7 +15,7 @@ void ice_update_eth_stats(struct ice_vsi *vsi);
int ice_vsi_cfg_rxqs(struct ice_vsi *vsi);
-int ice_vsi_cfg_txqs(struct ice_vsi *vsi);
+int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi);
void ice_vsi_cfg_msix(struct ice_vsi *vsi);
@@ -31,7 +31,8 @@ int ice_vsi_start_rx_rings(struct ice_vsi *vsi);
int ice_vsi_stop_rx_rings(struct ice_vsi *vsi);
-int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
+int
+ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
u16 rel_vmvf_num);
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 8725569d11f0..47cc3f905b7f 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -609,7 +609,8 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi)
}
}
- ice_vc_notify_link_state(pf);
+ if (!new_link_same_as_old && pf->num_alloc_vfs)
+ ice_vc_notify_link_state(pf);
return 0;
}
@@ -1356,14 +1357,39 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
}
/**
+ * ice_dis_ctrlq_interrupts - disable control queue interrupts
+ * @hw: pointer to HW structure
+ */
+static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
+{
+ /* disable Admin queue Interrupt causes */
+ wr32(hw, PFINT_FW_CTL,
+ rd32(hw, PFINT_FW_CTL) & ~PFINT_FW_CTL_CAUSE_ENA_M);
+
+ /* disable Mailbox queue Interrupt causes */
+ wr32(hw, PFINT_MBX_CTL,
+ rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M);
+
+ /* disable Control queue Interrupt causes */
+ wr32(hw, PFINT_OICR_CTL,
+ rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M);
+
+ ice_flush(hw);
+}
+
+/**
* ice_free_irq_msix_misc - Unroll misc vector setup
* @pf: board private structure
*/
static void ice_free_irq_msix_misc(struct ice_pf *pf)
{
+ struct ice_hw *hw = &pf->hw;
+
+ ice_dis_ctrlq_interrupts(hw);
+
/* disable OICR interrupt */
- wr32(&pf->hw, PFINT_OICR_ENA, 0);
- ice_flush(&pf->hw);
+ wr32(hw, PFINT_OICR_ENA, 0);
+ ice_flush(hw);
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {
synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector);
@@ -1378,6 +1404,32 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
}
/**
+ * ice_ena_ctrlq_interrupts - enable control queue interrupts
+ * @hw: pointer to HW structure
+ * @v_idx: HW vector index to associate the control queue interrupts with
+ */
+static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 v_idx)
+{
+ u32 val;
+
+ val = ((v_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
+ PFINT_OICR_CTL_CAUSE_ENA_M);
+ wr32(hw, PFINT_OICR_CTL, val);
+
+ /* enable Admin queue Interrupt causes */
+ val = ((v_idx & PFINT_FW_CTL_MSIX_INDX_M) |
+ PFINT_FW_CTL_CAUSE_ENA_M);
+ wr32(hw, PFINT_FW_CTL, val);
+
+ /* enable Mailbox queue Interrupt causes */
+ val = ((v_idx & PFINT_MBX_CTL_MSIX_INDX_M) |
+ PFINT_MBX_CTL_CAUSE_ENA_M);
+ wr32(hw, PFINT_MBX_CTL, val);
+
+ ice_flush(hw);
+}
+
+/**
* ice_req_irq_msix_misc - Setup the misc vector to handle non queue events
* @pf: board private structure
*
@@ -1389,8 +1441,6 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
{
struct ice_hw *hw = &pf->hw;
int oicr_idx, err = 0;
- u8 itr_gran;
- u32 val;
if (!pf->int_name[0])
snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
@@ -1439,24 +1489,9 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
skip_req_irq:
ice_ena_misc_vector(pf);
- val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
- PFINT_OICR_CTL_CAUSE_ENA_M);
- wr32(hw, PFINT_OICR_CTL, val);
-
- /* This enables Admin queue Interrupt causes */
- val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) |
- PFINT_FW_CTL_CAUSE_ENA_M);
- wr32(hw, PFINT_FW_CTL, val);
-
- /* This enables Mailbox queue Interrupt causes */
- val = ((pf->hw_oicr_idx & PFINT_MBX_CTL_MSIX_INDX_M) |
- PFINT_MBX_CTL_CAUSE_ENA_M);
- wr32(hw, PFINT_MBX_CTL, val);
-
- itr_gran = hw->itr_gran;
-
+ ice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx);
wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),
- ITR_TO_REG(ICE_ITR_8K, itr_gran));
+ ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);
ice_flush(hw);
ice_irq_dynamic_ena(hw, NULL, NULL);
@@ -1516,8 +1551,8 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
u8 mac_addr[ETH_ALEN];
int err;
- netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv),
- vsi->alloc_txq, vsi->alloc_rxq);
+ netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
+ vsi->alloc_rxq);
if (!netdev)
return -ENOMEM;
@@ -1531,6 +1566,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
csumo_features = NETIF_F_RXCSUM |
NETIF_F_IP_CSUM |
+ NETIF_F_SCTP_CRC |
NETIF_F_IPV6_CSUM;
vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
@@ -1869,7 +1905,7 @@ static int ice_ena_msix_range(struct ice_pf *pf)
v_left -= pf->num_lan_msix;
pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget,
- sizeof(struct msix_entry), GFP_KERNEL);
+ sizeof(*pf->msix_entries), GFP_KERNEL);
if (!pf->msix_entries) {
err = -ENOMEM;
@@ -1957,7 +1993,6 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf)
static int ice_init_interrupt_scheme(struct ice_pf *pf)
{
int vectors = 0, hw_vectors = 0;
- ssize_t size;
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
vectors = ice_ena_msix_range(pf);
@@ -1968,9 +2003,9 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
return vectors;
/* set up vector assignment tracking */
- size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors);
-
- pf->sw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
+ pf->sw_irq_tracker =
+ devm_kzalloc(&pf->pdev->dev, sizeof(*pf->sw_irq_tracker) +
+ (sizeof(u16) * vectors), GFP_KERNEL);
if (!pf->sw_irq_tracker) {
ice_dis_msix(pf);
return -ENOMEM;
@@ -1982,9 +2017,9 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
/* set up HW vector assignment tracking */
hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
- size = sizeof(struct ice_res_tracker) + (sizeof(u16) * hw_vectors);
-
- pf->hw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
+ pf->hw_irq_tracker =
+ devm_kzalloc(&pf->pdev->dev, sizeof(*pf->hw_irq_tracker) +
+ (sizeof(u16) * hw_vectors), GFP_KERNEL);
if (!pf->hw_irq_tracker) {
ice_clear_interrupt_scheme(pf);
return -ENOMEM;
@@ -1998,6 +2033,23 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
}
/**
+ * ice_verify_itr_gran - verify driver's assumption of ITR granularity
+ * @pf: pointer to the PF structure
+ *
+ * There is no error returned here because the driver will be able to handle a
+ * different ITR granularity, but interrupt moderation will not be accurate if
+ * the driver's assumptions are not verified. This assumption is made so we can
+ * use constants in the hot path instead of accessing structure members.
+ */
+static void ice_verify_itr_gran(struct ice_pf *pf)
+{
+ if (pf->hw.itr_gran != (ICE_ITR_GRAN_S << 1))
+ dev_warn(&pf->pdev->dev,
+ "%d ITR granularity assumption is invalid, actual ITR granularity is %d. Interrupt moderation will be inaccurate!\n",
+ (ICE_ITR_GRAN_S << 1), pf->hw.itr_gran);
+}
+
+/**
* ice_verify_cacheline_size - verify driver's assumption of 64 Byte cache lines
* @pf: pointer to the PF structure
*
@@ -2101,7 +2153,7 @@ static int ice_probe(struct pci_dev *pdev,
}
pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi,
- sizeof(struct ice_vsi *), GFP_KERNEL);
+ sizeof(*pf->vsi), GFP_KERNEL);
if (!pf->vsi) {
err = -ENOMEM;
goto err_init_pf_unroll;
@@ -2133,7 +2185,7 @@ static int ice_probe(struct pci_dev *pdev,
}
/* create switch struct for the switch element created by FW on boot */
- pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw),
+ pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(*pf->first_sw),
GFP_KERNEL);
if (!pf->first_sw) {
err = -ENOMEM;
@@ -2163,6 +2215,7 @@ static int ice_probe(struct pci_dev *pdev,
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
ice_verify_cacheline_size(pf);
+ ice_verify_itr_gran(pf);
return 0;
@@ -2419,10 +2472,12 @@ static void ice_set_rx_mode(struct net_device *netdev)
* @addr: the MAC address entry being added
* @vid: VLAN id
* @flags: instructions from stack about fdb operation
+ * @extack: netlink extended ack
*/
-static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
- struct net_device *dev, const unsigned char *addr,
- u16 vid, u16 flags)
+static int
+ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
+ struct net_device *dev, const unsigned char *addr, u16 vid,
+ u16 flags, struct netlink_ext_ack __always_unused *extack)
{
int err;
@@ -2546,7 +2601,8 @@ static int ice_vsi_cfg(struct ice_vsi *vsi)
if (err)
return err;
}
- err = ice_vsi_cfg_txqs(vsi);
+
+ err = ice_vsi_cfg_lan_txqs(vsi);
if (!err)
err = ice_vsi_cfg_rxqs(vsi);
@@ -2945,12 +3001,91 @@ static void ice_napi_disable_all(struct ice_vsi *vsi)
}
/**
+ * ice_force_phys_link_state - Force the physical link state
+ * @vsi: VSI to force the physical link state to up/down
+ * @link_up: true/false indicates to set the physical link to up/down
+ *
+ * Force the physical link state by getting the current PHY capabilities from
+ * hardware and setting the PHY config based on the determined capabilities. If
+ * link changes a link event will be triggered because both the Enable Automatic
+ * Link Update and LESM Enable bits are set when setting the PHY capabilities.
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up)
+{
+ struct ice_aqc_get_phy_caps_data *pcaps;
+ struct ice_aqc_set_phy_cfg_data *cfg;
+ struct ice_port_info *pi;
+ struct device *dev;
+ int retcode;
+
+ if (!vsi || !vsi->port_info || !vsi->back)
+ return -EINVAL;
+ if (vsi->type != ICE_VSI_PF)
+ return 0;
+
+ dev = &vsi->back->pdev->dev;
+
+ pi = vsi->port_info;
+
+ pcaps = devm_kzalloc(dev, sizeof(*pcaps), GFP_KERNEL);
+ if (!pcaps)
+ return -ENOMEM;
+
+ retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
+ NULL);
+ if (retcode) {
+ dev_err(dev,
+ "Failed to get phy capabilities, VSI %d error %d\n",
+ vsi->vsi_num, retcode);
+ retcode = -EIO;
+ goto out;
+ }
+
+ /* No change in link */
+ if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) &&
+ link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP))
+ goto out;
+
+ cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
+ if (!cfg) {
+ retcode = -ENOMEM;
+ goto out;
+ }
+
+ cfg->phy_type_low = pcaps->phy_type_low;
+ cfg->phy_type_high = pcaps->phy_type_high;
+ cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
+ cfg->low_power_ctrl = pcaps->low_power_ctrl;
+ cfg->eee_cap = pcaps->eee_cap;
+ cfg->eeer_value = pcaps->eeer_value;
+ cfg->link_fec_opt = pcaps->link_fec_options;
+ if (link_up)
+ cfg->caps |= ICE_AQ_PHY_ENA_LINK;
+ else
+ cfg->caps &= ~ICE_AQ_PHY_ENA_LINK;
+
+ retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL);
+ if (retcode) {
+ dev_err(dev, "Failed to set phy config, VSI %d error %d\n",
+ vsi->vsi_num, retcode);
+ retcode = -EIO;
+ }
+
+ devm_kfree(dev, cfg);
+out:
+ devm_kfree(dev, pcaps);
+ return retcode;
+}
+
+/**
* ice_down - Shutdown the connection
* @vsi: The VSI being stopped
*/
int ice_down(struct ice_vsi *vsi)
{
- int i, tx_err, rx_err;
+ int i, tx_err, rx_err, link_err = 0;
/* Caller of this function is expected to set the
* vsi->state __ICE_DOWN bit
@@ -2961,7 +3096,8 @@ int ice_down(struct ice_vsi *vsi)
}
ice_vsi_dis_irq(vsi);
- tx_err = ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0);
+
+ tx_err = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);
if (tx_err)
netdev_err(vsi->netdev,
"Failed stop Tx rings, VSI %d error %d\n",
@@ -2975,13 +3111,21 @@ int ice_down(struct ice_vsi *vsi)
ice_napi_disable_all(vsi);
+ if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
+ link_err = ice_force_phys_link_state(vsi, false);
+ if (link_err)
+ netdev_err(vsi->netdev,
+ "Failed to set physical link down, VSI %d error %d\n",
+ vsi->vsi_num, link_err);
+ }
+
ice_for_each_txq(vsi, i)
ice_clean_tx_ring(vsi->tx_rings[i]);
ice_for_each_rxq(vsi, i)
ice_clean_rx_ring(vsi->rx_rings[i]);
- if (tx_err || rx_err) {
+ if (tx_err || rx_err || link_err) {
netdev_err(vsi->netdev,
"Failed to close VSI 0x%04X on switch 0x%04X\n",
vsi->vsi_num, vsi->vsw->sw_id);
@@ -3601,30 +3745,39 @@ static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode)
struct device *dev = &vsi->back->pdev->dev;
struct ice_aqc_vsi_props *vsi_props;
struct ice_hw *hw = &vsi->back->hw;
- struct ice_vsi_ctx ctxt = { 0 };
+ struct ice_vsi_ctx *ctxt;
enum ice_status status;
+ int ret = 0;
vsi_props = &vsi->info;
- ctxt.info = vsi->info;
+
+ ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return -ENOMEM;
+
+ ctxt->info = vsi->info;
if (bmode == BRIDGE_MODE_VEB)
/* change from VEPA to VEB mode */
- ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
+ ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
else
/* change from VEB to VEPA mode */
- ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
- ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
+ ctxt->info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
+ ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
- status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
+ status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (status) {
dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n",
bmode, status, hw->adminq.sq_last_status);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
/* Update sw flags for book keeping */
- vsi_props->sw_flags = ctxt.info.sw_flags;
+ vsi_props->sw_flags = ctxt->info.sw_flags;
- return 0;
+out:
+ devm_kfree(dev, ctxt);
+ return ret;
}
/**
@@ -3641,7 +3794,8 @@ static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode)
*/
static int
ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
- u16 __always_unused flags, struct netlink_ext_ack *extack)
+ u16 __always_unused flags,
+ struct netlink_ext_ack __always_unused *extack)
{
struct ice_netdev_priv *np = netdev_priv(dev);
struct ice_pf *pf = np->vsi->back;
@@ -3814,8 +3968,14 @@ static int ice_open(struct net_device *netdev)
netif_carrier_off(netdev);
- err = ice_vsi_open(vsi);
+ err = ice_force_phys_link_state(vsi, true);
+ if (err) {
+ netdev_err(netdev,
+ "Failed to set physical link up, error %d\n", err);
+ return err;
+ }
+ err = ice_vsi_open(vsi);
if (err)
netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
vsi->vsi_num, vsi->vsw->sw_id);
diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c
index 3274c543283c..413fdbbcc4d0 100644
--- a/drivers/net/ethernet/intel/ice/ice_nvm.c
+++ b/drivers/net/ethernet/intel/ice/ice_nvm.c
@@ -125,6 +125,63 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
}
/**
+ * ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
+ * @words: (in) number of words to read; (out) number of words actually read
+ * @data: words read from the Shadow RAM
+ *
+ * Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq
+ * method. Ownership of the NVM is taken before reading the buffer and later
+ * released.
+ */
+static enum ice_status
+ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
+{
+ enum ice_status status;
+ bool last_cmd = false;
+ u16 words_read = 0;
+ u16 i = 0;
+
+ do {
+ u16 read_size, off_w;
+
+ /* Calculate number of bytes we should read in this step.
+ * It's not allowed to read more than one page at a time or
+ * to cross page boundaries.
+ */
+ off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS;
+ read_size = off_w ?
+ min_t(u16, *words,
+ (ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) :
+ min_t(u16, (*words - words_read),
+ ICE_SR_SECTOR_SIZE_IN_WORDS);
+
+ /* Check if this is last command, if so set proper flag */
+ if ((words_read + read_size) >= *words)
+ last_cmd = true;
+
+ status = ice_read_sr_aq(hw, offset, read_size,
+ data + words_read, last_cmd);
+ if (status)
+ goto read_nvm_buf_aq_exit;
+
+ /* Increment counter for words already read and move offset to
+ * new read location
+ */
+ words_read += read_size;
+ offset += read_size;
+ } while (words_read < *words);
+
+ for (i = 0; i < *words; i++)
+ data[i] = le16_to_cpu(((__le16 *)data)[i]);
+
+read_nvm_buf_aq_exit:
+ *words = words_read;
+ return status;
+}
+
+/**
* ice_acquire_nvm - Generic request for acquiring the NVM ownership
* @hw: pointer to the HW structure
* @access: NVM access type (read or write)
@@ -234,3 +291,28 @@ enum ice_status ice_init_nvm(struct ice_hw *hw)
return status;
}
+
+/**
+ * ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
+ * @words: (in) number of words to read; (out) number of words actually read
+ * @data: words read from the Shadow RAM
+ *
+ * Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq
+ * method. The buf read is preceded by the NVM ownership take
+ * and followed by the release.
+ */
+enum ice_status
+ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
+{
+ enum ice_status status;
+
+ status = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (!status) {
+ status = ice_read_sr_buf_aq(hw, offset, words, data);
+ ice_release_nvm(hw);
+ }
+
+ return status;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
index a1681853df2e..56049739a250 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.c
+++ b/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -85,37 +85,59 @@ ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid)
}
/**
- * ice_aq_query_sched_elems - query scheduler elements
+ * ice_aqc_send_sched_elem_cmd - send scheduling elements cmd
* @hw: pointer to the hw struct
- * @elems_req: number of elements to query
+ * @cmd_opc: cmd opcode
+ * @elems_req: number of elements to request
* @buf: pointer to buffer
* @buf_size: buffer size in bytes
- * @elems_ret: returns total number of elements returned
+ * @elems_resp: returns total number of elements response
* @cd: pointer to command details structure or NULL
*
- * Query scheduling elements (0x0404)
+ * This function sends a scheduling elements cmd (cmd_opc)
*/
static enum ice_status
-ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,
- struct ice_aqc_get_elem *buf, u16 buf_size,
- u16 *elems_ret, struct ice_sq_cd *cd)
+ice_aqc_send_sched_elem_cmd(struct ice_hw *hw, enum ice_adminq_opc cmd_opc,
+ u16 elems_req, void *buf, u16 buf_size,
+ u16 *elems_resp, struct ice_sq_cd *cd)
{
- struct ice_aqc_get_cfg_elem *cmd;
+ struct ice_aqc_sched_elem_cmd *cmd;
struct ice_aq_desc desc;
enum ice_status status;
- cmd = &desc.params.get_update_elem;
- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sched_elems);
+ cmd = &desc.params.sched_elem_cmd;
+ ice_fill_dflt_direct_cmd_desc(&desc, cmd_opc);
cmd->num_elem_req = cpu_to_le16(elems_req);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
- if (!status && elems_ret)
- *elems_ret = le16_to_cpu(cmd->num_elem_resp);
+ if (!status && elems_resp)
+ *elems_resp = le16_to_cpu(cmd->num_elem_resp);
return status;
}
/**
+ * ice_aq_query_sched_elems - query scheduler elements
+ * @hw: pointer to the hw struct
+ * @elems_req: number of elements to query
+ * @buf: pointer to buffer
+ * @buf_size: buffer size in bytes
+ * @elems_ret: returns total number of elements returned
+ * @cd: pointer to command details structure or NULL
+ *
+ * Query scheduling elements (0x0404)
+ */
+static enum ice_status
+ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,
+ struct ice_aqc_get_elem *buf, u16 buf_size,
+ u16 *elems_ret, struct ice_sq_cd *cd)
+{
+ return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_get_sched_elems,
+ elems_req, (void *)buf, buf_size,
+ elems_ret, cd);
+}
+
+/**
* ice_sched_query_elem - query element information from hw
* @hw: pointer to the hw struct
* @node_teid: node teid to be queried
@@ -218,20 +240,9 @@ ice_aq_delete_sched_elems(struct ice_hw *hw, u16 grps_req,
struct ice_aqc_delete_elem *buf, u16 buf_size,
u16 *grps_del, struct ice_sq_cd *cd)
{
- struct ice_aqc_add_move_delete_elem *cmd;
- struct ice_aq_desc desc;
- enum ice_status status;
-
- cmd = &desc.params.add_move_delete_elem;
- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_delete_sched_elems);
- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
- cmd->num_grps_req = cpu_to_le16(grps_req);
-
- status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
- if (!status && grps_del)
- *grps_del = le16_to_cpu(cmd->num_grps_updated);
-
- return status;
+ return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_delete_sched_elems,
+ grps_req, (void *)buf, buf_size,
+ grps_del, cd);
}
/**
@@ -442,52 +453,9 @@ ice_aq_add_sched_elems(struct ice_hw *hw, u16 grps_req,
struct ice_aqc_add_elem *buf, u16 buf_size,
u16 *grps_added, struct ice_sq_cd *cd)
{
- struct ice_aqc_add_move_delete_elem *cmd;
- struct ice_aq_desc desc;
- enum ice_status status;
-
- cmd = &desc.params.add_move_delete_elem;
- ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_sched_elems);
- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
-
- cmd->num_grps_req = cpu_to_le16(grps_req);
- status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
- if (!status && grps_added)
- *grps_added = le16_to_cpu(cmd->num_grps_updated);
-
- return status;
-}
-
-/**
- * ice_suspend_resume_elems - suspend/resume scheduler elements
- * @hw: pointer to the hw struct
- * @elems_req: number of elements to suspend
- * @buf: pointer to buffer
- * @buf_size: buffer size in bytes
- * @elems_ret: returns total number of elements suspended
- * @cd: pointer to command details structure or NULL
- * @cmd_code: command code for suspend or resume
- *
- * suspend/resume scheduler elements
- */
-static enum ice_status
-ice_suspend_resume_elems(struct ice_hw *hw, u16 elems_req,
- struct ice_aqc_suspend_resume_elem *buf, u16 buf_size,
- u16 *elems_ret, struct ice_sq_cd *cd,
- enum ice_adminq_opc cmd_code)
-{
- struct ice_aqc_get_cfg_elem *cmd;
- struct ice_aq_desc desc;
- enum ice_status status;
-
- cmd = &desc.params.get_update_elem;
- ice_fill_dflt_direct_cmd_desc(&desc, cmd_code);
- cmd->num_elem_req = cpu_to_le16(elems_req);
- desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
- status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
- if (!status && elems_ret)
- *elems_ret = le16_to_cpu(cmd->num_elem_resp);
- return status;
+ return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_add_sched_elems,
+ grps_req, (void *)buf, buf_size,
+ grps_added, cd);
}
/**
@@ -506,8 +474,9 @@ ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req,
struct ice_aqc_suspend_resume_elem *buf,
u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
{
- return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret,
- cd, ice_aqc_opc_suspend_sched_elems);
+ return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_suspend_sched_elems,
+ elems_req, (void *)buf, buf_size,
+ elems_ret, cd);
}
/**
@@ -526,8 +495,9 @@ ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req,
struct ice_aqc_suspend_resume_elem *buf,
u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
{
- return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret,
- cd, ice_aqc_opc_resume_sched_elems);
+ return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_resume_sched_elems,
+ elems_req, (void *)buf, buf_size,
+ elems_ret, cd);
}
/**
@@ -591,23 +561,18 @@ ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids,
}
/**
- * ice_sched_clear_tx_topo - clears the schduler tree nodes
- * @pi: port information structure
+ * ice_sched_clear_agg - clears the agg related information
+ * @hw: pointer to the hardware structure
*
- * This function removes all the nodes from HW as well as from SW DB.
+ * This function removes agg list and free up agg related memory
+ * previously allocated.
*/
-static void ice_sched_clear_tx_topo(struct ice_port_info *pi)
+void ice_sched_clear_agg(struct ice_hw *hw)
{
struct ice_sched_agg_info *agg_info;
struct ice_sched_agg_info *atmp;
- struct ice_hw *hw;
-
- if (!pi)
- return;
-
- hw = pi->hw;
- list_for_each_entry_safe(agg_info, atmp, &pi->agg_list, list_entry) {
+ list_for_each_entry_safe(agg_info, atmp, &hw->agg_list, list_entry) {
struct ice_sched_agg_vsi_info *agg_vsi_info;
struct ice_sched_agg_vsi_info *vtmp;
@@ -616,8 +581,21 @@ static void ice_sched_clear_tx_topo(struct ice_port_info *pi)
list_del(&agg_vsi_info->list_entry);
devm_kfree(ice_hw_to_dev(hw), agg_vsi_info);
}
+ list_del(&agg_info->list_entry);
+ devm_kfree(ice_hw_to_dev(hw), agg_info);
}
+}
+/**
+ * ice_sched_clear_tx_topo - clears the scheduler tree nodes
+ * @pi: port information structure
+ *
+ * This function removes all the nodes from HW as well as from SW DB.
+ */
+static void ice_sched_clear_tx_topo(struct ice_port_info *pi)
+{
+ if (!pi)
+ return;
if (pi->root) {
ice_free_sched_node(pi, pi->root);
pi->root = NULL;
@@ -1035,7 +1013,6 @@ enum ice_status ice_sched_init_port(struct ice_port_info *pi)
/* initialize the port for handling the scheduler tree */
pi->port_state = ICE_SCHED_PORT_STATE_READY;
mutex_init(&pi->sched_lock);
- INIT_LIST_HEAD(&pi->agg_list);
err_init_port:
if (status && pi->root) {
@@ -1089,11 +1066,10 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
hw->max_children[i] = le16_to_cpu(max_sibl);
}
- hw->layer_info = (struct ice_aqc_layer_props *)
- devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
- (hw->num_tx_sched_layers *
- sizeof(*hw->layer_info)),
- GFP_KERNEL);
+ hw->layer_info = devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
+ (hw->num_tx_sched_layers *
+ sizeof(*hw->layer_info)),
+ GFP_KERNEL);
if (!hw->layer_info) {
status = ICE_ERR_NO_MEMORY;
goto sched_query_out;
@@ -1367,9 +1343,14 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
node = node->sibling;
}
+ /* tree has one intermediate node to add this new VSI.
+ * So no need to calculate supported nodes for below
+ * layers.
+ */
+ if (node)
+ break;
/* all the nodes are full, allocate a new one */
- if (!node)
- num_nodes[i]++;
+ num_nodes[i]++;
}
}
@@ -1618,7 +1599,8 @@ ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle)
struct ice_sched_agg_info *agg_info;
struct ice_sched_agg_info *atmp;
- list_for_each_entry_safe(agg_info, atmp, &pi->agg_list, list_entry) {
+ list_for_each_entry_safe(agg_info, atmp, &pi->hw->agg_list,
+ list_entry) {
struct ice_sched_agg_vsi_info *agg_vsi_info;
struct ice_sched_agg_vsi_info *vtmp;
@@ -1634,6 +1616,23 @@ ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle)
}
/**
+ * ice_sched_is_leaf_node_present - check for a leaf node in the sub-tree
+ * @node: pointer to the sub-tree node
+ *
+ * This function checks for a leaf node presence in a given sub-tree node.
+ */
+static bool ice_sched_is_leaf_node_present(struct ice_sched_node *node)
+{
+ u8 i;
+
+ for (i = 0; i < node->num_children; i++)
+ if (ice_sched_is_leaf_node_present(node->children[i]))
+ return true;
+ /* check for a leaf node */
+ return (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF);
+}
+
+/**
* ice_sched_rm_vsi_cfg - remove the VSI and its children nodes
* @pi: port information structure
* @vsi_handle: software VSI handle
@@ -1667,6 +1666,12 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
if (!vsi_node)
continue;
+ if (ice_sched_is_leaf_node_present(vsi_node)) {
+ ice_debug(pi->hw, ICE_DBG_SCHED,
+ "VSI has leaf nodes in TC %d\n", i);
+ status = ICE_ERR_IN_USE;
+ goto exit_sched_rm_vsi_cfg;
+ }
while (j < vsi_node->num_children) {
if (vsi_node->children[j]->owner == owner) {
ice_free_sched_node(pi, vsi_node->children[j]);
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.h b/drivers/net/ethernet/intel/ice/ice_sched.h
index da5b4c166da8..bee8221ad146 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.h
+++ b/drivers/net/ethernet/intel/ice/ice_sched.h
@@ -28,6 +28,8 @@ enum ice_status ice_sched_init_port(struct ice_port_info *pi);
enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw);
void ice_sched_clear_port(struct ice_port_info *pi);
void ice_sched_cleanup_all(struct ice_hw *hw);
+void ice_sched_clear_agg(struct ice_hw *hw);
+
struct ice_sched_node *
ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid);
enum ice_status
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 533b989a23e1..d2db0d04e117 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -85,6 +85,12 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
case ICE_AQ_LINK_SPEED_40GB:
speed = ICE_LINK_SPEED_40000MBPS;
break;
+ case ICE_AQ_LINK_SPEED_50GB:
+ speed = ICE_LINK_SPEED_50000MBPS;
+ break;
+ case ICE_AQ_LINK_SPEED_100GB:
+ speed = ICE_LINK_SPEED_100000MBPS;
+ break;
default:
speed = ICE_LINK_SPEED_UNKNOWN;
break;
@@ -116,6 +122,9 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
break;
case ICE_AQ_LINK_SPEED_40GB:
/* fall through */
+ case ICE_AQ_LINK_SPEED_50GB:
+ /* fall through */
+ case ICE_AQ_LINK_SPEED_100GB:
speed = (u32)VIRTCHNL_LINK_SPEED_40GB;
break;
default:
diff --git a/drivers/net/ethernet/intel/ice/ice_status.h b/drivers/net/ethernet/intel/ice/ice_status.h
index f49f299ddf2c..683f48824a29 100644
--- a/drivers/net/ethernet/intel/ice/ice_status.h
+++ b/drivers/net/ethernet/intel/ice/ice_status.h
@@ -22,6 +22,7 @@ enum ice_status {
ICE_ERR_OUT_OF_RANGE = -13,
ICE_ERR_ALREADY_EXISTS = -14,
ICE_ERR_DOES_NOT_EXIST = -15,
+ ICE_ERR_IN_USE = -16,
ICE_ERR_MAX_LIMIT = -17,
ICE_ERR_RESET_ONGOING = -18,
ICE_ERR_BUF_TOO_SHORT = -52,
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index 2e5693107fa4..09d1c314b68f 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -98,7 +98,7 @@ enum ice_status ice_init_def_sw_recp(struct ice_hw *hw)
u8 i;
recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
- sizeof(struct ice_sw_recipe), GFP_KERNEL);
+ sizeof(*recps), GFP_KERNEL);
if (!recps)
return ICE_ERR_NO_MEMORY;
@@ -1538,9 +1538,20 @@ ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
} else if (!list_elem->vsi_list_info) {
status = ICE_ERR_DOES_NOT_EXIST;
goto exit;
+ } else if (list_elem->vsi_list_info->ref_cnt > 1) {
+ /* a ref_cnt > 1 indicates that the vsi_list is being
+ * shared by multiple rules. Decrement the ref_cnt and
+ * remove this rule, but do not modify the list, as it
+ * is in-use by other rules.
+ */
+ list_elem->vsi_list_info->ref_cnt--;
+ remove_rule = true;
} else {
- if (list_elem->vsi_list_info->ref_cnt > 1)
- list_elem->vsi_list_info->ref_cnt--;
+ /* a ref_cnt of 1 indicates the vsi_list is only used
+ * by one rule. However, the original removal request is only
+ * for a single VSI. Update the vsi_list first, and only
+ * remove the rule if there are no further VSIs in this list.
+ */
vsi_handle = f_entry->fltr_info.vsi_handle;
status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
if (status)
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 49fc38094185..c289d97f477d 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -48,7 +48,6 @@ static struct netdev_queue *txring_txq(const struct ice_ring *ring)
*/
void ice_clean_tx_ring(struct ice_ring *tx_ring)
{
- unsigned long size;
u16 i;
/* ring already cleared, nothing to do */
@@ -59,8 +58,7 @@ void ice_clean_tx_ring(struct ice_ring *tx_ring)
for (i = 0; i < tx_ring->count; i++)
ice_unmap_and_free_tx_buf(tx_ring, &tx_ring->tx_buf[i]);
- size = sizeof(struct ice_tx_buf) * tx_ring->count;
- memset(tx_ring->tx_buf, 0, size);
+ memset(tx_ring->tx_buf, 0, sizeof(*tx_ring->tx_buf) * tx_ring->count);
/* Zero out the descriptor ring */
memset(tx_ring->desc, 0, tx_ring->size);
@@ -226,21 +224,21 @@ static bool ice_clean_tx_irq(struct ice_vsi *vsi, struct ice_ring *tx_ring,
int ice_setup_tx_ring(struct ice_ring *tx_ring)
{
struct device *dev = tx_ring->dev;
- int bi_size;
if (!dev)
return -ENOMEM;
/* warn if we are about to overwrite the pointer */
WARN_ON(tx_ring->tx_buf);
- bi_size = sizeof(struct ice_tx_buf) * tx_ring->count;
- tx_ring->tx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL);
+ tx_ring->tx_buf =
+ devm_kzalloc(dev, sizeof(*tx_ring->tx_buf) * tx_ring->count,
+ GFP_KERNEL);
if (!tx_ring->tx_buf)
return -ENOMEM;
/* round up to nearest 4K */
- tx_ring->size = tx_ring->count * sizeof(struct ice_tx_desc);
- tx_ring->size = ALIGN(tx_ring->size, 4096);
+ tx_ring->size = ALIGN(tx_ring->count * sizeof(struct ice_tx_desc),
+ 4096);
tx_ring->desc = dmam_alloc_coherent(dev, tx_ring->size, &tx_ring->dma,
GFP_KERNEL);
if (!tx_ring->desc) {
@@ -267,7 +265,6 @@ err:
void ice_clean_rx_ring(struct ice_ring *rx_ring)
{
struct device *dev = rx_ring->dev;
- unsigned long size;
u16 i;
/* ring already cleared, nothing to do */
@@ -292,8 +289,7 @@ void ice_clean_rx_ring(struct ice_ring *rx_ring)
rx_buf->page_offset = 0;
}
- size = sizeof(struct ice_rx_buf) * rx_ring->count;
- memset(rx_ring->rx_buf, 0, size);
+ memset(rx_ring->rx_buf, 0, sizeof(*rx_ring->rx_buf) * rx_ring->count);
/* Zero out the descriptor ring */
memset(rx_ring->desc, 0, rx_ring->size);
@@ -331,15 +327,15 @@ void ice_free_rx_ring(struct ice_ring *rx_ring)
int ice_setup_rx_ring(struct ice_ring *rx_ring)
{
struct device *dev = rx_ring->dev;
- int bi_size;
if (!dev)
return -ENOMEM;
/* warn if we are about to overwrite the pointer */
WARN_ON(rx_ring->rx_buf);
- bi_size = sizeof(struct ice_rx_buf) * rx_ring->count;
- rx_ring->rx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL);
+ rx_ring->rx_buf =
+ devm_kzalloc(dev, sizeof(*rx_ring->rx_buf) * rx_ring->count,
+ GFP_KERNEL);
if (!rx_ring->rx_buf)
return -ENOMEM;
@@ -1053,6 +1049,69 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget)
}
/**
+ * ice_buildreg_itr - build value for writing to the GLINT_DYN_CTL register
+ * @itr_idx: interrupt throttling index
+ * @reg_itr: interrupt throttling value adjusted based on ITR granularity
+ */
+static u32 ice_buildreg_itr(int itr_idx, u16 reg_itr)
+{
+ return GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M |
+ (itr_idx << GLINT_DYN_CTL_ITR_INDX_S) |
+ (reg_itr << GLINT_DYN_CTL_INTERVAL_S);
+}
+
+/**
+ * ice_update_ena_itr - Update ITR and re-enable MSIX interrupt
+ * @vsi: the VSI associated with the q_vector
+ * @q_vector: q_vector for which ITR is being updated and interrupt enabled
+ */
+static void
+ice_update_ena_itr(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
+{
+ struct ice_hw *hw = &vsi->back->hw;
+ struct ice_ring_container *rc;
+ u32 itr_val;
+
+ /* This block of logic allows us to get away with only updating
+ * one ITR value with each interrupt. The idea is to perform a
+ * pseudo-lazy update with the following criteria.
+ *
+ * 1. Rx is given higher priority than Tx if both are in same state
+ * 2. If we must reduce an ITR that is given highest priority.
+ * 3. We then give priority to increasing ITR based on amount.
+ */
+ if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
+ rc = &q_vector->rx;
+ /* Rx ITR needs to be reduced, this is highest priority */
+ itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
+ rc->current_itr = rc->target_itr;
+ } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
+ ((q_vector->rx.target_itr - q_vector->rx.current_itr) <
+ (q_vector->tx.target_itr - q_vector->tx.current_itr))) {
+ rc = &q_vector->tx;
+ /* Tx ITR needs to be reduced, this is second priority
+ * Tx ITR needs to be increased more than Rx, fourth priority
+ */
+ itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
+ rc->current_itr = rc->target_itr;
+ } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
+ rc = &q_vector->rx;
+ /* Rx ITR needs to be increased, third priority */
+ itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
+ rc->current_itr = rc->target_itr;
+ } else {
+ /* Still have to re-enable the interrupts */
+ itr_val = ice_buildreg_itr(ICE_ITR_NONE, 0);
+ }
+
+ if (!test_bit(__ICE_DOWN, vsi->state)) {
+ int vector = vsi->hw_base_vector + q_vector->v_idx;
+
+ wr32(hw, GLINT_DYN_CTL(vector), itr_val);
+ }
+}
+
+/**
* ice_napi_poll - NAPI polling Rx/Tx cleanup routine
* @napi: napi struct with our devices info in it
* @budget: amount of work driver is allowed to do this pass, in packets
@@ -1108,9 +1167,9 @@ int ice_napi_poll(struct napi_struct *napi, int budget)
*/
if (likely(napi_complete_done(napi, work_done)))
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
- ice_irq_dynamic_ena(&vsi->back->hw, vsi, q_vector);
+ ice_update_ena_itr(vsi, q_vector);
- return min(work_done, budget - 1);
+ return min_t(int, work_done, budget - 1);
}
/* helper function for building cmd/type/offset */
@@ -1402,6 +1461,12 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
offset |= l4_len << ICE_TX_DESC_LEN_L4_LEN_S;
break;
case IPPROTO_SCTP:
+ /* enable SCTP checksum offload */
+ cmd |= ICE_TX_DESC_CMD_L4T_EOFT_SCTP;
+ l4_len = sizeof(struct sctphdr) >> 2;
+ offset |= l4_len << ICE_TX_DESC_LEN_L4_LEN_S;
+ break;
+
default:
if (first->tx_flags & ICE_TX_FLAGS_TSO)
return -1;
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index 75d0eaf6c9dd..fc358ea81816 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -116,16 +116,17 @@ enum ice_rx_dtype {
/* indices into GLINT_ITR registers */
#define ICE_RX_ITR ICE_IDX_ITR0
#define ICE_TX_ITR ICE_IDX_ITR1
-#define ICE_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
-#define ICE_ITR_8K 125
+#define ICE_ITR_8K 124
#define ICE_ITR_20K 50
-#define ICE_DFLT_TX_ITR ICE_ITR_20K
-#define ICE_DFLT_RX_ITR ICE_ITR_20K
-/* apply ITR granularity translation to program the register. itr_gran is either
- * 2 or 4 usecs so we need to divide by 2 first then shift by that value
- */
-#define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> \
- ((itr_gran) / 2))
+#define ICE_ITR_MAX 8160
+#define ICE_DFLT_TX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC)
+#define ICE_DFLT_RX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC)
+#define ICE_ITR_DYNAMIC 0x8000 /* used as flag for itr_setting */
+#define ITR_IS_DYNAMIC(setting) (!!((setting) & ICE_ITR_DYNAMIC))
+#define ITR_TO_REG(setting) ((setting) & ~ICE_ITR_DYNAMIC)
+#define ICE_ITR_GRAN_S 1 /* Assume ITR granularity is 2us */
+#define ICE_ITR_MASK 0x1FFE /* ITR register value alignment mask */
+#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK)
#define ICE_DFLT_INTRL 0
@@ -180,13 +181,20 @@ enum ice_latency_range {
};
struct ice_ring_container {
- /* array of pointers to rings */
+ /* head of linked-list of rings */
struct ice_ring *ring;
+ unsigned long next_update; /* jiffies value of next queue update */
unsigned int total_bytes; /* total bytes processed this int */
unsigned int total_pkts; /* total packets processed this int */
enum ice_latency_range latency_range;
- int itr_idx; /* index in the interrupt vector */
- u16 itr;
+ int itr_idx; /* index in the interrupt vector */
+ u16 target_itr; /* value in usecs divided by the hw->itr_gran */
+ u16 current_itr; /* value in usecs divided by the hw->itr_gran */
+ /* high bit set means dynamic ITR, rest is used to store user
+ * readable ITR value in usecs and must be converted before programming
+ * to a register.
+ */
+ u16 itr_setting;
};
/* iterator for handling rings in ring container */
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 0ea428104215..17086d5b5c33 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -90,6 +90,7 @@ enum ice_vsi_type {
struct ice_link_status {
/* Refer to ice_aq_phy_type for bits definition */
u64 phy_type_low;
+ u64 phy_type_high;
u16 max_frame_size;
u16 link_speed;
u16 req_speeds;
@@ -118,6 +119,7 @@ struct ice_phy_info {
struct ice_link_status link_info;
struct ice_link_status link_info_old;
u64 phy_type_low;
+ u64 phy_type_high;
enum ice_media_type media_type;
u8 get_link_info;
};
@@ -272,7 +274,6 @@ struct ice_port_info {
struct ice_mac_info mac;
struct ice_phy_info phy;
struct mutex sched_lock; /* protect access to TXSched tree */
- struct list_head agg_list; /* lists all aggregator */
u8 lport;
#define ICE_LPORT_MASK 0xff
u8 is_vf;
@@ -326,6 +327,7 @@ struct ice_hw {
u8 max_cgds;
u8 sw_entry_point_layer;
u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM];
+ struct list_head agg_list; /* lists all aggregator */
struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI];
u8 evb_veb; /* true for VEB, false for VEPA */
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
index 05ff4f910649..57155b4a59dc 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -173,7 +173,8 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
wr32(hw, VPINT_ALLOC(vf->vf_id), 0);
wr32(hw, VPINT_ALLOC_PCI(vf->vf_id), 0);
- first = vf->first_vector_idx;
+ first = vf->first_vector_idx +
+ hw->func_caps.common_cap.msix_vector_first_id;
last = first + pf->num_vf_msix - 1;
for (v = first; v <= last; v++) {
u32 reg;
@@ -224,13 +225,15 @@ void ice_free_vfs(struct ice_pf *pf)
/* Avoid wait time by stopping all VFs at the same time */
for (i = 0; i < pf->num_alloc_vfs; i++) {
+ struct ice_vsi *vsi;
+
if (!test_bit(ICE_VF_STATE_ENA, pf->vf[i].vf_states))
continue;
+ vsi = pf->vsi[pf->vf[i].lan_vsi_idx];
/* stop rings without wait time */
- ice_vsi_stop_tx_rings(pf->vsi[pf->vf[i].lan_vsi_idx],
- ICE_NO_RESET, i);
- ice_vsi_stop_rx_rings(pf->vsi[pf->vf[i].lan_vsi_idx]);
+ ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, i);
+ ice_vsi_stop_rx_rings(vsi);
clear_bit(ICE_VF_STATE_ENA, pf->vf[i].vf_states);
}
@@ -308,6 +311,11 @@ static void ice_trigger_vf_reset(struct ice_vf *vf, bool is_vflr)
*/
clear_bit(ICE_VF_STATE_INIT, vf->vf_states);
+ /* Clear the VF's ARQLEN register. This is how the VF detects reset,
+ * since the VFGEN_RSTAT register doesn't stick at 0 after reset.
+ */
+ wr32(hw, VF_MBX_ARQLEN(vf_abs_id), 0);
+
/* In the case of a VFLR, the HW has already reset the VF and we
* just need to clean up, so don't hit the VFRTRIG register.
*/
@@ -343,25 +351,33 @@ static int ice_vsi_set_pvid(struct ice_vsi *vsi, u16 vid)
{
struct device *dev = &vsi->back->pdev->dev;
struct ice_hw *hw = &vsi->back->hw;
- struct ice_vsi_ctx ctxt = { 0 };
+ struct ice_vsi_ctx *ctxt;
enum ice_status status;
+ int ret = 0;
+
+ ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ return -ENOMEM;
- ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_UNTAGGED |
- ICE_AQ_VSI_PVLAN_INSERT_PVID |
- ICE_AQ_VSI_VLAN_EMOD_STR;
- ctxt.info.pvid = cpu_to_le16(vid);
- ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
+ ctxt->info.vlan_flags = (ICE_AQ_VSI_VLAN_MODE_UNTAGGED |
+ ICE_AQ_VSI_PVLAN_INSERT_PVID |
+ ICE_AQ_VSI_VLAN_EMOD_STR);
+ ctxt->info.pvid = cpu_to_le16(vid);
+ ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
- status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
+ status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (status) {
dev_info(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- vsi->info.pvid = ctxt.info.pvid;
- vsi->info.vlan_flags = ctxt.info.vlan_flags;
- return 0;
+ vsi->info.pvid = ctxt->info.pvid;
+ vsi->info.vlan_flags = ctxt->info.vlan_flags;
+out:
+ devm_kfree(dev, ctxt);
+ return ret;
}
/**
@@ -508,7 +524,8 @@ static void ice_ena_vf_mappings(struct ice_vf *vf)
hw = &pf->hw;
vsi = pf->vsi[vf->lan_vsi_idx];
- first = vf->first_vector_idx;
+ first = vf->first_vector_idx +
+ hw->func_caps.common_cap.msix_vector_first_id;
last = (first + pf->num_vf_msix) - 1;
abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
@@ -831,6 +848,7 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
{
struct ice_pf *pf = vf->pf;
struct ice_hw *hw = &pf->hw;
+ struct ice_vsi *vsi;
bool rsd = false;
u32 reg;
int i;
@@ -843,17 +861,18 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
ice_trigger_vf_reset(vf, is_vflr);
+ vsi = pf->vsi[vf->lan_vsi_idx];
+
if (test_bit(ICE_VF_STATE_ENA, vf->vf_states)) {
- ice_vsi_stop_tx_rings(pf->vsi[vf->lan_vsi_idx], ICE_VF_RESET,
- vf->vf_id);
- ice_vsi_stop_rx_rings(pf->vsi[vf->lan_vsi_idx]);
+ ice_vsi_stop_lan_tx_rings(vsi, ICE_VF_RESET, vf->vf_id);
+ ice_vsi_stop_rx_rings(vsi);
clear_bit(ICE_VF_STATE_ENA, vf->vf_states);
} else {
/* Call Disable LAN Tx queue AQ call even when queues are not
* enabled. This is needed for successful completiom of VFR
*/
- ice_dis_vsi_txq(pf->vsi[vf->lan_vsi_idx]->port_info, 0,
- NULL, NULL, ICE_VF_RESET, vf->vf_id, NULL);
+ ice_dis_vsi_txq(vsi->port_info, 0, NULL, NULL, ICE_VF_RESET,
+ vf->vf_id, NULL);
}
/* poll VPGEN_VFRSTAT reg to make sure
@@ -1614,7 +1633,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
goto error_param;
}
- if (ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, vf->vf_id)) {
+ if (ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id)) {
dev_err(&vsi->back->pdev->dev,
"Failed to stop tx rings on VSI %d\n",
vsi->vsi_num);
@@ -1784,7 +1803,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
vsi->num_txq = qci->num_queue_pairs;
vsi->num_rxq = qci->num_queue_pairs;
- if (!ice_vsi_cfg_txqs(vsi) && !ice_vsi_cfg_rxqs(vsi))
+ if (!ice_vsi_cfg_lan_txqs(vsi) && !ice_vsi_cfg_rxqs(vsi))
aq_ret = 0;
else
aq_ret = ICE_ERR_PARAM;
@@ -2475,11 +2494,12 @@ int ice_get_vf_cfg(struct net_device *netdev, int vf_id,
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
- struct ice_vsi_ctx ctx = { 0 };
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
+ struct ice_vsi_ctx *ctx;
+ enum ice_status status;
struct ice_vf *vf;
- int status;
+ int ret = 0;
/* validate the request */
if (vf_id >= pf->num_alloc_vfs) {
@@ -2499,25 +2519,31 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
return 0;
}
- ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
+ ctx = devm_kzalloc(&pf->pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
if (ena) {
- ctx.info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
- ctx.info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M;
+ ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
+ ctx->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M;
}
- status = ice_update_vsi(&pf->hw, vsi->idx, &ctx, NULL);
+ status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL);
if (status) {
dev_dbg(&pf->pdev->dev,
"Error %d, failed to update VSI* parameters\n", status);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
vf->spoofchk = ena;
- vsi->info.sec_flags = ctx.info.sec_flags;
- vsi->info.sw_flags2 = ctx.info.sw_flags2;
-
- return status;
+ vsi->info.sec_flags = ctx->info.sec_flags;
+ vsi->info.sw_flags2 = ctx->info.sw_flags2;
+out:
+ devm_kfree(&pf->pdev->dev, ctx);
+ return ret;
}
/**
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index fe1592ae8769..ca54e268d157 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -515,7 +515,7 @@ struct igb_adapter {
/* OS defined structs */
struct pci_dev *pdev;
- struct mutex stats64_lock;
+ spinlock_t stats64_lock;
struct rtnl_link_stats64 stats64;
/* structs defined in e1000_hw.h */
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 7426060b678f..c57671068245 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2295,7 +2295,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
int i, j;
char *p;
- mutex_lock(&adapter->stats64_lock);
+ spin_lock(&adapter->stats64_lock);
igb_update_stats(adapter);
for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
@@ -2338,7 +2338,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
} while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
i += IGB_RX_QUEUE_STATS_LEN;
}
- mutex_unlock(&adapter->stats64_lock);
+ spin_unlock(&adapter->stats64_lock);
}
static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 87bdf1604ae2..69b230c53fed 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -39,7 +39,7 @@
#include "igb.h"
#define MAJ 5
-#define MIN 4
+#define MIN 6
#define BUILD 0
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
@@ -1189,15 +1189,15 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
{
struct igb_q_vector *q_vector;
struct igb_ring *ring;
- int ring_count, size;
+ int ring_count;
+ size_t size;
/* igb only supports 1 Tx and/or 1 Rx queue per vector */
if (txr_count > 1 || rxr_count > 1)
return -ENOMEM;
ring_count = txr_count + rxr_count;
- size = sizeof(struct igb_q_vector) +
- (sizeof(struct igb_ring) * ring_count);
+ size = struct_size(q_vector, ring, ring_count);
/* allocate q_vector and rings */
q_vector = adapter->q_vector[v_idx];
@@ -2203,9 +2203,9 @@ void igb_down(struct igb_adapter *adapter)
del_timer_sync(&adapter->phy_info_timer);
/* record the stats before reset*/
- mutex_lock(&adapter->stats64_lock);
+ spin_lock(&adapter->stats64_lock);
igb_update_stats(adapter);
- mutex_unlock(&adapter->stats64_lock);
+ spin_unlock(&adapter->stats64_lock);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -2486,7 +2486,8 @@ static int igb_set_features(struct net_device *netdev,
static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags)
+ u16 flags,
+ struct netlink_ext_ack *extack)
{
/* guarantee we can provide a unique filter for the unicast address */
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
@@ -2580,9 +2581,11 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter,
int traffic_class,
struct igb_nfc_filter *input)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_dissector *dissector = rule->match.dissector;
struct netlink_ext_ack *extack = f->common.extack;
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -2592,78 +2595,60 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter,
return -EOPNOTSUPP;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key, *mask;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
-
- if (!is_zero_ether_addr(mask->dst)) {
- if (!is_broadcast_ether_addr(mask->dst)) {
+ flow_rule_match_eth_addrs(rule, &match);
+ if (!is_zero_ether_addr(match.mask->dst)) {
+ if (!is_broadcast_ether_addr(match.mask->dst)) {
NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for destination MAC address");
return -EINVAL;
}
input->filter.match_flags |=
IGB_FILTER_FLAG_DST_MAC_ADDR;
- ether_addr_copy(input->filter.dst_addr, key->dst);
+ ether_addr_copy(input->filter.dst_addr, match.key->dst);
}
- if (!is_zero_ether_addr(mask->src)) {
- if (!is_broadcast_ether_addr(mask->src)) {
+ if (!is_zero_ether_addr(match.mask->src)) {
+ if (!is_broadcast_ether_addr(match.mask->src)) {
NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for source MAC address");
return -EINVAL;
}
input->filter.match_flags |=
IGB_FILTER_FLAG_SRC_MAC_ADDR;
- ether_addr_copy(input->filter.src_addr, key->src);
+ ether_addr_copy(input->filter.src_addr, match.key->src);
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key, *mask;
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- if (mask->n_proto) {
- if (mask->n_proto != ETHER_TYPE_FULL_MASK) {
+ flow_rule_match_basic(rule, &match);
+ if (match.mask->n_proto) {
+ if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) {
NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for EtherType filter");
return -EINVAL;
}
input->filter.match_flags |= IGB_FILTER_FLAG_ETHER_TYPE;
- input->filter.etype = key->n_proto;
+ input->filter.etype = match.key->n_proto;
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key, *mask;
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
- if (mask->vlan_priority) {
- if (mask->vlan_priority != VLAN_PRIO_FULL_MASK) {
+ flow_rule_match_vlan(rule, &match);
+ if (match.mask->vlan_priority) {
+ if (match.mask->vlan_priority != VLAN_PRIO_FULL_MASK) {
NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN priority");
return -EINVAL;
}
input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI;
- input->filter.vlan_tci = key->vlan_priority;
+ input->filter.vlan_tci = match.key->vlan_priority;
}
}
@@ -3840,7 +3825,7 @@ static int igb_sw_init(struct igb_adapter *adapter)
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
spin_lock_init(&adapter->nfc_lock);
- mutex_init(&adapter->stats64_lock);
+ spin_lock_init(&adapter->stats64_lock);
#ifdef CONFIG_PCI_IOV
switch (hw->mac.type) {
case e1000_82576:
@@ -5406,9 +5391,9 @@ no_wait:
}
}
- mutex_lock(&adapter->stats64_lock);
+ spin_lock(&adapter->stats64_lock);
igb_update_stats(adapter);
- mutex_unlock(&adapter->stats64_lock);
+ spin_unlock(&adapter->stats64_lock);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -6235,10 +6220,10 @@ static void igb_get_stats64(struct net_device *netdev,
{
struct igb_adapter *adapter = netdev_priv(netdev);
- mutex_lock(&adapter->stats64_lock);
+ spin_lock(&adapter->stats64_lock);
igb_update_stats(adapter);
memcpy(stats, &adapter->stats64, sizeof(*stats));
- mutex_unlock(&adapter->stats64_lock);
+ spin_unlock(&adapter->stats64_lock);
}
/**
diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile
index 4387f6ba8e67..88c6f88baac5 100644
--- a/drivers/net/ethernet/intel/igc/Makefile
+++ b/drivers/net/ethernet/intel/igc/Makefile
@@ -7,4 +7,5 @@
obj-$(CONFIG_IGC) += igc.o
-igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o
+igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
+igc_ethtool.o
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index b1039dd3dd13..80faccc34cda 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -13,19 +13,43 @@
#include "igc_hw.h"
-/* main */
+/* forward declaration */
+void igc_set_ethtool_ops(struct net_device *);
+
+struct igc_adapter;
+struct igc_ring;
+
+void igc_up(struct igc_adapter *adapter);
+void igc_down(struct igc_adapter *adapter);
+int igc_setup_tx_resources(struct igc_ring *ring);
+int igc_setup_rx_resources(struct igc_ring *ring);
+void igc_free_tx_resources(struct igc_ring *ring);
+void igc_free_rx_resources(struct igc_ring *ring);
+unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
+void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
+ const u32 max_rss_queues);
+int igc_reinit_queues(struct igc_adapter *adapter);
+bool igc_has_link(struct igc_adapter *adapter);
+void igc_reset(struct igc_adapter *adapter);
+int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx);
+
extern char igc_driver_name[];
extern char igc_driver_version[];
+#define IGC_REGS_LEN 740
+#define IGC_RETA_SIZE 128
+
/* Interrupt defines */
#define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_FLAG_HAS_MSI BIT(0)
-#define IGC_FLAG_QUEUE_PAIRS BIT(4)
+#define IGC_FLAG_QUEUE_PAIRS BIT(3)
+#define IGC_FLAG_DMAC BIT(4)
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
#define IGC_FLAG_MEDIA_RESET BIT(10)
#define IGC_FLAG_MAS_ENABLE BIT(12)
#define IGC_FLAG_HAS_MSIX BIT(13)
#define IGC_FLAG_VLAN_PROMISC BIT(15)
+#define IGC_FLAG_RX_LEGACY BIT(16)
#define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_4K_ITR 980
@@ -60,6 +84,7 @@ extern char igc_driver_version[];
#define IGC_RXBUFFER_2048 2048
#define IGC_RXBUFFER_3072 3072
+#define AUTO_ALL_MODES 0
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256
/* RX and TX descriptor control thresholds.
@@ -340,6 +365,8 @@ struct igc_adapter {
struct igc_mac_addr *mac_table;
+ u8 rss_indir_tbl[IGC_RETA_SIZE];
+
unsigned long link_check_timeout;
struct igc_info ei;
};
@@ -418,6 +445,9 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
return 0;
}
+/* forward declaration */
+void igc_reinit_locked(struct igc_adapter *);
+
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)
diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c
index df40af759542..51a8b8769c67 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.c
+++ b/drivers/net/ethernet/intel/igc/igc_base.c
@@ -54,22 +54,6 @@ out:
}
/**
- * igc_check_for_link_base - Check for link
- * @hw: pointer to the HW structure
- *
- * If sgmii is enabled, then use the pcs register to determine link, otherwise
- * use the generic interface for determining link.
- */
-static s32 igc_check_for_link_base(struct igc_hw *hw)
-{
- s32 ret_val = 0;
-
- ret_val = igc_check_for_copper_link(hw);
-
- return ret_val;
-}
-
-/**
* igc_reset_hw_base - Reset hardware
* @hw: pointer to the HW structure
*
@@ -124,22 +108,6 @@ static s32 igc_reset_hw_base(struct igc_hw *hw)
}
/**
- * igc_get_phy_id_base - Retrieve PHY addr and id
- * @hw: pointer to the HW structure
- *
- * Retrieves the PHY address and ID for both PHY's which do and do not use
- * sgmi interface.
- */
-static s32 igc_get_phy_id_base(struct igc_hw *hw)
-{
- s32 ret_val = 0;
-
- ret_val = igc_get_phy_id(hw);
-
- return ret_val;
-}
-
-/**
* igc_init_nvm_params_base - Init NVM func ptrs.
* @hw: pointer to the HW structure
*/
@@ -163,6 +131,7 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw)
if (size > 15)
size = 15;
+ nvm->type = igc_nvm_eeprom_spi;
nvm->word_size = BIT(size);
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
@@ -261,11 +230,11 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw)
goto out;
}
- ret_val = igc_get_phy_id_base(hw);
+ ret_val = igc_get_phy_id(hw);
if (ret_val)
return ret_val;
- igc_check_for_link_base(hw);
+ igc_check_for_copper_link(hw);
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
@@ -350,26 +319,6 @@ static void igc_release_phy_base(struct igc_hw *hw)
}
/**
- * igc_get_link_up_info_base - Get link speed/duplex info
- * @hw: pointer to the HW structure
- * @speed: stores the current speed
- * @duplex: stores the current duplex
- *
- * This is a wrapper function, if using the serial gigabit media independent
- * interface, use PCS to retrieve the link speed and duplex information.
- * Otherwise, use the generic function to get the link speed and duplex info.
- */
-static s32 igc_get_link_up_info_base(struct igc_hw *hw, u16 *speed,
- u16 *duplex)
-{
- s32 ret_val;
-
- ret_val = igc_get_speed_and_duplex_copper(hw, speed, duplex);
-
- return ret_val;
-}
-
-/**
* igc_init_hw_base - Initialize hardware
* @hw: pointer to the HW structure
*
@@ -408,19 +357,6 @@ static s32 igc_init_hw_base(struct igc_hw *hw)
}
/**
- * igc_read_mac_addr_base - Read device MAC address
- * @hw: pointer to the HW structure
- */
-static s32 igc_read_mac_addr_base(struct igc_hw *hw)
-{
- s32 ret_val = 0;
-
- ret_val = igc_read_mac_addr(hw);
-
- return ret_val;
-}
-
-/**
* igc_power_down_phy_copper_base - Remove link during PHY power down
* @hw: pointer to the HW structure
*
@@ -512,10 +448,10 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw)
static struct igc_mac_operations igc_mac_ops_base = {
.init_hw = igc_init_hw_base,
- .check_for_link = igc_check_for_link_base,
+ .check_for_link = igc_check_for_copper_link,
.rar_set = igc_rar_set,
- .read_mac_addr = igc_read_mac_addr_base,
- .get_speed_and_duplex = igc_get_link_up_info_base,
+ .read_mac_addr = igc_read_mac_addr,
+ .get_speed_and_duplex = igc_get_speed_and_duplex_copper,
};
static const struct igc_phy_operations igc_phy_ops_base = {
diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h
index 35588fa7b8c5..76d4991d7284 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.h
+++ b/drivers/net/ethernet/intel/igc/igc_base.h
@@ -36,28 +36,6 @@ union igc_adv_tx_desc {
#define IGC_RAR_ENTRIES 16
-struct igc_adv_data_desc {
- __le64 buffer_addr; /* Address of the descriptor's data buffer */
- union {
- u32 data;
- struct {
- u32 datalen:16; /* Data buffer length */
- u32 rsvd:4;
- u32 dtyp:4; /* Descriptor type */
- u32 dcmd:8; /* Descriptor command */
- } config;
- } lower;
- union {
- u32 data;
- struct {
- u32 status:4; /* Descriptor status */
- u32 idx:4;
- u32 popts:6; /* Packet Options */
- u32 paylen:18; /* Payload length */
- } options;
- } upper;
-};
-
/* Receive Descriptor - Advanced */
union igc_adv_rx_desc {
struct {
@@ -90,9 +68,6 @@ union igc_adv_rx_desc {
} wb; /* writeback */
};
-/* Adv Transmit Descriptor Config Masks */
-#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
-
/* Additional Transmit Descriptor Control definitions */
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 8740754ea1fd..7d1bdcd1225a 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -4,6 +4,10 @@
#ifndef _IGC_DEFINES_H_
#define _IGC_DEFINES_H_
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE 8
+#define REQ_RX_DESCRIPTOR_MULTIPLE 8
+
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
/* PCI Bus Info */
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
new file mode 100644
index 000000000000..eff37a6c0afa
--- /dev/null
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -0,0 +1,1032 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Intel Corporation */
+
+/* ethtool support for igc */
+#include <linux/pm_runtime.h>
+
+#include "igc.h"
+
+static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = {
+#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0)
+ "legacy-rx",
+};
+
+#define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings)
+
+static void igc_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ strlcpy(drvinfo->driver, igc_driver_name, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, igc_driver_version, sizeof(drvinfo->version));
+
+ /* add fw_version here */
+ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+ sizeof(drvinfo->bus_info));
+
+ drvinfo->n_priv_flags = IGC_PRIV_FLAGS_STR_LEN;
+}
+
+static int igc_get_regs_len(struct net_device *netdev)
+{
+ return IGC_REGS_LEN * sizeof(u32);
+}
+
+static void igc_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ u32 *regs_buff = p;
+ u8 i;
+
+ memset(p, 0, IGC_REGS_LEN * sizeof(u32));
+
+ regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id;
+
+ /* General Registers */
+ regs_buff[0] = rd32(IGC_CTRL);
+ regs_buff[1] = rd32(IGC_STATUS);
+ regs_buff[2] = rd32(IGC_CTRL_EXT);
+ regs_buff[3] = rd32(IGC_MDIC);
+ regs_buff[4] = rd32(IGC_CONNSW);
+
+ /* NVM Register */
+ regs_buff[5] = rd32(IGC_EECD);
+
+ /* Interrupt */
+ /* Reading EICS for EICR because they read the
+ * same but EICS does not clear on read
+ */
+ regs_buff[6] = rd32(IGC_EICS);
+ regs_buff[7] = rd32(IGC_EICS);
+ regs_buff[8] = rd32(IGC_EIMS);
+ regs_buff[9] = rd32(IGC_EIMC);
+ regs_buff[10] = rd32(IGC_EIAC);
+ regs_buff[11] = rd32(IGC_EIAM);
+ /* Reading ICS for ICR because they read the
+ * same but ICS does not clear on read
+ */
+ regs_buff[12] = rd32(IGC_ICS);
+ regs_buff[13] = rd32(IGC_ICS);
+ regs_buff[14] = rd32(IGC_IMS);
+ regs_buff[15] = rd32(IGC_IMC);
+ regs_buff[16] = rd32(IGC_IAC);
+ regs_buff[17] = rd32(IGC_IAM);
+
+ /* Flow Control */
+ regs_buff[18] = rd32(IGC_FCAL);
+ regs_buff[19] = rd32(IGC_FCAH);
+ regs_buff[20] = rd32(IGC_FCTTV);
+ regs_buff[21] = rd32(IGC_FCRTL);
+ regs_buff[22] = rd32(IGC_FCRTH);
+ regs_buff[23] = rd32(IGC_FCRTV);
+
+ /* Receive */
+ regs_buff[24] = rd32(IGC_RCTL);
+ regs_buff[25] = rd32(IGC_RXCSUM);
+ regs_buff[26] = rd32(IGC_RLPML);
+ regs_buff[27] = rd32(IGC_RFCTL);
+
+ /* Transmit */
+ regs_buff[28] = rd32(IGC_TCTL);
+ regs_buff[29] = rd32(IGC_TIPG);
+
+ /* Wake Up */
+
+ /* MAC */
+
+ /* Statistics */
+ regs_buff[30] = adapter->stats.crcerrs;
+ regs_buff[31] = adapter->stats.algnerrc;
+ regs_buff[32] = adapter->stats.symerrs;
+ regs_buff[33] = adapter->stats.rxerrc;
+ regs_buff[34] = adapter->stats.mpc;
+ regs_buff[35] = adapter->stats.scc;
+ regs_buff[36] = adapter->stats.ecol;
+ regs_buff[37] = adapter->stats.mcc;
+ regs_buff[38] = adapter->stats.latecol;
+ regs_buff[39] = adapter->stats.colc;
+ regs_buff[40] = adapter->stats.dc;
+ regs_buff[41] = adapter->stats.tncrs;
+ regs_buff[42] = adapter->stats.sec;
+ regs_buff[43] = adapter->stats.htdpmc;
+ regs_buff[44] = adapter->stats.rlec;
+ regs_buff[45] = adapter->stats.xonrxc;
+ regs_buff[46] = adapter->stats.xontxc;
+ regs_buff[47] = adapter->stats.xoffrxc;
+ regs_buff[48] = adapter->stats.xofftxc;
+ regs_buff[49] = adapter->stats.fcruc;
+ regs_buff[50] = adapter->stats.prc64;
+ regs_buff[51] = adapter->stats.prc127;
+ regs_buff[52] = adapter->stats.prc255;
+ regs_buff[53] = adapter->stats.prc511;
+ regs_buff[54] = adapter->stats.prc1023;
+ regs_buff[55] = adapter->stats.prc1522;
+ regs_buff[56] = adapter->stats.gprc;
+ regs_buff[57] = adapter->stats.bprc;
+ regs_buff[58] = adapter->stats.mprc;
+ regs_buff[59] = adapter->stats.gptc;
+ regs_buff[60] = adapter->stats.gorc;
+ regs_buff[61] = adapter->stats.gotc;
+ regs_buff[62] = adapter->stats.rnbc;
+ regs_buff[63] = adapter->stats.ruc;
+ regs_buff[64] = adapter->stats.rfc;
+ regs_buff[65] = adapter->stats.roc;
+ regs_buff[66] = adapter->stats.rjc;
+ regs_buff[67] = adapter->stats.mgprc;
+ regs_buff[68] = adapter->stats.mgpdc;
+ regs_buff[69] = adapter->stats.mgptc;
+ regs_buff[70] = adapter->stats.tor;
+ regs_buff[71] = adapter->stats.tot;
+ regs_buff[72] = adapter->stats.tpr;
+ regs_buff[73] = adapter->stats.tpt;
+ regs_buff[74] = adapter->stats.ptc64;
+ regs_buff[75] = adapter->stats.ptc127;
+ regs_buff[76] = adapter->stats.ptc255;
+ regs_buff[77] = adapter->stats.ptc511;
+ regs_buff[78] = adapter->stats.ptc1023;
+ regs_buff[79] = adapter->stats.ptc1522;
+ regs_buff[80] = adapter->stats.mptc;
+ regs_buff[81] = adapter->stats.bptc;
+ regs_buff[82] = adapter->stats.tsctc;
+ regs_buff[83] = adapter->stats.iac;
+ regs_buff[84] = adapter->stats.rpthc;
+ regs_buff[85] = adapter->stats.hgptc;
+ regs_buff[86] = adapter->stats.hgorc;
+ regs_buff[87] = adapter->stats.hgotc;
+ regs_buff[88] = adapter->stats.lenerrs;
+ regs_buff[89] = adapter->stats.scvpc;
+ regs_buff[90] = adapter->stats.hrmpc;
+
+ for (i = 0; i < 4; i++)
+ regs_buff[91 + i] = rd32(IGC_SRRCTL(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[95 + i] = rd32(IGC_PSRTYPE(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[99 + i] = rd32(IGC_RDBAL(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[103 + i] = rd32(IGC_RDBAH(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[107 + i] = rd32(IGC_RDLEN(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[111 + i] = rd32(IGC_RDH(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[115 + i] = rd32(IGC_RDT(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[119 + i] = rd32(IGC_RXDCTL(i));
+
+ for (i = 0; i < 10; i++)
+ regs_buff[123 + i] = rd32(IGC_EITR(i));
+ for (i = 0; i < 16; i++)
+ regs_buff[139 + i] = rd32(IGC_RAL(i));
+ for (i = 0; i < 16; i++)
+ regs_buff[145 + i] = rd32(IGC_RAH(i));
+
+ for (i = 0; i < 4; i++)
+ regs_buff[149 + i] = rd32(IGC_TDBAL(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[152 + i] = rd32(IGC_TDBAH(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[156 + i] = rd32(IGC_TDLEN(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[160 + i] = rd32(IGC_TDH(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[164 + i] = rd32(IGC_TDT(i));
+ for (i = 0; i < 4; i++)
+ regs_buff[168 + i] = rd32(IGC_TXDCTL(i));
+}
+
+static u32 igc_get_msglevel(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->msg_enable;
+}
+
+static void igc_set_msglevel(struct net_device *netdev, u32 data)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ adapter->msg_enable = data;
+}
+
+static int igc_nway_reset(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ if (netif_running(netdev))
+ igc_reinit_locked(adapter);
+ return 0;
+}
+
+static u32 igc_get_link(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_mac_info *mac = &adapter->hw.mac;
+
+ /* If the link is not reported up to netdev, interrupts are disabled,
+ * and so the physical link state may have changed since we last
+ * looked. Set get_link_status to make sure that the true link
+ * state is interrogated, rather than pulling a cached and possibly
+ * stale link state from the driver.
+ */
+ if (!netif_carrier_ok(netdev))
+ mac->get_link_status = 1;
+
+ return igc_has_link(adapter);
+}
+
+static int igc_get_eeprom_len(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->hw.nvm.word_size * 2;
+}
+
+static int igc_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ int first_word, last_word;
+ u16 *eeprom_buff;
+ int ret_val = 0;
+ u16 i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+
+ if (hw->nvm.type == igc_nvm_eeprom_spi) {
+ ret_val = hw->nvm.ops.read(hw, first_word,
+ last_word - first_word + 1,
+ eeprom_buff);
+ } else {
+ for (i = 0; i < last_word - first_word + 1; i++) {
+ ret_val = hw->nvm.ops.read(hw, first_word + i, 1,
+ &eeprom_buff[i]);
+ if (ret_val)
+ break;
+ }
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+
+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+ return ret_val;
+}
+
+static int igc_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ int max_len, first_word, last_word, ret_val = 0;
+ u16 *eeprom_buff;
+ void *ptr;
+ u16 i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+
+ if (hw->mac.type >= igc_i225 &&
+ !igc_get_flash_presence_i225(hw)) {
+ return -EOPNOTSUPP;
+ }
+
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ return -EFAULT;
+
+ max_len = hw->nvm.word_size * 2;
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+ eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+
+ ptr = (void *)eeprom_buff;
+
+ if (eeprom->offset & 1) {
+ /* need read/modify/write of first changed EEPROM word
+ * only the second byte of the word is being modified
+ */
+ ret_val = hw->nvm.ops.read(hw, first_word, 1,
+ &eeprom_buff[0]);
+ ptr++;
+ }
+ if (((eeprom->offset + eeprom->len) & 1) && ret_val == 0) {
+ /* need read/modify/write of last changed EEPROM word
+ * only the first byte of the word is being modified
+ */
+ ret_val = hw->nvm.ops.read(hw, last_word, 1,
+ &eeprom_buff[last_word - first_word]);
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+
+ memcpy(ptr, bytes, eeprom->len);
+
+ for (i = 0; i < last_word - first_word + 1; i++)
+ eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
+
+ ret_val = hw->nvm.ops.write(hw, first_word,
+ last_word - first_word + 1, eeprom_buff);
+
+ /* Update the checksum if nvm write succeeded */
+ if (ret_val == 0)
+ hw->nvm.ops.update(hw);
+
+ /* check if need: igc_set_fw_version(adapter); */
+ kfree(eeprom_buff);
+ return ret_val;
+}
+
+static void igc_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ ring->rx_max_pending = IGC_MAX_RXD;
+ ring->tx_max_pending = IGC_MAX_TXD;
+ ring->rx_pending = adapter->rx_ring_count;
+ ring->tx_pending = adapter->tx_ring_count;
+}
+
+static int igc_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_ring *temp_ring;
+ u16 new_rx_count, new_tx_count;
+ int i, err = 0;
+
+ if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+ return -EINVAL;
+
+ new_rx_count = min_t(u32, ring->rx_pending, IGC_MAX_RXD);
+ new_rx_count = max_t(u16, new_rx_count, IGC_MIN_RXD);
+ new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
+
+ new_tx_count = min_t(u32, ring->tx_pending, IGC_MAX_TXD);
+ new_tx_count = max_t(u16, new_tx_count, IGC_MIN_TXD);
+ new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
+
+ if (new_tx_count == adapter->tx_ring_count &&
+ new_rx_count == adapter->rx_ring_count) {
+ /* nothing to do */
+ return 0;
+ }
+
+ while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
+ usleep_range(1000, 2000);
+
+ if (!netif_running(adapter->netdev)) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i]->count = new_tx_count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i]->count = new_rx_count;
+ adapter->tx_ring_count = new_tx_count;
+ adapter->rx_ring_count = new_rx_count;
+ goto clear_reset;
+ }
+
+ if (adapter->num_tx_queues > adapter->num_rx_queues)
+ temp_ring = vmalloc(array_size(sizeof(struct igc_ring),
+ adapter->num_tx_queues));
+ else
+ temp_ring = vmalloc(array_size(sizeof(struct igc_ring),
+ adapter->num_rx_queues));
+
+ if (!temp_ring) {
+ err = -ENOMEM;
+ goto clear_reset;
+ }
+
+ igc_down(adapter);
+
+ /* We can't just free everything and then setup again,
+ * because the ISRs in MSI-X mode get passed pointers
+ * to the Tx and Rx ring structs.
+ */
+ if (new_tx_count != adapter->tx_ring_count) {
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ memcpy(&temp_ring[i], adapter->tx_ring[i],
+ sizeof(struct igc_ring));
+
+ temp_ring[i].count = new_tx_count;
+ err = igc_setup_tx_resources(&temp_ring[i]);
+ if (err) {
+ while (i) {
+ i--;
+ igc_free_tx_resources(&temp_ring[i]);
+ }
+ goto err_setup;
+ }
+ }
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ igc_free_tx_resources(adapter->tx_ring[i]);
+
+ memcpy(adapter->tx_ring[i], &temp_ring[i],
+ sizeof(struct igc_ring));
+ }
+
+ adapter->tx_ring_count = new_tx_count;
+ }
+
+ if (new_rx_count != adapter->rx_ring_count) {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ memcpy(&temp_ring[i], adapter->rx_ring[i],
+ sizeof(struct igc_ring));
+
+ temp_ring[i].count = new_rx_count;
+ err = igc_setup_rx_resources(&temp_ring[i]);
+ if (err) {
+ while (i) {
+ i--;
+ igc_free_rx_resources(&temp_ring[i]);
+ }
+ goto err_setup;
+ }
+ }
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ igc_free_rx_resources(adapter->rx_ring[i]);
+
+ memcpy(adapter->rx_ring[i], &temp_ring[i],
+ sizeof(struct igc_ring));
+ }
+
+ adapter->rx_ring_count = new_rx_count;
+ }
+err_setup:
+ igc_up(adapter);
+ vfree(temp_ring);
+clear_reset:
+ clear_bit(__IGC_RESETTING, &adapter->state);
+ return err;
+}
+
+static void igc_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+
+ pause->autoneg =
+ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+ if (hw->fc.current_mode == igc_fc_rx_pause) {
+ pause->rx_pause = 1;
+ } else if (hw->fc.current_mode == igc_fc_tx_pause) {
+ pause->tx_pause = 1;
+ } else if (hw->fc.current_mode == igc_fc_full) {
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
+ }
+}
+
+static int igc_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ int retval = 0;
+
+ adapter->fc_autoneg = pause->autoneg;
+
+ while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
+ usleep_range(1000, 2000);
+
+ if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+ hw->fc.requested_mode = igc_fc_default;
+ if (netif_running(adapter->netdev)) {
+ igc_down(adapter);
+ igc_up(adapter);
+ } else {
+ igc_reset(adapter);
+ }
+ } else {
+ if (pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = igc_fc_full;
+ else if (pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = igc_fc_rx_pause;
+ else if (!pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = igc_fc_tx_pause;
+ else if (!pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = igc_fc_none;
+
+ hw->fc.current_mode = hw->fc.requested_mode;
+
+ retval = ((hw->phy.media_type == igc_media_type_copper) ?
+ igc_force_mac_fc(hw) : igc_setup_link(hw));
+ }
+
+ clear_bit(__IGC_RESETTING, &adapter->state);
+ return retval;
+}
+
+static int igc_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ if (adapter->rx_itr_setting <= 3)
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting;
+ else
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2;
+
+ if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS)) {
+ if (adapter->tx_itr_setting <= 3)
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting;
+ else
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2;
+ }
+
+ return 0;
+}
+
+static int igc_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ if (ec->rx_max_coalesced_frames ||
+ ec->rx_coalesce_usecs_irq ||
+ ec->rx_max_coalesced_frames_irq ||
+ ec->tx_max_coalesced_frames ||
+ ec->tx_coalesce_usecs_irq ||
+ ec->stats_block_coalesce_usecs ||
+ ec->use_adaptive_rx_coalesce ||
+ ec->use_adaptive_tx_coalesce ||
+ ec->pkt_rate_low ||
+ ec->rx_coalesce_usecs_low ||
+ ec->rx_max_coalesced_frames_low ||
+ ec->tx_coalesce_usecs_low ||
+ ec->tx_max_coalesced_frames_low ||
+ ec->pkt_rate_high ||
+ ec->rx_coalesce_usecs_high ||
+ ec->rx_max_coalesced_frames_high ||
+ ec->tx_coalesce_usecs_high ||
+ ec->tx_max_coalesced_frames_high ||
+ ec->rate_sample_interval)
+ return -ENOTSUPP;
+
+ if (ec->rx_coalesce_usecs > IGC_MAX_ITR_USECS ||
+ (ec->rx_coalesce_usecs > 3 &&
+ ec->rx_coalesce_usecs < IGC_MIN_ITR_USECS) ||
+ ec->rx_coalesce_usecs == 2)
+ return -EINVAL;
+
+ if (ec->tx_coalesce_usecs > IGC_MAX_ITR_USECS ||
+ (ec->tx_coalesce_usecs > 3 &&
+ ec->tx_coalesce_usecs < IGC_MIN_ITR_USECS) ||
+ ec->tx_coalesce_usecs == 2)
+ return -EINVAL;
+
+ if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
+ return -EINVAL;
+
+ /* If ITR is disabled, disable DMAC */
+ if (ec->rx_coalesce_usecs == 0) {
+ if (adapter->flags & IGC_FLAG_DMAC)
+ adapter->flags &= ~IGC_FLAG_DMAC;
+ }
+
+ /* convert to rate of irq's per second */
+ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs;
+ else
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2;
+
+ /* convert to rate of irq's per second */
+ if (adapter->flags & IGC_FLAG_QUEUE_PAIRS)
+ adapter->tx_itr_setting = adapter->rx_itr_setting;
+ else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3)
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs;
+ else
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2;
+
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igc_q_vector *q_vector = adapter->q_vector[i];
+
+ q_vector->tx.work_limit = adapter->tx_work_limit;
+ if (q_vector->rx.ring)
+ q_vector->itr_val = adapter->rx_itr_setting;
+ else
+ q_vector->itr_val = adapter->tx_itr_setting;
+ if (q_vector->itr_val && q_vector->itr_val <= 3)
+ q_vector->itr_val = IGC_START_ITR;
+ q_vector->set_itr = 1;
+ }
+
+ return 0;
+}
+
+void igc_write_rss_indir_tbl(struct igc_adapter *adapter)
+{
+ struct igc_hw *hw = &adapter->hw;
+ u32 reg = IGC_RETA(0);
+ u32 shift = 0;
+ int i = 0;
+
+ while (i < IGC_RETA_SIZE) {
+ u32 val = 0;
+ int j;
+
+ for (j = 3; j >= 0; j--) {
+ val <<= 8;
+ val |= adapter->rss_indir_tbl[i + j];
+ }
+
+ wr32(reg, val << shift);
+ reg += 4;
+ i += 4;
+ }
+}
+
+static u32 igc_get_rxfh_indir_size(struct net_device *netdev)
+{
+ return IGC_RETA_SIZE;
+}
+
+static int igc_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+ if (!indir)
+ return 0;
+ for (i = 0; i < IGC_RETA_SIZE; i++)
+ indir[i] = adapter->rss_indir_tbl[i];
+
+ return 0;
+}
+
+static int igc_set_rxfh(struct net_device *netdev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ u32 num_queues;
+ int i;
+
+ /* We do not allow change in unsupported parameters */
+ if (key ||
+ (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
+ return -EOPNOTSUPP;
+ if (!indir)
+ return 0;
+
+ num_queues = adapter->rss_queues;
+
+ /* Verify user input. */
+ for (i = 0; i < IGC_RETA_SIZE; i++)
+ if (indir[i] >= num_queues)
+ return -EINVAL;
+
+ for (i = 0; i < IGC_RETA_SIZE; i++)
+ adapter->rss_indir_tbl[i] = indir[i];
+
+ igc_write_rss_indir_tbl(adapter);
+
+ return 0;
+}
+
+static unsigned int igc_max_channels(struct igc_adapter *adapter)
+{
+ return igc_get_max_rss_queues(adapter);
+}
+
+static void igc_get_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ /* Report maximum channels */
+ ch->max_combined = igc_max_channels(adapter);
+
+ /* Report info for other vector */
+ if (adapter->flags & IGC_FLAG_HAS_MSIX) {
+ ch->max_other = NON_Q_VECTORS;
+ ch->other_count = NON_Q_VECTORS;
+ }
+
+ ch->combined_count = adapter->rss_queues;
+}
+
+static int igc_set_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ unsigned int count = ch->combined_count;
+ unsigned int max_combined = 0;
+
+ /* Verify they are not requesting separate vectors */
+ if (!count || ch->rx_count || ch->tx_count)
+ return -EINVAL;
+
+ /* Verify other_count is valid and has not been changed */
+ if (ch->other_count != NON_Q_VECTORS)
+ return -EINVAL;
+
+ /* Verify the number of channels doesn't exceed hw limits */
+ max_combined = igc_max_channels(adapter);
+ if (count > max_combined)
+ return -EINVAL;
+
+ if (count != adapter->rss_queues) {
+ adapter->rss_queues = count;
+ igc_set_flag_queue_pairs(adapter, max_combined);
+
+ /* Hardware has to reinitialize queues and interrupts to
+ * match the new configuration.
+ */
+ return igc_reinit_queues(adapter);
+ }
+
+ return 0;
+}
+
+static u32 igc_get_priv_flags(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ u32 priv_flags = 0;
+
+ if (adapter->flags & IGC_FLAG_RX_LEGACY)
+ priv_flags |= IGC_PRIV_FLAGS_LEGACY_RX;
+
+ return priv_flags;
+}
+
+static int igc_set_priv_flags(struct net_device *netdev, u32 priv_flags)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ unsigned int flags = adapter->flags;
+
+ flags &= ~IGC_FLAG_RX_LEGACY;
+ if (priv_flags & IGC_PRIV_FLAGS_LEGACY_RX)
+ flags |= IGC_FLAG_RX_LEGACY;
+
+ if (flags != adapter->flags) {
+ adapter->flags = flags;
+
+ /* reset interface to repopulate queues */
+ if (netif_running(netdev))
+ igc_reinit_locked(adapter);
+ }
+
+ return 0;
+}
+
+static int igc_ethtool_begin(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ pm_runtime_get_sync(&adapter->pdev->dev);
+ return 0;
+}
+
+static void igc_ethtool_complete(struct net_device *netdev)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+
+ pm_runtime_put(&adapter->pdev->dev);
+}
+
+static int igc_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ u32 status;
+ u32 speed;
+
+ ethtool_link_ksettings_zero_link_mode(cmd, supported);
+ ethtool_link_ksettings_zero_link_mode(cmd, advertising);
+
+ /* supported link modes */
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, 2500baseT_Full);
+
+ /* twisted pair */
+ cmd->base.port = PORT_TP;
+ cmd->base.phy_address = hw->phy.addr;
+
+ /* advertising link modes */
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full);
+
+ /* set autoneg settings */
+ if (hw->mac.autoneg == 1) {
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ Autoneg);
+ }
+
+ switch (hw->fc.requested_mode) {
+ case igc_fc_full:
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
+ break;
+ case igc_fc_rx_pause:
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ Asym_Pause);
+ break;
+ case igc_fc_tx_pause:
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ Asym_Pause);
+ break;
+ default:
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ Asym_Pause);
+ }
+
+ status = rd32(IGC_STATUS);
+
+ if (status & IGC_STATUS_LU) {
+ if (status & IGC_STATUS_SPEED_1000) {
+ /* For I225, STATUS will indicate 1G speed in both
+ * 1 Gbps and 2.5 Gbps link modes.
+ * An additional bit is used
+ * to differentiate between 1 Gbps and 2.5 Gbps.
+ */
+ if (hw->mac.type == igc_i225 &&
+ (status & IGC_STATUS_SPEED_2500)) {
+ speed = SPEED_2500;
+ hw_dbg("2500 Mbs, ");
+ } else {
+ speed = SPEED_1000;
+ hw_dbg("1000 Mbs, ");
+ }
+ } else if (status & IGC_STATUS_SPEED_100) {
+ speed = SPEED_100;
+ hw_dbg("100 Mbs, ");
+ } else {
+ speed = SPEED_10;
+ hw_dbg("10 Mbs, ");
+ }
+ if ((status & IGC_STATUS_FD) ||
+ hw->phy.media_type != igc_media_type_copper)
+ cmd->base.duplex = DUPLEX_FULL;
+ else
+ cmd->base.duplex = DUPLEX_HALF;
+ } else {
+ speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ }
+ cmd->base.speed = speed;
+ if (hw->mac.autoneg)
+ cmd->base.autoneg = AUTONEG_ENABLE;
+ else
+ cmd->base.autoneg = AUTONEG_DISABLE;
+
+ /* MDI-X => 2; MDI =>1; Invalid =>0 */
+ if (hw->phy.media_type == igc_media_type_copper)
+ cmd->base.eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
+ ETH_TP_MDI;
+ else
+ cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
+
+ if (hw->phy.mdix == AUTO_ALL_MODES)
+ cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
+ else
+ cmd->base.eth_tp_mdix_ctrl = hw->phy.mdix;
+
+ return 0;
+}
+
+static int igc_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ struct igc_hw *hw = &adapter->hw;
+ u32 advertising;
+
+ /* When adapter in resetting mode, autoneg/speed/duplex
+ * cannot be changed
+ */
+ if (igc_check_reset_block(hw)) {
+ dev_err(&adapter->pdev->dev,
+ "Cannot change link characteristics when reset is active.\n");
+ return -EINVAL;
+ }
+
+ /* MDI setting is only allowed when autoneg enabled because
+ * some hardware doesn't allow MDI setting when speed or
+ * duplex is forced.
+ */
+ if (cmd->base.eth_tp_mdix_ctrl) {
+ if (cmd->base.eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO &&
+ cmd->base.autoneg != AUTONEG_ENABLE) {
+ dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
+ return -EINVAL;
+ }
+ }
+
+ while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
+ usleep_range(1000, 2000);
+
+ ethtool_convert_link_mode_to_legacy_u32(&advertising,
+ cmd->link_modes.advertising);
+
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
+ hw->mac.autoneg = 1;
+ hw->phy.autoneg_advertised = advertising;
+ if (adapter->fc_autoneg)
+ hw->fc.requested_mode = igc_fc_default;
+ } else {
+ /* calling this overrides forced MDI setting */
+ dev_info(&adapter->pdev->dev,
+ "Force mode currently not supported\n");
+ }
+
+ /* MDI-X => 2; MDI => 1; Auto => 3 */
+ if (cmd->base.eth_tp_mdix_ctrl) {
+ /* fix up the value for auto (3 => 0) as zero is mapped
+ * internally to auto
+ */
+ if (cmd->base.eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
+ hw->phy.mdix = AUTO_ALL_MODES;
+ else
+ hw->phy.mdix = cmd->base.eth_tp_mdix_ctrl;
+ }
+
+ /* reset the link */
+ if (netif_running(adapter->netdev)) {
+ igc_down(adapter);
+ igc_up(adapter);
+ } else {
+ igc_reset(adapter);
+ }
+
+ clear_bit(__IGC_RESETTING, &adapter->state);
+
+ return 0;
+}
+
+static const struct ethtool_ops igc_ethtool_ops = {
+ .get_drvinfo = igc_get_drvinfo,
+ .get_regs_len = igc_get_regs_len,
+ .get_regs = igc_get_regs,
+ .get_msglevel = igc_get_msglevel,
+ .set_msglevel = igc_set_msglevel,
+ .nway_reset = igc_nway_reset,
+ .get_link = igc_get_link,
+ .get_eeprom_len = igc_get_eeprom_len,
+ .get_eeprom = igc_get_eeprom,
+ .set_eeprom = igc_set_eeprom,
+ .get_ringparam = igc_get_ringparam,
+ .set_ringparam = igc_set_ringparam,
+ .get_pauseparam = igc_get_pauseparam,
+ .set_pauseparam = igc_set_pauseparam,
+ .get_coalesce = igc_get_coalesce,
+ .set_coalesce = igc_set_coalesce,
+ .get_rxfh_indir_size = igc_get_rxfh_indir_size,
+ .get_rxfh = igc_get_rxfh,
+ .set_rxfh = igc_set_rxfh,
+ .get_channels = igc_get_channels,
+ .set_channels = igc_set_channels,
+ .get_priv_flags = igc_get_priv_flags,
+ .set_priv_flags = igc_set_priv_flags,
+ .begin = igc_ethtool_begin,
+ .complete = igc_ethtool_complete,
+ .get_link_ksettings = igc_get_link_ksettings,
+ .set_link_ksettings = igc_set_link_ksettings,
+};
+
+void igc_set_ethtool_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &igc_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h
index c50414f48f0d..7c88b7bd4799 100644
--- a/drivers/net/ethernet/intel/igc/igc_hw.h
+++ b/drivers/net/ethernet/intel/igc/igc_hw.h
@@ -55,6 +55,7 @@ enum igc_media_type {
enum igc_nvm_type {
igc_nvm_unknown = 0,
+ igc_nvm_eeprom_spi,
igc_nvm_flash_hw,
igc_nvm_invm,
};
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index f20183037fb2..87a11879bf2d 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -12,6 +12,8 @@
#define DRV_VERSION "0.0.1-k"
#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver"
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
static int debug = -1;
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -66,7 +68,7 @@ enum latency_range {
latency_invalid = 255
};
-static void igc_reset(struct igc_adapter *adapter)
+void igc_reset(struct igc_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct igc_hw *hw = &adapter->hw;
@@ -150,7 +152,7 @@ static void igc_get_hw_control(struct igc_adapter *adapter)
*
* Free all transmit software resources
*/
-static void igc_free_tx_resources(struct igc_ring *tx_ring)
+void igc_free_tx_resources(struct igc_ring *tx_ring)
{
igc_clean_tx_ring(tx_ring);
@@ -261,7 +263,7 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter)
*
* Return 0 on success, negative on failure
*/
-static int igc_setup_tx_resources(struct igc_ring *tx_ring)
+int igc_setup_tx_resources(struct igc_ring *tx_ring)
{
struct device *dev = tx_ring->dev;
int size = 0;
@@ -381,7 +383,7 @@ static void igc_clean_all_rx_rings(struct igc_adapter *adapter)
*
* Free all receive software resources
*/
-static void igc_free_rx_resources(struct igc_ring *rx_ring)
+void igc_free_rx_resources(struct igc_ring *rx_ring)
{
igc_clean_rx_ring(rx_ring);
@@ -418,7 +420,7 @@ static void igc_free_all_rx_resources(struct igc_adapter *adapter)
*
* Returns 0 on success, negative on failure
*/
-static int igc_setup_rx_resources(struct igc_ring *rx_ring)
+int igc_setup_rx_resources(struct igc_ring *rx_ring)
{
struct device *dev = rx_ring->dev;
int size, desc_len;
@@ -1703,7 +1705,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
* igc_up - Open the interface and prepare it to handle traffic
* @adapter: board private structure
*/
-static void igc_up(struct igc_adapter *adapter)
+void igc_up(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
int i = 0;
@@ -1748,7 +1750,7 @@ static void igc_nfc_filter_exit(struct igc_adapter *adapter)
* igc_down - Close the interface
* @adapter: board private structure
*/
-static void igc_down(struct igc_adapter *adapter)
+void igc_down(struct igc_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct igc_hw *hw = &adapter->hw;
@@ -1810,7 +1812,7 @@ static void igc_down(struct igc_adapter *adapter)
igc_clean_all_rx_rings(adapter);
}
-static void igc_reinit_locked(struct igc_adapter *adapter)
+void igc_reinit_locked(struct igc_adapter *adapter)
{
WARN_ON(in_interrupt());
while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
@@ -1922,7 +1924,7 @@ static void igc_configure(struct igc_adapter *adapter)
/**
* igc_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table
- * @adapter: Pointer to adapter structure
+ * @adapter: address of board private structure
* @index: Index of the RAR entry which need to be synced with MAC table
*/
static void igc_rar_set_index(struct igc_adapter *adapter, u32 index)
@@ -2298,7 +2300,7 @@ static void igc_update_phy_info(struct timer_list *t)
* igc_has_link - check shared code for link and determine up/down
* @adapter: pointer to driver private info
*/
-static bool igc_has_link(struct igc_adapter *adapter)
+bool igc_has_link(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
bool link_active = false;
@@ -2956,22 +2958,21 @@ static int igc_alloc_q_vector(struct igc_adapter *adapter,
{
struct igc_q_vector *q_vector;
struct igc_ring *ring;
- int ring_count, size;
+ int ring_count;
/* igc only supports 1 Tx and/or 1 Rx queue per vector */
if (txr_count > 1 || rxr_count > 1)
return -ENOMEM;
ring_count = txr_count + rxr_count;
- size = sizeof(struct igc_q_vector) +
- (sizeof(struct igc_ring) * ring_count);
/* allocate q_vector and rings */
q_vector = adapter->q_vector[v_idx];
if (!q_vector)
- q_vector = kzalloc(size, GFP_KERNEL);
+ q_vector = kzalloc(struct_size(q_vector, ring, ring_count),
+ GFP_KERNEL);
else
- memset(q_vector, 0, size);
+ memset(q_vector, 0, struct_size(q_vector, ring, ring_count));
if (!q_vector)
return -ENOMEM;
@@ -3501,6 +3502,57 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
return value;
}
+int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct igc_mac_info *mac = &adapter->hw.mac;
+
+ mac->autoneg = 0;
+
+ /* Make sure dplx is at most 1 bit and lsb of speed is not set
+ * for the switch() below to work
+ */
+ if ((spd & 1) || (dplx & ~1))
+ goto err_inval;
+
+ switch (spd + dplx) {
+ case SPEED_10 + DUPLEX_HALF:
+ mac->forced_speed_duplex = ADVERTISE_10_HALF;
+ break;
+ case SPEED_10 + DUPLEX_FULL:
+ mac->forced_speed_duplex = ADVERTISE_10_FULL;
+ break;
+ case SPEED_100 + DUPLEX_HALF:
+ mac->forced_speed_duplex = ADVERTISE_100_HALF;
+ break;
+ case SPEED_100 + DUPLEX_FULL:
+ mac->forced_speed_duplex = ADVERTISE_100_FULL;
+ break;
+ case SPEED_1000 + DUPLEX_FULL:
+ mac->autoneg = 1;
+ adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
+ break;
+ case SPEED_1000 + DUPLEX_HALF: /* not supported */
+ goto err_inval;
+ case SPEED_2500 + DUPLEX_FULL:
+ mac->autoneg = 1;
+ adapter->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL;
+ break;
+ case SPEED_2500 + DUPLEX_HALF: /* not supported */
+ default:
+ goto err_inval;
+ }
+
+ /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */
+ adapter->hw.phy.mdix = AUTO_ALL_MODES;
+
+ return 0;
+
+err_inval:
+ dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n");
+ return -EINVAL;
+}
+
/**
* igc_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -3568,7 +3620,7 @@ static int igc_probe(struct pci_dev *pdev,
hw = &adapter->hw;
hw->back = adapter;
adapter->port_num = hw->bus.func;
- adapter->msg_enable = GENMASK(debug - 1, 0);
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
err = pci_save_state(pdev);
if (err)
@@ -3584,7 +3636,7 @@ static int igc_probe(struct pci_dev *pdev,
hw->hw_addr = adapter->io_addr;
netdev->netdev_ops = &igc_netdev_ops;
-
+ igc_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
netdev->mem_start = pci_resource_start(pdev, 0);
@@ -3744,8 +3796,8 @@ static struct pci_driver igc_driver = {
.remove = igc_remove,
};
-static void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
- const u32 max_rss_queues)
+void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
+ const u32 max_rss_queues)
{
/* Determine if we need to pair queues. */
/* If rss_queues > half of max_rss_queues, pair the queues in
@@ -3757,7 +3809,7 @@ static void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS;
}
-static unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter)
+unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter)
{
unsigned int max_rss_queues;
@@ -3837,6 +3889,32 @@ static int igc_sw_init(struct igc_adapter *adapter)
}
/**
+ * igc_reinit_queues - return error
+ * @adapter: pointer to adapter structure
+ */
+int igc_reinit_queues(struct igc_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ int err = 0;
+
+ if (netif_running(netdev))
+ igc_close(netdev);
+
+ igc_reset_interrupt_capability(adapter);
+
+ if (igc_init_interrupt_scheme(adapter, true)) {
+ dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+ if (netif_running(netdev))
+ err = igc_open(netdev);
+
+ return err;
+}
+
+/**
* igc_get_hw_dev - return device
* @hw: pointer to hardware structure
*
diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c
index 38e43e6fc1c7..4c8f96a9a148 100644
--- a/drivers/net/ethernet/intel/igc/igc_phy.c
+++ b/drivers/net/ethernet/intel/igc/igc_phy.c
@@ -152,7 +152,6 @@ void igc_power_down_phy_copper(struct igc_hw *hw)
s32 igc_check_downshift(struct igc_hw *hw)
{
struct igc_phy_info *phy = &hw->phy;
- u16 phy_data, offset, mask;
s32 ret_val;
switch (phy->type) {
@@ -161,15 +160,8 @@ s32 igc_check_downshift(struct igc_hw *hw)
/* speed downshift not supported */
phy->speed_downgraded = false;
ret_val = 0;
- goto out;
}
- ret_val = phy->ops.read_reg(hw, offset, &phy_data);
-
- if (!ret_val)
- phy->speed_downgraded = (phy_data & mask) ? true : false;
-
-out:
return ret_val;
}
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index a1bd3216c906..5afe7a8d3faf 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -80,6 +80,9 @@
/* MSI-X Table Register Descriptions */
#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */
+/* Redirection Table - RW Array */
+#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
+
/* Receive Register Descriptions */
#define IGC_RCTL 0x00100 /* Rx Control - RW */
#define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40))
@@ -188,7 +191,6 @@
#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
#define IGC_LENERRS 0x04138 /* Length Errors Count */
-#define IGC_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
#define IGC_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
/* Management registers */
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 1d4d1686909a..e5ac2d3fd816 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -680,8 +680,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
txdr->size = ALIGN(txdr->size, 4096);
- txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
- GFP_KERNEL);
+ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+ GFP_KERNEL);
if (!txdr->desc) {
vfree(txdr->buffer_info);
return -ENOMEM;
@@ -763,8 +763,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
rxdr->size = ALIGN(rxdr->size, 4096);
- rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
- GFP_KERNEL);
+ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+ GFP_KERNEL);
if (!rxdr->desc) {
vfree(rxdr->buffer_info);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 1e49716f52bc..109f8de5a1c2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -1048,7 +1048,7 @@ mac_reset_top:
* clear the multicast table. Also reset num_rar_entries to 128,
* since we modify this value when programming the SAN MAC address.
*/
- hw->mac.num_rar_entries = 128;
+ hw->mac.num_rar_entries = IXGBE_82599_RAR_ENTRIES;
hw->mac.ops.init_rx_addrs(hw);
/* Store the permanent SAN mac address */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 62e6499e4146..cc3196ae5aea 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -836,12 +836,10 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring;
int node = NUMA_NO_NODE;
int cpu = -1;
- int ring_count, size;
+ int ring_count;
u8 tcs = adapter->hw_tcs;
ring_count = txr_count + rxr_count + xdp_count;
- size = sizeof(struct ixgbe_q_vector) +
- (sizeof(struct ixgbe_ring) * ring_count);
/* customize cpu for Flow Director mapping */
if ((tcs <= 1) && !(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) {
@@ -855,9 +853,11 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
}
/* allocate q_vector and rings */
- q_vector = kzalloc_node(size, GFP_KERNEL, node);
+ q_vector = kzalloc_node(struct_size(q_vector, ring, ring_count),
+ GFP_KERNEL, node);
if (!q_vector)
- q_vector = kzalloc(size, GFP_KERNEL);
+ q_vector = kzalloc(struct_size(q_vector, ring, ring_count),
+ GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index daff8183534b..e100054a3765 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -27,6 +27,7 @@
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <linux/atomic.h>
+#include <linux/numa.h>
#include <scsi/fc/fc_fcoe.h>
#include <net/udp_tunnel.h>
#include <net/pkt_cls.h>
@@ -3953,8 +3954,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
else
mrqc = IXGBE_MRQC_VMDQRSS64EN;
- /* Enable L3/L4 for Tx Switched packets */
- mrqc |= IXGBE_MRQC_L3L4TXSWEN;
+ /* Enable L3/L4 for Tx Switched packets only for X550,
+ * older devices do not support this feature
+ */
+ if (hw->mac.type >= ixgbe_mac_X550)
+ mrqc |= IXGBE_MRQC_L3L4TXSWEN;
} else {
if (tcs > 4)
mrqc = IXGBE_MRQC_RTRSS8TCEN;
@@ -6415,7 +6419,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
{
struct device *dev = tx_ring->dev;
int orig_node = dev_to_node(dev);
- int ring_node = -1;
+ int ring_node = NUMA_NO_NODE;
int size;
size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
@@ -6509,7 +6513,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
{
struct device *dev = rx_ring->dev;
int orig_node = dev_to_node(dev);
- int ring_node = -1;
+ int ring_node = NUMA_NO_NODE;
int size;
size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
@@ -9910,7 +9914,8 @@ static void ixgbe_del_udp_tunnel_port(struct net_device *dev,
static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags)
+ u16 flags,
+ struct netlink_ext_ack *extack)
{
/* guarantee we can provide a unique filter for the unicast address */
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
@@ -10225,6 +10230,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct bpf_prog *old_prog;
+ bool need_reset;
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
return -EINVAL;
@@ -10247,9 +10253,10 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
return -ENOMEM;
old_prog = xchg(&adapter->xdp_prog, prog);
+ need_reset = (!!prog != !!old_prog);
/* If transitioning XDP modes reconfigure rings */
- if (!!prog != !!old_prog) {
+ if (need_reset) {
int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
if (err) {
@@ -10265,6 +10272,14 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
if (old_prog)
bpf_prog_put(old_prog);
+ /* Kick start the NAPI context if there is an AF_XDP socket open
+ * on that queue id. This so that receiving will start.
+ */
+ if (need_reset && prog)
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ if (adapter->xdp_ring[i]->xsk_umem)
+ (void)ixgbe_xsk_async_xmit(adapter->netdev, i);
+
return 0;
}
@@ -10279,9 +10294,6 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
xdp->prog_id = adapter->xdp_prog ?
adapter->xdp_prog->aux->id : 0;
return 0;
- case XDP_QUERY_XSK_UMEM:
- return ixgbe_xsk_umem_query(adapter, &xdp->xsk.umem,
- xdp->xsk.queue_id);
case XDP_SETUP_XSK_UMEM:
return ixgbe_xsk_umem_setup(adapter, xdp->xsk.umem,
xdp->xsk.queue_id);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h
index 53d4089f5644..d93a690aff74 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h
@@ -30,8 +30,6 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring);
struct xdp_umem *ixgbe_xsk_umem(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring);
-int ixgbe_xsk_umem_query(struct ixgbe_adapter *adapter, struct xdp_umem **umem,
- u16 qid);
int ixgbe_xsk_umem_setup(struct ixgbe_adapter *adapter, struct xdp_umem *umem,
u16 qid);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
index 65c3e2c979d4..bfe95ce0bd7f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
@@ -144,11 +144,19 @@ static int ixgbe_xsk_umem_enable(struct ixgbe_adapter *adapter,
ixgbe_txrx_ring_disable(adapter, qid);
err = ixgbe_add_xsk_umem(adapter, umem, qid);
+ if (err)
+ return err;
- if (if_running)
+ if (if_running) {
ixgbe_txrx_ring_enable(adapter, qid);
- return err;
+ /* Kick start the NAPI context so that receiving will start */
+ err = ixgbe_xsk_async_xmit(adapter->netdev, qid);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
static int ixgbe_xsk_umem_disable(struct ixgbe_adapter *adapter, u16 qid)
@@ -174,23 +182,6 @@ static int ixgbe_xsk_umem_disable(struct ixgbe_adapter *adapter, u16 qid)
return 0;
}
-int ixgbe_xsk_umem_query(struct ixgbe_adapter *adapter, struct xdp_umem **umem,
- u16 qid)
-{
- if (qid >= adapter->num_rx_queues)
- return -EINVAL;
-
- if (adapter->xsk_umems) {
- if (qid >= adapter->num_xsk_umems)
- return -EINVAL;
- *umem = adapter->xsk_umems[qid];
- return 0;
- }
-
- *umem = NULL;
- return 0;
-}
-
int ixgbe_xsk_umem_setup(struct ixgbe_adapter *adapter, struct xdp_umem *umem,
u16 qid)
{
@@ -634,7 +625,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
dma_addr_t dma;
while (budget-- > 0) {
- if (unlikely(!ixgbe_desc_unused(xdp_ring))) {
+ if (unlikely(!ixgbe_desc_unused(xdp_ring)) ||
+ !netif_carrier_ok(xdp_ring->netdev)) {
work_done = false;
break;
}
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index a5ab6f3403ae..763ee5281177 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2034,10 +2034,9 @@ static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int count)
ctxbi->len,
PCI_DMA_TODEVICE);
- ctxbi->mapping = 0;
- ctxbi->len = 0;
+ ctxbi->mapping = 0;
+ ctxbi->len = 0;
}
-
}
static int
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 32ac9045cdae..f9bb890733b5 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -112,10 +112,12 @@ struct ltq_etop_priv {
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+
ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN);
if (!ch->skb[ch->dma.desc])
return -ENOMEM;
- ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
+ ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(&priv->pdev->dev,
ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN,
DMA_FROM_DEVICE);
ch->dma.desc_base[ch->dma.desc].addr =
@@ -487,7 +489,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
netif_trans_update(dev);
spin_lock_irqsave(&priv->lock, flags);
- desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
+ desc->addr = ((unsigned int) dma_map_single(&priv->pdev->dev, skb->data, len,
DMA_TO_DEVICE)) - byte_offset;
wmb();
desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
index 2d4d10a017e5..d29104de0d53 100644
--- a/drivers/net/ethernet/lantiq_xrx200.c
+++ b/drivers/net/ethernet/lantiq_xrx200.c
@@ -335,7 +335,6 @@ static const struct net_device_ops xrx200_netdev_ops = {
.ndo_start_xmit = xrx200_start_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
};
static irqreturn_t xrx200_dma_irq(int irq, void *ptr)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 2f427271a793..292a668ce88e 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2879,7 +2879,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
ret = mv643xx_eth_shared_of_probe(pdev);
if (ret)
- return ret;
+ goto err_put_clk;
pd = dev_get_platdata(&pdev->dev);
msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
@@ -2887,6 +2887,11 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
infer_hw_params(msp);
return 0;
+
+err_put_clk:
+ if (!IS_ERR(msp->clk))
+ clk_disable_unprepare(msp->clk);
+ return ret;
}
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 9d4568eb2297..c0a3718b2e2a 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -27,6 +27,7 @@
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
+#include <linux/phy/phy.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
@@ -436,6 +437,7 @@ struct mvneta_port {
struct device_node *dn;
unsigned int tx_csum_limit;
struct phylink *phylink;
+ struct phy *comphy;
struct mvneta_bm *bm_priv;
struct mvneta_bm_pool *pool_long;
@@ -2146,7 +2148,7 @@ err_drop_frame:
if (unlikely(!skb))
goto err_drop_frame_ret_pool;
- dma_sync_single_range_for_cpu(dev->dev.parent,
+ dma_sync_single_range_for_cpu(&pp->bm_priv->pdev->dev,
rx_desc->buf_phys_addr,
MVNETA_MH_SIZE + NET_SKB_PAD,
rx_bytes,
@@ -3147,10 +3149,27 @@ static int mvneta_setup_txqs(struct mvneta_port *pp)
return 0;
}
+static int mvneta_comphy_init(struct mvneta_port *pp)
+{
+ int ret;
+
+ if (!pp->comphy)
+ return 0;
+
+ ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET,
+ pp->phy_interface);
+ if (ret)
+ return ret;
+
+ return phy_power_on(pp->comphy);
+}
+
static void mvneta_start_dev(struct mvneta_port *pp)
{
int cpu;
+ WARN_ON(mvneta_comphy_init(pp));
+
mvneta_max_rx_size_set(pp, pp->pkt_size);
mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -3213,6 +3232,8 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
mvneta_tx_reset(pp);
mvneta_rx_reset(pp);
+
+ WARN_ON(phy_power_off(pp->comphy));
}
static void mvneta_percpu_enable(void *arg)
@@ -3338,6 +3359,7 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
struct phylink_link_state *state)
{
+ struct mvneta_port *pp = netdev_priv(ndev);
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
/* We only support QSGMII, SGMII, 802.3z and RGMII modes */
@@ -3358,8 +3380,13 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
phylink_set(mask, Pause);
/* Half-duplex at speeds higher than 100Mbit is unsupported */
- phylink_set(mask, 1000baseT_Full);
- phylink_set(mask, 1000baseX_Full);
+ if (pp->comphy || state->interface != PHY_INTERFACE_MODE_2500BASEX) {
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+ }
+ if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) {
+ phylink_set(mask, 2500baseX_Full);
+ }
if (!phy_interface_mode_is_8023z(state->interface)) {
/* 10M and 100M are only supported in non-802.3z mode */
@@ -3373,6 +3400,11 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
__ETHTOOL_LINK_MODE_MASK_NBITS);
bitmap_and(state->advertising, state->advertising, mask,
__ETHTOOL_LINK_MODE_MASK_NBITS);
+
+ /* We can only operate at 2500BaseX or 1000BaseX. If requested
+ * to advertise both, only report advertising at 2500BaseX.
+ */
+ phylink_helper_basex_speed(state);
}
static int mvneta_mac_link_state(struct net_device *ndev,
@@ -3384,7 +3416,9 @@ static int mvneta_mac_link_state(struct net_device *ndev,
gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
if (gmac_stat & MVNETA_GMAC_SPEED_1000)
- state->speed = SPEED_1000;
+ state->speed =
+ state->interface == PHY_INTERFACE_MODE_2500BASEX ?
+ SPEED_2500 : SPEED_1000;
else if (gmac_stat & MVNETA_GMAC_SPEED_100)
state->speed = SPEED_100;
else
@@ -3499,12 +3533,23 @@ static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
MVNETA_GMAC_FORCE_LINK_DOWN);
}
+
/* When at 2.5G, the link partner can send frames with shortened
* preambles.
*/
if (state->speed == SPEED_2500)
new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE;
+ if (pp->comphy && pp->phy_interface != state->interface &&
+ (state->interface == PHY_INTERFACE_MODE_SGMII ||
+ state->interface == PHY_INTERFACE_MODE_1000BASEX ||
+ state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
+ pp->phy_interface = state->interface;
+
+ WARN_ON(phy_power_off(pp->comphy));
+ WARN_ON(mvneta_comphy_init(pp));
+ }
+
if (new_ctrl0 != gmac_ctrl0)
mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0);
if (new_ctrl2 != gmac_ctrl2)
@@ -4404,7 +4449,7 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
else if (phy_mode == PHY_INTERFACE_MODE_SGMII ||
- phy_mode == PHY_INTERFACE_MODE_1000BASEX)
+ phy_interface_mode_is_8023z(phy_mode))
mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
else if (!phy_interface_mode_is_rgmii(phy_mode))
return -EINVAL;
@@ -4421,6 +4466,7 @@ static int mvneta_probe(struct platform_device *pdev)
struct mvneta_port *pp;
struct net_device *dev;
struct phylink *phylink;
+ struct phy *comphy;
const char *dt_mac_addr;
char hw_mac_addr[ETH_ALEN];
const char *mac_from;
@@ -4446,6 +4492,14 @@ static int mvneta_probe(struct platform_device *pdev)
goto err_free_irq;
}
+ comphy = devm_of_phy_get(&pdev->dev, dn, NULL);
+ if (comphy == ERR_PTR(-EPROBE_DEFER)) {
+ err = -EPROBE_DEFER;
+ goto err_free_irq;
+ } else if (IS_ERR(comphy)) {
+ comphy = NULL;
+ }
+
phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode,
&mvneta_phylink_ops);
if (IS_ERR(phylink)) {
@@ -4462,6 +4516,7 @@ static int mvneta_probe(struct platform_device *pdev)
pp = netdev_priv(dev);
spin_lock_init(&pp->lock);
pp->phylink = phylink;
+ pp->comphy = comphy;
pp->phy_interface = phy_mode;
pp->dn = dn;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
index 398328f10743..ff0f4c503f53 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -389,7 +389,7 @@
#define MVPP2_GMAC_IN_BAND_AUTONEG BIT(2)
#define MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS BIT(3)
#define MVPP2_GMAC_IN_BAND_RESTART_AN BIT(4)
-#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
+#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
#define MVPP2_GMAC_FC_ADV_EN BIT(9)
@@ -402,8 +402,8 @@
#define MVPP2_GMAC_STATUS0_GMII_SPEED BIT(1)
#define MVPP2_GMAC_STATUS0_MII_SPEED BIT(2)
#define MVPP2_GMAC_STATUS0_FULL_DUPLEX BIT(3)
-#define MVPP2_GMAC_STATUS0_RX_PAUSE BIT(6)
-#define MVPP2_GMAC_STATUS0_TX_PAUSE BIT(7)
+#define MVPP2_GMAC_STATUS0_RX_PAUSE BIT(4)
+#define MVPP2_GMAC_STATUS0_TX_PAUSE BIT(5)
#define MVPP2_GMAC_STATUS0_AN_COMPLETE BIT(11)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
@@ -430,6 +430,8 @@
#define MVPP22_XLG_CTRL0_REG 0x100
#define MVPP22_XLG_CTRL0_PORT_EN BIT(0)
#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
+#define MVPP22_XLG_CTRL0_FORCE_LINK_DOWN BIT(2)
+#define MVPP22_XLG_CTRL0_FORCE_LINK_PASS BIT(3)
#define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7)
#define MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN BIT(8)
#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)
@@ -481,6 +483,7 @@
/* XPCS registers. PPv2.2 only */
#define MVPP22_XPCS_BASE(port) (0x7400 + (port) * 0x1000)
#define MVPP22_XPCS_CFG0 0x0
+#define MVPP22_XPCS_CFG0_RESET_DIS BIT(0)
#define MVPP22_XPCS_CFG0_PCS_MODE(n) ((n) << 3)
#define MVPP22_XPCS_CFG0_ACTIVE_LANE(n) ((n) << 5)
@@ -549,8 +552,8 @@
#define MVPP2_MAX_TSO_SEGS 300
#define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
-/* Dfault number of RXQs in use */
-#define MVPP2_DEFAULT_RXQ 1
+/* Max number of RXQs per port */
+#define MVPP2_PORT_MAX_RXQ 32
/* Max number of Rx descriptors */
#define MVPP2_MAX_RXD_MAX 1024
@@ -803,7 +806,7 @@ struct mvpp2_port {
u8 id;
/* Index of the port from the "group of ports" complex point
- * of view
+ * of view. This is specific to PPv2.2.
*/
int gop_id;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index e0875476a780..25fbed2b8d94 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -965,6 +965,11 @@ mvpp2_shared_interrupt_mask_unmask(struct mvpp2_port *port, bool mask)
}
/* Port configuration routines */
+static bool mvpp2_is_xlg(phy_interface_t interface)
+{
+ return interface == PHY_INTERFACE_MODE_10GKR ||
+ interface == PHY_INTERFACE_MODE_XAUI;
+}
static void mvpp22_gop_init_rgmii(struct mvpp2_port *port)
{
@@ -1010,27 +1015,20 @@ static void mvpp22_gop_init_10gkr(struct mvpp2_port *port)
void __iomem *xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
u32 val;
- /* XPCS */
val = readl(xpcs + MVPP22_XPCS_CFG0);
val &= ~(MVPP22_XPCS_CFG0_PCS_MODE(0x3) |
MVPP22_XPCS_CFG0_ACTIVE_LANE(0x3));
val |= MVPP22_XPCS_CFG0_ACTIVE_LANE(2);
writel(val, xpcs + MVPP22_XPCS_CFG0);
- /* MPCS */
val = readl(mpcs + MVPP22_MPCS_CTRL);
val &= ~MVPP22_MPCS_CTRL_FWD_ERR_CONN;
writel(val, mpcs + MVPP22_MPCS_CTRL);
val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
- val &= ~(MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7) | MAC_CLK_RESET_MAC |
- MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX);
+ val &= ~MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7);
val |= MVPP22_MPCS_CLK_RESET_DIV_RATIO(1);
writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
-
- val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET;
- val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX;
- writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
}
static int mvpp22_gop_init(struct mvpp2_port *port)
@@ -1090,9 +1088,8 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
u32 val;
if (phy_interface_mode_is_rgmii(port->phy_interface) ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
- port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ phy_interface_mode_is_8023z(port->phy_interface) ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
/* Enable the GMAC link status irq for this port */
val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
val |= MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
@@ -1102,7 +1099,7 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
if (port->gop_id == 0) {
/* Enable the XLG/GIG irqs for this port */
val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
- if (port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+ if (mvpp2_is_xlg(port->phy_interface))
val |= MVPP22_XLG_EXT_INT_MASK_XLG;
else
val |= MVPP22_XLG_EXT_INT_MASK_GIG;
@@ -1122,9 +1119,8 @@ static void mvpp22_gop_mask_irq(struct mvpp2_port *port)
}
if (phy_interface_mode_is_rgmii(port->phy_interface) ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
- port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ phy_interface_mode_is_8023z(port->phy_interface) ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
val &= ~MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
@@ -1135,10 +1131,10 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
{
u32 val;
- if (phy_interface_mode_is_rgmii(port->phy_interface) ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
- port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ if (port->phylink ||
+ phy_interface_mode_is_rgmii(port->phy_interface) ||
+ phy_interface_mode_is_8023z(port->phy_interface) ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
val = readl(port->base + MVPP22_GMAC_INT_MASK);
val |= MVPP22_GMAC_INT_MASK_LINK_STAT;
writel(val, port->base + MVPP22_GMAC_INT_MASK);
@@ -1183,12 +1179,9 @@ static void mvpp2_port_enable(struct mvpp2_port *port)
u32 val;
/* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 &&
- (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
- port->phy_interface == PHY_INTERFACE_MODE_10GKR)) {
+ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
- val |= MVPP22_XLG_CTRL0_PORT_EN |
- MVPP22_XLG_CTRL0_MAC_RESET_DIS;
+ val |= MVPP22_XLG_CTRL0_PORT_EN;
val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS;
writel(val, port->base + MVPP22_XLG_CTRL0_REG);
} else {
@@ -1204,21 +1197,15 @@ static void mvpp2_port_disable(struct mvpp2_port *port)
u32 val;
/* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 &&
- (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
- port->phy_interface == PHY_INTERFACE_MODE_10GKR)) {
+ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val &= ~MVPP22_XLG_CTRL0_PORT_EN;
writel(val, port->base + MVPP22_XLG_CTRL0_REG);
-
- /* Disable & reset should be done separately */
- val &= ~MVPP22_XLG_CTRL0_MAC_RESET_DIS;
- writel(val, port->base + MVPP22_XLG_CTRL0_REG);
- } else {
- val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
- val &= ~(MVPP2_GMAC_PORT_EN_MASK);
- writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
}
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~(MVPP2_GMAC_PORT_EN_MASK);
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
}
/* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */
@@ -1244,9 +1231,8 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port,
else
val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
- if (port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
- port->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
+ if (phy_interface_mode_is_8023z(port->phy_interface) ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII)
val |= MVPP2_GMAC_PCS_LB_EN_MASK;
else
val &= ~MVPP2_GMAC_PCS_LB_EN_MASK;
@@ -1371,22 +1357,75 @@ static int mvpp2_ethtool_get_sset_count(struct net_device *dev, int sset)
return -EOPNOTSUPP;
}
-static void mvpp2_port_reset(struct mvpp2_port *port)
+static void mvpp2_mac_reset_assert(struct mvpp2_port *port)
{
- u32 val;
unsigned int i;
+ u32 val;
/* Read the GOP statistics to reset the hardware counters */
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
mvpp2_read_count(port, &mvpp2_ethtool_regs[i]);
- val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
- ~MVPP2_GMAC_PORT_RESET_MASK;
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) |
+ MVPP2_GMAC_PORT_RESET_MASK;
writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
- while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
- MVPP2_GMAC_PORT_RESET_MASK)
- continue;
+ if (port->priv->hw_version == MVPP22 && port->gop_id == 0) {
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG) &
+ ~MVPP22_XLG_CTRL0_MAC_RESET_DIS;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+ }
+}
+
+static void mvpp22_pcs_reset_assert(struct mvpp2_port *port)
+{
+ struct mvpp2 *priv = port->priv;
+ void __iomem *mpcs, *xpcs;
+ u32 val;
+
+ if (port->priv->hw_version != MVPP22 || port->gop_id != 0)
+ return;
+
+ mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id);
+ xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
+
+ val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
+ val &= ~(MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX);
+ val |= MVPP22_MPCS_CLK_RESET_DIV_SET;
+ writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
+
+ val = readl(xpcs + MVPP22_XPCS_CFG0);
+ writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0);
+}
+
+static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port)
+{
+ struct mvpp2 *priv = port->priv;
+ void __iomem *mpcs, *xpcs;
+ u32 val;
+
+ if (port->priv->hw_version != MVPP22 || port->gop_id != 0)
+ return;
+
+ mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id);
+ xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
+
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_10GKR:
+ val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
+ val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX |
+ MAC_CLK_RESET_SD_TX;
+ val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET;
+ writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
+ break;
+ case PHY_INTERFACE_MODE_XAUI:
+ case PHY_INTERFACE_MODE_RXAUI:
+ val = readl(xpcs + MVPP22_XPCS_CFG0);
+ writel(val | MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0);
+ break;
+ default:
+ break;
+ }
}
/* Change maximum receive size of the port */
@@ -2044,9 +2083,9 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev,
u32 txq_dma;
/* Allocate memory for TX descriptors */
- aggr_txq->descs = dma_zalloc_coherent(&pdev->dev,
- MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
- &aggr_txq->descs_dma, GFP_KERNEL);
+ aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
+ MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+ &aggr_txq->descs_dma, GFP_KERNEL);
if (!aggr_txq->descs)
return -ENOMEM;
@@ -2462,8 +2501,7 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
mvpp22_gop_mask_irq(port);
- if (port->gop_id == 0 &&
- port->phy_interface == PHY_INTERFACE_MODE_10GKR) {
+ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_INT_STAT);
if (val & MVPP22_XLG_INT_STAT_LINK) {
event = true;
@@ -2472,9 +2510,8 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
link = true;
}
} else if (phy_interface_mode_is_rgmii(port->phy_interface) ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
- port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ phy_interface_mode_is_8023z(port->phy_interface) ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
val = readl(port->base + MVPP22_GMAC_INT_STAT);
if (val & MVPP22_GMAC_INT_STAT_LINK) {
event = true;
@@ -3143,19 +3180,26 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
{
u32 ctrl3;
+ /* Set the GMAC & XLG MAC in reset */
+ mvpp2_mac_reset_assert(port);
+
+ /* Set the MPCS and XPCS in reset */
+ mvpp22_pcs_reset_assert(port);
+
/* comphy reconfiguration */
mvpp22_comphy_init(port);
/* gop reconfiguration */
mvpp22_gop_init(port);
+ mvpp22_pcs_reset_deassert(port);
+
/* Only GOP port 0 has an XLG MAC */
if (port->gop_id == 0) {
ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG);
ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
- if (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
- port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+ if (mvpp2_is_xlg(port->phy_interface))
ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_10G;
else
ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
@@ -3163,9 +3207,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG);
}
- if (port->gop_id == 0 &&
- (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
- port->phy_interface == PHY_INTERFACE_MODE_10GKR))
+ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface))
mvpp2_xlg_max_rx_size_set(port);
else
mvpp2_gmac_max_rx_size_set(port);
@@ -3483,6 +3525,9 @@ static int mvpp2_stop(struct net_device *dev)
cancel_delayed_work_sync(&port->stats_work);
+ mvpp2_mac_reset_assert(port);
+ mvpp22_pcs_reset_assert(port);
+
return 0;
}
@@ -4072,8 +4117,8 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
snprintf(irqname, sizeof(irqname), "hif%d", i);
if (queue_mode == MVPP2_QDIST_MULTI_MODE) {
- v->first_rxq = i * MVPP2_DEFAULT_RXQ;
- v->nrxqs = MVPP2_DEFAULT_RXQ;
+ v->first_rxq = i;
+ v->nrxqs = 1;
} else if (queue_mode == MVPP2_QDIST_SINGLE_MODE &&
i == (port->nqvecs - 1)) {
v->first_rxq = 0;
@@ -4166,8 +4211,7 @@ static int mvpp2_port_init(struct mvpp2_port *port)
MVPP2_MAX_PORTS * priv->max_port_rxqs)
return -EINVAL;
- if (port->nrxqs % MVPP2_DEFAULT_RXQ ||
- port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ)
+ if (port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ)
return -EINVAL;
/* Disable port */
@@ -4374,7 +4418,7 @@ static void mvpp2_phylink_validate(struct net_device *dev,
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- if (port->gop_id == 0)
+ if (port->priv->hw_version == MVPP22 && port->gop_id == 0)
goto empty_set;
break;
default:
@@ -4414,6 +4458,7 @@ static void mvpp2_phylink_validate(struct net_device *dev,
case PHY_INTERFACE_MODE_2500BASEX:
phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 1000baseX_Full);
+ phylink_set(mask, 2500baseT_Full);
phylink_set(mask, 2500baseX_Full);
break;
default:
@@ -4505,131 +4550,198 @@ static int mvpp2_phylink_mac_link_state(struct net_device *dev,
static void mvpp2_mac_an_restart(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
- u32 val;
-
- if (port->phy_interface != PHY_INTERFACE_MODE_SGMII)
- return;
+ u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- /* The RESTART_AN bit is cleared by the h/w after restarting the AN
- * process.
- */
- val |= MVPP2_GMAC_IN_BAND_RESTART_AN | MVPP2_GMAC_IN_BAND_AUTONEG;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN,
+ port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ writel(val & ~MVPP2_GMAC_IN_BAND_RESTART_AN,
+ port->base + MVPP2_GMAC_AUTONEG_CONFIG);
}
static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
const struct phylink_link_state *state)
{
- u32 ctrl0, ctrl4;
+ u32 old_ctrl0, ctrl0;
+ u32 old_ctrl4, ctrl4;
- ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG);
- ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG);
+ old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG);
+
+ ctrl0 |= MVPP22_XLG_CTRL0_MAC_RESET_DIS;
if (state->pause & MLO_PAUSE_TX)
ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
+ else
+ ctrl0 &= ~MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
+
if (state->pause & MLO_PAUSE_RX)
ctrl0 |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
+ else
+ ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
ctrl4 &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC;
ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC |
MVPP22_XLG_CTRL4_EN_IDLE_CHECK;
- writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
- writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG);
+ if (old_ctrl0 != ctrl0)
+ writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
+ if (old_ctrl4 != ctrl4)
+ writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG);
+
+ if (!(old_ctrl0 & MVPP22_XLG_CTRL0_MAC_RESET_DIS)) {
+ while (!(readl(port->base + MVPP22_XLG_CTRL0_REG) &
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS))
+ continue;
+ }
}
static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
const struct phylink_link_state *state)
{
- u32 an, ctrl0, ctrl2, ctrl4;
-
- an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
- ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
- ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+ u32 old_an, an;
+ u32 old_ctrl0, ctrl0;
+ u32 old_ctrl2, ctrl2;
+ u32 old_ctrl4, ctrl4;
- /* Force link down */
- an &= ~MVPP2_GMAC_FORCE_LINK_PASS;
- an |= MVPP2_GMAC_FORCE_LINK_DOWN;
- writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
-
- /* Set the GMAC in a reset state */
- ctrl2 |= MVPP2_GMAC_PORT_RESET_MASK;
- writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG);
+ old_an = an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ old_ctrl0 = ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ old_ctrl2 = ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ old_ctrl4 = ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
an &= ~(MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED |
MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FC_ADV_EN |
MVPP2_GMAC_FC_ADV_ASM_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG |
MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN |
- MVPP2_GMAC_FORCE_LINK_DOWN);
+ MVPP2_GMAC_IN_BAND_AUTONEG | MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS);
ctrl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK;
- ctrl2 &= ~(MVPP2_GMAC_PORT_RESET_MASK | MVPP2_GMAC_PCS_ENABLE_MASK);
-
- if (state->interface == PHY_INTERFACE_MODE_1000BASEX ||
- state->interface == PHY_INTERFACE_MODE_2500BASEX) {
- /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can
- * they negotiate duplex: they are always operating with a fixed
- * speed of 1000/2500Mbps in full duplex, so force 1000/2500
- * speed and full duplex here.
- */
- ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK;
- an |= MVPP2_GMAC_CONFIG_GMII_SPEED |
- MVPP2_GMAC_CONFIG_FULL_DUPLEX;
- } else if (!phy_interface_mode_is_rgmii(state->interface)) {
- an |= MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG;
+ ctrl2 &= ~(MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PORT_RESET_MASK |
+ MVPP2_GMAC_PCS_ENABLE_MASK);
+ ctrl4 &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
+
+ /* Configure port type */
+ if (phy_interface_mode_is_8023z(state->interface)) {
+ ctrl2 |= MVPP2_GMAC_PCS_ENABLE_MASK;
+ ctrl4 &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+ ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS |
+ MVPP22_CTRL4_DP_CLK_SEL |
+ MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
+ ctrl2 |= MVPP2_GMAC_PCS_ENABLE_MASK | MVPP2_GMAC_INBAND_AN_MASK;
+ ctrl4 &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+ ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS |
+ MVPP22_CTRL4_DP_CLK_SEL |
+ MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ } else if (phy_interface_mode_is_rgmii(state->interface)) {
+ ctrl4 &= ~MVPP22_CTRL4_DP_CLK_SEL;
+ ctrl4 |= MVPP22_CTRL4_EXT_PIN_GMII_SEL |
+ MVPP22_CTRL4_SYNC_BYPASS_DIS |
+ MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
}
- if (state->duplex)
- an |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
+ /* Configure advertisement bits */
if (phylink_test(state->advertising, Pause))
an |= MVPP2_GMAC_FC_ADV_EN;
if (phylink_test(state->advertising, Asym_Pause))
an |= MVPP2_GMAC_FC_ADV_ASM_EN;
- if (state->interface == PHY_INTERFACE_MODE_SGMII ||
- state->interface == PHY_INTERFACE_MODE_1000BASEX ||
- state->interface == PHY_INTERFACE_MODE_2500BASEX) {
- an |= MVPP2_GMAC_IN_BAND_AUTONEG;
- ctrl2 |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK;
+ /* Configure negotiation style */
+ if (!phylink_autoneg_inband(mode)) {
+ /* Phy or fixed speed - no in-band AN */
+ if (state->duplex)
+ an |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
- ctrl4 &= ~(MVPP22_CTRL4_EXT_PIN_GMII_SEL |
- MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
- ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS |
- MVPP22_CTRL4_DP_CLK_SEL |
- MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ if (state->speed == SPEED_1000 || state->speed == SPEED_2500)
+ an |= MVPP2_GMAC_CONFIG_GMII_SPEED;
+ else if (state->speed == SPEED_100)
+ an |= MVPP2_GMAC_CONFIG_MII_SPEED;
if (state->pause & MLO_PAUSE_TX)
ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
if (state->pause & MLO_PAUSE_RX)
ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
- } else if (phy_interface_mode_is_rgmii(state->interface)) {
- an |= MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS;
+ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
+ /* SGMII in-band mode receives the speed and duplex from
+ * the PHY. Flow control information is not received. */
+ an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS);
+ an |= MVPP2_GMAC_IN_BAND_AUTONEG |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_AN_DUPLEX_EN;
- if (state->speed == SPEED_1000)
- an |= MVPP2_GMAC_CONFIG_GMII_SPEED;
- else if (state->speed == SPEED_100)
- an |= MVPP2_GMAC_CONFIG_MII_SPEED;
+ if (state->pause & MLO_PAUSE_TX)
+ ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
+ if (state->pause & MLO_PAUSE_RX)
+ ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
+ } else if (phy_interface_mode_is_8023z(state->interface)) {
+ /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can
+ * they negotiate duplex: they are always operating with a fixed
+ * speed of 1000/2500Mbps in full duplex, so force 1000/2500
+ * speed and full duplex here.
+ */
+ ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK;
+ an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS);
+ an |= MVPP2_GMAC_IN_BAND_AUTONEG |
+ MVPP2_GMAC_CONFIG_GMII_SPEED |
+ MVPP2_GMAC_CONFIG_FULL_DUPLEX;
- ctrl4 &= ~MVPP22_CTRL4_DP_CLK_SEL;
- ctrl4 |= MVPP22_CTRL4_EXT_PIN_GMII_SEL |
- MVPP22_CTRL4_SYNC_BYPASS_DIS |
- MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ if (state->pause & MLO_PAUSE_AN && state->an_enabled) {
+ an |= MVPP2_GMAC_FLOW_CTRL_AUTONEG;
+ } else {
+ if (state->pause & MLO_PAUSE_TX)
+ ctrl4 |= MVPP22_CTRL4_TX_FC_EN;
+ if (state->pause & MLO_PAUSE_RX)
+ ctrl4 |= MVPP22_CTRL4_RX_FC_EN;
+ }
}
- writel(ctrl0, port->base + MVPP2_GMAC_CTRL_0_REG);
- writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG);
- writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG);
- writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+/* Some fields of the auto-negotiation register require the port to be down when
+ * their value is updated.
+ */
+#define MVPP2_GMAC_AN_PORT_DOWN_MASK \
+ (MVPP2_GMAC_IN_BAND_AUTONEG | \
+ MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS | \
+ MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | \
+ MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_CONFIG_FULL_DUPLEX | \
+ MVPP2_GMAC_AN_DUPLEX_EN)
+
+ if ((old_ctrl0 ^ ctrl0) & MVPP2_GMAC_PORT_TYPE_MASK ||
+ (old_ctrl2 ^ ctrl2) & MVPP2_GMAC_INBAND_AN_MASK ||
+ (old_an ^ an) & MVPP2_GMAC_AN_PORT_DOWN_MASK) {
+ /* Force link down */
+ old_an &= ~MVPP2_GMAC_FORCE_LINK_PASS;
+ old_an |= MVPP2_GMAC_FORCE_LINK_DOWN;
+ writel(old_an, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+ /* Set the GMAC in a reset state - do this in a way that
+ * ensures we clear it below.
+ */
+ old_ctrl2 |= MVPP2_GMAC_PORT_RESET_MASK;
+ writel(old_ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG);
+ }
+
+ if (old_ctrl0 != ctrl0)
+ writel(ctrl0, port->base + MVPP2_GMAC_CTRL_0_REG);
+ if (old_ctrl2 != ctrl2)
+ writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (old_ctrl4 != ctrl4)
+ writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG);
+ if (old_an != an)
+ writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+ if (old_ctrl2 & MVPP2_GMAC_PORT_RESET_MASK) {
+ while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+ MVPP2_GMAC_PORT_RESET_MASK)
+ continue;
+ }
}
static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
const struct phylink_link_state *state)
{
struct mvpp2_port *port = netdev_priv(dev);
+ bool change_interface = port->phy_interface != state->interface;
/* Check for invalid configuration */
- if (state->interface == PHY_INTERFACE_MODE_10GKR && port->gop_id != 0) {
+ if (mvpp2_is_xlg(state->interface) && port->gop_id != 0) {
netdev_err(dev, "Invalid mode on %s\n", dev->name);
return;
}
@@ -4637,8 +4749,9 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
/* Make sure the port is disabled when reconfiguring the mode */
mvpp2_port_disable(port);
- if (port->priv->hw_version == MVPP22 &&
- port->phy_interface != state->interface) {
+ if (port->priv->hw_version == MVPP22 && change_interface) {
+ mvpp22_gop_mask_irq(port);
+
port->phy_interface = state->interface;
/* Reconfigure the serdes lanes */
@@ -4647,17 +4760,19 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
}
/* mac (re)configuration */
- if (state->interface == PHY_INTERFACE_MODE_10GKR)
+ if (mvpp2_is_xlg(state->interface))
mvpp2_xlg_config(port, mode, state);
else if (phy_interface_mode_is_rgmii(state->interface) ||
- state->interface == PHY_INTERFACE_MODE_SGMII ||
- state->interface == PHY_INTERFACE_MODE_1000BASEX ||
- state->interface == PHY_INTERFACE_MODE_2500BASEX)
+ phy_interface_mode_is_8023z(state->interface) ||
+ state->interface == PHY_INTERFACE_MODE_SGMII)
mvpp2_gmac_config(port, mode, state);
if (port->priv->hw_version == MVPP21 && port->flags & MVPP2_F_LOOPBACK)
mvpp2_port_loopback_set(port, state);
+ if (port->priv->hw_version == MVPP22 && change_interface)
+ mvpp22_gop_unmask_irq(port);
+
mvpp2_port_enable(port);
}
@@ -4667,13 +4782,18 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode,
struct mvpp2_port *port = netdev_priv(dev);
u32 val;
- if (!phylink_autoneg_inband(mode) &&
- interface != PHY_INTERFACE_MODE_10GKR) {
- val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- val &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
- if (phy_interface_mode_is_rgmii(interface))
+ if (!phylink_autoneg_inband(mode)) {
+ if (mvpp2_is_xlg(interface)) {
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
+ val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+ } else {
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
val |= MVPP2_GMAC_FORCE_LINK_PASS;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ }
}
mvpp2_port_enable(port);
@@ -4689,25 +4809,24 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode,
struct mvpp2_port *port = netdev_priv(dev);
u32 val;
- if (!phylink_autoneg_inband(mode) &&
- interface != PHY_INTERFACE_MODE_10GKR) {
- val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- val &= ~MVPP2_GMAC_FORCE_LINK_PASS;
- val |= MVPP2_GMAC_FORCE_LINK_DOWN;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ if (!phylink_autoneg_inband(mode)) {
+ if (mvpp2_is_xlg(interface)) {
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
+ val |= MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+ } else {
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val &= ~MVPP2_GMAC_FORCE_LINK_PASS;
+ val |= MVPP2_GMAC_FORCE_LINK_DOWN;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ }
}
netif_tx_stop_all_queues(dev);
mvpp2_egress_disable(port);
mvpp2_ingress_disable(port);
- /* When using link interrupts to notify phylink of a MAC state change,
- * we do not want the port to be disabled (we want to receive further
- * interrupts, to be notified when the port will have a link later).
- */
- if (!port->has_phy)
- return;
-
mvpp2_port_disable(port);
}
@@ -4749,10 +4868,18 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
ntxqs = MVPP2_MAX_TXQ;
- if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_MULTI_MODE)
- nrxqs = MVPP2_DEFAULT_RXQ * num_possible_cpus();
- else
- nrxqs = MVPP2_DEFAULT_RXQ;
+ if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_SINGLE_MODE) {
+ nrxqs = 1;
+ } else {
+ /* According to the PPv2.2 datasheet and our experiments on
+ * PPv2.1, RX queues have an allocation granularity of 4 (when
+ * more than a single one on PPv2.2).
+ * Round up to nearest multiple of 4.
+ */
+ nrxqs = (num_possible_cpus() + 3) & ~0x3;
+ if (nrxqs > MVPP2_PORT_MAX_RXQ)
+ nrxqs = MVPP2_PORT_MAX_RXQ;
+ }
dev = alloc_etherdev_mqs(sizeof(*port), ntxqs, nrxqs);
if (!dev)
@@ -4883,7 +5010,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
mvpp2_port_periodic_xon_disable(port);
- mvpp2_port_reset(port);
+ mvpp2_mac_reset_assert(port);
+ mvpp22_pcs_reset_assert(port);
port->pcpu = alloc_percpu(struct mvpp2_port_pcpu);
if (!port->pcpu) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 742f0c1f60df..6d55e3d0b7ea 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -825,7 +825,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!cgx->cgx_cmd_workq) {
dev_err(dev, "alloc workqueue failed for cgx cmd");
err = -ENOMEM;
- goto err_release_regions;
+ goto err_free_irq_vectors;
}
list_add(&cgx->cgx_list, &cgx_list);
@@ -841,6 +841,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_release_lmac:
cgx_lmac_exit(cgx);
list_del(&cgx->cgx_list);
+err_free_irq_vectors:
+ pci_free_irq_vectors(pdev);
err_release_regions:
pci_release_regions(pdev);
err_disable_device:
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index ec50a21c5aaf..e332e82fc066 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -64,7 +64,7 @@ static inline int qmem_alloc(struct device *dev, struct qmem **q,
qmem->entry_sz = entry_sz;
qmem->alloc_sz = (qsize * entry_sz) + OTX2_ALIGN;
- qmem->base = dma_zalloc_coherent(dev, qmem->alloc_sz,
+ qmem->base = dma_alloc_coherent(dev, qmem->alloc_sz,
&qmem->iova, GFP_KERNEL);
if (!qmem->base)
return -ENOMEM;
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 0bd4351b2a49..35f2142aac5e 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -201,6 +201,7 @@ struct tx_desc {
};
struct pxa168_eth_private {
+ struct platform_device *pdev;
int port_num; /* User Ethernet port number */
int phy_addr;
int phy_speed;
@@ -331,7 +332,7 @@ static void rxq_refill(struct net_device *dev)
used_rx_desc = pep->rx_used_desc_q;
p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc];
size = skb_end_pointer(skb) - skb->data;
- p_used_rx_desc->buf_ptr = dma_map_single(NULL,
+ p_used_rx_desc->buf_ptr = dma_map_single(&pep->pdev->dev,
skb->data,
size,
DMA_FROM_DEVICE);
@@ -557,9 +558,9 @@ static int init_hash_table(struct pxa168_eth_private *pep)
* table is full.
*/
if (!pep->htpr) {
- pep->htpr = dma_zalloc_coherent(pep->dev->dev.parent,
- HASH_ADDR_TABLE_SIZE,
- &pep->htpr_dma, GFP_KERNEL);
+ pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
+ HASH_ADDR_TABLE_SIZE,
+ &pep->htpr_dma, GFP_KERNEL);
if (!pep->htpr)
return -ENOMEM;
} else {
@@ -743,7 +744,7 @@ static int txq_reclaim(struct net_device *dev, int force)
netdev_err(dev, "Error in TX\n");
dev->stats.tx_errors++;
}
- dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
+ dma_unmap_single(&pep->pdev->dev, addr, count, DMA_TO_DEVICE);
if (skb)
dev_kfree_skb_irq(skb);
released++;
@@ -805,7 +806,7 @@ static int rxq_process(struct net_device *dev, int budget)
if (rx_next_curr_desc == rx_used_desc)
pep->rx_resource_err = 1;
pep->rx_desc_count--;
- dma_unmap_single(NULL, rx_desc->buf_ptr,
+ dma_unmap_single(&pep->pdev->dev, rx_desc->buf_ptr,
rx_desc->buf_size,
DMA_FROM_DEVICE);
received_packets++;
@@ -1044,9 +1045,9 @@ static int rxq_init(struct net_device *dev)
pep->rx_desc_count = 0;
size = pep->rx_ring_size * sizeof(struct rx_desc);
pep->rx_desc_area_size = size;
- pep->p_rx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
- &pep->rx_desc_dma,
- GFP_KERNEL);
+ pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+ &pep->rx_desc_dma,
+ GFP_KERNEL);
if (!pep->p_rx_desc_area)
goto out;
@@ -1103,9 +1104,9 @@ static int txq_init(struct net_device *dev)
pep->tx_desc_count = 0;
size = pep->tx_ring_size * sizeof(struct tx_desc);
pep->tx_desc_area_size = size;
- pep->p_tx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
- &pep->tx_desc_dma,
- GFP_KERNEL);
+ pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+ &pep->tx_desc_dma,
+ GFP_KERNEL);
if (!pep->p_tx_desc_area)
goto out;
/* Initialize the next_desc_ptr links in the Tx descriptors ring */
@@ -1274,7 +1275,8 @@ pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
length = skb->len;
pep->tx_skb[tx_index] = skb;
desc->byte_cnt = length;
- desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+ desc->buf_ptr = dma_map_single(&pep->pdev->dev, skb->data, length,
+ DMA_TO_DEVICE);
skb_tx_timestamp(skb);
@@ -1528,6 +1530,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
if (err)
goto err_free_mdio;
+ pep->pdev = pdev;
SET_NETDEV_DEV(dev, &pdev->dev);
pxa168_init_hw(pep);
err = register_netdev(dev);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 04fd1f135011..654ac534b10e 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
memset(p, 0, regs->len);
memcpy_fromio(p, io, B3_RAM_ADDR);
- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
+ if (regs->len > B3_RI_WTO_R1) {
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+ regs->len - B3_RI_WTO_R1);
+ }
}
/* Wake on Lan only supported on Yukon chips with rev 1 or above */
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index f3a5fa84860f..8b3495ee2b6e 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -46,6 +46,7 @@
#include <linux/mii.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
+#include <linux/dmi.h>
#include <asm/irq.h>
@@ -93,7 +94,7 @@ static int copybreak __read_mostly = 128;
module_param(copybreak, int, 0);
MODULE_PARM_DESC(copybreak, "Receive copy threshold");
-static int disable_msi = 0;
+static int disable_msi = -1;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
@@ -4917,6 +4918,24 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
return buf;
}
+static const struct dmi_system_id msi_blacklist[] = {
+ {
+ .ident = "Dell Inspiron 1545",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1545"),
+ },
+ },
+ {
+ .ident = "Gateway P-79",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P-79"),
+ },
+ },
+ {}
+};
+
static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev, *dev1;
@@ -5028,6 +5047,9 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_pci;
}
+ if (disable_msi == -1)
+ disable_msi = !!dmi_check_system(msi_blacklist);
+
if (!disable_msi && pci_enable_msi(pdev) == 0) {
err = sky2_test_msi(hw);
if (err) {
@@ -5073,7 +5095,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&hw->restart_work, sky2_restart);
pci_set_drvdata(pdev, hw);
- pdev->d3_delay = 200;
+ pdev->d3_delay = 300;
return 0;
diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
index f9149d2a4694..43656f961891 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -1,6 +1,6 @@
config NET_VENDOR_MEDIATEK
bool "MediaTek ethernet driver"
- depends on ARCH_MEDIATEK
+ depends on ARCH_MEDIATEK || SOC_MT7621
---help---
If you have a Mediatek SoC with ethernet, say Y.
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 399f565dd85a..549d36497b8c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -226,7 +226,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
case SPEED_100:
mcr |= MAC_MCR_SPEED_100;
break;
- };
+ }
if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
!mac->id && !mac->trgmii)
@@ -258,11 +258,6 @@ static void mtk_phy_link_adjust(struct net_device *dev)
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
- if (dev->phydev->link)
- netif_carrier_on(dev);
- else
- netif_carrier_off(dev);
-
if (!of_phy_is_fixed_link(mac->of_node))
phy_print_status(dev->phydev);
}
@@ -347,17 +342,6 @@ static int mtk_phy_connect(struct net_device *dev)
if (mtk_phy_connect_node(eth, mac, np))
goto err_phy;
- dev->phydev->autoneg = AUTONEG_ENABLE;
- dev->phydev->speed = 0;
- dev->phydev->duplex = 0;
-
- phy_set_max_speed(dev->phydev, SPEED_1000);
- phy_support_asym_pause(dev->phydev);
- linkmode_copy(dev->phydev->advertising, dev->phydev->supported);
- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- dev->phydev->advertising);
- phy_start_aneg(dev->phydev);
-
of_node_put(np);
return 0;
@@ -598,10 +582,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
dma_addr_t dma_addr;
int i;
- eth->scratch_ring = dma_zalloc_coherent(eth->dev,
- cnt * sizeof(struct mtk_tx_dma),
- &eth->phy_scratch_ring,
- GFP_ATOMIC);
+ eth->scratch_ring = dma_alloc_coherent(eth->dev,
+ cnt * sizeof(struct mtk_tx_dma),
+ &eth->phy_scratch_ring,
+ GFP_ATOMIC);
if (unlikely(!eth->scratch_ring))
return -ENOMEM;
@@ -1213,8 +1197,8 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
if (!ring->buf)
goto no_tx_mem;
- ring->dma = dma_zalloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
- &ring->phys, GFP_ATOMIC);
+ ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+ &ring->phys, GFP_ATOMIC);
if (!ring->dma)
goto no_tx_mem;
@@ -1310,9 +1294,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
return -ENOMEM;
}
- ring->dma = dma_zalloc_coherent(eth->dev,
- rx_dma_size * sizeof(*ring->dma),
- &ring->phys, GFP_ATOMIC);
+ ring->dma = dma_alloc_coherent(eth->dev,
+ rx_dma_size * sizeof(*ring->dma),
+ &ring->phys, GFP_ATOMIC);
if (!ring->dma)
return -ENOMEM;
@@ -1761,6 +1745,22 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
return IRQ_HANDLED;
}
+static irqreturn_t mtk_handle_irq(int irq, void *_eth)
+{
+ struct mtk_eth *eth = _eth;
+
+ if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) {
+ if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT)
+ mtk_handle_irq_rx(irq, _eth);
+ }
+ if (mtk_r32(eth, MTK_QDMA_INT_MASK) & MTK_TX_DONE_INT) {
+ if (mtk_r32(eth, MTK_QMTK_INT_STATUS) & MTK_TX_DONE_INT)
+ mtk_handle_irq_tx(irq, _eth);
+ }
+
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void mtk_poll_controller(struct net_device *dev)
{
@@ -2501,7 +2501,10 @@ static int mtk_probe(struct platform_device *pdev)
}
for (i = 0; i < 3; i++) {
- eth->irq[i] = platform_get_irq(pdev, i);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
+ eth->irq[i] = eth->irq[0];
+ else
+ eth->irq[i] = platform_get_irq(pdev, i);
if (eth->irq[i] < 0) {
dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
return -ENXIO;
@@ -2544,13 +2547,21 @@ static int mtk_probe(struct platform_device *pdev)
goto err_deinit_hw;
}
- err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
- dev_name(eth->dev), eth);
- if (err)
- goto err_free_dev;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
+ err = devm_request_irq(eth->dev, eth->irq[0],
+ mtk_handle_irq, 0,
+ dev_name(eth->dev), eth);
+ } else {
+ err = devm_request_irq(eth->dev, eth->irq[1],
+ mtk_handle_irq_tx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
- err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
- dev_name(eth->dev), eth);
+ err = devm_request_irq(eth->dev, eth->irq[2],
+ mtk_handle_irq_rx, 0,
+ dev_name(eth->dev), eth);
+ }
if (err)
goto err_free_dev;
@@ -2623,6 +2634,12 @@ static const struct mtk_soc_data mt2701_data = {
.required_pctl = true,
};
+static const struct mtk_soc_data mt7621_data = {
+ .caps = MTK_SHARED_INT,
+ .required_clks = MT7621_CLKS_BITMAP,
+ .required_pctl = false,
+};
+
static const struct mtk_soc_data mt7622_data = {
.caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW | MTK_HWLRO,
.required_clks = MT7622_CLKS_BITMAP,
@@ -2637,6 +2654,7 @@ static const struct mtk_soc_data mt7623_data = {
const struct of_device_id of_mtk_match[] = {
{ .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+ { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
{},
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 46819297fc3e..f7501997cea0 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -363,6 +363,7 @@
#define ETHSYS_CHIPID4_7 0x4
#define MT7623_ETH 7623
#define MT7622_ETH 7622
+#define MT7621_ETH 7621
/* ethernet subsystem config register */
#define ETHSYS_SYSCFG0 0x14
@@ -488,6 +489,8 @@ enum mtk_clks_map {
BIT(MTK_CLK_SGMII_CDR_FB) | \
BIT(MTK_CLK_SGMII_CK) | \
BIT(MTK_CLK_ETH2PLL))
+#define MT7621_CLKS_BITMAP (0)
+
enum mtk_dev_state {
MTK_HW_INIT,
MTK_RESETTING
@@ -567,6 +570,7 @@ struct mtk_rx_ring {
#define MTK_DUAL_GMAC_SHARED_SGMII (BIT(11) | MTK_GMAC1_SGMII | \
MTK_GMAC2_SGMII)
#define MTK_HWLRO BIT(12)
+#define MTK_SHARED_INT BIT(13)
#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x))
/* struct mtk_eth_data - This is the structure holding all differences
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index f200b8c420d5..ff8057ed97ee 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -4,7 +4,6 @@
config MLX4_EN
tristate "Mellanox Technologies 1/10/40Gbit Ethernet support"
- depends on MAY_USE_DEVLINK
depends on PCI && NETDEVICES && ETHERNET && INET
select MLX4_CORE
imply PTP_1588_CLOCK
diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
index 9af34e03892c..b330020dc0d6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
@@ -185,8 +185,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
bitmap->avail = num - reserved_top - reserved_bot;
bitmap->effective_len = bitmap->avail;
spin_lock_init(&bitmap->lock);
- bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long),
- GFP_KERNEL);
+ bitmap->table = bitmap_zalloc(bitmap->max, GFP_KERNEL);
if (!bitmap->table)
return -ENOMEM;
@@ -197,7 +196,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap)
{
- kfree(bitmap->table);
+ bitmap_free(bitmap->table);
}
struct mlx4_zone_allocator {
@@ -584,8 +583,8 @@ static int mlx4_buf_direct_alloc(struct mlx4_dev *dev, int size,
buf->npages = 1;
buf->page_shift = get_order(size) + PAGE_SHIFT;
buf->direct.buf =
- dma_zalloc_coherent(&dev->persist->pdev->dev,
- size, &t, GFP_KERNEL);
+ dma_alloc_coherent(&dev->persist->pdev->dev, size, &t,
+ GFP_KERNEL);
if (!buf->direct.buf)
return -ENOMEM;
@@ -624,8 +623,8 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
for (i = 0; i < buf->nbufs; ++i) {
buf->page_list[i].buf =
- dma_zalloc_coherent(&dev->persist->pdev->dev,
- PAGE_SIZE, &t, GFP_KERNEL);
+ dma_alloc_coherent(&dev->persist->pdev->dev,
+ PAGE_SIZE, &t, GFP_KERNEL);
if (!buf->page_list[i].buf)
goto err_free;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index e65bc3c95630..c19e74e6ac94 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -3274,7 +3274,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat
mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n",
link_state, slave, port);
return -EINVAL;
- };
+ }
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
s_info->link_state = link_state;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index db909b6069b5..65f8a4b6ed0c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -306,14 +306,16 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
if (entries_per_copy < entries) {
for (i = 0; i < entries / entries_per_copy; i++) {
- err = copy_to_user(buf, init_ents, PAGE_SIZE);
+ err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ?
+ -EFAULT : 0;
if (err)
goto out;
buf += PAGE_SIZE;
}
} else {
- err = copy_to_user(buf, init_ents, entries * cqe_size);
+ err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ?
+ -EFAULT : 0;
}
out:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 6b88881b8e35..c1438ae52a11 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3360,7 +3360,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->addr_len = ETH_ALEN;
mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
if (!is_valid_ether_addr(dev->dev_addr)) {
- en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+ en_err(priv, "Port: %d, invalid mac burned: %pM, quitting\n",
priv->port, dev->dev_addr);
err = -EINVAL;
goto out;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 9a0881cb7f51..6c01314e87b0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
}
#endif
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
/* We reach this function only after checking that any of
* the (IPv4 | IPv6) bits are set in cqe->status.
*/
@@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
netdev_features_t dev_features)
{
__wsum hw_checksum = 0;
+ void *hdr;
+
+ /* CQE csum doesn't cover padding octets in short ethernet
+ * frames. And the pad field is appended prior to calculating
+ * and appending the FCS field.
+ *
+ * Detecting these padded frames requires to verify and parse
+ * IP headers, so we simply force all those small frames to skip
+ * checksum complete.
+ */
+ if (short_frame(skb->len))
+ return -EINVAL;
- void *hdr = (u8 *)va + sizeof(struct ethhdr);
-
+ hdr = (u8 *)va + sizeof(struct ethhdr);
hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
@@ -819,6 +832,11 @@ xdp_drop_no_cnt:
skb_record_rx_queue(skb, cq_ring);
if (likely(dev->features & NETIF_F_RXCSUM)) {
+ /* TODO: For IP non TCP/UDP packets when csum complete is
+ * not an option (not supported or any other reason) we can
+ * actually check cqe IPOK status bit and report
+ * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE
+ */
if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
MLX4_CQE_STATUS_UDP)) &&
(cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 2df92dbd38e1..a5be27772b8e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -100,7 +100,7 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not)
req_not << 31),
eq->doorbell);
/* We still want ordering, just not swabbing, so add a barrier */
- mb();
+ wmb();
}
static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor,
@@ -558,6 +558,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
__func__, be32_to_cpu(eqe->event.srq.srqn),
eq->eqn);
+ /* fall through */
case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
if (mlx4_is_master(dev)) {
/* forward only to slave owning the SRQ */
@@ -820,7 +821,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
!!(eqe->owner & 0x80) ^
!!(eq->cons_index & eq->nent) ? "HW" : "SW");
break;
- };
+ }
++eq->cons_index;
eqes_found = 1;
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 7df728f1e5b5..6e501af0e532 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -2067,9 +2067,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
{
struct mlx4_cmd_mailbox *mailbox;
__be32 *outbox;
+ u64 qword_field;
u32 dword_field;
- int err;
+ u16 word_field;
u8 byte_field;
+ int err;
static const u8 a0_dmfs_query_hw_steering[] = {
[0] = MLX4_STEERING_DMFS_A0_DEFAULT,
[1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
@@ -2097,19 +2099,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
/* QPC/EEC/CQC/EQC/RDMARC attributes */
- MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET);
- MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET);
- MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET);
- MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET);
- MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET);
- MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET);
- MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET);
- MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET);
- MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET);
- MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET);
- MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
- MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
- MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
+ MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
+ param->qpc_base = qword_field & ~((u64)0x1f);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
+ param->log_num_qps = byte_field & 0x1f;
+ MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
+ param->srqc_base = qword_field & ~((u64)0x1f);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
+ param->log_num_srqs = byte_field & 0x1f;
+ MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
+ param->cqc_base = qword_field & ~((u64)0x1f);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
+ param->log_num_cqs = byte_field & 0x1f;
+ MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
+ param->altc_base = qword_field;
+ MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
+ param->auxc_base = qword_field;
+ MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
+ param->eqc_base = qword_field & ~((u64)0x1f);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
+ param->log_num_eqs = byte_field & 0x1f;
+ MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+ param->num_sys_eqs = word_field & 0xfff;
+ MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+ param->rdmarc_base = qword_field & ~((u64)0x1f);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
+ param->log_rd_per_qp = byte_field & 0x7;
MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
@@ -2128,22 +2143,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
/* steering attributes */
if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
- MLX4_GET(param->log_mc_entry_sz, outbox,
- INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
- MLX4_GET(param->log_mc_table_sz, outbox,
- INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
- MLX4_GET(byte_field, outbox,
- INIT_HCA_FS_A0_OFFSET);
+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+ param->log_mc_entry_sz = byte_field & 0x1f;
+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+ param->log_mc_table_sz = byte_field & 0x1f;
+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
param->dmfs_high_steer_mode =
a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
} else {
MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
- MLX4_GET(param->log_mc_entry_sz, outbox,
- INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
- MLX4_GET(param->log_mc_hash_sz, outbox,
- INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
- MLX4_GET(param->log_mc_table_sz, outbox,
- INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+ param->log_mc_entry_sz = byte_field & 0x1f;
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+ param->log_mc_hash_sz = byte_field & 0x1f;
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+ param->log_mc_table_sz = byte_field & 0x1f;
}
/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
@@ -2167,15 +2181,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
/* TPT attributes */
MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET);
- MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
- MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+ MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
+ param->mw_enabled = byte_field >> 7;
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+ param->log_mpt_sz = byte_field & 0x3f;
MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET);
MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET);
/* UAR attributes */
MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
- MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+ param->log_uar_sz = byte_field & 0xf;
/* phv_check enable */
MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c
index 4b4351141b94..d89a3da89e5a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.c
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c
@@ -57,12 +57,12 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu
int i;
if (chunk->nsg > 0)
- pci_unmap_sg(dev->persist->pdev, chunk->mem, chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_sg(&dev->persist->pdev->dev, chunk->sg, chunk->npages,
+ DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->npages; ++i)
- __free_pages(sg_page(&chunk->mem[i]),
- get_order(chunk->mem[i].length));
+ __free_pages(sg_page(&chunk->sg[i]),
+ get_order(chunk->sg[i].length));
}
static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
@@ -71,9 +71,9 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *
for (i = 0; i < chunk->npages; ++i)
dma_free_coherent(&dev->persist->pdev->dev,
- chunk->mem[i].length,
- lowmem_page_address(sg_page(&chunk->mem[i])),
- sg_dma_address(&chunk->mem[i]));
+ chunk->buf[i].size,
+ chunk->buf[i].addr,
+ chunk->buf[i].dma_addr);
}
void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
@@ -111,22 +111,21 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order,
return 0;
}
-static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
- int order, gfp_t gfp_mask)
+static int mlx4_alloc_icm_coherent(struct device *dev, struct mlx4_icm_buf *buf,
+ int order, gfp_t gfp_mask)
{
- void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order,
- &sg_dma_address(mem), gfp_mask);
- if (!buf)
+ buf->addr = dma_alloc_coherent(dev, PAGE_SIZE << order,
+ &buf->dma_addr, gfp_mask);
+ if (!buf->addr)
return -ENOMEM;
- if (offset_in_page(buf)) {
- dma_free_coherent(dev, PAGE_SIZE << order,
- buf, sg_dma_address(mem));
+ if (offset_in_page(buf->addr)) {
+ dma_free_coherent(dev, PAGE_SIZE << order, buf->addr,
+ buf->dma_addr);
return -ENOMEM;
}
- sg_set_buf(mem, buf, PAGE_SIZE << order);
- sg_dma_len(mem) = PAGE_SIZE << order;
+ buf->size = PAGE_SIZE << order;
return 0;
}
@@ -159,21 +158,21 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
while (npages > 0) {
if (!chunk) {
- chunk = kmalloc_node(sizeof(*chunk),
+ chunk = kzalloc_node(sizeof(*chunk),
gfp_mask & ~(__GFP_HIGHMEM |
__GFP_NOWARN),
dev->numa_node);
if (!chunk) {
- chunk = kmalloc(sizeof(*chunk),
+ chunk = kzalloc(sizeof(*chunk),
gfp_mask & ~(__GFP_HIGHMEM |
__GFP_NOWARN));
if (!chunk)
goto fail;
}
+ chunk->coherent = coherent;
- sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
- chunk->npages = 0;
- chunk->nsg = 0;
+ if (!coherent)
+ sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN);
list_add_tail(&chunk->list, &icm->chunk_list);
}
@@ -186,10 +185,10 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
if (coherent)
ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev,
- &chunk->mem[chunk->npages],
- cur_order, mask);
+ &chunk->buf[chunk->npages],
+ cur_order, mask);
else
- ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages],
+ ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages],
cur_order, mask,
dev->numa_node);
@@ -205,9 +204,9 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
if (coherent)
++chunk->nsg;
else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
- chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ chunk->nsg = dma_map_sg(&dev->persist->pdev->dev,
+ chunk->sg, chunk->npages,
+ DMA_BIDIRECTIONAL);
if (chunk->nsg <= 0)
goto fail;
@@ -220,9 +219,8 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
}
if (!coherent && chunk) {
- chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
+ chunk->npages, DMA_BIDIRECTIONAL);
if (chunk->nsg <= 0)
goto fail;
@@ -320,7 +318,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
u64 idx;
struct mlx4_icm_chunk *chunk;
struct mlx4_icm *icm;
- struct page *page = NULL;
+ void *addr = NULL;
if (!table->lowmem)
return NULL;
@@ -336,28 +334,49 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
list_for_each_entry(chunk, &icm->chunk_list, list) {
for (i = 0; i < chunk->npages; ++i) {
+ dma_addr_t dma_addr;
+ size_t len;
+
+ if (table->coherent) {
+ len = chunk->buf[i].size;
+ dma_addr = chunk->buf[i].dma_addr;
+ addr = chunk->buf[i].addr;
+ } else {
+ struct page *page;
+
+ len = sg_dma_len(&chunk->sg[i]);
+ dma_addr = sg_dma_address(&chunk->sg[i]);
+
+ /* XXX: we should never do this for highmem
+ * allocation. This function either needs
+ * to be split, or the kernel virtual address
+ * return needs to be made optional.
+ */
+ page = sg_page(&chunk->sg[i]);
+ addr = lowmem_page_address(page);
+ }
+
if (dma_handle && dma_offset >= 0) {
- if (sg_dma_len(&chunk->mem[i]) > dma_offset)
- *dma_handle = sg_dma_address(&chunk->mem[i]) +
- dma_offset;
- dma_offset -= sg_dma_len(&chunk->mem[i]);
+ if (len > dma_offset)
+ *dma_handle = dma_addr + dma_offset;
+ dma_offset -= len;
}
+
/*
* DMA mapping can merge pages but not split them,
* so if we found the page, dma_handle has already
* been assigned to.
*/
- if (chunk->mem[i].length > offset) {
- page = sg_page(&chunk->mem[i]);
+ if (len > offset)
goto out;
- }
- offset -= chunk->mem[i].length;
+ offset -= len;
}
}
+ addr = NULL;
out:
mutex_unlock(&table->mutex);
- return page ? lowmem_page_address(page) + offset : NULL;
+ return addr ? addr + offset : NULL;
}
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h
index c9169a490557..d199874b1c07 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.h
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.h
@@ -47,11 +47,21 @@ enum {
MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT,
};
+struct mlx4_icm_buf {
+ void *addr;
+ size_t size;
+ dma_addr_t dma_addr;
+};
+
struct mlx4_icm_chunk {
struct list_head list;
int npages;
int nsg;
- struct scatterlist mem[MLX4_ICM_CHUNK_LEN];
+ bool coherent;
+ union {
+ struct scatterlist sg[MLX4_ICM_CHUNK_LEN];
+ struct mlx4_icm_buf buf[MLX4_ICM_CHUNK_LEN];
+ };
};
struct mlx4_icm {
@@ -114,12 +124,18 @@ static inline void mlx4_icm_next(struct mlx4_icm_iter *iter)
static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter)
{
- return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
+ if (iter->chunk->coherent)
+ return iter->chunk->buf[iter->page_idx].dma_addr;
+ else
+ return sg_dma_address(&iter->chunk->sg[iter->page_idx]);
}
static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
{
- return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
+ if (iter->chunk->coherent)
+ return iter->chunk->buf[iter->page_idx].size;
+ else
+ return sg_dma_len(&iter->chunk->sg[iter->page_idx]);
}
int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index bdb8dd161923..1f6e16d5ea6b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -3981,6 +3981,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto err_params_unregister;
+ devlink_params_publish(devlink);
pci_save_state(pdev);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index 37a551436e4a..6debffb8336b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -4,7 +4,6 @@
config MLX5_CORE
tristate "Mellanox 5th generation network adapters (ConnectX series) core driver"
- depends on MAY_USE_DEVLINK
depends on PCI
imply PTP_1588_CLOCK
imply VXLAN
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 9de9abacf7f6..1a16f6d73cbc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_MLX5_CORE) += mlx5_core.o
#
mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
health.o mcg.o cq.o alloc.o qp.o port.o mr.o pd.o \
- mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \
+ transobj.o vport.o sriov.o fs_cmd.o fs_core.o \
fs_counters.o rl.o lag.o dev.o events.o wq.o lib/gid.o \
lib/devcom.o diag/fs_tracepoint.o diag/fw_tracer.o
@@ -22,7 +22,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
#
mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \
- en_selftest.o en/port.o en/monitor_stats.o
+ en_selftest.o en/port.o en/monitor_stats.o en/reporter_tx.o
#
# Netdev extra
@@ -30,12 +30,12 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
mlx5_core-$(CONFIG_MLX5_EN_ARFS) += en_arfs.o
mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o
mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o
-mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o
+mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o
#
# Core extra
#
-mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o
+mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o ecpf.o
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
index 456f30007ad6..9008e17126db 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
@@ -63,8 +63,8 @@ static void *mlx5_dma_zalloc_coherent_node(struct mlx5_core_dev *dev,
mutex_lock(&priv->alloc_mutex);
original_node = dev_to_node(&dev->pdev->dev);
set_dev_node(&dev->pdev->dev, node);
- cpu_handle = dma_zalloc_coherent(&dev->pdev->dev, size,
- dma_handle, GFP_KERNEL);
+ cpu_handle = dma_alloc_coherent(&dev->pdev->dev, size, dma_handle,
+ GFP_KERNEL);
set_dev_node(&dev->pdev->dev, original_node);
mutex_unlock(&priv->alloc_mutex);
return cpu_handle;
@@ -186,10 +186,7 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
if (!pgdir)
return NULL;
- pgdir->bitmap = kcalloc(BITS_TO_LONGS(db_per_page),
- sizeof(unsigned long),
- GFP_KERNEL);
-
+ pgdir->bitmap = bitmap_zalloc(db_per_page, GFP_KERNEL);
if (!pgdir->bitmap) {
kfree(pgdir);
return NULL;
@@ -200,7 +197,7 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
pgdir->db_page = mlx5_dma_zalloc_coherent_node(dev, PAGE_SIZE,
&pgdir->db_dma, node);
if (!pgdir->db_page) {
- kfree(pgdir->bitmap);
+ bitmap_free(pgdir->bitmap);
kfree(pgdir);
return NULL;
}
@@ -280,7 +277,7 @@ void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db)
dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
db->u.pgdir->db_page, db->u.pgdir->db_dma);
list_del(&db->u.pgdir->list);
- kfree(db->u.pgdir->bitmap);
+ bitmap_free(db->u.pgdir->bitmap);
kfree(db->u.pgdir);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index d3125cdf69db..be48c6440251 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -316,6 +316,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT:
case MLX5_CMD_OP_DEALLOC_MEMIC:
case MLX5_CMD_OP_PAGE_FAULT_RESUME:
+ case MLX5_CMD_OP_QUERY_HOST_PARAMS:
return MLX5_CMD_STAT_OK;
case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -627,6 +628,7 @@ const char *mlx5_command_str(int command)
MLX5_COMMAND_STR_CASE(QUERY_MODIFY_HEADER_CONTEXT);
MLX5_COMMAND_STR_CASE(ALLOC_MEMIC);
MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC);
+ MLX5_COMMAND_STR_CASE(QUERY_HOST_PARAMS);
default: return "unknown command opcode";
}
}
@@ -1583,6 +1585,24 @@ no_trig:
spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
}
+void mlx5_cmd_flush(struct mlx5_core_dev *dev)
+{
+ struct mlx5_cmd *cmd = &dev->cmd;
+ int i;
+
+ for (i = 0; i < cmd->max_reg_cmds; i++)
+ while (down_trylock(&cmd->sem))
+ mlx5_cmd_trigger_completions(dev);
+
+ while (down_trylock(&cmd->pages_sem))
+ mlx5_cmd_trigger_completions(dev);
+
+ /* Unlock cmdif */
+ up(&cmd->pages_sem);
+ for (i = 0; i < cmd->max_reg_cmds; i++)
+ up(&cmd->sem);
+}
+
static int status_to_err(u8 status)
{
return status ? -1 : 0; /* TBD more meaningful codes */
@@ -1711,12 +1731,57 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
}
EXPORT_SYMBOL(mlx5_cmd_exec);
-int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *in, int in_size,
- void *out, int out_size, mlx5_cmd_cbk_t callback,
- void *context)
+void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev,
+ struct mlx5_async_ctx *ctx)
+{
+ ctx->dev = dev;
+ /* Starts at 1 to avoid doing wake_up if we are not cleaning up */
+ atomic_set(&ctx->num_inflight, 1);
+ init_waitqueue_head(&ctx->wait);
+}
+EXPORT_SYMBOL(mlx5_cmd_init_async_ctx);
+
+/**
+ * mlx5_cmd_cleanup_async_ctx - Clean up an async_ctx
+ * @ctx: The ctx to clean
+ *
+ * Upon return all callbacks given to mlx5_cmd_exec_cb() have been called. The
+ * caller must ensure that mlx5_cmd_exec_cb() is not called during or after
+ * the call mlx5_cleanup_async_ctx().
+ */
+void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx)
+{
+ atomic_dec(&ctx->num_inflight);
+ wait_event(ctx->wait, atomic_read(&ctx->num_inflight) == 0);
+}
+EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx);
+
+static void mlx5_cmd_exec_cb_handler(int status, void *_work)
+{
+ struct mlx5_async_work *work = _work;
+ struct mlx5_async_ctx *ctx = work->ctx;
+
+ work->user_callback(status, work);
+ if (atomic_dec_and_test(&ctx->num_inflight))
+ wake_up(&ctx->wait);
+}
+
+int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size,
+ void *out, int out_size, mlx5_async_cbk_t callback,
+ struct mlx5_async_work *work)
{
- return cmd_exec(dev, in, in_size, out, out_size, callback, context,
- false);
+ int ret;
+
+ work->ctx = ctx;
+ work->user_callback = callback;
+ if (WARN_ON(!atomic_inc_not_zero(&ctx->num_inflight)))
+ return -EIO;
+ ret = cmd_exec(ctx->dev, in, in_size, out, out_size,
+ mlx5_cmd_exec_cb_handler, work, false);
+ if (ret && atomic_dec_and_test(&ctx->num_inflight))
+ wake_up(&ctx->wait);
+
+ return ret;
}
EXPORT_SYMBOL(mlx5_cmd_exec_cb);
@@ -1789,8 +1854,8 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
{
struct device *ddev = &dev->pdev->dev;
- cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
- &cmd->alloc_dma, GFP_KERNEL);
+ cmd->cmd_alloc_buf = dma_alloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
+ &cmd->alloc_dma, GFP_KERNEL);
if (!cmd->cmd_alloc_buf)
return -ENOMEM;
@@ -1804,9 +1869,9 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
dma_free_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, cmd->cmd_alloc_buf,
cmd->alloc_dma);
- cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev,
- 2 * MLX5_ADAPTER_PAGE_SIZE - 1,
- &cmd->alloc_dma, GFP_KERNEL);
+ cmd->cmd_alloc_buf = dma_alloc_coherent(ddev,
+ 2 * MLX5_ADAPTER_PAGE_SIZE - 1,
+ &cmd->alloc_dma, GFP_KERNEL);
if (!cmd->cmd_alloc_buf)
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
index 424457ff9759..8ecac81a385d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
@@ -258,6 +258,8 @@ const char *parse_fs_dst(struct trace_seq *p,
return ret;
}
+EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft);
+EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft);
EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg);
EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg);
EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
index d027ce00c8ce..a4cf123e3f17 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
@@ -61,6 +61,41 @@ const char *parse_fs_dst(struct trace_seq *p,
const struct mlx5_flow_destination *dst,
u32 counter_id);
+TRACE_EVENT(mlx5_fs_add_ft,
+ TP_PROTO(const struct mlx5_flow_table *ft),
+ TP_ARGS(ft),
+ TP_STRUCT__entry(
+ __field(const struct mlx5_flow_table *, ft)
+ __field(u32, id)
+ __field(u32, level)
+ __field(u32, type)
+ ),
+ TP_fast_assign(
+ __entry->ft = ft;
+ __entry->id = ft->id;
+ __entry->level = ft->level;
+ __entry->type = ft->type;
+ ),
+ TP_printk("ft=%p id=%u level=%u type=%u \n",
+ __entry->ft, __entry->id, __entry->level, __entry->type)
+ );
+
+TRACE_EVENT(mlx5_fs_del_ft,
+ TP_PROTO(const struct mlx5_flow_table *ft),
+ TP_ARGS(ft),
+ TP_STRUCT__entry(
+ __field(const struct mlx5_flow_table *, ft)
+ __field(u32, id)
+ ),
+ TP_fast_assign(
+ __entry->ft = ft;
+ __entry->id = ft->id;
+
+ ),
+ TP_printk("ft=%p id=%u\n",
+ __entry->ft, __entry->id)
+ );
+
TRACE_EVENT(mlx5_fs_add_fg,
TP_PROTO(const struct mlx5_flow_group *fg),
TP_ARGS(fg),
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c
new file mode 100644
index 000000000000..4746f2d28fb6
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#include "ecpf.h"
+
+bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev)
+{
+ return (ioread32be(&dev->iseg->initializing) >> MLX5_ECPU_BIT_NUM) & 1;
+}
+
+static int mlx5_peer_pf_enable_hca(struct mlx5_core_dev *dev)
+{
+ u32 out[MLX5_ST_SZ_DW(enable_hca_out)] = {};
+ u32 in[MLX5_ST_SZ_DW(enable_hca_in)] = {};
+
+ MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA);
+ MLX5_SET(enable_hca_in, in, function_id, 0);
+ MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0);
+ return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
+}
+
+static int mlx5_peer_pf_disable_hca(struct mlx5_core_dev *dev)
+{
+ u32 out[MLX5_ST_SZ_DW(disable_hca_out)] = {};
+ u32 in[MLX5_ST_SZ_DW(disable_hca_in)] = {};
+
+ MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA);
+ MLX5_SET(disable_hca_in, in, function_id, 0);
+ MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0);
+ return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+static int mlx5_peer_pf_init(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ err = mlx5_peer_pf_enable_hca(dev);
+ if (err)
+ mlx5_core_err(dev, "Failed to enable peer PF HCA err(%d)\n",
+ err);
+
+ return err;
+}
+
+static void mlx5_peer_pf_cleanup(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ err = mlx5_peer_pf_disable_hca(dev);
+ if (err) {
+ mlx5_core_err(dev, "Failed to disable peer PF HCA err(%d)\n",
+ err);
+ return;
+ }
+
+ err = mlx5_wait_for_pages(dev, &dev->priv.peer_pf_pages);
+ if (err)
+ mlx5_core_warn(dev, "Timeout reclaiming peer PF pages err(%d)\n",
+ err);
+}
+
+int mlx5_ec_init(struct mlx5_core_dev *dev)
+{
+ int err = 0;
+
+ if (!mlx5_core_is_ecpf(dev))
+ return 0;
+
+ /* ECPF shall enable HCA for peer PF in the same way a PF
+ * does this for its VFs.
+ */
+ err = mlx5_peer_pf_init(dev);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+void mlx5_ec_cleanup(struct mlx5_core_dev *dev)
+{
+ if (!mlx5_core_is_ecpf(dev))
+ return;
+
+ mlx5_peer_pf_cleanup(dev);
+}
+
+static int mlx5_query_host_params_context(struct mlx5_core_dev *dev,
+ u32 *out, int outlen)
+{
+ u32 in[MLX5_ST_SZ_DW(query_host_params_in)] = {};
+
+ MLX5_SET(query_host_params_in, in, opcode,
+ MLX5_CMD_OP_QUERY_HOST_PARAMS);
+
+ return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
+}
+
+int mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf)
+{
+ u32 out[MLX5_ST_SZ_DW(query_host_params_out)] = {};
+ int err;
+
+ err = mlx5_query_host_params_context(dev, out, sizeof(out));
+ if (err)
+ return err;
+
+ *num_vf = MLX5_GET(query_host_params_out, out,
+ host_params_context.host_num_of_vfs);
+ mlx5_core_dbg(dev, "host_num_of_vfs %d\n", *num_vf);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h
new file mode 100644
index 000000000000..346372df218f
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __MLX5_ECPF_H__
+#define __MLX5_ECPF_H__
+
+#include <linux/mlx5/driver.h>
+#include "mlx5_core.h"
+
+#ifdef CONFIG_MLX5_ESWITCH
+
+enum {
+ MLX5_ECPU_BIT_NUM = 23,
+};
+
+bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev);
+int mlx5_ec_init(struct mlx5_core_dev *dev);
+void mlx5_ec_cleanup(struct mlx5_core_dev *dev);
+int mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf);
+
+#else /* CONFIG_MLX5_ESWITCH */
+
+static inline bool
+mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { return false; }
+static inline int mlx5_ec_init(struct mlx5_core_dev *dev) { return 0; }
+static inline void mlx5_ec_cleanup(struct mlx5_core_dev *dev) {}
+static inline int
+mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf)
+{ return -EOPNOTSUPP; }
+
+#endif /* CONFIG_MLX5_ESWITCH */
+
+#endif /* __MLX5_ECPF_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 8fa8fdd30b85..71c65cc17904 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -76,15 +76,14 @@ struct page_pool;
#define MLX5_SKB_FRAG_SZ(len) (SKB_DATA_ALIGN(len) + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+#define MLX5E_RX_MAX_HEAD (256)
+
#define MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(mdev) \
(6 + MLX5_CAP_GEN(mdev, cache_line_128byte)) /* HW restriction */
#define MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, req) \
max_t(u32, MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(mdev), req)
-#define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, 6)
-#define MLX5_MPWRQ_CQE_CMPRS_LOG_STRIDE_SZ(mdev) MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, 8)
-#define MLX5E_MPWQE_STRIDE_SZ(mdev, cqe_cmprs) \
- (cqe_cmprs ? MLX5_MPWRQ_CQE_CMPRS_LOG_STRIDE_SZ(mdev) : \
- MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev))
+#define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) \
+ MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, order_base_2(MLX5E_RX_MAX_HEAD))
#define MLX5_MPWRQ_LOG_WQE_SZ 18
#define MLX5_MPWRQ_WQE_PAGE_ORDER (MLX5_MPWRQ_LOG_WQE_SZ - PAGE_SHIFT > 0 ? \
@@ -119,8 +118,6 @@ struct page_pool;
#define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW 0x2
-#define MLX5E_RX_MAX_HEAD (256)
-
#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
#define MLX5E_DEFAULT_LRO_TIMEOUT 32
#define MLX5E_LRO_TIMEOUT_ARR_SIZE 4
@@ -309,16 +306,18 @@ struct mlx5e_cq {
struct mlx5_core_cq mcq;
struct mlx5e_channel *channel;
+ /* control */
+ struct mlx5_core_dev *mdev;
+ struct mlx5_wq_ctrl wq_ctrl;
+} ____cacheline_aligned_in_smp;
+
+struct mlx5e_cq_decomp {
/* cqe decompression */
struct mlx5_cqe64 title;
struct mlx5_mini_cqe8 mini_arr[MLX5_MINI_CQE_ARRAY_SIZE];
u8 mini_arr_idx;
- u16 decmprs_left;
- u16 decmprs_wqe_counter;
-
- /* control */
- struct mlx5_core_dev *mdev;
- struct mlx5_wq_ctrl wq_ctrl;
+ u16 left;
+ u16 wqe_counter;
} ____cacheline_aligned_in_smp;
struct mlx5e_tx_wqe_info {
@@ -388,10 +387,7 @@ struct mlx5e_txqsq {
struct mlx5e_channel *channel;
int txq_ix;
u32 rate_limit;
- struct mlx5e_txqsq_recover {
- struct work_struct recover_work;
- u64 last_recover;
- } recover;
+ struct work_struct recover_work;
} ____cacheline_aligned_in_smp;
struct mlx5e_dma_info {
@@ -581,6 +577,7 @@ struct mlx5e_rq {
struct net_device *netdev;
struct mlx5e_rq_stats *stats;
struct mlx5e_cq cq;
+ struct mlx5e_cq_decomp cqd;
struct mlx5e_page_cache page_cache;
struct hwtstamp_config *tstamp;
struct mlx5_clock *clock;
@@ -638,6 +635,7 @@ struct mlx5e_channel {
struct hwtstamp_config *tstamp;
int ix;
int cpu;
+ cpumask_var_t xps_cpumask;
};
struct mlx5e_channels {
@@ -657,6 +655,7 @@ struct mlx5e_channel_stats {
enum {
MLX5E_STATE_OPENED,
MLX5E_STATE_DESTROYING,
+ MLX5E_STATE_XDP_TX_ENABLED,
};
struct mlx5e_rqt {
@@ -682,6 +681,13 @@ struct mlx5e_rss_params {
u8 hfunc;
};
+struct mlx5e_modify_sq_param {
+ int curr_state;
+ int next_state;
+ int rl_update;
+ int rl_index;
+};
+
struct mlx5e_priv {
/* priv data path fields - start */
struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
@@ -737,6 +743,7 @@ struct mlx5e_priv {
#ifdef CONFIG_MLX5_EN_TLS
struct mlx5e_tls *tls;
#endif
+ struct devlink_health_reporter *tx_reporter;
};
struct mlx5e_profile {
@@ -803,6 +810,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
void mlx5e_update_stats(struct mlx5e_priv *priv);
void mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
+void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s);
void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
int mlx5e_self_test_num(struct mlx5e_priv *priv);
@@ -850,9 +858,9 @@ void mlx5e_close_channels(struct mlx5e_channels *chs);
* switching channels
*/
typedef int (*mlx5e_fp_hw_modify)(struct mlx5e_priv *priv);
-void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
- struct mlx5e_channels *new_chs,
- mlx5e_fp_hw_modify hw_modify);
+int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
+ struct mlx5e_channels *new_chs,
+ mlx5e_fp_hw_modify hw_modify);
void mlx5e_activate_priv_channels(struct mlx5e_priv *priv);
void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv);
@@ -866,6 +874,11 @@ void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params);
void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev,
struct mlx5e_params *params);
+int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
+ struct mlx5e_modify_sq_param *p);
+void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq);
+void mlx5e_tx_disable_queue(struct netdev_queue *txq);
+
static inline bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev)
{
return (MLX5_CAP_ETH(mdev, tunnel_stateless_gre) &&
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
index 2ce420851e77..7cd5b02e0f10 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
@@ -66,7 +66,7 @@ static int mlx5e_monitor_event_handler(struct notifier_block *nb,
return NOTIFY_OK;
}
-void mlx5e_monitor_counter_start(struct mlx5e_priv *priv)
+static void mlx5e_monitor_counter_start(struct mlx5e_priv *priv)
{
MLX5_NB_INIT(&priv->monitor_counters_nb, mlx5e_monitor_event_handler,
MONITOR_COUNTER);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
index 4a37713023be..122927f3a600 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -63,66 +63,168 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = {
[MLX5E_50GBASE_KR2] = 50000,
};
-u32 mlx5e_port_ptys2speed(u32 eth_proto_oper)
+static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
+ [MLX5E_SGMII_100M] = 100,
+ [MLX5E_1000BASE_X_SGMII] = 1000,
+ [MLX5E_5GBASE_R] = 5000,
+ [MLX5E_10GBASE_XFI_XAUI_1] = 10000,
+ [MLX5E_40GBASE_XLAUI_4_XLPPI_4] = 40000,
+ [MLX5E_25GAUI_1_25GBASE_CR_KR] = 25000,
+ [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000,
+ [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR] = 50000,
+ [MLX5E_CAUI_4_100GBASE_CR4_KR4] = 100000,
+ [MLX5E_200GAUI_4_200GBASE_CR4_KR4] = 200000,
+ [MLX5E_400GAUI_8] = 400000,
+};
+
+static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
+ const u32 **arr, u32 *size)
+{
+ bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+
+ *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
+ ARRAY_SIZE(mlx5e_link_speed);
+ *arr = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
+}
+
+int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
+ struct mlx5e_port_eth_proto *eproto)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ int err;
+
+ if (!eproto)
+ return -EINVAL;
+
+ if (ext != MLX5_CAP_PCAM_FEATURE(dev, ptys_extended_ethernet))
+ return -EOPNOTSUPP;
+
+ err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
+ if (err)
+ return err;
+
+ eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+ eth_proto_capability);
+ eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
+ eproto->oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
+ return 0;
+}
+
+void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
+ u8 *an_disable_cap, u8 *an_disable_admin)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+
+ *an_status = 0;
+ *an_disable_cap = 0;
+ *an_disable_admin = 0;
+
+ if (mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 1))
+ return;
+
+ *an_status = MLX5_GET(ptys_reg, out, an_status);
+ *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
+ *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
+}
+
+int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
+ u32 proto_admin, bool ext)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ u32 in[MLX5_ST_SZ_DW(ptys_reg)];
+ u8 an_disable_admin;
+ u8 an_disable_cap;
+ u8 an_status;
+
+ mlx5_port_query_eth_autoneg(dev, &an_status, &an_disable_cap,
+ &an_disable_admin);
+ if (!an_disable_cap && an_disable)
+ return -EPERM;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(ptys_reg, in, local_port, 1);
+ MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
+ MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN);
+ if (ext)
+ MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
+ else
+ MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
+
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PTYS, 0, 1);
+}
+
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
{
unsigned long temp = eth_proto_oper;
+ const u32 *table;
u32 speed = 0;
+ u32 max_size;
int i;
- i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER);
- if (i < MLX5E_LINK_MODES_NUMBER)
- speed = mlx5e_link_speed[i];
-
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ i = find_first_bit(&temp, max_size);
+ if (i < max_size)
+ speed = table[i];
return speed;
}
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {};
- u32 eth_proto_oper;
+ struct mlx5e_port_eth_proto eproto;
+ bool ext;
int err;
- err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
+ ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+ err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
if (err)
- return err;
+ goto out;
- eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
- *speed = mlx5e_port_ptys2speed(eth_proto_oper);
+ *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
if (!(*speed))
err = -EINVAL;
+out:
return err;
}
int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
{
+ struct mlx5e_port_eth_proto eproto;
u32 max_speed = 0;
- u32 proto_cap;
+ const u32 *table;
+ u32 max_size;
+ bool ext;
int err;
int i;
- err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN);
+ ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+ err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
if (err)
return err;
- for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i)
- if (proto_cap & MLX5E_PROT_MASK(i))
- max_speed = max(max_speed, mlx5e_link_speed[i]);
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ for (i = 0; i < max_size; ++i)
+ if (eproto.cap & MLX5E_PROT_MASK(i))
+ max_speed = max(max_speed, table[i]);
*speed = max_speed;
return 0;
}
-u32 mlx5e_port_speed2linkmodes(u32 speed)
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
{
u32 link_modes = 0;
+ const u32 *table;
+ u32 max_size;
int i;
- for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
- if (mlx5e_link_speed[i] == speed)
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+ for (i = 0; i < max_size; ++i) {
+ if (table[i] == speed)
link_modes |= MLX5E_PROT_MASK(i);
}
-
return link_modes;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
index cd2160b8c9bf..70f536ec51c4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -36,10 +36,22 @@
#include <linux/mlx5/driver.h>
#include "en.h"
-u32 mlx5e_port_ptys2speed(u32 eth_proto_oper);
+struct mlx5e_port_eth_proto {
+ u32 cap;
+ u32 admin;
+ u32 oper;
+};
+
+int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
+ struct mlx5e_port_eth_proto *eproto);
+void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
+ u8 *an_disable_cap, u8 *an_disable_admin);
+int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
+ u32 proto_admin, bool ext);
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
-u32 mlx5e_port_speed2linkmodes(u32 speed);
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h
new file mode 100644
index 000000000000..e78e92753d73
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __MLX5E_EN_REPORTER_H
+#define __MLX5E_EN_REPORTER_H
+
+#include <linux/mlx5/driver.h>
+#include "en.h"
+
+int mlx5e_tx_reporter_create(struct mlx5e_priv *priv);
+void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv);
+void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq);
+int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq);
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
new file mode 100644
index 000000000000..9d38e62cdf24
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
@@ -0,0 +1,309 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#include <net/devlink.h>
+#include "reporter.h"
+#include "lib/eq.h"
+
+#define MLX5E_TX_REPORTER_PER_SQ_MAX_LEN 256
+
+struct mlx5e_tx_err_ctx {
+ int (*recover)(struct mlx5e_txqsq *sq);
+ struct mlx5e_txqsq *sq;
+};
+
+static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
+{
+ unsigned long exp_time = jiffies + msecs_to_jiffies(2000);
+
+ while (time_before(jiffies, exp_time)) {
+ if (sq->cc == sq->pc)
+ return 0;
+
+ msleep(20);
+ }
+
+ netdev_err(sq->channel->netdev,
+ "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n",
+ sq->sqn, sq->cc, sq->pc);
+
+ return -ETIMEDOUT;
+}
+
+static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq)
+{
+ WARN_ONCE(sq->cc != sq->pc,
+ "SQ 0x%x: cc (0x%x) != pc (0x%x)\n",
+ sq->sqn, sq->cc, sq->pc);
+ sq->cc = 0;
+ sq->dma_fifo_cc = 0;
+ sq->pc = 0;
+}
+
+static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state)
+{
+ struct mlx5_core_dev *mdev = sq->channel->mdev;
+ struct net_device *dev = sq->channel->netdev;
+ struct mlx5e_modify_sq_param msp = {0};
+ int err;
+
+ msp.curr_state = curr_state;
+ msp.next_state = MLX5_SQC_STATE_RST;
+
+ err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
+ if (err) {
+ netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn);
+ return err;
+ }
+
+ memset(&msp, 0, sizeof(msp));
+ msp.curr_state = MLX5_SQC_STATE_RST;
+ msp.next_state = MLX5_SQC_STATE_RDY;
+
+ err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
+ if (err) {
+ netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn);
+ return err;
+ }
+
+ return 0;
+}
+
+static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
+{
+ struct mlx5_core_dev *mdev = sq->channel->mdev;
+ struct net_device *dev = sq->channel->netdev;
+ u8 state;
+ int err;
+
+ if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
+ return 0;
+
+ err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
+ if (err) {
+ netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
+ sq->sqn, err);
+ return err;
+ }
+
+ if (state != MLX5_SQC_STATE_ERR) {
+ netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
+ return -EINVAL;
+ }
+
+ mlx5e_tx_disable_queue(sq->txq);
+
+ err = mlx5e_wait_for_sq_flush(sq);
+ if (err)
+ return err;
+
+ /* At this point, no new packets will arrive from the stack as TXQ is
+ * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
+ * pending WQEs. SQ can safely reset the SQ.
+ */
+
+ err = mlx5e_sq_to_ready(sq, state);
+ if (err)
+ return err;
+
+ mlx5e_reset_txqsq_cc_pc(sq);
+ sq->stats->recover++;
+ mlx5e_activate_txqsq(sq);
+
+ return 0;
+}
+
+static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter,
+ char *err_str,
+ struct mlx5e_tx_err_ctx *err_ctx)
+{
+ if (IS_ERR_OR_NULL(tx_reporter)) {
+ netdev_err(err_ctx->sq->channel->netdev, err_str);
+ return err_ctx->recover(err_ctx->sq);
+ }
+
+ return devlink_health_report(tx_reporter, err_str, err_ctx);
+}
+
+void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq)
+{
+ char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN];
+ struct mlx5e_tx_err_ctx err_ctx = {0};
+
+ err_ctx.sq = sq;
+ err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover;
+ sprintf(err_str, "ERR CQE on SQ: 0x%x", sq->sqn);
+
+ mlx5_tx_health_report(sq->channel->priv->tx_reporter, err_str,
+ &err_ctx);
+}
+
+static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq)
+{
+ struct mlx5_eq_comp *eq = sq->cq.mcq.eq;
+ u32 eqe_count;
+ int ret;
+
+ netdev_err(sq->channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
+ eq->core.eqn, eq->core.cons_index, eq->core.irqn);
+
+ eqe_count = mlx5_eq_poll_irq_disabled(eq);
+ ret = eqe_count ? false : true;
+ if (!eqe_count) {
+ clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
+ return ret;
+ }
+
+ netdev_err(sq->channel->netdev, "Recover %d eqes on EQ 0x%x\n",
+ eqe_count, eq->core.eqn);
+ sq->channel->stats->eq_rearm++;
+ return ret;
+}
+
+int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq)
+{
+ char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN];
+ struct mlx5e_tx_err_ctx err_ctx;
+
+ err_ctx.sq = sq;
+ err_ctx.recover = mlx5e_tx_reporter_timeout_recover;
+ sprintf(err_str,
+ "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n",
+ sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
+ jiffies_to_usecs(jiffies - sq->txq->trans_start));
+
+ return mlx5_tx_health_report(sq->channel->priv->tx_reporter, err_str,
+ &err_ctx);
+}
+
+/* state lock cannot be grabbed within this function.
+ * It can cause a dead lock or a read-after-free.
+ */
+static int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx)
+{
+ return err_ctx->recover(err_ctx->sq);
+}
+
+static int mlx5e_tx_reporter_recover_all(struct mlx5e_priv *priv)
+{
+ int err;
+
+ rtnl_lock();
+ mutex_lock(&priv->state_lock);
+ mlx5e_close_locked(priv->netdev);
+ err = mlx5e_open_locked(priv->netdev);
+ mutex_unlock(&priv->state_lock);
+ rtnl_unlock();
+
+ return err;
+}
+
+static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter,
+ void *context)
+{
+ struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
+ struct mlx5e_tx_err_ctx *err_ctx = context;
+
+ return err_ctx ? mlx5e_tx_reporter_recover_from_ctx(err_ctx) :
+ mlx5e_tx_reporter_recover_all(priv);
+}
+
+static int
+mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
+ u32 sqn, u8 state, bool stopped)
+{
+ int err;
+
+ err = devlink_fmsg_obj_nest_start(fmsg);
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u32_pair_put(fmsg, "sqn", sqn);
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u8_pair_put(fmsg, "HW state", state);
+ if (err)
+ return err;
+
+ err = devlink_fmsg_bool_pair_put(fmsg, "stopped", stopped);
+ if (err)
+ return err;
+
+ err = devlink_fmsg_obj_nest_end(fmsg);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
+ struct devlink_fmsg *fmsg)
+{
+ struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
+ int i, err = 0;
+
+ mutex_lock(&priv->state_lock);
+
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
+ goto unlock;
+
+ err = devlink_fmsg_arr_pair_nest_start(fmsg, "SQs");
+ if (err)
+ goto unlock;
+
+ for (i = 0; i < priv->channels.num * priv->channels.params.num_tc;
+ i++) {
+ struct mlx5e_txqsq *sq = priv->txq2sq[i];
+ u8 state;
+
+ err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state);
+ if (err)
+ break;
+
+ err = mlx5e_tx_reporter_build_diagnose_output(fmsg, sq->sqn,
+ state,
+ netif_xmit_stopped(sq->txq));
+ if (err)
+ break;
+ }
+ err = devlink_fmsg_arr_pair_nest_end(fmsg);
+ if (err)
+ goto unlock;
+
+unlock:
+ mutex_unlock(&priv->state_lock);
+ return err;
+}
+
+static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = {
+ .name = "tx",
+ .recover = mlx5e_tx_reporter_recover,
+ .diagnose = mlx5e_tx_reporter_diagnose,
+};
+
+#define MLX5_REPORTER_TX_GRACEFUL_PERIOD 500
+
+int mlx5e_tx_reporter_create(struct mlx5e_priv *priv)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct devlink *devlink = priv_to_devlink(mdev);
+
+ priv->tx_reporter =
+ devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops,
+ MLX5_REPORTER_TX_GRACEFUL_PERIOD,
+ true, priv);
+ if (IS_ERR(priv->tx_reporter))
+ netdev_warn(priv->netdev,
+ "Failed to create tx reporter, err = %ld\n",
+ PTR_ERR(priv->tx_reporter));
+ return IS_ERR_OR_NULL(priv->tx_reporter);
+}
+
+void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv)
+{
+ if (IS_ERR_OR_NULL(priv->tx_reporter))
+ return;
+
+ devlink_health_reporter_destroy(priv->tx_reporter);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
index 046948ead152..fa2a3c444cdc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -25,7 +25,7 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv,
/* if the egress device isn't on the same HW e-switch or
* it's a LAG device, use the uplink
*/
- if (!switchdev_port_same_parent_id(priv->netdev, dev) ||
+ if (!netdev_port_same_parent_id(priv->netdev, dev) ||
dst_is_lag_dev) {
*route_dev = uplink_dev;
*out_dev = *route_dev;
@@ -54,12 +54,24 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
struct neighbour *n = NULL;
#if IS_ENABLED(CONFIG_INET)
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct net_device *uplink_dev;
int ret;
+ if (mlx5_lag_is_multipath(mdev)) {
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
+
+ uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
+ fl4->flowi4_oif = uplink_dev->ifindex;
+ }
+
rt = ip_route_output_key(dev_net(mirred_dev), fl4);
ret = PTR_ERR_OR_ZERO(rt);
if (ret)
return ret;
+
+ if (mlx5_lag_is_multipath(mdev) && !rt->rt_gateway)
+ return -ENETUNREACH;
#else
return -EOPNOTSUPP;
#endif
@@ -256,6 +268,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
e->m_neigh.family = n->ops->family;
memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
e->out_dev = out_dev;
+ e->route_dev = route_dev;
/* It's important to add the neigh to the hash table before checking
* the neigh validity state. So if we'll get a notification, in case the
@@ -294,7 +307,9 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
if (!(nud_state & NUD_VALID)) {
neigh_event_send(n, NULL);
- err = -EAGAIN;
+ /* the encap entry will be made valid on neigh update event
+ * and not used before that.
+ */
goto out;
}
@@ -369,6 +384,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
e->m_neigh.family = n->ops->family;
memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
e->out_dev = out_dev;
+ e->route_dev = route_dev;
/* It's importent to add the neigh to the hash table before checking
* the neigh validity state. So if we'll get a notification, in case the
@@ -406,7 +422,9 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
if (!(nud_state & NUD_VALID)) {
neigh_event_send(n, NULL);
- err = -EAGAIN;
+ /* the encap entry will be made valid on neigh update event
+ * and not used before that.
+ */
goto out;
}
@@ -496,25 +514,21 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv,
void *headers_c,
void *headers_v)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
struct netlink_ext_ack *extack = f->common.extack;
- struct flow_dissector_key_ports *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_PORTS,
- f->key);
- struct flow_dissector_key_ports *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_PORTS,
- f->mask);
void *misc_c = MLX5_ADDR_OF(fte_match_param,
spec->match_criteria,
misc_parameters);
void *misc_v = MLX5_ADDR_OF(fte_match_param,
spec->match_value,
misc_parameters);
+ struct flow_match_ports enc_ports;
+
+ flow_rule_match_enc_ports(rule, &enc_ports);
/* Full udp dst port must be given */
- if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS) ||
- memchr_inv(&mask->dst, 0xff, sizeof(mask->dst))) {
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS) ||
+ memchr_inv(&enc_ports.mask->dst, 0xff, sizeof(enc_ports.mask->dst))) {
NL_SET_ERR_MSG_MOD(extack,
"VXLAN decap filter must include enc_dst_port condition");
netdev_warn(priv->netdev,
@@ -523,12 +537,12 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv,
}
/* udp dst port must be knonwn as a VXLAN port */
- if (!mlx5_vxlan_lookup_port(priv->mdev->vxlan, be16_to_cpu(key->dst))) {
+ if (!mlx5_vxlan_lookup_port(priv->mdev->vxlan, be16_to_cpu(enc_ports.key->dst))) {
NL_SET_ERR_MSG_MOD(extack,
"Matched UDP port is not registered as a VXLAN port");
netdev_warn(priv->netdev,
"UDP port %d is not registered as a VXLAN port\n",
- be16_to_cpu(key->dst));
+ be16_to_cpu(enc_ports.key->dst));
return -EOPNOTSUPP;
}
@@ -536,26 +550,26 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv,
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport, ntohs(mask->dst));
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, ntohs(key->dst));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport,
+ ntohs(enc_ports.mask->dst));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
+ ntohs(enc_ports.key->dst));
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport, ntohs(mask->src));
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, ntohs(key->src));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport,
+ ntohs(enc_ports.mask->src));
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
+ ntohs(enc_ports.key->src));
/* match on VNI */
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->key);
- struct flow_dissector_key_keyid *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid enc_keyid;
+
+ flow_rule_match_enc_keyid(rule, &enc_keyid);
+
MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni,
- be32_to_cpu(mask->keyid));
+ be32_to_cpu(enc_keyid.mask->keyid));
MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni,
- be32_to_cpu(key->keyid));
+ be32_to_cpu(enc_keyid.key->keyid));
}
return 0;
}
@@ -570,6 +584,7 @@ static int mlx5e_tc_tun_parse_gretap(struct mlx5e_priv *priv,
misc_parameters);
void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
misc_parameters);
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
if (!MLX5_CAP_ESW(priv->mdev, nvgre_encap_decap)) {
NL_SET_ERR_MSG_MOD(f->common.extack,
@@ -587,21 +602,14 @@ static int mlx5e_tc_tun_parse_gretap(struct mlx5e_priv *priv,
MLX5_SET(fte_match_set_misc, misc_v, gre_protocol, ETH_P_TEB);
/* gre key */
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *mask = NULL;
- struct flow_dissector_key_keyid *key = NULL;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid enc_keyid;
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->mask);
+ flow_rule_match_enc_keyid(rule, &enc_keyid);
MLX5_SET(fte_match_set_misc, misc_c,
- gre_key.key, be32_to_cpu(mask->keyid));
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->key);
+ gre_key.key, be32_to_cpu(enc_keyid.mask->keyid));
MLX5_SET(fte_match_set_misc, misc_v,
- gre_key.key, be32_to_cpu(key->keyid));
+ gre_key.key, be32_to_cpu(enc_keyid.key->keyid));
}
return 0;
@@ -612,16 +620,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f,
void *headers_c,
- void *headers_v)
+ void *headers_v, u8 *match_level)
{
int tunnel_type;
int err = 0;
tunnel_type = mlx5e_tc_tun_get_type(filter_dev);
if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
+ *match_level = MLX5_MATCH_L4;
err = mlx5e_tc_tun_parse_vxlan(priv, spec, f,
headers_c, headers_v);
} else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) {
+ *match_level = MLX5_MATCH_L3;
err = mlx5e_tc_tun_parse_gretap(priv, spec, f,
headers_c, headers_v);
} else {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
index 706ce7bf15e7..b63f15de899d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f,
void *headers_c,
- void *headers_v);
+ void *headers_v, u8 *match_level);
#endif //__MLX5_EN_TC_TUNNEL_H__
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index 3740177eed09..03b2a9f9c589 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -365,7 +365,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
int sq_num;
int i;
- if (unlikely(!test_bit(MLX5E_STATE_OPENED, &priv->state)))
+ /* this flag is sufficient, no need to test internal sq state */
+ if (unlikely(!mlx5e_xdp_tx_is_enabled(priv)))
return -ENETDOWN;
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
@@ -378,9 +379,6 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
sq = &priv->channels.c[sq_num]->xdpsq;
- if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
- return -ENETDOWN;
-
for (i = 0; i < n; i++) {
struct xdp_frame *xdpf = frames[i];
struct mlx5e_xdp_info xdpi;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
index 3a67cb3cd179..ee27a7c8cd87 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
@@ -50,6 +50,23 @@ void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq);
int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
u32 flags);
+static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
+{
+ set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
+static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
+{
+ clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+ /* let other device's napi(s) see our new state */
+ synchronize_rcu();
+}
+
+static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
+{
+ return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
{
if (sq->doorbell_cseg) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 722998d68564..554672edf8c3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -1126,9 +1126,7 @@ static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv)
priv->channels.params.tx_min_inline_mode)
goto out;
- if (mlx5e_open_channels(priv, &new_channels))
- goto out;
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
+ mlx5e_safe_switch_channels(priv, &new_channels, NULL);
out:
mutex_unlock(&priv->state_lock);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index c9df08133718..0804b478ad19 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -63,76 +63,147 @@ struct ptys2ethtool_config {
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);
};
-static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER];
+static
+struct ptys2ethtool_config ptys2legacy_ethtool_table[MLX5E_LINK_MODES_NUMBER];
+static
+struct ptys2ethtool_config ptys2ext_ethtool_table[MLX5E_EXT_LINK_MODES_NUMBER];
-#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, ...) \
+#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, table, ...) \
({ \
struct ptys2ethtool_config *cfg; \
const unsigned int modes[] = { __VA_ARGS__ }; \
- unsigned int i; \
- cfg = &ptys2ethtool_table[reg_]; \
+ unsigned int i, bit, idx; \
+ cfg = &ptys2##table##_ethtool_table[reg_]; \
bitmap_zero(cfg->supported, \
__ETHTOOL_LINK_MODE_MASK_NBITS); \
bitmap_zero(cfg->advertised, \
__ETHTOOL_LINK_MODE_MASK_NBITS); \
for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \
- __set_bit(modes[i], cfg->supported); \
- __set_bit(modes[i], cfg->advertised); \
+ bit = modes[i] % 64; \
+ idx = modes[i] / 64; \
+ __set_bit(bit, &cfg->supported[idx]); \
+ __set_bit(bit, &cfg->advertised[idx]); \
} \
})
void mlx5e_build_ptys2ethtool_map(void)
{
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII,
+ memset(ptys2legacy_ethtool_table, 0, sizeof(ptys2legacy_ethtool_table));
+ memset(ptys2ext_ethtool_table, 0, sizeof(ptys2ext_ethtool_table));
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, legacy,
ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, legacy,
ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, legacy,
ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, legacy,
ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, legacy,
ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, legacy,
ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, legacy,
ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, legacy,
ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, legacy,
ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, legacy,
ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, legacy,
ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, legacy,
ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, legacy,
ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, legacy,
ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, legacy,
ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, legacy,
ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, legacy,
ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, legacy,
ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, legacy,
ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, legacy,
ETHTOOL_LINK_MODE_10000baseT_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, legacy,
ETHTOOL_LINK_MODE_25000baseCR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, legacy,
ETHTOOL_LINK_MODE_25000baseKR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, legacy,
ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, legacy,
ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT);
- MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2,
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, legacy,
ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_SGMII_100M, ext,
+ ETHTOOL_LINK_MODE_100baseT_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_X_SGMII, ext,
+ ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_5GBASE_R, ext,
+ ETHTOOL_LINK_MODE_5000baseT_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_XFI_XAUI_1, ext,
+ ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseER_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_XLAUI_4_XLPPI_4, ext,
+ ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GAUI_1_25GBASE_CR_KR, ext,
+ ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
+ ext,
+ ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR, ext,
+ ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseDR_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_CAUI_4_100GBASE_CR4_KR4, ext,
+ ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GAUI_2_100GBASE_CR2_KR2, ext,
+ ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT);
+ MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_200GAUI_4_200GBASE_CR4_KR4, ext,
+ ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT);
+}
+
+static void mlx5e_ethtool_get_speed_arr(struct mlx5_core_dev *mdev,
+ struct ptys2ethtool_config **arr,
+ u32 *size)
+{
+ bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+
+ *arr = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
+ *size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
+ ARRAY_SIZE(ptys2legacy_ethtool_table);
}
typedef int (*mlx5e_pflag_handler)(struct net_device *netdev, bool enable);
@@ -298,11 +369,7 @@ int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv,
goto unlock;
}
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- goto unlock;
-
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
unlock:
mutex_unlock(&priv->state_lock);
@@ -354,32 +421,29 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
new_channels.params = priv->channels.params;
new_channels.params.num_channels = count;
- if (!netif_is_rxfh_configured(priv->netdev))
- mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
- MLX5E_INDIR_RQT_SIZE, count);
if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
priv->channels.params = new_channels.params;
goto out;
}
- /* Create fresh channels with new parameters */
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- goto out;
-
arfs_enabled = priv->netdev->features & NETIF_F_NTUPLE;
if (arfs_enabled)
mlx5e_arfs_disable(priv);
+ if (!netif_is_rxfh_configured(priv->netdev))
+ mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
+ MLX5E_INDIR_RQT_SIZE, count);
+
/* Switch to new channels, set new parameters and close old ones */
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
if (arfs_enabled) {
- err = mlx5e_arfs_enable(priv);
- if (err)
+ int err2 = mlx5e_arfs_enable(priv);
+
+ if (err2)
netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n",
- __func__, err);
+ __func__, err2);
}
out:
@@ -505,12 +569,7 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
goto out;
}
- /* open fresh channels with new coal parameters */
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- goto out;
-
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
out:
mutex_unlock(&priv->state_lock);
@@ -525,27 +584,35 @@ static int mlx5e_set_coalesce(struct net_device *netdev,
return mlx5e_ethtool_set_coalesce(priv, coal);
}
-static void ptys2ethtool_supported_link(unsigned long *supported_modes,
+static void ptys2ethtool_supported_link(struct mlx5_core_dev *mdev,
+ unsigned long *supported_modes,
u32 eth_proto_cap)
{
unsigned long proto_cap = eth_proto_cap;
+ struct ptys2ethtool_config *table;
+ u32 max_size;
int proto;
- for_each_set_bit(proto, &proto_cap, MLX5E_LINK_MODES_NUMBER)
+ mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size);
+ for_each_set_bit(proto, &proto_cap, max_size)
bitmap_or(supported_modes, supported_modes,
- ptys2ethtool_table[proto].supported,
+ table[proto].supported,
__ETHTOOL_LINK_MODE_MASK_NBITS);
}
-static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
+static void ptys2ethtool_adver_link(struct mlx5_core_dev *mdev,
+ unsigned long *advertising_modes,
u32 eth_proto_cap)
{
unsigned long proto_cap = eth_proto_cap;
+ struct ptys2ethtool_config *table;
+ u32 max_size;
int proto;
- for_each_set_bit(proto, &proto_cap, MLX5E_LINK_MODES_NUMBER)
+ mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size);
+ for_each_set_bit(proto, &proto_cap, max_size)
bitmap_or(advertising_modes, advertising_modes,
- ptys2ethtool_table[proto].advertised,
+ table[proto].advertised,
__ETHTOOL_LINK_MODE_MASK_NBITS);
}
@@ -695,13 +762,14 @@ static void get_speed_duplex(struct net_device *netdev,
u32 eth_proto_oper,
struct ethtool_link_ksettings *link_ksettings)
{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
u32 speed = SPEED_UNKNOWN;
u8 duplex = DUPLEX_UNKNOWN;
if (!netif_carrier_ok(netdev))
goto out;
- speed = mlx5e_port_ptys2speed(eth_proto_oper);
+ speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
if (!speed) {
speed = SPEED_UNKNOWN;
goto out;
@@ -714,22 +782,22 @@ out:
link_ksettings->base.duplex = duplex;
}
-static void get_supported(u32 eth_proto_cap,
+static void get_supported(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
struct ethtool_link_ksettings *link_ksettings)
{
unsigned long *supported = link_ksettings->link_modes.supported;
+ ptys2ethtool_supported_link(mdev, supported, eth_proto_cap);
- ptys2ethtool_supported_link(supported, eth_proto_cap);
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
}
-static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
- u8 rx_pause,
+static void get_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
+ u8 tx_pause, u8 rx_pause,
struct ethtool_link_ksettings *link_ksettings)
{
unsigned long *advertising = link_ksettings->link_modes.advertising;
+ ptys2ethtool_adver_link(mdev, advertising, eth_proto_cap);
- ptys2ethtool_adver_link(advertising, eth_proto_cap);
if (rx_pause)
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
if (tx_pause ^ rx_pause)
@@ -779,12 +847,12 @@ static u8 get_connector_port(u32 eth_proto, u8 connector_type)
return PORT_OTHER;
}
-static void get_lp_advertising(u32 eth_proto_lp,
+static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
struct ethtool_link_ksettings *link_ksettings)
{
unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
- ptys2ethtool_adver_link(lp_advertising, eth_proto_lp);
+ ptys2ethtool_adver_link(mdev, lp_advertising, eth_proto_lp);
}
int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
@@ -801,6 +869,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
u8 an_disable_admin;
u8 an_status;
u8 connector_type;
+ bool ext;
int err;
err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
@@ -809,22 +878,25 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
__func__, err);
goto err_query_regs;
}
-
- eth_proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
- eth_proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
- eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
- eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
- an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
- an_status = MLX5_GET(ptys_reg, out, an_status);
- connector_type = MLX5_GET(ptys_reg, out, connector_type);
+ ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+ eth_proto_cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+ eth_proto_capability);
+ eth_proto_admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+ eth_proto_admin);
+ eth_proto_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+ eth_proto_oper);
+ eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
+ an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
+ an_status = MLX5_GET(ptys_reg, out, an_status);
+ connector_type = MLX5_GET(ptys_reg, out, connector_type);
mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
- get_supported(eth_proto_cap, link_ksettings);
- get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);
+ get_supported(mdev, eth_proto_cap, link_ksettings);
+ get_advertising(mdev, eth_proto_admin, tx_pause, rx_pause, link_ksettings);
get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
@@ -833,7 +905,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
connector_type);
ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin,
connector_type);
- get_lp_advertising(eth_proto_lp, link_ksettings);
+ get_lp_advertising(mdev, eth_proto_lp, link_ksettings);
if (an_status == MLX5_AN_COMPLETE)
ethtool_link_ksettings_add_link_mode(link_ksettings,
@@ -844,9 +916,12 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
Autoneg);
- if (get_fec_supported_advertised(mdev, link_ksettings))
+ err = get_fec_supported_advertised(mdev, link_ksettings);
+ if (err) {
netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n",
__func__, err);
+ err = 0; /* don't fail caps query because of FEC error */
+ }
if (!an_disable_admin)
ethtool_link_ksettings_add_link_mode(link_ksettings,
@@ -869,7 +944,9 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
u32 i, ptys_modes = 0;
for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
- if (bitmap_intersects(ptys2ethtool_table[i].advertised,
+ if (*ptys2legacy_ethtool_table[i].advertised == 0)
+ continue;
+ if (bitmap_intersects(ptys2legacy_ethtool_table[i].advertised,
link_modes,
__ETHTOOL_LINK_MODE_MASK_NBITS))
ptys_modes |= MLX5E_PROT_MASK(i);
@@ -878,13 +955,34 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
return ptys_modes;
}
+static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
+{
+ u32 i, ptys_modes = 0;
+ unsigned long modes[2];
+
+ for (i = 0; i < MLX5E_EXT_LINK_MODES_NUMBER; ++i) {
+ if (*ptys2ext_ethtool_table[i].advertised == 0)
+ continue;
+ memset(modes, 0, sizeof(modes));
+ bitmap_and(modes, ptys2ext_ethtool_table[i].advertised,
+ link_modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
+
+ if (modes[0] == ptys2ext_ethtool_table[i].advertised[0] &&
+ modes[1] == ptys2ext_ethtool_table[i].advertised[1])
+ ptys_modes |= MLX5E_PROT_MASK(i);
+ }
+ return ptys_modes;
+}
+
int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
const struct ethtool_link_ksettings *link_ksettings)
{
struct mlx5_core_dev *mdev = priv->mdev;
- u32 eth_proto_cap, eth_proto_admin;
+ struct mlx5e_port_eth_proto eproto;
bool an_changes = false;
u8 an_disable_admin;
+ bool ext_supported;
+ bool ext_requested;
u8 an_disable_cap;
bool an_disable;
u32 link_modes;
@@ -892,20 +990,33 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
u32 speed;
int err;
- speed = link_ksettings->base.speed;
+ u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
- link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
- mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) :
- mlx5e_port_speed2linkmodes(speed);
+#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
- err = mlx5_query_port_proto_cap(mdev, &eth_proto_cap, MLX5_PTYS_EN);
+ ext_requested = (link_ksettings->link_modes.advertising[0] >
+ MLX5E_PTYS_EXT);
+ ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+
+ /*when ptys_extended_ethernet is set legacy link modes are deprecated */
+ if (ext_requested != ext_supported)
+ return -EPROTONOSUPPORT;
+
+ speed = link_ksettings->base.speed;
+ ethtool2ptys_adver_func = ext_requested ?
+ mlx5e_ethtool2ptys_ext_adver_link :
+ mlx5e_ethtool2ptys_adver_link;
+ err = mlx5_port_query_eth_proto(mdev, 1, ext_supported, &eproto);
if (err) {
- netdev_err(priv->netdev, "%s: query port eth proto cap failed: %d\n",
+ netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
__func__, err);
goto out;
}
+ link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
+ ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) :
+ mlx5e_port_speed2linkmodes(mdev, speed);
- link_modes = link_modes & eth_proto_cap;
+ link_modes = link_modes & eproto.cap;
if (!link_modes) {
netdev_err(priv->netdev, "%s: Not supported link mode(s) requested",
__func__);
@@ -913,24 +1024,17 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
goto out;
}
- err = mlx5_query_port_proto_admin(mdev, &eth_proto_admin, MLX5_PTYS_EN);
- if (err) {
- netdev_err(priv->netdev, "%s: query port eth proto admin failed: %d\n",
- __func__, err);
- goto out;
- }
-
- mlx5_query_port_autoneg(mdev, MLX5_PTYS_EN, &an_status,
- &an_disable_cap, &an_disable_admin);
+ mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
+ &an_disable_admin);
an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE;
an_changes = ((!an_disable && an_disable_admin) ||
(an_disable && !an_disable_admin));
- if (!an_changes && link_modes == eth_proto_admin)
+ if (!an_changes && link_modes == eproto.admin)
goto out;
- mlx5_set_port_ptys(mdev, an_disable, link_modes, MLX5_PTYS_EN);
+ mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_supported);
mlx5_toggle_port_link(mdev);
out:
@@ -1518,7 +1622,6 @@ static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
struct mlx5e_channels new_channels = {};
bool mode_changed;
u8 cq_period_mode, current_cq_period_mode;
- int err = 0;
cq_period_mode = enable ?
MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
@@ -1546,12 +1649,7 @@ static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
return 0;
}
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- return err;
-
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
- return 0;
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL);
}
static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
@@ -1584,11 +1682,10 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
return 0;
}
- err = mlx5e_open_channels(priv, &new_channels);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
if (err)
return err;
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n",
MLX5E_GET_PFLAG(&priv->channels.params,
MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
@@ -1621,7 +1718,6 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
- int err;
if (enable) {
if (!mlx5e_check_fragmented_striding_rq_cap(mdev))
@@ -1643,12 +1739,7 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
return 0;
}
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- return err;
-
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
- return 0;
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL);
}
static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
@@ -1691,12 +1782,8 @@ static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable)
return 0;
}
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- return err;
-
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
- return 0;
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+ return err;
}
static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 8cfd2ec7c0a2..b5fdbd3190d9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -35,6 +35,7 @@
#include <linux/mlx5/fs.h>
#include <net/vxlan.h>
#include <linux/bpf.h>
+#include <linux/if_bridge.h>
#include <net/page_pool.h>
#include "eswitch.h"
#include "en.h"
@@ -51,6 +52,7 @@
#include "en/xdp.h"
#include "lib/eq.h"
#include "en/monitor_stats.h"
+#include "en/reporter.h"
struct mlx5e_rq_param {
u32 rqc[MLX5_ST_SZ_DW(rqc)];
@@ -171,8 +173,7 @@ static u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev,
if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params))
return order_base_2(mlx5e_rx_get_linear_frag_sz(params));
- return MLX5E_MPWQE_STRIDE_SZ(mdev,
- MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS));
+ return MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev);
}
static u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev,
@@ -950,7 +951,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
if (params->rx_dim_enabled)
__set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
- if (params->pflags & MLX5E_PFLAG_RX_NO_CSUM_COMPLETE)
+ if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_NO_CSUM_COMPLETE))
__set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
return 0;
@@ -1160,7 +1161,7 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
return 0;
}
-static void mlx5e_sq_recover(struct work_struct *work);
+static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work);
static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
int txq_ix,
struct mlx5e_params *params,
@@ -1182,7 +1183,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
sq->uar_map = mdev->mlx5e_res.bfreg.map;
sq->min_inline_mode = params->tx_min_inline_mode;
sq->stats = &c->priv->channel_stats[c->ix].sq[tc];
- INIT_WORK(&sq->recover.recover_work, mlx5e_sq_recover);
+ INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work);
if (MLX5_IPSEC_DEV(c->priv->mdev))
set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state);
if (mlx5_accel_is_tls_device(c->priv->mdev))
@@ -1270,15 +1271,8 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
return err;
}
-struct mlx5e_modify_sq_param {
- int curr_state;
- int next_state;
- bool rl_update;
- int rl_index;
-};
-
-static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
- struct mlx5e_modify_sq_param *p)
+int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
+ struct mlx5e_modify_sq_param *p)
{
void *in;
void *sqc;
@@ -1376,17 +1370,7 @@ err_free_txqsq:
return err;
}
-static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq)
-{
- WARN_ONCE(sq->cc != sq->pc,
- "SQ 0x%x: cc (0x%x) != pc (0x%x)\n",
- sq->sqn, sq->cc, sq->pc);
- sq->cc = 0;
- sq->dma_fifo_cc = 0;
- sq->pc = 0;
-}
-
-static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
+void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
{
sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
@@ -1395,7 +1379,7 @@ static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
netif_tx_start_queue(sq->txq);
}
-static inline void netif_tx_disable_queue(struct netdev_queue *txq)
+void mlx5e_tx_disable_queue(struct netdev_queue *txq)
{
__netif_tx_lock_bh(txq);
netif_tx_stop_queue(txq);
@@ -1411,7 +1395,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
/* prevent netif_tx_wake_queue */
napi_synchronize(&c->napi);
- netif_tx_disable_queue(sq->txq);
+ mlx5e_tx_disable_queue(sq->txq);
/* last doorbell out, godspeed .. */
if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) {
@@ -1431,6 +1415,7 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
struct mlx5_rate_limit rl = {0};
cancel_work_sync(&sq->dim.work);
+ cancel_work_sync(&sq->recover_work);
mlx5e_destroy_sq(mdev, sq->sqn);
if (sq->rate_limit) {
rl.rate = sq->rate_limit;
@@ -1440,105 +1425,12 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
mlx5e_free_txqsq(sq);
}
-static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
-{
- unsigned long exp_time = jiffies + msecs_to_jiffies(2000);
-
- while (time_before(jiffies, exp_time)) {
- if (sq->cc == sq->pc)
- return 0;
-
- msleep(20);
- }
-
- netdev_err(sq->channel->netdev,
- "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n",
- sq->sqn, sq->cc, sq->pc);
-
- return -ETIMEDOUT;
-}
-
-static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state)
-{
- struct mlx5_core_dev *mdev = sq->channel->mdev;
- struct net_device *dev = sq->channel->netdev;
- struct mlx5e_modify_sq_param msp = {0};
- int err;
-
- msp.curr_state = curr_state;
- msp.next_state = MLX5_SQC_STATE_RST;
-
- err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
- if (err) {
- netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn);
- return err;
- }
-
- memset(&msp, 0, sizeof(msp));
- msp.curr_state = MLX5_SQC_STATE_RST;
- msp.next_state = MLX5_SQC_STATE_RDY;
-
- err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
- if (err) {
- netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn);
- return err;
- }
-
- return 0;
-}
-
-static void mlx5e_sq_recover(struct work_struct *work)
+static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work)
{
- struct mlx5e_txqsq_recover *recover =
- container_of(work, struct mlx5e_txqsq_recover,
- recover_work);
- struct mlx5e_txqsq *sq = container_of(recover, struct mlx5e_txqsq,
- recover);
- struct mlx5_core_dev *mdev = sq->channel->mdev;
- struct net_device *dev = sq->channel->netdev;
- u8 state;
- int err;
-
- err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
- if (err) {
- netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
- sq->sqn, err);
- return;
- }
-
- if (state != MLX5_RQC_STATE_ERR) {
- netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
- return;
- }
-
- netif_tx_disable_queue(sq->txq);
+ struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq,
+ recover_work);
- if (mlx5e_wait_for_sq_flush(sq))
- return;
-
- /* If the interval between two consecutive recovers per SQ is too
- * short, don't recover to avoid infinite loop of ERR_CQE -> recover.
- * If we reached this state, there is probably a bug that needs to be
- * fixed. let's keep the queue close and let tx timeout cleanup.
- */
- if (jiffies_to_msecs(jiffies - recover->last_recover) <
- MLX5E_SQ_RECOVER_MIN_INTERVAL) {
- netdev_err(dev, "Recover SQ 0x%x canceled, too many error CQEs\n",
- sq->sqn);
- return;
- }
-
- /* At this point, no new packets will arrive from the stack as TXQ is
- * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
- * pending WQEs. SQ can safely reset the SQ.
- */
- if (mlx5e_sq_to_ready(sq, state))
- return;
-
- mlx5e_reset_txqsq_cc_pc(sq);
- sq->stats->recover++;
- recover->last_recover = jiffies;
- mlx5e_activate_txqsq(sq);
+ mlx5e_tx_reporter_err_cqe(sq);
}
static int mlx5e_open_icosq(struct mlx5e_channel *c,
@@ -1950,6 +1842,29 @@ static int mlx5e_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
return err;
}
+static int mlx5e_alloc_xps_cpumask(struct mlx5e_channel *c,
+ struct mlx5e_params *params)
+{
+ int num_comp_vectors = mlx5_comp_vectors_count(c->mdev);
+ int irq;
+
+ if (!zalloc_cpumask_var(&c->xps_cpumask, GFP_KERNEL))
+ return -ENOMEM;
+
+ for (irq = c->ix; irq < num_comp_vectors; irq += params->num_channels) {
+ int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(c->mdev, irq));
+
+ cpumask_set_cpu(cpu, c->xps_cpumask);
+ }
+
+ return 0;
+}
+
+static void mlx5e_free_xps_cpumask(struct mlx5e_channel *c)
+{
+ free_cpumask_var(c->xps_cpumask);
+}
+
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
struct mlx5e_params *params,
struct mlx5e_channel_param *cparam,
@@ -1982,9 +1897,12 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
c->num_tc = params->num_tc;
c->xdp = !!params->xdp_prog;
c->stats = &priv->channel_stats[ix].ch;
-
c->irq_desc = irq_to_desc(irq);
+ err = mlx5e_alloc_xps_cpumask(c, params);
+ if (err)
+ goto err_free_channel;
+
netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);
err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->icosq.cq);
@@ -2067,6 +1985,9 @@ err_close_icosq_cq:
err_napi_del:
netif_napi_del(&c->napi);
+ mlx5e_free_xps_cpumask(c);
+
+err_free_channel:
kvfree(c);
return err;
@@ -2079,7 +2000,7 @@ static void mlx5e_activate_channel(struct mlx5e_channel *c)
for (tc = 0; tc < c->num_tc; tc++)
mlx5e_activate_txqsq(&c->sq[tc]);
mlx5e_activate_rq(&c->rq);
- netif_set_xps_queue(c->netdev, get_cpu_mask(c->cpu), c->ix);
+ netif_set_xps_queue(c->netdev, c->xps_cpumask, c->ix);
}
static void mlx5e_deactivate_channel(struct mlx5e_channel *c)
@@ -2107,6 +2028,7 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
mlx5e_close_tx_cqs(c);
mlx5e_close_cq(&c->icosq.cq);
netif_napi_del(&c->napi);
+ mlx5e_free_xps_cpumask(c);
kvfree(c);
}
@@ -2380,6 +2302,10 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
goto err_close_channels;
}
+ if (!IS_ERR_OR_NULL(priv->tx_reporter))
+ devlink_health_reporter_state_update(priv->tx_reporter,
+ DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
+
kvfree(cparam);
return 0;
@@ -2938,6 +2864,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
mlx5e_build_tx2sq_maps(priv);
mlx5e_activate_channels(&priv->channels);
+ mlx5e_xdp_tx_enable(priv);
netif_tx_start_all_queues(priv->netdev);
if (mlx5e_is_vport_rep(priv))
@@ -2959,16 +2886,18 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
*/
netif_tx_stop_all_queues(priv->netdev);
netif_tx_disable(priv->netdev);
+ mlx5e_xdp_tx_disable(priv);
mlx5e_deactivate_channels(&priv->channels);
}
-void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
- struct mlx5e_channels *new_chs,
- mlx5e_fp_hw_modify hw_modify)
+static void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
+ struct mlx5e_channels *new_chs,
+ mlx5e_fp_hw_modify hw_modify)
{
struct net_device *netdev = priv->netdev;
int new_num_txqs;
int carrier_ok;
+
new_num_txqs = new_chs->num * new_chs->params.num_tc;
carrier_ok = netif_carrier_ok(netdev);
@@ -2994,6 +2923,20 @@ void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
netif_carrier_on(netdev);
}
+int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
+ struct mlx5e_channels *new_chs,
+ mlx5e_fp_hw_modify hw_modify)
+{
+ int err;
+
+ err = mlx5e_open_channels(priv, new_chs);
+ if (err)
+ return err;
+
+ mlx5e_switch_priv_channels(priv, new_chs, hw_modify);
+ return 0;
+}
+
void mlx5e_timestamp_init(struct mlx5e_priv *priv)
{
priv->tstamp.tx_type = HWTSTAMP_TX_OFF;
@@ -3207,6 +3150,7 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
{
int tc;
+ mlx5e_tx_reporter_destroy(priv);
for (tc = 0; tc < priv->profile->max_tc; tc++)
mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
}
@@ -3409,13 +3353,12 @@ static int mlx5e_setup_tc_mqprio(struct net_device *netdev,
goto out;
}
- err = mlx5e_open_channels(priv, &new_channels);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
if (err)
goto out;
priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
new_channels.params.num_tc);
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
out:
mutex_unlock(&priv->state_lock);
return err;
@@ -3492,11 +3435,32 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
+void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
+{
+ int i;
+
+ for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+ struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i];
+ struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
+ int j;
+
+ s->rx_packets += rq_stats->packets;
+ s->rx_bytes += rq_stats->bytes;
+
+ for (j = 0; j < priv->max_opened_tc; j++) {
+ struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j];
+
+ s->tx_packets += sq_stats->packets;
+ s->tx_bytes += sq_stats->bytes;
+ s->tx_dropped += sq_stats->dropped;
+ }
+ }
+}
+
void
mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
struct mlx5e_priv *priv = netdev_priv(dev);
- struct mlx5e_sw_stats *sstats = &priv->stats.sw;
struct mlx5e_vport_stats *vstats = &priv->stats.vport;
struct mlx5e_pport_stats *pstats = &priv->stats.pport;
@@ -3511,12 +3475,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
stats->tx_bytes = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
} else {
- mlx5e_grp_sw_update_stats(priv);
- stats->rx_packets = sstats->rx_packets;
- stats->rx_bytes = sstats->rx_bytes;
- stats->tx_packets = sstats->tx_packets;
- stats->tx_bytes = sstats->tx_bytes;
- stats->tx_dropped = sstats->tx_queue_dropped;
+ mlx5e_fold_sw_stats64(priv, stats);
}
stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
@@ -3609,11 +3568,7 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
goto out;
}
- err = mlx5e_open_channels(priv, &new_channels);
- if (err)
- goto out;
-
- mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
out:
mutex_unlock(&priv->state_lock);
return err;
@@ -3831,11 +3786,10 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
goto out;
}
- err = mlx5e_open_channels(priv, &new_channels);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, set_mtu_cb);
if (err)
goto out;
- mlx5e_switch_priv_channels(priv, &new_channels, set_mtu_cb);
netdev->mtu = new_channels.params.sw_mtu;
out:
@@ -4178,31 +4132,13 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb,
return features;
}
-static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev,
- struct mlx5e_txqsq *sq)
-{
- struct mlx5_eq_comp *eq = sq->cq.mcq.eq;
- u32 eqe_count;
-
- netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
- eq->core.eqn, eq->core.cons_index, eq->core.irqn);
-
- eqe_count = mlx5_eq_poll_irq_disabled(eq);
- if (!eqe_count)
- return false;
-
- netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->core.eqn);
- sq->channel->stats->eq_rearm++;
- return true;
-}
-
static void mlx5e_tx_timeout_work(struct work_struct *work)
{
struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
tx_timeout_work);
- struct net_device *dev = priv->netdev;
- bool reopen_channels = false;
- int i, err;
+ bool report_failed = false;
+ int err;
+ int i;
rtnl_lock();
mutex_lock(&priv->state_lock);
@@ -4211,31 +4147,22 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
goto unlock;
for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) {
- struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, i);
+ struct netdev_queue *dev_queue =
+ netdev_get_tx_queue(priv->netdev, i);
struct mlx5e_txqsq *sq = priv->txq2sq[i];
if (!netif_xmit_stopped(dev_queue))
continue;
- netdev_err(dev,
- "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n",
- i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
- jiffies_to_usecs(jiffies - dev_queue->trans_start));
-
- /* If we recover a lost interrupt, most likely TX timeout will
- * be resolved, skip reopening channels
- */
- if (!mlx5e_tx_timeout_eq_recover(dev, sq)) {
- clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
- reopen_channels = true;
- }
+ if (mlx5e_tx_reporter_timeout(sq))
+ report_failed = true;
}
- if (!reopen_channels)
+ if (!report_failed)
goto unlock;
- mlx5e_close_locked(dev);
- err = mlx5e_open_locked(dev);
+ mlx5e_close_locked(priv->netdev);
+ err = mlx5e_open_locked(priv->netdev);
if (err)
netdev_err(priv->netdev,
"mlx5e_open_locked failed recovering from a tx_timeout, err(%d).\n",
@@ -4383,6 +4310,61 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
}
}
+#ifdef CONFIG_MLX5_ESWITCH
+static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev, u32 filter_mask,
+ int nlflags)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ u8 mode, setting;
+ int err;
+
+ err = mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting);
+ if (err)
+ return err;
+ mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
+ return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
+ mode,
+ 0, 0, nlflags, filter_mask, NULL);
+}
+
+static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+ u16 flags, struct netlink_ext_ack *extack)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct nlattr *attr, *br_spec;
+ u16 mode = BRIDGE_MODE_UNDEF;
+ u8 setting;
+ int rem;
+
+ br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+ if (!br_spec)
+ return -EINVAL;
+
+ nla_for_each_nested(attr, br_spec, rem) {
+ if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ continue;
+
+ if (nla_len(attr) < sizeof(mode))
+ return -EINVAL;
+
+ mode = nla_get_u16(attr);
+ if (mode > BRIDGE_MODE_VEPA)
+ return -EINVAL;
+
+ break;
+ }
+
+ if (mode == BRIDGE_MODE_UNDEF)
+ return -EINVAL;
+
+ setting = (mode == BRIDGE_MODE_VEPA) ? 1 : 0;
+ return mlx5_eswitch_set_vepa(mdev->priv.eswitch, setting);
+}
+#endif
+
const struct net_device_ops mlx5e_netdev_ops = {
.ndo_open = mlx5e_open,
.ndo_stop = mlx5e_close,
@@ -4409,6 +4391,9 @@ const struct net_device_ops mlx5e_netdev_ops = {
.ndo_rx_flow_steer = mlx5e_rx_flow_steer,
#endif
#ifdef CONFIG_MLX5_ESWITCH
+ .ndo_bridge_setlink = mlx5e_bridge_setlink,
+ .ndo_bridge_getlink = mlx5e_bridge_getlink,
+
/* SRIOV E-Switch NDOs */
.ndo_set_vf_mac = mlx5e_set_vf_mac,
.ndo_set_vf_vlan = mlx5e_set_vf_vlan,
@@ -4908,6 +4893,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
#ifdef CONFIG_MLX5_CORE_EN_DCB
mlx5e_dcbnl_initialize(priv);
#endif
+ mlx5e_tx_reporter_create(priv);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 96cc0c6a4014..a1a3e2774989 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -44,6 +44,7 @@
#include "en_tc.h"
#include "en/tc_tun.h"
#include "fs_core.h"
+#include "lib/port_tun.h"
#define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
@@ -58,7 +59,8 @@ struct mlx5e_rep_indr_block_priv {
struct list_head list;
};
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev);
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+ struct net_device *netdev);
static void mlx5e_rep_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
@@ -152,7 +154,7 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
- if (rep->vport == FDB_UPLINK_VPORT)
+ if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_uplink_rep_update_hw_counters(priv);
else
mlx5e_vf_rep_update_hw_counters(priv);
@@ -161,26 +163,16 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
{
struct mlx5e_sw_stats *s = &priv->stats.sw;
- struct mlx5e_rq_stats *rq_stats;
- struct mlx5e_sq_stats *sq_stats;
- int i, j;
+ struct rtnl_link_stats64 stats64 = {};
memset(s, 0, sizeof(*s));
- for (i = 0; i < priv->channels.num; i++) {
- struct mlx5e_channel *c = priv->channels.c[i];
-
- rq_stats = c->rq.stats;
-
- s->rx_packets += rq_stats->packets;
- s->rx_bytes += rq_stats->bytes;
-
- for (j = 0; j < priv->channels.params.num_tc; j++) {
- sq_stats = c->sq[j].stats;
+ mlx5e_fold_sw_stats64(priv, &stats64);
- s->tx_packets += sq_stats->packets;
- s->tx_bytes += sq_stats->bytes;
- }
- }
+ s->rx_packets = stats64.rx_packets;
+ s->rx_bytes = stats64.rx_bytes;
+ s->tx_packets = stats64.tx_packets;
+ s->tx_bytes = stats64.tx_bytes;
+ s->tx_queue_dropped = stats64.tx_dropped;
}
static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
@@ -193,8 +185,7 @@ static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
return;
mutex_lock(&priv->state_lock);
- if (test_bit(MLX5E_STATE_OPENED, &priv->state))
- mlx5e_rep_update_sw_counters(priv);
+ mlx5e_rep_update_sw_counters(priv);
mlx5e_rep_update_hw_counters(priv);
mutex_unlock(&priv->state_lock);
@@ -391,7 +382,8 @@ static const struct ethtool_ops mlx5e_uplink_rep_ethtool_ops = {
.set_pauseparam = mlx5e_uplink_rep_set_pauseparam,
};
-static int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+static int mlx5e_rep_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -408,20 +400,14 @@ static int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
uplink_priv = netdev_priv(uplink_dev);
}
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = ETH_ALEN;
- if (uplink_upper && mlx5_lag_is_sriov(uplink_priv->mdev)) {
- ether_addr_copy(attr->u.ppid.id, uplink_upper->dev_addr);
- } else {
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
- struct mlx5_eswitch_rep *rep = rpriv->rep;
+ ppid->id_len = ETH_ALEN;
+ if (uplink_upper && mlx5_lag_is_sriov(uplink_priv->mdev)) {
+ ether_addr_copy(ppid->id, uplink_upper->dev_addr);
+ } else {
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
+ struct mlx5_eswitch_rep *rep = rpriv->rep;
- ether_addr_copy(attr->u.ppid.id, rep->hw_id);
- }
- break;
- default:
- return -EOPNOTSUPP;
+ ether_addr_copy(ppid->id, rep->hw_id);
}
return 0;
@@ -594,6 +580,10 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
ether_addr_copy(e->h_dest, ha);
ether_addr_copy(eth->h_dest, ha);
+ /* Update the encap source mac, in case that we delete
+ * the flows when encap source mac changed.
+ */
+ ether_addr_copy(eth->h_source, e->route_dev->dev_addr);
mlx5e_tc_encap_flows_add(priv, e);
}
@@ -663,7 +653,7 @@ static void mlx5e_rep_indr_clean_block_privs(struct mlx5e_rep_priv *rpriv)
struct list_head *head = &rpriv->uplink_priv.tc_indr_block_priv_list;
list_for_each_entry_safe(cb_priv, temp, head, list) {
- mlx5e_rep_indr_unregister_block(cb_priv->netdev);
+ mlx5e_rep_indr_unregister_block(rpriv, cb_priv->netdev);
kfree(cb_priv);
}
}
@@ -735,7 +725,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
err = tcf_block_cb_register(f->block,
mlx5e_rep_indr_setup_block_cb,
- netdev, indr_priv, f->extack);
+ indr_priv, indr_priv, f->extack);
if (err) {
list_del(&indr_priv->list);
kfree(indr_priv);
@@ -743,14 +733,15 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
return err;
case TC_BLOCK_UNBIND:
+ indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
+ if (!indr_priv)
+ return -ENOENT;
+
tcf_block_cb_unregister(f->block,
mlx5e_rep_indr_setup_block_cb,
- netdev);
- indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
- if (indr_priv) {
- list_del(&indr_priv->list);
- kfree(indr_priv);
- }
+ indr_priv);
+ list_del(&indr_priv->list);
+ kfree(indr_priv);
return 0;
default:
@@ -779,7 +770,7 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
err = __tc_indr_block_cb_register(netdev, rpriv,
mlx5e_rep_indr_setup_tc_cb,
- netdev);
+ rpriv);
if (err) {
struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
@@ -789,10 +780,11 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
return err;
}
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev)
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+ struct net_device *netdev)
{
__tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
- netdev);
+ rpriv);
}
static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
@@ -811,7 +803,7 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
mlx5e_rep_indr_register_block(rpriv, netdev);
break;
case NETDEV_UNREGISTER:
- mlx5e_rep_indr_unregister_block(netdev);
+ mlx5e_rep_indr_unregister_block(rpriv, netdev);
break;
}
return NOTIFY_OK;
@@ -1053,14 +1045,23 @@ static void mlx5e_rep_neigh_entry_destroy(struct mlx5e_priv *priv,
int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
struct mlx5e_encap_entry *e)
{
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
+ struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
+ struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
struct mlx5e_neigh_hash_entry *nhe;
int err;
+ err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type);
+ if (err)
+ return err;
nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
if (!nhe) {
err = mlx5e_rep_neigh_entry_create(priv, e, &nhe);
- if (err)
+ if (err) {
+ mlx5_tun_entropy_refcount_dec(tun_entropy,
+ e->reformat_type);
return err;
+ }
}
list_add(&e->encap_list, &nhe->encap_list);
return 0;
@@ -1069,6 +1070,9 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
struct mlx5e_encap_entry *e)
{
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
+ struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
+ struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
struct mlx5e_neigh_hash_entry *nhe;
list_del(&e->encap_list);
@@ -1076,6 +1080,7 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
if (list_empty(&nhe->encap_list))
mlx5e_rep_neigh_entry_destroy(priv, nhe);
+ mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type);
}
static int mlx5e_vf_rep_open(struct net_device *dev)
@@ -1092,7 +1097,8 @@ static int mlx5e_vf_rep_open(struct net_device *dev)
if (!mlx5_modify_vport_admin_state(priv->mdev,
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
- rep->vport, MLX5_VPORT_ADMIN_STATE_UP))
+ rep->vport, 1,
+ MLX5_VPORT_ADMIN_STATE_UP))
netif_carrier_on(dev);
unlock:
@@ -1110,7 +1116,8 @@ static int mlx5e_vf_rep_close(struct net_device *dev)
mutex_lock(&priv->state_lock);
mlx5_modify_vport_admin_state(priv->mdev,
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
- rep->vport, MLX5_VPORT_ADMIN_STATE_DOWN);
+ rep->vport, 1,
+ MLX5_VPORT_ADMIN_STATE_DOWN);
ret = mlx5e_close_locked(dev);
mutex_unlock(&priv->state_lock);
return ret;
@@ -1122,9 +1129,17 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
- int ret;
+ int ret, pf_num;
+
+ ret = mlx5_lag_get_pf_num(priv->mdev, &pf_num);
+ if (ret)
+ return ret;
+
+ if (rep->vport == MLX5_VPORT_UPLINK)
+ ret = snprintf(buf, len, "p%d", pf_num);
+ else
+ ret = snprintf(buf, len, "pf%dvf%d", pf_num, rep->vport - 1);
- ret = snprintf(buf, len, "%d", rep->vport - 1);
if (ret >= len)
return -EOPNOTSUPP;
@@ -1207,7 +1222,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
return false;
rep = rpriv->rep;
- return (rep->vport == FDB_UPLINK_VPORT);
+ return (rep->vport == MLX5_VPORT_UPLINK);
}
static bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id)
@@ -1225,17 +1240,8 @@ mlx5e_get_sw_stats64(const struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
struct mlx5e_priv *priv = netdev_priv(dev);
- struct mlx5e_sw_stats *sstats = &priv->stats.sw;
-
- mlx5e_rep_update_sw_counters(priv);
-
- stats->rx_packets = sstats->rx_packets;
- stats->rx_bytes = sstats->rx_bytes;
- stats->tx_packets = sstats->tx_packets;
- stats->tx_bytes = sstats->tx_bytes;
-
- stats->tx_dropped = sstats->tx_queue_dropped;
+ mlx5e_fold_sw_stats64(priv, stats);
return 0;
}
@@ -1281,9 +1287,17 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
return 0;
}
-static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
- .switchdev_port_attr_get = mlx5e_attr_get,
-};
+static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
+ __be16 vlan_proto)
+{
+ netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n");
+
+ if (vlan != 0)
+ return -EOPNOTSUPP;
+
+ /* allow setting 0-vid for compatibility with libvirt */
+ return 0;
+}
static const struct net_device_ops mlx5e_netdev_ops_vf_rep = {
.ndo_open = mlx5e_vf_rep_open,
@@ -1295,6 +1309,7 @@ static const struct net_device_ops mlx5e_netdev_ops_vf_rep = {
.ndo_has_offload_stats = mlx5e_rep_has_offload_stats,
.ndo_get_offload_stats = mlx5e_rep_get_offload_stats,
.ndo_change_mtu = mlx5e_vf_rep_change_mtu,
+ .ndo_get_port_parent_id = mlx5e_rep_get_port_parent_id,
};
static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
@@ -1315,6 +1330,8 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
.ndo_set_vf_rate = mlx5e_set_vf_rate,
.ndo_get_vf_config = mlx5e_get_vf_config,
.ndo_get_vf_stats = mlx5e_get_vf_stats,
+ .ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan,
+ .ndo_get_port_parent_id = mlx5e_rep_get_port_parent_id,
};
bool mlx5e_eswitch_rep(struct net_device *netdev)
@@ -1343,7 +1360,7 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
params->sw_mtu = netdev->mtu;
/* SQ */
- if (rep->vport == FDB_UPLINK_VPORT)
+ if (rep->vport == MLX5_VPORT_UPLINK)
params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
else
params->log_sq_size = MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE;
@@ -1370,7 +1387,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
struct mlx5_eswitch_rep *rep = rpriv->rep;
struct mlx5_core_dev *mdev = priv->mdev;
- if (rep->vport == FDB_UPLINK_VPORT) {
+ if (rep->vport == MLX5_VPORT_UPLINK) {
SET_NETDEV_DEV(netdev, &priv->mdev->pdev->dev);
netdev->netdev_ops = &mlx5e_netdev_ops_uplink_rep;
/* we want a persistent mac for the uplink rep */
@@ -1389,8 +1406,6 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
netdev->watchdog_timeo = 15 * HZ;
- netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
-
netdev->features |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
netdev->hw_features |= NETIF_F_HW_TC;
@@ -1402,7 +1417,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
netdev->hw_features |= NETIF_F_TSO6;
netdev->hw_features |= NETIF_F_RXCSUM;
- if (rep->vport != FDB_UPLINK_VPORT)
+ if (rep->vport != MLX5_VPORT_UPLINK)
netdev->features |= NETIF_F_VLAN_CHALLENGED;
netdev->features |= netdev->hw_features;
@@ -1555,14 +1570,18 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
return err;
}
- if (rpriv->rep->vport == FDB_UPLINK_VPORT) {
+ if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
uplink_priv = &rpriv->uplink_priv;
+ INIT_LIST_HEAD(&uplink_priv->unready_flows);
+
/* init shared tc flow table */
err = mlx5e_tc_esw_init(&uplink_priv->tc_ht);
if (err)
goto destroy_tises;
+ mlx5_init_port_tun_entropy(&uplink_priv->tun_entropy, priv->mdev);
+
/* init indirect block notifications */
INIT_LIST_HEAD(&uplink_priv->tc_indr_block_priv_list);
uplink_priv->netdevice_nb.notifier_call = mlx5e_nic_rep_netdevice_event;
@@ -1591,7 +1610,7 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
for (tc = 0; tc < priv->profile->max_tc; tc++)
mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
- if (rpriv->rep->vport == FDB_UPLINK_VPORT) {
+ if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
/* clean indirect TC block notifications */
unregister_netdevice_notifier(&rpriv->uplink_priv.netdevice_nb);
mlx5e_rep_indr_clean_block_privs(rpriv);
@@ -1615,27 +1634,38 @@ static void mlx5e_vf_rep_enable(struct mlx5e_priv *priv)
static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data)
{
struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb);
- struct mlx5_eqe *eqe = data;
- if (event != MLX5_EVENT_TYPE_PORT_CHANGE)
- return NOTIFY_DONE;
+ if (event == MLX5_EVENT_TYPE_PORT_CHANGE) {
+ struct mlx5_eqe *eqe = data;
- switch (eqe->sub_type) {
- case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
- case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
- queue_work(priv->wq, &priv->update_carrier_work);
- break;
- default:
- return NOTIFY_DONE;
+ switch (eqe->sub_type) {
+ case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
+ case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
+ queue_work(priv->wq, &priv->update_carrier_work);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ return NOTIFY_OK;
}
- return NOTIFY_OK;
+ if (event == MLX5_DEV_EVENT_PORT_AFFINITY) {
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
+
+ queue_work(priv->wq, &rpriv->uplink_priv.reoffload_flows_work);
+
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
}
static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
{
struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
u16 max_mtu;
netdev->min_mtu = ETH_MIN_MTU;
@@ -1643,6 +1673,9 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
mlx5e_set_dev_port_mtu(priv);
+ INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
+ mlx5e_tc_reoffload_flows_work);
+
mlx5_lag_add(mdev, netdev);
priv->events_nb.notifier_call = uplink_rep_async_event;
mlx5_notifier_register(mdev, &priv->events_nb);
@@ -1655,11 +1688,13 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
{
struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
#ifdef CONFIG_MLX5_CORE_EN_DCB
mlx5e_dcbnl_delete_app(priv);
#endif
mlx5_notifier_unregister(mdev, &priv->events_nb);
+ cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
mlx5_lag_remove(mdev);
}
@@ -1710,7 +1745,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
rpriv->rep = rep;
nch = mlx5e_get_max_num_channels(dev);
- profile = (rep->vport == FDB_UPLINK_VPORT) ? &mlx5e_uplink_rep_profile : &mlx5e_vf_rep_profile;
+ profile = (rep->vport == MLX5_VPORT_UPLINK) ? &mlx5e_uplink_rep_profile : &mlx5e_vf_rep_profile;
netdev = mlx5e_create_netdev(dev, profile, nch, rpriv);
if (!netdev) {
pr_warn("Failed to create representor netdev for vport %d\n",
@@ -1723,7 +1758,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
rep->rep_if[REP_ETH].priv = rpriv;
INIT_LIST_HEAD(&rpriv->vport_sqs_list);
- if (rep->vport == FDB_UPLINK_VPORT) {
+ if (rep->vport == MLX5_VPORT_UPLINK) {
err = mlx5e_create_mdev_resources(dev);
if (err)
goto err_destroy_netdev;
@@ -1759,7 +1794,7 @@ err_detach_netdev:
mlx5e_detach_netdev(netdev_priv(netdev));
err_destroy_mdev_resources:
- if (rep->vport == FDB_UPLINK_VPORT)
+ if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(dev);
err_destroy_netdev:
@@ -1779,7 +1814,7 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
unregister_netdev(netdev);
mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_detach_netdev(priv);
- if (rep->vport == FDB_UPLINK_VPORT)
+ if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(priv->mdev);
mlx5e_destroy_netdev(priv);
kfree(ppriv); /* mlx5e_rep_priv */
@@ -1797,25 +1832,18 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
- int total_vfs = MLX5_TOTAL_VPORTS(mdev);
- int vport;
+ struct mlx5_eswitch_rep_if rep_if = {};
- for (vport = 0; vport < total_vfs; vport++) {
- struct mlx5_eswitch_rep_if rep_if = {};
+ rep_if.load = mlx5e_vport_rep_load;
+ rep_if.unload = mlx5e_vport_rep_unload;
+ rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
- rep_if.load = mlx5e_vport_rep_load;
- rep_if.unload = mlx5e_vport_rep_unload;
- rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
- mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_ETH);
- }
+ mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_ETH);
}
void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
- int total_vfs = MLX5_TOTAL_VPORTS(mdev);
- int vport;
- for (vport = total_vfs - 1; vport >= 0; vport--)
- mlx5_eswitch_unregister_vport_rep(esw, vport, REP_ETH);
+ mlx5_eswitch_unregister_vport_reps(esw, REP_ETH);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index edd722824697..83b573b1abac 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -37,6 +37,7 @@
#include <linux/rhashtable.h>
#include "eswitch.h"
#include "en.h"
+#include "lib/port_tun.h"
#ifdef CONFIG_MLX5_ESWITCH
struct mlx5e_neigh_update_table {
@@ -71,6 +72,11 @@ struct mlx5_rep_uplink_priv {
*/
struct list_head tc_indr_block_priv_list;
struct notifier_block netdevice_nb;
+
+ struct mlx5_tun_entropy tun_entropy;
+
+ struct list_head unready_flows;
+ struct work_struct reoffload_flows_work;
};
struct mlx5e_rep_priv {
@@ -148,6 +154,7 @@ struct mlx5e_encap_entry {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
struct net_device *out_dev;
+ struct net_device *route_dev;
int tunnel_type;
int tunnel_hlen;
int reformat_type;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 1d0bb5ff8c26..be396e5e4e39 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -52,40 +52,45 @@ static inline bool mlx5e_rx_hw_stamp(struct hwtstamp_config *config)
return config->rx_filter == HWTSTAMP_FILTER_ALL;
}
-static inline void mlx5e_read_cqe_slot(struct mlx5e_cq *cq, u32 cqcc,
- void *data)
+static inline void mlx5e_read_cqe_slot(struct mlx5_cqwq *wq,
+ u32 cqcc, void *data)
{
- u32 ci = mlx5_cqwq_ctr2ix(&cq->wq, cqcc);
+ u32 ci = mlx5_cqwq_ctr2ix(wq, cqcc);
- memcpy(data, mlx5_cqwq_get_wqe(&cq->wq, ci), sizeof(struct mlx5_cqe64));
+ memcpy(data, mlx5_cqwq_get_wqe(wq, ci), sizeof(struct mlx5_cqe64));
}
static inline void mlx5e_read_title_slot(struct mlx5e_rq *rq,
- struct mlx5e_cq *cq, u32 cqcc)
+ struct mlx5_cqwq *wq,
+ u32 cqcc)
{
- mlx5e_read_cqe_slot(cq, cqcc, &cq->title);
- cq->decmprs_left = be32_to_cpu(cq->title.byte_cnt);
- cq->decmprs_wqe_counter = be16_to_cpu(cq->title.wqe_counter);
+ struct mlx5e_cq_decomp *cqd = &rq->cqd;
+ struct mlx5_cqe64 *title = &cqd->title;
+
+ mlx5e_read_cqe_slot(wq, cqcc, title);
+ cqd->left = be32_to_cpu(title->byte_cnt);
+ cqd->wqe_counter = be16_to_cpu(title->wqe_counter);
rq->stats->cqe_compress_blks++;
}
-static inline void mlx5e_read_mini_arr_slot(struct mlx5e_cq *cq, u32 cqcc)
+static inline void mlx5e_read_mini_arr_slot(struct mlx5_cqwq *wq,
+ struct mlx5e_cq_decomp *cqd,
+ u32 cqcc)
{
- mlx5e_read_cqe_slot(cq, cqcc, cq->mini_arr);
- cq->mini_arr_idx = 0;
+ mlx5e_read_cqe_slot(wq, cqcc, cqd->mini_arr);
+ cqd->mini_arr_idx = 0;
}
-static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n)
+static inline void mlx5e_cqes_update_owner(struct mlx5_cqwq *wq, int n)
{
- struct mlx5_cqwq *wq = &cq->wq;
-
+ u32 cqcc = wq->cc;
u8 op_own = mlx5_cqwq_get_ctr_wrap_cnt(wq, cqcc) & 1;
u32 ci = mlx5_cqwq_ctr2ix(wq, cqcc);
u32 wq_sz = mlx5_cqwq_get_size(wq);
u32 ci_top = min_t(u32, wq_sz, ci + n);
for (; ci < ci_top; ci++, n--) {
- struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, ci);
+ struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(wq, ci);
cqe->op_own = op_own;
}
@@ -93,7 +98,7 @@ static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n)
if (unlikely(ci == wq_sz)) {
op_own = !op_own;
for (ci = 0; ci < n; ci++) {
- struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, ci);
+ struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(wq, ci);
cqe->op_own = op_own;
}
@@ -101,68 +106,79 @@ static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n)
}
static inline void mlx5e_decompress_cqe(struct mlx5e_rq *rq,
- struct mlx5e_cq *cq, u32 cqcc)
+ struct mlx5_cqwq *wq,
+ u32 cqcc)
{
- cq->title.byte_cnt = cq->mini_arr[cq->mini_arr_idx].byte_cnt;
- cq->title.check_sum = cq->mini_arr[cq->mini_arr_idx].checksum;
- cq->title.op_own &= 0xf0;
- cq->title.op_own |= 0x01 & (cqcc >> cq->wq.fbc.log_sz);
- cq->title.wqe_counter = cpu_to_be16(cq->decmprs_wqe_counter);
+ struct mlx5e_cq_decomp *cqd = &rq->cqd;
+ struct mlx5_mini_cqe8 *mini_cqe = &cqd->mini_arr[cqd->mini_arr_idx];
+ struct mlx5_cqe64 *title = &cqd->title;
+
+ title->byte_cnt = mini_cqe->byte_cnt;
+ title->check_sum = mini_cqe->checksum;
+ title->op_own &= 0xf0;
+ title->op_own |= 0x01 & (cqcc >> wq->fbc.log_sz);
+ title->wqe_counter = cpu_to_be16(cqd->wqe_counter);
if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
- cq->decmprs_wqe_counter +=
- mpwrq_get_cqe_consumed_strides(&cq->title);
+ cqd->wqe_counter += mpwrq_get_cqe_consumed_strides(title);
else
- cq->decmprs_wqe_counter =
- mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, cq->decmprs_wqe_counter + 1);
+ cqd->wqe_counter =
+ mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, cqd->wqe_counter + 1);
}
static inline void mlx5e_decompress_cqe_no_hash(struct mlx5e_rq *rq,
- struct mlx5e_cq *cq, u32 cqcc)
+ struct mlx5_cqwq *wq,
+ u32 cqcc)
{
- mlx5e_decompress_cqe(rq, cq, cqcc);
- cq->title.rss_hash_type = 0;
- cq->title.rss_hash_result = 0;
+ struct mlx5e_cq_decomp *cqd = &rq->cqd;
+
+ mlx5e_decompress_cqe(rq, wq, cqcc);
+ cqd->title.rss_hash_type = 0;
+ cqd->title.rss_hash_result = 0;
}
static inline u32 mlx5e_decompress_cqes_cont(struct mlx5e_rq *rq,
- struct mlx5e_cq *cq,
+ struct mlx5_cqwq *wq,
int update_owner_only,
int budget_rem)
{
- u32 cqcc = cq->wq.cc + update_owner_only;
+ struct mlx5e_cq_decomp *cqd = &rq->cqd;
+ u32 cqcc = wq->cc + update_owner_only;
u32 cqe_count;
u32 i;
- cqe_count = min_t(u32, cq->decmprs_left, budget_rem);
+ cqe_count = min_t(u32, cqd->left, budget_rem);
for (i = update_owner_only; i < cqe_count;
- i++, cq->mini_arr_idx++, cqcc++) {
- if (cq->mini_arr_idx == MLX5_MINI_CQE_ARRAY_SIZE)
- mlx5e_read_mini_arr_slot(cq, cqcc);
+ i++, cqd->mini_arr_idx++, cqcc++) {
+ if (cqd->mini_arr_idx == MLX5_MINI_CQE_ARRAY_SIZE)
+ mlx5e_read_mini_arr_slot(wq, cqd, cqcc);
- mlx5e_decompress_cqe_no_hash(rq, cq, cqcc);
- rq->handle_rx_cqe(rq, &cq->title);
+ mlx5e_decompress_cqe_no_hash(rq, wq, cqcc);
+ rq->handle_rx_cqe(rq, &cqd->title);
}
- mlx5e_cqes_update_owner(cq, cq->wq.cc, cqcc - cq->wq.cc);
- cq->wq.cc = cqcc;
- cq->decmprs_left -= cqe_count;
+ mlx5e_cqes_update_owner(wq, cqcc - wq->cc);
+ wq->cc = cqcc;
+ cqd->left -= cqe_count;
rq->stats->cqe_compress_pkts += cqe_count;
return cqe_count;
}
static inline u32 mlx5e_decompress_cqes_start(struct mlx5e_rq *rq,
- struct mlx5e_cq *cq,
+ struct mlx5_cqwq *wq,
int budget_rem)
{
- mlx5e_read_title_slot(rq, cq, cq->wq.cc);
- mlx5e_read_mini_arr_slot(cq, cq->wq.cc + 1);
- mlx5e_decompress_cqe(rq, cq, cq->wq.cc);
- rq->handle_rx_cqe(rq, &cq->title);
- cq->mini_arr_idx++;
+ struct mlx5e_cq_decomp *cqd = &rq->cqd;
+ u32 cc = wq->cc;
+
+ mlx5e_read_title_slot(rq, wq, cc);
+ mlx5e_read_mini_arr_slot(wq, cqd, cc + 1);
+ mlx5e_decompress_cqe(rq, wq, cc);
+ rq->handle_rx_cqe(rq, &cqd->title);
+ cqd->mini_arr_idx++;
- return mlx5e_decompress_cqes_cont(rq, cq, 1, budget_rem) - 1;
+ return mlx5e_decompress_cqes_cont(rq, wq, 1, budget_rem) - 1;
}
static inline bool mlx5e_page_is_reserved(struct page *page)
@@ -369,7 +385,7 @@ mlx5e_add_skb_frag(struct mlx5e_rq *rq, struct sk_buff *skb,
static inline void
mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb,
struct mlx5e_dma_info *dma_info,
- int offset_from, int offset_to, u32 headlen)
+ int offset_from, u32 headlen)
{
const void *from = page_address(dma_info->page) + offset_from;
/* Aligning len to sizeof(long) optimizes memcpy performance */
@@ -377,24 +393,7 @@ mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb,
dma_sync_single_for_cpu(pdev, dma_info->addr + offset_from, len,
DMA_FROM_DEVICE);
- skb_copy_to_linear_data_offset(skb, offset_to, from, len);
-}
-
-static inline void
-mlx5e_copy_skb_header_mpwqe(struct device *pdev,
- struct sk_buff *skb,
- struct mlx5e_dma_info *dma_info,
- u32 offset, u32 headlen)
-{
- u16 headlen_pg = min_t(u32, headlen, PAGE_SIZE - offset);
-
- mlx5e_copy_skb_header(pdev, skb, dma_info, offset, 0, headlen_pg);
-
- if (unlikely(offset + headlen > PAGE_SIZE)) {
- dma_info++;
- mlx5e_copy_skb_header(pdev, skb, dma_info, 0, headlen_pg,
- headlen - headlen_pg);
- }
+ skb_copy_to_linear_data(skb, from, len);
}
static void
@@ -732,6 +731,8 @@ static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto)
((struct ipv6hdr *)ip_p)->nexthdr;
}
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
static inline void mlx5e_handle_csum(struct net_device *netdev,
struct mlx5_cqe64 *cqe,
struct mlx5e_rq *rq,
@@ -754,6 +755,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
if (unlikely(test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state)))
goto csum_unnecessary;
+ /* CQE csum doesn't cover padding octets in short ethernet
+ * frames. And the pad field is appended prior to calculating
+ * and appending the FCS field.
+ *
+ * Detecting these padded frames requires to verify and parse
+ * IP headers, so we simply force all those small frames to be
+ * CHECKSUM_UNNECESSARY even if they are not padded.
+ */
+ if (short_frame(skb->len))
+ goto csum_unnecessary;
+
if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) {
if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
goto csum_unnecessary;
@@ -960,8 +972,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
}
/* copy header */
- mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset,
- 0, headlen);
+ mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset, headlen);
/* skb linear part was allocated with headlen and aligned to long */
skb->tail += headlen;
skb->len += headlen;
@@ -1083,8 +1094,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
di++;
}
/* copy header */
- mlx5e_copy_skb_header_mpwqe(rq->pdev, skb, head_di,
- head_offset, headlen);
+ mlx5e_copy_skb_header(rq->pdev, skb, head_di, head_offset, headlen);
/* skb linear part was allocated with headlen and aligned to long */
skb->tail += headlen;
skb->len += headlen;
@@ -1190,16 +1200,17 @@ mpwrq_cqe_out:
int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
{
struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
+ struct mlx5_cqwq *cqwq = &cq->wq;
struct mlx5_cqe64 *cqe;
int work_done = 0;
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
return 0;
- if (cq->decmprs_left)
- work_done += mlx5e_decompress_cqes_cont(rq, cq, 0, budget);
+ if (rq->cqd.left)
+ work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget);
- cqe = mlx5_cqwq_get_cqe(&cq->wq);
+ cqe = mlx5_cqwq_get_cqe(cqwq);
if (!cqe) {
if (unlikely(work_done))
goto out;
@@ -1209,21 +1220,21 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
do {
if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) {
work_done +=
- mlx5e_decompress_cqes_start(rq, cq,
+ mlx5e_decompress_cqes_start(rq, cqwq,
budget - work_done);
continue;
}
- mlx5_cqwq_pop(&cq->wq);
+ mlx5_cqwq_pop(cqwq);
rq->handle_rx_cqe(rq, cqe);
- } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(&cq->wq)));
+ } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(cqwq)));
out:
if (rq->xdp_prog)
mlx5e_xdp_rx_poll_complete(rq);
- mlx5_cqwq_update_db_record(&cq->wq);
+ mlx5_cqwq_update_db_record(cqwq);
/* ensure cq space is freed before enabling more cqes */
wmb();
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index d3fe48ff9da9..1a78e05cbba8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -127,9 +127,9 @@ static int mlx5e_grp_sw_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx)
return idx;
}
-void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
+static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
{
- struct mlx5e_sw_stats temp, *s = &temp;
+ struct mlx5e_sw_stats *s = &priv->stats.sw;
int i;
memset(s, 0, sizeof(*s));
@@ -212,8 +212,6 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
s->tx_cqes += sq_stats->cqes;
}
}
-
- memcpy(&priv->stats.sw, s, sizeof(*s));
}
static const struct counter_desc q_stats_desc[] = {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index fe91ec06e3c7..4640d4f986f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -277,7 +277,6 @@ struct mlx5e_stats_grp {
extern const struct mlx5e_stats_grp mlx5e_stats_grps[];
extern const int mlx5e_num_stats_grps;
-void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv);
void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv);
#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 cae6c6d48984..b4967a0ff8c7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -38,7 +38,6 @@
#include <linux/mlx5/fs.h>
#include <linux/mlx5/device.h>
#include <linux/rhashtable.h>
-#include <net/switchdev.h>
#include <net/tc_act/tc_mirred.h>
#include <net/tc_act/tc_vlan.h>
#include <net/tc_act/tc_tunnel_key.h>
@@ -76,6 +75,7 @@ enum {
MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(MLX5E_TC_FLOW_BASE + 2),
MLX5E_TC_FLOW_SLOW = BIT(MLX5E_TC_FLOW_BASE + 3),
MLX5E_TC_FLOW_DUP = BIT(MLX5E_TC_FLOW_BASE + 4),
+ MLX5E_TC_FLOW_NOT_READY = BIT(MLX5E_TC_FLOW_BASE + 5),
};
#define MLX5E_TC_MAX_SPLITS 1
@@ -117,6 +117,7 @@ struct mlx5e_tc_flow {
struct list_head mod_hdr; /* flows sharing the same mod hdr ID */
struct list_head hairpin; /* flows sharing the same hairpin */
struct list_head peer; /* flows with peer flow */
+ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */
union {
struct mlx5_esw_flow_attr esw_attr[0];
struct mlx5_nic_flow_attr nic_attr[0];
@@ -128,6 +129,7 @@ struct mlx5e_tc_flow_parse_attr {
struct net_device *filter_dev;
struct mlx5_flow_spec spec;
int num_mod_hdr_actions;
+ int max_mod_hdr_actions;
void *mod_hdr_actions;
int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
};
@@ -850,12 +852,12 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow, int out_index);
static int mlx5e_attach_encap(struct mlx5e_priv *priv,
- struct ip_tunnel_info *tun_info,
- struct net_device *mirred_dev,
- struct net_device **encap_dev,
struct mlx5e_tc_flow *flow,
+ struct net_device *mirred_dev,
+ int out_index,
struct netlink_ext_ack *extack,
- int out_index);
+ struct net_device **encap_dev,
+ bool *encap_valid);
static struct mlx5_flow_handle *
mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw,
@@ -927,21 +929,42 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
flow->flags &= ~MLX5E_TC_FLOW_SLOW;
}
+static void add_unready_flow(struct mlx5e_tc_flow *flow)
+{
+ struct mlx5_rep_uplink_priv *uplink_priv;
+ struct mlx5e_rep_priv *rpriv;
+ struct mlx5_eswitch *esw;
+
+ esw = flow->priv->mdev->priv.eswitch;
+ rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
+ uplink_priv = &rpriv->uplink_priv;
+
+ flow->flags |= MLX5E_TC_FLOW_NOT_READY;
+ list_add_tail(&flow->unready, &uplink_priv->unready_flows);
+}
+
+static void remove_unready_flow(struct mlx5e_tc_flow *flow)
+{
+ list_del(&flow->unready);
+ flow->flags &= ~MLX5E_TC_FLOW_NOT_READY;
+}
+
static int
mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
- struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow,
struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
u32 max_chain = mlx5_eswitch_get_chain_range(esw);
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
+ struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
u16 max_prio = mlx5_eswitch_get_prio_range(esw);
struct net_device *out_dev, *encap_dev = NULL;
struct mlx5_fc *counter = NULL;
struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *out_priv;
- int err = 0, encap_err = 0;
+ bool encap_valid = true;
+ int err = 0;
int out_index;
if (!mlx5_eswitch_prios_supported(esw) && attr->prio != 1) {
@@ -967,17 +990,14 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
if (!(attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
continue;
- mirred_ifindex = attr->parse_attr->mirred_ifindex[out_index];
+ mirred_ifindex = parse_attr->mirred_ifindex[out_index];
out_dev = __dev_get_by_index(dev_net(priv->netdev),
mirred_ifindex);
- err = mlx5e_attach_encap(priv,
- &parse_attr->tun_info[out_index],
- out_dev, &encap_dev, flow,
- extack, out_index);
- if (err && err != -EAGAIN)
+ err = mlx5e_attach_encap(priv, flow, out_dev, out_index,
+ extack, &encap_dev, &encap_valid);
+ if (err)
goto err_attach_encap;
- if (err == -EAGAIN)
- encap_err = err;
+
out_priv = netdev_priv(encap_dev);
rpriv = out_priv->ppriv;
attr->dests[out_index].rep = rpriv->rep;
@@ -1005,10 +1025,11 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
attr->counter = counter;
}
- /* we get here if (1) there's no error or when
- * (2) there's an encap action and we're on -EAGAIN (no valid neigh)
+ /* we get here if one of the following takes place:
+ * (1) there's no error
+ * (2) there's an encap action and we don't have valid neigh
*/
- if (encap_err == -EAGAIN) {
+ if (!encap_valid) {
/* continue with goto slow path rule instead */
struct mlx5_esw_flow_attr slow_attr;
@@ -1048,6 +1069,12 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
struct mlx5_esw_flow_attr slow_attr;
int out_index;
+ if (flow->flags & MLX5E_TC_FLOW_NOT_READY) {
+ remove_unready_flow(flow);
+ kvfree(attr->parse_attr);
+ return;
+ }
+
if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
if (flow->flags & MLX5E_TC_FLOW_SLOW)
mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr);
@@ -1302,101 +1329,89 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
static int parse_tunnel_attr(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f,
- struct net_device *filter_dev)
+ struct net_device *filter_dev, u8 *match_level)
{
struct netlink_ext_ack *extack = f->common.extack;
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
outer_headers);
void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
outer_headers);
-
- struct flow_dissector_key_control *enc_control =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_CONTROL,
- f->key);
- int err = 0;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_match_control enc_control;
+ int err;
err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
- headers_c, headers_v);
+ headers_c, headers_v, match_level);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"failed to parse tunnel attributes");
return err;
}
- if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
- f->mask);
+ flow_rule_match_enc_control(rule, &enc_control);
+
+ if (enc_control.key->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_enc_ipv4_addrs(rule, &match);
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv4_layout.ipv4,
- ntohl(mask->src));
+ ntohl(match.mask->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
src_ipv4_src_ipv6.ipv4_layout.ipv4,
- ntohl(key->src));
+ ntohl(match.key->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
- ntohl(mask->dst));
+ ntohl(match.mask->dst));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
- ntohl(key->dst));
+ ntohl(match.key->dst));
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
- } else if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
- f->mask);
+ } else if (enc_control.key->addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
+ struct flow_match_ipv6_addrs match;
+ flow_rule_match_enc_ipv6_addrs(rule, &match);
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv6_layout.ipv6),
- &mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+ &match.mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
src_ipv4_src_ipv6.ipv6_layout.ipv6),
- &key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+ &match.key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
- &mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+ &match.mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
- &key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+ &match.key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_IP)) {
- struct flow_dissector_key_ip *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IP,
- f->key);
- struct flow_dissector_key_ip *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IP,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
+ struct flow_match_ip match;
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3);
+ flow_rule_match_enc_ip(rule, &match);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn,
+ match.mask->tos & 0x3);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
+ match.key->tos & 0x3);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
+ match.mask->tos >> 2);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp,
+ match.key->tos >> 2);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, mask->ttl);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, key->ttl);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit,
+ match.mask->ttl);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit,
+ match.key->ttl);
- if (mask->ttl &&
+ if (match.mask->ttl &&
!MLX5_CAP_ESW_FLOWTABLE_FDB
(priv->mdev,
ft_field_support.outer_ipv4_ttl)) {
@@ -1426,7 +1441,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f,
struct net_device *filter_dev,
- u8 *match_level)
+ u8 *match_level, u8 *tunnel_match_level)
{
struct netlink_ext_ack *extack = f->common.extack;
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1437,12 +1452,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
misc_parameters);
void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
misc_parameters);
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_dissector *dissector = rule->match.dissector;
u16 addr_type = 0;
u8 ip_proto = 0;
*match_level = MLX5_MATCH_NONE;
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -1461,23 +1478,21 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
BIT(FLOW_DISSECTOR_KEY_ENC_IP))) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported key");
netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
- f->dissector->used_keys);
+ dissector->used_keys);
return -EOPNOTSUPP;
}
- if ((dissector_uses_key(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
- dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
- dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
- dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_CONTROL,
- f->key);
- switch (key->addr_type) {
+ if ((flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+ struct flow_match_control match;
+
+ flow_rule_match_enc_control(rule, &match);
+ switch (match.key->addr_type) {
case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
- if (parse_tunnel_attr(priv, spec, f, filter_dev))
+ if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
return -EOPNOTSUPP;
break;
default:
@@ -1493,35 +1508,27 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
inner_headers);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
+
+ flow_rule_match_basic(rule, &match);
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
- ntohs(mask->n_proto));
+ ntohs(match.mask->n_proto));
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
- ntohs(key->n_proto));
+ ntohs(match.key->n_proto));
- if (mask->n_proto)
+ if (match.mask->n_proto)
*match_level = MLX5_MATCH_L2;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
- if (mask->vlan_id || mask->vlan_priority || mask->vlan_tpid) {
- if (key->vlan_tpid == htons(ETH_P_8021AD)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
+
+ flow_rule_match_vlan(rule, &match);
+ if (match.mask->vlan_id ||
+ match.mask->vlan_priority ||
+ match.mask->vlan_tpid) {
+ if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
svlan_tag, 1);
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
@@ -1533,11 +1540,15 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
cvlan_tag, 1);
}
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, mask->vlan_id);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, key->vlan_id);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid,
+ match.mask->vlan_id);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid,
+ match.key->vlan_id);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio,
+ match.mask->vlan_priority);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio,
+ match.key->vlan_priority);
*match_level = MLX5_MATCH_L2;
}
@@ -1547,17 +1558,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
*match_level = MLX5_MATCH_L2;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CVLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CVLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CVLAN,
- f->mask);
- if (mask->vlan_id || mask->vlan_priority || mask->vlan_tpid) {
- if (key->vlan_tpid == htons(ETH_P_8021AD)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
+ struct flow_match_vlan match;
+
+ flow_rule_match_vlan(rule, &match);
+ if (match.mask->vlan_id ||
+ match.mask->vlan_priority ||
+ match.mask->vlan_tpid) {
+ if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
MLX5_SET(fte_match_set_misc, misc_c,
outer_second_svlan_tag, 1);
MLX5_SET(fte_match_set_misc, misc_v,
@@ -1570,69 +1578,58 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
}
MLX5_SET(fte_match_set_misc, misc_c, outer_second_vid,
- mask->vlan_id);
+ match.mask->vlan_id);
MLX5_SET(fte_match_set_misc, misc_v, outer_second_vid,
- key->vlan_id);
+ match.key->vlan_id);
MLX5_SET(fte_match_set_misc, misc_c, outer_second_prio,
- mask->vlan_priority);
+ match.mask->vlan_priority);
MLX5_SET(fte_match_set_misc, misc_v, outer_second_prio,
- key->vlan_priority);
+ match.key->vlan_priority);
*match_level = MLX5_MATCH_L2;
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
- struct flow_dissector_key_eth_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
+ flow_rule_match_eth_addrs(rule, &match);
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
dmac_47_16),
- mask->dst);
+ match.mask->dst);
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dmac_47_16),
- key->dst);
+ match.key->dst);
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
smac_47_16),
- mask->src);
+ match.mask->src);
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
smac_47_16),
- key->src);
+ match.key->src);
- if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst))
+ if (!is_zero_ether_addr(match.mask->src) ||
+ !is_zero_ether_addr(match.mask->dst))
*match_level = MLX5_MATCH_L2;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
- struct flow_dissector_key_control *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->mask);
- addr_type = key->addr_type;
+ flow_rule_match_control(rule, &match);
+ addr_type = match.key->addr_type;
/* the HW doesn't support frag first/later */
- if (mask->flags & FLOW_DIS_FIRST_FRAG)
+ if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
return -EOPNOTSUPP;
- if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
+ if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
- key->flags & FLOW_DIS_IS_FRAGMENT);
+ match.key->flags & FLOW_DIS_IS_FRAGMENT);
/* the HW doesn't need L3 inline to match on frag=no */
- if (!(key->flags & FLOW_DIS_IS_FRAGMENT))
+ if (!(match.key->flags & FLOW_DIS_IS_FRAGMENT))
*match_level = MLX5_MATCH_L2;
/* *** L2 attributes parsing up to here *** */
else
@@ -1640,102 +1637,85 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
}
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
- ip_proto = key->ip_proto;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
+
+ flow_rule_match_basic(rule, &match);
+ ip_proto = match.key->ip_proto;
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
- mask->ip_proto);
+ match.mask->ip_proto);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
- key->ip_proto);
+ match.key->ip_proto);
- if (mask->ip_proto)
+ if (match.mask->ip_proto)
*match_level = MLX5_MATCH_L3;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
+ struct flow_match_ipv4_addrs match;
+ flow_rule_match_ipv4_addrs(rule, &match);
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv4_layout.ipv4),
- &mask->src, sizeof(mask->src));
+ &match.mask->src, sizeof(match.mask->src));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
src_ipv4_src_ipv6.ipv4_layout.ipv4),
- &key->src, sizeof(key->src));
+ &match.key->src, sizeof(match.key->src));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
- &mask->dst, sizeof(mask->dst));
+ &match.mask->dst, sizeof(match.mask->dst));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
- &key->dst, sizeof(key->dst));
+ &match.key->dst, sizeof(match.key->dst));
- if (mask->src || mask->dst)
+ if (match.mask->src || match.mask->dst)
*match_level = MLX5_MATCH_L3;
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
+ struct flow_match_ipv6_addrs match;
+ flow_rule_match_ipv6_addrs(rule, &match);
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv6_layout.ipv6),
- &mask->src, sizeof(mask->src));
+ &match.mask->src, sizeof(match.mask->src));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
src_ipv4_src_ipv6.ipv6_layout.ipv6),
- &key->src, sizeof(key->src));
+ &match.key->src, sizeof(match.key->src));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
- &mask->dst, sizeof(mask->dst));
+ &match.mask->dst, sizeof(match.mask->dst));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
- &key->dst, sizeof(key->dst));
+ &match.key->dst, sizeof(match.key->dst));
- if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
- ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
+ if (ipv6_addr_type(&match.mask->src) != IPV6_ADDR_ANY ||
+ ipv6_addr_type(&match.mask->dst) != IPV6_ADDR_ANY)
*match_level = MLX5_MATCH_L3;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
- struct flow_dissector_key_ip *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IP,
- f->key);
- struct flow_dissector_key_ip *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IP,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
+ struct flow_match_ip match;
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3);
+ flow_rule_match_ip(rule, &match);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn,
+ match.mask->tos & 0x3);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
+ match.key->tos & 0x3);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
+ match.mask->tos >> 2);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp,
+ match.key->tos >> 2);
- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, mask->ttl);
- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, key->ttl);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit,
+ match.mask->ttl);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit,
+ match.key->ttl);
- if (mask->ttl &&
+ if (match.mask->ttl &&
!MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev,
ft_field_support.outer_ipv4_ttl)) {
NL_SET_ERR_MSG_MOD(extack,
@@ -1743,44 +1723,39 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
return -EOPNOTSUPP;
}
- if (mask->tos || mask->ttl)
+ if (match.mask->tos || match.mask->ttl)
*match_level = MLX5_MATCH_L3;
}
/* *** L3 attributes parsing up to here *** */
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- struct flow_dissector_key_ports *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
+
+ flow_rule_match_ports(rule, &match);
switch (ip_proto) {
case IPPROTO_TCP:
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
- tcp_sport, ntohs(mask->src));
+ tcp_sport, ntohs(match.mask->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
- tcp_sport, ntohs(key->src));
+ tcp_sport, ntohs(match.key->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
- tcp_dport, ntohs(mask->dst));
+ tcp_dport, ntohs(match.mask->dst));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
- tcp_dport, ntohs(key->dst));
+ tcp_dport, ntohs(match.key->dst));
break;
case IPPROTO_UDP:
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
- udp_sport, ntohs(mask->src));
+ udp_sport, ntohs(match.mask->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
- udp_sport, ntohs(key->src));
+ udp_sport, ntohs(match.key->src));
MLX5_SET(fte_match_set_lyr_2_4, headers_c,
- udp_dport, ntohs(mask->dst));
+ udp_dport, ntohs(match.mask->dst));
MLX5_SET(fte_match_set_lyr_2_4, headers_v,
- udp_dport, ntohs(key->dst));
+ udp_dport, ntohs(match.key->dst));
break;
default:
NL_SET_ERR_MSG_MOD(extack,
@@ -1790,26 +1765,20 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
return -EINVAL;
}
- if (mask->src || mask->dst)
+ if (match.mask->src || match.mask->dst)
*match_level = MLX5_MATCH_L4;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
- struct flow_dissector_key_tcp *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_TCP,
- f->key);
- struct flow_dissector_key_tcp *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_TCP,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
+ struct flow_match_tcp match;
+ flow_rule_match_tcp(rule, &match);
MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
- ntohs(mask->flags));
+ ntohs(match.mask->flags));
MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
- ntohs(key->flags));
+ ntohs(match.key->flags));
- if (mask->flags)
+ if (match.mask->flags)
*match_level = MLX5_MATCH_L4;
}
@@ -1826,15 +1795,15 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
+ u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
struct mlx5_eswitch_rep *rep;
- u8 match_level;
int err;
- err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level);
+ err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
rep = rpriv->rep;
- if (rep->vport != FDB_UPLINK_VPORT &&
+ if (rep->vport != MLX5_VPORT_UPLINK &&
(esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
esw->offloads.inline_mode < match_level)) {
NL_SET_ERR_MSG_MOD(extack,
@@ -1846,10 +1815,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
}
}
- if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+ if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
flow->esw_attr->match_level = match_level;
- else
+ flow->esw_attr->tunnel_match_level = tunnel_match_level;
+ } else {
flow->nic_attr->match_level = match_level;
+ }
return err;
}
@@ -1862,27 +1833,29 @@ struct pedit_headers {
struct udphdr udp;
};
+struct pedit_headers_action {
+ struct pedit_headers vals;
+ struct pedit_headers masks;
+ u32 pedits;
+};
+
static int pedit_header_offsets[] = {
- [TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
- [TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
- [TCA_PEDIT_KEY_EX_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
- [TCA_PEDIT_KEY_EX_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
- [TCA_PEDIT_KEY_EX_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
+ [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
+ [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
+ [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
+ [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
+ [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
};
#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
- struct pedit_headers *masks,
- struct pedit_headers *vals)
+ struct pedit_headers_action *hdrs)
{
u32 *curr_pmask, *curr_pval;
- if (hdr_type >= __PEDIT_HDR_TYPE_MAX)
- goto out_err;
-
- curr_pmask = (u32 *)(pedit_header(masks, hdr_type) + offset);
- curr_pval = (u32 *)(pedit_header(vals, hdr_type) + offset);
+ curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
+ curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
if (*curr_pmask & mask) /* disallow acting twice on the same location */
goto out_err;
@@ -1934,12 +1907,11 @@ static struct mlx5_fields fields[] = {
OFFLOAD(UDP_DPORT, 2, udp.dest, 0),
};
-/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
- * max from the SW pedit action. On success, it says how many HW actions were
- * actually parsed.
+/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
+ * max from the SW pedit action. On success, attr->num_mod_hdr_actions
+ * says how many HW actions were actually parsed.
*/
-static int offload_pedit_fields(struct pedit_headers *masks,
- struct pedit_headers *vals,
+static int offload_pedit_fields(struct pedit_headers_action *hdrs,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct netlink_ext_ack *extack)
{
@@ -1954,15 +1926,17 @@ static int offload_pedit_fields(struct pedit_headers *masks,
__be16 mask_be16;
void *action;
- set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET];
- add_masks = &masks[TCA_PEDIT_KEY_EX_CMD_ADD];
- set_vals = &vals[TCA_PEDIT_KEY_EX_CMD_SET];
- add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
+ set_masks = &hdrs[0].masks;
+ add_masks = &hdrs[1].masks;
+ set_vals = &hdrs[0].vals;
+ add_vals = &hdrs[1].vals;
action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
- action = parse_attr->mod_hdr_actions;
- max_actions = parse_attr->num_mod_hdr_actions;
- nactions = 0;
+ action = parse_attr->mod_hdr_actions +
+ parse_attr->num_mod_hdr_actions * action_size;
+
+ max_actions = parse_attr->max_mod_hdr_actions;
+ nactions = parse_attr->num_mod_hdr_actions;
for (i = 0; i < ARRAY_SIZE(fields); i++) {
f = &fields[i];
@@ -2053,12 +2027,14 @@ static int offload_pedit_fields(struct pedit_headers *masks,
}
static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
- const struct tc_action *a, int namespace,
+ struct pedit_headers_action *hdrs,
+ int namespace,
struct mlx5e_tc_flow_parse_attr *parse_attr)
{
int nkeys, action_size, max_actions;
- nkeys = tcf_pedit_nkeys(a);
+ nkeys = hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits +
+ hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits;
action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
@@ -2073,62 +2049,67 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
if (!parse_attr->mod_hdr_actions)
return -ENOMEM;
- parse_attr->num_mod_hdr_actions = max_actions;
+ parse_attr->max_mod_hdr_actions = max_actions;
return 0;
}
static const struct pedit_headers zero_masks = {};
static int parse_tc_pedit_action(struct mlx5e_priv *priv,
- const struct tc_action *a, int namespace,
+ const struct flow_action_entry *act, int namespace,
struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct pedit_headers_action *hdrs,
struct netlink_ext_ack *extack)
{
- struct pedit_headers masks[__PEDIT_CMD_MAX], vals[__PEDIT_CMD_MAX], *cmd_masks;
- int nkeys, i, err = -EOPNOTSUPP;
+ u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
+ int err = -EOPNOTSUPP;
u32 mask, val, offset;
- u8 cmd, htype;
+ u8 htype;
- nkeys = tcf_pedit_nkeys(a);
+ htype = act->mangle.htype;
+ err = -EOPNOTSUPP; /* can't be all optimistic */
- memset(masks, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
- memset(vals, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
+ if (htype == FLOW_ACT_MANGLE_UNSPEC) {
+ NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded");
+ goto out_err;
+ }
- for (i = 0; i < nkeys; i++) {
- htype = tcf_pedit_htype(a, i);
- cmd = tcf_pedit_cmd(a, i);
- err = -EOPNOTSUPP; /* can't be all optimistic */
+ mask = act->mangle.mask;
+ val = act->mangle.val;
+ offset = act->mangle.offset;
- if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
- NL_SET_ERR_MSG_MOD(extack,
- "legacy pedit isn't offloaded");
- goto out_err;
- }
+ err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]);
+ if (err)
+ goto out_err;
- if (cmd != TCA_PEDIT_KEY_EX_CMD_SET && cmd != TCA_PEDIT_KEY_EX_CMD_ADD) {
- NL_SET_ERR_MSG_MOD(extack, "pedit cmd isn't offloaded");
- goto out_err;
- }
+ hdrs[cmd].pedits++;
+
+ return 0;
+out_err:
+ return err;
+}
- mask = tcf_pedit_mask(a, i);
- val = tcf_pedit_val(a, i);
- offset = tcf_pedit_offset(a, i);
+static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct pedit_headers_action *hdrs,
+ struct netlink_ext_ack *extack)
+{
+ struct pedit_headers *cmd_masks;
+ int err;
+ u8 cmd;
- err = set_pedit_val(htype, ~mask, val, offset, &masks[cmd], &vals[cmd]);
+ if (!parse_attr->mod_hdr_actions) {
+ err = alloc_mod_hdr_actions(priv, hdrs, namespace, parse_attr);
if (err)
goto out_err;
}
- err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
- if (err)
- goto out_err;
-
- err = offload_pedit_fields(masks, vals, parse_attr, extack);
+ err = offload_pedit_fields(hdrs, parse_attr, extack);
if (err < 0)
goto out_dealloc_parsed_actions;
for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
- cmd_masks = &masks[cmd];
+ cmd_masks = &hdrs[cmd].masks;
if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
NL_SET_ERR_MSG_MOD(extack,
"attempt to offload an unsupported field");
@@ -2178,17 +2159,22 @@ static bool csum_offload_supported(struct mlx5e_priv *priv,
}
static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
- struct tcf_exts *exts,
+ struct flow_action *flow_action,
+ u32 actions,
struct netlink_ext_ack *extack)
{
- const struct tc_action *a;
+ const struct flow_action_entry *act;
bool modify_ip_header;
u8 htype, ip_proto;
void *headers_v;
u16 ethertype;
- int nkeys, i;
+ int i;
+
+ if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+ headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
+ else
+ headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
- headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
/* for non-IP we only re-write MACs, so we're okay */
@@ -2196,20 +2182,16 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
goto out_ok;
modify_ip_header = false;
- tcf_exts_for_each_action(i, a, exts) {
- int k;
-
- if (!is_tcf_pedit(a))
+ flow_action_for_each(i, act, flow_action) {
+ if (act->id != FLOW_ACTION_MANGLE &&
+ act->id != FLOW_ACTION_ADD)
continue;
- nkeys = tcf_pedit_nkeys(a);
- for (k = 0; k < nkeys; k++) {
- htype = tcf_pedit_htype(a, k);
- if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 ||
- htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) {
- modify_ip_header = true;
- break;
- }
+ htype = act->mangle.htype;
+ if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4 ||
+ htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) {
+ modify_ip_header = true;
+ break;
}
}
@@ -2227,7 +2209,7 @@ out_ok:
}
static bool actions_match_supported(struct mlx5e_priv *priv,
- struct tcf_exts *exts,
+ struct flow_action *flow_action,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow,
struct netlink_ext_ack *extack)
@@ -2244,7 +2226,8 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
return false;
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
- return modify_header_match_supported(&parse_attr->spec, exts,
+ return modify_header_match_supported(&parse_attr->spec,
+ flow_action, actions,
extack);
return true;
@@ -2264,52 +2247,50 @@ static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
return (fsystem_guid == psystem_guid);
}
-static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+static int parse_tc_nic_actions(struct mlx5e_priv *priv,
+ struct flow_action *flow_action,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow,
struct netlink_ext_ack *extack)
{
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
- const struct tc_action *a;
+ struct pedit_headers_action hdrs[2] = {};
+ const struct flow_action_entry *act;
u32 action = 0;
int err, i;
- if (!tcf_exts_has_actions(exts))
+ if (!flow_action_has_entries(flow_action))
return -EINVAL;
attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
- tcf_exts_for_each_action(i, a, exts) {
- if (is_tcf_gact_shot(a)) {
+ flow_action_for_each(i, act, flow_action) {
+ switch (act->id) {
+ case FLOW_ACTION_DROP:
action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
if (MLX5_CAP_FLOWTABLE(priv->mdev,
flow_table_properties_nic_receive.flow_counter))
action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
- continue;
- }
-
- if (is_tcf_pedit(a)) {
- err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL,
- parse_attr, extack);
+ break;
+ case FLOW_ACTION_MANGLE:
+ case FLOW_ACTION_ADD:
+ err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL,
+ parse_attr, hdrs, extack);
if (err)
return err;
action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- continue;
- }
-
- if (is_tcf_csum(a)) {
+ break;
+ case FLOW_ACTION_CSUM:
if (csum_offload_supported(priv, action,
- tcf_csum_update_flags(a),
+ act->csum_flags,
extack))
- continue;
+ break;
return -EOPNOTSUPP;
- }
-
- if (is_tcf_mirred_egress_redirect(a)) {
- struct net_device *peer_dev = tcf_mirred_dev(a);
+ case FLOW_ACTION_REDIRECT: {
+ struct net_device *peer_dev = act->dev;
if (priv->netdev->netdev_ops == peer_dev->netdev_ops &&
same_hw_devs(priv, netdev_priv(peer_dev))) {
@@ -2324,11 +2305,10 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
peer_dev->name);
return -EINVAL;
}
- continue;
- }
-
- if (is_tcf_skbedit_mark(a)) {
- u32 mark = tcf_skbedit_mark(a);
+ }
+ break;
+ case FLOW_ACTION_MARK: {
+ u32 mark = act->mark;
if (mark & ~MLX5E_TC_FLOW_ID_MASK) {
NL_SET_ERR_MSG_MOD(extack,
@@ -2338,14 +2318,23 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
attr->flow_tag = mark;
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
- continue;
+ }
+ break;
+ default:
+ return -EINVAL;
}
+ }
- return -EINVAL;
+ if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
+ hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
+ err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
+ parse_attr, hdrs, extack);
+ if (err)
+ return err;
}
attr->action = action;
- if (!actions_match_supported(priv, exts, parse_attr, flow, extack))
+ if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
return -EOPNOTSUPP;
return 0;
@@ -2371,31 +2360,37 @@ static bool is_merged_eswitch_dev(struct mlx5e_priv *priv,
peer_priv = netdev_priv(peer_netdev);
return (MLX5_CAP_ESW(priv->mdev, merged_eswitch) &&
- (priv->netdev->netdev_ops == peer_netdev->netdev_ops) &&
- same_hw_devs(priv, peer_priv) &&
- MLX5_VPORT_MANAGER(peer_priv->mdev) &&
- (peer_priv->mdev->priv.eswitch->mode == SRIOV_OFFLOADS));
+ mlx5e_eswitch_rep(priv->netdev) &&
+ mlx5e_eswitch_rep(peer_netdev) &&
+ same_hw_devs(priv, peer_priv));
}
static int mlx5e_attach_encap(struct mlx5e_priv *priv,
- struct ip_tunnel_info *tun_info,
- struct net_device *mirred_dev,
- struct net_device **encap_dev,
struct mlx5e_tc_flow *flow,
+ struct net_device *mirred_dev,
+ int out_index,
struct netlink_ext_ack *extack,
- int out_index)
+ struct net_device **encap_dev,
+ bool *encap_valid)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
- unsigned short family = ip_tunnel_info_af(tun_info);
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
- struct ip_tunnel_key *key = &tun_info->key;
+ struct mlx5e_tc_flow_parse_attr *parse_attr;
+ struct ip_tunnel_info *tun_info;
+ struct ip_tunnel_key *key;
struct mlx5e_encap_entry *e;
+ unsigned short family;
uintptr_t hash_key;
bool found = false;
int err = 0;
+ parse_attr = attr->parse_attr;
+ tun_info = &parse_attr->tun_info[out_index];
+ family = ip_tunnel_info_af(tun_info);
+ key = &tun_info->key;
+
hash_key = hash_encap_info(key);
hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
@@ -2426,7 +2421,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
else if (family == AF_INET6)
err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e);
- if (err && err != -EAGAIN)
+ if (err)
goto out_err;
hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
@@ -2438,8 +2433,9 @@ attach_flow:
if (e->flags & MLX5_ENCAP_ENTRY_VALID) {
attr->dests[out_index].encap_id = e->encap_id;
attr->dests[out_index].flags |= MLX5_ESW_DEST_ENCAP_VALID;
+ *encap_valid = true;
} else {
- err = -EAGAIN;
+ *encap_valid = false;
}
return err;
@@ -2450,7 +2446,7 @@ out_err:
}
static int parse_tc_vlan_action(struct mlx5e_priv *priv,
- const struct tc_action *a,
+ const struct flow_action_entry *act,
struct mlx5_esw_flow_attr *attr,
u32 *action)
{
@@ -2459,7 +2455,8 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
if (vlan_idx >= MLX5_FS_VLAN_DEPTH)
return -EOPNOTSUPP;
- if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
+ switch (act->id) {
+ case FLOW_ACTION_VLAN_POP:
if (vlan_idx) {
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
MLX5_FS_VLAN_DEPTH))
@@ -2469,10 +2466,11 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
} else {
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
}
- } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
- attr->vlan_vid[vlan_idx] = tcf_vlan_push_vid(a);
- attr->vlan_prio[vlan_idx] = tcf_vlan_push_prio(a);
- attr->vlan_proto[vlan_idx] = tcf_vlan_push_proto(a);
+ break;
+ case FLOW_ACTION_VLAN_PUSH:
+ attr->vlan_vid[vlan_idx] = act->vlan.vid;
+ attr->vlan_prio[vlan_idx] = act->vlan.prio;
+ attr->vlan_proto[vlan_idx] = act->vlan.proto;
if (!attr->vlan_proto[vlan_idx])
attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
@@ -2484,13 +2482,15 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
} else {
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
- (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) ||
- tcf_vlan_push_prio(a)))
+ (act->vlan.proto != htons(ETH_P_8021Q) ||
+ act->vlan.prio))
return -EOPNOTSUPP;
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
}
- } else { /* action is TCA_VLAN_ACT_MODIFY */
+ break;
+ default:
+ /* action is FLOW_ACT_VLAN_MANGLE */
return -EOPNOTSUPP;
}
@@ -2499,58 +2499,56 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
return 0;
}
-static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
+ struct flow_action *flow_action,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow,
struct netlink_ext_ack *extack)
{
+ struct pedit_headers_action hdrs[2] = {};
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
- struct ip_tunnel_info *info = NULL;
- const struct tc_action *a;
+ const struct ip_tunnel_info *info = NULL;
+ const struct flow_action_entry *act;
bool encap = false;
u32 action = 0;
int err, i;
- if (!tcf_exts_has_actions(exts))
+ if (!flow_action_has_entries(flow_action))
return -EINVAL;
attr->in_rep = rpriv->rep;
attr->in_mdev = priv->mdev;
- tcf_exts_for_each_action(i, a, exts) {
- if (is_tcf_gact_shot(a)) {
+ flow_action_for_each(i, act, flow_action) {
+ switch (act->id) {
+ case FLOW_ACTION_DROP:
action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
MLX5_FLOW_CONTEXT_ACTION_COUNT;
- continue;
- }
-
- if (is_tcf_pedit(a)) {
- err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
- parse_attr, extack);
+ break;
+ case FLOW_ACTION_MANGLE:
+ case FLOW_ACTION_ADD:
+ err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB,
+ parse_attr, hdrs, extack);
if (err)
return err;
action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
attr->split_count = attr->out_count;
- continue;
- }
-
- if (is_tcf_csum(a)) {
+ break;
+ case FLOW_ACTION_CSUM:
if (csum_offload_supported(priv, action,
- tcf_csum_update_flags(a),
- extack))
- continue;
+ act->csum_flags, extack))
+ break;
return -EOPNOTSUPP;
- }
-
- if (is_tcf_mirred_egress_redirect(a) || is_tcf_mirred_egress_mirror(a)) {
+ case FLOW_ACTION_REDIRECT:
+ case FLOW_ACTION_MIRRED: {
struct mlx5e_priv *out_priv;
struct net_device *out_dev;
- out_dev = tcf_mirred_dev(a);
+ out_dev = act->dev;
if (!out_dev) {
/* out_dev is NULL when filters with
* non-existing mirred device are replayed to
@@ -2569,8 +2567,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
MLX5_FLOW_CONTEXT_ACTION_COUNT;
- if (switchdev_port_same_parent_id(priv->netdev,
- out_dev) ||
+ if (netdev_port_same_parent_id(priv->netdev,
+ out_dev) ||
is_merged_eswitch_dev(priv, out_dev)) {
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
@@ -2615,35 +2613,29 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
priv->netdev->name, out_dev->name);
return -EINVAL;
}
- continue;
- }
-
- if (is_tcf_tunnel_set(a)) {
- info = tcf_tunnel_info(a);
+ }
+ break;
+ case FLOW_ACTION_TUNNEL_ENCAP:
+ info = act->tunnel;
if (info)
encap = true;
else
return -EOPNOTSUPP;
- continue;
- }
-
- if (is_tcf_vlan(a)) {
- err = parse_tc_vlan_action(priv, a, attr, &action);
+ break;
+ case FLOW_ACTION_VLAN_PUSH:
+ case FLOW_ACTION_VLAN_POP:
+ err = parse_tc_vlan_action(priv, act, attr, &action);
if (err)
return err;
attr->split_count = attr->out_count;
- continue;
- }
-
- if (is_tcf_tunnel_release(a)) {
+ break;
+ case FLOW_ACTION_TUNNEL_DECAP:
action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
- continue;
- }
-
- if (is_tcf_gact_goto_chain(a)) {
- u32 dest_chain = tcf_gact_goto_chain_index(a);
+ break;
+ case FLOW_ACTION_GOTO: {
+ u32 dest_chain = act->chain_index;
u32 max_chain = mlx5_eswitch_get_chain_range(esw);
if (dest_chain <= attr->chain) {
@@ -2656,15 +2648,23 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
}
action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
attr->dest_chain = dest_chain;
-
- continue;
+ break;
+ }
+ default:
+ return -EINVAL;
}
+ }
- return -EINVAL;
+ if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
+ hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
+ err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
+ parse_attr, hdrs, extack);
+ if (err)
+ return err;
}
attr->action = action;
- if (!actions_match_supported(priv, exts, parse_attr, flow, extack))
+ if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
return -EOPNOTSUPP;
if (attr->dest_chain) {
@@ -2724,15 +2724,22 @@ static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, int flags)
static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
{
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
- bool is_rep_ingress = attr->in_rep->vport != FDB_UPLINK_VPORT &&
+ bool is_rep_ingress = attr->in_rep->vport != MLX5_VPORT_UPLINK &&
flow->flags & MLX5E_TC_FLOW_INGRESS;
bool act_is_encap = !!(attr->action &
MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT);
bool esw_paired = mlx5_devcom_is_paired(attr->in_mdev->priv.devcom,
MLX5_DEVCOM_ESW_OFFLOADS);
- return esw_paired && mlx5_lag_is_sriov(attr->in_mdev) &&
- (is_rep_ingress || act_is_encap);
+ if (!esw_paired)
+ return false;
+
+ if ((mlx5_lag_is_sriov(attr->in_mdev) ||
+ mlx5_lag_is_multipath(attr->in_mdev)) &&
+ (is_rep_ingress || act_is_encap))
+ return true;
+
+ return false;
}
static int
@@ -2767,17 +2774,40 @@ err_free:
return err;
}
-static int
+static void
+mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
+ struct mlx5e_priv *priv,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct tc_cls_flower_offload *f,
+ struct mlx5_eswitch_rep *in_rep,
+ struct mlx5_core_dev *in_mdev)
+{
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+ esw_attr->parse_attr = parse_attr;
+ esw_attr->chain = f->common.chain_index;
+ esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
+
+ esw_attr->in_rep = in_rep;
+ esw_attr->in_mdev = in_mdev;
+
+ if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) ==
+ MLX5_COUNTER_SOURCE_ESWITCH)
+ esw_attr->counter_dev = in_mdev;
+ else
+ esw_attr->counter_dev = priv->mdev;
+}
+
+static struct mlx5e_tc_flow *
__mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *f,
u16 flow_flags,
struct net_device *filter_dev,
struct mlx5_eswitch_rep *in_rep,
- struct mlx5_core_dev *in_mdev,
- struct mlx5e_tc_flow **__flow)
+ struct mlx5_core_dev *in_mdev)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
struct netlink_ext_ack *extack = f->common.extack;
- struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5e_tc_flow_parse_attr *parse_attr;
struct mlx5e_tc_flow *flow;
int attr_size, err;
@@ -2788,45 +2818,41 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
&parse_attr, &flow);
if (err)
goto out;
+
parse_attr->filter_dev = filter_dev;
- flow->esw_attr->parse_attr = parse_attr;
+ mlx5e_flow_esw_attr_init(flow->esw_attr,
+ priv, parse_attr,
+ f, in_rep, in_mdev);
+
err = parse_cls_flower(flow->priv, flow, &parse_attr->spec,
f, filter_dev);
if (err)
goto err_free;
- flow->esw_attr->chain = f->common.chain_index;
- flow->esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
- err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow, extack);
+ err = parse_tc_fdb_actions(priv, &rule->action, parse_attr, flow, extack);
if (err)
goto err_free;
- flow->esw_attr->in_rep = in_rep;
- flow->esw_attr->in_mdev = in_mdev;
-
- if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) ==
- MLX5_COUNTER_SOURCE_ESWITCH)
- flow->esw_attr->counter_dev = in_mdev;
- else
- flow->esw_attr->counter_dev = priv->mdev;
-
- err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow, extack);
- if (err)
- goto err_free;
+ err = mlx5e_tc_add_fdb_flow(priv, flow, extack);
+ if (err) {
+ if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev)))
+ goto err_free;
- *__flow = flow;
+ add_unready_flow(flow);
+ }
- return 0;
+ return flow;
err_free:
kfree(flow);
kvfree(parse_attr);
out:
- return err;
+ return ERR_PTR(err);
}
static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f,
- struct mlx5e_tc_flow *flow)
+ struct mlx5e_tc_flow *flow,
+ u16 flow_flags)
{
struct mlx5e_priv *priv = flow->priv, *peer_priv;
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw;
@@ -2849,17 +2875,19 @@ static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f,
* original flow and packets redirected from uplink use the
* peer mdev.
*/
- if (flow->esw_attr->in_rep->vport == FDB_UPLINK_VPORT)
+ if (flow->esw_attr->in_rep->vport == MLX5_VPORT_UPLINK)
in_mdev = peer_priv->mdev;
else
in_mdev = priv->mdev;
parse_attr = flow->esw_attr->parse_attr;
- err = __mlx5e_add_fdb_flow(peer_priv, f, flow->flags,
- parse_attr->filter_dev,
- flow->esw_attr->in_rep, in_mdev, &peer_flow);
- if (err)
+ peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
+ parse_attr->filter_dev,
+ flow->esw_attr->in_rep, in_mdev);
+ if (IS_ERR(peer_flow)) {
+ err = PTR_ERR(peer_flow);
goto out;
+ }
flow->peer_flow = peer_flow;
flow->flags |= MLX5E_TC_FLOW_DUP;
@@ -2885,13 +2913,13 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow;
int err;
- err = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
- in_mdev, &flow);
- if (err)
- goto out;
+ flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
+ in_mdev);
+ if (IS_ERR(flow))
+ return PTR_ERR(flow);
if (is_peer_flow_needed(flow)) {
- err = mlx5e_tc_add_fdb_peer_flow(f, flow);
+ err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags);
if (err) {
mlx5e_tc_del_fdb_flow(priv, flow);
goto out;
@@ -2913,6 +2941,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv,
struct net_device *filter_dev,
struct mlx5e_tc_flow **__flow)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
struct netlink_ext_ack *extack = f->common.extack;
struct mlx5e_tc_flow_parse_attr *parse_attr;
struct mlx5e_tc_flow *flow;
@@ -2935,7 +2964,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv,
if (err)
goto err_free;
- err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow, extack);
+ err = parse_tc_nic_actions(priv, &rule->action, parse_attr, flow, extack);
if (err)
goto err_free;
@@ -3055,23 +3084,25 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
struct mlx5_eswitch *peer_esw;
struct mlx5e_tc_flow *flow;
struct mlx5_fc *counter;
- u64 bytes;
- u64 packets;
- u64 lastuse;
+ u64 lastuse = 0;
+ u64 packets = 0;
+ u64 bytes = 0;
flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params);
if (!flow || !same_flow_direction(flow, flags))
return -EINVAL;
- if (!(flow->flags & MLX5E_TC_FLOW_OFFLOADED))
- return 0;
-
- counter = mlx5e_tc_get_counter(flow);
- if (!counter)
- return 0;
+ if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
+ counter = mlx5e_tc_get_counter(flow);
+ if (!counter)
+ return 0;
- mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+ mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+ }
+ /* Under multipath it's possible for one rule to be currently
+ * un-offloaded while the other rule is offloaded.
+ */
peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
if (!peer_esw)
goto out;
@@ -3083,6 +3114,8 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
u64 lastuse2;
counter = mlx5e_tc_get_counter(flow->peer_flow);
+ if (!counter)
+ goto no_peer_counter;
mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
bytes += bytes2;
@@ -3090,10 +3123,10 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
lastuse = max_t(u64, lastuse, lastuse2);
}
+no_peer_counter:
mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
-
out:
- tcf_exts_stats_update(f->exts, bytes, packets, lastuse);
+ flow_stats_update(&f->stats, bytes, packets, lastuse);
return 0;
}
@@ -3213,3 +3246,18 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
__mlx5e_tc_del_fdb_peer_flow(flow);
}
+
+void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
+{
+ struct mlx5_rep_uplink_priv *rpriv =
+ container_of(work, struct mlx5_rep_uplink_priv,
+ reoffload_flows_work);
+ struct mlx5e_tc_flow *flow, *tmp;
+
+ rtnl_lock();
+ list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) {
+ if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL))
+ remove_unready_flow(flow);
+ }
+ rtnl_unlock();
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
index d2d87f978c06..f62e81902d27 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
@@ -72,6 +72,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe);
int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags);
+void mlx5e_tc_reoffload_flows_work(struct work_struct *work);
#else /* CONFIG_MLX5_ESWITCH */
static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index 598ad7e4d5c9..25a8f8260c14 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -148,12 +148,8 @@ static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb)
static inline int mlx5e_skb_l3_header_offset(struct sk_buff *skb)
{
- struct flow_keys keys;
-
if (skb_transport_header_was_set(skb))
return skb_transport_offset(skb);
- else if (skb_flow_dissect_flow_keys(skb, &keys, 0))
- return keys.control.thoff;
else
return mlx5e_skb_l2_header_offset(skb);
}
@@ -172,15 +168,8 @@ static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode,
hlen += VLAN_HLEN;
break;
case MLX5_INLINE_MODE_IP:
- /* When transport header is set to zero, it means no transport
- * header. When transport header is set to 0xff's, it means
- * transport header wasn't set.
- */
- if (skb_transport_offset(skb)) {
- hlen = mlx5e_skb_l3_header_offset(skb);
- break;
- }
- /* fall through */
+ hlen = mlx5e_skb_l3_header_offset(skb);
+ break;
case MLX5_INLINE_MODE_L2:
default:
hlen = mlx5e_skb_l2_header_offset(skb);
@@ -387,8 +376,14 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
if (unlikely(contig_wqebbs_room < num_wqebbs)) {
+#ifdef CONFIG_MLX5_EN_IPSEC
+ struct mlx5_wqe_eth_seg cur_eth = wqe->eth;
+#endif
mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
mlx5e_sq_fetch_wqe(sq, &wqe, &pi);
+#ifdef CONFIG_MLX5_EN_IPSEC
+ wqe->eth = cur_eth;
+#endif
}
/* fill wqe */
@@ -514,7 +509,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
mlx5e_dump_error_cqe(sq,
(struct mlx5_err_cqe *)cqe);
queue_work(cq->channel->priv->wq,
- &sq->recover.recover_work);
+ &sq->recover_work);
}
stats->cqe_err++;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index ee04aab65a9f..bb6e5b5d9681 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -34,6 +34,7 @@
#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
+#include <linux/mlx5/vport.h>
#include <linux/mlx5/eq.h>
#include <linux/mlx5/cmd.h>
#ifdef CONFIG_RFS_ACCEL
@@ -114,11 +115,11 @@ static struct mlx5_core_cq *mlx5_eq_cq_get(struct mlx5_eq *eq, u32 cqn)
struct mlx5_cq_table *table = &eq->cq_table;
struct mlx5_core_cq *cq = NULL;
- spin_lock(&table->lock);
+ rcu_read_lock();
cq = radix_tree_lookup(&table->tree, cqn);
if (likely(cq))
mlx5_cq_hold(cq);
- spin_unlock(&table->lock);
+ rcu_read_unlock();
return cq;
}
@@ -371,9 +372,9 @@ int mlx5_eq_add_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq)
struct mlx5_cq_table *table = &eq->cq_table;
int err;
- spin_lock_irq(&table->lock);
+ spin_lock(&table->lock);
err = radix_tree_insert(&table->tree, cq->cqn, cq);
- spin_unlock_irq(&table->lock);
+ spin_unlock(&table->lock);
return err;
}
@@ -383,9 +384,9 @@ int mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq)
struct mlx5_cq_table *table = &eq->cq_table;
struct mlx5_core_cq *tmp;
- spin_lock_irq(&table->lock);
+ spin_lock(&table->lock);
tmp = radix_tree_delete(&table->tree, cq->cqn);
- spin_unlock_irq(&table->lock);
+ spin_unlock(&table->lock);
if (!tmp) {
mlx5_core_warn(eq->dev, "cq 0x%x not found in eq 0x%x tree\n", eq->eqn, cq->cqn);
@@ -530,6 +531,9 @@ static u64 gather_async_events_mask(struct mlx5_core_dev *dev)
if (MLX5_CAP_GEN(dev, max_num_of_monitor_counters))
async_event_mask |= (1ull << MLX5_EVENT_TYPE_MONITOR_COUNTER);
+ if (mlx5_core_is_ecpf_esw_manager(dev))
+ async_event_mask |= (1ull << MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE);
+
return async_event_mask;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index a44ea7b85614..d0b28251abf2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -39,8 +39,7 @@
#include "lib/eq.h"
#include "eswitch.h"
#include "fs_core.h"
-
-#define UPLINK_VPORT 0xFFFF
+#include "ecpf.h"
enum {
MLX5_ACTION_NONE = 0,
@@ -52,7 +51,7 @@ enum {
struct vport_addr {
struct l2addr_node node;
u8 action;
- u32 vport;
+ u16 vport;
struct mlx5_flow_handle *flow_rule;
bool mpfs; /* UC MAC was added to MPFs */
/* A flag indicating that mac was added due to mc promiscuous vport */
@@ -65,11 +64,36 @@ enum {
PROMISC_CHANGE = BIT(3),
};
+static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
+static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
+
/* Vport context events */
#define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \
MC_ADDR_CHANGE | \
PROMISC_CHANGE)
+/* The vport getter/iterator are only valid after esw->total_vports
+ * and vport->vport are initialized in mlx5_eswitch_init.
+ */
+#define mlx5_esw_for_all_vports(esw, i, vport) \
+ for ((i) = MLX5_VPORT_PF; \
+ (vport) = &(esw)->vports[i], \
+ (i) < (esw)->total_vports; (i)++)
+
+#define mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs) \
+ for ((i) = MLX5_VPORT_FIRST_VF; \
+ (vport) = &(esw)->vports[i], \
+ (i) <= (nvfs); (i)++)
+
+static struct mlx5_vport *mlx5_eswitch_get_vport(struct mlx5_eswitch *esw,
+ u16 vport_num)
+{
+ u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
+
+ WARN_ON(idx > esw->total_vports - 1);
+ return &esw->vports[idx];
+}
+
static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
u32 events_mask)
{
@@ -115,7 +139,7 @@ static int modify_esw_vport_context_cmd(struct mlx5_core_dev *dev, u16 vport,
return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
}
-static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport,
+static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
u16 vlan, u8 qos, u8 set_flags)
{
u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {0};
@@ -152,7 +176,7 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport,
/* E-Switch FDB */
static struct mlx5_flow_handle *
-__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
+__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule,
u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
{
int match_header = (is_zero_ether_addr(mac_c) ? 0 :
@@ -188,7 +212,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
misc_parameters);
mc_misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
misc_parameters);
- MLX5_SET(fte_match_set_misc, mv_misc, source_port, UPLINK_VPORT);
+ MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK);
MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
}
@@ -215,7 +239,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
}
static struct mlx5_flow_handle *
-esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
+esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport)
{
u8 mac_c[ETH_ALEN];
@@ -224,7 +248,7 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
}
static struct mlx5_flow_handle *
-esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
+esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport)
{
u8 mac_c[ETH_ALEN];
u8 mac_v[ETH_ALEN];
@@ -237,7 +261,7 @@ esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
}
static struct mlx5_flow_handle *
-esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport)
+esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
{
u8 mac_c[ETH_ALEN];
u8 mac_v[ETH_ALEN];
@@ -247,6 +271,37 @@ esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport)
return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
}
+enum {
+ LEGACY_VEPA_PRIO = 0,
+ LEGACY_FDB_PRIO,
+};
+
+static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
+{
+ struct mlx5_core_dev *dev = esw->dev;
+ struct mlx5_flow_namespace *root_ns;
+ struct mlx5_flow_table *fdb;
+ int err;
+
+ root_ns = mlx5_get_fdb_sub_ns(dev, 0);
+ if (!root_ns) {
+ esw_warn(dev, "Failed to get FDB flow namespace\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* num FTE 2, num FG 2 */
+ fdb = mlx5_create_auto_grouped_flow_table(root_ns, LEGACY_VEPA_PRIO,
+ 2, 2, 0, 0);
+ if (IS_ERR(fdb)) {
+ err = PTR_ERR(fdb);
+ esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
+ return err;
+ }
+ esw->fdb_table.legacy.vepa_fdb = fdb;
+
+ return 0;
+}
+
static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
@@ -275,8 +330,8 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
return -ENOMEM;
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
-
ft_attr.max_fte = table_size;
+ ft_attr.prio = LEGACY_FDB_PRIO;
fdb = mlx5_create_flow_table(root_ns, &ft_attr);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
@@ -335,41 +390,65 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
esw->fdb_table.legacy.promisc_grp = g;
out:
- if (err) {
- if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.allmulti_grp)) {
- mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
- esw->fdb_table.legacy.allmulti_grp = NULL;
- }
- if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.addr_grp)) {
- mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
- esw->fdb_table.legacy.addr_grp = NULL;
- }
- if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.fdb)) {
- mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
- esw->fdb_table.legacy.fdb = NULL;
- }
- }
+ if (err)
+ esw_destroy_legacy_fdb_table(esw);
kvfree(flow_group_in);
return err;
}
+static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
+{
+ esw_debug(esw->dev, "Destroy VEPA Table\n");
+ if (!esw->fdb_table.legacy.vepa_fdb)
+ return;
+
+ mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
+ esw->fdb_table.legacy.vepa_fdb = NULL;
+}
+
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
{
+ esw_debug(esw->dev, "Destroy FDB Table\n");
if (!esw->fdb_table.legacy.fdb)
return;
- esw_debug(esw->dev, "Destroy FDB Table\n");
- mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
- mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
- mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
+ if (esw->fdb_table.legacy.promisc_grp)
+ mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
+ if (esw->fdb_table.legacy.allmulti_grp)
+ mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
+ if (esw->fdb_table.legacy.addr_grp)
+ mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
+
esw->fdb_table.legacy.fdb = NULL;
esw->fdb_table.legacy.addr_grp = NULL;
esw->fdb_table.legacy.allmulti_grp = NULL;
esw->fdb_table.legacy.promisc_grp = NULL;
}
+static int esw_create_legacy_table(struct mlx5_eswitch *esw)
+{
+ int err;
+
+ err = esw_create_legacy_vepa_table(esw);
+ if (err)
+ return err;
+
+ err = esw_create_legacy_fdb_table(esw);
+ if (err)
+ esw_destroy_legacy_vepa_table(esw);
+
+ return err;
+}
+
+static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
+{
+ esw_cleanup_vepa_rules(esw);
+ esw_destroy_legacy_fdb_table(esw);
+ esw_destroy_legacy_vepa_table(esw);
+}
+
/* E-Switch vport UC/MC lists management */
typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
struct vport_addr *vaddr);
@@ -377,19 +456,19 @@ typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
{
u8 *mac = vaddr->node.addr;
- u32 vport = vaddr->vport;
+ u16 vport = vaddr->vport;
int err;
- /* Skip mlx5_mpfs_add_mac for PFs,
- * it is already done by the PF netdev in mlx5e_execute_l2_action
+ /* Skip mlx5_mpfs_add_mac for eswitch_managers,
+ * it is already done by its netdev in mlx5e_execute_l2_action
*/
- if (!vport)
+ if (esw->manager_vport == vport)
goto fdb_add;
err = mlx5_mpfs_add_mac(esw->dev, mac);
if (err) {
esw_warn(esw->dev,
- "Failed to add L2 table mac(%pM) for vport(%d), err(%d)\n",
+ "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n",
mac, vport, err);
return err;
}
@@ -409,13 +488,13 @@ fdb_add:
static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
{
u8 *mac = vaddr->node.addr;
- u32 vport = vaddr->vport;
+ u16 vport = vaddr->vport;
int err = 0;
- /* Skip mlx5_mpfs_del_mac for PFs,
- * it is already done by the PF netdev in mlx5e_execute_l2_action
+ /* Skip mlx5_mpfs_del_mac for eswitch managerss,
+ * it is already done by its netdev in mlx5e_execute_l2_action
*/
- if (!vport || !vaddr->mpfs)
+ if (!vaddr->mpfs || esw->manager_vport == vport)
goto fdb_del;
err = mlx5_mpfs_del_mac(esw->dev, mac);
@@ -438,17 +517,18 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw,
struct esw_mc_addr *esw_mc)
{
u8 *mac = vaddr->node.addr;
- u32 vport_idx = 0;
+ struct mlx5_vport *vport;
+ u16 i, vport_num;
- for (vport_idx = 0; vport_idx < esw->total_vports; vport_idx++) {
- struct mlx5_vport *vport = &esw->vports[vport_idx];
+ mlx5_esw_for_all_vports(esw, i, vport) {
struct hlist_head *vport_hash = vport->mc_list;
struct vport_addr *iter_vaddr =
l2addr_hash_find(vport_hash,
mac,
struct vport_addr);
+ vport_num = vport->vport;
if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
- vaddr->vport == vport_idx)
+ vaddr->vport == vport_num)
continue;
switch (vaddr->action) {
case MLX5_ACTION_ADD:
@@ -460,14 +540,14 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw,
if (!iter_vaddr) {
esw_warn(esw->dev,
"ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
- mac, vport_idx);
+ mac, vport_num);
continue;
}
- iter_vaddr->vport = vport_idx;
+ iter_vaddr->vport = vport_num;
iter_vaddr->flow_rule =
esw_fdb_set_vport_rule(esw,
mac,
- vport_idx);
+ vport_num);
iter_vaddr->mc_promisc = true;
break;
case MLX5_ACTION_DEL:
@@ -485,7 +565,7 @@ static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
struct hlist_head *hash = esw->mc_table;
struct esw_mc_addr *esw_mc;
u8 *mac = vaddr->node.addr;
- u32 vport = vaddr->vport;
+ u16 vport = vaddr->vport;
if (!esw->fdb_table.legacy.fdb)
return 0;
@@ -499,7 +579,7 @@ static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
return -ENOMEM;
esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
- esw_fdb_set_vport_rule(esw, mac, UPLINK_VPORT);
+ esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK);
/* Add this multicast mac to all the mc promiscuous vports */
update_allmulti_vports(esw, vaddr, esw_mc);
@@ -525,7 +605,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
struct hlist_head *hash = esw->mc_table;
struct esw_mc_addr *esw_mc;
u8 *mac = vaddr->node.addr;
- u32 vport = vaddr->vport;
+ u16 vport = vaddr->vport;
if (!esw->fdb_table.legacy.fdb)
return 0;
@@ -564,9 +644,9 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
/* Apply vport UC/MC list to HW l2 table and FDB table */
static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
- u32 vport_num, int list_type)
+ u16 vport_num, int list_type)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
vport_addr_action vport_addr_add;
vport_addr_action vport_addr_del;
@@ -599,9 +679,9 @@ static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
/* Sync vport UC/MC list from vport context */
static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
- u32 vport_num, int list_type)
+ u16 vport_num, int list_type)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
u8 (*mac_list)[ETH_ALEN];
struct l2addr_node *node;
@@ -686,9 +766,9 @@ out:
/* Sync vport UC/MC list from vport context
* Must be called after esw_update_vport_addr_list
*/
-static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u32 vport_num)
+static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u16 vport_num)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
struct l2addr_node *node;
struct vport_addr *addr;
struct hlist_head *hash;
@@ -721,11 +801,11 @@ static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u32 vport_num)
}
/* Apply vport rx mode to HW FDB table */
-static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num,
+static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num,
bool promisc, bool mc_promisc)
{
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
- struct mlx5_vport *vport = &esw->vports[vport_num];
if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
goto promisc;
@@ -736,7 +816,7 @@ static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num,
if (!allmulti_addr->uplink_rule)
allmulti_addr->uplink_rule =
esw_fdb_set_vport_allmulti_rule(esw,
- UPLINK_VPORT);
+ MLX5_VPORT_UPLINK);
allmulti_addr->refcnt++;
} else if (vport->allmulti_rule) {
mlx5_del_flow_rules(vport->allmulti_rule);
@@ -764,9 +844,9 @@ promisc:
}
/* Sync vport rx mode from vport context */
-static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num)
+static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
int promisc_all = 0;
int promisc_uc = 0;
int promisc_mc = 0;
@@ -1134,13 +1214,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
int err = 0;
u8 *smac_v;
- if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
- mlx5_core_warn(esw->dev,
- "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
- vport->vport);
- return -EPERM;
- }
-
esw_vport_cleanup_ingress_rules(esw, vport);
if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
@@ -1350,8 +1423,8 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw)
static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
u32 initial_max_rate, u32 initial_bw_share)
{
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
- struct mlx5_vport *vport = &esw->vports[vport_num];
struct mlx5_core_dev *dev = esw->dev;
void *vport_elem;
int err = 0;
@@ -1390,7 +1463,7 @@ static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
int err = 0;
if (!vport->qos.enabled)
@@ -1409,8 +1482,8 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
u32 max_rate, u32 bw_share)
{
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
- struct mlx5_vport *vport = &esw->vports[vport_num];
struct mlx5_core_dev *dev = esw->dev;
void *vport_elem;
u32 bitmask = 0;
@@ -1466,15 +1539,22 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
{
int vport_num = vport->vport;
- if (!vport_num)
+ if (esw->manager_vport == vport_num)
return;
mlx5_modify_vport_admin_state(esw->dev,
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
- vport_num,
+ vport_num, 1,
vport->info.link_state);
- mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, vport->info.mac);
- mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, vport->info.node_guid);
+
+ /* Host PF has its own mac/guid. */
+ if (vport_num) {
+ mlx5_modify_nic_vport_mac_address(esw->dev, vport_num,
+ vport->info.mac);
+ mlx5_modify_nic_vport_node_guid(esw->dev, vport_num,
+ vport->info.node_guid);
+ }
+
modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, vport->info.qos,
(vport->info.vlan || vport->info.qos));
@@ -1520,10 +1600,10 @@ static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport)
mlx5_fc_destroy(dev, vport->egress.drop_counter);
}
-static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
+static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
int enable_events)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ u16 vport_num = vport->vport;
mutex_lock(&esw->state_lock);
WARN_ON(vport->enabled);
@@ -1546,8 +1626,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
vport->enabled_events = enable_events;
vport->enabled = true;
- /* only PF is trusted by default */
- if (!vport_num)
+ /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
+ * in smartNIC as it's a vport group manager.
+ */
+ if (esw->manager_vport == vport_num ||
+ (!vport_num && mlx5_core_is_ecpf(esw->dev)))
vport->info.trusted = true;
esw_vport_change_handle_locked(vport);
@@ -1557,9 +1640,10 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
mutex_unlock(&esw->state_lock);
}
-static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num)
+static void esw_disable_vport(struct mlx5_eswitch *esw,
+ struct mlx5_vport *vport)
{
- struct mlx5_vport *vport = &esw->vports[vport_num];
+ u16 vport_num = vport->vport;
if (!vport->enabled)
return;
@@ -1580,10 +1664,11 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num)
esw_vport_change_handle_locked(vport);
vport->enabled_events = 0;
esw_vport_disable_qos(esw, vport_num);
- if (vport_num && esw->mode == SRIOV_LEGACY) {
+ if (esw->manager_vport != vport_num &&
+ esw->mode == SRIOV_LEGACY) {
mlx5_modify_vport_admin_state(esw->dev,
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
- vport_num,
+ vport_num, 1,
MLX5_VPORT_ADMIN_STATE_DOWN);
esw_vport_disable_egress_acl(esw, vport);
esw_vport_disable_ingress_acl(esw, vport);
@@ -1602,7 +1687,7 @@ static int eswitch_vport_event(struct notifier_block *nb,
u16 vport_num;
vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
- vport = &esw->vports[vport_num];
+ vport = mlx5_eswitch_get_vport(esw, vport_num);
if (vport->enabled)
queue_work(esw->work_queue, &vport->vport_change_handler);
@@ -1614,6 +1699,8 @@ static int eswitch_vport_event(struct notifier_block *nb,
int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
{
+ int vf_nvports = 0, total_nvports = 0;
+ struct mlx5_vport *vport;
int err;
int i, enabled_events;
@@ -1631,16 +1718,30 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode);
+ if (mode == SRIOV_OFFLOADS) {
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ err = mlx5_query_host_params_num_vfs(esw->dev, &vf_nvports);
+ if (err)
+ return err;
+ total_nvports = esw->total_vports;
+ } else {
+ vf_nvports = nvfs;
+ total_nvports = nvfs + MLX5_SPECIAL_VPORTS(esw->dev);
+ }
+ }
+
esw->mode = mode;
mlx5_lag_update(esw->dev);
if (mode == SRIOV_LEGACY) {
- err = esw_create_legacy_fdb_table(esw);
+ err = esw_create_legacy_table(esw);
+ if (err)
+ goto abort;
} else {
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
- err = esw_offloads_init(esw, nvfs + 1);
+ err = esw_offloads_init(esw, vf_nvports, total_nvports);
}
if (err)
@@ -1655,8 +1756,20 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
* 2. FDB/Eswitch is programmed by user space tools
*/
enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : 0;
- for (i = 0; i <= nvfs; i++)
- esw_enable_vport(esw, i, enabled_events);
+
+ /* Enable PF vport */
+ vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
+ esw_enable_vport(esw, vport, enabled_events);
+
+ /* Enable ECPF vports */
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
+ esw_enable_vport(esw, vport, enabled_events);
+ }
+
+ /* Enable VF vports */
+ mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs)
+ esw_enable_vport(esw, vport, enabled_events);
if (mode == SRIOV_LEGACY) {
MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
@@ -1681,8 +1794,8 @@ abort:
void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
{
struct esw_mc_addr *mc_promisc;
+ struct mlx5_vport *vport;
int old_mode;
- int nvports;
int i;
if (!ESW_ALLOWED(esw) || esw->mode == SRIOV_NONE)
@@ -1692,13 +1805,12 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
esw->enabled_vports, esw->mode);
mc_promisc = &esw->mc_promisc;
- nvports = esw->enabled_vports;
if (esw->mode == SRIOV_LEGACY)
mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
- for (i = 0; i < esw->total_vports; i++)
- esw_disable_vport(esw, i);
+ mlx5_esw_for_all_vports(esw, i, vport)
+ esw_disable_vport(esw, vport);
if (mc_promisc && mc_promisc->uplink_rule)
mlx5_del_flow_rules(mc_promisc->uplink_rule);
@@ -1706,9 +1818,9 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
esw_destroy_tsar(esw);
if (esw->mode == SRIOV_LEGACY)
- esw_destroy_legacy_fdb_table(esw);
+ esw_destroy_legacy_table(esw);
else if (esw->mode == SRIOV_OFFLOADS)
- esw_offloads_cleanup(esw, nvports);
+ esw_offloads_cleanup(esw);
old_mode = esw->mode;
esw->mode = SRIOV_NONE;
@@ -1725,10 +1837,10 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
{
int total_vports = MLX5_TOTAL_VPORTS(dev);
struct mlx5_eswitch *esw;
- int vport_num;
- int err;
+ struct mlx5_vport *vport;
+ int err, i;
- if (!MLX5_ESWITCH_MANAGER(dev))
+ if (!MLX5_VPORT_MANAGER(dev))
return 0;
esw_info(dev,
@@ -1742,6 +1854,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
return -ENOMEM;
esw->dev = dev;
+ esw->manager_vport = mlx5_eswitch_manager_vport(dev);
esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
if (!esw->work_queue) {
@@ -1756,6 +1869,8 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
goto abort;
}
+ esw->total_vports = total_vports;
+
err = esw_offloads_init_reps(esw);
if (err)
goto abort;
@@ -1764,17 +1879,14 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
hash_init(esw->offloads.mod_hdr_tbl);
mutex_init(&esw->state_lock);
- for (vport_num = 0; vport_num < total_vports; vport_num++) {
- struct mlx5_vport *vport = &esw->vports[vport_num];
-
- vport->vport = vport_num;
+ mlx5_esw_for_all_vports(esw, i, vport) {
+ vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
vport->dev = dev;
INIT_WORK(&vport->vport_change_handler,
esw_vport_change_handler);
}
- esw->total_vports = total_vports;
esw->enabled_vports = 0;
esw->mode = SRIOV_NONE;
esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
@@ -1797,7 +1909,7 @@ abort:
void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
{
- if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
+ if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
return;
esw_info(esw->dev, "cleanup\n");
@@ -1827,13 +1939,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
mutex_lock(&esw->state_lock);
evport = &esw->vports[vport];
- if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
+ if (evport->info.spoofchk && !is_valid_ether_addr(mac))
mlx5_core_warn(esw->dev,
- "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n",
+ "Set invalid MAC while spoofchk is on, vport(%d)\n",
vport);
- err = -EPERM;
- goto unlock;
- }
err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
if (err) {
@@ -1876,7 +1985,7 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
err = mlx5_modify_vport_admin_state(esw->dev,
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
- vport, link_state);
+ vport, 1, link_state);
if (err) {
mlx5_core_warn(esw->dev,
"Failed to set vport %d link state, err = %d",
@@ -1979,6 +2088,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
evport = &esw->vports[vport];
pschk = evport->info.spoofchk;
evport->info.spoofchk = spoofchk;
+ if (pschk && !is_valid_ether_addr(evport->info.mac))
+ mlx5_core_warn(esw->dev,
+ "Spoofchk in set while MAC is invalid, vport(%d)\n",
+ evport->vport);
if (evport->enabled && esw->mode == SRIOV_LEGACY)
err = esw_vport_ingress_config(esw, evport);
if (err)
@@ -1988,6 +2101,127 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
return err;
}
+static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
+{
+ if (esw->fdb_table.legacy.vepa_uplink_rule)
+ mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
+
+ if (esw->fdb_table.legacy.vepa_star_rule)
+ mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
+
+ esw->fdb_table.legacy.vepa_uplink_rule = NULL;
+ esw->fdb_table.legacy.vepa_star_rule = NULL;
+}
+
+static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
+ u8 setting)
+{
+ struct mlx5_flow_destination dest = {};
+ struct mlx5_flow_act flow_act = {};
+ struct mlx5_flow_handle *flow_rule;
+ struct mlx5_flow_spec *spec;
+ int err = 0;
+ void *misc;
+
+ if (!setting) {
+ esw_cleanup_vepa_rules(esw);
+ return 0;
+ }
+
+ if (esw->fdb_table.legacy.vepa_uplink_rule)
+ return 0;
+
+ spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return -ENOMEM;
+
+ /* Uplink rule forward uplink traffic to FDB */
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
+ MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
+
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
+ MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
+
+ spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+ dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+ dest.ft = esw->fdb_table.legacy.fdb;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
+ &flow_act, &dest, 1);
+ if (IS_ERR(flow_rule)) {
+ err = PTR_ERR(flow_rule);
+ goto out;
+ } else {
+ esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
+ }
+
+ /* Star rule to forward all traffic to uplink vport */
+ memset(spec, 0, sizeof(*spec));
+ dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
+ dest.vport.num = MLX5_VPORT_UPLINK;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
+ &flow_act, &dest, 1);
+ if (IS_ERR(flow_rule)) {
+ err = PTR_ERR(flow_rule);
+ goto out;
+ } else {
+ esw->fdb_table.legacy.vepa_star_rule = flow_rule;
+ }
+
+out:
+ kvfree(spec);
+ if (err)
+ esw_cleanup_vepa_rules(esw);
+ return err;
+}
+
+int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
+{
+ int err = 0;
+
+ if (!esw)
+ return -EOPNOTSUPP;
+
+ if (!ESW_ALLOWED(esw))
+ return -EPERM;
+
+ mutex_lock(&esw->state_lock);
+ if (esw->mode != SRIOV_LEGACY) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = _mlx5_eswitch_set_vepa_locked(esw, setting);
+
+out:
+ mutex_unlock(&esw->state_lock);
+ return err;
+}
+
+int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
+{
+ int err = 0;
+
+ if (!esw)
+ return -EOPNOTSUPP;
+
+ if (!ESW_ALLOWED(esw))
+ return -EPERM;
+
+ mutex_lock(&esw->state_lock);
+ if (esw->mode != SRIOV_LEGACY) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
+
+out:
+ mutex_unlock(&esw->state_lock);
+ return err;
+}
+
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
int vport, bool setting)
{
@@ -2015,8 +2249,7 @@ static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
u32 max_guarantee = 0;
int i;
- for (i = 0; i < esw->total_vports; i++) {
- evport = &esw->vports[i];
+ mlx5_esw_for_all_vports(esw, i, evport) {
if (!evport->enabled || evport->info.min_rate < max_guarantee)
continue;
max_guarantee = evport->info.min_rate;
@@ -2035,8 +2268,7 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
int err;
int i;
- for (i = 0; i < esw->total_vports; i++) {
- evport = &esw->vports[i];
+ mlx5_esw_for_all_vports(esw, i, evport) {
if (!evport->enabled)
continue;
vport_min_rate = evport->info.min_rate;
@@ -2051,7 +2283,7 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
if (bw_share == evport->qos.bw_share)
continue;
- err = esw_vport_qos_config(esw, i, vport_max_rate,
+ err = esw_vport_qos_config(esw, evport->vport, vport_max_rate,
bw_share);
if (!err)
evport->qos.bw_share = bw_share;
@@ -2134,7 +2366,7 @@ static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
!MLX5_CAP_GEN(dev, transmit_discard_vport_down))
return 0;
- err = mlx5_query_vport_down_stats(dev, vport_idx,
+ err = mlx5_query_vport_down_stats(dev, vport_idx, 1,
&rx_discard_vport_down,
&tx_discard_vport_down);
if (err)
@@ -2171,8 +2403,7 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
MLX5_CMD_OP_QUERY_VPORT_COUNTER);
MLX5_SET(query_vport_counter_in, in, op_mod, 0);
MLX5_SET(query_vport_counter_in, in, vport_number, vport);
- if (vport)
- MLX5_SET(query_vport_counter_in, in, other_vport, 1);
+ MLX5_SET(query_vport_counter_in, in, other_vport, 1);
memset(out, 0, outlen);
err = mlx5_cmd_exec(esw->dev, in, sizeof(in), out, outlen);
@@ -2245,3 +2476,10 @@ bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
return false;
}
+
+bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
+ struct mlx5_core_dev *dev1)
+{
+ return (dev0->priv.eswitch->mode == SRIOV_OFFLOADS &&
+ dev1->priv.eswitch->mode == SRIOV_OFFLOADS);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index 9c89eea9b2c3..3f3cd32ae60a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -38,6 +38,7 @@
#include <net/devlink.h>
#include <linux/mlx5/device.h>
#include <linux/mlx5/eswitch.h>
+#include <linux/mlx5/vport.h>
#include <linux/mlx5/fs.h>
#include "lib/mpfs.h"
@@ -49,8 +50,6 @@
#define MLX5_MAX_MC_PER_VPORT(dev) \
(1 << MLX5_CAP_GEN(dev, log_max_current_mc_list))
-#define FDB_UPLINK_VPORT 0xffff
-
#define MLX5_MIN_BW_SHARE 1
#define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \
@@ -138,6 +137,9 @@ struct mlx5_eswitch_fdb {
struct mlx5_flow_group *addr_grp;
struct mlx5_flow_group *allmulti_grp;
struct mlx5_flow_group *promisc_grp;
+ struct mlx5_flow_table *vepa_fdb;
+ struct mlx5_flow_handle *vepa_uplink_rule;
+ struct mlx5_flow_handle *vepa_star_rule;
} legacy;
struct offloads_fdb {
@@ -183,6 +185,16 @@ struct esw_mc_addr { /* SRIOV only */
u32 refcnt;
};
+struct mlx5_host_work {
+ struct work_struct work;
+ struct mlx5_eswitch *esw;
+};
+
+struct mlx5_host_info {
+ struct mlx5_nb nb;
+ u16 num_vfs;
+};
+
struct mlx5_eswitch {
struct mlx5_core_dev *dev;
struct mlx5_nb nb;
@@ -206,10 +218,13 @@ struct mlx5_eswitch {
struct mlx5_esw_offload offloads;
int mode;
int nvports;
+ u16 manager_vport;
+ struct mlx5_host_info host_info;
};
-void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports);
-int esw_offloads_init(struct mlx5_eswitch *esw, int nvports);
+void esw_offloads_cleanup(struct mlx5_eswitch *esw);
+int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports,
+ int total_nvports);
void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw);
int esw_offloads_init_reps(struct mlx5_eswitch *esw);
@@ -230,6 +245,8 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
int vport_num, bool setting);
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
u32 max_rate, u32 min_rate);
+int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting);
+int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
int vport, struct ifla_vf_info *ivi);
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
@@ -312,6 +329,7 @@ struct mlx5_esw_flow_attr {
} dests[MLX5_MAX_FLOW_FWD_VPORTS];
u32 mod_hdr_id;
u8 match_level;
+ u8 tunnel_match_level;
struct mlx5_fc *counter;
u32 chain;
u16 prio;
@@ -353,6 +371,8 @@ static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev
bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0,
struct mlx5_core_dev *dev1);
+bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
+ struct mlx5_core_dev *dev1);
#define MLX5_DEBUG_ESWITCH_MASK BIT(3)
@@ -364,6 +384,53 @@ bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0,
#define esw_debug(dev, format, ...) \
mlx5_core_dbg_mask(dev, MLX5_DEBUG_ESWITCH_MASK, format, ##__VA_ARGS__)
+
+/* The returned number is valid only when the dev is eswitch manager. */
+static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev)
+{
+ return mlx5_core_is_ecpf_esw_manager(dev) ?
+ MLX5_VPORT_ECPF : MLX5_VPORT_PF;
+}
+
+static inline int mlx5_eswitch_uplink_idx(struct mlx5_eswitch *esw)
+{
+ /* Uplink always locate at the last element of the array.*/
+ return esw->total_vports - 1;
+}
+
+static inline int mlx5_eswitch_ecpf_idx(struct mlx5_eswitch *esw)
+{
+ return esw->total_vports - 2;
+}
+
+static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw,
+ u16 vport_num)
+{
+ if (vport_num == MLX5_VPORT_ECPF) {
+ if (!mlx5_ecpf_vport_exists(esw->dev))
+ esw_warn(esw->dev, "ECPF vport doesn't exist!\n");
+ return mlx5_eswitch_ecpf_idx(esw);
+ }
+
+ if (vport_num == MLX5_VPORT_UPLINK)
+ return mlx5_eswitch_uplink_idx(esw);
+
+ return vport_num;
+}
+
+static inline int mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw,
+ int index)
+{
+ if (index == mlx5_eswitch_ecpf_idx(esw) &&
+ mlx5_ecpf_vport_exists(esw->dev))
+ return MLX5_VPORT_ECPF;
+
+ if (index == mlx5_eswitch_uplink_idx(esw))
+ return MLX5_VPORT_UPLINK;
+
+ return index;
+}
+
#else /* CONFIG_MLX5_ESWITCH */
/* eswitch API stubs */
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 53065b6ae593..f2260391be5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -40,15 +40,59 @@
#include "en.h"
#include "fs_core.h"
#include "lib/devcom.h"
+#include "ecpf.h"
+#include "lib/eq.h"
enum {
FDB_FAST_PATH = 0,
FDB_SLOW_PATH
};
+/* There are two match-all miss flows, one for unicast dst mac and
+ * one for multicast.
+ */
+#define MLX5_ESW_MISS_FLOWS (2)
+
#define fdb_prio_table(esw, chain, prio, level) \
(esw)->fdb_table.offloads.fdb_prio[(chain)][(prio)][(level)]
+#define UPLINK_REP_INDEX 0
+
+/* The rep getter/iterator are only valid after esw->total_vports
+ * and vport->vport are initialized in mlx5_eswitch_init.
+ */
+#define mlx5_esw_for_all_reps(esw, i, rep) \
+ for ((i) = MLX5_VPORT_PF; \
+ (rep) = &(esw)->offloads.vport_reps[i], \
+ (i) < (esw)->total_vports; (i)++)
+
+#define mlx5_esw_for_each_vf_rep(esw, i, rep, nvfs) \
+ for ((i) = MLX5_VPORT_FIRST_VF; \
+ (rep) = &(esw)->offloads.vport_reps[i], \
+ (i) <= (nvfs); (i)++)
+
+#define mlx5_esw_for_each_vf_rep_reverse(esw, i, rep, nvfs) \
+ for ((i) = (nvfs); \
+ (rep) = &(esw)->offloads.vport_reps[i], \
+ (i) >= MLX5_VPORT_FIRST_VF; (i)--)
+
+#define mlx5_esw_for_each_vf_vport(esw, vport, nvfs) \
+ for ((vport) = MLX5_VPORT_FIRST_VF; \
+ (vport) <= (nvfs); (vport)++)
+
+#define mlx5_esw_for_each_vf_vport_reverse(esw, vport, nvfs) \
+ for ((vport) = (nvfs); \
+ (vport) >= MLX5_VPORT_FIRST_VF; (vport)--)
+
+static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw,
+ u16 vport_num)
+{
+ u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
+
+ WARN_ON(idx > esw->total_vports - 1);
+ return &esw->offloads.vport_reps[idx];
+}
+
static struct mlx5_flow_table *
esw_get_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level);
static void
@@ -160,14 +204,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
MLX5_SET_TO_ONES(fte_match_set_misc, misc,
source_eswitch_owner_vhca_id);
- if (attr->match_level == MLX5_MATCH_NONE)
- spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
- else
- spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
- MLX5_MATCH_MISC_PARAMETERS;
-
- if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
- spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+ spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+ if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
+ if (attr->tunnel_match_level != MLX5_MATCH_NONE)
+ spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+ if (attr->match_level != MLX5_MATCH_NONE)
+ spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+ } else if (attr->match_level != MLX5_MATCH_NONE) {
+ spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+ }
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
flow_act.modify_id = attr->mod_hdr_id;
@@ -318,7 +363,7 @@ static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val)
esw_debug(esw->dev, "%s applying global %s policy\n", __func__, val ? "pop" : "none");
for (vf_vport = 1; vf_vport < esw->enabled_vports; vf_vport++) {
rep = &esw->offloads.vport_reps[vf_vport];
- if (!rep->rep_if[REP_ETH].valid)
+ if (rep->rep_if[REP_ETH].state != REP_LOADED)
continue;
err = __mlx5_eswitch_set_vport_vlan(esw, rep->vport, 0, 0, val);
@@ -359,15 +404,15 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
in_rep = attr->in_rep;
out_rep = attr->dests[0].rep;
- if (push && in_rep->vport == FDB_UPLINK_VPORT)
+ if (push && in_rep->vport == MLX5_VPORT_UPLINK)
goto out_notsupp;
- if (pop && out_rep->vport == FDB_UPLINK_VPORT)
+ if (pop && out_rep->vport == MLX5_VPORT_UPLINK)
goto out_notsupp;
/* vport has vlan push configured, can't offload VF --> wire rules w.o it */
if (!push && !pop && fwd)
- if (in_rep->vlan && out_rep->vport == FDB_UPLINK_VPORT)
+ if (in_rep->vlan && out_rep->vport == MLX5_VPORT_UPLINK)
goto out_notsupp;
/* protects against (1) setting rules with different vlans to push and
@@ -409,7 +454,7 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
if (!push && !pop && fwd) {
/* tracks VF --> wire rules without vlan push action */
- if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT) {
+ if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) {
vport->vlan_refcount++;
attr->vlan_handled = true;
}
@@ -469,7 +514,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
if (!push && !pop && fwd) {
/* tracks VF --> wire rules without vlan push action */
- if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT)
+ if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK)
vport->vlan_refcount--;
return 0;
@@ -516,7 +561,8 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
- MLX5_SET(fte_match_set_misc, misc, source_port, 0x0); /* source vport is 0 */
+ /* source vport is the esw manager */
+ MLX5_SET(fte_match_set_misc, misc, source_port, esw->manager_vport);
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
@@ -561,7 +607,7 @@ static void peer_miss_rules_setup(struct mlx5_core_dev *peer_dev,
source_eswitch_owner_vhca_id);
dest->type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
- dest->vport.num = 0;
+ dest->vport.num = peer_dev->priv.eswitch->manager_vport;
dest->vport.vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id);
dest->vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
}
@@ -595,14 +641,35 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
misc_parameters);
- for (i = 1; i < nvports; i++) {
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_PF);
+ flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
+ spec, &flow_act, &dest, 1);
+ if (IS_ERR(flow)) {
+ err = PTR_ERR(flow);
+ goto add_pf_flow_err;
+ }
+ flows[MLX5_VPORT_PF] = flow;
+ }
+
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
+ flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
+ spec, &flow_act, &dest, 1);
+ if (IS_ERR(flow)) {
+ err = PTR_ERR(flow);
+ goto add_ecpf_flow_err;
+ }
+ flows[mlx5_eswitch_ecpf_idx(esw)] = flow;
+ }
+
+ mlx5_esw_for_each_vf_vport(esw, i, mlx5_core_max_vfs(esw->dev)) {
MLX5_SET(fte_match_set_misc, misc, source_port, i);
flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
spec, &flow_act, &dest, 1);
if (IS_ERR(flow)) {
err = PTR_ERR(flow);
- esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
- goto add_flow_err;
+ goto add_vf_flow_err;
}
flows[i] = flow;
}
@@ -612,9 +679,18 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
kvfree(spec);
return 0;
-add_flow_err:
- for (i--; i > 0; i--)
+add_vf_flow_err:
+ nvports = --i;
+ mlx5_esw_for_each_vf_vport_reverse(esw, i, nvports)
mlx5_del_flow_rules(flows[i]);
+
+ if (mlx5_ecpf_vport_exists(esw->dev))
+ mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
+add_ecpf_flow_err:
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev))
+ mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
+add_pf_flow_err:
+ esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
kvfree(flows);
alloc_flows_err:
kvfree(spec);
@@ -628,9 +704,15 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
flows = esw->fdb_table.offloads.peer_miss_rules;
- for (i = 1; i < esw->total_vports; i++)
+ mlx5_esw_for_each_vf_vport_reverse(esw, i, mlx5_core_max_vfs(esw->dev))
mlx5_del_flow_rules(flows[i]);
+ if (mlx5_ecpf_vport_exists(esw->dev))
+ mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
+
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev))
+ mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
+
kvfree(flows);
}
@@ -660,7 +742,7 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
dmac_c[0] = 0x01;
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
- dest.vport.num = 0;
+ dest.vport.num = esw->manager_vport;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec,
@@ -904,8 +986,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports)
esw->fdb_table.offloads.fdb_left[i] =
ESW_POOLS[i] <= fdb_max ? ESW_SIZE / ESW_POOLS[i] : 0;
- table_size = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ + 2 +
- esw->total_vports;
+ table_size = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ +
+ MLX5_ESW_MISS_FLOWS + esw->total_vports;
/* create the slow path fdb with encap set, so further table instances
* can be created at run time while VFs are probed if the FW allows that.
@@ -999,7 +1081,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports)
dmac[0] = 0x01;
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
- MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix + 2);
+ MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
+ ix + MLX5_ESW_MISS_FLOWS);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
@@ -1048,7 +1131,7 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
esw_destroy_offloads_fast_fdb_tables(esw);
}
-static int esw_create_offloads_table(struct mlx5_eswitch *esw)
+static int esw_create_offloads_table(struct mlx5_eswitch *esw, int nvports)
{
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_core_dev *dev = esw->dev;
@@ -1062,7 +1145,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
return -EOPNOTSUPP;
}
- ft_attr.max_fte = dev->priv.sriov.num_vfs + 2;
+ ft_attr.max_fte = nvports + MLX5_ESW_MISS_FLOWS;
ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
if (IS_ERR(ft_offloads)) {
@@ -1082,16 +1165,15 @@ static void esw_destroy_offloads_table(struct mlx5_eswitch *esw)
mlx5_destroy_flow_table(offloads->ft_offloads);
}
-static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
+static int esw_create_vport_rx_group(struct mlx5_eswitch *esw, int nvports)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_flow_group *g;
- struct mlx5_priv *priv = &esw->dev->priv;
u32 *flow_group_in;
void *match_criteria, *misc;
int err = 0;
- int nvports = priv->sriov.num_vfs + 2;
+ nvports = nvports + MLX5_ESW_MISS_FLOWS;
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;
@@ -1168,7 +1250,8 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
{
int err, err1, num_vfs = esw->dev->priv.sriov.num_vfs;
- if (esw->mode != SRIOV_LEGACY) {
+ if (esw->mode != SRIOV_LEGACY &&
+ !mlx5_core_is_ecpf_esw_manager(esw->dev)) {
NL_SET_ERR_MSG_MOD(extack,
"Can't set offloads mode, SRIOV legacy not enabled");
return -EINVAL;
@@ -1206,9 +1289,8 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw)
{
int total_vfs = MLX5_TOTAL_VPORTS(esw->dev);
struct mlx5_core_dev *dev = esw->dev;
- struct mlx5_esw_offload *offloads;
struct mlx5_eswitch_rep *rep;
- u8 hw_id[ETH_ALEN];
+ u8 hw_id[ETH_ALEN], rep_type;
int vport;
esw->offloads.vport_reps = kcalloc(total_vfs,
@@ -1217,75 +1299,203 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw)
if (!esw->offloads.vport_reps)
return -ENOMEM;
- offloads = &esw->offloads;
mlx5_query_nic_vport_mac_address(dev, 0, hw_id);
- for (vport = 0; vport < total_vfs; vport++) {
- rep = &offloads->vport_reps[vport];
-
- rep->vport = vport;
+ mlx5_esw_for_all_reps(esw, vport, rep) {
+ rep->vport = mlx5_eswitch_index_to_vport_num(esw, vport);
ether_addr_copy(rep->hw_id, hw_id);
- }
- offloads->vport_reps[0].vport = FDB_UPLINK_VPORT;
+ for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
+ rep->rep_if[rep_type].state = REP_UNREGISTERED;
+ }
return 0;
}
-static void esw_offloads_unload_reps_type(struct mlx5_eswitch *esw, int nvports,
- u8 rep_type)
+static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch_rep *rep, u8 rep_type)
+{
+ if (rep->rep_if[rep_type].state != REP_LOADED)
+ return;
+
+ rep->rep_if[rep_type].unload(rep);
+ rep->rep_if[rep_type].state = REP_REGISTERED;
+}
+
+static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
{
struct mlx5_eswitch_rep *rep;
- int vport;
- for (vport = nvports - 1; vport >= 0; vport--) {
- rep = &esw->offloads.vport_reps[vport];
- if (!rep->rep_if[rep_type].valid)
- continue;
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
+ __esw_offloads_unload_rep(esw, rep, rep_type);
+ }
- rep->rep_if[rep_type].unload(rep);
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+ __esw_offloads_unload_rep(esw, rep, rep_type);
}
+
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
+ __esw_offloads_unload_rep(esw, rep, rep_type);
}
-static void esw_offloads_unload_reps(struct mlx5_eswitch *esw, int nvports)
+static void __unload_reps_vf_vport(struct mlx5_eswitch *esw, int nvports,
+ u8 rep_type)
+{
+ struct mlx5_eswitch_rep *rep;
+ int i;
+
+ mlx5_esw_for_each_vf_rep_reverse(esw, i, rep, nvports)
+ __esw_offloads_unload_rep(esw, rep, rep_type);
+}
+
+static void esw_offloads_unload_vf_reps(struct mlx5_eswitch *esw, int nvports)
+{
+ u8 rep_type = NUM_REP_TYPES;
+
+ while (rep_type-- > 0)
+ __unload_reps_vf_vport(esw, nvports, rep_type);
+}
+
+static void __unload_reps_all_vport(struct mlx5_eswitch *esw, int nvports,
+ u8 rep_type)
+{
+ __unload_reps_vf_vport(esw, nvports, rep_type);
+
+ /* Special vports must be the last to unload. */
+ __unload_reps_special_vport(esw, rep_type);
+}
+
+static void esw_offloads_unload_all_reps(struct mlx5_eswitch *esw, int nvports)
{
u8 rep_type = NUM_REP_TYPES;
while (rep_type-- > 0)
- esw_offloads_unload_reps_type(esw, nvports, rep_type);
+ __unload_reps_all_vport(esw, nvports, rep_type);
+}
+
+static int __esw_offloads_load_rep(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch_rep *rep, u8 rep_type)
+{
+ int err = 0;
+
+ if (rep->rep_if[rep_type].state != REP_REGISTERED)
+ return 0;
+
+ err = rep->rep_if[rep_type].load(esw->dev, rep);
+ if (err)
+ return err;
+
+ rep->rep_if[rep_type].state = REP_LOADED;
+
+ return 0;
}
-static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports,
- u8 rep_type)
+static int __load_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
{
struct mlx5_eswitch_rep *rep;
- int vport;
int err;
- for (vport = 0; vport < nvports; vport++) {
- rep = &esw->offloads.vport_reps[vport];
- if (!rep->rep_if[rep_type].valid)
- continue;
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
+ err = __esw_offloads_load_rep(esw, rep, rep_type);
+ if (err)
+ return err;
- err = rep->rep_if[rep_type].load(esw->dev, rep);
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+ err = __esw_offloads_load_rep(esw, rep, rep_type);
if (err)
- goto err_reps;
+ goto err_pf;
+ }
+
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
+ err = __esw_offloads_load_rep(esw, rep, rep_type);
+ if (err)
+ goto err_ecpf;
+ }
+
+ return 0;
+
+err_ecpf:
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+ __esw_offloads_unload_rep(esw, rep, rep_type);
+ }
+
+err_pf:
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
+ __esw_offloads_unload_rep(esw, rep, rep_type);
+ return err;
+}
+
+static int __load_reps_vf_vport(struct mlx5_eswitch *esw, int nvports,
+ u8 rep_type)
+{
+ struct mlx5_eswitch_rep *rep;
+ int err, i;
+
+ mlx5_esw_for_each_vf_rep(esw, i, rep, nvports) {
+ err = __esw_offloads_load_rep(esw, rep, rep_type);
+ if (err)
+ goto err_vf;
}
return 0;
+err_vf:
+ __unload_reps_vf_vport(esw, --i, rep_type);
+ return err;
+}
+
+static int esw_offloads_load_vf_reps(struct mlx5_eswitch *esw, int nvports)
+{
+ u8 rep_type = 0;
+ int err;
+
+ for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
+ err = __load_reps_vf_vport(esw, nvports, rep_type);
+ if (err)
+ goto err_reps;
+ }
+
+ return err;
+
err_reps:
- esw_offloads_unload_reps_type(esw, vport, rep_type);
+ while (rep_type-- > 0)
+ __unload_reps_vf_vport(esw, nvports, rep_type);
+ return err;
+}
+
+static int __load_reps_all_vport(struct mlx5_eswitch *esw, int nvports,
+ u8 rep_type)
+{
+ int err;
+
+ /* Special vports must be loaded first. */
+ err = __load_reps_special_vport(esw, rep_type);
+ if (err)
+ return err;
+
+ err = __load_reps_vf_vport(esw, nvports, rep_type);
+ if (err)
+ goto err_vfs;
+
+ return 0;
+
+err_vfs:
+ __unload_reps_special_vport(esw, rep_type);
return err;
}
-static int esw_offloads_load_reps(struct mlx5_eswitch *esw, int nvports)
+static int esw_offloads_load_all_reps(struct mlx5_eswitch *esw, int nvports)
{
u8 rep_type = 0;
int err;
for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
- err = esw_offloads_load_reps_type(esw, nvports, rep_type);
+ err = __load_reps_all_vport(esw, nvports, rep_type);
if (err)
goto err_reps;
}
@@ -1294,7 +1504,7 @@ static int esw_offloads_load_reps(struct mlx5_eswitch *esw, int nvports)
err_reps:
while (rep_type-- > 0)
- esw_offloads_unload_reps_type(esw, nvports, rep_type);
+ __unload_reps_all_vport(esw, nvports, rep_type);
return err;
}
@@ -1397,7 +1607,7 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
}
-int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
+static int esw_offloads_steering_init(struct mlx5_eswitch *esw, int nvports)
{
int err;
@@ -1407,24 +1617,16 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
if (err)
return err;
- err = esw_create_offloads_table(esw);
+ err = esw_create_offloads_table(esw, nvports);
if (err)
goto create_ft_err;
- err = esw_create_vport_rx_group(esw);
+ err = esw_create_vport_rx_group(esw, nvports);
if (err)
goto create_fg_err;
- err = esw_offloads_load_reps(esw, nvports);
- if (err)
- goto err_reps;
-
- esw_offloads_devcom_init(esw);
return 0;
-err_reps:
- esw_destroy_vport_rx_group(esw);
-
create_fg_err:
esw_destroy_offloads_table(esw);
@@ -1434,6 +1636,95 @@ create_ft_err:
return err;
}
+static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
+{
+ esw_destroy_vport_rx_group(esw);
+ esw_destroy_offloads_table(esw);
+ esw_destroy_offloads_fdb_tables(esw);
+}
+
+static void esw_host_params_event_handler(struct work_struct *work)
+{
+ struct mlx5_host_work *host_work;
+ struct mlx5_eswitch *esw;
+ int err, num_vf = 0;
+
+ host_work = container_of(work, struct mlx5_host_work, work);
+ esw = host_work->esw;
+
+ err = mlx5_query_host_params_num_vfs(esw->dev, &num_vf);
+ if (err || num_vf == esw->host_info.num_vfs)
+ goto out;
+
+ /* Number of VFs can only change from "0 to x" or "x to 0". */
+ if (esw->host_info.num_vfs > 0) {
+ esw_offloads_unload_vf_reps(esw, esw->host_info.num_vfs);
+ } else {
+ err = esw_offloads_load_vf_reps(esw, num_vf);
+
+ if (err)
+ goto out;
+ }
+
+ esw->host_info.num_vfs = num_vf;
+
+out:
+ kfree(host_work);
+}
+
+static int esw_host_params_event(struct notifier_block *nb,
+ unsigned long type, void *data)
+{
+ struct mlx5_host_work *host_work;
+ struct mlx5_host_info *host_info;
+ struct mlx5_eswitch *esw;
+
+ host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC);
+ if (!host_work)
+ return NOTIFY_DONE;
+
+ host_info = mlx5_nb_cof(nb, struct mlx5_host_info, nb);
+ esw = container_of(host_info, struct mlx5_eswitch, host_info);
+
+ host_work->esw = esw;
+
+ INIT_WORK(&host_work->work, esw_host_params_event_handler);
+ queue_work(esw->work_queue, &host_work->work);
+
+ return NOTIFY_OK;
+}
+
+int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports,
+ int total_nvports)
+{
+ int err;
+
+ mutex_init(&esw->fdb_table.offloads.fdb_prio_lock);
+
+ err = esw_offloads_steering_init(esw, total_nvports);
+ if (err)
+ return err;
+
+ err = esw_offloads_load_all_reps(esw, vf_nvports);
+ if (err)
+ goto err_reps;
+
+ esw_offloads_devcom_init(esw);
+
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ MLX5_NB_INIT(&esw->host_info.nb, esw_host_params_event,
+ HOST_PARAMS_CHANGE);
+ mlx5_eq_notifier_register(esw->dev, &esw->host_info.nb);
+ esw->host_info.num_vfs = vf_nvports;
+ }
+
+ return 0;
+
+err_reps:
+ esw_offloads_steering_cleanup(esw);
+ return err;
+}
+
static int esw_offloads_stop(struct mlx5_eswitch *esw,
struct netlink_ext_ack *extack)
{
@@ -1453,13 +1744,21 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
return err;
}
-void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports)
+void esw_offloads_cleanup(struct mlx5_eswitch *esw)
{
+ u16 num_vfs;
+
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+ mlx5_eq_notifier_unregister(esw->dev, &esw->host_info.nb);
+ flush_workqueue(esw->work_queue);
+ num_vfs = esw->host_info.num_vfs;
+ } else {
+ num_vfs = esw->dev->priv.sriov.num_vfs;
+ }
+
esw_offloads_devcom_cleanup(esw);
- esw_offloads_unload_reps(esw, nvports);
- esw_destroy_vport_rx_group(esw);
- esw_destroy_offloads_table(esw);
- esw_destroy_offloads_fdb_tables(esw);
+ esw_offloads_unload_all_reps(esw, num_vfs);
+ esw_offloads_steering_cleanup(esw);
}
static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
@@ -1548,7 +1847,8 @@ static int mlx5_devlink_eswitch_check(struct devlink *devlink)
if(!MLX5_ESWITCH_MANAGER(dev))
return -EPERM;
- if (dev->priv.eswitch->mode == SRIOV_NONE)
+ if (dev->priv.eswitch->mode == SRIOV_NONE &&
+ !mlx5_core_is_ecpf_esw_manager(dev))
return -EOPNOTSUPP;
return 0;
@@ -1760,47 +2060,45 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap)
return 0;
}
-void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
- int vport_index,
- struct mlx5_eswitch_rep_if *__rep_if,
- u8 rep_type)
+void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch_rep_if *__rep_if,
+ u8 rep_type)
{
- struct mlx5_esw_offload *offloads = &esw->offloads;
struct mlx5_eswitch_rep_if *rep_if;
+ struct mlx5_eswitch_rep *rep;
+ int i;
- rep_if = &offloads->vport_reps[vport_index].rep_if[rep_type];
-
- rep_if->load = __rep_if->load;
- rep_if->unload = __rep_if->unload;
- rep_if->get_proto_dev = __rep_if->get_proto_dev;
- rep_if->priv = __rep_if->priv;
+ mlx5_esw_for_all_reps(esw, i, rep) {
+ rep_if = &rep->rep_if[rep_type];
+ rep_if->load = __rep_if->load;
+ rep_if->unload = __rep_if->unload;
+ rep_if->get_proto_dev = __rep_if->get_proto_dev;
+ rep_if->priv = __rep_if->priv;
- rep_if->valid = true;
+ rep_if->state = REP_REGISTERED;
+ }
}
-EXPORT_SYMBOL(mlx5_eswitch_register_vport_rep);
+EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps);
-void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,
- int vport_index, u8 rep_type)
+void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type)
{
- struct mlx5_esw_offload *offloads = &esw->offloads;
+ u16 max_vf = mlx5_core_max_vfs(esw->dev);
struct mlx5_eswitch_rep *rep;
+ int i;
- rep = &offloads->vport_reps[vport_index];
-
- if (esw->mode == SRIOV_OFFLOADS && esw->vports[vport_index].enabled)
- rep->rep_if[rep_type].unload(rep);
+ if (esw->mode == SRIOV_OFFLOADS)
+ __unload_reps_all_vport(esw, max_vf, rep_type);
- rep->rep_if[rep_type].valid = false;
+ mlx5_esw_for_all_reps(esw, i, rep)
+ rep->rep_if[rep_type].state = REP_UNREGISTERED;
}
-EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_rep);
+EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps);
void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type)
{
-#define UPLINK_REP_INDEX 0
- struct mlx5_esw_offload *offloads = &esw->offloads;
struct mlx5_eswitch_rep *rep;
- rep = &offloads->vport_reps[UPLINK_REP_INDEX];
+ rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
return rep->rep_if[rep_type].priv;
}
@@ -1808,15 +2106,11 @@ void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
int vport,
u8 rep_type)
{
- struct mlx5_esw_offload *offloads = &esw->offloads;
struct mlx5_eswitch_rep *rep;
- if (vport == FDB_UPLINK_VPORT)
- vport = UPLINK_REP_INDEX;
-
- rep = &offloads->vport_reps[vport];
+ rep = mlx5_eswitch_get_rep(esw, vport);
- if (rep->rep_if[rep_type].valid &&
+ if (rep->rep_if[rep_type].state == REP_LOADED &&
rep->rep_if[rep_type].get_proto_dev)
return rep->rep_if[rep_type].get_proto_dev(rep);
return NULL;
@@ -1825,13 +2119,13 @@ EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev);
void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type)
{
- return mlx5_eswitch_get_proto_dev(esw, UPLINK_REP_INDEX, rep_type);
+ return mlx5_eswitch_get_proto_dev(esw, MLX5_VPORT_UPLINK, rep_type);
}
EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev);
struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
int vport)
{
- return &esw->offloads.vport_reps[vport];
+ return mlx5_eswitch_get_rep(esw, vport);
}
EXPORT_SYMBOL(mlx5_eswitch_vport_rep);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
index fbc42b7252a9..5d5864e8df3c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
@@ -103,6 +103,8 @@ static const char *eqe_type_str(u8 type)
return "MLX5_EVENT_TYPE_STALL_EVENT";
case MLX5_EVENT_TYPE_CMD:
return "MLX5_EVENT_TYPE_CMD";
+ case MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE:
+ return "MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE";
case MLX5_EVENT_TYPE_PAGE_REQUEST:
return "MLX5_EVENT_TYPE_PAGE_REQUEST";
case MLX5_EVENT_TYPE_PAGE_FAULT:
@@ -211,11 +213,10 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
enum port_module_event_status_type module_status;
enum port_module_event_error_type error_type;
struct mlx5_eqe_port_module *module_event_eqe;
- const char *status_str, *error_str;
+ const char *status_str;
u8 module_num;
module_event_eqe = &eqe->data.port_module;
- module_num = module_event_eqe->module;
module_status = module_event_eqe->module_status &
PORT_MODULE_EVENT_MODULE_STATUS_MASK;
error_type = module_event_eqe->error_type &
@@ -223,25 +224,27 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
if (module_status < MLX5_MODULE_STATUS_NUM)
events->pme_stats.status_counters[module_status]++;
- status_str = mlx5_pme_status_to_string(module_status);
- if (module_status == MLX5_MODULE_STATUS_ERROR) {
+ if (module_status == MLX5_MODULE_STATUS_ERROR)
if (error_type < MLX5_MODULE_EVENT_ERROR_NUM)
events->pme_stats.error_counters[error_type]++;
- error_str = mlx5_pme_error_to_string(error_type);
- }
if (!printk_ratelimit())
return NOTIFY_OK;
- if (module_status == MLX5_MODULE_STATUS_ERROR)
+ module_num = module_event_eqe->module;
+ status_str = mlx5_pme_status_to_string(module_status);
+ if (module_status == MLX5_MODULE_STATUS_ERROR) {
+ const char *error_str = mlx5_pme_error_to_string(error_type);
+
mlx5_core_err(events->dev,
"Port module event[error]: module %u, %s, %s\n",
module_num, status_str, error_str);
- else
+ } else {
mlx5_core_info(events->dev,
"Port module event: module %u, %s\n",
module_num, status_str);
+ }
return NOTIFY_OK;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c
index 27c5f6c7d36a..d046d1ec2a86 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c
@@ -317,7 +317,6 @@ static int mlx5_fpga_event(struct mlx5_fpga_device *fdev,
const char *event_name;
bool teardown = false;
unsigned long flags;
- u32 fpga_qpn;
u8 syndrome;
switch (event) {
@@ -328,7 +327,6 @@ static int mlx5_fpga_event(struct mlx5_fpga_device *fdev,
case MLX5_EVENT_TYPE_FPGA_QP_ERROR:
syndrome = MLX5_GET(fpga_qp_error_event, data, syndrome);
event_name = mlx5_fpga_qp_syndrome_to_string(syndrome);
- fpga_qpn = MLX5_GET(fpga_qp_error_event, data, fpga_qpn);
break;
default:
return NOTIFY_DONE;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 79f122b45def..f2cfa012315e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -32,6 +32,7 @@
#include <linux/mutex.h>
#include <linux/mlx5/driver.h>
+#include <linux/mlx5/vport.h>
#include <linux/mlx5/eswitch.h>
#include "mlx5_core.h"
@@ -397,6 +398,7 @@ static void del_hw_flow_table(struct fs_node *node)
fs_get_obj(ft, node);
dev = get_dev(&ft->node);
root = find_root(&ft->node);
+ trace_mlx5_fs_del_ft(ft);
if (node->active) {
err = root->cmds->destroy_flow_table(dev, ft);
@@ -618,7 +620,8 @@ static struct mlx5_flow_group *alloc_flow_group(struct mlx5_flow_steering *steer
if (ret) {
kmem_cache_free(steering->fgs_cache, fg);
return ERR_PTR(ret);
-}
+ }
+
ida_init(&fg->fte_allocator);
fg->mask.match_criteria_enable = match_criteria_enable;
memcpy(&fg->mask.match_criteria, match_criteria,
@@ -1019,6 +1022,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
fs_prio->num_ft++;
up_write_ref_node(&fs_prio->node);
mutex_unlock(&root->chain_lock);
+ trace_mlx5_fs_add_ft(ft);
return ft;
destroy_ft:
root->cmds->destroy_flow_table(root->dev, ft);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 196c07383082..cb9fa3430c53 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -103,7 +103,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
mlx5_core_err(dev, "start\n");
if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
- mlx5_cmd_trigger_completions(dev);
+ mlx5_cmd_flush(dev);
}
mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index bfc0f6581729..4eac42555c7d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -446,11 +446,11 @@ static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu)
new_channels.params = *params;
new_channels.params.sw_mtu = new_mtu;
- err = mlx5e_open_channels(priv, &new_channels);
+
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
if (err)
goto out;
- mlx5e_switch_priv_channels(priv, &new_channels, NULL);
netdev->mtu = new_channels.params.sw_mtu;
out:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
index 3a6baed722d8..48aa6e030bcf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
@@ -35,37 +35,8 @@
#include <linux/mlx5/vport.h>
#include "mlx5_core.h"
#include "eswitch.h"
-
-enum {
- MLX5_LAG_FLAG_ROCE = 1 << 0,
- MLX5_LAG_FLAG_SRIOV = 1 << 1,
-};
-
-#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV)
-
-struct lag_func {
- struct mlx5_core_dev *dev;
- struct net_device *netdev;
-};
-
-/* Used for collection of netdev event info. */
-struct lag_tracker {
- enum netdev_lag_tx_type tx_type;
- struct netdev_lag_lower_state_info netdev_state[MLX5_MAX_PORTS];
- bool is_bonded;
-};
-
-/* LAG data of a ConnectX card.
- * It serves both its phys functions.
- */
-struct mlx5_lag {
- u8 flags;
- u8 v2p_map[MLX5_MAX_PORTS];
- struct lag_func pf[MLX5_MAX_PORTS];
- struct lag_tracker tracker;
- struct delayed_work bond_work;
- struct notifier_block nb;
-};
+#include "lag.h"
+#include "lag_mp.h"
/* General purpose, use for short periods of time.
* Beware of lock dependencies (preferably, no locks should be acquired
@@ -147,13 +118,8 @@ static int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev,
return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size);
}
-static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev)
-{
- return dev->priv.lag;
-}
-
-static int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
- struct net_device *ndev)
+int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
+ struct net_device *ndev)
{
int i;
@@ -174,11 +140,6 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev)
return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);
}
-static bool __mlx5_lag_is_active(struct mlx5_lag *ldev)
-{
- return !!(ldev->flags & MLX5_LAG_MODE_FLAGS);
-}
-
static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
u8 *port1, u8 *port2)
{
@@ -195,8 +156,8 @@ static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
*port2 = 1;
}
-static void mlx5_modify_lag(struct mlx5_lag *ldev,
- struct lag_tracker *tracker)
+void mlx5_modify_lag(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker)
{
struct mlx5_core_dev *dev0 = ldev->pf[0].dev;
u8 v2p_port1, v2p_port2;
@@ -241,9 +202,9 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
return err;
}
-static int mlx5_activate_lag(struct mlx5_lag *ldev,
- struct lag_tracker *tracker,
- u8 flags)
+int mlx5_activate_lag(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker,
+ u8 flags)
{
bool roce_lag = !!(flags & MLX5_LAG_FLAG_ROCE);
struct mlx5_core_dev *dev0 = ldev->pf[0].dev;
@@ -343,6 +304,11 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
roce_lag = !mlx5_sriov_is_enabled(dev0) &&
!mlx5_sriov_is_enabled(dev1);
+#ifdef CONFIG_MLX5_ESWITCH
+ roce_lag &= dev0->priv.eswitch->mode == SRIOV_NONE &&
+ dev1->priv.eswitch->mode == SRIOV_NONE;
+#endif
+
if (roce_lag)
mlx5_lag_remove_ib_devices(ldev);
@@ -381,7 +347,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay)
{
- schedule_delayed_work(&ldev->bond_work, delay);
+ queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
}
static void mlx5_do_bond_work(struct work_struct *work)
@@ -533,6 +499,12 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(void)
if (!ldev)
return NULL;
+ ldev->wq = create_singlethread_workqueue("mlx5_lag");
+ if (!ldev->wq) {
+ kfree(ldev);
+ return NULL;
+ }
+
INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
return ldev;
@@ -540,6 +512,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(void)
static void mlx5_lag_dev_free(struct mlx5_lag *ldev)
{
+ destroy_workqueue(ldev->wq);
kfree(ldev);
}
@@ -587,6 +560,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
{
struct mlx5_lag *ldev = NULL;
struct mlx5_core_dev *tmp_dev;
+ int err;
if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
!MLX5_CAP_GEN(dev, lag_master) ||
@@ -614,6 +588,32 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
}
}
+
+ err = mlx5_lag_mp_init(ldev);
+ if (err)
+ mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
+ err);
+}
+
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num)
+{
+ struct mlx5_lag *ldev;
+ int n;
+
+ ldev = mlx5_lag_dev_get(dev);
+ if (!ldev) {
+ mlx5_core_warn(dev, "no lag device, can't get pf num\n");
+ return -EINVAL;
+ }
+
+ for (n = 0; n < MLX5_MAX_PORTS; n++)
+ if (ldev->pf[n].dev == dev) {
+ *pf_num = n;
+ return 0;
+ }
+
+ mlx5_core_warn(dev, "wasn't able to locate pf in the lag device\n");
+ return -EINVAL;
}
/* Must be called with intf_mutex held */
@@ -638,6 +638,7 @@ void mlx5_lag_remove(struct mlx5_core_dev *dev)
if (i == MLX5_MAX_PORTS) {
if (ldev->nb.notifier_call)
unregister_netdevice_notifier(&ldev->nb);
+ mlx5_lag_mp_cleanup(ldev);
cancel_delayed_work_sync(&ldev->bond_work);
mlx5_lag_dev_free(ldev);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag.h
new file mode 100644
index 000000000000..1dea0b1c9826
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __MLX5_LAG_H__
+#define __MLX5_LAG_H__
+
+#include "mlx5_core.h"
+#include "lag_mp.h"
+
+enum {
+ MLX5_LAG_FLAG_ROCE = 1 << 0,
+ MLX5_LAG_FLAG_SRIOV = 1 << 1,
+ MLX5_LAG_FLAG_MULTIPATH = 1 << 2,
+};
+
+#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV |\
+ MLX5_LAG_FLAG_MULTIPATH)
+
+struct lag_func {
+ struct mlx5_core_dev *dev;
+ struct net_device *netdev;
+};
+
+/* Used for collection of netdev event info. */
+struct lag_tracker {
+ enum netdev_lag_tx_type tx_type;
+ struct netdev_lag_lower_state_info netdev_state[MLX5_MAX_PORTS];
+ unsigned int is_bonded:1;
+};
+
+/* LAG data of a ConnectX card.
+ * It serves both its phys functions.
+ */
+struct mlx5_lag {
+ u8 flags;
+ u8 v2p_map[MLX5_MAX_PORTS];
+ struct lag_func pf[MLX5_MAX_PORTS];
+ struct lag_tracker tracker;
+ struct workqueue_struct *wq;
+ struct delayed_work bond_work;
+ struct notifier_block nb;
+ struct lag_mp lag_mp;
+};
+
+static inline struct mlx5_lag *
+mlx5_lag_dev_get(struct mlx5_core_dev *dev)
+{
+ return dev->priv.lag;
+}
+
+static inline bool
+__mlx5_lag_is_active(struct mlx5_lag *ldev)
+{
+ return !!(ldev->flags & MLX5_LAG_MODE_FLAGS);
+}
+
+void mlx5_modify_lag(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker);
+int mlx5_activate_lag(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker,
+ u8 flags);
+int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
+ struct net_device *ndev);
+
+#endif /* __MLX5_LAG_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
new file mode 100644
index 000000000000..5633f8572800
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#include <linux/netdevice.h>
+#include "lag.h"
+#include "lag_mp.h"
+#include "mlx5_core.h"
+#include "eswitch.h"
+#include "lib/mlx5.h"
+
+static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
+{
+ if (!ldev->pf[0].dev || !ldev->pf[1].dev)
+ return false;
+
+ return mlx5_esw_multipath_prereq(ldev->pf[0].dev, ldev->pf[1].dev);
+}
+
+static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
+{
+ return !!(ldev->flags & MLX5_LAG_FLAG_MULTIPATH);
+}
+
+bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev)
+{
+ struct mlx5_lag *ldev;
+ bool res;
+
+ ldev = mlx5_lag_dev_get(dev);
+ res = ldev && __mlx5_lag_is_multipath(ldev);
+
+ return res;
+}
+
+/**
+ * Set lag port affinity
+ *
+ * @ldev: lag device
+ * @port:
+ * 0 - set normal affinity.
+ * 1 - set affinity to port 1.
+ * 2 - set affinity to port 2.
+ *
+ **/
+static void mlx5_lag_set_port_affinity(struct mlx5_lag *ldev, int port)
+{
+ struct lag_tracker tracker;
+
+ if (!__mlx5_lag_is_multipath(ldev))
+ return;
+
+ switch (port) {
+ case 0:
+ tracker.netdev_state[0].tx_enabled = true;
+ tracker.netdev_state[1].tx_enabled = true;
+ tracker.netdev_state[0].link_up = true;
+ tracker.netdev_state[1].link_up = true;
+ break;
+ case 1:
+ tracker.netdev_state[0].tx_enabled = true;
+ tracker.netdev_state[0].link_up = true;
+ tracker.netdev_state[1].tx_enabled = false;
+ tracker.netdev_state[1].link_up = false;
+ break;
+ case 2:
+ tracker.netdev_state[0].tx_enabled = false;
+ tracker.netdev_state[0].link_up = false;
+ tracker.netdev_state[1].tx_enabled = true;
+ tracker.netdev_state[1].link_up = true;
+ break;
+ default:
+ mlx5_core_warn(ldev->pf[0].dev, "Invalid affinity port %d",
+ port);
+ return;
+ }
+
+ if (tracker.netdev_state[0].tx_enabled)
+ mlx5_notifier_call_chain(ldev->pf[0].dev->priv.events,
+ MLX5_DEV_EVENT_PORT_AFFINITY,
+ (void *)0);
+
+ if (tracker.netdev_state[1].tx_enabled)
+ mlx5_notifier_call_chain(ldev->pf[1].dev->priv.events,
+ MLX5_DEV_EVENT_PORT_AFFINITY,
+ (void *)0);
+
+ mlx5_modify_lag(ldev, &tracker);
+}
+
+static void mlx5_lag_fib_event_flush(struct notifier_block *nb)
+{
+ struct lag_mp *mp = container_of(nb, struct lag_mp, fib_nb);
+ struct mlx5_lag *ldev = container_of(mp, struct mlx5_lag, lag_mp);
+
+ flush_workqueue(ldev->wq);
+}
+
+struct mlx5_fib_event_work {
+ struct work_struct work;
+ struct mlx5_lag *ldev;
+ unsigned long event;
+ union {
+ struct fib_entry_notifier_info fen_info;
+ struct fib_nh_notifier_info fnh_info;
+ };
+};
+
+static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
+ unsigned long event,
+ struct fib_info *fi)
+{
+ struct lag_mp *mp = &ldev->lag_mp;
+
+ /* Handle delete event */
+ if (event == FIB_EVENT_ENTRY_DEL) {
+ /* stop track */
+ if (mp->mfi == fi)
+ mp->mfi = NULL;
+ return;
+ }
+
+ /* Handle add/replace event */
+ if (fi->fib_nhs == 1) {
+ if (__mlx5_lag_is_active(ldev)) {
+ struct net_device *nh_dev = fi->fib_nh[0].nh_dev;
+ int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev);
+
+ mlx5_lag_set_port_affinity(ldev, ++i);
+ }
+ return;
+ }
+
+ if (fi->fib_nhs != 2)
+ return;
+
+ /* Verify next hops are ports of the same hca */
+ if (!(fi->fib_nh[0].nh_dev == ldev->pf[0].netdev &&
+ fi->fib_nh[1].nh_dev == ldev->pf[1].netdev) &&
+ !(fi->fib_nh[0].nh_dev == ldev->pf[1].netdev &&
+ fi->fib_nh[1].nh_dev == ldev->pf[0].netdev)) {
+ mlx5_core_warn(ldev->pf[0].dev, "Multipath offload require two ports of the same HCA\n");
+ return;
+ }
+
+ /* First time we see multipath route */
+ if (!mp->mfi && !__mlx5_lag_is_active(ldev)) {
+ struct lag_tracker tracker;
+
+ tracker = ldev->tracker;
+ mlx5_activate_lag(ldev, &tracker, MLX5_LAG_FLAG_MULTIPATH);
+ }
+
+ mlx5_lag_set_port_affinity(ldev, 0);
+ mp->mfi = fi;
+}
+
+static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
+ unsigned long event,
+ struct fib_nh *fib_nh,
+ struct fib_info *fi)
+{
+ struct lag_mp *mp = &ldev->lag_mp;
+
+ /* Check the nh event is related to the route */
+ if (!mp->mfi || mp->mfi != fi)
+ return;
+
+ /* nh added/removed */
+ if (event == FIB_EVENT_NH_DEL) {
+ int i = mlx5_lag_dev_get_netdev_idx(ldev, fib_nh->nh_dev);
+
+ if (i >= 0) {
+ i = (i + 1) % 2 + 1; /* peer port */
+ mlx5_lag_set_port_affinity(ldev, i);
+ }
+ } else if (event == FIB_EVENT_NH_ADD &&
+ fi->fib_nhs == 2) {
+ mlx5_lag_set_port_affinity(ldev, 0);
+ }
+}
+
+static void mlx5_lag_fib_update(struct work_struct *work)
+{
+ struct mlx5_fib_event_work *fib_work =
+ container_of(work, struct mlx5_fib_event_work, work);
+ struct mlx5_lag *ldev = fib_work->ldev;
+ struct fib_nh *fib_nh;
+
+ /* Protect internal structures from changes */
+ rtnl_lock();
+ switch (fib_work->event) {
+ case FIB_EVENT_ENTRY_REPLACE: /* fall through */
+ case FIB_EVENT_ENTRY_APPEND: /* fall through */
+ case FIB_EVENT_ENTRY_ADD: /* fall through */
+ case FIB_EVENT_ENTRY_DEL:
+ mlx5_lag_fib_route_event(ldev, fib_work->event,
+ fib_work->fen_info.fi);
+ fib_info_put(fib_work->fen_info.fi);
+ break;
+ case FIB_EVENT_NH_ADD: /* fall through */
+ case FIB_EVENT_NH_DEL:
+ fib_nh = fib_work->fnh_info.fib_nh;
+ mlx5_lag_fib_nexthop_event(ldev,
+ fib_work->event,
+ fib_work->fnh_info.fib_nh,
+ fib_nh->nh_parent);
+ fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
+ break;
+ }
+
+ rtnl_unlock();
+ kfree(fib_work);
+}
+
+static struct mlx5_fib_event_work *
+mlx5_lag_init_fib_work(struct mlx5_lag *ldev, unsigned long event)
+{
+ struct mlx5_fib_event_work *fib_work;
+
+ fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
+ if (WARN_ON(!fib_work))
+ return NULL;
+
+ INIT_WORK(&fib_work->work, mlx5_lag_fib_update);
+ fib_work->ldev = ldev;
+ fib_work->event = event;
+
+ return fib_work;
+}
+
+static int mlx5_lag_fib_event(struct notifier_block *nb,
+ unsigned long event,
+ void *ptr)
+{
+ struct lag_mp *mp = container_of(nb, struct lag_mp, fib_nb);
+ struct mlx5_lag *ldev = container_of(mp, struct mlx5_lag, lag_mp);
+ struct fib_notifier_info *info = ptr;
+ struct mlx5_fib_event_work *fib_work;
+ struct fib_entry_notifier_info *fen_info;
+ struct fib_nh_notifier_info *fnh_info;
+ struct fib_info *fi;
+
+ if (info->family != AF_INET)
+ return NOTIFY_DONE;
+
+ if (!mlx5_lag_multipath_check_prereq(ldev))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case FIB_EVENT_ENTRY_REPLACE: /* fall through */
+ case FIB_EVENT_ENTRY_APPEND: /* fall through */
+ case FIB_EVENT_ENTRY_ADD: /* fall through */
+ case FIB_EVENT_ENTRY_DEL:
+ fen_info = container_of(info, struct fib_entry_notifier_info,
+ info);
+ fi = fen_info->fi;
+ if (fi->fib_dev != ldev->pf[0].netdev &&
+ fi->fib_dev != ldev->pf[1].netdev) {
+ return NOTIFY_DONE;
+ }
+ fib_work = mlx5_lag_init_fib_work(ldev, event);
+ if (!fib_work)
+ return NOTIFY_DONE;
+ fib_work->fen_info = *fen_info;
+ /* Take reference on fib_info to prevent it from being
+ * freed while work is queued. Release it afterwards.
+ */
+ fib_info_hold(fib_work->fen_info.fi);
+ break;
+ case FIB_EVENT_NH_ADD: /* fall through */
+ case FIB_EVENT_NH_DEL:
+ fnh_info = container_of(info, struct fib_nh_notifier_info,
+ info);
+ fib_work = mlx5_lag_init_fib_work(ldev, event);
+ if (!fib_work)
+ return NOTIFY_DONE;
+ fib_work->fnh_info = *fnh_info;
+ fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ queue_work(ldev->wq, &fib_work->work);
+
+ return NOTIFY_DONE;
+}
+
+int mlx5_lag_mp_init(struct mlx5_lag *ldev)
+{
+ struct lag_mp *mp = &ldev->lag_mp;
+ int err;
+
+ if (mp->fib_nb.notifier_call)
+ return 0;
+
+ mp->fib_nb.notifier_call = mlx5_lag_fib_event;
+ err = register_fib_notifier(&mp->fib_nb,
+ mlx5_lag_fib_event_flush);
+ if (err)
+ mp->fib_nb.notifier_call = NULL;
+
+ return err;
+}
+
+void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev)
+{
+ struct lag_mp *mp = &ldev->lag_mp;
+
+ if (!mp->fib_nb.notifier_call)
+ return;
+
+ unregister_fib_notifier(&mp->fib_nb);
+ mp->fib_nb.notifier_call = NULL;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h
new file mode 100644
index 000000000000..6d14b1100be9
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __MLX5_LAG_MP_H__
+#define __MLX5_LAG_MP_H__
+
+#include "lag.h"
+#include "mlx5_core.h"
+
+struct lag_mp {
+ struct notifier_block fib_nb;
+ struct fib_info *mfi; /* used in tracking fib events */
+};
+
+#ifdef CONFIG_MLX5_ESWITCH
+
+int mlx5_lag_mp_init(struct mlx5_lag *ldev);
+void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev);
+
+#else /* CONFIG_MLX5_ESWITCH */
+
+static inline int mlx5_lag_mp_init(struct mlx5_lag *ldev) { return 0; }
+static inline void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev) {}
+
+#endif /* CONFIG_MLX5_ESWITCH */
+#endif /* __MLX5_LAG_MP_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
index 98359559c77e..a71d5b9c7ab2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
@@ -108,8 +108,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev)
mutex_init(&mpfs->lock);
mpfs->size = l2table_size;
- mpfs->bitmap = kcalloc(BITS_TO_LONGS(l2table_size),
- sizeof(uintptr_t), GFP_KERNEL);
+ mpfs->bitmap = bitmap_zalloc(l2table_size, GFP_KERNEL);
if (!mpfs->bitmap) {
kfree(mpfs);
return -ENOMEM;
@@ -127,7 +126,7 @@ void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev)
return;
WARN_ON(!hlist_empty(mpfs->hash));
- kfree(mpfs->bitmap);
+ bitmap_free(mpfs->bitmap);
kfree(mpfs);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
new file mode 100644
index 000000000000..40f4a19b1ce1
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#include <linux/module.h>
+#include <linux/mlx5/driver.h>
+#include <linux/mlx5/port.h>
+#include <linux/mlx5/cmd.h>
+#include "mlx5_core.h"
+#include "lib/port_tun.h"
+
+struct mlx5_port_tun_entropy_flags {
+ bool force_supported, force_enabled;
+ bool calc_supported, calc_enabled;
+ bool gre_calc_supported, gre_calc_enabled;
+};
+
+static void mlx5_query_port_tun_entropy(struct mlx5_core_dev *mdev,
+ struct mlx5_port_tun_entropy_flags *entropy_flags)
+{
+ u32 out[MLX5_ST_SZ_DW(pcmr_reg)];
+ /* Default values for FW which do not support MLX5_REG_PCMR */
+ entropy_flags->force_supported = false;
+ entropy_flags->calc_supported = false;
+ entropy_flags->gre_calc_supported = false;
+ entropy_flags->force_enabled = false;
+ entropy_flags->calc_enabled = true;
+ entropy_flags->gre_calc_enabled = true;
+
+ if (!MLX5_CAP_GEN(mdev, ports_check))
+ return;
+
+ if (mlx5_query_ports_check(mdev, out, sizeof(out)))
+ return;
+
+ entropy_flags->force_supported = !!(MLX5_GET(pcmr_reg, out, entropy_force_cap));
+ entropy_flags->calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_calc_cap));
+ entropy_flags->gre_calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc_cap));
+ entropy_flags->force_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_force));
+ entropy_flags->calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_calc));
+ entropy_flags->gre_calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc));
+}
+
+static int mlx5_set_port_tun_entropy_calc(struct mlx5_core_dev *mdev, u8 enable,
+ u8 force)
+{
+ u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
+ int err;
+
+ err = mlx5_query_ports_check(mdev, in, sizeof(in));
+ if (err)
+ return err;
+ MLX5_SET(pcmr_reg, in, local_port, 1);
+ MLX5_SET(pcmr_reg, in, entropy_force, force);
+ MLX5_SET(pcmr_reg, in, entropy_calc, enable);
+ return mlx5_set_ports_check(mdev, in, sizeof(in));
+}
+
+static int mlx5_set_port_gre_tun_entropy_calc(struct mlx5_core_dev *mdev,
+ u8 enable, u8 force)
+{
+ u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
+ int err;
+
+ err = mlx5_query_ports_check(mdev, in, sizeof(in));
+ if (err)
+ return err;
+ MLX5_SET(pcmr_reg, in, local_port, 1);
+ MLX5_SET(pcmr_reg, in, entropy_force, force);
+ MLX5_SET(pcmr_reg, in, entropy_gre_calc, enable);
+ return mlx5_set_ports_check(mdev, in, sizeof(in));
+}
+
+void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy *tun_entropy,
+ struct mlx5_core_dev *mdev)
+{
+ struct mlx5_port_tun_entropy_flags entropy_flags;
+
+ tun_entropy->mdev = mdev;
+ mutex_init(&tun_entropy->lock);
+ mlx5_query_port_tun_entropy(mdev, &entropy_flags);
+ tun_entropy->num_enabling_entries = 0;
+ tun_entropy->num_disabling_entries = 0;
+ tun_entropy->enabled = entropy_flags.calc_enabled;
+ tun_entropy->enabled =
+ (entropy_flags.calc_supported) ?
+ entropy_flags.calc_enabled : true;
+}
+
+static int mlx5_set_entropy(struct mlx5_tun_entropy *tun_entropy,
+ int reformat_type, bool enable)
+{
+ struct mlx5_port_tun_entropy_flags entropy_flags;
+ int err;
+
+ mlx5_query_port_tun_entropy(tun_entropy->mdev, &entropy_flags);
+ /* Tunnel entropy calculation may be controlled either on port basis
+ * for all tunneling protocols or specifically for GRE protocol.
+ * Prioritize GRE protocol control (if capable) over global port
+ * configuration.
+ */
+ if (entropy_flags.gre_calc_supported &&
+ reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) {
+ /* Other applications may change the global FW entropy
+ * calculations settings. Check that the current entropy value
+ * is the negative of the updated value.
+ */
+ if (entropy_flags.force_enabled &&
+ enable == entropy_flags.gre_calc_enabled) {
+ mlx5_core_warn(tun_entropy->mdev,
+ "Unexpected GRE entropy calc setting - expected %d",
+ !entropy_flags.gre_calc_enabled);
+ return -EOPNOTSUPP;
+ }
+ err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, enable,
+ entropy_flags.force_supported);
+ if (err)
+ return err;
+ /* if we turn on the entropy we don't need to force it anymore */
+ if (entropy_flags.force_supported && enable) {
+ err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, 1, 0);
+ if (err)
+ return err;
+ }
+ } else if (entropy_flags.calc_supported) {
+ /* Other applications may change the global FW entropy
+ * calculations settings. Check that the current entropy value
+ * is the negative of the updated value.
+ */
+ if (entropy_flags.force_enabled &&
+ enable == entropy_flags.calc_enabled) {
+ mlx5_core_warn(tun_entropy->mdev,
+ "Unexpected entropy calc setting - expected %d",
+ !entropy_flags.calc_enabled);
+ return -EOPNOTSUPP;
+ }
+ /* GRE requires disabling entropy calculation. if there are
+ * enabling entries (i.e VXLAN) we cannot turn it off for them,
+ * thus fail.
+ */
+ if (tun_entropy->num_enabling_entries)
+ return -EOPNOTSUPP;
+ err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, enable,
+ entropy_flags.force_supported);
+ if (err)
+ return err;
+ tun_entropy->enabled = enable;
+ /* if we turn on the entropy we don't need to force it anymore */
+ if (entropy_flags.force_supported && enable) {
+ err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, 1, 0);
+ if (err)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+/* the function manages the refcount for enabling/disabling tunnel types.
+ * the return value indicates if the inc is successful or not, depending on
+ * entropy capabilities and configuration.
+ */
+int mlx5_tun_entropy_refcount_inc(struct mlx5_tun_entropy *tun_entropy,
+ int reformat_type)
+{
+ /* the default is error for unknown (non VXLAN/GRE tunnel types) */
+ int err = -EOPNOTSUPP;
+
+ mutex_lock(&tun_entropy->lock);
+ if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN &&
+ tun_entropy->enabled) {
+ /* in case entropy calculation is enabled for all tunneling
+ * types, it is ok for VXLAN, so approve.
+ * otherwise keep the error default.
+ */
+ tun_entropy->num_enabling_entries++;
+ err = 0;
+ } else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) {
+ /* turn off the entropy only for the first GRE rule.
+ * for the next rules the entropy was already disabled
+ * successfully.
+ */
+ if (tun_entropy->num_disabling_entries == 0)
+ err = mlx5_set_entropy(tun_entropy, reformat_type, 0);
+ else
+ err = 0;
+ if (!err)
+ tun_entropy->num_disabling_entries++;
+ }
+ mutex_unlock(&tun_entropy->lock);
+
+ return err;
+}
+
+void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy,
+ int reformat_type)
+{
+ mutex_lock(&tun_entropy->lock);
+ if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN)
+ tun_entropy->num_enabling_entries--;
+ else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE &&
+ --tun_entropy->num_disabling_entries == 0)
+ mlx5_set_entropy(tun_entropy, reformat_type, 1);
+ mutex_unlock(&tun_entropy->lock);
+}
+
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h
new file mode 100644
index 000000000000..54c42a88705e
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __MLX5_PORT_TUN_H__
+#define __MLX5_PORT_TUN_H__
+
+#include <linux/mlx5/driver.h>
+
+struct mlx5_tun_entropy {
+ struct mlx5_core_dev *mdev;
+ u32 num_enabling_entries;
+ u32 num_disabling_entries;
+ u8 enabled;
+ struct mutex lock; /* lock the entropy fields */
+};
+
+void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy *tun_entropy,
+ struct mlx5_core_dev *mdev);
+int mlx5_tun_entropy_refcount_inc(struct mlx5_tun_entropy *tun_entropy,
+ int reformat_type);
+void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy,
+ int reformat_type);
+
+#endif /* __MLX5_PORT_TUN_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mad.c b/drivers/net/ethernet/mellanox/mlx5/core/mad.c
deleted file mode 100644
index 3a3b0005fd2b..000000000000
--- a/drivers/net/ethernet/mellanox/mlx5/core/mad.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * 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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mlx5/driver.h>
-#include <linux/mlx5/cmd.h>
-#include "mlx5_core.h"
-
-int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
- u16 opmod, u8 port)
-{
- int outlen = MLX5_ST_SZ_BYTES(mad_ifc_out);
- int inlen = MLX5_ST_SZ_BYTES(mad_ifc_in);
- int err = -ENOMEM;
- void *data;
- void *resp;
- u32 *out;
- u32 *in;
-
- in = kzalloc(inlen, GFP_KERNEL);
- out = kzalloc(outlen, GFP_KERNEL);
- if (!in || !out)
- goto out;
-
- MLX5_SET(mad_ifc_in, in, opcode, MLX5_CMD_OP_MAD_IFC);
- MLX5_SET(mad_ifc_in, in, op_mod, opmod);
- MLX5_SET(mad_ifc_in, in, port, port);
-
- data = MLX5_ADDR_OF(mad_ifc_in, in, mad);
- memcpy(data, inb, MLX5_FLD_SZ_BYTES(mad_ifc_in, mad));
-
- err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
- if (err)
- goto out;
-
- resp = MLX5_ADDR_OF(mad_ifc_out, out, response_mad_packet);
- memcpy(outb, resp,
- MLX5_FLD_SZ_BYTES(mad_ifc_out, response_mad_packet));
-
-out:
- kfree(out);
- kfree(in);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx5_core_mad_ifc);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index be81b319b0dc..8391dde869a7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -65,6 +65,7 @@
#include "lib/vxlan.h"
#include "lib/devcom.h"
#include "diag/fw_tracer.h"
+#include "ecpf.h"
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
@@ -459,6 +460,50 @@ static int handle_hca_cap_atomic(struct mlx5_core_dev *dev)
return err;
}
+static int handle_hca_cap_odp(struct mlx5_core_dev *dev)
+{
+ void *set_hca_cap;
+ void *set_ctx;
+ int set_sz;
+ int err;
+
+ if (!MLX5_CAP_GEN(dev, pg))
+ return 0;
+
+ err = mlx5_core_get_caps(dev, MLX5_CAP_ODP);
+ if (err)
+ return err;
+
+ if (!(MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive) ||
+ MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive) ||
+ MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive)))
+ return 0;
+
+ set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
+ set_ctx = kzalloc(set_sz, GFP_KERNEL);
+ if (!set_ctx)
+ return -ENOMEM;
+
+ set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
+ memcpy(set_hca_cap, dev->caps.hca_cur[MLX5_CAP_ODP],
+ MLX5_ST_SZ_BYTES(odp_cap));
+
+ /* set ODP SRQ support for RC/UD and XRC transports */
+ MLX5_SET(odp_cap, set_hca_cap, ud_odp_caps.srq_receive,
+ MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive));
+
+ MLX5_SET(odp_cap, set_hca_cap, rc_odp_caps.srq_receive,
+ MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive));
+
+ MLX5_SET(odp_cap, set_hca_cap, xrc_odp_caps.srq_receive,
+ MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive));
+
+ err = set_caps(dev, set_ctx, set_sz, MLX5_SET_HCA_CAP_OP_MOD_ODP);
+
+ kfree(set_ctx);
+ return err;
+}
+
static int handle_hca_cap(struct mlx5_core_dev *dev)
{
void *set_ctx = NULL;
@@ -567,6 +612,8 @@ int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id)
MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA);
MLX5_SET(enable_hca_in, in, function_id, func_id);
+ MLX5_SET(enable_hca_in, in, embedded_cpu_function,
+ dev->caps.embedded_cpu);
return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
}
@@ -577,6 +624,8 @@ int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id)
MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA);
MLX5_SET(disable_hca_in, in, function_id, func_id);
+ MLX5_SET(enable_hca_in, in, embedded_cpu_function,
+ dev->caps.embedded_cpu);
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
}
@@ -693,6 +742,11 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
goto err_clr_master;
}
+ if (pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32) &&
+ pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64) &&
+ pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP128))
+ mlx5_core_dbg(dev, "Enabling pci atomics failed\n");
+
dev->iseg_base = pci_resource_start(dev->pdev, 0);
dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg));
if (!dev->iseg) {
@@ -849,6 +903,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
struct pci_dev *pdev = dev->pdev;
int err;
+ dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
mutex_lock(&dev->intf_state_mutex);
if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
@@ -926,6 +981,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto reclaim_boot_pages;
}
+ err = handle_hca_cap_odp(dev);
+ if (err) {
+ dev_err(&pdev->dev, "handle_hca_cap_odp failed\n");
+ goto reclaim_boot_pages;
+ }
+
err = mlx5_satisfy_startup_pages(dev, 0);
if (err) {
dev_err(&pdev->dev, "failed to allocate init pages\n");
@@ -1014,6 +1075,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_sriov;
}
+ err = mlx5_ec_init(dev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init embedded CPU\n");
+ goto err_ec;
+ }
+
if (mlx5_device_registered(dev)) {
mlx5_attach_device(dev);
} else {
@@ -1031,6 +1098,9 @@ out:
return 0;
err_reg_dev:
+ mlx5_ec_cleanup(dev);
+
+err_ec:
mlx5_sriov_detach(dev);
err_sriov:
@@ -1105,6 +1175,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
if (mlx5_device_registered(dev))
mlx5_detach_device(dev);
+ mlx5_ec_cleanup(dev);
mlx5_sriov_detach(dev);
mlx5_cleanup_fs(dev);
mlx5_accel_ipsec_cleanup(dev);
@@ -1415,6 +1486,8 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5 Ex VF */
{ PCI_VDEVICE(MELLANOX, 0x101b) }, /* ConnectX-6 */
{ PCI_VDEVICE(MELLANOX, 0x101c), MLX5_PCI_DEV_IS_VF}, /* ConnectX-6 VF */
+ { PCI_VDEVICE(MELLANOX, 0x101d) }, /* ConnectX-6 Dx */
+ { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */
{ PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */
{ PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */
{ 0, }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index c68dcea5985b..9529cf9623e3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -121,11 +121,12 @@ int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
u32 modify_bitmask);
int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
u32 element_id);
-int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
+int mlx5_wait_for_pages(struct mlx5_core_dev *dev, int *pages);
u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
struct ptp_system_timestamp *sts);
void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev);
+void mlx5_cmd_flush(struct mlx5_core_dev *dev);
int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev);
void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
@@ -187,6 +188,8 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
MLX5_CAP_GEN(dev, lag_master);
}
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num);
+
void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol);
void mlx5_lag_update(struct mlx5_core_dev *dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c
index 0670165afd5f..ea744d8466ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c
@@ -51,9 +51,10 @@ void mlx5_cleanup_mkey_table(struct mlx5_core_dev *dev)
int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev,
struct mlx5_core_mkey *mkey,
- u32 *in, int inlen,
- u32 *out, int outlen,
- mlx5_cmd_cbk_t callback, void *context)
+ struct mlx5_async_ctx *async_ctx, u32 *in,
+ int inlen, u32 *out, int outlen,
+ mlx5_async_cbk_t callback,
+ struct mlx5_async_work *context)
{
struct mlx5_mkey_table *table = &dev->priv.mkey_table;
u32 lout[MLX5_ST_SZ_DW(create_mkey_out)] = {0};
@@ -71,7 +72,7 @@ int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev,
MLX5_SET(mkc, mkc, mkey_7_0, key);
if (callback)
- return mlx5_cmd_exec_cb(dev, in, inlen, out, outlen,
+ return mlx5_cmd_exec_cb(async_ctx, in, inlen, out, outlen,
callback, context);
err = mlx5_cmd_exec(dev, in, inlen, lout, sizeof(lout));
@@ -105,7 +106,7 @@ int mlx5_core_create_mkey(struct mlx5_core_dev *dev,
struct mlx5_core_mkey *mkey,
u32 *in, int inlen)
{
- return mlx5_core_create_mkey_cb(dev, mkey, in, inlen,
+ return mlx5_core_create_mkey_cb(dev, mkey, NULL, in, inlen,
NULL, 0, NULL, NULL);
}
EXPORT_SYMBOL(mlx5_core_create_mkey);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index a83b517b0714..41025387ff2c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -48,6 +48,7 @@ enum {
struct mlx5_pages_req {
struct mlx5_core_dev *dev;
u16 func_id;
+ u8 ec_function;
s32 npages;
struct work_struct work;
};
@@ -143,6 +144,7 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
MLX5_SET(query_pages_in, in, op_mod, boot ?
MLX5_QUERY_PAGES_IN_OP_MOD_BOOT_PAGES :
MLX5_QUERY_PAGES_IN_OP_MOD_INIT_PAGES);
+ MLX5_SET(query_pages_in, in, embedded_cpu_function, mlx5_core_is_ecpf(dev));
err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
if (err)
@@ -253,7 +255,8 @@ err_mapping:
return err;
}
-static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id)
+static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id,
+ bool ec_function)
{
u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0};
u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {0};
@@ -262,6 +265,7 @@ static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id)
MLX5_SET(manage_pages_in, in, opcode, MLX5_CMD_OP_MANAGE_PAGES);
MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_CANT_GIVE);
MLX5_SET(manage_pages_in, in, function_id, func_id);
+ MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
if (err)
@@ -270,7 +274,7 @@ static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id)
}
static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
- int notify_fail)
+ int notify_fail, bool ec_function)
{
u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0};
int inlen = MLX5_ST_SZ_BYTES(manage_pages_in);
@@ -305,6 +309,7 @@ retry:
MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_GIVE);
MLX5_SET(manage_pages_in, in, function_id, func_id);
MLX5_SET(manage_pages_in, in, input_num_entries, npages);
+ MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
if (err) {
@@ -316,8 +321,11 @@ retry:
dev->priv.fw_pages += npages;
if (func_id)
dev->priv.vfs_pages += npages;
+ else if (mlx5_core_is_ecpf(dev) && !ec_function)
+ dev->priv.peer_pf_pages += npages;
- mlx5_core_dbg(dev, "err %d\n", err);
+ mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n",
+ npages, ec_function, func_id, err);
kvfree(in);
return 0;
@@ -328,7 +336,7 @@ out_4k:
out_free:
kvfree(in);
if (notify_fail)
- page_notify_fail(dev, func_id);
+ page_notify_fail(dev, func_id, ec_function);
return err;
}
@@ -364,7 +372,7 @@ static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
}
static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
- int *nclaimed)
+ int *nclaimed, bool ec_function)
{
int outlen = MLX5_ST_SZ_BYTES(manage_pages_out);
u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {0};
@@ -385,6 +393,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_TAKE);
MLX5_SET(manage_pages_in, in, function_id, func_id);
MLX5_SET(manage_pages_in, in, input_num_entries, npages);
+ MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function);
mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen);
err = reclaim_pages_cmd(dev, in, sizeof(in), out, outlen);
@@ -410,6 +419,8 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
dev->priv.fw_pages -= num_claimed;
if (func_id)
dev->priv.vfs_pages -= num_claimed;
+ else if (mlx5_core_is_ecpf(dev) && !ec_function)
+ dev->priv.peer_pf_pages -= num_claimed;
out_free:
kvfree(out);
@@ -423,9 +434,10 @@ static void pages_work_handler(struct work_struct *work)
int err = 0;
if (req->npages < 0)
- err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL);
+ err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL,
+ req->ec_function);
else if (req->npages > 0)
- err = give_pages(dev, req->func_id, req->npages, 1);
+ err = give_pages(dev, req->func_id, req->npages, 1, req->ec_function);
if (err)
mlx5_core_warn(dev, "%s fail %d\n",
@@ -434,6 +446,10 @@ static void pages_work_handler(struct work_struct *work)
kfree(req);
}
+enum {
+ EC_FUNCTION_MASK = 0x8000,
+};
+
static int req_pages_handler(struct notifier_block *nb,
unsigned long type, void *data)
{
@@ -441,6 +457,7 @@ static int req_pages_handler(struct notifier_block *nb,
struct mlx5_core_dev *dev;
struct mlx5_priv *priv;
struct mlx5_eqe *eqe;
+ bool ec_function;
u16 func_id;
s32 npages;
@@ -450,6 +467,7 @@ static int req_pages_handler(struct notifier_block *nb,
func_id = be16_to_cpu(eqe->data.req_pages.func_id);
npages = be32_to_cpu(eqe->data.req_pages.num_pages);
+ ec_function = be16_to_cpu(eqe->data.req_pages.ec_function) & EC_FUNCTION_MASK;
mlx5_core_dbg(dev, "page request for func 0x%x, npages %d\n",
func_id, npages);
req = kzalloc(sizeof(*req), GFP_ATOMIC);
@@ -461,6 +479,7 @@ static int req_pages_handler(struct notifier_block *nb,
req->dev = dev;
req->func_id = func_id;
req->npages = npages;
+ req->ec_function = ec_function;
INIT_WORK(&req->work, pages_work_handler);
queue_work(dev->priv.pg_wq, &req->work);
return NOTIFY_OK;
@@ -479,7 +498,7 @@ int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n",
npages, boot ? "boot" : "init", func_id);
- return give_pages(dev, func_id, npages, 0);
+ return give_pages(dev, func_id, npages, 0, mlx5_core_is_ecpf(dev));
}
enum {
@@ -513,7 +532,7 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
fwp = rb_entry(p, struct fw_page, rb_node);
err = reclaim_pages(dev, fwp->func_id,
optimal_reclaimed_pages(),
- &nclaimed);
+ &nclaimed, mlx5_core_is_ecpf(dev));
if (err) {
mlx5_core_warn(dev, "failed reclaiming pages (%d)\n",
@@ -535,6 +554,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
WARN(dev->priv.vfs_pages,
"VFs FW pages counter is %d after reclaiming all pages\n",
dev->priv.vfs_pages);
+ WARN(dev->priv.peer_pf_pages,
+ "Peer PF FW pages counter is %d after reclaiming all pages\n",
+ dev->priv.peer_pf_pages);
return 0;
}
@@ -567,10 +589,10 @@ void mlx5_pagealloc_stop(struct mlx5_core_dev *dev)
flush_workqueue(dev->priv.pg_wq);
}
-int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev)
+int mlx5_wait_for_pages(struct mlx5_core_dev *dev, int *pages)
{
unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS);
- int prev_vfs_pages = dev->priv.vfs_pages;
+ int prev_pages = *pages;
/* In case of internal error we will free the pages manually later */
if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
@@ -578,16 +600,16 @@ int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev)
return 0;
}
- mlx5_core_dbg(dev, "Waiting for %d pages from %s\n", prev_vfs_pages,
+ mlx5_core_dbg(dev, "Waiting for %d pages from %s\n", prev_pages,
dev->priv.name);
- while (dev->priv.vfs_pages) {
+ while (*pages) {
if (time_after(jiffies, end)) {
- mlx5_core_warn(dev, "aborting while there are %d pending pages\n", dev->priv.vfs_pages);
+ mlx5_core_warn(dev, "aborting while there are %d pending pages\n", *pages);
return -ETIMEDOUT;
}
- if (dev->priv.vfs_pages < prev_vfs_pages) {
+ if (*pages < prev_pages) {
end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS);
- prev_vfs_pages = dev->priv.vfs_pages;
+ prev_pages = *pages;
}
msleep(50);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 2b82f35f4c35..21b7f05b16a5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -30,10 +30,7 @@
* SOFTWARE.
*/
-#include <linux/module.h>
-#include <linux/mlx5/driver.h>
#include <linux/mlx5/port.h>
-#include <linux/mlx5/cmd.h>
#include "mlx5_core.h"
int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
@@ -157,44 +154,6 @@ int mlx5_set_port_beacon(struct mlx5_core_dev *dev, u16 beacon_duration)
sizeof(out), MLX5_REG_MLCR, 0, 1);
}
-int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
- u32 *proto_cap, int proto_mask)
-{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
- int err;
-
- err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
- if (err)
- return err;
-
- if (proto_mask == MLX5_PTYS_EN)
- *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
- else
- *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
-
-int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
- u32 *proto_admin, int proto_mask)
-{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
- int err;
-
- err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
- if (err)
- return err;
-
- if (proto_mask == MLX5_PTYS_EN)
- *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
- else
- *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
-
int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev,
u8 *link_width_oper, u8 local_port)
{
@@ -211,23 +170,6 @@ int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev,
}
EXPORT_SYMBOL_GPL(mlx5_query_port_link_width_oper);
-int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
- u32 *proto_oper, u8 local_port)
-{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
- int err;
-
- err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
- local_port);
- if (err)
- return err;
-
- *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
-
- return 0;
-}
-EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
-
int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev,
u8 *proto_oper, u8 local_port)
{
@@ -245,35 +187,6 @@ int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev,
}
EXPORT_SYMBOL(mlx5_query_port_ib_proto_oper);
-int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable,
- u32 proto_admin, int proto_mask)
-{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
- u32 in[MLX5_ST_SZ_DW(ptys_reg)];
- u8 an_disable_admin;
- u8 an_disable_cap;
- u8 an_status;
-
- mlx5_query_port_autoneg(dev, proto_mask, &an_status,
- &an_disable_cap, &an_disable_admin);
- if (!an_disable_cap && an_disable)
- return -EPERM;
-
- memset(in, 0, sizeof(in));
-
- MLX5_SET(ptys_reg, in, local_port, 1);
- MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
- MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
- if (proto_mask == MLX5_PTYS_EN)
- MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
- else
- MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
-
- return mlx5_core_access_reg(dev, in, sizeof(in), out,
- sizeof(out), MLX5_REG_PTYS, 0, 1);
-}
-EXPORT_SYMBOL_GPL(mlx5_set_port_ptys);
-
/* This function should be used after setting a port register only */
void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
{
@@ -606,25 +519,6 @@ int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
}
EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
-void mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
- u8 *an_status,
- u8 *an_disable_cap, u8 *an_disable_admin)
-{
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
-
- *an_status = 0;
- *an_disable_cap = 0;
- *an_disable_admin = 0;
-
- if (mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1))
- return;
-
- *an_status = MLX5_GET(ptys_reg, out, an_status);
- *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
- *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
-}
-EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
-
int mlx5_max_tc(struct mlx5_core_dev *mdev)
{
u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
@@ -870,8 +764,7 @@ int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode)
}
EXPORT_SYMBOL_GPL(mlx5_query_port_wol);
-static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out,
- int outlen)
+int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen)
{
u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
@@ -880,7 +773,7 @@ static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out,
outlen, MLX5_REG_PCMR, 0, 0);
}
-static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
+int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
{
u32 out[MLX5_ST_SZ_DW(pcmr_reg)];
@@ -891,7 +784,11 @@ static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable)
{
u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
+ int err;
+ err = mlx5_query_ports_check(mdev, in, sizeof(in));
+ if (err)
+ return err;
MLX5_SET(pcmr_reg, in, local_port, 1);
MLX5_SET(pcmr_reg, in, fcs_chk, enable);
return mlx5_set_ports_check(mdev, in, sizeof(in));
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
index 388f205a497f..370ca94b6775 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
@@ -44,14 +44,15 @@ static struct mlx5_core_rsc_common *
mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
{
struct mlx5_core_rsc_common *common;
+ unsigned long flags;
- spin_lock(&table->lock);
+ spin_lock_irqsave(&table->lock, flags);
common = radix_tree_lookup(&table->tree, rsn);
if (common)
atomic_inc(&common->refcount);
- spin_unlock(&table->lock);
+ spin_unlock_irqrestore(&table->lock, flags);
return common;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
index 6e178030d8fb..7b23fa8d2d60 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
@@ -147,7 +147,7 @@ out:
if (MLX5_ESWITCH_MANAGER(dev))
mlx5_eswitch_disable_sriov(dev->priv.eswitch);
- if (mlx5_wait_for_vf_pages(dev))
+ if (mlx5_wait_for_pages(dev, &dev->priv.vfs_pages))
mlx5_core_warn(dev, "timeout reclaiming VFs pages\n");
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/uar.c b/drivers/net/ethernet/mellanox/mlx5/core/uar.c
index 8b97066dd1f1..94464723ff77 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/uar.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/uar.c
@@ -90,8 +90,8 @@ static void up_rel_func(struct kref *kref)
iounmap(up->map);
if (mlx5_cmd_free_uar(up->mdev, up->index))
mlx5_core_warn(up->mdev, "failed to free uar index %d\n", up->index);
- kfree(up->reg_bitmap);
- kfree(up->fp_bitmap);
+ bitmap_free(up->reg_bitmap);
+ bitmap_free(up->fp_bitmap);
kfree(up);
}
@@ -110,11 +110,11 @@ static struct mlx5_uars_page *alloc_uars_page(struct mlx5_core_dev *mdev,
return ERR_PTR(err);
up->mdev = mdev;
- up->reg_bitmap = kcalloc(BITS_TO_LONGS(bfregs), sizeof(unsigned long), GFP_KERNEL);
+ up->reg_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL);
if (!up->reg_bitmap)
goto error1;
- up->fp_bitmap = kcalloc(BITS_TO_LONGS(bfregs), sizeof(unsigned long), GFP_KERNEL);
+ up->fp_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL);
if (!up->fp_bitmap)
goto error1;
@@ -157,8 +157,8 @@ error2:
if (mlx5_cmd_free_uar(mdev, up->index))
mlx5_core_warn(mdev, "failed to free uar index %d\n", up->index);
error1:
- kfree(up->fp_bitmap);
- kfree(up->reg_bitmap);
+ bitmap_free(up->fp_bitmap);
+ bitmap_free(up->reg_bitmap);
kfree(up);
return ERR_PTR(err);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index 9b150ce9d315..ef95feca9961 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -64,7 +64,7 @@ u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
}
int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
- u16 vport, u8 state)
+ u16 vport, u8 other_vport, u8 state)
{
u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {0};
u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)] = {0};
@@ -73,8 +73,7 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
MLX5_CMD_OP_MODIFY_VPORT_STATE);
MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
MLX5_SET(modify_vport_state_in, in, vport_number, vport);
- if (vport)
- MLX5_SET(modify_vport_state_in, in, other_vport, 1);
+ MLX5_SET(modify_vport_state_in, in, other_vport, other_vport);
MLX5_SET(modify_vport_state_in, in, admin_state, state);
return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
@@ -255,7 +254,7 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
- u32 vport,
+ u16 vport,
enum mlx5_list_type list_type,
u8 addr_list[][ETH_ALEN],
int *list_size)
@@ -373,7 +372,7 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
- u32 vport,
+ u16 vport,
u16 vlans[],
int *size)
{
@@ -526,7 +525,7 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
- u32 vport, u64 node_guid)
+ u16 vport, u64 node_guid)
{
int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
void *nic_vport_context;
@@ -827,7 +826,7 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
- u32 vport,
+ u16 vport,
int *promisc_uc,
int *promisc_mc,
int *promisc_all)
@@ -1057,7 +1056,7 @@ free:
EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
- u64 *rx_discard_vport_down,
+ u8 other_vport, u64 *rx_discard_vport_down,
u64 *tx_discard_vport_down)
{
u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {0};
@@ -1068,8 +1067,7 @@ int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
MLX5_CMD_OP_QUERY_VNIC_ENV);
MLX5_SET(query_vnic_env_in, in, op_mod, 0);
MLX5_SET(query_vnic_env_in, in, vport_number, vport);
- if (vport)
- MLX5_SET(query_vnic_env_in, in, other_vport, 1);
+ MLX5_SET(query_vnic_env_in, in, other_vport, other_vport);
err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h
index 7a712b6b09ec..14c0c62f8e73 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#ifndef _MLXFW_H
#define _MLXFW_H
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c
index 2cf89126fb23..240c027e5f07 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#define pr_fmt(fmt) "mlxfw: " fmt
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
index 993cb5ba934e..544344ac4894 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#define pr_fmt(fmt) "mlxfw_mfa2: " fmt
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h
index 20472aa139cd..5bba6ad79d34 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#ifndef _MLXFW_MFA2_H
#define _MLXFW_MFA2_H
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h
index f667942b1ea3..874c0a2474ae 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#ifndef _MLXFW_MFA2_FILE_H
#define _MLXFW_MFA2_FILE_H
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
index dd66737c033d..b001e5258091 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
@@ -1,36 +1,6 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
+
#ifndef _MLXFW_MFA2_FORMAT_H
#define _MLXFW_MFA2_FORMAT_H
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h
index cc013e77b326..33c971190bba 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#ifndef _MLXFW_MFA2_TLV_H
#define _MLXFW_MFA2_TLV_H
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
index 0094b92a233b..017d68f1e123 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
@@ -1,36 +1,5 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
#define pr_fmt(fmt) "MFA2: " fmt
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h
index 2c667894f3a2..633284eeded7 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h
@@ -1,36 +1,6 @@
-/*
- * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the names of the copyright holders nor the names of its
- * 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") version 2 as published by the Free
- * Software Foundation.
- *
- * 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 OWNER 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.
- */
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
+
#ifndef _MLXFW_MFA2_TLV_MULTI_H
#define _MLXFW_MFA2_TLV_MULTI_H
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
index 080ddd1942ec..9c195dfed031 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
@@ -4,7 +4,6 @@
config MLXSW_CORE
tristate "Mellanox Technologies Switch ASICs support"
- depends on MAY_USE_DEVLINK
---help---
This driver supports Mellanox Technologies Switch ASICs family.
@@ -78,6 +77,7 @@ config MLXSW_SPECTRUM
depends on IPV6 || IPV6=n
depends on NET_IPGRE || NET_IPGRE=n
depends on IPV6_GRE || IPV6_GRE=n
+ depends on VXLAN || VXLAN=n
select GENERIC_ALLOCATOR
select PARMAN
select OBJAGG
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index bbf45f10c208..a01d15546e37 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o
mlxsw_core-objs := core.o core_acl_flex_keys.o \
- core_acl_flex_actions.o
+ core_acl_flex_actions.o core_env.o
mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o
obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index ddedf8ab5b64..d23d53c0e284 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1062,6 +1062,9 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
goto err_driver_init;
}
+ if (mlxsw_driver->params_register && !reload)
+ devlink_params_publish(devlink);
+
return 0;
err_driver_init:
@@ -1131,6 +1134,8 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
return;
}
+ if (mlxsw_core->driver->params_unregister && !reload)
+ devlink_params_unpublish(devlink);
if (mlxsw_core->driver->fini)
mlxsw_core->driver->fini(mlxsw_core);
mlxsw_thermal_fini(mlxsw_core->thermal);
@@ -1460,13 +1465,17 @@ static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans)
if (trans->retries)
dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n",
trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid);
- if (err)
+ if (err) {
dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n",
trans->tid, trans->reg->id,
mlxsw_reg_id_str(trans->reg->id),
mlxsw_core_reg_access_type_str(trans->type),
trans->emad_status,
mlxsw_emad_op_tlv_status_str(trans->emad_status));
+ trace_devlink_hwerr(priv_to_devlink(mlxsw_core),
+ trans->emad_status,
+ mlxsw_emad_op_tlv_status_str(trans->emad_status));
+ }
list_del(&trans->bulk_list);
kfree_rcu(trans, rcu);
@@ -1908,6 +1917,43 @@ void mlxsw_core_fw_flash_end(struct mlxsw_core *mlxsw_core)
}
EXPORT_SYMBOL(mlxsw_core_fw_flash_end);
+int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox,
+ struct mlxsw_res *res)
+{
+ int index, i;
+ u64 data;
+ u16 id;
+ int err;
+
+ if (!res)
+ return 0;
+
+ mlxsw_cmd_mbox_zero(mbox);
+
+ for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
+ index++) {
+ err = mlxsw_cmd_query_resources(mlxsw_core, mbox, index);
+ if (err)
+ return err;
+
+ for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
+ id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
+ data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
+
+ if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
+ return 0;
+
+ mlxsw_res_parse(res, id, data);
+ }
+ }
+
+ /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get
+ * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW.
+ */
+ return -EIO;
+}
+EXPORT_SYMBOL(mlxsw_core_resources_query);
+
static int __init mlxsw_core_module_init(void)
{
int err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 4e114f35ee0d..8ec53f027575 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -182,6 +182,8 @@ int mlxsw_core_port_get_phys_port_name(struct mlxsw_core *mlxsw_core,
int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);
bool mlxsw_core_schedule_work(struct work_struct *work);
void mlxsw_core_flush_owq(void);
+int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox,
+ struct mlxsw_res *res);
#define MLXSW_CONFIG_PROFILE_SWID_COUNT 8
@@ -344,6 +346,7 @@ struct mlxsw_bus_info {
struct mlxsw_fw_rev fw_rev;
u8 vsd[MLXSW_CMD_BOARDINFO_VSD_LEN];
u8 psid[MLXSW_CMD_BOARDINFO_PSID_LEN];
+ u8 low_frequency;
};
struct mlxsw_hwmon;
@@ -394,4 +397,9 @@ static inline void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
#endif
+enum mlxsw_devlink_param_id {
+ MLXSW_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+ MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
+};
+
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
index df78d23b3ec3..cb3e663b1d37 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
@@ -236,12 +236,10 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk,
struct mlxsw_afk_element_usage *elusage)
{
struct mlxsw_afk_key_info *key_info;
- size_t alloc_size;
int err;
- alloc_size = sizeof(*key_info) +
- sizeof(key_info->blocks[0]) * mlxsw_afk->max_blocks;
- key_info = kzalloc(alloc_size, GFP_KERNEL);
+ key_info = kzalloc(struct_size(key_info, blocks, mlxsw_afk->max_blocks),
+ GFP_KERNEL);
if (!key_info)
return ERR_PTR(-ENOMEM);
err = mlxsw_afk_picker(mlxsw_afk, key_info, elusage);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
new file mode 100644
index 000000000000..7a15e932ed2f
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include "core.h"
+#include "core_env.h"
+#include "item.h"
+#include "reg.h"
+
+static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id,
+ bool *qsfp)
+{
+ char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
+ char mcia_pl[MLXSW_REG_MCIA_LEN];
+ u8 ident;
+ int err;
+
+ mlxsw_reg_mcia_pack(mcia_pl, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1,
+ MLXSW_REG_MCIA_I2C_ADDR_LOW);
+ err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
+ if (err)
+ return err;
+ mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
+ ident = eeprom_tmp[0];
+ switch (ident) {
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
+ *qsfp = false;
+ break;
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: /* fall-through */
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: /* fall-through */
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD:
+ *qsfp = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
+ u16 offset, u16 size, void *data,
+ unsigned int *p_read_size)
+{
+ char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
+ char mcia_pl[MLXSW_REG_MCIA_LEN];
+ u16 i2c_addr;
+ int status;
+ int err;
+
+ size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
+
+ if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
+ offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
+ /* Cross pages read, read until offset 256 in low page */
+ size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
+
+ i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
+ if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
+ i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
+ offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
+ }
+
+ mlxsw_reg_mcia_pack(mcia_pl, module, 0, 0, offset, size, i2c_addr);
+
+ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl);
+ if (err)
+ return err;
+
+ status = mlxsw_reg_mcia_status_get(mcia_pl);
+ if (status)
+ return -EIO;
+
+ mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
+ memcpy(data, eeprom_tmp, size);
+ *p_read_size = size;
+
+ return 0;
+}
+
+int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
+ int off, int *temp)
+{
+ char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
+ union {
+ u8 buf[MLXSW_REG_MCIA_TH_ITEM_SIZE];
+ u16 temp;
+ } temp_thresh;
+ char mcia_pl[MLXSW_REG_MCIA_LEN] = {0};
+ char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
+ u16 module_temp;
+ bool qsfp;
+ int err;
+
+ mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
+ 1);
+ err = mlxsw_reg_query(core, MLXSW_REG(mtbr), mtbr_pl);
+ if (err)
+ return err;
+
+ /* Don't read temperature thresholds for module with no valid info. */
+ mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &module_temp, NULL);
+ switch (module_temp) {
+ case MLXSW_REG_MTBR_BAD_SENS_INFO: /* fall-through */
+ case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+ case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+ case MLXSW_REG_MTBR_INDEX_NA:
+ *temp = 0;
+ return 0;
+ default:
+ /* Do not consider thresholds for zero temperature. */
+ if (!MLXSW_REG_MTMP_TEMP_TO_MC(module_temp)) {
+ *temp = 0;
+ return 0;
+ }
+ break;
+ }
+
+ /* Read Free Side Device Temperature Thresholds from page 03h
+ * (MSB at lower byte address).
+ * Bytes:
+ * 128-129 - Temp High Alarm (SFP_TEMP_HIGH_ALARM);
+ * 130-131 - Temp Low Alarm (SFP_TEMP_LOW_ALARM);
+ * 132-133 - Temp High Warning (SFP_TEMP_HIGH_WARN);
+ * 134-135 - Temp Low Warning (SFP_TEMP_LOW_WARN);
+ */
+
+ /* Validate module identifier value. */
+ err = mlxsw_env_validate_cable_ident(core, module, &qsfp);
+ if (err)
+ return err;
+
+ if (qsfp)
+ mlxsw_reg_mcia_pack(mcia_pl, module, 0,
+ MLXSW_REG_MCIA_TH_PAGE_NUM,
+ MLXSW_REG_MCIA_TH_PAGE_OFF + off,
+ MLXSW_REG_MCIA_TH_ITEM_SIZE,
+ MLXSW_REG_MCIA_I2C_ADDR_LOW);
+ else
+ mlxsw_reg_mcia_pack(mcia_pl, module, 0,
+ MLXSW_REG_MCIA_PAGE0_LO,
+ off, MLXSW_REG_MCIA_TH_ITEM_SIZE,
+ MLXSW_REG_MCIA_I2C_ADDR_HIGH);
+
+ err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
+ if (err)
+ return err;
+
+ mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
+ memcpy(temp_thresh.buf, eeprom_tmp, MLXSW_REG_MCIA_TH_ITEM_SIZE);
+ *temp = temp_thresh.temp * 1000;
+
+ return 0;
+}
+
+int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
+ struct ethtool_modinfo *modinfo)
+{
+ u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
+ u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
+ u8 module_rev_id, module_id;
+ unsigned int read_size;
+ int err;
+
+ err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset,
+ module_info, &read_size);
+ if (err)
+ return err;
+
+ if (read_size < offset)
+ return -EIO;
+
+ module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID];
+ module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID];
+
+ switch (module_id) {
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+ break;
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
+ if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 ||
+ module_rev_id >=
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) {
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+ }
+ break;
+ case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
+ modinfo->type = ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mlxsw_env_get_module_info);
+
+int mlxsw_env_get_module_eeprom(struct net_device *netdev,
+ struct mlxsw_core *mlxsw_core, int module,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ int offset = ee->offset;
+ unsigned int read_size;
+ int i = 0;
+ int err;
+
+ if (!ee->len)
+ return -EINVAL;
+
+ memset(data, 0, ee->len);
+
+ while (i < ee->len) {
+ err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset,
+ ee->len - i, data + i,
+ &read_size);
+ if (err) {
+ netdev_err(netdev, "Eeprom query failed\n");
+ return err;
+ }
+
+ i += read_size;
+ offset += read_size;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mlxsw_env_get_module_eeprom);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
new file mode 100644
index 000000000000..064d0e770c01
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
+
+#ifndef _MLXSW_CORE_ENV_H
+#define _MLXSW_CORE_ENV_H
+
+int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
+ int off, int *temp);
+
+int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
+ struct ethtool_modinfo *modinfo);
+
+int mlxsw_env_get_module_eeprom(struct net_device *netdev,
+ struct mlxsw_core *mlxsw_core, int module,
+ struct ethtool_eeprom *ee, u8 *data);
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index e04e8162aa14..6956bbebe2f1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -7,8 +7,10 @@
#include <linux/sysfs.h>
#include <linux/hwmon.h>
#include <linux/err.h>
+#include <linux/sfp.h>
#include "core.h"
+#include "core_env.h"
#define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
@@ -30,6 +32,7 @@ struct mlxsw_hwmon {
struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
unsigned int attrs_count;
+ u8 sensor_count;
};
static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
@@ -121,6 +124,27 @@ static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
}
+static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+ char fore_pl[MLXSW_REG_FORE_LEN];
+ bool fault;
+ int err;
+
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl);
+ if (err) {
+ dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
+ return err;
+ }
+ mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault);
+
+ return sprintf(buf, "%u\n", fault);
+}
+
static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -167,12 +191,160 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
return len;
}
+static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+ char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
+ u16 temp;
+ u8 module;
+ int err;
+
+ module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+ mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
+ 1);
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
+ if (err) {
+ dev_err(dev, "Failed to query module temperature sensor\n");
+ return err;
+ }
+
+ mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
+ /* Update status and temperature cache. */
+ switch (temp) {
+ case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+ case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+ case MLXSW_REG_MTBR_INDEX_NA:
+ temp = 0;
+ break;
+ case MLXSW_REG_MTBR_BAD_SENS_INFO:
+ /* Untrusted cable is connected. Reading temperature from its
+ * sensor is faulty.
+ */
+ temp = 0;
+ break;
+ default:
+ temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
+ break;
+ }
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+ char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
+ u8 module, fault;
+ u16 temp;
+ int err;
+
+ module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+ mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
+ 1);
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
+ if (err) {
+ dev_err(dev, "Failed to query module temperature sensor\n");
+ return err;
+ }
+
+ mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
+
+ /* Update status and temperature cache. */
+ switch (temp) {
+ case MLXSW_REG_MTBR_BAD_SENS_INFO:
+ /* Untrusted cable is connected. Reading temperature from its
+ * sensor is faulty.
+ */
+ fault = 1;
+ break;
+ case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+ case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+ case MLXSW_REG_MTBR_INDEX_NA:
+ default:
+ fault = 0;
+ break;
+ }
+
+ return sprintf(buf, "%u\n", fault);
+}
+
+static ssize_t
+mlxsw_hwmon_module_temp_critical_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+ int temp;
+ u8 module;
+ int err;
+
+ module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
+ SFP_TEMP_HIGH_WARN, &temp);
+ if (err) {
+ dev_err(dev, "Failed to query module temperature thresholds\n");
+ return err;
+ }
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t
+mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+ u8 module;
+ int temp;
+ int err;
+
+ module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
+ SFP_TEMP_HIGH_ALARM, &temp);
+ if (err) {
+ dev_err(dev, "Failed to query module temperature thresholds\n");
+ return err;
+ }
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t
+mlxsw_hwmon_module_temp_label_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+
+ return sprintf(buf, "front panel %03u\n",
+ mlwsw_hwmon_attr->type_index);
+}
+
enum mlxsw_hwmon_attr_type {
MLXSW_HWMON_ATTR_TYPE_TEMP,
MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
+ MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
MLXSW_HWMON_ATTR_TYPE_PWM,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
};
static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
@@ -209,6 +381,12 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
"fan%u_input", num + 1);
break;
+ case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT:
+ mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "fan%u_fault", num + 1);
+ break;
case MLXSW_HWMON_ATTR_TYPE_PWM:
mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
@@ -216,6 +394,40 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
"pwm%u", num + 1);
break;
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE:
+ mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "temp%u_input", num + 1);
+ break;
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT:
+ mlxsw_hwmon_attr->dev_attr.show =
+ mlxsw_hwmon_module_temp_fault_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "temp%u_fault", num + 1);
+ break;
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT:
+ mlxsw_hwmon_attr->dev_attr.show =
+ mlxsw_hwmon_module_temp_critical_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "temp%u_crit", num + 1);
+ break;
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG:
+ mlxsw_hwmon_attr->dev_attr.show =
+ mlxsw_hwmon_module_temp_emergency_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "temp%u_emergency", num + 1);
+ break;
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL:
+ mlxsw_hwmon_attr->dev_attr.show =
+ mlxsw_hwmon_module_temp_label_show;
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+ "temp%u_label", num + 1);
+ break;
default:
WARN_ON(1);
}
@@ -233,7 +445,6 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
{
char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- u8 sensor_count;
int i;
int err;
@@ -242,8 +453,8 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n");
return err;
}
- sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
- for (i = 0; i < sensor_count; i++) {
+ mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
+ for (i = 0; i < mlxsw_hwmon->sensor_count; i++) {
mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true);
err = mlxsw_reg_write(mlxsw_hwmon->core,
MLXSW_REG(mtmp), mtmp_pl);
@@ -280,10 +491,14 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
num = 0;
for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
- if (tacho_active & BIT(type_index))
+ if (tacho_active & BIT(type_index)) {
mlxsw_hwmon_attr_add(mlxsw_hwmon,
MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
+ type_index, num);
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
type_index, num++);
+ }
}
num = 0;
for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
@@ -295,6 +510,53 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
return 0;
}
+static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
+{
+ unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core);
+ char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0};
+ int i, index;
+ u8 width;
+ int err;
+
+ /* Add extra attributes for module temperature. Sensor index is
+ * assigned to sensor_count value, while all indexed before
+ * sensor_count are already utilized by the sensors connected through
+ * mtmp register by mlxsw_hwmon_temp_init().
+ */
+ index = mlxsw_hwmon->sensor_count;
+ for (i = 1; i < module_count; i++) {
+ mlxsw_reg_pmlp_pack(pmlp_pl, i);
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp),
+ pmlp_pl);
+ if (err) {
+ dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n",
+ i);
+ return err;
+ }
+ width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+ if (!width)
+ continue;
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index,
+ index);
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
+ index, index);
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
+ index, index);
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
+ index, index);
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
+ index, index);
+ index++;
+ }
+
+ return 0;
+}
+
int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info,
struct mlxsw_hwmon **p_hwmon)
@@ -317,6 +579,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
if (err)
goto err_fans_init;
+ err = mlxsw_hwmon_module_init(mlxsw_hwmon);
+ if (err)
+ goto err_temp_module_init;
+
mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
@@ -333,6 +599,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
return 0;
err_hwmon_register:
+err_temp_module_init:
err_fans_init:
err_temp_init:
kfree(mlxsw_hwmon);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 61f897b40f82..0b85c7252f9e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -9,11 +9,20 @@
#include <linux/sysfs.h>
#include <linux/thermal.h>
#include <linux/err.h>
+#include <linux/sfp.h>
#include "core.h"
+#include "core_env.h"
#define MLXSW_THERMAL_POLL_INT 1000 /* ms */
-#define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */
+#define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */
+#define MLXSW_THERMAL_ASIC_TEMP_NORM 75000 /* 75C */
+#define MLXSW_THERMAL_ASIC_TEMP_HIGH 85000 /* 85C */
+#define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */
+#define MLXSW_THERMAL_ASIC_TEMP_CRIT 110000 /* 110C */
+#define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
+#define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
+#define MLXSW_THERMAL_ZONE_MAX_NAME 16
#define MLXSW_THERMAL_MAX_STATE 10
#define MLXSW_THERMAL_MAX_DUTY 255
/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
@@ -26,9 +35,22 @@
#define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2)
#define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */
+/* External cooling devices, allowed for binding to mlxsw thermal zones. */
+static char * const mlxsw_thermal_external_allowed_cdev[] = {
+ "mlxreg_fan",
+};
+
+enum mlxsw_thermal_trips {
+ MLXSW_THERMAL_TEMP_TRIP_NORM,
+ MLXSW_THERMAL_TEMP_TRIP_HIGH,
+ MLXSW_THERMAL_TEMP_TRIP_HOT,
+ MLXSW_THERMAL_TEMP_TRIP_CRIT,
+};
+
struct mlxsw_thermal_trip {
int type;
int temp;
+ int hyst;
int min_state;
int max_state;
};
@@ -36,32 +58,29 @@ struct mlxsw_thermal_trip {
static const struct mlxsw_thermal_trip default_thermal_trips[] = {
{ /* In range - 0-40% PWM */
.type = THERMAL_TRIP_ACTIVE,
- .temp = 75000,
+ .temp = MLXSW_THERMAL_ASIC_TEMP_NORM,
+ .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
.min_state = 0,
.max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
},
- { /* High - 40-100% PWM */
- .type = THERMAL_TRIP_ACTIVE,
- .temp = 80000,
- .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
- .max_state = MLXSW_THERMAL_MAX_STATE,
- },
{
- /* Very high - 100% PWM */
+ /* In range - 40-100% PWM */
.type = THERMAL_TRIP_ACTIVE,
- .temp = 85000,
- .min_state = MLXSW_THERMAL_MAX_STATE,
+ .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH,
+ .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
+ .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
.max_state = MLXSW_THERMAL_MAX_STATE,
},
{ /* Warning */
.type = THERMAL_TRIP_HOT,
- .temp = 105000,
+ .temp = MLXSW_THERMAL_ASIC_TEMP_HOT,
+ .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
.min_state = MLXSW_THERMAL_MAX_STATE,
.max_state = MLXSW_THERMAL_MAX_STATE,
},
{ /* Critical - soft poweroff */
.type = THERMAL_TRIP_CRITICAL,
- .temp = MLXSW_THERMAL_MAX_TEMP,
+ .temp = MLXSW_THERMAL_ASIC_TEMP_CRIT,
.min_state = MLXSW_THERMAL_MAX_STATE,
.max_state = MLXSW_THERMAL_MAX_STATE,
}
@@ -72,14 +91,27 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = {
/* Make sure all trips are writable */
#define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
+struct mlxsw_thermal;
+
+struct mlxsw_thermal_module {
+ struct mlxsw_thermal *parent;
+ struct thermal_zone_device *tzdev;
+ struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
+ enum thermal_device_mode mode;
+ int module;
+};
+
struct mlxsw_thermal {
struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info;
struct thermal_zone_device *tzdev;
+ int polling_delay;
struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
enum thermal_device_mode mode;
+ struct mlxsw_thermal_module *tz_module_arr;
+ unsigned int tz_module_num;
};
static inline u8 mlxsw_state_to_duty(int state)
@@ -103,9 +135,67 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
if (thermal->cdevs[i] == cdev)
return i;
+ /* Allow mlxsw thermal zone binding to an external cooling device */
+ for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
+ if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
+ sizeof(cdev->type)))
+ return 0;
+ }
+
return -ENODEV;
}
+static void
+mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
+{
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0;
+}
+
+static int
+mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
+ struct mlxsw_thermal_module *tz)
+{
+ int crit_temp, emerg_temp;
+ int err;
+
+ err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
+ SFP_TEMP_HIGH_WARN,
+ &crit_temp);
+ if (err)
+ return err;
+
+ err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
+ SFP_TEMP_HIGH_ALARM,
+ &emerg_temp);
+ if (err)
+ return err;
+
+ /* According to the system thermal requirements, the thermal zones are
+ * defined with four trip points. The critical and emergency
+ * temperature thresholds, provided by QSFP module are set as "active"
+ * and "hot" trip points, "normal" and "critical" trip points are
+ * derived from "active" and "hot" by subtracting or adding double
+ * hysteresis value.
+ */
+ if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
+ MLXSW_THERMAL_MODULE_TEMP_SHIFT;
+ else
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
+ if (emerg_temp > crit_temp)
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
+ MLXSW_THERMAL_MODULE_TEMP_SHIFT;
+ else
+ tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
+
+ return 0;
+}
+
static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
struct thermal_cooling_device *cdev)
{
@@ -172,7 +262,7 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
mutex_lock(&tzdev->lock);
if (mode == THERMAL_DEVICE_ENABLED)
- tzdev->polling_delay = MLXSW_THERMAL_POLL_INT;
+ tzdev->polling_delay = thermal->polling_delay;
else
tzdev->polling_delay = 0;
@@ -237,13 +327,31 @@ static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
struct mlxsw_thermal *thermal = tzdev->devdata;
if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
- temp > MLXSW_THERMAL_MAX_TEMP)
+ temp > MLXSW_THERMAL_ASIC_TEMP_CRIT)
return -EINVAL;
thermal->trips[trip].temp = temp;
return 0;
}
+static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
+ int trip, int *p_hyst)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ *p_hyst = thermal->trips[trip].hyst;
+ return 0;
+}
+
+static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
+ int trip, int hyst)
+{
+ struct mlxsw_thermal *thermal = tzdev->devdata;
+
+ thermal->trips[trip].hyst = hyst;
+ return 0;
+}
+
static struct thermal_zone_device_ops mlxsw_thermal_ops = {
.bind = mlxsw_thermal_bind,
.unbind = mlxsw_thermal_unbind,
@@ -253,6 +361,206 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
.get_trip_type = mlxsw_thermal_get_trip_type,
.get_trip_temp = mlxsw_thermal_get_trip_temp,
.set_trip_temp = mlxsw_thermal_set_trip_temp,
+ .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
+ .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
+};
+
+static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
+ struct thermal_cooling_device *cdev)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+ int i, j, err;
+
+ /* If the cooling device is one of ours bind it */
+ if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+ return 0;
+
+ for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+ const struct mlxsw_thermal_trip *trip = &tz->trips[i];
+
+ err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
+ trip->max_state,
+ trip->min_state,
+ THERMAL_WEIGHT_DEFAULT);
+ if (err < 0)
+ goto err_bind_cooling_device;
+ }
+ return 0;
+
+err_bind_cooling_device:
+ for (j = i - 1; j >= 0; j--)
+ thermal_zone_unbind_cooling_device(tzdev, j, cdev);
+ return err;
+}
+
+static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
+ struct thermal_cooling_device *cdev)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+ int i;
+ int err;
+
+ /* If the cooling device is one of ours unbind it */
+ if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+ return 0;
+
+ for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+ err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
+ WARN_ON(err);
+ }
+ return err;
+}
+
+static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
+ enum thermal_device_mode *mode)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ *mode = tz->mode;
+
+ return 0;
+}
+
+static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
+ enum thermal_device_mode mode)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+
+ mutex_lock(&tzdev->lock);
+
+ if (mode == THERMAL_DEVICE_ENABLED)
+ tzdev->polling_delay = thermal->polling_delay;
+ else
+ tzdev->polling_delay = 0;
+
+ mutex_unlock(&tzdev->lock);
+
+ tz->mode = mode;
+ thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
+
+ return 0;
+}
+
+static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
+ int *p_temp)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+ struct device *dev = thermal->bus_info->dev;
+ char mtbr_pl[MLXSW_REG_MTBR_LEN];
+ u16 temp;
+ int err;
+
+ /* Read module temperature. */
+ mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX +
+ tz->module, 1);
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtbr), mtbr_pl);
+ if (err)
+ return err;
+
+ mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
+ /* Update temperature. */
+ switch (temp) {
+ case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+ case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+ case MLXSW_REG_MTBR_INDEX_NA: /* fall-through */
+ case MLXSW_REG_MTBR_BAD_SENS_INFO:
+ temp = 0;
+ break;
+ default:
+ temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
+ /* Reset all trip point. */
+ mlxsw_thermal_module_trips_reset(tz);
+ /* Update trip points. */
+ err = mlxsw_thermal_module_trips_update(dev, thermal->core,
+ tz);
+ if (err)
+ return err;
+ break;
+ }
+
+ *p_temp = (int) temp;
+ return 0;
+}
+
+static int
+mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
+ enum thermal_trip_type *p_type)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+ return -EINVAL;
+
+ *p_type = tz->trips[trip].type;
+ return 0;
+}
+
+static int
+mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
+ int trip, int *p_temp)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+ return -EINVAL;
+
+ *p_temp = tz->trips[trip].temp;
+ return 0;
+}
+
+static int
+mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
+ int trip, int temp)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
+ temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp)
+ return -EINVAL;
+
+ tz->trips[trip].temp = temp;
+ return 0;
+}
+
+static int
+mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
+ int *p_hyst)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ *p_hyst = tz->trips[trip].hyst;
+ return 0;
+}
+
+static int
+mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
+ int hyst)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+
+ tz->trips[trip].hyst = hyst;
+ return 0;
+}
+
+static struct thermal_zone_params mlxsw_thermal_module_params = {
+ .governor_name = "user_space",
+};
+
+static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
+ .bind = mlxsw_thermal_module_bind,
+ .unbind = mlxsw_thermal_module_unbind,
+ .get_mode = mlxsw_thermal_module_mode_get,
+ .set_mode = mlxsw_thermal_module_mode_set,
+ .get_temp = mlxsw_thermal_module_temp_get,
+ .get_trip_type = mlxsw_thermal_module_trip_type_get,
+ .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
+ .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
+ .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
+ .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
};
static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
@@ -355,6 +663,123 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
.set_cur_state = mlxsw_thermal_set_cur_state,
};
+static int
+mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
+{
+ char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
+ int err;
+
+ snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
+ module_tz->module + 1);
+ module_tz->tzdev = thermal_zone_device_register(tz_name,
+ MLXSW_THERMAL_NUM_TRIPS,
+ MLXSW_THERMAL_TRIP_MASK,
+ module_tz,
+ &mlxsw_thermal_module_ops,
+ &mlxsw_thermal_module_params,
+ 0, 0);
+ if (IS_ERR(module_tz->tzdev)) {
+ err = PTR_ERR(module_tz->tzdev);
+ return err;
+ }
+
+ return 0;
+}
+
+static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
+{
+ thermal_zone_device_unregister(tzdev);
+}
+
+static int
+mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
+ struct mlxsw_thermal *thermal, u8 local_port)
+{
+ struct mlxsw_thermal_module *module_tz;
+ char pmlp_pl[MLXSW_REG_PMLP_LEN];
+ u8 width, module;
+ int err;
+
+ mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+ err = mlxsw_reg_query(core, MLXSW_REG(pmlp), pmlp_pl);
+ if (err)
+ return err;
+
+ width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+ if (!width)
+ return 0;
+
+ module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+ module_tz = &thermal->tz_module_arr[module];
+ module_tz->module = module;
+ module_tz->parent = thermal;
+ memcpy(module_tz->trips, default_thermal_trips,
+ sizeof(thermal->trips));
+ /* Initialize all trip point. */
+ mlxsw_thermal_module_trips_reset(module_tz);
+ /* Update trip point according to the module data. */
+ err = mlxsw_thermal_module_trips_update(dev, core, module_tz);
+ if (err)
+ return err;
+
+ thermal->tz_module_num++;
+
+ return 0;
+}
+
+static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
+{
+ if (module_tz && module_tz->tzdev) {
+ mlxsw_thermal_module_tz_fini(module_tz->tzdev);
+ module_tz->tzdev = NULL;
+ }
+}
+
+static int
+mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
+ struct mlxsw_thermal *thermal)
+{
+ unsigned int module_count = mlxsw_core_max_ports(core);
+ int i, err;
+
+ thermal->tz_module_arr = kcalloc(module_count,
+ sizeof(*thermal->tz_module_arr),
+ GFP_KERNEL);
+ if (!thermal->tz_module_arr)
+ return -ENOMEM;
+
+ for (i = 1; i < module_count; i++) {
+ err = mlxsw_thermal_module_init(dev, core, thermal, i);
+ if (err)
+ goto err_unreg_tz_module_arr;
+ }
+
+ for (i = 0; i < thermal->tz_module_num; i++) {
+ err = mlxsw_thermal_module_tz_init(&thermal->tz_module_arr[i]);
+ if (err)
+ goto err_unreg_tz_module_arr;
+ }
+
+ return 0;
+
+err_unreg_tz_module_arr:
+ for (i = module_count - 1; i >= 0; i--)
+ mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
+ kfree(thermal->tz_module_arr);
+ return err;
+}
+
+static void
+mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
+{
+ unsigned int module_count = mlxsw_core_max_ports(thermal->core);
+ int i;
+
+ for (i = module_count - 1; i >= 0; i--)
+ mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
+ kfree(thermal->tz_module_arr);
+}
+
int mlxsw_thermal_init(struct mlxsw_core *core,
const struct mlxsw_bus_info *bus_info,
struct mlxsw_thermal **p_thermal)
@@ -407,8 +832,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
if (pwm_active & BIT(i)) {
struct thermal_cooling_device *cdev;
- cdev = thermal_cooling_device_register("Fan", thermal,
- &mlxsw_cooling_ops);
+ cdev = thermal_cooling_device_register("mlxsw_fan",
+ thermal,
+ &mlxsw_cooling_ops);
if (IS_ERR(cdev)) {
err = PTR_ERR(cdev);
dev_err(dev, "Failed to register cooling device\n");
@@ -423,22 +849,36 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
i);
+ thermal->polling_delay = bus_info->low_frequency ?
+ MLXSW_THERMAL_SLOW_POLL_INT :
+ MLXSW_THERMAL_POLL_INT;
+
thermal->tzdev = thermal_zone_device_register("mlxsw",
MLXSW_THERMAL_NUM_TRIPS,
MLXSW_THERMAL_TRIP_MASK,
thermal,
&mlxsw_thermal_ops,
NULL, 0,
- MLXSW_THERMAL_POLL_INT);
+ thermal->polling_delay);
if (IS_ERR(thermal->tzdev)) {
err = PTR_ERR(thermal->tzdev);
dev_err(dev, "Failed to register thermal zone\n");
goto err_unreg_cdevs;
}
+ err = mlxsw_thermal_modules_init(dev, core, thermal);
+ if (err)
+ goto err_unreg_tzdev;
+
thermal->mode = THERMAL_DEVICE_ENABLED;
*p_thermal = thermal;
return 0;
+
+err_unreg_tzdev:
+ if (thermal->tzdev) {
+ thermal_zone_device_unregister(thermal->tzdev);
+ thermal->tzdev = NULL;
+ }
err_unreg_cdevs:
for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
if (thermal->cdevs[i])
@@ -452,6 +892,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
{
int i;
+ mlxsw_thermal_modules_fini(thermal);
if (thermal->tzdev) {
thermal_zone_device_unregister(thermal->tzdev);
thermal->tzdev = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index 798bd5aca384..06aea1999518 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -14,14 +14,17 @@
#include "cmd.h"
#include "core.h"
#include "i2c.h"
+#include "resources.h"
#define MLXSW_I2C_CIR2_BASE 0x72000
#define MLXSW_I2C_CIR_STATUS_OFF 0x18
#define MLXSW_I2C_CIR2_OFF_STATUS (MLXSW_I2C_CIR2_BASE + \
MLXSW_I2C_CIR_STATUS_OFF)
#define MLXSW_I2C_OPMOD_SHIFT 12
+#define MLXSW_I2C_EVENT_BIT_SHIFT 22
#define MLXSW_I2C_GO_BIT_SHIFT 23
#define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT 24
+#define MLXSW_I2C_EVENT_BIT BIT(MLXSW_I2C_EVENT_BIT_SHIFT)
#define MLXSW_I2C_GO_BIT BIT(MLXSW_I2C_GO_BIT_SHIFT)
#define MLXSW_I2C_GO_OPMODE BIT(MLXSW_I2C_OPMOD_SHIFT)
#define MLXSW_I2C_SET_IMM_CMD (MLXSW_I2C_GO_OPMODE | \
@@ -33,6 +36,9 @@
#define MLXSW_I2C_TLV_HDR_SIZE 0x10
#define MLXSW_I2C_ADDR_WIDTH 4
#define MLXSW_I2C_PUSH_CMD_SIZE (MLXSW_I2C_ADDR_WIDTH + 4)
+#define MLXSW_I2C_SET_EVENT_CMD (MLXSW_I2C_EVENT_BIT)
+#define MLXSW_I2C_PUSH_EVENT_CMD (MLXSW_I2C_GO_BIT | \
+ MLXSW_I2C_SET_EVENT_CMD)
#define MLXSW_I2C_READ_SEMA_SIZE 4
#define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28)
#define MLXSW_I2C_MBOX_SIZE 20
@@ -44,6 +50,7 @@
#define MLXSW_I2C_BLK_MAX 32
#define MLXSW_I2C_RETRY 5
#define MLXSW_I2C_TIMEOUT_MSECS 5000
+#define MLXSW_I2C_MAX_DATA_SIZE 256
/**
* struct mlxsw_i2c - device private data:
@@ -167,7 +174,7 @@ static int mlxsw_i2c_wait_go_bit(struct i2c_client *client,
return err > 0 ? 0 : err;
}
-/* Routine posts a command to ASIC though mail box. */
+/* Routine posts a command to ASIC through mail box. */
static int mlxsw_i2c_write_cmd(struct i2c_client *client,
struct mlxsw_i2c *mlxsw_i2c,
int immediate)
@@ -213,6 +220,66 @@ static int mlxsw_i2c_write_cmd(struct i2c_client *client,
return 0;
}
+/* Routine posts initialization command to ASIC through mail box. */
+static int
+mlxsw_i2c_write_init_cmd(struct i2c_client *client,
+ struct mlxsw_i2c *mlxsw_i2c, u16 opcode, u32 in_mod)
+{
+ __be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = {
+ 0, cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD)
+ };
+ __be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = {
+ 0, 0, 0, 0, 0, 0,
+ cpu_to_be32(client->adapter->nr & 0xffff),
+ cpu_to_be32(MLXSW_I2C_SET_EVENT_CMD)
+ };
+ struct i2c_msg push_cmd =
+ MLXSW_I2C_WRITE_MSG(client, push_cmd_buf,
+ MLXSW_I2C_PUSH_CMD_SIZE);
+ struct i2c_msg prep_cmd =
+ MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE);
+ u8 status;
+ int err;
+
+ push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD | opcode);
+ prep_cmd_buf[3] = cpu_to_be32(in_mod);
+ prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_GO_BIT | opcode);
+ mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf,
+ MLXSW_I2C_CIR2_BASE);
+ mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf,
+ MLXSW_I2C_CIR2_OFF_STATUS);
+
+ /* Prepare Command Interface Register for transaction */
+ err = i2c_transfer(client->adapter, &prep_cmd, 1);
+ if (err < 0)
+ return err;
+ else if (err != 1)
+ return -EIO;
+
+ /* Write out Command Interface Register GO bit to push transaction */
+ err = i2c_transfer(client->adapter, &push_cmd, 1);
+ if (err < 0)
+ return err;
+ else if (err != 1)
+ return -EIO;
+
+ /* Wait until go bit is cleared. */
+ err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status);
+ if (err) {
+ dev_err(&client->dev, "HW semaphore is not released");
+ return err;
+ }
+
+ /* Validate transaction completion status. */
+ if (status) {
+ dev_err(&client->dev, "Bad transaction completion status %x\n",
+ status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
/* Routine obtains mail box offsets from ASIC register space. */
static int mlxsw_i2c_get_mbox(struct i2c_client *client,
struct mlxsw_i2c *mlxsw_i2c)
@@ -310,8 +377,8 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
/* Routine executes I2C command. */
static int
-mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
- size_t out_mbox_size, u8 *out_mbox, u8 *status)
+mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
+ u8 *in_mbox, size_t out_mbox_size, u8 *out_mbox, u8 *status)
{
struct i2c_client *client = to_i2c_client(dev);
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
@@ -326,24 +393,40 @@ mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32));
- reg_size = mlxsw_i2c_get_reg_size(in_mbox);
- num = reg_size / MLXSW_I2C_BLK_MAX;
- if (reg_size % MLXSW_I2C_BLK_MAX)
- num++;
+ if (in_mbox) {
+ reg_size = mlxsw_i2c_get_reg_size(in_mbox);
+ num = reg_size / MLXSW_I2C_BLK_MAX;
+ if (reg_size % MLXSW_I2C_BLK_MAX)
+ num++;
- if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
- dev_err(&client->dev, "Could not acquire lock");
- return -EINVAL;
- }
+ if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
+ dev_err(&client->dev, "Could not acquire lock");
+ return -EINVAL;
+ }
+
+ err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
+ if (err)
+ goto cmd_fail;
+
+ /* No out mailbox is case of write transaction. */
+ if (!out_mbox) {
+ mutex_unlock(&mlxsw_i2c->cmd.lock);
+ return 0;
+ }
+ } else {
+ /* No input mailbox is case of initialization query command. */
+ reg_size = MLXSW_I2C_MAX_DATA_SIZE;
+ num = reg_size / MLXSW_I2C_BLK_MAX;
- err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
- if (err)
- goto cmd_fail;
+ if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
+ dev_err(&client->dev, "Could not acquire lock");
+ return -EINVAL;
+ }
- /* No out mailbox is case of write transaction. */
- if (!out_mbox) {
- mutex_unlock(&mlxsw_i2c->cmd.lock);
- return 0;
+ err = mlxsw_i2c_write_init_cmd(client, mlxsw_i2c, opcode,
+ in_mod);
+ if (err)
+ goto cmd_fail;
}
/* Send read transaction to get output mailbox content. */
@@ -395,8 +478,8 @@ static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
{
struct mlxsw_i2c *mlxsw_i2c = bus_priv;
- return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox,
- out_mbox_size, out_mbox, status);
+ return mlxsw_i2c_cmd(mlxsw_i2c->dev, opcode, in_mod, in_mbox_size,
+ in_mbox, out_mbox_size, out_mbox, status);
}
static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv,
@@ -414,13 +497,22 @@ static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb,
static int
mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
const struct mlxsw_config_profile *profile,
- struct mlxsw_res *resources)
+ struct mlxsw_res *res)
{
struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+ char *mbox;
+ int err;
mlxsw_i2c->core = mlxsw_core;
- return 0;
+ mbox = mlxsw_cmd_mbox_alloc();
+ if (!mbox)
+ return -ENOMEM;
+
+ err = mlxsw_core_resources_query(mlxsw_core, mbox, res);
+
+ mlxsw_cmd_mbox_free(mbox);
+ return err;
}
static void mlxsw_i2c_fini(void *bus_priv)
@@ -503,6 +595,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
mlxsw_i2c->bus_info.device_kind = id->name;
mlxsw_i2c->bus_info.device_name = client->name;
mlxsw_i2c->bus_info.dev = &client->dev;
+ mlxsw_i2c->bus_info.low_frequency = true;
mlxsw_i2c->dev = &client->dev;
err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
index 5a6c4457fb55..68bee9572a1b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
-/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
+/* Copyright (c) 2016-2019 Mellanox Technologies. All rights reserved */
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -8,59 +11,377 @@
#include <linux/types.h>
#include "core.h"
+#include "core_env.h"
#include "i2c.h"
-static const char mlxsw_minimal_driver_name[] = "mlxsw_minimal";
+static const char mlxsw_m_driver_name[] = "mlxsw_minimal";
-static const struct mlxsw_config_profile mlxsw_minimal_config_profile;
+struct mlxsw_m_port;
-static struct mlxsw_driver mlxsw_minimal_driver = {
- .kind = mlxsw_minimal_driver_name,
- .priv_size = 1,
- .profile = &mlxsw_minimal_config_profile,
+struct mlxsw_m {
+ struct mlxsw_m_port **ports;
+ int *module_to_port;
+ struct mlxsw_core *core;
+ const struct mlxsw_bus_info *bus_info;
+ u8 base_mac[ETH_ALEN];
+ u8 max_ports;
};
-static const struct i2c_device_id mlxsw_minimal_i2c_id[] = {
+struct mlxsw_m_port {
+ struct net_device *dev;
+ struct mlxsw_m *mlxsw_m;
+ u8 local_port;
+ u8 module;
+};
+
+static int mlxsw_m_port_dummy_open_stop(struct net_device *dev)
+{
+ return 0;
+}
+
+static int
+mlxsw_m_port_get_phys_port_name(struct net_device *dev, char *name, size_t len)
+{
+ struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
+ struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
+ u8 local_port = mlxsw_m_port->local_port;
+
+ return mlxsw_core_port_get_phys_port_name(core, local_port, name, len);
+}
+
+static int mlxsw_m_port_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
+ struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
+
+ ppid->id_len = sizeof(mlxsw_m->base_mac);
+ memcpy(&ppid->id, &mlxsw_m->base_mac, ppid->id_len);
+
+ return 0;
+}
+
+static const struct net_device_ops mlxsw_m_port_netdev_ops = {
+ .ndo_open = mlxsw_m_port_dummy_open_stop,
+ .ndo_stop = mlxsw_m_port_dummy_open_stop,
+ .ndo_get_phys_port_name = mlxsw_m_port_get_phys_port_name,
+ .ndo_get_port_parent_id = mlxsw_m_port_get_port_parent_id,
+};
+
+static int mlxsw_m_get_module_info(struct net_device *netdev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
+ struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
+
+ return mlxsw_env_get_module_info(core, mlxsw_m_port->module, modinfo);
+}
+
+static int
+mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee,
+ u8 *data)
+{
+ struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
+ struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
+
+ return mlxsw_env_get_module_eeprom(netdev, core, mlxsw_m_port->module,
+ ee, data);
+}
+
+static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
+ .get_module_info = mlxsw_m_get_module_info,
+ .get_module_eeprom = mlxsw_m_get_module_eeprom,
+};
+
+static int
+mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u8 local_port,
+ u8 *p_module, u8 *p_width)
+{
+ char pmlp_pl[MLXSW_REG_PMLP_LEN];
+ int err;
+
+ mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+ err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(pmlp), pmlp_pl);
+ if (err)
+ return err;
+ *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+ *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+
+ return 0;
+}
+
+static int
+mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
+{
+ struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
+ struct net_device *dev = mlxsw_m_port->dev;
+ char ppad_pl[MLXSW_REG_PPAD_LEN];
+ int err;
+
+ mlxsw_reg_ppad_pack(ppad_pl, false, 0);
+ err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(ppad), ppad_pl);
+ if (err)
+ return err;
+ mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, dev->dev_addr);
+ /* The last byte value in base mac address is guaranteed
+ * to be such it does not overflow when adding local_port
+ * value.
+ */
+ dev->dev_addr[ETH_ALEN - 1] += mlxsw_m_port->module + 1;
+ return 0;
+}
+
+static int
+mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module)
+{
+ struct mlxsw_m_port *mlxsw_m_port;
+ struct net_device *dev;
+ int err;
+
+ err = mlxsw_core_port_init(mlxsw_m->core, local_port);
+ if (err) {
+ dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to init core port\n",
+ local_port);
+ return err;
+ }
+
+ dev = alloc_etherdev(sizeof(struct mlxsw_m_port));
+ if (!dev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ SET_NETDEV_DEV(dev, mlxsw_m->bus_info->dev);
+ mlxsw_m_port = netdev_priv(dev);
+ mlxsw_m_port->dev = dev;
+ mlxsw_m_port->mlxsw_m = mlxsw_m;
+ mlxsw_m_port->local_port = local_port;
+ mlxsw_m_port->module = module;
+
+ dev->netdev_ops = &mlxsw_m_port_netdev_ops;
+ dev->ethtool_ops = &mlxsw_m_port_ethtool_ops;
+
+ err = mlxsw_m_port_dev_addr_get(mlxsw_m_port);
+ if (err) {
+ dev_err(mlxsw_m->bus_info->dev, "Port %d: Unable to get port mac address\n",
+ mlxsw_m_port->local_port);
+ goto err_dev_addr_get;
+ }
+
+ netif_carrier_off(dev);
+ mlxsw_m->ports[local_port] = mlxsw_m_port;
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to register netdev\n",
+ mlxsw_m_port->local_port);
+ goto err_register_netdev;
+ }
+
+ mlxsw_core_port_eth_set(mlxsw_m->core, mlxsw_m_port->local_port,
+ mlxsw_m_port, dev, module + 1, false, 0);
+
+ return 0;
+
+err_register_netdev:
+ mlxsw_m->ports[local_port] = NULL;
+ free_netdev(dev);
+err_dev_addr_get:
+err_alloc_etherdev:
+ mlxsw_core_port_fini(mlxsw_m->core, local_port);
+ return err;
+}
+
+static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 local_port)
+{
+ struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port];
+
+ mlxsw_core_port_clear(mlxsw_m->core, local_port, mlxsw_m);
+ unregister_netdev(mlxsw_m_port->dev); /* This calls ndo_stop */
+ mlxsw_m->ports[local_port] = NULL;
+ free_netdev(mlxsw_m_port->dev);
+ mlxsw_core_port_fini(mlxsw_m->core, local_port);
+}
+
+static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
+ u8 *last_module)
+{
+ u8 module, width;
+ int err;
+
+ /* Fill out to local port mapping array */
+ err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module,
+ &width);
+ if (err)
+ return err;
+
+ if (!width)
+ return 0;
+ /* Skip, if port belongs to the cluster */
+ if (module == *last_module)
+ return 0;
+ *last_module = module;
+ mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
+
+ return 0;
+}
+
+static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module)
+{
+ mlxsw_m->module_to_port[module] = -1;
+}
+
+static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
+{
+ unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
+ u8 last_module = max_ports;
+ int i;
+ int err;
+
+ mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports),
+ GFP_KERNEL);
+ if (!mlxsw_m->ports)
+ return -ENOMEM;
+
+ mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int),
+ GFP_KERNEL);
+ if (!mlxsw_m->module_to_port) {
+ err = -ENOMEM;
+ goto err_module_to_port_alloc;
+ }
+
+ /* Invalidate the entries of module to local port mapping array */
+ for (i = 0; i < max_ports; i++)
+ mlxsw_m->module_to_port[i] = -1;
+
+ /* Fill out module to local port mapping array */
+ for (i = 1; i < max_ports; i++) {
+ err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module);
+ if (err)
+ goto err_module_to_port_map;
+ }
+
+ /* Create port objects for each valid entry */
+ for (i = 0; i < mlxsw_m->max_ports; i++) {
+ if (mlxsw_m->module_to_port[i] > 0) {
+ err = mlxsw_m_port_create(mlxsw_m,
+ mlxsw_m->module_to_port[i],
+ i);
+ if (err)
+ goto err_module_to_port_create;
+ }
+ }
+
+ return 0;
+
+err_module_to_port_create:
+ for (i--; i >= 0; i--) {
+ if (mlxsw_m->module_to_port[i] > 0)
+ mlxsw_m_port_remove(mlxsw_m,
+ mlxsw_m->module_to_port[i]);
+ }
+ i = max_ports;
+err_module_to_port_map:
+ for (i--; i > 0; i--)
+ mlxsw_m_port_module_unmap(mlxsw_m, i);
+ kfree(mlxsw_m->module_to_port);
+err_module_to_port_alloc:
+ kfree(mlxsw_m->ports);
+ return err;
+}
+
+static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
+{
+ int i;
+
+ for (i = 0; i < mlxsw_m->max_ports; i++) {
+ if (mlxsw_m->module_to_port[i] > 0) {
+ mlxsw_m_port_remove(mlxsw_m,
+ mlxsw_m->module_to_port[i]);
+ mlxsw_m_port_module_unmap(mlxsw_m, i);
+ }
+ }
+
+ kfree(mlxsw_m->module_to_port);
+ kfree(mlxsw_m->ports);
+}
+
+static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
+ const struct mlxsw_bus_info *mlxsw_bus_info)
+{
+ struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
+ int err;
+
+ mlxsw_m->core = mlxsw_core;
+ mlxsw_m->bus_info = mlxsw_bus_info;
+
+ err = mlxsw_m_ports_create(mlxsw_m);
+ if (err) {
+ dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core)
+{
+ struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
+
+ mlxsw_m_ports_remove(mlxsw_m);
+}
+
+static const struct mlxsw_config_profile mlxsw_m_config_profile;
+
+static struct mlxsw_driver mlxsw_m_driver = {
+ .kind = mlxsw_m_driver_name,
+ .priv_size = sizeof(struct mlxsw_m),
+ .init = mlxsw_m_init,
+ .fini = mlxsw_m_fini,
+ .profile = &mlxsw_m_config_profile,
+ .res_query_enabled = true,
+};
+
+static const struct i2c_device_id mlxsw_m_i2c_id[] = {
{ "mlxsw_minimal", 0},
{ },
};
-static struct i2c_driver mlxsw_minimal_i2c_driver = {
+static struct i2c_driver mlxsw_m_i2c_driver = {
.driver.name = "mlxsw_minimal",
.class = I2C_CLASS_HWMON,
- .id_table = mlxsw_minimal_i2c_id,
+ .id_table = mlxsw_m_i2c_id,
};
-static int __init mlxsw_minimal_module_init(void)
+static int __init mlxsw_m_module_init(void)
{
int err;
- err = mlxsw_core_driver_register(&mlxsw_minimal_driver);
+ err = mlxsw_core_driver_register(&mlxsw_m_driver);
if (err)
return err;
- err = mlxsw_i2c_driver_register(&mlxsw_minimal_i2c_driver);
+ err = mlxsw_i2c_driver_register(&mlxsw_m_i2c_driver);
if (err)
goto err_i2c_driver_register;
return 0;
err_i2c_driver_register:
- mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+ mlxsw_core_driver_unregister(&mlxsw_m_driver);
return err;
}
-static void __exit mlxsw_minimal_module_exit(void)
+static void __exit mlxsw_m_module_exit(void)
{
- mlxsw_i2c_driver_unregister(&mlxsw_minimal_i2c_driver);
- mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+ mlxsw_i2c_driver_unregister(&mlxsw_m_i2c_driver);
+ mlxsw_core_driver_unregister(&mlxsw_m_driver);
}
-module_init(mlxsw_minimal_module_init);
-module_exit(mlxsw_minimal_module_exit);
+module_init(mlxsw_m_module_init);
+module_exit(mlxsw_m_module_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
MODULE_DESCRIPTION("Mellanox minimal driver");
-MODULE_DEVICE_TABLE(i2c, mlxsw_minimal_i2c_id);
+MODULE_DEVICE_TABLE(i2c, mlxsw_m_i2c_id);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 66b8098c6fd2..b40455f8293d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
+ char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
+
+ memcpy(ncqe, cqe, q->elem_size);
+ mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
if (sendq) {
struct mlxsw_pci_queue *sdq;
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
- wqe_counter, cqe);
+ wqe_counter, ncqe);
q->u.cq.comp_sdq_count++;
} else {
struct mlxsw_pci_queue *rdq;
rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
- wqe_counter, q->u.cq.v, cqe);
+ wqe_counter, q->u.cq.v, ncqe);
q->u.cq.comp_rdq_count++;
}
if (++items == credits)
break;
}
- if (items) {
- mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
+ if (items)
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
- }
}
static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
@@ -1037,42 +1039,6 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci,
mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask);
}
-static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
- struct mlxsw_res *res)
-{
- int index, i;
- u64 data;
- u16 id;
- int err;
-
- if (!res)
- return 0;
-
- mlxsw_cmd_mbox_zero(mbox);
-
- for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
- index++) {
- err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index);
- if (err)
- return err;
-
- for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
- id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
- data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
-
- if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
- return 0;
-
- mlxsw_res_parse(res, id, data);
- }
- }
-
- /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get
- * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW.
- */
- return -EIO;
-}
-
static int
mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_pci *mlxsw_pci,
const struct mlxsw_config_profile *profile,
@@ -1365,10 +1331,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
- break;
+ return 0;
cond_resched();
} while (time_before(jiffies, end));
- return 0;
+ return -EBUSY;
}
static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
@@ -1457,7 +1423,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
if (err)
goto err_boardinfo;
- err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res);
+ err = mlxsw_core_resources_query(mlxsw_core, mbox, res);
if (err)
goto err_query_resources;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
index bb99f6d41fe0..ffee38e36ce8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
@@ -27,7 +27,7 @@
#define MLXSW_PCI_SW_RESET 0xF0010
#define MLXSW_PCI_SW_RESET_RST_BIT BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 5000
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS 13000
#define MLXSW_PCI_SW_RESET_WAIT_MSECS 100
#define MLXSW_PCI_FW_READY 0xA1844
#define MLXSW_PCI_FW_READY_MASK 0xFFFF
@@ -53,6 +53,7 @@
#define MLXSW_PCI_WQE_SIZE 32 /* 32 bytes per element */
#define MLXSW_PCI_CQE01_SIZE 16 /* 16 bytes per element */
#define MLXSW_PCI_CQE2_SIZE 32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
#define MLXSW_PCI_EQE_SIZE 16 /* 16 bytes per element */
#define MLXSW_PCI_WQE_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
#define MLXSW_PCI_CQE01_COUNT (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 9b48dffc9f63..eb4c5e8964cd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -2199,6 +2199,14 @@ MLXSW_ITEM32(reg, pagt, size, 0x00, 0, 8);
*/
MLXSW_ITEM32(reg, pagt, acl_group_id, 0x08, 0, 16);
+/* reg_pagt_multi
+ * Multi-ACL
+ * 0 - This ACL is the last ACL in the multi-ACL
+ * 1 - This ACL is part of a multi-ACL
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, pagt, multi, 0x30, 31, 1, 0x04, 0x00, false);
+
/* reg_pagt_acl_id
* ACL identifier
* Access: RW
@@ -2212,12 +2220,13 @@ static inline void mlxsw_reg_pagt_pack(char *payload, u16 acl_group_id)
}
static inline void mlxsw_reg_pagt_acl_id_pack(char *payload, int index,
- u16 acl_id)
+ u16 acl_id, bool multi)
{
u8 size = mlxsw_reg_pagt_size_get(payload);
if (index >= size)
mlxsw_reg_pagt_size_set(payload, index + 1);
+ mlxsw_reg_pagt_multi_set(payload, index, multi);
mlxsw_reg_pagt_acl_id_set(payload, index, acl_id);
}
@@ -3962,6 +3971,25 @@ enum {
*/
MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4);
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M BIT(0)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII BIT(1)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII BIT(2)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R BIT(3)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G BIT(4)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G BIT(5)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR BIT(6)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2 BIT(7)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR BIT(8)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4 BIT(9)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2 BIT(10)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4 BIT(12)
+
+/* reg_ptys_ext_eth_proto_cap
+ * Extended Ethernet port supported speeds and protocols.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32);
+
#define MLXSW_REG_PTYS_ETH_SPEED_SGMII BIT(0)
#define MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX BIT(1)
#define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 BIT(2)
@@ -4016,6 +4044,12 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16);
*/
MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16);
+/* reg_ptys_ext_eth_proto_admin
+ * Extended speed and protocol to set port to.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ptys, ext_eth_proto_admin, 0x14, 0, 32);
+
/* reg_ptys_eth_proto_admin
* Speed and protocol to set port to.
* Access: RW
@@ -4034,6 +4068,12 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16);
*/
MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16);
+/* reg_ptys_ext_eth_proto_oper
+ * The extended current speed and protocol configured for the port.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ext_eth_proto_oper, 0x20, 0, 32);
+
/* reg_ptys_eth_proto_oper
* The current speed and protocol configured for the port.
* Access: RO
@@ -4052,12 +4092,23 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16);
*/
MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16);
-/* reg_ptys_eth_proto_lp_advertise
- * The protocols that were advertised by the link partner during
- * autonegotiation.
+enum mlxsw_reg_ptys_connector_type {
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA,
+ MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER,
+};
+
+/* reg_ptys_connector_type
+ * Connector type indication.
* Access: RO
*/
-MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32);
+MLXSW_ITEM32(reg, ptys, connector_type, 0x2C, 0, 4);
static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port,
u32 proto_admin, bool autoneg)
@@ -4069,17 +4120,46 @@ static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port,
mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg);
}
+static inline void mlxsw_reg_ptys_ext_eth_pack(char *payload, u8 local_port,
+ u32 proto_admin, bool autoneg)
+{
+ MLXSW_REG_ZERO(ptys, payload);
+ mlxsw_reg_ptys_local_port_set(payload, local_port);
+ mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_ETH);
+ mlxsw_reg_ptys_ext_eth_proto_admin_set(payload, proto_admin);
+ mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg);
+}
+
static inline void mlxsw_reg_ptys_eth_unpack(char *payload,
u32 *p_eth_proto_cap,
- u32 *p_eth_proto_adm,
+ u32 *p_eth_proto_admin,
u32 *p_eth_proto_oper)
{
if (p_eth_proto_cap)
- *p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload);
- if (p_eth_proto_adm)
- *p_eth_proto_adm = mlxsw_reg_ptys_eth_proto_admin_get(payload);
+ *p_eth_proto_cap =
+ mlxsw_reg_ptys_eth_proto_cap_get(payload);
+ if (p_eth_proto_admin)
+ *p_eth_proto_admin =
+ mlxsw_reg_ptys_eth_proto_admin_get(payload);
+ if (p_eth_proto_oper)
+ *p_eth_proto_oper =
+ mlxsw_reg_ptys_eth_proto_oper_get(payload);
+}
+
+static inline void mlxsw_reg_ptys_ext_eth_unpack(char *payload,
+ u32 *p_eth_proto_cap,
+ u32 *p_eth_proto_admin,
+ u32 *p_eth_proto_oper)
+{
+ if (p_eth_proto_cap)
+ *p_eth_proto_cap =
+ mlxsw_reg_ptys_ext_eth_proto_cap_get(payload);
+ if (p_eth_proto_admin)
+ *p_eth_proto_admin =
+ mlxsw_reg_ptys_ext_eth_proto_admin_get(payload);
if (p_eth_proto_oper)
- *p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload);
+ *p_eth_proto_oper =
+ mlxsw_reg_ptys_ext_eth_proto_oper_get(payload);
}
static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port,
@@ -5666,6 +5746,8 @@ enum mlxsw_reg_ritr_loopback_protocol {
MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV4,
/* IPinIP IPv6 underlay Unicast */
MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV6,
+ /* IPinIP generic - used for Spectrum-2 underlay RIF */
+ MLXSW_REG_RITR_LOOPBACK_GENERIC,
};
/* reg_ritr_loopback_protocol
@@ -5706,6 +5788,13 @@ MLXSW_ITEM32(reg, ritr, loopback_ipip_options, 0x10, 20, 4);
*/
MLXSW_ITEM32(reg, ritr, loopback_ipip_uvr, 0x10, 0, 16);
+/* reg_ritr_loopback_ipip_underlay_rif
+ * Underlay ingress router interface.
+ * Reserved for Spectrum.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ritr, loopback_ipip_underlay_rif, 0x14, 0, 16);
+
/* reg_ritr_loopback_ipip_usip*
* Encapsulation Underlay source IP.
* Access: RW
@@ -5821,11 +5910,12 @@ static inline void
mlxsw_reg_ritr_loopback_ipip_common_pack(char *payload,
enum mlxsw_reg_ritr_loopback_ipip_type ipip_type,
enum mlxsw_reg_ritr_loopback_ipip_options options,
- u16 uvr_id, u32 gre_key)
+ u16 uvr_id, u16 underlay_rif, u32 gre_key)
{
mlxsw_reg_ritr_loopback_ipip_type_set(payload, ipip_type);
mlxsw_reg_ritr_loopback_ipip_options_set(payload, options);
mlxsw_reg_ritr_loopback_ipip_uvr_set(payload, uvr_id);
+ mlxsw_reg_ritr_loopback_ipip_underlay_rif_set(payload, underlay_rif);
mlxsw_reg_ritr_loopback_ipip_gre_key_set(payload, gre_key);
}
@@ -5833,12 +5923,12 @@ static inline void
mlxsw_reg_ritr_loopback_ipip4_pack(char *payload,
enum mlxsw_reg_ritr_loopback_ipip_type ipip_type,
enum mlxsw_reg_ritr_loopback_ipip_options options,
- u16 uvr_id, u32 usip, u32 gre_key)
+ u16 uvr_id, u16 underlay_rif, u32 usip, u32 gre_key)
{
mlxsw_reg_ritr_loopback_protocol_set(payload,
MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV4);
mlxsw_reg_ritr_loopback_ipip_common_pack(payload, ipip_type, options,
- uvr_id, gre_key);
+ uvr_id, underlay_rif, gre_key);
mlxsw_reg_ritr_loopback_ipip_usip4_set(payload, usip);
}
@@ -7200,6 +7290,13 @@ MLXSW_ITEM32(reg, rtdp, type, 0x00, 28, 4);
*/
MLXSW_ITEM32(reg, rtdp, tunnel_index, 0x00, 0, 24);
+/* reg_rtdp_egress_router_interface
+ * Underlay egress router interface.
+ * Valid range is from 0 to cap_max_router_interfaces - 1
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, rtdp, egress_router_interface, 0x40, 0, 16);
+
/* IPinIP */
/* reg_rtdp_ipip_irif
@@ -7849,6 +7946,35 @@ static inline void mlxsw_reg_mfsl_unpack(char *payload, u8 tacho,
*p_tach_max = mlxsw_reg_mfsl_tach_max_get(payload);
}
+/* FORE - Fan Out of Range Event Register
+ * --------------------------------------
+ * This register reports the status of the controlled fans compared to the
+ * range defined by the MFSL register.
+ */
+#define MLXSW_REG_FORE_ID 0x9007
+#define MLXSW_REG_FORE_LEN 0x0C
+
+MLXSW_REG_DEFINE(fore, MLXSW_REG_FORE_ID, MLXSW_REG_FORE_LEN);
+
+/* fan_under_limit
+ * Fan speed is below the low limit defined in MFSL register. Each bit relates
+ * to a single tachometer and indicates the specific tachometer reading is
+ * below the threshold.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, fore, fan_under_limit, 0x00, 16, 10);
+
+static inline void mlxsw_reg_fore_unpack(char *payload, u8 tacho,
+ bool *fault)
+{
+ u16 limit;
+
+ if (fault) {
+ limit = mlxsw_reg_fore_fan_under_limit_get(payload);
+ *fault = limit & BIT(tacho);
+ }
+}
+
/* MTCAP - Management Temperature Capabilities
* -------------------------------------------
* This register exposes the capabilities of the device and
@@ -7975,6 +8101,80 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
mlxsw_reg_mtmp_sensor_name_memcpy_from(payload, sensor_name);
}
+/* MTBR - Management Temperature Bulk Register
+ * -------------------------------------------
+ * This register is used for bulk temperature reading.
+ */
+#define MLXSW_REG_MTBR_ID 0x900F
+#define MLXSW_REG_MTBR_BASE_LEN 0x10 /* base length, without records */
+#define MLXSW_REG_MTBR_REC_LEN 0x04 /* record length */
+#define MLXSW_REG_MTBR_REC_MAX_COUNT 47 /* firmware limitation */
+#define MLXSW_REG_MTBR_LEN (MLXSW_REG_MTBR_BASE_LEN + \
+ MLXSW_REG_MTBR_REC_LEN * \
+ MLXSW_REG_MTBR_REC_MAX_COUNT)
+
+MLXSW_REG_DEFINE(mtbr, MLXSW_REG_MTBR_ID, MLXSW_REG_MTBR_LEN);
+
+/* reg_mtbr_base_sensor_index
+ * Base sensors index to access (0 - ASIC sensor, 1-63 - ambient sensors,
+ * 64-127 are mapped to the SFP+/QSFP modules sequentially).
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mtbr, base_sensor_index, 0x00, 0, 7);
+
+/* reg_mtbr_num_rec
+ * Request: Number of records to read
+ * Response: Number of records read
+ * See above description for more details.
+ * Range 1..255
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtbr, num_rec, 0x04, 0, 8);
+
+/* reg_mtbr_rec_max_temp
+ * The highest measured temperature from the sensor.
+ * When the bit mte is cleared, the field max_temperature is reserved.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtbr, rec_max_temp, MLXSW_REG_MTBR_BASE_LEN, 16,
+ 16, MLXSW_REG_MTBR_REC_LEN, 0x00, false);
+
+/* reg_mtbr_rec_temp
+ * Temperature reading from the sensor. Reading is in 0..125 Celsius
+ * degrees units.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtbr, rec_temp, MLXSW_REG_MTBR_BASE_LEN, 0, 16,
+ MLXSW_REG_MTBR_REC_LEN, 0x00, false);
+
+static inline void mlxsw_reg_mtbr_pack(char *payload, u8 base_sensor_index,
+ u8 num_rec)
+{
+ MLXSW_REG_ZERO(mtbr, payload);
+ mlxsw_reg_mtbr_base_sensor_index_set(payload, base_sensor_index);
+ mlxsw_reg_mtbr_num_rec_set(payload, num_rec);
+}
+
+/* Error codes from temperatute reading */
+enum mlxsw_reg_mtbr_temp_status {
+ MLXSW_REG_MTBR_NO_CONN = 0x8000,
+ MLXSW_REG_MTBR_NO_TEMP_SENS = 0x8001,
+ MLXSW_REG_MTBR_INDEX_NA = 0x8002,
+ MLXSW_REG_MTBR_BAD_SENS_INFO = 0x8003,
+};
+
+/* Base index for reading modules temperature */
+#define MLXSW_REG_MTBR_BASE_MODULE_INDEX 64
+
+static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind,
+ u16 *p_temp, u16 *p_max_temp)
+{
+ if (p_temp)
+ *p_temp = mlxsw_reg_mtbr_rec_temp_get(payload, rec_ind);
+ if (p_max_temp)
+ *p_max_temp = mlxsw_reg_mtbr_rec_max_temp_get(payload, rec_ind);
+}
+
/* MCIA - Management Cable Info Access
* -----------------------------------
* MCIA register is used to access the SFP+ and QSFP connector's EPROM.
@@ -8029,13 +8229,41 @@ MLXSW_ITEM32(reg, mcia, device_address, 0x04, 0, 16);
*/
MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16);
-#define MLXSW_SP_REG_MCIA_EEPROM_SIZE 48
+#define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH 256
+#define MLXSW_REG_MCIA_EEPROM_SIZE 48
+#define MLXSW_REG_MCIA_I2C_ADDR_LOW 0x50
+#define MLXSW_REG_MCIA_I2C_ADDR_HIGH 0x51
+#define MLXSW_REG_MCIA_PAGE0_LO_OFF 0xa0
+#define MLXSW_REG_MCIA_TH_ITEM_SIZE 2
+#define MLXSW_REG_MCIA_TH_PAGE_NUM 3
+#define MLXSW_REG_MCIA_PAGE0_LO 0
+#define MLXSW_REG_MCIA_TH_PAGE_OFF 0x80
+
+enum mlxsw_reg_mcia_eeprom_module_info_rev_id {
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_UNSPC = 0x00,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8436 = 0x01,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636 = 0x03,
+};
+
+enum mlxsw_reg_mcia_eeprom_module_info_id {
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP = 0x03,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP = 0x0C,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS = 0x0D,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 = 0x11,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD = 0x18,
+};
+
+enum mlxsw_reg_mcia_eeprom_module_info {
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID,
+ MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE,
+};
/* reg_mcia_eeprom
* Bytes to read/write.
* Access: RW
*/
-MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_SP_REG_MCIA_EEPROM_SIZE);
+MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE);
static inline void mlxsw_reg_mcia_pack(char *payload, u8 module, u8 lock,
u8 page_number, u16 device_addr,
@@ -9723,8 +9951,10 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(mfsc),
MLXSW_REG(mfsm),
MLXSW_REG(mfsl),
+ MLXSW_REG(fore),
MLXSW_REG(mtcap),
MLXSW_REG(mtmp),
+ MLXSW_REG(mtbr),
MLXSW_REG(mcia),
MLXSW_REG(mpat),
MLXSW_REG(mpar),
diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h
index b8b3a01c2a9e..773ef7fdb285 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/resources.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h
@@ -26,6 +26,7 @@ enum mlxsw_res_id {
MLXSW_RES_ID_MAX_LAG_MEMBERS,
MLXSW_RES_ID_MAX_BUFFER_SIZE,
MLXSW_RES_ID_CELL_SIZE,
+ MLXSW_RES_ID_MAX_HEADROOM_SIZE,
MLXSW_RES_ID_ACL_MAX_TCAM_REGIONS,
MLXSW_RES_ID_ACL_MAX_TCAM_RULES,
MLXSW_RES_ID_ACL_MAX_REGIONS,
@@ -79,6 +80,7 @@ static u16 mlxsw_res_ids[] = {
[MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
[MLXSW_RES_ID_MAX_BUFFER_SIZE] = 0x2802, /* Bytes */
[MLXSW_RES_ID_CELL_SIZE] = 0x2803, /* Bytes */
+ [MLXSW_RES_ID_MAX_HEADROOM_SIZE] = 0x2811, /* Bytes */
[MLXSW_RES_ID_ACL_MAX_TCAM_REGIONS] = 0x2901,
[MLXSW_RES_ID_ACL_MAX_TCAM_RULES] = 0x2902,
[MLXSW_RES_ID_ACL_MAX_REGIONS] = 0x2903,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index eed1045e4d96..9eb63300c1d3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -32,6 +32,7 @@
#include "spectrum.h"
#include "pci.h"
#include "core.h"
+#include "core_env.h"
#include "reg.h"
#include "port.h"
#include "trap.h"
@@ -852,8 +853,12 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
u8 pfc_en = !!my_pfc ? my_pfc->pfc_en : 0;
u16 delay = !!my_pfc ? my_pfc->delay : 0;
char pbmc_pl[MLXSW_REG_PBMC_LEN];
+ u32 taken_headroom_cells = 0;
+ u32 max_headroom_cells;
int i, j, err;
+ max_headroom_cells = mlxsw_sp_sb_max_headroom_cells(mlxsw_sp);
+
mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
if (err)
@@ -862,8 +867,10 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
bool configure = false;
bool pfc = false;
+ u16 thres_cells;
+ u16 delay_cells;
+ u16 total_cells;
bool lossy;
- u16 thres;
for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) {
if (prio_tc[j] == i) {
@@ -877,10 +884,17 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
continue;
lossy = !(pfc || pause_en);
- thres = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
- delay = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, pfc,
- pause_en);
- mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres + delay, thres, lossy);
+ thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+ delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
+ pfc, pause_en);
+ total_cells = thres_cells + delay_cells;
+
+ taken_headroom_cells += total_cells;
+ if (taken_headroom_cells > max_headroom_cells)
+ return -ENOBUFS;
+
+ mlxsw_sp_pg_buf_pack(pbmc_pl, i, total_cells,
+ thres_cells, lossy);
}
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
@@ -1700,6 +1714,18 @@ static int mlxsw_sp_set_features(struct net_device *dev,
mlxsw_sp_feature_hw_tc);
}
+static int mlxsw_sp_port_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+ ppid->id_len = sizeof(mlxsw_sp->base_mac);
+ memcpy(&ppid->id, &mlxsw_sp->base_mac, ppid->id_len);
+
+ return 0;
+}
+
static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
.ndo_open = mlxsw_sp_port_open,
.ndo_stop = mlxsw_sp_port_stop,
@@ -1715,6 +1741,7 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
.ndo_vlan_rx_kill_vid = mlxsw_sp_port_kill_vid,
.ndo_get_phys_port_name = mlxsw_sp_port_get_phys_port_name,
.ndo_set_features = mlxsw_sp_set_features,
+ .ndo_get_port_parent_id = mlxsw_sp_port_get_port_parent_id,
};
static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
@@ -2103,7 +2130,7 @@ static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio)
int i;
for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) {
- snprintf(*p, ETH_GSTRING_LEN, "%s_%d",
+ snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
mlxsw_sp_port_hw_prio_stats[i].str, prio);
*p += ETH_GSTRING_LEN;
}
@@ -2114,7 +2141,7 @@ static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
int i;
for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
- snprintf(*p, ETH_GSTRING_LEN, "%s_%d",
+ snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
mlxsw_sp_port_hw_tc_stats[i].str, tc);
*p += ETH_GSTRING_LEN;
}
@@ -2310,13 +2337,13 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
}
}
-struct mlxsw_sp_port_link_mode {
+struct mlxsw_sp1_port_link_mode {
enum ethtool_link_mode_bit_indices mask_ethtool;
u32 mask;
u32 speed;
};
-static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
+static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
.mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
@@ -2388,11 +2415,6 @@ static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
.speed = SPEED_25000,
},
{
- .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
- .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
- .speed = SPEED_25000,
- },
- {
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
.mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
.speed = SPEED_50000,
@@ -2449,11 +2471,12 @@ static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
},
};
-#define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode)
+#define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
static void
-mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
+mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
+ u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd)
{
if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
@@ -2471,19 +2494,23 @@ mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto,
ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
}
-static void mlxsw_sp_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode)
+static void
+mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
+ unsigned long *mode)
{
int i;
- for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
- if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask)
- __set_bit(mlxsw_sp_port_link_mode[i].mask_ethtool,
+ for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
+ __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
mode);
}
}
-static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
+static void
+mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
+ u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd)
{
u32 speed = SPEED_UNKNOWN;
u8 duplex = DUPLEX_UNKNOWN;
@@ -2492,9 +2519,9 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
if (!carrier_ok)
goto out;
- for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
- if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) {
- speed = mlxsw_sp_port_link_mode[i].speed;
+ for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) {
+ speed = mlxsw_sp1_port_link_mode[i].speed;
duplex = DUPLEX_FULL;
break;
}
@@ -2504,129 +2531,559 @@ out:
cmd->base.duplex = duplex;
}
-static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto)
+static u32
+mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
+ const struct ethtool_link_ksettings *cmd)
{
- if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
- MLXSW_REG_PTYS_ETH_SPEED_SGMII))
- return PORT_FIBRE;
+ u32 ptys_proto = 0;
+ int i;
- if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4))
- return PORT_DA;
+ for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+ if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
+ cmd->link_modes.advertising))
+ ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
+ }
+ return ptys_proto;
+}
- if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4))
- return PORT_NONE;
+static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed)
+{
+ u32 ptys_proto = 0;
+ int i;
- return PORT_OTHER;
+ for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+ if (speed == mlxsw_sp1_port_link_mode[i].speed)
+ ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
+ }
+ return ptys_proto;
}
static u32
-mlxsw_sp_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd)
+mlxsw_sp1_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
{
u32 ptys_proto = 0;
int i;
- for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
- if (test_bit(mlxsw_sp_port_link_mode[i].mask_ethtool,
- cmd->link_modes.advertising))
- ptys_proto |= mlxsw_sp_port_link_mode[i].mask;
+ for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+ if (mlxsw_sp1_port_link_mode[i].speed <= upper_speed)
+ ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
}
return ptys_proto;
}
-static u32 mlxsw_sp_to_ptys_speed(u32 speed)
+static int
+mlxsw_sp1_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ u32 *base_speed)
+{
+ *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
+ return 0;
+}
+
+static void
+mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u8 local_port, u32 proto_admin, bool autoneg)
+{
+ mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg);
+}
+
+static void
+mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
+ u32 *p_eth_proto_oper)
+{
+ mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin,
+ p_eth_proto_oper);
+}
+
+static const struct mlxsw_sp_port_type_speed_ops
+mlxsw_sp1_port_type_speed_ops = {
+ .from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port,
+ .from_ptys_link = mlxsw_sp1_from_ptys_link,
+ .from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex,
+ .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
+ .to_ptys_speed = mlxsw_sp1_to_ptys_speed,
+ .to_ptys_upper_speed = mlxsw_sp1_to_ptys_upper_speed,
+ .port_speed_base = mlxsw_sp1_port_speed_base,
+ .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
+ .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
+};
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_sgmii_100m[] = {
+ ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = {
+ ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii[] = {
+ ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_5gbase_r[] = {
+ ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = {
+ ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = {
+ ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = {
+ ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = {
+ ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = {
+ ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
+ ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = {
+ ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = {
+ ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2)
+
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
+ ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
+ ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
+
+struct mlxsw_sp2_port_link_mode {
+ const enum ethtool_link_mode_bit_indices *mask_ethtool;
+ int m_ethtool_len;
+ u32 mask;
+ u32 speed;
+};
+
+static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_sgmii_100m,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
+ .speed = SPEED_100,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
+ .speed = SPEED_1000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
+ .speed = SPEED_2500,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_5gbase_r,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
+ .speed = SPEED_5000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
+ .speed = SPEED_10000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
+ .speed = SPEED_40000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
+ .speed = SPEED_25000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
+ .speed = SPEED_50000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
+ .speed = SPEED_50000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
+ .speed = SPEED_100000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
+ .speed = SPEED_100000,
+ },
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
+ .speed = SPEED_200000,
+ },
+};
+
+#define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
+
+static void
+mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
+ u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd)
+{
+ ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
+}
+
+static void
+mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
+ unsigned long *mode)
+{
+ int i;
+
+ for (i = 0; i < link_mode->m_ethtool_len; i++)
+ __set_bit(link_mode->mask_ethtool[i], mode);
+}
+
+static void
+mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
+ unsigned long *mode)
+{
+ int i;
+
+ for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
+ mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
+ mode);
+ }
+}
+
+static void
+mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
+ u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd)
+{
+ u32 speed = SPEED_UNKNOWN;
+ u8 duplex = DUPLEX_UNKNOWN;
+ int i;
+
+ if (!carrier_ok)
+ goto out;
+
+ for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+ if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) {
+ speed = mlxsw_sp2_port_link_mode[i].speed;
+ duplex = DUPLEX_FULL;
+ break;
+ }
+ }
+out:
+ cmd->base.speed = speed;
+ cmd->base.duplex = duplex;
+}
+
+static bool
+mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
+ const unsigned long *mode)
+{
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < link_mode->m_ethtool_len; i++) {
+ if (test_bit(link_mode->mask_ethtool[i], mode))
+ cnt++;
+ }
+
+ return cnt == link_mode->m_ethtool_len;
+}
+
+static u32
+mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
+ const struct ethtool_link_ksettings *cmd)
{
u32 ptys_proto = 0;
int i;
- for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
- if (speed == mlxsw_sp_port_link_mode[i].speed)
- ptys_proto |= mlxsw_sp_port_link_mode[i].mask;
+ for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+ if (mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
+ cmd->link_modes.advertising))
+ ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
}
return ptys_proto;
}
-static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed)
+static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed)
{
u32 ptys_proto = 0;
int i;
- for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
- if (mlxsw_sp_port_link_mode[i].speed <= upper_speed)
- ptys_proto |= mlxsw_sp_port_link_mode[i].mask;
+ for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+ if (speed == mlxsw_sp2_port_link_mode[i].speed)
+ ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
}
return ptys_proto;
}
-static void mlxsw_sp_port_get_link_supported(u32 eth_proto_cap,
- struct ethtool_link_ksettings *cmd)
+static u32
+mlxsw_sp2_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
{
+ u32 ptys_proto = 0;
+ int i;
+
+ for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+ if (mlxsw_sp2_port_link_mode[i].speed <= upper_speed)
+ ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
+ }
+ return ptys_proto;
+}
+
+static int
+mlxsw_sp2_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ u32 *base_speed)
+{
+ char ptys_pl[MLXSW_REG_PTYS_LEN];
+ u32 eth_proto_cap;
+ int err;
+
+ /* In Spectrum-2, the speed of 1x can change from port to port, so query
+ * it from firmware.
+ */
+ mlxsw_reg_ptys_ext_eth_pack(ptys_pl, local_port, 0, false);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
+ if (err)
+ return err;
+ mlxsw_reg_ptys_ext_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
+
+ if (eth_proto_cap &
+ MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR) {
+ *base_speed = MLXSW_SP_PORT_BASE_SPEED_50G;
+ return 0;
+ }
+
+ if (eth_proto_cap &
+ MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR) {
+ *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
+ return 0;
+ }
+
+ return -EIO;
+}
+
+static void
+mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u8 local_port, u32 proto_admin,
+ bool autoneg)
+{
+ mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg);
+}
+
+static void
+mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
+ u32 *p_eth_proto_oper)
+{
+ mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap,
+ p_eth_proto_admin, p_eth_proto_oper);
+}
+
+static const struct mlxsw_sp_port_type_speed_ops
+mlxsw_sp2_port_type_speed_ops = {
+ .from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port,
+ .from_ptys_link = mlxsw_sp2_from_ptys_link,
+ .from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex,
+ .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
+ .to_ptys_speed = mlxsw_sp2_to_ptys_speed,
+ .to_ptys_upper_speed = mlxsw_sp2_to_ptys_upper_speed,
+ .port_speed_base = mlxsw_sp2_port_speed_base,
+ .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,
+ .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
+};
+
+static void
+mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
+ struct ethtool_link_ksettings *cmd)
+{
+ const struct mlxsw_sp_port_type_speed_ops *ops;
+
+ ops = mlxsw_sp->port_type_speed_ops;
+
ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
- mlxsw_sp_from_ptys_supported_port(eth_proto_cap, cmd);
- mlxsw_sp_from_ptys_link(eth_proto_cap, cmd->link_modes.supported);
+ ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
+ ops->from_ptys_link(mlxsw_sp, eth_proto_cap, cmd->link_modes.supported);
}
-static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg,
- struct ethtool_link_ksettings *cmd)
+static void
+mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
+ u32 eth_proto_admin, bool autoneg,
+ struct ethtool_link_ksettings *cmd)
{
+ const struct mlxsw_sp_port_type_speed_ops *ops;
+
+ ops = mlxsw_sp->port_type_speed_ops;
+
if (!autoneg)
return;
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
- mlxsw_sp_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising);
+ ops->from_ptys_link(mlxsw_sp, eth_proto_admin,
+ cmd->link_modes.advertising);
}
-static void
-mlxsw_sp_port_get_link_lp_advertise(u32 eth_proto_lp, u8 autoneg_status,
- struct ethtool_link_ksettings *cmd)
+static u8
+mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
{
- if (autoneg_status != MLXSW_REG_PTYS_AN_STATUS_OK || !eth_proto_lp)
- return;
-
- ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, Autoneg);
- mlxsw_sp_from_ptys_link(eth_proto_lp, cmd->link_modes.lp_advertising);
+ switch (connector_type) {
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR:
+ return PORT_OTHER;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE:
+ return PORT_NONE;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP:
+ return PORT_TP;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI:
+ return PORT_AUI;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC:
+ return PORT_BNC;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII:
+ return PORT_MII;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE:
+ return PORT_FIBRE;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA:
+ return PORT_DA;
+ case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER:
+ return PORT_OTHER;
+ default:
+ WARN_ON_ONCE(1);
+ return PORT_OTHER;
+ }
}
static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
- u32 eth_proto_cap, eth_proto_admin, eth_proto_oper, eth_proto_lp;
+ u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ const struct mlxsw_sp_port_type_speed_ops *ops;
char ptys_pl[MLXSW_REG_PTYS_LEN];
- u8 autoneg_status;
+ u8 connector_type;
bool autoneg;
int err;
+ ops = mlxsw_sp->port_type_speed_ops;
+
autoneg = mlxsw_sp_port->link.autoneg;
- mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false);
+ ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
+ 0, false);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
- mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
- &eth_proto_oper);
+ ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
+ &eth_proto_admin, &eth_proto_oper);
- mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd);
+ mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap, cmd);
- mlxsw_sp_port_get_link_advertise(eth_proto_admin, autoneg, cmd);
-
- eth_proto_lp = mlxsw_reg_ptys_eth_proto_lp_advertise_get(ptys_pl);
- autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl);
- mlxsw_sp_port_get_link_lp_advertise(eth_proto_lp, autoneg_status, cmd);
+ mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg,
+ cmd);
cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
- cmd->base.port = mlxsw_sp_port_connector_port(eth_proto_oper);
- mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper,
- cmd);
+ connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
+ cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
+ ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
+ eth_proto_oper, cmd);
return 0;
}
@@ -2637,21 +3094,25 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ const struct mlxsw_sp_port_type_speed_ops *ops;
char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_cap, eth_proto_new;
bool autoneg;
int err;
- mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false);
+ ops = mlxsw_sp->port_type_speed_ops;
+
+ ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
+ 0, false);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
- mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
+ ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap, NULL, NULL);
autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
eth_proto_new = autoneg ?
- mlxsw_sp_to_ptys_advert_link(cmd) :
- mlxsw_sp_to_ptys_speed(cmd->base.speed);
+ ops->to_ptys_advert_link(mlxsw_sp, cmd) :
+ ops->to_ptys_speed(mlxsw_sp, cmd->base.speed);
eth_proto_new = eth_proto_new & eth_proto_cap;
if (!eth_proto_new) {
@@ -2659,8 +3120,8 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
return -EINVAL;
}
- mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
- eth_proto_new, autoneg);
+ ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
+ eth_proto_new, autoneg);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
@@ -2701,117 +3162,18 @@ out:
return err;
}
-#define MLXSW_SP_I2C_ADDR_LOW 0x50
-#define MLXSW_SP_I2C_ADDR_HIGH 0x51
-#define MLXSW_SP_EEPROM_PAGE_LENGTH 256
-
-static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port,
- u16 offset, u16 size, void *data,
- unsigned int *p_read_size)
-{
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE];
- char mcia_pl[MLXSW_REG_MCIA_LEN];
- u16 i2c_addr;
- int status;
- int err;
-
- size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE);
-
- if (offset < MLXSW_SP_EEPROM_PAGE_LENGTH &&
- offset + size > MLXSW_SP_EEPROM_PAGE_LENGTH)
- /* Cross pages read, read until offset 256 in low page */
- size = MLXSW_SP_EEPROM_PAGE_LENGTH - offset;
-
- i2c_addr = MLXSW_SP_I2C_ADDR_LOW;
- if (offset >= MLXSW_SP_EEPROM_PAGE_LENGTH) {
- i2c_addr = MLXSW_SP_I2C_ADDR_HIGH;
- offset -= MLXSW_SP_EEPROM_PAGE_LENGTH;
- }
-
- mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module,
- 0, 0, offset, size, i2c_addr);
-
- err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcia), mcia_pl);
- if (err)
- return err;
-
- status = mlxsw_reg_mcia_status_get(mcia_pl);
- if (status)
- return -EIO;
-
- mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
- memcpy(data, eeprom_tmp, size);
- *p_read_size = size;
-
- return 0;
-}
-
-enum mlxsw_sp_eeprom_module_info_rev_id {
- MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC = 0x00,
- MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436 = 0x01,
- MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636 = 0x03,
-};
-
-enum mlxsw_sp_eeprom_module_info_id {
- MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP = 0x03,
- MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP = 0x0C,
- MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS = 0x0D,
- MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 = 0x11,
-};
-
-enum mlxsw_sp_eeprom_module_info {
- MLXSW_SP_EEPROM_MODULE_INFO_ID,
- MLXSW_SP_EEPROM_MODULE_INFO_REV_ID,
- MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
-};
-
static int mlxsw_sp_get_module_info(struct net_device *netdev,
struct ethtool_modinfo *modinfo)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
- u8 module_info[MLXSW_SP_EEPROM_MODULE_INFO_SIZE];
- u8 module_rev_id, module_id;
- unsigned int read_size;
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
int err;
- err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0,
- MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
- module_info, &read_size);
- if (err)
- return err;
-
- if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE)
- return -EIO;
-
- module_rev_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_REV_ID];
- module_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_ID];
+ err = mlxsw_env_get_module_info(mlxsw_sp->core,
+ mlxsw_sp_port->mapping.module,
+ modinfo);
- switch (module_id) {
- case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP:
- modinfo->type = ETH_MODULE_SFF_8436;
- modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
- break;
- case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS:
- case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28:
- if (module_id == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 ||
- module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636) {
- modinfo->type = ETH_MODULE_SFF_8636;
- modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
- } else {
- modinfo->type = ETH_MODULE_SFF_8436;
- modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
- }
- break;
- case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP:
- modinfo->type = ETH_MODULE_SFF_8472;
- modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
+ return err;
}
static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
@@ -2819,30 +3181,14 @@ static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
u8 *data)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
- int offset = ee->offset;
- unsigned int read_size;
- int i = 0;
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
int err;
- if (!ee->len)
- return -EINVAL;
-
- memset(data, 0, ee->len);
+ err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core,
+ mlxsw_sp_port->mapping.module, ee,
+ data);
- while (i < ee->len) {
- err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, offset,
- ee->len - i, data + i,
- &read_size);
- if (err) {
- netdev_err(mlxsw_sp_port->dev, "Eeprom query failed\n");
- return err;
- }
-
- i += read_size;
- offset += read_size;
- }
-
- return 0;
+ return err;
}
static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
@@ -2865,13 +3211,24 @@ static int
mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- u32 upper_speed = MLXSW_SP_PORT_BASE_SPEED * width;
+ const struct mlxsw_sp_port_type_speed_ops *ops;
char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_admin;
+ u32 upper_speed;
+ u32 base_speed;
+ int err;
+
+ ops = mlxsw_sp->port_type_speed_ops;
+
+ err = ops->port_speed_base(mlxsw_sp, mlxsw_sp_port->local_port,
+ &base_speed);
+ if (err)
+ return err;
+ upper_speed = base_speed * width;
- eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed);
- mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
- eth_proto_admin, mlxsw_sp_port->link.autoneg);
+ eth_proto_admin = ops->to_ptys_upper_speed(mlxsw_sp, upper_speed);
+ ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
+ eth_proto_admin, mlxsw_sp_port->link.autoneg);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
}
@@ -3207,7 +3564,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
}
mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan;
- mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
err = register_netdev(dev);
if (err) {
@@ -3224,7 +3580,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
err_register_netdev:
mlxsw_sp->ports[local_port] = NULL;
- mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
err_port_vlan_create:
err_port_pvid_set:
@@ -3267,7 +3622,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
mlxsw_sp->ports[local_port] = NULL;
- mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true);
mlxsw_sp_port_nve_fini(mlxsw_sp_port);
mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
@@ -3744,8 +4098,8 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
burst_size = 7;
break;
case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
- rate = 4 * 1024;
- burst_size = 4;
+ rate = 1024;
+ burst_size = 7;
break;
default:
continue;
@@ -4094,6 +4448,9 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops;
mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr;
mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask;
+ mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
+ mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals;
+ mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
}
@@ -4110,6 +4467,9 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
+ mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
+ mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
+ mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
}
@@ -4398,6 +4758,71 @@ static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core)
ARRAY_SIZE(mlxsw_sp_devlink_params));
}
+static int
+mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+ ctx->val.vu32 = mlxsw_sp_acl_region_rehash_intrvl_get(mlxsw_sp);
+ return 0;
+}
+
+static int
+mlxsw_sp_params_acl_region_rehash_intrvl_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+ struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+ return mlxsw_sp_acl_region_rehash_intrvl_set(mlxsw_sp, ctx->val.vu32);
+}
+
+static const struct devlink_param mlxsw_sp2_devlink_params[] = {
+ DEVLINK_PARAM_DRIVER(MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
+ "acl_region_rehash_interval",
+ DEVLINK_PARAM_TYPE_U32,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ mlxsw_sp_params_acl_region_rehash_intrvl_get,
+ mlxsw_sp_params_acl_region_rehash_intrvl_set,
+ NULL),
+};
+
+static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core)
+{
+ struct devlink *devlink = priv_to_devlink(mlxsw_core);
+ union devlink_param_value value;
+ int err;
+
+ err = mlxsw_sp_params_register(mlxsw_core);
+ if (err)
+ return err;
+
+ err = devlink_params_register(devlink, mlxsw_sp2_devlink_params,
+ ARRAY_SIZE(mlxsw_sp2_devlink_params));
+ if (err)
+ goto err_devlink_params_register;
+
+ value.vu32 = 0;
+ devlink_param_driverinit_value_set(devlink,
+ MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
+ value);
+ return 0;
+
+err_devlink_params_register:
+ mlxsw_sp_params_unregister(mlxsw_core);
+ return err;
+}
+
+static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
+{
+ devlink_params_unregister(priv_to_devlink(mlxsw_core),
+ mlxsw_sp2_devlink_params,
+ ARRAY_SIZE(mlxsw_sp2_devlink_params));
+ mlxsw_sp_params_unregister(mlxsw_core);
+}
+
static struct mlxsw_driver mlxsw_sp1_driver = {
.kind = mlxsw_sp1_driver_name,
.priv_size = sizeof(struct mlxsw_sp),
@@ -4446,8 +4871,8 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
.sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get,
.txhdr_construct = mlxsw_sp_txhdr_construct,
.resources_register = mlxsw_sp2_resources_register,
- .params_register = mlxsw_sp_params_register,
- .params_unregister = mlxsw_sp_params_unregister,
+ .params_register = mlxsw_sp2_params_register,
+ .params_unregister = mlxsw_sp2_params_unregister,
.txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sp2_config_profile,
.res_query_enabled = true,
@@ -4691,9 +5116,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
if (err)
goto err_col_port_add;
- err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port, lag_id);
- if (err)
- goto err_col_port_enable;
mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index,
mlxsw_sp_port->local_port);
@@ -4707,8 +5129,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
return 0;
-err_col_port_enable:
- mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
err_col_port_add:
if (!lag->ref_count)
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -4727,7 +5147,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
WARN_ON(lag->ref_count == 0);
- mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
/* Any VLANs configured on the port are no longer valid */
@@ -4772,21 +5191,56 @@ static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
}
-static int mlxsw_sp_port_lag_tx_en_set(struct mlxsw_sp_port *mlxsw_sp_port,
- bool lag_tx_enabled)
+static int
+mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port)
{
- if (lag_tx_enabled)
- return mlxsw_sp_lag_dist_port_add(mlxsw_sp_port,
- mlxsw_sp_port->lag_id);
- else
- return mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
- mlxsw_sp_port->lag_id);
+ int err;
+
+ err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port,
+ mlxsw_sp_port->lag_id);
+ if (err)
+ return err;
+
+ err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+ if (err)
+ goto err_dist_port_add;
+
+ return 0;
+
+err_dist_port_add:
+ mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+ return err;
+}
+
+static int
+mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ int err;
+
+ err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
+ mlxsw_sp_port->lag_id);
+ if (err)
+ return err;
+
+ err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port,
+ mlxsw_sp_port->lag_id);
+ if (err)
+ goto err_col_port_disable;
+
+ return 0;
+
+err_col_port_disable:
+ mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+ return err;
}
static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
struct netdev_lag_lower_state_info *info)
{
- return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
+ if (info->tx_enabled)
+ return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port);
+ else
+ return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
}
static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -5005,12 +5459,14 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
lower_dev,
upper_dev);
} else if (netif_is_lag_master(upper_dev)) {
- if (info->linking)
+ if (info->linking) {
err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
upper_dev);
- else
+ } else {
+ mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
mlxsw_sp_port_lag_leave(mlxsw_sp_port,
upper_dev);
+ }
} else if (netif_is_ovs_master(upper_dev)) {
if (info->linking)
err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index a1c32a81b011..da6278b0caa4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -33,7 +33,8 @@
#define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4
-#define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */
+#define MLXSW_SP_PORT_BASE_SPEED_25G 25000 /* Mb/s */
+#define MLXSW_SP_PORT_BASE_SPEED_50G 50000 /* Mb/s */
#define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */
#define MLXSW_SP_KVD_GRANULARITY 128
@@ -75,6 +76,11 @@ enum mlxsw_sp_rif_type {
MLXSW_SP_RIF_TYPE_MAX,
};
+struct mlxsw_sp_rif_ops;
+
+extern const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[];
+extern const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[];
+
enum mlxsw_sp_fid_type {
MLXSW_SP_FID_TYPE_8021Q,
MLXSW_SP_FID_TYPE_8021D,
@@ -128,6 +134,8 @@ struct mlxsw_sp_kvdl_ops;
struct mlxsw_sp_mr_tcam_ops;
struct mlxsw_sp_acl_tcam_ops;
struct mlxsw_sp_nve_ops;
+struct mlxsw_sp_sb_vals;
+struct mlxsw_sp_port_type_speed_ops;
struct mlxsw_sp {
struct mlxsw_sp_port **ports;
@@ -161,6 +169,9 @@ struct mlxsw_sp {
const struct mlxsw_sp_mr_tcam_ops *mr_tcam_ops;
const struct mlxsw_sp_acl_tcam_ops *acl_tcam_ops;
const struct mlxsw_sp_nve_ops **nve_ops_arr;
+ const struct mlxsw_sp_rif_ops **rif_ops_arr;
+ const struct mlxsw_sp_sb_vals *sb_vals;
+ const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
};
static inline struct mlxsw_sp_upper *
@@ -250,6 +261,29 @@ struct mlxsw_sp_port {
struct mlxsw_sp_acl_block *eg_acl_block;
};
+struct mlxsw_sp_port_type_speed_ops {
+ void (*from_ptys_supported_port)(struct mlxsw_sp *mlxsw_sp,
+ u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd);
+ void (*from_ptys_link)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
+ unsigned long *mode);
+ void (*from_ptys_speed_duplex)(struct mlxsw_sp *mlxsw_sp,
+ bool carrier_ok, u32 ptys_eth_proto,
+ struct ethtool_link_ksettings *cmd);
+ u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp,
+ const struct ethtool_link_ksettings *cmd);
+ u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u32 speed);
+ u32 (*to_ptys_upper_speed)(struct mlxsw_sp *mlxsw_sp, u32 upper_speed);
+ int (*port_speed_base)(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ u32 *base_speed);
+ void (*reg_ptys_eth_pack)(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u8 local_port, u32 proto_admin, bool autoneg);
+ void (*reg_ptys_eth_unpack)(struct mlxsw_sp *mlxsw_sp, char *payload,
+ u32 *p_eth_proto_cap,
+ u32 *p_eth_proto_admin,
+ u32 *p_eth_proto_oper);
+};
+
static inline struct net_device *
mlxsw_sp_bridge_vxlan_dev_find(struct net_device *br_dev)
{
@@ -365,12 +399,14 @@ int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port,
u32 *p_cur, u32 *p_max);
u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells);
u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes);
+u32 mlxsw_sp_sb_max_headroom_cells(const struct mlxsw_sp *mlxsw_sp);
+
+extern const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals;
+extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals;
/* spectrum_switchdev.c */
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp);
-void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port);
-void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port);
int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
bool adding);
void
@@ -501,6 +537,9 @@ void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
const union mlxsw_sp_l3addr *ul_sip);
int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
u16 *vr_id);
+int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
+ u16 *ul_rif_index);
+void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index);
/* spectrum_kvdl.c */
enum mlxsw_sp_kvdl_entry_type {
@@ -681,6 +720,8 @@ struct mlxsw_sp_fid *mlxsw_sp_acl_dummy_fid(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp);
+u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp);
+int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val);
/* spectrum_acl_tcam.c */
struct mlxsw_sp_acl_tcam;
@@ -695,10 +736,13 @@ struct mlxsw_sp_acl_tcam_ops {
size_t region_priv_size;
int (*region_init)(struct mlxsw_sp *mlxsw_sp, void *region_priv,
void *tcam_priv,
- struct mlxsw_sp_acl_tcam_region *region);
+ struct mlxsw_sp_acl_tcam_region *region,
+ void *hints_priv);
void (*region_fini)(struct mlxsw_sp *mlxsw_sp, void *region_priv);
int (*region_associate)(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_region *region);
+ void * (*region_rehash_hints_get)(void *region_priv);
+ void (*region_rehash_hints_put)(void *hints_priv);
size_t chunk_priv_size;
void (*chunk_init)(void *region_priv, void *chunk_priv,
unsigned int priority);
@@ -712,8 +756,7 @@ struct mlxsw_sp_acl_tcam_ops {
void *region_priv, void *chunk_priv,
void *entry_priv);
int (*entry_action_replace)(struct mlxsw_sp *mlxsw_sp,
- void *region_priv, void *chunk_priv,
- void *entry_priv,
+ void *region_priv, void *entry_priv,
struct mlxsw_sp_acl_rule_info *rulei);
int (*entry_activity_get)(struct mlxsw_sp *mlxsw_sp,
void *region_priv, void *entry_priv,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c
index fe270c1a26a6..3a636f753607 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c
@@ -112,7 +112,8 @@ mlxsw_sp1_acl_ctcam_region_catchall_del(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp1_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
void *tcam_priv,
- struct mlxsw_sp_acl_tcam_region *_region)
+ struct mlxsw_sp_acl_tcam_region *_region,
+ void *hints_priv)
{
struct mlxsw_sp1_acl_tcam_region *region = region_priv;
int err;
@@ -194,8 +195,7 @@ static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp1_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
- void *region_priv, void *chunk_priv,
- void *entry_priv,
+ void *region_priv, void *entry_priv,
struct mlxsw_sp_acl_rule_info *rulei)
{
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
index 234ab51916db..6c66a0f1b79e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
@@ -139,7 +139,8 @@ static void mlxsw_sp2_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, void *priv)
static int
mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
void *tcam_priv,
- struct mlxsw_sp_acl_tcam_region *_region)
+ struct mlxsw_sp_acl_tcam_region *_region,
+ void *hints_priv)
{
struct mlxsw_sp2_acl_tcam_region *region = region_priv;
struct mlxsw_sp2_acl_tcam *tcam = tcam_priv;
@@ -147,7 +148,8 @@ mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
region->region = _region;
return mlxsw_sp_acl_atcam_region_init(mlxsw_sp, &tcam->atcam,
- &region->aregion, _region,
+ &region->aregion,
+ _region, hints_priv,
&mlxsw_sp2_acl_ctcam_region_ops);
}
@@ -166,6 +168,18 @@ mlxsw_sp2_acl_tcam_region_associate(struct mlxsw_sp *mlxsw_sp,
return mlxsw_sp_acl_atcam_region_associate(mlxsw_sp, region->id);
}
+static void *mlxsw_sp2_acl_tcam_region_rehash_hints_get(void *region_priv)
+{
+ struct mlxsw_sp2_acl_tcam_region *region = region_priv;
+
+ return mlxsw_sp_acl_atcam_rehash_hints_get(&region->aregion);
+}
+
+static void mlxsw_sp2_acl_tcam_region_rehash_hints_put(void *hints_priv)
+{
+ mlxsw_sp_acl_atcam_rehash_hints_put(hints_priv);
+}
+
static void mlxsw_sp2_acl_tcam_chunk_init(void *region_priv, void *chunk_priv,
unsigned int priority)
{
@@ -212,18 +226,15 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp2_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
- void *region_priv, void *chunk_priv,
- void *entry_priv,
+ void *region_priv, void *entry_priv,
struct mlxsw_sp_acl_rule_info *rulei)
{
struct mlxsw_sp2_acl_tcam_region *region = region_priv;
- struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
entry->act_block = rulei->act_block;
return mlxsw_sp_acl_atcam_entry_action_replace(mlxsw_sp,
&region->aregion,
- &chunk->achunk,
&entry->aentry, rulei);
}
@@ -246,6 +257,8 @@ const struct mlxsw_sp_acl_tcam_ops mlxsw_sp2_acl_tcam_ops = {
.region_init = mlxsw_sp2_acl_tcam_region_init,
.region_fini = mlxsw_sp2_acl_tcam_region_fini,
.region_associate = mlxsw_sp2_acl_tcam_region_associate,
+ .region_rehash_hints_get = mlxsw_sp2_acl_tcam_region_rehash_hints_get,
+ .region_rehash_hints_put = mlxsw_sp2_acl_tcam_region_rehash_hints_put,
.chunk_priv_size = sizeof(struct mlxsw_sp2_acl_tcam_chunk),
.chunk_init = mlxsw_sp2_acl_tcam_chunk_init,
.chunk_fini = mlxsw_sp2_acl_tcam_chunk_fini,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 695d33358988..a146a44634e9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -588,7 +588,7 @@ int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
{
u8 ethertype;
- if (action == TCA_VLAN_ACT_MODIFY) {
+ if (action == FLOW_ACTION_VLAN_MANGLE) {
switch (proto) {
case ETH_P_8021Q:
ethertype = 0;
@@ -640,7 +640,7 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
int err;
mlxsw_sp_acl_ruleset_ref_inc(ruleset);
- rule = kzalloc(sizeof(*rule) + ops->rule_priv_size(mlxsw_sp),
+ rule = kzalloc(sizeof(*rule) + ops->rule_priv_size,
GFP_KERNEL);
if (!rule) {
err = -ENOMEM;
@@ -742,8 +742,7 @@ int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
rulei = mlxsw_sp_acl_rule_rulei(rule);
rulei->act_block = afa_block;
- return ops->rule_action_replace(mlxsw_sp, ruleset->priv, rule->priv,
- rule->rulei);
+ return ops->rule_action_replace(mlxsw_sp, rule->priv, rule->rulei);
}
struct mlxsw_sp_acl_rule *
@@ -806,7 +805,7 @@ static void mlxsw_sp_acl_rule_activity_work_schedule(struct mlxsw_sp_acl *acl)
msecs_to_jiffies(interval));
}
-static void mlxsw_sp_acl_rul_activity_update_work(struct work_struct *work)
+static void mlxsw_sp_acl_rule_activity_update_work(struct work_struct *work)
{
struct mlxsw_sp_acl *acl = container_of(work, struct mlxsw_sp_acl,
rule_activity_update.dw.work);
@@ -885,7 +884,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp)
/* Create the delayed work for the rule activity_update */
INIT_DELAYED_WORK(&acl->rule_activity_update.dw,
- mlxsw_sp_acl_rul_activity_update_work);
+ mlxsw_sp_acl_rule_activity_update_work);
acl->rule_activity_update.interval = MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS;
mlxsw_core_schedule_dw(&acl->rule_activity_update.dw, 0);
return 0;
@@ -913,3 +912,19 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_afk_destroy(acl->afk);
kfree(acl);
}
+
+u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp)
+{
+ struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
+
+ return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(mlxsw_sp,
+ &acl->tcam);
+}
+
+int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val)
+{
+ struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
+
+ return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(mlxsw_sp,
+ &acl->tcam, val);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c
index 80fb268d51a5..ded4cf658680 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c
@@ -7,6 +7,8 @@
#include <linux/gfp.h>
#include <linux/refcount.h>
#include <linux/rhashtable.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/mlxsw.h>
#include "reg.h"
#include "core.h"
@@ -316,6 +318,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam,
struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_tcam_region *region,
+ void *hints_priv,
const struct mlxsw_sp_acl_ctcam_region_ops *ops)
{
int err;
@@ -332,7 +335,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
err = aregion->ops->init(aregion);
if (err)
goto err_ops_init;
- err = mlxsw_sp_acl_erp_region_init(aregion);
+ err = mlxsw_sp_acl_erp_region_init(aregion, hints_priv);
if (err)
goto err_erp_region_init;
err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, &aregion->cregion,
@@ -390,8 +393,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;
- lkey_id = aregion->ops->lkey_id_get(aregion, aentry->ht_key.enc_key,
- erp_id);
+ lkey_id = aregion->ops->lkey_id_get(aregion, aentry->enc_key, erp_id);
if (IS_ERR(lkey_id))
return PTR_ERR(lkey_id);
aentry->lkey_id = lkey_id;
@@ -399,7 +401,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE,
priority, region->tcam_region_info,
- aentry->ht_key.enc_key, erp_id,
+ aentry->enc_key, erp_id,
aentry->delta_info.start,
aentry->delta_info.mask,
aentry->delta_info.value,
@@ -424,12 +426,11 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
struct mlxsw_sp_acl_tcam_region *region = aregion->region;
u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
- char *enc_key = aentry->ht_key.enc_key;
char ptce3_pl[MLXSW_REG_PTCE3_LEN];
mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0,
region->tcam_region_info,
- enc_key, erp_id,
+ aentry->enc_key, erp_id,
aentry->delta_info.start,
aentry->delta_info.mask,
aentry->delta_info.value,
@@ -458,7 +459,7 @@ mlxsw_sp_acl_atcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE,
priority, region->tcam_region_info,
- aentry->ht_key.enc_key, erp_id,
+ aentry->enc_key, erp_id,
aentry->delta_info.start,
aentry->delta_info.mask,
aentry->delta_info.value,
@@ -481,15 +482,15 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
int err;
mlxsw_afk_encode(afk, region->key_info, &rulei->values,
- aentry->full_enc_key, mask);
+ aentry->ht_key.full_enc_key, mask);
erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
if (IS_ERR(erp_mask))
return PTR_ERR(erp_mask);
aentry->erp_mask = erp_mask;
aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask);
- memcpy(aentry->ht_key.enc_key, aentry->full_enc_key,
- sizeof(aentry->ht_key.enc_key));
+ memcpy(aentry->enc_key, aentry->ht_key.full_enc_key,
+ sizeof(aentry->enc_key));
/* Compute all needed delta information and clear the delta bits
* from the encrypted key.
@@ -498,8 +499,9 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
aentry->delta_info.start = mlxsw_sp_acl_erp_delta_start(delta);
aentry->delta_info.mask = mlxsw_sp_acl_erp_delta_mask(delta);
aentry->delta_info.value =
- mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key);
- mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key);
+ mlxsw_sp_acl_erp_delta_value(delta,
+ aentry->ht_key.full_enc_key);
+ mlxsw_sp_acl_erp_delta_clear(delta, aentry->enc_key);
/* Add rule to the list of A-TCAM rules, assuming this
* rule is intended to A-TCAM. In case this rule does
@@ -579,6 +581,7 @@ int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
/* It is possible we failed to add the rule to the A-TCAM due to
* exceeded number of masks. Try to spill into C-TCAM.
*/
+ trace_mlxsw_sp_acl_atcam_entry_add_ctcam_spill(mlxsw_sp, aregion);
err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, &aregion->cregion,
&achunk->cchunk, &aentry->centry,
rulei, true);
@@ -603,7 +606,6 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
int
mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_region *aregion,
- struct mlxsw_sp_acl_atcam_chunk *achunk,
struct mlxsw_sp_acl_atcam_entry *aentry,
struct mlxsw_sp_acl_rule_info *rulei)
{
@@ -612,7 +614,6 @@ mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp_acl_atcam_is_centry(aentry))
err = mlxsw_sp_acl_ctcam_entry_action_replace(mlxsw_sp,
&aregion->cregion,
- &achunk->cchunk,
&aentry->centry,
rulei);
else
@@ -634,3 +635,14 @@ void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
{
mlxsw_sp_acl_erps_fini(mlxsw_sp, atcam);
}
+
+void *
+mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion)
+{
+ return mlxsw_sp_acl_erp_rehash_hints_get(aregion);
+}
+
+void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv)
+{
+ mlxsw_sp_acl_erp_rehash_hints_put(hints_priv);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
index 505b87846acc..3a2de13fcb68 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
@@ -5,11 +5,13 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/refcount.h>
+#include <linux/mutex.h>
#include "spectrum.h"
#include "spectrum_acl_tcam.h"
struct mlxsw_sp_acl_bf {
+ struct mutex lock; /* Protects Bloom Filter updates. */
unsigned int bank_size;
refcount_t refcnt[0];
};
@@ -133,7 +135,7 @@ mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
memcpy(chunk + MLXSW_BLOOM_CHUNK_PAD_BYTES, &erp_region_id,
sizeof(erp_region_id));
memcpy(chunk + MLXSW_BLOOM_CHUNK_KEY_OFFSET,
- &aentry->ht_key.enc_key[chunk_key_offsets[chunk_index]],
+ &aentry->enc_key[chunk_key_offsets[chunk_index]],
MLXSW_BLOOM_CHUNK_KEY_BYTES);
chunk += MLXSW_BLOOM_KEY_CHUNK_BYTES;
}
@@ -172,26 +174,36 @@ mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
u16 bf_index;
int err;
+ mutex_lock(&bf->lock);
+
bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry);
rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
bf_index);
- if (refcount_inc_not_zero(&bf->refcnt[rule_index]))
- return 0;
+ if (refcount_inc_not_zero(&bf->refcnt[rule_index])) {
+ err = 0;
+ goto unlock;
+ }
peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
- if (!peabfe_pl)
- return -ENOMEM;
+ if (!peabfe_pl) {
+ err = -ENOMEM;
+ goto unlock;
+ }
mlxsw_reg_peabfe_pack(peabfe_pl);
mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 1, erp_bank, bf_index);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
kfree(peabfe_pl);
if (err)
- return err;
+ goto unlock;
refcount_set(&bf->refcnt[rule_index], 1);
- return 0;
+ err = 0;
+
+unlock:
+ mutex_unlock(&bf->lock);
+ return err;
}
void
@@ -205,6 +217,8 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
char *peabfe_pl;
u16 bf_index;
+ mutex_lock(&bf->lock);
+
bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry);
rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
bf_index);
@@ -212,13 +226,16 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
if (refcount_dec_and_test(&bf->refcnt[rule_index])) {
peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
if (!peabfe_pl)
- return;
+ goto unlock;
mlxsw_reg_peabfe_pack(peabfe_pl);
mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 0, erp_bank, bf_index);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
kfree(peabfe_pl);
}
+
+unlock:
+ mutex_unlock(&bf->lock);
}
struct mlxsw_sp_acl_bf *
@@ -234,16 +251,19 @@ mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks)
* is 2^ACL_MAX_BF_LOG
*/
bf_bank_size = 1 << MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_BF_LOG);
- bf = kzalloc(sizeof(*bf) + bf_bank_size * num_erp_banks *
- sizeof(*bf->refcnt), GFP_KERNEL);
+ bf = kzalloc(struct_size(bf, refcnt, bf_bank_size * num_erp_banks),
+ GFP_KERNEL);
if (!bf)
return ERR_PTR(-ENOMEM);
bf->bank_size = bf_bank_size;
+ mutex_init(&bf->lock);
+
return bf;
}
void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf)
{
+ mutex_destroy(&bf->lock);
kfree(bf);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
index b0f2d8e8ded0..05680a7e6c56 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
@@ -72,7 +72,15 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
act_set = mlxsw_afa_block_first_set(rulei->act_block);
mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
- return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+ if (err)
+ goto err_ptce2_write;
+
+ return 0;
+
+err_ptce2_write:
+ cregion->ops->entry_remove(cregion, centry);
+ return err;
}
static void
@@ -215,7 +223,6 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ctcam_region *cregion,
- struct mlxsw_sp_acl_ctcam_chunk *cchunk,
struct mlxsw_sp_acl_ctcam_entry *centry,
struct mlxsw_sp_acl_rule_info *rulei)
{
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
index 1c19feefa5f2..c1a9cc9a3292 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
@@ -7,6 +7,7 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/objagg.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
@@ -63,6 +64,7 @@ struct mlxsw_sp_acl_erp_table {
unsigned int num_ctcam_erps;
unsigned int num_deltas;
struct objagg *objagg;
+ struct mutex objagg_lock; /* guards objagg manipulation */
};
struct mlxsw_sp_acl_erp_table_ops {
@@ -1001,17 +1003,15 @@ struct mlxsw_sp_acl_erp_mask *
mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
const char *mask, bool ctcam)
{
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
struct mlxsw_sp_acl_erp_key key;
struct objagg_obj *objagg_obj;
- /* eRPs are allocated from a shared resource, but currently all
- * allocations are done under RTNL.
- */
- ASSERT_RTNL();
-
memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN);
key.ctcam = ctcam;
- objagg_obj = objagg_obj_get(aregion->erp_table->objagg, &key);
+ mutex_lock(&erp_table->objagg_lock);
+ objagg_obj = objagg_obj_get(erp_table->objagg, &key);
+ mutex_unlock(&erp_table->objagg_lock);
if (IS_ERR(objagg_obj))
return ERR_CAST(objagg_obj);
return (struct mlxsw_sp_acl_erp_mask *) objagg_obj;
@@ -1021,9 +1021,11 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_erp_mask *erp_mask)
{
struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
- ASSERT_RTNL();
- objagg_obj_put(aregion->erp_table->objagg, objagg_obj);
+ mutex_lock(&erp_table->objagg_lock);
+ objagg_obj_put(erp_table->objagg, objagg_obj);
+ mutex_unlock(&erp_table->objagg_lock);
}
int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
@@ -1035,7 +1037,6 @@ int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
unsigned int erp_bank;
- ASSERT_RTNL();
if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
return 0;
@@ -1054,7 +1055,6 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
unsigned int erp_bank;
- ASSERT_RTNL();
if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
return;
@@ -1202,6 +1202,32 @@ mlxsw_sp_acl_erp_delta_fill(const struct mlxsw_sp_acl_erp_key *parent_key,
return 0;
}
+static bool mlxsw_sp_acl_erp_delta_check(void *priv, const void *parent_obj,
+ const void *obj)
+{
+ const struct mlxsw_sp_acl_erp_key *parent_key = parent_obj;
+ const struct mlxsw_sp_acl_erp_key *key = obj;
+ u16 delta_start;
+ u8 delta_mask;
+ int err;
+
+ err = mlxsw_sp_acl_erp_delta_fill(parent_key, key,
+ &delta_start, &delta_mask);
+ return err ? false : true;
+}
+
+static int mlxsw_sp_acl_erp_hints_obj_cmp(const void *obj1, const void *obj2)
+{
+ const struct mlxsw_sp_acl_erp_key *key1 = obj1;
+ const struct mlxsw_sp_acl_erp_key *key2 = obj2;
+
+ /* For hints purposes, two objects are considered equal
+ * in case the masks are the same. Does not matter what
+ * the "ctcam" value is.
+ */
+ return memcmp(key1->mask, key2->mask, sizeof(key1->mask));
+}
+
static void *mlxsw_sp_acl_erp_delta_create(void *priv, void *parent_obj,
void *obj)
{
@@ -1256,12 +1282,17 @@ static void mlxsw_sp_acl_erp_delta_destroy(void *priv, void *delta_priv)
kfree(delta);
}
-static void *mlxsw_sp_acl_erp_root_create(void *priv, void *obj)
+static void *mlxsw_sp_acl_erp_root_create(void *priv, void *obj,
+ unsigned int root_id)
{
struct mlxsw_sp_acl_atcam_region *aregion = priv;
struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
struct mlxsw_sp_acl_erp_key *key = obj;
+ if (!key->ctcam &&
+ root_id != OBJAGG_OBJ_ROOT_ID_INVALID &&
+ root_id >= MLXSW_SP_ACL_ERP_MAX_PER_REGION)
+ return ERR_PTR(-ENOBUFS);
return erp_table->ops->erp_create(erp_table, key);
}
@@ -1275,6 +1306,8 @@ static void mlxsw_sp_acl_erp_root_destroy(void *priv, void *root_priv)
static const struct objagg_ops mlxsw_sp_acl_erp_objagg_ops = {
.obj_size = sizeof(struct mlxsw_sp_acl_erp_key),
+ .delta_check = mlxsw_sp_acl_erp_delta_check,
+ .hints_obj_cmp = mlxsw_sp_acl_erp_hints_obj_cmp,
.delta_create = mlxsw_sp_acl_erp_delta_create,
.delta_destroy = mlxsw_sp_acl_erp_delta_destroy,
.root_create = mlxsw_sp_acl_erp_root_create,
@@ -1282,7 +1315,8 @@ static const struct objagg_ops mlxsw_sp_acl_erp_objagg_ops = {
};
static struct mlxsw_sp_acl_erp_table *
-mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion)
+mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion,
+ struct objagg_hints *hints)
{
struct mlxsw_sp_acl_erp_table *erp_table;
int err;
@@ -1292,7 +1326,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion)
return ERR_PTR(-ENOMEM);
erp_table->objagg = objagg_create(&mlxsw_sp_acl_erp_objagg_ops,
- aregion);
+ hints, aregion);
if (IS_ERR(erp_table->objagg)) {
err = PTR_ERR(erp_table->objagg);
goto err_objagg_create;
@@ -1302,6 +1336,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion)
erp_table->ops = &erp_no_mask_ops;
INIT_LIST_HEAD(&erp_table->atcam_erps_list);
erp_table->aregion = aregion;
+ mutex_init(&erp_table->objagg_lock);
return erp_table;
@@ -1314,6 +1349,7 @@ static void
mlxsw_sp_acl_erp_table_destroy(struct mlxsw_sp_acl_erp_table *erp_table)
{
WARN_ON(!list_empty(&erp_table->atcam_erps_list));
+ mutex_destroy(&erp_table->objagg_lock);
objagg_destroy(erp_table->objagg);
kfree(erp_table);
}
@@ -1339,12 +1375,93 @@ mlxsw_sp_acl_erp_region_param_init(struct mlxsw_sp_acl_atcam_region *aregion)
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pererp), pererp_pl);
}
-int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion)
+static int
+mlxsw_sp_acl_erp_hints_check(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_atcam_region *aregion,
+ struct objagg_hints *hints, bool *p_rehash_needed)
+{
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
+ const struct objagg_stats *ostats;
+ const struct objagg_stats *hstats;
+ int err;
+
+ *p_rehash_needed = false;
+
+ mutex_lock(&erp_table->objagg_lock);
+ ostats = objagg_stats_get(erp_table->objagg);
+ mutex_unlock(&erp_table->objagg_lock);
+ if (IS_ERR(ostats)) {
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP stats\n");
+ return PTR_ERR(ostats);
+ }
+
+ hstats = objagg_hints_stats_get(hints);
+ if (IS_ERR(hstats)) {
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP hints stats\n");
+ err = PTR_ERR(hstats);
+ goto err_hints_stats_get;
+ }
+
+ /* Very basic criterion for now. */
+ if (hstats->root_count < ostats->root_count)
+ *p_rehash_needed = true;
+
+ err = 0;
+
+ objagg_stats_put(hstats);
+err_hints_stats_get:
+ objagg_stats_put(ostats);
+ return err;
+}
+
+void *
+mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion)
+{
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
+ struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;
+ struct objagg_hints *hints;
+ bool rehash_needed;
+ int err;
+
+ mutex_lock(&erp_table->objagg_lock);
+ hints = objagg_hints_get(erp_table->objagg,
+ OBJAGG_OPT_ALGO_SIMPLE_GREEDY);
+ mutex_unlock(&erp_table->objagg_lock);
+ if (IS_ERR(hints)) {
+ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to create ERP hints\n");
+ return ERR_CAST(hints);
+ }
+ err = mlxsw_sp_acl_erp_hints_check(mlxsw_sp, aregion, hints,
+ &rehash_needed);
+ if (err)
+ goto errout;
+
+ if (!rehash_needed) {
+ err = -EAGAIN;
+ goto errout;
+ }
+ return hints;
+
+errout:
+ objagg_hints_put(hints);
+ return ERR_PTR(err);
+}
+
+void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv)
+{
+ struct objagg_hints *hints = hints_priv;
+
+ objagg_hints_put(hints);
+}
+
+int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion,
+ void *hints_priv)
{
struct mlxsw_sp_acl_erp_table *erp_table;
+ struct objagg_hints *hints = hints_priv;
int err;
- erp_table = mlxsw_sp_acl_erp_table_create(aregion);
+ erp_table = mlxsw_sp_acl_erp_table_create(aregion, hints);
if (IS_ERR(erp_table))
return PTR_ERR(erp_table);
aregion->erp_table = erp_table;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index fe230acf92a9..8811f6513e36 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -8,6 +8,8 @@
#include <linux/list.h>
#include <linux/rhashtable.h>
#include <linux/netdevice.h>
+#include <linux/mutex.h>
+#include <trace/events/mlxsw.h>
#include "reg.h"
#include "core.h"
@@ -23,6 +25,10 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp)
return ops->priv_size;
}
+#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */
+#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */
+#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100 /* number of entries */
+
int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam *tcam)
{
@@ -33,6 +39,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
size_t alloc_size;
int err;
+ mutex_init(&tcam->lock);
+ tcam->vregion_rehash_intrvl =
+ MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT;
+ INIT_LIST_HEAD(&tcam->vregion_list);
+
max_tcam_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core,
ACL_MAX_TCAM_REGIONS);
max_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_REGIONS);
@@ -76,6 +87,7 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ mutex_destroy(&tcam->lock);
ops->fini(mlxsw_sp, tcam->priv);
kfree(tcam->used_groups);
kfree(tcam->used_regions);
@@ -153,37 +165,100 @@ struct mlxsw_sp_acl_tcam_pattern {
struct mlxsw_sp_acl_tcam_group {
struct mlxsw_sp_acl_tcam *tcam;
u16 id;
+ struct mutex lock; /* guards region list updates */
struct list_head region_list;
unsigned int region_count;
- struct rhashtable chunk_ht;
- struct mlxsw_sp_acl_tcam_group_ops *ops;
+};
+
+struct mlxsw_sp_acl_tcam_vgroup {
+ struct mlxsw_sp_acl_tcam_group group;
+ struct list_head vregion_list;
+ struct rhashtable vchunk_ht;
const struct mlxsw_sp_acl_tcam_pattern *patterns;
unsigned int patterns_count;
bool tmplt_elusage_set;
struct mlxsw_afk_element_usage tmplt_elusage;
+ bool vregion_rehash_enabled;
};
-struct mlxsw_sp_acl_tcam_chunk {
- struct list_head list; /* Member of a TCAM region */
- struct rhash_head ht_node; /* Member of a chunk HT */
- unsigned int priority; /* Priority within the region and group */
- struct mlxsw_sp_acl_tcam_group *group;
+struct mlxsw_sp_acl_tcam_rehash_ctx {
+ void *hints_priv;
+ bool this_is_rollback;
+ struct mlxsw_sp_acl_tcam_vchunk *current_vchunk; /* vchunk being
+ * currently migrated.
+ */
+ struct mlxsw_sp_acl_tcam_ventry *start_ventry; /* ventry to start
+ * migration from in
+ * a vchunk being
+ * currently migrated.
+ */
+ struct mlxsw_sp_acl_tcam_ventry *stop_ventry; /* ventry to stop
+ * migration at
+ * a vchunk being
+ * currently migrated.
+ */
+};
+
+struct mlxsw_sp_acl_tcam_vregion {
+ struct mutex lock; /* Protects consistency of region, region2 pointers
+ * and vchunk_list.
+ */
struct mlxsw_sp_acl_tcam_region *region;
+ struct mlxsw_sp_acl_tcam_region *region2; /* Used during migration */
+ struct list_head list; /* Member of a TCAM group */
+ struct list_head tlist; /* Member of a TCAM */
+ struct list_head vchunk_list; /* List of vchunks under this vregion */
+ struct mlxsw_afk_key_info *key_info;
+ struct mlxsw_sp_acl_tcam *tcam;
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup;
+ struct {
+ struct delayed_work dw;
+ struct mlxsw_sp_acl_tcam_rehash_ctx ctx;
+ } rehash;
+ struct mlxsw_sp *mlxsw_sp;
+ bool failed_rollback; /* Indicates failed rollback during migration */
unsigned int ref_count;
+};
+
+struct mlxsw_sp_acl_tcam_vchunk;
+
+struct mlxsw_sp_acl_tcam_chunk {
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ struct mlxsw_sp_acl_tcam_region *region;
unsigned long priv[0];
/* priv has to be always the last item */
};
+struct mlxsw_sp_acl_tcam_vchunk {
+ struct mlxsw_sp_acl_tcam_chunk *chunk;
+ struct mlxsw_sp_acl_tcam_chunk *chunk2; /* Used during migration */
+ struct list_head list; /* Member of a TCAM vregion */
+ struct rhash_head ht_node; /* Member of a chunk HT */
+ struct list_head ventry_list;
+ unsigned int priority; /* Priority within the vregion and group */
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup;
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+ unsigned int ref_count;
+};
+
struct mlxsw_sp_acl_tcam_entry {
+ struct mlxsw_sp_acl_tcam_ventry *ventry;
struct mlxsw_sp_acl_tcam_chunk *chunk;
unsigned long priv[0];
/* priv has to be always the last item */
};
-static const struct rhashtable_params mlxsw_sp_acl_tcam_chunk_ht_params = {
+struct mlxsw_sp_acl_tcam_ventry {
+ struct mlxsw_sp_acl_tcam_entry *entry;
+ struct list_head list; /* Member of a TCAM vchunk */
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ struct mlxsw_sp_acl_rule_info *rulei;
+};
+
+static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = {
.key_len = sizeof(unsigned int),
- .key_offset = offsetof(struct mlxsw_sp_acl_tcam_chunk, priority),
- .head_offset = offsetof(struct mlxsw_sp_acl_tcam_chunk, ht_node),
+ .key_offset = offsetof(struct mlxsw_sp_acl_tcam_vchunk, priority),
+ .head_offset = offsetof(struct mlxsw_sp_acl_tcam_vchunk, ht_node),
.automatic_shrinking = true,
};
@@ -195,55 +270,90 @@ static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp,
int acl_index = 0;
mlxsw_reg_pagt_pack(pagt_pl, group->id);
- list_for_each_entry(region, &group->region_list, list)
- mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, region->id);
+ list_for_each_entry(region, &group->region_list, list) {
+ bool multi = false;
+
+ /* Check if the next entry in the list has the same vregion. */
+ if (region->list.next != &group->region_list &&
+ list_next_entry(region, list)->vregion == region->vregion)
+ multi = true;
+ mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++,
+ region->id, multi);
+ }
mlxsw_reg_pagt_size_set(pagt_pl, acl_index);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl);
}
static int
-mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam *tcam,
- struct mlxsw_sp_acl_tcam_group *group,
- const struct mlxsw_sp_acl_tcam_pattern *patterns,
- unsigned int patterns_count,
- struct mlxsw_afk_element_usage *tmplt_elusage)
+mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam,
+ struct mlxsw_sp_acl_tcam_group *group)
{
int err;
group->tcam = tcam;
- group->patterns = patterns;
- group->patterns_count = patterns_count;
- if (tmplt_elusage) {
- group->tmplt_elusage_set = true;
- memcpy(&group->tmplt_elusage, tmplt_elusage,
- sizeof(group->tmplt_elusage));
- }
+ mutex_init(&group->lock);
INIT_LIST_HEAD(&group->region_list);
+
err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
if (err)
return err;
- err = rhashtable_init(&group->chunk_ht,
- &mlxsw_sp_acl_tcam_chunk_ht_params);
+ return 0;
+}
+
+static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp_acl_tcam_group *group)
+{
+ struct mlxsw_sp_acl_tcam *tcam = group->tcam;
+
+ mutex_destroy(&group->lock);
+ mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
+ WARN_ON(!list_empty(&group->region_list));
+}
+
+static int
+mlxsw_sp_acl_tcam_vgroup_add(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ const struct mlxsw_sp_acl_tcam_pattern *patterns,
+ unsigned int patterns_count,
+ struct mlxsw_afk_element_usage *tmplt_elusage,
+ bool vregion_rehash_enabled)
+{
+ int err;
+
+ vgroup->patterns = patterns;
+ vgroup->patterns_count = patterns_count;
+ vgroup->vregion_rehash_enabled = vregion_rehash_enabled;
+
+ if (tmplt_elusage) {
+ vgroup->tmplt_elusage_set = true;
+ memcpy(&vgroup->tmplt_elusage, tmplt_elusage,
+ sizeof(vgroup->tmplt_elusage));
+ }
+ INIT_LIST_HEAD(&vgroup->vregion_list);
+
+ err = mlxsw_sp_acl_tcam_group_add(tcam, &vgroup->group);
+ if (err)
+ return err;
+
+ err = rhashtable_init(&vgroup->vchunk_ht,
+ &mlxsw_sp_acl_tcam_vchunk_ht_params);
if (err)
goto err_rhashtable_init;
return 0;
err_rhashtable_init:
- mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
+ mlxsw_sp_acl_tcam_group_del(&vgroup->group);
return err;
}
-static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group)
+static void
+mlxsw_sp_acl_tcam_vgroup_del(struct mlxsw_sp_acl_tcam_vgroup *vgroup)
{
- struct mlxsw_sp_acl_tcam *tcam = group->tcam;
-
- rhashtable_destroy(&group->chunk_ht);
- mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
- WARN_ON(!list_empty(&group->region_list));
+ rhashtable_destroy(&vgroup->vchunk_ht);
+ mlxsw_sp_acl_tcam_group_del(&vgroup->group);
+ WARN_ON(!list_empty(&vgroup->vregion_list));
}
static int
@@ -283,146 +393,194 @@ mlxsw_sp_acl_tcam_group_id(struct mlxsw_sp_acl_tcam_group *group)
}
static unsigned int
-mlxsw_sp_acl_tcam_region_prio(struct mlxsw_sp_acl_tcam_region *region)
+mlxsw_sp_acl_tcam_vregion_prio(struct mlxsw_sp_acl_tcam_vregion *vregion)
{
- struct mlxsw_sp_acl_tcam_chunk *chunk;
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
- if (list_empty(&region->chunk_list))
+ if (list_empty(&vregion->vchunk_list))
return 0;
- /* As a priority of a region, return priority of the first chunk */
- chunk = list_first_entry(&region->chunk_list, typeof(*chunk), list);
- return chunk->priority;
+ /* As a priority of a vregion, return priority of the first vchunk */
+ vchunk = list_first_entry(&vregion->vchunk_list,
+ typeof(*vchunk), list);
+ return vchunk->priority;
}
static unsigned int
-mlxsw_sp_acl_tcam_region_max_prio(struct mlxsw_sp_acl_tcam_region *region)
+mlxsw_sp_acl_tcam_vregion_max_prio(struct mlxsw_sp_acl_tcam_vregion *vregion)
{
- struct mlxsw_sp_acl_tcam_chunk *chunk;
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
- if (list_empty(&region->chunk_list))
+ if (list_empty(&vregion->vchunk_list))
return 0;
- chunk = list_last_entry(&region->chunk_list, typeof(*chunk), list);
- return chunk->priority;
+ vchunk = list_last_entry(&vregion->vchunk_list,
+ typeof(*vchunk), list);
+ return vchunk->priority;
}
-static void
-mlxsw_sp_acl_tcam_group_list_add(struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_sp_acl_tcam_region *region)
+static int
+mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_region *region,
+ unsigned int priority,
+ struct mlxsw_sp_acl_tcam_region *next_region)
{
struct mlxsw_sp_acl_tcam_region *region2;
struct list_head *pos;
+ int err;
- /* Position the region inside the list according to priority */
- list_for_each(pos, &group->region_list) {
- region2 = list_entry(pos, typeof(*region2), list);
- if (mlxsw_sp_acl_tcam_region_prio(region2) >
- mlxsw_sp_acl_tcam_region_prio(region))
- break;
+ mutex_lock(&group->lock);
+ if (group->region_count == group->tcam->max_group_size) {
+ err = -ENOBUFS;
+ goto err_region_count_check;
+ }
+
+ if (next_region) {
+ /* If the next region is defined, place the new one
+ * before it. The next one is a sibling.
+ */
+ pos = &next_region->list;
+ } else {
+ /* Position the region inside the list according to priority */
+ list_for_each(pos, &group->region_list) {
+ region2 = list_entry(pos, typeof(*region2), list);
+ if (mlxsw_sp_acl_tcam_vregion_prio(region2->vregion) >
+ priority)
+ break;
+ }
}
list_add_tail(&region->list, pos);
+ region->group = group;
+
+ err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+ if (err)
+ goto err_group_update;
+
group->region_count++;
+ mutex_unlock(&group->lock);
+ return 0;
+
+err_group_update:
+ list_del(&region->list);
+err_region_count_check:
+ mutex_unlock(&group->lock);
+ return err;
}
static void
-mlxsw_sp_acl_tcam_group_list_del(struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_sp_acl_tcam_region *region)
+mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_region *region)
{
- group->region_count--;
+ struct mlxsw_sp_acl_tcam_group *group = region->group;
+
+ mutex_lock(&group->lock);
list_del(&region->list);
+ group->region_count--;
+ mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+ mutex_unlock(&group->lock);
}
static int
-mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_sp_acl_tcam_region *region)
+mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ unsigned int priority)
{
+ struct mlxsw_sp_acl_tcam_vregion *vregion2;
+ struct list_head *pos;
int err;
- if (group->region_count == group->tcam->max_group_size)
- return -ENOBUFS;
-
- mlxsw_sp_acl_tcam_group_list_add(group, region);
+ /* Position the vregion inside the list according to priority */
+ list_for_each(pos, &vgroup->vregion_list) {
+ vregion2 = list_entry(pos, typeof(*vregion2), list);
+ if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > priority)
+ break;
+ }
+ list_add_tail(&vregion->list, pos);
- err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+ err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, &vgroup->group,
+ vregion->region,
+ priority, NULL);
if (err)
- goto err_group_update;
- region->group = group;
+ goto err_region_attach;
return 0;
-err_group_update:
- mlxsw_sp_acl_tcam_group_list_del(group, region);
- mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+err_region_attach:
+ list_del(&vregion->list);
return err;
}
static void
-mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_region *region)
+mlxsw_sp_acl_tcam_vgroup_vregion_detach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
{
- struct mlxsw_sp_acl_tcam_group *group = region->group;
-
- mlxsw_sp_acl_tcam_group_list_del(group, region);
- mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+ list_del(&vregion->list);
+ if (vregion->region2)
+ mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp,
+ vregion->region2);
+ mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, vregion->region);
}
-static struct mlxsw_sp_acl_tcam_region *
-mlxsw_sp_acl_tcam_group_region_find(struct mlxsw_sp_acl_tcam_group *group,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage,
- bool *p_need_split)
+static struct mlxsw_sp_acl_tcam_vregion *
+mlxsw_sp_acl_tcam_vgroup_vregion_find(struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage,
+ bool *p_need_split)
{
- struct mlxsw_sp_acl_tcam_region *region, *region2;
+ struct mlxsw_sp_acl_tcam_vregion *vregion, *vregion2;
struct list_head *pos;
bool issubset;
- list_for_each(pos, &group->region_list) {
- region = list_entry(pos, typeof(*region), list);
+ list_for_each(pos, &vgroup->vregion_list) {
+ vregion = list_entry(pos, typeof(*vregion), list);
/* First, check if the requested priority does not rather belong
- * under some of the next regions.
+ * under some of the next vregions.
*/
- if (pos->next != &group->region_list) { /* not last */
- region2 = list_entry(pos->next, typeof(*region2), list);
- if (priority >= mlxsw_sp_acl_tcam_region_prio(region2))
+ if (pos->next != &vgroup->vregion_list) { /* not last */
+ vregion2 = list_entry(pos->next, typeof(*vregion2),
+ list);
+ if (priority >=
+ mlxsw_sp_acl_tcam_vregion_prio(vregion2))
continue;
}
- issubset = mlxsw_afk_key_info_subset(region->key_info, elusage);
+ issubset = mlxsw_afk_key_info_subset(vregion->key_info,
+ elusage);
/* If requested element usage would not fit and the priority
- * is lower than the currently inspected region we cannot
- * use this region, so return NULL to indicate new region has
+ * is lower than the currently inspected vregion we cannot
+ * use this region, so return NULL to indicate new vregion has
* to be created.
*/
if (!issubset &&
- priority < mlxsw_sp_acl_tcam_region_prio(region))
+ priority < mlxsw_sp_acl_tcam_vregion_prio(vregion))
return NULL;
/* If requested element usage would not fit and the priority
- * is higher than the currently inspected region we cannot
- * use this region. There is still some hope that the next
- * region would be the fit. So let it be processed and
+ * is higher than the currently inspected vregion we cannot
+ * use this vregion. There is still some hope that the next
+ * vregion would be the fit. So let it be processed and
* eventually break at the check right above this.
*/
if (!issubset &&
- priority > mlxsw_sp_acl_tcam_region_max_prio(region))
+ priority > mlxsw_sp_acl_tcam_vregion_max_prio(vregion))
continue;
- /* Indicate if the region needs to be split in order to add
+ /* Indicate if the vregion needs to be split in order to add
* the requested priority. Split is needed when requested
- * element usage won't fit into the found region.
+ * element usage won't fit into the found vregion.
*/
*p_need_split = !issubset;
- return region;
+ return vregion;
}
- return NULL; /* New region has to be created. */
+ return NULL; /* New vregion has to be created. */
}
static void
-mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_afk_element_usage *elusage,
- struct mlxsw_afk_element_usage *out)
+mlxsw_sp_acl_tcam_vgroup_use_patterns(struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ struct mlxsw_afk_element_usage *elusage,
+ struct mlxsw_afk_element_usage *out)
{
const struct mlxsw_sp_acl_tcam_pattern *pattern;
int i;
@@ -430,14 +588,14 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
/* In case the template is set, we don't have to look up the pattern
* and just use the template.
*/
- if (group->tmplt_elusage_set) {
- memcpy(out, &group->tmplt_elusage, sizeof(*out));
+ if (vgroup->tmplt_elusage_set) {
+ memcpy(out, &vgroup->tmplt_elusage, sizeof(*out));
WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out));
return;
}
- for (i = 0; i < group->patterns_count; i++) {
- pattern = &group->patterns[i];
+ for (i = 0; i < vgroup->patterns_count; i++) {
+ pattern = &vgroup->patterns[i];
mlxsw_afk_element_usage_fill(out, pattern->elements,
pattern->elements_count);
if (mlxsw_afk_element_usage_subset(elusage, out))
@@ -511,24 +669,19 @@ mlxsw_sp_acl_tcam_region_disable(struct mlxsw_sp *mlxsw_sp,
static struct mlxsw_sp_acl_tcam_region *
mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam *tcam,
- struct mlxsw_afk_element_usage *elusage)
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ void *hints_priv)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
struct mlxsw_sp_acl_tcam_region *region;
int err;
region = kzalloc(sizeof(*region) + ops->region_priv_size, GFP_KERNEL);
if (!region)
return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&region->chunk_list);
region->mlxsw_sp = mlxsw_sp;
-
- region->key_info = mlxsw_afk_key_info_get(afk, elusage);
- if (IS_ERR(region->key_info)) {
- err = PTR_ERR(region->key_info);
- goto err_key_info_get;
- }
+ region->vregion = vregion;
+ region->key_info = vregion->key_info;
err = mlxsw_sp_acl_tcam_region_id_get(tcam, &region->id);
if (err)
@@ -547,7 +700,8 @@ mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_tcam_region_enable;
- err = ops->region_init(mlxsw_sp, region->priv, tcam->priv, region);
+ err = ops->region_init(mlxsw_sp, region->priv, tcam->priv,
+ region, hints_priv);
if (err)
goto err_tcam_region_init;
@@ -561,8 +715,6 @@ err_tcam_region_alloc:
err_tcam_region_associate:
mlxsw_sp_acl_tcam_region_id_put(tcam, region->id);
err_region_id_get:
- mlxsw_afk_key_info_put(region->key_info);
-err_key_info_get:
kfree(region);
return ERR_PTR(err);
}
@@ -576,220 +728,415 @@ mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp,
ops->region_fini(mlxsw_sp, region->priv);
mlxsw_sp_acl_tcam_region_disable(mlxsw_sp, region);
mlxsw_sp_acl_tcam_region_free(mlxsw_sp, region);
- mlxsw_sp_acl_tcam_region_id_put(region->group->tcam, region->id);
- mlxsw_afk_key_info_put(region->key_info);
+ mlxsw_sp_acl_tcam_region_id_put(region->group->tcam,
+ region->id);
kfree(region);
}
-static int
-mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage,
- struct mlxsw_sp_acl_tcam_chunk *chunk)
+static void
+mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion *vregion)
{
- struct mlxsw_sp_acl_tcam_region *region;
- bool region_created = false;
- bool need_split;
- int err;
+ unsigned long interval = vregion->tcam->vregion_rehash_intrvl;
+
+ if (!interval)
+ return;
+ mlxsw_core_schedule_dw(&vregion->rehash.dw,
+ msecs_to_jiffies(interval));
+}
+
+static void
+mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ int *credits);
- region = mlxsw_sp_acl_tcam_group_region_find(group, priority, elusage,
- &need_split);
- if (region && need_split) {
- /* According to priority, the chunk should belong to an
- * existing region. However, this chunk needs elements
- * that region does not contain. We need to split the existing
- * region into two and create a new region for this chunk
- * in between. This is not supported now.
+static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
+{
+ struct mlxsw_sp_acl_tcam_vregion *vregion =
+ container_of(work, struct mlxsw_sp_acl_tcam_vregion,
+ rehash.dw.work);
+ int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
+
+ mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
+ if (credits < 0)
+ /* Rehash gone out of credits so it was interrupted.
+ * Schedule the work as soon as possible to continue.
*/
- return -EOPNOTSUPP;
- }
- if (!region) {
- struct mlxsw_afk_element_usage region_elusage;
-
- mlxsw_sp_acl_tcam_group_use_patterns(group, elusage,
- &region_elusage);
- region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, group->tcam,
- &region_elusage);
- if (IS_ERR(region))
- return PTR_ERR(region);
- region_created = true;
+ mlxsw_core_schedule_dw(&vregion->rehash.dw, 0);
+ else
+ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
+}
+
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+{
+ struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
+
+ /* If a rule was added or deleted from vchunk which is currently
+ * under rehash migration, we have to reset the ventry pointers
+ * to make sure all rules are properly migrated.
+ */
+ if (vregion->rehash.ctx.current_vchunk == vchunk) {
+ vregion->rehash.ctx.start_ventry = NULL;
+ vregion->rehash.ctx.stop_ventry = NULL;
}
+}
- chunk->region = region;
- list_add_tail(&chunk->list, &region->chunk_list);
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *vregion)
+{
+ /* If a chunk was added or deleted from vregion we have to reset
+ * the current chunk pointer to make sure all chunks
+ * are properly migrated.
+ */
+ vregion->rehash.ctx.current_vchunk = NULL;
+}
- if (!region_created)
- return 0;
+static struct mlxsw_sp_acl_tcam_vregion *
+mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
+ struct mlxsw_sp_acl_tcam *tcam = vgroup->group.tcam;
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+ int err;
+
+ vregion = kzalloc(sizeof(*vregion), GFP_KERNEL);
+ if (!vregion)
+ return ERR_PTR(-ENOMEM);
+ INIT_LIST_HEAD(&vregion->vchunk_list);
+ mutex_init(&vregion->lock);
+ vregion->tcam = tcam;
+ vregion->mlxsw_sp = mlxsw_sp;
+ vregion->vgroup = vgroup;
+ vregion->ref_count = 1;
+
+ vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
+ if (IS_ERR(vregion->key_info)) {
+ err = PTR_ERR(vregion->key_info);
+ goto err_key_info_get;
+ }
- err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, group, region);
+ vregion->region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, tcam,
+ vregion, NULL);
+ if (IS_ERR(vregion->region)) {
+ err = PTR_ERR(vregion->region);
+ goto err_region_create;
+ }
+
+ err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup, vregion,
+ priority);
if (err)
- goto err_group_region_attach;
+ goto err_vgroup_vregion_attach;
+
+ if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+ /* Create the delayed work for vregion periodic rehash */
+ INIT_DELAYED_WORK(&vregion->rehash.dw,
+ mlxsw_sp_acl_tcam_vregion_rehash_work);
+ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
+ mutex_lock(&tcam->lock);
+ list_add_tail(&vregion->tlist, &tcam->vregion_list);
+ mutex_unlock(&tcam->lock);
+ }
- return 0;
+ return vregion;
-err_group_region_attach:
- mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region);
- return err;
+err_vgroup_vregion_attach:
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
+err_region_create:
+ mlxsw_afk_key_info_put(vregion->key_info);
+err_key_info_get:
+ kfree(vregion);
+ return ERR_PTR(err);
}
static void
-mlxsw_sp_acl_tcam_chunk_deassoc(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_chunk *chunk)
+mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup = vregion->vgroup;
+ struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
+
+ if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+ mutex_lock(&tcam->lock);
+ list_del(&vregion->tlist);
+ mutex_unlock(&tcam->lock);
+ cancel_delayed_work_sync(&vregion->rehash.dw);
+ }
+ mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
+ if (vregion->region2)
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2);
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
+ mlxsw_afk_key_info_put(vregion->key_info);
+ mutex_destroy(&vregion->lock);
+ kfree(vregion);
+}
+
+u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ u32 vregion_rehash_intrvl;
+
+ if (WARN_ON(!ops->region_rehash_hints_get))
+ return 0;
+ vregion_rehash_intrvl = tcam->vregion_rehash_intrvl;
+ return vregion_rehash_intrvl;
+}
+
+int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam,
+ u32 val)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+
+ if (val < MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN && val)
+ return -EINVAL;
+ if (WARN_ON(!ops->region_rehash_hints_get))
+ return -EOPNOTSUPP;
+ tcam->vregion_rehash_intrvl = val;
+ mutex_lock(&tcam->lock);
+ list_for_each_entry(vregion, &tcam->vregion_list, tlist) {
+ if (val)
+ mlxsw_core_schedule_dw(&vregion->rehash.dw, 0);
+ else
+ cancel_delayed_work_sync(&vregion->rehash.dw);
+ }
+ mutex_unlock(&tcam->lock);
+ return 0;
+}
+
+static struct mlxsw_sp_acl_tcam_vregion *
+mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage)
{
- struct mlxsw_sp_acl_tcam_region *region = chunk->region;
+ struct mlxsw_afk_element_usage vregion_elusage;
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+ bool need_split;
- list_del(&chunk->list);
- if (list_empty(&region->chunk_list)) {
- mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, region);
- mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region);
+ vregion = mlxsw_sp_acl_tcam_vgroup_vregion_find(vgroup, priority,
+ elusage, &need_split);
+ if (vregion) {
+ if (need_split) {
+ /* According to priority, new vchunk should belong to
+ * an existing vregion. However, this vchunk needs
+ * elements that vregion does not contain. We need
+ * to split the existing vregion into two and create
+ * a new vregion for the new vchunk in between.
+ * This is not supported now.
+ */
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ vregion->ref_count++;
+ return vregion;
}
+
+ mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage,
+ &vregion_elusage);
+
+ return mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, vgroup, priority,
+ &vregion_elusage);
+}
+
+static void
+mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
+{
+ if (--vregion->ref_count)
+ return;
+ mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
}
static struct mlxsw_sp_acl_tcam_chunk *
mlxsw_sp_acl_tcam_chunk_create(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage)
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+ struct mlxsw_sp_acl_tcam_region *region)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
struct mlxsw_sp_acl_tcam_chunk *chunk;
+
+ chunk = kzalloc(sizeof(*chunk) + ops->chunk_priv_size, GFP_KERNEL);
+ if (!chunk)
+ return ERR_PTR(-ENOMEM);
+ chunk->vchunk = vchunk;
+ chunk->region = region;
+
+ ops->chunk_init(region->priv, chunk->priv, vchunk->priority);
+ return chunk;
+}
+
+static void
+mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_chunk *chunk)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+
+ ops->chunk_fini(chunk->priv);
+ kfree(chunk);
+}
+
+static struct mlxsw_sp_acl_tcam_vchunk *
+mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage)
+{
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
int err;
if (priority == MLXSW_SP_ACL_TCAM_CATCHALL_PRIO)
return ERR_PTR(-EINVAL);
- chunk = kzalloc(sizeof(*chunk) + ops->chunk_priv_size, GFP_KERNEL);
- if (!chunk)
+ vchunk = kzalloc(sizeof(*vchunk), GFP_KERNEL);
+ if (!vchunk)
return ERR_PTR(-ENOMEM);
- chunk->priority = priority;
- chunk->group = group;
- chunk->ref_count = 1;
-
- err = mlxsw_sp_acl_tcam_chunk_assoc(mlxsw_sp, group, priority,
- elusage, chunk);
- if (err)
- goto err_chunk_assoc;
+ INIT_LIST_HEAD(&vchunk->ventry_list);
+ vchunk->priority = priority;
+ vchunk->vgroup = vgroup;
+ vchunk->ref_count = 1;
+
+ vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup,
+ priority, elusage);
+ if (IS_ERR(vregion)) {
+ err = PTR_ERR(vregion);
+ goto err_vregion_get;
+ }
- ops->chunk_init(chunk->region->priv, chunk->priv, priority);
+ vchunk->vregion = vregion;
- err = rhashtable_insert_fast(&group->chunk_ht, &chunk->ht_node,
- mlxsw_sp_acl_tcam_chunk_ht_params);
+ err = rhashtable_insert_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
+ mlxsw_sp_acl_tcam_vchunk_ht_params);
if (err)
goto err_rhashtable_insert;
- return chunk;
+ mutex_lock(&vregion->lock);
+ vchunk->chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk,
+ vchunk->vregion->region);
+ if (IS_ERR(vchunk->chunk)) {
+ mutex_unlock(&vregion->lock);
+ err = PTR_ERR(vchunk->chunk);
+ goto err_chunk_create;
+ }
+ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
+ list_add_tail(&vchunk->list, &vregion->vchunk_list);
+ mutex_unlock(&vregion->lock);
+
+ return vchunk;
+
+err_chunk_create:
+ rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
+ mlxsw_sp_acl_tcam_vchunk_ht_params);
err_rhashtable_insert:
- ops->chunk_fini(chunk->priv);
- mlxsw_sp_acl_tcam_chunk_deassoc(mlxsw_sp, chunk);
-err_chunk_assoc:
- kfree(chunk);
+ mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vregion);
+err_vregion_get:
+ kfree(vchunk);
return ERR_PTR(err);
}
static void
-mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_chunk *chunk)
+mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk)
{
- const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_sp_acl_tcam_group *group = chunk->group;
-
- rhashtable_remove_fast(&group->chunk_ht, &chunk->ht_node,
- mlxsw_sp_acl_tcam_chunk_ht_params);
- ops->chunk_fini(chunk->priv);
- mlxsw_sp_acl_tcam_chunk_deassoc(mlxsw_sp, chunk);
- kfree(chunk);
+ struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
+
+ mutex_lock(&vregion->lock);
+ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
+ list_del(&vchunk->list);
+ if (vchunk->chunk2)
+ mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
+ mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
+ mutex_unlock(&vregion->lock);
+ rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
+ mlxsw_sp_acl_tcam_vchunk_ht_params);
+ mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion);
+ kfree(vchunk);
}
-static struct mlxsw_sp_acl_tcam_chunk *
-mlxsw_sp_acl_tcam_chunk_get(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage)
+static struct mlxsw_sp_acl_tcam_vchunk *
+mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage)
{
- struct mlxsw_sp_acl_tcam_chunk *chunk;
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
- chunk = rhashtable_lookup_fast(&group->chunk_ht, &priority,
- mlxsw_sp_acl_tcam_chunk_ht_params);
- if (chunk) {
- if (WARN_ON(!mlxsw_afk_key_info_subset(chunk->region->key_info,
+ vchunk = rhashtable_lookup_fast(&vgroup->vchunk_ht, &priority,
+ mlxsw_sp_acl_tcam_vchunk_ht_params);
+ if (vchunk) {
+ if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info,
elusage)))
return ERR_PTR(-EINVAL);
- chunk->ref_count++;
- return chunk;
+ vchunk->ref_count++;
+ return vchunk;
}
- return mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, group,
- priority, elusage);
+ return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup,
+ priority, elusage);
}
-static void mlxsw_sp_acl_tcam_chunk_put(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_chunk *chunk)
+static void
+mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk)
{
- if (--chunk->ref_count)
+ if (--vchunk->ref_count)
return;
- mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, chunk);
-}
-
-static size_t mlxsw_sp_acl_tcam_entry_priv_size(struct mlxsw_sp *mlxsw_sp)
-{
- const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
-
- return ops->entry_priv_size;
+ mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk);
}
-static int mlxsw_sp_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_sp_acl_tcam_entry *entry,
- struct mlxsw_sp_acl_rule_info *rulei)
+static struct mlxsw_sp_acl_tcam_entry *
+mlxsw_sp_acl_tcam_entry_create(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ struct mlxsw_sp_acl_tcam_chunk *chunk)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_sp_acl_tcam_chunk *chunk;
- struct mlxsw_sp_acl_tcam_region *region;
+ struct mlxsw_sp_acl_tcam_entry *entry;
int err;
- chunk = mlxsw_sp_acl_tcam_chunk_get(mlxsw_sp, group, rulei->priority,
- &rulei->values.elusage);
- if (IS_ERR(chunk))
- return PTR_ERR(chunk);
-
- region = chunk->region;
+ entry = kzalloc(sizeof(*entry) + ops->entry_priv_size, GFP_KERNEL);
+ if (!entry)
+ return ERR_PTR(-ENOMEM);
+ entry->ventry = ventry;
+ entry->chunk = chunk;
- err = ops->entry_add(mlxsw_sp, region->priv, chunk->priv,
- entry->priv, rulei);
+ err = ops->entry_add(mlxsw_sp, chunk->region->priv, chunk->priv,
+ entry->priv, ventry->rulei);
if (err)
goto err_entry_add;
- entry->chunk = chunk;
- return 0;
+ return entry;
err_entry_add:
- mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk);
- return err;
+ kfree(entry);
+ return ERR_PTR(err);
}
-static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_entry *entry)
+static void mlxsw_sp_acl_tcam_entry_destroy(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_entry *entry)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk;
- struct mlxsw_sp_acl_tcam_region *region = chunk->region;
- ops->entry_del(mlxsw_sp, region->priv, chunk->priv, entry->priv);
- mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk);
+ ops->entry_del(mlxsw_sp, entry->chunk->region->priv,
+ entry->chunk->priv, entry->priv);
+ kfree(entry);
}
static int
mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_region *region,
struct mlxsw_sp_acl_tcam_entry *entry,
struct mlxsw_sp_acl_rule_info *rulei)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk;
- struct mlxsw_sp_acl_tcam_region *region = chunk->region;
- return ops->entry_action_replace(mlxsw_sp, region->priv, chunk->priv,
+ return ops->entry_action_replace(mlxsw_sp, region->priv,
entry->priv, rulei);
}
@@ -799,13 +1146,377 @@ mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
bool *activity)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
- struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk;
- struct mlxsw_sp_acl_tcam_region *region = chunk->region;
- return ops->entry_activity_get(mlxsw_sp, region->priv,
+ return ops->entry_activity_get(mlxsw_sp, entry->chunk->region->priv,
entry->priv, activity);
}
+static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ struct mlxsw_sp_acl_rule_info *rulei)
+{
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ int err;
+
+ vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, vgroup, rulei->priority,
+ &rulei->values.elusage);
+ if (IS_ERR(vchunk))
+ return PTR_ERR(vchunk);
+
+ ventry->vchunk = vchunk;
+ ventry->rulei = rulei;
+ vregion = vchunk->vregion;
+
+ mutex_lock(&vregion->lock);
+ ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry,
+ vchunk->chunk);
+ if (IS_ERR(ventry->entry)) {
+ mutex_unlock(&vregion->lock);
+ err = PTR_ERR(ventry->entry);
+ goto err_entry_create;
+ }
+
+ list_add_tail(&ventry->list, &vchunk->ventry_list);
+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk);
+ mutex_unlock(&vregion->lock);
+
+ return 0;
+
+err_entry_create:
+ mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk);
+ return err;
+}
+
+static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry)
+{
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk;
+ struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
+
+ mutex_lock(&vregion->lock);
+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk);
+ list_del(&ventry->list);
+ mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
+ mutex_unlock(&vregion->lock);
+ mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk);
+}
+
+static int
+mlxsw_sp_acl_tcam_ventry_action_replace(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ struct mlxsw_sp_acl_rule_info *rulei)
+{
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk;
+
+ return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp,
+ vchunk->vregion->region,
+ ventry->entry, rulei);
+}
+
+static int
+mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ bool *activity)
+{
+ return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
+ ventry->entry, activity);
+}
+
+static int
+mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ struct mlxsw_sp_acl_tcam_chunk *chunk,
+ int *credits)
+{
+ struct mlxsw_sp_acl_tcam_entry *new_entry;
+
+ /* First check if the entry is not already where we want it to be. */
+ if (ventry->entry->chunk == chunk)
+ return 0;
+
+ if (--(*credits) < 0)
+ return 0;
+
+ new_entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk);
+ if (IS_ERR(new_entry))
+ return PTR_ERR(new_entry);
+ mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
+ ventry->entry = new_entry;
+ return 0;
+}
+
+static int
+mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+ struct mlxsw_sp_acl_tcam_region *region,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+ struct mlxsw_sp_acl_tcam_chunk *new_chunk;
+
+ new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
+ if (IS_ERR(new_chunk)) {
+ if (ctx->this_is_rollback)
+ vchunk->vregion->failed_rollback = true;
+ return PTR_ERR(new_chunk);
+ }
+ vchunk->chunk2 = vchunk->chunk;
+ vchunk->chunk = new_chunk;
+ ctx->current_vchunk = vchunk;
+ ctx->start_ventry = NULL;
+ ctx->stop_ventry = NULL;
+ return 0;
+}
+
+static void
+mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+ mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
+ vchunk->chunk2 = NULL;
+ ctx->current_vchunk = NULL;
+}
+
+static int
+mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+ struct mlxsw_sp_acl_tcam_region *region,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+ int *credits)
+{
+ struct mlxsw_sp_acl_tcam_ventry *ventry;
+ int err;
+
+ if (vchunk->chunk->region != region) {
+ err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk,
+ region, ctx);
+ if (err)
+ return err;
+ } else if (!vchunk->chunk2) {
+ /* The chunk is already as it should be, nothing to do. */
+ return 0;
+ }
+
+ /* If the migration got interrupted, we have the ventry to start from
+ * stored in context.
+ */
+ if (ctx->start_ventry)
+ ventry = ctx->start_ventry;
+ else
+ ventry = list_first_entry(&vchunk->ventry_list,
+ typeof(*ventry), list);
+
+ list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
+ /* During rollback, once we reach the ventry that failed
+ * to migrate, we are done.
+ */
+ if (ventry == ctx->stop_ventry)
+ break;
+
+ err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
+ vchunk->chunk, credits);
+ if (err) {
+ if (ctx->this_is_rollback)
+ return err;
+ /* Swap the chunk and chunk2 pointers so the follow-up
+ * rollback call will see the original chunk pointer
+ * in vchunk->chunk.
+ */
+ swap(vchunk->chunk, vchunk->chunk2);
+ /* The rollback has to be done from beginning of the
+ * chunk, that is why we have to null the start_ventry.
+ * However, we know where to stop the rollback,
+ * at the current ventry.
+ */
+ ctx->start_ventry = NULL;
+ ctx->stop_ventry = ventry;
+ return err;
+ } else if (*credits < 0) {
+ /* We are out of credits, the rest of the ventries
+ * will be migrated later. Save the ventry
+ * which we ended with.
+ */
+ ctx->start_ventry = ventry;
+ return 0;
+ }
+ }
+
+ mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
+ return 0;
+}
+
+static int
+mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+ int *credits)
+{
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ int err;
+
+ /* If the migration got interrupted, we have the vchunk
+ * we are working on stored in context.
+ */
+ if (ctx->current_vchunk)
+ vchunk = ctx->current_vchunk;
+ else
+ vchunk = list_first_entry(&vregion->vchunk_list,
+ typeof(*vchunk), list);
+
+ list_for_each_entry_from(vchunk, &vregion->vchunk_list, list) {
+ err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
+ vregion->region,
+ ctx, credits);
+ if (err || *credits < 0)
+ return err;
+ }
+ return 0;
+}
+
+static int
+mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+ int *credits)
+{
+ int err, err2;
+
+ trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
+ mutex_lock(&vregion->lock);
+ err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+ ctx, credits);
+ if (err) {
+ /* In case migration was not successful, we need to swap
+ * so the original region pointer is assigned again
+ * to vregion->region.
+ */
+ swap(vregion->region, vregion->region2);
+ ctx->current_vchunk = NULL;
+ ctx->this_is_rollback = true;
+ err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+ ctx, credits);
+ if (err2)
+ vregion->failed_rollback = true;
+ }
+ mutex_unlock(&vregion->lock);
+ trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
+ return err;
+}
+
+static bool
+mlxsw_sp_acl_tcam_vregion_rehash_in_progress(const struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+ return ctx->hints_priv;
+}
+
+static int
+mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
+ struct mlxsw_sp_acl_tcam_region *new_region;
+ void *hints_priv;
+ int err;
+
+ trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion);
+ if (vregion->failed_rollback)
+ return -EBUSY;
+
+ hints_priv = ops->region_rehash_hints_get(vregion->region->priv);
+ if (IS_ERR(hints_priv))
+ return PTR_ERR(hints_priv);
+
+ new_region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
+ vregion, hints_priv);
+ if (IS_ERR(new_region)) {
+ err = PTR_ERR(new_region);
+ goto err_region_create;
+ }
+
+ /* vregion->region contains the pointer to the new region
+ * we are going to migrate to.
+ */
+ vregion->region2 = vregion->region;
+ vregion->region = new_region;
+ err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
+ vregion->region2->group,
+ new_region, priority,
+ vregion->region2);
+ if (err)
+ goto err_group_region_attach;
+
+ ctx->hints_priv = hints_priv;
+ ctx->this_is_rollback = false;
+
+ return 0;
+
+err_group_region_attach:
+ vregion->region = vregion->region2;
+ vregion->region2 = NULL;
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, new_region);
+err_region_create:
+ ops->region_rehash_hints_put(hints_priv);
+ return err;
+}
+
+static void
+mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+ struct mlxsw_sp_acl_tcam_region *unused_region = vregion->region2;
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+
+ if (!vregion->failed_rollback) {
+ vregion->region2 = NULL;
+ mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region);
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region);
+ }
+ ops->region_rehash_hints_put(ctx->hints_priv);
+ ctx->hints_priv = NULL;
+}
+
+static void
+mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ int *credits)
+{
+ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+ int err;
+
+ /* Check if the previous rehash work was interrupted
+ * which means we have to continue it now.
+ * If not, start a new rehash.
+ */
+ if (!mlxsw_sp_acl_tcam_vregion_rehash_in_progress(ctx)) {
+ err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp,
+ vregion, ctx);
+ if (err) {
+ if (err != -EAGAIN)
+ dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
+ return;
+ }
+ }
+
+ err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
+ ctx, credits);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+ if (vregion->failed_rollback) {
+ trace_mlxsw_sp_acl_tcam_vregion_rehash_dis(mlxsw_sp,
+ vregion);
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to rollback during vregion migration fail\n");
+ }
+ }
+
+ if (*credits >= 0)
+ mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
+}
+
static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {
MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
MLXSW_AFK_ELEMENT_DMAC_32_47,
@@ -856,20 +1567,11 @@ static const struct mlxsw_sp_acl_tcam_pattern mlxsw_sp_acl_tcam_patterns[] = {
ARRAY_SIZE(mlxsw_sp_acl_tcam_patterns)
struct mlxsw_sp_acl_tcam_flower_ruleset {
- struct mlxsw_sp_acl_tcam_group group;
+ struct mlxsw_sp_acl_tcam_vgroup vgroup;
};
struct mlxsw_sp_acl_tcam_flower_rule {
- struct mlxsw_sp_acl_tcam_entry entry;
-};
-
-struct mlxsw_sp_acl_tcam_mr_ruleset {
- struct mlxsw_sp_acl_tcam_chunk *chunk;
- struct mlxsw_sp_acl_tcam_group group;
-};
-
-struct mlxsw_sp_acl_tcam_mr_rule {
- struct mlxsw_sp_acl_tcam_entry entry;
+ struct mlxsw_sp_acl_tcam_ventry ventry;
};
static int
@@ -880,10 +1582,10 @@ mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
- mlxsw_sp_acl_tcam_patterns,
- MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ return mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
+ mlxsw_sp_acl_tcam_patterns,
+ MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+ tmplt_elusage, true);
}
static void
@@ -892,7 +1594,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_del(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
}
static int
@@ -903,7 +1605,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->group,
+ return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->vgroup.group,
mlxsw_sp_port, ingress);
}
@@ -915,7 +1617,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_unbind(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->group,
+ mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->vgroup.group,
mlxsw_sp_port, ingress);
}
@@ -924,13 +1626,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_group_id(void *ruleset_priv)
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_id(&ruleset->group);
-}
-
-static size_t mlxsw_sp_acl_tcam_flower_rule_priv_size(struct mlxsw_sp *mlxsw_sp)
-{
- return sizeof(struct mlxsw_sp_acl_tcam_flower_rule) +
- mlxsw_sp_acl_tcam_entry_priv_size(mlxsw_sp);
+ return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group);
}
static int
@@ -941,8 +1637,8 @@ mlxsw_sp_acl_tcam_flower_rule_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_entry_add(mlxsw_sp, &ruleset->group,
- &rule->entry, rulei);
+ return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup,
+ &rule->ventry, rulei);
}
static void
@@ -950,12 +1646,11 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
{
struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv;
- mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry);
+ mlxsw_sp_acl_tcam_ventry_del(mlxsw_sp, &rule->ventry);
}
static int
mlxsw_sp_acl_tcam_flower_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
- void *ruleset_priv,
void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei)
{
@@ -968,8 +1663,8 @@ mlxsw_sp_acl_tcam_flower_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, &rule->entry,
- activity);
+ return mlxsw_sp_acl_tcam_ventry_activity_get(mlxsw_sp, &rule->ventry,
+ activity);
}
static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
@@ -979,13 +1674,22 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
.ruleset_bind = mlxsw_sp_acl_tcam_flower_ruleset_bind,
.ruleset_unbind = mlxsw_sp_acl_tcam_flower_ruleset_unbind,
.ruleset_group_id = mlxsw_sp_acl_tcam_flower_ruleset_group_id,
- .rule_priv_size = mlxsw_sp_acl_tcam_flower_rule_priv_size,
+ .rule_priv_size = sizeof(struct mlxsw_sp_acl_tcam_flower_rule),
.rule_add = mlxsw_sp_acl_tcam_flower_rule_add,
.rule_del = mlxsw_sp_acl_tcam_flower_rule_del,
.rule_action_replace = mlxsw_sp_acl_tcam_flower_rule_action_replace,
.rule_activity_get = mlxsw_sp_acl_tcam_flower_rule_activity_get,
};
+struct mlxsw_sp_acl_tcam_mr_ruleset {
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ struct mlxsw_sp_acl_tcam_vgroup vgroup;
+};
+
+struct mlxsw_sp_acl_tcam_mr_rule {
+ struct mlxsw_sp_acl_tcam_ventry ventry;
+};
+
static int
mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam *tcam,
@@ -995,10 +1699,10 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
int err;
- err = mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
- mlxsw_sp_acl_tcam_patterns,
- MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ err = mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
+ mlxsw_sp_acl_tcam_patterns,
+ MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+ tmplt_elusage, false);
if (err)
return err;
@@ -1008,17 +1712,18 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
* specific ACL Group ID which must exist in HW before multicast router
* is initialized.
*/
- ruleset->chunk = mlxsw_sp_acl_tcam_chunk_get(mlxsw_sp, &ruleset->group,
- 1, tmplt_elusage);
- if (IS_ERR(ruleset->chunk)) {
- err = PTR_ERR(ruleset->chunk);
+ ruleset->vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp,
+ &ruleset->vgroup, 1,
+ tmplt_elusage);
+ if (IS_ERR(ruleset->vchunk)) {
+ err = PTR_ERR(ruleset->vchunk);
goto err_chunk_get;
}
return 0;
err_chunk_get:
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
return err;
}
@@ -1027,8 +1732,8 @@ mlxsw_sp_acl_tcam_mr_ruleset_del(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv)
{
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
- mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, ruleset->chunk);
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, ruleset->vchunk);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
}
static int
@@ -1053,13 +1758,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_group_id(void *ruleset_priv)
{
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_id(&ruleset->group);
-}
-
-static size_t mlxsw_sp_acl_tcam_mr_rule_priv_size(struct mlxsw_sp *mlxsw_sp)
-{
- return sizeof(struct mlxsw_sp_acl_tcam_mr_rule) +
- mlxsw_sp_acl_tcam_entry_priv_size(mlxsw_sp);
+ return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group);
}
static int
@@ -1070,8 +1769,8 @@ mlxsw_sp_acl_tcam_mr_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_entry_add(mlxsw_sp, &ruleset->group,
- &rule->entry, rulei);
+ return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup,
+ &rule->ventry, rulei);
}
static void
@@ -1079,19 +1778,18 @@ mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
{
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
- mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry);
+ mlxsw_sp_acl_tcam_ventry_del(mlxsw_sp, &rule->ventry);
}
static int
mlxsw_sp_acl_tcam_mr_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
- void *ruleset_priv, void *rule_priv,
+ void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei)
{
- struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, &ruleset->group,
- &rule->entry, rulei);
+ return mlxsw_sp_acl_tcam_ventry_action_replace(mlxsw_sp, &rule->ventry,
+ rulei);
}
static int
@@ -1100,8 +1798,8 @@ mlxsw_sp_acl_tcam_mr_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, &rule->entry,
- activity);
+ return mlxsw_sp_acl_tcam_ventry_activity_get(mlxsw_sp, &rule->ventry,
+ activity);
}
static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = {
@@ -1111,7 +1809,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = {
.ruleset_bind = mlxsw_sp_acl_tcam_mr_ruleset_bind,
.ruleset_unbind = mlxsw_sp_acl_tcam_mr_ruleset_unbind,
.ruleset_group_id = mlxsw_sp_acl_tcam_mr_ruleset_group_id,
- .rule_priv_size = mlxsw_sp_acl_tcam_mr_rule_priv_size,
+ .rule_priv_size = sizeof(struct mlxsw_sp_acl_tcam_mr_rule),
.rule_add = mlxsw_sp_acl_tcam_mr_rule_add,
.rule_del = mlxsw_sp_acl_tcam_mr_rule_del,
.rule_action_replace = mlxsw_sp_acl_tcam_mr_rule_action_replace,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
index 0f1a9dee63de..5965913565a5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
@@ -17,6 +17,9 @@ struct mlxsw_sp_acl_tcam {
unsigned long *used_groups; /* bit array */
unsigned int max_groups;
unsigned int max_group_size;
+ struct mutex lock; /* guards vregion list */
+ struct list_head vregion_list;
+ u32 vregion_rehash_intrvl; /* ms */
unsigned long priv[0];
/* priv has to be always the last item */
};
@@ -26,6 +29,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam *tcam);
void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam *tcam);
+u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam);
+int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam,
+ u32 val);
int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
u32 *priority, bool fillup_priority);
@@ -43,13 +51,12 @@ struct mlxsw_sp_acl_profile_ops {
struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress);
u16 (*ruleset_group_id)(void *ruleset_priv);
- size_t (*rule_priv_size)(struct mlxsw_sp *mlxsw_sp);
+ size_t rule_priv_size;
int (*rule_add)(struct mlxsw_sp *mlxsw_sp,
void *ruleset_priv, void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei);
void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
- int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp,
- void *ruleset_priv, void *rule_priv,
+ int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei);
int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
bool *activity);
@@ -68,11 +75,12 @@ mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp,
(MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE)
struct mlxsw_sp_acl_tcam_group;
+struct mlxsw_sp_acl_tcam_vregion;
struct mlxsw_sp_acl_tcam_region {
- struct list_head list; /* Member of a TCAM group */
- struct list_head chunk_list; /* List of chunks under this region */
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
struct mlxsw_sp_acl_tcam_group *group;
+ struct list_head list; /* Member of a TCAM group */
enum mlxsw_reg_ptar_key_type key_type;
u16 id; /* ACL ID and region ID - they are same */
char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN];
@@ -126,7 +134,6 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ctcam_entry *centry);
int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ctcam_region *cregion,
- struct mlxsw_sp_acl_ctcam_chunk *cchunk,
struct mlxsw_sp_acl_ctcam_entry *centry,
struct mlxsw_sp_acl_rule_info *rulei);
static inline unsigned int
@@ -163,9 +170,9 @@ struct mlxsw_sp_acl_atcam_region {
};
struct mlxsw_sp_acl_atcam_entry_ht_key {
- char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
- * minus delta bits.
- */
+ char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded
+ * key.
+ */
u8 erp_id;
};
@@ -177,7 +184,9 @@ struct mlxsw_sp_acl_atcam_entry {
struct rhash_head ht_node;
struct list_head list; /* Member in entries_list */
struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
- char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
+ char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
+ * minus delta bits.
+ */
struct {
u16 start;
u8 mask;
@@ -207,6 +216,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam,
struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_tcam_region *region,
+ void *hints_priv,
const struct mlxsw_sp_acl_ctcam_region_ops *ops);
void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion,
@@ -224,13 +234,15 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_entry *aentry);
int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_region *aregion,
- struct mlxsw_sp_acl_atcam_chunk *achunk,
struct mlxsw_sp_acl_atcam_entry *aentry,
struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam);
void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam);
+void *
+mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
+void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv);
struct mlxsw_sp_acl_erp_delta;
@@ -261,7 +273,11 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_erp_mask *erp_mask,
struct mlxsw_sp_acl_atcam_entry *aentry);
-int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion);
+void *
+mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
+void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv);
+int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion,
+ void *hints_priv);
void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index 12c61e0cc570..9a79b5e11597 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -37,13 +37,19 @@ struct mlxsw_sp_sb_pm {
struct mlxsw_cp_sb_occ occ;
};
+struct mlxsw_sp_sb_mm {
+ u32 min_buff;
+ u32 max_buff;
+ u16 pool_index;
+};
+
struct mlxsw_sp_sb_pool_des {
enum mlxsw_reg_sbxx_dir dir;
u8 pool;
};
/* Order ingress pools before egress pools. */
-static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = {
+static const struct mlxsw_sp_sb_pool_des mlxsw_sp1_sb_pool_dess[] = {
{MLXSW_REG_SBXX_DIR_INGRESS, 0},
{MLXSW_REG_SBXX_DIR_INGRESS, 1},
{MLXSW_REG_SBXX_DIR_INGRESS, 2},
@@ -55,7 +61,16 @@ static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = {
{MLXSW_REG_SBXX_DIR_EGRESS, 15},
};
-#define MLXSW_SP_SB_POOL_DESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pool_dess)
+static const struct mlxsw_sp_sb_pool_des mlxsw_sp2_sb_pool_dess[] = {
+ {MLXSW_REG_SBXX_DIR_INGRESS, 0},
+ {MLXSW_REG_SBXX_DIR_INGRESS, 1},
+ {MLXSW_REG_SBXX_DIR_INGRESS, 2},
+ {MLXSW_REG_SBXX_DIR_INGRESS, 3},
+ {MLXSW_REG_SBXX_DIR_EGRESS, 0},
+ {MLXSW_REG_SBXX_DIR_EGRESS, 1},
+ {MLXSW_REG_SBXX_DIR_EGRESS, 2},
+ {MLXSW_REG_SBXX_DIR_EGRESS, 3},
+};
#define MLXSW_SP_SB_ING_TC_COUNT 8
#define MLXSW_SP_SB_EG_TC_COUNT 16
@@ -63,16 +78,32 @@ static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = {
struct mlxsw_sp_sb_port {
struct mlxsw_sp_sb_cm ing_cms[MLXSW_SP_SB_ING_TC_COUNT];
struct mlxsw_sp_sb_cm eg_cms[MLXSW_SP_SB_EG_TC_COUNT];
- struct mlxsw_sp_sb_pm pms[MLXSW_SP_SB_POOL_DESS_LEN];
+ struct mlxsw_sp_sb_pm *pms;
};
struct mlxsw_sp_sb {
- struct mlxsw_sp_sb_pr prs[MLXSW_SP_SB_POOL_DESS_LEN];
+ struct mlxsw_sp_sb_pr *prs;
struct mlxsw_sp_sb_port *ports;
u32 cell_size;
+ u32 max_headroom_cells;
u64 sb_size;
};
+struct mlxsw_sp_sb_vals {
+ unsigned int pool_count;
+ const struct mlxsw_sp_sb_pool_des *pool_dess;
+ const struct mlxsw_sp_sb_pm *pms;
+ const struct mlxsw_sp_sb_pr *prs;
+ const struct mlxsw_sp_sb_mm *mms;
+ const struct mlxsw_sp_sb_cm *cms_ingress;
+ const struct mlxsw_sp_sb_cm *cms_egress;
+ const struct mlxsw_sp_sb_cm *cms_cpu;
+ unsigned int mms_count;
+ unsigned int cms_ingress_count;
+ unsigned int cms_egress_count;
+ unsigned int cms_cpu_count;
+};
+
u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells)
{
return mlxsw_sp->sb->cell_size * cells;
@@ -83,6 +114,11 @@ u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes)
return DIV_ROUND_UP(bytes, mlxsw_sp->sb->cell_size);
}
+u32 mlxsw_sp_sb_max_headroom_cells(const struct mlxsw_sp *mlxsw_sp)
+{
+ return mlxsw_sp->sb->max_headroom_cells;
+}
+
static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp,
u16 pool_index)
{
@@ -121,7 +157,7 @@ static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u16 pool_index,
u32 size, bool infi_size)
{
const struct mlxsw_sp_sb_pool_des *des =
- &mlxsw_sp_sb_pool_dess[pool_index];
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
char sbpr_pl[MLXSW_REG_SBPR_LEN];
struct mlxsw_sp_sb_pr *pr;
int err;
@@ -145,7 +181,7 @@ static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
bool infi_max, u16 pool_index)
{
const struct mlxsw_sp_sb_pool_des *des =
- &mlxsw_sp_sb_pool_dess[pool_index];
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
char sbcm_pl[MLXSW_REG_SBCM_LEN];
struct mlxsw_sp_sb_cm *cm;
int err;
@@ -174,7 +210,7 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u16 pool_index, u32 min_buff, u32 max_buff)
{
const struct mlxsw_sp_sb_pool_des *des =
- &mlxsw_sp_sb_pool_dess[pool_index];
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
char sbpm_pl[MLXSW_REG_SBPM_LEN];
struct mlxsw_sp_sb_pm *pm;
int err;
@@ -195,7 +231,7 @@ static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u16 pool_index, struct list_head *bulk_list)
{
const struct mlxsw_sp_sb_pool_des *des =
- &mlxsw_sp_sb_pool_dess[pool_index];
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
char sbpm_pl[MLXSW_REG_SBPM_LEN];
mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir,
@@ -217,7 +253,7 @@ static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u16 pool_index, struct list_head *bulk_list)
{
const struct mlxsw_sp_sb_pool_des *des =
- &mlxsw_sp_sb_pool_dess[pool_index];
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
char sbpm_pl[MLXSW_REG_SBPM_LEN];
struct mlxsw_sp_sb_pm *pm;
@@ -230,24 +266,24 @@ static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port,
(unsigned long) pm);
}
-static const u16 mlxsw_sp_pbs[] = {
- [0] = 2 * ETH_FRAME_LEN,
- [9] = 2 * MLXSW_PORT_MAX_MTU,
-};
-
-#define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs)
+/* 1/4 of a headroom necessary for 100Gbps port and 100m cable. */
+#define MLXSW_SP_PB_HEADROOM 25632
#define MLXSW_SP_PB_UNUSED 8
static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
+ const u32 pbs[] = {
+ [0] = MLXSW_SP_PB_HEADROOM * mlxsw_sp_port->mapping.width,
+ [9] = 2 * MLXSW_PORT_MAX_MTU,
+ };
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char pbmc_pl[MLXSW_REG_PBMC_LEN];
int i;
mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port,
0xffff, 0xffff / 2);
- for (i = 0; i < MLXSW_SP_PBS_LEN; i++) {
- u16 size = mlxsw_sp_bytes_cells(mlxsw_sp, mlxsw_sp_pbs[i]);
+ for (i = 0; i < ARRAY_SIZE(pbs); i++) {
+ u16 size = mlxsw_sp_bytes_cells(mlxsw_sp, pbs[i]);
if (i == MLXSW_SP_PB_UNUSED)
continue;
@@ -280,50 +316,119 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port)
return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port);
}
+static int mlxsw_sp_sb_port_init(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_sb_port *sb_port)
+{
+ struct mlxsw_sp_sb_pm *pms;
+
+ pms = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*pms),
+ GFP_KERNEL);
+ if (!pms)
+ return -ENOMEM;
+ sb_port->pms = pms;
+ return 0;
+}
+
+static void mlxsw_sp_sb_port_fini(struct mlxsw_sp_sb_port *sb_port)
+{
+ kfree(sb_port->pms);
+}
+
static int mlxsw_sp_sb_ports_init(struct mlxsw_sp *mlxsw_sp)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+ struct mlxsw_sp_sb_pr *prs;
+ int i;
+ int err;
mlxsw_sp->sb->ports = kcalloc(max_ports,
sizeof(struct mlxsw_sp_sb_port),
GFP_KERNEL);
if (!mlxsw_sp->sb->ports)
return -ENOMEM;
+
+ prs = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*prs),
+ GFP_KERNEL);
+ if (!prs) {
+ err = -ENOMEM;
+ goto err_alloc_prs;
+ }
+ mlxsw_sp->sb->prs = prs;
+
+ for (i = 0; i < max_ports; i++) {
+ err = mlxsw_sp_sb_port_init(mlxsw_sp, &mlxsw_sp->sb->ports[i]);
+ if (err)
+ goto err_sb_port_init;
+ }
+
return 0;
+
+err_sb_port_init:
+ for (i--; i >= 0; i--)
+ mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]);
+ kfree(mlxsw_sp->sb->prs);
+err_alloc_prs:
+ kfree(mlxsw_sp->sb->ports);
+ return err;
}
static void mlxsw_sp_sb_ports_fini(struct mlxsw_sp *mlxsw_sp)
{
+ int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+ int i;
+
+ for (i = max_ports - 1; i >= 0; i--)
+ mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]);
+ kfree(mlxsw_sp->sb->prs);
kfree(mlxsw_sp->sb->ports);
}
-#define MLXSW_SP_SB_PR_INGRESS_SIZE 12440000
-#define MLXSW_SP_SB_PR_INGRESS_MNG_SIZE (200 * 1000)
-#define MLXSW_SP_SB_PR_EGRESS_SIZE 13232000
-
#define MLXSW_SP_SB_PR(_mode, _size) \
{ \
.mode = _mode, \
.size = _size, \
}
-static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs[] = {
+#define MLXSW_SP1_SB_PR_INGRESS_SIZE 12440000
+#define MLXSW_SP1_SB_PR_INGRESS_MNG_SIZE (200 * 1000)
+#define MLXSW_SP1_SB_PR_EGRESS_SIZE 13232000
+
+static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
/* Ingress pools. */
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
- MLXSW_SP_SB_PR_INGRESS_SIZE),
+ MLXSW_SP1_SB_PR_INGRESS_SIZE),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
- MLXSW_SP_SB_PR_INGRESS_MNG_SIZE),
+ MLXSW_SP1_SB_PR_INGRESS_MNG_SIZE),
/* Egress pools. */
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_PR_EGRESS_SIZE),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+ MLXSW_SP1_SB_PR_EGRESS_SIZE),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, MLXSW_SP_SB_INFI),
};
-#define MLXSW_SP_SB_PRS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs)
+#define MLXSW_SP2_SB_PR_INGRESS_SIZE 40960000
+#define MLXSW_SP2_SB_PR_INGRESS_MNG_SIZE (200 * 1000)
+#define MLXSW_SP2_SB_PR_EGRESS_SIZE 40960000
+
+static const struct mlxsw_sp_sb_pr mlxsw_sp2_sb_prs[] = {
+ /* Ingress pools. */
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+ MLXSW_SP2_SB_PR_INGRESS_SIZE),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+ MLXSW_SP2_SB_PR_INGRESS_MNG_SIZE),
+ /* Egress pools. */
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+ MLXSW_SP2_SB_PR_EGRESS_SIZE),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
+};
static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_sb_pr *prs,
@@ -357,7 +462,7 @@ static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp,
.pool_index = _pool, \
}
-static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = {
+static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_ingress[] = {
MLXSW_SP_SB_CM(10000, 8, 0),
MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
@@ -370,9 +475,20 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = {
MLXSW_SP_SB_CM(20000, 1, 3),
};
-#define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress)
+static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_ingress[] = {
+ MLXSW_SP_SB_CM(0, 7, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
+ MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */
+ MLXSW_SP_SB_CM(20000, 1, 3),
+};
-static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = {
+static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_egress[] = {
MLXSW_SP_SB_CM(1500, 9, 4),
MLXSW_SP_SB_CM(1500, 9, 4),
MLXSW_SP_SB_CM(1500, 9, 4),
@@ -392,7 +508,25 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = {
MLXSW_SP_SB_CM(1, 0xff, 4),
};
-#define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress)
+static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_egress[] = {
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(0, 7, 4),
+ MLXSW_SP_SB_CM(1, 0xff, 4),
+};
#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, 4)
@@ -431,9 +565,6 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
MLXSW_SP_CPU_PORT_SB_CM,
};
-#define MLXSW_SP_CPU_PORT_SB_MCS_LEN \
- ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms)
-
static bool
mlxsw_sp_sb_pool_is_static(struct mlxsw_sp *mlxsw_sp, u16 pool_index)
{
@@ -447,6 +578,7 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
const struct mlxsw_sp_sb_cm *cms,
size_t cms_len)
{
+ const struct mlxsw_sp_sb_vals *sb_vals = mlxsw_sp->sb_vals;
int i;
int err;
@@ -458,7 +590,7 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
if (i == 8 && dir == MLXSW_REG_SBXX_DIR_INGRESS)
continue; /* PG number 8 does not exist, skip it */
cm = &cms[i];
- if (WARN_ON(mlxsw_sp_sb_pool_dess[cm->pool_index].dir != dir))
+ if (WARN_ON(sb_vals->pool_dess[cm->pool_index].dir != dir))
continue;
min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, cm->min_buff);
@@ -484,27 +616,28 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
int err;
- err = __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
+ err = __mlxsw_sp_sb_cms_init(mlxsw_sp,
mlxsw_sp_port->local_port,
MLXSW_REG_SBXX_DIR_INGRESS,
- mlxsw_sp_sb_cms_ingress,
- MLXSW_SP_SB_CMS_INGRESS_LEN);
+ mlxsw_sp->sb_vals->cms_ingress,
+ mlxsw_sp->sb_vals->cms_ingress_count);
if (err)
return err;
return __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
mlxsw_sp_port->local_port,
MLXSW_REG_SBXX_DIR_EGRESS,
- mlxsw_sp_sb_cms_egress,
- MLXSW_SP_SB_CMS_EGRESS_LEN);
+ mlxsw_sp->sb_vals->cms_egress,
+ mlxsw_sp->sb_vals->cms_egress_count);
}
static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
{
return __mlxsw_sp_sb_cms_init(mlxsw_sp, 0, MLXSW_REG_SBXX_DIR_EGRESS,
- mlxsw_sp_cpu_port_sb_cms,
- MLXSW_SP_CPU_PORT_SB_MCS_LEN);
+ mlxsw_sp->sb_vals->cms_cpu,
+ mlxsw_sp->sb_vals->cms_cpu_count);
}
#define MLXSW_SP_SB_PM(_min_buff, _max_buff) \
@@ -513,7 +646,7 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
.max_buff = _max_buff, \
}
-static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
+static const struct mlxsw_sp_sb_pm mlxsw_sp1_sb_pms[] = {
/* Ingress pools. */
MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX),
MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
@@ -527,7 +660,18 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
MLXSW_SP_SB_PM(10000, 90000),
};
-#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms)
+static const struct mlxsw_sp_sb_pm mlxsw_sp2_sb_pms[] = {
+ /* Ingress pools. */
+ MLXSW_SP_SB_PM(0, 7),
+ MLXSW_SP_SB_PM(0, 0),
+ MLXSW_SP_SB_PM(0, 0),
+ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX),
+ /* Egress pools. */
+ MLXSW_SP_SB_PM(0, 7),
+ MLXSW_SP_SB_PM(0, 0),
+ MLXSW_SP_SB_PM(0, 0),
+ MLXSW_SP_SB_PM(0, 0),
+};
static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
@@ -535,8 +679,8 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
int i;
int err;
- for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) {
- const struct mlxsw_sp_sb_pm *pm = &mlxsw_sp_sb_pms[i];
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
+ const struct mlxsw_sp_sb_pm *pm = &mlxsw_sp->sb_vals->pms[i];
u32 max_buff;
u32 min_buff;
@@ -552,12 +696,6 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
return 0;
}
-struct mlxsw_sp_sb_mm {
- u32 min_buff;
- u32 max_buff;
- u16 pool_index;
-};
-
#define MLXSW_SP_SB_MM(_min_buff, _max_buff, _pool) \
{ \
.min_buff = _min_buff, \
@@ -583,21 +721,19 @@ static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = {
MLXSW_SP_SB_MM(0, 6, 4),
};
-#define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms)
-
static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
{
char sbmm_pl[MLXSW_REG_SBMM_LEN];
int i;
int err;
- for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) {
+ for (i = 0; i < mlxsw_sp->sb_vals->mms_count; i++) {
const struct mlxsw_sp_sb_pool_des *des;
const struct mlxsw_sp_sb_mm *mc;
u32 min_buff;
- mc = &mlxsw_sp_sb_mms[i];
- des = &mlxsw_sp_sb_pool_dess[mc->pool_index];
+ mc = &mlxsw_sp->sb_vals->mms[i];
+ des = &mlxsw_sp->sb_vals->pool_dess[mc->pool_index];
/* All pools used by sb_mm's are initialized using dynamic
* thresholds, therefore 'max_buff' isn't specified in cells.
*/
@@ -611,22 +747,55 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
return 0;
}
-static void mlxsw_sp_pool_count(u16 *p_ingress_len, u16 *p_egress_len)
+static void mlxsw_sp_pool_count(struct mlxsw_sp *mlxsw_sp,
+ u16 *p_ingress_len, u16 *p_egress_len)
{
int i;
- for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; ++i)
- if (mlxsw_sp_sb_pool_dess[i].dir == MLXSW_REG_SBXX_DIR_EGRESS)
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; ++i)
+ if (mlxsw_sp->sb_vals->pool_dess[i].dir ==
+ MLXSW_REG_SBXX_DIR_EGRESS)
goto out;
WARN(1, "No egress pools\n");
out:
*p_ingress_len = i;
- *p_egress_len = MLXSW_SP_SB_POOL_DESS_LEN - i;
+ *p_egress_len = mlxsw_sp->sb_vals->pool_count - i;
}
+const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = {
+ .pool_count = ARRAY_SIZE(mlxsw_sp1_sb_pool_dess),
+ .pool_dess = mlxsw_sp1_sb_pool_dess,
+ .pms = mlxsw_sp1_sb_pms,
+ .prs = mlxsw_sp1_sb_prs,
+ .mms = mlxsw_sp_sb_mms,
+ .cms_ingress = mlxsw_sp1_sb_cms_ingress,
+ .cms_egress = mlxsw_sp1_sb_cms_egress,
+ .cms_cpu = mlxsw_sp_cpu_port_sb_cms,
+ .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms),
+ .cms_ingress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_ingress),
+ .cms_egress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_egress),
+ .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms),
+};
+
+const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = {
+ .pool_count = ARRAY_SIZE(mlxsw_sp2_sb_pool_dess),
+ .pool_dess = mlxsw_sp2_sb_pool_dess,
+ .pms = mlxsw_sp2_sb_pms,
+ .prs = mlxsw_sp2_sb_prs,
+ .mms = mlxsw_sp_sb_mms,
+ .cms_ingress = mlxsw_sp2_sb_cms_ingress,
+ .cms_egress = mlxsw_sp2_sb_cms_egress,
+ .cms_cpu = mlxsw_sp_cpu_port_sb_cms,
+ .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms),
+ .cms_ingress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_ingress),
+ .cms_egress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_egress),
+ .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms),
+};
+
int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
{
+ u32 max_headroom_size;
u16 ing_pool_count;
u16 eg_pool_count;
int err;
@@ -637,18 +806,26 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_BUFFER_SIZE))
return -EIO;
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_HEADROOM_SIZE))
+ return -EIO;
+
mlxsw_sp->sb = kzalloc(sizeof(*mlxsw_sp->sb), GFP_KERNEL);
if (!mlxsw_sp->sb)
return -ENOMEM;
mlxsw_sp->sb->cell_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, CELL_SIZE);
mlxsw_sp->sb->sb_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
MAX_BUFFER_SIZE);
+ max_headroom_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ MAX_HEADROOM_SIZE);
+ /* Round down, because this limit must not be overstepped. */
+ mlxsw_sp->sb->max_headroom_cells = max_headroom_size /
+ mlxsw_sp->sb->cell_size;
err = mlxsw_sp_sb_ports_init(mlxsw_sp);
if (err)
goto err_sb_ports_init;
- err = mlxsw_sp_sb_prs_init(mlxsw_sp, mlxsw_sp_sb_prs,
- MLXSW_SP_SB_PRS_LEN);
+ err = mlxsw_sp_sb_prs_init(mlxsw_sp, mlxsw_sp->sb_vals->prs,
+ mlxsw_sp->sb_vals->pool_count);
if (err)
goto err_sb_prs_init;
err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
@@ -657,7 +834,7 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
err = mlxsw_sp_sb_mms_init(mlxsw_sp);
if (err)
goto err_sb_mms_init;
- mlxsw_sp_pool_count(&ing_pool_count, &eg_pool_count);
+ mlxsw_sp_pool_count(mlxsw_sp, &ing_pool_count, &eg_pool_count);
err = devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0,
mlxsw_sp->sb->sb_size,
ing_pool_count,
@@ -705,14 +882,16 @@ int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core,
unsigned int sb_index, u16 pool_index,
struct devlink_sb_pool_info *pool_info)
{
- enum mlxsw_reg_sbxx_dir dir = mlxsw_sp_sb_pool_dess[pool_index].dir;
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+ enum mlxsw_reg_sbxx_dir dir;
struct mlxsw_sp_sb_pr *pr;
+ dir = mlxsw_sp->sb_vals->pool_dess[pool_index].dir;
pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
pool_info->pool_type = (enum devlink_sb_pool_type) dir;
pool_info->size = mlxsw_sp_cells_bytes(mlxsw_sp, pr->size);
pool_info->threshold_type = (enum devlink_sb_threshold_type) pr->mode;
+ pool_info->cell_size = mlxsw_sp->sb->cell_size;
return 0;
}
@@ -833,7 +1012,7 @@ int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port,
u32 max_buff;
int err;
- if (dir != mlxsw_sp_sb_pool_dess[pool_index].dir)
+ if (dir != mlxsw_sp->sb_vals->pool_dess[pool_index].dir)
return -EINVAL;
err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool_index,
@@ -931,7 +1110,7 @@ next_batch:
continue;
mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
- for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; i++) {
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i,
&bulk_list);
if (err)
@@ -990,7 +1169,7 @@ next_batch:
continue;
mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
- for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; i++) {
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i,
&bulk_list);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 41e607a14846..49933818c6f5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -220,7 +220,7 @@ start_again:
for (; i < rif_count; i++) {
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
- if (!rif)
+ if (!rif || !mlxsw_sp_rif_dev(rif))
continue;
err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,
counters_enabled);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index 055cc6943b34..46baf3b44309 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
.type = MLXSW_SP_FID_TYPE_DUMMY,
.fid_size = sizeof(struct mlxsw_sp_fid),
- .start_index = MLXSW_SP_RFID_BASE - 1,
- .end_index = MLXSW_SP_RFID_BASE - 1,
+ .start_index = VLAN_N_VID - 1,
+ .end_index = VLAN_N_VID - 1,
.ops = &mlxsw_sp_fid_dummy_ops,
};
@@ -1188,8 +1188,7 @@ static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
fid_family->mlxsw_sp = mlxsw_sp;
INIT_LIST_HEAD(&fid_family->fids_list);
- fid_family->fids_bitmap = kcalloc(BITS_TO_LONGS(nr_fids),
- sizeof(unsigned long), GFP_KERNEL);
+ fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
if (!fid_family->fids_bitmap) {
err = -ENOMEM;
goto err_alloc_fids_bitmap;
@@ -1206,7 +1205,7 @@ static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
return 0;
err_fid_flood_tables_init:
- kfree(fid_family->fids_bitmap);
+ bitmap_free(fid_family->fids_bitmap);
err_alloc_fids_bitmap:
kfree(fid_family);
return err;
@@ -1217,7 +1216,7 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fid_family *fid_family)
{
mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
- kfree(fid_family->fids_bitmap);
+ bitmap_free(fid_family->fids_bitmap);
WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
kfree(fid_family);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index ff072358d950..15f804453cd6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -17,13 +17,13 @@
static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block,
struct mlxsw_sp_acl_rule_info *rulei,
- struct tcf_exts *exts,
+ struct flow_action *flow_action,
struct netlink_ext_ack *extack)
{
- const struct tc_action *a;
+ const struct flow_action_entry *act;
int err, i;
- if (!tcf_exts_has_actions(exts))
+ if (!flow_action_has_entries(flow_action))
return 0;
/* Count action is inserted first */
@@ -31,27 +31,31 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;
- tcf_exts_for_each_action(i, a, exts) {
- if (is_tcf_gact_ok(a)) {
+ flow_action_for_each(i, act, flow_action) {
+ switch (act->id) {
+ case FLOW_ACTION_ACCEPT:
err = mlxsw_sp_acl_rulei_act_terminate(rulei);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Cannot append terminate action");
return err;
}
- } else if (is_tcf_gact_shot(a)) {
+ break;
+ case FLOW_ACTION_DROP:
err = mlxsw_sp_acl_rulei_act_drop(rulei);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action");
return err;
}
- } else if (is_tcf_gact_trap(a)) {
+ break;
+ case FLOW_ACTION_TRAP:
err = mlxsw_sp_acl_rulei_act_trap(rulei);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Cannot append trap action");
return err;
}
- } else if (is_tcf_gact_goto_chain(a)) {
- u32 chain_index = tcf_gact_goto_chain_index(a);
+ break;
+ case FLOW_ACTION_GOTO: {
+ u32 chain_index = act->chain_index;
struct mlxsw_sp_acl_ruleset *ruleset;
u16 group_id;
@@ -67,7 +71,9 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
NL_SET_ERR_MSG_MOD(extack, "Cannot append jump action");
return err;
}
- } else if (is_tcf_mirred_egress_redirect(a)) {
+ }
+ break;
+ case FLOW_ACTION_REDIRECT: {
struct net_device *out_dev;
struct mlxsw_sp_fid *fid;
u16 fid_index;
@@ -79,29 +85,33 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;
- out_dev = tcf_mirred_dev(a);
+ out_dev = act->dev;
err = mlxsw_sp_acl_rulei_act_fwd(mlxsw_sp, rulei,
out_dev, extack);
if (err)
return err;
- } else if (is_tcf_mirred_egress_mirror(a)) {
- struct net_device *out_dev = tcf_mirred_dev(a);
+ }
+ break;
+ case FLOW_ACTION_MIRRED: {
+ struct net_device *out_dev = act->dev;
err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei,
block, out_dev,
extack);
if (err)
return err;
- } else if (is_tcf_vlan(a)) {
- u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
- u32 action = tcf_vlan_action(a);
- u8 prio = tcf_vlan_push_prio(a);
- u16 vid = tcf_vlan_push_vid(a);
+ }
+ break;
+ case FLOW_ACTION_VLAN_MANGLE: {
+ u16 proto = be16_to_cpu(act->vlan.proto);
+ u8 prio = act->vlan.prio;
+ u16 vid = act->vlan.vid;
return mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei,
- action, vid,
+ act->id, vid,
proto, prio, extack);
- } else {
+ }
+ default:
NL_SET_ERR_MSG_MOD(extack, "Unsupported action");
dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n");
return -EOPNOTSUPP;
@@ -113,59 +123,49 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei,
struct tc_cls_flower_offload *f)
{
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_ipv4_addrs(f->rule, &match);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
- (char *) &key->src,
- (char *) &mask->src, 4);
+ (char *) &match.key->src,
+ (char *) &match.mask->src, 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
- (char *) &key->dst,
- (char *) &mask->dst, 4);
+ (char *) &match.key->dst,
+ (char *) &match.mask->dst, 4);
}
static void mlxsw_sp_flower_parse_ipv6(struct mlxsw_sp_acl_rule_info *rulei,
struct tc_cls_flower_offload *f)
{
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
+ struct flow_match_ipv6_addrs match;
+
+ flow_rule_match_ipv6_addrs(f->rule, &match);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127,
- &key->src.s6_addr[0x0],
- &mask->src.s6_addr[0x0], 4);
+ &match.key->src.s6_addr[0x0],
+ &match.mask->src.s6_addr[0x0], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_64_95,
- &key->src.s6_addr[0x4],
- &mask->src.s6_addr[0x4], 4);
+ &match.key->src.s6_addr[0x4],
+ &match.mask->src.s6_addr[0x4], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_32_63,
- &key->src.s6_addr[0x8],
- &mask->src.s6_addr[0x8], 4);
+ &match.key->src.s6_addr[0x8],
+ &match.mask->src.s6_addr[0x8], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
- &key->src.s6_addr[0xC],
- &mask->src.s6_addr[0xC], 4);
+ &match.key->src.s6_addr[0xC],
+ &match.mask->src.s6_addr[0xC], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_96_127,
- &key->dst.s6_addr[0x0],
- &mask->dst.s6_addr[0x0], 4);
+ &match.key->dst.s6_addr[0x0],
+ &match.mask->dst.s6_addr[0x0], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_64_95,
- &key->dst.s6_addr[0x4],
- &mask->dst.s6_addr[0x4], 4);
+ &match.key->dst.s6_addr[0x4],
+ &match.mask->dst.s6_addr[0x4], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_32_63,
- &key->dst.s6_addr[0x8],
- &mask->dst.s6_addr[0x8], 4);
+ &match.key->dst.s6_addr[0x8],
+ &match.mask->dst.s6_addr[0x8], 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
- &key->dst.s6_addr[0xC],
- &mask->dst.s6_addr[0xC], 4);
+ &match.key->dst.s6_addr[0xC],
+ &match.mask->dst.s6_addr[0xC], 4);
}
static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp,
@@ -173,9 +173,10 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp,
struct tc_cls_flower_offload *f,
u8 ip_proto)
{
- struct flow_dissector_key_ports *key, *mask;
+ const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_match_ports match;
- if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS))
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS))
return 0;
if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
@@ -184,16 +185,13 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp,
return -EINVAL;
}
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
+ flow_rule_match_ports(rule, &match);
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_DST_L4_PORT,
- ntohs(key->dst), ntohs(mask->dst));
+ ntohs(match.key->dst),
+ ntohs(match.mask->dst));
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_SRC_L4_PORT,
- ntohs(key->src), ntohs(mask->src));
+ ntohs(match.key->src),
+ ntohs(match.mask->src));
return 0;
}
@@ -202,9 +200,10 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp,
struct tc_cls_flower_offload *f,
u8 ip_proto)
{
- struct flow_dissector_key_tcp *key, *mask;
+ const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_match_tcp match;
- if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP))
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP))
return 0;
if (ip_proto != IPPROTO_TCP) {
@@ -213,14 +212,11 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp,
return -EINVAL;
}
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_TCP,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_TCP,
- f->mask);
+ flow_rule_match_tcp(rule, &match);
+
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS,
- ntohs(key->flags), ntohs(mask->flags));
+ ntohs(match.key->flags),
+ ntohs(match.mask->flags));
return 0;
}
@@ -229,9 +225,10 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp,
struct tc_cls_flower_offload *f,
u16 n_proto)
{
- struct flow_dissector_key_ip *key, *mask;
+ const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_match_ip match;
- if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP))
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP))
return 0;
if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6) {
@@ -240,20 +237,18 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp,
return -EINVAL;
}
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IP,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IP,
- f->mask);
+ flow_rule_match_ip(rule, &match);
+
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_,
- key->ttl, mask->ttl);
+ match.key->ttl, match.mask->ttl);
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_ECN,
- key->tos & 0x3, mask->tos & 0x3);
+ match.key->tos & 0x3,
+ match.mask->tos & 0x3);
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP,
- key->tos >> 6, mask->tos >> 6);
+ match.key->tos >> 6,
+ match.mask->tos >> 6);
return 0;
}
@@ -263,13 +258,15 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct tc_cls_flower_offload *f)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+ struct flow_dissector *dissector = rule->match.dissector;
u16 n_proto_mask = 0;
u16 n_proto_key = 0;
u16 addr_type = 0;
u8 ip_proto = 0;
int err;
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -286,25 +283,19 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_rulei_priority(rulei, f->common.prio);
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->key);
- addr_type = key->addr_type;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
+
+ flow_rule_match_control(rule, &match);
+ addr_type = match.key->addr_type;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
- n_proto_key = ntohs(key->n_proto);
- n_proto_mask = ntohs(mask->n_proto);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
+
+ flow_rule_match_basic(rule, &match);
+ n_proto_key = ntohs(match.key->n_proto);
+ n_proto_mask = ntohs(match.mask->n_proto);
if (n_proto_key == ETH_P_ALL) {
n_proto_key = 0;
@@ -314,60 +305,53 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
MLXSW_AFK_ELEMENT_ETHERTYPE,
n_proto_key, n_proto_mask);
- ip_proto = key->ip_proto;
+ ip_proto = match.key->ip_proto;
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_IP_PROTO,
- key->ip_proto, mask->ip_proto);
+ match.key->ip_proto,
+ match.mask->ip_proto);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
- struct flow_dissector_key_eth_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
+ flow_rule_match_eth_addrs(rule, &match);
mlxsw_sp_acl_rulei_keymask_buf(rulei,
MLXSW_AFK_ELEMENT_DMAC_32_47,
- key->dst, mask->dst, 2);
+ match.key->dst,
+ match.mask->dst, 2);
mlxsw_sp_acl_rulei_keymask_buf(rulei,
MLXSW_AFK_ELEMENT_DMAC_0_31,
- key->dst + 2, mask->dst + 2, 4);
+ match.key->dst + 2,
+ match.mask->dst + 2, 4);
mlxsw_sp_acl_rulei_keymask_buf(rulei,
MLXSW_AFK_ELEMENT_SMAC_32_47,
- key->src, mask->src, 2);
+ match.key->src,
+ match.mask->src, 2);
mlxsw_sp_acl_rulei_keymask_buf(rulei,
MLXSW_AFK_ELEMENT_SMAC_0_31,
- key->src + 2, mask->src + 2, 4);
+ match.key->src + 2,
+ match.mask->src + 2, 4);
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
+ flow_rule_match_vlan(rule, &match);
if (mlxsw_sp_acl_block_is_egress_bound(block)) {
NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress");
return -EOPNOTSUPP;
}
- if (mask->vlan_id != 0)
+ if (match.mask->vlan_id != 0)
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_VID,
- key->vlan_id,
- mask->vlan_id);
- if (mask->vlan_priority != 0)
+ match.key->vlan_id,
+ match.mask->vlan_id);
+ if (match.mask->vlan_priority != 0)
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_PCP,
- key->vlan_priority,
- mask->vlan_priority);
+ match.key->vlan_priority,
+ match.mask->vlan_priority);
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS)
@@ -387,7 +371,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;
- return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei, f->exts,
+ return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei,
+ &f->rule->action,
f->common.extack);
}
@@ -486,7 +471,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_rule_get_stats;
- tcf_exts_stats_update(f->exts, bytes, packets, lastuse);
+ flow_stats_update(&f->stats, bytes, packets, lastuse);
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
index 00db26c96bf5..6400cd644b7a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
@@ -145,6 +145,7 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry)
{
u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
+ u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
char rtdp_pl[MLXSW_REG_RTDP_LEN];
struct ip_tunnel_parm parms;
unsigned int type_check;
@@ -157,6 +158,7 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp,
ikey = mlxsw_sp_ipip_parms4_ikey(parms);
mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index);
+ mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id);
type_check = has_ikey ?
MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY :
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
index 0a31fff2516e..1df164a4b06d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
@@ -267,8 +267,8 @@ mlxsw_sp_nve_mc_record_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nve_mc_record *mc_record;
int err;
- mc_record = kzalloc(sizeof(*mc_record) + num_max_entries *
- sizeof(struct mlxsw_sp_nve_mc_entry), GFP_KERNEL);
+ mc_record = kzalloc(struct_size(mc_record, entries, num_max_entries),
+ GFP_KERNEL);
if (!mc_record)
return ERR_PTR(-ENOMEM);
@@ -816,14 +816,14 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
ops = nve->nve_ops_arr[params->type];
if (!ops->can_offload(nve, params->dev, extack))
- return -EOPNOTSUPP;
+ return -EINVAL;
memset(&config, 0, sizeof(config));
ops->nve_config(nve, params->dev, &config);
if (nve->num_nve_tunnels &&
memcmp(&config, &nve->config, sizeof(config))) {
NL_SET_ERR_MSG_MOD(extack, "Conflicting NVE tunnels configuration");
- return -EOPNOTSUPP;
+ return -EINVAL;
}
err = mlxsw_sp_nve_tunnel_init(mlxsw_sp, &config);
@@ -841,11 +841,9 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
nve->config = config;
- err = ops->fdb_replay(params->dev, params->vni);
- if (err) {
- NL_SET_ERR_MSG_MOD(extack, "Failed to offload the FDB");
+ err = ops->fdb_replay(params->dev, params->vni, extack);
+ if (err)
goto err_fdb_replay;
- }
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
index 02937ea95bc3..0035640156a1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
@@ -28,6 +28,7 @@ struct mlxsw_sp_nve {
unsigned int num_nve_tunnels; /* Protected by RTNL */
unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
u32 tunnel_index;
+ u16 ul_rif_index; /* Reserved for Spectrum */
};
struct mlxsw_sp_nve_ops {
@@ -41,7 +42,8 @@ struct mlxsw_sp_nve_ops {
int (*init)(struct mlxsw_sp_nve *nve,
const struct mlxsw_sp_nve_config *config);
void (*fini)(struct mlxsw_sp_nve *nve);
- int (*fdb_replay)(const struct net_device *nve_dev, __be32 vni);
+ int (*fdb_replay)(const struct net_device *nve_dev, __be32 vni,
+ struct netlink_ext_ack *extack);
void (*fdb_clear_offload)(const struct net_device *nve_dev, __be32 vni);
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
index 74e564c4ac19..93ccd9fc2266 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
@@ -7,6 +7,7 @@
#include <net/vxlan.h>
#include "reg.h"
+#include "spectrum.h"
#include "spectrum_nve.h"
/* Eth (18B) | IPv6 (40B) | UDP (8B) | VxLAN (8B) | Eth (14B) | IPv6 (40B)
@@ -20,9 +21,9 @@
#define MLXSW_SP_NVE_VXLAN_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \
VXLAN_F_LEARN)
-static bool mlxsw_sp1_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve,
- const struct net_device *dev,
- struct netlink_ext_ack *extack)
+static bool mlxsw_sp_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve,
+ const struct net_device *dev,
+ struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_config *cfg = &vxlan->cfg;
@@ -112,13 +113,30 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
}
+static void
+mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
+ const struct mlxsw_sp_nve_config *config)
+{
+ u8 udp_sport;
+
+ mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true,
+ config->ttl);
+ /* VxLAN driver's default UDP source port range is 32768 (0x8000)
+ * to 60999 (0xee47). Set the upper 8 bits of the UDP source port
+ * to a random number between 0x80 and 0xee
+ */
+ get_random_bytes(&udp_sport, sizeof(udp_sport));
+ udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80;
+ mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport);
+ mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4));
+}
+
static int
mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_nve_config *config)
{
char tngcr_pl[MLXSW_REG_TNGCR_LEN];
u16 ul_vr_id;
- u8 udp_sport;
int err;
err = mlxsw_sp_router_tb_id_vr_id(mlxsw_sp, config->ul_tb_id,
@@ -126,18 +144,9 @@ mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;
- mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true,
- config->ttl);
- /* VxLAN driver's default UDP source port range is 32768 (0x8000)
- * to 60999 (0xee47). Set the upper 8 bits of the UDP source port
- * to a random number between 0x80 and 0xee
- */
- get_random_bytes(&udp_sport, sizeof(udp_sport));
- udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80;
- mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport);
+ mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config);
mlxsw_reg_tngcr_learn_enable_set(tngcr_pl, config->learning_en);
mlxsw_reg_tngcr_underlay_virtual_router_set(tngcr_pl, ul_vr_id);
- mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4));
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl);
}
@@ -212,11 +221,13 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
}
static int
-mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni)
+mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni,
+ struct netlink_ext_ack *extack)
{
if (WARN_ON(!netif_is_vxlan(nve_dev)))
return -EINVAL;
- return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier);
+ return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier,
+ extack);
}
static void
@@ -229,7 +240,7 @@ mlxsw_sp_nve_vxlan_clear_offload(const struct net_device *nve_dev, __be32 vni)
const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = {
.type = MLXSW_SP_NVE_TYPE_VXLAN,
- .can_offload = mlxsw_sp1_nve_vxlan_can_offload,
+ .can_offload = mlxsw_sp_nve_vxlan_can_offload,
.nve_config = mlxsw_sp_nve_vxlan_config,
.init = mlxsw_sp1_nve_vxlan_init,
.fini = mlxsw_sp1_nve_vxlan_fini,
@@ -237,26 +248,126 @@ const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = {
.fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload,
};
-static bool mlxsw_sp2_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve,
- const struct net_device *dev,
- struct netlink_ext_ack *extack)
+static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp,
+ bool learning_en)
{
- return false;
+ char tnpc_pl[MLXSW_REG_TNPC_LEN];
+
+ mlxsw_reg_tnpc_pack(tnpc_pl, MLXSW_REG_TNPC_TUNNEL_PORT_NVE,
+ learning_en);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tnpc), tnpc_pl);
+}
+
+static int
+mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_nve_config *config)
+{
+ char tngcr_pl[MLXSW_REG_TNGCR_LEN];
+ u16 ul_rif_index;
+ int err;
+
+ err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, config->ul_tb_id,
+ &ul_rif_index);
+ if (err)
+ return err;
+ mlxsw_sp->nve->ul_rif_index = ul_rif_index;
+
+ err = mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, config->learning_en);
+ if (err)
+ goto err_vxlan_learning_set;
+
+ mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config);
+ mlxsw_reg_tngcr_underlay_rif_set(tngcr_pl, ul_rif_index);
+
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl);
+ if (err)
+ goto err_tngcr_write;
+
+ return 0;
+
+err_tngcr_write:
+ mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false);
+err_vxlan_learning_set:
+ mlxsw_sp_router_ul_rif_put(mlxsw_sp, ul_rif_index);
+ return err;
+}
+
+static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp)
+{
+ char tngcr_pl[MLXSW_REG_TNGCR_LEN];
+
+ mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl);
+ mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false);
+ mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->nve->ul_rif_index);
+}
+
+static int mlxsw_sp2_nve_vxlan_rtdp_set(struct mlxsw_sp *mlxsw_sp,
+ unsigned int tunnel_index,
+ u16 ul_rif_index)
+{
+ char rtdp_pl[MLXSW_REG_RTDP_LEN];
+
+ mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_NVE, tunnel_index);
+ mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_index);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl);
}
static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
const struct mlxsw_sp_nve_config *config)
{
- return -EOPNOTSUPP;
+ struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
+ int err;
+
+ err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
+ MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
+ config->udp_dport);
+ if (err)
+ return err;
+
+ err = mlxsw_sp2_nve_vxlan_config_set(mlxsw_sp, config);
+ if (err)
+ goto err_config_set;
+
+ err = mlxsw_sp2_nve_vxlan_rtdp_set(mlxsw_sp, nve->tunnel_index,
+ nve->ul_rif_index);
+ if (err)
+ goto err_rtdp_set;
+
+ err = mlxsw_sp_router_nve_promote_decap(mlxsw_sp, config->ul_tb_id,
+ config->ul_proto,
+ &config->ul_sip,
+ nve->tunnel_index);
+ if (err)
+ goto err_promote_decap;
+
+ return 0;
+
+err_promote_decap:
+err_rtdp_set:
+ mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
+err_config_set:
+ mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
+ config->udp_dport);
+ return err;
}
static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
{
+ struct mlxsw_sp_nve_config *config = &nve->config;
+ struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
+
+ mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
+ config->ul_proto, &config->ul_sip);
+ mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
+ mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
+ config->udp_dport);
}
const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
.type = MLXSW_SP_NVE_TYPE_VXLAN,
- .can_offload = mlxsw_sp2_nve_vxlan_can_offload,
+ .can_offload = mlxsw_sp_nve_vxlan_can_offload,
.nve_config = mlxsw_sp_nve_vxlan_config,
.init = mlxsw_sp2_nve_vxlan_init,
.fini = mlxsw_sp2_nve_vxlan_fini,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 98e5ffd71b91..52fed8c7bf1e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -80,7 +80,7 @@ struct mlxsw_sp_router {
struct mlxsw_sp_rif {
struct list_head nexthop_list;
struct list_head neigh_list;
- struct net_device *dev;
+ struct net_device *dev; /* NULL for underlay RIF */
struct mlxsw_sp_fid *fid;
unsigned char addr[ETH_ALEN];
int mtu;
@@ -120,6 +120,7 @@ struct mlxsw_sp_rif_ipip_lb {
struct mlxsw_sp_rif common;
struct mlxsw_sp_rif_ipip_lb_config lb_config;
u16 ul_vr_id; /* Reserved for Spectrum-2. */
+ u16 ul_rif_id; /* Reserved for Spectrum. */
};
struct mlxsw_sp_rif_params_ipip_lb {
@@ -363,6 +364,7 @@ enum mlxsw_sp_fib_entry_type {
MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
+ MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
/* This is a special case of local delivery, where a packet should be
* decapsulated on reception. Note that there is no corresponding ENCAP,
@@ -440,6 +442,8 @@ struct mlxsw_sp_vr {
struct mlxsw_sp_fib *fib4;
struct mlxsw_sp_fib *fib6;
struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX];
+ struct mlxsw_sp_rif *ul_rif;
+ refcount_t ul_rif_refcnt;
};
static const struct rhashtable_params mlxsw_sp_fib_ht_params;
@@ -1437,8 +1441,8 @@ mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp,
}
static int
-mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
- struct mlxsw_sp_vr *ul_vr, bool enable)
+mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
+ u16 ul_rif_id, bool enable)
{
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
struct mlxsw_sp_rif *rif = &lb_rif->common;
@@ -1453,7 +1457,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
rif->rif_index, rif->vr_id, rif->dev->mtu);
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
- ul_vr->id, saddr4, lb_cf.okey);
+ ul_vr_id, ul_rif_id, saddr4, lb_cf.okey);
break;
case MLXSW_SP_L3_PROTO_IPV6:
@@ -1468,14 +1472,13 @@ static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_ipip_entry *ipip_entry;
struct mlxsw_sp_rif_ipip_lb *lb_rif;
- struct mlxsw_sp_vr *ul_vr;
int err = 0;
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
if (ipip_entry) {
lb_rif = ipip_entry->ol_lb;
- ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
- err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
+ err = mlxsw_sp_rif_ipip_lb_op(lb_rif, lb_rif->ul_vr_id,
+ lb_rif->ul_rif_id, true);
if (err)
goto out;
lb_rif->common.mtu = ol_dev->mtu;
@@ -3811,13 +3814,11 @@ mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
struct mlxsw_sp_nexthop_group *nh_grp;
struct mlxsw_sp_nexthop *nh;
struct fib_nh *fib_nh;
- size_t alloc_size;
int i;
int err;
- alloc_size = sizeof(*nh_grp) +
- fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop);
- nh_grp = kzalloc(alloc_size, GFP_KERNEL);
+ nh_grp = kzalloc(struct_size(nh_grp, nexthops, fi->fib_nhs),
+ GFP_KERNEL);
if (!nh_grp)
return ERR_PTR(-ENOMEM);
nh_grp->priv = fi;
@@ -3926,6 +3927,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
return !!nh_group->adj_index_valid;
case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
return !!nh_group->nh_rif;
+ case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
return true;
@@ -3961,6 +3963,7 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
int i;
if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
+ fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE ||
fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ||
fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP) {
nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
@@ -4002,7 +4005,8 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
common);
- if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) {
+ if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
+ fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) {
list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
return;
@@ -4170,6 +4174,19 @@ static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
}
+static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_fib_entry *fib_entry,
+ enum mlxsw_reg_ralue_op op)
+{
+ enum mlxsw_reg_ralue_trap_action trap_action;
+ char ralue_pl[MLXSW_REG_RALUE_LEN];
+
+ trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR;
+ mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
+ mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
+}
+
static int
mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry,
@@ -4209,6 +4226,8 @@ static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
+ case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
+ return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
fib_entry, op);
@@ -4277,8 +4296,10 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
case RTN_BROADCAST:
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
return 0;
+ case RTN_BLACKHOLE:
+ fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
+ return 0;
case RTN_UNREACHABLE: /* fall through */
- case RTN_BLACKHOLE: /* fall through */
case RTN_PROHIBIT:
/* Packets hitting these routes need to be trapped, but
* can do so with a lower priority than packets directed
@@ -5043,13 +5064,11 @@ mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop_group *nh_grp;
struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
struct mlxsw_sp_nexthop *nh;
- size_t alloc_size;
int i = 0;
int err;
- alloc_size = sizeof(*nh_grp) +
- fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop);
- nh_grp = kzalloc(alloc_size, GFP_KERNEL);
+ nh_grp = kzalloc(struct_size(nh_grp, nexthops, fib6_entry->nrt6),
+ GFP_KERNEL);
if (!nh_grp)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&nh_grp->fib_list);
@@ -5227,6 +5246,8 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
*/
if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
+ else if (rt->fib6_type == RTN_BLACKHOLE)
+ fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
else if (rt->fib6_flags & RTF_REJECT)
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
@@ -6121,7 +6142,7 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
- if (WARN_ON_ONCE(err))
+ if (err)
return err;
mlxsw_reg_ritr_enable_set(ritr_pl, false);
@@ -6224,10 +6245,12 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
INIT_LIST_HEAD(&rif->nexthop_list);
INIT_LIST_HEAD(&rif->neigh_list);
- ether_addr_copy(rif->addr, l3_dev->dev_addr);
- rif->mtu = l3_dev->mtu;
+ if (l3_dev) {
+ ether_addr_copy(rif->addr, l3_dev->dev_addr);
+ rif->mtu = l3_dev->mtu;
+ rif->dev = l3_dev;
+ }
rif->vr_id = vr_id;
- rif->dev = l3_dev;
rif->rif_index = rif_index;
return rif;
@@ -6251,7 +6274,19 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
{
- return lb_rif->ul_vr_id;
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev);
+ struct mlxsw_sp_vr *ul_vr;
+
+ ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL);
+ if (WARN_ON(IS_ERR(ul_vr)))
+ return 0;
+
+ return ul_vr->id;
+}
+
+u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
+{
+ return lb_rif->ul_rif_id;
}
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
@@ -6284,7 +6319,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
int i, err;
type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
- ops = mlxsw_sp->router->rif_ops_arr[type];
+ ops = mlxsw_sp->rif_ops_arr[type];
vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack);
if (IS_ERR(vr))
@@ -6303,6 +6338,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
goto err_rif_alloc;
}
dev_hold(rif->dev);
+ mlxsw_sp->router->rifs[rif_index] = rif;
rif->mlxsw_sp = mlxsw_sp;
rif->ops = ops;
@@ -6329,7 +6365,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
}
mlxsw_sp_rif_counters_alloc(rif);
- mlxsw_sp->router->rifs[rif_index] = rif;
return rif;
@@ -6341,6 +6376,7 @@ err_configure:
if (fid)
mlxsw_sp_fid_put(fid);
err_fid_get:
+ mlxsw_sp->router->rifs[rif_index] = NULL;
dev_put(rif->dev);
kfree(rif);
err_rif_alloc:
@@ -6361,7 +6397,6 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
vr = &mlxsw_sp->router->vrs[rif->vr_id];
- mlxsw_sp->router->rifs[rif->rif_index] = NULL;
mlxsw_sp_rif_counters_free(rif);
for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
@@ -6369,6 +6404,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
if (fid)
/* Loopback RIFs are not associated with a FID. */
mlxsw_sp_fid_put(fid);
+ mlxsw_sp->router->rifs[rif->rif_index] = NULL;
dev_put(rif->dev);
kfree(rif);
vr->rif_count--;
@@ -6750,7 +6786,7 @@ static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp *mlxsw_sp,
for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
rif = mlxsw_sp->router->rifs[i];
- if (rif && rif->dev != dev &&
+ if (rif && rif->dev && rif->dev != dev &&
!ether_addr_equal_masked(rif->dev->dev_addr, dev_addr,
mlxsw_sp->mac_mask)) {
NL_SET_ERR_MSG_MOD(extack, "All router interface MAC addresses must have the same prefix");
@@ -7294,7 +7330,8 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
info.addr = mac;
info.vid = vid;
- call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info);
+ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
+ NULL);
}
static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = {
@@ -7381,7 +7418,8 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
info.addr = mac;
info.vid = 0;
- call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info);
+ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
+ NULL);
}
static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
@@ -7422,7 +7460,7 @@ mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
}
static int
-mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
+mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
@@ -7434,11 +7472,12 @@ mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
if (IS_ERR(ul_vr))
return PTR_ERR(ul_vr);
- err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
+ err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true);
if (err)
goto err_loopback_op;
lb_rif->ul_vr_id = ul_vr->id;
+ lb_rif->ul_rif_id = 0;
++ul_vr->rif_count;
return 0;
@@ -7447,32 +7486,213 @@ err_loopback_op:
return err;
}
-static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
+static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_vr *ul_vr;
ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
- mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false);
+ mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, false);
--ul_vr->rif_count;
mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
}
-static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = {
+static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops = {
+ .type = MLXSW_SP_RIF_TYPE_IPIP_LB,
+ .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb),
+ .setup = mlxsw_sp_rif_ipip_lb_setup,
+ .configure = mlxsw_sp1_rif_ipip_lb_configure,
+ .deconfigure = mlxsw_sp1_rif_ipip_lb_deconfigure,
+};
+
+const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = {
+ [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops,
+ [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops,
+ [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops,
+ [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp1_rif_ipip_lb_ops,
+};
+
+static int
+mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
+{
+ struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
+ char ritr_pl[MLXSW_REG_RITR_LEN];
+
+ mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
+ ul_rif->rif_index, ul_rif->vr_id, IP_MAX_MTU);
+ mlxsw_reg_ritr_loopback_protocol_set(ritr_pl,
+ MLXSW_REG_RITR_LOOPBACK_GENERIC);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
+}
+
+static struct mlxsw_sp_rif *
+mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_sp_rif *ul_rif;
+ u16 rif_index;
+ int err;
+
+ err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
+ return ERR_PTR(err);
+ }
+
+ ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
+ if (!ul_rif)
+ return ERR_PTR(-ENOMEM);
+
+ mlxsw_sp->router->rifs[rif_index] = ul_rif;
+ ul_rif->mlxsw_sp = mlxsw_sp;
+ err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true);
+ if (err)
+ goto ul_rif_op_err;
+
+ return ul_rif;
+
+ul_rif_op_err:
+ mlxsw_sp->router->rifs[rif_index] = NULL;
+ kfree(ul_rif);
+ return ERR_PTR(err);
+}
+
+static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
+{
+ struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
+
+ mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
+ mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
+ kfree(ul_rif);
+}
+
+static struct mlxsw_sp_rif *
+mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_sp_vr *vr;
+ int err;
+
+ vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, extack);
+ if (IS_ERR(vr))
+ return ERR_CAST(vr);
+
+ if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
+ return vr->ul_rif;
+
+ vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
+ if (IS_ERR(vr->ul_rif)) {
+ err = PTR_ERR(vr->ul_rif);
+ goto err_ul_rif_create;
+ }
+
+ vr->rif_count++;
+ refcount_set(&vr->ul_rif_refcnt, 1);
+
+ return vr->ul_rif;
+
+err_ul_rif_create:
+ mlxsw_sp_vr_put(mlxsw_sp, vr);
+ return ERR_PTR(err);
+}
+
+static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif)
+{
+ struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
+ struct mlxsw_sp_vr *vr;
+
+ vr = &mlxsw_sp->router->vrs[ul_rif->vr_id];
+
+ if (!refcount_dec_and_test(&vr->ul_rif_refcnt))
+ return;
+
+ vr->rif_count--;
+ mlxsw_sp_ul_rif_destroy(ul_rif);
+ mlxsw_sp_vr_put(mlxsw_sp, vr);
+}
+
+int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
+ u16 *ul_rif_index)
+{
+ struct mlxsw_sp_rif *ul_rif;
+
+ ASSERT_RTNL();
+
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ if (IS_ERR(ul_rif))
+ return PTR_ERR(ul_rif);
+ *ul_rif_index = ul_rif->rif_index;
+
+ return 0;
+}
+
+void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index)
+{
+ struct mlxsw_sp_rif *ul_rif;
+
+ ASSERT_RTNL();
+
+ ul_rif = mlxsw_sp->router->rifs[ul_rif_index];
+ if (WARN_ON(!ul_rif))
+ return;
+
+ mlxsw_sp_ul_rif_put(ul_rif);
+}
+
+static int
+mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
+{
+ struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
+ struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
+ struct mlxsw_sp_rif *ul_rif;
+ int err;
+
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ if (IS_ERR(ul_rif))
+ return PTR_ERR(ul_rif);
+
+ err = mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, ul_rif->rif_index, true);
+ if (err)
+ goto err_loopback_op;
+
+ lb_rif->ul_vr_id = 0;
+ lb_rif->ul_rif_id = ul_rif->rif_index;
+
+ return 0;
+
+err_loopback_op:
+ mlxsw_sp_ul_rif_put(ul_rif);
+ return err;
+}
+
+static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
+{
+ struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
+ struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
+ struct mlxsw_sp_rif *ul_rif;
+
+ ul_rif = mlxsw_sp_rif_by_index(mlxsw_sp, lb_rif->ul_rif_id);
+ mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, lb_rif->ul_rif_id, false);
+ mlxsw_sp_ul_rif_put(ul_rif);
+}
+
+static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = {
.type = MLXSW_SP_RIF_TYPE_IPIP_LB,
.rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb),
.setup = mlxsw_sp_rif_ipip_lb_setup,
- .configure = mlxsw_sp_rif_ipip_lb_configure,
- .deconfigure = mlxsw_sp_rif_ipip_lb_deconfigure,
+ .configure = mlxsw_sp2_rif_ipip_lb_configure,
+ .deconfigure = mlxsw_sp2_rif_ipip_lb_deconfigure,
};
-static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = {
+const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = {
[MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops,
[MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops,
[MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops,
- [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp_rif_ipip_lb_ops,
+ [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp2_rif_ipip_lb_ops,
};
static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
@@ -7485,8 +7705,6 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
if (!mlxsw_sp->router->rifs)
return -ENOMEM;
- mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr;
-
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 3dbafdeaab2b..cc1de91e8217 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -29,6 +29,7 @@ struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif);
u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *rif);
u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif);
+u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif);
u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev);
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif);
const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index ad5a9b9e1466..536c23c578c3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
- 0, 0, parms.link, tun->fwmark);
+ 0, 0, parms.link, tun->fwmark, 0);
rt = ip_route_output_key(tun->net, &fl4);
if (IS_ERR(rt))
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 1bd2c6e15f8d..f6ce386c3036 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -431,46 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan)
mlxsw_sp_bridge_vlan_destroy(bridge_vlan);
}
-static void mlxsw_sp_port_bridge_flags_get(struct mlxsw_sp_bridge *bridge,
- struct net_device *dev,
- unsigned long *brport_flags)
-{
- struct mlxsw_sp_bridge_port *bridge_port;
-
- bridge_port = mlxsw_sp_bridge_port_find(bridge, dev);
- if (WARN_ON(!bridge_port))
- return;
-
- memcpy(brport_flags, &bridge_port->flags, sizeof(*brport_flags));
-}
-
-static int mlxsw_sp_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac);
- memcpy(&attr->u.ppid.id, &mlxsw_sp->base_mac,
- attr->u.ppid.id_len);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
- mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev,
- &attr->u.brport_flags);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD |
- BR_MCAST_FLOOD;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
static int
mlxsw_sp_port_bridge_vlan_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_bridge_vlan *bridge_vlan,
@@ -620,6 +580,17 @@ err_port_bridge_vlan_learning_set:
return err;
}
+static int mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port
+ *mlxsw_sp_port,
+ struct switchdev_trans *trans,
+ unsigned long brport_flags)
+{
+ if (brport_flags & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD))
+ return -EINVAL;
+
+ return 0;
+}
+
static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct switchdev_trans *trans,
struct net_device *orig_dev,
@@ -866,6 +837,11 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
attr->orig_dev,
attr->u.stp_state);
break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port,
+ trans,
+ attr->u.brport_flags);
+ break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans,
attr->orig_dev,
@@ -1078,8 +1054,7 @@ static int
mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port,
u16 vid, bool is_untagged, bool is_pvid,
- struct netlink_ext_ack *extack,
- struct switchdev_trans *trans)
+ struct netlink_ext_ack *extack)
{
u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
@@ -1095,9 +1070,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port_vlan->bridge_port != bridge_port)
return -EEXIST;
- if (switchdev_trans_ph_prepare(trans))
- return 0;
-
if (!mlxsw_sp_port_vlan) {
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
vid);
@@ -1188,6 +1160,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
return err;
}
+ if (switchdev_trans_ph_commit(trans))
+ return 0;
+
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (WARN_ON(!bridge_port))
return -EINVAL;
@@ -1200,7 +1175,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
vid, flag_untagged,
- flag_pvid, extack, trans);
+ flag_pvid, extack);
if (err)
return err;
}
@@ -1234,7 +1209,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
{
return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
- MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+ MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
}
static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
@@ -1291,7 +1266,7 @@ out:
static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
const char *mac, u16 fid, bool adding,
enum mlxsw_reg_sfd_rec_action action,
- bool dynamic)
+ enum mlxsw_reg_sfd_rec_policy policy)
{
char *sfd_pl;
u8 num_rec;
@@ -1302,8 +1277,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
return -ENOMEM;
mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
- mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
- mac, fid, action, local_port);
+ mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
if (err)
@@ -1322,7 +1296,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
bool dynamic)
{
return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
- MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
+ MLXSW_REG_SFD_REC_ACTION_NOP,
+ mlxsw_sp_sfd_rec_policy(dynamic));
}
int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
@@ -1330,7 +1305,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
{
return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
- false);
+ MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
}
static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
@@ -1808,7 +1783,7 @@ static void
mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port, u16 vid)
{
- u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid;
+ u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
@@ -1963,11 +1938,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
return NULL;
}
-static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
- .switchdev_port_attr_get = mlxsw_sp_port_attr_get,
- .switchdev_port_attr_set = mlxsw_sp_port_attr_set,
-};
-
static int
mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device,
struct mlxsw_sp_bridge_port *bridge_port,
@@ -2028,6 +1998,7 @@ mlxsw_sp_bridge_8021q_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device,
return 0;
if (mlxsw_sp_fid_vni_is_set(fid)) {
+ NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID");
err = -EINVAL;
goto err_vni_exists;
}
@@ -2214,10 +2185,13 @@ mlxsw_sp_bridge_8021d_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device,
int err;
fid = mlxsw_sp_fid_8021d_lookup(mlxsw_sp, bridge_device->dev->ifindex);
- if (!fid)
+ if (!fid) {
+ NL_SET_ERR_MSG_MOD(extack, "Did not find a corresponding FID");
return -EINVAL;
+ }
if (mlxsw_sp_fid_vni_is_set(fid)) {
+ NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID");
err = -EINVAL;
goto err_vni_exists;
}
@@ -2444,7 +2418,7 @@ static void mlxsw_sp_fdb_vxlan_call_notifiers(struct net_device *dev,
ether_addr_copy(info.eth_addr, mac);
info.vni = vni;
info.offloaded = adding;
- call_switchdev_notifiers(type, dev, &info.info);
+ call_switchdev_notifiers(type, dev, &info.info, NULL);
}
static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev,
@@ -2469,7 +2443,7 @@ mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
info.addr = mac;
info.vid = vid;
info.offloaded = offloaded;
- call_switchdev_notifiers(type, dev, &info.info);
+ call_switchdev_notifiers(type, dev, &info.info, NULL);
}
static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
@@ -2820,7 +2794,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp,
return;
vxlan_fdb_info.offloaded = true;
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
- &vxlan_fdb_info.info);
+ &vxlan_fdb_info.info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info.eth_addr,
fdb_info->vid, dev, true);
@@ -2833,7 +2807,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp,
false);
vxlan_fdb_info.offloaded = false;
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
- &vxlan_fdb_info.info);
+ &vxlan_fdb_info.info, NULL);
break;
}
}
@@ -2978,7 +2952,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp,
}
vxlan_fdb_info->offloaded = true;
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
- &vxlan_fdb_info->info);
+ &vxlan_fdb_info->info, NULL);
mlxsw_sp_fid_put(fid);
return;
}
@@ -2999,7 +2973,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp,
goto err_fdb_tunnel_uc_op;
vxlan_fdb_info->offloaded = true;
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
- &vxlan_fdb_info->info);
+ &vxlan_fdb_info->info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info->eth_addr, vid, dev, true);
@@ -3100,23 +3074,34 @@ mlxsw_sp_switchdev_vxlan_work_prepare(struct mlxsw_sp_switchdev_event_work *
struct vxlan_dev *vxlan = netdev_priv(switchdev_work->dev);
struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info;
struct vxlan_config *cfg = &vxlan->cfg;
+ struct netlink_ext_ack *extack;
+ extack = switchdev_notifier_info_to_extack(info);
vxlan_fdb_info = container_of(info,
struct switchdev_notifier_vxlan_fdb_info,
info);
- if (vxlan_fdb_info->remote_port != cfg->dst_port)
- return -EOPNOTSUPP;
- if (vxlan_fdb_info->remote_vni != cfg->vni)
+ if (vxlan_fdb_info->remote_port != cfg->dst_port) {
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default remote port is not supported");
return -EOPNOTSUPP;
- if (vxlan_fdb_info->vni != cfg->vni)
+ }
+ if (vxlan_fdb_info->remote_vni != cfg->vni ||
+ vxlan_fdb_info->vni != cfg->vni) {
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default VNI is not supported");
return -EOPNOTSUPP;
- if (vxlan_fdb_info->remote_ifindex)
+ }
+ if (vxlan_fdb_info->remote_ifindex) {
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Local interface is not supported");
return -EOPNOTSUPP;
- if (is_multicast_ether_addr(vxlan_fdb_info->eth_addr))
+ }
+ if (is_multicast_ether_addr(vxlan_fdb_info->eth_addr)) {
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast MAC addresses not supported");
return -EOPNOTSUPP;
- if (vxlan_addr_multicast(&vxlan_fdb_info->remote_ip))
+ }
+ if (vxlan_addr_multicast(&vxlan_fdb_info->remote_ip)) {
+ NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast destination IP is not supported");
return -EOPNOTSUPP;
+ }
switchdev_work->vxlan_fdb_info = *vxlan_fdb_info;
@@ -3134,6 +3119,13 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
struct net_device *br_dev;
int err;
+ if (event == SWITCHDEV_PORT_ATTR_SET) {
+ err = switchdev_handle_port_attr_set(dev, ptr,
+ mlxsw_sp_port_dev_check,
+ mlxsw_sp_port_attr_set);
+ return notifier_from_errno(err);
+ }
+
/* Tunnel devices are not our uppers, so check their master instead */
br_dev = netdev_master_upper_dev_get_rcu(dev);
if (!br_dev)
@@ -3207,7 +3199,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_bridge_device *bridge_device,
const struct net_device *vxlan_dev, u16 vid,
bool flag_untagged, bool flag_pvid,
- struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
@@ -3222,11 +3213,10 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
* the lookup function to return 'vxlan_dev'
*/
if (flag_untagged && flag_pvid &&
- mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid))
+ mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) {
+ NL_SET_ERR_MSG_MOD(extack, "VLAN already mapped to a different VNI");
return -EINVAL;
-
- if (switchdev_trans_ph_prepare(trans))
- return 0;
+ }
if (!netif_running(vxlan_dev))
return 0;
@@ -3345,6 +3335,9 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
port_obj_info->handled = true;
+ if (switchdev_trans_ph_commit(trans))
+ return 0;
+
bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
if (!bridge_device)
return -EINVAL;
@@ -3358,8 +3351,7 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device,
vxlan_dev, vid,
flag_untagged,
- flag_pvid, trans,
- extack);
+ flag_pvid, extack);
if (err)
return err;
}
@@ -3457,6 +3449,11 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
mlxsw_sp_port_dev_check,
mlxsw_sp_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = switchdev_handle_port_attr_set(dev, ptr,
+ mlxsw_sp_port_dev_check,
+ mlxsw_sp_port_attr_set);
+ return notifier_from_errno(err);
}
return NOTIFY_DONE;
@@ -3544,11 +3541,3 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
kfree(mlxsw_sp->bridge);
}
-void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
-{
- mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;
-}
-
-void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port)
-{
-}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 2d4f213e154d..533fe6235b7c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -11,7 +11,6 @@
#include <linux/device.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
-#include <net/switchdev.h>
#include "pci.h"
#include "core.h"
@@ -390,6 +389,18 @@ static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name,
name, len);
}
+static int mlxsw_sx_port_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
+ struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
+
+ ppid->id_len = sizeof(mlxsw_sx->hw_id);
+ memcpy(&ppid->id, &mlxsw_sx->hw_id, ppid->id_len);
+
+ return 0;
+}
+
static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
.ndo_open = mlxsw_sx_port_open,
.ndo_stop = mlxsw_sx_port_stop,
@@ -397,6 +408,7 @@ static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
.ndo_change_mtu = mlxsw_sx_port_change_mtu,
.ndo_get_stats64 = mlxsw_sx_port_get_stats64,
.ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name,
+ .ndo_get_port_parent_id = mlxsw_sx_port_get_port_parent_id,
};
static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
@@ -901,28 +913,6 @@ static const struct ethtool_ops mlxsw_sx_port_ethtool_ops = {
.set_link_ksettings = mlxsw_sx_port_set_link_ksettings,
};
-static int mlxsw_sx_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
- struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id);
- memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
- .switchdev_port_attr_get = mlxsw_sx_port_attr_get,
-};
-
static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx)
{
char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
@@ -1034,7 +1024,6 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
dev->netdev_ops = &mlxsw_sx_port_netdev_ops;
dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops;
- dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops;
err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port);
if (err) {
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index b881f5d4a7f9..6006d47707cb 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -391,7 +391,7 @@ ks8695_tx_irq(int irq, void *dev_id)
ksp->tx_buffers[buff_n].dma_ptr,
ksp->tx_buffers[buff_n].length,
DMA_TO_DEVICE);
- dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
+ dev_consume_skb_irq(ksp->tx_buffers[buff_n].skb);
ksp->tx_buffers[buff_n].skb = NULL;
ksp->tx_ring_used--;
}
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index f6ecfa778660..8f72587b5a2c 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1681,5 +1681,5 @@ MODULE_DESCRIPTION(DRV_NAME " ethernet driver");
MODULE_AUTHOR("Claudio Lanconelli <lanconelli.claudio@eptar.com>");
MODULE_LICENSE("GPL");
module_param_named(debug, debug.msg_enable, int, 0);
-MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., ffff=all)");
+MODULE_PARM_DESC(debug, "Debug verbosity level in amount of bits set (0=none, ..., 31=all)");
MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 07c1eb63415a..3a0b289d9771 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -14,61 +14,138 @@
#define EEPROM_INDICATOR_1 (0xA5)
#define EEPROM_INDICATOR_2 (0xAA)
#define EEPROM_MAC_OFFSET (0x01)
-#define MAX_EEPROM_SIZE 512
+#define MAX_EEPROM_SIZE (512)
+#define MAX_OTP_SIZE (1024)
#define OTP_INDICATOR_1 (0xF3)
#define OTP_INDICATOR_2 (0xF7)
-static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
- u32 length, u8 *data)
+static int lan743x_otp_power_up(struct lan743x_adapter *adapter)
+{
+ u32 reg_value;
+
+ reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
+
+ if (reg_value & OTP_PWR_DN_PWRDN_N_) {
+ /* clear it and wait to be cleared */
+ reg_value &= ~OTP_PWR_DN_PWRDN_N_;
+ lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
+
+ usleep_range(100, 20000);
+ }
+
+ return 0;
+}
+
+static void lan743x_otp_power_down(struct lan743x_adapter *adapter)
+{
+ u32 reg_value;
+
+ reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
+ if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) {
+ /* set power down bit */
+ reg_value |= OTP_PWR_DN_PWRDN_N_;
+ lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
+ }
+}
+
+static void lan743x_otp_set_address(struct lan743x_adapter *adapter,
+ u32 address)
+{
+ lan743x_csr_write(adapter, OTP_ADDR_HIGH, (address >> 8) & 0x03);
+ lan743x_csr_write(adapter, OTP_ADDR_LOW, address & 0xFF);
+}
+
+static void lan743x_otp_read_go(struct lan743x_adapter *adapter)
+{
+ lan743x_csr_write(adapter, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+ lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
+}
+
+static int lan743x_otp_wait_till_not_busy(struct lan743x_adapter *adapter)
{
unsigned long timeout;
- u32 buf;
+ u32 reg_val;
+
+ timeout = jiffies + HZ;
+ do {
+ if (time_after(jiffies, timeout)) {
+ netif_warn(adapter, drv, adapter->netdev,
+ "Timeout on OTP_STATUS completion\n");
+ return -EIO;
+ }
+ udelay(1);
+ reg_val = lan743x_csr_read(adapter, OTP_STATUS);
+ } while (reg_val & OTP_STATUS_BUSY_);
+
+ return 0;
+}
+
+static int lan743x_otp_read(struct lan743x_adapter *adapter, u32 offset,
+ u32 length, u8 *data)
+{
+ int ret;
int i;
- buf = lan743x_csr_read(adapter, OTP_PWR_DN);
+ if (offset + length > MAX_OTP_SIZE)
+ return -EINVAL;
- if (buf & OTP_PWR_DN_PWRDN_N_) {
- /* clear it and wait to be cleared */
- lan743x_csr_write(adapter, OTP_PWR_DN, 0);
-
- timeout = jiffies + HZ;
- do {
- udelay(1);
- buf = lan743x_csr_read(adapter, OTP_PWR_DN);
- if (time_after(jiffies, timeout)) {
- netif_warn(adapter, drv, adapter->netdev,
- "timeout on OTP_PWR_DN completion\n");
- return -EIO;
- }
- } while (buf & OTP_PWR_DN_PWRDN_N_);
+ ret = lan743x_otp_power_up(adapter);
+ if (ret < 0)
+ return ret;
+
+ ret = lan743x_otp_wait_till_not_busy(adapter);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < length; i++) {
+ lan743x_otp_set_address(adapter, offset + i);
+
+ lan743x_otp_read_go(adapter);
+ ret = lan743x_otp_wait_till_not_busy(adapter);
+ if (ret < 0)
+ return ret;
+ data[i] = lan743x_csr_read(adapter, OTP_READ_DATA);
}
+ lan743x_otp_power_down(adapter);
+
+ return 0;
+}
+
+static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
+ u32 length, u8 *data)
+{
+ int ret;
+ int i;
+
+ if (offset + length > MAX_OTP_SIZE)
+ return -EINVAL;
+
+ ret = lan743x_otp_power_up(adapter);
+ if (ret < 0)
+ return ret;
+
+ ret = lan743x_otp_wait_till_not_busy(adapter);
+ if (ret < 0)
+ return ret;
+
/* set to BYTE program mode */
lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
for (i = 0; i < length; i++) {
- lan743x_csr_write(adapter, OTP_ADDR1,
- ((offset + i) >> 8) &
- OTP_ADDR1_15_11_MASK_);
- lan743x_csr_write(adapter, OTP_ADDR2,
- ((offset + i) &
- OTP_ADDR2_10_3_MASK_));
+ lan743x_otp_set_address(adapter, offset + i);
+
lan743x_csr_write(adapter, OTP_PRGM_DATA, data[i]);
lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
- timeout = jiffies + HZ;
- do {
- udelay(1);
- buf = lan743x_csr_read(adapter, OTP_STATUS);
- if (time_after(jiffies, timeout)) {
- netif_warn(adapter, drv, adapter->netdev,
- "Timeout on OTP_STATUS completion\n");
- return -EIO;
- }
- } while (buf & OTP_STATUS_BUSY_);
+ ret = lan743x_otp_wait_till_not_busy(adapter);
+ if (ret < 0)
+ return ret;
}
+ lan743x_otp_power_down(adapter);
+
return 0;
}
@@ -120,6 +197,9 @@ static int lan743x_eeprom_read(struct lan743x_adapter *adapter,
u32 val;
int i;
+ if (offset + length > MAX_EEPROM_SIZE)
+ return -EINVAL;
+
retval = lan743x_eeprom_confirm_not_busy(adapter);
if (retval)
return retval;
@@ -148,6 +228,9 @@ static int lan743x_eeprom_write(struct lan743x_adapter *adapter,
u32 val;
int i;
+ if (offset + length > MAX_EEPROM_SIZE)
+ return -EINVAL;
+
retval = lan743x_eeprom_confirm_not_busy(adapter);
if (retval)
return retval;
@@ -207,6 +290,11 @@ static void lan743x_ethtool_set_msglevel(struct net_device *netdev,
static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev)
{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
+ return MAX_OTP_SIZE;
+
return MAX_EEPROM_SIZE;
}
@@ -214,8 +302,14 @@ static int lan743x_ethtool_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *ee, u8 *data)
{
struct lan743x_adapter *adapter = netdev_priv(netdev);
+ int ret = 0;
+
+ if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
+ ret = lan743x_otp_read(adapter, ee->offset, ee->len, data);
+ else
+ ret = lan743x_eeprom_read(adapter, ee->offset, ee->len, data);
- return lan743x_eeprom_read(adapter, ee->offset, ee->len, data);
+ return ret;
}
static int lan743x_ethtool_set_eeprom(struct net_device *netdev,
@@ -224,17 +318,18 @@ static int lan743x_ethtool_set_eeprom(struct net_device *netdev,
struct lan743x_adapter *adapter = netdev_priv(netdev);
int ret = -EINVAL;
- if (ee->magic == LAN743X_EEPROM_MAGIC)
- ret = lan743x_eeprom_write(adapter, ee->offset, ee->len,
- data);
- /* Beware! OTP is One Time Programming ONLY!
- * So do some strict condition check before messing up
- */
- else if ((ee->magic == LAN743X_OTP_MAGIC) &&
- (ee->offset == 0) &&
- (ee->len == MAX_EEPROM_SIZE) &&
- (data[0] == OTP_INDICATOR_1))
- ret = lan743x_otp_write(adapter, ee->offset, ee->len, data);
+ if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) {
+ /* Beware! OTP is One Time Programming ONLY! */
+ if (ee->magic == LAN743X_OTP_MAGIC) {
+ ret = lan743x_otp_write(adapter, ee->offset,
+ ee->len, data);
+ }
+ } else {
+ if (ee->magic == LAN743X_EEPROM_MAGIC) {
+ ret = lan743x_eeprom_write(adapter, ee->offset,
+ ee->len, data);
+ }
+ }
return ret;
}
@@ -360,6 +455,10 @@ static const u32 lan743x_set2_hw_cnt_addr[] = {
STAT_TX_COUNTER_ROLLOVER_STATUS
};
+static const char lan743x_priv_flags_strings[][ETH_GSTRING_LEN] = {
+ "OTP_ACCESS",
+};
+
static void lan743x_ethtool_get_strings(struct net_device *netdev,
u32 stringset, u8 *data)
{
@@ -375,6 +474,10 @@ static void lan743x_ethtool_get_strings(struct net_device *netdev,
lan743x_set2_hw_cnt_strings,
sizeof(lan743x_set2_hw_cnt_strings));
break;
+ case ETH_SS_PRIV_FLAGS:
+ memcpy(data, lan743x_priv_flags_strings,
+ sizeof(lan743x_priv_flags_strings));
+ break;
}
}
@@ -399,6 +502,22 @@ static void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev,
}
}
+static u32 lan743x_ethtool_get_priv_flags(struct net_device *netdev)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->flags;
+}
+
+static int lan743x_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ adapter->flags = flags;
+
+ return 0;
+}
+
static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
@@ -411,6 +530,8 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings);
return ret;
}
+ case ETH_SS_PRIV_FLAGS:
+ return ARRAY_SIZE(lan743x_priv_flags_strings);
default:
return -EOPNOTSUPP;
}
@@ -705,6 +826,8 @@ const struct ethtool_ops lan743x_ethtool_ops = {
.set_eeprom = lan743x_ethtool_set_eeprom,
.get_strings = lan743x_ethtool_get_strings,
.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
+ .get_priv_flags = lan743x_ethtool_get_priv_flags,
+ .set_priv_flags = lan743x_ethtool_set_priv_flags,
.get_sset_count = lan743x_ethtool_get_sset_count,
.get_rxnfc = lan743x_ethtool_get_rxnfc,
.get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 20c9377e99cb..4d1b4a24907f 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -962,13 +962,10 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
memset(&ksettings, 0, sizeof(ksettings));
phy_ethtool_get_link_ksettings(netdev, &ksettings);
- local_advertisement = phy_read(phydev, MII_ADVERTISE);
- if (local_advertisement < 0)
- return;
-
- remote_advertisement = phy_read(phydev, MII_LPA);
- if (remote_advertisement < 0)
- return;
+ local_advertisement =
+ linkmode_adv_to_mii_adv_t(phydev->advertising);
+ remote_advertisement =
+ linkmode_adv_to_mii_adv_t(phydev->lp_advertising);
lan743x_phy_update_flowcontrol(adapter,
ksettings.base.duplex,
@@ -1403,7 +1400,8 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx,
}
static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx,
- unsigned int frame_length)
+ unsigned int frame_length,
+ int nr_frags)
{
/* called only from within lan743x_tx_xmit_frame.
* assuming tx->ring_lock has already been acquired.
@@ -1413,6 +1411,10 @@ static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx,
/* wrap up previous descriptor */
tx->frame_data0 |= TX_DESC_DATA0_EXT_;
+ if (nr_frags <= 0) {
+ tx->frame_data0 |= TX_DESC_DATA0_LS_;
+ tx->frame_data0 |= TX_DESC_DATA0_IOC_;
+ }
tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
tx_descriptor->data0 = tx->frame_data0;
@@ -1517,8 +1519,11 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx,
u32 tx_tail_flags = 0;
/* wrap up previous descriptor */
- tx->frame_data0 |= TX_DESC_DATA0_LS_;
- tx->frame_data0 |= TX_DESC_DATA0_IOC_;
+ if ((tx->frame_data0 & TX_DESC_DATA0_DTYPE_MASK_) ==
+ TX_DESC_DATA0_DTYPE_DATA_) {
+ tx->frame_data0 |= TX_DESC_DATA0_LS_;
+ tx->frame_data0 |= TX_DESC_DATA0_IOC_;
+ }
tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
buffer_info = &tx->buffer_info[tx->frame_tail];
@@ -1603,7 +1608,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
}
if (gso)
- lan743x_tx_frame_add_lso(tx, frame_length);
+ lan743x_tx_frame_add_lso(tx, frame_length, nr_frags);
if (nr_frags <= 0)
goto finish;
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 2d6eea18973e..3b02eeae5f45 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -26,6 +26,8 @@
#define FPGA_REV_GET_MAJOR_(fpga_rev) ((fpga_rev) & 0x000000FF)
#define HW_CFG (0x010)
+#define HW_CFG_RELOAD_TYPE_ALL_ (0x00000FC0)
+#define HW_CFG_EE_OTP_RELOAD_ BIT(4)
#define HW_CFG_LRST_ BIT(1)
#define PMT_CTL (0x014)
@@ -453,17 +455,19 @@
#define OTP_PWR_DN (0x1000)
#define OTP_PWR_DN_PWRDN_N_ BIT(0)
-#define OTP_ADDR1 (0x1004)
-#define OTP_ADDR1_15_11_MASK_ (0x1F)
-
-#define OTP_ADDR2 (0x1008)
-#define OTP_ADDR2_10_3_MASK_ (0xFF)
+#define OTP_ADDR_HIGH (0x1004)
+#define OTP_ADDR_LOW (0x1008)
#define OTP_PRGM_DATA (0x1010)
#define OTP_PRGM_MODE (0x1014)
#define OTP_PRGM_MODE_BYTE_ BIT(0)
+#define OTP_READ_DATA (0x1018)
+
+#define OTP_FUNC_CMD (0x1020)
+#define OTP_FUNC_CMD_READ_ BIT(0)
+
#define OTP_TST_CMD (0x1024)
#define OTP_TST_CMD_PRGVRFY_ BIT(3)
@@ -713,6 +717,9 @@ struct lan743x_adapter {
struct lan743x_phy phy;
struct lan743x_tx tx[LAN743X_MAX_TX_CHANNELS];
struct lan743x_rx rx[LAN743X_MAX_RX_CHANNELS];
+
+#define LAN743X_ADAPTER_FLAG_OTP BIT(0)
+ u32 flags;
};
#define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel))
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index b34055ac476f..e1651756bf9d 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -81,11 +81,13 @@ static void moxart_mac_free_memory(struct net_device *ndev)
priv->rx_buf_size, DMA_FROM_DEVICE);
if (priv->tx_desc_base)
- dma_free_coherent(NULL, TX_REG_DESC_SIZE * TX_DESC_NUM,
+ dma_free_coherent(&priv->pdev->dev,
+ TX_REG_DESC_SIZE * TX_DESC_NUM,
priv->tx_desc_base, priv->tx_base);
if (priv->rx_desc_base)
- dma_free_coherent(NULL, RX_REG_DESC_SIZE * RX_DESC_NUM,
+ dma_free_coherent(&priv->pdev->dev,
+ RX_REG_DESC_SIZE * RX_DESC_NUM,
priv->rx_desc_base, priv->rx_base);
kfree(priv->tx_buf_base);
@@ -298,7 +300,7 @@ static void moxart_tx_finished(struct net_device *ndev)
ndev->stats.tx_packets++;
ndev->stats.tx_bytes += priv->tx_skb[tx_tail]->len;
- dev_kfree_skb_irq(priv->tx_skb[tx_tail]);
+ dev_consume_skb_irq(priv->tx_skb[tx_tail]);
priv->tx_skb[tx_tail] = NULL;
tx_tail = TX_NEXT(tx_tail);
@@ -476,6 +478,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
priv = netdev_priv(ndev);
priv->ndev = ndev;
+ priv->pdev = pdev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ndev->base_addr = res->start;
@@ -491,7 +494,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
priv->tx_buf_size = TX_BUF_SIZE;
priv->rx_buf_size = RX_BUF_SIZE;
- priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE *
+ priv->tx_desc_base = dma_alloc_coherent(&pdev->dev, TX_REG_DESC_SIZE *
TX_DESC_NUM, &priv->tx_base,
GFP_DMA | GFP_KERNEL);
if (!priv->tx_desc_base) {
@@ -499,7 +502,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
goto init_fail;
}
- priv->rx_desc_base = dma_alloc_coherent(NULL, RX_REG_DESC_SIZE *
+ priv->rx_desc_base = dma_alloc_coherent(&pdev->dev, RX_REG_DESC_SIZE *
RX_DESC_NUM, &priv->rx_base,
GFP_DMA | GFP_KERNEL);
if (!priv->rx_desc_base) {
diff --git a/drivers/net/ethernet/moxa/moxart_ether.h b/drivers/net/ethernet/moxa/moxart_ether.h
index bee608b547d1..bf4c3029cd0c 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.h
+++ b/drivers/net/ethernet/moxa/moxart_ether.h
@@ -292,6 +292,7 @@
#define LINK_STATUS 0x4
struct moxart_mac_priv_t {
+ struct platform_device *pdev;
void __iomem *base;
unsigned int reg_maccr;
unsigned int reg_imr;
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 215a45374d7b..a1d0d6e42533 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -721,7 +721,8 @@ static void ocelot_get_stats64(struct net_device *dev,
static int ocelot_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev, const unsigned char *addr,
- u16 vid, u16 flags)
+ u16 vid, u16 flags,
+ struct netlink_ext_ack *extack)
{
struct ocelot_port *port = netdev_priv(dev);
struct ocelot *ocelot = port->ocelot;
@@ -915,6 +916,18 @@ static int ocelot_set_features(struct net_device *dev,
return 0;
}
+static int ocelot_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct ocelot_port *ocelot_port = netdev_priv(dev);
+ struct ocelot *ocelot = ocelot_port->ocelot;
+
+ ppid->id_len = sizeof(ocelot->base_mac);
+ memcpy(&ppid->id, &ocelot->base_mac, ppid->id_len);
+
+ return 0;
+}
+
static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_open = ocelot_port_open,
.ndo_stop = ocelot_port_stop,
@@ -929,6 +942,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_vlan_rx_add_vid = ocelot_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ocelot_vlan_rx_kill_vid,
.ndo_set_features = ocelot_set_features,
+ .ndo_get_port_parent_id = ocelot_get_port_parent_id,
};
static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -1012,25 +1026,6 @@ static const struct ethtool_ops ocelot_ethtool_ops = {
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
-static int ocelot_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- struct ocelot_port *ocelot_port = netdev_priv(dev);
- struct ocelot *ocelot = ocelot_port->ocelot;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(ocelot->base_mac);
- memcpy(&attr->u.ppid.id, &ocelot->base_mac,
- attr->u.ppid.id_len);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
struct switchdev_trans *trans,
u8 state)
@@ -1329,11 +1324,6 @@ static int ocelot_port_obj_del(struct net_device *dev,
return ret;
}
-static const struct switchdev_ops ocelot_port_switchdev_ops = {
- .switchdev_port_attr_get = ocelot_port_attr_get,
- .switchdev_port_attr_set = ocelot_port_attr_set,
-};
-
static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
struct net_device *bridge)
{
@@ -1588,6 +1578,28 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = {
};
EXPORT_SYMBOL(ocelot_netdevice_nb);
+static int ocelot_switchdev_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+ int err;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = switchdev_handle_port_attr_set(dev, ptr,
+ ocelot_netdevice_dev_check,
+ ocelot_port_attr_set);
+ return notifier_from_errno(err);
+ }
+
+ return NOTIFY_DONE;
+}
+
+struct notifier_block ocelot_switchdev_nb __read_mostly = {
+ .notifier_call = ocelot_switchdev_event,
+};
+EXPORT_SYMBOL(ocelot_switchdev_nb);
+
static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1606,6 +1618,11 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
ocelot_netdevice_dev_check,
ocelot_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = switchdev_handle_port_attr_set(dev, ptr,
+ ocelot_netdevice_dev_check,
+ ocelot_port_attr_set);
+ return notifier_from_errno(err);
}
return NOTIFY_DONE;
@@ -1639,7 +1656,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
dev->netdev_ops = &ocelot_port_netdev_ops;
dev->ethtool_ops = &ocelot_ethtool_ops;
- dev->switchdev_ops = &ocelot_port_switchdev_ops;
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXFCS;
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 086775f7b52f..ba3b3380b4d0 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -499,6 +499,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
struct phy_device *phy);
extern struct notifier_block ocelot_netdevice_nb;
+extern struct notifier_block ocelot_switchdev_nb;
extern struct notifier_block ocelot_switchdev_blocking_nb;
#endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index ca3ea2fbfcd0..e7f90101d2e0 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -267,6 +267,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
struct phy *serdes;
void __iomem *regs;
char res_name[8];
+ int phy_mode;
u32 port;
if (of_property_read_u32(portnp, "reg", &port))
@@ -292,11 +293,11 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
if (err)
return err;
- err = of_get_phy_mode(portnp);
- if (err < 0)
+ phy_mode = of_get_phy_mode(portnp);
+ if (phy_mode < 0)
ocelot->ports[port]->phy_mode = PHY_INTERFACE_MODE_NA;
else
- ocelot->ports[port]->phy_mode = err;
+ ocelot->ports[port]->phy_mode = phy_mode;
switch (ocelot->ports[port]->phy_mode) {
case PHY_INTERFACE_MODE_NA:
@@ -304,6 +305,13 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
case PHY_INTERFACE_MODE_SGMII:
break;
case PHY_INTERFACE_MODE_QSGMII:
+ /* Ensure clock signals and speed is set on all
+ * QSGMII links
+ */
+ ocelot_port_writel(ocelot->ports[port],
+ DEV_CLOCK_CFG_LINK_SPEED
+ (OCELOT_SPEED_1000),
+ DEV_CLOCK_CFG);
break;
default:
dev_err(ocelot->dev,
@@ -329,6 +337,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
}
register_netdevice_notifier(&ocelot_netdevice_nb);
+ register_switchdev_notifier(&ocelot_switchdev_nb);
register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
dev_info(&pdev->dev, "Ocelot switch probed\n");
@@ -345,6 +354,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
ocelot_deinit(ocelot);
unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
+ unregister_switchdev_notifier(&ocelot_switchdev_nb);
unregister_netdevice_notifier(&ocelot_netdevice_nb);
return 0;
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 5f384f73007d..e0340f778d8f 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1408,7 +1408,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
if (skb) {
ss->stats.tx_bytes += skb->len;
ss->stats.tx_packets++;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
if (len)
pci_unmap_single(pdev,
dma_unmap_addr(&tx->info[idx],
@@ -3604,9 +3604,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
for (i = 0; i < mgp->num_slices; i++) {
ss = &mgp->ss[i];
bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
- ss->rx_done.entry = dma_zalloc_coherent(&pdev->dev, bytes,
- &ss->rx_done.bus,
- GFP_KERNEL);
+ ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+ &ss->rx_done.bus,
+ GFP_KERNEL);
if (ss->rx_done.entry == NULL)
goto abort;
bytes = sizeof(*ss->fw_stats);
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index b9a1a9f999ea..1a2634cbbb69 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -2173,7 +2173,7 @@ static void netdev_tx_done(struct net_device *dev)
np->tx_skbuff[entry]->len,
PCI_DMA_TODEVICE);
/* Free the original skb. */
- dev_kfree_skb_irq(np->tx_skbuff[entry]);
+ dev_consume_skb_irq(np->tx_skbuff[entry]);
np->tx_skbuff[entry] = NULL;
}
if (netif_queue_stopped(dev) &&
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index 958fced4dacf..9098ee7fe0d1 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -1003,7 +1003,7 @@ static void do_tx_done(struct net_device *ndev)
addr,
len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
atomic_dec(&dev->nr_tx_skbs);
} else
pci_unmap_page(dev->pci_dev,
@@ -1869,56 +1869,28 @@ static unsigned ns83820_mii_write_reg(struct ns83820 *dev, unsigned phy, unsigne
static void ns83820_probe_phy(struct net_device *ndev)
{
struct ns83820 *dev = PRIV(ndev);
- static int first;
- int i;
-#define MII_PHYIDR1 0x02
-#define MII_PHYIDR2 0x03
-
-#if 0
- if (!first) {
- unsigned tmp;
- ns83820_mii_read_reg(dev, 1, 0x09);
- ns83820_mii_write_reg(dev, 1, 0x10, 0x0d3e);
-
- tmp = ns83820_mii_read_reg(dev, 1, 0x00);
- ns83820_mii_write_reg(dev, 1, 0x00, tmp | 0x8000);
- udelay(1300);
- ns83820_mii_read_reg(dev, 1, 0x09);
- }
-#endif
- first = 1;
-
- for (i=1; i<2; i++) {
- int j;
- unsigned a, b;
- a = ns83820_mii_read_reg(dev, i, MII_PHYIDR1);
- b = ns83820_mii_read_reg(dev, i, MII_PHYIDR2);
-
- //printk("%s: phy %d: 0x%04x 0x%04x\n",
- // ndev->name, i, a, b);
-
- for (j=0; j<0x16; j+=4) {
- dprintk("%s: [0x%02x] %04x %04x %04x %04x\n",
- ndev->name, j,
- ns83820_mii_read_reg(dev, i, 0 + j),
- ns83820_mii_read_reg(dev, i, 1 + j),
- ns83820_mii_read_reg(dev, i, 2 + j),
- ns83820_mii_read_reg(dev, i, 3 + j)
- );
- }
- }
- {
- unsigned a, b;
- /* read firmware version: memory addr is 0x8402 and 0x8403 */
- ns83820_mii_write_reg(dev, 1, 0x16, 0x000d);
- ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e);
- a = ns83820_mii_read_reg(dev, 1, 0x1d);
-
- ns83820_mii_write_reg(dev, 1, 0x16, 0x000d);
- ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e);
- b = ns83820_mii_read_reg(dev, 1, 0x1d);
- dprintk("version: 0x%04x 0x%04x\n", a, b);
+ int j;
+ unsigned a, b;
+
+ for (j = 0; j < 0x16; j += 4) {
+ dprintk("%s: [0x%02x] %04x %04x %04x %04x\n",
+ ndev->name, j,
+ ns83820_mii_read_reg(dev, 1, 0 + j),
+ ns83820_mii_read_reg(dev, 1, 1 + j),
+ ns83820_mii_read_reg(dev, 1, 2 + j),
+ ns83820_mii_read_reg(dev, 1, 3 + j)
+ );
}
+
+ /* read firmware version: memory addr is 0x8402 and 0x8403 */
+ ns83820_mii_write_reg(dev, 1, 0x16, 0x000d);
+ ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e);
+ a = ns83820_mii_read_reg(dev, 1, 0x1d);
+
+ ns83820_mii_write_reg(dev, 1, 0x16, 0x000d);
+ ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e);
+ b = ns83820_mii_read_reg(dev, 1, 0x1d);
+ dprintk("version: 0x%04x 0x%04x\n", a, b);
}
#endif
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index c805dcbebd02..aaec00912ea0 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -328,7 +328,7 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id)
}
/* We must free the original skb */
- dev_kfree_skb_irq(lp->tx_skb[entry]);
+ dev_consume_skb_irq(lp->tx_skb[entry]);
lp->tx_skb[entry] = NULL;
/* and unmap DMA buffer */
dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE);
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 82be90075695..feda9644289d 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -3055,7 +3055,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
/* Updating the statistics block */
swstats->mem_freed += skb->truesize;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
get_info.offset++;
if (get_info.offset == get_info.fifo_len + 1)
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 5ae3fa82909f..b877acec5cde 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -114,7 +114,7 @@ static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo)
/* free SKBs */
for (temp = completed; temp != skb_ptr; temp++)
- dev_kfree_skb_irq(*temp);
+ dev_consume_skb_irq(*temp);
} while (more);
}
@@ -2553,7 +2553,7 @@ static int vxge_add_isr(struct vxgedev *vdev)
vxge_debug_init(VXGE_ERR,
"%s: Defaulting to INTA",
vdev->ndev->name);
- goto INTA_MODE;
+ goto INTA_MODE;
}
msix_idx = (vdev->vpaths[0].handle->vpath->vp_id *
diff --git a/drivers/net/ethernet/netronome/Kconfig b/drivers/net/ethernet/netronome/Kconfig
index 66f15b05b65e..549898d5d450 100644
--- a/drivers/net/ethernet/netronome/Kconfig
+++ b/drivers/net/ethernet/netronome/Kconfig
@@ -19,7 +19,6 @@ config NFP
tristate "Netronome(R) NFP4000/NFP6000 NIC driver"
depends on PCI && PCI_MSI
depends on VXLAN || VXLAN=n
- depends on MAY_USE_DEVLINK
---help---
This driver supports the Netronome(R) NFP4000/NFP6000 based
cards working as a advanced Ethernet NIC. It works with both
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index e23ca90289f7..f272247d1708 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -1266,7 +1266,7 @@ wrp_alu64_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
u64 imm = insn->imm; /* sign extend */
if (skip) {
- meta->skip = true;
+ meta->flags |= FLAG_INSN_SKIP_NOOP;
return 0;
}
@@ -1291,15 +1291,10 @@ wrp_alu64_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
static int
wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
- enum alu_op alu_op, bool skip)
+ enum alu_op alu_op)
{
const struct bpf_insn *insn = &meta->insn;
- if (skip) {
- meta->skip = true;
- return 0;
- }
-
wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm);
wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
@@ -1334,8 +1329,9 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
wrp_test_reg_one(nfp_prog, insn->dst_reg * 2, alu_op,
insn->src_reg * 2, br_mask, insn->off);
- wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op,
- insn->src_reg * 2 + 1, br_mask, insn->off);
+ if (is_mbpf_jmp64(meta))
+ wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op,
+ insn->src_reg * 2 + 1, br_mask, insn->off);
return 0;
}
@@ -1390,13 +1386,15 @@ static int cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
else
emit_alu(nfp_prog, reg_none(), tmp_reg, alu_op, reg_a(reg));
- tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
- if (!code->swap)
- emit_alu(nfp_prog, reg_none(),
- reg_a(reg + 1), carry_op, tmp_reg);
- else
- emit_alu(nfp_prog, reg_none(),
- tmp_reg, carry_op, reg_a(reg + 1));
+ if (is_mbpf_jmp64(meta)) {
+ tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
+ if (!code->swap)
+ emit_alu(nfp_prog, reg_none(),
+ reg_a(reg + 1), carry_op, tmp_reg);
+ else
+ emit_alu(nfp_prog, reg_none(),
+ tmp_reg, carry_op, reg_a(reg + 1));
+ }
emit_br(nfp_prog, code->br_mask, insn->off, 0);
@@ -1423,8 +1421,9 @@ static int cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
}
emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg));
- emit_alu(nfp_prog, reg_none(),
- reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1));
+ if (is_mbpf_jmp64(meta))
+ emit_alu(nfp_prog, reg_none(),
+ reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1));
emit_br(nfp_prog, code->br_mask, insn->off, 0);
return 0;
@@ -1963,6 +1962,9 @@ static int neg_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/
static int __shl_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{
+ if (!shift_amt)
+ return 0;
+
if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst + 1), reg_a(dst + 1),
SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF,
@@ -2075,6 +2077,9 @@ static int shl_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/
static int __shr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{
+ if (!shift_amt)
+ return 0;
+
if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE,
reg_b(dst), SHF_SC_R_DSHF, shift_amt);
@@ -2176,6 +2181,9 @@ static int shr_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/
static int __ashr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{
+ if (!shift_amt)
+ return 0;
+
if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE,
reg_b(dst), SHF_SC_R_DSHF, shift_amt);
@@ -2309,7 +2317,7 @@ static int xor_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int xor_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
- return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR, !~meta->insn.imm);
+ return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR);
}
static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2319,7 +2327,7 @@ static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int and_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
- return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm);
+ return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND);
}
static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2329,7 +2337,7 @@ static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int or_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
- return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm);
+ return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR);
}
static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2339,7 +2347,7 @@ static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int add_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
- return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD, !meta->insn.imm);
+ return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD);
}
static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2349,7 +2357,7 @@ static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int sub_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
- return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB, !meta->insn.imm);
+ return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB);
}
static int mul_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2384,10 +2392,13 @@ static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{
- /* Set signedness bit (MSB of result). */
- emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR, reg_imm(0));
- emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, reg_b(dst),
- SHF_SC_R_SHF, shift_amt);
+ if (shift_amt) {
+ /* Set signedness bit (MSB of result). */
+ emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR,
+ reg_imm(0));
+ emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR,
+ reg_b(dst), SHF_SC_R_SHF, shift_amt);
+ }
wrp_immed(nfp_prog, reg_both(dst + 1), 0);
return 0;
@@ -2425,18 +2436,75 @@ static int ashr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return __ashr_imm(nfp_prog, dst, insn->imm);
}
+static int __shr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
+{
+ if (shift_amt)
+ emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
+ reg_b(dst), SHF_SC_R_SHF, shift_amt);
+ wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+ return 0;
+}
+
+static int shr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ const struct bpf_insn *insn = &meta->insn;
+ u8 dst = insn->dst_reg * 2;
+
+ return __shr_imm(nfp_prog, dst, insn->imm);
+}
+
+static int shr_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ const struct bpf_insn *insn = &meta->insn;
+ u64 umin, umax;
+ u8 dst, src;
+
+ dst = insn->dst_reg * 2;
+ umin = meta->umin_src;
+ umax = meta->umax_src;
+ if (umin == umax)
+ return __shr_imm(nfp_prog, dst, umin);
+
+ src = insn->src_reg * 2;
+ emit_alu(nfp_prog, reg_none(), reg_a(src), ALU_OP_OR, reg_imm(0));
+ emit_shf_indir(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
+ reg_b(dst), SHF_SC_R_SHF);
+ wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+ return 0;
+}
+
+static int __shl_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
+{
+ if (shift_amt)
+ emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
+ reg_b(dst), SHF_SC_L_SHF, shift_amt);
+ wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+ return 0;
+}
+
static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
const struct bpf_insn *insn = &meta->insn;
+ u8 dst = insn->dst_reg * 2;
- if (!insn->imm)
- return 1; /* TODO: zero shift means indirect */
+ return __shl_imm(nfp_prog, dst, insn->imm);
+}
- emit_shf(nfp_prog, reg_both(insn->dst_reg * 2),
- reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2),
- SHF_SC_L_SHF, insn->imm);
- wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
+static int shl_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ const struct bpf_insn *insn = &meta->insn;
+ u64 umin, umax;
+ u8 dst, src;
+
+ dst = insn->dst_reg * 2;
+ umin = meta->umin_src;
+ umax = meta->umax_src;
+ if (umin == umax)
+ return __shl_imm(nfp_prog, dst, umin);
+ src = insn->src_reg * 2;
+ shl_reg64_lt32_low(nfp_prog, dst, src);
+ wrp_immed(nfp_prog, reg_both(dst + 1), 0);
return 0;
}
@@ -3048,6 +3116,19 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return 0;
}
+static int jeq32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+ const struct bpf_insn *insn = &meta->insn;
+ swreg tmp_reg;
+
+ tmp_reg = ur_load_imm_any(nfp_prog, insn->imm, imm_b(nfp_prog));
+ emit_alu(nfp_prog, reg_none(),
+ reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg);
+ emit_br(nfp_prog, BR_BEQ, insn->off, 0);
+
+ return 0;
+}
+
static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
const struct bpf_insn *insn = &meta->insn;
@@ -3061,9 +3142,10 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
/* Upper word of the mask can only be 0 or ~0 from sign extension,
* so either ignore it or OR the whole thing in.
*/
- if (imm >> 32)
+ if (is_mbpf_jmp64(meta) && imm >> 32) {
emit_alu(nfp_prog, reg_none(),
reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog));
+ }
emit_br(nfp_prog, BR_BNE, insn->off, 0);
return 0;
@@ -3073,11 +3155,16 @@ static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
const struct bpf_insn *insn = &meta->insn;
u64 imm = insn->imm; /* sign extend */
+ bool is_jmp32 = is_mbpf_jmp32(meta);
swreg tmp_reg;
if (!imm) {
- emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2),
- ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1));
+ if (is_jmp32)
+ emit_alu(nfp_prog, reg_none(), reg_none(), ALU_OP_NONE,
+ reg_b(insn->dst_reg * 2));
+ else
+ emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2),
+ ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1));
emit_br(nfp_prog, BR_BNE, insn->off, 0);
return 0;
}
@@ -3087,6 +3174,9 @@ static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg);
emit_br(nfp_prog, BR_BNE, insn->off, 0);
+ if (is_jmp32)
+ return 0;
+
tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
emit_alu(nfp_prog, reg_none(),
reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg);
@@ -3101,10 +3191,13 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
emit_alu(nfp_prog, imm_a(nfp_prog), reg_a(insn->dst_reg * 2),
ALU_OP_XOR, reg_b(insn->src_reg * 2));
- emit_alu(nfp_prog, imm_b(nfp_prog), reg_a(insn->dst_reg * 2 + 1),
- ALU_OP_XOR, reg_b(insn->src_reg * 2 + 1));
- emit_alu(nfp_prog, reg_none(),
- imm_a(nfp_prog), ALU_OP_OR, imm_b(nfp_prog));
+ if (is_mbpf_jmp64(meta)) {
+ emit_alu(nfp_prog, imm_b(nfp_prog),
+ reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR,
+ reg_b(insn->src_reg * 2 + 1));
+ emit_alu(nfp_prog, reg_none(), imm_a(nfp_prog), ALU_OP_OR,
+ imm_b(nfp_prog));
+ }
emit_br(nfp_prog, BR_BEQ, insn->off, 0);
return 0;
@@ -3182,7 +3275,7 @@ bpf_to_bpf_call(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
wrp_immed_relo(nfp_prog, imm_b(nfp_prog), 0, RELO_IMMED_REL);
} else {
ret_tgt = nfp_prog_current_offset(nfp_prog) + 2;
- emit_br(nfp_prog, BR_UNC, meta->n + 1 + meta->insn.imm, 1);
+ emit_br(nfp_prog, BR_UNC, meta->insn.imm, 1);
offset_br = nfp_prog_current_offset(nfp_prog);
}
wrp_immed_relo(nfp_prog, ret_reg(nfp_prog), ret_tgt, RELO_IMMED_REL);
@@ -3321,7 +3414,10 @@ static const instr_cb_t instr_cb[256] = {
[BPF_ALU | BPF_DIV | BPF_X] = div_reg,
[BPF_ALU | BPF_DIV | BPF_K] = div_imm,
[BPF_ALU | BPF_NEG] = neg_reg,
+ [BPF_ALU | BPF_LSH | BPF_X] = shl_reg,
[BPF_ALU | BPF_LSH | BPF_K] = shl_imm,
+ [BPF_ALU | BPF_RSH | BPF_X] = shr_reg,
+ [BPF_ALU | BPF_RSH | BPF_K] = shr_imm,
[BPF_ALU | BPF_ARSH | BPF_X] = ashr_reg,
[BPF_ALU | BPF_ARSH | BPF_K] = ashr_imm,
[BPF_ALU | BPF_END | BPF_X] = end_reg32,
@@ -3369,6 +3465,28 @@ static const instr_cb_t instr_cb[256] = {
[BPF_JMP | BPF_JSLE | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSET | BPF_X] = jset_reg,
[BPF_JMP | BPF_JNE | BPF_X] = jne_reg,
+ [BPF_JMP32 | BPF_JEQ | BPF_K] = jeq32_imm,
+ [BPF_JMP32 | BPF_JGT | BPF_K] = cmp_imm,
+ [BPF_JMP32 | BPF_JGE | BPF_K] = cmp_imm,
+ [BPF_JMP32 | BPF_JLT | BPF_K] = cmp_imm,
+ [BPF_JMP32 | BPF_JLE | BPF_K] = cmp_imm,
+ [BPF_JMP32 | BPF_JSGT | BPF_K] =cmp_imm,
+ [BPF_JMP32 | BPF_JSGE | BPF_K] =cmp_imm,
+ [BPF_JMP32 | BPF_JSLT | BPF_K] =cmp_imm,
+ [BPF_JMP32 | BPF_JSLE | BPF_K] =cmp_imm,
+ [BPF_JMP32 | BPF_JSET | BPF_K] =jset_imm,
+ [BPF_JMP32 | BPF_JNE | BPF_K] = jne_imm,
+ [BPF_JMP32 | BPF_JEQ | BPF_X] = jeq_reg,
+ [BPF_JMP32 | BPF_JGT | BPF_X] = cmp_reg,
+ [BPF_JMP32 | BPF_JGE | BPF_X] = cmp_reg,
+ [BPF_JMP32 | BPF_JLT | BPF_X] = cmp_reg,
+ [BPF_JMP32 | BPF_JLE | BPF_X] = cmp_reg,
+ [BPF_JMP32 | BPF_JSGT | BPF_X] =cmp_reg,
+ [BPF_JMP32 | BPF_JSGE | BPF_X] =cmp_reg,
+ [BPF_JMP32 | BPF_JSLT | BPF_X] =cmp_reg,
+ [BPF_JMP32 | BPF_JSLE | BPF_X] =cmp_reg,
+ [BPF_JMP32 | BPF_JSET | BPF_X] =jset_reg,
+ [BPF_JMP32 | BPF_JNE | BPF_X] = jne_reg,
[BPF_JMP | BPF_CALL] = call,
[BPF_JMP | BPF_EXIT] = jmp_exit,
};
@@ -3395,9 +3513,9 @@ static int nfp_fixup_branches(struct nfp_prog *nfp_prog)
int err;
list_for_each_entry(meta, &nfp_prog->insns, l) {
- if (meta->skip)
+ if (meta->flags & FLAG_INSN_SKIP_MASK)
continue;
- if (BPF_CLASS(meta->insn.code) != BPF_JMP)
+ if (!is_mbpf_jmp(meta))
continue;
if (meta->insn.code == (BPF_JMP | BPF_EXIT) &&
!nfp_is_main_function(meta))
@@ -3439,7 +3557,7 @@ static int nfp_fixup_branches(struct nfp_prog *nfp_prog)
jmp_dst = meta->jmp_dst;
- if (jmp_dst->skip) {
+ if (jmp_dst->flags & FLAG_INSN_SKIP_PREC_DEPENDENT) {
pr_err("Branch landing on removed instruction!!\n");
return -ELOOP;
}
@@ -3689,7 +3807,7 @@ static int nfp_translate(struct nfp_prog *nfp_prog)
return nfp_prog->error;
}
- if (meta->skip) {
+ if (meta->flags & FLAG_INSN_SKIP_MASK) {
nfp_prog->n_translated++;
continue;
}
@@ -3737,10 +3855,10 @@ static void nfp_bpf_opt_reg_init(struct nfp_prog *nfp_prog)
/* Programs start with R6 = R1 but we ignore the skb pointer */
if (insn.code == (BPF_ALU64 | BPF_MOV | BPF_X) &&
insn.src_reg == 1 && insn.dst_reg == 6)
- meta->skip = true;
+ meta->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
/* Return as soon as something doesn't match */
- if (!meta->skip)
+ if (!(meta->flags & FLAG_INSN_SKIP_MASK))
return;
}
}
@@ -3755,19 +3873,17 @@ static void nfp_bpf_opt_neg_add_sub(struct nfp_prog *nfp_prog)
list_for_each_entry(meta, &nfp_prog->insns, l) {
struct bpf_insn insn = meta->insn;
- if (meta->skip)
+ if (meta->flags & FLAG_INSN_SKIP_MASK)
continue;
- if (BPF_CLASS(insn.code) != BPF_ALU &&
- BPF_CLASS(insn.code) != BPF_ALU64 &&
- BPF_CLASS(insn.code) != BPF_JMP)
+ if (!is_mbpf_alu(meta) && !is_mbpf_jmp(meta))
continue;
if (BPF_SRC(insn.code) != BPF_K)
continue;
if (insn.imm >= 0)
continue;
- if (BPF_CLASS(insn.code) == BPF_JMP) {
+ if (is_mbpf_jmp(meta)) {
switch (BPF_OP(insn.code)) {
case BPF_JGE:
case BPF_JSGE:
@@ -3829,7 +3945,7 @@ static void nfp_bpf_opt_ld_mask(struct nfp_prog *nfp_prog)
if (meta2->flags & FLAG_INSN_IS_JUMP_DST)
continue;
- meta2->skip = true;
+ meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
}
}
@@ -3869,8 +3985,8 @@ static void nfp_bpf_opt_ld_shift(struct nfp_prog *nfp_prog)
meta3->flags & FLAG_INSN_IS_JUMP_DST)
continue;
- meta2->skip = true;
- meta3->skip = true;
+ meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
+ meta3->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
}
}
@@ -4065,7 +4181,8 @@ static void nfp_bpf_opt_ldst_gather(struct nfp_prog *nfp_prog)
}
head_ld_meta->paired_st = &head_st_meta->insn;
- head_st_meta->skip = true;
+ head_st_meta->flags |=
+ FLAG_INSN_SKIP_PREC_DEPENDENT;
} else {
head_ld_meta->ldst_gather_len = 0;
}
@@ -4098,8 +4215,8 @@ static void nfp_bpf_opt_ldst_gather(struct nfp_prog *nfp_prog)
head_ld_meta = meta1;
head_st_meta = meta2;
} else {
- meta1->skip = true;
- meta2->skip = true;
+ meta1->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
+ meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT;
}
head_ld_meta->ldst_gather_len += BPF_LDST_BYTES(ld);
@@ -4124,7 +4241,7 @@ static void nfp_bpf_opt_pkt_cache(struct nfp_prog *nfp_prog)
if (meta->flags & FLAG_INSN_IS_JUMP_DST)
cache_avail = false;
- if (meta->skip)
+ if (meta->flags & FLAG_INSN_SKIP_MASK)
continue;
insn = &meta->insn;
@@ -4210,7 +4327,7 @@ start_new:
}
list_for_each_entry(meta, &nfp_prog->insns, l) {
- if (meta->skip)
+ if (meta->flags & FLAG_INSN_SKIP_MASK)
continue;
if (is_mbpf_load_pkt(meta) && !meta->ldst_gather_len) {
@@ -4246,7 +4363,8 @@ static int nfp_bpf_replace_map_ptrs(struct nfp_prog *nfp_prog)
u32 id;
nfp_for_each_insn_walk2(nfp_prog, meta1, meta2) {
- if (meta1->skip || meta2->skip)
+ if (meta1->flags & FLAG_INSN_SKIP_MASK ||
+ meta2->flags & FLAG_INSN_SKIP_MASK)
continue;
if (meta1->insn.code != (BPF_LD | BPF_IMM | BPF_DW) ||
@@ -4325,7 +4443,7 @@ int nfp_bpf_jit(struct nfp_prog *nfp_prog)
return ret;
}
-void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt)
+void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog)
{
struct nfp_insn_meta *meta;
@@ -4336,7 +4454,7 @@ void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt)
unsigned int dst_idx;
bool pseudo_call;
- if (BPF_CLASS(code) != BPF_JMP)
+ if (!is_mbpf_jmp(meta))
continue;
if (BPF_OP(code) == BPF_EXIT)
continue;
@@ -4353,7 +4471,7 @@ void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt)
else
dst_idx = meta->n + 1 + meta->insn.off;
- dst_meta = nfp_bpf_goto_meta(nfp_prog, meta, dst_idx, cnt);
+ dst_meta = nfp_bpf_goto_meta(nfp_prog, meta, dst_idx);
if (pseudo_call)
dst_meta->flags |= FLAG_INSN_IS_SUBPROG_START;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index dccae0319204..275de9f4c61c 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -465,7 +465,7 @@ static int nfp_bpf_init(struct nfp_app *app)
app->ctrl_mtu = nfp_bpf_ctrl_cmsg_mtu(bpf);
}
- bpf->bpf_dev = bpf_offload_dev_create(&nfp_bpf_dev_ops);
+ bpf->bpf_dev = bpf_offload_dev_create(&nfp_bpf_dev_ops, bpf);
err = PTR_ERR_OR_ZERO(bpf->bpf_dev);
if (err)
goto err_free_neutral_maps;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index 941277936475..b25a48218bcf 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -243,6 +243,16 @@ struct nfp_bpf_reg_state {
#define FLAG_INSN_IS_JUMP_DST BIT(0)
#define FLAG_INSN_IS_SUBPROG_START BIT(1)
#define FLAG_INSN_PTR_CALLER_STACK_FRAME BIT(2)
+/* Instruction is pointless, noop even on its own */
+#define FLAG_INSN_SKIP_NOOP BIT(3)
+/* Instruction is optimized out based on preceding instructions */
+#define FLAG_INSN_SKIP_PREC_DEPENDENT BIT(4)
+/* Instruction is optimized by the verifier */
+#define FLAG_INSN_SKIP_VERIFIER_OPT BIT(5)
+
+#define FLAG_INSN_SKIP_MASK (FLAG_INSN_SKIP_NOOP | \
+ FLAG_INSN_SKIP_PREC_DEPENDENT | \
+ FLAG_INSN_SKIP_VERIFIER_OPT)
/**
* struct nfp_insn_meta - BPF instruction wrapper
@@ -271,7 +281,6 @@ struct nfp_bpf_reg_state {
* @n: eBPF instruction number
* @flags: eBPF instruction extra optimization flags
* @subprog_idx: index of subprogram to which the instruction belongs
- * @skip: skip this instruction (optimized out)
* @double_cb: callback for second part of the instruction
* @l: link on nfp_prog->insns list
*/
@@ -319,7 +328,6 @@ struct nfp_insn_meta {
unsigned short n;
unsigned short flags;
unsigned short subprog_idx;
- bool skip;
instr_cb_t double_cb;
struct list_head l;
@@ -357,6 +365,21 @@ static inline bool is_mbpf_load(const struct nfp_insn_meta *meta)
return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_LDX | BPF_MEM);
}
+static inline bool is_mbpf_jmp32(const struct nfp_insn_meta *meta)
+{
+ return mbpf_class(meta) == BPF_JMP32;
+}
+
+static inline bool is_mbpf_jmp64(const struct nfp_insn_meta *meta)
+{
+ return mbpf_class(meta) == BPF_JMP;
+}
+
+static inline bool is_mbpf_jmp(const struct nfp_insn_meta *meta)
+{
+ return is_mbpf_jmp32(meta) || is_mbpf_jmp64(meta);
+}
+
static inline bool is_mbpf_store(const struct nfp_insn_meta *meta)
{
return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_STX | BPF_MEM);
@@ -407,6 +430,20 @@ static inline bool is_mbpf_div(const struct nfp_insn_meta *meta)
return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_DIV;
}
+static inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta)
+{
+ u8 op;
+
+ if (is_mbpf_jmp32(meta))
+ return true;
+
+ if (!is_mbpf_jmp64(meta))
+ return false;
+
+ op = mbpf_op(meta);
+ return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL;
+}
+
static inline bool is_mbpf_helper_call(const struct nfp_insn_meta *meta)
{
struct bpf_insn insn = meta->insn;
@@ -457,6 +494,7 @@ struct nfp_bpf_subprog_info {
* @subprog_cnt: number of sub-programs, including main function
* @map_records: the map record pointers from bpf->maps_neutral
* @subprog: pointer to an array of objects holding info about sub-programs
+ * @n_insns: number of instructions on @insns list
* @insns: list of BPF instruction wrappers (struct nfp_insn_meta)
*/
struct nfp_prog {
@@ -489,6 +527,7 @@ struct nfp_prog {
struct nfp_bpf_neutral_map **map_records;
struct nfp_bpf_subprog_info *subprog;
+ unsigned int n_insns;
struct list_head insns;
};
@@ -505,7 +544,7 @@ struct nfp_bpf_vnic {
};
bool nfp_is_subprog_start(struct nfp_insn_meta *meta);
-void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt);
+void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog);
int nfp_bpf_jit(struct nfp_prog *prog);
bool nfp_bpf_supported_opcode(u8 code);
@@ -513,6 +552,10 @@ int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx,
int prev_insn_idx);
int nfp_bpf_finalize(struct bpf_verifier_env *env);
+int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off,
+ struct bpf_insn *insn);
+int nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
+
extern const struct bpf_prog_offload_ops nfp_bpf_dev_ops;
struct netdev_bpf;
@@ -526,7 +569,7 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
struct nfp_insn_meta *
nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
- unsigned int insn_idx, unsigned int n_insns);
+ unsigned int insn_idx);
void *nfp_bpf_relo_for_vnic(struct nfp_prog *nfp_prog, struct nfp_bpf_vnic *bv);
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
index f0283854fade..15dce97650a5 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -163,8 +163,9 @@ nfp_prog_prepare(struct nfp_prog *nfp_prog, const struct bpf_insn *prog,
list_add_tail(&meta->l, &nfp_prog->insns);
}
+ nfp_prog->n_insns = cnt;
- nfp_bpf_jit_prepare(nfp_prog, cnt);
+ nfp_bpf_jit_prepare(nfp_prog);
return 0;
}
@@ -184,8 +185,6 @@ static void nfp_prog_free(struct nfp_prog *nfp_prog)
static int nfp_bpf_verifier_prep(struct bpf_prog *prog)
{
- struct nfp_net *nn = netdev_priv(prog->aux->offload->netdev);
- struct nfp_app *app = nn->app;
struct nfp_prog *nfp_prog;
int ret;
@@ -196,7 +195,7 @@ static int nfp_bpf_verifier_prep(struct bpf_prog *prog)
INIT_LIST_HEAD(&nfp_prog->insns);
nfp_prog->type = prog->type;
- nfp_prog->bpf = app->priv;
+ nfp_prog->bpf = bpf_offload_dev_priv(prog->aux->offload->offdev);
ret = nfp_prog_prepare(nfp_prog, prog->insnsi, prog->len);
if (ret)
@@ -219,6 +218,10 @@ static int nfp_bpf_translate(struct bpf_prog *prog)
unsigned int max_instr;
int err;
+ /* We depend on dead code elimination succeeding */
+ if (prog->aux->offload->opt_failed)
+ return -EINVAL;
+
max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
nfp_prog->__prog_alloc_len = max_instr * sizeof(u64);
@@ -591,6 +594,8 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
const struct bpf_prog_offload_ops nfp_bpf_dev_ops = {
.insn_hook = nfp_verify_insn,
.finalize = nfp_bpf_finalize,
+ .replace_insn = nfp_bpf_opt_replace_insn,
+ .remove_insns = nfp_bpf_opt_remove_insns,
.prepare = nfp_bpf_verifier_prep,
.translate = nfp_bpf_translate,
.destroy = nfp_bpf_destroy,
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
index 337bb862ec1d..36f56eb4cbe2 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
@@ -18,15 +18,15 @@
struct nfp_insn_meta *
nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
- unsigned int insn_idx, unsigned int n_insns)
+ unsigned int insn_idx)
{
unsigned int forward, backward, i;
backward = meta->n - insn_idx;
forward = insn_idx - meta->n;
- if (min(forward, backward) > n_insns - insn_idx - 1) {
- backward = n_insns - insn_idx - 1;
+ if (min(forward, backward) > nfp_prog->n_insns - insn_idx - 1) {
+ backward = nfp_prog->n_insns - insn_idx - 1;
meta = nfp_prog_last_meta(nfp_prog);
}
if (min(forward, backward) > insn_idx && backward > insn_idx) {
@@ -629,7 +629,7 @@ int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx,
struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv;
struct nfp_insn_meta *meta = nfp_prog->verifier_meta;
- meta = nfp_bpf_goto_meta(nfp_prog, meta, insn_idx, env->prog->len);
+ meta = nfp_bpf_goto_meta(nfp_prog, meta, insn_idx);
nfp_prog->verifier_meta = meta;
if (!nfp_bpf_supported_opcode(meta->insn.code)) {
@@ -690,8 +690,7 @@ nfp_assign_subprog_idx_and_regs(struct bpf_verifier_env *env,
return 0;
}
-static unsigned int
-nfp_bpf_get_stack_usage(struct nfp_prog *nfp_prog, unsigned int cnt)
+static unsigned int nfp_bpf_get_stack_usage(struct nfp_prog *nfp_prog)
{
struct nfp_insn_meta *meta = nfp_prog_first_meta(nfp_prog);
unsigned int max_depth = 0, depth = 0, frame = 0;
@@ -726,7 +725,7 @@ continue_subprog:
/* Find the callee and start processing it. */
meta = nfp_bpf_goto_meta(nfp_prog, meta,
- meta->n + 1 + meta->insn.imm, cnt);
+ meta->n + 1 + meta->insn.imm);
idx = meta->subprog_idx;
frame++;
goto process_subprog;
@@ -778,8 +777,7 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env)
nn = netdev_priv(env->prog->aux->offload->netdev);
max_stack = nn_readb(nn, NFP_NET_CFG_BPF_STACK_SZ) * 64;
- nfp_prog->stack_size = nfp_bpf_get_stack_usage(nfp_prog,
- env->prog->len);
+ nfp_prog->stack_size = nfp_bpf_get_stack_usage(nfp_prog);
if (nfp_prog->stack_size > max_stack) {
pr_vlog(env, "stack too large: program %dB > FW stack %dB\n",
nfp_prog->stack_size, max_stack);
@@ -788,3 +786,61 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env)
return 0;
}
+
+int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off,
+ struct bpf_insn *insn)
+{
+ struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv;
+ struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
+ struct nfp_insn_meta *meta = nfp_prog->verifier_meta;
+
+ meta = nfp_bpf_goto_meta(nfp_prog, meta, aux_data[off].orig_idx);
+ nfp_prog->verifier_meta = meta;
+
+ /* conditional jump to jump conversion */
+ if (is_mbpf_cond_jump(meta) &&
+ insn->code == (BPF_JMP | BPF_JA | BPF_K)) {
+ unsigned int tgt_off;
+
+ tgt_off = off + insn->off + 1;
+
+ if (!insn->off) {
+ meta->jmp_dst = list_next_entry(meta, l);
+ meta->jump_neg_op = false;
+ } else if (meta->jmp_dst->n != aux_data[tgt_off].orig_idx) {
+ pr_vlog(env, "branch hard wire at %d changes target %d -> %d\n",
+ off, meta->jmp_dst->n,
+ aux_data[tgt_off].orig_idx);
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ pr_vlog(env, "unsupported instruction replacement %hhx -> %hhx\n",
+ meta->insn.code, insn->code);
+ return -EINVAL;
+}
+
+int nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
+{
+ struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv;
+ struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
+ struct nfp_insn_meta *meta = nfp_prog->verifier_meta;
+ unsigned int i;
+
+ meta = nfp_bpf_goto_meta(nfp_prog, meta, aux_data[off].orig_idx);
+
+ for (i = 0; i < cnt; i++) {
+ if (WARN_ON_ONCE(&meta->l == &nfp_prog->insns))
+ return -EINVAL;
+
+ /* doesn't count if it already has the flag */
+ if (meta->flags & FLAG_INSN_SKIP_VERIFIER_OPT)
+ i--;
+
+ meta->flags |= FLAG_INSN_SKIP_VERIFIER_OPT;
+ meta = list_next_entry(meta, l);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index 8d54b36afee8..eeda4ed98333 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -3,7 +3,6 @@
#include <linux/bitfield.h>
#include <net/pkt_cls.h>
-#include <net/switchdev.h>
#include <net/tc_act/tc_csum.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
@@ -37,7 +36,7 @@ static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan)
static void
nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
- const struct tc_action *action)
+ const struct flow_action_entry *act)
{
size_t act_size = sizeof(struct nfp_fl_push_vlan);
u16 tmp_push_vlan_tci;
@@ -45,17 +44,17 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN;
push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
push_vlan->reserved = 0;
- push_vlan->vlan_tpid = tcf_vlan_push_proto(action);
+ push_vlan->vlan_tpid = act->vlan.proto;
tmp_push_vlan_tci =
- FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, tcf_vlan_push_prio(action)) |
- FIELD_PREP(NFP_FL_PUSH_VLAN_VID, tcf_vlan_push_vid(action)) |
+ FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, act->vlan.prio) |
+ FIELD_PREP(NFP_FL_PUSH_VLAN_VID, act->vlan.vid) |
NFP_FL_PUSH_VLAN_CFI;
push_vlan->vlan_tci = cpu_to_be16(tmp_push_vlan_tci);
}
static int
-nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action,
+nfp_fl_pre_lag(struct nfp_app *app, const struct flow_action_entry *act,
struct nfp_fl_payload *nfp_flow, int act_len)
{
size_t act_size = sizeof(struct nfp_fl_pre_lag);
@@ -63,7 +62,7 @@ nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action,
struct net_device *out_dev;
int err;
- out_dev = tcf_mirred_dev(action);
+ out_dev = act->dev;
if (!out_dev || !netif_is_lag_master(out_dev))
return 0;
@@ -92,7 +91,8 @@ nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action,
static int
nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
- const struct tc_action *action, struct nfp_fl_payload *nfp_flow,
+ const struct flow_action_entry *act,
+ struct nfp_fl_payload *nfp_flow,
bool last, struct net_device *in_dev,
enum nfp_flower_tun_type tun_type, int *tun_out_cnt)
{
@@ -104,7 +104,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT;
output->head.len_lw = act_size >> NFP_FL_LW_SIZ;
- out_dev = tcf_mirred_dev(action);
+ out_dev = act->dev;
if (!out_dev)
return -EOPNOTSUPP;
@@ -137,7 +137,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
if (nfp_netdev_is_nfp_repr(in_dev)) {
/* Confirm ingress and egress are on same device. */
- if (!switchdev_port_same_parent_id(in_dev, out_dev))
+ if (!netdev_port_same_parent_id(in_dev, out_dev))
return -EOPNOTSUPP;
}
@@ -155,9 +155,9 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
static enum nfp_flower_tun_type
nfp_fl_get_tun_from_act_l4_port(struct nfp_app *app,
- const struct tc_action *action)
+ const struct flow_action_entry *act)
{
- struct ip_tunnel_info *tun = tcf_tunnel_info(action);
+ const struct ip_tunnel_info *tun = act->tunnel;
struct nfp_flower_priv *priv = app->priv;
switch (tun->key.tp_dst) {
@@ -195,9 +195,9 @@ static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
static int
nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len,
- const struct tc_action *action)
+ const struct flow_action_entry *act)
{
- struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action);
+ struct ip_tunnel_info *ip_tun = (struct ip_tunnel_info *)act->tunnel;
int opt_len, opt_cnt, act_start, tot_push_len;
u8 *src = ip_tunnel_info_opts(ip_tun);
@@ -259,13 +259,13 @@ nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len,
static int
nfp_fl_set_ipv4_udp_tun(struct nfp_app *app,
struct nfp_fl_set_ipv4_udp_tun *set_tun,
- const struct tc_action *action,
+ const struct flow_action_entry *act,
struct nfp_fl_pre_tunnel *pre_tun,
enum nfp_flower_tun_type tun_type,
struct net_device *netdev)
{
size_t act_size = sizeof(struct nfp_fl_set_ipv4_udp_tun);
- struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action);
+ const struct ip_tunnel_info *ip_tun = act->tunnel;
struct nfp_flower_priv *priv = app->priv;
u32 tmp_set_ip_tun_type_index = 0;
/* Currently support one pre-tunnel so index is always 0. */
@@ -345,7 +345,7 @@ static void nfp_fl_set_helper32(u32 value, u32 mask, u8 *p_exact, u8 *p_mask)
}
static int
-nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
+nfp_fl_set_eth(const struct flow_action_entry *act, u32 off,
struct nfp_fl_set_eth *set_eth)
{
u32 exact, mask;
@@ -353,8 +353,8 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
if (off + 4 > ETH_ALEN * 2)
return -EOPNOTSUPP;
- mask = ~tcf_pedit_mask(action, idx);
- exact = tcf_pedit_val(action, idx);
+ mask = ~act->mangle.mask;
+ exact = act->mangle.val;
if (exact & ~mask)
return -EOPNOTSUPP;
@@ -376,7 +376,7 @@ struct ipv4_ttl_word {
};
static int
-nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
+nfp_fl_set_ip4(const struct flow_action_entry *act, u32 off,
struct nfp_fl_set_ip4_addrs *set_ip_addr,
struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos)
{
@@ -387,8 +387,8 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
__be32 exact, mask;
/* We are expecting tcf_pedit to return a big endian value */
- mask = (__force __be32)~tcf_pedit_mask(action, idx);
- exact = (__force __be32)tcf_pedit_val(action, idx);
+ mask = (__force __be32)~act->mangle.mask;
+ exact = (__force __be32)act->mangle.val;
if (exact & ~mask)
return -EOPNOTSUPP;
@@ -505,7 +505,7 @@ nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask,
}
static int
-nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
+nfp_fl_set_ip6(const struct flow_action_entry *act, u32 off,
struct nfp_fl_set_ipv6_addr *ip_dst,
struct nfp_fl_set_ipv6_addr *ip_src,
struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl)
@@ -515,8 +515,8 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
u8 word;
/* We are expecting tcf_pedit to return a big endian value */
- mask = (__force __be32)~tcf_pedit_mask(action, idx);
- exact = (__force __be32)tcf_pedit_val(action, idx);
+ mask = (__force __be32)~act->mangle.mask;
+ exact = (__force __be32)act->mangle.val;
if (exact & ~mask)
return -EOPNOTSUPP;
@@ -541,7 +541,7 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
}
static int
-nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off,
+nfp_fl_set_tport(const struct flow_action_entry *act, u32 off,
struct nfp_fl_set_tport *set_tport, int opcode)
{
u32 exact, mask;
@@ -549,8 +549,8 @@ nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off,
if (off)
return -EOPNOTSUPP;
- mask = ~tcf_pedit_mask(action, idx);
- exact = tcf_pedit_val(action, idx);
+ mask = ~act->mangle.mask;
+ exact = act->mangle.val;
if (exact & ~mask)
return -EOPNOTSUPP;
@@ -584,20 +584,22 @@ static u32 nfp_fl_csum_l4_to_flag(u8 ip_proto)
}
static int
-nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
+nfp_fl_pedit(const struct flow_action_entry *act,
+ struct tc_cls_flower_offload *flow,
char *nfp_action, int *a_len, u32 *csum_updated)
{
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src;
struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl;
struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos;
struct nfp_fl_set_ip4_addrs set_ip_addr;
+ enum flow_action_mangle_base htype;
struct nfp_fl_set_tport set_tport;
struct nfp_fl_set_eth set_eth;
- enum pedit_header_type htype;
- int idx, nkeys, err;
size_t act_size = 0;
- u32 offset, cmd;
u8 ip_proto = 0;
+ u32 offset;
+ int err;
memset(&set_ip6_tc_hl_fl, 0, sizeof(set_ip6_tc_hl_fl));
memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos));
@@ -606,50 +608,41 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
memset(&set_ip_addr, 0, sizeof(set_ip_addr));
memset(&set_tport, 0, sizeof(set_tport));
memset(&set_eth, 0, sizeof(set_eth));
- nkeys = tcf_pedit_nkeys(action);
-
- for (idx = 0; idx < nkeys; idx++) {
- cmd = tcf_pedit_cmd(action, idx);
- htype = tcf_pedit_htype(action, idx);
- offset = tcf_pedit_offset(action, idx);
- if (cmd != TCA_PEDIT_KEY_EX_CMD_SET)
- return -EOPNOTSUPP;
+ htype = act->mangle.htype;
+ offset = act->mangle.offset;
- switch (htype) {
- case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
- err = nfp_fl_set_eth(action, idx, offset, &set_eth);
- break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
- err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr,
- &set_ip_ttl_tos);
- break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
- err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst,
- &set_ip6_src, &set_ip6_tc_hl_fl);
- break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
- err = nfp_fl_set_tport(action, idx, offset, &set_tport,
- NFP_FL_ACTION_OPCODE_SET_TCP);
- break;
- case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
- err = nfp_fl_set_tport(action, idx, offset, &set_tport,
- NFP_FL_ACTION_OPCODE_SET_UDP);
- break;
- default:
- return -EOPNOTSUPP;
- }
- if (err)
- return err;
+ switch (htype) {
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
+ err = nfp_fl_set_eth(act, offset, &set_eth);
+ break;
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
+ err = nfp_fl_set_ip4(act, offset, &set_ip_addr,
+ &set_ip_ttl_tos);
+ break;
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
+ err = nfp_fl_set_ip6(act, offset, &set_ip6_dst,
+ &set_ip6_src, &set_ip6_tc_hl_fl);
+ break;
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
+ err = nfp_fl_set_tport(act, offset, &set_tport,
+ NFP_FL_ACTION_OPCODE_SET_TCP);
+ break;
+ case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
+ err = nfp_fl_set_tport(act, offset, &set_tport,
+ NFP_FL_ACTION_OPCODE_SET_UDP);
+ break;
+ default:
+ return -EOPNOTSUPP;
}
+ if (err)
+ return err;
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *basic;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- basic = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- flow->key);
- ip_proto = basic->ip_proto;
+ flow_rule_match_basic(rule, &match);
+ ip_proto = match.key->ip_proto;
}
if (set_eth.head.len_lw) {
@@ -733,7 +726,7 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
}
static int
-nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a,
+nfp_flower_output_action(struct nfp_app *app, const struct flow_action_entry *act,
struct nfp_fl_payload *nfp_fl, int *a_len,
struct net_device *netdev, bool last,
enum nfp_flower_tun_type *tun_type, int *tun_out_cnt,
@@ -753,7 +746,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a,
return -EOPNOTSUPP;
output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len];
- err = nfp_fl_output(app, output, a, nfp_fl, last, netdev, *tun_type,
+ err = nfp_fl_output(app, output, act, nfp_fl, last, netdev, *tun_type,
tun_out_cnt);
if (err)
return err;
@@ -764,7 +757,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a,
/* nfp_fl_pre_lag returns -err or size of prelag action added.
* This will be 0 if it is not egressing to a lag dev.
*/
- prelag_size = nfp_fl_pre_lag(app, a, nfp_fl, *a_len);
+ prelag_size = nfp_fl_pre_lag(app, act, nfp_fl, *a_len);
if (prelag_size < 0)
return prelag_size;
else if (prelag_size > 0 && (!last || *out_cnt))
@@ -778,7 +771,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a,
}
static int
-nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a,
+nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act,
struct tc_cls_flower_offload *flow,
struct nfp_fl_payload *nfp_fl, int *a_len,
struct net_device *netdev,
@@ -791,23 +784,25 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a,
struct nfp_fl_pop_vlan *pop_v;
int err;
- if (is_tcf_gact_shot(a)) {
+ switch (act->id) {
+ case FLOW_ACTION_DROP:
nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_DROP);
- } else if (is_tcf_mirred_egress_redirect(a)) {
- err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev,
+ break;
+ case FLOW_ACTION_REDIRECT:
+ err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev,
true, tun_type, tun_out_cnt,
out_cnt, csum_updated);
if (err)
return err;
-
- } else if (is_tcf_mirred_egress_mirror(a)) {
- err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev,
+ break;
+ case FLOW_ACTION_MIRRED:
+ err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev,
false, tun_type, tun_out_cnt,
out_cnt, csum_updated);
if (err)
return err;
-
- } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
+ break;
+ case FLOW_ACTION_VLAN_POP:
if (*a_len + sizeof(struct nfp_fl_pop_vlan) > NFP_FL_MAX_A_SIZ)
return -EOPNOTSUPP;
@@ -816,19 +811,21 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a,
nfp_fl_pop_vlan(pop_v);
*a_len += sizeof(struct nfp_fl_pop_vlan);
- } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
+ break;
+ case FLOW_ACTION_VLAN_PUSH:
if (*a_len + sizeof(struct nfp_fl_push_vlan) > NFP_FL_MAX_A_SIZ)
return -EOPNOTSUPP;
psh_v = (struct nfp_fl_push_vlan *)&nfp_fl->action_data[*a_len];
nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
- nfp_fl_push_vlan(psh_v, a);
+ nfp_fl_push_vlan(psh_v, act);
*a_len += sizeof(struct nfp_fl_push_vlan);
- } else if (is_tcf_tunnel_set(a)) {
- struct ip_tunnel_info *ip_tun = tcf_tunnel_info(a);
+ break;
+ case FLOW_ACTION_TUNNEL_ENCAP: {
+ const struct ip_tunnel_info *ip_tun = act->tunnel;
- *tun_type = nfp_fl_get_tun_from_act_l4_port(app, a);
+ *tun_type = nfp_fl_get_tun_from_act_l4_port(app, act);
if (*tun_type == NFP_FL_TUNNEL_NONE)
return -EOPNOTSUPP;
@@ -847,32 +844,36 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a,
nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
*a_len += sizeof(struct nfp_fl_pre_tunnel);
- err = nfp_fl_push_geneve_options(nfp_fl, a_len, a);
+ err = nfp_fl_push_geneve_options(nfp_fl, a_len, act);
if (err)
return err;
set_tun = (void *)&nfp_fl->action_data[*a_len];
- err = nfp_fl_set_ipv4_udp_tun(app, set_tun, a, pre_tun,
+ err = nfp_fl_set_ipv4_udp_tun(app, set_tun, act, pre_tun,
*tun_type, netdev);
if (err)
return err;
*a_len += sizeof(struct nfp_fl_set_ipv4_udp_tun);
- } else if (is_tcf_tunnel_release(a)) {
+ }
+ break;
+ case FLOW_ACTION_TUNNEL_DECAP:
/* Tunnel decap is handled by default so accept action. */
return 0;
- } else if (is_tcf_pedit(a)) {
- if (nfp_fl_pedit(a, flow, &nfp_fl->action_data[*a_len],
+ case FLOW_ACTION_MANGLE:
+ if (nfp_fl_pedit(act, flow, &nfp_fl->action_data[*a_len],
a_len, csum_updated))
return -EOPNOTSUPP;
- } else if (is_tcf_csum(a)) {
+ break;
+ case FLOW_ACTION_CSUM:
/* csum action requests recalc of something we have not fixed */
- if (tcf_csum_update_flags(a) & ~*csum_updated)
+ if (act->csum_flags & ~*csum_updated)
return -EOPNOTSUPP;
/* If we will correctly fix the csum we can remove it from the
* csum update list. Which will later be used to check support.
*/
- *csum_updated &= ~tcf_csum_update_flags(a);
- } else {
+ *csum_updated &= ~act->csum_flags;
+ break;
+ default:
/* Currently we do not handle any other actions. */
return -EOPNOTSUPP;
}
@@ -887,7 +888,7 @@ int nfp_flower_compile_action(struct nfp_app *app,
{
int act_len, act_cnt, err, tun_out_cnt, out_cnt, i;
enum nfp_flower_tun_type tun_type;
- const struct tc_action *a;
+ struct flow_action_entry *act;
u32 csum_updated = 0;
memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
@@ -898,8 +899,8 @@ int nfp_flower_compile_action(struct nfp_app *app,
tun_out_cnt = 0;
out_cnt = 0;
- tcf_exts_for_each_action(i, a, flow->exts) {
- err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len,
+ flow_action_for_each(i, act, &flow->rule->action) {
+ err = nfp_flower_loop_action(app, act, flow, nfp_flow, &act_len,
netdev, &tun_type, &tun_out_cnt,
&out_cnt, &csum_updated);
if (err)
diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
index 4c5eaf36d5bb..cf9e1118ee8f 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c
@@ -45,11 +45,9 @@ nfp_flower_cmsg_mac_repr_start(struct nfp_app *app, unsigned int num_ports)
{
struct nfp_flower_cmsg_mac_repr *msg;
struct sk_buff *skb;
- unsigned int size;
- size = sizeof(*msg) + num_ports * sizeof(msg->ports[0]);
- skb = nfp_flower_cmsg_alloc(app, size, NFP_FLOWER_CMSG_TYPE_MAC_REPR,
- GFP_KERNEL);
+ skb = nfp_flower_cmsg_alloc(app, struct_size(msg, ports, num_ports),
+ NFP_FLOWER_CMSG_TYPE_MAC_REPR, GFP_KERNEL);
if (!skb)
return NULL;
@@ -203,7 +201,7 @@ nfp_flower_cmsg_portreify_rx(struct nfp_app *app, struct sk_buff *skb)
}
atomic_inc(&priv->reify_replies);
- wake_up_interruptible(&priv->reify_wait_queue);
+ wake_up(&priv->reify_wait_queue);
}
static void
diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
index 15f41cfef9f1..4fcaf11ed56e 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
@@ -97,6 +97,9 @@
#define NFP_FLOWER_WORKQ_MAX_SKBS 30000
+/* Cmesg reply (empirical) timeout*/
+#define NFP_FL_REPLY_TIMEOUT msecs_to_jiffies(40)
+
#define nfp_flower_cmsg_warn(app, fmt, args...) \
do { \
if (net_ratelimit()) \
diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c
index 5059110a1768..408089133599 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.c
@@ -32,6 +32,71 @@ static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
return DEVLINK_ESWITCH_MODE_SWITCHDEV;
}
+static struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev)
+{
+ struct nfp_flower_priv *priv = app->priv;
+ struct nfp_flower_non_repr_priv *entry;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(entry, &priv->non_repr_priv, list)
+ if (entry->netdev == netdev)
+ return entry;
+
+ return NULL;
+}
+
+void
+__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv)
+{
+ non_repr_priv->ref_count++;
+}
+
+struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev)
+{
+ struct nfp_flower_priv *priv = app->priv;
+ struct nfp_flower_non_repr_priv *entry;
+
+ entry = nfp_flower_non_repr_priv_lookup(app, netdev);
+ if (entry)
+ goto inc_ref;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return NULL;
+
+ entry->netdev = netdev;
+ list_add(&entry->list, &priv->non_repr_priv);
+
+inc_ref:
+ __nfp_flower_non_repr_priv_get(entry);
+ return entry;
+}
+
+void
+__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv)
+{
+ if (--non_repr_priv->ref_count)
+ return;
+
+ list_del(&non_repr_priv->list);
+ kfree(non_repr_priv);
+}
+
+void
+nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev)
+{
+ struct nfp_flower_non_repr_priv *entry;
+
+ entry = nfp_flower_non_repr_priv_lookup(app, netdev);
+ if (!entry)
+ return;
+
+ __nfp_flower_non_repr_priv_put(entry);
+}
+
static enum nfp_repr_type
nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
{
@@ -107,16 +172,14 @@ static int
nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl)
{
struct nfp_flower_priv *priv = app->priv;
- int err;
if (!tot_repl)
return 0;
lockdep_assert_held(&app->pf->lock);
- err = wait_event_interruptible_timeout(priv->reify_wait_queue,
- atomic_read(replies) >= tot_repl,
- msecs_to_jiffies(10));
- if (err <= 0) {
+ if (!wait_event_timeout(priv->reify_wait_queue,
+ atomic_read(replies) >= tot_repl,
+ NFP_FL_REPLY_TIMEOUT)) {
nfp_warn(app->cpp, "Not all reprs responded to reify\n");
return -EIO;
}
@@ -223,6 +286,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
nfp_repr = netdev_priv(repr);
nfp_repr->app_priv = repr_priv;
+ repr_priv->nfp_repr = nfp_repr;
/* For now we only support 1 PF */
WARN_ON(repr_type == NFP_REPR_TYPE_PF && i);
@@ -337,6 +401,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
nfp_repr = netdev_priv(repr);
nfp_repr->app_priv = repr_priv;
+ repr_priv->nfp_repr = nfp_repr;
port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr);
if (IS_ERR(port)) {
@@ -476,8 +541,8 @@ err_clear_nn:
static int nfp_flower_init(struct nfp_app *app)
{
+ u64 version, features, ctx_count, num_mems;
const struct nfp_pf *pf = app->pf;
- u64 version, features, ctx_count;
struct nfp_flower_priv *app_priv;
int err;
@@ -502,6 +567,23 @@ static int nfp_flower_init(struct nfp_app *app)
return err;
}
+ num_mems = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_SPLIT",
+ &err);
+ if (err) {
+ nfp_warn(app->cpp,
+ "FlowerNIC: unsupported host context memory: %d\n",
+ err);
+ err = 0;
+ num_mems = 1;
+ }
+
+ if (!FIELD_FIT(NFP_FL_STAT_ID_MU_NUM, num_mems) || !num_mems) {
+ nfp_warn(app->cpp,
+ "FlowerNIC: invalid host context memory: %llu\n",
+ num_mems);
+ return -EINVAL;
+ }
+
ctx_count = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_COUNT",
&err);
if (err) {
@@ -522,6 +604,8 @@ static int nfp_flower_init(struct nfp_app *app)
if (!app_priv)
return -ENOMEM;
+ app_priv->total_mem_units = num_mems;
+ app_priv->active_mem_unit = 0;
app_priv->stats_ring_size = roundup_pow_of_two(ctx_count);
app->priv = app_priv;
app_priv->app = app;
@@ -533,7 +617,7 @@ static int nfp_flower_init(struct nfp_app *app)
init_waitqueue_head(&app_priv->mtu_conf.wait_q);
spin_lock_init(&app_priv->mtu_conf.lock);
- err = nfp_flower_metadata_init(app, ctx_count);
+ err = nfp_flower_metadata_init(app, ctx_count, num_mems);
if (err)
goto err_free_app_priv;
@@ -558,6 +642,7 @@ static int nfp_flower_init(struct nfp_app *app)
}
INIT_LIST_HEAD(&app_priv->indr_block_cb_priv);
+ INIT_LIST_HEAD(&app_priv->non_repr_priv);
return 0;
@@ -601,7 +686,7 @@ nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
{
struct nfp_flower_priv *app_priv = app->priv;
struct nfp_repr *repr = netdev_priv(netdev);
- int err, ack;
+ int err;
/* Only need to config FW for physical port MTU change. */
if (repr->port->type != NFP_PORT_PHYS_PORT)
@@ -628,11 +713,9 @@ nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
}
/* Wait for fw to ack the change. */
- ack = wait_event_timeout(app_priv->mtu_conf.wait_q,
- nfp_flower_check_ack(app_priv),
- msecs_to_jiffies(10));
-
- if (!ack) {
+ if (!wait_event_timeout(app_priv->mtu_conf.wait_q,
+ nfp_flower_check_ack(app_priv),
+ NFP_FL_REPLY_TIMEOUT)) {
spin_lock_bh(&app_priv->mtu_conf.lock);
app_priv->mtu_conf.requested_val = 0;
spin_unlock_bh(&app_priv->mtu_conf.lock);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h
index b858bac47621..c0945a5fd1a4 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.h
@@ -20,6 +20,9 @@ struct nfp_fl_pre_lag;
struct net_device;
struct nfp_app;
+#define NFP_FL_STAT_ID_MU_NUM GENMASK(31, 22)
+#define NFP_FL_STAT_ID_STAT GENMASK(21, 0)
+
#define NFP_FL_STATS_ELEM_RS FIELD_SIZEOF(struct nfp_fl_stats_id, \
init_unalloc)
#define NFP_FLOWER_MASK_ENTRY_RS 256
@@ -54,6 +57,26 @@ struct nfp_fl_stats_id {
};
/**
+ * struct nfp_fl_tunnel_offloads - priv data for tunnel offloads
+ * @offloaded_macs: Hashtable of the offloaded MAC addresses
+ * @ipv4_off_list: List of IPv4 addresses to offload
+ * @neigh_off_list: List of neighbour offloads
+ * @ipv4_off_lock: Lock for the IPv4 address list
+ * @neigh_off_lock: Lock for the neighbour address list
+ * @mac_off_ids: IDA to manage id assignment for offloaded MACs
+ * @neigh_nb: Notifier to monitor neighbour state
+ */
+struct nfp_fl_tunnel_offloads {
+ struct rhashtable offloaded_macs;
+ struct list_head ipv4_off_list;
+ struct list_head neigh_off_list;
+ struct mutex ipv4_off_lock;
+ spinlock_t neigh_off_lock;
+ struct ida mac_off_ids;
+ struct notifier_block neigh_nb;
+};
+
+/**
* struct nfp_mtu_conf - manage MTU setting
* @portnum: NFP port number of repr with requested MTU change
* @requested_val: MTU value requested for repr
@@ -113,23 +136,16 @@ struct nfp_fl_lag {
* processing
* @cmsg_skbs_low: List of lower priority skbs for control message
* processing
- * @nfp_mac_off_list: List of MAC addresses to offload
- * @nfp_mac_index_list: List of unique 8-bit indexes for non NFP netdevs
- * @nfp_ipv4_off_list: List of IPv4 addresses to offload
- * @nfp_neigh_off_list: List of neighbour offloads
- * @nfp_mac_off_lock: Lock for the MAC address list
- * @nfp_mac_index_lock: Lock for the MAC index list
- * @nfp_ipv4_off_lock: Lock for the IPv4 address list
- * @nfp_neigh_off_lock: Lock for the neighbour address list
- * @nfp_mac_off_ids: IDA to manage id assignment for offloaded macs
- * @nfp_mac_off_count: Number of MACs in address list
- * @nfp_tun_neigh_nb: Notifier to monitor neighbour state
+ * @tun: Tunnel offload data
* @reify_replies: atomically stores the number of replies received
* from firmware for repr reify
* @reify_wait_queue: wait queue for repr reify response counting
* @mtu_conf: Configuration of repr MTU value
* @nfp_lag: Link aggregation data block
* @indr_block_cb_priv: List of priv data passed to indirect block cbs
+ * @non_repr_priv: List of offloaded non-repr ports and their priv data
+ * @active_mem_unit: Current active memory unit for flower rules
+ * @total_mem_units: Total number of available memory units for flower rules
*/
struct nfp_flower_priv {
struct nfp_app *app;
@@ -147,30 +163,47 @@ struct nfp_flower_priv {
struct work_struct cmsg_work;
struct sk_buff_head cmsg_skbs_high;
struct sk_buff_head cmsg_skbs_low;
- struct list_head nfp_mac_off_list;
- struct list_head nfp_mac_index_list;
- struct list_head nfp_ipv4_off_list;
- struct list_head nfp_neigh_off_list;
- struct mutex nfp_mac_off_lock;
- struct mutex nfp_mac_index_lock;
- struct mutex nfp_ipv4_off_lock;
- spinlock_t nfp_neigh_off_lock;
- struct ida nfp_mac_off_ids;
- int nfp_mac_off_count;
- struct notifier_block nfp_tun_neigh_nb;
+ struct nfp_fl_tunnel_offloads tun;
atomic_t reify_replies;
wait_queue_head_t reify_wait_queue;
struct nfp_mtu_conf mtu_conf;
struct nfp_fl_lag nfp_lag;
struct list_head indr_block_cb_priv;
+ struct list_head non_repr_priv;
+ unsigned int active_mem_unit;
+ unsigned int total_mem_units;
};
/**
* struct nfp_flower_repr_priv - Flower APP per-repr priv data
+ * @nfp_repr: Back pointer to nfp_repr
* @lag_port_flags: Extended port flags to record lag state of repr
+ * @mac_offloaded: Flag indicating a MAC address is offloaded for repr
+ * @offloaded_mac_addr: MAC address that has been offloaded for repr
+ * @mac_list: List entry of reprs that share the same offloaded MAC
*/
struct nfp_flower_repr_priv {
+ struct nfp_repr *nfp_repr;
unsigned long lag_port_flags;
+ bool mac_offloaded;
+ u8 offloaded_mac_addr[ETH_ALEN];
+ struct list_head mac_list;
+};
+
+/**
+ * struct nfp_flower_non_repr_priv - Priv data for non-repr offloaded ports
+ * @list: List entry of offloaded reprs
+ * @netdev: Pointer to non-repr net_device
+ * @ref_count: Number of references held for this priv data
+ * @mac_offloaded: Flag indicating a MAC address is offloaded for device
+ * @offloaded_mac_addr: MAC address that has been offloaded for dev
+ */
+struct nfp_flower_non_repr_priv {
+ struct list_head list;
+ struct net_device *netdev;
+ int ref_count;
+ bool mac_offloaded;
+ u8 offloaded_mac_addr[ETH_ALEN];
};
struct nfp_fl_key_ls {
@@ -217,7 +250,8 @@ struct nfp_fl_stats_frame {
__be64 stats_cookie;
};
-int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count);
+int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
+ unsigned int host_ctx_split);
void nfp_flower_metadata_cleanup(struct nfp_app *app);
int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
@@ -252,7 +286,6 @@ void nfp_tunnel_config_stop(struct nfp_app *app);
int nfp_tunnel_mac_event_handler(struct nfp_app *app,
struct net_device *netdev,
unsigned long event, void *ptr);
-void nfp_tunnel_write_macs(struct nfp_app *app);
void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4);
void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4);
void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb);
@@ -273,4 +306,12 @@ int nfp_flower_reg_indir_block_handler(struct nfp_app *app,
struct net_device *netdev,
unsigned long event);
+void
+__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv);
+struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev);
+void
+__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv);
+void
+nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev);
#endif
diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c
index cdf75595f627..e03c8ef2c28c 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/match.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/match.c
@@ -8,31 +8,41 @@
#include "main.h"
static void
-nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *frame,
- struct tc_cls_flower_offload *flow, u8 key_type,
- bool mask_version)
+nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext,
+ struct nfp_flower_meta_tci *msk,
+ struct tc_cls_flower_offload *flow, u8 key_type)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_vlan *flow_vlan;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
u16 tmp_tci;
- memset(frame, 0, sizeof(struct nfp_flower_meta_tci));
+ memset(ext, 0, sizeof(struct nfp_flower_meta_tci));
+ memset(msk, 0, sizeof(struct nfp_flower_meta_tci));
+
/* Populate the metadata frame. */
- frame->nfp_flow_key_layer = key_type;
- frame->mask_id = ~0;
+ ext->nfp_flow_key_layer = key_type;
+ ext->mask_id = ~0;
+
+ msk->nfp_flow_key_layer = key_type;
+ msk->mask_id = ~0;
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- flow_vlan = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- target);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan match;
+
+ flow_rule_match_vlan(rule, &match);
/* Populate the tci field. */
- if (flow_vlan->vlan_id || flow_vlan->vlan_priority) {
+ if (match.key->vlan_id || match.key->vlan_priority) {
tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
- flow_vlan->vlan_priority) |
+ match.key->vlan_priority) |
FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
- flow_vlan->vlan_id) |
+ match.key->vlan_id) |
NFP_FLOWER_MASK_VLAN_CFI;
- frame->tci = cpu_to_be16(tmp_tci);
+ ext->tci = cpu_to_be16(tmp_tci);
+ tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
+ match.mask->vlan_priority) |
+ FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
+ match.mask->vlan_id) |
+ NFP_FLOWER_MASK_VLAN_CFI;
+ msk->tci = cpu_to_be16(tmp_tci);
}
}
}
@@ -64,231 +74,249 @@ nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
}
static void
-nfp_flower_compile_mac(struct nfp_flower_mac_mpls *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
+ struct nfp_flower_mac_mpls *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_eth_addrs *addr;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
+
+ memset(ext, 0, sizeof(struct nfp_flower_mac_mpls));
+ memset(msk, 0, sizeof(struct nfp_flower_mac_mpls));
- memset(frame, 0, sizeof(struct nfp_flower_mac_mpls));
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_match_eth_addrs match;
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- addr = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- target);
+ flow_rule_match_eth_addrs(rule, &match);
/* Populate mac frame. */
- ether_addr_copy(frame->mac_dst, &addr->dst[0]);
- ether_addr_copy(frame->mac_src, &addr->src[0]);
+ ether_addr_copy(ext->mac_dst, &match.key->dst[0]);
+ ether_addr_copy(ext->mac_src, &match.key->src[0]);
+ ether_addr_copy(msk->mac_dst, &match.mask->dst[0]);
+ ether_addr_copy(msk->mac_src, &match.mask->src[0]);
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_MPLS)) {
- struct flow_dissector_key_mpls *mpls;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
+ struct flow_match_mpls match;
u32 t_mpls;
- mpls = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_MPLS,
- target);
-
- t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, mpls->mpls_label) |
- FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, mpls->mpls_tc) |
- FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, mpls->mpls_bos) |
+ flow_rule_match_mpls(rule, &match);
+ t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.key->mpls_label) |
+ FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.key->mpls_tc) |
+ FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.key->mpls_bos) |
NFP_FLOWER_MASK_MPLS_Q;
-
- frame->mpls_lse = cpu_to_be32(t_mpls);
- } else if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC)) {
+ ext->mpls_lse = cpu_to_be32(t_mpls);
+ t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.mask->mpls_label) |
+ FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.mask->mpls_tc) |
+ FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.mask->mpls_bos) |
+ NFP_FLOWER_MASK_MPLS_Q;
+ msk->mpls_lse = cpu_to_be32(t_mpls);
+ } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
/* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q
* bit, which indicates an mpls ether type but without any
* mpls fields.
*/
- struct flow_dissector_key_basic *key_basic;
-
- key_basic = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- flow->key);
- if (key_basic->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
- key_basic->n_proto == cpu_to_be16(ETH_P_MPLS_MC))
- frame->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
+ struct flow_match_basic match;
+
+ flow_rule_match_basic(rule, &match);
+ if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
+ match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) {
+ ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
+ msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
+ }
}
}
static void
-nfp_flower_compile_tport(struct nfp_flower_tp_ports *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
+ struct nfp_flower_tp_ports *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_ports *tp;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
+
+ memset(ext, 0, sizeof(struct nfp_flower_tp_ports));
+ memset(msk, 0, sizeof(struct nfp_flower_tp_ports));
- memset(frame, 0, sizeof(struct nfp_flower_tp_ports));
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- tp = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- target);
- frame->port_src = tp->src;
- frame->port_dst = tp->dst;
+ flow_rule_match_ports(rule, &match);
+ ext->port_src = match.key->src;
+ ext->port_dst = match.key->dst;
+ msk->port_src = match.mask->src;
+ msk->port_dst = match.mask->dst;
}
}
static void
-nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
+ struct nfp_flower_ip_ext *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *basic;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- basic = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- target);
- frame->proto = basic->ip_proto;
+ flow_rule_match_basic(rule, &match);
+ ext->proto = match.key->ip_proto;
+ msk->proto = match.mask->ip_proto;
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_IP)) {
- struct flow_dissector_key_ip *flow_ip;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
+ struct flow_match_ip match;
- flow_ip = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_IP,
- target);
- frame->tos = flow_ip->tos;
- frame->ttl = flow_ip->ttl;
+ flow_rule_match_ip(rule, &match);
+ ext->tos = match.key->tos;
+ ext->ttl = match.key->ttl;
+ msk->tos = match.mask->tos;
+ msk->ttl = match.mask->ttl;
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_TCP)) {
- struct flow_dissector_key_tcp *tcp;
- u32 tcp_flags;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
+ u16 tcp_flags, tcp_flags_mask;
+ struct flow_match_tcp match;
- tcp = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_TCP, target);
- tcp_flags = be16_to_cpu(tcp->flags);
+ flow_rule_match_tcp(rule, &match);
+ tcp_flags = be16_to_cpu(match.key->flags);
+ tcp_flags_mask = be16_to_cpu(match.mask->flags);
if (tcp_flags & TCPHDR_FIN)
- frame->flags |= NFP_FL_TCP_FLAG_FIN;
+ ext->flags |= NFP_FL_TCP_FLAG_FIN;
+ if (tcp_flags_mask & TCPHDR_FIN)
+ msk->flags |= NFP_FL_TCP_FLAG_FIN;
+
if (tcp_flags & TCPHDR_SYN)
- frame->flags |= NFP_FL_TCP_FLAG_SYN;
+ ext->flags |= NFP_FL_TCP_FLAG_SYN;
+ if (tcp_flags_mask & TCPHDR_SYN)
+ msk->flags |= NFP_FL_TCP_FLAG_SYN;
+
if (tcp_flags & TCPHDR_RST)
- frame->flags |= NFP_FL_TCP_FLAG_RST;
+ ext->flags |= NFP_FL_TCP_FLAG_RST;
+ if (tcp_flags_mask & TCPHDR_RST)
+ msk->flags |= NFP_FL_TCP_FLAG_RST;
+
if (tcp_flags & TCPHDR_PSH)
- frame->flags |= NFP_FL_TCP_FLAG_PSH;
+ ext->flags |= NFP_FL_TCP_FLAG_PSH;
+ if (tcp_flags_mask & TCPHDR_PSH)
+ msk->flags |= NFP_FL_TCP_FLAG_PSH;
+
if (tcp_flags & TCPHDR_URG)
- frame->flags |= NFP_FL_TCP_FLAG_URG;
+ ext->flags |= NFP_FL_TCP_FLAG_URG;
+ if (tcp_flags_mask & TCPHDR_URG)
+ msk->flags |= NFP_FL_TCP_FLAG_URG;
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key;
-
- key = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- target);
- if (key->flags & FLOW_DIS_IS_FRAGMENT)
- frame->flags |= NFP_FL_IP_FRAGMENTED;
- if (key->flags & FLOW_DIS_FIRST_FRAG)
- frame->flags |= NFP_FL_IP_FRAG_FIRST;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
+
+ flow_rule_match_control(rule, &match);
+ if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
+ ext->flags |= NFP_FL_IP_FRAGMENTED;
+ if (match.mask->flags & FLOW_DIS_IS_FRAGMENT)
+ msk->flags |= NFP_FL_IP_FRAGMENTED;
+ if (match.key->flags & FLOW_DIS_FIRST_FRAG)
+ ext->flags |= NFP_FL_IP_FRAG_FIRST;
+ if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
+ msk->flags |= NFP_FL_IP_FRAG_FIRST;
}
}
static void
-nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
+ struct nfp_flower_ipv4 *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_ipv4_addrs *addr;
-
- memset(frame, 0, sizeof(struct nfp_flower_ipv4));
-
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
- addr = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- target);
- frame->ipv4_src = addr->src;
- frame->ipv4_dst = addr->dst;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
+ struct flow_match_ipv4_addrs match;
+
+ memset(ext, 0, sizeof(struct nfp_flower_ipv4));
+ memset(msk, 0, sizeof(struct nfp_flower_ipv4));
+
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
+ flow_rule_match_ipv4_addrs(rule, &match);
+ ext->ipv4_src = match.key->src;
+ ext->ipv4_dst = match.key->dst;
+ msk->ipv4_src = match.mask->src;
+ msk->ipv4_dst = match.mask->dst;
}
- nfp_flower_compile_ip_ext(&frame->ip_ext, flow, mask_version);
+ nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, flow);
}
static void
-nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
+ struct nfp_flower_ipv6 *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_ipv6_addrs *addr;
-
- memset(frame, 0, sizeof(struct nfp_flower_ipv6));
-
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
- addr = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- target);
- frame->ipv6_src = addr->src;
- frame->ipv6_dst = addr->dst;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
+
+ memset(ext, 0, sizeof(struct nfp_flower_ipv6));
+ memset(msk, 0, sizeof(struct nfp_flower_ipv6));
+
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
+ struct flow_match_ipv6_addrs match;
+
+ flow_rule_match_ipv6_addrs(rule, &match);
+ ext->ipv6_src = match.key->src;
+ ext->ipv6_dst = match.key->dst;
+ msk->ipv6_src = match.mask->src;
+ msk->ipv6_dst = match.mask->dst;
}
- nfp_flower_compile_ip_ext(&frame->ip_ext, flow, mask_version);
+ nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, flow);
}
static int
-nfp_flower_compile_geneve_opt(void *key_buf, struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_geneve_opt(void *ext, void *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_enc_opts *opts;
+ struct flow_match_enc_opts match;
- opts = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_OPTS,
- target);
- memcpy(key_buf, opts->data, opts->len);
+ flow_rule_match_enc_opts(flow->rule, &match);
+ memcpy(ext, match.key->data, match.key->len);
+ memcpy(msk, match.mask->data, match.mask->len);
return 0;
}
static void
-nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *frame,
- struct tc_cls_flower_offload *flow,
- bool mask_version)
+nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext,
+ struct nfp_flower_ipv4_udp_tun *msk,
+ struct tc_cls_flower_offload *flow)
{
- struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
- struct flow_dissector_key_ipv4_addrs *tun_ips;
- struct flow_dissector_key_keyid *vni;
- struct flow_dissector_key_ip *ip;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
- memset(frame, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
+ memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
+ memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_match_enc_keyid match;
u32 temp_vni;
- vni = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- target);
- temp_vni = be32_to_cpu(vni->keyid) << NFP_FL_TUN_VNI_OFFSET;
- frame->tun_id = cpu_to_be32(temp_vni);
+ flow_rule_match_enc_keyid(rule, &match);
+ temp_vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET;
+ ext->tun_id = cpu_to_be32(temp_vni);
+ temp_vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET;
+ msk->tun_id = cpu_to_be32(temp_vni);
}
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
- tun_ips =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
- target);
- frame->ip_src = tun_ips->src;
- frame->ip_dst = tun_ips->dst;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
+ struct flow_match_ipv4_addrs match;
+
+ flow_rule_match_enc_ipv4_addrs(rule, &match);
+ ext->ip_src = match.key->src;
+ ext->ip_dst = match.key->dst;
+ msk->ip_src = match.mask->src;
+ msk->ip_dst = match.mask->dst;
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ENC_IP)) {
- ip = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_IP,
- target);
- frame->tos = ip->tos;
- frame->ttl = ip->ttl;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
+ struct flow_match_ip match;
+
+ flow_rule_match_enc_ip(rule, &match);
+ ext->tos = match.key->tos;
+ ext->ttl = match.key->ttl;
+ msk->tos = match.mask->tos;
+ msk->ttl = match.mask->ttl;
}
}
@@ -313,12 +341,9 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
ext = nfp_flow->unmasked_data;
msk = nfp_flow->mask_data;
- /* Populate Exact Metadata. */
nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext,
- flow, key_ls->key_layer, false);
- /* Populate Mask Metadata. */
- nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)msk,
- flow, key_ls->key_layer, true);
+ (struct nfp_flower_meta_tci *)msk,
+ flow, key_ls->key_layer);
ext += sizeof(struct nfp_flower_meta_tci);
msk += sizeof(struct nfp_flower_meta_tci);
@@ -348,45 +373,33 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
msk += sizeof(struct nfp_flower_in_port);
if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
- /* Populate Exact MAC Data. */
nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext,
- flow, false);
- /* Populate Mask MAC Data. */
- nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)msk,
- flow, true);
+ (struct nfp_flower_mac_mpls *)msk,
+ flow);
ext += sizeof(struct nfp_flower_mac_mpls);
msk += sizeof(struct nfp_flower_mac_mpls);
}
if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
- /* Populate Exact TP Data. */
nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
- flow, false);
- /* Populate Mask TP Data. */
- nfp_flower_compile_tport((struct nfp_flower_tp_ports *)msk,
- flow, true);
+ (struct nfp_flower_tp_ports *)msk,
+ flow);
ext += sizeof(struct nfp_flower_tp_ports);
msk += sizeof(struct nfp_flower_tp_ports);
}
if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
- /* Populate Exact IPv4 Data. */
nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
- flow, false);
- /* Populate Mask IPv4 Data. */
- nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)msk,
- flow, true);
+ (struct nfp_flower_ipv4 *)msk,
+ flow);
ext += sizeof(struct nfp_flower_ipv4);
msk += sizeof(struct nfp_flower_ipv4);
}
if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
- /* Populate Exact IPv4 Data. */
nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
- flow, false);
- /* Populate Mask IPv4 Data. */
- nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)msk,
- flow, true);
+ (struct nfp_flower_ipv6 *)msk,
+ flow);
ext += sizeof(struct nfp_flower_ipv6);
msk += sizeof(struct nfp_flower_ipv6);
}
@@ -395,17 +408,11 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) {
__be32 tun_dst;
- /* Populate Exact VXLAN Data. */
- nfp_flower_compile_ipv4_udp_tun((void *)ext, flow, false);
- /* Populate Mask VXLAN Data. */
- nfp_flower_compile_ipv4_udp_tun((void *)msk, flow, true);
+ nfp_flower_compile_ipv4_udp_tun((void *)ext, (void *)msk, flow);
tun_dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ip_dst;
ext += sizeof(struct nfp_flower_ipv4_udp_tun);
msk += sizeof(struct nfp_flower_ipv4_udp_tun);
- /* Configure tunnel end point MAC. */
- nfp_tunnel_write_macs(app);
-
/* Store the tunnel destination in the rule data.
* This must be present and be an exact match.
*/
@@ -413,11 +420,7 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
nfp_tunnel_add_ipv4_off(app, tun_dst);
if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) {
- err = nfp_flower_compile_geneve_opt(ext, flow, false);
- if (err)
- return err;
-
- err = nfp_flower_compile_geneve_opt(msk, flow, true);
+ err = nfp_flower_compile_geneve_opt(ext, msk, flow);
if (err)
return err;
}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
index 573a4400a26c..492837b852b6 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
@@ -4,6 +4,7 @@
#include <linux/hash.h>
#include <linux/hashtable.h>
#include <linux/jhash.h>
+#include <linux/math64.h>
#include <linux/vmalloc.h>
#include <net/pkt_cls.h>
@@ -52,8 +53,17 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)
freed_stats_id = priv->stats_ring_size;
/* Check for unallocated entries first. */
if (priv->stats_ids.init_unalloc > 0) {
- *stats_context_id = priv->stats_ids.init_unalloc - 1;
- priv->stats_ids.init_unalloc--;
+ if (priv->active_mem_unit == priv->total_mem_units) {
+ priv->stats_ids.init_unalloc--;
+ priv->active_mem_unit = 0;
+ }
+
+ *stats_context_id =
+ FIELD_PREP(NFP_FL_STAT_ID_STAT,
+ priv->stats_ids.init_unalloc - 1) |
+ FIELD_PREP(NFP_FL_STAT_ID_MU_NUM,
+ priv->active_mem_unit);
+ priv->active_mem_unit++;
return 0;
}
@@ -381,10 +391,11 @@ const struct rhashtable_params nfp_flower_table_params = {
.automatic_shrinking = true,
};
-int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count)
+int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
+ unsigned int host_num_mems)
{
struct nfp_flower_priv *priv = app->priv;
- int err;
+ int err, stats_size;
hash_init(priv->mask_table);
@@ -417,10 +428,12 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count)
if (!priv->stats_ids.free_list.buf)
goto err_free_last_used;
- priv->stats_ids.init_unalloc = host_ctx_count;
+ priv->stats_ids.init_unalloc = div_u64(host_ctx_count, host_num_mems);
- priv->stats = kvmalloc_array(priv->stats_ring_size,
- sizeof(struct nfp_fl_stats), GFP_KERNEL);
+ stats_size = FIELD_PREP(NFP_FL_STAT_ID_STAT, host_ctx_count) |
+ FIELD_PREP(NFP_FL_STAT_ID_MU_NUM, host_num_mems - 1);
+ priv->stats = kvmalloc_array(stats_size, sizeof(struct nfp_fl_stats),
+ GFP_KERNEL);
if (!priv->stats)
goto err_free_ring_buf;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 2cdbf29ecbe7..450d7296fd57 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -102,23 +102,22 @@ nfp_flower_xmit_flow(struct nfp_app *app, struct nfp_fl_payload *nfp_flow,
static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)
{
- return dissector_uses_key(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS) ||
- dissector_uses_key(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS) ||
- dissector_uses_key(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS) ||
- dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ICMP);
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+
+ return flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP);
}
static int
-nfp_flower_calc_opt_layer(struct flow_dissector_key_enc_opts *enc_opts,
+nfp_flower_calc_opt_layer(struct flow_match_enc_opts *enc_opts,
u32 *key_layer_two, int *key_size)
{
- if (enc_opts->len > NFP_FL_MAX_GENEVE_OPT_KEY)
+ if (enc_opts->key->len > NFP_FL_MAX_GENEVE_OPT_KEY)
return -EOPNOTSUPP;
- if (enc_opts->len > 0) {
+ if (enc_opts->key->len > 0) {
*key_layer_two |= NFP_FLOWER_LAYER2_GENEVE_OP;
*key_size += sizeof(struct nfp_flower_geneve_options);
}
@@ -133,20 +132,21 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
struct tc_cls_flower_offload *flow,
enum nfp_flower_tun_type *tun_type)
{
- struct flow_dissector_key_basic *mask_basic = NULL;
- struct flow_dissector_key_basic *key_basic = NULL;
+ struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow);
+ struct flow_dissector *dissector = rule->match.dissector;
+ struct flow_match_basic basic = { NULL, NULL};
struct nfp_flower_priv *priv = app->priv;
u32 key_layer_two;
u8 key_layer;
int key_size;
int err;
- if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
+ if (dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR)
return -EOPNOTSUPP;
/* If any tun dissector is used then the required set must be used. */
- if (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR &&
- (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
+ if (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR &&
+ (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
!= NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R)
return -EOPNOTSUPP;
@@ -155,76 +155,52 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
key_size = sizeof(struct nfp_flower_meta_tci) +
sizeof(struct nfp_flower_in_port);
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS) ||
- dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_MPLS)) {
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS) ||
+ flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
key_layer |= NFP_FLOWER_LAYER_MAC;
key_size += sizeof(struct nfp_flower_mac_mpls);
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *flow_vlan;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_match_vlan vlan;
- flow_vlan = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- flow->mask);
+ flow_rule_match_vlan(rule, &vlan);
if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_PCP) &&
- flow_vlan->vlan_priority)
+ vlan.key->vlan_priority)
return -EOPNOTSUPP;
}
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
- struct flow_dissector_key_ipv4_addrs *mask_ipv4 = NULL;
- struct flow_dissector_key_ports *mask_enc_ports = NULL;
- struct flow_dissector_key_enc_opts *enc_op = NULL;
- struct flow_dissector_key_ports *enc_ports = NULL;
- struct flow_dissector_key_control *mask_enc_ctl =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_CONTROL,
- flow->mask);
- struct flow_dissector_key_control *enc_ctl =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_CONTROL,
- flow->key);
-
- if (mask_enc_ctl->addr_type != 0xffff ||
- enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+ struct flow_match_enc_opts enc_op = { NULL, NULL };
+ struct flow_match_ipv4_addrs ipv4_addrs;
+ struct flow_match_control enc_ctl;
+ struct flow_match_ports enc_ports;
+
+ flow_rule_match_enc_control(rule, &enc_ctl);
+
+ if (enc_ctl.mask->addr_type != 0xffff ||
+ enc_ctl.key->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
return -EOPNOTSUPP;
/* These fields are already verified as used. */
- mask_ipv4 =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
- flow->mask);
- if (mask_ipv4->dst != cpu_to_be32(~0))
+ flow_rule_match_enc_ipv4_addrs(rule, &ipv4_addrs);
+ if (ipv4_addrs.mask->dst != cpu_to_be32(~0))
return -EOPNOTSUPP;
- mask_enc_ports =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_PORTS,
- flow->mask);
- enc_ports =
- skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_PORTS,
- flow->key);
-
- if (mask_enc_ports->dst != cpu_to_be16(~0))
+ flow_rule_match_enc_ports(rule, &enc_ports);
+ if (enc_ports.mask->dst != cpu_to_be16(~0))
return -EOPNOTSUPP;
- if (dissector_uses_key(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_OPTS)) {
- enc_op = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_ENC_OPTS,
- flow->key);
- }
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS))
+ flow_rule_match_enc_opts(rule, &enc_op);
- switch (enc_ports->dst) {
+ switch (enc_ports.key->dst) {
case htons(NFP_FL_VXLAN_PORT):
*tun_type = NFP_FL_TUNNEL_VXLAN;
key_layer |= NFP_FLOWER_LAYER_VXLAN;
key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
- if (enc_op)
+ if (enc_op.key)
return -EOPNOTSUPP;
break;
case htons(NFP_FL_GENEVE_PORT):
@@ -236,11 +212,11 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
- if (!enc_op)
+ if (!enc_op.key)
break;
if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT))
return -EOPNOTSUPP;
- err = nfp_flower_calc_opt_layer(enc_op, &key_layer_two,
+ err = nfp_flower_calc_opt_layer(&enc_op, &key_layer_two,
&key_size);
if (err)
return err;
@@ -254,19 +230,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
return -EOPNOTSUPP;
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- mask_basic = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- flow->mask);
-
- key_basic = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- flow->key);
- }
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC))
+ flow_rule_match_basic(rule, &basic);
- if (mask_basic && mask_basic->n_proto) {
+ if (basic.mask && basic.mask->n_proto) {
/* Ethernet type is present in the key. */
- switch (key_basic->n_proto) {
+ switch (basic.key->n_proto) {
case cpu_to_be16(ETH_P_IP):
key_layer |= NFP_FLOWER_LAYER_IPV4;
key_size += sizeof(struct nfp_flower_ipv4);
@@ -305,9 +274,9 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
}
}
- if (mask_basic && mask_basic->ip_proto) {
+ if (basic.mask && basic.mask->ip_proto) {
/* Ethernet type is present in the key. */
- switch (key_basic->ip_proto) {
+ switch (basic.key->ip_proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_SCTP:
@@ -324,14 +293,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
}
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_TCP)) {
- struct flow_dissector_key_tcp *tcp;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
+ struct flow_match_tcp tcp;
u32 tcp_flags;
- tcp = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_TCP,
- flow->key);
- tcp_flags = be16_to_cpu(tcp->flags);
+ flow_rule_match_tcp(rule, &tcp);
+ tcp_flags = be16_to_cpu(tcp.key->flags);
if (tcp_flags & ~NFP_FLOWER_SUPPORTED_TCPFLAGS)
return -EOPNOTSUPP;
@@ -347,12 +314,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
* space, thus we need to ensure we include a IPv4/IPv6 key
* layer if we have not done so already.
*/
- if (!key_basic)
+ if (!basic.key)
return -EOPNOTSUPP;
if (!(key_layer & NFP_FLOWER_LAYER_IPV4) &&
!(key_layer & NFP_FLOWER_LAYER_IPV6)) {
- switch (key_basic->n_proto) {
+ switch (basic.key->n_proto) {
case cpu_to_be16(ETH_P_IP):
key_layer |= NFP_FLOWER_LAYER_IPV4;
key_size += sizeof(struct nfp_flower_ipv4);
@@ -369,14 +336,11 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
}
}
- if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key_ctl;
-
- key_ctl = skb_flow_dissector_target(flow->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- flow->key);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control ctl;
- if (key_ctl->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS)
+ flow_rule_match_control(rule, &ctl);
+ if (ctl.key->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS)
return -EOPNOTSUPP;
}
@@ -589,9 +553,8 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id);
spin_lock_bh(&priv->stats_lock);
- tcf_exts_stats_update(flow->exts, priv->stats[ctx_id].bytes,
- priv->stats[ctx_id].pkts,
- priv->stats[ctx_id].used);
+ flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes,
+ priv->stats[ctx_id].pkts, priv->stats[ctx_id].used);
priv->stats[ctx_id].pkts = 0;
priv->stats[ctx_id].bytes = 0;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 2d9f26a725c2..4d78be4ec4e9 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -98,47 +98,51 @@ struct nfp_ipv4_addr_entry {
struct list_head list;
};
-/**
- * struct nfp_tun_mac_addr - configure MAC address of tunnel EP on NFP
- * @reserved: reserved for future use
- * @count: number of MAC addresses in the message
- * @addresses.index: index of MAC address in the lookup table
- * @addresses.addr: interface MAC address
- * @addresses: series of MACs to offload
- */
-struct nfp_tun_mac_addr {
- __be16 reserved;
- __be16 count;
- struct index_mac_addr {
- __be16 index;
- u8 addr[ETH_ALEN];
- } addresses[];
-};
+#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG 0x2
/**
- * struct nfp_tun_mac_offload_entry - list of MACs to offload
- * @index: index of MAC address for offloading
+ * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP
+ * @flags: MAC address offload options
+ * @count: number of MAC addresses in the message (should be 1)
+ * @index: index of MAC address in the lookup table
* @addr: interface MAC address
- * @list: list pointer
*/
-struct nfp_tun_mac_offload_entry {
+struct nfp_tun_mac_addr_offload {
+ __be16 flags;
+ __be16 count;
__be16 index;
u8 addr[ETH_ALEN];
- struct list_head list;
+};
+
+enum nfp_flower_mac_offload_cmd {
+ NFP_TUNNEL_MAC_OFFLOAD_ADD = 0,
+ NFP_TUNNEL_MAC_OFFLOAD_DEL = 1,
+ NFP_TUNNEL_MAC_OFFLOAD_MOD = 2,
};
#define NFP_MAX_MAC_INDEX 0xff
/**
- * struct nfp_tun_mac_non_nfp_idx - converts non NFP netdev ifindex to 8-bit id
- * @ifindex: netdev ifindex of the device
- * @index: index of netdevs mac on NFP
- * @list: list pointer
+ * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC
+ * @ht_node: Hashtable entry
+ * @addr: Offloaded MAC address
+ * @index: Offloaded index for given MAC address
+ * @ref_count: Number of devs using this MAC address
+ * @repr_list: List of reprs sharing this MAC address
*/
-struct nfp_tun_mac_non_nfp_idx {
- int ifindex;
- u8 index;
- struct list_head list;
+struct nfp_tun_offloaded_mac {
+ struct rhash_head ht_node;
+ u8 addr[ETH_ALEN];
+ u16 index;
+ int ref_count;
+ struct list_head repr_list;
+};
+
+static const struct rhashtable_params offloaded_macs_params = {
+ .key_offset = offsetof(struct nfp_tun_offloaded_mac, addr),
+ .head_offset = offsetof(struct nfp_tun_offloaded_mac, ht_node),
+ .key_len = ETH_ALEN,
+ .automatic_shrinking = true,
};
void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb)
@@ -205,15 +209,15 @@ static bool nfp_tun_has_route(struct nfp_app *app, __be32 ipv4_addr)
struct nfp_ipv4_route_entry *entry;
struct list_head *ptr, *storage;
- spin_lock_bh(&priv->nfp_neigh_off_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {
+ spin_lock_bh(&priv->tun.neigh_off_lock);
+ list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) {
entry = list_entry(ptr, struct nfp_ipv4_route_entry, list);
if (entry->ipv4_addr == ipv4_addr) {
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
return true;
}
}
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
return false;
}
@@ -223,24 +227,24 @@ static void nfp_tun_add_route_to_cache(struct nfp_app *app, __be32 ipv4_addr)
struct nfp_ipv4_route_entry *entry;
struct list_head *ptr, *storage;
- spin_lock_bh(&priv->nfp_neigh_off_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {
+ spin_lock_bh(&priv->tun.neigh_off_lock);
+ list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) {
entry = list_entry(ptr, struct nfp_ipv4_route_entry, list);
if (entry->ipv4_addr == ipv4_addr) {
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
return;
}
}
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
nfp_flower_cmsg_warn(app, "Mem error when storing new route.\n");
return;
}
entry->ipv4_addr = ipv4_addr;
- list_add_tail(&entry->list, &priv->nfp_neigh_off_list);
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ list_add_tail(&entry->list, &priv->tun.neigh_off_list);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
}
static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr)
@@ -249,8 +253,8 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr)
struct nfp_ipv4_route_entry *entry;
struct list_head *ptr, *storage;
- spin_lock_bh(&priv->nfp_neigh_off_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {
+ spin_lock_bh(&priv->tun.neigh_off_lock);
+ list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) {
entry = list_entry(ptr, struct nfp_ipv4_route_entry, list);
if (entry->ipv4_addr == ipv4_addr) {
list_del(&entry->list);
@@ -258,7 +262,7 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr)
break;
}
}
- spin_unlock_bh(&priv->nfp_neigh_off_lock);
+ spin_unlock_bh(&priv->tun.neigh_off_lock);
}
static void
@@ -326,7 +330,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
if (!nfp_netdev_is_nfp_repr(n->dev))
return NOTIFY_DONE;
- app_priv = container_of(nb, struct nfp_flower_priv, nfp_tun_neigh_nb);
+ app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
app = app_priv->app;
/* Only concerned with changes to routes already added to NFP. */
@@ -401,11 +405,11 @@ static void nfp_tun_write_ipv4_list(struct nfp_app *app)
int count;
memset(&payload, 0, sizeof(struct nfp_tun_ipv4_addr));
- mutex_lock(&priv->nfp_ipv4_off_lock);
+ mutex_lock(&priv->tun.ipv4_off_lock);
count = 0;
- list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) {
+ list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
if (count >= NFP_FL_IPV4_ADDRS_MAX) {
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
nfp_flower_cmsg_warn(app, "IPv4 offload exceeds limit.\n");
return;
}
@@ -413,7 +417,7 @@ static void nfp_tun_write_ipv4_list(struct nfp_app *app)
payload.ipv4_addr[count++] = entry->ipv4_addr;
}
payload.count = cpu_to_be32(count);
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS,
sizeof(struct nfp_tun_ipv4_addr),
@@ -426,26 +430,26 @@ void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4)
struct nfp_ipv4_addr_entry *entry;
struct list_head *ptr, *storage;
- mutex_lock(&priv->nfp_ipv4_off_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) {
+ mutex_lock(&priv->tun.ipv4_off_lock);
+ list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
if (entry->ipv4_addr == ipv4) {
entry->ref_count++;
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
return;
}
}
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n");
return;
}
entry->ipv4_addr = ipv4;
entry->ref_count = 1;
- list_add_tail(&entry->list, &priv->nfp_ipv4_off_list);
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ list_add_tail(&entry->list, &priv->tun.ipv4_off_list);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
nfp_tun_write_ipv4_list(app);
}
@@ -456,8 +460,8 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4)
struct nfp_ipv4_addr_entry *entry;
struct list_head *ptr, *storage;
- mutex_lock(&priv->nfp_ipv4_off_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) {
+ mutex_lock(&priv->tun.ipv4_off_lock);
+ list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
if (entry->ipv4_addr == ipv4) {
entry->ref_count--;
@@ -468,191 +472,357 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4)
break;
}
}
- mutex_unlock(&priv->nfp_ipv4_off_lock);
+ mutex_unlock(&priv->tun.ipv4_off_lock);
nfp_tun_write_ipv4_list(app);
}
-void nfp_tunnel_write_macs(struct nfp_app *app)
+static int
+__nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del)
{
- struct nfp_flower_priv *priv = app->priv;
- struct nfp_tun_mac_offload_entry *entry;
- struct nfp_tun_mac_addr *payload;
- struct list_head *ptr, *storage;
- int mac_count, err, pay_size;
+ struct nfp_tun_mac_addr_offload payload;
- mutex_lock(&priv->nfp_mac_off_lock);
- if (!priv->nfp_mac_off_count) {
- mutex_unlock(&priv->nfp_mac_off_lock);
- return;
- }
+ memset(&payload, 0, sizeof(payload));
- pay_size = sizeof(struct nfp_tun_mac_addr) +
- sizeof(struct index_mac_addr) * priv->nfp_mac_off_count;
+ if (del)
+ payload.flags = cpu_to_be16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
- payload = kzalloc(pay_size, GFP_KERNEL);
- if (!payload) {
- mutex_unlock(&priv->nfp_mac_off_lock);
- return;
- }
+ /* FW supports multiple MACs per cmsg but restrict to single. */
+ payload.count = cpu_to_be16(1);
+ payload.index = cpu_to_be16(idx);
+ ether_addr_copy(payload.addr, mac);
- payload->count = cpu_to_be16(priv->nfp_mac_off_count);
+ return nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC,
+ sizeof(struct nfp_tun_mac_addr_offload),
+ &payload, GFP_KERNEL);
+}
- mac_count = 0;
- list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) {
- entry = list_entry(ptr, struct nfp_tun_mac_offload_entry,
- list);
- payload->addresses[mac_count].index = entry->index;
- ether_addr_copy(payload->addresses[mac_count].addr,
- entry->addr);
- mac_count++;
- }
+static bool nfp_tunnel_port_is_phy_repr(int port)
+{
+ if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) ==
+ NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT)
+ return true;
- err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC,
- pay_size, payload, GFP_KERNEL);
+ return false;
+}
- kfree(payload);
+static u16 nfp_tunnel_get_mac_idx_from_phy_port_id(int port)
+{
+ return port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;
+}
- if (err) {
- mutex_unlock(&priv->nfp_mac_off_lock);
- /* Write failed so retain list for future retry. */
- return;
- }
+static u16 nfp_tunnel_get_global_mac_idx_from_ida(int id)
+{
+ return id << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
+}
+
+static int nfp_tunnel_get_ida_from_global_mac_idx(u16 nfp_mac_idx)
+{
+ return nfp_mac_idx >> 8;
+}
+
+static bool nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx)
+{
+ return (nfp_mac_idx & 0xff) == NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
+}
+
+static struct nfp_tun_offloaded_mac *
+nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, u8 *mac)
+{
+ struct nfp_flower_priv *priv = app->priv;
+
+ return rhashtable_lookup_fast(&priv->tun.offloaded_macs, mac,
+ offloaded_macs_params);
+}
+
+static void
+nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac *entry,
+ struct net_device *netdev, bool mod)
+{
+ if (nfp_netdev_is_nfp_repr(netdev)) {
+ struct nfp_flower_repr_priv *repr_priv;
+ struct nfp_repr *repr;
- /* If list was successfully offloaded, flush it. */
- list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) {
- entry = list_entry(ptr, struct nfp_tun_mac_offload_entry,
- list);
- list_del(&entry->list);
- kfree(entry);
+ repr = netdev_priv(netdev);
+ repr_priv = repr->app_priv;
+
+ /* If modifing MAC, remove repr from old list first. */
+ if (mod)
+ list_del(&repr_priv->mac_list);
+
+ list_add_tail(&repr_priv->mac_list, &entry->repr_list);
}
- priv->nfp_mac_off_count = 0;
- mutex_unlock(&priv->nfp_mac_off_lock);
+ entry->ref_count++;
}
-static int nfp_tun_get_mac_idx(struct nfp_app *app, int ifindex)
+static int
+nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev,
+ int port, bool mod)
{
struct nfp_flower_priv *priv = app->priv;
- struct nfp_tun_mac_non_nfp_idx *entry;
- struct list_head *ptr, *storage;
- int idx;
-
- mutex_lock(&priv->nfp_mac_index_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) {
- entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list);
- if (entry->ifindex == ifindex) {
- idx = entry->index;
- mutex_unlock(&priv->nfp_mac_index_lock);
- return idx;
- }
+ int ida_idx = NFP_MAX_MAC_INDEX, err;
+ struct nfp_tun_offloaded_mac *entry;
+ u16 nfp_mac_idx = 0;
+
+ entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr);
+ if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) {
+ nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod);
+ return 0;
}
- idx = ida_simple_get(&priv->nfp_mac_off_ids, 0,
- NFP_MAX_MAC_INDEX, GFP_KERNEL);
- if (idx < 0) {
- mutex_unlock(&priv->nfp_mac_index_lock);
- return idx;
+ /* Assign a global index if non-repr or MAC address is now shared. */
+ if (entry || !port) {
+ ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0,
+ NFP_MAX_MAC_INDEX, GFP_KERNEL);
+ if (ida_idx < 0)
+ return ida_idx;
+
+ nfp_mac_idx = nfp_tunnel_get_global_mac_idx_from_ida(ida_idx);
+ } else {
+ nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port);
}
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
- mutex_unlock(&priv->nfp_mac_index_lock);
- return -ENOMEM;
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ err = -ENOMEM;
+ goto err_free_ida;
+ }
+
+ ether_addr_copy(entry->addr, netdev->dev_addr);
+ INIT_LIST_HEAD(&entry->repr_list);
+
+ if (rhashtable_insert_fast(&priv->tun.offloaded_macs,
+ &entry->ht_node,
+ offloaded_macs_params)) {
+ err = -ENOMEM;
+ goto err_free_entry;
+ }
+ }
+
+ err = __nfp_tunnel_offload_mac(app, netdev->dev_addr,
+ nfp_mac_idx, false);
+ if (err) {
+ /* If not shared then free. */
+ if (!entry->ref_count)
+ goto err_remove_hash;
+ goto err_free_ida;
}
- entry->ifindex = ifindex;
- entry->index = idx;
- list_add_tail(&entry->list, &priv->nfp_mac_index_list);
- mutex_unlock(&priv->nfp_mac_index_lock);
- return idx;
+ entry->index = nfp_mac_idx;
+ nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod);
+
+ return 0;
+
+err_remove_hash:
+ rhashtable_remove_fast(&priv->tun.offloaded_macs, &entry->ht_node,
+ offloaded_macs_params);
+err_free_entry:
+ kfree(entry);
+err_free_ida:
+ if (ida_idx != NFP_MAX_MAC_INDEX)
+ ida_simple_remove(&priv->tun.mac_off_ids, ida_idx);
+
+ return err;
}
-static void nfp_tun_del_mac_idx(struct nfp_app *app, int ifindex)
+static int
+nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev,
+ u8 *mac, bool mod)
{
struct nfp_flower_priv *priv = app->priv;
- struct nfp_tun_mac_non_nfp_idx *entry;
- struct list_head *ptr, *storage;
+ struct nfp_flower_repr_priv *repr_priv;
+ struct nfp_tun_offloaded_mac *entry;
+ struct nfp_repr *repr;
+ int ida_idx;
+
+ entry = nfp_tunnel_lookup_offloaded_macs(app, mac);
+ if (!entry)
+ return 0;
+
+ entry->ref_count--;
+ /* If del is part of a mod then mac_list is still in use elsewheree. */
+ if (nfp_netdev_is_nfp_repr(netdev) && !mod) {
+ repr = netdev_priv(netdev);
+ repr_priv = repr->app_priv;
+ list_del(&repr_priv->mac_list);
+ }
- mutex_lock(&priv->nfp_mac_index_lock);
- list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) {
- entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list);
- if (entry->ifindex == ifindex) {
- ida_simple_remove(&priv->nfp_mac_off_ids,
- entry->index);
- list_del(&entry->list);
- kfree(entry);
- break;
+ /* If MAC is now used by 1 repr set the offloaded MAC index to port. */
+ if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) {
+ u16 nfp_mac_idx;
+ int port, err;
+
+ repr_priv = list_first_entry(&entry->repr_list,
+ struct nfp_flower_repr_priv,
+ mac_list);
+ repr = repr_priv->nfp_repr;
+ port = nfp_repr_get_port_id(repr->netdev);
+ nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port);
+ err = __nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, false);
+ if (err) {
+ nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n",
+ netdev_name(netdev));
+ return 0;
}
+
+ ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index);
+ ida_simple_remove(&priv->tun.mac_off_ids, ida_idx);
+ entry->index = nfp_mac_idx;
+ return 0;
}
- mutex_unlock(&priv->nfp_mac_index_lock);
-}
-static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev,
- struct nfp_app *app)
-{
- struct nfp_flower_priv *priv = app->priv;
- struct nfp_tun_mac_offload_entry *entry;
- u16 nfp_mac_idx;
- int port = 0;
+ if (entry->ref_count)
+ return 0;
- /* Check if MAC should be offloaded. */
- if (!is_valid_ether_addr(netdev->dev_addr))
- return;
+ WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs,
+ &entry->ht_node,
+ offloaded_macs_params));
+ /* If MAC has global ID then extract and free the ida entry. */
+ if (nfp_tunnel_is_mac_idx_global(entry->index)) {
+ ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index);
+ ida_simple_remove(&priv->tun.mac_off_ids, ida_idx);
+ }
- if (nfp_netdev_is_nfp_repr(netdev))
+ kfree(entry);
+
+ return __nfp_tunnel_offload_mac(app, mac, 0, true);
+}
+
+static int
+nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev,
+ enum nfp_flower_mac_offload_cmd cmd)
+{
+ struct nfp_flower_non_repr_priv *nr_priv = NULL;
+ bool non_repr = false, *mac_offloaded;
+ u8 *off_mac = NULL;
+ int err, port = 0;
+
+ if (nfp_netdev_is_nfp_repr(netdev)) {
+ struct nfp_flower_repr_priv *repr_priv;
+ struct nfp_repr *repr;
+
+ repr = netdev_priv(netdev);
+ if (repr->app != app)
+ return 0;
+
+ repr_priv = repr->app_priv;
+ mac_offloaded = &repr_priv->mac_offloaded;
+ off_mac = &repr_priv->offloaded_mac_addr[0];
port = nfp_repr_get_port_id(netdev);
- else if (!nfp_fl_is_netdev_to_offload(netdev))
- return;
+ if (!nfp_tunnel_port_is_phy_repr(port))
+ return 0;
+ } else if (nfp_fl_is_netdev_to_offload(netdev)) {
+ nr_priv = nfp_flower_non_repr_priv_get(app, netdev);
+ if (!nr_priv)
+ return -ENOMEM;
+
+ mac_offloaded = &nr_priv->mac_offloaded;
+ off_mac = &nr_priv->offloaded_mac_addr[0];
+ non_repr = true;
+ } else {
+ return 0;
+ }
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- nfp_flower_cmsg_warn(app, "Mem fail when offloading MAC.\n");
- return;
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ err = -EINVAL;
+ goto err_put_non_repr_priv;
}
- if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) ==
- NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) {
- nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;
- } else if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) ==
- NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT) {
- port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port);
- nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT;
- } else {
- /* Must assign our own unique 8-bit index. */
- int idx = nfp_tun_get_mac_idx(app, netdev->ifindex);
+ if (cmd == NFP_TUNNEL_MAC_OFFLOAD_MOD && !*mac_offloaded)
+ cmd = NFP_TUNNEL_MAC_OFFLOAD_ADD;
- if (idx < 0) {
- nfp_flower_cmsg_warn(app, "Can't assign non-repr MAC index.\n");
- kfree(entry);
- return;
- }
- nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
+ switch (cmd) {
+ case NFP_TUNNEL_MAC_OFFLOAD_ADD:
+ err = nfp_tunnel_add_shared_mac(app, netdev, port, false);
+ if (err)
+ goto err_put_non_repr_priv;
+
+ if (non_repr)
+ __nfp_flower_non_repr_priv_get(nr_priv);
+
+ *mac_offloaded = true;
+ ether_addr_copy(off_mac, netdev->dev_addr);
+ break;
+ case NFP_TUNNEL_MAC_OFFLOAD_DEL:
+ /* Only attempt delete if add was successful. */
+ if (!*mac_offloaded)
+ break;
+
+ if (non_repr)
+ __nfp_flower_non_repr_priv_put(nr_priv);
+
+ *mac_offloaded = false;
+
+ err = nfp_tunnel_del_shared_mac(app, netdev, netdev->dev_addr,
+ false);
+ if (err)
+ goto err_put_non_repr_priv;
+
+ break;
+ case NFP_TUNNEL_MAC_OFFLOAD_MOD:
+ /* Ignore if changing to the same address. */
+ if (ether_addr_equal(netdev->dev_addr, off_mac))
+ break;
+
+ err = nfp_tunnel_add_shared_mac(app, netdev, port, true);
+ if (err)
+ goto err_put_non_repr_priv;
+
+ /* Delete the previous MAC address. */
+ err = nfp_tunnel_del_shared_mac(app, netdev, off_mac, true);
+ if (err)
+ nfp_flower_cmsg_warn(app, "Failed to remove offload of replaced MAC addr on %s.\n",
+ netdev_name(netdev));
+
+ ether_addr_copy(off_mac, netdev->dev_addr);
+ break;
+ default:
+ err = -EINVAL;
+ goto err_put_non_repr_priv;
}
- entry->index = cpu_to_be16(nfp_mac_idx);
- ether_addr_copy(entry->addr, netdev->dev_addr);
+ if (non_repr)
+ __nfp_flower_non_repr_priv_put(nr_priv);
+
+ return 0;
+
+err_put_non_repr_priv:
+ if (non_repr)
+ __nfp_flower_non_repr_priv_put(nr_priv);
- mutex_lock(&priv->nfp_mac_off_lock);
- priv->nfp_mac_off_count++;
- list_add_tail(&entry->list, &priv->nfp_mac_off_list);
- mutex_unlock(&priv->nfp_mac_off_lock);
+ return err;
}
int nfp_tunnel_mac_event_handler(struct nfp_app *app,
struct net_device *netdev,
unsigned long event, void *ptr)
{
- if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER) {
- /* If non-nfp netdev then free its offload index. */
- if (nfp_fl_is_netdev_to_offload(netdev))
- nfp_tun_del_mac_idx(app, netdev->ifindex);
- } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR ||
- event == NETDEV_REGISTER) {
- nfp_tun_add_to_mac_offload_list(netdev, app);
-
- /* Force a list write to keep NFP up to date. */
- nfp_tunnel_write_macs(app);
+ int err;
+
+ if (event == NETDEV_DOWN) {
+ err = nfp_tunnel_offload_mac(app, netdev,
+ NFP_TUNNEL_MAC_OFFLOAD_DEL);
+ if (err)
+ nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n",
+ netdev_name(netdev));
+ } else if (event == NETDEV_UP) {
+ err = nfp_tunnel_offload_mac(app, netdev,
+ NFP_TUNNEL_MAC_OFFLOAD_ADD);
+ if (err)
+ nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n",
+ netdev_name(netdev));
+ } else if (event == NETDEV_CHANGEADDR) {
+ /* Only offload addr change if netdev is already up. */
+ if (!(netdev->flags & IFF_UP))
+ return NOTIFY_OK;
+
+ err = nfp_tunnel_offload_mac(app, netdev,
+ NFP_TUNNEL_MAC_OFFLOAD_MOD);
+ if (err)
+ nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n",
+ netdev_name(netdev));
}
return NOTIFY_OK;
}
@@ -660,68 +830,62 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app,
int nfp_tunnel_config_start(struct nfp_app *app)
{
struct nfp_flower_priv *priv = app->priv;
+ int err;
+
+ /* Initialise rhash for MAC offload tracking. */
+ err = rhashtable_init(&priv->tun.offloaded_macs,
+ &offloaded_macs_params);
+ if (err)
+ return err;
- /* Initialise priv data for MAC offloading. */
- priv->nfp_mac_off_count = 0;
- mutex_init(&priv->nfp_mac_off_lock);
- INIT_LIST_HEAD(&priv->nfp_mac_off_list);
- mutex_init(&priv->nfp_mac_index_lock);
- INIT_LIST_HEAD(&priv->nfp_mac_index_list);
- ida_init(&priv->nfp_mac_off_ids);
+ ida_init(&priv->tun.mac_off_ids);
/* Initialise priv data for IPv4 offloading. */
- mutex_init(&priv->nfp_ipv4_off_lock);
- INIT_LIST_HEAD(&priv->nfp_ipv4_off_list);
+ mutex_init(&priv->tun.ipv4_off_lock);
+ INIT_LIST_HEAD(&priv->tun.ipv4_off_list);
/* Initialise priv data for neighbour offloading. */
- spin_lock_init(&priv->nfp_neigh_off_lock);
- INIT_LIST_HEAD(&priv->nfp_neigh_off_list);
- priv->nfp_tun_neigh_nb.notifier_call = nfp_tun_neigh_event_handler;
+ spin_lock_init(&priv->tun.neigh_off_lock);
+ INIT_LIST_HEAD(&priv->tun.neigh_off_list);
+ priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler;
+
+ err = register_netevent_notifier(&priv->tun.neigh_nb);
+ if (err) {
+ rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
+ nfp_check_rhashtable_empty, NULL);
+ return err;
+ }
- return register_netevent_notifier(&priv->nfp_tun_neigh_nb);
+ return 0;
}
void nfp_tunnel_config_stop(struct nfp_app *app)
{
- struct nfp_tun_mac_offload_entry *mac_entry;
struct nfp_flower_priv *priv = app->priv;
struct nfp_ipv4_route_entry *route_entry;
- struct nfp_tun_mac_non_nfp_idx *mac_idx;
struct nfp_ipv4_addr_entry *ip_entry;
struct list_head *ptr, *storage;
- unregister_netevent_notifier(&priv->nfp_tun_neigh_nb);
-
- /* Free any memory that may be occupied by MAC list. */
- list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) {
- mac_entry = list_entry(ptr, struct nfp_tun_mac_offload_entry,
- list);
- list_del(&mac_entry->list);
- kfree(mac_entry);
- }
-
- /* Free any memory that may be occupied by MAC index list. */
- list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) {
- mac_idx = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx,
- list);
- list_del(&mac_idx->list);
- kfree(mac_idx);
- }
+ unregister_netevent_notifier(&priv->tun.neigh_nb);
- ida_destroy(&priv->nfp_mac_off_ids);
+ ida_destroy(&priv->tun.mac_off_ids);
/* Free any memory that may be occupied by ipv4 list. */
- list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) {
+ list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
ip_entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
list_del(&ip_entry->list);
kfree(ip_entry);
}
/* Free any memory that may be occupied by the route list. */
- list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {
+ list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) {
route_entry = list_entry(ptr, struct nfp_ipv4_route_entry,
list);
list_del(&route_entry->list);
kfree(route_entry);
}
+
+ /* Destroy rhash. Entries should be cleaned on netdev notifier unreg. */
+ rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
+ nfp_check_rhashtable_empty, NULL);
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index d578d856a009..f8d422713705 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -433,4 +433,6 @@ int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
int nfp_app_nic_vnic_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,
struct nfp_net *nn, unsigned int id);
+struct devlink *nfp_devlink_get_devlink(struct net_device *netdev);
+
#endif
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index 808647ec3573..e9eca99cf493 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -4,6 +4,7 @@
#include <linux/rtnetlink.h>
#include <net/devlink.h>
+#include "nfpcore/nfp.h"
#include "nfpcore/nfp_nsp.h"
#include "nfp_app.h"
#include "nfp_main.h"
@@ -171,6 +172,173 @@ static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
return ret;
}
+static const struct nfp_devlink_versions_simple {
+ const char *key;
+ const char *hwinfo;
+} nfp_devlink_versions_hwinfo[] = {
+ { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", },
+ { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", },
+ { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", },
+ { "board.model", /* code name */ "assembly.model", },
+};
+
+static int
+nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req)
+{
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) {
+ const struct nfp_devlink_versions_simple *info;
+ const char *val;
+
+ info = &nfp_devlink_versions_hwinfo[i];
+
+ val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo);
+ if (!val)
+ continue;
+
+ err = devlink_info_version_fixed_put(req, info->key, val);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct nfp_devlink_versions {
+ enum nfp_nsp_versions id;
+ const char *key;
+} nfp_devlink_versions_nsp[] = {
+ { NFP_VERSIONS_BUNDLE, "fw.bundle_id", },
+ { NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, },
+ { NFP_VERSIONS_CPLD, "fw.cpld", },
+ { NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, },
+ { NFP_VERSIONS_UNDI, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, },
+ { NFP_VERSIONS_NCSI, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, },
+ { NFP_VERSIONS_CFGR, "chip.init", },
+};
+
+static int
+nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash,
+ const u8 *buf, unsigned int size)
+{
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) {
+ const struct nfp_devlink_versions *info;
+ const char *version;
+
+ info = &nfp_devlink_versions_nsp[i];
+
+ version = nfp_nsp_versions_get(info->id, flash, buf, size);
+ if (IS_ERR(version)) {
+ if (PTR_ERR(version) == -ENOENT)
+ continue;
+ else
+ return PTR_ERR(version);
+ }
+
+ if (flash)
+ err = devlink_info_version_stored_put(req, info->key,
+ version);
+ else
+ err = devlink_info_version_running_put(req, info->key,
+ version);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
+ struct netlink_ext_ack *extack)
+{
+ struct nfp_pf *pf = devlink_priv(devlink);
+ const char *sn, *vendor, *part;
+ struct nfp_nsp *nsp;
+ char *buf = NULL;
+ int err;
+
+ err = devlink_info_driver_name_put(req, "nfp");
+ if (err)
+ return err;
+
+ vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor");
+ part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
+ sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial");
+ if (vendor && part && sn) {
+ char *buf;
+
+ buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1,
+ GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = '\0';
+ strcat(buf, vendor);
+ strcat(buf, part);
+ strcat(buf, sn);
+
+ err = devlink_info_serial_number_put(req, buf);
+ kfree(buf);
+ if (err)
+ return err;
+ }
+
+ nsp = nfp_nsp_open(pf->cpp);
+ if (IS_ERR(nsp)) {
+ NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
+ return PTR_ERR(nsp);
+ }
+
+ if (nfp_nsp_has_versions(nsp)) {
+ buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL);
+ if (!buf) {
+ err = -ENOMEM;
+ goto err_close_nsp;
+ }
+
+ err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ);
+ if (err)
+ goto err_free_buf;
+
+ err = nfp_devlink_versions_get_nsp(req, false,
+ buf, NFP_NSP_VERSION_BUFSZ);
+ if (err)
+ goto err_free_buf;
+
+ err = nfp_devlink_versions_get_nsp(req, true,
+ buf, NFP_NSP_VERSION_BUFSZ);
+ if (err)
+ goto err_free_buf;
+
+ kfree(buf);
+ }
+
+ nfp_nsp_close(nsp);
+
+ return nfp_devlink_versions_get_hwinfo(pf, req);
+
+err_free_buf:
+ kfree(buf);
+err_close_nsp:
+ nfp_nsp_close(nsp);
+ return err;
+}
+
+static int
+nfp_devlink_flash_update(struct devlink *devlink, const char *path,
+ const char *component, struct netlink_ext_ack *extack)
+{
+ if (component)
+ return -EOPNOTSUPP;
+ return nfp_flash_update_common(devlink_priv(devlink), path, extack);
+}
+
const struct devlink_ops nfp_devlink_ops = {
.port_split = nfp_devlink_port_split,
.port_unsplit = nfp_devlink_port_unsplit,
@@ -178,6 +346,8 @@ const struct devlink_ops nfp_devlink_ops = {
.sb_pool_set = nfp_devlink_sb_pool_set,
.eswitch_mode_get = nfp_devlink_eswitch_mode_get,
.eswitch_mode_set = nfp_devlink_eswitch_mode_set,
+ .info_get = nfp_devlink_info_get,
+ .flash_update = nfp_devlink_flash_update,
};
int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
@@ -206,3 +376,14 @@ void nfp_devlink_port_unregister(struct nfp_port *port)
{
devlink_port_unregister(&port->dl_port);
}
+
+struct devlink *nfp_devlink_get_devlink(struct net_device *netdev)
+{
+ struct nfp_app *app;
+
+ app = nfp_app_from_netdev(netdev);
+ if (!app)
+ return NULL;
+
+ return priv_to_devlink(app->pf);
+}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index 6c10e8d119e4..f4c8776e42b6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -300,6 +300,47 @@ static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs)
return nfp_pcie_sriov_enable(pdev, num_vfs);
}
+int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
+ struct netlink_ext_ack *extack)
+{
+ struct device *dev = &pf->pdev->dev;
+ const struct firmware *fw;
+ struct nfp_nsp *nsp;
+ int err;
+
+ nsp = nfp_nsp_open(pf->cpp);
+ if (IS_ERR(nsp)) {
+ err = PTR_ERR(nsp);
+ if (extack)
+ NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
+ else
+ dev_err(dev, "Failed to access the NSP: %d\n", err);
+ return err;
+ }
+
+ err = request_firmware_direct(&fw, path, dev);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "unable to read flash file from disk");
+ goto exit_close_nsp;
+ }
+
+ dev_info(dev, "Please be patient while writing flash image: %s\n",
+ path);
+
+ err = nfp_nsp_write_flash(nsp, fw);
+ if (err < 0)
+ goto exit_release_fw;
+ dev_info(dev, "Finished writing flash image\n");
+ err = 0;
+
+exit_release_fw:
+ release_firmware(fw);
+exit_close_nsp:
+ nfp_nsp_close(nsp);
+ return err;
+}
+
static const struct firmware *
nfp_net_fw_request(struct pci_dev *pdev, struct nfp_pf *pf, const char *name)
{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index a3613a2e0aa5..b7211f200d22 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -164,6 +164,8 @@ nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
unsigned int min_size, struct nfp_cpp_area **area);
int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
void *out_data, u64 out_length);
+int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
+ struct netlink_ext_ack *extack);
enum nfp_dump_diag {
NFP_DUMP_NSP_DIAG = 0,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index e97636d2e6ee..6d1b8816552e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -36,7 +36,6 @@
#include <linux/vmalloc.h>
#include <linux/ktime.h>
-#include <net/switchdev.h>
#include <net/vxlan.h>
#include "nfpcore/nfp_nsp.h"
@@ -2170,9 +2169,9 @@ nfp_net_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
tx_ring->cnt = dp->txd_cnt;
tx_ring->size = array_size(tx_ring->cnt, sizeof(*tx_ring->txds));
- tx_ring->txds = dma_zalloc_coherent(dp->dev, tx_ring->size,
- &tx_ring->dma,
- GFP_KERNEL | __GFP_NOWARN);
+ tx_ring->txds = dma_alloc_coherent(dp->dev, tx_ring->size,
+ &tx_ring->dma,
+ GFP_KERNEL | __GFP_NOWARN);
if (!tx_ring->txds) {
netdev_warn(dp->netdev, "failed to allocate TX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
tx_ring->cnt);
@@ -2328,9 +2327,9 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
rx_ring->cnt = dp->rxd_cnt;
rx_ring->size = array_size(rx_ring->cnt, sizeof(*rx_ring->rxds));
- rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size,
- &rx_ring->dma,
- GFP_KERNEL | __GFP_NOWARN);
+ rx_ring->rxds = dma_alloc_coherent(dp->dev, rx_ring->size,
+ &rx_ring->dma,
+ GFP_KERNEL | __GFP_NOWARN);
if (!rx_ring->rxds) {
netdev_warn(dp->netdev, "failed to allocate RX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
rx_ring->cnt);
@@ -3531,6 +3530,8 @@ const struct net_device_ops nfp_net_netdev_ops = {
.ndo_udp_tunnel_add = nfp_net_add_vxlan_port,
.ndo_udp_tunnel_del = nfp_net_del_vxlan_port,
.ndo_bpf = nfp_net_xdp,
+ .ndo_get_port_parent_id = nfp_port_get_port_parent_id,
+ .ndo_get_devlink = nfp_devlink_get_devlink,
};
/**
@@ -3815,8 +3816,6 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
netdev->netdev_ops = &nfp_net_netdev_ops;
netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
- SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
-
/* MTU range: 68 - hw-specific max */
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = nn->max_mtu;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index cb9c512abc76..690b62718dbb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -1234,57 +1234,6 @@ static int nfp_net_set_channels(struct net_device *netdev,
return nfp_net_set_num_rings(nn, total_rx, total_tx);
}
-static int
-nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash)
-{
- const struct firmware *fw;
- struct nfp_app *app;
- struct nfp_nsp *nsp;
- struct device *dev;
- int err;
-
- if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
- return -EOPNOTSUPP;
-
- app = nfp_app_from_netdev(netdev);
- if (!app)
- return -EOPNOTSUPP;
-
- dev = &app->pdev->dev;
-
- nsp = nfp_nsp_open(app->cpp);
- if (IS_ERR(nsp)) {
- err = PTR_ERR(nsp);
- dev_err(dev, "Failed to access the NSP: %d\n", err);
- return err;
- }
-
- err = request_firmware_direct(&fw, flash->data, dev);
- if (err)
- goto exit_close_nsp;
-
- dev_info(dev, "Please be patient while writing flash image: %s\n",
- flash->data);
- dev_hold(netdev);
- rtnl_unlock();
-
- err = nfp_nsp_write_flash(nsp, fw);
- if (err < 0) {
- dev_err(dev, "Flash write failed: %d\n", err);
- goto exit_rtnl_lock;
- }
- dev_info(dev, "Finished writing flash image\n");
-
-exit_rtnl_lock:
- rtnl_lock();
- dev_put(netdev);
- release_firmware(fw);
-
-exit_close_nsp:
- nfp_nsp_close(nsp);
- return err;
-}
-
static const struct ethtool_ops nfp_net_ethtool_ops = {
.get_drvinfo = nfp_net_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -1295,7 +1244,6 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.get_sset_count = nfp_net_get_sset_count,
.get_rxnfc = nfp_net_get_rxnfc,
.set_rxnfc = nfp_net_set_rxnfc,
- .flash_device = nfp_net_flash_device,
.get_rxfh_indir_size = nfp_net_get_rxfh_indir_size,
.get_rxfh_key_size = nfp_net_get_rxfh_key_size,
.get_rxfh = nfp_net_get_rxfh,
@@ -1321,7 +1269,6 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
.get_strings = nfp_port_get_strings,
.get_ethtool_stats = nfp_port_get_stats,
.get_sset_count = nfp_port_get_sset_count,
- .flash_device = nfp_net_flash_device,
.set_dump = nfp_app_set_dump,
.get_dump_flag = nfp_app_get_dump_flag,
.get_dump_data = nfp_app_get_dump_data,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 69d7aebda09b..d2c803bb4e56 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -5,7 +5,6 @@
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/lockdep.h>
#include <net/dst_metadata.h>
-#include <net/switchdev.h>
#include "nfpcore/nfp_cpp.h"
#include "nfpcore/nfp_nsp.h"
@@ -273,6 +272,8 @@ const struct net_device_ops nfp_repr_netdev_ops = {
.ndo_fix_features = nfp_repr_fix_features,
.ndo_set_features = nfp_port_set_features,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_get_port_parent_id = nfp_port_get_port_parent_id,
+ .ndo_get_devlink = nfp_devlink_get_devlink,
};
void
@@ -336,8 +337,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
netdev->max_mtu = pf_netdev->max_mtu;
- SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
-
/* Set features the lower device can support with representors */
if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 86bc149ca231..93c5bfc0510b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -3,7 +3,6 @@
#include <linux/lockdep.h>
#include <linux/netdevice.h>
-#include <net/switchdev.h>
#include "nfpcore/nfp_cpp.h"
#include "nfpcore/nfp_nsp.h"
@@ -31,34 +30,22 @@ struct nfp_port *nfp_port_from_netdev(struct net_device *netdev)
return NULL;
}
-static int
-nfp_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr)
+int nfp_port_get_port_parent_id(struct net_device *netdev,
+ struct netdev_phys_item_id *ppid)
{
struct nfp_port *port;
+ const u8 *serial;
port = nfp_port_from_netdev(netdev);
if (!port)
return -EOPNOTSUPP;
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: {
- const u8 *serial;
- /* N.B: attr->u.ppid.id is binary data */
- attr->u.ppid.id_len = nfp_cpp_serial(port->app->cpp, &serial);
- memcpy(&attr->u.ppid.id, serial, attr->u.ppid.id_len);
- break;
- }
- default:
- return -EOPNOTSUPP;
- }
+ ppid->id_len = nfp_cpp_serial(port->app->cpp, &serial);
+ memcpy(&ppid->id, serial, ppid->id_len);
return 0;
}
-const struct switchdev_ops nfp_port_switchdev_ops = {
- .switchdev_port_attr_get = nfp_port_attr_get,
-};
-
int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h
index b2479a2a49e5..90ae053f5c07 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h
@@ -7,6 +7,7 @@
#include <net/devlink.h>
struct net_device;
+struct netdev_phys_item_id;
struct nfp_app;
struct nfp_pf;
struct nfp_port;
@@ -90,7 +91,6 @@ struct nfp_port {
};
extern const struct ethtool_ops nfp_port_ethtool_ops;
-extern const struct switchdev_ops nfp_port_switchdev_ops;
__printf(2, 3) u8 *nfp_pr_et(u8 *data, const char *fmt, ...);
@@ -106,6 +106,8 @@ int
nfp_port_set_features(struct net_device *netdev, netdev_features_t features);
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
+int nfp_port_get_port_parent_id(struct net_device *netdev,
+ struct netdev_phys_item_id *ppid);
struct nfp_port *
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
struct nfp_eth_table_port *__nfp_port_get_eth_port(struct nfp_port *port);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c b/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c
index 814360ed3a20..ea2e3f829aba 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c
@@ -48,6 +48,7 @@ int nfp_shared_buf_pool_get(struct nfp_pf *pf, unsigned int sb, u16 pool_index,
pool_info->pool_type = le32_to_cpu(get_data.pool_type);
pool_info->threshold_type = le32_to_cpu(get_data.threshold_type);
pool_info->size = le32_to_cpu(get_data.size) * unit_size;
+ pool_info->cell_size = unit_size;
return 0;
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
index ce1577bbbd2a..3a4e224a64b7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
@@ -7,11 +7,13 @@
* Jason McMullan <jason.mcmullan@netronome.com>
*/
+#include <asm/unaligned.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/overflow.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -36,6 +38,7 @@
#define NSP_COMMAND 0x08
#define NSP_COMMAND_OPTION GENMASK_ULL(63, 32)
#define NSP_COMMAND_CODE GENMASK_ULL(31, 16)
+#define NSP_COMMAND_DMA_BUF BIT_ULL(1)
#define NSP_COMMAND_START BIT_ULL(0)
/* CPP address to retrieve the data from */
@@ -48,8 +51,12 @@
#define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0)
#define NSP_DFLT_BUFFER_CONFIG 0x20
+#define NSP_DFLT_BUFFER_DMA_CHUNK_ORDER GENMASK_ULL(63, 58)
+#define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8)
#define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0)
+#define NFP_CAP_CMD_DMA_SG 0x28
+
#define NSP_MAGIC 0xab10
#define NSP_MAJOR 0
#define NSP_MINOR 8
@@ -62,6 +69,16 @@
#define NFP_HWINFO_LOOKUP_SIZE GENMASK(11, 0)
+#define NFP_VERSIONS_SIZE GENMASK(11, 0)
+#define NFP_VERSIONS_CNT_OFF 0
+#define NFP_VERSIONS_BSP_OFF 2
+#define NFP_VERSIONS_CPLD_OFF 6
+#define NFP_VERSIONS_APP_OFF 10
+#define NFP_VERSIONS_BUNDLE_OFF 14
+#define NFP_VERSIONS_UNDI_OFF 18
+#define NFP_VERSIONS_NCSI_OFF 22
+#define NFP_VERSIONS_CFGR_OFF 26
+
enum nfp_nsp_cmd {
SPCODE_NOOP = 0, /* No operation */
SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */
@@ -77,6 +94,17 @@ enum nfp_nsp_cmd {
SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */
SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */
SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */
+ SPCODE_VERSIONS = 21, /* Report FW versions */
+};
+
+struct nfp_nsp_dma_buf {
+ __le32 chunk_cnt;
+ __le32 reserved[3];
+ struct {
+ __le32 size;
+ __le32 reserved;
+ __le64 addr;
+ } descs[];
};
static const struct {
@@ -107,18 +135,18 @@ struct nfp_nsp {
/**
* struct nfp_nsp_command_arg - NFP command argument structure
* @code: NFP SP Command Code
+ * @dma: @buf points to a host buffer, not NSP buffer
* @timeout_sec:Timeout value to wait for completion in seconds
* @option: NFP SP Command Argument
- * @buff_cpp: NFP SP Buffer CPP Address info
- * @buff_addr: NFP SP Buffer Host address
+ * @buf: NFP SP Buffer Address
* @error_cb: Callback for interpreting option if error occurred
*/
struct nfp_nsp_command_arg {
u16 code;
+ bool dma;
unsigned int timeout_sec;
u32 option;
- u32 buff_cpp;
- u64 buff_addr;
+ u64 buf;
void (*error_cb)(struct nfp_nsp *state, u32 ret_val);
};
@@ -332,22 +360,14 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
if (err)
return err;
- if (!FIELD_FIT(NSP_BUFFER_CPP, arg->buff_cpp >> 8) ||
- !FIELD_FIT(NSP_BUFFER_ADDRESS, arg->buff_addr)) {
- nfp_err(cpp, "Host buffer out of reach %08x %016llx\n",
- arg->buff_cpp, arg->buff_addr);
- return -EINVAL;
- }
-
- err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer,
- FIELD_PREP(NSP_BUFFER_CPP, arg->buff_cpp >> 8) |
- FIELD_PREP(NSP_BUFFER_ADDRESS, arg->buff_addr));
+ err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
if (err < 0)
return err;
err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
FIELD_PREP(NSP_COMMAND_OPTION, arg->option) |
FIELD_PREP(NSP_COMMAND_CODE, arg->code) |
+ FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) |
FIELD_PREP(NSP_COMMAND_START, 1));
if (err < 0)
return err;
@@ -399,36 +419,14 @@ static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
}
static int
-nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
+nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
+ struct nfp_nsp_command_buf_arg *arg)
{
struct nfp_cpp *cpp = nsp->cpp;
- unsigned int max_size;
u64 reg, cpp_buf;
- int ret, err;
+ int err, ret;
u32 cpp_id;
- if (nsp->ver.minor < 13) {
- nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
- arg->arg.code, nsp->ver.major, nsp->ver.minor);
- return -EOPNOTSUPP;
- }
-
- err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
- nfp_resource_address(nsp->res) +
- NSP_DFLT_BUFFER_CONFIG,
- &reg);
- if (err < 0)
- return err;
-
- max_size = max(arg->in_size, arg->out_size);
- if (FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M < max_size) {
- nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%llu < %u)\n",
- arg->arg.code,
- FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M,
- max_size);
- return -EINVAL;
- }
-
err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
nfp_resource_address(nsp->res) +
NSP_DFLT_BUFFER,
@@ -447,15 +445,21 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
}
/* Zero out remaining part of the buffer */
if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) {
- memset(arg->out_buf, 0, arg->out_size - arg->in_size);
err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size,
arg->out_buf, arg->out_size - arg->in_size);
if (err < 0)
return err;
}
- arg->arg.buff_cpp = cpp_id;
- arg->arg.buff_addr = cpp_buf;
+ if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) ||
+ !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) {
+ nfp_err(cpp, "Buffer out of reach %08x %016llx\n",
+ cpp_id, cpp_buf);
+ return -EINVAL;
+ }
+
+ arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) |
+ FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf);
ret = __nfp_nsp_command(nsp, &arg->arg);
if (ret < 0)
return ret;
@@ -470,6 +474,210 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
return ret;
}
+static int
+nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp,
+ struct nfp_nsp_command_buf_arg *arg,
+ unsigned int max_size, unsigned int chunk_order,
+ unsigned int dma_order)
+{
+ struct nfp_cpp *cpp = nsp->cpp;
+ struct nfp_nsp_dma_buf *desc;
+ struct {
+ dma_addr_t dma_addr;
+ unsigned long len;
+ void *chunk;
+ } *chunks;
+ size_t chunk_size, dma_size;
+ dma_addr_t dma_desc;
+ struct device *dev;
+ unsigned long off;
+ int i, ret, nseg;
+ size_t desc_sz;
+
+ chunk_size = BIT_ULL(chunk_order);
+ dma_size = BIT_ULL(dma_order);
+ nseg = DIV_ROUND_UP(max_size, chunk_size);
+
+ chunks = kzalloc(array_size(sizeof(*chunks), nseg), GFP_KERNEL);
+ if (!chunks)
+ return -ENOMEM;
+
+ off = 0;
+ ret = -ENOMEM;
+ for (i = 0; i < nseg; i++) {
+ unsigned long coff;
+
+ chunks[i].chunk = kmalloc(chunk_size,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!chunks[i].chunk)
+ goto exit_free_prev;
+
+ chunks[i].len = min_t(u64, chunk_size, max_size - off);
+
+ coff = 0;
+ if (arg->in_size > off) {
+ coff = min_t(u64, arg->in_size - off, chunk_size);
+ memcpy(chunks[i].chunk, arg->in_buf + off, coff);
+ }
+ memset(chunks[i].chunk + coff, 0, chunk_size - coff);
+
+ off += chunks[i].len;
+ }
+
+ dev = nfp_cpp_device(cpp)->parent;
+
+ for (i = 0; i < nseg; i++) {
+ dma_addr_t addr;
+
+ addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len,
+ DMA_BIDIRECTIONAL);
+ chunks[i].dma_addr = addr;
+
+ ret = dma_mapping_error(dev, addr);
+ if (ret)
+ goto exit_unmap_prev;
+
+ if (WARN_ONCE(round_down(addr, dma_size) !=
+ round_down(addr + chunks[i].len - 1, dma_size),
+ "unaligned DMA address: %pad %lu %zd\n",
+ &addr, chunks[i].len, dma_size)) {
+ ret = -EFAULT;
+ i++;
+ goto exit_unmap_prev;
+ }
+ }
+
+ desc_sz = struct_size(desc, descs, nseg);
+ desc = kmalloc(desc_sz, GFP_KERNEL);
+ if (!desc) {
+ ret = -ENOMEM;
+ goto exit_unmap_all;
+ }
+
+ desc->chunk_cnt = cpu_to_le32(nseg);
+ for (i = 0; i < nseg; i++) {
+ desc->descs[i].size = cpu_to_le32(chunks[i].len);
+ desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr);
+ }
+
+ dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE);
+ ret = dma_mapping_error(dev, dma_desc);
+ if (ret)
+ goto exit_free_desc;
+
+ arg->arg.dma = true;
+ arg->arg.buf = dma_desc;
+ ret = __nfp_nsp_command(nsp, &arg->arg);
+ if (ret < 0)
+ goto exit_unmap_desc;
+
+ i = 0;
+ off = 0;
+ while (off < arg->out_size) {
+ unsigned int len;
+
+ len = min_t(u64, chunks[i].len, arg->out_size - off);
+ memcpy(arg->out_buf + off, chunks[i].chunk, len);
+ off += len;
+ i++;
+ }
+
+exit_unmap_desc:
+ dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE);
+exit_free_desc:
+ kfree(desc);
+exit_unmap_all:
+ i = nseg;
+exit_unmap_prev:
+ while (--i >= 0)
+ dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len,
+ DMA_BIDIRECTIONAL);
+ i = nseg;
+exit_free_prev:
+ while (--i >= 0)
+ kfree(chunks[i].chunk);
+ kfree(chunks);
+ if (ret < 0)
+ nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n",
+ arg->arg.code, ret, max_size, chunk_order);
+ return ret;
+}
+
+static int
+nfp_nsp_command_buf_dma(struct nfp_nsp *nsp,
+ struct nfp_nsp_command_buf_arg *arg,
+ unsigned int max_size, unsigned int dma_order)
+{
+ unsigned int chunk_order, buf_order;
+ struct nfp_cpp *cpp = nsp->cpp;
+ bool sg_ok;
+ u64 reg;
+ int err;
+
+ buf_order = order_base_2(roundup_pow_of_two(max_size));
+
+ err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
+ nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG,
+ &reg);
+ if (err < 0)
+ return err;
+ sg_ok = reg & BIT_ULL(arg->arg.code - 1);
+
+ if (!sg_ok) {
+ if (buf_order > dma_order) {
+ nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n",
+ arg->arg.code);
+ return -ENOMEM;
+ }
+ chunk_order = buf_order;
+ } else {
+ chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT);
+ }
+
+ return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order,
+ dma_order);
+}
+
+static int
+nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
+{
+ unsigned int dma_order, def_size, max_size;
+ struct nfp_cpp *cpp = nsp->cpp;
+ u64 reg;
+ int err;
+
+ if (nsp->ver.minor < 13) {
+ nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
+ arg->arg.code, nsp->ver.major, nsp->ver.minor);
+ return -EOPNOTSUPP;
+ }
+
+ err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
+ nfp_resource_address(nsp->res) +
+ NSP_DFLT_BUFFER_CONFIG,
+ &reg);
+ if (err < 0)
+ return err;
+
+ /* Zero out undefined part of the out buffer */
+ if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size)
+ memset(arg->out_buf, 0, arg->out_size - arg->in_size);
+
+ max_size = max(arg->in_size, arg->out_size);
+ def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
+ FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
+ dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg);
+ if (def_size >= max_size) {
+ return nfp_nsp_command_buf_def(nsp, arg);
+ } else if (!dma_order) {
+ nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
+ arg->arg.code, def_size, max_size);
+ return -EINVAL;
+ }
+
+ return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order);
+}
+
int nfp_nsp_wait(struct nfp_nsp *state)
{
const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ;
@@ -591,10 +799,7 @@ int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw)
{
.code = SPCODE_NSP_WRITE_FLASH,
.option = fw->size,
- /* The flash time is specified to take a maximum of 70s
- * so we add an additional factor to this spec time.
- */
- .timeout_sec = 2.5 * 70,
+ .timeout_sec = 900,
},
.in_buf = fw->data,
.in_size = fw->size,
@@ -711,3 +916,52 @@ int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
return 0;
}
+
+int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size)
+{
+ struct nfp_nsp_command_buf_arg versions = {
+ {
+ .code = SPCODE_VERSIONS,
+ .option = min_t(u32, size, NFP_VERSIONS_SIZE),
+ },
+ .out_buf = buf,
+ .out_size = min_t(u32, size, NFP_VERSIONS_SIZE),
+ };
+
+ return nfp_nsp_command_buf(state, &versions);
+}
+
+const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash,
+ const u8 *buf, unsigned int size)
+{
+ static const u32 id2off[] = {
+ [NFP_VERSIONS_BSP] = NFP_VERSIONS_BSP_OFF,
+ [NFP_VERSIONS_CPLD] = NFP_VERSIONS_CPLD_OFF,
+ [NFP_VERSIONS_APP] = NFP_VERSIONS_APP_OFF,
+ [NFP_VERSIONS_BUNDLE] = NFP_VERSIONS_BUNDLE_OFF,
+ [NFP_VERSIONS_UNDI] = NFP_VERSIONS_UNDI_OFF,
+ [NFP_VERSIONS_NCSI] = NFP_VERSIONS_NCSI_OFF,
+ [NFP_VERSIONS_CFGR] = NFP_VERSIONS_CFGR_OFF,
+ };
+ unsigned int field, buf_field_cnt, buf_off;
+
+ if (id >= ARRAY_SIZE(id2off) || !id2off[id])
+ return ERR_PTR(-EINVAL);
+
+ field = id * 2 + flash;
+
+ buf_field_cnt = get_unaligned_le16(buf);
+ if (buf_field_cnt <= field)
+ return ERR_PTR(-ENOENT);
+
+ buf_off = get_unaligned_le16(buf + id2off[id] + flash * 2);
+ if (!buf_off)
+ return ERR_PTR(-ENOENT);
+
+ if (buf_off >= size)
+ return ERR_PTR(-EINVAL);
+ if (strnlen(&buf[buf_off], size - buf_off) == size - buf_off)
+ return ERR_PTR(-EINVAL);
+
+ return (const char *)&buf[buf_off];
+}
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
index ff33ac54097a..bd9c358c646f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
@@ -38,12 +38,18 @@ static inline bool nfp_nsp_has_hwinfo_lookup(struct nfp_nsp *state)
return nfp_nsp_get_abi_ver_minor(state) > 24;
}
+static inline bool nfp_nsp_has_versions(struct nfp_nsp *state)
+{
+ return nfp_nsp_get_abi_ver_minor(state) > 27;
+}
+
enum nfp_eth_interface {
NFP_INTERFACE_NONE = 0,
NFP_INTERFACE_SFP = 1,
NFP_INTERFACE_SFPP = 10,
NFP_INTERFACE_SFP28 = 28,
NFP_INTERFACE_QSFP = 40,
+ NFP_INTERFACE_RJ45 = 45,
NFP_INTERFACE_CXP = 100,
NFP_INTERFACE_QSFP28 = 112,
};
@@ -208,4 +214,19 @@ enum nfp_nsp_sensor_id {
int nfp_hwmon_read_sensor(struct nfp_cpp *cpp, enum nfp_nsp_sensor_id id,
long *val);
+#define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */
+
+enum nfp_nsp_versions {
+ NFP_VERSIONS_BSP,
+ NFP_VERSIONS_CPLD,
+ NFP_VERSIONS_APP,
+ NFP_VERSIONS_BUNDLE,
+ NFP_VERSIONS_UNDI,
+ NFP_VERSIONS_NCSI,
+ NFP_VERSIONS_CFGR,
+};
+
+int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size);
+const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash,
+ const u8 *buf, unsigned int size);
#endif
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
index 802c9224bb32..311a5be25acb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
@@ -206,6 +206,9 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
if (entry->interface == NFP_INTERFACE_NONE) {
entry->port_type = PORT_NONE;
return;
+ } else if (entry->interface == NFP_INTERFACE_RJ45) {
+ entry->port_type = PORT_TP;
+ return;
}
if (entry->media == NFP_MEDIA_FIBRE)
@@ -269,8 +272,7 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
goto err;
}
- table = kzalloc(sizeof(*table) +
- sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
+ table = kzalloc(struct_size(table, ports, cnt), GFP_KERNEL);
if (!table)
goto err;
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index 0611f2335b4a..96f7a9818294 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -105,6 +105,12 @@
#define NIXGE_MAX_JUMBO_FRAME_SIZE \
(NIXGE_JUMBO_MTU + NIXGE_HDR_SIZE + NIXGE_TRL_SIZE)
+enum nixge_version {
+ NIXGE_V2,
+ NIXGE_V3,
+ NIXGE_VERSION_COUNT
+};
+
struct nixge_hw_dma_bd {
u32 next_lo;
u32 next_hi;
@@ -287,9 +293,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
priv->rx_bd_ci = 0;
/* Allocate the Tx and Rx buffer descriptors. */
- priv->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*priv->tx_bd_v) * TX_BD_NUM,
- &priv->tx_bd_p, GFP_KERNEL);
+ priv->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*priv->tx_bd_v) * TX_BD_NUM,
+ &priv->tx_bd_p, GFP_KERNEL);
if (!priv->tx_bd_v)
goto out;
@@ -299,9 +305,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
if (!priv->tx_skb)
goto out;
- priv->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*priv->rx_bd_v) * RX_BD_NUM,
- &priv->rx_bd_p, GFP_KERNEL);
+ priv->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*priv->rx_bd_v) * RX_BD_NUM,
+ &priv->rx_bd_p, GFP_KERNEL);
if (!priv->rx_bd_v)
goto out;
@@ -1225,11 +1231,60 @@ static void *nixge_get_nvmem_address(struct device *dev)
return mac;
}
+/* Match table for of_platform binding */
+static const struct of_device_id nixge_dt_ids[] = {
+ { .compatible = "ni,xge-enet-2.00", .data = (void *)NIXGE_V2 },
+ { .compatible = "ni,xge-enet-3.00", .data = (void *)NIXGE_V3 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nixge_dt_ids);
+
+static int nixge_of_get_resources(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id;
+ enum nixge_version version;
+ struct resource *ctrlres;
+ struct resource *dmares;
+ struct net_device *ndev;
+ struct nixge_priv *priv;
+
+ ndev = platform_get_drvdata(pdev);
+ priv = netdev_priv(ndev);
+ of_id = of_match_node(nixge_dt_ids, pdev->dev.of_node);
+ if (!of_id)
+ return -ENODEV;
+
+ version = (enum nixge_version)of_id->data;
+ if (version <= NIXGE_V2)
+ dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ else
+ dmares = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dma");
+
+ priv->dma_regs = devm_ioremap_resource(&pdev->dev, dmares);
+ if (IS_ERR(priv->dma_regs)) {
+ netdev_err(ndev, "failed to map dma regs\n");
+ return PTR_ERR(priv->dma_regs);
+ }
+ if (version <= NIXGE_V2) {
+ priv->ctrl_regs = priv->dma_regs + NIXGE_REG_CTRL_OFFSET;
+ } else {
+ ctrlres = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "ctrl");
+ priv->ctrl_regs = devm_ioremap_resource(&pdev->dev, ctrlres);
+ }
+ if (IS_ERR(priv->ctrl_regs)) {
+ netdev_err(ndev, "failed to map ctrl regs\n");
+ return PTR_ERR(priv->ctrl_regs);
+ }
+ return 0;
+}
+
static int nixge_probe(struct platform_device *pdev)
{
+ struct device_node *mn, *phy_node;
struct nixge_priv *priv;
struct net_device *ndev;
- struct resource *dmares;
const u8 *mac_addr;
int err;
@@ -1261,14 +1316,9 @@ static int nixge_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
netif_napi_add(ndev, &priv->napi, nixge_poll, NAPI_POLL_WEIGHT);
-
- dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->dma_regs = devm_ioremap_resource(&pdev->dev, dmares);
- if (IS_ERR(priv->dma_regs)) {
- netdev_err(ndev, "failed to map dma regs\n");
- return PTR_ERR(priv->dma_regs);
- }
- priv->ctrl_regs = priv->dma_regs + NIXGE_REG_CTRL_OFFSET;
+ err = nixge_of_get_resources(pdev);
+ if (err)
+ return err;
__nixge_hw_set_mac_address(ndev);
priv->tx_irq = platform_get_irq_byname(pdev, "tx");
@@ -1286,10 +1336,14 @@ static int nixge_probe(struct platform_device *pdev)
priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
priv->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
- err = nixge_mdio_setup(priv, pdev->dev.of_node);
- if (err) {
- netdev_err(ndev, "error registering mdio bus");
- goto free_netdev;
+ mn = of_get_child_by_name(pdev->dev.of_node, "mdio");
+ if (mn) {
+ err = nixge_mdio_setup(priv, mn);
+ of_node_put(mn);
+ if (err) {
+ netdev_err(ndev, "error registering mdio bus");
+ goto free_netdev;
+ }
}
priv->phy_mode = of_get_phy_mode(pdev->dev.of_node);
@@ -1299,23 +1353,33 @@ static int nixge_probe(struct platform_device *pdev)
goto unregister_mdio;
}
- priv->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
- if (!priv->phy_node) {
- netdev_err(ndev, "not find \"phy-handle\" property\n");
- err = -EINVAL;
- goto unregister_mdio;
+ phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+ if (!phy_node && of_phy_is_fixed_link(pdev->dev.of_node)) {
+ err = of_phy_register_fixed_link(pdev->dev.of_node);
+ if (err < 0) {
+ netdev_err(ndev, "broken fixed-link specification\n");
+ goto unregister_mdio;
+ }
+ phy_node = of_node_get(pdev->dev.of_node);
}
+ priv->phy_node = phy_node;
err = register_netdev(priv->ndev);
if (err) {
netdev_err(ndev, "register_netdev() error (%i)\n", err);
- goto unregister_mdio;
+ goto free_phy;
}
return 0;
+free_phy:
+ if (of_phy_is_fixed_link(pdev->dev.of_node))
+ of_phy_deregister_fixed_link(pdev->dev.of_node);
+ of_node_put(phy_node);
+
unregister_mdio:
- mdiobus_unregister(priv->mii_bus);
+ if (priv->mii_bus)
+ mdiobus_unregister(priv->mii_bus);
free_netdev:
free_netdev(ndev);
@@ -1330,20 +1394,18 @@ static int nixge_remove(struct platform_device *pdev)
unregister_netdev(ndev);
- mdiobus_unregister(priv->mii_bus);
+ if (of_phy_is_fixed_link(pdev->dev.of_node))
+ of_phy_deregister_fixed_link(pdev->dev.of_node);
+ of_node_put(priv->phy_node);
+
+ if (priv->mii_bus)
+ mdiobus_unregister(priv->mii_bus);
free_netdev(ndev);
return 0;
}
-/* Match table for of_platform binding */
-static const struct of_device_id nixge_dt_ids[] = {
- { .compatible = "ni,xge-enet-2.00", },
- {},
-};
-MODULE_DEVICE_TABLE(of, nixge_dt_ids);
-
static struct platform_driver nixge_driver = {
.probe = nixge_probe,
.remove = nixge_remove,
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index c662c6f5bee3..67bf02b0763a 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -630,7 +630,7 @@ static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
ether->skb = skb;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
return 0;
}
return -EAGAIN;
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 43c0c10dfeb7..552d930e3940 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1440,8 +1440,8 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY;
rx_ring->rx_buff_pool =
- dma_zalloc_coherent(&pdev->dev, size,
- &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, size,
+ &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
if (!rx_ring->rx_buff_pool)
return -ENOMEM;
@@ -1755,8 +1755,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
- tx_ring->desc = dma_zalloc_coherent(&pdev->dev, tx_ring->size,
- &tx_ring->dma, GFP_KERNEL);
+ tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+ &tx_ring->dma, GFP_KERNEL);
if (!tx_ring->desc) {
vfree(tx_ring->buffer_info);
return -ENOMEM;
@@ -1798,8 +1798,8 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
return -ENOMEM;
rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
- rx_ring->desc = dma_zalloc_coherent(&pdev->dev, rx_ring->size,
- &rx_ring->dma, GFP_KERNEL);
+ rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+ &rx_ring->dma, GFP_KERNEL);
if (!rx_ring->desc) {
vfree(rx_ring->buffer_info);
return -ENOMEM;
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index c9529c29a0a7..eee883a2aa8d 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -1337,7 +1337,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance)
leXX_to_cpu(hmp->tx_ring[entry].addr),
skb->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
hmp->tx_skbuff[entry] = NULL;
}
hmp->tx_ring[entry].status_n_length = 0;
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 54224d1822e3..6f8d6584f809 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -925,7 +925,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance)
/* Free the original skb. */
pci_unmap_single(yp->pci_dev, le32_to_cpu(yp->tx_ring[entry].addr),
skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
yp->tx_skbuff[entry] = NULL;
}
if (yp->tx_full &&
@@ -983,7 +983,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance)
pci_unmap_single(yp->pci_dev,
yp->tx_ring[entry<<1].addr, skb->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
yp->tx_skbuff[entry] = 0;
/* Mark status as empty. */
yp->tx_status[entry].tx_errs = 0;
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 8a31a02c9f47..d21041554507 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -401,9 +401,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE))
goto out_ring_desc;
- ring->buffers = dma_zalloc_coherent(&mac->dma_pdev->dev,
- RX_RING_SIZE * sizeof(u64),
- &ring->buf_dma, GFP_KERNEL);
+ ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
+ RX_RING_SIZE * sizeof(u64),
+ &ring->buf_dma, GFP_KERNEL);
if (!ring->buffers)
goto out_ring_desc;
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 24a90163775e..43a57ec296fd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -53,7 +53,7 @@
extern const struct qed_common_ops qed_common_ops_pass;
#define QED_MAJOR_VERSION 8
-#define QED_MINOR_VERSION 33
+#define QED_MINOR_VERSION 37
#define QED_REVISION_VERSION 0
#define QED_ENGINEERING_VERSION 20
@@ -554,7 +554,6 @@ struct qed_hwfn {
u8 dp_level;
char name[NAME_SIZE];
- bool first_on_engine;
bool hw_init_done;
u8 num_funcs_on_engine;
@@ -754,6 +753,7 @@ struct qed_dev {
#define CHIP_BOND_ID_SHIFT 0
u8 num_engines;
+ u8 num_ports;
u8 num_ports_in_engine;
u8 num_funcs_in_port;
@@ -805,6 +805,9 @@ struct qed_dev {
u32 mcp_nvm_resp;
+ /* Recovery */
+ bool recov_in_prog;
+
/* Linux specific here */
struct qede_dev *edev;
struct pci_dev *pdev;
@@ -890,7 +893,6 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev,
void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
int qed_device_num_engines(struct qed_dev *cdev);
-int qed_device_get_port_id(struct qed_dev *cdev);
void qed_set_fw_mac_addr(__le16 *fw_msb,
__le16 *fw_mid, __le16 *fw_lsb, u8 *mac);
@@ -937,6 +939,10 @@ bool qed_edpm_enabled(struct qed_hwfn *p_hwfn);
writel((u32)val, (void __iomem *)((u8 __iomem *)\
(cdev->doorbells) + (db_addr)))
+#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \
+ qed_device_num_ports((_p_hwfn)->cdev))
+int qed_device_num_ports(struct qed_dev *cdev);
+
/* Prototypes */
int qed_fill_dev_info(struct qed_dev *cdev,
struct qed_dev_info *dev_info);
@@ -944,6 +950,7 @@ void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt);
u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
u32 input_len, u8 *input_buf,
u32 max_size, u8 *unzip_buf);
+void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn);
void qed_get_protocol_stats(struct qed_dev *cdev,
enum qed_mcp_protocol_type type,
union qed_mcp_protocol_stats *stats);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
index dc1c1b616084..e61d1d905415 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
@@ -936,9 +936,9 @@ static int qed_cxt_src_t2_alloc(struct qed_hwfn *p_hwfn)
u32 size = min_t(u32, total_size, psz);
void **p_virt = &p_mngr->t2[i].p_virt;
- *p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
- size, &p_mngr->t2[i].p_phys,
- GFP_KERNEL);
+ *p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+ &p_mngr->t2[i].p_phys,
+ GFP_KERNEL);
if (!p_mngr->t2[i].p_virt) {
rc = -ENOMEM;
goto t2_fail;
@@ -1054,8 +1054,8 @@ static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
u32 size;
size = min_t(u32, sz_left, p_blk->real_size_in_page);
- p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, size,
- &p_phys, GFP_KERNEL);
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+ &p_phys, GFP_KERNEL);
if (!p_virt)
return -ENOMEM;
@@ -2129,17 +2129,18 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn, u32 rdma_tasks)
rdma_tasks);
/* no need for break since RoCE coexist with Ethernet */
}
+ /* fall through */
case QED_PCI_ETH:
{
struct qed_eth_pf_params *p_params =
&p_hwfn->pf_params.eth_pf_params;
- if (!p_params->num_vf_cons)
- p_params->num_vf_cons =
- ETH_PF_PARAMS_VF_CONS_DEFAULT;
- qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
- p_params->num_cons,
- p_params->num_vf_cons);
+ if (!p_params->num_vf_cons)
+ p_params->num_vf_cons =
+ ETH_PF_PARAMS_VF_CONS_DEFAULT;
+ qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
+ p_params->num_cons,
+ p_params->num_vf_cons);
p_hwfn->p_cxt_mngr->arfs_count = p_params->num_arfs_filters;
break;
}
@@ -2306,9 +2307,9 @@ qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
goto out0;
}
- p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
- p_blk->real_size_in_page, &p_phys,
- GFP_KERNEL);
+ p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+ p_blk->real_size_in_page, &p_phys,
+ GFP_KERNEL);
if (!p_virt) {
rc = -ENOMEM;
goto out1;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 8f6551421945..9df8c4b3b54e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -795,19 +795,19 @@ static void qed_init_qm_pq(struct qed_hwfn *p_hwfn,
/* get pq index according to PQ_FLAGS */
static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
- u32 pq_flags)
+ unsigned long pq_flags)
{
struct qed_qm_info *qm_info = &p_hwfn->qm_info;
/* Can't have multiple flags set here */
- if (bitmap_weight((unsigned long *)&pq_flags,
+ if (bitmap_weight(&pq_flags,
sizeof(pq_flags) * BITS_PER_BYTE) > 1) {
- DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags);
+ DP_ERR(p_hwfn, "requested multiple pq flags 0x%lx\n", pq_flags);
goto err;
}
if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) {
- DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);
+ DP_ERR(p_hwfn, "pq flag 0x%lx is not set\n", pq_flags);
goto err;
}
@@ -1959,11 +1959,6 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
(p_hwfn->hw_info.personality == QED_PCI_FCOE) ? 1 : 0);
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0);
- /* Cleanup chip from previous driver if such remains exist */
- rc = qed_final_cleanup(p_hwfn, p_ptt, rel_pf_id, false);
- if (rc)
- return rc;
-
/* Sanity check before the PF init sequence that uses DMAE */
rc = qed_dmae_sanity(p_hwfn, p_ptt, "pf_phase");
if (rc)
@@ -2007,17 +2002,15 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
return rc;
}
-static int qed_change_pci_hwfn(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt,
- u8 enable)
+int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, bool b_enable)
{
- u32 delay_idx = 0, val, set_val = enable ? 1 : 0;
+ u32 delay_idx = 0, val, set_val = b_enable ? 1 : 0;
- /* Change PF in PXP */
- qed_wr(p_hwfn, p_ptt,
- PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val);
+ /* Configure the PF's internal FID_enable for master transactions */
+ qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val);
- /* wait until value is set - try for 1 second every 50us */
+ /* Wait until value is set - try for 1 second every 50us */
for (delay_idx = 0; delay_idx < 20000; delay_idx++) {
val = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
@@ -2071,13 +2064,19 @@ static int qed_vf_start(struct qed_hwfn *p_hwfn,
return 0;
}
+static void qed_pglueb_clear_err(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR,
+ BIT(p_hwfn->abs_pf_id));
+}
+
int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
{
struct qed_load_req_params load_req_params;
u32 load_code, resp, param, drv_mb_param;
bool b_default_mtu = true;
struct qed_hwfn *p_hwfn;
- int rc = 0, mfw_rc, i;
+ int rc = 0, i;
u16 ether_type;
if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
@@ -2092,7 +2091,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
}
for_each_hwfn(cdev, i) {
- struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+ p_hwfn = &cdev->hwfns[i];
/* If management didn't provide a default, set one of our own */
if (!p_hwfn->hw_info.mtu) {
@@ -2105,9 +2104,6 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
continue;
}
- /* Enable DMAE in PXP */
- rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true);
-
rc = qed_calc_hw_mode(p_hwfn);
if (rc)
return rc;
@@ -2144,12 +2140,43 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
"Load request was sent. Load code: 0x%x\n",
load_code);
+ /* Only relevant for recovery:
+ * Clear the indication after LOAD_REQ is responded by the MFW.
+ */
+ cdev->recov_in_prog = false;
+
qed_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt);
qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt);
- p_hwfn->first_on_engine = (load_code ==
- FW_MSG_CODE_DRV_LOAD_ENGINE);
+ /* Clean up chip from previous driver if such remains exist.
+ * This is not needed when the PF is the first one on the
+ * engine, since afterwards we are going to init the FW.
+ */
+ if (load_code != FW_MSG_CODE_DRV_LOAD_ENGINE) {
+ rc = qed_final_cleanup(p_hwfn, p_hwfn->p_main_ptt,
+ p_hwfn->rel_pf_id, false);
+ if (rc) {
+ DP_NOTICE(p_hwfn, "Final cleanup failed\n");
+ goto load_err;
+ }
+ }
+
+ /* Log and clear previous pglue_b errors if such exist */
+ qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt);
+
+ /* Enable the PF's internal FID_enable in the PXP */
+ rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt,
+ true);
+ if (rc)
+ goto load_err;
+
+ /* Clear the pglue_b was_error indication.
+ * In E4 it must be done after the BME and the internal
+ * FID_enable for the PF are set, since VDMs may cause the
+ * indication to be set again.
+ */
+ qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt);
switch (load_code) {
case FW_MSG_CODE_DRV_LOAD_ENGINE:
@@ -2180,39 +2207,29 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
break;
}
- if (rc)
+ if (rc) {
DP_NOTICE(p_hwfn,
"init phase failed for loadcode 0x%x (rc %d)\n",
- load_code, rc);
+ load_code, rc);
+ goto load_err;
+ }
- /* ACK mfw regardless of success or failure of initialization */
- mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
- DRV_MSG_CODE_LOAD_DONE,
- 0, &load_code, &param);
+ rc = qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt);
if (rc)
return rc;
- if (mfw_rc) {
- DP_NOTICE(p_hwfn, "Failed sending LOAD_DONE command\n");
- return mfw_rc;
- }
-
- /* Check if there is a DID mismatch between nvm-cfg/efuse */
- if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR)
- DP_NOTICE(p_hwfn,
- "warning: device configuration is not supported on this board type. The device may not function as expected.\n");
/* send DCBX attention request command */
DP_VERBOSE(p_hwfn,
QED_MSG_DCB,
"sending phony dcbx set command to trigger DCBx attention handling\n");
- mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
- DRV_MSG_CODE_SET_DCBX,
- 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT,
- &load_code, &param);
- if (mfw_rc) {
+ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
+ DRV_MSG_CODE_SET_DCBX,
+ 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT,
+ &resp, &param);
+ if (rc) {
DP_NOTICE(p_hwfn,
"Failed to send DCBX attention request\n");
- return mfw_rc;
+ return rc;
}
p_hwfn->hw_init_done = true;
@@ -2261,6 +2278,12 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
}
return 0;
+
+load_err:
+ /* The MFW load lock should be released also when initialization fails.
+ */
+ qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt);
+ return rc;
}
#define QED_HW_STOP_RETRY_LIMIT (10)
@@ -2273,6 +2296,9 @@ static void qed_hw_timers_stop(struct qed_dev *cdev,
qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0);
qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0);
+ if (cdev->recov_in_prog)
+ return;
+
for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) {
if ((!qed_rd(p_hwfn, p_ptt,
TM_REG_PF_SCAN_ACTIVE_CONN)) &&
@@ -2335,12 +2361,14 @@ int qed_hw_stop(struct qed_dev *cdev)
p_hwfn->hw_init_done = false;
/* Send unload command to MCP */
- rc = qed_mcp_unload_req(p_hwfn, p_ptt);
- if (rc) {
- DP_NOTICE(p_hwfn,
- "Failed sending a UNLOAD_REQ command. rc = %d.\n",
- rc);
- rc2 = -EINVAL;
+ if (!cdev->recov_in_prog) {
+ rc = qed_mcp_unload_req(p_hwfn, p_ptt);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "Failed sending a UNLOAD_REQ command. rc = %d.\n",
+ rc);
+ rc2 = -EINVAL;
+ }
}
qed_slowpath_irq_sync(p_hwfn);
@@ -2382,27 +2410,31 @@ int qed_hw_stop(struct qed_dev *cdev)
qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0);
qed_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0);
- qed_mcp_unload_done(p_hwfn, p_ptt);
- if (rc) {
- DP_NOTICE(p_hwfn,
- "Failed sending a UNLOAD_DONE command. rc = %d.\n",
- rc);
- rc2 = -EINVAL;
+ if (!cdev->recov_in_prog) {
+ rc = qed_mcp_unload_done(p_hwfn, p_ptt);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "Failed sending a UNLOAD_DONE command. rc = %d.\n",
+ rc);
+ rc2 = -EINVAL;
+ }
}
}
- if (IS_PF(cdev)) {
+ if (IS_PF(cdev) && !cdev->recov_in_prog) {
p_hwfn = QED_LEADING_HWFN(cdev);
p_ptt = QED_LEADING_HWFN(cdev)->p_main_ptt;
- /* Disable DMAE in PXP - in CMT, this should only be done for
- * first hw-function, and only after all transactions have
- * stopped for all active hw-functions.
+ /* Clear the PF's internal FID_enable in the PXP.
+ * In CMT this should only be done for first hw-function, and
+ * only after all transactions have stopped for all active
+ * hw-functions.
*/
- rc = qed_change_pci_hwfn(p_hwfn, p_ptt, false);
+ rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false);
if (rc) {
DP_NOTICE(p_hwfn,
- "qed_change_pci_hwfn failed. rc = %d.\n", rc);
+ "qed_pglueb_set_pfid_enable() failed. rc = %d.\n",
+ rc);
rc2 = -EINVAL;
}
}
@@ -2502,9 +2534,8 @@ static void qed_hw_hwfn_prepare(struct qed_hwfn *p_hwfn)
PGLUE_B_REG_PGL_ADDR_94_F0_BB, 0);
}
- /* Clean Previous errors if such exist */
- qed_wr(p_hwfn, p_hwfn->p_main_ptt,
- PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, 1 << p_hwfn->abs_pf_id);
+ /* Clean previous pglue_b errors if such exist */
+ qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt);
/* enable internal target-read */
qed_wr(p_hwfn, p_hwfn->p_main_ptt,
@@ -3238,55 +3269,43 @@ static void qed_get_num_funcs(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
p_hwfn->enabled_func_idx, p_hwfn->num_funcs_on_engine);
}
-static void qed_hw_info_port_num_bb(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt)
-{
- u32 port_mode;
-
- port_mode = qed_rd(p_hwfn, p_ptt, CNIG_REG_NW_PORT_MODE_BB);
-
- if (port_mode < 3) {
- p_hwfn->cdev->num_ports_in_engine = 1;
- } else if (port_mode <= 5) {
- p_hwfn->cdev->num_ports_in_engine = 2;
- } else {
- DP_NOTICE(p_hwfn, "PORT MODE: %d not supported\n",
- p_hwfn->cdev->num_ports_in_engine);
-
- /* Default num_ports_in_engine to something */
- p_hwfn->cdev->num_ports_in_engine = 1;
- }
-}
-
-static void qed_hw_info_port_num_ah(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt)
+static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
- u32 port;
- int i;
-
- p_hwfn->cdev->num_ports_in_engine = 0;
+ u32 addr, global_offsize, global_addr, port_mode;
+ struct qed_dev *cdev = p_hwfn->cdev;
- for (i = 0; i < MAX_NUM_PORTS_K2; i++) {
- port = qed_rd(p_hwfn, p_ptt,
- CNIG_REG_NIG_PORT0_CONF_K2 + (i * 4));
- if (port & 1)
- p_hwfn->cdev->num_ports_in_engine++;
+ /* In CMT there is always only one port */
+ if (cdev->num_hwfns > 1) {
+ cdev->num_ports_in_engine = 1;
+ cdev->num_ports = 1;
+ return;
}
- if (!p_hwfn->cdev->num_ports_in_engine) {
- DP_NOTICE(p_hwfn, "All NIG ports are inactive\n");
-
- /* Default num_ports_in_engine to something */
- p_hwfn->cdev->num_ports_in_engine = 1;
+ /* Determine the number of ports per engine */
+ port_mode = qed_rd(p_hwfn, p_ptt, MISC_REG_PORT_MODE);
+ switch (port_mode) {
+ case 0x0:
+ cdev->num_ports_in_engine = 1;
+ break;
+ case 0x1:
+ cdev->num_ports_in_engine = 2;
+ break;
+ case 0x2:
+ cdev->num_ports_in_engine = 4;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Unknown port mode 0x%08x\n", port_mode);
+ cdev->num_ports_in_engine = 1; /* Default to something */
+ break;
}
-}
-static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
-{
- if (QED_IS_BB(p_hwfn->cdev))
- qed_hw_info_port_num_bb(p_hwfn, p_ptt);
- else
- qed_hw_info_port_num_ah(p_hwfn, p_ptt);
+ /* Get the total number of ports of the device */
+ addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+ PUBLIC_GLOBAL);
+ global_offsize = qed_rd(p_hwfn, p_ptt, addr);
+ global_addr = SECTION_ADDR(global_offsize, 0);
+ addr = global_addr + offsetof(struct public_global, max_ports);
+ cdev->num_ports = (u8)qed_rd(p_hwfn, p_ptt, addr);
}
static void qed_get_eee_caps(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
@@ -3324,7 +3343,8 @@ qed_get_hw_info(struct qed_hwfn *p_hwfn,
return rc;
}
- qed_hw_info_port_num(p_hwfn, p_ptt);
+ if (IS_LEAD_HWFN(p_hwfn))
+ qed_hw_info_port_num(p_hwfn, p_ptt);
qed_mcp_get_capabilities(p_hwfn, p_ptt);
@@ -3440,6 +3460,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
void __iomem *p_doorbells,
enum qed_pci_personality personality)
{
+ struct qed_dev *cdev = p_hwfn->cdev;
int rc = 0;
/* Split PCI bars evenly between hwfns */
@@ -3492,7 +3513,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
/* Sending a mailbox to the MFW should be done after qed_get_hw_info()
* is called as it sets the ports number in an engine.
*/
- if (IS_LEAD_HWFN(p_hwfn)) {
+ if (IS_LEAD_HWFN(p_hwfn) && !cdev->recov_in_prog) {
rc = qed_mcp_initiate_pf_flr(p_hwfn, p_hwfn->p_main_ptt);
if (rc)
DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n");
@@ -4728,23 +4749,9 @@ void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
sizeof(*p_hwfn->qm_info.wfq_data) * p_hwfn->qm_info.num_vports);
}
-int qed_device_num_engines(struct qed_dev *cdev)
-{
- return QED_IS_BB(cdev) ? 2 : 1;
-}
-
-static int qed_device_num_ports(struct qed_dev *cdev)
-{
- /* in CMT always only one port */
- if (cdev->num_hwfns > 1)
- return 1;
-
- return cdev->num_ports_in_engine * qed_device_num_engines(cdev);
-}
-
-int qed_device_get_port_id(struct qed_dev *cdev)
+int qed_device_num_ports(struct qed_dev *cdev)
{
- return (QED_LEADING_HWFN(cdev)->abs_pf_id) % qed_device_num_ports(cdev);
+ return cdev->num_ports;
}
void qed_set_fw_mac_addr(__le16 *fw_msb,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
index acccd85170aa..e4b4e3b78e8a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
@@ -473,6 +473,18 @@ int
qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle);
/**
+ * @brief qed_pglueb_set_pfid_enable - Enable or disable PCI BUS MASTER
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param b_enable - true/false
+ *
+ * @return int
+ */
+int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, bool b_enable);
+
+/**
* @brief db_recovery_add - add doorbell information to the doorbell
* recovery mechanism.
*
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index b13cfb449d8f..37edaa847512 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12796,6 +12796,7 @@ struct public_drv_mb {
#define FW_MB_PARAM_GET_PF_RDMA_BOTH 0x3
/* get MFW feature support response */
+#define FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ 0x00000001
#define FW_MB_PARAM_FEATURE_SUPPORT_EEE 0x00000002
#define FW_MB_PARAM_FEATURE_SUPPORT_VLINK 0x00010000
@@ -12827,7 +12828,7 @@ enum MFW_DRV_MSG_TYPE {
MFW_DRV_MSG_LLDP_DATA_UPDATED,
MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED,
MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED,
- MFW_DRV_MSG_RESERVED4,
+ MFW_DRV_MSG_ERROR_RECOVERY,
MFW_DRV_MSG_BW_UPDATE,
MFW_DRV_MSG_S_TAG_UPDATE,
MFW_DRV_MSG_GET_LAN_STATS,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c
index 70504dcf4087..72ec1c6bdf70 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hw.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c
@@ -703,6 +703,17 @@ static int qed_dmae_execute_command(struct qed_hwfn *p_hwfn,
int qed_status = 0;
u32 offset = 0;
+ if (p_hwfn->cdev->recov_in_prog) {
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_HW,
+ "Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n",
+ src_addr, src_type, dst_addr, dst_type,
+ size_in_dwords);
+
+ /* Let the flow complete w/o any error handling */
+ return 0;
+ }
+
qed_dmae_opcode(p_hwfn,
(src_type == QED_DMAE_ADDRESS_GRC),
(dst_type == QED_DMAE_ADDRESS_GRC),
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c
index 92340919d852..e23980e301b6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -255,112 +255,114 @@ out:
#define PGLUE_ATTENTION_ICPL_VALID (1 << 23)
#define PGLUE_ATTENTION_ZLR_VALID (1 << 25)
#define PGLUE_ATTENTION_ILT_VALID (1 << 23)
-static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn)
+
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
{
u32 tmp;
- tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_TX_ERR_WR_DETAILS2);
+ tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2);
if (tmp & PGLUE_ATTENTION_VALID) {
u32 addr_lo, addr_hi, details;
- addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_lo = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_WR_ADD_31_0);
- addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_hi = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_WR_ADD_63_32);
- details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ details = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_WR_DETAILS);
- DP_INFO(p_hwfn,
- "Illegal write by chip to [%08x:%08x] blocked.\n"
- "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
- "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
- addr_hi, addr_lo, details,
- (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
- (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
- GET_FIELD(details,
- PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
- tmp,
- GET_FIELD(tmp,
- PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0,
- GET_FIELD(tmp,
- PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
- GET_FIELD(tmp,
- PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0);
+ DP_NOTICE(p_hwfn,
+ "Illegal write by chip to [%08x:%08x] blocked.\n"
+ "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
+ "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
+ addr_hi, addr_lo, details,
+ (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
+ (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
+ GET_FIELD(details,
+ PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
+ tmp,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0);
}
- tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_TX_ERR_RD_DETAILS2);
+ tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2);
if (tmp & PGLUE_ATTENTION_RD_VALID) {
u32 addr_lo, addr_hi, details;
- addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_lo = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_RD_ADD_31_0);
- addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_hi = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_RD_ADD_63_32);
- details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ details = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_TX_ERR_RD_DETAILS);
- DP_INFO(p_hwfn,
- "Illegal read by chip from [%08x:%08x] blocked.\n"
- " Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
- " Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
- addr_hi, addr_lo, details,
- (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
- (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
- GET_FIELD(details,
- PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
- tmp,
- GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1
- : 0,
- GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
- GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1
- : 0);
+ DP_NOTICE(p_hwfn,
+ "Illegal read by chip from [%08x:%08x] blocked.\n"
+ "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
+ "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
+ addr_hi, addr_lo, details,
+ (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
+ (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
+ GET_FIELD(details,
+ PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
+ tmp,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
+ GET_FIELD(tmp,
+ PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0);
}
- tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL);
+ tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL);
if (tmp & PGLUE_ATTENTION_ICPL_VALID)
- DP_INFO(p_hwfn, "ICPL error - %08x\n", tmp);
+ DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp);
- tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS);
+ tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS);
if (tmp & PGLUE_ATTENTION_ZLR_VALID) {
u32 addr_hi, addr_lo;
- addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_lo = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_MASTER_ZLR_ERR_ADD_31_0);
- addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_hi = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_MASTER_ZLR_ERR_ADD_63_32);
- DP_INFO(p_hwfn, "ZLR eror - %08x [Address %08x:%08x]\n",
- tmp, addr_hi, addr_lo);
+ DP_NOTICE(p_hwfn, "ZLR error - %08x [Address %08x:%08x]\n",
+ tmp, addr_hi, addr_lo);
}
- tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_VF_ILT_ERR_DETAILS2);
+ tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_DETAILS2);
if (tmp & PGLUE_ATTENTION_ILT_VALID) {
u32 addr_hi, addr_lo, details;
- addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_lo = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_VF_ILT_ERR_ADD_31_0);
- addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ addr_hi = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_VF_ILT_ERR_ADD_63_32);
- details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt,
+ details = qed_rd(p_hwfn, p_ptt,
PGLUE_B_REG_VF_ILT_ERR_DETAILS);
- DP_INFO(p_hwfn,
- "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n",
- details, tmp, addr_hi, addr_lo);
+ DP_NOTICE(p_hwfn,
+ "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n",
+ details, tmp, addr_hi, addr_lo);
}
/* Clear the indications */
- qed_wr(p_hwfn, p_hwfn->p_dpc_ptt,
- PGLUE_B_REG_LATCHED_ERRORS_CLR, (1 << 2));
+ qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_LATCHED_ERRORS_CLR, BIT(2));
return 0;
}
+static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn)
+{
+ return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt);
+}
+
#define QED_DORQ_ATTENTION_REASON_MASK (0xfffff)
#define QED_DORQ_ATTENTION_OPAQUE_MASK (0xffff)
#define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
@@ -540,7 +542,7 @@ static struct aeu_invert_reg aeu_descs[NUM_ATTN_REGS] = {
{"PGLUE misc_flr", ATTENTION_SINGLE,
NULL, MAX_BLOCK_ID},
{"PGLUE B RBC", ATTENTION_PAR_INT,
- qed_pglub_rbc_attn_cb, BLOCK_PGLUE_B},
+ qed_pglueb_rbc_attn_cb, BLOCK_PGLUE_B},
{"PGLUE misc_mctp", ATTENTION_SINGLE,
NULL, MAX_BLOCK_ID},
{"Flash event", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID},
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h
index d81a62ebd524..1f356ed4f761 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.h
@@ -431,4 +431,7 @@ int qed_int_set_timer_res(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
#define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev))
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
index beb8e5d6401a..ded556b7bab5 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
@@ -1688,6 +1688,15 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn,
eth_hlen = ETH_HLEN + (vlan_valid ? sizeof(u32) : 0);
+ if (!ether_addr_equal(ethh->h_dest,
+ p_hwfn->p_rdma_info->iwarp.mac_addr)) {
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_RDMA,
+ "Got unexpected mac %pM instead of %pM\n",
+ ethh->h_dest, p_hwfn->p_rdma_info->iwarp.mac_addr);
+ return -EINVAL;
+ }
+
ether_addr_copy(remote_mac_addr, ethh->h_source);
ether_addr_copy(local_mac_addr, ethh->h_dest);
@@ -2605,7 +2614,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
struct qed_iwarp_info *iwarp_info;
struct qed_ll2_acquire_data data;
struct qed_ll2_cbs cbs;
- u32 mpa_buff_size;
+ u32 buff_size;
u16 n_ooo_bufs;
int rc = 0;
int i;
@@ -2632,7 +2641,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
memset(&data, 0, sizeof(data));
data.input.conn_type = QED_LL2_TYPE_IWARP;
- data.input.mtu = QED_IWARP_MAX_SYN_PKT_SIZE;
+ data.input.mtu = params->max_mtu;
data.input.rx_num_desc = QED_IWARP_LL2_SYN_RX_SIZE;
data.input.tx_num_desc = QED_IWARP_LL2_SYN_TX_SIZE;
data.input.tx_max_bds_per_packet = 1; /* will never be fragmented */
@@ -2654,9 +2663,10 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
goto err;
}
+ buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu);
rc = qed_iwarp_ll2_alloc_buffers(p_hwfn,
QED_IWARP_LL2_SYN_RX_SIZE,
- QED_IWARP_MAX_SYN_PKT_SIZE,
+ buff_size,
iwarp_info->ll2_syn_handle);
if (rc)
goto err;
@@ -2710,10 +2720,9 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
if (rc)
goto err;
- mpa_buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu);
rc = qed_iwarp_ll2_alloc_buffers(p_hwfn,
data.input.rx_num_desc,
- mpa_buff_size,
+ buff_size,
iwarp_info->ll2_mpa_handle);
if (rc)
goto err;
@@ -2726,7 +2735,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
- iwarp_info->mpa_intermediate_buf = kzalloc(mpa_buff_size, GFP_KERNEL);
+ iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL);
if (!iwarp_info->mpa_intermediate_buf)
goto err;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.h b/drivers/net/ethernet/qlogic/qed/qed_iwarp.h
index b8f612d00241..7ac959038324 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.h
@@ -46,7 +46,6 @@ enum qed_iwarp_qp_state qed_roce2iwarp_state(enum qed_roce_qp_state state);
#define QED_IWARP_LL2_SYN_TX_SIZE (128)
#define QED_IWARP_LL2_SYN_RX_SIZE (256)
-#define QED_IWARP_MAX_SYN_PKT_SIZE (128)
#define QED_IWARP_LL2_OOO_DEF_TX_SIZE (256)
#define QED_IWARP_MAX_OOO (16)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 67c02ea93906..57641728df69 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -609,6 +609,10 @@ qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn,
(!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
!!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
+ SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL,
+ (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) &&
+ !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)));
+
SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL,
!!(accept_filter & QED_ACCEPT_BCAST));
@@ -744,6 +748,11 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
return rc;
}
+ if (p_params->update_ctl_frame_check) {
+ p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en;
+ p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en;
+ }
+
/* Update mcast bins for VFs, PF doesn't use this functionality */
qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params);
@@ -1889,6 +1898,7 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn)
: NULL;
+ bool b_get_port_stats;
if (IS_PF(cdev)) {
/* The main vport index is relative first */
@@ -1903,8 +1913,9 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
continue;
}
+ b_get_port_stats = IS_PF(cdev) && IS_LEAD_HWFN(p_hwfn);
__qed_get_vport_stats(p_hwfn, p_ptt, stats, fw_vport,
- IS_PF(cdev) ? true : false);
+ b_get_port_stats);
out:
if (IS_PF(cdev) && p_ptt)
@@ -2207,7 +2218,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
u16 num_queues = 0;
/* Since the feature controls only queue-zones,
- * make sure we have the contexts [rx, tx, xdp] to
+ * make sure we have the contexts [rx, xdp, tcs] to
* match.
*/
for_each_hwfn(cdev, i) {
@@ -2217,7 +2228,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
u16 cids;
cids = hwfn->pf_params.eth_pf_params.num_cons;
- num_queues += min_t(u16, l2_queues, cids / 3);
+ cids /= (2 + info->num_tc);
+ num_queues += min_t(u16, l2_queues, cids);
}
/* queues might theoretically be >256, but interrupts'
@@ -2688,7 +2700,8 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev,
if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) {
accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
QED_ACCEPT_MCAST_UNMATCHED;
- accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
+ accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
+ QED_ACCEPT_MCAST_UNMATCHED;
} else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) {
accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
@@ -2860,7 +2873,8 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
p_hwfn = p_cid->p_owner;
rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
if (rc)
- DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
+ DP_VERBOSE(cdev, QED_MSG_DEBUG,
+ "Unable to read queue coalescing\n");
return rc;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h
index 8d80f1095d17..7127d5aaac42 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h
@@ -219,6 +219,9 @@ struct qed_sp_vport_update_params {
struct qed_rss_params *rss_params;
struct qed_filter_accept_flags accept_flags;
struct qed_sge_tpa_params *sge_tpa_params;
+ u8 update_ctl_frame_check;
+ u8 mac_chk_en;
+ u8 ethtype_chk_en;
};
int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index 90afd514ffe1..b5f419b71287 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1619,6 +1619,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);
rx_prod.bd_prod = cpu_to_le16(bd_prod);
rx_prod.cqe_prod = cpu_to_le16(cq_prod);
+
+ /* Make sure chain element is updated before ringing the doorbell */
+ dma_wmb();
+
DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
}
@@ -2447,19 +2451,24 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
{
struct qed_ll2_tx_pkt_info pkt;
const skb_frag_t *frag;
+ u8 flags = 0, nr_frags;
int rc = -EINVAL, i;
dma_addr_t mapping;
u16 vlan = 0;
- u8 flags = 0;
if (unlikely(skb->ip_summed != CHECKSUM_NONE)) {
DP_INFO(cdev, "Cannot transmit a checksummed packet\n");
return -EINVAL;
}
- if (1 + skb_shinfo(skb)->nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
+ /* Cache number of fragments from SKB since SKB may be freed by
+ * the completion routine after calling qed_ll2_prepare_tx_packet()
+ */
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
+ if (1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n",
- 1 + skb_shinfo(skb)->nr_frags);
+ 1 + nr_frags);
return -EINVAL;
}
@@ -2481,7 +2490,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
}
memset(&pkt, 0, sizeof(pkt));
- pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
+ pkt.num_of_bds = 1 + nr_frags;
pkt.vlan = vlan;
pkt.bd_flags = flags;
pkt.tx_dest = QED_LL2_TX_DEST_NW;
@@ -2492,12 +2501,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags))
pkt.remove_stag = true;
+ /* qed_ll2_prepare_tx_packet() may actually send the packet if
+ * there are no fragments in the skb and subsequently the completion
+ * routine may run and free the SKB, so no dereferencing the SKB
+ * beyond this point unless skb has any fragments.
+ */
rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
&pkt, 1);
if (rc)
goto err;
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ for (i = 0; i < nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i];
mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 6adf5bda9811..f164d4acebcb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -281,6 +281,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME)
dev_info->wol_support = true;
+ dev_info->smart_an = qed_mcp_is_smart_an_supported(p_hwfn);
+
dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id;
} else {
qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
@@ -359,6 +361,8 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev,
qed_init_dp(cdev, params->dp_module, params->dp_level);
+ cdev->recov_in_prog = params->recov_in_prog;
+
rc = qed_init_pci(cdev, pdev);
if (rc) {
DP_ERR(cdev, "init pci failed\n");
@@ -2203,6 +2207,15 @@ static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
return qed_mcp_get_nvm_image(hwfn, type, buf, len);
}
+void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn)
+{
+ struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common;
+ void *cookie = p_hwfn->cdev->ops_cookie;
+
+ if (ops && ops->schedule_recovery_handler)
+ ops->schedule_recovery_handler(cookie);
+}
+
static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal,
void *handle)
{
@@ -2226,6 +2239,23 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
return status;
}
+static int qed_recovery_process(struct qed_dev *cdev)
+{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt;
+ int rc = 0;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EAGAIN;
+
+ rc = qed_start_recovery_process(p_hwfn, p_ptt);
+
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return rc;
+}
+
static int qed_update_wol(struct qed_dev *cdev, bool enabled)
{
struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
@@ -2380,6 +2410,8 @@ const struct qed_common_ops qed_common_ops_pass = {
.nvm_get_image = &qed_nvm_get_image,
.set_coalesce = &qed_set_coalesce,
.set_led = &qed_set_led,
+ .recovery_process = &qed_recovery_process,
+ .recovery_prolog = &qed_recovery_prolog,
.update_drv_state = &qed_update_drv_state,
.update_mac = &qed_update_mac,
.update_mtu = &qed_update_mtu,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index e7f18e34ff0d..cc27fd60d689 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1070,6 +1070,27 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn,
return 0;
}
+int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ u32 resp = 0, param = 0;
+ int rc;
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_DONE, 0, &resp,
+ &param);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "Failed to send a LOAD_DONE command, rc = %d\n", rc);
+ return rc;
+ }
+
+ /* Check if there is a DID mismatch between nvm-cfg/efuse */
+ if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR)
+ DP_NOTICE(p_hwfn,
+ "warning: device configuration is not supported on this board type. The device may not function as expected.\n");
+
+ return 0;
+}
+
int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
struct qed_mcp_mb_params mb_params;
@@ -1528,6 +1549,60 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
return 0;
}
+u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt;
+
+ if (IS_VF(p_hwfn->cdev))
+ return -EINVAL;
+
+ path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+ PUBLIC_PATH);
+ path_offsize = qed_rd(p_hwfn, p_ptt, path_offsize_addr);
+ path_addr = SECTION_ADDR(path_offsize, QED_PATH_ID(p_hwfn));
+
+ proc_kill_cnt = qed_rd(p_hwfn, p_ptt,
+ path_addr +
+ offsetof(struct public_path, process_kill)) &
+ PROCESS_KILL_COUNTER_MASK;
+
+ return proc_kill_cnt;
+}
+
+static void qed_mcp_handle_process_kill(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+ u32 proc_kill_cnt;
+
+ /* Prevent possible attentions/interrupts during the recovery handling
+ * and till its load phase, during which they will be re-enabled.
+ */
+ qed_int_igu_disable_int(p_hwfn, p_ptt);
+
+ DP_NOTICE(p_hwfn, "Received a process kill indication\n");
+
+ /* The following operations should be done once, and thus in CMT mode
+ * are carried out by only the first HW function.
+ */
+ if (p_hwfn != QED_LEADING_HWFN(cdev))
+ return;
+
+ if (cdev->recov_in_prog) {
+ DP_NOTICE(p_hwfn,
+ "Ignoring the indication since a recovery process is already in progress\n");
+ return;
+ }
+
+ cdev->recov_in_prog = true;
+
+ proc_kill_cnt = qed_get_process_kill_counter(p_hwfn, p_ptt);
+ DP_NOTICE(p_hwfn, "Process kill counter: %d\n", proc_kill_cnt);
+
+ qed_schedule_recovery_handler(p_hwfn);
+}
+
static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum MFW_DRV_MSG_TYPE type)
@@ -1758,6 +1833,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
qed_mcp_handle_transceiver_change(p_hwfn, p_ptt);
break;
+ case MFW_DRV_MSG_ERROR_RECOVERY:
+ qed_mcp_handle_process_kill(p_hwfn, p_ptt);
+ break;
case MFW_DRV_MSG_GET_LAN_STATS:
case MFW_DRV_MSG_GET_FCOE_STATS:
case MFW_DRV_MSG_GET_ISCSI_STATS:
@@ -2303,6 +2381,43 @@ int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn,
return 0;
}
+int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ struct qed_dev *cdev = p_hwfn->cdev;
+
+ if (cdev->recov_in_prog) {
+ DP_NOTICE(p_hwfn,
+ "Avoid triggering a recovery since such a process is already in progress\n");
+ return -EAGAIN;
+ }
+
+ DP_NOTICE(p_hwfn, "Triggering a recovery process\n");
+ qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1);
+
+ return 0;
+}
+
+#define QED_RECOVERY_PROLOG_SLEEP_MS 100
+
+int qed_recovery_prolog(struct qed_dev *cdev)
+{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt = p_hwfn->p_main_ptt;
+ int rc;
+
+ /* Allow ongoing PCIe transactions to complete */
+ msleep(QED_RECOVERY_PROLOG_SLEEP_MS);
+
+ /* Clear the PF's internal FID_enable in the PXP */
+ rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false);
+ if (rc)
+ DP_NOTICE(p_hwfn,
+ "qed_pglueb_set_pfid_enable() failed. rc = %d.\n",
+ rc);
+
+ return rc;
+}
+
static int
qed_mcp_config_vf_msix_bb(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 vf_id, u8 num)
@@ -3539,6 +3654,12 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
}
}
+bool qed_mcp_is_smart_an_supported(struct qed_hwfn *p_hwfn)
+{
+ return !!(p_hwfn->mcp_info->capabilities &
+ FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ);
+}
+
int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 mcp_resp;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index eddf67798d6f..261c1a392e2c 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -441,6 +441,38 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
struct qed_mcp_drv_version *p_ver);
/**
+ * @brief Read the MFW process kill counter
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return u32
+ */
+u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt);
+
+/**
+ * @brief Trigger a recovery process
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return int
+ */
+int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+
+/**
+ * @brief A recovery handler must call this function as its first step.
+ * It is assumed that the handler is not run from an interrupt context.
+ *
+ * @param cdev
+ * @param p_ptt
+ *
+ * @return int
+ */
+int qed_recovery_prolog(struct qed_dev *cdev);
+
+/**
* @brief Notify MFW about the change in base device properties
*
* @param p_hwfn
@@ -659,10 +691,6 @@ int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
rel_pfid)
#define MCP_PF_ID(p_hwfn) MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id)
-#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \
- ((_p_hwfn)->cdev->num_ports_in_engine * \
- qed_device_num_engines((_p_hwfn)->cdev)))
-
struct qed_mcp_info {
/* List for mailbox commands which were sent and wait for a response */
struct list_head cmd_list;
@@ -801,6 +829,16 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn,
struct qed_load_req_params *p_params);
/**
+ * @brief Sends a LOAD_DONE message to the MFW
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ *
+ * @return int - 0 - Operation was successful.
+ */
+int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+
+/**
* @brief Sends a UNLOAD_REQ message to the MFW
*
* @param p_hwfn
@@ -1106,6 +1144,16 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
struct qed_resc_unlock_params *p_unlock,
enum qed_resc_lock
resource, bool b_is_permanent);
+
+/**
+ * @brief - Return whether management firmware support smart AN
+ *
+ * @param p_hwfn
+ *
+ * @return bool - true if feature is supported.
+ */
+bool qed_mcp_is_smart_an_supported(struct qed_hwfn *p_hwfn);
+
/**
* @brief Learn of supported MFW features; To be done during early init
*
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ptp.c b/drivers/net/ethernet/qlogic/qed/qed_ptp.c
index 5a90d69dc2f8..1302b308bd87 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ptp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ptp.c
@@ -47,7 +47,7 @@
static enum qed_resc_lock qed_ptcdev_to_resc(struct qed_hwfn *p_hwfn)
{
- switch (qed_device_get_port_id(p_hwfn->cdev)) {
+ switch (MFW_PORT(p_hwfn)) {
case 0:
return QED_RESC_LOCK_PTP_PORT0;
case 1:
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
index 8939ed6e08b7..5ce825ca5f24 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
@@ -518,6 +518,8 @@
0x180824UL
#define MISC_REG_AEU_GENERAL_ATTN_0 \
0x008400UL
+#define MISC_REG_AEU_GENERAL_ATTN_35 \
+ 0x00848cUL
#define CAU_REG_SB_ADDR_MEMORY \
0x1c8000UL
#define CAU_REG_SB_VAR_MEMORY \
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index 4179c9013fc6..96ab77ae6af5 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -382,6 +382,7 @@ void qed_consq_setup(struct qed_hwfn *p_hwfn);
* @param p_hwfn
*/
void qed_consq_free(struct qed_hwfn *p_hwfn);
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn);
/**
* @file
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
index 888274fa208b..5a495fda9e9d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
@@ -604,6 +604,9 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn)
p_ent->ramrod.pf_update.update_mf_vlan_flag = true;
p_ent->ramrod.pf_update.mf_vlan = cpu_to_le16(p_hwfn->hw_info.ovlan);
+ if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
+ p_ent->ramrod.pf_update.mf_vlan |=
+ cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13));
return qed_spq_post(p_hwfn, p_ent, NULL);
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index eb88bbc6b193..79b311b86f66 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -397,6 +397,11 @@ int qed_eq_completion(struct qed_hwfn *p_hwfn, void *cookie)
qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain));
+ /* Attempt to post pending requests */
+ spin_lock_bh(&p_hwfn->p_spq->lock);
+ rc = qed_spq_pend_post(p_hwfn);
+ spin_unlock_bh(&p_hwfn->p_spq->lock);
+
return rc;
}
@@ -767,7 +772,7 @@ static int qed_spq_post_list(struct qed_hwfn *p_hwfn,
return 0;
}
-static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
{
struct qed_spq *p_spq = p_hwfn->p_spq;
struct qed_spq_entry *p_ent = NULL;
@@ -790,6 +795,17 @@ static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
SPQ_HIGH_PRI_RESERVE_DEFAULT);
}
+static void qed_spq_recov_set_ret_code(struct qed_spq_entry *p_ent,
+ u8 *fw_return_code)
+{
+ if (!fw_return_code)
+ return;
+
+ if (p_ent->elem.hdr.protocol_id == PROTOCOLID_ROCE ||
+ p_ent->elem.hdr.protocol_id == PROTOCOLID_IWARP)
+ *fw_return_code = RDMA_RETURN_OK;
+}
+
/* Avoid overriding of SPQ entries when getting out-of-order completions, by
* marking the completions in a bitmap and increasing the chain consumer only
* for the first successive completed entries.
@@ -825,6 +841,17 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
return -EINVAL;
}
+ if (p_hwfn->cdev->recov_in_prog) {
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_SPQ,
+ "Recovery is in progress. Skip spq post [cmd %02x protocol %02x]\n",
+ p_ent->elem.hdr.cmd_id, p_ent->elem.hdr.protocol_id);
+
+ /* Let the flow complete w/o any error handling */
+ qed_spq_recov_set_ret_code(p_ent, fw_return_code);
+ return 0;
+ }
+
/* Complete the entry */
rc = qed_spq_fill_entry(p_hwfn, p_ent);
@@ -905,7 +932,6 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
struct qed_spq_entry *p_ent = NULL;
struct qed_spq_entry *tmp;
struct qed_spq_entry *found = NULL;
- int rc;
if (!p_hwfn)
return -EINVAL;
@@ -963,12 +989,7 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
*/
qed_spq_return_entry(p_hwfn, found);
- /* Attempt to post pending requests */
- spin_lock_bh(&p_spq->lock);
- rc = qed_spq_pend_post(p_hwfn);
- spin_unlock_bh(&p_spq->lock);
-
- return rc;
+ return 0;
}
int qed_consq_alloc(struct qed_hwfn *p_hwfn)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index ca6290fa0f30..9faaa6df78ed 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -1969,7 +1969,9 @@ static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn,
params.vport_id = vf->vport_id;
params.max_buffers_per_cqe = start->max_buffers_per_cqe;
params.mtu = vf->mtu;
- params.check_mac = true;
+
+ /* Non trusted VFs should enable control frame filtering */
+ params.check_mac = !vf->p_vf_info.is_trusted_configured;
rc = qed_sp_eth_vport_start(p_hwfn, &params);
if (rc) {
@@ -4447,6 +4449,13 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled)
pci_disable_sriov(cdev->pdev);
+ if (cdev->recov_in_prog) {
+ DP_VERBOSE(cdev,
+ QED_MSG_IOV,
+ "Skip SRIOV disable operations in the device since a recovery is in progress\n");
+ goto out;
+ }
+
for_each_hwfn(cdev, i) {
struct qed_hwfn *hwfn = &cdev->hwfns[i];
struct qed_ptt *ptt = qed_ptt_acquire(hwfn);
@@ -4486,7 +4495,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
qed_ptt_release(hwfn, ptt);
}
-
+out:
qed_iov_set_vfs_to_disable(cdev, false);
return 0;
@@ -5130,6 +5139,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
params.opaque_fid = vf->opaque_fid;
params.vport_id = vf->vport_id;
+ params.update_ctl_frame_check = 1;
+ params.mac_chk_en = !vf_info->is_trusted_configured;
+
if (vf_info->rx_accept_mode & mask) {
flags->update_rx_mode_config = 1;
flags->rx_accept_filter = vf_info->rx_accept_mode;
@@ -5147,7 +5159,8 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
}
if (flags->update_rx_mode_config ||
- flags->update_tx_mode_config)
+ flags->update_tx_mode_config ||
+ params.update_ctl_frame_check)
qed_sp_vport_update(hwfn, &params,
QED_SPQ_MODE_EBLOCK, NULL);
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index b6cccf44bf40..5dda547772c1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -261,6 +261,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
struct vf_pf_resc_request *p_resc;
+ u8 retry_cnt = VF_ACQUIRE_THRESH;
bool resources_acquired = false;
struct vfpf_acquire_tlv *req;
int rc = 0, attempts = 0;
@@ -314,6 +315,15 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
/* send acquire request */
rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
+
+ /* Re-try acquire in case of vf-pf hw channel timeout */
+ if (retry_cnt && rc == -EBUSY) {
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "VF retrying to acquire due to VPC timeout\n");
+ retry_cnt--;
+ continue;
+ }
+
if (rc)
goto exit;
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 613249d1e967..63a78162cfaf 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -56,7 +56,7 @@
#include <net/tc_act/tc_gact.h>
#define QEDE_MAJOR_VERSION 8
-#define QEDE_MINOR_VERSION 33
+#define QEDE_MINOR_VERSION 37
#define QEDE_REVISION_VERSION 0
#define QEDE_ENGINEERING_VERSION 20
#define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \
@@ -162,6 +162,7 @@ struct qede_rdma_dev {
struct list_head entry;
struct list_head rdma_event_list;
struct workqueue_struct *rdma_wq;
+ bool exp_recovery;
};
struct qede_ptp;
@@ -264,6 +265,7 @@ struct qede_dev {
enum QEDE_STATE {
QEDE_STATE_CLOSED,
QEDE_STATE_OPEN,
+ QEDE_STATE_RECOVERY,
};
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
@@ -462,6 +464,7 @@ struct qede_fastpath {
#define QEDE_CSUM_UNNECESSARY BIT(1)
#define QEDE_TUNN_CSUM_UNNECESSARY BIT(2)
+#define QEDE_SP_RECOVERY 0
#define QEDE_SP_RX_MODE 1
#ifdef CONFIG_RFS_ACCEL
@@ -494,6 +497,9 @@ struct qede_reload_args {
/* Datapath functions definition */
netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+ struct net_device *sb_dev,
+ select_queue_fallback_t fallback);
netdev_features_t qede_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 16331c6c6fa7..c6238083e898 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -186,11 +186,13 @@ static const struct {
enum {
QEDE_PRI_FLAG_CMT,
+ QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */
QEDE_PRI_FLAG_LEN,
};
static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
"Coupled-Function",
+ "SmartAN capable",
};
enum qede_ethtool_tests {
@@ -404,8 +406,15 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
static u32 qede_get_priv_flags(struct net_device *dev)
{
struct qede_dev *edev = netdev_priv(dev);
+ u32 flags = 0;
- return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT;
+ if (edev->dev_info.common.num_hwfns > 1)
+ flags |= BIT(QEDE_PRI_FLAG_CMT);
+
+ if (edev->dev_info.common.smart_an)
+ flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT);
+
+ return flags;
}
struct qede_link_mode_mapping {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index b16ce7d93caf..add922b93d2c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -1665,198 +1665,6 @@ static int qede_set_v6_tuple_to_profile(struct qede_dev *edev,
return 0;
}
-static int qede_flow_spec_to_tuple_ipv4_common(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- if ((fs->h_u.tcp_ip4_spec.ip4src &
- fs->m_u.tcp_ip4_spec.ip4src) != fs->h_u.tcp_ip4_spec.ip4src) {
- DP_INFO(edev, "Don't support IP-masks\n");
- return -EOPNOTSUPP;
- }
-
- if ((fs->h_u.tcp_ip4_spec.ip4dst &
- fs->m_u.tcp_ip4_spec.ip4dst) != fs->h_u.tcp_ip4_spec.ip4dst) {
- DP_INFO(edev, "Don't support IP-masks\n");
- return -EOPNOTSUPP;
- }
-
- if ((fs->h_u.tcp_ip4_spec.psrc &
- fs->m_u.tcp_ip4_spec.psrc) != fs->h_u.tcp_ip4_spec.psrc) {
- DP_INFO(edev, "Don't support port-masks\n");
- return -EOPNOTSUPP;
- }
-
- if ((fs->h_u.tcp_ip4_spec.pdst &
- fs->m_u.tcp_ip4_spec.pdst) != fs->h_u.tcp_ip4_spec.pdst) {
- DP_INFO(edev, "Don't support port-masks\n");
- return -EOPNOTSUPP;
- }
-
- if (fs->h_u.tcp_ip4_spec.tos) {
- DP_INFO(edev, "Don't support tos\n");
- return -EOPNOTSUPP;
- }
-
- t->eth_proto = htons(ETH_P_IP);
- t->src_ipv4 = fs->h_u.tcp_ip4_spec.ip4src;
- t->dst_ipv4 = fs->h_u.tcp_ip4_spec.ip4dst;
- t->src_port = fs->h_u.tcp_ip4_spec.psrc;
- t->dst_port = fs->h_u.tcp_ip4_spec.pdst;
-
- return qede_set_v4_tuple_to_profile(edev, t);
-}
-
-static int qede_flow_spec_to_tuple_tcpv4(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- t->ip_proto = IPPROTO_TCP;
-
- if (qede_flow_spec_to_tuple_ipv4_common(edev, t, fs))
- return -EINVAL;
-
- return 0;
-}
-
-static int qede_flow_spec_to_tuple_udpv4(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- t->ip_proto = IPPROTO_UDP;
-
- if (qede_flow_spec_to_tuple_ipv4_common(edev, t, fs))
- return -EINVAL;
-
- return 0;
-}
-
-static int qede_flow_spec_to_tuple_ipv6_common(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- struct in6_addr zero_addr;
-
- memset(&zero_addr, 0, sizeof(zero_addr));
-
- if ((fs->h_u.tcp_ip6_spec.psrc &
- fs->m_u.tcp_ip6_spec.psrc) != fs->h_u.tcp_ip6_spec.psrc) {
- DP_INFO(edev, "Don't support port-masks\n");
- return -EOPNOTSUPP;
- }
-
- if ((fs->h_u.tcp_ip6_spec.pdst &
- fs->m_u.tcp_ip6_spec.pdst) != fs->h_u.tcp_ip6_spec.pdst) {
- DP_INFO(edev, "Don't support port-masks\n");
- return -EOPNOTSUPP;
- }
-
- if (fs->h_u.tcp_ip6_spec.tclass) {
- DP_INFO(edev, "Don't support tclass\n");
- return -EOPNOTSUPP;
- }
-
- t->eth_proto = htons(ETH_P_IPV6);
- memcpy(&t->src_ipv6, &fs->h_u.tcp_ip6_spec.ip6src,
- sizeof(struct in6_addr));
- memcpy(&t->dst_ipv6, &fs->h_u.tcp_ip6_spec.ip6dst,
- sizeof(struct in6_addr));
- t->src_port = fs->h_u.tcp_ip6_spec.psrc;
- t->dst_port = fs->h_u.tcp_ip6_spec.pdst;
-
- return qede_set_v6_tuple_to_profile(edev, t, &zero_addr);
-}
-
-static int qede_flow_spec_to_tuple_tcpv6(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- t->ip_proto = IPPROTO_TCP;
-
- if (qede_flow_spec_to_tuple_ipv6_common(edev, t, fs))
- return -EINVAL;
-
- return 0;
-}
-
-static int qede_flow_spec_to_tuple_udpv6(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- t->ip_proto = IPPROTO_UDP;
-
- if (qede_flow_spec_to_tuple_ipv6_common(edev, t, fs))
- return -EINVAL;
-
- return 0;
-}
-
-static int qede_flow_spec_to_tuple(struct qede_dev *edev,
- struct qede_arfs_tuple *t,
- struct ethtool_rx_flow_spec *fs)
-{
- memset(t, 0, sizeof(*t));
-
- if (qede_flow_spec_validate_unused(edev, fs))
- return -EOPNOTSUPP;
-
- switch ((fs->flow_type & ~FLOW_EXT)) {
- case TCP_V4_FLOW:
- return qede_flow_spec_to_tuple_tcpv4(edev, t, fs);
- case UDP_V4_FLOW:
- return qede_flow_spec_to_tuple_udpv4(edev, t, fs);
- case TCP_V6_FLOW:
- return qede_flow_spec_to_tuple_tcpv6(edev, t, fs);
- case UDP_V6_FLOW:
- return qede_flow_spec_to_tuple_udpv6(edev, t, fs);
- default:
- DP_VERBOSE(edev, NETIF_MSG_IFUP,
- "Can't support flow of type %08x\n", fs->flow_type);
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int qede_flow_spec_validate(struct qede_dev *edev,
- struct ethtool_rx_flow_spec *fs,
- struct qede_arfs_tuple *t)
-{
- if (fs->location >= QEDE_RFS_MAX_FLTR) {
- DP_INFO(edev, "Location out-of-bounds\n");
- return -EINVAL;
- }
-
- /* Check location isn't already in use */
- if (test_bit(fs->location, edev->arfs->arfs_fltr_bmap)) {
- DP_INFO(edev, "Location already in use\n");
- return -EINVAL;
- }
-
- /* Check if the filtering-mode could support the filter */
- if (edev->arfs->filter_count &&
- edev->arfs->mode != t->mode) {
- DP_INFO(edev,
- "flow_spec would require filtering mode %08x, but %08x is configured\n",
- t->mode, edev->arfs->filter_count);
- return -EINVAL;
- }
-
- /* If drop requested then no need to validate other data */
- if (fs->ring_cookie == RX_CLS_FLOW_DISC)
- return 0;
-
- if (ethtool_get_flow_spec_ring_vf(fs->ring_cookie))
- return 0;
-
- if (fs->ring_cookie >= QEDE_RSS_COUNT(edev)) {
- DP_INFO(edev, "Queue out-of-bounds\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
/* Must be called while qede lock is held */
static struct qede_arfs_fltr_node *
qede_flow_find_fltr(struct qede_dev *edev, struct qede_arfs_tuple *t)
@@ -1896,72 +1704,6 @@ static void qede_flow_set_destination(struct qede_dev *edev,
"Configuring N-tuple for VF 0x%02x\n", n->vfid - 1);
}
-int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
-{
- struct ethtool_rx_flow_spec *fsp = &info->fs;
- struct qede_arfs_fltr_node *n;
- struct qede_arfs_tuple t;
- int min_hlen, rc;
-
- __qede_lock(edev);
-
- if (!edev->arfs) {
- rc = -EPERM;
- goto unlock;
- }
-
- /* Translate the flow specification into something fittign our DB */
- rc = qede_flow_spec_to_tuple(edev, &t, fsp);
- if (rc)
- goto unlock;
-
- /* Make sure location is valid and filter isn't already set */
- rc = qede_flow_spec_validate(edev, fsp, &t);
- if (rc)
- goto unlock;
-
- if (qede_flow_find_fltr(edev, &t)) {
- rc = -EINVAL;
- goto unlock;
- }
-
- n = kzalloc(sizeof(*n), GFP_KERNEL);
- if (!n) {
- rc = -ENOMEM;
- goto unlock;
- }
-
- min_hlen = qede_flow_get_min_header_size(&t);
- n->data = kzalloc(min_hlen, GFP_KERNEL);
- if (!n->data) {
- kfree(n);
- rc = -ENOMEM;
- goto unlock;
- }
-
- n->sw_id = fsp->location;
- set_bit(n->sw_id, edev->arfs->arfs_fltr_bmap);
- n->buf_len = min_hlen;
-
- memcpy(&n->tuple, &t, sizeof(n->tuple));
-
- qede_flow_set_destination(edev, n, fsp);
-
- /* Build a minimal header according to the flow */
- n->tuple.build_hdr(&n->tuple, n->data);
-
- rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0);
- if (rc)
- goto unlock;
-
- qede_configure_arfs_fltr(edev, n, n->rxq_id, true);
- rc = qede_poll_arfs_filter_config(edev, n);
-unlock:
- __qede_unlock(edev);
-
- return rc;
-}
-
int qede_delete_flow_filter(struct qede_dev *edev, u64 cookie)
{
struct qede_arfs_fltr_node *fltr = NULL;
@@ -2004,190 +1746,172 @@ unlock:
}
static int qede_parse_actions(struct qede_dev *edev,
- struct tcf_exts *exts)
+ struct flow_action *flow_action)
{
- int rc = -EINVAL, num_act = 0, i;
- const struct tc_action *a;
- bool is_drop = false;
+ const struct flow_action_entry *act;
+ int i;
- if (!tcf_exts_has_actions(exts)) {
- DP_NOTICE(edev, "No tc actions received\n");
- return rc;
+ if (!flow_action_has_entries(flow_action)) {
+ DP_NOTICE(edev, "No actions received\n");
+ return -EINVAL;
}
- tcf_exts_for_each_action(i, a, exts) {
- num_act++;
+ flow_action_for_each(i, act, flow_action) {
+ switch (act->id) {
+ case FLOW_ACTION_DROP:
+ break;
+ case FLOW_ACTION_QUEUE:
+ if (act->queue.vf)
+ break;
- if (is_tcf_gact_shot(a))
- is_drop = true;
+ if (act->queue.index >= QEDE_RSS_COUNT(edev)) {
+ DP_INFO(edev, "Queue out-of-bounds\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
}
- if (num_act == 1 && is_drop)
- return 0;
-
- return rc;
+ return 0;
}
static int
-qede_tc_parse_ports(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
- struct qede_arfs_tuple *t)
-{
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key, *mask;
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
-
- if ((key->src && mask->src != U16_MAX) ||
- (key->dst && mask->dst != U16_MAX)) {
+qede_flow_parse_ports(struct qede_dev *edev, struct flow_rule *rule,
+ struct qede_arfs_tuple *t)
+{
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_match_ports match;
+
+ flow_rule_match_ports(rule, &match);
+ if ((match.key->src && match.mask->src != U16_MAX) ||
+ (match.key->dst && match.mask->dst != U16_MAX)) {
DP_NOTICE(edev, "Do not support ports masks\n");
return -EINVAL;
}
- t->src_port = key->src;
- t->dst_port = key->dst;
+ t->src_port = match.key->src;
+ t->dst_port = match.key->dst;
}
return 0;
}
static int
-qede_tc_parse_v6_common(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
- struct qede_arfs_tuple *t)
+qede_flow_parse_v6_common(struct qede_dev *edev, struct flow_rule *rule,
+ struct qede_arfs_tuple *t)
{
struct in6_addr zero_addr, addr;
memset(&zero_addr, 0, sizeof(addr));
memset(&addr, 0xff, sizeof(addr));
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
- struct flow_dissector_key_ipv6_addrs *key, *mask;
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
+ struct flow_match_ipv6_addrs match;
- if ((memcmp(&key->src, &zero_addr, sizeof(addr)) &&
- memcmp(&mask->src, &addr, sizeof(addr))) ||
- (memcmp(&key->dst, &zero_addr, sizeof(addr)) &&
- memcmp(&mask->dst, &addr, sizeof(addr)))) {
+ flow_rule_match_ipv6_addrs(rule, &match);
+ if ((memcmp(&match.key->src, &zero_addr, sizeof(addr)) &&
+ memcmp(&match.mask->src, &addr, sizeof(addr))) ||
+ (memcmp(&match.key->dst, &zero_addr, sizeof(addr)) &&
+ memcmp(&match.mask->dst, &addr, sizeof(addr)))) {
DP_NOTICE(edev,
"Do not support IPv6 address prefix/mask\n");
return -EINVAL;
}
- memcpy(&t->src_ipv6, &key->src, sizeof(addr));
- memcpy(&t->dst_ipv6, &key->dst, sizeof(addr));
+ memcpy(&t->src_ipv6, &match.key->src, sizeof(addr));
+ memcpy(&t->dst_ipv6, &match.key->dst, sizeof(addr));
}
- if (qede_tc_parse_ports(edev, f, t))
+ if (qede_flow_parse_ports(edev, rule, t))
return -EINVAL;
return qede_set_v6_tuple_to_profile(edev, t, &zero_addr);
}
static int
-qede_tc_parse_v4_common(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
+qede_flow_parse_v4_common(struct qede_dev *edev, struct flow_rule *rule,
struct qede_arfs_tuple *t)
{
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
- struct flow_dissector_key_ipv4_addrs *key, *mask;
-
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- mask = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
+ struct flow_match_ipv4_addrs match;
- if ((key->src && mask->src != U32_MAX) ||
- (key->dst && mask->dst != U32_MAX)) {
+ flow_rule_match_ipv4_addrs(rule, &match);
+ if ((match.key->src && match.mask->src != U32_MAX) ||
+ (match.key->dst && match.mask->dst != U32_MAX)) {
DP_NOTICE(edev, "Do not support ipv4 prefix/masks\n");
return -EINVAL;
}
- t->src_ipv4 = key->src;
- t->dst_ipv4 = key->dst;
+ t->src_ipv4 = match.key->src;
+ t->dst_ipv4 = match.key->dst;
}
- if (qede_tc_parse_ports(edev, f, t))
+ if (qede_flow_parse_ports(edev, rule, t))
return -EINVAL;
return qede_set_v4_tuple_to_profile(edev, t);
}
static int
-qede_tc_parse_tcp_v6(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
+qede_flow_parse_tcp_v6(struct qede_dev *edev, struct flow_rule *rule,
struct qede_arfs_tuple *tuple)
{
tuple->ip_proto = IPPROTO_TCP;
tuple->eth_proto = htons(ETH_P_IPV6);
- return qede_tc_parse_v6_common(edev, f, tuple);
+ return qede_flow_parse_v6_common(edev, rule, tuple);
}
static int
-qede_tc_parse_tcp_v4(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
+qede_flow_parse_tcp_v4(struct qede_dev *edev, struct flow_rule *rule,
struct qede_arfs_tuple *tuple)
{
tuple->ip_proto = IPPROTO_TCP;
tuple->eth_proto = htons(ETH_P_IP);
- return qede_tc_parse_v4_common(edev, f, tuple);
+ return qede_flow_parse_v4_common(edev, rule, tuple);
}
static int
-qede_tc_parse_udp_v6(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
+qede_flow_parse_udp_v6(struct qede_dev *edev, struct flow_rule *rule,
struct qede_arfs_tuple *tuple)
{
tuple->ip_proto = IPPROTO_UDP;
tuple->eth_proto = htons(ETH_P_IPV6);
- return qede_tc_parse_v6_common(edev, f, tuple);
+ return qede_flow_parse_v6_common(edev, rule, tuple);
}
static int
-qede_tc_parse_udp_v4(struct qede_dev *edev,
- struct tc_cls_flower_offload *f,
+qede_flow_parse_udp_v4(struct qede_dev *edev, struct flow_rule *rule,
struct qede_arfs_tuple *tuple)
{
tuple->ip_proto = IPPROTO_UDP;
tuple->eth_proto = htons(ETH_P_IP);
- return qede_tc_parse_v4_common(edev, f, tuple);
+ return qede_flow_parse_v4_common(edev, rule, tuple);
}
static int
-qede_parse_flower_attr(struct qede_dev *edev, __be16 proto,
- struct tc_cls_flower_offload *f,
- struct qede_arfs_tuple *tuple)
+qede_parse_flow_attr(struct qede_dev *edev, __be16 proto,
+ struct flow_rule *rule, struct qede_arfs_tuple *tuple)
{
+ struct flow_dissector *dissector = rule->match.dissector;
int rc = -EINVAL;
u8 ip_proto = 0;
memset(tuple, 0, sizeof(*tuple));
- if (f->dissector->used_keys &
+ if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_PORTS))) {
DP_NOTICE(edev, "Unsupported key set:0x%x\n",
- f->dissector->used_keys);
+ dissector->used_keys);
return -EOPNOTSUPP;
}
@@ -2197,25 +1921,23 @@ qede_parse_flower_attr(struct qede_dev *edev, __be16 proto,
return -EPROTONOSUPPORT;
}
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key;
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_match_basic match;
- key = skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
- ip_proto = key->ip_proto;
+ flow_rule_match_basic(rule, &match);
+ ip_proto = match.key->ip_proto;
}
if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IP))
- rc = qede_tc_parse_tcp_v4(edev, f, tuple);
+ rc = qede_flow_parse_tcp_v4(edev, rule, tuple);
else if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IPV6))
- rc = qede_tc_parse_tcp_v6(edev, f, tuple);
+ rc = qede_flow_parse_tcp_v6(edev, rule, tuple);
else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IP))
- rc = qede_tc_parse_udp_v4(edev, f, tuple);
+ rc = qede_flow_parse_udp_v4(edev, rule, tuple);
else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IPV6))
- rc = qede_tc_parse_udp_v6(edev, f, tuple);
+ rc = qede_flow_parse_udp_v6(edev, rule, tuple);
else
- DP_NOTICE(edev, "Invalid tc protocol request\n");
+ DP_NOTICE(edev, "Invalid protocol request\n");
return rc;
}
@@ -2235,7 +1957,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
}
/* parse flower attribute and prepare filter */
- if (qede_parse_flower_attr(edev, proto, f, &t))
+ if (qede_parse_flow_attr(edev, proto, f->rule, &t))
goto unlock;
/* Validate profile mode and number of filters */
@@ -2248,7 +1970,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
}
/* parse tc actions and get the vf_id */
- if (qede_parse_actions(edev, f->exts))
+ if (qede_parse_actions(edev, &f->rule->action))
goto unlock;
if (qede_flow_find_fltr(edev, &t)) {
@@ -2290,3 +2012,141 @@ unlock:
__qede_unlock(edev);
return rc;
}
+
+static int qede_flow_spec_validate(struct qede_dev *edev,
+ struct flow_action *flow_action,
+ struct qede_arfs_tuple *t,
+ __u32 location)
+{
+ if (location >= QEDE_RFS_MAX_FLTR) {
+ DP_INFO(edev, "Location out-of-bounds\n");
+ return -EINVAL;
+ }
+
+ /* Check location isn't already in use */
+ if (test_bit(location, edev->arfs->arfs_fltr_bmap)) {
+ DP_INFO(edev, "Location already in use\n");
+ return -EINVAL;
+ }
+
+ /* Check if the filtering-mode could support the filter */
+ if (edev->arfs->filter_count &&
+ edev->arfs->mode != t->mode) {
+ DP_INFO(edev,
+ "flow_spec would require filtering mode %08x, but %08x is configured\n",
+ t->mode, edev->arfs->filter_count);
+ return -EINVAL;
+ }
+
+ if (qede_parse_actions(edev, flow_action))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int qede_flow_spec_to_rule(struct qede_dev *edev,
+ struct qede_arfs_tuple *t,
+ struct ethtool_rx_flow_spec *fs)
+{
+ struct ethtool_rx_flow_spec_input input = {};
+ struct ethtool_rx_flow_rule *flow;
+ __be16 proto;
+ int err = 0;
+
+ if (qede_flow_spec_validate_unused(edev, fs))
+ return -EOPNOTSUPP;
+
+ switch ((fs->flow_type & ~FLOW_EXT)) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ proto = htons(ETH_P_IP);
+ break;
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ proto = htons(ETH_P_IPV6);
+ break;
+ default:
+ DP_VERBOSE(edev, NETIF_MSG_IFUP,
+ "Can't support flow of type %08x\n", fs->flow_type);
+ return -EOPNOTSUPP;
+ }
+
+ input.fs = fs;
+ flow = ethtool_rx_flow_rule_create(&input);
+ if (IS_ERR(flow))
+ return PTR_ERR(flow);
+
+ if (qede_parse_flow_attr(edev, proto, flow->rule, t)) {
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ /* Make sure location is valid and filter isn't already set */
+ err = qede_flow_spec_validate(edev, &flow->rule->action, t,
+ fs->location);
+err_out:
+ ethtool_rx_flow_rule_destroy(flow);
+ return err;
+
+}
+
+int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
+{
+ struct ethtool_rx_flow_spec *fsp = &info->fs;
+ struct qede_arfs_fltr_node *n;
+ struct qede_arfs_tuple t;
+ int min_hlen, rc;
+
+ __qede_lock(edev);
+
+ if (!edev->arfs) {
+ rc = -EPERM;
+ goto unlock;
+ }
+
+ /* Translate the flow specification into something fittign our DB */
+ rc = qede_flow_spec_to_rule(edev, &t, fsp);
+ if (rc)
+ goto unlock;
+
+ if (qede_flow_find_fltr(edev, &t)) {
+ rc = -EINVAL;
+ goto unlock;
+ }
+
+ n = kzalloc(sizeof(*n), GFP_KERNEL);
+ if (!n) {
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ min_hlen = qede_flow_get_min_header_size(&t);
+ n->data = kzalloc(min_hlen, GFP_KERNEL);
+ if (!n->data) {
+ kfree(n);
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ n->sw_id = fsp->location;
+ set_bit(n->sw_id, edev->arfs->arfs_fltr_bmap);
+ n->buf_len = min_hlen;
+
+ memcpy(&n->tuple, &t, sizeof(n->tuple));
+
+ qede_flow_set_destination(edev, n, fsp);
+
+ /* Build a minimal header according to the flow */
+ n->tuple.build_hdr(&n->tuple, n->data);
+
+ rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0);
+ if (rc)
+ goto unlock;
+
+ qede_configure_arfs_fltr(edev, n, n->rxq_id, true);
+ rc = qede_poll_arfs_filter_config(edev, n);
+unlock:
+ __qede_unlock(edev);
+
+ return rc;
+}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index bdf816fe5a16..31b046e24565 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_OK;
}
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+ struct net_device *sb_dev,
+ select_queue_fallback_t fallback)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ int total_txq;
+
+ total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc;
+
+ return QEDE_TSS_COUNT(edev) ?
+ fallback(dev, skb, NULL) % total_txq : 0;
+}
+
/* 8B udp header + 8B base tunnel header + 32B option length */
#define QEDE_MAX_TUN_HDR_LEN 48
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 5a74fcbdbc2b..02a97c659e29 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -133,23 +133,12 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void qede_remove(struct pci_dev *pdev);
static void qede_shutdown(struct pci_dev *pdev);
static void qede_link_update(void *dev, struct qed_link_output *link);
+static void qede_schedule_recovery_handler(void *dev);
+static void qede_recovery_handler(struct qede_dev *edev);
static void qede_get_eth_tlv_data(void *edev, void *data);
static void qede_get_generic_tlv_data(void *edev,
struct qed_generic_tlvs *data);
-/* The qede lock is used to protect driver state change and driver flows that
- * are not reentrant.
- */
-void __qede_lock(struct qede_dev *edev)
-{
- mutex_lock(&edev->qede_lock);
-}
-
-void __qede_unlock(struct qede_dev *edev)
-{
- mutex_unlock(&edev->qede_lock);
-}
-
#ifdef CONFIG_QED_SRIOV
static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos,
__be16 vlan_proto)
@@ -231,6 +220,7 @@ static struct qed_eth_cb_ops qede_ll_ops = {
.arfs_filter_op = qede_arfs_filter_op,
#endif
.link_update = qede_link_update,
+ .schedule_recovery_handler = qede_schedule_recovery_handler,
.get_generic_tlv_data = qede_get_generic_tlv_data,
.get_protocol_tlv_data = qede_get_eth_tlv_data,
},
@@ -631,6 +621,7 @@ static const struct net_device_ops qede_netdev_ops = {
.ndo_open = qede_open,
.ndo_stop = qede_close,
.ndo_start_xmit = qede_start_xmit,
+ .ndo_select_queue = qede_select_queue,
.ndo_set_rx_mode = qede_set_rx_mode,
.ndo_set_mac_address = qede_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -666,6 +657,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
.ndo_open = qede_open,
.ndo_stop = qede_close,
.ndo_start_xmit = qede_start_xmit,
+ .ndo_select_queue = qede_select_queue,
.ndo_set_rx_mode = qede_set_rx_mode,
.ndo_set_mac_address = qede_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -684,6 +676,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
.ndo_open = qede_open,
.ndo_stop = qede_close,
.ndo_start_xmit = qede_start_xmit,
+ .ndo_select_queue = qede_select_queue,
.ndo_set_rx_mode = qede_set_rx_mode,
.ndo_set_mac_address = qede_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -950,11 +943,57 @@ err:
return -ENOMEM;
}
+/* The qede lock is used to protect driver state change and driver flows that
+ * are not reentrant.
+ */
+void __qede_lock(struct qede_dev *edev)
+{
+ mutex_lock(&edev->qede_lock);
+}
+
+void __qede_unlock(struct qede_dev *edev)
+{
+ mutex_unlock(&edev->qede_lock);
+}
+
+/* This version of the lock should be used when acquiring the RTNL lock is also
+ * needed in addition to the internal qede lock.
+ */
+void qede_lock(struct qede_dev *edev)
+{
+ rtnl_lock();
+ __qede_lock(edev);
+}
+
+void qede_unlock(struct qede_dev *edev)
+{
+ __qede_unlock(edev);
+ rtnl_unlock();
+}
+
static void qede_sp_task(struct work_struct *work)
{
struct qede_dev *edev = container_of(work, struct qede_dev,
sp_task.work);
+ /* The locking scheme depends on the specific flag:
+ * In case of QEDE_SP_RECOVERY, acquiring the RTNL lock is required to
+ * ensure that ongoing flows are ended and new ones are not started.
+ * In other cases - only the internal qede lock should be acquired.
+ */
+
+ if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) {
+#ifdef CONFIG_QED_SRIOV
+ /* SRIOV must be disabled outside the lock to avoid a deadlock.
+ * The recovery of the active VFs is currently not supported.
+ */
+ qede_sriov_configure(edev->pdev, 0);
+#endif
+ qede_lock(edev);
+ qede_recovery_handler(edev);
+ qede_unlock(edev);
+ }
+
__qede_lock(edev);
if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags))
@@ -1031,6 +1070,7 @@ static void qede_log_probe(struct qede_dev *edev)
enum qede_probe_mode {
QEDE_PROBE_NORMAL,
+ QEDE_PROBE_RECOVERY,
};
static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
@@ -1051,6 +1091,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
probe_params.dp_module = dp_module;
probe_params.dp_level = dp_level;
probe_params.is_vf = is_vf;
+ probe_params.recov_in_prog = (mode == QEDE_PROBE_RECOVERY);
cdev = qed_ops->common->probe(pdev, &probe_params);
if (!cdev) {
rc = -ENODEV;
@@ -1078,11 +1119,20 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
if (rc)
goto err2;
- edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module,
- dp_level);
- if (!edev) {
- rc = -ENOMEM;
- goto err2;
+ if (mode != QEDE_PROBE_RECOVERY) {
+ edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module,
+ dp_level);
+ if (!edev) {
+ rc = -ENOMEM;
+ goto err2;
+ }
+ } else {
+ struct net_device *ndev = pci_get_drvdata(pdev);
+
+ edev = netdev_priv(ndev);
+ edev->cdev = cdev;
+ memset(&edev->stats, 0, sizeof(edev->stats));
+ memcpy(&edev->dev_info, &dev_info, sizeof(dev_info));
}
if (is_vf)
@@ -1090,28 +1140,31 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
qede_init_ndev(edev);
- rc = qede_rdma_dev_add(edev);
+ rc = qede_rdma_dev_add(edev, (mode == QEDE_PROBE_RECOVERY));
if (rc)
goto err3;
- /* Prepare the lock prior to the registration of the netdev,
- * as once it's registered we might reach flows requiring it
- * [it's even possible to reach a flow needing it directly
- * from there, although it's unlikely].
- */
- INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task);
- mutex_init(&edev->qede_lock);
- rc = register_netdev(edev->ndev);
- if (rc) {
- DP_NOTICE(edev, "Cannot register net-device\n");
- goto err4;
+ if (mode != QEDE_PROBE_RECOVERY) {
+ /* Prepare the lock prior to the registration of the netdev,
+ * as once it's registered we might reach flows requiring it
+ * [it's even possible to reach a flow needing it directly
+ * from there, although it's unlikely].
+ */
+ INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task);
+ mutex_init(&edev->qede_lock);
+
+ rc = register_netdev(edev->ndev);
+ if (rc) {
+ DP_NOTICE(edev, "Cannot register net-device\n");
+ goto err4;
+ }
}
edev->ops->common->set_name(cdev, edev->ndev->name);
/* PTP not supported on VFs */
if (!is_vf)
- qede_ptp_enable(edev, true);
+ qede_ptp_enable(edev, (mode == QEDE_PROBE_NORMAL));
edev->ops->register_ops(cdev, &qede_ll_ops, edev);
@@ -1126,7 +1179,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
return 0;
err4:
- qede_rdma_dev_remove(edev);
+ qede_rdma_dev_remove(edev, (mode == QEDE_PROBE_RECOVERY));
err3:
free_netdev(edev->ndev);
err2:
@@ -1162,6 +1215,7 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id)
enum qede_remove_mode {
QEDE_REMOVE_NORMAL,
+ QEDE_REMOVE_RECOVERY,
};
static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
@@ -1172,15 +1226,19 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
DP_INFO(edev, "Starting qede_remove\n");
- qede_rdma_dev_remove(edev);
- unregister_netdev(ndev);
- cancel_delayed_work_sync(&edev->sp_task);
+ qede_rdma_dev_remove(edev, (mode == QEDE_REMOVE_RECOVERY));
- qede_ptp_disable(edev);
+ if (mode != QEDE_REMOVE_RECOVERY) {
+ unregister_netdev(ndev);
- edev->ops->common->set_power_state(cdev, PCI_D0);
+ cancel_delayed_work_sync(&edev->sp_task);
- pci_set_drvdata(pdev, NULL);
+ edev->ops->common->set_power_state(cdev, PCI_D0);
+
+ pci_set_drvdata(pdev, NULL);
+ }
+
+ qede_ptp_disable(edev);
/* Use global ops since we've freed edev */
qed_ops->common->slowpath_stop(cdev);
@@ -1194,7 +1252,8 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
* [e.g., QED register callbacks] won't break anything when
* accessing the netdevice.
*/
- free_netdev(ndev);
+ if (mode != QEDE_REMOVE_RECOVERY)
+ free_netdev(ndev);
dev_info(&pdev->dev, "Ending qede_remove successfully\n");
}
@@ -1539,6 +1598,58 @@ static int qede_alloc_mem_load(struct qede_dev *edev)
return 0;
}
+static void qede_empty_tx_queue(struct qede_dev *edev,
+ struct qede_tx_queue *txq)
+{
+ unsigned int pkts_compl = 0, bytes_compl = 0;
+ struct netdev_queue *netdev_txq;
+ int rc, len = 0;
+
+ netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id);
+
+ while (qed_chain_get_cons_idx(&txq->tx_pbl) !=
+ qed_chain_get_prod_idx(&txq->tx_pbl)) {
+ DP_VERBOSE(edev, NETIF_MSG_IFDOWN,
+ "Freeing a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n",
+ txq->index, qed_chain_get_cons_idx(&txq->tx_pbl),
+ qed_chain_get_prod_idx(&txq->tx_pbl));
+
+ rc = qede_free_tx_pkt(edev, txq, &len);
+ if (rc) {
+ DP_NOTICE(edev,
+ "Failed to free a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n",
+ txq->index,
+ qed_chain_get_cons_idx(&txq->tx_pbl),
+ qed_chain_get_prod_idx(&txq->tx_pbl));
+ break;
+ }
+
+ bytes_compl += len;
+ pkts_compl++;
+ txq->sw_tx_cons++;
+ }
+
+ netdev_tx_completed_queue(netdev_txq, pkts_compl, bytes_compl);
+}
+
+static void qede_empty_tx_queues(struct qede_dev *edev)
+{
+ int i;
+
+ for_each_queue(i)
+ if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
+ int cos;
+
+ for_each_cos_in_txq(edev, cos) {
+ struct qede_fastpath *fp;
+
+ fp = &edev->fp_array[i];
+ qede_empty_tx_queue(edev,
+ &fp->txq[cos]);
+ }
+ }
+}
+
/* This function inits fp content and resets the SB, RXQ and TXQ structures */
static void qede_init_fp(struct qede_dev *edev)
{
@@ -2053,6 +2164,7 @@ out:
enum qede_unload_mode {
QEDE_UNLOAD_NORMAL,
+ QEDE_UNLOAD_RECOVERY,
};
static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
@@ -2068,7 +2180,8 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
clear_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags);
- edev->state = QEDE_STATE_CLOSED;
+ if (mode != QEDE_UNLOAD_RECOVERY)
+ edev->state = QEDE_STATE_CLOSED;
qede_rdma_dev_event_close(edev);
@@ -2076,17 +2189,20 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
netif_tx_disable(edev->ndev);
netif_carrier_off(edev->ndev);
- /* Reset the link */
- memset(&link_params, 0, sizeof(link_params));
- link_params.link_up = false;
- edev->ops->common->set_link(edev->cdev, &link_params);
- rc = qede_stop_queues(edev);
- if (rc) {
- qede_sync_free_irqs(edev);
- goto out;
- }
+ if (mode != QEDE_UNLOAD_RECOVERY) {
+ /* Reset the link */
+ memset(&link_params, 0, sizeof(link_params));
+ link_params.link_up = false;
+ edev->ops->common->set_link(edev->cdev, &link_params);
- DP_INFO(edev, "Stopped Queues\n");
+ rc = qede_stop_queues(edev);
+ if (rc) {
+ qede_sync_free_irqs(edev);
+ goto out;
+ }
+
+ DP_INFO(edev, "Stopped Queues\n");
+ }
qede_vlan_mark_nonconfigured(edev);
edev->ops->fastpath_stop(edev->cdev);
@@ -2102,18 +2218,26 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
qede_napi_disable_remove(edev);
+ if (mode == QEDE_UNLOAD_RECOVERY)
+ qede_empty_tx_queues(edev);
+
qede_free_mem_load(edev);
qede_free_fp_array(edev);
out:
if (!is_locked)
__qede_unlock(edev);
+
+ if (mode != QEDE_UNLOAD_RECOVERY)
+ DP_NOTICE(edev, "Link is down\n");
+
DP_INFO(edev, "Ending qede unload\n");
}
enum qede_load_mode {
QEDE_LOAD_NORMAL,
QEDE_LOAD_RELOAD,
+ QEDE_LOAD_RECOVERY,
};
static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
@@ -2293,6 +2417,77 @@ static void qede_link_update(void *dev, struct qed_link_output *link)
}
}
+static void qede_schedule_recovery_handler(void *dev)
+{
+ struct qede_dev *edev = dev;
+
+ if (edev->state == QEDE_STATE_RECOVERY) {
+ DP_NOTICE(edev,
+ "Avoid scheduling a recovery handling since already in recovery state\n");
+ return;
+ }
+
+ set_bit(QEDE_SP_RECOVERY, &edev->sp_flags);
+ schedule_delayed_work(&edev->sp_task, 0);
+
+ DP_INFO(edev, "Scheduled a recovery handler\n");
+}
+
+static void qede_recovery_failed(struct qede_dev *edev)
+{
+ netdev_err(edev->ndev, "Recovery handling has failed. Power cycle is needed.\n");
+
+ netif_device_detach(edev->ndev);
+
+ if (edev->cdev)
+ edev->ops->common->set_power_state(edev->cdev, PCI_D3hot);
+}
+
+static void qede_recovery_handler(struct qede_dev *edev)
+{
+ u32 curr_state = edev->state;
+ int rc;
+
+ DP_NOTICE(edev, "Starting a recovery process\n");
+
+ /* No need to acquire first the qede_lock since is done by qede_sp_task
+ * before calling this function.
+ */
+ edev->state = QEDE_STATE_RECOVERY;
+
+ edev->ops->common->recovery_prolog(edev->cdev);
+
+ if (curr_state == QEDE_STATE_OPEN)
+ qede_unload(edev, QEDE_UNLOAD_RECOVERY, true);
+
+ __qede_remove(edev->pdev, QEDE_REMOVE_RECOVERY);
+
+ rc = __qede_probe(edev->pdev, edev->dp_module, edev->dp_level,
+ IS_VF(edev), QEDE_PROBE_RECOVERY);
+ if (rc) {
+ edev->cdev = NULL;
+ goto err;
+ }
+
+ if (curr_state == QEDE_STATE_OPEN) {
+ rc = qede_load(edev, QEDE_LOAD_RECOVERY, true);
+ if (rc)
+ goto err;
+
+ qede_config_rx_mode(edev->ndev);
+ udp_tunnel_get_rx_info(edev->ndev);
+ }
+
+ edev->state = curr_state;
+
+ DP_NOTICE(edev, "Recovery handling is done\n");
+
+ return;
+
+err:
+ qede_recovery_failed(edev);
+}
+
static bool qede_is_txq_full(struct qede_dev *edev, struct qede_tx_queue *txq)
{
struct netdev_queue *netdev_txq;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_rdma.c b/drivers/net/ethernet/qlogic/qede/qede_rdma.c
index 1900bf7e67d1..ffabc2d2f082 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_rdma.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_rdma.c
@@ -50,6 +50,8 @@ static void _qede_rdma_dev_add(struct qede_dev *edev)
if (!qedr_drv)
return;
+ /* Leftovers from previous error recovery */
+ edev->rdma_info.exp_recovery = false;
edev->rdma_info.qedr_dev = qedr_drv->add(edev->cdev, edev->pdev,
edev->ndev);
}
@@ -87,21 +89,26 @@ static void qede_rdma_destroy_wq(struct qede_dev *edev)
destroy_workqueue(edev->rdma_info.rdma_wq);
}
-int qede_rdma_dev_add(struct qede_dev *edev)
+int qede_rdma_dev_add(struct qede_dev *edev, bool recovery)
{
- int rc = 0;
+ int rc;
- if (qede_rdma_supported(edev)) {
- rc = qede_rdma_create_wq(edev);
- if (rc)
- return rc;
+ if (!qede_rdma_supported(edev))
+ return 0;
- INIT_LIST_HEAD(&edev->rdma_info.entry);
- mutex_lock(&qedr_dev_list_lock);
- list_add_tail(&edev->rdma_info.entry, &qedr_dev_list);
- _qede_rdma_dev_add(edev);
- mutex_unlock(&qedr_dev_list_lock);
- }
+ /* Cannot start qedr while recovering since it wasn't fully stopped */
+ if (recovery)
+ return 0;
+
+ rc = qede_rdma_create_wq(edev);
+ if (rc)
+ return rc;
+
+ INIT_LIST_HEAD(&edev->rdma_info.entry);
+ mutex_lock(&qedr_dev_list_lock);
+ list_add_tail(&edev->rdma_info.entry, &qedr_dev_list);
+ _qede_rdma_dev_add(edev);
+ mutex_unlock(&qedr_dev_list_lock);
return rc;
}
@@ -110,19 +117,30 @@ static void _qede_rdma_dev_remove(struct qede_dev *edev)
{
if (qedr_drv && qedr_drv->remove && edev->rdma_info.qedr_dev)
qedr_drv->remove(edev->rdma_info.qedr_dev);
- edev->rdma_info.qedr_dev = NULL;
}
-void qede_rdma_dev_remove(struct qede_dev *edev)
+void qede_rdma_dev_remove(struct qede_dev *edev, bool recovery)
{
if (!qede_rdma_supported(edev))
return;
- qede_rdma_destroy_wq(edev);
- mutex_lock(&qedr_dev_list_lock);
- _qede_rdma_dev_remove(edev);
- list_del(&edev->rdma_info.entry);
- mutex_unlock(&qedr_dev_list_lock);
+ /* Cannot remove qedr while recovering since it wasn't fully stopped */
+ if (!recovery) {
+ qede_rdma_destroy_wq(edev);
+ mutex_lock(&qedr_dev_list_lock);
+ if (!edev->rdma_info.exp_recovery)
+ _qede_rdma_dev_remove(edev);
+ edev->rdma_info.qedr_dev = NULL;
+ list_del(&edev->rdma_info.entry);
+ mutex_unlock(&qedr_dev_list_lock);
+ } else {
+ if (!edev->rdma_info.exp_recovery) {
+ mutex_lock(&qedr_dev_list_lock);
+ _qede_rdma_dev_remove(edev);
+ mutex_unlock(&qedr_dev_list_lock);
+ }
+ edev->rdma_info.exp_recovery = true;
+ }
}
static void _qede_rdma_dev_open(struct qede_dev *edev)
@@ -204,7 +222,8 @@ void qede_rdma_unregister_driver(struct qedr_driver *drv)
mutex_lock(&qedr_dev_list_lock);
list_for_each_entry(edev, &qedr_dev_list, rdma_info.entry) {
- if (edev->rdma_info.qedr_dev)
+ /* If device has experienced recovery it was already removed */
+ if (edev->rdma_info.qedr_dev && !edev->rdma_info.exp_recovery)
_qede_rdma_dev_remove(edev);
}
qedr_drv = NULL;
@@ -284,6 +303,10 @@ static void qede_rdma_add_event(struct qede_dev *edev,
{
struct qede_rdma_event_work *event_node;
+ /* If a recovery was experienced avoid adding the event */
+ if (edev->rdma_info.exp_recovery)
+ return;
+
if (!edev->rdma_info.qedr_dev)
return;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index d344e9d43832..af38d3d73291 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -434,14 +434,14 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
*(tx_ring->hw_consumer) = 0;
rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
- rq_addr = dma_zalloc_coherent(&adapter->pdev->dev, rq_size,
- &rq_phys_addr, GFP_KERNEL);
+ rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+ &rq_phys_addr, GFP_KERNEL);
if (!rq_addr)
return -ENOMEM;
rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
- rsp_addr = dma_zalloc_coherent(&adapter->pdev->dev, rsp_size,
- &rsp_phys_addr, GFP_KERNEL);
+ rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+ &rsp_phys_addr, GFP_KERNEL);
if (!rsp_addr) {
err = -ENOMEM;
goto out_free_rq;
@@ -855,8 +855,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args cmd;
size_t nic_size = sizeof(struct qlcnic_info_le);
- nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
+ nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+ &nic_dma_t, GFP_KERNEL);
if (!nic_info_addr)
return -ENOMEM;
@@ -909,8 +909,8 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return err;
- nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
+ nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+ &nic_dma_t, GFP_KERNEL);
if (!nic_info_addr)
return -ENOMEM;
@@ -964,8 +964,8 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
void *pci_info_addr;
int err = 0, i;
- pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size,
- &pci_info_dma_t, GFP_KERNEL);
+ pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
+ &pci_info_dma_t, GFP_KERNEL);
if (!pci_info_addr)
return -ENOMEM;
@@ -1078,8 +1078,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
return -EIO;
}
- stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
+ stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+ &stats_dma_t, GFP_KERNEL);
if (!stats_addr)
return -ENOMEM;
@@ -1134,8 +1134,8 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
if (mac_stats == NULL)
return -ENOMEM;
- stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
+ stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+ &stats_dma_t, GFP_KERNEL);
if (!stats_addr)
return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 16d0479f6891..7a873002e626 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -396,7 +396,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *netdev,
- const unsigned char *addr, u16 vid, u16 flags)
+ const unsigned char *addr, u16 vid, u16 flags,
+ struct netlink_ext_ack *extack)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err = 0;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
index 5edbd532127d..a6886cc5654c 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
@@ -249,8 +249,8 @@ static void ql_update_stats(struct ql_adapter *qdev)
spin_lock(&qdev->stats_lock);
if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) {
- netif_err(qdev, drv, qdev->ndev,
- "Couldn't get xgmac sem.\n");
+ netif_err(qdev, drv, qdev->ndev,
+ "Couldn't get xgmac sem.\n");
goto quit;
}
/*
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 059ba9429e51..096515c27263 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -1159,10 +1159,10 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
map = lbq_desc->p.pg_chunk.map +
lbq_desc->p.pg_chunk.offset;
- dma_unmap_addr_set(lbq_desc, mapaddr, map);
+ dma_unmap_addr_set(lbq_desc, mapaddr, map);
dma_unmap_len_set(lbq_desc, maplen,
rx_ring->lbq_buf_size);
- *lbq_desc->addr = cpu_to_le64(map);
+ *lbq_desc->addr = cpu_to_le64(map);
pci_dma_sync_single_for_device(qdev->pdev, map,
rx_ring->lbq_buf_size,
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index 031f6e6ee9c1..20d2400ad300 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -776,7 +776,7 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt)
8 + 2 * 8; /* 8 byte per one Tx and two Rx rings */
ring_header->used = 0;
- ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size,
+ ring_header->v_addr = dma_alloc_coherent(dev, ring_header->size,
&ring_header->dma_addr,
GFP_KERNEL);
if (!ring_header->v_addr)
@@ -1204,7 +1204,7 @@ void emac_mac_tx_process(struct emac_adapter *adpt, struct emac_tx_queue *tx_q)
if (tpbuf->skb) {
pkts_compl++;
bytes_compl += tpbuf->skb->len;
- dev_kfree_skb_irq(tpbuf->skb);
+ dev_consume_skb_irq(tpbuf->skb);
tpbuf->skb = NULL;
}
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 44f6e4873aad..4f910c4f67b0 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -691,7 +691,7 @@ static void cp_tx (struct cp_private *cp)
}
bytes_compl += skb->len;
pkts_compl++;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
cp->tx_skb[tx_tail] = NULL;
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index 7e011c1c1e6e..cfb67b746595 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -454,14 +454,14 @@ static void hardware_init(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
long ioaddr = dev->base_addr;
- int i;
+ int i;
/* Turn off the printer multiplexer on the 8012. */
for (i = 0; i < 8; i++)
outb(mux_8012[i], ioaddr + PAR_DATA);
write_reg_high(ioaddr, CMR1, CMR1h_RESET);
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++)
write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
write_reg_high(ioaddr, CMR2, lp->addr_mode);
@@ -471,15 +471,15 @@ static void hardware_init(struct net_device *dev)
(read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
}
- write_reg(ioaddr, CMR2, CMR2_IRQOUT);
- write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
/* Enable the interrupt line from the serial port. */
outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
/* Unmask the interesting interrupts. */
- write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
- write_reg_high(ioaddr, IMR, ISRh_RxErr);
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr);
lp->tx_unit_busy = 0;
lp->pac_cnt_in_tx_buf = 0;
@@ -610,10 +610,12 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance)
write_reg(ioaddr, CMR2, CMR2_NULL);
write_reg(ioaddr, IMR, 0);
- if (net_debug > 5) printk(KERN_DEBUG "%s: In interrupt ", dev->name);
- while (--boguscount > 0) {
+ if (net_debug > 5)
+ printk(KERN_DEBUG "%s: In interrupt ", dev->name);
+ while (--boguscount > 0) {
int status = read_nibble(ioaddr, ISR);
- if (net_debug > 5) printk("loop status %02x..", status);
+ if (net_debug > 5)
+ printk("loop status %02x..", status);
if (status & (ISR_RxOK<<3)) {
handled = 1;
@@ -640,7 +642,8 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance)
} while (--boguscount > 0);
} else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) {
handled = 1;
- if (net_debug > 6) printk("handling Tx done..");
+ if (net_debug > 6)
+ printk("handling Tx done..");
/* Clear the Tx interrupt. We should check for too many failures
and reinitialize the adapter. */
write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK);
@@ -680,7 +683,7 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance)
break;
} else
break;
- }
+ }
/* This following code fixes a rare (and very difficult to track down)
problem where the adapter forgets its ethernet address. */
@@ -694,7 +697,7 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance)
}
/* Tell the adapter that it can go back to using the output line as IRQ. */
- write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
/* Enable the physical interrupt line, which is sure to be low until.. */
outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
/* .. we enable the interrupt sources. */
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 298930d39b79..c29dde064078 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -205,6 +205,8 @@ enum cfg_version {
};
static const struct pci_device_id rtl8169_pci_tbl[] = {
+ { PCI_VDEVICE(REALTEK, 0x2502), RTL_CFG_1 },
+ { PCI_VDEVICE(REALTEK, 0x2600), RTL_CFG_1 },
{ PCI_VDEVICE(REALTEK, 0x8129), RTL_CFG_0 },
{ PCI_VDEVICE(REALTEK, 0x8136), RTL_CFG_2 },
{ PCI_VDEVICE(REALTEK, 0x8161), RTL_CFG_1 },
@@ -227,7 +229,6 @@ static const struct pci_device_id rtl8169_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
-static int use_dac = -1;
static struct {
u32 msg_enable;
} debug = { -1 };
@@ -637,6 +638,7 @@ struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev;
struct net_device *dev;
+ struct phy_device *phydev;
struct napi_struct napi;
u32 msg_enable;
u16 mac_version;
@@ -677,12 +679,12 @@ struct rtl8169_private {
} wk;
unsigned supports_gmii:1;
- struct mii_bus *mii_bus;
dma_addr_t counters_phys_addr;
struct rtl8169_counters *counters;
struct rtl8169_tc_offsets tc_offset;
u32 saved_wolopts;
+ const char *fw_name;
struct rtl_fw {
const struct firmware *fw;
@@ -695,17 +697,15 @@ struct rtl8169_private {
size_t size;
} phy_action;
} *rtl_fw;
-#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
u32 ocp_base;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param(use_dac, int, 0);
-MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
module_param_named(debug, debug.msg_enable, int, 0);
MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_SOFTDEP("pre: realtek");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_8168D_1);
MODULE_FIRMWARE(FIRMWARE_8168D_2);
@@ -742,6 +742,16 @@ static void rtl_unlock_work(struct rtl8169_private *tp)
mutex_unlock(&tp->wk.mutex);
}
+static void rtl_lock_config_regs(struct rtl8169_private *tp)
+{
+ RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+}
+
+static void rtl_unlock_config_regs(struct rtl8169_private *tp)
+{
+ RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+}
+
static void rtl_tx_performance_tweak(struct rtl8169_private *tp, u16 force)
{
pcie_capability_clear_and_set_word(tp->pci_dev, PCI_EXP_DEVCTL,
@@ -1275,11 +1285,6 @@ static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
}
-static u16 rtl_get_events(struct rtl8169_private *tp)
-{
- return RTL_R16(tp, IntrStatus);
-}
-
static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
{
RTL_W16(tp, IntrStatus, bits);
@@ -1310,7 +1315,7 @@ static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
static void rtl_link_chg_patch(struct rtl8169_private *tp)
{
struct net_device *dev = tp->dev;
- struct phy_device *phydev = dev->phydev;
+ struct phy_device *phydev = tp->phydev;
if (!netif_running(dev))
return;
@@ -1366,41 +1371,6 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
-static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
-{
- u8 options;
- u32 wolopts = 0;
-
- options = RTL_R8(tp, Config1);
- if (!(options & PMEnable))
- return 0;
-
- options = RTL_R8(tp, Config3);
- if (options & LinkUp)
- wolopts |= WAKE_PHY;
- switch (tp->mac_version) {
- case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
- if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
- wolopts |= WAKE_MAGIC;
- break;
- default:
- if (options & MagicPacket)
- wolopts |= WAKE_MAGIC;
- break;
- }
-
- options = RTL_R8(tp, Config5);
- if (options & UWF)
- wolopts |= WAKE_UCAST;
- if (options & BWF)
- wolopts |= WAKE_BCAST;
- if (options & MWF)
- wolopts |= WAKE_MCAST;
-
- return wolopts;
-}
-
static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -1428,7 +1398,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
};
u8 options;
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
@@ -1476,7 +1446,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
break;
}
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
device_set_wakeup_enable(tp_to_dev(tp), wolopts);
}
@@ -1505,11 +1475,6 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return 0;
}
-static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
-{
- return rtl_chip_infos[tp->mac_version].fw_name;
-}
-
static void rtl8169_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -1519,7 +1484,7 @@ static void rtl8169_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, MODULENAME, sizeof(info->driver));
strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
- if (!IS_ERR_OR_NULL(rtl_fw))
+ if (rtl_fw)
strlcpy(info->fw_version, rtl_fw->version,
sizeof(info->fw_version));
}
@@ -1679,11 +1644,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp)
static bool rtl8169_update_counters(struct rtl8169_private *tp)
{
+ u8 val = RTL_R8(tp, ChipCmd);
+
/*
* Some chips are unable to dump tally counters when the receiver
- * is disabled.
+ * is disabled. If 0xff chip may be in a PCI power-save state.
*/
- if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0)
+ if (!(val & CmdRxEnb) || val == 0xff)
return true;
return rtl8169_do_counters(tp, CounterDump);
@@ -1982,6 +1949,196 @@ static int rtl_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
return 0;
}
+static int rtl_get_eee_supp(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+ int ret;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
+ case RTL_GIGA_MAC_VER_38:
+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+ break;
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+ phy_write(phydev, 0x1f, 0x0a5c);
+ ret = phy_read(phydev, 0x12);
+ phy_write(phydev, 0x1f, 0x0000);
+ break;
+ default:
+ ret = -EPROTONOSUPPORT;
+ break;
+ }
+
+ return ret;
+}
+
+static int rtl_get_eee_lpadv(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+ int ret;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
+ case RTL_GIGA_MAC_VER_38:
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
+ break;
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+ phy_write(phydev, 0x1f, 0x0a5d);
+ ret = phy_read(phydev, 0x11);
+ phy_write(phydev, 0x1f, 0x0000);
+ break;
+ default:
+ ret = -EPROTONOSUPPORT;
+ break;
+ }
+
+ return ret;
+}
+
+static int rtl_get_eee_adv(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+ int ret;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
+ case RTL_GIGA_MAC_VER_38:
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
+ break;
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+ phy_write(phydev, 0x1f, 0x0a5d);
+ ret = phy_read(phydev, 0x10);
+ phy_write(phydev, 0x1f, 0x0000);
+ break;
+ default:
+ ret = -EPROTONOSUPPORT;
+ break;
+ }
+
+ return ret;
+}
+
+static int rtl_set_eee_adv(struct rtl8169_private *tp, int val)
+{
+ struct phy_device *phydev = tp->phydev;
+ int ret = 0;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
+ case RTL_GIGA_MAC_VER_38:
+ ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+ break;
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+ phy_write(phydev, 0x1f, 0x0a5d);
+ phy_write(phydev, 0x10, val);
+ phy_write(phydev, 0x1f, 0x0000);
+ break;
+ default:
+ ret = -EPROTONOSUPPORT;
+ break;
+ }
+
+ return ret;
+}
+
+static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct device *d = tp_to_dev(tp);
+ int ret;
+
+ pm_runtime_get_noresume(d);
+
+ if (!pm_runtime_active(d)) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* Get Supported EEE */
+ ret = rtl_get_eee_supp(tp);
+ if (ret < 0)
+ goto out;
+ data->supported = mmd_eee_cap_to_ethtool_sup_t(ret);
+
+ /* Get advertisement EEE */
+ ret = rtl_get_eee_adv(tp);
+ if (ret < 0)
+ goto out;
+ data->advertised = mmd_eee_adv_to_ethtool_adv_t(ret);
+ data->eee_enabled = !!data->advertised;
+
+ /* Get LP advertisement EEE */
+ ret = rtl_get_eee_lpadv(tp);
+ if (ret < 0)
+ goto out;
+ data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(ret);
+ data->eee_active = !!(data->advertised & data->lp_advertised);
+out:
+ pm_runtime_put_noidle(d);
+ return ret < 0 ? ret : 0;
+}
+
+static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct device *d = tp_to_dev(tp);
+ int old_adv, adv = 0, cap, ret;
+
+ pm_runtime_get_noresume(d);
+
+ if (!dev->phydev || !pm_runtime_active(d)) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (dev->phydev->autoneg == AUTONEG_DISABLE ||
+ dev->phydev->duplex != DUPLEX_FULL) {
+ ret = -EPROTONOSUPPORT;
+ goto out;
+ }
+
+ /* Get Supported EEE */
+ ret = rtl_get_eee_supp(tp);
+ if (ret < 0)
+ goto out;
+ cap = ret;
+
+ ret = rtl_get_eee_adv(tp);
+ if (ret < 0)
+ goto out;
+ old_adv = ret;
+
+ if (data->eee_enabled) {
+ adv = !data->advertised ? cap :
+ ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
+ /* Mask prohibited EEE modes */
+ adv &= ~dev->phydev->eee_broken_modes;
+ }
+
+ if (old_adv != adv) {
+ ret = rtl_set_eee_adv(tp, adv);
+ if (ret < 0)
+ goto out;
+
+ /* Restart autonegotiation so the new modes get sent to the
+ * link partner.
+ */
+ ret = phy_restart_aneg(dev->phydev);
+ }
+
+out:
+ pm_runtime_put_noidle(d);
+ return ret < 0 ? ret : 0;
+}
+
static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
@@ -1998,10 +2155,20 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_ethtool_stats = rtl8169_get_ethtool_stats,
.get_ts_info = ethtool_op_get_ts_info,
.nway_reset = phy_ethtool_nway_reset,
+ .get_eee = rtl8169_get_eee,
+ .set_eee = rtl8169_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
+static void rtl_enable_eee(struct rtl8169_private *tp)
+{
+ int supported = rtl_get_eee_supp(tp);
+
+ if (supported > 0)
+ rtl_set_eee_adv(tp, supported);
+}
+
static void rtl8169_get_mac_version(struct rtl8169_private *tp)
{
/*
@@ -2194,7 +2361,7 @@ static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
if (fw->size % FW_OPCODE_SIZE)
goto out;
- strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
+ strlcpy(version, tp->fw_name, RTL_VER_SIZE);
pa->code = (__le32 *)fw->data;
pa->size = fw->size / FW_OPCODE_SIZE;
@@ -2369,20 +2536,18 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
static void rtl_release_firmware(struct rtl8169_private *tp)
{
- if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
+ if (tp->rtl_fw) {
release_firmware(tp->rtl_fw->fw);
kfree(tp->rtl_fw);
+ tp->rtl_fw = NULL;
}
- tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
}
static void rtl_apply_firmware(struct rtl8169_private *tp)
{
- struct rtl_fw *rtl_fw = tp->rtl_fw;
-
/* TODO: release firmware once rtl_phy_write_fw signals failures. */
- if (!IS_ERR_OR_NULL(rtl_fw))
- rtl_phy_write_fw(tp, rtl_fw);
+ if (tp->rtl_fw)
+ rtl_phy_write_fw(tp, tp->rtl_fw);
}
static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -2393,6 +2558,33 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
rtl_apply_firmware(tp);
}
+static void rtl8168_config_eee_mac(struct rtl8169_private *tp)
+{
+ rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC);
+}
+
+static void rtl8168f_config_eee_phy(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+
+ phy_write(phydev, 0x1f, 0x0007);
+ phy_write(phydev, 0x1e, 0x0020);
+ phy_set_bits(phydev, 0x15, BIT(8));
+
+ phy_write(phydev, 0x1f, 0x0005);
+ phy_write(phydev, 0x05, 0x8b85);
+ phy_set_bits(phydev, 0x06, BIT(13));
+
+ phy_write(phydev, 0x1f, 0x0000);
+}
+
+static void rtl8168g_config_eee_phy(struct rtl8169_private *tp)
+{
+ phy_write(tp->phydev, 0x1f, 0x0a43);
+ phy_set_bits(tp->phydev, 0x11, BIT(4));
+ phy_write(tp->phydev, 0x1f, 0x0000);
+}
+
static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3160,22 +3352,8 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
- /* EEE setting */
- rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC);
- rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b85);
- rtl_w0w1_phy(tp, 0x06, 0x2000, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0004);
- rtl_writephy(tp, 0x1f, 0x0007);
- rtl_writephy(tp, 0x1e, 0x0020);
- rtl_w0w1_phy(tp, 0x15, 0x0100, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0002);
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_writephy(tp, 0x0d, 0x0007);
- rtl_writephy(tp, 0x0e, 0x003c);
- rtl_writephy(tp, 0x0d, 0x4007);
- rtl_writephy(tp, 0x0e, 0x0006);
- rtl_writephy(tp, 0x0d, 0x0000);
+ rtl8168f_config_eee_phy(tp);
+ rtl_enable_eee(tp);
/* Green feature */
rtl_writephy(tp, 0x1f, 0x0003);
@@ -3210,6 +3388,9 @@ static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x05, 0x8b86);
rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ rtl8168f_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3343,22 +3524,6 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x06, 0x8000, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
- /* eee setting */
- rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
- rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b85);
- rtl_w0w1_phy(tp, 0x06, 0x0000, 0x2000);
- rtl_writephy(tp, 0x1f, 0x0004);
- rtl_writephy(tp, 0x1f, 0x0007);
- rtl_writephy(tp, 0x1e, 0x0020);
- rtl_w0w1_phy(tp, 0x15, 0x0000, 0x0100);
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_writephy(tp, 0x0d, 0x0007);
- rtl_writephy(tp, 0x0e, 0x003c);
- rtl_writephy(tp, 0x0d, 0x4007);
- rtl_writephy(tp, 0x0e, 0x0000);
- rtl_writephy(tp, 0x0d, 0x0000);
-
/* Green feature */
rtl_writephy(tp, 0x1f, 0x0003);
rtl_w0w1_phy(tp, 0x19, 0x0000, 0x0001);
@@ -3366,6 +3531,30 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
}
+static void rtl8168g_disable_aldps(struct rtl8169_private *tp)
+{
+ phy_write(tp->phydev, 0x1f, 0x0a43);
+ phy_clear_bits(tp->phydev, 0x10, BIT(2));
+}
+
+static void rtl8168g_phy_adjust_10m_aldps(struct rtl8169_private *tp)
+{
+ struct phy_device *phydev = tp->phydev;
+
+ phy_write(phydev, 0x1f, 0x0bcc);
+ phy_clear_bits(phydev, 0x14, BIT(8));
+
+ phy_write(phydev, 0x1f, 0x0a44);
+ phy_set_bits(phydev, 0x11, BIT(7) | BIT(6));
+
+ phy_write(phydev, 0x1f, 0x0a43);
+ phy_write(phydev, 0x13, 0x8084);
+ phy_clear_bits(phydev, 0x14, BIT(14) | BIT(13));
+ phy_set_bits(phydev, 0x10, BIT(12) | BIT(1) | BIT(0));
+
+ phy_write(phydev, 0x1f, 0x0000);
+}
+
static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
{
rtl_apply_firmware(tp);
@@ -3392,14 +3581,7 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0a44);
rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0bcc);
- rtl_w0w1_phy(tp, 0x14, 0x0100, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0a44);
- rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0a43);
- rtl_writephy(tp, 0x13, 0x8084);
- rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
- rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
+ rtl8168g_phy_adjust_10m_aldps(tp);
/* EEE auto-fallback function */
rtl_writephy(tp, 0x1f, 0x0a4b);
@@ -3424,17 +3606,16 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x14, 0x9065);
rtl_writephy(tp, 0x14, 0x1065);
- /* Check ALDPS bit, disable it if enabled */
- rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
- rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
-
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_disable_aldps(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
{
rtl_apply_firmware(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3539,12 +3720,9 @@ static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x11, 0x0000, 0x0080);
rtl_writephy(tp, 0x1f, 0x0000);
- /* Check ALDPS bit, disable it if enabled */
- rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
- rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
-
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_disable_aldps(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3612,12 +3790,9 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x11, 0x0000, 0x0080);
rtl_writephy(tp, 0x1f, 0x0000);
- /* Check ALDPS bit, disable it if enabled */
- rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
- rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
-
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_disable_aldps(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3627,16 +3802,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
- /* patch 10M & ALDPS */
- rtl_writephy(tp, 0x1f, 0x0bcc);
- rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
- rtl_writephy(tp, 0x1f, 0x0a44);
- rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0a43);
- rtl_writephy(tp, 0x13, 0x8084);
- rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
- rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_phy_adjust_10m_aldps(tp);
/* Enable EEE auto-fallback function */
rtl_writephy(tp, 0x1f, 0x0a4b);
@@ -3654,26 +3820,14 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000);
rtl_writephy(tp, 0x1f, 0x0000);
- /* Check ALDPS bit, disable it if enabled */
- rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
- rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
-
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_disable_aldps(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
{
- /* patch 10M & ALDPS */
- rtl_writephy(tp, 0x1f, 0x0bcc);
- rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
- rtl_writephy(tp, 0x1f, 0x0a44);
- rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0a43);
- rtl_writephy(tp, 0x13, 0x8084);
- rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
- rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_phy_adjust_10m_aldps(tp);
/* Enable UC LPF tune function */
rtl_writephy(tp, 0x1f, 0x0a43);
@@ -3745,12 +3899,9 @@ static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x14, 0x1065);
rtl_writephy(tp, 0x1f, 0x0000);
- /* Check ALDPS bit, disable it if enabled */
- rtl_writephy(tp, 0x1f, 0x0a43);
- if (rtl_readphy(tp, 0x10) & 0x0004)
- rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
-
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168g_disable_aldps(tp);
+ rtl8168g_config_eee_phy(tp);
+ rtl_enable_eee(tp);
}
static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
@@ -3989,24 +4140,24 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
}
/* We may have called phy_speed_down before */
- phy_speed_up(dev->phydev);
+ phy_speed_up(tp->phydev);
- genphy_soft_reset(dev->phydev);
+ genphy_soft_reset(tp->phydev);
/* It was reported that several chips end up with 10MBit/Half on a
* 1GBit link after resuming from S3. For whatever reason the PHY on
* these chips doesn't properly start a renegotiation when soft-reset.
* Explicitly requesting a renegotiation fixes this.
*/
- if (dev->phydev->autoneg == AUTONEG_ENABLE)
- phy_restart_aneg(dev->phydev);
+ if (tp->phydev->autoneg == AUTONEG_ENABLE)
+ phy_restart_aneg(tp->phydev);
}
static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
{
rtl_lock_work(tp);
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
RTL_W32(tp, MAC4, addr[4] | addr[5] << 8);
RTL_R32(tp, MAC4);
@@ -4017,7 +4168,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
if (tp->mac_version == RTL_GIGA_MAC_VER_34)
rtl_rar_exgmac_set(tp, addr);
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
rtl_unlock_work(tp);
}
@@ -4044,10 +4195,12 @@ static int rtl_set_mac_address(struct net_device *dev, void *p)
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
if (!netif_running(dev))
return -ENODEV;
- return phy_mii_ioctl(dev->phydev, ifr, cmd);
+ return phy_mii_ioctl(tp->phydev, ifr, cmd);
}
static void rtl_init_mdio_ops(struct rtl8169_private *tp)
@@ -4094,22 +4247,6 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
}
}
-static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
-{
- struct phy_device *phydev;
-
- if (!__rtl8169_get_wol(tp))
- return false;
-
- /* phydev may not be attached to netdevice */
- phydev = mdiobus_get_phy(tp->mii_bus, 0);
-
- phy_speed_down(phydev, false);
- rtl_wol_suspend_quirk(tp);
-
- return true;
-}
-
static void r8168_pll_power_down(struct rtl8169_private *tp)
{
if (r8168_check_dash(tp))
@@ -4119,8 +4256,11 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
tp->mac_version == RTL_GIGA_MAC_VER_33)
rtl_ephy_write(tp, 0x19, 0xff64);
- if (rtl_wol_pll_power_down(tp))
+ if (device_may_wakeup(tp_to_dev(tp))) {
+ phy_speed_down(tp->phydev, false);
+ rtl_wol_suspend_quirk(tp);
return;
+ }
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33:
@@ -4173,7 +4313,7 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
break;
}
- phy_resume(tp->dev->phydev);
+ phy_resume(tp->phydev);
/* give MAC/PHY some time to resume */
msleep(20);
}
@@ -4229,18 +4369,18 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
{
if (tp->jumbo_ops.enable) {
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
tp->jumbo_ops.enable(tp);
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
}
}
static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
{
if (tp->jumbo_ops.disable) {
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
tp->jumbo_ops.disable(tp);
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
}
}
@@ -4373,21 +4513,20 @@ static void rtl_hw_reset(struct rtl8169_private *tp)
rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
}
-static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
+static void rtl_request_firmware(struct rtl8169_private *tp)
{
struct rtl_fw *rtl_fw;
- const char *name;
int rc = -ENOMEM;
- name = rtl_lookup_firmware_name(tp);
- if (!name)
- goto out_no_firmware;
+ /* firmware loaded already or no firmware available */
+ if (tp->rtl_fw || !tp->fw_name)
+ return;
rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
if (!rtl_fw)
goto err_warn;
- rc = request_firmware(&rtl_fw->fw, name, tp_to_dev(tp));
+ rc = request_firmware(&rtl_fw->fw, tp->fw_name, tp_to_dev(tp));
if (rc < 0)
goto err_free;
@@ -4396,7 +4535,7 @@ static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
goto err_release_firmware;
tp->rtl_fw = rtl_fw;
-out:
+
return;
err_release_firmware:
@@ -4405,16 +4544,7 @@ err_free:
kfree(rtl_fw);
err_warn:
netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
- name, rc);
-out_no_firmware:
- tp->rtl_fw = NULL;
- goto out;
-}
-
-static void rtl_request_firmware(struct rtl8169_private *tp)
-{
- if (IS_ERR(tp->rtl_fw))
- rtl_request_uncached_firmware(tp);
+ tp->fw_name, rc);
}
static void rtl_rx_close(struct rtl8169_private *tp)
@@ -4561,13 +4691,13 @@ static void rtl_set_rx_mode(struct net_device *dev)
static void rtl_hw_start(struct rtl8169_private *tp)
{
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
tp->hw_start(tp);
rtl_set_rx_max_size(tp);
rtl_set_rx_tx_desc_registers(tp);
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
RTL_R8(tp, IntrMask);
@@ -4691,18 +4821,10 @@ static void rtl_enable_clock_request(struct rtl8169_private *tp)
PCI_EXP_LNKCTL_CLKREQ_EN);
}
-static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable)
+static void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp)
{
- u8 data;
-
- data = RTL_R8(tp, Config3);
-
- if (enable)
- data |= Rdy_to_L23;
- else
- data &= ~Rdy_to_L23;
-
- RTL_W8(tp, Config3, data);
+ /* work around an issue when PCI reset occurs during L2/L3 state */
+ RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23);
}
static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
@@ -4960,6 +5082,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
/* Adjust EEE LED frequency */
RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
+ rtl8168_config_eee_mac(tp);
+
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
@@ -4992,6 +5116,8 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
+
+ rtl8168_config_eee_mac(tp);
}
static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
@@ -5023,7 +5149,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp)
};
rtl_hw_start_8168f(tp);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
@@ -5054,10 +5180,12 @@ static void rtl_hw_start_8168g(struct rtl8169_private *tp)
/* Adjust EEE LED frequency */
RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
+ rtl8168_config_eee_mac(tp);
+
rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
}
static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
@@ -5156,6 +5284,8 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
/* Adjust EEE LED frequency */
RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
+ rtl8168_config_eee_mac(tp);
+
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
@@ -5163,7 +5293,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
rtl_writephy(tp, 0x1f, 0x0c42);
rg_saw_cnt = (rtl_readphy(tp, 0x13) & 0x3fff);
@@ -5236,11 +5366,13 @@ static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
/* Adjust EEE LED frequency */
RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
+ rtl8168_config_eee_mac(tp);
+
rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
}
static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
@@ -5511,7 +5643,7 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
}
static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
@@ -5546,7 +5678,7 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
}
static void rtl_hw_start_8106(struct rtl8169_private *tp)
@@ -5560,7 +5692,7 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
- rtl_pcie_state_l2l3_enable(tp, false);
+ rtl_pcie_state_l2l3_disable(tp);
rtl_hw_aspm_clkreq_enable(tp, true);
}
@@ -5660,11 +5792,6 @@ static inline void rtl8169_mark_to_asic(struct RxDesc *desc)
desc->opts1 = cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE);
}
-static inline void *rtl8169_align(void *data)
-{
- return (void *)ALIGN((long)data, 16);
-}
-
static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
struct RxDesc *desc)
{
@@ -5677,15 +5804,13 @@ static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
if (!data)
return NULL;
- if (rtl8169_align(data) != data) {
- kfree(data);
- data = kmalloc_node(R8169_RX_BUF_SIZE + 15, GFP_KERNEL, node);
- if (!data)
- return NULL;
+ /* Memory should be properly aligned, but better check. */
+ if (!IS_ALIGNED((unsigned long)data, 8)) {
+ netdev_err_once(tp->dev, "RX buffer not 8-byte-aligned\n");
+ goto err_out;
}
- mapping = dma_map_single(d, rtl8169_align(data), R8169_RX_BUF_SIZE,
- DMA_FROM_DEVICE);
+ mapping = dma_map_single(d, data, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(d, mapping))) {
if (net_ratelimit())
netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
@@ -6067,7 +6192,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
struct device *d = tp_to_dev(tp);
dma_addr_t mapping;
u32 opts[2], len;
- bool stop_queue;
int frags;
if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) {
@@ -6109,6 +6233,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
txd->opts2 = cpu_to_le32(opts[1]);
+ netdev_sent_queue(dev, skb->len);
+
skb_tx_timestamp(skb);
/* Force memory writes to complete before releasing descriptor */
@@ -6121,14 +6247,14 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
tp->cur_tx += frags + 1;
- stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
- if (unlikely(stop_queue))
- netif_stop_queue(dev);
-
- if (__netdev_sent_queue(dev, skb->len, skb->xmit_more))
- RTL_W8(tp, TxPoll, NPQ);
+ RTL_W8(tp, TxPoll, NPQ);
- if (unlikely(stop_queue)) {
+ if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
+ /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
+ * not miss a ring update when it notices a stopped queue.
+ */
+ smp_wmb();
+ netif_stop_queue(dev);
/* Sync with rtl_tx:
* - publish queue status and cur_tx ring index (write barrier)
* - refresh dirty_tx ring index (read barrier).
@@ -6188,16 +6314,6 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
- /* The infamous DAC f*ckup only happens at boot time */
- if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) {
- netif_info(tp, intr, dev, "disabling PCI DAC\n");
- tp->cp_cmd &= ~PCIDAC;
- RTL_W16(tp, CPlusCmd, tp->cp_cmd);
- dev->features &= ~NETIF_F_HIGHDMA;
- }
-
- rtl8169_hw_reset(tp);
-
rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
@@ -6293,7 +6409,6 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data,
struct sk_buff *skb;
struct device *d = tp_to_dev(tp);
- data = rtl8169_align(data);
dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
prefetch(data);
skb = napi_alloc_skb(&tp->napi, pkt_size);
@@ -6404,7 +6519,7 @@ release_descriptor:
static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
{
struct rtl8169_private *tp = dev_instance;
- u16 status = rtl_get_events(tp);
+ u16 status = RTL_R16(tp, IntrStatus);
u16 irq_mask = RTL_R16(tp, IntrMask);
if (status == 0xffff || !(status & irq_mask))
@@ -6415,8 +6530,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
goto out;
}
- if (status & LinkChg && tp->dev->phydev)
- phy_mac_interrupt(tp->dev->phydev);
+ if (status & LinkChg)
+ phy_mac_interrupt(tp->phydev);
if (unlikely(status & RxFIFOOver &&
tp->mac_version == RTL_GIGA_MAC_VER_11)) {
@@ -6507,12 +6622,12 @@ static void r8169_phylink_handler(struct net_device *ndev)
}
if (net_ratelimit())
- phy_print_status(ndev->phydev);
+ phy_print_status(tp->phydev);
}
static int r8169_phy_connect(struct rtl8169_private *tp)
{
- struct phy_device *phydev = mdiobus_get_phy(tp->mii_bus, 0);
+ struct phy_device *phydev = tp->phydev;
phy_interface_t phy_mode;
int ret;
@@ -6539,7 +6654,7 @@ static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
- phy_stop(dev->phydev);
+ phy_stop(tp->phydev);
napi_disable(&tp->napi);
netif_stop_queue(dev);
@@ -6581,7 +6696,7 @@ static int rtl8169_close(struct net_device *dev)
cancel_work_sync(&tp->wk.work);
- phy_disconnect(dev->phydev);
+ phy_disconnect(tp->phydev);
pci_free_irq(pdev, 0, tp);
@@ -6632,10 +6747,6 @@ static int rtl_open(struct net_device *dev)
if (retval < 0)
goto err_free_rx_1;
- INIT_WORK(&tp->wk.work, rtl_task);
-
- smp_mb();
-
rtl_request_firmware(tp);
retval = pci_request_irq(pdev, 0, rtl8169_interrupt, NULL, tp,
@@ -6662,7 +6773,7 @@ static int rtl_open(struct net_device *dev)
if (!rtl8169_init_counter_offsets(tp))
netif_warn(tp, hw, dev, "counter reset/update failed\n");
- phy_start(dev->phydev);
+ phy_start(tp->phydev);
netif_start_queue(dev);
rtl_unlock_work(tp);
@@ -6751,7 +6862,7 @@ static void rtl8169_net_suspend(struct net_device *dev)
if (!netif_running(dev))
return;
- phy_stop(dev->phydev);
+ phy_stop(tp->phydev);
netif_device_detach(dev);
rtl_lock_work(tp);
@@ -6786,14 +6897,13 @@ static void __rtl8169_resume(struct net_device *dev)
rtl_pll_power_up(tp);
rtl8169_init_phy(dev, tp);
- phy_start(tp->dev->phydev);
+ phy_start(tp->phydev);
rtl_lock_work(tp);
napi_enable(&tp->napi);
set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+ rtl_reset_work(tp);
rtl_unlock_work(tp);
-
- rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
static int rtl8169_resume(struct device *device)
@@ -6930,7 +7040,7 @@ static void rtl_remove_one(struct pci_dev *pdev)
netif_napi_del(&tp->napi);
unregister_netdev(dev);
- mdiobus_unregister(tp->mii_bus);
+ mdiobus_unregister(tp->phydev->mdio.bus);
rtl_release_firmware(tp);
@@ -6990,9 +7100,9 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
unsigned int flags;
if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+ rtl_unlock_config_regs(tp);
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ rtl_lock_config_regs(tp);
flags = PCI_IRQ_LEGACY;
} else {
flags = PCI_IRQ_ALL_TYPES;
@@ -7001,6 +7111,30 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
}
+static void rtl_read_mac_address(struct rtl8169_private *tp,
+ u8 mac_addr[ETH_ALEN])
+{
+ u32 value;
+
+ /* Get MAC address */
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+ value = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
+ mac_addr[0] = (value >> 0) & 0xff;
+ mac_addr[1] = (value >> 8) & 0xff;
+ mac_addr[2] = (value >> 16) & 0xff;
+ mac_addr[3] = (value >> 24) & 0xff;
+
+ value = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+ mac_addr[4] = (value >> 0) & 0xff;
+ mac_addr[5] = (value >> 8) & 0xff;
+ break;
+ default:
+ break;
+ }
+}
+
DECLARE_RTL_COND(rtl_link_list_ready_cond)
{
return RTL_R8(tp, MCU) & LINK_LIST_RDY;
@@ -7037,7 +7171,6 @@ static int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr,
static int r8169_mdio_register(struct rtl8169_private *tp)
{
struct pci_dev *pdev = tp->pci_dev;
- struct phy_device *phydev;
struct mii_bus *new_bus;
int ret;
@@ -7059,16 +7192,14 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
if (ret)
return ret;
- phydev = mdiobus_get_phy(new_bus, 0);
- if (!phydev) {
+ tp->phydev = mdiobus_get_phy(new_bus, 0);
+ if (!tp->phydev) {
mdiobus_unregister(new_bus);
return -ENODEV;
}
/* PHY will be woken up in rtl_open() */
- phy_suspend(phydev);
-
- tp->mii_bus = new_bus;
+ phy_suspend(tp->phydev);
return 0;
}
@@ -7166,9 +7297,37 @@ static void rtl_disable_clk(void *data)
clk_disable_unprepare(data);
}
+static int rtl_get_ether_clk(struct rtl8169_private *tp)
+{
+ struct device *d = tp_to_dev(tp);
+ struct clk *clk;
+ int rc;
+
+ clk = devm_clk_get(d, "ether_clk");
+ if (IS_ERR(clk)) {
+ rc = PTR_ERR(clk);
+ if (rc == -ENOENT)
+ /* clk-core allows NULL (for suspend / resume) */
+ rc = 0;
+ else if (rc != -EPROBE_DEFER)
+ dev_err(d, "failed to get clk: %d\n", rc);
+ } else {
+ tp->clk = clk;
+ rc = clk_prepare_enable(clk);
+ if (rc)
+ dev_err(d, "failed to enable clk: %d\n", rc);
+ else
+ rc = devm_add_action_or_reset(d, rtl_disable_clk, clk);
+ }
+
+ return rc;
+}
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+ /* align to u16 for is_valid_ether_addr() */
+ u8 mac_addr[ETH_ALEN] __aligned(2) = {};
struct rtl8169_private *tp;
struct net_device *dev;
int chipset, region, i;
@@ -7187,30 +7346,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->supports_gmii = cfg->has_gmii;
/* Get the *optional* external "ether_clk" used on some boards */
- tp->clk = devm_clk_get(&pdev->dev, "ether_clk");
- if (IS_ERR(tp->clk)) {
- rc = PTR_ERR(tp->clk);
- if (rc == -ENOENT) {
- /* clk-core allows NULL (for suspend / resume) */
- tp->clk = NULL;
- } else if (rc == -EPROBE_DEFER) {
- return rc;
- } else {
- dev_err(&pdev->dev, "failed to get clk: %d\n", rc);
- return rc;
- }
- } else {
- rc = clk_prepare_enable(tp->clk);
- if (rc) {
- dev_err(&pdev->dev, "failed to enable clk: %d\n", rc);
- return rc;
- }
-
- rc = devm_add_action_or_reset(&pdev->dev, rtl_disable_clk,
- tp->clk);
- if (rc)
- return rc;
- }
+ rc = rtl_get_ether_clk(tp);
+ if (rc)
+ return rc;
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev);
@@ -7255,13 +7393,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->cp_cmd = RTL_R16(tp, CPlusCmd);
- if (sizeof(dma_addr_t) > 4 && (use_dac == 1 || (use_dac == -1 &&
- tp->mac_version >= RTL_GIGA_MAC_VER_18)) &&
+ if (sizeof(dma_addr_t) > 4 && tp->mac_version >= RTL_GIGA_MAC_VER_18 &&
!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
-
- /* CPlusCmd Dual Access Cycle is only needed for non-PCIe */
- if (!pci_is_pcie(pdev))
- tp->cp_cmd |= PCIDAC;
dev->features |= NETIF_F_HIGHDMA;
} else {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
@@ -7292,26 +7425,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
- tp->saved_wolopts = __rtl8169_get_wol(tp);
-
mutex_init(&tp->wk.mutex);
+ INIT_WORK(&tp->wk.work, rtl_task);
u64_stats_init(&tp->rx_stats.syncp);
u64_stats_init(&tp->tx_stats.syncp);
- /* Get MAC address */
- switch (tp->mac_version) {
- u8 mac_addr[ETH_ALEN] __aligned(4);
- case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
- *(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
- *(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+ /* get MAC address */
+ rc = eth_platform_get_mac_address(&pdev->dev, mac_addr);
+ if (rc)
+ rtl_read_mac_address(tp, mac_addr);
+
+ if (is_valid_ether_addr(mac_addr))
+ rtl_rar_set(tp, mac_addr);
- if (is_valid_ether_addr(mac_addr))
- rtl_rar_set(tp, mac_addr);
- break;
- default:
- break;
- }
for (i = 0; i < ETH_ALEN; i++)
dev->dev_addr[i] = RTL_R8(tp, MAC0 + i);
@@ -7360,7 +7486,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->irq_mask = RTL_EVENT_NAPI | cfg->irq_mask;
tp->coalesce_info = cfg->coalesce_info;
- tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
+ tp->fw_name = rtl_chip_infos[chipset].fw_name;
tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters),
&tp->counters_phys_addr,
@@ -7401,7 +7527,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_mdio_unregister:
- mdiobus_unregister(tp->mii_bus);
+ mdiobus_unregister(tp->phydev->mdio.bus);
return rc;
}
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index ffc1ada4e6da..d28c8f9ca55b 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -343,7 +343,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
int i;
priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) +
- ETH_HLEN + VLAN_HLEN;
+ ETH_HLEN + VLAN_HLEN + sizeof(__sum16);
/* Allocate RX and TX skb rings */
priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
@@ -524,13 +524,15 @@ static void ravb_rx_csum(struct sk_buff *skb)
{
u8 *hw_csum;
- /* The hardware checksum is 2 bytes appended to packet data */
- if (unlikely(skb->len < 2))
+ /* The hardware checksum is contained in sizeof(__sum16) (2) bytes
+ * appended to packet data
+ */
+ if (unlikely(skb->len < sizeof(__sum16)))
return;
- hw_csum = skb_tail_pointer(skb) - 2;
+ hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
skb->ip_summed = CHECKSUM_COMPLETE;
- skb_trim(skb, skb->len - 2);
+ skb_trim(skb, skb->len - sizeof(__sum16));
}
/* Packet receive function for Ethernet AVB */
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index f27a0dc8c563..339b2eae2100 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -555,7 +555,7 @@ static int sh_eth_soft_reset_gether(struct net_device *ndev)
sh_eth_write(ndev, 0, RDFFR);
/* Reset HW CRC register */
- if (mdp->cd->hw_checksum)
+ if (mdp->cd->csmr)
sh_eth_write(ndev, 0, CSMR);
/* Select MII mode */
@@ -619,7 +619,8 @@ static struct sh_eth_cpu_data r7s72100_data = {
.no_trimd = 1,
.no_ade = 1,
.xdfar_rw = 1,
- .hw_checksum = 1,
+ .csmr = 1,
+ .rx_csum = 1,
.tsu = 1,
.no_tx_cntrs = 1,
};
@@ -668,7 +669,8 @@ static struct sh_eth_cpu_data r8a7740_data = {
.no_trimd = 1,
.no_ade = 1,
.xdfar_rw = 1,
- .hw_checksum = 1,
+ .csmr = 1,
+ .rx_csum = 1,
.tsu = 1,
.select_mii = 1,
.magic = 1,
@@ -793,7 +795,8 @@ static struct sh_eth_cpu_data r8a77980_data = {
.no_trimd = 1,
.no_ade = 1,
.xdfar_rw = 1,
- .hw_checksum = 1,
+ .csmr = 1,
+ .rx_csum = 1,
.select_mii = 1,
.magic = 1,
.cexcr = 1,
@@ -1045,7 +1048,8 @@ static struct sh_eth_cpu_data sh7734_data = {
.no_ade = 1,
.xdfar_rw = 1,
.tsu = 1,
- .hw_checksum = 1,
+ .csmr = 1,
+ .rx_csum = 1,
.select_mii = 1,
.magic = 1,
.cexcr = 1,
@@ -1088,6 +1092,7 @@ static struct sh_eth_cpu_data sh7763_data = {
.irq_flags = IRQF_SHARED,
.magic = 1,
.cexcr = 1,
+ .rx_csum = 1,
.dual_port = 1,
};
@@ -1532,8 +1537,9 @@ static int sh_eth_dev_init(struct net_device *ndev)
mdp->irq_enabled = true;
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
- /* PAUSE Prohibition */
+ /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) |
+ (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
ECMR_TE | ECMR_RE, ECMR);
if (mdp->cd->set_rate)
@@ -1592,6 +1598,19 @@ static void sh_eth_dev_exit(struct net_device *ndev)
update_mac_address(ndev);
}
+static void sh_eth_rx_csum(struct sk_buff *skb)
+{
+ u8 *hw_csum;
+
+ /* The hardware checksum is 2 bytes appended to packet data */
+ if (unlikely(skb->len < sizeof(__sum16)))
+ return;
+ hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
+ skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb_trim(skb, skb->len - sizeof(__sum16));
+}
+
/* Packet receive function */
static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
{
@@ -1633,7 +1652,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
* the RFS bits are from bit 25 to bit 16. So, the
* driver needs right shifting by 16.
*/
- if (mdp->cd->hw_checksum)
+ if (mdp->cd->csmr)
desc_status >>= 16;
skb = mdp->rx_skbuff[entry];
@@ -1666,6 +1685,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
DMA_FROM_DEVICE);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
+ if (ndev->features & NETIF_F_RXCSUM)
+ sh_eth_rx_csum(skb);
netif_receive_skb(skb);
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += pkt_len;
@@ -2173,7 +2194,7 @@ static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf)
add_reg(MAFCR);
if (cd->rtrate)
add_reg(RTRATE);
- if (cd->hw_checksum)
+ if (cd->csmr)
add_reg(CSMR);
if (cd->select_mii)
add_reg(RMII_MII);
@@ -2921,6 +2942,39 @@ static void sh_eth_set_rx_mode(struct net_device *ndev)
spin_unlock_irqrestore(&mdp->lock, flags);
}
+static void sh_eth_set_rx_csum(struct net_device *ndev, bool enable)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&mdp->lock, flags);
+
+ /* Disable TX and RX */
+ sh_eth_rcv_snd_disable(ndev);
+
+ /* Modify RX Checksum setting */
+ sh_eth_modify(ndev, ECMR, ECMR_RCSC, enable ? ECMR_RCSC : 0);
+
+ /* Enable TX and RX */
+ sh_eth_rcv_snd_enable(ndev);
+
+ spin_unlock_irqrestore(&mdp->lock, flags);
+}
+
+static int sh_eth_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ netdev_features_t changed = ndev->features ^ features;
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+
+ if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum)
+ sh_eth_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
+
+ ndev->features = features;
+
+ return 0;
+}
+
static int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
{
if (!mdp->port)
@@ -3102,6 +3156,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
.ndo_change_mtu = sh_eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_features = sh_eth_set_features,
};
static const struct net_device_ops sh_eth_netdev_ops_tsu = {
@@ -3117,6 +3172,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
.ndo_change_mtu = sh_eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_features = sh_eth_set_features,
};
#ifdef CONFIG_OF
@@ -3245,6 +3301,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
ndev->max_mtu = 2000 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
ndev->min_mtu = ETH_MIN_MTU;
+ if (mdp->cd->rx_csum) {
+ ndev->features = NETIF_F_RXCSUM;
+ ndev->hw_features = NETIF_F_RXCSUM;
+ }
+
/* set function */
if (mdp->cd->tsu)
ndev->netdev_ops = &sh_eth_netdev_ops_tsu;
@@ -3294,7 +3355,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
goto out_release;
}
mdp->port = port;
- ndev->features = NETIF_F_HW_VLAN_CTAG_FILTER;
+ ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
/* Need to init only the first port of the two sharing a TSU */
if (port == 0) {
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 0c18650bbfe6..850726301e1c 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -499,7 +499,8 @@ struct sh_eth_cpu_data {
unsigned no_ade:1; /* E-DMAC DOES NOT have ADE bit in EESR */
unsigned no_xdfar:1; /* E-DMAC DOES NOT have RDFAR/TDFAR */
unsigned xdfar_rw:1; /* E-DMAC has writeable RDFAR/TDFAR */
- unsigned hw_checksum:1; /* E-DMAC has CSMR */
+ unsigned csmr:1; /* E-DMAC has CSMR */
+ unsigned rx_csum:1; /* EtherC has ECMR.RCSC */
unsigned select_mii:1; /* EtherC has RMII_MII (MII select register) */
unsigned rmiimode:1; /* EtherC has RMIIMODE register */
unsigned rtrate:1; /* EtherC has RTRATE register */
diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index 748fb12260a6..2b2e1c4f0dc3 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -109,8 +109,6 @@ struct rocker_world_ops {
int (*port_attr_bridge_flags_set)(struct rocker_port *rocker_port,
unsigned long brport_flags,
struct switchdev_trans *trans);
- int (*port_attr_bridge_flags_get)(const struct rocker_port *rocker_port,
- unsigned long *p_brport_flags);
int (*port_attr_bridge_flags_support_get)(const struct rocker_port *
rocker_port,
unsigned long *
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 6213827e3956..c883aa89b7ca 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1566,45 +1566,57 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port,
}
static int
-rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
- unsigned long brport_flags,
- struct switchdev_trans *trans)
+rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
+ rocker_port,
+ unsigned long *
+ p_brport_flags_support)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;
- if (!wops->port_attr_bridge_flags_set)
+ if (!wops->port_attr_bridge_flags_support_get)
return -EOPNOTSUPP;
-
- if (switchdev_trans_ph_prepare(trans))
- return 0;
-
- return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
- trans);
+ return wops->port_attr_bridge_flags_support_get(rocker_port,
+ p_brport_flags_support);
}
static int
-rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
- unsigned long *p_brport_flags)
+rocker_world_port_attr_pre_bridge_flags_set(struct rocker_port *rocker_port,
+ unsigned long brport_flags,
+ struct switchdev_trans *trans)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;
+ unsigned long brport_flags_s;
+ int err;
- if (!wops->port_attr_bridge_flags_get)
+ if (!wops->port_attr_bridge_flags_set)
return -EOPNOTSUPP;
- return wops->port_attr_bridge_flags_get(rocker_port, p_brport_flags);
+
+ err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
+ &brport_flags_s);
+ if (err)
+ return err;
+
+ if (brport_flags & ~brport_flags_s)
+ return -EINVAL;
+
+ return 0;
}
static int
-rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
- rocker_port,
- unsigned long *
- p_brport_flags_support)
+rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
+ unsigned long brport_flags,
+ struct switchdev_trans *trans)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;
- if (!wops->port_attr_bridge_flags_support_get)
+ if (!wops->port_attr_bridge_flags_set)
return -EOPNOTSUPP;
- return wops->port_attr_bridge_flags_support_get(rocker_port,
- p_brport_flags_support);
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
+ trans);
}
static int
@@ -2026,6 +2038,18 @@ static void rocker_port_neigh_destroy(struct net_device *dev,
err);
}
+static int rocker_port_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ const struct rocker_port *rocker_port = netdev_priv(dev);
+ const struct rocker *rocker = rocker_port->rocker;
+
+ ppid->id_len = sizeof(rocker->hw.id);
+ memcpy(&ppid->id, &rocker->hw.id, ppid->id_len);
+
+ return 0;
+}
+
static const struct net_device_ops rocker_port_netdev_ops = {
.ndo_open = rocker_port_open,
.ndo_stop = rocker_port_stop,
@@ -2035,39 +2059,13 @@ static const struct net_device_ops rocker_port_netdev_ops = {
.ndo_get_phys_port_name = rocker_port_get_phys_port_name,
.ndo_change_proto_down = rocker_port_change_proto_down,
.ndo_neigh_destroy = rocker_port_neigh_destroy,
+ .ndo_get_port_parent_id = rocker_port_get_port_parent_id,
};
/********************
* swdev interface
********************/
-static int rocker_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
-{
- const struct rocker_port *rocker_port = netdev_priv(dev);
- const struct rocker *rocker = rocker_port->rocker;
- int err = 0;
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(rocker->hw.id);
- memcpy(&attr->u.ppid.id, &rocker->hw.id, attr->u.ppid.id_len);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
- err = rocker_world_port_attr_bridge_flags_get(rocker_port,
- &attr->u.brport_flags);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
- &attr->u.brport_flags_support);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return err;
-}
-
static int rocker_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr,
struct switchdev_trans *trans)
@@ -2081,6 +2079,11 @@ static int rocker_port_attr_set(struct net_device *dev,
attr->u.stp_state,
trans);
break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ err = rocker_world_port_attr_pre_bridge_flags_set(rocker_port,
+ attr->u.brport_flags,
+ trans);
+ break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = rocker_world_port_attr_bridge_flags_set(rocker_port,
attr->u.brport_flags,
@@ -2139,11 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev,
return err;
}
-static const struct switchdev_ops rocker_port_switchdev_ops = {
- .switchdev_port_attr_get = rocker_port_attr_get,
- .switchdev_port_attr_set = rocker_port_attr_set,
-};
-
struct rocker_fib_event_work {
struct work_struct work;
union {
@@ -2597,7 +2595,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port_dev_addr_init(rocker_port);
dev->netdev_ops = &rocker_port_netdev_ops;
dev->ethtool_ops = &rocker_port_ethtool_ops;
- dev->switchdev_ops = &rocker_port_switchdev_ops;
netif_tx_napi_add(dev, &rocker_port->napi_tx, rocker_port_poll_tx,
NAPI_POLL_WEIGHT);
netif_napi_add(dev, &rocker_port->napi_rx, rocker_port_poll_rx,
@@ -2708,6 +2705,19 @@ static bool rocker_port_dev_check(const struct net_device *dev)
return dev->netdev_ops == &rocker_port_netdev_ops;
}
+static int
+rocker_switchdev_port_attr_set_event(struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err;
+
+ err = rocker_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
struct rocker_switchdev_event_work {
struct work_struct work;
struct switchdev_notifier_fdb_info fdb_info;
@@ -2725,7 +2735,7 @@ rocker_fdb_offload_notify(struct rocker_port *rocker_port,
info.vid = recv_info->vid;
info.offloaded = true;
call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
- rocker_port->dev, &info.info);
+ rocker_port->dev, &info.info, NULL);
}
static void rocker_switchdev_event_work(struct work_struct *work)
@@ -2777,6 +2787,9 @@ static int rocker_switchdev_event(struct notifier_block *unused,
if (!rocker_port_dev_check(dev))
return NOTIFY_DONE;
+ if (event == SWITCHDEV_PORT_ATTR_SET)
+ return rocker_switchdev_port_attr_set_event(dev, ptr);
+
rocker_port = netdev_priv(dev);
switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
if (WARN_ON(!switchdev_work))
@@ -2839,6 +2852,8 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD:
case SWITCHDEV_PORT_OBJ_DEL:
return rocker_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET:
+ return rocker_switchdev_port_attr_set_event(dev, ptr);
}
return NOTIFY_DONE;
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 6473cc68c2d5..fa296a7c255d 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1833,10 +1833,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
rtnl_lock();
if (learned && removing)
call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
- lw->ofdpa_port->dev, &info.info);
+ lw->ofdpa_port->dev, &info.info, NULL);
else if (learned && !removing)
call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
- lw->ofdpa_port->dev, &info.info);
+ lw->ofdpa_port->dev, &info.info, NULL);
rtnl_unlock();
kfree(work);
@@ -2512,16 +2512,6 @@ static int ofdpa_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
}
static int
-ofdpa_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
- unsigned long *p_brport_flags)
-{
- const struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-
- *p_brport_flags = ofdpa_port->brport_flags;
- return 0;
-}
-
-static int
ofdpa_port_attr_bridge_flags_support_get(const struct rocker_port *
rocker_port,
unsigned long *
@@ -2823,7 +2813,6 @@ struct rocker_world_ops rocker_ofdpa_ops = {
.port_stop = ofdpa_port_stop,
.port_attr_stp_state_set = ofdpa_port_attr_stp_state_set,
.port_attr_bridge_flags_set = ofdpa_port_attr_bridge_flags_set,
- .port_attr_bridge_flags_get = ofdpa_port_attr_bridge_flags_get,
.port_attr_bridge_flags_support_get = ofdpa_port_attr_bridge_flags_support_get,
.port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set,
.port_obj_vlan_add = ofdpa_port_obj_vlan_add,
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 690aee88f0eb..6d22dd500790 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -400,9 +400,9 @@ static int init_tx_ring(struct device *dev, u8 queue_no,
}
/* allocate memory for TX descriptors */
- tx_ring->dma_tx = dma_zalloc_coherent(dev,
- tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
- &tx_ring->dma_tx_phy, GFP_KERNEL);
+ tx_ring->dma_tx = dma_alloc_coherent(dev,
+ tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
+ &tx_ring->dma_tx_phy, GFP_KERNEL);
if (!tx_ring->dma_tx)
return -ENOMEM;
@@ -479,9 +479,9 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no,
rx_ring->queue_no = queue_no;
/* allocate memory for RX descriptors */
- rx_ring->dma_rx = dma_zalloc_coherent(priv->device,
- rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
- &rx_ring->dma_rx_phy, GFP_KERNEL);
+ rx_ring->dma_rx = dma_alloc_coherent(priv->device,
+ rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
+ &rx_ring->dma_rx_phy, GFP_KERNEL);
if (rx_ring->dma_rx == NULL)
return -ENOMEM;
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index b6a50058bb8d..e888b479c596 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -6041,27 +6041,33 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 0, 3, "sfc_exp_rom_cfg" },
{ NVRAM_PARTITION_TYPE_LICENSE, 0, 0, "sfc_license" },
{ NVRAM_PARTITION_TYPE_PHY_MIN, 0xff, 0, "sfc_phy_fw" },
- /* MUM and SUC firmware share the same partition type */
{ NVRAM_PARTITION_TYPE_MUM_FIRMWARE, 0, 0, "sfc_mumfw" },
{ NVRAM_PARTITION_TYPE_EXPANSION_UEFI, 0, 0, "sfc_uefi" },
- { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" }
+ { NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS, 0, 0, "sfc_dynamic_cfg_dflt" },
+ { NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS, 0, 0, "sfc_exp_rom_cfg_dflt" },
+ { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" },
+ { NVRAM_PARTITION_TYPE_BUNDLE, 0, 0, "sfc_bundle" },
+ { NVRAM_PARTITION_TYPE_BUNDLE_METADATA, 0, 0, "sfc_bundle_metadata" },
};
+#define EF10_NVRAM_PARTITION_COUNT ARRAY_SIZE(efx_ef10_nvram_types)
static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
struct efx_mcdi_mtd_partition *part,
- unsigned int type)
+ unsigned int type,
+ unsigned long *found)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX);
const struct efx_ef10_nvram_type_info *info;
size_t size, erase_size, outlen;
+ int type_idx = 0;
bool protected;
int rc;
- for (info = efx_ef10_nvram_types; ; info++) {
- if (info ==
- efx_ef10_nvram_types + ARRAY_SIZE(efx_ef10_nvram_types))
+ for (type_idx = 0; ; type_idx++) {
+ if (type_idx == EF10_NVRAM_PARTITION_COUNT)
return -ENODEV;
+ info = efx_ef10_nvram_types + type_idx;
if ((type & ~info->type_mask) == info->type)
break;
}
@@ -6071,8 +6077,22 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected);
if (rc)
return rc;
+ if (protected &&
+ (type != NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS &&
+ type != NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS))
+ /* Hide protected partitions that don't provide defaults. */
+ return -ENODEV;
+
if (protected)
- return -ENODEV; /* hide it */
+ /* Protected partitions are read only. */
+ erase_size = 0;
+
+ /* If we've already exposed a partition of this type, hide this
+ * duplicate. All operations on MTDs are keyed by the type anyway,
+ * so we can't act on the duplicate.
+ */
+ if (__test_and_set_bit(type_idx, found))
+ return -EEXIST;
part->nvram_type = type;
@@ -6105,6 +6125,7 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
static int efx_ef10_mtd_probe(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
+ DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 };
struct efx_mcdi_mtd_partition *parts;
size_t outlen, n_parts_total, i, n_parts;
unsigned int type;
@@ -6133,11 +6154,13 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx)
for (i = 0; i < n_parts_total; i++) {
type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID,
i);
- rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type);
- if (rc == 0)
- n_parts++;
- else if (rc != -ENODEV)
+ rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type,
+ found);
+ if (rc == -EEXIST || rc == -ENODEV)
+ continue;
+ if (rc)
goto fail;
+ n_parts++;
}
rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 3643015a55cf..bc655ffc9e02 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -915,7 +915,7 @@ rollback:
void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
{
- mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
+ mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(10));
}
static bool efx_default_channel_want_txqs(struct efx_channel *channel)
diff --git a/drivers/net/ethernet/sfc/falcon/nic.c b/drivers/net/ethernet/sfc/falcon/nic.c
index a8ecb33390da..9c07b5175581 100644
--- a/drivers/net/ethernet/sfc/falcon/nic.c
+++ b/drivers/net/ethernet/sfc/falcon/nic.c
@@ -33,8 +33,8 @@
int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer,
unsigned int len, gfp_t gfp_flags)
{
- buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
- &buffer->dma_addr, gfp_flags);
+ buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+ &buffer->dma_addr, gfp_flags);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index dfad93fca0a6..295ec1787b9f 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -2074,22 +2074,26 @@ fail:
static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN);
int rc;
MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
+ MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_START_V2_IN_FLAGS,
+ NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT,
+ 1);
BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
NULL, 0, NULL);
+
return rc;
}
static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
loff_t offset, u8 *buffer, size_t length)
{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_V2_LEN);
MCDI_DECLARE_BUF(outbuf,
MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
size_t outlen;
@@ -2098,6 +2102,8 @@ static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
+ MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_V2_MODE,
+ MC_CMD_NVRAM_READ_IN_V2_DEFAULT);
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
outbuf, sizeof(outbuf), &outlen);
@@ -2147,15 +2153,51 @@ static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
- int rc;
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN);
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
+ size_t outlen;
+ int rc, rc2;
MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
-
- BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
+ /* Always set this flag. Old firmware ignores it */
+ MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
+ NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT,
+ 1);
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
- NULL, 0, NULL);
+ outbuf, sizeof(outbuf), &outlen);
+ if (!rc && outlen >= MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
+ rc2 = MCDI_DWORD(outbuf, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
+ if (rc2 != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)
+ netif_err(efx, drv, efx->net_dev,
+ "NVRAM update failed verification with code 0x%x\n",
+ rc2);
+ switch (rc2) {
+ case MC_CMD_NVRAM_VERIFY_RC_SUCCESS:
+ break;
+ case MC_CMD_NVRAM_VERIFY_RC_CMS_CHECK_FAILED:
+ case MC_CMD_NVRAM_VERIFY_RC_MESSAGE_DIGEST_CHECK_FAILED:
+ case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHECK_FAILED:
+ case MC_CMD_NVRAM_VERIFY_RC_TRUSTED_APPROVERS_CHECK_FAILED:
+ case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHAIN_CHECK_FAILED:
+ rc = -EIO;
+ break;
+ case MC_CMD_NVRAM_VERIFY_RC_INVALID_CMS_FORMAT:
+ case MC_CMD_NVRAM_VERIFY_RC_BAD_MESSAGE_DIGEST:
+ rc = -EINVAL;
+ break;
+ case MC_CMD_NVRAM_VERIFY_RC_NO_VALID_SIGNATURES:
+ case MC_CMD_NVRAM_VERIFY_RC_NO_TRUSTED_APPROVERS:
+ case MC_CMD_NVRAM_VERIFY_RC_NO_SIGNATURE_MATCH:
+ rc = -EPERM;
+ break;
+ default:
+ netif_err(efx, drv, efx->net_dev,
+ "Unknown response to NVRAM_UPDATE_FINISH\n");
+ rc = -EIO;
+ }
+ }
+
return rc;
}
diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index 3839eec783ea..20a5523bf9f3 100644
--- a/drivers/net/ethernet/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
@@ -6784,6 +6784,14 @@
* subset of the information stored in this partition.
*/
#define NVRAM_PARTITION_TYPE_FRU_INFORMATION 0x1d00
+/* enum: Bundle image partition */
+#define NVRAM_PARTITION_TYPE_BUNDLE 0x1e00
+/* enum: Bundle metadata partition that holds additional information related to
+ * a bundle update in TLV format
+ */
+#define NVRAM_PARTITION_TYPE_BUNDLE_METADATA 0x1e01
+/* enum: Bundle update non-volatile log output partition */
+#define NVRAM_PARTITION_TYPE_BUNDLE_LOG 0x1e02
/* enum: Start of reserved value range (firmware may use for any purpose) */
#define NVRAM_PARTITION_TYPE_RESERVED_VALUES_MIN 0xff00
/* enum: End of reserved value range (firmware may use for any purpose) */
diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c
index 4ac30b6e5dab..0d03e0577d85 100644
--- a/drivers/net/ethernet/sfc/mtd.c
+++ b/drivers/net/ethernet/sfc/mtd.c
@@ -66,6 +66,9 @@ int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
part->mtd.writesize = 1;
+ if (!(part->mtd.flags & MTD_NO_ERASE))
+ part->mtd.flags |= MTD_WRITEABLE;
+
part->mtd.owner = THIS_MODULE;
part->mtd.priv = efx;
part->mtd.name = part->name;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index aa1945a858d5..c2d45a40eb48 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -34,8 +34,8 @@
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
unsigned int len, gfp_t gfp_flags)
{
- buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
- &buffer->dma_addr, gfp_flags);
+ buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+ &buffer->dma_addr, gfp_flags);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 396ff01298cd..8702ab44d80b 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -360,8 +360,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic)
rc = efx_init_rx_buffers(rx_queue, atomic);
if (unlikely(rc)) {
/* Ensure that we don't leave the rx queue empty */
- if (rx_queue->added_count == rx_queue->removed_count)
- efx_schedule_slow_fill(rx_queue);
+ efx_schedule_slow_fill(rx_queue);
goto out;
}
} while ((space -= batch_size) >= batch_size);
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 22eb059086f7..06c8f282263f 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -471,7 +471,7 @@ static int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue,
if (IS_ERR(segments))
return PTR_ERR(segments);
- dev_kfree_skb_any(skb);
+ dev_consume_skb_any(skb);
skb = segments;
while (skb) {
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 3140999642ba..358e66b81926 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -666,7 +666,7 @@ static inline void ioc3_tx(struct net_device *dev)
packets++;
skb = ip->tx_skbs[o_entry];
bytes += skb->len;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
ip->tx_skbs[o_entry] = NULL;
o_entry = (o_entry + 1) & 127; /* Next */
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index 703fbbefea44..f1271402ca21 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -68,6 +68,8 @@ module_param(timeout, int, 0);
* packets in and out, so there is place for a packet
*/
struct meth_private {
+ struct platform_device *pdev;
+
/* in-memory copy of MAC Control register */
u64 mac_ctrl;
@@ -211,8 +213,8 @@ static void meth_check_link(struct net_device *dev)
static int meth_init_tx_ring(struct meth_private *priv)
{
/* Init TX ring */
- priv->tx_ring = dma_zalloc_coherent(NULL, TX_RING_BUFFER_SIZE,
- &priv->tx_ring_dma, GFP_ATOMIC);
+ priv->tx_ring = dma_alloc_coherent(&priv->pdev->dev,
+ TX_RING_BUFFER_SIZE, &priv->tx_ring_dma, GFP_ATOMIC);
if (!priv->tx_ring)
return -ENOMEM;
@@ -236,7 +238,7 @@ static int meth_init_rx_ring(struct meth_private *priv)
priv->rx_ring[i]=(rx_packet*)(priv->rx_skbs[i]->head);
/* I'll need to re-sync it after each RX */
priv->rx_ring_dmas[i] =
- dma_map_single(NULL, priv->rx_ring[i],
+ dma_map_single(&priv->pdev->dev, priv->rx_ring[i],
METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
mace->eth.rx_fifo = priv->rx_ring_dmas[i];
}
@@ -253,7 +255,7 @@ static void meth_free_tx_ring(struct meth_private *priv)
dev_kfree_skb(priv->tx_skbs[i]);
priv->tx_skbs[i] = NULL;
}
- dma_free_coherent(NULL, TX_RING_BUFFER_SIZE, priv->tx_ring,
+ dma_free_coherent(&priv->pdev->dev, TX_RING_BUFFER_SIZE, priv->tx_ring,
priv->tx_ring_dma);
}
@@ -263,7 +265,7 @@ static void meth_free_rx_ring(struct meth_private *priv)
int i;
for (i = 0; i < RX_RING_ENTRIES; i++) {
- dma_unmap_single(NULL, priv->rx_ring_dmas[i],
+ dma_unmap_single(&priv->pdev->dev, priv->rx_ring_dmas[i],
METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
priv->rx_ring[i] = 0;
priv->rx_ring_dmas[i] = 0;
@@ -393,7 +395,8 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
fifo_rptr = (fifo_rptr - 1) & 0x0f;
}
while (priv->rx_write != fifo_rptr) {
- dma_unmap_single(NULL, priv->rx_ring_dmas[priv->rx_write],
+ dma_unmap_single(&priv->pdev->dev,
+ priv->rx_ring_dmas[priv->rx_write],
METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
status = priv->rx_ring[priv->rx_write]->status.raw;
#if MFE_DEBUG
@@ -454,7 +457,8 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
priv->rx_ring[priv->rx_write] = (rx_packet*)skb->head;
priv->rx_ring[priv->rx_write]->status.raw = 0;
priv->rx_ring_dmas[priv->rx_write] =
- dma_map_single(NULL, priv->rx_ring[priv->rx_write],
+ dma_map_single(&priv->pdev->dev,
+ priv->rx_ring[priv->rx_write],
METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
mace->eth.rx_fifo = priv->rx_ring_dmas[priv->rx_write];
ADVANCE_RX_PTR(priv->rx_write);
@@ -521,7 +525,7 @@ static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
DPRINTK("RPTR points us here, but packet not done?\n");
break;
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
priv->tx_skbs[priv->tx_read] = NULL;
priv->tx_ring[priv->tx_read].header.raw = 0;
priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1);
@@ -637,7 +641,7 @@ static void meth_tx_1page_prepare(struct meth_private *priv,
}
/* first page */
- catbuf = dma_map_single(NULL, buffer_data, buffer_len,
+ catbuf = dma_map_single(&priv->pdev->dev, buffer_data, buffer_len,
DMA_TO_DEVICE);
desc->data.cat_buf[0].form.start_addr = catbuf >> 3;
desc->data.cat_buf[0].form.len = buffer_len - 1;
@@ -663,12 +667,12 @@ static void meth_tx_2page_prepare(struct meth_private *priv,
}
/* first page */
- catbuf1 = dma_map_single(NULL, buffer1_data, buffer1_len,
+ catbuf1 = dma_map_single(&priv->pdev->dev, buffer1_data, buffer1_len,
DMA_TO_DEVICE);
desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3;
desc->data.cat_buf[0].form.len = buffer1_len - 1;
/* second page */
- catbuf2 = dma_map_single(NULL, buffer2_data, buffer2_len,
+ catbuf2 = dma_map_single(&priv->pdev->dev, buffer2_data, buffer2_len,
DMA_TO_DEVICE);
desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3;
desc->data.cat_buf[1].form.len = buffer2_len - 1;
@@ -840,6 +844,7 @@ static int meth_probe(struct platform_device *pdev)
memcpy(dev->dev_addr, o2meth_eaddr, ETH_ALEN);
priv = netdev_priv(dev);
+ priv->pdev = pdev;
spin_lock_init(&priv->meth_lock);
SET_NETDEV_DEV(dev, &pdev->dev);
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index 808cf9816673..5b351beb78cb 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -714,7 +714,7 @@ static void sis190_tx_interrupt(struct net_device *dev,
sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
tp->Tx_skbuff[entry] = NULL;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
if (tp->dirty_tx != dirty_tx) {
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index 4bb89f74742c..6073387511f8 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -1927,7 +1927,7 @@ static void sis900_finish_xmit (struct net_device *net_dev)
pci_unmap_single(sis_priv->pci_dev,
sis_priv->tx_ring[entry].bufptr, skb->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
sis_priv->tx_skbuff[entry] = NULL;
sis_priv->tx_ring[entry].bufptr = 0;
sis_priv->tx_ring[entry].cmdsts = 0;
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 15c62c160953..be47d864f8b9 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -1037,7 +1037,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
skb = ep->tx_skbuff[entry];
pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
ep->tx_skbuff[entry] = NULL;
}
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 8355dfbb8ec3..b550e624500d 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1188,7 +1188,7 @@ smc911x_tx_dma_irq(void *data)
DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, dev, "TX DMA irq handler\n");
BUG_ON(skb == NULL);
- dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE);
+ dma_unmap_single(lp->dev, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE);
netif_trans_update(dev);
dev_kfree_skb_irq(skb);
lp->current_tx_skb = NULL;
@@ -1219,7 +1219,7 @@ smc911x_rx_dma_irq(void *data)
DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__);
DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, dev, "RX DMA irq handler\n");
- dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE);
+ dma_unmap_single(lp->dev, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE);
BUG_ON(skb == NULL);
lp->current_rx_skb = NULL;
PRINT_PKT(skb->data, skb->len);
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 05a0948ad929..a18149720aa2 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1029,8 +1029,8 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
struct netsec_desc_ring *dring = &priv->desc_ring[id];
int i;
- dring->vaddr = dma_zalloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
- &dring->desc_dma, GFP_KERNEL);
+ dring->vaddr = dma_alloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
+ &dring->desc_dma, GFP_KERNEL);
if (!dring->vaddr)
goto err;
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 6209cc1fb305..f194235153f9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -105,6 +105,16 @@ config DWMAC_OXNAS
This selects the Oxford Semiconductor OXNASSoC glue layer support for
the stmmac device driver. This driver is used for OX820.
+config DWMAC_QCOM_ETHQOS
+ tristate "Qualcomm ETHQOS support"
+ default ARCH_QCOM
+ depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ help
+ Support for the Qualcomm ETHQOS core.
+
+ This selects the Qualcomm ETHQOS glue layer support for the
+ stmmac device driver.
+
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"
default ARCH_ROCKCHIP
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index bf09701d2623..c529c21e9bdd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
+obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
new file mode 100644
index 000000000000..7ec895407d23
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-19, Linaro Limited
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+#define RGMII_IO_MACRO_CONFIG 0x0
+#define SDCC_HC_REG_DLL_CONFIG 0x4
+#define SDCC_HC_REG_DDR_CONFIG 0xC
+#define SDCC_HC_REG_DLL_CONFIG2 0x10
+#define SDC4_STATUS 0x14
+#define SDCC_USR_CTL 0x18
+#define RGMII_IO_MACRO_CONFIG2 0x1C
+#define RGMII_IO_MACRO_DEBUG1 0x20
+#define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28
+
+/* RGMII_IO_MACRO_CONFIG fields */
+#define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
+#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23)
+#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20)
+#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17)
+#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8)
+#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6)
+#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4)
+#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3)
+#define RGMII_CONFIG_LOOPBACK_EN BIT(2)
+#define RGMII_CONFIG_PROG_SWAP BIT(1)
+#define RGMII_CONFIG_DDR_MODE BIT(0)
+
+/* SDCC_HC_REG_DLL_CONFIG fields */
+#define SDCC_DLL_CONFIG_DLL_RST BIT(30)
+#define SDCC_DLL_CONFIG_PDN BIT(29)
+#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24)
+#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20)
+#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19)
+#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18)
+#define SDCC_DLL_CONFIG_CDR_EN BIT(17)
+#define SDCC_DLL_CONFIG_DLL_EN BIT(16)
+#define SDCC_DLL_MCLK_GATING_EN BIT(5)
+#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2)
+
+/* SDCC_HC_REG_DDR_CONFIG fields */
+#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
+#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
+
+/* SDCC_HC_REG_DLL_CONFIG2 fields */
+#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21)
+#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10)
+#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2)
+#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1)
+#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0)
+
+/* SDC4_STATUS bits */
+#define SDC4_STATUS_DLL_LOCK BIT(7)
+
+/* RGMII_IO_MACRO_CONFIG2 fields */
+#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17)
+#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16)
+#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13)
+#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12)
+#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7)
+#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
+#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
+
+struct ethqos_emac_por {
+ unsigned int offset;
+ unsigned int value;
+};
+
+struct qcom_ethqos {
+ struct platform_device *pdev;
+ void __iomem *rgmii_base;
+
+ unsigned int rgmii_clk_rate;
+ struct clk *rgmii_clk;
+ unsigned int speed;
+
+ const struct ethqos_emac_por *por;
+ unsigned int num_por;
+};
+
+static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
+{
+ return readl(ethqos->rgmii_base + offset);
+}
+
+static void rgmii_writel(struct qcom_ethqos *ethqos,
+ int value, unsigned int offset)
+{
+ writel(value, ethqos->rgmii_base + offset);
+}
+
+static void rgmii_updatel(struct qcom_ethqos *ethqos,
+ int mask, int val, unsigned int offset)
+{
+ unsigned int temp;
+
+ temp = rgmii_readl(ethqos, offset);
+ temp = (temp & ~(mask)) | val;
+ rgmii_writel(ethqos, temp, offset);
+}
+
+static void rgmii_dump(struct qcom_ethqos *ethqos)
+{
+ dev_dbg(&ethqos->pdev->dev, "Rgmii register dump\n");
+ dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
+ rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
+ dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
+ rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
+ dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
+ rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
+ dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
+ rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
+ dev_dbg(&ethqos->pdev->dev, "SDC4_STATUS: %x\n",
+ rgmii_readl(ethqos, SDC4_STATUS));
+ dev_dbg(&ethqos->pdev->dev, "SDCC_USR_CTL: %x\n",
+ rgmii_readl(ethqos, SDCC_USR_CTL));
+ dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
+ rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
+ dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
+ rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
+ dev_dbg(&ethqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
+ rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
+}
+
+/* Clock rates */
+#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL)
+#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL)
+#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
+
+static void
+ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed)
+{
+ switch (speed) {
+ case SPEED_1000:
+ ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ;
+ break;
+
+ case SPEED_100:
+ ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
+ break;
+
+ case SPEED_10:
+ ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
+ break;
+ }
+
+ clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate);
+}
+
+static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
+{
+ rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
+ RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
+}
+
+static const struct ethqos_emac_por emac_v2_3_0_por[] = {
+ { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C },
+ { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 },
+ { .offset = SDCC_USR_CTL, .value = 0x00010800 },
+ { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 },
+};
+
+static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
+{
+ unsigned int val;
+ int retry = 1000;
+
+ /* Set CDR_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN,
+ SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Set CDR_EXT_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN,
+ SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Clear CK_OUT_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
+ 0, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Set DLL_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
+ SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
+
+ rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
+ 0, SDCC_HC_REG_DLL_CONFIG);
+
+ rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
+ 0, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Wait for CK_OUT_EN clear */
+ do {
+ val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
+ val &= SDCC_DLL_CONFIG_CK_OUT_EN;
+ if (!val)
+ break;
+ mdelay(1);
+ retry--;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(&ethqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
+
+ /* Set CK_OUT_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
+ SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Wait for CK_OUT_EN set */
+ retry = 1000;
+ do {
+ val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
+ val &= SDCC_DLL_CONFIG_CK_OUT_EN;
+ if (val)
+ break;
+ mdelay(1);
+ retry--;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(&ethqos->pdev->dev, "Set CK_OUT_EN timedout\n");
+
+ /* Set DDR_CAL_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
+ SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
+
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
+ 0, SDCC_HC_REG_DLL_CONFIG2);
+
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
+ 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
+
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
+ BIT(2), SDCC_HC_REG_DLL_CONFIG2);
+
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
+ SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
+ SDCC_HC_REG_DLL_CONFIG2);
+
+ return 0;
+}
+
+static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
+{
+ /* Disable loopback mode */
+ rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
+ 0, RGMII_IO_MACRO_CONFIG2);
+
+ /* Select RGMII, write 0 to interface select */
+ rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL,
+ 0, RGMII_IO_MACRO_CONFIG);
+
+ switch (ethqos->speed) {
+ case SPEED_1000:
+ rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
+ RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
+ 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
+ RGMII_CONFIG_POS_NEG_DATA_SEL,
+ RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
+ RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_IO_MACRO_CONFIG2);
+
+ /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
+ 57, SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
+ SDCC_DDR_CONFIG_PRG_DLY_EN,
+ SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
+ RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
+ break;
+
+ case SPEED_100:
+ rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
+ RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
+ RGMII_CONFIG_BYPASS_TX_ID_EN,
+ RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
+ 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
+ BIT(6), RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ /* Write 0x5 to PRG_RCLK_DLY_CODE */
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
+ (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
+ SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
+ SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
+ RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
+ break;
+
+ case SPEED_10:
+ rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
+ RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
+ RGMII_CONFIG_BYPASS_TX_ID_EN,
+ RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
+ 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
+ BIT(12) | GENMASK(9, 8),
+ RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ /* Write 0x5 to PRG_RCLK_DLY_CODE */
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
+ (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
+ SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
+ SDCC_HC_REG_DDR_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
+ RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
+ break;
+ default:
+ dev_err(&ethqos->pdev->dev,
+ "Invalid speed %d\n", ethqos->speed);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ethqos_configure(struct qcom_ethqos *ethqos)
+{
+ volatile unsigned int dll_lock;
+ unsigned int i, retry = 1000;
+
+ /* Reset to POR values and enable clk */
+ for (i = 0; i < ethqos->num_por; i++)
+ rgmii_writel(ethqos, ethqos->por[i].value,
+ ethqos->por[i].offset);
+ ethqos_set_func_clk_en(ethqos);
+
+ /* Initialize the DLL first */
+
+ /* Set DLL_RST */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST,
+ SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Set PDN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
+ SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Clear DLL_RST */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0,
+ SDCC_HC_REG_DLL_CONFIG);
+
+ /* Clear PDN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0,
+ SDCC_HC_REG_DLL_CONFIG);
+
+ if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) {
+ /* Set DLL_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
+ SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
+
+ /* Set CK_OUT_EN */
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
+ SDCC_DLL_CONFIG_CK_OUT_EN,
+ SDCC_HC_REG_DLL_CONFIG);
+
+ /* Set USR_CTL bit 26 with mask of 3 bits */
+ rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL);
+
+ /* wait for DLL LOCK */
+ do {
+ mdelay(1);
+ dll_lock = rgmii_readl(ethqos, SDC4_STATUS);
+ if (dll_lock & SDC4_STATUS_DLL_LOCK)
+ break;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(&ethqos->pdev->dev,
+ "Timeout while waiting for DLL lock\n");
+ }
+
+ if (ethqos->speed == SPEED_1000)
+ ethqos_dll_configure(ethqos);
+
+ ethqos_rgmii_macro_init(ethqos);
+
+ return 0;
+}
+
+static void ethqos_fix_mac_speed(void *priv, unsigned int speed)
+{
+ struct qcom_ethqos *ethqos = priv;
+
+ ethqos->speed = speed;
+ ethqos_update_rgmii_clk(ethqos, speed);
+ ethqos_configure(ethqos);
+}
+
+static int qcom_ethqos_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct qcom_ethqos *ethqos;
+ struct resource *res;
+ int ret;
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+ if (IS_ERR(plat_dat)) {
+ dev_err(&pdev->dev, "dt configuration failed\n");
+ return PTR_ERR(plat_dat);
+ }
+
+ ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
+ if (!ethqos) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ ethqos->pdev = pdev;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii");
+ ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ethqos->rgmii_base)) {
+ dev_err(&pdev->dev, "Can't get rgmii base\n");
+ ret = PTR_ERR(ethqos->rgmii_base);
+ goto err_mem;
+ }
+
+ ethqos->por = of_device_get_match_data(&pdev->dev);
+
+ ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
+ if (IS_ERR(ethqos->rgmii_clk)) {
+ ret = PTR_ERR(ethqos->rgmii_clk);
+ goto err_mem;
+ }
+
+ ret = clk_prepare_enable(ethqos->rgmii_clk);
+ if (ret)
+ goto err_mem;
+
+ ethqos->speed = SPEED_1000;
+ ethqos_update_rgmii_clk(ethqos, SPEED_1000);
+ ethqos_set_func_clk_en(ethqos);
+
+ plat_dat->bsp_priv = ethqos;
+ plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
+ plat_dat->has_gmac4 = 1;
+ plat_dat->pmt = 1;
+ plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ if (ret)
+ goto err_clk;
+
+ rgmii_dump(ethqos);
+
+ return ret;
+
+err_clk:
+ clk_disable_unprepare(ethqos->rgmii_clk);
+
+err_mem:
+ stmmac_remove_config_dt(pdev, plat_dat);
+
+ return ret;
+}
+
+static int qcom_ethqos_remove(struct platform_device *pdev)
+{
+ struct qcom_ethqos *ethqos;
+ int ret;
+
+ ethqos = get_stmmac_bsp_priv(&pdev->dev);
+ if (!ethqos)
+ return -ENODEV;
+
+ ret = stmmac_pltfr_remove(pdev);
+ clk_disable_unprepare(ethqos->rgmii_clk);
+
+ return ret;
+}
+
+static const struct of_device_id qcom_ethqos_match[] = {
+ { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
+
+static struct platform_driver qcom_ethqos_driver = {
+ .probe = qcom_ethqos_probe,
+ .remove = qcom_ethqos_remove,
+ .driver = {
+ .name = "qcom-ethqos",
+ .pm = &stmmac_pltfr_pm_ops,
+ .of_match_table = of_match_ptr(qcom_ethqos_match),
+ },
+};
+module_platform_driver(qcom_ethqos_driver);
+
+MODULE_DESCRIPTION("Qualcomm ETHQOS driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 7b923362ee55..3b174eae77c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1342,8 +1342,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
}
ret = phy_power_on(bsp_priv, true);
- if (ret)
+ if (ret) {
+ gmac_clk_enable(bsp_priv, false);
return ret;
+ }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index 20299f6f65fc..7fbb6a4dbf51 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -241,15 +241,18 @@ static inline void dwmac4_get_timestamp(void *desc, u32 ats, u64 *ts)
static int dwmac4_rx_check_timestamp(void *desc)
{
struct dma_desc *p = (struct dma_desc *)desc;
+ unsigned int rdes0 = le32_to_cpu(p->des0);
+ unsigned int rdes1 = le32_to_cpu(p->des1);
+ unsigned int rdes3 = le32_to_cpu(p->des3);
u32 own, ctxt;
int ret = 1;
- own = p->des3 & RDES3_OWN;
- ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR)
+ own = rdes3 & RDES3_OWN;
+ ctxt = ((rdes3 & RDES3_CONTEXT_DESCRIPTOR)
>> RDES3_CONTEXT_DESCRIPTOR_SHIFT);
if (likely(!own && ctxt)) {
- if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
+ if ((rdes0 == 0xffffffff) && (rdes1 == 0xffffffff))
/* Corrupted value */
ret = -EINVAL;
else
@@ -268,7 +271,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, void *next_desc,
int ret = -EINVAL;
/* Get the status from normal w/b descriptor */
- if (likely(p->des3 & TDES3_RS1V)) {
+ if (likely(le32_to_cpu(p->des3) & RDES3_RDES1_VALID)) {
if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) {
int i = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index 49f5687879df..545cb9c47433 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -124,9 +124,9 @@ void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan)
int dwmac4_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x, u32 chan)
{
- int ret = 0;
-
u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
+ u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
+ int ret = 0;
/* ABNORMAL interrupts */
if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) {
@@ -151,16 +151,11 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr,
if (likely(intr_status & DMA_CHAN_STATUS_NIS)) {
x->normal_irq_n++;
if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
- u32 value;
-
- value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
- /* to schedule NAPI on real RIE event. */
- if (likely(value & DMA_CHAN_INTR_ENA_RIE)) {
- x->rx_normal_irq_n++;
- ret |= handle_rx;
- }
+ x->rx_normal_irq_n++;
+ ret |= handle_rx;
}
- if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
+ if (likely(intr_status & (DMA_CHAN_STATUS_TI |
+ DMA_CHAN_STATUS_TBU))) {
x->tx_normal_irq_n++;
ret |= handle_tx;
}
@@ -168,12 +163,7 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr,
x->rx_early_irq++;
}
- /* Clear the interrupt by writing a logic 1 to the chanX interrupt
- * status [21-0] expect reserved bits [5-3]
- */
- writel((intr_status & 0x3fffc7),
- ioaddr + DMA_CHAN_STATUS(chan));
-
+ writel(intr_status & intr_en, ioaddr + DMA_CHAN_STATUS(chan));
return ret;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index d6bb953685fa..37d5e6fe7473 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -193,9 +193,10 @@
#define XGMAC_AIE BIT(14)
#define XGMAC_RBUE BIT(7)
#define XGMAC_RIE BIT(6)
+#define XGMAC_TBUE BIT(2)
#define XGMAC_TIE BIT(0)
#define XGMAC_DMA_INT_DEFAULT_EN (XGMAC_NIE | XGMAC_AIE | XGMAC_RBUE | \
- XGMAC_RIE | XGMAC_TIE)
+ XGMAC_RIE | XGMAC_TBUE | XGMAC_TIE)
#define XGMAC_DMA_CH_Rx_WATCHDOG(x) (0x0000313c + (0x80 * (x)))
#define XGMAC_RWT GENMASK(7, 0)
#define XGMAC_DMA_CH_STATUS(x) (0x00003160 + (0x80 * (x)))
@@ -204,6 +205,7 @@
#define XGMAC_FBE BIT(12)
#define XGMAC_RBU BIT(7)
#define XGMAC_RI BIT(6)
+#define XGMAC_TBU BIT(2)
#define XGMAC_TPS BIT(1)
#define XGMAC_TI BIT(0)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index 6c5092e7771c..2ba712b48a89 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -263,6 +263,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x, u32 chan)
{
u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
+ u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
int ret = 0;
/* ABNORMAL interrupts */
@@ -282,20 +283,17 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
x->normal_irq_n++;
if (likely(intr_status & XGMAC_RI)) {
- u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
- if (likely(value & XGMAC_RIE)) {
- x->rx_normal_irq_n++;
- ret |= handle_rx;
- }
+ x->rx_normal_irq_n++;
+ ret |= handle_rx;
}
- if (likely(intr_status & XGMAC_TI)) {
+ if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
x->tx_normal_irq_n++;
ret |= handle_tx;
}
}
/* Clear interrupts */
- writel(~0x0, ioaddr + XGMAC_DMA_CH_STATUS(chan));
+ writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));
return ret;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 63e1064b27a2..dd95d959c1ce 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
+#include <linux/net_tstamp.h>
#include <linux/reset.h>
struct stmmac_resources {
@@ -78,11 +79,10 @@ struct stmmac_rx_queue {
};
struct stmmac_channel {
- struct napi_struct napi ____cacheline_aligned_in_smp;
+ struct napi_struct rx_napi ____cacheline_aligned_in_smp;
+ struct napi_struct tx_napi ____cacheline_aligned_in_smp;
struct stmmac_priv *priv_data;
u32 index;
- int has_rx;
- int has_tx;
};
struct stmmac_tc_entry {
@@ -174,6 +174,7 @@ struct stmmac_priv {
unsigned int mode;
unsigned int chain_mode;
int extend_desc;
+ struct hwtstamp_config tstamp_config;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_ops;
unsigned int default_addend;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index d1f61c25d82b..3c749c327cbd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -696,33 +696,38 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
struct ethtool_eee *edata)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ int ret;
- priv->eee_enabled = edata->eee_enabled;
-
- if (!priv->eee_enabled)
+ if (!edata->eee_enabled) {
stmmac_disable_eee_mode(priv);
- else {
+ } else {
/* We are asking for enabling the EEE but it is safe
* to verify all by invoking the eee_init function.
* In case of failure it will return an error.
*/
- priv->eee_enabled = stmmac_eee_init(priv);
- if (!priv->eee_enabled)
+ edata->eee_enabled = stmmac_eee_init(priv);
+ if (!edata->eee_enabled)
return -EOPNOTSUPP;
-
- /* Do not change tx_lpi_timer in case of failure */
- priv->tx_lpi_timer = edata->tx_lpi_timer;
}
- return phy_ethtool_set_eee(dev->phydev, edata);
+ ret = phy_ethtool_set_eee(dev->phydev, edata);
+ if (ret)
+ return ret;
+
+ priv->eee_enabled = edata->eee_enabled;
+ priv->tx_lpi_timer = edata->tx_lpi_timer;
+ return 0;
}
static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
{
unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
- if (!clk)
- return 0;
+ if (!clk) {
+ clk = priv->plat->clk_ref_rate;
+ if (!clk)
+ return 0;
+ }
return (usec * (clk / 1000000)) / 256;
}
@@ -731,8 +736,11 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
{
unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
- if (!clk)
- return 0;
+ if (!clk) {
+ clk = priv->plat->clk_ref_rate;
+ if (!clk)
+ return 0;
+ }
return (riwt * 256) / (clk / 1000000);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0e0a0789c2ed..e2a13ec2e30b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -155,7 +155,10 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv)
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
- napi_disable(&ch->napi);
+ if (queue < rx_queues_cnt)
+ napi_disable(&ch->rx_napi);
+ if (queue < tx_queues_cnt)
+ napi_disable(&ch->tx_napi);
}
}
@@ -173,7 +176,10 @@ static void stmmac_enable_all_queues(struct stmmac_priv *priv)
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
- napi_enable(&ch->napi);
+ if (queue < rx_queues_cnt)
+ napi_enable(&ch->rx_napi);
+ if (queue < tx_queues_cnt)
+ napi_enable(&ch->tx_napi);
}
}
@@ -534,7 +540,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
}
/**
- * stmmac_hwtstamp_ioctl - control hardware timestamping.
+ * stmmac_hwtstamp_set - control hardware timestamping.
* @dev: device pointer.
* @ifr: An IOCTL specific structure, that can contain a pointer to
* a proprietary structure used to pass information to the driver.
@@ -544,7 +550,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
* Return Value:
* 0 on success and an appropriate -ve integer on failure.
*/
-static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct hwtstamp_config config;
@@ -573,7 +579,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
}
if (copy_from_user(&config, ifr->ifr_data,
- sizeof(struct hwtstamp_config)))
+ sizeof(config)))
return -EFAULT;
netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
@@ -597,12 +603,13 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
/* PTP v1, UDP, any kind of event packet */
config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
- /* take time stamp for all event messages */
- if (xmac)
- snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
- else
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
-
+ /* 'xmac' hardware can support Sync, Pdelay_Req and
+ * Pdelay_resp by setting bit14 and bits17/16 to 01
+ * This leaves Delay_Req timestamps out.
+ * Enable all events *and* general purpose message
+ * timestamping
+ */
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
break;
@@ -633,10 +640,7 @@ 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 */
- if (xmac)
- snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
- else
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -669,12 +673,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
/* PTP v2/802.AS1 any layer, any kind of event packet */
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
- /* take time stamp for all event messages */
- if (xmac)
- snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
- else
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
-
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
ptp_over_ethernet = PTP_TCR_TSIPENA;
@@ -765,8 +764,31 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
(u32)now.tv_sec, now.tv_nsec);
}
+ memcpy(&priv->tstamp_config, &config, sizeof(config));
+
return copy_to_user(ifr->ifr_data, &config,
- sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
+ sizeof(config)) ? -EFAULT : 0;
+}
+
+/**
+ * stmmac_hwtstamp_get - read hardware timestamping.
+ * @dev: device pointer.
+ * @ifr: An IOCTL specific structure, that can contain a pointer to
+ * a proprietary structure used to pass information to the driver.
+ * Description:
+ * This function obtain the current hardware timestamping settings
+ as requested.
+ */
+static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ struct hwtstamp_config *config = &priv->tstamp_config;
+
+ if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
+ return -EOPNOTSUPP;
+
+ return copy_to_user(ifr->ifr_data, config,
+ sizeof(*config)) ? -EFAULT : 0;
}
/**
@@ -1549,22 +1571,18 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
goto err_dma;
if (priv->extend_desc) {
- rx_q->dma_erx = dma_zalloc_coherent(priv->device,
- DMA_RX_SIZE *
- sizeof(struct
- dma_extended_desc),
- &rx_q->dma_rx_phy,
- GFP_KERNEL);
+ rx_q->dma_erx = dma_alloc_coherent(priv->device,
+ DMA_RX_SIZE * sizeof(struct dma_extended_desc),
+ &rx_q->dma_rx_phy,
+ GFP_KERNEL);
if (!rx_q->dma_erx)
goto err_dma;
} else {
- rx_q->dma_rx = dma_zalloc_coherent(priv->device,
- DMA_RX_SIZE *
- sizeof(struct
- dma_desc),
- &rx_q->dma_rx_phy,
- GFP_KERNEL);
+ rx_q->dma_rx = dma_alloc_coherent(priv->device,
+ DMA_RX_SIZE * sizeof(struct dma_desc),
+ &rx_q->dma_rx_phy,
+ GFP_KERNEL);
if (!rx_q->dma_rx)
goto err_dma;
}
@@ -1612,21 +1630,17 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
goto err_dma;
if (priv->extend_desc) {
- tx_q->dma_etx = dma_zalloc_coherent(priv->device,
- DMA_TX_SIZE *
- sizeof(struct
- dma_extended_desc),
- &tx_q->dma_tx_phy,
- GFP_KERNEL);
+ tx_q->dma_etx = dma_alloc_coherent(priv->device,
+ DMA_TX_SIZE * sizeof(struct dma_extended_desc),
+ &tx_q->dma_tx_phy,
+ GFP_KERNEL);
if (!tx_q->dma_etx)
goto err_dma;
} else {
- tx_q->dma_tx = dma_zalloc_coherent(priv->device,
- DMA_TX_SIZE *
- sizeof(struct
- dma_desc),
- &tx_q->dma_tx_phy,
- GFP_KERNEL);
+ tx_q->dma_tx = dma_alloc_coherent(priv->device,
+ DMA_TX_SIZE * sizeof(struct dma_desc),
+ &tx_q->dma_tx_phy,
+ GFP_KERNEL);
if (!tx_q->dma_tx)
goto err_dma;
}
@@ -1947,6 +1961,10 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
}
+ /* We still have pending packets, let's call for a new scheduling */
+ if (tx_q->dirty_tx != tx_q->cur_tx)
+ mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(10));
+
__netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
return count;
@@ -2037,23 +2055,15 @@ static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
int status = stmmac_dma_interrupt_status(priv, priv->ioaddr,
&priv->xstats, chan);
struct stmmac_channel *ch = &priv->channel[chan];
- bool needs_work = false;
-
- if ((status & handle_rx) && ch->has_rx) {
- needs_work = true;
- } else {
- status &= ~handle_rx;
- }
- if ((status & handle_tx) && ch->has_tx) {
- needs_work = true;
- } else {
- status &= ~handle_tx;
+ if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
+ stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+ napi_schedule_irqoff(&ch->rx_napi);
}
- if (needs_work && napi_schedule_prep(&ch->napi)) {
+ if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
- __napi_schedule(&ch->napi);
+ napi_schedule_irqoff(&ch->tx_napi);
}
return status;
@@ -2249,8 +2259,14 @@ static void stmmac_tx_timer(struct timer_list *t)
ch = &priv->channel[tx_q->queue_index];
- if (likely(napi_schedule_prep(&ch->napi)))
- __napi_schedule(&ch->napi);
+ /*
+ * If NAPI is already running we can miss some events. Let's rearm
+ * the timer and try again.
+ */
+ if (likely(napi_schedule_prep(&ch->tx_napi)))
+ __napi_schedule(&ch->tx_napi);
+ else
+ mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(10));
}
/**
@@ -3031,10 +3047,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
tx_q = &priv->tx_queue[queue];
+ if (priv->tx_path_in_lpi_mode)
+ stmmac_disable_eee_mode(priv);
+
/* Manage oversized TCP frames for GMAC4 device */
if (skb_is_gso(skb) && priv->tso) {
- if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+ /*
+ * There is no way to determine the number of TSO
+ * capable Queues. Let's use always the Queue 0
+ * because if TSO is supported then at least this
+ * one will be capable.
+ */
+ skb_set_queue_mapping(skb, 0);
+
return stmmac_tso_xmit(skb, dev);
+ }
}
if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
@@ -3049,9 +3077,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- if (priv->tx_path_in_lpi_mode)
- stmmac_disable_eee_mode(priv);
-
entry = tx_q->cur_tx;
first_entry = entry;
WARN_ON(tx_q->tx_skbuff[first_entry]);
@@ -3497,7 +3522,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
- napi_gro_receive(&ch->napi, skb);
+ napi_gro_receive(&ch->rx_napi, skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
@@ -3512,41 +3537,47 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
return count;
}
-/**
- * stmmac_poll - stmmac poll method (NAPI)
- * @napi : pointer to the napi structure.
- * @budget : maximum number of packets that the current CPU can receive from
- * all interfaces.
- * Description :
- * To look at the incoming frames and clear the tx resources.
- */
-static int stmmac_napi_poll(struct napi_struct *napi, int budget)
+static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
{
struct stmmac_channel *ch =
- container_of(napi, struct stmmac_channel, napi);
+ container_of(napi, struct stmmac_channel, rx_napi);
struct stmmac_priv *priv = ch->priv_data;
- int work_done = 0, work_rem = budget;
u32 chan = ch->index;
+ int work_done;
priv->xstats.napi_poll++;
- if (ch->has_tx) {
- int done = stmmac_tx_clean(priv, work_rem, chan);
+ work_done = stmmac_rx(priv, budget, chan);
+ if (work_done < budget && napi_complete_done(napi, work_done))
+ stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+ return work_done;
+}
- work_done += done;
- work_rem -= done;
- }
+static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
+{
+ struct stmmac_channel *ch =
+ container_of(napi, struct stmmac_channel, tx_napi);
+ struct stmmac_priv *priv = ch->priv_data;
+ struct stmmac_tx_queue *tx_q;
+ u32 chan = ch->index;
+ int work_done;
- if (ch->has_rx) {
- int done = stmmac_rx(priv, work_rem, chan);
+ priv->xstats.napi_poll++;
- work_done += done;
- work_rem -= done;
- }
+ work_done = stmmac_tx_clean(priv, DMA_TX_SIZE, chan);
+ work_done = min(work_done, budget);
if (work_done < budget && napi_complete_done(napi, work_done))
stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+ /* Force transmission restart */
+ tx_q = &priv->tx_queue[chan];
+ if (tx_q->cur_tx != tx_q->dirty_tx) {
+ stmmac_enable_dma_transmission(priv, priv->ioaddr);
+ stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr,
+ chan);
+ }
+
return work_done;
}
@@ -3774,7 +3805,10 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ret = phy_mii_ioctl(dev->phydev, rq, cmd);
break;
case SIOCSHWTSTAMP:
- ret = stmmac_hwtstamp_ioctl(dev, rq);
+ ret = stmmac_hwtstamp_set(dev, rq);
+ break;
+ case SIOCGHWTSTAMP:
+ ret = stmmac_hwtstamp_get(dev, rq);
break;
default:
break;
@@ -4168,6 +4202,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
return ret;
}
+ /* Rx Watchdog is available in the COREs newer than the 3.40.
+ * In some case, for example on bugged HW this feature
+ * has to be disable and this can be done by passing the
+ * riwt_off field from the platform.
+ */
+ if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
+ (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+ priv->use_riwt = 1;
+ dev_info(priv->device,
+ "Enable RX Mitigation via HW Watchdog Timer\n");
+ }
+
return 0;
}
@@ -4300,18 +4346,6 @@ int stmmac_dvr_probe(struct device *device,
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
- /* Rx Watchdog is available in the COREs newer than the 3.40.
- * In some case, for example on bugged HW this feature
- * has to be disable and this can be done by passing the
- * riwt_off field from the platform.
- */
- if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
- (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
- priv->use_riwt = 1;
- dev_info(priv->device,
- "Enable RX Mitigation via HW Watchdog Timer\n");
- }
-
/* Setup channels NAPI */
maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
@@ -4321,13 +4355,14 @@ int stmmac_dvr_probe(struct device *device,
ch->priv_data = priv;
ch->index = queue;
- if (queue < priv->plat->rx_queues_to_use)
- ch->has_rx = true;
- if (queue < priv->plat->tx_queues_to_use)
- ch->has_tx = true;
-
- netif_napi_add(ndev, &ch->napi, stmmac_napi_poll,
- NAPI_POLL_WEIGHT);
+ if (queue < priv->plat->rx_queues_to_use) {
+ netif_napi_add(ndev, &ch->rx_napi, stmmac_napi_poll_rx,
+ NAPI_POLL_WEIGHT);
+ }
+ if (queue < priv->plat->tx_queues_to_use) {
+ netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx,
+ NAPI_POLL_WEIGHT);
+ }
}
mutex_init(&priv->lock);
@@ -4383,7 +4418,10 @@ error_mdio_register:
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
- netif_napi_del(&ch->napi);
+ if (queue < priv->plat->rx_queues_to_use)
+ netif_napi_del(&ch->rx_napi);
+ if (queue < priv->plat->tx_queues_to_use)
+ netif_napi_del(&ch->tx_napi);
}
error_hw_init:
destroy_workqueue(priv->wq);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index c54a50dbd5ac..d819e8eaba12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
*/
static void stmmac_pci_remove(struct pci_dev *pdev)
{
+ int i;
+
stmmac_dvr_remove(&pdev->dev);
+
+ for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+ if (pci_resource_len(pdev, i) == 0)
+ continue;
+ pcim_iounmap_regions(pdev, BIT(i));
+ break;
+ }
+
pci_disable_device(pdev);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index ecccf895fd7e..e852821289cf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -59,9 +59,14 @@
#define PTP_TCR_TSEVNTENA BIT(14)
/* Enable Snapshot for Messages Relevant to Master */
#define PTP_TCR_TSMSTRENA BIT(15)
-/* Select PTP packets for Taking Snapshots */
+/* Select PTP packets for Taking Snapshots
+ * On gmac4 specifically:
+ * Enable SYNC, Pdelay_Req, Pdelay_Resp when TSEVNTENA is enabled.
+ * or
+ * Enable SYNC, Follow_Up, Delay_Req, Delay_Resp, Pdelay_Req, Pdelay_Resp,
+ * Pdelay_Resp_Follow_Up if TSEVNTENA is disabled
+ */
#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/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 531294f4978b..58ea18af9813 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -301,6 +301,8 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
/* Queue 0 is not AVB capable */
if (queue <= 0 || queue >= tx_queues_count)
return -EINVAL;
+ if (!priv->dma_cap.av)
+ return -EOPNOTSUPP;
if (priv->speed != SPEED_100 && priv->speed != SPEED_1000)
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index 9020b084b953..6fc05c106afc 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -1,22 +1,9 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
/* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
*
* Copyright (C) 2004 Sun Microsystems Inc.
* Copyright (C) 2003 Adrian Sun (asun@darksunrising.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.
- *
- * 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 driver uses the sungem driver (c) David Miller
* (davem@redhat.com) as its basis.
*
@@ -1911,7 +1898,7 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
cp->net_stats[ring].tx_packets++;
cp->net_stats[ring].tx_bytes += skb->len;
spin_unlock(&cp->stat_lock[ring]);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
cp->tx_old[ring] = entry;
diff --git a/drivers/net/ethernet/sun/cassini.h b/drivers/net/ethernet/sun/cassini.h
index 13f3860496a8..ae5f05f03f88 100644
--- a/drivers/net/ethernet/sun/cassini.h
+++ b/drivers/net/ethernet/sun/cassini.h
@@ -1,23 +1,10 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
/* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
* cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
*
* Copyright (C) 2004 Sun Microsystems Inc.
* Copyright (c) 2003 Adrian Sun (asun@darksunrising.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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
* vendor id: 0x108E (Sun Microsystems, Inc.)
* device id: 0xabba (Cassini)
* revision ids: 0x01 = Cassini
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 720b7ac77f3b..e9b757b03b56 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -781,7 +781,7 @@ static void bigmac_tx(struct bigmac *bp)
DTX(("skb(%p) ", skb));
bp->tx_skbs[elem] = NULL;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
elem = NEXT_TX(elem);
}
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index b9221fc1674d..3e7631160384 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2760,7 +2760,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
void __iomem *p = pci_map_rom(pdev, &size);
if (p) {
- int found;
+ int found;
found = readb(p) == 0x55 &&
readb(p + 1) == 0xaa &&
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index ff641cf30a4e..d007dfeba5c3 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -1962,7 +1962,7 @@ static void happy_meal_tx(struct happy_meal *hp)
this = &txbase[elem];
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
dev->stats.tx_packets++;
}
hp->tx_old = elem;
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index dc966ddb6d81..b24c11187017 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1739,7 +1739,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv)
tx_level -= db->rptr->len; /* '-' koz len is negative */
/* now should come skb pointer - free it */
- dev_kfree_skb_irq(db->rptr->addr.skb);
+ dev_consume_skb_irq(db->rptr->addr.skb);
bdx_tx_db_inc_rptr(db);
}
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index bb126be1eb72..8b21b40a9fe5 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -49,10 +49,11 @@ config TI_DAVINCI_CPDMA
will be called davinci_cpdma. This is recommended.
config TI_CPSW_PHY_SEL
- bool
+ bool "TI CPSW Phy mode Selection (DEPRECATED)"
+ default n
---help---
This driver supports configuring of the phy mode connected to
- the CPSW.
+ the CPSW. DEPRECATED: use PHY_TI_GMII_SEL.
config TI_CPSW_ALE
tristate "TI CPSW ALE Support"
@@ -64,7 +65,6 @@ config TI_CPSW
depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || COMPILE_TEST
select TI_DAVINCI_CPDMA
select TI_DAVINCI_MDIO
- select TI_CPSW_PHY_SEL
select TI_CPSW_ALE
select MFD_SYSCON
select REGMAP
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 810dfc7de1f9..e2d47b24a869 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -608,7 +608,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
netdev_dbg(dev, "sent 0x%p, len=%d\n",
desc->skb, desc->skb->len);
- dev_kfree_skb_irq(desc->skb);
+ dev_consume_skb_irq(desc->skb);
desc->skb = NULL;
if (__netif_subqueue_stopped(dev, queue))
netif_wake_subqueue(dev, queue);
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
index 396e1cd10667..fec275e2208d 100644
--- a/drivers/net/ethernet/ti/cpsw-phy-sel.c
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -78,7 +78,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv,
case PHY_INTERFACE_MODE_MII:
mode = AM33XX_GMII_SEL_MODE_MII;
break;
- };
+ }
mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
mask |= BIT(slave + 4);
@@ -133,7 +133,7 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv,
case PHY_INTERFACE_MODE_MII:
mode = AM33XX_GMII_SEL_MODE_MII;
break;
- };
+ }
switch (slave) {
case 0:
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index cf111db3dc27..907e05fc22e4 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -21,7 +21,13 @@
((mac)[2] << 16) | ((mac)[3] << 24))
#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8))
+#if IS_ENABLED(CONFIG_TI_CPSW_PHY_SEL)
void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave);
+#else
+static inline
+void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave)
+{}
+#endif
int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr);
#endif /* __CPSW_H__ */
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 1f612268c998..d847f672a705 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -259,7 +259,7 @@ static int netcp_module_probe(struct netcp_device *netcp_device,
const char *name;
char node_name[32];
- if (of_property_read_string(node, "label", &name) < 0) {
+ if (of_property_read_string(child, "label", &name) < 0) {
snprintf(node_name, sizeof(node_name), "%pOFn", child);
name = node_name;
}
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index edcd1e60b30d..37925a1d58de 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1311,13 +1311,13 @@ static int tsi108_open(struct net_device *dev)
data->id, dev->irq, dev->name);
}
- data->rxring = dma_zalloc_coherent(&data->pdev->dev, rxring_size,
- &data->rxdma, GFP_KERNEL);
+ data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size,
+ &data->rxdma, GFP_KERNEL);
if (!data->rxring)
return -ENOMEM;
- data->txring = dma_zalloc_coherent(&data->pdev->dev, txring_size,
- &data->txdma, GFP_KERNEL);
+ data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size,
+ &data->txdma, GFP_KERNEL);
if (!data->txring) {
dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring,
data->rxdma);
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 82412691ee66..27f6cf140845 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -1740,7 +1740,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
le16_to_cpu(pktlen), DMA_TO_DEVICE);
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
tdinfo->skb = NULL;
}
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 2241f9897092..44efffbe7970 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -243,15 +243,15 @@ static int temac_dma_bd_init(struct net_device *ndev)
/* allocate the tx and rx ring buffer descriptors. */
/* returns a virtual address and a physical address. */
- lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- &lp->tx_bd_p, GFP_KERNEL);
+ lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+ &lp->tx_bd_p, GFP_KERNEL);
if (!lp->tx_bd_v)
goto out;
- lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- &lp->rx_bd_p, GFP_KERNEL);
+ lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+ &lp->rx_bd_p, GFP_KERNEL);
if (!lp->rx_bd_v)
goto out;
@@ -630,7 +630,7 @@ static void temac_start_xmit_done(struct net_device *ndev)
dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len,
DMA_TO_DEVICE);
if (cur_p->app4)
- dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
+ dev_consume_skb_irq((struct sk_buff *)cur_p->app4);
cur_p->app0 = 0;
cur_p->app1 = 0;
cur_p->app2 = 0;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 12a14609ec47..ec7e7ec24ff9 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -199,15 +199,15 @@ static int axienet_dma_bd_init(struct net_device *ndev)
lp->rx_bd_ci = 0;
/* Allocate the Tx and Rx buffer descriptors. */
- lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- &lp->tx_bd_p, GFP_KERNEL);
+ lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+ &lp->tx_bd_p, GFP_KERNEL);
if (!lp->tx_bd_v)
goto out;
- lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- &lp->rx_bd_p, GFP_KERNEL);
+ lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+ &lp->rx_bd_p, GFP_KERNEL);
if (!lp->rx_bd_v)
goto out;
@@ -595,7 +595,7 @@ static void axienet_start_xmit_done(struct net_device *ndev)
(cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
DMA_TO_DEVICE);
if (cur_p->app4)
- dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
+ dev_consume_skb_irq((struct sk_buff *)cur_p->app4);
/*cur_p->phys = 0;*/
cur_p->app0 = 0;
cur_p->app1 = 0;
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 639e3e99af46..b03a417d0073 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -581,7 +581,7 @@ static void xemaclite_tx_handler(struct net_device *dev)
return;
dev->stats.tx_bytes += lp->deferred_skb->len;
- dev_kfree_skb_irq(lp->deferred_skb);
+ dev_consume_skb_irq(lp->deferred_skb);
lp->deferred_skb = NULL;
netif_trans_update(dev); /* prevent tx timeout */
netif_wake_queue(dev);
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index aee55c03def0..ed6623a9801e 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -139,7 +139,7 @@
#ifdef __ARMEB__
typedef struct sk_buff buffer_t;
#define free_buffer dev_kfree_skb
-#define free_buffer_irq dev_kfree_skb_irq
+#define free_buffer_irq dev_consume_skb_irq
#else
typedef void buffer_t;
#define free_buffer kfree
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index 61fceee73c1b..56b7791911bf 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -1139,9 +1139,9 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
#endif
sizeof(PI_CONSUMER_BLOCK) +
(PI_ALIGN_K_DESC_BLK - 1);
- bp->kmalloced = top_v = dma_zalloc_coherent(bp->bus_dev, alloc_size,
- &bp->kmalloced_dma,
- GFP_ATOMIC);
+ bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+ &bp->kmalloced_dma,
+ GFP_ATOMIC);
if (top_v == NULL)
return DFX_K_FAILURE;
@@ -3512,7 +3512,7 @@ static int dfx_xmt_done(DFX_board_t *bp)
bp->descr_block_virt->xmt_data[comp].long_1,
p_xmt_drv_descr->p_skb->len,
DMA_TO_DEVICE);
- dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+ dev_consume_skb_irq(p_xmt_drv_descr->p_skb);
/*
* Move to start of next packet by updating completion index
diff --git a/drivers/net/fddi/skfp/pcmplc.c b/drivers/net/fddi/skfp/pcmplc.c
index 6ef44c480bd5..f29f5a6a45ab 100644
--- a/drivers/net/fddi/skfp/pcmplc.c
+++ b/drivers/net/fddi/skfp/pcmplc.c
@@ -851,6 +851,7 @@ static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
case ACTIONS(PC5_SIGNAL) :
ACTIONS_DONE() ;
+ /* fall through */
case PC5_SIGNAL :
if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
break ;
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index 72433f3efc74..5d661f60b101 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -409,10 +409,10 @@ static int skfp_driver_init(struct net_device *dev)
if (bp->SharedMemSize > 0) {
bp->SharedMemSize += 16; // for descriptor alignment
- bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev,
- bp->SharedMemSize,
- &bp->SharedMemDMA,
- GFP_ATOMIC);
+ bp->SharedMemAddr = dma_alloc_coherent(&bp->pdev.dev,
+ bp->SharedMemSize,
+ &bp->SharedMemDMA,
+ GFP_ATOMIC);
if (!bp->SharedMemAddr) {
printk("could not allocate mem for ");
printk("hardware module: %ld byte\n",
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 58bbba8582b0..5583d993480d 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -692,15 +692,20 @@ out:
static int geneve_open(struct net_device *dev)
{
struct geneve_dev *geneve = netdev_priv(dev);
- bool ipv6 = !!(geneve->info.mode & IP_TUNNEL_INFO_IPV6);
bool metadata = geneve->collect_md;
+ bool ipv4, ipv6;
int ret = 0;
+ ipv6 = geneve->info.mode & IP_TUNNEL_INFO_IPV6 || metadata;
+ ipv4 = !ipv6 || metadata;
#if IS_ENABLED(CONFIG_IPV6)
- if (ipv6 || metadata)
+ if (ipv6) {
ret = geneve_sock_add(geneve, true);
+ if (ret < 0 && ret != -EAFNOSUPPORT)
+ ipv4 = false;
+ }
#endif
- if (!ret && (!ipv6 || metadata))
+ if (ipv4)
ret = geneve_sock_add(geneve, false);
if (ret < 0)
geneve_sock_release(geneve);
@@ -1512,9 +1517,13 @@ static void geneve_link_config(struct net_device *dev,
}
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6: {
- struct rt6_info *rt = rt6_lookup(geneve->net,
- &info->key.u.ipv6.dst, NULL, 0,
- NULL, 0);
+ struct rt6_info *rt;
+
+ if (!__in6_dev_get(dev))
+ break;
+
+ rt = rt6_lookup(geneve->net, &info->key.u.ipv6.dst, NULL, 0,
+ NULL, 0);
if (rt && rt->dst.dev)
ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 190f66c88479..ed0841630990 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -203,32 +203,6 @@ static inline void ser12_set_divisor(struct net_device *dev,
*/
}
-/* --------------------------------------------------------------------- */
-
-#if 0
-static inline unsigned int hweight16(unsigned int w)
- __attribute__ ((unused));
-static inline unsigned int hweight8(unsigned int w)
- __attribute__ ((unused));
-
-static inline unsigned int hweight16(unsigned int w)
-{
- unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
- res = (res & 0x3333) + ((res >> 2) & 0x3333);
- res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
- return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-static inline unsigned int hweight8(unsigned int w)
-{
- unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
- res = (res & 0x33) + ((res >> 2) & 0x33);
- return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs)
{
int timediff;
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index ef6f766f6389..e859ae2e42d5 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
u32 total_data_buflen;
};
+#define NETVSC_HASH_KEYLEN 40
+
struct netvsc_device_info {
unsigned char mac_adr[ETH_ALEN];
u32 num_chn;
@@ -151,6 +153,8 @@ struct netvsc_device_info {
u32 recv_sections;
u32 send_section_size;
u32 recv_section_size;
+
+ u8 rss_key[NETVSC_HASH_KEYLEN];
};
enum rndis_device_state {
@@ -160,8 +164,6 @@ enum rndis_device_state {
RNDIS_DEV_DATAINITIALIZED,
};
-#define NETVSC_HASH_KEYLEN 40
-
struct rndis_device {
struct net_device *ndev;
@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
void netvsc_channel_cb(void *context);
int netvsc_poll(struct napi_struct *napi, int budget);
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
+int rndis_set_subchannel(struct net_device *ndev,
+ struct netvsc_device *nvdev,
+ struct netvsc_device_info *dev_info);
int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev);
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {
enum rndis_per_pkt_info_interal_type {
RNDIS_PKTINFO_ID = 1,
- /* Add more memebers here */
+ /* Add more members here */
RNDIS_PKTINFO_MAX
};
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 922054c1d544..813d195bbd57 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
rdev = nvdev->extension;
if (rdev) {
- ret = rndis_set_subchannel(rdev->ndev, nvdev);
+ ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
if (ret == 0) {
netif_device_attach(rdev->ndev);
} else {
@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
if (napi_schedule_prep(&nvchan->napi)) {
- /* disable interupts from host */
+ /* disable interrupts from host */
hv_begin_read(rbi);
__napi_schedule_irqoff(&nvchan->napi);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 91ed15ea5883..cf4897043e83 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
{
int j = 0;
- /* Deal with compund pages by ignoring unused part
+ /* Deal with compound pages by ignoring unused part
* of the page.
*/
page += (offset >> PAGE_SHIFT);
@@ -744,6 +744,14 @@ void netvsc_linkstatus_callback(struct net_device *net,
schedule_delayed_work(&ndev_ctx->dwork, 0);
}
+static void netvsc_comp_ipcsum(struct sk_buff *skb)
+{
+ struct iphdr *iph = (struct iphdr *)skb->data;
+
+ iph->check = 0;
+ iph->check = ip_fast_csum(iph, iph->ihl);
+}
+
static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
struct netvsc_channel *nvchan)
{
@@ -770,9 +778,17 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
/* skb is already created with CHECKSUM_NONE */
skb_checksum_none_assert(skb);
- /*
- * In Linux, the IP checksum is always checked.
- * Do L4 checksum offload if enabled and present.
+ /* Incoming packets may have IP header checksum verified by the host.
+ * They may not have IP header checksum computed after coalescing.
+ * We compute it here if the flags are set, because on Linux, the IP
+ * checksum is always checked.
+ */
+ if (csum_info && csum_info->receive.ip_checksum_value_invalid &&
+ csum_info->receive.ip_checksum_succeeded &&
+ skb->protocol == htons(ETH_P_IP))
+ netvsc_comp_ipcsum(skb);
+
+ /* Do L4 checksum offload if enabled and present.
*/
if (csum_info && (net->features & NETIF_F_RXCSUM)) {
if (csum_info->receive.tcp_checksum_succeeded ||
@@ -858,6 +874,39 @@ static void netvsc_get_channels(struct net_device *net,
}
}
+/* Alloc struct netvsc_device_info, and initialize it from either existing
+ * struct netvsc_device, or from default values.
+ */
+static struct netvsc_device_info *netvsc_devinfo_get
+ (struct netvsc_device *nvdev)
+{
+ struct netvsc_device_info *dev_info;
+
+ dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);
+
+ if (!dev_info)
+ return NULL;
+
+ if (nvdev) {
+ dev_info->num_chn = nvdev->num_chn;
+ dev_info->send_sections = nvdev->send_section_cnt;
+ dev_info->send_section_size = nvdev->send_section_size;
+ dev_info->recv_sections = nvdev->recv_section_cnt;
+ dev_info->recv_section_size = nvdev->recv_section_size;
+
+ memcpy(dev_info->rss_key, nvdev->extension->rss_key,
+ NETVSC_HASH_KEYLEN);
+ } else {
+ dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
+ dev_info->send_sections = NETVSC_DEFAULT_TX;
+ dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
+ dev_info->recv_sections = NETVSC_DEFAULT_RX;
+ dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
+ }
+
+ return dev_info;
+}
+
static int netvsc_detach(struct net_device *ndev,
struct netvsc_device *nvdev)
{
@@ -909,7 +958,7 @@ static int netvsc_attach(struct net_device *ndev,
return PTR_ERR(nvdev);
if (nvdev->num_chn > 1) {
- ret = rndis_set_subchannel(ndev, nvdev);
+ ret = rndis_set_subchannel(ndev, nvdev, dev_info);
/* if unavailable, just proceed with one queue */
if (ret) {
@@ -943,7 +992,7 @@ static int netvsc_set_channels(struct net_device *net,
struct net_device_context *net_device_ctx = netdev_priv(net);
struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
unsigned int orig, count = channels->combined_count;
- struct netvsc_device_info device_info;
+ struct netvsc_device_info *device_info;
int ret;
/* We do not support separate count for rx, tx, or other */
@@ -962,24 +1011,26 @@ static int netvsc_set_channels(struct net_device *net,
orig = nvdev->num_chn;
- memset(&device_info, 0, sizeof(device_info));
- device_info.num_chn = count;
- device_info.send_sections = nvdev->send_section_cnt;
- device_info.send_section_size = nvdev->send_section_size;
- device_info.recv_sections = nvdev->recv_section_cnt;
- device_info.recv_section_size = nvdev->recv_section_size;
+ device_info = netvsc_devinfo_get(nvdev);
+
+ if (!device_info)
+ return -ENOMEM;
+
+ device_info->num_chn = count;
ret = netvsc_detach(net, nvdev);
if (ret)
- return ret;
+ goto out;
- ret = netvsc_attach(net, &device_info);
+ ret = netvsc_attach(net, device_info);
if (ret) {
- device_info.num_chn = orig;
- if (netvsc_attach(net, &device_info))
+ device_info->num_chn = orig;
+ if (netvsc_attach(net, device_info))
netdev_err(net, "restoring channel setting failed\n");
}
+out:
+ kfree(device_info);
return ret;
}
@@ -1048,48 +1099,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
int orig_mtu = ndev->mtu;
- struct netvsc_device_info device_info;
+ struct netvsc_device_info *device_info;
int ret = 0;
if (!nvdev || nvdev->destroy)
return -ENODEV;
+ device_info = netvsc_devinfo_get(nvdev);
+
+ if (!device_info)
+ return -ENOMEM;
+
/* Change MTU of underlying VF netdev first. */
if (vf_netdev) {
ret = dev_set_mtu(vf_netdev, mtu);
if (ret)
- return ret;
+ goto out;
}
- memset(&device_info, 0, sizeof(device_info));
- device_info.num_chn = nvdev->num_chn;
- device_info.send_sections = nvdev->send_section_cnt;
- device_info.send_section_size = nvdev->send_section_size;
- device_info.recv_sections = nvdev->recv_section_cnt;
- device_info.recv_section_size = nvdev->recv_section_size;
-
ret = netvsc_detach(ndev, nvdev);
if (ret)
goto rollback_vf;
ndev->mtu = mtu;
- ret = netvsc_attach(ndev, &device_info);
- if (ret)
- goto rollback;
-
- return 0;
+ ret = netvsc_attach(ndev, device_info);
+ if (!ret)
+ goto out;
-rollback:
/* Attempt rollback to original MTU */
ndev->mtu = orig_mtu;
- if (netvsc_attach(ndev, &device_info))
+ if (netvsc_attach(ndev, device_info))
netdev_err(ndev, "restoring mtu failed\n");
rollback_vf:
if (vf_netdev)
dev_set_mtu(vf_netdev, orig_mtu);
+out:
+ kfree(device_info);
return ret;
}
@@ -1674,7 +1722,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
{
struct net_device_context *ndevctx = netdev_priv(ndev);
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
- struct netvsc_device_info device_info;
+ struct netvsc_device_info *device_info;
struct ethtool_ringparam orig;
u32 new_tx, new_rx;
int ret = 0;
@@ -1694,26 +1742,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
new_rx == orig.rx_pending)
return 0; /* no change */
- memset(&device_info, 0, sizeof(device_info));
- device_info.num_chn = nvdev->num_chn;
- device_info.send_sections = new_tx;
- device_info.send_section_size = nvdev->send_section_size;
- device_info.recv_sections = new_rx;
- device_info.recv_section_size = nvdev->recv_section_size;
+ device_info = netvsc_devinfo_get(nvdev);
+
+ if (!device_info)
+ return -ENOMEM;
+
+ device_info->send_sections = new_tx;
+ device_info->recv_sections = new_rx;
ret = netvsc_detach(ndev, nvdev);
if (ret)
- return ret;
+ goto out;
- ret = netvsc_attach(ndev, &device_info);
+ ret = netvsc_attach(ndev, device_info);
if (ret) {
- device_info.send_sections = orig.tx_pending;
- device_info.recv_sections = orig.rx_pending;
+ device_info->send_sections = orig.tx_pending;
+ device_info->recv_sections = orig.rx_pending;
- if (netvsc_attach(ndev, &device_info))
+ if (netvsc_attach(ndev, device_info))
netdev_err(ndev, "restoring ringparam failed");
}
+out:
+ kfree(device_info);
return ret;
}
@@ -2088,7 +2139,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
return NOTIFY_DONE;
- /* if syntihetic interface is a different namespace,
+ /* if synthetic interface is a different namespace,
* then move the VF to that namespace; join will be
* done again in that context.
*/
@@ -2167,7 +2218,7 @@ static int netvsc_probe(struct hv_device *dev,
{
struct net_device *net = NULL;
struct net_device_context *net_device_ctx;
- struct netvsc_device_info device_info;
+ struct netvsc_device_info *device_info = NULL;
struct netvsc_device *nvdev;
int ret = -ENOMEM;
@@ -2214,21 +2265,21 @@ static int netvsc_probe(struct hv_device *dev,
netif_set_real_num_rx_queues(net, 1);
/* Notify the netvsc driver of the new device */
- memset(&device_info, 0, sizeof(device_info));
- device_info.num_chn = VRSS_CHANNEL_DEFAULT;
- device_info.send_sections = NETVSC_DEFAULT_TX;
- device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
- device_info.recv_sections = NETVSC_DEFAULT_RX;
- device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
-
- nvdev = rndis_filter_device_add(dev, &device_info);
+ device_info = netvsc_devinfo_get(NULL);
+
+ if (!device_info) {
+ ret = -ENOMEM;
+ goto devinfo_failed;
+ }
+
+ nvdev = rndis_filter_device_add(dev, device_info);
if (IS_ERR(nvdev)) {
ret = PTR_ERR(nvdev);
netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
goto rndis_failed;
}
- memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+ memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);
/* We must get rtnl lock before scheduling nvdev->subchan_work,
* otherwise netvsc_subchan_work() can get rtnl lock first and wait
@@ -2236,7 +2287,7 @@ static int netvsc_probe(struct hv_device *dev,
* netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
* -> ... -> device_add() -> ... -> __device_attach() can't get
* the device lock, so all the subchannels can't be processed --
- * finally netvsc_subchan_work() hangs for ever.
+ * finally netvsc_subchan_work() hangs forever.
*/
rtnl_lock();
@@ -2266,12 +2317,16 @@ static int netvsc_probe(struct hv_device *dev,
list_add(&net_device_ctx->list, &netvsc_dev_list);
rtnl_unlock();
+
+ kfree(device_info);
return 0;
register_failed:
rtnl_unlock();
rndis_filter_device_remove(dev, nvdev);
rndis_failed:
+ kfree(device_info);
+devinfo_failed:
free_percpu(net_device_ctx->vf_stats);
no_stats:
hv_set_drvdata(dev, NULL);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 8b537a049c1e..73b60592de06 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -774,8 +774,8 @@ cleanup:
return ret;
}
-int rndis_filter_set_rss_param(struct rndis_device *rdev,
- const u8 *rss_key)
+static int rndis_set_rss_param_msg(struct rndis_device *rdev,
+ const u8 *rss_key, u16 flag)
{
struct net_device *ndev = rdev->ndev;
struct rndis_request *request;
@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
- rssp->flag = 0;
+ rssp->flag = flag;
rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
NDIS_HASH_TCP_IPV6;
@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
wait_for_completion(&request->wait_event);
set_complete = &request->response_msg.msg.set_complete;
- if (set_complete->status == RNDIS_STATUS_SUCCESS)
- memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
- else {
+ if (set_complete->status == RNDIS_STATUS_SUCCESS) {
+ if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
+ !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
+ memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
+
+ } else {
netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
set_complete->status);
ret = -EINVAL;
@@ -842,6 +845,16 @@ cleanup:
return ret;
}
+int rndis_filter_set_rss_param(struct rndis_device *rdev,
+ const u8 *rss_key)
+{
+ /* Disable RSS before change */
+ rndis_set_rss_param_msg(rdev, rss_key,
+ NDIS_RSS_PARAM_FLAG_DISABLE_RSS);
+
+ return rndis_set_rss_param_msg(rdev, rss_key, 0);
+}
+
static int rndis_filter_query_device_link_status(struct rndis_device *dev,
struct netvsc_device *net_device)
{
@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
* This breaks overlap of processing the host message for the
* new primary channel with the initialization of sub-channels.
*/
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
+int rndis_set_subchannel(struct net_device *ndev,
+ struct netvsc_device *nvdev,
+ struct netvsc_device_info *dev_info)
{
struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
struct net_device_context *ndev_ctx = netdev_priv(ndev);
@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
wait_event(nvdev->subchan_open,
atomic_read(&nvdev->open_chn) == nvdev->num_chn);
- /* ignore failues from setting rss parameters, still have channels */
- rndis_filter_set_rss_param(rdev, netvsc_hash_key);
+ /* ignore failures from setting rss parameters, still have channels */
+ if (dev_info)
+ rndis_filter_set_rss_param(rdev, dev_info->rss_key);
+ else
+ rndis_filter_set_rss_param(rdev, netvsc_hash_key);
netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
index 44de81e5f140..c589f5ae75bb 100644
--- a/drivers/net/ieee802154/mcr20a.c
+++ b/drivers/net/ieee802154/mcr20a.c
@@ -905,9 +905,9 @@ mcr20a_irq_clean_complete(void *context)
}
break;
case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ):
- /* rx is starting */
- dev_dbg(printdev(lp), "RX is starting\n");
- mcr20a_handle_rx(lp);
+ /* rx is starting */
+ dev_dbg(printdev(lp), "RX is starting\n");
+ mcr20a_handle_rx(lp);
break;
case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ):
if (lp->is_tx) {
diff --git a/drivers/net/ipvlan/Makefile b/drivers/net/ipvlan/Makefile
index 8a2c64dc9641..3ee95367a994 100644
--- a/drivers/net/ipvlan/Makefile
+++ b/drivers/net/ipvlan/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_IPVLAN) += ipvlan.o
obj-$(CONFIG_IPVTAP) += ipvtap.o
-ipvlan-objs := ipvlan_core.o ipvlan_main.o
+ipvlan-objs-$(CONFIG_IPVLAN_L3S) += ipvlan_l3s.o
+ipvlan-objs := ipvlan_core.o ipvlan_main.o $(ipvlan-objs-y)
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index adb826f55e60..b906d2f6bd04 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -165,10 +165,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
const void *iaddr, bool is_v6);
bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
void ipvlan_ht_addr_del(struct ipvl_addr *addr);
-struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
- u16 proto);
-unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
- const struct nf_hook_state *state);
+struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
+ int addr_type, bool use_dest);
+void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type);
void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
unsigned int len, bool success, bool mcast);
int ipvlan_link_new(struct net *src_net, struct net_device *dev,
@@ -177,6 +176,36 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
void ipvlan_link_delete(struct net_device *dev, struct list_head *head);
void ipvlan_link_setup(struct net_device *dev);
int ipvlan_link_register(struct rtnl_link_ops *ops);
+#ifdef CONFIG_IPVLAN_L3S
+int ipvlan_l3s_register(struct ipvl_port *port);
+void ipvlan_l3s_unregister(struct ipvl_port *port);
+void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet);
+int ipvlan_l3s_init(void);
+void ipvlan_l3s_cleanup(void);
+#else
+static inline int ipvlan_l3s_register(struct ipvl_port *port)
+{
+ return -ENOTSUPP;
+}
+
+static inline void ipvlan_l3s_unregister(struct ipvl_port *port)
+{
+}
+
+static inline void ipvlan_migrate_l3s_hook(struct net *oldnet,
+ struct net *newnet)
+{
+}
+
+static inline int ipvlan_l3s_init(void)
+{
+ return 0;
+}
+
+static inline void ipvlan_l3s_cleanup(void)
+{
+}
+#endif /* CONFIG_IPVLAN_L3S */
static inline bool netif_is_ipvlan_port(const struct net_device *dev)
{
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 1a8132eb2a3e..e0f5bc82b10c 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -138,7 +138,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
return ret;
}
-static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type)
+void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type)
{
void *lyr3h = NULL;
@@ -355,9 +355,8 @@ out:
return ret;
}
-static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
- void *lyr3h, int addr_type,
- bool use_dest)
+struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
+ int addr_type, bool use_dest)
{
struct ipvl_addr *addr = NULL;
@@ -647,7 +646,9 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
case IPVLAN_MODE_L2:
return ipvlan_xmit_mode_l2(skb, dev);
case IPVLAN_MODE_L3:
+#ifdef CONFIG_IPVLAN_L3S
case IPVLAN_MODE_L3S:
+#endif
return ipvlan_xmit_mode_l3(skb, dev);
}
@@ -743,8 +744,10 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
return ipvlan_handle_mode_l2(pskb, port);
case IPVLAN_MODE_L3:
return ipvlan_handle_mode_l3(pskb, port);
+#ifdef CONFIG_IPVLAN_L3S
case IPVLAN_MODE_L3S:
return RX_HANDLER_PASS;
+#endif
}
/* Should not reach here */
@@ -753,97 +756,3 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
kfree_skb(skb);
return RX_HANDLER_CONSUMED;
}
-
-static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct ipvl_addr *addr = NULL;
- struct ipvl_port *port;
- void *lyr3h;
- int addr_type;
-
- if (!dev || !netif_is_ipvlan_port(dev))
- goto out;
-
- port = ipvlan_port_get_rcu(dev);
- if (!port || port->mode != IPVLAN_MODE_L3S)
- goto out;
-
- lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
- if (!lyr3h)
- goto out;
-
- addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
-out:
- return addr;
-}
-
-struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
- u16 proto)
-{
- struct ipvl_addr *addr;
- struct net_device *sdev;
-
- addr = ipvlan_skb_to_addr(skb, dev);
- if (!addr)
- goto out;
-
- sdev = addr->master->dev;
- switch (proto) {
- case AF_INET:
- {
- int err;
- struct iphdr *ip4h = ip_hdr(skb);
-
- err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
- ip4h->tos, sdev);
- if (unlikely(err))
- goto out;
- break;
- }
-#if IS_ENABLED(CONFIG_IPV6)
- case AF_INET6:
- {
- struct dst_entry *dst;
- struct ipv6hdr *ip6h = ipv6_hdr(skb);
- int flags = RT6_LOOKUP_F_HAS_SADDR;
- struct flowi6 fl6 = {
- .flowi6_iif = sdev->ifindex,
- .daddr = ip6h->daddr,
- .saddr = ip6h->saddr,
- .flowlabel = ip6_flowinfo(ip6h),
- .flowi6_mark = skb->mark,
- .flowi6_proto = ip6h->nexthdr,
- };
-
- skb_dst_drop(skb);
- dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
- skb, flags);
- skb_dst_set(skb, dst);
- break;
- }
-#endif
- default:
- break;
- }
-
-out:
- return skb;
-}
-
-unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
- const struct nf_hook_state *state)
-{
- struct ipvl_addr *addr;
- unsigned int len;
-
- addr = ipvlan_skb_to_addr(skb, skb->dev);
- if (!addr)
- goto out;
-
- skb->dev = addr->master->dev;
- len = skb->len + ETH_HLEN;
- ipvlan_count_rx(addr->master, len, true, false);
-out:
- return NF_ACCEPT;
-}
diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c
new file mode 100644
index 000000000000..d17480a911a3
--- /dev/null
+++ b/drivers/net/ipvlan/ipvlan_l3s.c
@@ -0,0 +1,227 @@
+/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.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.
+ */
+
+#include "ipvlan.h"
+
+static unsigned int ipvlan_netid __read_mostly;
+
+struct ipvlan_netns {
+ unsigned int ipvl_nf_hook_refcnt;
+};
+
+static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ipvl_addr *addr = NULL;
+ struct ipvl_port *port;
+ int addr_type;
+ void *lyr3h;
+
+ if (!dev || !netif_is_ipvlan_port(dev))
+ goto out;
+
+ port = ipvlan_port_get_rcu(dev);
+ if (!port || port->mode != IPVLAN_MODE_L3S)
+ goto out;
+
+ lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
+ if (!lyr3h)
+ goto out;
+
+ addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
+out:
+ return addr;
+}
+
+static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
+ struct sk_buff *skb, u16 proto)
+{
+ struct ipvl_addr *addr;
+ struct net_device *sdev;
+
+ addr = ipvlan_skb_to_addr(skb, dev);
+ if (!addr)
+ goto out;
+
+ sdev = addr->master->dev;
+ switch (proto) {
+ case AF_INET:
+ {
+ struct iphdr *ip4h = ip_hdr(skb);
+ int err;
+
+ err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
+ ip4h->tos, sdev);
+ if (unlikely(err))
+ goto out;
+ break;
+ }
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ {
+ struct dst_entry *dst;
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
+ struct flowi6 fl6 = {
+ .flowi6_iif = sdev->ifindex,
+ .daddr = ip6h->daddr,
+ .saddr = ip6h->saddr,
+ .flowlabel = ip6_flowinfo(ip6h),
+ .flowi6_mark = skb->mark,
+ .flowi6_proto = ip6h->nexthdr,
+ };
+
+ skb_dst_drop(skb);
+ dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
+ skb, flags);
+ skb_dst_set(skb, dst);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+out:
+ return skb;
+}
+
+static const struct l3mdev_ops ipvl_l3mdev_ops = {
+ .l3mdev_l3_rcv = ipvlan_l3_rcv,
+};
+
+static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ struct ipvl_addr *addr;
+ unsigned int len;
+
+ addr = ipvlan_skb_to_addr(skb, skb->dev);
+ if (!addr)
+ goto out;
+
+ skb->dev = addr->master->dev;
+ len = skb->len + ETH_HLEN;
+ ipvlan_count_rx(addr->master, len, true, false);
+out:
+ return NF_ACCEPT;
+}
+
+static const struct nf_hook_ops ipvl_nfops[] = {
+ {
+ .hook = ipvlan_nf_input,
+ .pf = NFPROTO_IPV4,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = INT_MAX,
+ },
+#if IS_ENABLED(CONFIG_IPV6)
+ {
+ .hook = ipvlan_nf_input,
+ .pf = NFPROTO_IPV6,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = INT_MAX,
+ },
+#endif
+};
+
+static int ipvlan_register_nf_hook(struct net *net)
+{
+ struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
+ int err = 0;
+
+ if (!vnet->ipvl_nf_hook_refcnt) {
+ err = nf_register_net_hooks(net, ipvl_nfops,
+ ARRAY_SIZE(ipvl_nfops));
+ if (!err)
+ vnet->ipvl_nf_hook_refcnt = 1;
+ } else {
+ vnet->ipvl_nf_hook_refcnt++;
+ }
+
+ return err;
+}
+
+static void ipvlan_unregister_nf_hook(struct net *net)
+{
+ struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
+
+ if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
+ return;
+
+ vnet->ipvl_nf_hook_refcnt--;
+ if (!vnet->ipvl_nf_hook_refcnt)
+ nf_unregister_net_hooks(net, ipvl_nfops,
+ ARRAY_SIZE(ipvl_nfops));
+}
+
+void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet)
+{
+ struct ipvlan_netns *old_vnet;
+
+ ASSERT_RTNL();
+
+ old_vnet = net_generic(oldnet, ipvlan_netid);
+ if (!old_vnet->ipvl_nf_hook_refcnt)
+ return;
+
+ ipvlan_register_nf_hook(newnet);
+ ipvlan_unregister_nf_hook(oldnet);
+}
+
+static void ipvlan_ns_exit(struct net *net)
+{
+ struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
+
+ if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
+ vnet->ipvl_nf_hook_refcnt = 0;
+ nf_unregister_net_hooks(net, ipvl_nfops,
+ ARRAY_SIZE(ipvl_nfops));
+ }
+}
+
+static struct pernet_operations ipvlan_net_ops = {
+ .id = &ipvlan_netid,
+ .size = sizeof(struct ipvlan_netns),
+ .exit = ipvlan_ns_exit,
+};
+
+int ipvlan_l3s_init(void)
+{
+ return register_pernet_subsys(&ipvlan_net_ops);
+}
+
+void ipvlan_l3s_cleanup(void)
+{
+ unregister_pernet_subsys(&ipvlan_net_ops);
+}
+
+int ipvlan_l3s_register(struct ipvl_port *port)
+{
+ struct net_device *dev = port->dev;
+ int ret;
+
+ ASSERT_RTNL();
+
+ ret = ipvlan_register_nf_hook(read_pnet(&port->pnet));
+ if (!ret) {
+ dev->l3mdev_ops = &ipvl_l3mdev_ops;
+ dev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
+ }
+
+ return ret;
+}
+
+void ipvlan_l3s_unregister(struct ipvl_port *port)
+{
+ struct net_device *dev = port->dev;
+
+ ASSERT_RTNL();
+
+ dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
+ ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
+ dev->l3mdev_ops = NULL;
+}
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 19bdde60680c..bbeb1623e2d5 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -9,73 +9,10 @@
#include "ipvlan.h"
-static unsigned int ipvlan_netid __read_mostly;
-
-struct ipvlan_netns {
- unsigned int ipvl_nf_hook_refcnt;
-};
-
-static const struct nf_hook_ops ipvl_nfops[] = {
- {
- .hook = ipvlan_nf_input,
- .pf = NFPROTO_IPV4,
- .hooknum = NF_INET_LOCAL_IN,
- .priority = INT_MAX,
- },
-#if IS_ENABLED(CONFIG_IPV6)
- {
- .hook = ipvlan_nf_input,
- .pf = NFPROTO_IPV6,
- .hooknum = NF_INET_LOCAL_IN,
- .priority = INT_MAX,
- },
-#endif
-};
-
-static const struct l3mdev_ops ipvl_l3mdev_ops = {
- .l3mdev_l3_rcv = ipvlan_l3_rcv,
-};
-
-static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
-{
- ipvlan->dev->mtu = dev->mtu;
-}
-
-static int ipvlan_register_nf_hook(struct net *net)
-{
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
- int err = 0;
-
- if (!vnet->ipvl_nf_hook_refcnt) {
- err = nf_register_net_hooks(net, ipvl_nfops,
- ARRAY_SIZE(ipvl_nfops));
- if (!err)
- vnet->ipvl_nf_hook_refcnt = 1;
- } else {
- vnet->ipvl_nf_hook_refcnt++;
- }
-
- return err;
-}
-
-static void ipvlan_unregister_nf_hook(struct net *net)
-{
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
-
- if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
- return;
-
- vnet->ipvl_nf_hook_refcnt--;
- if (!vnet->ipvl_nf_hook_refcnt)
- nf_unregister_net_hooks(net, ipvl_nfops,
- ARRAY_SIZE(ipvl_nfops));
-}
-
static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
struct netlink_ext_ack *extack)
{
struct ipvl_dev *ipvlan;
- struct net_device *mdev = port->dev;
unsigned int flags;
int err;
@@ -97,17 +34,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
}
if (nval == IPVLAN_MODE_L3S) {
/* New mode is L3S */
- err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
- if (!err) {
- mdev->l3mdev_ops = &ipvl_l3mdev_ops;
- mdev->priv_flags |= IFF_L3MDEV_MASTER;
- } else
+ err = ipvlan_l3s_register(port);
+ if (err)
goto fail;
} else if (port->mode == IPVLAN_MODE_L3S) {
/* Old mode was L3S */
- mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
- ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
- mdev->l3mdev_ops = NULL;
+ ipvlan_l3s_unregister(port);
}
port->mode = nval;
}
@@ -166,11 +98,8 @@ static void ipvlan_port_destroy(struct net_device *dev)
struct ipvl_port *port = ipvlan_port_get_rtnl(dev);
struct sk_buff *skb;
- if (port->mode == IPVLAN_MODE_L3S) {
- dev->priv_flags &= ~IFF_L3MDEV_MASTER;
- ipvlan_unregister_nf_hook(dev_net(dev));
- dev->l3mdev_ops = NULL;
- }
+ if (port->mode == IPVLAN_MODE_L3S)
+ ipvlan_l3s_unregister(port);
netdev_rx_handler_unregister(dev);
cancel_work_sync(&port->wq);
while ((skb = __skb_dequeue(&port->backlog)) != NULL) {
@@ -446,6 +375,11 @@ static const struct header_ops ipvlan_header_ops = {
.cache_update = eth_header_cache_update,
};
+static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
+{
+ ipvlan->dev->mtu = dev->mtu;
+}
+
static bool netif_is_ipvlan(const struct net_device *dev)
{
/* both ipvlan and ipvtap devices use the same netdev_ops */
@@ -499,6 +433,8 @@ static int ipvlan_nl_changelink(struct net_device *dev,
if (!data)
return 0;
+ if (!ns_capable(dev_net(ipvlan->phy_dev)->user_ns, CAP_NET_ADMIN))
+ return -EPERM;
if (data[IFLA_IPVLAN_MODE]) {
u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
@@ -601,6 +537,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
struct ipvl_dev *tmp = netdev_priv(phy_dev);
phy_dev = tmp->phy_dev;
+ if (!ns_capable(dev_net(phy_dev)->user_ns, CAP_NET_ADMIN))
+ return -EPERM;
} else if (!netif_is_ipvlan_port(phy_dev)) {
/* Exit early if the underlying link is invalid or busy */
if (phy_dev->type != ARPHRD_ETHER ||
@@ -781,7 +719,6 @@ static int ipvlan_device_event(struct notifier_block *unused,
case NETDEV_REGISTER: {
struct net *oldnet, *newnet = dev_net(dev);
- struct ipvlan_netns *old_vnet;
oldnet = read_pnet(&port->pnet);
if (net_eq(newnet, oldnet))
@@ -789,12 +726,7 @@ static int ipvlan_device_event(struct notifier_block *unused,
write_pnet(&port->pnet, newnet);
- old_vnet = net_generic(oldnet, ipvlan_netid);
- if (!old_vnet->ipvl_nf_hook_refcnt)
- break;
-
- ipvlan_register_nf_hook(newnet);
- ipvlan_unregister_nf_hook(oldnet);
+ ipvlan_migrate_l3s_hook(oldnet, newnet);
break;
}
case NETDEV_UNREGISTER:
@@ -1068,23 +1000,6 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
};
#endif
-static void ipvlan_ns_exit(struct net *net)
-{
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
-
- if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
- vnet->ipvl_nf_hook_refcnt = 0;
- nf_unregister_net_hooks(net, ipvl_nfops,
- ARRAY_SIZE(ipvl_nfops));
- }
-}
-
-static struct pernet_operations ipvlan_net_ops = {
- .id = &ipvlan_netid,
- .size = sizeof(struct ipvlan_netns),
- .exit = ipvlan_ns_exit,
-};
-
static int __init ipvlan_init_module(void)
{
int err;
@@ -1099,13 +1014,13 @@ static int __init ipvlan_init_module(void)
register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
- err = register_pernet_subsys(&ipvlan_net_ops);
+ err = ipvlan_l3s_init();
if (err < 0)
goto error;
err = ipvlan_link_register(&ipvlan_link_ops);
if (err < 0) {
- unregister_pernet_subsys(&ipvlan_net_ops);
+ ipvlan_l3s_cleanup();
goto error;
}
@@ -1126,7 +1041,7 @@ error:
static void __exit ipvlan_cleanup_module(void)
{
rtnl_link_unregister(&ipvlan_link_ops);
- unregister_pernet_subsys(&ipvlan_net_ops);
+ ipvlan_l3s_cleanup();
unregister_netdevice_notifier(&ipvlan_notifier_block);
unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
unregister_inetaddr_validator_notifier(
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index fc726ce4c164..0c0f105657d3 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -119,8 +119,6 @@ static struct macvlan_port *macvlan_port_get_rtnl(const struct net_device *dev)
return rtnl_dereference(dev->rx_handler_data);
}
-#define macvlan_port_exists(dev) (dev->priv_flags & IFF_MACVLAN_PORT)
-
static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
const unsigned char *addr)
{
@@ -337,7 +335,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
if (src)
dev_put(src->dev);
- kfree_skb(skb);
+ consume_skb(skb);
}
}
@@ -963,7 +961,8 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags)
+ u16 flags,
+ struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EINVAL;
@@ -1123,6 +1122,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
#endif
.ndo_get_iflink = macvlan_dev_get_iflink,
.ndo_features_check = passthru_features_check,
+ .ndo_change_proto_down = dev_change_proto_down_generic,
};
void macvlan_common_setup(struct net_device *dev)
@@ -1377,7 +1377,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
if (!tb[IFLA_ADDRESS])
eth_hw_addr_random(dev);
- if (!macvlan_port_exists(lowerdev)) {
+ if (!netif_is_macvlan_port(lowerdev)) {
err = macvlan_port_create(lowerdev);
if (err < 0)
return err;
@@ -1637,7 +1637,7 @@ static int macvlan_device_event(struct notifier_block *unused,
struct macvlan_port *port;
LIST_HEAD(list_kill);
- if (!macvlan_port_exists(dev))
+ if (!netif_is_macvlan_port(dev))
return NOTIFY_DONE;
port = macvlan_port_get_rtnl(dev);
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 172b271c8bd2..f92c43453ec6 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -248,7 +248,7 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)
static int nsim_bpf_verifier_prep(struct bpf_prog *prog)
{
- struct netdevsim *ns = netdev_priv(prog->aux->offload->netdev);
+ struct netdevsim *ns = bpf_offload_dev_priv(prog->aux->offload->offdev);
if (!ns->bpf_bind_accept)
return -EOPNOTSUPP;
@@ -589,7 +589,8 @@ int nsim_bpf_init(struct netdevsim *ns)
if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs))
return -ENOMEM;
- ns->sdev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops);
+ ns->sdev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops,
+ ns);
err = PTR_ERR_OR_ZERO(ns->sdev->bpf_dev);
if (err)
return err;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 8d8e2b3f263e..75a50b59cb8f 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -22,7 +22,6 @@
#include <net/netlink.h>
#include <net/pkt_cls.h>
#include <net/rtnetlink.h>
-#include <net/switchdev.h>
#include "netdevsim.h"
@@ -148,26 +147,16 @@ static struct device_type nsim_dev_type = {
.release = nsim_dev_release,
};
-static int
-nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+static int nsim_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
{
struct netdevsim *ns = netdev_priv(dev);
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = sizeof(ns->sdev->switch_id);
- memcpy(&attr->u.ppid.id, &ns->sdev->switch_id,
- attr->u.ppid.id_len);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
+ ppid->id_len = sizeof(ns->sdev->switch_id);
+ memcpy(&ppid->id, &ns->sdev->switch_id, ppid->id_len);
+ return 0;
}
-static const struct switchdev_ops nsim_switchdev_ops = {
- .switchdev_port_attr_get = nsim_port_attr_get,
-};
-
static int nsim_init(struct net_device *dev)
{
char sdev_ddir_name[10], sdev_link_name[32];
@@ -214,7 +203,6 @@ static int nsim_init(struct net_device *dev)
goto err_bpf_uninit;
SET_NETDEV_DEV(dev, &ns->dev);
- SWITCHDEV_SET_OPS(dev, &nsim_switchdev_ops);
err = nsim_devlink_setup(ns);
if (err)
@@ -493,6 +481,7 @@ static const struct net_device_ops nsim_netdev_ops = {
.ndo_setup_tc = nsim_setup_tc,
.ndo_set_features = nsim_set_features,
.ndo_bpf = nsim_bpf,
+ .ndo_get_port_parent_id = nsim_get_port_parent_id,
};
static void nsim_setup(struct net_device *dev)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d187cd50eb0..071869db44cf 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -87,6 +87,18 @@ config MDIO_BUS_MUX_MMIOREG
Currently, only 8/16/32 bits registers are supported.
+config MDIO_BUS_MUX_MULTIPLEXER
+ tristate "MDIO bus multiplexer using kernel multiplexer subsystem"
+ depends on OF_MDIO
+ select MULTIPLEXER
+ select MDIO_BUS_MUX
+ help
+ This module provides a driver for MDIO bus multiplexer
+ that is controlled via the kernel multiplexer subsystem. The
+ bus multiplexer connects one of several child MDIO busses to
+ a parent bus. Child bus selection is under the control of
+ the kernel multiplexer subsystem.
+
config MDIO_CAVIUM
tristate
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 5805c0b7d60e..ece5dae67174 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o
obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
@@ -45,6 +46,10 @@ sfp-obj-$(CONFIG_SFP) += sfp-bus.o
obj-y += $(sfp-obj-y) $(sfp-obj-m)
obj-$(CONFIG_AMD_PHY) += amd.o
+aquantia-objs += aquantia_main.o
+ifdef CONFIG_HWMON
+aquantia-objs += aquantia_hwmon.o
+endif
obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
obj-$(CONFIG_ASIX_PHY) += asix.o
obj-$(CONFIG_AT803X_PHY) += at803x.o
diff --git a/drivers/net/phy/amd.c b/drivers/net/phy/amd.c
index 9d0504f3e3b2..65b4b0960b1e 100644
--- a/drivers/net/phy/amd.c
+++ b/drivers/net/phy/amd.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for AMD am79c PHYs
*
* Author: Heiko Schocher <hs@denx.de>
*
* Copyright (c) 2011 DENX Software Engineering GmbH
- *
- * 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/kernel.h>
#include <linux/errno.h>
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
deleted file mode 100644
index beb3309bb0f0..000000000000
--- a/drivers/net/phy/aquantia.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Driver for Aquantia PHY
- *
- * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
- *
- * Copyright 2015 Freescale Semiconductor, Inc.
- *
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/phy.h>
-#include <linux/mdio.h>
-
-#define PHY_ID_AQ1202 0x03a1b445
-#define PHY_ID_AQ2104 0x03a1b460
-#define PHY_ID_AQR105 0x03a1b4a2
-#define PHY_ID_AQR106 0x03a1b4d0
-#define PHY_ID_AQR107 0x03a1b4e0
-#define PHY_ID_AQR405 0x03a1b4b0
-
-static int aquantia_config_aneg(struct phy_device *phydev)
-{
- linkmode_copy(phydev->supported, phy_10gbit_features);
- linkmode_copy(phydev->advertising, phydev->supported);
-
- return 0;
-}
-
-static int aquantia_config_intr(struct phy_device *phydev)
-{
- int err;
-
- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
- err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 1);
- if (err < 0)
- return err;
-
- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 1);
- if (err < 0)
- return err;
-
- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0x1001);
- } else {
- err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 0);
- if (err < 0)
- return err;
-
- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 0);
- if (err < 0)
- return err;
-
- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0);
- }
-
- return err;
-}
-
-static int aquantia_ack_interrupt(struct phy_device *phydev)
-{
- int reg;
-
- reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xcc01);
- return (reg < 0) ? reg : 0;
-}
-
-static int aquantia_read_status(struct phy_device *phydev)
-{
- int reg;
-
- reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
- reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
- if (reg & MDIO_STAT1_LSTATUS)
- phydev->link = 1;
- else
- phydev->link = 0;
-
- reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);
- mdelay(10);
- reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);
-
- switch (reg) {
- case 0x9:
- phydev->speed = SPEED_2500;
- break;
- case 0x5:
- phydev->speed = SPEED_1000;
- break;
- case 0x3:
- phydev->speed = SPEED_100;
- break;
- case 0x7:
- default:
- phydev->speed = SPEED_10000;
- break;
- }
- phydev->duplex = DUPLEX_FULL;
-
- return 0;
-}
-
-static struct phy_driver aquantia_driver[] = {
-{
- .phy_id = PHY_ID_AQ1202,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQ1202",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-{
- .phy_id = PHY_ID_AQ2104,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQ2104",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-{
- .phy_id = PHY_ID_AQR105,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQR105",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-{
- .phy_id = PHY_ID_AQR106,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQR106",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-{
- .phy_id = PHY_ID_AQR107,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQR107",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-{
- .phy_id = PHY_ID_AQR405,
- .phy_id_mask = 0xfffffff0,
- .name = "Aquantia AQR405",
- .features = PHY_10GBIT_FULL_FEATURES,
- .aneg_done = genphy_c45_aneg_done,
- .config_aneg = aquantia_config_aneg,
- .config_intr = aquantia_config_intr,
- .ack_interrupt = aquantia_ack_interrupt,
- .read_status = aquantia_read_status,
-},
-};
-
-module_phy_driver(aquantia_driver);
-
-static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
- { PHY_ID_AQ1202, 0xfffffff0 },
- { PHY_ID_AQ2104, 0xfffffff0 },
- { PHY_ID_AQR105, 0xfffffff0 },
- { PHY_ID_AQR106, 0xfffffff0 },
- { PHY_ID_AQR107, 0xfffffff0 },
- { PHY_ID_AQR405, 0xfffffff0 },
- { }
-};
-
-MODULE_DEVICE_TABLE(mdio, aquantia_tbl);
-
-MODULE_DESCRIPTION("Aquantia PHY driver");
-MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
new file mode 100644
index 000000000000..5a16caab7b2f
--- /dev/null
+++ b/drivers/net/phy/aquantia.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * HWMON driver for Aquantia PHY
+ *
+ * Author: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+ * Author: Andrew Lunn <andrew@lunn.ch>
+ * Author: Heiner Kallweit <hkallweit1@gmail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/phy.h>
+
+#if IS_REACHABLE(CONFIG_HWMON)
+int aqr_hwmon_probe(struct phy_device *phydev);
+#else
+static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
+#endif
diff --git a/drivers/net/phy/aquantia_hwmon.c b/drivers/net/phy/aquantia_hwmon.c
new file mode 100644
index 000000000000..19c4c280a6cd
--- /dev/null
+++ b/drivers/net/phy/aquantia_hwmon.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+/* HWMON driver for Aquantia PHY
+ *
+ * Author: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+ * Author: Andrew Lunn <andrew@lunn.ch>
+ * Author: Heiner Kallweit <hkallweit1@gmail.com>
+ */
+
+#include <linux/phy.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/hwmon.h>
+
+#include "aquantia.h"
+
+/* Vendor specific 1, MDIO_MMD_VEND2 */
+#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
+#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
+#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
+#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424
+#define VEND1_THERMAL_STAT1 0xc820
+#define VEND1_THERMAL_STAT2 0xc821
+#define VEND1_THERMAL_STAT2_VALID BIT(0)
+#define VEND1_GENERAL_STAT1 0xc830
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13)
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11)
+
+#if IS_REACHABLE(CONFIG_HWMON)
+
+static umode_t aqr_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_lcrit_alarm:
+ case hwmon_temp_crit_alarm:
+ return 0444;
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_lcrit:
+ case hwmon_temp_crit:
+ return 0644;
+ default:
+ return 0;
+ }
+}
+
+static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value)
+{
+ int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);
+
+ if (temp < 0)
+ return temp;
+
+ /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */
+ *value = (s16)temp * 1000 / 256;
+
+ return 0;
+}
+
+static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value)
+{
+ int temp;
+
+ if (value >= 128000 || value < -128000)
+ return -ERANGE;
+
+ temp = value * 256 / 1000;
+
+ /* temp is in s16 range and we're interested in lower 16 bits only */
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp);
+}
+
+static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit)
+{
+ int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);
+
+ if (val < 0)
+ return val;
+
+ return !!(val & bit);
+}
+
+static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value)
+{
+ int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit);
+
+ if (val < 0)
+ return val;
+
+ *value = val;
+
+ return 0;
+}
+
+static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *value)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int reg;
+
+ if (type != hwmon_temp)
+ return -EOPNOTSUPP;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2,
+ VEND1_THERMAL_STAT2_VALID);
+ if (reg < 0)
+ return reg;
+ if (!reg)
+ return -EBUSY;
+
+ return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value);
+
+ case hwmon_temp_lcrit:
+ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
+ value);
+ case hwmon_temp_min:
+ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
+ value);
+ case hwmon_temp_max:
+ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
+ value);
+ case hwmon_temp_crit:
+ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
+ value);
+ case hwmon_temp_lcrit_alarm:
+ return aqr_hwmon_status1(phydev,
+ VEND1_GENERAL_STAT1_LOW_TEMP_FAIL,
+ value);
+ case hwmon_temp_min_alarm:
+ return aqr_hwmon_status1(phydev,
+ VEND1_GENERAL_STAT1_LOW_TEMP_WARN,
+ value);
+ case hwmon_temp_max_alarm:
+ return aqr_hwmon_status1(phydev,
+ VEND1_GENERAL_STAT1_HIGH_TEMP_WARN,
+ value);
+ case hwmon_temp_crit_alarm:
+ return aqr_hwmon_status1(phydev,
+ VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL,
+ value);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long value)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+
+ if (type != hwmon_temp)
+ return -EOPNOTSUPP;
+
+ switch (attr) {
+ case hwmon_temp_lcrit:
+ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
+ value);
+ case hwmon_temp_min:
+ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
+ value);
+ case hwmon_temp_max:
+ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
+ value);
+ case hwmon_temp_crit:
+ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
+ value);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_ops aqr_hwmon_ops = {
+ .is_visible = aqr_hwmon_is_visible,
+ .read = aqr_hwmon_read,
+ .write = aqr_hwmon_write,
+};
+
+static u32 aqr_hwmon_chip_config[] = {
+ HWMON_C_REGISTER_TZ,
+ 0,
+};
+
+static const struct hwmon_channel_info aqr_hwmon_chip = {
+ .type = hwmon_chip,
+ .config = aqr_hwmon_chip_config,
+};
+
+static u32 aqr_hwmon_temp_config[] = {
+ HWMON_T_INPUT |
+ HWMON_T_MAX | HWMON_T_MIN |
+ HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM |
+ HWMON_T_CRIT | HWMON_T_LCRIT |
+ HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM,
+ 0,
+};
+
+static const struct hwmon_channel_info aqr_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = aqr_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *aqr_hwmon_info[] = {
+ &aqr_hwmon_chip,
+ &aqr_hwmon_temp,
+ NULL,
+};
+
+static const struct hwmon_chip_info aqr_hwmon_chip_info = {
+ .ops = &aqr_hwmon_ops,
+ .info = aqr_hwmon_info,
+};
+
+int aqr_hwmon_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct device *hwmon_dev;
+ char *hwmon_name;
+ int i, j;
+
+ hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+ if (!hwmon_name)
+ return -ENOMEM;
+
+ for (i = j = 0; hwmon_name[i]; i++) {
+ if (isalnum(hwmon_name[i])) {
+ if (i != j)
+ hwmon_name[j] = hwmon_name[i];
+ j++;
+ }
+ }
+ hwmon_name[j] = '\0';
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name,
+ phydev, &aqr_hwmon_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+#endif
diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
new file mode 100644
index 000000000000..37218e5d7cc9
--- /dev/null
+++ b/drivers/net/phy/aquantia_main.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Aquantia PHY
+ *
+ * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
+ *
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/phy.h>
+
+#include "aquantia.h"
+
+#define PHY_ID_AQ1202 0x03a1b445
+#define PHY_ID_AQ2104 0x03a1b460
+#define PHY_ID_AQR105 0x03a1b4a2
+#define PHY_ID_AQR106 0x03a1b4d0
+#define PHY_ID_AQR107 0x03a1b4e0
+#define PHY_ID_AQCS109 0x03a1b5c2
+#define PHY_ID_AQR405 0x03a1b4b0
+
+#define MDIO_AN_VEND_PROV 0xc400
+#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15)
+#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14)
+
+#define MDIO_AN_TX_VEND_STATUS1 0xc800
+#define MDIO_AN_TX_VEND_STATUS1_10BASET (0x0 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_100BASETX (0x1 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_1000BASET (0x2 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_10GBASET (0x3 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_2500BASET (0x4 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_5000BASET (0x5 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK (0x7 << 1)
+#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0)
+
+#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01
+
+#define MDIO_AN_TX_VEND_INT_MASK2 0xd401
+#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0)
+
+#define MDIO_AN_RX_LP_STAT1 0xe820
+#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15)
+#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14)
+
+/* Vendor specific 1, MDIO_MMD_VEND1 */
+#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00
+#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01
+
+#define VEND1_GLOBAL_INT_STD_MASK 0xff00
+#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15)
+#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9)
+#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8)
+#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7)
+#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6)
+#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0)
+
+#define VEND1_GLOBAL_INT_VEND_MASK 0xff01
+#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15)
+#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14)
+#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13)
+#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12)
+#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
+
+static int aqr_config_aneg(struct phy_device *phydev)
+{
+ bool changed = false;
+ u16 reg;
+ int ret;
+
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ return genphy_c45_pma_setup_forced(phydev);
+
+ ret = genphy_c45_an_config_aneg(phydev);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ /* Clause 45 has no standardized support for 1000BaseT, therefore
+ * use vendor registers for this mode.
+ */
+ reg = 0;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ phydev->advertising))
+ reg |= MDIO_AN_VEND_PROV_1000BASET_FULL;
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ phydev->advertising))
+ reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
+ MDIO_AN_VEND_PROV_1000BASET_HALF |
+ MDIO_AN_VEND_PROV_1000BASET_FULL, reg);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
+}
+
+static int aqr_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ err = phy_write_mmd(phydev, MDIO_MMD_AN,
+ MDIO_AN_TX_VEND_INT_MASK2,
+ MDIO_AN_TX_VEND_INT_MASK2_LINK);
+ if (err < 0)
+ return err;
+
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_INT_STD_MASK,
+ VEND1_GLOBAL_INT_STD_MASK_ALL);
+ if (err < 0)
+ return err;
+
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_INT_VEND_MASK,
+ VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 |
+ VEND1_GLOBAL_INT_VEND_MASK_AN);
+ } else {
+ err = phy_write_mmd(phydev, MDIO_MMD_AN,
+ MDIO_AN_TX_VEND_INT_MASK2, 0);
+ if (err < 0)
+ return err;
+
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_INT_STD_MASK, 0);
+ if (err < 0)
+ return err;
+
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_INT_VEND_MASK, 0);
+ }
+
+ return err;
+}
+
+static int aqr_ack_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_AN,
+ MDIO_AN_TX_VEND_INT_STATUS2);
+ return (reg < 0) ? reg : 0;
+}
+
+static int aqr_read_status(struct phy_device *phydev)
+{
+ int val;
+
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1);
+ if (val < 0)
+ return val;
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ phydev->lp_advertising,
+ val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ phydev->lp_advertising,
+ val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF);
+ }
+
+ return genphy_c45_read_status(phydev);
+}
+
+static int aqcs109_config_init(struct phy_device *phydev)
+{
+ /* AQCS109 belongs to a chip family partially supporting 10G and 5G.
+ * PMA speed ability bits are the same for all members of the family,
+ * AQCS109 however supports speeds up to 2.5G only.
+ */
+ return phy_set_max_speed(phydev, SPEED_2500);
+}
+
+static struct phy_driver aqr_driver[] = {
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQ1202),
+ .name = "Aquantia AQ1202",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQ2104),
+ .name = "Aquantia AQ2104",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR105),
+ .name = "Aquantia AQR105",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR106),
+ .name = "Aquantia AQR106",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR107),
+ .name = "Aquantia AQR107",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .probe = aqr_hwmon_probe,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
+ .name = "Aquantia AQCS109",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .probe = aqr_hwmon_probe,
+ .config_init = aqcs109_config_init,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR405),
+ .name = "Aquantia AQR405",
+ .aneg_done = genphy_c45_aneg_done,
+ .get_features = genphy_c45_pma_read_abilities,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr_read_status,
+},
+};
+
+module_phy_driver(aqr_driver);
+
+static struct mdio_device_id __maybe_unused aqr_tbl[] = {
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, aqr_tbl);
+
+MODULE_DESCRIPTION("Aquantia PHY driver");
+MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/asix.c b/drivers/net/phy/asix.c
index 8ebe7f5484ae..f14ba5366b91 100644
--- a/drivers/net/phy/asix.c
+++ b/drivers/net/phy/asix.c
@@ -1,13 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
/* Driver for Asix PHYs
*
* Author: Michael Schmitz <schmitzmic@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.
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index f9432d053a22..f3e96191eb6f 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/at803x.c
*
* Driver for Atheros 803x PHY
*
* Author: Matus Ujhelyi <ujhelyi.m@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.
*/
#include <linux/phy.h>
@@ -39,9 +35,6 @@
#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
-#define AT803X_MMD_ACCESS_CONTROL 0x0D
-#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
-#define AT803X_FUNC_DATA 0x4003
#define AT803X_REG_CHIP_CONFIG 0x1f
#define AT803X_BT_BX_REG_SEL 0x8000
@@ -110,16 +103,28 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
return phy_write(phydev, AT803X_DEBUG_DATA, val);
}
-static inline int at803x_enable_rx_delay(struct phy_device *phydev)
+static int at803x_enable_rx_delay(struct phy_device *phydev)
{
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
- AT803X_DEBUG_RX_CLK_DLY_EN);
+ AT803X_DEBUG_RX_CLK_DLY_EN);
}
-static inline int at803x_enable_tx_delay(struct phy_device *phydev)
+static int at803x_enable_tx_delay(struct phy_device *phydev)
{
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
- AT803X_DEBUG_TX_CLK_DLY_EN);
+ AT803X_DEBUG_TX_CLK_DLY_EN);
+}
+
+static int at803x_disable_rx_delay(struct phy_device *phydev)
+{
+ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
+ AT803X_DEBUG_RX_CLK_DLY_EN, 0);
+}
+
+static int at803x_disable_tx_delay(struct phy_device *phydev)
+{
+ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
+ AT803X_DEBUG_TX_CLK_DLY_EN, 0);
}
/* save relevant PHY registers to private copy */
@@ -168,16 +173,9 @@ static int at803x_set_wol(struct phy_device *phydev,
if (!is_valid_ether_addr(mac))
return -EINVAL;
- for (i = 0; i < 3; i++) {
- phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
- AT803X_DEVICE_ADDR);
- phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
- offsets[i]);
- phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
- AT803X_FUNC_DATA);
- phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
- mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
- }
+ for (i = 0; i < 3; i++)
+ phy_write_mmd(phydev, AT803X_DEVICE_ADDR, offsets[i],
+ mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
value = phy_read(phydev, AT803X_INTR_ENABLE);
value |= AT803X_INTR_ENABLE_WOL;
@@ -255,21 +253,42 @@ static int at803x_config_init(struct phy_device *phydev)
if (ret < 0)
return ret;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+ /* The RX and TX delay default is:
+ * after HW reset: RX delay enabled and TX delay disabled
+ * after SW reset: RX delay enabled, while TX delay retains the
+ * value before reset.
+ *
+ * So let's first disable the RX and TX delays in PHY and enable
+ * them based on the mode selected (this also takes care of RGMII
+ * mode where we expect delays to be disabled)
+ */
+
+ ret = at803x_disable_rx_delay(phydev);
+ if (ret < 0)
+ return ret;
+ ret = at803x_disable_tx_delay(phydev);
+ if (ret < 0)
+ return ret;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+ /* If RGMII_ID or RGMII_RXID are specified enable RX delay,
+ * otherwise keep it disabled
+ */
ret = at803x_enable_rx_delay(phydev);
if (ret < 0)
return ret;
}
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+ /* If RGMII_ID or RGMII_TXID are specified enable TX delay,
+ * otherwise keep it disabled
+ */
ret = at803x_enable_tx_delay(phydev);
- if (ret < 0)
- return ret;
}
- return 0;
+ return ret;
}
static int at803x_ack_interrupt(struct phy_device *phydev)
diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c
index e757b09f1889..ab8e12922bf9 100644
--- a/drivers/net/phy/bcm-cygnus.c
+++ b/drivers/net/phy/bcm-cygnus.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 Broadcom Corporation
- *
- * 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.
*/
/* Broadcom Cygnus SoC internal transceivers support. */
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index e10e7b54ec4b..a75642051b8b 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015-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 "bcm-phy-lib.h"
diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h
index 81cceaa412fe..17faaefcfd60 100644
--- a/drivers/net/phy/bcm-phy-lib.h
+++ b/drivers/net/phy/bcm-phy-lib.h
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 Broadcom Corporation
- *
- * 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.
*/
#ifndef _LINUX_BCM_PHY_LIB_H
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index a88dd14a25c0..44e6cff419a0 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Broadcom 63xx SOCs integrated PHYs
- *
- * 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 "bcm-phy-lib.h"
#include <linux/module.h>
diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 712224cc442d..b8415f8fae14 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Broadcom BCM7xxx internal transceivers support.
*
* Copyright (C) 2014-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; either version
- * 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
index 1b350183bffb..f0c0eefe2202 100644
--- a/drivers/net/phy/bcm87xx.c
+++ b/drivers/net/phy/bcm87xx.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2011 - 2012 Cavium, Inc.
*/
@@ -197,6 +194,7 @@ static struct phy_driver bcm87xx_driver[] = {
.phy_id = PHY_ID_BCM8706,
.phy_id_mask = 0xffffffff,
.name = "Broadcom BCM8706",
+ .features = PHY_10GBIT_FEC_FEATURES,
.config_init = bcm87xx_config_init,
.config_aneg = bcm87xx_config_aneg,
.read_status = bcm87xx_read_status,
@@ -208,6 +206,7 @@ static struct phy_driver bcm87xx_driver[] = {
.phy_id = PHY_ID_BCM8727,
.phy_id_mask = 0xffffffff,
.name = "Broadcom BCM8727",
+ .features = PHY_10GBIT_FEC_FEATURES,
.config_init = bcm87xx_config_init,
.config_aneg = bcm87xx_config_aneg,
.read_status = bcm87xx_read_status,
@@ -219,4 +218,4 @@ static struct phy_driver bcm87xx_driver[] = {
module_phy_driver(bcm87xx_driver);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index aa73c5cc5f86..9605d4fe540b 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/broadcom.c
*
@@ -7,11 +8,6 @@
* Copyright (c) 2006 Maciej W. Rozycki
*
* Inspired by code written by Amy Fong.
- *
- * 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 "bcm-phy-lib.h"
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index fea61c81bda9..108ed24f8489 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/cicada.c
*
@@ -6,12 +7,6 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index 8022cd317f62..856cdc36aacd 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2017 NXP
*
- * 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.
- *
* CORTINA is a registered trademark of Cortina Systems, Inc.
*
*/
@@ -88,10 +79,10 @@ static struct phy_driver cortina_driver[] = {
.phy_id = PHY_ID_CS4340,
.phy_id_mask = 0xffffffff,
.name = "Cortina CS4340",
- .config_init = gen10g_config_init,
+ .features = PHY_10GBIT_FEATURES,
.config_aneg = gen10g_config_aneg,
.read_status = cortina_read_status,
- .soft_reset = gen10g_no_soft_reset,
+ .soft_reset = genphy_no_soft_reset,
.probe = cortina_probe,
},
};
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 97162008f42b..bf39baa7f2c8 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/davicom.c
*
@@ -6,12 +7,6 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 18b41bc345ab..2fe2ebaf62d1 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for the National Semiconductor DP83640 PHYTER
*
* Copyright (C) 2010 OMICRON electronics GmbH
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -898,14 +885,14 @@ static void decode_txts(struct dp83640_private *dp83640,
struct phy_txts *phy_txts)
{
struct skb_shared_hwtstamps shhwtstamps;
+ struct dp83640_skb_info *skb_info;
struct sk_buff *skb;
- u64 ns;
u8 overflow;
+ u64 ns;
/* We must already have the skb that triggered this. */
-
+again:
skb = skb_dequeue(&dp83640->tx_queue);
-
if (!skb) {
pr_debug("have timestamp but tx_queue empty\n");
return;
@@ -920,6 +907,11 @@ static void decode_txts(struct dp83640_private *dp83640,
}
return;
}
+ skb_info = (struct dp83640_skb_info *)skb->cb;
+ if (time_after(jiffies, skb_info->tmo)) {
+ kfree_skb(skb);
+ goto again;
+ }
ns = phy2txts(phy_txts);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -1472,6 +1464,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
static void dp83640_txtstamp(struct phy_device *phydev,
struct sk_buff *skb, int type)
{
+ struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
struct dp83640_private *dp83640 = phydev->priv;
switch (dp83640->hwts_tx_en) {
@@ -1484,6 +1477,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
/* fall through */
case HWTSTAMP_TX_ON:
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
skb_queue_tail(&dp83640->tx_queue, skb);
break;
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index 24c7f149f3e6..bbd8c22067f3 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the Texas Instruments DP83822 PHY
*
* Copyright (C) 2017 Texas Instruments 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.
- *
- * 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/ethtool.h>
@@ -338,4 +330,4 @@ MODULE_DEVICE_TABLE(mdio, dp83822_tbl);
MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
index a6b55909d1dc..f55dc907c2f3 100644
--- a/drivers/net/phy/dp83848.c
+++ b/drivers/net/phy/dp83848.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the Texas Instruments DP83848 PHY
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.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.
- *
- * 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>
@@ -133,4 +125,4 @@ module_phy_driver(dp83848_driver);
MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index da6a67d47ce9..8448d01819ef 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the Texas Instruments DP83867 PHY
*
* Copyright (C) 2015 Texas Instruments 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.
- *
- * 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/ethtool.h>
@@ -19,6 +11,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy.h>
+#include <linux/delay.h>
#include <dt-bindings/net/ti-dp83867.h>
@@ -135,17 +128,13 @@ static int dp83867_config_port_mirroring(struct phy_device *phydev)
{
struct dp83867_private *dp83867 =
(struct dp83867_private *)phydev->priv;
- u16 val;
-
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN)
- val |= DP83867_CFG4_PORT_MIRROR_EN;
+ phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
+ DP83867_CFG4_PORT_MIRROR_EN);
else
- val &= ~DP83867_CFG4_PORT_MIRROR_EN;
-
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
-
+ phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
+ DP83867_CFG4_PORT_MIRROR_EN);
return 0;
}
@@ -230,11 +219,9 @@ static int dp83867_config_init(struct phy_device *phydev)
}
/* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
- if (dp83867->rxctrl_strap_quirk) {
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
- val &= ~BIT(7);
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
- }
+ if (dp83867->rxctrl_strap_quirk)
+ phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
+ BIT(7));
if (phy_interface_is_rgmii(phydev)) {
val = phy_read(phydev, MII_DP83867_PHYCTRL);
@@ -283,17 +270,11 @@ static int dp83867_config_init(struct phy_device *phydev)
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL,
delay);
- if (dp83867->io_impedance >= 0) {
- val = phy_read_mmd(phydev, DP83867_DEVADDR,
- DP83867_IO_MUX_CFG);
-
- val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
- val |= dp83867->io_impedance &
- DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
-
- phy_write_mmd(phydev, DP83867_DEVADDR,
- DP83867_IO_MUX_CFG, val);
- }
+ if (dp83867->io_impedance >= 0)
+ phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG,
+ DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL,
+ dp83867->io_impedance &
+ DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL);
}
/* Enable Interrupt output INT_OE in CFG3 register */
@@ -307,12 +288,11 @@ static int dp83867_config_init(struct phy_device *phydev)
dp83867_config_port_mirroring(phydev);
/* Clock output selection if muxing property is set */
- if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) {
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG);
- val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
- val |= (dp83867->clk_output_sel << DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, val);
- }
+ if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK)
+ phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG,
+ DP83867_IO_MUX_CFG_CLK_O_SEL_MASK,
+ dp83867->clk_output_sel <<
+ DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
return 0;
}
@@ -325,6 +305,8 @@ static int dp83867_phy_reset(struct phy_device *phydev)
if (err < 0)
return err;
+ usleep_range(10, 20);
+
return dp83867_config_init(phydev);
}
@@ -357,4 +339,4 @@ MODULE_DEVICE_TABLE(mdio, dp83867_tbl);
MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/dp83tc811.c b/drivers/net/phy/dp83tc811.c
index da13356999e5..e9704af1d239 100644
--- a/drivers/net/phy/dp83tc811.c
+++ b/drivers/net/phy/dp83tc811.c
@@ -144,11 +144,8 @@ static int dp83811_set_wol(struct phy_device *phydev,
phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
value);
} else {
- value = phy_read_mmd(phydev, DP83811_DEVADDR,
- MII_DP83811_WOL_CFG);
- value &= ~DP83811_WOL_EN;
- phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
- value);
+ phy_clear_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
+ DP83811_WOL_EN);
}
return 0;
@@ -328,14 +325,10 @@ static int dp83811_suspend(struct phy_device *phydev)
static int dp83811_resume(struct phy_device *phydev)
{
- int value;
-
genphy_resume(phydev);
- value = phy_read_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG);
-
- phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, value |
- DP83811_WOL_CLR_INDICATION);
+ phy_set_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
+ DP83811_WOL_CLR_INDICATION);
return 0;
}
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 565e49e7f76f..2aa367c04a8e 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/et1011c.c
*
@@ -6,12 +7,6 @@
* Author: Chaithrika U S
*
* Copyright (c) 2008 Texas Instruments
- *
- * 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index 72d43c88e6ff..1acd8bfdb3bc 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Fixed MDIO bus (MDIO bus emulation with fixed PHYs)
*
@@ -5,11 +6,6 @@
* Anton Vorontsov <avorontsov@ru.mvista.com>
*
* Copyright (c) 2006-2007 MontaVista Software, 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/kernel.h>
@@ -22,10 +18,11 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/seqlock.h>
#include <linux/idr.h>
#include <linux/netdevice.h>
+#include <linux/linkmode.h>
#include "swphy.h"
@@ -42,7 +39,7 @@ struct fixed_phy {
bool no_carrier;
int (*link_update)(struct net_device *, struct fixed_phy_status *);
struct list_head node;
- int link_gpio;
+ struct gpio_desc *link_gpiod;
};
static struct platform_device *pdev;
@@ -71,8 +68,8 @@ EXPORT_SYMBOL_GPL(fixed_phy_change_carrier);
static void fixed_phy_update(struct fixed_phy *fp)
{
- if (!fp->no_carrier && gpio_is_valid(fp->link_gpio))
- fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);
+ if (!fp->no_carrier && fp->link_gpiod)
+ fp->status.link = !!gpiod_get_value_cansleep(fp->link_gpiod);
}
static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
@@ -89,11 +86,11 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
s = read_seqcount_begin(&fp->seqcount);
fp->status.link = !fp->no_carrier;
/* Issue callback if user registered it. */
- if (fp->link_update) {
+ if (fp->link_update)
fp->link_update(fp->phydev->attached_dev,
&fp->status);
- fixed_phy_update(fp);
- }
+ /* Check the GPIO for change in status */
+ fixed_phy_update(fp);
state = fp->status;
} while (read_seqcount_retry(&fp->seqcount, s));
@@ -137,9 +134,9 @@ int fixed_phy_set_link_update(struct phy_device *phydev,
}
EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
-int fixed_phy_add(unsigned int irq, int phy_addr,
- struct fixed_phy_status *status,
- int link_gpio)
+static int fixed_phy_add_gpiod(unsigned int irq, int phy_addr,
+ struct fixed_phy_status *status,
+ struct gpio_desc *gpiod)
{
int ret;
struct fixed_mdio_bus *fmb = &platform_fmb;
@@ -160,24 +157,19 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
fp->addr = phy_addr;
fp->status = *status;
- fp->link_gpio = link_gpio;
-
- if (gpio_is_valid(fp->link_gpio)) {
- ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN,
- "fixed-link-gpio-link");
- if (ret)
- goto err_regs;
- }
+ fp->link_gpiod = gpiod;
fixed_phy_update(fp);
list_add_tail(&fp->node, &fmb->phys);
return 0;
+}
-err_regs:
- kfree(fp);
- return ret;
+int fixed_phy_add(unsigned int irq, int phy_addr,
+ struct fixed_phy_status *status) {
+
+ return fixed_phy_add_gpiod(irq, phy_addr, status, NULL);
}
EXPORT_SYMBOL_GPL(fixed_phy_add);
@@ -191,8 +183,8 @@ static void fixed_phy_del(int phy_addr)
list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
if (fp->addr == phy_addr) {
list_del(&fp->node);
- if (gpio_is_valid(fp->link_gpio))
- gpio_free(fp->link_gpio);
+ if (fp->link_gpiod)
+ gpiod_put(fp->link_gpiod);
kfree(fp);
ida_simple_remove(&phy_fixed_ida, phy_addr);
return;
@@ -200,10 +192,48 @@ static void fixed_phy_del(int phy_addr)
}
}
-struct phy_device *fixed_phy_register(unsigned int irq,
- struct fixed_phy_status *status,
- int link_gpio,
- struct device_node *np)
+#ifdef CONFIG_OF_GPIO
+static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
+{
+ struct device_node *fixed_link_node;
+ struct gpio_desc *gpiod;
+
+ if (!np)
+ return NULL;
+
+ fixed_link_node = of_get_child_by_name(np, "fixed-link");
+ if (!fixed_link_node)
+ return NULL;
+
+ /*
+ * As the fixed link is just a device tree node without any
+ * Linux device associated with it, we simply have obtain
+ * the GPIO descriptor from the device tree like this.
+ */
+ gpiod = gpiod_get_from_of_node(fixed_link_node, "link-gpios", 0,
+ GPIOD_IN, "mdio");
+ of_node_put(fixed_link_node);
+ if (IS_ERR(gpiod)) {
+ if (PTR_ERR(gpiod) == -EPROBE_DEFER)
+ return gpiod;
+ pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
+ fixed_link_node);
+ gpiod = NULL;
+ }
+
+ return gpiod;
+}
+#else
+static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
+{
+ return NULL;
+}
+#endif
+
+static struct phy_device *__fixed_phy_register(unsigned int irq,
+ struct fixed_phy_status *status,
+ struct device_node *np,
+ struct gpio_desc *gpiod)
{
struct fixed_mdio_bus *fmb = &platform_fmb;
struct phy_device *phy;
@@ -213,12 +243,19 @@ struct phy_device *fixed_phy_register(unsigned int irq,
if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED)
return ERR_PTR(-EPROBE_DEFER);
+ /* Check if we have a GPIO associated with this fixed phy */
+ if (!gpiod) {
+ gpiod = fixed_phy_get_gpiod(np);
+ if (IS_ERR(gpiod))
+ return ERR_CAST(gpiod);
+ }
+
/* Get the next available PHY address, up to PHY_MAX_ADDR */
phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL);
if (phy_addr < 0)
return ERR_PTR(phy_addr);
- ret = fixed_phy_add(irq, phy_addr, status, link_gpio);
+ ret = fixed_phy_add_gpiod(irq, phy_addr, status, gpiod);
if (ret < 0) {
ida_simple_remove(&phy_fixed_ida, phy_addr);
return ERR_PTR(ret);
@@ -264,6 +301,8 @@ struct phy_device *fixed_phy_register(unsigned int irq,
phy->supported);
}
+ linkmode_copy(phy->advertising, phy->supported);
+
ret = phy_device_register(phy);
if (ret) {
phy_device_free(phy);
@@ -274,8 +313,24 @@ struct phy_device *fixed_phy_register(unsigned int irq,
return phy;
}
+
+struct phy_device *fixed_phy_register(unsigned int irq,
+ struct fixed_phy_status *status,
+ struct device_node *np)
+{
+ return __fixed_phy_register(irq, status, np, NULL);
+}
EXPORT_SYMBOL_GPL(fixed_phy_register);
+struct phy_device *
+fixed_phy_register_with_gpiod(unsigned int irq,
+ struct fixed_phy_status *status,
+ struct gpio_desc *gpiod)
+{
+ return __fixed_phy_register(irq, status, NULL, gpiod);
+}
+EXPORT_SYMBOL_GPL(fixed_phy_register_with_gpiod);
+
void fixed_phy_unregister(struct phy_device *phy)
{
phy_device_remove(phy);
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 7d5938b87660..ebef8354bc81 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -1,13 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for ICPlus PHYs
*
* Copyright (c) 2007 Freescale Semiconductor, 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index fc0f5024a29e..02d9713318b6 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
* Copyright (C) 2016 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * 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/mdio.h>
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index c8bb29ae1a2a..a93d673baf35 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/lxt.c
*
@@ -6,12 +7,6 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index a9c7c7f41b0c..3ccba37bd6dd 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/marvell.c
*
@@ -8,12 +9,6 @@
* Copyright (c) 2004 Freescale Semiconductor, Inc.
*
* Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.de>
- *
- * 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/kernel.h>
#include <linux/string.h>
@@ -847,7 +842,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
/* SGMII-to-Copper mode initialization */
if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
-
/* Select page 18 */
err = marvell_set_page(phydev, 18);
if (err < 0)
@@ -870,21 +864,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
if (err < 0)
return err;
-
- /* There appears to be a bug in the 88e1512 when used in
- * SGMII to copper mode, where the AN advertisement register
- * clears the pause bits each time a negotiation occurs.
- * This means we can never be truely sure what was advertised,
- * so disable Pause support.
- */
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
- phydev->supported);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
- phydev->supported);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
- phydev->advertising);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
- phydev->advertising);
}
return m88e1318_config_init(phydev);
@@ -1046,6 +1025,39 @@ static int m88e1145_config_init(struct phy_device *phydev)
return 0;
}
+/* The VOD can be out of specification on link up. Poke an
+ * undocumented register, in an undocumented page, with a magic value
+ * to fix this.
+ */
+static int m88e6390_errata(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_BMCR,
+ BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);
+ if (err)
+ return err;
+
+ usleep_range(300, 400);
+
+ err = phy_write_paged(phydev, 0xf8, 0x08, 0x36);
+ if (err)
+ return err;
+
+ return genphy_soft_reset(phydev);
+}
+
+static int m88e6390_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ err = m88e6390_errata(phydev);
+ if (err)
+ return err;
+
+ return m88e1510_config_aneg(phydev);
+}
+
/**
* fiber_lpa_mod_linkmode_lpa_t
* @advertising: the linkmode advertisement settings
@@ -1402,7 +1414,7 @@ static int m88e1318_set_wol(struct phy_device *phydev,
* before enabling it if !phy_interrupt_is_valid()
*/
if (!phy_interrupt_is_valid(phydev))
- phy_read(phydev, MII_M1011_IEVENT);
+ __phy_read(phydev, MII_M1011_IEVENT);
/* Enable the WOL interrupt */
err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
@@ -2283,7 +2295,7 @@ static struct phy_driver marvell_drivers[] = {
.features = PHY_GBIT_FEATURES,
.probe = m88e6390_probe,
.config_init = &marvell_config_init,
- .config_aneg = &m88e1510_config_aneg,
+ .config_aneg = &m88e6390_config_aneg,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 82ab6ed3b74e..100b401b1f4a 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Marvell 10G 88x3310 PHY driver
*
@@ -26,6 +27,9 @@
#include <linux/marvell_phy.h>
#include <linux/phy.h>
+#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
+#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
+
enum {
MV_PCS_BASE_T = 0x0000,
MV_PCS_BASE_R = 0x1000,
@@ -57,24 +61,6 @@ struct mv3310_priv {
char *hwmon_name;
};
-static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
- u16 mask, u16 bits)
-{
- int old, val, ret;
-
- old = phy_read_mmd(phydev, devad, reg);
- if (old < 0)
- return old;
-
- val = (old & ~mask) | (bits & mask);
- if (val == old)
- return 0;
-
- ret = phy_write_mmd(phydev, devad, reg, val);
-
- return ret < 0 ? ret : 1;
-}
-
#ifdef CONFIG_HWMON
static umode_t mv3310_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type,
@@ -158,10 +144,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
return ret;
val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
- ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
- MV_V2_TEMP_CTRL_MASK, val);
- return ret < 0 ? ret : 0;
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
+ MV_V2_TEMP_CTRL_MASK, val);
}
static void mv3310_hwmon_disable(void *data)
@@ -249,95 +234,58 @@ static int mv3310_resume(struct phy_device *phydev)
return mv3310_hwmon_config(phydev, true);
}
-static int mv3310_config_init(struct phy_device *phydev)
+/* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010
+ * don't set bit 14 in PMA Extended Abilities (1.11), although they do
+ * support 2.5GBASET and 5GBASET. For these models, we can still read their
+ * 2.5G/5G extended abilities register (1.21). We detect these models based on
+ * the PMA device identifier, with a mask matching models known to have this
+ * issue
+ */
+static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
{
- __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
- int val;
+ if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))
+ return false;
+ /* Only some revisions of the 88X3310 family PMA seem to be impacted */
+ return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
+ MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
+}
+
+static int mv3310_config_init(struct phy_device *phydev)
+{
/* Check that the PHY interface type is compatible */
if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
phydev->interface != PHY_INTERFACE_MODE_XAUI &&
phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
phydev->interface != PHY_INTERFACE_MODE_10GKR)
return -ENODEV;
- __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
- __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
-
- if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
- if (val < 0)
- return val;
+ return 0;
+}
- if (val & MDIO_AN_STAT1_ABLE)
- __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
- }
+static int mv3310_get_features(struct phy_device *phydev)
+{
+ int ret, val;
- val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
- if (val < 0)
- return val;
+ ret = genphy_c45_pma_read_abilities(phydev);
+ if (ret)
+ return ret;
- /* Ethtool does not support the WAN mode bits */
- if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
- MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
- MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
- MDIO_PMA_STAT2_10GBEW))
- __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
- if (val & MDIO_PMA_STAT2_10GBSR)
- __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
- if (val & MDIO_PMA_STAT2_10GBLR)
- __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
- if (val & MDIO_PMA_STAT2_10GBER)
- __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
-
- if (val & MDIO_PMA_STAT2_EXTABLE) {
- val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
+ if (mv3310_has_pma_ngbaset_quirk(phydev)) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
+ MDIO_PMA_NG_EXTABLE);
if (val < 0)
return val;
- if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
- MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
- __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
- if (val & MDIO_PMA_EXTABLE_10GBLRM)
- __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
- if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
- MDIO_PMA_EXTABLE_1000BKX))
- __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
- if (val & MDIO_PMA_EXTABLE_10GBLRM)
- __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_10GBT)
- __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_10GBKX4)
- __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_10GBKR)
- __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_1000BT)
- __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_1000BKX)
- __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
- supported);
- if (val & MDIO_PMA_EXTABLE_100BTX) {
- __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- supported);
- __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
- supported);
- }
- if (val & MDIO_PMA_EXTABLE_10BT) {
- __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
- supported);
- __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
- supported);
- }
- }
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_NG_EXTABLE_2_5GBT);
- linkmode_copy(phydev->supported, supported);
- linkmode_and(phydev->advertising, phydev->advertising,
- phydev->supported);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_NG_EXTABLE_5GBT);
+ }
return 0;
}
@@ -351,52 +299,27 @@ static int mv3310_config_aneg(struct phy_device *phydev)
/* We don't support manual MDI control */
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
- if (phydev->autoneg == AUTONEG_DISABLE) {
- ret = genphy_c45_pma_setup_forced(phydev);
- if (ret < 0)
- return ret;
-
- return genphy_c45_an_disable_aneg(phydev);
- }
-
- linkmode_and(phydev->advertising, phydev->advertising,
- phydev->supported);
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ return genphy_c45_pma_setup_forced(phydev);
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_100BASE4 |
- ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
- linkmode_adv_to_mii_adv_t(phydev->advertising));
+ ret = genphy_c45_an_config_aneg(phydev);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
+ /* Clause 45 has no standardized support for 1000BaseT, therefore
+ * use vendor registers for this mode.
+ */
reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
- ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
- /* 10G control register */
- if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- phydev->advertising))
- reg = MDIO_AN_10GBT_CTRL_ADV10G;
- else
- reg = 0;
-
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
- MDIO_AN_10GBT_CTRL_ADV10G, reg);
- if (ret < 0)
- return ret;
- if (ret > 0)
- changed = true;
-
- if (changed)
- ret = genphy_c45_restart_aneg(phydev);
-
- return ret;
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
}
static int mv3310_aneg_done(struct phy_device *phydev)
@@ -416,18 +339,29 @@ static int mv3310_aneg_done(struct phy_device *phydev)
static void mv3310_update_interface(struct phy_device *phydev)
{
if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
+ phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
/* The PHY automatically switches its serdes interface (and
- * active PHYXS instance) between Cisco SGMII and 10GBase-KR
- * modes according to the speed. Florian suggests setting
- * phydev->interface to communicate this to the MAC. Only do
- * this if we are already in either SGMII or 10GBase-KR mode.
+ * active PHYXS instance) between Cisco SGMII, 10GBase-KR and
+ * 2500BaseX modes according to the speed. Florian suggests
+ * setting phydev->interface to communicate this to the MAC.
+ * Only do this if we are already in one of the above modes.
*/
- if (phydev->speed == SPEED_10000)
+ switch (phydev->speed) {
+ case SPEED_10000:
phydev->interface = PHY_INTERFACE_MODE_10GKR;
- else if (phydev->speed >= SPEED_10 &&
- phydev->speed < SPEED_10000)
+ break;
+ case SPEED_2500:
+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
+ break;
+ case SPEED_1000:
+ case SPEED_100:
+ case SPEED_10:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
+ break;
+ default:
+ break;
+ }
}
}
@@ -445,16 +379,8 @@ static int mv3310_read_10gbr_status(struct phy_device *phydev)
static int mv3310_read_status(struct phy_device *phydev)
{
- u32 mmd_mask = phydev->c45_ids.devices_in_package;
int val;
- /* The vendor devads do not report link status. Avoid the PHYXS
- * instance as there are three, and its status depends on the MAC
- * being appropriately configured for the negotiated speed.
- */
- mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
- BIT(MDIO_MMD_PHYXS));
-
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
linkmode_zero(phydev->lp_advertising);
@@ -470,12 +396,10 @@ static int mv3310_read_status(struct phy_device *phydev)
if (val & MDIO_STAT1_LSTATUS)
return mv3310_read_10gbr_status(phydev);
- val = genphy_c45_read_link(phydev, mmd_mask);
+ val = genphy_c45_read_link(phydev);
if (val < 0)
return val;
- phydev->link = val > 0 ? 1 : 0;
-
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
if (val < 0)
return val;
@@ -531,11 +455,11 @@ static int mv3310_read_status(struct phy_device *phydev)
static struct phy_driver mv3310_drivers[] = {
{
- .phy_id = 0x002b09aa,
+ .phy_id = MARVELL_PHY_ID_88X3310,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "mv88x3310",
- .features = PHY_10GBIT_FEATURES,
- .soft_reset = gen10g_no_soft_reset,
+ .get_features = mv3310_get_features,
+ .soft_reset = genphy_no_soft_reset,
.config_init = mv3310_config_init,
.probe = mv3310_probe,
.suspend = mv3310_suspend,
@@ -544,12 +468,25 @@ static struct phy_driver mv3310_drivers[] = {
.aneg_done = mv3310_aneg_done,
.read_status = mv3310_read_status,
},
+ {
+ .phy_id = MARVELL_PHY_ID_88E2110,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+ .name = "mv88x2110",
+ .get_features = genphy_c45_pma_read_abilities,
+ .probe = mv3310_probe,
+ .soft_reset = genphy_no_soft_reset,
+ .config_init = mv3310_config_init,
+ .config_aneg = mv3310_config_aneg,
+ .aneg_done = mv3310_aneg_done,
+ .read_status = mv3310_read_status,
+ },
};
module_phy_driver(mv3310_drivers);
static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
- { 0x002b09aa, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
{ },
};
MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c
index 46fe1ae919a3..7d0f388d8db8 100644
--- a/drivers/net/phy/mdio-bcm-iproc.c
+++ b/drivers/net/phy/mdio-bcm-iproc.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 Broadcom Corporation
- *
- * 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>
diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c
index df75efa96a7d..8295bc7c8c20 100644
--- a/drivers/net/phy/mdio-bcm-unimac.c
+++ b/drivers/net/phy/mdio-bcm-unimac.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Broadcom UniMAC MDIO bus controller driver
*
* Copyright (C) 2014-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; either version 2 of the License, or
- * (at your option) any later version.
*/
#include <linux/kernel.h>
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 15352f987bdf..5136275c8e73 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Bitbanged MDIO support.
*
@@ -11,10 +12,6 @@
*
* 2005 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.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/module.h>
@@ -232,4 +229,4 @@ void free_mdio_bitbang(struct mii_bus *bus)
}
EXPORT_SYMBOL(free_mdio_bitbang);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-boardinfo.c b/drivers/net/phy/mdio-boardinfo.c
index 863496fa5d13..d9b54c67ef9f 100644
--- a/drivers/net/phy/mdio-boardinfo.c
+++ b/drivers/net/phy/mdio-boardinfo.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* mdio-boardinfo - Collect pre-declarations for MDIO devices
- *
- * 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/kernel.h>
diff --git a/drivers/net/phy/mdio-cavium.c b/drivers/net/phy/mdio-cavium.c
index 6df2fa755bb4..1afd6fc1a351 100644
--- a/drivers/net/phy/mdio-cavium.c
+++ b/drivers/net/phy/mdio-cavium.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2009-2016 Cavium, Inc.
*/
@@ -150,4 +147,4 @@ EXPORT_SYMBOL(cavium_mdiobus_write);
MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers");
MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-cavium.h b/drivers/net/phy/mdio-cavium.h
index 4bccd45d24e2..ed5f9bb5448d 100644
--- a/drivers/net/phy/mdio-cavium.h
+++ b/drivers/net/phy/mdio-cavium.h
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2009-2016 Cavium, Inc.
*/
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index ea9a0e339778..1b00235d7dc5 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* GPIO based MDIO bitbang driver.
* Supports OpenFirmware.
@@ -14,10 +15,6 @@
*
* 2005 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.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/module.h>
@@ -216,5 +213,5 @@ module_platform_driver(mdio_gpio_driver);
MODULE_ALIAS("platform:mdio-gpio");
MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO");
diff --git a/drivers/net/phy/mdio-hisi-femac.c b/drivers/net/phy/mdio-hisi-femac.c
index b03fedd6c1d8..287f3ccf1da1 100644
--- a/drivers/net/phy/mdio-hisi-femac.c
+++ b/drivers/net/phy/mdio-hisi-femac.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Hisilicon Fast Ethernet MDIO Bus Driver
*
* Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
- *
- * 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/clk.h>
@@ -163,4 +151,4 @@ module_platform_driver(hisi_femac_mdio_driver);
MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver");
MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c
index 6d24fd13ca86..0dce67672548 100644
--- a/drivers/net/phy/mdio-i2c.c
+++ b/drivers/net/phy/mdio-i2c.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* MDIO I2C bridge
*
* Copyright (C) 2015-2016 Russell King
*
- * 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.
- *
* Network PHYs can appear on I2C buses when they are part of SFP module.
* This driver exposes these PHYs to the networking PHY code, allowing
* our PHY drivers access to these PHYs, and so allowing configuration
diff --git a/drivers/net/phy/mdio-i2c.h b/drivers/net/phy/mdio-i2c.h
index 889ab57d7f3e..751dab281f57 100644
--- a/drivers/net/phy/mdio-i2c.h
+++ b/drivers/net/phy/mdio-i2c.h
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* MDIO I2C bridge
*
* Copyright (C) 2015 Russell King
- *
- * 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 MDIO_I2C_H
#define MDIO_I2C_H
diff --git a/drivers/net/phy/mdio-moxart.c b/drivers/net/phy/mdio-moxart.c
index 5bb56d126693..af3910fe8ec7 100644
--- a/drivers/net/phy/mdio-moxart.c
+++ b/drivers/net/phy/mdio-moxart.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/* MOXA ART Ethernet (RTL8201CP) MDIO interface driver
*
* Copyright (C) 2013 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/delay.h>
@@ -190,4 +187,4 @@ module_platform_driver(moxart_mdio_driver);
MODULE_DESCRIPTION("MOXA ART MDIO interface driver");
MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c
index 696bdf1e4576..88d409e48c1f 100644
--- a/drivers/net/phy/mdio-mux-bcm-iproc.c
+++ b/drivers/net/phy/mdio-mux-bcm-iproc.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2016 Broadcom
- *
- * 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 (the "GPL").
- *
- * 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 version 2 (GPLv2) for more details.
- *
- * You should have received a copy of the GNU General Public License
- * version 2 (GPLv2) along with this source code.
*/
#include <linux/clk.h>
#include <linux/platform_device.h>
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index fe34576262bd..6c8960df43b0 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2011, 2012 Cavium, Inc.
*/
@@ -103,4 +100,4 @@ module_platform_driver(mdio_mux_gpio_driver);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 70f6115530af..d1a8780e24d8 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Simple memory-mapped device MDIO MUX driver
*
* Author: Timur Tabi <timur@freescale.com>
*
* Copyright 2012 Freescale Semiconductor, Inc.
- *
- * 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/platform_device.h>
diff --git a/drivers/net/phy/mdio-mux-multiplexer.c b/drivers/net/phy/mdio-mux-multiplexer.c
new file mode 100644
index 000000000000..d6564381aa3e
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-multiplexer.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* MDIO bus multiplexer using kernel multiplexer subsystem
+ *
+ * Copyright 2019 NXP
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mdio-mux.h>
+#include <linux/module.h>
+#include <linux/mux/consumer.h>
+
+struct mdio_mux_multiplexer_state {
+ struct mux_control *muxc;
+ bool do_deselect;
+ void *mux_handle;
+};
+
+/**
+ * mdio_mux_multiplexer_switch_fn - This function is called by the mdio-mux
+ * layer when it thinks the mdio bus
+ * multiplexer needs to switch.
+ * @current_child: current value of the mux register.
+ * @desired_child: value of the 'reg' property of the target child MDIO node.
+ * @data: Private data used by this switch_fn passed to mdio_mux_init function
+ * via mdio_mux_init(.., .., .., .., data, ..).
+ *
+ * The first time this function is called, current_child == -1.
+ * If current_child == desired_child, then the mux is already set to the
+ * correct bus.
+ */
+static int mdio_mux_multiplexer_switch_fn(int current_child, int desired_child,
+ void *data)
+{
+ struct platform_device *pdev;
+ struct mdio_mux_multiplexer_state *s;
+ int ret = 0;
+
+ pdev = (struct platform_device *)data;
+ s = platform_get_drvdata(pdev);
+
+ if (!(current_child ^ desired_child))
+ return 0;
+
+ if (s->do_deselect)
+ ret = mux_control_deselect(s->muxc);
+ if (ret) {
+ dev_err(&pdev->dev, "mux_control_deselect failed in %s: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = mux_control_select(s->muxc, desired_child);
+ if (!ret) {
+ dev_dbg(&pdev->dev, "%s %d -> %d\n", __func__, current_child,
+ desired_child);
+ s->do_deselect = true;
+ } else {
+ s->do_deselect = false;
+ }
+
+ return ret;
+}
+
+static int mdio_mux_multiplexer_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mdio_mux_multiplexer_state *s;
+ int ret = 0;
+
+ s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->muxc = devm_mux_control_get(dev, NULL);
+ if (IS_ERR(s->muxc)) {
+ ret = PTR_ERR(s->muxc);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get mux: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, s);
+
+ ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node,
+ mdio_mux_multiplexer_switch_fn, &s->mux_handle,
+ pdev, NULL);
+
+ return ret;
+}
+
+static int mdio_mux_multiplexer_remove(struct platform_device *pdev)
+{
+ struct mdio_mux_multiplexer_state *s = platform_get_drvdata(pdev);
+
+ mdio_mux_uninit(s->mux_handle);
+
+ if (s->do_deselect)
+ mux_control_deselect(s->muxc);
+
+ return 0;
+}
+
+static const struct of_device_id mdio_mux_multiplexer_match[] = {
+ { .compatible = "mdio-mux-multiplexer", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_multiplexer_match);
+
+static struct platform_driver mdio_mux_multiplexer_driver = {
+ .driver = {
+ .name = "mdio-mux-multiplexer",
+ .of_match_table = mdio_mux_multiplexer_match,
+ },
+ .probe = mdio_mux_multiplexer_probe,
+ .remove = mdio_mux_multiplexer_remove,
+};
+
+module_platform_driver(mdio_mux_multiplexer_driver);
+
+MODULE_DESCRIPTION("MDIO bus multiplexer using kernel multiplexer subsystem");
+MODULE_AUTHOR("Pankaj Bansal <pankaj.bansal@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 0a86f1e4c02f..6a1d3540210b 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2011, 2012 Cavium, Inc.
*/
@@ -210,4 +207,4 @@ EXPORT_SYMBOL_GPL(mdio_mux_uninit);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index ab6914f8bd50..8327382aa568 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2009-2015 Cavium, Inc.
*/
@@ -122,4 +119,4 @@ module_platform_driver(octeon_mdiobus_driver);
MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver");
MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c
index 6425ce04d3f9..20ffd8fb79ce 100644
--- a/drivers/net/phy/mdio-sun4i.c
+++ b/drivers/net/phy/mdio-sun4i.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Allwinner EMAC MDIO interface driver
*
@@ -6,10 +7,6 @@
*
* Based on the Linux driver provided by Allwinner:
* Copyright (C) 1997 Sten Wang
- *
- * 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/delay.h>
@@ -179,4 +176,4 @@ module_platform_driver(sun4i_mdio_driver);
MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver");
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-thunder.c b/drivers/net/phy/mdio-thunder.c
index 1546f6398831..b6128ae7f14f 100644
--- a/drivers/net/phy/mdio-thunder.c
+++ b/drivers/net/phy/mdio-thunder.c
@@ -1,8 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * 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) 2009-2016 Cavium, Inc.
*/
@@ -151,4 +148,4 @@ static struct pci_driver thunder_mdiobus_driver = {
module_pci_driver(thunder_mdiobus_driver);
MODULE_DESCRIPTION("Cavium ThunderX MDIO bus driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c
index 07c6048200c6..717cc2a056e8 100644
--- a/drivers/net/phy/mdio-xgene.c
+++ b/drivers/net/phy/mdio-xgene.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Applied Micro X-Gene SoC MDIO Driver
*
* Copyright (c) 2016, Applied Micro Circuits Corporation
* Author: Iyappan Subramanian <isubramanian@apm.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.
- *
- * 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/acpi.h>
diff --git a/drivers/net/phy/mdio-xgene.h b/drivers/net/phy/mdio-xgene.h
index 3c85f3e30baa..b1f5ccb4ad9c 100644
--- a/drivers/net/phy/mdio-xgene.h
+++ b/drivers/net/phy/mdio-xgene.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Applied Micro X-Gene SoC MDIO Driver
*
* Copyright (c) 2016, Applied Micro Circuits Corporation
* Author: Iyappan Subramanian <isubramanian@apm.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.
- *
- * 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 __MDIO_XGENE_H__
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 2e59a8419b17..4be4cc09eb90 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -1,14 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/* MDIO Bus interface
*
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -39,8 +34,6 @@
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <asm/irq.h>
-
#define CREATE_TRACE_POINTS
#include <trace/events/mdio.h>
@@ -55,11 +48,12 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
gpiod = fwnode_get_named_gpiod(&mdiodev->dev.of_node->fwnode,
"reset-gpios", 0, GPIOD_OUT_LOW,
"PHY reset");
- if (PTR_ERR(gpiod) == -ENOENT ||
- PTR_ERR(gpiod) == -ENOSYS)
- gpiod = NULL;
- else if (IS_ERR(gpiod))
- return PTR_ERR(gpiod);
+ if (IS_ERR(gpiod)) {
+ if (PTR_ERR(gpiod) == -ENOENT || PTR_ERR(gpiod) == -ENOSYS)
+ gpiod = NULL;
+ else
+ return PTR_ERR(gpiod);
+ }
mdiodev->reset = gpiod;
@@ -379,7 +373,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
err = device_register(&bus->dev);
if (err) {
pr_err("mii_bus %s failed to register\n", bus->id);
- put_device(&bus->dev);
return -EINVAL;
}
@@ -390,6 +383,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
if (IS_ERR(gpiod)) {
dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
bus->id);
+ device_del(&bus->dev);
return PTR_ERR(gpiod);
} else if (gpiod) {
bus->reset_gpiod = gpiod;
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index c924700cf37b..887076292e50 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -1,12 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Framework for MDIO devices, other than PHYs.
*
* Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
- *
- * 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.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index b03bcf2c388a..a238388eb1a5 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -1,20 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Amlogic Meson GXL Internal PHY Driver
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
* Copyright (C) 2016 BayLibre, SAS. All rights reserved.
* Author: Neil Armstrong <narmstrong@baylibre.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.
- *
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -233,6 +223,7 @@ static struct phy_driver meson_gxl_phy[] = {
.name = "Meson GXL Internal PHY",
.features = PHY_BASIC_FEATURES,
.flags = PHY_IS_INTERNAL,
+ .soft_reset = genphy_soft_reset,
.config_init = meson_gxl_config_init,
.aneg_done = genphy_aneg_done,
.read_status = meson_gxl_read_status,
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index c33384710d26..352da24f1f33 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/micrel.c
*
@@ -8,11 +9,6 @@
* Copyright (c) 2010-2013 Micrel, Inc.
* Copyright (c) 2014 Johan Hovold <johan@kernel.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.
- *
* Support : Micrel Phys:
* Giga phys: ksz9021, ksz9031, ksz9131
* 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
@@ -344,6 +340,17 @@ static int ksz8041_config_aneg(struct phy_device *phydev)
return genphy_config_aneg(phydev);
}
+static int ksz8061_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
+ if (ret)
+ return ret;
+
+ return kszphy_config_init(phydev);
+}
+
static int ksz9021_load_values_from_of(struct phy_device *phydev,
const struct device_node *of_node,
u16 reg,
@@ -426,9 +433,6 @@ static int ksz9021_config_init(struct phy_device *phydev)
return 0;
}
-#define MII_KSZ9031RN_MMD_CTRL_REG 0x0d
-#define MII_KSZ9031RN_MMD_REGDATA_REG 0x0e
-#define OP_DATA 1
#define KSZ9031_PS_TO_REG 60
/* Extended registers */
@@ -446,24 +450,6 @@ static int ksz9021_config_init(struct phy_device *phydev)
#define MII_KSZ9031RN_EDPD 0x23
#define MII_KSZ9031RN_EDPD_ENABLE BIT(0)
-static int ksz9031_extended_write(struct phy_device *phydev,
- u8 mode, u32 dev_addr, u32 regnum, u16 val)
-{
- phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
- phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
- phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
- return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val);
-}
-
-static int ksz9031_extended_read(struct phy_device *phydev,
- u8 mode, u32 dev_addr, u32 regnum)
-{
- phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
- phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
- phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
- return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG);
-}
-
static int ksz9031_of_load_skew_values(struct phy_device *phydev,
const struct device_node *of_node,
u16 reg, size_t field_sz,
@@ -484,7 +470,7 @@ static int ksz9031_of_load_skew_values(struct phy_device *phydev,
return 0;
if (matches < numfields)
- newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
+ newval = phy_read_mmd(phydev, 2, reg);
else
newval = 0;
@@ -498,7 +484,7 @@ static int ksz9031_of_load_skew_values(struct phy_device *phydev,
<< (field_sz * i));
}
- return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
+ return phy_write_mmd(phydev, 2, reg, newval);
}
/* Center KSZ9031RNX FLP timing at 16ms. */
@@ -506,13 +492,13 @@ static int ksz9031_center_flp_timing(struct phy_device *phydev)
{
int result;
- result = ksz9031_extended_write(phydev, OP_DATA, 0,
- MII_KSZ9031RN_FLP_BURST_TX_HI, 0x0006);
+ result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_HI,
+ 0x0006);
if (result)
return result;
- result = ksz9031_extended_write(phydev, OP_DATA, 0,
- MII_KSZ9031RN_FLP_BURST_TX_LO, 0x1A80);
+ result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_LO,
+ 0x1A80);
if (result)
return result;
@@ -524,11 +510,11 @@ static int ksz9031_enable_edpd(struct phy_device *phydev)
{
int reg;
- reg = ksz9031_extended_read(phydev, OP_DATA, 0x1C, MII_KSZ9031RN_EDPD);
+ reg = phy_read_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD);
if (reg < 0)
return reg;
- return ksz9031_extended_write(phydev, OP_DATA, 0x1C, MII_KSZ9031RN_EDPD,
- reg | MII_KSZ9031RN_EDPD_ENABLE);
+ return phy_write_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD,
+ reg | MII_KSZ9031RN_EDPD_ENABLE);
}
static int ksz9031_config_init(struct phy_device *phydev)
@@ -654,7 +640,7 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev,
return 0;
if (matches < numfields)
- newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
+ newval = phy_read_mmd(phydev, 2, reg);
else
newval = 0;
@@ -668,7 +654,7 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev,
<< (field_sz * i));
}
- return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
+ return phy_write_mmd(phydev, 2, reg, newval);
}
static int ksz9131_config_init(struct phy_device *phydev)
@@ -1040,7 +1026,7 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KSZ8061",
.phy_id_mask = MICREL_PHY_ID_MASK,
.features = PHY_BASIC_FEATURES,
- .config_init = kszphy_config_init,
+ .config_init = ksz8061_config_init,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
.suspend = genphy_suspend,
@@ -1070,6 +1056,7 @@ static struct phy_driver ksphy_driver[] = {
.driver_data = &ksz9021_type,
.probe = kszphy_probe,
.config_init = ksz9031_config_init,
+ .soft_reset = genphy_soft_reset,
.read_status = ksz9031_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
@@ -1098,6 +1085,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id = PHY_ID_KSZ8873MLL,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Micrel KSZ8873MLL Switch",
+ .features = PHY_BASIC_FEATURES,
.config_init = kszphy_config_init,
.config_aneg = ksz8873mll_config_aneg,
.read_status = ksz8873mll_read_status,
diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
index 7557bebd5d7f..c6cbb3aa8ae0 100644
--- a/drivers/net/phy/microchip.c
+++ b/drivers/net/phy/microchip.c
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015 Microchip Technology
- *
- * 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/kernel.h>
#include <linux/module.h>
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 3949fe299b18..db50efb30df5 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Driver for Microsemi VSC85xx PHYs
*
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index 139bed2c8ab4..42282a86b680 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/national.c
*
@@ -7,12 +8,6 @@
* Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*
* Copyright (c) 2008 STMicroelectronics Limited
- *
- * 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.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 03af927fa5ad..9e24d9569424 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -47,6 +47,16 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev)
/* Assume 1000base-T */
ctrl2 |= MDIO_PMA_CTRL2_1000BT;
break;
+ case SPEED_2500:
+ ctrl1 |= MDIO_CTRL1_SPEED2_5G;
+ /* Assume 2.5Gbase-T */
+ ctrl2 |= MDIO_PMA_CTRL2_2_5GBT;
+ break;
+ case SPEED_5000:
+ ctrl1 |= MDIO_CTRL1_SPEED5G;
+ /* Assume 5Gbase-T */
+ ctrl2 |= MDIO_PMA_CTRL2_5GBT;
+ break;
case SPEED_10000:
ctrl1 |= MDIO_CTRL1_SPEED10G;
/* Assume 10Gbase-T */
@@ -60,11 +70,60 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev)
if (ret < 0)
return ret;
- return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
+ ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
+ if (ret < 0)
+ return ret;
+
+ return genphy_c45_an_disable_aneg(phydev);
}
EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
/**
+ * genphy_c45_an_config_aneg - configure advertisement registers
+ * @phydev: target phy_device struct
+ *
+ * Configure advertisement registers based on modes set in phydev->advertising
+ *
+ * Returns negative errno code on failure, 0 if advertisement didn't change,
+ * or 1 if advertised modes changed.
+ */
+int genphy_c45_an_config_aneg(struct phy_device *phydev)
+{
+ int changed, ret;
+ u32 adv;
+
+ linkmode_and(phydev->advertising, phydev->advertising,
+ phydev->supported);
+
+ changed = genphy_config_eee_advert(phydev);
+
+ adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_100BASE4 |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
+ adv);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = 1;
+
+ adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV10G |
+ MDIO_AN_10GBT_CTRL_ADV5G |
+ MDIO_AN_10GBT_CTRL_ADV2_5G, adv);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = 1;
+
+ return changed;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg);
+
+/**
* genphy_c45_an_disable_aneg - disable auto-negotiation
* @phydev: target phy_device struct
*
@@ -75,15 +134,9 @@ EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
*/
int genphy_c45_an_disable_aneg(struct phy_device *phydev)
{
- int val;
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
- if (val < 0)
- return val;
-
- val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
-
- return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
+ MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
}
EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
@@ -97,17 +150,40 @@ EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
*/
int genphy_c45_restart_aneg(struct phy_device *phydev)
{
- int val;
+ return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
+ MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
- if (val < 0)
- return val;
+/**
+ * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation
+ * @phydev: target phy_device struct
+ * @restart: whether aneg restart is requested
+ *
+ * This assumes that the auto-negotiation MMD is present.
+ *
+ * Check, and restart auto-negotiation if needed.
+ */
+int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
+{
+ int ret = 0;
+
+ if (!restart) {
+ /* Configure and restart aneg if it wasn't set before */
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ if (ret < 0)
+ return ret;
- val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
+ if (!(ret & MDIO_AN_CTRL1_ENABLE))
+ restart = true;
+ }
+
+ if (restart)
+ ret = genphy_c45_restart_aneg(phydev);
- return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
+ return ret;
}
-EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
+EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
/**
* genphy_c45_aneg_done - return auto-negotiation complete status
@@ -131,25 +207,33 @@ EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
/**
* genphy_c45_read_link - read the overall link status from the MMDs
* @phydev: target phy_device struct
- * @mmd_mask: MMDs to read status from
*
* Read the link status from the specified MMDs, and if they all indicate
- * that the link is up, return positive. If an error is encountered,
+ * that the link is up, set phydev->link to 1. If an error is encountered,
* a negative errno will be returned, otherwise zero.
*/
-int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
+int genphy_c45_read_link(struct phy_device *phydev)
{
+ u32 mmd_mask = MDIO_DEVS_PMAPMD;
int val, devad;
bool link = true;
- while (mmd_mask) {
+ while (mmd_mask && link) {
devad = __ffs(mmd_mask);
mmd_mask &= ~BIT(devad);
/* The link state is latched low so that momentary link
- * drops can be detected. Do not double-read the status
- * register if the link is down.
+ * drops can be detected. Do not double-read the status
+ * in polling mode to detect such short link drops.
*/
+ if (!phy_polling_mode(phydev)) {
+ val = phy_read_mmd(phydev, devad, MDIO_STAT1);
+ if (val < 0)
+ return val;
+ else if (val & MDIO_STAT1_LSTATUS)
+ continue;
+ }
+
val = phy_read_mmd(phydev, devad, MDIO_STAT1);
if (val < 0)
return val;
@@ -158,7 +242,9 @@ int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
link = false;
}
- return link;
+ phydev->link = link;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(genphy_c45_read_link);
@@ -181,7 +267,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev)
if (val < 0)
return val;
- mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, val);
+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, val);
phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
@@ -190,9 +276,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev)
if (val < 0)
return val;
- if (val & MDIO_AN_10GBT_STAT_LP10G)
- linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- phydev->lp_advertising);
+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val);
return 0;
}
@@ -220,6 +304,12 @@ int genphy_c45_read_pma(struct phy_device *phydev)
case MDIO_PMA_CTRL1_SPEED1000:
phydev->speed = SPEED_1000;
break;
+ case MDIO_CTRL1_SPEED2_5G:
+ phydev->speed = SPEED_2500;
+ break;
+ case MDIO_CTRL1_SPEED5G:
+ phydev->speed = SPEED_5000;
+ break;
case MDIO_CTRL1_SPEED10G:
phydev->speed = SPEED_10000;
break;
@@ -267,75 +357,162 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
-/* The gen10g_* functions are the old Clause 45 stub */
-
-int gen10g_config_aneg(struct phy_device *phydev)
+/**
+ * genphy_c45_pma_read_abilities - read supported link modes from PMA
+ * @phydev: target phy_device struct
+ *
+ * Read the supported link modes from the PMA Status 2 (1.8) register. If bit
+ * 1.8.9 is set, the list of supported modes is build using the values in the
+ * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related
+ * modes. If bit 1.11.14 is set, then the list is also extended with the modes
+ * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and
+ * 5GBASET are supported.
+ */
+int genphy_c45_pma_read_abilities(struct phy_device *phydev)
{
- return 0;
-}
-EXPORT_SYMBOL_GPL(gen10g_config_aneg);
+ int val;
-int gen10g_read_status(struct phy_device *phydev)
-{
- u32 mmd_mask = phydev->c45_ids.devices_in_package;
- int ret;
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+ if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+ if (val < 0)
+ return val;
- /* For now just lie and say it's 10G all the time */
- phydev->speed = SPEED_10000;
- phydev->duplex = DUPLEX_FULL;
+ if (val & MDIO_AN_STAT1_ABLE)
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ phydev->supported);
+ }
- /* Avoid reading the vendor MMDs */
- mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
+ if (val < 0)
+ return val;
- ret = genphy_c45_read_link(phydev, mmd_mask);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_STAT2_10GBSR);
- phydev->link = ret > 0 ? 1 : 0;
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_STAT2_10GBLR);
- return 0;
-}
-EXPORT_SYMBOL_GPL(gen10g_read_status);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_STAT2_10GBER);
+
+ if (val & MDIO_PMA_STAT2_EXTABLE) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
+ if (val < 0)
+ return val;
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10GBLRM);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10GBT);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10GBKX4);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10GBKR);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_1000BT);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_1000BKX);
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_100BTX);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_100BTX);
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10BT);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ phydev->supported,
+ val & MDIO_PMA_EXTABLE_10BT);
+
+ if (val & MDIO_PMA_EXTABLE_NBT) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
+ MDIO_PMA_NG_EXTABLE);
+ if (val < 0)
+ return val;
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_NG_EXTABLE_2_5GBT);
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+ phydev->supported,
+ val & MDIO_PMA_NG_EXTABLE_5GBT);
+ }
+ }
-int gen10g_no_soft_reset(struct phy_device *phydev)
-{
- /* Do nothing for now */
return 0;
}
-EXPORT_SYMBOL_GPL(gen10g_no_soft_reset);
+EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
-int gen10g_config_init(struct phy_device *phydev)
+/**
+ * genphy_c45_read_status - read PHY status
+ * @phydev: target phy_device struct
+ *
+ * Reads status from PHY and sets phy_device members accordingly.
+ */
+int genphy_c45_read_status(struct phy_device *phydev)
{
- /* Temporarily just say we support everything */
- linkmode_zero(phydev->supported);
+ int ret;
- linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- phydev->supported);
- linkmode_copy(phydev->advertising, phydev->supported);
+ ret = genphy_c45_read_link(phydev);
+ if (ret)
+ return ret;
- return 0;
+ phydev->speed = SPEED_UNKNOWN;
+ phydev->duplex = DUPLEX_UNKNOWN;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ ret = genphy_c45_read_lpa(phydev);
+ if (ret)
+ return ret;
+
+ phy_resolve_aneg_linkmode(phydev);
+ } else {
+ ret = genphy_c45_read_pma(phydev);
+ }
+
+ return ret;
}
-EXPORT_SYMBOL_GPL(gen10g_config_init);
+EXPORT_SYMBOL_GPL(genphy_c45_read_status);
-int gen10g_suspend(struct phy_device *phydev)
+/* The gen10g_* functions are the old Clause 45 stub */
+
+int gen10g_config_aneg(struct phy_device *phydev)
{
return 0;
}
-EXPORT_SYMBOL_GPL(gen10g_suspend);
+EXPORT_SYMBOL_GPL(gen10g_config_aneg);
-int gen10g_resume(struct phy_device *phydev)
+static int gen10g_read_status(struct phy_device *phydev)
{
- return 0;
+ /* For now just lie and say it's 10G all the time */
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+
+ return genphy_c45_read_link(phydev);
}
-EXPORT_SYMBOL_GPL(gen10g_resume);
struct phy_driver genphy_10g_driver = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic 10G PHY",
- .soft_reset = gen10g_no_soft_reset,
- .config_init = gen10g_config_init,
+ .soft_reset = genphy_no_soft_reset,
.features = PHY_10GBIT_FEATURES,
.config_aneg = gen10g_config_aneg,
.read_status = gen10g_read_status,
- .suspend = gen10g_suspend,
- .resume = gen10g_resume,
};
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 20fbd5eb56fd..5016cd5fd7c7 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Core PHY library, taken from phy.c
- *
- * 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/export.h>
#include <linux/phy.h>
+#include <linux/of.h>
const char *phy_speed_to_str(int speed)
{
@@ -342,6 +339,77 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
return count;
}
+static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
+{
+ const struct phy_setting *p;
+ int i;
+
+ for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
+ if (p->speed > max_speed)
+ linkmode_clear_bit(p->bit, phydev->supported);
+ else
+ break;
+ }
+
+ return 0;
+}
+
+int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
+{
+ int err;
+
+ err = __set_phy_supported(phydev, max_speed);
+ if (err)
+ return err;
+
+ linkmode_copy(phydev->advertising, phydev->supported);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_set_max_speed);
+
+void of_set_phy_supported(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ u32 max_speed;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (!of_property_read_u32(node, "max-speed", &max_speed))
+ __set_phy_supported(phydev, max_speed);
+}
+
+void of_set_phy_eee_broken(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ u32 broken = 0;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (of_property_read_bool(node, "eee-broken-100tx"))
+ broken |= MDIO_EEE_100TX;
+ if (of_property_read_bool(node, "eee-broken-1000t"))
+ broken |= MDIO_EEE_1000T;
+ if (of_property_read_bool(node, "eee-broken-10gt"))
+ broken |= MDIO_EEE_10GT;
+ if (of_property_read_bool(node, "eee-broken-1000kx"))
+ broken |= MDIO_EEE_1000KX;
+ if (of_property_read_bool(node, "eee-broken-10gkx4"))
+ broken |= MDIO_EEE_10GKX4;
+ if (of_property_read_bool(node, "eee-broken-10gkr"))
+ broken |= MDIO_EEE_10GKR;
+
+ phydev->eee_broken_modes = broken;
+}
+
/**
* phy_resolve_aneg_linkmode - resolve the advertisements into phy settings
* @phydev: The phy_device struct
@@ -353,45 +421,16 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
void phy_resolve_aneg_linkmode(struct phy_device *phydev)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
+ int i;
linkmode_and(common, phydev->lp_advertising, phydev->advertising);
- if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, common)) {
- phydev->speed = SPEED_10000;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
- common)) {
- phydev->speed = SPEED_5000;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
- common)) {
- phydev->speed = SPEED_2500;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- common)) {
- phydev->speed = SPEED_1000;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
- common)) {
- phydev->speed = SPEED_1000;
- phydev->duplex = DUPLEX_HALF;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- common)) {
- phydev->speed = SPEED_100;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
- common)) {
- phydev->speed = SPEED_100;
- phydev->duplex = DUPLEX_HALF;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
- common)) {
- phydev->speed = SPEED_10;
- phydev->duplex = DUPLEX_FULL;
- } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
- common)) {
- phydev->speed = SPEED_10;
- phydev->duplex = DUPLEX_HALF;
- }
+ for (i = 0; i < ARRAY_SIZE(settings); i++)
+ if (test_bit(settings[i].bit, common)) {
+ phydev->speed = settings[i].speed;
+ phydev->duplex = settings[i].duplex;
+ break;
+ }
if (phydev->duplex == DUPLEX_FULL) {
phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
@@ -418,15 +457,15 @@ static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
}
/**
- * phy_read_mmd - Convenience function for reading a register
+ * __phy_read_mmd - Convenience function for reading a register
* from an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from (0..31)
* @regnum: The register on the MMD to read (0..65535)
*
- * Same rules as for phy_read();
+ * Same rules as for __phy_read();
*/
-int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
+int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
{
int val;
@@ -438,33 +477,52 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
} else if (phydev->is_c45) {
u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
- val = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
+ val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
} else {
struct mii_bus *bus = phydev->mdio.bus;
int phy_addr = phydev->mdio.addr;
- mutex_lock(&bus->mdio_lock);
mmd_phy_indirect(bus, phy_addr, devad, regnum);
/* Read the content of the MMD's selected register */
val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
- mutex_unlock(&bus->mdio_lock);
}
return val;
}
+EXPORT_SYMBOL(__phy_read_mmd);
+
+/**
+ * phy_read_mmd - Convenience function for reading a register
+ * from an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ *
+ * Same rules as for phy_read();
+ */
+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
+{
+ int ret;
+
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
+ ret = __phy_read_mmd(phydev, devad, regnum);
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
+
+ return ret;
+}
EXPORT_SYMBOL(phy_read_mmd);
/**
- * phy_write_mmd - Convenience function for writing a register
+ * __phy_write_mmd - Convenience function for writing a register
* on an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from
* @regnum: The register on the MMD to read
* @val: value to write to @regnum
*
- * Same rules as for phy_write();
+ * Same rules as for __phy_write();
*/
-int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
+int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
{
int ret;
@@ -476,27 +534,47 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
} else if (phydev->is_c45) {
u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
- ret = mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
- addr, val);
+ ret = __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
+ addr, val);
} else {
struct mii_bus *bus = phydev->mdio.bus;
int phy_addr = phydev->mdio.addr;
- mutex_lock(&bus->mdio_lock);
mmd_phy_indirect(bus, phy_addr, devad, regnum);
/* Write the data into MMD's selected register */
__mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
- mutex_unlock(&bus->mdio_lock);
ret = 0;
}
return ret;
}
+EXPORT_SYMBOL(__phy_write_mmd);
+
+/**
+ * phy_write_mmd - Convenience function for writing a register
+ * on an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ * @val: value to write to @regnum
+ *
+ * Same rules as for phy_write();
+ */
+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
+{
+ int ret;
+
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
+ ret = __phy_write_mmd(phydev, devad, regnum, val);
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
+
+ return ret;
+}
EXPORT_SYMBOL(phy_write_mmd);
/**
- * __phy_modify() - Convenience function for modifying a PHY register
+ * __phy_modify_changed() - Convenience function for modifying a PHY register
* @phydev: a pointer to a &struct phy_device
* @regnum: register number
* @mask: bit mask of bits to clear
@@ -504,16 +582,69 @@ EXPORT_SYMBOL(phy_write_mmd);
*
* Unlocked helper function which allows a PHY register to be modified as
* new register value = (old register value & ~mask) | set
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
*/
-int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
+int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
+ u16 set)
{
- int ret;
+ int new, ret;
ret = __phy_read(phydev, regnum);
if (ret < 0)
return ret;
- ret = __phy_write(phydev, regnum, (ret & ~mask) | set);
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = __phy_write(phydev, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+EXPORT_SYMBOL_GPL(__phy_modify_changed);
+
+/**
+ * phy_modify_changed - Function for modifying a PHY register
+ * @phydev: the phy_device struct
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
+{
+ int ret;
+
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
+ ret = __phy_modify_changed(phydev, regnum, mask, set);
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_modify_changed);
+
+/**
+ * __phy_modify - Convenience function for modifying a PHY register
+ * @phydev: the phy_device struct
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
+{
+ int ret;
+
+ ret = __phy_modify_changed(phydev, regnum, mask, set);
return ret < 0 ? ret : 0;
}
@@ -542,6 +673,113 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
}
EXPORT_SYMBOL_GPL(phy_modify);
+/**
+ * __phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * Unlocked helper function which allows a MMD register to be modified as
+ * new register value = (old register value & ~mask) | set
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int new, ret;
+
+ ret = __phy_read_mmd(phydev, devad, regnum);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = __phy_write_mmd(phydev, devad, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
+
+/**
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
+ ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
+
+/**
+ * __phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+
+ return ret < 0 ? ret : 0;
+}
+EXPORT_SYMBOL_GPL(__phy_modify_mmd);
+
+/**
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
+ ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_modify_mmd);
+
static int __phy_read_page(struct phy_device *phydev)
{
return phydev->drv->read_page(phydev);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d33e7b3caf03..3745220c5c98 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Framework for configuring and reading PHY devices
* Based on code in sungem_phy.c and gianfar_phy.c
*
@@ -5,16 +6,8 @@
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
* Copyright (c) 2006, 2007 Maciej W. Rozycki
- *
- * 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.
- *
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -36,8 +29,6 @@
#include <linux/uaccess.h>
#include <linux/atomic.h>
-#include <asm/irq.h>
-
#define PHY_STATE_STR(_state) \
case PHY_##_state: \
return __stringify(_state); \
@@ -51,7 +42,6 @@ static const char *phy_state_to_str(enum phy_state st)
PHY_STATE_STR(RUNNING)
PHY_STATE_STR(NOLINK)
PHY_STATE_STR(FORCING)
- PHY_STATE_STR(CHANGELINK)
PHY_STATE_STR(HALTED)
PHY_STATE_STR(RESUMING)
}
@@ -154,14 +144,10 @@ int phy_aneg_done(struct phy_device *phydev)
{
if (phydev->drv && phydev->drv->aneg_done)
return phydev->drv->aneg_done(phydev);
-
- /* Avoid genphy_aneg_done() if the Clause 45 PHY does not
- * implement Clause 22 registers
- */
- if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
- return -EINVAL;
-
- return genphy_aneg_done(phydev);
+ else if (phydev->is_c45)
+ return genphy_c45_aneg_done(phydev);
+ else
+ return genphy_aneg_done(phydev);
}
EXPORT_SYMBOL(phy_aneg_done);
@@ -543,13 +529,6 @@ int phy_start_aneg(struct phy_device *phydev)
mutex_lock(&phydev->lock);
- if (!__phy_is_started(phydev)) {
- WARN(1, "called from state %s\n",
- phy_state_to_str(phydev->state));
- err = -EBUSY;
- goto out_unlock;
- }
-
if (AUTONEG_DISABLE == phydev->autoneg)
phy_sanitize_settings(phydev);
@@ -560,11 +539,13 @@ int phy_start_aneg(struct phy_device *phydev)
if (err < 0)
goto out_unlock;
- if (phydev->autoneg == AUTONEG_ENABLE) {
- err = phy_check_link_status(phydev);
- } else {
- phydev->state = PHY_FORCING;
- phydev->link_timeout = PHY_FORCE_TIMEOUT;
+ if (phy_is_started(phydev)) {
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ err = phy_check_link_status(phydev);
+ } else {
+ phydev->state = PHY_FORCING;
+ phydev->link_timeout = PHY_FORCE_TIMEOUT;
+ }
}
out_unlock:
@@ -714,7 +695,7 @@ void phy_stop_machine(struct phy_device *phydev)
cancel_delayed_work_sync(&phydev->state_queue);
mutex_lock(&phydev->lock);
- if (__phy_is_started(phydev))
+ if (phy_is_started(phydev))
phydev->state = PHY_UP;
mutex_unlock(&phydev->lock);
}
@@ -767,9 +748,6 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
- if (!phy_is_started(phydev))
- return IRQ_NONE; /* It can't be ours. */
-
if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev))
return IRQ_NONE;
@@ -800,46 +778,27 @@ static int phy_enable_interrupts(struct phy_device *phydev)
}
/**
- * phy_start_interrupts - request and enable interrupts for a PHY device
+ * phy_request_interrupt - request interrupt for a PHY device
* @phydev: target phy_device struct
*
* Description: Request the interrupt for the given PHY.
* If this fails, then we set irq to PHY_POLL.
- * Otherwise, we enable the interrupts in the PHY.
* This should only be called with a valid IRQ number.
- * Returns 0 on success or < 0 on error.
*/
-int phy_start_interrupts(struct phy_device *phydev)
+void phy_request_interrupt(struct phy_device *phydev)
{
- if (request_threaded_irq(phydev->irq, NULL, phy_interrupt,
- IRQF_ONESHOT | IRQF_SHARED,
- phydev_name(phydev), phydev) < 0) {
- pr_warn("%s: Can't get IRQ %d (PHY)\n",
- phydev->mdio.bus->name, phydev->irq);
+ int err;
+
+ err = request_threaded_irq(phydev->irq, NULL, phy_interrupt,
+ IRQF_ONESHOT | IRQF_SHARED,
+ phydev_name(phydev), phydev);
+ if (err) {
+ phydev_warn(phydev, "Error %d requesting IRQ %d, falling back to polling\n",
+ err, phydev->irq);
phydev->irq = PHY_POLL;
- return 0;
}
-
- return phy_enable_interrupts(phydev);
}
-EXPORT_SYMBOL(phy_start_interrupts);
-
-/**
- * phy_stop_interrupts - disable interrupts from a PHY device
- * @phydev: target phy_device struct
- */
-int phy_stop_interrupts(struct phy_device *phydev)
-{
- int err = phy_disable_interrupts(phydev);
-
- if (err)
- phy_error(phydev);
-
- free_irq(phydev->irq, phydev);
-
- return err;
-}
-EXPORT_SYMBOL(phy_stop_interrupts);
+EXPORT_SYMBOL(phy_request_interrupt);
/**
* phy_stop - Bring down the PHY link, and stop checking the status
@@ -847,15 +806,14 @@ EXPORT_SYMBOL(phy_stop_interrupts);
*/
void phy_stop(struct phy_device *phydev)
{
- mutex_lock(&phydev->lock);
-
- if (!__phy_is_started(phydev)) {
+ if (!phy_is_started(phydev)) {
WARN(1, "called from state %s\n",
phy_state_to_str(phydev->state));
- mutex_unlock(&phydev->lock);
return;
}
+ mutex_lock(&phydev->lock);
+
if (phy_interrupt_is_valid(phydev))
phy_disable_interrupts(phydev);
@@ -864,6 +822,7 @@ void phy_stop(struct phy_device *phydev)
mutex_unlock(&phydev->lock);
phy_state_machine(&phydev->state_queue.work);
+ phy_stop_machine(phydev);
/* Cannot call flush_scheduled_work() here as desired because
* of rtnl_lock(), but PHY_HALTED shall guarantee irq handler
@@ -884,33 +843,34 @@ EXPORT_SYMBOL(phy_stop);
*/
void phy_start(struct phy_device *phydev)
{
- int err = 0;
+ int err;
mutex_lock(&phydev->lock);
- switch (phydev->state) {
- case PHY_READY:
- phydev->state = PHY_UP;
- break;
- case PHY_HALTED:
- /* if phy was suspended, bring the physical link up again */
- __phy_resume(phydev);
+ if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
+ WARN(1, "called from state %s\n",
+ phy_state_to_str(phydev->state));
+ goto out;
+ }
- /* make sure interrupts are re-enabled for the PHY */
- if (phy_interrupt_is_valid(phydev)) {
- err = phy_enable_interrupts(phydev);
- if (err < 0)
- break;
- }
+ /* if phy was suspended, bring the physical link up again */
+ __phy_resume(phydev);
- phydev->state = PHY_RESUMING;
- break;
- default:
- break;
+ /* make sure interrupts are enabled for the PHY */
+ if (phy_interrupt_is_valid(phydev)) {
+ err = phy_enable_interrupts(phydev);
+ if (err < 0)
+ goto out;
}
- mutex_unlock(&phydev->lock);
- phy_trigger_machine(phydev);
+ if (phydev->state == PHY_READY)
+ phydev->state = PHY_UP;
+ else
+ phydev->state = PHY_RESUMING;
+
+ phy_start_machine(phydev);
+out:
+ mutex_unlock(&phydev->lock);
}
EXPORT_SYMBOL(phy_start);
@@ -944,7 +904,6 @@ void phy_state_machine(struct work_struct *work)
break;
case PHY_NOLINK:
case PHY_RUNNING:
- case PHY_CHANGELINK:
case PHY_RESUMING:
err = phy_check_link_status(phydev);
break;
@@ -994,8 +953,10 @@ void phy_state_machine(struct work_struct *work)
* state machine would be pointless and possibly error prone when
* called from phy_disconnect() synchronously.
*/
+ mutex_lock(&phydev->lock);
if (phy_polling_mode(phydev) && phy_is_started(phydev))
phy_queue_state_machine(phydev, PHY_STATE_TIME);
+ mutex_unlock(&phydev->lock);
}
/**
@@ -1093,17 +1054,12 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
if (!phy_check_valid(phydev->speed, phydev->duplex, common))
goto eee_exit_err;
- if (clk_stop_enable) {
+ if (clk_stop_enable)
/* Configure the PHY to stop receiving xMII
* clock while it is signaling LPI.
*/
- int val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1);
- if (val < 0)
- return val;
-
- val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, val);
- }
+ phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
+ MDIO_PCS_CTRL1_CLKSTOP_EN);
return 0; /* EEE supported */
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 51990002d495..49fdd1ee798e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Framework for finding and configuring PHYs.
* Also contains generic PHY driver
*
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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.
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -35,9 +30,6 @@
#include <linux/mdio.h>
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <linux/of.h>
-
-#include <asm/irq.h>
MODULE_DESCRIPTION("PHY library");
MODULE_AUTHOR("Andy Fleming");
@@ -61,6 +53,9 @@ EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
EXPORT_SYMBOL_GPL(phy_10gbit_features);
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features);
+
static const int phy_basic_ports_array[] = {
ETHTOOL_LINK_MODE_Autoneg_BIT,
ETHTOOL_LINK_MODE_TP_BIT,
@@ -109,6 +104,11 @@ const int phy_10gbit_features_array[1] = {
};
EXPORT_SYMBOL_GPL(phy_10gbit_features_array);
+const int phy_10gbit_fec_features_array[1] = {
+ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features_array);
+
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
@@ -191,6 +191,10 @@ static void features_init(void)
linkmode_set_bit_array(phy_10gbit_full_features_array,
ARRAY_SIZE(phy_10gbit_full_features_array),
phy_10gbit_full_features);
+ /* 10G FEC only */
+ linkmode_set_bit_array(phy_10gbit_fec_features_array,
+ ARRAY_SIZE(phy_10gbit_fec_features_array),
+ phy_10gbit_fec_features);
}
void phy_device_free(struct phy_device *phydev)
@@ -548,12 +552,33 @@ static const struct device_type mdio_bus_phy_type = {
.pm = MDIO_BUS_PHY_PM_OPS,
};
+static int phy_request_driver_module(struct phy_device *dev, int phy_id)
+{
+ int ret;
+
+ ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
+ MDIO_ID_ARGS(phy_id));
+ /* We only check for failures in executing the usermode binary,
+ * not whether a PHY driver module exists for the PHY ID.
+ * Accept -ENOENT because this may occur in case no initramfs exists,
+ * then modprobe isn't available.
+ */
+ if (IS_ENABLED(CONFIG_MODULES) && ret < 0 && ret != -ENOENT) {
+ phydev_err(dev, "error %d loading PHY driver module for ID 0x%08x\n",
+ ret, phy_id);
+ return ret;
+ }
+
+ return 0;
+}
+
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
bool is_c45,
struct phy_c45_device_ids *c45_ids)
{
struct phy_device *dev;
struct mdio_device *mdiodev;
+ int ret = 0;
/* We allocate the device, and initialize the default values */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -610,15 +635,21 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
if (!(c45_ids->devices_in_package & (1 << i)))
continue;
- request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
- MDIO_ID_ARGS(c45_ids->device_ids[i]));
+ ret = phy_request_driver_module(dev,
+ c45_ids->device_ids[i]);
+ if (ret)
+ break;
}
} else {
- request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
- MDIO_ID_ARGS(phy_id));
+ ret = phy_request_driver_module(dev, phy_id);
}
- device_initialize(&mdiodev->dev);
+ if (!ret) {
+ device_initialize(&mdiodev->dev);
+ } else {
+ kfree(dev);
+ dev = ERR_PTR(ret);
+ }
return dev;
}
@@ -644,13 +675,16 @@ static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr,
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
- *devices_in_package = (phy_reg & 0xffff) << 16;
+ *devices_in_package = phy_reg << 16;
reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS1;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
- *devices_in_package |= (phy_reg & 0xffff);
+ *devices_in_package |= phy_reg;
+
+ /* Bit 0 doesn't represent a device, it indicates c22 regs presence */
+ *devices_in_package &= ~BIT(0);
return 0;
}
@@ -711,13 +745,13 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
- c45_ids->device_ids[i] = (phy_reg & 0xffff) << 16;
+ c45_ids->device_ids[i] = phy_reg << 16;
reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID2;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
- c45_ids->device_ids[i] |= (phy_reg & 0xffff);
+ c45_ids->device_ids[i] |= phy_reg;
}
*phy_id = 0;
return 0;
@@ -750,25 +784,18 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
/* Grab the bits from PHYIR1, and put them in the upper half */
phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
if (phy_reg < 0) {
- /* if there is no device, return without an error so scanning
- * the bus works properly
- */
- if (phy_reg == -EIO || phy_reg == -ENODEV) {
- *phy_id = 0xffffffff;
- return 0;
- }
-
- return -EIO;
+ /* returning -ENODEV doesn't stop bus scanning */
+ return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
}
- *phy_id = (phy_reg & 0xffff) << 16;
+ *phy_id = phy_reg << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
if (phy_reg < 0)
return -EIO;
- *phy_id |= (phy_reg & 0xffff);
+ *phy_id |= phy_reg;
return 0;
}
@@ -819,13 +846,13 @@ int phy_device_register(struct phy_device *phydev)
/* Run all of the fixups for this PHY */
err = phy_scan_fixups(phydev);
if (err) {
- pr_err("PHY %d failed to initialize\n", phydev->mdio.addr);
+ phydev_err(phydev, "failed to initialize\n");
goto out;
}
err = device_add(&phydev->mdio.dev);
if (err) {
- pr_err("PHY %d failed to add\n", phydev->mdio.addr);
+ phydev_err(phydev, "failed to add\n");
goto out;
}
@@ -926,9 +953,8 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
return rc;
phy_prepare_link(phydev, handler);
- phy_start_machine(phydev);
- if (phydev->irq > 0)
- phy_start_interrupts(phydev);
+ if (phy_interrupt_is_valid(phydev))
+ phy_request_interrupt(phydev);
return 0;
}
@@ -983,10 +1009,11 @@ EXPORT_SYMBOL(phy_connect);
*/
void phy_disconnect(struct phy_device *phydev)
{
- if (phydev->irq > 0)
- phy_stop_interrupts(phydev);
+ if (phy_is_started(phydev))
+ phy_stop(phydev);
- phy_stop_machine(phydev);
+ if (phy_interrupt_is_valid(phydev))
+ free_irq(phydev->irq, phydev);
phydev->adjust_link = NULL;
@@ -1041,7 +1068,7 @@ int phy_init_hw(struct phy_device *phydev)
/* Deassert the reset signal */
phy_device_reset(phydev, 0);
- if (!phydev->drv || !phydev->drv->config_init)
+ if (!phydev->drv)
return 0;
if (phydev->drv->soft_reset)
@@ -1054,7 +1081,10 @@ int phy_init_hw(struct phy_device *phydev)
if (ret < 0)
return ret;
- return phydev->drv->config_init(phydev);
+ if (phydev->drv->config_init)
+ ret = phydev->drv->config_init(phydev);
+
+ return ret;
}
EXPORT_SYMBOL(phy_init_hw);
@@ -1279,6 +1309,36 @@ struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
}
EXPORT_SYMBOL(phy_attach);
+static bool phy_driver_is_genphy_kind(struct phy_device *phydev,
+ struct device_driver *driver)
+{
+ struct device *d = &phydev->mdio.dev;
+ bool ret = false;
+
+ if (!phydev->drv)
+ return ret;
+
+ get_device(d);
+ ret = d->driver == driver;
+ put_device(d);
+
+ return ret;
+}
+
+bool phy_driver_is_genphy(struct phy_device *phydev)
+{
+ return phy_driver_is_genphy_kind(phydev,
+ &genphy_driver.mdiodrv.driver);
+}
+EXPORT_SYMBOL_GPL(phy_driver_is_genphy);
+
+bool phy_driver_is_genphy_10g(struct phy_device *phydev)
+{
+ return phy_driver_is_genphy_kind(phydev,
+ &genphy_10g_driver.mdiodrv.driver);
+}
+EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
+
/**
* phy_detach - detach a PHY device from its network device
* @phydev: target phy_device struct
@@ -1310,8 +1370,8 @@ void phy_detach(struct phy_device *phydev)
* from the generic driver so that there's a chance a
* real driver could be loaded
*/
- if (phydev->mdio.dev.driver == &genphy_10g_driver.mdiodrv.driver ||
- phydev->mdio.dev.driver == &genphy_driver.mdiodrv.driver)
+ if (phy_driver_is_genphy(phydev) ||
+ phy_driver_is_genphy_10g(phydev))
device_release_driver(&phydev->mdio.dev);
/*
@@ -1455,7 +1515,7 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable);
static int genphy_config_advert(struct phy_device *phydev)
{
u32 advertise;
- int oldadv, adv, bmsr;
+ int bmsr, adv;
int err, changed = 0;
/* Only allow advertising what this PHY supports */
@@ -1468,22 +1528,14 @@ static int genphy_config_advert(struct phy_device *phydev)
phydev->advertising);
/* Setup standard advertisement */
- adv = phy_read(phydev, MII_ADVERTISE);
- if (adv < 0)
- return adv;
-
- oldadv = adv;
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
- ADVERTISE_PAUSE_ASYM);
- adv |= ethtool_adv_to_mii_adv_t(advertise);
-
- if (adv != oldadv) {
- err = phy_write(phydev, MII_ADVERTISE, adv);
-
- if (err < 0)
- return err;
+ err = phy_modify_changed(phydev, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_100BASE4 |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
+ ethtool_adv_to_mii_adv_t(advertise));
+ if (err < 0)
+ return err;
+ if (err > 0)
changed = 1;
- }
bmsr = phy_read(phydev, MII_BMSR);
if (bmsr < 0)
@@ -1497,25 +1549,20 @@ static int genphy_config_advert(struct phy_device *phydev)
return changed;
/* Configure gigabit if it's supported */
- adv = phy_read(phydev, MII_CTRL1000);
- if (adv < 0)
- return adv;
-
- oldadv = adv;
- adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
-
+ adv = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported) ||
linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported))
- adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
-
- if (adv != oldadv)
- changed = 1;
+ adv = ethtool_adv_to_mii_ctrl1000_t(advertise);
- err = phy_write(phydev, MII_CTRL1000, adv);
+ err = phy_modify_changed(phydev, MII_CTRL1000,
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF,
+ adv);
if (err < 0)
return err;
+ if (err > 0)
+ changed = 1;
return changed;
}
@@ -1528,34 +1575,20 @@ static int genphy_config_advert(struct phy_device *phydev)
* efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't
* changed, and 1 if it has changed.
*/
-static int genphy_config_eee_advert(struct phy_device *phydev)
+int genphy_config_eee_advert(struct phy_device *phydev)
{
- int broken = phydev->eee_broken_modes;
- int old_adv, adv;
+ int err;
/* Nothing to disable */
- if (!broken)
- return 0;
-
- /* If the following call fails, we assume that EEE is not
- * supported by the phy. If we read 0, EEE is not advertised
- * In both case, we don't need to continue
- */
- adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
- if (adv <= 0)
+ if (!phydev->eee_broken_modes)
return 0;
- old_adv = adv;
- adv &= ~broken;
-
- /* Advertising remains unchanged with the broken mask */
- if (old_adv == adv)
- return 0;
-
- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
-
- return 1;
+ err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
+ phydev->eee_broken_modes, 0);
+ /* If the call failed, we assume that EEE is not supported */
+ return err < 0 ? 0 : err;
}
+EXPORT_SYMBOL(genphy_config_eee_advert);
/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
@@ -1671,10 +1704,19 @@ int genphy_update_link(struct phy_device *phydev)
{
int status;
- /* Do a fake read */
- status = phy_read(phydev, MII_BMSR);
- if (status < 0)
- return status;
+ /* The link state is latched low so that momentary link
+ * drops can be detected. Do not double-read the status
+ * in polling mode to detect such short link drops.
+ */
+ if (!phy_polling_mode(phydev)) {
+ status = phy_read(phydev, MII_BMSR);
+ if (status < 0) {
+ return status;
+ } else if (status & BMSR_LSTATUS) {
+ phydev->link = 1;
+ return 0;
+ }
+ }
/* Read link and autonegotiation status */
status = phy_read(phydev, MII_BMSR);
@@ -1705,8 +1747,6 @@ int genphy_read_status(struct phy_device *phydev)
int err;
int lpa;
int lpagb = 0;
- int common_adv;
- int common_adv_gb = 0;
/* Update the link, but return if there was an error */
err = genphy_update_link(phydev);
@@ -1738,7 +1778,6 @@ int genphy_read_status(struct phy_device *phydev)
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
lpagb);
- common_adv_gb = lpagb & adv << 2;
}
lpa = phy_read(phydev, MII_LPA);
@@ -1747,35 +1786,12 @@ int genphy_read_status(struct phy_device *phydev)
mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);
- adv = phy_read(phydev, MII_ADVERTISE);
- if (adv < 0)
- return adv;
-
- common_adv = lpa & adv;
-
- phydev->speed = SPEED_10;
- phydev->duplex = DUPLEX_HALF;
+ phydev->speed = SPEED_UNKNOWN;
+ phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
- if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
- phydev->speed = SPEED_1000;
-
- if (common_adv_gb & LPA_1000FULL)
- phydev->duplex = DUPLEX_FULL;
- } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
- phydev->speed = SPEED_100;
-
- if (common_adv & LPA_100FULL)
- phydev->duplex = DUPLEX_FULL;
- } else
- if (common_adv & LPA_10FULL)
- phydev->duplex = DUPLEX_FULL;
-
- if (phydev->duplex == DUPLEX_FULL) {
- phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
- phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
- }
+ phy_resolve_aneg_linkmode(phydev);
} else {
int bmcr = phy_read(phydev, MII_BMCR);
@@ -1907,44 +1923,6 @@ int genphy_loopback(struct phy_device *phydev, bool enable)
}
EXPORT_SYMBOL(genphy_loopback);
-static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
-{
- switch (max_speed) {
- case SPEED_10:
- linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
- phydev->supported);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- phydev->supported);
- /* fall through */
- case SPEED_100:
- linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
- phydev->supported);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- phydev->supported);
- break;
- case SPEED_1000:
- break;
- default:
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
-{
- int err;
-
- err = __set_phy_supported(phydev, max_speed);
- if (err)
- return err;
-
- linkmode_copy(phydev->advertising, phydev->supported);
-
- return 0;
-}
-EXPORT_SYMBOL(phy_set_max_speed);
-
/**
* phy_remove_link_mode - Remove a supported link mode
* @phydev: phy_device structure to remove link mode from
@@ -2075,48 +2053,6 @@ bool phy_validate_pause(struct phy_device *phydev,
}
EXPORT_SYMBOL(phy_validate_pause);
-static void of_set_phy_supported(struct phy_device *phydev)
-{
- struct device_node *node = phydev->mdio.dev.of_node;
- u32 max_speed;
-
- if (!IS_ENABLED(CONFIG_OF_MDIO))
- return;
-
- if (!node)
- return;
-
- if (!of_property_read_u32(node, "max-speed", &max_speed))
- __set_phy_supported(phydev, max_speed);
-}
-
-static void of_set_phy_eee_broken(struct phy_device *phydev)
-{
- struct device_node *node = phydev->mdio.dev.of_node;
- u32 broken = 0;
-
- if (!IS_ENABLED(CONFIG_OF_MDIO))
- return;
-
- if (!node)
- return;
-
- if (of_property_read_bool(node, "eee-broken-100tx"))
- broken |= MDIO_EEE_100TX;
- if (of_property_read_bool(node, "eee-broken-1000t"))
- broken |= MDIO_EEE_1000T;
- if (of_property_read_bool(node, "eee-broken-10gt"))
- broken |= MDIO_EEE_10GT;
- if (of_property_read_bool(node, "eee-broken-1000kx"))
- broken |= MDIO_EEE_1000KX;
- if (of_property_read_bool(node, "eee-broken-10gkx4"))
- broken |= MDIO_EEE_10GKX4;
- if (of_property_read_bool(node, "eee-broken-10gkr"))
- broken |= MDIO_EEE_10GKR;
-
- phydev->eee_broken_modes = broken;
-}
-
static bool phy_drv_supports_irq(struct phy_driver *phydrv)
{
return phydrv->config_intr && phydrv->ack_interrupt;
@@ -2150,11 +2086,30 @@ static int phy_probe(struct device *dev)
mutex_lock(&phydev->lock);
+ if (phydev->drv->probe) {
+ /* Deassert the reset signal */
+ phy_device_reset(phydev, 0);
+
+ err = phydev->drv->probe(phydev);
+ if (err) {
+ /* Assert the reset signal */
+ phy_device_reset(phydev, 1);
+ goto out;
+ }
+ }
+
/* Start out supporting everything. Eventually,
* a controller will attach, and may modify one
* or both of these values
*/
- linkmode_copy(phydev->supported, phydrv->features);
+ if (phydrv->features) {
+ linkmode_copy(phydev->supported, phydrv->features);
+ } else {
+ err = phydrv->get_features(phydev);
+ if (err)
+ goto out;
+ }
+
of_set_phy_supported(phydev);
linkmode_copy(phydev->advertising, phydev->supported);
@@ -2174,20 +2129,8 @@ static int phy_probe(struct device *dev)
* (e.g. hardware erratum) where the driver wants to set only one
* of these bits.
*/
- if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features) ||
- test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydrv->features)) {
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
- phydev->supported);
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
- phydev->supported);
- if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features))
- linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
- phydev->supported);
- if (test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
- phydrv->features))
- linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
- phydev->supported);
- } else {
+ if (!test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported) &&
+ !test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported)) {
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@@ -2197,17 +2140,7 @@ static int phy_probe(struct device *dev)
/* Set the state to READY by default */
phydev->state = PHY_READY;
- if (phydev->drv->probe) {
- /* Deassert the reset signal */
- phy_device_reset(phydev, 0);
-
- err = phydev->drv->probe(phydev);
- if (err) {
- /* Assert the reset signal */
- phy_device_reset(phydev, 1);
- }
- }
-
+out:
mutex_unlock(&phydev->lock);
return err;
@@ -2243,6 +2176,15 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
{
int retval;
+ /* Either the features are hard coded, or dynamically
+ * determine. It cannot be both or neither
+ */
+ if (WARN_ON((!new_driver->features && !new_driver->get_features) ||
+ (new_driver->features && new_driver->get_features))) {
+ pr_err("%s: Driver features are missing\n", new_driver->name);
+ return -EINVAL;
+ }
+
new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY;
new_driver->mdiodrv.driver.name = new_driver->name;
new_driver->mdiodrv.driver.bus = &mdio_bus_type;
@@ -2250,14 +2192,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
new_driver->mdiodrv.driver.remove = phy_remove;
new_driver->mdiodrv.driver.owner = owner;
- /* The following works around an issue where the PHY driver doesn't bind
- * to the device, resulting in the genphy driver being used instead of
- * the dedicated driver. The root cause of the issue isn't known yet
- * and seems to be in the base driver core. Once this is fixed we may
- * remove this workaround.
- */
- new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
-
retval = driver_register(&new_driver->mdiodrv.driver);
if (retval) {
pr_err("%s: Error %d in registering driver\n",
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
index 263385b75bba..b86a4b2116f8 100644
--- a/drivers/net/phy/phy_led_triggers.c
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -1,15 +1,5 @@
-/* Copyright (C) 2016 National Instruments 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.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2016 National Instruments Corp. */
#include <linux/leds.h>
#include <linux/phy.h>
#include <linux/phy_led_triggers.h>
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index e7becc7379d7..89750c7dfd6f 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* phylink models the MAC to optional PHY connection, supporting
* technologies such as SFP cages where the PHY is hot-pluggable.
*
* Copyright (C) 2015 Russell King
- *
- * 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/ethtool.h>
#include <linux/export.h>
@@ -305,6 +302,13 @@ static void phylink_mac_config(struct phylink *pl,
pl->ops->mac_config(pl->netdev, pl->link_an_mode, state);
}
+static void phylink_mac_config_up(struct phylink *pl,
+ const struct phylink_link_state *state)
+{
+ if (state->link)
+ phylink_mac_config(pl, state);
+}
+
static void phylink_mac_an_restart(struct phylink *pl)
{
if (pl->link_config.an_enabled &&
@@ -320,6 +324,10 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *
linkmode_zero(state->lp_advertising);
state->interface = pl->link_config.interface;
state->an_enabled = pl->link_config.an_enabled;
+ state->speed = SPEED_UNKNOWN;
+ state->duplex = DUPLEX_UNKNOWN;
+ state->pause = MLO_PAUSE_NONE;
+ state->an_complete = 0;
state->link = 1;
return pl->ops->mac_link_state(ndev, state);
@@ -404,12 +412,12 @@ static void phylink_resolve(struct work_struct *w)
case MLO_AN_PHY:
link_state = pl->phy_state;
phylink_resolve_flow(pl, &link_state);
- phylink_mac_config(pl, &link_state);
+ phylink_mac_config_up(pl, &link_state);
break;
case MLO_AN_FIXED:
phylink_get_fixed_state(pl, &link_state);
- phylink_mac_config(pl, &link_state);
+ phylink_mac_config_up(pl, &link_state);
break;
case MLO_AN_INBAND:
@@ -474,6 +482,17 @@ static void phylink_run_resolve(struct phylink *pl)
queue_work(system_power_efficient_wq, &pl->resolve);
}
+static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
+{
+ unsigned long state = pl->phylink_disable_state;
+
+ set_bit(bit, &pl->phylink_disable_state);
+ if (state == 0) {
+ queue_work(system_power_efficient_wq, &pl->resolve);
+ flush_work(&pl->resolve);
+ }
+}
+
static void phylink_fixed_poll(struct timer_list *t)
{
struct phylink *pl = container_of(t, struct phylink, link_poll);
@@ -679,9 +698,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported,
__ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising);
- phy_start_machine(phy);
- if (phy->irq > 0)
- phy_start_interrupts(phy);
+ if (phy_interrupt_is_valid(phy))
+ phy_request_interrupt(phy);
return 0;
}
@@ -924,9 +942,7 @@ void phylink_stop(struct phylink *pl)
if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
del_timer_sync(&pl->link_poll);
- set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
- queue_work(system_power_efficient_wq, &pl->resolve);
- flush_work(&pl->resolve);
+ phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
}
EXPORT_SYMBOL_GPL(phylink_stop);
@@ -1269,6 +1285,24 @@ int phylink_get_eee_err(struct phylink *pl)
EXPORT_SYMBOL_GPL(phylink_get_eee_err);
/**
+ * phylink_init_eee() - init and check the EEE features
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @clk_stop_enable: allow PHY to stop receive clock
+ *
+ * Must be called either with RTNL held or within mac_link_up()
+ */
+int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
+{
+ int ret = -EOPNOTSUPP;
+
+ if (pl->phydev)
+ ret = phy_init_eee(pl->phydev, clk_stop_enable);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phylink_init_eee);
+
+/**
* phylink_ethtool_get_eee() - read the energy efficient ethernet parameters
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @eee: a pointer to a &struct ethtool_eee for the read parameters
@@ -1632,9 +1666,7 @@ static void phylink_sfp_link_down(void *upstream)
ASSERT_RTNL();
- set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
- queue_work(system_power_efficient_wq, &pl->resolve);
- flush_work(&pl->resolve);
+ phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
}
static void phylink_sfp_link_up(void *upstream)
@@ -1697,4 +1729,4 @@ void phylink_helper_basex_speed(struct phylink_link_state *state)
}
EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index cfe2313dbefd..5486f6fb2ab2 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/qsemi.c
*
@@ -6,12 +7,6 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, 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/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index c6010fb1aa0f..10df52ccddfe 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/realtek.c
*
@@ -6,12 +7,6 @@
* Author: Johnson Leung <r58129@freescale.com>
*
* Copyright (c) 2004 Freescale Semiconductor, 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/bitops.h>
#include <linux/phy.h>
@@ -278,10 +273,26 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
+ PHY_ID_MATCH_EXACT(0x001cc800),
+ .name = "Generic Realtek PHY",
+ .features = PHY_GBIT_FEATURES,
+ .config_init = genphy_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ }, {
PHY_ID_MATCH_EXACT(0x001cc961),
.name = "RTL8366RB Gigabit Ethernet",
.features = PHY_GBIT_FEATURES,
.config_init = &rtl8366rb_config_init,
+ /* These interrupts are handled by the irq controller
+ * embedded inside the RTL8366RB, they get unmasked when the
+ * irq is requested and ACKed by reading the status register,
+ * which is done by the irqchip code.
+ */
+ .ack_interrupt = genphy_no_ack_interrupt,
+ .config_intr = genphy_no_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
},
diff --git a/drivers/net/phy/rockchip.c b/drivers/net/phy/rockchip.c
index f1da70b9b55f..95abf7072f32 100644
--- a/drivers/net/phy/rockchip.c
+++ b/drivers/net/phy/rockchip.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/**
* drivers/net/phy/rockchip.c
*
@@ -6,12 +7,6 @@
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
*
* David Wu <david.wu@rock-chips.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.
- *
*/
#include <linux/ethtool.h>
@@ -229,4 +224,4 @@ MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
MODULE_AUTHOR("David Wu <david.wu@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip Ethernet PHY driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index ad9db652874d..fef701bfad62 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -347,6 +347,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
return ret;
}
}
+ bus->socket_ops->attach(bus->sfp);
if (bus->started)
bus->socket_ops->start(bus->sfp);
bus->netdev->sfp_bus = bus;
@@ -362,6 +363,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
if (bus->registered) {
if (bus->started)
bus->socket_ops->stop(bus->sfp);
+ bus->socket_ops->detach(bus->sfp);
if (bus->phydev && ops && ops->disconnect_phy)
ops->disconnect_phy(bus->upstream);
}
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index fd8bb998ae52..d4635c2178d1 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
@@ -184,6 +185,7 @@ struct sfp {
struct gpio_desc *gpio[GPIO_MAX];
+ bool attached;
unsigned int state;
struct delayed_work poll;
struct delayed_work timeout;
@@ -1475,7 +1477,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
*/
switch (sfp->sm_mod_state) {
default:
- if (event == SFP_E_INSERT) {
+ if (event == SFP_E_INSERT && sfp->attached) {
sfp_module_tx_disable(sfp);
sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
}
@@ -1607,6 +1609,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
mutex_unlock(&sfp->sm_mutex);
}
+static void sfp_attach(struct sfp *sfp)
+{
+ sfp->attached = true;
+ if (sfp->state & SFP_F_PRESENT)
+ sfp_sm_event(sfp, SFP_E_INSERT);
+}
+
+static void sfp_detach(struct sfp *sfp)
+{
+ sfp->attached = false;
+ sfp_sm_event(sfp, SFP_E_REMOVE);
+}
+
static void sfp_start(struct sfp *sfp)
{
sfp_sm_event(sfp, SFP_E_DEV_UP);
@@ -1667,6 +1682,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
}
static const struct sfp_socket_ops sfp_module_ops = {
+ .attach = sfp_attach,
+ .detach = sfp_detach,
.start = sfp_start,
.stop = sfp_stop,
.module_info = sfp_module_info,
@@ -1834,10 +1851,6 @@ static int sfp_probe(struct platform_device *pdev)
dev_info(sfp->dev, "Host maximum power %u.%uW\n",
sfp->max_power_mW / 1000, (sfp->max_power_mW / 100) % 10);
- sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
- if (!sfp->sfp_bus)
- return -ENOMEM;
-
/* Get the initial state, and always signal TX disable,
* since the network interface will not be up.
*/
@@ -1848,10 +1861,6 @@ static int sfp_probe(struct platform_device *pdev)
sfp->state |= SFP_F_RATE_SELECT;
sfp_set_state(sfp, sfp->state);
sfp_module_tx_disable(sfp);
- rtnl_lock();
- if (sfp->state & SFP_F_PRESENT)
- sfp_sm_event(sfp, SFP_E_INSERT);
- rtnl_unlock();
for (i = 0; i < GPIO_MAX; i++) {
if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
@@ -1884,6 +1893,10 @@ static int sfp_probe(struct platform_device *pdev)
dev_warn(sfp->dev,
"No tx_disable pin: SFP modules will always be emitting.\n");
+ sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+ if (!sfp->sfp_bus)
+ return -ENOMEM;
+
return 0;
}
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 31b0acf337e2..64f54b0bbd8c 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -7,6 +7,8 @@
struct sfp;
struct sfp_socket_ops {
+ void (*attach)(struct sfp *sfp);
+ void (*detach)(struct sfp *sfp);
void (*start)(struct sfp *sfp);
void (*stop)(struct sfp *sfp);
int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index f9477ff55545..c94d3bfbc772 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/smsc.c
*
@@ -7,11 +8,6 @@
*
* Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.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.
- *
* Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
*
*/
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index f17b3441779b..92b64e254b44 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches
*
@@ -5,10 +6,6 @@
*
* This file was based on: drivers/spi/at25.c
* Copyright (C) 2006 David Brownell
- *
- * 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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c
index 33d733684f5b..5b6acf431f98 100644
--- a/drivers/net/phy/ste10Xp.c
+++ b/drivers/net/phy/ste10Xp.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* drivers/net/phy/ste10Xp.c
*
@@ -6,12 +7,6 @@
* Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*
* Copyright (c) 2008 STMicroelectronics Limited
- *
- * 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/module.h>
diff --git a/drivers/net/phy/swphy.c b/drivers/net/phy/swphy.c
index 34f58f2349e9..dad22481d9c1 100644
--- a/drivers/net/phy/swphy.c
+++ b/drivers/net/phy/swphy.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Software PHY emulation
*
@@ -7,11 +8,6 @@
* Anton Vorontsov <avorontsov@ru.mvista.com>
*
* Copyright (c) 2006-2007 MontaVista Software, 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/export.h>
#include <linux/mii.h>
@@ -23,7 +19,6 @@
#define MII_REGS_NUM 29
struct swmii_regs {
- u16 bmcr;
u16 bmsr;
u16 lpa;
u16 lpagb;
@@ -44,16 +39,13 @@ enum {
*/
static const struct swmii_regs speed[] = {
[SWMII_SPEED_10] = {
- .bmcr = BMCR_FULLDPLX,
.lpa = LPA_10FULL | LPA_10HALF,
},
[SWMII_SPEED_100] = {
- .bmcr = BMCR_FULLDPLX | BMCR_SPEED100,
.bmsr = BMSR_100FULL | BMSR_100HALF,
.lpa = LPA_100FULL | LPA_100HALF,
},
[SWMII_SPEED_1000] = {
- .bmcr = BMCR_FULLDPLX | BMCR_SPEED1000,
.bmsr = BMSR_ESTATEN,
.lpagb = LPA_1000FULL | LPA_1000HALF,
},
@@ -61,13 +53,11 @@ static const struct swmii_regs speed[] = {
static const struct swmii_regs duplex[] = {
[SWMII_DUPLEX_HALF] = {
- .bmcr = ~BMCR_FULLDPLX,
.bmsr = BMSR_ESTATEN | BMSR_100HALF,
.lpa = LPA_10HALF | LPA_100HALF,
.lpagb = LPA_1000HALF,
},
[SWMII_DUPLEX_FULL] = {
- .bmcr = ~0,
.bmsr = BMSR_ESTATEN | BMSR_100FULL,
.lpa = LPA_10FULL | LPA_100FULL,
.lpagb = LPA_1000FULL,
@@ -122,7 +112,6 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state)
{
int speed_index, duplex_index;
u16 bmsr = BMSR_ANEGCAPABLE;
- u16 bmcr = 0;
u16 lpagb = 0;
u16 lpa = 0;
@@ -140,7 +129,6 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state)
if (state->link) {
bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
- bmcr |= speed[speed_index].bmcr & duplex[duplex_index].bmcr;
lpa |= speed[speed_index].lpa & duplex[duplex_index].lpa;
lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb;
@@ -153,7 +141,7 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state)
switch (reg) {
case MII_BMCR:
- return bmcr;
+ return BMCR_ANENABLE;
case MII_BMSR:
return bmsr;
case MII_PHYSID1:
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index 22f3bdd8206c..beb054b931ee 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Teranetics PHY
*
* Author: Shaohui Xie <Shaohui.Xie@freescale.com>
*
* Copyright 2015 Freescale Semiconductor, Inc.
- *
- * 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/kernel.h>
@@ -80,9 +77,9 @@ static struct phy_driver teranetics_driver[] = {
.phy_id = PHY_ID_TN2020,
.phy_id_mask = 0xffffffff,
.name = "Teranetics TN2020",
- .soft_reset = gen10g_no_soft_reset,
+ .features = PHY_10GBIT_FEATURES,
+ .soft_reset = genphy_no_soft_reset,
.aneg_done = teranetics_aneg_done,
- .config_init = gen10g_config_init,
.config_aneg = gen10g_config_aneg,
.read_status = teranetics_read_status,
.match_phy_device = teranetics_match_phy_device,
diff --git a/drivers/net/phy/uPD60620.c b/drivers/net/phy/uPD60620.c
index 1e4fc42e4629..219fc7cdc2b3 100644
--- a/drivers/net/phy/uPD60620.c
+++ b/drivers/net/phy/uPD60620.c
@@ -1,13 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for the Renesas PHY uPD60620.
*
* Copyright (C) 2015 Softing Industrial Automation GmbH
- *
- * 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/kernel.h>
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 0646af458f6a..dc0dd87a6694 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for Vitesse PHYs
*
* Author: Kriston Carson
- *
- * Copyright (c) 2005, 2009, 2011 Freescale Semiconductor, 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/kernel.h>
diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 74a8782313cf..2d1449345959 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/* Xilinx GMII2RGMII Converter driver
*
* Copyright (C) 2016 Xilinx, Inc.
@@ -8,16 +9,6 @@
*
* Description:
* This driver is developed for Xilinx GMII2RGMII Converter
- *
- * 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 <linux/kernel.h>
@@ -44,7 +35,10 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
u16 val = 0;
int err;
- err = priv->phy_drv->read_status(phydev);
+ if (priv->phy_drv->read_status)
+ err = priv->phy_drv->read_status(phydev);
+ else
+ err = genphy_read_status(phydev);
if (err < 0)
return err;
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 62dc564b251d..f22639f0116a 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
if (pskb_trim_rcsum(skb, len))
goto drop;
+ ph = pppoe_hdr(skb);
pn = pppoe_pernet(dev_net(dev));
/* Note that get_item does a sock_hold(), so sk_pppox(po)
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 7820fced33f6..941cfa8f1c2a 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -535,17 +535,20 @@ sb1000_activate(const int ioaddr[], const char* name)
int status;
ssleep(1);
- if ((status = card_send_command(ioaddr, name, Command0, st)))
+ status = card_send_command(ioaddr, name, Command0, st);
+ if (status)
return status;
- if ((status = card_send_command(ioaddr, name, Command1, st)))
+ status = card_send_command(ioaddr, name, Command1, st);
+ if (status)
return status;
if (st[3] != 0xf1) {
- if ((status = sb1000_start_get_set_command(ioaddr, name)))
+ status = sb1000_start_get_set_command(ioaddr, name);
+ if (status)
return status;
return -EIO;
}
udelay(1000);
- return sb1000_start_get_set_command(ioaddr, name);
+ return sb1000_start_get_set_command(ioaddr, name);
}
/* get SB1000 firmware version */
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index c0b52e48f0e6..2ea9b4976f4a 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -712,7 +712,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
goto err_kfree;
}
- skb_probe_transport_header(skb, ETH_HLEN);
+ skb_probe_transport_header(skb);
/* Move network header to the right position for VLAN tagged packets */
if ((skb->protocol == htons(ETH_P_8021Q) ||
@@ -1187,7 +1187,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
tap = rcu_dereference(q->tap);
if (tap) {
skb->dev = tap->dev;
- skb_probe_transport_header(skb, ETH_HLEN);
+ skb_probe_transport_header(skb);
dev_queue_xmit(skb);
} else {
kfree_skb(skb);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index afd9d25d1992..6ed96fdfd96d 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -28,7 +28,6 @@
#include <net/genetlink.h>
#include <net/netlink.h>
#include <net/sch_generic.h>
-#include <net/switchdev.h>
#include <generated/utsrelease.h>
#include <linux/if_team.h>
@@ -256,17 +255,6 @@ static void __team_option_inst_mark_removed_port(struct team *team,
}
}
-static bool __team_option_inst_tmp_find(const struct list_head *opts,
- const struct team_option_inst *needle)
-{
- struct team_option_inst *opt_inst;
-
- list_for_each_entry(opt_inst, opts, tmp_list)
- if (opt_inst == needle)
- return true;
- return false;
-}
-
static int __team_options_register(struct team *team,
const struct team_option *option,
size_t option_count)
@@ -1267,7 +1255,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
list_add_tail_rcu(&port->list, &team->port_list);
team_port_enable(team, port);
__team_compute_features(team);
- __team_port_change_port_added(port, !!netif_carrier_ok(port_dev));
+ __team_port_change_port_added(port, !!netif_oper_up(port_dev));
__team_options_change_check(team);
netdev_info(dev, "Port device %s added\n", portname);
@@ -2460,7 +2448,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
int err = 0;
int i;
struct nlattr *nl_option;
- LIST_HEAD(opt_inst_list);
rtnl_lock();
@@ -2480,6 +2467,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
struct nlattr *attr;
struct nlattr *attr_data;
+ LIST_HEAD(opt_inst_list);
enum team_option_type opt_type;
int opt_port_ifindex = 0; /* != 0 for per-port options */
u32 opt_array_index = 0;
@@ -2584,23 +2572,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
if (err)
goto team_put;
opt_inst->changed = true;
-
- /* dumb/evil user-space can send us duplicate opt,
- * keep only the last one
- */
- if (__team_option_inst_tmp_find(&opt_inst_list,
- opt_inst))
- continue;
-
list_add(&opt_inst->tmp_list, &opt_inst_list);
}
if (!opt_found) {
err = -ENOENT;
goto team_put;
}
- }
- err = team_nl_send_event_options_get(team, &opt_inst_list);
+ err = team_nl_send_event_options_get(team, &opt_inst_list);
+ if (err)
+ break;
+ }
team_put:
team_nl_team_put(team);
@@ -2932,7 +2914,7 @@ static int team_device_event(struct notifier_block *unused,
switch (event) {
case NETDEV_UP:
- if (netif_carrier_ok(dev))
+ if (netif_oper_up(dev))
team_port_change_check(port, true);
break;
case NETDEV_DOWN:
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index a5ef97010eb3..5541e1c19936 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -325,6 +325,20 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
return 0;
}
+static void lb_bpf_func_free(struct team *team)
+{
+ struct lb_priv *lb_priv = get_lb_priv(team);
+ struct bpf_prog *fp;
+
+ if (!lb_priv->ex->orig_fprog)
+ return;
+
+ __fprog_destroy(lb_priv->ex->orig_fprog);
+ fp = rcu_dereference_protected(lb_priv->fp,
+ lockdep_is_held(&team->lock));
+ bpf_prog_destroy(fp);
+}
+
static int lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx)
{
struct lb_priv *lb_priv = get_lb_priv(team);
@@ -639,6 +653,7 @@ static void lb_exit(struct team *team)
team_options_unregister(team, lb_options,
ARRAY_SIZE(lb_options));
+ lb_bpf_func_free(team);
cancel_delayed_work_sync(&lb_priv->ex->stats.refresh_dw);
free_percpu(lb_priv->pcpu_stats);
kfree(lb_priv->ex);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a4fdad475594..1d68921723dc 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
err = 0;
}
- rcu_assign_pointer(tfile->tun, tun);
- rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
- tun->numqueues++;
-
if (tfile->detached) {
tun_enable_queue(tfile);
} else {
@@ -870,12 +866,18 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
if (rtnl_dereference(tun->xdp_prog))
sock_set_flag(&tfile->sk, SOCK_XDP);
- tun_set_real_num_queues(tun);
-
/* device is allowed to go away first, so no need to hold extra
* refcnt.
*/
+ /* Publish tfile->tun and tun->tfiles only after we've fully
+ * initialized tfile; otherwise we risk using half-initialized
+ * object.
+ */
+ rcu_assign_pointer(tfile->tun, tun);
+ rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+ tun->numqueues++;
+ tun_set_real_num_queues(tun);
out:
return err;
}
@@ -1927,7 +1929,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
}
skb_reset_network_header(skb);
- skb_probe_transport_header(skb, 0);
+ skb_probe_transport_header(skb);
if (skb_xdp) {
struct bpf_prog *xdp_prog;
@@ -2165,9 +2167,9 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
}
add_wait_queue(&tfile->wq.wait, &wait);
- current->state = TASK_INTERRUPTIBLE;
while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
ptr = ptr_ring_consume(&tfile->tx_ring);
if (ptr)
break;
@@ -2183,7 +2185,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
schedule();
}
- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&tfile->wq.wait, &wait);
out:
@@ -2480,7 +2482,7 @@ build:
skb->protocol = eth_type_trans(skb, tun->dev);
skb_reset_network_header(skb);
- skb_probe_transport_header(skb, 0);
+ skb_probe_transport_header(skb);
if (skb_xdp) {
err = do_xdp_generic(xdp_prog, skb);
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 57f1c94fca0b..820a2fe7d027 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -1287,6 +1287,20 @@ static const struct driver_info asix112_info = {
#undef ASIX112_DESC
+static const struct driver_info trendnet_info = {
+ .description = "USB-C 3.1 to 5GBASE-T Ethernet Adapter",
+ .bind = aqc111_bind,
+ .unbind = aqc111_unbind,
+ .status = aqc111_status,
+ .link_reset = aqc111_link_reset,
+ .reset = aqc111_reset,
+ .stop = aqc111_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX |
+ FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+ .rx_fixup = aqc111_rx_fixup,
+ .tx_fixup = aqc111_tx_fixup,
+};
+
static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -1440,6 +1454,7 @@ static const struct usb_device_id products[] = {
{AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
{AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)},
{AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)},
+ {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)},
{ },/* END */
};
MODULE_DEVICE_TABLE(usb, products);
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index b654f05b2ccd..3d93993e74da 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -739,8 +739,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
chipcode &= AX_CHIPCODE_MASK;
- (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
- ax88772a_hw_reset(dev, 0);
+ ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+ ax88772a_hw_reset(dev, 0);
+
+ if (ret < 0) {
+ netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret);
+ return ret;
+ }
/* Read PHYID register *AFTER* the PHY was reset properly */
phyid = asix_get_phyid(dev);
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 78b16eb9e58c..63aaae487995 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -361,8 +361,8 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i
else
return -EINVAL;
- dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
- ifname, NET_NAME_UNKNOWN, usbpn_setup);
+ dev = alloc_netdev(struct_size(pnd, urbs, rxq_size), ifname,
+ NET_NAME_UNKNOWN, usbpn_setup);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index b3b3c05903a1..5512a1038721 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -179,10 +179,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
* probed with) and a slave/data interface; union
* descriptors sort this all out.
*/
- info->control = usb_ifnum_to_if(dev->udev,
- info->u->bMasterInterface0);
- info->data = usb_ifnum_to_if(dev->udev,
- info->u->bSlaveInterface0);
+ info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
+ info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
if (!info->control || !info->data) {
dev_dbg(&intf->dev,
"master #%u/%p slave #%u/%p\n",
@@ -216,18 +214,16 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
/* a data interface altsetting does the real i/o */
d = &info->data->cur_altsetting->desc;
if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
- dev_dbg(&intf->dev, "slave class %u\n",
- d->bInterfaceClass);
+ dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass);
goto bad_desc;
}
skip:
- if ( rndis &&
- header.usb_cdc_acm_descriptor &&
- header.usb_cdc_acm_descriptor->bmCapabilities) {
- dev_dbg(&intf->dev,
- "ACM capabilities %02x, not really RNDIS?\n",
- header.usb_cdc_acm_descriptor->bmCapabilities);
- goto bad_desc;
+ if (rndis && header.usb_cdc_acm_descriptor &&
+ header.usb_cdc_acm_descriptor->bmCapabilities) {
+ dev_dbg(&intf->dev,
+ "ACM capabilities %02x, not really RNDIS?\n",
+ header.usb_cdc_acm_descriptor->bmCapabilities);
+ goto bad_desc;
}
if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
@@ -238,7 +234,7 @@ skip:
}
if (header.usb_cdc_mdlm_desc &&
- memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+ memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
dev_dbg(&intf->dev, "GUID doesn't match\n");
goto bad_desc;
}
@@ -302,7 +298,7 @@ skip:
if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
struct usb_endpoint_descriptor *desc;
- dev->status = &info->control->cur_altsetting->endpoint [0];
+ dev->status = &info->control->cur_altsetting->endpoint[0];
desc = &dev->status->desc;
if (!usb_endpoint_is_int_in(desc) ||
(le16_to_cpu(desc->wMaxPacketSize)
@@ -847,6 +843,14 @@ static const struct usb_device_id products[] = {
.driver_info = 0,
},
+/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/* WHITELIST!!!
*
* CDC Ether uses two interfaces, not necessarily consecutive.
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index e96bc0c6140f..3d92ea6fcc02 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2051,8 +2051,7 @@ static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev)
phydev = phy_find_first(dev->mdiobus);
if (!phydev) {
netdev_dbg(dev->net, "PHY Not Found!! Registering Fixed PHY\n");
- phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1,
- NULL);
+ phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
if (IS_ERR(phydev)) {
netdev_err(dev->net, "No PHY/fixed_PHY found\n");
return NULL;
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index f4247b275e09..63e44e746ccc 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1011,6 +1011,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
switch (cmd) {
case SIOCDEVPRIVATE:
data[0] = pegasus->phy;
+ /* fall through */
case SIOCDEVPRIVATE + 1:
read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]);
res = 0;
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 774e1ff01c9a..74bebbdb4b15 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -123,6 +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->mtu = 1500;
dev->needs_free_netdev = true;
}
@@ -975,6 +976,13 @@ static const struct usb_device_id products[] = {
0xff),
.driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr,
},
+ { /* Quectel EG12/EM12 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0512,
+ USB_CLASS_VENDOR_SPEC,
+ USB_SUBCLASS_VENDOR_SPEC,
+ 0xff),
+ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr,
+ },
/* 3. Combined interface devices matching on interface number */
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
@@ -1200,8 +1208,8 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */
{QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
{QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */
- {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC7304/MC7354 */
- {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC7304/MC7354 */
+ {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC7304/MC7354, WP76xx */
+ {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 10)},/* Sierra Wireless MC7304/MC7354 */
{QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */
{QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */
{QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */
@@ -1342,17 +1350,20 @@ static bool quectel_ec20_detected(struct usb_interface *intf)
return false;
}
-static bool quectel_ep06_diag_detected(struct usb_interface *intf)
+static bool quectel_diag_detected(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_interface_descriptor intf_desc = intf->cur_altsetting->desc;
+ u16 id_vendor = le16_to_cpu(dev->descriptor.idVendor);
+ u16 id_product = le16_to_cpu(dev->descriptor.idProduct);
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x2c7c &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x0306 &&
- intf_desc.bNumEndpoints == 2)
- return true;
+ if (id_vendor != 0x2c7c || intf_desc.bNumEndpoints != 2)
+ return false;
- return false;
+ if (id_product == 0x0306 || id_product == 0x0512)
+ return true;
+ else
+ return false;
}
static int qmi_wwan_probe(struct usb_interface *intf,
@@ -1389,13 +1400,13 @@ static int qmi_wwan_probe(struct usb_interface *intf,
return -ENODEV;
}
- /* Quectel EP06/EM06/EG06 supports dynamic interface configuration, so
+ /* Several Quectel modems supports dynamic interface configuration, so
* we need to match on class/subclass/protocol. These values are
* identical for the diagnostic- and QMI-interface, but bNumEndpoints is
* different. Ignore the current interface if the number of endpoints
* the number for the diag interface (two).
*/
- if (quectel_ep06_diag_detected(intf))
+ if (quectel_diag_detected(intf))
return -ENODEV;
return usbnet_probe(intf, id);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 60dd1ec1665f..86c8c64fbb0f 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -557,6 +557,7 @@ enum spd_duplex {
/* MAC PASSTHRU */
#define AD_MASK 0xfee0
#define BND_MASK 0x0004
+#define BD_MASK 0x0001
#define EFUSE 0xcfdb
#define PASS_THRU_MASK 0x1
@@ -1176,9 +1177,9 @@ static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa)
return -ENODEV;
}
} else {
- /* test for RTL8153-BND */
+ /* test for RTL8153-BND and RTL8153-BD */
ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
- if ((ocp_data & BND_MASK) == 0) {
+ if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) {
netif_dbg(tp, probe, tp->netdev,
"Invalid variant for MAC pass through\n");
return -ENODEV;
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 80373a9171dd..59dbdbb5feff 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -388,7 +388,6 @@ static void read_bulk_callback(struct urb *urb)
unsigned pkt_len, res;
struct sk_buff *skb;
struct net_device *netdev;
- u16 rx_stat;
int status = urb->status;
int result;
unsigned long flags;
@@ -424,7 +423,6 @@ static void read_bulk_callback(struct urb *urb)
goto goon;
res = urb->actual_length;
- rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));
pkt_len = res - 4;
skb_put(dev->rx_skb, pkt_len);
@@ -849,6 +847,7 @@ static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
switch (cmd) {
case SIOCDEVPRIVATE:
data[0] = dev->phy;
+ /* fall through */
case SIOCDEVPRIVATE + 1:
read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);
break;
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
index 6ac232e52bf7..e04c8054c2cf 100644
--- a/drivers/net/usb/sr9700.c
+++ b/drivers/net/usb/sr9700.c
@@ -434,7 +434,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
usbnet_skb_return(dev, sr_skb);
skb_pull(skb, len + SR_RX_OVERHEAD);
- };
+ }
return 0;
}
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index f412ea1cef18..569e87a51a33 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -115,7 +115,8 @@ static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
p += sizeof(ethtool_stats_keys);
for (i = 0; i < dev->real_num_rx_queues; i++) {
for (j = 0; j < VETH_RQ_STATS_LEN; j++) {
- snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s",
+ snprintf(p, ETH_GSTRING_LEN,
+ "rx_queue_%u_%.11s",
i, veth_rq_stats_desc[j].desc);
p += ETH_GSTRING_LEN;
}
@@ -540,8 +541,10 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq,
goto xdp_xmit;
default:
bpf_warn_invalid_xdp_action(act);
+ /* fall through */
case XDP_ABORTED:
trace_xdp_exception(rq->dev, xdp_prog, act);
+ /* fall through */
case XDP_DROP:
goto err_xdp;
}
@@ -661,8 +664,10 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq, struct sk_buff *skb,
goto xdp_xmit;
default:
bpf_warn_invalid_xdp_action(act);
+ /* fall through */
case XDP_ABORTED:
trace_xdp_exception(rq->dev, xdp_prog, act);
+ /* fall through */
case XDP_DROP:
goto drop;
}
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 023725086046..7eb38ea9ba56 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644);
#define VIRTIO_XDP_TX BIT(0)
#define VIRTIO_XDP_REDIR BIT(1)
+#define VIRTIO_XDP_FLAG BIT(0)
+
/* RX packet size EWMA. The average packet size is used to determine the packet
* buffer size when refilling RX rings. As the entire RX ring may be refilled
* at once, the weight is chosen so that the EWMA will be insensitive to short-
@@ -252,6 +254,21 @@ struct padded_vnet_hdr {
char padding[4];
};
+static bool is_xdp_frame(void *ptr)
+{
+ return (unsigned long)ptr & VIRTIO_XDP_FLAG;
+}
+
+static void *xdp_to_ptr(struct xdp_frame *ptr)
+{
+ return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
+}
+
+static struct xdp_frame *ptr_to_xdp(void *ptr)
+{
+ return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
+}
+
/* Converting between virtqueue no. and kernel tx/rx queue no.
* 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
*/
@@ -462,7 +479,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
sg_init_one(sq->sg, xdpf->data, xdpf->len);
- err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC);
+ err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf),
+ GFP_ATOMIC);
if (unlikely(err))
return -ENOSPC; /* Caller handle free/refcnt */
@@ -482,36 +500,47 @@ static int virtnet_xdp_xmit(struct net_device *dev,
{
struct virtnet_info *vi = netdev_priv(dev);
struct receive_queue *rq = vi->rq;
- struct xdp_frame *xdpf_sent;
struct bpf_prog *xdp_prog;
struct send_queue *sq;
unsigned int len;
+ int packets = 0;
+ int bytes = 0;
int drops = 0;
int kicks = 0;
int ret, err;
+ void *ptr;
int i;
- sq = virtnet_xdp_sq(vi);
-
- if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
- ret = -EINVAL;
- drops = n;
- goto out;
- }
-
/* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
* indicate XDP resources have been successfully allocated.
*/
xdp_prog = rcu_dereference(rq->xdp_prog);
- if (!xdp_prog) {
- ret = -ENXIO;
+ if (!xdp_prog)
+ return -ENXIO;
+
+ sq = virtnet_xdp_sq(vi);
+
+ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
+ ret = -EINVAL;
drops = n;
goto out;
}
/* Free up any pending old buffers before queueing new ones. */
- while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
- xdp_return_frame(xdpf_sent);
+ while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+ if (likely(is_xdp_frame(ptr))) {
+ struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+ bytes += frame->len;
+ xdp_return_frame(frame);
+ } else {
+ struct sk_buff *skb = ptr;
+
+ bytes += skb->len;
+ napi_consume_skb(skb, false);
+ }
+ packets++;
+ }
for (i = 0; i < n; i++) {
struct xdp_frame *xdpf = frames[i];
@@ -530,6 +559,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
}
out:
u64_stats_update_begin(&sq->stats.syncp);
+ sq->stats.bytes += bytes;
+ sq->stats.packets += packets;
sq->stats.xdp_tx += n;
sq->stats.xdp_tx_drops += drops;
sq->stats.kicks += kicks;
@@ -1035,6 +1066,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
goto frame_err;
}
+ skb_record_rx_queue(skb, vq2rxq(rq->vq));
skb->protocol = eth_type_trans(skb, dev);
pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
ntohs(skb->protocol), skb->len, skb->pkt_type);
@@ -1330,20 +1362,28 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
return stats.packets;
}
-static void free_old_xmit_skbs(struct send_queue *sq)
+static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
{
- struct sk_buff *skb;
unsigned int len;
unsigned int packets = 0;
unsigned int bytes = 0;
+ void *ptr;
- while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
- pr_debug("Sent skb %p\n", skb);
+ while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+ if (likely(!is_xdp_frame(ptr))) {
+ struct sk_buff *skb = ptr;
- bytes += skb->len;
- packets++;
+ pr_debug("Sent skb %p\n", skb);
+
+ bytes += skb->len;
+ napi_consume_skb(skb, in_napi);
+ } else {
+ struct xdp_frame *frame = ptr_to_xdp(ptr);
- dev_consume_skb_any(skb);
+ bytes += frame->len;
+ xdp_return_frame(frame);
+ }
+ packets++;
}
/* Avoid overhead when no packets have been processed
@@ -1358,6 +1398,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
u64_stats_update_end(&sq->stats.syncp);
}
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+ if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+ return false;
+ else if (q < vi->curr_queue_pairs)
+ return true;
+ else
+ return false;
+}
+
static void virtnet_poll_cleantx(struct receive_queue *rq)
{
struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1365,11 +1415,11 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
struct send_queue *sq = &vi->sq[index];
struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
- if (!sq->napi.weight)
+ if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
return;
if (__netif_tx_trylock(txq)) {
- free_old_xmit_skbs(sq);
+ free_old_xmit_skbs(sq, true);
__netif_tx_unlock(txq);
}
@@ -1442,10 +1492,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
{
struct send_queue *sq = container_of(napi, struct send_queue, napi);
struct virtnet_info *vi = sq->vq->vdev->priv;
- struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+ unsigned int index = vq2txq(sq->vq);
+ struct netdev_queue *txq;
+ if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
+ /* We don't need to enable cb for XDP */
+ napi_complete_done(napi, 0);
+ return 0;
+ }
+
+ txq = netdev_get_tx_queue(vi->dev, index);
__netif_tx_lock(txq, raw_smp_processor_id());
- free_old_xmit_skbs(sq);
+ free_old_xmit_skbs(sq, true);
__netif_tx_unlock(txq);
virtqueue_napi_complete(napi, sq->vq, 0);
@@ -1514,7 +1572,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
bool use_napi = sq->napi.weight;
/* Free up any pending old buffers before queueing new ones. */
- free_old_xmit_skbs(sq);
+ free_old_xmit_skbs(sq, false);
if (use_napi && kick)
virtqueue_enable_cb_delayed(sq->vq);
@@ -1557,7 +1615,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!use_napi &&
unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
/* More just got used, free them then recheck. */
- free_old_xmit_skbs(sq);
+ free_old_xmit_skbs(sq, false);
if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
netif_start_subqueue(dev, qnum);
virtqueue_disable_cb(sq->vq);
@@ -2395,6 +2453,10 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
return -ENOMEM;
}
+ old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
+ if (!prog && !old_prog)
+ return 0;
+
if (prog) {
prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
if (IS_ERR(prog))
@@ -2402,36 +2464,62 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
}
/* Make sure NAPI is not using any XDP TX queues for RX. */
- if (netif_running(dev))
- for (i = 0; i < vi->max_queue_pairs; i++)
+ if (netif_running(dev)) {
+ for (i = 0; i < vi->max_queue_pairs; i++) {
napi_disable(&vi->rq[i].napi);
+ virtnet_napi_tx_disable(&vi->sq[i].napi);
+ }
+ }
+
+ if (!prog) {
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+ if (i == 0)
+ virtnet_restore_guest_offloads(vi);
+ }
+ synchronize_net();
+ }
- netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
if (err)
goto err;
+ netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
vi->xdp_queue_pairs = xdp_qp;
- for (i = 0; i < vi->max_queue_pairs; i++) {
- old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
- rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
- if (i == 0) {
- if (!old_prog)
+ if (prog) {
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+ if (i == 0 && !old_prog)
virtnet_clear_guest_offloads(vi);
- if (!prog)
- virtnet_restore_guest_offloads(vi);
}
+ }
+
+ for (i = 0; i < vi->max_queue_pairs; i++) {
if (old_prog)
bpf_prog_put(old_prog);
- if (netif_running(dev))
+ if (netif_running(dev)) {
virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+ virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+ &vi->sq[i].napi);
+ }
}
return 0;
err:
- for (i = 0; i < vi->max_queue_pairs; i++)
- virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+ if (!prog) {
+ virtnet_clear_guest_offloads(vi);
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
+ }
+
+ if (netif_running(dev)) {
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+ virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+ &vi->sq[i].napi);
+ }
+ }
if (prog)
bpf_prog_sub(prog, vi->max_queue_pairs - 1);
return err;
@@ -2613,16 +2701,6 @@ static void free_receive_page_frags(struct virtnet_info *vi)
put_page(vi->rq[i].alloc_frag.page);
}
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
- if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
- return false;
- else if (q < vi->curr_queue_pairs)
- return true;
- else
- return false;
-}
-
static void free_unused_bufs(struct virtnet_info *vi)
{
void *buf;
@@ -2631,10 +2709,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
for (i = 0; i < vi->max_queue_pairs; i++) {
struct virtqueue *vq = vi->sq[i].vq;
while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
- if (!is_xdp_raw_buffer_queue(vi, i))
+ if (!is_xdp_frame(buf))
dev_kfree_skb(buf);
else
- put_page(virt_to_head_page(buf));
+ xdp_return_frame(ptr_to_xdp(buf));
}
}
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index e454dfc9ad8f..89984fcab01e 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -535,8 +535,8 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq,
}
sz = tq->tx_ring.size * sizeof(tq->buf_info[0]);
- tq->buf_info = dma_zalloc_coherent(&adapter->pdev->dev, sz,
- &tq->buf_info_pa, GFP_KERNEL);
+ tq->buf_info = dma_alloc_coherent(&adapter->pdev->dev, sz,
+ &tq->buf_info_pa, GFP_KERNEL);
if (!tq->buf_info)
goto err;
@@ -1815,8 +1815,8 @@ vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter)
sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size +
rq->rx_ring[1].size);
- bi = dma_zalloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
- GFP_KERNEL);
+ bi = dma_alloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
+ GFP_KERNEL);
if (!bi)
goto err;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 95909e262ba4..7c1430ed0244 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1273,6 +1273,9 @@ static void vrf_setup(struct net_device *dev)
/* default to no qdisc; user can add if desired */
dev->priv_flags |= IFF_NO_QUEUE;
+
+ dev->min_mtu = 0;
+ dev->max_mtu = 0;
}
static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 5209ee9aac47..a3c46d78d216 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -361,10 +361,11 @@ errout:
static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan,
const struct vxlan_fdb *fdb,
const struct vxlan_rdst *rd,
+ struct netlink_ext_ack *extack,
struct switchdev_notifier_vxlan_fdb_info *fdb_info)
{
fdb_info->info.dev = vxlan->dev;
- fdb_info->info.extack = NULL;
+ fdb_info->info.extack = extack;
fdb_info->remote_ip = rd->remote_ip;
fdb_info->remote_port = rd->remote_port;
fdb_info->remote_vni = rd->remote_vni;
@@ -375,41 +376,50 @@ static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan,
fdb_info->added_by_user = fdb->flags & NTF_VXLAN_ADDED_BY_USER;
}
-static void vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan,
- struct vxlan_fdb *fdb,
- struct vxlan_rdst *rd,
- bool adding)
+static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan,
+ struct vxlan_fdb *fdb,
+ struct vxlan_rdst *rd,
+ bool adding,
+ struct netlink_ext_ack *extack)
{
struct switchdev_notifier_vxlan_fdb_info info;
enum switchdev_notifier_type notifier_type;
+ int ret;
if (WARN_ON(!rd))
- return;
+ return 0;
notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE
: SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE;
- vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, &info);
- call_switchdev_notifiers(notifier_type, vxlan->dev,
- &info.info);
+ vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, NULL, &info);
+ ret = call_switchdev_notifiers(notifier_type, vxlan->dev,
+ &info.info, extack);
+ return notifier_to_errno(ret);
}
-static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
- struct vxlan_rdst *rd, int type, bool swdev_notify)
+static int vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
+ struct vxlan_rdst *rd, int type, bool swdev_notify,
+ struct netlink_ext_ack *extack)
{
+ int err;
+
if (swdev_notify) {
switch (type) {
case RTM_NEWNEIGH:
- vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd,
- true);
+ err = vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd,
+ true, extack);
+ if (err)
+ return err;
break;
case RTM_DELNEIGH:
vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd,
- false);
+ false, extack);
break;
}
}
__vxlan_fdb_notify(vxlan, fdb, rd, type);
+ return 0;
}
static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
@@ -423,7 +433,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
.remote_vni = cpu_to_be32(VXLAN_N_VID),
};
- vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true);
+ vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL);
}
static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
@@ -435,7 +445,7 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
memcpy(f.eth_addr, eth_addr, ETH_ALEN);
- vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true);
+ vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL);
}
/* Hash Ethernet address */
@@ -545,7 +555,7 @@ int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
}
rdst = first_remote_rcu(f);
- vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, fdb_info);
+ vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, NULL, fdb_info);
out:
rcu_read_unlock();
@@ -556,19 +566,21 @@ EXPORT_SYMBOL_GPL(vxlan_fdb_find_uc);
static int vxlan_fdb_notify_one(struct notifier_block *nb,
const struct vxlan_dev *vxlan,
const struct vxlan_fdb *f,
- const struct vxlan_rdst *rdst)
+ const struct vxlan_rdst *rdst,
+ struct netlink_ext_ack *extack)
{
struct switchdev_notifier_vxlan_fdb_info fdb_info;
int rc;
- vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, &fdb_info);
+ vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, extack, &fdb_info);
rc = nb->notifier_call(nb, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
&fdb_info);
return notifier_to_errno(rc);
}
int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
- struct notifier_block *nb)
+ struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan;
struct vxlan_rdst *rdst;
@@ -586,7 +598,8 @@ int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
if (f->vni == vni) {
list_for_each_entry(rdst, &f->remotes, list) {
rc = vxlan_fdb_notify_one(nb, vxlan,
- f, rdst);
+ f, rdst,
+ extack);
if (rc)
goto out;
}
@@ -625,7 +638,7 @@ EXPORT_SYMBOL_GPL(vxlan_fdb_clear_offload);
/* Replace destination of unicast mac */
static int vxlan_fdb_replace(struct vxlan_fdb *f,
union vxlan_addr *ip, __be16 port, __be32 vni,
- __u32 ifindex)
+ __u32 ifindex, struct vxlan_rdst *oldrd)
{
struct vxlan_rdst *rd;
@@ -637,6 +650,7 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
if (!rd)
return 0;
+ *oldrd = *rd;
dst_cache_reset(&rd->dst_cache);
rd->remote_ip = *ip;
rd->remote_port = port;
@@ -826,92 +840,6 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
return 0;
}
-/* Add new entry to forwarding table -- assumes lock held */
-static int vxlan_fdb_update(struct vxlan_dev *vxlan,
- const u8 *mac, union vxlan_addr *ip,
- __u16 state, __u16 flags,
- __be16 port, __be32 src_vni, __be32 vni,
- __u32 ifindex, __u16 ndm_flags,
- bool swdev_notify)
-{
- __u16 fdb_flags = (ndm_flags & ~NTF_USE);
- struct vxlan_rdst *rd = NULL;
- struct vxlan_fdb *f;
- int notify = 0;
- int rc;
-
- f = __vxlan_find_mac(vxlan, mac, src_vni);
- if (f) {
- if (flags & NLM_F_EXCL) {
- netdev_dbg(vxlan->dev,
- "lost race to create %pM\n", mac);
- return -EEXIST;
- }
-
- /* Do not allow an externally learned entry to take over an
- * entry added by the user.
- */
- if (!(fdb_flags & NTF_EXT_LEARNED) ||
- !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
- if (f->state != state) {
- f->state = state;
- f->updated = jiffies;
- notify = 1;
- }
- if (f->flags != fdb_flags) {
- f->flags = fdb_flags;
- f->updated = jiffies;
- notify = 1;
- }
- }
-
- if ((flags & NLM_F_REPLACE)) {
- /* Only change unicasts */
- if (!(is_multicast_ether_addr(f->eth_addr) ||
- is_zero_ether_addr(f->eth_addr))) {
- notify |= vxlan_fdb_replace(f, ip, port, vni,
- ifindex);
- } else
- return -EOPNOTSUPP;
- }
- if ((flags & NLM_F_APPEND) &&
- (is_multicast_ether_addr(f->eth_addr) ||
- is_zero_ether_addr(f->eth_addr))) {
- rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
-
- if (rc < 0)
- return rc;
- notify |= rc;
- }
-
- if (ndm_flags & NTF_USE)
- f->used = jiffies;
- } else {
- if (!(flags & NLM_F_CREATE))
- return -ENOENT;
-
- /* Disallow replace to add a multicast entry */
- if ((flags & NLM_F_REPLACE) &&
- (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
- return -EOPNOTSUPP;
-
- netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
- rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
- vni, ifindex, fdb_flags, &f);
- if (rc < 0)
- return rc;
- notify = 1;
- }
-
- if (notify) {
- if (rd == NULL)
- rd = first_remote_rtnl(f);
- vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, swdev_notify);
- }
-
- return 0;
-}
-
static void vxlan_fdb_free(struct rcu_head *head)
{
struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu);
@@ -929,14 +857,13 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
{
struct vxlan_rdst *rd;
- netdev_dbg(vxlan->dev,
- "delete %pM\n", f->eth_addr);
+ netdev_dbg(vxlan->dev, "delete %pM\n", f->eth_addr);
--vxlan->addrcnt;
if (do_notify)
list_for_each_entry(rd, &f->remotes, list)
vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH,
- swdev_notify);
+ swdev_notify, NULL);
hlist_del_rcu(&f->hlist);
call_rcu(&f->rcu, vxlan_fdb_free);
@@ -950,11 +877,157 @@ static void vxlan_dst_free(struct rcu_head *head)
kfree(rd);
}
+static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
+ union vxlan_addr *ip,
+ __u16 state, __u16 flags,
+ __be16 port, __be32 vni,
+ __u32 ifindex, __u16 ndm_flags,
+ struct vxlan_fdb *f,
+ bool swdev_notify,
+ struct netlink_ext_ack *extack)
+{
+ __u16 fdb_flags = (ndm_flags & ~NTF_USE);
+ struct vxlan_rdst *rd = NULL;
+ struct vxlan_rdst oldrd;
+ int notify = 0;
+ int rc = 0;
+ int err;
+
+ /* Do not allow an externally learned entry to take over an entry added
+ * by the user.
+ */
+ if (!(fdb_flags & NTF_EXT_LEARNED) ||
+ !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
+ if (f->state != state) {
+ f->state = state;
+ f->updated = jiffies;
+ notify = 1;
+ }
+ if (f->flags != fdb_flags) {
+ f->flags = fdb_flags;
+ f->updated = jiffies;
+ notify = 1;
+ }
+ }
+
+ if ((flags & NLM_F_REPLACE)) {
+ /* Only change unicasts */
+ if (!(is_multicast_ether_addr(f->eth_addr) ||
+ is_zero_ether_addr(f->eth_addr))) {
+ rc = vxlan_fdb_replace(f, ip, port, vni,
+ ifindex, &oldrd);
+ notify |= rc;
+ } else {
+ return -EOPNOTSUPP;
+ }
+ }
+ if ((flags & NLM_F_APPEND) &&
+ (is_multicast_ether_addr(f->eth_addr) ||
+ is_zero_ether_addr(f->eth_addr))) {
+ rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
+
+ if (rc < 0)
+ return rc;
+ notify |= rc;
+ }
+
+ if (ndm_flags & NTF_USE)
+ f->used = jiffies;
+
+ if (notify) {
+ if (rd == NULL)
+ rd = first_remote_rtnl(f);
+
+ err = vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH,
+ swdev_notify, extack);
+ if (err)
+ goto err_notify;
+ }
+
+ return 0;
+
+err_notify:
+ if ((flags & NLM_F_REPLACE) && rc)
+ *rd = oldrd;
+ else if ((flags & NLM_F_APPEND) && rc) {
+ list_del_rcu(&rd->list);
+ call_rcu(&rd->rcu, vxlan_dst_free);
+ }
+ return err;
+}
+
+static int vxlan_fdb_update_create(struct vxlan_dev *vxlan,
+ const u8 *mac, union vxlan_addr *ip,
+ __u16 state, __u16 flags,
+ __be16 port, __be32 src_vni, __be32 vni,
+ __u32 ifindex, __u16 ndm_flags,
+ bool swdev_notify,
+ struct netlink_ext_ack *extack)
+{
+ __u16 fdb_flags = (ndm_flags & ~NTF_USE);
+ struct vxlan_fdb *f;
+ int rc;
+
+ /* Disallow replace to add a multicast entry */
+ if ((flags & NLM_F_REPLACE) &&
+ (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
+ return -EOPNOTSUPP;
+
+ netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
+ rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
+ vni, ifindex, fdb_flags, &f);
+ if (rc < 0)
+ return rc;
+
+ rc = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH,
+ swdev_notify, extack);
+ if (rc)
+ goto err_notify;
+
+ return 0;
+
+err_notify:
+ vxlan_fdb_destroy(vxlan, f, false, false);
+ return rc;
+}
+
+/* Add new entry to forwarding table -- assumes lock held */
+static int vxlan_fdb_update(struct vxlan_dev *vxlan,
+ const u8 *mac, union vxlan_addr *ip,
+ __u16 state, __u16 flags,
+ __be16 port, __be32 src_vni, __be32 vni,
+ __u32 ifindex, __u16 ndm_flags,
+ bool swdev_notify,
+ struct netlink_ext_ack *extack)
+{
+ struct vxlan_fdb *f;
+
+ f = __vxlan_find_mac(vxlan, mac, src_vni);
+ if (f) {
+ if (flags & NLM_F_EXCL) {
+ netdev_dbg(vxlan->dev,
+ "lost race to create %pM\n", mac);
+ return -EEXIST;
+ }
+
+ return vxlan_fdb_update_existing(vxlan, ip, state, flags, port,
+ vni, ifindex, ndm_flags, f,
+ swdev_notify, extack);
+ } else {
+ if (!(flags & NLM_F_CREATE))
+ return -ENOENT;
+
+ return vxlan_fdb_update_create(vxlan, mac, ip, state, flags,
+ port, src_vni, vni, ifindex,
+ ndm_flags, swdev_notify, extack);
+ }
+}
+
static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
struct vxlan_rdst *rd, bool swdev_notify)
{
list_del_rcu(&rd->list);
- vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, swdev_notify);
+ vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, swdev_notify, NULL);
call_rcu(&rd->rcu, vxlan_dst_free);
}
@@ -1025,7 +1098,8 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
/* Add static entry (via netlink) */
static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid, u16 flags)
+ const unsigned char *addr, u16 vid, u16 flags,
+ struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
/* struct net *net = dev_net(vxlan->dev); */
@@ -1055,7 +1129,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags,
port, src_vni, vni, ifindex,
ndm->ndm_flags | NTF_VXLAN_ADDED_BY_USER,
- true);
+ true, extack);
spin_unlock_bh(&vxlan->hash_lock);
return err;
@@ -1223,7 +1297,7 @@ static bool vxlan_snoop(struct net_device *dev,
rdst->remote_ip = *src_ip;
f->updated = jiffies;
- vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true);
+ vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL);
} else {
/* learned new entry */
spin_lock(&vxlan->hash_lock);
@@ -1236,7 +1310,7 @@ static bool vxlan_snoop(struct net_device *dev,
vxlan->cfg.dst_port,
vni,
vxlan->default_dst.remote_vni,
- ifindex, NTF_SELF, true);
+ ifindex, NTF_SELF, true, NULL);
spin_unlock(&vxlan->hash_lock);
}
@@ -2219,7 +2293,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
struct pcpu_sw_netstats *tx_stats, *rx_stats;
union vxlan_addr loopback;
union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
- struct net_device *dev = skb->dev;
+ struct net_device *dev;
int len = skb->len;
tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
@@ -2239,9 +2313,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
#endif
}
+ rcu_read_lock();
+ dev = skb->dev;
+ if (unlikely(!(dev->flags & IFF_UP))) {
+ kfree_skb(skb);
+ goto drop;
+ }
+
if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
- vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
- vni);
+ vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
u64_stats_update_begin(&tx_stats->syncp);
tx_stats->tx_packets++;
@@ -2254,8 +2334,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
rx_stats->rx_bytes += len;
u64_stats_update_end(&rx_stats->syncp);
} else {
+drop:
dev->stats.rx_dropped++;
}
+ rcu_read_unlock();
}
static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
@@ -2841,6 +2923,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = {
.ndo_fdb_dump = vxlan_fdb_dump,
.ndo_fdb_get = vxlan_fdb_get,
.ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
+ .ndo_change_proto_down = dev_change_proto_down_generic,
};
static const struct net_device_ops vxlan_netdev_raw_ops = {
@@ -3478,9 +3561,12 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
goto errout;
/* notify default fdb entry */
- if (f)
- vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH,
- true);
+ if (f) {
+ err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
+ RTM_NEWNEIGH, true, extack);
+ if (err)
+ goto errout;
+ }
list_add(&vxlan->next, &vn->vxlan_list);
return 0;
@@ -3497,11 +3583,40 @@ errout:
return err;
}
+/* Set/clear flags based on attribute */
+static int vxlan_nl2flag(struct vxlan_config *conf, struct nlattr *tb[],
+ int attrtype, unsigned long mask, bool changelink,
+ bool changelink_supported,
+ struct netlink_ext_ack *extack)
+{
+ unsigned long flags;
+
+ if (!tb[attrtype])
+ return 0;
+
+ if (changelink && !changelink_supported) {
+ vxlan_flag_attr_error(attrtype, extack);
+ return -EOPNOTSUPP;
+ }
+
+ if (vxlan_policy[attrtype].type == NLA_FLAG)
+ flags = conf->flags | mask;
+ else if (nla_get_u8(tb[attrtype]))
+ flags = conf->flags | mask;
+ else
+ flags = conf->flags & ~mask;
+
+ conf->flags = flags;
+
+ return 0;
+}
+
static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
struct net_device *dev, struct vxlan_config *conf,
- bool changelink)
+ bool changelink, struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
+ int err = 0;
memset(conf, 0, sizeof(*conf));
@@ -3512,40 +3627,54 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
if (data[IFLA_VXLAN_ID]) {
__be32 vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID]));
- if (changelink && (vni != conf->vni))
+ if (changelink && (vni != conf->vni)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_ID], "Cannot change VNI");
return -EOPNOTSUPP;
+ }
conf->vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID]));
}
if (data[IFLA_VXLAN_GROUP]) {
- if (changelink && (conf->remote_ip.sa.sa_family != AF_INET))
+ if (changelink && (conf->remote_ip.sa.sa_family != AF_INET)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP], "New group address family does not match old group");
return -EOPNOTSUPP;
+ }
conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
conf->remote_ip.sa.sa_family = AF_INET;
} else if (data[IFLA_VXLAN_GROUP6]) {
- if (!IS_ENABLED(CONFIG_IPV6))
+ if (!IS_ENABLED(CONFIG_IPV6)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "IPv6 support not enabled in the kernel");
return -EPFNOSUPPORT;
+ }
- if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6))
+ if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "New group address family does not match old group");
return -EOPNOTSUPP;
+ }
conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]);
conf->remote_ip.sa.sa_family = AF_INET6;
}
if (data[IFLA_VXLAN_LOCAL]) {
- if (changelink && (conf->saddr.sa.sa_family != AF_INET))
+ if (changelink && (conf->saddr.sa.sa_family != AF_INET)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "New local address family does not match old");
return -EOPNOTSUPP;
+ }
conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
conf->saddr.sa.sa_family = AF_INET;
} else if (data[IFLA_VXLAN_LOCAL6]) {
- if (!IS_ENABLED(CONFIG_IPV6))
+ if (!IS_ENABLED(CONFIG_IPV6)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "IPv6 support not enabled in the kernel");
return -EPFNOSUPPORT;
+ }
- if (changelink && (conf->saddr.sa.sa_family != AF_INET6))
+ if (changelink && (conf->saddr.sa.sa_family != AF_INET6)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "New local address family does not match old");
return -EOPNOTSUPP;
+ }
/* TODO: respect scope id */
conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]);
@@ -3562,9 +3691,12 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
if (data[IFLA_VXLAN_TTL_INHERIT]) {
- if (changelink)
- return -EOPNOTSUPP;
- conf->flags |= VXLAN_F_TTL_INHERIT;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_TTL_INHERIT,
+ VXLAN_F_TTL_INHERIT, changelink, false,
+ extack);
+ if (err)
+ return err;
+
}
if (data[IFLA_VXLAN_LABEL])
@@ -3572,10 +3704,11 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
IPV6_FLOWLABEL_MASK;
if (data[IFLA_VXLAN_LEARNING]) {
- if (nla_get_u8(data[IFLA_VXLAN_LEARNING]))
- conf->flags |= VXLAN_F_LEARN;
- else
- conf->flags &= ~VXLAN_F_LEARN;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LEARNING,
+ VXLAN_F_LEARN, changelink, true,
+ extack);
+ if (err)
+ return err;
} else if (!changelink) {
/* default to learn on a new device */
conf->flags |= VXLAN_F_LEARN;
@@ -3585,44 +3718,52 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
conf->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
if (data[IFLA_VXLAN_PROXY]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_PROXY]))
- conf->flags |= VXLAN_F_PROXY;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_PROXY,
+ VXLAN_F_PROXY, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_RSC]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_RSC]))
- conf->flags |= VXLAN_F_RSC;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_RSC,
+ VXLAN_F_RSC, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_L2MISS]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_L2MISS]))
- conf->flags |= VXLAN_F_L2MISS;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L2MISS,
+ VXLAN_F_L2MISS, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_L3MISS]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_L3MISS]))
- conf->flags |= VXLAN_F_L3MISS;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L3MISS,
+ VXLAN_F_L3MISS, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_LIMIT]) {
- if (changelink)
+ if (changelink) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LIMIT],
+ "Cannot change limit");
return -EOPNOTSUPP;
+ }
conf->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
}
if (data[IFLA_VXLAN_COLLECT_METADATA]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_COLLECT_METADATA]))
- conf->flags |= VXLAN_F_COLLECT_METADATA;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_COLLECT_METADATA,
+ VXLAN_F_COLLECT_METADATA, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_PORT_RANGE]) {
@@ -3632,72 +3773,92 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
conf->port_min = ntohs(p->low);
conf->port_max = ntohs(p->high);
} else {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT_RANGE],
+ "Cannot change port range");
return -EOPNOTSUPP;
}
}
if (data[IFLA_VXLAN_PORT]) {
- if (changelink)
+ if (changelink) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT],
+ "Cannot change port");
return -EOPNOTSUPP;
+ }
conf->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]);
}
if (data[IFLA_VXLAN_UDP_CSUM]) {
- if (changelink)
+ if (changelink) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_UDP_CSUM],
+ "Cannot change UDP_CSUM flag");
return -EOPNOTSUPP;
+ }
if (!nla_get_u8(data[IFLA_VXLAN_UDP_CSUM]))
conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX;
}
if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]))
- conf->flags |= VXLAN_F_UDP_ZERO_CSUM6_TX;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
+ VXLAN_F_UDP_ZERO_CSUM6_TX, changelink,
+ false, extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
- conf->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
+ VXLAN_F_UDP_ZERO_CSUM6_RX, changelink,
+ false, extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_REMCSUM_TX]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_REMCSUM_TX]))
- conf->flags |= VXLAN_F_REMCSUM_TX;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_TX,
+ VXLAN_F_REMCSUM_TX, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_REMCSUM_RX]) {
- if (changelink)
- return -EOPNOTSUPP;
- if (nla_get_u8(data[IFLA_VXLAN_REMCSUM_RX]))
- conf->flags |= VXLAN_F_REMCSUM_RX;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_RX,
+ VXLAN_F_REMCSUM_RX, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_GBP]) {
- if (changelink)
- return -EOPNOTSUPP;
- conf->flags |= VXLAN_F_GBP;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GBP,
+ VXLAN_F_GBP, changelink, false, extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_GPE]) {
- if (changelink)
- return -EOPNOTSUPP;
- conf->flags |= VXLAN_F_GPE;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GPE,
+ VXLAN_F_GPE, changelink, false,
+ extack);
+ if (err)
+ return err;
}
if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) {
- if (changelink)
- return -EOPNOTSUPP;
- conf->flags |= VXLAN_F_REMCSUM_NOPARTIAL;
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_NOPARTIAL,
+ VXLAN_F_REMCSUM_NOPARTIAL, changelink,
+ false, extack);
+ if (err)
+ return err;
}
if (tb[IFLA_MTU]) {
- if (changelink)
+ if (changelink) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_MTU],
+ "Cannot change mtu");
return -EOPNOTSUPP;
+ }
conf->mtu = nla_get_u32(tb[IFLA_MTU]);
}
@@ -3714,7 +3875,7 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
struct vxlan_config conf;
int err;
- err = vxlan_nl2conf(tb, data, dev, &conf, false);
+ err = vxlan_nl2conf(tb, data, dev, &conf, false, extack);
if (err)
return err;
@@ -3727,56 +3888,51 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
- unsigned long old_age_interval;
- struct vxlan_rdst old_dst;
+ struct net_device *lowerdev;
struct vxlan_config conf;
int err;
- err = vxlan_nl2conf(tb, data,
- dev, &conf, true);
+ err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
if (err)
return err;
- old_age_interval = vxlan->cfg.age_interval;
- memcpy(&old_dst, dst, sizeof(struct vxlan_rdst));
-
- err = vxlan_dev_configure(vxlan->net, dev, &conf, true, extack);
+ err = vxlan_config_validate(vxlan->net, &conf, &lowerdev,
+ vxlan, extack);
if (err)
return err;
- if (old_age_interval != vxlan->cfg.age_interval)
- mod_timer(&vxlan->age_timer, jiffies);
-
/* handle default dst entry */
- if (!vxlan_addr_equal(&dst->remote_ip, &old_dst.remote_ip)) {
+ if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
spin_lock_bh(&vxlan->hash_lock);
- if (!vxlan_addr_any(&old_dst.remote_ip))
- __vxlan_fdb_delete(vxlan, all_zeros_mac,
- old_dst.remote_ip,
- vxlan->cfg.dst_port,
- old_dst.remote_vni,
- old_dst.remote_vni,
- old_dst.remote_ifindex,
- true);
-
- if (!vxlan_addr_any(&dst->remote_ip)) {
+ if (!vxlan_addr_any(&conf.remote_ip)) {
err = vxlan_fdb_update(vxlan, all_zeros_mac,
- &dst->remote_ip,
+ &conf.remote_ip,
NUD_REACHABLE | NUD_PERMANENT,
NLM_F_APPEND | NLM_F_CREATE,
vxlan->cfg.dst_port,
- dst->remote_vni,
- dst->remote_vni,
- dst->remote_ifindex,
- NTF_SELF, true);
+ conf.vni, conf.vni,
+ conf.remote_ifindex,
+ NTF_SELF, true, extack);
if (err) {
spin_unlock_bh(&vxlan->hash_lock);
return err;
}
}
+ if (!vxlan_addr_any(&dst->remote_ip))
+ __vxlan_fdb_delete(vxlan, all_zeros_mac,
+ dst->remote_ip,
+ vxlan->cfg.dst_port,
+ dst->remote_vni,
+ dst->remote_vni,
+ dst->remote_ifindex,
+ true);
spin_unlock_bh(&vxlan->hash_lock);
}
+ if (conf.age_interval != vxlan->cfg.age_interval)
+ mod_timer(&vxlan->age_timer, jiffies);
+
+ vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
return 0;
}
@@ -4051,8 +4207,11 @@ vxlan_fdb_external_learn_add(struct net_device *dev,
struct switchdev_notifier_vxlan_fdb_info *fdb_info)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct netlink_ext_ack *extack;
int err;
+ extack = switchdev_notifier_info_to_extack(&fdb_info->info);
+
spin_lock_bh(&vxlan->hash_lock);
err = vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip,
NUD_REACHABLE,
@@ -4062,7 +4221,7 @@ vxlan_fdb_external_learn_add(struct net_device *dev,
fdb_info->remote_vni,
fdb_info->remote_ifindex,
NTF_USE | NTF_SELF | NTF_EXT_LEARNED,
- false);
+ false, extack);
spin_unlock_bh(&vxlan->hash_lock);
return err;
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index f6b000ddcd15..55f76e422fa0 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -769,7 +769,7 @@ static int cosa_net_tx_done(struct channel_data *chan, int size)
chan->netdev->stats.tx_aborted_errors++;
return 1;
}
- dev_kfree_skb_irq(chan->tx_skb);
+ dev_consume_skb_irq(chan->tx_skb);
chan->tx_skb = NULL;
chan->netdev->stats.tx_packets++;
chan->netdev->stats.tx_bytes += size;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index c0b0f525c87c..fa78d2b14136 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -456,16 +456,16 @@ static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
int ret = 0;
if (debug > 1) {
- if (SOURCE_ID(state) != dpriv->dev_id) {
- printk(KERN_DEBUG "%s (%s): Source Id=%d, state=%08x\n",
- dev->name, msg, SOURCE_ID(state), state );
+ if (SOURCE_ID(state) != dpriv->dev_id) {
+ printk(KERN_DEBUG "%s (%s): Source Id=%d, state=%08x\n",
+ dev->name, msg, SOURCE_ID(state), state);
ret = -1;
- }
- if (state & 0x0df80c00) {
- printk(KERN_DEBUG "%s (%s): state=%08x (UFO alert)\n",
- dev->name, msg, state);
+ }
+ if (state & 0x0df80c00) {
+ printk(KERN_DEBUG "%s (%s): state=%08x (UFO alert)\n",
+ dev->name, msg, state);
ret = -1;
- }
+ }
}
return ret;
}
@@ -1575,7 +1575,7 @@ try:
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
}
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
dpriv->tx_skbuff[cur] = NULL;
++dpriv->tx_dirty;
} else {
@@ -1760,25 +1760,25 @@ try:
} else { /* SccEvt */
if (debug > 1) {
//FIXME: verifier la presence de tous les evenements
- static struct {
- u32 mask;
- const char *irq_name;
- } evts[] = {
- { 0x00008000, "TIN"},
- { 0x00000020, "RSC"},
- { 0x00000010, "PCE"},
- { 0x00000008, "PLLA"},
- { 0, NULL}
- }, *evt;
-
- for (evt = evts; evt->irq_name; evt++) {
- if (state & evt->mask) {
+ static struct {
+ u32 mask;
+ const char *irq_name;
+ } evts[] = {
+ { 0x00008000, "TIN"},
+ { 0x00000020, "RSC"},
+ { 0x00000010, "PCE"},
+ { 0x00000008, "PLLA"},
+ { 0, NULL}
+ }, *evt;
+
+ for (evt = evts; evt->irq_name; evt++) {
+ if (state & evt->mask) {
printk(KERN_DEBUG "%s: %s\n",
- dev->name, evt->irq_name);
- if (!(state &= ~evt->mask))
- goto try;
+ dev->name, evt->irq_name);
+ if (!(state &= ~evt->mask))
+ goto try;
+ }
}
- }
} else {
if (!(state &= ~0x0000c03c))
goto try;
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 839fa7715709..a08f04c3f644 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -279,10 +279,9 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4);
/* Get BD buffer */
- bd_buffer = dma_zalloc_coherent(priv->dev,
- (RX_BD_RING_LEN + TX_BD_RING_LEN) *
- MAX_RX_BUF_LENGTH,
- &bd_dma_addr, GFP_KERNEL);
+ bd_buffer = dma_alloc_coherent(priv->dev,
+ (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH,
+ &bd_dma_addr, GFP_KERNEL);
if (!bd_buffer) {
dev_err(priv->dev, "Could not allocate buffer descriptors\n");
@@ -483,7 +482,7 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv)
memset(priv->tx_buffer +
(be32_to_cpu(bd->buf) - priv->dma_tx_addr),
0, skb->len);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
priv->tx_skbuff[priv->skb_dirtytx] = NULL;
priv->skb_dirtytx =
@@ -1057,6 +1056,54 @@ static const struct net_device_ops uhdlc_ops = {
.ndo_tx_timeout = uhdlc_tx_timeout,
};
+static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr)
+{
+ struct device_node *np;
+ struct platform_device *pdev;
+ struct resource *res;
+ static int siram_init_flag;
+ int ret = 0;
+
+ np = of_find_compatible_node(NULL, NULL, name);
+ if (!np)
+ return -EINVAL;
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev) {
+ pr_err("%pOFn: failed to lookup pdev\n", np);
+ of_node_put(np);
+ return -EINVAL;
+ }
+
+ of_node_put(np);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -EINVAL;
+ goto error_put_device;
+ }
+ *ptr = ioremap(res->start, resource_size(res));
+ if (!*ptr) {
+ ret = -ENOMEM;
+ goto error_put_device;
+ }
+
+ /* We've remapped the addresses, and we don't need the device any
+ * more, so we should release it.
+ */
+ put_device(&pdev->dev);
+
+ if (init_flag && siram_init_flag == 0) {
+ memset_io(*ptr, 0, resource_size(res));
+ siram_init_flag = 1;
+ }
+ return 0;
+
+error_put_device:
+ put_device(&pdev->dev);
+
+ return ret;
+}
+
static int ucc_hdlc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1151,6 +1198,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
ret = ucc_of_parse_tdm(np, utdm, ut_info);
if (ret)
goto free_utdm;
+
+ ret = hdlc_map_iomem("fsl,t1040-qe-si", 0,
+ (void __iomem **)&utdm->si_regs);
+ if (ret)
+ goto free_utdm;
+ ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1,
+ (void __iomem **)&utdm->siram);
+ if (ret)
+ goto unmap_si_regs;
}
if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask))
@@ -1159,7 +1215,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
ret = uhdlc_init(uhdlc_priv);
if (ret) {
dev_err(&pdev->dev, "Failed to init uhdlc\n");
- goto free_utdm;
+ goto undo_uhdlc_init;
}
dev = alloc_hdlcdev(uhdlc_priv);
@@ -1188,6 +1244,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
free_dev:
free_netdev(dev);
undo_uhdlc_init:
+ iounmap(utdm->siram);
+unmap_si_regs:
+ iounmap(utdm->si_regs);
free_utdm:
if (uhdlc_priv->tsa)
kfree(utdm);
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 6a505c26a3e7..5c60dc60a8e6 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -246,7 +246,7 @@
#ifdef __ARMEB__
typedef struct sk_buff buffer_t;
#define free_buffer dev_kfree_skb
-#define free_buffer_irq dev_kfree_skb_irq
+#define free_buffer_irq dev_consume_skb_irq
#else
typedef void buffer_t;
#define free_buffer kfree
diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile
index 609710d64eb5..247f60c401ef 100644
--- a/drivers/net/wan/lmc/Makefile
+++ b/drivers/net/wan/lmc/Makefile
@@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
# -DDEBUG \
# -DLMC_PACKET_LOG
-ccflags-y := -I. $(DBGDEF)
+ccflags-y := $(DBGDEF)
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 4907453f17f5..22b065ff6d39 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1320,8 +1320,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/
sc->lmc_device->stats.tx_packets++;
}
- // dev_kfree_skb(sc->lmc_txq[i]);
- dev_kfree_skb_irq(sc->lmc_txq[i]);
+ dev_consume_skb_irq(sc->lmc_txq[i]);
sc->lmc_txq[i] = NULL;
badtx++;
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 8e8c4c0e1b64..40c04ea1200a 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -761,7 +761,7 @@ send_complete( struct net_device *dev )
dev->stats.tx_packets++;
dev->stats.tx_bytes += nl->tx_buf_p->len;
#endif
- dev_kfree_skb_irq( nl->tx_buf_p );
+ dev_consume_skb_irq(nl->tx_buf_p);
nl->tx_buf_p = NULL;
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index d573a57bc301..10d5333b7a88 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -185,7 +185,7 @@ static inline void wanxl_tx_intr(struct port *port)
desc->stat = PACKET_EMPTY; /* Free descriptor */
pci_unmap_single(port->card->pdev, desc->address, skb->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
port->tx_in = (port->tx_in + 1) % TX_BUFFERS;
}
}
@@ -565,7 +565,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
u32 plx_phy; /* PLX PCI base address */
u32 mem_phy; /* memory PCI base addr */
u8 __iomem *mem; /* memory virtual base addr */
- int i, ports, alloc_size;
+ int i, ports;
#ifndef MODULE
pr_info_once("%s\n", version);
@@ -601,8 +601,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
default: ports = 4;
}
- alloc_size = sizeof(struct card) + ports * sizeof(struct port);
- card = kzalloc(alloc_size, GFP_KERNEL);
+ card = kzalloc(struct_size(card, ports, ports), GFP_KERNEL);
if (card == NULL) {
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index deea41e96f01..0e56ab0aed9a 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -1536,7 +1536,7 @@ static void z8530_tx_done(struct z8530_channel *c)
z8530_tx_begin(c);
c->netdevice->stats.tx_packets++;
c->netdevice->stats.tx_bytes += skb->len;
- dev_kfree_skb_irq(skb);
+ dev_consume_skb_irq(skb);
}
/**
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
index 0b602951ff6b..d28b96d06919 100644
--- a/drivers/net/wimax/i2400m/rx.c
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -1260,8 +1260,8 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
goto error_msg_hdr_check;
result = -EIO;
num_pls = le16_to_cpu(msg_hdr->num_pls);
- pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */
- num_pls * sizeof(msg_hdr->pld[0]);
+ /* Check payload descriptor(s) */
+ pl_itr = struct_size(msg_hdr, pld, num_pls);
pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN);
if (pl_itr > skb_len) { /* got all the payload descriptors? */
dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index f8eb66ef2944..73842a830645 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -210,6 +210,7 @@ retry:
msleep(10); /* give the device some time */
goto retry;
}
+ /* fall through */
case -EINVAL: /* while removing driver */
case -ENODEV: /* dev disconnect ... */
case -ENOENT: /* just ignore it */
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 66326b949ab1..142c777b287f 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: ISC
obj-$(CONFIG_ATH10K) += ath10k_core.o
ath10k_core-y += mac.o \
debug.o \
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index 4cd69aca75e2..0bf726c55736 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2016-2017 Qualcomm Atheros, Inc. All rights reserved.
* Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
#include <linux/of.h>
@@ -661,7 +650,8 @@ static void ath10k_ahb_hif_stop(struct ath10k *ar)
ath10k_pci_flush(ar);
}
-static int ath10k_ahb_hif_power_up(struct ath10k *ar)
+static int ath10k_ahb_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
int ret;
diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h
index d43e375215c8..cee11a3ae2a5 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.h
+++ b/drivers/net/wireless/ath/ath10k/ahb.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved.
* Copyright (c) 2015 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _AHB_H_
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index 1750b182209b..95dc4be82e5c 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "bmi.h"
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 725c9afc63f2..ef3bdba43bed 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BMI_H_
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index f6d3ecbdd3a3..24b983edb357 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hif.h"
@@ -228,11 +217,31 @@ ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar,
}
static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
- u32 ce_ctrl_addr,
- unsigned int addr)
+ u32 ce_id,
+ u64 addr)
+{
+ struct ath10k_ce *ce = ath10k_ce_priv(ar);
+ struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
+ u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id);
+ u32 addr_lo = lower_32_bits(addr);
+
+ ath10k_ce_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_base_addr_lo, addr_lo);
+
+ if (ce_state->ops->ce_set_src_ring_base_addr_hi) {
+ ce_state->ops->ce_set_src_ring_base_addr_hi(ar, ce_ctrl_addr,
+ addr);
+ }
+}
+
+static void ath10k_ce_set_src_ring_base_addr_hi(struct ath10k *ar,
+ u32 ce_ctrl_addr,
+ u64 addr)
{
+ u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK;
+
ath10k_ce_write32(ar, ce_ctrl_addr +
- ar->hw_ce_regs->sr_base_addr, addr);
+ ar->hw_ce_regs->sr_base_addr_hi, addr_hi);
}
static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
@@ -313,11 +322,36 @@ static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
}
static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
- u32 ce_ctrl_addr,
- u32 addr)
+ u32 ce_id,
+ u64 addr)
{
+ struct ath10k_ce *ce = ath10k_ce_priv(ar);
+ struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
+ u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id);
+ u32 addr_lo = lower_32_bits(addr);
+
ath10k_ce_write32(ar, ce_ctrl_addr +
- ar->hw_ce_regs->dr_base_addr, addr);
+ ar->hw_ce_regs->dr_base_addr_lo, addr_lo);
+
+ if (ce_state->ops->ce_set_dest_ring_base_addr_hi) {
+ ce_state->ops->ce_set_dest_ring_base_addr_hi(ar, ce_ctrl_addr,
+ addr);
+ }
+}
+
+static void ath10k_ce_set_dest_ring_base_addr_hi(struct ath10k *ar,
+ u32 ce_ctrl_addr,
+ u64 addr)
+{
+ u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK;
+ u32 reg_value;
+
+ reg_value = ath10k_ce_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_base_addr_hi);
+ reg_value &= ~CE_DESC_ADDR_HI_MASK;
+ reg_value |= addr_hi;
+ ath10k_ce_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_base_addr_hi, reg_value);
}
static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
@@ -500,14 +534,8 @@ static int _ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
/* WORKAROUND */
- if (!(flags & CE_SEND_FLAG_GATHER)) {
- if (ar->hw_params.shadow_reg_support)
- ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state,
- write_index);
- else
- ath10k_ce_src_ring_write_index_set(ar, ctrl_addr,
- write_index);
- }
+ if (!(flags & CE_SEND_FLAG_GATHER))
+ ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index);
src_ring->write_index = write_index;
exit:
@@ -563,7 +591,7 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state,
addr = (__le32 *)&sdesc.addr;
- flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK;
+ flags |= upper_32_bits(buffer) & CE_DESC_ADDR_HI_MASK;
addr[0] = __cpu_to_le32(buffer);
addr[1] = __cpu_to_le32(flags);
if (flags & CE_SEND_FLAG_GATHER)
@@ -581,8 +609,14 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state,
/* Update Source Ring Write Index */
write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
- if (!(flags & CE_SEND_FLAG_GATHER))
- ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index);
+ if (!(flags & CE_SEND_FLAG_GATHER)) {
+ if (ar->hw_params.shadow_reg_support)
+ ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state,
+ write_index);
+ else
+ ath10k_ce_src_ring_write_index_set(ar, ctrl_addr,
+ write_index);
+ }
src_ring->write_index = write_index;
exit:
@@ -731,7 +765,7 @@ static int __ath10k_ce_rx_post_buf_64(struct ath10k_ce_pipe *pipe,
return -ENOSPC;
desc->addr = __cpu_to_le64(paddr);
- desc->addr &= __cpu_to_le64(CE_DESC_37BIT_ADDR_MASK);
+ desc->addr &= __cpu_to_le64(CE_DESC_ADDR_MASK);
desc->nbytes = 0;
@@ -1032,8 +1066,8 @@ EXPORT_SYMBOL(ath10k_ce_revoke_recv_next);
* Guts of ath10k_ce_completed_send_next.
* The caller takes responsibility for any necessary locking.
*/
-int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp)
+static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp)
{
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
u32 ctrl_addr = ce_state->ctrl_addr;
@@ -1084,6 +1118,66 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
return 0;
}
+
+static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp)
+{
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
+ u32 ctrl_addr = ce_state->ctrl_addr;
+ struct ath10k *ar = ce_state->ar;
+ unsigned int nentries_mask = src_ring->nentries_mask;
+ unsigned int sw_index = src_ring->sw_index;
+ unsigned int read_index;
+ struct ce_desc_64 *desc;
+
+ if (src_ring->hw_index == sw_index) {
+ /*
+ * The SW completion index has caught up with the cached
+ * version of the HW completion index.
+ * Update the cached HW completion index to see whether
+ * the SW has really caught up to the HW, or if the cached
+ * value of the HW index has become stale.
+ */
+
+ read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+ if (read_index == 0xffffffff)
+ return -ENODEV;
+
+ read_index &= nentries_mask;
+ src_ring->hw_index = read_index;
+ }
+
+ if (ar->hw_params.rri_on_ddr)
+ read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+ else
+ read_index = src_ring->hw_index;
+
+ if (read_index == sw_index)
+ return -EIO;
+
+ if (per_transfer_contextp)
+ *per_transfer_contextp =
+ src_ring->per_transfer_context[sw_index];
+
+ /* sanity */
+ src_ring->per_transfer_context[sw_index] = NULL;
+ desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space,
+ sw_index);
+ desc->nbytes = 0;
+
+ /* Update sw_index */
+ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
+ src_ring->sw_index = sw_index;
+
+ return 0;
+}
+
+int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp)
+{
+ return ce_state->ops->ce_completed_send_next_nolock(ce_state,
+ per_transfer_contextp);
+}
EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock);
static void ath10k_ce_extract_desc_data(struct ath10k *ar,
@@ -1346,7 +1440,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
ath10k_ce_src_ring_write_index_get(ar, ctrl_addr);
src_ring->write_index &= src_ring->nentries_mask;
- ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr,
+ ath10k_ce_src_ring_base_addr_set(ar, ce_id,
src_ring->base_addr_ce_space);
ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries);
ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, attr->src_sz_max);
@@ -1385,7 +1479,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
dest_ring->write_index &= dest_ring->nentries_mask;
- ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr,
+ ath10k_ce_dest_ring_base_addr_set(ar, ce_id,
dest_ring->base_addr_ce_space);
ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries);
ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0);
@@ -1404,12 +1498,12 @@ static int ath10k_ce_alloc_shadow_base(struct ath10k *ar,
u32 nentries)
{
src_ring->shadow_base_unaligned = kcalloc(nentries,
- sizeof(struct ce_desc),
+ sizeof(struct ce_desc_64),
GFP_KERNEL);
if (!src_ring->shadow_base_unaligned)
return -ENOMEM;
- src_ring->shadow_base = (struct ce_desc *)
+ src_ring->shadow_base = (struct ce_desc_64 *)
PTR_ALIGN(src_ring->shadow_base_unaligned,
CE_DESC_RING_ALIGN);
return 0;
@@ -1461,7 +1555,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
if (ret) {
dma_free_coherent(ar->dev,
- (nentries * sizeof(struct ce_desc) +
+ (nentries * sizeof(struct ce_desc_64) +
CE_DESC_RING_ALIGN),
src_ring->base_addr_owner_space_unaligned,
base_addr);
@@ -1553,10 +1647,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
* coherent DMA are unsupported
*/
dest_ring->base_addr_owner_space_unaligned =
- dma_zalloc_coherent(ar->dev,
- (nentries * sizeof(struct ce_desc) +
- CE_DESC_RING_ALIGN),
- &base_addr, GFP_KERNEL);
+ dma_alloc_coherent(ar->dev,
+ (nentries * sizeof(struct ce_desc) +
+ CE_DESC_RING_ALIGN),
+ &base_addr, GFP_KERNEL);
if (!dest_ring->base_addr_owner_space_unaligned) {
kfree(dest_ring);
return ERR_PTR(-ENOMEM);
@@ -1661,7 +1755,7 @@ static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id)
{
u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
- ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, 0);
+ ath10k_ce_src_ring_base_addr_set(ar, ce_id, 0);
ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0);
ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, 0);
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, 0);
@@ -1671,7 +1765,7 @@ static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id)
{
u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
- ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, 0);
+ ath10k_ce_dest_ring_base_addr_set(ar, ce_id, 0);
ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0);
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, 0);
}
@@ -1803,6 +1897,9 @@ static const struct ath10k_ce_ops ce_ops = {
.ce_extract_desc_data = ath10k_ce_extract_desc_data,
.ce_free_pipe = _ath10k_ce_free_pipe,
.ce_send_nolock = _ath10k_ce_send_nolock,
+ .ce_set_src_ring_base_addr_hi = NULL,
+ .ce_set_dest_ring_base_addr_hi = NULL,
+ .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock,
};
static const struct ath10k_ce_ops ce_64_ops = {
@@ -1815,6 +1912,9 @@ static const struct ath10k_ce_ops ce_64_ops = {
.ce_extract_desc_data = ath10k_ce_extract_desc_data_64,
.ce_free_pipe = _ath10k_ce_free_pipe_64,
.ce_send_nolock = _ath10k_ce_send_nolock_64,
+ .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi,
+ .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi,
+ .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64,
};
static void ath10k_ce_set_ops(struct ath10k *ar,
@@ -1910,7 +2010,7 @@ void ath10k_ce_alloc_rri(struct ath10k *ar)
lower_32_bits(ce->paddr_rri));
ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_high,
(upper_32_bits(ce->paddr_rri) &
- CE_DESC_FLAGS_GET_MASK));
+ CE_DESC_ADDR_HI_MASK));
for (i = 0; i < CE_COUNT; i++) {
ctrl1_regs = ar->hw_ce_regs->ctrl1_regs->addr;
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index ead9987c3259..a7478c240f78 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _CE_H_
@@ -39,8 +28,8 @@ struct ath10k_ce_pipe;
#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1)
#define CE_WCN3990_DESC_FLAGS_GATHER BIT(31)
-#define CE_DESC_FLAGS_GET_MASK GENMASK(4, 0)
-#define CE_DESC_37BIT_ADDR_MASK GENMASK_ULL(37, 0)
+#define CE_DESC_ADDR_MASK GENMASK_ULL(34, 0)
+#define CE_DESC_ADDR_HI_MASK GENMASK(4, 0)
/* Following desc flags are used in QCA99X0 */
#define CE_DESC_FLAGS_HOST_INT_DIS (1 << 2)
@@ -104,7 +93,7 @@ struct ath10k_ce_ring {
/* Host address space */
void *base_addr_owner_space_unaligned;
/* CE address space */
- u32 base_addr_ce_space_unaligned;
+ dma_addr_t base_addr_ce_space_unaligned;
/*
* Actual start of descriptors.
@@ -115,10 +104,10 @@ struct ath10k_ce_ring {
void *base_addr_owner_space;
/* CE address space */
- u32 base_addr_ce_space;
+ dma_addr_t base_addr_ce_space;
char *shadow_base_unaligned;
- struct ce_desc *shadow_base;
+ struct ce_desc_64 *shadow_base;
/* keep last */
void *per_transfer_context[0];
@@ -334,6 +323,14 @@ struct ath10k_ce_ops {
void *per_transfer_context,
dma_addr_t buffer, u32 nbytes,
u32 transfer_id, u32 flags);
+ void (*ce_set_src_ring_base_addr_hi)(struct ath10k *ar,
+ u32 ce_ctrl_addr,
+ u64 addr);
+ void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar,
+ u32 ce_ctrl_addr,
+ u64 addr);
+ int (*ce_completed_send_next_nolock)(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp);
};
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 399b501f3c3c..835b8de92d55 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
@@ -548,7 +537,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
.id = WCN3990_HW_1_0_DEV_VERSION,
.dev_id = 0,
- .bus = ATH10K_BUS_PCI,
+ .bus = ATH10K_BUS_SNOC,
.name = "wcn3990 hw1.0",
.continuous_frag_desc = true,
.tx_chain_mask = 0x7,
@@ -560,10 +549,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.sw_decrypt_mcast_mgmt = true,
.hw_ops = &wcn3990_ops,
.decap_align_bytes = 1,
- .num_peers = TARGET_HL_10_TLV_NUM_PEERS,
- .n_cipher_suites = 8,
- .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT,
- .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES,
+ .num_peers = TARGET_HL_TLV_NUM_PEERS,
+ .n_cipher_suites = 11,
+ .ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT,
+ .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,
.target_64bit = true,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,
.per_ce_irq = true,
@@ -648,11 +637,24 @@ static void ath10k_init_sdio(struct ath10k *ar)
ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
ath10k_bmi_read32(ar, hi_acs_flags, &param);
- param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET |
- HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET |
- HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE);
+ /* Data transfer is not initiated, when reduced Tx completion
+ * is used for SDIO. disable it until fixed
+ */
+ param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
+ /* Alternate credit size of 1544 as used by SDIO firmware is
+ * not big enough for mac80211 / native wifi frames. disable it
+ */
+ param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
+ param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
ath10k_bmi_write32(ar, hi_acs_flags, param);
+
+ /* Explicitly set fwlog prints to zero as target may turn it on
+ * based on scratch registers.
+ */
+ ath10k_bmi_read32(ar, hi_option_flag, &param);
+ param |= HI_OPTION_DISABLE_DBGLOG;
+ ath10k_bmi_write32(ar, hi_option_flag, param);
}
static int ath10k_init_configure_target(struct ath10k *ar)
@@ -2309,10 +2311,14 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
- ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
+ if (ar->hif.bus == ATH10K_BUS_SDIO)
+ ar->htt.max_num_pending_tx =
+ TARGET_TLV_NUM_MSDU_DESC_HL;
+ else
+ ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;
- ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
- WMI_STAT_PEER;
+ ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV |
+ WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD;
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;
break;
@@ -2556,6 +2562,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
+ status = ath10k_hif_swap_mailbox(ar);
+ if (status) {
+ ath10k_err(ar, "failed to swap mailbox: %d\n", status);
+ goto err_hif_stop;
+ }
+
if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
status = ath10k_htt_connect(&ar->htt);
if (status) {
@@ -2621,6 +2633,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ar->wmi.svc_map))
val |= WMI_10_4_TX_DATA_ACK_RSSI;
+ if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
+ val |= WMI_10_4_REPORT_AIRTIME;
+
status = ath10k_mac_ext_resource_config(ar, val);
if (status) {
ath10k_err(ar,
@@ -2649,6 +2664,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
+ status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);
+ if (status && status != -EOPNOTSUPP) {
+ ath10k_err(ar,
+ "failed to set base mac address: %d\n", status);
+ goto err_hif_stop;
+ }
+
/* Some firmware revisions do not properly set up hardware rx filter
* registers.
*
@@ -2763,7 +2785,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
struct bmi_target_info target_info;
int ret = 0;
- ret = ath10k_hif_power_up(ar);
+ ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "could not power on hif bus (%d)\n", ret);
return ret;
@@ -2977,8 +2999,8 @@ err:
int ath10k_core_register(struct ath10k *ar,
const struct ath10k_bus_params *bus_params)
{
- ar->chip_id = bus_params->chip_id;
- ar->dev_type = bus_params->dev_type;
+ ar->bus_param = *bus_params;
+
queue_work(ar->workqueue, &ar->register_work);
return 0;
@@ -3098,9 +3120,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
- spin_lock_init(&ar->txqs_lock);
- INIT_LIST_HEAD(&ar->txqs);
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 46e9c8c97a4d..e08a17b01e03 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _CORE_H_
@@ -90,6 +79,9 @@
/* The magic used by QCA spec */
#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_"
+/* Default Airtime weight multipler (Tuned for multiclient performance) */
+#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
+
struct ath10k;
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -116,6 +108,7 @@ enum ath10k_skb_flags {
ATH10K_SKB_F_DELIVER_CAB = BIT(2),
ATH10K_SKB_F_MGMT = BIT(3),
ATH10K_SKB_F_QOS = BIT(4),
+ ATH10K_SKB_F_RAW_TX = BIT(5),
};
struct ath10k_skb_cb {
@@ -123,6 +116,7 @@ struct ath10k_skb_cb {
u8 flags;
u8 eid;
u16 msdu_id;
+ u16 airtime_est;
struct ieee80211_vif *vif;
struct ieee80211_txq *txq;
} __packed;
@@ -195,7 +189,7 @@ struct ath10k_fw_stats_peer {
u32 peer_rssi;
u32 peer_tx_rate;
u32 peer_rx_rate; /* 10x only */
- u32 rx_duration;
+ u64 rx_duration;
};
struct ath10k_fw_extd_stats_peer {
@@ -443,14 +437,14 @@ enum ath10k_amsdu_subfrm_num {
};
struct ath10k_sta_tid_stats {
- unsigned long int rx_pkt_from_fw;
- unsigned long int rx_pkt_unchained;
- unsigned long int rx_pkt_drop_chained;
- unsigned long int rx_pkt_drop_filter;
- unsigned long int rx_pkt_err[ATH10K_PKT_RX_ERR_MAX];
- unsigned long int rx_pkt_queued_for_mac;
- unsigned long int rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX];
- unsigned long int rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX];
+ unsigned long rx_pkt_from_fw;
+ unsigned long rx_pkt_unchained;
+ unsigned long rx_pkt_drop_chained;
+ unsigned long rx_pkt_drop_filter;
+ unsigned long rx_pkt_err[ATH10K_PKT_RX_ERR_MAX];
+ unsigned long rx_pkt_queued_for_mac;
+ unsigned long rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX];
+ unsigned long rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX];
};
enum ath10k_counter_type {
@@ -495,6 +489,7 @@ struct ath10k_sta {
u16 peer_id;
struct rate_info txrate;
struct ieee80211_tx_info tx_info;
+ u32 last_tx_bitrate;
struct work_struct update_wk;
u64 rx_duration;
@@ -571,6 +566,7 @@ struct ath10k_vif {
bool nohwcrypt;
int num_legacy_stations;
int txpower;
+ bool ftm_responder;
struct wmi_wmm_params_all_arg wmm_params;
struct work_struct ap_csa_work;
struct delayed_work connection_loss_work;
@@ -922,6 +918,7 @@ enum ath10k_dev_type {
struct ath10k_bus_params {
u32 chip_id;
enum ath10k_dev_type dev_type;
+ bool link_can_suspend;
};
struct ath10k {
@@ -1068,10 +1065,7 @@ struct ath10k {
/* protects shared structure data */
spinlock_t data_lock;
- /* protects: ar->txqs, artxq->list */
- spinlock_t txqs_lock;
- struct list_head txqs;
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
@@ -1182,6 +1176,7 @@ struct ath10k {
u32 ampdu_reference;
+ const u8 *wmi_key_cipher;
void *ce_priv;
u32 sta_tid_stats_mask;
@@ -1190,6 +1185,7 @@ struct ath10k {
enum ath10k_radar_confirmation_state radar_conf_state;
struct ath10k_radar_found_info last_radar_info;
struct work_struct radar_confirmation_work;
+ struct ath10k_bus_params bus_param;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c
index eadae2f9206b..33838d9c1cb6 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.c
+++ b/drivers/net/wireless/ath/ath10k/coredump.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "coredump.h"
@@ -1167,7 +1156,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
guid_copy(&dump_data->guid, &crash_data->guid);
- dump_data->chip_id = cpu_to_le32(ar->chip_id);
+ dump_data->chip_id = cpu_to_le32(ar->bus_param.chip_id);
dump_data->bus_type = cpu_to_le32(0);
dump_data->target_version = cpu_to_le32(ar->target_version);
dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h
index 5dac653e1649..09de41922f97 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.h
+++ b/drivers/net/wireless/ath/ath10k/coredump.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _COREDUMP_H_
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 02988fc378a1..32d967a31c65 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
@@ -58,7 +47,7 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
ar->hw_params.name,
ar->target_version,
- ar->chip_id,
+ ar->bus_param.chip_id,
ar->id.subsystem_vendor, ar->id.subsystem_device);
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
@@ -625,7 +614,7 @@ static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
size_t len;
char buf[50];
- len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
+ len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->bus_param.chip_id);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1263,6 +1252,9 @@ static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
return -EINVAL;
+ if (ar->hw_params.cal_data_len == 0)
+ return -EOPNOTSUPP;
+
hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 5cf16d690724..db78e855a80f 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _DEBUG_H_
@@ -213,12 +202,12 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void ath10k_sta_update_rx_duration(struct ath10k *ar,
struct ath10k_fw_stats *stats);
void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
- unsigned long int num_msdus,
+ unsigned long num_msdus,
enum ath10k_pkt_rx_err err,
- unsigned long int unchain_cnt,
- unsigned long int drop_cnt,
- unsigned long int drop_cnt_filter,
- unsigned long int queued_msdus);
+ unsigned long unchain_cnt,
+ unsigned long drop_cnt,
+ unsigned long drop_cnt_filter,
+ unsigned long queued_msdus);
void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
u16 peer_id, u8 tid,
struct htt_rx_indication_mpdu_range *ranges,
@@ -232,12 +221,12 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar,
static inline
void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
- unsigned long int num_msdus,
+ unsigned long num_msdus,
enum ath10k_pkt_rx_err err,
- unsigned long int unchain_cnt,
- unsigned long int drop_cnt,
- unsigned long int drop_cnt_filter,
- unsigned long int queued_msdus)
+ unsigned long unchain_cnt,
+ unsigned long drop_cnt,
+ unsigned long drop_cnt_filter,
+ unsigned long queued_msdus)
{
}
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index 4778a455d81a..c704ae371c4d 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
@@ -87,12 +76,12 @@ out:
}
void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
- unsigned long int num_msdus,
+ unsigned long num_msdus,
enum ath10k_pkt_rx_err err,
- unsigned long int unchain_cnt,
- unsigned long int drop_cnt,
- unsigned long int drop_cnt_filter,
- unsigned long int queued_msdus)
+ unsigned long unchain_cnt,
+ unsigned long drop_cnt,
+ unsigned long drop_cnt_filter,
+ unsigned long queued_msdus)
{
struct ieee80211_sta *sta;
struct ath10k_sta *arsta;
@@ -696,11 +685,12 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
" %llu ", stats->ht[j][i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len,
- " BW %s (20,40,80,160 MHz)\n", str[j]);
+ " BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
len += scnprintf(buf + len, size - len,
- " %llu %llu %llu %llu\n",
+ " %llu %llu %llu %llu %llu %llu\n",
stats->bw[j][0], stats->bw[j][1],
- stats->bw[j][2], stats->bw[j][3]);
+ stats->bw[j][2], stats->bw[j][3],
+ stats->bw[j][4], stats->bw[j][5]);
len += scnprintf(buf + len, size - len,
" NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
len += scnprintf(buf + len, size - len,
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 1a59ea0068c2..fe5417962f40 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HIF_H_
@@ -59,6 +48,8 @@ struct ath10k_hif_ops {
*/
void (*stop)(struct ath10k *ar);
+ int (*swap_mailbox)(struct ath10k *ar);
+
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe);
@@ -81,7 +72,7 @@ struct ath10k_hif_ops {
void (*write32)(struct ath10k *ar, u32 address, u32 value);
/* Power up the device and enter BMI transfer mode for FW download */
- int (*power_up)(struct ath10k *ar);
+ int (*power_up)(struct ath10k *ar, enum ath10k_firmware_mode fw_mode);
/* Power down the device and free up resources. stop() must be called
* before this if start() was called earlier
@@ -139,6 +130,13 @@ static inline void ath10k_hif_stop(struct ath10k *ar)
return ar->hif.ops->stop(ar);
}
+static inline int ath10k_hif_swap_mailbox(struct ath10k *ar)
+{
+ if (ar->hif.ops->swap_mailbox)
+ return ar->hif.ops->swap_mailbox(ar);
+ return 0;
+}
+
static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar,
u16 service_id,
u8 *ul_pipe, u8 *dl_pipe)
@@ -165,9 +163,10 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
return ar->hif.ops->get_free_queue_number(ar, pipe_id);
}
-static inline int ath10k_hif_power_up(struct ath10k *ar)
+static inline int ath10k_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
- return ar->hif.ops->power_up(ar);
+ return ar->hif.ops->power_up(ar, fw_mode);
}
static inline void ath10k_hif_power_down(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 28daed5981a1..805a7f8a04f2 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
@@ -53,7 +42,7 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
{
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
- if (htc->ar->dev_type != ATH10K_DEV_TYPE_HL)
+ if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
}
@@ -88,7 +77,8 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
hdr->eid = ep->eid;
hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
hdr->flags = 0;
- hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
+ if (ep->tx_credit_flow_enabled)
+ hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
spin_lock_bh(&ep->htc->tx_lock);
hdr->seq_no = ep->seq_no++;
@@ -138,7 +128,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
ath10k_htc_prepare_tx_skb(ep, skb);
skb_cb->eid = eid;
- if (ar->dev_type != ATH10K_DEV_TYPE_HL) {
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) {
skb_cb->paddr = dma_map_single(dev, skb->data, skb->len,
DMA_TO_DEVICE);
ret = dma_mapping_error(dev, skb_cb->paddr);
@@ -161,7 +151,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return 0;
err_unmap:
- if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
err_credits:
if (ep->tx_credit_flow_enabled) {
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 51fda6c23f69..f55d3caec61f 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HTC_H_
@@ -51,7 +40,6 @@ struct ath10k;
*/
#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 8
-#define HTC_HOST_MAX_MSG_PER_TX_BUNDLE 16
enum ath10k_htc_tx_flags {
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 21a67f82f037..d235ff3098e8 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/slab.h>
@@ -268,7 +257,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
return status;
}
- status = ath10k_htt_h2t_aggr_cfg_msg(htt,
+ status = htt->tx_ops->htt_h2t_aggr_cfg_msg(htt,
htt->max_num_ampdu,
htt->max_num_amsdu);
if (status) {
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index a76f7c9e2199..4cee5492abc8 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HTT_H_
@@ -357,6 +346,13 @@ struct htt_aggr_conf {
u8 max_num_amsdu_subframes;
} __packed;
+struct htt_aggr_conf_v2 {
+ u8 max_num_ampdu_subframes;
+ /* amsdu_subframes is limited by 0x1F mask */
+ u8 max_num_amsdu_subframes;
+ u8 reserved;
+} __packed;
+
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
struct htt_mgmt_tx_desc_qca99x0 {
__le32 rate;
@@ -564,6 +560,7 @@ struct htt_mgmt_tx_completion {
#define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0)
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5)
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6)
+#define HTT_RX_INDICATION_INFO0_PPDU_DURATION BIT(7)
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0
@@ -576,7 +573,14 @@ struct htt_mgmt_tx_completion {
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_MASK 0xFF000000
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_LSB 24
-#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
+#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
+#define HTT_TX_CMPL_FLAG_PPID_PRESENT BIT(1)
+#define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2)
+#define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3)
+
+#define HTT_TX_DATA_RSSI_ENABLE_WCN3990 BIT(3)
+#define HTT_TX_DATA_APPEND_RETRIES BIT(0)
+#define HTT_TX_DATA_APPEND_TIMESTAMP BIT(1)
struct htt_rx_indication_hdr {
u8 info0; /* %HTT_RX_INDICATION_INFO0_ */
@@ -852,6 +856,88 @@ enum htt_data_tx_flags {
#define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF
+struct htt_append_retries {
+ __le16 msdu_id;
+ u8 tx_retries;
+ u8 flag;
+} __packed;
+
+struct htt_data_tx_completion_ext {
+ struct htt_append_retries a_retries;
+ __le32 t_stamp;
+ __le16 msdus_rssi[0];
+} __packed;
+
+/**
+ * @brief target -> host TX completion indication message definition
+ *
+ * @details
+ * The following diagram shows the format of the TX completion indication sent
+ * from the target to the host
+ *
+ * |31 28|27|26|25|24|23 16| 15 |14 11|10 8|7 0|
+ * |-------------------------------------------------------------|
+ * header: |rsvd |A2|TP|A1|A0| num | t_i| tid |status| msg_type |
+ * |-------------------------------------------------------------|
+ * payload: | MSDU1 ID | MSDU0 ID |
+ * |-------------------------------------------------------------|
+ * : MSDU3 ID : MSDU2 ID :
+ * |-------------------------------------------------------------|
+ * | struct htt_tx_compl_ind_append_retries |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ * | struct htt_tx_compl_ind_append_tx_tstamp |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ * | MSDU1 ACK RSSI | MSDU0 ACK RSSI |
+ * |-------------------------------------------------------------|
+ * : MSDU3 ACK RSSI : MSDU2 ACK RSSI :
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ * -msg_type
+ * Bits 7:0
+ * Purpose: identifies this as HTT TX completion indication
+ * -status
+ * Bits 10:8
+ * Purpose: the TX completion status of payload fragmentations descriptors
+ * Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD
+ * -tid
+ * Bits 14:11
+ * Purpose: the tid associated with those fragmentation descriptors. It is
+ * valid or not, depending on the tid_invalid bit.
+ * Value: 0 to 15
+ * -tid_invalid
+ * Bits 15:15
+ * Purpose: this bit indicates whether the tid field is valid or not
+ * Value: 0 indicates valid, 1 indicates invalid
+ * -num
+ * Bits 23:16
+ * Purpose: the number of payload in this indication
+ * Value: 1 to 255
+ * -A0 = append
+ * Bits 24:24
+ * Purpose: append the struct htt_tx_compl_ind_append_retries which contains
+ * the number of tx retries for one MSDU at the end of this message
+ * Value: 0 indicates no appending, 1 indicates appending
+ * -A1 = append1
+ * Bits 25:25
+ * Purpose: Append the struct htt_tx_compl_ind_append_tx_tstamp which
+ * contains the timestamp info for each TX msdu id in payload.
+ * Value: 0 indicates no appending, 1 indicates appending
+ * -TP = MSDU tx power presence
+ * Bits 26:26
+ * Purpose: Indicate whether the TX_COMPL_IND includes a tx power report
+ * for each MSDU referenced by the TX_COMPL_IND message.
+ * The order of the per-MSDU tx power reports matches the order
+ * of the MSDU IDs.
+ * Value: 0 indicates not appending, 1 indicates appending
+ * -A2 = append2
+ * Bits 27:27
+ * Purpose: Indicate whether data ACK RSSI is appended for each MSDU in
+ * TX_COMP_IND message. The order of the per-MSDU ACK RSSI report
+ * matches the order of the MSDU IDs.
+ * The ACK RSSI values are valid when status is COMPLETE_OK (and
+ * this append2 bit is set).
+ * Value: 0 indicates not appending, 1 indicates appending
+ */
+
struct htt_data_tx_completion {
union {
u8 flags;
@@ -866,6 +952,21 @@ struct htt_data_tx_completion {
__le16 msdus[0]; /* variable length based on %num_msdus */
} __packed;
+#define HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK GENMASK(15, 0)
+#define HTT_TX_PPDU_DUR_INFO0_TID_MASK GENMASK(20, 16)
+
+struct htt_data_tx_ppdu_dur {
+ __le32 info0; /* HTT_TX_PPDU_DUR_INFO0_ */
+ __le32 tx_duration; /* in usecs */
+} __packed;
+
+#define HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK GENMASK(7, 0)
+
+struct htt_data_tx_compl_ppdu_dur {
+ __le32 info0; /* HTT_TX_COMPL_PPDU_DUR_INFO0_ */
+ struct htt_data_tx_ppdu_dur ppdu_dur[0];
+} __packed;
+
struct htt_tx_compl_ind_base {
u32 hdr;
u16 payload[1/*or more*/];
@@ -1650,6 +1751,7 @@ struct htt_cmd {
struct htt_stats_req stats_req;
struct htt_oob_sync_req oob_sync_req;
struct htt_aggr_conf aggr_conf;
+ struct htt_aggr_conf_v2 aggr_conf_v2;
struct htt_frag_desc_bank_cfg32 frag_desc_bank_cfg32;
struct htt_frag_desc_bank_cfg64 frag_desc_bank_cfg64;
struct htt_tx_fetch_resp tx_fetch_resp;
@@ -1716,14 +1818,14 @@ struct ath10k_htt_txbuf_32 {
struct ath10k_htc_hdr htc_hdr;
struct htt_cmd_hdr cmd_hdr;
struct htt_data_tx_desc cmd_tx;
-} __packed;
+} __packed __aligned(4);
struct ath10k_htt_txbuf_64 {
struct htt_data_tx_desc_frag frags[2];
struct ath10k_htc_hdr htc_hdr;
struct htt_cmd_hdr cmd_hdr;
struct htt_data_tx_desc_64 cmd_tx;
-} __packed;
+} __packed __aligned(4);
struct ath10k_htt {
struct ath10k *ar;
@@ -1890,6 +1992,9 @@ struct ath10k_htt_tx_ops {
struct sk_buff *msdu);
int (*htt_alloc_txbuff)(struct ath10k_htt *htt);
void (*htt_free_txbuff)(struct ath10k_htt *htt);
+ int (*htt_h2t_aggr_cfg_msg)(struct ath10k_htt *htt,
+ u8 max_subfrms_ampdu,
+ u8 max_subfrms_amsdu);
};
static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt)
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index f42bac204ef8..a20ea270d519 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
@@ -265,7 +254,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
struct ath10k_htt *htt = &ar->htt;
int ret;
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return 0;
spin_lock_bh(&htt->rx_ring.lock);
@@ -282,7 +271,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
void ath10k_htt_rx_free(struct ath10k_htt *htt)
{
- if (htt->ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (htt->ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return;
del_timer_sync(&htt->rx_ring.refill_retry_timer);
@@ -760,7 +749,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
size_t size;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return 0;
htt->rx_confused = false;
@@ -1905,7 +1894,7 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar,
}
static int ath10k_unchain_msdu(struct sk_buff_head *amsdu,
- unsigned long int *unchain_cnt)
+ unsigned long *unchain_cnt)
{
struct sk_buff *skb, *first;
int space;
@@ -1954,8 +1943,8 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu,
static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
struct sk_buff_head *amsdu,
- unsigned long int *drop_cnt,
- unsigned long int *unchain_cnt)
+ unsigned long *drop_cnt,
+ unsigned long *unchain_cnt)
{
struct sk_buff *first;
struct htt_rx_desc *rxd;
@@ -2005,7 +1994,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
static void ath10k_htt_rx_h_filter(struct ath10k *ar,
struct sk_buff_head *amsdu,
struct ieee80211_rx_status *rx_status,
- unsigned long int *drop_cnt)
+ unsigned long *drop_cnt)
{
if (skb_queue_empty(amsdu))
return;
@@ -2025,10 +2014,10 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct sk_buff_head amsdu;
int ret;
- unsigned long int drop_cnt = 0;
- unsigned long int unchain_cnt = 0;
- unsigned long int drop_cnt_filter = 0;
- unsigned long int msdus_to_queue, num_msdus;
+ unsigned long drop_cnt = 0;
+ unsigned long unchain_cnt = 0;
+ unsigned long drop_cnt_filter = 0;
+ unsigned long msdus_to_queue, num_msdus;
enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX;
u8 first_hdr[RX_HTT_HDR_STATUS_LEN];
@@ -2130,9 +2119,15 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
hdr = (struct ieee80211_hdr *)skb->data;
rx_status = IEEE80211_SKB_RXCB(skb);
rx_status->chains |= BIT(0);
- rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
- rx->ppdu.combined_rssi;
- rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
+ if (rx->ppdu.combined_rssi == 0) {
+ /* SDIO firmware does not provide signal */
+ rx_status->signal = 0;
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ } else {
+ rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
+ rx->ppdu.combined_rssi;
+ rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
+ }
spin_lock_bh(&ar->data_lock);
ch = ar->scan_channel;
@@ -2220,8 +2215,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS);
__le16 msdu_id, *msdus;
bool rssi_enabled = false;
- u8 msdu_count = 0;
- int i;
+ u8 msdu_count = 0, num_airtime_records, tid;
+ int i, htt_pad = 0;
+ struct htt_data_tx_compl_ppdu_dur *ppdu_info;
+ struct ath10k_peer *peer;
+ u16 ppdu_info_offset = 0, peer_id;
+ u32 tx_duration;
switch (status) {
case HTT_DATA_TX_STATUS_NO_ACK:
@@ -2245,12 +2244,14 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
resp->data_tx_completion.num_msdus);
msdu_count = resp->data_tx_completion.num_msdus;
+ msdus = resp->data_tx_completion.msdus;
+ rssi_enabled = ath10k_is_rssi_enable(&ar->hw_params, resp);
- if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI)
- rssi_enabled = true;
+ if (rssi_enabled)
+ htt_pad = ath10k_tx_data_rssi_get_pad_bytes(&ar->hw_params,
+ resp);
for (i = 0; i < msdu_count; i++) {
- msdus = resp->data_tx_completion.msdus;
msdu_id = msdus[i];
tx_done.msdu_id = __le16_to_cpu(msdu_id);
@@ -2260,10 +2261,10 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
* last msdu id with 0xffff
*/
if (msdu_count & 0x01) {
- msdu_id = msdus[msdu_count + i + 1];
+ msdu_id = msdus[msdu_count + i + 1 + htt_pad];
tx_done.ack_rssi = __le16_to_cpu(msdu_id);
} else {
- msdu_id = msdus[msdu_count + i];
+ msdu_id = msdus[msdu_count + i + htt_pad];
tx_done.ack_rssi = __le16_to_cpu(msdu_id);
}
}
@@ -2282,6 +2283,50 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
ath10k_txrx_tx_unref(htt, &tx_done);
}
}
+
+ if (!(resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT))
+ return;
+
+ ppdu_info_offset = (msdu_count & 0x01) ? msdu_count + 1 : msdu_count;
+
+ if (rssi_enabled)
+ ppdu_info_offset += ppdu_info_offset;
+
+ if (resp->data_tx_completion.flags2 &
+ (HTT_TX_CMPL_FLAG_PPID_PRESENT | HTT_TX_CMPL_FLAG_PA_PRESENT))
+ ppdu_info_offset += 2;
+
+ ppdu_info = (struct htt_data_tx_compl_ppdu_dur *)&msdus[ppdu_info_offset];
+ num_airtime_records = FIELD_GET(HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK,
+ __le32_to_cpu(ppdu_info->info0));
+
+ for (i = 0; i < num_airtime_records; i++) {
+ struct htt_data_tx_ppdu_dur *ppdu_dur;
+ u32 info0;
+
+ ppdu_dur = &ppdu_info->ppdu_dur[i];
+ info0 = __le32_to_cpu(ppdu_dur->info0);
+
+ peer_id = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK,
+ info0);
+ rcu_read_lock();
+ spin_lock_bh(&ar->data_lock);
+
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer) {
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+ continue;
+ }
+
+ tid = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_TID_MASK, info0);
+ tx_duration = __le32_to_cpu(ppdu_dur->tx_duration);
+
+ ieee80211_sta_register_airtime(peer->sta, tid, tx_duration, 0);
+
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+ }
}
static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
@@ -2596,6 +2641,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb)
u8 tid;
int ret;
int i;
+ bool may_tx;
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n");
@@ -2668,8 +2714,13 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb)
num_msdus = 0;
num_bytes = 0;
+ ieee80211_txq_schedule_start(hw, txq->ac);
+ may_tx = ieee80211_txq_may_transmit(hw, txq);
while (num_msdus < max_num_msdus &&
num_bytes < max_num_bytes) {
+ if (!may_tx)
+ break;
+
ret = ath10k_mac_tx_push_txq(hw, txq);
if (ret < 0)
break;
@@ -2677,6 +2728,8 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb)
num_msdus++;
num_bytes += ret;
}
+ ieee80211_return_txq(hw, txq);
+ ieee80211_txq_schedule_end(hw, txq->ac);
record->num_msdus = cpu_to_le16(num_msdus);
record->num_bytes = cpu_to_le32(num_bytes);
@@ -2868,17 +2921,19 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
struct rate_info *txrate = &arsta->txrate;
struct ath10k_htt_tx_stats *tx_stats;
int idx, ht_idx, gi, mcs, bw, nss;
+ unsigned long flags;
if (!arsta->tx_stats)
return;
tx_stats = arsta->tx_stats;
- gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI);
- ht_idx = txrate->mcs + txrate->nss * 8;
- mcs = txrate->mcs;
+ flags = txrate->flags;
+ gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags);
+ mcs = ATH10K_HW_MCS_RATE(pstats->ratecode);
bw = txrate->bw;
nss = txrate->nss;
- idx = mcs * 8 + 8 * 10 * nss;
+ ht_idx = mcs + (nss - 1) * 8;
+ idx = mcs * 8 + 8 * 10 * (nss - 1);
idx += bw * 2 + gi;
#define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name]
@@ -2924,7 +2979,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
}
STATS_OP_FMT(AMPDU).bw[0][bw] +=
pstats->succ_bytes + pstats->retry_bytes;
- STATS_OP_FMT(AMPDU).nss[0][nss] +=
+ STATS_OP_FMT(AMPDU).nss[0][nss - 1] +=
pstats->succ_bytes + pstats->retry_bytes;
STATS_OP_FMT(AMPDU).gi[0][gi] +=
pstats->succ_bytes + pstats->retry_bytes;
@@ -2932,7 +2987,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
pstats->succ_bytes + pstats->retry_bytes;
STATS_OP_FMT(AMPDU).bw[1][bw] +=
pstats->succ_pkts + pstats->retry_pkts;
- STATS_OP_FMT(AMPDU).nss[1][nss] +=
+ STATS_OP_FMT(AMPDU).nss[1][nss - 1] +=
pstats->succ_pkts + pstats->retry_pkts;
STATS_OP_FMT(AMPDU).gi[1][gi] +=
pstats->succ_pkts + pstats->retry_pkts;
@@ -2944,27 +2999,27 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
}
STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes;
- STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes;
+ STATS_OP_FMT(SUCC).nss[0][nss - 1] += pstats->succ_bytes;
STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes;
STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts;
- STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts;
+ STATS_OP_FMT(SUCC).nss[1][nss - 1] += pstats->succ_pkts;
STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts;
STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes;
- STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes;
+ STATS_OP_FMT(FAIL).nss[0][nss - 1] += pstats->failed_bytes;
STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes;
STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts;
- STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts;
+ STATS_OP_FMT(FAIL).nss[1][nss - 1] += pstats->failed_pkts;
STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts;
STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes;
- STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes;
+ STATS_OP_FMT(RETRY).nss[0][nss - 1] += pstats->retry_bytes;
STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes;
STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts;
- STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts;
+ STATS_OP_FMT(RETRY).nss[1][nss - 1] += pstats->retry_pkts;
STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts;
if (txrate->flags >= RATE_INFO_FLAGS_MCS) {
@@ -2975,6 +3030,8 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
STATS_OP_FMT(RETRY).rate_table[0][idx] += pstats->retry_bytes;
STATS_OP_FMT(RETRY).rate_table[1][idx] += pstats->retry_pkts;
}
+
+ tx_stats->tx_duration += pstats->duration;
}
static void
@@ -3070,6 +3127,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.nss = txrate.nss;
arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw);
+ arsta->last_tx_bitrate = cfg80211_calculate_bitrate(&arsta->txrate);
if (sgi)
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
@@ -3141,6 +3199,7 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts);
p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts);
p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts);
+ p_tx_stats->duration = __le16_to_cpu(tx_stats->tx_duration);
ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats);
}
@@ -3234,7 +3293,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
}
case HTT_T2H_MSG_TYPE_RX_IND:
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return ath10k_htt_rx_proc_rx_ind_hl(htt,
&resp->rx_ind_hl,
skb);
@@ -3530,7 +3589,7 @@ void ath10k_htt_set_rx_ops(struct ath10k_htt *htt)
{
struct ath10k *ar = htt->ar;
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
htt->rx_ops = &htt_rx_ops_hl;
else if (ar->hw_params.target_64bit)
htt->rx_ops = &htt_rx_ops_64;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index ad05ab714c9b..d8e9cc0bb772 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/etherdevice.h>
@@ -495,7 +484,7 @@ int ath10k_htt_tx_start(struct ath10k_htt *htt)
if (htt->tx_mem_allocated)
return 0;
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return 0;
ret = ath10k_htt_tx_alloc_buf(htt);
@@ -1035,6 +1024,53 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
return 0;
}
+static int ath10k_htt_h2t_aggr_cfg_msg_v2(struct ath10k_htt *htt,
+ u8 max_subfrms_ampdu,
+ u8 max_subfrms_amsdu)
+{
+ struct ath10k *ar = htt->ar;
+ struct htt_aggr_conf_v2 *aggr_conf;
+ struct sk_buff *skb;
+ struct htt_cmd *cmd;
+ int len;
+ int ret;
+
+ /* Firmware defaults are: amsdu = 3 and ampdu = 64 */
+
+ if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
+ return -EINVAL;
+
+ if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
+ return -EINVAL;
+
+ len = sizeof(cmd->hdr);
+ len += sizeof(cmd->aggr_conf_v2);
+
+ skb = ath10k_htc_alloc_skb(ar, len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+ cmd = (struct htt_cmd *)skb->data;
+ cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
+
+ aggr_conf = &cmd->aggr_conf_v2;
+ aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
+ aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
+
+ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
+ aggr_conf->max_num_amsdu_subframes,
+ aggr_conf->max_num_ampdu_subframes);
+
+ ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ return 0;
+}
+
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
__le32 token,
__le16 fetch_seq_num,
@@ -1177,7 +1213,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
return 0;
err_unmap_msdu:
- if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
err_free_txdesc:
dev_kfree_skb_any(txdesc);
@@ -1498,7 +1534,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt,
u16 msdu_id, flags1 = 0;
u16 freq = 0;
dma_addr_t frags_paddr = 0;
- u32 txbuf_paddr;
+ dma_addr_t txbuf_paddr;
struct htt_msdu_ext_desc_64 *ext_desc = NULL;
struct htt_msdu_ext_desc_64 *ext_desc_t = NULL;
@@ -1692,6 +1728,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_32 = {
.htt_tx = ath10k_htt_tx_32,
.htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_32,
.htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_32,
+ .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg,
};
static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
@@ -1702,6 +1739,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
.htt_tx = ath10k_htt_tx_64,
.htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_64,
.htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_64,
+ .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_v2,
};
static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
@@ -1714,7 +1752,7 @@ void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
{
struct ath10k *ar = htt->ar;
- if (ar->dev_type == ATH10K_DEV_TYPE_HL)
+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
htt->tx_ops = &htt_tx_ops_hl;
else if (ar->hw_params.target_64bit)
htt->tx_ops = &htt_tx_ops_64;
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 61ecf931ba4d..ad082b7d7643 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/types.h>
@@ -318,9 +307,11 @@ static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = {
};
const struct ath10k_hw_ce_regs wcn3990_ce_regs = {
- .sr_base_addr = 0x00000000,
+ .sr_base_addr_lo = 0x00000000,
+ .sr_base_addr_hi = 0x00000004,
.sr_size_addr = 0x00000008,
- .dr_base_addr = 0x0000000c,
+ .dr_base_addr_lo = 0x0000000c,
+ .dr_base_addr_hi = 0x00000010,
.dr_size_addr = 0x00000014,
.misc_ie_addr = 0x00000034,
.sr_wr_index_addr = 0x0000003c,
@@ -464,9 +455,9 @@ static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
};
const struct ath10k_hw_ce_regs qcax_ce_regs = {
- .sr_base_addr = 0x00000000,
+ .sr_base_addr_lo = 0x00000000,
.sr_size_addr = 0x00000004,
- .dr_base_addr = 0x00000008,
+ .dr_base_addr_lo = 0x00000008,
.dr_size_addr = 0x0000000c,
.ce_cmd_addr = 0x00000018,
.misc_ie_addr = 0x00000034,
@@ -1109,6 +1100,32 @@ int ath10k_hw_diag_fast_download(struct ath10k *ar,
return ret;
}
+static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp)
+{
+ return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI);
+}
+
+static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp)
+{
+ return (resp->data_tx_completion.flags2 &
+ HTT_TX_DATA_RSSI_ENABLE_WCN3990);
+}
+
+static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp)
+{
+ struct htt_data_tx_completion_ext extd;
+ int pad_bytes = 0;
+
+ if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES)
+ pad_bytes += sizeof(extd.a_retries) /
+ sizeof(extd.msdus_rssi[0]);
+
+ if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP)
+ pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]);
+
+ return pad_bytes;
+}
+
const struct ath10k_hw_ops qca988x_ops = {
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
};
@@ -1133,6 +1150,10 @@ const struct ath10k_hw_ops qca99x0_ops = {
const struct ath10k_hw_ops qca6174_ops = {
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
};
-const struct ath10k_hw_ops wcn3990_ops = {};
+const struct ath10k_hw_ops wcn3990_ops = {
+ .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
+};
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index e50a8dc5b093..71314999aa24 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HW_H_
@@ -353,9 +342,11 @@ struct ath10k_hw_ce_ctrl1_upd {
};
struct ath10k_hw_ce_regs {
- u32 sr_base_addr;
+ u32 sr_base_addr_lo;
+ u32 sr_base_addr_hi;
u32 sr_size_addr;
- u32 dr_base_addr;
+ u32 dr_base_addr_lo;
+ u32 dr_base_addr_hi;
u32 dr_size_addr;
u32 ce_cmd_addr;
u32 misc_ie_addr;
@@ -618,6 +609,8 @@ struct ath10k_hw_params {
};
struct htt_rx_desc;
+struct htt_resp;
+struct htt_data_tx_completion_ext;
/* Defines needed for Rx descriptor abstraction */
struct ath10k_hw_ops {
@@ -625,6 +618,8 @@ struct ath10k_hw_ops {
void (*set_coverage_class)(struct ath10k *ar, s16 value);
int (*enable_pll_clk)(struct ath10k *ar);
bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd);
+ int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt);
+ int (*is_rssi_enable)(struct htt_resp *resp);
};
extern const struct ath10k_hw_ops qca988x_ops;
@@ -652,6 +647,24 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw,
return false;
}
+static inline int
+ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw,
+ struct htt_resp *htt)
+{
+ if (hw->hw_ops->tx_data_rssi_pad_bytes)
+ return hw->hw_ops->tx_data_rssi_pad_bytes(htt);
+ return 0;
+}
+
+static inline int
+ath10k_is_rssi_enable(struct ath10k_hw_params *hw,
+ struct htt_resp *resp)
+{
+ if (hw->hw_ops->is_rssi_enable)
+ return hw->hw_ops->is_rssi_enable(resp);
+ return 0;
+}
+
/* Target specific defines for MAIN firmware */
#define TARGET_NUM_VDEVS 8
#define TARGET_NUM_PEER_AST 2
@@ -734,13 +747,14 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw,
#define TARGET_TLV_NUM_TDLS_VDEVS 1
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
+#define TARGET_TLV_NUM_MSDU_DESC_HL 64
#define TARGET_TLV_NUM_WOW_PATTERNS 22
#define TARGET_TLV_MGMT_NUM_MSDU_DESC (50)
/* Target specific defines for WMI-HL-1.0 firmware */
-#define TARGET_HL_10_TLV_NUM_PEERS 14
-#define TARGET_HL_10_TLV_AST_SKID_LIMIT 6
-#define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2
+#define TARGET_HL_TLV_NUM_PEERS 33
+#define TARGET_HL_TLV_AST_SKID_LIMIT 16
+#define TARGET_HL_TLV_NUM_WDS_ENTRIES 2
/* Diagnostic Window */
#define CE_DIAG_PIPE 7
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e49b36752ba2..b73c23d4ce86 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#include "mac.h"
@@ -250,24 +239,24 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
- arg.key_cipher = WMI_CIPHER_AES_CCM;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM];
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
break;
case WLAN_CIPHER_SUITE_TKIP:
- arg.key_cipher = WMI_CIPHER_TKIP;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_TKIP];
arg.key_txmic_len = 8;
arg.key_rxmic_len = 8;
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
- arg.key_cipher = WMI_CIPHER_WEP;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_WEP];
break;
case WLAN_CIPHER_SUITE_CCMP_256:
- arg.key_cipher = WMI_CIPHER_AES_CCM;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM];
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- arg.key_cipher = WMI_CIPHER_AES_GCM;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM];
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
@@ -284,7 +273,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (cmd == DISABLE_KEY) {
- arg.key_cipher = WMI_CIPHER_NONE;
+ arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_NONE];
arg.key_data = NULL;
}
@@ -3397,6 +3386,7 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
struct sk_buff *skb)
{
const struct ieee80211_hdr *hdr = (void *)skb->data;
+ const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
__le16 fc = hdr->frame_control;
if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
@@ -3438,7 +3428,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
if (ieee80211_is_data_present(fc) && sta && sta->tdls)
return ATH10K_HW_TXRX_ETHERNET;
- if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
+ if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) ||
+ skb_cb->flags & ATH10K_SKB_F_RAW_TX)
return ATH10K_HW_TXRX_RAW;
return ATH10K_HW_TXRX_NATIVE_WIFI;
@@ -3544,10 +3535,13 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_txq *txq,
- struct sk_buff *skb)
+ struct sk_buff *skb, u16 airtime)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+ const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ bool is_data = ieee80211_is_data(hdr->frame_control) ||
+ ieee80211_is_data_qos(hdr->frame_control);
cb->flags = 0;
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
@@ -3559,8 +3553,19 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
if (ieee80211_is_data_qos(hdr->frame_control))
cb->flags |= ATH10K_SKB_F_QOS;
+ /* Data frames encrypted in software will be posted to firmware
+ * with tx encap mode set to RAW. Ex: Multicast traffic generated
+ * for a specific VLAN group will always be encrypted in software.
+ */
+ if (is_data && ieee80211_has_protected(hdr->frame_control) &&
+ !info->control.hw_key) {
+ cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
+ cb->flags |= ATH10K_SKB_F_RAW_TX;
+ }
+
cb->vif = vif;
cb->txq = txq;
+ cb->airtime_est = airtime;
}
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
@@ -3667,6 +3672,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
{
struct ieee80211_hw *hw = ar->hw;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
int ret;
/* We should disable CCK RATE due to P2P */
@@ -3684,7 +3690,8 @@ static int ath10k_mac_tx(struct ath10k *ar,
ath10k_tx_h_8023(skb);
break;
case ATH10K_HW_TXRX_RAW:
- if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
+ !(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) {
WARN_ON_ONCE(1);
ieee80211_free_txskb(hw, skb);
return -ENOTSUPP;
@@ -3863,7 +3870,7 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n",
ret);
dma_unmap_single(ar->dev, paddr, skb->len,
- DMA_FROM_DEVICE);
+ DMA_TO_DEVICE);
ieee80211_free_txskb(ar->hw, skb);
}
} else {
@@ -3890,7 +3897,6 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
{
- struct ath10k_txq *artxq;
struct ath10k_skb_cb *cb;
struct sk_buff *msdu;
int msdu_id;
@@ -3898,12 +3904,6 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
if (!txq)
return;
- artxq = (void *)txq->drv_priv;
- spin_lock_bh(&ar->txqs_lock);
- if (!list_empty(&artxq->list))
- list_del_init(&artxq->list);
- spin_unlock_bh(&ar->txqs_lock);
-
spin_lock_bh(&ar->htt.tx_lock);
idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) {
cb = ATH10K_SKB_CB(msdu);
@@ -3943,7 +3943,6 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw,
struct ath10k_txq *artxq = (void *)txq->drv_priv;
/* No need to get locks */
-
if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH)
return true;
@@ -3956,6 +3955,52 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw,
return false;
}
+/* Return estimated airtime in microsecond, which is calculated using last
+ * reported TX rate. This is just a rough estimation because host driver has no
+ * knowledge of the actual transmit rate, retries or aggregation. If actual
+ * airtime can be reported by firmware, then delta between estimated and actual
+ * airtime can be adjusted from deficit.
+ */
+#define IEEE80211_ATF_OVERHEAD 100 /* IFS + some slot time */
+#define IEEE80211_ATF_OVERHEAD_IFS 16 /* IFS only */
+static u16 ath10k_mac_update_airtime(struct ath10k *ar,
+ struct ieee80211_txq *txq,
+ struct sk_buff *skb)
+{
+ struct ath10k_sta *arsta;
+ u32 pktlen;
+ u16 airtime = 0;
+
+ if (!txq || !txq->sta)
+ return airtime;
+
+ if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
+ return airtime;
+
+ spin_lock_bh(&ar->data_lock);
+ arsta = (struct ath10k_sta *)txq->sta->drv_priv;
+
+ pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */
+ if (arsta->last_tx_bitrate) {
+ /* airtime in us, last_tx_bitrate in 100kbps */
+ airtime = (pktlen * 8 * (1000 / 100))
+ / arsta->last_tx_bitrate;
+ /* overhead for media access time and IFS */
+ airtime += IEEE80211_ATF_OVERHEAD_IFS;
+ } else {
+ /* This is mostly for throttle excessive BC/MC frames, and the
+ * airtime/rate doesn't need be exact. Airtime of BC/MC frames
+ * in 2G get some discount, which helps prevent very low rate
+ * frames from being blocked for too long.
+ */
+ airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */
+ airtime += IEEE80211_ATF_OVERHEAD;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
+ return airtime;
+}
+
int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
@@ -3971,6 +4016,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
size_t skb_len;
bool is_mgmt, is_presp;
int ret;
+ u16 airtime;
spin_lock_bh(&ar->htt.tx_lock);
ret = ath10k_htt_tx_inc_pending(htt);
@@ -3988,7 +4034,8 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
return -ENOENT;
}
- ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
+ airtime = ath10k_mac_update_airtime(ar, txq, skb);
+ ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
skb_len = skb->len;
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
@@ -4030,48 +4077,45 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
return skb_len;
}
-void ath10k_mac_tx_push_pending(struct ath10k *ar)
+static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac)
{
- struct ieee80211_hw *hw = ar->hw;
struct ieee80211_txq *txq;
- struct ath10k_txq *artxq;
- struct ath10k_txq *last;
- int ret;
- int max;
-
- if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
- return;
-
- spin_lock_bh(&ar->txqs_lock);
- rcu_read_lock();
-
- last = list_last_entry(&ar->txqs, struct ath10k_txq, list);
- while (!list_empty(&ar->txqs)) {
- artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
- txq = container_of((void *)artxq, struct ieee80211_txq,
- drv_priv);
+ int ret = 0;
- /* Prevent aggressive sta/tid taking over tx queue */
- max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE;
- ret = 0;
- while (ath10k_mac_tx_can_push(hw, txq) && max--) {
+ ieee80211_txq_schedule_start(hw, ac);
+ while ((txq = ieee80211_next_txq(hw, ac))) {
+ while (ath10k_mac_tx_can_push(hw, txq)) {
ret = ath10k_mac_tx_push_txq(hw, txq);
if (ret < 0)
break;
}
+ ieee80211_return_txq(hw, txq);
+ ath10k_htt_tx_txq_update(hw, txq);
+ if (ret == -EBUSY)
+ break;
+ }
+ ieee80211_txq_schedule_end(hw, ac);
- list_del_init(&artxq->list);
- if (ret != -ENOENT)
- list_add_tail(&artxq->list, &ar->txqs);
+ return ret;
+}
- ath10k_htt_tx_txq_update(hw, txq);
+void ath10k_mac_tx_push_pending(struct ath10k *ar)
+{
+ struct ieee80211_hw *hw = ar->hw;
+ u32 ac;
+
+ if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
+ return;
+
+ if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
+ return;
- if (artxq == last || (ret < 0 && ret != -ENOENT))
+ rcu_read_lock();
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ if (ath10k_mac_schedule_txq(hw, ac) == -EBUSY)
break;
}
-
rcu_read_unlock();
- spin_unlock_bh(&ar->txqs_lock);
}
EXPORT_SYMBOL(ath10k_mac_tx_push_pending);
@@ -4258,8 +4302,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
bool is_mgmt;
bool is_presp;
int ret;
+ u16 airtime;
- ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
+ airtime = ath10k_mac_update_airtime(ar, txq, skb);
+ ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
@@ -4310,31 +4356,28 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct ath10k *ar = hw->priv;
- struct ath10k_txq *artxq = (void *)txq->drv_priv;
- struct ieee80211_txq *f_txq;
- struct ath10k_txq *f_artxq;
- int ret = 0;
- int max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE;
+ int ret;
+ u8 ac;
- spin_lock_bh(&ar->txqs_lock);
- if (list_empty(&artxq->list))
- list_add_tail(&artxq->list, &ar->txqs);
+ ath10k_htt_tx_txq_update(hw, txq);
+ if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
+ return;
- f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
- f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv);
- list_del_init(&f_artxq->list);
+ ac = txq->ac;
+ ieee80211_txq_schedule_start(hw, ac);
+ txq = ieee80211_next_txq(hw, ac);
+ if (!txq)
+ goto out;
- while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
- ret = ath10k_mac_tx_push_txq(hw, f_txq);
+ while (ath10k_mac_tx_can_push(hw, txq)) {
+ ret = ath10k_mac_tx_push_txq(hw, txq);
if (ret < 0)
break;
}
- if (ret != -ENOENT)
- list_add_tail(&f_artxq->list, &ar->txqs);
- spin_unlock_bh(&ar->txqs_lock);
-
- ath10k_htt_tx_txq_update(hw, f_txq);
+ ieee80211_return_txq(hw, txq);
ath10k_htt_tx_txq_update(hw, txq);
+out:
+ ieee80211_txq_schedule_end(hw, ac);
}
/* Must not be called with conf_mutex held as workers can use that also. */
@@ -4549,7 +4592,8 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
ht_cap.cap |= stbc;
}
- if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
+ if (ar->ht_cap_info & WMI_HT_CAP_LDPC || (ar->ht_cap_info &
+ WMI_HT_CAP_RX_LDPC && (ar->ht_cap_info & WMI_HT_CAP_TX_LDPC)))
ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
@@ -4704,7 +4748,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err;
}
- ret = ath10k_hif_power_up(ar);
+ ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "Could not init hif: %d\n", ret);
goto err_off;
@@ -5169,10 +5213,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_AP) {
- arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
- IEEE80211_MAX_FRAME_LEN,
- &arvif->beacon_paddr,
- GFP_ATOMIC);
+ arvif->beacon_buf = dma_alloc_coherent(ar->dev,
+ IEEE80211_MAX_FRAME_LEN,
+ &arvif->beacon_paddr,
+ GFP_ATOMIC);
if (!arvif->beacon_buf) {
ret = -ENOMEM;
ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
@@ -5341,6 +5385,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_peer_delete;
}
+ if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) {
+ vdev_param = ar->wmi.vdev_param->rtt_responder_role;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+ arvif->ftm_responder);
+
+ /* It is harmless to not set FTM role. Do not warn */
+ if (ret && ret != -EOPNOTSUPP)
+ ath10k_warn(ar, "failed to set vdev %i FTM Responder: %d\n",
+ arvif->vdev_id, ret);
+ }
+
if (vif->type == NL80211_IFTYPE_MONITOR) {
ar->monitor_arvif = arvif;
ret = ath10k_monitor_recalc(ar);
@@ -5615,6 +5670,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
ether_addr_copy(arvif->bssid, info->bssid);
+ if (changed & BSS_CHANGED_FTM_RESPONDER &&
+ arvif->ftm_responder != info->ftm_responder &&
+ test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) {
+ arvif->ftm_responder = info->ftm_responder;
+
+ vdev_param = ar->wmi.vdev_param->rtt_responder_role;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+ arvif->ftm_responder);
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac vdev %d ftm_responder %d:ret %d\n",
+ arvif->vdev_id, arvif->ftm_responder, ret);
+ }
+
if (changed & BSS_CHANGED_BEACON_ENABLED)
ath10k_control_beaconing(arvif, info);
@@ -8617,6 +8686,15 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+ if (ath10k_peer_stats_enabled(ar) ||
+ test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
+
+ if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map))
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
@@ -8726,12 +8804,19 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+ ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
+
ret = ieee80211_register_hw(ar->hw);
if (ret) {
ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
goto err_dfs_detector_exit;
}
+ if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) {
+ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+ ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
+ }
+
if (!ath_is_world_regd(&ar->ath_common.regulatory)) {
ret = regulatory_hint(ar->hw->wiphy,
ar->ath_common.regulatory.alpha2);
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 570493d2d648..1fe84948b868 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MAC_H_
diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c
index 7e621ee194e3..29c737b2f432 100644
--- a/drivers/net/wireless/ath/ath10k/p2p.c
+++ b/drivers/net/wireless/ath/ath10k/p2p.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2015 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
diff --git a/drivers/net/wireless/ath/ath10k/p2p.h b/drivers/net/wireless/ath/ath10k/p2p.h
index 7be616e2e121..7d7f44809fbb 100644
--- a/drivers/net/wireless/ath/ath10k/p2p.h
+++ b/drivers/net/wireless/ath/ath10k/p2p.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2015 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _P2P_H
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 01b4edb00e9e..271f92c24d44 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/pci.h>
@@ -913,7 +902,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
int nbytes)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce *ce = ath10k_ce_priv(ar);
int ret = 0;
u32 *buf;
unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
@@ -924,8 +912,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
void *data_buf = NULL;
int i;
- spin_lock_bh(&ce->ce_lock);
-
+ mutex_lock(&ar_pci->ce_diag_mutex);
ce_diag = ar_pci->ce_diag;
/*
@@ -936,8 +923,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
*/
alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
- data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev,
- alloc_nbytes,
+ data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, alloc_nbytes,
&ce_data_base,
GFP_ATOMIC);
@@ -961,19 +947,17 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
nbytes = min_t(unsigned int, remaining_bytes,
DIAG_TRANSFER_LIMIT);
- ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &ce_data, ce_data);
+ ret = ath10k_ce_rx_post_buf(ce_diag, &ce_data, ce_data);
if (ret != 0)
goto done;
/* Request CE to send from Target(!) address to Host buffer */
- ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
- 0);
+ ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, 0);
if (ret)
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag,
- NULL) != 0) {
+ while (ath10k_ce_completed_send_next(ce_diag, NULL) != 0) {
udelay(DIAG_ACCESS_CE_WAIT_US);
i += DIAG_ACCESS_CE_WAIT_US;
@@ -984,10 +968,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
}
i = 0;
- while (ath10k_ce_completed_recv_next_nolock(ce_diag,
- (void **)&buf,
- &completed_nbytes)
- != 0) {
+ while (ath10k_ce_completed_recv_next(ce_diag, (void **)&buf,
+ &completed_nbytes) != 0) {
udelay(DIAG_ACCESS_CE_WAIT_US);
i += DIAG_ACCESS_CE_WAIT_US;
@@ -1020,7 +1002,7 @@ done:
dma_free_coherent(ar->dev, alloc_nbytes, data_buf,
ce_data_base);
- spin_unlock_bh(&ce->ce_lock);
+ mutex_unlock(&ar_pci->ce_diag_mutex);
return ret;
}
@@ -1068,7 +1050,6 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
const void *data, int nbytes)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_ce *ce = ath10k_ce_priv(ar);
int ret = 0;
u32 *buf;
unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
@@ -1077,8 +1058,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
dma_addr_t ce_data_base = 0;
int i;
- spin_lock_bh(&ce->ce_lock);
-
+ mutex_lock(&ar_pci->ce_diag_mutex);
ce_diag = ar_pci->ce_diag;
/*
@@ -1119,7 +1099,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
memcpy(data_buf, data, nbytes);
/* Set up to receive directly into Target(!) address */
- ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &address, address);
+ ret = ath10k_ce_rx_post_buf(ce_diag, &address, address);
if (ret != 0)
goto done;
@@ -1127,14 +1107,12 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
* Request CE to send caller-supplied data that
* was copied to bounce buffer to Target(!) address.
*/
- ret = ath10k_ce_send_nolock(ce_diag, NULL, ce_data_base,
- nbytes, 0, 0);
+ ret = ath10k_ce_send(ce_diag, NULL, ce_data_base, nbytes, 0, 0);
if (ret != 0)
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag,
- NULL) != 0) {
+ while (ath10k_ce_completed_send_next(ce_diag, NULL) != 0) {
udelay(DIAG_ACCESS_CE_WAIT_US);
i += DIAG_ACCESS_CE_WAIT_US;
@@ -1145,10 +1123,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
}
i = 0;
- while (ath10k_ce_completed_recv_next_nolock(ce_diag,
- (void **)&buf,
- &completed_nbytes)
- != 0) {
+ while (ath10k_ce_completed_recv_next(ce_diag, (void **)&buf,
+ &completed_nbytes) != 0) {
udelay(DIAG_ACCESS_CE_WAIT_US);
i += DIAG_ACCESS_CE_WAIT_US;
@@ -1183,7 +1159,7 @@ done:
ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
address, ret);
- spin_unlock_bh(&ce->ce_lock);
+ mutex_unlock(&ar_pci->ce_diag_mutex);
return ret;
}
@@ -2284,7 +2260,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
return 1;
case QCA6164_2_1_DEVICE_ID:
case QCA6174_2_1_DEVICE_ID:
- switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) {
+ switch (MS(ar->bus_param.chip_id, SOC_CHIP_ID_REV)) {
case QCA6174_HW_1_0_CHIP_ID_REV:
case QCA6174_HW_1_1_CHIP_ID_REV:
case QCA6174_HW_2_1_CHIP_ID_REV:
@@ -2807,7 +2783,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
return ar_pci->pci_hard_reset(ar);
}
-static int ath10k_pci_hif_power_up(struct ath10k *ar)
+static int ath10k_pci_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
@@ -3463,6 +3440,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
spin_lock_init(&ce->ce_lock);
spin_lock_init(&ar_pci->ps_lock);
+ mutex_init(&ar_pci->ce_diag_mutex);
timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0);
@@ -3554,7 +3532,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
case QCA9377_1_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA9377;
pci_ps = true;
- pci_soft_reset = NULL;
+ pci_soft_reset = ath10k_pci_warm_reset;
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
targ_cpu_to_ce_addr = ath10k_pci_qca6174_targ_cpu_to_ce_addr;
break;
@@ -3637,6 +3615,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
}
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+ bus_params.link_can_suspend = true;
bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
if (bus_params.chip_id == 0xffffffff) {
ath10k_err(ar, "failed to get chip id\n");
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index e8d86331c539..3773c79f322f 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -1,24 +1,14 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _PCI_H_
#define _PCI_H_
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include "hw.h"
#include "ce.h"
@@ -128,6 +118,8 @@ struct ath10k_pci {
/* Copy Engine used for Diagnostic Accesses */
struct ath10k_ce_pipe *ce_diag;
+ /* For protecting ce_diag */
+ struct mutex ce_diag_mutex;
struct ath10k_ce ce;
struct timer_list rx_post_retry;
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 37b3bd629f48..a7bc2c70d076 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/completion.h>
diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h
index 1efe1d22fc2f..e4aa20445666 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.h
+++ b/drivers/net/wireless/ath/ath10k/qmi.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _ATH10K_QMI_H_
#define _ATH10K_QMI_H_
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
index ba79c2e4aed6..1fe05c6218c3 100644
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/soc/qcom/qmi.h>
@@ -1763,14 +1752,239 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
daemon_support_valid),
},
{
- .data_type = QMI_UNSIGNED_1_BYTE,
+ .data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
- .elem_size = sizeof(u8),
+ .elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct wlfw_host_cap_req_msg_v01,
daemon_support),
},
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ wake_msi_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ wake_msi),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ gpios_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ gpios_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = QMI_WLFW_MAX_NUM_GPIO_V01,
+ .elem_size = sizeof(u32),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ gpios),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ nm_modem_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ nm_modem),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ bdf_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ bdf_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ bdf_cache_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ bdf_cache_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ m3_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ m3_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x17,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ m3_cache_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x17,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ m3_cache_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x18,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_filesys_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x18,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_filesys_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x19,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_cache_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x19,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_cache_support),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1A,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_done_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1A,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ cal_done),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1B,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ mem_bucket_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1B,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ mem_bucket),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1C,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ mem_cfg_mode_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x1C,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ mem_cfg_mode),
+ },
{}
};
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
index c5e3870b8871..bca1186e1560 100644
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WCN3990_QMI_SVC_V01_H
@@ -553,12 +542,38 @@ struct wlfw_mac_addr_resp_msg_v01 {
#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[];
+#define QMI_WLFW_MAX_NUM_GPIO_V01 32
struct wlfw_host_cap_req_msg_v01 {
u8 daemon_support_valid;
- u8 daemon_support;
-};
-
-#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 4
+ u32 daemon_support;
+ u8 wake_msi_valid;
+ u32 wake_msi;
+ u8 gpios_valid;
+ u32 gpios_len;
+ u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01];
+ u8 nm_modem_valid;
+ u8 nm_modem;
+ u8 bdf_support_valid;
+ u8 bdf_support;
+ u8 bdf_cache_support_valid;
+ u8 bdf_cache_support;
+ u8 m3_support_valid;
+ u8 m3_support;
+ u8 m3_cache_support_valid;
+ u8 m3_cache_support;
+ u8 cal_filesys_support_valid;
+ u8 cal_filesys_support;
+ u8 cal_cache_support_valid;
+ u8 cal_cache_support;
+ u8 cal_done_valid;
+ u8 cal_done;
+ u8 mem_bucket_valid;
+ u32 mem_bucket;
+ u8 mem_cfg_mode_valid;
+ u8 mem_cfg_mode;
+};
+
+#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
struct wlfw_host_cap_resp_msg_v01 {
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index dfbfe674e11e..dec1582005b9 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _RX_DESC_H_
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 983ecfef1d28..fae56c67766f 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
@@ -1381,7 +1370,8 @@ static int ath10k_sdio_hif_disable_intrs(struct ath10k *ar)
return ret;
}
-static int ath10k_sdio_hif_power_up(struct ath10k *ar)
+static int ath10k_sdio_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
struct sdio_func *func = ar_sdio->func;
@@ -1392,6 +1382,12 @@ static int ath10k_sdio_hif_power_up(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n");
+ ret = ath10k_sdio_config(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to config sdio: %d\n", ret);
+ return ret;
+ }
+
sdio_claim_host(func);
ret = sdio_enable_func(func);
@@ -1429,11 +1425,19 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar)
/* Disable the card */
sdio_claim_host(ar_sdio->func);
+
ret = sdio_disable_func(ar_sdio->func);
- sdio_release_host(ar_sdio->func);
+ if (ret) {
+ ath10k_warn(ar, "unable to disable sdio function: %d\n", ret);
+ sdio_release_host(ar_sdio->func);
+ return;
+ }
+ ret = mmc_hw_reset(ar_sdio->func->card->host);
if (ret)
- ath10k_warn(ar, "unable to disable sdio function: %d\n", ret);
+ ath10k_warn(ar, "unable to reset sdio: %d\n", ret);
+
+ sdio_release_host(ar_sdio->func);
ar_sdio->is_disabled = true;
}
@@ -1615,12 +1619,33 @@ static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address,
return 0;
}
+static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ u32 addr, val;
+ int ret = 0;
+
+ addr = host_interest_item_address(HI_ITEM(hi_acs_flags));
+
+ ret = ath10k_sdio_hif_diag_read32(ar, addr, &val);
+ if (ret) {
+ ath10k_warn(ar, "unable to read hi_acs_flags : %d\n", ret);
+ return ret;
+ }
+
+ if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) {
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio mailbox swap service enabled\n");
+ ar_sdio->swap_mbox = true;
+ }
+ return 0;
+}
+
/* HIF start/stop */
static int ath10k_sdio_hif_start(struct ath10k *ar)
{
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
- u32 addr, val;
int ret;
/* Sleep 20 ms before HIF interrupts are disabled.
@@ -1654,20 +1679,6 @@ static int ath10k_sdio_hif_start(struct ath10k *ar)
if (ret)
ath10k_warn(ar, "failed to enable sdio interrupts: %d\n", ret);
- addr = host_interest_item_address(HI_ITEM(hi_acs_flags));
-
- ret = ath10k_sdio_hif_diag_read32(ar, addr, &val);
- if (ret) {
- ath10k_warn(ar, "unable to read hi_acs_flags address: %d\n", ret);
- return ret;
- }
-
- if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) {
- ath10k_dbg(ar, ATH10K_DBG_SDIO,
- "sdio mailbox swap service enabled\n");
- ar_sdio->swap_mbox = true;
- }
-
/* Enable sleep and then disable it again */
ret = ath10k_sdio_hif_set_mbox_sleep(ar, true);
if (ret)
@@ -1898,6 +1909,7 @@ static const struct ath10k_hif_ops ath10k_sdio_hif_ops = {
.exchange_bmi_msg = ath10k_sdio_bmi_exchange_msg,
.start = ath10k_sdio_hif_start,
.stop = ath10k_sdio_hif_stop,
+ .swap_mailbox = ath10k_sdio_hif_swap_mailbox,
.map_service_to_pipe = ath10k_sdio_hif_map_service_to_pipe,
.get_default_pipe = ath10k_sdio_hif_get_default_pipe,
.send_complete_check = ath10k_sdio_hif_send_complete_check,
@@ -2030,12 +2042,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
ath10k_sdio_set_mbox_info(ar);
- ret = ath10k_sdio_config(ar);
- if (ret) {
- ath10k_err(ar, "failed to config sdio: %d\n", ret);
- goto err_free_wq;
- }
-
bus_params.dev_type = ATH10K_DEV_TYPE_HL;
/* TODO: don't know yet how to get chip_id with SDIO */
bus_params.chip_id = 0;
@@ -2088,7 +2094,10 @@ static struct sdio_driver ath10k_sdio_driver = {
.id_table = ath10k_sdio_devices,
.probe = ath10k_sdio_probe,
.remove = ath10k_sdio_remove,
- .drv.pm = ATH10K_SDIO_PM_OPS,
+ .drv = {
+ .owner = THIS_MODULE,
+ .pm = ATH10K_SDIO_PM_OPS,
+ },
};
static int __init ath10k_sdio_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
index 453eb6263143..b8c7ac0330bd 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDIO_H_
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 54efe6be8f1d..873cb4ce419b 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/clk.h>
@@ -30,6 +19,7 @@
#define ATH10K_SNOC_RX_POST_RETRY_MS 50
#define CE_POLL_PIPE 4
+#define ATH10K_SNOC_WAKE_IRQ 2
static char *const ce_name[] = {
"WLAN_CE_0",
@@ -66,7 +56,7 @@ static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
static const struct ath10k_snoc_drv_priv drv_priv = {
.hw_rev = ATH10K_HW_WCN3990,
- .dma_mask = DMA_BIT_MASK(37),
+ .dma_mask = DMA_BIT_MASK(35),
.msa_size = 0x100000,
};
@@ -875,13 +865,11 @@ static void ath10k_snoc_tx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
{
struct ath10k_ce_pipe *ce_pipe;
struct ath10k_ce_ring *ce_ring;
- struct ath10k_snoc *ar_snoc;
struct sk_buff *skb;
struct ath10k *ar;
int i;
ar = snoc_pipe->hif_ce_state;
- ar_snoc = ath10k_snoc_priv(ar);
ce_pipe = snoc_pipe->ce_hdl;
ce_ring = ce_pipe->src_ring;
@@ -958,7 +946,8 @@ static int ath10k_snoc_init_pipes(struct ath10k *ar)
return 0;
}
-static int ath10k_snoc_wlan_enable(struct ath10k *ar)
+static int ath10k_snoc_wlan_enable(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
struct ath10k_tgt_pipe_cfg tgt_cfg[CE_COUNT_MAX];
struct ath10k_qmi_wlan_enable_cfg cfg;
@@ -992,7 +981,17 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar)
cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)
&target_shadow_reg_cfg_map;
- mode = QMI_WLFW_MISSION_V01;
+ switch (fw_mode) {
+ case ATH10K_FIRMWARE_MODE_NORMAL:
+ mode = QMI_WLFW_MISSION_V01;
+ break;
+ case ATH10K_FIRMWARE_MODE_UTF:
+ mode = QMI_WLFW_FTM_V01;
+ break;
+ default:
+ ath10k_err(ar, "invalid firmware mode %d\n", fw_mode);
+ return -EINVAL;
+ }
return ath10k_qmi_wlan_enable(ar, &cfg, mode,
NULL);
@@ -1000,7 +999,16 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar)
static void ath10k_snoc_wlan_disable(struct ath10k *ar)
{
- if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+
+ /* If both ATH10K_FLAG_CRASH_FLUSH and ATH10K_SNOC_FLAG_RECOVERY
+ * flags are not set, it means that the driver has restarted
+ * due to a crash inject via debugfs. In this case, the driver
+ * needs to restart the firmware and hence send qmi wlan disable,
+ * during the driver restart sequence.
+ */
+ if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags) ||
+ !test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))
ath10k_qmi_wlan_disable(ar);
}
@@ -1012,14 +1020,15 @@ static void ath10k_snoc_hif_power_down(struct ath10k *ar)
ath10k_ce_free_rri(ar);
}
-static int ath10k_snoc_hif_power_up(struct ath10k *ar)
+static int ath10k_snoc_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
int ret;
ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 driver state = %d\n",
__func__, ar->state);
- ret = ath10k_snoc_wlan_enable(ar);
+ ret = ath10k_snoc_wlan_enable(ar, fw_mode);
if (ret) {
ath10k_err(ar, "failed to enable wcn3990: %d\n", ret);
return ret;
@@ -1041,6 +1050,46 @@ err_wlan_enable:
return ret;
}
+#ifdef CONFIG_PM
+static int ath10k_snoc_hif_suspend(struct ath10k *ar)
+{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ int ret;
+
+ if (!device_may_wakeup(ar->dev))
+ return -EPERM;
+
+ ret = enable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line);
+ if (ret) {
+ ath10k_err(ar, "failed to enable wakeup irq :%d\n", ret);
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device suspended\n");
+
+ return ret;
+}
+
+static int ath10k_snoc_hif_resume(struct ath10k *ar)
+{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ int ret;
+
+ if (!device_may_wakeup(ar->dev))
+ return -EPERM;
+
+ ret = disable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line);
+ if (ret) {
+ ath10k_err(ar, "failed to disable wakeup irq: %d\n", ret);
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device resumed\n");
+
+ return ret;
+}
+#endif
+
static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
.read32 = ath10k_snoc_read32,
.write32 = ath10k_snoc_write32,
@@ -1054,6 +1103,10 @@ static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
.send_complete_check = ath10k_snoc_hif_send_complete_check,
.get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
.get_target_info = ath10k_snoc_hif_get_target_info,
+#ifdef CONFIG_PM
+ .suspend = ath10k_snoc_hif_suspend,
+ .resume = ath10k_snoc_hif_resume,
+#endif
};
static const struct ath10k_bus_ops ath10k_snoc_bus_ops = {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 2b2f23cf7c5d..d62f53501fbb 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SNOC_H_
@@ -90,7 +79,7 @@ struct ath10k_snoc {
struct ath10k_vreg_info *vreg;
struct ath10k_clk_info *clk;
struct ath10k_qmi *qmi;
- unsigned long int flags;
+ unsigned long flags;
};
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 653b6d013207..5db6bff5193b 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2013-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/relay.h>
@@ -494,6 +483,9 @@ static struct dentry *create_buf_file_handler(const char *filename,
buf_file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
+ if (IS_ERR(buf_file))
+ return NULL;
+
*is_global = 1;
return buf_file;
}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
index 13276f4dc12c..5f481f11c6e5 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.h
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2013-2015 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SPECTRAL_H
diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c
index e7f57efadae1..4dddeee684b4 100644
--- a/drivers/net/wireless/ath/ath10k/swap.c
+++ b/drivers/net/wireless/ath/ath10k/swap.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2015-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* This file has implementation for code swap logic. With code swap feature,
diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h
index fa602f15fa93..25e0ad36ddb1 100644
--- a/drivers/net/wireless/ath/ath10k/swap.h
+++ b/drivers/net/wireless/ath/ath10k/swap.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2015-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SWAP_H_
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index b11a1c3d87b4..dff6c8ac9dba 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __TARGADDRS_H__
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index c24ee616833c..6433ff10d80e 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "testmode.h"
@@ -270,7 +259,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
ar->testmode.utf_mode_fw.fw_file.wmi_op_version);
- ret = ath10k_hif_power_up(ar);
+ ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_UTF);
if (ret) {
ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF;
diff --git a/drivers/net/wireless/ath/ath10k/testmode.h b/drivers/net/wireless/ath/ath10k/testmode.h
index 9cdd150815db..6488fd514ae3 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.h
+++ b/drivers/net/wireless/ath/ath10k/testmode.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
index 6514d1a14242..ee1cb27c1d60 100644
--- a/drivers/net/wireless/ath/ath10k/testmode_i.h
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* "API" level of the ath10k testmode interface. Bump it after every
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c
index fe35edcd3ec8..36c9a1364253 100644
--- a/drivers/net/wireless/ath/ath10k/thermal.c
+++ b/drivers/net/wireless/ath/ath10k/thermal.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/device.h>
diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h
index 65e2419543f9..5fdb020f4da3 100644
--- a/drivers/net/wireless/ath/ath10k/thermal.h
+++ b/drivers/net/wireless/ath/ath10k/thermal.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _THERMAL_
#define _THERMAL_
diff --git a/drivers/net/wireless/ath/ath10k/trace.c b/drivers/net/wireless/ath/ath10k/trace.c
index 4a31e2c6fbd4..3ecdff17f64e 100644
--- a/drivers/net/wireless/ath/ath10k/trace.c
+++ b/drivers/net/wireless/ath/ath10k/trace.c
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h
index 7d2fac342150..ba977bbe6291 100644
--- a/drivers/net/wireless/ath/ath10k/trace.h
+++ b/drivers/net/wireless/ath/ath10k/trace.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 23606b6972d0..c5818d28f55a 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
@@ -95,7 +84,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
- if (ar->dev_type != ATH10K_DEV_TYPE_HL)
+ if (txq && txq->sta && skb_cb->airtime_est)
+ ieee80211_sta_register_airtime(txq->sta, txq->tid,
+ skb_cb->airtime_est, 0);
+
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
ath10k_report_offchan_tx(htt->ar, msdu);
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index 2bf401e436d3..ecac441d83a7 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -1,18 +1,7 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2014,2016 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _TXRX_H_
#define _TXRX_H_
diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
index f731d35ee76d..970cf69ac35f 100644
--- a/drivers/net/wireless/ath/ath10k/usb.c
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2007-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
@@ -706,7 +695,8 @@ static void ath10k_usb_hif_send_complete_check(struct ath10k *ar,
{
}
-static int ath10k_usb_hif_power_up(struct ath10k *ar)
+static int ath10k_usb_hif_power_up(struct ath10k *ar,
+ enum ath10k_firmware_mode fw_mode)
{
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h
index f60a3cc7d712..34d683e8fc18 100644
--- a/drivers/net/wireless/ath/ath10k/usb.h
+++ b/drivers/net/wireless/ath/ath10k/usb.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _USB_H_
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 04663076d27a..1491c25518bb 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WMI_OPS_H_
@@ -33,6 +22,9 @@ struct wmi_ops {
struct wmi_mgmt_rx_ev_arg *arg);
int (*pull_mgmt_tx_compl)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_tlv_mgmt_tx_compl_ev_arg *arg);
+ int (*pull_mgmt_tx_bundle_compl)(
+ struct ath10k *ar, struct sk_buff *skb,
+ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg);
int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_ch_info_ev_arg *arg);
int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
@@ -66,6 +58,8 @@ struct wmi_ops {
struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
+ struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar,
+ const u8 macaddr[ETH_ALEN]);
struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg);
@@ -280,6 +274,16 @@ ath10k_wmi_pull_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb,
}
static inline int
+ath10k_wmi_pull_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb,
+ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
+{
+ if (!ar->wmi.ops->pull_mgmt_tx_bundle_compl)
+ return -EOPNOTSUPP;
+
+ return ar->wmi.ops->pull_mgmt_tx_bundle_compl(ar, skb, arg);
+}
+
+static inline int
ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg)
{
@@ -507,6 +511,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
}
static inline int
+ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN])
+{
+ struct sk_buff *skb;
+
+ if (!ar->wmi.ops->gen_pdev_set_base_macaddr)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
+}
+
+static inline int
ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
{
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 892bd8c30dd9..582fb11f648a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#include "debug.h"
@@ -24,6 +13,7 @@
#include "wmi-tlv.h"
#include "p2p.h"
#include "testmode.h"
+#include <linux/bitfield.h>
/***************/
/* TLV helpers */
@@ -620,6 +610,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
ath10k_wmi_event_mgmt_tx_compl(ar, skb);
break;
+ case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
+ ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
+ break;
default:
ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
break;
@@ -681,11 +674,88 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
arg->desc_id = ev->desc_id;
arg->status = ev->status;
arg->pdev_id = ev->pdev_id;
+ arg->ppdu_id = ev->ppdu_id;
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ arg->ack_rssi = ev->ack_rssi;
kfree(tb);
return 0;
}
+struct wmi_tlv_tx_bundle_compl_parse {
+ const __le32 *num_reports;
+ const __le32 *desc_ids;
+ const __le32 *status;
+ const __le32 *ppdu_ids;
+ const __le32 *ack_rssi;
+ bool desc_ids_done;
+ bool status_done;
+ bool ppdu_ids_done;
+ bool ack_rssi_done;
+};
+
+static int
+ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
+
+ switch (tag) {
+ case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
+ bundle_tx_compl->num_reports = ptr;
+ break;
+ case WMI_TLV_TAG_ARRAY_UINT32:
+ if (!bundle_tx_compl->desc_ids_done) {
+ bundle_tx_compl->desc_ids_done = true;
+ bundle_tx_compl->desc_ids = ptr;
+ } else if (!bundle_tx_compl->status_done) {
+ bundle_tx_compl->status_done = true;
+ bundle_tx_compl->status = ptr;
+ } else if (!bundle_tx_compl->ppdu_ids_done) {
+ bundle_tx_compl->ppdu_ids_done = true;
+ bundle_tx_compl->ppdu_ids = ptr;
+ } else if (!bundle_tx_compl->ack_rssi_done) {
+ bundle_tx_compl->ack_rssi_done = true;
+ bundle_tx_compl->ack_rssi = ptr;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
+ struct ath10k *ar, struct sk_buff *skb,
+ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
+{
+ struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
+ int ret;
+
+ ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
+ ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
+ &bundle_tx_compl);
+ if (ret) {
+ ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
+ return ret;
+ }
+
+ if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
+ !bundle_tx_compl.status)
+ return -EPROTO;
+
+ arg->num_reports = *bundle_tx_compl.num_reports;
+ arg->desc_ids = bundle_tx_compl.desc_ids;
+ arg->status = bundle_tx_compl.status;
+ arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ arg->ack_rssi = bundle_tx_compl.ack_rssi;
+
+ return 0;
+}
+
static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg)
@@ -1227,6 +1297,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
{
const void **tb;
const struct wmi_tlv_stats_ev *ev;
+ u32 num_peer_stats_extd;
const void *data;
u32 num_pdev_stats;
u32 num_vdev_stats;
@@ -1234,6 +1305,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
u32 num_bcnflt_stats;
u32 num_chan_stats;
size_t data_len;
+ u32 stats_id;
int ret;
int i;
@@ -1258,11 +1330,13 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
+ stats_id = __le32_to_cpu(ev->stats_id);
+ num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
+ "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
num_pdev_stats, num_vdev_stats, num_peer_stats,
- num_bcnflt_stats, num_chan_stats);
+ num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
for (i = 0; i < num_pdev_stats; i++) {
const struct wmi_pdev_stats *src;
@@ -1327,6 +1401,28 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
ath10k_wmi_pull_peer_stats(&src->old, dst);
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+
+ if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
+ const struct wmi_tlv_peer_stats_extd *extd;
+ unsigned long rx_duration_high;
+
+ extd = data + sizeof(*src) * (num_peer_stats - i - 1)
+ + sizeof(*extd) * i;
+
+ dst->rx_duration = __le32_to_cpu(extd->rx_duration);
+ rx_duration_high = __le32_to_cpu
+ (extd->rx_duration_high);
+
+ if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
+ &rx_duration_high)) {
+ rx_duration_high =
+ FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
+ rx_duration_high);
+ dst->rx_duration |= (u64)rx_duration_high <<
+ WMI_TLV_PEER_RX_DURATION_SHIFT;
+ }
+ }
+
list_add_tail(&dst->list, &stats->peers);
}
@@ -1514,21 +1610,55 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(param_value);
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n");
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
+ param_id, param_value);
return skb;
}
+static void
+ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
+{
+ struct host_memory_chunk *chunk;
+ struct wmi_tlv *tlv;
+ int i;
+ __le16 tlv_len, tlv_tag;
+
+ tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
+ tlv_len = __cpu_to_le16(sizeof(*chunk));
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ tlv = host_mem_chunks;
+ tlv->tag = tlv_tag;
+ tlv->len = tlv_len;
+ chunk = (void *)tlv->value;
+
+ chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+ chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
+ chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
+ i,
+ ar->wmi.mem_chunks[i].len,
+ (unsigned long long)ar->wmi.mem_chunks[i].paddr,
+ ar->wmi.mem_chunks[i].req_id);
+
+ host_mem_chunks += sizeof(*tlv);
+ host_mem_chunks += sizeof(*chunk);
+ }
+}
+
static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
{
struct sk_buff *skb;
struct wmi_tlv *tlv;
struct wmi_tlv_init_cmd *cmd;
struct wmi_tlv_resource_config *cfg;
- struct wmi_host_mem_chunks *chunks;
+ void *chunks;
size_t len, chunks_len;
void *ptr;
- chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk);
+ chunks_len = ar->wmi.num_mem_chunks *
+ (sizeof(struct host_memory_chunk) + sizeof(*tlv));
len = (sizeof(*tlv) + sizeof(*cmd)) +
(sizeof(*tlv) + sizeof(*cfg)) +
(sizeof(*tlv) + chunks_len);
@@ -1611,7 +1741,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
cfg->vow_config = __cpu_to_le32(0);
cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
- cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC);
+ cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx);
cfg->max_frag_entries = __cpu_to_le32(2);
cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
@@ -1626,9 +1756,12 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_ocb_vdevs = __cpu_to_le32(0);
cfg->num_ocb_channels = __cpu_to_le32(0);
cfg->num_ocb_schedules = __cpu_to_le32(0);
- cfg->host_capab = __cpu_to_le32(0);
+ cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
- ath10k_wmi_put_host_mem_chunks(ar, chunks);
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
+
+ ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
return skb;
@@ -1984,7 +2117,8 @@ ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(param_value);
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n");
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
+ vdev_id, param_id, param_value);
return skb;
}
@@ -1998,9 +2132,11 @@ ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
size_t len;
void *ptr;
- if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
+ if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
+ arg->key_data)
return ERR_PTR(-EINVAL);
- if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
+ if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] &&
+ !arg->key_data)
return ERR_PTR(-EINVAL);
len = sizeof(*tlv) + sizeof(*cmd) +
@@ -2298,7 +2434,9 @@ ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
cmd->param_value = __cpu_to_le32(param_value);
ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n");
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
+ vdev_id, peer_addr, param_id, param_value);
return skb;
}
@@ -2692,7 +2830,9 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
arvif = (void *)cb->vif->drv_priv;
vdev_id = arvif->vdev_id;
- if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
+ if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
+ (!(ieee80211_is_nullfunc(hdr->frame_control) ||
+ ieee80211_is_qos_nullfunc(hdr->frame_control)))))
return ERR_PTR(-EINVAL);
len = sizeof(*cmd) + 2 * sizeof(*tlv);
@@ -2700,10 +2840,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- len += IEEE80211_CCMP_MIC_LEN;
+ ieee80211_has_protected(hdr->frame_control))
buf_len += IEEE80211_CCMP_MIC_LEN;
- }
buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
buf_len = round_up(buf_len, 4);
@@ -3259,6 +3397,8 @@ ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
cmd = (void *)tlv->value;
cmd->enable = __cpu_to_le32(1);
+ if (!ar->bus_param.link_can_suspend)
+ cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n");
return skb;
@@ -4093,6 +4233,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
+ .pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index e07e9907e355..65e6aa520b06 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1,19 +1,8 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WMI_TLV_H
#define _WMI_TLV_H
@@ -25,6 +14,8 @@
#define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
#define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64
+#define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI BIT(18)
+
enum wmi_tlv_grp_id {
WMI_TLV_GRP_START = 0x3,
WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START,
@@ -321,6 +312,7 @@ enum wmi_tlv_event_id {
WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID,
WMI_TLV_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID,
WMI_TLV_MGMT_TX_COMPLETION_EVENTID,
+ WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID,
WMI_TLV_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_BA_NEG),
WMI_TLV_TX_ADDBA_COMPLETE_EVENTID,
WMI_TLV_BA_RSP_SSN_EVENTID,
@@ -1394,6 +1386,25 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_AP_TWT = 153,
WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154,
WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155,
+ WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156,
+ WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157,
+ WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158,
+ WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159,
+ WMI_TLV_SERVICE_MOTION_DET = 160,
+ WMI_TLV_SERVICE_INFRA_MBSSID = 161,
+ WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162,
+ WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163,
+ WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164,
+ WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165,
+ WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166,
+ WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167,
+ WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168,
+ WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169,
+ WMI_TLV_SERVICE_ESP_SUPPORT = 170,
+ WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171,
+ WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
+ WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
+ WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
WMI_TLV_MAX_EXT_SERVICE = 256,
};
@@ -1567,6 +1578,8 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
SVCMAP(WMI_TLV_SERVICE_THERM_THROT,
WMI_SERVICE_THERM_THROT,
WMI_TLV_MAX_SERVICE);
+ SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
+ WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
}
#undef SVCMAP
@@ -1592,10 +1605,14 @@ struct chan_info_params {
u32 mac_clk_mhz;
};
+#define WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL BIT(9)
+
struct wmi_tlv_mgmt_tx_compl_ev {
__le32 desc_id;
__le32 status;
__le32 pdev_id;
+ __le32 ppdu_id;
+ __le32 ack_rssi;
};
#define WMI_TLV_MGMT_RX_NUM_RSSI 4
@@ -1872,6 +1889,22 @@ struct wmi_tlv_req_stats_cmd {
struct wmi_mac_addr peer_macaddr;
} __packed;
+#define WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT 31
+#define WMI_TLV_PEER_RX_DURATION_HIGH_MASK GENMASK(30, 0)
+#define WMI_TLV_PEER_RX_DURATION_SHIFT 32
+
+struct wmi_tlv_peer_stats_extd {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 rx_duration;
+ __le32 peer_tx_bytes;
+ __le32 peer_rx_bytes;
+ __le32 last_tx_rate_code;
+ __le32 last_tx_power;
+ __le32 rx_mc_bc_cnt;
+ __le32 rx_duration_high;
+ __le32 reserved[2];
+} __packed;
+
struct wmi_tlv_vdev_stats {
__le32 vdev_id;
__le32 beacon_snr;
@@ -1965,6 +1998,10 @@ struct wmi_tlv_stats_ev {
__le32 num_peer_stats;
__le32 num_bcnflt_stats;
__le32 num_chan_stats;
+ __le32 num_mib_stats;
+ __le32 pdev_id;
+ __le32 num_bcn_stats;
+ __le32 num_peer_stats_extd;
} __packed;
struct wmi_tlv_p2p_noa_ev {
@@ -1998,8 +2035,15 @@ struct wmi_tlv_set_quiet_cmd {
__le32 enabled;
} __packed;
+enum wmi_tlv_wow_interface_cfg {
+ WOW_IFACE_PAUSE_ENABLED,
+ WOW_IFACE_PAUSE_DISABLED
+};
+
struct wmi_tlv_wow_enable_cmd {
__le32 enable;
+ __le32 pause_iface_config;
+ __le32 flags;
} __packed;
struct wmi_tlv_wow_host_wakeup_ind {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ba837403e266..98a90e49d666 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/skbuff.h>
@@ -827,6 +816,7 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = {
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
.disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED,
+ .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED,
};
/* 10.X WMI VDEV param map */
@@ -903,6 +893,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = {
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
.disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED,
+ .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED,
};
static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
@@ -978,6 +969,7 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
.disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED,
+ .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED,
};
static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
@@ -1056,6 +1048,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
.inc_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
.dec_tsf = WMI_10_4_VDEV_PARAM_TSF_DECREMENT,
.disable_4addr_src_lrn = WMI_10_4_VDEV_PARAM_DISABLE_4_ADDR_SRC_LRN,
+ .rtt_responder_role = WMI_10_4_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE,
};
static struct wmi_pdev_param_map wmi_pdev_param_map = {
@@ -1606,6 +1599,30 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
.enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
};
+static const u8 wmi_key_cipher_suites[] = {
+ [WMI_CIPHER_NONE] = WMI_CIPHER_NONE,
+ [WMI_CIPHER_WEP] = WMI_CIPHER_WEP,
+ [WMI_CIPHER_TKIP] = WMI_CIPHER_TKIP,
+ [WMI_CIPHER_AES_OCB] = WMI_CIPHER_AES_OCB,
+ [WMI_CIPHER_AES_CCM] = WMI_CIPHER_AES_CCM,
+ [WMI_CIPHER_WAPI] = WMI_CIPHER_WAPI,
+ [WMI_CIPHER_CKIP] = WMI_CIPHER_CKIP,
+ [WMI_CIPHER_AES_CMAC] = WMI_CIPHER_AES_CMAC,
+ [WMI_CIPHER_AES_GCM] = WMI_CIPHER_AES_GCM,
+};
+
+static const u8 wmi_tlv_key_cipher_suites[] = {
+ [WMI_CIPHER_NONE] = WMI_TLV_CIPHER_NONE,
+ [WMI_CIPHER_WEP] = WMI_TLV_CIPHER_WEP,
+ [WMI_CIPHER_TKIP] = WMI_TLV_CIPHER_TKIP,
+ [WMI_CIPHER_AES_OCB] = WMI_TLV_CIPHER_AES_OCB,
+ [WMI_CIPHER_AES_CCM] = WMI_TLV_CIPHER_AES_CCM,
+ [WMI_CIPHER_WAPI] = WMI_TLV_CIPHER_WAPI,
+ [WMI_CIPHER_CKIP] = WMI_TLV_CIPHER_CKIP,
+ [WMI_CIPHER_AES_CMAC] = WMI_TLV_CIPHER_AES_CMAC,
+ [WMI_CIPHER_AES_GCM] = WMI_TLV_CIPHER_AES_GCM,
+};
+
static const struct wmi_peer_flags_map wmi_peer_flags_map = {
.auth = WMI_PEER_AUTH,
.qos = WMI_PEER_QOS,
@@ -2325,8 +2342,8 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
return true;
}
-static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
- u32 status)
+static int
+wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
{
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
struct ath10k_wmi *wmi = &ar->wmi;
@@ -2336,30 +2353,34 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
spin_lock_bh(&ar->data_lock);
- pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id);
+ pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id);
if (!pkt_addr) {
ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n",
- desc_id);
+ param->desc_id);
ret = -ENOENT;
goto out;
}
msdu = pkt_addr->vaddr;
dma_unmap_single(ar->dev, pkt_addr->paddr,
- msdu->len, DMA_FROM_DEVICE);
+ msdu->len, DMA_TO_DEVICE);
info = IEEE80211_SKB_CB(msdu);
- if (status)
+ if (param->status) {
info->flags &= ~IEEE80211_TX_STAT_ACK;
- else
+ } else {
info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
+ param->ack_rssi;
+ info->status.is_valid_ack_signal = true;
+ }
ieee80211_tx_status_irqsafe(ar->hw, msdu);
ret = 0;
out:
- idr_remove(&wmi->mgmt_pending_tx, desc_id);
+ idr_remove(&wmi->mgmt_pending_tx, param->desc_id);
spin_unlock_bh(&ar->data_lock);
return ret;
}
@@ -2367,6 +2388,7 @@ out:
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_tlv_mgmt_tx_compl_ev_arg arg;
+ struct mgmt_tx_compl_params param;
int ret;
ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg);
@@ -2375,14 +2397,50 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
return ret;
}
- wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id),
- __le32_to_cpu(arg.status));
+ memset(&param, 0, sizeof(struct mgmt_tx_compl_params));
+ param.desc_id = __le32_to_cpu(arg.desc_id);
+ param.status = __le32_to_cpu(arg.status);
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ param.ack_rssi = __le32_to_cpu(arg.ack_rssi);
+
+ wmi_process_mgmt_tx_comp(ar, &param);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n");
return 0;
}
+int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg;
+ struct mgmt_tx_compl_params param;
+ u32 num_reports;
+ int i, ret;
+
+ ret = ath10k_wmi_pull_mgmt_tx_bundle_compl(ar, skb, &arg);
+ if (ret) {
+ ath10k_warn(ar, "failed to parse bundle mgmt compl event: %d\n", ret);
+ return ret;
+ }
+
+ num_reports = __le32_to_cpu(arg.num_reports);
+
+ for (i = 0; i < num_reports; i++) {
+ memset(&param, 0, sizeof(struct mgmt_tx_compl_params));
+ param.desc_id = __le32_to_cpu(arg.desc_ids[i]);
+ param.status = __le32_to_cpu(arg.desc_ids[i]);
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]);
+ wmi_process_mgmt_tx_comp(ar, &param);
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n");
+
+ return 0;
+}
+
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_mgmt_rx_ev_arg arg = {};
@@ -5193,7 +5251,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
void *vaddr;
pool_size = num_units * round_up(unit_len, 4);
- vaddr = dma_zalloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
+ vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
if (!vaddr)
return -ENOMEM;
@@ -6240,6 +6298,25 @@ int ath10k_wmi_connect(struct ath10k *ar)
}
static struct sk_buff *
+ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
+ const u8 macaddr[ETH_ALEN])
+{
+ struct wmi_pdev_set_base_macaddr_cmd *cmd;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data;
+ ether_addr_copy(cmd->mac_addr.addr, macaddr);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi pdev basemac %pM\n", macaddr);
+ return skb;
+}
+
+static struct sk_buff *
ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg)
@@ -8245,7 +8322,7 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer,
"Peer TX rate", peer->peer_tx_rate);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"Peer RX rate", peer->peer_rx_rate);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ len += scnprintf(buf + len, buf_len - len, "%30s %llu\n",
"Peer RX duration", peer->rx_duration);
len += scnprintf(buf + len, buf_len - len, "\n");
@@ -9048,6 +9125,7 @@ static const struct wmi_ops wmi_10_2_ops = {
.gen_peer_create = ath10k_wmi_op_gen_peer_create,
.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
+ .gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
@@ -9166,6 +9244,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ .gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
.gen_init = ath10k_wmi_10_4_op_gen_init,
@@ -9229,6 +9308,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
+ ar->wmi_key_cipher = wmi_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->wmi.cmd = &wmi_10_2_4_cmd_map;
@@ -9236,6 +9316,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
+ ar->wmi_key_cipher = wmi_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_10_2:
ar->wmi.cmd = &wmi_10_2_cmd_map;
@@ -9243,6 +9324,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
+ ar->wmi_key_cipher = wmi_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
ar->wmi.cmd = &wmi_10x_cmd_map;
@@ -9250,6 +9332,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
+ ar->wmi_key_cipher = wmi_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_MAIN:
ar->wmi.cmd = &wmi_cmd_map;
@@ -9257,9 +9340,11 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_vdev_param_map;
ar->wmi.pdev_param = &wmi_pdev_param_map;
ar->wmi.peer_flags = &wmi_peer_flags_map;
+ ar->wmi_key_cipher = wmi_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
ath10k_wmi_tlv_attach(ar);
+ ar->wmi_key_cipher = wmi_tlv_key_cipher_suites;
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 2034ccc7cc72..e1c40bb69932 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1,26 +1,15 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WMI_H_
#define _WMI_H_
#include <linux/types.h>
-#include <net/mac80211.h>
+#include <linux/ieee80211.h>
/*
* This file specifies the WMI interface for the Unified Software
@@ -208,6 +197,11 @@ enum wmi_service {
WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT,
WMI_SERVICE_THERM_THROT,
+ WMI_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
+ WMI_SERVICE_REPORT_AIRTIME,
+
+ /* Remember to add the new value to wmi_service_name()! */
/* keep last */
WMI_SERVICE_MAX,
@@ -368,9 +362,14 @@ enum wmi_10_4_service {
WMI_10_4_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT,
WMI_10_4_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS,
WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
+ WMI_10_4_SERVICE_PEER_CHWIDTH_CHANGE,
+ WMI_10_4_SERVICE_RX_FILTER_OUT_COUNT,
+ WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_10_4_SERVICE_REPORT_AIRTIME,
};
-static inline char *wmi_service_name(int service_id)
+static inline char *wmi_service_name(enum wmi_service service_id)
{
#define SVCSTR(x) case x: return #x
@@ -467,6 +466,7 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL);
SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC);
SVCSTR(WMI_SERVICE_VDEV_RX_FILTER);
+ SVCSTR(WMI_SERVICE_BTCOEX);
SVCSTR(WMI_SERVICE_CHECK_CAL_VERSION);
SVCSTR(WMI_SERVICE_DBGLOG_WARN2);
SVCSTR(WMI_SERVICE_BTCOEX_DUTY_CYCLE);
@@ -476,18 +476,29 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_SMART_LOGGING_SUPPORT);
SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE);
SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY);
+ SVCSTR(WMI_SERVICE_MGMT_TX_WMI);
SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH);
SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
SVCSTR(WMI_SERVICE_RESET_CHIP);
+ SVCSTR(WMI_SERVICE_SPOOF_MAC_SUPPORT);
SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT);
- default:
+ SVCSTR(WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT);
+ SVCSTR(WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT);
+ SVCSTR(WMI_SERVICE_THERM_THROT);
+ SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
+ SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
+ SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
+
+ case WMI_SERVICE_MAX:
return NULL;
}
#undef SVCSTR
+
+ return NULL;
}
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
@@ -579,6 +590,8 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len);
SVCMAP(WMI_10X_SERVICE_BB_TIMING_CONFIG_SUPPORT,
WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT, len);
+ SVCMAP(WMI_10X_SERVICE_PER_PACKET_SW_ENCRYPT,
+ WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
}
static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
@@ -799,6 +812,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, len);
SVCMAP(WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_SERVICE_RTT_RESPONDER_ROLE, len);
+ SVCMAP(WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
+ WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
+ SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
+ WMI_SERVICE_REPORT_AIRTIME, len);
}
#undef SVCMAP
@@ -1986,7 +2005,7 @@ static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode)
/* no default handler to allow compiler to check that the
* enum is fully handled
*/
- };
+ }
return "<unknown>";
}
@@ -2075,6 +2094,8 @@ enum wmi_channel_change_cause {
#define WMI_HT_CAP_MPDU_DENSITY 0x0700 /* MPDU Density */
#define WMI_HT_CAP_MPDU_DENSITY_MASK_SHIFT 8
#define WMI_HT_CAP_HT40_SGI 0x0800
+#define WMI_HT_CAP_RX_LDPC 0x1000 /* LDPC RX support */
+#define WMI_HT_CAP_TX_LDPC 0x2000 /* LDPC TX support */
#define WMI_HT_CAP_DEFAULT_ALL (WMI_HT_CAP_ENABLED | \
WMI_HT_CAP_HT20_SGI | \
@@ -2972,6 +2993,8 @@ enum wmi_10_4_feature_mask {
WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE = BIT(11),
WMI_10_4_TDLS_EXPLICIT_MODE_ONLY = BIT(12),
WMI_10_4_TX_DATA_ACK_RSSI = BIT(16),
+ WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT = BIT(17),
+ WMI_10_4_REPORT_AIRTIME = BIT(18),
};
@@ -4083,6 +4106,10 @@ struct wmi_pdev_set_param_cmd {
__le32 param_value;
} __packed;
+struct wmi_pdev_set_base_macaddr_cmd {
+ struct wmi_mac_addr mac_addr;
+} __packed;
+
/* valid period is 1 ~ 60000ms, unit in millisecond */
#define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
@@ -4507,6 +4534,13 @@ enum wmi_10_4_stats_id {
WMI_10_4_STAT_VDEV_EXTD = BIT(4),
};
+enum wmi_tlv_stats_id {
+ WMI_TLV_STAT_PDEV = BIT(0),
+ WMI_TLV_STAT_VDEV = BIT(1),
+ WMI_TLV_STAT_PEER = BIT(2),
+ WMI_TLV_STAT_PEER_EXTD = BIT(10),
+};
+
struct wlan_inst_rssi_args {
__le16 cfg_retry_count;
__le16 retry_count;
@@ -4929,15 +4963,30 @@ struct wmi_key_seq_counter {
__le32 key_seq_counter_h;
} __packed;
-#define WMI_CIPHER_NONE 0x0 /* clear key */
-#define WMI_CIPHER_WEP 0x1
-#define WMI_CIPHER_TKIP 0x2
-#define WMI_CIPHER_AES_OCB 0x3
-#define WMI_CIPHER_AES_CCM 0x4
-#define WMI_CIPHER_WAPI 0x5
-#define WMI_CIPHER_CKIP 0x6
-#define WMI_CIPHER_AES_CMAC 0x7
-#define WMI_CIPHER_AES_GCM 0x8
+enum wmi_cipher_suites {
+ WMI_CIPHER_NONE,
+ WMI_CIPHER_WEP,
+ WMI_CIPHER_TKIP,
+ WMI_CIPHER_AES_OCB,
+ WMI_CIPHER_AES_CCM,
+ WMI_CIPHER_WAPI,
+ WMI_CIPHER_CKIP,
+ WMI_CIPHER_AES_CMAC,
+ WMI_CIPHER_AES_GCM,
+};
+
+enum wmi_tlv_cipher_suites {
+ WMI_TLV_CIPHER_NONE,
+ WMI_TLV_CIPHER_WEP,
+ WMI_TLV_CIPHER_TKIP,
+ WMI_TLV_CIPHER_AES_OCB,
+ WMI_TLV_CIPHER_AES_CCM,
+ WMI_TLV_CIPHER_WAPI,
+ WMI_TLV_CIPHER_CKIP,
+ WMI_TLV_CIPHER_AES_CMAC,
+ WMI_TLV_CIPHER_ANY,
+ WMI_TLV_CIPHER_AES_GCM,
+};
struct wmi_vdev_install_key_cmd {
__le32 vdev_id;
@@ -5003,12 +5052,13 @@ enum wmi_rate_preamble {
#define ATH10K_FW_SKIPPED_RATE_CTRL(flags) (((flags) >> 6) & 0x1)
#define ATH10K_VHT_MCS_NUM 10
-#define ATH10K_BW_NUM 4
+#define ATH10K_BW_NUM 6
#define ATH10K_NSS_NUM 4
#define ATH10K_LEGACY_NUM 12
#define ATH10K_GI_NUM 2
#define ATH10K_HT_MCS_NUM 32
#define ATH10K_RATE_TABLE_NUM 320
+#define ATH10K_RATE_INFO_FLAGS_SGI_BIT 2
/* Value to disable fixed rate setting */
#define WMI_FIXED_RATE_NONE (0xff)
@@ -5083,6 +5133,7 @@ struct wmi_vdev_param_map {
u32 inc_tsf;
u32 dec_tsf;
u32 disable_4addr_src_lrn;
+ u32 rtt_responder_role;
};
#define WMI_VDEV_PARAM_UNSUPPORTED 0
@@ -6682,10 +6733,27 @@ struct wmi_scan_ev_arg {
__le32 vdev_id;
};
+struct mgmt_tx_compl_params {
+ u32 desc_id;
+ u32 status;
+ u32 ppdu_id;
+ int ack_rssi;
+};
+
struct wmi_tlv_mgmt_tx_compl_ev_arg {
__le32 desc_id;
__le32 status;
__le32 pdev_id;
+ __le32 ppdu_id;
+ __le32 ack_rssi;
+};
+
+struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
+ __le32 num_reports;
+ const __le32 *desc_ids;
+ const __le32 *status;
+ const __le32 *ppdu_ids;
+ const __le32 *ack_rssi;
};
struct wmi_mgmt_rx_ev_arg {
@@ -7244,6 +7312,7 @@ int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb);
+int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
index 36d4245c308e..8c26adddd034 100644
--- a/drivers/net/wireless/ath/ath10k/wow.c
+++ b/drivers/net/wireless/ath/ath10k/wow.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "mac.h"
@@ -77,7 +66,7 @@ static int ath10k_wow_cleanup(struct ath10k *ar)
return 0;
}
-/**
+/*
* Convert a 802.3 format to a 802.11 format.
* +------------+-----------+--------+----------------+
* 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... |
@@ -88,9 +77,8 @@ static int ath10k_wow_cleanup(struct ath10k *ar)
* 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... |
* +--+------------+----+-----------+---------------+-----------+
*/
-static void ath10k_wow_convert_8023_to_80211
- (struct cfg80211_pkt_pattern *new,
- const struct cfg80211_pkt_pattern *old)
+static void ath10k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
+ const struct cfg80211_pkt_pattern *old)
{
u8 hdr_8023_pattern[ETH_HLEN] = {};
u8 hdr_8023_bit_mask[ETH_HLEN] = {};
diff --git a/drivers/net/wireless/ath/ath10k/wow.h b/drivers/net/wireless/ath/ath10k/wow.h
index 6e810105b775..14ea4e1e925e 100644
--- a/drivers/net/wireless/ath/ath10k/wow.h
+++ b/drivers/net/wireless/ath/ath10k/wow.h
@@ -1,17 +1,6 @@
+/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2015,2017 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WOW_H_
#define _WOW_H_
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 54132af70094..aa1c71a76ef7 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1140,7 +1140,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
len -= ie_len;
data += ie_len;
- };
+ }
ret = 0;
out:
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 9d7ac1ab2d02..68854c45d0a4 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -776,10 +776,8 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS;
- ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
+ return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
NO_SYNC_WMIFLAG);
-
- return 0;
}
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index f019a20e5a1f..2b29bf4730f6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3457,9 +3457,9 @@ static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size,
if (!((pBase->txrxMask >> i) & 1))
continue;
- len += snprintf(buf + len, size - len, "Chain %d\n", i);
+ len += scnprintf(buf + len, size - len, "Chain %d\n", i);
- len += snprintf(buf + len, size - len,
+ len += scnprintf(buf + len, size - len,
"Freq\t ref\tvolt\ttemp\tnf_cal\tnf_pow\trx_temp\n");
for (j = 0; j < cal_pier_nr; j++) {
@@ -3471,10 +3471,10 @@ static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size,
freq = 4800 + eep->calFreqPier5G[j] * 5;
}
- len += snprintf(buf + len, size - len,
+ len += scnprintf(buf + len, size - len,
"%d\t", freq);
- len += snprintf(buf + len, size - len,
+ len += scnprintf(buf + len, size - len,
"%d\t%d\t%d\t%d\t%d\t%d\n",
cal_pier->refPower,
cal_pier->voltMeas,
@@ -3505,12 +3505,12 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
len += scnprintf(buf + len, size - len, "Calibration data\n");
len = ar9003_dump_cal_data(ah, buf, len, size, true);
- len += snprintf(buf + len, size - len,
+ len += scnprintf(buf + len, size - len,
"%20s :\n", "5GHz modal Header");
len = ar9003_dump_modal_eeprom(buf, len, size,
&eep->modalHeader5G);
- len += snprintf(buf + len, size - len, "Calibration data\n");
+ len += scnprintf(buf + len, size - len, "Calibration data\n");
len = ar9003_dump_cal_data(ah, buf, len, size, false);
goto out;
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 0fca44e91a71..a412b352182c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -112,8 +112,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_TXFIFO_DEPTH 8
#define ATH_TX_ERROR 0x01
-#define ATH_AIRTIME_QUANTUM 300 /* usec */
-
/* Stop tx traffic 1ms before the GO goes away */
#define ATH_P2P_PS_STOP_TIME 1000
@@ -246,10 +244,8 @@ struct ath_atx_tid {
s8 bar_index;
bool active;
bool clear_ps_filter;
- bool has_queued;
};
-void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
struct ath_node {
@@ -263,12 +259,9 @@ struct ath_node {
bool sleeping;
bool no_ps_filter;
- s64 airtime_deficit[IEEE80211_NUM_ACS];
- u32 airtime_rx_start;
#ifdef CONFIG_ATH9K_STATION_STATISTICS
struct ath_rx_rate_stats rx_rate_stats;
- struct ath_airtime_stats airtime_stats;
#endif
u8 key_idx[4];
@@ -986,11 +979,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
-#define AIRTIME_USE_TX BIT(0)
-#define AIRTIME_USE_RX BIT(1)
-#define AIRTIME_USE_NEW_QUEUES BIT(2)
-#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
-
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
@@ -1034,8 +1022,6 @@ struct ath_softc {
short nbcnvifs;
unsigned long ps_usecount;
- u16 airtime_flags; /* AIRTIME_* */
-
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index 6aa3ec024ffa..21191955a7c1 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -1039,6 +1039,9 @@ static struct dentry *create_buf_file_handler(const char *filename,
buf_file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
+ if (IS_ERR(buf_file))
+ return NULL;
+
*is_global = 1;
return buf_file;
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 4399e9ad058f..26ea51a72156 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -148,7 +148,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
{ "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
{ "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
{ "SPUR UP", ah->stats.ast_ani_spurup },
- { "SPUR DOWN", ah->stats.ast_ani_spurup },
+ { "SPUR DOWN", ah->stats.ast_ani_spurdown },
{ "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
{ "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
{ "MRC-CCK ON", ah->stats.ast_ani_ccklow },
@@ -1443,9 +1443,6 @@ int ath9k_init_debug(struct ath_hw *ah)
#endif
debugfs_create_file("tpc", 0600, sc->debug.debugfs_phy, sc, &fops_tpc);
- debugfs_create_u16("airtime_flags", 0600,
- sc->debug.debugfs_phy, &sc->airtime_flags);
-
debugfs_create_file("nf_override", 0600,
sc->debug.debugfs_phy, sc, &fops_nf_override);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 79607db14387..33826aa13687 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -319,20 +319,12 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
void ath_debug_rate_stats(struct ath_softc *sc,
struct ath_rx_status *rs,
struct sk_buff *skb);
-void ath_debug_airtime(struct ath_softc *sc,
- struct ath_node *an,
- u32 rx, u32 tx);
#else
static inline void ath_debug_rate_stats(struct ath_softc *sc,
struct ath_rx_status *rs,
struct sk_buff *skb)
{
}
-static inline void ath_debug_airtime(struct ath_softc *sc,
- struct ath_node *an,
- u32 rx, u32 tx)
-{
-}
#endif /* CONFIG_ATH9K_STATION_STATISTICS */
#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index e8fcd3e1c470..d95cabddce33 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -242,75 +242,6 @@ static const struct file_operations fops_node_recv = {
.llseek = default_llseek,
};
-void ath_debug_airtime(struct ath_softc *sc,
- struct ath_node *an,
- u32 rx,
- u32 tx)
-{
- struct ath_airtime_stats *astats = &an->airtime_stats;
-
- astats->rx_airtime += rx;
- astats->tx_airtime += tx;
-}
-
-static ssize_t read_airtime(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath_node *an = file->private_data;
- struct ath_airtime_stats *astats;
- static const char *qname[4] = {
- "VO", "VI", "BE", "BK"
- };
- u32 len = 0, size = 256;
- char *buf;
- size_t retval;
- int i;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- astats = &an->airtime_stats;
-
- len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
- len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
- len += scnprintf(buf + len, size - len, "Deficit: ");
- for (i = 0; i < 4; i++)
- len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
- if (len < size)
- buf[len++] = '\n';
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-}
-
-static ssize_t
-write_airtime_reset_stub(struct file *file, const char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- struct ath_node *an = file->private_data;
- struct ath_airtime_stats *astats;
- int i;
-
- astats = &an->airtime_stats;
- astats->rx_airtime = 0;
- astats->tx_airtime = 0;
- for (i = 0; i < 4; i++)
- an->airtime_deficit[i] = ATH_AIRTIME_QUANTUM;
- return count;
-}
-
-static const struct file_operations fops_airtime = {
- .read = read_airtime,
- .write = write_airtime_reset_stub,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-
void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -320,5 +251,4 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
debugfs_create_file("node_aggr", 0444, dir, an, &fops_node_aggr);
debugfs_create_file("node_recv", 0444, dir, an, &fops_node_recv);
- debugfs_create_file("airtime", 0644, dir, an, &fops_airtime);
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 799010ed04e0..4e8e80ac8341 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -574,12 +574,12 @@ void ath9k_tx_failed_tasklet(unsigned long data)
{
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
- spin_lock_bh(&priv->tx.tx_lock);
+ spin_lock(&priv->tx.tx_lock);
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
- spin_unlock_bh(&priv->tx.tx_lock);
+ spin_unlock(&priv->tx.tx_lock);
return;
}
- spin_unlock_bh(&priv->tx.tx_lock);
+ spin_unlock(&priv->tx.tx_lock);
ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
}
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c070a9e51ebf..98141b699c88 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -636,15 +636,15 @@ static int ath9k_of_init(struct ath_softc *sc)
ret = ath9k_eeprom_request(sc, eeprom_name);
if (ret)
return ret;
+
+ ah->ah_flags &= ~AH_USE_EEPROM;
+ ah->ah_flags |= AH_NO_EEP_SWAP;
}
mac = of_get_mac_address(np);
if (mac)
ether_addr_copy(common->macaddr, mac);
- ah->ah_flags &= ~AH_USE_EEPROM;
- ah->ah_flags |= AH_NO_EEP_SWAP;
-
return 0;
}
@@ -676,8 +676,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
/* Will be cleared in ath9k_start() */
set_bit(ATH_OP_INVALID, &common->op_flags);
- sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
- AIRTIME_USE_NEW_QUEUES);
sc->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
@@ -1013,6 +1011,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
}
int ath9k_init_device(u16 devid, struct ath_softc *sc,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 30d1bd832d90..4e97f7f3b2a3 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1006,9 +1006,6 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
struct ath_rx_status *rs,
struct sk_buff *skb)
{
- struct ath_node *an;
- struct ath_acq *acq;
- struct ath_vif *avp;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -1019,7 +1016,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
int phy;
u16 len = rs->rs_datalen;
u32 airtime = 0;
- u8 tidno, acno;
+ u8 tidno;
if (!ieee80211_is_data(hdr->frame_control))
return;
@@ -1029,11 +1026,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
if (!sta)
goto exit;
- an = (struct ath_node *) sta->drv_priv;
- avp = (struct ath_vif *) an->vif->drv_priv;
tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
- acno = TID_TO_WME_AC(tidno);
- acq = &avp->chanctx->acq[acno];
rxs = IEEE80211_SKB_RXCB(skb);
@@ -1054,14 +1047,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
len, rxs->rate_idx, is_sp);
}
- if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
- spin_lock_bh(&acq->lock);
- an->airtime_deficit[acno] -= airtime;
- if (an->airtime_deficit[acno] <= 0)
- __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
- spin_unlock_bh(&acq->lock);
- }
- ath_debug_airtime(sc, an, airtime, 0);
+ ieee80211_sta_register_airtime(sta, tidno, 0, airtime);
exit:
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f448d5716639..773d428ff1b0 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -113,44 +113,14 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
ath_tx_status(hw, skb);
}
-void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
- struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
- struct ath_chanctx *ctx = avp->chanctx;
- struct ath_acq *acq;
- struct list_head *tid_list;
- u8 acno = TID_TO_WME_AC(tid->tidno);
-
- if (!ctx || !list_empty(&tid->list))
- return;
-
-
- acq = &ctx->acq[acno];
- if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) &&
- tid->an->airtime_deficit[acno] > 0)
- tid_list = &acq->acq_new;
- else
- tid_list = &acq->acq_old;
-
- list_add_tail(&tid->list, tid_list);
-}
-
void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
- struct ath_chanctx *ctx = avp->chanctx;
- struct ath_acq *acq;
+ struct ieee80211_txq *queue =
+ container_of((void *)tid, struct ieee80211_txq, drv_priv);
- if (!ctx || !list_empty(&tid->list))
- return;
-
- acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
- spin_lock_bh(&acq->lock);
- __ath_tx_queue_tid(sc, tid);
- spin_unlock_bh(&acq->lock);
+ ieee80211_schedule_txq(sc->hw, queue);
}
-
void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
{
struct ath_softc *sc = hw->priv;
@@ -163,11 +133,7 @@ void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
tid->tidno);
ath_txq_lock(sc, txq);
-
- tid->has_queued = true;
- ath_tx_queue_tid(sc, tid);
ath_txq_schedule(sc, txq);
-
ath_txq_unlock(sc, txq);
}
@@ -217,8 +183,8 @@ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
return ATH_AN_2_TID(an, tidno);
}
-static struct sk_buff *
-ath_tid_pull(struct ath_atx_tid *tid)
+static int
+ath_tid_pull(struct ath_atx_tid *tid, struct sk_buff **skbuf)
{
struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv);
struct ath_softc *sc = tid->an->sc;
@@ -229,20 +195,16 @@ ath_tid_pull(struct ath_atx_tid *tid)
};
struct sk_buff *skb;
struct ath_frame_info *fi;
- int q;
-
- if (!tid->has_queued)
- return NULL;
+ int q, ret;
skb = ieee80211_tx_dequeue(hw, txq);
- if (!skb) {
- tid->has_queued = false;
- return NULL;
- }
+ if (!skb)
+ return -ENOENT;
- if (ath_tx_prepare(hw, skb, &txctl)) {
+ ret = ath_tx_prepare(hw, skb, &txctl);
+ if (ret) {
ieee80211_free_txskb(hw, skb);
- return NULL;
+ return ret;
}
q = skb_get_queue_mapping(skb);
@@ -252,24 +214,19 @@ ath_tid_pull(struct ath_atx_tid *tid)
++tid->txq->pending_frames;
}
- return skb;
-}
-
-
-static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
-{
- return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
+ *skbuf = skb;
+ return 0;
}
-static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
+static int ath_tid_dequeue(struct ath_atx_tid *tid,
+ struct sk_buff **skb)
{
- struct sk_buff *skb;
+ int ret = 0;
+ *skb = __skb_dequeue(&tid->retry_q);
+ if (!*skb)
+ ret = ath_tid_pull(tid, skb);
- skb = __skb_dequeue(&tid->retry_q);
- if (!skb)
- skb = ath_tid_pull(tid);
-
- return skb;
+ return ret;
}
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
@@ -365,11 +322,12 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
struct list_head bf_head;
struct ath_tx_status ts;
struct ath_frame_info *fi;
+ int ret;
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- while ((skb = ath_tid_dequeue(tid))) {
+ while ((ret = ath_tid_dequeue(tid, &skb)) == 0) {
fi = get_frame_info(skb);
bf = fi->bf;
@@ -681,7 +639,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
skb_queue_splice_tail(&bf_pending, &tid->retry_q);
if (!an->sleeping) {
ath_tx_queue_tid(sc, tid);
-
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->clear_ps_filter = true;
}
@@ -708,11 +665,11 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
-static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
- struct ath_atx_tid *tid, struct ath_buf *bf,
+static void ath_tx_count_airtime(struct ath_softc *sc,
+ struct ieee80211_sta *sta,
+ struct ath_buf *bf,
struct ath_tx_status *ts)
{
- struct ath_txq *txq = tid->txq;
u32 airtime = 0;
int i;
@@ -722,17 +679,7 @@ static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
airtime += rate_dur * bf->rates[i].count;
}
- if (sc->airtime_flags & AIRTIME_USE_TX) {
- int q = txq->mac80211_qnum;
- struct ath_acq *acq = &sc->cur_chan->acq[q];
-
- spin_lock_bh(&acq->lock);
- an->airtime_deficit[q] -= airtime;
- if (an->airtime_deficit[q] <= 0)
- __ath_tx_queue_tid(sc, tid);
- spin_unlock_bh(&acq->lock);
- }
- ath_debug_airtime(sc, an, 0, airtime);
+ ieee80211_sta_register_airtime(sta, ts->tid, airtime, 0);
}
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
@@ -762,7 +709,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
if (sta) {
struct ath_node *an = (struct ath_node *)sta->drv_priv;
tid = ath_get_skb_tid(sc, an, bf->bf_mpdu);
- ath_tx_count_airtime(sc, an, tid, bf, ts);
+ ath_tx_count_airtime(sc, sta, bf, ts);
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->clear_ps_filter = true;
}
@@ -947,20 +894,21 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
return ndelim;
}
-static struct ath_buf *
+static int
ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid)
+ struct ath_atx_tid *tid, struct ath_buf **buf)
{
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
- struct sk_buff *skb, *first_skb = NULL;
struct ath_buf *bf;
+ struct sk_buff *skb, *first_skb = NULL;
u16 seqno;
+ int ret;
while (1) {
- skb = ath_tid_dequeue(tid);
- if (!skb)
- break;
+ ret = ath_tid_dequeue(tid, &skb);
+ if (ret < 0)
+ return ret;
fi = get_frame_info(skb);
bf = fi->bf;
@@ -992,7 +940,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
bf->bf_state.bf_type = 0;
- return bf;
+ break;
}
bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
@@ -1011,7 +959,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
first_skb = skb;
continue;
}
- break;
+ return -EINPROGRESS;
}
if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
@@ -1028,10 +976,11 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
if (bf_isampdu(bf))
ath_tx_addto_baw(sc, tid, bf);
- return bf;
+ break;
}
- return NULL;
+ *buf = bf;
+ return 0;
}
static int
@@ -1041,7 +990,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
struct ath_buf *bf = bf_first, *bf_prev = NULL;
- int nframes = 0, ndelim;
+ int nframes = 0, ndelim, ret;
u16 aggr_limit = 0, al = 0, bpad = 0,
al_delta, h_baw = tid->baw_size / 2;
struct ieee80211_tx_info *tx_info;
@@ -1093,7 +1042,9 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf_prev = bf;
- bf = ath_tx_get_tid_subframe(sc, txq, tid);
+ ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf);
+ if (ret < 0)
+ break;
}
goto finish;
stop:
@@ -1490,7 +1441,7 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf_first)
{
struct ath_buf *bf = bf_first, *bf_prev = NULL;
- int nframes = 0;
+ int nframes = 0, ret;
do {
struct ieee80211_tx_info *tx_info;
@@ -1504,8 +1455,8 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
if (nframes >= 2)
break;
- bf = ath_tx_get_tid_subframe(sc, txq, tid);
- if (!bf)
+ ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf);
+ if (ret < 0)
break;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
@@ -1518,30 +1469,27 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
} while (1);
}
-static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid)
+static int ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid)
{
- struct ath_buf *bf;
+ struct ath_buf *bf = NULL;
struct ieee80211_tx_info *tx_info;
struct list_head bf_q;
- int aggr_len = 0;
+ int aggr_len = 0, ret;
bool aggr;
- if (!ath_tid_has_buffered(tid))
- return false;
-
INIT_LIST_HEAD(&bf_q);
- bf = ath_tx_get_tid_subframe(sc, txq, tid);
- if (!bf)
- return false;
+ ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf);
+ if (ret < 0)
+ return ret;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
- return false;
+ return -EBUSY;
}
ath_set_rates(tid->an->vif, tid->an->sta, bf);
@@ -1551,7 +1499,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
if (list_empty(&bf_q))
- return false;
+ return -EAGAIN;
if (tid->clear_ps_filter || tid->an->no_ps_filter) {
tid->clear_ps_filter = false;
@@ -1560,7 +1508,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_fill_desc(sc, bf, txq, aggr_len);
ath_tx_txqaddbuf(sc, txq, &bf_q, false);
- return true;
+ return 0;
}
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -1623,28 +1571,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
- struct ath_txq *txq;
int tidno;
ath_dbg(common, XMIT, "%s called\n", __func__);
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
tid = ath_node_to_tid(an, tidno);
- txq = tid->txq;
-
- ath_txq_lock(sc, txq);
-
- if (list_empty(&tid->list)) {
- ath_txq_unlock(sc, txq);
- continue;
- }
if (!skb_queue_empty(&tid->retry_q))
ieee80211_sta_set_buffered(sta, tid->tidno, true);
- list_del_init(&tid->list);
-
- ath_txq_unlock(sc, txq);
}
}
@@ -1663,11 +1599,12 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ath_txq_lock(sc, txq);
tid->clear_ps_filter = true;
- if (ath_tid_has_buffered(tid)) {
+ if (!skb_queue_empty(&tid->retry_q)) {
ath_tx_queue_tid(sc, tid);
ath_txq_schedule(sc, txq);
}
ath_txq_unlock_complete(sc, txq);
+
}
}
@@ -1698,9 +1635,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ath_txq *txq = sc->tx.uapsdq;
struct ieee80211_tx_info *info;
struct list_head bf_q;
- struct ath_buf *bf_tail = NULL, *bf;
+ struct ath_buf *bf_tail = NULL, *bf = NULL;
int sent = 0;
- int i;
+ int i, ret;
INIT_LIST_HEAD(&bf_q);
for (i = 0; tids && nframes; i++, tids >>= 1) {
@@ -1713,8 +1650,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
ath_txq_lock(sc, tid->txq);
while (nframes > 0) {
- bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
- if (!bf)
+ ret = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq,
+ tid, &bf);
+ if (ret < 0)
break;
ath9k_set_moredata(sc, bf, true);
@@ -1980,11 +1918,11 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
*/
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
{
+ struct ieee80211_hw *hw = sc->hw;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_txq *queue;
struct ath_atx_tid *tid;
- struct list_head *tid_list;
- struct ath_acq *acq;
- bool active = AIRTIME_ACTIVE(sc->airtime_flags);
+ int ret;
if (txq->mac80211_qnum < 0)
return;
@@ -1992,58 +1930,26 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
return;
+ ieee80211_txq_schedule_start(hw, txq->mac80211_qnum);
spin_lock_bh(&sc->chan_lock);
rcu_read_lock();
- acq = &sc->cur_chan->acq[txq->mac80211_qnum];
if (sc->cur_chan->stopped)
goto out;
-begin:
- tid_list = &acq->acq_new;
- if (list_empty(tid_list)) {
- tid_list = &acq->acq_old;
- if (list_empty(tid_list))
- goto out;
- }
- tid = list_first_entry(tid_list, struct ath_atx_tid, list);
-
- if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
- spin_lock_bh(&acq->lock);
- tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM;
- list_move_tail(&tid->list, &acq->acq_old);
- spin_unlock_bh(&acq->lock);
- goto begin;
- }
-
- if (!ath_tid_has_buffered(tid)) {
- spin_lock_bh(&acq->lock);
- if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old))
- list_move_tail(&tid->list, &acq->acq_old);
- else {
- list_del_init(&tid->list);
- }
- spin_unlock_bh(&acq->lock);
- goto begin;
- }
+ while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) {
+ tid = (struct ath_atx_tid *)queue->drv_priv;
+ ret = ath_tx_sched_aggr(sc, txq, tid);
+ ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret);
- /*
- * If we succeed in scheduling something, immediately restart to make
- * sure we keep the HW busy.
- */
- if(ath_tx_sched_aggr(sc, txq, tid)) {
- if (!active) {
- spin_lock_bh(&acq->lock);
- list_move_tail(&tid->list, &acq->acq_old);
- spin_unlock_bh(&acq->lock);
- }
- goto begin;
+ ieee80211_return_txq(hw, queue);
}
out:
rcu_read_unlock();
spin_unlock_bh(&sc->chan_lock);
+ ieee80211_txq_schedule_end(hw, txq->mac80211_qnum);
}
void ath_txq_schedule_all(struct ath_softc *sc)
@@ -2646,6 +2552,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
}
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
+
+ /* we report airtime in ath_tx_count_airtime(), don't report twice */
+ tx_info->status.tx_time = 0;
}
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
@@ -2887,9 +2796,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
struct ath_atx_tid *tid;
int tidno, acno;
- for (acno = 0; acno < IEEE80211_NUM_ACS; acno++)
- an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM;
-
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
tid = ath_node_to_tid(an, tidno);
tid->an = an;
@@ -2899,7 +2805,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->baw_head = tid->baw_tail = 0;
tid->active = false;
tid->clear_ps_filter = true;
- tid->has_queued = false;
__skb_queue_head_init(&tid->retry_q);
INIT_LIST_HEAD(&tid->list);
acno = TID_TO_WME_AC(tidno);
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index f7c2f19e81c1..8e154f6364a3 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -427,7 +427,7 @@ static int carl9170_rx_mac_status(struct ar9170 *ar,
if (head->plcp[6] & 0x80)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f);
+ status->rate_idx = clamp(head->plcp[3] & 0x7f, 0, 75);
status->encoding = RX_ENC_HT;
break;
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index d73e45e26547..75ddaefdd049 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -185,7 +185,9 @@ enum CountryCode {
CTRY_UKRAINE = 804,
CTRY_UNITED_KINGDOM = 826,
CTRY_UNITED_STATES = 840,
+ CTRY_UNITED_STATES2 = 841,
CTRY_UNITED_STATES_FCC49 = 842,
+ CTRY_UNITED_STATES3 = 843,
CTRY_URUGUAY = 858,
CTRY_UZBEKISTAN = 860,
CTRY_VENEZUELA = 862,
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
index 4021e37a225a..c4bd26e65949 100644
--- a/drivers/net/wireless/ath/regd_common.h
+++ b/drivers/net/wireless/ath/regd_common.h
@@ -483,6 +483,8 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_UAE, NULL1_WORLD, "AE"},
{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
+ {CTRY_UNITED_STATES2, FCC3_FCCA, "US"},
+ {CTRY_UNITED_STATES3, FCC3_FCCA, "US"},
/* This "PS" is for US public safety actually... to support this we
* would need to assign new special alpha2 to CRDA db as with the world
* regdomain and use another alpha2 */
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 5ab3e31c9ffa..bab30f7a443c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -174,9 +174,8 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
int i;
size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
- wcn_ch->cpu_addr = dma_zalloc_coherent(dev, size,
- &wcn_ch->dma_addr,
- GFP_KERNEL);
+ wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
+ GFP_KERNEL);
if (!wcn_ch->cpu_addr)
return -ENOMEM;
@@ -627,9 +626,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
- cpu_addr = dma_zalloc_coherent(wcn->dev, s,
- &wcn->mgmt_mem_pool.phy_addr,
- GFP_KERNEL);
+ cpu_addr = dma_alloc_coherent(wcn->dev, s,
+ &wcn->mgmt_mem_pool.phy_addr,
+ GFP_KERNEL);
if (!cpu_addr)
goto out_err;
@@ -642,9 +641,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
- cpu_addr = dma_zalloc_coherent(wcn->dev, s,
- &wcn->data_mem_pool.phy_addr,
- GFP_KERNEL);
+ cpu_addr = dma_alloc_coherent(wcn->dev, s,
+ &wcn->data_mem_pool.phy_addr,
+ GFP_KERNEL);
if (!cpu_addr)
goto out_err;
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 9b2f9f543952..a1e226652b4a 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -395,7 +395,7 @@ static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
{
int i;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
if (wil->sta[i].status == wil_sta_unused)
continue;
if (wil->sta[i].mid != mid)
@@ -1580,6 +1580,12 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
u8 *buf, *dpos;
const u8 *spos;
+ if (!ies1)
+ ies1_len = 0;
+
+ if (!ies2)
+ ies2_len = 0;
+
if (ies1_len == 0 && ies2_len == 0) {
*merged_ies = NULL;
*merged_len = 0;
@@ -1589,17 +1595,19 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- memcpy(buf, ies1, ies1_len);
+ if (ies1)
+ memcpy(buf, ies1, ies1_len);
dpos = buf + ies1_len;
spos = ies2;
- while (spos + 1 < ies2 + ies2_len) {
+ while (spos && (spos + 1 < ies2 + ies2_len)) {
/* IE tag at offset 0, length at offset 1 */
u16 ielen = 2 + spos[1];
if (spos + ielen > ies2 + ies2_len)
break;
if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
- !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
+ (!ies1 || !_wil_cfg80211_find_ie(ies1, ies1_len,
+ spos, ielen))) {
memcpy(dpos, spos, ielen);
dpos += ielen;
}
@@ -3007,7 +3015,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,
sector_type, WIL_CID_ALL);
if (rc == -EINVAL) {
- for (i = 0; i < WIL6210_MAX_CID; i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
if (wil->sta[i].mid != vif->mid)
continue;
rc = wil_rf_sector_wmi_set_selected(
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 835c902b84c1..7ad4e5328439 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -162,7 +162,7 @@ static int ring_show(struct seq_file *s, void *data)
snprintf(name, sizeof(name), "tx_%2d", i);
- if (cid < WIL6210_MAX_CID)
+ if (cid < max_assoc_sta)
seq_printf(s,
"\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",
wil->sta[cid].addr, cid, tid,
@@ -792,14 +792,14 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
"BACK: del_rx require at least 2 params\n");
return -EINVAL;
}
- if (p1 < 0 || p1 >= WIL6210_MAX_CID) {
+ if (p1 < 0 || p1 >= max_assoc_sta) {
wil_err(wil, "BACK: invalid CID %d\n", p1);
return -EINVAL;
}
if (rc < 4)
p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
sta = &wil->sta[p1];
- wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3);
+ wmi_delba_rx(wil, sta->mid, p1, p2, p3);
} else {
wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
return -EINVAL;
@@ -1243,7 +1243,7 @@ static int bf_show(struct seq_file *s, void *data)
memset(&reply, 0, sizeof(reply));
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
u32 status;
cmd.cid = i;
@@ -1340,7 +1340,7 @@ static int link_show(struct seq_file *s, void *data)
if (!sinfo)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
struct wil_sta_info *p = &wil->sta[i];
char *status = "unknown";
struct wil6210_vif *vif;
@@ -1542,7 +1542,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
struct wil6210_priv *wil = s->private;
int i, tid, mcs;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
struct wil_sta_info *p = &wil->sta[i];
char *status = "unknown";
u8 aid = 0;
@@ -1651,7 +1651,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
struct wil6210_priv *wil = s->private;
int i, bin;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
struct wil_sta_info *p = &wil->sta[i];
char *status = "unknown";
u8 aid = 0;
@@ -1740,7 +1740,7 @@ static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf,
size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS;
wil->tx_latency_res = val;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
struct wil_sta_info *sta = &wil->sta[i];
kfree(sta->tx_latency_bins);
@@ -1825,7 +1825,7 @@ static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif,
}
seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf);
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
if (wil->sta[i].status == wil_sta_unused)
continue;
if (wil->sta[i].mid != vif->mid)
@@ -2386,6 +2386,7 @@ static const struct dbg_off dbg_statics[] = {
{"led_polarity", 0644, (ulong)&led_polarity, doff_u8},
{"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32},
{"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32},
+ {"drop_if_ring_full", 0644, (ulong)&drop_if_ring_full, doff_u8},
{},
};
@@ -2439,7 +2440,7 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil)
wil->debug = NULL;
kfree(wil->dbg_data.data_arr);
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++)
+ for (i = 0; i < max_assoc_sta; i++)
kfree(wil->sta[i].tx_latency_bins);
/* free pmc memory without sending command to fw, as it will
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 5d287a8e1b45..3f5bd177d55f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
}
if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
- wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
- wil6210_mask_halp(wil);
isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
- complete(&wil->halp.comp);
+ if (wil->halp.handle_icr) {
+ /* no need to handle HALP ICRs until next vote */
+ wil->halp.handle_icr = false;
+ wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
+ wil6210_mask_halp(wil);
+ complete(&wil->halp.comp);
+ }
}
wil->isr_misc = isr;
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 5b7de00affe2..277abfdf3322 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -219,7 +219,7 @@ static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid)
{
int i;
- for (i = 0; i < WIL6210_MAX_CID; i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
if (wil->sta[i].mid == mid &&
wil->sta[i].status == wil_sta_connected)
return true;
@@ -322,7 +322,7 @@ static void _wil6210_disconnect_complete(struct wil6210_vif *vif,
wil_disconnect_cid_complete(vif, cid, reason_code);
} else { /* all */
wil_dbg_misc(wil, "Disconnect complete all\n");
- for (cid = 0; cid < WIL6210_MAX_CID; cid++)
+ for (cid = 0; cid < max_assoc_sta; cid++)
wil_disconnect_cid_complete(vif, cid, reason_code);
}
@@ -434,7 +434,7 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
wil_disconnect_cid(vif, cid, reason_code);
} else { /* all */
wil_dbg_misc(wil, "Disconnect all\n");
- for (cid = 0; cid < WIL6210_MAX_CID; cid++)
+ for (cid = 0; cid < max_assoc_sta; cid++)
wil_disconnect_cid(vif, cid, reason_code);
}
@@ -1895,7 +1895,7 @@ int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac)
int i;
int rc = -ENOENT;
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ for (i = 0; i < max_assoc_sta; i++) {
if (wil->sta[i].mid == mid &&
wil->sta[i].status != wil_sta_unused &&
ether_addr_equal(wil->sta[i].addr, mac)) {
@@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil)
if (++wil->halp.ref_cnt == 1) {
reinit_completion(&wil->halp.comp);
+ /* mark to IRQ context to handle HALP ICR */
+ wil->halp.handle_icr = true;
wil6210_set_halp(wil);
rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
if (!rc) {
wil_err(wil, "HALP vote timed out\n");
/* Mask HALP as done in case the interrupt is raised */
+ wil->halp.handle_icr = false;
wil6210_mask_halp(wil);
} else {
wil_dbg_irq(wil,
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 983bd001b53b..32b14fc33a59 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -307,8 +307,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
}
/* Block Ack - Rx side (recipient) */
-int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
- u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
+int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
+ u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
@@ -316,7 +316,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
u16 agg_timeout = le16_to_cpu(ba_timeout);
u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl);
struct wil_sta_info *sta;
- u8 cid, tid;
u16 agg_wsize = 0;
/* bit 0: A-MSDU supported
* bit 1: policy (should be 0 for us)
@@ -335,10 +334,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
int rc = 0;
might_sleep();
- parse_cidxtid(cidxtid, &cid, &tid);
/* sanity checks */
- if (cid >= WIL6210_MAX_CID) {
+ if (cid >= max_assoc_sta) {
wil_err(wil, "BACK: invalid CID %d\n", cid);
rc = -EINVAL;
goto out;
diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h
index 853abc3a73e4..36ebfcf9ef30 100644
--- a/drivers/net/wireless/ath/wil6210/trace.h
+++ b/drivers/net/wireless/ath/wil6210/trace.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -181,7 +182,7 @@ TRACE_EVENT(wil6210_rx,
__entry->seq = wil_rxdesc_seq(d);
__entry->mcs = wil_rxdesc_mcs(d);
),
- TP_printk("index %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x"
+ TP_printk("index %d len %d mid %d cid (%%8) %d tid %d mcs %d seq 0x%03x"
" type 0x%1x subtype 0x%1x", __entry->index, __entry->len,
__entry->mid, __entry->cid, __entry->tid, __entry->mcs,
__entry->seq, __entry->type, __entry->subtype)
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 3e1c831ab2fb..4ccfd1404458 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,11 +30,6 @@
#include "trace.h"
#include "txrx_edma.h"
-static bool rtap_include_phy_info;
-module_param(rtap_include_phy_info, bool, 0444);
-MODULE_PARM_DESC(rtap_include_phy_info,
- " Include PHY info in the radiotap header, default - no");
-
bool rx_align_2;
module_param(rx_align_2, bool, 0444);
MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no");
@@ -43,6 +38,9 @@ bool rx_large_buf;
module_param(rx_large_buf, bool, 0444);
MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no");
+/* Drop Tx packets in case Tx ring is full */
+bool drop_if_ring_full;
+
static inline uint wil_rx_snaplen(void)
{
return rx_align_2 ? 6 : 0;
@@ -332,87 +330,34 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
u8 mcs_flags;
u8 mcs_index;
} __packed;
- struct wil6210_rtap_vendor {
- struct wil6210_rtap rtap;
- /* vendor */
- u8 vendor_oui[3] __aligned(2);
- u8 vendor_ns;
- __le16 vendor_skip;
- u8 vendor_data[0];
- } __packed;
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
- struct wil6210_rtap_vendor *rtap_vendor;
+ struct wil6210_rtap *rtap;
int rtap_len = sizeof(struct wil6210_rtap);
- int phy_length = 0; /* phy info header size, bytes */
- static char phy_data[128];
struct ieee80211_channel *ch = wil->monitor_chandef.chan;
- if (rtap_include_phy_info) {
- rtap_len = sizeof(*rtap_vendor) + sizeof(*d);
- /* calculate additional length */
- if (d->dma.status & RX_DMA_STATUS_PHY_INFO) {
- /**
- * PHY info starts from 8-byte boundary
- * there are 8-byte lines, last line may be partially
- * written (HW bug), thus FW configures for last line
- * to be excessive. Driver skips this last line.
- */
- int len = min_t(int, 8 + sizeof(phy_data),
- wil_rxdesc_phy_length(d));
-
- if (len > 8) {
- void *p = skb_tail_pointer(skb);
- void *pa = PTR_ALIGN(p, 8);
-
- if (skb_tailroom(skb) >= len + (pa - p)) {
- phy_length = len - 8;
- memcpy(phy_data, pa, phy_length);
- }
- }
- }
- rtap_len += phy_length;
- }
-
if (skb_headroom(skb) < rtap_len &&
pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) {
wil_err(wil, "Unable to expand headroom to %d\n", rtap_len);
return;
}
- rtap_vendor = skb_push(skb, rtap_len);
- memset(rtap_vendor, 0, rtap_len);
+ rtap = skb_push(skb, rtap_len);
+ memset(rtap, 0, rtap_len);
- rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
- rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len);
- rtap_vendor->rtap.rthdr.it_present = cpu_to_le32(
- (1 << IEEE80211_RADIOTAP_FLAGS) |
+ rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
+ rtap->rthdr.it_len = cpu_to_le16(rtap_len);
+ rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
(1 << IEEE80211_RADIOTAP_MCS));
if (d->dma.status & RX_DMA_STATUS_ERROR)
- rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS;
-
- rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
- rtap_vendor->rtap.chnl_flags = cpu_to_le16(0);
-
- rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
- rtap_vendor->rtap.mcs_flags = 0;
- rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d);
-
- if (rtap_include_phy_info) {
- rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 <<
- IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
- /* OUI for Wilocity 04:ce:14 */
- rtap_vendor->vendor_oui[0] = 0x04;
- rtap_vendor->vendor_oui[1] = 0xce;
- rtap_vendor->vendor_oui[2] = 0x14;
- rtap_vendor->vendor_ns = 1;
- /* Rx descriptor + PHY data */
- rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) +
- phy_length);
- memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d));
- memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data,
- phy_length);
- }
+ rtap->flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+ rtap->chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
+ rtap->chnl_flags = cpu_to_le16(0);
+
+ rtap->mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
+ rtap->mcs_flags = 0;
+ rtap->mcs_index = wil_rxdesc_mcs(d);
}
static bool wil_is_rx_idle(struct wil6210_priv *wil)
@@ -427,6 +372,76 @@ static bool wil_is_rx_idle(struct wil6210_priv *wil)
return true;
}
+static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb)
+{
+ struct vring_rx_desc *d = wil_skb_rxdesc(skb);
+ int mid = wil_rxdesc_mid(d);
+ struct wil6210_vif *vif = wil->vifs[mid];
+ /* cid from DMA descriptor is limited to 3 bits.
+ * In case of cid>=8, the value would be cid modulo 8 and we need to
+ * find real cid by locating the transmitter (ta) inside sta array
+ */
+ int cid = wil_rxdesc_cid(d);
+ unsigned int snaplen = wil_rx_snaplen();
+ struct ieee80211_hdr_3addr *hdr;
+ int i;
+ unsigned char *ta;
+ u8 ftype;
+
+ /* in monitor mode there are no connections */
+ if (vif->wdev.iftype == NL80211_IFTYPE_MONITOR)
+ return cid;
+
+ ftype = wil_rxdesc_ftype(d) << 2;
+ if (likely(ftype == IEEE80211_FTYPE_DATA)) {
+ if (unlikely(skb->len < ETH_HLEN + snaplen)) {
+ wil_err_ratelimited(wil,
+ "Short data frame, len = %d\n",
+ skb->len);
+ return -ENOENT;
+ }
+ ta = wil_skb_get_sa(skb);
+ } else {
+ if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
+ wil_err_ratelimited(wil, "Short frame, len = %d\n",
+ skb->len);
+ return -ENOENT;
+ }
+ hdr = (void *)skb->data;
+ ta = hdr->addr2;
+ }
+
+ if (max_assoc_sta <= WIL6210_RX_DESC_MAX_CID)
+ return cid;
+
+ /* assuming no concurrency between AP interfaces and STA interfaces.
+ * multista is used only in P2P_GO or AP mode. In other modes return
+ * cid from the rx descriptor
+ */
+ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_GO &&
+ vif->wdev.iftype != NL80211_IFTYPE_AP)
+ return cid;
+
+ /* For Rx packets cid from rx descriptor is limited to 3 bits (0..7),
+ * to find the real cid, compare transmitter address with the stored
+ * stations mac address in the driver sta array
+ */
+ for (i = cid; i < max_assoc_sta; i += WIL6210_RX_DESC_MAX_CID) {
+ if (wil->sta[i].status != wil_sta_unused &&
+ ether_addr_equal(wil->sta[i].addr, ta)) {
+ cid = i;
+ break;
+ }
+ }
+ if (i >= max_assoc_sta) {
+ wil_err_ratelimited(wil, "Could not find cid for frame with transmit addr = %pM, iftype = %d, frametype = %d, len = %d\n",
+ ta, vif->wdev.iftype, ftype, skb->len);
+ cid = -ENOENT;
+ }
+
+ return cid;
+}
+
/**
* reap 1 frame from @swhead
*
@@ -452,7 +467,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
int i;
struct wil_net_stats *stats;
- BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
+ BUILD_BUG_ON(sizeof(struct skb_rx_info) > sizeof(skb->cb));
again:
if (unlikely(wil_ring_is_empty(vring)))
@@ -484,7 +499,6 @@ again:
wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4,
(const void *)d, sizeof(*d), false);
- cid = wil_rxdesc_cid(d);
mid = wil_rxdesc_mid(d);
vif = wil->vifs[mid];
@@ -495,11 +509,9 @@ again:
goto again;
}
ndev = vif_to_ndev(vif);
- stats = &wil->sta[cid].stats;
-
if (unlikely(dmalen > sz)) {
- wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
- stats->rx_large_frame++;
+ wil_err_ratelimited(wil, "Rx size too large: %d bytes!\n",
+ dmalen);
kfree_skb(skb);
goto again;
}
@@ -510,6 +522,14 @@ again:
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb_headlen(skb), false);
+ cid = wil_rx_get_cid_by_skb(wil, skb);
+ if (cid == -ENOENT) {
+ kfree_skb(skb);
+ goto again;
+ }
+ wil_skb_set_cid(skb, (u8)cid);
+ stats = &wil->sta[cid].stats;
+
stats->last_mcs_rx = wil_rxdesc_mcs(d);
if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs))
stats->rx_per_mcs[stats->last_mcs_rx]++;
@@ -556,13 +576,6 @@ again:
goto again;
}
- if (unlikely(skb->len < ETH_HLEN + snaplen)) {
- wil_err(wil, "Short frame, len = %d\n", skb->len);
- stats->rx_short_frame++;
- kfree_skb(skb);
- goto again;
- }
-
/* L4 IDENT is on when HW calculated checksum, check status
* and in case of error drop the packet
* higher stack layers will handle retransmission (if required)
@@ -659,7 +672,7 @@ int reverse_memcmp(const void *cs, const void *ct, size_t count)
static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
{
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
- int cid = wil_rxdesc_cid(d);
+ int cid = wil_skb_get_cid(skb);
int tid = wil_rxdesc_tid(d);
int key_id = wil_rxdesc_key_id(d);
int mc = wil_rxdesc_mcast(d);
@@ -707,7 +720,7 @@ static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid,
{
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
- *cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
+ *cid = wil_skb_get_cid(skb);
*security = wil_rxdesc_security(d);
}
@@ -724,11 +737,11 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
unsigned int len = skb->len;
int cid;
int security;
- struct ethhdr *eth = (void *)skb->data;
+ u8 *sa, *da = wil_skb_get_da(skb);
/* here looking for DA, not A1, thus Rxdesc's 'mcast' indication
* is not suitable, need to look at data
*/
- int mcast = is_multicast_ether_addr(eth->h_dest);
+ int mcast = is_multicast_ether_addr(da);
struct wil_net_stats *stats;
struct sk_buff *xmit_skb = NULL;
static const char * const gro_res_str[] = {
@@ -759,7 +772,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
}
if (wdev->iftype == NL80211_IFTYPE_STATION) {
- if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) {
+ sa = wil_skb_get_sa(skb);
+ if (mcast && ether_addr_equal(sa, ndev->dev_addr)) {
/* mcast packet looped back to us */
rc = GRO_DROP;
dev_kfree_skb(skb);
@@ -772,8 +786,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
*/
xmit_skb = skb_copy(skb, GFP_ATOMIC);
} else {
- int xmit_cid = wil_find_cid(wil, vif->mid,
- eth->h_dest);
+ int xmit_cid = wil_find_cid(wil, vif->mid, da);
if (xmit_cid >= 0) {
/* The destination station is associated to
@@ -971,7 +984,6 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
.ring_size = cpu_to_le16(size),
},
.ringid = id,
- .cidxtid = mk_cidxtid(cid, tid),
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
.mac_ctrl = 0,
.to_resolution = 0,
@@ -991,6 +1003,14 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
struct wil_ring *vring = &wil->ring_tx[id];
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id];
+ if (cid >= WIL6210_RX_DESC_MAX_CID) {
+ cmd.vring_cfg.cidxtid = CIDXTID_EXTENDED_CID_TID;
+ cmd.vring_cfg.cid = cid;
+ cmd.vring_cfg.tid = tid;
+ } else {
+ cmd.vring_cfg.cidxtid = mk_cidxtid(cid, tid);
+ }
+
wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n",
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
lockdep_assert_held(&wil->mutex);
@@ -1043,7 +1063,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
txdata->enabled = 0;
spin_unlock_bh(&txdata->lock);
wil_vring_free(wil, vring);
- wil->ring2cid_tid[id][0] = WIL6210_MAX_CID;
+ wil->ring2cid_tid[id][0] = max_assoc_sta;
wil->ring2cid_tid[id][1] = 0;
out:
@@ -1128,7 +1148,7 @@ fail:
txdata->dot1x_open = false;
txdata->enabled = 0;
spin_unlock_bh(&txdata->lock);
- wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
+ wil->ring2cid_tid[ring_id][0] = max_assoc_sta;
wil->ring2cid_tid[ring_id][1] = 0;
return rc;
}
@@ -1175,7 +1195,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
if (rc)
goto out;
- wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */
+ wil->ring2cid_tid[id][0] = max_assoc_sta; /* CID */
wil->ring2cid_tid[id][1] = 0; /* TID */
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
@@ -1217,12 +1237,13 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil,
struct wil6210_vif *vif,
struct sk_buff *skb)
{
- int i;
- struct ethhdr *eth = (void *)skb->data;
- int cid = wil_find_cid(wil, vif->mid, eth->h_dest);
+ int i, cid;
+ const u8 *da = wil_skb_get_da(skb);
int min_ring_id = wil_get_min_tx_ring_id(wil);
- if (cid < 0)
+ cid = wil_find_cid(wil, vif->mid, da);
+
+ if (cid < 0 || cid >= max_assoc_sta)
return NULL;
/* TODO: fix for multiple TID */
@@ -1235,7 +1256,7 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil,
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];
wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n",
- eth->h_dest, i);
+ da, i);
if (v->va && txdata->enabled) {
return v;
} else {
@@ -1274,7 +1295,7 @@ static struct wil_ring *wil_find_tx_ring_sta(struct wil6210_priv *wil,
continue;
cid = wil->ring2cid_tid[i][0];
- if (cid >= WIL6210_MAX_CID) /* skip BCAST */
+ if (cid >= max_assoc_sta) /* skip BCAST */
continue;
if (!wil->ring_tx_data[i].dot1x_open &&
@@ -1326,10 +1347,10 @@ static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
static void wil_set_da_for_vring(struct wil6210_priv *wil,
struct sk_buff *skb, int vring_index)
{
- struct ethhdr *eth = (void *)skb->data;
+ u8 *da = wil_skb_get_da(skb);
int cid = wil->ring2cid_tid[vring_index][0];
- ether_addr_copy(eth->h_dest, wil->sta[cid].addr);
+ ether_addr_copy(da, wil->sta[cid].addr);
}
static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
@@ -1340,8 +1361,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
struct sk_buff *skb2;
int i;
u8 cid;
- struct ethhdr *eth = (void *)skb->data;
- char *src = eth->h_source;
+ const u8 *src = wil_skb_get_sa(skb);
struct wil_ring_tx_data *txdata, *txdata2;
int min_ring_id = wil_get_min_tx_ring_id(wil);
@@ -1353,7 +1373,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
continue;
cid = wil->ring2cid_tid[i][0];
- if (cid >= WIL6210_MAX_CID) /* skip BCAST */
+ if (cid >= max_assoc_sta) /* skip BCAST */
continue;
if (!wil->ring_tx_data[i].dot1x_open &&
skb->protocol != cpu_to_be16(ETH_P_PAE))
@@ -1381,7 +1401,7 @@ found:
if (!v2->va || txdata2->mid != vif->mid)
continue;
cid = wil->ring2cid_tid[i][0];
- if (cid >= WIL6210_MAX_CID) /* skip BCAST */
+ if (cid >= max_assoc_sta) /* skip BCAST */
continue;
if (!wil->ring_tx_data[i].dot1x_open &&
skb->protocol != cpu_to_be16(ETH_P_PAE))
@@ -2032,6 +2052,10 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d",
check_stop, vif->mid, vif->net_queue_stopped);
+ if (ring && drop_if_ring_full)
+ /* no need to stop/wake net queues */
+ return;
+
if (check_stop == vif->net_queue_stopped)
/* net queues already in desired state */
return;
@@ -2095,8 +2119,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wil6210_priv *wil = vif_to_wil(vif);
- struct ethhdr *eth = (void *)skb->data;
- bool bcast = is_multicast_ether_addr(eth->h_dest);
+ const u8 *da = wil_skb_get_da(skb);
+ bool bcast = is_multicast_ether_addr(da);
struct wil_ring *ring;
static bool pr_once_fw;
int rc;
@@ -2143,7 +2167,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
ring = wil_find_tx_ucast(wil, vif, skb);
}
if (unlikely(!ring)) {
- wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest);
+ wil_dbg_txrx(wil, "No Tx RING found for %pM\n", da);
goto drop;
}
/* set up vring entry */
@@ -2157,6 +2181,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
case -ENOMEM:
+ if (drop_if_ring_full)
+ goto drop;
return NETDEV_TX_BUSY;
default:
break; /* goto drop; */
@@ -2228,7 +2254,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid)
used_before_complete = wil_ring_used_tx(vring);
- if (cid < WIL6210_MAX_CID)
+ if (cid < max_assoc_sta)
stats = &wil->sta[cid].stats;
while (!wil_ring_is_empty(vring)) {
@@ -2337,7 +2363,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil,
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
*tid = wil_rxdesc_tid(d);
- *cid = wil_rxdesc_cid(d);
+ *cid = wil_skb_get_cid(skb);
*mid = wil_rxdesc_mid(d);
*seq = wil_rxdesc_seq(d);
*mcast = wil_rxdesc_mcast(d);
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 9d83be481839..c0da1340c2d2 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -458,6 +458,18 @@ union wil_ring_desc {
union wil_rx_desc rx;
} __packed;
+struct packet_rx_info {
+ u8 cid;
+};
+
+/* this struct will be stored in the skb cb buffer
+ * max length of the struct is limited to 48 bytes
+ */
+struct skb_rx_info {
+ struct vring_rx_desc rx_desc;
+ struct packet_rx_info rx_info;
+};
+
static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d0, 0, 3);
@@ -530,11 +542,6 @@ static inline int wil_rxdesc_mcast(struct vring_rx_desc *d)
return WIL_GET_BITS(d->mac.d1, 13, 14);
}
-static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
-{
- return WIL_GET_BITS(d->dma.d0, 16, 29);
-}
-
static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
{
return (void *)skb->cb;
@@ -560,11 +567,25 @@ static inline int wil_ring_is_full(struct wil_ring *ring)
return wil_ring_next_tail(ring) == ring->swhead;
}
-static inline bool wil_need_txstat(struct sk_buff *skb)
+static inline u8 *wil_skb_get_da(struct sk_buff *skb)
+{
+ struct ethhdr *eth = (void *)skb->data;
+
+ return eth->h_dest;
+}
+
+static inline u8 *wil_skb_get_sa(struct sk_buff *skb)
{
struct ethhdr *eth = (void *)skb->data;
- return is_unicast_ether_addr(eth->h_dest) && skb->sk &&
+ return eth->h_source;
+}
+
+static inline bool wil_need_txstat(struct sk_buff *skb)
+{
+ const u8 *da = wil_skb_get_da(skb);
+
+ return is_unicast_ether_addr(da) && skb->sk &&
(skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS);
}
@@ -610,6 +631,20 @@ static inline bool wil_val_in_range(int val, int min, int max)
return val >= min && val < max;
}
+static inline u8 wil_skb_get_cid(struct sk_buff *skb)
+{
+ struct skb_rx_info *skb_rx_info = (void *)skb->cb;
+
+ return skb_rx_info->rx_info.cid;
+}
+
+static inline void wil_skb_set_cid(struct sk_buff *skb, u8 cid)
+{
+ struct skb_rx_info *skb_rx_info = (void *)skb->cb;
+
+ skb_rx_info->rx_info.cid = cid;
+}
+
void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb);
void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif,
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index 05a8348bd7b9..c38773878ae3 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -99,7 +99,7 @@ static int wil_sring_alloc(struct wil6210_priv *wil,
/* Status messages are allocated and initialized to 0. This is necessary
* since DR bit should be initialized to 0.
*/
- sring->va = dma_zalloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
+ sring->va = dma_alloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
if (!sring->va)
return -ENOMEM;
@@ -381,15 +381,15 @@ static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil,
if (!ring->ctx)
goto err;
- ring->va = dma_zalloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
+ ring->va = dma_alloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
if (!ring->va)
goto err_free_ctx;
if (ring->is_rx) {
sz = sizeof(*ring->edma_rx_swtail.va);
ring->edma_rx_swtail.va =
- dma_zalloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
- GFP_KERNEL);
+ dma_alloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
+ GFP_KERNEL);
if (!ring->edma_rx_swtail.va)
goto err_free_va;
}
@@ -727,7 +727,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
txdata->enabled = 0;
spin_unlock_bh(&txdata->lock);
wil_ring_free_edma(wil, ring);
- wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
+ wil->ring2cid_tid[ring_id][0] = max_assoc_sta;
wil->ring2cid_tid[ring_id][1] = 0;
out:
@@ -932,7 +932,7 @@ again:
eop = wil_rx_status_get_eop(msg);
cid = wil_rx_status_get_cid(msg);
- if (unlikely(!wil_val_in_range(cid, 0, WIL6210_MAX_CID))) {
+ if (unlikely(!wil_val_in_range(cid, 0, max_assoc_sta))) {
wil_err(wil, "Corrupt cid=%d, sring->swhead=%d\n",
cid, sring->swhead);
rxdata->skipping = true;
@@ -1137,7 +1137,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
/* Total number of completed descriptors in all descriptor rings */
int desc_cnt = 0;
int cid;
- struct wil_net_stats *stats = NULL;
+ struct wil_net_stats *stats;
struct wil_tx_enhanced_desc *_d;
unsigned int ring_id;
unsigned int num_descs;
@@ -1187,8 +1187,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
ndev = vif_to_ndev(vif);
cid = wil->ring2cid_tid[ring_id][0];
- if (cid < WIL6210_MAX_CID)
- stats = &wil->sta[cid].stats;
+ stats = (cid < max_assoc_sta ? &wil->sta[cid].stats : NULL);
wil_dbg_txrx(wil,
"tx_status: completed desc_ring (%d), num_descs (%d)\n",
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 0f3be3ffc6a2..e1b1039b13ab 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -38,6 +38,8 @@ extern bool rx_large_buf;
extern bool debug_fw;
extern bool disable_ap_sme;
extern bool ftm_mode;
+extern bool drop_if_ring_full;
+extern uint max_assoc_sta;
struct wil6210_priv;
struct wil6210_vif;
@@ -89,7 +91,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
#define WIL_RING_SIZE_ORDER_MIN (5)
#define WIL_RING_SIZE_ORDER_MAX (15)
#define WIL6210_MAX_TX_RINGS (24) /* HW limit */
-#define WIL6210_MAX_CID (8) /* HW limit */
+#define WIL6210_MAX_CID (20) /* max number of stations */
+#define WIL6210_RX_DESC_MAX_CID (8) /* HW limit */
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
#define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */
#define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */
@@ -457,7 +460,7 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
*/
static inline bool wil_cid_valid(u8 cid)
{
- return cid < WIL6210_MAX_CID;
+ return (cid >= 0 && cid < max_assoc_sta);
}
struct wil6210_mbox_ring {
@@ -791,6 +794,7 @@ struct wil_halp {
struct mutex lock; /* protect halp ref_cnt */
unsigned int ref_cnt;
struct completion comp;
+ u8 handle_icr;
};
struct wil_blob_wrapper {
@@ -1235,7 +1239,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
int wmi_addba(struct wil6210_priv *wil, u8 mid,
u8 ringid, u8 size, u16 timeout);
int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason);
-int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason);
+int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason);
int wmi_addba_rx_resp(struct wil6210_priv *wil,
u8 mid, u8 cid, u8 tid, u8 token,
u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
@@ -1248,8 +1252,8 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid,
const u8 *mac, enum nl80211_iftype iftype);
int wmi_port_delete(struct wil6210_priv *wil, u8 mid);
int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval);
-int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
- u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
+int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
+ u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl);
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 345f05969190..bda4a9712f91 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,8 +24,9 @@
#include "wmi.h"
#include "trace.h"
-static uint max_assoc_sta = WIL6210_MAX_CID;
-module_param(max_assoc_sta, uint, 0644);
+/* set the default max assoc sta to max supported by driver */
+uint max_assoc_sta = WIL6210_MAX_CID;
+module_param(max_assoc_sta, uint, 0444);
MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
int agg_wsize; /* = 0; */
@@ -770,6 +771,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
struct wil6210_priv *wil = vif_to_wil(vif);
struct wiphy *wiphy = wil_to_wiphy(wil);
struct wmi_ready_event *evt = d;
+ u8 fw_max_assoc_sta;
wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
wil->fw_version, le32_to_cpu(evt->sw_version),
@@ -787,6 +789,25 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
evt->rfc_read_calib_result);
wil->fw_calib_result = evt->rfc_read_calib_result;
}
+
+ fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID;
+ if (len > offsetof(struct wmi_ready_event, max_assoc_sta) &&
+ evt->max_assoc_sta > 0) {
+ fw_max_assoc_sta = evt->max_assoc_sta;
+ wil_dbg_wmi(wil, "fw reported max assoc sta %d\n",
+ fw_max_assoc_sta);
+
+ if (fw_max_assoc_sta > WIL6210_MAX_CID) {
+ wil_dbg_wmi(wil,
+ "fw max assoc sta %d exceeds max driver supported %d\n",
+ fw_max_assoc_sta, WIL6210_MAX_CID);
+ fw_max_assoc_sta = WIL6210_MAX_CID;
+ }
+ }
+
+ max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta);
+ wil_dbg_wmi(wil, "setting max assoc sta to %d\n", max_assoc_sta);
+
wil_set_recovery_state(wil, fw_recovery_idle);
set_bit(wil_status_fwready, wil->status);
/* let the reset sequence continue */
@@ -952,7 +973,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
evt->assoc_req_len, evt->assoc_resp_len);
return;
}
- if (evt->cid >= WIL6210_MAX_CID) {
+ if (evt->cid >= max_assoc_sta) {
wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
return;
}
@@ -1271,9 +1292,16 @@ static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id,
void *d, int len)
{
struct wil6210_priv *wil = vif_to_wil(vif);
+ u8 cid, tid;
struct wmi_rcp_addba_req_event *evt = d;
- wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token,
+ if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
+ parse_cidxtid(evt->cidxtid, &cid, &tid);
+ } else {
+ cid = evt->cid;
+ tid = evt->tid;
+ }
+ wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token,
evt->ba_param_set, evt->ba_timeout,
evt->ba_seq_ctrl);
}
@@ -1289,7 +1317,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
struct wil_tid_ampdu_rx *r;
might_sleep();
- parse_cidxtid(evt->cidxtid, &cid, &tid);
+
+ if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
+ parse_cidxtid(evt->cidxtid, &cid, &tid);
+ } else {
+ cid = evt->cid;
+ tid = evt->tid;
+ }
wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n",
vif->mid, cid, tid,
evt->from_initiator ? "originator" : "recipient",
@@ -1404,7 +1438,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif,
u8 cid = basic->cid;
struct wil_sta_info *sta;
- if (cid < 0 || cid >= WIL6210_MAX_CID) {
+ if (cid < 0 || cid >= max_assoc_sta) {
wil_err(wil, "invalid cid %d\n", cid);
return;
}
@@ -1554,7 +1588,7 @@ static int wil_find_cid_ringid_sta(struct wil6210_priv *wil,
continue;
lcid = wil->ring2cid_tid[i][0];
- if (lcid >= WIL6210_MAX_CID) /* skip BCAST */
+ if (lcid >= max_assoc_sta) /* skip BCAST */
continue;
wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid);
@@ -2120,10 +2154,9 @@ int wmi_pcp_start(struct wil6210_vif *vif,
if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
(cmd.pcp_max_assoc_sta <= 0)) {
- wil_info(wil,
- "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
- max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
- cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
+ wil_err(wil, "unexpected max_assoc_sta %d\n",
+ cmd.pcp_max_assoc_sta);
+ return -EOPNOTSUPP;
}
if (disable_ap_sme &&
@@ -2516,7 +2549,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
if (ch)
cmd.sniffer_cfg.channel = ch->hw_value - 1;
cmd.sniffer_cfg.phy_info_mode =
- cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
+ cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED);
cmd.sniffer_cfg.phy_support =
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
@@ -2651,15 +2684,22 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
}
-int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason)
+int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason)
{
struct wmi_rcp_delba_cmd cmd = {
- .cidxtid = cidxtid,
.reason = cpu_to_le16(reason),
};
- wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
- (cidxtid >> 4) & 0xf, reason);
+ if (cid >= WIL6210_RX_DESC_MAX_CID) {
+ cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
+ cmd.cid = cid;
+ cmd.tid = tid;
+ } else {
+ cmd.cidxtid = mk_cidxtid(cid, tid);
+ }
+
+ wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid,
+ tid, reason);
return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd));
}
@@ -2670,7 +2710,6 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
{
int rc;
struct wmi_rcp_addba_resp_cmd cmd = {
- .cidxtid = mk_cidxtid(cid, tid),
.dialog_token = token,
.status_code = cpu_to_le16(status),
/* bit 0: A-MSDU supported
@@ -2689,6 +2728,14 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
.evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
};
+ if (cid >= WIL6210_RX_DESC_MAX_CID) {
+ cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
+ cmd.cid = cid;
+ cmd.tid = tid;
+ } else {
+ cmd.cidxtid = mk_cidxtid(cid, tid);
+ }
+
wil_dbg_wmi(wil,
"ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
mid, cid, tid, agg_wsize,
diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c
index 77046384dd80..976c8ec4e992 100644
--- a/drivers/net/wireless/broadcom/b43/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43/debugfs.c
@@ -668,15 +668,13 @@ static void b43_remove_dynamic_debug(struct b43_wldev *dev)
static void b43_add_dynamic_debug(struct b43_wldev *dev)
{
struct b43_dfsentry *e = dev->dfsentry;
- struct dentry *d;
-#define add_dyn_dbg(name, id, initstate) do { \
- e->dyn_debug[id] = (initstate); \
- d = debugfs_create_bool(name, 0600, e->subdir, \
- &(e->dyn_debug[id])); \
- if (!IS_ERR(d)) \
- e->dyn_debug_dentries[id] = d; \
- } while (0)
+#define add_dyn_dbg(name, id, initstate) do { \
+ e->dyn_debug[id] = (initstate); \
+ e->dyn_debug_dentries[id] = \
+ debugfs_create_bool(name, 0600, e->subdir, \
+ &(e->dyn_debug[id])); \
+ } while (0)
add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false);
add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false);
@@ -718,19 +716,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
e->subdir = debugfs_create_dir(devdir, rootdir);
- if (!e->subdir || IS_ERR(e->subdir)) {
- if (e->subdir == ERR_PTR(-ENODEV)) {
- b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
- "enabled in kernel config\n");
- } else {
- b43err(dev->wl, "debugfs: cannot create %s directory\n",
- devdir);
- }
- dev->dfsentry = NULL;
- kfree(log->log);
- kfree(e);
- return;
- }
e->mmio16read_next = 0xFFFF; /* invalid address */
e->mmio32read_next = 0xFFFF; /* invalid address */
@@ -741,13 +726,10 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
#define ADD_FILE(name, mode) \
do { \
- struct dentry *d; \
- d = debugfs_create_file(__stringify(name), \
+ e->file_##name.dentry = \
+ debugfs_create_file(__stringify(name), \
mode, e->subdir, dev, \
&fops_##name.fops); \
- e->file_##name.dentry = NULL; \
- if (!IS_ERR(d)) \
- e->file_##name.dentry = d; \
} while (0)
@@ -818,8 +800,6 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
void b43_debugfs_init(void)
{
rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (IS_ERR(rootdir))
- rootdir = NULL;
}
void b43_debugfs_exit(void)
diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
index dfc4c34298d4..b34e51933257 100644
--- a/drivers/net/wireless/broadcom/b43/dma.c
+++ b/drivers/net/wireless/broadcom/b43/dma.c
@@ -431,9 +431,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
- ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
- ring_mem_size, &(ring->dmabase),
- GFP_KERNEL);
+ ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+ ring_mem_size, &(ring->dmabase),
+ GFP_KERNEL);
if (!ring->descbase)
return -ENOMEM;
diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
index 82ef56ed7ca1..8150adee3e34 100644
--- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c
+++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
@@ -361,15 +361,13 @@ static void b43legacy_remove_dynamic_debug(struct b43legacy_wldev *dev)
static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev)
{
struct b43legacy_dfsentry *e = dev->dfsentry;
- struct dentry *d;
-#define add_dyn_dbg(name, id, initstate) do { \
- e->dyn_debug[id] = (initstate); \
- d = debugfs_create_bool(name, 0600, e->subdir, \
- &(e->dyn_debug[id])); \
- if (!IS_ERR(d)) \
- e->dyn_debug_dentries[id] = d; \
- } while (0)
+#define add_dyn_dbg(name, id, initstate) do { \
+ e->dyn_debug[id] = (initstate); \
+ e->dyn_debug_dentries[id] = \
+ debugfs_create_bool(name, 0600, e->subdir, \
+ &(e->dyn_debug[id])); \
+ } while (0)
add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false);
add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, false);
@@ -408,29 +406,14 @@ void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev)
snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
e->subdir = debugfs_create_dir(devdir, rootdir);
- if (!e->subdir || IS_ERR(e->subdir)) {
- if (e->subdir == ERR_PTR(-ENODEV)) {
- b43legacydbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
- "enabled in kernel config\n");
- } else {
- b43legacyerr(dev->wl, "debugfs: cannot create %s directory\n",
- devdir);
- }
- dev->dfsentry = NULL;
- kfree(log->log);
- kfree(e);
- return;
- }
#define ADD_FILE(name, mode) \
do { \
- struct dentry *d; \
- d = debugfs_create_file(__stringify(name), \
+ e->file_##name.dentry = \
+ debugfs_create_file(__stringify(name), \
mode, e->subdir, dev, \
&fops_##name.fops); \
e->file_##name.dentry = NULL; \
- if (!IS_ERR(d)) \
- e->file_##name.dentry = d; \
} while (0)
@@ -492,8 +475,6 @@ void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev,
void b43legacy_debugfs_init(void)
{
rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (IS_ERR(rootdir))
- rootdir = NULL;
}
void b43legacy_debugfs_exit(void)
diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c
index 1b1da7d83652..2ce1537d983c 100644
--- a/drivers/net/wireless/broadcom/b43legacy/dma.c
+++ b/drivers/net/wireless/broadcom/b43legacy/dma.c
@@ -331,9 +331,9 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
static int alloc_ringmemory(struct b43legacy_dmaring *ring)
{
/* GFP flags must match the flags in free_ringmemory()! */
- ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
- B43legacy_DMA_RINGMEMSIZE,
- &(ring->dmabase), GFP_KERNEL);
+ ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+ B43legacy_DMA_RINGMEMSIZE,
+ &(ring->dmabase), GFP_KERNEL);
if (!ring->descbase)
return -ENOMEM;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
index 22fd95a736a8..f7cf3e5f4849 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
@@ -16,8 +16,8 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y += \
- -Idrivers/net/wireless/broadcom/brcm80211/brcmfmac \
- -Idrivers/net/wireless/broadcom/brcm80211/include
+ -I $(srctree)/$(src) \
+ -I $(srctree)/$(src)/../include
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += \
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index 1068a2a4494c..73d3c1a0a7c9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -178,8 +178,8 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
*fwerr = 0;
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
if (ret < 0) {
- brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
- ret);
+ bphy_err(drvr, "brcmf_proto_bcdc_msg failed w/status %d\n",
+ ret);
goto done;
}
@@ -195,9 +195,9 @@ retry:
if ((id < bcdc->reqid) && (++retries < RETRIES))
goto retry;
if (id != bcdc->reqid) {
- brcmf_err("%s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
- bcdc->reqid);
+ bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+ bcdc->reqid);
ret = -EINVAL;
goto done;
}
@@ -245,9 +245,9 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
if (id != bcdc->reqid) {
- brcmf_err("%s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
- bcdc->reqid);
+ bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+ bcdc->reqid);
ret = -EINVAL;
goto done;
}
@@ -312,8 +312,8 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
}
if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
BCDC_PROTO_VER) {
- brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
- brcmf_ifname(tmp_if), h->flags);
+ bphy_err(drvr, "%s: non-BCDC packet received, flags 0x%x\n",
+ brcmf_ifname(tmp_if), h->flags);
return -EBADE;
}
@@ -460,7 +460,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) {
- brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n");
+ bphy_err(drvr, "struct brcmf_proto_bcdc is not correctly defined\n");
goto fail;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index d64bf233b12c..ec129864cc9c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -315,7 +315,7 @@ static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
/* bail out as things are really fishy here */
WARN(1, "invalid sdio function number: %d\n", func->num);
err = -ENOMEDIUM;
- };
+ }
if (err == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index c4965184cdf3..3d441c5c745c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -90,6 +90,7 @@ struct brcmf_bus_ops {
int (*get_memdump)(struct device *dev, void *data, size_t len);
int (*get_fwname)(struct device *dev, const char *ext,
unsigned char *fw_name);
+ void (*debugfs_create)(struct device *dev);
};
@@ -235,6 +236,15 @@ int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
return bus->ops->get_fwname(bus->dev, ext, fw_name);
}
+static inline
+void brcmf_bus_debugfs_create(struct brcmf_bus *bus)
+{
+ if (!bus->ops->debugfs_create)
+ return;
+
+ return bus->ops->debugfs_create(bus->dev);
+}
+
/*
* interface functions from common layer
*/
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 35301237d435..e92f6351bd22 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -457,6 +457,7 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
static int
send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
{
+ struct brcmf_pub *drvr = ifp->drvr;
int err;
struct brcmf_wsec_key_le key_le;
@@ -468,7 +469,7 @@ send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
sizeof(key_le));
if (err)
- brcmf_err("wsec_key error (%d)\n", err);
+ bphy_err(drvr, "wsec_key error (%d)\n", err);
return err;
}
@@ -508,6 +509,7 @@ static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr)
static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_mbss_ssid_le mbss_ssid_le;
int bsscfgidx;
int err;
@@ -524,7 +526,7 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
sizeof(mbss_ssid_le));
if (err < 0)
- brcmf_err("setting ssid failed %d\n", err);
+ bphy_err(drvr, "setting ssid failed %d\n", err);
return err;
}
@@ -542,6 +544,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_vif *vif;
int err;
@@ -567,7 +570,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
BRCMF_VIF_EVENT_TIMEOUT);
brcmf_cfg80211_arm_vif_event(cfg, NULL);
if (!err) {
- brcmf_err("timeout occurred\n");
+ bphy_err(drvr, "timeout occurred\n");
err = -EIO;
goto fail;
}
@@ -575,7 +578,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
/* interface created in firmware */
ifp = vif->ifp;
if (!ifp) {
- brcmf_err("no if pointer provided\n");
+ bphy_err(drvr, "no if pointer provided\n");
err = -ENOENT;
goto fail;
}
@@ -583,7 +586,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
err = brcmf_net_attach(ifp, true);
if (err) {
- brcmf_err("Registering netdevice failed\n");
+ bphy_err(drvr, "Registering netdevice failed\n");
free_netdev(ifp->ndev);
goto fail;
}
@@ -614,13 +617,15 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
enum nl80211_iftype type,
struct vif_params *params)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct wireless_dev *wdev;
int err;
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
if (err) {
- brcmf_err("iface validation failed: err=%d\n", err);
+ bphy_err(drvr, "iface validation failed: err=%d\n", err);
return ERR_PTR(err);
}
switch (type) {
@@ -645,8 +650,8 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
}
if (IS_ERR(wdev))
- brcmf_err("add iface %s type %d failed: err=%d\n",
- name, type, (int)PTR_ERR(wdev));
+ bphy_err(drvr, "add iface %s type %d failed: err=%d\n", name,
+ type, (int)PTR_ERR(wdev));
else
brcmf_cfg80211_update_proto_addr_mode(wdev);
@@ -661,12 +666,13 @@ static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err = 0;
if (check_vif_up(ifp->vif)) {
err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
if (err) {
- brcmf_err("fail to set mpc\n");
+ bphy_err(drvr, "fail to set mpc\n");
return;
}
brcmf_dbg(INFO, "MPC : %d\n", mpc);
@@ -677,6 +683,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp, bool aborted,
bool fw_abort)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
u64 reqid;
@@ -711,7 +718,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
- brcmf_err("Scan abort failed\n");
+ bphy_err(drvr, "Scan abort failed\n");
}
brcmf_scan_config_mpc(ifp, 1);
@@ -756,6 +763,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = wdev->netdev;
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
int ret;
int err;
@@ -763,7 +771,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);
if (err) {
- brcmf_err("interface_remove failed %d\n", err);
+ bphy_err(drvr, "interface_remove failed %d\n", err);
goto err_unarm;
}
@@ -771,7 +779,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
BRCMF_VIF_EVENT_TIMEOUT);
if (!ret) {
- brcmf_err("timeout occurred\n");
+ bphy_err(drvr, "timeout occurred\n");
err = -EIO;
goto err_unarm;
}
@@ -834,6 +842,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_vif *vif = ifp->vif;
+ struct brcmf_pub *drvr = cfg->pub;
s32 infra = 0;
s32 ap = 0;
s32 err = 0;
@@ -873,14 +882,14 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
}
err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
if (err) {
- brcmf_err("iface validation failed: err=%d\n", err);
+ bphy_err(drvr, "iface validation failed: err=%d\n", err);
return err;
}
switch (type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
- brcmf_err("type (%d) : currently we do not support this type\n",
- type);
+ bphy_err(drvr, "type (%d) : currently we do not support this type\n",
+ type);
return -EOPNOTSUPP;
case NL80211_IFTYPE_ADHOC:
infra = 0;
@@ -908,7 +917,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
} else {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);
if (err) {
- brcmf_err("WLC_SET_INFRA error (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_INFRA error (%d)\n", err);
err = -EAGAIN;
goto done;
}
@@ -999,6 +1008,7 @@ static s32
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
struct cfg80211_scan_request *request)
{
+ struct brcmf_pub *drvr = cfg->pub;
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
offsetof(struct brcmf_escan_params_le, params_le);
struct brcmf_escan_params_le *params;
@@ -1030,7 +1040,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
if (err == -EBUSY)
brcmf_dbg(INFO, "system busy : escan canceled\n");
else
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
}
kfree(params);
@@ -1067,6 +1077,7 @@ static s32
brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
@@ -1076,21 +1087,22 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
return -EIO;
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
- brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
+ bphy_err(drvr, "Scanning already: status (%lu)\n",
+ cfg->scan_status);
return -EAGAIN;
}
if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
- brcmf_err("Scanning being aborted: status (%lu)\n",
- cfg->scan_status);
+ bphy_err(drvr, "Scanning being aborted: status (%lu)\n",
+ cfg->scan_status);
return -EAGAIN;
}
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
- brcmf_err("Scanning suppressed: status (%lu)\n",
- cfg->scan_status);
+ bphy_err(drvr, "Scanning suppressed: status (%lu)\n",
+ cfg->scan_status);
return -EAGAIN;
}
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
- brcmf_err("Connecting: status (%lu)\n", vif->sme_state);
+ bphy_err(drvr, "Connecting: status (%lu)\n", vif->sme_state);
return -EAGAIN;
}
@@ -1124,7 +1136,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
return 0;
scan_out:
- brcmf_err("scan error (%d)\n", err);
+ bphy_err(drvr, "scan error (%d)\n", err);
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
cfg->scan_request = NULL;
return err;
@@ -1132,36 +1144,41 @@ scan_out:
static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err = 0;
- err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
- rts_threshold);
+ err = brcmf_fil_iovar_int_set(ifp, "rtsthresh", rts_threshold);
if (err)
- brcmf_err("Error (%d)\n", err);
+ bphy_err(drvr, "Error (%d)\n", err);
return err;
}
static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err = 0;
- err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
+ err = brcmf_fil_iovar_int_set(ifp, "fragthresh",
frag_threshold);
if (err)
- brcmf_err("Error (%d)\n", err);
+ bphy_err(drvr, "Error (%d)\n", err);
return err;
}
static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err = 0;
u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
- err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
+ err = brcmf_fil_cmd_int_set(ifp, cmd, retry);
if (err) {
- brcmf_err("cmd (%d) , error (%d)\n", cmd, err);
+ bphy_err(drvr, "cmd (%d) , error (%d)\n", cmd, err);
return err;
}
return err;
@@ -1237,6 +1254,7 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_wsec_pmk_le pmk;
int i, err;
@@ -1250,8 +1268,8 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
&pmk, sizeof(pmk));
if (err < 0)
- brcmf_err("failed to change PSK in firmware (len=%u)\n",
- pmk_len);
+ bphy_err(drvr, "failed to change PSK in firmware (len=%u)\n",
+ pmk_len);
return err;
}
@@ -1259,6 +1277,7 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -1268,7 +1287,7 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
err = brcmf_fil_cmd_data_set(vif->ifp,
BRCMF_C_DISASSOC, NULL, 0);
if (err) {
- brcmf_err("WLC_DISASSOC failed (%d)\n", err);
+ bphy_err(drvr, "WLC_DISASSOC failed (%d)\n", err);
}
if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) ||
(vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT))
@@ -1292,6 +1311,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_join_params join_params;
size_t join_params_size = 0;
s32 err = 0;
@@ -1356,7 +1376,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
if (err) {
- brcmf_err("wsec failed (%d)\n", err);
+ bphy_err(drvr, "wsec failed (%d)\n", err);
goto done;
}
@@ -1368,7 +1388,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
if (err) {
- brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_BCNPRD failed (%d)\n", err);
goto done;
}
@@ -1413,7 +1433,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
target_channel);
if (err) {
- brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_CHANNEL failed (%d)\n", err);
goto done;
}
} else
@@ -1425,7 +1445,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, join_params_size);
if (err) {
- brcmf_err("WLC_SET_SSID failed (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_SSID failed (%d)\n", err);
goto done;
}
@@ -1461,7 +1481,9 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
static s32 brcmf_set_wpa_version(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1473,9 +1495,9 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
else
val = WPA_AUTH_DISABLED;
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
- err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
if (err) {
- brcmf_err("set wpa_auth failed (%d)\n", err);
+ bphy_err(drvr, "set wpa_auth failed (%d)\n", err);
return err;
}
sec = &profile->sec;
@@ -1486,7 +1508,9 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
static s32 brcmf_set_auth_type(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1506,9 +1530,9 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
break;
}
- err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
+ err = brcmf_fil_bsscfg_int_set(ifp, "auth", val);
if (err) {
- brcmf_err("set auth failed (%d)\n", err);
+ bphy_err(drvr, "set auth failed (%d)\n", err);
return err;
}
sec = &profile->sec;
@@ -1520,7 +1544,9 @@ static s32
brcmf_set_wsec_mode(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_security *sec;
s32 pval = 0;
s32 gval = 0;
@@ -1543,8 +1569,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
pval = AES_ENABLED;
break;
default:
- brcmf_err("invalid cipher pairwise (%d)\n",
- sme->crypto.ciphers_pairwise[0]);
+ bphy_err(drvr, "invalid cipher pairwise (%d)\n",
+ sme->crypto.ciphers_pairwise[0]);
return -EINVAL;
}
}
@@ -1564,8 +1590,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
gval = AES_ENABLED;
break;
default:
- brcmf_err("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ bphy_err(drvr, "invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
}
@@ -1578,9 +1604,9 @@ brcmf_set_wsec_mode(struct net_device *ndev,
pval = AES_ENABLED;
wsec = pval | gval;
- err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err) {
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
return err;
}
@@ -1596,6 +1622,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+ struct brcmf_pub *drvr = ifp->drvr;
s32 val;
s32 err;
const struct brcmf_tlv *rsn_ie;
@@ -1613,7 +1640,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val);
if (err) {
- brcmf_err("could not get wpa_auth (%d)\n", err);
+ bphy_err(drvr, "could not get wpa_auth (%d)\n", err);
return err;
}
if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
@@ -1627,8 +1654,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA_AUTH_PSK;
break;
default:
- brcmf_err("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ bphy_err(drvr, "invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -1658,8 +1685,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
break;
default:
- brcmf_err("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ bphy_err(drvr, "invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
}
@@ -1705,7 +1732,7 @@ skip_mfp_config:
brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
if (err) {
- brcmf_err("could not set wpa_auth (%d)\n", err);
+ bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
return err;
}
@@ -1716,6 +1743,8 @@ static s32
brcmf_set_sharedkey(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
struct brcmf_wsec_key key;
@@ -1742,7 +1771,7 @@ brcmf_set_sharedkey(struct net_device *ndev,
key.len = (u32) sme->key_len;
key.index = (u32) sme->key_idx;
if (key.len > sizeof(key.data)) {
- brcmf_err("Too long key length (%u)\n", key.len);
+ bphy_err(drvr, "Too long key length (%u)\n", key.len);
return -EINVAL;
}
memcpy(key.data, sme->key, key.len);
@@ -1755,24 +1784,24 @@ brcmf_set_sharedkey(struct net_device *ndev,
key.algo = CRYPTO_ALGO_WEP128;
break;
default:
- brcmf_err("Invalid algorithm (%d)\n",
- sme->crypto.ciphers_pairwise[0]);
+ bphy_err(drvr, "Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]);
return -EINVAL;
}
/* Set the new key/index */
brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
key.len, key.index, key.algo);
brcmf_dbg(CONN, "key \"%s\"\n", key.data);
- err = send_key_to_dongle(netdev_priv(ndev), &key);
+ err = send_key_to_dongle(ifp, &key);
if (err)
return err;
if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
brcmf_dbg(CONN, "set auth_type to shared key\n");
val = WL_AUTH_SHARED_KEY; /* shared key */
- err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
+ err = brcmf_fil_bsscfg_int_set(ifp, "auth", val);
if (err)
- brcmf_err("set auth failed (%d)\n", err);
+ bphy_err(drvr, "set auth failed (%d)\n", err);
}
return err;
}
@@ -1792,6 +1821,7 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
static void brcmf_set_join_pref(struct brcmf_if *ifp,
struct cfg80211_bss_selection *bss_select)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_join_pref_params join_pref_params[2];
enum nl80211_band band;
int err, i = 0;
@@ -1830,7 +1860,7 @@ static void brcmf_set_join_pref(struct brcmf_if *ifp,
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
sizeof(join_pref_params));
if (err)
- brcmf_err("Set join_pref error (%d)\n", err);
+ bphy_err(drvr, "Set join_pref error (%d)\n", err);
}
static s32
@@ -1841,6 +1871,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan = sme->channel;
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_join_params join_params;
size_t join_params_size;
const struct brcmf_tlv *rsn_ie;
@@ -1857,7 +1888,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
return -EIO;
if (!sme->ssid) {
- brcmf_err("Invalid ssid\n");
+ bphy_err(drvr, "Invalid ssid\n");
return -EOPNOTSUPP;
}
@@ -1886,7 +1917,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
sme->ie, sme->ie_len);
if (err)
- brcmf_err("Set Assoc REQ IE Failed\n");
+ bphy_err(drvr, "Set Assoc REQ IE Failed\n");
else
brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
@@ -1907,32 +1938,32 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_set_wpa_version(ndev, sme);
if (err) {
- brcmf_err("wl_set_wpa_version failed (%d)\n", err);
+ bphy_err(drvr, "wl_set_wpa_version failed (%d)\n", err);
goto done;
}
sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type);
err = brcmf_set_auth_type(ndev, sme);
if (err) {
- brcmf_err("wl_set_auth_type failed (%d)\n", err);
+ bphy_err(drvr, "wl_set_auth_type failed (%d)\n", err);
goto done;
}
err = brcmf_set_wsec_mode(ndev, sme);
if (err) {
- brcmf_err("wl_set_set_cipher failed (%d)\n", err);
+ bphy_err(drvr, "wl_set_set_cipher failed (%d)\n", err);
goto done;
}
err = brcmf_set_key_mgmt(ndev, sme);
if (err) {
- brcmf_err("wl_set_key_mgmt failed (%d)\n", err);
+ bphy_err(drvr, "wl_set_key_mgmt failed (%d)\n", err);
goto done;
}
err = brcmf_set_sharedkey(ndev, sme);
if (err) {
- brcmf_err("brcmf_set_sharedkey failed (%d)\n", err);
+ bphy_err(drvr, "brcmf_set_sharedkey failed (%d)\n", err);
goto done;
}
@@ -1949,7 +1980,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
/* enable firmware supplicant for this interface */
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
if (err < 0) {
- brcmf_err("failed to enable fw supplicant\n");
+ bphy_err(drvr, "failed to enable fw supplicant\n");
goto done;
}
}
@@ -2044,7 +2075,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, join_params_size);
if (err)
- brcmf_err("BRCMF_C_SET_SSID failed (%d)\n", err);
+ bphy_err(drvr, "BRCMF_C_SET_SSID failed (%d)\n", err);
done:
if (err)
@@ -2057,8 +2088,10 @@ static s32
brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
u16 reason_code)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_scb_val_le scbval;
s32 err = 0;
@@ -2075,7 +2108,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
&scbval, sizeof(scbval));
if (err)
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
brcmf_dbg(TRACE, "Exit\n");
return err;
@@ -2088,6 +2121,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
s32 err;
s32 disable;
u32 qdbm = 127;
@@ -2102,7 +2136,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
case NL80211_TX_POWER_LIMITED:
case NL80211_TX_POWER_FIXED:
if (mbm < 0) {
- brcmf_err("TX_POWER_FIXED - dbm is negative\n");
+ bphy_err(drvr, "TX_POWER_FIXED - dbm is negative\n");
err = -EINVAL;
goto done;
}
@@ -2112,7 +2146,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
qdbm |= WL_TXPWR_OVERRIDE;
break;
default:
- brcmf_err("Unsupported type %d\n", type);
+ bphy_err(drvr, "Unsupported type %d\n", type);
err = -EINVAL;
goto done;
}
@@ -2120,11 +2154,11 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
disable = WL_RADIO_SW_DISABLE << 16;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
if (err)
- brcmf_err("WLC_SET_RADIO error (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_RADIO error (%d)\n", err);
err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm);
if (err)
- brcmf_err("qtxpower error (%d)\n", err);
+ bphy_err(drvr, "qtxpower error (%d)\n", err);
done:
brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE);
@@ -2135,7 +2169,9 @@ static s32
brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
s32 *dbm)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
+ struct brcmf_pub *drvr = cfg->pub;
s32 qdbm = 0;
s32 err;
@@ -2145,7 +2181,7 @@ brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);
if (err) {
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
goto done;
}
*dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4;
@@ -2160,6 +2196,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool unicast, bool multicast)
{
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = ifp->drvr;
u32 index;
u32 wsec;
s32 err = 0;
@@ -2171,7 +2208,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- brcmf_err("WLC_GET_WSEC error (%d)\n", err);
+ bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err);
goto done;
}
@@ -2181,7 +2218,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp,
BRCMF_C_SET_KEY_PRIMARY, index);
if (err)
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
}
done:
brcmf_dbg(TRACE, "Exit\n");
@@ -2230,7 +2267,9 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_wsec_key *key;
s32 val;
s32 wsec;
@@ -2245,7 +2284,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
/* we ignore this key index in this case */
- brcmf_err("invalid key index (%d)\n", key_idx);
+ bphy_err(drvr, "invalid key index (%d)\n", key_idx);
return -EINVAL;
}
@@ -2254,7 +2293,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
mac_addr);
if (params->key_len > sizeof(key->data)) {
- brcmf_err("Too long key length (%u)\n", params->key_len);
+ bphy_err(drvr, "Too long key length (%u)\n", params->key_len);
return -EINVAL;
}
@@ -2308,7 +2347,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
break;
default:
- brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
+ bphy_err(drvr, "Invalid cipher (0x%x)\n", params->cipher);
err = -EINVAL;
goto done;
}
@@ -2319,13 +2358,13 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- brcmf_err("get wsec error (%d)\n", err);
+ bphy_err(drvr, "get wsec error (%d)\n", err);
goto done;
}
wsec |= val;
err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err) {
- brcmf_err("set wsec error (%d)\n", err);
+ bphy_err(drvr, "set wsec error (%d)\n", err);
goto done;
}
@@ -2340,9 +2379,11 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
void (*callback)(void *cookie,
struct key_params *params))
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct key_params params;
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_security *sec;
s32 wsec;
s32 err = 0;
@@ -2356,7 +2397,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- brcmf_err("WLC_GET_WSEC error (%d)\n", err);
+ bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
@@ -2377,7 +2418,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
} else {
- brcmf_err("Invalid algo (0x%x)\n", wsec);
+ bphy_err(drvr, "Invalid algo (0x%x)\n", wsec);
err = -EINVAL;
goto done;
}
@@ -2407,6 +2448,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
static void
brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err;
u8 key_idx;
struct brcmf_wsec_key *key;
@@ -2423,18 +2465,18 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
err = send_key_to_dongle(ifp, key);
if (err) {
- brcmf_err("Setting WEP key failed (%d)\n", err);
+ bphy_err(drvr, "Setting WEP key failed (%d)\n", err);
return;
}
err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- brcmf_err("get wsec error (%d)\n", err);
+ bphy_err(drvr, "get wsec error (%d)\n", err);
return;
}
wsec |= WEP_ENABLED;
err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err)
- brcmf_err("set wsec error (%d)\n", err);
+ bphy_err(drvr, "set wsec error (%d)\n", err);
}
static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
@@ -2460,6 +2502,7 @@ static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct {
__le32 len;
struct brcmf_bss_info_le bss_le;
@@ -2475,7 +2518,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
WL_BSS_INFO_MAX);
if (err) {
- brcmf_err("Failed to get bss info (%d)\n", err);
+ bphy_err(drvr, "Failed to get bss info (%d)\n", err);
goto out_kfree;
}
si->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM);
@@ -2497,6 +2540,7 @@ static s32
brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
struct station_info *sinfo)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_scb_val_le scbval;
struct brcmf_pktcnt_le pktcnt;
s32 err;
@@ -2506,7 +2550,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
/* Get the current tx rate */
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
if (err < 0) {
- brcmf_err("BRCMF_C_GET_RATE error (%d)\n", err);
+ bphy_err(drvr, "BRCMF_C_GET_RATE error (%d)\n", err);
return err;
}
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
@@ -2516,7 +2560,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval,
sizeof(scbval));
if (err) {
- brcmf_err("BRCMF_C_GET_RSSI error (%d)\n", err);
+ bphy_err(drvr, "BRCMF_C_GET_RSSI error (%d)\n", err);
return err;
}
rssi = le32_to_cpu(scbval.val);
@@ -2526,7 +2570,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt,
sizeof(pktcnt));
if (err) {
- brcmf_err("BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err);
+ bphy_err(drvr, "BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err);
return err;
}
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS) |
@@ -2545,7 +2589,9 @@ static s32
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
const u8 *mac, struct station_info *sinfo)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_scb_val_le scb_val;
s32 err = 0;
struct brcmf_sta_info_le sta_info_le;
@@ -2574,7 +2620,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
&sta_info_le,
sizeof(sta_info_le));
if (err < 0) {
- brcmf_err("GET STA INFO failed, %d\n", err);
+ bphy_err(drvr, "GET STA INFO failed, %d\n", err);
goto done;
}
}
@@ -2643,7 +2689,8 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
&scb_val, sizeof(scb_val));
if (err) {
- brcmf_err("Could not get rssi (%d)\n", err);
+ bphy_err(drvr, "Could not get rssi (%d)\n",
+ err);
goto done;
} else {
rssi = le32_to_cpu(scb_val.val);
@@ -2664,6 +2711,7 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
s32 err;
brcmf_dbg(TRACE, "Enter, idx %d\n", idx);
@@ -2674,8 +2722,8 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
&cfg->assoclist,
sizeof(cfg->assoclist));
if (err) {
- brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n",
- err);
+ bphy_err(drvr, "BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n",
+ err);
cfg->assoclist.count = 0;
return -EOPNOTSUPP;
}
@@ -2695,6 +2743,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
s32 err = 0;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
brcmf_dbg(TRACE, "Enter\n");
@@ -2723,9 +2772,9 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
if (err) {
if (err == -ENODEV)
- brcmf_err("net_device is not ready yet\n");
+ bphy_err(drvr, "net_device is not ready yet\n");
else
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
}
done:
brcmf_dbg(TRACE, "Exit\n");
@@ -2736,6 +2785,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
struct brcmf_bss_info_le *bi)
{
struct wiphy *wiphy = cfg_to_wiphy(cfg);
+ struct brcmf_pub *drvr = cfg->pub;
struct cfg80211_bss *bss;
enum nl80211_band band;
struct brcmu_chan ch;
@@ -2748,7 +2798,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
struct cfg80211_inform_bss bss_data = {};
if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
- brcmf_err("Bss info is larger than buffer. Discarding\n");
+ bphy_err(drvr, "Bss info is larger than buffer. Discarding\n");
return 0;
}
@@ -2807,6 +2857,7 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_scan_results *bss_list;
struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
s32 err = 0;
@@ -2815,8 +2866,8 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
if (bss_list->count != 0 &&
bss_list->version != BRCMF_BSS_INFO_VERSION) {
- brcmf_err("Version %d != WL_BSS_INFO_VERSION\n",
- bss_list->version);
+ bphy_err(drvr, "Version %d != WL_BSS_INFO_VERSION\n",
+ bss_list->version);
return -EOPNOTSUPP;
}
brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);
@@ -2833,6 +2884,7 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev, const u8 *bssid)
{
struct wiphy *wiphy = cfg_to_wiphy(cfg);
+ struct brcmf_pub *drvr = cfg->pub;
struct ieee80211_channel *notify_channel;
struct brcmf_bss_info_le *bi = NULL;
struct ieee80211_supported_band *band;
@@ -2860,7 +2912,7 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
buf, WL_BSS_INFO_MAX);
if (err) {
- brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err);
+ bphy_err(drvr, "WLC_GET_BSS_INFO failed: %d\n", err);
goto CleanUp;
}
@@ -2914,6 +2966,7 @@ CleanUp:
static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_bss_info_le *bi;
const struct brcmf_tlv *tim;
u16 beacon_interval;
@@ -2930,7 +2983,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
cfg->extra_buf, WL_EXTRA_BUF_MAX);
if (err) {
- brcmf_err("Could not get bss info %d\n", err);
+ bphy_err(drvr, "Could not get bss info %d\n", err);
goto update_bss_info_out;
}
@@ -2955,7 +3008,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
u32 var;
err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
if (err) {
- brcmf_err("wl dtim_assoc failed (%d)\n", err);
+ bphy_err(drvr, "wl dtim_assoc failed (%d)\n", err);
goto update_bss_info_out;
}
dtim_period = (u8)var;
@@ -2993,9 +3046,10 @@ static void brcmf_escan_timeout(struct timer_list *t)
{
struct brcmf_cfg80211_info *cfg =
from_timer(cfg, t, escan_timeout);
+ struct brcmf_pub *drvr = cfg->pub;
if (cfg->int_escan_map || cfg->scan_request) {
- brcmf_err("timer expired\n");
+ bphy_err(drvr, "timer expired\n");
schedule_work(&cfg->escan_timeout_work);
}
}
@@ -3043,7 +3097,8 @@ static s32
brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_cfg80211_info *cfg = drvr->config;
s32 status;
struct brcmf_escan_result_le *escan_result_le;
u32 escan_buflen;
@@ -3060,32 +3115,33 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
goto exit;
if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
- brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx);
+ bphy_err(drvr, "scan not ready, bsscfgidx=%d\n",
+ ifp->bsscfgidx);
return -EPERM;
}
if (status == BRCMF_E_STATUS_PARTIAL) {
brcmf_dbg(SCAN, "ESCAN Partial result\n");
if (e->datalen < sizeof(*escan_result_le)) {
- brcmf_err("invalid event data length\n");
+ bphy_err(drvr, "invalid event data length\n");
goto exit;
}
escan_result_le = (struct brcmf_escan_result_le *) data;
if (!escan_result_le) {
- brcmf_err("Invalid escan result (NULL pointer)\n");
+ bphy_err(drvr, "Invalid escan result (NULL pointer)\n");
goto exit;
}
escan_buflen = le32_to_cpu(escan_result_le->buflen);
if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||
escan_buflen > e->datalen ||
escan_buflen < sizeof(*escan_result_le)) {
- brcmf_err("Invalid escan buffer length: %d\n",
- escan_buflen);
+ bphy_err(drvr, "Invalid escan buffer length: %d\n",
+ escan_buflen);
goto exit;
}
if (le16_to_cpu(escan_result_le->bss_count) != 1) {
- brcmf_err("Invalid bss_count %d: ignoring\n",
- escan_result_le->bss_count);
+ bphy_err(drvr, "Invalid bss_count %d: ignoring\n",
+ escan_result_le->bss_count);
goto exit;
}
bss_info_le = &escan_result_le->bss_info_le;
@@ -3100,8 +3156,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
bi_length = le32_to_cpu(bss_info_le->length);
if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) {
- brcmf_err("Ignoring invalid bss_info length: %d\n",
- bi_length);
+ bphy_err(drvr, "Ignoring invalid bss_info length: %d\n",
+ bi_length);
goto exit;
}
@@ -3109,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
BIT(NL80211_IFTYPE_ADHOC))) {
if (le16_to_cpu(bss_info_le->capability) &
WLAN_CAPABILITY_IBSS) {
- brcmf_err("Ignoring IBSS result\n");
+ bphy_err(drvr, "Ignoring IBSS result\n");
goto exit;
}
}
@@ -3117,7 +3173,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
list = (struct brcmf_scan_results *)
cfg->escan_info.escan_buf;
if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) {
- brcmf_err("Buffer is too small: ignoring\n");
+ bphy_err(drvr, "Buffer is too small: ignoring\n");
goto exit;
}
@@ -3276,7 +3332,8 @@ static s32
brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_cfg80211_info *cfg = drvr->config;
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
struct cfg80211_scan_request *request = NULL;
struct wiphy *wiphy = cfg_to_wiphy(cfg);
@@ -3309,14 +3366,14 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
if (!result_count) {
- brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
+ bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n");
goto out_err;
}
netinfo_start = brcmf_get_netinfo_array(pfn_result);
datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
if (datalen < result_count * sizeof(*netinfo)) {
- brcmf_err("insufficient event data\n");
+ bphy_err(drvr, "insufficient event data\n");
goto out_err;
}
@@ -3363,15 +3420,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct net_device *ndev,
struct cfg80211_sched_scan_request *req)
{
- struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
req->n_match_sets, req->n_ssids);
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
- brcmf_err("Scanning suppressed: status=%lu\n",
- cfg->scan_status);
+ bphy_err(drvr, "Scanning suppressed: status=%lu\n",
+ cfg->scan_status);
return -EAGAIN;
}
@@ -3449,7 +3507,8 @@ static s32
brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
void *data)
{
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_cfg80211_info *cfg = drvr->config;
struct brcmf_pno_scanresults_le *pfn_result;
struct brcmf_pno_net_info_le *netinfo;
@@ -3468,12 +3527,14 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
}
if (le32_to_cpu(pfn_result->count) < 1) {
- brcmf_err("Invalid result count, expected 1 (%d)\n",
- le32_to_cpu(pfn_result->count));
+ bphy_err(drvr, "Invalid result count, expected 1 (%d)\n",
+ le32_to_cpu(pfn_result->count));
return -EINVAL;
}
netinfo = brcmf_get_netinfo_array(pfn_result);
+ if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
+ netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
cfg->wowl.nd->n_channels = 1;
@@ -3496,6 +3557,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_wowl_wakeind_le wake_ind_le;
struct cfg80211_wowlan_wakeup wakeup_data;
struct cfg80211_wowlan_wakeup *wakeup;
@@ -3506,7 +3568,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le,
sizeof(wake_ind_le));
if (err) {
- brcmf_err("Get wowl_wakeind failed, err = %d\n", err);
+ bphy_err(drvr, "Get wowl_wakeind failed, err = %d\n", err);
return;
}
@@ -3547,7 +3609,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
cfg->wowl.nd_data_completed,
BRCMF_ND_INFO_TIMEOUT);
if (!timeout)
- brcmf_err("No result for wowl net detect\n");
+ bphy_err(drvr, "No result for wowl net detect\n");
else
wakeup_data.net_detect = cfg->wowl.nd_info;
}
@@ -3736,6 +3798,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+ struct brcmf_pub *drvr = cfg->pub;
s32 err;
u32 npmk, i;
@@ -3755,7 +3818,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
cfg->pmk_list.npmk = cpu_to_le32(npmk);
}
} else {
- brcmf_err("Too many PMKSA entries cached %d\n", npmk);
+ bphy_err(drvr, "Too many PMKSA entries cached %d\n", npmk);
return -EINVAL;
}
@@ -3778,6 +3841,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+ struct brcmf_pub *drvr = cfg->pub;
s32 err;
u32 npmk, i;
@@ -3801,7 +3865,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
memset(&pmk[i], 0, sizeof(*pmk));
cfg->pmk_list.npmk = cpu_to_le32(npmk - 1);
} else {
- brcmf_err("Cache entry not found\n");
+ bphy_err(drvr, "Cache entry not found\n");
return -EINVAL;
}
@@ -3833,19 +3897,20 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err;
s32 wpa_val;
/* set auth */
err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
if (err < 0) {
- brcmf_err("auth error %d\n", err);
+ bphy_err(drvr, "auth error %d\n", err);
return err;
}
/* set wsec */
err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
if (err < 0) {
- brcmf_err("wsec error %d\n", err);
+ bphy_err(drvr, "wsec error %d\n", err);
return err;
}
/* set upper-layer auth */
@@ -3855,7 +3920,7 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
wpa_val = WPA_AUTH_DISABLED;
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val);
if (err < 0) {
- brcmf_err("wpa_auth error %d\n", err);
+ bphy_err(drvr, "wpa_auth error %d\n", err);
return err;
}
@@ -3875,6 +3940,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
const struct brcmf_vs_tlv *wpa_ie,
bool is_rsn_ie)
{
+ struct brcmf_pub *drvr = ifp->drvr;
u32 auth = 0; /* d11 open authentication */
u16 count;
s32 err = 0;
@@ -3905,13 +3971,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
/* check for multicast cipher suite */
if (offset + WPA_IE_MIN_OUI_LEN > len) {
err = -EINVAL;
- brcmf_err("no multicast cipher suite\n");
+ bphy_err(drvr, "no multicast cipher suite\n");
goto exit;
}
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- brcmf_err("ivalid OUI\n");
+ bphy_err(drvr, "ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
@@ -3933,7 +3999,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
break;
default:
err = -EINVAL;
- brcmf_err("Invalid multi cast cipher info\n");
+ bphy_err(drvr, "Invalid multi cast cipher info\n");
goto exit;
}
@@ -3944,13 +4010,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
/* Check for unicast suite(s) */
if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
err = -EINVAL;
- brcmf_err("no unicast cipher suite\n");
+ bphy_err(drvr, "no unicast cipher suite\n");
goto exit;
}
for (i = 0; i < count; i++) {
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- brcmf_err("ivalid OUI\n");
+ bphy_err(drvr, "ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
@@ -3968,7 +4034,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
pval |= AES_ENABLED;
break;
default:
- brcmf_err("Invalid unicast security info\n");
+ bphy_err(drvr, "Invalid unicast security info\n");
}
offset++;
}
@@ -3978,13 +4044,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
/* Check for auth key management suite(s) */
if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
err = -EINVAL;
- brcmf_err("no auth key mgmt suite\n");
+ bphy_err(drvr, "no auth key mgmt suite\n");
goto exit;
}
for (i = 0; i < count; i++) {
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- brcmf_err("ivalid OUI\n");
+ bphy_err(drvr, "ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
@@ -4012,7 +4078,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
wpa_auth |= WPA2_AUTH_1X_SHA256;
break;
default:
- brcmf_err("Invalid key mgmt info\n");
+ bphy_err(drvr, "Invalid key mgmt info\n");
}
offset++;
}
@@ -4054,7 +4120,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
wme_bss_disable);
if (err < 0) {
- brcmf_err("wme_bss_disable error %d\n", err);
+ bphy_err(drvr, "wme_bss_disable error %d\n", err);
goto exit;
}
@@ -4068,7 +4134,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
&data[offset],
WPA_IE_MIN_OUI_LEN);
if (err < 0) {
- brcmf_err("bip error %d\n", err);
+ bphy_err(drvr, "bip error %d\n", err);
goto exit;
}
}
@@ -4079,13 +4145,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
/* set auth */
err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
if (err < 0) {
- brcmf_err("auth error %d\n", err);
+ bphy_err(drvr, "auth error %d\n", err);
goto exit;
}
/* set wsec */
err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err < 0) {
- brcmf_err("wsec error %d\n", err);
+ bphy_err(drvr, "wsec error %d\n", err);
goto exit;
}
/* Configure MFP, this needs to go after wsec otherwise the wsec command
@@ -4094,14 +4160,14 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) {
err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp);
if (err < 0) {
- brcmf_err("mfp error %d\n", err);
+ bphy_err(drvr, "mfp error %d\n", err);
goto exit;
}
}
/* set upper-layer auth */
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
if (err < 0) {
- brcmf_err("wpa_auth error %d\n", err);
+ bphy_err(drvr, "wpa_auth error %d\n", err);
goto exit;
}
@@ -4187,6 +4253,7 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
const u8 *vndr_ie_buf, u32 vndr_ie_len)
{
+ struct brcmf_pub *drvr;
struct brcmf_if *ifp;
struct vif_saved_ie *saved_ie;
s32 err = 0;
@@ -4208,6 +4275,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
if (!vif)
return -ENODEV;
ifp = vif->ifp;
+ drvr = ifp->drvr;
saved_ie = &vif->saved_ie;
brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx,
@@ -4239,13 +4307,13 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
break;
default:
err = -EPERM;
- brcmf_err("not suitable type\n");
+ bphy_err(drvr, "not suitable type\n");
goto exit;
}
if (vndr_ie_len > mgmt_ie_buf_len) {
err = -ENOMEM;
- brcmf_err("extra IE size too big\n");
+ bphy_err(drvr, "extra IE size too big\n");
goto exit;
}
@@ -4306,8 +4374,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
/* verify remained buf size before copy data */
if (remained_buf_len < (vndrie_info->vndrie.len +
VNDR_IE_VSIE_OFFSET)) {
- brcmf_err("no space in mgmt_ie_buf: len left %d",
- remained_buf_len);
+ bphy_err(drvr, "no space in mgmt_ie_buf: len left %d",
+ remained_buf_len);
break;
}
remained_buf_len -= (vndrie_info->ie_len +
@@ -4338,7 +4406,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
total_ie_buf_len);
if (err)
- brcmf_err("vndr ie set error : %d\n", err);
+ bphy_err(drvr, "vndr ie set error : %d\n", err);
}
exit:
@@ -4366,13 +4434,14 @@ static s32
brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
struct cfg80211_beacon_data *beacon)
{
+ struct brcmf_pub *drvr = vif->ifp->drvr;
s32 err;
/* Set Beacon IEs to FW */
err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG,
beacon->tail, beacon->tail_len);
if (err) {
- brcmf_err("Set Beacon IE Failed\n");
+ bphy_err(drvr, "Set Beacon IE Failed\n");
return err;
}
brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
@@ -4382,7 +4451,7 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
beacon->proberesp_ies,
beacon->proberesp_ies_len);
if (err)
- brcmf_err("Set Probe Resp IE Failed\n");
+ bphy_err(drvr, "Set Probe Resp IE Failed\n");
else
brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
@@ -4396,6 +4465,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
s32 ie_offset;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
const struct brcmf_tlv *ssid_ie;
const struct brcmf_tlv *country_ie;
struct brcmf_ssid_le ssid_le;
@@ -4491,7 +4561,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
is_11d);
if (err < 0) {
- brcmf_err("Regulatory Set Error, %d\n", err);
+ bphy_err(drvr, "Regulatory Set Error, %d\n",
+ err);
goto exit;
}
}
@@ -4499,8 +4570,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
settings->beacon_interval);
if (err < 0) {
- brcmf_err("Beacon Interval Set Error, %d\n",
- err);
+ bphy_err(drvr, "Beacon Interval Set Error, %d\n",
+ err);
goto exit;
}
}
@@ -4508,7 +4579,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
settings->dtim_period);
if (err < 0) {
- brcmf_err("DTIM Interval Set Error, %d\n", err);
+ bphy_err(drvr, "DTIM Interval Set Error, %d\n",
+ err);
goto exit;
}
}
@@ -4518,7 +4590,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
if (err < 0) {
- brcmf_err("BRCMF_C_DOWN error %d\n", err);
+ bphy_err(drvr, "BRCMF_C_DOWN error %d\n",
+ err);
goto exit;
}
brcmf_fil_iovar_int_set(ifp, "apsta", 0);
@@ -4526,7 +4599,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
if (err < 0) {
- brcmf_err("SET INFRA error %d\n", err);
+ bphy_err(drvr, "SET INFRA error %d\n", err);
goto exit;
}
} else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) {
@@ -4542,7 +4615,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
if (err < 0) {
- brcmf_err("setting AP mode failed %d\n", err);
+ bphy_err(drvr, "setting AP mode failed %d\n",
+ err);
goto exit;
}
if (!mbss) {
@@ -4551,14 +4625,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
*/
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
if (err < 0) {
- brcmf_err("Set Channel failed: chspec=%d, %d\n",
- chanspec, err);
+ bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n",
+ chanspec, err);
goto exit;
}
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0) {
- brcmf_err("BRCMF_C_UP error (%d)\n", err);
+ bphy_err(drvr, "BRCMF_C_UP error (%d)\n", err);
goto exit;
}
/* On DOWN the firmware removes the WEP keys, reconfigure
@@ -4573,14 +4647,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, sizeof(join_params));
if (err < 0) {
- brcmf_err("SET SSID error (%d)\n", err);
+ bphy_err(drvr, "SET SSID error (%d)\n", err);
goto exit;
}
if (settings->hidden_ssid) {
err = brcmf_fil_iovar_int_set(ifp, "closednet", 1);
if (err) {
- brcmf_err("closednet error (%d)\n", err);
+ bphy_err(drvr, "closednet error (%d)\n", err);
goto exit;
}
}
@@ -4589,14 +4663,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
} else if (dev_role == NL80211_IFTYPE_P2P_GO) {
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
if (err < 0) {
- brcmf_err("Set Channel failed: chspec=%d, %d\n",
- chanspec, err);
+ bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n",
+ chanspec, err);
goto exit;
}
err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
sizeof(ssid_le));
if (err < 0) {
- brcmf_err("setting ssid failed %d\n", err);
+ bphy_err(drvr, "setting ssid failed %d\n", err);
goto exit;
}
bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
@@ -4604,7 +4678,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
sizeof(bss_enable));
if (err < 0) {
- brcmf_err("bss_enable config failed %d\n", err);
+ bphy_err(drvr, "bss_enable config failed %d\n", err);
goto exit;
}
@@ -4627,7 +4701,9 @@ exit:
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_pub *drvr = cfg->pub;
s32 err;
struct brcmf_fil_bss_enable_le bss_enable;
struct brcmf_join_params join_params;
@@ -4652,13 +4728,13 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, sizeof(join_params));
if (err < 0)
- brcmf_err("SET SSID error (%d)\n", err);
+ bphy_err(drvr, "SET SSID error (%d)\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
if (err < 0)
- brcmf_err("BRCMF_C_DOWN error %d\n", err);
+ bphy_err(drvr, "BRCMF_C_DOWN error %d\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0)
- brcmf_err("setting AP mode failed %d\n", err);
+ bphy_err(drvr, "setting AP mode failed %d\n", err);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
brcmf_fil_iovar_int_set(ifp, "mbss", 0);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
@@ -4666,7 +4742,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
/* Bring device back up so it can be used again */
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0)
- brcmf_err("BRCMF_C_UP error %d\n", err);
+ bphy_err(drvr, "BRCMF_C_UP error %d\n", err);
brcmf_vif_clear_mgmt_ies(ifp->vif);
} else {
@@ -4675,7 +4751,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
sizeof(bss_enable));
if (err < 0)
- brcmf_err("bss_enable config failed %d\n", err);
+ bphy_err(drvr, "bss_enable config failed %d\n", err);
}
brcmf_set_mpc(ifp, 1);
brcmf_configure_arp_nd_offload(ifp, true);
@@ -4704,6 +4780,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
struct station_del_parameters *params)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_scb_val_le scbval;
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
@@ -4723,7 +4800,8 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
&scbval, sizeof(scbval));
if (err)
- brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
+ bphy_err(drvr, "SCB_DEAUTHENTICATE_FOR_REASON failed %d\n",
+ err);
brcmf_dbg(TRACE, "Exit\n");
return err;
@@ -4733,6 +4811,8 @@ static int
brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
const u8 *mac, struct station_parameters *params)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
@@ -4753,7 +4833,7 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE,
(void *)mac, ETH_ALEN);
if (err < 0)
- brcmf_err("Setting SCB (de-)authorize failed, %d\n", err);
+ bphy_err(drvr, "Setting SCB (de-)authorize failed, %d\n", err);
return err;
}
@@ -4783,6 +4863,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = params->chan;
+ struct brcmf_pub *drvr = cfg->pub;
const u8 *buf = params->buf;
size_t len = params->len;
const struct ieee80211_mgmt *mgmt;
@@ -4803,7 +4884,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
mgmt = (const struct ieee80211_mgmt *)buf;
if (!ieee80211_is_mgmt(mgmt->frame_control)) {
- brcmf_err("Driver only allows MGMT packet type\n");
+ bphy_err(drvr, "Driver only allows MGMT packet type\n");
return -EPERM;
}
@@ -4834,13 +4915,13 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
GFP_KERNEL);
} else if (ieee80211_is_action(mgmt->frame_control)) {
if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
- brcmf_err("invalid action frame length\n");
+ bphy_err(drvr, "invalid action frame length\n");
err = -EINVAL;
goto exit;
}
af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
if (af_params == NULL) {
- brcmf_err("unable to allocate frame\n");
+ bphy_err(drvr, "unable to allocate frame\n");
err = -ENOMEM;
goto exit;
}
@@ -4891,6 +4972,7 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
u64 cookie)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_vif *vif;
int err = 0;
@@ -4898,7 +4980,7 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
if (vif == NULL) {
- brcmf_err("No p2p device available for probe response\n");
+ bphy_err(drvr, "No p2p device available for probe response\n");
err = -ENODEV;
goto exit;
}
@@ -4913,6 +4995,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = wdev->netdev;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_if *ifp;
struct brcmu_chan ch;
enum nl80211_band band = 0;
@@ -4926,7 +5009,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy,
err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec);
if (err) {
- brcmf_err("chanspec failed (%d)\n", err);
+ bphy_err(drvr, "chanspec failed (%d)\n", err);
return err;
}
@@ -5048,6 +5131,8 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
struct net_device *ndev, const u8 *peer,
enum nl80211_tdls_operation oper)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_if *ifp;
struct brcmf_tdls_iovar_le info;
int ret = 0;
@@ -5065,7 +5150,7 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint",
&info, sizeof(info));
if (ret < 0)
- brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret);
+ bphy_err(drvr, "tdls_endpoint iovar failed: ret=%d\n", ret);
return ret;
}
@@ -5076,6 +5161,8 @@ brcmf_cfg80211_update_conn_params(struct wiphy *wiphy,
struct cfg80211_connect_params *sme,
u32 changed)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_if *ifp;
int err;
@@ -5086,7 +5173,7 @@ brcmf_cfg80211_update_conn_params(struct wiphy *wiphy,
err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
sme->ie, sme->ie_len);
if (err)
- brcmf_err("Set Assoc REQ IE Failed\n");
+ bphy_err(drvr, "Set Assoc REQ IE Failed\n");
else
brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
@@ -5098,6 +5185,8 @@ static int
brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_gtk_rekey_data *gtk)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_gtk_keyinfo_le gtk_le;
int ret;
@@ -5112,7 +5201,7 @@ brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
sizeof(gtk_le));
if (ret < 0)
- brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
+ bphy_err(drvr, "gtk_key_info iovar failed: ret=%d\n", ret);
return ret;
}
@@ -5344,6 +5433,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
u32 req_len;
@@ -5355,7 +5445,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
cfg->extra_buf, WL_ASSOC_INFO_MAX);
if (err) {
- brcmf_err("could not get assoc info (%d)\n", err);
+ bphy_err(drvr, "could not get assoc info (%d)\n", err);
return err;
}
assoc_info =
@@ -5367,7 +5457,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
cfg->extra_buf,
WL_ASSOC_INFO_MAX);
if (err) {
- brcmf_err("could not get assoc req (%d)\n", err);
+ bphy_err(drvr, "could not get assoc req (%d)\n", err);
return err;
}
conn_info->req_ie_len = req_len;
@@ -5383,7 +5473,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
cfg->extra_buf,
WL_ASSOC_INFO_MAX);
if (err) {
- brcmf_err("could not get assoc resp (%d)\n", err);
+ bphy_err(drvr, "could not get assoc resp (%d)\n", err);
return err;
}
conn_info->resp_ie_len = resp_len;
@@ -5510,6 +5600,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
+ struct brcmf_pub *drvr = cfg->pub;
static int generation;
u32 event = e->event_code;
u32 reason = e->reason;
@@ -5527,7 +5618,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
(reason == BRCMF_E_STATUS_SUCCESS)) {
if (!data) {
- brcmf_err("No IEs present in ASSOC/REASSOC_IND");
+ bphy_err(drvr, "No IEs present in ASSOC/REASSOC_IND\n");
return -EINVAL;
}
@@ -5819,6 +5910,7 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err;
u32 bcn_timeout;
__le32 roamtrigger[2];
@@ -5831,7 +5923,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
if (err) {
- brcmf_err("bcn_timeout error (%d)\n", err);
+ bphy_err(drvr, "bcn_timeout error (%d)\n", err);
goto roam_setup_done;
}
@@ -5843,7 +5935,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
err = brcmf_fil_iovar_int_set(ifp, "roam_off",
ifp->drvr->settings->roamoff);
if (err) {
- brcmf_err("roam_off error (%d)\n", err);
+ bphy_err(drvr, "roam_off error (%d)\n", err);
goto roam_setup_done;
}
@@ -5852,7 +5944,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
(void *)roamtrigger, sizeof(roamtrigger));
if (err) {
- brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_ROAM_TRIGGER error (%d)\n", err);
goto roam_setup_done;
}
@@ -5861,7 +5953,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
(void *)roam_delta, sizeof(roam_delta));
if (err) {
- brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
+ bphy_err(drvr, "WLC_SET_ROAM_DELTA error (%d)\n", err);
goto roam_setup_done;
}
@@ -5872,25 +5964,26 @@ roam_setup_done:
static s32
brcmf_dongle_scantime(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 err = 0;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
BRCMF_SCAN_CHANNEL_TIME);
if (err) {
- brcmf_err("Scan assoc time error (%d)\n", err);
+ bphy_err(drvr, "Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
BRCMF_SCAN_UNASSOC_TIME);
if (err) {
- brcmf_err("Scan unassoc time error (%d)\n", err);
+ bphy_err(drvr, "Scan unassoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
BRCMF_SCAN_PASSIVE_TIME);
if (err) {
- brcmf_err("Scan passive time error (%d)\n", err);
+ bphy_err(drvr, "Scan passive time error (%d)\n", err);
goto dongle_scantime_out;
}
@@ -5922,10 +6015,11 @@ static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
u32 bw_cap[])
{
- struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct wiphy *wiphy = cfg_to_wiphy(cfg);
+ struct brcmf_pub *drvr = cfg->pub;
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
struct ieee80211_supported_band *band;
struct ieee80211_channel *channel;
- struct wiphy *wiphy;
struct brcmf_chanspec_list *list;
struct brcmu_chan ch;
int err;
@@ -5944,11 +6038,10 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
BRCMF_DCMD_MEDLEN);
if (err) {
- brcmf_err("get chanspecs error (%d)\n", err);
+ bphy_err(drvr, "get chanspecs error (%d)\n", err);
goto fail_pbuf;
}
- wiphy = cfg_to_wiphy(cfg);
band = wiphy->bands[NL80211_BAND_2GHZ];
if (band)
for (i = 0; i < band->n_channels; i++)
@@ -5968,7 +6061,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
} else if (ch.band == BRCMU_CHAN_BAND_5G) {
band = wiphy->bands[NL80211_BAND_5GHZ];
} else {
- brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
+ bphy_err(drvr, "Invalid channel Spec. 0x%x.\n",
+ ch.chspec);
continue;
}
if (!band)
@@ -5991,8 +6085,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
/* It seems firmware supports some channel we never
* considered. Something new in IEEE standard?
*/
- brcmf_err("Ignoring unexpected firmware channel %d\n",
- ch.control_ch_num);
+ bphy_err(drvr, "Ignoring unexpected firmware channel %d\n",
+ ch.control_ch_num);
continue;
}
@@ -6002,11 +6096,21 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
/* assuming the chanspecs order is HT20,
* HT40 upper, HT40 lower, and VHT80.
*/
- if (ch.bw == BRCMU_CHAN_BW_80) {
+ switch (ch.bw) {
+ case BRCMU_CHAN_BW_160:
+ channel->flags &= ~IEEE80211_CHAN_NO_160MHZ;
+ break;
+ case BRCMU_CHAN_BW_80:
channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
- } else if (ch.bw == BRCMU_CHAN_BW_40) {
+ break;
+ case BRCMU_CHAN_BW_40:
brcmf_update_bw40_channel_flag(channel, &ch);
- } else {
+ break;
+ default:
+ wiphy_warn(wiphy, "Firmware reported unsupported bandwidth %d\n",
+ ch.bw);
+ /* fall through */
+ case BRCMU_CHAN_BW_20:
/* enable the channel and disable other bandwidths
* for now as mentioned order assure they are enabled
* for subsequent chanspecs.
@@ -6038,7 +6142,8 @@ fail_pbuf:
static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct brcmf_pub *drvr = cfg->pub;
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
struct ieee80211_supported_band *band;
struct brcmf_fil_bwcap_le band_bwcap;
struct brcmf_chanspec_list *list;
@@ -6084,7 +6189,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
BRCMF_DCMD_MEDLEN);
if (err) {
- brcmf_err("get chanspecs error (%d)\n", err);
+ bphy_err(drvr, "get chanspecs error (%d)\n", err);
kfree(pbuf);
return err;
}
@@ -6115,6 +6220,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
{
+ struct brcmf_pub *drvr = ifp->drvr;
u32 band, mimo_bwcap;
int err;
@@ -6150,7 +6256,7 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
break;
default:
- brcmf_err("invalid mimo_bw_cap value\n");
+ bphy_err(drvr, "invalid mimo_bw_cap value\n");
}
}
@@ -6225,8 +6331,9 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
- struct wiphy *wiphy;
+ struct brcmf_pub *drvr = cfg->pub;
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+ struct wiphy *wiphy = cfg_to_wiphy(cfg);
u32 nmode = 0;
u32 vhtmode = 0;
u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
@@ -6242,7 +6349,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
if (err) {
- brcmf_err("nmode error (%d)\n", err);
+ bphy_err(drvr, "nmode error (%d)\n", err);
} else {
brcmf_get_bwcap(ifp, bw_cap);
}
@@ -6252,7 +6359,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
if (err) {
- brcmf_err("rxchain error (%d)\n", err);
+ bphy_err(drvr, "rxchain error (%d)\n", err);
nchain = 1;
} else {
for (nchain = 0; rxchain; nchain++)
@@ -6262,7 +6369,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
err = brcmf_construct_chaninfo(cfg, bw_cap);
if (err) {
- brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
+ bphy_err(drvr, "brcmf_construct_chaninfo failed (%d)\n", err);
return err;
}
@@ -6274,7 +6381,6 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
&txbf_bfr_cap);
}
- wiphy = cfg_to_wiphy(cfg);
for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
band = wiphy->bands[i];
if (band == NULL)
@@ -6470,12 +6576,13 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp)
{
#ifdef CONFIG_PM
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_pub *drvr = cfg->pub;
struct wiphy_wowlan_support *wowl;
wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support),
GFP_KERNEL);
if (!wowl) {
- brcmf_err("only support basic wowlan features\n");
+ bphy_err(drvr, "only support basic wowlan features\n");
wiphy->wowlan = &brcmf_wowlan_support;
return;
}
@@ -6572,7 +6679,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist,
sizeof(bandlist));
if (err) {
- brcmf_err("could not obtain band info: err=%d\n", err);
+ bphy_err(drvr, "could not obtain band info: err=%d\n", err);
return err;
}
/* first entry in bandlist is number of bands */
@@ -6621,6 +6728,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct net_device *ndev;
struct wireless_dev *wdev;
struct brcmf_if *ifp;
@@ -6658,7 +6766,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1);
if (err) {
- brcmf_err("failed to set frameburst mode\n");
+ bphy_err(drvr, "failed to set frameburst mode\n");
goto default_conf_out;
}
@@ -6839,6 +6947,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_fil_country_le ccreq;
s32 err;
int i;
@@ -6850,8 +6959,8 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
/* ignore non-ISO3166 country codes */
for (i = 0; i < 2; i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
- brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
- req->alpha2[0], req->alpha2[1]);
+ bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n",
+ req->alpha2[0], req->alpha2[1]);
return;
}
@@ -6860,7 +6969,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
if (err) {
- brcmf_err("Country code iovar returned err = %d\n", err);
+ bphy_err(drvr, "Country code iovar returned err = %d\n", err);
return;
}
@@ -6870,7 +6979,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
if (err) {
- brcmf_err("Firmware rejected country setting\n");
+ bphy_err(drvr, "Firmware rejected country setting\n");
return;
}
brcmf_setup_wiphybands(cfg);
@@ -6916,13 +7025,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
u16 *cap = NULL;
if (!ndev) {
- brcmf_err("ndev is invalid\n");
+ bphy_err(drvr, "ndev is invalid\n");
return NULL;
}
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
- brcmf_err("Could not allocate wiphy device\n");
+ bphy_err(drvr, "Could not allocate wiphy device\n");
return NULL;
}
@@ -6943,7 +7052,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
err = wl_init_priv(cfg);
if (err) {
- brcmf_err("Failed to init iwm_priv (%d)\n", err);
+ bphy_err(drvr, "Failed to init iwm_priv (%d)\n", err);
brcmf_free_vif(vif);
goto wiphy_out;
}
@@ -6952,7 +7061,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
/* determine d11 io type before wiphy setup */
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
if (err) {
- brcmf_err("Failed to get D11 version (%d)\n", err);
+ bphy_err(drvr, "Failed to get D11 version (%d)\n", err);
goto priv_out;
}
cfg->d11inf.io_type = (u8)io_type;
@@ -6986,13 +7095,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
#endif
err = wiphy_register(wiphy);
if (err < 0) {
- brcmf_err("Could not register wiphy device (%d)\n", err);
+ bphy_err(drvr, "Could not register wiphy device (%d)\n", err);
goto priv_out;
}
err = brcmf_setup_wiphybands(cfg);
if (err) {
- brcmf_err("Setting wiphy bands failed (%d)\n", err);
+ bphy_err(drvr, "Setting wiphy bands failed (%d)\n", err);
goto wiphy_unreg_out;
}
@@ -7010,24 +7119,24 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
err = brcmf_fweh_activate_events(ifp);
if (err) {
- brcmf_err("FWEH activation failed (%d)\n", err);
+ bphy_err(drvr, "FWEH activation failed (%d)\n", err);
goto wiphy_unreg_out;
}
err = brcmf_p2p_attach(cfg, p2pdev_forced);
if (err) {
- brcmf_err("P2P initialisation failed (%d)\n", err);
+ bphy_err(drvr, "P2P initialisation failed (%d)\n", err);
goto wiphy_unreg_out;
}
err = brcmf_btcoex_attach(cfg);
if (err) {
- brcmf_err("BT-coex initialisation failed (%d)\n", err);
+ bphy_err(drvr, "BT-coex initialisation failed (%d)\n", err);
brcmf_p2p_detach(&cfg->p2p);
goto wiphy_unreg_out;
}
err = brcmf_pno_attach(cfg);
if (err) {
- brcmf_err("PNO initialisation failed (%d)\n", err);
+ bphy_err(drvr, "PNO initialisation failed (%d)\n", err);
brcmf_btcoex_detach(cfg);
brcmf_p2p_detach(&cfg->p2p);
goto wiphy_unreg_out;
@@ -7047,7 +7156,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
/* (re-) activate FWEH event handling */
err = brcmf_fweh_activate_events(ifp);
if (err) {
- brcmf_err("FWEH activation failed (%d)\n", err);
+ bphy_err(drvr, "FWEH activation failed (%d)\n", err);
goto detach;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 1f1e95a15a17..96b8d5b3aeed 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -90,6 +90,7 @@ struct brcmf_mp_global_t brcmf_mp_global;
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_join_pref_params join_pref_params[2];
int err;
@@ -106,7 +107,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
sizeof(join_pref_params));
if (err)
- brcmf_err("Set join_pref error (%d)\n", err);
+ bphy_err(drvr, "Set join_pref error (%d)\n", err);
}
static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
@@ -129,7 +130,8 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
{
- struct brcmf_bus *bus = ifp->drvr->bus_if;
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_bus *bus = drvr->bus_if;
struct brcmf_dload_data_le *chunk_buf;
const struct firmware *clm = NULL;
u8 clm_name[BRCMF_FW_NAME_LEN];
@@ -145,11 +147,11 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
memset(clm_name, 0, sizeof(clm_name));
err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
if (err) {
- brcmf_err("get CLM blob file name failed (%d)\n", err);
+ bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
return err;
}
- err = request_firmware(&clm, clm_name, bus->dev);
+ err = firmware_request_nowarn(&clm, clm_name, bus->dev);
if (err) {
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
err);
@@ -182,12 +184,12 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
} while ((datalen > 0) && (err == 0));
if (err) {
- brcmf_err("clmload (%zu byte file) failed (%d); ",
- clm->size, err);
+ bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n",
+ clm->size, err);
/* Retrieve clmload_status and print */
err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
if (err)
- brcmf_err("get clmload_status failed (%d)\n", err);
+ bphy_err(drvr, "get clmload_status failed (%d)\n", err);
else
brcmf_dbg(INFO, "clmload_status=%d\n", status);
err = -EIO;
@@ -201,6 +203,7 @@ done:
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
u8 buf[BRCMF_DCMD_SMLEN];
struct brcmf_bus *bus;
@@ -214,7 +217,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
sizeof(ifp->mac_addr));
if (err < 0) {
- brcmf_err("Retrieving cur_etheraddr failed, %d\n", err);
+ bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
goto done;
}
memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
@@ -226,7 +229,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
&revinfo, sizeof(revinfo));
if (err < 0) {
- brcmf_err("retrieving revision info failed, %d\n", err);
+ bphy_err(drvr, "retrieving revision info failed, %d\n", err);
strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
} else {
ri->vendorid = le32_to_cpu(revinfo.vendorid);
@@ -260,7 +263,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
/* Do any CLM downloading */
err = brcmf_c_process_clm_blob(ifp);
if (err < 0) {
- brcmf_err("download CLM blob file failed, %d\n", err);
+ bphy_err(drvr, "download CLM blob file failed, %d\n", err);
goto done;
}
@@ -269,8 +272,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
strcpy(buf, "ver");
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
if (err < 0) {
- brcmf_err("Retrieving version information failed, %d\n",
- err);
+ bphy_err(drvr, "Retrieving version information failed, %d\n",
+ err);
goto done;
}
ptr = (char *)buf;
@@ -304,7 +307,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
/* set mpc */
err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
if (err) {
- brcmf_err("failed setting mpc\n");
+ bphy_err(drvr, "failed setting mpc\n");
goto done;
}
@@ -314,14 +317,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
BRCMF_EVENTING_MASK_LEN);
if (err) {
- brcmf_err("Get event_msgs error (%d)\n", err);
+ bphy_err(drvr, "Get event_msgs error (%d)\n", err);
goto done;
}
setbit(eventmask, BRCMF_E_IF);
err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
BRCMF_EVENTING_MASK_LEN);
if (err) {
- brcmf_err("Set event_msgs error (%d)\n", err);
+ bphy_err(drvr, "Set event_msgs error (%d)\n", err);
goto done;
}
@@ -329,8 +332,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
if (err) {
- brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
- err);
+ bphy_err(drvr, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+ err);
goto done;
}
@@ -338,8 +341,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
if (err) {
- brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
- err);
+ bphy_err(drvr, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+ err);
goto done;
}
@@ -350,7 +353,7 @@ done:
}
#ifndef CONFIG_BRCM_TRACING
-void __brcmf_err(const char *func, const char *fmt, ...)
+void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
@@ -359,7 +362,10 @@ void __brcmf_err(const char *func, const char *fmt, ...)
vaf.fmt = fmt;
vaf.va = &args;
- pr_err("%s: %pV", func, &vaf);
+ if (bus)
+ dev_err(bus->dev, "%s: %pV", func, &vaf);
+ else
+ pr_err("%s: %pV", func, &vaf);
va_end(args);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 860a4372cb56..4fbe8791f674 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -43,6 +43,36 @@
#define BRCMF_BSSIDX_INVALID -1
+#define RXS_PBPRES BIT(2)
+
+#define D11_PHY_HDR_LEN 6
+
+struct d11rxhdr_le {
+ __le16 RxFrameSize;
+ u16 PAD;
+ __le16 PhyRxStatus_0;
+ __le16 PhyRxStatus_1;
+ __le16 PhyRxStatus_2;
+ __le16 PhyRxStatus_3;
+ __le16 PhyRxStatus_4;
+ __le16 PhyRxStatus_5;
+ __le16 RxStatus1;
+ __le16 RxStatus2;
+ __le16 RxTSFTime;
+ __le16 RxChan;
+ u8 unknown[12];
+} __packed;
+
+struct wlc_d11rxhdr {
+ struct d11rxhdr_le rxhdr;
+ __le32 tsf_l;
+ s8 rssi;
+ s8 rxpwr0;
+ s8 rxpwr1;
+ s8 do_rssi_ma;
+ s8 rxpwr[4];
+} __packed;
+
char *brcmf_ifname(struct brcmf_if *ifp)
{
if (!ifp)
@@ -60,7 +90,7 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
s32 bsscfgidx;
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
- brcmf_err("ifidx %d out of range\n", ifidx);
+ bphy_err(drvr, "ifidx %d out of range\n", ifidx);
return NULL;
}
@@ -111,7 +141,9 @@ void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
static void _brcmf_set_multicast_list(struct work_struct *work)
{
- struct brcmf_if *ifp;
+ struct brcmf_if *ifp = container_of(work, struct brcmf_if,
+ multicast_work);
+ struct brcmf_pub *drvr = ifp->drvr;
struct net_device *ndev;
struct netdev_hw_addr *ha;
u32 cmd_value, cnt;
@@ -120,8 +152,6 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
u32 buflen;
s32 err;
- ifp = container_of(work, struct brcmf_if, multicast_work);
-
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
ndev = ifp->ndev;
@@ -151,7 +181,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
if (err < 0) {
- brcmf_err("Setting mcast_list failed, %d\n", err);
+ bphy_err(drvr, "Setting mcast_list failed, %d\n", err);
cmd_value = cnt ? true : cmd_value;
}
@@ -164,25 +194,25 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
*/
err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
if (err < 0)
- brcmf_err("Setting allmulti failed, %d\n", err);
+ bphy_err(drvr, "Setting allmulti failed, %d\n", err);
/*Finally, pick up the PROMISC flag */
cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
if (err < 0)
- brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
- err);
+ bphy_err(drvr, "Setting BRCMF_C_SET_PROMISC failed, %d\n",
+ err);
brcmf_configure_arp_nd_offload(ifp, !cmd_value);
}
#if IS_ENABLED(CONFIG_IPV6)
static void _brcmf_update_ndtable(struct work_struct *work)
{
- struct brcmf_if *ifp;
+ struct brcmf_if *ifp = container_of(work, struct brcmf_if,
+ ndoffload_work);
+ struct brcmf_pub *drvr = ifp->drvr;
int i, ret;
- ifp = container_of(work, struct brcmf_if, ndoffload_work);
-
/* clear the table in firmware */
ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0);
if (ret) {
@@ -195,7 +225,7 @@ static void _brcmf_update_ndtable(struct work_struct *work)
&ifp->ipv6_addr_tbl[i],
sizeof(struct in6_addr));
if (ret)
- brcmf_err("add nd ip err %d\n", ret);
+ bphy_err(drvr, "add nd ip err %d\n", ret);
}
}
#else
@@ -208,6 +238,7 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct sockaddr *sa = (struct sockaddr *)addr;
+ struct brcmf_pub *drvr = ifp->drvr;
int err;
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
@@ -215,7 +246,7 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", sa->sa_data,
ETH_ALEN);
if (err < 0) {
- brcmf_err("Setting cur_etheraddr failed, %d\n", err);
+ bphy_err(drvr, "Setting cur_etheraddr failed, %d\n", err);
} else {
brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data);
memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN);
@@ -275,7 +306,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
/* Can the device send data? */
if (drvr->bus_if->state != BRCMF_BUS_UP) {
- brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
+ bphy_err(drvr, "xmit rejected state=%d\n", drvr->bus_if->state);
netif_stop_queue(ndev);
dev_kfree_skb(skb);
ret = -ENODEV;
@@ -309,8 +340,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
ret = pskb_expand_head(skb, ALIGN(head_delta, NET_SKB_PAD), 0,
GFP_ATOMIC);
if (ret < 0) {
- brcmf_err("%s: failed to expand headroom\n",
- brcmf_ifname(ifp));
+ bphy_err(drvr, "%s: failed to expand headroom\n",
+ brcmf_ifname(ifp));
atomic_inc(&drvr->bus_if->stats.pktcow_failed);
goto done;
}
@@ -409,6 +440,31 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
/* Do nothing */
+ } else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) {
+ struct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb->data;
+ struct ieee80211_radiotap_header *radiotap;
+ unsigned int offset;
+ u16 RxStatus1;
+
+ RxStatus1 = le16_to_cpu(wlc_rxhdr->rxhdr.RxStatus1);
+
+ offset = sizeof(struct wlc_d11rxhdr);
+ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU
+ * subframes
+ */
+ if (RxStatus1 & RXS_PBPRES)
+ offset += 2;
+ offset += D11_PHY_HDR_LEN;
+
+ skb_pull(skb, offset);
+
+ /* TODO: use RX header to fill some radiotap data */
+ radiotap = skb_push(skb, sizeof(*radiotap));
+ memset(radiotap, 0, sizeof(*radiotap));
+ radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
+
+ /* TODO: 4 bytes with receive status? */
+ skb->len -= 4;
} else {
struct ieee80211_radiotap_header *radiotap;
@@ -464,7 +520,8 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
} else {
/* Process special event packets */
if (handle_event)
- brcmf_fweh_process_skb(ifp->drvr, skb);
+ brcmf_fweh_process_skb(ifp->drvr, skb,
+ BCMILCP_SUBTYPE_VENDOR_LONG);
brcmf_netif_rx(ifp, skb);
}
@@ -481,7 +538,7 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
if (brcmf_rx_hdrpull(drvr, skb, &ifp))
return;
- brcmf_fweh_process_skb(ifp->drvr, skb);
+ brcmf_fweh_process_skb(ifp->drvr, skb, 0);
brcmu_pkt_buf_free_skb(skb);
}
@@ -551,7 +608,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
/* If bus is not ready, can't continue */
if (bus_if->state != BRCMF_BUS_UP) {
- brcmf_err("failed bus is not ready\n");
+ bphy_err(drvr, "failed bus is not ready\n");
return -EAGAIN;
}
@@ -565,7 +622,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
ndev->features &= ~NETIF_F_IP_CSUM;
if (brcmf_cfg80211_up(ndev)) {
- brcmf_err("failed to bring up cfg80211\n");
+ bphy_err(drvr, "failed to bring up cfg80211\n");
return -EIO;
}
@@ -610,7 +667,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
else
err = register_netdev(ndev);
if (err != 0) {
- brcmf_err("couldn't register the net device\n");
+ bphy_err(drvr, "couldn't register the net device\n");
goto fail;
}
@@ -687,6 +744,7 @@ static const struct net_device_ops brcmf_netdev_ops_p2p = {
static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct net_device *ndev;
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
@@ -699,7 +757,7 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
if (register_netdev(ndev) != 0) {
- brcmf_err("couldn't register the p2p net device\n");
+ bphy_err(drvr, "couldn't register the p2p net device\n");
goto fail;
}
@@ -728,8 +786,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
*/
if (ifp) {
if (ifidx) {
- brcmf_err("ERROR: netdev:%s already exists\n",
- ifp->ndev->name);
+ bphy_err(drvr, "ERROR: netdev:%s already exists\n",
+ ifp->ndev->name);
netif_stop_queue(ifp->ndev);
brcmf_net_detach(ifp->ndev, false);
drvr->iflist[bsscfgidx] = NULL;
@@ -787,7 +845,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,
ifp = drvr->iflist[bsscfgidx];
drvr->iflist[bsscfgidx] = NULL;
if (!ifp) {
- brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx);
+ bphy_err(drvr, "Null interface, bsscfgidx=%d\n", bsscfgidx);
return;
}
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,
@@ -837,16 +895,17 @@ static int brcmf_psm_watchdog_notify(struct brcmf_if *ifp,
const struct brcmf_event_msg *evtmsg,
void *data)
{
+ struct brcmf_pub *drvr = ifp->drvr;
int err;
brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
- brcmf_err("PSM's watchdog has fired!\n");
+ bphy_err(drvr, "PSM's watchdog has fired!\n");
err = brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
evtmsg->datalen);
if (err)
- brcmf_err("Failed to get memory dump, %d\n", err);
+ bphy_err(drvr, "Failed to get memory dump, %d\n", err);
return err;
}
@@ -890,7 +949,7 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb,
ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table,
sizeof(addr_table));
if (ret) {
- brcmf_err("fail to get arp ip table err:%d\n", ret);
+ bphy_err(drvr, "fail to get arp ip table err:%d\n", ret);
return NOTIFY_OK;
}
@@ -907,7 +966,7 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb,
ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip",
&ifa->ifa_address, sizeof(ifa->ifa_address));
if (ret)
- brcmf_err("add arp ip err %d\n", ret);
+ bphy_err(drvr, "add arp ip err %d\n", ret);
}
break;
case NETDEV_DOWN:
@@ -919,8 +978,8 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb,
ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear",
NULL, 0);
if (ret) {
- brcmf_err("fail to clear arp ip table err:%d\n",
- ret);
+ bphy_err(drvr, "fail to clear arp ip table err:%d\n",
+ ret);
return NOTIFY_OK;
}
for (i = 0; i < ARPOL_MAX_ENTRIES; i++) {
@@ -930,8 +989,8 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb,
&addr_table[i],
sizeof(addr_table[i]));
if (ret)
- brcmf_err("add arp ip err %d\n",
- ret);
+ bphy_err(drvr, "add arp ip err %d\n",
+ ret);
}
}
break;
@@ -1100,11 +1159,12 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
brcmf_feat_debugfs_create(drvr);
brcmf_proto_debugfs_create(drvr);
+ brcmf_bus_debugfs_create(bus_if);
return 0;
fail:
- brcmf_err("failed: %d\n", ret);
+ bphy_err(drvr, "failed: %d\n", ret);
if (drvr->config) {
brcmf_cfg80211_detach(drvr->config);
drvr->config = NULL;
@@ -1156,7 +1216,7 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
/* Attach and link in the protocol */
ret = brcmf_proto_attach(drvr);
if (ret != 0) {
- brcmf_err("brcmf_prot_attach failed\n");
+ bphy_err(drvr, "brcmf_prot_attach failed\n");
goto fail;
}
@@ -1169,7 +1229,7 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
ret = brcmf_bus_started(drvr, ops);
if (ret != 0) {
- brcmf_err("dongle is not responding: err=%d\n", ret);
+ bphy_err(drvr, "dongle is not responding: err=%d\n", ret);
goto fail;
}
@@ -1269,6 +1329,7 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
int err;
err = wait_event_timeout(ifp->pend_8021x_wait,
@@ -1276,7 +1337,7 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
MAX_WAIT_FOR_8021X_TX);
if (!err)
- brcmf_err("Timed out waiting for no pending 802.1x packets\n");
+ bphy_err(drvr, "Timed out waiting for no pending 802.1x packets\n");
return !err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index dcf6e27cc16f..d8085ce579f4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -36,7 +36,7 @@
#define BRCMF_DCMD_MEDLEN 1536
#define BRCMF_DCMD_MAXLEN 8192
-/* IOCTL from host to device are limited in lenght. A device can only handle
+/* IOCTL from host to device are limited in length. A device can only handle
* ethernet frame size. This limitation is to be applied by protocol layer.
*/
#define BRCMF_TX_IOCTL_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index cfed0626bf5a..2998726b62c3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -45,17 +45,30 @@
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-__printf(2, 3)
-void __brcmf_err(const char *func, const char *fmt, ...);
+struct brcmf_bus;
+
+__printf(3, 4)
+void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...);
/* Macro for error messages. When debugging / tracing the driver all error
* messages are important to us.
*/
+#ifndef brcmf_err
#define brcmf_err(fmt, ...) \
do { \
if (IS_ENABLED(CONFIG_BRCMDBG) || \
IS_ENABLED(CONFIG_BRCM_TRACING) || \
net_ratelimit()) \
- __brcmf_err(__func__, fmt, ##__VA_ARGS__); \
+ __brcmf_err(NULL, __func__, fmt, ##__VA_ARGS__);\
+ } while (0)
+#endif
+
+#define bphy_err(drvr, fmt, ...) \
+ do { \
+ if (IS_ENABLED(CONFIG_BRCMDBG) || \
+ IS_ENABLED(CONFIG_BRCM_TRACING) || \
+ net_ratelimit()) \
+ wiphy_err((drvr)->wiphy, "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
} while (0)
#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
index 51d76ac45075..7535cb0d4ac0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
@@ -43,6 +43,10 @@ static const struct brcmf_dmi_data meegopad_t08_data = {
BRCM_CC_43340_CHIP_ID, 2, "meegopad-t08"
};
+static const struct brcmf_dmi_data pov_tab_p1006w_data = {
+ BRCM_CC_43340_CHIP_ID, 2, "pov-tab-p1006w-data"
+};
+
static const struct dmi_system_id dmi_platform_data[] = {
{
/* Match for the GPDwin which unfortunately uses somewhat
@@ -81,6 +85,17 @@ static const struct dmi_system_id dmi_platform_data[] = {
},
.driver_data = (void *)&meegopad_t08_data,
},
+ {
+ /* Point of View TAB-P1006W-232 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ /* Note 105b is Foxcon's USB/PCI vendor id */
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
+ },
+ .driver_data = (void *)&pov_tab_p1006w_data,
+ },
{}
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 4c5a3995dc35..acca719b3907 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -103,6 +103,10 @@ static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = {
{ "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
/* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */
{ "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
+ /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 211de1679a68 */
+ { "01-801fb449", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
+ /* brcmfmac4366c-pcie.bin from linux-firmware.git commit 211de1679a68 */
+ { "01-d2cbb8fd", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
};
static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
@@ -181,13 +185,14 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
#define MAX_CAPS_BUFFER_SIZE 768
static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
char caps[MAX_CAPS_BUFFER_SIZE];
enum brcmf_feat_id id;
int i, err;
err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
if (err) {
- brcmf_err("could not get firmware cap (%d)\n", err);
+ bphy_err(drvr, "could not get firmware cap (%d)\n", err);
return;
}
@@ -212,14 +217,15 @@ static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data)
{
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
- struct brcmf_if *ifp = brcmf_get_ifp(bus_if->drvr, 0);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
char caps[MAX_CAPS_BUFFER_SIZE + 1] = { };
char *tmp;
int err;
err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
if (err) {
- brcmf_err("could not get firmware cap (%d)\n", err);
+ bphy_err(drvr, "could not get firmware cap (%d)\n", err);
return err;
}
@@ -268,9 +274,15 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
BIT(BRCMF_FEAT_WOWL_GTK);
}
}
- /* MBSS does not work for 43362 */
- if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
+ /* MBSS does not work for all chips */
+ switch (drvr->bus_if->chip) {
+ case BRCM_CC_4330_CHIP_ID:
+ case BRCM_CC_43362_CHIP_ID:
ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+ break;
+ default:
+ break;
+ }
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp");
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 0b4974df353a..5e88a7f16ad2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -35,6 +35,7 @@
* FWSUP: Firmware supplicant.
* MONITOR: firmware can pass monitor packets to host.
* MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
+ * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -52,7 +53,8 @@
BRCMF_FEAT_DEF(GSCAN) \
BRCMF_FEAT_DEF(FWSUP) \
BRCMF_FEAT_DEF(MONITOR) \
- BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
+ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
+ BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR)
/*
* Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 14b948917a1a..8209a42dea72 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -47,7 +47,7 @@ enum nvram_parser_state {
* @state: current parser state.
* @data: input buffer being parsed.
* @nvram: output buffer with parse result.
- * @nvram_len: lenght of parse result.
+ * @nvram_len: length of parse result.
* @line: current line.
* @column: current column in line.
* @pos: byte offset in input buffer.
@@ -719,8 +719,10 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,
break;
}
+ brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
+
if (i == table_size) {
- brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
+ brcmf_err("Unknown chip %s\n", chipname);
return NULL;
}
@@ -729,8 +731,6 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,
if (!fwreq)
return NULL;
- brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
-
brcmf_info("using %s for chip %s\n",
mapping_table[i].fw_base, chipname);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index e7eaa57d11d9..63e98fd583ab 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -102,7 +102,8 @@ static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
schedule_work(&fweh->event_work);
}
-static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
+static int brcmf_fweh_call_event_handler(struct brcmf_pub *drvr,
+ struct brcmf_if *ifp,
enum brcmf_fweh_event_code code,
struct brcmf_event_msg *emsg,
void *data)
@@ -117,9 +118,9 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
if (fweh->evt_handler[code])
err = fweh->evt_handler[code](ifp, emsg, data);
else
- brcmf_err("unhandled event %d ignored\n", code);
+ bphy_err(drvr, "unhandled event %d ignored\n", code);
} else {
- brcmf_err("no interface object\n");
+ bphy_err(drvr, "no interface object\n");
}
return err;
}
@@ -158,7 +159,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
return;
}
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
- brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
+ bphy_err(drvr, "invalid interface index: %u\n", ifevent->ifidx);
return;
}
@@ -181,7 +182,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
if (ifp && ifevent->action == BRCMF_E_IF_CHANGE)
brcmf_proto_reset_if(drvr, ifp);
- err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+ err = brcmf_fweh_call_event_handler(drvr, ifp, emsg->event_code, emsg,
+ data);
if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);
@@ -268,11 +270,11 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
ifp = drvr->iflist[0];
else
ifp = drvr->iflist[emsg.bsscfgidx];
- err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
- event->data);
+ err = brcmf_fweh_call_event_handler(drvr, ifp, event->code,
+ &emsg, event->data);
if (err) {
- brcmf_err("event handler failed (%d)\n",
- event->code);
+ bphy_err(drvr, "event handler failed (%d)\n",
+ event->code);
err = 0;
}
event_free:
@@ -339,7 +341,7 @@ int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
brcmf_fweh_handler_t handler)
{
if (drvr->fweh.evt_handler[code]) {
- brcmf_err("event code %d already registered\n", code);
+ bphy_err(drvr, "event code %d already registered\n", code);
return -ENOSPC;
}
drvr->fweh.evt_handler[code] = handler;
@@ -369,6 +371,7 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr,
*/
int brcmf_fweh_activate_events(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
int i, err;
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
@@ -388,7 +391,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
eventmask, BRCMF_EVENTING_MASK_LEN);
if (err)
- brcmf_err("Set event_msgs error (%d)\n", err);
+ bphy_err(drvr, "Set event_msgs error (%d)\n", err);
return err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index 816f80ea925b..7027243db17e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -211,7 +211,7 @@ enum brcmf_fweh_event_code {
*/
#define BRCM_OUI "\x00\x10\x18"
#define BCMILCP_BCM_SUBTYPE_EVENT 1
-
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
/**
* struct brcm_ethhdr - broadcom specific ether header.
@@ -266,7 +266,7 @@ struct brcmf_event {
* @status: status information.
* @reason: reason code.
* @auth_type: authentication type.
- * @datalen: lenght of event data buffer.
+ * @datalen: length of event data buffer.
* @addr: ether address.
* @ifname: interface name.
* @ifidx: interface index.
@@ -334,10 +334,10 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
- struct sk_buff *skb)
+ struct sk_buff *skb, u16 stype)
{
struct brcmf_event *event_packet;
- u16 usr_stype;
+ u16 subtype, usr_stype;
/* only process events when protocol matches */
if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
@@ -346,8 +346,16 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
return;
- /* check for BRCM oui match */
event_packet = (struct brcmf_event *)skb_mac_header(skb);
+
+ /* check subtype if needed */
+ if (unlikely(stype)) {
+ subtype = get_unaligned_be16(&event_packet->hdr.subtype);
+ if (subtype != stype)
+ return;
+ }
+
+ /* check for BRCM oui match */
if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0],
sizeof(event_packet->hdr.oui)))
return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
index 802d7cb73b80..8ea27489734e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -110,7 +110,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
s32 err, fwerr;
if (drvr->bus_if->state != BRCMF_BUS_UP) {
- brcmf_err("bus is down. we have nothing to do.\n");
+ bphy_err(drvr, "bus is down. we have nothing to do.\n");
return -EIO;
}
@@ -242,7 +242,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
buflen, true);
} else {
err = -EPERM;
- brcmf_err("Creating iovar failed\n");
+ bphy_err(drvr, "Creating iovar failed\n");
}
mutex_unlock(&drvr->proto_block);
@@ -268,7 +268,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
memcpy(data, drvr->proto_buf, len);
} else {
err = -EPERM;
- brcmf_err("Creating iovar failed\n");
+ bphy_err(drvr, "Creating iovar failed\n");
}
brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
@@ -366,7 +366,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
buflen, true);
} else {
err = -EPERM;
- brcmf_err("Creating bsscfg failed\n");
+ bphy_err(drvr, "Creating bsscfg failed\n");
}
mutex_unlock(&drvr->proto_block);
@@ -392,7 +392,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
memcpy(data, drvr->proto_buf, len);
} else {
err = -EPERM;
- brcmf_err("Creating bsscfg failed\n");
+ bphy_err(drvr, "Creating bsscfg failed\n");
}
brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bsscfgidx, name, len);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index 02759ebd207c..abeb305492e0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -1255,6 +1255,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws,
enum brcmf_fws_skb_state state, int fifo,
struct sk_buff *p)
{
+ struct brcmf_pub *drvr = fws->drvr;
int prec = 2 * fifo;
u32 *qfull_stat = &fws->stats.delayq_full_error;
struct brcmf_fws_mac_descriptor *entry;
@@ -1267,7 +1268,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws,
entry = brcmf_skbcb(p)->mac;
if (entry == NULL) {
- brcmf_err("no mac descriptor found for skb %p\n", p);
+ bphy_err(drvr, "no mac descriptor found for skb %p\n", p);
return -ENOENT;
}
@@ -1457,6 +1458,7 @@ static int
brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
u32 genbit, u16 seq, u8 compcnt)
{
+ struct brcmf_pub *drvr = fws->drvr;
u32 fifo;
u8 cnt = 0;
int ret;
@@ -1481,14 +1483,14 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
fws->stats.txs_host_tossed += compcnt;
else
- brcmf_err("unexpected txstatus\n");
+ bphy_err(drvr, "unexpected txstatus\n");
while (cnt < compcnt) {
ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
remove_from_hanger);
if (ret != 0) {
- brcmf_err("no packet in hanger slot: hslot=%d\n",
- hslot);
+ bphy_err(drvr, "no packet in hanger slot: hslot=%d\n",
+ hslot);
goto cont;
}
@@ -1612,12 +1614,13 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
const struct brcmf_event_msg *e,
void *data)
{
- struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fws_info *fws = drvr_to_fws(drvr);
int i;
u8 *credits = data;
if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
- brcmf_err("event payload too small (%d)\n", e->datalen);
+ bphy_err(drvr, "event payload too small (%d)\n", e->datalen);
return -EINVAL;
}
@@ -1681,6 +1684,7 @@ static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
{
+ struct brcmf_pub *drvr = ifp->drvr;
u8 *reorder_data;
u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
struct brcmf_ampdu_rx_reorder *rfi;
@@ -1695,7 +1699,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
/* validate flags and flow id */
if (flags == 0xFF) {
- brcmf_err("invalid flags...so ignore this packet\n");
+ bphy_err(drvr, "invalid flags...so ignore this packet\n");
brcmf_netif_rx(ifp, pkt);
return;
}
@@ -1732,7 +1736,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
flow_id, max_idx);
rfi = kzalloc(buf_size, GFP_ATOMIC);
if (rfi == NULL) {
- brcmf_err("failed to alloc buffer\n");
+ bphy_err(drvr, "failed to alloc buffer\n");
brcmf_netif_rx(ifp, pkt);
return;
}
@@ -1996,6 +2000,7 @@ static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
struct sk_buff *skb, int fifo)
{
+ struct brcmf_pub *drvr = fws->drvr;
struct brcmf_fws_mac_descriptor *entry;
struct sk_buff *pktout;
int qidx, hslot;
@@ -2009,11 +2014,11 @@ static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
if (pktout == NULL) {
- brcmf_err("%s queue %d full\n", entry->name, qidx);
+ bphy_err(drvr, "%s queue %d full\n", entry->name, qidx);
rc = -ENOSPC;
}
} else {
- brcmf_err("%s entry removed\n", entry->name);
+ bphy_err(drvr, "%s entry removed\n", entry->name);
rc = -ENOENT;
}
@@ -2118,7 +2123,8 @@ static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
{
- struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fws_info *fws = drvr_to_fws(drvr);
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
struct ethhdr *eh = (struct ethhdr *)(skb->data);
int fifo = BRCMF_FWS_FIFO_BCMC;
@@ -2146,7 +2152,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
brcmf_fws_schedule_deq(fws);
} else {
- brcmf_err("drop skb: no hanger slot\n");
+ bphy_err(drvr, "drop skb: no hanger slot\n");
brcmf_txfinalize(ifp, skb, false);
rc = -ENOMEM;
}
@@ -2365,7 +2371,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
if (fws->fws_wq == NULL) {
- brcmf_err("workqueue creation failed\n");
+ bphy_err(drvr, "workqueue creation failed\n");
rc = -EBADF;
goto fail;
}
@@ -2381,13 +2387,13 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
brcmf_fws_notify_credit_map);
if (rc < 0) {
- brcmf_err("register credit map handler failed\n");
+ bphy_err(drvr, "register credit map handler failed\n");
goto fail;
}
rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
brcmf_fws_notify_bcmc_credit_support);
if (rc < 0) {
- brcmf_err("register bcmc credit handler failed\n");
+ bphy_err(drvr, "register bcmc credit handler failed\n");
brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
goto fail;
}
@@ -2399,7 +2405,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
fws->fw_signals = true;
ifp = brcmf_get_ifp(drvr, 0);
if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
- brcmf_err("failed to set bdcv2 tlv signaling\n");
+ bphy_err(drvr, "failed to set bdcv2 tlv signaling\n");
fws->fcmode = BRCMF_FWS_FCMODE_NONE;
fws->fw_signals = false;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 4e8397a0cbc8..d3780eae7f19 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -134,6 +134,22 @@ struct msgbuf_completion_hdr {
__le16 flow_ring_id;
};
+/* Data struct for the MSGBUF_TYPE_GEN_STATUS */
+struct msgbuf_gen_status {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 write_idx;
+ __le32 rsvd0[3];
+};
+
+/* Data struct for the MSGBUF_TYPE_RING_STATUS */
+struct msgbuf_ring_status {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 write_idx;
+ __le16 rsvd0[5];
+};
+
struct msgbuf_rx_event {
struct msgbuf_common_hdr msg;
struct msgbuf_completion_hdr compl_hdr;
@@ -431,7 +447,7 @@ static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
brcmf_commonring_lock(commonring);
ret_ptr = brcmf_commonring_reserve_for_write(commonring);
if (!ret_ptr) {
- brcmf_err("Failed to reserve space in commonring\n");
+ bphy_err(drvr, "Failed to reserve space in commonring\n");
brcmf_commonring_unlock(commonring);
return -ENOMEM;
}
@@ -495,7 +511,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf);
if (!timeout) {
- brcmf_err("Timeout on response for query command\n");
+ bphy_err(drvr, "Timeout on response for query command\n");
return -EIO;
}
@@ -572,6 +588,7 @@ static u32
brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
struct brcmf_msgbuf_work_item *work)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_tx_flowring_create_req *create;
struct brcmf_commonring *commonring;
void *ret_ptr;
@@ -587,7 +604,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
&msgbuf->flowring_dma_handle[flowid],
GFP_KERNEL);
if (!dma_buf) {
- brcmf_err("dma_alloc_coherent failed\n");
+ bphy_err(drvr, "dma_alloc_coherent failed\n");
brcmf_flowring_delete(msgbuf->flow, flowid);
return BRCMF_FLOWRING_INVALID_ID;
}
@@ -600,7 +617,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
brcmf_commonring_lock(commonring);
ret_ptr = brcmf_commonring_reserve_for_write(commonring);
if (!ret_ptr) {
- brcmf_err("Failed to reserve space in commonring\n");
+ bphy_err(drvr, "Failed to reserve space in commonring\n");
brcmf_commonring_unlock(commonring);
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
return BRCMF_FLOWRING_INVALID_ID;
@@ -627,7 +644,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
err = brcmf_commonring_write_complete(commonring);
brcmf_commonring_unlock(commonring);
if (err) {
- brcmf_err("Failed to write commonring\n");
+ bphy_err(drvr, "Failed to write commonring\n");
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
return BRCMF_FLOWRING_INVALID_ID;
}
@@ -686,6 +703,7 @@ static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx,
static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
{
struct brcmf_flowring *flow = msgbuf->flow;
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct brcmf_commonring *commonring;
void *ret_ptr;
u32 count;
@@ -705,8 +723,8 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
while (brcmf_flowring_qlen(flow, flowid)) {
skb = brcmf_flowring_dequeue(flow, flowid);
if (skb == NULL) {
- brcmf_err("No SKB, but qlen %d\n",
- brcmf_flowring_qlen(flow, flowid));
+ bphy_err(drvr, "No SKB, but qlen %d\n",
+ brcmf_flowring_qlen(flow, flowid));
break;
}
skb_orphan(skb);
@@ -714,7 +732,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
msgbuf->tx_pktids, skb, ETH_HLEN,
&physaddr, &pktid)) {
brcmf_flowring_reinsert(flow, flowid, skb);
- brcmf_err("No PKTID available !!\n");
+ bphy_err(drvr, "No PKTID available !!\n");
break;
}
ret_ptr = brcmf_commonring_reserve_for_write(commonring);
@@ -885,6 +903,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct brcmf_commonring *commonring;
void *ret_ptr;
struct sk_buff *skb;
@@ -912,7 +931,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
if (skb == NULL) {
- brcmf_err("Failed to alloc SKB\n");
+ bphy_err(drvr, "Failed to alloc SKB\n");
brcmf_commonring_write_cancel(commonring, alloced - i);
break;
}
@@ -922,7 +941,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
msgbuf->rx_pktids, skb, 0,
&physaddr, &pktid)) {
dev_kfree_skb_any(skb);
- brcmf_err("No PKTID available !!\n");
+ bphy_err(drvr, "No PKTID available !!\n");
brcmf_commonring_write_cancel(commonring, alloced - i);
break;
}
@@ -992,6 +1011,7 @@ static u32
brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
u32 count)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct brcmf_commonring *commonring;
void *ret_ptr;
struct sk_buff *skb;
@@ -1009,7 +1029,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
count,
&alloced);
if (!ret_ptr) {
- brcmf_err("Failed to reserve space in commonring\n");
+ bphy_err(drvr, "Failed to reserve space in commonring\n");
brcmf_commonring_unlock(commonring);
return 0;
}
@@ -1021,7 +1041,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
if (skb == NULL) {
- brcmf_err("Failed to alloc SKB\n");
+ bphy_err(drvr, "Failed to alloc SKB\n");
brcmf_commonring_write_cancel(commonring, alloced - i);
break;
}
@@ -1031,7 +1051,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
msgbuf->rx_pktids, skb, 0,
&physaddr, &pktid)) {
dev_kfree_skb_any(skb);
- brcmf_err("No PKTID available !!\n");
+ bphy_err(drvr, "No PKTID available !!\n");
brcmf_commonring_write_cancel(commonring, alloced - i);
break;
}
@@ -1083,6 +1103,7 @@ static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf)
static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_rx_event *event;
u32 idx;
u16 buflen;
@@ -1109,14 +1130,14 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx);
if (!ifp || !ifp->ndev) {
- brcmf_err("Received pkt for invalid ifidx %d\n",
- event->msg.ifidx);
+ bphy_err(drvr, "Received pkt for invalid ifidx %d\n",
+ event->msg.ifidx);
goto exit;
}
skb->protocol = eth_type_trans(skb, ifp->ndev);
- brcmf_fweh_process_skb(ifp->drvr, skb);
+ brcmf_fweh_process_skb(ifp->drvr, skb, 0);
exit:
brcmu_pkt_buf_free_skb(skb);
@@ -1126,6 +1147,7 @@ exit:
static void
brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_rx_complete *rx_complete;
struct sk_buff *skb;
u16 data_offset;
@@ -1159,7 +1181,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
ifp = msgbuf->drvr->mon_if;
if (!ifp) {
- brcmf_err("Received unexpected monitor pkt\n");
+ bphy_err(drvr, "Received unexpected monitor pkt\n");
brcmu_pkt_buf_free_skb(skb);
return;
}
@@ -1170,8 +1192,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
if (!ifp || !ifp->ndev) {
- brcmf_err("Received pkt for invalid ifidx %d\n",
- rx_complete->msg.ifidx);
+ bphy_err(drvr, "Received pkt for invalid ifidx %d\n",
+ rx_complete->msg.ifidx);
brcmu_pkt_buf_free_skb(skb);
return;
}
@@ -1180,11 +1202,39 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
brcmf_netif_rx(ifp, skb);
}
+static void brcmf_msgbuf_process_gen_status(struct brcmf_msgbuf *msgbuf,
+ void *buf)
+{
+ struct msgbuf_gen_status *gen_status = buf;
+ struct brcmf_pub *drvr = msgbuf->drvr;
+ int err;
+
+ err = le16_to_cpu(gen_status->compl_hdr.status);
+ if (err)
+ bphy_err(drvr, "Firmware reported general error: %d\n", err);
+}
+
+static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf,
+ void *buf)
+{
+ struct msgbuf_ring_status *ring_status = buf;
+ struct brcmf_pub *drvr = msgbuf->drvr;
+ int err;
+
+ err = le16_to_cpu(ring_status->compl_hdr.status);
+ if (err) {
+ int ring = le16_to_cpu(ring_status->compl_hdr.flow_ring_id);
+
+ bphy_err(drvr, "Firmware reported ring %d error: %d\n", ring,
+ err);
+ }
+}
static void
brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
void *buf)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_flowring_create_resp *flowring_create_resp;
u16 status;
u16 flowid;
@@ -1196,7 +1246,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
status = le16_to_cpu(flowring_create_resp->compl_hdr.status);
if (status) {
- brcmf_err("Flowring creation failed, code %d\n", status);
+ bphy_err(drvr, "Flowring creation failed, code %d\n", status);
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
return;
}
@@ -1213,6 +1263,7 @@ static void
brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
void *buf)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_flowring_delete_resp *flowring_delete_resp;
u16 status;
u16 flowid;
@@ -1224,7 +1275,7 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
status = le16_to_cpu(flowring_delete_resp->compl_hdr.status);
if (status) {
- brcmf_err("Flowring deletion failed, code %d\n", status);
+ bphy_err(drvr, "Flowring deletion failed, code %d\n", status);
brcmf_flowring_delete(msgbuf->flow, flowid);
return;
}
@@ -1237,10 +1288,19 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
{
+ struct brcmf_pub *drvr = msgbuf->drvr;
struct msgbuf_common_hdr *msg;
msg = (struct msgbuf_common_hdr *)buf;
switch (msg->msgtype) {
+ case MSGBUF_TYPE_GEN_STATUS:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_GEN_STATUS\n");
+ brcmf_msgbuf_process_gen_status(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_RING_STATUS:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n");
+ brcmf_msgbuf_process_ring_status(msgbuf, buf);
+ break;
case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT\n");
brcmf_msgbuf_process_flow_ring_create_response(msgbuf, buf);
@@ -1269,7 +1329,7 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
brcmf_msgbuf_process_rx_complete(msgbuf, buf);
break;
default:
- brcmf_err("Unsupported msgtype %d\n", msg->msgtype);
+ bphy_err(drvr, "Unsupported msgtype %d\n", msg->msgtype);
break;
}
}
@@ -1352,7 +1412,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
brcmf_commonring_lock(commonring);
ret_ptr = brcmf_commonring_reserve_for_write(commonring);
if (!ret_ptr) {
- brcmf_err("FW unaware, flowring will be removed !!\n");
+ bphy_err(drvr, "FW unaware, flowring will be removed !!\n");
brcmf_commonring_unlock(commonring);
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
return;
@@ -1376,7 +1436,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
err = brcmf_commonring_write_complete(commonring);
brcmf_commonring_unlock(commonring);
if (err) {
- brcmf_err("Failed to submit RING_DELETE, flowring will be removed\n");
+ bphy_err(drvr, "Failed to submit RING_DELETE, flowring will be removed\n");
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
}
}
@@ -1451,8 +1511,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
if_msgbuf = drvr->bus_if->msgbuf;
if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
- brcmf_err("driver not configured for this many flowrings %d\n",
- if_msgbuf->max_flowrings);
+ bphy_err(drvr, "driver not configured for this many flowrings %d\n",
+ if_msgbuf->max_flowrings);
if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
}
@@ -1462,7 +1522,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
msgbuf->txflow_wq = create_singlethread_workqueue("msgbuf_txflow");
if (msgbuf->txflow_wq == NULL) {
- brcmf_err("workqueue creation failed\n");
+ bphy_err(drvr, "workqueue creation failed\n");
goto fail;
}
INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 456a1bf008b3..73a0e550f2b2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -434,6 +434,7 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
*/
static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
{
+ struct brcmf_pub *drvr = ifp->drvr;
s32 ret = 0;
brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
@@ -450,7 +451,7 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac,
ETH_ALEN);
if (ret)
- brcmf_err("failed to update device address ret %d\n", ret);
+ bphy_err(drvr, "failed to update device address ret %d\n", ret);
return ret;
}
@@ -570,13 +571,14 @@ static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
*/
static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
struct brcmf_cfg80211_vif *vif;
s32 ret = 0;
brcmf_dbg(TRACE, "enter\n");
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
if (!vif) {
- brcmf_err("P2P config device not available\n");
+ bphy_err(drvr, "P2P config device not available\n");
ret = -EPERM;
goto exit;
}
@@ -590,13 +592,13 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1);
if (ret < 0) {
- brcmf_err("set p2p_disc error\n");
+ bphy_err(drvr, "set p2p_disc error\n");
goto exit;
}
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
if (ret < 0) {
- brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n");
+ bphy_err(drvr, "unable to set WL_P2P_DISC_ST_SCAN\n");
goto exit;
}
@@ -608,7 +610,7 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
*/
ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED);
if (ret < 0) {
- brcmf_err("wsec error %d\n", ret);
+ bphy_err(drvr, "wsec error %d\n", ret);
goto exit;
}
@@ -630,6 +632,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
u16 chanspecs[], s32 search_state,
enum p2p_bss_type bss_type)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
s32 ret = 0;
s32 memsize = offsetof(struct brcmf_p2p_scan_le,
eparams.params_le.channel_list);
@@ -648,7 +651,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
vif = p2p->bss_idx[bss_type].vif;
if (vif == NULL) {
- brcmf_err("no vif for bss type %d\n", bss_type);
+ bphy_err(drvr, "no vif for bss type %d\n", bss_type);
ret = -EINVAL;
goto exit;
}
@@ -676,7 +679,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
BRCMF_P2P_WILDCARD_SSID_LEN);
break;
default:
- brcmf_err(" invalid search state %d\n", search_state);
+ bphy_err(drvr, " invalid search state %d\n", search_state);
ret = -EINVAL;
goto exit;
}
@@ -760,6 +763,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
struct cfg80211_scan_request *request)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
+ struct brcmf_pub *drvr = cfg->pub;
s32 err = 0;
s32 search_state = WL_P2P_DISC_ST_SCAN;
struct brcmf_cfg80211_vif *vif;
@@ -822,7 +826,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
}
exit:
if (err)
- brcmf_err("error (%d)\n", err);
+ bphy_err(drvr, "error (%d)\n", err);
return err;
}
@@ -917,19 +921,20 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
static s32
brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
struct brcmf_cfg80211_vif *vif;
struct brcmu_chan ch;
s32 err = 0;
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
if (!vif) {
- brcmf_err("Discovery is not set, so we have nothing to do\n");
+ bphy_err(drvr, "Discovery is not set, so we have nothing to do\n");
err = -EPERM;
goto exit;
}
if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) {
- brcmf_err("Previous LISTEN is not completed yet\n");
+ bphy_err(drvr, "Previous LISTEN is not completed yet\n");
/* WAR: prevent cookie mismatch in wpa_supplicant return OK */
goto exit;
}
@@ -1046,6 +1051,7 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp)
*/
static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
s32 err;
u32 channel_cnt;
u16 *default_chan_list;
@@ -1061,7 +1067,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
default_chan_list = kcalloc(channel_cnt, sizeof(*default_chan_list),
GFP_KERNEL);
if (default_chan_list == NULL) {
- brcmf_err("channel list allocation failed\n");
+ bphy_err(drvr, "channel list allocation failed\n");
err = -ENOMEM;
goto exit;
}
@@ -1103,6 +1109,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work)
struct brcmf_p2p_info *p2p = container_of(afx_hdl,
struct brcmf_p2p_info,
afx_hdl);
+ struct brcmf_pub *drvr = p2p->cfg->pub;
s32 err;
if (!afx_hdl->is_active)
@@ -1116,7 +1123,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work)
err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan);
if (err) {
- brcmf_err("ERROR occurred! value is (%d)\n", err);
+ bphy_err(drvr, "ERROR occurred! value is (%d)\n", err);
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
&p2p->status))
complete(&afx_hdl->act_frm_scan);
@@ -1338,7 +1345,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
const struct brcmf_event_msg *e,
void *data)
{
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_cfg80211_info *cfg = drvr->config;
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct wireless_dev *wdev;
@@ -1409,7 +1417,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
mgmt_frame = kzalloc(offsetof(struct ieee80211_mgmt, u) +
mgmt_frame_len, GFP_KERNEL);
if (!mgmt_frame) {
- brcmf_err("No memory available for action frame\n");
+ bphy_err(drvr, "No memory available for action frame\n");
return -ENOMEM;
}
memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
@@ -1492,6 +1500,7 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
struct brcmf_fil_af_params_le *af_params)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
s32 timeout = 0;
@@ -1506,7 +1515,7 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params,
sizeof(*af_params));
if (err) {
- brcmf_err(" sending action frame has failed\n");
+ bphy_err(drvr, " sending action frame has failed\n");
goto exit;
}
@@ -1556,6 +1565,7 @@ static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg,
struct brcmf_config_af_params *config_af_params)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_fil_action_frame_le *action_frame;
struct brcmf_p2p_pub_act_frame *act_frm;
s32 err = 0;
@@ -1634,8 +1644,8 @@ static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg,
config_af_params->extra_listen = false;
break;
default:
- brcmf_err("Unknown p2p pub act frame subtype: %d\n",
- act_frm->subtype);
+ bphy_err(drvr, "Unknown p2p pub act frame subtype: %d\n",
+ act_frm->subtype);
err = -EINVAL;
}
return err;
@@ -1657,6 +1667,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
struct brcmf_fil_action_frame_le *action_frame;
struct brcmf_config_af_params config_af_params;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+ struct brcmf_pub *drvr = cfg->pub;
u16 action_frame_len;
bool ack = false;
u8 category;
@@ -1692,7 +1703,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
if (brcmf_p2p_pub_af_tx(cfg, af_params, &config_af_params)) {
/* Just send unknown subtype frame with */
/* default parameters. */
- brcmf_err("P2P Public action frame, unknown subtype.\n");
+ bphy_err(drvr, "P2P Public action frame, unknown subtype.\n");
}
} else if (brcmf_p2p_is_gas_action(action_frame->data,
action_frame_len)) {
@@ -1714,7 +1725,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
af_params->dwell_time =
cpu_to_le32(P2P_AF_MIN_DWELL_TIME);
} else {
- brcmf_err("Unknown action type: %d\n", action);
+ bphy_err(drvr, "Unknown action type: %d\n", action);
goto exit;
}
} else if (brcmf_p2p_is_p2p_action(action_frame->data,
@@ -1722,8 +1733,8 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
/* do not configure anything. it will be */
/* sent with a default configuration */
} else {
- brcmf_err("Unknown Frame: category 0x%x, action 0x%x\n",
- category, action);
+ bphy_err(drvr, "Unknown Frame: category 0x%x, action 0x%x\n",
+ category, action);
return false;
}
@@ -1761,7 +1772,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
if (brcmf_p2p_af_searching_channel(p2p) ==
P2P_INVALID_CHANNEL) {
- brcmf_err("Couldn't find peer's channel.\n");
+ bphy_err(drvr, "Couldn't find peer's channel.\n");
goto exit;
}
@@ -1783,7 +1794,8 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
tx_retry++;
}
if (ack == false) {
- brcmf_err("Failed to send Action Frame(retry %d)\n", tx_retry);
+ bphy_err(drvr, "Failed to send Action Frame(retry %d)\n",
+ tx_retry);
clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
}
@@ -1965,6 +1977,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
enum brcmf_fil_p2p_if_types if_type)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_vif *vif;
struct brcmf_fil_p2p_if_le if_request;
s32 err;
@@ -1974,13 +1987,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
if (!vif) {
- brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
+ bphy_err(drvr, "vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
return -EPERM;
}
brcmf_notify_escan_complete(cfg, vif->ifp, true, true);
vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
if (!vif) {
- brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
+ bphy_err(drvr, "vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
return -EPERM;
}
brcmf_set_mpc(vif->ifp, 0);
@@ -1998,7 +2011,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_iovar_data_set(vif->ifp, "p2p_ifupd", &if_request,
sizeof(if_request));
if (err) {
- brcmf_err("p2p_ifupd FAILED, err=%d\n", err);
+ bphy_err(drvr, "p2p_ifupd FAILED, err=%d\n", err);
brcmf_cfg80211_arm_vif_event(cfg, NULL);
return err;
}
@@ -2006,7 +2019,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
BRCMF_VIF_EVENT_TIMEOUT);
brcmf_cfg80211_arm_vif_event(cfg, NULL);
if (!err) {
- brcmf_err("No BRCMF_E_IF_CHANGE event received\n");
+ bphy_err(drvr, "No BRCMF_E_IF_CHANGE event received\n");
return -EIO;
}
@@ -2069,6 +2082,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
struct wiphy *wiphy,
u8 *addr)
{
+ struct brcmf_pub *drvr = p2p->cfg->pub;
struct brcmf_cfg80211_vif *p2p_vif;
struct brcmf_if *p2p_ifp;
struct brcmf_if *pri_ifp;
@@ -2080,7 +2094,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE);
if (IS_ERR(p2p_vif)) {
- brcmf_err("could not create discovery vif\n");
+ bphy_err(drvr, "could not create discovery vif\n");
return (struct wireless_dev *)p2p_vif;
}
@@ -2088,7 +2102,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
/* firmware requires unique mac address for p2pdev interface */
if (addr && ether_addr_equal(addr, pri_ifp->mac_addr)) {
- brcmf_err("discovery vif must be different from primary interface\n");
+ bphy_err(drvr, "discovery vif must be different from primary interface\n");
return ERR_PTR(-EINVAL);
}
@@ -2101,7 +2115,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
/* Initialize P2P Discovery in the firmware */
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
if (err < 0) {
- brcmf_err("set p2p_disc error\n");
+ bphy_err(drvr, "set p2p_disc error\n");
brcmf_fweh_p2pdev_setup(pri_ifp, false);
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
goto fail;
@@ -2113,7 +2127,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
brcmf_fweh_p2pdev_setup(pri_ifp, false);
if (!err) {
- brcmf_err("timeout occurred\n");
+ bphy_err(drvr, "timeout occurred\n");
err = -EIO;
goto fail;
}
@@ -2127,7 +2141,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
/* verify bsscfg index for P2P discovery */
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bsscfgidx);
if (err < 0) {
- brcmf_err("retrieving discover bsscfg index failed\n");
+ bphy_err(drvr, "retrieving discover bsscfg index failed\n");
goto fail;
}
@@ -2161,6 +2175,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_cfg80211_vif *vif;
enum brcmf_fil_p2p_if_types iftype;
int err;
@@ -2201,7 +2216,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
BRCMF_VIF_EVENT_TIMEOUT);
brcmf_cfg80211_arm_vif_event(cfg, NULL);
if (!err) {
- brcmf_err("timeout occurred\n");
+ bphy_err(drvr, "timeout occurred\n");
err = -EIO;
goto fail;
}
@@ -2209,7 +2224,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
/* interface created in firmware */
ifp = vif->ifp;
if (!ifp) {
- brcmf_err("no if pointer provided\n");
+ bphy_err(drvr, "no if pointer provided\n");
err = -ENOENT;
goto fail;
}
@@ -2218,7 +2233,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
ifp->ndev->name_assign_type = name_assign_type;
err = brcmf_net_attach(ifp, true);
if (err) {
- brcmf_err("Registering netdevice failed\n");
+ bphy_err(drvr, "Registering netdevice failed\n");
free_netdev(ifp->ndev);
goto fail;
}
@@ -2373,6 +2388,7 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
*/
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
{
+ struct brcmf_pub *drvr = cfg->pub;
struct brcmf_p2p_info *p2p;
struct brcmf_if *pri_ifp;
s32 err = 0;
@@ -2387,7 +2403,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
if (p2pdev_forced) {
err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL);
if (IS_ERR(err_ptr)) {
- brcmf_err("P2P device creation failed.\n");
+ bphy_err(drvr, "P2P device creation failed.\n");
err = PTR_ERR(err_ptr);
}
} else {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 16d7dda965d8..58a6bc379358 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -30,6 +30,15 @@
#include <brcmu_wifi.h>
#include <brcm_hw_ids.h>
+/* Custom brcmf_err() that takes bus arg and passes it further */
+#define brcmf_err(bus, fmt, ...) \
+ do { \
+ if (IS_ENABLED(CONFIG_BRCMDBG) || \
+ IS_ENABLED(CONFIG_BRCM_TRACING) || \
+ net_ratelimit()) \
+ __brcmf_err(bus, __func__, fmt, ##__VA_ARGS__); \
+ } while (0)
+
#include "debug.h"
#include "bus.h"
#include "commonring.h"
@@ -531,6 +540,7 @@ static void
brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
{
const struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
struct brcmf_core *core;
u32 bar0_win;
@@ -548,7 +558,7 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
}
}
} else {
- brcmf_err("Unsupported core selected %x\n", coreid);
+ brcmf_err(bus, "Unsupported core selected %x\n", coreid);
}
}
@@ -848,9 +858,8 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
{
- struct pci_dev *pdev;
-
- pdev = devinfo->pdev;
+ struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
brcmf_pcie_intr_disable(devinfo);
@@ -861,7 +870,7 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
brcmf_pcie_isr_thread, IRQF_SHARED,
"brcmf_pcie_intr", devinfo)) {
pci_disable_msi(pdev);
- brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+ brcmf_err(bus, "Failed to request IRQ %d\n", pdev->irq);
return -EIO;
}
devinfo->irq_allocated = true;
@@ -871,15 +880,14 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
{
- struct pci_dev *pdev;
+ struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
u32 status;
u32 count;
if (!devinfo->irq_allocated)
return;
- pdev = devinfo->pdev;
-
brcmf_pcie_intr_disable(devinfo);
free_irq(pdev->irq, devinfo);
pci_disable_msi(pdev);
@@ -891,7 +899,7 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
count++;
}
if (devinfo->in_irq)
- brcmf_err("Still in IRQ (processing) !!!\n");
+ brcmf_err(bus, "Still in IRQ (processing) !!!\n");
status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
@@ -1102,6 +1110,7 @@ static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
{
+ struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
struct brcmf_pcie_ringbuf *ring;
struct brcmf_pcie_ringbuf *rings;
u32 d2h_w_idx_ptr;
@@ -1254,7 +1263,7 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
return 0;
fail:
- brcmf_err("Allocating ring buffers failed\n");
+ brcmf_err(bus, "Allocating ring buffers failed\n");
brcmf_pcie_release_ringbuffers(devinfo);
return -ENOMEM;
}
@@ -1277,14 +1286,15 @@ brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
{
+ struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
u64 address;
u32 addr;
devinfo->shared.scratch =
- dma_zalloc_coherent(&devinfo->pdev->dev,
- BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
- &devinfo->shared.scratch_dmahandle,
- GFP_KERNEL);
+ dma_alloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+ &devinfo->shared.scratch_dmahandle,
+ GFP_KERNEL);
if (!devinfo->shared.scratch)
goto fail;
@@ -1298,10 +1308,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
devinfo->shared.ringupd =
- dma_zalloc_coherent(&devinfo->pdev->dev,
- BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
- &devinfo->shared.ringupd_dmahandle,
- GFP_KERNEL);
+ dma_alloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+ &devinfo->shared.ringupd_dmahandle,
+ GFP_KERNEL);
if (!devinfo->shared.ringupd)
goto fail;
@@ -1316,7 +1326,7 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
return 0;
fail:
- brcmf_err("Allocating scratch buffers failed\n");
+ brcmf_err(bus, "Allocating scratch buffers failed\n");
brcmf_pcie_release_scratchbuffers(devinfo);
return -ENOMEM;
}
@@ -1437,6 +1447,7 @@ static int
brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
u32 sharedram_addr)
{
+ struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
struct brcmf_pcie_shared_info *shared;
u32 addr;
@@ -1448,7 +1459,8 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);
if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
(shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
- brcmf_err("Unsupported PCIE version %d\n", shared->version);
+ brcmf_err(bus, "Unsupported PCIE version %d\n",
+ shared->version);
return -EINVAL;
}
@@ -1490,6 +1502,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
const struct firmware *fw, void *nvram,
u32 nvram_len)
{
+ struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
u32 sharedram_addr;
u32 sharedram_addr_written;
u32 loop_counter;
@@ -1544,7 +1557,13 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
loop_counter--;
}
if (sharedram_addr == sharedram_addr_written) {
- brcmf_err("FW failed to initialize\n");
+ brcmf_err(bus, "FW failed to initialize\n");
+ return -ENODEV;
+ }
+ if (sharedram_addr < devinfo->ci->rambase ||
+ sharedram_addr >= devinfo->ci->rambase + devinfo->ci->ramsize) {
+ brcmf_err(bus, "Invalid shared RAM address 0x%08x\n",
+ sharedram_addr);
return -ENODEV;
}
brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);
@@ -1555,16 +1574,15 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
{
- struct pci_dev *pdev;
+ struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
int err;
phys_addr_t bar0_addr, bar1_addr;
ulong bar1_size;
- pdev = devinfo->pdev;
-
err = pci_enable_device(pdev);
if (err) {
- brcmf_err("pci_enable_device failed err=%d\n", err);
+ brcmf_err(bus, "pci_enable_device failed err=%d\n", err);
return err;
}
@@ -1577,7 +1595,7 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
/* read Bar-1 mapped memory range */
bar1_size = pci_resource_len(pdev, 2);
if ((bar1_size == 0) || (bar1_addr == 0)) {
- brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
+ brcmf_err(bus, "BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
bar1_size, (unsigned long long)bar1_addr);
return -EINVAL;
}
@@ -1586,7 +1604,7 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size);
if (!devinfo->regs || !devinfo->tcm) {
- brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
+ brcmf_err(bus, "ioremap() failed (%p,%p)\n", devinfo->regs,
devinfo->tcm);
return -EINVAL;
}
@@ -1873,7 +1891,7 @@ fail_bus:
kfree(bus->msgbuf);
kfree(bus);
fail:
- brcmf_err("failed %x:%x\n", pdev->vendor, pdev->device);
+ brcmf_err(NULL, "failed %x:%x\n", pdev->vendor, pdev->device);
brcmf_pcie_release_resource(devinfo);
if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
@@ -1947,7 +1965,7 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev)
wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,
BRCMF_PCIE_MBDATA_TIMEOUT);
if (!devinfo->mbdata_completed) {
- brcmf_err("Timeout on response for entering D3 substate\n");
+ brcmf_err(bus, "Timeout on response for entering D3 substate\n");
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
return -EIO;
}
@@ -1993,7 +2011,7 @@ cleanup:
err = brcmf_pcie_probe(pdev, NULL);
if (err)
- brcmf_err("probe after resume failed, err=%d\n", err);
+ brcmf_err(bus, "probe after resume failed, err=%d\n", err);
return err;
}
@@ -2064,7 +2082,8 @@ void brcmf_pcie_register(void)
brcmf_dbg(PCIE, "Enter\n");
err = pci_register_driver(&brcmf_pciedrvr);
if (err)
- brcmf_err("PCIE driver registration failed, err=%d\n", err);
+ brcmf_err(NULL, "PCIE driver registration failed, err=%d\n",
+ err);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
index ffa243e2e2d0..0fb97f7dd5a2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -109,6 +109,7 @@ static int brcmf_pno_channel_config(struct brcmf_if *ifp,
static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
u32 mscan, u32 bestn)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_pno_param_le pfn_param;
u16 flags;
u32 pfnmem;
@@ -132,13 +133,13 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
/* set bestn in firmware */
err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem);
if (err < 0) {
- brcmf_err("failed to set pfnmem\n");
+ bphy_err(drvr, "failed to set pfnmem\n");
goto exit;
}
/* get max mscan which the firmware supports */
err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem);
if (err < 0) {
- brcmf_err("failed to get pfnmem\n");
+ bphy_err(drvr, "failed to get pfnmem\n");
goto exit;
}
mscan = min_t(u32, mscan, pfnmem);
@@ -152,7 +153,7 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
sizeof(pfn_param));
if (err)
- brcmf_err("pfn_set failed, err=%d\n", err);
+ bphy_err(drvr, "pfn_set failed, err=%d\n", err);
exit:
return err;
@@ -160,6 +161,7 @@ exit:
static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_pno_macaddr_le pfn_mac;
u8 *mac_addr = NULL;
u8 *mac_mask = NULL;
@@ -194,7 +196,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
sizeof(pfn_mac));
if (err)
- brcmf_err("pfn_macaddr failed, err=%d\n", err);
+ bphy_err(drvr, "pfn_macaddr failed, err=%d\n", err);
return err;
}
@@ -202,6 +204,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
bool active)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_pno_net_param_le pfn;
int err;
@@ -218,12 +221,13 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active);
err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
if (err < 0)
- brcmf_err("adding failed: err=%d\n", err);
+ bphy_err(drvr, "adding failed: err=%d\n", err);
return err;
}
static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_pno_bssid_le bssid_cfg;
int err;
@@ -234,7 +238,7 @@ static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg,
sizeof(bssid_cfg));
if (err < 0)
- brcmf_err("adding failed: err=%d\n", err);
+ bphy_err(drvr, "adding failed: err=%d\n", err);
return err;
}
@@ -258,6 +262,7 @@ static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
static int brcmf_pno_clean(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
int ret;
/* Disable pfn */
@@ -267,7 +272,7 @@ static int brcmf_pno_clean(struct brcmf_if *ifp)
ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
}
if (ret < 0)
- brcmf_err("failed code %d\n", ret);
+ bphy_err(drvr, "failed code %d\n", ret);
return ret;
}
@@ -392,6 +397,7 @@ static int brcmf_pno_config_networks(struct brcmf_if *ifp,
static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
{
+ struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_pno_info *pi;
struct brcmf_gscan_config *gscan_cfg;
struct brcmf_gscan_bucket_config *buckets;
@@ -416,7 +422,7 @@ static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
/* clean up everything */
err = brcmf_pno_clean(ifp);
if (err < 0) {
- brcmf_err("failed error=%d\n", err);
+ bphy_err(drvr, "failed error=%d\n", err);
goto free_gscan;
}
@@ -496,6 +502,11 @@ int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
pi = ifp_to_pno(ifp);
+
+ /* No PNO request */
+ if (!pi->n_reqs)
+ return 0;
+
err = brcmf_pno_remove_request(pi, reqid);
if (err)
return err;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
index c5ff551ec659..024c643052bc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
@@ -47,8 +47,8 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
if (brcmf_proto_msgbuf_attach(drvr))
goto fail;
} else {
- brcmf_err("Unsupported proto type %d\n",
- drvr->bus_if->proto_type);
+ bphy_err(drvr, "Unsupported proto type %d\n",
+ drvr->bus_if->proto_type);
goto fail;
}
if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
@@ -56,7 +56,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
(proto->configure_addr_mode == NULL) ||
(proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) ||
(proto->debugfs_create == NULL)) {
- brcmf_err("Not all proto handlers have been installed\n");
+ bphy_err(drvr, "Not all proto handlers have been installed\n");
goto fail;
}
return 0;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 0cd5b8d970d7..4d104ab80fd8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -2999,21 +2999,35 @@ static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
if (error < 0)
return error;
- seq_printf(seq,
- "dongle trap info: type 0x%x @ epc 0x%08x\n"
- " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
- " lr 0x%08x pc 0x%08x offset 0x%x\n"
- " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
- " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
- le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
- le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
- le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
- le32_to_cpu(tr.pc), sh->trap_addr,
- le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
- le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
- le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
- le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
-
+ if (seq)
+ seq_printf(seq,
+ "dongle trap info: type 0x%x @ epc 0x%08x\n"
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+ le32_to_cpu(tr.pc), sh->trap_addr,
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+ else
+ pr_debug("dongle trap info: type 0x%x @ epc 0x%08x\n"
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+ le32_to_cpu(tr.pc), sh->trap_addr,
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
return 0;
}
@@ -3067,8 +3081,10 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
else if (sh.flags & SDPCM_SHARED_ASSERT)
brcmf_err("assertion in dongle\n");
- if (sh.flags & SDPCM_SHARED_TRAP)
+ if (sh.flags & SDPCM_SHARED_TRAP) {
brcmf_err("firmware trap in dongle\n");
+ brcmf_sdio_trap_info(NULL, bus, &sh);
+ }
return 0;
}
@@ -3143,9 +3159,12 @@ static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
return 0;
}
-static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+static void brcmf_sdio_debugfs_create(struct device *dev)
{
- struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiodev->bus;
struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);
if (IS_ERR_OR_NULL(dentry))
@@ -3165,7 +3184,7 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
return 0;
}
-static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+static void brcmf_sdio_debugfs_create(struct device *dev)
{
}
#endif /* DEBUG */
@@ -3477,8 +3496,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
if (bus->rxbuf)
bus->rxblen = value;
- brcmf_sdio_debugfs_create(bus);
-
/* the commands below use the terms tx and rx from
* a device perspective, ie. bus:txglom affects the
* bus transfers from device to host.
@@ -4088,6 +4105,7 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
.get_fwname = brcmf_sdio_get_fwname,
+ .debugfs_create = brcmf_sdio_debugfs_create
};
#define BRCMF_SDIO_FW_CODE 0
@@ -4197,7 +4215,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
} else {
/* Disable F2 again */
sdio_disable_func(sdiod->func2);
- goto release;
+ goto checkdied;
}
if (brcmf_chip_sr_capable(bus->ci)) {
@@ -4218,8 +4236,10 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
}
/* If we didn't come up, turn off backplane clock */
- if (err != 0)
+ if (err != 0) {
brcmf_sdio_clkctl(bus, CLK_NONE, false);
+ goto checkdied;
+ }
sdio_release_host(sdiod->func1);
@@ -4233,12 +4253,15 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
err = brcmf_attach(sdiod->dev, sdiod->settings);
if (err != 0) {
brcmf_err("brcmf_attach failed\n");
- goto fail;
+ sdio_claim_host(sdiod->func1);
+ goto checkdied;
}
/* ready */
return;
+checkdied:
+ brcmf_sdio_checkdied(bus);
release:
sdio_release_host(sdiod->func1);
fail:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
index fe6755944b7b..a5c271bff446 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
@@ -14,14 +14,16 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/device.h>
#include <linux/module.h> /* bug in tracepoint.h, it should include this */
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
+#include "bus.h"
#include "tracepoint.h"
#include "debug.h"
-void __brcmf_err(const char *func, const char *fmt, ...)
+void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
@@ -30,7 +32,10 @@ void __brcmf_err(const char *func, const char *fmt, ...)
va_start(args, fmt);
vaf.va = &args;
- pr_err("%s: %pV", func, &vaf);
+ if (bus)
+ dev_err(bus->dev, "%s: %pV", func, &vaf);
+ else
+ pr_err("%s: %pV", func, &vaf);
trace_brcmf_err(func, &vaf);
va_end(args);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index a4308c6e72d7..e9cbfd077710 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -508,7 +508,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
skb = req->skb;
req->skb = NULL;
- /* zero lenght packets indicate usb "failure". Do not refill */
+ /* zero length packets indicate usb "failure". Do not refill */
if (urb->status != 0 || !urb->actual_length) {
brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
@@ -575,7 +575,6 @@ static void
brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
{
struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
- int old_state;
brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n",
devinfo->bus_pub.state, state);
@@ -583,7 +582,6 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
if (devinfo->bus_pub.state == state)
return;
- old_state = devinfo->bus_pub.state;
devinfo->bus_pub.state = state;
/* update state of upper layer */
@@ -1550,6 +1548,10 @@ void brcmf_usb_exit(void)
void brcmf_usb_register(void)
{
+ int ret;
+
brcmf_dbg(USB, "Enter\n");
- usb_register(&brcmf_usbdrvr);
+ ret = usb_register(&brcmf_usbdrvr);
+ if (ret)
+ brcmf_err("usb_register failed %d\n", ret);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
index ed83f33aceb7..482d7737764d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
@@ -16,9 +16,9 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y := \
- -Idrivers/net/wireless/broadcom/brcm80211/brcmsmac \
- -Idrivers/net/wireless/broadcom/brcm80211/brcmsmac/phy \
- -Idrivers/net/wireless/broadcom/brcm80211/include
+ -I $(srctree)/$(src) \
+ -I $(srctree)/$(src)/phy \
+ -I $(srctree)/$(src)/../include
brcmsmac-y := \
mac80211_if.o \
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
index 3bd54f125776..6d776ef6ff54 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
@@ -37,27 +37,18 @@ static struct dentry *root_folder;
void brcms_debugfs_init(void)
{
root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (IS_ERR(root_folder))
- root_folder = NULL;
}
void brcms_debugfs_exit(void)
{
- if (!root_folder)
- return;
-
debugfs_remove_recursive(root_folder);
root_folder = NULL;
}
-int brcms_debugfs_attach(struct brcms_pub *drvr)
+void brcms_debugfs_attach(struct brcms_pub *drvr)
{
- if (!root_folder)
- return -ENODEV;
-
drvr->dbgfs_dir = debugfs_create_dir(
dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
- return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
}
void brcms_debugfs_detach(struct brcms_pub *drvr)
@@ -195,7 +186,7 @@ static const struct file_operations brcms_debugfs_def_ops = {
.llseek = seq_lseek
};
-static int
+static void
brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data))
{
@@ -203,27 +194,18 @@ brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
struct dentry *dentry = drvr->dbgfs_dir;
struct brcms_debugfs_entry *entry;
- if (IS_ERR_OR_NULL(dentry))
- return -ENOENT;
-
entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
if (!entry)
- return -ENOMEM;
+ return;
entry->read = read_fn;
entry->drvr = drvr;
- dentry = debugfs_create_file(fn, 0444, dentry, entry,
- &brcms_debugfs_def_ops);
-
- return PTR_ERR_OR_ZERO(dentry);
+ debugfs_create_file(fn, 0444, dentry, entry, &brcms_debugfs_def_ops);
}
void brcms_debugfs_create_files(struct brcms_pub *drvr)
{
- if (IS_ERR_OR_NULL(drvr->dbgfs_dir))
- return;
-
brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read);
brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
index 822781cf15d4..56898e6d789d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
@@ -68,7 +68,7 @@ void __brcms_dbg(struct device *dev, u32 level, const char *func,
struct brcms_pub;
void brcms_debugfs_init(void);
void brcms_debugfs_exit(void);
-int brcms_debugfs_attach(struct brcms_pub *drvr);
+void brcms_debugfs_attach(struct brcms_pub *drvr);
void brcms_debugfs_detach(struct brcms_pub *drvr);
struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr);
void brcms_debugfs_create_files(struct brcms_pub *drvr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
index e78a93a45741..c6e107f41948 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1199,8 +1199,6 @@ wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
{
int wait_count = 0;
bool result = true;
- u8 phybw40;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
@@ -3082,7 +3080,7 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
u8 bbmult;
struct phytbl_info tab;
s32 a1, b0, b1;
- s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+ s32 tssi, pwr, mintargetpwr;
bool suspend;
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
@@ -3119,7 +3117,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
b0 = pi->txpa_2g[0];
b1 = pi->txpa_2g[1];
a1 = pi->txpa_2g[2];
- maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
@@ -4212,7 +4209,7 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
s8 index;
struct phytbl_info tab;
s32 a1, b0, b1;
- s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+ s32 tssi, pwr, mintargetpwr;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
pi->phy_lastcal = pi->sh->now;
@@ -4249,7 +4246,6 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
b0 = pi->txpa_2g[0];
b1 = pi->txpa_2g[1];
a1 = pi->txpa_2g[2];
- maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
@@ -4622,13 +4618,10 @@ static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
{
uint idx;
- u8 phybw40;
struct phytbl_info tab;
const struct phytbl_info *tb;
u32 val;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
@@ -4831,9 +4824,7 @@ static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
void wlc_phy_init_lcnphy(struct brcms_phy *pi)
{
- u8 phybw40;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
pi_lcn->lcnphy_cal_counter = 0;
pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile
index 256c91f9ac4b..bb02c6220a88 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile
@@ -15,9 +15,7 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-ccflags-y := \
- -Idrivers/net/wireless/broadcom/brcm80211/brcmutil \
- -Idrivers/net/wireless/broadcom/brcm80211/include
+ccflags-y := -I $(srctree)/$(src)/../include
obj-$(CONFIG_BRCMUTIL) += brcmutil.o
brcmutil-objs = utils.o d11.o
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
index 57e3b6cca234..271977f7fbb0 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -3756,10 +3756,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto out_remove_sysfs;
- err = il_dbgfs_register(il, DRV_NAME);
- if (err)
- IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
- err);
+ il_dbgfs_register(il, DRV_NAME);
/* Start monitoring the killswitch */
queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll, 2 * HZ);
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 6b4488a178a7..94222ae464ae 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -4988,10 +4988,7 @@ il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
if (err)
goto out_unbind;
- err = il_dbgfs_register(il, DRV_NAME);
- if (err)
- IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
- err);
+ il_dbgfs_register(il, DRV_NAME);
err = sysfs_create_group(&il->pci_dev->dev.kobj, &il_attribute_group);
if (err) {
diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h
index dc6a74a05983..b079c64ca014 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -2974,13 +2974,11 @@ il_print_hex_dump(struct il_priv *il, int level, const void *p, u32 len)
#endif /* CONFIG_IWLEGACY_DEBUG */
#ifdef CONFIG_IWLEGACY_DEBUGFS
-int il_dbgfs_register(struct il_priv *il, const char *name);
+void il_dbgfs_register(struct il_priv *il, const char *name);
void il_dbgfs_unregister(struct il_priv *il);
#else
-static inline int
-il_dbgfs_register(struct il_priv *il, const char *name)
+static inline void il_dbgfs_register(struct il_priv *il, const char *name)
{
- return 0;
}
static inline void
diff --git a/drivers/net/wireless/intel/iwlegacy/debug.c b/drivers/net/wireless/intel/iwlegacy/debug.c
index d76073def677..fa211412e0ac 100644
--- a/drivers/net/wireless/intel/iwlegacy/debug.c
+++ b/drivers/net/wireless/intel/iwlegacy/debug.c
@@ -128,23 +128,12 @@ EXPORT_SYMBOL(il_update_stats);
/* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, il, \
- &il_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(#name, mode, parent, il, \
+ &il_dbgfs_##name##_ops); \
} while (0)
#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_bool(#name, 0600, parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
-} while (0)
-
-#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_x32(#name, 0600, parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
+ debugfs_create_bool(#name, 0600, parent, ptr); \
} while (0)
/* file operation */
@@ -1341,27 +1330,18 @@ DEBUGFS_WRITE_FILE_OPS(wd_timeout);
* Create the debugfs files and directories
*
*/
-int
+void
il_dbgfs_register(struct il_priv *il, const char *name)
{
struct dentry *phyd = il->hw->wiphy->debugfsdir;
struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
dir_drv = debugfs_create_dir(name, phyd);
- if (!dir_drv)
- return -ENOMEM;
-
il->debugfs_dir = dir_drv;
dir_data = debugfs_create_dir("data", dir_drv);
- if (!dir_data)
- goto err;
dir_rf = debugfs_create_dir("rf", dir_drv);
- if (!dir_rf)
- goto err;
dir_debug = debugfs_create_dir("debug", dir_drv);
- if (!dir_debug)
- goto err;
DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
DEBUGFS_ADD_FILE(sram, dir_data, 0600);
@@ -1399,12 +1379,6 @@ il_dbgfs_register(struct il_priv *il, const char *name)
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
&il->disable_chain_noise_cal);
DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
- return 0;
-
-err:
- IL_ERR("Can't create the debugfs directory\n");
- il_dbgfs_unregister(il);
- return -ENOMEM;
}
EXPORT_SYMBOL(il_dbgfs_register);
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig
index 491ca3c8b43c..83d5bceea08f 100644
--- a/drivers/net/wireless/intel/iwlwifi/Kconfig
+++ b/drivers/net/wireless/intel/iwlwifi/Kconfig
@@ -1,6 +1,6 @@
config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
- depends on PCI && HAS_IOMEM
+ depends on PCI && HAS_IOMEM && CFG80211
select FW_LOADER
---help---
Select to build the driver supporting the:
@@ -47,6 +47,7 @@ if IWLWIFI
config IWLWIFI_LEDS
bool
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
+ depends on IWLMVM || IWLDVM
select LEDS_TRIGGERS
select MAC80211_LEDS
default y
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 7e65073834b7..fdc56f821b5a 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
*
* 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
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@
#include "iwl-config.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 43
+#define IWL_22000_UCODE_API_MAX 46
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@@ -79,10 +79,15 @@
#define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
-#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-"
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
+#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
+#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
+#define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-"
+#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
+#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
+#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
#define IWL_22000_HR_MODULE_FIRMWARE(api) \
IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
@@ -96,14 +101,26 @@
IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \
IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \
- IWL_22000_JF_B0_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
+ IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
+ IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_CC_A_MODULE_FIRMWARE(api) \
+ IWL_CC_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \
+ IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_22000_SO_A_HR_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_22000_SO_A_GF_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_22000_TY_A_GF_A_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@@ -164,6 +181,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024
+#define IWL_DEVICE_AX200_COMMON \
+ IWL_DEVICE_22000_COMMON, \
+ .umac_prph_offset = 0x300000
+
#define IWL_DEVICE_22500 \
IWL_DEVICE_22000_COMMON, \
.device_family = IWL_DEVICE_FAMILY_22000, \
@@ -176,6 +197,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.base_params = &iwl_22560_base_params, \
.csr = &iwl_csr_v2
+#define IWL_DEVICE_AX210 \
+ IWL_DEVICE_AX200_COMMON, \
+ .device_family = IWL_DEVICE_FAMILY_AX210, \
+ .base_params = &iwl_22000_base_params, \
+ .csr = &iwl_csr_v1, \
+ .min_txq_size = 128
+
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AC 22000",
.fw_name_pre = IWL_22000_HR_FW_PRE,
@@ -195,8 +223,8 @@ const struct iwl_cfg iwl22000_2ac_cfg_jf = {
IWL_DEVICE_22500,
};
-const struct iwl_cfg iwl22000_2ax_cfg_hr = {
- .name = "Intel(R) Dual Band Wireless AX 22000",
+const struct iwl_cfg iwl_ax101_cfg_qu_hr = {
+ .name = "Intel(R) Wi-Fi 6 AX101",
.fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
@@ -207,6 +235,45 @@ const struct iwl_cfg iwl22000_2ax_cfg_hr = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
+const struct iwl_cfg iwl22260_2ax_cfg = {
+ .name = "Intel(R) Wireless-AX 22260",
+ .fw_name_pre = IWL_CC_A_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+ .bisr_workaround = 1,
+};
+
+const struct iwl_cfg killer1650x_2ax_cfg = {
+ .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (200NGW)",
+ .fw_name_pre = IWL_CC_A_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+ .bisr_workaround = 1,
+};
+
+const struct iwl_cfg killer1650w_2ax_cfg = {
+ .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (200D2W)",
+ .fw_name_pre = IWL_CC_A_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+ .bisr_workaround = 1,
+};
+
/*
* All JF radio modules are part of the 9000 series, but the MAC part
* looks more like 22000. That's why this device is here, but called
@@ -230,6 +297,24 @@ const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0 = {
IWL_DEVICE_22500,
};
+const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+};
+
+const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = {
.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
@@ -242,9 +327,9 @@ const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = {
IWL_DEVICE_22500,
};
-const struct iwl_cfg iwl22000_2ax_cfg_jf = {
- .name = "Intel(R) Dual Band Wireless AX 22000",
- .fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
+const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
+ .name = "Killer(R) Wireless-AX 1650i Wireless Network Adapter (22560NGW)",
+ .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
@@ -254,9 +339,21 @@ const struct iwl_cfg iwl22000_2ax_cfg_jf = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
-const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = {
+const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
+ .name = "Killer(R) Wireless-AX 1650s Wireless Network Adapter (22560D2W)",
+ .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
+const struct iwl_cfg iwl22000_2ax_cfg_jf = {
.name = "Intel(R) Dual Band Wireless AX 22000",
- .fw_name_pre = IWL_22000_HR_A_F0_FW_PRE,
+ .fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
@@ -266,9 +363,9 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
-const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
+const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = {
.name = "Intel(R) Dual Band Wireless AX 22000",
- .fw_name_pre = IWL_22000_HR_B_FW_PRE,
+ .fw_name_pre = IWL_22000_HR_A_F0_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
@@ -278,9 +375,9 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
-const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = {
+const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
.name = "Intel(R) Dual Band Wireless AX 22000",
- .fw_name_pre = IWL_22000_JF_B0_FW_PRE,
+ .fw_name_pre = IWL_22000_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
@@ -315,12 +412,41 @@ const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
+const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE,
+ IWL_DEVICE_AX210,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
+ .name = "Intel(R) Wi-Fi 6 AX201 160MHz",
+ .fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE,
+ IWL_DEVICE_AX210,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = {
+ .name = "Intel(R) Wi-Fi 7 AX211 160MHz",
+ .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
+ IWL_DEVICE_AX210,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
+ .name = "Intel(R) Wi-Fi 7 AX210 160MHz",
+ .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
+ IWL_DEVICE_AX210,
+};
+
MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index f2114137c13f..3225b64eb845 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -57,7 +57,7 @@
#include "fw/file.h"
/* Highest firmware API version supported */
-#define IWL9000_UCODE_API_MAX 43
+#define IWL9000_UCODE_API_MAX 46
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
@@ -73,21 +73,12 @@
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
-#define IWL9000A_FW_PRE "iwlwifi-9000-pu-a0-jf-a0-"
-#define IWL9000B_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-"
-#define IWL9000RFB_FW_PRE "iwlwifi-9000-pu-a0-jf-b0-"
-#define IWL9260A_FW_PRE "iwlwifi-9260-th-a0-jf-a0-"
-#define IWL9260B_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
-#define IWL9000A_MODULE_FIRMWARE(api) \
- IWL9000A_FW_PRE __stringify(api) ".ucode"
-#define IWL9000B_MODULE_FIRMWARE(api) \
- IWL9000B_FW_PRE __stringify(api) ".ucode"
-#define IWL9000RFB_MODULE_FIRMWARE(api) \
- IWL9000RFB_FW_PRE __stringify(api) ".ucode"
-#define IWL9260A_MODULE_FIRMWARE(api) \
- IWL9260A_FW_PRE __stringify(api) ".ucode"
-#define IWL9260B_MODULE_FIRMWARE(api) \
- IWL9260B_FW_PRE __stringify(api) ".ucode"
+#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-"
+#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
+#define IWL9000_MODULE_FIRMWARE(api) \
+ IWL9000_FW_PRE __stringify(api) ".ucode"
+#define IWL9260_MODULE_FIRMWARE(api) \
+ IWL9260_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@@ -162,81 +153,87 @@ static const struct iwl_tt_params iwl9000_tt_params = {
const struct iwl_cfg iwl9160_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9160",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9260",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
+ IWL_DEVICE_9000,
+};
+
+const struct iwl_cfg iwl9260_2ac_160_cfg = {
+ .name = "Intel(R) Wireless-AC 9260 160MHz",
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9260_killer_2ac_cfg = {
.name = "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9270_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9270",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9460_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9460",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9460_2ac_cfg_soc = {
.name = "Intel(R) Dual Band Wireless AC 9460",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
};
const struct iwl_cfg iwl9461_2ac_cfg_soc = {
- .name = "Intel(R) Dual Band Wireless AC 9461",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
- IWL_DEVICE_9000,
- .integrated = true,
- .soc_latency = 5000,
+ .name = "Intel(R) Dual Band Wireless AC 9461",
+ .fw_name_pre = IWL9000_FW_PRE,
+ IWL_DEVICE_9000,
+ .integrated = true,
+ .soc_latency = 5000,
};
const struct iwl_cfg iwl9462_2ac_cfg_soc = {
- .name = "Intel(R) Dual Band Wireless AC 9462",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
- IWL_DEVICE_9000,
- .integrated = true,
- .soc_latency = 5000,
+ .name = "Intel(R) Dual Band Wireless AC 9462",
+ .fw_name_pre = IWL9000_FW_PRE,
+ IWL_DEVICE_9000,
+ .integrated = true,
+ .soc_latency = 5000,
};
const struct iwl_cfg iwl9560_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9560",
- .fw_name_pre = IWL9260A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE,
+ .fw_name_pre = IWL9260_FW_PRE,
+ IWL_DEVICE_9000,
+};
+
+const struct iwl_cfg iwl9560_2ac_160_cfg = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9560_2ac_cfg_soc = {
.name = "Intel(R) Dual Band Wireless AC 9560",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
+ IWL_DEVICE_9000,
+ .integrated = true,
+ .soc_latency = 5000,
+};
+
+const struct iwl_cfg iwl9560_2ac_160_cfg_soc = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -244,9 +241,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = {
const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = {
.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -254,9 +249,7 @@ const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = {
const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc = {
.name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -264,9 +257,7 @@ const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc = {
const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9460",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -275,9 +266,7 @@ const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = {
const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9461",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -286,9 +275,7 @@ const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = {
const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9462",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -297,9 +284,16 @@ const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = {
const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9560",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
+ IWL_DEVICE_9000,
+ .integrated = true,
+ .soc_latency = 5000,
+ .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
+};
+
+const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -308,9 +302,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = {
const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = {
.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
@@ -319,17 +311,12 @@ const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = {
const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk = {
.name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)",
- .fw_name_pre = IWL9000A_FW_PRE,
- .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
- .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
+ .fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.integrated = true,
.soc_latency = 5000,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
-MODULE_FIRMWARE(IWL9000A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL9000B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL9260A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL9260B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/Makefile b/drivers/net/wireless/intel/iwlwifi/dvm/Makefile
index 702d42b2d452..0486b17d7c41 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/Makefile
@@ -11,4 +11,4 @@ iwldvm-objs += rxon.o devices.o
iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
-ccflags-y += -I$(src)/../
+ccflags-y += -I $(srctree)/$(src)/../
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
index 431e13c6ee35..254a5ce52456 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
@@ -439,13 +439,10 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir);
+void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir);
#else
-static inline int iwl_dbgfs_register(struct iwl_priv *priv,
- struct dentry *dbgfs_dir)
-{
- return 0;
-}
+static inline void iwl_dbgfs_register(struct iwl_priv *priv,
+ struct dentry *dbgfs_dir) { }
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#ifdef CONFIG_IWLWIFI_DEBUG
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
index 3d2e44a642de..d4b19673b06a 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
@@ -3,6 +3,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
*
* 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
@@ -36,31 +37,8 @@
/* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, priv, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
-} while (0)
-
-#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_bool(#name, 0600, parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
-} while (0)
-
-#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_x32(#name, 0600, parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
-} while (0)
-
-#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \
- struct dentry *__tmp; \
- __tmp = debugfs_create_u32(#name, mode, \
- parent, ptr); \
- if (IS_ERR(__tmp) || !__tmp) \
- goto err; \
+ debugfs_create_file(#name, mode, parent, priv, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
/* file operation */
@@ -2238,7 +2216,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
- if (sscanf(buf, "%d", &event_log_flag) != 1)
+ if (sscanf(buf, "%u", &event_log_flag) != 1)
return -EFAULT;
if (event_log_flag == 1)
iwl_dump_nic_event_log(priv, true, NULL);
@@ -2347,21 +2325,15 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
* Create the debugfs files and directories
*
*/
-int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
+void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
{
struct dentry *dir_data, *dir_rf, *dir_debug;
priv->debugfs_dir = dbgfs_dir;
dir_data = debugfs_create_dir("data", dbgfs_dir);
- if (!dir_data)
- goto err;
dir_rf = debugfs_create_dir("rf", dbgfs_dir);
- if (!dir_rf)
- goto err;
dir_debug = debugfs_create_dir("debug", dbgfs_dir);
- if (!dir_debug)
- goto err;
DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
DEBUGFS_ADD_FILE(sram, dir_data, 0600);
@@ -2421,13 +2393,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
snprintf(buf, 100, "../../%pd2", dev_dir);
- if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf))
- goto err;
+ debugfs_create_symlink("iwlwifi", mac80211_dir, buf);
}
-
- return 0;
-
-err:
- IWL_ERR(priv, "failed to create the dvm debugfs entries\n");
- return -ENOMEM;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 49b71dbf8490..54b759cec8b3 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -710,24 +711,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return ret;
}
-static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
-{
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
- return false;
- return true;
-}
-
-static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
-{
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
- return false;
- if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
- return true;
-
- /* disabled by default */
- return false;
-}
-
static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params)
@@ -752,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if (!iwl_enable_rx_ampdu(priv->cfg))
+ if (!iwl_enable_rx_ampdu())
break;
IWL_DEBUG_HT(priv, "start Rx\n");
ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
@@ -764,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_START:
if (!priv->trans->ops->txq_enable)
break;
- if (!iwl_enable_tx_ampdu(priv->cfg))
+ if (!iwl_enable_tx_ampdu())
break;
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
index c219bca5cff4..7c68a86ed9e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -1054,7 +1054,7 @@ static void iwl_bg_restart(struct work_struct *data)
ieee80211_restart_hw(priv->hw);
else
IWL_ERR(priv,
- "Cannot request restart before registrating with mac80211\n");
+ "Cannot request restart before registering with mac80211\n");
} else {
WARN_ON(1);
}
@@ -1509,13 +1509,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
goto out_destroy_workqueue;
- if (iwl_dbgfs_register(priv, dbgfs_dir))
- goto out_mac80211_unregister;
+ iwl_dbgfs_register(priv, dbgfs_dir);
return op_mode;
-out_mac80211_unregister:
- iwlagn_mac_unregister(priv);
out_destroy_workqueue:
iwl_tt_exit(priv);
iwl_cancel_deferred_work(priv);
@@ -1881,7 +1878,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
return pos;
}
- if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
+ if (!(iwl_have_debug_level(IWL_DL_FW)) && !full_log)
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
@@ -1897,7 +1894,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
if (!*buf)
return -ENOMEM;
}
- if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
+ if (iwl_have_debug_level(IWL_DL_FW) || full_log) {
/*
* if uCode has wrapped back to top of log,
* start at the oldest entry,
@@ -1927,7 +1924,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
unsigned int reload_msec;
unsigned long reload_jiffies;
- if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
+ if (iwl_have_debug_level(IWL_DL_FW))
iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
/* uCode is no longer loaded. */
@@ -1965,12 +1962,12 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
if (iwlwifi_mod_params.fw_restart) {
- IWL_DEBUG_FW_ERRORS(priv,
- "Restarting adapter due to uCode error.\n");
+ IWL_DEBUG_FW(priv,
+ "Restarting adapter due to uCode error.\n");
queue_work(priv->workqueue, &priv->restart);
} else
- IWL_DEBUG_FW_ERRORS(priv,
- "Detected FW error, but not restarting\n");
+ IWL_DEBUG_FW(priv,
+ "Detected FW error, but not restarting\n");
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
index 6f17a5e24e82..e224b23f0ba8 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
@@ -2,6 +2,7 @@
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portionhelp of the ieee80211 subsystem header files.
@@ -592,7 +593,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv,
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
RX_RES_STATUS_BAD_KEY_TTAK)
break;
-
+ /* fall through */
case RX_RES_STATUS_SEC_TYPE_WEP:
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
RX_RES_STATUS_BAD_ICV_MIC) {
@@ -601,6 +602,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv,
IWL_DEBUG_RX(priv, "Packet destroyed\n");
return -1;
}
+ /* fall through */
case RX_RES_STATUS_SEC_TYPE_CCMP:
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
RX_RES_STATUS_DECRYPT_OK) {
@@ -729,7 +731,7 @@ static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
break;
}
- /* fall through if TTAK OK */
+ /* fall through */
default:
if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
index 8d7aafb4d9e9..f190f7beb3a8 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
@@ -3,6 +3,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 Intel Corporation
*
* 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
@@ -418,7 +419,7 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
limit /= 2;
dwell_time = min(limit, dwell_time);
- /* fall through to limit further */
+ /* fall through */
case 1:
limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
limit /= n_active;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
index 4de2727ac63e..a156dcf5b7d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -325,9 +326,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
iwl_prepare_ct_kill_task(priv);
tt->state = old_state;
}
- } else if (old_state == IWL_TI_CT_KILL &&
- tt->state != IWL_TI_CT_KILL)
+ } else if (old_state == IWL_TI_CT_KILL) {
iwl_perform_ct_kill_task(priv, false);
+ }
IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
tt->state);
IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 32d000cffe9f..405038ce98d6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright (C) 2019 Intel Corporation
*
* 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
@@ -26,6 +27,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright (C) 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -205,3 +207,33 @@ out:
return dflt_pwr_limit;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
+
+int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
+{
+ union acpi_object *wifi_pkg, *data;
+ int ret;
+
+ data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE);
+ if (IS_ERR(wifi_pkg)) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ *extl_clk = wifi_pkg->package.elements[1].integer.value;
+
+ ret = 0;
+
+out_free:
+ kfree(data);
+ return ret;
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 7492dfb6729b..f5704e16643f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -27,7 +27,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,6 +67,7 @@
#define ACPI_WGDS_METHOD "WGDS"
#define ACPI_WRDD_METHOD "WRDD"
#define ACPI_SPLC_METHOD "SPLC"
+#define ACPI_ECKV_METHOD "ECKV"
#define ACPI_WIFI_DOMAIN (0x07)
@@ -86,6 +87,7 @@
#define ACPI_WGDS_WIFI_DATA_SIZE 19
#define ACPI_WRDD_WIFI_DATA_SIZE 2
#define ACPI_SPLC_WIFI_DATA_SIZE 2
+#define ACPI_ECKV_WIFI_DATA_SIZE 2
#define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3
@@ -109,6 +111,17 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc);
u64 iwl_acpi_get_pwr_limit(struct device *dev);
+/*
+ * iwl_acpi_get_eckv - read external clock validation from ACPI, if available
+ *
+ * @dev: the struct device
+ * @extl_clk: output var (2 bytes) that will get the clk indication.
+ *
+ * This function tries to read the external clock indication
+ * from ACPI if available.
+ */
+int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
+
#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
@@ -133,5 +146,10 @@ static inline u64 iwl_acpi_get_pwr_limit(struct device *dev)
return 0;
}
+static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
+{
+ return -ENOENT;
+}
+
#endif /* CONFIG_ACPI */
#endif /* __iwl_fw_acpi__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
index 08d3d8a190f6..df1bd0d2450e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
@@ -96,14 +96,7 @@ enum {
#define IWL_ALIVE_FLG_RFKILL BIT(0)
-struct iwl_lmac_alive {
- __le32 ucode_major;
- __le32 ucode_minor;
- u8 ver_subtype;
- u8 ver_type;
- u8 mac;
- u8 opt;
- __le32 timestamp;
+struct iwl_lmac_debug_addrs {
__le32 error_event_table_ptr; /* SRAM address for error log */
__le32 log_event_table_ptr; /* SRAM address for LMAC event log */
__le32 cpu_register_ptr;
@@ -112,13 +105,28 @@ struct iwl_lmac_alive {
__le32 scd_base_ptr; /* SRAM address for SCD */
__le32 st_fwrd_addr; /* pointer to Store and forward */
__le32 st_fwrd_size;
+} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */
+
+struct iwl_lmac_alive {
+ __le32 ucode_major;
+ __le32 ucode_minor;
+ u8 ver_subtype;
+ u8 ver_type;
+ u8 mac;
+ u8 opt;
+ __le32 timestamp;
+ struct iwl_lmac_debug_addrs dbg_ptrs;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
+struct iwl_umac_debug_addrs {
+ __le32 error_info_addr; /* SRAM address for UMAC error log */
+ __le32 dbg_print_buff_addr;
+} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */
+
struct iwl_umac_alive {
__le32 umac_major; /* UMAC version: major */
__le32 umac_minor; /* UMAC version: minor */
- __le32 error_info_addr; /* SRAM address for UMAC error log */
- __le32 dbg_print_buff_addr;
+ struct iwl_umac_debug_addrs dbg_ptrs;
} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
struct mvm_alive_resp_v3 {
@@ -189,4 +197,24 @@ struct iwl_card_state_notif {
__le32 flags;
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
+/**
+ * enum iwl_error_recovery_flags - flags for error recovery cmd
+ * @ERROR_RECOVERY_UPDATE_DB: update db from blob sent
+ * @ERROR_RECOVERY_END_OF_RECOVERY: end of recovery
+ */
+enum iwl_error_recovery_flags {
+ ERROR_RECOVERY_UPDATE_DB = BIT(0),
+ ERROR_RECOVERY_END_OF_RECOVERY = BIT(1),
+};
+
+/**
+ * struct iwl_fw_error_recovery_cmd - recovery cmd sent upon assert
+ * @flags: &enum iwl_error_recovery_flags
+ * @buf_size: db buffer size in bytes
+ */
+struct iwl_fw_error_recovery_cmd {
+ __le32 flags;
+ __le32 buf_size;
+} __packed; /* ERROR_RECOVERY_CMD_HDR_API_S_VER_1 */
+
#endif /* __iwl_fw_api_alive_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
index 8b4922bbe139..4d2274bcc0b5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
@@ -77,7 +77,8 @@
* @DATA_PATH_GROUP: data path group, uses command IDs from
* &enum iwl_data_path_subcmd_ids
* @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids
- * @TOF_GROUP: TOF group, uses command IDs from &enum iwl_tof_subcmd_ids
+ * @LOCATION_GROUP: location group, uses command IDs from
+ * &enum iwl_location_subcmd_ids
* @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from
* &enum iwl_prot_offload_subcmd_ids
* @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
@@ -92,7 +93,7 @@ enum iwl_mvm_command_groups {
PHY_OPS_GROUP = 0x4,
DATA_PATH_GROUP = 0x5,
NAN_GROUP = 0x7,
- TOF_GROUP = 0x8,
+ LOCATION_GROUP = 0x8,
PROT_OFFLOAD_GROUP = 0xb,
REGULATORY_AND_NVM_GROUP = 0xc,
DEBUG_GROUP = 0xf,
@@ -353,16 +354,6 @@ enum iwl_legacy_cmds {
PHY_DB_CMD = 0x6c,
/**
- * @TOF_CMD: &struct iwl_tof_config_cmd
- */
- TOF_CMD = 0x10,
-
- /**
- * @TOF_NOTIFICATION: &struct iwl_tof_gen_resp_cmd
- */
- TOF_NOTIFICATION = 0x11,
-
- /**
* @POWER_TABLE_CMD: &struct iwl_device_power_cmd
*/
POWER_TABLE_CMD = 0x77,
@@ -415,7 +406,11 @@ enum iwl_legacy_cmds {
TX_ANT_CONFIGURATION_CMD = 0x98,
/**
- * @STATISTICS_CMD: &struct iwl_statistics_cmd
+ * @STATISTICS_CMD:
+ * one of &struct iwl_statistics_cmd,
+ * &struct iwl_notif_statistics_v11,
+ * &struct iwl_notif_statistics_v10,
+ * &struct iwl_notif_statistics
*/
STATISTICS_CMD = 0x9c,
@@ -423,7 +418,7 @@ enum iwl_legacy_cmds {
* @STATISTICS_NOTIFICATION:
* one of &struct iwl_notif_statistics_v10,
* &struct iwl_notif_statistics_v11,
- * &struct iwl_notif_statistics_cdb
+ * &struct iwl_notif_statistics
*/
STATISTICS_NOTIFICATION = 0x9d,
@@ -648,6 +643,11 @@ enum iwl_system_subcmd_ids {
* @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
*/
INIT_EXTENDED_CFG_CMD = 0x03,
+
+ /**
+ * @FW_ERROR_RECOVERY_CMD: &struct iwl_fw_error_recovery_cmd
+ */
+ FW_ERROR_RECOVERY_CMD = 0x7,
};
#endif /* __iwl_fw_api_commands_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index 6fae02fa4cad..86ea0784e1a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -224,8 +224,18 @@ struct iwl_wowlan_pattern {
#define IWL_WOWLAN_MAX_PATTERNS 20
+/**
+ * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
+ */
struct iwl_wowlan_patterns_cmd {
+ /**
+ * @n_patterns: number of patterns
+ */
__le32 n_patterns;
+
+ /**
+ * @patterns: the patterns, array length in @n_patterns
+ */
struct iwl_wowlan_pattern patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index fdc54a5dc9de..93c06e6c1ced 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -105,6 +105,12 @@ enum iwl_data_path_subcmd_ids {
HE_AIR_SNIFFER_CONFIG_CMD = 0x13,
/**
+ * @CHEST_COLLECTOR_FILTER_CONFIG_CMD: Configure the CSI
+ * matrix collection, uses &struct iwl_channel_estimation_cfg
+ */
+ CHEST_COLLECTOR_FILTER_CONFIG_CMD = 0x14,
+
+ /**
* @RX_NO_DATA_NOTIF: &struct iwl_rx_no_data
*/
RX_NO_DATA_NOTIF = 0xF5,
@@ -156,4 +162,53 @@ struct iwl_mu_group_mgmt_notif {
__le32 user_position[4];
} __packed; /* MU_GROUP_MNG_NTFY_API_S_VER_1 */
+enum iwl_channel_estimation_flags {
+ IWL_CHANNEL_ESTIMATION_ENABLE = BIT(0),
+ IWL_CHANNEL_ESTIMATION_TIMER = BIT(1),
+ IWL_CHANNEL_ESTIMATION_COUNTER = BIT(2),
+};
+
+/**
+ * struct iwl_channel_estimation_cfg - channel estimation reporting config
+ */
+struct iwl_channel_estimation_cfg {
+ /**
+ * @flags: flags, see &enum iwl_channel_estimation_flags
+ */
+ __le32 flags;
+ /**
+ * @timer: if enabled via flags, automatically disable after this many
+ * microseconds
+ */
+ __le32 timer;
+ /**
+ * @count: if enabled via flags, automatically disable after this many
+ * frames with channel estimation matrix were captured
+ */
+ __le32 count;
+ /**
+ * @rate_n_flags_mask: only try to record the channel estimation matrix
+ * if the rate_n_flags value for the received frame (let's call
+ * that rx_rnf) matches the mask/value given here like this:
+ * (rx_rnf & rate_n_flags_mask) == rate_n_flags_val.
+ */
+ __le32 rate_n_flags_mask;
+ /**
+ * @rate_n_flags_val: see @rate_n_flags_mask
+ */
+ __le32 rate_n_flags_val;
+ /**
+ * @reserved: reserved (for alignment)
+ */
+ __le32 reserved;
+ /**
+ * @frame_types: bitmap of frame types to capture, the received frame's
+ * subtype|type takes 6 bits in the frame and the corresponding bit
+ * in this field must be set to 1 to capture channel estimation for
+ * that frame type. Set to all-ones to enable capturing for all
+ * frame types.
+ */
+ __le64 frame_types;
+} __packed; /* CHEST_COLLECTOR_FILTER_CMD_API_S_VER_1 */
+
#endif /* __iwl_fw_api_datapath_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
index ab82b7a67967..33858787817b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -25,7 +25,7 @@
*
* BSD LICENSE
*
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ struct iwl_fw_ini_header {
__le32 tlv_version;
__le32 apply_point;
u8 data[];
-} __packed; /* FW_INI_HEADER_TLV_S */
+} __packed; /* FW_DEBUG_TLV_HEADER_S */
/**
* struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION)
@@ -92,7 +92,7 @@ struct iwl_fw_ini_allocation_tlv {
__le32 size;
__le32 max_fragments;
__le32 min_frag_size;
-} __packed; /* FW_INI_BUFFER_ALLOCATION_TLV_S_VER_1 */
+} __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */
/**
* struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD)
@@ -108,7 +108,7 @@ struct iwl_fw_ini_hcmd {
u8 group;
__le16 padding;
u8 data[0];
-} __packed; /* FW_INI_HCMD_S */
+} __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */
/**
* struct iwl_fw_ini_hcmd_tlv
@@ -118,7 +118,7 @@ struct iwl_fw_ini_hcmd {
struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_header header;
struct iwl_fw_ini_hcmd hcmd;
-} __packed; /* FW_INI_HCMD_TLV_S_VER_1 */
+} __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */
/*
* struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW)
@@ -129,20 +129,50 @@ struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_debug_flow_tlv {
struct iwl_fw_ini_header header;
__le32 debug_flow_cfg;
-} __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */
+} __packed; /* FW_DEBUG_TLV_FLOW_TLV_S_VER_1 */
-#define IWL_FW_INI_MAX_REGION_ID 20
+#define IWL_FW_INI_MAX_REGION_ID 64
#define IWL_FW_INI_MAX_NAME 32
+
+/**
+ * struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region
+ * @num_of_range: the amount of ranges in the region
+ * @range_data_size: size of the data to read per range, in bytes.
+ */
+struct iwl_fw_ini_region_cfg_internal {
+ __le32 num_of_ranges;
+ __le32 range_data_size;
+} __packed; /* FW_DEBUG_TLV_REGION_NIC_INTERNAL_RANGES_S */
+
+/**
+ * struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region
+ * @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region
+ * @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region.
+ * It is unused for tx.
+ * @num_of_registers: number of prph registers in the region, each register is
+ * 4 bytes size.
+ * @header_only: none zero value indicates that this region does not include
+ * fifo data and includes only the given registers.
+ */
+struct iwl_fw_ini_region_cfg_fifos {
+ __le32 fid1;
+ __le32 fid2;
+ __le32 num_of_registers;
+ __le32 header_only;
+} __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */
+
/**
* struct iwl_fw_ini_region_cfg
* @region_id: ID of this dump configuration
* @region_type: &enum iwl_fw_ini_region_type
* @num_regions: amount of regions in the address array.
- * @allocation_id: For DRAM type field substitutes for allocation_id.
* @name_len: name length
* @name: file name to use for this region
- * @size: size of the data, in bytes.(unused for IWL_FW_INI_REGION_DRAM_BUFFER)
- * @start_addr: array of addresses. (unused for IWL_FW_INI_REGION_DRAM_BUFFER)
+ * @internal: used in case the region uses internal memory.
+ * @allocation_id: For DRAM type field substitutes for allocation_id
+ * @fifos: used in case of fifos region.
+ * @offset: offset to use for each memory base address
+ * @start_addr: array of addresses.
*/
struct iwl_fw_ini_region_cfg {
__le32 region_id;
@@ -150,32 +180,38 @@ struct iwl_fw_ini_region_cfg {
__le32 name_len;
u8 name[IWL_FW_INI_MAX_NAME];
union {
- __le32 num_regions;
+ struct iwl_fw_ini_region_cfg_internal internal;
__le32 allocation_id;
+ struct iwl_fw_ini_region_cfg_fifos fifos;
};
- __le32 size;
+ __le32 offset;
__le32 start_addr[];
-} __packed; /* FW_INI_REGION_CONFIG_S */
+} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */
/**
* struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG)
* DUMP sections define IDs and triggers that use those IDs TLV
* @header: header
* @num_regions: how many different region section and IDs are coming next
- * @iwl_fw_ini_dump dump_config: list of dump configurations
+ * @region_config: list of dump configurations
*/
struct iwl_fw_ini_region_tlv {
struct iwl_fw_ini_header header;
__le32 num_regions;
struct iwl_fw_ini_region_cfg region_config[];
-} __packed; /* FW_INI_REGION_CFG_S */
+} __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */
/**
* struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG)
* Region sections define IDs and triggers that use those IDs TLV
*
* @trigger_id: enum &iwl_fw_ini_tigger_id
- * @ignore_default: override FW TLV with binary TLV
+ * @override_trig: determines how apply trigger in case a trigger with the
+ * same id is already in use. Using the first 2 bytes:
+ * Byte 0: if 0, override trigger configuration, otherwise use the
+ * existing configuration.
+ * Byte 1: if 0, override trigger regions, otherwise append regions to
+ * existing trigger.
* @dump_delay: delay from trigger fire to dump, in usec
* @occurrences: max amount of times to be fired
* @ignore_consec: ignore consecutive triggers, in usec
@@ -187,7 +223,7 @@ struct iwl_fw_ini_region_tlv {
*/
struct iwl_fw_ini_trigger {
__le32 trigger_id;
- __le32 ignore_default;
+ __le32 override_trig;
__le32 dump_delay;
__le32 occurrences;
__le32 ignore_consec;
@@ -196,7 +232,7 @@ struct iwl_fw_ini_trigger {
__le32 trigger_data;
__le32 num_regions;
__le32 data[];
-} __packed; /* FW_INI_TRIGGER_CONFIG_S */
+} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */
/**
* struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG)
@@ -210,20 +246,17 @@ struct iwl_fw_ini_trigger_tlv {
struct iwl_fw_ini_header header;
__le32 num_triggers;
struct iwl_fw_ini_trigger trigger_config[];
-} __packed; /* FW_INI_TRIGGER_CFG_S */
+} __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */
/**
* enum iwl_fw_ini_trigger_id
* @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert
- * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
* @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert
- * @IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR: FW error notification
- * @IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING: FW warning notification
- * @IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO: FW info notification
- * @IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG: FW debug notification
+ * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
+ * @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification
+ * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification
* @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger
* @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity
- * @FW_DEBUG_TLV_TRIGGER_ID_HOST_DID_INITIATED_EVENT: undefined
* @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency
* threshold was crossed
* @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed
@@ -257,50 +290,53 @@ struct iwl_fw_ini_trigger_tlv {
* @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs
*/
enum iwl_fw_ini_trigger_id {
+ IWL_FW_TRIGGER_ID_INVALID = 0,
+
/* Errors triggers */
IWL_FW_TRIGGER_ID_FW_ASSERT = 1,
- IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 2,
- IWL_FW_TRIGGER_ID_FW_HW_ERROR = 3,
- /* Generic triggers */
- IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR = 4,
- IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING = 5,
- IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO = 6,
- IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG = 7,
- /* User Trigger */
- IWL_FW_TRIGGER_ID_USER_TRIGGER = 8,
+ IWL_FW_TRIGGER_ID_FW_HW_ERROR = 2,
+ IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 3,
+
+ /* FW triggers */
+ IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4,
+ IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5,
+
+ /* User trigger */
+ IWL_FW_TRIGGER_ID_USER_TRIGGER = 6,
+
/* Host triggers */
- IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 9,
- IWL_FW_TRIGGER_ID_HOST_DID_INITIATED_EVENT = 10,
- IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 11,
- IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 12,
- IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 13,
- IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 14,
- IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 15,
- IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 16,
- IWL_FW_TRIGGER_ID_HOST_SCAN_START = 17,
- IWL_FW_TRIGGER_ID_HOST_SCAN_SUBITTED = 18,
- IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 19,
- IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 20,
- IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 21,
- IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 22,
- IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 23,
- IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 24,
- IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 25,
- IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 26,
- IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 27,
- IWL_FW_TRIGGER_ID_HOST_D3_START = 28,
- IWL_FW_TRIGGER_ID_HOST_D3_END = 29,
- IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 30,
- IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 31,
- IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 32,
- IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 33,
- IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 34,
- IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 35,
- IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 36,
- IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 37,
- IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 38,
+ IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7,
+ IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8,
+ IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9,
+ IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10,
+ IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11,
+ IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12,
+ IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16,
+ IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17,
+ IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18,
+ IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19,
+ IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20,
+ IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22,
+ IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24,
+ IWL_FW_TRIGGER_ID_HOST_D3_START = 25,
+ IWL_FW_TRIGGER_ID_HOST_D3_END = 26,
+ IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27,
+ IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28,
+ IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29,
+ IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33,
+ IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34,
+ IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35,
+
IWL_FW_TRIGGER_ID_NUM,
-}; /* FW_INI_TRIGGER_ID_E_VER_1 */
+}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */
/**
* enum iwl_fw_ini_apply_point
@@ -320,7 +356,7 @@ enum iwl_fw_ini_apply_point {
IWL_FW_INI_APPLY_MISSED_BEACONS,
IWL_FW_INI_APPLY_SCAN_COMPLETE,
IWL_FW_INI_APPLY_NUM,
-}; /* FW_INI_APPLY_POINT_E_VER_1 */
+}; /* FW_DEBUG_TLV_APPLY_POINT_E_VER_1 */
/**
* enum iwl_fw_ini_allocation_id
@@ -340,7 +376,7 @@ enum iwl_fw_ini_allocation_id {
IWL_FW_INI_ALLOCATION_ID_SDFX,
IWL_FW_INI_ALLOCATION_ID_FW_DUMP,
IWL_FW_INI_ALLOCATION_ID_USER_DEFINED,
-}; /* FW_INI_ALLOCATION_ID_E_VER_1 */
+}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
/**
* enum iwl_fw_ini_buffer_location
@@ -349,10 +385,10 @@ enum iwl_fw_ini_allocation_id {
* @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location
*/
enum iwl_fw_ini_buffer_location {
- IWL_FW_INI_LOCATION_SRAM_INVALID,
+ IWL_FW_INI_LOCATION_INVALID,
IWL_FW_INI_LOCATION_SRAM_PATH,
IWL_FW_INI_LOCATION_DRAM_PATH,
-}; /* FW_INI_BUFFER_LOCATION_E_VER_1 */
+}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
/**
* enum iwl_fw_ini_debug_flow
@@ -364,7 +400,7 @@ enum iwl_fw_ini_debug_flow {
IWL_FW_INI_DEBUG_INVALID,
IWL_FW_INI_DEBUG_DBTR_FLOW,
IWL_FW_INI_DEBUG_TB2DTF_FLOW,
-}; /* FW_INI_DEBUG_FLOW_E_VER_1 */
+}; /* FW_DEBUG_TLV_FLOW_E_VER_1 */
/**
* enum iwl_fw_ini_region_type
@@ -396,6 +432,6 @@ enum iwl_fw_ini_region_type {
IWL_FW_INI_REGION_PAGING,
IWL_FW_INI_REGION_CSR,
IWL_FW_INI_REGION_NUM
-}; /* FW_INI_REGION_TYPE_E_VER_1*/
+}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
index dc1fa377087a..988584973aba 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
@@ -335,29 +335,11 @@ struct iwl_dbg_mem_access_rsp {
__le32 data[];
} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
-#define CONT_REC_COMMAND_SIZE 80
-#define ENABLE_CONT_RECORDING 0x15
-#define DISABLE_CONT_RECORDING 0x16
+#define LDBG_CFG_COMMAND_SIZE 80
#define BUFFER_ALLOCATION 0x27
#define START_DEBUG_RECORDING 0x29
#define STOP_DEBUG_RECORDING 0x2A
-/*
- * struct iwl_continuous_record_mode - recording mode
- */
-struct iwl_continuous_record_mode {
- __le16 enable_recording;
-} __packed;
-
-/*
- * struct iwl_continuous_record_cmd - enable/disable continuous recording
- */
-struct iwl_continuous_record_cmd {
- struct iwl_continuous_record_mode record_mode;
- u8 pad[CONT_REC_COMMAND_SIZE -
- sizeof(struct iwl_continuous_record_mode)];
-} __packed;
-
/* maximum fragments to be allocated per target of allocationId */
#define IWL_BUFFER_LOCATION_MAX_FRAGS 2
@@ -385,4 +367,17 @@ struct iwl_buffer_allocation_cmd {
struct iwl_fragment_data fragments[IWL_BUFFER_LOCATION_MAX_FRAGS];
} __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_1 */
+/**
+ * struct iwl_ldbg_config_cmd - LDBG config command
+ * @type: configuration type
+ * @pad: reserved space for type-dependent data
+ */
+struct iwl_ldbg_config_cmd {
+ __le32 type;
+ union {
+ u8 pad[LDBG_CFG_COMMAND_SIZE - sizeof(__le32)];
+ struct iwl_buffer_allocation_cmd buffer_allocation;
+ }; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */
+} __packed; /* LDBG_CFG_CMD_API_S_VER_2 */
+
#endif /* __iwl_fw_api_debug_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
new file mode 100644
index 000000000000..5dddb21c1c4d
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -0,0 +1,878 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * 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
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 __iwl_fw_api_location_h__
+#define __iwl_fw_api_location_h__
+
+/**
+ * enum iwl_location_subcmd_ids - location group command IDs
+ */
+enum iwl_location_subcmd_ids {
+ /**
+ * @TOF_RANGE_REQ_CMD: TOF ranging request,
+ * uses &struct iwl_tof_range_req_cmd
+ */
+ TOF_RANGE_REQ_CMD = 0x0,
+ /**
+ * @TOF_CONFIG_CMD: TOF configuration, uses &struct iwl_tof_config_cmd
+ */
+ TOF_CONFIG_CMD = 0x1,
+ /**
+ * @TOF_RANGE_ABORT_CMD: abort ongoing ranging, uses
+ * &struct iwl_tof_range_abort_cmd
+ */
+ TOF_RANGE_ABORT_CMD = 0x2,
+ /**
+ * @TOF_RANGE_REQ_EXT_CMD: TOF extended ranging config,
+ * uses &struct iwl_tof_range_request_ext_cmd
+ */
+ TOF_RANGE_REQ_EXT_CMD = 0x3,
+ /**
+ * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration,
+ * uses &struct iwl_tof_responder_config_cmd
+ */
+ TOF_RESPONDER_CONFIG_CMD = 0x4,
+ /**
+ * @TOF_RESPONDER_DYN_CONFIG_CMD: FTM dynamic configuration,
+ * uses &struct iwl_tof_responder_dyn_config_cmd
+ */
+ TOF_RESPONDER_DYN_CONFIG_CMD = 0x5,
+ /**
+ * @CSI_HEADER_NOTIFICATION: CSI header
+ */
+ CSI_HEADER_NOTIFICATION = 0xFA,
+ /**
+ * @CSI_CHUNKS_NOTIFICATION: CSI chunk,
+ * uses &struct iwl_csi_chunk_notification
+ */
+ CSI_CHUNKS_NOTIFICATION = 0xFB,
+ /**
+ * @TOF_LC_NOTIF: used for LCI/civic location, contains just
+ * the action frame
+ */
+ TOF_LC_NOTIF = 0xFC,
+ /**
+ * @TOF_RESPONDER_STATS: FTM responder statistics notification,
+ * uses &struct iwl_ftm_responder_stats
+ */
+ TOF_RESPONDER_STATS = 0xFD,
+ /**
+ * @TOF_MCSI_DEBUG_NOTIF: MCSI debug notification, uses
+ * &struct iwl_tof_mcsi_notif
+ */
+ TOF_MCSI_DEBUG_NOTIF = 0xFE,
+ /**
+ * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using
+ * &struct iwl_tof_range_rsp_ntfy
+ */
+ TOF_RANGE_RESPONSE_NOTIF = 0xFF,
+};
+
+/**
+ * struct iwl_tof_config_cmd - ToF configuration
+ * @tof_disabled: indicates if ToF is disabled (or not)
+ * @one_sided_disabled: indicates if one-sided is disabled (or not)
+ * @is_debug_mode: indiciates if debug mode is active
+ * @is_buf_required: indicates if channel estimation buffer is required
+ */
+struct iwl_tof_config_cmd {
+ u8 tof_disabled;
+ u8 one_sided_disabled;
+ u8 is_debug_mode;
+ u8 is_buf_required;
+} __packed;
+
+/**
+ * enum iwl_tof_bandwidth - values for iwl_tof_range_req_ap_entry.bandwidth
+ * @IWL_TOF_BW_20_LEGACY: 20 MHz non-HT
+ * @IWL_TOF_BW_20_HT: 20 MHz HT
+ * @IWL_TOF_BW_40: 40 MHz
+ * @IWL_TOF_BW_80: 80 MHz
+ * @IWL_TOF_BW_160: 160 MHz
+ */
+enum iwl_tof_bandwidth {
+ IWL_TOF_BW_20_LEGACY,
+ IWL_TOF_BW_20_HT,
+ IWL_TOF_BW_40,
+ IWL_TOF_BW_80,
+ IWL_TOF_BW_160,
+}; /* LOCAT_BW_TYPE_E */
+
+/*
+ * enum iwl_tof_algo_type - Algorithym type for range measurement request
+ */
+enum iwl_tof_algo_type {
+ IWL_TOF_ALGO_TYPE_MAX_LIKE = 0,
+ IWL_TOF_ALGO_TYPE_LINEAR_REG = 1,
+ IWL_TOF_ALGO_TYPE_FFT = 2,
+
+ /* Keep last */
+ IWL_TOF_ALGO_TYPE_INVALID,
+}; /* ALGO_TYPE_E */
+
+/*
+ * enum iwl_tof_mcsi_ntfy - Enable/Disable MCSI notifications
+ */
+enum iwl_tof_mcsi_enable {
+ IWL_TOF_MCSI_DISABLED = 0,
+ IWL_TOF_MCSI_ENABLED = 1,
+}; /* MCSI_ENABLE_E */
+
+/**
+ * enum iwl_tof_responder_cmd_valid_field - valid fields in the responder cfg
+ * @IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO: channel info is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_TOA_OFFSET: ToA offset is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_COMMON_CALIB: common calibration mode is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_SPECIFIC_CALIB: spefici calibration mode is
+ * valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_BSSID: BSSID is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_TX_ANT: TX antenna is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_ALGO_TYPE: algorithm type is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_NON_ASAP_SUPPORT: non-ASAP support is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_STATISTICS_REPORT_SUPPORT: statistics report
+ * support is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_MCSI_NOTIF_SUPPORT: MCSI notification support
+ * is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT: fast algorithm support
+ * is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL: retry on algorithm failure
+ * is valid
+ * @IWL_TOF_RESPONDER_CMD_VALID_STA_ID: station ID is valid
+ */
+enum iwl_tof_responder_cmd_valid_field {
+ IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO = BIT(0),
+ IWL_TOF_RESPONDER_CMD_VALID_TOA_OFFSET = BIT(1),
+ IWL_TOF_RESPONDER_CMD_VALID_COMMON_CALIB = BIT(2),
+ IWL_TOF_RESPONDER_CMD_VALID_SPECIFIC_CALIB = BIT(3),
+ IWL_TOF_RESPONDER_CMD_VALID_BSSID = BIT(4),
+ IWL_TOF_RESPONDER_CMD_VALID_TX_ANT = BIT(5),
+ IWL_TOF_RESPONDER_CMD_VALID_ALGO_TYPE = BIT(6),
+ IWL_TOF_RESPONDER_CMD_VALID_NON_ASAP_SUPPORT = BIT(7),
+ IWL_TOF_RESPONDER_CMD_VALID_STATISTICS_REPORT_SUPPORT = BIT(8),
+ IWL_TOF_RESPONDER_CMD_VALID_MCSI_NOTIF_SUPPORT = BIT(9),
+ IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT = BIT(10),
+ IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL = BIT(11),
+ IWL_TOF_RESPONDER_CMD_VALID_STA_ID = BIT(12),
+};
+
+/**
+ * enum iwl_tof_responder_cfg_flags - responder configuration flags
+ * @IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT: non-ASAP support
+ * @IWL_TOF_RESPONDER_FLAGS_REPORT_STATISTICS: report statistics
+ * @IWL_TOF_RESPONDER_FLAGS_REPORT_MCSI: report MCSI
+ * @IWL_TOF_RESPONDER_FLAGS_ALGO_TYPE: algorithm type
+ * @IWL_TOF_RESPONDER_FLAGS_TOA_OFFSET_MODE: ToA offset mode
+ * @IWL_TOF_RESPONDER_FLAGS_COMMON_CALIB_MODE: common calibration mode
+ * @IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE: specific calibration mode
+ * @IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT: fast algorithm support
+ * @IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL: retry on algorithm fail
+ * @IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT: TX antenna mask
+ */
+enum iwl_tof_responder_cfg_flags {
+ IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT = BIT(0),
+ IWL_TOF_RESPONDER_FLAGS_REPORT_STATISTICS = BIT(1),
+ IWL_TOF_RESPONDER_FLAGS_REPORT_MCSI = BIT(2),
+ IWL_TOF_RESPONDER_FLAGS_ALGO_TYPE = BIT(3) | BIT(4) | BIT(5),
+ IWL_TOF_RESPONDER_FLAGS_TOA_OFFSET_MODE = BIT(6),
+ IWL_TOF_RESPONDER_FLAGS_COMMON_CALIB_MODE = BIT(7),
+ IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE = BIT(8),
+ IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9),
+ IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10),
+ IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK,
+};
+
+/**
+ * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug)
+ * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
+ * @responder_cfg_flags: &iwl_tof_responder_cfg_flags
+ * @bandwidth: current AP Bandwidth: &enum iwl_tof_bandwidth
+ * @rate: current AP rate
+ * @channel_num: current AP Channel
+ * @ctrl_ch_position: coding of the control channel position relative to
+ * the center frequency, see iwl_mvm_get_ctrl_pos()
+ * @sta_id: index of the AP STA when in AP mode
+ * @reserved1: reserved
+ * @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug
+ * purposes, simulating station movement by adding various values
+ * to this field
+ * @common_calib: XVT: common calibration value
+ * @specific_calib: XVT: specific calibration value
+ * @bssid: Current AP BSSID
+ * @reserved2: reserved
+ */
+struct iwl_tof_responder_config_cmd {
+ __le32 cmd_valid_fields;
+ __le32 responder_cfg_flags;
+ u8 bandwidth;
+ u8 rate;
+ u8 channel_num;
+ u8 ctrl_ch_position;
+ u8 sta_id;
+ u8 reserved1;
+ __le16 toa_offset;
+ __le16 common_calib;
+ __le16 specific_calib;
+ u8 bssid[ETH_ALEN];
+ __le16 reserved2;
+} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */
+
+#define IWL_LCI_CIVIC_IE_MAX_SIZE 400
+
+/**
+ * struct iwl_tof_responder_dyn_config_cmd - Dynamic responder settings
+ * @lci_len: The length of the 1st (LCI) part in the @lci_civic buffer
+ * @civic_len: The length of the 2nd (CIVIC) part in the @lci_civic buffer
+ * @lci_civic: The LCI/CIVIC buffer. LCI data (if exists) comes first, then, if
+ * needed, 0-padding such that the next part is dword-aligned, then CIVIC
+ * data (if exists) follows, and then 0-padding again to complete a
+ * 4-multiple long buffer.
+ */
+struct iwl_tof_responder_dyn_config_cmd {
+ __le32 lci_len;
+ __le32 civic_len;
+ u8 lci_civic[];
+} __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_2 */
+
+/**
+ * struct iwl_tof_range_request_ext_cmd - extended range req for WLS
+ * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF
+ * @reserved: reserved
+ * @min_delta_ftm: Minimal time between two consecutive measurements,
+ * in units of 100us. 0 means no preference by station
+ * @ftm_format_and_bw20M: FTM Channel Spacing/Format for 20MHz: recommended
+ * value be sent to the AP
+ * @ftm_format_and_bw40M: FTM Channel Spacing/Format for 40MHz: recommended
+ * value to be sent to the AP
+ * @ftm_format_and_bw80M: FTM Channel Spacing/Format for 80MHz: recommended
+ * value to be sent to the AP
+ */
+struct iwl_tof_range_req_ext_cmd {
+ __le16 tsf_timer_offset_msec;
+ __le16 reserved;
+ u8 min_delta_ftm;
+ u8 ftm_format_and_bw20M;
+ u8 ftm_format_and_bw40M;
+ u8 ftm_format_and_bw80M;
+} __packed;
+
+/**
+ * enum iwl_tof_location_query - values for query bitmap
+ * @IWL_TOF_LOC_LCI: query LCI
+ * @IWL_TOF_LOC_CIVIC: query civic
+ */
+enum iwl_tof_location_query {
+ IWL_TOF_LOC_LCI = 0x01,
+ IWL_TOF_LOC_CIVIC = 0x02,
+};
+
+ /**
+ * struct iwl_tof_range_req_ap_entry_v2 - AP configuration parameters
+ * @channel_num: Current AP Channel
+ * @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth.
+ * @tsf_delta_direction: TSF relatively to the subject AP
+ * @ctrl_ch_position: Coding of the control channel position relative to the
+ * center frequency, see iwl_mvm_get_ctrl_pos().
+ * @bssid: AP's BSSID
+ * @measure_type: Measurement type: 0 - two sided, 1 - One sided
+ * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of the
+ * number of measurement iterations (min 2^0 = 1, max 2^14)
+ * @burst_period: Recommended value to be sent to the AP. Measurement
+ * periodicity In units of 100ms. ignored if num_of_bursts = 0
+ * @samples_per_burst: 2-sided: the number of FTMs pairs in single Burst (1-31);
+ * 1-sided: how many rts/cts pairs should be used per burst.
+ * @retries_per_sample: Max number of retries that the LMAC should send
+ * in case of no replies by the AP.
+ * @tsf_delta: TSF Delta in units of microseconds.
+ * The difference between the AP TSF and the device local clock.
+ * @location_req: Location Request Bit[0] LCI should be sent in the FTMR;
+ * Bit[1] Civic should be sent in the FTMR
+ * @asap_mode: 0 - non asap mode, 1 - asap mode (not relevant for one sided)
+ * @enable_dyn_ack: Enable Dynamic ACK BW.
+ * 0: Initiator interact with regular AP;
+ * 1: Initiator interact with Responder machine: need to send the
+ * Initiator Acks with HT 40MHz / 80MHz, since the Responder should
+ * use it for its ch est measurement (this flag will be set when we
+ * configure the opposite machine to be Responder).
+ * @rssi: Last received value
+ * legal values: -128-0 (0x7f). above 0x0 indicating an invalid value.
+ * @algo_type: &enum iwl_tof_algo_type
+ * @notify_mcsi: &enum iwl_tof_mcsi_ntfy.
+ * @reserved: For alignment and future use
+ */
+struct iwl_tof_range_req_ap_entry_v2 {
+ u8 channel_num;
+ u8 bandwidth;
+ u8 tsf_delta_direction;
+ u8 ctrl_ch_position;
+ u8 bssid[ETH_ALEN];
+ u8 measure_type;
+ u8 num_of_bursts;
+ __le16 burst_period;
+ u8 samples_per_burst;
+ u8 retries_per_sample;
+ __le32 tsf_delta;
+ u8 location_req;
+ u8 asap_mode;
+ u8 enable_dyn_ack;
+ s8 rssi;
+ u8 algo_type;
+ u8 notify_mcsi;
+ __le16 reserved;
+} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_2 */
+
+/**
+ * enum iwl_initiator_ap_flags - per responder FTM configuration flags
+ * @IWL_INITIATOR_AP_FLAGS_ASAP: Request for ASAP measurement.
+ * @IWL_INITIATOR_AP_FLAGS_LCI_REQUEST: Request for LCI information
+ * @IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST: Request for CIVIC information
+ * @IWL_INITIATOR_AP_FLAGS_DYN_ACK: Send HT/VHT ack for FTM frames. If not set,
+ * 20Mhz dup acks will be sent.
+ * @IWL_INITIATOR_AP_FLAGS_ALGO_LR: Use LR algo type for rtt calculation.
+ * Default algo type is ML.
+ * @IWL_INITIATOR_AP_FLAGS_ALGO_FFT: Use FFT algo type for rtt calculation.
+ * Default algo type is ML.
+ * @IWL_INITIATOR_AP_FLAGS_MCSI_REPORT: Send the MCSI for each FTM frame to the
+ * driver.
+ */
+enum iwl_initiator_ap_flags {
+ IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
+ IWL_INITIATOR_AP_FLAGS_LCI_REQUEST = BIT(2),
+ IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST = BIT(3),
+ IWL_INITIATOR_AP_FLAGS_DYN_ACK = BIT(4),
+ IWL_INITIATOR_AP_FLAGS_ALGO_LR = BIT(5),
+ IWL_INITIATOR_AP_FLAGS_ALGO_FFT = BIT(6),
+ IWL_INITIATOR_AP_FLAGS_MCSI_REPORT = BIT(8),
+};
+
+/**
+ * struct iwl_tof_range_req_ap_entry - AP configuration parameters
+ * @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
+ * @channel_num: AP Channel number
+ * @bandwidth: AP bandwidth. One of iwl_tof_bandwidth.
+ * @ctrl_ch_position: Coding of the control channel position relative to the
+ * center frequency, see iwl_mvm_get_ctrl_pos().
+ * @ftmr_max_retries: Max number of retries to send the FTMR in case of no
+ * reply from the AP.
+ * @bssid: AP's BSSID
+ * @burst_period: Recommended value to be sent to the AP. Measurement
+ * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0
+ * @samples_per_burst: the number of FTMs pairs in single Burst (1-31);
+ * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
+ * the number of measurement iterations (min 2^0 = 1, max 2^14)
+ * @reserved: For alignment and future use
+ * @tsf_delta: not in use
+ */
+struct iwl_tof_range_req_ap_entry {
+ __le32 initiator_ap_flags;
+ u8 channel_num;
+ u8 bandwidth;
+ u8 ctrl_ch_position;
+ u8 ftmr_max_retries;
+ u8 bssid[ETH_ALEN];
+ __le16 burst_period;
+ u8 samples_per_burst;
+ u8 num_of_bursts;
+ __le16 reserved;
+ __le32 tsf_delta;
+} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */
+
+/**
+ * enum iwl_tof_response_mode
+ * @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as
+ * possible (not supported for this release)
+ * @IWL_MVM_TOF_RESPONSE_TIMEOUT: report all AP measurements as a batch upon
+ * timeout expiration
+ * @IWL_MVM_TOF_RESPONSE_COMPLETE: report all AP measurements as a batch at the
+ * earlier of: measurements completion / timeout
+ * expiration.
+ */
+enum iwl_tof_response_mode {
+ IWL_MVM_TOF_RESPONSE_ASAP,
+ IWL_MVM_TOF_RESPONSE_TIMEOUT,
+ IWL_MVM_TOF_RESPONSE_COMPLETE,
+};
+
+/**
+ * enum iwl_tof_initiator_flags
+ *
+ * @IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED: disable fast algo, meaning run
+ * the algo on ant A+B, instead of only one of them.
+ * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_A: open RX antenna A for FTMs RX
+ * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_B: open RX antenna B for FTMs RX
+ * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_C: open RX antenna C for FTMs RX
+ * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM
+ * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM
+ * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM
+ * @IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM: use random mac address for FTM
+ * @IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB: use the specific calib value from
+ * the range request command
+ * @IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB: use the common calib value from the
+ * ragne request command
+ * @IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT: support non-asap measurements
+ */
+enum iwl_tof_initiator_flags {
+ IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0),
+ IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_A = BIT(1),
+ IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_B = BIT(2),
+ IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_C = BIT(3),
+ IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4),
+ IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5),
+ IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6),
+ IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM = BIT(7),
+ IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB = BIT(15),
+ IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB = BIT(16),
+ IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT = BIT(20),
+}; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
+
+#define IWL_MVM_TOF_MAX_APS 5
+#define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5
+
+/**
+ * struct iwl_tof_range_req_cmd_v5 - start measurement cmd
+ * @initiator_flags: see flags @ iwl_tof_initiator_flags
+ * @request_id: A Token incremented per request. The same Token will be
+ * sent back in the range response
+ * @initiator: 0- NW initiated, 1 - Client Initiated
+ * @one_sided_los_disable: '0'- run ML-Algo for both ToF/OneSided,
+ * '1' - run ML-Algo for ToF only
+ * @req_timeout: Requested timeout of the response in units of 100ms.
+ * This is equivalent to the session time configured to the
+ * LMAC in Initiator Request
+ * @report_policy: Supported partially for this release: For current release -
+ * the range report will be uploaded as a batch when ready or
+ * when the session is done (successfully / partially).
+ * one of iwl_tof_response_mode.
+ * @reserved0: reserved
+ * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
+ * @macaddr_random: '0' Use default source MAC address (i.e. p2_p),
+ * '1' Use MAC Address randomization according to the below
+ * @range_req_bssid: ranging request BSSID
+ * @macaddr_template: MAC address template to use for non-randomized bits
+ * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
+ * Bits set to 1 shall be randomized by the UMAC
+ * @ftm_rx_chains: Rx chain to open to receive Responder's FTMs (XVT)
+ * @ftm_tx_chains: Tx chain to send the ack to the Responder FTM (XVT)
+ * @common_calib: The common calib value to inject to this measurement calc
+ * @specific_calib: The specific calib value to inject to this measurement calc
+ * @ap: per-AP request data
+ */
+struct iwl_tof_range_req_cmd_v5 {
+ __le32 initiator_flags;
+ u8 request_id;
+ u8 initiator;
+ u8 one_sided_los_disable;
+ u8 req_timeout;
+ u8 report_policy;
+ u8 reserved0;
+ u8 num_of_ap;
+ u8 macaddr_random;
+ u8 range_req_bssid[ETH_ALEN];
+ u8 macaddr_template[ETH_ALEN];
+ u8 macaddr_mask[ETH_ALEN];
+ u8 ftm_rx_chains;
+ u8 ftm_tx_chains;
+ __le16 common_calib;
+ __le16 specific_calib;
+ struct iwl_tof_range_req_ap_entry_v2 ap[IWL_MVM_TOF_MAX_APS];
+} __packed;
+/* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
+
+/**
+ * struct iwl_tof_range_req_cmd - start measurement cmd
+ * @initiator_flags: see flags @ iwl_tof_initiator_flags
+ * @request_id: A Token incremented per request. The same Token will be
+ * sent back in the range response
+ * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
+ * @range_req_bssid: ranging request BSSID
+ * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
+ * Bits set to 1 shall be randomized by the UMAC
+ * @macaddr_template: MAC address template to use for non-randomized bits
+ * @req_timeout_ms: Requested timeout of the response in units of milliseconds.
+ * This is the session time for completing the measurement.
+ * @tsf_mac_id: report the measurement start time for each ap in terms of the
+ * TSF of this mac id. 0xff to disable TSF reporting.
+ * @common_calib: The common calib value to inject to this measurement calc
+ * @specific_calib: The specific calib value to inject to this measurement calc
+ * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2.
+ */
+struct iwl_tof_range_req_cmd {
+ __le32 initiator_flags;
+ u8 request_id;
+ u8 num_of_ap;
+ u8 range_req_bssid[ETH_ALEN];
+ u8 macaddr_mask[ETH_ALEN];
+ u8 macaddr_template[ETH_ALEN];
+ __le32 req_timeout_ms;
+ __le32 tsf_mac_id;
+ __le16 common_calib;
+ __le16 specific_calib;
+ struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS];
+} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */
+
+/*
+ * enum iwl_tof_range_request_status - status of the sent request
+ * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the
+ * request
+ * @IWL_TOF_RANGE_REQUEST_STATUS_BUSY - FW is busy with a previous request, the
+ * sent request will not be handled
+ */
+enum iwl_tof_range_request_status {
+ IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS,
+ IWL_TOF_RANGE_REQUEST_STATUS_BUSY,
+};
+
+/**
+ * enum iwl_tof_entry_status
+ *
+ * @IWL_TOF_ENTRY_SUCCESS: successful measurement.
+ * @IWL_TOF_ENTRY_GENERAL_FAILURE: General failure.
+ * @IWL_TOF_ENTRY_NO_RESPONSE: Responder didn't reply to the request.
+ * @IWL_TOF_ENTRY_REQUEST_REJECTED: Responder rejected the request.
+ * @IWL_TOF_ENTRY_NOT_SCHEDULED: Time event was scheduled but not called yet.
+ * @IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT: Time event triggered but no
+ * measurement was completed.
+ * @IWL_TOF_ENTRY_TARGET_DIFF_CH_CANNOT_CHANGE: No range due inability to switch
+ * from the primary channel.
+ * @IWL_TOF_ENTRY_RANGE_NOT_SUPPORTED: Device doesn't support FTM.
+ * @IWL_TOF_ENTRY_REQUEST_ABORT_UNKNOWN_REASON: Request aborted due to unknown
+ * reason.
+ * @IWL_TOF_ENTRY_LOCATION_INVALID_T1_T4_TIME_STAMP: Failure due to invalid
+ * T1/T4.
+ * @IWL_TOF_ENTRY_11MC_PROTOCOL_FAILURE: Failure due to invalid FTM frame
+ * structure.
+ * @IWL_TOF_ENTRY_REQUEST_CANNOT_SCHED: Request cannot be scheduled.
+ * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE: Responder cannot serve the
+ * initiator for some period, period supplied in @refusal_period.
+ * @IWL_TOF_ENTRY_BAD_REQUEST_ARGS: Bad request arguments.
+ * @IWL_TOF_ENTRY_WIFI_NOT_ENABLED: Wifi not enabled.
+ * @IWL_TOF_ENTRY_RESPONDER_OVERRIDE_PARAMS: Responder override the original
+ * parameters within the current session.
+ */
+enum iwl_tof_entry_status {
+ IWL_TOF_ENTRY_SUCCESS = 0,
+ IWL_TOF_ENTRY_GENERAL_FAILURE = 1,
+ IWL_TOF_ENTRY_NO_RESPONSE = 2,
+ IWL_TOF_ENTRY_REQUEST_REJECTED = 3,
+ IWL_TOF_ENTRY_NOT_SCHEDULED = 4,
+ IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT = 5,
+ IWL_TOF_ENTRY_TARGET_DIFF_CH_CANNOT_CHANGE = 6,
+ IWL_TOF_ENTRY_RANGE_NOT_SUPPORTED = 7,
+ IWL_TOF_ENTRY_REQUEST_ABORT_UNKNOWN_REASON = 8,
+ IWL_TOF_ENTRY_LOCATION_INVALID_T1_T4_TIME_STAMP = 9,
+ IWL_TOF_ENTRY_11MC_PROTOCOL_FAILURE = 10,
+ IWL_TOF_ENTRY_REQUEST_CANNOT_SCHED = 11,
+ IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE = 12,
+ IWL_TOF_ENTRY_BAD_REQUEST_ARGS = 13,
+ IWL_TOF_ENTRY_WIFI_NOT_ENABLED = 14,
+ IWL_TOF_ENTRY_RESPONDER_OVERRIDE_PARAMS = 15,
+}; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */
+
+/**
+ * struct iwl_tof_range_rsp_ap_entry_ntfy_v3 - AP parameters (response)
+ * @bssid: BSSID of the AP
+ * @measure_status: current APs measurement status, one of
+ * &enum iwl_tof_entry_status.
+ * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
+ * @rtt: The Round Trip Time that took for the last measurement for
+ * current AP [pSec]
+ * @rtt_variance: The Variance of the RTT values measured for current AP
+ * @rtt_spread: The Difference between the maximum and the minimum RTT
+ * values measured for current AP in the current session [pSec]
+ * @rssi: RSSI as uploaded in the Channel Estimation notification
+ * @rssi_spread: The Difference between the maximum and the minimum RSSI values
+ * measured for current AP in the current session
+ * @reserved: reserved
+ * @refusal_period: refusal period in case of
+ * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
+ * @range: Measured range [cm]
+ * @range_variance: Measured range variance [cm]
+ * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
+ * uploaded by the LMAC
+ * @t2t3_initiator: as calculated from the algo in the initiator
+ * @t1t4_responder: as calculated from the algo in the responder
+ * @common_calib: Calib val that was used in for this AP measurement
+ * @specific_calib: val that was used in for this AP measurement
+ * @papd_calib_output: The result of the tof papd calibration that was injected
+ * into the algorithm.
+ */
+struct iwl_tof_range_rsp_ap_entry_ntfy_v3 {
+ u8 bssid[ETH_ALEN];
+ u8 measure_status;
+ u8 measure_bw;
+ __le32 rtt;
+ __le32 rtt_variance;
+ __le32 rtt_spread;
+ s8 rssi;
+ u8 rssi_spread;
+ u8 reserved;
+ u8 refusal_period;
+ __le32 range;
+ __le32 range_variance;
+ __le32 timestamp;
+ __le32 t2t3_initiator;
+ __le32 t1t4_responder;
+ __le16 common_calib;
+ __le16 specific_calib;
+ __le32 papd_calib_output;
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */
+
+/**
+ * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
+ * @bssid: BSSID of the AP
+ * @measure_status: current APs measurement status, one of
+ * &enum iwl_tof_entry_status.
+ * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
+ * @rtt: The Round Trip Time that took for the last measurement for
+ * current AP [pSec]
+ * @rtt_variance: The Variance of the RTT values measured for current AP
+ * @rtt_spread: The Difference between the maximum and the minimum RTT
+ * values measured for current AP in the current session [pSec]
+ * @rssi: RSSI as uploaded in the Channel Estimation notification
+ * @rssi_spread: The Difference between the maximum and the minimum RSSI values
+ * measured for current AP in the current session
+ * @last_burst: 1 if no more FTM sessions are scheduled for this responder
+ * @refusal_period: refusal period in case of
+ * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
+ * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
+ * uploaded by the LMAC
+ * @start_tsf: measurement start time in TSF of the mac specified in the range
+ * request
+ * @rx_rate_n_flags: rate and flags of the last FTM frame received from this
+ * responder
+ * @tx_rate_n_flags: rate and flags of the last ack sent to this responder
+ * @t2t3_initiator: as calculated from the algo in the initiator
+ * @t1t4_responder: as calculated from the algo in the responder
+ * @common_calib: Calib val that was used in for this AP measurement
+ * @specific_calib: val that was used in for this AP measurement
+ * @papd_calib_output: The result of the tof papd calibration that was injected
+ * into the algorithm.
+ */
+struct iwl_tof_range_rsp_ap_entry_ntfy {
+ u8 bssid[ETH_ALEN];
+ u8 measure_status;
+ u8 measure_bw;
+ __le32 rtt;
+ __le32 rtt_variance;
+ __le32 rtt_spread;
+ s8 rssi;
+ u8 rssi_spread;
+ u8 last_burst;
+ u8 refusal_period;
+ __le32 timestamp;
+ __le32 start_tsf;
+ __le32 rx_rate_n_flags;
+ __le32 tx_rate_n_flags;
+ __le32 t2t3_initiator;
+ __le32 t1t4_responder;
+ __le16 common_calib;
+ __le16 specific_calib;
+ __le32 papd_calib_output;
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */
+
+/**
+ * enum iwl_tof_response_status - tof response status
+ *
+ * @IWL_TOF_RESPONSE_SUCCESS: successful range.
+ * @IWL_TOF_RESPONSE_TIMEOUT: request aborted due to timeout expiration.
+ * partial result of ranges done so far is included in the response.
+ * @IWL_TOF_RESPONSE_ABORTED: Measurement aborted by command.
+ * @IWL_TOF_RESPONSE_FAILED: Measurement request command failed.
+ */
+enum iwl_tof_response_status {
+ IWL_TOF_RESPONSE_SUCCESS = 0,
+ IWL_TOF_RESPONSE_TIMEOUT = 1,
+ IWL_TOF_RESPONSE_ABORTED = 4,
+ IWL_TOF_RESPONSE_FAILED = 5,
+}; /* LOCATION_RNG_RSP_STATUS */
+
+/**
+ * struct iwl_tof_range_rsp_ntfy_v5 - ranging response notification
+ * @request_id: A Token ID of the corresponding Range request
+ * @request_status: status of current measurement session, one of
+ * &enum iwl_tof_response_status.
+ * @last_in_batch: reprot policy (when not all responses are uploaded at once)
+ * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
+ * @ap: per-AP data
+ */
+struct iwl_tof_range_rsp_ntfy_v5 {
+ u8 request_id;
+ u8 request_status;
+ u8 last_in_batch;
+ u8 num_of_aps;
+ struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_MVM_TOF_MAX_APS];
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */
+
+/**
+ * struct iwl_tof_range_rsp_ntfy - ranging response notification
+ * @request_id: A Token ID of the corresponding Range request
+ * @num_of_aps: Number of APs results
+ * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
+ * @reserved: reserved
+ * @ap: per-AP data
+ */
+struct iwl_tof_range_rsp_ntfy {
+ u8 request_id;
+ u8 num_of_aps;
+ u8 last_report;
+ u8 reserved;
+ struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS];
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */
+
+#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
+/**
+ * struct iwl_tof_mcsi_notif - used for debug
+ * @token: token ID for the current session
+ * @role: '0' - initiator, '1' - responder
+ * @reserved: reserved
+ * @initiator_bssid: initiator machine
+ * @responder_bssid: responder machine
+ * @mcsi_buffer: debug data
+ */
+struct iwl_tof_mcsi_notif {
+ u8 token;
+ u8 role;
+ __le16 reserved;
+ u8 initiator_bssid[ETH_ALEN];
+ u8 responder_bssid[ETH_ALEN];
+ u8 mcsi_buffer[IWL_MVM_TOF_MCSI_BUF_SIZE * 4];
+} __packed;
+
+/**
+ * struct iwl_tof_range_abort_cmd
+ * @request_id: corresponds to a range request
+ * @reserved: reserved
+ */
+struct iwl_tof_range_abort_cmd {
+ u8 request_id;
+ u8 reserved[3];
+} __packed;
+
+enum ftm_responder_stats_flags {
+ FTM_RESP_STAT_NON_ASAP_STARTED = BIT(0),
+ FTM_RESP_STAT_NON_ASAP_IN_WIN = BIT(1),
+ FTM_RESP_STAT_NON_ASAP_OUT_WIN = BIT(2),
+ FTM_RESP_STAT_TRIGGER_DUP = BIT(3),
+ FTM_RESP_STAT_DUP = BIT(4),
+ FTM_RESP_STAT_DUP_IN_WIN = BIT(5),
+ FTM_RESP_STAT_DUP_OUT_WIN = BIT(6),
+ FTM_RESP_STAT_SCHED_SUCCESS = BIT(7),
+ FTM_RESP_STAT_ASAP_REQ = BIT(8),
+ FTM_RESP_STAT_NON_ASAP_REQ = BIT(9),
+ FTM_RESP_STAT_ASAP_RESP = BIT(10),
+ FTM_RESP_STAT_NON_ASAP_RESP = BIT(11),
+ FTM_RESP_STAT_FAIL_INITIATOR_INACTIVE = BIT(12),
+ FTM_RESP_STAT_FAIL_INITIATOR_OUT_WIN = BIT(13),
+ FTM_RESP_STAT_FAIL_INITIATOR_RETRY_LIM = BIT(14),
+ FTM_RESP_STAT_FAIL_NEXT_SERVED = BIT(15),
+ FTM_RESP_STAT_FAIL_TRIGGER_ERR = BIT(16),
+ FTM_RESP_STAT_FAIL_GC = BIT(17),
+ FTM_RESP_STAT_SUCCESS = BIT(18),
+ FTM_RESP_STAT_INTEL_IE = BIT(19),
+ FTM_RESP_STAT_INITIATOR_ACTIVE = BIT(20),
+ FTM_RESP_STAT_MEASUREMENTS_AVAILABLE = BIT(21),
+ FTM_RESP_STAT_TRIGGER_UNKNOWN = BIT(22),
+ FTM_RESP_STAT_PROCESS_FAIL = BIT(23),
+ FTM_RESP_STAT_ACK = BIT(24),
+ FTM_RESP_STAT_NACK = BIT(25),
+ FTM_RESP_STAT_INVALID_INITIATOR_ID = BIT(26),
+ FTM_RESP_STAT_TIMER_MIN_DELTA = BIT(27),
+ FTM_RESP_STAT_INITIATOR_REMOVED = BIT(28),
+ FTM_RESP_STAT_INITIATOR_ADDED = BIT(29),
+ FTM_RESP_STAT_ERR_LIST_FULL = BIT(30),
+ FTM_RESP_STAT_INITIATOR_SCHED_NOW = BIT(31),
+}; /* RESP_IND_E */
+
+/**
+ * struct iwl_ftm_responder_stats - FTM responder statistics
+ * @addr: initiator address
+ * @success_ftm: number of successful ftm frames
+ * @ftm_per_burst: num of FTM frames that were received
+ * @flags: &enum ftm_responder_stats_flags
+ * @duration: actual duration of FTM
+ * @allocated_duration: time that was allocated for this FTM session
+ * @bw: FTM request bandwidth
+ * @rate: FTM request rate
+ * @reserved: for alingment and future use
+ */
+struct iwl_ftm_responder_stats {
+ u8 addr[ETH_ALEN];
+ u8 success_ftm;
+ u8 ftm_per_burst;
+ __le32 flags;
+ __le32 duration;
+ __le32 allocated_duration;
+ u8 bw;
+ u8 rate;
+ __le16 reserved;
+} __packed; /* TOF_RESPONDER_STATISTICS_NTFY_S_VER_2 */
+
+#define IWL_CSI_CHUNK_CTL_NUM_MASK 0x3
+#define IWL_CSI_CHUNK_CTL_IDX_MASK 0xc
+
+struct iwl_csi_chunk_notification {
+ __le32 token;
+ __le16 seq;
+ __le16 ctl;
+ __le32 size;
+ u8 data[];
+} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1 */
+
+#endif /* __iwl_fw_api_location_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index ca49db786ed6..6b4d59daacd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -74,6 +74,10 @@ enum iwl_mac_conf_subcmd_ids {
*/
LOW_LATENCY_CMD = 0x3,
/**
+ * @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd
+ */
+ CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4,
+ /**
* @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif
*/
PROBE_RESPONSE_DATA_NOTIF = 0xFC,
@@ -136,6 +140,29 @@ struct iwl_channel_switch_noa_notif {
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
/**
+ * struct iwl_chan_switch_te_cmd - Channel Switch Time Event command
+ *
+ * @mac_id: MAC ID for channel switch
+ * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @tsf: beacon tsf
+ * @cs_count: channel switch count from CSA/eCSA IE
+ * @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals
+ * at the new channel after the channel switch, otherwise (N == 0) expect
+ * beacon right after the channel switch.
+ * @cs_mode: 1 - quiet, 0 - otherwise
+ * @reserved: reserved for alignment purposes
+ */
+struct iwl_chan_switch_te_cmd {
+ __le32 mac_id;
+ __le32 action;
+ __le32 tsf;
+ u8 cs_count;
+ u8 cs_delayed_bcn_count;
+ u8 cs_mode;
+ u8 reserved;
+} __packed; /* MAC_CHANNEL_SWITCH_TIME_EVENT_S_VER_2 */
+
+/**
* struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode'
*
* @mac_id: MAC ID to whom to apply the low-latency configurations
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index 7a3f7b7e6358..941c50477003 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -29,7 +29,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -433,6 +433,28 @@ struct iwl_he_backoff_conf {
__le16 mu_time;
} __packed; /* AC_QOS_DOT11AX_API_S */
+/**
+ * enum iwl_he_pkt_ext_constellations - PPE constellation indices
+ * @IWL_HE_PKT_EXT_BPSK: BPSK
+ * @IWL_HE_PKT_EXT_QPSK: QPSK
+ * @IWL_HE_PKT_EXT_16QAM: 16-QAM
+ * @IWL_HE_PKT_EXT_64QAM: 64-QAM
+ * @IWL_HE_PKT_EXT_256QAM: 256-QAM
+ * @IWL_HE_PKT_EXT_1024QAM: 1024-QAM
+ * @IWL_HE_PKT_EXT_RESERVED: reserved value
+ * @IWL_HE_PKT_EXT_NONE: not defined
+ */
+enum iwl_he_pkt_ext_constellations {
+ IWL_HE_PKT_EXT_BPSK = 0,
+ IWL_HE_PKT_EXT_QPSK,
+ IWL_HE_PKT_EXT_16QAM,
+ IWL_HE_PKT_EXT_64QAM,
+ IWL_HE_PKT_EXT_256QAM,
+ IWL_HE_PKT_EXT_1024QAM,
+ IWL_HE_PKT_EXT_RESERVED,
+ IWL_HE_PKT_EXT_NONE,
+};
+
#define MAX_HE_SUPP_NSS 2
#define MAX_HE_CHANNEL_BW_INDX 4
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
index 45f61c6af14e..b833b80ea3d6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -95,17 +97,36 @@
#define PHY_VHT_CTRL_POS_4_ABOVE (0x7)
/*
+ * struct iwl_fw_channel_info_v1 - channel information
+ *
* @band: PHY_BAND_*
* @channel: channel number
* @width: PHY_[VHT|LEGACY]_CHANNEL_*
* @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*
*/
-struct iwl_fw_channel_info {
+struct iwl_fw_channel_info_v1 {
u8 band;
u8 channel;
u8 width;
u8 ctrl_pos;
-} __packed;
+} __packed; /* CHANNEL_CONFIG_API_S_VER_1 */
+
+/*
+ * struct iwl_fw_channel_info - channel information
+ *
+ * @channel: channel number
+ * @band: PHY_BAND_*
+ * @width: PHY_[VHT|LEGACY]_CHANNEL_*
+ * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*
+ * @reserved: for future use and alignment
+ */
+struct iwl_fw_channel_info {
+ __le32 channel;
+ u8 band;
+ u8 width;
+ u8 ctrl_pos;
+ u8 reserved;
+} __packed; /*CHANNEL_CONFIG_API_S_VER_2 */
#define PHY_RX_CHAIN_DRIVER_FORCE_POS (0)
#define PHY_RX_CHAIN_DRIVER_FORCE_MSK \
@@ -134,6 +155,22 @@ struct iwl_fw_channel_info {
/* TODO: complete missing documentation */
/**
+ * struct iwl_phy_context_cmd_tail - tail of iwl_phy_ctx_cmd for alignment with
+ * various channel structures.
+ *
+ * @txchain_info: ???
+ * @rxchain_info: ???
+ * @acquisition_data: ???
+ * @dsp_cfg_flags: set to 0
+ */
+struct iwl_phy_context_cmd_tail {
+ __le32 txchain_info;
+ __le32 rxchain_info;
+ __le32 acquisition_data;
+ __le32 dsp_cfg_flags;
+} __packed;
+
+/**
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
@@ -142,10 +179,7 @@ struct iwl_fw_channel_info {
* other value means apply new params after X usecs
* @tx_param_color: ???
* @ci: channel info
- * @txchain_info: ???
- * @rxchain_info: ???
- * @acquisition_data: ???
- * @dsp_cfg_flags: set to 0
+ * @tail: command tail
*/
struct iwl_phy_context_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
@@ -155,10 +189,7 @@ struct iwl_phy_context_cmd {
__le32 apply_time;
__le32 tx_param_color;
struct iwl_fw_channel_info ci;
- __le32 txchain_info;
- __le32 rxchain_info;
- __le32 acquisition_data;
- __le32 dsp_cfg_flags;
+ struct iwl_phy_context_cmd_tail tail;
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
#endif /* __iwl_fw_api_phy_ctxt_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index 286a22da232d..01f003c6cff9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -200,9 +200,16 @@ struct iwl_powertable_cmd {
* @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
* '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
+ * @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK:
+ * Device Retention indication, '1' indicate retention is enabled.
+ * @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK:
+ * 32Khz external slow clock valid indication, '1' indicate cloack is
+ * valid.
*/
enum iwl_device_power_flags {
- DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
+ DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
+ DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1),
+ DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12),
};
/**
@@ -470,6 +477,13 @@ struct iwl_geo_tx_power_profiles_resp {
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
* for a longer period of time then this escape-timeout. Units: Beacons.
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
+ * @bf_threshold_absolute_low: See below.
+ * @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated
+ * for this beacon crossed this absolute threshold. For the 'Increase'
+ * direction the bf_energy_absolute_low[i] is used. For the 'Decrease'
+ * direction the bf_energy_absolute_high[i] is used. Zero value means
+ * that this specific threshold is ignored for beacon filtering, and
+ * beacon will not be forced to be sent to driver due to this setting.
*/
struct iwl_beacon_filter_cmd {
__le32 bf_energy_delta;
@@ -483,7 +497,9 @@ struct iwl_beacon_filter_cmd {
__le32 bf_escape_timer;
__le32 ba_escape_timer;
__le32 ba_enable_beacon_abort;
-} __packed;
+ __le32 bf_threshold_absolute_low[2];
+ __le32 bf_threshold_absolute_high[2];
+} __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */
/* Beacon filtering and beacon abort */
#define IWL_BF_ENERGY_DELTA_DEFAULT 5
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index 0791a854fc8f..6e8224ce8906 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -209,8 +209,6 @@ enum iwl_rx_phy_flags {
* @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
* @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask
* @RX_MDPU_RES_STATUS_STA_ID_SHIFT: station ID bit shift
- * @RX_MPDU_RES_STATUS_FILTERING_MSK: filter status
- * @RX_MPDU_RES_STATUS2_FILTERING_MSK: filter status 2
*/
enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
@@ -238,8 +236,6 @@ enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24,
RX_MPDU_RES_STATUS_STA_ID_MSK = 0x1f << RX_MDPU_RES_STATUS_STA_ID_SHIFT,
- RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
- RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
};
/* 9000 series API */
@@ -337,6 +333,8 @@ enum iwl_rx_mpdu_phy_info {
IWL_RX_MPDU_PHY_AMPDU = BIT(5),
IWL_RX_MPDU_PHY_AMPDU_TOGGLE = BIT(6),
IWL_RX_MPDU_PHY_SHORT_PREAMBLE = BIT(7),
+ /* short preamble is only for CCK, for non-CCK overridden by this */
+ IWL_RX_MPDU_PHY_NCCK_ADDTL_NTFY = BIT(7),
IWL_RX_MPDU_PHY_TSF_OVERLOAD = BIT(8),
};
@@ -723,6 +721,9 @@ struct iwl_rx_mpdu_desc {
#define RX_NO_DATA_FRAME_TIME_POS 0
#define RX_NO_DATA_FRAME_TIME_MSK (0xfffff << RX_NO_DATA_FRAME_TIME_POS)
+#define RX_NO_DATA_RX_VEC0_HE_NSTS_MSK 0x03800000
+#define RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK 0x38000000
+
/**
* struct iwl_rx_no_data - RX no data descriptor
* @info: 7:0 frame type, 15:8 RX error type
@@ -743,7 +744,7 @@ struct iwl_rx_no_data {
__le32 fr_time;
__le32 rate;
__le32 phy_info[2];
- __le32 rx_vec[3];
+ __le32 rx_vec[2];
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 18741889ec30..890a939c463d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -434,7 +434,7 @@ struct iwl_periodic_scan_complete {
/* The maximum of either of these cannot exceed 8, because we use an
* 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h).
*/
-#define IWL_MVM_MAX_UMAC_SCANS 8
+#define IWL_MVM_MAX_UMAC_SCANS 4
#define IWL_MVM_MAX_LMAC_SCANS 1
enum scan_config_flags {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
index 53cb622aa9ab..318843138490 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* 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
@@ -29,6 +30,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -363,14 +365,7 @@ struct mvm_statistics_general_v8 {
u8 reserved[4 - (NUM_MAC_INDEX % 4)];
} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
-struct mvm_statistics_general_cdb_v9 {
- struct mvm_statistics_general_common_v19 common;
- __le32 beacon_counter[NUM_MAC_INDEX_CDB];
- u8 beacon_average_energy[NUM_MAC_INDEX_CDB];
- u8 reserved[4 - (NUM_MAC_INDEX_CDB % 4)];
-} __packed; /* STATISTICS_GENERAL_API_S_VER_9 */
-
-struct mvm_statistics_general_cdb {
+struct mvm_statistics_general {
struct mvm_statistics_general_common common;
__le32 beacon_counter[MAC_INDEX_AUX];
u8 beacon_average_energy[MAC_INDEX_AUX];
@@ -435,11 +430,11 @@ struct iwl_notif_statistics_v11 {
struct mvm_statistics_load_v1 load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_11 */
-struct iwl_notif_statistics_cdb {
+struct iwl_notif_statistics {
__le32 flag;
struct mvm_statistics_rx rx;
struct mvm_statistics_tx tx;
- struct mvm_statistics_general_cdb general;
+ struct mvm_statistics_general general;
struct mvm_statistics_load load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_13 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
index 7c6c2462d0e8..b089285ac466 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,6 +113,17 @@ struct iwl_tdls_channel_switch_frame {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
/**
+ * struct iwl_tdls_channel_switch_cmd_tail - tail of iwl_tdls_channel_switch_cmd
+ *
+ * @timing: timing related data for command
+ * @frame: channel-switch request/response template, depending to switch_type
+ */
+struct iwl_tdls_channel_switch_cmd_tail {
+ struct iwl_tdls_channel_switch_timing timing;
+ struct iwl_tdls_channel_switch_frame frame;
+} __packed;
+
+/**
* struct iwl_tdls_channel_switch_cmd - TDLS channel switch command
*
* The command is sent to initiate a channel switch and also in response to
@@ -119,15 +132,13 @@ struct iwl_tdls_channel_switch_frame {
* @switch_type: see &enum iwl_tdls_channel_switch_type
* @peer_sta_id: station id of TDLS peer
* @ci: channel we switch to
- * @timing: timing related data for command
- * @frame: channel-switch request/response template, depending to switch_type
+ * @tail: command tail
*/
struct iwl_tdls_channel_switch_cmd {
u8 switch_type;
__le32 peer_sta_id;
struct iwl_fw_channel_info ci;
- struct iwl_tdls_channel_switch_timing timing;
- struct iwl_tdls_channel_switch_frame frame;
+ struct iwl_tdls_channel_switch_cmd_tail tail;
} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
index f824bebceb06..4621ef93a2cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -318,6 +320,25 @@ struct iwl_time_event_notif {
} __packed; /* MAC_TIME_EVENT_NTFY_API_S_VER_1 */
/*
+ * struct iwl_hs20_roc_req_tail - tail of iwl_hs20_roc_req
+ *
+ * @node_addr: Our MAC Address
+ * @reserved: reserved for alignment
+ * @apply_time: GP2 value to start (should always be the current GP2 value)
+ * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
+ * time by which start of the event is allowed to be postponed.
+ * @duration: event duration in TU To calculate event duration:
+ * timeEventDuration = min(duration, remainingQuota)
+ */
+struct iwl_hs20_roc_req_tail {
+ u8 node_addr[ETH_ALEN];
+ __le16 reserved;
+ __le32 apply_time;
+ __le32 apply_time_max_delay;
+ __le32 duration;
+} __packed;
+
+/*
* Aux ROC command
*
* Command requests the firmware to create a time event for a certain duration
@@ -336,13 +357,6 @@ struct iwl_time_event_notif {
* @sta_id_and_color: station id and color, resumed during "Remain On Channel"
* activity.
* @channel_info: channel info
- * @node_addr: Our MAC Address
- * @reserved: reserved for alignment
- * @apply_time: GP2 value to start (should always be the current GP2 value)
- * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
- * time by which start of the event is allowed to be postponed.
- * @duration: event duration in TU To calculate event duration:
- * timeEventDuration = min(duration, remainingQuota)
*/
struct iwl_hs20_roc_req {
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
@@ -351,11 +365,7 @@ struct iwl_hs20_roc_req {
__le32 event_unique_id;
__le32 sta_id_and_color;
struct iwl_fw_channel_info channel_info;
- u8 node_addr[ETH_ALEN];
- __le16 reserved;
- __le32 apply_time;
- __le32 apply_time_max_delay;
- __le32 duration;
+ struct iwl_hs20_roc_req_tail tail;
} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h
deleted file mode 100644
index 7328a1606146..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2015 - 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- * Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * All rights reserved.
- *
- * 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 Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 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
- * OWNER 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 __iwl_fw_api_tof_h__
-#define __iwl_fw_api_tof_h__
-
-/* ToF sub-group command IDs */
-enum iwl_mvm_tof_sub_grp_ids {
- TOF_RANGE_REQ_CMD = 0x1,
- TOF_CONFIG_CMD = 0x2,
- TOF_RANGE_ABORT_CMD = 0x3,
- TOF_RANGE_REQ_EXT_CMD = 0x4,
- TOF_RESPONDER_CONFIG_CMD = 0x5,
- TOF_NW_INITIATED_RES_SEND_CMD = 0x6,
- TOF_NEIGHBOR_REPORT_REQ_CMD = 0x7,
- TOF_NEIGHBOR_REPORT_RSP_NOTIF = 0xFC,
- TOF_NW_INITIATED_REQ_RCVD_NOTIF = 0xFD,
- TOF_RANGE_RESPONSE_NOTIF = 0xFE,
- TOF_MCSI_DEBUG_NOTIF = 0xFB,
-};
-
-/**
- * struct iwl_tof_config_cmd - ToF configuration
- * @tof_disabled: 0 enabled, 1 - disabled
- * @one_sided_disabled: 0 enabled, 1 - disabled
- * @is_debug_mode: 1 debug mode, 0 - otherwise
- * @is_buf_required: 1 channel estimation buffer required, 0 - otherwise
- */
-struct iwl_tof_config_cmd {
- __le32 sub_grp_cmd_id;
- u8 tof_disabled;
- u8 one_sided_disabled;
- u8 is_debug_mode;
- u8 is_buf_required;
-} __packed;
-
-/**
- * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug)
- * @burst_period: future use: (currently hard coded in the LMAC)
- * The interval between two sequential bursts.
- * @min_delta_ftm: future use: (currently hard coded in the LMAC)
- * The minimum delay between two sequential FTM Responses
- * in the same burst.
- * @burst_duration: future use: (currently hard coded in the LMAC)
- * The total time for all FTMs handshake in the same burst.
- * Affect the time events duration in the LMAC.
- * @num_of_burst_exp: future use: (currently hard coded in the LMAC)
- * The number of bursts for the current ToF request. Affect
- * the number of events allocations in the current iteration.
- * @get_ch_est: for xVT only, NA for driver
- * @abort_responder: when set to '1' - Responder will terminate its activity
- * (all other fields in the command are ignored)
- * @recv_sta_req_params: 1 - Responder will ignore the other Responder's
- * params and use the recomended Initiator params.
- * 0 - otherwise
- * @channel_num: current AP Channel
- * @bandwidth: current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
- * @rate: current AP rate
- * @ctrl_ch_position: coding of the control channel position relative to
- * the center frequency:
- *
- * 40 MHz
- * 0 below center, 1 above center
- *
- * 80 MHz
- * bits [0..1]
- * * 0 the near 20MHz to the center,
- * * 1 the far 20MHz to the center
- * bit[2]
- * as above 40MHz
- * @ftm_per_burst: FTMs per Burst
- * @ftm_resp_ts_avail: '0' - we don't measure over the Initial FTM Response,
- * '1' - we measure over the Initial FTM Response
- * @asap_mode: ASAP / Non ASAP mode for the current WLS station
- * @sta_id: index of the AP STA when in AP mode
- * @tsf_timer_offset_msecs: The dictated time offset (mSec) from the AP's TSF
- * @toa_offset: Artificial addition [0.1nsec] for the ToA - to be used for debug
- * purposes, simulating station movement by adding various values
- * to this field
- * @bssid: Current AP BSSID
- */
-struct iwl_tof_responder_config_cmd {
- __le32 sub_grp_cmd_id;
- __le16 burst_period;
- u8 min_delta_ftm;
- u8 burst_duration;
- u8 num_of_burst_exp;
- u8 get_ch_est;
- u8 abort_responder;
- u8 recv_sta_req_params;
- u8 channel_num;
- u8 bandwidth;
- u8 rate;
- u8 ctrl_ch_position;
- u8 ftm_per_burst;
- u8 ftm_resp_ts_avail;
- u8 asap_mode;
- u8 sta_id;
- __le16 tsf_timer_offset_msecs;
- __le16 toa_offset;
- u8 bssid[ETH_ALEN];
-} __packed;
-
-/**
- * struct iwl_tof_range_request_ext_cmd - extended range req for WLS
- * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF
- * @reserved: reserved
- * @min_delta_ftm: Minimal time between two consecutive measurements,
- * in units of 100us. 0 means no preference by station
- * @ftm_format_and_bw20M: FTM Channel Spacing/Format for 20MHz: recommended
- * value be sent to the AP
- * @ftm_format_and_bw40M: FTM Channel Spacing/Format for 40MHz: recommended
- * value to be sent to the AP
- * @ftm_format_and_bw80M: FTM Channel Spacing/Format for 80MHz: recommended
- * value to be sent to the AP
- */
-struct iwl_tof_range_req_ext_cmd {
- __le32 sub_grp_cmd_id;
- __le16 tsf_timer_offset_msec;
- __le16 reserved;
- u8 min_delta_ftm;
- u8 ftm_format_and_bw20M;
- u8 ftm_format_and_bw40M;
- u8 ftm_format_and_bw80M;
-} __packed;
-
-#define IWL_MVM_TOF_MAX_APS 21
-
-/**
- * struct iwl_tof_range_req_ap_entry - AP configuration parameters
- * @channel_num: Current AP Channel
- * @bandwidth: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
- * @tsf_delta_direction: TSF relatively to the subject AP
- * @ctrl_ch_position: Coding of the control channel position relative to the
- * center frequency.
- * 40MHz 0 below center, 1 above center
- * 80MHz bits [0..1]: 0 the near 20MHz to the center,
- * 1 the far 20MHz to the center
- * bit[2] as above 40MHz
- * @bssid: AP's bss id
- * @measure_type: Measurement type: 0 - two sided, 1 - One sided
- * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of the
- * number of measurement iterations (min 2^0 = 1, max 2^14)
- * @burst_period: Recommended value to be sent to the AP. Measurement
- * periodicity In units of 100ms. ignored if num_of_bursts = 0
- * @samples_per_burst: 2-sided: the number of FTMs pairs in single Burst (1-31)
- * 1-sided: how many rts/cts pairs should be used per burst.
- * @retries_per_sample: Max number of retries that the LMAC should send
- * in case of no replies by the AP.
- * @tsf_delta: TSF Delta in units of microseconds.
- * The difference between the AP TSF and the device local clock.
- * @location_req: Location Request Bit[0] LCI should be sent in the FTMR
- * Bit[1] Civic should be sent in the FTMR
- * @asap_mode: 0 - non asap mode, 1 - asap mode (not relevant for one sided)
- * @enable_dyn_ack: Enable Dynamic ACK BW.
- * 0 Initiator interact with regular AP
- * 1 Initiator interact with Responder machine: need to send the
- * Initiator Acks with HT 40MHz / 80MHz, since the Responder should
- * use it for its ch est measurement (this flag will be set when we
- * configure the opposite machine to be Responder).
- * @rssi: Last received value
- * leagal values: -128-0 (0x7f). above 0x0 indicating an invalid value.
- */
-struct iwl_tof_range_req_ap_entry {
- u8 channel_num;
- u8 bandwidth;
- u8 tsf_delta_direction;
- u8 ctrl_ch_position;
- u8 bssid[ETH_ALEN];
- u8 measure_type;
- u8 num_of_bursts;
- __le16 burst_period;
- u8 samples_per_burst;
- u8 retries_per_sample;
- __le32 tsf_delta;
- u8 location_req;
- u8 asap_mode;
- u8 enable_dyn_ack;
- s8 rssi;
-} __packed;
-
-/**
- * enum iwl_tof_response_mode
- * @IWL_MVM_TOF_RESPOSE_ASAP: report each AP measurement separately as soon as
- * possible (not supported for this release)
- * @IWL_MVM_TOF_RESPOSE_TIMEOUT: report all AP measurements as a batch upon
- * timeout expiration
- * @IWL_MVM_TOF_RESPOSE_COMPLETE: report all AP measurements as a batch at the
- * earlier of: measurements completion / timeout
- * expiration.
- */
-enum iwl_tof_response_mode {
- IWL_MVM_TOF_RESPOSE_ASAP = 1,
- IWL_MVM_TOF_RESPOSE_TIMEOUT,
- IWL_MVM_TOF_RESPOSE_COMPLETE,
-};
-
-/**
- * struct iwl_tof_range_req_cmd - start measurement cmd
- * @request_id: A Token incremented per request. The same Token will be
- * sent back in the range response
- * @initiator: 0- NW initiated, 1 - Client Initiated
- * @one_sided_los_disable: '0'- run ML-Algo for both ToF/OneSided,
- * '1' - run ML-Algo for ToF only
- * @req_timeout: Requested timeout of the response in units of 100ms.
- * This is equivalent to the session time configured to the
- * LMAC in Initiator Request
- * @report_policy: Supported partially for this release: For current release -
- * the range report will be uploaded as a batch when ready or
- * when the session is done (successfully / partially).
- * one of iwl_tof_response_mode.
- * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
- * @macaddr_random: '0' Use default source MAC address (i.e. p2_p),
- * '1' Use MAC Address randomization according to the below
- * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
- * Bits set to 1 shall be randomized by the UMAC
- * @ap: per-AP request data
- */
-struct iwl_tof_range_req_cmd {
- __le32 sub_grp_cmd_id;
- u8 request_id;
- u8 initiator;
- u8 one_sided_los_disable;
- u8 req_timeout;
- u8 report_policy;
- u8 los_det_disable;
- u8 num_of_ap;
- u8 macaddr_random;
- u8 macaddr_template[ETH_ALEN];
- u8 macaddr_mask[ETH_ALEN];
- struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS];
-} __packed;
-
-/**
- * struct iwl_tof_gen_resp_cmd - generic ToF response
- */
-struct iwl_tof_gen_resp_cmd {
- __le32 sub_grp_cmd_id;
- u8 data[];
-} __packed;
-
-/**
- * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
- * @bssid: BSSID of the AP
- * @measure_status: current APs measurement status, one of
- * &enum iwl_tof_entry_status.
- * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
- * @rtt: The Round Trip Time that took for the last measurement for
- * current AP [nSec]
- * @rtt_variance: The Variance of the RTT values measured for current AP
- * @rtt_spread: The Difference between the maximum and the minimum RTT
- * values measured for current AP in the current session [nsec]
- * @rssi: RSSI as uploaded in the Channel Estimation notification
- * @rssi_spread: The Difference between the maximum and the minimum RSSI values
- * measured for current AP in the current session
- * @reserved: reserved
- * @range: Measured range [cm]
- * @range_variance: Measured range variance [cm]
- * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
- * uploaded by the LMAC
- */
-struct iwl_tof_range_rsp_ap_entry_ntfy {
- u8 bssid[ETH_ALEN];
- u8 measure_status;
- u8 measure_bw;
- __le32 rtt;
- __le32 rtt_variance;
- __le32 rtt_spread;
- s8 rssi;
- u8 rssi_spread;
- __le16 reserved;
- __le32 range;
- __le32 range_variance;
- __le32 timestamp;
-} __packed;
-
-/**
- * struct iwl_tof_range_rsp_ntfy -
- * @request_id: A Token ID of the corresponding Range request
- * @request_status: status of current measurement session
- * @last_in_batch: reprot policy (when not all responses are uploaded at once)
- * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
- * @ap: per-AP data
- */
-struct iwl_tof_range_rsp_ntfy {
- u8 request_id;
- u8 request_status;
- u8 last_in_batch;
- u8 num_of_aps;
- struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS];
-} __packed;
-
-#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
-/**
- * struct iwl_tof_mcsi_notif - used for debug
- * @token: token ID for the current session
- * @role: '0' - initiator, '1' - responder
- * @reserved: reserved
- * @initiator_bssid: initiator machine
- * @responder_bssid: responder machine
- * @mcsi_buffer: debug data
- */
-struct iwl_tof_mcsi_notif {
- u8 token;
- u8 role;
- __le16 reserved;
- u8 initiator_bssid[ETH_ALEN];
- u8 responder_bssid[ETH_ALEN];
- u8 mcsi_buffer[IWL_MVM_TOF_MCSI_BUF_SIZE * 4];
-} __packed;
-
-/**
- * struct iwl_tof_neighbor_report_notif
- * @bssid: BSSID of the AP which sent the report
- * @request_token: same token as the corresponding request
- * @status:
- * @report_ie_len: the length of the response frame starting from the Element ID
- * @data: the IEs
- */
-struct iwl_tof_neighbor_report {
- u8 bssid[ETH_ALEN];
- u8 request_token;
- u8 status;
- __le16 report_ie_len;
- u8 data[];
-} __packed;
-
-/**
- * struct iwl_tof_range_abort_cmd
- * @request_id: corresponds to a range request
- * @reserved: reserved
- */
-struct iwl_tof_range_abort_cmd {
- __le32 sub_grp_cmd_id;
- u8 request_id;
- u8 reserved[3];
-} __packed;
-
-#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
index 358bdf051e83..8511e735c374 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -847,13 +847,13 @@ struct iwl_beacon_notif {
} __packed;
/**
- * struct iwl_extended_beacon_notif - notifies about beacon transmission
+ * struct iwl_extended_beacon_notif_v5 - notifies about beacon transmission
* @beacon_notify_hdr: tx response command associated with the beacon
* @tsf: last beacon tsf
* @ibss_mgr_status: whether IBSS is manager
* @gp2: last beacon time in gp2
*/
-struct iwl_extended_beacon_notif {
+struct iwl_extended_beacon_notif_v5 {
struct iwl_mvm_tx_resp beacon_notify_hdr;
__le64 tsf;
__le32 ibss_mgr_status;
@@ -861,6 +861,20 @@ struct iwl_extended_beacon_notif {
} __packed; /* BEACON_NTFY_API_S_VER_5 */
/**
+ * struct iwl_extended_beacon_notif - notifies about beacon transmission
+ * @status: the status of the Tx response of the beacon
+ * @tsf: last beacon tsf
+ * @ibss_mgr_status: whether IBSS is manager
+ * @gp2: last beacon time in gp2
+ */
+struct iwl_extended_beacon_notif {
+ __le32 status;
+ __le64 tsf;
+ __le32 ibss_mgr_status;
+ __le32 gp2;
+} __packed; /* BEACON_NTFY_API_S_VER_6_ */
+
+/**
* enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
* and the TFD queues are empty.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 2a19b178c5e8..f119c49cd39c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -8,7 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -242,7 +242,8 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
cfg->lmac[0].rxfifo1_size, 0, 0);
/* Pull RXF2 */
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
- RXF_DIFF_FROM_PREV, 1);
+ RXF_DIFF_FROM_PREV +
+ fwrt->trans->cfg->umac_prph_offset, 1);
/* Pull LMAC2 RXF1 */
if (fwrt->smem_cfg.num_lmacs > 1)
iwl_fwrt_dump_rxf(fwrt, dump_data,
@@ -469,6 +470,93 @@ static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
{ .start = 0x00a02400, .end = 0x00a02758 },
};
+static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
+ { .start = 0x00a00000, .end = 0x00a00000 },
+ { .start = 0x00a0000c, .end = 0x00a00024 },
+ { .start = 0x00a0002c, .end = 0x00a00034 },
+ { .start = 0x00a0003c, .end = 0x00a0003c },
+ { .start = 0x00a00410, .end = 0x00a00418 },
+ { .start = 0x00a00420, .end = 0x00a00420 },
+ { .start = 0x00a00428, .end = 0x00a00428 },
+ { .start = 0x00a00430, .end = 0x00a0043c },
+ { .start = 0x00a00444, .end = 0x00a00444 },
+ { .start = 0x00a00840, .end = 0x00a00840 },
+ { .start = 0x00a00850, .end = 0x00a00858 },
+ { .start = 0x00a01004, .end = 0x00a01008 },
+ { .start = 0x00a01010, .end = 0x00a01010 },
+ { .start = 0x00a01018, .end = 0x00a01018 },
+ { .start = 0x00a01024, .end = 0x00a01024 },
+ { .start = 0x00a0102c, .end = 0x00a01034 },
+ { .start = 0x00a0103c, .end = 0x00a01040 },
+ { .start = 0x00a01048, .end = 0x00a01050 },
+ { .start = 0x00a01058, .end = 0x00a01058 },
+ { .start = 0x00a01060, .end = 0x00a01070 },
+ { .start = 0x00a0108c, .end = 0x00a0108c },
+ { .start = 0x00a01c20, .end = 0x00a01c28 },
+ { .start = 0x00a01d10, .end = 0x00a01d10 },
+ { .start = 0x00a01e28, .end = 0x00a01e2c },
+ { .start = 0x00a01e60, .end = 0x00a01e60 },
+ { .start = 0x00a01e80, .end = 0x00a01e80 },
+ { .start = 0x00a01ea0, .end = 0x00a01ea0 },
+ { .start = 0x00a02000, .end = 0x00a0201c },
+ { .start = 0x00a02024, .end = 0x00a02024 },
+ { .start = 0x00a02040, .end = 0x00a02048 },
+ { .start = 0x00a020c0, .end = 0x00a020e0 },
+ { .start = 0x00a02400, .end = 0x00a02404 },
+ { .start = 0x00a0240c, .end = 0x00a02414 },
+ { .start = 0x00a0241c, .end = 0x00a0243c },
+ { .start = 0x00a02448, .end = 0x00a024bc },
+ { .start = 0x00a024c4, .end = 0x00a024cc },
+ { .start = 0x00a02508, .end = 0x00a02508 },
+ { .start = 0x00a02510, .end = 0x00a02514 },
+ { .start = 0x00a0251c, .end = 0x00a0251c },
+ { .start = 0x00a0252c, .end = 0x00a0255c },
+ { .start = 0x00a02564, .end = 0x00a025a0 },
+ { .start = 0x00a025a8, .end = 0x00a025b4 },
+ { .start = 0x00a025c0, .end = 0x00a025c0 },
+ { .start = 0x00a025e8, .end = 0x00a025f4 },
+ { .start = 0x00a02c08, .end = 0x00a02c18 },
+ { .start = 0x00a02c2c, .end = 0x00a02c38 },
+ { .start = 0x00a02c68, .end = 0x00a02c78 },
+ { .start = 0x00a03000, .end = 0x00a03000 },
+ { .start = 0x00a03010, .end = 0x00a03014 },
+ { .start = 0x00a0301c, .end = 0x00a0302c },
+ { .start = 0x00a03034, .end = 0x00a03038 },
+ { .start = 0x00a03040, .end = 0x00a03044 },
+ { .start = 0x00a03060, .end = 0x00a03068 },
+ { .start = 0x00a03070, .end = 0x00a03070 },
+ { .start = 0x00a0307c, .end = 0x00a03084 },
+ { .start = 0x00a0308c, .end = 0x00a03090 },
+ { .start = 0x00a03098, .end = 0x00a03098 },
+ { .start = 0x00a030a0, .end = 0x00a030a0 },
+ { .start = 0x00a030a8, .end = 0x00a030b4 },
+ { .start = 0x00a030bc, .end = 0x00a030c0 },
+ { .start = 0x00a030c8, .end = 0x00a030f4 },
+ { .start = 0x00a03100, .end = 0x00a0312c },
+ { .start = 0x00a03c00, .end = 0x00a03c5c },
+ { .start = 0x00a04400, .end = 0x00a04454 },
+ { .start = 0x00a04460, .end = 0x00a04474 },
+ { .start = 0x00a044c0, .end = 0x00a044ec },
+ { .start = 0x00a04500, .end = 0x00a04504 },
+ { .start = 0x00a04510, .end = 0x00a04538 },
+ { .start = 0x00a04540, .end = 0x00a04548 },
+ { .start = 0x00a04560, .end = 0x00a04560 },
+ { .start = 0x00a04570, .end = 0x00a0457c },
+ { .start = 0x00a04590, .end = 0x00a04590 },
+ { .start = 0x00a04598, .end = 0x00a04598 },
+ { .start = 0x00a045c0, .end = 0x00a045f4 },
+ { .start = 0x00a0c000, .end = 0x00a0c018 },
+ { .start = 0x00a0c020, .end = 0x00a0c028 },
+ { .start = 0x00a0c038, .end = 0x00a0c094 },
+ { .start = 0x00a0c0c0, .end = 0x00a0c104 },
+ { .start = 0x00a0c10c, .end = 0x00a0c118 },
+ { .start = 0x00a0c150, .end = 0x00a0c174 },
+ { .start = 0x00a0c17c, .end = 0x00a0c188 },
+ { .start = 0x00a0c190, .end = 0x00a0c198 },
+ { .start = 0x00a0c1a0, .end = 0x00a0c1a8 },
+ { .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
+};
+
static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
u32 len_bytes, __le32 *data)
{
@@ -478,15 +566,20 @@ static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
*data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i));
}
-static void iwl_dump_prph(struct iwl_trans *trans,
- struct iwl_fw_error_dump_data **data,
+static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
const struct iwl_prph_range *iwl_prph_dump_addr,
- u32 range_len)
+ u32 range_len, void *ptr)
{
struct iwl_fw_error_dump_prph *prph;
+ struct iwl_trans *trans = fwrt->trans;
+ struct iwl_fw_error_dump_data **data =
+ (struct iwl_fw_error_dump_data **)ptr;
unsigned long flags;
u32 i;
+ if (!data)
+ return;
+
IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
if (!iwl_trans_grab_nic_access(trans, &flags))
@@ -552,37 +645,49 @@ static struct scatterlist *alloc_sgtable(int size)
return table;
}
-static int iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt)
+static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
+ const struct iwl_prph_range *iwl_prph_dump_addr,
+ u32 range_len, void *ptr)
{
- u32 prph_len = 0;
- int i;
+ u32 *prph_len = (u32 *)ptr;
+ int i, num_bytes_in_chunk;
- for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
- i++) {
+ if (!prph_len)
+ return;
+
+ for (i = 0; i < range_len; i++) {
/* The range includes both boundaries */
- int num_bytes_in_chunk =
- iwl_prph_dump_addr_comm[i].end -
- iwl_prph_dump_addr_comm[i].start + 4;
+ num_bytes_in_chunk =
+ iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4;
- prph_len += sizeof(struct iwl_fw_error_dump_data) +
+ *prph_len += sizeof(struct iwl_fw_error_dump_data) +
sizeof(struct iwl_fw_error_dump_prph) +
num_bytes_in_chunk;
}
+}
+
+static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
+ void (*handler)(struct iwl_fw_runtime *,
+ const struct iwl_prph_range *,
+ u32, void *))
+{
+ u32 range_len;
- if (fwrt->trans->cfg->mq_rx_supported) {
- for (i = 0; i <
- ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
- /* The range includes both boundaries */
- int num_bytes_in_chunk =
- iwl_prph_dump_addr_9000[i].end -
- iwl_prph_dump_addr_9000[i].start + 4;
-
- prph_len += sizeof(struct iwl_fw_error_dump_data) +
- sizeof(struct iwl_fw_error_dump_prph) +
- num_bytes_in_chunk;
+ if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ /* TODO */
+ } else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
+ handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
+ } else {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
+ handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
+
+ if (fwrt->trans->cfg->mq_rx_supported) {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
+ handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
}
}
- return prph_len;
}
static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
@@ -605,28 +710,6 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
}
-static void iwl_fw_dump_named_mem(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data,
- u32 len, u32 ofs, u8 *name, u8 name_len)
-{
- struct iwl_fw_error_dump_named_mem *dump_mem;
-
- if (!len)
- return;
-
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_NAMED_MEM);
- dump_mem->offset = cpu_to_le32(ofs);
- dump_mem->name_len = name_len;
- memcpy(dump_mem->name, name, name_len);
- iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
-
- IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
-}
-
#define ADD_LEN(len, item_len, const_len) \
do {size_t item = item_len; len += (!!item) * const_len + item; } \
while (0)
@@ -646,6 +729,9 @@ static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt,
ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
/* Count RXF1 sizes */
+ if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+ mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
for (i = 0; i < mem_cfg->num_lmacs; i++)
ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
@@ -664,6 +750,9 @@ static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt,
goto dump_internal_txf;
/* Count TXF sizes */
+ if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+ mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
for (i = 0; i < mem_cfg->num_lmacs; i++) {
int j;
@@ -707,6 +796,9 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
DMA_BIDIRECTIONAL);
memcpy(paging->data, page_address(pages),
PAGING_BLOCK_SIZE);
+ dma_sync_single_for_device(fwrt->trans->dev, addr,
+ PAGING_BLOCK_SIZE,
+ DMA_BIDIRECTIONAL);
(*data) = iwl_fw_error_next_data(*data);
}
}
@@ -733,6 +825,8 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) {
const struct fw_img *img;
+ if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
+ return NULL;
img = &fwrt->fw->img[fwrt->cur_fw_img];
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
@@ -747,9 +841,9 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
/* Make room for PRPH registers */
- if (!fwrt->trans->cfg->gen2 &&
- iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
- prph_len += iwl_fw_get_prph_len(fwrt);
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
+ iwl_fw_prph_handler(fwrt, &prph_len,
+ iwl_fw_get_prph_len);
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 &&
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
@@ -828,7 +922,13 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
sizeof(dump_info->dev_human_readable) - 1);
strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
sizeof(dump_info->bus_human_readable) - 1);
- dump_info->rt_status = cpu_to_le32(fwrt->dump.rt_status);
+ dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
+ dump_info->lmac_err_id[0] =
+ cpu_to_le32(fwrt->dump.lmac_err_id[0]);
+ if (fwrt->smem_cfg.num_lmacs > 1)
+ dump_info->lmac_err_id[1] =
+ cpu_to_le32(fwrt->dump.lmac_err_id[1]);
+ dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id);
dump_data = iwl_fw_error_next_data(dump_data);
}
@@ -935,133 +1035,653 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
if (iwl_fw_dbg_is_paging_enabled(fwrt))
iwl_dump_paging(fwrt, &dump_data);
- if (prph_len) {
- iwl_dump_prph(fwrt->trans, &dump_data,
- iwl_prph_dump_addr_comm,
- ARRAY_SIZE(iwl_prph_dump_addr_comm));
-
- if (fwrt->trans->cfg->mq_rx_supported)
- iwl_dump_prph(fwrt->trans, &dump_data,
- iwl_prph_dump_addr_9000,
- ARRAY_SIZE(iwl_prph_dump_addr_9000));
- }
+ if (prph_len)
+ iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph);
out:
dump_file->file_len = cpu_to_le32(file_len);
return dump_file;
}
-static void iwl_dump_prph_ini(struct iwl_trans *trans,
- struct iwl_fw_error_dump_data **data,
- struct iwl_fw_ini_region_cfg *reg)
+static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
{
- struct iwl_fw_error_dump_prph *prph;
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ __le32 *val = range->data;
+ u32 addr, prph_val, offset = le32_to_cpu(reg->offset);
+ int i;
+
+ range->start_addr = reg->start_addr[idx];
+ range->range_data_size = reg->internal.range_data_size;
+ for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
+ addr = le32_to_cpu(range->start_addr) + i;
+ prph_val = iwl_read_prph(fwrt->trans, addr + offset);
+ if (prph_val == 0x5a5a5a5a)
+ return -EBUSY;
+ *val++ = cpu_to_le32(prph_val);
+ }
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
+{
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ __le32 *val = range->data;
+ u32 addr, offset = le32_to_cpu(reg->offset);
+ int i;
+
+ range->start_addr = reg->start_addr[idx];
+ range->range_data_size = reg->internal.range_data_size;
+ for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
+ addr = le32_to_cpu(range->start_addr) + i;
+ *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans,
+ addr + offset));
+ }
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
+{
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ u32 addr = le32_to_cpu(range->start_addr);
+ u32 offset = le32_to_cpu(reg->offset);
+
+ range->start_addr = reg->start_addr[idx];
+ range->range_data_size = reg->internal.range_data_size;
+ iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data,
+ le32_to_cpu(reg->internal.range_data_size));
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static int
+iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
+{
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ u32 page_size = fwrt->trans->init_dram.paging[idx].size;
+
+ range->start_addr = cpu_to_le32(idx);
+ range->range_data_size = cpu_to_le32(page_size);
+ memcpy(range->data, fwrt->trans->init_dram.paging[idx].block,
+ page_size);
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
+{
+ /* increase idx by 1 since the pages are from 1 to
+ * fwrt->num_of_paging_blk + 1
+ */
+ struct page *page = fwrt->fw_paging_db[++idx].fw_paging_block;
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys;
+ u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size;
+
+ range->start_addr = cpu_to_le32(idx);
+ range->range_data_size = cpu_to_le32(page_size);
+ dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size,
+ DMA_BIDIRECTIONAL);
+ memcpy(range->data, page_address(page), page_size);
+ dma_sync_single_for_device(fwrt->trans->dev, addr, page_size,
+ DMA_BIDIRECTIONAL);
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static int
+iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg, void *range_ptr,
+ int idx)
+{
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
+ u32 start_addr = iwl_read_umac_prph(fwrt->trans,
+ MON_BUFF_BASE_ADDR_VER2);
+
+ if (start_addr == 0x5a5a5a5a)
+ return -EBUSY;
+
+ range->start_addr = cpu_to_le32(start_addr);
+ range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size);
+
+ memcpy(range->data, fwrt->trans->fw_mon[idx].block,
+ fwrt->trans->fw_mon[idx].size);
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+struct iwl_ini_txf_iter_data {
+ int fifo;
+ int lmac;
+ u32 fifo_size;
+ bool internal_txf;
+ bool init;
+};
+
+static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ struct iwl_ini_txf_iter_data *iter = fwrt->dump.fifo_iter;
+ struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
+ int txf_num = cfg->num_txfifo_entries;
+ int int_txf_num = ARRAY_SIZE(cfg->internal_txfifo_size);
+ u32 lmac_bitmap = le32_to_cpu(reg->fifos.fid1);
+
+ if (!iter)
+ return false;
+
+ if (iter->init) {
+ if (le32_to_cpu(reg->offset) &&
+ WARN_ONCE(cfg->num_lmacs == 1,
+ "Invalid lmac offset: 0x%x\n",
+ le32_to_cpu(reg->offset)))
+ return false;
+
+ iter->init = false;
+ iter->internal_txf = false;
+ iter->fifo_size = 0;
+ iter->fifo = -1;
+ if (le32_to_cpu(reg->offset))
+ iter->lmac = 1;
+ else
+ iter->lmac = 0;
+ }
+
+ if (!iter->internal_txf)
+ for (iter->fifo++; iter->fifo < txf_num; iter->fifo++) {
+ iter->fifo_size =
+ cfg->lmac[iter->lmac].txfifo_size[iter->fifo];
+ if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo)))
+ return true;
+ }
+
+ iter->internal_txf = true;
+
+ if (!fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG))
+ return false;
+
+ for (iter->fifo++; iter->fifo < int_txf_num + txf_num; iter->fifo++) {
+ iter->fifo_size =
+ cfg->internal_txfifo_size[iter->fifo - txf_num];
+ if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo)))
+ return true;
+ }
+
+ return false;
+}
+
+static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
+{
+ struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
+ struct iwl_ini_txf_iter_data *iter;
+ u32 offs = le32_to_cpu(reg->offset), addr;
+ u32 registers_size =
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+ __le32 *val = range->data;
unsigned long flags;
- u32 i, size = le32_to_cpu(reg->num_regions);
+ int i;
- IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
+ if (!iwl_ini_txf_iter(fwrt, reg))
+ return -EIO;
- if (!iwl_trans_grab_nic_access(trans, &flags))
+ if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
+ return -EBUSY;
+
+ iter = fwrt->dump.fifo_iter;
+
+ range->fifo_num = cpu_to_le32(iter->fifo);
+ range->num_of_registers = reg->fifos.num_of_registers;
+ range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size);
+
+ iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
+
+ /* read txf registers */
+ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) {
+ addr = le32_to_cpu(reg->start_addr[i]) + offs;
+
+ *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ }
+
+ if (reg->fifos.header_only) {
+ range->range_data_size = cpu_to_le32(registers_size);
+ goto out;
+ }
+
+ /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
+ iwl_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs,
+ TXF_WR_PTR + offs);
+
+ /* Dummy-read to advance the read pointer to the head */
+ iwl_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs);
+
+ /* Read FIFO */
+ addr = TXF_READ_MODIFY_DATA + offs;
+ for (i = 0; i < iter->fifo_size; i += sizeof(__le32))
+ *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+
+out:
+ iwl_trans_release_nic_access(fwrt->trans, &flags);
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+struct iwl_ini_rxf_data {
+ u32 fifo_num;
+ u32 size;
+ u32 offset;
+};
+
+static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ struct iwl_ini_rxf_data *data)
+{
+ u32 fid1 = le32_to_cpu(reg->fifos.fid1);
+ u32 fid2 = le32_to_cpu(reg->fifos.fid2);
+ u32 fifo_idx;
+
+ if (!data)
return;
- for (i = 0; i < size; i++) {
- (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
- (*data)->len = cpu_to_le32(le32_to_cpu(reg->size) +
- sizeof(*prph));
- prph = (void *)(*data)->data;
- prph->prph_start = reg->start_addr[i];
- prph->data[0] = cpu_to_le32(iwl_read_prph_no_grab(trans,
- le32_to_cpu(prph->prph_start)));
- *data = iwl_fw_error_next_data(*data);
+ memset(data, 0, sizeof(*data));
+
+ if (WARN_ON_ONCE((fid1 && fid2) || (!fid1 && !fid2)))
+ return;
+
+ fifo_idx = ffs(fid1) - 1;
+ if (fid1 && !WARN_ON_ONCE((~BIT(fifo_idx) & fid1) ||
+ fifo_idx >= MAX_NUM_LMAC)) {
+ data->size = fwrt->smem_cfg.lmac[fifo_idx].rxfifo1_size;
+ data->fifo_num = fifo_idx;
+ return;
+ }
+
+ fifo_idx = ffs(fid2) - 1;
+ if (fid2 && !WARN_ON_ONCE(fifo_idx != 0)) {
+ data->size = fwrt->smem_cfg.rxfifo2_size;
+ data->offset = RXF_DIFF_FROM_PREV;
+ /* use bit 31 to distinguish between umac and lmac rxf while
+ * parsing the dump
+ */
+ data->fifo_num = fifo_idx | IWL_RXF_UMAC_BIT;
+ return;
}
- iwl_trans_release_nic_access(trans, &flags);
}
-static void iwl_dump_csr_ini(struct iwl_trans *trans,
- struct iwl_fw_error_dump_data **data,
- struct iwl_fw_ini_region_cfg *reg)
+static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *range_ptr, int idx)
{
- int i, num = le32_to_cpu(reg->num_regions);
- u32 size = le32_to_cpu(reg->size);
+ struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
+ struct iwl_ini_rxf_data rxf_data;
+ u32 offs = le32_to_cpu(reg->offset), addr;
+ u32 registers_size =
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+ __le32 *val = range->data;
+ unsigned long flags;
+ int i;
- IWL_DEBUG_INFO(trans, "WRT CSR dump\n");
+ iwl_ini_get_rxf_data(fwrt, reg, &rxf_data);
+ if (!rxf_data.size)
+ return -EIO;
- for (i = 0; i < num; i++) {
- u32 add = le32_to_cpu(reg->start_addr[i]);
- __le32 *val;
- int j;
+ if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
+ return -EBUSY;
- (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
- (*data)->len = cpu_to_le32(size);
- val = (void *)(*data)->data;
+ offs += rxf_data.offset;
- for (j = 0; j < size; j += 4)
- *val++ = cpu_to_le32(iwl_trans_read32(trans, j + add));
+ range->fifo_num = cpu_to_le32(rxf_data.fifo_num);
+ range->num_of_registers = reg->fifos.num_of_registers;
+ range->range_data_size = cpu_to_le32(rxf_data.size + registers_size);
- *data = iwl_fw_error_next_data(*data);
+ /* read rxf registers */
+ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) {
+ addr = le32_to_cpu(reg->start_addr[i]) + offs;
+
+ *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ }
+
+ if (reg->fifos.header_only) {
+ range->range_data_size = cpu_to_le32(registers_size);
+ goto out;
+ }
+
+ /* Lock fence */
+ iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
+ /* Set fence pointer to the same place like WR pointer */
+ iwl_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1);
+ /* Set fence offset */
+ iwl_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs,
+ 0x0);
+
+ /* Read FIFO */
+ addr = RXF_FIFO_RD_FENCE_INC + offs;
+ for (i = 0; i < rxf_data.size; i += sizeof(__le32))
+ *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+
+out:
+ iwl_trans_release_nic_access(fwrt->trans, &flags);
+
+ return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
+static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *data)
+{
+ struct iwl_fw_ini_error_dump *dump = data;
+
+ return dump->ranges;
+}
+
+static void
+*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *data)
+{
+ struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data;
+ u32 write_ptr, cycle_cnt;
+ unsigned long flags;
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) {
+ IWL_ERR(fwrt, "Failed to get DRAM monitor header\n");
+ return NULL;
+ }
+ write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans,
+ MON_BUFF_WRPTR_VER2);
+ cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans,
+ MON_BUFF_CYCLE_CNT_VER2);
+ iwl_trans_release_nic_access(fwrt->trans, &flags);
+
+ mon_dump->write_ptr = cpu_to_le32(write_ptr);
+ mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt);
+
+ return mon_dump->ranges;
+}
+
+static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *data)
+{
+ struct iwl_fw_ini_fifo_error_dump *dump = data;
+
+ return dump->ranges;
+}
+
+static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return le32_to_cpu(reg->internal.num_of_ranges);
+}
+
+static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return fwrt->trans->init_dram.paging_cnt;
+}
+
+static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return fwrt->num_of_paging_blk;
+}
+
+static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return 1;
+}
+
+static u32 iwl_dump_ini_txf_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ struct iwl_ini_txf_iter_data iter = { .init = true };
+ void *fifo_iter = fwrt->dump.fifo_iter;
+ u32 num_of_fifos = 0;
+
+ fwrt->dump.fifo_iter = &iter;
+ while (iwl_ini_txf_iter(fwrt, reg))
+ num_of_fifos++;
+
+ fwrt->dump.fifo_iter = fifo_iter;
+
+ return num_of_fifos;
+}
+
+static u32 iwl_dump_ini_rxf_ranges(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ /* Each Rx fifo needs a different offset and therefore, it's
+ * region can contain only one fifo, i.e. 1 memory range.
+ */
+ return 1;
+}
+
+static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return sizeof(struct iwl_fw_ini_error_dump) +
+ iwl_dump_ini_mem_ranges(fwrt, reg) *
+ (sizeof(struct iwl_fw_ini_error_dump_range) +
+ le32_to_cpu(reg->internal.range_data_size));
+}
+
+static u32 iwl_dump_ini_paging_gen2_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ int i;
+ u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range);
+ u32 size = sizeof(struct iwl_fw_ini_error_dump);
+
+ for (i = 0; i < iwl_dump_ini_paging_gen2_ranges(fwrt, reg); i++)
+ size += range_header_len +
+ fwrt->trans->init_dram.paging[i].size;
+
+ return size;
+}
+
+static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ int i;
+ u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range);
+ u32 size = sizeof(struct iwl_fw_ini_error_dump);
+
+ for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg); i++)
+ size += range_header_len + fwrt->fw_paging_db[i].fw_paging_size;
+
+ return size;
+}
+
+static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump);
+
+ if (fwrt->trans->num_blocks)
+ size += fwrt->trans->fw_mon[0].size;
+
+ return size;
+}
+
+static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ struct iwl_ini_txf_iter_data iter = { .init = true };
+ void *fifo_iter = fwrt->dump.fifo_iter;
+ u32 size = 0;
+ u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+
+ fwrt->dump.fifo_iter = &iter;
+ while (iwl_ini_txf_iter(fwrt, reg)) {
+ size += fifo_hdr;
+ if (!reg->fifos.header_only)
+ size += iter.fifo_size;
+ }
+
+ if (size)
+ size += sizeof(struct iwl_fw_ini_fifo_error_dump);
+
+ fwrt->dump.fifo_iter = fifo_iter;
+
+ return size;
+}
+
+static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ struct iwl_ini_rxf_data rx_data;
+ u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) +
+ sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+
+ if (reg->fifos.header_only)
+ return size;
+
+ iwl_ini_get_rxf_data(fwrt, reg, &rx_data);
+ size += rx_data.size;
+
+ return size;
+}
+
+/**
+ * struct iwl_dump_ini_mem_ops - ini memory dump operations
+ * @get_num_of_ranges: returns the number of memory ranges in the region.
+ * @get_size: returns the total size of the region.
+ * @fill_mem_hdr: fills region type specific headers and returns pointer to
+ * the first range or NULL if failed to fill headers.
+ * @fill_range: copies a given memory range into the dump.
+ * Returns the size of the range or negative error value otherwise.
+ */
+struct iwl_dump_ini_mem_ops {
+ u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg);
+ u32 (*get_size)(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg);
+ void *(*fill_mem_hdr)(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg, void *data);
+ int (*fill_range)(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg, void *range,
+ int idx);
+};
+
+/**
+ * iwl_dump_ini_mem - copy a memory region into the dump
+ * @fwrt: fw runtime struct.
+ * @data: dump memory data.
+ * @reg: region to copy to the dump.
+ */
+static void
+iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_ini_region_type type,
+ struct iwl_fw_error_dump_data **data,
+ struct iwl_fw_ini_region_cfg *reg,
+ struct iwl_dump_ini_mem_ops *ops)
+{
+ struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data;
+ void *range;
+ u32 num_of_ranges, i;
+
+ if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size ||
+ !ops->fill_mem_hdr || !ops->fill_range))
+ return;
+
+ num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
+
+ (*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
+ (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg));
+
+ header->num_of_ranges = cpu_to_le32(num_of_ranges);
+ header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME,
+ le32_to_cpu(reg->name_len)));
+ memcpy(header->name, reg->name, le32_to_cpu(header->name_len));
+
+ range = ops->fill_mem_hdr(fwrt, reg, header);
+ if (!range) {
+ IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n",
+ le32_to_cpu(reg->region_id), type);
+ return;
}
+
+ for (i = 0; i < num_of_ranges; i++) {
+ int range_size = ops->fill_range(fwrt, reg, range, i);
+
+ if (range_size < 0) {
+ IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n",
+ le32_to_cpu(reg->region_id), type);
+ return;
+ }
+ range = range + range_size;
+ }
+ *data = iwl_fw_error_next_data(*data);
}
static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trigger)
{
- int i, num, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
+ int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
if (!trigger || !trigger->num_regions)
return 0;
- num = le32_to_cpu(trigger->num_regions);
- for (i = 0; i < num; i++) {
+ for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) {
u32 reg_id = le32_to_cpu(trigger->data[i]);
struct iwl_fw_ini_region_cfg *reg;
enum iwl_fw_ini_region_type type;
- u32 num_entries;
if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)))
continue;
- reg = fwrt->dump.active_regs[reg_id].reg;
+ reg = fwrt->dump.active_regs[reg_id];
if (WARN(!reg, "Unassigned region %d\n", reg_id))
continue;
type = le32_to_cpu(reg->region_type);
- num_entries = le32_to_cpu(reg->num_regions);
-
switch (type) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
- size += hdr_len +
- sizeof(struct iwl_fw_error_dump_named_mem) +
- le32_to_cpu(reg->size);
- break;
case IWL_FW_INI_REGION_PERIPHERY_MAC:
case IWL_FW_INI_REGION_PERIPHERY_PHY:
case IWL_FW_INI_REGION_PERIPHERY_AUX:
- size += num_entries *
- (hdr_len +
- sizeof(struct iwl_fw_error_dump_prph) +
- sizeof(u32));
+ case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ case IWL_FW_INI_REGION_CSR:
+ size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
break;
case IWL_FW_INI_REGION_TXF:
- size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg);
+ size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg);
break;
case IWL_FW_INI_REGION_RXF:
- size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg);
+ size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg);
break;
- case IWL_FW_INI_REGION_PAGING:
- if (!iwl_fw_dbg_is_paging_enabled(fwrt))
- break;
- size += fwrt->num_of_paging_blk *
- (hdr_len +
- sizeof(struct iwl_fw_error_dump_paging) +
- PAGING_BLOCK_SIZE);
- break;
- case IWL_FW_INI_REGION_CSR:
- size += num_entries *
- (hdr_len + le32_to_cpu(reg->size));
+ case IWL_FW_INI_REGION_PAGING: {
+ size += hdr_len;
+ if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
+ size += iwl_dump_ini_paging_get_size(fwrt, reg);
+ } else {
+ size += iwl_dump_ini_paging_gen2_get_size(fwrt,
+ reg);
+ }
break;
+ }
case IWL_FW_INI_REGION_DRAM_BUFFER:
- /* Transport takes care of DRAM dumping */
- case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ if (!fwrt->trans->num_blocks)
+ break;
+ size += hdr_len +
+ iwl_dump_ini_mon_dram_get_size(fwrt, reg);
+ break;
case IWL_FW_INI_REGION_DRAM_IMR:
/* Undefined yet */
default:
@@ -1073,8 +1693,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trigger,
- struct iwl_fw_error_dump_data **data,
- u32 *dump_mask)
+ struct iwl_fw_error_dump_data **data)
{
int i, num = le32_to_cpu(trigger->num_regions);
@@ -1082,11 +1701,12 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
u32 reg_id = le32_to_cpu(trigger->data[i]);
enum iwl_fw_ini_region_type type;
struct iwl_fw_ini_region_cfg *reg;
+ struct iwl_dump_ini_mem_ops ops;
if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))
continue;
- reg = fwrt->dump.active_regs[reg_id].reg;
+ reg = fwrt->dump.active_regs[reg_id];
/* Don't warn, get_trigger_len already warned */
if (!reg)
continue;
@@ -1094,39 +1714,75 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
type = le32_to_cpu(reg->region_type);
switch (type) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
- if (WARN_ON(le32_to_cpu(reg->num_regions) > 1))
- continue;
- iwl_fw_dump_named_mem(fwrt, data,
- le32_to_cpu(reg->size),
- le32_to_cpu(reg->start_addr[0]),
- reg->name,
- le32_to_cpu(reg->name_len));
+ case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
+ ops.get_size = iwl_dump_ini_mem_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
+ ops.fill_range = iwl_dump_ini_dev_mem_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
case IWL_FW_INI_REGION_PERIPHERY_MAC:
case IWL_FW_INI_REGION_PERIPHERY_PHY:
case IWL_FW_INI_REGION_PERIPHERY_AUX:
- iwl_dump_prph_ini(fwrt->trans, data, reg);
+ ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
+ ops.get_size = iwl_dump_ini_mem_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
+ ops.fill_range = iwl_dump_ini_prph_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
case IWL_FW_INI_REGION_DRAM_BUFFER:
- *dump_mask |= IWL_FW_ERROR_DUMP_FW_MONITOR;
+ ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges;
+ ops.get_size = iwl_dump_ini_mon_dram_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header;
+ ops.fill_range = iwl_dump_ini_mon_dram_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
- case IWL_FW_INI_REGION_PAGING:
- if (iwl_fw_dbg_is_paging_enabled(fwrt))
- iwl_dump_paging(fwrt, data);
- else
- *dump_mask |= IWL_FW_ERROR_DUMP_PAGING;
+ case IWL_FW_INI_REGION_PAGING: {
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
+ if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
+ ops.get_num_of_ranges =
+ iwl_dump_ini_paging_ranges;
+ ops.get_size = iwl_dump_ini_paging_get_size;
+ ops.fill_range = iwl_dump_ini_paging_iter;
+ } else {
+ ops.get_num_of_ranges =
+ iwl_dump_ini_paging_gen2_ranges;
+ ops.get_size =
+ iwl_dump_ini_paging_gen2_get_size;
+ ops.fill_range = iwl_dump_ini_paging_gen2_iter;
+ }
+
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
- case IWL_FW_INI_REGION_TXF:
- iwl_fw_dump_txf(fwrt, data);
+ }
+ case IWL_FW_INI_REGION_TXF: {
+ struct iwl_ini_txf_iter_data iter = { .init = true };
+ void *fifo_iter = fwrt->dump.fifo_iter;
+
+ fwrt->dump.fifo_iter = &iter;
+ ops.get_num_of_ranges = iwl_dump_ini_txf_ranges;
+ ops.get_size = iwl_dump_ini_txf_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
+ ops.fill_range = iwl_dump_ini_txf_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ fwrt->dump.fifo_iter = fifo_iter;
break;
+ }
case IWL_FW_INI_REGION_RXF:
- iwl_fw_dump_rxf(fwrt, data);
+ ops.get_num_of_ranges = iwl_dump_ini_rxf_ranges;
+ ops.get_size = iwl_dump_ini_rxf_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
+ ops.fill_range = iwl_dump_ini_rxf_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
case IWL_FW_INI_REGION_CSR:
- iwl_dump_csr_ini(fwrt->trans, data, reg);
+ ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
+ ops.get_size = iwl_dump_ini_mem_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
+ ops.fill_range = iwl_dump_ini_csr_iter;
+ iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
break;
case IWL_FW_INI_REGION_DRAM_IMR:
- case IWL_FW_INI_REGION_INTERNAL_BUFFER:
/* This is undefined yet */
default:
break;
@@ -1136,30 +1792,23 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
static struct iwl_fw_error_dump_file *
_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dump_ptrs *fw_error_dump,
- u32 *dump_mask)
+ struct iwl_fw_dump_ptrs *fw_error_dump)
{
int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type);
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_file *dump_file;
- struct iwl_fw_ini_trigger *trigger, *ext;
+ struct iwl_fw_ini_trigger *trigger;
if (id == FW_DBG_TRIGGER_FW_ASSERT)
id = IWL_FW_TRIGGER_ID_FW_ASSERT;
- else if (id == FW_DBG_TRIGGER_USER)
- id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
- else if (id < FW_DBG_TRIGGER_MAX)
- return NULL;
- if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
+ if (!iwl_fw_ini_trigger_on(fwrt, id))
return NULL;
- trigger = fwrt->dump.active_trigs[id].conf;
- ext = fwrt->dump.active_trigs[id].conf_ext;
+ trigger = fwrt->dump.active_trigs[id].trig;
size = sizeof(*dump_file);
size += iwl_fw_ini_get_trigger_len(fwrt, trigger);
- size += iwl_fw_ini_get_trigger_len(fwrt, ext);
if (!size)
return NULL;
@@ -1174,11 +1823,7 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
dump_data = (void *)dump_file->data;
dump_file->file_len = cpu_to_le32(size);
- *dump_mask = 0;
- if (trigger)
- iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data, dump_mask);
- if (ext)
- iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data, dump_mask);
+ iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data);
return dump_file;
}
@@ -1204,8 +1849,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
goto out;
if (fwrt->trans->ini_valid)
- dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump,
- &dump_mask);
+ dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump);
else
dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
@@ -1217,7 +1861,10 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
- fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
+ if (!fwrt->trans->ini_valid)
+ fw_error_dump->trans_ptr =
+ iwl_trans_dump_data(fwrt->trans, dump_mask);
+
file_len = le32_to_cpu(dump_file->file_len);
fw_error_dump->fwrt_len = file_len;
if (fw_error_dump->trans_ptr) {
@@ -1258,61 +1905,12 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
};
IWL_EXPORT_SYMBOL(iwl_dump_desc_assert);
-void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt)
-{
- IWL_INFO(fwrt, "error dump due to fw assert\n");
- fwrt->dump.desc = &iwl_dump_desc_assert;
- iwl_fw_error_dump(fwrt);
-}
-IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump);
-
-void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt)
-{
- struct iwl_fw_dump_desc *iwl_dump_desc_no_alive =
- kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL);
-
- if (!iwl_dump_desc_no_alive)
- return;
-
- iwl_dump_desc_no_alive->trig_desc.type =
- cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE);
- iwl_dump_desc_no_alive->len = 0;
-
- if (WARN_ON(fwrt->dump.desc))
- iwl_fw_free_dump_desc(fwrt);
-
- IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
- FW_DBG_TRIGGER_NO_ALIVE);
-
- fwrt->dump.desc = iwl_dump_desc_no_alive;
- iwl_fw_error_dump(fwrt);
- clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status);
-}
-IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump);
-
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc,
bool monitor_only,
unsigned int delay)
{
- /*
- * If the loading of the FW completed successfully, the next step is to
- * get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non
- * zero, the FW was already loaded successully. If the state is "NO_FW"
- * in such a case - exit, since FW may be dead. Otherwise, we
- * can try to collect the data, since FW might just not be fully
- * loaded (no "ALIVE" yet), and the debug data is accessible.
- *
- * Corner case: got the FW alive but crashed before getting the SMEM
- * config. In such a case, due to HW access problems, we might
- * collect garbage.
- */
- if (fwrt->trans->state == IWL_TRANS_NO_FW &&
- fwrt->smem_cfg.num_lmacs)
- return -EIO;
-
- if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) ||
- test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status))
+ if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
return -EBUSY;
if (WARN_ON(fwrt->dump.desc))
@@ -1324,12 +1922,39 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
fwrt->dump.desc = desc;
fwrt->dump.monitor_only = monitor_only;
- schedule_delayed_work(&fwrt->dump.wk, delay);
+ schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
return 0;
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
+int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_dbg_trigger trig_type)
+{
+ int ret;
+ struct iwl_fw_dump_desc *iwl_dump_error_desc =
+ kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
+
+ if (!iwl_dump_error_desc)
+ return -ENOMEM;
+
+ iwl_dump_error_desc->trig_desc.type = cpu_to_le32(trig_type);
+ iwl_dump_error_desc->len = 0;
+
+ ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0);
+ if (ret) {
+ kfree(iwl_dump_error_desc);
+ } else {
+ set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
+
+ /* trigger nmi to halt the fw */
+ iwl_force_nmi(fwrt->trans);
+ }
+
+ return ret;
+}
+IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect);
+
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig,
const char *str, size_t len,
@@ -1353,8 +1978,10 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
}
trigger->occurrences = cpu_to_le16(occurrences);
- delay = le16_to_cpu(trigger->trig_dis_ms);
monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY;
+
+ /* convert msec to usec */
+ delay = le32_to_cpu(trigger->stop_delay) * USEC_PER_MSEC;
}
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
@@ -1374,6 +2001,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
u32 id, const char *str, size_t len)
{
struct iwl_fw_dump_desc *desc;
+ struct iwl_fw_ini_active_triggers *active;
u32 occur, delay;
if (!fwrt->trans->ini_valid)
@@ -1382,15 +2010,17 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
if (id == FW_DBG_TRIGGER_USER)
id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
- if (WARN_ON(!fwrt->dump.active_trigs[id].active))
+ active = &fwrt->dump.active_trigs[id];
+
+ if (WARN_ON(!active->active))
return -EINVAL;
- delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->ignore_consec);
- occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences);
+ delay = le32_to_cpu(active->trig->dump_delay);
+ occur = le32_to_cpu(active->trig->occurrences);
if (!occur)
return 0;
- if (le32_to_cpu(fwrt->dump.active_trigs[id].conf->force_restart)) {
+ if (le32_to_cpu(active->trig->force_restart)) {
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
iwl_force_nmi(fwrt->trans);
return 0;
@@ -1400,8 +2030,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
if (!desc)
return -ENOMEM;
- occur--;
- fwrt->dump.active_trigs[id].conf->occurrences = cpu_to_le32(occur);
+ active->trig->occurrences = cpu_to_le32(--occur);
desc->len = len;
desc->trig_desc.type = cpu_to_le32(id);
@@ -1566,55 +2195,81 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
static void
-iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_ini_allocation_tlv *alloc)
+iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
{
struct iwl_trans *trans = fwrt->trans;
- struct iwl_continuous_record_cmd cont_rec = {};
- struct iwl_buffer_allocation_cmd *cmd = (void *)&cont_rec.pad[0];
- struct iwl_host_cmd hcmd = {
- .id = LDBG_CONFIG_CMD,
- .flags = CMD_ASYNC,
- .data[0] = &cont_rec,
- .len[0] = sizeof(cont_rec),
- };
void *virtual_addr = NULL;
- u32 size = le32_to_cpu(alloc->size);
dma_addr_t phys_addr;
- cont_rec.record_mode.enable_recording = cpu_to_le16(BUFFER_ALLOCATION);
-
- if (!trans->num_blocks &&
- le32_to_cpu(alloc->buffer_location) !=
- IWL_FW_INI_LOCATION_DRAM_PATH)
+ if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon)))
return;
- virtual_addr = dma_alloc_coherent(fwrt->trans->dev, size,
- &phys_addr, GFP_KERNEL);
+ virtual_addr =
+ dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO |
+ __GFP_COMP);
/* TODO: alloc fragments if needed */
if (!virtual_addr)
IWL_ERR(fwrt, "Failed to allocate debug memory\n");
- if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon)))
- return;
-
trans->fw_mon[trans->num_blocks].block = virtual_addr;
trans->fw_mon[trans->num_blocks].physical = phys_addr;
trans->fw_mon[trans->num_blocks].size = size;
trans->num_blocks++;
IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size);
+}
+
+static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_allocation_data *alloc,
+ enum iwl_fw_ini_apply_point pnt)
+{
+ struct iwl_trans *trans = fwrt->trans;
+ struct iwl_ldbg_config_cmd ldbg_cmd = {
+ .type = cpu_to_le32(BUFFER_ALLOCATION),
+ };
+ struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation;
+ struct iwl_host_cmd hcmd = {
+ .id = LDBG_CONFIG_CMD,
+ .flags = CMD_ASYNC,
+ .data[0] = &ldbg_cmd,
+ .len[0] = sizeof(ldbg_cmd),
+ };
+ int block_idx = trans->num_blocks;
+ u32 buf_location = le32_to_cpu(alloc->tlv.buffer_location);
+
+ if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
+ if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY,
+ "Invalid apply point %d for SMEM buffer allocation",
+ pnt))
+ /* set sram monitor by enabling bit 7 */
+ iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
+ return;
+ }
+
+ if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH)
+ return;
+
+ if (!alloc->is_alloc) {
+ iwl_fw_dbg_buffer_allocation(fwrt,
+ le32_to_cpu(alloc->tlv.size));
+ if (block_idx == trans->num_blocks)
+ return;
+ alloc->is_alloc = 1;
+ }
/* First block is assigned via registers / context info */
if (trans->num_blocks == 1)
return;
cmd->num_frags = cpu_to_le32(1);
- cmd->fragments[0].address = cpu_to_le64(phys_addr);
- cmd->fragments[0].size = alloc->size;
- cmd->allocation_id = alloc->allocation_id;
- cmd->buffer_location = alloc->buffer_location;
+ cmd->fragments[0].address =
+ cpu_to_le64(trans->fw_mon[block_idx].physical);
+ cmd->fragments[0].size = alloc->tlv.size;
+ cmd->allocation_id = alloc->tlv.allocation_id;
+ cmd->buffer_location = alloc->tlv.buffer_location;
iwl_trans_send_cmd(trans, &hcmd);
}
@@ -1643,9 +2298,9 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
int i, size = le32_to_cpu(tlv->num_regions);
for (i = 0; i < size; i++) {
- struct iwl_fw_ini_region_cfg *reg = iter;
+ struct iwl_fw_ini_region_cfg *reg = iter, **active;
int id = le32_to_cpu(reg->region_id);
- struct iwl_fw_ini_active_regs *active;
+ u32 type = le32_to_cpu(reg->region_type);
if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs),
"Invalid region id %d for apply point %d\n", id, pnt))
@@ -1653,26 +2308,47 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
active = &fwrt->dump.active_regs[id];
- if (ext && active->apply_point == pnt)
- IWL_WARN(fwrt->trans,
- "External region TLV overrides FW default %x\n",
- id);
+ if (*active)
+ IWL_WARN(fwrt->trans, "region TLV %d override\n", id);
IWL_DEBUG_FW(fwrt,
"%s: apply point %d, activating region ID %d\n",
__func__, pnt, id);
- active->reg = reg;
- active->apply_point = pnt;
+ *active = reg;
- if (le32_to_cpu(reg->region_type) !=
- IWL_FW_INI_REGION_DRAM_BUFFER)
- iter += le32_to_cpu(reg->num_regions) * sizeof(__le32);
+ if (type == IWL_FW_INI_REGION_TXF ||
+ type == IWL_FW_INI_REGION_RXF)
+ iter += le32_to_cpu(reg->fifos.num_of_registers) *
+ sizeof(__le32);
+ else if (type != IWL_FW_INI_REGION_DRAM_BUFFER)
+ iter += le32_to_cpu(reg->internal.num_of_ranges) *
+ sizeof(__le32);
iter += sizeof(*reg);
}
}
+static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_active_triggers *active,
+ u32 id, int size)
+{
+ void *ptr;
+
+ if (size <= active->size)
+ return 0;
+
+ ptr = krealloc(active->trig, size, GFP_KERNEL);
+ if (!ptr) {
+ IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id);
+ return -ENOMEM;
+ }
+ active->trig = ptr;
+ active->size = size;
+
+ return 0;
+}
+
static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger_tlv *tlv,
bool ext,
@@ -1685,43 +2361,61 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trig = iter;
struct iwl_fw_ini_active_triggers *active;
int id = le32_to_cpu(trig->trigger_id);
- u32 num;
+ u32 trig_regs_size = le32_to_cpu(trig->num_regions) *
+ sizeof(__le32);
if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
break;
active = &fwrt->dump.active_trigs[id];
- if (active->apply_point != apply_point) {
- active->conf = NULL;
- active->conf_ext = NULL;
- }
+ if (!active->active) {
+ size_t trig_size = sizeof(*trig) + trig_regs_size;
+
+ if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
+ trig_size))
+ goto next;
- num = le32_to_cpu(trig->num_regions);
+ memcpy(active->trig, trig, trig_size);
- if (ext && active->apply_point == apply_point) {
- num += le32_to_cpu(active->conf->num_regions);
- if (trig->ignore_default) {
- active->conf_ext = active->conf;
- active->conf = trig;
+ } else {
+ u32 conf_override =
+ !(le32_to_cpu(trig->override_trig) & 0xff);
+ u32 region_override =
+ !(le32_to_cpu(trig->override_trig) & 0xff00);
+ u32 offset = 0;
+ u32 active_regs =
+ le32_to_cpu(active->trig->num_regions);
+ u32 new_regs = le32_to_cpu(trig->num_regions);
+ int mem_to_add = trig_regs_size;
+
+ if (region_override) {
+ mem_to_add -= active_regs * sizeof(__le32);
} else {
- active->conf_ext = trig;
+ offset += active_regs;
+ new_regs += active_regs;
}
- } else {
- active->conf = trig;
+
+ if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
+ active->size + mem_to_add))
+ goto next;
+
+ if (conf_override)
+ memcpy(active->trig, trig, sizeof(*trig));
+
+ memcpy(active->trig->data + offset, trig->data,
+ trig_regs_size);
+ active->trig->num_regions = cpu_to_le32(new_regs);
}
/* Since zero means infinity - just set to -1 */
- if (!le32_to_cpu(trig->occurrences))
- trig->occurrences = cpu_to_le32(-1);
- if (!le32_to_cpu(trig->ignore_consec))
- trig->ignore_consec = cpu_to_le32(-1);
+ if (!le32_to_cpu(active->trig->occurrences))
+ active->trig->occurrences = cpu_to_le32(-1);
- iter += sizeof(*trig) +
- le32_to_cpu(trig->num_regions) * sizeof(__le32);
+ active->active = true;
+next:
+ iter += sizeof(*trig) + trig_regs_size;
- active->active = num;
- active->apply_point = apply_point;
}
}
@@ -1738,9 +2432,13 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
u32 type = le32_to_cpu(tlv->type);
switch (type) {
- case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
- iwl_fw_dbg_buffer_allocation(fwrt, ini_tlv);
+ case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
+ struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
+
+ iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt);
+ iter += sizeof(buf_alloc->is_alloc);
break;
+ }
case IWL_UCODE_TLV_TYPE_HCMD:
if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
IWL_ERR(fwrt,
@@ -1771,6 +2469,16 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_apply_point apply_point)
{
void *data = &fwrt->trans->apply_points[apply_point];
+ int i;
+
+ if (apply_point == IWL_FW_INI_APPLY_EARLY) {
+ for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
+ fwrt->dump.active_regs[i] = NULL;
+
+ /* disable the triggers, used in recovery flow */
+ for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
+ fwrt->dump.active_trigs[i].active = false;
+ }
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
@@ -1778,3 +2486,27 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, true);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
+
+void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
+{
+ /* if the wait event timeout elapses instead of wake up then
+ * the driver did not receive NMI interrupt and can not assume the FW
+ * is halted
+ */
+ int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq,
+ !test_bit(STATUS_FW_WAIT_DUMP,
+ &fwrt->trans->status),
+ msecs_to_jiffies(2000));
+ if (!ret) {
+ /* failed to receive NMI interrupt, assuming the FW is stuck */
+ set_bit(STATUS_FW_ERROR, &fwrt->trans->status);
+
+ clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
+ }
+
+ /* Assuming the op mode mutex is held at this point */
+ iwl_fw_dbg_collect_sync(fwrt);
+
+ iwl_trans_stop_device(fwrt->trans);
+}
+IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 6aabbdd72326..a199056234d3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -8,7 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -102,13 +102,18 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
if (fwrt->dump.desc != &iwl_dump_desc_assert)
kfree(fwrt->dump.desc);
fwrt->dump.desc = NULL;
- fwrt->dump.rt_status = 0;
+ fwrt->dump.lmac_err_id[0] = 0;
+ if (fwrt->smem_cfg.num_lmacs > 1)
+ fwrt->dump.lmac_err_id[1] = 0;
+ fwrt->dump.umac_err_id = 0;
}
void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc,
bool monitor_only, unsigned int delay);
+int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_dbg_trigger trig_type);
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig,
const char *str, size_t len,
@@ -157,9 +162,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt,
}
static inline bool
-iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms)
+iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec)
{
- unsigned long wind_jiff = msecs_to_jiffies(dis_ms);
+ unsigned long wind_jiff = usecs_to_jiffies(dis_usec);
/* If this is the first event checked, jump to update start ts */
if (fwrt->dump.non_collect_ts_start[id] &&
@@ -176,11 +181,12 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
struct iwl_fw_dbg_trigger_tlv *trig)
{
+ u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC;
+
if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev))
return false;
- if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id),
- le16_to_cpu(trig->trig_dis_ms))) {
+ if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) {
IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n",
trig->id);
return false;
@@ -217,23 +223,22 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
})
static inline bool
-_iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
- const enum iwl_fw_dbg_trigger id)
+iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_ini_trigger_id id)
{
- struct iwl_fw_ini_active_triggers *trig = &fwrt->dump.active_trigs[id];
- u32 ms;
+ struct iwl_fw_ini_trigger *trig;
+ u32 usec;
- if (!fwrt->trans->ini_valid)
- return false;
- if (!trig || !trig->active)
+
+ if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM ||
+ !fwrt->dump.active_trigs[id].active)
return false;
- ms = le32_to_cpu(trig->conf->ignore_consec);
- if (ms)
- ms /= USEC_PER_MSEC;
+ trig = fwrt->dump.active_trigs[id].trig;
+ usec = le32_to_cpu(trig->ignore_consec);
- if (iwl_fw_dbg_no_trig_window(fwrt, id, ms)) {
+ if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) {
IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id);
return false;
}
@@ -241,12 +246,6 @@ _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
return true;
}
-#define iwl_fw_ini_trigger_on(fwrt, wdev, id) ({ \
- BUILD_BUG_ON(!__builtin_constant_p(id)); \
- BUILD_BUG_ON((id) >= IWL_FW_TRIGGER_ID_NUM); \
- _iwl_fw_ini_trigger_on((fwrt), (wdev), (id)); \
-})
-
static inline void
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
@@ -266,20 +265,20 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig)))
-static int iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start)
+static inline int
+iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start)
{
- struct iwl_continuous_record_cmd cont_rec = {};
+ struct iwl_ldbg_config_cmd cmd = {
+ .type = start ? cpu_to_le32(START_DEBUG_RECORDING) :
+ cpu_to_le32(STOP_DEBUG_RECORDING),
+ };
struct iwl_host_cmd hcmd = {
.id = LDBG_CONFIG_CMD,
.flags = CMD_ASYNC,
- .data[0] = &cont_rec,
- .len[0] = sizeof(cont_rec),
+ .data[0] = &cmd,
+ .len[0] = sizeof(cmd),
};
- cont_rec.record_mode.enable_recording = start ?
- cpu_to_le16(START_DEBUG_RECORDING) :
- cpu_to_le16(STOP_DEBUG_RECORDING);
-
return iwl_trans_send_cmd(fwrt->trans, &hcmd);
}
@@ -293,13 +292,13 @@ _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
}
if (params) {
- params->in_sample = iwl_read_prph(trans, DBGC_IN_SAMPLE);
- params->out_ctrl = iwl_read_prph(trans, DBGC_OUT_CTRL);
+ params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE);
+ params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL);
}
- iwl_write_prph(trans, DBGC_IN_SAMPLE, 0);
+ iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
udelay(100);
- iwl_write_prph(trans, DBGC_OUT_CTRL, 0);
+ iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
#ifdef CONFIG_IWLWIFI_DEBUGFS
trans->dbg_rec_on = false;
#endif
@@ -327,9 +326,9 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
} else {
- iwl_write_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
+ iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
udelay(100);
- iwl_write_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
+ iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
}
}
@@ -370,7 +369,9 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
{
return fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
- fwrt->trans->cfg->d3_debug_data_length &&
+ fwrt->trans->cfg->d3_debug_data_length && fwrt->ops &&
+ fwrt->ops->d3_debug_enable &&
+ fwrt->ops->d3_debug_enable(fwrt->ops_ctx) &&
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
}
@@ -378,6 +379,7 @@ static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
{
return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) &&
!fwrt->trans->cfg->gen2 &&
+ fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block;
}
@@ -430,10 +432,33 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
-void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt);
-void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt);
void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt);
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_apply_point apply_point);
+void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
+
+static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
+ u32 lmac_error_event_table)
+{
+ if (!(trans->error_event_table_tlv_status &
+ IWL_ERROR_EVENT_TABLE_LMAC1) ||
+ WARN_ON(trans->lmac_error_event_table[0] !=
+ lmac_error_event_table))
+ trans->lmac_error_event_table[0] = lmac_error_event_table;
+}
+
+static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
+ u32 umac_error_event_table)
+{
+ if (!(trans->error_event_table_tlv_status &
+ IWL_ERROR_EVENT_TABLE_UMAC) ||
+ WARN_ON(trans->umac_error_event_table !=
+ umac_error_event_table))
+ trans->umac_error_event_table = umac_error_event_table;
+}
+
+/* This bit is used to differentiate the legacy dump from the ini dump */
+#define INI_DUMP_BIT BIT(31)
+
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index 3e120dd47305..c1aa4360736b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -173,9 +173,8 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
_FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime)
#define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \
- if (!debugfs_create_file(alias, mode, parent, fwrt, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(alias, mode, parent, fwrt, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
@@ -321,14 +320,10 @@ out:
FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512);
-int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
+void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir)
{
INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk);
FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200);
FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200);
- return 0;
-err:
- IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n");
- return -ENOMEM;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h
index 88255035e8ef..fde40ff88451 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h
@@ -63,14 +63,11 @@
#include "runtime.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
+void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir);
#else
-static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
- struct dentry *dbgfs_dir)
-{
- return 0;
-}
+static inline void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
+ struct dentry *dbgfs_dir) { }
#endif /* CONFIG_IWLWIFI_DEBUGFS */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 65faecf552cd..9b5077bd46c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -8,7 +8,7 @@
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,6 +180,8 @@ enum iwl_fw_error_dump_family {
IWL_FW_ERROR_DUMP_FAMILY_8 = 8,
};
+#define MAX_NUM_LMAC 2
+
/**
* struct iwl_fw_error_dump_info - info on the device / firmware
* @device_family: the family of the device (7 / 8)
@@ -187,7 +189,10 @@ enum iwl_fw_error_dump_family {
* @fw_human_readable: human readable FW version
* @dev_human_readable: name of the device
* @bus_human_readable: name of the bus used
- * @rt_status: the error_id/rt_status that that triggered the latest dump
+ * @num_of_lmacs: the number of lmacs
+ * @lmac_err_id: the lmac 0/1 error_id/rt_status that triggered the latest dump
+ * if the dump collection was not initiated by an assert, the value is 0
+ * @umac_err_id: the umac error_id/rt_status that triggered the latest dump
* if the dump collection was not initiated by an assert, the value is 0
*/
struct iwl_fw_error_dump_info {
@@ -196,7 +201,9 @@ struct iwl_fw_error_dump_info {
u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
u8 dev_human_readable[64];
u8 bus_human_readable[8];
- __le32 rt_status;
+ u8 num_of_lmacs;
+ __le32 umac_err_id;
+ __le32 lmac_err_id[MAX_NUM_LMAC];
} __packed;
/**
@@ -268,22 +275,68 @@ struct iwl_fw_error_dump_mem {
};
/**
- * struct iwl_fw_error_dump_named_mem - chunk of memory
- * @type: &enum iwl_fw_error_dump_mem_type
- * @offset: the offset from which the memory was read
- * @name_len: name length
- * @name: file name
- * @data: the content of the memory
+ * struct iwl_fw_ini_error_dump_range - range of memory
+ * @start_addr: the start address of this range
+ * @range_data_size: the size of this range, in bytes
+ * @data: the actual memory
*/
-struct iwl_fw_error_dump_named_mem {
- __le32 type;
- __le32 offset;
- u8 name_len;
- u8 name[32];
- u8 data[];
+struct iwl_fw_ini_error_dump_range {
+ __le32 start_addr;
+ __le32 range_data_size;
+ __le32 data[];
+} __packed;
+
+/**
+ * struct iwl_fw_ini_error_dump_header - ini region dump header
+ * @num_of_ranges: number of ranges in this region
+ * @name_len: number of bytes allocated to the name string of this region
+ * @name: name of the region
+ */
+struct iwl_fw_ini_error_dump_header {
+ __le32 num_of_ranges;
+ __le32 name_len;
+ u8 name[IWL_FW_INI_MAX_NAME];
};
/**
+ * struct iwl_fw_ini_error_dump - ini region dump
+ * @header: the header of this region
+ * @ranges: the memory ranges of this region
+ */
+struct iwl_fw_ini_error_dump {
+ struct iwl_fw_ini_error_dump_header header;
+ struct iwl_fw_ini_error_dump_range ranges[];
+} __packed;
+
+/* This bit is used to differentiate between lmac and umac rxf */
+#define IWL_RXF_UMAC_BIT BIT(31)
+
+/**
+ * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump
+ * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to
+ * distinguish between lmac and umac
+ * @num_of_registers: num of registers to dump, dword size each
+ * @range_data_size: the size of the registers and fifo data
+ * @data: fifo data
+ */
+struct iwl_fw_ini_fifo_error_dump_range {
+ __le32 fifo_num;
+ __le32 num_of_registers;
+ __le32 range_data_size;
+ __le32 data[];
+} __packed;
+
+/**
+ * struct iwl_fw_ini_fifo_error_dump - ini fifo region dump
+ * @header: the header of this region
+ * @ranges: the memory ranges of this region
+ */
+struct iwl_fw_ini_fifo_error_dump {
+ struct iwl_fw_ini_error_dump_header header;
+ struct iwl_fw_ini_fifo_error_dump_range ranges[];
+} __packed;
+
+/**
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
* @index: the index of the Receive Buffer in the Rx queue
* @rxq: the RB's Rx queue
@@ -298,6 +351,20 @@ struct iwl_fw_error_dump_rb {
};
/**
+ * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump
+ * @header - header of the region
+ * @write_ptr - write pointer position in the dram
+ * @cycle_cnt - cycles count
+ * @ranges - the memory ranges of this this region
+ */
+struct iwl_fw_ini_monitor_dram_dump {
+ struct iwl_fw_ini_error_dump_header header;
+ __le32 write_ptr;
+ __le32 cycle_cnt;
+ struct iwl_fw_ini_error_dump_range ranges[];
+} __packed;
+
+/**
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
* block on DRAM
* @index: the index of the page block
@@ -348,7 +415,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
* @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when
* the firmware sends a tx reply.
- * @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails
+ * @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts
+ * @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure
+ * in the driver.
*/
enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_INVALID = 0,
@@ -366,7 +435,8 @@ enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_TX_LATENCY,
FW_DBG_TRIGGER_TDLS,
FW_DBG_TRIGGER_TX_STATUS,
- FW_DBG_TRIGGER_NO_ALIVE,
+ FW_DBG_TRIGGER_ALIVE_TIMEOUT,
+ FW_DBG_TRIGGER_DRIVER,
/* must be last */
FW_DBG_TRIGGER_MAX,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 81f557c0b58d..641c95d03b15 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -9,6 +9,7 @@
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2019 Intel Corporation
*
* 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
@@ -32,6 +33,7 @@
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -143,6 +145,9 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
IWL_UCODE_TLV_FW_MEM_SEG = 51,
IWL_UCODE_TLV_IML = 52,
+ IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54,
+ IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55,
+ IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1,
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2,
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3,
@@ -263,6 +268,12 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS
* @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of
* the REDUCE_TX_POWER_CMD.
+ * @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short
+ * version of the beacon notification.
+ * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
+ * BEACON_FILTER_CONFIG_API_S_VER_4.
+ * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
+ * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
@@ -287,6 +298,9 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42,
IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44,
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
+ IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
+ IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
+ IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
@@ -303,7 +317,6 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory
* @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.
* @IWL_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer
- * @IWL_UCODE_TLV_CAPA_TOF_SUPPORT: supports Time of Flight (802.11mc FTM)
* @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality
* @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
* tx power value into TPC Report action frame and Link Measurement Report
@@ -334,6 +347,9 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm
* @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related
* @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2
+ * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
+ * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
+ * (6 GHz).
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -357,19 +373,24 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_TX_POWER_ACK: reduced TX power API has larger
* command size (command version 4) that supports toggling ACK TX
* power reduction.
- * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
* @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3
* @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax
* capability.
+ * @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured
+ * to report the CSI information with (certain) RX frames
+ * @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both
+ * initiator and responder
+ *
+ * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
enum iwl_ucode_tlv_capa {
+ /* set 0 */
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1,
IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2,
IWL_UCODE_TLV_CAPA_BEAMFORMER = (__force iwl_ucode_tlv_capa_t)3,
- IWL_UCODE_TLV_CAPA_TOF_SUPPORT = (__force iwl_ucode_tlv_capa_t)5,
IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = (__force iwl_ucode_tlv_capa_t)6,
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = (__force iwl_ucode_tlv_capa_t)8,
IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = (__force iwl_ucode_tlv_capa_t)9,
@@ -387,6 +408,8 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
+
+ /* set 1 */
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
@@ -394,6 +417,11 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43,
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44,
IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
+ IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
+ IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
+
+ /* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
@@ -412,6 +440,9 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_D3_DEBUG = (__force iwl_ucode_tlv_capa_t)87,
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
+ IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
+
+ /* set 3 */
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
NUM_IWL_UCODE_TLV_CAPA
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index 12333167ea23..f4c5a4d73206 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -105,6 +105,8 @@ struct iwl_ucode_capabilities {
u32 n_scan_channels;
u32 standard_phy_calibration_size;
u32 flags;
+ u32 error_log_addr;
+ u32 error_log_size;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
};
@@ -223,27 +225,24 @@ struct iwl_fw_dbg {
};
/**
+ * @tlv: the buffer allocation tlv
+ * @is_alloc: indicates if the buffer was already allocated
+ */
+struct iwl_fw_ini_allocation_data {
+ struct iwl_fw_ini_allocation_tlv tlv;
+ u32 is_alloc;
+} __packed;
+
+/**
* struct iwl_fw_ini_active_triggers
* @active: is this trigger active
- * @apply_point: last apply point that updated this trigger
- * @conf: active trigger
- * @conf_ext: second trigger, contains extra regions to dump
+ * @size: allocated memory size of the trigger
+ * @trig: trigger
*/
struct iwl_fw_ini_active_triggers {
bool active;
- enum iwl_fw_ini_apply_point apply_point;
- struct iwl_fw_ini_trigger *conf;
- struct iwl_fw_ini_trigger *conf_ext;
-};
-
-/**
- * struct iwl_fw_ini_active_regs
- * @reg: active region from TLV
- * @apply_point: apply point where it became active
- */
-struct iwl_fw_ini_active_regs {
- struct iwl_fw_ini_region_cfg *reg;
- enum iwl_fw_ini_apply_point apply_point;
+ size_t size;
+ struct iwl_fw_ini_trigger *trig;
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
index 2efac307909e..7adf4e4e841a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright(c) 2019 Intel Corporation
*
* 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
@@ -26,6 +27,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright(c) 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,6 +76,7 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
fwrt->ops_ctx = ops_ctx;
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
+ init_waitqueue_head(&fwrt->trans->fw_halt_waitq);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index 4f7090f88cb0..a5fe1a8ca426 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
*
* 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
@@ -27,7 +27,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,7 @@ struct iwl_fw_runtime_ops {
void (*dump_end)(void *ctx);
bool (*fw_running)(void *ctx);
int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
+ bool (*d3_debug_enable)(void *ctx);
};
#define MAX_NUM_LMAC 2
@@ -90,7 +91,6 @@ struct iwl_fwrt_shared_mem_cfg {
enum iwl_fw_runtime_status {
IWL_FWRT_STATUS_DUMPING = 0,
- IWL_FWRT_STATUS_WAIT_ALIVE,
};
/**
@@ -138,11 +138,13 @@ struct iwl_fw_runtime {
u8 conf;
/* ts of the beginning of a non-collect fw dbg data period */
- unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1];
+ unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM];
u32 *d3_debug_data;
- struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID];
+ struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID];
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
- u32 rt_status;
+ u32 lmac_err_id[MAX_NUM_LMAC];
+ u32 umac_err_id;
+ void *fifo_iter;
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
@@ -160,8 +162,20 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
{
+ int i;
+
kfree(fwrt->dump.d3_debug_data);
fwrt->dump.d3_debug_data = NULL;
+
+ for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) {
+ struct iwl_fw_ini_active_triggers *active =
+ &fwrt->dump.active_trigs[i];
+
+ active->active = false;
+ active->size = 0;
+ kfree(active->trig);
+ active->trig = NULL;
+ }
}
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 91861a9cbe57..f5f87773667b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -29,7 +29,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,6 +89,7 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_9000,
IWL_DEVICE_FAMILY_22000,
IWL_DEVICE_FAMILY_22560,
+ IWL_DEVICE_FAMILY_AX210,
};
/*
@@ -335,10 +336,6 @@ struct iwl_csr_params {
* @fw_name_pre: Firmware filename prefix. The api version and extension
* (.ucode) will be added to filename before loading from disk. The
* filename is constructed as fw_name_pre<api>.ucode.
- * @fw_name_pre_b_or_c_step: same as @fw_name_pre, only for b or c steps
- * (if supported)
- * @fw_name_pre_rf_next_step: same as @fw_name_pre_b_or_c_step, only for rf
- * next step. Supported only in integrated solutions.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section (only DVM)
@@ -383,6 +380,9 @@ struct iwl_csr_params {
* @nvm_type: see &enum iwl_nvm_type
* @d3_debug_data_base_addr: base address where D3 debug data is stored
* @d3_debug_data_length: length of the D3 debug data
+ * @bisr_workaround: BISR hardware workaround (for 22260 series devices)
+ * @min_txq_size: minimum number of slots required in a TX queue
+ * @umac_prph_offset: offset to add to UMAC periphery address
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -392,8 +392,6 @@ struct iwl_cfg {
/* params specific to an individual device within a device family */
const char *name;
const char *fw_name_pre;
- const char *fw_name_pre_b_or_c_step;
- const char *fw_name_pre_rf_next_step;
/* params not likely to change within a device family */
const struct iwl_base_params *base_params;
/* params likely to change within a device family */
@@ -434,7 +432,8 @@ struct iwl_cfg {
use_tfh:1,
gen2:1,
cdb:1,
- dbgc_supported:1;
+ dbgc_supported:1,
+ bisr_workaround:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
@@ -449,37 +448,12 @@ struct iwl_cfg {
u32 extra_phy_cfg_flags;
u32 d3_debug_data_base_addr;
u32 d3_debug_data_length;
+ u32 min_txq_size;
+ u32 umac_prph_offset;
};
-static const struct iwl_csr_params iwl_csr_v1 = {
- .flag_mac_clock_ready = 0,
- .flag_val_mac_access_en = 0,
- .flag_init_done = 2,
- .flag_mac_access_req = 3,
- .flag_sw_reset = 7,
- .flag_master_dis = 8,
- .flag_stop_master = 9,
- .addr_sw_reset = (CSR_BASE + 0x020),
- .mac_addr0_otp = 0x380,
- .mac_addr1_otp = 0x384,
- .mac_addr0_strap = 0x388,
- .mac_addr1_strap = 0x38C
-};
-
-static const struct iwl_csr_params iwl_csr_v2 = {
- .flag_init_done = 6,
- .flag_mac_clock_ready = 20,
- .flag_val_mac_access_en = 20,
- .flag_mac_access_req = 21,
- .flag_master_dis = 28,
- .flag_stop_master = 29,
- .flag_sw_reset = 31,
- .addr_sw_reset = (CSR_BASE + 0x024),
- .mac_addr0_otp = 0x30,
- .mac_addr1_otp = 0x34,
- .mac_addr0_strap = 0x38,
- .mac_addr1_strap = 0x3C
-};
+extern const struct iwl_csr_params iwl_csr_v1;
+extern const struct iwl_csr_params iwl_csr_v2;
/*
* This list declares the config structures for all devices.
@@ -551,38 +525,53 @@ extern const struct iwl_cfg iwl8275_2ac_cfg;
extern const struct iwl_cfg iwl4165_2ac_cfg;
extern const struct iwl_cfg iwl9160_2ac_cfg;
extern const struct iwl_cfg iwl9260_2ac_cfg;
+extern const struct iwl_cfg iwl9260_2ac_160_cfg;
extern const struct iwl_cfg iwl9260_killer_2ac_cfg;
extern const struct iwl_cfg iwl9270_2ac_cfg;
extern const struct iwl_cfg iwl9460_2ac_cfg;
extern const struct iwl_cfg iwl9560_2ac_cfg;
+extern const struct iwl_cfg iwl9560_2ac_160_cfg;
extern const struct iwl_cfg iwl9460_2ac_cfg_soc;
extern const struct iwl_cfg iwl9461_2ac_cfg_soc;
extern const struct iwl_cfg iwl9462_2ac_cfg_soc;
extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
+extern const struct iwl_cfg iwl9560_2ac_160_cfg_soc;
extern const struct iwl_cfg iwl9560_killer_2ac_cfg_soc;
extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc;
extern const struct iwl_cfg iwl9460_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9461_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9462_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk;
+extern const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk;
extern const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
+extern const struct iwl_cfg iwl_ax101_cfg_qu_hr;
extern const struct iwl_cfg iwl22000_2ax_cfg_hr;
+extern const struct iwl_cfg iwl22260_2ax_cfg;
+extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
+extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
+extern const struct iwl_cfg killer1650x_2ax_cfg;
+extern const struct iwl_cfg killer1650w_2ax_cfg;
extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0;
+extern const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl22000_2ax_cfg_jf;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0;
-extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0;
+extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0;
extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb;
+extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0;
+extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
+extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0;
+extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
#endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index caa5806acd81..aea6d03e545a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -180,6 +180,7 @@
/* Bits for CSR_HW_IF_CONFIG_REG */
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
+#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080)
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
@@ -325,12 +326,16 @@ enum {
#define CSR_HW_REV_TYPE_7265D (0x0000210)
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
+#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
+#define CSR_HW_REV_TYPE_SO (0x0000370)
+#define CSR_HW_REV_TYPE_TY (0x0000420)
/* RF_ID value */
#define CSR_HW_RF_ID_TYPE_JF (0x00105100)
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
+#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
/* HW_RF CHIP ID */
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
@@ -592,6 +597,7 @@ enum msix_hw_int_causes {
MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0),
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
MSIX_HW_INT_CAUSES_REG_IPC = BIT(1),
+ MSIX_HW_INT_CAUSES_REG_IML = BIT(2),
MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5),
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index 43d815cb3ce9..5798f434f68f 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -71,6 +71,7 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
u32 apply_point = le32_to_cpu(header->apply_point);
int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
+ int offset_size = copy_size;
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
"Invalid apply point id %d\n", apply_point))
@@ -81,17 +82,25 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
else
data = &trans->apply_points[apply_point];
+ /* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */
+ if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
+ struct iwl_fw_ini_allocation_data *buf_alloc =
+ (void *)tlv->data;
+
+ offset_size += sizeof(buf_alloc->is_alloc);
+ }
+
/*
* Make sure we still have room to copy this TLV. Offset points to the
* location the last copy ended.
*/
- if (WARN_ONCE(data->offset + copy_size > data->size,
+ if (WARN_ONCE(data->offset + offset_size > data->size,
"Not enough memory for apply point %d\n",
apply_point))
return;
memcpy(data->data + data->offset, (void *)tlv, copy_size);
- data->offset += copy_size;
+ data->offset += offset_size;
}
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
@@ -129,6 +138,16 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM))
continue;
+ /* add room for is_alloc field in &iwl_fw_ini_allocation_data
+ * struct
+ */
+ if (tlv_type == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
+ struct iwl_fw_ini_allocation_data *buf_alloc =
+ (void *)tlv->data;
+
+ size[apply] += sizeof(buf_alloc->is_alloc);
+ }
+
size[apply] += sizeof(*tlv) + tlv_len;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
index a2af68a0d34b..655ff5694560 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project.
*
@@ -159,7 +160,7 @@ do { \
/* 0x000F0000 - 0x00010000 */
#define IWL_DL_FW 0x00010000
#define IWL_DL_RF_KILL 0x00020000
-#define IWL_DL_FW_ERRORS 0x00040000
+#define IWL_DL_TPT 0x00040000
/* 0x00F00000 - 0x00100000 */
#define IWL_DL_RATE 0x00100000
#define IWL_DL_CALIB 0x00200000
@@ -193,7 +194,6 @@ do { \
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
-#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a)
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
@@ -215,6 +215,7 @@ do { \
#define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)
+#define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a)
#define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
#define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index bf1be985f36b..689a65b11cc3 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -8,6 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,6 +77,7 @@
#include "iwl-dbg-tlv.h"
#include "iwl-config.h"
#include "iwl-modparams.h"
+#include "fw/api/alive.h"
/******************************************************************************
*
@@ -210,18 +213,15 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
{
const struct iwl_cfg *cfg = drv->trans->cfg;
char tag[8];
- const char *fw_pre_name;
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
- (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_B_STEP ||
- CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_C_STEP))
- fw_pre_name = cfg->fw_name_pre_b_or_c_step;
- else if (drv->trans->cfg->integrated &&
- CSR_HW_RFID_STEP(drv->trans->hw_rf_id) == SILICON_B_STEP &&
- cfg->fw_name_pre_rf_next_step)
- fw_pre_name = cfg->fw_name_pre_rf_next_step;
- else
- fw_pre_name = cfg->fw_name_pre;
+ (CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP &&
+ CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) {
+ IWL_ERR(drv,
+ "Only HW steps B and C are currently supported (0x%0x)\n",
+ drv->trans->hw_rev);
+ return -EINVAL;
+ }
if (first) {
drv->fw_index = cfg->ucode_api_max;
@@ -235,15 +235,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
IWL_ERR(drv, "no suitable firmware found!\n");
if (cfg->ucode_api_min == cfg->ucode_api_max) {
- IWL_ERR(drv, "%s%d is required\n", fw_pre_name,
+ IWL_ERR(drv, "%s%d is required\n", cfg->fw_name_pre,
cfg->ucode_api_max);
} else {
IWL_ERR(drv, "minimum version required: %s%d\n",
- fw_pre_name,
- cfg->ucode_api_min);
+ cfg->fw_name_pre, cfg->ucode_api_min);
IWL_ERR(drv, "maximum version supported: %s%d\n",
- fw_pre_name,
- cfg->ucode_api_max);
+ cfg->fw_name_pre, cfg->ucode_api_max);
}
IWL_ERR(drv,
@@ -252,7 +250,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
}
snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode",
- fw_pre_name, tag);
+ cfg->fw_name_pre, tag);
IWL_DEBUG_INFO(drv, "attempting to load firmware '%s'\n",
drv->firmware_name);
@@ -593,6 +591,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
return 0;
}
+#define FW_ADDR_CACHE_CONTROL 0xC0000000
+
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces,
@@ -1090,6 +1090,52 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
return -ENOMEM;
break;
}
+ case IWL_UCODE_TLV_FW_RECOVERY_INFO: {
+ struct {
+ __le32 buf_addr;
+ __le32 buf_size;
+ } *recov_info = (void *)tlv_data;
+
+ if (tlv_len != sizeof(*recov_info))
+ goto invalid_tlv_len;
+ capa->error_log_addr =
+ le32_to_cpu(recov_info->buf_addr);
+ capa->error_log_size =
+ le32_to_cpu(recov_info->buf_size);
+ }
+ break;
+ case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
+ struct iwl_umac_debug_addrs *dbg_ptrs =
+ (void *)tlv_data;
+
+ if (tlv_len != sizeof(*dbg_ptrs))
+ goto invalid_tlv_len;
+ if (drv->trans->cfg->device_family <
+ IWL_DEVICE_FAMILY_22000)
+ break;
+ drv->trans->umac_error_event_table =
+ le32_to_cpu(dbg_ptrs->error_info_addr) &
+ ~FW_ADDR_CACHE_CONTROL;
+ drv->trans->error_event_table_tlv_status |=
+ IWL_ERROR_EVENT_TABLE_UMAC;
+ break;
+ }
+ case IWL_UCODE_TLV_LMAC_DEBUG_ADDRS: {
+ struct iwl_lmac_debug_addrs *dbg_ptrs =
+ (void *)tlv_data;
+
+ if (tlv_len != sizeof(*dbg_ptrs))
+ goto invalid_tlv_len;
+ if (drv->trans->cfg->device_family <
+ IWL_DEVICE_FAMILY_22000)
+ break;
+ drv->trans->lmac_error_event_table[0] =
+ le32_to_cpu(dbg_ptrs->error_event_table_ptr) &
+ ~FW_ADDR_CACHE_CONTROL;
+ drv->trans->error_event_table_tlv_status |=
+ IWL_ERROR_EVENT_TABLE_LMAC1;
+ break;
+ }
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
@@ -1207,11 +1253,6 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
#ifdef CONFIG_IWLWIFI_DEBUGFS
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
drv->dbgfs_drv);
- if (!drv->dbgfs_op_mode) {
- IWL_ERR(drv,
- "failed to create opmode debugfs directory\n");
- return op_mode;
- }
dbgfs_dir = drv->dbgfs_op_mode;
#endif
@@ -1267,8 +1308,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->ucode_capa.standard_phy_calibration_size =
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
- /* dump all fw memory areas by default except d3 debug data */
- fw->dbg.dump_mask = 0xfffdffff;
+ /* dump all fw memory areas by default */
+ fw->dbg.dump_mask = 0xffffffff;
pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
if (!pieces)
@@ -1574,20 +1615,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
iwl_dbgfs_root);
- if (!drv->dbgfs_drv) {
- IWL_ERR(drv, "failed to create debugfs directory\n");
- ret = -ENOMEM;
- goto err_free_tlv;
- }
-
/* Create transport layer debugfs dir */
drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv);
-
- if (!drv->trans->dbgfs_dir) {
- IWL_ERR(drv, "failed to create transport debugfs directory\n");
- ret = -ENOMEM;
- goto err_free_dbgfs;
- }
#endif
ret = iwl_request_firmware(drv, true);
@@ -1600,9 +1629,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
err_fw:
#ifdef CONFIG_IWLWIFI_DEBUGFS
-err_free_dbgfs:
debugfs_remove_recursive(drv->dbgfs_drv);
-err_free_tlv:
iwl_fw_dbg_free(drv->trans);
#endif
kfree(drv);
@@ -1713,9 +1740,6 @@ static int __init iwl_drv_init(void)
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* Create the root of iwlwifi debugfs subsystem. */
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
-
- if (!iwl_dbgfs_root)
- return -EFAULT;
#endif
return iwl_pci_register_driver();
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c
index 75940ac406b9..04338c3a6205 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c
@@ -850,8 +850,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
if (WARN_ON(!cfg || !cfg->eeprom_params))
return NULL;
- data = kzalloc(sizeof(*data) +
- sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
+ data = kzalloc(struct_size(data, channels, IWL_NUM_CHANNELS),
GFP_KERNEL);
if (!data)
return NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
index a6db6a814257..82e87192119e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
@@ -193,34 +193,25 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
{
int ret;
- /* Enable 40MHz radio clock */
- iwl_write32(trans, CSR_GP_CNTRL,
- iwl_read32(trans, CSR_GP_CNTRL) |
- BIT(trans->cfg->csr->flag_init_done));
-
- /* wait for clock to be ready */
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (ret < 0) {
- IWL_ERR(trans, "Time out access OTP\n");
- } else {
- iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_RESET_REQ);
- udelay(5);
- iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_RESET_REQ);
-
- /*
- * CSR auto clock gate disable bit -
- * this is only applicable for HW with OTP shadow RAM
- */
- if (trans->cfg->base_params->shadow_ram_support)
- iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
- CSR_RESET_LINK_PWR_MGMT_DISABLED);
- }
- return ret;
+ ret = iwl_finish_nic_init(trans);
+ if (ret)
+ return ret;
+
+ iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_RESET_REQ);
+ udelay(5);
+ iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_RESET_REQ);
+
+ /*
+ * CSR auto clock gate disable bit -
+ * this is only applicable for HW with OTP shadow RAM
+ */
+ if (trans->cfg->base_params->shadow_ram_support)
+ iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
+
+ return 0;
}
static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 4f10914f6048..a704e25af810 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -1,9 +1,13 @@
/******************************************************************************
*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- *
- * Portions of this file are derived from the ipw3945 project.
+ * Copyright(C) 2018 - 2019 Intel Corporation
*
* 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
@@ -15,12 +19,45 @@
* more details.
*
* The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
+ * file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright (C) 2018 - 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 <linux/delay.h>
#include <linux/device.h>
@@ -33,6 +70,36 @@
#include "iwl-prph.h"
#include "iwl-fh.h"
+const struct iwl_csr_params iwl_csr_v1 = {
+ .flag_mac_clock_ready = 0,
+ .flag_val_mac_access_en = 0,
+ .flag_init_done = 2,
+ .flag_mac_access_req = 3,
+ .flag_sw_reset = 7,
+ .flag_master_dis = 8,
+ .flag_stop_master = 9,
+ .addr_sw_reset = CSR_BASE + 0x020,
+ .mac_addr0_otp = 0x380,
+ .mac_addr1_otp = 0x384,
+ .mac_addr0_strap = 0x388,
+ .mac_addr1_strap = 0x38C
+};
+
+const struct iwl_csr_params iwl_csr_v2 = {
+ .flag_init_done = 6,
+ .flag_mac_clock_ready = 20,
+ .flag_val_mac_access_en = 20,
+ .flag_mac_access_req = 21,
+ .flag_master_dis = 28,
+ .flag_stop_master = 29,
+ .flag_sw_reset = 31,
+ .addr_sw_reset = CSR_BASE + 0x024,
+ .mac_addr0_otp = 0x30,
+ .mac_addr1_otp = 0x34,
+ .mac_addr0_strap = 0x38,
+ .mac_addr1_strap = 0x3C
+};
+
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
@@ -240,9 +307,12 @@ void iwl_force_nmi(struct iwl_trans *trans)
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_DRV);
+ else if (trans->cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
+ UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK);
else
- iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER,
- UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK);
+ iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
+ UREG_DOORBELL_TO_ISR6_NMI_BIT);
}
IWL_EXPORT_SYMBOL(iwl_force_nmi);
@@ -421,3 +491,43 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
return 0;
}
+
+int iwl_finish_nic_init(struct iwl_trans *trans)
+{
+ int err;
+
+ if (trans->cfg->bisr_workaround) {
+ /* ensure the TOP FSM isn't still in previous reset */
+ mdelay(2);
+ }
+
+ /*
+ * Set "initialization complete" bit to move adapter from
+ * D0U* --> D0A* (powered-up active) state.
+ */
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ BIT(trans->cfg->csr->flag_init_done));
+
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ udelay(2);
+
+ /*
+ * Wait for clock stabilization; once stabilized, access to
+ * device-internal resources is supported, e.g. iwl_write_prph()
+ * and accesses to uCode SRAM.
+ */
+ err = iwl_poll_bit(trans, CSR_GP_CNTRL,
+ BIT(trans->cfg->csr->flag_mac_clock_ready),
+ BIT(trans->cfg->csr->flag_mac_clock_ready),
+ 25000);
+ if (err < 0)
+ IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
+
+ if (trans->cfg->bisr_workaround) {
+ /* ensure BISR shift has finished */
+ udelay(200);
+ }
+
+ return err < 0 ? err : 0;
+}
+IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
index 38085850a2d3..920e2146ea3f 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
@@ -1,8 +1,11 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
*
- * Portions of this file are derived from the ipw3945 project.
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -14,14 +17,44 @@
* more details.
*
* The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
+ * file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
+ * BSD LICENSE
+ *
+ * Copyright (C) 2018 - 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 __iwl_io_h__
#define __iwl_io_h__
@@ -66,7 +99,48 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_force_nmi(struct iwl_trans *trans);
+int iwl_finish_nic_init(struct iwl_trans *trans);
+
/* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
+/*
+ * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
+ * device family AX200. So peripheries used in families above and below AX200
+ * should go through iwl_..._umac_..._prph.
+ */
+static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
+{
+ return ofs + trans->cfg->umac_prph_offset;
+}
+
+static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
+{
+ return iwl_read_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset);
+}
+
+static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
+{
+ return iwl_read_prph(trans, ofs + trans->cfg->umac_prph_offset);
+}
+
+static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
+ u32 val)
+{
+ iwl_write_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset, val);
+}
+
+static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
+ u32 val)
+{
+ iwl_write_prph(trans, ofs + trans->cfg->umac_prph_offset, val);
+}
+
+static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
+ u32 bits, u32 mask, int timeout)
+{
+ return iwl_poll_prph_bit(trans, addr + trans->cfg->umac_prph_offset,
+ bits, mask, timeout);
+}
+
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
index 73b1c46f1158..0cae2ef9b9df 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
@@ -152,4 +152,22 @@ struct iwl_mod_params {
bool enable_ini;
};
+static inline bool iwl_enable_rx_ampdu(void)
+{
+ if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+ return false;
+ return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(void)
+{
+ if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+ return false;
+ if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+ return true;
+
+ /* enabled by default */
+ return true;
+}
+
#endif /* #__iwl_modparams_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index d9afedc3d1d9..87d6de7efdd2 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -8,7 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -463,6 +463,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
}
vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
+
+ vht_cap->vht_mcs.tx_highest |=
+ cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
}
static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
@@ -479,7 +482,6 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
.mac_cap_info[2] =
IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP |
- IEEE80211_HE_MAC_CAP2_MU_CASCADING |
IEEE80211_HE_MAC_CAP2_ACK_EN,
.mac_cap_info[3] =
IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
@@ -490,7 +492,9 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
.mac_cap_info[5] =
IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 |
IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 |
- IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU,
+ IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
+ IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS |
+ IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX,
.phy_cap_info[0] =
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
@@ -498,18 +502,13 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
.phy_cap_info[1] =
IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
- IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
- IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS,
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
.phy_cap_info[2] =
- IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
- IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
- IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
- IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
- IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,
+ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US,
.phy_cap_info[3] =
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,
.phy_cap_info[4] =
IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
@@ -517,16 +516,8 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,
.phy_cap_info[5] =
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
- IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 |
- IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
- IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK,
+ IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,
.phy_cap_info[6] =
- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
- IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
- IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB |
- IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
- IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO |
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
.phy_cap_info[7] =
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR |
@@ -537,11 +528,12 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
- IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ,
+ IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996,
.phy_cap_info[9] =
IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
- IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB,
+ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
},
/*
* Set default Tx/Rx HE MCS NSS Support field.
@@ -569,35 +561,32 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
.has_he = true,
.he_cap_elem = {
.mac_cap_info[0] =
- IEEE80211_HE_MAC_CAP0_HTC_HE |
- IEEE80211_HE_MAC_CAP0_TWT_RES,
+ IEEE80211_HE_MAC_CAP0_HTC_HE,
.mac_cap_info[1] =
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
.mac_cap_info[2] =
IEEE80211_HE_MAC_CAP2_BSR |
- IEEE80211_HE_MAC_CAP2_MU_CASCADING |
IEEE80211_HE_MAC_CAP2_ACK_EN,
.mac_cap_info[3] =
IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,
.mac_cap_info[4] =
IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU,
+ .mac_cap_info[5] =
+ IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU,
.phy_cap_info[0] =
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G,
.phy_cap_info[1] =
- IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
- IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS,
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
.phy_cap_info[2] =
- IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
- IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
- IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ,
+ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US,
.phy_cap_info[3] =
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,
.phy_cap_info[4] =
IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
@@ -605,12 +594,8 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,
.phy_cap_info[5] =
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
- IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 |
- IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
- IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK,
+ IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,
.phy_cap_info[6] =
- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
.phy_cap_info[7] =
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI |
@@ -620,10 +605,11 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
- IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ,
+ IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996,
.phy_cap_info[9] =
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
- IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB,
+ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
},
/*
* Set default Tx/Rx HE MCS NSS Support field.
@@ -947,15 +933,13 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const __le16 *ch_section;
if (cfg->nvm_type != IWL_NVM_EXT)
- data = kzalloc(sizeof(*data) +
- sizeof(struct ieee80211_channel) *
- IWL_NVM_NUM_CHANNELS,
- GFP_KERNEL);
+ data = kzalloc(struct_size(data, channels,
+ IWL_NVM_NUM_CHANNELS),
+ GFP_KERNEL);
else
- data = kzalloc(sizeof(*data) +
- sizeof(struct ieee80211_channel) *
- IWL_NVM_NUM_CHANNELS_EXT,
- GFP_KERNEL);
+ data = kzalloc(struct_size(data, channels,
+ IWL_NVM_NUM_CHANNELS_EXT),
+ GFP_KERNEL);
if (!data)
return NULL;
@@ -1103,12 +1087,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
- if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
- return ERR_PTR(-EINVAL);
-
if (WARN_ON(num_of_ch > max_num_ch))
num_of_ch = max_num_ch;
+ if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
+ return ERR_PTR(-EINVAL);
+
IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n",
num_of_ch);
@@ -1196,14 +1180,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
regd_to_copy = sizeof(struct ieee80211_regdomain) +
valid_rules * sizeof(struct ieee80211_reg_rule);
- copy_rd = kzalloc(regd_to_copy, GFP_KERNEL);
+ copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL);
if (!copy_rd) {
copy_rd = ERR_PTR(-ENOMEM);
goto out;
}
- memcpy(copy_rd, regd, regd_to_copy);
-
out:
kfree(regdb_ptrs);
kfree(regd);
@@ -1444,9 +1426,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
if (empty_otp)
IWL_INFO(trans, "OTP is empty\n");
- nvm = kzalloc(sizeof(*nvm) +
- sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
- GFP_KERNEL);
+ nvm = kzalloc(struct_size(nvm, channels, IWL_NUM_CHANNELS), GFP_KERNEL);
if (!nvm) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 9d89b7d7f9fa..1af9f9e1ecd4 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -358,12 +358,12 @@
/* FW monitor */
#define MON_BUFF_SAMPLE_CTL (0xa03c00)
-#define MON_BUFF_BASE_ADDR (0xa03c3c)
+#define MON_BUFF_BASE_ADDR (0xa03c1c)
#define MON_BUFF_END_ADDR (0xa03c40)
#define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48)
/* FW monitor family 8000 and on */
-#define MON_BUFF_BASE_ADDR_VER2 (0xa03c3c)
+#define MON_BUFF_BASE_ADDR_VER2 (0xa03c1c)
#define MON_BUFF_END_ADDR_VER2 (0xa03c20)
#define MON_BUFF_WRPTR_VER2 (0xa03c24)
#define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28)
@@ -433,4 +433,7 @@ enum {
#define HPM_DEBUG 0xA03440
#define PERSISTENCE_BIT BIT(12)
#define PREG_WFPM_ACCESS BIT(12)
+
+#define UREG_DOORBELL_TO_ISR6 0xA05C04
+#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
#endif /* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index a7009cd4232d..bbebbf3efd57 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -8,6 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -230,6 +232,12 @@ enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_DUP = BIT(1),
};
+enum iwl_error_event_table_status {
+ IWL_ERROR_EVENT_TABLE_LMAC1 = BIT(0),
+ IWL_ERROR_EVENT_TABLE_LMAC2 = BIT(1),
+ IWL_ERROR_EVENT_TABLE_UMAC = BIT(2),
+};
+
/**
* struct iwl_host_cmd - Host command to the uCode
*
@@ -330,6 +338,7 @@ enum iwl_d3_status {
* are sent
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
+ * @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump
*/
enum iwl_trans_status {
STATUS_SYNC_HCMD_ACTIVE,
@@ -342,6 +351,7 @@ enum iwl_trans_status {
STATUS_TRANS_GOING_IDLE,
STATUS_TRANS_IDLE,
STATUS_TRANS_DEAD,
+ STATUS_FW_WAIT_DUMP,
};
static inline int
@@ -684,6 +694,9 @@ enum iwl_plat_pm_mode {
*/
#define IWL_TRANS_IDLE_TIMEOUT 2000
+/* Max time to wait for nmi interrupt */
+#define IWL_TRANS_NMI_TIMEOUT (HZ / 4)
+
/**
* struct iwl_dram_data
* @physical: page phy pointer
@@ -697,6 +710,20 @@ struct iwl_dram_data {
};
/**
+ * struct iwl_self_init_dram - dram data used by self init process
+ * @fw: lmac and umac dram data
+ * @fw_cnt: total number of items in array
+ * @paging: paging dram data
+ * @paging_cnt: total number of items in array
+ */
+struct iwl_self_init_dram {
+ struct iwl_dram_data *fw;
+ int fw_cnt;
+ struct iwl_dram_data *paging;
+ int paging_cnt;
+};
+
+/**
* struct iwl_trans - transport common data
*
* @ops - pointer to iwl_trans_ops
@@ -738,6 +765,10 @@ struct iwl_dram_data {
* mode is set during the initialization phase and is not
* supposed to change during runtime.
* @dbg_rec_on: true iff there is a fw debug recording currently active
+ * @lmac_error_event_table: addrs of lmacs error tables
+ * @umac_error_event_table: addr of umac error table
+ * @error_event_table_tlv_status: bitmap that indicates what error table
+ * pointers was recevied via TLV. use enum &iwl_error_event_table_status
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@@ -790,12 +821,18 @@ struct iwl_trans {
u8 dbg_n_dest_reg;
int num_blocks;
struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM];
+ struct iwl_self_init_dram init_dram;
enum iwl_plat_pm_mode system_pm_mode;
enum iwl_plat_pm_mode runtime_pm_mode;
bool suspending;
bool dbg_rec_on;
+ u32 lmac_error_event_table[2];
+ u32 umac_error_event_table;
+ unsigned int error_event_table_tlv_status;
+ wait_queue_head_t fw_halt_waitq;
+
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
@@ -1202,6 +1239,10 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
/* prevent double restarts due to the same erroneous FW */
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status))
iwl_op_mode_nic_error(trans->op_mode);
+
+ if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status))
+ wake_up(&trans->fw_halt_waitq);
+
}
/*****************************************************
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
index 9ffd21918b5a..dd268c4bd371 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
@@ -5,9 +5,9 @@ iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o rs-fw.o
iwlmvm-y += power.o coex.o
iwlmvm-y += tt.o offloading.o tdls.o
+iwlmvm-y += ftm-responder.o ftm-initiator.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
-iwlmvm-y += tof.o
iwlmvm-$(CONFIG_PM) += d3.o
-ccflags-y += -I$(src)/../
+ccflags-y += -I $(srctree)/$(src)/../
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 730e37744dc0..3d2abbc5c76c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -241,7 +241,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
struct iwl_mvm_sta *mvmsta;
u32 value;
- int ret;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
if (!mvmsta)
@@ -262,10 +261,8 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
cmd.reduced_txp = cpu_to_le32(value);
mvmsta->bt_reduced_txpower = enable;
- ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC,
- sizeof(cmd), &cmd);
-
- return ret;
+ return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP,
+ CMD_ASYNC, sizeof(cmd), &cmd);
}
struct iwl_bt_iterator_data {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index d96ada3c06fc..dff14f1ec55f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -8,6 +8,7 @@
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +65,7 @@
#define __MVM_CONSTANTS_H
#include <linux/ieee80211.h>
+#include "fw-api.h"
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
@@ -114,6 +117,7 @@
#define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */
#define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */
#define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM
+#define IWL_MVM_NON_TRANSMITTING_AP 0
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1
@@ -145,5 +149,8 @@
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
#define IWL_MVM_ENABLE_EBS 1
+#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
+#define IWL_MVM_FTM_INITIATOR_DYNACK true
+#define IWL_MVM_D3_DEBUG false
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 01b5338201d6..808bc6f363d0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1899,7 +1899,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
- u32 base = mvm->error_event_table[0];
+ u32 base = mvm->trans->lmac_error_event_table[0];
struct error_table_start {
/* cf. struct iwl_error_event_table */
u32 valid;
@@ -2125,7 +2125,6 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
file->private_data = inode->i_private;
- ieee80211_stop_queues(mvm->hw);
synchronize_net();
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
@@ -2140,10 +2139,9 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
rtnl_unlock();
if (err > 0)
err = -EINVAL;
- if (err) {
- ieee80211_wake_queues(mvm->hw);
+ if (err)
return err;
- }
+
mvm->d3_test_active = true;
mvm->keep_vif = NULL;
return 0;
@@ -2223,8 +2221,6 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);
- ieee80211_wake_queues(mvm->hw);
-
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 33b0af24a537..2453ceabf00d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -60,7 +60,6 @@
*
*****************************************************************************/
#include "mvm.h"
-#include "fw/api/tof.h"
#include "debugfs.h"
static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
@@ -523,753 +522,30 @@ static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
- char *buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 value;
- int ret = -EINVAL;
- char *data;
-
- mutex_lock(&mvm->mutex);
-
- data = iwl_dbgfs_is_match("tof_disabled=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.tof_cfg.tof_disabled = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("one_sided_disabled=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.tof_cfg.one_sided_disabled = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("is_debug_mode=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.tof_cfg.is_debug_mode = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("is_buf=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.tof_cfg.is_buf_required = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("send_tof_cfg=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
- ret = iwl_mvm_tof_config_cmd(mvm);
- goto out;
- }
- }
-
-out:
- mutex_unlock(&mvm->mutex);
-
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_tof_enable_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- char buf[256];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
- struct iwl_tof_config_cmd *cmd;
-
- cmd = &mvm->tof_data.tof_cfg;
-
- mutex_lock(&mvm->mutex);
-
- pos += scnprintf(buf + pos, bufsz - pos, "tof_disabled = %d\n",
- cmd->tof_disabled);
- pos += scnprintf(buf + pos, bufsz - pos, "one_sided_disabled = %d\n",
- cmd->one_sided_disabled);
- pos += scnprintf(buf + pos, bufsz - pos, "is_debug_mode = %d\n",
- cmd->is_debug_mode);
- pos += scnprintf(buf + pos, bufsz - pos, "is_buf_required = %d\n",
- cmd->is_buf_required);
-
- mutex_unlock(&mvm->mutex);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
- char *buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 value;
- int ret = 0;
- char *data;
-
- mutex_lock(&mvm->mutex);
-
- data = iwl_dbgfs_is_match("burst_period=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (!ret)
- mvm->tof_data.responder_cfg.burst_period =
- cpu_to_le16(value);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.min_delta_ftm = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("burst_duration=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.burst_duration = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("num_of_burst_exp=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.num_of_burst_exp = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("abort_responder=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.abort_responder = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("get_ch_est=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.get_ch_est = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("recv_sta_req_params=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.recv_sta_req_params = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("channel_num=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.channel_num = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("bandwidth=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.bandwidth = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("rate=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.rate = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("bssid=", buf);
- if (data) {
- u8 *mac = mvm->tof_data.responder_cfg.bssid;
-
- if (!mac_pton(data, mac)) {
- ret = -EINVAL;
- goto out;
- }
- }
-
- data = iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.tsf_timer_offset_msecs =
- cpu_to_le16(value);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("toa_offset=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.toa_offset =
- cpu_to_le16(value);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("center_freq=", buf);
- if (data) {
- struct iwl_tof_responder_config_cmd *cmd =
- &mvm->tof_data.responder_cfg;
-
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
- enum nl80211_band band = (cmd->channel_num <= 14) ?
- NL80211_BAND_2GHZ :
- NL80211_BAND_5GHZ;
- struct ieee80211_channel chn = {
- .band = band,
- .center_freq = ieee80211_channel_to_frequency(
- cmd->channel_num, band),
- };
- struct cfg80211_chan_def chandef = {
- .chan = &chn,
- .center_freq1 =
- ieee80211_channel_to_frequency(value,
- band),
- };
-
- cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef);
- }
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ftm_per_burst=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.ftm_per_burst = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.ftm_resp_ts_avail = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("asap_mode=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.responder_cfg.asap_mode = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("send_responder_cfg=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
- ret = iwl_mvm_tof_responder_cmd(mvm, vif);
- goto out;
- }
- }
-
-out:
- mutex_unlock(&mvm->mutex);
-
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_tof_responder_params_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- char buf[256];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
- struct iwl_tof_responder_config_cmd *cmd;
-
- cmd = &mvm->tof_data.responder_cfg;
-
- mutex_lock(&mvm->mutex);
-
- pos += scnprintf(buf + pos, bufsz - pos, "burst_period = %d\n",
- le16_to_cpu(cmd->burst_period));
- pos += scnprintf(buf + pos, bufsz - pos, "burst_duration = %d\n",
- cmd->burst_duration);
- pos += scnprintf(buf + pos, bufsz - pos, "bandwidth = %d\n",
- cmd->bandwidth);
- pos += scnprintf(buf + pos, bufsz - pos, "channel_num = %d\n",
- cmd->channel_num);
- pos += scnprintf(buf + pos, bufsz - pos, "ctrl_ch_position = 0x%x\n",
- cmd->ctrl_ch_position);
- pos += scnprintf(buf + pos, bufsz - pos, "bssid = %pM\n",
- cmd->bssid);
- pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %d\n",
- cmd->min_delta_ftm);
- pos += scnprintf(buf + pos, bufsz - pos, "num_of_burst_exp = %d\n",
- cmd->num_of_burst_exp);
- pos += scnprintf(buf + pos, bufsz - pos, "rate = %d\n", cmd->rate);
- pos += scnprintf(buf + pos, bufsz - pos, "abort_responder = %d\n",
- cmd->abort_responder);
- pos += scnprintf(buf + pos, bufsz - pos, "get_ch_est = %d\n",
- cmd->get_ch_est);
- pos += scnprintf(buf + pos, bufsz - pos, "recv_sta_req_params = %d\n",
- cmd->recv_sta_req_params);
- pos += scnprintf(buf + pos, bufsz - pos, "ftm_per_burst = %d\n",
- cmd->ftm_per_burst);
- pos += scnprintf(buf + pos, bufsz - pos, "ftm_resp_ts_avail = %d\n",
- cmd->ftm_resp_ts_avail);
- pos += scnprintf(buf + pos, bufsz - pos, "asap_mode = %d\n",
- cmd->asap_mode);
- pos += scnprintf(buf + pos, bufsz - pos,
- "tsf_timer_offset_msecs = %d\n",
- le16_to_cpu(cmd->tsf_timer_offset_msecs));
- pos += scnprintf(buf + pos, bufsz - pos, "toa_offset = %d\n",
- le16_to_cpu(cmd->toa_offset));
-
- mutex_unlock(&mvm->mutex);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
- char *buf, size_t count,
- loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 value;
- int ret = 0;
- char *data;
-
- mutex_lock(&mvm->mutex);
-
- data = iwl_dbgfs_is_match("request_id=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.request_id = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("initiator=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.initiator = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("one_sided_los_disable=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.one_sided_los_disable = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("req_timeout=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.req_timeout = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("report_policy=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.report_policy = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("macaddr_random=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.macaddr_random = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("num_of_ap=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req.num_of_ap = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("macaddr_template=", buf);
- if (data) {
- u8 mac[ETH_ALEN];
-
- if (!mac_pton(data, mac)) {
- ret = -EINVAL;
- goto out;
- }
- memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("macaddr_mask=", buf);
- if (data) {
- u8 mac[ETH_ALEN];
-
- if (!mac_pton(data, mac)) {
- ret = -EINVAL;
- goto out;
- }
- memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ap=", buf);
- if (data) {
- struct iwl_tof_range_req_ap_entry ap = {};
- int size = sizeof(struct iwl_tof_range_req_ap_entry);
- u16 burst_period;
- u8 *mac = ap.bssid;
- unsigned int i;
-
- if (sscanf(data, "%u %hhd %hhd %hhd"
- "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
- "%hhd %hhd %hd"
- "%hhd %hhd %d"
- "%hhx %hhd %hhd %hhd",
- &i, &ap.channel_num, &ap.bandwidth,
- &ap.ctrl_ch_position,
- mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5,
- &ap.measure_type, &ap.num_of_bursts,
- &burst_period,
- &ap.samples_per_burst, &ap.retries_per_sample,
- &ap.tsf_delta, &ap.location_req, &ap.asap_mode,
- &ap.enable_dyn_ack, &ap.rssi) != 20) {
- ret = -EINVAL;
- goto out;
- }
- if (i >= IWL_MVM_TOF_MAX_APS) {
- IWL_ERR(mvm, "Invalid AP index %d\n", i);
- ret = -EINVAL;
- goto out;
- }
-
- ap.burst_period = cpu_to_le16(burst_period);
-
- memcpy(&mvm->tof_data.range_req.ap[i], &ap, size);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("send_range_request=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value)
- ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
- goto out;
- }
-
- ret = -EINVAL;
-out:
- mutex_unlock(&mvm->mutex);
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- char buf[512];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
- struct iwl_tof_range_req_cmd *cmd;
- int i;
-
- cmd = &mvm->tof_data.range_req;
-
- mutex_lock(&mvm->mutex);
-
- pos += scnprintf(buf + pos, bufsz - pos, "request_id= %d\n",
- cmd->request_id);
- pos += scnprintf(buf + pos, bufsz - pos, "initiator= %d\n",
- cmd->initiator);
- pos += scnprintf(buf + pos, bufsz - pos, "one_sided_los_disable = %d\n",
- cmd->one_sided_los_disable);
- pos += scnprintf(buf + pos, bufsz - pos, "req_timeout= %d\n",
- cmd->req_timeout);
- pos += scnprintf(buf + pos, bufsz - pos, "report_policy= %d\n",
- cmd->report_policy);
- pos += scnprintf(buf + pos, bufsz - pos, "macaddr_random= %d\n",
- cmd->macaddr_random);
- pos += scnprintf(buf + pos, bufsz - pos, "macaddr_template= %pM\n",
- cmd->macaddr_template);
- pos += scnprintf(buf + pos, bufsz - pos, "macaddr_mask= %pM\n",
- cmd->macaddr_mask);
- pos += scnprintf(buf + pos, bufsz - pos, "num_of_ap= %d\n",
- cmd->num_of_ap);
- for (i = 0; i < cmd->num_of_ap; i++) {
- struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i];
-
- pos += scnprintf(buf + pos, bufsz - pos,
- "ap %.2d: channel_num=%hhd bw=%hhd"
- " control=%hhd bssid=%pM type=%hhd"
- " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
- " retries=%hhd tsf_delta=%d"
- " tsf_delta_direction=%hhd location_req=0x%hhx "
- " asap=%hhd enable=%hhd rssi=%hhd\n",
- i, ap->channel_num, ap->bandwidth,
- ap->ctrl_ch_position, ap->bssid,
- ap->measure_type, ap->num_of_bursts,
- ap->burst_period, ap->samples_per_burst,
- ap->retries_per_sample, ap->tsf_delta,
- ap->tsf_delta_direction,
- ap->location_req, ap->asap_mode,
- ap->enable_dyn_ack, ap->rssi);
- }
-
- mutex_unlock(&mvm->mutex);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
- char *buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 value;
- int ret = 0;
- char *data;
-
- mutex_lock(&mvm->mutex);
-
- data = iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req_ext.tsf_timer_offset_msec =
- cpu_to_le16(value);
- goto out;
- }
-
- data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req_ext.min_delta_ftm = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req_ext.ftm_format_and_bw20M =
- value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req_ext.ftm_format_and_bw40M =
- value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.range_req_ext.ftm_format_and_bw80M =
- value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("send_range_req_ext=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value)
- ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
- goto out;
- }
-
- ret = -EINVAL;
-out:
- mutex_unlock(&mvm->mutex);
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- char buf[256];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
- struct iwl_tof_range_req_ext_cmd *cmd;
-
- cmd = &mvm->tof_data.range_req_ext;
-
- mutex_lock(&mvm->mutex);
-
- pos += scnprintf(buf + pos, bufsz - pos,
- "tsf_timer_offset_msec = %hd\n",
- cmd->tsf_timer_offset_msec);
- pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n",
- cmd->min_delta_ftm);
- pos += scnprintf(buf + pos, bufsz - pos,
- "ftm_format_and_bw20M = %hhd\n",
- cmd->ftm_format_and_bw20M);
- pos += scnprintf(buf + pos, bufsz - pos,
- "ftm_format_and_bw40M = %hhd\n",
- cmd->ftm_format_and_bw40M);
- pos += scnprintf(buf + pos, bufsz - pos,
- "ftm_format_and_bw80M = %hhd\n",
- cmd->ftm_format_and_bw80M);
-
- mutex_unlock(&mvm->mutex);
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif,
- char *buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 value;
- int abort_id, ret = 0;
- char *data;
-
- mutex_lock(&mvm->mutex);
-
- data = iwl_dbgfs_is_match("abort_id=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0)
- mvm->tof_data.last_abort_id = value;
- goto out;
- }
-
- data = iwl_dbgfs_is_match("send_range_abort=", buf);
- if (data) {
- ret = kstrtou32(data, 10, &value);
- if (ret == 0 && value) {
- abort_id = mvm->tof_data.last_abort_id;
- ret = iwl_mvm_tof_range_abort_cmd(mvm, abort_id);
- goto out;
- }
- }
-
-out:
- mutex_unlock(&mvm->mutex);
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_tof_range_abort_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- char buf[32];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
- int last_abort_id;
-
- mutex_lock(&mvm->mutex);
- last_abort_id = mvm->tof_data.last_abort_id;
- mutex_unlock(&mvm->mutex);
-
- pos += scnprintf(buf + pos, bufsz - pos, "last_abort_id = %d\n",
- last_abort_id);
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
+static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
+ size_t count, loff_t *ppos)
{
- struct ieee80211_vif *vif = file->private_data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
- char *buf;
- int pos = 0;
- const size_t bufsz = sizeof(struct iwl_tof_range_rsp_ntfy) + 256;
- struct iwl_tof_range_rsp_ntfy *cmd;
- int i, ret;
+ u8 value;
+ int ret;
- buf = kzalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ ret = kstrtou8(buf, 0, &value);
+ if (ret)
+ return ret;
+ if (value > 1)
+ return -EINVAL;
mutex_lock(&mvm->mutex);
- cmd = &mvm->tof_data.range_resp;
-
- pos += scnprintf(buf + pos, bufsz - pos, "request_id = %d\n",
- cmd->request_id);
- pos += scnprintf(buf + pos, bufsz - pos, "status = %d\n",
- cmd->request_status);
- pos += scnprintf(buf + pos, bufsz - pos, "last_in_batch = %d\n",
- cmd->last_in_batch);
- pos += scnprintf(buf + pos, bufsz - pos, "num_of_aps = %d\n",
- cmd->num_of_aps);
- for (i = 0; i < cmd->num_of_aps; i++) {
- struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i];
-
- pos += scnprintf(buf + pos, bufsz - pos,
- "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
- " rtt=%d rtt_var=%d rtt_spread=%d"
- " rssi=%hhd rssi_spread=%hhd"
- " range=%d range_var=%d"
- " time_stamp=%d\n",
- i, ap->bssid, ap->measure_status,
- ap->measure_bw,
- ap->rtt, ap->rtt_variance, ap->rtt_spread,
- ap->rssi, ap->rssi_spread, ap->range,
- ap->range_variance, ap->timestamp);
- }
+ iwl_mvm_update_low_latency(mvm, vif, value, LOW_LATENCY_DEBUGFS);
mutex_unlock(&mvm->mutex);
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- return ret;
+ return count;
}
-static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
- size_t count, loff_t *ppos)
+static ssize_t
+iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
+ size_t count, loff_t *ppos)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
@@ -1279,13 +555,24 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
ret = kstrtou8(buf, 0, &value);
if (ret)
return ret;
- if (value > 1)
+
+ if (value > NUM_LOW_LATENCY_FORCE)
return -EINVAL;
mutex_lock(&mvm->mutex);
- iwl_mvm_update_low_latency(mvm, vif, value, LOW_LATENCY_DEBUGFS);
+ if (value == LOW_LATENCY_FORCE_UNSET) {
+ iwl_mvm_update_low_latency(mvm, vif, false,
+ LOW_LATENCY_DEBUGFS_FORCE);
+ iwl_mvm_update_low_latency(mvm, vif, false,
+ LOW_LATENCY_DEBUGFS_FORCE_ENABLE);
+ } else {
+ iwl_mvm_update_low_latency(mvm, vif,
+ value == LOW_LATENCY_FORCE_ON,
+ LOW_LATENCY_DEBUGFS_FORCE);
+ iwl_mvm_update_low_latency(mvm, vif, true,
+ LOW_LATENCY_DEBUGFS_FORCE_ENABLE);
+ }
mutex_unlock(&mvm->mutex);
-
return count;
}
@@ -1295,15 +582,25 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
{
struct ieee80211_vif *vif = file->private_data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- char buf[30] = {};
+ char format[] = "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n"
+ "dbgfs_force_enable=%d\ndbgfs_force=%d\nactual=%d\n";
+
+ /*
+ * all values in format are boolean so the size of format is enough
+ * for holding the result string
+ */
+ char buf[sizeof(format) + 1] = {};
int len;
- len = scnprintf(buf, sizeof(buf) - 1,
- "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n",
+ len = scnprintf(buf, sizeof(buf) - 1, format,
!!(mvmvif->low_latency & LOW_LATENCY_TRAFFIC),
!!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS),
!!(mvmvif->low_latency & LOW_LATENCY_VCMD),
- !!(mvmvif->low_latency & LOW_LATENCY_VIF_TYPE));
+ !!(mvmvif->low_latency & LOW_LATENCY_VIF_TYPE),
+ !!(mvmvif->low_latency &
+ LOW_LATENCY_DEBUGFS_FORCE_ENABLE),
+ !!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS_FORCE),
+ !!(mvmvif->low_latency_actual));
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1456,14 +753,9 @@ MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
+MVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
-MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
@@ -1497,6 +789,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, 0400);
MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, 0400);
MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, 0600);
+ MVM_DEBUGFS_ADD_FILE_VIF(low_latency_force, mvmvif->dbgfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600);
@@ -1506,24 +799,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif == mvm->bf_allowed_vif)
MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600);
- if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT) &&
- !vif->p2p && (vif->type != NL80211_IFTYPE_P2P_DEVICE)) {
- if (IWL_MVM_TOF_IS_RESPONDER && vif->type == NL80211_IFTYPE_AP)
- MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params,
- mvmvif->dbgfs_dir, 0600);
-
- MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request, mvmvif->dbgfs_dir,
- 0600);
- MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext, mvmvif->dbgfs_dir,
- 0600);
- MVM_DEBUGFS_ADD_FILE_VIF(tof_enable, mvmvif->dbgfs_dir,
- 0600);
- MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort, mvmvif->dbgfs_dir,
- 0600);
- MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response, mvmvif->dbgfs_dir,
- 0400);
- }
-
/*
* Create symlink for convenience pointing to interface specific
* debugfs entries for the driver. For example, under
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 52c361a6124c..776b24f54200 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,6 +69,7 @@
#include "sta.h"
#include "iwl-io.h"
#include "debugfs.h"
+#include "iwl-modparams.h"
#include "fw/error-dump.h"
static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
@@ -1187,64 +1188,128 @@ out:
return ret ?: count;
}
-static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
+static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
{
- struct iwl_mvm *mvm = file->private_data;
- int conf;
- char buf[8];
- const size_t bufsz = sizeof(buf);
- int pos = 0;
+ struct ieee80211_vif *vif;
+ struct iwl_mvm_vif *mvmvif;
+ struct sk_buff *beacon;
+ struct ieee80211_tx_info *info;
+ struct iwl_mac_beacon_cmd beacon_cmd = {};
+ u8 rate;
+ u16 flags;
+ int i;
+
+ len /= 2;
+
+ /* Element len should be represented by u8 */
+ if (len >= U8_MAX)
+ return -EINVAL;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
+ if (!iwl_mvm_has_new_tx_api(mvm) &&
+ !fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
+ return -EINVAL;
+
+ rcu_read_lock();
+
+ for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
+ if (!vif)
+ continue;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ break;
+ }
+
+ if (i == NUM_MAC_INDEX_DRIVER || !vif)
+ goto out_err;
+
+ mvm->hw->extra_beacon_tailroom = len;
+
+ beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
+ if (!beacon)
+ goto out_err;
+
+ if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
+ dev_kfree_skb(beacon);
+ goto out_err;
+ }
+
+ mvm->beacon_inject_active = true;
+
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ info = IEEE80211_SKB_CB(beacon);
+ rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
+ flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
+
+ if (rate == IWL_FIRST_CCK_RATE)
+ flags |= IWL_MAC_BEACON_CCK;
+
+ beacon_cmd.flags = cpu_to_le16(flags);
+ beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
+ beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
+
+ iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
+ &beacon_cmd.tim_size,
+ beacon->data, beacon->len);
mutex_lock(&mvm->mutex);
- conf = mvm->fwrt.dump.conf;
+ iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
+ sizeof(beacon_cmd));
mutex_unlock(&mvm->mutex);
- pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
+ dev_kfree_skb(beacon);
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ rcu_read_unlock();
+ return 0;
+
+out_err:
+ rcu_read_unlock();
+ return -EINVAL;
}
-/*
- * Enable / Disable continuous recording.
- * Cause the FW to start continuous recording, by sending the relevant hcmd.
- * Enable: input of every integer larger than 0, ENABLE_CONT_RECORDING.
- * Disable: for 0 as input, DISABLE_CONT_RECORDING.
- */
-static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
- char *buf, size_t count,
- loff_t *ppos)
+static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
+ char *buf, size_t count,
+ loff_t *ppos)
{
- struct iwl_trans *trans = mvm->trans;
- const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv;
- struct iwl_continuous_record_cmd cont_rec = {};
- int ret, rec_mode;
+ int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
- if (!iwl_mvm_firmware_running(mvm))
- return -EIO;
-
- if (!dest)
- return -EOPNOTSUPP;
+ mvm->hw->extra_beacon_tailroom = 0;
+ return ret ?: count;
+}
- if (dest->monitor_mode != SMEM_MODE ||
- trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
- return -EOPNOTSUPP;
+static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
+ char *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
- ret = kstrtoint(buf, 0, &rec_mode);
- if (ret)
- return ret;
+ mvm->hw->extra_beacon_tailroom = 0;
+ mvm->beacon_inject_active = false;
+ return ret ?: count;
+}
- cont_rec.record_mode.enable_recording = rec_mode ?
- cpu_to_le16(ENABLE_CONT_RECORDING) :
- cpu_to_le16(DISABLE_CONT_RECORDING);
+static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ int conf;
+ char buf[8];
+ const size_t bufsz = sizeof(buf);
+ int pos = 0;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_send_cmd_pdu(mvm, LDBG_CONFIG_CMD, 0,
- sizeof(cont_rec), &cont_rec);
+ conf = mvm->fwrt.dump.conf;
mutex_unlock(&mvm->mutex);
- return ret ?: count;
+ pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
@@ -1722,11 +1787,36 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
return ret ?: count;
}
+struct iwl_mvm_sniffer_apply {
+ struct iwl_mvm *mvm;
+ u8 *bssid;
+ u16 aid;
+};
+
+static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
+ struct iwl_rx_packet *pkt, void *data)
+{
+ struct iwl_mvm_sniffer_apply *apply = data;
+
+ apply->mvm->cur_aid = cpu_to_le16(apply->aid);
+ memcpy(apply->mvm->cur_bssid, apply->bssid,
+ sizeof(apply->mvm->cur_bssid));
+
+ return true;
+}
+
static ssize_t
iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
+ struct iwl_notification_wait wait;
struct iwl_he_monitor_cmd he_mon_cmd = {};
+ struct iwl_mvm_sniffer_apply apply = {
+ .mvm = mvm,
+ };
+ u16 wait_cmds[] = {
+ iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0),
+ };
u32 aid;
int ret;
@@ -1742,16 +1832,54 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
he_mon_cmd.aid = cpu_to_le16(aid);
+ apply.aid = aid;
+ apply.bssid = (void *)he_mon_cmd.bssid;
+
mutex_lock(&mvm->mutex);
+
+ /*
+ * Use the notification waiter to get our function triggered
+ * in sequence with other RX. This ensures that frames we get
+ * on the RX queue _before_ the new configuration is applied
+ * still have mvm->cur_aid pointing to the old AID, and that
+ * frames on the RX queue _after_ the firmware processed the
+ * new configuration (and sent the response, synchronously)
+ * get mvm->cur_aid correctly set to the new AID.
+ */
+ iwl_init_notification_wait(&mvm->notif_wait, &wait,
+ wait_cmds, ARRAY_SIZE(wait_cmds),
+ iwl_mvm_sniffer_apply, &apply);
+
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD,
DATA_PATH_GROUP, 0), 0,
sizeof(he_mon_cmd), &he_mon_cmd);
+
+ /* no need to really wait, we already did anyway */
+ iwl_remove_notification(&mvm->notif_wait, &wait);
+
mutex_unlock(&mvm->mutex);
return ret ?: count;
}
static ssize_t
+iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ u8 buf[32];
+ int len;
+
+ len = scnprintf(buf, sizeof(buf),
+ "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
+ le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
+ mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
+ mvm->cur_bssid[4], mvm->cur_bssid[5]);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t
iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1800,11 +1928,12 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
-MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
+MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
+MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
@@ -1820,7 +1949,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
#endif
-MVM_DEBUGFS_WRITE_FILE_OPS(he_sniffer_params, 32);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -2004,13 +2133,14 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
- MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
+ MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
+ MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
#ifdef CONFIG_ACPI
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400);
#endif
- MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0200);
+ MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
if (!debugfs_create_bool("enable_scan_iteration_notif",
0600,
@@ -2071,6 +2201,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (!debugfs_create_blob("nvm_phy_sku", 0400,
mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
goto err;
+ if (!debugfs_create_blob("nvm_reg", S_IRUSR,
+ mvm->debugfs_dir, &mvm->nvm_reg_blob))
+ goto err;
debugfs_create_file("mem", 0600, dbgfs_dir, mvm, &iwl_dbgfs_mem_ops);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
new file mode 100644
index 000000000000..e9822a3ec373
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -0,0 +1,654 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * 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
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 <linux/etherdevice.h>
+#include <linux/math64.h>
+#include <net/cfg80211.h>
+#include "mvm.h"
+#include "iwl-io.h"
+#include "iwl-prph.h"
+#include "constants.h"
+
+struct iwl_mvm_loc_entry {
+ struct list_head list;
+ u8 addr[ETH_ALEN];
+ u8 lci_len, civic_len;
+ u8 buf[];
+};
+
+static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
+{
+ struct iwl_mvm_loc_entry *e, *t;
+
+ mvm->ftm_initiator.req = NULL;
+ mvm->ftm_initiator.req_wdev = NULL;
+ memset(mvm->ftm_initiator.responses, 0,
+ sizeof(mvm->ftm_initiator.responses));
+ list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) {
+ list_del(&e->list);
+ kfree(e);
+ }
+}
+
+void iwl_mvm_ftm_restart(struct iwl_mvm *mvm)
+{
+ struct cfg80211_pmsr_result result = {
+ .status = NL80211_PMSR_STATUS_FAILURE,
+ .final = 1,
+ .host_time = ktime_get_boot_ns(),
+ .type = NL80211_PMSR_TYPE_FTM,
+ };
+ int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!mvm->ftm_initiator.req)
+ return;
+
+ for (i = 0; i < mvm->ftm_initiator.req->n_peers; i++) {
+ memcpy(result.addr, mvm->ftm_initiator.req->peers[i].addr,
+ ETH_ALEN);
+ result.ftm.burst_index = mvm->ftm_initiator.responses[i];
+
+ cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
+ mvm->ftm_initiator.req,
+ &result, GFP_KERNEL);
+ }
+
+ cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev,
+ mvm->ftm_initiator.req, GFP_KERNEL);
+ iwl_mvm_ftm_reset(mvm);
+}
+
+static int
+iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s)
+{
+ switch (s) {
+ case IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS:
+ return 0;
+ case IWL_TOF_RANGE_REQUEST_STATUS_BUSY:
+ return -EBUSY;
+ default:
+ WARN_ON_ONCE(1);
+ return -EIO;
+ }
+}
+
+static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_tof_range_req_cmd_v5 *cmd,
+ struct cfg80211_pmsr_request *req)
+{
+ int i;
+
+ cmd->request_id = req->cookie;
+ cmd->num_of_ap = req->n_peers;
+
+ /* use maximum for "no timeout" or bigger than what we can do */
+ if (!req->timeout || req->timeout > 255 * 100)
+ cmd->req_timeout = 255;
+ else
+ cmd->req_timeout = DIV_ROUND_UP(req->timeout, 100);
+
+ /*
+ * We treat it always as random, since if not we'll
+ * have filled our local address there instead.
+ */
+ cmd->macaddr_random = 1;
+ memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN);
+ for (i = 0; i < ETH_ALEN; i++)
+ cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
+
+ if (vif->bss_conf.assoc)
+ memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
+ else
+ eth_broadcast_addr(cmd->range_req_bssid);
+}
+
+static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_tof_range_req_cmd *cmd,
+ struct cfg80211_pmsr_request *req)
+{
+ int i;
+
+ cmd->initiator_flags =
+ cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM |
+ IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT);
+ cmd->request_id = req->cookie;
+ cmd->num_of_ap = req->n_peers;
+
+ /*
+ * Use a large value for "no timeout". Don't use the maximum value
+ * because of fw limitations.
+ */
+ if (req->timeout)
+ cmd->req_timeout_ms = cpu_to_le32(req->timeout);
+ else
+ cmd->req_timeout_ms = cpu_to_le32(0xfffff);
+
+ memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN);
+ for (i = 0; i < ETH_ALEN; i++)
+ cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
+
+ if (vif->bss_conf.assoc)
+ memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
+ else
+ eth_broadcast_addr(cmd->range_req_bssid);
+
+ /* TODO: fill in tsf_mac_id if needed */
+ cmd->tsf_mac_id = cpu_to_le32(0xff);
+}
+
+static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm,
+ struct cfg80211_pmsr_request_peer *peer,
+ u8 *channel, u8 *bandwidth,
+ u8 *ctrl_ch_position)
+{
+ u32 freq = peer->chandef.chan->center_freq;
+
+ *channel = ieee80211_frequency_to_channel(freq);
+
+ switch (peer->chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ *bandwidth = IWL_TOF_BW_20_LEGACY;
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ *bandwidth = IWL_TOF_BW_20_HT;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ *bandwidth = IWL_TOF_BW_40;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ *bandwidth = IWL_TOF_BW_80;
+ break;
+ default:
+ IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n",
+ peer->chandef.width);
+ return -EINVAL;
+ }
+
+ *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ?
+ iwl_mvm_get_ctrl_pos(&peer->chandef) : 0;
+
+ return 0;
+}
+
+static int
+iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm,
+ struct cfg80211_pmsr_request_peer *peer,
+ struct iwl_tof_range_req_ap_entry_v2 *target)
+{
+ int ret;
+
+ ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num,
+ &target->bandwidth,
+ &target->ctrl_ch_position);
+ if (ret)
+ return ret;
+
+ memcpy(target->bssid, peer->addr, ETH_ALEN);
+ target->burst_period =
+ cpu_to_le16(peer->ftm.burst_period);
+ target->samples_per_burst = peer->ftm.ftms_per_burst;
+ target->num_of_bursts = peer->ftm.num_bursts_exp;
+ target->measure_type = 0; /* regular two-sided FTM */
+ target->retries_per_sample = peer->ftm.ftmr_retries;
+ target->asap_mode = peer->ftm.asap;
+ target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK;
+
+ if (peer->ftm.request_lci)
+ target->location_req |= IWL_TOF_LOC_LCI;
+ if (peer->ftm.request_civicloc)
+ target->location_req |= IWL_TOF_LOC_CIVIC;
+
+ target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO;
+
+ return 0;
+}
+
+#define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \
+ cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag))
+
+static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm,
+ struct cfg80211_pmsr_request_peer *peer,
+ struct iwl_tof_range_req_ap_entry *target)
+{
+ int ret;
+
+ ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num,
+ &target->bandwidth,
+ &target->ctrl_ch_position);
+ if (ret)
+ return ret;
+
+ memcpy(target->bssid, peer->addr, ETH_ALEN);
+ target->burst_period =
+ cpu_to_le16(peer->ftm.burst_period);
+ target->samples_per_burst = peer->ftm.ftms_per_burst;
+ target->num_of_bursts = peer->ftm.num_bursts_exp;
+ target->ftmr_max_retries = peer->ftm.ftmr_retries;
+ target->initiator_ap_flags = cpu_to_le32(0);
+
+ if (peer->ftm.asap)
+ FTM_PUT_FLAG(ASAP);
+
+ if (peer->ftm.request_lci)
+ FTM_PUT_FLAG(LCI_REQUEST);
+
+ if (peer->ftm.request_civicloc)
+ FTM_PUT_FLAG(CIVIC_REQUEST);
+
+ if (IWL_MVM_FTM_INITIATOR_DYNACK)
+ FTM_PUT_FLAG(DYN_ACK);
+
+ if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG)
+ FTM_PUT_FLAG(ALGO_LR);
+ else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT)
+ FTM_PUT_FLAG(ALGO_FFT);
+
+ return 0;
+}
+
+int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *req)
+{
+ struct iwl_tof_range_req_cmd_v5 cmd_v5;
+ struct iwl_tof_range_req_cmd cmd;
+ bool new_api = fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ);
+ u8 num_of_ap;
+ struct iwl_host_cmd hcmd = {
+ .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0),
+ .dataflags[0] = IWL_HCMD_DFL_DUP,
+ };
+ u32 status = 0;
+ int err, i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (mvm->ftm_initiator.req)
+ return -EBUSY;
+
+ if (new_api) {
+ iwl_mvm_ftm_cmd(mvm, vif, &cmd, req);
+ hcmd.data[0] = &cmd;
+ hcmd.len[0] = sizeof(cmd);
+ num_of_ap = cmd.num_of_ap;
+ } else {
+ iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req);
+ hcmd.data[0] = &cmd_v5;
+ hcmd.len[0] = sizeof(cmd_v5);
+ num_of_ap = cmd_v5.num_of_ap;
+ }
+
+ for (i = 0; i < num_of_ap; i++) {
+ struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
+
+ if (new_api)
+ err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]);
+ else
+ err = iwl_mvm_ftm_put_target_v2(mvm, peer,
+ &cmd_v5.ap[i]);
+
+ if (err)
+ return err;
+ }
+
+ err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status);
+ if (!err && status) {
+ IWL_ERR(mvm, "FTM range request command failure, status: %u\n",
+ status);
+ err = iwl_ftm_range_request_status_to_err(status);
+ }
+
+ if (!err) {
+ mvm->ftm_initiator.req = req;
+ mvm->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif);
+ }
+
+ return err;
+}
+
+void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req)
+{
+ struct iwl_tof_range_abort_cmd cmd = {
+ .request_id = req->cookie,
+ };
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (req != mvm->ftm_initiator.req)
+ return;
+
+ if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RANGE_ABORT_CMD,
+ LOCATION_GROUP, 0),
+ 0, sizeof(cmd), &cmd))
+ IWL_ERR(mvm, "failed to abort FTM process\n");
+}
+
+static int iwl_mvm_ftm_find_peer(struct cfg80211_pmsr_request *req,
+ const u8 *addr)
+{
+ int i;
+
+ for (i = 0; i < req->n_peers; i++) {
+ struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
+
+ if (ether_addr_equal_unaligned(peer->addr, addr))
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+static u64 iwl_mvm_ftm_get_host_time(struct iwl_mvm *mvm, __le32 fw_gp2_ts)
+{
+ u32 gp2_ts = le32_to_cpu(fw_gp2_ts);
+ u32 curr_gp2, diff;
+ u64 now_from_boot_ns;
+
+ iwl_mvm_get_sync_time(mvm, &curr_gp2, &now_from_boot_ns);
+
+ if (curr_gp2 >= gp2_ts)
+ diff = curr_gp2 - gp2_ts;
+ else
+ diff = curr_gp2 + (U32_MAX - gp2_ts + 1);
+
+ return now_from_boot_ns - (u64)diff * 1000;
+}
+
+static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm,
+ struct cfg80211_pmsr_result *res)
+{
+ struct iwl_mvm_loc_entry *entry;
+
+ list_for_each_entry(entry, &mvm->ftm_initiator.loc_list, list) {
+ if (!ether_addr_equal_unaligned(res->addr, entry->addr))
+ continue;
+
+ if (entry->lci_len) {
+ res->ftm.lci_len = entry->lci_len;
+ res->ftm.lci = entry->buf;
+ }
+
+ if (entry->civic_len) {
+ res->ftm.civicloc_len = entry->civic_len;
+ res->ftm.civicloc = entry->buf + entry->lci_len;
+ }
+
+ /* we found the entry we needed */
+ break;
+ }
+}
+
+static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
+ u8 num_of_aps)
+{
+ lockdep_assert_held(&mvm->mutex);
+
+ if (request_id != (u8)mvm->ftm_initiator.req->cookie) {
+ IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n",
+ request_id, (u8)mvm->ftm_initiator.req->cookie);
+ return -EINVAL;
+ }
+
+ if (num_of_aps > mvm->ftm_initiator.req->n_peers) {
+ IWL_ERR(mvm, "FTM range response invalid\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
+ struct cfg80211_pmsr_result *res)
+{
+ s64 rtt_avg = res->ftm.rtt_avg * 100;
+
+ do_div(rtt_avg, 6666);
+
+ IWL_DEBUG_INFO(mvm, "entry %d\n", index);
+ IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status);
+ IWL_DEBUG_INFO(mvm, "\tBSSID: %pM\n", res->addr);
+ IWL_DEBUG_INFO(mvm, "\thost time: %llu\n", res->host_time);
+ IWL_DEBUG_INFO(mvm, "\tburst index: %hhu\n", res->ftm.burst_index);
+ IWL_DEBUG_INFO(mvm, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes);
+ IWL_DEBUG_INFO(mvm, "\trssi: %d\n", res->ftm.rssi_avg);
+ IWL_DEBUG_INFO(mvm, "\trssi spread: %hhu\n", res->ftm.rssi_spread);
+ IWL_DEBUG_INFO(mvm, "\trtt: %lld\n", res->ftm.rtt_avg);
+ IWL_DEBUG_INFO(mvm, "\trtt var: %llu\n", res->ftm.rtt_variance);
+ IWL_DEBUG_INFO(mvm, "\trtt spread: %llu\n", res->ftm.rtt_spread);
+ IWL_DEBUG_INFO(mvm, "\tdistance: %lld\n", rtt_avg);
+}
+
+void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data;
+ struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data;
+ int i;
+ bool new_api = fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ);
+ u8 num_of_aps, last_in_batch;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (!mvm->ftm_initiator.req) {
+ IWL_ERR(mvm, "Got FTM response but have no request?\n");
+ return;
+ }
+
+ if (new_api) {
+ if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp->request_id,
+ fw_resp->num_of_aps))
+ return;
+
+ num_of_aps = fw_resp->num_of_aps;
+ last_in_batch = fw_resp->last_report;
+ } else {
+ if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v5->request_id,
+ fw_resp_v5->num_of_aps))
+ return;
+
+ num_of_aps = fw_resp_v5->num_of_aps;
+ last_in_batch = fw_resp_v5->last_in_batch;
+ }
+
+ IWL_DEBUG_INFO(mvm, "Range response received\n");
+ IWL_DEBUG_INFO(mvm, "request id: %lld, num of entries: %hhu\n",
+ mvm->ftm_initiator.req->cookie, num_of_aps);
+
+ for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) {
+ struct cfg80211_pmsr_result result = {};
+ struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap;
+ int peer_idx;
+
+ if (new_api) {
+ fw_ap = &fw_resp->ap[i];
+ result.final = fw_resp->ap[i].last_burst;
+ } else {
+ /* the first part is the same for old and new APIs */
+ fw_ap = (void *)&fw_resp_v5->ap[i];
+ /*
+ * FIXME: the firmware needs to report this, we don't
+ * even know the number of bursts the responder picked
+ * (if we asked it to)
+ */
+ result.final = 0;
+ }
+
+ peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req,
+ fw_ap->bssid);
+ if (peer_idx < 0) {
+ IWL_WARN(mvm,
+ "Unknown address (%pM, target #%d) in FTM response\n",
+ fw_ap->bssid, i);
+ continue;
+ }
+
+ switch (fw_ap->measure_status) {
+ case IWL_TOF_ENTRY_SUCCESS:
+ result.status = NL80211_PMSR_STATUS_SUCCESS;
+ break;
+ case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT:
+ result.status = NL80211_PMSR_STATUS_TIMEOUT;
+ break;
+ case IWL_TOF_ENTRY_NO_RESPONSE:
+ result.status = NL80211_PMSR_STATUS_FAILURE;
+ result.ftm.failure_reason =
+ NL80211_PMSR_FTM_FAILURE_NO_RESPONSE;
+ break;
+ case IWL_TOF_ENTRY_REQUEST_REJECTED:
+ result.status = NL80211_PMSR_STATUS_FAILURE;
+ result.ftm.failure_reason =
+ NL80211_PMSR_FTM_FAILURE_PEER_BUSY;
+ result.ftm.busy_retry_time = fw_ap->refusal_period;
+ break;
+ default:
+ result.status = NL80211_PMSR_STATUS_FAILURE;
+ result.ftm.failure_reason =
+ NL80211_PMSR_FTM_FAILURE_UNSPECIFIED;
+ break;
+ }
+ memcpy(result.addr, fw_ap->bssid, ETH_ALEN);
+ result.host_time = iwl_mvm_ftm_get_host_time(mvm,
+ fw_ap->timestamp);
+ result.type = NL80211_PMSR_TYPE_FTM;
+ result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx];
+ mvm->ftm_initiator.responses[peer_idx]++;
+ result.ftm.rssi_avg = fw_ap->rssi;
+ result.ftm.rssi_avg_valid = 1;
+ result.ftm.rssi_spread = fw_ap->rssi_spread;
+ result.ftm.rssi_spread_valid = 1;
+ result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt);
+ result.ftm.rtt_avg_valid = 1;
+ result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance);
+ result.ftm.rtt_variance_valid = 1;
+ result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread);
+ result.ftm.rtt_spread_valid = 1;
+
+ iwl_mvm_ftm_get_lci_civic(mvm, &result);
+
+ cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
+ mvm->ftm_initiator.req,
+ &result, GFP_KERNEL);
+
+ iwl_mvm_debug_range_resp(mvm, i, &result);
+ }
+
+ if (last_in_batch) {
+ cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev,
+ mvm->ftm_initiator.req,
+ GFP_KERNEL);
+ iwl_mvm_ftm_reset(mvm);
+ }
+}
+
+void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ const struct ieee80211_mgmt *mgmt = (void *)pkt->data;
+ size_t len = iwl_rx_packet_payload_len(pkt);
+ struct iwl_mvm_loc_entry *entry;
+ const u8 *ies, *lci, *civic, *msr_ie;
+ size_t ies_len, lci_len = 0, civic_len = 0;
+ size_t baselen = IEEE80211_MIN_ACTION_SIZE +
+ sizeof(mgmt->u.action.u.ftm);
+ static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI;
+ static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC;
+
+ if (len <= baselen)
+ return;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ ies = mgmt->u.action.u.ftm.variable;
+ ies_len = len - baselen;
+
+ msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len,
+ &rprt_type_lci, 1, 4);
+ if (msr_ie) {
+ lci = msr_ie + 2;
+ lci_len = msr_ie[1];
+ }
+
+ msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len,
+ &rprt_type_civic, 1, 4);
+ if (msr_ie) {
+ civic = msr_ie + 2;
+ civic_len = msr_ie[1];
+ }
+
+ entry = kmalloc(sizeof(*entry) + lci_len + civic_len, GFP_KERNEL);
+ if (!entry)
+ return;
+
+ memcpy(entry->addr, mgmt->bssid, ETH_ALEN);
+
+ entry->lci_len = lci_len;
+ if (lci_len)
+ memcpy(entry->buf, lci, lci_len);
+
+ entry->civic_len = civic_len;
+ if (civic_len)
+ memcpy(entry->buf + lci_len, civic, civic_len);
+
+ list_add_tail(&entry->list, &mvm->ftm_initiator.loc_list);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
new file mode 100644
index 000000000000..1513b8b4062f
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -0,0 +1,244 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * 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
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 <net/cfg80211.h>
+#include <linux/etherdevice.h>
+#include "mvm.h"
+#include "constants.h"
+
+static int
+iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *chandef)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_tof_responder_config_cmd cmd = {
+ .channel_num = chandef->chan->hw_value,
+ .cmd_valid_fields =
+ cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
+ IWL_TOF_RESPONDER_CMD_VALID_BSSID |
+ IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
+ .sta_id = mvmvif->bcast_sta.sta_id,
+ };
+
+ lockdep_assert_held(&mvm->mutex);
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ cmd.bandwidth = IWL_TOF_BW_20_LEGACY;
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ cmd.bandwidth = IWL_TOF_BW_20_HT;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ cmd.bandwidth = IWL_TOF_BW_40;
+ cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ cmd.bandwidth = IWL_TOF_BW_80;
+ cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ memcpy(cmd.bssid, vif->addr, ETH_ALEN);
+
+ return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD,
+ LOCATION_GROUP, 0),
+ 0, sizeof(cmd), &cmd);
+}
+
+static int
+iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ftm_responder_params *params)
+{
+ struct iwl_tof_responder_dyn_config_cmd cmd = {
+ .lci_len = cpu_to_le32(params->lci_len + 2),
+ .civic_len = cpu_to_le32(params->civicloc_len + 2),
+ };
+ u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0};
+ struct iwl_host_cmd hcmd = {
+ .id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
+ LOCATION_GROUP, 0),
+ .data[0] = &cmd,
+ .len[0] = sizeof(cmd),
+ .data[1] = &data,
+ /* .len[1] set later */
+ /* may not be able to DMA from stack */
+ .dataflags[1] = IWL_HCMD_DFL_DUP,
+ };
+ u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4);
+ u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4);
+ u8 *pos = data;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) {
+ IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n",
+ params->lci_len, params->civicloc_len);
+ return -ENOBUFS;
+ }
+
+ pos[0] = WLAN_EID_MEASURE_REPORT;
+ pos[1] = params->lci_len;
+ memcpy(pos + 2, params->lci, params->lci_len);
+
+ pos += aligned_lci_len;
+ pos[0] = WLAN_EID_MEASURE_REPORT;
+ pos[1] = params->civicloc_len;
+ memcpy(pos + 2, params->civicloc, params->civicloc_len);
+
+ hcmd.len[1] = aligned_lci_len + aligned_civicloc_len;
+
+ return iwl_mvm_send_cmd(mvm, &hcmd);
+}
+
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_ftm_responder_params *params;
+ struct ieee80211_chanctx_conf ctx, *pctx;
+ u16 *phy_ctxt_id;
+ struct iwl_mvm_phy_ctxt *phy_ctxt;
+ int ret;
+
+ params = vif->bss_conf.ftmr_params;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
+ return -EINVAL;
+
+ if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
+ !mvmvif->ap_ibss_active) {
+ IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
+ return -EIO;
+ }
+
+ rcu_read_lock();
+ pctx = rcu_dereference(vif->chanctx_conf);
+ /* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
+ * about changes in the ctx after releasing the lock because the driver
+ * is still protected by the mutex. */
+ ctx = *pctx;
+ phy_ctxt_id = (u16 *)pctx->drv_priv;
+ rcu_read_unlock();
+
+ phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+ ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
+ ctx.rx_chains_static,
+ ctx.rx_chains_dynamic);
+ if (ret)
+ return ret;
+
+ ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
+ if (ret)
+ return ret;
+
+ if (params)
+ ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params);
+
+ return ret;
+}
+
+void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ if (!vif->bss_conf.ftm_responder)
+ return;
+
+ iwl_mvm_ftm_start_responder(mvm, vif);
+}
+
+void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_ftm_responder_stats *resp = (void *)pkt->data;
+ struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats;
+ u32 flags = le32_to_cpu(resp->flags);
+
+ if (resp->success_ftm == resp->ftm_per_burst)
+ stats->success_num++;
+ else if (resp->success_ftm >= 2)
+ stats->partial_num++;
+ else
+ stats->failed_num++;
+
+ if ((flags & FTM_RESP_STAT_ASAP_REQ) &&
+ (flags & FTM_RESP_STAT_ASAP_RESP))
+ stats->asap_num++;
+
+ if (flags & FTM_RESP_STAT_NON_ASAP_RESP)
+ stats->non_asap_num++;
+
+ stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC;
+
+ if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN)
+ stats->unknown_triggers_num++;
+
+ if (flags & FTM_RESP_STAT_DUP)
+ stats->reschedule_requests_num++;
+
+ if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN)
+ stats->out_of_window_triggers_num++;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 143c7fcaea41..e3eb812e0248 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +91,7 @@
#include "fw/api/sf.h"
#include "fw/api/sta.h"
#include "fw/api/stats.h"
-#include "fw/api/tof.h"
+#include "fw/api/location.h"
#include "fw/api/tx.h"
#endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 0d6c313b6669..00a47f6f1d81 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -105,12 +105,12 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
int i;
struct iwl_rss_config_cmd cmd = {
.flags = cpu_to_le32(IWL_RSS_ENABLE),
- .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
- IWL_RSS_HASH_TYPE_IPV4_UDP |
- IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
- IWL_RSS_HASH_TYPE_IPV6_TCP |
- IWL_RSS_HASH_TYPE_IPV6_UDP |
- IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
+ .hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) |
+ BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) |
+ BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) |
+ BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) |
+ BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) |
+ BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD),
};
if (mvm->trans->num_rx_queues == 1)
@@ -127,13 +127,17 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
static int iwl_configure_rxq(struct iwl_mvm *mvm)
{
- int i, num_queues, size;
+ int i, num_queues, size, ret;
struct iwl_rfh_queue_config *cmd;
+ struct iwl_host_cmd hcmd = {
+ .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+ };
/* Do not configure default queue, it is configured via context info */
num_queues = mvm->trans->num_rx_queues - 1;
- size = sizeof(*cmd) + num_queues * sizeof(struct iwl_rfh_queue_data);
+ size = struct_size(cmd, data, num_queues);
cmd = kzalloc(size, GFP_KERNEL);
if (!cmd)
@@ -154,10 +158,14 @@ static int iwl_configure_rxq(struct iwl_mvm *mvm)
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
}
- return iwl_mvm_send_cmd_pdu(mvm,
- WIDE_ID(DATA_PATH_GROUP,
- RFH_QUEUE_CONFIG_CMD),
- 0, size, cmd);
+ hcmd.data[0] = cmd;
+ hcmd.len[0] = size;
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
+
+ kfree(cmd);
+
+ return ret;
}
static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm)
@@ -210,7 +218,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_lmac_alive *lmac1;
struct iwl_lmac_alive *lmac2 = NULL;
u16 status;
- u32 umac_error_event_table;
+ u32 lmac_error_event_table, umac_error_event_table;
if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
palive = (void *)pkt->data;
@@ -225,30 +233,35 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
status = le16_to_cpu(palive3->status);
}
- mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr);
+ lmac_error_event_table =
+ le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
+ iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table);
+
if (lmac2)
- mvm->error_event_table[1] =
- le32_to_cpu(lmac2->error_event_table_ptr);
- mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
+ mvm->trans->lmac_error_event_table[1] =
+ le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
- umac_error_event_table = le32_to_cpu(umac->error_info_addr);
+ umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
if (!umac_error_event_table) {
mvm->support_umac_log = false;
} else if (umac_error_event_table >=
mvm->trans->cfg->min_umac_error_event_table) {
mvm->support_umac_log = true;
- mvm->umac_error_event_table = umac_error_event_table;
} else {
IWL_ERR(mvm,
"Not valid error log pointer 0x%08X for %s uCode\n",
- mvm->umac_error_event_table,
+ umac_error_event_table,
(mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
"Init" : "RT");
mvm->support_umac_log = false;
}
- alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr);
+ if (mvm->support_umac_log)
+ iwl_fw_umac_set_alive_err_table(mvm->trans,
+ umac_error_event_table);
+
+ alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr);
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
IWL_DEBUG_FW(mvm,
@@ -293,13 +306,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
enum iwl_ucode_type ucode_type)
{
struct iwl_notification_wait alive_wait;
- struct iwl_mvm_alive_data alive_data;
+ struct iwl_mvm_alive_data alive_data = {};
const struct fw_img *fw;
- int ret, i;
+ int ret;
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
static const u16 alive_cmd[] = { MVM_ALIVE };
- set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
if (ucode_type == IWL_UCODE_REGULAR &&
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
!(fw_has_capa(&mvm->fw->ucode_capa,
@@ -332,11 +344,16 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
if (ret) {
struct iwl_trans *trans = mvm->trans;
+ if (ret == -ETIMEDOUT)
+ iwl_fw_dbg_error_collect(&mvm->fwrt,
+ FW_DBG_TRIGGER_ALIVE_TIMEOUT);
+
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
- iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
- iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
+ iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
+ iwl_read_umac_prph(trans,
+ UMAG_SB_CPU_2_STATUS));
else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
@@ -373,14 +390,10 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].tid_bitmap =
BIT(IWL_MAX_TID_COUNT + 2);
- for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
- atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
-
set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_fw_set_dbg_rec_on(&mvm->fwrt);
#endif
- clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
return 0;
}
@@ -406,13 +419,15 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
iwl_wait_init_complete,
NULL);
+ iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
+
/* Will also start the device */
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
if (ret) {
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
- iwl_fw_assert_error_dump(&mvm->fwrt);
goto error;
}
+ iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
/* Send init config command to mark that we are sending NVM access
* commands
@@ -631,10 +646,10 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
}
#ifdef CONFIG_ACPI
-static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
- union acpi_object *table,
- struct iwl_mvm_sar_profile *profile,
- bool enabled)
+static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
+ union acpi_object *table,
+ struct iwl_mvm_sar_profile *profile,
+ bool enabled)
{
int i;
@@ -965,6 +980,57 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
}
#endif /* CONFIG_ACPI */
+void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
+{
+ u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
+ int ret;
+ u32 resp;
+
+ struct iwl_fw_error_recovery_cmd recovery_cmd = {
+ .flags = cpu_to_le32(flags),
+ .buf_size = 0,
+ };
+ struct iwl_host_cmd host_cmd = {
+ .id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
+ .flags = CMD_WANT_SKB,
+ .data = {&recovery_cmd, },
+ .len = {sizeof(recovery_cmd), },
+ };
+
+ /* no error log was defined in TLV */
+ if (!error_log_size)
+ return;
+
+ if (flags & ERROR_RECOVERY_UPDATE_DB) {
+ /* no buf was allocated while HW reset */
+ if (!mvm->error_recovery_buf)
+ return;
+
+ host_cmd.data[1] = mvm->error_recovery_buf;
+ host_cmd.len[1] = error_log_size;
+ host_cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
+ recovery_cmd.buf_size = cpu_to_le32(error_log_size);
+ }
+
+ ret = iwl_mvm_send_cmd(mvm, &host_cmd);
+ kfree(mvm->error_recovery_buf);
+ mvm->error_recovery_buf = NULL;
+
+ if (ret) {
+ IWL_ERR(mvm, "Failed to send recovery cmd %d\n", ret);
+ return;
+ }
+
+ /* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
+ if (flags & ERROR_RECOVERY_UPDATE_DB) {
+ resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
+ if (resp)
+ IWL_ERR(mvm,
+ "Failed to send recovery cmd blob was invalid %d\n",
+ resp);
+ }
+}
+
static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
{
int ret;
@@ -1055,7 +1121,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
ret = iwl_mvm_load_rt_fw(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
- iwl_fw_assert_error_dump(&mvm->fwrt);
+ iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
goto error;
}
@@ -1201,6 +1267,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+ iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
+
+ if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
+ IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
+
ret = iwl_mvm_sar_init(mvm);
if (ret == 0) {
ret = iwl_mvm_sar_geo_init(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
index 9bb1de1cad64..4348bb00e761 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
*
* 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
@@ -28,6 +29,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -113,6 +115,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)
switch (mode) {
case IWL_LED_BLINK:
IWL_ERR(mvm, "Blink led mode not supported, used default\n");
+ /* fall through */
case IWL_LED_DEFAULT:
case IWL_LED_RF_STATE:
mode = IWL_LED_RF_STATE;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 7779951a9533..6a70dece447d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -97,11 +97,6 @@ struct iwl_mvm_mac_iface_iterator_data {
bool found_vif;
};
-struct iwl_mvm_hw_queues_iface_iterator_data {
- struct ieee80211_vif *exclude_vif;
- unsigned long used_hw_queues;
-};
-
static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -208,61 +203,6 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
data->preferred_tsf = NUM_TSF_IDS;
}
-/*
- * Get the mask of the queues used by the vif
- */
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
-{
- u32 qmask = 0, ac;
-
- if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
- return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
- qmask |= BIT(vif->hw_queue[ac]);
- }
-
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC)
- qmask |= BIT(vif->cab_queue);
-
- return qmask;
-}
-
-static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
-
- /* exclude the given vif */
- if (vif == data->exclude_vif)
- return;
-
- data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
-}
-
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
- struct ieee80211_vif *exclude_vif)
-{
- struct iwl_mvm_hw_queues_iface_iterator_data data = {
- .exclude_vif = exclude_vif,
- .used_hw_queues =
- BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
- BIT(mvm->aux_queue) |
- BIT(IWL_MVM_DQA_GCAST_QUEUE),
- };
-
- lockdep_assert_held(&mvm->mutex);
-
- /* mark all VIF used hw queues */
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
- iwl_mvm_iface_hw_queues_iter, &data);
-
- return data.used_hw_queues;
-}
-
static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -360,8 +300,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
iwl_mvm_mac_iface_iterator, &data);
- used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif);
-
/*
* In the case we're getting here during resume, it's similar to
* firmware restart, and with RESUME_ALL the iterator will find
@@ -416,9 +354,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* the ones here - no real limit
*/
queue_limit = IEEE80211_MAX_QUEUES;
- BUILD_BUG_ON(IEEE80211_MAX_QUEUES >
- BITS_PER_BYTE *
- sizeof(mvm->hw_queue_to_mac80211[0]));
/*
* Find available queues, and allocate them to the ACs. When in
@@ -446,9 +381,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* queue value (when queue is enabled).
*/
mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
- vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
- } else {
- vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
}
mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
@@ -462,8 +394,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
exit_fail:
memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
- memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue));
- vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
return ret;
}
@@ -776,29 +706,10 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
- if (vif->bss_conf.assoc && vif->bss_conf.he_support &&
- !iwlwifi_mod_params.disable_11ax) {
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u8 sta_id = mvmvif->ap_sta_id;
-
+ if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
- if (sta_id != IWL_MVM_INVALID_STA) {
- struct ieee80211_sta *sta;
-
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
-
- /*
- * TODO: we should check the ext cap IE but it is
- * unclear why the spec requires two bits (one in HE
- * cap IE, and one in the ext cap IE). In the meantime
- * rely on the HE cap IE only.
- */
- if (sta && (sta->he_cap.he_cap_elem.mac_cap_info[0] &
- IEEE80211_HE_MAC_CAP0_TWT_RES))
- ctxt_sta->data_policy |=
- cpu_to_le32(TWT_SUPPORTED);
- }
+ if (vif->bss_conf.twt_requester)
+ ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
}
@@ -881,8 +792,6 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
- cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
-
/* Override the filter flags to accept only probe requests */
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
@@ -902,9 +811,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
-static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
- __le32 *tim_index, __le32 *tim_size,
- u8 *beacon, u32 frame_size)
+void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
+ __le32 *tim_index, __le32 *tim_size,
+ u8 *beacon, u32 frame_size)
{
u32 tim_idx;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@@ -944,8 +853,8 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
return ie - beacon;
}
-static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
- struct ieee80211_vif *vif)
+u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
+ struct ieee80211_vif *vif)
{
u8 rate;
@@ -995,9 +904,9 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
}
-static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
- struct sk_buff *beacon,
- void *data, int len)
+int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
+ struct sk_buff *beacon,
+ void *data, int len)
{
struct iwl_host_cmd cmd = {
.id = BEACON_TEMPLATE_CMD,
@@ -1100,13 +1009,16 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
sizeof(beacon_cmd));
}
-static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct sk_buff *beacon)
+int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct sk_buff *beacon)
{
if (WARN_ON(!beacon))
return -EINVAL;
+ if (IWL_MVM_NON_TRANSMITTING_AP)
+ return 0;
+
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD))
return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon);
@@ -1132,6 +1044,11 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
if (!beacon)
return -ENOMEM;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (mvm->beacon_inject_active)
+ return -EBUSY;
+#endif
+
ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
dev_kfree_skb(beacon);
return ret;
@@ -1203,7 +1120,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE))
- ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
+ ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
/*
* Only set the beacon time when the MAC is being added, when we
@@ -1420,7 +1337,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
- struct iwl_mvm_tx_resp *beacon_notify_hdr;
+ struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data;
struct ieee80211_vif *csa_vif;
struct ieee80211_vif *tx_blocked_vif;
struct agg_tx_status *agg_status;
@@ -1428,18 +1345,29 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- beacon_notify_hdr = &beacon->beacon_notify_hdr;
mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
- mvm->ibss_manager = beacon->ibss_mgr_status != 0;
- agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
- status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
- IWL_DEBUG_RX(mvm,
- "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
- status, beacon_notify_hdr->failure_frame,
- le64_to_cpu(beacon->tsf),
- mvm->ap_last_beacon_gp2,
- le32_to_cpu(beacon_notify_hdr->initial_rate));
+ if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) {
+ struct iwl_mvm_tx_resp *beacon_notify_hdr =
+ &beacon_v5->beacon_notify_hdr;
+
+ mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0;
+ agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
+ status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
+ IWL_DEBUG_RX(mvm,
+ "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
+ status, beacon_notify_hdr->failure_frame,
+ le64_to_cpu(beacon->tsf),
+ mvm->ap_last_beacon_gp2,
+ le32_to_cpu(beacon_notify_hdr->initial_rate));
+ } else {
+ mvm->ibss_manager = beacon->ibss_mgr_status != 0;
+ status = le32_to_cpu(beacon->status) & TX_STATUS_MSK;
+ IWL_DEBUG_RX(mvm,
+ "beacon status %#x tsf:0x%016llX gp2:0x%X\n",
+ status, le64_to_cpu(beacon->tsf),
+ mvm->ap_last_beacon_gp2);
+ }
csa_vif = rcu_dereference_protected(mvm->csa_vif,
lockdep_is_held(&mvm->mutex));
@@ -1472,35 +1400,48 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
}
}
-static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
+void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
{
- struct iwl_missed_beacons_notif *missed_beacons = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
struct iwl_fw_dbg_trigger_tlv *trigger;
u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
u32 rx_missed_bcon, rx_missed_bcon_since_rx;
+ struct ieee80211_vif *vif;
+ u32 id = le32_to_cpu(mb->mac_id);
- if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id))
- return;
+ IWL_DEBUG_INFO(mvm,
+ "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
+ le32_to_cpu(mb->mac_id),
+ le32_to_cpu(mb->consec_missed_beacons),
+ le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
+ le32_to_cpu(mb->num_recvd_beacons),
+ le32_to_cpu(mb->num_expected_beacons));
+
+ rcu_read_lock();
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
+ if (!vif)
+ goto out;
- rx_missed_bcon = le32_to_cpu(missed_beacons->consec_missed_beacons);
+ rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
rx_missed_bcon_since_rx =
- le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx);
+ le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
/*
* TODO: the threshold should be adjusted based on latency conditions,
* and/or in case of a CS flow on one of the other AP vifs.
*/
- if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) >
- IWL_MVM_MISSED_BEACONS_THRESHOLD)
+ if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG)
+ iwl_mvm_connection_loss(mvm, vif, "missed beacons");
+ else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
ieee80211_beacon_loss(vif);
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
FW_DBG_TRIGGER_MISSED_BEACONS);
if (!trigger)
- return;
+ goto out;
bcon_trig = (void *)trigger->data;
stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
@@ -1512,28 +1453,11 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
rx_missed_bcon >= stop_trig_missed_bcon)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
-}
-
-void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
-
- IWL_DEBUG_INFO(mvm,
- "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
- le32_to_cpu(mb->mac_id),
- le32_to_cpu(mb->consec_missed_beacons),
- le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
- le32_to_cpu(mb->num_recvd_beacons),
- le32_to_cpu(mb->num_expected_beacons));
-
- ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_beacon_loss_iterator,
- mb);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
+
+out:
+ rcu_read_unlock();
}
void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
@@ -1575,16 +1499,29 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
}
-static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
+void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
{
- struct iwl_probe_resp_data_notif *notif = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
struct iwl_probe_resp_data *old_data, *new_data;
+ int len = iwl_rx_packet_payload_len(pkt);
+ u32 id = le32_to_cpu(notif->mac_id);
+ struct ieee80211_vif *vif;
+ struct iwl_mvm_vif *mvmvif;
+
+ if (WARN_ON_ONCE(len < sizeof(*notif)))
+ return;
+
+ IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
+ notif->noa_active, notif->csa_counter);
- if (mvmvif->id != (u16)le32_to_cpu(notif->mac_id))
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
+ if (!vif)
return;
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
if (!new_data)
return;
@@ -1615,66 +1552,63 @@ static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac,
ieee80211_csa_set_counter(vif, notif->csa_counter);
}
-void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
- int len = iwl_rx_packet_payload_len(pkt);
-
- if (WARN_ON_ONCE(len < sizeof(*notif)))
- return;
-
- IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
- notif->noa_active, notif->csa_counter);
-
- ieee80211_iterate_active_interfaces(mvm->hw,
- IEEE80211_IFACE_ITER_ACTIVE,
- iwl_mvm_probe_resp_data_iter,
- notif);
-}
-
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
- struct ieee80211_vif *csa_vif;
+ struct ieee80211_vif *csa_vif, *vif;
struct iwl_mvm_vif *mvmvif;
int len = iwl_rx_packet_payload_len(pkt);
- u32 id_n_color;
+ u32 id_n_color, csa_id, mac_id;
if (WARN_ON_ONCE(len < sizeof(*notif)))
return;
- rcu_read_lock();
-
- csa_vif = rcu_dereference(mvm->csa_vif);
- if (WARN_ON(!csa_vif || !csa_vif->csa_active))
- goto out_unlock;
-
id_n_color = le32_to_cpu(notif->id_and_color);
+ mac_id = id_n_color & FW_CTXT_ID_MSK;
+
+ if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
+ return;
- mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
- if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color,
- "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
- FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color))
- goto out_unlock;
+ rcu_read_lock();
+ vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
- IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
+ csa_vif = rcu_dereference(mvm->csa_vif);
+ if (WARN_ON(!csa_vif || !csa_vif->csa_active ||
+ csa_vif != vif))
+ goto out_unlock;
- schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
- msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
- csa_vif->bss_conf.beacon_int));
+ mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
+ csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
+ if (WARN(csa_id != id_n_color,
+ "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
+ csa_id, id_n_color))
+ goto out_unlock;
- ieee80211_csa_finish(csa_vif);
+ IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
- rcu_read_unlock();
+ schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
+ msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
+ csa_vif->bss_conf.beacon_int));
- RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ ieee80211_csa_finish(csa_vif);
- return;
+ rcu_read_unlock();
+ RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ return;
+ case NL80211_IFTYPE_STATION:
+ iwl_mvm_csa_client_absent(mvm, vif);
+ ieee80211_chswitch_done(vif, true);
+ break;
+ default:
+ /* should never happen */
+ WARN_ON_ONCE(1);
+ break;
+ }
out_unlock:
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 97dc464379d2..3a92c09d4692 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -184,6 +184,29 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = {
};
#endif
+static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
+ .max_peers = IWL_MVM_TOF_MAX_APS,
+ .report_ap_tsf = 1,
+ .randomize_mac_addr = 1,
+
+ .ftm = {
+ .supported = 1,
+ .asap = 1,
+ .non_asap = 1,
+ .request_lci = 1,
+ .request_civicloc = 1,
+ .max_bursts_exponent = -1, /* all supported */
+ .max_ftms_per_burst = 0, /* no limits */
+ .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+ BIT(NL80211_CHAN_WIDTH_20) |
+ BIT(NL80211_CHAN_WIDTH_40) |
+ BIT(NL80211_CHAN_WIDTH_80),
+ .preambles = BIT(NL80211_PREAMBLE_LEGACY) |
+ BIT(NL80211_PREAMBLE_HT) |
+ BIT(NL80211_PREAMBLE_VHT),
+ },
+};
+
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
if (!iwl_mvm_is_d0i3_supported(mvm))
@@ -395,6 +418,21 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
return ret;
}
+const static u8 he_if_types_ext_capa_sta[] = {
+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
+};
+
+const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
+ {
+ .iftype = NL80211_IFTYPE_STATION,
+ .extended_capabilities = he_if_types_ext_capa_sta,
+ .extended_capabilities_mask = he_if_types_ext_capa_sta,
+ .extended_capabilities_len = sizeof(he_if_types_ext_capa_sta),
+ },
+};
+
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
{
struct ieee80211_hw *hw = mvm->hw;
@@ -405,12 +443,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
};
+#ifdef CONFIG_PM_SLEEP
+ bool unified = fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
+#endif
/* Tell mac80211 our characteristics */
ieee80211_hw_set(hw, SIGNAL_DBM);
ieee80211_hw_set(hw, SPECTRUM_MGMT);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
- ieee80211_hw_set(hw, QUEUE_CONTROL);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
@@ -424,6 +465,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
+ ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
+ ieee80211_hw_set(hw, STA_MMPDU_TXQ);
+ ieee80211_hw_set(hw, TX_AMSDU);
+ ieee80211_hw_set(hw, TX_FRAG_LIST);
if (iwl_mvm_has_tlc_offload(mvm)) {
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
@@ -469,6 +514,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
+ hw->max_tx_fragments = mvm->trans->max_skb_frags;
BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 6);
memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
@@ -525,6 +571,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->n_cipher_suites++;
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
+ wiphy_ext_feature_set(hw->wiphy,
+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
+ }
+
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
hw->wiphy->features |=
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
@@ -534,6 +587,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
hw->chanctx_data_size = sizeof(u16);
+ hw->txq_data_size = sizeof(struct iwl_mvm_txq);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
@@ -673,6 +727,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
}
+ if (mvm->nvm_data->sku_cap_11ax_enable &&
+ !iwlwifi_mod_params.disable_11ax) {
+ hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa;
+ hw->wiphy->num_iftype_ext_capab =
+ ARRAY_SIZE(he_iftypes_ext_capa);
+ }
+
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
#ifdef CONFIG_PM_SLEEP
@@ -682,7 +743,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->wowlan = &mvm->wowlan;
}
- if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec &&
+ if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
mvm->trans->ops->d3_suspend &&
mvm->trans->ops->d3_resume &&
device_can_wakeup(mvm->trans->dev)) {
@@ -735,15 +796,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS;
}
- ret = ieee80211_register_hw(mvm->hw);
- if (ret)
- iwl_mvm_leds_exit(mvm);
- mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
-
if (mvm->cfg->vht_mu_mimo_supported)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
+ ret = ieee80211_register_hw(mvm->hw);
+ if (ret) {
+ iwl_mvm_leds_exit(mvm);
+ }
+
return ret;
}
@@ -776,7 +837,6 @@ static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm,
goto out;
__skb_queue_tail(&mvm->d0i3_tx, skb);
- ieee80211_stop_queues(mvm->hw);
/* trigger wakeup */
iwl_mvm_ref(mvm, IWL_MVM_REF_TX);
@@ -796,13 +856,15 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
struct ieee80211_sta *sta = control->sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
+ bool offchannel = IEEE80211_SKB_CB(skb)->flags &
+ IEEE80211_TX_CTL_TX_OFFCHAN;
if (iwl_mvm_is_radio_killed(mvm)) {
IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
goto drop;
}
- if (info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
+ if (offchannel &&
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
!test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
goto drop;
@@ -815,8 +877,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
sta = NULL;
/* If there is no sta, and it's not offchannel - send through AP */
- if (info->control.vif->type == NL80211_IFTYPE_STATION &&
- info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) {
+ if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION &&
+ !offchannel) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info->control.vif);
u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
@@ -844,22 +906,101 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
ieee80211_free_txskb(hw, skb);
}
-static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
{
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
- return false;
- return true;
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
+ struct sk_buff *skb = NULL;
+
+ /*
+ * No need for threads to be pending here, they can leave the first
+ * taker all the work.
+ *
+ * mvmtxq->tx_request logic:
+ *
+ * If 0, no one is currently TXing, set to 1 to indicate current thread
+ * will now start TX and other threads should quit.
+ *
+ * If 1, another thread is currently TXing, set to 2 to indicate to
+ * that thread that there was another request. Since that request may
+ * have raced with the check whether the queue is empty, the TXing
+ * thread should check the queue's status one more time before leaving.
+ * This check is done in order to not leave any TX hanging in the queue
+ * until the next TX invocation (which may not even happen).
+ *
+ * If 2, another thread is currently TXing, and it will already double
+ * check the queue, so do nothing.
+ */
+ if (atomic_fetch_add_unless(&mvmtxq->tx_request, 1, 2))
+ return;
+
+ rcu_read_lock();
+ do {
+ while (likely(!mvmtxq->stopped &&
+ (mvm->trans->system_pm_mode ==
+ IWL_PLAT_PM_MODE_DISABLED))) {
+ skb = ieee80211_tx_dequeue(hw, txq);
+
+ if (!skb) {
+ if (txq->sta)
+ IWL_DEBUG_TX(mvm,
+ "TXQ of sta %pM tid %d is now empty\n",
+ txq->sta->addr,
+ txq->tid);
+ break;
+ }
+
+ if (!txq->sta)
+ iwl_mvm_tx_skb_non_sta(mvm, skb);
+ else
+ iwl_mvm_tx_skb(mvm, skb, txq->sta);
+ }
+ } while (atomic_dec_return(&mvmtxq->tx_request));
+ rcu_read_unlock();
}
-static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
{
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
- return false;
- if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
- return true;
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
- /* enabled by default */
- return true;
+ /*
+ * Please note that racing is handled very carefully here:
+ * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
+ * deleted afterwards.
+ * This means that if:
+ * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
+ * queue is allocated and we can TX.
+ * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
+ * a race, should defer the frame.
+ * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
+ * need to allocate the queue and defer the frame.
+ * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
+ * queue is already scheduled for allocation, no need to allocate,
+ * should defer the frame.
+ */
+
+ /* If the queue is allocated TX and return. */
+ if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
+ /*
+ * Check that list is empty to avoid a race where txq_id is
+ * already updated, but the queue allocation work wasn't
+ * finished
+ */
+ if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
+ return;
+
+ iwl_mvm_mac_itxq_xmit(hw, txq);
+ return;
+ }
+
+ /* The list is being deleted only after the queue is fully allocated. */
+ if (!list_empty(&mvmtxq->list))
+ return;
+
+ list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
+ schedule_work(&mvm->add_stream_wk);
}
#define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \
@@ -974,7 +1115,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
mvmvif = iwl_mvm_vif_from_mac80211(vif);
cancel_delayed_work(&mvmvif->uapsd_nonagg_detected_wk);
}
- if (!iwl_enable_rx_ampdu(mvm->cfg)) {
+ if (!iwl_enable_rx_ampdu()) {
ret = -EINVAL;
break;
}
@@ -986,7 +1127,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
timeout);
break;
case IEEE80211_AMPDU_TX_START:
- if (!iwl_enable_tx_ampdu(mvm->cfg)) {
+ if (!iwl_enable_tx_ampdu()) {
ret = -EINVAL;
break;
}
@@ -1066,6 +1207,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_stop_device(mvm);
+ mvm->cur_aid = 0;
+
mvm->scan_status = 0;
mvm->ps_disabled = false;
mvm->calibrating = false;
@@ -1074,6 +1217,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_cleanup_roc_te(mvm);
ieee80211_remain_on_channel_expired(mvm->hw);
+ iwl_mvm_ftm_restart(mvm);
+
/*
* cleanup all interfaces, even inactive ones, as some might have
* gone down during the HW restart
@@ -1085,7 +1230,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
- memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames));
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
@@ -1188,6 +1332,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
/* allow transport/FW low power modes */
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
+ iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY);
+
/*
* If we have TDLS peers, remove them. We don't know the last seqno/PN
* of packets the FW sent out, so we must reconnect.
@@ -1391,6 +1537,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out_unlock;
+ rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
+
/* Counting number of interfaces is needed for legacy PM */
if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
mvm->vif_count++;
@@ -1549,6 +1697,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
}
+ if (vif->bss_conf.ftm_responder)
+ memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
+
iwl_mvm_vif_dbgfs_clean(mvm, vif);
/*
@@ -1582,6 +1733,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_power_update_mac(mvm);
iwl_mvm_mac_ctxt_remove(mvm, vif);
+ RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
+
if (vif->type == NL80211_IFTYPE_MONITOR)
mvm->monitor_on = false;
@@ -2076,6 +2229,46 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
}
flags |= STA_CTXT_HE_PACKET_EXT;
+ } else if ((sta->he_cap.he_cap_elem.phy_cap_info[9] &
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) !=
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED) {
+ int low_th = -1;
+ int high_th = -1;
+
+ /* Take the PPE thresholds from the nominal padding info */
+ switch (sta->he_cap.he_cap_elem.phy_cap_info[9] &
+ IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) {
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US:
+ low_th = IWL_HE_PKT_EXT_NONE;
+ high_th = IWL_HE_PKT_EXT_NONE;
+ break;
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US:
+ low_th = IWL_HE_PKT_EXT_BPSK;
+ high_th = IWL_HE_PKT_EXT_NONE;
+ break;
+ case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US:
+ low_th = IWL_HE_PKT_EXT_NONE;
+ high_th = IWL_HE_PKT_EXT_BPSK;
+ break;
+ }
+
+ /* Set the PPE thresholds accordingly */
+ if (low_th >= 0 && high_th >= 0) {
+ u8 ***pkt_ext_qam =
+ (void *)sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th;
+
+ for (i = 0; i < MAX_HE_SUPP_NSS; i++) {
+ u8 bw;
+
+ for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX;
+ bw++) {
+ pkt_ext_qam[i][bw][0] = low_th;
+ pkt_ext_qam[i][bw][1] = high_th;
+ }
+ }
+
+ flags |= STA_CTXT_HE_PACKET_EXT;
+ }
}
rcu_read_unlock();
@@ -2146,6 +2339,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
}
+ /* Update MU EDCA params */
+ if (changes & BSS_CHANGED_QOS && mvmvif->associated &&
+ bss_conf->assoc && vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax)
+ iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);
+
/*
* If we're not associated yet, take the (new) BSSID before associating
* so the firmware knows. If we're already associated, then use the old
@@ -2211,7 +2410,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
* If update fails - SF might be running in associated
* mode while disassociated - which is forbidden.
*/
- WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
+ ret = iwl_mvm_sf_update(mvm, vif, false);
+ WARN_ONCE(ret &&
+ !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status),
"Failed to update SF upon disassociation\n");
/*
@@ -2432,6 +2634,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
+ iwl_mvm_ftm_restart_responder(mvm, vif);
+
goto out_unlock;
out_quota_failed:
@@ -2543,6 +2747,15 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
bss_conf->txpower);
iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
}
+
+ if (changes & BSS_CHANGED_FTM_RESPONDER) {
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+
+ if (ret)
+ IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
+ ret);
+ }
+
}
static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
@@ -2672,7 +2885,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
return;
spin_lock_bh(&mvmsta->lock);
- for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
+ for (tid = 0; tid < ARRAY_SIZE(mvmsta->tid_data); tid++) {
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE)
@@ -2861,32 +3074,6 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
peer_addr, action);
}
-static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta)
-{
- struct iwl_mvm_tid_data *tid_data;
- struct sk_buff *skb;
- int i;
-
- spin_lock_bh(&mvm_sta->lock);
- for (i = 0; i <= IWL_MAX_TID_COUNT; i++) {
- tid_data = &mvm_sta->tid_data[i];
-
- while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
- /*
- * The first deferred frame should've stopped the MAC
- * queues, so we should never get a second deferred
- * frame for the RA/TID.
- */
- iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));
- ieee80211_free_txskb(mvm->hw, skb);
- }
- }
- spin_unlock_bh(&mvm_sta->lock);
-}
-
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -2920,7 +3107,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
*/
if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) {
- iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta);
flush_work(&mvm->add_stream_wk);
/*
@@ -2967,6 +3153,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
NL80211_TDLS_SETUP);
}
+
+ sta->max_rc_amsdu_len = 1;
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) {
/*
@@ -2979,11 +3167,15 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC) {
if (vif->type == NL80211_IFTYPE_AP) {
+ vif->bss_conf.he_support = sta->he_cap.has_he;
mvmvif->ap_assoc_sta_count++;
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (vif->bss_conf.he_support &&
!iwlwifi_mod_params.disable_11ax)
iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
+ vif->bss_conf.he_support = sta->he_cap.has_he;
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
@@ -2991,6 +3183,24 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
ret = iwl_mvm_update_sta(mvm, vif, sta);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
+ /* if wep is used, need to set the key for the station now */
+ if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
+ mvm_sta->wep_key =
+ kmemdup(mvmvif->ap_wep_key,
+ sizeof(*mvmvif->ap_wep_key) +
+ mvmvif->ap_wep_key->keylen,
+ GFP_KERNEL);
+ if (!mvm_sta->wep_key) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ ret = iwl_mvm_set_sta_key(mvm, vif, sta,
+ mvm_sta->wep_key,
+ STA_KEY_IDX_INVALID);
+ } else {
+ ret = 0;
+ }
/* we don't support TDLS during DCM */
if (iwl_mvm_phy_ctx_count(mvm) > 1)
@@ -3005,18 +3215,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
true);
-
- /* if wep is used, need to set the key for the station now */
- if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key)
- ret = iwl_mvm_set_sta_key(mvm, vif, sta,
- mvmvif->ap_wep_key,
- STA_KEY_IDX_INVALID);
- else
- ret = 0;
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
/* disable beacon filtering */
- WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0));
+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+ WARN_ON(ret &&
+ !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status));
ret = 0;
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
@@ -3036,6 +3241,22 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
NL80211_TDLS_DISABLE_LINK);
}
+
+ /* Remove STA key if this is an AP using WEP */
+ if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
+ int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta,
+ mvm_sta->wep_key);
+
+ if (!ret)
+ ret = rm_ret;
+ kfree(mvm_sta->wep_key);
+ mvm_sta->wep_key = NULL;
+ }
+
+ if (unlikely(ret &&
+ test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status)))
+ ret = 0;
} else {
ret = -EIO;
}
@@ -3431,14 +3652,20 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
.sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
- /* Set the channel info data */
- .channel_info.band = (channel->band == NL80211_BAND_2GHZ) ?
- PHY_BAND_24 : PHY_BAND_5,
- .channel_info.channel = channel->hw_value,
- .channel_info.width = PHY_VHT_CHANNEL_MODE20,
- /* Set the time and duration */
- .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
- };
+ };
+ struct iwl_hs20_roc_req_tail *tail = iwl_mvm_chan_info_cmd_tail(mvm,
+ &aux_roc_req.channel_info);
+ u16 len = sizeof(aux_roc_req) - iwl_mvm_chan_info_padding(mvm);
+
+ /* Set the channel info data */
+ iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value,
+ (channel->band == NL80211_BAND_2GHZ) ?
+ PHY_BAND_24 : PHY_BAND_5,
+ PHY_VHT_CHANNEL_MODE20,
+ 0);
+
+ /* Set the time and duration */
+ tail->apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg));
delay = AUX_ROC_MIN_DELAY;
req_dur = MSEC_TO_TU(duration);
@@ -3463,15 +3690,15 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
}
}
- aux_roc_req.duration = cpu_to_le32(req_dur);
- aux_roc_req.apply_time_max_delay = cpu_to_le32(delay);
+ tail->duration = cpu_to_le32(req_dur);
+ tail->apply_time_max_delay = cpu_to_le32(delay);
IWL_DEBUG_TE(mvm,
"ROC: Requesting to remain on channel %u for %ums (requested = %ums, max_delay = %ums, dtim_interval = %ums)\n",
channel->hw_value, req_dur, duration, delay,
dtim_interval);
/* Set the node address */
- memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
+ memcpy(tail->node_addr, vif->addr, ETH_ALEN);
lockdep_assert_held(&mvm->mutex);
@@ -3502,7 +3729,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
ARRAY_SIZE(time_event_response),
iwl_mvm_rx_aux_roc, te_data);
- res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
+ res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, len,
&aux_roc_req);
if (res) {
@@ -3673,11 +3900,43 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
return 0;
}
+struct iwl_mvm_ftm_responder_iter_data {
+ bool responder;
+ struct ieee80211_chanctx_conf *ctx;
+};
+
+static void iwl_mvm_ftm_responder_chanctx_iter(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_ftm_responder_iter_data *data = _data;
+
+ if (rcu_access_pointer(vif->chanctx_conf) == data->ctx &&
+ vif->type == NL80211_IFTYPE_AP && vif->bss_conf.ftmr_params)
+ data->responder = true;
+}
+
+static bool iwl_mvm_is_ftm_responder_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct iwl_mvm_ftm_responder_iter_data data = {
+ .responder = false,
+ .ctx = ctx,
+ };
+
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_ftm_responder_chanctx_iter,
+ &data);
+ return data.responder;
+}
+
static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
struct ieee80211_chanctx_conf *ctx)
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt;
+ bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
+ struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
int ret;
lockdep_assert_held(&mvm->mutex);
@@ -3690,7 +3949,7 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
goto out;
}
- ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
+ ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
ctx->rx_chains_static,
ctx->rx_chains_dynamic);
if (ret) {
@@ -3745,6 +4004,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+ bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
+ struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
if (WARN_ONCE((phy_ctxt->ref > 1) &&
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
@@ -3759,17 +4020,17 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
/* we are only changing the min_width, may be a noop */
if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
- if (phy_ctxt->width == ctx->min_def.width)
+ if (phy_ctxt->width == def->width)
goto out_unlock;
/* we are just toggling between 20_NOHT and 20 */
if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 &&
- ctx->min_def.width <= NL80211_CHAN_WIDTH_20)
+ def->width <= NL80211_CHAN_WIDTH_20)
goto out_unlock;
}
iwl_mvm_bt_coex_vif_change(mvm);
- iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
+ iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
ctx->rx_chains_static,
ctx->rx_chains_dynamic);
@@ -3798,6 +4059,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
mvmvif->ap_ibss_active = true;
break;
}
+ /* fall through */
case NL80211_IFTYPE_ADHOC:
/*
* The AP binding flow is handled as part of the start_ap flow
@@ -3850,25 +4112,30 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
}
if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
- u32 duration = 3 * vif->bss_conf.beacon_int;
+ mvmvif->csa_bcn_pending = true;
- /* iwl_mvm_protect_session() reads directly from the
- * device (the system time), so make sure it is
- * available.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
- if (ret)
- goto out_remove_binding;
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
+ u32 duration = 3 * vif->bss_conf.beacon_int;
- /* Protect the session to make sure we hear the first
- * beacon on the new channel.
- */
- mvmvif->csa_bcn_pending = true;
- iwl_mvm_protect_session(mvm, vif, duration, duration,
- vif->bss_conf.beacon_int / 2,
- true);
- iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
+ /* iwl_mvm_protect_session() reads directly from the
+ * device (the system time), so make sure it is
+ * available.
+ */
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
+ if (ret)
+ goto out_remove_binding;
+
+ /* Protect the session to make sure we hear the first
+ * beacon on the new channel.
+ */
+ iwl_mvm_protect_session(mvm, vif, duration, duration,
+ vif->bss_conf.beacon_int / 2,
+ true);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
+ }
iwl_mvm_update_quotas(mvm, false, NULL);
}
@@ -3938,7 +4205,9 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
disabled_vif = vif;
- iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+ iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
break;
default:
break;
@@ -4189,6 +4458,27 @@ static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
"dummy channel switch op\n");
}
+static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_chan_switch_te_cmd cmd = {
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+ mvmvif->color)),
+ .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
+ .tsf = cpu_to_le32(chsw->timestamp),
+ .cs_count = chsw->count,
+ };
+
+ lockdep_assert_held(&mvm->mutex);
+
+ return iwl_mvm_send_cmd_pdu(mvm,
+ WIDE_ID(MAC_CONF_GROUP,
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
+ 0, sizeof(cmd), &cmd);
+}
+
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
@@ -4256,14 +4546,19 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
if (chsw->block_tx)
iwl_mvm_csa_client_absent(mvm, vif);
- iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
- apply_time);
if (mvmvif->bf_data.bf_enabled) {
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
if (ret)
goto out_unlock;
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+ iwl_mvm_schedule_client_csa(mvm, vif, chsw);
+ else
+ iwl_mvm_schedule_csa_period(mvm, vif,
+ vif->bss_conf.beacon_int,
+ apply_time);
break;
default:
break;
@@ -4656,8 +4951,89 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
mutex_unlock(&mvm->mutex);
}
+static int
+iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_ftm_responder_stats *stats)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
+ !mvmvif->ap_ibss_active || !vif->bss_conf.ftm_responder)
+ return -EINVAL;
+
+ mutex_lock(&mvm->mutex);
+ *stats = mvm->ftm_resp_stats;
+ mutex_unlock(&mvm->mutex);
+
+ stats->filled = BIT(NL80211_FTM_STATS_SUCCESS_NUM) |
+ BIT(NL80211_FTM_STATS_PARTIAL_NUM) |
+ BIT(NL80211_FTM_STATS_FAILED_NUM) |
+ BIT(NL80211_FTM_STATS_ASAP_NUM) |
+ BIT(NL80211_FTM_STATS_NON_ASAP_NUM) |
+ BIT(NL80211_FTM_STATS_TOTAL_DURATION_MSEC) |
+ BIT(NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM) |
+ BIT(NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM) |
+ BIT(NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM);
+
+ return 0;
+}
+
+static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+ ret = iwl_mvm_ftm_start(mvm, vif, request);
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ mutex_lock(&mvm->mutex);
+ iwl_mvm_ftm_abort(mvm, request);
+ mutex_unlock(&mvm->mutex);
+}
+
+static bool iwl_mvm_can_hw_csum(struct sk_buff *skb)
+{
+ u8 protocol = ip_hdr(skb)->protocol;
+
+ if (!IS_ENABLED(CONFIG_INET))
+ return false;
+
+ return protocol == IPPROTO_TCP || protocol == IPPROTO_UDP;
+}
+
+static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
+ struct sk_buff *head,
+ struct sk_buff *skb)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ /* For now don't aggregate IPv6 in AMSDU */
+ if (skb->protocol != htons(ETH_P_IP))
+ return false;
+
+ if (!iwl_mvm_is_csum_supported(mvm))
+ return true;
+
+ return iwl_mvm_can_hw_csum(skb) == iwl_mvm_can_hw_csum(head);
+}
+
const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
+ .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
.ampdu_action = iwl_mvm_mac_ampdu_action,
.start = iwl_mvm_mac_start,
.reconfig_complete = iwl_mvm_mac_reconfig_complete,
@@ -4731,6 +5107,11 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
#endif
.get_survey = iwl_mvm_mac_get_survey,
.sta_statistics = iwl_mvm_mac_sta_statistics,
+ .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
+ .start_pmsr = iwl_mvm_start_pmsr,
+ .abort_pmsr = iwl_mvm_abort_pmsr,
+
+ .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.sta_add_debugfs = iwl_mvm_sta_add_debugfs,
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 1aa690e081ff..bca6f6b536d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -83,7 +83,6 @@
#include "sta.h"
#include "fw-api.h"
#include "constants.h"
-#include "tof.h"
#include "fw/runtime.h"
#include "fw/dbg.h"
#include "fw/acpi.h"
@@ -95,6 +94,8 @@
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
+#define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 16
+
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
@@ -299,17 +300,38 @@ enum iwl_bt_force_ant_mode {
};
/**
+ * struct iwl_mvm_low_latency_force - low latency force mode set by debugfs
+ * @LOW_LATENCY_FORCE_UNSET: unset force mode
+ * @LOW_LATENCY_FORCE_ON: for low latency on
+ * @LOW_LATENCY_FORCE_OFF: for low latency off
+ * @NUM_LOW_LATENCY_FORCE: max num of modes
+ */
+enum iwl_mvm_low_latency_force {
+ LOW_LATENCY_FORCE_UNSET,
+ LOW_LATENCY_FORCE_ON,
+ LOW_LATENCY_FORCE_OFF,
+ NUM_LOW_LATENCY_FORCE
+};
+
+/**
* struct iwl_mvm_low_latency_cause - low latency set causes
* @LOW_LATENCY_TRAFFIC: indicates low latency traffic was detected
* @LOW_LATENCY_DEBUGFS: low latency mode set from debugfs
* @LOW_LATENCY_VCMD: low latency mode set from vendor command
* @LOW_LATENCY_VIF_TYPE: low latency mode set because of vif type (ap)
+* @LOW_LATENCY_DEBUGFS_FORCE_ENABLE: indicate that force mode is enabled
+* the actual set/unset is done with LOW_LATENCY_DEBUGFS_FORCE
+* @LOW_LATENCY_DEBUGFS_FORCE: low latency force mode from debugfs
+* set this with LOW_LATENCY_DEBUGFS_FORCE_ENABLE flag
+* in low_latency.
*/
enum iwl_mvm_low_latency_cause {
LOW_LATENCY_TRAFFIC = BIT(0),
LOW_LATENCY_DEBUGFS = BIT(1),
LOW_LATENCY_VCMD = BIT(2),
LOW_LATENCY_VIF_TYPE = BIT(3),
+ LOW_LATENCY_DEBUGFS_FORCE_ENABLE = BIT(4),
+ LOW_LATENCY_DEBUGFS_FORCE = BIT(5),
};
/**
@@ -360,8 +382,10 @@ struct iwl_probe_resp_data {
* @pm_enabled - Indicate if MAC power management is allowed
* @monitor_active: indicates that monitor context is configured, and that the
* interface should get quota etc.
- * @low_latency: indicates low latency is set, see
- * enum &iwl_mvm_low_latency_cause for causes.
+ * @low_latency: bit flags for low latency
+ * see enum &iwl_mvm_low_latency_cause for causes.
+ * @low_latency_actual: boolean, indicates low latency is set,
+ * as a result from low_latency bit flags and takes force into account.
* @ps_disabled: indicates that this interface requires PS to be disabled
* @queue_params: QoS params for this MAC
* @bcast_sta: station used for broadcast packets. Used by the following
@@ -393,7 +417,8 @@ struct iwl_mvm_vif {
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
- u8 low_latency;
+ u8 low_latency: 6;
+ u8 low_latency_actual: 1;
bool ps_disabled;
struct iwl_mvm_vif_bf_data bf_data;
@@ -778,6 +803,39 @@ struct iwl_mvm_geo_profile {
u8 values[ACPI_GEO_TABLE_SIZE];
};
+struct iwl_mvm_txq {
+ struct list_head list;
+ u16 txq_id;
+ atomic_t tx_request;
+ bool stopped;
+};
+
+static inline struct iwl_mvm_txq *
+iwl_mvm_txq_from_mac80211(struct ieee80211_txq *txq)
+{
+ return (void *)txq->drv_priv;
+}
+
+static inline struct iwl_mvm_txq *
+iwl_mvm_txq_from_tid(struct ieee80211_sta *sta, u8 tid)
+{
+ if (tid == IWL_MAX_TID_COUNT)
+ tid = IEEE80211_NUM_TIDS;
+
+ return (void *)sta->txq[tid]->drv_priv;
+}
+
+/**
+ * struct iwl_mvm_tvqm_txq_info - maps TVQM hw queue to tid
+ *
+ * @sta_id: sta id
+ * @txq_tid: txq tid
+ */
+struct iwl_mvm_tvqm_txq_info {
+ u8 sta_id;
+ u8 txq_tid;
+};
+
struct iwl_mvm_dqa_txq_info {
u8 ra_sta_id; /* The RA this queue is mapped to, if exists */
bool reserved; /* Is this the TXQ reserved for a STA */
@@ -821,9 +879,6 @@ struct iwl_mvm {
bool hw_registered;
bool calibrating;
- u32 error_event_table[2];
- u32 log_event_table;
- u32 umac_error_event_table;
bool support_umac_log;
u32 ampdu_ref;
@@ -843,13 +898,13 @@ struct iwl_mvm {
u64 on_time_scan;
} radio_stats, accu_radio_stats;
- u16 hw_queue_to_mac80211[IWL_MAX_TVQM_QUEUES];
-
- struct iwl_mvm_dqa_txq_info queue_info[IWL_MAX_HW_QUEUES];
+ struct list_head add_stream_txqs;
+ union {
+ struct iwl_mvm_dqa_txq_info queue_info[IWL_MAX_HW_QUEUES];
+ struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
+ };
struct work_struct add_stream_wk; /* To add streams to queues */
- atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES];
-
const char *nvm_file_name;
struct iwl_nvm_data *nvm_data;
/* NVM sections */
@@ -863,7 +918,6 @@ struct iwl_mvm {
/* data related to data path */
struct iwl_rx_phy_info last_phy_info;
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT];
- unsigned long sta_deferred_frames[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
u8 rx_ba_sessions;
/* configured by mac80211 */
@@ -924,6 +978,7 @@ struct iwl_mvm {
u32 dbgfs_prph_reg_addr;
bool disable_power_off;
bool disable_power_off_d3;
+ bool beacon_inject_active;
bool scan_iter_notif_enabled;
@@ -932,6 +987,7 @@ struct iwl_mvm {
struct debugfs_blob_wrapper nvm_calib_blob;
struct debugfs_blob_wrapper nvm_prod_blob;
struct debugfs_blob_wrapper nvm_phy_sku_blob;
+ struct debugfs_blob_wrapper nvm_reg_blob;
struct iwl_mvm_frame_stats drv_rx_stats;
spinlock_t drv_stats_lock;
@@ -955,9 +1011,11 @@ struct iwl_mvm {
u8 refs[IWL_MVM_REF_COUNT];
u8 vif_count;
+ struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
/* -1 for always, 0 for never, >0 for that many times */
s8 fw_restart;
+ u8 *error_recovery_buf;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
@@ -1047,6 +1105,8 @@ struct iwl_mvm {
/* Indicate if device power save is allowed */
u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
+ /* Indicate if 32Khz external clock is valid */
+ u32 ext_clock_valid;
unsigned int max_amsdu_len; /* used for debugfs only */
struct ieee80211_vif __rcu *csa_vif;
@@ -1090,7 +1150,14 @@ struct iwl_mvm {
u32 ciphers[IWL_MVM_NUM_CIPHERS];
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
- struct iwl_mvm_tof_data tof_data;
+
+ struct cfg80211_ftm_responder_stats ftm_resp_stats;
+ struct {
+ struct cfg80211_pmsr_request *req;
+ struct wireless_dev *req_wdev;
+ struct list_head loc_list;
+ int responses[IWL_MVM_TOF_MAX_APS];
+ } ftm_initiator;
struct ieee80211_vif *nan_vif;
#define IWL_MAX_BAID 32
@@ -1106,6 +1173,11 @@ struct iwl_mvm {
/* does a monitor vif exist (only one can exist hence bool) */
bool monitor_on;
+
+ /* sniffer data to include in radiotap */
+ __le16 cur_aid;
+ u8 cur_bssid[ETH_ALEN];
+
#ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
@@ -1149,8 +1221,6 @@ enum iwl_mvm_status {
enum iwl_mvm_init_status {
IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0),
IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1),
- IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2),
- IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE = BIT(3),
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -1207,6 +1277,19 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
return iwl_mvm_sta_from_mac80211(sta);
}
+static inline struct ieee80211_vif *
+iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
+{
+ if (WARN_ON(vif_id >= ARRAY_SIZE(mvm->vif_id_to_mac)))
+ return NULL;
+
+ if (rcu)
+ return rcu_dereference(mvm->vif_id_to_mac[vif_id]);
+
+ return rcu_dereference_protected(mvm->vif_id_to_mac[vif_id],
+ lockdep_is_held(&mvm->mutex));
+}
+
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
{
return !iwlwifi_mod_params.d0i3_disable &&
@@ -1237,6 +1320,12 @@ static inline bool iwl_mvm_is_frag_ebs_supported(struct iwl_mvm *mvm)
return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAG_EBS);
}
+static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm)
+{
+ return fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF);
+}
+
static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
{
/* For now we only use this mode to differentiate between
@@ -1470,6 +1559,11 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc);
+void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
+unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ unsigned int tid);
+
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_mvm_get_tx_fail_reason(u32 status);
#else
@@ -1567,6 +1661,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags);
void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
@@ -1599,9 +1694,19 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
+int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct sk_buff *beacon);
+int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
+ struct sk_buff *beacon,
+ void *data, int len);
+u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
+ struct ieee80211_vif *vif);
+void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
+ __le32 *tim_index, __le32 *tim_size,
+ u8 *beacon, u32 frame_size);
void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
@@ -1615,8 +1720,6 @@ void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
- struct ieee80211_vif *exclude_vif);
void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
@@ -1870,17 +1973,43 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
* binding, so this has no real impact. For now, just return
* the current desired low-latency state.
*/
- return mvmvif->low_latency;
+ return mvmvif->low_latency_actual;
}
static inline
void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set,
enum iwl_mvm_low_latency_cause cause)
{
+ u8 new_state;
+
if (set)
mvmvif->low_latency |= cause;
else
mvmvif->low_latency &= ~cause;
+
+ /*
+ * if LOW_LATENCY_DEBUGFS_FORCE_ENABLE is enabled no changes are
+ * allowed to actual mode.
+ */
+ if (mvmvif->low_latency & LOW_LATENCY_DEBUGFS_FORCE_ENABLE &&
+ cause != LOW_LATENCY_DEBUGFS_FORCE_ENABLE)
+ return;
+
+ if (cause == LOW_LATENCY_DEBUGFS_FORCE_ENABLE && set)
+ /*
+ * We enter force state
+ */
+ new_state = !!(mvmvif->low_latency &
+ LOW_LATENCY_DEBUGFS_FORCE);
+ else
+ /*
+ * Check if any other one set low latency
+ */
+ new_state = !!(mvmvif->low_latency &
+ ~(LOW_LATENCY_DEBUGFS_FORCE_ENABLE |
+ LOW_LATENCY_DEBUGFS_FORCE));
+
+ mvmvif->low_latency_actual = new_state;
}
/* Return a bitmask with all the hw supported queues, except for the
@@ -1895,21 +2024,24 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);
- /* calling this function without using dump_start/end since at this
- * point we already hold the op mode mutex
+ /* If IWL_MVM_STATUS_HW_RESTART_REQUESTED bit is set then we received
+ * an assert. Since we failed to bring the interface up, mac80211
+ * will not attempt to reconfig the device,
+ * which handles the dump collection in assert flow,
+ * so trigger dump collection here.
*/
- iwl_fw_dbg_collect_sync(&mvm->fwrt);
+ if (test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status))
+ iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
+ false, 0);
+
iwl_fw_cancel_timestamp(&mvm->fwrt);
- iwl_free_fw_paging(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+ iwl_fwrt_stop_device(&mvm->fwrt);
+ iwl_free_fw_paging(&mvm->fwrt);
iwl_fw_dump_conf_clear(&mvm->fwrt);
- iwl_trans_stop_device(mvm->trans);
}
-/* Stop/start all mac queues in a given bitmap */
-void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq);
-void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq);
-
/* Re-configure the SCD for a queue that has already been configured */
int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
int tid, int frame_limit, u16 ssn);
@@ -1949,6 +2081,23 @@ void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm);
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif);
+/* FTM responder */
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif);
+void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+
+/* FTM initiator */
+void iwl_mvm_ftm_restart(struct iwl_mvm *mvm);
+void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct cfg80211_pmsr_request *request);
+void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req);
+
/* TDLS */
/*
@@ -2015,4 +2164,59 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
struct dentry *dir);
#endif
+/* Channel info utils */
+static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
+{
+ return fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS);
+}
+
+static inline void *iwl_mvm_chan_info_cmd_tail(struct iwl_mvm *mvm,
+ struct iwl_fw_channel_info *ci)
+{
+ return (u8 *)ci + (iwl_mvm_has_ultra_hb_channel(mvm) ?
+ sizeof(struct iwl_fw_channel_info) :
+ sizeof(struct iwl_fw_channel_info_v1));
+}
+
+static inline size_t iwl_mvm_chan_info_padding(struct iwl_mvm *mvm)
+{
+ return iwl_mvm_has_ultra_hb_channel(mvm) ? 0 :
+ sizeof(struct iwl_fw_channel_info) -
+ sizeof(struct iwl_fw_channel_info_v1);
+}
+
+static inline void iwl_mvm_set_chan_info(struct iwl_mvm *mvm,
+ struct iwl_fw_channel_info *ci,
+ u32 chan, u8 band, u8 width,
+ u8 ctrl_pos)
+{
+ if (iwl_mvm_has_ultra_hb_channel(mvm)) {
+ ci->channel = cpu_to_le32(chan);
+ ci->band = band;
+ ci->width = width;
+ ci->ctrl_pos = ctrl_pos;
+ } else {
+ struct iwl_fw_channel_info_v1 *ci_v1 =
+ (struct iwl_fw_channel_info_v1 *)ci;
+
+ ci_v1->channel = chan;
+ ci_v1->band = band;
+ ci_v1->width = width;
+ ci_v1->ctrl_pos = ctrl_pos;
+ }
+}
+
+static inline void
+iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm,
+ struct iwl_fw_channel_info *ci,
+ struct cfg80211_chan_def *chandef)
+{
+ iwl_mvm_set_chan_info(mvm, ci, chandef->chan->hw_value,
+ (chandef->chan->band == NL80211_BAND_2GHZ ?
+ PHY_BAND_24 : PHY_BAND_5),
+ iwl_mvm_get_channel_width(chandef),
+ iwl_mvm_get_ctrl_pos(chandef));
+}
+
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index 6fc5cc1f2b5b..7bdbd010ae6b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -179,7 +179,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM access command failed with status %d (device: %s)\n",
ret, mvm->cfg->name);
- ret = -EIO;
+ ret = -ENODATA;
}
goto exit;
}
@@ -380,8 +380,12 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer,
size_read);
- if (ret < 0)
+ if (ret == -ENODATA) {
+ ret = 0;
continue;
+ }
+ if (ret < 0)
+ break;
size_read += ret;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
@@ -412,6 +416,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
mvm->nvm_phy_sku_blob.data = temp;
mvm->nvm_phy_sku_blob.size = ret;
break;
+ case NVM_SECTION_TYPE_REGULATORY_SDP:
+ case NVM_SECTION_TYPE_REGULATORY:
+ mvm->nvm_reg_blob.data = temp;
+ mvm->nvm_reg_blob.size = ret;
+ break;
default:
if (section == mvm->cfg->nvm_hw_section_num) {
mvm->nvm_hw_blob.data = temp;
@@ -454,7 +463,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
IWL_DEBUG_EEPROM(mvm->trans->dev, "nvm version = %x\n",
mvm->nvm_data->nvm_version);
- return 0;
+ return ret < 0 ? ret : 0;
}
struct iwl_mcc_update_resp *
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 30c5127034a0..ba27dce4c2bb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -82,7 +82,6 @@
#include "fw/api/scan.h"
#include "time-event.h"
#include "fw-api.h"
-#include "fw/api/scan.h"
#include "fw/acpi.h"
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
@@ -301,8 +300,14 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif,
RX_HANDLER_SYNC),
- RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler,
- RX_HANDLER_ASYNC_LOCKED),
+ RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS,
+ iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED),
+
+ RX_HANDLER_GRP(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,
+ iwl_mvm_ftm_range_resp, RX_HANDLER_ASYNC_LOCKED),
+ RX_HANDLER_GRP(LOCATION_GROUP, TOF_LC_NOTIF,
+ iwl_mvm_ftm_lc_notif, RX_HANDLER_ASYNC_LOCKED),
+
RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF,
iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC),
RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
@@ -329,8 +334,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_REQ_UMAC),
HCMD_NAME(SCAN_ABORT_UMAC),
HCMD_NAME(SCAN_COMPLETE_UMAC),
- HCMD_NAME(TOF_CMD),
- HCMD_NAME(TOF_NOTIFICATION),
HCMD_NAME(BA_WINDOW_STATUS_NOTIFICATION_ID),
HCMD_NAME(ADD_STA_KEY),
HCMD_NAME(ADD_STA),
@@ -419,12 +422,14 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
HCMD_NAME(SHARED_MEM_CFG_CMD),
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
+ HCMD_NAME(FW_ERROR_RECOVERY_CMD),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
+ HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
};
@@ -449,6 +454,8 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
HCMD_NAME(STA_HE_CTXT_CMD),
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
+ HCMD_NAME(TLC_MNG_CONFIG_CMD),
+ HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
@@ -464,6 +471,22 @@ static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
+static const struct iwl_hcmd_names iwl_mvm_location_names[] = {
+ HCMD_NAME(TOF_RANGE_REQ_CMD),
+ HCMD_NAME(TOF_CONFIG_CMD),
+ HCMD_NAME(TOF_RANGE_ABORT_CMD),
+ HCMD_NAME(TOF_RANGE_REQ_EXT_CMD),
+ HCMD_NAME(TOF_RESPONDER_CONFIG_CMD),
+ HCMD_NAME(TOF_RESPONDER_DYN_CONFIG_CMD),
+ HCMD_NAME(TOF_LC_NOTIF),
+ HCMD_NAME(TOF_RESPONDER_STATS),
+ HCMD_NAME(TOF_MCSI_DEBUG_NOTIF),
+ HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF),
+};
+
+/* Please keep this array *SORTED* by hex value.
+ * Access is done through binary search
+ */
static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
HCMD_NAME(STORED_BEACON_NTF),
};
@@ -483,6 +506,7 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
[MAC_CONF_GROUP] = HCMD_ARR(iwl_mvm_mac_conf_names),
[PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names),
[DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names),
+ [LOCATION_GROUP] = HCMD_ARR(iwl_mvm_location_names),
[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
[REGULATORY_AND_NVM_GROUP] =
HCMD_ARR(iwl_mvm_regulatory_and_nvm_names),
@@ -577,11 +601,17 @@ static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd)
return ret;
}
+static bool iwl_mvm_d3_debug_enable(void *ctx)
+{
+ return IWL_MVM_D3_DEBUG;
+}
+
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
.dump_start = iwl_mvm_fwrt_dump_start,
.dump_end = iwl_mvm_fwrt_dump_end,
.fw_running = iwl_mvm_fwrt_fw_running,
.send_hcmd = iwl_mvm_fwrt_send_hcmd,
+ .d3_debug_enable = iwl_mvm_d3_debug_enable,
};
static struct iwl_op_mode *
@@ -676,6 +706,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_LIST_HEAD(&mvm->aux_roc_te_list);
INIT_LIST_HEAD(&mvm->async_handlers_list);
spin_lock_init(&mvm->time_event_lock);
+ INIT_LIST_HEAD(&mvm->ftm_initiator.loc_list);
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
@@ -685,6 +716,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
+ INIT_LIST_HEAD(&mvm->add_stream_txqs);
spin_lock_init(&mvm->d0i3_tx_lock);
spin_lock_init(&mvm->refs_lock);
@@ -736,6 +768,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.rx_buf_size = rb_size_default;
}
+ BUILD_BUG_ON(sizeof(struct iwl_ldbg_config_cmd) !=
+ LDBG_CFG_COMMAND_SIZE);
+
trans->wide_cmd_header = true;
trans_cfg.bc_table_dword =
mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560;
@@ -799,8 +834,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_lock(&mvm->mutex);
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
err = iwl_run_init_mvm_ucode(mvm, true);
- if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status))
- iwl_fw_alive_error_dump(&mvm->fwrt);
+ if (err)
+ iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
if (!iwlmvm_mod_params.init_dbg || !err)
iwl_mvm_stop_device(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
@@ -842,8 +877,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (iwl_mvm_is_d0i3_supported(mvm))
iwl_trans_unref(mvm->trans);
- iwl_mvm_tof_init(mvm);
-
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
return op_mode;
@@ -886,15 +919,15 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_mvm_thermal_exit(mvm);
- if (mvm->init_status & IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE) {
- ieee80211_unregister_hw(mvm->hw);
- mvm->init_status &= ~IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
- }
+ ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd);
kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL;
+ kfree(mvm->error_recovery_buf);
+ mvm->error_recovery_buf = NULL;
+
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
kfree(mvm->d3_resume_sram);
#endif
@@ -909,8 +942,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
cancel_delayed_work_sync(&mvm->tcm.work);
- iwl_mvm_tof_clean(mvm);
-
iwl_fw_runtime_free(&mvm->fwrt);
mutex_destroy(&mvm->mutex);
mutex_destroy(&mvm->d0i3_suspend_mutex);
@@ -1079,24 +1110,6 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
iwl_mvm_rx_common(mvm, rxb, pkt);
}
-void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq)
-{
- int q;
-
- if (WARN_ON_ONCE(!mq))
- return;
-
- for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) {
- if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) {
- IWL_DEBUG_TX_QUEUES(mvm,
- "mac80211 %d already stopped\n", q);
- continue;
- }
-
- ieee80211_stop_queue(mvm->hw, q);
- }
-}
-
static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd)
{
@@ -1109,38 +1122,81 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
iwl_trans_block_txq_ptrs(mvm->trans, false);
}
-static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
+static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue)
{
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue];
-
- iwl_mvm_stop_mac_queues(mvm, mq);
+ return queue == mvm->aux_queue || queue == mvm->probe_queue ||
+ queue == mvm->p2p_dev_queue || queue == mvm->snif_queue;
}
-void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq)
+static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
+ int hw_queue, bool start)
{
- int q;
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+ struct ieee80211_sta *sta;
+ struct ieee80211_txq *txq;
+ struct iwl_mvm_txq *mvmtxq;
+ int i;
+ unsigned long tid_bitmap;
+ struct iwl_mvm_sta *mvmsta;
+ u8 sta_id;
+
+ sta_id = iwl_mvm_has_new_tx_api(mvm) ?
+ mvm->tvqm_info[hw_queue].sta_id :
+ mvm->queue_info[hw_queue].ra_sta_id;
- if (WARN_ON_ONCE(!mq))
+ if (WARN_ON_ONCE(sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
return;
- for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) {
- if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) {
- IWL_DEBUG_TX_QUEUES(mvm,
- "mac80211 %d still stopped\n", q);
- continue;
- }
+ rcu_read_lock();
+
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+ if (IS_ERR_OR_NULL(sta))
+ goto out;
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (iwl_mvm_is_static_queue(mvm, hw_queue)) {
+ if (!start)
+ ieee80211_stop_queues(mvm->hw);
+ else if (mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
+ ieee80211_wake_queues(mvm->hw);
+
+ goto out;
+ }
+
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ int tid = mvm->tvqm_info[hw_queue].txq_tid;
+
+ tid_bitmap = BIT(tid);
+ } else {
+ tid_bitmap = mvm->queue_info[hw_queue].tid_bitmap;
+ }
+
+ for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
+ int tid = i;
+
+ if (tid == IWL_MAX_TID_COUNT)
+ tid = IEEE80211_NUM_TIDS;
- ieee80211_wake_queue(mvm->hw, q);
+ txq = sta->txq[tid];
+ mvmtxq = iwl_mvm_txq_from_mac80211(txq);
+ mvmtxq->stopped = !start;
+
+ if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
+ iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
}
+
+out:
+ rcu_read_unlock();
}
-static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
+static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
{
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue];
+ iwl_mvm_queue_state_change(op_mode, hw_queue, false);
+}
- iwl_mvm_start_mac_queues(mvm, mq);
+static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
+{
+ iwl_mvm_queue_state_change(op_mode, hw_queue, true);
}
static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm)
@@ -1261,12 +1317,29 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
reprobe->dev = mvm->trans->dev;
INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
schedule_work(&reprobe->work);
+ } else if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+ &mvm->status)) {
+ IWL_ERR(mvm, "HW restart already requested, but not started\n");
} else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR &&
mvm->hw_registered &&
!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
/* don't let the transport/FW power down */
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
+ if (mvm->fw->ucode_capa.error_log_size) {
+ u32 src_size = mvm->fw->ucode_capa.error_log_size;
+ u32 src_addr = mvm->fw->ucode_capa.error_log_addr;
+ u8 *recover_buf = kzalloc(src_size, GFP_ATOMIC);
+
+ if (recover_buf) {
+ mvm->error_recovery_buf = recover_buf;
+ iwl_trans_read_mem_bytes(mvm->trans,
+ src_addr,
+ recover_buf,
+ src_size);
+ }
+ }
+
if (fw_error && mvm->fw_restart > 0)
mvm->fw_restart--;
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 7f5434b34d0d..86e40bae57e3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -109,6 +109,7 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
return PHY_VHT_CTRL_POS_4_ABOVE;
default:
WARN(1, "Invalid channel definition");
+ /* fall through */
case 0:
/*
* The FW is expected to check the control channel position only
@@ -143,14 +144,11 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
u8 chains_static, u8 chains_dynamic)
{
u8 active_cnt, idle_cnt;
+ struct iwl_phy_context_cmd_tail *tail =
+ iwl_mvm_chan_info_cmd_tail(mvm, &cmd->ci);
/* Set the channel info data */
- cmd->ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ?
- PHY_BAND_24 : PHY_BAND_5);
-
- cmd->ci.channel = chandef->chan->hw_value;
- cmd->ci.width = iwl_mvm_get_channel_width(chandef);
- cmd->ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
+ iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);
/* Set rx the chains */
idle_cnt = chains_static;
@@ -168,17 +166,17 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
active_cnt = 2;
}
- cmd->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) <<
+ tail->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) <<
PHY_RX_CHAIN_VALID_POS);
- cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
- cmd->rxchain_info |= cpu_to_le32(active_cnt <<
+ tail->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
+ tail->rxchain_info |= cpu_to_le32(active_cnt <<
PHY_RX_CHAIN_MIMO_CNT_POS);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (unlikely(mvm->dbgfs_rx_phyinfo))
- cmd->rxchain_info = cpu_to_le32(mvm->dbgfs_rx_phyinfo);
+ tail->rxchain_info = cpu_to_le32(mvm->dbgfs_rx_phyinfo);
#endif
- cmd->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
+ tail->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
}
/*
@@ -195,6 +193,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
{
struct iwl_phy_context_cmd cmd;
int ret;
+ u16 len = sizeof(cmd) - iwl_mvm_chan_info_padding(mvm);
/* Set the command header fields */
iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, action, apply_time);
@@ -203,9 +202,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef,
chains_static, chains_dynamic);
- ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0,
- sizeof(struct iwl_phy_context_cmd),
- &cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0, len, &cmd);
if (ret)
IWL_ERR(mvm, "PHY ctxt cmd error. ret=%d\n", ret);
return ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index 5a0a28fd762d..36f5fa1ee793 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
@@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,6 +81,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
struct iwl_beacon_filter_cmd *cmd,
u32 flags)
{
+ u16 len;
+
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
le32_to_cpu(cmd->ba_enable_beacon_abort));
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
@@ -101,9 +105,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
le32_to_cpu(cmd->bf_temp_fast_filter));
IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
le32_to_cpu(cmd->bf_temp_slow_filter));
+ IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
+ le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
+ le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
+
+ IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
+ le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
+ le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
+
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_BEACON_FILTER_V4))
+ len = sizeof(struct iwl_beacon_filter_cmd);
+ else
+ len = offsetof(struct iwl_beacon_filter_cmd,
+ bf_threshold_absolute_low);
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
- sizeof(struct iwl_beacon_filter_cmd), cmd);
+ len, cmd);
}
static
@@ -526,6 +544,9 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
cmd.flags &=
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
#endif
+ if (mvm->ext_clock_valid)
+ cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
+
IWL_DEBUG_POWER(mvm,
"Sending device power command with flags = 0x%X\n",
cmd.flags);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index dabbc04853ac..a28283ff7295 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -149,14 +149,9 @@ static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm,
if (he_cap && he_cap->has_he &&
(he_cap->he_cap_elem.phy_cap_info[3] &
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK)) {
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK))
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
- if (he_cap->he_cap_elem.phy_cap_info[3] &
- IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2)
- flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK;
- }
-
return flags;
}
@@ -320,12 +315,26 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
if (flags & IWL_TLC_NOTIF_FLAG_AMSDU) {
u16 size = le32_to_cpu(notif->amsdu_size);
+ int i;
if (WARN_ON(sta->max_amsdu_len < size))
goto out;
mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
mvmsta->max_amsdu_len = size;
+ sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
+
+ for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
+ if (mvmsta->amsdu_enabled & BIT(i))
+ sta->max_tid_amsdu_len[i] =
+ iwl_mvm_max_amsdu_size(mvm, sta, i);
+ else
+ /*
+ * Not so elegant, but this will effectively
+ * prevent AMSDU on this TID
+ */
+ sta->max_tid_amsdu_len[i] = 1;
+ }
IWL_DEBUG_RATE(mvm,
"AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 089972280daa..e231a44d2423 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -3,7 +3,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -1643,8 +1643,26 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
{
+ struct ieee80211_sta_vht_cap *sta_vht_cap = &sta->vht_cap;
+ struct ieee80211_vht_cap vht_cap = {
+ .vht_cap_info = cpu_to_le32(sta_vht_cap->cap),
+ .supp_mcs = sta_vht_cap->vht_mcs,
+ };
+
switch (sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
+ /*
+ * Don't use 160 MHz if VHT extended NSS support
+ * says we cannot use 2 streams, we don't want to
+ * deal with this.
+ * We only check MCS 0 - they will support that if
+ * we got here at all and we don't care which MCS,
+ * we want to determine a more global state.
+ */
+ if (ieee80211_get_vht_max_nss(&vht_cap,
+ IEEE80211_VHT_CHANWIDTH_160MHZ,
+ 0, true) < sta->rx_nss)
+ return RATE_MCS_CHAN_WIDTH_80;
return RATE_MCS_CHAN_WIDTH_160;
case IEEE80211_STA_RX_BW_80:
return RATE_MCS_CHAN_WIDTH_80;
@@ -1744,6 +1762,7 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum rs_action scale_action)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ int i;
/*
* In case TLC offload is not active amsdu_enabled is either 0xFFFF
@@ -1756,7 +1775,25 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
else
mvmsta->amsdu_enabled = 0xFFFF;
- mvmsta->max_amsdu_len = sta->max_amsdu_len;
+ if (mvmsta->vif->bss_conf.he_support &&
+ !iwlwifi_mod_params.disable_11ax)
+ mvmsta->max_amsdu_len = sta->max_amsdu_len;
+ else
+ mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500);
+
+ sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
+
+ for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
+ if (mvmsta->amsdu_enabled)
+ sta->max_tid_amsdu_len[i] =
+ iwl_mvm_max_amsdu_size(mvm, sta, i);
+ else
+ /*
+ * Not so elegant, but this will effectively
+ * prevent AMSDU on this TID
+ */
+ sta->max_tid_amsdu_len[i] = 1;
+ }
}
/*
@@ -1777,7 +1814,7 @@ static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl,
enum rs_action scale_action)
{
- if (sta->bandwidth != IEEE80211_STA_RX_BW_80)
+ if (rs_bw_from_sta_bw(sta) != RATE_MCS_CHAN_WIDTH_80)
return false;
if (!is_vht_siso(&tbl->rate))
@@ -3332,12 +3369,12 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI
* column the rate table should look like this:
*
- * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
- * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
- * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
- * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
- * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
- * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
+ * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
+ * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
+ * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
+ * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
+ * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
+ * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
* rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI
* rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI
* rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI
@@ -4108,6 +4145,7 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
.add_sta_debugfs = rs_drv_add_sta_debugfs,
.remove_sta_debugfs = rs_remove_sta_debugfs,
#endif
+ .capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW,
};
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 6653a238f32e..fbd3014e8b82 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -222,7 +222,7 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
*crypt_len = IEEE80211_TKIP_IV_LEN;
- /* fall through if TTAK OK */
+ /* fall through */
case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK))
@@ -599,8 +599,8 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
* data copied into the "data" struct, but rather the data from
* the notification directly.
*/
- if (iwl_mvm_is_cdb_supported(mvm)) {
- struct mvm_statistics_general_cdb *general =
+ if (iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct mvm_statistics_general *general =
data->general;
mvmvif->beacon_stats.num_beacons =
@@ -723,7 +723,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
else
expected_size = sizeof(struct iwl_notif_statistics_v10);
} else {
- expected_size = sizeof(struct iwl_notif_statistics_cdb);
+ expected_size = sizeof(struct iwl_notif_statistics);
}
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) != expected_size,
@@ -753,7 +753,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
flags = stats->flag;
} else {
- struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+ struct iwl_notif_statistics *stats = (void *)&pkt->data;
data.mac_id = stats->rx.general.mac_id;
data.beacon_filter_average_energy =
@@ -792,7 +792,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
bytes = (void *)&v11->load_stats.byte_count;
air_time = (void *)&v11->load_stats.air_time;
} else {
- struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+ struct iwl_notif_statistics *stats = (void *)&pkt->data;
energy = (void *)&stats->load_stats.avg_energy;
bytes = (void *)&stats->load_stats.byte_count;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 7bd8676508f5..1e03acf30762 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -66,11 +66,37 @@
#include "mvm.h"
#include "fw-api.h"
+static void *iwl_mvm_skb_get_hdr(struct sk_buff *skb)
+{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ u8 *data = skb->data;
+
+ /* Alignment concerns */
+ BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4);
+ BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4);
+ BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) % 4);
+ BUILD_BUG_ON(sizeof(struct ieee80211_vendor_radiotap) % 4);
+
+ if (rx_status->flag & RX_FLAG_RADIOTAP_HE)
+ data += sizeof(struct ieee80211_radiotap_he);
+ if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU)
+ data += sizeof(struct ieee80211_radiotap_he_mu);
+ if (rx_status->flag & RX_FLAG_RADIOTAP_LSIG)
+ data += sizeof(struct ieee80211_radiotap_lsig);
+ if (rx_status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
+ struct ieee80211_vendor_radiotap *radiotap = (void *)data;
+
+ data += sizeof(*radiotap) + radiotap->len + radiotap->pad;
+ }
+
+ return data;
+}
+
static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
int queue, struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvmsta;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
struct iwl_mvm_key_pn *ptk_pn;
int res;
@@ -192,27 +218,50 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
}
}
+static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
+ struct sk_buff *skb)
+{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_vendor_radiotap *radiotap;
+ const int size = sizeof(*radiotap) + sizeof(__le16);
+
+ if (!mvm->cur_aid)
+ return;
+
+ /* ensure alignment */
+ BUILD_BUG_ON((size + 2) % 4);
+
+ radiotap = skb_put(skb, size + 2);
+ radiotap->align = 1;
+ /* Intel OUI */
+ radiotap->oui[0] = 0xf6;
+ radiotap->oui[1] = 0x54;
+ radiotap->oui[2] = 0x25;
+ /* radiotap sniffer config sub-namespace */
+ radiotap->subns = 1;
+ radiotap->present = 0x1;
+ radiotap->len = size - sizeof(*radiotap);
+ radiotap->pad = 2;
+
+ /* fill the data now */
+ memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
+ /* and clear the padding */
+ memset(radiotap->data + sizeof(__le16), 0, radiotap->pad);
+
+ rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
+}
+
/* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
struct napi_struct *napi,
struct sk_buff *skb, int queue,
- struct ieee80211_sta *sta)
+ struct ieee80211_sta *sta,
+ bool csi)
{
- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
-
- if (!(rx_status->flag & RX_FLAG_NO_PSDU) &&
- iwl_mvm_check_pn(mvm, skb, queue, sta)) {
+ if (iwl_mvm_check_pn(mvm, skb, queue, sta))
kfree_skb(skb);
- } else {
- unsigned int radiotap_len = 0;
-
- if (rx_status->flag & RX_FLAG_RADIOTAP_HE)
- radiotap_len += sizeof(struct ieee80211_radiotap_he);
- if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU)
- radiotap_len += sizeof(struct ieee80211_radiotap_he_mu);
- __skb_push(skb, radiotap_len);
+ else
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
- }
}
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
@@ -289,7 +338,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
stats->flag |= RX_FLAG_MMIC_ERROR;
*crypt_len = IEEE80211_TKIP_IV_LEN;
- /* fall through if TTAK OK */
+ /* fall through */
case IWL_RX_MPDU_STATUS_SEC_WEP:
if (!(status & IWL_RX_MPDU_STATUS_ICV_OK))
return -1;
@@ -473,7 +522,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
while ((skb = __skb_dequeue(skb_list))) {
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
reorder_buf->queue,
- sta);
+ sta, false);
reorder_buf->num_stored--;
}
}
@@ -642,7 +691,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_baid_data *baid_data;
struct iwl_mvm_reorder_buffer *buffer;
@@ -666,6 +715,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* This also covers the case of receiving a Block Ack Request
* outside a BA session; we'll pass it to mac80211 and that
* then sends a delBA action frame.
+ * This also covers pure monitor mode, in which case we won't
+ * have any BA sessions.
*/
if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
return false;
@@ -937,6 +988,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
* the TSF/timers are not be transmitted in HE-MU.
*/
u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
+ u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
u8 offs = 0;
rx_status->bw = RATE_INFO_BW_HE_RU;
@@ -979,19 +1031,27 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
- if (he_mu) {
#define CHECK_BW(bw) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
+ RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \
RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
- CHECK_BW(20);
- CHECK_BW(40);
- CHECK_BW(80);
- CHECK_BW(160);
+ CHECK_BW(20);
+ CHECK_BW(40);
+ CHECK_BW(80);
+ CHECK_BW(160);
+
+ if (he_mu)
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
rate_n_flags),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
- }
+ else if (he_type == RATE_MCS_HE_TYPE_TRIG)
+ he->data6 |=
+ cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
+ le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
+ rate_n_flags),
+ IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
}
static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
@@ -1014,16 +1074,16 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
+ he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
+ he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
+ he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
+ he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
/* fall through */
@@ -1033,7 +1093,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
case IWL_RX_PHY_INFO_TYPE_HE_TB:
/* HE common */
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
@@ -1053,9 +1112,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
- IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
- IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
@@ -1076,6 +1132,20 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
switch (phy_data->info_type) {
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
+ case IWL_RX_PHY_INFO_TYPE_HE_MU:
+ case IWL_RX_PHY_INFO_TYPE_HE_SU:
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);
+ he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
+ IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
+ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
+ break;
+ default:
+ /* nothing here */
+ break;
+ }
+
+ switch (phy_data->info_type) {
+ case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
he_mu->flags1 |=
le16_encode_bits(le16_get_bits(phy_data->d4,
IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM),
@@ -1142,30 +1212,22 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
- unsigned int radiotap_len = 0;
he = skb_put_data(skb, &known, sizeof(known));
- radiotap_len += sizeof(known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
- radiotap_len += sizeof(mu_known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
}
- /* temporarily hide the radiotap data */
- __skb_pull(skb, radiotap_len);
-
- if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_SU) {
- /* report the AMPDU-EOF bit on single frames */
- if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
- rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
- if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
- }
+ /* report the AMPDU-EOF bit on single frames */
+ if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
+ rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
+ if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
@@ -1178,9 +1240,7 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
/* toggle is switched whenever new aggregation starts */
- if (toggle_bit != mvm->ampdu_toggle &&
- (he_type == RATE_MCS_HE_TYPE_MU ||
- he_type == RATE_MCS_HE_TYPE_SU)) {
+ if (toggle_bit != mvm->ampdu_toggle) {
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
@@ -1314,6 +1374,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
.d4 = desc->phy_data4,
.info_type = IWL_RX_PHY_INFO_TYPE_NONE,
};
+ bool csi = false;
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
@@ -1412,7 +1473,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
}
/* set the preamble flag if appropriate */
- if (phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
+ if (rate_n_flags & RATE_MCS_CCK_MSK &&
+ phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
@@ -1441,14 +1503,23 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status->ampdu_reference = mvm->ampdu_ref;
- /* toggle is switched whenever new aggregation starts */
+ /*
+ * Toggle is switched whenever new aggregation starts. Make
+ * sure ampdu_reference is never 0 so we can later use it to
+ * see if the frame was really part of an A-MPDU or not.
+ */
if (toggle_bit != mvm->ampdu_toggle) {
mvm->ampdu_ref++;
+ if (mvm->ampdu_ref == 0)
+ mvm->ampdu_ref++;
mvm->ampdu_toggle = toggle_bit;
}
+ rx_status->ampdu_reference = mvm->ampdu_ref;
}
+ if (unlikely(mvm->monitor_on))
+ iwl_mvm_add_rtap_sniffer_config(mvm, skb);
+
rcu_read_lock();
if (desc->status & cpu_to_le16(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
@@ -1602,7 +1673,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb);
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
- iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
+ iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue,
+ sta, csi);
out:
rcu_read_unlock();
}
@@ -1705,15 +1777,24 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
RATE_MCS_STBC_POS;
- rx_status->nss =
- ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
- RATE_VHT_MCS_NSS_POS) + 1;
rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
rx_status->encoding = RX_ENC_VHT;
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
if (rate_n_flags & RATE_MCS_BF_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_BF;
- } else if (!(rate_n_flags & RATE_MCS_HE_MSK)) {
+ /*
+ * take the nss from the rx_vec since the rate_n_flags has
+ * only 2 bits for the nss which gives a max of 4 ss but
+ * there may be up to 8 spatial streams
+ */
+ rx_status->nss =
+ le32_get_bits(desc->rx_vec[0],
+ RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;
+ } else if (rate_n_flags & RATE_MCS_HE_MSK) {
+ rx_status->nss =
+ le32_get_bits(desc->rx_vec[0],
+ RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;
+ } else {
int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
rx_status->band);
@@ -1726,7 +1807,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status->rate_idx = rate;
}
- iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
+ ieee80211_rx_napi(mvm->hw, sta, skb, napi);
out:
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 86d598d5b68f..78694bc38e76 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1580,6 +1580,11 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
* scheduled scan before starting a normal scan.
*/
+ /* FW supports only a single periodic scan */
+ if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) &&
+ mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT))
+ return -EBUSY;
+
if (iwl_mvm_num_scans(mvm) < mvm->max_scans)
return 0;
@@ -1616,10 +1621,10 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED,
true);
-
- /* fall through, something is wrong if no scan was
- * running but we ran out of scans.
+ /* Something is wrong if no scan was running but we
+ * ran out of scans.
*/
+ /* fall through */
default:
WARN_ON(1);
break;
@@ -1976,9 +1981,8 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
return ret;
}
- ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
-
- return ret;
+ return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done,
+ 1 * HZ);
}
int iwl_mvm_scan_size(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index d1d76bb9a750..9da0dae78510 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* 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
@@ -28,6 +29,7 @@
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,7 +66,7 @@ struct iwl_mvm_active_iface_iterator_data {
struct ieee80211_vif *ignore_vif;
u8 sta_vif_ap_sta_id;
enum iwl_sf_state sta_vif_state;
- int num_active_macs;
+ u32 num_active_macs;
};
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index e28009832da0..498c315291cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -314,7 +314,6 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
struct iwl_mvm_sta *mvmsta;
u32 status;
u8 sta_id;
- int ret;
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
return -EINVAL;
@@ -349,31 +348,21 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
/* Notify FW of queue removal from the STA queues */
status = ADD_STA_SUCCESS;
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
- iwl_mvm_add_sta_cmd_size(mvm),
- &cmd, &status);
-
- return ret;
+ return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
+ iwl_mvm_add_sta_cmd_size(mvm),
+ &cmd, &status);
}
-static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue,
- int mac80211_queue, u8 tid, u8 flags)
+static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int queue, u8 tid, u8 flags)
{
struct iwl_scd_txq_cfg_cmd cmd = {
.scd_queue = queue,
.action = SCD_CFG_DISABLE_QUEUE,
};
- bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE;
int ret;
- if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES))
- return -EINVAL;
-
if (iwl_mvm_has_new_tx_api(mvm)) {
- if (remove_mac_queue)
- mvm->hw_queue_to_mac80211[queue] &=
- ~BIT(mac80211_queue);
-
iwl_trans_txq_free(mvm->trans, queue);
return 0;
@@ -384,36 +373,15 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue,
mvm->queue_info[queue].tid_bitmap &= ~BIT(tid);
- /*
- * If there is another TID with the same AC - don't remove the MAC queue
- * from the mapping
- */
- if (tid < IWL_MAX_TID_COUNT) {
- unsigned long tid_bitmap =
- mvm->queue_info[queue].tid_bitmap;
- int ac = tid_to_mac80211_ac[tid];
- int i;
-
- for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) {
- if (tid_to_mac80211_ac[i] == ac)
- remove_mac_queue = false;
- }
- }
-
- if (remove_mac_queue)
- mvm->hw_queue_to_mac80211[queue] &=
- ~BIT(mac80211_queue);
-
cmd.action = mvm->queue_info[queue].tid_bitmap ?
SCD_CFG_ENABLE_QUEUE : SCD_CFG_DISABLE_QUEUE;
if (cmd.action == SCD_CFG_DISABLE_QUEUE)
mvm->queue_info[queue].status = IWL_MVM_QUEUE_FREE;
IWL_DEBUG_TX_QUEUES(mvm,
- "Disabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n",
+ "Disabling TXQ #%d tids=0x%x\n",
queue,
- mvm->queue_info[queue].tid_bitmap,
- mvm->hw_queue_to_mac80211[queue]);
+ mvm->queue_info[queue].tid_bitmap);
/* If the queue is still enabled - nothing left to do in this func */
if (cmd.action == SCD_CFG_ENABLE_QUEUE)
@@ -423,15 +391,19 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue,
cmd.tid = mvm->queue_info[queue].txq_tid;
/* Make sure queue info is correct even though we overwrite it */
- WARN(mvm->queue_info[queue].tid_bitmap ||
- mvm->hw_queue_to_mac80211[queue],
- "TXQ #%d info out-of-sync - mac map=0x%x, tids=0x%x\n",
- queue, mvm->hw_queue_to_mac80211[queue],
- mvm->queue_info[queue].tid_bitmap);
+ WARN(mvm->queue_info[queue].tid_bitmap,
+ "TXQ #%d info out-of-sync - tids=0x%x\n",
+ queue, mvm->queue_info[queue].tid_bitmap);
/* If we are here - the queue is freed and we can zero out these vals */
mvm->queue_info[queue].tid_bitmap = 0;
- mvm->hw_queue_to_mac80211[queue] = 0;
+
+ if (sta) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_tid(sta, tid);
+
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ }
/* Regardless if this is a reserved TXQ for a STA - mark it as false */
mvm->queue_info[queue].reserved = false;
@@ -517,9 +489,14 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
spin_lock_bh(&mvmsta->lock);
/* Unmap MAC queues and TIDs from this queue */
for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_tid(sta, tid);
+
if (mvmsta->tid_data[tid].state == IWL_AGG_ON)
disable_agg_tids |= BIT(tid);
mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
+
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
}
mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
@@ -541,10 +518,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
}
static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
+ struct ieee80211_sta *old_sta,
u8 new_sta_id)
{
struct iwl_mvm_sta *mvmsta;
- u8 txq_curr_ac, sta_id, tid;
+ u8 sta_id, tid;
unsigned long disable_agg_tids = 0;
bool same_sta;
int ret;
@@ -554,7 +532,6 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
return -EINVAL;
- txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
sta_id = mvm->queue_info[queue].ra_sta_id;
tid = mvm->queue_info[queue].txq_tid;
@@ -570,9 +547,7 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
iwl_mvm_invalidate_sta_queue(mvm, queue,
disable_agg_tids, false);
- ret = iwl_mvm_disable_txq(mvm, queue,
- mvmsta->vif->hw_queue[txq_curr_ac],
- tid, 0);
+ ret = iwl_mvm_disable_txq(mvm, old_sta, queue, tid, 0);
if (ret) {
IWL_ERR(mvm,
"Failed to free inactive queue %d (ret=%d)\n",
@@ -662,16 +637,15 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm,
* in such a case, otherwise - if no redirection required - it does nothing,
* unless the %force param is true.
*/
-static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
- int ac, int ssn, unsigned int wdg_timeout,
- bool force)
+static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
+ int ac, int ssn, unsigned int wdg_timeout,
+ bool force, struct iwl_mvm_txq *txq)
{
struct iwl_scd_txq_cfg_cmd cmd = {
.scd_queue = queue,
.action = SCD_CFG_DISABLE_QUEUE,
};
bool shared_queue;
- unsigned long mq;
int ret;
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
@@ -695,14 +669,14 @@ static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[mvm->queue_info[queue].mac80211_ac];
cmd.tid = mvm->queue_info[queue].txq_tid;
- mq = mvm->hw_queue_to_mac80211[queue];
shared_queue = hweight16(mvm->queue_info[queue].tid_bitmap) > 1;
IWL_DEBUG_TX_QUEUES(mvm, "Redirecting TXQ #%d to FIFO #%d\n",
queue, iwl_mvm_ac_to_tx_fifo[ac]);
- /* Stop MAC queues and wait for this queue to empty */
- iwl_mvm_stop_mac_queues(mvm, mq);
+ /* Stop the queue and wait for it to empty */
+ txq->stopped = true;
+
ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
if (ret) {
IWL_ERR(mvm, "Error draining queue %d before reconfig\n",
@@ -743,8 +717,8 @@ static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
iwl_trans_txq_set_shared_mode(mvm->trans, queue, true);
out:
- /* Continue using the MAC queues */
- iwl_mvm_start_mac_queues(mvm, mq);
+ /* Continue using the queue */
+ txq->stopped = false;
return ret;
}
@@ -769,14 +743,15 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,
return -ENOSPC;
}
-static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue,
+static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
u8 sta_id, u8 tid, unsigned int timeout)
{
int queue, size = IWL_DEFAULT_QUEUE_SIZE;
if (tid == IWL_MAX_TID_COUNT) {
tid = IWL_MGMT_TID;
- size = IWL_MGMT_QUEUE_SIZE;
+ size = max_t(u32, IWL_MGMT_QUEUE_SIZE,
+ mvm->trans->cfg->min_txq_size);
}
queue = iwl_trans_txq_alloc(mvm->trans,
cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE),
@@ -792,10 +767,7 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue,
IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n",
queue, sta_id, tid);
- mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue);
- IWL_DEBUG_TX_QUEUES(mvm,
- "Enabling TXQ #%d (mac80211 map:0x%x)\n",
- queue, mvm->hw_queue_to_mac80211[queue]);
+ IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d\n", queue);
return queue;
}
@@ -805,9 +777,10 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
int tid)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_tid(sta, tid);
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false);
- u8 mac_queue = mvmsta->vif->hw_queue[ac];
int queue = -1;
lockdep_assert_held(&mvm->mutex);
@@ -815,11 +788,14 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
IWL_DEBUG_TX_QUEUES(mvm,
"Allocating queue for sta %d on tid %d\n",
mvmsta->sta_id, tid);
- queue = iwl_mvm_tvqm_enable_txq(mvm, mac_queue, mvmsta->sta_id, tid,
- wdg_timeout);
+ queue = iwl_mvm_tvqm_enable_txq(mvm, mvmsta->sta_id, tid, wdg_timeout);
if (queue < 0)
return queue;
+ mvmtxq->txq_id = queue;
+ mvm->tvqm_info[queue].txq_tid = tid;
+ mvm->tvqm_info[queue].sta_id = mvmsta->sta_id;
+
IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue);
spin_lock_bh(&mvmsta->lock);
@@ -829,8 +805,9 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
return 0;
}
-static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue,
- int mac80211_queue, u8 sta_id, u8 tid)
+static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ int queue, u8 sta_id, u8 tid)
{
bool enable_queue = true;
@@ -845,14 +822,6 @@ static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue,
if (mvm->queue_info[queue].tid_bitmap)
enable_queue = false;
- if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) {
- WARN(mac80211_queue >=
- BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]),
- "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n",
- mac80211_queue, queue, sta_id, tid);
- mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue);
- }
-
mvm->queue_info[queue].tid_bitmap |= BIT(tid);
mvm->queue_info[queue].ra_sta_id = sta_id;
@@ -866,16 +835,22 @@ static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue,
mvm->queue_info[queue].txq_tid = tid;
}
+ if (sta) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_tid(sta, tid);
+
+ mvmtxq->txq_id = queue;
+ }
+
IWL_DEBUG_TX_QUEUES(mvm,
- "Enabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n",
- queue, mvm->queue_info[queue].tid_bitmap,
- mvm->hw_queue_to_mac80211[queue]);
+ "Enabling TXQ #%d tids=0x%x\n",
+ queue, mvm->queue_info[queue].tid_bitmap);
return enable_queue;
}
-static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue,
- int mac80211_queue, u16 ssn,
+static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int queue, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout)
{
@@ -895,8 +870,7 @@ static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue,
return false;
/* Send the enabling command if we need to */
- if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue,
- cfg->sta_id, cfg->tid))
+ if (!iwl_mvm_update_txq_mapping(mvm, sta, queue, cfg->sta_id, cfg->tid))
return false;
inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn,
@@ -989,9 +963,10 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number);
- ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid,
- tid_to_mac80211_ac[tid], ssn,
- wdg_timeout, true);
+ ret = iwl_mvm_redirect_queue(mvm, queue, tid,
+ tid_to_mac80211_ac[tid], ssn,
+ wdg_timeout, true,
+ iwl_mvm_txq_from_tid(sta, tid));
if (ret) {
IWL_ERR(mvm, "Failed to redirect TXQ %d\n", queue);
return;
@@ -1068,11 +1043,9 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm,
* Remove the ones that did.
*/
for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
- int mac_queue = mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]];
u16 tid_bitmap;
mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
- mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac_queue);
mvm->queue_info[queue].tid_bitmap &= ~BIT(tid);
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
@@ -1105,10 +1078,6 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm,
* sure all TIDs have existing corresponding mac queues enabled
*/
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
- for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
- mvm->hw_queue_to_mac80211[queue] |=
- BIT(mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]);
- }
/* If the queue is marked as shared - "unshare" it */
if (hweight16(mvm->queue_info[queue].tid_bitmap) == 1 &&
@@ -1136,6 +1105,7 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
unsigned long unshare_queues = 0;
unsigned long changetid_queues = 0;
int i, ret, free_queue = -ENOSPC;
+ struct ieee80211_sta *queue_owner = NULL;
lockdep_assert_held(&mvm->mutex);
@@ -1201,13 +1171,14 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
inactive_tid_bitmap,
&unshare_queues,
&changetid_queues);
- if (ret >= 0 && free_queue < 0)
+ if (ret >= 0 && free_queue < 0) {
+ queue_owner = sta;
free_queue = ret;
+ }
/* only unlock sta lock - we still need the queue info lock */
spin_unlock_bh(&mvmsta->lock);
}
- rcu_read_unlock();
/* Reconfigure queues requiring reconfiguation */
for_each_set_bit(i, &unshare_queues, IWL_MAX_HW_QUEUES)
@@ -1216,18 +1187,21 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
iwl_mvm_change_queue_tid(mvm, i);
if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) {
- ret = iwl_mvm_free_inactive_queue(mvm, free_queue,
+ ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner,
alloc_for_sta);
- if (ret)
+ if (ret) {
+ rcu_read_unlock();
return ret;
+ }
}
+ rcu_read_unlock();
+
return free_queue;
}
static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta, u8 ac, int tid,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_sta *sta, u8 ac, int tid)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_trans_txq_scd_cfg cfg = {
@@ -1238,7 +1212,6 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
};
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false);
- u8 mac_queue = mvmsta->vif->hw_queue[ac];
int queue = -1;
unsigned long disable_agg_tids = 0;
enum iwl_mvm_agg_state queue_state;
@@ -1257,12 +1230,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number);
spin_unlock_bh(&mvmsta->lock);
- /*
- * Non-QoS, QoS NDP and MGMT frames should go to a MGMT queue, if one
- * exists
- */
- if (!ieee80211_is_data_qos(hdr->frame_control) ||
- ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+ if (tid == IWL_MAX_TID_COUNT) {
queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
IWL_MVM_DQA_MIN_MGMT_QUEUE,
IWL_MVM_DQA_MAX_MGMT_QUEUE);
@@ -1341,8 +1309,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
}
- inc_ssn = iwl_mvm_enable_txq(mvm, queue, mac_queue,
- ssn, &cfg, wdg_timeout);
+ inc_ssn = iwl_mvm_enable_txq(mvm, sta, queue, ssn, &cfg, wdg_timeout);
/*
* Mark queue as shared in transport if shared
@@ -1384,8 +1351,9 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
} else {
/* Redirect queue, if needed */
- ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, ac, ssn,
- wdg_timeout, false);
+ ret = iwl_mvm_redirect_queue(mvm, queue, tid, ac, ssn,
+ wdg_timeout, false,
+ iwl_mvm_txq_from_tid(sta, tid));
if (ret)
goto out_err;
}
@@ -1393,7 +1361,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
return 0;
out_err:
- iwl_mvm_disable_txq(mvm, queue, mac_queue, tid, 0);
+ iwl_mvm_disable_txq(mvm, sta, queue, tid, 0);
return ret;
}
@@ -1406,87 +1374,32 @@ static inline u8 iwl_mvm_tid_to_ac_queue(int tid)
return tid_to_mac80211_ac[tid];
}
-static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta, int tid)
-{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
- struct sk_buff *skb;
- struct ieee80211_hdr *hdr;
- struct sk_buff_head deferred_tx;
- u8 mac_queue;
- bool no_queue = false; /* Marks if there is a problem with the queue */
- u8 ac;
-
- lockdep_assert_held(&mvm->mutex);
-
- skb = skb_peek(&tid_data->deferred_tx_frames);
- if (!skb)
- return;
- hdr = (void *)skb->data;
-
- ac = iwl_mvm_tid_to_ac_queue(tid);
- mac_queue = IEEE80211_SKB_CB(skb)->hw_queue;
-
- if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE &&
- iwl_mvm_sta_alloc_queue(mvm, sta, ac, tid, hdr)) {
- IWL_ERR(mvm,
- "Can't alloc TXQ for sta %d tid %d - dropping frame\n",
- mvmsta->sta_id, tid);
-
- /*
- * Mark queue as problematic so later the deferred traffic is
- * freed, as we can do nothing with it
- */
- no_queue = true;
- }
-
- __skb_queue_head_init(&deferred_tx);
-
- /* Disable bottom-halves when entering TX path */
- local_bh_disable();
- spin_lock(&mvmsta->lock);
- skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx);
- mvmsta->deferred_traffic_tid_map &= ~BIT(tid);
- spin_unlock(&mvmsta->lock);
-
- while ((skb = __skb_dequeue(&deferred_tx)))
- if (no_queue || iwl_mvm_tx_skb(mvm, skb, sta))
- ieee80211_free_txskb(mvm->hw, skb);
- local_bh_enable();
-
- /* Wake queue */
- iwl_mvm_start_mac_queues(mvm, BIT(mac_queue));
-}
-
void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
{
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,
add_stream_wk);
- struct ieee80211_sta *sta;
- struct iwl_mvm_sta *mvmsta;
- unsigned long deferred_tid_traffic;
- int sta_id, tid;
mutex_lock(&mvm->mutex);
iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA);
- /* Go over all stations with deferred traffic */
- for_each_set_bit(sta_id, mvm->sta_deferred_frames,
- IWL_MVM_STATION_COUNT) {
- clear_bit(sta_id, mvm->sta_deferred_frames);
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(sta))
- continue;
+ while (!list_empty(&mvm->add_stream_txqs)) {
+ struct iwl_mvm_txq *mvmtxq;
+ struct ieee80211_txq *txq;
+ u8 tid;
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- deferred_tid_traffic = mvmsta->deferred_traffic_tid_map;
+ mvmtxq = list_first_entry(&mvm->add_stream_txqs,
+ struct iwl_mvm_txq, list);
+
+ txq = container_of((void *)mvmtxq, struct ieee80211_txq,
+ drv_priv);
+ tid = txq->tid;
+ if (tid == IEEE80211_NUM_TIDS)
+ tid = IWL_MAX_TID_COUNT;
- for_each_set_bit(tid, &deferred_tid_traffic,
- IWL_MAX_TID_COUNT + 1)
- iwl_mvm_tx_deferred_stream(mvm, sta, tid);
+ iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid);
+ list_del_init(&mvmtxq->list);
+ iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
}
mutex_unlock(&mvm->mutex);
@@ -1542,10 +1455,11 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
* Note that re-enabling aggregations isn't done in this function.
*/
static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta)
+ struct ieee80211_sta *sta)
{
- unsigned int wdg_timeout =
- iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false);
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ unsigned int wdg =
+ iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false);
int i;
struct iwl_trans_txq_scd_cfg cfg = {
.sta_id = mvm_sta->sta_id,
@@ -1561,23 +1475,18 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
struct iwl_mvm_tid_data *tid_data = &mvm_sta->tid_data[i];
int txq_id = tid_data->txq_id;
int ac;
- u8 mac_queue;
if (txq_id == IWL_MVM_INVALID_QUEUE)
continue;
- skb_queue_head_init(&tid_data->deferred_tx_frames);
-
ac = tid_to_mac80211_ac[i];
- mac_queue = mvm_sta->vif->hw_queue[ac];
if (iwl_mvm_has_new_tx_api(mvm)) {
IWL_DEBUG_TX_QUEUES(mvm,
"Re-mapping sta %d tid %d\n",
mvm_sta->sta_id, i);
- txq_id = iwl_mvm_tvqm_enable_txq(mvm, mac_queue,
- mvm_sta->sta_id,
- i, wdg_timeout);
+ txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id,
+ i, wdg);
tid_data->txq_id = txq_id;
/*
@@ -1600,8 +1509,7 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
"Re-mapping sta %d tid %d to queue %d\n",
mvm_sta->sta_id, i, txq_id);
- iwl_mvm_enable_txq(mvm, txq_id, mac_queue, seq, &cfg,
- wdg_timeout);
+ iwl_mvm_enable_txq(mvm, sta, txq_id, seq, &cfg, wdg);
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY;
}
}
@@ -1691,7 +1599,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
if (ret)
goto err;
- iwl_mvm_realloc_queues_after_restart(mvm, mvm_sta);
+ iwl_mvm_realloc_queues_after_restart(mvm, sta);
sta_update = true;
sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES;
goto update_fw;
@@ -1724,9 +1632,17 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
* frames until the queue is allocated
*/
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
- skb_queue_head_init(&mvm_sta->tid_data[i].deferred_tx_frames);
}
- mvm_sta->deferred_traffic_tid_map = 0;
+
+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_mac80211(sta->txq[i]);
+
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ INIT_LIST_HEAD(&mvmtxq->list);
+ atomic_set(&mvmtxq->tx_request, 0);
+ }
+
mvm_sta->agg_tids = 0;
if (iwl_mvm_has_new_rx_api(mvm) &&
@@ -1861,9 +1777,9 @@ static int iwl_mvm_rm_sta_common(struct iwl_mvm *mvm, u8 sta_id)
static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct iwl_mvm_sta *mvm_sta)
+ struct ieee80211_sta *sta)
{
- int ac;
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int i;
lockdep_assert_held(&mvm->mutex);
@@ -1872,11 +1788,17 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
continue;
- ac = iwl_mvm_tid_to_ac_queue(i);
- iwl_mvm_disable_txq(mvm, mvm_sta->tid_data[i].txq_id,
- vif->hw_queue[ac], i, 0);
+ iwl_mvm_disable_txq(mvm, sta, mvm_sta->tid_data[i].txq_id, i,
+ 0);
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
}
+
+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
+ struct iwl_mvm_txq *mvmtxq =
+ iwl_mvm_txq_from_mac80211(sta->txq[i]);
+
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ }
}
int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
@@ -1938,7 +1860,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
- iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
+ iwl_mvm_disable_sta_queues(mvm, vif, sta);
/* If there is a TXQ still marked as reserved - free it */
if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
@@ -2044,7 +1966,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
if (iwl_mvm_has_new_tx_api(mvm)) {
int tvqm_queue =
- iwl_mvm_tvqm_enable_txq(mvm, *queue, sta_id,
+ iwl_mvm_tvqm_enable_txq(mvm, sta_id,
IWL_MAX_TID_COUNT,
wdg_timeout);
*queue = tvqm_queue;
@@ -2057,7 +1979,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
.frame_limit = IWL_FRAME_LIMIT,
};
- iwl_mvm_enable_txq(mvm, *queue, *queue, 0, &cfg, wdg_timeout);
+ iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout);
}
}
@@ -2135,8 +2057,7 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
- iwl_mvm_disable_txq(mvm, mvm->snif_queue, mvm->snif_queue,
- IWL_MAX_TID_COUNT, 0);
+ iwl_mvm_disable_txq(mvm, NULL, mvm->snif_queue, IWL_MAX_TID_COUNT, 0);
ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id);
if (ret)
IWL_WARN(mvm, "Failed sending remove station\n");
@@ -2195,8 +2116,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
bsta->tfd_queue_msk |= BIT(queue);
- iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0,
- &cfg, wdg_timeout);
+ iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout);
}
if (vif->type == NL80211_IFTYPE_ADHOC)
@@ -2215,8 +2135,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* to firmware so enable queue here - after the station was added
*/
if (iwl_mvm_has_new_tx_api(mvm)) {
- queue = iwl_mvm_tvqm_enable_txq(mvm, vif->hw_queue[0],
- bsta->sta_id,
+ queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id,
IWL_MAX_TID_COUNT,
wdg_timeout);
@@ -2254,7 +2173,7 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
return;
}
- iwl_mvm_disable_txq(mvm, queue, vif->hw_queue[0], IWL_MAX_TID_COUNT, 0);
+ iwl_mvm_disable_txq(mvm, NULL, queue, IWL_MAX_TID_COUNT, 0);
if (iwl_mvm_has_new_tx_api(mvm))
return;
@@ -2377,10 +2296,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* 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;
- }
+ if (vif->type == NL80211_IFTYPE_ADHOC)
+ mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
/*
* While in previous FWs we had to exclude cab queue from TFD queue
@@ -2388,9 +2305,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
*/
if (!iwl_mvm_has_new_tx_api(mvm) &&
fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) {
- iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
- &cfg, timeout);
- msta->tfd_queue_msk |= BIT(vif->cab_queue);
+ iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg,
+ timeout);
+ msta->tfd_queue_msk |= BIT(mvmvif->cab_queue);
}
ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
mvmvif->id, mvmvif->color);
@@ -2407,24 +2324,25 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* tfd_queue_mask.
*/
if (iwl_mvm_has_new_tx_api(mvm)) {
- int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue,
- msta->sta_id,
+ int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id,
0,
timeout);
mvmvif->cab_queue = queue;
} else if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE))
- iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
- &cfg, timeout);
+ iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg,
+ timeout);
if (mvmvif->ap_wep_key) {
u8 key_offset = iwl_mvm_set_fw_key_idx(mvm);
+ __set_bit(key_offset, mvm->fw_key_table);
+
if (key_offset == STA_KEY_IDX_INVALID)
return -ENOSPC;
ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id,
- mvmvif->ap_wep_key, 1, 0, NULL, 0,
+ mvmvif->ap_wep_key, true, 0, NULL, 0,
key_offset, 0);
if (ret)
return ret;
@@ -2433,6 +2351,59 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return 0;
}
+static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
+ struct ieee80211_key_conf *keyconf,
+ bool mcast)
+{
+ union {
+ struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
+ struct iwl_mvm_add_sta_key_cmd cmd;
+ } u = {};
+ bool new_api = fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
+ __le16 key_flags;
+ int ret, size;
+ u32 status;
+
+ /* This is a valid situation for GTK removal */
+ if (sta_id == IWL_MVM_INVALID_STA)
+ return 0;
+
+ key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
+ STA_KEY_FLG_KEYID_MSK);
+ key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
+ key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
+
+ if (mcast)
+ key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
+
+ /*
+ * The fields assigned here are in the same location at the start
+ * of the command, so we can do this union trick.
+ */
+ u.cmd.common.key_flags = key_flags;
+ u.cmd.common.key_offset = keyconf->hw_key_idx;
+ u.cmd.common.sta_id = sta_id;
+
+ size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
+
+ status = ADD_STA_SUCCESS;
+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
+ &status);
+
+ switch (status) {
+ case ADD_STA_SUCCESS:
+ IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
+ break;
+ }
+
+ return ret;
+}
+
/*
* Send the FW a request to remove the station from it's internal data
* structures, and in addition remove it from the local data structure.
@@ -2446,8 +2417,29 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
- iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue,
- 0, 0);
+ iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0);
+
+ if (mvmvif->ap_wep_key) {
+ int i;
+
+ if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx,
+ mvm->fw_key_table)) {
+ IWL_ERR(mvm, "offset %d not used in fw key table.\n",
+ mvmvif->ap_wep_key->hw_key_idx);
+ return -ENOENT;
+ }
+
+ /* track which key was deleted last */
+ for (i = 0; i < STA_KEY_MAX_NUM; i++) {
+ if (mvm->fw_key_deleted[i] < U8_MAX)
+ mvm->fw_key_deleted[i]++;
+ }
+ mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0;
+ ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id,
+ mvmvif->ap_wep_key, true);
+ if (ret)
+ return ret;
+ }
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
if (ret)
@@ -2781,7 +2773,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_tid_data *tid_data;
u16 normalized_ssn;
- int txq_id;
+ u16 txq_id;
int ret;
if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
@@ -2823,17 +2815,24 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*/
txq_id = mvmsta->tid_data[tid].txq_id;
if (txq_id == IWL_MVM_INVALID_QUEUE) {
- txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
- IWL_MVM_DQA_MIN_DATA_QUEUE,
- IWL_MVM_DQA_MAX_DATA_QUEUE);
- if (txq_id < 0) {
- ret = txq_id;
+ ret = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
+ IWL_MVM_DQA_MIN_DATA_QUEUE,
+ IWL_MVM_DQA_MAX_DATA_QUEUE);
+ if (ret < 0) {
IWL_ERR(mvm, "Failed to allocate agg queue\n");
goto out;
}
+ txq_id = ret;
+
/* TXQ hasn't yet been enabled, so mark it only as reserved */
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED;
+ } else if (WARN_ON(txq_id >= IWL_MAX_HW_QUEUES)) {
+ ret = -ENXIO;
+ IWL_ERR(mvm, "tid_id %d out of range (0, %d)!\n",
+ tid, IWL_MAX_HW_QUEUES - 1);
+ goto out;
+
} else if (unlikely(mvm->queue_info[txq_id].status ==
IWL_MVM_QUEUE_SHARED)) {
ret = -ENXIO;
@@ -2976,8 +2975,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
if (alloc_queue)
- iwl_mvm_enable_txq(mvm, queue,
- vif->hw_queue[tid_to_mac80211_ac[tid]], ssn,
+ iwl_mvm_enable_txq(mvm, sta, queue, ssn,
&cfg, wdg_timeout);
/* Send ADD_STA command to enable aggs only if the queue isn't shared */
@@ -3474,59 +3472,6 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
return ret;
}
-static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
- struct ieee80211_key_conf *keyconf,
- bool mcast)
-{
- union {
- struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
- struct iwl_mvm_add_sta_key_cmd cmd;
- } u = {};
- bool new_api = fw_has_api(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
- __le16 key_flags;
- int ret, size;
- u32 status;
-
- /* This is a valid situation for GTK removal */
- if (sta_id == IWL_MVM_INVALID_STA)
- return 0;
-
- key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
- STA_KEY_FLG_KEYID_MSK);
- key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
- key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
-
- if (mcast)
- key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
-
- /*
- * The fields assigned here are in the same location at the start
- * of the command, so we can do this union trick.
- */
- u.cmd.common.key_flags = key_flags;
- u.cmd.common.key_offset = keyconf->hw_key_idx;
- u.cmd.common.sta_id = sta_id;
-
- size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
-
- status = ADD_STA_SUCCESS;
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
- &status);
-
- switch (status) {
- case ADD_STA_SUCCESS:
- IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
- break;
- default:
- ret = -EIO;
- IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
- break;
- }
-
- return ret;
-}
-
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index d52cd888f77d..79700c7310a1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -297,7 +297,6 @@ enum iwl_mvm_agg_state {
/**
* struct iwl_mvm_tid_data - holds the states for each RA / TID
- * @deferred_tx_frames: deferred TX frames for this RA/TID
* @seq_number: the next WiFi sequence number to use
* @next_reclaimed: the WiFi sequence number of the next packet to be acked.
* This is basically (last acked packet++).
@@ -318,7 +317,6 @@ enum iwl_mvm_agg_state {
* tpt_meas_start
*/
struct iwl_mvm_tid_data {
- struct sk_buff_head deferred_tx_frames;
u16 seq_number;
u16 next_reclaimed;
/* The rest is Tx AGG related */
@@ -396,6 +394,7 @@ struct iwl_mvm_rxq_dup_data {
* the BA window. To be used for UAPSD only.
* @ptk_pn: per-queue PTK PN data structures
* @dup_data: per queue duplicate packet detection data
+ * @wep_key: used in AP mode. Is a duplicate of the WEP key.
* @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID
* @tx_ant: the index of the antenna to use for data tx to this station. Only
* used during connection establishment (e.g. for the 4 way handshake
@@ -427,7 +426,7 @@ struct iwl_mvm_sta {
struct iwl_mvm_key_pn __rcu *ptk_pn[4];
struct iwl_mvm_rxq_dup_data *dup_data;
- u16 deferred_traffic_tid_map;
+ struct ieee80211_key_conf *wep_key;
u8 reserved_queue;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index e02f4eb20359..859aa5a4e6b5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -399,6 +399,9 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
struct iwl_tdls_channel_switch_cmd cmd = {0};
+ struct iwl_tdls_channel_switch_cmd_tail *tail =
+ iwl_mvm_chan_info_cmd_tail(mvm, &cmd.ci);
+ u16 len = sizeof(cmd) - iwl_mvm_chan_info_padding(mvm);
int ret;
lockdep_assert_held(&mvm->mutex);
@@ -414,9 +417,9 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
}
cmd.switch_type = type;
- cmd.timing.frame_timestamp = cpu_to_le32(timestamp);
- cmd.timing.switch_time = cpu_to_le32(switch_time);
- cmd.timing.switch_timeout = cpu_to_le32(switch_timeout);
+ tail->timing.frame_timestamp = cpu_to_le32(timestamp);
+ tail->timing.switch_time = cpu_to_le32(switch_time);
+ tail->timing.switch_timeout = cpu_to_le32(switch_timeout);
rcu_read_lock();
sta = ieee80211_find_sta(vif, peer);
@@ -448,21 +451,16 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
}
}
- if (chandef) {
- cmd.ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ?
- PHY_BAND_24 : PHY_BAND_5);
- cmd.ci.channel = chandef->chan->hw_value;
- cmd.ci.width = iwl_mvm_get_channel_width(chandef);
- cmd.ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
- }
+ if (chandef)
+ iwl_mvm_set_chan_info_chandef(mvm, &cmd.ci, chandef);
/* keep quota calculation simple for now - 50% of DTIM for TDLS */
- cmd.timing.max_offchan_duration =
+ tail->timing.max_offchan_duration =
cpu_to_le32(TU_TO_US(vif->bss_conf.dtim_period *
vif->bss_conf.beacon_int) / 2);
/* Switch time is the first element in the switch-timing IE. */
- cmd.frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2);
+ tail->frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2);
info = IEEE80211_SKB_CB(skb);
hdr = (void *)skb->data;
@@ -472,20 +470,19 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
ret = -EINVAL;
goto out;
}
- iwl_mvm_set_tx_cmd_ccmp(info, &cmd.frame.tx_cmd);
+ iwl_mvm_set_tx_cmd_ccmp(info, &tail->frame.tx_cmd);
}
- iwl_mvm_set_tx_cmd(mvm, skb, &cmd.frame.tx_cmd, info,
+ iwl_mvm_set_tx_cmd(mvm, skb, &tail->frame.tx_cmd, info,
mvmsta->sta_id);
- iwl_mvm_set_tx_cmd_rate(mvm, &cmd.frame.tx_cmd, info, sta,
+ iwl_mvm_set_tx_cmd_rate(mvm, &tail->frame.tx_cmd, info, sta,
hdr->frame_control);
rcu_read_unlock();
- memcpy(cmd.frame.data, skb->data, skb->len);
+ memcpy(tail->frame.data, skb->data, skb->len);
- ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0,
- sizeof(cmd), &cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0, len, &cmd);
if (ret) {
IWL_ERR(mvm, "Failed to send TDLS_CHANNEL_SWITCH cmd: %d\n",
ret);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index e1a6f4e22253..9693fa4cdc39 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -85,7 +85,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
{
lockdep_assert_held(&mvm->time_event_lock);
- if (!te_data->vif)
+ if (!te_data || !te_data->vif)
return;
list_del(&te_data->list);
@@ -334,6 +334,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
switch (te_data->vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
ieee80211_remain_on_channel_expired(mvm->hw);
+ set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
iwl_mvm_roc_finished(mvm);
break;
case NL80211_IFTYPE_STATION:
@@ -686,6 +687,8 @@ static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm,
struct iwl_mvm_time_event_data *te_data)
{
struct iwl_hs20_roc_req aux_cmd = {};
+ u16 len = sizeof(aux_cmd) - iwl_mvm_chan_info_padding(mvm);
+
u32 uid;
int ret;
@@ -699,7 +702,7 @@ static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm,
IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n",
le32_to_cpu(aux_cmd.event_unique_id));
ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0,
- sizeof(aux_cmd), &aux_cmd);
+ len, &aux_cmd);
if (WARN_ON(ret))
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
deleted file mode 100644
index 01e0a999063b..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2015 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- * Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2015 Intel Deutschland GmbH
- * All rights reserved.
- *
- * 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 Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 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
- * OWNER 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 "mvm.h"
-#include "fw/api/tof.h"
-
-#define IWL_MVM_TOF_RANGE_REQ_MAX_ID 256
-
-void iwl_mvm_tof_init(struct iwl_mvm *mvm)
-{
- struct iwl_mvm_tof_data *tof_data = &mvm->tof_data;
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return;
-
- memset(tof_data, 0, sizeof(*tof_data));
-
- tof_data->tof_cfg.sub_grp_cmd_id = cpu_to_le32(TOF_CONFIG_CMD);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (IWL_MVM_TOF_IS_RESPONDER) {
- tof_data->responder_cfg.sub_grp_cmd_id =
- cpu_to_le32(TOF_RESPONDER_CONFIG_CMD);
- tof_data->responder_cfg.sta_id = IWL_MVM_INVALID_STA;
- }
-#endif
-
- tof_data->range_req.sub_grp_cmd_id = cpu_to_le32(TOF_RANGE_REQ_CMD);
- tof_data->range_req.req_timeout = 1;
- tof_data->range_req.initiator = 1;
- tof_data->range_req.report_policy = 3;
-
- tof_data->range_req_ext.sub_grp_cmd_id =
- cpu_to_le32(TOF_RANGE_REQ_EXT_CMD);
-
- mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
- mvm->init_status |= IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
-}
-
-void iwl_mvm_tof_clean(struct iwl_mvm *mvm)
-{
- struct iwl_mvm_tof_data *tof_data = &mvm->tof_data;
-
- if (!fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_TOF_SUPPORT) ||
- !(mvm->init_status & IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE))
- return;
-
- memset(tof_data, 0, sizeof(*tof_data));
- mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
- mvm->init_status &= ~IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
-}
-
-static void iwl_tof_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- bool *enabled = _data;
-
- /* non bss vif exists */
- if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION)
- *enabled = false;
-}
-
-int iwl_mvm_tof_config_cmd(struct iwl_mvm *mvm)
-{
- struct iwl_tof_config_cmd *cmd = &mvm->tof_data.tof_cfg;
- bool enabled;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return -EINVAL;
-
- ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_tof_iterator, &enabled);
- if (!enabled) {
- IWL_DEBUG_INFO(mvm, "ToF is not supported (non bss vif)\n");
- return -EINVAL;
- }
-
- mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
- return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD,
- IWL_ALWAYS_LONG_GROUP, 0),
- 0, sizeof(*cmd), cmd);
-}
-
-int iwl_mvm_tof_range_abort_cmd(struct iwl_mvm *mvm, u8 id)
-{
- struct iwl_tof_range_abort_cmd cmd = {
- .sub_grp_cmd_id = cpu_to_le32(TOF_RANGE_ABORT_CMD),
- .request_id = id,
- };
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return -EINVAL;
-
- if (id != mvm->tof_data.active_range_request) {
- IWL_ERR(mvm, "Invalid range request id %d (active %d)\n",
- id, mvm->tof_data.active_range_request);
- return -EINVAL;
- }
-
- /* after abort is sent there's no active request anymore */
- mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
-
- return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD,
- IWL_ALWAYS_LONG_GROUP, 0),
- 0, sizeof(cmd), &cmd);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_tof_responder_config_cmd *cmd = &mvm->tof_data.responder_cfg;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return -EINVAL;
-
- if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
- !mvmvif->ap_ibss_active) {
- IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
- return -EIO;
- }
-
- cmd->sta_id = mvmvif->bcast_sta.sta_id;
- memcpy(cmd->bssid, vif->addr, ETH_ALEN);
- return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD,
- IWL_ALWAYS_LONG_GROUP, 0),
- 0, sizeof(*cmd), cmd);
-}
-#endif
-
-int iwl_mvm_tof_range_request_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_host_cmd cmd = {
- .id = iwl_cmd_id(TOF_CMD, IWL_ALWAYS_LONG_GROUP, 0),
- .len = { sizeof(mvm->tof_data.range_req), },
- /* no copy because of the command size */
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- };
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return -EINVAL;
-
- if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) {
- IWL_ERR(mvm, "Cannot send range request, not STA mode\n");
- return -EIO;
- }
-
- /* nesting of range requests is not supported in FW */
- if (mvm->tof_data.active_range_request !=
- IWL_MVM_TOF_RANGE_REQ_MAX_ID) {
- IWL_ERR(mvm, "Cannot send range req, already active req %d\n",
- mvm->tof_data.active_range_request);
- return -EIO;
- }
-
- mvm->tof_data.active_range_request = mvm->tof_data.range_req.request_id;
-
- cmd.data[0] = &mvm->tof_data.range_req;
- return iwl_mvm_send_cmd(mvm, &cmd);
-}
-
-int iwl_mvm_tof_range_request_ext_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- lockdep_assert_held(&mvm->mutex);
-
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
- return -EINVAL;
-
- if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) {
- IWL_ERR(mvm, "Cannot send ext range req, not in STA mode\n");
- return -EIO;
- }
-
- return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD,
- IWL_ALWAYS_LONG_GROUP, 0),
- 0, sizeof(mvm->tof_data.range_req_ext),
- &mvm->tof_data.range_req_ext);
-}
-
-static int iwl_mvm_tof_range_resp(struct iwl_mvm *mvm, void *data)
-{
- struct iwl_tof_range_rsp_ntfy *resp = (void *)data;
-
- if (resp->request_id != mvm->tof_data.active_range_request) {
- IWL_ERR(mvm, "Request id mismatch, got %d, active %d\n",
- resp->request_id, mvm->tof_data.active_range_request);
- return -EIO;
- }
-
- memcpy(&mvm->tof_data.range_resp, resp,
- sizeof(struct iwl_tof_range_rsp_ntfy));
- mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
-
- return 0;
-}
-
-static int iwl_mvm_tof_mcsi_notif(struct iwl_mvm *mvm, void *data)
-{
- struct iwl_tof_mcsi_notif *resp = (struct iwl_tof_mcsi_notif *)data;
-
- IWL_DEBUG_INFO(mvm, "MCSI notification, token %d\n", resp->token);
- return 0;
-}
-
-static int iwl_mvm_tof_nb_report_notif(struct iwl_mvm *mvm, void *data)
-{
- struct iwl_tof_neighbor_report *report =
- (struct iwl_tof_neighbor_report *)data;
-
- IWL_DEBUG_INFO(mvm, "NB report, bssid %pM, token %d, status 0x%x\n",
- report->bssid, report->request_token, report->status);
- return 0;
-}
-
-void iwl_mvm_tof_resp_handler(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_tof_gen_resp_cmd *resp = (void *)pkt->data;
-
- lockdep_assert_held(&mvm->mutex);
-
- switch (le32_to_cpu(resp->sub_grp_cmd_id)) {
- case TOF_RANGE_RESPONSE_NOTIF:
- iwl_mvm_tof_range_resp(mvm, resp->data);
- break;
- case TOF_MCSI_DEBUG_NOTIF:
- iwl_mvm_tof_mcsi_notif(mvm, resp->data);
- break;
- case TOF_NEIGHBOR_REPORT_RSP_NOTIF:
- iwl_mvm_tof_nb_report_notif(mvm, resp->data);
- break;
- default:
- IWL_ERR(mvm, "Unknown sub-group command 0x%x\n",
- resp->sub_grp_cmd_id);
- break;
- }
-}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.h b/drivers/net/wireless/intel/iwlwifi/mvm/tof.h
deleted file mode 100644
index 8138d0606c52..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2015 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- * Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2015 Intel Deutschland GmbH
- * All rights reserved.
- *
- * 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 Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 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
- * OWNER 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 __tof_h__
-#define __tof_h__
-
-#include "fw/api/tof.h"
-
-struct iwl_mvm_tof_data {
- struct iwl_tof_config_cmd tof_cfg;
- struct iwl_tof_range_req_cmd range_req;
- struct iwl_tof_range_req_ext_cmd range_req_ext;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- struct iwl_tof_responder_config_cmd responder_cfg;
-#endif
- struct iwl_tof_range_rsp_ntfy range_resp;
- u8 last_abort_id;
- u16 active_range_request;
-};
-
-void iwl_mvm_tof_init(struct iwl_mvm *mvm);
-void iwl_mvm_tof_clean(struct iwl_mvm *mvm);
-int iwl_mvm_tof_config_cmd(struct iwl_mvm *mvm);
-int iwl_mvm_tof_range_abort_cmd(struct iwl_mvm *mvm, u8 id);
-int iwl_mvm_tof_range_request_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
-void iwl_mvm_tof_resp_handler(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb);
-int iwl_mvm_tof_range_request_ext_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
-#endif
-#endif /* __tof_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 995fe2a6abbb..0c2aabc842f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -209,7 +209,9 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
u16 offload_assist = 0;
u8 ac;
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) ||
+ (ieee80211_is_probe_resp(fc) &&
+ !is_multicast_ether_addr(hdr->addr1)))
tx_flags |= TX_CMD_FLG_ACK;
else
tx_flags &= ~TX_CMD_FLG_ACK;
@@ -278,7 +280,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
}
if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
- !is_multicast_ether_addr(ieee80211_get_DA(hdr)))
+ !is_multicast_ether_addr(hdr->addr1))
tx_flags |= TX_CMD_FLG_PROT_REQUIRE;
if (fw_has_capa(&mvm->fw->ucode_capa,
@@ -533,10 +535,11 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
/*
* For data packets rate info comes from the fw. Only
- * set rate/antenna during connection establishment.
+ * set rate/antenna during connection establishment or in case
+ * no station is given.
*/
- if (sta && (!ieee80211_is_data(hdr->frame_control) ||
- mvmsta->sta_state < IEEE80211_STA_AUTHORIZED)) {
+ if (!sta || !ieee80211_is_data(hdr->frame_control) ||
+ mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
flags |= IWL_TX_FLAGS_CMD_RATE;
rate_n_flags =
iwl_mvm_get_tx_rate_n_flags(mvm, info, sta,
@@ -602,11 +605,12 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
}
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info, __le16 fc)
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr)
{
- struct iwl_mvm_vif *mvmvif;
-
- mvmvif = iwl_mvm_vif_from_mac80211(info->control.vif);
+ struct iwl_mvm_vif *mvmvif =
+ iwl_mvm_vif_from_mac80211(info->control.vif);
+ __le16 fc = hdr->frame_control;
switch (info->control.vif->type) {
case NL80211_IFTYPE_AP:
@@ -625,7 +629,9 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
(!ieee80211_is_bufferable_mmpdu(fc) ||
ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
return mvm->probe_queue;
- if (info->hw_queue == info->control.vif->cab_queue)
+
+ if (!ieee80211_has_order(fc) && !ieee80211_is_probe_req(fc) &&
+ is_multicast_ether_addr(hdr->addr1))
return mvmvif->cab_queue;
WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
@@ -634,8 +640,6 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
case NL80211_IFTYPE_P2P_DEVICE:
if (ieee80211_is_mgmt(fc))
return mvm->p2p_dev_queue;
- if (info->hw_queue == info->control.vif->cab_queue)
- return mvmvif->cab_queue;
WARN_ON_ONCE(1);
return mvm->p2p_dev_queue;
@@ -713,18 +717,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
u8 sta_id;
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
__le16 fc = hdr->frame_control;
+ bool offchannel = IEEE80211_SKB_CB(skb)->flags &
+ IEEE80211_TX_CTL_TX_OFFCHAN;
int queue = -1;
+ if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc))
+ return -1;
+
memcpy(&info, skb->cb, sizeof(info));
if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU))
return -1;
- if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
- (!info.control.vif ||
- info.hw_queue != info.control.vif->cab_queue)))
- return -1;
-
if (info.control.vif) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info.control.vif);
@@ -737,14 +741,12 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
else
sta_id = mvmvif->mcast_sta.sta_id;
- queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
- hdr->frame_control);
-
+ queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
queue = mvm->snif_queue;
sta_id = mvm->snif_sta.sta_id;
} else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
- info.hw_queue == IWL_MVM_OFFCHANNEL_QUEUE) {
+ offchannel) {
/*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets
* that can be used in 2 different types of vifs, P2P &
@@ -758,8 +760,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
}
}
- if (queue < 0)
+ if (queue < 0) {
+ IWL_ERR(mvm, "No queue was found. Dropping TX\n");
return -1;
+ }
if (unlikely(ieee80211_is_probe_resp(fc)))
iwl_mvm_probe_resp_set_noa(mvm, skb);
@@ -781,6 +785,35 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
return 0;
}
+unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta, unsigned int tid)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ enum nl80211_band band = mvmsta->vif->bss_conf.chandef.chan->band;
+ u8 ac = tid_to_mac80211_ac[tid];
+ unsigned int txf;
+ int lmac = IWL_LMAC_24G_INDEX;
+
+ if (iwl_mvm_is_cdb_supported(mvm) &&
+ band == NL80211_BAND_5GHZ)
+ lmac = IWL_LMAC_5G_INDEX;
+
+ /* For HE redirect to trigger based fifos */
+ if (sta->he_cap.has_he && !WARN_ON(!iwl_mvm_has_new_tx_api(mvm)))
+ ac += 4;
+
+ txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, ac);
+
+ /*
+ * Don't send an AMSDU that will be longer than the TXF.
+ * Add a security margin of 256 for the TX command + headers.
+ * We also want to have the start of the next packet inside the
+ * fifo to be able to send bursts.
+ */
+ return min_t(unsigned int, mvmsta->max_amsdu_len,
+ mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
+}
+
#ifdef CONFIG_INET
static int
@@ -850,36 +883,6 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
return 0;
}
-static unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
- unsigned int tid)
-{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- enum nl80211_band band = mvmsta->vif->bss_conf.chandef.chan->band;
- u8 ac = tid_to_mac80211_ac[tid];
- unsigned int txf;
- int lmac = IWL_LMAC_24G_INDEX;
-
- if (iwl_mvm_is_cdb_supported(mvm) &&
- band == NL80211_BAND_5GHZ)
- lmac = IWL_LMAC_5G_INDEX;
-
- /* For HE redirect to trigger based fifos */
- if (sta->he_cap.has_he && !WARN_ON(!iwl_mvm_has_new_tx_api(mvm)))
- ac += 4;
-
- txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, ac);
-
- /*
- * Don't send an AMSDU that will be longer than the TXF.
- * Add a security margin of 256 for the TX command + headers.
- * We also want to have the start of the next packet inside the
- * fifo to be able to send bursts.
- */
- return min_t(unsigned int, mvmsta->max_amsdu_len,
- mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
-}
-
static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
@@ -1002,34 +1005,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
}
#endif
-static void iwl_mvm_tx_add_stream(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta, u8 tid,
- struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- u8 mac_queue = info->hw_queue;
- struct sk_buff_head *deferred_tx_frames;
-
- lockdep_assert_held(&mvm_sta->lock);
-
- mvm_sta->deferred_traffic_tid_map |= BIT(tid);
- set_bit(mvm_sta->sta_id, mvm->sta_deferred_frames);
-
- deferred_tx_frames = &mvm_sta->tid_data[tid].deferred_tx_frames;
-
- skb_queue_tail(deferred_tx_frames, skb);
-
- /*
- * The first deferred frame should've stopped the MAC queues, so we
- * should never get a second deferred frame for the RA/TID.
- * In case of GSO the first packet may have been split, so don't warn.
- */
- if (skb_queue_len(deferred_tx_frames) == 1) {
- iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue));
- schedule_work(&mvm->add_stream_wk);
- }
-}
-
/* Check if there are any timed-out TIDs on a given shared TXQ */
static bool iwl_mvm_txq_should_update(struct iwl_mvm *mvm, int txq_id)
{
@@ -1054,7 +1029,12 @@ static void iwl_mvm_tx_airtime(struct iwl_mvm *mvm,
int airtime)
{
int mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK;
- struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
+ struct iwl_mvm_tcm_mac *mdata;
+
+ if (mac >= NUM_MAC_INDEX_DRIVER)
+ return;
+
+ mdata = &mvm->tcm.data[mac];
if (mvm->tcm.paused)
return;
@@ -1065,14 +1045,21 @@ static void iwl_mvm_tx_airtime(struct iwl_mvm *mvm,
mdata->tx.airtime += airtime;
}
-static void iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvmsta, int tid)
+static int iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvmsta, int tid)
{
u32 ac = tid_to_mac80211_ac[tid];
int mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK;
- struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
+ struct iwl_mvm_tcm_mac *mdata;
+
+ if (mac >= NUM_MAC_INDEX_DRIVER)
+ return -EINVAL;
+
+ mdata = &mvm->tcm.data[mac];
mdata->tx.pkts[ac]++;
+
+ return 0;
}
/*
@@ -1088,7 +1075,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
__le16 fc;
u16 seq_number = 0;
u8 tid = IWL_MAX_TID_COUNT;
- u16 txq_id = info->hw_queue;
+ u16 txq_id;
bool is_ampdu = false;
int hdrlen;
@@ -1096,6 +1083,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
fc = hdr->frame_control;
hdrlen = ieee80211_hdrlen(fc);
+ if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc))
+ return -1;
+
if (WARN_ON_ONCE(!mvmsta))
return -1;
@@ -1125,12 +1115,14 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
*/
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
tid = ieee80211_get_tid(hdr);
- if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
+ if (WARN_ONCE(tid >= IWL_MAX_TID_COUNT, "Invalid TID %d", tid))
goto drop_unlock_sta;
is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU;
- if (WARN_ON_ONCE(is_ampdu &&
- mvmsta->tid_data[tid].state != IWL_AGG_ON))
+ if (WARN_ONCE(is_ampdu &&
+ mvmsta->tid_data[tid].state != IWL_AGG_ON,
+ "Invalid internal agg state %d for TID %d",
+ mvmsta->tid_data[tid].state, tid))
goto drop_unlock_sta;
seq_number = mvmsta->tid_data[tid].seq_number;
@@ -1152,14 +1144,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
- /* Check if TXQ needs to be allocated or re-activated */
- if (unlikely(txq_id == IWL_MVM_INVALID_QUEUE)) {
- iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb);
-
- /*
- * The frame is now deferred, and the worker scheduled
- * will re-allocate it, so we can free it for now.
- */
+ if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) {
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
spin_unlock(&mvmsta->lock);
return 0;
@@ -1199,7 +1184,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
spin_unlock(&mvmsta->lock);
- iwl_mvm_tx_pkt_queued(mvm, mvmsta, tid == IWL_MAX_TID_COUNT ? 0 : tid);
+ if (iwl_mvm_tx_pkt_queued(mvm, mvmsta,
+ tid == IWL_MAX_TID_COUNT ? 0 : tid))
+ goto drop;
return 0;
@@ -1207,6 +1194,7 @@ drop_unlock_sta:
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
spin_unlock(&mvmsta->lock);
drop:
+ IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->sta_id, tid);
return -1;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index d116c6ae18ff..4649327abb45 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -248,7 +248,7 @@ void iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
IWL_ERR(mvm, "FW Error notification: seq 0x%04X service 0x%08X\n",
le16_to_cpu(err_resp->bad_cmd_seq_num),
le32_to_cpu(err_resp->error_service));
- IWL_ERR(mvm, "FW Error notification: timestamp 0x%16llX\n",
+ IWL_ERR(mvm, "FW Error notification: timestamp 0x%016llX\n",
le64_to_cpu(err_resp->timestamp));
}
@@ -294,6 +294,7 @@ static const struct {
{ "SYSASSERT", 0x35 },
{ "UCODE_VERSION_MISMATCH", 0x37 },
{ "BAD_COMMAND", 0x38 },
+ { "BAD_COMMAND", 0x39 },
{ "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
{ "FATAL_ERROR", 0x3D },
{ "NMI_TRM_HW_ERR", 0x46 },
@@ -456,12 +457,17 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
{
struct iwl_trans *trans = mvm->trans;
struct iwl_umac_error_event_table table;
+ u32 base = mvm->trans->umac_error_event_table;
- if (!mvm->support_umac_log)
+ if (!mvm->support_umac_log &&
+ !(mvm->trans->error_event_table_tlv_status &
+ IWL_ERROR_EVENT_TABLE_UMAC))
return;
- iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table,
- sizeof(table));
+ iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
+
+ if (table.valid)
+ mvm->fwrt.dump.umac_err_id = table.error_id;
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
@@ -486,11 +492,11 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref);
}
-static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
+static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
{
struct iwl_trans *trans = mvm->trans;
struct iwl_error_event_table table;
- u32 val;
+ u32 val, base = mvm->trans->lmac_error_event_table[lmac_num];
if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) {
if (!base)
@@ -519,29 +525,15 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
/* reset the device */
iwl_trans_sw_reset(trans);
- /* set INIT_DONE flag */
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
-
- /* and wait for clock stabilization */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
- udelay(2);
-
- err = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (err < 0) {
- IWL_DEBUG_INFO(trans,
- "Failed to reset the card for the dump\n");
+ err = iwl_finish_nic_init(trans);
+ if (err)
return;
- }
}
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
if (table.valid)
- mvm->fwrt.dump.rt_status = table.error_id;
+ mvm->fwrt.dump.lmac_err_id[lmac_num] = table.error_id;
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
@@ -598,10 +590,10 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
return;
}
- iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[0]);
+ iwl_mvm_dump_lmac_error_log(mvm, 0);
- if (mvm->error_event_table[1])
- iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[1]);
+ if (mvm->trans->lmac_error_event_table[1])
+ iwl_mvm_dump_lmac_error_log(mvm, 1);
iwl_mvm_dump_umac_error_log(mvm);
}
@@ -1133,19 +1125,14 @@ static void iwl_mvm_tcm_uapsd_nonagg_detected_wk(struct work_struct *wk)
"AP isn't using AMPDU with uAPSD enabled");
}
-static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac,
- struct ieee80211_vif *vif)
+static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- int *mac_id = data;
if (vif->type != NL80211_IFTYPE_STATION)
return;
- if (mvmvif->id != *mac_id)
- return;
-
if (!vif->bss_conf.assoc)
return;
@@ -1155,10 +1142,10 @@ static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac,
!mvmvif->queue_params[IEEE80211_AC_BK].uapsd)
return;
- if (mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected)
+ if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected)
return;
- mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected = true;
+ mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true;
IWL_INFO(mvm,
"detected AP should do aggregation but isn't, likely due to U-APSD\n");
schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk, 15 * HZ);
@@ -1171,6 +1158,7 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
u64 bytes = mvm->tcm.data[mac].uapsd_nonagg_detect.rx_bytes;
u64 tpt;
unsigned long rate;
+ struct ieee80211_vif *vif;
rate = ewma_rate_read(&mvm->tcm.data[mac].uapsd_nonagg_detect.rate);
@@ -1199,9 +1187,11 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
return;
}
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_uapsd_agg_disconnect_iter, &mac);
+ rcu_read_lock();
+ vif = rcu_dereference(mvm->vif_id_to_mac[mac]);
+ if (vif)
+ iwl_mvm_uapsd_agg_disconnect(mvm, vif);
+ rcu_read_unlock();
}
static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
index ceb3aa03d561..1e36459948db 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -18,7 +18,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
void *iml_img;
u32 control_flags = 0;
int ret;
+ int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
/* Allocate prph scratch */
prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
@@ -151,7 +152,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
ctxt_info_gen3->mcr_base_addr =
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
ctxt_info_gen3->mtr_size =
- cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS));
+ cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size));
ctxt_info_gen3->mcr_size =
cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
@@ -175,8 +176,13 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
iwl_write64(trans, CSR_IML_DATA_ADDR,
trans_pcie->iml_dma_addr);
iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
- iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA);
- iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
+
+ iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
+ CSR_AUTO_FUNC_BOOT_ENA);
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
+ else
+ iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 7f4aaa810ea1..9274e317cc77 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -59,8 +59,7 @@
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
+ struct iwl_self_init_dram *dram = &trans->init_dram;
int i;
if (!dram->paging) {
@@ -83,8 +82,7 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
struct iwl_context_info_dram *ctxt_dram)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
+ struct iwl_self_init_dram *dram = &trans->init_dram;
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
if (WARN(dram->paging,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 353581ccc01e..2b94e4cef56c 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -8,7 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016-2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -32,7 +32,7 @@
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -513,10 +513,12 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)},
/* 9000 Series */
- {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0040, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -525,23 +527,26 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x02A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x02F0, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0040, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x06F0, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -550,26 +555,28 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x06F0, 0x0234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x0238, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x023C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x06F0, 0x0260, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x02A0, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x02A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x06F0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x06F0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x06F0, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x001C, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x0060, iwl9460_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x0064, iwl9460_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9460_2ac_cfg)},
@@ -593,24 +600,28 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2526, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x1552, iwl9560_killer_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x1610, iwl9270_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x4018, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},
{IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -619,6 +630,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)},
{IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)},
{IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)},
@@ -628,17 +640,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2720, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x2720, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_cfg)},
- {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg)},
+ {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9460_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -656,17 +668,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x30DC, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x30DC, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_160_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_160_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_160_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_shared_clk)},
@@ -684,18 +696,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x31DC, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x31DC, 0x1551, iwl9560_killer_s_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x1552, iwl9560_killer_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_160_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_160_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_160_cfg_shared_clk)},
+ {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_160_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x4234, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x42A4, iwl9462_2ac_cfg_shared_clk)},
- {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
@@ -704,24 +717,25 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x34F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x34F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x2030, iwl9560_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x2034, iwl9560_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x4030, iwl9560_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x34F0, 0x4034, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
- {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -739,17 +753,18 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x3DF0, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x3DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x3DF0, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -758,6 +773,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)},
@@ -767,19 +783,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x43F0, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0x43F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9460_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9460_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x0060, iwl9460_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -805,18 +821,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x9DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl9460_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl9460_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x9DF0, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0044, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -825,6 +842,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0244, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)},
@@ -834,17 +852,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0xA0F0, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0xA0F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x0060, iwl9460_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x0064, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x00A0, iwl9462_2ac_cfg_soc)},
@@ -862,41 +880,98 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0xA370, 0x1210, iwl9260_2ac_cfg)},
{IWL_PCI_DEVICE(0xA370, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x1552, iwl9560_killer_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_cfg_soc)},
- {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_160_cfg_soc)},
+ {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_160_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)},
/* 22000 Series */
- {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x02F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x02F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x06F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0000, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0040, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)},
- {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)},
- {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x007C, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)},
{IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)},
- {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)},
+ {IWL_PCI_DEVICE(0x2720, 0x1080, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x2720, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x2720, 0x4070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)},
{IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)},
{IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)},
{IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)},
{IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)},
- {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22000_2ax_cfg_hr)},
- {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl_ax101_cfg_qu_hr)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
+ {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax101_cfg_qu_hr)},
+
+ {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)},
+
+ {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)},
+ {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)},
+
+ {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_so_hr_a0)},
+ {IWL_PCI_DEVICE(0x2725, 0x00B0, iwlax210_2ax_cfg_so_hr_a0)},
#endif /* CONFIG_IWLMVM */
@@ -949,7 +1024,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rf_id_chp == jf_chp_id) {
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ)
- cfg = &iwl22000_2ax_cfg_qnj_jf_b0;
+ cfg = &iwl9560_2ac_cfg_qnj_jf_b0;
else
cfg = &iwl22000_2ac_cfg_jf;
} else if (rf_id_chp == hr_chp_id) {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index d6fc6ce73e0a..bf8b61a476c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -1,12 +1,14 @@
/******************************************************************************
*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
* Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -18,12 +20,46 @@
* more details.
*
* The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
+ * file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 __iwl_trans_int_pcie_h__
#define __iwl_trans_int_pcie_h__
@@ -364,6 +400,8 @@ struct iwl_txq {
u32 id;
int low_mark;
int high_mark;
+
+ bool overflow_tx;
};
static inline dma_addr_t
@@ -418,20 +456,6 @@ enum iwl_image_response_code {
};
/**
- * struct iwl_self_init_dram - dram data used by self init process
- * @fw: lmac and umac dram data
- * @fw_cnt: total number of items in array
- * @paging: paging dram data
- * @paging_cnt: total number of items in array
- */
-struct iwl_self_init_dram {
- struct iwl_dram_data *fw;
- int fw_cnt;
- struct iwl_dram_data *paging;
- int paging_cnt;
-};
-
-/**
* struct cont_rec: continuous recording data structure
* @prev_wr_ptr: the last address that was read in monitor_data
* debugfs file
@@ -502,6 +526,8 @@ struct cont_rec {
* @fh_mask: current unmasked fh causes
* @hw_mask: current unmasked hw causes
* @in_rescan: true if we have triggered a device rescan
+ * @base_rb_stts: base virtual address of receive buffer status for all queues
+ * @base_rb_stts_dma: base physical address of receive buffer status
*/
struct iwl_trans_pcie {
struct iwl_rxq *rxq;
@@ -518,7 +544,6 @@ struct iwl_trans_pcie {
dma_addr_t prph_info_dma_addr;
dma_addr_t prph_scratch_dma_addr;
dma_addr_t iml_dma_addr;
- struct iwl_self_init_dram init_dram;
struct iwl_trans *trans;
struct net_device napi_dev;
@@ -594,6 +619,9 @@ struct iwl_trans_pcie {
cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES];
u16 tx_cmd_queue_size;
bool in_rescan;
+
+ void *base_rb_stts;
+ dma_addr_t base_rb_stts_dma;
};
static inline struct iwl_trans_pcie *
@@ -777,8 +805,7 @@ static inline int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
+ struct iwl_self_init_dram *dram = &trans->init_dram;
int i;
if (!dram->fw) {
@@ -1016,6 +1043,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
+void iwl_trans_sync_nmi(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
@@ -1029,8 +1057,6 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans);
int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans);
-void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable);
-
void iwl_pcie_rx_allocator_work(struct work_struct *data);
/* common functions that are used by gen2 transport */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index e965cc588850..8d4f0628622b 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1,12 +1,14 @@
/******************************************************************************
*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -18,12 +20,46 @@
* more details.
*
* The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
+ * file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 <linux/sched.h>
#include <linux/wait.h>
@@ -166,9 +202,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
{
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
/* TODO: remove this for 22560 once fw does it */
- iwl_write_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
- return iwl_poll_prph_bit(trans, RFH_GEN_STATUS_GEN3,
- RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
+ iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
+ return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3,
+ RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
} else if (trans->cfg->mq_rx_supported) {
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
@@ -211,7 +247,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
}
rxq->write_actual = round_down(rxq->write, 8);
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
iwl_write32(trans, HBUS_TARG_WRPTR,
(rxq->write_actual |
((FIRST_RX_QUEUE + rxq->id) << 16)));
@@ -256,6 +292,9 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid);
}
+
+ IWL_DEBUG_RX(trans, "Assigned virtual RB ID %u to queue %d index %d\n",
+ (u32)rxb->vid, rxq->id, rxq->write);
}
/*
@@ -499,9 +538,9 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
struct list_head local_empty;
- int pending = atomic_xchg(&rba->req_pending, 0);
+ int pending = atomic_read(&rba->req_pending);
- IWL_DEBUG_RX(trans, "Pending allocation requests = %d\n", pending);
+ IWL_DEBUG_TPT(trans, "Pending allocation requests = %d\n", pending);
/* If we were scheduled - there is at least one request */
spin_lock(&rba->lock);
@@ -554,12 +593,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
i++;
}
+ atomic_dec(&rba->req_pending);
pending--;
+
if (!pending) {
- pending = atomic_xchg(&rba->req_pending, 0);
- IWL_DEBUG_RX(trans,
- "Pending allocation requests = %d\n",
- pending);
+ pending = atomic_read(&rba->req_pending);
+ if (pending)
+ IWL_DEBUG_TPT(trans,
+ "Got more pending allocation requests = %d\n",
+ pending);
}
spin_lock(&rba->lock);
@@ -570,12 +612,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
spin_unlock(&rba->lock);
atomic_inc(&rba->req_ready);
+
}
spin_lock(&rba->lock);
/* return unused rbds to the allocator empty list */
list_splice_tail(&local_empty, &rba->rbd_empty);
spin_unlock(&rba->lock);
+
+ IWL_DEBUG_TPT(trans, "%s, exit.\n", __func__);
}
/*
@@ -657,11 +702,6 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
rxq->bd_dma = 0;
rxq->bd = NULL;
- if (rxq->rb_stts)
- dma_free_coherent(trans->dev,
- use_rx_td ? sizeof(__le16) :
- sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
rxq->rb_stts_dma = 0;
rxq->rb_stts = NULL;
@@ -698,6 +738,8 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
int free_size;
bool use_rx_td = (trans->cfg->device_family >=
IWL_DEVICE_FAMILY_22560);
+ size_t rb_stts_size = use_rx_td ? sizeof(__le16) :
+ sizeof(struct iwl_rb_status);
spin_lock_init(&rxq->lock);
if (trans->cfg->mq_rx_supported)
@@ -711,47 +753,36 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
* Allocate the circular buffer of Read Buffer Descriptors
* (RBDs)
*/
- rxq->bd = dma_zalloc_coherent(dev,
- free_size * rxq->queue_size,
- &rxq->bd_dma, GFP_KERNEL);
+ rxq->bd = dma_alloc_coherent(dev, free_size * rxq->queue_size,
+ &rxq->bd_dma, GFP_KERNEL);
if (!rxq->bd)
goto err;
if (trans->cfg->mq_rx_supported) {
- rxq->used_bd = dma_zalloc_coherent(dev,
- (use_rx_td ?
- sizeof(*rxq->cd) :
- sizeof(__le32)) *
- rxq->queue_size,
- &rxq->used_bd_dma,
- GFP_KERNEL);
+ rxq->used_bd = dma_alloc_coherent(dev,
+ (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size,
+ &rxq->used_bd_dma,
+ GFP_KERNEL);
if (!rxq->used_bd)
goto err;
}
- /* Allocate the driver's pointer to receive buffer status */
- rxq->rb_stts = dma_zalloc_coherent(dev, use_rx_td ?
- sizeof(__le16) :
- sizeof(struct iwl_rb_status),
- &rxq->rb_stts_dma,
- GFP_KERNEL);
- if (!rxq->rb_stts)
- goto err;
+ rxq->rb_stts = trans_pcie->base_rb_stts + rxq->id * rb_stts_size;
+ rxq->rb_stts_dma =
+ trans_pcie->base_rb_stts_dma + rxq->id * rb_stts_size;
if (!use_rx_td)
return 0;
/* Allocate the driver's pointer to TR tail */
- rxq->tr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
- &rxq->tr_tail_dma,
- GFP_KERNEL);
+ rxq->tr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+ &rxq->tr_tail_dma, GFP_KERNEL);
if (!rxq->tr_tail)
goto err;
/* Allocate the driver's pointer to CR tail */
- rxq->cr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
- &rxq->cr_tail_dma,
- GFP_KERNEL);
+ rxq->cr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+ &rxq->cr_tail_dma, GFP_KERNEL);
if (!rxq->cr_tail)
goto err;
/*
@@ -768,7 +799,6 @@ err:
iwl_pcie_free_rxq_dma(trans, rxq);
}
- kfree(trans_pcie->rxq);
return -ENOMEM;
}
@@ -778,6 +808,9 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i, ret;
+ size_t rb_stts_size = trans->cfg->device_family >=
+ IWL_DEVICE_FAMILY_22560 ?
+ sizeof(__le16) : sizeof(struct iwl_rb_status);
if (WARN_ON(trans_pcie->rxq))
return -EINVAL;
@@ -785,18 +818,46 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans)
trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq),
GFP_KERNEL);
if (!trans_pcie->rxq)
- return -EINVAL;
+ return -ENOMEM;
spin_lock_init(&rba->lock);
+ /*
+ * Allocate the driver's pointer to receive buffer status.
+ * Allocate for all queues continuously (HW requirement).
+ */
+ trans_pcie->base_rb_stts =
+ dma_alloc_coherent(trans->dev,
+ rb_stts_size * trans->num_rx_queues,
+ &trans_pcie->base_rb_stts_dma,
+ GFP_KERNEL);
+ if (!trans_pcie->base_rb_stts) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
for (i = 0; i < trans->num_rx_queues; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
+ rxq->id = i;
ret = iwl_pcie_alloc_rxq_dma(trans, rxq);
if (ret)
- return ret;
+ goto err;
}
return 0;
+
+err:
+ if (trans_pcie->base_rb_stts) {
+ dma_free_coherent(trans->dev,
+ rb_stts_size * trans->num_rx_queues,
+ trans_pcie->base_rb_stts,
+ trans_pcie->base_rb_stts_dma);
+ trans_pcie->base_rb_stts = NULL;
+ trans_pcie->base_rb_stts_dma = 0;
+ }
+ kfree(trans_pcie->rxq);
+
+ return ret;
}
static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
@@ -868,30 +929,6 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
}
-void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable)
-{
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_9000)
- return;
-
- if (CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP)
- return;
-
- if (!trans->cfg->integrated)
- return;
-
- /*
- * Turn on the chicken-bits that cause MAC wakeup for RX-related
- * values.
- * This costs some power, but needed for W/A 9000 integrated A-step
- * bug where shadow registers are not in the retention list and their
- * value is lost when NIC powers down
- */
- iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
- CSR_MAC_SHADOW_REG_CTRL_RX_WAKE);
- iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTL2,
- CSR_MAC_SHADOW_REG_CTL2_RX_WAKE);
-}
-
static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -979,8 +1016,6 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
/* Set interrupt coalescing timer to default (2048 usecs) */
iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-
- iwl_pcie_enable_rx_wake(trans, true);
}
void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
@@ -1031,8 +1066,6 @@ int _iwl_pcie_rx_init(struct iwl_trans *trans)
for (i = 0; i < trans->num_rx_queues; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
- rxq->id = i;
-
spin_lock(&rxq->lock);
/*
* Set read write pointer to reflect that we have processed
@@ -1119,6 +1152,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i;
+ size_t rb_stts_size = trans->cfg->device_family >=
+ IWL_DEVICE_FAMILY_22560 ?
+ sizeof(__le16) : sizeof(struct iwl_rb_status);
/*
* if rxq is NULL, it means that nothing has been allocated,
@@ -1133,6 +1169,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
iwl_pcie_free_rbs_pool(trans);
+ if (trans_pcie->base_rb_stts) {
+ dma_free_coherent(trans->dev,
+ rb_stts_size * trans->num_rx_queues,
+ trans_pcie->base_rb_stts,
+ trans_pcie->base_rb_stts_dma);
+ trans_pcie->base_rb_stts = NULL;
+ trans_pcie->base_rb_stts_dma = 0;
+ }
+
for (i = 0; i < trans->num_rx_queues; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
@@ -1368,6 +1413,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
if (rxb->invalid)
goto out_err;
+ IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid);
+
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE;
@@ -1417,13 +1464,17 @@ restart:
!emergency)) {
iwl_pcie_rx_move_to_allocator(rxq, rba);
emergency = true;
+ IWL_DEBUG_TPT(trans,
+ "RX path is in emergency. Pending allocations %d\n",
+ rb_pending_alloc);
}
+ IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
+
rxb = iwl_pcie_get_rxb(trans, rxq, i);
if (!rxb)
goto out;
- IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency, i);
i = (i + 1) & (rxq->queue_size - 1);
@@ -1445,8 +1496,12 @@ restart:
count++;
if (count == 8) {
count = 0;
- if (rb_pending_alloc < rxq->queue_size / 3)
+ if (rb_pending_alloc < rxq->queue_size / 3) {
+ IWL_DEBUG_TPT(trans,
+ "RX path exited emergency. Pending allocations %d\n",
+ rb_pending_alloc);
emergency = false;
+ }
rxq->read = i;
spin_unlock(&rxq->lock);
@@ -1947,9 +2002,8 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
trans_pcie->ict_tbl =
- dma_zalloc_coherent(trans->dev, ICT_SIZE,
- &trans_pcie->ict_tbl_dma,
- GFP_KERNEL);
+ dma_alloc_coherent(trans->dev, ICT_SIZE,
+ &trans_pcie->ict_tbl_dma, GFP_KERNEL);
if (!trans_pcie->ict_tbl)
return -ENOMEM;
@@ -2113,7 +2167,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
}
}
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 &&
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560 &&
inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
/* Reflect IML transfer status */
int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
@@ -2132,6 +2186,17 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
isr_stats->wakeup++;
}
+ if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) {
+ /* Reflect IML transfer status */
+ int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
+
+ IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res);
+ if (res == IWL_IMAGE_RESP_FAIL) {
+ isr_stats->sw++;
+ iwl_pcie_irq_handle_error(trans);
+ }
+ }
+
/* Chip got too hot and stopped itself */
if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) {
IWL_ERR(trans, "Microcode CT kill error detected.\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 77f3610e5ca9..9c203ca75de9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -92,26 +92,9 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans);
- /*
- * Set "initialization complete" bit to move adapter from
- * D0U* --> D0A* (powered-up active) state.
- */
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
-
- /*
- * Wait for clock stabilization; once stabilized, access to
- * device-internal resources is supported, e.g. iwl_write_prph()
- * and accesses to uCode SRAM.
- */
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (ret < 0) {
- IWL_DEBUG_INFO(trans, "Failed to init the card\n");
+ ret = iwl_finish_nic_init(trans);
+ if (ret)
return ret;
- }
set_bit(STATUS_DEVICE_ENABLED, &trans->status);
@@ -188,7 +171,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
}
iwl_pcie_ctxt_info_free_paging(trans);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
iwl_pcie_ctxt_info_gen3_free(trans);
else
iwl_pcie_ctxt_info_free(trans);
@@ -251,6 +234,7 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
spin_lock(&trans_pcie->irq_lock);
@@ -264,7 +248,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
return -ENOMEM;
/* Allocate or reset and init all Tx and Command queues */
- if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, TFD_CMD_SLOTS))
+ if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, queue_size))
return -ENOMEM;
/* enable shadow regs in HW */
@@ -349,7 +333,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
goto out;
}
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
else
ret = iwl_pcie_ctxt_info_init(trans, fw);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index f97aea5ffc44..fe8269d023de 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -8,7 +8,7 @@
* Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -364,26 +364,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
if (trans->cfg->base_params->pll_cfg)
iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
- /*
- * Set "initialization complete" bit to move adapter from
- * D0U* --> D0A* (powered-up active) state.
- */
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
-
- /*
- * Wait for clock stabilization; once stabilized, access to
- * device-internal resources is supported, e.g. iwl_write_prph()
- * and accesses to uCode SRAM.
- */
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (ret < 0) {
- IWL_ERR(trans, "Failed to init the card\n");
+ ret = iwl_finish_nic_init(trans);
+ if (ret)
return ret;
- }
if (trans->cfg->host_interrupt_operation_mode) {
/*
@@ -453,23 +436,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
iwl_trans_pcie_sw_reset(trans);
- /*
- * Set "initialization complete" bit to move adapter from
- * D0U* --> D0A* (powered-up active) state.
- */
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
-
- /*
- * Wait for clock stabilization; once stabilized, access to
- * device-internal resources is possible.
- */
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (WARN_ON(ret < 0)) {
- IWL_ERR(trans, "Access time out - failed to enable LP XTAL\n");
+ ret = iwl_finish_nic_init(trans);
+ if (WARN_ON(ret)) {
/* Release XTAL ON request */
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
@@ -928,13 +896,13 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
if (!trans->num_blocks)
return;
- iwl_write_prph(trans, MON_BUFF_BASE_ADDR_VER2,
- trans->fw_mon[0].physical >>
- MON_BUFF_SHIFT_VER2);
- iwl_write_prph(trans, MON_BUFF_END_ADDR_VER2,
- (trans->fw_mon[0].physical +
- trans->fw_mon[0].size - 256) >>
- MON_BUFF_SHIFT_VER2);
+ iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
+ trans->fw_mon[0].physical >>
+ MON_BUFF_SHIFT_VER2);
+ iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2,
+ (trans->fw_mon[0].physical +
+ trans->fw_mon[0].size - 256) >>
+ MON_BUFF_SHIFT_VER2);
return;
}
@@ -1126,6 +1094,7 @@ static struct iwl_causes_list causes_list[] = {
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
+ {MSIX_HW_INT_CAUSES_REG_IML, CSR_MSIX_HW_INT_MASK_AD, 0x12},
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
@@ -1158,7 +1127,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
int i, arr_size =
- (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
+ (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
/*
@@ -1168,7 +1137,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
*/
for (i = 0; i < arr_size; i++) {
struct iwl_causes_list *causes =
- (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
+ (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
causes_list : causes_list_v2;
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
@@ -1214,8 +1183,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
if (!trans_pcie->msix_enabled) {
if (trans->cfg->mq_rx_supported &&
test_bit(STATUS_DEVICE_ENABLED, &trans->status))
- iwl_write_prph(trans, UREG_CHICK,
- UREG_CHICK_MSI_ENABLE);
+ iwl_write_umac_prph(trans, UREG_CHICK,
+ UREG_CHICK_MSI_ENABLE);
return;
}
/*
@@ -1224,7 +1193,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
* prph.
*/
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
- iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
+ iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
/*
* Each cause from the causes list above and the RX causes is
@@ -1530,8 +1499,6 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done));
- iwl_pcie_enable_rx_wake(trans, false);
-
if (reset) {
/*
* reset TX queues -- some of their registers reset during S3
@@ -1558,24 +1525,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return 0;
}
- iwl_pcie_enable_rx_wake(trans, true);
-
iwl_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req));
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
- udelay(2);
-
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (ret < 0) {
- IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
+ ret = iwl_finish_nic_init(trans);
+ if (ret)
return ret;
- }
/*
* Reconfigure IVAR table in case of MSIX or reset ict table in
@@ -1606,7 +1561,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
}
IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n",
- iwl_read_prph(trans, WFPM_GP2));
+ iwl_read_umac_prph(trans, WFPM_GP2));
val = iwl_read32(trans, CSR_RESET);
if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
@@ -1755,15 +1710,18 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
return err;
}
- hpm = iwl_trans_read_prph(trans, HPM_DEBUG);
+ hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
- if (iwl_trans_read_prph(trans, PREG_PRPH_WPROT_0) &
- PREG_WFPM_ACCESS) {
+ int wfpm_val = iwl_read_umac_prph_no_grab(trans,
+ PREG_PRPH_WPROT_0);
+
+ if (wfpm_val & PREG_WFPM_ACCESS) {
IWL_ERR(trans,
"Error, can not clear persistence bit\n");
return -EPERM;
}
- iwl_trans_write_prph(trans, HPM_DEBUG, hpm & ~PERSISTENCE_BIT);
+ iwl_write_umac_prph_no_grab(trans, HPM_DEBUG,
+ hpm & ~PERSISTENCE_BIT);
}
iwl_trans_pcie_sw_reset(trans);
@@ -1968,7 +1926,7 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk)
struct iwl_trans_pcie_removal *removal =
container_of(wk, struct iwl_trans_pcie_removal, work);
struct pci_dev *pdev = removal->pdev;
- char *prop[] = {"EVENT=INACCESSIBLE", NULL};
+ static char *prop[] = {"EVENT=INACCESSIBLE", NULL};
dev_err(&pdev->dev, "Device gone - attempting removal\n");
kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, prop);
@@ -2285,6 +2243,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq;
unsigned long now = jiffies;
+ bool overflow_tx;
u8 wr_ptr;
/* Make sure the NIC is still alive in the bus */
@@ -2296,18 +2255,37 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
txq = trans_pcie->txq[txq_idx];
+
+ spin_lock_bh(&txq->lock);
+ overflow_tx = txq->overflow_tx ||
+ !skb_queue_empty(&txq->overflow_q);
+ spin_unlock_bh(&txq->lock);
+
wr_ptr = READ_ONCE(txq->write_ptr);
- while (txq->read_ptr != READ_ONCE(txq->write_ptr) &&
+ while ((txq->read_ptr != READ_ONCE(txq->write_ptr) ||
+ overflow_tx) &&
!time_after(jiffies,
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
u8 write_ptr = READ_ONCE(txq->write_ptr);
- if (WARN_ONCE(wr_ptr != write_ptr,
+ /*
+ * If write pointer moved during the wait, warn only
+ * if the TX came from op mode. In case TX came from
+ * trans layer (overflow TX) don't warn.
+ */
+ if (WARN_ONCE(wr_ptr != write_ptr && !overflow_tx,
"WR pointer moved while flushing %d -> %d\n",
wr_ptr, write_ptr))
return -ETIMEDOUT;
+ wr_ptr = write_ptr;
+
usleep_range(1000, 2000);
+
+ spin_lock_bh(&txq->lock);
+ overflow_tx = txq->overflow_tx ||
+ !skb_queue_empty(&txq->overflow_q);
+ spin_unlock_bh(&txq->lock);
}
if (txq->read_ptr != txq->write_ptr) {
@@ -2993,7 +2971,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
i += sizeof(u32))
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
else
- for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2;
+ for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2);
+ i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2);
i += sizeof(u32))
*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
i));
@@ -3018,11 +2997,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans,
if (!iwl_trans_grab_nic_access(trans, &flags))
return 0;
- iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
+ iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
for (i = 0; i < buf_size_in_dwords; i++)
- buffer[i] = iwl_read_prph_no_grab(trans,
- MON_DMARB_RD_DATA_ADDR);
- iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
+ buffer[i] = iwl_read_umac_prph_no_grab(trans,
+ MON_DMARB_RD_DATA_ADDR);
+ iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
iwl_trans_release_nic_access(trans, &flags);
@@ -3037,9 +3016,9 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
/* If there was a dest TLV - use the values from there */
if (trans->ini_valid) {
- base = MON_BUFF_BASE_ADDR_VER2;
- write_ptr = MON_BUFF_WRPTR_VER2;
- wrap_cnt = MON_BUFF_CYCLE_CNT_VER2;
+ base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2);
+ write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2);
+ wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2);
} else if (trans->dbg_dest_tlv) {
write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
@@ -3118,7 +3097,7 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
return len;
}
-static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, int *len)
+static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
{
if (trans->num_blocks) {
*len += sizeof(struct iwl_fw_error_dump_data) +
@@ -3173,8 +3152,7 @@ static struct iwl_trans_dump_data
struct iwl_txq *cmdq = trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_fw_error_dump_txcmd *txcmd;
struct iwl_trans_dump_data *dump_data;
- u32 len, num_rbs = 0;
- u32 monitor_len;
+ u32 len, num_rbs = 0, monitor_len = 0;
int i, ptr;
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
!trans->cfg->mq_rx_supported &&
@@ -3191,19 +3169,8 @@ static struct iwl_trans_dump_data
cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
/* FW monitor */
- monitor_len = iwl_trans_get_fw_monitor_len(trans, &len);
-
- if (dump_mask == BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) {
- dump_data = vzalloc(len);
- if (!dump_data)
- return NULL;
-
- data = (void *)dump_data->data;
- len = iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
- dump_data->len = len;
-
- return dump_data;
- }
+ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
+ monitor_len = iwl_trans_get_fw_monitor_len(trans, &len);
/* CSR registers */
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
@@ -3213,8 +3180,8 @@ static struct iwl_trans_dump_data
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
if (trans->cfg->gen2)
len += sizeof(*data) +
- (FH_MEM_UPPER_BOUND_GEN2 -
- FH_MEM_LOWER_BOUND_GEN2);
+ (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) -
+ iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2));
else
len += sizeof(*data) +
(FH_MEM_UPPER_BOUND -
@@ -3236,10 +3203,10 @@ static struct iwl_trans_dump_data
/* Paged memory for gen2 HW */
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
- for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
+ for (i = 0; i < trans->init_dram.paging_cnt; i++)
len += sizeof(*data) +
sizeof(struct iwl_fw_error_dump_paging) +
- trans_pcie->init_dram.paging[i].size;
+ trans->init_dram.paging[i].size;
dump_data = vzalloc(len);
if (!dump_data)
@@ -3291,20 +3258,16 @@ static struct iwl_trans_dump_data
/* Paged memory for gen2 HW */
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
- for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
+ for (i = 0; i < trans->init_dram.paging_cnt; i++) {
struct iwl_fw_error_dump_paging *paging;
- dma_addr_t addr =
- trans_pcie->init_dram.paging[i].physical;
- u32 page_len = trans_pcie->init_dram.paging[i].size;
+ u32 page_len = trans->init_dram.paging[i].size;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
data->len = cpu_to_le32(sizeof(*paging) + page_len);
paging = (void *)data->data;
paging->index = cpu_to_le32(i);
- dma_sync_single_for_cpu(trans->dev, addr, page_len,
- DMA_BIDIRECTIONAL);
memcpy(paging->data,
- trans_pcie->init_dram.paging[i].block, page_len);
+ trans->init_dram.paging[i].block, page_len);
data = iwl_fw_error_next_data(data);
len += sizeof(*data) + sizeof(*paging) + page_len;
@@ -3541,25 +3504,18 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* in-order to recognize C step driver should read chip version
* id located at the AUX bus MISC address space.
*/
- iwl_set_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_init_done));
- udelay(2);
-
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- BIT(trans->cfg->csr->flag_mac_clock_ready),
- 25000);
- if (ret < 0) {
- IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n");
+ ret = iwl_finish_nic_init(trans);
+ if (ret)
goto out_no_pci;
- }
if (iwl_trans_grab_nic_access(trans, &flags)) {
u32 hw_step;
- hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG);
+ hw_step = iwl_read_umac_prph_no_grab(trans,
+ WFPM_CTRL_REG);
hw_step |= ENABLE_WFPM;
- iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step);
+ iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
+ hw_step);
hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
if (hw_step == 0x3)
@@ -3569,24 +3525,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
- /*
- * 9000-series integrated A-step has a problem with suspend/resume
- * and sometimes even causes the whole platform to get stuck. This
- * workaround makes the hardware not go into the problematic state.
- */
- if (trans->cfg->integrated &&
- trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
- CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)
- iwl_set_bit(trans, CSR_HOST_CHICKEN,
- CSR_HOST_CHICKEN_PM_IDLE_SRC_DIS_SB_PME);
+ IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev);
#if IS_ENABLED(CONFIG_IWLMVM)
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
- if (cfg == &iwl22000_2ax_cfg_hr) {
+ if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
+ if (trans->hw_rev == CSR_HW_REV_TYPE_TY) {
+ trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
+ } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
+ CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
+ trans->cfg = &iwlax210_2ax_cfg_so_jf_a0;
+ } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
+ CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
+ trans->cfg = &iwlax210_2ax_cfg_so_gf_a0;
+ }
+ } else if (cfg == &iwl_ax101_cfg_qu_hr) {
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
- trans->cfg = &iwl22000_2ax_cfg_hr;
+ trans->cfg = &iwl_ax101_cfg_qu_hr;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
trans->cfg = &iwl22000_2ax_cfg_jf;
@@ -3602,7 +3559,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_no_pci;
}
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
- CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
+ CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
+ (trans->cfg != &iwl22260_2ax_cfg ||
+ trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
u32 hw_status;
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
@@ -3677,3 +3636,28 @@ out_no_pci:
iwl_trans_free(trans);
return ERR_PTR(ret);
}
+
+void iwl_trans_sync_nmi(struct iwl_trans *trans)
+{
+ unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
+
+ iwl_disable_interrupts(trans);
+ iwl_force_nmi(trans);
+ while (time_after(timeout, jiffies)) {
+ u32 inta_hw = iwl_read32(trans,
+ CSR_MSIX_HW_INT_CAUSES_AD);
+
+ /* Error detected by uCode */
+ if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) {
+ /* Clear causes register */
+ iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
+ inta_hw &
+ MSIX_HW_INT_CAUSES_REG_SW_ERR);
+ break;
+ }
+
+ mdelay(1);
+ }
+ iwl_enable_interrupts(trans);
+ iwl_trans_fw_error(trans);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 156ca1b1f621..88530d9f4a54 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -214,7 +214,11 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int idx = iwl_pcie_gen2_get_num_tbs(trans, tfd);
- struct iwl_tfh_tb *tb = &tfd->tbs[idx];
+ struct iwl_tfh_tb *tb;
+
+ if (WARN_ON(idx >= IWL_TFH_NUM_TBS))
+ return -EINVAL;
+ tb = &tfd->tbs[idx];
/* Each TFD can point to a maximum max_tbs Tx buffers */
if (le16_to_cpu(tfd->num_tbs) >= trans_pcie->max_tbs) {
@@ -408,7 +412,7 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans,
goto out_err;
/* building the A-MSDU might have changed this data, memcpy it now */
- memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr, IWL_FIRST_TB_SIZE);
+ memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE);
return tfd;
out_err:
@@ -469,7 +473,7 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans,
tb_phys = iwl_pcie_get_first_tb_dma(txq, idx);
/* The first TB points to bi-directional DMA data */
- memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr, IWL_FIRST_TB_SIZE);
+ memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE);
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
@@ -834,14 +838,14 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
/* start the TFD with the minimum copy bytes */
tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
- memcpy(&txq->first_tb_bufs[idx], &out_cmd->hdr, tb0_size);
+ memcpy(&txq->first_tb_bufs[idx], out_cmd, tb0_size);
iwl_pcie_gen2_set_tb(trans, tfd, iwl_pcie_get_first_tb_dma(txq, idx),
tb0_size);
/* map first command fragment, if any remains */
if (copy_size > tb0_size) {
phys_addr = dma_map_single(trans->dev,
- ((u8 *)&out_cmd->hdr) + tb0_size,
+ (u8 *)out_cmd + tb0_size,
copy_size - tb0_size,
DMA_TO_DEVICE);
if (dma_mapping_error(trans->dev, phys_addr)) {
@@ -961,9 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
cmd_str);
ret = -ETIMEDOUT;
- iwl_force_nmi(trans);
- iwl_trans_fw_error(trans);
-
+ iwl_trans_sync_nmi(trans);
goto cancel;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index ee990a7a5411..9fbd37d23e85 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -1,12 +1,14 @@
/******************************************************************************
*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
@@ -18,12 +20,46 @@
* more details.
*
* The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
+ * file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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 <linux/etherdevice.h>
#include <linux/ieee80211.h>
@@ -959,7 +995,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
- slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ if (cmd_queue)
+ slots_num = max_t(u32, TFD_CMD_SLOTS,
+ trans->cfg->min_txq_size);
+ else
+ slots_num = TFD_TX_CMD_SLOTS;
trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
@@ -1008,7 +1048,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
- slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ if (cmd_queue)
+ slots_num = max_t(u32, TFD_CMD_SLOTS,
+ trans->cfg->min_txq_size);
+ else
+ slots_num = TFD_TX_CMD_SLOTS;
ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
if (ret) {
@@ -1138,6 +1182,15 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
skb_queue_splice_init(&txq->overflow_q, &overflow_skbs);
/*
+ * We are going to transmit from the overflow queue.
+ * Remember this state so that wait_for_txq_empty will know we
+ * are adding more packets to the TFD queue. It cannot rely on
+ * the state of &txq->overflow_q, as we just emptied it, but
+ * haven't TXed the content yet.
+ */
+ txq->overflow_tx = true;
+
+ /*
* This is tricky: we are in reclaim path which is non
* re-entrant, so noone will try to take the access the
* txq data from that path. We stopped tx, so we can't
@@ -1165,6 +1218,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
iwl_wake_queue(trans, txq);
spin_lock_bh(&txq->lock);
+ txq->overflow_tx = false;
}
if (txq->read_ptr == txq->write_ptr) {
@@ -1906,9 +1960,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
iwl_get_cmd_string(trans, cmd->id));
ret = -ETIMEDOUT;
- iwl_force_nmi(trans);
- iwl_trans_fw_error(trans);
-
+ iwl_trans_sync_nmi(trans);
goto cancel;
}
@@ -2438,8 +2490,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
}
/* building the A-MSDU might have changed this data, so memcpy it now */
- memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
- IWL_FIRST_TB_SIZE);
+ memcpy(&txq->first_tb_bufs[txq->write_ptr], dev_cmd, IWL_FIRST_TB_SIZE);
tfd = iwl_pcie_get_tfd(trans, txq, txq->write_ptr);
/* Set up entry for this TFD in Tx byte-count array */
diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c
index 709d9ab3e7bc..67b0c05afbdb 100644
--- a/drivers/net/wireless/intersil/orinoco/mic.c
+++ b/drivers/net/wireless/intersil/orinoco/mic.c
@@ -18,16 +18,16 @@ int orinoco_mic_init(struct orinoco_private *priv)
{
priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->tx_tfm_mic)) {
- printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
- "crypto API michael_mic\n");
+ printk(KERN_DEBUG "%s: could not allocate "
+ "crypto API michael_mic\n", __func__);
priv->tx_tfm_mic = NULL;
return -ENOMEM;
}
priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(priv->rx_tfm_mic)) {
- printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
- "crypto API michael_mic\n");
+ printk(KERN_DEBUG "%s: could not allocate "
+ "crypto API michael_mic\n", __func__);
priv->rx_tfm_mic = NULL;
return -ENOMEM;
}
@@ -52,7 +52,7 @@ int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
int err;
if (tfm_michael == NULL) {
- printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n");
+ printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__);
return -1;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 3a4b8786f7ea..0838af04d681 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1273,10 +1273,12 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
* probably doesn't really matter.
*/
if (ieee80211_is_beacon(hdr->frame_control) ||
- ieee80211_is_probe_resp(hdr->frame_control))
+ ieee80211_is_probe_resp(hdr->frame_control)) {
+ rx_status.boottime_ns = ktime_get_boot_ns();
now = data->abs_bcn_ts;
- else
+ } else {
now = mac80211_hwsim_get_tsf_raw();
+ }
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
@@ -2761,6 +2763,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
BIT(NL80211_CHAN_WIDTH_160);
}
+ if (!n_limits) {
+ err = -EINVAL;
+ goto failed_hw;
+ }
+
data->if_combination.n_limits = n_limits;
data->if_combination.max_interfaces = 2048;
data->if_combination.limits = data->if_limits;
@@ -2794,6 +2801,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
ieee80211_hw_set(hw, TDLS_WIDER_BW);
if (rctbl)
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
@@ -3549,7 +3557,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
goto out_err;
}
- genlmsg_reply(skb, info);
+ res = genlmsg_reply(skb, info);
break;
}
diff --git a/drivers/net/wireless/marvell/libertas/debugfs.c b/drivers/net/wireless/marvell/libertas/debugfs.c
index c83f44f9ddf1..fe14814af300 100644
--- a/drivers/net/wireless/marvell/libertas/debugfs.c
+++ b/drivers/net/wireless/marvell/libertas/debugfs.c
@@ -708,8 +708,6 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
goto exit;
priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
- if (!priv->debugfs_dir)
- goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
files = &debugfs_files[i];
@@ -721,8 +719,6 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
}
priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
- if (!priv->events_dir)
- goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
files = &debugfs_events_files[i];
@@ -734,8 +730,6 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
}
priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
- if (!priv->regs_dir)
- goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
files = &debugfs_regs_files[i];
diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c
index b0cb16ef8d1d..2315fdff56c2 100644
--- a/drivers/net/wireless/marvell/libertas/mesh.c
+++ b/drivers/net/wireless/marvell/libertas/mesh.c
@@ -797,7 +797,12 @@ static void lbs_persist_config_init(struct net_device *dev)
{
int ret;
ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
+ if (ret)
+ pr_err("failed to create boot_opts_group.\n");
+
ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
+ if (ret)
+ pr_err("failed to create mesh_ie_group.\n");
}
static void lbs_persist_config_remove(struct net_device *dev)
diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c
index 909ac3685010..130f578daafd 100644
--- a/drivers/net/wireless/marvell/libertas_tf/cmd.c
+++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c
@@ -256,7 +256,7 @@ static void lbtf_submit_command(struct lbtf_private *priv,
command, le16_to_cpu(cmd->seqnum), cmdsize);
lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+ ret = priv->ops->hw_host_to_card(priv, MVMS_CMD, (u8 *)cmd, cmdsize);
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (ret) {
@@ -737,10 +737,9 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
- if (net_ratelimit())
- pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
- respcmd, le16_to_cpu(resp->seqnum),
- le16_to_cpu(resp->size));
+ lbtf_deb_cmd("libertastf: cmd response 0x%04x, seq %d, size %d\n",
+ respcmd, le16_to_cpu(resp->seqnum),
+ le16_to_cpu(resp->size));
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index 789337ea676a..a4b9ede70705 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_prog_firmware(struct lbtf_private *priv);
static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
uint16_t nb, u8 data);
static void if_usb_free(struct if_usb_card *cardp);
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
-static int if_usb_reset_device(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct lbtf_private *priv);
/**
* if_usb_wrike_bulk_callback - call back to handle URB status
@@ -131,6 +131,12 @@ static void if_usb_fw_timeo(struct timer_list *t)
lbtf_deb_leave(LBTF_DEB_USB);
}
+static const struct lbtf_ops if_usb_ops = {
+ .hw_host_to_card = if_usb_host_to_card,
+ .hw_prog_firmware = if_usb_prog_firmware,
+ .hw_reset_device = if_usb_reset_device,
+};
+
/**
* if_usb_probe - sets the configuration values
*
@@ -216,17 +222,11 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc;
}
- priv = lbtf_add_card(cardp, &udev->dev);
+ cardp->boot2_version = udev->descriptor.bcdDevice;
+ priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops);
if (!priv)
goto dealloc;
- cardp->priv = priv;
-
- priv->hw_host_to_card = if_usb_host_to_card;
- priv->hw_prog_firmware = if_usb_prog_firmware;
- priv->hw_reset_device = if_usb_reset_device;
- cardp->boot2_version = udev->descriptor.bcdDevice;
-
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
@@ -251,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
lbtf_deb_enter(LBTF_DEB_MAIN);
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
if (priv)
lbtf_remove_card(priv);
@@ -334,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
return 0;
}
-static int if_usb_reset_device(struct if_usb_card *cardp)
+static int if_usb_reset_device(struct lbtf_private *priv)
{
+ struct if_usb_card *cardp = priv->card;
struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
int ret;
@@ -433,8 +434,6 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
skb_tail_pointer(skb),
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
- cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
-
lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
cardp->rx_urb);
ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
@@ -808,14 +807,17 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
}
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
+static int if_usb_prog_firmware(struct lbtf_private *priv)
{
+ struct if_usb_card *cardp = priv->card;
int i = 0;
static int reset_count = 10;
int ret = 0;
lbtf_deb_enter(LBTF_DEB_USB);
+ cardp->priv = priv;
+
kernel_param_lock(THIS_MODULE);
ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
if (ret < 0) {
@@ -851,7 +853,7 @@ restart:
if (cardp->bootcmdresp <= 0) {
if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
goto restart;
}
return -1;
@@ -880,7 +882,7 @@ restart:
if (!cardp->fwdnldover) {
pr_info("failed to load fw, resetting device!\n");
if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
goto restart;
}
@@ -889,8 +891,6 @@ restart:
goto release_fw;
}
- cardp->priv->fw_ready = 1;
-
release_fw:
release_firmware(cardp->fw);
cardp->fw = NULL;
diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
index ad77b92d0b41..3ed1fbe28798 100644
--- a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
+++ b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
@@ -173,10 +173,19 @@ struct channel_range {
struct if_usb_card;
+struct lbtf_ops {
+ /** Hardware access */
+ int (*hw_host_to_card)(struct lbtf_private *priv, u8 type,
+ u8 *payload, u16 nb);
+ int (*hw_prog_firmware)(struct lbtf_private *priv);
+ int (*hw_reset_device)(struct lbtf_private *priv);
+};
+
/** Private structure for the MV device */
struct lbtf_private {
void *card;
struct ieee80211_hw *hw;
+ const struct lbtf_ops *ops;
/* Command response buffer */
u8 cmd_resp_buff[LBS_UPLD_SIZE];
@@ -188,11 +197,6 @@ struct lbtf_private {
struct work_struct cmd_work;
struct work_struct tx_work;
- /** Hardware access */
- int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb);
- int (*hw_prog_firmware) (struct if_usb_card *cardp);
- int (*hw_reset_device) (struct if_usb_card *cardp);
-
/** Wlan adapter data structure*/
/** STATUS variables */
@@ -250,7 +254,6 @@ struct lbtf_private {
struct ieee80211_supported_band band;
struct lbtf_offset_value offsetvalue;
- u8 fw_ready;
u8 surpriseremoved;
struct sk_buff_head bc_ps_buf;
@@ -486,7 +489,8 @@ void lbtf_cmd_response_rx(struct lbtf_private *priv);
/* main.c */
struct chan_freq_power *lbtf_get_region_cfp_table(u8 region,
int *cfp_no);
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev);
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
+ const struct lbtf_ops *ops);
int lbtf_remove_card(struct lbtf_private *priv);
int lbtf_start_card(struct lbtf_private *priv);
int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb);
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index 1d45da187b9b..5799e9886d83 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work)
priv->cmd_timed_out = 0;
spin_unlock_irq(&priv->driver_lock);
- if (!priv->fw_ready) {
- lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
- return;
- }
-
/* Execute the next command */
if (!priv->cur_cmd)
lbtf_execute_next_command(priv);
@@ -131,37 +126,6 @@ static void lbtf_cmd_work(struct work_struct *work)
}
/**
- * lbtf_setup_firmware: initialize firmware.
- *
- * @priv A pointer to struct lbtf_private structure
- *
- * Returns: 0 on success.
- */
-static int lbtf_setup_firmware(struct lbtf_private *priv)
-{
- int ret = -1;
-
- lbtf_deb_enter(LBTF_DEB_FW);
- /*
- * Read priv address from HW
- */
- eth_broadcast_addr(priv->current_addr);
- ret = lbtf_update_hw_spec(priv);
- if (ret) {
- ret = -1;
- goto done;
- }
-
- lbtf_set_mac_control(priv);
- lbtf_set_radio_control(priv);
-
- ret = 0;
-done:
- lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
- return ret;
-}
-
-/**
* This function handles the timeout of command sending.
* It will re-send the same command again.
*/
@@ -281,7 +245,7 @@ static void lbtf_tx_work(struct work_struct *work)
BUG_ON(priv->tx_skb);
spin_lock_irq(&priv->driver_lock);
priv->tx_skb = skb;
- err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
+ err = priv->ops->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
spin_unlock_irq(&priv->driver_lock);
if (err) {
dev_kfree_skb_any(skb);
@@ -294,38 +258,17 @@ static void lbtf_tx_work(struct work_struct *work)
static int lbtf_op_start(struct ieee80211_hw *hw)
{
struct lbtf_private *priv = hw->priv;
- void *card = priv->card;
- int ret = -1;
lbtf_deb_enter(LBTF_DEB_MACOPS);
- if (!priv->fw_ready)
- /* Upload firmware */
- if (priv->hw_prog_firmware(card))
- goto err_prog_firmware;
-
- /* poke the firmware */
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->radioon = RADIO_ON;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- ret = lbtf_setup_firmware(priv);
- if (ret)
- goto err_prog_firmware;
-
- if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
- (priv->fwrelease > LBTF_FW_VER_MAX)) {
- ret = -1;
- goto err_prog_firmware;
- }
+ lbtf_set_mac_control(priv);
+ lbtf_set_radio_control(priv);
- printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
-
-err_prog_firmware:
- priv->hw_reset_device(card);
- lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
- return ret;
}
static void lbtf_op_stop(struct ieee80211_hw *hw)
@@ -551,11 +494,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
struct ieee80211_rx_status stats;
struct rxpd *prxpd;
int need_padding;
- unsigned int flags;
struct ieee80211_hdr *hdr;
lbtf_deb_enter(LBTF_DEB_RX);
+ if (priv->radioon != RADIO_ON) {
+ lbtf_deb_rx("rx before we turned on the radio");
+ goto done;
+ }
+
prxpd = (struct rxpd *) skb->data;
memset(&stats, 0, sizeof(stats));
@@ -563,7 +510,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
stats.freq = priv->cur_freq;
stats.band = NL80211_BAND_2GHZ;
- stats.signal = prxpd->snr;
+ stats.signal = prxpd->snr - prxpd->nf;
priv->noise = prxpd->nf;
/* Marvell rate index has a hole at value 4 */
if (prxpd->rx_rate > 4)
@@ -572,7 +519,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
skb_pull(skb, sizeof(struct rxpd));
hdr = (struct ieee80211_hdr *)skb->data;
- flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
need_padding = ieee80211_is_data_qos(hdr->frame_control);
need_padding ^= ieee80211_has_a4(hdr->frame_control);
@@ -594,19 +540,21 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
ieee80211_rx_irqsafe(priv->hw, skb);
+done:
lbtf_deb_leave(LBTF_DEB_RX);
return 0;
}
EXPORT_SYMBOL_GPL(lbtf_rx);
/**
- * lbtf_add_card: Add and initialize the card, no fw upload yet.
+ * lbtf_add_card: Add and initialize the card.
*
* @card A pointer to card
*
* Returns: pointer to struct lbtf_priv.
*/
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
+ const struct lbtf_ops *ops)
{
struct ieee80211_hw *hw;
struct lbtf_private *priv = NULL;
@@ -623,10 +571,13 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
priv->hw = hw;
priv->card = card;
+ priv->ops = ops;
priv->tx_skb = NULL;
+ priv->radioon = RADIO_OFF;
hw->queues = 1;
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+ ieee80211_hw_set(hw, SIGNAL_DBM);
hw->extra_tx_headroom = sizeof(struct txpd);
memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
@@ -646,9 +597,31 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
INIT_WORK(&priv->tx_work, lbtf_tx_work);
+
+ if (priv->ops->hw_prog_firmware(priv)) {
+ lbtf_deb_usbd(dmdev, "Error programming the firmware\n");
+ priv->ops->hw_reset_device(priv);
+ goto err_init_adapter;
+ }
+
+ eth_broadcast_addr(priv->current_addr);
+ if (lbtf_update_hw_spec(priv))
+ goto err_init_adapter;
+
+ if (priv->fwrelease < LBTF_FW_VER_MIN ||
+ priv->fwrelease > LBTF_FW_VER_MAX) {
+ goto err_init_adapter;
+ }
+
+ /* The firmware seems to start with the radio enabled. Turn it
+ * off before an actual mac80211 start callback is invoked.
+ */
+ lbtf_set_radio_control(priv);
+
if (ieee80211_register_hw(hw))
goto err_init_adapter;
+ dev_info(dmdev, "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
goto done;
err_init_adapter:
@@ -676,7 +649,7 @@ int lbtf_remove_card(struct lbtf_private *priv)
ieee80211_unregister_hw(hw);
ieee80211_free_hw(hw);
- lbtf_deb_leave(LBTF_DEB_MAIN);
+ lbtf_deb_leave(LBTF_DEB_MAIN);
return 0;
}
EXPORT_SYMBOL_GPL(lbtf_remove_card);
diff --git a/drivers/net/wireless/marvell/mwifiex/Kconfig b/drivers/net/wireless/marvell/mwifiex/Kconfig
index 279167ddd293..524fd565cb2a 100644
--- a/drivers/net/wireless/marvell/mwifiex/Kconfig
+++ b/drivers/net/wireless/marvell/mwifiex/Kconfig
@@ -9,7 +9,7 @@ config MWIFIEX
mwifiex.
config MWIFIEX_SDIO
- tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997"
+ tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997"
depends on MWIFIEX && MMC
select FW_LOADER
select WANT_DEV_COREDUMP
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 1467af22e394..c46f0a54a0c7 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -376,11 +376,20 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
struct mwifiex_power_cfg power_cfg;
int dbm = MBM_TO_DBM(mbm);
- if (type == NL80211_TX_POWER_FIXED) {
+ switch (type) {
+ case NL80211_TX_POWER_FIXED:
power_cfg.is_power_auto = 0;
+ power_cfg.is_power_fixed = 1;
power_cfg.power_level = dbm;
- } else {
+ break;
+ case NL80211_TX_POWER_LIMITED:
+ power_cfg.is_power_auto = 0;
+ power_cfg.is_power_fixed = 0;
+ power_cfg.power_level = dbm;
+ break;
+ case NL80211_TX_POWER_AUTOMATIC:
power_cfg.is_power_auto = 1;
+ break;
}
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
@@ -4310,11 +4319,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
wiphy->max_remain_on_channel_duration = 5000;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_AP);
+ if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz;
if (adapter->config_bands & BAND_A)
wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz;
@@ -4374,11 +4385,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
- wiphy->features |= NL80211_FEATURE_HT_IBSS |
- NL80211_FEATURE_INACTIVITY_TIMER |
+ wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER |
NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_NEED_OBSS_SCAN;
+ if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
+ wiphy->features |= NL80211_FEATURE_HT_IBSS;
+
if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info))
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index cbe4493b3266..8ab114cf3467 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -922,9 +922,8 @@ mwifiex_reset_write(struct file *file,
}
#define MWIFIEX_DFS_ADD_FILE(name) do { \
- if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \
- priv, &mwifiex_dfs_##name##_fops)) \
- return; \
+ debugfs_create_file(#name, 0644, priv->dfs_dev_dir, priv, \
+ &mwifiex_dfs_##name##_fops); \
} while (0);
#define MWIFIEX_DFS_FILE_OPS(name) \
diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h
index 48e154e1865d..0dd592ea6e83 100644
--- a/drivers/net/wireless/marvell/mwifiex/ioctl.h
+++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h
@@ -267,6 +267,7 @@ struct mwifiex_ds_encrypt_key {
struct mwifiex_power_cfg {
u32 is_power_auto;
+ u32 is_power_fixed;
u32 power_level;
};
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index d49fbd58afa7..a85648342d15 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -489,6 +489,8 @@ static void mwifiex_sdio_coredump(struct device *dev)
#define SDIO_DEVICE_ID_MARVELL_8887 (0x9135)
/* Device ID for SD8801 */
#define SDIO_DEVICE_ID_MARVELL_8801 (0x9139)
+/* Device ID for SD8977 */
+#define SDIO_DEVICE_ID_MARVELL_8977 (0x9145)
/* Device ID for SD8997 */
#define SDIO_DEVICE_ID_MARVELL_8997 (0x9141)
@@ -507,6 +509,8 @@ static const struct sdio_device_id mwifiex_ids[] = {
.driver_data = (unsigned long)&mwifiex_sdio_sd8887},
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801),
.driver_data = (unsigned long)&mwifiex_sdio_sd8801},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8977),
+ .driver_data = (unsigned long)&mwifiex_sdio_sd8977},
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997),
.driver_data = (unsigned long)&mwifiex_sdio_sd8997},
{},
@@ -2726,4 +2730,5 @@ MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8977_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index dccf7fd1aef3..912de2cde8d9 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -36,6 +36,7 @@
#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
+#define SD8977_DEFAULT_FW_NAME "mrvl/sd8977_uapsta.bin"
#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin"
#define BLOCK_MODE 1
@@ -371,6 +372,59 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
0x59, 0x5c, 0x5d},
};
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8977 = {
+ .start_rd_port = 0,
+ .start_wr_port = 0,
+ .base_0_reg = 0xF8,
+ .base_1_reg = 0xF9,
+ .poll_reg = 0x5C,
+ .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+ CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+ .host_int_rsr_reg = 0x4,
+ .host_int_status_reg = 0x0C,
+ .host_int_mask_reg = 0x08,
+ .status_reg_0 = 0xE8,
+ .status_reg_1 = 0xE9,
+ .sdio_int_mask = 0xff,
+ .data_port_mask = 0xffffffff,
+ .io_port_0_reg = 0xE4,
+ .io_port_1_reg = 0xE5,
+ .io_port_2_reg = 0xE6,
+ .max_mp_regs = 196,
+ .rd_bitmap_l = 0x10,
+ .rd_bitmap_u = 0x11,
+ .rd_bitmap_1l = 0x12,
+ .rd_bitmap_1u = 0x13,
+ .wr_bitmap_l = 0x14,
+ .wr_bitmap_u = 0x15,
+ .wr_bitmap_1l = 0x16,
+ .wr_bitmap_1u = 0x17,
+ .rd_len_p0_l = 0x18,
+ .rd_len_p0_u = 0x19,
+ .card_misc_cfg_reg = 0xd8,
+ .card_cfg_2_1_reg = 0xd9,
+ .cmd_rd_len_0 = 0xc0,
+ .cmd_rd_len_1 = 0xc1,
+ .cmd_rd_len_2 = 0xc2,
+ .cmd_rd_len_3 = 0xc3,
+ .cmd_cfg_0 = 0xc4,
+ .cmd_cfg_1 = 0xc5,
+ .cmd_cfg_2 = 0xc6,
+ .cmd_cfg_3 = 0xc7,
+ .fw_dump_host_ready = 0xcc,
+ .fw_dump_ctrl = 0xf0,
+ .fw_dump_start = 0xf1,
+ .fw_dump_end = 0xf8,
+ .func1_dump_reg_start = 0x10,
+ .func1_dump_reg_end = 0x17,
+ .func1_scratch_reg = 0xe8,
+ .func1_spec_reg_num = 13,
+ .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D,
+ 0x60, 0x61, 0x62, 0x64,
+ 0x65, 0x66, 0x68, 0x69,
+ 0x6a},
+};
+
static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = {
.start_rd_port = 0,
.start_wr_port = 0,
@@ -532,6 +586,22 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
.can_ext_scan = true,
};
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8977 = {
+ .firmware = SD8977_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_sd8977,
+ .max_ports = 32,
+ .mp_agg_pkt_limit = 16,
+ .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+ .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+ .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+ .supports_sdio_new_mode = true,
+ .has_control_mask = false,
+ .can_dump_fw = true,
+ .fw_dump_enh = true,
+ .can_auto_tdls = false,
+ .can_ext_scan = true,
+};
+
static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
.firmware = SD8997_DEFAULT_FW_NAME,
.reg = &mwifiex_reg_sd8997,
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
index b454b5f85503..ebc0e41e5d3b 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -688,6 +688,9 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf;
txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
if (!power_cfg->is_power_auto) {
+ u16 dbm_min = power_cfg->is_power_fixed ?
+ dbm : priv->min_tx_power_level;
+
txp_cfg->mode = cpu_to_le32(1);
pg_tlv = (struct mwifiex_types_power_group *)
(buf + sizeof(struct host_cmd_ds_txpwr_cfg));
@@ -702,7 +705,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
pg->last_rate_code = 0x03;
pg->modulation_class = MOD_CLASS_HR_DSSS;
pg->power_step = 0;
- pg->power_min = (s8) dbm;
+ pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg++;
/* Power group for modulation class OFDM */
@@ -710,7 +713,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
pg->last_rate_code = 0x07;
pg->modulation_class = MOD_CLASS_OFDM;
pg->power_step = 0;
- pg->power_min = (s8) dbm;
+ pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg++;
/* Power group for modulation class HTBW20 */
@@ -718,7 +721,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
pg->last_rate_code = 0x20;
pg->modulation_class = MOD_CLASS_HT;
pg->power_step = 0;
- pg->power_min = (s8) dbm;
+ pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg->ht_bandwidth = HT_BW_20;
pg++;
@@ -727,7 +730,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
pg->last_rate_code = 0x20;
pg->modulation_class = MOD_CLASS_HT;
pg->power_step = 0;
- pg->power_min = (s8) dbm;
+ pg->power_min = (s8) dbm_min;
pg->power_max = (s8) dbm;
pg->ht_bandwidth = HT_BW_40;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c
index e86217a6b9ca..ca759d9c0253 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c
@@ -300,7 +300,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
break;
case EVENT_BT_COEX_WLAN_PARA_CHANGE:
- dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
+ mwifiex_dbg(adapter, EVENT, "event: BT coex wlan param update\n");
mwifiex_bt_coex_wlan_param_update_event(priv,
adapter->event_skb);
break;
diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig
index c30d8f5bbf2a..dbe8c70a8f73 100644
--- a/drivers/net/wireless/mediatek/mt76/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/Kconfig
@@ -21,3 +21,4 @@ config MT76x02_USB
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
+source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig"
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
index 1a45cb30f39f..3fd1b64b4aa7 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -4,9 +4,10 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o
mt76-y := \
- mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o
+ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
+ tx.o agg-rx.o mcu.o
-mt76-usb-y := usb.o usb_trace.o usb_mcu.o
+mt76-usb-y := usb.o usb_trace.o
CFLAGS_trace.o := -I$(src)
CFLAGS_usb_trace.o := -I$(src)
@@ -21,3 +22,4 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
+obj-$(CONFIG_MT7603E) += mt7603/
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index e2ba26378575..6eedc0ec7661 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -242,6 +242,30 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
iowrite32(q->head, &q->regs->cpu_idx);
}
+static int
+mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,
+ struct sk_buff *skb, u32 tx_info)
+{
+ struct mt76_queue *q = &dev->q_tx[qid];
+ struct mt76_queue_buf buf;
+ dma_addr_t addr;
+
+ addr = dma_map_single(dev->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev->dev, addr))
+ return -ENOMEM;
+
+ buf.addr = addr;
+ buf.len = skb->len;
+
+ spin_lock_bh(&q->lock);
+ mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
+ mt76_dma_kick_queue(dev, q);
+ spin_unlock_bh(&q->lock);
+
+ return 0;
+}
+
int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta)
@@ -300,7 +324,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
if (q->queued + (n + 1) / 2 >= q->ndesc - 1)
goto unmap;
- return dev->queue_ops->add_buf(dev, q, buf, n, tx_info, skb, t);
+ return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t);
unmap:
ret = -ENOMEM;
@@ -318,7 +342,7 @@ free:
EXPORT_SYMBOL_GPL(mt76_dma_tx_queue_skb);
static int
-mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, bool napi)
+mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
{
dma_addr_t addr;
void *buf;
@@ -392,7 +416,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
mt76_dma_rx_cleanup(dev, q);
mt76_dma_sync_idx(dev, q);
- mt76_dma_rx_fill(dev, q, false);
+ mt76_dma_rx_fill(dev, q);
}
static void
@@ -417,10 +441,9 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
static int
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
{
+ int len, data_len, done = 0;
struct sk_buff *skb;
unsigned char *data;
- int len;
- int done = 0;
bool more;
while (done < budget) {
@@ -430,6 +453,19 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
if (!data)
break;
+ if (q->rx_head)
+ data_len = q->buf_size;
+ else
+ data_len = SKB_WITH_OVERHEAD(q->buf_size);
+
+ if (data_len < len + q->buf_offset) {
+ dev_kfree_skb(q->rx_head);
+ q->rx_head = NULL;
+
+ skb_free_frag(data);
+ continue;
+ }
+
if (q->rx_head) {
mt76_add_fragment(dev, q, data, len, more);
continue;
@@ -440,12 +476,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
skb_free_frag(data);
continue;
}
-
skb_reserve(skb, q->buf_offset);
- if (skb->tail + len > skb->end) {
- dev_kfree_skb(skb);
- continue;
- }
if (q == &dev->q_rx[MT_RXQ_MCU]) {
u32 *rxfce = (u32 *) skb->cb;
@@ -463,7 +494,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
dev->drv->rx_skb(dev, q - dev->q_rx, skb);
}
- mt76_dma_rx_fill(dev, q, true);
+ mt76_dma_rx_fill(dev, q);
return done;
}
@@ -504,7 +535,7 @@ mt76_dma_init(struct mt76_dev *dev)
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
64);
- mt76_dma_rx_fill(dev, &dev->q_rx[i], false);
+ mt76_dma_rx_fill(dev, &dev->q_rx[i]);
skb_queue_head_init(&dev->rx_skb[i]);
napi_enable(&dev->napi[i]);
}
@@ -515,17 +546,16 @@ mt76_dma_init(struct mt76_dev *dev)
static const struct mt76_queue_ops mt76_dma_ops = {
.init = mt76_dma_init,
.alloc = mt76_dma_alloc_queue,
- .add_buf = mt76_dma_add_buf,
+ .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
.tx_queue_skb = mt76_dma_tx_queue_skb,
.tx_cleanup = mt76_dma_tx_cleanup,
.rx_reset = mt76_dma_rx_reset,
.kick = mt76_dma_kick_queue,
};
-int mt76_dma_attach(struct mt76_dev *dev)
+void mt76_dma_attach(struct mt76_dev *dev)
{
dev->queue_ops = &mt76_dma_ops;
- return 0;
}
EXPORT_SYMBOL_GPL(mt76_dma_attach);
diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h
index 357cc356342d..e3292df5e9b2 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.h
+++ b/drivers/net/wireless/mediatek/mt76/dma.h
@@ -54,7 +54,7 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP,
};
-int mt76_dma_attach(struct mt76_dev *dev);
+void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 530e5593765c..a1529920d877 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -54,22 +54,30 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len)
part = np->name;
mtd = get_mtd_device_nm(part);
- if (IS_ERR(mtd))
- return PTR_ERR(mtd);
+ if (IS_ERR(mtd)) {
+ ret = PTR_ERR(mtd);
+ goto out_put_node;
+ }
- if (size <= sizeof(*list))
- return -EINVAL;
+ if (size <= sizeof(*list)) {
+ ret = -EINVAL;
+ goto out_put_node;
+ }
offset = be32_to_cpup(list);
ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
put_mtd_device(mtd);
if (ret)
- return ret;
+ goto out_put_node;
- if (retlen < len)
- return -EINVAL;
+ if (retlen < len) {
+ ret = -EINVAL;
+ goto out_put_node;
+ }
- return 0;
+out_put_node:
+ of_node_put(np);
+ return ret;
#else
return -ENOENT;
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 7b926dfa6b97..a033745adb2f 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev,
bool vht)
{
struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
- int i, nstream = __sw_hweight8(dev->antenna_mask);
+ int i, nstream = hweight8(dev->antenna_mask);
struct ieee80211_sta_vht_cap *vht_cap;
u16 mcs_map = 0;
@@ -269,7 +269,9 @@ mt76_check_sband(struct mt76_dev *dev, int band)
}
struct mt76_dev *
-mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops)
+mt76_alloc_device(struct device *pdev, unsigned int size,
+ const struct ieee80211_ops *ops,
+ const struct mt76_driver_ops *drv_ops)
{
struct ieee80211_hw *hw;
struct mt76_dev *dev;
@@ -280,6 +282,9 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops)
dev = hw->priv;
dev->hw = hw;
+ dev->dev = pdev;
+ dev->drv = drv_ops;
+
spin_lock_init(&dev->rx_lock);
spin_lock_init(&dev->lock);
spin_lock_init(&dev->cc_lock);
@@ -328,6 +333,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, AP_LINK_PS);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
+ ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -547,7 +553,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
}
static void
-mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
+mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -566,6 +572,11 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv);
+ if (status->signal <= 0)
+ ewma_signal_add(&wcid->rssi, -status->signal);
+
+ wcid->inactive_count = 0;
+
if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
return;
@@ -625,7 +636,7 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
__skb_queue_head_init(&frames);
while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
- mt76_check_ps(dev, skb);
+ mt76_check_sta(dev, skb);
mt76_rx_aggr_reorder(skb, &frames);
}
@@ -659,6 +670,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
mt76_txq_init(dev, sta->txq[i]);
}
+ ewma_signal_init(&wcid->rssi);
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
out:
@@ -702,6 +714,11 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
new_state == IEEE80211_STA_NONE)
return mt76_sta_add(dev, vif, sta);
+ if (old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC &&
+ dev->drv->sta_assoc)
+ dev->drv->sta_assoc(dev, vif, sta);
+
if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)
mt76_sta_remove(dev, vif, sta);
@@ -709,3 +726,60 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return 0;
}
EXPORT_SYMBOL_GPL(mt76_sta_state);
+
+int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ int *dbm)
+{
+ struct mt76_dev *dev = hw->priv;
+ int n_chains = hweight8(dev->antenna_mask);
+
+ *dbm = dev->txpower_cur / 2;
+
+ /* convert from per-chain power to combined
+ * output on 2x2 devices
+ */
+ if (n_chains > 1)
+ *dbm += 3;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_get_txpower);
+
+static void
+__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ if (vif->csa_active && ieee80211_csa_is_complete(vif))
+ ieee80211_csa_finish(vif);
+}
+
+void mt76_csa_finish(struct mt76_dev *dev)
+{
+ if (!dev->csa_complete)
+ return;
+
+ ieee80211_iterate_active_interfaces_atomic(dev->hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ __mt76_csa_finish, dev);
+
+ dev->csa_complete = 0;
+}
+EXPORT_SYMBOL_GPL(mt76_csa_finish);
+
+static void
+__mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct mt76_dev *dev = priv;
+
+ if (!vif->csa_active)
+ return;
+
+ dev->csa_complete |= ieee80211_csa_is_complete(vif);
+}
+
+void mt76_csa_check(struct mt76_dev *dev)
+{
+ ieee80211_iterate_active_interfaces_atomic(dev->hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ __mt76_csa_check, dev);
+}
+EXPORT_SYMBOL_GPL(mt76_csa_check);
diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c
new file mode 100644
index 000000000000..dbb57b593a87
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mcu.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mt76.h"
+
+struct sk_buff *
+mt76_mcu_msg_alloc(const void *data, int head_len,
+ int data_len, int tail_len)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(head_len + data_len + tail_len,
+ GFP_KERNEL);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, head_len);
+ if (data && data_len)
+ skb_put_data(skb, data, data_len);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc);
+
+/* mmio */
+struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
+ unsigned long expires)
+{
+ unsigned long timeout;
+
+ if (!time_is_after_jiffies(expires))
+ return NULL;
+
+ timeout = expires - jiffies;
+ wait_event_timeout(dev->mmio.mcu.wait,
+ !skb_queue_empty(&dev->mmio.mcu.res_q),
+ timeout);
+ return skb_dequeue(&dev->mmio.mcu.res_q);
+}
+EXPORT_SYMBOL_GPL(mt76_mcu_get_response);
+
+void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb)
+{
+ skb_queue_tail(&dev->mmio.mcu.res_q, skb);
+ wake_up(&dev->mmio.mcu.wait);
+}
+EXPORT_SYMBOL_GPL(mt76_mcu_rx_event);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 5cd508a68609..5dfb0601f101 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -23,6 +23,7 @@
#include <linux/skbuff.h>
#include <linux/leds.h>
#include <linux/usb.h>
+#include <linux/average.h>
#include <net/mac80211.h>
#include "util.h"
@@ -86,6 +87,7 @@ struct mt76u_buf {
struct mt76_dev *dev;
struct urb *urb;
size_t len;
+ void *buf;
bool done;
};
@@ -156,6 +158,9 @@ struct mt76_queue_ops {
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta);
+ int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid,
+ struct sk_buff *skb, u32 tx_info);
+
void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
int *len, u32 *info, bool *more);
@@ -174,6 +179,8 @@ enum mt76_wcid_flags {
#define MT76_N_WCIDS 128
+DECLARE_EWMA(signal, 10, 8);
+
struct mt76_wcid {
struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS];
@@ -181,6 +188,9 @@ struct mt76_wcid {
unsigned long flags;
+ struct ewma_signal rssi;
+ int inactive_count;
+
u8 idx;
u8 hw_key_idx;
@@ -239,7 +249,9 @@ struct mt76_rx_tid {
#define MT_TX_CB_TXS_FAILED BIT(2)
#define MT_PACKET_ID_MASK GENMASK(7, 0)
-#define MT_PACKET_ID_NO_ACK MT_PACKET_ID_MASK
+#define MT_PACKET_ID_NO_ACK 0
+#define MT_PACKET_ID_NO_SKB 1
+#define MT_PACKET_ID_FIRST 2
#define MT_TX_STATUS_SKB_TIMEOUT HZ
@@ -292,6 +304,9 @@ struct mt76_driver_ops {
int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+ void (*sta_assoc)(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+
void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
};
@@ -368,11 +383,11 @@ struct mt76_usb {
u16 out_max_packet;
u8 in_ep[__MT_EP_IN_MAX];
u16 in_max_packet;
+ bool sg_en;
struct mt76u_mcu {
struct mutex mutex;
- struct completion cmpl;
- struct mt76u_buf res;
+ u8 *data;
u32 msg_seq;
/* multiple reads */
@@ -421,6 +436,7 @@ struct mt76_dev {
struct mt76_queue q_tx[__MT_TXQ_MAX];
struct mt76_queue q_rx[__MT_RXQ_MAX];
const struct mt76_queue_ops *queue_ops;
+ int tx_dma_idx[4];
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
@@ -454,6 +470,8 @@ struct mt76_dev {
bool led_al;
u8 led_pin;
+ u8 csa_complete;
+
u32 rxfilter;
union {
@@ -488,7 +506,7 @@ struct mt76_rx_status {
u8 rate_idx;
u8 nss;
u8 band;
- u8 signal;
+ s8 signal;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
};
@@ -551,7 +569,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
#define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76))
#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__)
-#define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__)
+#define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
@@ -571,8 +589,9 @@ mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c)
return &msband->chan[idx];
}
-struct mt76_dev *mt76_alloc_device(unsigned int size,
- const struct ieee80211_ops *ops);
+struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
+ const struct ieee80211_ops *ops,
+ const struct mt76_driver_ops *drv_ops);
int mt76_register_device(struct mt76_dev *dev, bool vht,
struct ieee80211_rate *rates, int n_rates);
void mt76_unregister_device(struct mt76_dev *dev);
@@ -677,6 +696,14 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
+int mt76_get_min_avg_rssi(struct mt76_dev *dev);
+
+int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ int *dbm);
+
+void mt76_csa_check(struct mt76_dev *dev);
+void mt76_csa_finish(struct mt76_dev *dev);
+
/* internal */
void mt76_tx_free(struct mt76_dev *dev);
struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
@@ -703,14 +730,21 @@ static inline u8 q2ep(u8 qid)
return qid + 1;
}
-static inline bool mt76u_check_sg(struct mt76_dev *dev)
+static inline int
+mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+ int timeout)
{
struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf);
+ struct mt76_usb *usb = &dev->usb;
+ unsigned int pipe;
+
+ if (actual_len)
+ pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]);
+ else
+ pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
- return (udev->bus->sg_tablesize > 0 &&
- (udev->bus->no_sg_constraint ||
- udev->speed == USB_SPEED_WIRELESS));
+ return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
@@ -719,21 +753,17 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
const u16 offset, const u32 val);
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
-void mt76u_deinit(struct mt76_dev *dev);
-int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
- int nsgs, int len, int sglen, gfp_t gfp);
-void mt76u_buf_free(struct mt76u_buf *buf);
-int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
- struct mt76u_buf *buf, gfp_t gfp,
- usb_complete_t complete_fn, void *context);
int mt76u_submit_rx_buffers(struct mt76_dev *dev);
int mt76u_alloc_queues(struct mt76_dev *dev);
void mt76u_stop_queues(struct mt76_dev *dev);
void mt76u_stop_stat_wk(struct mt76_dev *dev);
void mt76u_queues_deinit(struct mt76_dev *dev);
-void mt76u_mcu_complete_urb(struct urb *urb);
-int mt76u_mcu_init_rx(struct mt76_dev *dev);
-void mt76u_mcu_deinit(struct mt76_dev *dev);
+struct sk_buff *
+mt76_mcu_msg_alloc(const void *data, int head_len,
+ int data_len, int tail_len);
+void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
+struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
+ unsigned long expires);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
new file mode 100644
index 000000000000..087945c3d8f3
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
@@ -0,0 +1,9 @@
+config MT7603E
+ tristate "MediaTek MT7603E (PCIe) and MT76x8 WLAN support"
+ select MT76_CORE
+ depends on MAC80211
+ depends on PCI
+ help
+ This adds support for MT7603E wireless PCIe devices and the WLAN core on
+ MT7628/MT7688 SoC devices
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Makefile b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile
new file mode 100644
index 000000000000..d95a30421c62
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_MT7603E) += mt7603e.o
+
+mt7603e-y := \
+ pci.o soc.o main.o init.o mcu.o \
+ core.o dma.o mac.o eeprom.o \
+ beacon.o debugfs.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
new file mode 100644
index 000000000000..afcd86f735b4
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7603.h"
+
+struct beacon_bc_data {
+ struct mt7603_dev *dev;
+ struct sk_buff_head q;
+ struct sk_buff *tail[MT7603_MAX_INTERFACES];
+ int count[MT7603_MAX_INTERFACES];
+};
+
+static void
+mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct mt7603_dev *dev = (struct mt7603_dev *)priv;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct sk_buff *skb = NULL;
+
+ if (!(dev->beacon_mask & BIT(mvif->idx)))
+ return;
+
+ skb = ieee80211_beacon_get(mt76_hw(dev), vif);
+ if (!skb)
+ return;
+
+ mt76_dma_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb,
+ &mvif->sta.wcid, NULL);
+
+ spin_lock_bh(&dev->ps_lock);
+ mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+ FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
+ FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
+ dev->mt76.q_tx[MT_TXQ_CAB].hw_idx) |
+ FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
+ FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
+
+ if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
+ dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
+
+ spin_unlock_bh(&dev->ps_lock);
+}
+
+static void
+mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct beacon_bc_data *data = priv;
+ struct mt7603_dev *dev = data->dev;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct ieee80211_tx_info *info;
+ struct sk_buff *skb;
+
+ if (!(dev->beacon_mask & BIT(mvif->idx)))
+ return;
+
+ skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
+ if (!skb)
+ return;
+
+ info = IEEE80211_SKB_CB(skb);
+ info->control.vif = vif;
+ info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
+ mt76_skb_set_moredata(skb, true);
+ __skb_queue_tail(&data->q, skb);
+ data->tail[mvif->idx] = skb;
+ data->count[mvif->idx]++;
+}
+
+void mt7603_pre_tbtt_tasklet(unsigned long arg)
+{
+ struct mt7603_dev *dev = (struct mt7603_dev *)arg;
+ struct mt76_queue *q;
+ struct beacon_bc_data data = {};
+ struct sk_buff *skb;
+ int i, nframes;
+
+ data.dev = dev;
+ __skb_queue_head_init(&data.q);
+
+ q = &dev->mt76.q_tx[MT_TXQ_BEACON];
+ spin_lock_bh(&q->lock);
+ ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7603_update_beacon_iter, dev);
+ mt76_queue_kick(dev, q);
+ spin_unlock_bh(&q->lock);
+
+ /* Flush all previous CAB queue packets */
+ mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
+
+ mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false);
+
+ mt76_csa_check(&dev->mt76);
+ if (dev->mt76.csa_complete)
+ goto out;
+
+ q = &dev->mt76.q_tx[MT_TXQ_CAB];
+ do {
+ nframes = skb_queue_len(&data.q);
+ ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7603_add_buffered_bc, &data);
+ } while (nframes != skb_queue_len(&data.q) &&
+ skb_queue_len(&data.q) < 8);
+
+ if (skb_queue_empty(&data.q))
+ goto out;
+
+ for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
+ if (!data.tail[i])
+ continue;
+
+ mt76_skb_set_moredata(data.tail[i], false);
+ }
+
+ spin_lock_bh(&q->lock);
+ while ((skb = __skb_dequeue(&data.q)) != NULL) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+
+ mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid,
+ NULL);
+ }
+ mt76_queue_kick(dev, q);
+ spin_unlock_bh(&q->lock);
+
+ for (i = 0; i < ARRAY_SIZE(data.count); i++)
+ mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i),
+ data.count[i] << MT_WF_ARB_CAB_COUNT_B0_SHIFT(i));
+
+ mt76_wr(dev, MT_WF_ARB_CAB_START,
+ MT_WF_ARB_CAB_START_BSSn(0) |
+ (MT_WF_ARB_CAB_START_BSS0n(1) *
+ ((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
+
+out:
+ mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
+ if (dev->mt76.q_tx[MT_TXQ_BEACON].queued >
+ __sw_hweight8(dev->beacon_mask))
+ dev->beacon_check++;
+}
+
+void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
+{
+ u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64;
+
+ if (idx >= 0) {
+ if (intval)
+ dev->beacon_mask |= BIT(idx);
+ else
+ dev->beacon_mask &= ~BIT(idx);
+ }
+
+ if (!dev->beacon_mask || (!intval && idx < 0)) {
+ mt7603_irq_disable(dev, MT_INT_MAC_IRQ3);
+ mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK);
+ mt76_wr(dev, MT_HW_INT_MASK(3), 0);
+ return;
+ }
+
+ dev->beacon_int = intval;
+ mt76_wr(dev, MT_TBTT,
+ FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
+
+ mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */
+
+ mt76_rmw_field(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK,
+ MT_BCNQ_OPMODE_AP);
+ mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCN_PRIO);
+ mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCAST_PRIO);
+
+ mt76_wr(dev, MT_PRE_TBTT, pre_tbtt);
+
+ mt76_set(dev, MT_HW_INT_MASK(3),
+ MT_HW_INT3_PRE_TBTT0 | MT_HW_INT3_TBTT0);
+
+ mt76_set(dev, MT_WF_ARB_BCN_START,
+ MT_WF_ARB_BCN_START_BSSn(0) |
+ ((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1)));
+ mt7603_irq_enable(dev, MT_INT_MAC_IRQ3);
+
+ if (dev->beacon_mask & ~BIT(0))
+ mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
+ else
+ mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
new file mode 100644
index 000000000000..1086dcd376a0
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7603.h"
+
+void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags);
+ dev->mt76.mmio.irqmask &= ~clear;
+ dev->mt76.mmio.irqmask |= set;
+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
+ spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags);
+}
+
+void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+
+ mt7603_irq_enable(dev, MT_INT_RX_DONE(q));
+}
+
+irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
+{
+ struct mt7603_dev *dev = dev_instance;
+ u32 intr;
+
+ intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
+ mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+
+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
+ return IRQ_NONE;
+
+ intr &= dev->mt76.mmio.irqmask;
+
+ if (intr & MT_INT_MAC_IRQ3) {
+ u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3));
+
+ mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr);
+ if (hwintr & MT_HW_INT3_PRE_TBTT0)
+ tasklet_schedule(&dev->pre_tbtt_tasklet);
+
+ if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete)
+ mt76_csa_finish(&dev->mt76);
+ }
+
+ if (intr & MT_INT_TX_DONE_ALL) {
+ mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL);
+ tasklet_schedule(&dev->tx_tasklet);
+ }
+
+ if (intr & MT_INT_RX_DONE(0)) {
+ mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
+ napi_schedule(&dev->mt76.napi[0]);
+ }
+
+ if (intr & MT_INT_RX_DONE(1)) {
+ mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
+ napi_schedule(&dev->mt76.napi[1]);
+ }
+
+ return IRQ_HANDLED;
+}
+
+u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr)
+{
+ u32 base = addr & GENMASK(31, 19);
+ u32 offset = addr & GENMASK(18, 0);
+
+ dev->bus_ops->wr(&dev->mt76, MT_MCU_PCIE_REMAP_2, base);
+
+ return MT_PCIE_REMAP_BASE_2 + offset;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c
new file mode 100644
index 000000000000..f8b3b6ab6297
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7603.h"
+
+static int
+mt7603_reset_read(struct seq_file *s, void *data)
+{
+ struct mt7603_dev *dev = dev_get_drvdata(s->private);
+ static const char * const reset_cause_str[] = {
+ [RESET_CAUSE_TX_HANG] = "TX hang",
+ [RESET_CAUSE_TX_BUSY] = "TX DMA busy stuck",
+ [RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck",
+ [RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck",
+ [RESET_CAUSE_BEACON_STUCK] = "Beacon stuck",
+ [RESET_CAUSE_MCU_HANG] = "MCU hang",
+ [RESET_CAUSE_RESET_FAILED] = "PSE reset failed",
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reset_cause_str); i++) {
+ if (!reset_cause_str[i])
+ continue;
+
+ seq_printf(s, "%20s: %u\n", reset_cause_str[i],
+ dev->reset_cause[i]);
+ }
+
+ return 0;
+}
+
+static int
+mt7603_radio_read(struct seq_file *s, void *data)
+{
+ struct mt7603_dev *dev = dev_get_drvdata(s->private);
+
+ seq_printf(s, "Sensitivity: %d\n", dev->sensitivity);
+ seq_printf(s, "False CCA: ofdm=%d cck=%d\n",
+ dev->false_cca_ofdm, dev->false_cca_cck);
+
+ return 0;
+}
+
+void mt7603_init_debugfs(struct mt7603_dev *dev)
+{
+ struct dentry *dir;
+
+ dir = mt76_register_debugfs(&dev->mt76);
+ if (!dir)
+ return;
+
+ debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir,
+ mt7603_reset_read);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
+ mt7603_radio_read);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
new file mode 100644
index 000000000000..d69e82c66ab2
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7603.h"
+#include "mac.h"
+#include "../dma.h"
+
+static int
+mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc)
+{
+ int ret;
+
+ q->hw_idx = idx;
+ q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
+ q->ndesc = n_desc;
+
+ ret = mt76_queue_alloc(dev, q);
+ if (ret)
+ return ret;
+
+ mt7603_irq_enable(dev, MT_INT_TX_DONE(idx));
+
+ return 0;
+}
+
+static void
+mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
+{
+ __le32 *txd = (__le32 *)skb->data;
+ struct mt7603_sta *msta;
+ struct mt76_wcid *wcid;
+ int idx;
+ u32 val;
+
+ if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr))
+ goto free;
+
+ val = le32_to_cpu(txd[1]);
+ idx = FIELD_GET(MT_TXD1_WLAN_IDX, val);
+ skb->priority = FIELD_GET(MT_TXD1_TID, val);
+
+ if (idx >= MT7603_WTBL_STA - 1)
+ goto free;
+
+ wcid = rcu_dereference(dev->mt76.wcid[idx]);
+ if (!wcid)
+ goto free;
+
+ msta = container_of(wcid, struct mt7603_sta, wcid);
+ val = le32_to_cpu(txd[0]);
+ skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val));
+
+ spin_lock_bh(&dev->ps_lock);
+ __skb_queue_tail(&msta->psq, skb);
+ if (skb_queue_len(&msta->psq) >= 64) {
+ skb = __skb_dequeue(&msta->psq);
+ dev_kfree_skb(skb);
+ }
+ spin_unlock_bh(&dev->ps_lock);
+ return;
+
+free:
+ dev_kfree_skb(skb);
+}
+
+void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ struct sk_buff *skb)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+ __le32 *end = (__le32 *)&skb->data[skb->len];
+ enum rx_pkt_type type;
+
+ type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
+
+ if (q == MT_RXQ_MCU) {
+ if (type == PKT_TYPE_RX_EVENT)
+ mt76_mcu_rx_event(&dev->mt76, skb);
+ else
+ mt7603_rx_loopback_skb(dev, skb);
+ return;
+ }
+
+ switch (type) {
+ case PKT_TYPE_TXS:
+ for (rxd++; rxd + 5 <= end; rxd += 5)
+ mt7603_mac_add_txs(dev, rxd);
+ dev_kfree_skb(skb);
+ break;
+ case PKT_TYPE_RX_EVENT:
+ mt76_mcu_rx_event(&dev->mt76, skb);
+ return;
+ case PKT_TYPE_NORMAL:
+ if (mt7603_mac_fill_rx(dev, skb) == 0) {
+ mt76_rx(&dev->mt76, q, skb);
+ return;
+ }
+ /* fall through */
+ default:
+ dev_kfree_skb(skb);
+ break;
+ }
+}
+
+static int
+mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc, int bufsize)
+{
+ int ret;
+
+ q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
+ q->ndesc = n_desc;
+ q->buf_size = bufsize;
+
+ ret = mt76_queue_alloc(dev, q);
+ if (ret)
+ return ret;
+
+ mt7603_irq_enable(dev, MT_INT_RX_DONE(idx));
+
+ return 0;
+}
+
+static void
+mt7603_tx_tasklet(unsigned long data)
+{
+ struct mt7603_dev *dev = (struct mt7603_dev *)data;
+ int i;
+
+ dev->tx_dma_check = 0;
+ for (i = MT_TXQ_MCU; i >= 0; i--)
+ mt76_queue_tx_cleanup(dev, i, false);
+
+ mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL);
+}
+
+int mt7603_dma_init(struct mt7603_dev *dev)
+{
+ static const u8 wmm_queue_map[] = {
+ [IEEE80211_AC_BK] = 0,
+ [IEEE80211_AC_BE] = 1,
+ [IEEE80211_AC_VI] = 2,
+ [IEEE80211_AC_VO] = 3,
+ };
+ int ret;
+ int i;
+
+ mt76_dma_attach(&dev->mt76);
+
+ init_waitqueue_head(&dev->mt76.mmio.mcu.wait);
+ skb_queue_head_init(&dev->mt76.mmio.mcu.res_q);
+
+ tasklet_init(&dev->tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev);
+
+ mt76_clear(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_EN |
+ MT_WPDMA_GLO_CFG_RX_DMA_EN |
+ MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
+ MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
+
+ mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
+ mt7603_pse_client_reset(dev);
+
+ for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
+ ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i],
+ wmm_queue_map[i],
+ MT_TX_RING_SIZE);
+ if (ret)
+ return ret;
+ }
+
+ ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
+ MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
+ MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON],
+ MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB],
+ MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
+ MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
+ if (ret)
+ return ret;
+
+ ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
+ MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE);
+ if (ret)
+ return ret;
+
+ mt76_wr(dev, MT_DELAY_INT_CFG, 0);
+ return mt76_init_queues(dev);
+}
+
+void mt7603_dma_cleanup(struct mt7603_dev *dev)
+{
+ mt76_clear(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_EN |
+ MT_WPDMA_GLO_CFG_RX_DMA_EN |
+ MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
+
+ tasklet_kill(&dev->tx_tasklet);
+ mt76_dma_cleanup(&dev->mt76);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
new file mode 100644
index 000000000000..8c120e4461b0
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7603.h"
+#include "eeprom.h"
+
+static int
+mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data)
+{
+ u32 val;
+ int i;
+
+ val = mt76_rr(dev, base + MT_EFUSE_CTRL);
+ val &= ~(MT_EFUSE_CTRL_AIN |
+ MT_EFUSE_CTRL_MODE);
+ val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
+ val |= MT_EFUSE_CTRL_KICK;
+ mt76_wr(dev, base + MT_EFUSE_CTRL, val);
+
+ if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
+ return -ETIMEDOUT;
+
+ udelay(2);
+
+ val = mt76_rr(dev, base + MT_EFUSE_CTRL);
+ if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
+ WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
+ memset(data, 0xff, 16);
+ return 0;
+ }
+
+ for (i = 0; i < 4; i++) {
+ val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
+ put_unaligned_le32(val, data + 4 * i);
+ }
+
+ return 0;
+}
+
+static int
+mt7603_efuse_init(struct mt7603_dev *dev)
+{
+ u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE);
+ int len = MT7603_EEPROM_SIZE;
+ void *buf;
+ int ret, i;
+
+ if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY)
+ return 0;
+
+ dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
+ dev->mt76.otp.size = len;
+ if (!dev->mt76.otp.data)
+ return -ENOMEM;
+
+ buf = dev->mt76.otp.data;
+ for (i = 0; i + 16 <= len; i += 16) {
+ ret = mt7603_efuse_read(dev, base, i, buf + i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static bool
+mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
+{
+ if (!efuse[MT_EE_TEMP_SENSOR_CAL])
+ return false;
+
+ if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0)
+ return false;
+
+ if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0)
+ return false;
+
+ if (!efuse[MT_EE_CP_FT_VERSION])
+ return false;
+
+ if (!efuse[MT_EE_XTAL_FREQ_OFFSET])
+ return false;
+
+ if (!efuse[MT_EE_XTAL_WF_RFCAL])
+ return false;
+
+ return true;
+}
+
+static void
+mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
+{
+ static const u8 cal_free_bytes[] = {
+ MT_EE_TEMP_SENSOR_CAL,
+ MT_EE_CP_FT_VERSION,
+ MT_EE_XTAL_FREQ_OFFSET,
+ MT_EE_XTAL_WF_RFCAL,
+ /* Skip for MT7628 */
+ MT_EE_TX_POWER_0_START_2G,
+ MT_EE_TX_POWER_0_START_2G + 1,
+ MT_EE_TX_POWER_1_START_2G,
+ MT_EE_TX_POWER_1_START_2G + 1,
+ };
+ u8 *eeprom = dev->mt76.eeprom.data;
+ int n = ARRAY_SIZE(cal_free_bytes);
+ int i;
+
+ if (!mt7603_has_cal_free_data(dev, efuse))
+ return;
+
+ if (is_mt7628(dev))
+ n -= 4;
+
+ for (i = 0; i < n; i++) {
+ int offset = cal_free_bytes[i];
+
+ eeprom[offset] = efuse[offset];
+ }
+}
+
+static int
+mt7603_eeprom_load(struct mt7603_dev *dev)
+{
+ int ret;
+
+ ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE);
+ if (ret < 0)
+ return ret;
+
+ return mt7603_efuse_init(dev);
+}
+
+static int mt7603_check_eeprom(struct mt76_dev *dev)
+{
+ u16 val = get_unaligned_le16(dev->eeprom.data);
+
+ switch (val) {
+ case 0x7628:
+ case 0x7603:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int mt7603_eeprom_init(struct mt7603_dev *dev)
+{
+ int ret;
+
+ ret = mt7603_eeprom_load(dev);
+ if (ret < 0)
+ return ret;
+
+ if (dev->mt76.otp.data) {
+ if (mt7603_check_eeprom(&dev->mt76) == 0)
+ mt7603_apply_cal_free_data(dev, dev->mt76.otp.data);
+ else
+ memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
+ MT7603_EEPROM_SIZE);
+ }
+
+ dev->mt76.cap.has_2ghz = true;
+ memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
+ ETH_ALEN);
+
+ mt76_eeprom_override(&dev->mt76);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
new file mode 100644
index 000000000000..f27b99b7e359
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: ISC */
+
+#ifndef __MT7603_EEPROM_H
+#define __MT7603_EEPROM_H
+
+#include "mt7603.h"
+
+enum mt7603_eeprom_field {
+ MT_EE_CHIP_ID = 0x000,
+ MT_EE_VERSION = 0x002,
+ MT_EE_MAC_ADDR = 0x004,
+ MT_EE_NIC_CONF_0 = 0x034,
+ MT_EE_NIC_CONF_1 = 0x036,
+ MT_EE_NIC_CONF_2 = 0x042,
+
+ MT_EE_XTAL_TRIM_1 = 0x03a,
+
+ MT_EE_RSSI_OFFSET_2G = 0x046,
+ MT_EE_WIFI_RF_SETTING = 0x048,
+ MT_EE_RSSI_OFFSET_5G = 0x04a,
+
+ MT_EE_TX_POWER_DELTA_BW40 = 0x050,
+ MT_EE_TX_POWER_DELTA_BW80 = 0x052,
+
+ MT_EE_TX_POWER_EXT_PA_5G = 0x054,
+
+ MT_EE_TEMP_SENSOR_CAL = 0x055,
+
+ MT_EE_TX_POWER_0_START_2G = 0x056,
+ MT_EE_TX_POWER_1_START_2G = 0x05c,
+
+ /* used as byte arrays */
+#define MT_TX_POWER_GROUP_SIZE_5G 5
+#define MT_TX_POWER_GROUPS_5G 6
+ MT_EE_TX_POWER_0_START_5G = 0x062,
+
+ MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
+ MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
+
+ MT_EE_TX_POWER_1_START_5G = 0x080,
+
+ MT_EE_TX_POWER_CCK = 0x0a0,
+ MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2,
+ MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4,
+ MT_EE_TX_POWER_OFDM_2G_54M = 0x0a6,
+ MT_EE_TX_POWER_HT_BPSK_QPSK = 0x0a8,
+ MT_EE_TX_POWER_HT_16_64_QAM = 0x0aa,
+ MT_EE_TX_POWER_HT_64_QAM = 0x0ac,
+
+ MT_EE_ELAN_RX_MODE_GAIN = 0x0c0,
+ MT_EE_ELAN_RX_MODE_NF = 0x0c1,
+ MT_EE_ELAN_RX_MODE_P1DB = 0x0c2,
+
+ MT_EE_ELAN_BYPASS_MODE_GAIN = 0x0c3,
+ MT_EE_ELAN_BYPASS_MODE_NF = 0x0c4,
+ MT_EE_ELAN_BYPASS_MODE_P1DB = 0x0c5,
+
+ MT_EE_STEP_NUM_NEG_6_7 = 0x0c6,
+ MT_EE_STEP_NUM_NEG_4_5 = 0x0c8,
+ MT_EE_STEP_NUM_NEG_2_3 = 0x0ca,
+ MT_EE_STEP_NUM_NEG_0_1 = 0x0cc,
+
+ MT_EE_REF_STEP_24G = 0x0ce,
+
+ MT_EE_STEP_NUM_PLUS_1_2 = 0x0d0,
+ MT_EE_STEP_NUM_PLUS_3_4 = 0x0d2,
+ MT_EE_STEP_NUM_PLUS_5_6 = 0x0d4,
+ MT_EE_STEP_NUM_PLUS_7 = 0x0d6,
+
+ MT_EE_CP_FT_VERSION = 0x0f0,
+
+ MT_EE_XTAL_FREQ_OFFSET = 0x0f4,
+ MT_EE_XTAL_TRIM_2_COMP = 0x0f5,
+ MT_EE_XTAL_TRIM_3_COMP = 0x0f6,
+ MT_EE_XTAL_WF_RFCAL = 0x0f7,
+
+ __MT_EE_MAX
+};
+
+enum mt7603_eeprom_source {
+ MT_EE_SRC_PROM,
+ MT_EE_SRC_EFUSE,
+ MT_EE_SRC_FLASH,
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
new file mode 100644
index 000000000000..15cc8f33b34d
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -0,0 +1,578 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/etherdevice.h>
+#include "mt7603.h"
+#include "mac.h"
+#include "eeprom.h"
+
+const struct mt76_driver_ops mt7603_drv_ops = {
+ .txwi_size = MT_TXD_SIZE,
+ .tx_prepare_skb = mt7603_tx_prepare_skb,
+ .tx_complete_skb = mt7603_tx_complete_skb,
+ .rx_skb = mt7603_queue_rx_skb,
+ .rx_poll_complete = mt7603_rx_poll_complete,
+ .sta_ps = mt7603_sta_ps,
+ .sta_add = mt7603_sta_add,
+ .sta_assoc = mt7603_sta_assoc,
+ .sta_remove = mt7603_sta_remove,
+ .update_survey = mt7603_update_channel,
+};
+
+static void
+mt7603_set_tmac_template(struct mt7603_dev *dev)
+{
+ u32 desc[5] = {
+ [1] = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 0xf),
+ [3] = MT_TXD5_SW_POWER_MGMT
+ };
+ u32 addr;
+ int i;
+
+ addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR);
+ addr += MT_CLIENT_TMAC_INFO_TEMPLATE;
+ for (i = 0; i < ARRAY_SIZE(desc); i++)
+ mt76_wr(dev, addr + 4 * i, desc[i]);
+}
+
+static void
+mt7603_dma_sched_init(struct mt7603_dev *dev)
+{
+ int page_size = 128;
+ int page_count;
+ int max_len = 1792;
+ int max_amsdu_pages = 4096 / page_size;
+ int max_mcu_len = 4096;
+ int max_beacon_len = 512 * 4 + max_len;
+ int max_mcast_pages = 4 * max_len / page_size;
+ int reserved_count = 0;
+ int beacon_pages;
+ int mcu_pages;
+ int i;
+
+ page_count = mt76_get_field(dev, MT_PSE_FC_P0,
+ MT_PSE_FC_P0_MAX_QUOTA);
+ beacon_pages = 4 * (max_beacon_len / page_size);
+ mcu_pages = max_mcu_len / page_size;
+
+ mt76_wr(dev, MT_PSE_FRP,
+ FIELD_PREP(MT_PSE_FRP_P0, 7) |
+ FIELD_PREP(MT_PSE_FRP_P1, 6) |
+ FIELD_PREP(MT_PSE_FRP_P2_RQ2, 4));
+
+ mt76_wr(dev, MT_HIGH_PRIORITY_1, 0x55555553);
+ mt76_wr(dev, MT_HIGH_PRIORITY_2, 0x78555555);
+
+ mt76_wr(dev, MT_QUEUE_PRIORITY_1, 0x2b1a096e);
+ mt76_wr(dev, MT_QUEUE_PRIORITY_2, 0x785f4d3c);
+
+ mt76_wr(dev, MT_PRIORITY_MASK, 0xffffffff);
+
+ mt76_wr(dev, MT_SCH_1, page_count | (2 << 28));
+ mt76_wr(dev, MT_SCH_2, max_amsdu_pages);
+
+ for (i = 0; i <= 4; i++)
+ mt76_wr(dev, MT_PAGE_COUNT(i), max_amsdu_pages);
+ reserved_count += 5 * max_amsdu_pages;
+
+ mt76_wr(dev, MT_PAGE_COUNT(5), mcu_pages);
+ reserved_count += mcu_pages;
+
+ mt76_wr(dev, MT_PAGE_COUNT(7), beacon_pages);
+ reserved_count += beacon_pages;
+
+ mt76_wr(dev, MT_PAGE_COUNT(8), max_mcast_pages);
+ reserved_count += max_mcast_pages;
+
+ if (is_mt7603(dev))
+ reserved_count = 0;
+
+ mt76_wr(dev, MT_RSV_MAX_THRESH, page_count - reserved_count);
+
+ if (is_mt7603(dev) && mt76xx_rev(dev) >= MT7603_REV_E2) {
+ mt76_wr(dev, MT_GROUP_THRESH(0),
+ page_count - beacon_pages - mcu_pages);
+ mt76_wr(dev, MT_GROUP_THRESH(1), beacon_pages);
+ mt76_wr(dev, MT_BMAP_0, 0x0080ff5f);
+ mt76_wr(dev, MT_GROUP_THRESH(2), mcu_pages);
+ mt76_wr(dev, MT_BMAP_1, 0x00000020);
+ } else {
+ mt76_wr(dev, MT_GROUP_THRESH(0), page_count);
+ mt76_wr(dev, MT_BMAP_0, 0xffff);
+ }
+
+ mt76_wr(dev, MT_SCH_4, 0);
+
+ for (i = 0; i <= 15; i++)
+ mt76_wr(dev, MT_TXTIME_THRESH(i), 0xfffff);
+
+ mt76_set(dev, MT_SCH_4, BIT(6));
+}
+
+static void
+mt7603_phy_init(struct mt7603_dev *dev)
+{
+ int rx_chains = dev->mt76.antenna_mask;
+ int tx_chains = __sw_hweight8(rx_chains) - 1;
+
+ mt76_rmw(dev, MT_WF_RMAC_RMCR,
+ (MT_WF_RMAC_RMCR_SMPS_MODE |
+ MT_WF_RMAC_RMCR_RX_STREAMS),
+ (FIELD_PREP(MT_WF_RMAC_RMCR_SMPS_MODE, 3) |
+ FIELD_PREP(MT_WF_RMAC_RMCR_RX_STREAMS, rx_chains)));
+
+ mt76_rmw_field(dev, MT_TMAC_TCR, MT_TMAC_TCR_TX_STREAMS,
+ tx_chains);
+
+ dev->agc0 = mt76_rr(dev, MT_AGC(0));
+ dev->agc3 = mt76_rr(dev, MT_AGC(3));
+}
+
+static void
+mt7603_mac_init(struct mt7603_dev *dev)
+{
+ u8 bc_addr[ETH_ALEN];
+ u32 addr;
+ int i;
+
+ mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_0,
+ (MT_AGG_SIZE_LIMIT(0) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(1) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(2) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(3) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT));
+
+ mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_1,
+ (MT_AGG_SIZE_LIMIT(4) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(5) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(6) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) |
+ (MT_AGG_SIZE_LIMIT(7) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT));
+
+ mt76_wr(dev, MT_AGG_LIMIT,
+ FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(3), 24));
+
+ mt76_wr(dev, MT_AGG_LIMIT_1,
+ FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) |
+ FIELD_PREP(MT_AGG_LIMIT_AC(3), 24));
+
+ mt76_wr(dev, MT_AGG_CONTROL,
+ FIELD_PREP(MT_AGG_CONTROL_BAR_RATE, 0x4b) |
+ FIELD_PREP(MT_AGG_CONTROL_CFEND_RATE, 0x69) |
+ MT_AGG_CONTROL_NO_BA_AR_RULE);
+
+ mt76_wr(dev, MT_AGG_RETRY_CONTROL,
+ FIELD_PREP(MT_AGG_RETRY_CONTROL_BAR_LIMIT, 1) |
+ FIELD_PREP(MT_AGG_RETRY_CONTROL_RTS_LIMIT, 15));
+
+ mt76_rmw(dev, MT_DMA_DCR0, ~0xfffc, 4096);
+
+ mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13));
+ mt76_rmw(dev, MT_DMA_TMCFR0, BIT(0) | BIT(1), BIT(13));
+
+ mt76_clear(dev, MT_WF_RMAC_TMR_PA, BIT(31));
+
+ mt76_set(dev, MT_WF_RMACDR, MT_WF_RMACDR_MAXLEN_20BIT);
+ mt76_rmw(dev, MT_WF_RMAC_MAXMINLEN, 0xffffff, 0x19000);
+
+ mt76_wr(dev, MT_WF_RFCR1, 0);
+
+ mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE);
+
+ mt7603_set_tmac_template(dev);
+
+ /* Enable RX group to HIF */
+ addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR);
+ mt76_set(dev, addr + MT_CLIENT_RXINF, MT_CLIENT_RXINF_RXSH_GROUPS);
+
+ /* Enable RX group to MCU */
+ mt76_set(dev, MT_DMA_DCR1, GENMASK(13, 11));
+
+ mt76_rmw_field(dev, MT_AGG_PCR_RTS, MT_AGG_PCR_RTS_PKT_THR, 3);
+ mt76_set(dev, MT_TMAC_PCR, MT_TMAC_PCR_SPE_EN);
+
+ /* include preamble detection in CCA trigger signal */
+ mt76_rmw_field(dev, MT_TXREQ, MT_TXREQ_CCA_SRC_SEL, 2);
+
+ mt76_wr(dev, MT_RXREQ, 4);
+
+ /* Configure all rx packets to HIF */
+ mt76_wr(dev, MT_DMA_RCFR0, 0xc0000000);
+
+ /* Configure MCU txs selection with aggregation */
+ mt76_wr(dev, MT_DMA_TCFR0,
+ FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */
+ MT_DMA_TCFR_TXS_AGGR_COUNT);
+
+ /* Configure HIF txs selection with aggregation */
+ mt76_wr(dev, MT_DMA_TCFR1,
+ FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */
+ MT_DMA_TCFR_TXS_AGGR_COUNT | /* Maximum count */
+ MT_DMA_TCFR_TXS_BIT_MAP);
+
+ mt76_wr(dev, MT_MCU_PCIE_REMAP_1, MT_PSE_WTBL_2_PHYS_ADDR);
+
+ for (i = 0; i < MT7603_WTBL_SIZE; i++)
+ mt7603_wtbl_clear(dev, i);
+
+ eth_broadcast_addr(bc_addr);
+ mt7603_wtbl_init(dev, MT7603_WTBL_RESERVED, -1, bc_addr);
+ dev->global_sta.wcid.idx = MT7603_WTBL_RESERVED;
+ rcu_assign_pointer(dev->mt76.wcid[MT7603_WTBL_RESERVED],
+ &dev->global_sta.wcid);
+
+ mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2);
+ mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2);
+
+ mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7));
+ mt76_wr(dev, MT_AGG_ARDCR,
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(1),
+ max_t(int, 0, MT7603_RATE_RETRY - 2)) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7603_RATE_RETRY - 1) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7603_RATE_RETRY - 1) |
+ FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7603_RATE_RETRY - 1));
+
+ mt76_wr(dev, MT_AGG_ARCR,
+ (MT_AGG_ARCR_INIT_RATE1 |
+ FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) |
+ MT_AGG_ARCR_RATE_DOWN_RATIO_EN |
+ FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) |
+ FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4)));
+
+ mt76_set(dev, MT_WTBL_RMVTCR, MT_WTBL_RMVTCR_RX_MV_MODE);
+
+ mt76_clear(dev, MT_SEC_SCR, MT_SEC_SCR_MASK_ORDER);
+ mt76_clear(dev, MT_SEC_SCR, BIT(18));
+
+ /* Set secondary beacon time offsets */
+ for (i = 0; i <= 4; i++)
+ mt76_rmw_field(dev, MT_LPON_SBTOR(i), MT_LPON_SBTOR_TIME_OFFSET,
+ (i + 1) * (20 + 4096));
+}
+
+static int
+mt7603_init_hardware(struct mt7603_dev *dev)
+{
+ int i, ret;
+
+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
+
+ ret = mt7603_eeprom_init(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = mt7603_dma_init(dev);
+ if (ret)
+ return ret;
+
+ mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850);
+ mt7603_mac_dma_start(dev);
+ dev->rxfilter = mt76_rr(dev, MT_WF_RFCR);
+ set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
+
+ for (i = 0; i < MT7603_WTBL_SIZE; i++) {
+ mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE |
+ FIELD_PREP(MT_PSE_RTA_TAG_ID, i));
+ mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
+ }
+
+ ret = mt7603_mcu_init(dev);
+ if (ret)
+ return ret;
+
+ mt7603_dma_sched_init(dev);
+ mt7603_mcu_set_eeprom(dev);
+ mt7603_phy_init(dev);
+ mt7603_mac_init(dev);
+
+ return 0;
+}
+
+#define CCK_RATE(_idx, _rate) { \
+ .bitrate = _rate, \
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
+ .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
+ .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx), \
+}
+
+#define OFDM_RATE(_idx, _rate) { \
+ .bitrate = _rate, \
+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
+}
+
+static struct ieee80211_rate mt7603_rates[] = {
+ CCK_RATE(0, 10),
+ CCK_RATE(1, 20),
+ CCK_RATE(2, 55),
+ CCK_RATE(3, 110),
+ OFDM_RATE(11, 60),
+ OFDM_RATE(15, 90),
+ OFDM_RATE(10, 120),
+ OFDM_RATE(14, 180),
+ OFDM_RATE(9, 240),
+ OFDM_RATE(13, 360),
+ OFDM_RATE(8, 480),
+ OFDM_RATE(12, 540),
+};
+
+static const struct ieee80211_iface_limit if_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_ADHOC)
+ }, {
+ .max = MT7603_MAX_INTERFACES,
+ .types = BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+ BIT(NL80211_IFTYPE_AP)
+ },
+};
+
+static const struct ieee80211_iface_combination if_comb[] = {
+ {
+ .limits = if_limits,
+ .n_limits = ARRAY_SIZE(if_limits),
+ .max_interfaces = 4,
+ .num_different_channels = 1,
+ .beacon_int_infra_match = true,
+ }
+};
+
+static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on,
+ u8 delay_off)
+{
+ struct mt7603_dev *dev = container_of(mt76, struct mt7603_dev,
+ mt76);
+ u32 val, addr;
+
+ val = MT_LED_STATUS_DURATION(0xffff) |
+ MT_LED_STATUS_OFF(delay_off) |
+ MT_LED_STATUS_ON(delay_on);
+
+ addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin));
+ mt76_wr(dev, addr, val);
+ addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin));
+ mt76_wr(dev, addr, val);
+
+ val = MT_LED_CTRL_REPLAY(mt76->led_pin) |
+ MT_LED_CTRL_KICK(mt76->led_pin);
+ if (mt76->led_al)
+ val |= MT_LED_CTRL_POLARITY(mt76->led_pin);
+ addr = mt7603_reg_map(dev, MT_LED_CTRL);
+ mt76_wr(dev, addr, val);
+}
+
+static int mt7603_led_set_blink(struct led_classdev *led_cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
+ led_cdev);
+ u8 delta_on, delta_off;
+
+ delta_off = max_t(u8, *delay_off / 10, 1);
+ delta_on = max_t(u8, *delay_on / 10, 1);
+
+ mt7603_led_set_config(mt76, delta_on, delta_off);
+ return 0;
+}
+
+static void mt7603_led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
+ led_cdev);
+
+ if (!brightness)
+ mt7603_led_set_config(mt76, 0, 0xff);
+ else
+ mt7603_led_set_config(mt76, 0xff, 0);
+}
+
+static u32 __mt7603_reg_addr(struct mt7603_dev *dev, u32 addr)
+{
+ if (addr < 0x100000)
+ return addr;
+
+ return mt7603_reg_map(dev, addr);
+}
+
+static u32 mt7603_rr(struct mt76_dev *mdev, u32 offset)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ u32 addr = __mt7603_reg_addr(dev, offset);
+
+ return dev->bus_ops->rr(mdev, addr);
+}
+
+static void mt7603_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ u32 addr = __mt7603_reg_addr(dev, offset);
+
+ dev->bus_ops->wr(mdev, addr, val);
+}
+
+static u32 mt7603_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ u32 addr = __mt7603_reg_addr(dev, offset);
+
+ return dev->bus_ops->rmw(mdev, addr, mask, val);
+}
+
+static void
+mt7603_regd_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct mt7603_dev *dev = hw->priv;
+
+ dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI;
+}
+
+static int
+mt7603_txpower_signed(int val)
+{
+ bool sign = val & BIT(6);
+
+ if (!(val & BIT(7)))
+ return 0;
+
+ val &= GENMASK(5, 0);
+ if (!sign)
+ val = -val;
+
+ return val;
+}
+
+static void
+mt7603_init_txpower(struct mt7603_dev *dev,
+ struct ieee80211_supported_band *sband)
+{
+ struct ieee80211_channel *chan;
+ u8 *eeprom = (u8 *)dev->mt76.eeprom.data;
+ int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7);
+ u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK];
+ int max_offset, cur_offset;
+ int i;
+
+ if (target_power & BIT(6))
+ target_power = -(target_power & GENMASK(5, 0));
+
+ max_offset = 0;
+ for (i = 0; i < 14; i++) {
+ cur_offset = mt7603_txpower_signed(rate_power[i]);
+ max_offset = max(max_offset, cur_offset);
+ }
+
+ target_power += max_offset;
+
+ dev->tx_power_limit = target_power;
+ dev->mt76.txpower_cur = target_power;
+
+ target_power = DIV_ROUND_UP(target_power, 2);
+
+ /* add 3 dBm for 2SS devices (combined output) */
+ if (dev->mt76.antenna_mask & BIT(1))
+ target_power += 3;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
+ chan->max_power = target_power;
+ }
+}
+
+
+int mt7603_register_device(struct mt7603_dev *dev)
+{
+ struct mt76_bus_ops *bus_ops;
+ struct ieee80211_hw *hw = mt76_hw(dev);
+ struct wiphy *wiphy = hw->wiphy;
+ int ret;
+
+ dev->bus_ops = dev->mt76.bus;
+ bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
+ GFP_KERNEL);
+ if (!bus_ops)
+ return -ENOMEM;
+
+ bus_ops->rr = mt7603_rr;
+ bus_ops->wr = mt7603_wr;
+ bus_ops->rmw = mt7603_rmw;
+ dev->mt76.bus = bus_ops;
+
+ INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work);
+ tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
+ (unsigned long)dev);
+
+ /* Check for 7688, which only has 1SS */
+ dev->mt76.antenna_mask = 3;
+ if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4))
+ dev->mt76.antenna_mask = 1;
+
+ dev->slottime = 9;
+
+ ret = mt7603_init_hardware(dev);
+ if (ret)
+ return ret;
+
+ hw->queues = 4;
+ hw->max_rates = 3;
+ hw->max_report_rates = 7;
+ hw->max_rate_tries = 11;
+
+ hw->sta_data_size = sizeof(struct mt7603_sta);
+ hw->vif_data_size = sizeof(struct mt7603_vif);
+
+ wiphy->iface_combinations = if_comb;
+ wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+
+ ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+ ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
+
+ /* init led callbacks */
+ if (IS_ENABLED(CONFIG_MT76_LEDS)) {
+ dev->mt76.led_cdev.brightness_set = mt7603_led_set_brightness;
+ dev->mt76.led_cdev.blink_set = mt7603_led_set_blink;
+ }
+
+ wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+ BIT(NL80211_IFTYPE_ADHOC);
+
+ wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
+ wiphy->reg_notifier = mt7603_regd_notifier;
+
+ ret = mt76_register_device(&dev->mt76, true, mt7603_rates,
+ ARRAY_SIZE(mt7603_rates));
+ if (ret)
+ return ret;
+
+ mt7603_init_debugfs(dev);
+ mt7603_init_txpower(dev, &dev->mt76.sband_2g.sband);
+
+ return 0;
+}
+
+void mt7603_unregister_device(struct mt7603_dev *dev)
+{
+ tasklet_disable(&dev->pre_tbtt_tasklet);
+ mt76_unregister_device(&dev->mt76);
+ mt7603_mcu_exit(dev);
+ mt7603_dma_cleanup(dev);
+ ieee80211_free_hw(mt76_hw(dev));
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
new file mode 100644
index 000000000000..0a0115861b51
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -0,0 +1,1749 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/etherdevice.h>
+#include <linux/timekeeping.h>
+#include "mt7603.h"
+#include "mac.h"
+
+#define MT_PSE_PAGE_SIZE 128
+
+static u32
+mt7603_ac_queue_mask0(u32 mask)
+{
+ u32 ret = 0;
+
+ ret |= GENMASK(3, 0) * !!(mask & BIT(0));
+ ret |= GENMASK(8, 5) * !!(mask & BIT(1));
+ ret |= GENMASK(13, 10) * !!(mask & BIT(2));
+ ret |= GENMASK(19, 16) * !!(mask & BIT(3));
+ return ret;
+}
+
+static void
+mt76_stop_tx_ac(struct mt7603_dev *dev, u32 mask)
+{
+ mt76_set(dev, MT_WF_ARB_TX_STOP_0, mt7603_ac_queue_mask0(mask));
+}
+
+static void
+mt76_start_tx_ac(struct mt7603_dev *dev, u32 mask)
+{
+ mt76_set(dev, MT_WF_ARB_TX_START_0, mt7603_ac_queue_mask0(mask));
+}
+
+void mt7603_mac_set_timing(struct mt7603_dev *dev)
+{
+ u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
+ FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
+ u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
+ FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24);
+ int offset = 3 * dev->coverage_class;
+ u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
+ FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
+ int sifs;
+ u32 val;
+
+ if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ)
+ sifs = 16;
+ else
+ sifs = 10;
+
+ mt76_set(dev, MT_ARB_SCR,
+ MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+ udelay(1);
+
+ mt76_wr(dev, MT_TIMEOUT_CCK, cck + reg_offset);
+ mt76_wr(dev, MT_TIMEOUT_OFDM, ofdm + reg_offset);
+ mt76_wr(dev, MT_IFS,
+ FIELD_PREP(MT_IFS_EIFS, 360) |
+ FIELD_PREP(MT_IFS_RIFS, 2) |
+ FIELD_PREP(MT_IFS_SIFS, sifs) |
+ FIELD_PREP(MT_IFS_SLOT, dev->slottime));
+
+ if (dev->slottime < 20)
+ val = MT7603_CFEND_RATE_DEFAULT;
+ else
+ val = MT7603_CFEND_RATE_11B;
+
+ mt76_rmw_field(dev, MT_AGG_CONTROL, MT_AGG_CONTROL_CFEND_RATE, val);
+
+ mt76_clear(dev, MT_ARB_SCR,
+ MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+}
+
+static void
+mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask)
+{
+ mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
+ FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
+
+ mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+}
+
+static u32
+mt7603_wtbl1_addr(int idx)
+{
+ return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
+}
+
+static u32
+mt7603_wtbl2_addr(int idx)
+{
+ /* Mapped to WTBL2 */
+ return MT_PCIE_REMAP_BASE_1 + idx * MT_WTBL2_SIZE;
+}
+
+static u32
+mt7603_wtbl3_addr(int idx)
+{
+ u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE);
+
+ return base + idx * MT_WTBL3_SIZE;
+}
+
+static u32
+mt7603_wtbl4_addr(int idx)
+{
+ u32 base = mt7603_wtbl3_addr(MT7603_WTBL_SIZE);
+
+ return base + idx * MT_WTBL4_SIZE;
+}
+
+void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif,
+ const u8 *mac_addr)
+{
+ const void *_mac = mac_addr;
+ u32 addr = mt7603_wtbl1_addr(idx);
+ u32 w0 = 0, w1 = 0;
+ int i;
+
+ if (_mac) {
+ w0 = FIELD_PREP(MT_WTBL1_W0_ADDR_HI,
+ get_unaligned_le16(_mac + 4));
+ w1 = FIELD_PREP(MT_WTBL1_W1_ADDR_LO,
+ get_unaligned_le32(_mac));
+ }
+
+ if (vif < 0)
+ vif = 0;
+ else
+ w0 |= MT_WTBL1_W0_RX_CHECK_A1;
+ w0 |= FIELD_PREP(MT_WTBL1_W0_MUAR_IDX, vif);
+
+ mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+
+ mt76_set(dev, addr + 0 * 4, w0);
+ mt76_set(dev, addr + 1 * 4, w1);
+ mt76_set(dev, addr + 2 * 4, MT_WTBL1_W2_ADMISSION_CONTROL);
+
+ mt76_stop_tx_ac(dev, GENMASK(3, 0));
+ addr = mt7603_wtbl2_addr(idx);
+ for (i = 0; i < MT_WTBL2_SIZE; i += 4)
+ mt76_wr(dev, addr + i, 0);
+ mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2);
+ mt76_start_tx_ac(dev, GENMASK(3, 0));
+
+ addr = mt7603_wtbl3_addr(idx);
+ for (i = 0; i < MT_WTBL3_SIZE; i += 4)
+ mt76_wr(dev, addr + i, 0);
+
+ addr = mt7603_wtbl4_addr(idx);
+ for (i = 0; i < MT_WTBL4_SIZE; i += 4)
+ mt76_wr(dev, addr + i, 0);
+}
+
+static void
+mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled)
+{
+ u32 addr = mt7603_wtbl1_addr(idx);
+ u32 val = mt76_rr(dev, addr + 3 * 4);
+
+ val &= ~MT_WTBL1_W3_SKIP_TX;
+ val |= enabled * MT_WTBL1_W3_SKIP_TX;
+
+ mt76_wr(dev, addr + 3 * 4, val);
+}
+
+void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
+{
+ int i, port, queue;
+
+ if (abort) {
+ port = 3; /* PSE */
+ queue = 8; /* free queue */
+ } else {
+ port = 0; /* HIF */
+ queue = 1; /* MCU queue */
+ }
+
+ mt7603_wtbl_set_skip_tx(dev, idx, true);
+
+ mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN |
+ FIELD_PREP(MT_TX_ABORT_WCID, idx));
+
+ for (i = 0; i < 4; i++) {
+ mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+ FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) |
+ FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, i) |
+ FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) |
+ FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue));
+
+ WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY,
+ 0, 5000));
+ }
+
+ mt76_wr(dev, MT_TX_ABORT, 0);
+
+ mt7603_wtbl_set_skip_tx(dev, idx, false);
+}
+
+void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ bool enabled)
+{
+ u32 addr = mt7603_wtbl1_addr(sta->wcid.idx);
+
+ if (sta->smps == enabled)
+ return;
+
+ mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_SMPS, enabled);
+ sta->smps = enabled;
+}
+
+void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ bool enabled)
+{
+ int idx = sta->wcid.idx;
+ u32 addr;
+
+ spin_lock_bh(&dev->ps_lock);
+
+ if (sta->ps == enabled)
+ goto out;
+
+ mt76_wr(dev, MT_PSE_RTA,
+ FIELD_PREP(MT_PSE_RTA_TAG_ID, idx) |
+ FIELD_PREP(MT_PSE_RTA_PORT_ID, 0) |
+ FIELD_PREP(MT_PSE_RTA_QUEUE_ID, 1) |
+ FIELD_PREP(MT_PSE_RTA_REDIRECT_EN, enabled) |
+ MT_PSE_RTA_WRITE | MT_PSE_RTA_BUSY);
+
+ mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
+
+ if (enabled)
+ mt7603_filter_tx(dev, idx, false);
+
+ addr = mt7603_wtbl1_addr(idx);
+ mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
+ mt76_rmw(dev, addr + 3 * 4, MT_WTBL1_W3_POWER_SAVE,
+ enabled * MT_WTBL1_W3_POWER_SAVE);
+ mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
+ sta->ps = enabled;
+
+out:
+ spin_unlock_bh(&dev->ps_lock);
+}
+
+void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx)
+{
+ int wtbl2_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL2_SIZE;
+ int wtbl2_frame = idx / wtbl2_frame_size;
+ int wtbl2_entry = idx % wtbl2_frame_size;
+
+ int wtbl3_base_frame = MT_WTBL3_OFFSET / MT_PSE_PAGE_SIZE;
+ int wtbl3_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL3_SIZE;
+ int wtbl3_frame = wtbl3_base_frame + idx / wtbl3_frame_size;
+ int wtbl3_entry = (idx % wtbl3_frame_size) * 2;
+
+ int wtbl4_base_frame = MT_WTBL4_OFFSET / MT_PSE_PAGE_SIZE;
+ int wtbl4_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL4_SIZE;
+ int wtbl4_frame = wtbl4_base_frame + idx / wtbl4_frame_size;
+ int wtbl4_entry = idx % wtbl4_frame_size;
+
+ u32 addr = MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
+ int i;
+
+ mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+
+ mt76_wr(dev, addr + 0 * 4,
+ MT_WTBL1_W0_RX_CHECK_A1 |
+ MT_WTBL1_W0_RX_CHECK_A2 |
+ MT_WTBL1_W0_RX_VALID);
+ mt76_wr(dev, addr + 1 * 4, 0);
+ mt76_wr(dev, addr + 2 * 4, 0);
+
+ mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
+
+ mt76_wr(dev, addr + 3 * 4,
+ FIELD_PREP(MT_WTBL1_W3_WTBL2_FRAME_ID, wtbl2_frame) |
+ FIELD_PREP(MT_WTBL1_W3_WTBL2_ENTRY_ID, wtbl2_entry) |
+ FIELD_PREP(MT_WTBL1_W3_WTBL4_FRAME_ID, wtbl4_frame) |
+ MT_WTBL1_W3_I_PSM | MT_WTBL1_W3_KEEP_I_PSM);
+ mt76_wr(dev, addr + 4 * 4,
+ FIELD_PREP(MT_WTBL1_W4_WTBL3_FRAME_ID, wtbl3_frame) |
+ FIELD_PREP(MT_WTBL1_W4_WTBL3_ENTRY_ID, wtbl3_entry) |
+ FIELD_PREP(MT_WTBL1_W4_WTBL4_ENTRY_ID, wtbl4_entry));
+
+ mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
+
+ addr = mt7603_wtbl2_addr(idx);
+
+ /* Clear BA information */
+ mt76_wr(dev, addr + (15 * 4), 0);
+
+ mt76_stop_tx_ac(dev, GENMASK(3, 0));
+ for (i = 2; i <= 4; i++)
+ mt76_wr(dev, addr + (i * 4), 0);
+ mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2);
+ mt76_start_tx_ac(dev, GENMASK(3, 0));
+
+ mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_RX_COUNT_CLEAR);
+ mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_TX_COUNT_CLEAR);
+ mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+}
+
+void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta)
+{
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ int idx = msta->wcid.idx;
+ u32 addr;
+ u32 val;
+
+ addr = mt7603_wtbl1_addr(idx);
+
+ val = mt76_rr(dev, addr + 2 * 4);
+ val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL;
+ val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) |
+ FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) |
+ MT_WTBL1_W2_TXS_BAF_REPORT;
+
+ if (sta->ht_cap.cap)
+ val |= MT_WTBL1_W2_HT;
+ if (sta->vht_cap.cap)
+ val |= MT_WTBL1_W2_VHT;
+
+ mt76_wr(dev, addr + 2 * 4, val);
+
+ addr = mt7603_wtbl2_addr(idx);
+ val = mt76_rr(dev, addr + 9 * 4);
+ val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 |
+ MT_WTBL2_W9_SHORT_GI_80);
+ if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
+ val |= MT_WTBL2_W9_SHORT_GI_20;
+ if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
+ val |= MT_WTBL2_W9_SHORT_GI_40;
+ mt76_wr(dev, addr + 9 * 4, val);
+}
+
+void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid)
+{
+ mt76_wr(dev, MT_BA_CONTROL_0, get_unaligned_le32(addr));
+ mt76_wr(dev, MT_BA_CONTROL_1,
+ (get_unaligned_le16(addr + 4) |
+ FIELD_PREP(MT_BA_CONTROL_1_TID, tid) |
+ MT_BA_CONTROL_1_RESET));
+}
+
+void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn,
+ int ba_size)
+{
+ u32 addr = mt7603_wtbl2_addr(wcid);
+ u32 tid_mask = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) |
+ (MT_WTBL2_W15_BA_WIN_SIZE <<
+ (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT));
+ u32 tid_val;
+ int i;
+
+ if (ba_size < 0) {
+ /* disable */
+ mt76_clear(dev, addr + (15 * 4), tid_mask);
+ return;
+ }
+ mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+
+ mt7603_mac_stop(dev);
+ switch (tid) {
+ case 0:
+ mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn);
+ break;
+ case 1:
+ mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn);
+ break;
+ case 2:
+ mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO,
+ ssn);
+ mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI,
+ ssn >> 8);
+ break;
+ case 3:
+ mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn);
+ break;
+ case 4:
+ mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn);
+ break;
+ case 5:
+ mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO,
+ ssn);
+ mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI,
+ ssn >> 4);
+ break;
+ case 6:
+ mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn);
+ break;
+ case 7:
+ mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn);
+ break;
+ }
+ mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2);
+ mt7603_mac_start(dev);
+
+ for (i = 7; i > 0; i--) {
+ if (ba_size >= MT_AGG_SIZE_LIMIT(i))
+ break;
+ }
+
+ tid_val = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) |
+ i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT);
+
+ mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val);
+}
+
+static int
+mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband,
+ int idx, bool cck)
+{
+ int offset = 0;
+ int len = sband->n_bitrates;
+ int i;
+
+ if (cck) {
+ if (sband == &dev->mt76.sband_5g.sband)
+ return 0;
+
+ idx &= ~BIT(2); /* short preamble */
+ } else if (sband == &dev->mt76.sband_2g.sband) {
+ offset = 4;
+ }
+
+ for (i = offset; i < len; i++) {
+ if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx)
+ return i;
+ }
+
+ return 0;
+}
+
+static struct mt76_wcid *
+mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
+{
+ struct mt7603_sta *sta;
+ struct mt76_wcid *wcid;
+
+ if (idx >= ARRAY_SIZE(dev->mt76.wcid))
+ return NULL;
+
+ wcid = rcu_dereference(dev->mt76.wcid[idx]);
+ if (unicast || !wcid)
+ return wcid;
+
+ if (!wcid->sta)
+ return NULL;
+
+ sta = container_of(wcid, struct mt7603_sta, wcid);
+ if (!sta->vif)
+ return NULL;
+
+ return &sta->vif->sta.wcid;
+}
+
+static void
+mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+ u8 *pn = status->iv;
+ u8 *hdr;
+
+ __skb_push(skb, 8);
+ memmove(skb->data, skb->data + 8, hdr_len);
+ hdr = skb->data + hdr_len;
+
+ hdr[0] = pn[5];
+ hdr[1] = pn[4];
+ hdr[2] = 0;
+ hdr[3] = 0x20 | (key_id << 6);
+ hdr[4] = pn[3];
+ hdr[5] = pn[2];
+ hdr[6] = pn[1];
+ hdr[7] = pn[0];
+
+ status->flag &= ~RX_FLAG_IV_STRIPPED;
+}
+
+int
+mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_hdr *hdr;
+ __le32 *rxd = (__le32 *)skb->data;
+ u32 rxd0 = le32_to_cpu(rxd[0]);
+ u32 rxd1 = le32_to_cpu(rxd[1]);
+ u32 rxd2 = le32_to_cpu(rxd[2]);
+ bool unicast = rxd1 & MT_RXD1_NORMAL_U2M;
+ bool insert_ccmp_hdr = false;
+ bool remove_pad;
+ int idx;
+ int i;
+
+ memset(status, 0, sizeof(*status));
+
+ i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);
+ sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband;
+ i >>= 1;
+
+ idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
+ status->wcid = mt7603_rx_get_wcid(dev, idx, unicast);
+
+ status->band = sband->band;
+ if (i < sband->n_channels)
+ status->freq = sband->channels[i].center_freq;
+
+ if (rxd2 & MT_RXD2_NORMAL_FCS_ERR)
+ status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+ if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR)
+ status->flag |= RX_FLAG_MMIC_ERROR;
+
+ if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
+ !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {
+ status->flag |= RX_FLAG_DECRYPTED;
+ status->flag |= RX_FLAG_IV_STRIPPED;
+ status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
+ }
+
+ remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
+
+ if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
+ return -EINVAL;
+
+ if (!sband->channels)
+ return -EINVAL;
+
+ rxd += 4;
+ if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {
+ rxd += 4;
+ if ((u8 *)rxd - skb->data >= skb->len)
+ return -EINVAL;
+ }
+ if (rxd0 & MT_RXD0_NORMAL_GROUP_1) {
+ u8 *data = (u8 *)rxd;
+
+ if (status->flag & RX_FLAG_DECRYPTED) {
+ status->iv[0] = data[5];
+ status->iv[1] = data[4];
+ status->iv[2] = data[3];
+ status->iv[3] = data[2];
+ status->iv[4] = data[1];
+ status->iv[5] = data[0];
+
+ insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+ }
+
+ rxd += 4;
+ if ((u8 *)rxd - skb->data >= skb->len)
+ return -EINVAL;
+ }
+ if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
+ rxd += 2;
+ if ((u8 *)rxd - skb->data >= skb->len)
+ return -EINVAL;
+ }
+ if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {
+ u32 rxdg0 = le32_to_cpu(rxd[0]);
+ u32 rxdg3 = le32_to_cpu(rxd[3]);
+ bool cck = false;
+
+ i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0);
+ switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ /* fall through */
+ case MT_PHY_TYPE_OFDM:
+ i = mt7603_get_rate(dev, sband, i, cck);
+ break;
+ case MT_PHY_TYPE_HT_GF:
+ case MT_PHY_TYPE_HT:
+ status->encoding = RX_ENC_HT;
+ if (i > 15)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rxdg0 & MT_RXV1_HT_SHORT_GI)
+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ if (rxdg0 & MT_RXV1_HT_AD_CODE)
+ status->enc_flags |= RX_ENC_FLAG_LDPC;
+
+ status->enc_flags |= RX_ENC_FLAG_STBC_MASK *
+ FIELD_GET(MT_RXV1_HT_STBC, rxdg0);
+
+ status->rate_idx = i;
+
+ status->chains = dev->mt76.antenna_mask;
+ status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) +
+ dev->rssi_offset[0];
+ status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) +
+ dev->rssi_offset[1];
+
+ status->signal = status->chain_signal[0];
+ if (status->chains & BIT(1))
+ status->signal = max(status->signal,
+ status->chain_signal[1]);
+
+ if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1)
+ status->bw = RATE_INFO_BW_40;
+
+ rxd += 6;
+ if ((u8 *)rxd - skb->data >= skb->len)
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
+
+ if (insert_ccmp_hdr) {
+ u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
+
+ mt7603_insert_ccmp_hdr(skb, key_id);
+ }
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
+ return 0;
+
+ status->aggr = unicast &&
+ !ieee80211_is_qos_nullfunc(hdr->frame_control);
+ status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ status->seqno = hdr->seq_ctrl >> 4;
+
+ return 0;
+}
+
+static u16
+mt7603_mac_tx_rate_val(struct mt7603_dev *dev,
+ const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw)
+{
+ u8 phy, nss, rate_idx;
+ u16 rateval;
+
+ *bw = 0;
+ if (rate->flags & IEEE80211_TX_RC_MCS) {
+ rate_idx = rate->idx;
+ nss = 1 + (rate->idx >> 3);
+ phy = MT_PHY_TYPE_HT;
+ if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+ phy = MT_PHY_TYPE_HT_GF;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ *bw = 1;
+ } else {
+ const struct ieee80211_rate *r;
+ int band = dev->mt76.chandef.chan->band;
+ u16 val;
+
+ nss = 1;
+ r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx];
+ if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ val = r->hw_value_short;
+ else
+ val = r->hw_value;
+
+ phy = val >> 8;
+ rate_idx = val & 0xff;
+ }
+
+ rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) |
+ FIELD_PREP(MT_TX_RATE_MODE, phy));
+
+ if (stbc && nss == 1)
+ rateval |= MT_TX_RATE_STBC;
+
+ return rateval;
+}
+
+void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ struct ieee80211_tx_rate *probe_rate,
+ struct ieee80211_tx_rate *rates)
+{
+ int wcid = sta->wcid.idx;
+ u32 addr = mt7603_wtbl2_addr(wcid);
+ bool stbc = false;
+ int n_rates = sta->n_rates;
+ u8 bw, bw_prev, bw_idx = 0;
+ u16 val[4];
+ u16 probe_val;
+ u32 w9 = mt76_rr(dev, addr + 9 * 4);
+ int i;
+
+ if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))
+ return;
+
+ for (i = n_rates; i < 4; i++)
+ rates[i] = rates[n_rates - 1];
+
+ w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 |
+ MT_WTBL2_W9_SHORT_GI_80;
+
+ val[0] = mt7603_mac_tx_rate_val(dev, &rates[0], stbc, &bw);
+ bw_prev = bw;
+
+ if (probe_rate) {
+ probe_val = mt7603_mac_tx_rate_val(dev, probe_rate, stbc, &bw);
+ if (bw)
+ bw_idx = 1;
+ else
+ bw_prev = 0;
+ } else {
+ probe_val = val[0];
+ }
+
+ w9 |= FIELD_PREP(MT_WTBL2_W9_CC_BW_SEL, bw);
+ w9 |= FIELD_PREP(MT_WTBL2_W9_BW_CAP, bw);
+
+ val[1] = mt7603_mac_tx_rate_val(dev, &rates[1], stbc, &bw);
+ if (bw_prev) {
+ bw_idx = 3;
+ bw_prev = bw;
+ }
+
+ val[2] = mt7603_mac_tx_rate_val(dev, &rates[2], stbc, &bw);
+ if (bw_prev) {
+ bw_idx = 5;
+ bw_prev = bw;
+ }
+
+ val[3] = mt7603_mac_tx_rate_val(dev, &rates[3], stbc, &bw);
+ if (bw_prev)
+ bw_idx = 7;
+
+ w9 |= FIELD_PREP(MT_WTBL2_W9_CHANGE_BW_RATE,
+ bw_idx ? bw_idx - 1 : 7);
+
+ mt76_wr(dev, MT_WTBL_RIUCR0, w9);
+
+ mt76_wr(dev, MT_WTBL_RIUCR1,
+ FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) |
+ FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) |
+ FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0]));
+
+ mt76_wr(dev, MT_WTBL_RIUCR2,
+ FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) |
+ FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) |
+ FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) |
+ FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2]));
+
+ mt76_wr(dev, MT_WTBL_RIUCR3,
+ FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) |
+ FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) |
+ FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3]));
+
+ mt76_wr(dev, MT_WTBL_UPDATE,
+ FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) |
+ MT_WTBL_UPDATE_RATE_UPDATE |
+ MT_WTBL_UPDATE_TX_COUNT_CLEAR);
+
+ if (!sta->wcid.tx_rate_set)
+ mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+
+ sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates;
+ sta->wcid.tx_rate_set = true;
+}
+
+static enum mt7603_cipher_type
+mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
+{
+ memset(key_data, 0, 32);
+ if (!key)
+ return MT_CIPHER_NONE;
+
+ if (key->keylen > 32)
+ return MT_CIPHER_NONE;
+
+ memcpy(key_data, key->key, key->keylen);
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ return MT_CIPHER_WEP40;
+ case WLAN_CIPHER_SUITE_WEP104:
+ return MT_CIPHER_WEP104;
+ case WLAN_CIPHER_SUITE_TKIP:
+ /* Rx/Tx MIC keys are swapped */
+ memcpy(key_data + 16, key->key + 24, 8);
+ memcpy(key_data + 24, key->key + 16, 8);
+ return MT_CIPHER_TKIP;
+ case WLAN_CIPHER_SUITE_CCMP:
+ return MT_CIPHER_AES_CCMP;
+ default:
+ return MT_CIPHER_NONE;
+ }
+}
+
+int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
+ struct ieee80211_key_conf *key)
+{
+ enum mt7603_cipher_type cipher;
+ u32 addr = mt7603_wtbl3_addr(wcid);
+ u8 key_data[32];
+ int key_len = sizeof(key_data);
+
+ cipher = mt7603_mac_get_key_info(key, key_data);
+ if (cipher == MT_CIPHER_NONE && key)
+ return -EOPNOTSUPP;
+
+ if (key && (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104)) {
+ addr += key->keyidx * 16;
+ key_len = 16;
+ }
+
+ mt76_wr_copy(dev, addr, key_data, key_len);
+
+ addr = mt7603_wtbl1_addr(wcid);
+ mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher);
+ if (key)
+ mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx);
+ mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key);
+
+ return 0;
+}
+
+static int
+mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ int pid, struct ieee80211_key_conf *key)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt7603_vif *mvif;
+ int wlan_idx;
+ int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+ int tx_count = 8;
+ u8 frame_type, frame_subtype;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ u8 vif_idx = 0;
+ u32 val;
+ u8 bw;
+
+ if (vif) {
+ mvif = (struct mt7603_vif *)vif->drv_priv;
+ vif_idx = mvif->idx;
+ if (vif_idx && q >= &dev->mt76.q_tx[MT_TXQ_BEACON])
+ vif_idx += 0x10;
+ }
+
+ if (sta) {
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+
+ tx_count = msta->rate_count;
+ }
+
+ if (wcid)
+ wlan_idx = wcid->idx;
+ else
+ wlan_idx = MT7603_WTBL_RESERVED;
+
+ frame_type = (fc & IEEE80211_FCTL_FTYPE) >> 2;
+ frame_subtype = (fc & IEEE80211_FCTL_STYPE) >> 4;
+
+ val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
+ FIELD_PREP(MT_TXD0_Q_IDX, q->hw_idx);
+ txwi[0] = cpu_to_le32(val);
+
+ val = MT_TXD1_LONG_FORMAT |
+ FIELD_PREP(MT_TXD1_OWN_MAC, vif_idx) |
+ FIELD_PREP(MT_TXD1_TID,
+ skb->priority & IEEE80211_QOS_CTL_TID_MASK) |
+ FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
+ FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) |
+ FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) |
+ FIELD_PREP(MT_TXD1_PROTECTED, !!key);
+ txwi[1] = cpu_to_le32(val);
+
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ txwi[1] |= cpu_to_le32(MT_TXD1_NO_ACK);
+
+ val = FIELD_PREP(MT_TXD2_FRAME_TYPE, frame_type) |
+ FIELD_PREP(MT_TXD2_SUB_TYPE, frame_subtype) |
+ FIELD_PREP(MT_TXD2_MULTICAST,
+ is_multicast_ether_addr(hdr->addr1));
+ txwi[2] = cpu_to_le32(val);
+
+ if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
+ txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);
+
+ txwi[4] = 0;
+
+ val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT |
+ FIELD_PREP(MT_TXD5_PID, pid);
+ txwi[5] = cpu_to_le32(val);
+
+ txwi[6] = 0;
+
+ if (rate->idx >= 0 && rate->count &&
+ !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) {
+ bool stbc = info->flags & IEEE80211_TX_CTL_STBC;
+ u16 rateval = mt7603_mac_tx_rate_val(dev, rate, stbc, &bw);
+
+ txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE);
+
+ val = MT_TXD6_FIXED_BW |
+ FIELD_PREP(MT_TXD6_BW, bw) |
+ FIELD_PREP(MT_TXD6_TX_RATE, rateval);
+ txwi[6] |= cpu_to_le32(val);
+
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ txwi[6] |= cpu_to_le32(MT_TXD6_SGI);
+
+ if (!(rate->flags & IEEE80211_TX_RC_MCS))
+ txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);
+
+ tx_count = rate->count;
+ }
+
+ /* use maximum tx count for beacons and buffered multicast */
+ if (q >= &dev->mt76.q_tx[MT_TXQ_BEACON])
+ tx_count = 0x1f;
+
+ val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) |
+ FIELD_PREP(MT_TXD3_SEQ, le16_to_cpu(hdr->seq_ctrl));
+ txwi[3] = cpu_to_le32(val);
+
+ if (key) {
+ u64 pn = atomic64_inc_return(&key->tx_pn);
+
+ txwi[3] |= cpu_to_le32(MT_TXD3_PN_VALID);
+ txwi[4] = cpu_to_le32(pn & GENMASK(31, 0));
+ txwi[5] |= cpu_to_le32(FIELD_PREP(MT_TXD5_PN_HIGH, pn >> 32));
+ }
+
+ txwi[7] = 0;
+
+ return 0;
+}
+
+int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_key_conf *key = info->control.hw_key;
+ int pid;
+
+ if (!wcid)
+ wcid = &dev->global_sta.wcid;
+
+ if (sta) {
+ msta = (struct mt7603_sta *)sta->drv_priv;
+
+ if ((info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
+ IEEE80211_TX_CTL_CLEAR_PS_FILT)) ||
+ (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
+ mt7603_wtbl_set_ps(dev, msta, false);
+ }
+
+ pid = mt76_tx_status_skb_add(mdev, wcid, skb);
+
+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
+ spin_lock_bh(&dev->mt76.lock);
+ msta->rate_probe = true;
+ mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0],
+ msta->rates);
+ spin_unlock_bh(&dev->mt76.lock);
+ }
+
+ mt7603_mac_write_txwi(dev, txwi_ptr, skb, q, wcid, sta, pid, key);
+
+ return 0;
+}
+
+static bool
+mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ struct ieee80211_tx_info *info, __le32 *txs_data)
+{
+ struct ieee80211_supported_band *sband;
+ int final_idx = 0;
+ u32 final_rate;
+ u32 final_rate_flags;
+ bool final_mpdu;
+ bool ack_timeout;
+ bool fixed_rate;
+ bool probe;
+ bool ampdu;
+ bool cck = false;
+ int count;
+ u32 txs;
+ u8 pid;
+ int idx;
+ int i;
+
+ fixed_rate = info->status.rates[0].count;
+ probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+
+ txs = le32_to_cpu(txs_data[4]);
+ final_mpdu = txs & MT_TXS4_ACKED_MPDU;
+ ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU);
+ pid = FIELD_GET(MT_TXS4_PID, txs);
+ count = FIELD_GET(MT_TXS4_TX_COUNT, txs);
+
+ txs = le32_to_cpu(txs_data[0]);
+ final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs);
+ ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;
+
+ if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT))
+ return false;
+
+ if (txs & MT_TXS0_QUEUE_TIMEOUT)
+ return false;
+
+ if (!ack_timeout)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ info->status.ampdu_len = 1;
+ info->status.ampdu_ack_len = !!(info->flags &
+ IEEE80211_TX_STAT_ACK);
+
+ if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU))
+ info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU;
+
+ if (fixed_rate && !probe) {
+ info->status.rates[0].count = count;
+ goto out;
+ }
+
+ for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) {
+ int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY);
+
+ if (!i && probe) {
+ cur_count = 1;
+ } else {
+ info->status.rates[i] = sta->rates[idx];
+ idx++;
+ }
+
+ if (i && info->status.rates[i].idx < 0) {
+ info->status.rates[i - 1].count += count;
+ break;
+ }
+
+ if (!count) {
+ info->status.rates[i].idx = -1;
+ break;
+ }
+
+ info->status.rates[i].count = cur_count;
+ final_idx = i;
+ count -= cur_count;
+ }
+
+out:
+ final_rate_flags = info->status.rates[final_idx].flags;
+
+ switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ /* fall through */
+ case MT_PHY_TYPE_OFDM:
+ if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ)
+ sband = &dev->mt76.sband_5g.sband;
+ else
+ sband = &dev->mt76.sband_2g.sband;
+ final_rate &= GENMASK(5, 0);
+ final_rate = mt7603_get_rate(dev, sband, final_rate, cck);
+ final_rate_flags = 0;
+ break;
+ case MT_PHY_TYPE_HT_GF:
+ case MT_PHY_TYPE_HT:
+ final_rate_flags |= IEEE80211_TX_RC_MCS;
+ final_rate &= GENMASK(5, 0);
+ if (i > 15)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ info->status.rates[final_idx].idx = final_rate;
+ info->status.rates[final_idx].flags = final_rate_flags;
+
+ return true;
+}
+
+static bool
+mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid,
+ __le32 *txs_data)
+{
+ struct mt76_dev *mdev = &dev->mt76;
+ struct sk_buff_head list;
+ struct sk_buff *skb;
+
+ if (pid < MT_PACKET_ID_FIRST)
+ return false;
+
+ mt76_tx_status_lock(mdev, &list);
+ skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list);
+ if (skb) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
+ spin_lock_bh(&dev->mt76.lock);
+ if (sta->rate_probe) {
+ mt7603_wtbl_set_rates(dev, sta, NULL,
+ sta->rates);
+ sta->rate_probe = false;
+ }
+ spin_unlock_bh(&dev->mt76.lock);
+ }
+
+ if (!mt7603_fill_txs(dev, sta, info, txs_data)) {
+ ieee80211_tx_info_clear_status(info);
+ info->status.rates[0].idx = -1;
+ }
+
+ mt76_tx_status_skb_done(mdev, skb, &list);
+ }
+ mt76_tx_status_unlock(mdev, &list);
+
+ return !!skb;
+}
+
+void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
+{
+ struct ieee80211_tx_info info = {};
+ struct ieee80211_sta *sta = NULL;
+ struct mt7603_sta *msta = NULL;
+ struct mt76_wcid *wcid;
+ __le32 *txs_data = data;
+ u32 txs;
+ u8 wcidx;
+ u8 pid;
+
+ txs = le32_to_cpu(txs_data[4]);
+ pid = FIELD_GET(MT_TXS4_PID, txs);
+ txs = le32_to_cpu(txs_data[3]);
+ wcidx = FIELD_GET(MT_TXS3_WCID, txs);
+
+ if (pid == MT_PACKET_ID_NO_ACK)
+ return;
+
+ if (wcidx >= ARRAY_SIZE(dev->mt76.wcid))
+ return;
+
+ rcu_read_lock();
+
+ wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
+ if (!wcid)
+ goto out;
+
+ msta = container_of(wcid, struct mt7603_sta, wcid);
+ sta = wcid_to_sta(wcid);
+
+ if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data))
+ goto out;
+
+ if (wcidx >= MT7603_WTBL_STA || !sta)
+ goto out;
+
+ if (mt7603_fill_txs(dev, msta, &info, txs_data))
+ ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
+
+out:
+ rcu_read_unlock();
+}
+
+void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct sk_buff *skb = e->skb;
+
+ if (!e->txwi) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ if (q - dev->mt76.q_tx < 4)
+ dev->tx_hang_check = 0;
+
+ mt76_tx_complete_skb(mdev, skb);
+}
+
+static bool
+wait_for_wpdma(struct mt7603_dev *dev)
+{
+ return mt76_poll(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+ MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
+ 0, 1000);
+}
+
+static void mt7603_pse_reset(struct mt7603_dev *dev)
+{
+ /* Clear previous reset result */
+ if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED])
+ mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE_S);
+
+ /* Reset PSE */
+ mt76_set(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE);
+
+ if (!mt76_poll_msec(dev, MT_MCU_DEBUG_RESET,
+ MT_MCU_DEBUG_RESET_PSE_S,
+ MT_MCU_DEBUG_RESET_PSE_S, 500)) {
+ dev->reset_cause[RESET_CAUSE_RESET_FAILED]++;
+ mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE);
+ } else {
+ dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0;
+ mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_QUEUES);
+ }
+
+ if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] >= 3)
+ dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0;
+}
+
+void mt7603_mac_dma_start(struct mt7603_dev *dev)
+{
+ mt7603_mac_start(dev);
+
+ wait_for_wpdma(dev);
+ usleep_range(50, 100);
+
+ mt76_set(dev, MT_WPDMA_GLO_CFG,
+ (MT_WPDMA_GLO_CFG_TX_DMA_EN |
+ MT_WPDMA_GLO_CFG_RX_DMA_EN |
+ FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) |
+ MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE));
+
+ mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL);
+}
+
+void mt7603_mac_start(struct mt7603_dev *dev)
+{
+ mt76_clear(dev, MT_ARB_SCR,
+ MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+ mt76_wr(dev, MT_WF_ARB_TX_START_0, ~0);
+ mt76_set(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START);
+}
+
+void mt7603_mac_stop(struct mt7603_dev *dev)
+{
+ mt76_set(dev, MT_ARB_SCR,
+ MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+ mt76_wr(dev, MT_WF_ARB_TX_START_0, 0);
+ mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START);
+}
+
+void mt7603_pse_client_reset(struct mt7603_dev *dev)
+{
+ u32 addr;
+
+ addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR +
+ MT_CLIENT_RESET_TX);
+
+ /* Clear previous reset state */
+ mt76_clear(dev, addr,
+ MT_CLIENT_RESET_TX_R_E_1 |
+ MT_CLIENT_RESET_TX_R_E_2 |
+ MT_CLIENT_RESET_TX_R_E_1_S |
+ MT_CLIENT_RESET_TX_R_E_2_S);
+
+ /* Start PSE client TX abort */
+ mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1);
+ mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S,
+ MT_CLIENT_RESET_TX_R_E_1_S, 500);
+
+ mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2);
+ mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET);
+
+ /* Wait for PSE client to clear TX FIFO */
+ mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S,
+ MT_CLIENT_RESET_TX_R_E_2_S, 500);
+
+ /* Clear PSE client TX abort state */
+ mt76_clear(dev, addr,
+ MT_CLIENT_RESET_TX_R_E_1 |
+ MT_CLIENT_RESET_TX_R_E_2);
+}
+
+static void mt7603_dma_sched_reset(struct mt7603_dev *dev)
+{
+ if (!is_mt7628(dev))
+ return;
+
+ mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
+ mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
+}
+
+static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
+{
+ int beacon_int = dev->beacon_int;
+ u32 mask = dev->mt76.mmio.irqmask;
+ int i;
+
+ ieee80211_stop_queues(dev->mt76.hw);
+ set_bit(MT76_RESET, &dev->mt76.state);
+
+ /* lock/unlock all queues to ensure that no tx is pending */
+ mt76_txq_schedule_all(&dev->mt76);
+
+ tasklet_disable(&dev->tx_tasklet);
+ tasklet_disable(&dev->pre_tbtt_tasklet);
+ napi_disable(&dev->mt76.napi[0]);
+ napi_disable(&dev->mt76.napi[1]);
+
+ mutex_lock(&dev->mt76.mutex);
+
+ mt7603_beacon_set_timer(dev, -1, 0);
+
+ if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
+ dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY ||
+ dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK ||
+ dev->cur_reset_cause == RESET_CAUSE_TX_HANG)
+ mt7603_pse_reset(dev);
+
+ if (dev->reset_cause[RESET_CAUSE_RESET_FAILED])
+ goto skip_dma_reset;
+
+ mt7603_mac_stop(dev);
+
+ mt76_clear(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
+ MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
+ usleep_range(1000, 2000);
+
+ mt7603_irq_disable(dev, mask);
+
+ mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
+
+ mt7603_pse_client_reset(dev);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
+ mt76_queue_tx_cleanup(dev, i, true);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_queue_rx_reset(dev, i);
+
+ mt7603_dma_sched_reset(dev);
+
+ mt7603_mac_dma_start(dev);
+
+ mt7603_irq_enable(dev, mask);
+
+skip_dma_reset:
+ clear_bit(MT76_RESET, &dev->mt76.state);
+ mutex_unlock(&dev->mt76.mutex);
+
+ tasklet_enable(&dev->tx_tasklet);
+ tasklet_schedule(&dev->tx_tasklet);
+
+ tasklet_enable(&dev->pre_tbtt_tasklet);
+ mt7603_beacon_set_timer(dev, -1, beacon_int);
+
+ napi_enable(&dev->mt76.napi[0]);
+ napi_schedule(&dev->mt76.napi[0]);
+
+ napi_enable(&dev->mt76.napi[1]);
+ napi_schedule(&dev->mt76.napi[1]);
+
+ ieee80211_wake_queues(dev->mt76.hw);
+ mt76_txq_schedule_all(&dev->mt76);
+}
+
+static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index)
+{
+ u32 val;
+
+ mt76_wr(dev, MT_WPDMA_DEBUG,
+ FIELD_PREP(MT_WPDMA_DEBUG_IDX, index) |
+ MT_WPDMA_DEBUG_SEL);
+
+ val = mt76_rr(dev, MT_WPDMA_DEBUG);
+ return FIELD_GET(MT_WPDMA_DEBUG_VALUE, val);
+}
+
+static bool mt7603_rx_fifo_busy(struct mt7603_dev *dev)
+{
+ if (is_mt7628(dev))
+ return mt7603_dma_debug(dev, 9) & BIT(9);
+
+ return mt7603_dma_debug(dev, 2) & BIT(8);
+}
+
+static bool mt7603_rx_dma_busy(struct mt7603_dev *dev)
+{
+ if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_RX_DMA_BUSY))
+ return false;
+
+ return mt7603_rx_fifo_busy(dev);
+}
+
+static bool mt7603_tx_dma_busy(struct mt7603_dev *dev)
+{
+ u32 val;
+
+ if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_TX_DMA_BUSY))
+ return false;
+
+ val = mt7603_dma_debug(dev, 9);
+ return (val & BIT(8)) && (val & 0xf) != 0xf;
+}
+
+static bool mt7603_tx_hang(struct mt7603_dev *dev)
+{
+ struct mt76_queue *q;
+ u32 dma_idx, prev_dma_idx;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ q = &dev->mt76.q_tx[i];
+
+ if (!q->queued)
+ continue;
+
+ prev_dma_idx = dev->tx_dma_idx[i];
+ dma_idx = ioread32(&q->regs->dma_idx);
+ dev->tx_dma_idx[i] = dma_idx;
+
+ if (dma_idx == prev_dma_idx &&
+ dma_idx != ioread32(&q->regs->cpu_idx))
+ break;
+ }
+
+ return i < 4;
+}
+
+static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
+{
+ u32 addr, val;
+
+ if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
+ return true;
+
+ if (mt7603_rx_fifo_busy(dev))
+ return false;
+
+ addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
+ mt76_wr(dev, addr, 3);
+ val = mt76_rr(dev, addr) >> 16;
+
+ if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
+ return true;
+
+ return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
+}
+
+static bool
+mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter,
+ enum mt7603_reset_cause cause,
+ bool (*check)(struct mt7603_dev *dev))
+{
+ if (dev->reset_test == cause + 1) {
+ dev->reset_test = 0;
+ goto trigger;
+ }
+
+ if (check) {
+ if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) {
+ *counter = 0;
+ return false;
+ }
+
+ (*counter)++;
+ }
+
+ if (*counter < MT7603_WATCHDOG_TIMEOUT)
+ return false;
+trigger:
+ dev->cur_reset_cause = cause;
+ dev->reset_cause[cause]++;
+ return true;
+}
+
+void mt7603_update_channel(struct mt76_dev *mdev)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct mt76_channel_state *state;
+ ktime_t cur_time;
+ u32 busy;
+
+ if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
+ return;
+
+ state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan);
+ busy = mt76_rr(dev, MT_MIB_STAT_PSCCA);
+
+ spin_lock_bh(&dev->mt76.cc_lock);
+ cur_time = ktime_get_boottime();
+ state->cc_busy += busy;
+ state->cc_active += ktime_to_us(ktime_sub(cur_time, dev->survey_time));
+ dev->survey_time = cur_time;
+ spin_unlock_bh(&dev->mt76.cc_lock);
+}
+
+void
+mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val)
+{
+ u32 rxtd_6 = 0xd7c80000;
+
+ if (val == dev->ed_strict_mode)
+ return;
+
+ dev->ed_strict_mode = val;
+
+ /* Ensure that ED/CCA does not trigger if disabled */
+ if (!dev->ed_monitor)
+ rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34);
+ else
+ rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d);
+
+ if (dev->ed_monitor && !dev->ed_strict_mode)
+ rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f);
+ else
+ rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10);
+
+ mt76_wr(dev, MT_RXTD(6), rxtd_6);
+
+ mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN,
+ dev->ed_monitor && !dev->ed_strict_mode);
+}
+
+static void
+mt7603_edcca_check(struct mt7603_dev *dev)
+{
+ u32 val = mt76_rr(dev, MT_AGC(41));
+ ktime_t cur_time;
+ int rssi0, rssi1;
+ u32 active;
+ u32 ed_busy;
+
+ if (!dev->ed_monitor)
+ return;
+
+ rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val);
+ if (rssi0 > 128)
+ rssi0 -= 256;
+
+ rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val);
+ if (rssi1 > 128)
+ rssi1 -= 256;
+
+ if (max(rssi0, rssi1) >= -40 &&
+ dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH)
+ dev->ed_strong_signal++;
+ else if (dev->ed_strong_signal > 0)
+ dev->ed_strong_signal--;
+
+ cur_time = ktime_get_boottime();
+ ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK;
+
+ active = ktime_to_us(ktime_sub(cur_time, dev->ed_time));
+ dev->ed_time = cur_time;
+
+ if (!active)
+ return;
+
+ if (100 * ed_busy / active > 90) {
+ if (dev->ed_trigger < 0)
+ dev->ed_trigger = 0;
+ dev->ed_trigger++;
+ } else {
+ if (dev->ed_trigger > 0)
+ dev->ed_trigger = 0;
+ dev->ed_trigger--;
+ }
+
+ if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH ||
+ dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) {
+ mt7603_edcca_set_strict(dev, true);
+ } else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) {
+ mt7603_edcca_set_strict(dev, false);
+ }
+
+ if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH)
+ dev->ed_trigger = MT7603_EDCCA_BLOCK_TH;
+ else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH)
+ dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH;
+}
+
+void mt7603_cca_stats_reset(struct mt7603_dev *dev)
+{
+ mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET);
+ mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET);
+ mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN);
+}
+
+static void
+mt7603_adjust_sensitivity(struct mt7603_dev *dev)
+{
+ u32 agc0 = dev->agc0, agc3 = dev->agc3;
+ u32 adj;
+
+ if (!dev->sensitivity || dev->sensitivity < -100) {
+ dev->sensitivity = 0;
+ } else if (dev->sensitivity <= -84) {
+ adj = 7 + (dev->sensitivity + 92) / 2;
+
+ agc0 = 0x56f0076f;
+ agc0 |= adj << 12;
+ agc0 |= adj << 16;
+ agc3 = 0x81d0d5e3;
+ } else if (dev->sensitivity <= -72) {
+ adj = 7 + (dev->sensitivity + 80) / 2;
+
+ agc0 = 0x6af0006f;
+ agc0 |= adj << 8;
+ agc0 |= adj << 12;
+ agc0 |= adj << 16;
+
+ agc3 = 0x8181d5e3;
+ } else {
+ if (dev->sensitivity > -54)
+ dev->sensitivity = -54;
+
+ adj = 7 + (dev->sensitivity + 80) / 2;
+
+ agc0 = 0x7ff0000f;
+ agc0 |= adj << 4;
+ agc0 |= adj << 8;
+ agc0 |= adj << 12;
+ agc0 |= adj << 16;
+
+ agc3 = 0x818181e3;
+ }
+
+ mt76_wr(dev, MT_AGC(0), agc0);
+ mt76_wr(dev, MT_AGC1(0), agc0);
+
+ mt76_wr(dev, MT_AGC(3), agc3);
+ mt76_wr(dev, MT_AGC1(3), agc3);
+}
+
+static void
+mt7603_false_cca_check(struct mt7603_dev *dev)
+{
+ int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm;
+ int false_cca;
+ int min_signal;
+ u32 val;
+
+ val = mt76_rr(dev, MT_PHYCTRL_STAT_PD);
+ pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val);
+ pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val);
+
+ val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY);
+ mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val);
+ mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val);
+
+ dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm;
+ dev->false_cca_cck = pd_cck - mdrdy_cck;
+
+ mt7603_cca_stats_reset(dev);
+
+ min_signal = mt76_get_min_avg_rssi(&dev->mt76);
+ if (!min_signal) {
+ dev->sensitivity = 0;
+ dev->last_cca_adj = jiffies;
+ goto out;
+ }
+
+ min_signal -= 15;
+
+ false_cca = dev->false_cca_ofdm + dev->false_cca_cck;
+ if (false_cca > 600) {
+ if (!dev->sensitivity)
+ dev->sensitivity = -92;
+ else
+ dev->sensitivity += 2;
+ dev->last_cca_adj = jiffies;
+ } else if (false_cca < 100 ||
+ time_after(jiffies, dev->last_cca_adj + 10 * HZ)) {
+ dev->last_cca_adj = jiffies;
+ if (!dev->sensitivity)
+ goto out;
+
+ dev->sensitivity -= 2;
+ }
+
+ if (dev->sensitivity && dev->sensitivity > min_signal) {
+ dev->sensitivity = min_signal;
+ dev->last_cca_adj = jiffies;
+ }
+
+out:
+ mt7603_adjust_sensitivity(dev);
+}
+
+void mt7603_mac_work(struct work_struct *work)
+{
+ struct mt7603_dev *dev = container_of(work, struct mt7603_dev,
+ mac_work.work);
+ bool reset = false;
+
+ mt76_tx_status_check(&dev->mt76, NULL, false);
+
+ mutex_lock(&dev->mt76.mutex);
+
+ dev->mac_work_count++;
+ mt7603_update_channel(&dev->mt76);
+ mt7603_edcca_check(dev);
+
+ if (dev->mac_work_count == 10)
+ mt7603_false_cca_check(dev);
+
+ if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
+ RESET_CAUSE_RX_PSE_BUSY,
+ mt7603_rx_pse_busy) ||
+ mt7603_watchdog_check(dev, &dev->beacon_check,
+ RESET_CAUSE_BEACON_STUCK,
+ NULL) ||
+ mt7603_watchdog_check(dev, &dev->tx_hang_check,
+ RESET_CAUSE_TX_HANG,
+ mt7603_tx_hang) ||
+ mt7603_watchdog_check(dev, &dev->tx_dma_check,
+ RESET_CAUSE_TX_BUSY,
+ mt7603_tx_dma_busy) ||
+ mt7603_watchdog_check(dev, &dev->rx_dma_check,
+ RESET_CAUSE_RX_BUSY,
+ mt7603_rx_dma_busy) ||
+ mt7603_watchdog_check(dev, &dev->mcu_hang,
+ RESET_CAUSE_MCU_HANG,
+ NULL) ||
+ dev->reset_cause[RESET_CAUSE_RESET_FAILED]) {
+ dev->beacon_check = 0;
+ dev->tx_dma_check = 0;
+ dev->tx_hang_check = 0;
+ dev->rx_dma_check = 0;
+ dev->rx_pse_check = 0;
+ dev->mcu_hang = 0;
+ dev->rx_dma_idx = ~0;
+ memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx));
+ reset = true;
+ dev->mac_work_count = 0;
+ }
+
+ if (dev->mac_work_count >= 10)
+ dev->mac_work_count = 0;
+
+ mutex_unlock(&dev->mt76.mutex);
+
+ if (reset)
+ mt7603_mac_watchdog_reset(dev);
+
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ msecs_to_jiffies(MT7603_WATCHDOG_TIME));
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.h b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h
new file mode 100644
index 000000000000..17e34ecf2bfb
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: ISC */
+
+#ifndef __MT7603_MAC_H
+#define __MT7603_MAC_H
+
+#define MT_RXD0_LENGTH GENMASK(15, 0)
+#define MT_RXD0_PKT_TYPE GENMASK(31, 29)
+
+#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
+#define MT_RXD0_NORMAL_IP_SUM BIT(23)
+#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
+#define MT_RXD0_NORMAL_GROUP_1 BIT(25)
+#define MT_RXD0_NORMAL_GROUP_2 BIT(26)
+#define MT_RXD0_NORMAL_GROUP_3 BIT(27)
+#define MT_RXD0_NORMAL_GROUP_4 BIT(28)
+
+enum rx_pkt_type {
+ PKT_TYPE_TXS = 0,
+ PKT_TYPE_TXRXV = 1,
+ PKT_TYPE_NORMAL = 2,
+ PKT_TYPE_RX_DUP_RFB = 3,
+ PKT_TYPE_RX_TMR = 4,
+ PKT_TYPE_RETRIEVE = 5,
+ PKT_TYPE_RX_EVENT = 7,
+};
+
+#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
+#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
+#define MT_RXD1_NORMAL_HDR_TRANS BIT(23)
+#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22)
+#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16)
+#define MT_RXD1_NORMAL_CH_FREQ GENMASK(15, 8)
+#define MT_RXD1_NORMAL_KEY_ID GENMASK(7, 6)
+#define MT_RXD1_NORMAL_BEACON_UC BIT(5)
+#define MT_RXD1_NORMAL_BEACON_MC BIT(4)
+#define MT_RXD1_NORMAL_BCAST BIT(3)
+#define MT_RXD1_NORMAL_MCAST BIT(2)
+#define MT_RXD1_NORMAL_U2M BIT(1)
+#define MT_RXD1_NORMAL_HTC_VLD BIT(0)
+
+#define MT_RXD2_NORMAL_NON_AMPDU BIT(31)
+#define MT_RXD2_NORMAL_NON_AMPDU_SUB BIT(30)
+#define MT_RXD2_NORMAL_NDATA BIT(29)
+#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
+#define MT_RXD2_NORMAL_FRAG BIT(27)
+#define MT_RXD2_NORMAL_UDF_VALID BIT(26)
+#define MT_RXD2_NORMAL_LLC_MIS BIT(25)
+#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
+#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
+#define MT_RXD2_NORMAL_LEN_MISMATCH BIT(22)
+#define MT_RXD2_NORMAL_TKIP_MIC_ERR BIT(21)
+#define MT_RXD2_NORMAL_ICV_ERR BIT(20)
+#define MT_RXD2_NORMAL_CLM BIT(19)
+#define MT_RXD2_NORMAL_CM BIT(18)
+#define MT_RXD2_NORMAL_FCS_ERR BIT(17)
+#define MT_RXD2_NORMAL_SW_BIT BIT(16)
+#define MT_RXD2_NORMAL_SEC_MODE GENMASK(15, 12)
+#define MT_RXD2_NORMAL_TID GENMASK(11, 8)
+#define MT_RXD2_NORMAL_WLAN_IDX GENMASK(7, 0)
+
+#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
+#define MT_RXD3_NORMAL_PF_MODE BIT(29)
+#define MT_RXD3_NORMAL_CLS_BITMAP GENMASK(28, 19)
+#define MT_RXD3_NORMAL_WOL GENMASK(18, 14)
+#define MT_RXD3_NORMAL_MAGIC_PKT BIT(13)
+#define MT_RXD3_NORMAL_OFLD GENMASK(12, 11)
+#define MT_RXD3_NORMAL_CLS BIT(10)
+#define MT_RXD3_NORMAL_PATTERN_DROP BIT(9)
+#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8)
+#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
+
+#define MT_RXV1_VHTA1_B5_B4 GENMASK(31, 30)
+#define MT_RXV1_VHTA2_B8_B1 GENMASK(29, 22)
+#define MT_RXV1_HT_NO_SOUND BIT(21)
+#define MT_RXV1_HT_SMOOTH BIT(20)
+#define MT_RXV1_HT_SHORT_GI BIT(19)
+#define MT_RXV1_HT_AGGR BIT(18)
+#define MT_RXV1_VHTA1_B22 BIT(17)
+#define MT_RXV1_FRAME_MODE GENMASK(16, 15)
+#define MT_RXV1_TX_MODE GENMASK(14, 12)
+#define MT_RXV1_HT_EXT_LTF GENMASK(11, 10)
+#define MT_RXV1_HT_AD_CODE BIT(9)
+#define MT_RXV1_HT_STBC GENMASK(8, 7)
+#define MT_RXV1_TX_RATE GENMASK(6, 0)
+
+#define MT_RXV2_VHTA1_B16_B6 GENMASK(31, 21)
+#define MT_RXV2_LENGTH GENMASK(20, 0)
+
+#define MT_RXV3_F_AGC1_CAL_GAIN GENMASK(31, 29)
+#define MT_RXV3_F_AGC1_EQ_CAL BIT(28)
+#define MT_RXV3_RCPI1 GENMASK(27, 20)
+#define MT_RXV3_F_AGC0_CAL_GAIN GENMASK(19, 17)
+#define MT_RXV3_F_AGC0_EQ_CAL BIT(16)
+#define MT_RXV3_RCPI0 GENMASK(15, 8)
+#define MT_RXV3_SEL_ANT BIT(7)
+#define MT_RXV3_ACI_DET_X BIT(6)
+#define MT_RXV3_OFDM_FREQ_TRANS_DETECT BIT(5)
+#define MT_RXV3_VHTA1_B21_B17 GENMASK(4, 0)
+
+#define MT_RXV4_F_AGC_CAL_GAIN GENMASK(31, 29)
+#define MT_RXV4_F_AGC2_EQ_CAL BIT(28)
+#define MT_RXV4_IB_RSSI1 GENMASK(27, 20)
+#define MT_RXV4_F_AGC_LPF_GAIN_X GENMASK(19, 16)
+#define MT_RXV4_WB_RSSI_X GENMASK(15, 8)
+#define MT_RXV4_IB_RSSI0 GENMASK(7, 0)
+
+#define MT_RXV5_LTF_SNR0 GENMASK(31, 26)
+#define MT_RXV5_LTF_PROC_TIME GENMASK(25, 19)
+#define MT_RXV5_FOE GENMASK(18, 7)
+#define MT_RXV5_C_AGC_SATE GENMASK(6, 4)
+#define MT_RXV5_F_AGC_LNA_GAIN_0 GENMASK(3, 2)
+#define MT_RXV5_F_AGC_LNA_GAIN_1 GENMASK(1, 0)
+
+#define MT_RXV6_C_AGC_STATE GENMASK(30, 28)
+#define MT_RXV6_NS_TS_FIELD GENMASK(27, 25)
+#define MT_RXV6_RX_VALID BIT(24)
+#define MT_RXV6_NF2 GENMASK(23, 16)
+#define MT_RXV6_NF1 GENMASK(15, 8)
+#define MT_RXV6_NF0 GENMASK(7, 0)
+
+enum mt7603_tx_header_format {
+ MT_HDR_FORMAT_802_3,
+ MT_HDR_FORMAT_CMD,
+ MT_HDR_FORMAT_802_11,
+ MT_HDR_FORMAT_802_11_EXT,
+};
+
+#define MT_TXD_SIZE (8 * 4)
+
+#define MT_TXD0_P_IDX BIT(31)
+#define MT_TXD0_Q_IDX GENMASK(30, 27)
+#define MT_TXD0_UTXB BIT(26)
+#define MT_TXD0_UNXV BIT(25)
+#define MT_TXD0_UDP_TCP_SUM BIT(24)
+#define MT_TXD0_IP_SUM BIT(23)
+#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
+#define MT_TXD0_TX_BYTES GENMASK(15, 0)
+
+#define MT_TXD1_OWN_MAC GENMASK(31, 26)
+#define MT_TXD1_PROTECTED BIT(23)
+#define MT_TXD1_TID GENMASK(22, 20)
+#define MT_TXD1_NO_ACK BIT(19)
+#define MT_TXD1_HDR_PAD GENMASK(18, 16)
+#define MT_TXD1_LONG_FORMAT BIT(15)
+#define MT_TXD1_HDR_FORMAT GENMASK(14, 13)
+#define MT_TXD1_HDR_INFO GENMASK(12, 8)
+#define MT_TXD1_WLAN_IDX GENMASK(7, 0)
+
+#define MT_TXD2_FIX_RATE BIT(31)
+#define MT_TXD2_TIMING_MEASURE BIT(30)
+#define MT_TXD2_BA_DISABLE BIT(29)
+#define MT_TXD2_POWER_OFFSET GENMASK(28, 24)
+#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
+#define MT_TXD2_FRAG GENMASK(15, 14)
+#define MT_TXD2_HTC_VLD BIT(13)
+#define MT_TXD2_DURATION BIT(12)
+#define MT_TXD2_BIP BIT(11)
+#define MT_TXD2_MULTICAST BIT(10)
+#define MT_TXD2_RTS BIT(9)
+#define MT_TXD2_SOUNDING BIT(8)
+#define MT_TXD2_NDPA BIT(7)
+#define MT_TXD2_NDP BIT(6)
+#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
+#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
+
+#define MT_TXD3_SN_VALID BIT(31)
+#define MT_TXD3_PN_VALID BIT(30)
+#define MT_TXD3_SEQ GENMASK(27, 16)
+#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
+#define MT_TXD3_TX_COUNT GENMASK(10, 6)
+
+#define MT_TXD4_PN_LOW GENMASK(31, 0)
+
+#define MT_TXD5_PN_HIGH GENMASK(31, 16)
+#define MT_TXD5_SW_POWER_MGMT BIT(13)
+#define MT_TXD5_BA_SEQ_CTRL BIT(12)
+#define MT_TXD5_DA_SELECT BIT(11)
+#define MT_TXD5_TX_STATUS_HOST BIT(10)
+#define MT_TXD5_TX_STATUS_MCU BIT(9)
+#define MT_TXD5_TX_STATUS_FMT BIT(8)
+#define MT_TXD5_PID GENMASK(7, 0)
+
+#define MT_TXD6_SGI BIT(31)
+#define MT_TXD6_LDPC BIT(30)
+#define MT_TXD6_TX_RATE GENMASK(29, 18)
+#define MT_TXD6_I_TXBF BIT(17)
+#define MT_TXD6_E_TXBF BIT(16)
+#define MT_TXD6_DYN_BW BIT(15)
+#define MT_TXD6_ANT_PRI GENMASK(14, 12)
+#define MT_TXD6_SPE_EN BIT(11)
+#define MT_TXD6_FIXED_BW BIT(10)
+#define MT_TXD6_BW GENMASK(9, 8)
+#define MT_TXD6_ANT_ID GENMASK(7, 2)
+#define MT_TXD6_FIXED_RATE BIT(0)
+
+#define MT_TX_RATE_STBC BIT(11)
+#define MT_TX_RATE_NSS GENMASK(10, 9)
+#define MT_TX_RATE_MODE GENMASK(8, 6)
+#define MT_TX_RATE_IDX GENMASK(5, 0)
+
+#define MT_TXS0_ANTENNA GENMASK(31, 26)
+#define MT_TXS0_TID GENMASK(25, 22)
+#define MT_TXS0_BA_ERROR BIT(22)
+#define MT_TXS0_PS_FLAG BIT(21)
+#define MT_TXS0_TXOP_TIMEOUT BIT(20)
+#define MT_TXS0_BIP_ERROR BIT(19)
+
+#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
+#define MT_TXS0_RTS_TIMEOUT BIT(17)
+#define MT_TXS0_ACK_TIMEOUT BIT(16)
+#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
+
+#define MT_TXS0_TX_STATUS_HOST BIT(15)
+#define MT_TXS0_TX_STATUS_MCU BIT(14)
+#define MT_TXS0_TXS_FORMAT BIT(13)
+#define MT_TXS0_FIXED_RATE BIT(12)
+#define MT_TXS0_TX_RATE GENMASK(11, 0)
+
+#define MT_TXS1_F0_TIMESTAMP GENMASK(31, 0)
+#define MT_TXS1_F1_NOISE_2 GENMASK(23, 16)
+#define MT_TXS1_F1_NOISE_1 GENMASK(15, 8)
+#define MT_TXS1_F1_NOISE_0 GENMASK(7, 0)
+
+#define MT_TXS2_F0_FRONT_TIME GENMASK(24, 0)
+#define MT_TXS2_F1_RCPI_2 GENMASK(23, 16)
+#define MT_TXS2_F1_RCPI_1 GENMASK(15, 8)
+#define MT_TXS2_F1_RCPI_0 GENMASK(7, 0)
+
+#define MT_TXS3_WCID GENMASK(31, 24)
+#define MT_TXS3_RXV_SEQNO GENMASK(23, 16)
+#define MT_TXS3_TX_DELAY GENMASK(15, 0)
+
+#define MT_TXS4_LAST_TX_RATE GENMASK(31, 29)
+#define MT_TXS4_TX_COUNT GENMASK(28, 24)
+#define MT_TXS4_AMPDU BIT(23)
+#define MT_TXS4_ACKED_MPDU BIT(22)
+#define MT_TXS4_PID GENMASK(21, 14)
+#define MT_TXS4_BW GENMASK(13, 12)
+#define MT_TXS4_F0_SEQNO GENMASK(11, 0)
+#define MT_TXS4_F1_TSSI GENMASK(11, 0)
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
new file mode 100644
index 000000000000..b10775ed92e6
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -0,0 +1,709 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include "mt7603.h"
+#include "eeprom.h"
+
+static int
+mt7603_start(struct ieee80211_hw *hw)
+{
+ struct mt7603_dev *dev = hw->priv;
+
+ mt7603_mac_start(dev);
+ dev->survey_time = ktime_get_boottime();
+ set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+ mt7603_mac_work(&dev->mac_work.work);
+
+ return 0;
+}
+
+static void
+mt7603_stop(struct ieee80211_hw *hw)
+{
+ struct mt7603_dev *dev = hw->priv;
+
+ clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
+ cancel_delayed_work_sync(&dev->mac_work);
+ mt7603_mac_stop(dev);
+}
+
+static int
+mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct mt7603_dev *dev = hw->priv;
+ struct mt76_txq *mtxq;
+ u8 bc_addr[ETH_ALEN];
+ int idx;
+ int ret = 0;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ mvif->idx = ffs(~dev->vif_mask) - 1;
+ if (mvif->idx >= MT7603_MAX_INTERFACES) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ mt76_wr(dev, MT_MAC_ADDR0(mvif->idx),
+ get_unaligned_le32(vif->addr));
+ mt76_wr(dev, MT_MAC_ADDR1(mvif->idx),
+ (get_unaligned_le16(vif->addr + 4) |
+ MT_MAC_ADDR1_VALID));
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ mt76_wr(dev, MT_BSSID0(mvif->idx),
+ get_unaligned_le32(vif->addr));
+ mt76_wr(dev, MT_BSSID1(mvif->idx),
+ (get_unaligned_le16(vif->addr + 4) |
+ MT_BSSID1_VALID));
+ }
+
+ idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
+ dev->vif_mask |= BIT(mvif->idx);
+ mvif->sta.wcid.idx = idx;
+ mvif->sta.wcid.hw_key_idx = -1;
+
+ eth_broadcast_addr(bc_addr);
+ mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
+
+ mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+ mtxq->wcid = &mvif->sta.wcid;
+ mt76_txq_init(&dev->mt76, vif->txq);
+ rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+
+out:
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret;
+}
+
+static void
+mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct mt7603_dev *dev = hw->priv;
+ int idx = mvif->sta.wcid.idx;
+
+ mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 0);
+ mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 0);
+ mt76_wr(dev, MT_BSSID0(mvif->idx), 0);
+ mt76_wr(dev, MT_BSSID1(mvif->idx), 0);
+ mt7603_beacon_set_timer(dev, mvif->idx, 0);
+
+ rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
+ mt76_txq_remove(&dev->mt76, vif->txq);
+
+ mutex_lock(&dev->mt76.mutex);
+ dev->vif_mask &= ~BIT(mvif->idx);
+ mutex_unlock(&dev->mt76.mutex);
+}
+
+static void
+mt7603_init_edcca(struct mt7603_dev *dev)
+{
+ /* Set lower signal level to -65dBm */
+ mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23);
+
+ /* clear previous energy detect monitor results */
+ mt76_rr(dev, MT_MIB_STAT_ED);
+
+ if (dev->ed_monitor)
+ mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);
+ else
+ mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);
+
+ dev->ed_strict_mode = 0xff;
+ dev->ed_strong_signal = 0;
+ dev->ed_time = ktime_get_boottime();
+
+ mt7603_edcca_set_strict(dev, false);
+}
+
+static int
+mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
+{
+ u8 *rssi_data = (u8 *)dev->mt76.eeprom.data;
+ int idx, ret;
+ u8 bw = MT_BW_20;
+ bool failed = false;
+
+ cancel_delayed_work_sync(&dev->mac_work);
+
+ mutex_lock(&dev->mt76.mutex);
+ set_bit(MT76_RESET, &dev->mt76.state);
+
+ mt76_set_channel(&dev->mt76);
+ mt7603_mac_stop(dev);
+
+ if (def->width == NL80211_CHAN_WIDTH_40)
+ bw = MT_BW_40;
+
+ dev->mt76.chandef = *def;
+ mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw);
+ ret = mt7603_mcu_set_channel(dev);
+ if (ret) {
+ failed = true;
+ goto out;
+ }
+
+ if (def->chan->band == NL80211_BAND_5GHZ) {
+ idx = 1;
+ rssi_data += MT_EE_RSSI_OFFSET_5G;
+ } else {
+ idx = 0;
+ rssi_data += MT_EE_RSSI_OFFSET_2G;
+ }
+
+ memcpy(dev->rssi_offset, rssi_data, sizeof(dev->rssi_offset));
+
+ idx |= (def->chan -
+ mt76_hw(dev)->wiphy->bands[def->chan->band]->channels) << 1;
+ mt76_wr(dev, MT_WF_RMAC_CH_FREQ, idx);
+ mt7603_mac_set_timing(dev);
+ mt7603_mac_start(dev);
+
+ clear_bit(MT76_RESET, &dev->mt76.state);
+
+ mt76_txq_schedule_all(&dev->mt76);
+
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ MT7603_WATCHDOG_TIME);
+
+ /* reset channel stats */
+ mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS);
+ mt76_set(dev, MT_MIB_CTL,
+ MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME);
+ mt76_rr(dev, MT_MIB_STAT_PSCCA);
+ mt7603_cca_stats_reset(dev);
+
+ dev->survey_time = ktime_get_boottime();
+
+ mt7603_init_edcca(dev);
+
+out:
+ mutex_unlock(&dev->mt76.mutex);
+
+ if (failed)
+ mt7603_mac_work(&dev->mac_work.work);
+
+ return ret;
+}
+
+static int
+mt7603_config(struct ieee80211_hw *hw, u32 changed)
+{
+ struct mt7603_dev *dev = hw->priv;
+ int ret = 0;
+
+ if (changed & (IEEE80211_CONF_CHANGE_CHANNEL |
+ IEEE80211_CONF_CHANGE_POWER))
+ ret = mt7603_set_channel(dev, &hw->conf.chandef);
+
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ mutex_lock(&dev->mt76.mutex);
+
+ if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
+ dev->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
+ else
+ dev->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
+
+ mt76_wr(dev, MT_WF_RFCR, dev->rxfilter);
+
+ mutex_unlock(&dev->mt76.mutex);
+ }
+
+ return ret;
+}
+
+static void
+mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast)
+{
+ struct mt7603_dev *dev = hw->priv;
+ u32 flags = 0;
+
+#define MT76_FILTER(_flag, _hw) do { \
+ flags |= *total_flags & FIF_##_flag; \
+ dev->rxfilter &= ~(_hw); \
+ dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
+ } while (0)
+
+ dev->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
+ MT_WF_RFCR_DROP_OTHER_BEACON |
+ MT_WF_RFCR_DROP_FRAME_REPORT |
+ MT_WF_RFCR_DROP_PROBEREQ |
+ MT_WF_RFCR_DROP_MCAST_FILTERED |
+ MT_WF_RFCR_DROP_MCAST |
+ MT_WF_RFCR_DROP_BCAST |
+ MT_WF_RFCR_DROP_DUPLICATE |
+ MT_WF_RFCR_DROP_A2_BSSID |
+ MT_WF_RFCR_DROP_UNWANTED_CTL |
+ MT_WF_RFCR_DROP_STBC_MULTI);
+
+ MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
+ MT_WF_RFCR_DROP_A3_MAC |
+ MT_WF_RFCR_DROP_A3_BSSID);
+
+ MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
+
+ MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
+ MT_WF_RFCR_DROP_RTS |
+ MT_WF_RFCR_DROP_CTL_RSV |
+ MT_WF_RFCR_DROP_NDPA);
+
+ *total_flags = flags;
+ mt76_wr(dev, MT_WF_RFCR, dev->rxfilter);
+}
+
+static void
+mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info, u32 changed)
+{
+ struct mt7603_dev *dev = hw->priv;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) {
+ if (info->assoc || info->ibss_joined) {
+ mt76_wr(dev, MT_BSSID0(mvif->idx),
+ get_unaligned_le32(info->bssid));
+ mt76_wr(dev, MT_BSSID1(mvif->idx),
+ (get_unaligned_le16(info->bssid + 4) |
+ MT_BSSID1_VALID));
+ } else {
+ mt76_wr(dev, MT_BSSID0(mvif->idx), 0);
+ mt76_wr(dev, MT_BSSID1(mvif->idx), 0);
+ }
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ int slottime = info->use_short_slot ? 9 : 20;
+
+ if (slottime != dev->slottime) {
+ dev->slottime = slottime;
+ mt7603_mac_set_timing(dev);
+ }
+ }
+
+ if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) {
+ int beacon_int = !!info->enable_beacon * info->beacon_int;
+
+ tasklet_disable(&dev->pre_tbtt_tasklet);
+ mt7603_beacon_set_timer(dev, mvif->idx, beacon_int);
+ tasklet_enable(&dev->pre_tbtt_tasklet);
+ }
+
+ mutex_unlock(&dev->mt76.mutex);
+}
+
+int
+mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ int idx;
+ int ret = 0;
+
+ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7603_WTBL_STA - 1);
+ if (idx < 0)
+ return -ENOSPC;
+
+ __skb_queue_head_init(&msta->psq);
+ msta->ps = ~0;
+ msta->smps = ~0;
+ msta->wcid.sta = 1;
+ msta->wcid.idx = idx;
+ mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr);
+ mt7603_wtbl_set_ps(dev, msta, false);
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
+
+ return ret;
+}
+
+void
+mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+
+ mt7603_wtbl_update_cap(dev, sta);
+}
+
+void
+mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
+
+ spin_lock_bh(&dev->ps_lock);
+ __skb_queue_purge(&msta->psq);
+ mt7603_filter_tx(dev, wcid->idx, true);
+ spin_unlock_bh(&dev->ps_lock);
+
+ mt7603_wtbl_clear(dev, wcid->idx);
+}
+
+static void
+mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(list)) != NULL)
+ mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb),
+ skb, 0);
+}
+
+void
+mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
+{
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ struct sk_buff_head list;
+
+ mt76_stop_tx_queues(&dev->mt76, sta, false);
+ mt7603_wtbl_set_ps(dev, msta, ps);
+ if (ps)
+ return;
+
+ __skb_queue_head_init(&list);
+
+ spin_lock_bh(&dev->ps_lock);
+ skb_queue_splice_tail_init(&msta->psq, &list);
+ spin_unlock_bh(&dev->ps_lock);
+
+ mt7603_ps_tx_list(dev, &list);
+}
+
+static void
+mt7603_release_buffered_frames(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int nframes,
+ enum ieee80211_frame_release_type reason,
+ bool more_data)
+{
+ struct mt7603_dev *dev = hw->priv;
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ struct sk_buff_head list;
+ struct sk_buff *skb, *tmp;
+
+ __skb_queue_head_init(&list);
+
+ spin_lock_bh(&dev->ps_lock);
+ skb_queue_walk_safe(&msta->psq, skb, tmp) {
+ if (!nframes)
+ break;
+
+ if (!(tids & BIT(skb->priority)))
+ continue;
+
+ skb_set_queue_mapping(skb, MT_TXQ_PSD);
+ __skb_unlink(skb, &msta->psq);
+ __skb_queue_tail(&list, skb);
+ nframes--;
+ }
+ spin_unlock_bh(&dev->ps_lock);
+
+ mt7603_ps_tx_list(dev, &list);
+
+ if (nframes)
+ mt76_release_buffered_frames(hw, sta, tids, nframes, reason,
+ more_data);
+}
+
+static int
+mt7603_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 mt7603_dev *dev = hw->priv;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct mt7603_sta *msta = sta ? (struct mt7603_sta *)sta->drv_priv :
+ &mvif->sta;
+ struct mt76_wcid *wcid = &msta->wcid;
+ int idx = key->keyidx;
+
+ /* fall back to sw encryption for unsupported ciphers */
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * The hardware does not support per-STA RX GTK, fall back
+ * to software mode for these.
+ */
+ if ((vif->type == NL80211_IFTYPE_ADHOC ||
+ vif->type == NL80211_IFTYPE_MESH_POINT) &&
+ (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+ key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
+ !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+ return -EOPNOTSUPP;
+
+ if (cmd == SET_KEY) {
+ key->hw_key_idx = wcid->idx;
+ wcid->hw_key_idx = idx;
+ } else {
+ if (idx == wcid->hw_key_idx)
+ wcid->hw_key_idx = -1;
+
+ key = NULL;
+ }
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
+
+ return mt7603_wtbl_set_key(dev, wcid->idx, key);
+}
+
+static int
+mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct mt7603_dev *dev = hw->priv;
+ u16 cw_min = (1 << 5) - 1;
+ u16 cw_max = (1 << 10) - 1;
+ u32 val;
+
+ queue = dev->mt76.q_tx[queue].hw_idx;
+
+ if (params->cw_min)
+ cw_min = params->cw_min;
+ if (params->cw_max)
+ cw_max = params->cw_max;
+
+ mutex_lock(&dev->mt76.mutex);
+ mt7603_mac_stop(dev);
+
+ val = mt76_rr(dev, MT_WMM_TXOP(queue));
+ val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue));
+ val |= params->txop << MT_WMM_TXOP_SHIFT(queue);
+ mt76_wr(dev, MT_WMM_TXOP(queue), val);
+
+ val = mt76_rr(dev, MT_WMM_AIFSN);
+ val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue));
+ val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue);
+ mt76_wr(dev, MT_WMM_AIFSN, val);
+
+ val = mt76_rr(dev, MT_WMM_CWMIN);
+ val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue));
+ val |= cw_min << MT_WMM_CWMIN_SHIFT(queue);
+ mt76_wr(dev, MT_WMM_CWMIN, val);
+
+ val = mt76_rr(dev, MT_WMM_CWMAX(queue));
+ val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue));
+ val |= cw_max << MT_WMM_CWMAX_SHIFT(queue);
+ mt76_wr(dev, MT_WMM_CWMAX(queue), val);
+
+ mt7603_mac_start(dev);
+ mutex_unlock(&dev->mt76.mutex);
+
+ return 0;
+}
+
+static void
+mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ const u8 *mac)
+{
+ struct mt7603_dev *dev = hw->priv;
+
+ set_bit(MT76_SCANNING, &dev->mt76.state);
+ mt7603_beacon_set_timer(dev, -1, 0);
+}
+
+static void
+mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ struct mt7603_dev *dev = hw->priv;
+
+ clear_bit(MT76_SCANNING, &dev->mt76.state);
+ mt7603_beacon_set_timer(dev, -1, dev->beacon_int);
+}
+
+static void
+mt7603_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+}
+
+static int
+mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params)
+{
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ struct mt7603_dev *dev = hw->priv;
+ struct ieee80211_sta *sta = params->sta;
+ struct ieee80211_txq *txq = sta->txq[params->tid];
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ u16 tid = params->tid;
+ u16 *ssn = &params->ssn;
+ u8 ba_size = params->buf_size;
+ struct mt76_txq *mtxq;
+
+ if (!txq)
+ return -EINVAL;
+
+ mtxq = (struct mt76_txq *)txq->drv_priv;
+
+ switch (action) {
+ case IEEE80211_AMPDU_RX_START:
+ mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn,
+ params->buf_size);
+ mt7603_mac_rx_ba_reset(dev, sta->addr, tid);
+ break;
+ case IEEE80211_AMPDU_RX_STOP:
+ mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
+ break;
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+ mtxq->aggr = true;
+ mtxq->send_bar = false;
+ mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ mtxq->aggr = false;
+ ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn);
+ mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1);
+ break;
+ case IEEE80211_AMPDU_TX_START:
+ mtxq->agg_ssn = *ssn << 4;
+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_CONT:
+ mtxq->aggr = false;
+ mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1);
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ break;
+ }
+
+ return 0;
+}
+
+static void
+mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt7603_dev *dev = hw->priv;
+ struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
+ int i;
+
+ spin_lock_bh(&dev->mt76.lock);
+ for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
+ msta->rates[i].idx = sta_rates->rate[i].idx;
+ msta->rates[i].count = sta_rates->rate[i].count;
+ msta->rates[i].flags = sta_rates->rate[i].flags;
+
+ if (msta->rates[i].idx < 0 || !msta->rates[i].count)
+ break;
+ }
+ msta->n_rates = i;
+ mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates);
+ msta->rate_probe = false;
+ mt7603_wtbl_set_smps(dev, msta,
+ sta->smps_mode == IEEE80211_SMPS_DYNAMIC);
+ spin_unlock_bh(&dev->mt76.lock);
+}
+
+static void
+mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
+{
+ struct mt7603_dev *dev = hw->priv;
+
+ dev->coverage_class = coverage_class;
+ mt7603_mac_set_timing(dev);
+}
+
+static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt7603_dev *dev = hw->priv;
+ struct mt76_wcid *wcid = &dev->global_sta.wcid;
+
+ if (control->sta) {
+ struct mt7603_sta *msta;
+
+ msta = (struct mt7603_sta *)control->sta->drv_priv;
+ wcid = &msta->wcid;
+ } else if (vif) {
+ struct mt7603_vif *mvif;
+
+ mvif = (struct mt7603_vif *)vif->drv_priv;
+ wcid = &mvif->sta.wcid;
+ }
+
+ mt76_tx(&dev->mt76, control->sta, wcid, skb);
+}
+
+static int
+mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
+{
+ return 0;
+}
+
+const struct ieee80211_ops mt7603_ops = {
+ .tx = mt7603_tx,
+ .start = mt7603_start,
+ .stop = mt7603_stop,
+ .add_interface = mt7603_add_interface,
+ .remove_interface = mt7603_remove_interface,
+ .config = mt7603_config,
+ .configure_filter = mt7603_configure_filter,
+ .bss_info_changed = mt7603_bss_info_changed,
+ .sta_state = mt76_sta_state,
+ .set_key = mt7603_set_key,
+ .conf_tx = mt7603_conf_tx,
+ .sw_scan_start = mt7603_sw_scan,
+ .sw_scan_complete = mt7603_sw_scan_complete,
+ .flush = mt7603_flush,
+ .ampdu_action = mt7603_ampdu_action,
+ .get_txpower = mt76_get_txpower,
+ .wake_tx_queue = mt76_wake_tx_queue,
+ .sta_rate_tbl_update = mt7603_sta_rate_tbl_update,
+ .release_buffered_frames = mt7603_release_buffered_frames,
+ .set_coverage_class = mt7603_set_coverage_class,
+ .set_tim = mt7603_set_tim,
+ .get_survey = mt76_get_survey,
+};
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+static int __init mt7603_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&mt76_wmac_driver);
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_PCI
+ ret = pci_register_driver(&mt7603_pci_driver);
+ if (ret)
+ platform_driver_unregister(&mt76_wmac_driver);
+#endif
+ return ret;
+}
+
+static void __exit mt7603_exit(void)
+{
+#ifdef CONFIG_PCI
+ pci_unregister_driver(&mt7603_pci_driver);
+#endif
+ platform_driver_unregister(&mt76_wmac_driver);
+}
+
+module_init(mt7603_init);
+module_exit(mt7603_exit);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
new file mode 100644
index 000000000000..4b0713f1fd5e
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -0,0 +1,483 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/firmware.h>
+#include "mt7603.h"
+#include "mcu.h"
+#include "eeprom.h"
+
+#define MCU_SKB_RESERVE 8
+
+struct mt7603_fw_trailer {
+ char fw_ver[10];
+ char build_date[15];
+ __le32 dl_len;
+} __packed;
+
+static int
+__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
+ int query, int *wait_seq)
+{
+ int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12;
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt7603_mcu_txd *txd;
+ u8 seq;
+
+ if (!skb)
+ return -EINVAL;
+
+ seq = ++mdev->mmio.mcu.msg_seq & 0xf;
+ if (!seq)
+ seq = ++mdev->mmio.mcu.msg_seq & 0xf;
+
+ txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen);
+ memset(txd, 0, hdrlen);
+
+ txd->len = cpu_to_le16(skb->len);
+ if (cmd == -MCU_CMD_FW_SCATTER)
+ txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW);
+ else
+ txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE);
+ txd->pkt_type = MCU_PKT_ID;
+ txd->seq = seq;
+
+ if (cmd < 0) {
+ txd->cid = -cmd;
+ } else {
+ txd->cid = MCU_CMD_EXT_CID;
+ txd->ext_cid = cmd;
+ if (query != MCU_Q_NA)
+ txd->ext_cid_ack = 1;
+ }
+
+ txd->set_query = query;
+
+ if (wait_seq)
+ *wait_seq = seq;
+
+ return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0);
+}
+
+static int
+mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
+ int query)
+{
+ struct mt76_dev *mdev = &dev->mt76;
+ unsigned long expires = jiffies + 3 * HZ;
+ struct mt7603_mcu_rxd *rxd;
+ int ret, seq;
+
+ mutex_lock(&mdev->mmio.mcu.mutex);
+
+ ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq);
+ if (ret)
+ goto out;
+
+ while (1) {
+ bool check_seq = false;
+
+ skb = mt76_mcu_get_response(&dev->mt76, expires);
+ if (!skb) {
+ dev_err(mdev->dev,
+ "MCU message %d (seq %d) timed out\n",
+ cmd, seq);
+ dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT;
+ ret = -ETIMEDOUT;
+ break;
+ }
+
+ rxd = (struct mt7603_mcu_rxd *)skb->data;
+ if (seq == rxd->seq)
+ check_seq = true;
+
+ dev_kfree_skb(skb);
+
+ if (check_seq)
+ break;
+ }
+
+out:
+ mutex_unlock(&mdev->mmio.mcu.mutex);
+
+ return ret;
+}
+
+static int
+mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
+{
+ struct {
+ __le32 addr;
+ __le32 len;
+ __le32 mode;
+ } req = {
+ .addr = cpu_to_le32(addr),
+ .len = cpu_to_le32(len),
+ .mode = cpu_to_le32(BIT(31)),
+ };
+ struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
+
+ return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
+ MCU_Q_NA);
+}
+
+static int
+mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len)
+{
+ struct sk_buff *skb;
+ int ret = 0;
+
+ while (len > 0) {
+ int cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd),
+ len);
+
+ skb = mt7603_mcu_msg_alloc(data, cur_len);
+ if (!skb)
+ return -ENOMEM;
+
+ ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER,
+ MCU_Q_NA, NULL);
+ if (ret)
+ break;
+
+ data += cur_len;
+ len -= cur_len;
+ }
+
+ return ret;
+}
+
+static int
+mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
+{
+ struct {
+ __le32 override;
+ __le32 addr;
+ } req = {
+ .override = cpu_to_le32(addr ? 1 : 0),
+ .addr = cpu_to_le32(addr),
+ };
+ struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
+
+ return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ,
+ MCU_Q_NA);
+}
+
+static int
+mt7603_mcu_restart(struct mt7603_dev *dev)
+{
+ struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0);
+
+ return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ,
+ MCU_Q_NA);
+}
+
+static int
+mt7603_load_firmware(struct mt7603_dev *dev)
+{
+ const struct firmware *fw;
+ const struct mt7603_fw_trailer *hdr;
+ const char *firmware;
+ int dl_len;
+ u32 addr, val;
+ int ret;
+
+ if (is_mt7628(dev)) {
+ if (mt76xx_rev(dev) == MT7628_REV_E1)
+ firmware = MT7628_FIRMWARE_E1;
+ else
+ firmware = MT7628_FIRMWARE_E2;
+ } else {
+ if (mt76xx_rev(dev) < MT7603_REV_E2)
+ firmware = MT7603_FIRMWARE_E1;
+ else
+ firmware = MT7603_FIRMWARE_E2;
+ }
+
+ ret = request_firmware(&fw, firmware, dev->mt76.dev);
+ if (ret)
+ return ret;
+
+ if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+ dev_err(dev->mt76.dev, "Invalid firmware\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ hdr = (const struct mt7603_fw_trailer *)(fw->data + fw->size -
+ sizeof(*hdr));
+
+ dev_info(dev->mt76.dev, "Firmware Version: %.10s\n", hdr->fw_ver);
+ dev_info(dev->mt76.dev, "Build Time: %.15s\n", hdr->build_date);
+
+ addr = mt7603_reg_map(dev, 0x50012498);
+ mt76_wr(dev, addr, 0x5);
+ mt76_wr(dev, addr, 0x5);
+ udelay(1);
+
+ /* switch to bypass mode */
+ mt76_rmw(dev, MT_SCH_4, MT_SCH_4_FORCE_QID,
+ MT_SCH_4_BYPASS | FIELD_PREP(MT_SCH_4_FORCE_QID, 5));
+
+ val = mt76_rr(dev, MT_TOP_MISC2);
+ if (val & BIT(1)) {
+ dev_info(dev->mt76.dev, "Firmware already running...\n");
+ goto running;
+ }
+
+ if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(0) | BIT(1), BIT(0), 500)) {
+ dev_err(dev->mt76.dev, "Timeout waiting for ROM code to become ready\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ dl_len = le32_to_cpu(hdr->dl_len) + 4;
+ ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len);
+ if (ret) {
+ dev_err(dev->mt76.dev, "Download request failed\n");
+ goto out;
+ }
+
+ ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len);
+ if (ret) {
+ dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
+ goto out;
+ }
+
+ ret = mt7603_mcu_start_firmware(dev, MCU_FIRMWARE_ADDRESS);
+ if (ret) {
+ dev_err(dev->mt76.dev, "Failed to start firmware\n");
+ goto out;
+ }
+
+ if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(1), BIT(1), 500)) {
+ dev_err(dev->mt76.dev, "Timeout waiting for firmware to initialize\n");
+ ret = -EIO;
+ goto out;
+ }
+
+running:
+ mt76_clear(dev, MT_SCH_4, MT_SCH_4_FORCE_QID | MT_SCH_4_BYPASS);
+
+ mt76_set(dev, MT_SCH_4, BIT(8));
+ mt76_clear(dev, MT_SCH_4, BIT(8));
+
+ dev->mcu_running = true;
+ dev_info(dev->mt76.dev, "firmware init done\n");
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+int mt7603_mcu_init(struct mt7603_dev *dev)
+{
+ mutex_init(&dev->mt76.mmio.mcu.mutex);
+
+ return mt7603_load_firmware(dev);
+}
+
+void mt7603_mcu_exit(struct mt7603_dev *dev)
+{
+ mt7603_mcu_restart(dev);
+ skb_queue_purge(&dev->mt76.mmio.mcu.res_q);
+}
+
+int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
+{
+ static const u16 req_fields[] = {
+#define WORD(_start) \
+ _start, \
+ _start + 1
+#define GROUP_2G(_start) \
+ WORD(_start), \
+ WORD(_start + 2), \
+ WORD(_start + 4)
+
+ MT_EE_NIC_CONF_0 + 1,
+ WORD(MT_EE_NIC_CONF_1),
+ MT_EE_WIFI_RF_SETTING,
+ MT_EE_TX_POWER_DELTA_BW40,
+ MT_EE_TX_POWER_DELTA_BW80 + 1,
+ MT_EE_TX_POWER_EXT_PA_5G,
+ MT_EE_TEMP_SENSOR_CAL,
+ GROUP_2G(MT_EE_TX_POWER_0_START_2G),
+ GROUP_2G(MT_EE_TX_POWER_1_START_2G),
+ WORD(MT_EE_TX_POWER_CCK),
+ WORD(MT_EE_TX_POWER_OFDM_2G_6M),
+ WORD(MT_EE_TX_POWER_OFDM_2G_24M),
+ WORD(MT_EE_TX_POWER_OFDM_2G_54M),
+ WORD(MT_EE_TX_POWER_HT_BPSK_QPSK),
+ WORD(MT_EE_TX_POWER_HT_16_64_QAM),
+ WORD(MT_EE_TX_POWER_HT_64_QAM),
+ MT_EE_ELAN_RX_MODE_GAIN,
+ MT_EE_ELAN_RX_MODE_NF,
+ MT_EE_ELAN_RX_MODE_P1DB,
+ MT_EE_ELAN_BYPASS_MODE_GAIN,
+ MT_EE_ELAN_BYPASS_MODE_NF,
+ MT_EE_ELAN_BYPASS_MODE_P1DB,
+ WORD(MT_EE_STEP_NUM_NEG_6_7),
+ WORD(MT_EE_STEP_NUM_NEG_4_5),
+ WORD(MT_EE_STEP_NUM_NEG_2_3),
+ WORD(MT_EE_STEP_NUM_NEG_0_1),
+ WORD(MT_EE_REF_STEP_24G),
+ WORD(MT_EE_STEP_NUM_PLUS_1_2),
+ WORD(MT_EE_STEP_NUM_PLUS_3_4),
+ WORD(MT_EE_STEP_NUM_PLUS_5_6),
+ MT_EE_STEP_NUM_PLUS_7,
+ MT_EE_XTAL_FREQ_OFFSET,
+ MT_EE_XTAL_TRIM_2_COMP,
+ MT_EE_XTAL_TRIM_3_COMP,
+ MT_EE_XTAL_WF_RFCAL,
+
+ /* unknown fields below */
+ WORD(0x24),
+ 0x34,
+ 0x39,
+ 0x3b,
+ WORD(0x42),
+ WORD(0x9e),
+ 0xf2,
+ WORD(0xf8),
+ 0xfa,
+ 0x12e,
+ WORD(0x130), WORD(0x132), WORD(0x134), WORD(0x136),
+ WORD(0x138), WORD(0x13a), WORD(0x13c), WORD(0x13e),
+
+#undef GROUP_2G
+#undef WORD
+
+ };
+ struct req_data {
+ u16 addr;
+ u8 val;
+ u8 pad;
+ } __packed;
+ struct {
+ u8 buffer_mode;
+ u8 len;
+ u8 pad[2];
+ } req_hdr = {
+ .buffer_mode = 1,
+ .len = ARRAY_SIZE(req_fields) - 1,
+ };
+ struct sk_buff *skb;
+ struct req_data *data;
+ const int size = 0xff * sizeof(struct req_data);
+ u8 *eep = (u8 *)dev->mt76.eeprom.data;
+ int i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size);
+
+ skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr));
+ memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr));
+ data = (struct req_data *)skb_put(skb, size);
+ memset(data, 0, size);
+
+ for (i = 0; i < ARRAY_SIZE(req_fields); i++) {
+ data[i].addr = cpu_to_le16(req_fields[i]);
+ data[i].val = eep[req_fields[i]];
+ data[i].pad = 0;
+ }
+
+ return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
+ MCU_Q_SET);
+}
+
+static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
+{
+ struct {
+ u8 center_channel;
+ u8 tssi;
+ u8 temp_comp;
+ u8 target_power[2];
+ u8 rate_power_delta[14];
+ u8 bw_power_delta;
+ u8 ch_power_delta[6];
+ u8 temp_comp_power[17];
+ u8 reserved;
+ } req = {
+ .center_channel = dev->mt76.chandef.chan->hw_value,
+#define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n]
+ .tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1),
+ .temp_comp = EEP_VAL(MT_EE_NIC_CONF_1),
+ .target_power = {
+ EEP_VAL(MT_EE_TX_POWER_0_START_2G + 2),
+ EEP_VAL(MT_EE_TX_POWER_1_START_2G + 2)
+ },
+ .bw_power_delta = EEP_VAL(MT_EE_TX_POWER_DELTA_BW40),
+ .ch_power_delta = {
+ EEP_VAL(MT_EE_TX_POWER_0_START_2G + 3),
+ EEP_VAL(MT_EE_TX_POWER_0_START_2G + 4),
+ EEP_VAL(MT_EE_TX_POWER_0_START_2G + 5),
+ EEP_VAL(MT_EE_TX_POWER_1_START_2G + 3),
+ EEP_VAL(MT_EE_TX_POWER_1_START_2G + 4),
+ EEP_VAL(MT_EE_TX_POWER_1_START_2G + 5)
+ },
+#undef EEP_VAL
+ };
+ struct sk_buff *skb;
+ u8 *eep = (u8 *)dev->mt76.eeprom.data;
+
+ memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK,
+ sizeof(req.rate_power_delta));
+
+ memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7,
+ sizeof(req.temp_comp_power));
+
+ skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
+ return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL,
+ MCU_Q_SET);
+}
+
+int mt7603_mcu_set_channel(struct mt7603_dev *dev)
+{
+ struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+ struct ieee80211_hw *hw = mt76_hw(dev);
+ int n_chains = __sw_hweight8(dev->mt76.antenna_mask);
+ struct {
+ u8 control_chan;
+ u8 center_chan;
+ u8 bw;
+ u8 tx_streams;
+ u8 rx_streams;
+ u8 _res0[7];
+ u8 txpower[21];
+ u8 _res1[3];
+ } req = {
+ .control_chan = chandef->chan->hw_value,
+ .center_chan = chandef->chan->hw_value,
+ .bw = MT_BW_20,
+ .tx_streams = n_chains,
+ .rx_streams = n_chains,
+ };
+ struct sk_buff *skb;
+ s8 tx_power;
+ int ret;
+ int i;
+
+ if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) {
+ req.bw = MT_BW_40;
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ req.center_chan += 2;
+ else
+ req.center_chan -= 2;
+ }
+
+ tx_power = hw->conf.power_level * 2;
+ if (dev->mt76.antenna_mask == 3)
+ tx_power -= 6;
+ tx_power = min(tx_power, dev->tx_power_limit);
+
+ dev->mt76.txpower_cur = tx_power;
+
+ for (i = 0; i < ARRAY_SIZE(req.txpower); i++)
+ req.txpower[i] = tx_power;
+
+ skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
+ ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH,
+ MCU_Q_SET);
+ if (ret)
+ return ret;
+
+ return mt7603_mcu_set_tx_power(dev);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h
new file mode 100644
index 000000000000..1bba369d5c8a
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: ISC */
+
+#ifndef __MT7603_MCU_H
+#define __MT7603_MCU_H
+
+struct mt7603_mcu_txd {
+ __le16 len;
+ __le16 pq_id;
+
+ u8 cid;
+ u8 pkt_type;
+ u8 set_query;
+ u8 seq;
+
+ u8 uc_d2b0_rev;
+ u8 ext_cid;
+ u8 uc_d2b2_rev;
+ u8 ext_cid_ack;
+
+ u32 au4_d3_to_d7_rev[5];
+} __packed __aligned(4);
+
+struct mt7603_mcu_rxd {
+ __le16 len;
+ __le16 pkt_type_id;
+
+ u8 eid;
+ u8 seq;
+ __le16 __rsv;
+
+ u8 ext_eid;
+ u8 __rsv1[3];
+};
+
+#define MCU_PKT_ID 0xa0
+#define MCU_PORT_QUEUE 0x8000
+#define MCU_PORT_QUEUE_FW 0xc000
+
+#define MCU_FIRMWARE_ADDRESS 0x100000
+
+enum {
+ MCU_Q_QUERY,
+ MCU_Q_SET,
+ MCU_Q_RESERVED,
+ MCU_Q_NA
+};
+
+enum {
+ MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01,
+ MCU_CMD_FW_START_REQ = 0x02,
+ MCU_CMD_INIT_ACCESS_REG = 0x3,
+ MCU_CMD_PATCH_START_REQ = 0x05,
+ MCU_CMD_PATCH_FINISH_REQ = 0x07,
+ MCU_CMD_PATCH_SEM_CONTROL = 0x10,
+ MCU_CMD_HIF_LOOPBACK = 0x20,
+ MCU_CMD_CH_PRIVILEGE = 0x20,
+ MCU_CMD_ACCESS_REG = 0xC2,
+ MCU_CMD_EXT_CID = 0xED,
+ MCU_CMD_FW_SCATTER = 0xEE,
+ MCU_CMD_RESTART_DL_REQ = 0xEF,
+};
+
+enum {
+ MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
+ MCU_EXT_CMD_RF_TEST = 0x04,
+ MCU_EXT_CMD_RADIO_ON_OFF_CTRL = 0x05,
+ MCU_EXT_CMD_WIFI_RX_DISABLE = 0x06,
+ MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
+ MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
+ MCU_EXT_CMD_NIC_CAPABILITY = 0x09,
+ MCU_EXT_CMD_PWR_SAVING = 0x0A,
+ MCU_EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E,
+ MCU_EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF,
+ MCU_EXT_CMD_SEC_ADDREMOVE_KEY = 0x10,
+ MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
+ MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
+ MCU_EXT_CMD_PS_RETRIEVE_START = 0x14,
+ MCU_EXT_CMD_LED_CTRL = 0x17,
+ MCU_EXT_CMD_PACKET_FILTER = 0x18,
+ MCU_EXT_CMD_PWR_MGT_BIT_WIFI = 0x1B,
+ MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
+ MCU_EXT_CMD_THERMAL_PROTECT = 0x23,
+ MCU_EXT_CMD_EDCA_SET = 0x27,
+ MCU_EXT_CMD_SLOT_TIME_SET = 0x28,
+ MCU_EXT_CMD_CONFIG_INTERNAL_SETTING = 0x29,
+ MCU_EXT_CMD_NOA_OFFLOAD_CTRL = 0x2B,
+ MCU_EXT_CMD_GET_THEMAL_SENSOR = 0x2C,
+ MCU_EXT_CMD_WAKEUP_OPTION = 0x2E,
+ MCU_EXT_CMD_AC_QUEUE_CONTROL = 0x31,
+ MCU_EXT_CMD_BCN_UPDATE = 0x33
+};
+
+enum {
+ MCU_EXT_EVENT_CMD_RESULT = 0x0,
+ MCU_EXT_EVENT_RF_REG_ACCESS = 0x2,
+ MCU_EXT_EVENT_MULTI_CR_ACCESS = 0x0E,
+ MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
+ MCU_EXT_EVENT_BEACON_LOSS = 0x1A,
+ MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
+ MCU_EXT_EVENT_BCN_UPDATE = 0x31,
+};
+
+static inline struct sk_buff *
+mt7603_mcu_msg_alloc(const void *data, int len)
+{
+ return mt76_mcu_msg_alloc(data, sizeof(struct mt7603_mcu_txd),
+ len, 0);
+}
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
new file mode 100644
index 000000000000..79f332429432
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: ISC */
+
+#ifndef __MT7603_H
+#define __MT7603_H
+
+#include <linux/interrupt.h>
+#include <linux/ktime.h>
+#include "../mt76.h"
+#include "regs.h"
+
+#define MT7603_MAX_INTERFACES 4
+#define MT7603_WTBL_SIZE 128
+#define MT7603_WTBL_RESERVED (MT7603_WTBL_SIZE - 1)
+#define MT7603_WTBL_STA (MT7603_WTBL_RESERVED - MT7603_MAX_INTERFACES)
+
+#define MT7603_RATE_RETRY 2
+
+#define MT7603_RX_RING_SIZE 128
+
+#define MT7603_FIRMWARE_E1 "mt7603_e1.bin"
+#define MT7603_FIRMWARE_E2 "mt7603_e2.bin"
+#define MT7628_FIRMWARE_E1 "mt7628_e1.bin"
+#define MT7628_FIRMWARE_E2 "mt7628_e2.bin"
+
+#define MT7603_EEPROM_SIZE 1024
+
+#define MT_AGG_SIZE_LIMIT(_n) (((_n) + 1) * 4)
+
+#define MT7603_PRE_TBTT_TIME 5000 /* ms */
+
+#define MT7603_WATCHDOG_TIME 100 /* ms */
+#define MT7603_WATCHDOG_TIMEOUT 10 /* number of checks */
+
+#define MT7603_EDCCA_BLOCK_TH 10
+
+#define MT7603_CFEND_RATE_DEFAULT 0x69 /* chip default (24M) */
+#define MT7603_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
+
+struct mt7603_vif;
+struct mt7603_sta;
+
+enum {
+ MT7603_REV_E1 = 0x00,
+ MT7603_REV_E2 = 0x10,
+ MT7628_REV_E1 = 0x8a00,
+};
+
+enum mt7603_bw {
+ MT_BW_20,
+ MT_BW_40,
+ MT_BW_80,
+};
+
+struct mt7603_sta {
+ struct mt76_wcid wcid; /* must be first */
+
+ struct mt7603_vif *vif;
+
+ struct sk_buff_head psq;
+
+ struct ieee80211_tx_rate rates[8];
+ u8 rate_count;
+ u8 n_rates;
+
+ u8 rate_probe;
+ u8 smps;
+
+ u8 ps;
+};
+
+struct mt7603_vif {
+ struct mt7603_sta sta; /* must be first */
+
+ u8 idx;
+};
+
+enum mt7603_reset_cause {
+ RESET_CAUSE_TX_HANG,
+ RESET_CAUSE_TX_BUSY,
+ RESET_CAUSE_RX_BUSY,
+ RESET_CAUSE_BEACON_STUCK,
+ RESET_CAUSE_RX_PSE_BUSY,
+ RESET_CAUSE_MCU_HANG,
+ RESET_CAUSE_RESET_FAILED,
+ __RESET_CAUSE_MAX
+};
+
+struct mt7603_dev {
+ struct mt76_dev mt76; /* must be first */
+
+ const struct mt76_bus_ops *bus_ops;
+
+ u32 rxfilter;
+
+ u8 vif_mask;
+
+ struct mt7603_sta global_sta;
+
+ u32 agc0, agc3;
+ u32 false_cca_ofdm, false_cca_cck;
+ unsigned long last_cca_adj;
+
+ u8 rssi_offset[3];
+
+ u8 slottime;
+ s16 coverage_class;
+
+ s8 tx_power_limit;
+
+ ktime_t survey_time;
+ ktime_t ed_time;
+ int beacon_int;
+
+ struct mt76_queue q_rx;
+
+ spinlock_t ps_lock;
+
+ u8 mac_work_count;
+
+ u8 mcu_running;
+ u8 ed_monitor;
+
+ s8 ed_trigger;
+ u8 ed_strict_mode;
+ u8 ed_strong_signal;
+
+ s8 sensitivity;
+
+ u8 beacon_mask;
+
+ u8 beacon_check;
+ u8 tx_hang_check;
+ u8 tx_dma_check;
+ u8 rx_dma_check;
+ u8 rx_pse_check;
+ u8 mcu_hang;
+
+ enum mt7603_reset_cause cur_reset_cause;
+
+ u16 tx_dma_idx[4];
+ u16 rx_dma_idx;
+
+ u32 reset_test;
+
+ unsigned int reset_cause[__RESET_CAUSE_MAX];
+
+ struct delayed_work mac_work;
+ struct tasklet_struct tx_tasklet;
+ struct tasklet_struct pre_tbtt_tasklet;
+};
+
+extern const struct mt76_driver_ops mt7603_drv_ops;
+extern const struct ieee80211_ops mt7603_ops;
+extern struct pci_driver mt7603_pci_driver;
+extern struct platform_driver mt76_wmac_driver;
+
+static inline bool is_mt7603(struct mt7603_dev *dev)
+{
+ return mt76xx_chip(dev) == 0x7603;
+}
+
+static inline bool is_mt7628(struct mt7603_dev *dev)
+{
+ return mt76xx_chip(dev) == 0x7628;
+}
+
+/* need offset to prevent conflict with ampdu_ack_len */
+#define MT_RATE_DRIVER_DATA_OFFSET 4
+
+u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr);
+
+irqreturn_t mt7603_irq_handler(int irq, void *dev_instance);
+
+int mt7603_register_device(struct mt7603_dev *dev);
+void mt7603_unregister_device(struct mt7603_dev *dev);
+int mt7603_eeprom_init(struct mt7603_dev *dev);
+int mt7603_dma_init(struct mt7603_dev *dev);
+void mt7603_dma_cleanup(struct mt7603_dev *dev);
+int mt7603_mcu_init(struct mt7603_dev *dev);
+void mt7603_init_debugfs(struct mt7603_dev *dev);
+
+void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set);
+
+static inline void mt7603_irq_enable(struct mt7603_dev *dev, u32 mask)
+{
+ mt7603_set_irq_mask(dev, 0, mask);
+}
+
+static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask)
+{
+ mt7603_set_irq_mask(dev, mask, 0);
+}
+
+void mt7603_mac_dma_start(struct mt7603_dev *dev);
+void mt7603_mac_start(struct mt7603_dev *dev);
+void mt7603_mac_stop(struct mt7603_dev *dev);
+void mt7603_mac_work(struct work_struct *work);
+void mt7603_mac_set_timing(struct mt7603_dev *dev);
+void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval);
+int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb);
+void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data);
+void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid);
+void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn,
+ int ba_size);
+
+void mt7603_pse_client_reset(struct mt7603_dev *dev);
+
+int mt7603_mcu_set_channel(struct mt7603_dev *dev);
+int mt7603_mcu_set_eeprom(struct mt7603_dev *dev);
+void mt7603_mcu_exit(struct mt7603_dev *dev);
+
+void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif,
+ const u8 *mac_addr);
+void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx);
+void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta);
+void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ struct ieee80211_tx_rate *probe_rate,
+ struct ieee80211_tx_rate *rates);
+int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
+ struct ieee80211_key_conf *key);
+void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ bool enabled);
+void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ bool enabled);
+void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort);
+
+int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info);
+
+void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
+ struct mt76_queue_entry *e, bool flush);
+
+void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ struct sk_buff *skb);
+void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
+void mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
+int mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+
+void mt7603_pre_tbtt_tasklet(unsigned long arg);
+
+void mt7603_update_channel(struct mt76_dev *mdev);
+
+void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val);
+void mt7603_cca_stats_reset(struct mt7603_dev *dev);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c
new file mode 100644
index 000000000000..4acdbf5d8968
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "mt7603.h"
+
+static const struct pci_device_id mt76pci_device_table[] = {
+ { PCI_DEVICE(0x14c3, 0x7603) },
+ { },
+};
+
+static int
+mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct mt7603_dev *dev;
+ struct mt76_dev *mdev;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
+ &mt7603_drv_ops);
+ if (!mdev)
+ return -ENOMEM;
+
+ dev = container_of(mdev, struct mt7603_dev, mt76);
+ mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
+
+ mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
+ (mt76_rr(dev, MT_HW_REV) & 0xff);
+ dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+
+ ret = devm_request_irq(mdev->dev, pdev->irq, mt7603_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret)
+ goto error;
+
+ ret = mt7603_register_device(dev);
+ if (ret)
+ goto error;
+
+ return 0;
+error:
+ ieee80211_free_hw(mt76_hw(dev));
+ return ret;
+}
+
+static void
+mt76pci_remove(struct pci_dev *pdev)
+{
+ struct mt76_dev *mdev = pci_get_drvdata(pdev);
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+
+ mt7603_unregister_device(dev);
+}
+
+MODULE_DEVICE_TABLE(pci, mt76pci_device_table);
+MODULE_FIRMWARE(MT7603_FIRMWARE_E1);
+MODULE_FIRMWARE(MT7603_FIRMWARE_E2);
+
+struct pci_driver mt7603_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = mt76pci_device_table,
+ .probe = mt76pci_probe,
+ .remove = mt76pci_remove,
+};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h
new file mode 100644
index 000000000000..da6827ae6cee
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h
@@ -0,0 +1,774 @@
+/* SPDX-License-Identifier: ISC */
+
+#ifndef __MT7603_REGS_H
+#define __MT7603_REGS_H
+
+#define MT_HW_REV 0x1000
+#define MT_HW_CHIPID 0x1008
+#define MT_TOP_MISC2 0x1134
+
+#define MT_MCU_BASE 0x2000
+#define MT_MCU(ofs) (MT_MCU_BASE + (ofs))
+
+#define MT_MCU_PCIE_REMAP_1 MT_MCU(0x500)
+#define MT_MCU_PCIE_REMAP_1_OFFSET GENMASK(17, 0)
+#define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18)
+
+#define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504)
+#define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0)
+#define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19)
+
+#define MT_HIF_BASE 0x4000
+#define MT_HIF(ofs) (MT_HIF_BASE + (ofs))
+
+#define MT_INT_SOURCE_CSR MT_HIF(0x200)
+#define MT_INT_MASK_CSR MT_HIF(0x204)
+#define MT_DELAY_INT_CFG MT_HIF(0x210)
+
+#define MT_INT_RX_DONE(_n) BIT(_n)
+#define MT_INT_RX_DONE_ALL GENMASK(1, 0)
+#define MT_INT_TX_DONE_ALL GENMASK(19, 4)
+#define MT_INT_TX_DONE(_n) BIT((_n) + 4)
+
+#define MT_INT_RX_COHERENT BIT(20)
+#define MT_INT_TX_COHERENT BIT(21)
+#define MT_INT_MAC_IRQ3 BIT(27)
+
+#define MT_INT_MCU_CMD BIT(30)
+
+#define MT_WPDMA_GLO_CFG MT_HIF(0x208)
+#define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0)
+#define MT_WPDMA_GLO_CFG_TX_DMA_BUSY BIT(1)
+#define MT_WPDMA_GLO_CFG_RX_DMA_EN BIT(2)
+#define MT_WPDMA_GLO_CFG_RX_DMA_BUSY BIT(3)
+#define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE GENMASK(5, 4)
+#define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6)
+#define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7)
+#define MT_WPDMA_GLO_CFG_HDR_SEG_LEN GENMASK(15, 8)
+#define MT_WPDMA_GLO_CFG_SW_RESET BIT(24)
+#define MT_WPDMA_GLO_CFG_FORCE_TX_EOF BIT(25)
+#define MT_WPDMA_GLO_CFG_CLK_GATE_DIS BIT(30)
+#define MT_WPDMA_GLO_CFG_RX_2B_OFFSET BIT(31)
+
+#define MT_WPDMA_RST_IDX MT_HIF(0x20c)
+
+#define MT_WPDMA_DEBUG MT_HIF(0x244)
+#define MT_WPDMA_DEBUG_VALUE GENMASK(17, 0)
+#define MT_WPDMA_DEBUG_SEL BIT(27)
+#define MT_WPDMA_DEBUG_IDX GENMASK(31, 28)
+
+#define MT_TX_RING_BASE MT_HIF(0x300)
+#define MT_RX_RING_BASE MT_HIF(0x400)
+
+#define MT_TXTIME_THRESH_BASE MT_HIF(0x500)
+#define MT_TXTIME_THRESH(n) (MT_TXTIME_THRESH_BASE + ((n) * 4))
+
+#define MT_PAGE_COUNT_BASE MT_HIF(0x540)
+#define MT_PAGE_COUNT(n) (MT_PAGE_COUNT_BASE + ((n) * 4))
+
+#define MT_SCH_1 MT_HIF(0x588)
+#define MT_SCH_2 MT_HIF(0x58c)
+#define MT_SCH_3 MT_HIF(0x590)
+
+#define MT_SCH_4 MT_HIF(0x594)
+#define MT_SCH_4_FORCE_QID GENMASK(4, 0)
+#define MT_SCH_4_BYPASS BIT(5)
+#define MT_SCH_4_RESET BIT(8)
+
+#define MT_GROUP_THRESH_BASE MT_HIF(0x598)
+#define MT_GROUP_THRESH(n) (MT_GROUP_THRESH_BASE + ((n) * 4))
+
+#define MT_QUEUE_PRIORITY_1 MT_HIF(0x580)
+#define MT_QUEUE_PRIORITY_2 MT_HIF(0x584)
+
+#define MT_BMAP_0 MT_HIF(0x5b0)
+#define MT_BMAP_1 MT_HIF(0x5b4)
+#define MT_BMAP_2 MT_HIF(0x5b8)
+
+#define MT_HIGH_PRIORITY_1 MT_HIF(0x5bc)
+#define MT_HIGH_PRIORITY_2 MT_HIF(0x5c0)
+
+#define MT_PRIORITY_MASK MT_HIF(0x5c4)
+
+#define MT_RSV_MAX_THRESH MT_HIF(0x5c8)
+
+#define MT_PSE_BASE 0x8000
+#define MT_PSE(ofs) (MT_PSE_BASE + (ofs))
+
+#define MT_MCU_DEBUG_RESET MT_PSE(0x16c)
+#define MT_MCU_DEBUG_RESET_PSE BIT(0)
+#define MT_MCU_DEBUG_RESET_PSE_S BIT(1)
+#define MT_MCU_DEBUG_RESET_QUEUES GENMASK(6, 2)
+
+#define MT_PSE_FC_P0 MT_PSE(0x120)
+#define MT_PSE_FC_P0_MIN_RESERVE GENMASK(11, 0)
+#define MT_PSE_FC_P0_MAX_QUOTA GENMASK(27, 16)
+
+#define MT_PSE_FRP MT_PSE(0x138)
+#define MT_PSE_FRP_P0 GENMASK(2, 0)
+#define MT_PSE_FRP_P1 GENMASK(5, 3)
+#define MT_PSE_FRP_P2_RQ0 GENMASK(8, 6)
+#define MT_PSE_FRP_P2_RQ1 GENMASK(11, 9)
+#define MT_PSE_FRP_P2_RQ2 GENMASK(14, 12)
+
+#define MT_FC_RSV_COUNT_0 MT_PSE(0x13c)
+#define MT_FC_RSV_COUNT_0_P0 GENMASK(11, 0)
+#define MT_FC_RSV_COUNT_0_P1 GENMASK(27, 16)
+
+#define MT_FC_SP2_Q0Q1 MT_PSE(0x14c)
+#define MT_FC_SP2_Q0Q1_SRC_COUNT_Q0 GENMASK(11, 0)
+#define MT_FC_SP2_Q0Q1_SRC_COUNT_Q1 GENMASK(27, 16)
+
+#define MT_PSE_FW_SHARED MT_PSE(0x17c)
+
+#define MT_PSE_RTA MT_PSE(0x194)
+#define MT_PSE_RTA_QUEUE_ID GENMASK(4, 0)
+#define MT_PSE_RTA_PORT_ID GENMASK(6, 5)
+#define MT_PSE_RTA_REDIRECT_EN BIT(7)
+#define MT_PSE_RTA_TAG_ID GENMASK(15, 8)
+#define MT_PSE_RTA_WRITE BIT(16)
+#define MT_PSE_RTA_BUSY BIT(31)
+
+#define MT_WF_PHY_BASE 0x10000
+#define MT_WF_PHY_OFFSET 0x1000
+#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs))
+
+#define MT_AGC_BASE MT_WF_PHY(0x500)
+#define MT_AGC(n) (MT_AGC_BASE + ((n) * 4))
+
+#define MT_AGC1_BASE MT_WF_PHY(0x1500)
+#define MT_AGC1(n) (MT_AGC1_BASE + ((n) * 4))
+
+#define MT_AGC_41_RSSI_0 GENMASK(23, 16)
+#define MT_AGC_41_RSSI_1 GENMASK(7, 0)
+
+#define MT_RXTD_BASE MT_WF_PHY(0x600)
+#define MT_RXTD(n) (MT_RXTD_BASE + ((n) * 4))
+
+#define MT_RXTD_6_ACI_TH GENMASK(4, 0)
+#define MT_RXTD_6_CCAED_TH GENMASK(14, 8)
+
+#define MT_RXTD_8_LOWER_SIGNAL GENMASK(5, 0)
+
+#define MT_RXTD_13_ACI_TH_EN BIT(0)
+
+#define MT_WF_PHY_CR_TSSI_BASE MT_WF_PHY(0xd00)
+#define MT_WF_PHY_CR_TSSI(phy, n) (MT_WF_PHY_CR_TSSI_BASE + \
+ ((phy) * MT_WF_PHY_OFFSET) + \
+ ((n) * 4))
+
+#define MT_PHYCTRL_BASE MT_WF_PHY(0x4100)
+#define MT_PHYCTRL(n) (MT_PHYCTRL_BASE + ((n) * 4))
+
+#define MT_PHYCTRL_2_STATUS_RESET BIT(6)
+#define MT_PHYCTRL_2_STATUS_EN BIT(7)
+
+#define MT_PHYCTRL_STAT_PD MT_PHYCTRL(3)
+#define MT_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16)
+#define MT_PHYCTRL_STAT_PD_CCK GENMASK(15, 0)
+
+#define MT_PHYCTRL_STAT_MDRDY MT_PHYCTRL(8)
+#define MT_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16)
+#define MT_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0)
+
+#define MT_WF_AGG_BASE 0x21200
+#define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs))
+
+#define MT_AGG_ARCR MT_WF_AGG(0x010)
+#define MT_AGG_ARCR_INIT_RATE1 BIT(0)
+#define MT_AGG_ARCR_FB_SGI_DISABLE BIT(1)
+#define MT_AGG_ARCR_RATE8_DOWN_WRAP BIT(2)
+#define MT_AGG_ARCR_RTS_RATE_THR GENMASK(12, 8)
+#define MT_AGG_ARCR_RATE_DOWN_RATIO GENMASK(17, 16)
+#define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19)
+#define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20)
+#define MT_AGG_ARCR_SPE_DIS_TH GENMASK(27, 24)
+
+#define MT_AGG_ARUCR MT_WF_AGG(0x014)
+#define MT_AGG_ARDCR MT_WF_AGG(0x018)
+#define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n))
+#define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \
+ MT_AGG_ARxCR_LIMIT_SHIFT(_n), \
+ MT_AGG_ARxCR_LIMIT_SHIFT(_n))
+
+#define MT_AGG_LIMIT MT_WF_AGG(0x040)
+#define MT_AGG_LIMIT_1 MT_WF_AGG(0x044)
+#define MT_AGG_LIMIT_AC(_n) GENMASK(((_n) + 1) * 8 - 1, (_n) * 8)
+
+#define MT_AGG_BA_SIZE_LIMIT_0 MT_WF_AGG(0x048)
+#define MT_AGG_BA_SIZE_LIMIT_1 MT_WF_AGG(0x04c)
+#define MT_AGG_BA_SIZE_LIMIT_SHIFT 8
+
+#define MT_AGG_PCR MT_WF_AGG(0x050)
+#define MT_AGG_PCR_MM BIT(16)
+#define MT_AGG_PCR_GF BIT(17)
+#define MT_AGG_PCR_BW40 BIT(18)
+#define MT_AGG_PCR_RIFS BIT(19)
+#define MT_AGG_PCR_BW80 BIT(20)
+#define MT_AGG_PCR_BW160 BIT(21)
+#define MT_AGG_PCR_ERP BIT(22)
+
+#define MT_AGG_PCR_RTS MT_WF_AGG(0x054)
+#define MT_AGG_PCR_RTS_THR GENMASK(19, 0)
+#define MT_AGG_PCR_RTS_PKT_THR GENMASK(31, 25)
+
+#define MT_AGG_CONTROL MT_WF_AGG(0x070)
+#define MT_AGG_CONTROL_NO_BA_RULE BIT(0)
+#define MT_AGG_CONTROL_NO_BA_AR_RULE BIT(1)
+#define MT_AGG_CONTROL_CFEND_SPE_EN BIT(3)
+#define MT_AGG_CONTROL_CFEND_RATE GENMASK(15, 4)
+#define MT_AGG_CONTROL_BAR_SPE_EN BIT(19)
+#define MT_AGG_CONTROL_BAR_RATE GENMASK(31, 20)
+
+#define MT_AGG_TMP MT_WF_AGG(0x0d8)
+
+#define MT_AGG_BWCR MT_WF_AGG(0x0ec)
+#define MT_AGG_BWCR_BW GENMASK(3, 2)
+
+#define MT_AGG_RETRY_CONTROL MT_WF_AGG(0x0f4)
+#define MT_AGG_RETRY_CONTROL_RTS_LIMIT GENMASK(11, 7)
+#define MT_AGG_RETRY_CONTROL_BAR_LIMIT GENMASK(15, 12)
+
+#define MT_WF_DMA_BASE 0x21c00
+#define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs))
+
+#define MT_DMA_DCR0 MT_WF_DMA(0x000)
+#define MT_DMA_DCR1 MT_WF_DMA(0x004)
+
+#define MT_DMA_FQCR0 MT_WF_DMA(0x008)
+#define MT_DMA_FQCR0_TARGET_WCID GENMASK(7, 0)
+#define MT_DMA_FQCR0_TARGET_BSS GENMASK(13, 8)
+#define MT_DMA_FQCR0_TARGET_QID GENMASK(20, 16)
+#define MT_DMA_FQCR0_DEST_PORT_ID GENMASK(23, 22)
+#define MT_DMA_FQCR0_DEST_QUEUE_ID GENMASK(28, 24)
+#define MT_DMA_FQCR0_MODE BIT(29)
+#define MT_DMA_FQCR0_STATUS BIT(30)
+#define MT_DMA_FQCR0_BUSY BIT(31)
+
+#define MT_DMA_RCFR0 MT_WF_DMA(0x070)
+#define MT_DMA_VCFR0 MT_WF_DMA(0x07c)
+
+#define MT_DMA_TCFR0 MT_WF_DMA(0x080)
+#define MT_DMA_TCFR1 MT_WF_DMA(0x084)
+#define MT_DMA_TCFR_TXS_AGGR_TIMEOUT GENMASK(27, 16)
+#define MT_DMA_TCFR_TXS_QUEUE BIT(14)
+#define MT_DMA_TCFR_TXS_AGGR_COUNT GENMASK(12, 8)
+#define MT_DMA_TCFR_TXS_BIT_MAP GENMASK(6, 0)
+
+#define MT_DMA_TMCFR0 MT_WF_DMA(0x088)
+
+#define MT_WF_ARB_BASE 0x21400
+#define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs))
+
+#define MT_WMM_AIFSN MT_WF_ARB(0x020)
+#define MT_WMM_AIFSN_MASK GENMASK(3, 0)
+#define MT_WMM_AIFSN_SHIFT(_n) ((_n) * 4)
+
+#define MT_WMM_CWMAX_BASE MT_WF_ARB(0x028)
+#define MT_WMM_CWMAX(_n) (MT_WMM_CWMAX_BASE + (((_n) / 2) << 2))
+#define MT_WMM_CWMAX_SHIFT(_n) (((_n) & 1) * 16)
+#define MT_WMM_CWMAX_MASK GENMASK(15, 0)
+
+#define MT_WMM_CWMIN MT_WF_ARB(0x040)
+#define MT_WMM_CWMIN_MASK GENMASK(7, 0)
+#define MT_WMM_CWMIN_SHIFT(_n) ((_n) * 8)
+
+#define MT_WF_ARB_RQCR MT_WF_ARB(0x070)
+#define MT_WF_ARB_RQCR_RX_START BIT(0)
+#define MT_WF_ARB_RQCR_RXV_START BIT(4)
+#define MT_WF_ARB_RQCR_RXV_R_EN BIT(7)
+#define MT_WF_ARB_RQCR_RXV_T_EN BIT(8)
+
+#define MT_ARB_SCR MT_WF_ARB(0x080)
+#define MT_ARB_SCR_BCNQ_OPMODE_MASK GENMASK(1, 0)
+#define MT_ARB_SCR_BCNQ_OPMODE_SHIFT(n) ((n) * 2)
+#define MT_ARB_SCR_TX_DISABLE BIT(8)
+#define MT_ARB_SCR_RX_DISABLE BIT(9)
+#define MT_ARB_SCR_BCNQ_EMPTY_SKIP BIT(28)
+#define MT_ARB_SCR_TTTT_BTIM_PRIO BIT(29)
+#define MT_ARB_SCR_TBTT_BCN_PRIO BIT(30)
+#define MT_ARB_SCR_TBTT_BCAST_PRIO BIT(31)
+
+enum {
+ MT_BCNQ_OPMODE_STA = 0,
+ MT_BCNQ_OPMODE_AP = 1,
+ MT_BCNQ_OPMODE_ADHOC = 2,
+};
+
+#define MT_WF_ARB_TX_START_0 MT_WF_ARB(0x100)
+#define MT_WF_ARB_TX_START_1 MT_WF_ARB(0x104)
+#define MT_WF_ARB_TX_FLUSH_0 MT_WF_ARB(0x108)
+#define MT_WF_ARB_TX_FLUSH_1 MT_WF_ARB(0x10c)
+#define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110)
+#define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114)
+
+#define MT_WF_ARB_BCN_START MT_WF_ARB(0x118)
+#define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n))
+#define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10)
+#define MT_WF_ARB_BCN_START_T_TTTT BIT(11)
+#define MT_WF_ARB_BCN_START_T_PRE_TBTT BIT(12)
+#define MT_WF_ARB_BCN_START_T_TBTT BIT(13)
+#define MT_WF_ARB_BCN_START_T_SLOT_IDLE BIT(14)
+#define MT_WF_ARB_BCN_START_T_TX_START BIT(15)
+#define MT_WF_ARB_BCN_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
+
+#define MT_WF_ARB_BCN_FLUSH MT_WF_ARB(0x11c)
+#define MT_WF_ARB_BCN_FLUSH_BSSn(n) BIT(0 + (n))
+#define MT_WF_ARB_BCN_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
+
+#define MT_WF_ARB_CAB_START MT_WF_ARB(0x120)
+#define MT_WF_ARB_CAB_START_BSSn(n) BIT(0 + (n))
+#define MT_WF_ARB_CAB_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
+
+#define MT_WF_ARB_CAB_FLUSH MT_WF_ARB(0x124)
+#define MT_WF_ARB_CAB_FLUSH_BSSn(n) BIT(0 + (n))
+#define MT_WF_ARB_CAB_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
+
+#define MT_WF_ARB_CAB_COUNT(n) MT_WF_ARB(0x128 + (n) * 4)
+#define MT_WF_ARB_CAB_COUNT_SHIFT 4
+#define MT_WF_ARB_CAB_COUNT_MASK GENMASK(3, 0)
+#define MT_WF_ARB_CAB_COUNT_B0_REG(n) MT_WF_ARB_CAB_COUNT(((n) > 12 ? 2 : \
+ ((n) > 4 ? 1 : 0)))
+#define MT_WF_ARB_CAB_COUNT_B0_SHIFT(n) (((n) > 12 ? (n) - 12 : \
+ ((n) > 4 ? (n) - 4 : \
+ (n) ? (n) + 3 : 0)) * 4)
+
+#define MT_TX_ABORT MT_WF_ARB(0x134)
+#define MT_TX_ABORT_EN BIT(0)
+#define MT_TX_ABORT_WCID GENMASK(15, 8)
+
+#define MT_WF_TMAC_BASE 0x21600
+#define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs))
+
+#define MT_TMAC_TCR MT_WF_TMAC(0x000)
+#define MT_TMAC_TCR_BLINK_SEL GENMASK(7, 6)
+#define MT_TMAC_TCR_PRE_RTS_GUARD GENMASK(11, 8)
+#define MT_TMAC_TCR_PRE_RTS_SEC_IDLE GENMASK(13, 12)
+#define MT_TMAC_TCR_RTS_SIGTA BIT(14)
+#define MT_TMAC_TCR_LDPC_OFS BIT(15)
+#define MT_TMAC_TCR_TX_STREAMS GENMASK(17, 16)
+#define MT_TMAC_TCR_SCH_IDLE_SEL GENMASK(19, 18)
+#define MT_TMAC_TCR_SCH_DET_PER_IOD BIT(20)
+#define MT_TMAC_TCR_DCH_DET_DISABLE BIT(21)
+#define MT_TMAC_TCR_TX_RIFS BIT(22)
+#define MT_TMAC_TCR_RX_RIFS_MODE BIT(23)
+#define MT_TMAC_TCR_TXOP_TBTT_CTL BIT(24)
+#define MT_TMAC_TCR_TBTT_TX_STOP_CTL BIT(25)
+#define MT_TMAC_TCR_TXOP_BURST_STOP BIT(26)
+#define MT_TMAC_TCR_RDG_RA_MODE BIT(27)
+#define MT_TMAC_TCR_RDG_RESP BIT(29)
+#define MT_TMAC_TCR_RDG_NO_PENDING BIT(30)
+#define MT_TMAC_TCR_SMOOTHING BIT(31)
+
+#define MT_WMM_TXOP_BASE MT_WF_TMAC(0x010)
+#define MT_WMM_TXOP(_n) (MT_WMM_TXOP_BASE + \
+ ((((_n) / 2) ^ 0x1) << 2))
+#define MT_WMM_TXOP_SHIFT(_n) (((_n) & 1) * 16)
+#define MT_WMM_TXOP_MASK GENMASK(15, 0)
+
+#define MT_TIMEOUT_CCK MT_WF_TMAC(0x090)
+#define MT_TIMEOUT_OFDM MT_WF_TMAC(0x094)
+#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
+#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
+
+#define MT_TXREQ MT_WF_TMAC(0x09c)
+#define MT_TXREQ_CCA_SRC_SEL GENMASK(31, 30)
+
+#define MT_RXREQ MT_WF_TMAC(0x0a0)
+#define MT_RXREQ_DELAY GENMASK(8, 0)
+
+#define MT_IFS MT_WF_TMAC(0x0a4)
+#define MT_IFS_EIFS GENMASK(8, 0)
+#define MT_IFS_RIFS GENMASK(14, 10)
+#define MT_IFS_SIFS GENMASK(22, 16)
+#define MT_IFS_SLOT GENMASK(30, 24)
+
+#define MT_TMAC_PCR MT_WF_TMAC(0x0b4)
+#define MT_TMAC_PCR_RATE GENMASK(8, 0)
+#define MT_TMAC_PCR_RATE_FIXED BIT(15)
+#define MT_TMAC_PCR_ANT_ID GENMASK(21, 16)
+#define MT_TMAC_PCR_ANT_ID_SEL BIT(22)
+#define MT_TMAC_PCR_SPE_EN BIT(23)
+#define MT_TMAC_PCR_ANT_PRI GENMASK(26, 24)
+#define MT_TMAC_PCR_ANT_PRI_SEL GENMASK(27)
+
+#define MT_WF_RMAC_BASE 0x21800
+#define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs))
+
+#define MT_WF_RFCR MT_WF_RMAC(0x000)
+#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0)
+#define MT_WF_RFCR_DROP_FCSFAIL BIT(1)
+#define MT_WF_RFCR_DROP_VERSION BIT(3)
+#define MT_WF_RFCR_DROP_PROBEREQ BIT(4)
+#define MT_WF_RFCR_DROP_MCAST BIT(5)
+#define MT_WF_RFCR_DROP_BCAST BIT(6)
+#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7)
+#define MT_WF_RFCR_DROP_A3_MAC BIT(8)
+#define MT_WF_RFCR_DROP_A3_BSSID BIT(9)
+#define MT_WF_RFCR_DROP_A2_BSSID BIT(10)
+#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11)
+#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12)
+#define MT_WF_RFCR_DROP_CTL_RSV BIT(13)
+#define MT_WF_RFCR_DROP_CTS BIT(14)
+#define MT_WF_RFCR_DROP_RTS BIT(15)
+#define MT_WF_RFCR_DROP_DUPLICATE BIT(16)
+#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17)
+#define MT_WF_RFCR_DROP_OTHER_UC BIT(18)
+#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19)
+#define MT_WF_RFCR_DROP_NDPA BIT(20)
+#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21)
+
+#define MT_BSSID0(idx) MT_WF_RMAC(0x004 + (idx) * 8)
+#define MT_BSSID1(idx) MT_WF_RMAC(0x008 + (idx) * 8)
+#define MT_BSSID1_VALID BIT(16)
+
+#define MT_MAC_ADDR0(idx) MT_WF_RMAC(0x024 + (idx) * 8)
+#define MT_MAC_ADDR1(idx) MT_WF_RMAC(0x028 + (idx) * 8)
+#define MT_MAC_ADDR1_ADDR GENMASK(15, 0)
+#define MT_MAC_ADDR1_VALID BIT(16)
+
+#define MT_BA_CONTROL_0 MT_WF_RMAC(0x068)
+#define MT_BA_CONTROL_1 MT_WF_RMAC(0x06c)
+#define MT_BA_CONTROL_1_ADDR GENMASK(15, 0)
+#define MT_BA_CONTROL_1_TID GENMASK(19, 16)
+#define MT_BA_CONTROL_1_IGNORE_TID BIT(20)
+#define MT_BA_CONTROL_1_IGNORE_ALL BIT(21)
+#define MT_BA_CONTROL_1_RESET BIT(22)
+
+#define MT_WF_RMACDR MT_WF_RMAC(0x078)
+#define MT_WF_RMACDR_TSF_PROBERSP_DIS BIT(0)
+#define MT_WF_RMACDR_TSF_TIM BIT(4)
+#define MT_WF_RMACDR_MBSSID_MASK GENMASK(25, 24)
+#define MT_WF_RMACDR_CHECK_HTC_BY_RATE BIT(26)
+#define MT_WF_RMACDR_MAXLEN_20BIT BIT(30)
+
+#define MT_WF_RMAC_RMCR MT_WF_RMAC(0x080)
+#define MT_WF_RMAC_RMCR_SMPS_MODE GENMASK(21, 20)
+#define MT_WF_RMAC_RMCR_RX_STREAMS GENMASK(24, 22)
+#define MT_WF_RMAC_RMCR_SMPS_RTS BIT(25)
+
+#define MT_WF_RMAC_CH_FREQ MT_WF_RMAC(0x090)
+#define MT_WF_RMAC_MAXMINLEN MT_WF_RMAC(0x098)
+#define MT_WF_RFCR1 MT_WF_RMAC(0x0a4)
+#define MT_WF_RMAC_TMR_PA MT_WF_RMAC(0x0e0)
+
+#define MT_WF_SEC_BASE 0x21a00
+#define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs))
+
+#define MT_SEC_SCR MT_WF_SEC(0x004)
+#define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0)
+
+#define MT_WTBL_OFF_BASE 0x23000
+#define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n))
+
+#define MT_WTBL_UPDATE MT_WTBL_OFF(0x000)
+#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(7, 0)
+#define MT_WTBL_UPDATE_WTBL2 BIT(11)
+#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12)
+#define MT_WTBL_UPDATE_RATE_UPDATE BIT(13)
+#define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14)
+#define MT_WTBL_UPDATE_RX_COUNT_CLEAR BIT(15)
+#define MT_WTBL_UPDATE_BUSY BIT(16)
+
+#define MT_WTBL_RMVTCR MT_WTBL_OFF(0x008)
+#define MT_WTBL_RMVTCR_RX_MV_MODE BIT(23)
+
+#define MT_LPON_BASE 0x24000
+#define MT_LPON(n) (MT_LPON_BASE + (n))
+
+#define MT_LPON_BTEIR MT_LPON(0x020)
+#define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29)
+
+#define MT_PRE_TBTT MT_LPON(0x030)
+#define MT_PRE_TBTT_MASK GENMASK(7, 0)
+#define MT_PRE_TBTT_SHIFT 8
+
+#define MT_TBTT MT_LPON(0x034)
+#define MT_TBTT_PERIOD GENMASK(15, 0)
+#define MT_TBTT_DTIM_PERIOD GENMASK(23, 16)
+#define MT_TBTT_TBTT_WAKE_PERIOD GENMASK(27, 24)
+#define MT_TBTT_DTIM_WAKE_PERIOD GENMASK(30, 28)
+#define MT_TBTT_CAL_ENABLE BIT(31)
+
+#define MT_TBTT_TIMER_CFG MT_LPON(0x05c)
+
+#define MT_LPON_SBTOR(n) MT_LPON(0x0a0)
+#define MT_LPON_SBTOR_SUB_BSS_EN BIT(29)
+#define MT_LPON_SBTOR_TIME_OFFSET GENMASK(19, 0)
+
+#define MT_INT_WAKEUP_BASE 0x24400
+#define MT_INT_WAKEUP(n) (MT_INT_WAKEUP_BASE + (n))
+
+#define MT_HW_INT_STATUS(n) MT_INT_WAKEUP(0x3c + (n) * 8)
+#define MT_HW_INT_MASK(n) MT_INT_WAKEUP(0x40 + (n) * 8)
+
+#define MT_HW_INT3_TBTT0 BIT(15)
+#define MT_HW_INT3_PRE_TBTT0 BIT(31)
+
+#define MT_WTBL1_BASE 0x28000
+
+#define MT_WTBL_ON_BASE (MT_WTBL1_BASE + 0x2000)
+#define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n))
+
+#define MT_WTBL_RIUCR0 MT_WTBL_ON(0x200)
+
+#define MT_WTBL_RIUCR1 MT_WTBL_ON(0x204)
+#define MT_WTBL_RIUCR1_RATE0 GENMASK(11, 0)
+#define MT_WTBL_RIUCR1_RATE1 GENMASK(23, 12)
+#define MT_WTBL_RIUCR1_RATE2_LO GENMASK(31, 24)
+
+#define MT_WTBL_RIUCR2 MT_WTBL_ON(0x208)
+#define MT_WTBL_RIUCR2_RATE2_HI GENMASK(3, 0)
+#define MT_WTBL_RIUCR2_RATE3 GENMASK(15, 4)
+#define MT_WTBL_RIUCR2_RATE4 GENMASK(27, 16)
+#define MT_WTBL_RIUCR2_RATE5_LO GENMASK(31, 28)
+
+#define MT_WTBL_RIUCR3 MT_WTBL_ON(0x20c)
+#define MT_WTBL_RIUCR3_RATE5_HI GENMASK(7, 0)
+#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)
+#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20)
+
+#define MT_MIB_BASE 0x2c000
+#define MT_MIB(_n) (MT_MIB_BASE + (_n))
+
+#define MT_MIB_CTL MT_MIB(0x00)
+#define MT_MIB_CTL_PSCCA_TIME GENMASK(13, 11)
+#define MT_MIB_CTL_CCA_NAV_TX GENMASK(16, 14)
+#define MT_MIB_CTL_ED_TIME GENMASK(30, 28)
+#define MT_MIB_CTL_READ_CLR_DIS BIT(31)
+
+#define MT_MIB_STAT(_n) MT_MIB(0x08 + (_n) * 4)
+
+#define MT_MIB_STAT_CCA MT_MIB_STAT(9)
+#define MT_MIB_STAT_CCA_MASK GENMASK(23, 0)
+
+#define MT_MIB_STAT_PSCCA MT_MIB_STAT(16)
+#define MT_MIB_STAT_PSCCA_MASK GENMASK(23, 0)
+
+#define MT_MIB_STAT_ED MT_MIB_STAT(18)
+#define MT_MIB_STAT_ED_MASK GENMASK(23, 0)
+
+#define MT_PCIE_REMAP_BASE_1 0x40000
+#define MT_PCIE_REMAP_BASE_2 0x80000
+
+#define MT_TX_HW_QUEUE_MGMT 4
+#define MT_TX_HW_QUEUE_MCU 5
+#define MT_TX_HW_QUEUE_BCN 7
+#define MT_TX_HW_QUEUE_BMC 8
+
+#define MT_LED_BASE_PHYS 0x80024000
+#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n))
+
+#define MT_LED_CTRL MT_LED_PHYS(0x00)
+
+#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
+#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
+#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
+#define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n)))
+#define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n)))
+#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
+
+#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8))
+#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8))
+#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
+#define MT_LED_STATUS_OFF(_v) (((_v) << \
+ __ffs(MT_LED_STATUS_OFF_MASK)) & \
+ MT_LED_STATUS_OFF_MASK)
+#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
+#define MT_LED_STATUS_ON(_v) (((_v) << \
+ __ffs(MT_LED_STATUS_ON_MASK)) & \
+ MT_LED_STATUS_ON_MASK)
+#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 0)
+#define MT_LED_STATUS_DURATION(_v) (((_v) << \
+ __ffs(MT_LED_STATUS_DURATION_MASK)) &\
+ MT_LED_STATUS_DURATION_MASK)
+
+#define MT_CLIENT_BASE_PHYS_ADDR 0x800c0000
+
+#define MT_CLIENT_TMAC_INFO_TEMPLATE 0x040
+
+#define MT_CLIENT_STATUS 0x06c
+
+#define MT_CLIENT_RESET_TX 0x070
+#define MT_CLIENT_RESET_TX_R_E_1 BIT(16)
+#define MT_CLIENT_RESET_TX_R_E_2 BIT(17)
+#define MT_CLIENT_RESET_TX_R_E_1_S BIT(20)
+#define MT_CLIENT_RESET_TX_R_E_2_S BIT(21)
+
+#define MT_EFUSE_BASE 0x81070000
+
+#define MT_EFUSE_BASE_CTRL 0x000
+#define MT_EFUSE_BASE_CTRL_EMPTY BIT(30)
+
+#define MT_EFUSE_CTRL 0x008
+#define MT_EFUSE_CTRL_AOUT GENMASK(5, 0)
+#define MT_EFUSE_CTRL_MODE GENMASK(7, 6)
+#define MT_EFUSE_CTRL_LDO_OFF_TIME GENMASK(13, 8)
+#define MT_EFUSE_CTRL_LDO_ON_TIME GENMASK(15, 14)
+#define MT_EFUSE_CTRL_AIN GENMASK(25, 16)
+#define MT_EFUSE_CTRL_VALID BIT(29)
+#define MT_EFUSE_CTRL_KICK BIT(30)
+#define MT_EFUSE_CTRL_SEL BIT(31)
+
+#define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4))
+#define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4))
+
+#define MT_CLIENT_RXINF 0x068
+#define MT_CLIENT_RXINF_RXSH_GROUPS GENMASK(2, 0)
+
+#define MT_PSE_BASE_PHYS_ADDR 0xa0000000
+
+#define MT_PSE_WTBL_2_PHYS_ADDR 0xa5000000
+
+#define MT_WTBL1_SIZE (8 * 4)
+#define MT_WTBL2_SIZE (16 * 4)
+#define MT_WTBL3_OFFSET (MT7603_WTBL_SIZE * MT_WTBL2_SIZE)
+#define MT_WTBL3_SIZE (16 * 4)
+#define MT_WTBL4_OFFSET (MT7603_WTBL_SIZE * MT_WTBL3_SIZE + \
+ MT_WTBL3_OFFSET)
+#define MT_WTBL4_SIZE (8 * 4)
+
+#define MT_WTBL1_W0_ADDR_HI GENMASK(15, 0)
+#define MT_WTBL1_W0_MUAR_IDX GENMASK(21, 16)
+#define MT_WTBL1_W0_RX_CHECK_A1 BIT(22)
+#define MT_WTBL1_W0_KEY_IDX GENMASK(24, 23)
+#define MT_WTBL1_W0_RX_CHECK_KEY_IDX BIT(25)
+#define MT_WTBL1_W0_RX_KEY_VALID BIT(26)
+#define MT_WTBL1_W0_RX_IK_VALID BIT(27)
+#define MT_WTBL1_W0_RX_VALID BIT(28)
+#define MT_WTBL1_W0_RX_CHECK_A2 BIT(29)
+#define MT_WTBL1_W0_RX_DATA_VALID BIT(30)
+#define MT_WTBL1_W0_WRITE_BURST BIT(31)
+
+#define MT_WTBL1_W1_ADDR_LO GENMASK(31, 0)
+
+#define MT_WTBL1_W2_MPDU_DENSITY GENMASK(2, 0)
+#define MT_WTBL1_W2_KEY_TYPE GENMASK(6, 3)
+#define MT_WTBL1_W2_EVEN_PN BIT(7)
+#define MT_WTBL1_W2_TO_DS BIT(8)
+#define MT_WTBL1_W2_FROM_DS BIT(9)
+#define MT_WTBL1_W2_HEADER_TRANS BIT(10)
+#define MT_WTBL1_W2_AMPDU_FACTOR GENMASK(13, 11)
+#define MT_WTBL1_W2_PWR_MGMT BIT(14)
+#define MT_WTBL1_W2_RDG BIT(15)
+#define MT_WTBL1_W2_RTS BIT(16)
+#define MT_WTBL1_W2_CFACK BIT(17)
+#define MT_WTBL1_W2_RDG_BA BIT(18)
+#define MT_WTBL1_W2_SMPS BIT(19)
+#define MT_WTBL1_W2_TXS_BAF_REPORT BIT(20)
+#define MT_WTBL1_W2_DYN_BW BIT(21)
+#define MT_WTBL1_W2_LDPC BIT(22)
+#define MT_WTBL1_W2_ITXBF BIT(23)
+#define MT_WTBL1_W2_ETXBF BIT(24)
+#define MT_WTBL1_W2_TXOP_PS BIT(25)
+#define MT_WTBL1_W2_MESH BIT(26)
+#define MT_WTBL1_W2_QOS BIT(27)
+#define MT_WTBL1_W2_HT BIT(28)
+#define MT_WTBL1_W2_VHT BIT(29)
+#define MT_WTBL1_W2_ADMISSION_CONTROL BIT(30)
+#define MT_WTBL1_W2_GROUP_ID BIT(31)
+
+#define MT_WTBL1_W3_WTBL2_FRAME_ID GENMASK(10, 0)
+#define MT_WTBL1_W3_WTBL2_ENTRY_ID GENMASK(15, 11)
+#define MT_WTBL1_W3_WTBL4_FRAME_ID GENMASK(26, 16)
+#define MT_WTBL1_W3_CHECK_PER BIT(27)
+#define MT_WTBL1_W3_KEEP_I_PSM BIT(28)
+#define MT_WTBL1_W3_I_PSM BIT(29)
+#define MT_WTBL1_W3_POWER_SAVE BIT(30)
+#define MT_WTBL1_W3_SKIP_TX BIT(31)
+
+#define MT_WTBL1_W4_WTBL3_FRAME_ID GENMASK(10, 0)
+#define MT_WTBL1_W4_WTBL3_ENTRY_ID GENMASK(16, 11)
+#define MT_WTBL1_W4_WTBL4_ENTRY_ID GENMASK(22, 17)
+#define MT_WTBL1_W4_PARTIAL_AID GENMASK(31, 23)
+
+#define MT_WTBL2_W0_PN_LO GENMASK(31, 0)
+
+#define MT_WTBL2_W1_PN_HI GENMASK(15, 0)
+#define MT_WTBL2_W1_NON_QOS_SEQNO GENMASK(27, 16)
+
+#define MT_WTBL2_W2_TID0_SN GENMASK(11, 0)
+#define MT_WTBL2_W2_TID1_SN GENMASK(23, 12)
+#define MT_WTBL2_W2_TID2_SN_LO GENMASK(31, 24)
+
+#define MT_WTBL2_W3_TID2_SN_HI GENMASK(3, 0)
+#define MT_WTBL2_W3_TID3_SN GENMASK(15, 4)
+#define MT_WTBL2_W3_TID4_SN GENMASK(27, 16)
+#define MT_WTBL2_W3_TID5_SN_LO GENMASK(31, 28)
+
+#define MT_WTBL2_W4_TID5_SN_HI GENMASK(7, 0)
+#define MT_WTBL2_W4_TID6_SN GENMASK(19, 8)
+#define MT_WTBL2_W4_TID7_SN GENMASK(31, 20)
+
+#define MT_WTBL2_W5_TX_COUNT_RATE1 GENMASK(15, 0)
+#define MT_WTBL2_W5_FAIL_COUNT_RATE1 GENAMSK(31, 16)
+
+#define MT_WTBL2_W6_TX_COUNT_RATE2 GENMASK(7, 0)
+#define MT_WTBL2_W6_TX_COUNT_RATE3 GENMASK(15, 8)
+#define MT_WTBL2_W6_TX_COUNT_RATE4 GENMASK(23, 16)
+#define MT_WTBL2_W6_TX_COUNT_RATE5 GENMASK(31, 24)
+
+#define MT_WTBL2_W7_TX_COUNT_CUR_BW GENMASK(15, 0)
+#define MT_WTBL2_W7_FAIL_COUNT_CUR_BW GENMASK(31, 16)
+
+#define MT_WTBL2_W8_TX_COUNT_OTHER_BW GENMASK(15, 0)
+#define MT_WTBL2_W8_FAIL_COUNT_OTHER_BW GENMASK(31, 16)
+
+#define MT_WTBL2_W9_POWER_OFFSET GENMASK(4, 0)
+#define MT_WTBL2_W9_SPATIAL_EXT BIT(5)
+#define MT_WTBL2_W9_ANT_PRIORITY GENMASK(8, 6)
+#define MT_WTBL2_W9_CC_BW_SEL GENMASK(10, 9)
+#define MT_WTBL2_W9_CHANGE_BW_RATE GENMASK(13, 11)
+#define MT_WTBL2_W9_BW_CAP GENMASK(15, 14)
+#define MT_WTBL2_W9_SHORT_GI_20 BIT(16)
+#define MT_WTBL2_W9_SHORT_GI_40 BIT(17)
+#define MT_WTBL2_W9_SHORT_GI_80 BIT(18)
+#define MT_WTBL2_W9_SHORT_GI_160 BIT(19)
+#define MT_WTBL2_W9_MPDU_FAIL_COUNT GENMASK(25, 23)
+#define MT_WTBL2_W9_MPDU_OK_COUNT GENMASK(28, 26)
+#define MT_WTBL2_W9_RATE_IDX GENMASK(31, 29)
+
+#define MT_WTBL2_W10_RATE1 GENMASK(11, 0)
+#define MT_WTBL2_W10_RATE2 GENMASK(23, 12)
+#define MT_WTBL2_W10_RATE3_LO GENMASK(31, 24)
+
+#define MT_WTBL2_W11_RATE3_HI GENMASK(3, 0)
+#define MT_WTBL2_W11_RATE4 GENMASK(15, 4)
+#define MT_WTBL2_W11_RATE5 GENMASK(27, 16)
+#define MT_WTBL2_W11_RATE6_LO GENMASK(31, 28)
+
+#define MT_WTBL2_W12_RATE6_HI GENMASK(7, 0)
+#define MT_WTBL2_W12_RATE7 GENMASK(19, 8)
+#define MT_WTBL2_W12_RATE8 GENMASK(31, 20)
+
+#define MT_WTBL2_W13_AVG_RCPI0 GENMASK(7, 0)
+#define MT_WTBL2_W13_AVG_RCPI1 GENMASK(15, 8)
+#define MT_WTBL2_W13_AVG_RCPI2 GENAMSK(23, 16)
+
+#define MT_WTBL2_W14_CC_NOISE_1S GENMASK(6, 0)
+#define MT_WTBL2_W14_CC_NOISE_2S GENMASK(13, 7)
+#define MT_WTBL2_W14_CC_NOISE_3S GENMASK(20, 14)
+#define MT_WTBL2_W14_CHAN_EST_RMS GENMASK(24, 21)
+#define MT_WTBL2_W14_CC_NOISE_SEL BIT(15)
+#define MT_WTBL2_W14_ANT_SEL GENMASK(31, 26)
+
+#define MT_WTBL2_W15_BA_WIN_SIZE GENMASK(2, 0)
+#define MT_WTBL2_W15_BA_WIN_SIZE_SHIFT 3
+#define MT_WTBL2_W15_BA_EN_TIDS GENMASK(31, 24)
+
+#define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300)
+#define MT_WTBL1_OR_PSM_WRITE BIT(31)
+
+enum mt7603_cipher_type {
+ MT_CIPHER_NONE,
+ MT_CIPHER_WEP40,
+ MT_CIPHER_TKIP,
+ MT_CIPHER_TKIP_NO_MIC,
+ MT_CIPHER_AES_CCMP,
+ MT_CIPHER_WEP104,
+ MT_CIPHER_BIP_CMAC_128,
+ MT_CIPHER_WEP128,
+ MT_CIPHER_WAPI,
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c
new file mode 100644
index 000000000000..e13fea80d970
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: ISC */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "mt7603.h"
+
+static int
+mt76_wmac_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct mt7603_dev *dev;
+ void __iomem *mem_base;
+ struct mt76_dev *mdev;
+ int irq;
+ int ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get device IRQ\n");
+ return irq;
+ }
+
+ mem_base = devm_ioremap_resource(&pdev->dev, res);
+ if (!mem_base) {
+ dev_err(&pdev->dev, "Failed to get memory resource\n");
+ return -EINVAL;
+ }
+
+ mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
+ &mt7603_drv_ops);
+ if (!mdev)
+ return -ENOMEM;
+
+ dev = container_of(mdev, struct mt7603_dev, mt76);
+ mt76_mmio_init(mdev, mem_base);
+
+ mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
+ (mt76_rr(dev, MT_HW_REV) & 0xff);
+ dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+
+ ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret)
+ goto error;
+
+ ret = mt7603_register_device(dev);
+ if (ret)
+ goto error;
+
+ return 0;
+error:
+ ieee80211_free_hw(mt76_hw(dev));
+ return ret;
+}
+
+static int
+mt76_wmac_remove(struct platform_device *pdev)
+{
+ struct mt76_dev *mdev = platform_get_drvdata(pdev);
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+
+ mt7603_unregister_device(dev);
+
+ return 0;
+}
+
+static const struct of_device_id of_wmac_match[] = {
+ { .compatible = "mediatek,mt7628-wmac" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, of_wmac_match);
+MODULE_FIRMWARE(MT7628_FIRMWARE_E1);
+MODULE_FIRMWARE(MT7628_FIRMWARE_E2);
+
+struct platform_driver mt76_wmac_driver = {
+ .probe = mt76_wmac_probe,
+ .remove = mt76_wmac_remove,
+ .driver = {
+ .name = "mt76_wmac",
+ .of_match_table = of_wmac_match,
+ },
+};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 497e762978cc..ab6dfc026acb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -152,11 +152,11 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
return mt76x02_rate_power_val(val);
}
-void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
+void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
+ struct ieee80211_channel *chan,
+ struct mt76_rate_power *t)
{
- struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
- struct mt76_rate_power *t = &dev->mt76.rate_power;
u16 val, addr;
s8 delta;
@@ -189,7 +189,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126;
val = mt76x02_eeprom_get(dev, addr);
t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val);
- t->ht[6] = t->vht[6] = s6_to_s8(val >> 8);
+ t->ht[6] = t->ht[7] = t->vht[6] = t->vht[7] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 0, 1, 2, 3 stbc */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec;
@@ -205,31 +205,31 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
/* vht mcs 8, 9 5GHz */
val = mt76x02_eeprom_get(dev, 0x132);
- t->vht[7] = s6_to_s8(val);
- t->vht[8] = s6_to_s8(val >> 8);
+ t->vht[8] = s6_to_s8(val);
+ t->vht[9] = s6_to_s8(val >> 8);
delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev);
mt76x02_add_rate_power_offset(t, delta);
}
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
+void mt76x0_get_power_info(struct mt76x02_dev *dev,
+ struct ieee80211_channel *chan, s8 *tp)
{
struct mt76x0_chan_map {
u8 chan;
u8 offset;
} chan_map[] = {
- { 2, 0 }, { 4, 1 }, { 6, 2 }, { 8, 3 },
- { 10, 4 }, { 12, 5 }, { 14, 6 }, { 38, 0 },
- { 44, 1 }, { 48, 2 }, { 54, 3 }, { 60, 4 },
- { 64, 5 }, { 102, 6 }, { 108, 7 }, { 112, 8 },
- { 118, 9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
- { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
- { 167, 17 }, { 171, 18 }, { 173, 19 },
+ { 2, 0 }, { 4, 2 }, { 6, 4 }, { 8, 6 },
+ { 10, 8 }, { 12, 10 }, { 14, 12 }, { 38, 0 },
+ { 44, 2 }, { 48, 4 }, { 54, 6 }, { 60, 8 },
+ { 64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
+ { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
+ { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
+ { 167, 34 }, { 171, 36 }, { 175, 38 },
};
- struct ieee80211_channel *chan = dev->mt76.chandef.chan;
u8 offset, addr;
+ int i, idx = 0;
u16 data;
- int i;
if (mt76x0_tssi_enabled(dev)) {
s8 target_power;
@@ -239,14 +239,14 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
else
data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
- info[0] = target_power + mt76x0_get_delta(dev);
- info[1] = 0;
+ *tp = target_power + mt76x0_get_delta(dev);
return;
}
for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
- if (chan_map[i].chan <= chan->hw_value) {
+ if (chan->hw_value <= chan_map[i].chan) {
+ idx = (chan->hw_value == chan_map[i].chan);
offset = chan_map[i].offset;
break;
}
@@ -258,13 +258,16 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
} else {
switch (chan->hw_value) {
+ case 42:
+ offset = 2;
+ break;
case 58:
offset = 8;
break;
case 106:
offset = 14;
break;
- case 112:
+ case 122:
offset = 20;
break;
case 155:
@@ -277,14 +280,9 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
}
data = mt76x02_eeprom_get(dev, addr);
-
- info[0] = data;
- if (!info[0] || info[0] > 0x3f)
- info[0] = 5;
-
- info[1] = data >> 8;
- if (!info[1] || info[1] > 0x3f)
- info[1] = 5;
+ *tp = data >> (8 * idx);
+ if (*tp < 0 || *tp > 0x3f)
+ *tp = 5;
}
static int mt76x0_check_eeprom(struct mt76x02_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
index ee9ade9f3c8b..7f73034a23b1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
@@ -25,8 +25,11 @@ struct mt76x02_dev;
int mt76x0_eeprom_init(struct mt76x02_dev *dev);
void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
-void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev);
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info);
+void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
+ struct ieee80211_channel *chan,
+ struct mt76_rate_power *t);
+void mt76x0_get_power_info(struct mt76x02_dev *dev,
+ struct ieee80211_channel *chan, s8 *tp);
static inline s8 s6_to_s8(u32 val)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 87b575fe1c74..bcb72e019fd2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -18,6 +18,7 @@
#include "eeprom.h"
#include "mcu.h"
#include "initvals.h"
+#include "../mt76x02_phy.h"
static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
{
@@ -186,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev)
{
int i = 200, ok = 0;
+ mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+
/* Page count on TxQ */
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
(mt76_rr(dev, 0x0a30) & 0x000000ff) ||
@@ -262,27 +265,24 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
-struct mt76x02_dev *
-mt76x0_alloc_device(struct device *pdev,
- const struct mt76_driver_ops *drv_ops,
- const struct ieee80211_ops *ops)
+static void
+mt76x0_init_txpower(struct mt76x02_dev *dev,
+ struct ieee80211_supported_band *sband)
{
- struct mt76x02_dev *dev;
- struct mt76_dev *mdev;
-
- mdev = mt76_alloc_device(sizeof(*dev), ops);
- if (!mdev)
- return NULL;
+ struct ieee80211_channel *chan;
+ struct mt76_rate_power t;
+ s8 tp;
+ int i;
- mdev->dev = pdev;
- mdev->drv = drv_ops;
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
- dev = container_of(mdev, struct mt76x02_dev, mt76);
- mutex_init(&dev->phy_mutex);
+ mt76x0_get_tx_power_per_rate(dev, chan, &t);
+ mt76x0_get_power_info(dev, chan, &tp);
- return dev;
+ chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2;
+ }
}
-EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
int mt76x0_register_device(struct mt76x02_dev *dev)
{
@@ -296,9 +296,14 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
if (ret)
return ret;
- /* overwrite unsupported features */
- if (dev->mt76.cap.has_5ghz)
+ if (dev->mt76.cap.has_5ghz) {
+ /* overwrite unsupported features */
mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
+ mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband);
+ }
+
+ if (dev->mt76.cap.has_2ghz)
+ mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband);
mt76x02_init_debugfs(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
index a1657922758e..0290ba5869a5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h
@@ -88,6 +88,7 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
+ { MT_VHT_HT_FBK_CFG1, 0xedcba980 },
};
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index a803a9b6a4c5..fee16ab21edb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
mt76_rr(dev, MT_CH_IDLE);
mt76_rr(dev, MT_CH_BUSY);
+ mt76x02_edcca_init(dev, true);
+
if (mt76_is_mmio(dev)) {
mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->pre_tbtt_tasklet);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 46629f61673b..51fbd75dff31 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -50,10 +50,6 @@ static inline bool is_mt7630(struct mt76x02_dev *dev)
}
/* Init */
-struct mt76x02_dev *
-mt76x0_alloc_device(struct device *pdev,
- const struct mt76_driver_ops *drv_ops,
- const struct ieee80211_ops *ops);
int mt76x0_init_hardware(struct mt76x02_dev *dev);
int mt76x0_register_device(struct mt76x02_dev *dev);
void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index d895b6f3dc44..f302162036d0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -30,7 +30,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
mt76x02_mac_start(dev);
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
+ MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
@@ -99,7 +99,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.wake_tx_queue = mt76_wake_tx_queue,
.get_survey = mt76_get_survey,
- .get_txpower = mt76x02_get_txpower,
+ .get_txpower = mt76_get_txpower,
.flush = mt76x0e_flush,
.set_tim = mt76x0e_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
@@ -141,6 +141,15 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
mt76_clear(dev, 0x110, BIT(9));
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
+ mt76_wr(dev, MT_CH_TIME_CFG,
+ MT_CH_TIME_CFG_TIMER_EN |
+ MT_CH_TIME_CFG_TX_AS_BUSY |
+ MT_CH_TIME_CFG_RX_AS_BUSY |
+ MT_CH_TIME_CFG_NAV_AS_BUSY |
+ MT_CH_TIME_CFG_EIFS_AS_BUSY |
+ MT_CH_CCA_RC_EN |
+ FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
+
err = mt76x0_register_device(dev);
if (err < 0)
return err;
@@ -165,6 +174,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev;
+ struct mt76_dev *mdev;
int ret;
ret = pcim_enable_device(pdev);
@@ -181,16 +191,20 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
- dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops);
- if (!dev)
+ mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
+ &drv_ops);
+ if (!mdev)
return -ENOMEM;
- mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+ mutex_init(&dev->phy_mutex);
+
+ mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
- dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
- dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
+ mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
+ dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
- ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler,
+ ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 1eb1a802ed20..1fd22eb841c3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -845,17 +845,18 @@ static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
{
struct mt76_rate_power *t = &dev->mt76.rate_power;
- u8 info[2];
+ s8 info;
- mt76x0_get_tx_power_per_rate(dev);
- mt76x0_get_power_info(dev, info);
+ mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t);
+ mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info);
- mt76x02_add_rate_power_offset(t, info[0]);
+ mt76x02_add_rate_power_offset(t, info);
mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
- mt76x02_add_rate_power_offset(t, -info[0]);
+ mt76x02_add_rate_power_offset(t, -info);
- mt76x02_phy_set_txpower(dev, info[0], info[1]);
+ dev->target_power = info;
+ mt76x02_phy_set_txpower(dev, info, info);
}
void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
@@ -1075,7 +1076,9 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev)
u8 gain_delta;
int low_gain;
- dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
+ dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
+ if (!dev->cal.avg_rssi_all)
+ dev->cal.avg_rssi_all = -75;
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 0e6b43bb4678..91718647da02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -79,7 +79,6 @@ static void mt76x0u_cleanup(struct mt76x02_dev *dev)
clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
mt76x0_chip_onoff(dev, false, false);
mt76u_queues_deinit(&dev->mt76);
- mt76u_mcu_deinit(&dev->mt76);
}
static void mt76x0u_mac_stop(struct mt76x02_dev *dev)
@@ -118,7 +117,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
+ MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
@@ -155,48 +154,54 @@ static const struct ieee80211_ops mt76x0u_ops = {
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
- .get_txpower = mt76x02_get_txpower,
+ .get_txpower = mt76_get_txpower,
};
-static int mt76x0u_register_device(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
{
- struct ieee80211_hw *hw = dev->mt76.hw;
int err;
- err = mt76u_alloc_queues(&dev->mt76);
- if (err < 0)
- goto out_err;
-
- err = mt76u_mcu_init_rx(&dev->mt76);
- if (err < 0)
- goto out_err;
-
mt76x0_chip_onoff(dev, true, true);
- if (!mt76x02_wait_for_mac(&dev->mt76)) {
- err = -ETIMEDOUT;
- goto out_err;
- }
+
+ if (!mt76x02_wait_for_mac(&dev->mt76))
+ return -ETIMEDOUT;
err = mt76x0u_mcu_init(dev);
if (err < 0)
- goto out_err;
+ return err;
mt76x0_init_usb_dma(dev);
err = mt76x0_init_hardware(dev);
if (err < 0)
- goto out_err;
+ return err;
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
mt76_wr(dev, MT_TXOP_CTRL_CFG,
FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
+ return 0;
+}
+
+static int mt76x0u_register_device(struct mt76x02_dev *dev)
+{
+ struct ieee80211_hw *hw = dev->mt76.hw;
+ int err;
+
+ err = mt76u_alloc_queues(&dev->mt76);
+ if (err < 0)
+ goto out_err;
+
+ err = mt76x0u_init_hardware(dev);
+ if (err < 0)
+ goto out_err;
+
err = mt76x0_register_device(dev);
if (err < 0)
goto out_err;
/* check hw sg support in order to enable AMSDU */
- if (mt76u_check_sg(&dev->mt76))
+ if (dev->mt76.usb.sg_en)
hw->max_tx_fragments = MT_SG_MAX_SIZE;
else
hw->max_tx_fragments = 1;
@@ -223,14 +228,18 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
};
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct mt76x02_dev *dev;
+ struct mt76_dev *mdev;
u32 asic_rev, mac_rev;
int ret;
- dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops,
- &mt76x0u_ops);
- if (!dev)
+ mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
+ &drv_ops);
+ if (!mdev)
return -ENOMEM;
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+ mutex_init(&dev->phy_mutex);
+
/* Quirk for Archer T1U */
if (id->driver_info)
dev->no_2ghz = true;
@@ -240,27 +249,27 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
usb_set_intfdata(usb_intf, dev);
- mt76x02u_init_mcu(&dev->mt76);
- ret = mt76u_init(&dev->mt76, usb_intf);
+ mt76x02u_init_mcu(mdev);
+ ret = mt76u_init(mdev, usb_intf);
if (ret)
goto err;
/* Disable the HW, otherwise MCU fail to initalize on hot reboot */
mt76x0_chip_onoff(dev, false, false);
- if (!mt76x02_wait_for_mac(&dev->mt76)) {
+ if (!mt76x02_wait_for_mac(mdev)) {
ret = -ETIMEDOUT;
goto err;
}
asic_rev = mt76_rr(dev, MT_ASIC_VERSION);
mac_rev = mt76_rr(dev, MT_MAC_CSR0);
- dev_info(dev->mt76.dev, "ASIC revision: %08x MAC revision: %08x\n",
+ dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n",
asic_rev, mac_rev);
/* Note: vendor driver skips this check for MT76X0U */
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
- dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");
+ dev_warn(mdev->dev, "Warning: eFUSE not present\n");
ret = mt76x0u_register_device(dev);
if (ret < 0)
@@ -272,7 +281,7 @@ err:
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
- ieee80211_free_hw(dev->mt76.hw);
+ ieee80211_free_hw(mdev->hw);
return ret;
}
@@ -297,11 +306,11 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
pm_message_t state)
{
struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
- struct mt76_usb *usb = &dev->mt76.usb;
mt76u_stop_queues(&dev->mt76);
mt76x0u_mac_stop(dev);
- usb_kill_urb(usb->mcu.res.urb);
+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+ mt76x0_chip_onoff(dev, false, false);
return 0;
}
@@ -312,15 +321,6 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
struct mt76_usb *usb = &dev->mt76.usb;
int ret;
- reinit_completion(&usb->mcu.cmpl);
- ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
- MT_EP_IN_CMD_RESP,
- &usb->mcu.res, GFP_KERNEL,
- mt76u_mcu_complete_urb,
- &usb->mcu.cmpl);
- if (ret < 0)
- goto err;
-
ret = mt76u_submit_rx_buffers(&dev->mt76);
if (ret < 0)
goto err;
@@ -328,7 +328,7 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
tasklet_enable(&usb->rx_tasklet);
tasklet_enable(&usb->tx_tasklet);
- ret = mt76x0_init_hardware(dev);
+ ret = mt76x0u_init_hardware(dev);
if (ret)
goto err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
index 9d7585029df9..4a282761ca58 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
@@ -15,6 +15,7 @@
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
+#include <linux/module.h>
#include "mt76x0.h"
#include "mcu.h"
@@ -139,12 +140,6 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
mt76x02u_mcu_fw_reset(dev);
usleep_range(5000, 6000);
-/*
- mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
- MT_PBF_CFG_TX1Q_EN |
- MT_PBF_CFG_TX2Q_EN |
- MT_PBF_CFG_TX3Q_EN));
-*/
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 6782665049dd..6915cce5def9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -15,8 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef __MT76X02_UTIL_H
-#define __MT76X02_UTIL_H
+#ifndef __MT76x02_H
+#define __MT76x02_H
#include <linux/kfifo.h>
@@ -27,6 +27,10 @@
#include "mt76x02_dma.h"
#define MT_CALIBRATE_INTERVAL HZ
+#define MT_MAC_WORK_INTERVAL (HZ / 10)
+
+#define MT_WATCHDOG_TIME (HZ / 10)
+#define MT_TX_HANG_TH 10
#define MT_MAX_CHAINS 2
struct mt76x02_rx_freq_cal {
@@ -70,6 +74,8 @@ struct mt76x02_dev {
struct mutex phy_mutex;
+ u16 vif_mask;
+
u8 txdone_seq;
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
@@ -79,6 +85,7 @@ struct mt76x02_dev {
struct tasklet_struct pre_tbtt_tasklet;
struct delayed_work cal_work;
struct delayed_work mac_work;
+ struct delayed_work wdt_work;
u32 aggr_stats[32];
@@ -89,6 +96,10 @@ struct mt76x02_dev {
u8 tbtt_count;
u16 beacon_int;
+ u32 tx_hang_reset;
+ u8 tx_hang_check;
+ u8 mcu_timeout;
+
struct mt76x02_calibration cal;
s8 target_power;
@@ -101,6 +112,13 @@ struct mt76x02_dev {
u8 slottime;
struct mt76x02_dfs_pattern_detector dfs_pd;
+
+ /* edcca monitor */
+ bool ed_tx_blocked;
+ bool ed_monitor;
+ u8 ed_trigger;
+ u8 ed_silent;
+ ktime_t ed_time;
};
extern struct ieee80211_rate mt76x02_rates[12];
@@ -115,8 +133,7 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev);
-void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
- unsigned int idx);
+
int mt76x02_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void mt76x02_remove_interface(struct ieee80211_hw *hw,
@@ -136,6 +153,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev,
const struct ieee80211_tx_rate *rate);
s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr,
s8 max_txpwr_adj);
+void mt76x02_wdt_work(struct work_struct *work);
void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
@@ -158,8 +176,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac);
void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
-int mt76x02_get_txpower(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int *dbm);
void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -224,4 +240,4 @@ mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast)
return &sta->vif->group_wcid;
}
-#endif
+#endif /* __MT76x02_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c
index a9d52ba1e270..7580c5c986ff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c
@@ -133,5 +133,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
read_txpower);
debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc);
+
+ debugfs_create_u32("tx_hang_reset", 0400, dir, &dev->tx_hang_reset);
}
EXPORT_SYMBOL_GPL(mt76x02_init_debugfs);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
index 054609c634a2..e4649103efd4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
@@ -881,12 +881,18 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
{
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+ mutex_lock(&dev->mt76.mutex);
if (dfs_pd->region != region) {
tasklet_disable(&dfs_pd->dfs_tasklet);
+
+ dev->ed_monitor = region == NL80211_DFS_ETSI;
+ mt76x02_edcca_init(dev, true);
+
dfs_pd->region = region;
mt76x02_dfs_init_params(dev);
tasklet_enable(&dfs_pd->dfs_tasklet);
}
+ mutex_unlock(&dev->mt76.mutex);
}
void mt76x02_regd_notifier(struct wiphy *wiphy,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index c08bf371e527..91ff6598eccf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -130,10 +130,8 @@ static __le16
mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
const struct ieee80211_tx_rate *rate, u8 *nss_val)
{
+ u8 phy, rate_idx, nss, bw = 0;
u16 rateval;
- u8 phy, rate_idx;
- u8 nss = 1;
- u8 bw = 0;
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
rate_idx = rate->idx;
@@ -164,7 +162,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
phy = val >> 8;
rate_idx = val & 0xff;
- bw = 0;
+ nss = 1;
}
rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx);
@@ -293,6 +291,13 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
memset(txwi, 0, sizeof(*txwi));
+ if (!info->control.hw_key && wcid && wcid->hw_key_idx != 0xff &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ wcid = NULL;
+ ieee80211_get_tx_rates(info->control.vif, sta, skb,
+ info->control.rates, 1);
+ }
+
if (wcid)
txwi->wcid = wcid->idx;
else
@@ -309,7 +314,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
ccmp_pn[6] = pn >> 32;
ccmp_pn[7] = pn >> 40;
txwi->iv = *((__le32 *)&ccmp_pn[0]);
- txwi->eiv = *((__le32 *)&ccmp_pn[1]);
+ txwi->eiv = *((__le32 *)&ccmp_pn[4]);
}
spin_lock_bh(&dev->mt76.lock);
@@ -435,7 +440,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
}
if (wcid) {
- if (stat->pktid)
+ if (stat->pktid >= MT_PACKET_ID_FIRST)
status.skb = mt76_tx_status_skb_get(mdev, wcid,
stat->pktid, &list);
if (status.skb)
@@ -478,7 +483,9 @@ out:
}
static int
-mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
+mt76x02_mac_process_rate(struct mt76x02_dev *dev,
+ struct mt76_rx_status *status,
+ u16 rate)
{
u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
@@ -510,11 +517,15 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
status->encoding = RX_ENC_HT;
status->rate_idx = idx;
break;
- case MT_PHY_TYPE_VHT:
+ case MT_PHY_TYPE_VHT: {
+ u8 n_rxstream = dev->mt76.chainmask & 0xf;
+
status->encoding = RX_ENC_VHT;
status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
- status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
+ status->nss = min_t(u8, n_rxstream,
+ FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1);
break;
+ }
default:
return -EINVAL;
}
@@ -544,8 +555,11 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
return 0;
}
-void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr)
+void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr)
{
+ static const u8 null_addr[ETH_ALEN] = {};
+ int i;
+
ether_addr_copy(dev->mt76.macaddr, addr);
if (!is_valid_ether_addr(dev->mt76.macaddr)) {
@@ -559,6 +573,16 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr)
mt76_wr(dev, MT_MAC_ADDR_DW1,
get_unaligned_le16(dev->mt76.macaddr + 4) |
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
+
+ mt76_wr(dev, MT_MAC_BSSID_DW0,
+ get_unaligned_le32(dev->mt76.macaddr));
+ mt76_wr(dev, MT_MAC_BSSID_DW1,
+ get_unaligned_le16(dev->mt76.macaddr + 4) |
+ FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */
+ MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT);
+
+ for (i = 0; i < 16; i++)
+ mt76x02_mac_set_bssid(dev, i, null_addr);
}
EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr);
@@ -584,7 +608,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
u16 rate = le16_to_cpu(rxwi->rate);
u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
- int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf;
+ int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf;
s8 signal;
u8 pn_len;
u8 wcid;
@@ -644,12 +668,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->chains = BIT(0);
signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
- for (i = 1; i < nstreams; i++) {
- status->chains |= BIT(i);
- status->chain_signal[i] = mt76x02_mac_get_rssi(dev,
- rxwi->rssi[i],
- i);
- signal = max_t(s8, signal, status->chain_signal[i]);
+ status->chain_signal[0] = signal;
+ if (nstreams > 1) {
+ status->chains |= BIT(1);
+ status->chain_signal[1] = mt76x02_mac_get_rssi(dev,
+ rxwi->rssi[1],
+ 1);
+ signal = max_t(s8, signal, status->chain_signal[1]);
}
status->signal = signal;
status->freq = dev->mt76.chandef.chan->center_freq;
@@ -658,12 +683,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
- if (sta) {
- ewma_signal_add(&sta->rssi, status->signal);
- sta->inactive_count = 0;
- }
-
- return mt76x02_mac_process_rate(status, rate);
+ return mt76x02_mac_process_rate(dev, status, rate);
}
void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
@@ -715,7 +735,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
}
EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
-void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
+void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val)
{
u32 data = 0;
@@ -729,20 +749,89 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
mt76_rmw(dev, MT_OFDM_PROT_CFG,
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_MM20_PROT_CFG,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_MM40_PROT_CFG,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_GF20_PROT_CFG,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_GF40_PROT_CFG,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_TX_PROT_CFG6,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_TX_PROT_CFG7,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
- mt76_rmw(dev, MT_TX_PROT_CFG8,
- MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
+}
+
+void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
+ int ht_mode)
+{
+ int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+ bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+ u32 prot[6];
+ u32 vht_prot[3];
+ int i;
+ u16 rts_thr;
+
+ for (i = 0; i < ARRAY_SIZE(prot); i++) {
+ prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4);
+ prot[i] &= ~MT_PROT_CFG_CTRL;
+ if (i >= 2)
+ prot[i] &= ~MT_PROT_CFG_RATE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vht_prot); i++) {
+ vht_prot[i] = mt76_rr(dev, MT_TX_PROT_CFG6 + i * 4);
+ vht_prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE);
+ }
+
+ rts_thr = mt76_get_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH);
+
+ if (rts_thr != 0xffff)
+ prot[0] |= MT_PROT_CTRL_RTS_CTS;
+
+ if (legacy_prot) {
+ prot[1] |= MT_PROT_CTRL_CTS2SELF;
+
+ prot[2] |= MT_PROT_RATE_CCK_11;
+ prot[3] |= MT_PROT_RATE_CCK_11;
+ prot[4] |= MT_PROT_RATE_CCK_11;
+ prot[5] |= MT_PROT_RATE_CCK_11;
+
+ vht_prot[0] |= MT_PROT_RATE_CCK_11;
+ vht_prot[1] |= MT_PROT_RATE_CCK_11;
+ vht_prot[2] |= MT_PROT_RATE_CCK_11;
+ } else {
+ if (rts_thr != 0xffff)
+ prot[1] |= MT_PROT_CTRL_RTS_CTS;
+
+ prot[2] |= MT_PROT_RATE_OFDM_24;
+ prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
+ prot[4] |= MT_PROT_RATE_OFDM_24;
+ prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
+
+ vht_prot[0] |= MT_PROT_RATE_OFDM_24;
+ vht_prot[1] |= MT_PROT_RATE_DUP_OFDM_24;
+ vht_prot[2] |= MT_PROT_RATE_SGI_OFDM_24;
+ }
+
+ switch (mode) {
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+ prot[2] |= MT_PROT_CTRL_RTS_CTS;
+ prot[3] |= MT_PROT_CTRL_RTS_CTS;
+ prot[4] |= MT_PROT_CTRL_RTS_CTS;
+ prot[5] |= MT_PROT_CTRL_RTS_CTS;
+ vht_prot[0] |= MT_PROT_CTRL_RTS_CTS;
+ vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
+ vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+ prot[3] |= MT_PROT_CTRL_RTS_CTS;
+ prot[5] |= MT_PROT_CTRL_RTS_CTS;
+ vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
+ vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
+ break;
+ }
+
+ if (non_gf) {
+ prot[4] |= MT_PROT_CTRL_RTS_CTS;
+ prot[5] |= MT_PROT_CTRL_RTS_CTS;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(prot); i++)
+ mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
+
+ for (i = 0; i < ARRAY_SIZE(vht_prot); i++)
+ mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]);
}
void mt76x02_update_channel(struct mt76_dev *mdev)
@@ -774,8 +863,100 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
udelay(10);
- mt76_clear(dev, MT_MAC_SYS_CTRL,
- MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+}
+
+static void
+mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable)
+{
+ if (enable) {
+ u32 data;
+
+ mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
+ mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
+ /* enable pa-lna */
+ data = mt76_rr(dev, MT_TX_PIN_CFG);
+ data |= MT_TX_PIN_CFG_TXANT |
+ MT_TX_PIN_CFG_RXANT |
+ MT_TX_PIN_RFTR_EN |
+ MT_TX_PIN_TRSW_EN;
+ mt76_wr(dev, MT_TX_PIN_CFG, data);
+ } else {
+ mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
+ mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
+ /* disable pa-lna */
+ mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT);
+ mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_RXANT);
+ }
+ dev->ed_tx_blocked = !enable;
+}
+
+void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable)
+{
+ dev->ed_trigger = 0;
+ dev->ed_silent = 0;
+
+ if (dev->ed_monitor && enable) {
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+ u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20;
+
+ mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
+ mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+ mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0),
+ ed_th << 8 | ed_th);
+ mt76_set(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
+ } else {
+ mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
+ mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+ if (is_mt76x2(dev)) {
+ mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070);
+ mt76_set(dev, MT_TXOP_HLDR_ET,
+ MT_TXOP_HLDR_TX40M_BLK_EN);
+ } else {
+ mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464);
+ mt76_clear(dev, MT_TXOP_HLDR_ET,
+ MT_TXOP_HLDR_TX40M_BLK_EN);
+ }
+ }
+ mt76x02_edcca_tx_enable(dev, true);
+
+ /* clear previous CCA timer value */
+ mt76_rr(dev, MT_ED_CCA_TIMER);
+ dev->ed_time = ktime_get_boottime();
+}
+EXPORT_SYMBOL_GPL(mt76x02_edcca_init);
+
+#define MT_EDCCA_TH 92
+#define MT_EDCCA_BLOCK_TH 2
+static void mt76x02_edcca_check(struct mt76x02_dev *dev)
+{
+ ktime_t cur_time;
+ u32 active, val, busy;
+
+ cur_time = ktime_get_boottime();
+ val = mt76_rr(dev, MT_ED_CCA_TIMER);
+
+ active = ktime_to_us(ktime_sub(cur_time, dev->ed_time));
+ dev->ed_time = cur_time;
+
+ busy = (val * 100) / active;
+ busy = min_t(u32, busy, 100);
+
+ if (busy > MT_EDCCA_TH) {
+ dev->ed_trigger++;
+ dev->ed_silent = 0;
+ } else {
+ dev->ed_silent++;
+ dev->ed_trigger = 0;
+ }
+
+ if (dev->ed_trigger > MT_EDCCA_BLOCK_TH &&
+ !dev->ed_tx_blocked)
+ mt76x02_edcca_tx_enable(dev, false);
+ else if (dev->ed_silent > MT_EDCCA_BLOCK_TH &&
+ dev->ed_tx_blocked)
+ mt76x02_edcca_tx_enable(dev, true);
}
void mt76x02_mac_work(struct work_struct *work)
@@ -784,6 +965,8 @@ void mt76x02_mac_work(struct work_struct *work)
mac_work.work);
int i, idx;
+ mutex_lock(&dev->mt76.mutex);
+
mt76x02_update_channel(&dev->mt76);
for (i = 0, idx = 0; i < 16; i++) {
u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i));
@@ -792,14 +975,18 @@ void mt76x02_mac_work(struct work_struct *work)
dev->aggr_stats[idx++] += val >> 16;
}
- /* XXX: check beacon stuck for ap mode */
if (!dev->beacon_mask)
mt76x02_check_mac_err(dev);
+ if (dev->ed_monitor)
+ mt76x02_edcca_check(dev);
+
+ mutex_unlock(&dev->mt76.mutex);
+
mt76_tx_status_check(&dev->mt76, NULL, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
+ MT_MAC_WORK_INTERVAL);
}
void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr)
@@ -891,8 +1078,9 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
return 0;
}
-void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
- u8 vif_idx, bool val)
+static void
+__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
+ bool val, struct sk_buff *skb)
{
u8 old_mask = dev->beacon_mask;
bool en;
@@ -900,6 +1088,8 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
if (val) {
dev->beacon_mask |= BIT(vif_idx);
+ if (skb)
+ mt76x02_mac_set_beacon(dev, vif_idx, skb);
} else {
dev->beacon_mask &= ~BIT(vif_idx);
mt76x02_mac_set_beacon(dev, vif_idx, NULL);
@@ -910,14 +1100,37 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
en = dev->beacon_mask;
- mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
reg = MT_BEACON_TIME_CFG_BEACON_TX |
MT_BEACON_TIME_CFG_TBTT_EN |
MT_BEACON_TIME_CFG_TIMER_EN;
mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
+ if (mt76_is_usb(dev))
+ return;
+
+ mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
if (en)
mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
else
mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
}
+
+void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
+ struct ieee80211_vif *vif, bool val)
+{
+ u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx;
+ struct sk_buff *skb = NULL;
+
+ if (mt76_is_mmio(dev))
+ tasklet_disable(&dev->pre_tbtt_tasklet);
+ else if (val)
+ skb = ieee80211_beacon_get(mt76_hw(dev), vif);
+
+ if (!dev->beacon_mask)
+ dev->tbtt_count = 0;
+
+ __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
+
+ if (mt76_is_mmio(dev))
+ tasklet_enable(&dev->pre_tbtt_tasklet);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
index 4e597004c445..6b1f25d2f64c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
@@ -18,8 +18,6 @@
#ifndef __MT76X02_MAC_H
#define __MT76X02_MAC_H
-#include <linux/average.h>
-
struct mt76x02_dev;
struct mt76x02_tx_status {
@@ -41,8 +39,6 @@ struct mt76x02_vif {
u8 idx;
};
-DECLARE_EWMA(signal, 10, 8);
-
struct mt76x02_sta {
struct mt76_wcid wcid; /* must be first */
@@ -50,8 +46,6 @@ struct mt76x02_sta {
struct mt76x02_tx_status status;
int n_frames;
- struct ewma_signal rssi;
- int inactive_count;
};
#define MT_RXINFO_BA BIT(0)
@@ -194,8 +188,10 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
struct mt76x02_tx_status *stat, u8 *update);
int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
void *rxi);
-void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val);
-void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr);
+void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
+ int ht_mode);
+void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
+void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr);
void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta, int len);
@@ -208,6 +204,8 @@ void mt76x02_mac_work(struct work_struct *work);
void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr);
int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
struct sk_buff *skb);
-void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
- bool val);
+void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
+ struct ieee80211_vif *vif, bool val);
+
+void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
index b7f4edb729e3..6501b853b65c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
@@ -21,70 +21,13 @@
#include "mt76x02_mcu.h"
-static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
-{
- struct sk_buff *skb;
-
- skb = alloc_skb(len, GFP_KERNEL);
- if (!skb)
- return NULL;
- memcpy(skb_put(skb, len), data, len);
-
- return skb;
-}
-
-static struct sk_buff *
-mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires)
-{
- unsigned long timeout;
-
- if (!time_is_after_jiffies(expires))
- return NULL;
-
- timeout = expires - jiffies;
- wait_event_timeout(dev->mt76.mmio.mcu.wait,
- !skb_queue_empty(&dev->mt76.mmio.mcu.res_q),
- timeout);
- return skb_dequeue(&dev->mt76.mmio.mcu.res_q);
-}
-
-static int
-mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid,
- struct sk_buff *skb, int cmd, int seq)
-{
- struct mt76_queue *q = &dev->mt76.q_tx[qid];
- struct mt76_queue_buf buf;
- dma_addr_t addr;
- u32 tx_info;
-
- tx_info = MT_MCU_MSG_TYPE_CMD |
- FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) |
- FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) |
- FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
- FIELD_PREP(MT_MCU_MSG_LEN, skb->len);
-
- addr = dma_map_single(dev->mt76.dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev->mt76.dev, addr))
- return -ENOMEM;
-
- buf.addr = addr;
- buf.len = skb->len;
-
- spin_lock_bh(&q->lock);
- mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
- mt76_queue_kick(dev, q);
- spin_unlock_bh(&q->lock);
-
- return 0;
-}
-
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int len, bool wait_resp)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
unsigned long expires = jiffies + HZ;
struct sk_buff *skb;
+ u32 tx_info;
int ret;
u8 seq;
@@ -98,7 +41,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
if (!seq)
seq = ++mdev->mmio.mcu.msg_seq & 0xf;
- ret = mt76x02_tx_queue_mcu(dev, MT_TXQ_MCU, skb, cmd, seq);
+ tx_info = MT_MCU_MSG_TYPE_CMD |
+ FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) |
+ FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) |
+ FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
+ FIELD_PREP(MT_MCU_MSG_LEN, skb->len);
+
+ ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info);
if (ret)
goto out;
@@ -106,12 +55,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
u32 *rxfce;
bool check_seq = false;
- skb = mt76x02_mcu_get_response(dev, expires);
+ skb = mt76_mcu_get_response(&dev->mt76, expires);
if (!skb) {
dev_err(mdev->dev,
"MCU message %d (seq %d) timed out\n", cmd,
seq);
ret = -ETIMEDOUT;
+ dev->mcu_timeout = 1;
break;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
index 7e4004120102..a7b0d3e5df1d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h
@@ -96,6 +96,12 @@ struct mt76x02_patch_header {
u8 pad[2];
};
+static inline struct sk_buff *
+mt76x02_mcu_msg_alloc(const void *data, int len)
+{
+ return mt76_mcu_msg_alloc(data, 0, len, 0);
+}
+
int mt76x02_mcu_cleanup(struct mt76x02_dev *dev);
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param);
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 66315410aebe..1229f19f2b02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -79,24 +79,24 @@ mt76x02_resync_beacon_timer(struct mt76x02_dev *dev)
* Beacon timer drifts by 1us every tick, the timer is configured
* in 1/16 TU (64us) units.
*/
- if (dev->tbtt_count < 62)
+ if (dev->tbtt_count < 63)
return;
- if (dev->tbtt_count >= 64) {
- dev->tbtt_count = 0;
- return;
- }
-
/*
* The updated beacon interval takes effect after two TBTT, because
* at this point the original interval has already been loaded into
* the next TBTT_TIMER value
*/
- if (dev->tbtt_count == 62)
+ if (dev->tbtt_count == 63)
timer_val -= 1;
mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_INTVAL, timer_val);
+
+ if (dev->tbtt_count >= 64) {
+ dev->tbtt_count = 0;
+ return;
+ }
}
static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
@@ -116,14 +116,20 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_update_beacon_iter, dev);
+ mt76_csa_check(&dev->mt76);
+
+ if (dev->mt76.csa_complete)
+ return;
+
do {
nframes = skb_queue_len(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_add_buffered_bc, &data);
- } while (nframes != skb_queue_len(&data.q));
+ } while (nframes != skb_queue_len(&data.q) &&
+ skb_queue_len(&data.q) < 8);
- if (!nframes)
+ if (!skb_queue_len(&data.q))
return;
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
@@ -308,8 +314,12 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
tasklet_schedule(&dev->pre_tbtt_tasklet);
/* send buffered multicast frames now */
- if (intr & MT_INT_TBTT)
- mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
+ if (intr & MT_INT_TBTT) {
+ if (dev->mt76.csa_complete)
+ mt76_csa_finish(&dev->mt76);
+ else
+ mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
+ }
if (intr & MT_INT_TX_STAT) {
mt76x02_mac_poll_tx_status(dev, true);
@@ -384,3 +394,137 @@ void mt76x02_mac_start(struct mt76x02_dev *dev)
MT_INT_TX_STAT);
}
EXPORT_SYMBOL_GPL(mt76x02_mac_start);
+
+static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
+{
+ u32 dma_idx, prev_dma_idx;
+ struct mt76_queue *q;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ q = &dev->mt76.q_tx[i];
+
+ if (!q->queued)
+ continue;
+
+ prev_dma_idx = dev->mt76.tx_dma_idx[i];
+ dma_idx = ioread32(&q->regs->dma_idx);
+ dev->mt76.tx_dma_idx[i] = dma_idx;
+
+ if (prev_dma_idx == dma_idx)
+ break;
+ }
+
+ return i < 4;
+}
+
+static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
+{
+ u32 mask = dev->mt76.mmio.irqmask;
+ int i;
+
+ ieee80211_stop_queues(dev->mt76.hw);
+ set_bit(MT76_RESET, &dev->mt76.state);
+
+ tasklet_disable(&dev->pre_tbtt_tasklet);
+ tasklet_disable(&dev->tx_tasklet);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
+ napi_disable(&dev->mt76.napi[i]);
+
+ mutex_lock(&dev->mt76.mutex);
+
+ if (dev->beacon_mask)
+ mt76_clear(dev, MT_BEACON_TIME_CFG,
+ MT_BEACON_TIME_CFG_BEACON_TX |
+ MT_BEACON_TIME_CFG_TBTT_EN);
+
+ mt76x02_irq_disable(dev, mask);
+
+ /* perform device reset */
+ mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+ mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
+ mt76_clear(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
+ usleep_range(5000, 10000);
+ mt76_wr(dev, MT_INT_SOURCE_CSR, 0xffffffff);
+
+ /* let fw reset DMA */
+ mt76_set(dev, 0x734, 0x3);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
+ mt76_queue_tx_cleanup(dev, i, true);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_queue_rx_reset(dev, i);
+
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+ mt76_set(dev, MT_WPDMA_GLO_CFG,
+ MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
+ if (dev->ed_monitor)
+ mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+
+ if (dev->beacon_mask)
+ mt76_set(dev, MT_BEACON_TIME_CFG,
+ MT_BEACON_TIME_CFG_BEACON_TX |
+ MT_BEACON_TIME_CFG_TBTT_EN);
+
+ mt76x02_irq_enable(dev, mask);
+
+ mutex_unlock(&dev->mt76.mutex);
+
+ clear_bit(MT76_RESET, &dev->mt76.state);
+
+ tasklet_enable(&dev->tx_tasklet);
+ tasklet_schedule(&dev->tx_tasklet);
+
+ tasklet_enable(&dev->pre_tbtt_tasklet);
+
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) {
+ napi_enable(&dev->mt76.napi[i]);
+ napi_schedule(&dev->mt76.napi[i]);
+ }
+
+ ieee80211_wake_queues(dev->mt76.hw);
+
+ mt76_txq_schedule_all(&dev->mt76);
+}
+
+static void mt76x02_check_tx_hang(struct mt76x02_dev *dev)
+{
+ if (mt76x02_tx_hang(dev)) {
+ if (++dev->tx_hang_check >= MT_TX_HANG_TH)
+ goto restart;
+ } else {
+ dev->tx_hang_check = 0;
+ }
+
+ if (dev->mcu_timeout)
+ goto restart;
+
+ return;
+
+restart:
+ mt76x02_watchdog_reset(dev);
+
+ mutex_lock(&dev->mt76.mmio.mcu.mutex);
+ dev->mcu_timeout = 0;
+ mutex_unlock(&dev->mt76.mmio.mcu.mutex);
+
+ dev->tx_hang_reset++;
+ dev->tx_hang_check = 0;
+ memset(dev->mt76.tx_dma_idx, 0xff,
+ sizeof(dev->mt76.tx_dma_idx));
+}
+
+void mt76x02_wdt_work(struct work_struct *work)
+{
+ struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
+ wdt_work.work);
+
+ mt76x02_check_tx_hang(dev);
+
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
+ MT_WATCHDOG_TIME);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
index 977a8e7e26df..a020c757ba5c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
@@ -132,53 +132,6 @@ void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1)
}
EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower);
-int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev)
-{
- struct mt76x02_sta *sta;
- struct mt76_wcid *wcid;
- int i, j, min_rssi = 0;
- s8 cur_rssi;
-
- local_bh_disable();
- rcu_read_lock();
-
- for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) {
- unsigned long mask = dev->mt76.wcid_mask[i];
-
- if (!mask)
- continue;
-
- for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
- if (!(mask & 1))
- continue;
-
- wcid = rcu_dereference(dev->mt76.wcid[j]);
- if (!wcid)
- continue;
-
- sta = container_of(wcid, struct mt76x02_sta, wcid);
- spin_lock(&dev->mt76.rx_lock);
- if (sta->inactive_count++ < 5)
- cur_rssi = ewma_signal_read(&sta->rssi);
- else
- cur_rssi = 0;
- spin_unlock(&dev->mt76.rx_lock);
-
- if (cur_rssi < min_rssi)
- min_rssi = cur_rssi;
- }
- }
-
- rcu_read_unlock();
- local_bh_enable();
-
- if (!min_rssi)
- return -75;
-
- return min_rssi;
-}
-EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi);
-
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl)
{
int core_val, agc_val;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
index 2b316cf7c70c..d2971db06f13 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
@@ -51,7 +51,6 @@ void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit);
int mt76x02_get_max_rate_power(struct mt76_rate_power *r);
void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev);
void mt76x02_phy_set_txdac(struct mt76x02_dev *dev);
-int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev);
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl);
void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band,
bool primary_upper);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
index f7de77d09d28..7401cb94fb72 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
@@ -230,6 +230,29 @@
#define MT_COM_REG2 0x0738
#define MT_COM_REG3 0x073C
+#define MT_LED_CTRL 0x0770
+#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
+#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
+#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
+#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
+
+#define MT_LED_TX_BLINK_0 0x0774
+#define MT_LED_TX_BLINK_1 0x0778
+
+#define MT_LED_S0_BASE 0x077C
+#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
+#define MT_LED_S1_BASE 0x0780
+#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
+#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
+#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
+ MT_LED_STATUS_OFF_MASK)
+#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
+#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
+ MT_LED_STATUS_ON_MASK)
+#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
+#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
+ MT_LED_STATUS_DURATION_MASK)
+
#define MT_FCE_PSE_CTRL 0x0800
#define MT_FCE_PARAMETERS 0x0804
#define MT_FCE_CSO 0x0808
@@ -318,6 +341,7 @@
#define MT_CH_TIME_CFG_NAV_AS_BUSY BIT(3)
#define MT_CH_TIME_CFG_EIFS_AS_BUSY BIT(4)
#define MT_CH_TIME_CFG_MDRDY_CNT_EN BIT(5)
+#define MT_CH_CCA_RC_EN BIT(6)
#define MT_CH_TIME_CFG_CH_TIMER_CLR GENMASK(9, 8)
#define MT_CH_TIME_CFG_MDRDY_CLR GENMASK(11, 10)
@@ -378,6 +402,9 @@
#define MT_TX_PWR_CFG_4 0x1324
#define MT_TX_PIN_CFG 0x1328
#define MT_TX_PIN_CFG_TXANT GENMASK(3, 0)
+#define MT_TX_PIN_CFG_RXANT GENMASK(11, 8)
+#define MT_TX_PIN_RFTR_EN BIT(16)
+#define MT_TX_PIN_TRSW_EN BIT(18)
#define MT_TX_BAND_CFG 0x132c
#define MT_TX_BAND_CFG_UPPER_40M BIT(0)
@@ -398,6 +425,7 @@
#define MT_TXOP_CTRL_CFG 0x1340
#define MT_TXOP_TRUN_EN GENMASK(5, 0)
#define MT_TXOP_EXT_CCA_DLY GENMASK(15, 8)
+#define MT_TXOP_ED_CCA_EN BIT(20)
#define MT_TX_RTS_CFG 0x1344
#define MT_TX_RTS_CFG_RETRY_LIMIT GENMASK(7, 0)
@@ -409,6 +437,7 @@
#define MT_TX_RETRY_CFG 0x134c
#define MT_TX_LINK_CFG 0x1350
+#define MT_TX_CFACK_EN BIT(12)
#define MT_VHT_HT_FBK_CFG0 0x1354
#define MT_VHT_HT_FBK_CFG1 0x1358
#define MT_LG_FBK_CFG0 0x135c
@@ -440,9 +469,10 @@
#define MT_PROT_TXOP_ALLOW_GF40 BIT(25)
#define MT_PROT_RTS_THR_EN BIT(26)
#define MT_PROT_RATE_CCK_11 0x0003
-#define MT_PROT_RATE_OFDM_6 0x4000
-#define MT_PROT_RATE_OFDM_24 0x4004
-#define MT_PROT_RATE_DUP_OFDM_24 0x4084
+#define MT_PROT_RATE_OFDM_6 0x2000
+#define MT_PROT_RATE_OFDM_24 0x2004
+#define MT_PROT_RATE_DUP_OFDM_24 0x2084
+#define MT_PROT_RATE_SGI_OFDM_24 0x2104
#define MT_PROT_TXOP_ALLOW_ALL GENMASK(25, 20)
#define MT_PROT_TXOP_ALLOW_BW20 (MT_PROT_TXOP_ALLOW_ALL & \
~MT_PROT_TXOP_ALLOW_MM40 & \
@@ -511,6 +541,7 @@
#define MT_RX_FILTR_CFG_CTRL_RSV BIT(16)
#define MT_AUTO_RSP_CFG 0x1404
+#define MT_AUTO_RSP_EN BIT(0)
#define MT_AUTO_RSP_PREAMB_SHORT BIT(4)
#define MT_LEGACY_BASIC_RATE 0x1408
#define MT_HT_BASIC_RATE 0x140c
@@ -532,6 +563,7 @@
#define MT_PN_PAD_MODE 0x150c
#define MT_TXOP_HLDR_ET 0x1608
+#define MT_TXOP_HLDR_TX40M_BLK_EN BIT(1)
#define MT_PROT_AUTO_TX_CFG 0x1648
#define MT_PROT_AUTO_TX_CFG_PROT_PADJ GENMASK(11, 8)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index 4598cb2cc3ff..94f47248c59f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -22,7 +22,6 @@
void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76x02_dev *dev = hw->priv;
struct ieee80211_vif *vif = info->control.vif;
@@ -33,13 +32,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
msta = (struct mt76x02_sta *)control->sta->drv_priv;
wcid = &msta->wcid;
- /* sw encrypted frames */
- if (!info->control.hw_key && wcid->hw_key_idx != 0xff &&
- ieee80211_has_protected(hdr->frame_control))
- control->sta = NULL;
- }
-
- if (vif && !control->sta) {
+ } else if (vif) {
struct mt76x02_vif *mvif;
mvif = (struct mt76x02_vif *)vif->drv_priv;
@@ -58,8 +51,7 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
if (q == MT_RXQ_MCU) {
/* this is used just by mmio code */
- skb_queue_tail(&mdev->mmio.mcu.res_q, skb);
- wake_up(&mdev->mmio.mcu.wait);
+ mt76_mcu_rx_event(&dev->mt76, skb);
return;
}
@@ -177,7 +169,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (ret < 0)
return ret;
- if (pid && pid != MT_PACKET_ID_NO_ACK)
+ if (pid >= MT_PACKET_ID_FIRST)
qsel = MT_QSEL_MGMT;
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 81970cf777c0..43f07461c8d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -49,7 +49,12 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
put_unaligned_le32(info, skb_push(skb, sizeof(info)));
+ /* Add zero pad of 4 - 7 bytes */
pad = round_up(skb->len, 4) + 4 - skb->len;
+
+ /* First packet of a A-MSDU burst keeps track of the whole burst
+ * length, need to update lenght of it and the last packet.
+ */
skb_walk_frags(skb, iter) {
last = iter;
if (!iter->next) {
@@ -59,11 +64,10 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
}
}
- if (unlikely(pad)) {
- if (skb_pad(last, pad))
- return -ENOMEM;
- __skb_put(last, pad);
- }
+ if (skb_pad(last, pad))
+ return -ENOMEM;
+ __skb_put(last, pad);
+
return 0;
}
@@ -87,8 +91,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
txwi->pktid = pid;
- if ((pid && pid != MT_PACKET_ID_NO_ACK) ||
- q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
+ if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
qsel = MT_QSEL_MGMT;
else
qsel = MT_QSEL_EDCA;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
index 6db789f90269..0cb8751321a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
@@ -28,21 +28,6 @@
#define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX 0x09a8
-static struct sk_buff *
-mt76x02u_mcu_msg_alloc(const void *data, int len)
-{
- struct sk_buff *skb;
-
- skb = alloc_skb(MT_CMD_HDR_LEN + len + 8, GFP_KERNEL);
- if (!skb)
- return NULL;
-
- skb_reserve(skb, MT_CMD_HDR_LEN);
- skb_put_data(skb, data, len);
-
- return skb;
-}
-
static void
mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len)
{
@@ -76,34 +61,21 @@ mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len)
static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
{
struct mt76_usb *usb = &dev->usb;
- struct mt76u_buf *buf = &usb->mcu.res;
- struct urb *urb = buf->urb;
- int i, ret;
+ u8 *data = usb->mcu.data;
+ int i, len, ret;
u32 rxfce;
- u8 *data;
for (i = 0; i < 5; i++) {
- if (!wait_for_completion_timeout(&usb->mcu.cmpl,
- msecs_to_jiffies(300)))
+ ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300);
+ if (ret == -ETIMEDOUT)
continue;
+ if (ret)
+ goto out;
- if (urb->status)
- return -EIO;
-
- data = sg_virt(&urb->sg[0]);
if (usb->mcu.rp)
- mt76x02u_multiple_mcu_reads(dev, data + 4,
- urb->actual_length - 8);
+ mt76x02u_multiple_mcu_reads(dev, data + 4, len - 8);
rxfce = get_unaligned_le32(data);
- ret = mt76u_submit_buf(dev, USB_DIR_IN,
- MT_EP_IN_CMD_RESP,
- buf, GFP_KERNEL,
- mt76u_mcu_complete_urb,
- &usb->mcu.cmpl);
- if (ret)
- return ret;
-
if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce) &&
FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce) == EVT_CMD_DONE)
return 0;
@@ -112,27 +84,23 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce),
seq, FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce));
}
-
- dev_err(dev->dev, "error: %s timed out\n", __func__);
- return -ETIMEDOUT;
+out:
+ dev_err(dev->dev, "error: %s failed with %d\n", __func__, ret);
+ return ret;
}
static int
__mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, bool wait_resp)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
struct mt76_usb *usb = &dev->usb;
- unsigned int pipe;
- int ret, sent;
+ int ret;
u8 seq = 0;
u32 info;
if (test_bit(MT76_REMOVED, &dev->state))
return 0;
- pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
if (wait_resp) {
seq = ++usb->mcu.msg_seq & 0xf;
if (!seq)
@@ -146,7 +114,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
if (ret)
return ret;
- ret = usb_bulk_msg(udev, pipe, skb->data, skb->len, &sent, 500);
+ ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500);
if (ret)
return ret;
@@ -166,7 +134,7 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data,
struct sk_buff *skb;
int err;
- skb = mt76x02u_mcu_msg_alloc(data, len);
+ skb = mt76_mcu_msg_alloc(data, MT_CMD_HDR_LEN, len, 8);
if (!skb)
return -ENOMEM;
@@ -268,14 +236,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev)
EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset);
static int
-__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
+__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data,
const void *fw_data, int len, u32 dst_addr)
{
- u8 *data = sg_virt(&buf->urb->sg[0]);
- DECLARE_COMPLETION_ONSTACK(cmpl);
__le32 info;
u32 val;
- int err;
+ int err, data_len;
info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, len) |
@@ -291,25 +257,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE,
MT_FCE_DMA_LEN, len << 16);
- buf->len = MT_CMD_HDR_LEN + len + sizeof(info);
- err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT,
- MT_EP_OUT_INBAND_CMD,
- buf, GFP_KERNEL,
- mt76u_mcu_complete_urb, &cmpl);
- if (err < 0)
- return err;
-
- if (!wait_for_completion_timeout(&cmpl,
- msecs_to_jiffies(1000))) {
- dev_err(dev->mt76.dev, "firmware upload timed out\n");
- usb_kill_urb(buf->urb);
- return -ETIMEDOUT;
- }
+ data_len = MT_CMD_HDR_LEN + len + sizeof(info);
- if (mt76u_urb_error(buf->urb)) {
- dev_err(dev->mt76.dev, "firmware upload failed: %d\n",
- buf->urb->status);
- return buf->urb->status;
+ err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000);
+ if (err) {
+ dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err);
+ return err;
}
val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX);
@@ -322,17 +275,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
int data_len, u32 max_payload, u32 offset)
{
- int err, len, pos = 0, max_len = max_payload - 8;
- struct mt76u_buf buf;
+ int len, err = 0, pos = 0, max_len = max_payload - 8;
+ u8 *buf;
- err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload,
- GFP_KERNEL);
- if (err < 0)
- return err;
+ buf = kmalloc(max_payload, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
while (data_len > 0) {
len = min_t(int, data_len, max_len);
- err = __mt76x02u_mcu_fw_send_data(dev, &buf, data + pos,
+ err = __mt76x02u_mcu_fw_send_data(dev, buf, data + pos,
len, offset + pos);
if (err < 0)
break;
@@ -341,7 +293,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
pos += len;
usleep_range(5000, 10000);
}
- mt76u_buf_free(&buf);
+ kfree(buf);
return err;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 38bd466cff16..a48c261b0c63 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -75,6 +75,58 @@ static const struct ieee80211_iface_combination mt76x02_if_comb[] = {
}
};
+static void
+mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on,
+ u8 delay_off)
+{
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev,
+ mt76);
+ u32 val;
+
+ val = MT_LED_STATUS_DURATION(0xff) |
+ MT_LED_STATUS_OFF(delay_off) |
+ MT_LED_STATUS_ON(delay_on);
+
+ mt76_wr(dev, MT_LED_S0(mdev->led_pin), val);
+ mt76_wr(dev, MT_LED_S1(mdev->led_pin), val);
+
+ val = MT_LED_CTRL_REPLAY(mdev->led_pin) |
+ MT_LED_CTRL_KICK(mdev->led_pin);
+ if (mdev->led_al)
+ val |= MT_LED_CTRL_POLARITY(mdev->led_pin);
+ mt76_wr(dev, MT_LED_CTRL, val);
+}
+
+static int
+mt76x02_led_set_blink(struct led_classdev *led_cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
+ led_cdev);
+ u8 delta_on, delta_off;
+
+ delta_off = max_t(u8, *delay_off / 10, 1);
+ delta_on = max_t(u8, *delay_on / 10, 1);
+
+ mt76x02_led_set_config(mdev, delta_on, delta_off);
+
+ return 0;
+}
+
+static void
+mt76x02_led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
+ led_cdev);
+
+ if (!brightness)
+ mt76x02_led_set_config(mdev, 0, 0xff);
+ else
+ mt76x02_led_set_config(mdev, 0xff, 0);
+}
+
void mt76x02_init_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
@@ -88,27 +140,37 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
hw->max_rate_tries = 1;
hw->extra_tx_headroom = 2;
+ wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+ BIT(NL80211_IFTYPE_ADHOC);
+
if (mt76_is_usb(dev)) {
hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) +
MT_DMA_HDR_LEN;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
} else {
+ INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work);
+
mt76x02_dfs_init_detector(dev);
wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy->iface_combinations = mt76x02_if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb);
- wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
-#ifdef CONFIG_MAC80211_MESH
- BIT(NL80211_IFTYPE_MESH_POINT) |
-#endif
- BIT(NL80211_IFTYPE_ADHOC);
-
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
+ wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
+ /* init led callbacks */
+ if (IS_ENABLED(CONFIG_MT76_LEDS)) {
+ dev->mt76.led_cdev.brightness_set =
+ mt76x02_led_set_brightness;
+ dev->mt76.led_cdev.blink_set = mt76x02_led_set_blink;
+ }
}
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+
hw->sta_data_size = sizeof(struct mt76x02_sta);
hw->vif_data_size = sizeof(struct mt76x02_vif);
@@ -189,8 +251,6 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_AP)
set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
- ewma_signal_init(&msta->rssi);
-
return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_sta_add);
@@ -207,8 +267,9 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
}
EXPORT_SYMBOL_GPL(mt76x02_sta_remove);
-void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
- unsigned int idx)
+static void
+mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
+ unsigned int idx)
{
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
struct mt76_txq *mtxq;
@@ -221,7 +282,6 @@ void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mt76_txq_init(&dev->mt76, vif->txq);
}
-EXPORT_SYMBOL_GPL(mt76x02_vif_init);
int
mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
@@ -248,6 +308,15 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
if (vif->type == NL80211_IFTYPE_STATION)
idx += 8;
+ if (dev->vif_mask & BIT(idx))
+ return -EBUSY;
+
+ /* Allow to change address in HW if we create first interface. */
+ if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr))
+ mt76x02_mac_setaddr(dev, vif->addr);
+
+ dev->vif_mask |= BIT(idx);
+
mt76x02_vif_init(dev, vif, idx);
return 0;
}
@@ -257,8 +326,10 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt76x02_dev *dev = hw->priv;
+ struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
mt76_txq_remove(&dev->mt76, vif->txq);
+ dev->vif_mask &= ~BIT(mvif->idx);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
@@ -360,7 +431,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
} else {
if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
- wcid->sw_iv = true;
+ wcid->sw_iv = false;
}
key = NULL;
@@ -463,7 +534,7 @@ int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
return -EINVAL;
mutex_lock(&dev->mt76.mutex);
- mt76x02_mac_set_tx_protection(dev, val);
+ mt76x02_mac_set_rts_thresh(dev, val);
mutex_unlock(&dev->mt76.mutex);
return 0;
@@ -546,24 +617,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(mt76x02_sw_scan_complete);
-int mt76x02_get_txpower(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int *dbm)
-{
- struct mt76x02_dev *dev = hw->priv;
- u8 nstreams = dev->mt76.chainmask & 0xf;
-
- *dbm = dev->mt76.txpower_cur / 2;
-
- /* convert from per-chain power to combined
- * output on 2x2 devices
- */
- if (nstreams > 1)
- *dbm += 3;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mt76x02_get_txpower);
-
void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,
bool ps)
{
@@ -614,29 +667,26 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
{
- static const u8 null_addr[ETH_ALEN] = {};
int i;
- mt76_wr(dev, MT_MAC_BSSID_DW0,
- get_unaligned_le32(dev->mt76.macaddr));
- mt76_wr(dev, MT_MAC_BSSID_DW1,
- get_unaligned_le16(dev->mt76.macaddr + 4) |
- FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */
- MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT);
-
- /* Fire a pre-TBTT interrupt 8 ms before TBTT */
- mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT,
- 8 << 4);
- mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
- MT_DFS_GP_INTERVAL);
- mt76_wr(dev, MT_INT_TIMER_EN, 0);
+ if (mt76_is_mmio(dev)) {
+ /* Fire a pre-TBTT interrupt 8 ms before TBTT */
+ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT,
+ 8 << 4);
+ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
+ MT_DFS_GP_INTERVAL);
+ mt76_wr(dev, MT_INT_TIMER_EN, 0);
+ }
+ mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
+ MT_BEACON_TIME_CFG_TBTT_EN |
+ MT_BEACON_TIME_CFG_BEACON_TX));
+ mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE);
mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff);
- for (i = 0; i < 8; i++) {
- mt76x02_mac_set_bssid(dev, i, null_addr);
+ for (i = 0; i < 8; i++)
mt76x02_mac_set_beacon(dev, i, NULL);
- }
+
mt76x02_set_beacon_offsets(dev);
}
EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config);
@@ -654,21 +704,20 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID)
mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid);
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
- tasklet_disable(&dev->pre_tbtt_tasklet);
- mt76x02_mac_set_beacon_enable(dev, mvif->idx,
- info->enable_beacon);
- tasklet_enable(&dev->pre_tbtt_tasklet);
- }
+ if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+ mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
+ info->ht_operation_mode);
if (changed & BSS_CHANGED_BEACON_INT) {
mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_INTVAL,
info->beacon_int << 4);
dev->beacon_int = info->beacon_int;
- dev->tbtt_count = 0;
}
+ if (changed & BSS_CHANGED_BEACON_ENABLED)
+ mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon);
+
if (changed & BSS_CHANGED_ERP_PREAMBLE)
mt76x02_mac_set_short_preamble(dev, info->use_short_preamble);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
index 54a9b5fac787..f8534362e2c8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
@@ -143,6 +143,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev)
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
{ MT_PROT_AUTO_TX_CFG, 0x00830083 },
{ MT_HT_CTRL_CFG, 0x000001ff },
+ { MT_TX_LINK_CFG, 0x00001020 },
};
struct mt76_reg_pair prot_vals[] = {
{ MT_CCK_PROT_CFG, DEFAULT_PROT_CFG_CCK },
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
index e25905c91ee2..e99d4c9bd428 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c
@@ -23,6 +23,9 @@ void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force)
u32 rts_cfg;
int i;
+ mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+ mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
+
mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
index 4c8e20bce920..42ff221d7706 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h
@@ -25,6 +25,12 @@ struct mt76x02_vif;
int mt76x2_mac_start(struct mt76x02_dev *dev);
void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force);
-void mt76x2_mac_resume(struct mt76x02_dev *dev);
+
+static inline void mt76x2_mac_resume(struct mt76x02_dev *dev)
+{
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_ENABLE_TX |
+ MT_MAC_SYS_CTRL_ENABLE_RX);
+}
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
index acfa2b570c7c..40ef43926c06 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h
@@ -26,29 +26,6 @@
#define MT_MCU_PCIE_REMAP_BASE2 0x0744
#define MT_MCU_PCIE_REMAP_BASE3 0x0748
-#define MT_LED_CTRL 0x0770
-#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
-#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
-#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
-#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
-
-#define MT_LED_TX_BLINK_0 0x0774
-#define MT_LED_TX_BLINK_1 0x0778
-
-#define MT_LED_S0_BASE 0x077C
-#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
-#define MT_LED_S1_BASE 0x0780
-#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
-#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
-#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
- MT_LED_STATUS_OFF_MASK)
-#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
-#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
- MT_LED_STATUS_ON_MASK)
-#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
-#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
- MT_LED_STATUS_DURATION_MASK)
-
#define MT_MCU_ROM_PATCH_OFFSET 0x80000
#define MT_MCU_ROM_PATCH_ADDR 0x90000
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
index b259e4b50f1e..6c619f1c65c9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h
@@ -49,11 +49,9 @@ static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev)
extern const struct ieee80211_ops mt76x2_ops;
-struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev);
int mt76x2_register_device(struct mt76x02_dev *dev);
void mt76x2_phy_power_on(struct mt76x02_dev *dev);
-int mt76x2_init_hardware(struct mt76x02_dev *dev);
void mt76x2_stop_hardware(struct mt76x02_dev *dev);
int mt76x2_eeprom_init(struct mt76x02_dev *dev);
int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
index 0b0075411b34..76cb1f84eff5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h
@@ -29,14 +29,12 @@
extern const struct ieee80211_ops mt76x2u_ops;
-struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev);
int mt76x2u_register_device(struct mt76x02_dev *dev);
int mt76x2u_init_hardware(struct mt76x02_dev *dev);
void mt76x2u_cleanup(struct mt76x02_dev *dev);
void mt76x2u_stop_hw(struct mt76x02_dev *dev);
int mt76x2u_mac_reset(struct mt76x02_dev *dev);
-void mt76x2u_mac_resume(struct mt76x02_dev *dev);
int mt76x2u_mac_start(struct mt76x02_dev *dev);
int mt76x2u_mac_stop(struct mt76x02_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
index 92432fe97312..6274655e1f7e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
@@ -30,7 +30,19 @@ static const struct pci_device_id mt76pci_device_table[] = {
static int
mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ static const struct mt76_driver_ops drv_ops = {
+ .txwi_size = sizeof(struct mt76x02_txwi),
+ .update_survey = mt76x02_update_channel,
+ .tx_prepare_skb = mt76x02_tx_prepare_skb,
+ .tx_complete_skb = mt76x02_tx_complete_skb,
+ .rx_skb = mt76x02_queue_rx_skb,
+ .rx_poll_complete = mt76x02_rx_poll_complete,
+ .sta_ps = mt76x02_sta_ps,
+ .sta_add = mt76x02_sta_add,
+ .sta_remove = mt76x02_sta_remove,
+ };
struct mt76x02_dev *dev;
+ struct mt76_dev *mdev;
int ret;
ret = pcim_enable_device(pdev);
@@ -47,17 +59,19 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
- dev = mt76x2_alloc_device(&pdev->dev);
- if (!dev)
+ mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x2_ops,
+ &drv_ops);
+ if (!mdev)
return -ENOMEM;
- mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+ mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
mt76x2_reset_wlan(dev, false);
- dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
- dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
+ mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
+ dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
- ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler,
+ ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
index 7f4ea2d00f42..984d9c4c2e1a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
@@ -119,9 +119,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401);
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
- mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr));
- mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4));
-
+ mt76x02_mac_setaddr(dev, macaddr);
mt76x02_init_beacon_config(dev);
if (!hard)
return 0;
@@ -151,6 +149,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
MT_CH_TIME_CFG_RX_AS_BUSY |
MT_CH_TIME_CFG_NAV_AS_BUSY |
MT_CH_TIME_CFG_EIFS_AS_BUSY |
+ MT_CH_CCA_RC_EN |
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
mt76x02_set_tx_ackto(dev);
@@ -174,13 +173,6 @@ int mt76x2_mac_start(struct mt76x02_dev *dev)
return 0;
}
-void mt76x2_mac_resume(struct mt76x02_dev *dev)
-{
- mt76_wr(dev, MT_MAC_SYS_CTRL,
- MT_MAC_SYS_CTRL_ENABLE_TX |
- MT_MAC_SYS_CTRL_ENABLE_RX);
-}
-
static void
mt76x2_power_on_rf_patch(struct mt76x02_dev *dev)
{
@@ -260,7 +252,7 @@ mt76x2_power_on(struct mt76x02_dev *dev)
mt76x2_power_on_rf(dev, 1);
}
-int mt76x2_init_hardware(struct mt76x02_dev *dev)
+static int mt76x2_init_hardware(struct mt76x02_dev *dev)
{
int ret;
@@ -300,6 +292,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->wdt_work);
mt76x02_mcu_set_radio_state(dev, false);
mt76x2_mac_stop(dev, false);
}
@@ -313,81 +306,6 @@ void mt76x2_cleanup(struct mt76x02_dev *dev)
mt76x02_mcu_cleanup(dev);
}
-struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev)
-{
- static const struct mt76_driver_ops drv_ops = {
- .txwi_size = sizeof(struct mt76x02_txwi),
- .update_survey = mt76x02_update_channel,
- .tx_prepare_skb = mt76x02_tx_prepare_skb,
- .tx_complete_skb = mt76x02_tx_complete_skb,
- .rx_skb = mt76x02_queue_rx_skb,
- .rx_poll_complete = mt76x02_rx_poll_complete,
- .sta_ps = mt76x02_sta_ps,
- .sta_add = mt76x02_sta_add,
- .sta_remove = mt76x02_sta_remove,
- };
- struct mt76x02_dev *dev;
- struct mt76_dev *mdev;
-
- mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops);
- if (!mdev)
- return NULL;
-
- dev = container_of(mdev, struct mt76x02_dev, mt76);
- mdev->dev = pdev;
- mdev->drv = &drv_ops;
-
- return dev;
-}
-
-static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on,
- u8 delay_off)
-{
- struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev,
- mt76);
- u32 val;
-
- val = MT_LED_STATUS_DURATION(0xff) |
- MT_LED_STATUS_OFF(delay_off) |
- MT_LED_STATUS_ON(delay_on);
-
- mt76_wr(dev, MT_LED_S0(mt76->led_pin), val);
- mt76_wr(dev, MT_LED_S1(mt76->led_pin), val);
-
- val = MT_LED_CTRL_REPLAY(mt76->led_pin) |
- MT_LED_CTRL_KICK(mt76->led_pin);
- if (mt76->led_al)
- val |= MT_LED_CTRL_POLARITY(mt76->led_pin);
- mt76_wr(dev, MT_LED_CTRL, val);
-}
-
-static int mt76x2_led_set_blink(struct led_classdev *led_cdev,
- unsigned long *delay_on,
- unsigned long *delay_off)
-{
- struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
- led_cdev);
- u8 delta_on, delta_off;
-
- delta_off = max_t(u8, *delay_off / 10, 1);
- delta_on = max_t(u8, *delay_on / 10, 1);
-
- mt76x2_led_set_config(mt76, delta_on, delta_off);
- return 0;
-}
-
-static void mt76x2_led_set_brightness(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
- led_cdev);
-
- if (!brightness)
- mt76x2_led_set_config(mt76, 0, 0xff);
- else
- mt76x2_led_set_config(mt76, 0xff, 0);
-}
-
int mt76x2_register_device(struct mt76x02_dev *dev)
{
int ret;
@@ -402,12 +320,6 @@ int mt76x2_register_device(struct mt76x02_dev *dev)
mt76x02_config_mac_addr_list(dev);
- /* init led callbacks */
- if (IS_ENABLED(CONFIG_MT76_LEDS)) {
- dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
- dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
- }
-
ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
ARRAY_SIZE(mt76x02_rates));
if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index b54a32397486..878ce92405ed 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -33,7 +33,9 @@ mt76x2_start(struct ieee80211_hw *hw)
goto out;
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
+ MT_MAC_WORK_INTERVAL);
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
+ MT_WATCHDOG_TIME);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
@@ -189,7 +191,7 @@ const struct ieee80211_ops mt76x2_ops = {
.sw_scan_complete = mt76x02_sw_scan_complete,
.flush = mt76x2_flush,
.ampdu_action = mt76x02_ampdu_action,
- .get_txpower = mt76x02_get_txpower,
+ .get_txpower = mt76_get_txpower,
.wake_tx_queue = mt76_wake_tx_queue,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.release_buffered_frames = mt76_release_buffered_frames,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
index da7cd40f56ff..cc1aebcb0696 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c
@@ -74,6 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped)
mt76x2_mac_resume(dev);
mt76x2_apply_gain_adj(dev);
+ mt76x02_edcca_init(dev, true);
dev->cal.channel_cal_done = true;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
index c9634a774705..1848e8ab2e21 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c
@@ -241,7 +241,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev)
t.offset1 = txp.chain[1].tssi_offset;
mt76x2_mcu_tssi_comp(dev, &t);
- if (t.pa_mode || dev->cal.dpd_cal_done)
+ if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked)
return;
usleep_range(10000, 20000);
@@ -284,7 +284,9 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
int low_gain;
u32 val;
- dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
+ dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
+ if (!dev->cal.avg_rssi_all)
+ dev->cal.avg_rssi_all = -75;
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index 4d1788eb3812..ddb6b2c48e01 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -36,24 +36,36 @@ static const struct usb_device_id mt76x2u_device_table[] = {
static int mt76x2u_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ static const struct mt76_driver_ops drv_ops = {
+ .tx_prepare_skb = mt76x02u_tx_prepare_skb,
+ .tx_complete_skb = mt76x02u_tx_complete_skb,
+ .tx_status_data = mt76x02_tx_status_data,
+ .rx_skb = mt76x02_queue_rx_skb,
+ .sta_add = mt76x02_sta_add,
+ .sta_remove = mt76x02_sta_remove,
+ };
struct usb_device *udev = interface_to_usbdev(intf);
struct mt76x02_dev *dev;
+ struct mt76_dev *mdev;
int err;
- dev = mt76x2u_alloc_device(&intf->dev);
- if (!dev)
+ mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops,
+ &drv_ops);
+ if (!mdev)
return -ENOMEM;
+ dev = container_of(mdev, struct mt76x02_dev, mt76);
+
udev = usb_get_dev(udev);
usb_reset_device(udev);
- mt76x02u_init_mcu(&dev->mt76);
- err = mt76u_init(&dev->mt76, intf);
+ mt76x02u_init_mcu(mdev);
+ err = mt76u_init(mdev, intf);
if (err < 0)
goto err;
- dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
- dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
+ mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
+ dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
err = mt76x2u_register_device(dev);
if (err < 0)
@@ -88,11 +100,9 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
pm_message_t state)
{
struct mt76x02_dev *dev = usb_get_intfdata(intf);
- struct mt76_usb *usb = &dev->mt76.usb;
mt76u_stop_queues(&dev->mt76);
mt76x2u_stop_hw(dev);
- usb_kill_urb(usb->mcu.res.urb);
return 0;
}
@@ -103,15 +113,6 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf)
struct mt76_usb *usb = &dev->mt76.usb;
int err;
- reinit_completion(&usb->mcu.cmpl);
- err = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
- MT_EP_IN_CMD_RESP,
- &usb->mcu.res, GFP_KERNEL,
- mt76u_mcu_complete_urb,
- &usb->mcu.cmpl);
- if (err < 0)
- goto err;
-
err = mt76u_submit_rx_buffers(&dev->mt76);
if (err < 0)
goto err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
index 0be3784f44fb..1da90e58d942 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
@@ -134,30 +134,6 @@ static int mt76x2u_init_eeprom(struct mt76x02_dev *dev)
return 0;
}
-struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev)
-{
- static const struct mt76_driver_ops drv_ops = {
- .tx_prepare_skb = mt76x02u_tx_prepare_skb,
- .tx_complete_skb = mt76x02u_tx_complete_skb,
- .tx_status_data = mt76x02_tx_status_data,
- .rx_skb = mt76x02_queue_rx_skb,
- .sta_add = mt76x02_sta_add,
- .sta_remove = mt76x02_sta_remove,
- };
- struct mt76x02_dev *dev;
- struct mt76_dev *mdev;
-
- mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops);
- if (!mdev)
- return NULL;
-
- dev = container_of(mdev, struct mt76x02_dev, mt76);
- mdev->dev = pdev;
- mdev->drv = &drv_ops;
-
- return dev;
-}
-
int mt76x2u_init_hardware(struct mt76x02_dev *dev)
{
int i, k, err;
@@ -207,11 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev)
mt76x02_mac_shared_key_setup(dev, i, k, NULL);
}
- mt76_clear(dev, MT_BEACON_TIME_CFG,
- MT_BEACON_TIME_CFG_TIMER_EN |
- MT_BEACON_TIME_CFG_SYNC_MODE |
- MT_BEACON_TIME_CFG_TBTT_EN |
- MT_BEACON_TIME_CFG_BEACON_TX);
+ mt76x02_init_beacon_config(dev);
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f);
@@ -242,10 +214,6 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
if (err < 0)
goto fail;
- err = mt76u_mcu_init_rx(&dev->mt76);
- if (err < 0)
- goto fail;
-
err = mt76x2u_init_hardware(dev);
if (err < 0)
goto fail;
@@ -256,7 +224,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
goto fail;
/* check hw sg support in order to enable AMSDU */
- if (mt76u_check_sg(&dev->mt76))
+ if (dev->mt76.usb.sg_en)
hw->max_tx_fragments = MT_SG_MAX_SIZE;
else
hw->max_tx_fragments = 1;
@@ -287,5 +255,4 @@ void mt76x2u_cleanup(struct mt76x02_dev *dev)
mt76x02_mcu_set_radio_state(dev, false);
mt76x2u_stop_hw(dev);
mt76u_queues_deinit(&dev->mt76);
- mt76u_mcu_deinit(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
index db2194a92e67..5e84b4535cb1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c
@@ -143,8 +143,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev)
rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
- mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20));
- mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1));
+ mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
+ mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
/* wait tx dma to stop */
for (i = 0; i < 2000; i++) {
@@ -211,12 +211,3 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev)
return 0;
}
-
-void mt76x2u_mac_resume(struct mt76x02_dev *dev)
-{
- mt76_wr(dev, MT_MAC_SYS_CTRL,
- MT_MAC_SYS_CTRL_ENABLE_TX |
- MT_MAC_SYS_CTRL_ENABLE_RX);
- mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20));
- mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1));
-}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 2b48cc51a30d..2ac78e4dc41a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -28,7 +28,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)
goto out;
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
- MT_CALIBRATE_INTERVAL);
+ MT_MAC_WORK_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
out:
@@ -46,19 +46,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
mutex_unlock(&dev->mt76.mutex);
}
-static int mt76x2u_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct mt76x02_dev *dev = hw->priv;
- unsigned int idx = 8;
-
- if (!ether_addr_equal(dev->mt76.macaddr, vif->addr))
- mt76x02_mac_setaddr(dev, vif->addr);
-
- mt76x02_vif_init(dev, vif, idx);
- return 0;
-}
-
static int
mt76x2u_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef)
@@ -70,13 +57,12 @@ mt76x2u_set_channel(struct mt76x02_dev *dev,
mt76_set_channel(&dev->mt76);
- mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20));
- mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1));
mt76x2_mac_stop(dev, false);
err = mt76x2u_phy_set_channel(dev, chandef);
- mt76x2u_mac_resume(dev);
+ mt76x2_mac_resume(dev);
+ mt76x02_edcca_init(dev, true);
clear_bit(MT76_RESET, &dev->mt76.state);
mt76_txq_schedule_all(&dev->mt76);
@@ -125,7 +111,7 @@ const struct ieee80211_ops mt76x2u_ops = {
.tx = mt76x02_tx,
.start = mt76x2u_start,
.stop = mt76x2u_stop,
- .add_interface = mt76x2u_add_interface,
+ .add_interface = mt76x02_add_interface,
.remove_interface = mt76x02_remove_interface,
.sta_state = mt76_sta_state,
.set_key = mt76x02_set_key,
@@ -138,5 +124,5 @@ const struct ieee80211_ops mt76x2u_ops = {
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
- .get_txpower = mt76x02_get_txpower,
+ .get_txpower = mt76_get_txpower,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
index 45a95ee3a415..152d41fe9ff5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
@@ -39,7 +39,7 @@ static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
{
struct mt76_usb *usb = &dev->mt76.usb;
- const u8 data[] = {
+ static const u8 data[] = {
0x6f, 0xfc, 0x08, 0x01,
0x20, 0x04, 0x00, 0x00,
0x00, 0x09, 0x00,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
index 11d414d86c68..07f67cb6854c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c
@@ -43,8 +43,9 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped)
mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0);
if (!mac_stopped)
- mt76x2u_mac_resume(dev);
+ mt76x2_mac_resume(dev);
mt76x2_apply_gain_adj(dev);
+ mt76x02_edcca_init(dev, true);
dev->cal.channel_cal_done = true;
}
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 7b711058807d..5a349fe3e576 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -170,21 +170,22 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
int pid;
if (!wcid)
- return 0;
+ return MT_PACKET_ID_NO_ACK;
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
return MT_PACKET_ID_NO_ACK;
if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
- return 0;
+ return MT_PACKET_ID_NO_SKB;
spin_lock_bh(&dev->status_list.lock);
memset(cb, 0, sizeof(*cb));
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
- if (!wcid->packet_id || wcid->packet_id == MT_PACKET_ID_NO_ACK)
- wcid->packet_id = 1;
+ if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
+ wcid->packet_id == MT_PACKET_ID_NO_SKB)
+ wcid->packet_id = MT_PACKET_ID_FIRST;
pid = wcid->packet_id;
cb->wcid = wcid->idx;
@@ -204,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
{
struct sk_buff *skb, *tmp;
- if (pktid == MT_PACKET_ID_NO_ACK)
- return NULL;
-
skb_queue_walk_safe(&dev->status_list, skb, tmp) {
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
@@ -216,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
if (cb->pktid == pktid)
return skb;
- if (!pktid &&
+ if (pktid >= 0 &&
!time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT))
continue;
@@ -330,7 +328,8 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
if (last)
- info->flags |= IEEE80211_TX_STATUS_EOSP;
+ info->flags |= IEEE80211_TX_STATUS_EOSP |
+ IEEE80211_TX_CTL_REQ_TX_STATUS;
mt76_skb_set_moredata(skb, !last);
dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta);
@@ -394,6 +393,11 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq,
bool probe;
int idx;
+ if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
+ *empty = true;
+ return 0;
+ }
+
skb = mt76_txq_dequeue(dev, mtxq, false);
if (!skb) {
*empty = true;
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index b061263453d4..ae6ada370597 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -22,6 +22,10 @@
#define MT_VEND_REQ_MAX_RETRY 10
#define MT_VEND_REQ_TOUT_MS 300
+static bool disable_usb_sg;
+module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644);
+MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support");
+
/* should be called with usb_ctrl_mtx locked */
static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
@@ -241,6 +245,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base,
return mt76u_req_rd_rp(dev, base, data, n);
}
+static bool mt76u_check_sg(struct mt76_dev *dev)
+{
+ struct usb_interface *intf = to_usb_interface(dev->dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
+ (udev->bus->no_sg_constraint ||
+ udev->speed == USB_SPEED_WIRELESS));
+}
+
static int
mt76u_set_endpoints(struct usb_interface *intf,
struct mt76_usb *usb)
@@ -309,42 +323,66 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
return i ? : -ENOMEM;
}
-int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
- int nsgs, int len, int sglen, gfp_t gfp)
+static int
+mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
+ struct mt76u_buf *buf, int nsgs, gfp_t gfp)
+{
+ if (dev->usb.sg_en) {
+ return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size,
+ SKB_WITH_OVERHEAD(q->buf_size));
+ } else {
+ buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
+ return buf->buf ? 0 : -ENOMEM;
+ }
+}
+
+static int
+mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf)
{
- buf->urb = usb_alloc_urb(0, gfp);
+ struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+
+ buf->len = SKB_WITH_OVERHEAD(q->buf_size);
+ buf->dev = dev;
+
+ buf->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!buf->urb)
return -ENOMEM;
- buf->urb->sg = devm_kcalloc(dev->dev, nsgs, sizeof(*buf->urb->sg),
- gfp);
- if (!buf->urb->sg)
- return -ENOMEM;
+ if (dev->usb.sg_en) {
+ buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
+ sizeof(*buf->urb->sg),
+ GFP_KERNEL);
+ if (!buf->urb->sg)
+ return -ENOMEM;
- sg_init_table(buf->urb->sg, nsgs);
- buf->dev = dev;
+ sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE);
+ }
- return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen);
+ return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL);
}
-EXPORT_SYMBOL_GPL(mt76u_buf_alloc);
-void mt76u_buf_free(struct mt76u_buf *buf)
+static void mt76u_buf_free(struct mt76u_buf *buf)
{
struct urb *urb = buf->urb;
int i;
for (i = 0; i < urb->num_sgs; i++)
skb_free_frag(sg_virt(&urb->sg[i]));
+
+ if (buf->buf)
+ skb_free_frag(buf->buf);
+
usb_free_urb(buf->urb);
}
-EXPORT_SYMBOL_GPL(mt76u_buf_free);
-int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
- struct mt76u_buf *buf, gfp_t gfp,
- usb_complete_t complete_fn, void *context)
+static void
+mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index,
+ struct mt76u_buf *buf, usb_complete_t complete_fn,
+ void *context)
{
struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf);
+ u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
unsigned int pipe;
if (dir == USB_DIR_IN)
@@ -352,13 +390,21 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
else
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
- usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len,
+ usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len,
complete_fn, context);
+}
+
+static int
+mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
+ struct mt76u_buf *buf, gfp_t gfp,
+ usb_complete_t complete_fn, void *context)
+{
+ mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn,
+ context);
trace_submit_urb(dev, buf->urb);
return usb_submit_urb(buf->urb, gfp);
}
-EXPORT_SYMBOL_GPL(mt76u_submit_buf);
static inline struct mt76u_buf
*mt76u_get_next_rx_entry(struct mt76_queue *q)
@@ -393,10 +439,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
}
static int
-mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
+mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- u8 *data = sg_virt(&urb->sg[0]);
+ struct urb *urb = buf->urb;
+ u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
int data_len, len, nsgs = 1;
struct sk_buff *skb;
@@ -407,21 +454,20 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
if (len < 0)
return 0;
+ data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
+ data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN);
+ if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
+ return 0;
+
skb = build_skb(data, q->buf_size);
if (!skb)
return 0;
- data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
skb_reserve(skb, MT_DMA_HDR_LEN);
- if (skb->tail + data_len > skb->end) {
- dev_kfree_skb(skb);
- return 1;
- }
-
__skb_put(skb, data_len);
len -= data_len;
- while (len > 0) {
+ while (len > 0 && nsgs < urb->num_sgs) {
data_len = min_t(int, len, urb->sg[nsgs].length);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
sg_page(&urb->sg[nsgs]),
@@ -449,7 +495,8 @@ static void mt76u_complete_rx(struct urb *urb)
case -ENOENT:
return;
default:
- dev_err(dev->dev, "rx urb failed: %d\n", urb->status);
+ dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",
+ urb->status);
/* fall through */
case 0:
break;
@@ -470,8 +517,8 @@ static void mt76u_rx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- int err, nsgs, buf_len = q->buf_size;
struct mt76u_buf *buf;
+ int err, count;
rcu_read_lock();
@@ -480,11 +527,10 @@ static void mt76u_rx_tasklet(unsigned long data)
if (!buf)
break;
- nsgs = mt76u_process_rx_entry(dev, buf->urb);
- if (nsgs > 0) {
- err = mt76u_fill_rx_sg(dev, buf, nsgs,
- buf_len,
- SKB_WITH_OVERHEAD(buf_len));
+ count = mt76u_process_rx_entry(dev, buf);
+ if (count > 0) {
+ err = mt76u_refill_rx(dev, q, buf, count,
+ GFP_ATOMIC);
if (err < 0)
break;
}
@@ -521,8 +567,13 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers);
static int mt76u_alloc_rx(struct mt76_dev *dev)
{
+ struct mt76_usb *usb = &dev->usb;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- int i, err, nsgs;
+ int i, err;
+
+ usb->mcu.data = devm_kmalloc(dev->dev, MCU_RESP_URB_SIZE, GFP_KERNEL);
+ if (!usb->mcu.data)
+ return -ENOMEM;
spin_lock_init(&q->rx_page_lock);
spin_lock_init(&q->lock);
@@ -532,23 +583,13 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
if (!q->entry)
return -ENOMEM;
- if (mt76u_check_sg(dev)) {
- q->buf_size = MT_RX_BUF_SIZE;
- nsgs = MT_SG_MAX_SIZE;
- } else {
- q->buf_size = PAGE_SIZE;
- nsgs = 1;
- }
-
- for (i = 0; i < MT_NUM_RX_ENTRIES; i++) {
- err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
- nsgs, q->buf_size,
- SKB_WITH_OVERHEAD(q->buf_size),
- GFP_KERNEL);
+ q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
+ q->ndesc = MT_NUM_RX_ENTRIES;
+ for (i = 0; i < q->ndesc; i++) {
+ err = mt76u_buf_alloc(dev, &q->entry[i].ubuf);
if (err < 0)
return err;
}
- q->ndesc = MT_NUM_RX_ENTRIES;
return mt76u_submit_rx_buffers(dev);
}
@@ -585,6 +626,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev)
static void mt76u_tx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
+ struct mt76_queue_entry entry;
struct mt76u_buf *buf;
struct mt76_queue *q;
bool wake;
@@ -599,17 +641,18 @@ static void mt76u_tx_tasklet(unsigned long data)
if (!buf->done || !q->queued)
break;
- dev->drv->tx_complete_skb(dev, q,
- &q->entry[q->head],
- false);
-
if (q->entry[q->head].schedule) {
q->entry[q->head].schedule = false;
q->swq_queued--;
}
+ entry = q->entry[q->head];
q->head = (q->head + 1) % q->ndesc;
q->queued--;
+
+ spin_unlock_bh(&q->lock);
+ dev->drv->tx_complete_skb(dev, q, &entry, false);
+ spin_lock_bh(&q->lock);
}
mt76_txq_schedule(dev, q);
wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
@@ -667,21 +710,15 @@ static void mt76u_complete_tx(struct urb *urb)
}
static int
-mt76u_tx_build_sg(struct sk_buff *skb, struct urb *urb)
+mt76u_tx_build_sg(struct mt76_dev *dev, struct sk_buff *skb,
+ struct urb *urb)
{
- int nsgs = 1 + skb_shinfo(skb)->nr_frags;
- struct sk_buff *iter;
-
- skb_walk_frags(skb, iter)
- nsgs += 1 + skb_shinfo(iter)->nr_frags;
-
- memset(urb->sg, 0, sizeof(*urb->sg) * MT_SG_MAX_SIZE);
-
- nsgs = min_t(int, MT_SG_MAX_SIZE, nsgs);
- sg_init_marker(urb->sg, nsgs);
- urb->num_sgs = nsgs;
+ if (!dev->usb.sg_en)
+ return 0;
- return skb_to_sgvec_nomark(skb, urb->sg, 0, skb->len);
+ sg_init_table(urb->sg, MT_SG_MAX_SIZE);
+ urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len);
+ return urb->num_sgs;
}
static int
@@ -689,12 +726,8 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
- u8 ep = q2ep(q->hw_idx);
struct mt76u_buf *buf;
u16 idx = q->tail;
- unsigned int pipe;
int err;
if (q->queued == q->ndesc)
@@ -706,15 +739,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
return err;
buf = &q->entry[idx].ubuf;
+ buf->buf = skb->data;
+ buf->len = skb->len;
buf->done = false;
- err = mt76u_tx_build_sg(skb, buf->urb);
+ err = mt76u_tx_build_sg(dev, skb, buf->urb);
if (err < 0)
return err;
- pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]);
- usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len,
- mt76u_complete_tx, buf);
+ mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
+ buf, mt76u_complete_tx, buf);
q->tail = (q->tail + 1) % q->ndesc;
q->entry[idx].skb = skb;
@@ -749,10 +783,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
{
struct mt76u_buf *buf;
struct mt76_queue *q;
- size_t size;
int i, j;
- size = MT_SG_MAX_SIZE * sizeof(struct scatterlist);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
q = &dev->q_tx[i];
spin_lock_init(&q->lock);
@@ -774,9 +806,15 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
if (!buf->urb)
return -ENOMEM;
- buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL);
- if (!buf->urb->sg)
- return -ENOMEM;
+ if (dev->usb.sg_en) {
+ size_t size = MT_SG_MAX_SIZE *
+ sizeof(struct scatterlist);
+
+ buf->urb->sg = devm_kzalloc(dev->dev, size,
+ GFP_KERNEL);
+ if (!buf->urb->sg)
+ return -ENOMEM;
+ }
}
}
return 0;
@@ -838,16 +876,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev)
err = mt76u_alloc_rx(dev);
if (err < 0)
- goto err;
-
- err = mt76u_alloc_tx(dev);
- if (err < 0)
- goto err;
+ return err;
- return 0;
-err:
- mt76u_queues_deinit(dev);
- return err;
+ return mt76u_alloc_tx(dev);
}
EXPORT_SYMBOL_GPL(mt76u_alloc_queues);
@@ -875,13 +906,14 @@ int mt76u_init(struct mt76_dev *dev,
INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data);
skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]);
- init_completion(&usb->mcu.cmpl);
mutex_init(&usb->mcu.mutex);
mutex_init(&usb->usb_ctrl_mtx);
dev->bus = &mt76u_ops;
dev->queue_ops = &usb_queue_ops;
+ usb->sg_en = mt76u_check_sg(dev);
+
return mt76u_set_endpoints(intf, usb);
}
EXPORT_SYMBOL_GPL(mt76u_init);
diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
deleted file mode 100644
index 036be4163e69..000000000000
--- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "mt76.h"
-
-void mt76u_mcu_complete_urb(struct urb *urb)
-{
- struct completion *cmpl = urb->context;
-
- complete(cmpl);
-}
-EXPORT_SYMBOL_GPL(mt76u_mcu_complete_urb);
-
-int mt76u_mcu_init_rx(struct mt76_dev *dev)
-{
- struct mt76_usb *usb = &dev->usb;
- int err;
-
- err = mt76u_buf_alloc(dev, &usb->mcu.res, 1,
- MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE,
- GFP_KERNEL);
- if (err < 0)
- return err;
-
- err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
- &usb->mcu.res, GFP_KERNEL,
- mt76u_mcu_complete_urb,
- &usb->mcu.cmpl);
- if (err < 0)
- mt76u_buf_free(&usb->mcu.res);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx);
-
-void mt76u_mcu_deinit(struct mt76_dev *dev)
-{
- struct mt76_usb *usb = &dev->usb;
-
- usb_kill_urb(usb->mcu.res.urb);
- mt76u_buf_free(&usb->mcu.res);
-}
-EXPORT_SYMBOL_GPL(mt76u_mcu_deinit);
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 0c35b8db58cd..69270c1a9091 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -75,4 +75,46 @@ int mt76_wcid_alloc(unsigned long *mask, int size)
}
EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
+int mt76_get_min_avg_rssi(struct mt76_dev *dev)
+{
+ struct mt76_wcid *wcid;
+ int i, j, min_rssi = 0;
+ s8 cur_rssi;
+
+ local_bh_disable();
+ rcu_read_lock();
+
+ for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
+ unsigned long mask = dev->wcid_mask[i];
+
+ if (!mask)
+ continue;
+
+ for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
+ if (!(mask & 1))
+ continue;
+
+ wcid = rcu_dereference(dev->wcid[j]);
+ if (!wcid)
+ continue;
+
+ spin_lock(&dev->rx_lock);
+ if (wcid->inactive_count++ < 5)
+ cur_rssi = -ewma_signal_read(&wcid->rssi);
+ else
+ cur_rssi = 0;
+ spin_unlock(&dev->rx_lock);
+
+ if (cur_rssi < min_rssi)
+ min_rssi = cur_rssi;
+ }
+ }
+
+ rcu_read_unlock();
+ local_bh_enable();
+
+ return min_rssi;
+}
+EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
+
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index 7f3e3983b781..f7edeffb2b19 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -124,9 +124,9 @@ static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)
u16 dma_len = get_unaligned_le16(data);
if (data_len < min_seg_len ||
- WARN_ON(!dma_len) ||
- WARN_ON(dma_len + MT_DMA_HDRS > data_len) ||
- WARN_ON(dma_len & 0x3))
+ WARN_ON_ONCE(!dma_len) ||
+ WARN_ON_ONCE(dma_len + MT_DMA_HDRS > data_len) ||
+ WARN_ON_ONCE(dma_len & 0x3))
return 0;
return MT_DMA_HDRS + dma_len;
diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.h b/drivers/net/wireless/mediatek/mt7601u/eeprom.h
index 662d12703b69..57b503ae63f1 100644
--- a/drivers/net/wireless/mediatek/mt7601u/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt7601u/eeprom.h
@@ -17,7 +17,7 @@
struct mt7601u_dev;
-#define MT7601U_EE_MAX_VER 0x0c
+#define MT7601U_EE_MAX_VER 0x0d
#define MT7601U_EEPROM_SIZE 256
#define MT7601U_DEFAULT_TX_POWER 6
diff --git a/drivers/net/wireless/quantenna/Makefile b/drivers/net/wireless/quantenna/Makefile
index baebfbde119e..cea83d178d2e 100644
--- a/drivers/net/wireless/quantenna/Makefile
+++ b/drivers/net/wireless/quantenna/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2015-2016 Quantenna Communications, Inc.
# All rights reserved.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 528ca7f5e070..14b569b6d1b5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015 Quantenna Communications
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */
#ifndef QTNFMAC_BUS_H
#define QTNFMAC_BUS_H
@@ -135,7 +122,5 @@ static __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus)
int qtnf_core_attach(struct qtnf_bus *bus);
void qtnf_core_detach(struct qtnf_bus *bus);
-void qtnf_txflowblock(struct device *dev, bool state);
-void qtnf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
#endif /* QTNFMAC_BUS_H */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 51b33ec78fac..dcb0991432f4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012-2012 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/kernel.h>
#include <linux/etherdevice.h>
@@ -66,9 +53,11 @@ static const u32 qtnf_cipher_suites[] = {
static const struct ieee80211_txrx_stypes
qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
- .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4),
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4),
},
[NL80211_IFTYPE_AP] = {
.tx = BIT(IEEE80211_STYPE_ACTION >> 4),
@@ -122,7 +111,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
struct vif_params *params)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
- u8 *mac_addr;
+ u8 *mac_addr = NULL;
+ int use4addr = 0;
int ret;
ret = qtnf_validate_iface_combinations(wiphy, vif, type);
@@ -132,14 +122,14 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
return ret;
}
- if (params)
+ if (params) {
mac_addr = params->macaddr;
- else
- mac_addr = NULL;
+ use4addr = params->use_4addr;
+ }
qtnf_scan_done(vif->mac, true);
- ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
+ ret = qtnf_cmd_send_change_intf_type(vif, type, use4addr, mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to change type to %d\n",
vif->mac->macid, vif->vifid, type);
@@ -190,6 +180,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
struct qtnf_wmac *mac;
struct qtnf_vif *vif;
u8 *mac_addr = NULL;
+ int use4addr = 0;
int ret;
mac = wiphy_priv(wiphy);
@@ -225,10 +216,12 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
return ERR_PTR(-ENOTSUPP);
}
- if (params)
+ if (params) {
mac_addr = params->macaddr;
+ use4addr = params->use_4addr;
+ }
- ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+ ret = qtnf_cmd_send_add_intf(vif, type, use4addr, mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to add VIF %pM\n",
mac->macid, vif->vifid, mac_addr);
@@ -359,11 +352,6 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return -EFAULT;
}
- if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) {
- pr_err("MAC%u: can't modify retry params\n", mac->macid);
- return -EOPNOTSUPP;
- }
-
ret = qtnf_cmd_send_update_phy_params(mac, changed);
if (ret)
pr_err("MAC%u: failed to update PHY params\n", mac->macid);
@@ -650,6 +638,12 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
+ if (sme->auth_type == NL80211_AUTHTYPE_SAE &&
+ !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) {
+ pr_err("can not offload authentication to userspace\n");
+ return -EOPNOTSUPP;
+ }
+
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
@@ -667,6 +661,30 @@ out:
}
static int
+qtnf_external_auth(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_external_auth_params *auth)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (!ether_addr_equal(vif->bssid, auth->bssid))
+ pr_warn("unexpected bssid: %pM", auth->bssid);
+
+ ret = qtnf_cmd_send_external_auth(vif, auth);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to report external auth\n",
+ vif->mac->macid, vif->vifid);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static int
qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code)
{
@@ -960,6 +978,7 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
.set_default_mgmt_key = qtnf_set_default_mgmt_key,
.scan = qtnf_scan,
.connect = qtnf_connect,
+ .external_auth = qtnf_external_auth,
.disconnect = qtnf_disconnect,
.dump_survey = qtnf_dump_survey,
.get_channel = qtnf_get_channel,
@@ -1107,7 +1126,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_AP_UAPSD |
- WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+ WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+ WIPHY_FLAG_4ADDR_STATION;
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
@@ -1138,6 +1158,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN))
wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
+ if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE)
+ wiphy->features |= NL80211_FEATURE_SAE;
+
#ifdef CONFIG_PM
if (macinfo->wowlan)
wiphy->wowlan = macinfo->wowlan;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
index b73425122a10..c374857283ac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_CFG80211_H_
#define _QTN_FMAC_CFG80211_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 659e7649fe22..85a2a58f4c16 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1,17 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, 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.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/types.h>
#include <linux/skbuff.h>
@@ -72,6 +60,8 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
return -EADDRINUSE;
case QLINK_CMD_RESULT_EADDRNOTAVAIL:
return -EADDRNOTAVAIL;
+ case QLINK_CMD_RESULT_EBUSY:
+ return -EBUSY;
default:
return -EFAULT;
}
@@ -97,14 +87,12 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
vif_id = cmd->vifid;
cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
- pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
- le16_to_cpu(cmd->cmd_id));
+ pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
if (bus->fw_state != QTNF_FW_STATE_ACTIVE &&
- le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT) {
+ cmd_id != QLINK_CMD_FW_INIT) {
pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
- mac_id, vif_id, le16_to_cpu(cmd->cmd_id),
- bus->fw_state);
+ mac_id, vif_id, cmd_id, bus->fw_state);
dev_kfree_skb(cmd_skb);
return -ENODEV;
}
@@ -138,7 +126,7 @@ out:
return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result));
pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
- mac_id, vif_id, le16_to_cpu(cmd->cmd_id), ret);
+ mac_id, vif_id, cmd_id, ret);
return ret;
}
@@ -732,6 +720,7 @@ out:
static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
enum nl80211_iftype iftype,
+ int use4addr,
u8 *mac_addr,
enum qlink_cmd_type cmd_type)
{
@@ -749,6 +738,7 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
qtnf_bus_lock(vif->mac->bus);
cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+ cmd->intf_info.use4addr = use4addr;
switch (iftype) {
case NL80211_IFTYPE_AP:
@@ -784,17 +774,19 @@ out:
return ret;
}
-int qtnf_cmd_send_add_intf(struct qtnf_vif *vif,
- enum nl80211_iftype iftype, u8 *mac_addr)
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
+ int use4addr, u8 *mac_addr)
{
- return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+ return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
QLINK_CMD_ADD_INTF);
}
int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
- enum nl80211_iftype iftype, u8 *mac_addr)
+ enum nl80211_iftype iftype,
+ int use4addr,
+ u8 *mac_addr)
{
- return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+ return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
QLINK_CMD_CHANGE_INTF);
}
@@ -914,9 +906,8 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
return -E2BIG;
- hwinfo->rd = kzalloc(sizeof(*hwinfo->rd)
- + sizeof(struct ieee80211_reg_rule)
- * resp->n_reg_rules, GFP_KERNEL);
+ hwinfo->rd = kzalloc(struct_size(hwinfo->rd, reg_rules,
+ resp->n_reg_rules), GFP_KERNEL);
if (!hwinfo->rd)
return -ENOMEM;
@@ -1558,11 +1549,11 @@ static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
switch (tlv_type) {
case QTN_TLV_ID_FRAG_THRESH:
phy_thr = (void *)tlv;
- mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr);
+ mac_info->frag_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_RTS_THRESH:
phy_thr = (void *)tlv;
- mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr);
+ mac_info->rts_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_SRETRY_LIMIT:
limit = (void *)tlv;
@@ -1810,15 +1801,23 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
qtnf_bus_lock(mac->bus);
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
- qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
+ qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
wiphy->frag_threshold);
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
- qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH,
+ qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
wiphy->rts_threshold);
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
wiphy->coverage_class);
+ if (changed & WIPHY_PARAM_RETRY_LONG)
+ qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
+ wiphy->retry_long);
+
+ if (changed & WIPHY_PARAM_RETRY_SHORT)
+ qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
+ wiphy->retry_short);
+
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
@@ -2323,6 +2322,35 @@ out:
return ret;
}
+int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
+ struct cfg80211_external_auth_params *auth)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_external_auth *cmd;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_EXTERNAL_AUTH,
+ sizeof(*cmd));
+ if (!cmd_skb)
+ return -ENOMEM;
+
+ cmd = (struct qlink_cmd_external_auth *)cmd_skb->data;
+
+ ether_addr_copy(cmd->bssid, auth->bssid);
+ cmd->status = cpu_to_le16(auth->status);
+
+ qtnf_bus_lock(vif->mac->bus);
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
+ if (ret)
+ goto out;
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+
+ return ret;
+}
+
int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
{
struct sk_buff *cmd_skb;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 1ac41156c192..64f0b9dc8a14 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -1,17 +1,5 @@
-/*
- * Copyright (c) 2016 Quantenna Communications, 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.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2016 Quantenna Communications. All rights reserved. */
#ifndef QLINK_COMMANDS_H_
#define QLINK_COMMANDS_H_
@@ -26,9 +14,11 @@ void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus);
int qtnf_cmd_get_hw_info(struct qtnf_bus *bus);
int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac);
int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
- u8 *mac_addr);
+ int use4addr, u8 *mac_addr);
int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
- enum nl80211_iftype iftype, u8 *mac_addr);
+ enum nl80211_iftype iftype,
+ int use4addr,
+ u8 *mac_addr);
int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
struct ieee80211_supported_band *band);
@@ -61,6 +51,8 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
int qtnf_cmd_send_scan(struct qtnf_wmac *mac);
int qtnf_cmd_send_connect(struct qtnf_vif *vif,
struct cfg80211_connect_params *sme);
+int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
+ struct cfg80211_external_auth_params *auth);
int qtnf_cmd_send_disconnect(struct qtnf_vif *vif,
u16 reason_code);
int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 5d18a4a917c9..ee1b75fda1dd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -195,6 +182,7 @@ static int qtnf_netdev_set_mac_address(struct net_device *ndev, void *addr)
qtnf_scan_done(vif->mac, true);
ret = qtnf_cmd_send_change_intf_type(vif, vif->wdev.iftype,
+ vif->wdev.use_4addr,
sa->sa_data);
if (ret)
@@ -545,7 +533,8 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
goto error;
}
- ret = qtnf_cmd_send_add_intf(vif, vif->wdev.iftype, vif->mac_addr);
+ ret = qtnf_cmd_send_add_intf(vif, vif->wdev.iftype,
+ vif->wdev.use_4addr, vif->mac_addr);
if (ret) {
pr_err("MAC%u: failed to add VIF\n", macid);
goto error;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 293055049caa..a31cff46e964 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_CORE_H_
#define _QTN_FMAC_CORE_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c
index 9f826b9ef5d9..598ece753a4b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/debug.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c
@@ -1,32 +1,11 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include "debug.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "qtnfmac dbg: %s: " fmt, __func__
-
void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
{
bus->dbg_dir = debugfs_create_dir(name, NULL);
-
- if (IS_ERR_OR_NULL(bus->dbg_dir)) {
- pr_warn("failed to create debugfs root dir\n");
- bus->dbg_dir = NULL;
- }
}
void qtnf_debugfs_remove(struct qtnf_bus *bus)
@@ -38,9 +17,5 @@ void qtnf_debugfs_remove(struct qtnf_bus *bus)
void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
int (*fn)(struct seq_file *seq, void *data))
{
- struct dentry *entry;
-
- entry = debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn);
- if (IS_ERR_OR_NULL(entry))
- pr_warn("failed to add entry (%s)\n", name);
+ debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn);
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.h b/drivers/net/wireless/quantenna/qtnfmac/debug.h
index d6dd12b5d434..61b45536b83a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/debug.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/debug.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_DEBUG_H_
#define _QTN_FMAC_DEBUG_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 8b542b431b75..6c1b886339ac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -158,6 +145,19 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
const struct qlink_event_bss_join *join_info,
u16 len)
{
+ struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+ enum ieee80211_statuscode status = le16_to_cpu(join_info->status);
+ struct cfg80211_chan_def chandef;
+ struct cfg80211_bss *bss = NULL;
+ u8 *ie = NULL;
+ size_t payload_len;
+ u16 tlv_type;
+ u16 tlv_value_len;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+ const u8 *rsp_ies = NULL;
+ size_t rsp_ies_len = 0;
+
if (unlikely(len < sizeof(*join_info))) {
pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
vif->mac->macid, vif->vifid, len,
@@ -171,15 +171,131 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
return -EPROTO;
}
- pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
- join_info->bssid);
+ pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
+ vif->mac->macid, vif->vifid, join_info->bssid, status);
+
+ if (status != WLAN_STATUS_SUCCESS)
+ goto done;
+
+ qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
+ if (!cfg80211_chandef_valid(&chandef)) {
+ pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
+ vif->mac->macid, vif->vifid,
+ chandef.chan->center_freq,
+ chandef.center_freq1,
+ chandef.center_freq2,
+ chandef.width);
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+
+ bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
+ NULL, 0, IEEE80211_BSS_TYPE_ESS,
+ IEEE80211_PRIVACY_ANY);
+ if (!bss) {
+ pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+ vif->mac->macid, vif->vifid,
+ join_info->bssid, chandef.chan->hw_value);
+
+ if (!vif->wdev.ssid_len) {
+ pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
+ vif->mac->macid, vif->vifid,
+ join_info->bssid);
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+
+ ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
+ if (!ie) {
+ pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
+ vif->mac->macid, vif->vifid,
+ join_info->bssid);
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+
+ ie[0] = WLAN_EID_SSID;
+ ie[1] = vif->wdev.ssid_len;
+ memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
+
+ bss = cfg80211_inform_bss(wiphy, chandef.chan,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ join_info->bssid, 0,
+ WLAN_CAPABILITY_ESS, 100,
+ ie, 2 + vif->wdev.ssid_len,
+ 0, GFP_KERNEL);
+ if (!bss) {
+ pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
+ vif->mac->macid, vif->vifid,
+ join_info->bssid);
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+ }
+
+ payload_len = len - sizeof(*join_info);
+ tlv = (struct qlink_tlv_hdr *)join_info->ies;
+
+ while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+ if (payload_len < tlv_full_len) {
+ pr_warn("invalid %u TLV\n", tlv_type);
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+
+ if (tlv_type == QTN_TLV_ID_IE_SET) {
+ const struct qlink_tlv_ie_set *ie_set;
+ unsigned int ie_len;
+
+ if (payload_len < sizeof(*ie_set)) {
+ pr_warn("invalid IE_SET TLV\n");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto done;
+ }
+
+ ie_set = (const struct qlink_tlv_ie_set *)tlv;
+ ie_len = tlv_value_len -
+ (sizeof(*ie_set) - sizeof(ie_set->hdr));
+
+ switch (ie_set->type) {
+ case QLINK_IE_SET_ASSOC_RESP:
+ if (ie_len) {
+ rsp_ies = ie_set->ie_data;
+ rsp_ies_len = ie_len;
+ }
+ break;
+ default:
+ pr_warn("unexpected IE type: %u\n",
+ ie_set->type);
+ break;
+ }
+ }
- cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
- 0, le16_to_cpu(join_info->status), GFP_KERNEL);
+ payload_len -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
- if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS)
+ if (payload_len)
+ pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n",
+ vif->mac->macid, vif->vifid, payload_len);
+
+done:
+ cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies,
+ rsp_ies_len, status, GFP_KERNEL);
+ if (bss) {
+ if (!ether_addr_equal(vif->bssid, join_info->bssid))
+ ether_addr_copy(vif->bssid, join_info->bssid);
+ cfg80211_put_bss(wiphy, bss);
+ }
+
+ if (status == WLAN_STATUS_SUCCESS)
netif_carrier_on(vif->netdev);
+ kfree(ie);
return 0;
}
@@ -458,6 +574,43 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
return 0;
}
+static int
+qtnf_event_handle_external_auth(struct qtnf_vif *vif,
+ const struct qlink_event_external_auth *ev,
+ u16 len)
+{
+ struct cfg80211_external_auth_params auth = {0};
+ struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+ int ret;
+
+ if (len < sizeof(*ev)) {
+ pr_err("MAC%u: payload is too short\n", vif->mac->macid);
+ return -EINVAL;
+ }
+
+ if (!wiphy->registered || !vif->netdev)
+ return 0;
+
+ if (ev->ssid_len) {
+ memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len);
+ auth.ssid.ssid_len = ev->ssid_len;
+ }
+
+ auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
+ ether_addr_copy(auth.bssid, ev->bssid);
+ auth.action = ev->action;
+
+ pr_info("%s: external auth bss=%pM action=%u akm=%u\n",
+ vif->netdev->name, auth.bssid, auth.action,
+ auth.key_mgmt_suite);
+
+ ret = cfg80211_external_auth_request(vif->netdev, &auth, GFP_KERNEL);
+ if (ret)
+ pr_warn("failed to offload external auth request\n");
+
+ return ret;
+}
+
static int qtnf_event_parse(struct qtnf_wmac *mac,
const struct sk_buff *event_skb)
{
@@ -516,6 +669,10 @@ static int qtnf_event_parse(struct qtnf_wmac *mac,
ret = qtnf_event_handle_radar(vif, (const void *)event,
event_len);
break;
+ case QLINK_EVENT_EXTERNAL_AUTH:
+ ret = qtnf_event_handle_external_auth(vif, (const void *)event,
+ event_len);
+ break;
default:
pr_warn("unknown event type: %x\n", event_id);
break;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.h b/drivers/net/wireless/quantenna/qtnfmac/event.h
index ae759b602c2a..533ad99d045d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_EVENT_H_
#define _QTN_FMAC_EVENT_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index 598edb814421..cbcda57105f3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -559,6 +559,9 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void *data)
if (!priv->msi_enabled && !qtnf_topaz_intx_asserted(ts))
return IRQ_NONE;
+ if (!priv->msi_enabled)
+ qtnf_deassert_intx(ts);
+
priv->pcie_irq_count++;
qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in);
@@ -571,9 +574,6 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void *data)
tasklet_hi_schedule(&priv->reclaim_tq);
- if (!priv->msi_enabled)
- qtnf_deassert_intx(ts);
-
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 8d62addea895..7798edcf7980 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1,25 +1,12 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_QLINK_H_
#define _QTN_QLINK_H_
#include <linux/ieee80211.h>
-#define QLINK_PROTO_VER 11
+#define QLINK_PROTO_VER 13
#define QLINK_MACID_RSVD 0xFF
#define QLINK_VIFID_RSVD 0xFF
@@ -81,6 +68,7 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
QLINK_HW_CAPAB_OBSS_SCAN = BIT(5),
QLINK_HW_CAPAB_SCAN_DWELL = BIT(6),
+ QLINK_HW_CAPAB_SAE = BIT(8),
};
enum qlink_iface_type {
@@ -105,7 +93,8 @@ struct qlink_intf_info {
__le16 if_type;
__le16 vlanid;
u8 mac_addr[ETH_ALEN];
- u8 rsvd[2];
+ u8 use4addr;
+ u8 rsvd[1];
} __packed;
enum qlink_sta_flags {
@@ -262,6 +251,7 @@ enum qlink_cmd_type {
QLINK_CMD_DISCONNECT = 0x0061,
QLINK_CMD_PM_SET = 0x0062,
QLINK_CMD_WOWLAN_SET = 0x0063,
+ QLINK_CMD_EXTERNAL_AUTH = 0x0066,
};
/**
@@ -493,6 +483,20 @@ struct qlink_cmd_connect {
} __packed;
/**
+ * struct qlink_cmd_external_auth - data for QLINK_CMD_EXTERNAL_AUTH command
+ *
+ * @bssid: BSSID of the BSS to connect to
+ * @status: authentication status code
+ * @payload: variable portion of connection request.
+ */
+struct qlink_cmd_external_auth {
+ struct qlink_cmd chdr;
+ u8 bssid[ETH_ALEN];
+ __le16 status;
+ u8 payload[0];
+} __packed;
+
+/**
* struct qlink_cmd_disconnect - data for QLINK_CMD_DISCONNECT command
*
* @reason: code of the reason of disconnect, see &enum ieee80211_reasoncode.
@@ -733,6 +737,7 @@ enum qlink_cmd_result {
QLINK_CMD_RESULT_EALREADY,
QLINK_CMD_RESULT_EADDRINUSE,
QLINK_CMD_RESULT_EADDRNOTAVAIL,
+ QLINK_CMD_RESULT_EBUSY,
};
/**
@@ -936,6 +941,7 @@ enum qlink_event_type {
QLINK_EVENT_BSS_LEAVE = 0x0027,
QLINK_EVENT_FREQ_CHANGE = 0x0028,
QLINK_EVENT_RADAR = 0x0029,
+ QLINK_EVENT_EXTERNAL_AUTH = 0x0030,
};
/**
@@ -986,13 +992,16 @@ struct qlink_event_sta_deauth {
/**
* struct qlink_event_bss_join - data for QLINK_EVENT_BSS_JOIN event
*
+ * @chan: new operating channel definition
* @bssid: BSSID of a BSS which interface tried to joined.
* @status: status of joining attempt, see &enum ieee80211_statuscode.
*/
struct qlink_event_bss_join {
struct qlink_event ehdr;
+ struct qlink_chandef chan;
u8 bssid[ETH_ALEN];
__le16 status;
+ u8 ies[0];
} __packed;
/**
@@ -1108,6 +1117,24 @@ struct qlink_event_radar {
u8 rsvd[3];
} __packed;
+/**
+ * struct qlink_event_external_auth - data for QLINK_EVENT_EXTERNAL_AUTH event
+ *
+ * @ssid: SSID announced by BSS
+ * @ssid_len: SSID length
+ * @bssid: BSSID of the BSS to connect to
+ * @akm_suite: AKM suite for external authentication
+ * @action: action type/trigger for external authentication
+ */
+struct qlink_event_external_auth {
+ struct qlink_event ehdr;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_len;
+ u8 bssid[ETH_ALEN];
+ __le32 akm_suite;
+ u8 action;
+} __packed;
+
/* QLINK TLVs (Type-Length Values) definitions
*/
@@ -1182,7 +1209,7 @@ struct qlink_iface_limit_record {
struct qlink_tlv_frag_rts_thr {
struct qlink_tlv_hdr hdr;
- __le16 thr;
+ __le32 thr;
} __packed;
struct qlink_tlv_rlimit {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index aeeda81b09ea..72bfd17cb687 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -1,17 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, 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.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/nl80211.h>
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 960d5d97492f..781ea7fe79f2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_QLINK_UTIL_H_
#define _QTN_FMAC_QLINK_UTIL_H_
@@ -69,6 +56,17 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,
memcpy(hdr->val, &tmp, sizeof(tmp));
}
+static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb,
+ u16 tlv_id, u32 value)
+{
+ struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value));
+ __le32 tmp = cpu_to_le32(value);
+
+ hdr->type = cpu_to_le16(tlv_id);
+ hdr->len = cpu_to_le16(sizeof(value));
+ memcpy(hdr->val, &tmp, sizeof(tmp));
+}
+
u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
void qlink_chandef_q2cfg(struct wiphy *wiphy,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
index 40295a511224..82d879950b62 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_HW_IDS_H_
#define _QTN_HW_IDS_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
index 2ec334199c2b..ff678951d3b2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/types.h>
#include <linux/io.h>
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
index c2a3702a9ee7..52cac5439b03 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_SHM_IPC_H_
#define _QTN_FMAC_SHM_IPC_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
index 95a5f89a8b1a..78be70df1218 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_SHM_IPC_DEFS_H_
#define _QTN_FMAC_SHM_IPC_DEFS_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.c b/drivers/net/wireless/quantenna/qtnfmac/trans.c
index 345f34ec9750..95356e280e23 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/trans.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/trans.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include <linux/types.h>
#include <linux/export.h>
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.h b/drivers/net/wireless/quantenna/qtnfmac/trans.h
index 9a473e07af0f..c0b76f871b31 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/trans.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/trans.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#ifndef _QTN_FMAC_TRANS_H_
#define _QTN_FMAC_TRANS_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c
index 3bc96b264769..cda6f5f3f38a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
#include "util.h"
#include "qtn_hw_ids.h"
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h
index b8744baac332..a14b7078a9c7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015 Quantenna Communications
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */
#ifndef QTNFMAC_UTIL_H
#define QTNFMAC_UTIL_H
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0e95555aec62..a03b5284a050 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -2966,6 +2966,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
struct channel_info *info)
{
u8 rfcsr;
+ int idx = rf->channel-1;
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
@@ -3003,60 +3004,56 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_freq_cal_mode1(rt2x00dev);
- if (rf->channel <= 14) {
- int idx = rf->channel-1;
-
- if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
- if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
- /* r55/r59 value array of channel 1~14 */
- static const char r55_bt_rev[] = {0x83, 0x83,
- 0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
- 0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
- static const char r59_bt_rev[] = {0x0e, 0x0e,
- 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
-
- rt2800_rfcsr_write(rt2x00dev, 55,
- r55_bt_rev[idx]);
- rt2800_rfcsr_write(rt2x00dev, 59,
- r59_bt_rev[idx]);
- } else {
- static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
- 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
- 0x88, 0x88, 0x86, 0x85, 0x84};
-
- rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
- }
+ if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
+ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+ /* r55/r59 value array of channel 1~14 */
+ static const char r55_bt_rev[] = {0x83, 0x83,
+ 0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
+ 0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
+ static const char r59_bt_rev[] = {0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
+
+ rt2800_rfcsr_write(rt2x00dev, 55,
+ r55_bt_rev[idx]);
+ rt2800_rfcsr_write(rt2x00dev, 59,
+ r59_bt_rev[idx]);
} else {
- if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
- static const char r55_nonbt_rev[] = {0x23, 0x23,
- 0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
- static const char r59_nonbt_rev[] = {0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
-
- rt2800_rfcsr_write(rt2x00dev, 55,
- r55_nonbt_rev[idx]);
- rt2800_rfcsr_write(rt2x00dev, 59,
- r59_nonbt_rev[idx]);
- } else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392) ||
- rt2x00_rt(rt2x00dev, RT6352)) {
- static const char r59_non_bt[] = {0x8f, 0x8f,
- 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
- 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
-
- rt2800_rfcsr_write(rt2x00dev, 59,
- r59_non_bt[idx]);
- } else if (rt2x00_rt(rt2x00dev, RT5350)) {
- static const char r59_non_bt[] = {0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
- 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
-
- rt2800_rfcsr_write(rt2x00dev, 59,
- r59_non_bt[idx]);
- }
+ static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
+ 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
+ 0x88, 0x88, 0x86, 0x85, 0x84};
+
+ rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
+ }
+ } else {
+ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+ static const char r55_nonbt_rev[] = {0x23, 0x23,
+ 0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+ static const char r59_nonbt_rev[] = {0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
+
+ rt2800_rfcsr_write(rt2x00dev, 55,
+ r55_nonbt_rev[idx]);
+ rt2800_rfcsr_write(rt2x00dev, 59,
+ r59_nonbt_rev[idx]);
+ } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT6352)) {
+ static const char r59_non_bt[] = {0x8f, 0x8f,
+ 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
+ 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
+
+ rt2800_rfcsr_write(rt2x00dev, 59,
+ r59_non_bt[idx]);
+ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
+ static const char r59_non_bt[] = {0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
+ 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
+
+ rt2800_rfcsr_write(rt2x00dev, 59,
+ r59_non_bt[idx]);
}
}
}
@@ -3861,10 +3858,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
if (rt2x00_rt(rt2x00dev, RT3572))
rt2800_rfcsr_write(rt2x00dev, 8, 0);
- if (rt2x00_rt(rt2x00dev, RT6352))
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
- else
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1);
+ } else {
tx_pin = 0;
+ }
switch (rt2x00dev->default_ant.tx_chain_num) {
case 3:
@@ -3896,24 +3895,29 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
switch (rt2x00dev->default_ant.rx_chain_num) {
case 3:
/* Turn on tertiary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
+ rf->channel <= 14);
/* fall-through */
case 2:
/* Turn on secondary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
+ rf->channel <= 14);
/* fall-through */
case 1:
/* Turn on primary LNAs */
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
+ rf->channel > 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
+ rf->channel <= 14);
break;
}
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); /* mt7620 */
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
@@ -3985,13 +3989,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_bbp_write(rt2x00dev, 195, 141);
rt2800_bbp_write(rt2x00dev, 196, reg);
- /* AGC init */
- if (rt2x00_rt(rt2x00dev, RT6352))
- reg = 0x04;
- else
- reg = rf->channel <= 14 ? 0x1c : 0x24;
-
- reg += 2 * rt2x00dev->lna_gain;
+ /* AGC init.
+ * Despite the vendor driver using different values here for
+ * RT6352 chip, we use 0x1c for now. This may have to be changed
+ * once TSSI got implemented.
+ */
+ reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
rt2800_iq_calibrate(rt2x00dev, rf->channel);
@@ -5477,7 +5480,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002);
rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F);
- rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x06060606);
+ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index 61ba573e8bf1..05a2e8da412c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -656,36 +656,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->driver_folder =
debugfs_create_dir(intf->rt2x00dev->ops->name,
rt2x00dev->hw->wiphy->debugfsdir);
- if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
- goto exit;
intf->driver_entry =
rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
- if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
- goto exit;
intf->chipset_entry =
rt2x00debug_create_file_chipset("chipset",
intf, &intf->chipset_blob);
- if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
- goto exit;
intf->dev_flags = debugfs_create_file("dev_flags", 0400,
intf->driver_folder, intf,
&rt2x00debug_fop_dev_flags);
- if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
- goto exit;
intf->cap_flags = debugfs_create_file("cap_flags", 0400,
intf->driver_folder, intf,
&rt2x00debug_fop_cap_flags);
- if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
- goto exit;
intf->register_folder =
debugfs_create_dir("register", intf->driver_folder);
- if (IS_ERR(intf->register_folder) || !intf->register_folder)
- goto exit;
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
({ \
@@ -695,9 +683,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
0600, \
(__intf)->register_folder, \
&(__intf)->offset_##__name); \
- if (IS_ERR((__intf)->__name##_off_entry) || \
- !(__intf)->__name##_off_entry) \
- goto exit; \
\
(__intf)->__name##_val_entry = \
debugfs_create_file(__stringify(__name) "_value", \
@@ -705,9 +690,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
(__intf)->register_folder, \
(__intf), \
&rt2x00debug_fop_##__name); \
- if (IS_ERR((__intf)->__name##_val_entry) || \
- !(__intf)->__name##_val_entry) \
- goto exit; \
} \
})
@@ -721,15 +703,10 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->queue_folder =
debugfs_create_dir("queue", intf->driver_folder);
- if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
- goto exit;
intf->queue_frame_dump_entry =
debugfs_create_file("dump", 0400, intf->queue_folder,
intf, &rt2x00debug_fop_queue_dump);
- if (IS_ERR(intf->queue_frame_dump_entry)
- || !intf->queue_frame_dump_entry)
- goto exit;
skb_queue_head_init(&intf->frame_dump_skbqueue);
init_waitqueue_head(&intf->frame_dump_waitqueue);
@@ -747,10 +724,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
#endif
return;
-
-exit:
- rt2x00debug_deregister(rt2x00dev);
- rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
}
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
index 528cb0401df1..4956a54151cb 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
@@ -119,9 +119,9 @@ static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
/*
* Allocate DMA memory for descriptor and buffer.
*/
- addr = dma_zalloc_coherent(rt2x00dev->dev,
- queue->limit * queue->desc_size, &dma,
- GFP_KERNEL);
+ addr = dma_alloc_coherent(rt2x00dev->dev,
+ queue->limit * queue->desc_size, &dma,
+ GFP_KERNEL);
if (!addr)
return -ENOMEM;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index 4c5de8fc8f12..52b9fc480f8b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -321,97 +321,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key)
{
- struct hw_key_entry key_entry;
- struct rt2x00_field32 field;
- u32 mask;
- u32 reg;
-
- if (crypto->cmd == SET_KEY) {
- /*
- * rt2x00lib can't determine the correct free
- * key_idx for shared keys. We have 1 register
- * with key valid bits. The goal is simple, read
- * the register, if that is full we have no slots
- * left.
- * Note that each BSS is allowed to have up to 4
- * shared keys, so put a mask over the allowed
- * entries.
- */
- mask = (0xf << crypto->bssidx);
-
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
- reg &= mask;
-
- if (reg && reg == mask)
- return -ENOSPC;
-
- key->hw_key_idx += reg ? ffz(reg) : 0;
-
- /*
- * Upload key to hardware
- */
- memcpy(key_entry.key, crypto->key,
- sizeof(key_entry.key));
- memcpy(key_entry.tx_mic, crypto->tx_mic,
- sizeof(key_entry.tx_mic));
- memcpy(key_entry.rx_mic, crypto->rx_mic,
- sizeof(key_entry.rx_mic));
-
- reg = SHARED_KEY_ENTRY(key->hw_key_idx);
- rt2x00mmio_register_multiwrite(rt2x00dev, reg,
- &key_entry, sizeof(key_entry));
-
- /*
- * The cipher types are stored over 2 registers.
- * bssidx 0 and 1 keys are stored in SEC_CSR1 and
- * bssidx 1 and 2 keys are stored in SEC_CSR5.
- * Using the correct defines correctly will cause overhead,
- * so just calculate the correct offset.
- */
- if (key->hw_key_idx < 8) {
- field.bit_offset = (3 * key->hw_key_idx);
- field.bit_mask = 0x7 << field.bit_offset;
-
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR1);
- rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
- } else {
- field.bit_offset = (3 * (key->hw_key_idx - 8));
- field.bit_mask = 0x7 << field.bit_offset;
-
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR5);
- rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
- }
-
- /*
- * The driver does not support the IV/EIV generation
- * in hardware. However it doesn't support the IV/EIV
- * inside the ieee80211 frame either, but requires it
- * to be provided separately for the descriptor.
- * rt2x00lib will cut the IV/EIV data out of all frames
- * given to us by mac80211, but we must tell mac80211
- * to generate the IV/EIV data.
- */
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- }
-
/*
- * SEC_CSR0 contains only single-bit fields to indicate
- * a particular key is valid. Because using the FIELD32()
- * defines directly will cause a lot of overhead, we use
- * a calculation to determine the correct bit directly.
+ * Let the software handle the shared keys,
+ * since the hardware decryption does not work reliably,
+ * because the firmware does not know the key's keyidx.
*/
- mask = 1 << key->hw_key_idx;
-
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
- if (crypto->cmd == SET_KEY)
- reg |= mask;
- else if (crypto->cmd == DISABLE_KEY)
- reg &= ~mask;
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
-
- return 0;
+ return -EOPNOTSUPP;
}
static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 33ad87528d9a..44a943d18b84 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -959,7 +959,7 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) {
/* This is the selective translation table, only 2 entries */
writeb(0xf8,
- &((struct snaphdr_t __iomem *)ptx->var)->org[3]);
+ &((struct snaphdr_t __iomem *)ptx->var)->org[2]);
}
/* Copy body of ethernet packet without ethernet header */
memcpy_toio((void __iomem *)&ptx->var +
@@ -2211,7 +2211,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,
untranslate(local, skb, total_len);
}
} else { /* sniffer mode, so just pass whole packet */
- };
+ }
/************************/
/* Now pick up the rest of the fragments if any */
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile
index 2966681efaef..5d6b06d3c02c 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile
@@ -2,4 +2,4 @@ rtl818x_pci-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o
obj-$(CONFIG_RTL8180) += rtl818x_pci.o
-ccflags-y += -Idrivers/net/wireless/realtek/rtl818x
+ccflags-y += -I $(srctree)/$(src)/..
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
index 225c1c8851cc..d5f65372356b 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
@@ -803,7 +803,7 @@ static void rtl8180_config_cardbus(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, FEMR_SE, 0xffff);
} else {
reg16 = rtl818x_ioread16(priv, &priv->map->FEMR);
- reg16 |= (1 << 15) | (1 << 14) | (1 << 4);
+ reg16 |= (1 << 15) | (1 << 14) | (1 << 4);
rtl818x_iowrite16(priv, &priv->map->FEMR, reg16);
}
@@ -1723,8 +1723,8 @@ static int rtl8180_probe(struct pci_dev *pdev,
{
struct ieee80211_hw *dev;
struct rtl8180_priv *priv;
- unsigned long mem_addr, mem_len;
- unsigned int io_addr, io_len;
+ unsigned long mem_len;
+ unsigned int io_len;
int err;
const char *chip_name, *rf_name = NULL;
u32 reg;
@@ -1743,9 +1743,7 @@ static int rtl8180_probe(struct pci_dev *pdev,
goto err_disable_dev;
}
- io_addr = pci_resource_start(pdev, 0);
io_len = pci_resource_len(pdev, 0);
- mem_addr = pci_resource_start(pdev, 1);
mem_len = pci_resource_len(pdev, 1);
if (mem_len < sizeof(struct rtl818x_csr) ||
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile
index ff074912a095..95bac73ece7c 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile
@@ -2,4 +2,4 @@ rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o
obj-$(CONFIG_RTL8187) += rtl8187.o
-ccflags-y += -Idrivers/net/wireless/realtek/rtl818x
+ccflags-y += -I $(srctree)/$(src)/..
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index ef9b502ce576..217d2a7a43c7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "rc.h"
@@ -452,6 +430,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr);
} else {
u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 };
+
get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1);
SET_IEEE80211_PERM_ADDR(hw, rtlmac1);
}
@@ -481,7 +460,6 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
(void *)rtl_fwevt_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq,
(void *)rtl_c2hcmd_wq_callback);
-
}
void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq)
@@ -640,6 +618,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
u8 rate_flag = info->control.rates[0].flags;
u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0;
u8 sgi_80 = 0, bw_80 = 0;
+
tcb_desc->use_shortgi = false;
if (sta == NULL)
@@ -1872,6 +1851,7 @@ int rtl_rx_agg_stop(struct ieee80211_hw *hw,
return 0;
}
+
int rtl_tx_agg_oper(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid)
{
@@ -2095,7 +2075,6 @@ void rtl_watchdog_wq_callback(void *data)
* busytraffic we don't change channel
*/
if (mac->link_state >= MAC80211_LINKED) {
-
/* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */
for (idx = 0; idx <= 2; idx++) {
rtlpriv->link_info.num_rx_in4period[idx] =
@@ -2172,8 +2151,6 @@ label_lps_done:
;
}
- rtlpriv->link_info.num_rx_inperiod = 0;
- rtlpriv->link_info.num_tx_inperiod = 0;
for (tid = 0; tid <= 7; tid++)
rtlpriv->link_info.tidtx_inperiod[tid] = 0;
@@ -2236,6 +2213,8 @@ label_lps_done:
rtlpriv->btcoexist.btc_info.in_4way = false;
}
+ rtlpriv->link_info.num_rx_inperiod = 0;
+ rtlpriv->link_info.num_tx_inperiod = 0;
rtlpriv->link_info.bcn_rx_inperiod = 0;
/* <6> scan list */
@@ -2255,6 +2234,7 @@ void rtl_watch_dog_timer_callback(struct timer_list *t)
mod_timer(&rtlpriv->works.watchdog_timer,
jiffies + MSECS(RTL_WATCH_DOG_TIME));
}
+
void rtl_fwevt_wq_callback(void *data)
{
struct rtl_works *rtlworks =
@@ -2311,11 +2291,10 @@ static void rtl_c2h_content_parsing(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops;
const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
- u8 cmd_id, cmd_seq, cmd_len;
+ u8 cmd_id, cmd_len;
u8 *cmd_buf = NULL;
cmd_id = GET_C2H_CMD_ID(skb->data);
- cmd_seq = GET_C2H_SEQ(skb->data);
cmd_len = skb->len - C2H_DATA_OFFSET;
cmd_buf = GET_C2H_DATA_PTR(skb->data);
@@ -2407,6 +2386,7 @@ void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t)
rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
}
+
/*********************************************************
*
* frame process functions
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index a7ae40eaa3cd..99565ad09cdc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_BASE_H__
#define __RTL_BASE_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
index 02dff4c3f664..30a25480752d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2007-2011 Realtek Corporation.*/
#ifndef __HALBT_PRECOMP_H__
#define __HALBT_PRECOMP_H__
@@ -49,8 +28,6 @@
#include "halbtc8821a2ant.h"
#include "halbtc8821a1ant.h"
-#define GetDefaultAdapter(padapter) padapter
-
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
index f22fec093f1d..3ebc7c93b1e9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
@@ -1,36 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-/**************************************************************
- * Description:
- *
- * This file is for RTL8192E Co-exist mechanism
- *
- * History
- * 2012/11/15 Cosa first check in.
- *
- **************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2012 Realtek Corporation.*/
/**************************************************************
* include files
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
index b8c95c7afc06..41ac0d5dcc9c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2012 Realtek Corporation.*/
+
/*****************************************************************
* The following is for 8192E 2Ant BT Co-exist definition
*****************************************************************/
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index 59553db020ef..5f5739904edf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2012 Realtek Corporation.*/
/***************************************************************
* Description:
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
index 934f27893c16..9d41e11388ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2012 Realtek Corporation.*/
+
/**********************************************************************
* The following is for 8723B 1ANT BT Co-exist definition
**********************************************************************/
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index 6597f7cb3411..9f7b9af5bdcd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2012 Realtek Corporation.*/
+
/***************************************************************
* Description:
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
index aa24da402fb9..08aad6ef4046 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2012 Realtek Corporation.*/
+
#ifndef _HAL8723B_2_ANT
#define _HAL8723B_2_ANT
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
index b5d65872db84..fa5b73f81c57 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2012 Realtek Corporation.*/
/**************************************************************
* Description:
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
index a498ff5b1b9c..a63fb79a971a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2012 Realtek Corporation.*/
/*===========================================
* The following is for 8821A 1ANT BT Co-exist definition
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
index 01a9d303603b..e9e211fda264 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2012 Realtek Corporation.*/
/************************************************************
* Description:
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
index ce3e58c4e660..3df0ee8bd37b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2012 Realtek Corporation.*/
/*===========================================
* The following is for 8821A 2Ant BT Co-exist definition
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c
index 951b8c1e0153..145d6f9c017a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c
@@ -1,17 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2016-2017 Realtek Corporation.
- *
- * 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
- * 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.
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2016-2017 Realtek Corporation.*/
+
#include "halbt_precomp.h"
void ex_hal8822b_wifi_only_hw_config(struct wifi_only_cfg *wifionlycfg)
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h
index 6ec356542eea..5fc66cea74b2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h
@@ -1,17 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2016-2017 Realtek Corporation.
- *
- * 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
- * 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.
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2016-2017 Realtek Corporation.*/
+
#ifndef __INC_HAL8822BWIFIONLYHWCFG_H
#define __INC_HAL8822BWIFIONLYHWCFG_H
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index d748aab66aa2..2ac0481b29ef 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007-2013 Realtek Corporation.*/
#include "halbt_precomp.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index 9eae87d19120..ee9aeddf1ebc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __HALBTC_OUT_SRC_H__
#define __HALBTC_OUT_SRC_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index cce4a37ea408..0e509c33e9e6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
+
#include "../wifi.h"
#include <linux/vmalloc.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
index 8c996055de71..bf2cf8505aca 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL_BTC_H__
#define __RTL_BTC_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.c b/drivers/net/wireless/realtek/rtlwifi/cam.c
index f7a7dcbf945e..bf0e0bb1f99b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/cam.c
+++ b/drivers/net/wireless/realtek/rtlwifi/cam.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#include "wifi.h"
#include "cam.h"
#include <linux/export.h>
diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.h b/drivers/net/wireless/realtek/rtlwifi/cam.h
index e2e647d511c1..2461fa9afda0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/cam.h
+++ b/drivers/net/wireless/realtek/rtlwifi/cam.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_CAM_H_
#define __RTL_CAM_H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 4bf7967590ca..f73e690bbe8e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "core.h"
@@ -210,6 +188,7 @@ static void rtl_op_tx(struct ieee80211_hw *hw,
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_tcb_desc tcb_desc;
+
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
@@ -368,12 +347,14 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&rtlpriv->locks.conf_mutex);
}
+
static int rtl_op_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype new_type, bool p2p)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
int ret;
+
rtl_op_remove_interface(hw, vif);
vif->type = new_type;
@@ -903,6 +884,7 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw,
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&mac->rx_conf));
}
+
static int rtl_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -955,6 +937,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_sta_info *sta_entry;
+
if (sta) {
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
"Remove sta addr is %pM\n", sta->addr);
@@ -967,6 +950,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
}
return 0;
}
+
static int _rtl_get_hal_qnum(u16 queue)
{
int qnum;
@@ -1088,6 +1072,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
/*TODO: reference to enum ieee80211_bss_change */
if (changed & BSS_CHANGED_ASSOC) {
u8 mstatus;
+
if (bss_conf->assoc) {
struct ieee80211_sta *sta = NULL;
u8 keep_alive = 10;
@@ -1316,6 +1301,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
* set in sta_add, and will be NULL here */
if (vif->type == NL80211_IFTYPE_STATION) {
struct rtl_sta_info *sta_entry;
+
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
sta_entry->wireless_mode = mac->mode;
}
@@ -1957,5 +1943,7 @@ void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igvalue)
dm_digtable->bt30_cur_igi = 0x32;
dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+ dm_digtable->pre_cck_fa_state = 0;
+ dm_digtable->cur_cck_fa_state = 0;
}
EXPORT_SYMBOL(rtl_dm_diginit);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h
index 782ac2fc4b28..7447ff456710 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.h
+++ b/drivers/net/wireless/realtek/rtlwifi/core.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_CORE_H__
#define __RTL_CORE_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c
index d70385be9976..a051de16284d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "cam.h"
@@ -463,12 +442,9 @@ static const struct file_operations file_ops_common_write = {
#define RTL_DEBUGFS_ADD_CORE(name, mode, fopname) \
do { \
rtl_debug_priv_ ##name.rtlpriv = rtlpriv; \
- if (!debugfs_create_file(#name, mode, \
- parent, &rtl_debug_priv_ ##name, \
- &file_ops_ ##fopname)) \
- pr_err("Unable to initialize debugfs:%s/%s\n", \
- rtlpriv->dbg.debugfs_name, \
- #name); \
+ debugfs_create_file(#name, mode, parent, \
+ &rtl_debug_priv_ ##name, \
+ &file_ops_ ##fopname); \
} while (0)
#define RTL_DEBUGFS_ADD(name) \
@@ -486,11 +462,6 @@ void rtl_debug_add_one(struct ieee80211_hw *hw)
rtlpriv->dbg.debugfs_dir =
debugfs_create_dir(rtlpriv->dbg.debugfs_name, debugfs_topdir);
- if (!rtlpriv->dbg.debugfs_dir) {
- pr_err("Unable to init debugfs:/%s/%s\n", rtlpriv->cfg->name,
- rtlpriv->dbg.debugfs_name);
- return;
- }
parent = rtlpriv->dbg.debugfs_dir;
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h
index ad6834af618b..69f169d4d4ae 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.h
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_DEBUG_H__
#define __RTL_DEBUG_H__
@@ -157,7 +136,7 @@ enum dbgp_flag_e {
FEEPROM = 11,
FPWR = 12,
FDM = 13,
- FDBGCtrl = 14,
+ FDBGCTRL = 14,
FC2H = 15,
FBT = 16,
FINIT = 17,
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c
index 9729e51fce38..e68340dfd980 100644
--- a/drivers/net/wireless/realtek/rtlwifi/efuse.c
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * Tmis 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
- * published by the Free Software Foundation.
- *
- * Tmis 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.
- *
- * Tme full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#include "wifi.h"
#include "efuse.h"
#include "pci.h"
@@ -386,20 +365,20 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- u8 section_idx, i, Base;
+ u8 section_idx, i, base;
u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used;
bool wordchanged, result = true;
for (section_idx = 0; section_idx < 16; section_idx++) {
- Base = section_idx * 8;
+ base = section_idx * 8;
wordchanged = false;
for (i = 0; i < 8; i = i + 2) {
- if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] !=
- rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) ||
- (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] !=
- rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i +
- 1])) {
+ if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] !=
+ rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i] ||
+ rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] !=
+ rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i +
+ 1]) {
words_need++;
wordchanged = true;
}
@@ -495,6 +474,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
if (word_en != 0x0F) {
u8 tmpdata[8];
+
memcpy(tmpdata,
&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base],
8);
@@ -508,7 +488,6 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
break;
}
}
-
}
efuse_power_switch(hw, true, false);
@@ -540,7 +519,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
-void efuse_force_write_vendor_Id(struct ieee80211_hw *hw)
+void efuse_force_write_vendor_id(struct ieee80211_hw *hw)
{
u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -683,6 +662,7 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
efuse_power_switch(hw, false, true);
read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse);
efuse_power_switch(hw, false, false);
@@ -833,6 +813,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
if (0x0F != (badworden & 0x0F)) {
u8 reorg_offset = offset;
u8 reorg_worden = badworden;
+
efuse_pg_packet_write(hw, reorg_offset,
reorg_worden,
originaldata);
@@ -922,6 +903,7 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr,
if (0x0F != (badworden & 0x0F)) {
u8 reorg_offset = tmp_pkt.offset;
u8 reorg_worden = badworden;
+
efuse_pg_packet_write(hw, reorg_offset,
reorg_worden,
originaldata);
@@ -978,7 +960,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
-
if (write_state == PG_STATE_HEADER) {
dataempty = true;
badworden = 0x0F;
@@ -1132,40 +1113,39 @@ void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 tempval;
- u16 tmpV16;
+ u16 tmpv16;
if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) {
-
if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE &&
rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) {
rtl_write_byte(rtlpriv,
rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
} else {
- tmpV16 =
+ tmpv16 =
rtl_read_word(rtlpriv,
rtlpriv->cfg->maps[SYS_ISO_CTRL]);
- if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) {
- tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V];
+ if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) {
+ tmpv16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V];
rtl_write_word(rtlpriv,
rtlpriv->cfg->maps[SYS_ISO_CTRL],
- tmpV16);
+ tmpv16);
}
}
- tmpV16 = rtl_read_word(rtlpriv,
+ tmpv16 = rtl_read_word(rtlpriv,
rtlpriv->cfg->maps[SYS_FUNC_EN]);
- if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) {
- tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR];
+ if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) {
+ tmpv16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR];
rtl_write_word(rtlpriv,
- rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16);
+ rtlpriv->cfg->maps[SYS_FUNC_EN], tmpv16);
}
- tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]);
- if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) ||
- (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) {
- tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] |
+ tmpv16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]);
+ if ((!(tmpv16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) ||
+ (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) {
+ tmpv16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] |
rtlpriv->cfg->maps[EFUSE_ANA8M]);
rtl_write_word(rtlpriv,
- rtlpriv->cfg->maps[SYS_CLK], tmpV16);
+ rtlpriv->cfg->maps[SYS_CLK], tmpv16);
}
}
@@ -1240,6 +1220,7 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)
static u8 efuse_calculate_word_cnts(u8 word_en)
{
u8 word_cnts = 0;
+
if (!(word_en & BIT(0)))
word_cnts++;
if (!(word_en & BIT(1)))
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h
index dfa31c13fc7a..1ec59f439382 100644
--- a/drivers/net/wireless/realtek/rtlwifi/efuse.h
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_EFUSE_H_
#define __RTL_EFUSE_H_
@@ -107,7 +85,7 @@ void efuse_shadow_write(struct ieee80211_hw *hw, u8 type,
bool efuse_shadow_update(struct ieee80211_hw *hw);
bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
-void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
+void efuse_force_write_vendor_id(struct ieee80211_hw *hw);
void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate);
int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv,
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 5d1fda16fc8c..48ca52102cef 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index 3fb56c845a61..866861626a0a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_PCI_H__
#define __RTL_PCI_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index 479a4cfc245d..70f04c2f5b17 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "base.h"
@@ -740,6 +718,7 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data,
static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
u8 noa_num, index , i, noa_index = 0;
bool find_p2p_ie = false , find_p2p_ps_ie = false;
+
pos = (u8 *)mgmt->u.beacon.variable;
end = data + len;
ie = NULL;
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h
index 0df2b5203030..aaa2ed2bbe16 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.h
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __REALTEK_RTL_PCI_PS_H__
#define __REALTEK_RTL_PCI_PS_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h
index 17ce0cb2c35c..db1765c6fef6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_PWRSEQCMD_H__
#define __RTL8723E_PWRSEQCMD_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c
index 6c78c6dabbdf..cf8e42a01015 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rc.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "base.h"
@@ -258,6 +236,7 @@ static void rtl_tx_status(void *ppriv,
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 tid = rtl_get_tid(skb);
+
if (_rtl_tx_aggr_check(rtlpriv, sta_entry,
tid)) {
sta_entry->tids[tid].agg.agg_state =
@@ -315,6 +294,7 @@ static void rtl_rate_free_sta(void *rtlpriv,
struct ieee80211_sta *sta, void *priv_sta)
{
struct rtl_rate_priv *rate_priv = priv_sta;
+
kfree(rate_priv);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.h b/drivers/net/wireless/realtek/rtlwifi/rc.h
index f29643d60d6b..1c0a17370093 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rc.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_RC_H__
#define __RTL_RC_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index 1bf3eb25c1da..6ccb5b93a595 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -1,32 +1,10 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "regd.h"
-static struct country_code_to_enum_rd allCountries[] = {
+static struct country_code_to_enum_rd all_countries[] = {
{COUNTRY_CODE_FCC, "US"},
{COUNTRY_CODE_IC, "US"},
{COUNTRY_CODE_ETSI, "EC"},
@@ -63,7 +41,6 @@ static struct country_code_to_enum_rd allCountries[] = {
NL80211_RRF_PASSIVE_SCAN | \
NL80211_RRF_NO_OFDM)
-
/* 5G chan 36 - chan 64*/
#define RTL819x_5GHZ_5150_5350 \
REG_RULE(5150-10, 5350+10, 80, 0, 30, 0)
@@ -391,9 +368,9 @@ static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode)
{
int i;
- for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
- if (allCountries[i].countrycode == countrycode)
- return &allCountries[i];
+ for (i = 0; i < ARRAY_SIZE(all_countries); i++) {
+ if (all_countries[i].countrycode == countrycode)
+ return &all_countries[i];
}
return NULL;
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.h b/drivers/net/wireless/realtek/rtlwifi/regd.h
index f7f15bce35dd..3ba068511e34 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.h
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_REGD_H__
#define __RTL_REGD_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h
index 45c866d3ca88..fa2e1b063f68 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92C_DEF_H__
#define __RTL92C_DEF_H__
@@ -123,9 +101,6 @@
#define IS_92C_SERIAL(version) \
((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
-#define IS_81xxC_VENDOR_UMC_A_CUT(version) \
- (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \
- ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false)
#define IS_81XXC_VENDOR_UMC_B_CUT(version) \
(IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
index e05af7d60830..85360353f557 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
index 50f26a9a97db..eb8090caeec2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL88E_DM_H__
#define __RTL88E_DM_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
index 63874512598b..203e7b574e84 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
index b884c30c7b37..39ddb7afea9d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92C__FW__H__
#define __RTL92C__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
index cfc8762c55f4..454bab38b165 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
index 214cd2a32018..fd09b0712d17 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92CE_HW_H__
#define __RTL92CE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
index df3e214460db..4ef6d5907521 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
index 4b325b75faaf..67d3dc389ba0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
index 14a256062614..96d8f25b120f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h
index b29bd77210f4..8157ef419eeb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92C_PHY_H__
#define __RTL92C_PHY_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c
index 02013df968a0..d69497bf5d19 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../pwrseqcmd.h"
#include "pwrseq.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h
index 8379a3e5198c..42e222c1795f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL8723E_PWRSEQ_H__
#define __RTL8723E_PWRSEQ_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
index 0c0d64aea651..0fc8db8916fa 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92C_REG_H__
#define __RTL92C_REG_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c
index 30798b12a363..0f401ad92c2e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h
index 0eca030e3238..05e27b40b2a9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92C_RF_H__
#define __RTL92C_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 8c15ffd3568b..eab48fed61ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h
index 22398c3753a6..1407151503f8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92CE_SW_H__
#define __RTL92CE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c
index 68bcb7fe6a65..a3c312c3ed9a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "table.h"
u32 RTL8188EEPHY_REG_1TARRAY[] = {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h
index 403c4ddd236f..df6065602401 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92CE_TABLE__H_
#define __RTL92CE_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
index 14dcb0816bc0..106011a24827 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -415,7 +393,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
(GET_RX_DESC_FAGGR(pdesc) == 1));
if (status->packet_report_type == NORMAL_RX)
status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate);
@@ -442,7 +420,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (status->rx_is40Mhzpacket)
+ if (status->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (status->is_ht)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
index 127ba977206f..c29d9bfa5bd4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2013 Realtek Corporation.*/
#ifndef __RTL92CE_TRX_H__
#define __RTL92CE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
index 0b5a06ffa482..f2908ee5f860 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include <linux/export.h>
#include "dm_common.h"
@@ -447,7 +425,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
-
if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
dm_digtable->rssi_val_min =
rtl92c_dm_initial_gain_min_pwdb(hw);
@@ -526,7 +503,6 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
rtl92c_dm_cck_packet_detection_thresh(hw);
dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
-
}
static void rtl92c_dm_dig(struct ieee80211_hw *hw)
@@ -629,6 +605,7 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtlpriv->dm.current_turbo_edca = false;
rtlpriv->dm.is_any_nonbepkts = false;
rtlpriv->dm.is_cur_rdlstate = false;
@@ -682,7 +659,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
(!rtlpriv->dm.disable_framebursting))) {
-
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
@@ -707,6 +683,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
} else {
if (rtlpriv->dm.current_turbo_edca) {
u8 tmp = AC0_BE;
+
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
&tmp);
rtlpriv->dm.current_turbo_edca = false;
@@ -1657,7 +1634,6 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
-
/* Only enable HW BT coexist when BT in "Busy" state. */
if (rtlpriv->mac80211.vendor == PEER_CISCO &&
rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
index 441604ff5858..c4ce9fc96163 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92COMMON_DM_H__
#define __RTL92COMMON_DM_H__
@@ -49,7 +27,7 @@
#define DM_DIG_FA_TH1 0x100
#define DM_DIG_FA_TH2 0x200
-#define RXPATHSELECTION_SS_TH_lOW 30
+#define RXPATHSELECTION_SS_TH_LOW 30
#define RXPATHSELECTION_DIFF_TH 18
#define DM_RATR_STA_INIT 0
@@ -60,7 +38,7 @@
#define CTS2SELF_THVAL 30
#define REGC38_TH 20
-#define WAIOTTHVal 25
+#define WAIOTTHVAL 25
#define TXHIGHPWRLEVEL_NORMAL 0
#define TXHIGHPWRLEVEL_LEVEL1 1
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
index f3bff66e85d0..18c76990a089 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -40,6 +18,7 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+
if (enable)
value32 |= MCUFWDL_EN;
else
@@ -47,8 +26,8 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
u8 tmp;
- if (enable) {
+ if (enable) {
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
tmp | 0x04);
@@ -59,7 +38,6 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
} else {
-
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
@@ -79,27 +57,27 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
is_version_b = IS_NORMAL_CHIP(version);
if (is_version_b) {
- u32 pageNums, remainsize;
+ u32 pagenums, remainsize;
u32 page, offset;
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
rtl_fill_dummy(bufferptr, &size);
- pageNums = size / FW_8192C_PAGE_SIZE;
+ pagenums = size / FW_8192C_PAGE_SIZE;
remainsize = size % FW_8192C_PAGE_SIZE;
- if (pageNums > 4)
+ if (pagenums > 4)
pr_err("Page numbers should not greater then 4\n");
- for (page = 0; page < pageNums; page++) {
+ for (page = 0; page < pagenums; page++) {
offset = page * FW_8192C_PAGE_SIZE;
rtl_fw_page_write(hw, page, (bufferptr + offset),
FW_8192C_PAGE_SIZE);
}
if (remainsize) {
- offset = pageNums * FW_8192C_PAGE_SIZE;
- page = pageNums;
+ offset = pagenums * FW_8192C_PAGE_SIZE;
+ page = pagenums;
rtl_fw_page_write(hw, page, (bufferptr + offset),
remainsize);
}
@@ -118,7 +96,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
- (!(value32 & FWDL_ChkSum_rpt)));
+ (!(value32 & FWDL_CHKSUM_RPT)));
if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
@@ -644,7 +622,6 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
"rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
u1rsvdpageloc, 3);
-
skb = dev_alloc_skb(totalpacketlen);
skb_put_data(skb, &reserved_page_packet, totalpacketlen);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
index c5fa14bda387..888d9fc94bc2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C__FW__COMMON__H__
#define __RTL92C__FW__COMMON__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
index 889bd1301154..97ad21c3964f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
@@ -1,32 +1,9 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include <linux/module.h>
-
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
index 7c6e5d91439d..0efd19aa4fe5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../rtl8192ce/reg.h"
@@ -239,7 +217,7 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile);
-void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask,
u32 data)
{
@@ -393,7 +371,7 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
rtlphy->pwrgroup_cnt++;
}
}
-EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset);
+EXPORT_SYMBOL(_rtl92c_store_pwrindex_diffrate_offset);
void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
{
@@ -452,10 +430,10 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
RFPGA0_XB_LSSIPARAMETER;
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
- rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
- rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER;
rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
@@ -769,6 +747,7 @@ static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) {
if (channel == 6 &&
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
@@ -1120,19 +1099,19 @@ static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw,
static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw,
u32 *addareg, bool is_patha_on, bool is2t)
{
- u32 pathOn;
+ u32 pathon;
u32 i;
- pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
+ pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
if (false == is2t) {
- pathOn = 0x0bdb25a0;
+ pathon = 0x0bdb25a0;
rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
} else {
- rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn);
+ rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon);
}
for (i = 1; i < IQK_ADDA_REG_NUM; i++)
- rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn);
+ rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon);
}
static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw,
@@ -1361,7 +1340,7 @@ static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw,
if (is_hal_stop(rtlhal)) {
rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
- rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+ rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
}
if (is2t) {
if (bmain)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
index d11261e05a2e..75afa6253ad0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_PHY_COMMON_H__
#define __RTL92C_PHY_COMMON_H__
@@ -44,9 +22,9 @@
#define LOOP_LIMIT 5
#define MAX_STALL_TIME 50
-#define AntennaDiversityValue 0x80
+#define ANTENNADIVERSITYVALUE 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
-#define Reset_Cnt_Limit 3
+#define RESET_CNT_LIMIT 3
#define IQK_ADDA_REG_NUM 16
#define IQK_MAC_REG_NUM 4
@@ -242,7 +220,7 @@ void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 offset,
u32 data);
bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
-void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask,
u32 data);
bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
index d2005d7e9ad2..147bf2407f8f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_DEF_H__
#define __RTL92C_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
index 2c8205e46be4..a3e2c8a60967 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
index 9761d0ca31b0..eab42c1bd470 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_DM_H__
#define __RTL92C_DM_H__
@@ -44,7 +22,7 @@
#define DM_DIG_FA_TH1 0x100
#define DM_DIG_FA_TH2 0x200
-#define RXPATHSELECTION_SS_TH_lOW 30
+#define RXPATHSELECTION_SS_TH_LOW 30
#define RXPATHSELECTION_DIFF_TH 18
#define DM_RATR_STA_INIT 0
@@ -55,7 +33,7 @@
#define CTS2SELF_THVAL 30
#define REGC38_TH 20
-#define WAIOTTHVal 25
+#define WAIOTTHVAL 25
#define TXHIGHPWRLEVEL_NORMAL 0
#define TXHIGHPWRLEVEL_LEVEL1 1
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index 4a81e0ef4b8e..a52dd64d528d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -104,13 +82,13 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
break;
case HW_VAR_FWLPS_RF_ON:{
- enum rf_pwrstate rfState;
+ enum rf_pwrstate rfstate;
u32 val_rcr;
rtlpriv->cfg->ops->get_hw_reg(hw,
HW_VAR_RF_STATE,
- (u8 *) (&rfState));
- if (rfState == ERFOFF) {
+ (u8 *)(&rfstate));
+ if (rfstate == ERFOFF) {
*((bool *) (val)) = true;
} else {
val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
@@ -166,6 +144,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_BASIC_RATE:{
u16 rate_cfg = ((u16 *) val)[0];
u8 rate_index = 0;
+
rate_cfg &= 0x15f;
rate_cfg |= 0x01;
rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
@@ -219,6 +198,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_ACK_PREAMBLE:{
u8 reg_tmp;
u8 short_preamble = (bool)*val;
+
reg_tmp = (mac->cur_40_prime_sc) << 5;
if (short_preamble)
reg_tmp |= 0x80;
@@ -315,6 +295,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
case HW_VAR_AC_PARAM:{
u8 e_aci = *(val);
+
rtl92c_dm_init_edca_turbo(hw);
if (rtlpci->acm_method != EACMWAY2_SW)
@@ -336,13 +317,13 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
if (acm) {
switch (e_aci) {
case AC0_BE:
- acm_ctrl |= AcmHw_BeqEn;
+ acm_ctrl |= ACMHW_BEQEN;
break;
case AC2_VI:
- acm_ctrl |= AcmHw_ViqEn;
+ acm_ctrl |= ACMHW_VIQEN;
break;
case AC3_VO:
- acm_ctrl |= AcmHw_VoqEn;
+ acm_ctrl |= ACMHW_VOQEN;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -353,13 +334,13 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
} else {
switch (e_aci) {
case AC0_BE:
- acm_ctrl &= (~AcmHw_BeqEn);
+ acm_ctrl &= (~ACMHW_BEQEN);
break;
case AC2_VI:
- acm_ctrl &= (~AcmHw_ViqEn);
+ acm_ctrl &= (~ACMHW_VIQEN);
break;
case AC3_VO:
- acm_ctrl &= (~AcmHw_VoqEn);
+ acm_ctrl &= (~ACMHW_VOQEN);
break;
default:
pr_err("switch case %#x not processed\n",
@@ -478,6 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
break;
case HW_VAR_AID:{
u16 u2btmp;
+
u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
u2btmp &= 0xC000;
rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
@@ -584,23 +566,23 @@ static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned short i;
u8 txpktbuf_bndy;
- u8 maxPage;
+ u8 maxpage;
bool status;
#if LLT_CONFIG == 1
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 252;
#elif LLT_CONFIG == 2
- maxPage = 127;
+ maxpage = 127;
txpktbuf_bndy = 124;
#elif LLT_CONFIG == 3
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 174;
#elif LLT_CONFIG == 4
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 246;
#elif LLT_CONFIG == 5
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 246;
#endif
@@ -639,13 +621,13 @@ static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw)
if (true != status)
return status;
- for (i = txpktbuf_bndy; i < maxPage; i++) {
+ for (i = txpktbuf_bndy; i < maxpage; i++) {
status = _rtl92ce_llt_write(hw, i, (i + 1));
if (true != status)
return status;
}
- status = _rtl92ce_llt_write(hw, maxPage, txpktbuf_bndy);
+ status = _rtl92ce_llt_write(hw, maxpage, txpktbuf_bndy);
if (true != status)
return status;
@@ -683,6 +665,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
if (rtlpriv->btcoexist.bt_coexistence) {
u32 value32;
+
value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO);
value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK);
rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32);
@@ -908,11 +891,11 @@ void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw)
return;
}
- sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable;
+ sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE;
if (rtlpriv->sec.use_defaultkey) {
- sec_reg_value |= SCR_TxUseDK;
- sec_reg_value |= SCR_RxUseDK;
+ sec_reg_value |= SCR_TXUSEDK;
+ sec_reg_value |= SCR_RXUSEDK;
}
sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
@@ -1267,6 +1250,7 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtl92c_dm_init_edca_turbo(hw);
switch (aci) {
case AC1_BK:
@@ -2301,7 +2285,6 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw)
rtlpriv->btcoexist.reg_bt_sco = 0;
}
-
void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
index 6711ea1a75d9..fa1049d16cb7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_HW_H__
#define __RTL92CE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
index 7edf5af9046e..d6933d36ada2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
index f6edb9cd9b67..97ab1e00af5f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
index 7c6d7fc1ef9a..f6574f31fa3b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -104,7 +82,7 @@ bool rtl92c_phy_bb_config(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN,
FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE |
- FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ FEN_BB_GLB_RSTN | FEN_BBRSTB);
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
@@ -236,7 +214,7 @@ bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
rtl_addr_delay(phy_regarray_table_pg[i]);
- _rtl92c_store_pwrIndex_diffrate_offset(hw,
+ _rtl92c_store_pwrindex_diffrate_offset(hw,
phy_regarray_table_pg[i],
phy_regarray_table_pg[i + 1],
phy_regarray_table_pg[i + 2]);
@@ -464,13 +442,14 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
if ((ppsc->rfpwr_state == ERFOFF) &&
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
- u32 InitializeCount = 0;
+ u32 initializecount = 0;
+
do {
- InitializeCount++;
+ initializecount++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic enable\n");
rtstatus = rtl_ps_enable_nic(hw);
- } while (!rtstatus && (InitializeCount < 10));
+ } while (!rtstatus && (initializecount < 10));
RT_CLEAR_PS_LEVEL(ppsc,
RT_RF_OFF_LEVL_HALT_NIC);
} else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
index 93f3bc0197b4..7582a162bd11 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_PHY_H__
#define __RTL92C_PHY_H__
@@ -44,9 +22,9 @@
#define LOOP_LIMIT 5
#define MAX_STALL_TIME 50
-#define AntennaDiversityValue 0x80
+#define ANTENNADIVERSITYVALUE 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
-#define Reset_Cnt_Limit 3
+#define RESET_CNT_LIMIT 3
#define IQK_ADDA_REG_NUM 16
#define IQK_MAC_REG_NUM 4
@@ -122,7 +100,7 @@ void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 offset,
u32 data);
-void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask, u32 data);
bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
index 9e3b58a5d2bb..431277ef1c98 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_REG_H__
#define __RTL92C_REG_H__
@@ -702,7 +680,7 @@
#define PWC_EV12V BIT(15)
#define FEN_BBRSTB BIT(0)
-#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_BB_GLB_RSTN BIT(1)
#define FEN_USBA BIT(2)
#define FEN_UPLL BIT(3)
#define FEN_USBD BIT(4)
@@ -722,7 +700,7 @@
#define PFM_ALDN BIT(1)
#define PFM_LDKP BIT(2)
#define PFM_WOWL BIT(3)
-#define EnPDN BIT(4)
+#define ENPDN BIT(4)
#define PDN_PL BIT(5)
#define APFM_ONMAC BIT(8)
#define APFM_OFF BIT(9)
@@ -837,19 +815,19 @@
#define LDOE25_EN BIT(31)
#define RSM_EN BIT(0)
-#define Timer_EN BIT(4)
+#define TIMER_EN BIT(4)
#define TRSW0EN BIT(2)
#define TRSW1EN BIT(3)
#define EROM_EN BIT(4)
-#define EnBT BIT(5)
-#define EnUart BIT(8)
-#define Uart_910 BIT(9)
-#define EnPMAC BIT(10)
+#define ENBT BIT(5)
+#define ENUART BIT(8)
+#define UART_910 BIT(9)
+#define ENPMAC BIT(10)
#define SIC_SWRST BIT(11)
-#define EnSIC BIT(12)
+#define ENSIC BIT(12)
#define SIC_23 BIT(13)
-#define EnHDP BIT(14)
+#define ENHDP BIT(14)
#define SIC_LBK BIT(15)
#define LED0PL BIT(4)
@@ -858,7 +836,7 @@
#define MCUFWDL_EN BIT(0)
#define MCUFWDL_RDY BIT(1)
-#define FWDL_ChkSum_rpt BIT(2)
+#define FWDL_CHKSUM_RPT BIT(2)
#define MACINI_RDY BIT(3)
#define BBINI_RDY BIT(4)
#define RFINI_RDY BIT(5)
@@ -1076,13 +1054,13 @@
#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4)
#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
-#define AcmHw_HwEn BIT(0)
-#define AcmHw_BeqEn BIT(1)
-#define AcmHw_ViqEn BIT(2)
-#define AcmHw_VoqEn BIT(3)
-#define AcmHw_BeqStatus BIT(4)
-#define AcmHw_ViqStatus BIT(5)
-#define AcmHw_VoqStatus BIT(6)
+#define ACMHW_HWEN BIT(0)
+#define ACMHW_BEQEN BIT(1)
+#define ACMHW_VIQEN BIT(2)
+#define ACMHW_VOQEN BIT(3)
+#define ACMHW_BEQSTATUS BIT(4)
+#define ACMHW_VIQSTATUS BIT(5)
+#define ACMHW_VOQSTATUS BIT(6)
#define APSDOFF BIT(6)
#define APSDOFF_STATUS BIT(7)
@@ -1121,7 +1099,7 @@
#define BM_DATA_EN BIT(17)
#define MFBEN BIT(22)
#define LSIGEN BIT(23)
-#define EnMBID BIT(24)
+#define ENMBID BIT(24)
#define APP_BASSN BIT(27)
#define APP_PHYSTS BIT(28)
#define APP_ICV BIT(29)
@@ -1150,12 +1128,12 @@
#define RXERR_RPT_RST BIT(27)
#define _RXERR_RPT_SEL(type) ((type) << 28)
-#define SCR_TxUseDK BIT(0)
-#define SCR_RxUseDK BIT(1)
-#define SCR_TxEncEnable BIT(2)
-#define SCR_RxDecEnable BIT(3)
-#define SCR_SKByA2 BIT(4)
-#define SCR_NoSKMC BIT(5)
+#define SCR_TXUSEDK BIT(0)
+#define SCR_RXUSEDK BIT(1)
+#define SCR_TXENCENABLE BIT(2)
+#define SCR_RXDECENABLE BIT(3)
+#define SCR_SKBYA2 BIT(4)
+#define SCR_NOSKMC BIT(5)
#define SCR_TXBCUSEDK BIT(6)
#define SCR_RXBCUSEDK BIT(7)
@@ -1208,7 +1186,7 @@
#define RPMAC_CCKPLCPHEADER 0x144
#define RPMAC_CCKCRC16 0x148
#define RPMAC_OFDMRXCRC32OK 0x170
-#define RPMAC_OFDMRXCRC32Er 0x174
+#define RPMAC_OFDMRXCRC32ER 0x174
#define RPMAC_OFDMRXPARITYER 0x178
#define RPMAC_OFDMRXCRC8ER 0x17c
#define RPMAC_CCKCRXRC16ER 0x180
@@ -1246,8 +1224,8 @@
#define RFPGA0_XAB_RFINTERFACESW 0x870
#define RFPGA0_XCD_RFINTERFACESW 0x874
-#define rFPGA0_XAB_RFPARAMETER 0x878
-#define rFPGA0_XCD_RFPARAMETER 0x87c
+#define RFPGA0_XAB_RFPARAMETER 0x878
+#define RFPGA0_XCD_RFPARAMETER 0x87c
#define RFPGA0_ANALOGPARAMETER1 0x880
#define RFPGA0_ANALOGPARAMETER2 0x884
@@ -1521,8 +1499,8 @@
#define BCCKTXCRC16 0xffff
#define BCCKTXSTATUS 0x1
#define BOFDMTXSTATUS 0x2
-#define IS_BB_REG_OFFSET_92S(_Offset) \
- ((_Offset >= 0x800) && (_Offset <= 0xfff))
+#define IS_BB_REG_OFFSET_92S(_offset) \
+ (((_offset) >= 0x800) && ((_offset) <= 0xfff))
#define BRFMOD 0x1
#define BJAPANMODE 0x2
@@ -1715,7 +1693,6 @@
#define BCCK_RF_EXTEND 0x20000000
#define BCCK_RXAGC_SATLEVEL 0x1f000000
#define BCCK_RXAGC_SATCOUNT 0xe0
-#define bCCKRxRFSettle 0x1f
#define BCCK_FIXED_RXAGC 0x8000
#define BCCK_ANTENNA_POLARITY 0x2000
#define BCCK_TXFILTER_TYPE 0x0c00
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
index e68ed7f37c79..713859488744 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
@@ -150,18 +128,18 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- u32 powerBase0, powerBase1;
+ u32 powerbase0, powerbase1;
u8 legacy_pwrdiff, ht20_pwrdiff;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
powerlevel[i] = ppowerlevel[i];
legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
- powerBase0 = powerlevel[i] + legacy_pwrdiff;
+ powerbase0 = powerlevel[i] + legacy_pwrdiff;
- powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
- (powerBase0 << 8) | powerBase0;
- *(ofdmbase + i) = powerBase0;
+ powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
+ (powerbase0 << 8) | powerbase0;
+ *(ofdmbase + i) = powerbase0;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
" [OFDM power base index rf(%c) = 0x%x]\n",
i == 0 ? 'A' : 'B', *(ofdmbase + i));
@@ -172,11 +150,11 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
powerlevel[i] += ht20_pwrdiff;
}
- powerBase1 = powerlevel[i];
- powerBase1 = (powerBase1 << 24) |
- (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+ powerbase1 = powerlevel[i];
+ powerbase1 = (powerbase1 << 24) |
+ (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
- *(mcsbase + i) = powerBase1;
+ *(mcsbase + i) = powerbase1;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
" [MCS power base index rf(%c) = 0x%x]\n",
@@ -186,37 +164,37 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
u8 channel, u8 index,
- u32 *powerBase0,
- u32 *powerBase1,
+ u32 *powerbase0,
+ u32 *powerbase1,
u32 *p_outwriteval)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 i, chnlgroup = 0, pwr_diff_limit[4];
- u32 writeVal, customer_limit, rf;
+ u32 writeval, customer_limit, rf;
for (rf = 0; rf < 2; rf++) {
switch (rtlefuse->eeprom_regulatory) {
case 0:
chnlgroup = 0;
- writeVal = rtlphy->mcs_offset[chnlgroup][index +
+ writeval = rtlphy->mcs_offset[chnlgroup][index +
(rf ? 8 : 0)]
- + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "RTK better performance, writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "RTK better performance, writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
case 1:
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
- writeVal = ((index < 2) ? powerBase0[rf] :
- powerBase1[rf]);
+ writeval = ((index < 2) ? powerbase0[rf] :
+ powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Realtek regulatory, 40MHz, writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
} else {
if (rtlphy->pwrgroup_cnt == 1)
chnlgroup = 0;
@@ -231,23 +209,23 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
chnlgroup++;
}
- writeVal = rtlphy->mcs_offset[chnlgroup]
+ writeval = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)] + ((index < 2) ?
- powerBase0[rf] :
- powerBase1[rf]);
+ powerbase0[rf] :
+ powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
}
break;
case 2:
- writeVal =
- ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ writeval =
+ ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Better regulatory, writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Better regulatory, writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
case 3:
chnlgroup = 0;
@@ -297,36 +275,36 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
"Customer's limit rf(%c) = 0x%x\n",
rf == 0 ? 'A' : 'B', customer_limit);
- writeVal = customer_limit +
- ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ writeval = customer_limit +
+ ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Customer, writeVal rf(%c)= 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Customer, writeval rf(%c)= 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
default:
chnlgroup = 0;
- writeVal = rtlphy->mcs_offset[chnlgroup]
+ writeval = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)]
- + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "RTK better performance, writeVal rf(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "RTK better performance, writeval rf(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
}
if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
- writeVal = writeVal - 0x06060606;
+ writeval = writeval - 0x06060606;
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TXHIGHPWRLEVEL_BT2)
- writeVal = writeVal - 0x0c0c0c0c;
- *(p_outwriteval + rf) = writeVal;
+ writeval = writeval - 0x0c0c0c0c;
+ *(p_outwriteval + rf) = writeval;
}
}
static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
- u8 index, u32 *pValue)
+ u8 index, u32 *value)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
@@ -342,29 +320,29 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
};
u8 i, rf, pwr_val[4];
- u32 writeVal;
+ u32 writeval;
u16 regoffset;
for (rf = 0; rf < 2; rf++) {
- writeVal = pValue[rf];
+ writeval = value[rf];
for (i = 0; i < 4; i++) {
- pwr_val[i] = (u8) ((writeVal & (0x7f <<
+ pwr_val[i] = (u8)((writeval & (0x7f <<
(i * 8))) >> (i * 8));
if (pwr_val[i] > RF6052_MAX_TX_PWR)
pwr_val[i] = RF6052_MAX_TX_PWR;
}
- writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+ writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
(pwr_val[1] << 8) | pwr_val[0];
if (rf == 0)
regoffset = regoffset_a[index];
else
regoffset = regoffset_b[index];
- rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
+ rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Set 0x%x = %08x\n", regoffset, writeVal);
+ "Set 0x%x = %08x\n", regoffset, writeval);
if (((get_rf_type(rtlphy) == RF_2T2R) &&
(regoffset == RTXAGC_A_MCS15_MCS12 ||
@@ -373,7 +351,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
(regoffset == RTXAGC_A_MCS07_MCS04 ||
regoffset == RTXAGC_B_MCS07_MCS04))) {
- writeVal = pwr_val[3];
+ writeval = pwr_val[3];
if (regoffset == RTXAGC_A_MCS15_MCS12 ||
regoffset == RTXAGC_A_MCS07_MCS04)
regoffset = 0xc90;
@@ -382,9 +360,9 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
regoffset = 0xc98;
for (i = 0; i < 3; i++) {
- writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+ writeval = (writeval > 6) ? (writeval - 6) : 0;
rtl_write_byte(rtlpriv, (u32) (regoffset + i),
- (u8) writeVal);
+ (u8)writeval);
}
}
}
@@ -393,20 +371,20 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
u8 *ppowerlevel, u8 channel)
{
- u32 writeVal[2], powerBase0[2], powerBase1[2];
+ u32 writeval[2], powerbase0[2], powerbase1[2];
u8 index;
rtl92c_phy_get_power_base(hw, ppowerlevel,
- channel, &powerBase0[0], &powerBase1[0]);
+ channel, &powerbase0[0], &powerbase1[0]);
for (index = 0; index < 6; index++) {
_rtl92c_get_txpower_writeval_by_regulatory(hw,
channel, index,
- &powerBase0[0],
- &powerBase1[0],
- &writeVal[0]);
+ &powerbase0[0],
+ &powerbase1[0],
+ &writeval[0]);
- _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
+ _rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]);
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
index 22c5e6f51331..6fa70224d2d4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_RF_H__
#define __RTL92C_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index 71a6761d3648..a9c0111444bc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
index 9a1c89cbbda1..f2d121a60159 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_SW_H__
#define __RTL92CE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
index 98b06d48a2dd..58878db404ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
@@ -1,33 +1,8 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "table.h"
-
u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = {
0x024, 0x0011800f,
0x028, 0x00ffdb83,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
index 51e4e07396a6..473af27f80d9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_TABLE__H_
#define __RTL92CE_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index d36e0060cc7a..18a0ab59631a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -58,6 +36,7 @@ static u8 _rtl92c_query_rxpwrpercentage(s8 antpower)
static u8 _rtl92c_evm_db_to_percentage(s8 value)
{
s8 ret_val;
+
ret_val = value;
if (ret_val >= 0)
@@ -131,6 +110,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
if (is_cck_rate) {
u8 report, cck_highpwr;
+
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
if (ppsc->rfpwr_state == ERFON)
@@ -142,6 +122,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
if (!cck_highpwr) {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = cck_buf->cck_agc_rpt & 0xc0;
report = report >> 6;
switch (report) {
@@ -160,6 +141,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
}
} else {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = p_drvinfo->cfosho[0] & 0x60;
report = report >> 5;
switch (report) {
@@ -204,6 +186,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
/* (3) Get Signal Quality (EVM) */
if (packet_match_bssid) {
u8 sq;
+
if (pstats->rx_pwdb_all > 40)
sq = 100;
else {
@@ -340,6 +323,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
struct ieee80211_hdr *hdr;
u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
RX_DRV_INFO_SIZE_UNIT;
@@ -354,7 +338,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc->rxmcs);
@@ -368,7 +352,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
if (stats->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (stats->rx_is40Mhzpacket)
+ if (stats->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (stats->is_ht)
@@ -519,6 +503,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
if (sta) {
u8 ampdu_density = sta->ht_cap.ampdu_density;
+
SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
}
@@ -755,6 +740,7 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
if (hw_queue == BEACON_QUEUE) {
rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
} else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
index 91f0bd6b752f..fb1d4444a52f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_TRX_H__
#define __RTL92CE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
index 316fe9990b6d..91e4427ab022 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../rtl8192ce/def.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
index 00fc0685317a..9d1167ff3b50 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
index ce71433792e3..2befc2f4e3fd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../rtl8192ce/dm.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
index 1e60f70481f5..56cc3bc30860 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -53,9 +31,9 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw)
rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY;
if (IS_HIGHT_PA(rtlefuse->board_type)) {
rtlphy->hwparam_tables[PHY_REG_PG].length =
- RTL8192CUPHY_REG_Array_PG_HPLength;
+ RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH;
rtlphy->hwparam_tables[PHY_REG_PG].pdata =
- RTL8192CUPHY_REG_Array_PG_HP;
+ RTL8192CUPHY_REG_ARRAY_PG_HP;
} else {
rtlphy->hwparam_tables[PHY_REG_PG].length =
RTL8192CUPHY_REG_ARRAY_PGLENGTH;
@@ -82,21 +60,21 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw)
/* 1T */
if (IS_HIGHT_PA(rtlefuse->board_type)) {
rtlphy->hwparam_tables[PHY_REG_1T].length =
- RTL8192CUPHY_REG_1T_HPArrayLength;
+ RTL8192CUPHY_REG_1T_HPARRAYLENGTH;
rtlphy->hwparam_tables[PHY_REG_1T].pdata =
- RTL8192CUPHY_REG_1T_HPArray;
+ RTL8192CUPHY_REG_1T_HPARRAY;
rtlphy->hwparam_tables[RADIOA_1T].length =
- RTL8192CURadioA_1T_HPArrayLength;
+ RTL8192CURADIOA_1T_HPARRAYLENGTH;
rtlphy->hwparam_tables[RADIOA_1T].pdata =
- RTL8192CURadioA_1T_HPArray;
+ RTL8192CURADIOA_1T_HPARRAY;
rtlphy->hwparam_tables[RADIOB_1T].length =
RTL8192CURADIOB_1TARRAYLENGTH;
rtlphy->hwparam_tables[RADIOB_1T].pdata =
RTL8192CU_RADIOB_1TARRAY;
rtlphy->hwparam_tables[AGCTAB_1T].length =
- RTL8192CUAGCTAB_1T_HPArrayLength;
+ RTL8192CUAGCTAB_1T_HPARRAYLENGTH;
rtlphy->hwparam_tables[AGCTAB_1T].pdata =
- Rtl8192CUAGCTAB_1T_HPArray;
+ RTL8192CUAGCTAB_1T_HPARRAY;
} else {
rtlphy->hwparam_tables[PHY_REG_1T].length =
RTL8192CUPHY_REG_1TARRAY_LENGTH;
@@ -323,16 +301,16 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
{
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- u8 boardType;
+ u8 boardtype;
if (IS_NORMAL_CHIP(rtlhal->version)) {
- boardType = ((contents[EEPROM_RF_OPT1]) &
+ boardtype = ((contents[EEPROM_RF_OPT1]) &
BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/
} else {
- boardType = contents[EEPROM_RF_OPT4];
- boardType &= BOARD_TYPE_TEST_MASK;
+ boardtype = contents[EEPROM_RF_OPT4];
+ boardtype &= BOARD_TYPE_TEST_MASK;
}
- rtlefuse->board_type = boardType;
+ rtlefuse->board_type = boardtype;
if (IS_HIGHT_PA(rtlefuse->board_type))
rtlefuse->external_pa = 1;
pr_info("Board Type %x\n", rtlefuse->board_type);
@@ -442,7 +420,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
u16 value16;
u8 value8;
/* polling autoload done. */
- u32 pollingCount = 0;
+ u32 pollingcount = 0;
do {
if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) {
@@ -450,7 +428,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
"Autoload Done!\n");
break;
}
- if (pollingCount++ > 100) {
+ if (pollingcount++ > 100) {
pr_err("Failed to polling REG_APS_FSMCO[PFM_ALDN] done!\n");
return -ENODEV;
}
@@ -474,7 +452,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8);
}
/* auto enable WLAN */
- pollingCount = 0;
+ pollingcount = 0;
value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO);
value16 |= APFM_ONMAC;
rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
@@ -483,7 +461,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
pr_info("MAC auto ON okay!\n");
break;
}
- if (pollingCount++ > 1000) {
+ if (pollingcount++ > 1000) {
pr_err("Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n");
return -ENODEV;
}
@@ -495,12 +473,12 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
value16 &= ~ISO_DIOR;
rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16);
/* Reconsider when to do this operation after asking HWSD. */
- pollingCount = 0;
+ pollingcount = 0;
rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv,
REG_APSD_CTRL) & ~BIT(6)));
do {
- pollingCount++;
- } while ((pollingCount < 200) &&
+ pollingcount++;
+ } while ((pollingcount < 200) &&
(rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7)));
/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
value16 = rtl_read_word(rtlpriv, REG_CR);
@@ -517,60 +495,60 @@ static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- bool isChipN = IS_NORMAL_CHIP(rtlhal->version);
- u32 outEPNum = (u32)out_ep_num;
- u32 numHQ = 0;
- u32 numLQ = 0;
- u32 numNQ = 0;
- u32 numPubQ;
+ bool ischipn = IS_NORMAL_CHIP(rtlhal->version);
+ u32 outepnum = (u32)out_ep_num;
+ u32 numhq = 0;
+ u32 numlq = 0;
+ u32 numnq = 0;
+ u32 numpubq;
u32 value32;
u8 value8;
- u32 txQPageNum, txQPageUnit, txQRemainPage;
+ u32 txqpagenum, txqpageunit, txqremaininpage;
if (!wmm_enable) {
- numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ :
+ numpubq = (ischipn) ? CHIP_B_PAGE_NUM_PUBQ :
CHIP_A_PAGE_NUM_PUBQ;
- txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ;
+ txqpagenum = TX_TOTAL_PAGE_NUMBER - numpubq;
- txQPageUnit = txQPageNum/outEPNum;
- txQRemainPage = txQPageNum % outEPNum;
+ txqpageunit = txqpagenum / outepnum;
+ txqremaininpage = txqpagenum % outepnum;
if (queue_sel & TX_SELE_HQ)
- numHQ = txQPageUnit;
+ numhq = txqpageunit;
if (queue_sel & TX_SELE_LQ)
- numLQ = txQPageUnit;
+ numlq = txqpageunit;
/* HIGH priority queue always present in the configuration of
* 2 out-ep. Remainder pages have assigned to High queue */
- if ((outEPNum > 1) && (txQRemainPage))
- numHQ += txQRemainPage;
+ if (outepnum > 1 && txqremaininpage)
+ numhq += txqremaininpage;
/* NOTE: This step done before writting REG_RQPN. */
- if (isChipN) {
+ if (ischipn) {
if (queue_sel & TX_SELE_NQ)
- numNQ = txQPageUnit;
- value8 = (u8)_NPQ(numNQ);
+ numnq = txqpageunit;
+ value8 = (u8)_NPQ(numnq);
rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
}
} else {
/* for WMM ,number of out-ep must more than or equal to 2! */
- numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ :
+ numpubq = ischipn ? WMM_CHIP_B_PAGE_NUM_PUBQ :
WMM_CHIP_A_PAGE_NUM_PUBQ;
if (queue_sel & TX_SELE_HQ) {
- numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ :
+ numhq = ischipn ? WMM_CHIP_B_PAGE_NUM_HPQ :
WMM_CHIP_A_PAGE_NUM_HPQ;
}
if (queue_sel & TX_SELE_LQ) {
- numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ :
+ numlq = ischipn ? WMM_CHIP_B_PAGE_NUM_LPQ :
WMM_CHIP_A_PAGE_NUM_LPQ;
}
/* NOTE: This step done before writting REG_RQPN. */
- if (isChipN) {
+ if (ischipn) {
if (queue_sel & TX_SELE_NQ)
- numNQ = WMM_CHIP_B_PAGE_NUM_NPQ;
- value8 = (u8)_NPQ(numNQ);
+ numnq = WMM_CHIP_B_PAGE_NUM_NPQ;
+ value8 = (u8)_NPQ(numnq);
rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
}
}
/* TX DMA */
- value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
+ value32 = _HPQ(numhq) | _LPQ(numlq) | _PUBQ(numpubq) | LD_RQPN;
rtl_write_dword(rtlpriv, REG_RQPN, value32);
}
@@ -597,20 +575,20 @@ static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable)
rtl_write_byte(rtlpriv, REG_PBP, value8);
}
-static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ,
- u16 bkQ, u16 viQ, u16 voQ,
- u16 mgtQ, u16 hiQ)
+static void _rtl92c_init_chipn_reg_priority(struct ieee80211_hw *hw, u16 beq,
+ u16 bkq, u16 viq, u16 voq,
+ u16 mgtq, u16 hiq)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7);
- value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
- _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
- _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
+ value16 |= _TXDMA_BEQ_MAP(beq) | _TXDMA_BKQ_MAP(bkq) |
+ _TXDMA_VIQ_MAP(viq) | _TXDMA_VOQ_MAP(voq) |
+ _TXDMA_MGQ_MAP(mgtq) | _TXDMA_HIQ_MAP(hiq);
rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, value16);
}
-static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
+static void _rtl92cu_init_chipn_one_out_ep_priority(struct ieee80211_hw *hw,
bool wmm_enable,
u8 queue_sel)
{
@@ -630,96 +608,96 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
WARN_ON(1); /* Shall not reach here! */
break;
}
- _rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
+ _rtl92c_init_chipn_reg_priority(hw, value, value, value, value,
value, value);
pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
-static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
- bool wmm_enable,
- u8 queue_sel)
+static void _rtl92cu_init_chipn_two_out_ep_priority(struct ieee80211_hw *hw,
+ bool wmm_enable,
+ u8 queue_sel)
{
- u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
- u16 uninitialized_var(valueHi);
- u16 uninitialized_var(valueLow);
+ u16 beq, bkq, viq, voq, mgtq, hiq;
+ u16 uninitialized_var(valuehi);
+ u16 uninitialized_var(valuelow);
switch (queue_sel) {
case (TX_SELE_HQ | TX_SELE_LQ):
- valueHi = QUEUE_HIGH;
- valueLow = QUEUE_LOW;
+ valuehi = QUEUE_HIGH;
+ valuelow = QUEUE_LOW;
break;
case (TX_SELE_NQ | TX_SELE_LQ):
- valueHi = QUEUE_NORMAL;
- valueLow = QUEUE_LOW;
+ valuehi = QUEUE_NORMAL;
+ valuelow = QUEUE_LOW;
break;
case (TX_SELE_HQ | TX_SELE_NQ):
- valueHi = QUEUE_HIGH;
- valueLow = QUEUE_NORMAL;
+ valuehi = QUEUE_HIGH;
+ valuelow = QUEUE_NORMAL;
break;
default:
WARN_ON(1);
break;
}
if (!wmm_enable) {
- beQ = valueLow;
- bkQ = valueLow;
- viQ = valueHi;
- voQ = valueHi;
- mgtQ = valueHi;
- hiQ = valueHi;
+ beq = valuelow;
+ bkq = valuelow;
+ viq = valuehi;
+ voq = valuehi;
+ mgtq = valuehi;
+ hiq = valuehi;
} else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */
- beQ = valueHi;
- bkQ = valueLow;
- viQ = valueLow;
- voQ = valueHi;
- mgtQ = valueHi;
- hiQ = valueHi;
+ beq = valuehi;
+ bkq = valuelow;
+ viq = valuelow;
+ voq = valuehi;
+ mgtq = valuehi;
+ hiq = valuehi;
}
- _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+ _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq);
pr_info("Tx queue select: 0x%02x\n", queue_sel);
}
-static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
+static void _rtl92cu_init_chipn_three_out_ep_priority(struct ieee80211_hw *hw,
bool wmm_enable,
u8 queue_sel)
{
- u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+ u16 beq, bkq, viq, voq, mgtq, hiq;
if (!wmm_enable) { /* typical setting */
- beQ = QUEUE_LOW;
- bkQ = QUEUE_LOW;
- viQ = QUEUE_NORMAL;
- voQ = QUEUE_HIGH;
- mgtQ = QUEUE_HIGH;
- hiQ = QUEUE_HIGH;
+ beq = QUEUE_LOW;
+ bkq = QUEUE_LOW;
+ viq = QUEUE_NORMAL;
+ voq = QUEUE_HIGH;
+ mgtq = QUEUE_HIGH;
+ hiq = QUEUE_HIGH;
} else { /* for WMM */
- beQ = QUEUE_LOW;
- bkQ = QUEUE_NORMAL;
- viQ = QUEUE_NORMAL;
- voQ = QUEUE_HIGH;
- mgtQ = QUEUE_HIGH;
- hiQ = QUEUE_HIGH;
+ beq = QUEUE_LOW;
+ bkq = QUEUE_NORMAL;
+ viq = QUEUE_NORMAL;
+ voq = QUEUE_HIGH;
+ mgtq = QUEUE_HIGH;
+ hiq = QUEUE_HIGH;
}
- _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+ _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq);
pr_info("Tx queue select :0x%02x..\n", queue_sel);
}
-static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw,
+static void _rtl92cu_init_chipn_queue_priority(struct ieee80211_hw *hw,
bool wmm_enable,
u8 out_ep_num,
u8 queue_sel)
{
switch (out_ep_num) {
case 1:
- _rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable,
+ _rtl92cu_init_chipn_one_out_ep_priority(hw, wmm_enable,
queue_sel);
break;
case 2:
- _rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable,
+ _rtl92cu_init_chipn_two_out_ep_priority(hw, wmm_enable,
queue_sel);
break;
case 3:
- _rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable,
+ _rtl92cu_init_chipn_three_out_ep_priority(hw, wmm_enable,
queue_sel);
break;
default:
@@ -728,7 +706,7 @@ static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw,
}
}
-static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw,
+static void _rtl92cu_init_chipt_queue_priority(struct ieee80211_hw *hw,
bool wmm_enable,
u8 out_ep_num,
u8 queue_sel)
@@ -769,11 +747,12 @@ static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw,
u8 queue_sel)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
if (IS_NORMAL_CHIP(rtlhal->version))
- _rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num,
+ _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num,
queue_sel);
else
- _rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num,
+ _rtl92cu_init_chipt_queue_priority(hw, wmm_enable, out_ep_num,
queue_sel);
}
@@ -835,6 +814,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
u8 wmm_enable = false; /* TODO */
u8 out_ep_nums = rtlusb->out_ep_nums;
u8 queue_sel = rtlusb->out_queue_sel;
+
err = _rtl92cu_init_power_on(hw);
if (err) {
@@ -889,10 +869,10 @@ void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw)
"not open sw encryption\n");
return;
}
- sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable;
+ sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE;
if (rtlpriv->sec.use_defaultkey) {
- sec_reg_value |= SCR_TxUseDK;
- sec_reg_value |= SCR_RxUseDK;
+ sec_reg_value |= SCR_TXUSEDK;
+ sec_reg_value |= SCR_RXUSEDK;
}
if (IS_NORMAL_CHIP(rtlhal->version))
sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
@@ -921,7 +901,7 @@ static void _rtl92cu_hw_configure(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val);
}
-static void _InitPABias(struct ieee80211_hw *hw)
+static void _initpabias(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1017,14 +997,14 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
rtl92c_phy_lc_calibrate(hw);
}
_rtl92cu_hw_configure(hw);
- _InitPABias(hw);
+ _initpabias(hw);
rtl92c_dm_init(hw);
exit:
local_irq_restore(flags);
return err;
}
-static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw)
+static void disable_rfafeandresetbb(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
/**************************************
@@ -1034,20 +1014,21 @@ c. APSD_CTRL 0x600[7:0] = 0x40
d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
***************************************/
- u8 eRFPath = 0, value8 = 0;
+ u8 erfpath = 0, value8 = 0;
+
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
- rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0);
+ rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0);
value8 |= APSDOFF;
rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/
value8 = 0;
- value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
+ value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTN);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/
- value8 &= (~FEN_BB_GLB_RSTn);
+ value8 &= (~FEN_BB_GLB_RSTN);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/
}
-static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
+static void _resetdigitalprocedure1(struct ieee80211_hw *hw, bool withouthwsm)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1098,7 +1079,7 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54);
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
}
- if (bWithoutHWSM) {
+ if (withouthwsm) {
/*****************************
Without HW auto state machine
g.SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock
@@ -1113,7 +1094,7 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
}
}
-static void _ResetDigitalProcedure2(struct ieee80211_hw *hw)
+static void _resetdigitalprocedure2(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
/*****************************
@@ -1125,7 +1106,7 @@ m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON
rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82);
}
-static void _DisableGPIO(struct ieee80211_hw *hw)
+static void _disablegpio(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
/***************************************
@@ -1155,13 +1136,13 @@ n. LEDCFG 0x4C[15:0] = 0x8080
rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
}
-static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM)
+static void disable_analog(struct ieee80211_hw *hw, bool withouthwsm)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 value16 = 0;
u8 value8 = 0;
- if (bWithoutHWSM) {
+ if (withouthwsm) {
/*****************************
n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power
o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
@@ -1184,30 +1165,30 @@ i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E);
}
-static void _CardDisableHWSM(struct ieee80211_hw *hw)
+static void carddisable_hwsm(struct ieee80211_hw *hw)
{
/* ==== RF Off Sequence ==== */
- _DisableRFAFEAndResetBB(hw);
+ disable_rfafeandresetbb(hw);
/* ==== Reset digital sequence ====== */
- _ResetDigitalProcedure1(hw, false);
+ _resetdigitalprocedure1(hw, false);
/* ==== Pull GPIO PIN to balance level and LED control ====== */
- _DisableGPIO(hw);
+ _disablegpio(hw);
/* ==== Disable analog sequence === */
- _DisableAnalog(hw, false);
+ disable_analog(hw, false);
}
-static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw)
+static void carddisablewithout_hwsm(struct ieee80211_hw *hw)
{
/*==== RF Off Sequence ==== */
- _DisableRFAFEAndResetBB(hw);
+ disable_rfafeandresetbb(hw);
/* ==== Reset digital sequence ====== */
- _ResetDigitalProcedure1(hw, true);
+ _resetdigitalprocedure1(hw, true);
/* ==== Pull GPIO PIN to balance level and LED control ====== */
- _DisableGPIO(hw);
+ _disablegpio(hw);
/* ==== Reset digital sequence ====== */
- _ResetDigitalProcedure2(hw);
+ _resetdigitalprocedure2(hw);
/* ==== Disable analog sequence === */
- _DisableAnalog(hw, true);
+ disable_analog(hw, true);
}
static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
@@ -1226,6 +1207,7 @@ static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 tmp1byte = 0;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
@@ -1353,10 +1335,10 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
_rtl92cu_set_media_status(hw, opmode);
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
- if (rtlusb->disableHWSM)
- _CardDisableHWSM(hw);
+ if (rtlusb->disablehwsm)
+ carddisable_hwsm(hw);
else
- _CardDisableWithoutHWSM(hw);
+ carddisablewithout_hwsm(hw);
/* after power off we should do iqk again */
rtlpriv->phy.iqk_initialized = false;
@@ -1375,6 +1357,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (check_bssid) {
u8 tmp;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
@@ -1387,6 +1370,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
_rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
} else {
u8 tmp;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
@@ -1498,12 +1482,12 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
break;
case HW_VAR_FWLPS_RF_ON:{
- enum rf_pwrstate rfState;
+ enum rf_pwrstate rfstate;
u32 val_rcr;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
- (u8 *)(&rfState));
- if (rfState == ERFOFF) {
+ (u8 *)(&rfstate));
+ if (rfstate == ERFOFF) {
*((bool *) (val)) = true;
} else {
val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
@@ -1630,7 +1614,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
&e_aci);
} else {
u8 sifstime = 0;
- u8 u1bAIFS;
+ u8 u1baifs;
if (IS_WIRELESS_MODE_A(wirelessmode) ||
IS_WIRELESS_MODE_N_24G(wirelessmode) ||
@@ -1638,21 +1622,22 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
sifstime = 16;
else
sifstime = 10;
- u1bAIFS = sifstime + (2 * val[0]);
+ u1baifs = sifstime + (2 * val[0]);
rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM,
- u1bAIFS);
+ u1baifs);
rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM,
- u1bAIFS);
+ u1baifs);
rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM,
- u1bAIFS);
+ u1baifs);
rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM,
- u1bAIFS);
+ u1baifs);
}
break;
}
case HW_VAR_ACK_PREAMBLE:{
u8 reg_tmp;
u8 short_preamble = (bool)*val;
+
reg_tmp = 0;
if (short_preamble)
reg_tmp |= 0x80;
@@ -1903,6 +1888,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
break;
case HW_VAR_KEEP_ALIVE:{
u8 array[2];
+
array[0] = 0xff;
array[1] = *((u8 *)val);
rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2,
@@ -1985,7 +1971,6 @@ static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
if (nmode && ((curtxbw_40mhz &&
curshortgi_40mhz) || (!curtxbw_40mhz &&
curshortgi_20mhz))) {
-
ratr_value |= 0x10000000;
tmp_ratr_value = (ratr_value >> 12);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
index ebd168400d45..5c48c3fd45e4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_HW_H__
#define __RTL92CU_HW_H__
@@ -36,14 +14,12 @@
#define TX_TOTAL_PAGE_NUMBER 0xF8
#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1)
-
#define CHIP_B_PAGE_NUM_PUBQ 0xE7
/* For Test Chip Setting
* (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
#define CHIP_A_PAGE_NUM_PUBQ 0x7E
-
/* For Chip A Setting */
#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5
#define WMM_CHIP_A_TX_PAGE_BOUNDARY \
@@ -53,8 +29,6 @@
#define WMM_CHIP_A_PAGE_NUM_HPQ 0x29
#define WMM_CHIP_A_PAGE_NUM_LPQ 0x29
-
-
/* Note: For Chip B Setting ,modify later */
#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5
#define WMM_CHIP_B_TX_PAGE_BOUNDARY \
@@ -71,14 +45,14 @@
/* should be renamed and moved to another file */
enum _BOARD_TYPE_8192CUSB {
BOARD_USB_DONGLE = 0, /* USB dongle */
- BOARD_USB_High_PA = 1, /* USB dongle - high power PA */
+ BOARD_USB_HIGH_PA = 1, /* USB dongle - high power PA */
BOARD_MINICARD = 2, /* Minicard */
BOARD_USB_SOLO = 3, /* USB solo-Slim module */
BOARD_USB_COMBO = 4, /* USB Combo-Slim module */
};
#define IS_HIGHT_PA(boardtype) \
- ((boardtype == BOARD_USB_High_PA) ? true : false)
+ ((boardtype == BOARD_USB_HIGH_PA) ? true : false)
#define RTL92C_DRIVER_INFO_SIZE 4
void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
index 66d2784de67d..cc13a4a8f856 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
@@ -1,25 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../usb.h"
@@ -34,7 +14,7 @@ static void _rtl92cu_init_led(struct ieee80211_hw *hw,
pled->ledon = false;
}
-static void _rtl92cu_deInit_led(struct rtl_led *pled)
+static void rtl92cu_deinit_led(struct rtl_led *pled)
{
}
@@ -108,8 +88,8 @@ void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- _rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led0);
- _rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led1);
+ rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led0);
+ rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led1);
}
static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
index 551deb8afb6f..3fc1e7c8f78b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
@@ -1,25 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_LED_H__
#define __RTL92CU_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index 5657b1e34ad0..b3ce8000d52d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
-****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -46,7 +24,6 @@
#define RX_EVM rx_evm_percentage
#define RX_SIGQ rx_mimo_sig_qual
-
void rtl92c_read_chip_version(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -165,6 +142,7 @@ bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
} while (++count);
return status;
}
+
/**
* rtl92c_init_LLT_table - Init LLT table
* @io: io callback
@@ -211,6 +189,7 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
}
return rst;
}
+
void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
u8 *p_macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all)
@@ -392,6 +371,7 @@ void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
}
@@ -669,6 +649,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->RX_SIGQ[1] = -1;
if (is_cck_rate) {
u8 report, cck_highpwr;
+
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
if (!in_powersavemode)
cck_highpwr = rtlphy->cck_high_power;
@@ -676,6 +657,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
cck_highpwr = false;
if (!cck_highpwr) {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = cck_buf->cck_agc_rpt & 0xc0;
report = report >> 6;
switch (report) {
@@ -694,6 +676,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
}
} else {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = p_drvinfo->cfosho[0] & 0x60;
report = report >> 5;
switch (report) {
@@ -716,6 +699,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->recvsignalpower = rx_pwr_all;
if (packet_match_bssid) {
u8 sq;
+
if (pstats->rx_pwdb_all > 40)
sq = 100;
else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
index 8573b7e257d9..dd76a05829d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_MAC_H__
#define __RTL92C_MAC_H__
@@ -40,7 +18,6 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw);
void rtl92c_disable_interrupt(struct ieee80211_hw *hw);
void rtl92c_set_qos(struct ieee80211_hw *hw, int aci);
-
/*---------------------------------------------------------------
* Hardware init functions
*---------------------------------------------------------------*/
@@ -152,6 +129,4 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
* Card disable functions
*---------------------------------------------------------------*/
-
-
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
index f068dd5317a7..9cd028cb2239 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -125,7 +103,7 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
- FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ FEN_BB_GLB_RSTN | FEN_BBRSTB);
regval32 = rtl_read_dword(rtlpriv, 0x87c);
rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31)));
rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
@@ -143,7 +121,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
u32 arraylength;
u32 *ptrarray;
- RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_ARRAY\n");
arraylength = rtlphy->hwparam_tables[MAC_REG].length ;
ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n");
@@ -181,7 +159,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
phy_regarray_table[i + 1]);
udelay(1);
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
- "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
+ "The phy_regarray_table[0] is %x Rtl819XPHY_REGARRAY[1] is %x\n",
phy_regarray_table[i],
phy_regarray_table[i + 1]);
}
@@ -191,7 +169,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
agctab_array_table[i + 1]);
udelay(1);
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
- "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
+ "The agctab_array_table[0] is %x Rtl819XPHY_REGARRAY[1] is %x\n",
agctab_array_table[i],
agctab_array_table[i + 1]);
}
@@ -214,7 +192,7 @@ bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
if (configtype == BASEBAND_CONFIG_PHY_REG) {
for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
rtl_addr_delay(phy_regarray_table_pg[i]);
- _rtl92c_store_pwrIndex_diffrate_offset(hw,
+ _rtl92c_store_pwrindex_diffrate_offset(hw,
phy_regarray_table_pg[i],
phy_regarray_table_pg[i + 1],
phy_regarray_table_pg[i + 2]);
@@ -408,14 +386,14 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
if ((ppsc->rfpwr_state == ERFOFF) &&
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
- u32 InitializeCount = 0;
+ u32 init_count = 0;
do {
- InitializeCount++;
+ init_count++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic enable\n");
rtstatus = rtl_ps_enable_nic(hw);
- } while (!rtstatus && (InitializeCount < 10));
+ } while (!rtstatus && (init_count < 10));
RT_CLEAR_PS_LEVEL(ppsc,
RT_RF_OFF_LEVL_HALT_NIC);
} else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
index a422c4db1a41..a3cc980c42fe 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../rtl8192ce/phy.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
index 8185886daa8e..b4b6cde23341 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h
@@ -1,26 +1,4 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../rtl8192ce/reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
index cf551785eb08..f3a336e0ea98 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
@@ -148,17 +126,17 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- u32 powerBase0, powerBase1;
+ u32 powerbase0, powerbase1;
u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
powerlevel[i] = ppowerlevel[i];
legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
- powerBase0 = powerlevel[i] + legacy_pwrdiff;
- powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
- (powerBase0 << 8) | powerBase0;
- *(ofdmbase + i) = powerBase0;
+ powerbase0 = powerlevel[i] + legacy_pwrdiff;
+ powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
+ (powerbase0 << 8) | powerbase0;
+ *(ofdmbase + i) = powerbase0;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
" [OFDM power base index rf(%c) = 0x%x]\n",
i == 0 ? 'A' : 'B', *(ofdmbase + i));
@@ -168,10 +146,10 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
powerlevel[i] += ht20_pwrdiff;
}
- powerBase1 = powerlevel[i];
- powerBase1 = (powerBase1 << 24) |
- (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
- *(mcsbase + i) = powerBase1;
+ powerbase1 = powerlevel[i];
+ powerbase1 = (powerbase1 << 24) |
+ (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
+ *(mcsbase + i) = powerbase1;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
" [MCS power base index rf(%c) = 0x%x]\n",
i == 0 ? 'A' : 'B', *(mcsbase + i));
@@ -180,26 +158,26 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
u8 channel, u8 index,
- u32 *powerBase0,
- u32 *powerBase1,
+ u32 *powerbase0,
+ u32 *powerbase1,
u32 *p_outwriteval)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 i, chnlgroup = 0, pwr_diff_limit[4];
- u32 writeVal, customer_limit, rf;
+ u32 writeval, customer_limit, rf;
for (rf = 0; rf < 2; rf++) {
switch (rtlefuse->eeprom_regulatory) {
case 0:
chnlgroup = 0;
- writeVal = rtlphy->mcs_offset
+ writeval = rtlphy->mcs_offset
[chnlgroup][index + (rf ? 8 : 0)]
- + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "RTK better performance,writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "RTK better performance,writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
case 1:
if (rtlphy->pwrgroup_cnt == 1)
@@ -217,20 +195,20 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
else
chnlgroup += 4;
}
- writeVal = rtlphy->mcs_offset[chnlgroup][index +
+ writeval = rtlphy->mcs_offset[chnlgroup][index +
(rf ? 8 : 0)] +
- ((index < 2) ? powerBase0[rf] :
- powerBase1[rf]);
+ ((index < 2) ? powerbase0[rf] :
+ powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
case 2:
- writeVal = ((index < 2) ? powerBase0[rf] :
- powerBase1[rf]);
+ writeval = ((index < 2) ? powerbase0[rf] :
+ powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Better regulatory,writeVal(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Better regulatory,writeval(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
case 3:
chnlgroup = 0;
@@ -275,36 +253,36 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Customer's limit rf(%c) = 0x%x\n",
rf == 0 ? 'A' : 'B', customer_limit);
- writeVal = customer_limit + ((index < 2) ?
- powerBase0[rf] : powerBase1[rf]);
+ writeval = customer_limit + ((index < 2) ?
+ powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Customer, writeVal rf(%c)= 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "Customer, writeval rf(%c)= 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
default:
chnlgroup = 0;
- writeVal = rtlphy->mcs_offset[chnlgroup]
+ writeval = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)] + ((index < 2) ?
- powerBase0[rf] : powerBase1[rf]);
+ powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "RTK better performance, writeValrf(%c) = 0x%x\n",
- rf == 0 ? 'A' : 'B', writeVal);
+ "RTK better performance, writevalrf(%c) = 0x%x\n",
+ rf == 0 ? 'A' : 'B', writeval);
break;
}
if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TXHIGHPWRLEVEL_LEVEL1)
- writeVal = 0x14141414;
+ writeval = 0x14141414;
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TXHIGHPWRLEVEL_LEVEL2)
- writeVal = 0x00000000;
+ writeval = 0x00000000;
if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
- writeVal = writeVal - 0x06060606;
- *(p_outwriteval + rf) = writeVal;
+ writeval = writeval - 0x06060606;
+ *(p_outwriteval + rf) = writeval;
}
}
static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
- u8 index, u32 *pValue)
+ u8 index, u32 *value)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
@@ -319,33 +297,33 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
};
u8 i, rf, pwr_val[4];
- u32 writeVal;
+ u32 writeval;
u16 regoffset;
for (rf = 0; rf < 2; rf++) {
- writeVal = pValue[rf];
+ writeval = value[rf];
for (i = 0; i < 4; i++) {
- pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >>
+ pwr_val[i] = (u8)((writeval & (0x7f << (i * 8))) >>
(i * 8));
if (pwr_val[i] > RF6052_MAX_TX_PWR)
pwr_val[i] = RF6052_MAX_TX_PWR;
}
- writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+ writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
(pwr_val[1] << 8) | pwr_val[0];
if (rf == 0)
regoffset = regoffset_a[index];
else
regoffset = regoffset_b[index];
- rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
+ rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
- "Set 0x%x = %08x\n", regoffset, writeVal);
+ "Set 0x%x = %08x\n", regoffset, writeval);
if (((get_rf_type(rtlphy) == RF_2T2R) &&
(regoffset == RTXAGC_A_MCS15_MCS12 ||
regoffset == RTXAGC_B_MCS15_MCS12)) ||
((get_rf_type(rtlphy) != RF_2T2R) &&
(regoffset == RTXAGC_A_MCS07_MCS04 ||
regoffset == RTXAGC_B_MCS07_MCS04))) {
- writeVal = pwr_val[3];
+ writeval = pwr_val[3];
if (regoffset == RTXAGC_A_MCS15_MCS12 ||
regoffset == RTXAGC_A_MCS07_MCS04)
regoffset = 0xc90;
@@ -354,13 +332,13 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
regoffset = 0xc98;
for (i = 0; i < 3; i++) {
if (i != 2)
- writeVal = (writeVal > 8) ?
- (writeVal - 8) : 0;
+ writeval = (writeval > 8) ?
+ (writeval - 8) : 0;
else
- writeVal = (writeVal > 6) ?
- (writeVal - 6) : 0;
+ writeval = (writeval > 6) ?
+ (writeval - 6) : 0;
rtl_write_byte(rtlpriv, (u32)(regoffset + i),
- (u8)writeVal);
+ (u8)writeval);
}
}
}
@@ -369,18 +347,18 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
u8 *ppowerlevel, u8 channel)
{
- u32 writeVal[2], powerBase0[2], powerBase1[2];
+ u32 writeval[2], powerbase0[2], powerbase1[2];
u8 index = 0;
rtl92c_phy_get_power_base(hw, ppowerlevel,
- channel, &powerBase0[0], &powerBase1[0]);
+ channel, &powerbase0[0], &powerbase1[0]);
for (index = 0; index < 6; index++) {
_rtl92c_get_txpower_writeval_by_regulatory(hw,
channel, index,
- &powerBase0[0],
- &powerBase1[0],
- &writeVal[0]);
- _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
+ &powerbase0[0],
+ &powerbase1[0],
+ &writeval[0]);
+ _rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]);
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
index 07aec0b20cc9..2661e5f8f6da 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_RF_H__
#define __RTL92CU_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index 43e021b49260..c1c34dca39d2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
index 4ea2cb225580..662440c4cdc9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_SW_H__
#define __RTL92CU_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
index b3ac981d88c6..addeac90ee0c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "table.h"
@@ -1269,7 +1247,7 @@ u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = {
0xc78, 0x621f001e,
};
-u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = {
+u32 RTL8192CUPHY_REG_1T_HPARRAY[RTL8192CUPHY_REG_1T_HPARRAYLENGTH] = {
0x024, 0x0011800f,
0x028, 0x00ffdb83,
0x040, 0x000c0004,
@@ -1461,7 +1439,7 @@ u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = {
0xf00, 0x00000300,
};
-u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = {
+u32 RTL8192CUPHY_REG_ARRAY_PG_HP[RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH] = {
0xe00, 0xffffffff, 0x06080808,
0xe04, 0xffffffff, 0x00040406,
0xe08, 0x0000ff00, 0x00000000,
@@ -1576,7 +1554,7 @@ u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = {
0x868, 0xffffffff, 0x00000000,
};
-u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = {
+u32 RTL8192CURADIOA_1T_HPARRAY[RTL8192CURADIOA_1T_HPARRAYLENGTH] = {
0x000, 0x00030159,
0x001, 0x00031284,
0x002, 0x00098000,
@@ -1720,7 +1698,7 @@ u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = {
0x000, 0x00030159,
};
-u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = {
+u32 RTL8192CUAGCTAB_1T_HPARRAY[RTL8192CUAGCTAB_1T_HPARRAYLENGTH] = {
0xc78, 0x7b000001,
0xc78, 0x7b010001,
0xc78, 0x7b020001,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
index 851bf53d246c..efc89f7db80f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_TABLE__H_
#define __RTL92CU_TABLE__H_
@@ -53,15 +31,15 @@ extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH];
#define RTL8192CUAGCTAB_1TARRAYLENGTH 320
extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH];
-#define RTL8192CUPHY_REG_1T_HPArrayLength 378
-extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength];
+#define RTL8192CUPHY_REG_1T_HPARRAYLENGTH 378
+extern u32 RTL8192CUPHY_REG_1T_HPARRAY[RTL8192CUPHY_REG_1T_HPARRAYLENGTH];
-#define RTL8192CUPHY_REG_Array_PG_HPLength 336
-extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength];
+#define RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH 336
+extern u32 RTL8192CUPHY_REG_ARRAY_PG_HP[RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH];
-#define RTL8192CURadioA_1T_HPArrayLength 282
-extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength];
-#define RTL8192CUAGCTAB_1T_HPArrayLength 320
-extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength];
+#define RTL8192CURADIOA_1T_HPARRAYLENGTH 282
+extern u32 RTL8192CURADIOA_1T_HPARRAY[RTL8192CURADIOA_1T_HPARRAYLENGTH];
+#define RTL8192CUAGCTAB_1T_HPARRAYLENGTH 320
+extern u32 RTL8192CUAGCTAB_1T_HPARRAY[RTL8192CUAGCTAB_1T_HPARRAYLENGTH];
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 9ab56827124e..0020adc004a5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../usb.h"
@@ -36,7 +14,7 @@
#include "trx.h"
#include "../rtl8192c/fw_common.h"
-static int _ConfigVerTOutEP(struct ieee80211_hw *hw)
+static int configvertoutep(struct ieee80211_hw *hw)
{
u8 ep_cfg, txqsele;
u8 ep_nums = 0;
@@ -69,7 +47,7 @@ static int _ConfigVerTOutEP(struct ieee80211_hw *hw)
return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
}
-static int _ConfigVerNOutEP(struct ieee80211_hw *hw)
+static int configvernoutep(struct ieee80211_hw *hw)
{
u8 ep_cfg;
u8 ep_nums = 0;
@@ -98,7 +76,7 @@ static int _ConfigVerNOutEP(struct ieee80211_hw *hw)
return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
}
-static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB,
+static void twooutepmapping(struct ieee80211_hw *hw, bool is_chip8,
bool bwificfg, struct rtl_ep_map *ep_map)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -126,10 +104,11 @@ static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB,
}
}
-static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg,
+static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg,
struct rtl_ep_map *ep_map)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
if (bwificfg) { /* for WMM */
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"USB 3EP Setting for WMM.....\n");
@@ -153,7 +132,7 @@ static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg,
}
}
-static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
+static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
{
ep_map->ep_mapping[RTL_TXQ_BE] = 2;
ep_map->ep_mapping[RTL_TXQ_BK] = 2;
@@ -163,30 +142,31 @@ static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
ep_map->ep_mapping[RTL_TXQ_HI] = 2;
}
+
static int _out_ep_mapping(struct ieee80211_hw *hw)
{
int err = 0;
- bool bIsChipN, bwificfg = false;
+ bool ischipn, bwificfg = false;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
struct rtl_ep_map *ep_map = &(rtlusb->ep_map);
- bIsChipN = IS_NORMAL_CHIP(rtlhal->version);
+ ischipn = IS_NORMAL_CHIP(rtlhal->version);
switch (rtlusb->out_ep_nums) {
case 2:
- _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map);
+ twooutepmapping(hw, ischipn, bwificfg, ep_map);
break;
case 3:
/* Test chip doesn't support three out EPs. */
- if (!bIsChipN) {
+ if (!ischipn) {
err = -EINVAL;
goto err_out;
}
- _ThreeOutEpMapping(hw, bIsChipN, ep_map);
+ threeoutepmapping(hw, ischipn, ep_map);
break;
case 1:
- _OneOutEpMapping(hw, ep_map);
+ oneoutepmapping(hw, ep_map);
break;
default:
err = -EINVAL;
@@ -196,15 +176,17 @@ err_out:
return err;
}
+
/* endpoint mapping */
int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
int error = 0;
+
if (likely(IS_NORMAL_CHIP(rtlhal->version)))
- error = _ConfigVerNOutEP(hw);
+ error = configvernoutep(hw);
else
- error = _ConfigVerTOutEP(hw);
+ error = configvertoutep(hw);
if (error)
goto err_out;
error = _out_ep_mapping(hw);
@@ -320,7 +302,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1)
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc);
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
@@ -387,7 +369,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1)
&& (GET_RX_DESC_FAGGR(rxdesc) == 1));
stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc);
- stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc);
+ stats.rx_is40mhzpacket = (bool)GET_RX_DESC_BW(rxdesc);
stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc);
/* TODO: is center_freq changed when doing scan? */
/* TODO: Shall we add protection or just skip those two step? */
@@ -464,6 +446,7 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc)
SET_TX_DESC_LAST_SEG(txdesc, 1);
SET_TX_DESC_FIRST_SEG(txdesc, 1);
}
+
/**
* For HW recovery information
*/
@@ -553,11 +536,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
sta = ieee80211_find_sta(mac->vif, mac->bssid);
if (sta) {
u8 ampdu_density = sta->ht_cap.ampdu_density;
+
SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
}
rcu_read_unlock();
if (info->control.hw_key) {
struct ieee80211_key_conf *keyconf = info->control.hw_key;
+
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
@@ -610,28 +595,28 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n");
}
-void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
- u32 buffer_len, bool bIsPsPoll)
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
+ u32 buffer_len, bool is_pspoll)
{
/* Clear all status */
- memset(pDesc, 0, RTL_TX_HEADER_SIZE);
- SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */
- SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */
- SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
- SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */
- SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
+ memset(pdesc, 0, RTL_TX_HEADER_SIZE);
+ SET_TX_DESC_FIRST_SEG(pdesc, 1); /* bFirstSeg; */
+ SET_TX_DESC_LAST_SEG(pdesc, 1); /* bLastSeg; */
+ SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
+ SET_TX_DESC_PKT_SIZE(pdesc, buffer_len); /* Buffer size + command hdr */
+ SET_TX_DESC_QUEUE_SEL(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error
* vlaue by Hw. */
- if (bIsPsPoll) {
- SET_TX_DESC_NAV_USE_HDR(pDesc, 1);
+ if (is_pspoll) {
+ SET_TX_DESC_NAV_USE_HDR(pdesc, 1);
} else {
- SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */
- SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */
+ SET_TX_DESC_HWSEQ_EN(pdesc, 1); /* Hw set sequence number */
+ SET_TX_DESC_PKT_ID(pdesc, 0x100); /* set bit3 to 1. */
}
- SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */
- SET_TX_DESC_OWN(pDesc, 1);
- SET_TX_DESC_TX_RATE(pDesc, DESC_RATE1M);
- _rtl_tx_desc_checksum(pDesc);
+ SET_TX_DESC_USE_RATE(pdesc, 1); /* use data rate which is set by Sw */
+ SET_TX_DESC_OWN(pdesc, 1);
+ SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M);
+ _rtl_tx_desc_checksum(pdesc);
}
void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index 15a66c547287..ae2e8aa212de 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CU_TRX_H__
#define __RTL92CU_TRX_H__
@@ -220,7 +198,6 @@ struct rx_drv_info_92c {
#define SET_TX_DESC_OWN(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value)
-
/* Dword 1 */
#define SET_TX_DESC_MACID(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value)
@@ -377,7 +354,6 @@ struct rx_drv_info_92c {
#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value)
-
int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
@@ -397,8 +373,8 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
struct sk_buff *skb,
u8 queue_index,
struct rtl_tcb_desc *tcb_desc);
-void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
- u32 buffer_len, bool bIsPsPoll);
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
+ u32 buffer_len, bool ispspoll);
void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 *pdesc, bool b_firstseg,
bool b_lastseg, struct sk_buff *skb);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
index cb7b9b727e3a..fa33b05db052 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92D_DEF_H__
#define __RTL92D_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
index ac6d554b67c8..7cc86bb387a1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
@@ -864,7 +842,7 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
else
rf = 1;
if (thermalvalue) {
- ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
MASKDWORD) & MASKOFDM_D;
for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
@@ -872,13 +850,13 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
- ROFDM0_XATxIQIMBALANCE,
+ ROFDM0_XATXIQIMBALANCE,
ele_d, ofdm_index_old[0]);
break;
}
}
if (is2t) {
- ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
MASKDWORD) & MASKOFDM_D;
for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
if (ele_d ==
@@ -887,7 +865,7 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
DBG_LOUD,
"Initial pathB ele_d reg 0x%x = 0x%lx, ofdm_index = 0x%x\n",
- ROFDM0_XBTxIQIMBALANCE, ele_d,
+ ROFDM0_XBTXIQIMBALANCE, ele_d,
ofdm_index_old[1]);
break;
}
@@ -1059,11 +1037,11 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
* regC94, element B is always 0 */
value32 = (ele_d << 22) | ((ele_c & 0x3F) <<
16) | ele_a;
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
MASKDWORD, value32);
value32 = (ele_c & 0x000003C0) >> 6;
- rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS,
+ rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
value32);
value32 = ((val_x * ele_d) >> 7) & 0x01;
@@ -1071,11 +1049,11 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
value32);
} else {
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
MASKDWORD,
ofdmswing_table
[(u8)ofdm_index[0]]);
- rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS,
+ rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
0x00);
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
BIT(24), 0x00);
@@ -1172,21 +1150,21 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
((ele_c & 0x3F) << 16) |
ele_a;
rtl_set_bbreg(hw,
- ROFDM0_XBTxIQIMBALANCE,
+ ROFDM0_XBTXIQIMBALANCE,
MASKDWORD, value32);
value32 = (ele_c & 0x000003C0) >> 6;
- rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
MASKH4BITS, value32);
value32 = ((val_x * ele_d) >> 7) & 0x01;
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
BIT(28), value32);
} else {
rtl_set_bbreg(hw,
- ROFDM0_XBTxIQIMBALANCE,
+ ROFDM0_XBTXIQIMBALANCE,
MASKDWORD,
ofdmswing_table
[(u8) ofdm_index[1]]);
- rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+ rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
MASKH4BITS, 0x00);
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
BIT(28), 0x00);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
index 5d346ec366ce..939cc45bfebd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_DM_H__
#define __RTL92C_DM_H__
@@ -44,7 +22,7 @@
#define DM_DIG_FA_TH1 0x400
#define DM_DIG_FA_TH2 0x600
-#define RXPATHSELECTION_SS_TH_lOW 30
+#define RXPATHSELECTION_SS_TH_LOW 30
#define RXPATHSELECTION_DIFF_TH 18
#define DM_RATR_STA_INIT 0
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
index 75bfa9dfef4a..2064813f9381 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -97,7 +75,7 @@ static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
- (!(value32 & FWDL_ChkSum_rpt)));
+ (!(value32 & FWDL_CHKSUM_RPT)));
if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
value32);
@@ -621,7 +599,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
struct sk_buff *skb = NULL;
u32 totalpacketlen;
bool rtstatus;
- u8 u1RsvdPageLoc[3] = { 0 };
+ u8 u1rsvdpageloc[3] = { 0 };
bool dlok = false;
u8 *beacon;
u8 *p_pspoll;
@@ -640,7 +618,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
- SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
/*--------------------------------------------------------
(3) null data
---------------------------------------------------------*/
@@ -648,7 +626,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
/*---------------------------------------------------------
(4) probe response
----------------------------------------------------------*/
@@ -656,14 +634,14 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
totalpacketlen = TOTAL_RESERVED_PKT_LEN;
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
"rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
&reserved_page_packet[0], totalpacketlen);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
- u1RsvdPageLoc, 3);
+ u1rsvdpageloc, 3);
skb = dev_alloc_skb(totalpacketlen);
if (!skb) {
dlok = false;
@@ -678,9 +656,9 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Set RSVD page location to Fw\n");
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
- "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
+ "H2C_RSVDPAGE", u1rsvdpageloc, 3);
rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
- sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ sizeof(u1rsvdpageloc), u1rsvdpageloc);
} else
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"Set RSVD page location to Fw FAIL!!!!!!\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
index 6b435236a28e..bd8ea6d66dff 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92D__FW__H__
#define __RTL92D__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
index 80123fd97221..c7f29a9be50d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -124,12 +102,12 @@ void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
break;
case HW_VAR_FWLPS_RF_ON:{
- enum rf_pwrstate rfState;
+ enum rf_pwrstate rfstate;
u32 val_rcr;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
- (u8 *) (&rfState));
- if (rfState == ERFOFF) {
+ (u8 *)(&rfstate));
+ if (rfstate == ERFOFF) {
*((bool *) (val)) = true;
} else {
val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
@@ -280,23 +258,23 @@ void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
case HW_VAR_AMPDU_FACTOR: {
u8 factor_toset;
- u32 regtoSet;
+ u32 regtoset;
u8 *ptmp_byte = NULL;
u8 index;
if (rtlhal->macphymode == DUALMAC_DUALPHY)
- regtoSet = 0xb9726641;
+ regtoset = 0xb9726641;
else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
- regtoSet = 0x66626641;
+ regtoset = 0x66626641;
else
- regtoSet = 0xb972a841;
+ regtoset = 0xb972a841;
factor_toset = *val;
if (factor_toset <= 3) {
factor_toset = (1 << (factor_toset + 2));
if (factor_toset > 0xf)
factor_toset = 0xf;
for (index = 0; index < 4; index++) {
- ptmp_byte = (u8 *) (&regtoSet) + index;
+ ptmp_byte = (u8 *)(&regtoset) + index;
if ((*ptmp_byte & 0xf0) >
(factor_toset << 4))
*ptmp_byte = (*ptmp_byte & 0x0f)
@@ -305,7 +283,7 @@ void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
*ptmp_byte = (*ptmp_byte & 0xf0)
| (factor_toset);
}
- rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet);
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoset);
RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
"Set HW_VAR_AMPDU_FACTOR: %#x\n",
factor_toset);
@@ -531,18 +509,18 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned short i;
u8 txpktbuf_bndy;
- u8 maxPage;
+ u8 maxpage;
bool status;
u32 value32; /* High+low page number */
u8 value8; /* normal page number */
if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 246;
value8 = 0;
value32 = 0x80bf0d29;
} else {
- maxPage = 127;
+ maxpage = 127;
txpktbuf_bndy = 123;
value8 = 0;
value32 = 0x80750005;
@@ -598,14 +576,14 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
/* This ring buffer is used as beacon buffer if we */
/* config this MAC as two MAC transfer. */
/* Otherwise used as local loopback buffer. */
- for (i = txpktbuf_bndy; i < maxPage; i++) {
+ for (i = txpktbuf_bndy; i < maxpage; i++) {
status = _rtl92de_llt_write(hw, i, (i + 1));
if (true != status)
return status;
}
/* Let last entry point to the start entry of ring buffer */
- status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy);
+ status = _rtl92de_llt_write(hw, maxpage, txpktbuf_bndy);
if (true != status)
return status;
@@ -1415,13 +1393,13 @@ void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
}
static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo,
- u8 *rom_content, bool autoLoadfail)
+ u8 *rom_content, bool autoloadfail)
{
u32 rfpath, eeaddr, group, offset1, offset2;
u8 i;
memset(pwrinfo, 0, sizeof(struct txpower_info));
- if (autoLoadfail) {
+ if (autoloadfail) {
for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
if (group < CHANNEL_GROUP_MAX_2G) {
@@ -1563,7 +1541,7 @@ static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct txpower_info pwrinfo;
u8 tempval[2], i, pwr, diff;
- u32 ch, rfPath, group;
+ u32 ch, rfpath, group;
_rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail);
if (!autoload_fail) {
@@ -1643,25 +1621,25 @@ static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
"Delta_IQK = 0x%x Delta_LCK = 0x%x\n",
rtlefuse->delta_iqk, rtlefuse->delta_lck);
- for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) {
+ for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
group = rtl92d_get_chnlgroup_fromarray((u8) ch);
if (ch < CHANNEL_MAX_NUMBER_2G)
- rtlefuse->txpwrlevel_cck[rfPath][ch] =
- pwrinfo.cck_index[rfPath][group];
- rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] =
- pwrinfo.ht40_1sindex[rfPath][group];
- rtlefuse->txpwr_ht20diff[rfPath][ch] =
- pwrinfo.ht20indexdiff[rfPath][group];
- rtlefuse->txpwr_legacyhtdiff[rfPath][ch] =
- pwrinfo.ofdmindexdiff[rfPath][group];
- rtlefuse->pwrgroup_ht20[rfPath][ch] =
- pwrinfo.ht20maxoffset[rfPath][group];
- rtlefuse->pwrgroup_ht40[rfPath][ch] =
- pwrinfo.ht40maxoffset[rfPath][group];
- pwr = pwrinfo.ht40_1sindex[rfPath][group];
- diff = pwrinfo.ht40_2sindexdiff[rfPath][group];
- rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] =
+ rtlefuse->txpwrlevel_cck[rfpath][ch] =
+ pwrinfo.cck_index[rfpath][group];
+ rtlefuse->txpwrlevel_ht40_1s[rfpath][ch] =
+ pwrinfo.ht40_1sindex[rfpath][group];
+ rtlefuse->txpwr_ht20diff[rfpath][ch] =
+ pwrinfo.ht20indexdiff[rfpath][group];
+ rtlefuse->txpwr_legacyhtdiff[rfpath][ch] =
+ pwrinfo.ofdmindexdiff[rfpath][group];
+ rtlefuse->pwrgroup_ht20[rfpath][ch] =
+ pwrinfo.ht20maxoffset[rfpath][group];
+ rtlefuse->pwrgroup_ht40[rfpath][ch] =
+ pwrinfo.ht40maxoffset[rfpath][group];
+ pwr = pwrinfo.ht40_1sindex[rfpath][group];
+ diff = pwrinfo.ht40_2sindexdiff[rfpath][group];
+ rtlefuse->txpwrlevel_ht40_2s[rfpath][ch] =
(pwr > diff) ? (pwr - diff) : 0;
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
index e6c702e69ecf..ea495216d394 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92DE_HW_H__
#define __RTL92DE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
index 8851038c9eba..2b76a025deb8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
index 9874519704d3..7599c7e5ecc3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
index de98d88199d6..0ae6371b6318 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -506,16 +484,16 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
/* Tx AFE control 1 */
- rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
/* Tx AFE control 2 */
- rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
- rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE;
- rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE;
- rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
+ rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
/* Tranceiver LSSI Readback SI mode */
rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
@@ -764,7 +742,7 @@ bool rtl92d_phy_bb_config(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB |
RF_SDMRSTB);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
- FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+ FEN_DIO_PCIE | FEN_BB_GLB_RSTN | FEN_BBRSTB);
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) {
regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
@@ -1480,11 +1458,11 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
u8 result = 0;
u8 i;
u8 retrycount = 2;
- u32 TxOKBit = BIT(28), RxOKBit = BIT(27);
+ u32 TXOKBIT = BIT(28), RXOKBIT = BIT(27);
if (rtlhal->interfaceindex == 1) { /* PHY1 */
- TxOKBit = BIT(31);
- RxOKBit = BIT(30);
+ TXOKBIT = BIT(31);
+ RXOKBIT = BIT(30);
}
RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n");
/* path-A IQK setting */
@@ -1526,7 +1504,7 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c);
regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4);
- if (!(regeac & TxOKBit) &&
+ if (!(regeac & TXOKBIT) &&
(((rege94 & 0x03FF0000) >> 16) != 0x142)) {
result |= 0x01;
} else { /* if Tx not OK, ignore Rx */
@@ -1536,7 +1514,7 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
}
/* if Tx is OK, check whether Rx is OK */
- if (!(regeac & RxOKBit) &&
+ if (!(regeac & RXOKBIT) &&
(((regea4 & 0x03FF0000) >> 16) != 0x132)) {
result |= 0x02;
break;
@@ -2165,7 +2143,7 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
if (final_candidate == 0xFF) {
return;
} else if (iqk_ok) {
- oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
MASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */
val_x = result[final_candidate][0];
if ((val_x & 0x00000200) != 0)
@@ -2174,7 +2152,7 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
RTPRINT(rtlpriv, FINIT, INIT_IQK,
"X = 0x%x, tx0_a = 0x%x, oldval_0 0x%x\n",
val_x, tx0_a, oldval_0);
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a);
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
((val_x * oldval_0 >> 7) & 0x1));
val_y = result[final_candidate][1];
@@ -2188,15 +2166,15 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
RTPRINT(rtlpriv, FINIT, INIT_IQK,
"Y = 0x%lx, tx0_c = 0x%lx\n",
val_y, tx0_c);
- rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000,
+ rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
((tx0_c & 0x3C0) >> 6));
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
(tx0_c & 0x3F));
if (is2t)
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26),
((val_y * oldval_0 >> 7) & 0x1));
RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xC80 = 0x%x\n",
- rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+ rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
MASKDWORD));
if (txonly) {
RTPRINT(rtlpriv, FINIT, INIT_IQK, "only Tx OK\n");
@@ -2224,7 +2202,7 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
if (final_candidate == 0xFF) {
return;
} else if (iqk_ok) {
- oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+ oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
MASKDWORD) >> 22) & 0x3FF;
val_x = result[final_candidate][4];
if ((val_x & 0x00000200) != 0)
@@ -2232,7 +2210,7 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
tx1_a = (val_x * oldval_1) >> 8;
RTPRINT(rtlpriv, FINIT, INIT_IQK, "X = 0x%x, tx1_a = 0x%x\n",
val_x, tx1_a);
- rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a);
+ rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28),
((val_x * oldval_1 >> 7) & 0x1));
val_y = result[final_candidate][5];
@@ -2243,9 +2221,9 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
tx1_c = (val_y * oldval_1) >> 8;
RTPRINT(rtlpriv, FINIT, INIT_IQK, "Y = 0x%lx, tx1_c = 0x%lx\n",
val_y, tx1_c);
- rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000,
+ rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
((tx1_c & 0x3C0) >> 6));
- rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000,
+ rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
(tx1_c & 0x3F));
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30),
((val_y * oldval_1 >> 7) & 0x1));
@@ -3086,13 +3064,13 @@ bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
if ((ppsc->rfpwr_state == ERFOFF) &&
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
- u32 InitializeCount = 0;
+ u32 initializecount = 0;
do {
- InitializeCount++;
+ initializecount++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic enable\n");
rtstatus = rtl_ps_enable_nic(hw);
- } while (!rtstatus && (InitializeCount < 10));
+ } while (!rtstatus && (initializecount < 10));
RT_CLEAR_PS_LEVEL(ppsc,
RT_RF_OFF_LEVL_HALT_NIC);
@@ -3387,9 +3365,9 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
/* 5G LAN ON */
rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa);
/* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
0x40000100);
- rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD,
0x40000100);
if (rtlhal->macphymode == DUALMAC_DUALPHY) {
rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
@@ -3443,16 +3421,16 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0);
/* TX BB gain shift,Just for testchip,0xc80,0xc88 */
if (rtlefuse->internal_pa_5g[0])
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
0x2d4000b5);
else
- rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
0x20000080);
if (rtlefuse->internal_pa_5g[1])
- rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD,
0x2d4000b5);
else
- rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD,
+ rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD,
0x20000080);
if (rtlhal->macphymode == DUALMAC_DUALPHY) {
rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
@@ -3481,10 +3459,10 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
/* update IQK related settings */
rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, MASKDWORD, 0x40000100);
rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, MASKDWORD, 0x40000100);
- rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, 0x00);
rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) |
BIT(26) | BIT(24), 0x00);
- rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00);
+ rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, 0x00);
rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00);
rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
index 58b56b523dbe..8d07c783a023 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92D_PHY_H__
#define __RTL92D_PHY_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
index d4c4e76a9244..2783d7e7b227 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92D_REG_H__
#define __RTL92D_REG_H__
@@ -752,7 +730,7 @@
/* SYS_FUNC_EN */
#define FEN_BBRSTB BIT(0)
-#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_BB_GLB_RSTN BIT(1)
#define FEN_USBA BIT(2)
#define FEN_UPLL BIT(3)
#define FEN_USBD BIT(4)
@@ -773,7 +751,7 @@
#define PFM_ALDN BIT(1)
#define PFM_LDKP BIT(2)
#define PFM_WOWL BIT(3)
-#define EnPDN BIT(4)
+#define ENPDN BIT(4)
#define PDN_PL BIT(5)
#define APFM_ONMAC BIT(8)
#define APFM_OFF BIT(9)
@@ -910,7 +888,7 @@
/* MCUFWDL */
#define MCUFWDL_EN BIT(0)
#define MCUFWDL_RDY BIT(1)
-#define FWDL_ChkSum_rpt BIT(2)
+#define FWDL_CHKSUM_RPT BIT(2)
#define MACINI_RDY BIT(3)
#define BBINI_RDY BIT(4)
#define RFINI_RDY BIT(5)
@@ -1033,7 +1011,7 @@
#define RFPGA0_XA_LSSIPARAMETER 0x840
#define RFPGA0_XB_LSSIPARAMETER 0x844
-#define RFPGA0_RFWAkEUPPARAMETER 0x850
+#define RFPGA0_RFWAKEUPPARAMETER 0x850
#define RFPGA0_RFSLEEPUPPARAMETER 0x854
#define RFPGA0_XAB_SWITCHCONTROL 0x858
@@ -1135,14 +1113,14 @@
#define ROFDM0_AGCRSSITABLE 0xc78
#define ROFDM0_HTSTFAGC 0xc7c
-#define ROFDM0_XATxIQIMBALANCE 0xc80
-#define ROFDM0_XATxAFE 0xc84
-#define ROFDM0_XBTxIQIMBALANCE 0xc88
-#define ROFDM0_XBTxAFE 0xc8c
-#define ROFDM0_XCTxIQIMBALANCE 0xc90
-#define ROFDM0_XCTxAFE 0xc94
-#define ROFDM0_XDTxIQIMBALANCE 0xc98
-#define ROFDM0_XDTxAFE 0xc9c
+#define ROFDM0_XATXIQIMBALANCE 0xc80
+#define ROFDM0_XATXAFE 0xc84
+#define ROFDM0_XBTXIQIMBALANCE 0xc88
+#define ROFDM0_XBTXAFE 0xc8c
+#define ROFDM0_XCTXIQIMBALANCE 0xc90
+#define ROFDM0_XCTXAFE 0xc94
+#define ROFDM0_XDTXIQIMBALANCE 0xc98
+#define ROFDM0_XDTXAFE 0xc9c
#define ROFDM0_RXHPPARAMETER 0xce0
#define ROFDM0_TXPSEUDONOISEWGT 0xce4
@@ -1186,7 +1164,7 @@
#define ROFDM_AGCREPORT 0xdd0
#define ROFDM_RXSNR 0xdd4
#define ROFDM_RXEVMCSI 0xdd8
-#define ROFDM_SIGReport 0xddc
+#define ROFDM_SIGREPORT 0xddc
/* 8. PageE(0xE00) */
#define RTXAGC_A_RATE18_06 0xe00
@@ -1228,7 +1206,7 @@
#define RF_IPA 0x15
#define RF_POW_ABILITY 0x17
#define RF_MODE_AG 0x18
-#define rRfChannel 0x18
+#define rfchannel 0x18
#define RF_CHNLBW 0x18
#define RF_TOP 0x19
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
index 021d3c538ac2..915a36f7af5e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
index c650a8dcdb26..4e646cc9ebc0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92D_RF_H__
#define __RTL92D_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index d5ba2bace79b..99e5cd9a5c86 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
index fd7d036e9abc..19db4ce30e44 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92DE_SW_H__
#define __RTL92DE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
index 4badb183cf35..9b35c65d91f2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c
@@ -1,28 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- * Created on 2010/12/23, 6:38
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include <linux/types.h>
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
index 7fefc483ec28..2a45082f441f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h
@@ -1,28 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- * Created on 2010/ 5/18, 1:41
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92DE_TABLE__H_
#define __RTL92DE_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index d7b023cf7400..d162884a9e00 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -494,7 +472,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
index f7f776539438..36820070fd76 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92DE_TRX_H__
#define __RTL92DE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h
index 9f7e7bb8610b..fe1b7cdab1d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_DEF_H__
#define __RTL92E_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c
index faed6e2dedf6..648f9108ed4b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h
index 107d5a488fa8..ec48e5671b5b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_DM_H__
#define __RTL92E_DM_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
index 84a0d0eb72e1..7c5b54b71a92 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
index 6a2fbf20d579..cbfecea232a3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E__FW__H__
#define __RTL92E__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 3f2295fdb02d..53011c2a44f5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h
index 3a63bec9b0cc..fc224392615f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_HW_H__
#define __RTL92E_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
index 96c64785108b..78202ad4036e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
index 8ef640a2ef7f..6d775e14846f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_LED_H__
#define __RTL92E_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
index 8b072ee8e0d5..222abc41669c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h
index 49bd0e554c65..1a5dbc628379 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_PHY_H__
#define __RTL92E_PHY_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c
index 1a701d007f0c..515c1c3d6b43 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "pwrseq.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h
index c570801508cc..2ae8347f7ebb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_PWRSEQ_H__
#define __RTL92E_PWRSEQ_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h
index 1eaa1fab550d..0164e006f43e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_REG_H__
#define __RTL92E_REG_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c
index bc76a91da762..6b8ef680dc57 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h
index 039c0133ad6b..d7b391599926 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_RF_H__
#define __RTL92E_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index 9ea62599ecbb..b6ee7dae5943 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h
index 21433d0332d0..36e29a2da0fd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_SW_H__
#define __RTL92E_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c
index abcdd0670fd8..fb66f610bf5d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "table.h"
u32 RTL8192EE_PHY_REG_ARRAY[] = {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h
index bff9df88815d..0bc7ef58c3b9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_TABLE__H_
#define __RTL92E_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
index 14d6e3fc5767..09cf8180e4ff 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -393,7 +371,7 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw,
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (status->rx_is40Mhzpacket)
+ if (status->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (status->is_ht)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
index 45df3e79f490..a9e5e620a653 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL92E_TRX_H__
#define __RTL92E_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
index b5ba0554a0cd..bb6b60814762 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_92S_DEF_H__
#define __REALTEK_92S_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
index 44f510a94b09..a6e4384ceea1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
index 3af07efed73a..b9c5a92c2bd0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __RTL_92S_DM_H__
#define __RTL_92S_DM_H__
@@ -79,7 +58,7 @@ enum dm_ratr_sta {
#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
#define DM_DIG_HIGH_PWR_THRESH_LOW 70
-#define DM_DIG_MIN_Netcore 0x12
+#define DM_DIG_MIN_NETCORE 0x12
void rtl92s_dm_watchdog(struct ieee80211_hw *hw);
void rtl92s_dm_init(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
index e7b1d7c0f542..541b7881735e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -158,7 +136,6 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct sk_buff *skb;
struct rtl_tcb_desc *tcb_desc;
- unsigned char *seg_ptr;
u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
u16 frag_length, frag_offset = 0;
u16 extra_descoffset = 0;
@@ -188,9 +165,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
if (!skb)
return false;
skb_reserve(skb, extra_descoffset);
- seg_ptr = skb_put_data(skb,
- code_virtual_address + frag_offset,
- (u32)(frag_length - extra_descoffset));
+ skb_put_data(skb, code_virtual_address + frag_offset,
+ (u32)(frag_length - extra_descoffset));
tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
tcb_desc->queue_index = TXCMD_QUEUE;
@@ -569,14 +545,14 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
return true;
}
-void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode)
+void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct h2c_set_pwrmode_parm pwrmode;
u16 max_wakeup_period = 0;
- pwrmode.mode = Mode;
+ pwrmode.mode = mode;
pwrmode.flag_low_traffic_en = 0;
pwrmode.flag_lpnav_en = 0;
pwrmode.flag_rf_low_snr_en = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
index 5827aa32cef0..99c6f7eefd85 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_FIRMWARE92S_H__
#define __REALTEK_FIRMWARE92S_H__
@@ -297,7 +276,7 @@ enum fw_h2c_cmd {
H2C_JOINBSS_CMD,
H2C_DISCONNECT_CMD, /*15*/
H2C_CREATEBSS_CMD,
- H2C_SETOPMode_CMD,
+ H2C_SETOPMODE_CMD,
H2C_SITESURVEY_CMD,
H2C_SETAUTH_CMD,
H2C_SETKEY_CMD, /*20*/
@@ -336,10 +315,10 @@ enum fw_h2c_cmd {
/* The following macros are used for FW
* CMD map and parameter updated. */
-#define FW_CMD_IO_CLR(rtlpriv, _Bit) \
+#define FW_CMD_IO_CLR(rtlpriv, _bit) \
do { \
udelay(1000); \
- rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \
+ rtlpriv->rtlhal.fwcmd_iomap &= (~_bit); \
} while (0)
#define FW_CMD_IO_UPDATE(rtlpriv, _val) \
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
index 30dea7b9bc17..6d6e8994460d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -258,7 +236,7 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&(
mac->ac[0].aifs));
u8 acm = p_aci_aifsn->f.acm;
- u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl);
+ u8 acm_ctrl = rtl_read_byte(rtlpriv, ACMHWCTRL);
acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ?
0x0 : 0x1);
@@ -266,13 +244,13 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
if (acm) {
switch (e_aci) {
case AC0_BE:
- acm_ctrl |= AcmHw_BeqEn;
+ acm_ctrl |= ACMHW_BEQEN;
break;
case AC2_VI:
- acm_ctrl |= AcmHw_ViqEn;
+ acm_ctrl |= ACMHW_VIQEN;
break;
case AC3_VO:
- acm_ctrl |= AcmHw_VoqEn;
+ acm_ctrl |= ACMHW_VOQEN;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -283,13 +261,13 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
} else {
switch (e_aci) {
case AC0_BE:
- acm_ctrl &= (~AcmHw_BeqEn);
+ acm_ctrl &= (~ACMHW_BEQEN);
break;
case AC2_VI:
- acm_ctrl &= (~AcmHw_ViqEn);
+ acm_ctrl &= (~ACMHW_VIQEN);
break;
case AC3_VO:
- acm_ctrl &= (~AcmHw_VoqEn);
+ acm_ctrl &= (~ACMHW_VOQEN);
break;
default:
pr_err("switch case %#x not processed\n",
@@ -300,7 +278,7 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
"HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl);
- rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl);
+ rtl_write_byte(rtlpriv, ACMHWCTRL, acm_ctrl);
break;
}
case HW_VAR_RCR:{
@@ -869,7 +847,7 @@ static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw)
/* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */
/* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */
/* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */
- /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */
+ /* 13. Test mode and Debug Control Register (Offset: 0x0310 - 0x034F) */
/* 14. Set driver info, we only accept PHY status now. */
rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4);
@@ -1641,7 +1619,7 @@ void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw,
rtl92se_enable_interrupt(hw);
}
-static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw)
+static void _rtl8192se_get_ic_inferiority(struct ieee80211_hw *hw)
{
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1704,7 +1682,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
if (rtlefuse->autoload_failflag)
return;
- _rtl8192se_get_IC_Inferiority(hw);
+ _rtl8192se_get_ic_inferiority(hw);
/* Read IC Version && Channel Plan */
/* VID, DID SE 0xA-D */
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
index fa836ceefc8f..5edbc1ecd261 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_PCI92SE_HW_H__
#define __REALTEK_PCI92SE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
index 33c307aca911..2d18bc1ee480 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
index 90e265d9ffc6..c9e481a8d943 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_PCI92SE_LED_H__
#define __REALTEK_PCI92SE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
index 86cb853f7169..d5c0eb462315 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -549,13 +527,13 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
- u32 InitializeCount = 0;
+ u32 initializecount = 0;
do {
- InitializeCount++;
+ initializecount++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic enable\n");
rtstatus = rtl_ps_enable_nic(hw);
- } while (!rtstatus && (InitializeCount < 10));
+ } while (!rtstatus && (initializecount < 10));
RT_CLEAR_PS_LEVEL(ppsc,
RT_RF_OFF_LEVL_HALT_NIC);
@@ -935,7 +913,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
if (!rtstatus) {
pr_err("Write BB Reg Fail!!\n");
- goto phy_BB8190_Config_ParaFile_Fail;
+ goto phy_bb8190_config_parafile_fail;
}
/* 2. If EEPROM or EFUSE autoload OK, We must config by
@@ -948,7 +926,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
}
if (!rtstatus) {
pr_err("_rtl92s_phy_bb_config_parafile(): BB_PG Reg Fail!!\n");
- goto phy_BB8190_Config_ParaFile_Fail;
+ goto phy_bb8190_config_parafile_fail;
}
/* 3. BB AGC table Initialization */
@@ -956,7 +934,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
if (!rtstatus) {
pr_err("%s(): AGC Table Fail\n", __func__);
- goto phy_BB8190_Config_ParaFile_Fail;
+ goto phy_bb8190_config_parafile_fail;
}
/* Check if the CCK HighPower is turned ON. */
@@ -964,7 +942,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw,
RFPGA0_XA_HSSIPARAMETER2, 0x200));
-phy_BB8190_Config_ParaFile_Fail:
+phy_bb8190_config_parafile_fail:
return rtstatus;
}
@@ -1029,13 +1007,13 @@ bool rtl92s_phy_mac_config(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 i;
u32 arraylength;
- u32 *ptraArray;
+ u32 *ptrarray;
arraylength = MAC_2T_ARRAYLENGTH;
- ptraArray = rtl8192semac_2t_array;
+ ptrarray = rtl8192semac_2t_array;
for (i = 0; i < arraylength; i = i + 2)
- rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]);
+ rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]);
return true;
}
@@ -1128,7 +1106,7 @@ void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
}
static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
- u8 *cckpowerlevel, u8 *ofdmpowerLevel)
+ u8 *cckpowerlevel, u8 *ofdmpowerlevel)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
@@ -1144,15 +1122,15 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
/* 2. OFDM for 1T or 2T */
if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) {
/* Read HT 40 OFDM TX power */
- ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index];
- ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index];
+ ofdmpowerlevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index];
+ ofdmpowerlevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index];
} else if (rtlphy->rf_type == RF_2T2R) {
/* Read HT 40 OFDM TX power */
- ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index];
- ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index];
+ ofdmpowerlevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index];
+ ofdmpowerlevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index];
} else {
- ofdmpowerLevel[0] = 0;
- ofdmpowerLevel[1] = 0;
+ ofdmpowerlevel[0] = 0;
+ ofdmpowerlevel[1] = 0;
}
}
@@ -1171,7 +1149,7 @@ void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
/* [0]:RF-A, [1]:RF-B */
- u8 cckpowerlevel[2], ofdmpowerLevel[2];
+ u8 cckpowerlevel[2], ofdmpowerlevel[2];
if (!rtlefuse->txpwr_fromeprom)
return;
@@ -1183,18 +1161,18 @@ void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel)
* 1. For CCK.
* 2. For OFDM 1T or 2T */
_rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0],
- &ofdmpowerLevel[0]);
+ &ofdmpowerlevel[0]);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n",
channel, cckpowerlevel[0], cckpowerlevel[1],
- ofdmpowerLevel[0], ofdmpowerLevel[1]);
+ ofdmpowerlevel[0], ofdmpowerlevel[1]);
_rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0],
- &ofdmpowerLevel[0]);
+ &ofdmpowerlevel[0]);
rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]);
- rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel);
+ rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerlevel[0], channel);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
index 7a3b6b623872..b8b5f097b67b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __RTL92S_PHY_H__
#define __RTL92S_PHY_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
index 5d445c2afcf3..45f968e0e57c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_92S_REG_H__
#define __REALTEK_92S_REG_H__
@@ -190,7 +169,7 @@
#define BCNTCFG 0x01E0
#define CWRR 0x01E2
#define ACMAVG 0x01E4
-#define AcmHwCtrl 0x01E7
+#define ACMHWCTRL 0x01E7
#define VO_ADMTM 0x01E8
#define VI_ADMTM 0x01EC
#define BE_ADMTM 0x01F0
@@ -256,7 +235,7 @@
#define INTA_MASK 0x0300
#define ISR 0x0308
-/* 13. Test Mode and Debug Control Registers */
+/* 13. Test mode and Debug Control Registers */
#define DBG_PORT_SWITCH 0x003A
#define BIST 0x0310
#define DBS 0x0314
@@ -346,9 +325,9 @@
#define SYS_SWHW_SEL BIT(14)
#define SYS_FWHW_SEL BIT(15)
-#define CmdEEPROM_En BIT(5)
-#define CmdEERPOMSEL BIT(4)
-#define Cmd9346CR_9356SEL BIT(4)
+#define CMDEEPROM_EN BIT(5)
+#define CMDEERPOMSEL BIT(4)
+#define CMD9346CR_9356SEL BIT(4)
#define AFE_MBEN BIT(1)
#define AFE_BGEN BIT(0)
@@ -369,9 +348,9 @@
#define APLL_EN BIT(0)
-#define AFR_CardBEn BIT(0)
+#define AFR_CARDBEN BIT(0)
#define AFR_CLKRUN_SEL BIT(1)
-#define AFR_FuncRegEn BIT(2)
+#define AFR_FUNCREGEN BIT(2)
#define APSDOFF_STATUS BIT(15)
#define APSDOFF BIT(14)
@@ -387,13 +366,13 @@
#define HCI_RXDMA_EN BIT(3)
#define HCI_TXDMA_EN BIT(2)
-#define StopHCCA BIT(6)
-#define StopHigh BIT(5)
-#define StopMgt BIT(4)
-#define StopVO BIT(3)
-#define StopVI BIT(2)
-#define StopBE BIT(1)
-#define StopBK BIT(0)
+#define STOPHCCA BIT(6)
+#define STOPHIGH BIT(5)
+#define STOPMGT BIT(4)
+#define STOPVO BIT(3)
+#define STOPVI BIT(2)
+#define STOPBE BIT(1)
+#define STOPBK BIT(0)
#define LBK_NORMAL 0x00
#define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3))
@@ -405,7 +384,7 @@
#define TXDMAPRE2FULL BIT(23)
#define DISCW BIT(20)
#define TCRICV BIT(19)
-#define CfendForm BIT(17)
+#define cfendform BIT(17)
#define TCRCRC BIT(16)
#define FAKE_IMEM_EN BIT(15)
#define TSFRST BIT(9)
@@ -530,7 +509,7 @@
#define RRSR_MCS5 BIT(17)
#define RRSR_MCS6 BIT(18)
#define RRSR_MCS7 BIT(19)
-#define BRSR_AckShortPmb BIT(23)
+#define BRSR_ACKSHORTPMB BIT(23)
#define RATR_1M 0x00000001
#define RATR_2M 0x00000002
@@ -581,13 +560,13 @@
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
-#define AcmHw_HwEn BIT(0)
-#define AcmHw_BeqEn BIT(1)
-#define AcmHw_ViqEn BIT(2)
-#define AcmHw_VoqEn BIT(3)
-#define AcmHw_BeqStatus BIT(4)
-#define AcmHw_ViqStatus BIT(5)
-#define AcmHw_VoqStatus BIT(6)
+#define ACMHW_HWEN BIT(0)
+#define ACMHW_BEQEN BIT(1)
+#define ACMHW_VIQEN BIT(2)
+#define ACMHW_VOQEN BIT(3)
+#define ACMHW_BEQSTATUS BIT(4)
+#define ACMHW_VIQSTATUS BIT(5)
+#define ACMHW_VOQSTATUS BIT(6)
#define RETRY_LIMIT_SHORT_SHIFT 8
#define RETRY_LIMIT_LONG_SHIFT 0
@@ -845,7 +824,7 @@
#define TCR_SAT BIT(24)
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
-#define RCR_OnlyErlPkt BIT(31)
+#define RCR_ONLYERLPKT BIT(31)
#define CWR 0xDC
#define RETRYCTR 0xDE
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
index ea5b8ec45ec9..a37855f57e76 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
index e9ba283d05ad..a5959a228a35 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __INC_RTL92S_RF_H
#define __INC_RTL92S_RF_H
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index d55554b7fa9a..d1d84e7d47a4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
index af449d6714e6..a31efba0e6b5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h
@@ -1,25 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_PCI92SE_SW_H__
#define __REALTEK_PCI92SE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
index 162578f05c85..776e28e99d53 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c
@@ -1,28 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- * Created on 2010/ 5/18, 1:41
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "table.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
index aa3c7687d226..4fd09f11f5bc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h
@@ -1,20 +1,6 @@
-/******************************************************************************
- * Copyright(c) 2008 - 2012 Realtek Corporation. All rights reserved.
- *
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __INC_HAL8192SE_FW_IMG_H
#define __INC_HAL8192SE_FW_IMG_H
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
index e1904c39f147..efb432c6d785 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -275,7 +253,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1)
&& (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
- stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
+ stats->rx_is40mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc);
stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc);
@@ -288,7 +266,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
if (stats->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (stats->rx_is40Mhzpacket)
+ if (stats->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (stats->is_ht)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
index 81a5445c04a3..90aa12fc6a7f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#ifndef __REALTEK_PCI92SE_TRX_H__
#define __REALTEK_PCI92SE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h
index 06c448c010fd..20a67dcc59cb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- **
- ** Copyright(c) 2009-2012 Realtek Corporation.
- **
- ** 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
- ** 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.
- **
- ** The full GNU General Public License is included in this distribution in the
- ** file called LICENSE.
- **
- ** Contact Information:
- ** wlanfae <wlanfae@realtek.com>
- ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- ** Hsinchu 300, Taiwan.
- ** Larry Finger <Larry.Finger@lwfinger.net>
- **
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_BTC_H__
#define __RTL8723E_BTC_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h
index 847544817549..42958df6b5d4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_DEF_H__
#define __RTL8723E_DEF_H__
@@ -116,7 +94,7 @@
#define IS_VENDOR_8723A_B_CUT(version) ((IS_8723_SERIES(version))\
? ((GET_CVID_CUT_VERSION(version) == \
B_CUT_VERSION) ? true : false) : false)
-#define IS_81xxC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\
+#define IS_81XXC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\
? ((GET_CVID_CUT_VERSION(version) == \
B_CUT_VERSION) ? true : false) : false)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
index 42a6fba90ba9..514891ea2c64 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
@@ -151,8 +129,14 @@ static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
long rssi_val_min = 0;
+ if (mac->link_state == MAC80211_LINKED &&
+ mac->opmode == NL80211_IFTYPE_STATION &&
+ rtlpriv->link_info.bcn_rx_inperiod == 0)
+ return 0;
+
if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
(dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
@@ -417,6 +401,8 @@ static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
} else {
rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
+ dm_digtable->pre_cck_fa_state = 0;
+ dm_digtable->cur_cck_fa_state = 0;
}
dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
@@ -665,7 +651,7 @@ void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rate_adaptive *p_ra = &(rtlpriv->ra);
+ struct rate_adaptive *p_ra = &rtlpriv->ra;
p_ra->ratr_state = DM_RATR_STA_INIT;
p_ra->pre_ratr_state = DM_RATR_STA_INIT;
@@ -677,6 +663,89 @@ void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
}
+void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rate_adaptive *p_ra = &rtlpriv->ra;
+ u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
+ struct ieee80211_sta *sta = NULL;
+
+ if (is_hal_stop(rtlhal)) {
+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+ " driver is going to unload\n");
+ return;
+ }
+
+ if (!rtlpriv->dm.useramask) {
+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+ " driver does not control rate adaptive mask\n");
+ return;
+ }
+
+ if (mac->link_state == MAC80211_LINKED &&
+ mac->opmode == NL80211_IFTYPE_STATION) {
+ switch (p_ra->pre_ratr_state) {
+ case DM_RATR_STA_HIGH:
+ high_rssithresh_for_ra = 50;
+ low_rssithresh_for_ra = 20;
+ break;
+ case DM_RATR_STA_MIDDLE:
+ high_rssithresh_for_ra = 55;
+ low_rssithresh_for_ra = 20;
+ break;
+ case DM_RATR_STA_LOW:
+ high_rssithresh_for_ra = 60;
+ low_rssithresh_for_ra = 25;
+ break;
+ default:
+ high_rssithresh_for_ra = 50;
+ low_rssithresh_for_ra = 20;
+ break;
+ }
+
+ if (rtlpriv->link_info.bcn_rx_inperiod == 0)
+ switch (p_ra->pre_ratr_state) {
+ case DM_RATR_STA_HIGH:
+ default:
+ p_ra->ratr_state = DM_RATR_STA_MIDDLE;
+ break;
+ case DM_RATR_STA_MIDDLE:
+ case DM_RATR_STA_LOW:
+ p_ra->ratr_state = DM_RATR_STA_LOW;
+ break;
+ }
+ else if (rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra)
+ p_ra->ratr_state = DM_RATR_STA_HIGH;
+ else if (rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra)
+ p_ra->ratr_state = DM_RATR_STA_MIDDLE;
+ else
+ p_ra->ratr_state = DM_RATR_STA_LOW;
+
+ if (p_ra->pre_ratr_state != p_ra->ratr_state) {
+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+ "RSSI = %ld\n",
+ rtlpriv->dm.undec_sm_pwdb);
+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+ "RSSI_LEVEL = %d\n", p_ra->ratr_state);
+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+ "PreState = %d, CurState = %d\n",
+ p_ra->pre_ratr_state, p_ra->ratr_state);
+
+ rcu_read_lock();
+ sta = rtl_find_sta(hw, mac->bssid);
+ if (sta)
+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
+ p_ra->ratr_state,
+ true);
+ rcu_read_unlock();
+
+ p_ra->pre_ratr_state = p_ra->ratr_state;
+ }
+ }
+}
+
void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -826,7 +895,7 @@ void rtl8723e_dm_watchdog(struct ieee80211_hw *hw)
rtl8723e_dm_dynamic_bb_powersaving(hw);
rtl8723e_dm_dynamic_txpower(hw);
rtl8723e_dm_check_txpower_tracking(hw);
- /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
+ rtl8723e_dm_refresh_rate_adaptive_mask(hw);
rtl8723e_dm_bt_coexist(hw);
rtl8723e_dm_check_edca_turbo(hw);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
index a113780af08a..bcad516f0d28 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_DM_H__
#define __RTL8723E_DM_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
index bf9859f74b6f..be451a6f7dbe 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
index 2e668fcfc5c2..5c843736de8d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C__FW__H__
#define __RTL92C__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
index 5aac45d5a974..3ac31ec26517 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "hal_bt_coexist.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
index 45719fdcb067..0455a3712f3e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_HAL_BT_COEXIST_H__
#define __RTL8723E_HAL_BT_COEXIST_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c
index 788de88ab1ee..680198280f8f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#include "hal_btc.h"
#include "../pci.h"
#include "phy.h"
@@ -1426,7 +1405,6 @@ static void rtl8723e_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw)
static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- u8 bt_retry_cnt;
u8 bt_info_original;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
"[BTCoex] Get bt info by fw!!\n");
@@ -1438,7 +1416,6 @@ static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
"[BTCoex] c2h for bt_info not rcvd yet!!\n");
}
- bt_retry_cnt = hal_coex_8723.bt_retry_cnt;
bt_info_original = hal_coex_8723.c2h_bt_info_original;
/* when bt inquiry or page scan, we have to set h2c 0x25 */
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h
index 756868897d8b..620677128f11 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_HAL_BTC_H__
#define __RTL8723E_HAL_BTC_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index f783e4a8083d..6bab162e1bb8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -698,7 +676,7 @@ static bool _rtl8712e_init_mac(struct ieee80211_hw *hw)
/* HW Power on sequence */
if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
- PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW))
+ PWR_INTF_PCI_MSK, RTL8723_NIC_ENABLE_FLOW))
return false;
bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2);
@@ -988,7 +966,7 @@ int rtl8723e_hw_init(struct ieee80211_hw *hw)
if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) {
rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
- } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) {
rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
@@ -1284,7 +1262,7 @@ static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw)
/* Combo (PCIe + USB) Card and PCIe-MF Card */
/* 1. Run LPS WL RFOFF flow */
rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
- PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW);
+ PWR_INTF_PCI_MSK, RTL8723_NIC_LPS_ENTER_FLOW);
/* 2. 0x1F[7:0] = 0 */
/* turn off RF */
@@ -1304,7 +1282,7 @@ static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw)
/* HW card disable configuration. */
rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
- PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW);
+ PWR_INTF_PCI_MSK, RTL8723_NIC_DISABLE_FLOW);
/* Reset MCU IO Wrapper */
u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h
index c76e453f4f43..cf55f45d0779 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_HW_H__
#define __RTL8723E_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
index d567b0df0e9f..5e503dbc463b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
index c22b19f542a6..9f85845d23cd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
index 3f3327878b51..54a3aec1dfa7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -905,7 +883,7 @@ static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
struct rtl_phy *rtlphy = &rtlpriv->phy;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) {
if (channel == 6 && rtlphy->current_chan_bw ==
HT_CHANNEL_WIDTH_20)
rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h
index b85f5c7c5c01..98bfe02f66d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL92C_PHY_H__
#define __RTL92C_PHY_H__
@@ -48,7 +26,7 @@
#define MAX_STALL_TIME 50
#define ANTENNADIVERSITYVALUE 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
-#define Reset_Cnt_Limit 3
+#define reset_cnt_limit 3
#define IQK_ADDA_REG_NUM 16
#define IQK_MAC_REG_NUM 4
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c
index 2f7f81af8a55..041e3113a500 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../pwrseqcmd.h"
#include "pwrseq.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h
index e6c3aac3e9fd..d9247a8f3039 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_PWRSEQ_H__
#define __RTL8723E_PWRSEQ_H__
@@ -327,14 +305,14 @@ extern struct wlan_pwr_cfg rtl8723A_leave_lps_flow
[RTL8723A_TRANS_LPS_TO_ACT_STEPS + RTL8723A_TRANS_END_STEPS];
/* RTL8723 Power Configuration CMDs for PCIe interface */
-#define Rtl8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow
-#define Rtl8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow
-#define Rtl8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow
-#define Rtl8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow
-#define Rtl8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow
-#define Rtl8723_NIC_RESUME_FLOW rtl8723A_resume_flow
-#define Rtl8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow
-#define Rtl8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow
-#define Rtl8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow
+#define RTL8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow
+#define RTL8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow
+#define RTL8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow
+#define RTL8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow
+#define RTL8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow
+#define RTL8723_NIC_RESUME_FLOW rtl8723A_resume_flow
+#define RTL8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow
+#define RTL8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow
+#define RTL8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
index 30938cd9fce5..8696614c7cdd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_REG_H__
#define __RTL8723E_REG_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c
index 89958b64b52d..9058527a7f94 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h
index 7b44ebc0fac9..b445cfe65bf4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_RF_H__
#define __RTL8723E_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 07b82700d1de..4b370410c83c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
@@ -175,7 +153,7 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
return 1;
}
- if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+ if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
fw_name = "rtlwifi/rtl8723fw_B.bin";
rtlpriv->max_fw_size = 0x6000;
@@ -266,8 +244,8 @@ static struct rtl_hal_ops rtl8723e_hal_ops = {
static struct rtl_mod_params rtl8723e_mod_params = {
.sw_crypto = false,
.inactiveps = true,
- .swctrl_lps = false,
- .fwctrl_lps = true,
+ .swctrl_lps = true,
+ .fwctrl_lps = false,
.aspm_support = 1,
.debug_level = 0,
.debug_mask = 0,
@@ -395,8 +373,8 @@ module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog,
bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
-MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
MODULE_PARM_DESC(aspm, "Set to 1 to enable ASPM (default 1)\n");
MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h
index 46478780d262..200ce39a0dd7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_SW_H__
#define __RTL8723E_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c
index 1bbee0bfac23..d895694be023 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "table.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h
index a044f3c456fa..4897dbc73b9f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_TABLE__H_
#define __RTL8723E_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
index d461d0c9631f..90dc91b0d35b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -302,7 +280,7 @@ bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw,
status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) &&
(GET_RX_DESC_FAGGR(pdesc) == 1));
status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
+ status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
status->is_cck = RX_HAL_IS_CCK_RATE(status->rate);
@@ -316,7 +294,7 @@ bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw,
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (status->rx_is40Mhzpacket)
+ if (status->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (status->is_ht)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
index d592b08d4ac8..4a19ea76b290 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL8723E_TRX_H__
#define __RTL8723E_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h
index 5e5403d69220..f4886c868df8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_DEF_H__
#define __RTL8723BE_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
index 47e87a21ae27..b13fd3c0c832 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
@@ -1017,12 +995,9 @@ static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
u32 edca_be = 0x5ea42b;
u32 iot_peer = 0;
bool b_is_cur_rdlstate;
- bool b_last_is_cur_rdlstate = false;
bool b_bias_on_rx = false;
bool b_edca_turbo_on = false;
- b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate;
-
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h
index f752a2cad63d..c4f36e951747 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h
@@ -1,24 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_DM_H__
#define __RTL8723BE_DM_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
index f2441fbb92f1..4d7fa27f55ca 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
index 948d28646364..97ea77464139 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE__FW__H__
#define __RTL8723BE__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index b4f3f91b590e..979e5bfe5f45 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -319,12 +297,12 @@ void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
break;
case HW_VAR_FWLPS_RF_ON:{
- enum rf_pwrstate rfState;
+ enum rf_pwrstate rfstate;
u32 val_rcr;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
- (u8 *)(&rfState));
- if (rfState == ERFOFF) {
+ (u8 *)(&rfstate));
+ if (rfstate == ERFOFF) {
*((bool *)(val)) = true;
} else {
val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
@@ -764,10 +742,10 @@ static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned short i;
u8 txpktbuf_bndy;
- u8 maxPage;
+ u8 maxpage;
bool status;
- maxPage = 255;
+ maxpage = 255;
txpktbuf_bndy = 245;
rtl_write_dword(rtlpriv, REG_TRXFF_BNDY,
@@ -792,13 +770,13 @@ static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw)
if (!status)
return status;
- for (i = txpktbuf_bndy; i < maxPage; i++) {
+ for (i = txpktbuf_bndy; i < maxpage; i++) {
status = _rtl8723be_llt_write(hw, i, (i + 1));
if (!status)
return status;
}
- status = _rtl8723be_llt_write(hw, maxPage, txpktbuf_bndy);
+ status = _rtl8723be_llt_write(hw, maxpage, txpktbuf_bndy);
if (!status)
return status;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h
index ae856a19e81a..eb797e9bb931 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_HW_H__
#define __RTL8723BE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
index 4f7890d62c21..525f2c47da5b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
index c57de379ee8d..8ac59374b632 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_LED_H__
#define __RTL8723BE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
index 1263b12db5dc..aa8a0950fcea 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -332,7 +310,7 @@ static void _rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw,
"Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- };
+ }
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d in PHY_SetTxPowerByRateBase()\n",
@@ -374,7 +352,7 @@ static u8 _rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw,
"Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- };
+ }
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d in PHY_GetTxPowerByRateBase()\n",
@@ -694,7 +672,7 @@ static u8 _rtl8723be_get_rate_section_index(u32 regaddr)
else if (regaddr >= 0xE20 && regaddr <= 0xE4C)
index = (u8)((regaddr - 0xE20) / 4);
break;
- };
+ }
return index;
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h
index 9021d4745ab7..a59813ea7c72 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_PHY_H__
#define __RTL8723BE_PHY_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c
index a1bb1f6116fb..95adac66676e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../pwrseqcmd.h"
#include "pwrseq.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h
index 3367cfbc9502..57eac4864184 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_PWRSEQ_H__
#define __RTL8723BE_PWRSEQ_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
index 95c4f8e206c7..28fd22b2a792 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_REG_H__
#define __RTL8723BE_REG_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c
index 48491454b878..af72e489e31c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h
index f423e157020f..81537a1a4fdf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_RF_H__
#define __RTL8723BE_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index c9f7b042d9c6..00e6254bf82b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h
index a7b25e769950..6ecacf9fbfd7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_SW_H__
#define __RTL8723BE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c
index 160fee8333ae..5864be89d187 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include <linux/kernel.h>
#include "table.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h
index 1deaffe22251..cf0c8d58cea1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_TABLE__H_
#define __RTL8723BE_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
index 9f8dfb5af774..9ada9a06c6ea 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -338,7 +316,7 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw,
status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1);
status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
- status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
+ status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
status->bandwidth = (u8)GET_RX_DESC_BW(pdesc);
status->macid = GET_RX_DESC_MACID(pdesc);
status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
@@ -372,7 +350,7 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw,
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (status->rx_is40Mhzpacket)
+ if (status->rx_is40mhzpacket)
rx_status->bw = RATE_INFO_BW_40;
if (status->is_ht)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
index 609f7ad7f787..11e75a4e68bd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __RTL8723BE_TRX_H__
#define __RTL8723BE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c
index 064340641913..46ab90332eb7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "dm_common.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h
index 5c1b94ce2f86..6300be65aba0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __DM_COMMON_H__
#define __DM_COMMON_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
index 521039c5d4ce..18ce2856a91b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h
index 77c25a976233..b527fcbbdf08 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __FW_COMMON_H__
#define __FW_COMMON_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c
index 9014a94fac6a..f5a9ecbf7363 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include <linux/module.h>
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
index 43d24e1ee5e6..aae14c68bf69 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#include "../wifi.h"
#include "phy_common.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h
index 83b891a9adb8..edf1c52f0ee2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2014 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2014 Realtek Corporation.*/
#ifndef __PHY_COMMON__
#define __PHY_COMMON__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h
index 3fe3aaa5fe3c..827bc5f35d2a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_DEF_H__
#define __RTL8821AE_DEF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
index 3be8c88971e2..49d05b631ba1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../base.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h
index 625a6bbb21fc..137ed735d80d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_DM_H__
#define __RTL8821AE_DM_H__
@@ -92,11 +70,11 @@
#define DM_REG_CCK_CCA_CNT_11N 0xA60
#define DM_REG_BB_PWR_SAV4_11N 0xA74
/*PAGE B */
-#define DM_REG_LNA_SWITCH_11N 0xB2C
-#define DM_REG_PATH_SWITCH_11N 0xB30
-#define DM_REG_RSSI_CTRL_11N 0xB38
-#define DM_REG_CONFIG_ANTA_11N 0xB68
-#define DM_REG_RSSI_BT_11N 0xB9C
+#define DM_REG_LNA_SWITCH_11N 0XB2C
+#define DM_REG_PATH_SWITCH_11N 0XB30
+#define DM_REG_RSSI_CTRL_11N 0XB38
+#define DM_REG_CONFIG_ANTA_11N 0XB68
+#define DM_REG_RSSI_BT_11N 0XB9C
/*PAGE C */
#define DM_REG_OFDM_FA_HOLDC_11N 0xC00
#define DM_REG_RX_PATH_11N 0xC04
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
index d868a034659f..dc0eb692088f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -844,9 +822,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 3: qos null data */
- 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -877,9 +855,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 4: BT qos null data */
- 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -911,9 +889,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = {
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 5~7 is for wowlan */
/* page 5: ARP resp */
- 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06,
0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02,
0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00,
@@ -1015,7 +993,7 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
/* page 0: beacon */
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x60, 0x00,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x00, 0x20, 0x04, 0x00, 0x03, 0x32, 0x31,
0x35, 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C,
@@ -1078,8 +1056,8 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 1: ps-poll */
- 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1143,9 +1121,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 2: null data */
- 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1208,9 +1186,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 3: Qos null data */
- 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1273,9 +1251,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 4: BT Qos null data */
- 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1339,9 +1317,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = {
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 5~7 is for wowlan */
/* page 5: ARP resp */
- 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
- 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
- 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
+ 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7,
+ 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
+ 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00,
0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06,
0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02,
0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00,
@@ -1543,8 +1521,8 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
u32 totalpacketlen;
bool rtstatus;
- u8 u1RsvdPageLoc[5] = { 0 };
- u8 u1RsvdPageLoc2[7] = { 0 };
+ u8 u1rsvdpageloc[5] = { 0 };
+ u8 u1rsvdpageloc2[7] = { 0 };
bool b_dlok = false;
u8 *beacon;
u8 *p_pspoll;
@@ -1574,7 +1552,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
- SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
/*--------------------------------------------------------
* (3) null data
@@ -1585,7 +1563,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
/*---------------------------------------------------------
* (4) Qos null data
@@ -1596,7 +1574,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOSNULL_PG);
/*---------------------------------------------------------
* (5) BT Qos null data
@@ -1607,7 +1585,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1RsvdPageLoc, BT_QOSNULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOSNULL_PG);
if (!dl_whole_packets) {
totalpacketlen = 512 * (BT_QOSNULL_PG + 1) - 40;
@@ -1622,20 +1600,20 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr);
SET_80211_HDR_ADDRESS3(arpresp, mac->bssid);
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG);
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1rsvdpageloc2, ARPRESP_PG);
/*---------------------------------------------------------
* (7) Remote Wake Ctrl
*----------------------------------------------------------
*/
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2,
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1rsvdpageloc2,
REMOTE_PG);
/*---------------------------------------------------------
* (8) GTK Ext Memory
*----------------------------------------------------------
*/
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG);
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1rsvdpageloc2, GTKEXT_PG);
totalpacketlen = TOTAL_RESERVED_PKT_LEN_8812 - 40;
@@ -1654,14 +1632,14 @@ out:
if (!b_dl_finished && b_dlok) {
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
- "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5);
+ "H2C_RSVDPAGE:\n", u1rsvdpageloc, 5);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE,
- sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ sizeof(u1rsvdpageloc), u1rsvdpageloc);
if (dl_whole_packets) {
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
- "wowlan H2C_RSVDPAGE:\n", u1RsvdPageLoc2, 7);
+ "wowlan H2C_RSVDPAGE:\n", u1rsvdpageloc2, 7);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE,
- sizeof(u1RsvdPageLoc2), u1RsvdPageLoc2);
+ sizeof(u1rsvdpageloc2), u1rsvdpageloc2);
}
}
@@ -1678,8 +1656,8 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
u32 totalpacketlen;
bool rtstatus;
- u8 u1RsvdPageLoc[5] = { 0 };
- u8 u1RsvdPageLoc2[7] = { 0 };
+ u8 u1rsvdpageloc[5] = { 0 };
+ u8 u1rsvdpageloc2[7] = { 0 };
bool b_dlok = false;
u8 *beacon;
u8 *p_pspoll;
@@ -1709,7 +1687,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
- SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
/*--------------------------------------------------------
* (3) null data
@@ -1720,7 +1698,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
/*---------------------------------------------------------
* (4) Qos null data
@@ -1731,7 +1709,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOSNULL_PG);
/*---------------------------------------------------------
* (5) Qos null data
@@ -1742,7 +1720,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
- SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1RsvdPageLoc, BT_QOSNULL_PG);
+ SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOSNULL_PG);
if (!dl_whole_packets) {
totalpacketlen = 256 * (BT_QOSNULL_PG + 1) - 40;
@@ -1757,20 +1735,20 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr);
SET_80211_HDR_ADDRESS3(arpresp, mac->bssid);
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG);
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1rsvdpageloc2, ARPRESP_PG);
/*---------------------------------------------------------
* (7) Remote Wake Ctrl
*----------------------------------------------------------
*/
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2,
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1rsvdpageloc2,
REMOTE_PG);
/*---------------------------------------------------------
* (8) GTK Ext Memory
*----------------------------------------------------------
*/
- SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG);
+ SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1rsvdpageloc2, GTKEXT_PG);
totalpacketlen = TOTAL_RESERVED_PKT_LEN_8821 - 40;
@@ -1792,16 +1770,16 @@ out:
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Set RSVD page location to Fw.\n");
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
- "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5);
+ "H2C_RSVDPAGE:\n", u1rsvdpageloc, 5);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE,
- sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ sizeof(u1rsvdpageloc), u1rsvdpageloc);
if (dl_whole_packets) {
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"wowlan H2C_RSVDPAGE:\n",
- u1RsvdPageLoc2, 7);
+ u1rsvdpageloc2, 7);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE,
- sizeof(u1RsvdPageLoc2),
- u1RsvdPageLoc2);
+ sizeof(u1rsvdpageloc2),
+ u1rsvdpageloc2);
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
index 99c902ff0b84..e11e496b7277 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
@@ -1,26 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE__FW__H__
#define __RTL8821AE__FW__H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index ba258318ee9f..198d419ebb9c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
@@ -2606,50 +2584,50 @@ static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw,
u8 *hwinfo)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- u32 rfPath, eeAddr = EEPROM_TX_PWR_INX, group, TxCount = 0;
+ u32 rfpath, eeaddr = EEPROM_TX_PWR_INX, group, txcount = 0;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"hal_ReadPowerValueFromPROM8821ae(): hwinfo[0x%x]=0x%x\n",
- (eeAddr+1), hwinfo[eeAddr+1]);
- if (0xFF == hwinfo[eeAddr+1]) /*YJ,add,120316*/
+ (eeaddr + 1), hwinfo[eeaddr + 1]);
+ if (hwinfo[eeaddr + 1] == 0xFF) /*YJ,add,120316*/
autoload_fail = true;
if (autoload_fail) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"auto load fail : Use Default value!\n");
- for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
+ for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) {
/*2.4G default value*/
for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) {
- pwrinfo24g->index_cck_base[rfPath][group] = 0x2D;
- pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D;
+ pwrinfo24g->index_cck_base[rfpath][group] = 0x2D;
+ pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D;
}
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrinfo24g->bw20_diff[rfPath][0] = 0x02;
- pwrinfo24g->ofdm_diff[rfPath][0] = 0x04;
+ for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) {
+ if (txcount == 0) {
+ pwrinfo24g->bw20_diff[rfpath][0] = 0x02;
+ pwrinfo24g->ofdm_diff[rfpath][0] = 0x04;
} else {
- pwrinfo24g->bw20_diff[rfPath][TxCount] = 0xFE;
- pwrinfo24g->bw40_diff[rfPath][TxCount] = 0xFE;
- pwrinfo24g->cck_diff[rfPath][TxCount] = 0xFE;
- pwrinfo24g->ofdm_diff[rfPath][TxCount] = 0xFE;
+ pwrinfo24g->bw20_diff[rfpath][txcount] = 0xFE;
+ pwrinfo24g->bw40_diff[rfpath][txcount] = 0xFE;
+ pwrinfo24g->cck_diff[rfpath][txcount] = 0xFE;
+ pwrinfo24g->ofdm_diff[rfpath][txcount] = 0xFE;
}
}
/*5G default value*/
for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++)
- pwrinfo5g->index_bw40_base[rfPath][group] = 0x2A;
-
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrinfo5g->ofdm_diff[rfPath][0] = 0x04;
- pwrinfo5g->bw20_diff[rfPath][0] = 0x00;
- pwrinfo5g->bw80_diff[rfPath][0] = 0xFE;
- pwrinfo5g->bw160_diff[rfPath][0] = 0xFE;
+ pwrinfo5g->index_bw40_base[rfpath][group] = 0x2A;
+
+ for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) {
+ if (txcount == 0) {
+ pwrinfo5g->ofdm_diff[rfpath][0] = 0x04;
+ pwrinfo5g->bw20_diff[rfpath][0] = 0x00;
+ pwrinfo5g->bw80_diff[rfpath][0] = 0xFE;
+ pwrinfo5g->bw160_diff[rfpath][0] = 0xFE;
} else {
- pwrinfo5g->ofdm_diff[rfPath][0] = 0xFE;
- pwrinfo5g->bw20_diff[rfPath][0] = 0xFE;
- pwrinfo5g->bw40_diff[rfPath][0] = 0xFE;
- pwrinfo5g->bw80_diff[rfPath][0] = 0xFE;
- pwrinfo5g->bw160_diff[rfPath][0] = 0xFE;
+ pwrinfo5g->ofdm_diff[rfpath][0] = 0xFE;
+ pwrinfo5g->bw20_diff[rfpath][0] = 0xFE;
+ pwrinfo5g->bw40_diff[rfpath][0] = 0xFE;
+ pwrinfo5g->bw80_diff[rfpath][0] = 0xFE;
+ pwrinfo5g->bw160_diff[rfpath][0] = 0xFE;
}
}
}
@@ -2658,112 +2636,112 @@ static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw,
rtl_priv(hw)->efuse.txpwr_fromeprom = true;
- for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
+ for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) {
/*2.4G default value*/
for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) {
- pwrinfo24g->index_cck_base[rfPath][group] = hwinfo[eeAddr++];
- if (pwrinfo24g->index_cck_base[rfPath][group] == 0xFF)
- pwrinfo24g->index_cck_base[rfPath][group] = 0x2D;
+ pwrinfo24g->index_cck_base[rfpath][group] = hwinfo[eeaddr++];
+ if (pwrinfo24g->index_cck_base[rfpath][group] == 0xFF)
+ pwrinfo24g->index_cck_base[rfpath][group] = 0x2D;
}
for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) {
- pwrinfo24g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++];
- if (pwrinfo24g->index_bw40_base[rfPath][group] == 0xFF)
- pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D;
+ pwrinfo24g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++];
+ if (pwrinfo24g->index_bw40_base[rfpath][group] == 0xFF)
+ pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D;
}
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrinfo24g->bw40_diff[rfPath][TxCount] = 0;
+ for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) {
+ if (txcount == 0) {
+ pwrinfo24g->bw40_diff[rfpath][txcount] = 0;
/*bit sign number to 8 bit sign number*/
- pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4;
- if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0;
/*bit sign number to 8 bit sign number*/
- pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0;
- pwrinfo24g->cck_diff[rfPath][TxCount] = 0;
- eeAddr++;
+ pwrinfo24g->cck_diff[rfpath][txcount] = 0;
+ eeaddr++;
} else {
- pwrinfo24g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr]&0xf0) >> 4;
- if (pwrinfo24g->bw40_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->bw40_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ if (pwrinfo24g->bw40_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->bw40_diff[rfpath][txcount] |= 0xF0;
- pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0;
- eeAddr++;
+ eeaddr++;
- pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4;
- if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0;
- pwrinfo24g->cck_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo24g->cck_diff[rfPath][TxCount] & BIT(3))
- pwrinfo24g->cck_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo24g->cck_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo24g->cck_diff[rfpath][txcount] & BIT(3))
+ pwrinfo24g->cck_diff[rfpath][txcount] |= 0xF0;
- eeAddr++;
+ eeaddr++;
}
}
/*5G default value*/
for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) {
- pwrinfo5g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++];
- if (pwrinfo5g->index_bw40_base[rfPath][group] == 0xFF)
- pwrinfo5g->index_bw40_base[rfPath][group] = 0xFE;
+ pwrinfo5g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++];
+ if (pwrinfo5g->index_bw40_base[rfpath][group] == 0xFF)
+ pwrinfo5g->index_bw40_base[rfpath][group] = 0xFE;
}
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrinfo5g->bw40_diff[rfPath][TxCount] = 0;
+ for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) {
+ if (txcount == 0) {
+ pwrinfo5g->bw40_diff[rfpath][txcount] = 0;
- pwrinfo5g->bw20_diff[rfPath][0] = (hwinfo[eeAddr] & 0xf0) >> 4;
- if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo5g->bw20_diff[rfpath][0] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0;
- pwrinfo5g->ofdm_diff[rfPath][0] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo5g->ofdm_diff[rfpath][0] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0;
- eeAddr++;
+ eeaddr++;
} else {
- pwrinfo5g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4;
- if (pwrinfo5g->bw40_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->bw40_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo5g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ if (pwrinfo5g->bw40_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->bw40_diff[rfpath][txcount] |= 0xF0;
- pwrinfo5g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo5g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0;
- eeAddr++;
+ eeaddr++;
}
}
- pwrinfo5g->ofdm_diff[rfPath][1] = (hwinfo[eeAddr] & 0xf0) >> 4;
- pwrinfo5g->ofdm_diff[rfPath][2] = (hwinfo[eeAddr] & 0x0f);
+ pwrinfo5g->ofdm_diff[rfpath][1] = (hwinfo[eeaddr] & 0xf0) >> 4;
+ pwrinfo5g->ofdm_diff[rfpath][2] = (hwinfo[eeaddr] & 0x0f);
- eeAddr++;
+ eeaddr++;
- pwrinfo5g->ofdm_diff[rfPath][3] = (hwinfo[eeAddr] & 0x0f);
+ pwrinfo5g->ofdm_diff[rfpath][3] = (hwinfo[eeaddr] & 0x0f);
- eeAddr++;
+ eeaddr++;
- for (TxCount = 1; TxCount < MAX_TX_COUNT; TxCount++) {
- if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0;
+ for (txcount = 1; txcount < MAX_TX_COUNT; txcount++) {
+ if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0;
}
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- pwrinfo5g->bw80_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4;
+ for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) {
+ pwrinfo5g->bw80_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4;
/* 4bit sign number to 8 bit sign number */
- if (pwrinfo5g->bw80_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->bw80_diff[rfPath][TxCount] |= 0xF0;
+ if (pwrinfo5g->bw80_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->bw80_diff[rfpath][txcount] |= 0xF0;
/* 4bit sign number to 8 bit sign number */
- pwrinfo5g->bw160_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f);
- if (pwrinfo5g->bw160_diff[rfPath][TxCount] & BIT(3))
- pwrinfo5g->bw160_diff[rfPath][TxCount] |= 0xF0;
+ pwrinfo5g->bw160_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f);
+ if (pwrinfo5g->bw160_diff[rfpath][txcount] & BIT(3))
+ pwrinfo5g->bw160_diff[rfpath][txcount] |= 0xF0;
- eeAddr++;
+ eeaddr++;
}
}
}
@@ -2930,8 +2908,8 @@ static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo,
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!autoload_fail) {
- rtlhal->pa_type_2g = hwinfo[0xBC];
- rtlhal->lna_type_2g = hwinfo[0xBD];
+ rtlhal->pa_type_2g = hwinfo[0XBC];
+ rtlhal->lna_type_2g = hwinfo[0XBD];
if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) {
rtlhal->pa_type_2g = 0;
rtlhal->lna_type_2g = 0;
@@ -2943,8 +2921,8 @@ static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo,
(rtlhal->lna_type_2g & BIT(3))) ?
1 : 0;
- rtlhal->pa_type_5g = hwinfo[0xBC];
- rtlhal->lna_type_5g = hwinfo[0xBF];
+ rtlhal->pa_type_5g = hwinfo[0XBC];
+ rtlhal->lna_type_5g = hwinfo[0XBF];
if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) {
rtlhal->pa_type_5g = 0;
rtlhal->lna_type_5g = 0;
@@ -2969,18 +2947,18 @@ static void _rtl8812ae_read_amplifier_type(struct ieee80211_hw *hw, u8 *hwinfo,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
- u8 ext_type_pa_2g_a = (hwinfo[0xBD] & BIT(2)) >> 2; /* 0xBD[2] */
- u8 ext_type_pa_2g_b = (hwinfo[0xBD] & BIT(6)) >> 6; /* 0xBD[6] */
- u8 ext_type_pa_5g_a = (hwinfo[0xBF] & BIT(2)) >> 2; /* 0xBF[2] */
- u8 ext_type_pa_5g_b = (hwinfo[0xBF] & BIT(6)) >> 6; /* 0xBF[6] */
- /* 0xBD[1:0] */
- u8 ext_type_lna_2g_a = (hwinfo[0xBD] & (BIT(1) | BIT(0))) >> 0;
- /* 0xBD[5:4] */
- u8 ext_type_lna_2g_b = (hwinfo[0xBD] & (BIT(5) | BIT(4))) >> 4;
- /* 0xBF[1:0] */
- u8 ext_type_lna_5g_a = (hwinfo[0xBF] & (BIT(1) | BIT(0))) >> 0;
- /* 0xBF[5:4] */
- u8 ext_type_lna_5g_b = (hwinfo[0xBF] & (BIT(5) | BIT(4))) >> 4;
+ u8 ext_type_pa_2g_a = (hwinfo[0XBD] & BIT(2)) >> 2; /* 0XBD[2] */
+ u8 ext_type_pa_2g_b = (hwinfo[0XBD] & BIT(6)) >> 6; /* 0XBD[6] */
+ u8 ext_type_pa_5g_a = (hwinfo[0XBF] & BIT(2)) >> 2; /* 0XBF[2] */
+ u8 ext_type_pa_5g_b = (hwinfo[0XBF] & BIT(6)) >> 6; /* 0XBF[6] */
+ /* 0XBD[1:0] */
+ u8 ext_type_lna_2g_a = (hwinfo[0XBD] & (BIT(1) | BIT(0))) >> 0;
+ /* 0XBD[5:4] */
+ u8 ext_type_lna_2g_b = (hwinfo[0XBD] & (BIT(5) | BIT(4))) >> 4;
+ /* 0XBF[1:0] */
+ u8 ext_type_lna_5g_a = (hwinfo[0XBF] & (BIT(1) | BIT(0))) >> 0;
+ /* 0XBF[5:4] */
+ u8 ext_type_lna_5g_b = (hwinfo[0XBF] & (BIT(5) | BIT(4))) >> 4;
_rtl8812ae_read_pa_type(hw, hwinfo, autoload_fail);
@@ -3008,8 +2986,8 @@ static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo,
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!autoload_fail) {
- rtlhal->pa_type_2g = hwinfo[0xBC];
- rtlhal->lna_type_2g = hwinfo[0xBD];
+ rtlhal->pa_type_2g = hwinfo[0XBC];
+ rtlhal->lna_type_2g = hwinfo[0XBD];
if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) {
rtlhal->pa_type_2g = 0;
rtlhal->lna_type_2g = 0;
@@ -3017,8 +2995,8 @@ static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo,
rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(5)) ? 1 : 0;
rtlhal->external_lna_2g = (rtlhal->lna_type_2g & BIT(7)) ? 1 : 0;
- rtlhal->pa_type_5g = hwinfo[0xBC];
- rtlhal->lna_type_5g = hwinfo[0xBF];
+ rtlhal->pa_type_5g = hwinfo[0XBC];
+ rtlhal->lna_type_5g = hwinfo[0XBF];
if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) {
rtlhal->pa_type_5g = 0;
rtlhal->lna_type_5g = 0;
@@ -4033,10 +4011,10 @@ void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw,
rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT);
for (addr = 0; addr < WKFMCAM_ADDR_NUM; addr++) {
/* Set Rx packet buffer offset.
- * RxBufer pointer increases 1,
+ * RXBufer pointer increases 1,
* we can access 8 bytes in Rx packet buffer.
* CAM start offset (unit: 1 byte) = index*WKFMCAM_SIZE
- * RxBufer addr = (CAM start offset +
+ * RXBufer addr = (CAM start offset +
* per entry offset of a WKFM CAM)/8
* * index: The index of the wake up frame mask
* * WKFMCAM_SIZE: the total size of one WKFM CAM
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h
index e2ab783a2ad9..fb0fb3a501d9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_HW_H__
#define __RTL8821AE_HW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
index 405c7541b386..dd7553e80ab1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
index 038e64e18ae8..249a37a8d9db 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_LED_H__
#define __RTL8821AE_LED_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
index a75451c246fd..408af144098e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
@@ -475,7 +453,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band,
const s8 auto_temp = -1;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
- "===> PHY_GetTxBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n",
+ "===> PHY_GetTXBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n",
(int)swing_2g, (int)swing_5g,
(int)rtlefuse->autoload_failflag);
@@ -556,7 +534,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band,
swing_a = (swing & 0x3) >> 0; /* 0xC6/C7[1:0] */
swing_b = (swing & 0xC) >> 2; /* 0xC6/C7[3:2] */
RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
- "===> PHY_GetTxBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n",
+ "===> PHY_GetTXBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n",
swing_a, swing_b);
/* 3 Path-A */
@@ -614,7 +592,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band,
}
RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
- "<=== PHY_GetTxBBSwing_8812A, out = 0x%X\n", out);
+ "<=== PHY_GetTXBBSwing_8812A, out = 0x%X\n", out);
return out;
}
@@ -1078,52 +1056,52 @@ static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &rtlpriv->phy;
- u16 rawValue = 0;
+ u16 rawvalue = 0;
u8 base = 0, path = 0;
for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) {
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, CCK, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, OFDM, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS0_MCS7, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS8_MCS15, RF_2TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, OFDM, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS0_MCS7, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS8_MCS15, RF_2TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base);
- rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF;
- base = (rawValue >> 4) * 10 + (rawValue & 0xF);
+ rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF;
+ base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
_rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base);
}
}
@@ -1380,7 +1358,7 @@ static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
- "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfPath %d] %d)\n",
+ "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfpath %d] %d)\n",
regulation, bw, rate_section, channel,
rtlphy->txpwr_limit_2_4g[regulation][bw]
[rate_section][channel][rf_path], (temp_pwrlmt == 63)
@@ -1445,7 +1423,7 @@ static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
- "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfPath %d] %d)\n",
+ "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfpath %d] %d)\n",
regulation, bw, rate_section,
channel, rtlphy->txpwr_limit_5g[regulation]
[bw][rate_section][channel][rf_path],
@@ -1495,106 +1473,106 @@ static void _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(struct ieee8021
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &rtlpriv->phy;
- u8 base = 0, rfPath = 0;
+ u8 base = 0, rfpath = 0;
- for (rfPath = RF90_PATH_A; rfPath <= RF90_PATH_B; ++rfPath) {
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, CCK);
+ for (rfpath = RF90_PATH_A; rfpath <= RF90_PATH_B; ++rfpath) {
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, CCK);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][0],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][0],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, OFDM);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, OFDM);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][1],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][1],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][2],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][2],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, HT_MCS0_MCS7);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, HT_MCS0_MCS7);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][3],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][3],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][4],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][4],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, HT_MCS8_MCS15);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_2TX, HT_MCS8_MCS15);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][5],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][5],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][6],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][6],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, VHT_1SSMCS0_1SSMCS9);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][7],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][7],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][8],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][8],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][9],
0, 1, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_2TX, VHT_2SSMCS0_2SSMCS9);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][9],
2, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][10],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][10],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][11],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][11],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, OFDM);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, OFDM);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][1],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][1],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][2],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][2],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, HT_MCS0_MCS7);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, HT_MCS0_MCS7);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][3],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][3],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][4],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][4],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, HT_MCS8_MCS15);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_2TX, HT_MCS8_MCS15);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][5],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][5],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][6],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][6],
0, 3, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, VHT_1SSMCS0_1SSMCS9);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][7],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][7],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][8],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][8],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][9],
0, 1, base);
- base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9);
+ base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_2TX, VHT_2SSMCS0_2SSMCS9);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][9],
2, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][10],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][10],
0, 3, base);
_phy_convert_txpower_dbm_to_relative_value(
- &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][11],
+ &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][11],
0, 3, base);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h
index 1285e1adfe9d..35b7d0f70125 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_PHY_H__
#define __RTL8821AE_PHY_H__
@@ -59,9 +37,9 @@
#define LOOP_LIMIT 5
#define MAX_STALL_TIME 50
-#define AntennaDiversityValue 0x80
+#define ANTENNADIVERSITYVALUE 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
-#define Reset_Cnt_Limit 3
+#define RESET_CNT_LIMIT 3
#define IQK_ADDA_REG_NUM 16
#define IQK_MAC_REG_NUM 4
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c
index 9ddf78a187dd..1e7b3c770ac2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../pwrseqcmd.h"
#include "pwrseq.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h
index 6dd575435c63..d6f3cbab4abc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_PWRSEQ_H__
#define __RTL8821AE_PWRSEQ_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
index db8bc8a2de61..7d833b72c7ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_REG_H__
#define __RTL8821AE_REG_H__
@@ -696,7 +674,7 @@
#define EEPROM_CHANNEL_PLAN_TELEC 0x8
#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
-#define EEPROM_CHANNEL_PLAN_NCC 0xB
+#define EEPROM_CHANNEL_PLAN_NCC 0XB
#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
#define EEPROM_CID_DEFAULT 0x0
@@ -718,10 +696,10 @@
#define EEPROM_TX_PWR_INX 0x10
-#define EEPROM_CHANNELPLAN 0xB8
-#define EEPROM_XTAL_8821AE 0xB9
-#define EEPROM_THERMAL_METER 0xBA
-#define EEPROM_IQK_LCK_88E 0xBB
+#define EEPROM_CHANNELPLAN 0XB8
+#define EEPROM_XTAL_8821AE 0XB9
+#define EEPROM_THERMAL_METER 0XBA
+#define EEPROM_IQK_LCK_88E 0XBB
#define EEPROM_RF_BOARD_OPTION 0xC1
#define EEPROM_RF_FEATURE_OPTION_88E 0xC2
@@ -1015,7 +993,7 @@
#define _LBMODE(x) (((x) & 0xF) << 24)
#define MASK_LBMODE 0xF000000
#define LOOPBACK_NORMAL 0x0
-#define LOOPBACK_IMMEDIATELY 0xB
+#define LOOPBACK_IMMEDIATELY 0XB
#define LOOPBACK_MAC_DELAY 0x3
#define LOOPBACK_PHY 0x1
#define LOOPBACK_DMA 0x7
@@ -1430,7 +1408,7 @@
#define RCCK0_FACOUNTERUPPER 0xa58
#define RCCK0_CCA_CNT 0xa60
-/* PageB(0xB00) */
+/* PageB(0XB00) */
#define RPDP_ANTA 0xb00
#define RPDP_ANTA_4 0xb04
#define RPDP_ANTA_8 0xb08
@@ -1477,16 +1455,16 @@
#define RPM_RX3_ANTB 0xbf8
/*RSSI Dump*/
-#define RA_RSSI_DUMP 0xBF0
-#define RB_RSSI_DUMP 0xBF1
-#define RS1_RX_EVM_DUMP 0xBF4
-#define RS2_RX_EVM_DUMP 0xBF5
-#define RA_RX_SNR_DUMP 0xBF6
-#define RB_RX_SNR_DUMP 0xBF7
-#define RA_CFO_SHORT_DUMP 0xBF8
-#define RB_CFO_SHORT_DUMP 0xBFA
-#define RA_CFO_LONG_DUMP 0xBEC
-#define RB_CFO_LONG_DUMP 0xBEE
+#define RA_RSSI_DUMP 0XBF0
+#define RB_RSSI_DUMP 0XBF1
+#define RS1_RX_EVM_DUMP 0XBF4
+#define RS2_RX_EVM_DUMP 0XBF5
+#define RA_RX_SNR_DUMP 0XBF6
+#define RB_RX_SNR_DUMP 0XBF7
+#define RA_CFO_SHORT_DUMP 0XBF8
+#define RB_CFO_SHORT_DUMP 0XBFA
+#define RA_CFO_LONG_DUMP 0XBEC
+#define RB_CFO_LONG_DUMP 0XBEE
/*Page C*/
#define ROFDM0_LSTF 0xc00
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c
index 95489f41f8a0..a6e56872e063 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "reg.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h
index efd22bd0b139..6e3c8bfb2048 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_RF_H__
#define __RTL8821AE_RF_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 77f6401021c9..eec7c4ecf3ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../core.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h
index d001e7ce3052..9d7610f84b20 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_SW_H__
#define __RTL8821AE_SW_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
index f87f9d03b9fa..85093b3e5373 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
@@ -1,29 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
+
#include <linux/kernel.h>
#include "table.h"
u32 RTL8812AE_PHY_REG_ARRAY[] = {
@@ -134,30 +111,30 @@ u32 RTL8812AE_PHY_REG_ARRAY[] = {
0xA7C, 0x225B0606,
0xA80, 0x218075B2,
0xA84, 0x001F8C80,
- 0xB00, 0x03100000,
- 0xB04, 0x0000B000,
- 0xB08, 0xAE0201EB,
- 0xB0C, 0x01003207,
- 0xB10, 0x00009807,
- 0xB14, 0x01000000,
- 0xB18, 0x00000002,
- 0xB1C, 0x00000002,
- 0xB20, 0x0000001F,
- 0xB24, 0x03020100,
- 0xB28, 0x07060504,
- 0xB2C, 0x0B0A0908,
- 0xB30, 0x0F0E0D0C,
- 0xB34, 0x13121110,
- 0xB38, 0x17161514,
- 0xB3C, 0x0000003A,
- 0xB40, 0x00000000,
- 0xB44, 0x00000000,
- 0xB48, 0x13000032,
- 0xB4C, 0x48080000,
- 0xB50, 0x00000000,
- 0xB54, 0x00000000,
- 0xB58, 0x00000000,
- 0xB5C, 0x00000000,
+ 0XB00, 0x03100000,
+ 0XB04, 0x0000B000,
+ 0XB08, 0xAE0201EB,
+ 0XB0C, 0x01003207,
+ 0XB10, 0x00009807,
+ 0XB14, 0x01000000,
+ 0XB18, 0x00000002,
+ 0XB1C, 0x00000002,
+ 0XB20, 0x0000001F,
+ 0XB24, 0x03020100,
+ 0XB28, 0x07060504,
+ 0XB2C, 0x0B0A0908,
+ 0XB30, 0x0F0E0D0C,
+ 0XB34, 0x13121110,
+ 0XB38, 0x17161514,
+ 0XB3C, 0x0000003A,
+ 0XB40, 0x00000000,
+ 0XB44, 0x00000000,
+ 0XB48, 0x13000032,
+ 0XB4C, 0x48080000,
+ 0XB50, 0x00000000,
+ 0XB54, 0x00000000,
+ 0XB58, 0x00000000,
+ 0XB5C, 0x00000000,
0xC00, 0x00000007,
0xC04, 0x00042020,
0xC08, 0x80410231,
@@ -197,7 +174,7 @@ u32 RTL8812AE_PHY_REG_ARRAY[] = {
0xC68, 0x59791979,
0xA0000000, 0x00000000,
0xC68, 0x59799979,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0xC6C, 0x59795979,
0xC70, 0x19795979,
0xC74, 0x19795979,
@@ -367,30 +344,30 @@ u32 RTL8821AE_PHY_REG_ARRAY[] = {
0xA7C, 0x225B0606,
0xA80, 0x21805490,
0xA84, 0x001F0000,
- 0xB00, 0x03100040,
- 0xB04, 0x0000B000,
- 0xB08, 0xAE0201EB,
- 0xB0C, 0x01003207,
- 0xB10, 0x00009807,
- 0xB14, 0x01000000,
- 0xB18, 0x00000002,
- 0xB1C, 0x00000002,
- 0xB20, 0x0000001F,
- 0xB24, 0x03020100,
- 0xB28, 0x07060504,
- 0xB2C, 0x0B0A0908,
- 0xB30, 0x0F0E0D0C,
- 0xB34, 0x13121110,
- 0xB38, 0x17161514,
- 0xB3C, 0x0000003A,
- 0xB40, 0x00000000,
- 0xB44, 0x00000000,
- 0xB48, 0x13000032,
- 0xB4C, 0x48080000,
- 0xB50, 0x00000000,
- 0xB54, 0x00000000,
- 0xB58, 0x00000000,
- 0xB5C, 0x00000000,
+ 0XB00, 0x03100040,
+ 0XB04, 0x0000B000,
+ 0XB08, 0xAE0201EB,
+ 0XB0C, 0x01003207,
+ 0XB10, 0x00009807,
+ 0XB14, 0x01000000,
+ 0XB18, 0x00000002,
+ 0XB1C, 0x00000002,
+ 0XB20, 0x0000001F,
+ 0XB24, 0x03020100,
+ 0XB28, 0x07060504,
+ 0XB2C, 0x0B0A0908,
+ 0XB30, 0x0F0E0D0C,
+ 0XB34, 0x13121110,
+ 0XB38, 0x17161514,
+ 0XB3C, 0x0000003A,
+ 0XB40, 0x00000000,
+ 0XB44, 0x00000000,
+ 0XB48, 0x13000032,
+ 0XB4C, 0x48080000,
+ 0XB50, 0x00000000,
+ 0XB54, 0x00000000,
+ 0XB58, 0x00000000,
+ 0XB5C, 0x00000000,
0xC00, 0x00000007,
0xC04, 0x00042020,
0xC08, 0x80410231,
@@ -521,12 +498,12 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x086, 0x00014B3A,
0xA0000000, 0x00000000,
0x086, 0x00014B38,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000004, 0x00000000, 0x40000000, 0x00000000,
0x08B, 0x00080180,
0xA0000000, 0x00000000,
0x08B, 0x00087180,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0B1, 0x0001FC1A,
0x0B3, 0x000F0810,
0x0B4, 0x0001A78D,
@@ -557,7 +534,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x03B, 0x00018248,
0x03B, 0x00010240,
0x03B, 0x00008240,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000100,
0x80000002, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0000A4EE,
@@ -583,7 +560,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x034, 0x000024E7,
0x034, 0x0000146B,
0x034, 0x0000006D,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x0EF, 0x000020A2,
0x0DF, 0x00000080,
@@ -712,7 +689,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x034, 0x000428C5,
0x034, 0x000418C2,
0x034, 0x000408C0,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0002A0B2,
0x034, 0x000290AF,
@@ -749,7 +726,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x034, 0x000228C5,
0x034, 0x000218C2,
0x034, 0x000208C0,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0000A0B2,
0x034, 0x000090AF,
@@ -786,7 +763,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x034, 0x000028C9,
0x034, 0x000018C6,
0x034, 0x000008C3,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x018, 0x0001712A,
@@ -824,7 +801,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x035, 0x000401D8,
0x035, 0x000481D8,
0x035, 0x000501D8,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x018, 0x0001712A,
@@ -871,7 +848,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x036, 0x000CCC35,
0x036, 0x000D4C35,
0x036, 0x000DCC35,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x0EF, 0x00000008,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
@@ -886,7 +863,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x03C, 0x000002A8,
0x03C, 0x000005A2,
0x03C, 0x00000880,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x018, 0x0001712A,
0x0EF, 0x00000002,
@@ -910,7 +887,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = {
0x063, 0x000114EB,
0x064, 0x000196AC,
0x065, 0x000911D7,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x008, 0x00008400,
0x01C, 0x000739D2,
0x0B4, 0x0001E78D,
@@ -935,12 +912,12 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x086, 0x00014B3A,
0xA0000000, 0x00000000,
0x086, 0x00014B38,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000004, 0x00000000, 0x40000000, 0x00000000,
0x08B, 0x00080180,
0xA0000000, 0x00000000,
0x08B, 0x00087180,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x018, 0x00000006,
0x0EF, 0x00002000,
0x80000001, 0x00000000, 0x40000000, 0x00000000,
@@ -967,7 +944,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x03B, 0x00018248,
0x03B, 0x00010240,
0x03B, 0x00008240,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000100,
0x80000002, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0000A4EE,
@@ -993,7 +970,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x034, 0x000024E7,
0x034, 0x0000146B,
0x034, 0x0000006D,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x0EF, 0x000020A2,
0x0DF, 0x00000080,
@@ -1122,7 +1099,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x034, 0x000428C5,
0x034, 0x000418C2,
0x034, 0x000408C0,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0002A0B2,
0x034, 0x000290AF,
@@ -1159,7 +1136,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x034, 0x000228C5,
0x034, 0x000218C2,
0x034, 0x000208C0,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x034, 0x0000A0B2,
0x034, 0x000090AF,
@@ -1196,7 +1173,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x034, 0x000028C9,
0x034, 0x000018C6,
0x034, 0x000008C3,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x018, 0x0001712A,
@@ -1237,7 +1214,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x035, 0x000481D8,
0x035, 0x000501D8,
0x0EF, 0x00000000,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
0x018, 0x0001712A,
0x0EF, 0x00000010,
@@ -1283,7 +1260,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x036, 0x000CCC35,
0x036, 0x000D4C35,
0x036, 0x000DCC35,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x0EF, 0x00000008,
0x80000008, 0x00000000, 0x40000000, 0x00000000,
@@ -1298,7 +1275,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x03C, 0x000002A8,
0x03C, 0x000005A2,
0x03C, 0x00000880,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x0EF, 0x00000000,
0x018, 0x0001712A,
0x0EF, 0x00000002,
@@ -1327,7 +1304,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = {
0x063, 0x000114EB,
0x064, 0x000196AC,
0x065, 0x000911D7,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x008, 0x00008400,
};
@@ -1933,7 +1910,7 @@ u32 RTL8812AE_MAC_REG_ARRAY[] = {
0x011, 0x00000066,
0xA0000000, 0x00000000,
0x011, 0x0000005A,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x025, 0x0000000F,
0x072, 0x00000000,
0x420, 0x00000080,
@@ -2337,7 +2314,7 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = {
0x81C, 0x417A0001,
0x81C, 0x417C0001,
0x81C, 0x417E0001,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0x80000004, 0x00000000, 0x40000000, 0x00000000,
0x81C, 0xFC800001,
0x81C, 0xFB820001,
@@ -2468,7 +2445,7 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = {
0x81C, 0x01FA0001,
0x81C, 0x01FC0001,
0x81C, 0x01FE0001,
- 0xB0000000, 0x00000000,
+ 0XB0000000, 0x00000000,
0xC50, 0x00000022,
0xC50, 0x00000020,
0xE50, 0x00000022,
@@ -2478,24 +2455,24 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = {
u32 RTL8812AE_AGC_TAB_1TARRAYLEN = ARRAY_SIZE(RTL8812AE_AGC_TAB_ARRAY);
u32 RTL8821AE_AGC_TAB_ARRAY[] = {
- 0x81C, 0xBF000001,
- 0x81C, 0xBF020001,
- 0x81C, 0xBF040001,
- 0x81C, 0xBF060001,
- 0x81C, 0xBE080001,
- 0x81C, 0xBD0A0001,
- 0x81C, 0xBC0C0001,
- 0x81C, 0xBA0E0001,
- 0x81C, 0xB9100001,
- 0x81C, 0xB8120001,
- 0x81C, 0xB7140001,
- 0x81C, 0xB6160001,
- 0x81C, 0xB5180001,
- 0x81C, 0xB41A0001,
- 0x81C, 0xB31C0001,
- 0x81C, 0xB21E0001,
- 0x81C, 0xB1200001,
- 0x81C, 0xB0220001,
+ 0x81C, 0XBF000001,
+ 0x81C, 0XBF020001,
+ 0x81C, 0XBF040001,
+ 0x81C, 0XBF060001,
+ 0x81C, 0XBE080001,
+ 0x81C, 0XBD0A0001,
+ 0x81C, 0XBC0C0001,
+ 0x81C, 0XBA0E0001,
+ 0x81C, 0XB9100001,
+ 0x81C, 0XB8120001,
+ 0x81C, 0XB7140001,
+ 0x81C, 0XB6160001,
+ 0x81C, 0XB5180001,
+ 0x81C, 0XB41A0001,
+ 0x81C, 0XB31C0001,
+ 0x81C, 0XB21E0001,
+ 0x81C, 0XB1200001,
+ 0x81C, 0XB0220001,
0x81C, 0xAF240001,
0x81C, 0xAE260001,
0x81C, 0xAD280001,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
index 36c2388b60bc..540159c25078 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
@@ -1,29 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Created on 2010/ 5/18, 1:41
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_TABLE__H_
#define __RTL8821AE_TABLE__H_
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
index 0f2b7c619918..db5e628b17ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
index 4ff0968dba81..a3feecad645d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2010 Realtek Corporation.*/
#ifndef __RTL8821AE_TRX_H__
#define __RTL8821AE_TRX_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.c b/drivers/net/wireless/realtek/rtlwifi/stats.c
index 61700fa05570..504ca587a16a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/stats.c
+++ b/drivers/net/wireless/realtek/rtlwifi/stats.c
@@ -1,27 +1,6 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
+
#include "wifi.h"
#include "stats.h"
#include <linux/export.h>
diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.h b/drivers/net/wireless/realtek/rtlwifi/stats.h
index bd0108f93182..581590729b0f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/stats.h
+++ b/drivers/net/wireless/realtek/rtlwifi/stats.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_STATS_H__
#define __RTL_STATS_H__
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 2ac5004d7a40..e24fda5e9087 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -1,25 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "core.h"
@@ -214,7 +194,7 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
_usb_write_async(to_usb_device(dev), addr, val, 4);
}
-static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
+static void _usb_writen_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
u16 len)
{
struct device *dev = rtlpriv->io.dev;
@@ -249,7 +229,7 @@ static void _rtl_usb_io_handler_init(struct device *dev,
rtlpriv->io.read8_sync = _usb_read8_sync;
rtlpriv->io.read16_sync = _usb_read16_sync;
rtlpriv->io.read32_sync = _usb_read32_sync;
- rtlpriv->io.writeN_sync = _usb_writeN_sync;
+ rtlpriv->io.writen_sync = _usb_writen_sync;
}
static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
@@ -287,6 +267,7 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw)
for (i = 0; i < __RTL_TXQ_NUM; i++) {
u32 ep_num = rtlusb->ep_map.ep_mapping[i];
+
if (!ep_num) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"Invalid endpoint map setting!\n");
@@ -351,6 +332,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0;
for (epidx = 0; epidx < epnums; epidx++) {
struct usb_endpoint_descriptor *pep_desc;
+
pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc;
if (usb_endpoint_dir_in(pep_desc))
@@ -413,7 +395,7 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw)
rtlusb->irq_mask[0] = 0xFFFFFFFF;
/* HIMR_EX - turn all on */
rtlusb->irq_mask[1] = 0xFFFFFFFF;
- rtlusb->disableHWSM = true;
+ rtlusb->disablehwsm = true;
}
static void _rtl_rx_completed(struct urb *urb);
@@ -773,6 +755,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
return err;
}
+
/**
*
*
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h
index c91cec04bfaf..3bf85b23eec1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.h
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.h
@@ -1,25 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_USB_H__
#define __RTL_USB_H__
@@ -37,7 +17,6 @@
#define USB_HIGH_SPEED_BULK_SIZE 512
#define USB_FULL_SPEED_BULK_SIZE 64
-
#define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */
#define RTL_USB_MAX_EP_NUM 6 /* max ep number */
#define RTL_USB_MAX_TX_URBS_NUM 8
@@ -73,11 +52,11 @@ static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb,
u32 ep_num)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
info->rate_driver_data[0] = rtlusb;
info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num;
}
-
/* Add suspend/resume later */
enum rtl_usb_state {
USB_STATE_STOP = 0,
@@ -104,7 +83,7 @@ struct rtl_usb {
/* Bcn control register setting */
u32 reg_bcn_ctrl_val;
/* for 88/92cu card disable */
- u8 disableHWSM;
+ u8 disablehwsm;
/*QOS & EDCA */
enum acm_method acm_method;
/* irq . HIMR,HIMR_EX */
@@ -153,8 +132,6 @@ struct rtl_usb_priv {
#define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv))
#define rtl_usbdev(usbpriv) (&((usbpriv)->dev))
-
-
int rtl_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id,
struct rtl_hal_cfg *rtl92cu_hal_cfg);
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 87bc21bb5e8b..e32e9ffa3192 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1,27 +1,5 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2012 Realtek Corporation.
- *
- * 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
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2009-2012 Realtek Corporation.*/
#ifndef __RTL_WIFI_H__
#define __RTL_WIFI_H__
@@ -263,7 +241,7 @@ struct rtlwifi_firmware_header {
u8 date;
u8 hour;
u8 minute;
- __le16 ramcodeSize;
+ __le16 ramcodesize;
__le16 rsvd2;
__le32 svnindex;
__le32 rsvd3;
@@ -435,8 +413,8 @@ enum hw_variables {
HW_VAR_MULTICAST_REG = 0x1,
HW_VAR_BASIC_RATE = 0x2,
HW_VAR_BSSID = 0x3,
- HW_VAR_MEDIA_STATUS= 0x4,
- HW_VAR_SECURITY_CONF= 0x5,
+ HW_VAR_MEDIA_STATUS = 0x4,
+ HW_VAR_SECURITY_CONF = 0x5,
HW_VAR_BEACON_INTERVAL = 0x6,
HW_VAR_ATIM_WINDOW = 0x7,
HW_VAR_LISTEN_INTERVAL = 0x8,
@@ -453,7 +431,7 @@ enum hw_variables {
HW_VAR_ACK_PREAMBLE = 0x13,
HW_VAR_CW_CONFIG = 0x14,
HW_VAR_CW_VALUES = 0x15,
- HW_VAR_RATE_FALLBACK_CONTROL= 0x16,
+ HW_VAR_RATE_FALLBACK_CONTROL = 0x16,
HW_VAR_CONTENTION_WINDOW = 0x17,
HW_VAR_RETRY_COUNT = 0x18,
HW_VAR_TR_SWITCH = 0x19,
@@ -465,11 +443,11 @@ enum hw_variables {
HW_VAR_MCS_RATE_AVAILABLE = 0x1f,
HW_VAR_AC_PARAM = 0x20,
HW_VAR_ACM_CTRL = 0x21,
- HW_VAR_DIS_Req_Qsize = 0x22,
+ HW_VAR_DIS_REQ_QSIZE = 0x22,
HW_VAR_CCX_CHNL_LOAD = 0x23,
HW_VAR_CCX_NOISE_HISTOGRAM = 0x24,
HW_VAR_CCX_CLM_NHM = 0x25,
- HW_VAR_TxOPLimit = 0x26,
+ HW_VAR_TXOPLIMIT = 0x26,
HW_VAR_TURBO_MODE = 0x27,
HW_VAR_RF_STATE = 0x28,
HW_VAR_RF_OFF_BY_HW = 0x29,
@@ -522,7 +500,7 @@ enum hw_variables {
HW_VAR_BCN_VALID = 0x55,
HW_VAR_FWLPS_RF_ON = 0x56,
HW_VAR_DUAL_TSF_RST = 0x57,
- HW_VAR_SWITCH_EPHY_WoWLAN = 0x58,
+ HW_VAR_SWITCH_EPHY_WOWLAN = 0x58,
HW_VAR_INT_MIGRATION = 0x59,
HW_VAR_INT_AC = 0x5a,
HW_VAR_RF_TIMING = 0x5b,
@@ -620,7 +598,8 @@ enum ht_channel_width {
};
/* Ref: 802.11i sepc D10.0 7.3.2.25.1
-Cipher Suites Encryption Algorithms */
+ * Cipher Suites Encryption Algorithms
+ */
enum rt_enc_alg {
NO_ENCRYPTION = 0,
WEP40_ENCRYPTION = 1,
@@ -770,7 +749,8 @@ enum rtl_var_map {
RTL_IMR_ROK, /*Receive DMA OK Interrupt */
RTL_IMR_HSISR_IND, /*HSISR Interrupt*/
RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK |
- * RTL_IMR_TBDER) */
+ * RTL_IMR_TBDER)
+ */
RTL_IMR_C2HCMD, /*fw interrupt*/
/*CCK Rates, TxHT = 0 */
@@ -814,8 +794,8 @@ enum _fw_ps_mode {
FW_PS_UAPSD_MODE = 6,
FW_PS_IBSS_MODE = 7,
FW_PS_WWLAN_MODE = 8,
- FW_PS_PM_Radio_Off = 9,
- FW_PS_PM_Card_Disable = 10,
+ FW_PS_PM_RADIO_OFF = 9,
+ FW_PS_PM_CARD_DISABLE = 10,
};
enum rt_psmode {
@@ -849,8 +829,8 @@ enum rtl_led_pin {
/*QoS related.*/
/*acm implementation method.*/
enum acm_method {
- eAcmWay0_SwAndHw = 0,
- eAcmWay1_HW = 1,
+ EACMWAY0_SWANDHW = 0,
+ EACMWAY1_HW = 1,
EACMWAY2_SW = 2,
};
@@ -867,8 +847,9 @@ enum band_type {
BANDMAX
};
-/*aci/aifsn Field.
-Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/
+/* aci/aifsn Field.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
+ */
union aci_aifsn {
u8 char_data;
@@ -1084,7 +1065,8 @@ struct rtl_probe_rsp {
__le16 beacon_interval;
__le16 capability;
/*SSID, supported rates, FH params, DS params,
- CF params, IBSS params, TIM (if beacon), RSN */
+ * CF params, IBSS params, TIM (if beacon), RSN
+ */
struct rtl_info_element info_element[0];
} __packed;
@@ -1158,7 +1140,8 @@ struct wireless_stats {
long rx_snr_db[4];
/*Correct smoothed ss in Dbm, only used
- in driver to report real power now. */
+ * in driver to report real power now.
+ */
long recv_signal_power;
long signal_quality;
long last_sigstrength_inpercent;
@@ -1166,8 +1149,9 @@ struct wireless_stats {
u32 rssi_calculate_cnt;
u32 pwdb_all_cnt;
- /*Transformed, in dbm. Beautified signal
- strength for UI, not correct. */
+ /* Transformed, in dbm. Beautified signal
+ * strength for UI, not correct.
+ */
long signal_strength;
u8 rx_rssi_percentage[4];
@@ -1478,15 +1462,15 @@ struct rtl_io {
/*PCI IO map */
unsigned long pci_base_addr; /*device I/O address */
- void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
- void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
- void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
- void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf,
- u16 len);
+ void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val);
+ void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val);
+ void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val);
+ void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf,
+ u16 len);
- u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
- u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
- u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
+ u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr);
+ u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr);
+ u32 (*read32_sync)(struct rtl_priv *rtlpriv, u32 addr);
};
@@ -1711,7 +1695,8 @@ struct rtl_hal {
bool during_mac1init_radioa;
bool reloadtxpowerindex;
/* True if IMR or IQK have done
- for 2.4G in scan progress */
+ * for 2.4G in scan progress
+ */
bool load_imrandiqk_setting_for2g;
bool disable_amsdu_8k;
@@ -1750,12 +1735,14 @@ struct rtl_security {
u32 hwsec_cam_bitmap;
u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN];
/*local Key buffer, indx 0 is for
- pairwise key 1-4 is for agoup key. */
+ * pairwise key 1-4 is for agoup key.
+ */
u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN];
u8 key_len[KEY_BUF_SIZE];
/*The pointer of Pairwise Key,
- it always points to KeyBuf[4] */
+ * it always points to KeyBuf[4]
+ */
u8 *pairwise_key;
};
@@ -1898,7 +1885,7 @@ struct rtl_dm {
struct rtl_efuse {
const struct rtl_efuse_ops *efuse_ops;
- bool autoLoad_ok;
+ bool autoload_ok;
bool bootfromefuse;
u16 max_physical_size;
@@ -2019,11 +2006,10 @@ struct rtl_ps_ctl {
bool rfchange_inprogress;
bool swrf_processing;
bool hwradiooff;
- /*
- * just for PCIE ASPM
+ /* just for PCIE ASPM
* If it supports ASPM, Offset[560h] = 0x40,
* otherwise Offset[560h] = 0x00.
- * */
+ */
bool support_aspm;
bool support_backdoor;
@@ -2103,10 +2089,9 @@ struct rtl_stats {
u8 nic_type;
u16 length;
u8 signalquality; /*in 0-100 index. */
- /*
- * Real power in dBm for this packet,
+ /* Real power in dBm for this packet,
* no beautification and aggregation.
- * */
+ */
s32 recvsignalpower;
s8 rxpower; /*in dBm Translate from PWdB */
u8 signalstrength; /*in 0-100 index. */
@@ -2125,7 +2110,7 @@ struct rtl_stats {
u8 rx_bufshift;
bool isampdu;
bool isfirst_ampdu;
- bool rx_is40Mhzpacket;
+ bool rx_is40mhzpacket;
u8 rx_packet_bw;
u32 rx_pwdb_all;
u8 rx_mimo_signalstrength[4]; /*in 0~100 index */
@@ -2158,7 +2143,6 @@ struct rtl_stats {
u32 macid_valid_entry[2];
};
-
struct rt_link_detect {
/* count for roaming */
u32 bcn_rx_inperiod;
@@ -2232,114 +2216,114 @@ struct rtl_int {
};
struct rtl_hal_ops {
- int (*init_sw_vars) (struct ieee80211_hw *hw);
- void (*deinit_sw_vars) (struct ieee80211_hw *hw);
+ int (*init_sw_vars)(struct ieee80211_hw *hw);
+ void (*deinit_sw_vars)(struct ieee80211_hw *hw);
void (*read_chip_version)(struct ieee80211_hw *hw);
- void (*read_eeprom_info) (struct ieee80211_hw *hw);
- void (*interrupt_recognized) (struct ieee80211_hw *hw,
- struct rtl_int *intvec);
- int (*hw_init) (struct ieee80211_hw *hw);
- void (*hw_disable) (struct ieee80211_hw *hw);
- void (*hw_suspend) (struct ieee80211_hw *hw);
- void (*hw_resume) (struct ieee80211_hw *hw);
- void (*enable_interrupt) (struct ieee80211_hw *hw);
- void (*disable_interrupt) (struct ieee80211_hw *hw);
- int (*set_network_type) (struct ieee80211_hw *hw,
- enum nl80211_iftype type);
+ void (*read_eeprom_info)(struct ieee80211_hw *hw);
+ void (*interrupt_recognized)(struct ieee80211_hw *hw,
+ struct rtl_int *intvec);
+ int (*hw_init)(struct ieee80211_hw *hw);
+ void (*hw_disable)(struct ieee80211_hw *hw);
+ void (*hw_suspend)(struct ieee80211_hw *hw);
+ void (*hw_resume)(struct ieee80211_hw *hw);
+ void (*enable_interrupt)(struct ieee80211_hw *hw);
+ void (*disable_interrupt)(struct ieee80211_hw *hw);
+ int (*set_network_type)(struct ieee80211_hw *hw,
+ enum nl80211_iftype type);
void (*set_chk_bssid)(struct ieee80211_hw *hw,
- bool check_bssid);
- void (*set_bw_mode) (struct ieee80211_hw *hw,
- enum nl80211_channel_type ch_type);
- u8(*switch_channel) (struct ieee80211_hw *hw);
- void (*set_qos) (struct ieee80211_hw *hw, int aci);
- void (*set_bcn_reg) (struct ieee80211_hw *hw);
- void (*set_bcn_intv) (struct ieee80211_hw *hw);
- void (*update_interrupt_mask) (struct ieee80211_hw *hw,
- u32 add_msr, u32 rm_msr);
- void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val);
- void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val);
- void (*update_rate_tbl) (struct ieee80211_hw *hw,
- struct ieee80211_sta *sta, u8 rssi_leve,
- bool update_bw);
+ bool check_bssid);
+ void (*set_bw_mode)(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+ u8 (*switch_channel)(struct ieee80211_hw *hw);
+ void (*set_qos)(struct ieee80211_hw *hw, int aci);
+ void (*set_bcn_reg)(struct ieee80211_hw *hw);
+ void (*set_bcn_intv)(struct ieee80211_hw *hw);
+ void (*update_interrupt_mask)(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr);
+ void (*get_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val);
+ void (*set_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val);
+ void (*update_rate_tbl)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_leve,
+ bool update_bw);
void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc,
u8 *desc, u8 queue_index,
struct sk_buff *skb, dma_addr_t addr);
- void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level);
+ void (*update_rate_mask)(struct ieee80211_hw *hw, u8 rssi_level);
u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw,
u8 queue_index);
void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc,
u8 queue_index);
- void (*fill_tx_desc) (struct ieee80211_hw *hw,
- struct ieee80211_hdr *hdr, u8 *pdesc_tx,
- u8 *pbd_desc_tx,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta,
- struct sk_buff *skb, u8 hw_queue,
- struct rtl_tcb_desc *ptcb_desc);
- void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc,
- u32 buffer_len, bool bIsPsPoll);
- void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc,
- bool firstseg, bool lastseg,
- struct sk_buff *skb);
+ void (*fill_tx_desc)(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+ u8 *pbd_desc_tx,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb, u8 hw_queue,
+ struct rtl_tcb_desc *ptcb_desc);
+ void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc,
+ u32 buffer_len, bool bsspspoll);
+ void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc,
+ bool firstseg, bool lastseg,
+ struct sk_buff *skb);
void (*fill_tx_special_desc)(struct ieee80211_hw *hw,
u8 *pdesc, u8 *pbd_desc,
struct sk_buff *skb, u8 hw_queue);
- bool (*query_rx_desc) (struct ieee80211_hw *hw,
- struct rtl_stats *stats,
- struct ieee80211_rx_status *rx_status,
- u8 *pdesc, struct sk_buff *skb);
- void (*set_channel_access) (struct ieee80211_hw *hw);
- bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid);
- void (*dm_watchdog) (struct ieee80211_hw *hw);
- void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation);
- bool (*set_rf_power_state) (struct ieee80211_hw *hw,
- enum rf_pwrstate rfpwr_state);
- void (*led_control) (struct ieee80211_hw *hw,
- enum led_ctl_mode ledaction);
+ bool (*query_rx_desc)(struct ieee80211_hw *hw,
+ struct rtl_stats *stats,
+ struct ieee80211_rx_status *rx_status,
+ u8 *pdesc, struct sk_buff *skb);
+ void (*set_channel_access)(struct ieee80211_hw *hw);
+ bool (*radio_onoff_checking)(struct ieee80211_hw *hw, u8 *valid);
+ void (*dm_watchdog)(struct ieee80211_hw *hw);
+ void (*scan_operation_backup)(struct ieee80211_hw *hw, u8 operation);
+ bool (*set_rf_power_state)(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
+ void (*led_control)(struct ieee80211_hw *hw,
+ enum led_ctl_mode ledaction);
void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
u8 desc_name, u8 *val);
u64 (*get_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
u8 desc_name);
- bool (*is_tx_desc_closed) (struct ieee80211_hw *hw,
- u8 hw_queue, u16 index);
- void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue);
- void (*enable_hw_sec) (struct ieee80211_hw *hw);
- void (*set_key) (struct ieee80211_hw *hw, u32 key_index,
- u8 *macaddr, bool is_group, u8 enc_algo,
- bool is_wepkey, bool clear_all);
- void (*init_sw_leds) (struct ieee80211_hw *hw);
- void (*deinit_sw_leds) (struct ieee80211_hw *hw);
- u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
- void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
- u32 data);
- u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
- u32 regaddr, u32 bitmask);
- void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
- u32 regaddr, u32 bitmask, u32 data);
- void (*linked_set_reg) (struct ieee80211_hw *hw);
- void (*chk_switch_dmdp) (struct ieee80211_hw *hw);
- void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw);
- void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw);
- bool (*phy_rf6052_config) (struct ieee80211_hw *hw);
- void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw,
- u8 *powerlevel);
- void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw,
- u8 *ppowerlevel, u8 channel);
- bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw,
- u8 configtype);
- bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw,
- u8 configtype);
- void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t);
- void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw);
- void (*dm_dynamic_txpower) (struct ieee80211_hw *hw);
- void (*c2h_command_handle) (struct ieee80211_hw *hw);
- void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw,
- bool mstate);
- void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw);
- void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id,
- u32 cmd_len, u8 *p_cmdbuffer);
+ bool (*is_tx_desc_closed)(struct ieee80211_hw *hw,
+ u8 hw_queue, u16 index);
+ void (*tx_polling)(struct ieee80211_hw *hw, u8 hw_queue);
+ void (*enable_hw_sec)(struct ieee80211_hw *hw);
+ void (*set_key)(struct ieee80211_hw *hw, u32 key_index,
+ u8 *macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all);
+ void (*init_sw_leds)(struct ieee80211_hw *hw);
+ void (*deinit_sw_leds)(struct ieee80211_hw *hw);
+ u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+ void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+ u32 data);
+ u32 (*get_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask);
+ void (*set_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data);
+ void (*linked_set_reg)(struct ieee80211_hw *hw);
+ void (*chk_switch_dmdp)(struct ieee80211_hw *hw);
+ void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw);
+ void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw);
+ bool (*phy_rf6052_config)(struct ieee80211_hw *hw);
+ void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw,
+ u8 *powerlevel);
+ void (*phy_rf6052_set_ofdm_txpower)(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+ bool (*config_bb_with_headerfile)(struct ieee80211_hw *hw,
+ u8 configtype);
+ bool (*config_bb_with_pgheaderfile)(struct ieee80211_hw *hw,
+ u8 configtype);
+ void (*phy_lc_calibrate)(struct ieee80211_hw *hw, bool is2t);
+ void (*phy_set_bw_mode_callback)(struct ieee80211_hw *hw);
+ void (*dm_dynamic_txpower)(struct ieee80211_hw *hw);
+ void (*c2h_command_handle)(struct ieee80211_hw *hw);
+ void (*bt_wifi_media_status_notify)(struct ieee80211_hw *hw,
+ bool mstate);
+ void (*bt_coex_off_before_lps)(struct ieee80211_hw *hw);
+ void (*fill_h2c_cmd)(struct ieee80211_hw *hw, u8 element_id,
+ u32 cmd_len, u8 *p_cmdbuffer);
void (*set_default_port_id_cmd)(struct ieee80211_hw *hw);
- bool (*get_btc_status) (void);
+ bool (*get_btc_status)(void);
bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr);
void (*add_wowlan_pattern)(struct ieee80211_hw *hw,
struct rtl_wow_pattern *rtl_pattern,
@@ -2352,24 +2336,24 @@ struct rtl_hal_ops {
struct rtl_intf_ops {
/*com */
void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
- int (*adapter_start) (struct ieee80211_hw *hw);
- void (*adapter_stop) (struct ieee80211_hw *hw);
+ int (*adapter_start)(struct ieee80211_hw *hw);
+ void (*adapter_stop)(struct ieee80211_hw *hw);
bool (*check_buddy_priv)(struct ieee80211_hw *hw,
struct rtl_priv **buddy_priv);
- int (*adapter_tx) (struct ieee80211_hw *hw,
- struct ieee80211_sta *sta,
- struct sk_buff *skb,
- struct rtl_tcb_desc *ptcb_desc);
+ int (*adapter_tx)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb,
+ struct rtl_tcb_desc *ptcb_desc);
void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop);
- int (*reset_trx_ring) (struct ieee80211_hw *hw);
- bool (*waitq_insert) (struct ieee80211_hw *hw,
- struct ieee80211_sta *sta,
- struct sk_buff *skb);
+ int (*reset_trx_ring)(struct ieee80211_hw *hw);
+ bool (*waitq_insert)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb);
/*pci */
- void (*disable_aspm) (struct ieee80211_hw *hw);
- void (*enable_aspm) (struct ieee80211_hw *hw);
+ void (*disable_aspm)(struct ieee80211_hw *hw);
+ void (*enable_aspm)(struct ieee80211_hw *hw);
/*usb */
};
@@ -2447,7 +2431,8 @@ struct rtl_hal_cfg {
enum rtl_spec_ver spec_ver;
/*this map used for some registers or vars
- defined int HAL but used in MAIN */
+ * defined int HAL but used in MAIN
+ */
u32 maps[RTL_VAR_MAP_MAX];
};
@@ -2609,7 +2594,8 @@ struct dig_t {
struct rtl_global_var {
/* from this list we can get
- * other adapter's rtl_priv */
+ * other adapter's rtl_priv
+ */
struct list_head glb_priv_list;
spinlock_t glb_list_lock;
};
@@ -2688,30 +2674,30 @@ struct bt_coexist_info {
};
struct rtl_btc_ops {
- void (*btc_init_variables) (struct rtl_priv *rtlpriv);
+ void (*btc_init_variables)(struct rtl_priv *rtlpriv);
void (*btc_init_variables_wifi_only)(struct rtl_priv *rtlpriv);
void (*btc_deinit_variables)(struct rtl_priv *rtlpriv);
- void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv);
+ void (*btc_init_hal_vars)(struct rtl_priv *rtlpriv);
void (*btc_power_on_setting)(struct rtl_priv *rtlpriv);
- void (*btc_init_hw_config) (struct rtl_priv *rtlpriv);
+ void (*btc_init_hw_config)(struct rtl_priv *rtlpriv);
void (*btc_init_hw_config_wifi_only)(struct rtl_priv *rtlpriv);
- void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
+ void (*btc_ips_notify)(struct rtl_priv *rtlpriv, u8 type);
void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type);
- void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype);
+ void (*btc_scan_notify)(struct rtl_priv *rtlpriv, u8 scantype);
void (*btc_scan_notify_wifi_only)(struct rtl_priv *rtlpriv,
u8 scantype);
- void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action);
- void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv,
- enum rt_media_status mstatus);
- void (*btc_periodical) (struct rtl_priv *rtlpriv);
+ void (*btc_connect_notify)(struct rtl_priv *rtlpriv, u8 action);
+ void (*btc_mediastatus_notify)(struct rtl_priv *rtlpriv,
+ enum rt_media_status mstatus);
+ void (*btc_periodical)(struct rtl_priv *rtlpriv);
void (*btc_halt_notify)(struct rtl_priv *rtlpriv);
- void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv,
- u8 *tmp_buf, u8 length);
+ void (*btc_btinfo_notify)(struct rtl_priv *rtlpriv,
+ u8 *tmp_buf, u8 length);
void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv,
u8 *tmp_buf, u8 length);
- bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv);
- bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv);
- bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
+ bool (*btc_is_limited_dig)(struct rtl_priv *rtlpriv);
+ bool (*btc_is_disable_edca_turbo)(struct rtl_priv *rtlpriv);
+ bool (*btc_is_bt_disabled)(struct rtl_priv *rtlpriv);
void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
u8 pkt_type);
void (*btc_switch_band_notify)(struct rtl_priv *rtlpriv, u8 type,
@@ -2797,16 +2783,16 @@ struct rtl_priv {
struct rtl_debug dbg;
int max_fw_size;
- /*
- *hal_cfg : for diff cards
- *intf_ops : for diff interrface usb/pcie
+ /* hal_cfg : for diff cards
+ * intf_ops : for diff interrface usb/pcie
*/
struct rtl_hal_cfg *cfg;
const struct rtl_intf_ops *intf_ops;
- /*this var will be set by set_bit,
- and was used to indicate status of
- interface or hardware */
+ /* this var will be set by set_bit,
+ * and was used to indicate status of
+ * interface or hardware
+ */
unsigned long status;
/* tables for dm */
@@ -2842,10 +2828,11 @@ struct rtl_priv {
#ifdef CONFIG_PM
struct wiphy_wowlan_support wowlan;
#endif
- /*This must be the last item so
- that it points to the data allocated
- beyond this structure like:
- rtl_pci_priv or rtl_usb_priv */
+ /* This must be the last item so
+ * that it points to the data allocated
+ * beyond this structure like:
+ * rtl_pci_priv or rtl_usb_priv
+ */
u8 priv[0] __aligned(sizeof(void *));
};
@@ -2855,10 +2842,7 @@ struct rtl_priv {
#define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse))
#define rtl_psc(rtlpriv) (&((rtlpriv)->psc))
-
-/***************************************
- Bluetooth Co-existence Related
-****************************************/
+/* Bluetooth Co-existence Related */
enum bt_ant_num {
ANT_X2 = 0,
@@ -2907,14 +2891,13 @@ enum bt_radio_shared {
BT_RADIO_INDIVIDUAL = 1,
};
-
/****************************************
- mem access macro define start
- Call endian free function when
- 1. Read/write packet content.
- 2. Before write integer to IO.
- 3. After read integer from IO.
-****************************************/
+ * mem access macro define start
+ * Call endian free function when
+ * 1. Read/write packet content.
+ * 2. Before write integer to IO.
+ * 3. After read integer from IO.
+ ****************************************/
/* Convert little data endian to host ordering */
#define EF1BYTE(_val) \
((u8)(_val))
@@ -2970,8 +2953,9 @@ enum bt_radio_shared {
(EF1BYTE(*((u8 *)(__pstart))))
/*Description:
-Translate subfield (continuous bits in little-endian) of 4-byte
-value to host byte ordering.*/
+ * Translate subfield (continuous bits in little-endian) of 4-byte
+ * value to host byte ordering.
+ */
#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
( \
(LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \
@@ -3033,9 +3017,7 @@ value to host byte ordering.*/
#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \
(__value) : (((__value + __aligment - 1) / __aligment) * __aligment))
-/****************************************
- mem access macro define end
-****************************************/
+/* mem access macro define end */
#define byte(x, n) ((x >> (8 * n)) & 0xff)
@@ -3170,7 +3152,7 @@ static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr,
}
static inline void rtl_set_bbreg_with_dwmask(struct ieee80211_hw *hw,
- u32 regaddr, u32 data)
+ u32 regaddr, u32 data)
{
rtl_set_bbreg(hw, regaddr, 0xffffffff, data);
}
@@ -3241,9 +3223,10 @@ static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
}
static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw,
- u8 *mac_addr)
+ u8 *mac_addr)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
return ieee80211_find_sta(mac->vif, mac_addr);
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
index 8c6ca8e689e4..c71b41e45423 100644
--- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c
+++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
@@ -59,7 +59,7 @@ static int rsi_sdio_stats_read(struct seq_file *seq, void *data)
}
/**
- * rsi_sdio_stats_open() - This funtion calls single open function of seq_file
+ * rsi_sdio_stats_open() - This function calls single open function of seq_file
* to open file and read contents from it.
* @inode: Pointer to the inode structure.
* @file: Pointer to the file structure.
@@ -93,7 +93,7 @@ static int rsi_version_read(struct seq_file *seq, void *data)
}
/**
- * rsi_version_open() - This funtion calls single open function of seq_file to
+ * rsi_version_open() - This function calls single open function of seq_file to
* open file and read contents from it.
* @inode: Pointer to the inode structure.
* @file: Pointer to the file structure.
@@ -178,7 +178,7 @@ static int rsi_stats_read(struct seq_file *seq, void *data)
}
/**
- * rsi_stats_open() - This funtion calls single open function of seq_file to
+ * rsi_stats_open() - This function calls single open function of seq_file to
* open file and read contents from it.
* @inode: Pointer to the inode structure.
* @file: Pointer to the file structure.
@@ -207,7 +207,7 @@ static int rsi_debug_zone_read(struct seq_file *seq, void *data)
}
/**
- * rsi_debug_read() - This funtion calls single open function of seq_file to
+ * rsi_debug_read() - This function calls single open function of seq_file to
* open file and read contents from it.
* @inode: Pointer to the inode structure.
* @file: Pointer to the file structure.
@@ -297,11 +297,6 @@ int rsi_init_dbgfs(struct rsi_hw *adapter)
dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);
- if (!dev_dbgfs->subdir) {
- kfree(dev_dbgfs);
- return -ENOMEM;
- }
-
for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {
files = &dev_debugfs_files[ii];
dev_dbgfs->rsi_files[ii] =
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 182b06629371..1dbaab2a96b7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -100,6 +100,9 @@ int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
mgmt_desc->frame_type = TX_DOT11_MGMT;
mgmt_desc->header_len = MIN_802_11_HDR_LEN;
mgmt_desc->xtend_desc_size = header_size - FRAME_DESC_SZ;
+
+ if (ieee80211_is_probe_req(wh->frame_control))
+ mgmt_desc->frame_info = cpu_to_le16(RSI_INSERT_SEQ_IN_FW);
mgmt_desc->frame_info |= cpu_to_le16(RATE_INFO_ENABLE);
if (is_broadcast_ether_addr(wh->addr1))
mgmt_desc->frame_info |= cpu_to_le16(RSI_BROADCAST_PKT);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index e56fc83faf0e..831046e760f8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -229,6 +229,69 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
/* sbands->ht_cap.mcs.rx_highest = 0x82; */
}
+static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
+{
+ struct cfg80211_scan_request *scan_req = &hw_req->req;
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
+
+ rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n");
+ common->mac_ops_resumed = false;
+
+ if (common->fsm_state != FSM_MAC_INIT_DONE)
+ return -ENODEV;
+
+ if ((common->wow_flags & RSI_WOW_ENABLED) ||
+ scan_req->n_channels == 0)
+ return -EINVAL;
+
+ /* Scan already in progress. So return */
+ if (common->bgscan_en)
+ return -EBUSY;
+
+ /* If STA is not connected, return with special value 1, in order
+ * to start sw_scan in mac80211
+ */
+ if (!bss->assoc)
+ return 1;
+
+ mutex_lock(&common->mutex);
+ common->hwscan = scan_req;
+ if (!rsi_send_bgscan_params(common, RSI_START_BGSCAN)) {
+ if (!rsi_send_bgscan_probe_req(common, vif)) {
+ rsi_dbg(INFO_ZONE, "Background scan started...\n");
+ common->bgscan_en = true;
+ }
+ }
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct cfg80211_scan_info info;
+
+ rsi_dbg(INFO_ZONE, "***** Hardware scan stop *****\n");
+ mutex_lock(&common->mutex);
+
+ if (common->bgscan_en) {
+ if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ common->bgscan_en = false;
+ info.aborted = false;
+ ieee80211_scan_completed(adapter->hw, &info);
+ rsi_dbg(INFO_ZONE, "Back ground scan cancelled\n");
+ }
+ common->hwscan = NULL;
+ mutex_unlock(&common->mutex);
+}
+
/**
* rsi_mac80211_detach() - This function is used to de-initialize the
* Mac80211 stack.
@@ -308,6 +371,10 @@ static void rsi_mac80211_tx(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ struct ieee80211_hdr *wlh = (struct ieee80211_hdr *)skb->data;
+
+ if (ieee80211_is_auth(wlh->frame_control))
+ common->mac_ops_resumed = false;
rsi_core_xmit(common, skb);
}
@@ -615,7 +682,8 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
}
/* Power save parameters */
- if (changed & IEEE80211_CONF_CHANGE_PS) {
+ if ((changed & IEEE80211_CONF_CHANGE_PS) &&
+ !common->mac_ops_resumed) {
struct ieee80211_vif *vif, *sta_vif = NULL;
unsigned long flags;
int i, set_ps = 1;
@@ -748,15 +816,15 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
adapter->ps_info.dtim_interval_duration = bss->dtim_period;
adapter->ps_info.listen_interval = conf->listen_interval;
- /* If U-APSD is updated, send ps parameters to firmware */
- if (bss->assoc) {
- if (common->uapsd_bitmap) {
- rsi_dbg(INFO_ZONE, "Configuring UAPSD\n");
- rsi_conf_uapsd(adapter, vif);
+ /* If U-APSD is updated, send ps parameters to firmware */
+ if (bss->assoc) {
+ if (common->uapsd_bitmap) {
+ rsi_dbg(INFO_ZONE, "Configuring UAPSD\n");
+ rsi_conf_uapsd(adapter, vif);
+ }
+ } else {
+ common->uapsd_bitmap = 0;
}
- } else {
- common->uapsd_bitmap = 0;
- }
}
if (changed & BSS_CHANGED_CQM) {
@@ -1270,7 +1338,7 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
}
/**
- * rsi_indicate_pkt_to_os() - This function sends recieved packet to mac80211.
+ * rsi_indicate_pkt_to_os() - This function sends received packet to mac80211.
* @common: Pointer to the driver private structure.
* @skb: Pointer to the socket buffer structure.
*
@@ -1833,6 +1901,10 @@ int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan)
return 0;
}
rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
+
+ if (common->coex_mode > 1)
+ rsi_disable_ps(adapter, adapter->vifs[0]);
+
rsi_send_wowlan_request(common, triggers, 1);
/**
@@ -1876,8 +1948,13 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw)
rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
- if (common->hibernate_resume)
- return 0;
+ if (common->hibernate_resume) {
+ common->mac_ops_resumed = true;
+ /* Device need a complete restart of all MAC operations.
+ * returning 1 will serve this purpose.
+ */
+ return 1;
+ }
mutex_lock(&common->mutex);
rsi_send_wowlan_request(common, 0, 0);
@@ -1917,6 +1994,8 @@ static const struct ieee80211_ops mac80211_ops = {
.suspend = rsi_mac80211_suspend,
.resume = rsi_mac80211_resume,
#endif
+ .hw_scan = rsi_mac80211_hw_scan_start,
+ .cancel_hw_scan = rsi_mac80211_cancel_hw_scan,
};
/**
@@ -1999,6 +2078,9 @@ int rsi_mac80211_attach(struct rsi_common *common)
common->max_stations = wiphy->max_ap_assoc_sta;
rsi_dbg(ERR_ZONE, "Max Stations Allowed = %d\n", common->max_stations);
hw->sta_data_size = sizeof(struct rsi_sta);
+
+ wiphy->max_scan_ssids = RSI_MAX_SCAN_SSIDS;
+ wiphy->max_scan_ie_len = RSI_MAX_SCAN_IE_LEN;
wiphy->flags = WIPHY_FLAG_REPORTS_OBSS;
wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 01d99ed985ee..29d83049c5f5 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -121,11 +121,8 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
u32 pkt_len,
u8 extended_desc)
{
- struct ieee80211_tx_info *info;
struct sk_buff *skb = NULL;
u8 payload_offset;
- struct ieee80211_vif *vif;
- struct ieee80211_hdr *wh;
if (WARN(!pkt_len, "%s: Dummy pkt received", __func__))
return NULL;
@@ -144,10 +141,7 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
payload_offset = (extended_desc + FRAME_DESC_SZ);
skb_put(skb, pkt_len);
memcpy((skb->data), (buffer + payload_offset), skb->len);
- wh = (struct ieee80211_hdr *)skb->data;
- vif = rsi_get_vif(common->priv, wh->addr1);
- info = IEEE80211_SKB_CB(skb);
return skb;
}
@@ -328,6 +322,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
}
rsi_default_ps_params(adapter);
+ init_bgscan_params(common);
spin_lock_init(&adapter->ps_lock);
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
init_completion(&common->wlan_init_completion);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 1095df7d9573..844f2fac298f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -15,6 +15,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/timer.h>
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_ps.h"
@@ -236,6 +237,18 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->dtim_cnt = RSI_DTIM_COUNT;
}
+void init_bgscan_params(struct rsi_common *common)
+{
+ memset((u8 *)&common->bgscan, 0, sizeof(struct rsi_bgscan_params));
+ common->bgscan.bgscan_threshold = RSI_DEF_BGSCAN_THRLD;
+ common->bgscan.roam_threshold = RSI_DEF_ROAM_THRLD;
+ common->bgscan.bgscan_periodicity = RSI_BGSCAN_PERIODICITY;
+ common->bgscan.num_bgscan_channels = 0;
+ common->bgscan.two_probe = 1;
+ common->bgscan.active_scan_duration = RSI_ACTIVE_SCAN_TIME;
+ common->bgscan.passive_scan_duration = RSI_PASSIVE_SCAN_TIME;
+}
+
/**
* rsi_set_contention_vals() - This function sets the contention values for the
* backoff procedure.
@@ -396,8 +409,8 @@ static int rsi_load_radio_caps(struct rsi_common *common)
* rsi_mgmt_pkt_to_core() - This function is the entry point for Mgmt module.
* @common: Pointer to the driver private structure.
* @msg: Pointer to received packet.
- * @msg_len: Length of the recieved packet.
- * @type: Type of recieved packet.
+ * @msg_len: Length of the received packet.
+ * @type: Type of received packet.
*
* Return: 0 on success, -1 on failure.
*/
@@ -1534,7 +1547,7 @@ int rsi_send_ps_request(struct rsi_hw *adapter, bool enable,
}
/**
- * rsi_set_antenna() - This fuction send antenna configuration request
+ * rsi_set_antenna() - This function send antenna configuration request
* to device
*
* @common: Pointer to the driver private structure.
@@ -1628,6 +1641,111 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
}
#endif
+int rsi_send_bgscan_params(struct rsi_common *common, int enable)
+{
+ struct rsi_bgscan_params *params = &common->bgscan;
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_config *bgscan;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u8 i;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len);
+
+ bgscan = (struct rsi_bgscan_config *)skb->data;
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q);
+ bgscan->desc_dword0.frame_type = BG_SCAN_PARAMS;
+ bgscan->bgscan_threshold = cpu_to_le16(params->bgscan_threshold);
+ bgscan->roam_threshold = cpu_to_le16(params->roam_threshold);
+ if (enable)
+ bgscan->bgscan_periodicity =
+ cpu_to_le16(params->bgscan_periodicity);
+ bgscan->active_scan_duration =
+ cpu_to_le16(params->active_scan_duration);
+ bgscan->passive_scan_duration =
+ cpu_to_le16(params->passive_scan_duration);
+ bgscan->two_probe = params->two_probe;
+
+ bgscan->num_bgscan_channels = scan_req->n_channels;
+ for (i = 0; i < bgscan->num_bgscan_channels; i++)
+ bgscan->channels2scan[i] =
+ cpu_to_le16(scan_req->channels[i]->hw_value);
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/* This function sends the probe request to be used by firmware in
+ * background scan
+ */
+int rsi_send_bgscan_probe_req(struct rsi_common *common,
+ struct ieee80211_vif *vif)
+{
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_probe *bgscan;
+ struct sk_buff *skb;
+ struct sk_buff *probereq_skb;
+ u16 frame_len = sizeof(*bgscan);
+ size_t ssid_len = 0;
+ u8 *ssid = NULL;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending bgscan probe req frame\n", __func__);
+
+ if (common->priv->sc_nvifs <= 0)
+ return -ENODEV;
+
+ if (scan_req->n_ssids) {
+ ssid = scan_req->ssids[0].ssid;
+ ssid_len = scan_req->ssids[0].ssid_len;
+ }
+
+ skb = dev_alloc_skb(frame_len + MAX_BGSCAN_PROBE_REQ_LEN);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len + MAX_BGSCAN_PROBE_REQ_LEN);
+
+ bgscan = (struct rsi_bgscan_probe *)skb->data;
+ bgscan->desc_dword0.frame_type = BG_SCAN_PROBE_REQ;
+ bgscan->flags = cpu_to_le16(HOST_BG_SCAN_TRIG);
+ if (common->band == NL80211_BAND_5GHZ) {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_6);
+ bgscan->def_chan = cpu_to_le16(40);
+ } else {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_1);
+ bgscan->def_chan = cpu_to_le16(11);
+ }
+ bgscan->channel_scan_time = cpu_to_le16(RSI_CHANNEL_SCAN_TIME);
+
+ probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid,
+ ssid_len, scan_req->ie_len);
+ if (!probereq_skb) {
+ dev_kfree_skb(skb);
+ return -ENOMEM;
+ }
+
+ memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len);
+
+ bgscan->probe_req_length = cpu_to_le16(probereq_skb->len);
+
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ + probereq_skb->len),
+ RSI_WIFI_MGMT_Q);
+
+ skb_put(skb, frame_len + probereq_skb->len);
+
+ dev_kfree_skb(probereq_skb);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
@@ -1771,9 +1889,28 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
return 0;
}
break;
+
+ case SCAN_REQUEST:
+ rsi_dbg(INFO_ZONE, "Set channel confirm\n");
+ break;
+
case WAKEUP_SLEEP_REQUEST:
rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
return rsi_handle_ps_confirm(adapter, msg);
+
+ case BG_SCAN_PROBE_REQ:
+ rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+ if (common->bgscan_en) {
+ struct cfg80211_scan_info info;
+
+ if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ common->bgscan_en = 0;
+ info.aborted = false;
+ ieee80211_scan_completed(adapter->hw, &info);
+ }
+ rsi_dbg(INFO_ZONE, "Background scan completed\n");
+ break;
+
default:
rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n",
__func__);
@@ -1822,7 +1959,7 @@ int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
/**
* rsi_mgmt_pkt_recv() - This function processes the management packets
- * recieved from the hardware.
+ * received from the hardware.
* @common: Pointer to the driver private structure.
* @msg: Pointer to the received packet.
*
@@ -1870,6 +2007,35 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
return -1;
rsi_send_beacon(common);
break;
+ case WOWLAN_WAKEUP_REASON:
+ rsi_dbg(ERR_ZONE, "\n\nWakeup Type: %x\n", msg[15]);
+ switch (msg[15]) {
+ case RSI_UNICAST_MAGIC_PKT:
+ rsi_dbg(ERR_ZONE,
+ "*** Wakeup for Unicast magic packet ***\n");
+ break;
+ case RSI_BROADCAST_MAGICPKT:
+ rsi_dbg(ERR_ZONE,
+ "*** Wakeup for Broadcast magic packet ***\n");
+ break;
+ case RSI_EAPOL_PKT:
+ rsi_dbg(ERR_ZONE,
+ "*** Wakeup for GTK renewal ***\n");
+ break;
+ case RSI_DISCONNECT_PKT:
+ rsi_dbg(ERR_ZONE,
+ "*** Wakeup for Disconnect ***\n");
+ break;
+ case RSI_HW_BMISS_PKT:
+ rsi_dbg(ERR_ZONE,
+ "*** Wakeup for HW Beacon miss ***\n");
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "##### Un-intentional Wakeup #####\n");
+ break;
+ }
+ break;
case RX_DOT11_MGMT:
return rsi_mgmt_pkt_to_core(common, msg, msg_len);
default:
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 5733e440ecaf..3430d7a0899e 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -138,7 +138,7 @@ static int rsi_issue_sdiocommand(struct sdio_func *func,
}
/**
- * rsi_handle_interrupt() - This function is called upon the occurence
+ * rsi_handle_interrupt() - This function is called upon the occurrence
* of an interrupt.
* @function: Pointer to the sdio_func structure.
*
@@ -230,16 +230,19 @@ static void rsi_reset_card(struct sdio_func *pfunction)
rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
/* Issue CMD5, arg = 0 */
- err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0,
- (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
- if (err)
- rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", __func__, err);
- card->ocr = resp;
+ if (!host->ocr_avail) {
+ err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0,
+ (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
+ if (err)
+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ __func__, err);
+ host->ocr_avail = resp;
+ }
/* Issue CMD5, arg = ocr. Wait till card is ready */
for (i = 0; i < 100; i++) {
err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND,
- card->ocr,
+ host->ocr_avail,
(MMC_RSP_R4 | MMC_CMD_BCR), &resp);
if (err) {
rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
@@ -872,7 +875,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
goto fail;
}
- rsi_dbg(INIT_ZONE, "%s: Setup card succesfully\n", __func__);
+ rsi_dbg(INIT_ZONE, "%s: Setup card successfully\n", __func__);
status = rsi_init_sdio_slave_regs(adapter);
if (status) {
@@ -1129,6 +1132,12 @@ static void rsi_disconnect(struct sdio_func *pfunction)
rsi_mac80211_detach(adapter);
mdelay(10);
+ if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
+ adapter->priv->bt_adapter) {
+ rsi_bt_ops.detach(adapter->priv->bt_adapter);
+ adapter->priv->bt_adapter = NULL;
+ }
+
/* Reset Chip */
rsi_reset_chip(adapter);
@@ -1305,6 +1314,12 @@ static int rsi_freeze(struct device *dev)
rsi_dbg(ERR_ZONE,
"##### Device can not wake up through WLAN\n");
+ if (IS_ENABLED(CONFIG_RSI_COEX) && common->coex_mode > 1 &&
+ common->bt_adapter) {
+ rsi_bt_ops.detach(common->bt_adapter);
+ common->bt_adapter = NULL;
+ }
+
ret = rsi_sdio_disable_interrupts(pfunction);
if (sdev->write_fail)
@@ -1352,6 +1367,12 @@ static void rsi_shutdown(struct device *dev)
if (rsi_config_wowlan(adapter, wowlan))
rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
+ if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
+ adapter->priv->bt_adapter) {
+ rsi_bt_ops.detach(adapter->priv->bt_adapter);
+ adapter->priv->bt_adapter = NULL;
+ }
+
rsi_sdio_disable_interrupts(sdev->pfunction);
if (sdev->write_fail)
@@ -1375,7 +1396,7 @@ static int rsi_restore(struct device *dev)
common->iface_down = true;
adapter->sc_nvifs = 0;
- ieee80211_restart_hw(adapter->hw);
+ adapter->ps_state = PS_NONE;
common->wow_flags = 0;
common->iface_down = false;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index f360690396dd..ac0ef5ea6ffb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -252,7 +252,7 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
/**
* rsi_rx_done_handler() - This function is called when a packet is received
- * from USB stack. This is callback to recieve done.
+ * from USB stack. This is callback to receive done.
* @urb: Received URB.
*
* Return: None.
@@ -816,6 +816,13 @@ static void rsi_disconnect(struct usb_interface *pfunction)
return;
rsi_mac80211_detach(adapter);
+
+ if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
+ adapter->priv->bt_adapter) {
+ rsi_bt_ops.detach(adapter->priv->bt_adapter);
+ adapter->priv->bt_adapter = NULL;
+ }
+
rsi_reset_card(adapter);
rsi_deinit_usb_interface(adapter);
rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index a084f224bb03..35d13f35e9b0 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -164,6 +164,24 @@ struct transmit_q_stats {
u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 2];
};
+#define MAX_BGSCAN_CHANNELS_DUAL_BAND 38
+#define MAX_BGSCAN_PROBE_REQ_LEN 0x64
+#define RSI_DEF_BGSCAN_THRLD 0x0
+#define RSI_DEF_ROAM_THRLD 0xa
+#define RSI_BGSCAN_PERIODICITY 0x1e
+#define RSI_ACTIVE_SCAN_TIME 0x14
+#define RSI_PASSIVE_SCAN_TIME 0x46
+#define RSI_CHANNEL_SCAN_TIME 20
+struct rsi_bgscan_params {
+ u16 bgscan_threshold;
+ u16 roam_threshold;
+ u16 bgscan_periodicity;
+ u8 num_bgscan_channels;
+ u8 two_probe;
+ u16 active_scan_duration;
+ u16 passive_scan_duration;
+};
+
struct vif_priv {
bool is_ht;
bool sgi;
@@ -289,6 +307,11 @@ struct rsi_common {
bool eapol4_confirm;
void *bt_adapter;
+
+ struct cfg80211_scan_request *hwscan;
+ struct rsi_bgscan_params bgscan;
+ u8 bgscan_en;
+ u8 mac_ops_resumed;
};
struct eepromrw_info {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 359fbdf85739..ea83faa15c7e 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -228,6 +228,9 @@
#define RSI_MAX_TX_AGGR_FRMS 8
#define RSI_MAX_RX_AGGR_FRMS 8
+#define RSI_MAX_SCAN_SSIDS 16
+#define RSI_MAX_SCAN_IE_LEN 256
+
enum opmode {
RSI_OPMODE_UNSUPPORTED = -1,
RSI_OPMODE_AP = 0,
@@ -623,6 +626,34 @@ struct rsi_wowlan_req {
u16 host_sleep_status;
} __packed;
+#define RSI_START_BGSCAN 1
+#define RSI_STOP_BGSCAN 0
+#define HOST_BG_SCAN_TRIG BIT(4)
+struct rsi_bgscan_config {
+ struct rsi_cmd_desc_dword0 desc_dword0;
+ __le64 reserved;
+ __le32 reserved1;
+ __le16 bgscan_threshold;
+ __le16 roam_threshold;
+ __le16 bgscan_periodicity;
+ u8 num_bgscan_channels;
+ u8 two_probe;
+ __le16 active_scan_duration;
+ __le16 passive_scan_duration;
+ __le16 channels2scan[MAX_BGSCAN_CHANNELS_DUAL_BAND];
+} __packed;
+
+struct rsi_bgscan_probe {
+ struct rsi_cmd_desc_dword0 desc_dword0;
+ __le64 reserved;
+ __le32 reserved1;
+ __le16 mgmt_rate;
+ __le16 flags;
+ __le16 def_chan;
+ __le16 channel_scan_time;
+ __le16 probe_req_length;
+} __packed;
+
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
{
return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -694,4 +725,8 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
#endif
int rsi_send_ps_request(struct rsi_hw *adapter, bool enable,
struct ieee80211_vif *vif);
+void init_bgscan_params(struct rsi_common *common);
+int rsi_send_bgscan_params(struct rsi_common *common, int enable);
+int rsi_send_bgscan_probe_req(struct rsi_common *common,
+ struct ieee80211_vif *vif);
#endif
diff --git a/drivers/net/wireless/st/cw1200/debug.c b/drivers/net/wireless/st/cw1200/debug.c
index 2231ba08bc1f..d94266d9d0b8 100644
--- a/drivers/net/wireless/st/cw1200/debug.c
+++ b/drivers/net/wireless/st/cw1200/debug.c
@@ -371,28 +371,14 @@ int cw1200_debug_init(struct cw1200_common *priv)
d->debugfs_phy = debugfs_create_dir("cw1200",
priv->hw->wiphy->debugfsdir);
- if (!d->debugfs_phy)
- goto err;
-
- if (!debugfs_create_file("status", 0400, d->debugfs_phy,
- priv, &cw1200_status_fops))
- goto err;
-
- if (!debugfs_create_file("counters", 0400, d->debugfs_phy,
- priv, &cw1200_counters_fops))
- goto err;
-
- if (!debugfs_create_file("wsm_dumps", 0200, d->debugfs_phy,
- priv, &fops_wsm_dumps))
- goto err;
+ debugfs_create_file("status", 0400, d->debugfs_phy, priv,
+ &cw1200_status_fops);
+ debugfs_create_file("counters", 0400, d->debugfs_phy, priv,
+ &cw1200_counters_fops);
+ debugfs_create_file("wsm_dumps", 0200, d->debugfs_phy, priv,
+ &fops_wsm_dumps);
return 0;
-
-err:
- priv->debug = NULL;
- debugfs_remove_recursive(d->debugfs_phy);
- kfree(d);
- return ret;
}
void cw1200_debug_release(struct cw1200_common *priv)
diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c
index 30e7646d04af..b7881232499c 100644
--- a/drivers/net/wireless/st/cw1200/fwio.c
+++ b/drivers/net/wireless/st/cw1200/fwio.c
@@ -465,8 +465,8 @@ int cw1200_load_firmware(struct cw1200_common *priv)
if (!(val32 & ST90TDS_CONFIG_ACCESS_MODE_BIT)) {
pr_err("Device is already in QUEUE mode!\n");
- ret = -EINVAL;
- goto out;
+ ret = -EINVAL;
+ goto out;
}
switch (priv->hw_type) {
diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c
index 7c31b63b8258..7895efefa95d 100644
--- a/drivers/net/wireless/st/cw1200/queue.c
+++ b/drivers/net/wireless/st/cw1200/queue.c
@@ -283,7 +283,6 @@ int cw1200_queue_put(struct cw1200_queue *queue,
struct cw1200_txpriv *txpriv)
{
int ret = 0;
- LIST_HEAD(gc_list);
struct cw1200_queue_stats *stats = queue->stats;
if (txpriv->link_id >= queue->stats->map_capacity)
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index 0a9eac93dd01..71e9b91cf15b 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -84,8 +84,11 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
req->ie_len);
- if (!frame.skb)
+ if (!frame.skb) {
+ mutex_unlock(&priv->conf_mutex);
+ up(&priv->scan.lock);
return -ENOMEM;
+ }
if (req->ie_len)
skb_put_data(frame.skb, req->ie, req->ie_len);
diff --git a/drivers/net/wireless/ti/wl1251/debugfs.c b/drivers/net/wireless/ti/wl1251/debugfs.c
index 448da1f8c22f..c99b23aaa70e 100644
--- a/drivers/net/wireless/ti/wl1251/debugfs.c
+++ b/drivers/net/wireless/ti/wl1251/debugfs.c
@@ -54,11 +54,6 @@ static const struct file_operations name## _ops = { \
#define DEBUGFS_ADD(name, parent) \
wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \
wl, &name## _ops); \
- if (IS_ERR(wl->debugfs.name)) { \
- ret = PTR_ERR(wl->debugfs.name); \
- wl->debugfs.name = NULL; \
- goto out; \
- }
#define DEBUGFS_DEL(name) \
do { \
@@ -354,10 +349,8 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl)
DEBUGFS_DEL(excessive_retries);
}
-static int wl1251_debugfs_add_files(struct wl1251 *wl)
+static void wl1251_debugfs_add_files(struct wl1251 *wl)
{
- int ret = 0;
-
DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
@@ -453,12 +446,6 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl)
DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
-
-out:
- if (ret < 0)
- wl1251_debugfs_delete_files(wl);
-
- return ret;
}
void wl1251_debugfs_reset(struct wl1251 *wl)
@@ -471,56 +458,20 @@ void wl1251_debugfs_reset(struct wl1251 *wl)
int wl1251_debugfs_init(struct wl1251 *wl)
{
- int ret;
+ wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), GFP_KERNEL);
+ if (!wl->stats.fw_stats)
+ return -ENOMEM;
wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (IS_ERR(wl->debugfs.rootdir)) {
- ret = PTR_ERR(wl->debugfs.rootdir);
- wl->debugfs.rootdir = NULL;
- goto err;
- }
-
wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
wl->debugfs.rootdir);
- if (IS_ERR(wl->debugfs.fw_statistics)) {
- ret = PTR_ERR(wl->debugfs.fw_statistics);
- wl->debugfs.fw_statistics = NULL;
- goto err_root;
- }
-
- wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
- GFP_KERNEL);
-
- if (!wl->stats.fw_stats) {
- ret = -ENOMEM;
- goto err_fw;
- }
-
wl->stats.fw_stats_update = jiffies;
- ret = wl1251_debugfs_add_files(wl);
-
- if (ret < 0)
- goto err_file;
+ wl1251_debugfs_add_files(wl);
return 0;
-
-err_file:
- kfree(wl->stats.fw_stats);
- wl->stats.fw_stats = NULL;
-
-err_fw:
- debugfs_remove(wl->debugfs.fw_statistics);
- wl->debugfs.fw_statistics = NULL;
-
-err_root:
- debugfs_remove(wl->debugfs.rootdir);
- wl->debugfs.rootdir = NULL;
-
-err:
- return ret;
}
void wl1251_debugfs_exit(struct wl1251 *wl)
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c
index 0521cbf858cf..6c3c04eca8fd 100644
--- a/drivers/net/wireless/ti/wl12xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl12xx/debugfs.c
@@ -125,20 +125,10 @@ WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u");
int wl12xx_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
- int ret = 0;
- struct dentry *entry, *stats, *moddir;
+ struct dentry *stats, *moddir;
moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir);
- if (!moddir || IS_ERR(moddir)) {
- entry = moddir;
- goto err;
- }
-
stats = debugfs_create_dir("fw_stats", moddir);
- if (!stats || IS_ERR(stats)) {
- entry = stats;
- goto err;
- }
DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
@@ -232,12 +222,4 @@ int wl12xx_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
return 0;
-
-err:
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- ret = -ENOMEM;
-
- return ret;
}
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c
index 597e934c4630..5f4ec997ca59 100644
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -422,20 +422,10 @@ static const struct file_operations radar_debug_mode_ops = {
int wl18xx_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
- int ret = 0;
- struct dentry *entry, *stats, *moddir;
+ struct dentry *stats, *moddir;
moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir);
- if (!moddir || IS_ERR(moddir)) {
- entry = moddir;
- goto err;
- }
-
stats = debugfs_create_dir("fw_stats", moddir);
- if (!stats || IS_ERR(stats)) {
- entry = stats;
- goto err;
- }
DEBUGFS_ADD(clear_fw_stats, stats);
@@ -590,12 +580,4 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(dynamic_fw_traces, moddir);
return 0;
-
-err:
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- ret = -ENOMEM;
-
- return ret;
}
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 903968735a74..348be0aed97e 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1427,7 +1427,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("could not set keys");
- goto out;
+ goto out;
}
out:
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index aeb74e74698e..68acd901d384 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -1301,11 +1301,10 @@ static const struct file_operations fw_logger_ops = {
.llseek = default_llseek,
};
-static int wl1271_debugfs_add_files(struct wl1271 *wl,
- struct dentry *rootdir)
+static void wl1271_debugfs_add_files(struct wl1271 *wl,
+ struct dentry *rootdir)
{
- int ret = 0;
- struct dentry *entry, *streaming;
+ struct dentry *streaming;
DEBUGFS_ADD(tx_queue_len, rootdir);
DEBUGFS_ADD(retry_count, rootdir);
@@ -1330,23 +1329,11 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(fw_logger, rootdir);
streaming = debugfs_create_dir("rx_streaming", rootdir);
- if (!streaming || IS_ERR(streaming))
- goto err;
DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
-
- return 0;
-
-err:
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- ret = -ENOMEM;
-
- return ret;
}
void wl1271_debugfs_reset(struct wl1271 *wl)
@@ -1367,11 +1354,6 @@ int wl1271_debugfs_init(struct wl1271 *wl)
rootdir = debugfs_create_dir(KBUILD_MODNAME,
wl->hw->wiphy->debugfsdir);
- if (IS_ERR(rootdir)) {
- ret = PTR_ERR(rootdir);
- goto out;
- }
-
wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL);
if (!wl->stats.fw_stats) {
ret = -ENOMEM;
@@ -1380,9 +1362,7 @@ int wl1271_debugfs_init(struct wl1271 *wl)
wl->stats.fw_stats_update = jiffies;
- ret = wl1271_debugfs_add_files(wl, rootdir);
- if (ret < 0)
- goto out_exit;
+ wl1271_debugfs_add_files(wl, rootdir);
ret = wlcore_debugfs_init(wl, rootdir);
if (ret < 0)
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h
index bf14676e6515..a4952c4f587e 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.h
+++ b/drivers/net/wireless/ti/wlcore/debugfs.h
@@ -53,19 +53,15 @@ static const struct file_operations name## _ops = { \
#define DEBUGFS_ADD(name, parent) \
do { \
- entry = debugfs_create_file(#name, 0400, parent, \
- wl, &name## _ops); \
- if (!entry || IS_ERR(entry)) \
- goto err; \
+ debugfs_create_file(#name, 0400, parent, \
+ wl, &name## _ops); \
} while (0)
#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
do { \
- entry = debugfs_create_file(#name, 0400, parent, \
+ debugfs_create_file(#name, 0400, parent, \
wl, &prefix## _## name## _ops); \
- if (!entry || IS_ERR(entry)) \
- goto err; \
} while (0)
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 26b187336875..2e12de813a5b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1085,8 +1085,11 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
goto out;
ret = wl12xx_fetch_firmware(wl, plt);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ kfree(wl->fw_status);
+ kfree(wl->raw_fw_status);
+ kfree(wl->tx_res_if);
+ }
out:
return ret;
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index bd10165d7eec..4d4b07701149 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -164,6 +164,12 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
}
sdio_claim_host(func);
+ /*
+ * To guarantee that the SDIO card is power cycled, as required to make
+ * the FW programming to succeed, let's do a brute force HW reset.
+ */
+ mmc_hw_reset(card->host);
+
sdio_enable_func(func);
sdio_release_host(func);
@@ -174,20 +180,13 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
{
struct sdio_func *func = dev_to_sdio_func(glue->dev);
struct mmc_card *card = func->card;
- int error;
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
/* Let runtime PM know the card is powered off */
- error = pm_runtime_put(&card->dev);
- if (error < 0 && error != -EBUSY) {
- dev_err(&card->dev, "%s failed: %i\n", __func__, error);
-
- return error;
- }
-
+ pm_runtime_put(&card->dev);
return 0;
}
diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c
index 64b218699656..606999f102eb 100644
--- a/drivers/net/wireless/virt_wifi.c
+++ b/drivers/net/wireless/virt_wifi.c
@@ -14,11 +14,6 @@
#include <linux/etherdevice.h>
#include <linux/module.h>
-#include <net/cfg80211.h>
-#include <net/rtnetlink.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-
static struct wiphy *common_wiphy;
struct virt_wifi_wiphy_priv {
@@ -365,7 +360,6 @@ static struct wiphy *virt_wifi_make_wiphy(void)
wiphy->bands[NL80211_BAND_5GHZ] = &band_5ghz;
wiphy->bands[NL80211_BAND_60GHZ] = NULL;
- wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
priv = wiphy_priv(wiphy);
@@ -429,13 +423,11 @@ static int virt_wifi_net_device_open(struct net_device *dev)
static int virt_wifi_net_device_stop(struct net_device *dev)
{
struct virt_wifi_netdev_priv *n_priv = netdev_priv(dev);
- struct virt_wifi_wiphy_priv *w_priv;
n_priv->is_up = false;
if (!dev->ieee80211_ptr)
return 0;
- w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy);
virt_wifi_cancel_connect(dev);
@@ -530,8 +522,10 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
- if (!dev->ieee80211_ptr)
+ if (!dev->ieee80211_ptr) {
+ err = -ENOMEM;
goto remove_handler;
+ }
dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
dev->ieee80211_ptr->wiphy = common_wiphy;
diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c
index 0ccb021f1e78..10d580c3dea3 100644
--- a/drivers/net/xen-netback/hash.c
+++ b/drivers/net/xen-netback/hash.c
@@ -454,6 +454,8 @@ void xenvif_init_hash(struct xenvif *vif)
if (xenvif_hash_cache_size == 0)
return;
+ BUG_ON(vif->hash.cache.count);
+
spin_lock_init(&vif->hash.cache.lock);
INIT_LIST_HEAD(&vif->hash.cache.list);
}
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 182d6770f102..6da12518e693 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -153,6 +153,13 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
{
struct xenvif *vif = netdev_priv(dev);
unsigned int size = vif->hash.size;
+ unsigned int num_queues;
+
+ /* If queues are not set up internally - always return 0
+ * as the packet going to be dropped anyway */
+ num_queues = READ_ONCE(vif->num_queues);
+ if (num_queues < 1)
+ return 0;
if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
return fallback(dev, skb, NULL) % dev->real_num_tx_queues;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a32c2a..1d9940d4e8c7 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
skb_frag_size_set(&frags[i], len);
}
- /* Copied all the bits from the frag list -- free it. */
- skb_frag_list_init(skb);
- xenvif_skb_zerocopy_prepare(queue, nskb);
- kfree_skb(nskb);
-
/* Release all the original (foreign) frags. */
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
skb_frag_unref(skb, f);
@@ -1145,6 +1140,8 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
xenvif_fill_frags(queue, skb);
if (unlikely(skb_has_frag_list(skb))) {
+ struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
+ xenvif_skb_zerocopy_prepare(queue, nskb);
if (xenvif_handle_frag_list(queue, skb)) {
if (net_ratelimit())
netdev_err(queue->vif->dev,
@@ -1153,6 +1150,9 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
kfree_skb(skb);
continue;
}
+ /* Copied all the bits from the frag list -- free it. */
+ skb_frag_list_init(skb);
+ kfree_skb(nskb);
}
skb->dev = queue->vif->dev;
@@ -1169,15 +1169,24 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
continue;
}
- skb_probe_transport_header(skb, 0);
+ skb_probe_transport_header(skb);
/* If the packet is GSO then we will have just set up the
* transport header offset in checksum_setup so it's now
* straightforward to calculate gso_segs.
*/
if (skb_is_gso(skb)) {
- int mss = skb_shinfo(skb)->gso_size;
- int hdrlen = skb_transport_header(skb) -
+ int mss, hdrlen;
+
+ /* GSO implies having the L4 header. */
+ WARN_ON_ONCE(!skb_transport_header_was_set(skb));
+ if (unlikely(!skb_transport_header_was_set(skb))) {
+ kfree_skb(skb);
+ continue;
+ }
+
+ mss = skb_shinfo(skb)->gso_size;
+ hdrlen = skb_transport_header(skb) -
skb_mac_header(skb) +
tcp_hdrlen(skb);
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 2625740bdc4a..330ddb64930f 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -655,7 +655,7 @@ static void frontend_changed(struct xenbus_device *dev,
set_backend_state(be, XenbusStateClosed);
if (xenbus_dev_is_online(dev))
break;
- /* fall through if not online */
+ /* fall through - if not online */
case XenbusStateUnknown:
set_backend_state(be, XenbusStateClosed);
device_unregister(&dev->dev);
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.h b/drivers/ntb/hw/intel/ntb_hw_intel.h
index c49ff8970ce3..e071e28bca3f 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.h
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.h
@@ -53,6 +53,7 @@
#include <linux/ntb.h>
#include <linux/pci.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
/* PCI device IDs */
#define PCI_DEVICE_ID_INTEL_NTB_B2B_JSF 0x3725
@@ -218,33 +219,4 @@ static inline int pdev_is_gen3(struct pci_dev *pdev)
return 0;
}
-#ifndef ioread64
-#ifdef readq
-#define ioread64 readq
-#else
-#define ioread64 _ioread64
-static inline u64 _ioread64(void __iomem *mmio)
-{
- u64 low, high;
-
- low = ioread32(mmio);
- high = ioread32(mmio + sizeof(u32));
- return low | (high << 32);
-}
-#endif
-#endif
-
-#ifndef iowrite64
-#ifdef writeq
-#define iowrite64 writeq
-#else
-#define iowrite64 _iowrite64
-static inline void _iowrite64(u64 val, void __iomem *mmio)
-{
- iowrite32(val, mmio);
- iowrite32(val >> 32, mmio + sizeof(u32));
-}
-#endif
-#endif
-
#endif
diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 5ee5f40b4dfc..f2df2d39c65b 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -13,13 +13,14 @@
*
*/
-#include <linux/switchtec.h>
-#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/delay.h>
#include <linux/kthread.h>
-#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/ntb.h>
#include <linux/pci.h>
+#include <linux/switchtec.h>
MODULE_DESCRIPTION("Microsemi Switchtec(tm) NTB Driver");
MODULE_VERSION("0.1");
@@ -36,35 +37,6 @@ module_param(use_lut_mws, bool, 0644);
MODULE_PARM_DESC(use_lut_mws,
"Enable the use of the LUT based memory windows");
-#ifndef ioread64
-#ifdef readq
-#define ioread64 readq
-#else
-#define ioread64 _ioread64
-static inline u64 _ioread64(void __iomem *mmio)
-{
- u64 low, high;
-
- low = ioread32(mmio);
- high = ioread32(mmio + sizeof(u32));
- return low | (high << 32);
-}
-#endif
-#endif
-
-#ifndef iowrite64
-#ifdef writeq
-#define iowrite64 writeq
-#else
-#define iowrite64 _iowrite64
-static inline void _iowrite64(u64 val, void __iomem *mmio)
-{
- iowrite32(val, mmio);
- iowrite32(val >> 32, mmio + sizeof(u32));
-}
-#endif
-#endif
-
#define SWITCHTEC_NTB_MAGIC 0x45CC0001
#define MAX_MWS 128
@@ -1339,10 +1311,10 @@ static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev)
int rc;
sndev->nr_rsvd_luts++;
- sndev->self_shared = dma_zalloc_coherent(&sndev->stdev->pdev->dev,
- LUT_SIZE,
- &sndev->self_shared_dma,
- GFP_KERNEL);
+ sndev->self_shared = dma_alloc_coherent(&sndev->stdev->pdev->dev,
+ LUT_SIZE,
+ &sndev->self_shared_dma,
+ GFP_KERNEL);
if (!sndev->self_shared) {
dev_err(&sndev->stdev->dev,
"unable to allocate memory for shared mw\n");
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index dca5f7a805cb..7bbff0af29b2 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -23,6 +23,7 @@
#include <linux/ndctl.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/cpu.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -534,11 +535,15 @@ void __nd_device_register(struct device *dev)
set_dev_node(dev, to_nd_region(dev)->numa_node);
dev->bus = &nvdimm_bus_type;
- if (dev->parent)
+ if (dev->parent) {
get_device(dev->parent);
+ if (dev_to_node(dev) == NUMA_NO_NODE)
+ set_dev_node(dev, dev_to_node(dev->parent));
+ }
get_device(dev);
- async_schedule_domain(nd_async_device_register, dev,
- &nd_async_domain);
+
+ async_schedule_dev_domain(nd_async_device_register, dev,
+ &nd_async_domain);
}
void nd_device_register(struct device *dev)
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index 0cf58cabc9ed..3cf50274fadb 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -26,6 +26,12 @@ static int nvdimm_probe(struct device *dev)
struct nvdimm_drvdata *ndd;
int rc;
+ rc = nvdimm_security_setup_events(dev);
+ if (rc < 0) {
+ dev_err(dev, "security event setup failed: %d\n", rc);
+ return rc;
+ }
+
rc = nvdimm_check_config_data(dev);
if (rc) {
/* not required for non-aliased nvdimm, ex. NVDIMM-N */
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 4890310df874..efe412a6b5b9 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -578,13 +578,25 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
}
EXPORT_SYMBOL_GPL(__nvdimm_create);
-int nvdimm_security_setup_events(struct nvdimm *nvdimm)
+static void shutdown_security_notify(void *data)
{
- nvdimm->sec.overwrite_state = sysfs_get_dirent(nvdimm->dev.kobj.sd,
- "security");
+ struct nvdimm *nvdimm = data;
+
+ sysfs_put(nvdimm->sec.overwrite_state);
+}
+
+int nvdimm_security_setup_events(struct device *dev)
+{
+ struct nvdimm *nvdimm = to_nvdimm(dev);
+
+ if (nvdimm->sec.state < 0 || !nvdimm->sec.ops
+ || !nvdimm->sec.ops->overwrite)
+ return 0;
+ nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
if (!nvdimm->sec.overwrite_state)
- return -ENODEV;
- return 0;
+ return -ENOMEM;
+
+ return devm_add_action_or_reset(dev, shutdown_security_notify, nvdimm);
}
EXPORT_SYMBOL_GPL(nvdimm_security_setup_events);
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 2b2cf4e554d3..e5ffd5733540 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -54,12 +54,12 @@ struct nvdimm {
};
static inline enum nvdimm_security_state nvdimm_security_state(
- struct nvdimm *nvdimm, bool master)
+ struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
{
if (!nvdimm->sec.ops)
return -ENXIO;
- return nvdimm->sec.ops->state(nvdimm, master);
+ return nvdimm->sec.ops->state(nvdimm, ptype);
}
int nvdimm_security_freeze(struct nvdimm *nvdimm);
#if IS_ENABLED(CONFIG_NVDIMM_KEYS)
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index cfde992684e7..379bf4305e61 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -250,6 +250,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
void nvdimm_set_aliasing(struct device *dev);
void nvdimm_set_locked(struct device *dev);
void nvdimm_clear_locked(struct device *dev);
+int nvdimm_security_setup_events(struct device *dev);
#if IS_ENABLED(CONFIG_NVDIMM_KEYS)
int nvdimm_security_unlock(struct device *dev);
#else
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 08f2c92602f4..6a9dd68c0f4f 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1253,6 +1253,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
* effects say only one namespace is affected.
*/
if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+ mutex_lock(&ctrl->scan_lock);
nvme_start_freeze(ctrl);
nvme_wait_freeze(ctrl);
}
@@ -1281,8 +1282,10 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
*/
if (effects & NVME_CMD_EFFECTS_LBCC)
nvme_update_formats(ctrl);
- if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK))
+ if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
nvme_unfreeze(ctrl);
+ mutex_unlock(&ctrl->scan_lock);
+ }
if (effects & NVME_CMD_EFFECTS_CCC)
nvme_init_identify(ctrl);
if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
@@ -2173,18 +2176,20 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct
size_t nqnlen;
int off;
- nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
- if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
- strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
- return;
- }
+ if(!(ctrl->quirks & NVME_QUIRK_IGNORE_DEV_SUBNQN)) {
+ nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
+ if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
+ strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
+ return;
+ }
- if (ctrl->vs >= NVME_VS(1, 2, 1))
- dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+ 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(subsys->subnqn, NVMF_NQN_SIZE,
- "nqn.2014.08.org.nvmexpress:%4x%4x",
+ "nqn.2014.08.org.nvmexpress:%04x%04x",
le16_to_cpu(id->vid), le16_to_cpu(id->ssvid));
memcpy(subsys->subnqn + off, id->sn, sizeof(id->sn));
off += sizeof(id->sn);
@@ -2500,7 +2505,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ctrl->oaes = le32_to_cpu(id->oaes);
atomic_set(&ctrl->abort_limit, id->acl + 1);
ctrl->vwc = id->vwc;
- ctrl->cntlid = le16_to_cpup(&id->cntlid);
if (id->mdts)
max_hw_sectors = 1 << (id->mdts + page_shift - 9);
else
@@ -3400,6 +3404,7 @@ static void nvme_scan_work(struct work_struct *work)
if (nvme_identify_ctrl(ctrl, &id))
return;
+ mutex_lock(&ctrl->scan_lock);
nn = le32_to_cpu(id->nn);
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
!(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
@@ -3408,6 +3413,7 @@ static void nvme_scan_work(struct work_struct *work)
}
nvme_scan_ns_sequential(ctrl, nn);
out_free_id:
+ mutex_unlock(&ctrl->scan_lock);
kfree(id);
down_write(&ctrl->namespaces_rwsem);
list_sort(NULL, &ctrl->namespaces, ns_cmp);
@@ -3651,6 +3657,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
ctrl->state = NVME_CTRL_NEW;
spin_lock_init(&ctrl->lock);
+ mutex_init(&ctrl->scan_lock);
INIT_LIST_HEAD(&ctrl->namespaces);
init_rwsem(&ctrl->namespaces_rwsem);
ctrl->dev = dev;
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index b2ab213f43de..3eb908c50e1a 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -874,6 +874,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
if (opts->discovery_nqn) {
opts->kato = 0;
opts->nr_io_queues = 0;
+ opts->nr_write_queues = 0;
+ opts->nr_poll_queues = 0;
opts->duplicate_connect = true;
}
if (ctrl_loss_tmo < 0)
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 183ec17ba067..b9fff3b8ed1b 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -545,8 +545,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
- if (!(ctrl->anacap & (1 << 6)))
- ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
+ ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
dev_err(ctrl->device,
@@ -570,6 +569,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
return 0;
out_free_ana_log_buf:
kfree(ctrl->ana_log_buf);
+ ctrl->ana_log_buf = NULL;
out:
return error;
}
@@ -577,5 +577,6 @@ out:
void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
{
kfree(ctrl->ana_log_buf);
+ ctrl->ana_log_buf = NULL;
}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 2b36ac922596..c4a1bb41abf0 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -90,6 +90,11 @@ enum nvme_quirks {
* Set MEDIUM priority on SQ creation
*/
NVME_QUIRK_MEDIUM_PRIO_SQ = (1 << 7),
+
+ /*
+ * Ignore device provided subnqn.
+ */
+ NVME_QUIRK_IGNORE_DEV_SUBNQN = (1 << 8),
};
/*
@@ -149,6 +154,7 @@ struct nvme_ctrl {
enum nvme_ctrl_state state;
bool identified;
spinlock_t lock;
+ struct mutex scan_lock;
const struct nvme_ctrl_ops *ops;
struct request_queue *admin_q;
struct request_queue *connect_q;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5a0bf6a24d50..e905861186e3 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -95,6 +95,7 @@ struct nvme_dev;
struct nvme_queue;
static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode);
/*
* Represents an NVM Express device. Each nvme_dev is a PCI function.
@@ -1019,9 +1020,11 @@ static void nvme_complete_cqes(struct nvme_queue *nvmeq, u16 start, u16 end)
static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
{
- if (++nvmeq->cq_head == nvmeq->q_depth) {
+ if (nvmeq->cq_head == nvmeq->q_depth - 1) {
nvmeq->cq_head = 0;
nvmeq->cq_phase = !nvmeq->cq_phase;
+ } else {
+ nvmeq->cq_head++;
}
}
@@ -1420,6 +1423,14 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
return 0;
}
+static void nvme_suspend_io_queues(struct nvme_dev *dev)
+{
+ int i;
+
+ for (i = dev->ctrl.queue_count - 1; i > 0; i--)
+ nvme_suspend_queue(&dev->queues[i]);
+}
+
static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
{
struct nvme_queue *nvmeq = &dev->queues[0];
@@ -1485,8 +1496,8 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
if (dev->ctrl.queue_count > qid)
return 0;
- nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth),
- &nvmeq->cq_dma_addr, GFP_KERNEL);
+ nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth),
+ &nvmeq->cq_dma_addr, GFP_KERNEL);
if (!nvmeq->cqes)
goto free_nvmeq;
@@ -1885,8 +1896,9 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
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));
+ dma_free_attrs(dev->dev, size, dev->host_mem_desc_bufs[i],
+ le64_to_cpu(desc->addr),
+ DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
}
kfree(dev->host_mem_desc_bufs);
@@ -1915,8 +1927,8 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
max_entries = dev->ctrl.hmmaxd;
- descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs),
- &descs_dma, GFP_KERNEL);
+ descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
+ &descs_dma, GFP_KERNEL);
if (!descs)
goto out;
@@ -1952,8 +1964,9 @@ 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));
+ dma_free_attrs(dev->dev, size, bufs[i],
+ le64_to_cpu(descs[i].addr),
+ DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
}
kfree(bufs);
@@ -2028,49 +2041,52 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
return ret;
}
-static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
+/*
+ * nirqs is the number of interrupts available for write and read
+ * queues. The core already reserved an interrupt for the admin queue.
+ */
+static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs)
{
- unsigned int this_w_queues = write_queues;
-
- /*
- * Setup read/write queue split
- */
- if (irq_queues == 1) {
- dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
- dev->io_queues[HCTX_TYPE_READ] = 0;
- return;
- }
-
- /*
- * If 'write_queues' is set, ensure it leaves room for at least
- * one read queue
- */
- if (this_w_queues >= irq_queues)
- this_w_queues = irq_queues - 1;
+ struct nvme_dev *dev = affd->priv;
+ unsigned int nr_read_queues;
/*
- * If 'write_queues' is set to zero, reads and writes will share
- * a queue set.
+ * If there is no interupt available for queues, ensure that
+ * the default queue is set to 1. The affinity set size is
+ * also set to one, but the irq core ignores it for this case.
+ *
+ * If only one interrupt is available or 'write_queue' == 0, combine
+ * write and read queues.
+ *
+ * If 'write_queues' > 0, ensure it leaves room for at least one read
+ * queue.
*/
- if (!this_w_queues) {
- dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues;
- dev->io_queues[HCTX_TYPE_READ] = 0;
+ if (!nrirqs) {
+ nrirqs = 1;
+ nr_read_queues = 0;
+ } else if (nrirqs == 1 || !write_queues) {
+ nr_read_queues = 0;
+ } else if (write_queues >= nrirqs) {
+ nr_read_queues = 1;
} else {
- dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues;
- dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues;
+ nr_read_queues = nrirqs - write_queues;
}
+
+ dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues;
+ affd->set_size[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues;
+ dev->io_queues[HCTX_TYPE_READ] = nr_read_queues;
+ affd->set_size[HCTX_TYPE_READ] = nr_read_queues;
+ affd->nr_sets = nr_read_queues ? 2 : 1;
}
static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
{
struct pci_dev *pdev = to_pci_dev(dev->dev);
- int irq_sets[2];
struct irq_affinity affd = {
- .pre_vectors = 1,
- .nr_sets = ARRAY_SIZE(irq_sets),
- .sets = irq_sets,
+ .pre_vectors = 1,
+ .calc_sets = nvme_calc_irq_sets,
+ .priv = dev,
};
- int result = 0;
unsigned int irq_queues, this_p_queues;
/*
@@ -2082,54 +2098,22 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
this_p_queues = nr_io_queues - 1;
irq_queues = 1;
} else {
- irq_queues = nr_io_queues - this_p_queues;
+ irq_queues = nr_io_queues - this_p_queues + 1;
}
dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
- /*
- * For irq sets, we have to ask for minvec == maxvec. This passes
- * any reduction back to us, so we can adjust our queue counts and
- * IRQ vector needs.
- */
- do {
- nvme_calc_io_queues(dev, irq_queues);
- irq_sets[0] = dev->io_queues[HCTX_TYPE_DEFAULT];
- irq_sets[1] = dev->io_queues[HCTX_TYPE_READ];
- if (!irq_sets[1])
- affd.nr_sets = 1;
-
- /*
- * If we got a failure and we're down to asking for just
- * 1 + 1 queues, just ask for a single vector. We'll share
- * that between the single IO queue and the admin queue.
- */
- if (result >= 0 && irq_queues > 1)
- irq_queues = irq_sets[0] + irq_sets[1] + 1;
-
- result = pci_alloc_irq_vectors_affinity(pdev, irq_queues,
- irq_queues,
- PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
+ /* Initialize for the single interrupt case */
+ dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
+ dev->io_queues[HCTX_TYPE_READ] = 0;
- /*
- * Need to reduce our vec counts. If we get ENOSPC, the
- * platform should support mulitple vecs, we just need
- * to decrease our ask. If we get EINVAL, the platform
- * likely does not. Back down to ask for just one vector.
- */
- if (result == -ENOSPC) {
- irq_queues--;
- if (!irq_queues)
- return result;
- continue;
- } else if (result == -EINVAL) {
- irq_queues = 1;
- continue;
- } else if (result <= 0)
- return -EIO;
- break;
- } while (1);
+ return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
+ PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
+}
- return result;
+static void nvme_disable_io_queues(struct nvme_dev *dev)
+{
+ if (__nvme_disable_io_queues(dev, nvme_admin_delete_sq))
+ __nvme_disable_io_queues(dev, nvme_admin_delete_cq);
}
static int nvme_setup_io_queues(struct nvme_dev *dev)
@@ -2168,6 +2152,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
} while (1);
adminq->q_db = dev->dbs;
+ retry:
/* Deregister the admin queue's interrupt */
pci_free_irq(pdev, 0, adminq);
@@ -2185,25 +2170,34 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
result = max(result - 1, 1);
dev->max_qid = result + dev->io_queues[HCTX_TYPE_POLL];
- dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
- dev->io_queues[HCTX_TYPE_DEFAULT],
- dev->io_queues[HCTX_TYPE_READ],
- dev->io_queues[HCTX_TYPE_POLL]);
-
/*
* Should investigate if there's a performance win from allocating
* more queues than interrupt vectors; it might allow the submission
* path to scale better, even if the receive path is limited by the
* number of interrupts.
*/
-
result = queue_request_irq(adminq);
if (result) {
adminq->cq_vector = -1;
return result;
}
set_bit(NVMEQ_ENABLED, &adminq->flags);
- return nvme_create_io_queues(dev);
+
+ result = nvme_create_io_queues(dev);
+ if (result || dev->online_queues < 2)
+ return result;
+
+ if (dev->online_queues - 1 < dev->max_qid) {
+ nr_io_queues = dev->online_queues - 1;
+ nvme_disable_io_queues(dev);
+ nvme_suspend_io_queues(dev);
+ goto retry;
+ }
+ dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
+ dev->io_queues[HCTX_TYPE_DEFAULT],
+ dev->io_queues[HCTX_TYPE_READ],
+ dev->io_queues[HCTX_TYPE_POLL]);
+ return 0;
}
static void nvme_del_queue_end(struct request *req, blk_status_t error)
@@ -2248,7 +2242,7 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
return 0;
}
-static bool nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
{
int nr_queues = dev->online_queues - 1, sent = 0;
unsigned long timeout;
@@ -2294,7 +2288,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
dev->tagset.nr_maps = 2; /* default + read */
if (dev->io_queues[HCTX_TYPE_POLL])
dev->tagset.nr_maps++;
- dev->tagset.nr_maps = HCTX_MAX_TYPES;
dev->tagset.timeout = NVME_IO_TIMEOUT;
dev->tagset.numa_node = dev_to_node(dev->dev);
dev->tagset.queue_depth =
@@ -2410,7 +2403,6 @@ static void nvme_pci_disable(struct nvme_dev *dev)
static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
{
- int i;
bool dead = true;
struct pci_dev *pdev = to_pci_dev(dev->dev);
@@ -2437,13 +2429,11 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
nvme_stop_queues(&dev->ctrl);
if (!dead && dev->ctrl.queue_count > 0) {
- if (nvme_disable_io_queues(dev, nvme_admin_delete_sq))
- nvme_disable_io_queues(dev, nvme_admin_delete_cq);
+ nvme_disable_io_queues(dev);
nvme_disable_admin_queue(dev, shutdown);
}
- for (i = dev->ctrl.queue_count - 1; i >= 0; i--)
- nvme_suspend_queue(&dev->queues[i]);
-
+ nvme_suspend_io_queues(dev);
+ nvme_suspend_queue(&dev->queues[0]);
nvme_pci_disable(dev);
blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl);
@@ -2527,27 +2517,18 @@ static void nvme_reset_work(struct work_struct *work)
if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
nvme_dev_disable(dev, false);
- /*
- * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
- * initializing procedure here.
- */
- if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
- dev_warn(dev->ctrl.device,
- "failed to mark controller CONNECTING\n");
- goto out;
- }
-
+ mutex_lock(&dev->shutdown_lock);
result = nvme_pci_enable(dev);
if (result)
- goto out;
+ goto out_unlock;
result = nvme_pci_configure_admin_queue(dev);
if (result)
- goto out;
+ goto out_unlock;
result = nvme_alloc_admin_tags(dev);
if (result)
- goto out;
+ goto out_unlock;
/*
* Limit the max command size to prevent iod->sg allocations going
@@ -2555,6 +2536,17 @@ static void nvme_reset_work(struct work_struct *work)
*/
dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1;
dev->ctrl.max_segments = NVME_MAX_SEGS;
+ mutex_unlock(&dev->shutdown_lock);
+
+ /*
+ * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
+ * initializing procedure here.
+ */
+ if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
+ dev_warn(dev->ctrl.device,
+ "failed to mark controller CONNECTING\n");
+ goto out;
+ }
result = nvme_init_identify(&dev->ctrl);
if (result)
@@ -2619,6 +2611,8 @@ static void nvme_reset_work(struct work_struct *work)
nvme_start_ctrl(&dev->ctrl);
return;
+ out_unlock:
+ mutex_unlock(&dev->shutdown_lock);
out:
nvme_remove_dead_ctrl(dev, result);
}
@@ -2946,6 +2940,8 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_VDEVICE(INTEL, 0xf1a5), /* Intel 600P/P3100 */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_MEDIUM_PRIO_SQ },
+ { PCI_VDEVICE(INTEL, 0xf1a6), /* Intel 760p/Pro 7600p */
+ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
{ PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */
.driver_data = NVME_QUIRK_IDENTIFY_CNS, },
{ PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
@@ -2988,6 +2984,7 @@ static struct pci_driver nvme_driver = {
static int __init nvme_init(void)
{
+ BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2);
return pci_register_driver(&nvme_driver);
}
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 0a2fd2949ad7..52abc3a6de12 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -119,6 +119,7 @@ struct nvme_rdma_ctrl {
struct nvme_ctrl ctrl;
bool use_inline_data;
+ u32 io_queues[HCTX_MAX_TYPES];
};
static inline struct nvme_rdma_ctrl *to_rdma_ctrl(struct nvme_ctrl *ctrl)
@@ -165,8 +166,8 @@ static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue)
static bool nvme_rdma_poll_queue(struct nvme_rdma_queue *queue)
{
return nvme_rdma_queue_idx(queue) >
- queue->ctrl->ctrl.opts->nr_io_queues +
- queue->ctrl->ctrl.opts->nr_write_queues;
+ queue->ctrl->io_queues[HCTX_TYPE_DEFAULT] +
+ queue->ctrl->io_queues[HCTX_TYPE_READ];
}
static inline size_t nvme_rdma_inline_data_size(struct nvme_rdma_queue *queue)
@@ -661,8 +662,21 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
nr_io_queues = min_t(unsigned int, nr_io_queues,
ibdev->num_comp_vectors);
- nr_io_queues += min(opts->nr_write_queues, num_online_cpus());
- nr_io_queues += min(opts->nr_poll_queues, num_online_cpus());
+ if (opts->nr_write_queues) {
+ ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+ min(opts->nr_write_queues, nr_io_queues);
+ nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT];
+ } else {
+ ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues;
+ }
+
+ ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues;
+
+ if (opts->nr_poll_queues) {
+ ctrl->io_queues[HCTX_TYPE_POLL] =
+ min(opts->nr_poll_queues, num_online_cpus());
+ nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL];
+ }
ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
if (ret)
@@ -1689,18 +1703,28 @@ static enum blk_eh_timer_return
nvme_rdma_timeout(struct request *rq, bool reserved)
{
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+ struct nvme_rdma_queue *queue = req->queue;
+ struct nvme_rdma_ctrl *ctrl = queue->ctrl;
- dev_warn(req->queue->ctrl->ctrl.device,
- "I/O %d QID %d timeout, reset controller\n",
- rq->tag, nvme_rdma_queue_idx(req->queue));
+ dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n",
+ rq->tag, nvme_rdma_queue_idx(queue));
- /* queue error recovery */
- nvme_rdma_error_recovery(req->queue->ctrl);
+ if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
+ /*
+ * Teardown immediately if controller times out while starting
+ * or we are already started error recovery. all outstanding
+ * requests are completed on shutdown, so we return BLK_EH_DONE.
+ */
+ flush_work(&ctrl->err_work);
+ nvme_rdma_teardown_io_queues(ctrl, false);
+ nvme_rdma_teardown_admin_queue(ctrl, false);
+ return BLK_EH_DONE;
+ }
- /* fail with DNR on cmd timeout */
- nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+ dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+ nvme_rdma_error_recovery(ctrl);
- return BLK_EH_DONE;
+ return BLK_EH_RESET_TIMER;
}
static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -1779,17 +1803,15 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
struct nvme_rdma_ctrl *ctrl = set->driver_data;
set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
- set->map[HCTX_TYPE_READ].nr_queues = ctrl->ctrl.opts->nr_io_queues;
+ set->map[HCTX_TYPE_DEFAULT].nr_queues =
+ ctrl->io_queues[HCTX_TYPE_DEFAULT];
+ set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ];
if (ctrl->ctrl.opts->nr_write_queues) {
/* separate read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->ctrl.opts->nr_write_queues;
set->map[HCTX_TYPE_READ].queue_offset =
- ctrl->ctrl.opts->nr_write_queues;
+ ctrl->io_queues[HCTX_TYPE_DEFAULT];
} else {
/* mixed read/write queues */
- set->map[HCTX_TYPE_DEFAULT].nr_queues =
- ctrl->ctrl.opts->nr_io_queues;
set->map[HCTX_TYPE_READ].queue_offset = 0;
}
blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT],
@@ -1799,12 +1821,12 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
if (ctrl->ctrl.opts->nr_poll_queues) {
set->map[HCTX_TYPE_POLL].nr_queues =
- ctrl->ctrl.opts->nr_poll_queues;
+ ctrl->io_queues[HCTX_TYPE_POLL];
set->map[HCTX_TYPE_POLL].queue_offset =
- ctrl->ctrl.opts->nr_io_queues;
+ ctrl->io_queues[HCTX_TYPE_DEFAULT];
if (ctrl->ctrl.opts->nr_write_queues)
set->map[HCTX_TYPE_POLL].queue_offset +=
- ctrl->ctrl.opts->nr_write_queues;
+ ctrl->io_queues[HCTX_TYPE_READ];
blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
}
return 0;
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index de174912445e..5f0a00425242 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1565,8 +1565,7 @@ static void nvme_tcp_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
{
nvme_tcp_stop_io_queues(ctrl);
if (remove) {
- if (ctrl->ops->flags & NVME_F_FABRICS)
- blk_cleanup_queue(ctrl->connect_q);
+ blk_cleanup_queue(ctrl->connect_q);
blk_mq_free_tag_set(ctrl->tagset);
}
nvme_tcp_free_io_queues(ctrl);
@@ -1587,12 +1586,10 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
goto out_free_io_queues;
}
- if (ctrl->ops->flags & NVME_F_FABRICS) {
- ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
- if (IS_ERR(ctrl->connect_q)) {
- ret = PTR_ERR(ctrl->connect_q);
- goto out_free_tag_set;
- }
+ ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
+ if (IS_ERR(ctrl->connect_q)) {
+ ret = PTR_ERR(ctrl->connect_q);
+ goto out_free_tag_set;
}
} else {
blk_mq_update_nr_hw_queues(ctrl->tagset,
@@ -1606,7 +1603,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
return 0;
out_cleanup_connect_q:
- if (new && (ctrl->ops->flags & NVME_F_FABRICS))
+ if (new)
blk_cleanup_queue(ctrl->connect_q);
out_free_tag_set:
if (new)
@@ -1620,7 +1617,6 @@ static void nvme_tcp_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove)
{
nvme_tcp_stop_queue(ctrl, 0);
if (remove) {
- free_opal_dev(ctrl->opal_dev);
blk_cleanup_queue(ctrl->admin_q);
blk_mq_free_tag_set(ctrl->admin_tagset);
}
@@ -1952,20 +1948,23 @@ nvme_tcp_timeout(struct request *rq, bool reserved)
struct nvme_tcp_ctrl *ctrl = req->queue->ctrl;
struct nvme_tcp_cmd_pdu *pdu = req->pdu;
- dev_dbg(ctrl->ctrl.device,
+ dev_warn(ctrl->ctrl.device,
"queue %d: timeout request %#x type %d\n",
- nvme_tcp_queue_id(req->queue), rq->tag,
- pdu->hdr.type);
+ nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type);
if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
- union nvme_result res = {};
-
- nvme_req(rq)->flags |= NVME_REQ_CANCELLED;
- nvme_end_request(rq, cpu_to_le16(NVME_SC_ABORT_REQ), res);
+ /*
+ * Teardown immediately if controller times out while starting
+ * or we are already started error recovery. all outstanding
+ * requests are completed on shutdown, so we return BLK_EH_DONE.
+ */
+ flush_work(&ctrl->err_work);
+ nvme_tcp_teardown_io_queues(&ctrl->ctrl, false);
+ nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false);
return BLK_EH_DONE;
}
- /* queue error recovery */
+ dev_warn(ctrl->ctrl.device, "starting error recovery\n");
nvme_tcp_error_recovery(&ctrl->ctrl);
return BLK_EH_RESET_TIMER;
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index a8d23eb80192..a884e3a0e8af 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -139,6 +139,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc);
static void nvmet_rdma_qp_event(struct ib_event *event, void *priv);
static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
+static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
+ struct nvmet_rdma_rsp *r);
+static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
+ struct nvmet_rdma_rsp *r);
static const struct nvmet_fabrics_ops nvmet_rdma_ops;
@@ -182,9 +186,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
spin_unlock_irqrestore(&queue->rsps_lock, flags);
if (unlikely(!rsp)) {
- rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
+ int ret;
+
+ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
if (unlikely(!rsp))
return NULL;
+ ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
+ if (unlikely(ret)) {
+ kfree(rsp);
+ return NULL;
+ }
+
rsp->allocated = true;
}
@@ -197,6 +209,7 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
unsigned long flags;
if (unlikely(rsp->allocated)) {
+ nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
kfree(rsp);
return;
}
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 44b37b202e39..ad0df786fe93 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1089,7 +1089,7 @@ out:
static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue)
{
- int result;
+ int result = 0;
if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR))
return 0;
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 0a7a470ee859..530d570724c9 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -26,7 +26,7 @@ config NVMEM_IMX_IIM
config NVMEM_IMX_OCOTP
tristate "i.MX6 On-Chip OTP Controller support"
- depends on SOC_IMX6 || COMPILE_TEST
+ depends on SOC_IMX6 || SOC_IMX7D || COMPILE_TEST
depends on HAS_IOMEM
help
This is a driver for the On-Chip OTP Controller (OCOTP) available on
@@ -192,4 +192,14 @@ config SC27XX_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem-sc27xx-efuse.
+config NVMEM_ZYNQMP
+ bool "Xilinx ZYNQMP SoC nvmem firmware support"
+ depends on ARCH_ZYNQMP
+ help
+ This is a driver to access hardware related data like
+ soc revision, IDCODE... etc by using the firmware
+ interface.
+
+ If sure, say yes. If unsure, say no.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 4e8c61628f1a..2ece8ffffdda 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -41,3 +41,5 @@ obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o
nvmem-sc27xx-efuse-y := sc27xx-efuse.o
+obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
+nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
diff --git a/drivers/nvmem/bcm-ocotp.c b/drivers/nvmem/bcm-ocotp.c
index 4159b3f41d79..a8097511582a 100644
--- a/drivers/nvmem/bcm-ocotp.c
+++ b/drivers/nvmem/bcm-ocotp.c
@@ -11,13 +11,14 @@
* GNU General Public License for more details.
*/
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
-#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
/*
@@ -78,9 +79,9 @@ static struct otpc_map otp_map_v2 = {
};
struct otpc_priv {
- struct device *dev;
- void __iomem *base;
- struct otpc_map *map;
+ struct device *dev;
+ void __iomem *base;
+ const struct otpc_map *map;
struct nvmem_config *config;
};
@@ -237,16 +238,22 @@ static struct nvmem_config bcm_otpc_nvmem_config = {
};
static const struct of_device_id bcm_otpc_dt_ids[] = {
- { .compatible = "brcm,ocotp" },
- { .compatible = "brcm,ocotp-v2" },
+ { .compatible = "brcm,ocotp", .data = &otp_map },
+ { .compatible = "brcm,ocotp-v2", .data = &otp_map_v2 },
{ },
};
MODULE_DEVICE_TABLE(of, bcm_otpc_dt_ids);
+static const struct acpi_device_id bcm_otpc_acpi_ids[] = {
+ { .id = "BRCM0700", .driver_data = (kernel_ulong_t)&otp_map },
+ { .id = "BRCM0701", .driver_data = (kernel_ulong_t)&otp_map_v2 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_ids);
+
static int bcm_otpc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *dn = dev->of_node;
struct resource *res;
struct otpc_priv *priv;
struct nvmem_device *nvmem;
@@ -257,14 +264,9 @@ static int bcm_otpc_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- if (of_device_is_compatible(dev->of_node, "brcm,ocotp"))
- priv->map = &otp_map;
- else if (of_device_is_compatible(dev->of_node, "brcm,ocotp-v2"))
- priv->map = &otp_map_v2;
- else {
- dev_err(dev, "%s otpc config map not defined\n", __func__);
- return -EINVAL;
- }
+ priv->map = device_get_match_data(dev);
+ if (!priv->map)
+ return -ENODEV;
/* Get OTP base address register. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -281,7 +283,7 @@ static int bcm_otpc_probe(struct platform_device *pdev)
reset_start_bit(priv->base);
/* Read size of memory in words. */
- err = of_property_read_u32(dn, "brcm,ocotp-size", &num_words);
+ err = device_property_read_u32(dev, "brcm,ocotp-size", &num_words);
if (err) {
dev_err(dev, "size parameter not specified\n");
return -EINVAL;
@@ -294,7 +296,7 @@ static int bcm_otpc_probe(struct platform_device *pdev)
bcm_otpc_nvmem_config.dev = dev;
bcm_otpc_nvmem_config.priv = priv;
- if (of_device_is_compatible(dev->of_node, "brcm,ocotp-v2")) {
+ if (priv->map == &otp_map_v2) {
bcm_otpc_nvmem_config.word_size = 8;
bcm_otpc_nvmem_config.stride = 8;
}
@@ -315,6 +317,7 @@ static struct platform_driver bcm_otpc_driver = {
.driver = {
.name = "brcm-otpc",
.of_match_table = bcm_otpc_dt_ids,
+ .acpi_match_table = ACPI_PTR(bcm_otpc_acpi_ids),
},
};
module_platform_driver(bcm_otpc_driver);
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index f7301bb4ef3b..f24008b66826 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -525,12 +525,14 @@ out:
static struct nvmem_cell *
nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
{
- struct nvmem_cell *cell = NULL;
+ struct nvmem_cell *iter, *cell = NULL;
mutex_lock(&nvmem_mutex);
- list_for_each_entry(cell, &nvmem->cells, node) {
- if (strcmp(cell_id, cell->name) == 0)
+ list_for_each_entry(iter, &nvmem->cells, node) {
+ if (strcmp(cell_id, iter->name) == 0) {
+ cell = iter;
break;
+ }
}
mutex_unlock(&nvmem_mutex);
@@ -646,8 +648,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
config->name ? config->id : nvmem->id);
}
- nvmem->read_only = device_property_present(config->dev, "read-only") |
- config->read_only;
+ nvmem->read_only = device_property_present(config->dev, "read-only") ||
+ config->read_only || !nvmem->reg_write;
if (config->root_only)
nvmem->dev.groups = nvmem->read_only ?
@@ -686,9 +688,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (rval)
goto err_remove_cells;
- rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
- if (rval)
- goto err_remove_cells;
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
return nvmem;
@@ -809,6 +809,7 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np,
"could not increase module refcount for cell %s\n",
nvmem_dev_name(nvmem));
+ put_device(&nvmem->dev);
return ERR_PTR(-EINVAL);
}
@@ -819,6 +820,7 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np,
static void __nvmem_device_put(struct nvmem_device *nvmem)
{
+ put_device(&nvmem->dev);
module_put(nvmem->owner);
kref_put(&nvmem->refcnt, nvmem_device_release);
}
@@ -837,13 +839,14 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
{
struct device_node *nvmem_np;
- int index;
+ int index = 0;
- index = of_property_match_string(np, "nvmem-names", id);
+ if (id)
+ index = of_property_match_string(np, "nvmem-names", id);
nvmem_np = of_parse_phandle(np, "nvmem", index);
if (!nvmem_np)
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOENT);
return __nvmem_device_get(nvmem_np, NULL);
}
@@ -871,7 +874,7 @@ struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
}
- return nvmem_find(dev_name);
+ return __nvmem_device_get(NULL, dev_name);
}
EXPORT_SYMBOL_GPL(nvmem_device_get);
@@ -972,7 +975,7 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
if (IS_ERR(nvmem)) {
/* Provider may not be registered yet. */
cell = ERR_CAST(nvmem);
- goto out;
+ break;
}
cell = nvmem_find_cell_by_name(nvmem,
@@ -980,12 +983,11 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
if (!cell) {
__nvmem_device_put(nvmem);
cell = ERR_PTR(-ENOENT);
- goto out;
}
+ break;
}
}
-out:
mutex_unlock(&nvmem_lookup_mutex);
return cell;
}
@@ -994,12 +996,14 @@ out:
static struct nvmem_cell *
nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
{
- struct nvmem_cell *cell = NULL;
+ struct nvmem_cell *iter, *cell = NULL;
mutex_lock(&nvmem_mutex);
- list_for_each_entry(cell, &nvmem->cells, node) {
- if (np == cell->np)
+ list_for_each_entry(iter, &nvmem->cells, node) {
+ if (np == iter->np) {
+ cell = iter;
break;
+ }
}
mutex_unlock(&nvmem_mutex);
@@ -1031,7 +1035,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
cell_np = of_parse_phandle(np, "nvmem-cells", index);
if (!cell_np)
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOENT);
nvmem_np = of_get_next_parent(cell_np);
if (!nvmem_np)
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index afb429a417fe..08a9b1ef8ae4 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -427,19 +427,32 @@ static const struct ocotp_params imx6ul_params = {
.set_timing = imx_ocotp_set_imx6_timing,
};
+static const struct ocotp_params imx6ull_params = {
+ .nregs = 64,
+ .bank_address_words = 0,
+ .set_timing = imx_ocotp_set_imx6_timing,
+};
+
static const struct ocotp_params imx7d_params = {
.nregs = 64,
.bank_address_words = 4,
.set_timing = imx_ocotp_set_imx7_timing,
};
+static const struct ocotp_params imx7ulp_params = {
+ .nregs = 256,
+ .bank_address_words = 0,
+};
+
static const struct of_device_id imx_ocotp_dt_ids[] = {
{ .compatible = "fsl,imx6q-ocotp", .data = &imx6q_params },
{ .compatible = "fsl,imx6sl-ocotp", .data = &imx6sl_params },
{ .compatible = "fsl,imx6sx-ocotp", .data = &imx6sx_params },
{ .compatible = "fsl,imx6ul-ocotp", .data = &imx6ul_params },
+ { .compatible = "fsl,imx6ull-ocotp", .data = &imx6ull_params },
{ .compatible = "fsl,imx7d-ocotp", .data = &imx7d_params },
{ .compatible = "fsl,imx6sll-ocotp", .data = &imx6sll_params },
+ { .compatible = "fsl,imx7ulp-ocotp", .data = &imx7ulp_params },
{ },
};
MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
diff --git a/drivers/nvmem/sc27xx-efuse.c b/drivers/nvmem/sc27xx-efuse.c
index 33185d8d82cf..c6ee21018d80 100644
--- a/drivers/nvmem/sc27xx-efuse.c
+++ b/drivers/nvmem/sc27xx-efuse.c
@@ -106,10 +106,12 @@ static int sc27xx_efuse_poll_status(struct sc27xx_efuse *efuse, u32 bits)
static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes)
{
struct sc27xx_efuse *efuse = context;
- u32 buf;
+ u32 buf, blk_index = offset / SC27XX_EFUSE_BLOCK_WIDTH;
+ u32 blk_offset = (offset % SC27XX_EFUSE_BLOCK_WIDTH) * BITS_PER_BYTE;
int ret;
- if (offset > SC27XX_EFUSE_BLOCK_MAX || bytes > SC27XX_EFUSE_BLOCK_WIDTH)
+ if (blk_index > SC27XX_EFUSE_BLOCK_MAX ||
+ bytes > SC27XX_EFUSE_BLOCK_WIDTH)
return -EINVAL;
ret = sc27xx_efuse_lock(efuse);
@@ -133,7 +135,7 @@ static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes)
/* Set the block address to be read. */
ret = regmap_write(efuse->regmap,
efuse->base + SC27XX_EFUSE_BLOCK_INDEX,
- offset & SC27XX_EFUSE_BLOCK_MASK);
+ blk_index & SC27XX_EFUSE_BLOCK_MASK);
if (ret)
goto disable_efuse;
@@ -171,8 +173,10 @@ disable_efuse:
unlock_efuse:
sc27xx_efuse_unlock(efuse);
- if (!ret)
+ if (!ret) {
+ buf >>= blk_offset;
memcpy(val, &buf, bytes);
+ }
return ret;
}
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
new file mode 100644
index 000000000000..490c8fcaec80
--- /dev/null
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Xilinx, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define SILICON_REVISION_MASK 0xF
+
+struct zynqmp_nvmem_data {
+ struct device *dev;
+ struct nvmem_device *nvmem;
+};
+
+static int zynqmp_nvmem_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ int ret;
+ int idcode, version;
+ struct zynqmp_nvmem_data *priv = context;
+
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->get_chipid)
+ return -ENXIO;
+
+ ret = eemi_ops->get_chipid(&idcode, &version);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version);
+ *(int *)val = version & SILICON_REVISION_MASK;
+
+ return 0;
+}
+
+static struct nvmem_config econfig = {
+ .name = "zynqmp-nvmem",
+ .owner = THIS_MODULE,
+ .word_size = 1,
+ .size = 1,
+ .read_only = true,
+};
+
+static const struct of_device_id zynqmp_nvmem_match[] = {
+ { .compatible = "xlnx,zynqmp-nvmem-fw", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, zynqmp_nvmem_match);
+
+static int zynqmp_nvmem_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct zynqmp_nvmem_data *priv;
+
+ priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ econfig.dev = dev;
+ econfig.reg_read = zynqmp_nvmem_read;
+ econfig.priv = priv;
+
+ priv->nvmem = devm_nvmem_register(dev, &econfig);
+
+ return PTR_ERR_OR_ZERO(priv->nvmem);
+}
+
+static struct platform_driver zynqmp_nvmem_driver = {
+ .probe = zynqmp_nvmem_probe,
+ .driver = {
+ .name = "zynqmp-nvmem",
+ .of_match_table = zynqmp_nvmem_match,
+ },
+};
+
+module_platform_driver(zynqmp_nvmem_driver);
+
+MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
+MODULE_DESCRIPTION("ZynqMP NVMEM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index a09c1c3cf831..49b16f76d78e 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -207,11 +207,8 @@ static void __of_attach_node(struct device_node *np)
if (!of_node_check_flag(np, OF_OVERLAY)) {
np->name = __of_get_property(np, "name", NULL);
- np->type = __of_get_property(np, "device_type", NULL);
if (!np->name)
np->name = "<NULL>";
- if (!np->type)
- np->type = "<NULL>";
phandle = __of_get_property(np, "phandle", &sz);
if (!phandle)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 7099c652c6a5..9cc1461aac7d 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -314,12 +314,8 @@ static bool populate_node(const void *blob,
populate_properties(blob, offset, mem, np, pathp, dryrun);
if (!dryrun) {
np->name = of_get_property(np, "name", NULL);
- np->type = of_get_property(np, "device_type", NULL);
-
if (!np->name)
np->name = "<NULL>";
- if (!np->type)
- np->type = "<NULL>";
}
*pnp = np;
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 5ad1342f5682..de6157357e26 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -16,7 +16,6 @@
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
@@ -463,7 +462,6 @@ int of_phy_register_fixed_link(struct device_node *np)
struct device_node *fixed_link_node;
u32 fixed_link_prop[5];
const char *managed;
- int link_gpio = -1;
if (of_property_read_string(np, "managed", &managed) == 0 &&
strcmp(managed, "in-band-status") == 0) {
@@ -485,11 +483,7 @@ int of_phy_register_fixed_link(struct device_node *np)
status.pause = of_property_read_bool(fixed_link_node, "pause");
status.asym_pause = of_property_read_bool(fixed_link_node,
"asym-pause");
- link_gpio = of_get_named_gpio_flags(fixed_link_node,
- "link-gpios", 0, NULL);
of_node_put(fixed_link_node);
- if (link_gpio == -EPROBE_DEFER)
- return -EPROBE_DEFER;
goto register_phy;
}
@@ -508,8 +502,7 @@ int of_phy_register_fixed_link(struct device_node *np)
return -ENODEV;
register_phy:
- return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, link_gpio,
- np));
+ return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, np));
}
EXPORT_SYMBOL(of_phy_register_fixed_link);
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 2b5ac43a5690..c423e94baf0f 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -423,12 +423,9 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
tchild->parent = target->np;
tchild->name = __of_get_property(node, "name", NULL);
- tchild->type = __of_get_property(node, "device_type", NULL);
if (!tchild->name)
tchild->name = "<NULL>";
- if (!tchild->type)
- tchild->type = "<NULL>";
/* ignore obsolete "linux,phandle" */
phandle = __of_get_property(node, "phandle", &size);
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index d3185063d369..7eda43c66c91 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -155,7 +155,6 @@ static struct device_node * __init of_pdt_create_node(phandle node,
dp->parent = parent;
dp->name = of_pdt_get_one_property(node, "name");
- dp->type = of_pdt_get_one_property(node, "device_type");
dp->phandle = node;
dp->properties = of_pdt_build_prop_list(node);
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 08430031bd28..8631efa1daa1 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -806,6 +806,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
if (!of_device_is_available(remote)) {
pr_debug("not available for remote node\n");
+ of_node_put(remote);
return NULL;
}
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index e5507add8f04..d7f97167cac3 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -131,6 +131,24 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
/**
+ * dev_pm_opp_get_level() - Gets the level corresponding to an available opp
+ * @opp: opp for which level value has to be returned for
+ *
+ * Return: level read from device tree corresponding to the opp, else
+ * return 0.
+ */
+unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
+{
+ if (IS_ERR_OR_NULL(opp) || !opp->available) {
+ pr_err("%s: Invalid parameters\n", __func__);
+ return 0;
+ }
+
+ return opp->level;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_level);
+
+/**
* dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
* @opp: opp for which turbo mode is being verified
*
@@ -533,9 +551,8 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
return ret;
}
-static inline int
-_generic_set_opp_clk_only(struct device *dev, struct clk *clk,
- unsigned long old_freq, unsigned long freq)
+static inline int _generic_set_opp_clk_only(struct device *dev, struct clk *clk,
+ unsigned long freq)
{
int ret;
@@ -572,7 +589,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table,
}
/* Change frequency */
- ret = _generic_set_opp_clk_only(dev, opp_table->clk, old_freq, freq);
+ ret = _generic_set_opp_clk_only(dev, opp_table->clk, freq);
if (ret)
goto restore_voltage;
@@ -586,7 +603,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table,
return 0;
restore_freq:
- if (_generic_set_opp_clk_only(dev, opp_table->clk, freq, old_freq))
+ if (_generic_set_opp_clk_only(dev, opp_table->clk, old_freq))
dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
__func__, old_freq);
restore_voltage:
@@ -759,7 +776,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
opp->supplies);
} else {
/* Only frequency scaling */
- ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq);
+ ret = _generic_set_opp_clk_only(dev, clk, freq);
}
/* Scaling down? Configure required OPPs after frequency */
@@ -793,7 +810,6 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
struct opp_table *opp_table)
{
struct opp_device *opp_dev;
- int ret;
opp_dev = kzalloc(sizeof(*opp_dev), GFP_KERNEL);
if (!opp_dev)
@@ -805,10 +821,7 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
list_add(&opp_dev->node, &opp_table->dev_list);
/* Create debugfs entries for the opp_table */
- ret = opp_debug_register(opp_dev, opp_table);
- if (ret)
- dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
- __func__, ret);
+ opp_debug_register(opp_dev, opp_table);
return opp_dev;
}
@@ -988,11 +1001,9 @@ void _opp_free(struct dev_pm_opp *opp)
kfree(opp);
}
-static void _opp_kref_release(struct kref *kref)
+static void _opp_kref_release(struct dev_pm_opp *opp,
+ struct opp_table *opp_table)
{
- struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
- struct opp_table *opp_table = opp->opp_table;
-
/*
* Notify the changes in the availability of the operable
* frequency/voltage list.
@@ -1002,7 +1013,22 @@ static void _opp_kref_release(struct kref *kref)
opp_debug_remove_one(opp);
list_del(&opp->node);
kfree(opp);
+}
+
+static void _opp_kref_release_unlocked(struct kref *kref)
+{
+ struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+ struct opp_table *opp_table = opp->opp_table;
+ _opp_kref_release(opp, opp_table);
+}
+
+static void _opp_kref_release_locked(struct kref *kref)
+{
+ struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+ struct opp_table *opp_table = opp->opp_table;
+
+ _opp_kref_release(opp, opp_table);
mutex_unlock(&opp_table->lock);
}
@@ -1013,10 +1039,16 @@ void dev_pm_opp_get(struct dev_pm_opp *opp)
void dev_pm_opp_put(struct dev_pm_opp *opp)
{
- kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
+ kref_put_mutex(&opp->kref, _opp_kref_release_locked,
+ &opp->opp_table->lock);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_put);
+static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
+{
+ kref_put(&opp->kref, _opp_kref_release_unlocked);
+}
+
/**
* dev_pm_opp_remove() - Remove an OPP from OPP table
* @dev: device for which we do this operation
@@ -1060,6 +1092,40 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
+/**
+ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
+ * @dev: device for which we do this operation
+ *
+ * This function removes all dynamically created OPPs from the opp table.
+ */
+void dev_pm_opp_remove_all_dynamic(struct device *dev)
+{
+ struct opp_table *opp_table;
+ struct dev_pm_opp *opp, *temp;
+ int count = 0;
+
+ opp_table = _find_opp_table(dev);
+ if (IS_ERR(opp_table))
+ return;
+
+ mutex_lock(&opp_table->lock);
+ list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
+ if (opp->dynamic) {
+ dev_pm_opp_put_unlocked(opp);
+ count++;
+ }
+ }
+ mutex_unlock(&opp_table->lock);
+
+ /* Drop the references taken by dev_pm_opp_add() */
+ while (count--)
+ dev_pm_opp_put_opp_table(opp_table);
+
+ /* Drop the reference taken by _find_opp_table() */
+ dev_pm_opp_put_opp_table(opp_table);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
+
struct dev_pm_opp *_opp_allocate(struct opp_table *table)
{
struct dev_pm_opp *opp;
@@ -1176,10 +1242,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
new_opp->opp_table = opp_table;
kref_init(&new_opp->kref);
- ret = opp_debug_create_one(new_opp, opp_table);
- if (ret)
- dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
- __func__, ret);
+ opp_debug_create_one(new_opp, opp_table);
if (!_opp_supported_by_regulators(new_opp, opp_table)) {
new_opp->available = false;
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index e6828e5f81b0..a1c57fe14de4 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -35,7 +35,7 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
debugfs_remove_recursive(opp->dentry);
}
-static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
+static void opp_debug_create_supplies(struct dev_pm_opp *opp,
struct opp_table *opp_table,
struct dentry *pdentry)
{
@@ -50,30 +50,21 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
/* Create per-opp directory */
d = debugfs_create_dir(name, pdentry);
- if (!d)
- return false;
+ debugfs_create_ulong("u_volt_target", S_IRUGO, d,
+ &opp->supplies[i].u_volt);
- if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,
- &opp->supplies[i].u_volt))
- return false;
+ debugfs_create_ulong("u_volt_min", S_IRUGO, d,
+ &opp->supplies[i].u_volt_min);
- if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,
- &opp->supplies[i].u_volt_min))
- return false;
+ debugfs_create_ulong("u_volt_max", S_IRUGO, d,
+ &opp->supplies[i].u_volt_max);
- if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,
- &opp->supplies[i].u_volt_max))
- return false;
-
- if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
- &opp->supplies[i].u_amp))
- return false;
+ debugfs_create_ulong("u_amp", S_IRUGO, d,
+ &opp->supplies[i].u_amp);
}
-
- return true;
}
-int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
+void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
{
struct dentry *pdentry = opp_table->dentry;
struct dentry *d;
@@ -95,40 +86,23 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
/* Create per-opp directory */
d = debugfs_create_dir(name, pdentry);
- if (!d)
- return -ENOMEM;
-
- if (!debugfs_create_bool("available", S_IRUGO, d, &opp->available))
- return -ENOMEM;
-
- if (!debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic))
- return -ENOMEM;
-
- if (!debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo))
- return -ENOMEM;
-
- if (!debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend))
- return -ENOMEM;
-
- if (!debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate))
- return -ENOMEM;
- if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
- return -ENOMEM;
+ debugfs_create_bool("available", S_IRUGO, d, &opp->available);
+ debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic);
+ debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
+ debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
+ debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
+ debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate);
+ debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+ &opp->clock_latency_ns);
- if (!opp_debug_create_supplies(opp, opp_table, d))
- return -ENOMEM;
-
- if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
- &opp->clock_latency_ns))
- return -ENOMEM;
+ opp_debug_create_supplies(opp, opp_table, d);
opp->dentry = d;
- return 0;
}
-static int opp_list_debug_create_dir(struct opp_device *opp_dev,
- struct opp_table *opp_table)
+static void opp_list_debug_create_dir(struct opp_device *opp_dev,
+ struct opp_table *opp_table)
{
const struct device *dev = opp_dev->dev;
struct dentry *d;
@@ -137,36 +111,21 @@ static int opp_list_debug_create_dir(struct opp_device *opp_dev,
/* Create device specific directory */
d = debugfs_create_dir(opp_table->dentry_name, rootdir);
- if (!d) {
- dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
- return -ENOMEM;
- }
opp_dev->dentry = d;
opp_table->dentry = d;
-
- return 0;
}
-static int opp_list_debug_create_link(struct opp_device *opp_dev,
- struct opp_table *opp_table)
+static void opp_list_debug_create_link(struct opp_device *opp_dev,
+ struct opp_table *opp_table)
{
- const struct device *dev = opp_dev->dev;
char name[NAME_MAX];
- struct dentry *d;
opp_set_dev_name(opp_dev->dev, name);
/* Create device specific directory link */
- d = debugfs_create_symlink(name, rootdir, opp_table->dentry_name);
- if (!d) {
- dev_err(dev, "%s: Failed to create link\n", __func__);
- return -ENOMEM;
- }
-
- opp_dev->dentry = d;
-
- return 0;
+ opp_dev->dentry = debugfs_create_symlink(name, rootdir,
+ opp_table->dentry_name);
}
/**
@@ -177,20 +136,13 @@ static int opp_list_debug_create_link(struct opp_device *opp_dev,
* Dynamically adds device specific directory in debugfs 'opp' directory. If the
* device-opp is shared with other devices, then links will be created for all
* devices except the first.
- *
- * Return: 0 on success, otherwise negative error.
*/
-int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
+void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
{
- if (!rootdir) {
- pr_debug("%s: Uninitialized rootdir\n", __func__);
- return -EINVAL;
- }
-
if (opp_table->dentry)
- return opp_list_debug_create_link(opp_dev, opp_table);
-
- return opp_list_debug_create_dir(opp_dev, opp_table);
+ opp_list_debug_create_link(opp_dev, opp_table);
+ else
+ opp_list_debug_create_dir(opp_dev, opp_table);
}
static void opp_migrate_dentry(struct opp_device *opp_dev,
@@ -252,10 +204,6 @@ static int __init opp_debug_init(void)
{
/* Create /sys/kernel/debug/opp directory */
rootdir = debugfs_create_dir("opp", NULL);
- if (!rootdir) {
- pr_err("%s: Failed to create root directory\n", __func__);
- return -ENOMEM;
- }
return 0;
}
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 06f0f632ec47..62504b18f198 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -20,6 +20,7 @@
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/energy_model.h>
#include "opp.h"
@@ -594,6 +595,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
new_opp->rate = (unsigned long)rate;
}
+ of_property_read_u32(np, "opp-level", &new_opp->level);
+
/* Check if the OPP supports hardware's hierarchy of versions or not */
if (!_opp_is_supported(dev, opp_table, np)) {
dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
@@ -1047,3 +1050,101 @@ struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
return of_node_get(opp->np);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node);
+
+/*
+ * Callback function provided to the Energy Model framework upon registration.
+ * This computes the power estimated by @CPU at @kHz if it is the frequency
+ * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise
+ * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled
+ * frequency and @mW to the associated power. The power is estimated as
+ * P = C * V^2 * f with C being the CPU's capacitance and V and f respectively
+ * the voltage and frequency of the OPP.
+ *
+ * Returns -ENODEV if the CPU device cannot be found, -EINVAL if the power
+ * calculation failed because of missing parameters, 0 otherwise.
+ */
+static int __maybe_unused _get_cpu_power(unsigned long *mW, unsigned long *kHz,
+ int cpu)
+{
+ struct device *cpu_dev;
+ struct dev_pm_opp *opp;
+ struct device_node *np;
+ unsigned long mV, Hz;
+ u32 cap;
+ u64 tmp;
+ int ret;
+
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev)
+ return -ENODEV;
+
+ np = of_node_get(cpu_dev->of_node);
+ if (!np)
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap);
+ of_node_put(np);
+ if (ret)
+ return -EINVAL;
+
+ Hz = *kHz * 1000;
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz);
+ if (IS_ERR(opp))
+ return -EINVAL;
+
+ mV = dev_pm_opp_get_voltage(opp) / 1000;
+ dev_pm_opp_put(opp);
+ if (!mV)
+ return -EINVAL;
+
+ tmp = (u64)cap * mV * mV * (Hz / 1000000);
+ do_div(tmp, 1000000000);
+
+ *mW = (unsigned long)tmp;
+ *kHz = Hz / 1000;
+
+ return 0;
+}
+
+/**
+ * dev_pm_opp_of_register_em() - Attempt to register an Energy Model
+ * @cpus : CPUs for which an Energy Model has to be registered
+ *
+ * This checks whether the "dynamic-power-coefficient" devicetree property has
+ * been specified, and tries to register an Energy Model with it if it has.
+ */
+void dev_pm_opp_of_register_em(struct cpumask *cpus)
+{
+ struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
+ int ret, nr_opp, cpu = cpumask_first(cpus);
+ struct device *cpu_dev;
+ struct device_node *np;
+ u32 cap;
+
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev)
+ return;
+
+ nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+ if (nr_opp <= 0)
+ return;
+
+ np = of_node_get(cpu_dev->of_node);
+ if (!np)
+ return;
+
+ /*
+ * Register an EM only if the 'dynamic-power-coefficient' property is
+ * set in devicetree. It is assumed the voltage values are known if that
+ * property is set since it is useless otherwise. If voltages are not
+ * known, just let the EM registration fail with an error to alert the
+ * user about the inconsistent configuration.
+ */
+ ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap);
+ of_node_put(np);
+ if (ret || !cap)
+ return;
+
+ em_register_perf_domain(cpus, nr_opp, &em_cb);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_register_em);
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index e24d81497375..569b3525aa67 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -60,6 +60,7 @@ extern struct list_head opp_tables;
* @suspend: true if suspend OPP
* @pstate: Device's power domain's performance state.
* @rate: Frequency in hertz
+ * @level: Performance level
* @supplies: Power supplies voltage/current values
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
* frequency from any other OPP's frequency.
@@ -80,6 +81,7 @@ struct dev_pm_opp {
bool suspend;
unsigned int pstate;
unsigned long rate;
+ unsigned int level;
struct dev_pm_opp_supply *supplies;
@@ -236,18 +238,17 @@ static inline void _of_opp_free_required_opps(struct opp_table *opp_table,
#ifdef CONFIG_DEBUG_FS
void opp_debug_remove_one(struct dev_pm_opp *opp);
-int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
-int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
+void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
+void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
#else
static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
-static inline int opp_debug_create_one(struct dev_pm_opp *opp,
- struct opp_table *opp_table)
-{ return 0; }
-static inline int opp_debug_register(struct opp_device *opp_dev,
- struct opp_table *opp_table)
-{ return 0; }
+static inline void opp_debug_create_one(struct dev_pm_opp *opp,
+ struct opp_table *opp_table) { }
+
+static inline void opp_debug_register(struct opp_device *opp_dev,
+ struct opp_table *opp_table) { }
static inline void opp_debug_unregister(struct opp_device *opp_dev,
struct opp_table *opp_table)
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 8d2fc84119c6..097b0d43d13c 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -55,6 +55,8 @@
#include <asm/hardware.h> /* for register_module() */
#include <asm/parisc-device.h>
+#include "iommu.h"
+
/*
** Choose "ccio" since that's what HP-UX calls it.
** Make it easier for folks to migrate from one to the other :^)
@@ -1517,6 +1519,7 @@ static int __init ccio_probe(struct parisc_device *dev)
{
int i;
struct ioc *ioc, **ioc_p = &ioc_list;
+ struct pci_hba_data *hba;
ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
if (ioc == NULL) {
@@ -1543,11 +1546,13 @@ static int __init ccio_probe(struct parisc_device *dev)
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
- dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
+ hba = kzalloc(sizeof(*hba), GFP_KERNEL);
/* if this fails, no I/O cards will work, so may as well bug */
- BUG_ON(dev->dev.platform_data == NULL);
- HBA_DATA(dev->dev.platform_data)->iommu = ioc;
+ BUG_ON(hba == NULL);
+
+ hba->iommu = ioc;
+ dev->dev.platform_data = hba;
#ifdef CONFIG_PROC_FS
if (ioc_count == 0) {
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index dfeea458a789..846b59d15999 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -59,6 +59,7 @@
#include <asm/hardware.h>
#include "gsc.h"
+#include "iommu.h"
#undef DINO_DEBUG
@@ -153,12 +154,10 @@ struct dino_device
#endif
};
-/* Looks nice and keeps the compiler happy */
-#define DINO_DEV(d) ({ \
- void *__pdata = d; \
- BUG_ON(!__pdata); \
- (struct dino_device *)__pdata; })
-
+static inline struct dino_device *DINO_DEV(struct pci_hba_data *hba)
+{
+ return container_of(hba, struct dino_device, hba);
+}
/*
* Dino Configuration Space Accessor Functions
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 9ff434f354bd..5657a1d3eb2b 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -45,6 +45,8 @@
#include <asm/eisa_bus.h>
#include <asm/eisa_eeprom.h>
+#include "iommu.h"
+
#if 0
#define EISA_DBG(msg, arg...) printk(KERN_DEBUG "eisa: " msg, ## arg)
#else
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index ebc7b617e5d0..3b3481c0d81d 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -23,6 +23,8 @@
#include <asm/hardware.h>
#include <asm/parisc-device.h>
+#include "iommu.h"
+
struct hppb_card {
unsigned long hpa;
struct resource mmio_region;
diff --git a/drivers/parisc/iommu.h b/drivers/parisc/iommu.h
new file mode 100644
index 000000000000..240059cd8185
--- /dev/null
+++ b/drivers/parisc/iommu.h
@@ -0,0 +1,55 @@
+#ifndef _IOMMU_H
+#define _IOMMU_H 1
+
+#include <linux/pci.h>
+
+struct parisc_device;
+struct ioc;
+
+static inline struct pci_hba_data *parisc_walk_tree(struct device *dev)
+{
+ struct device *otherdev;
+
+ if (likely(dev->platform_data))
+ return dev->platform_data;
+
+ /* OK, just traverse the bus to find it */
+ for (otherdev = dev->parent;
+ otherdev;
+ otherdev = otherdev->parent) {
+ if (otherdev->platform_data) {
+ dev->platform_data = otherdev->platform_data;
+ break;
+ }
+ }
+
+ return dev->platform_data;
+}
+
+static inline struct ioc *GET_IOC(struct device *dev)
+{
+ struct pci_hba_data *pdata = parisc_walk_tree(dev);
+
+ if (!pdata)
+ return NULL;
+ return pdata->iommu;
+}
+
+#ifdef CONFIG_IOMMU_CCIO
+void *ccio_get_iommu(const struct parisc_device *dev);
+int ccio_request_resource(const struct parisc_device *dev,
+ struct resource *res);
+int ccio_allocate_resource(const struct parisc_device *dev,
+ struct resource *res, unsigned long size,
+ unsigned long min, unsigned long max, unsigned long align);
+#else /* !CONFIG_IOMMU_CCIO */
+#define ccio_get_iommu(dev) NULL
+#define ccio_request_resource(dev, res) insert_resource(&iomem_resource, res)
+#define ccio_allocate_resource(dev, res, size, min, max, align) \
+ allocate_resource(&iomem_resource, res, size, min, max, \
+ align, NULL, NULL)
+#endif /* !CONFIG_IOMMU_CCIO */
+
+void *sba_get_iommu(struct parisc_device *dev);
+
+#endif /* _IOMMU_H */
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 144c77dfe4b1..1be571c20062 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -126,21 +126,10 @@
** o disable IRdT - call disable_irq(vector[line]->processor_irq)
*/
-
-/* FIXME: determine which include files are really needed */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <asm/byteorder.h> /* get in-line asm for swab */
#include <asm/pdc.h>
#include <asm/pdcpat.h>
-#include <asm/page.h>
-#include <asm/io.h> /* read/write functions */
#ifdef CONFIG_SUPERIO
#include <asm/superio.h>
#endif
@@ -168,12 +157,8 @@
#define DBG_IRT(x...)
#endif
-#ifdef CONFIG_64BIT
-#define COMPARE_IRTE_ADDR(irte, hpa) ((irte)->dest_iosapic_addr == (hpa))
-#else
#define COMPARE_IRTE_ADDR(irte, hpa) \
- ((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
-#endif
+ ((irte)->dest_iosapic_addr == F_EXTEND(hpa))
#define IOSAPIC_REG_SELECT 0x00
#define IOSAPIC_REG_WINDOW 0x10
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 69bd98421eb1..d4701589bc8c 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -49,6 +49,8 @@
#include <asm/parisc-device.h>
#include <asm/io.h> /* read/write stuff */
+#include "iommu.h"
+
#undef DEBUG_LBA /* general stuff */
#undef DEBUG_LBA_PORT /* debug I/O Port access */
#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */
@@ -109,12 +111,10 @@ static u32 lba_t32;
#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
-
-/* Looks nice and keeps the compiler happy */
-#define LBA_DEV(d) ({ \
- void *__pdata = d; \
- BUG_ON(!__pdata); \
- (struct lba_device *)__pdata; })
+static inline struct lba_device *LBA_DEV(struct pci_hba_data *hba)
+{
+ return container_of(hba, struct lba_device, hba);
+}
/*
** Only allow 8 subsidiary busses per LBA
@@ -1275,7 +1275,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
r->flags = IORESOURCE_MEM;
/* mmio_mask also clears Enable bit */
r->start &= mmio_mask;
- r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
+ r->start = PCI_HOST_ADDR(&lba_dev->hba, r->start);
rsize = ~ READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_MASK);
/*
@@ -1321,7 +1321,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
r->flags = IORESOURCE_MEM;
/* mmio_mask also clears Enable bit */
r->start &= mmio_mask;
- r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
+ r->start = PCI_HOST_ADDR(&lba_dev->hba, r->start);
rsize = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_MASK);
r->end = r->start + ~rsize;
}
@@ -1562,7 +1562,7 @@ lba_driver_probe(struct parisc_device *dev)
/* ------------ Second : initialize common stuff ---------- */
pci_bios = &lba_bios_ops;
- pcibios_register_hba(HBA_DATA(lba_dev));
+ pcibios_register_hba(&lba_dev->hba);
spin_lock_init(&lba_dev->lba_lock);
if (lba_hw_init(lba_dev))
@@ -1743,3 +1743,15 @@ static void quirk_diva_aux_disable(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
quirk_diva_aux_disable);
+
+static void quirk_tosca_aux_disable(struct pci_dev *dev)
+{
+ if (dev->subsystem_vendor != PCI_VENDOR_ID_HP ||
+ dev->subsystem_device != 0x104a)
+ return;
+
+ dev_info(&dev->dev, "Hiding Tosca secondary built-in AUX serial device");
+ dev->device = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+ quirk_tosca_aux_disable);
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 42172eb32235..afaf8e6aefe6 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -49,6 +49,8 @@
#include <asm/pdcpat.h> /* for is_pdc_pat() */
#include <asm/parisc-device.h>
+#include "iommu.h"
+
#define MODULE_NAME "SBA"
/*
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 5484a46dafda..56dd83a45e55 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -213,10 +213,12 @@ void parport_daisy_fini(struct parport *port)
struct pardevice *parport_open(int devnum, const char *name)
{
struct daisydev *p = topology;
+ struct pardev_cb par_cb;
struct parport *port;
struct pardevice *dev;
int daisy;
+ memset(&par_cb, 0, sizeof(par_cb));
spin_lock(&topology_lock);
while (p && p->devnum != devnum)
p = p->next;
@@ -230,7 +232,7 @@ struct pardevice *parport_open(int devnum, const char *name)
port = parport_get_port(p->port);
spin_unlock(&topology_lock);
- dev = parport_register_device(port, name, NULL, NULL, NULL, 0, NULL);
+ dev = parport_register_dev_model(port, name, &par_cb, devnum);
parport_put_port(port);
if (!dev)
return NULL;
@@ -480,3 +482,31 @@ static int assign_addrs(struct parport *port)
kfree(deviceid);
return detected;
}
+
+static int daisy_drv_probe(struct pardevice *par_dev)
+{
+ struct device_driver *drv = par_dev->dev.driver;
+
+ if (strcmp(drv->name, "daisy_drv"))
+ return -ENODEV;
+ if (strcmp(par_dev->name, daisy_dev_name))
+ return -ENODEV;
+
+ return 0;
+}
+
+static struct parport_driver daisy_driver = {
+ .name = "daisy_drv",
+ .probe = daisy_drv_probe,
+ .devmodel = true,
+};
+
+int daisy_drv_init(void)
+{
+ return parport_register_driver(&daisy_driver);
+}
+
+void daisy_drv_exit(void)
+{
+ parport_unregister_driver(&daisy_driver);
+}
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 9c8249f74479..6296dbb83d47 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1377,7 +1377,7 @@ static struct superio_struct *find_superio(struct parport *p)
{
int i;
for (i = 0; i < NR_SUPERIOS; i++)
- if (superios[i].io != p->base)
+ if (superios[i].io == p->base)
return &superios[i];
return NULL;
}
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index e035174ba205..e5e6a463a941 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -257,7 +257,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
ssize_t parport_device_id (int devnum, char *buffer, size_t count)
{
ssize_t retval = -ENXIO;
- struct pardevice *dev = parport_open (devnum, "Device ID probe");
+ struct pardevice *dev = parport_open(devnum, daisy_dev_name);
if (!dev)
return -ENXIO;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 5dc53d420ca8..0171b8dbcdcd 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -137,11 +137,19 @@ static struct bus_type parport_bus_type = {
int parport_bus_init(void)
{
- return bus_register(&parport_bus_type);
+ int retval;
+
+ retval = bus_register(&parport_bus_type);
+ if (retval)
+ return retval;
+ daisy_drv_init();
+
+ return 0;
}
void parport_bus_exit(void)
{
+ daisy_drv_exit();
bus_unregister(&parport_bus_type);
}
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 4310c7a4212e..2ab92409210a 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -21,13 +21,14 @@ menuconfig PCI
support for PCI-X and the foundations for PCI Express support.
Say 'Y' here unless you know what you are doing.
+if PCI
+
config PCI_DOMAINS
bool
depends on PCI
config PCI_DOMAINS_GENERIC
bool
- depends on PCI
select PCI_DOMAINS
config PCI_SYSCALL
@@ -37,7 +38,6 @@ source "drivers/pci/pcie/Kconfig"
config PCI_MSI
bool "Message Signaled Interrupts (MSI and MSI-X)"
- depends on PCI
select GENERIC_MSI_IRQ
help
This allows device drivers to enable MSI (Message Signaled
@@ -59,7 +59,6 @@ config PCI_MSI_IRQ_DOMAIN
config PCI_QUIRKS
default y
bool "Enable PCI quirk workarounds" if EXPERT
- depends on PCI
help
This enables workarounds for various PCI chipset bugs/quirks.
Disable this only if your target machine is unaffected by PCI
@@ -67,7 +66,7 @@ config PCI_QUIRKS
config PCI_DEBUG
bool "PCI Debugging"
- depends on PCI && DEBUG_KERNEL
+ depends on DEBUG_KERNEL
help
Say Y here if you want the PCI core to produce a bunch of debug
messages to the system log. Select this if you are having a
@@ -77,7 +76,6 @@ config PCI_DEBUG
config PCI_REALLOC_ENABLE_AUTO
bool "Enable PCI resource re-allocation detection"
- depends on PCI
depends on PCI_IOV
help
Say Y here if you want the PCI core to detect if PCI resource
@@ -90,7 +88,6 @@ config PCI_REALLOC_ENABLE_AUTO
config PCI_STUB
tristate "PCI Stub driver"
- depends on PCI
help
Say Y or M here if you want be able to reserve a PCI device
when it is going to be assigned to a guest operating system.
@@ -99,7 +96,6 @@ config PCI_STUB
config PCI_PF_STUB
tristate "PCI PF Stub driver"
- depends on PCI
depends on PCI_IOV
help
Say Y or M here if you want to enable support for devices that
@@ -111,7 +107,7 @@ config PCI_PF_STUB
config XEN_PCIDEV_FRONTEND
tristate "Xen PCI Frontend"
- depends on PCI && X86 && XEN
+ depends on X86 && XEN
select PCI_XEN
select XEN_XENBUS_FRONTEND
default y
@@ -133,7 +129,6 @@ config PCI_BRIDGE_EMUL
config PCI_IOV
bool "PCI IOV support"
- depends on PCI
select PCI_ATS
help
I/O Virtualization is a PCI feature supported by some devices
@@ -144,7 +139,6 @@ config PCI_IOV
config PCI_PRI
bool "PCI PRI support"
- depends on PCI
select PCI_ATS
help
PRI is the PCI Page Request Interface. It allows PCI devices that are
@@ -154,7 +148,6 @@ config PCI_PRI
config PCI_PASID
bool "PCI PASID support"
- depends on PCI
select PCI_ATS
help
Process Address Space Identifiers (PASIDs) can be used by PCI devices
@@ -167,7 +160,7 @@ config PCI_PASID
config PCI_P2PDMA
bool "PCI peer-to-peer transfer support"
- depends on PCI && ZONE_DEVICE
+ depends on ZONE_DEVICE
select GENERIC_ALLOCATOR
help
Enableѕ drivers to do PCI peer-to-peer transactions to and from
@@ -184,12 +177,11 @@ config PCI_P2PDMA
config PCI_LABEL
def_bool y if (DMI || ACPI)
- depends on PCI
select NLS
config PCI_HYPERV
tristate "Hyper-V PCI Frontend"
- depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+ depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
help
The PCI device frontend driver allows the kernel to import arbitrary
PCI devices from a PCI backend to support PCI driver domains.
@@ -198,3 +190,5 @@ source "drivers/pci/hotplug/Kconfig"
source "drivers/pci/controller/Kconfig"
source "drivers/pci/endpoint/Kconfig"
source "drivers/pci/switch/Kconfig"
+
+endif
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 52e47dac028f..80f843030e36 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -310,6 +310,9 @@ static int imx6_pcie_attach_pd(struct device *dev)
imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
if (IS_ERR(imx6_pcie->pd_pcie))
return PTR_ERR(imx6_pcie->pd_pcie);
+ /* Do nothing when power domain missing */
+ if (!imx6_pcie->pd_pcie)
+ return 0;
link = device_link_add(dev, imx6_pcie->pd_pcie,
DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
@@ -323,13 +326,13 @@ static int imx6_pcie_attach_pd(struct device *dev)
if (IS_ERR(imx6_pcie->pd_pcie_phy))
return PTR_ERR(imx6_pcie->pd_pcie_phy);
- device_link_add(dev, imx6_pcie->pd_pcie_phy,
+ link = device_link_add(dev, imx6_pcie->pd_pcie_phy,
DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
- if (IS_ERR(link)) {
- dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link));
- return PTR_ERR(link);
+ if (!link) {
+ dev_err(dev, "Failed to add device_link to pcie_phy pd.\n");
+ return -EINVAL;
}
return 0;
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 241ebe0c4505..e35e9eaa50ee 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c
index b171b6bc15c8..0c389a30ef5d 100644
--- a/drivers/pci/controller/dwc/pcie-armada8k.c
+++ b/drivers/pci/controller/dwc/pcie-armada8k.c
@@ -22,7 +22,6 @@
#include <linux/resource.h>
#include <linux/of_pci.h>
#include <linux/of_irq.h>
-#include <linux/gpio/consumer.h>
#include "pcie-designware.h"
@@ -30,7 +29,6 @@ struct armada8k_pcie {
struct dw_pcie *pci;
struct clk *clk;
struct clk *clk_reg;
- struct gpio_desc *reset_gpio;
};
#define PCIE_VENDOR_REGS_OFFSET 0x8000
@@ -139,12 +137,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
- if (pcie->reset_gpio) {
- /* assert and then deassert the reset signal */
- gpiod_set_value_cansleep(pcie->reset_gpio, 1);
- msleep(100);
- gpiod_set_value_cansleep(pcie->reset_gpio, 0);
- }
dw_pcie_setup_rc(pp);
armada8k_pcie_establish_link(pcie);
@@ -257,14 +249,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
goto fail_clkreg;
}
- /* Get reset gpio signal and hold asserted (logically high) */
- pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset",
- GPIOD_OUT_HIGH);
- if (IS_ERR(pcie->reset_gpio)) {
- ret = PTR_ERR(pcie->reset_gpio);
- goto fail_clkreg;
- }
-
platform_set_drvdata(pdev, pcie);
ret = armada8k_add_pcie_port(pcie, pdev);
diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c
index 9deb56989d72..cb3401a931f8 100644
--- a/drivers/pci/controller/pcie-iproc-msi.c
+++ b/drivers/pci/controller/pcie-iproc-msi.c
@@ -602,9 +602,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node)
}
/* Reserve memory for event queue and make sure memories are zeroed */
- msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
- msi->nr_eq_region * EQ_MEM_REGION_SIZE,
- &msi->eq_dma, GFP_KERNEL);
+ msi->eq_cpu = dma_alloc_coherent(pcie->dev,
+ msi->nr_eq_region * EQ_MEM_REGION_SIZE,
+ &msi->eq_dma, GFP_KERNEL);
if (!msi->eq_cpu) {
ret = -ENOMEM;
goto free_irqs;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7a1c8a09efa5..73986825d221 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -532,7 +532,7 @@ error_attrs:
}
static struct msi_desc *
-msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd)
+msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
{
struct irq_affinity_desc *masks = NULL;
struct msi_desc *entry;
@@ -597,7 +597,7 @@ static int msi_verify_entries(struct pci_dev *dev)
* which could have been allocated.
*/
static int msi_capability_init(struct pci_dev *dev, int nvec,
- const struct irq_affinity *affd)
+ struct irq_affinity *affd)
{
struct msi_desc *entry;
int ret;
@@ -669,7 +669,7 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)
static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
struct msix_entry *entries, int nvec,
- const struct irq_affinity *affd)
+ struct irq_affinity *affd)
{
struct irq_affinity_desc *curmsk, *masks = NULL;
struct msi_desc *entry;
@@ -736,7 +736,7 @@ static void msix_program_entries(struct pci_dev *dev,
* requested MSI-X entries with allocated irqs or non-zero for otherwise.
**/
static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
- int nvec, const struct irq_affinity *affd)
+ int nvec, struct irq_affinity *affd)
{
int ret;
u16 control;
@@ -932,7 +932,7 @@ int pci_msix_vec_count(struct pci_dev *dev)
EXPORT_SYMBOL(pci_msix_vec_count);
static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
- int nvec, const struct irq_affinity *affd)
+ int nvec, struct irq_affinity *affd)
{
int nr_entries;
int i, j;
@@ -1018,7 +1018,7 @@ int pci_msi_enabled(void)
EXPORT_SYMBOL(pci_msi_enabled);
static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
- const struct irq_affinity *affd)
+ struct irq_affinity *affd)
{
int nvec;
int rc;
@@ -1035,13 +1035,6 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
if (maxvec < minvec)
return -ERANGE;
- /*
- * If the caller is passing in sets, we can't support a range of
- * vectors. The caller needs to handle that.
- */
- if (affd && affd->nr_sets && minvec != maxvec)
- return -EINVAL;
-
if (WARN_ON_ONCE(dev->msi_enabled))
return -EINVAL;
@@ -1086,20 +1079,13 @@ EXPORT_SYMBOL(pci_enable_msi);
static int __pci_enable_msix_range(struct pci_dev *dev,
struct msix_entry *entries, int minvec,
- int maxvec, const struct irq_affinity *affd)
+ int maxvec, struct irq_affinity *affd)
{
int rc, nvec = maxvec;
if (maxvec < minvec)
return -ERANGE;
- /*
- * If the caller is passing in sets, we can't support a range of
- * supported vectors. The caller needs to handle that.
- */
- if (affd && affd->nr_sets && minvec != maxvec)
- return -EINVAL;
-
if (WARN_ON_ONCE(dev->msix_enabled))
return -EINVAL;
@@ -1165,10 +1151,11 @@ EXPORT_SYMBOL(pci_enable_msix_range);
*/
int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags,
- const struct irq_affinity *affd)
+ struct irq_affinity *affd)
{
- static const struct irq_affinity msi_default_affd;
- int vecs = -ENOSPC;
+ struct irq_affinity msi_default_affd = {0};
+ int msix_vecs = -ENOSPC;
+ int msi_vecs = -ENOSPC;
if (flags & PCI_IRQ_AFFINITY) {
if (!affd)
@@ -1179,27 +1166,37 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
}
if (flags & PCI_IRQ_MSIX) {
- vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
- affd);
- if (vecs > 0)
- return vecs;
+ msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs,
+ max_vecs, affd);
+ if (msix_vecs > 0)
+ return msix_vecs;
}
if (flags & PCI_IRQ_MSI) {
- vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
- if (vecs > 0)
- return vecs;
+ msi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs,
+ affd);
+ if (msi_vecs > 0)
+ return msi_vecs;
}
/* use legacy irq if allowed */
if (flags & PCI_IRQ_LEGACY) {
if (min_vecs == 1 && dev->irq) {
+ /*
+ * Invoke the affinity spreading logic to ensure that
+ * the device driver can adjust queue configuration
+ * for the single interrupt case.
+ */
+ if (affd)
+ irq_create_affinity_masks(1, affd);
pci_intx(dev, 1);
return 1;
}
}
- return vecs;
+ if (msix_vecs == -ENOSPC)
+ return -ENOSPC;
+ return msi_vecs;
}
EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9ecfe13157c0..25794c27c7a4 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -412,8 +412,7 @@ static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(msi_bus);
-static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
- size_t count)
+static ssize_t rescan_store(struct bus_type *bus, const char *buf, size_t count)
{
unsigned long val;
struct pci_bus *b = NULL;
@@ -429,7 +428,7 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
}
return count;
}
-static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store);
+static BUS_ATTR_WO(rescan);
static struct attribute *pci_bus_attrs[] = {
&bus_attr_rescan.attr,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c9d8e3c837de..db55acf32a7e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -6034,19 +6034,18 @@ static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
return count;
}
-static ssize_t pci_resource_alignment_show(struct bus_type *bus, char *buf)
+static ssize_t resource_alignment_show(struct bus_type *bus, char *buf)
{
return pci_get_resource_alignment_param(buf, PAGE_SIZE);
}
-static ssize_t pci_resource_alignment_store(struct bus_type *bus,
+static ssize_t resource_alignment_store(struct bus_type *bus,
const char *buf, size_t count)
{
return pci_set_resource_alignment_param(buf, count);
}
-static BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
- pci_resource_alignment_store);
+static BUS_ATTR_RW(resource_alignment);
static int __init pci_resource_alignment_sysfs_init(void)
{
@@ -6195,7 +6194,8 @@ static int __init pci_setup(char *str)
} else if (!strncmp(str, "pcie_scan_all", 13)) {
pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
} else if (!strncmp(str, "disable_acs_redir=", 18)) {
- disable_acs_redir_param = str + 18;
+ disable_acs_redir_param =
+ kstrdup(str + 18, GFP_KERNEL);
} else {
printk(KERN_ERR "PCI: Unknown option `%s'\n",
str);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b0a413f3f7ca..e2a879e93d86 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -639,8 +639,9 @@ static void quirk_synopsys_haps(struct pci_dev *pdev)
break;
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
- quirk_synopsys_haps);
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
+ PCI_CLASS_SERIAL_USB_XHCI, 0,
+ quirk_synopsys_haps);
/*
* Let's make the southbridge information explicit instead of having to
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 6c5536d3d42a..e22766c79fe9 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1373,10 +1373,10 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0)
return 0;
- stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev,
- sizeof(*stdev->dma_mrpc),
- &stdev->dma_mrpc_dma_addr,
- GFP_KERNEL);
+ stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev,
+ sizeof(*stdev->dma_mrpc),
+ &stdev->dma_mrpc_dma_addr,
+ GFP_KERNEL);
if (stdev->dma_mrpc == NULL)
return -ENOMEM;
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c
index 1bfeb160c5b1..bfd03e023308 100644
--- a/drivers/perf/arm-cci.c
+++ b/drivers/perf/arm-cci.c
@@ -1327,15 +1327,6 @@ static int cci_pmu_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EOPNOTSUPP;
- /* We have no filtering of any kind */
- if (event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle ||
- event->attr.exclude_host ||
- event->attr.exclude_guest)
- return -EINVAL;
-
/*
* Following the example set by other "uncore" PMUs, we accept any CPU
* and rewrite its affinity dynamically rather than having perf core
@@ -1433,6 +1424,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
.stop = cci_pmu_stop,
.read = pmu_read,
.attr_groups = pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
cci_pmu->plat_device = pdev;
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c
index 7dd850e02f19..2ae76026e947 100644
--- a/drivers/perf/arm-ccn.c
+++ b/drivers/perf/arm-ccn.c
@@ -741,10 +741,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
return -EOPNOTSUPP;
}
- if (has_branch_stack(event) || event->attr.exclude_user ||
- event->attr.exclude_kernel || event->attr.exclude_hv ||
- event->attr.exclude_idle || event->attr.exclude_host ||
- event->attr.exclude_guest) {
+ if (has_branch_stack(event)) {
dev_dbg(ccn->dev, "Can't exclude execution levels!\n");
return -EINVAL;
}
@@ -1290,6 +1287,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
.read = arm_ccn_pmu_event_read,
.pmu_enable = arm_ccn_pmu_enable,
.pmu_disable = arm_ccn_pmu_disable,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
/* No overflow interrupt? Have to use a timer instead. */
diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
index 660cb8ac886a..5851de56bbd0 100644
--- a/drivers/perf/arm_dsu_pmu.c
+++ b/drivers/perf/arm_dsu_pmu.c
@@ -562,13 +562,7 @@ static int dsu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
- if (has_branch_stack(event) ||
- event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle ||
- event->attr.exclude_host ||
- event->attr.exclude_guest) {
+ if (has_branch_stack(event)) {
dev_dbg(dsu_pmu->pmu.dev, "Can't support filtering\n");
return -EINVAL;
}
@@ -735,6 +729,7 @@ static int dsu_pmu_device_probe(struct platform_device *pdev)
.read = dsu_pmu_read,
.attr_groups = dsu_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
rc = perf_pmu_register(&dsu_pmu->pmu, name, -1);
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index d0b7dd8fb184..eec75b97e7ea 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -357,13 +357,6 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
}
static int
-event_requires_mode_exclusion(struct perf_event_attr *attr)
-{
- return attr->exclude_idle || attr->exclude_user ||
- attr->exclude_kernel || attr->exclude_hv;
-}
-
-static int
__hw_perf_event_init(struct perf_event *event)
{
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
@@ -393,9 +386,8 @@ __hw_perf_event_init(struct perf_event *event)
/*
* Check whether we need to exclude the counter from certain modes.
*/
- if ((!armpmu->set_event_filter ||
- armpmu->set_event_filter(hwc, &event->attr)) &&
- event_requires_mode_exclusion(&event->attr)) {
+ if (armpmu->set_event_filter &&
+ armpmu->set_event_filter(hwc, &event->attr)) {
pr_debug("ARM performance counters do not support "
"mode exclusion\n");
return -EOPNOTSUPP;
@@ -867,6 +859,9 @@ int armpmu_register(struct arm_pmu *pmu)
if (ret)
return ret;
+ if (!pmu->set_event_filter)
+ pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;
+
ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
if (ret)
goto out_destroy;
diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index 8e46a9dad2fa..7cb766dafe85 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -824,10 +824,10 @@ static void arm_spe_pmu_read(struct perf_event *event)
{
}
-static void *arm_spe_pmu_setup_aux(int cpu, void **pages, int nr_pages,
- bool snapshot)
+static void *arm_spe_pmu_setup_aux(struct perf_event *event, void **pages,
+ int nr_pages, bool snapshot)
{
- int i;
+ int i, cpu = event->cpu;
struct page **pglist;
struct arm_spe_pmu_buf *buf;
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 69372e2bc93c..0eba947c2ee9 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -396,6 +396,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_ddrc_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 443906e0aff3..2553a844ebf6 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -407,6 +407,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_hha_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 0bde5d919b2e..cf1cc34f402a 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -397,6 +397,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_l3c_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 9efd2413240c..f028cbc3443c 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -142,15 +142,6 @@ int hisi_uncore_pmu_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EOPNOTSUPP;
- /* counters do not have these bits */
- if (event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_host ||
- event->attr.exclude_guest ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle)
- return -EINVAL;
-
/*
* The uncore counters not specific to any CPU, so cannot
* support per-task
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 842135cf35a3..091b4d7d32c4 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -509,14 +509,6 @@ static int l2_cache_event_init(struct perf_event *event)
return -EOPNOTSUPP;
}
- /* We cannot filter accurately so we just don't allow it. */
- if (event->attr.exclude_user || event->attr.exclude_kernel ||
- event->attr.exclude_hv || event->attr.exclude_idle) {
- dev_dbg_ratelimited(&l2cache_pmu->pdev->dev,
- "Can't exclude execution levels\n");
- return -EOPNOTSUPP;
- }
-
if (((L2_EVT_GROUP(event->attr.config) > L2_EVT_GROUP_MAX) ||
((event->attr.config & ~L2_EVT_MASK) != 0)) &&
(event->attr.config != L2CYCLE_CTR_RAW_CODE)) {
@@ -982,6 +974,7 @@ static int l2_cache_pmu_probe(struct platform_device *pdev)
.stop = l2_cache_event_stop,
.read = l2_cache_event_read,
.attr_groups = l2_cache_pmu_attr_grps,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
l2cache_pmu->num_counters = get_num_counters();
diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c
index 2dc63d61f2ea..5d70646da8c7 100644
--- a/drivers/perf/qcom_l3_pmu.c
+++ b/drivers/perf/qcom_l3_pmu.c
@@ -495,13 +495,6 @@ static int qcom_l3_cache__event_init(struct perf_event *event)
return -ENOENT;
/*
- * There are no per-counter mode filters in the PMU.
- */
- if (event->attr.exclude_user || event->attr.exclude_kernel ||
- event->attr.exclude_hv || event->attr.exclude_idle)
- return -EINVAL;
-
- /*
* Sampling not supported since these events are not core-attributable.
*/
if (hwc->sample_period)
@@ -777,6 +770,7 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev)
.read = qcom_l3_cache__event_read,
.attr_groups = qcom_l3_cache_pmu_attr_grps,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
memrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/perf/thunderx2_pmu.c b/drivers/perf/thunderx2_pmu.c
index c9a1701d3e54..43d76c85da56 100644
--- a/drivers/perf/thunderx2_pmu.c
+++ b/drivers/perf/thunderx2_pmu.c
@@ -424,15 +424,6 @@ static int tx2_uncore_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EINVAL;
- /* We have no filtering of any kind */
- if (event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle ||
- event->attr.exclude_host ||
- event->attr.exclude_guest)
- return -EINVAL;
-
if (event->cpu < 0)
return -EINVAL;
@@ -572,6 +563,7 @@ static int tx2_uncore_pmu_register(
.start = tx2_uncore_event_start,
.stop = tx2_uncore_event_stop,
.read = tx2_uncore_event_read,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
tx2_pmu->pmu.name = devm_kasprintf(dev, GFP_KERNEL,
diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
index 0dc9ff0f8894..d4ec04868d59 100644
--- a/drivers/perf/xgene_pmu.c
+++ b/drivers/perf/xgene_pmu.c
@@ -917,11 +917,6 @@ static int xgene_perf_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EINVAL;
- /* SOC counters do not have usr/os/guest/host bits */
- if (event->attr.exclude_user || event->attr.exclude_kernel ||
- event->attr.exclude_host || event->attr.exclude_guest)
- return -EINVAL;
-
if (event->cpu < 0)
return -EINVAL;
/*
@@ -1136,6 +1131,7 @@ static int xgene_init_perf(struct xgene_pmu_dev *pmu_dev, char *name)
.start = xgene_perf_start,
.stop = xgene_perf_stop,
.read = xgene_perf_read,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
/* Hardware counter init */
diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
index c10e95f86de5..96a3af126a78 100644
--- a/drivers/phy/broadcom/phy-bcm-sr-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
@@ -78,8 +78,8 @@ struct sr_pcie_phy_core {
static const u8 pipemux_table[] = {
/* PIPEMUX = 0, EP 1x16 */
0x00,
- /* PIPEMUX = 1, EP 2x8 */
- 0x00,
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ 0x80,
/* PIPEMUX = 2, EP 4x4 */
0x00,
/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig
index 2b8c0851ff33..31f18b67dd7c 100644
--- a/drivers/phy/cadence/Kconfig
+++ b/drivers/phy/cadence/Kconfig
@@ -1,6 +1,7 @@
#
# Phy drivers for Cadence PHYs
#
+
config PHY_CADENCE_DP
tristate "Cadence MHDP DisplayPort PHY driver"
depends on OF
@@ -9,9 +10,19 @@ config PHY_CADENCE_DP
help
Support for Cadence MHDP DisplayPort PHY.
+config PHY_CADENCE_DPHY
+ tristate "Cadence D-PHY Support"
+ depends on HAS_IOMEM && OF
+ select GENERIC_PHY
+ select GENERIC_PHY_MIPI_DPHY
+ help
+ Choose this option if you have a Cadence D-PHY in your
+ system. If M is selected, the module will be called
+ cdns-dphy.
+
config PHY_CADENCE_SIERRA
tristate "Cadence Sierra PHY Driver"
depends on OF && HAS_IOMEM && RESET_CONTROLLER
select GENERIC_PHY
help
- Enable this to support the Cadence Sierra PHY driver \ No newline at end of file
+ Enable this to support the Cadence Sierra PHY driver
diff --git a/drivers/phy/cadence/Makefile b/drivers/phy/cadence/Makefile
index 412349af0492..2f9e3457b954 100644
--- a/drivers/phy/cadence/Makefile
+++ b/drivers/phy/cadence/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o
+obj-$(CONFIG_PHY_CADENCE_DPHY) += cdns-dphy.o
obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
new file mode 100644
index 000000000000..90c4e9b5aac8
--- /dev/null
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright: 2017-2018 Cadence Design Systems, Inc.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+
+#define REG_WAKEUP_TIME_NS 800
+#define DPHY_PLL_RATE_HZ 108000000
+
+/* DPHY registers */
+#define DPHY_PMA_CMN(reg) (reg)
+#define DPHY_PMA_LCLK(reg) (0x100 + (reg))
+#define DPHY_PMA_LDATA(lane, reg) (0x200 + ((lane) * 0x100) + (reg))
+#define DPHY_PMA_RCLK(reg) (0x600 + (reg))
+#define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
+#define DPHY_PCS(reg) (0xb00 + (reg))
+
+#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
+#define DPHY_CMN_SSM_EN BIT(0)
+#define DPHY_CMN_TX_MODE_EN BIT(9)
+
+#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
+#define DPHY_CMN_PWM_DIV(x) ((x) << 20)
+#define DPHY_CMN_PWM_LOW(x) ((x) << 10)
+#define DPHY_CMN_PWM_HIGH(x) (x)
+
+#define DPHY_CMN_FBDIV DPHY_PMA_CMN(0x4c)
+#define DPHY_CMN_FBDIV_VAL(low, high) (((high) << 11) | ((low) << 22))
+#define DPHY_CMN_FBDIV_FROM_REG (BIT(10) | BIT(21))
+
+#define DPHY_CMN_OPIPDIV DPHY_PMA_CMN(0x50)
+#define DPHY_CMN_IPDIV_FROM_REG BIT(0)
+#define DPHY_CMN_IPDIV(x) ((x) << 1)
+#define DPHY_CMN_OPDIV_FROM_REG BIT(6)
+#define DPHY_CMN_OPDIV(x) ((x) << 7)
+
+#define DPHY_PSM_CFG DPHY_PCS(0x4)
+#define DPHY_PSM_CFG_FROM_REG BIT(0)
+#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
+
+#define DSI_HBP_FRAME_OVERHEAD 12
+#define DSI_HSA_FRAME_OVERHEAD 14
+#define DSI_HFP_FRAME_OVERHEAD 6
+#define DSI_HSS_VSS_VSE_FRAME_OVERHEAD 4
+#define DSI_BLANKING_FRAME_OVERHEAD 6
+#define DSI_NULL_FRAME_OVERHEAD 6
+#define DSI_EOT_PKT_SIZE 4
+
+struct cdns_dphy_cfg {
+ u8 pll_ipdiv;
+ u8 pll_opdiv;
+ u16 pll_fbdiv;
+ unsigned int nlanes;
+};
+
+enum cdns_dphy_clk_lane_cfg {
+ DPHY_CLK_CFG_LEFT_DRIVES_ALL = 0,
+ DPHY_CLK_CFG_LEFT_DRIVES_RIGHT = 1,
+ DPHY_CLK_CFG_LEFT_DRIVES_LEFT = 2,
+ DPHY_CLK_CFG_RIGHT_DRIVES_ALL = 3,
+};
+
+struct cdns_dphy;
+struct cdns_dphy_ops {
+ int (*probe)(struct cdns_dphy *dphy);
+ void (*remove)(struct cdns_dphy *dphy);
+ void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
+ void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
+ enum cdns_dphy_clk_lane_cfg cfg);
+ void (*set_pll_cfg)(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg);
+ unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy);
+};
+
+struct cdns_dphy {
+ struct cdns_dphy_cfg cfg;
+ void __iomem *regs;
+ struct clk *psm_clk;
+ struct clk *pll_ref_clk;
+ const struct cdns_dphy_ops *ops;
+ struct phy *phy;
+};
+
+static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
+ struct cdns_dphy_cfg *cfg,
+ struct phy_configure_opts_mipi_dphy *opts,
+ unsigned int *dsi_hfp_ext)
+{
+ unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk);
+ u64 dlane_bps;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ if (pll_ref_hz < 9600000 || pll_ref_hz >= 150000000)
+ return -EINVAL;
+ else if (pll_ref_hz < 19200000)
+ cfg->pll_ipdiv = 1;
+ else if (pll_ref_hz < 38400000)
+ cfg->pll_ipdiv = 2;
+ else if (pll_ref_hz < 76800000)
+ cfg->pll_ipdiv = 4;
+ else
+ cfg->pll_ipdiv = 8;
+
+ dlane_bps = opts->hs_clk_rate;
+
+ if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL)
+ return -EINVAL;
+ else if (dlane_bps >= 1250000000)
+ cfg->pll_opdiv = 1;
+ else if (dlane_bps >= 630000000)
+ cfg->pll_opdiv = 2;
+ else if (dlane_bps >= 320000000)
+ cfg->pll_opdiv = 4;
+ else if (dlane_bps >= 160000000)
+ cfg->pll_opdiv = 8;
+
+ cfg->pll_fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv *
+ cfg->pll_ipdiv,
+ pll_ref_hz);
+
+ return 0;
+}
+
+static int cdns_dphy_setup_psm(struct cdns_dphy *dphy)
+{
+ unsigned long psm_clk_hz = clk_get_rate(dphy->psm_clk);
+ unsigned long psm_div;
+
+ if (!psm_clk_hz || psm_clk_hz > 100000000)
+ return -EINVAL;
+
+ psm_div = DIV_ROUND_CLOSEST(psm_clk_hz, 1000000);
+ if (dphy->ops->set_psm_div)
+ dphy->ops->set_psm_div(dphy, psm_div);
+
+ return 0;
+}
+
+static void cdns_dphy_set_clk_lane_cfg(struct cdns_dphy *dphy,
+ enum cdns_dphy_clk_lane_cfg cfg)
+{
+ if (dphy->ops->set_clk_lane_cfg)
+ dphy->ops->set_clk_lane_cfg(dphy, cfg);
+}
+
+static void cdns_dphy_set_pll_cfg(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg)
+{
+ if (dphy->ops->set_pll_cfg)
+ dphy->ops->set_pll_cfg(dphy, cfg);
+}
+
+static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy)
+{
+ return dphy->ops->get_wakeup_time_ns(dphy);
+}
+
+static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy)
+{
+ /* Default wakeup time is 800 ns (in a simulated environment). */
+ return 800;
+}
+
+static void cdns_dphy_ref_set_pll_cfg(struct cdns_dphy *dphy,
+ const struct cdns_dphy_cfg *cfg)
+{
+ u32 fbdiv_low, fbdiv_high;
+
+ fbdiv_low = (cfg->pll_fbdiv / 4) - 2;
+ fbdiv_high = cfg->pll_fbdiv - fbdiv_low - 2;
+
+ writel(DPHY_CMN_IPDIV_FROM_REG | DPHY_CMN_OPDIV_FROM_REG |
+ DPHY_CMN_IPDIV(cfg->pll_ipdiv) |
+ DPHY_CMN_OPDIV(cfg->pll_opdiv),
+ dphy->regs + DPHY_CMN_OPIPDIV);
+ writel(DPHY_CMN_FBDIV_FROM_REG |
+ DPHY_CMN_FBDIV_VAL(fbdiv_low, fbdiv_high),
+ dphy->regs + DPHY_CMN_FBDIV);
+ writel(DPHY_CMN_PWM_HIGH(6) | DPHY_CMN_PWM_LOW(0x101) |
+ DPHY_CMN_PWM_DIV(0x8),
+ dphy->regs + DPHY_CMN_PWM);
+}
+
+static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
+{
+ writel(DPHY_PSM_CFG_FROM_REG | DPHY_PSM_CLK_DIV(div),
+ dphy->regs + DPHY_PSM_CFG);
+}
+
+/*
+ * This is the reference implementation of DPHY hooks. Specific integration of
+ * this IP may have to re-implement some of them depending on how they decided
+ * to wire things in the SoC.
+ */
+static const struct cdns_dphy_ops ref_dphy_ops = {
+ .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
+ .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
+ .set_psm_div = cdns_dphy_ref_set_psm_div,
+};
+
+static int cdns_dphy_config_from_opts(struct phy *phy,
+ struct phy_configure_opts_mipi_dphy *opts,
+ struct cdns_dphy_cfg *cfg)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ unsigned int dsi_hfp_ext = 0;
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(opts);
+ if (ret)
+ return ret;
+
+ ret = cdns_dsi_get_dphy_pll_cfg(dphy, cfg,
+ opts, &dsi_hfp_ext);
+ if (ret)
+ return ret;
+
+ opts->wakeup = cdns_dphy_get_wakeup_time_ns(dphy) / 1000;
+
+ return 0;
+}
+
+static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ struct cdns_dphy_cfg cfg = { 0 };
+
+ if (mode != PHY_MODE_MIPI_DPHY)
+ return -EINVAL;
+
+ return cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
+}
+
+static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ struct cdns_dphy_cfg cfg = { 0 };
+ int ret;
+
+ ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure the internal PSM clk divider so that the DPHY has a
+ * 1MHz clk (or something close).
+ */
+ ret = cdns_dphy_setup_psm(dphy);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
+ * and 8 data lanes, each clk lane can be attache different set of
+ * data lanes. The 2 groups are named 'left' and 'right', so here we
+ * just say that we want the 'left' clk lane to drive the 'left' data
+ * lanes.
+ */
+ cdns_dphy_set_clk_lane_cfg(dphy, DPHY_CLK_CFG_LEFT_DRIVES_LEFT);
+
+ /*
+ * Configure the DPHY PLL that will be used to generate the TX byte
+ * clk.
+ */
+ cdns_dphy_set_pll_cfg(dphy, &cfg);
+
+ return 0;
+}
+
+static int cdns_dphy_power_on(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ clk_prepare_enable(dphy->psm_clk);
+ clk_prepare_enable(dphy->pll_ref_clk);
+
+ /* Start TX state machine. */
+ writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN,
+ dphy->regs + DPHY_CMN_SSM);
+
+ return 0;
+}
+
+static int cdns_dphy_power_off(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(dphy->pll_ref_clk);
+ clk_disable_unprepare(dphy->psm_clk);
+
+ return 0;
+}
+
+static const struct phy_ops cdns_dphy_ops = {
+ .configure = cdns_dphy_configure,
+ .validate = cdns_dphy_validate,
+ .power_on = cdns_dphy_power_on,
+ .power_off = cdns_dphy_power_off,
+};
+
+static int cdns_dphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct cdns_dphy *dphy;
+ struct resource *res;
+ int ret;
+
+ dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
+ if (!dphy)
+ return -ENOMEM;
+ dev_set_drvdata(&pdev->dev, dphy);
+
+ dphy->ops = of_device_get_match_data(&pdev->dev);
+ if (!dphy->ops)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dphy->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dphy->regs))
+ return PTR_ERR(dphy->regs);
+
+ dphy->psm_clk = devm_clk_get(&pdev->dev, "psm");
+ if (IS_ERR(dphy->psm_clk))
+ return PTR_ERR(dphy->psm_clk);
+
+ dphy->pll_ref_clk = devm_clk_get(&pdev->dev, "pll_ref");
+ if (IS_ERR(dphy->pll_ref_clk))
+ return PTR_ERR(dphy->pll_ref_clk);
+
+ if (dphy->ops->probe) {
+ ret = dphy->ops->probe(dphy);
+ if (ret)
+ return ret;
+ }
+
+ dphy->phy = devm_phy_create(&pdev->dev, NULL, &cdns_dphy_ops);
+ if (IS_ERR(dphy->phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ if (dphy->ops->remove)
+ dphy->ops->remove(dphy);
+ return PTR_ERR(dphy->phy);
+ }
+
+ phy_set_drvdata(dphy->phy, dphy);
+ phy_provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int cdns_dphy_remove(struct platform_device *pdev)
+{
+ struct cdns_dphy *dphy = dev_get_drvdata(&pdev->dev);
+
+ if (dphy->ops->remove)
+ dphy->ops->remove(dphy);
+
+ return 0;
+}
+
+static const struct of_device_id cdns_dphy_of_match[] = {
+ { .compatible = "cdns,dphy", .data = &ref_dphy_ops },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cdns_dphy_of_match);
+
+static struct platform_driver cdns_dphy_platform_driver = {
+ .probe = cdns_dphy_probe,
+ .remove = cdns_dphy_remove,
+ .driver = {
+ .name = "cdns-mipi-dphy",
+ .of_match_table = cdns_dphy_of_match,
+ },
+};
+module_platform_driver(cdns_dphy_platform_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
+MODULE_DESCRIPTION("Cadence MIPI D-PHY Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index f050bd4e97e0..832670b4952b 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -2,4 +2,4 @@ config PHY_FSL_IMX8MQ_USB
tristate "Freescale i.MX8M USB3 PHY"
depends on OF && HAS_IOMEM
select GENERIC_PHY
- default SOC_IMX8MQ
+ default ARCH_MXC && ARM64
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
index 6fb4b56e4c14..9ba872325dad 100644
--- a/drivers/phy/marvell/Kconfig
+++ b/drivers/phy/marvell/Kconfig
@@ -21,6 +21,37 @@ config PHY_BERLIN_USB
help
Enable this to support the USB PHY on Marvell Berlin SoCs.
+config PHY_MVEBU_A3700_COMPHY
+ tristate "Marvell A3700 comphy driver"
+ depends on ARCH_MVEBU || COMPILE_TEST
+ depends on OF
+ depends on HAVE_ARM_SMCCC
+ default y
+ select GENERIC_PHY
+ help
+ This driver allows to control the comphy, a hardware block providing
+ shared serdes PHYs on Marvell Armada 3700. Its serdes lanes can be
+ used by various controllers: Ethernet, SATA, USB3, PCIe.
+
+config PHY_MVEBU_A3700_UTMI
+ tristate "Marvell A3700 UTMI driver"
+ depends on ARCH_MVEBU || COMPILE_TEST
+ depends on OF
+ default y
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell A3700 UTMI PHY driver.
+
+config PHY_MVEBU_A38X_COMPHY
+ tristate "Marvell Armada 38x comphy driver"
+ depends on ARCH_MVEBU || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ This driver allows to control the comphy, an hardware block providing
+ shared serdes PHYs on Marvell Armada 38x. Its serdes lanes can be
+ used by various controllers (Ethernet, sata, usb, PCIe...).
+
config PHY_MVEBU_CP110_COMPHY
tristate "Marvell CP110 comphy driver"
depends on ARCH_MVEBU || COMPILE_TEST
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
index 3975b144f8ec..434eb9ca6cc3 100644
--- a/drivers/phy/marvell/Makefile
+++ b/drivers/phy/marvell/Makefile
@@ -2,6 +2,9 @@
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_A3700_COMPHY) += phy-mvebu-a3700-comphy.o
+obj-$(CONFIG_PHY_MVEBU_A3700_UTMI) += phy-mvebu-a3700-utmi.o
+obj-$(CONFIG_PHY_MVEBU_A38X_COMPHY) += phy-armada38x-comphy.o
obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
index 1a3db288c0a9..fa5dc9462d09 100644
--- a/drivers/phy/marvell/phy-armada375-usb2.c
+++ b/drivers/phy/marvell/phy-armada375-usb2.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* USB cluster support for Armada 375 platform.
*
@@ -5,10 +6,6 @@
*
* Gregory CLEMENT <gregory.clement@free-electrons.com>
*
- * This file is licensed under the terms of the GNU General Public
- * License version 2 or later. This program is licensed "as is"
- * without any warranty of any kind, whether express or implied.
- *
* Armada 375 comes with an USB2 host and device controller and an
* USB3 controller. The USB cluster control register allows to manage
* common features of both USB controllers.
@@ -18,7 +15,6 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
@@ -142,7 +138,6 @@ static const struct of_device_id of_usb_cluster_table[] = {
{ .compatible = "marvell,armada-375-usb-cluster", },
{ /* end of list */ },
};
-MODULE_DEVICE_TABLE(of, of_usb_cluster_table);
static struct platform_driver armada375_usb_phy_driver = {
.probe = armada375_usb_phy_probe,
@@ -151,8 +146,4 @@ static struct platform_driver armada375_usb_phy_driver = {
.name = "armada-375-usb-cluster",
}
};
-module_platform_driver(armada375_usb_phy_driver);
-
-MODULE_DESCRIPTION("Armada 375 USB cluster driver");
-MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(armada375_usb_phy_driver);
diff --git a/drivers/phy/marvell/phy-armada38x-comphy.c b/drivers/phy/marvell/phy-armada38x-comphy.c
new file mode 100644
index 000000000000..3e00bc679d4e
--- /dev/null
+++ b/drivers/phy/marvell/phy-armada38x-comphy.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Russell King, Deep Blue Solutions Ltd.
+ *
+ * Partly derived from CP110 comphy driver by Antoine Tenart
+ * <antoine.tenart@bootlin.com>
+ */
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+
+#define MAX_A38X_COMPHY 6
+#define MAX_A38X_PORTS 3
+
+#define COMPHY_CFG1 0x00
+#define COMPHY_CFG1_GEN_TX(x) ((x) << 26)
+#define COMPHY_CFG1_GEN_TX_MSK COMPHY_CFG1_GEN_TX(15)
+#define COMPHY_CFG1_GEN_RX(x) ((x) << 22)
+#define COMPHY_CFG1_GEN_RX_MSK COMPHY_CFG1_GEN_RX(15)
+#define GEN_SGMII_1_25GBPS 6
+#define GEN_SGMII_3_125GBPS 8
+
+#define COMPHY_STAT1 0x18
+#define COMPHY_STAT1_PLL_RDY_TX BIT(3)
+#define COMPHY_STAT1_PLL_RDY_RX BIT(2)
+
+#define COMPHY_SELECTOR 0xfc
+
+struct a38x_comphy;
+
+struct a38x_comphy_lane {
+ void __iomem *base;
+ struct a38x_comphy *priv;
+ unsigned int n;
+
+ int port;
+};
+
+struct a38x_comphy {
+ void __iomem *base;
+ struct device *dev;
+ struct a38x_comphy_lane lane[MAX_A38X_COMPHY];
+};
+
+static const u8 gbe_mux[MAX_A38X_COMPHY][MAX_A38X_PORTS] = {
+ { 0, 0, 0 },
+ { 4, 5, 0 },
+ { 0, 4, 0 },
+ { 0, 0, 4 },
+ { 0, 3, 0 },
+ { 0, 0, 3 },
+};
+
+static void a38x_comphy_set_reg(struct a38x_comphy_lane *lane,
+ unsigned int offset, u32 mask, u32 value)
+{
+ u32 val;
+
+ val = readl_relaxed(lane->base + offset) & ~mask;
+ writel(val | value, lane->base + offset);
+}
+
+static void a38x_comphy_set_speed(struct a38x_comphy_lane *lane,
+ unsigned int gen_tx, unsigned int gen_rx)
+{
+ a38x_comphy_set_reg(lane, COMPHY_CFG1,
+ COMPHY_CFG1_GEN_TX_MSK | COMPHY_CFG1_GEN_RX_MSK,
+ COMPHY_CFG1_GEN_TX(gen_tx) |
+ COMPHY_CFG1_GEN_RX(gen_rx));
+}
+
+static int a38x_comphy_poll(struct a38x_comphy_lane *lane,
+ unsigned int offset, u32 mask, u32 value)
+{
+ u32 val;
+ int ret;
+
+ ret = readl_relaxed_poll_timeout_atomic(lane->base + offset, val,
+ (val & mask) == value,
+ 1000, 150000);
+
+ if (ret)
+ dev_err(lane->priv->dev,
+ "comphy%u: timed out waiting for status\n", lane->n);
+
+ return ret;
+}
+
+/*
+ * We only support changing the speed for comphys configured for GBE.
+ * Since that is all we do, we only poll for PLL ready status.
+ */
+static int a38x_comphy_set_mode(struct phy *phy, enum phy_mode mode, int sub)
+{
+ struct a38x_comphy_lane *lane = phy_get_drvdata(phy);
+ unsigned int gen;
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ switch (sub) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ gen = GEN_SGMII_1_25GBPS;
+ break;
+
+ case PHY_INTERFACE_MODE_2500BASEX:
+ gen = GEN_SGMII_3_125GBPS;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ a38x_comphy_set_speed(lane, gen, gen);
+
+ return a38x_comphy_poll(lane, COMPHY_STAT1,
+ COMPHY_STAT1_PLL_RDY_TX |
+ COMPHY_STAT1_PLL_RDY_RX,
+ COMPHY_STAT1_PLL_RDY_TX |
+ COMPHY_STAT1_PLL_RDY_RX);
+}
+
+static const struct phy_ops a38x_comphy_ops = {
+ .set_mode = a38x_comphy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *a38x_comphy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct a38x_comphy_lane *lane;
+ struct phy *phy;
+ u32 val;
+
+ if (WARN_ON(args->args[0] >= MAX_A38X_PORTS))
+ return ERR_PTR(-EINVAL);
+
+ phy = of_phy_simple_xlate(dev, args);
+ if (IS_ERR(phy))
+ return phy;
+
+ lane = phy_get_drvdata(phy);
+ if (lane->port >= 0)
+ return ERR_PTR(-EBUSY);
+
+ lane->port = args->args[0];
+
+ val = readl_relaxed(lane->priv->base + COMPHY_SELECTOR);
+ val = (val >> (4 * lane->n)) & 0xf;
+
+ if (!gbe_mux[lane->n][lane->port] ||
+ val != gbe_mux[lane->n][lane->port]) {
+ dev_warn(lane->priv->dev,
+ "comphy%u: not configured for GBE\n", lane->n);
+ phy = ERR_PTR(-EINVAL);
+ }
+
+ return phy;
+}
+
+static int a38x_comphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *provider;
+ struct device_node *child;
+ struct a38x_comphy *priv;
+ struct resource *res;
+ void __iomem *base;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->dev = &pdev->dev;
+ priv->base = base;
+
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ struct phy *phy;
+ int ret;
+ u32 val;
+
+ ret = of_property_read_u32(child, "reg", &val);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
+ ret);
+ continue;
+ }
+
+ if (val >= MAX_A38X_COMPHY || priv->lane[val].base) {
+ dev_err(&pdev->dev, "invalid 'reg' property\n");
+ continue;
+ }
+
+ phy = devm_phy_create(&pdev->dev, child, &a38x_comphy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ priv->lane[val].base = base + 0x28 * val;
+ priv->lane[val].priv = priv;
+ priv->lane[val].n = val;
+ priv->lane[val].port = -1;
+ phy_set_drvdata(phy, &priv->lane[val]);
+ }
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ provider = devm_of_phy_provider_register(&pdev->dev, a38x_comphy_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id a38x_comphy_of_match_table[] = {
+ { .compatible = "marvell,armada-380-comphy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, a38x_comphy_of_match_table);
+
+static struct platform_driver a38x_comphy_driver = {
+ .probe = a38x_comphy_probe,
+ .driver = {
+ .name = "armada-38x-comphy",
+ .of_match_table = a38x_comphy_of_match_table,
+ },
+};
+module_platform_driver(a38x_comphy_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@armlinux.org.uk>");
+MODULE_DESCRIPTION("Common PHY driver for Armada 38x SoCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c
index a91fc67fc4e0..d70ba9bc42d9 100644
--- a/drivers/phy/marvell/phy-berlin-sata.c
+++ b/drivers/phy/marvell/phy-berlin-sata.c
@@ -32,7 +32,7 @@
/* register 0x01 */
#define REF_FREF_SEL_25 BIT(0)
-#define PHY_MODE_SATA (0x0 << 5)
+#define PHY_BERLIN_MODE_SATA (0x0 << 5)
/* register 0x02 */
#define USE_MAX_PLL_RATE BIT(12)
@@ -102,7 +102,8 @@ static int phy_berlin_sata_power_on(struct phy *phy)
/* set PHY mode and ref freq to 25 MHz */
phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
- 0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
+ 0x00ff,
+ REF_FREF_SEL_25 | PHY_BERLIN_MODE_SATA);
/* set PHY up to 6 Gbps */
phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
new file mode 100644
index 000000000000..8812a104c233
--- /dev/null
+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Marvell
+ *
+ * Authors:
+ * Evan Wang <xswang@marvell.com>
+ * Miquèl Raynal <miquel.raynal@bootlin.com>
+ *
+ * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart.
+ * SMC call initial support done by Grzegorz Jaszczyk.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define MVEBU_A3700_COMPHY_LANES 3
+#define MVEBU_A3700_COMPHY_PORTS 2
+
+/* COMPHY Fast SMC function identifiers */
+#define COMPHY_SIP_POWER_ON 0x82000001
+#define COMPHY_SIP_POWER_OFF 0x82000002
+#define COMPHY_SIP_PLL_LOCK 0x82000003
+
+#define COMPHY_FW_MODE_SATA 0x1
+#define COMPHY_FW_MODE_SGMII 0x2
+#define COMPHY_FW_MODE_HS_SGMII 0x3
+#define COMPHY_FW_MODE_USB3H 0x4
+#define COMPHY_FW_MODE_USB3D 0x5
+#define COMPHY_FW_MODE_PCIE 0x6
+#define COMPHY_FW_MODE_RXAUI 0x7
+#define COMPHY_FW_MODE_XFI 0x8
+#define COMPHY_FW_MODE_SFI 0x9
+#define COMPHY_FW_MODE_USB3 0xa
+
+#define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */
+#define COMPHY_FW_SPEED_2_5G 1
+#define COMPHY_FW_SPEED_3_125G 2 /* SGMII 2.5G */
+#define COMPHY_FW_SPEED_5G 3
+#define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */
+#define COMPHY_FW_SPEED_6G 5
+#define COMPHY_FW_SPEED_10_3125G 6 /* XFI 10G */
+#define COMPHY_FW_SPEED_MAX 0x3F
+
+#define COMPHY_FW_MODE(mode) ((mode) << 12)
+#define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \
+ ((idx) << 8) | \
+ ((speed) << 2))
+#define COMPHY_FW_PCIE(mode, idx, speed, width) (COMPHY_FW_NET(mode, idx, speed) | \
+ ((width) << 18))
+
+struct mvebu_a3700_comphy_conf {
+ unsigned int lane;
+ enum phy_mode mode;
+ int submode;
+ unsigned int port;
+ u32 fw_mode;
+};
+
+#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw) \
+ { \
+ .lane = _lane, \
+ .mode = _mode, \
+ .submode = _smode, \
+ .port = _port, \
+ .fw_mode = _fw, \
+ }
+
+#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \
+ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw)
+
+#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \
+ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw)
+
+static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = {
+ /* lane 0 */
+ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0,
+ COMPHY_FW_MODE_USB3H),
+ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1,
+ COMPHY_FW_MODE_SGMII),
+ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1,
+ COMPHY_FW_MODE_HS_SGMII),
+ /* lane 1 */
+ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0,
+ COMPHY_FW_MODE_PCIE),
+ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0,
+ COMPHY_FW_MODE_SGMII),
+ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0,
+ COMPHY_FW_MODE_HS_SGMII),
+ /* lane 2 */
+ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0,
+ COMPHY_FW_MODE_SATA),
+ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0,
+ COMPHY_FW_MODE_USB3H),
+};
+
+struct mvebu_a3700_comphy_lane {
+ struct device *dev;
+ unsigned int id;
+ enum phy_mode mode;
+ int submode;
+ int port;
+};
+
+static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane,
+ unsigned long mode)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res);
+
+ return res.a0;
+}
+
+static int mvebu_a3700_comphy_get_fw_mode(int lane, int port,
+ enum phy_mode mode,
+ int submode)
+{
+ int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes);
+
+ /* Unused PHY mux value is 0x0 */
+ if (mode == PHY_MODE_INVALID)
+ return -EINVAL;
+
+ for (i = 0; i < n; i++) {
+ if (mvebu_a3700_comphy_modes[i].lane == lane &&
+ mvebu_a3700_comphy_modes[i].port == port &&
+ mvebu_a3700_comphy_modes[i].mode == mode &&
+ mvebu_a3700_comphy_modes[i].submode == submode)
+ break;
+ }
+
+ if (i == n)
+ return -EINVAL;
+
+ return mvebu_a3700_comphy_modes[i].fw_mode;
+}
+
+static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
+ int fw_mode;
+
+ if (submode == PHY_INTERFACE_MODE_1000BASEX)
+ submode = PHY_INTERFACE_MODE_SGMII;
+
+ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode,
+ submode);
+ if (fw_mode < 0) {
+ dev_err(lane->dev, "invalid COMPHY mode\n");
+ return fw_mode;
+ }
+
+ /* Just remember the mode, ->power_on() will do the real setup */
+ lane->mode = mode;
+ lane->submode = submode;
+
+ return 0;
+}
+
+static int mvebu_a3700_comphy_power_on(struct phy *phy)
+{
+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
+ u32 fw_param;
+ int fw_mode;
+
+ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port,
+ lane->mode, lane->submode);
+ if (fw_mode < 0) {
+ dev_err(lane->dev, "invalid COMPHY mode\n");
+ return fw_mode;
+ }
+
+ switch (lane->mode) {
+ case PHY_MODE_USB_HOST_SS:
+ dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id);
+ fw_param = COMPHY_FW_MODE(fw_mode);
+ break;
+ case PHY_MODE_SATA:
+ dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id);
+ fw_param = COMPHY_FW_MODE(fw_mode);
+ break;
+ case PHY_MODE_ETHERNET:
+ switch (lane->submode) {
+ case PHY_INTERFACE_MODE_SGMII:
+ dev_dbg(lane->dev, "set lane %d to SGMII mode\n",
+ lane->id);
+ fw_param = COMPHY_FW_NET(fw_mode, lane->port,
+ COMPHY_FW_SPEED_1_25G);
+ break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n",
+ lane->id);
+ fw_param = COMPHY_FW_NET(fw_mode, lane->port,
+ COMPHY_FW_SPEED_3_125G);
+ break;
+ default:
+ dev_err(lane->dev, "unsupported PHY submode (%d)\n",
+ lane->submode);
+ return -ENOTSUPP;
+ }
+ break;
+ case PHY_MODE_PCIE:
+ dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id);
+ fw_param = COMPHY_FW_PCIE(fw_mode, lane->port,
+ COMPHY_FW_SPEED_5G,
+ phy->attrs.bus_width);
+ break;
+ default:
+ dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode);
+ return -ENOTSUPP;
+ }
+
+ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param);
+}
+
+static int mvebu_a3700_comphy_power_off(struct phy *phy)
+{
+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
+
+ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0);
+}
+
+static const struct phy_ops mvebu_a3700_comphy_ops = {
+ .power_on = mvebu_a3700_comphy_power_on,
+ .power_off = mvebu_a3700_comphy_power_off,
+ .set_mode = mvebu_a3700_comphy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *mvebu_a3700_comphy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct mvebu_a3700_comphy_lane *lane;
+ struct phy *phy;
+
+ if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS))
+ return ERR_PTR(-EINVAL);
+
+ phy = of_phy_simple_xlate(dev, args);
+ if (IS_ERR(phy))
+ return phy;
+
+ lane = phy_get_drvdata(phy);
+ lane->port = args->args[0];
+
+ return phy;
+}
+
+static int mvebu_a3700_comphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *provider;
+ struct device_node *child;
+
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ struct mvebu_a3700_comphy_lane *lane;
+ struct phy *phy;
+ int ret;
+ u32 lane_id;
+
+ ret = of_property_read_u32(child, "reg", &lane_id);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
+ ret);
+ continue;
+ }
+
+ if (lane_id >= MVEBU_A3700_COMPHY_LANES) {
+ dev_err(&pdev->dev, "invalid 'reg' property\n");
+ continue;
+ }
+
+ lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL);
+ if (!lane)
+ return -ENOMEM;
+
+ phy = devm_phy_create(&pdev->dev, child,
+ &mvebu_a3700_comphy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ lane->dev = &pdev->dev;
+ lane->mode = PHY_MODE_INVALID;
+ lane->submode = PHY_INTERFACE_MODE_NA;
+ lane->id = lane_id;
+ lane->port = -1;
+ phy_set_drvdata(phy, lane);
+ }
+
+ provider = devm_of_phy_provider_register(&pdev->dev,
+ mvebu_a3700_comphy_xlate);
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id mvebu_a3700_comphy_of_match_table[] = {
+ { .compatible = "marvell,comphy-a3700" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, mvebu_a3700_comphy_of_match_table);
+
+static struct platform_driver mvebu_a3700_comphy_driver = {
+ .probe = mvebu_a3700_comphy_probe,
+ .driver = {
+ .name = "mvebu-a3700-comphy",
+ .of_match_table = mvebu_a3700_comphy_of_match_table,
+ },
+};
+module_platform_driver(mvebu_a3700_comphy_driver);
+
+MODULE_AUTHOR("Miquèl Raynal <miquel.raynal@bootlin.com>");
+MODULE_DESCRIPTION("Common PHY driver for A3700");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-mvebu-a3700-utmi.c b/drivers/phy/marvell/phy-mvebu-a3700-utmi.c
new file mode 100644
index 000000000000..94a29dea57af
--- /dev/null
+++ b/drivers/phy/marvell/phy-mvebu-a3700-utmi.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Marvell
+ *
+ * Authors:
+ * Igal Liberman <igall@marvell.com>
+ * Miquèl Raynal <miquel.raynal@bootlin.com>
+ *
+ * Marvell A3700 UTMI PHY driver
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Armada 3700 UTMI PHY registers */
+#define USB2_PHY_PLL_CTRL_REG0 0x0
+#define PLL_REF_DIV_OFF 0
+#define PLL_REF_DIV_MASK GENMASK(6, 0)
+#define PLL_REF_DIV_5 5
+#define PLL_FB_DIV_OFF 16
+#define PLL_FB_DIV_MASK GENMASK(24, 16)
+#define PLL_FB_DIV_96 96
+#define PLL_SEL_LPFR_OFF 28
+#define PLL_SEL_LPFR_MASK GENMASK(29, 28)
+#define PLL_READY BIT(31)
+#define USB2_PHY_CAL_CTRL 0x8
+#define PHY_PLLCAL_DONE BIT(31)
+#define PHY_IMPCAL_DONE BIT(23)
+#define USB2_RX_CHAN_CTRL1 0x18
+#define USB2PHY_SQCAL_DONE BIT(31)
+#define USB2_PHY_OTG_CTRL 0x34
+#define PHY_PU_OTG BIT(4)
+#define USB2_PHY_CHRGR_DETECT 0x38
+#define PHY_CDP_EN BIT(2)
+#define PHY_DCP_EN BIT(3)
+#define PHY_PD_EN BIT(4)
+#define PHY_PU_CHRG_DTC BIT(5)
+#define PHY_CDP_DM_AUTO BIT(7)
+#define PHY_ENSWITCH_DP BIT(12)
+#define PHY_ENSWITCH_DM BIT(13)
+
+/* Armada 3700 USB miscellaneous registers */
+#define USB2_PHY_CTRL(usb32) (usb32 ? 0x20 : 0x4)
+#define RB_USB2PHY_PU BIT(0)
+#define USB2_DP_PULLDN_DEV_MODE BIT(5)
+#define USB2_DM_PULLDN_DEV_MODE BIT(6)
+#define RB_USB2PHY_SUSPM(usb32) (usb32 ? BIT(14) : BIT(7))
+
+#define PLL_LOCK_DELAY_US 10000
+#define PLL_LOCK_TIMEOUT_US 1000000
+
+/**
+ * struct mvebu_a3700_utmi_caps - PHY capabilities
+ *
+ * @usb32: Flag indicating which PHY is in use (impacts the register map):
+ * - The UTMI PHY wired to the USB3/USB2 controller (otg)
+ * - The UTMI PHY wired to the USB2 controller (host only)
+ * @ops: PHY operations
+ */
+struct mvebu_a3700_utmi_caps {
+ int usb32;
+ const struct phy_ops *ops;
+};
+
+/**
+ * struct mvebu_a3700_utmi - PHY driver data
+ *
+ * @regs: PHY registers
+ * @usb_mis: Regmap with USB miscellaneous registers including PHY ones
+ * @caps: PHY capabilities
+ * @phy: PHY handle
+ */
+struct mvebu_a3700_utmi {
+ void __iomem *regs;
+ struct regmap *usb_misc;
+ const struct mvebu_a3700_utmi_caps *caps;
+ struct phy *phy;
+};
+
+static int mvebu_a3700_utmi_phy_power_on(struct phy *phy)
+{
+ struct mvebu_a3700_utmi *utmi = phy_get_drvdata(phy);
+ struct device *dev = &phy->dev;
+ int usb32 = utmi->caps->usb32;
+ int ret = 0;
+ u32 reg;
+
+ /*
+ * Setup PLL. 40MHz clock used to be the default, being 25MHz now.
+ * See "PLL Settings for Typical REFCLK" table.
+ */
+ reg = readl(utmi->regs + USB2_PHY_PLL_CTRL_REG0);
+ reg &= ~(PLL_REF_DIV_MASK | PLL_FB_DIV_MASK | PLL_SEL_LPFR_MASK);
+ reg |= (PLL_REF_DIV_5 << PLL_REF_DIV_OFF) |
+ (PLL_FB_DIV_96 << PLL_FB_DIV_OFF);
+ writel(reg, utmi->regs + USB2_PHY_PLL_CTRL_REG0);
+
+ /* Enable PHY pull up and disable USB2 suspend */
+ regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
+ RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU,
+ RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU);
+
+ if (usb32) {
+ /* Power up OTG module */
+ reg = readl(utmi->regs + USB2_PHY_OTG_CTRL);
+ reg |= PHY_PU_OTG;
+ writel(reg, utmi->regs + USB2_PHY_OTG_CTRL);
+
+ /* Disable PHY charger detection */
+ reg = readl(utmi->regs + USB2_PHY_CHRGR_DETECT);
+ reg &= ~(PHY_CDP_EN | PHY_DCP_EN | PHY_PD_EN | PHY_PU_CHRG_DTC |
+ PHY_CDP_DM_AUTO | PHY_ENSWITCH_DP | PHY_ENSWITCH_DM);
+ writel(reg, utmi->regs + USB2_PHY_CHRGR_DETECT);
+
+ /* Disable PHY DP/DM pull-down (used for device mode) */
+ regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
+ USB2_DP_PULLDN_DEV_MODE |
+ USB2_DM_PULLDN_DEV_MODE, 0);
+ }
+
+ /* Wait for PLL calibration */
+ ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
+ reg & PHY_PLLCAL_DONE,
+ PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "Failed to end USB2 PLL calibration\n");
+ return ret;
+ }
+
+ /* Wait for impedance calibration */
+ ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
+ reg & PHY_IMPCAL_DONE,
+ PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "Failed to end USB2 impedance calibration\n");
+ return ret;
+ }
+
+ /* Wait for squelch calibration */
+ ret = readl_poll_timeout(utmi->regs + USB2_RX_CHAN_CTRL1, reg,
+ reg & USB2PHY_SQCAL_DONE,
+ PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "Failed to end USB2 unknown calibration\n");
+ return ret;
+ }
+
+ /* Wait for PLL to be locked */
+ ret = readl_poll_timeout(utmi->regs + USB2_PHY_PLL_CTRL_REG0, reg,
+ reg & PLL_READY,
+ PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
+ if (ret)
+ dev_err(dev, "Failed to lock USB2 PLL\n");
+
+ return ret;
+}
+
+static int mvebu_a3700_utmi_phy_power_off(struct phy *phy)
+{
+ struct mvebu_a3700_utmi *utmi = phy_get_drvdata(phy);
+ int usb32 = utmi->caps->usb32;
+ u32 reg;
+
+ /* Disable PHY pull-up and enable USB2 suspend */
+ reg = readl(utmi->regs + USB2_PHY_CTRL(usb32));
+ reg &= ~(RB_USB2PHY_PU | RB_USB2PHY_SUSPM(usb32));
+ writel(reg, utmi->regs + USB2_PHY_CTRL(usb32));
+
+ /* Power down OTG module */
+ if (usb32) {
+ reg = readl(utmi->regs + USB2_PHY_OTG_CTRL);
+ reg &= ~PHY_PU_OTG;
+ writel(reg, utmi->regs + USB2_PHY_OTG_CTRL);
+ }
+
+ return 0;
+}
+
+static const struct phy_ops mvebu_a3700_utmi_phy_ops = {
+ .power_on = mvebu_a3700_utmi_phy_power_on,
+ .power_off = mvebu_a3700_utmi_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static const struct mvebu_a3700_utmi_caps mvebu_a3700_utmi_otg_phy_caps = {
+ .usb32 = true,
+ .ops = &mvebu_a3700_utmi_phy_ops,
+};
+
+static const struct mvebu_a3700_utmi_caps mvebu_a3700_utmi_host_phy_caps = {
+ .usb32 = false,
+ .ops = &mvebu_a3700_utmi_phy_ops,
+};
+
+static const struct of_device_id mvebu_a3700_utmi_of_match[] = {
+ {
+ .compatible = "marvell,a3700-utmi-otg-phy",
+ .data = &mvebu_a3700_utmi_otg_phy_caps,
+ },
+ {
+ .compatible = "marvell,a3700-utmi-host-phy",
+ .data = &mvebu_a3700_utmi_host_phy_caps,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mvebu_a3700_utmi_of_match);
+
+static int mvebu_a3700_utmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mvebu_a3700_utmi *utmi;
+ struct phy_provider *provider;
+ struct resource *res;
+
+ utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
+ if (!utmi)
+ return -ENOMEM;
+
+ /* Get UTMI memory region */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Missing UTMI PHY memory resource\n");
+ return -ENODEV;
+ }
+
+ utmi->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(utmi->regs))
+ return PTR_ERR(utmi->regs);
+
+ /* Get miscellaneous Host/PHY region */
+ utmi->usb_misc = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "marvell,usb-misc-reg");
+ if (IS_ERR(utmi->usb_misc)) {
+ dev_err(dev,
+ "Missing USB misc purpose system controller\n");
+ return PTR_ERR(utmi->usb_misc);
+ }
+
+ /* Retrieve PHY capabilities */
+ utmi->caps = of_device_get_match_data(dev);
+
+ /* Instantiate the PHY */
+ utmi->phy = devm_phy_create(dev, NULL, utmi->caps->ops);
+ if (IS_ERR(utmi->phy)) {
+ dev_err(dev, "Failed to create the UTMI PHY\n");
+ return PTR_ERR(utmi->phy);
+ }
+
+ phy_set_drvdata(utmi->phy, utmi);
+
+ /* Ensure the PHY is powered off */
+ utmi->caps->ops->power_off(utmi->phy);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static struct platform_driver mvebu_a3700_utmi_driver = {
+ .probe = mvebu_a3700_utmi_phy_probe,
+ .driver = {
+ .name = "mvebu-a3700-utmi-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = mvebu_a3700_utmi_of_match,
+ },
+};
+module_platform_driver(mvebu_a3700_utmi_driver);
+
+MODULE_AUTHOR("Igal Liberman <igall@marvell.com>");
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
+MODULE_DESCRIPTION("Marvell EBU A3700 UTMI PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
index 187cccde53b5..d98e0451f6a1 100644
--- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
+++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
@@ -580,8 +580,6 @@ static struct phy *mvebu_comphy_xlate(struct device *dev,
return phy;
lane = phy_get_drvdata(phy);
- if (lane->port >= 0)
- return ERR_PTR(-EBUSY);
lane->port = args->args[0];
return phy;
diff --git a/drivers/phy/marvell/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c
index 768ce92e81ce..369fece2be7a 100644
--- a/drivers/phy/marvell/phy-mvebu-sata.c
+++ b/drivers/phy/marvell/phy-mvebu-sata.c
@@ -10,7 +10,7 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/clk.h>
#include <linux/phy/phy.h>
#include <linux/io.h>
@@ -122,7 +122,6 @@ static const struct of_device_id phy_mvebu_sata_of_match[] = {
{ .compatible = "marvell,mvebu-sata-phy" },
{ },
};
-MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match);
static struct platform_driver phy_mvebu_sata_driver = {
.probe = phy_mvebu_sata_probe,
@@ -131,8 +130,4 @@ static struct platform_driver phy_mvebu_sata_driver = {
.of_match_table = phy_mvebu_sata_of_match,
}
};
-module_platform_driver(phy_mvebu_sata_driver);
-
-MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
-MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(phy_mvebu_sata_driver);
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
index 465fa1b91a5f..14e0551cd319 100644
--- a/drivers/phy/phy-core-mipi-dphy.c
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -65,12 +65,12 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
*/
cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
- cfg->init = 100000000;
+ cfg->init = 100;
cfg->lpx = 60000;
cfg->ta_get = 5 * cfg->lpx;
cfg->ta_go = 4 * cfg->lpx;
cfg->ta_sure = 2 * cfg->lpx;
- cfg->wakeup = 1000000000;
+ cfg->wakeup = 1000;
cfg->hs_clk_rate = hs_clk_rate;
cfg->lanes = lanes;
@@ -143,7 +143,7 @@ int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))
return -EINVAL;
- if (cfg->init < 100000000)
+ if (cfg->init < 100)
return -EINVAL;
if (cfg->lpx < 50000)
@@ -158,7 +158,7 @@ int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))
return -EINVAL;
- if (cfg->wakeup < 1000000000)
+ if (cfg->wakeup < 1000)
return -EINVAL;
return 0;
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 19b05e824ee4..cb38f6e8614c 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -1112,14 +1112,4 @@ static int __init phy_core_init(void)
return 0;
}
-module_init(phy_core_init);
-
-static void __exit phy_core_exit(void)
-{
- class_destroy(phy_class);
-}
-module_exit(phy_core_exit);
-
-MODULE_DESCRIPTION("Generic PHY Framework");
-MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
-MODULE_LICENSE("GPL v2");
+device_initcall(phy_core_init);
diff --git a/drivers/phy/qualcomm/phy-ath79-usb.c b/drivers/phy/qualcomm/phy-ath79-usb.c
index 6fd6e07ab345..09a77e556ece 100644
--- a/drivers/phy/qualcomm/phy-ath79-usb.c
+++ b/drivers/phy/qualcomm/phy-ath79-usb.c
@@ -31,7 +31,7 @@ static int ath79_usb_phy_power_on(struct phy *phy)
err = reset_control_deassert(priv->reset);
if (err && priv->no_suspend_override)
- reset_control_assert(priv->no_suspend_override);
+ reset_control_deassert(priv->no_suspend_override);
return err;
}
@@ -69,7 +69,7 @@ static int ath79_usb_phy_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy");
+ priv->reset = devm_reset_control_get(&pdev->dev, "phy");
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index b4006818e1b6..08d6f6f7f039 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -687,6 +687,116 @@ static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02),
};
+static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+};
+
+
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@@ -1036,6 +1146,33 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.no_pcs_sw_reset = true,
};
+static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
+ .type = PHY_TYPE_USB3,
+ .nlanes = 1,
+
+ .serdes_tbl = msm8998_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
+ .tx_tbl = msm8998_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl),
+ .rx_tbl = msm8998_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl),
+ .pcs_tbl = msm8998_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl),
+ .clk_list = msm8996_phy_clk_l,
+ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l),
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+
+ .start_ctrl = SERDES_START | PCS_START,
+ .pwrdn_ctrl = SW_PWRDN,
+ .mask_pcs_ready = PHYSTATUS,
+
+ .is_dual_lane_phy = true,
+};
+
static void qcom_qmp_phy_configure(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
@@ -1736,6 +1873,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
+ .compatible = "qcom,msm8998-qmp-ufs-phy",
+ .data = &sdm845_ufsphy_cfg,
+ }, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
}, {
@@ -1747,6 +1887,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,sdm845-qmp-ufs-phy",
.data = &sdm845_ufsphy_cfg,
+ }, {
+ .compatible = "qcom,msm8998-qmp-usb3-phy",
+ .data = &msm8998_usb3phy_cfg,
},
{ },
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index d201cc307151..a1b6cdee9a08 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -174,6 +174,7 @@
#define QSERDES_V3_COM_DIV_FRAC_START1_MODE1 0x0c4
#define QSERDES_V3_COM_DIV_FRAC_START2_MODE1 0x0c8
#define QSERDES_V3_COM_DIV_FRAC_START3_MODE1 0x0cc
+#define QSERDES_V3_COM_INTEGLOOP_INITVAL 0x0d0
#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0 0x0d8
#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0 0x0dc
#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1 0x0e0
@@ -201,6 +202,7 @@
#define QSERDES_V3_COM_DEBUG_BUS2 0x170
#define QSERDES_V3_COM_DEBUG_BUS3 0x174
#define QSERDES_V3_COM_DEBUG_BUS_SEL 0x178
+#define QSERDES_V3_COM_CMN_MODE 0x184
/* Only for QMP V3 PHY - TX registers */
#define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX 0x044
@@ -211,6 +213,7 @@
#define QSERDES_V3_TX_RCV_DETECT_LVL_2 0x0a4
/* Only for QMP V3 PHY - RX registers */
+#define QSERDES_V3_RX_UCDR_FO_GAIN 0x008
#define QSERDES_V3_RX_UCDR_SO_GAIN_HALF 0x00c
#define QSERDES_V3_RX_UCDR_SO_GAIN 0x014
#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF 0x024
@@ -219,6 +222,7 @@
#define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030
#define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
#define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c
+#define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040
#define QSERDES_V3_RX_UCDR_PI_CONTROLS 0x044
#define QSERDES_V3_RX_RX_TERM_BW 0x07c
#define QSERDES_V3_RX_VGA_CAL_CNTRL1 0x0bc
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 9177989f22d1..8fd7ce139772 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -152,6 +152,31 @@ static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
+static const unsigned int msm8998_regs_layout[] = {
+ [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
+ [QUSB2PHY_PLL_STATUS] = 0x1a0,
+ [QUSB2PHY_PORT_TUNE1] = 0x23c,
+ [QUSB2PHY_PORT_TUNE2] = 0x240,
+ [QUSB2PHY_PORT_TUNE3] = 0x244,
+ [QUSB2PHY_PORT_TUNE4] = 0x248,
+ [QUSB2PHY_PORT_TEST1] = 0x24c,
+ [QUSB2PHY_PORT_TEST2] = 0x250,
+ [QUSB2PHY_PORT_POWERDOWN] = 0x210,
+ [QUSB2PHY_INTR_CTRL] = 0x22c,
+};
+
+static const struct qusb2_phy_init_tbl msm8998_init_tbl[] = {
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x13),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_LOCK_DELAY, 0x0a),
+
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xa5),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x09),
+
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19),
+};
+
static const unsigned int sdm845_regs_layout[] = {
[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
[QUSB2PHY_PLL_STATUS] = 0x1a0,
@@ -221,6 +246,18 @@ static const struct qusb2_phy_cfg msm8996_phy_cfg = {
.autoresume_en = BIT(3),
};
+static const struct qusb2_phy_cfg msm8998_phy_cfg = {
+ .tbl = msm8998_init_tbl,
+ .tbl_num = ARRAY_SIZE(msm8998_init_tbl),
+ .regs = msm8998_regs_layout,
+
+ .disable_ctrl = POWER_DOWN,
+ .mask_core_ready = CORE_READY_STATUS,
+ .has_pll_override = true,
+ .autoresume_en = BIT(0),
+ .update_tune1_with_efuse = true,
+};
+
static const struct qusb2_phy_cfg sdm845_phy_cfg = {
.tbl = sdm845_init_tbl,
.tbl_num = ARRAY_SIZE(sdm845_init_tbl),
@@ -734,6 +771,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
.compatible = "qcom,msm8996-qusb2-phy",
.data = &msm8996_phy_cfg,
}, {
+ .compatible = "qcom,msm8998-qusb2-phy",
+ .data = &msm8998_phy_cfg,
+ }, {
.compatible = "qcom,sdm845-qusb2-phy",
.data = &sdm845_phy_cfg,
},
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-i.h b/drivers/phy/qualcomm/phy-qcom-ufs-i.h
index 681644e43248..f798fb64de94 100644
--- a/drivers/phy/qualcomm/phy-qcom-ufs-i.h
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-i.h
@@ -23,24 +23,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/delay.h>
-
-#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
-({ \
- ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
- might_sleep_if(timeout_us); \
- for (;;) { \
- (val) = readl(addr); \
- if (cond) \
- break; \
- if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
- (val) = readl(addr); \
- break; \
- } \
- if (sleep_us) \
- usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \
- } \
- (cond) ? 0 : -ETIMEDOUT; \
-})
+#include <linux/iopoll.h>
#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \
{ \
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 91fba60267a0..ba07121c3eff 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -55,16 +55,16 @@ enum rockchip_usb2phy_host_state {
};
/**
- * Different states involved in USB charger detection.
- * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * enum usb_chg_state - Different states involved in USB charger detection.
+ * @USB_CHG_STATE_UNDEFINED: USB charger is not connected or detection
* process is not yet started.
- * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
- * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
- * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * @USB_CHG_STATE_WAIT_FOR_DCD: Waiting for Data pins contact.
+ * @USB_CHG_STATE_DCD_DONE: Data pin contact is detected.
+ * @USB_CHG_STATE_PRIMARY_DONE: Primary detection is completed (Detects
* between SDP and DCP/CDP).
- * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
- * between DCP and CDP).
- * USB_CHG_STATE_DETECTED USB charger type is determined.
+ * @USB_CHG_STATE_SECONDARY_DONE: Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * @USB_CHG_STATE_DETECTED: USB charger type is determined.
*/
enum usb_chg_state {
USB_CHG_STATE_UNDEFINED = 0,
@@ -94,7 +94,7 @@ struct usb2phy_reg {
};
/**
- * struct rockchip_chg_det_reg: usb charger detect registers
+ * struct rockchip_chg_det_reg - usb charger detect registers
* @cp_det: charging port detected successfully.
* @dcp_det: dedicated charging port detected successfully.
* @dp_det: assert data pin connect successfully.
@@ -120,7 +120,7 @@ struct rockchip_chg_det_reg {
};
/**
- * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
+ * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
* @phy_sus: phy suspend register.
* @bvalid_det_en: vbus valid rise detection enable register.
* @bvalid_det_st: vbus valid rise detection status register.
@@ -148,10 +148,11 @@ struct rockchip_usb2phy_port_cfg {
};
/**
- * struct rockchip_usb2phy_cfg: usb-phy configuration.
+ * struct rockchip_usb2phy_cfg - usb-phy configuration.
* @reg: the address offset of grf for usb-phy config.
* @num_ports: specify how many ports that the phy has.
* @clkout_ctl: keep on/turn off output clk of phy.
+ * @port_cfgs: usb-phy port configurations.
* @chg_det: charger detection registers.
*/
struct rockchip_usb2phy_cfg {
@@ -163,12 +164,10 @@ struct rockchip_usb2phy_cfg {
};
/**
- * struct rockchip_usb2phy_port: usb-phy port data.
+ * struct rockchip_usb2phy_port - usb-phy port data.
+ * @phy: generic phy.
* @port_id: flag for otg port or host port.
* @suspended: phy suspended flag.
- * @utmi_avalid: utmi avalid status usage flag.
- * true - use avalid to get vbus status
- * flase - use bvalid to get vbus status
* @vbus_attached: otg device vbus status.
* @bvalid_irq: IRQ number assigned for vbus valid rise detection.
* @ls_irq: IRQ number assigned for linestate detection.
@@ -178,7 +177,7 @@ struct rockchip_usb2phy_cfg {
* @chg_work: charge detect work.
* @otg_sm_work: OTG state machine work.
* @sm_work: HOST state machine work.
- * @phy_cfg: port register configuration, assigned by driver data.
+ * @port_cfg: port register configuration, assigned by driver data.
* @event_nb: hold event notification callback.
* @state: define OTG enumeration states before device reset.
* @mode: the dr_mode of the controller.
@@ -187,7 +186,6 @@ struct rockchip_usb2phy_port {
struct phy *phy;
unsigned int port_id;
bool suspended;
- bool utmi_avalid;
bool vbus_attached;
int bvalid_irq;
int ls_irq;
@@ -203,12 +201,13 @@ struct rockchip_usb2phy_port {
};
/**
- * struct rockchip_usb2phy: usb2.0 phy driver data.
+ * struct rockchip_usb2phy - usb2.0 phy driver data.
+ * @dev: pointer to device.
* @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
* @clk: clock struct of phy input clk.
* @clk480m: clock struct of phy output clk.
- * @clk_hw: clock struct of phy output clk management.
+ * @clk480m_hw: clock struct of phy output clk management.
* @chg_state: states involved in USB charger detection.
* @chg_type: USB charger types.
* @dcd_retries: The retry count used to track Data contact
@@ -542,12 +541,8 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
unsigned long delay;
bool vbus_attach, sch_work, notify_charger;
- if (rport->utmi_avalid)
- vbus_attach = property_enabled(rphy->grf,
- &rport->port_cfg->utmi_avalid);
- else
- vbus_attach = property_enabled(rphy->grf,
- &rport->port_cfg->utmi_bvalid);
+ vbus_attach = property_enabled(rphy->grf,
+ &rport->port_cfg->utmi_bvalid);
sch_work = false;
notify_charger = false;
@@ -1021,9 +1016,6 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
- rport->utmi_avalid =
- of_property_read_bool(child_np, "rockchip,utmi-avalid");
-
/*
* Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
* interrupts muxed together, so probe the otg-mux interrupt first,
diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
index f137e0107764..103efc456a12 100644
--- a/drivers/phy/ti/Kconfig
+++ b/drivers/phy/ti/Kconfig
@@ -33,12 +33,11 @@ config OMAP_CONTROL_PHY
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || ARCH_K3
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
- select OMAP_CONTROL_PHY
- depends on OMAP_OCP2SCP
+ select OMAP_CONTROL_PHY if ARCH_OMAP2PLUS
help
Enable this to support the transceiver that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
@@ -50,7 +49,6 @@ config TI_PIPE3
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.
@@ -82,6 +80,7 @@ config PHY_TI_GMII_SEL
default y if TI_CPSW=y
depends on TI_CPSW || COMPILE_TEST
select GENERIC_PHY
+ select REGMAP
default m
help
This driver supports configuring of the TI CPSW Port mode depending on
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 77fdaa551977..a52c5bb35033 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
+++ b/drivers/phy/ti/phy-gmii-sel.c
@@ -204,11 +204,11 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
if (args->args_count < 1)
return ERR_PTR(-EINVAL);
+ if (!priv || !priv->if_phys)
+ return ERR_PTR(-ENODEV);
if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
args->args_count < 2)
return ERR_PTR(-EINVAL);
- if (!priv || !priv->if_phys)
- return ERR_PTR(-ENODEV);
if (phy_id > priv->soc_data->num_ports)
return ERR_PTR(-EINVAL);
if (phy_id != priv->if_phys[phy_id - 1].id)
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index fe909fd8144f..e871f2983a0e 100644
--- a/drivers/phy/ti/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
@@ -36,6 +36,10 @@
#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
#define USB2PHY_ANA_CONFIG1 0x4c
+#define AM654_USB2_OTG_PD BIT(8)
+#define AM654_USB2_VBUS_DET_EN BIT(5)
+#define AM654_USB2_VBUSVALID_DET_EN BIT(4)
+
/**
* omap_usb2_set_comparator - links the comparator present in the sytem with
* this phy
@@ -135,9 +139,9 @@ static int omap_usb_power_on(struct phy *x)
static int omap_usb2_disable_clocks(struct omap_usb *phy)
{
- clk_disable(phy->wkupclk);
+ clk_disable_unprepare(phy->wkupclk);
if (!IS_ERR(phy->optclk))
- clk_disable(phy->optclk);
+ clk_disable_unprepare(phy->optclk);
return 0;
}
@@ -146,14 +150,14 @@ static int omap_usb2_enable_clocks(struct omap_usb *phy)
{
int ret;
- ret = clk_enable(phy->wkupclk);
+ ret = clk_prepare_enable(phy->wkupclk);
if (ret < 0) {
dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
goto err0;
}
if (!IS_ERR(phy->optclk)) {
- ret = clk_enable(phy->optclk);
+ ret = clk_prepare_enable(phy->optclk);
if (ret < 0) {
dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
goto err1;
@@ -245,6 +249,15 @@ static const struct usb_phy_data am437x_usb2_data = {
.power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
};
+static const struct usb_phy_data am654_usb2_data = {
+ .label = "am654_usb2",
+ .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+ .mask = AM654_USB2_OTG_PD | AM654_USB2_VBUS_DET_EN |
+ AM654_USB2_VBUSVALID_DET_EN,
+ .power_on = AM654_USB2_VBUS_DET_EN | AM654_USB2_VBUSVALID_DET_EN,
+ .power_off = AM654_USB2_OTG_PD,
+};
+
static const struct of_device_id omap_usb2_id_table[] = {
{
.compatible = "ti,omap-usb2",
@@ -266,6 +279,10 @@ static const struct of_device_id omap_usb2_id_table[] = {
.compatible = "ti,am437x-usb2",
.data = &am437x_usb2_data,
},
+ {
+ .compatible = "ti,am654-usb2",
+ .data = &am654_usb2_data,
+ },
{},
};
MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
@@ -346,63 +363,72 @@ static int omap_usb2_probe(struct platform_device *pdev)
}
}
- otg->set_host = omap_usb_set_host;
- otg->set_peripheral = omap_usb_set_peripheral;
- if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
- otg->set_vbus = omap_usb_set_vbus;
- if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
- otg->start_srp = omap_usb_start_srp;
- otg->usb_phy = &phy->phy;
-
- platform_set_drvdata(pdev, phy);
- pm_runtime_enable(phy->dev);
-
- generic_phy = devm_phy_create(phy->dev, NULL, &ops);
- if (IS_ERR(generic_phy)) {
- pm_runtime_disable(phy->dev);
- return PTR_ERR(generic_phy);
- }
-
- phy_set_drvdata(generic_phy, phy);
- omap_usb_power_off(generic_phy);
-
- phy_provider = devm_of_phy_provider_register(phy->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- pm_runtime_disable(phy->dev);
- return PTR_ERR(phy_provider);
- }
phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
if (IS_ERR(phy->wkupclk)) {
- dev_warn(&pdev->dev, "unable to get wkupclk, trying old name\n");
+ if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_warn(&pdev->dev, "unable to get wkupclk %ld, trying old name\n",
+ PTR_ERR(phy->wkupclk));
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+
if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
- pm_runtime_disable(phy->dev);
+ if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
return PTR_ERR(phy->wkupclk);
} else {
dev_warn(&pdev->dev,
"found usb_phy_cm_clk32k, please fix DTS\n");
}
}
- clk_prepare(phy->wkupclk);
phy->optclk = devm_clk_get(phy->dev, "refclk");
if (IS_ERR(phy->optclk)) {
+ if (PTR_ERR(phy->optclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+
if (IS_ERR(phy->optclk)) {
- dev_dbg(&pdev->dev,
- "unable to get usb_otg_ss_refclk960m\n");
+ if (PTR_ERR(phy->optclk) != -EPROBE_DEFER) {
+ dev_dbg(&pdev->dev,
+ "unable to get usb_otg_ss_refclk960m\n");
+ }
} else {
dev_warn(&pdev->dev,
"found usb_otg_ss_refclk960m, please fix DTS\n");
}
}
- if (!IS_ERR(phy->optclk))
- clk_prepare(phy->optclk);
+ otg->set_host = omap_usb_set_host;
+ otg->set_peripheral = omap_usb_set_peripheral;
+ if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
+ otg->set_vbus = omap_usb_set_vbus;
+ if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
+ otg->start_srp = omap_usb_start_srp;
+ otg->usb_phy = &phy->phy;
+
+ platform_set_drvdata(pdev, phy);
+ pm_runtime_enable(phy->dev);
+
+ generic_phy = devm_phy_create(phy->dev, NULL, &ops);
+ if (IS_ERR(generic_phy)) {
+ pm_runtime_disable(phy->dev);
+ return PTR_ERR(generic_phy);
+ }
+
+ phy_set_drvdata(generic_phy, phy);
+ omap_usb_power_off(generic_phy);
+
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ pm_runtime_disable(phy->dev);
+ return PTR_ERR(phy_provider);
+ }
+
usb_add_phy_dev(&phy->phy);
@@ -413,9 +439,6 @@ static int omap_usb2_remove(struct platform_device *pdev)
{
struct omap_usb *phy = platform_get_drvdata(pdev);
- clk_unprepare(phy->wkupclk);
- if (!IS_ERR(phy->optclk))
- clk_unprepare(phy->optclk);
usb_remove_phy(&phy->phy);
pm_runtime_disable(phy->dev);
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 05044e323ea5..03ec7a5d9d0b 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1513,7 +1513,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
},
},
{
@@ -1521,7 +1521,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
},
},
{
@@ -1529,7 +1529,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
},
},
{
@@ -1537,7 +1537,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
},
},
{}
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 1817786ab6aa..a005cbccb4f7 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -45,12 +45,14 @@ config PINCTRL_MT2701
config PINCTRL_MT7623
bool "Mediatek MT7623 pin control with generic binding"
depends on MACH_MT7623 || COMPILE_TEST
+ depends on OF
default MACH_MT7623
select PINCTRL_MTK_MOORE
config PINCTRL_MT7629
bool "Mediatek MT7629 pin control"
depends on MACH_MT7629 || COMPILE_TEST
+ depends on OF
default MACH_MT7629
select PINCTRL_MTK_MOORE
@@ -92,6 +94,7 @@ config PINCTRL_MT6797
config PINCTRL_MT7622
bool "MediaTek MT7622 pin control"
+ depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
select PINCTRL_MTK_MOORE
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index c69ca95b1ad5..0f140a802137 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -693,7 +693,7 @@ static const char * const sd_a_groups[] = {
static const char * const sdxc_a_groups[] = {
"sdxc_d0_0_a", "sdxc_d13_0_a", "sdxc_d47_a", "sdxc_clk_a",
- "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d0_13_1_a"
+ "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d13_1_a"
};
static const char * const pcm_a_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index b03481ef99a1..98905d4a79ca 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -832,8 +832,13 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
break;
case MCP_TYPE_S18:
+ one_regmap_config =
+ devm_kmemdup(dev, &mcp23x17_regmap,
+ sizeof(struct regmap_config), GFP_KERNEL);
+ if (!one_regmap_config)
+ return -ENOMEM;
mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
- &mcp23x17_regmap);
+ one_regmap_config);
mcp->reg_shift = 1;
mcp->chip.ngpio = 16;
mcp->chip.label = "mcp23s18";
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c
index 7aae52a09ff0..4ffd56ff809e 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcs404.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c
@@ -79,7 +79,7 @@ enum {
.intr_cfg_reg = 0, \
.intr_status_reg = 0, \
.intr_target_reg = 0, \
- .tile = NORTH, \
+ .tile = SOUTH, \
.mux_bit = -1, \
.pull_bit = pull, \
.drv_bit = drv, \
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
index aa8b58125568..ef4268cc6227 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
@@ -588,7 +588,7 @@ static const unsigned int h6_irq_bank_map[] = { 1, 5, 6, 7 };
static const struct sunxi_pinctrl_desc h6_pinctrl_data = {
.pins = h6_pins,
.npins = ARRAY_SIZE(h6_pins),
- .irq_banks = 3,
+ .irq_banks = 4,
.irq_bank_map = h6_irq_bank_map,
.irq_read_needs_mux = true,
};
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 5d9184d18c16..0e7fa69e93df 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -698,26 +698,24 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
{
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
unsigned short bank = offset / PINS_PER_BANK;
- struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
- struct regulator *reg;
+ unsigned short bank_offset = bank - pctl->desc->pin_base /
+ PINS_PER_BANK;
+ struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
+ struct regulator *reg = s_reg->regulator;
+ char supply[16];
int ret;
- reg = s_reg->regulator;
- if (!reg) {
- char supply[16];
-
- snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
- reg = regulator_get(pctl->dev, supply);
- if (IS_ERR(reg)) {
- dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
- 'A' + bank);
- return PTR_ERR(reg);
- }
-
- s_reg->regulator = reg;
- refcount_set(&s_reg->refcount, 1);
- } else {
+ if (reg) {
refcount_inc(&s_reg->refcount);
+ return 0;
+ }
+
+ snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
+ reg = regulator_get(pctl->dev, supply);
+ if (IS_ERR(reg)) {
+ dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
+ 'A' + bank);
+ return PTR_ERR(reg);
}
ret = regulator_enable(reg);
@@ -727,13 +725,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
goto out;
}
+ s_reg->regulator = reg;
+ refcount_set(&s_reg->refcount, 1);
+
return 0;
out:
- if (refcount_dec_and_test(&s_reg->refcount)) {
- regulator_put(s_reg->regulator);
- s_reg->regulator = NULL;
- }
+ regulator_put(s_reg->regulator);
return ret;
}
@@ -742,7 +740,9 @@ static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
{
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
unsigned short bank = offset / PINS_PER_BANK;
- struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
+ unsigned short bank_offset = bank - pctl->desc->pin_base /
+ PINS_PER_BANK;
+ struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
if (!refcount_dec_and_test(&s_reg->refcount))
return 0;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index e340d2a24b44..034c0317c8d6 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -136,7 +136,7 @@ struct sunxi_pinctrl {
struct gpio_chip *chip;
const struct sunxi_pinctrl_desc *desc;
struct device *dev;
- struct sunxi_pinctrl_regulator regulators[12];
+ struct sunxi_pinctrl_regulator regulators[9];
struct irq_domain *domain;
struct sunxi_pinctrl_function *functions;
unsigned nfunctions;
diff --git a/drivers/platform/goldfish/Kconfig b/drivers/platform/goldfish/Kconfig
index 479031aa4f88..74fdfa68d1f2 100644
--- a/drivers/platform/goldfish/Kconfig
+++ b/drivers/platform/goldfish/Kconfig
@@ -2,7 +2,7 @@ menuconfig GOLDFISH
bool "Platform support for Goldfish virtual devices"
depends on X86_32 || X86_64 || ARM || ARM64 || MIPS
depends on HAS_IOMEM
- ---help---
+ help
Say Y here to get to see options for the Goldfish virtual platform.
This option alone does not add any kernel code.
@@ -12,7 +12,7 @@ if GOLDFISH
config GOLDFISH_PIPE
tristate "Goldfish virtual device for QEMU pipes"
- ---help---
+ help
This is a virtual device to drive the QEMU pipe interface used by
the Goldfish Android Virtual Device.
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e3b62c2ee8d1..b5e9db85e881 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -905,6 +905,7 @@ config TOSHIBA_WMI
config ACPI_CMPC
tristate "CMPC Laptop Extras"
depends on ACPI && INPUT
+ depends on BACKLIGHT_LCD_SUPPORT
depends on RFKILL || RFKILL=n
select BACKLIGHT_CLASS_DEVICE
help
@@ -1009,7 +1010,7 @@ config INTEL_MFLD_THERMAL
config INTEL_IPS
tristate "Intel Intelligent Power Sharing"
- depends on ACPI
+ depends on ACPI && PCI
---help---
Intel Calpella platforms support dynamic power sharing between the
CPU and GPU, maximizing performance in a given TDP. This driver,
@@ -1128,6 +1129,7 @@ config INTEL_OAKTRAIL
config SAMSUNG_Q10
tristate "Samsung Q10 Extras"
depends on ACPI
+ depends on BACKLIGHT_LCD_SUPPORT
select BACKLIGHT_CLASS_DEVICE
---help---
This driver provides support for backlight control on Samsung Q10
@@ -1135,7 +1137,7 @@ config SAMSUNG_Q10
config APPLE_GMUX
tristate "Apple Gmux Driver"
- depends on ACPI
+ depends on ACPI && PCI
depends on PNP
depends on BACKLIGHT_CLASS_DEVICE
depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE
@@ -1174,7 +1176,7 @@ config INTEL_SMARTCONNECT
config INTEL_PMC_IPC
tristate "Intel PMC IPC Driver"
- depends on ACPI
+ depends on ACPI && PCI
---help---
This driver provides support for PMC control on some Intel platforms.
The PMC is an ARC processor which defines IPC commands for communication
diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c
index 02bc74608cf3..6fa3cced6f8e 100644
--- a/drivers/platform/x86/intel_cht_int33fe.c
+++ b/drivers/platform/x86/intel_cht_int33fe.c
@@ -32,7 +32,7 @@ struct cht_int33fe_data {
struct i2c_client *fusb302;
struct i2c_client *pi3usb30532;
/* Contain a list-head must be per device */
- struct device_connection connections[5];
+ struct device_connection connections[4];
};
/*
@@ -174,16 +174,13 @@ static int cht_int33fe_probe(struct platform_device *pdev)
data->connections[0].endpoint[0] = "port0";
data->connections[0].endpoint[1] = "i2c-pi3usb30532";
- data->connections[0].id = "typec-switch";
+ data->connections[0].id = "orientation-switch";
data->connections[1].endpoint[0] = "port0";
data->connections[1].endpoint[1] = "i2c-pi3usb30532";
- data->connections[1].id = "typec-mux";
- data->connections[2].endpoint[0] = "port0";
- data->connections[2].endpoint[1] = "i2c-pi3usb30532";
- data->connections[2].id = "idff01m01";
- data->connections[3].endpoint[0] = "i2c-fusb302";
- data->connections[3].endpoint[1] = "intel_xhci_usb_sw-role-switch";
- data->connections[3].id = "usb-role-switch";
+ data->connections[1].id = "mode-switch";
+ data->connections[2].endpoint[0] = "i2c-fusb302";
+ data->connections[2].endpoint[1] = "intel_xhci_usb_sw-role-switch";
+ data->connections[2].id = "usb-role-switch";
device_connections_add(data->connections);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index b205b037fd61..4bfbfa3f78e6 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -4392,7 +4392,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
list_add(&interrupt->list, &dev->interrupts);
interrupt->irq.triggering = p->triggering;
interrupt->irq.polarity = p->polarity;
- interrupt->irq.sharable = p->sharable;
+ interrupt->irq.shareable = p->shareable;
interrupt->irq.interrupt_count = 1;
interrupt->irq.interrupts[0] = p->interrupts[i];
}
@@ -4546,7 +4546,7 @@ static int sony_pic_enable(struct acpi_device *device,
memcpy(&resource->res3.data.irq, &irq->irq,
sizeof(struct acpi_resource_irq));
/* we requested a shared irq */
- resource->res3.data.irq.sharable = ACPI_SHARED;
+ resource->res3.data.irq.shareable = ACPI_SHARED;
resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
resource->res4.length = sizeof(struct acpi_resource);
@@ -4565,7 +4565,7 @@ static int sony_pic_enable(struct acpi_device *device,
memcpy(&resource->res2.data.irq, &irq->irq,
sizeof(struct acpi_resource_irq));
/* we requested a shared irq */
- resource->res2.data.irq.sharable = ACPI_SHARED;
+ resource->res2.data.irq.shareable = ACPI_SHARED;
resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
resource->res3.length = sizeof(struct acpi_resource);
@@ -4779,7 +4779,7 @@ static int sony_pic_add(struct acpi_device *device)
irq->irq.interrupts[0],
irq->irq.triggering,
irq->irq.polarity,
- irq->irq.sharable);
+ irq->irq.shareable);
spic_dev.cur_irq = irq;
break;
}
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 43d8ed577e70..c79417ca1b3c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -215,7 +215,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
if (i >= 0) {
flags = acpi_dev_irq_flags(gpio->triggering,
gpio->polarity,
- gpio->sharable);
+ gpio->shareable);
} else {
flags = IORESOURCE_DISABLED;
}
@@ -324,7 +324,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
if (p->interrupts[i])
__set_bit(p->interrupts[i], map.bits);
- flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
+ flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
@@ -348,7 +348,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
}
}
- flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
+ flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
@@ -681,7 +681,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
irq->triggering = triggering;
irq->polarity = polarity;
- irq->sharable = shareable;
+ irq->shareable = shareable;
irq->interrupt_count = 1;
irq->interrupts[0] = p->start;
@@ -689,7 +689,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
(int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
- irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
+ irq->shareable == ACPI_SHARED ? "shared" : "exclusive",
irq->descriptor_length);
}
@@ -711,14 +711,14 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
extended_irq->producer_consumer = ACPI_CONSUMER;
extended_irq->triggering = triggering;
extended_irq->polarity = polarity;
- extended_irq->sharable = shareable;
+ extended_irq->shareable = shareable;
extended_irq->interrupt_count = 1;
extended_irq->interrupts[0] = p->start;
pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
- extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
+ extended_irq->shareable == ACPI_SHARED ? "shared" : "exclusive");
}
static void pnpacpi_encode_dma(struct pnp_dev *dev,
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 6cdb2c14eee4..4347f15165f8 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -1156,6 +1156,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
INTEL_CPU_FAM6(KABYLAKE_MOBILE, rapl_defaults_core),
INTEL_CPU_FAM6(KABYLAKE_DESKTOP, rapl_defaults_core),
INTEL_CPU_FAM6(CANNONLAKE_MOBILE, rapl_defaults_core),
+ INTEL_CPU_FAM6(ICELAKE_MOBILE, rapl_defaults_core),
INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt),
INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
@@ -1164,6 +1165,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
INTEL_CPU_FAM6(ATOM_GOLDMONT, rapl_defaults_core),
INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, rapl_defaults_core),
INTEL_CPU_FAM6(ATOM_GOLDMONT_X, rapl_defaults_core),
+ INTEL_CPU_FAM6(ATOM_TREMONT_X, rapl_defaults_core),
INTEL_CPU_FAM6(XEON_PHI_KNL, rapl_defaults_hsw_server),
INTEL_CPU_FAM6(XEON_PHI_KNM, rapl_defaults_hsw_server),
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index d137c480db46..7fe18636915a 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -43,7 +43,7 @@ config PTP_1588_CLOCK_DTE
config PTP_1588_CLOCK_QORIQ
tristate "Freescale QorIQ 1588 timer as PTP clock"
- depends on GIANFAR || FSL_DPAA_ETH
+ depends on GIANFAR || FSL_DPAA_ETH || FSL_ENETC || FSL_ENETC_VF
depends on PTP_1588_CLOCK
default y
help
@@ -53,7 +53,7 @@ config PTP_1588_CLOCK_QORIQ
packets using the SO_TIMESTAMPING API.
To compile this driver as a module, choose M here: the module
- will be called ptp_qoriq.
+ will be called ptp-qoriq.
config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock"
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 19efa9cfa950..677d1d178a3e 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -9,4 +9,6 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o
obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o
obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o
-obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp_qoriq.o
+obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp-qoriq.o
+ptp-qoriq-y += ptp_qoriq.o
+ptp-qoriq-$(CONFIG_DEBUG_FS) += ptp_qoriq_debugfs.o
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 797fab33bb98..7cbea796652a 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -224,7 +224,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
extoff = NULL;
break;
}
- if (extoff->n_samples > PTP_MAX_SAMPLES) {
+ if (extoff->n_samples > PTP_MAX_SAMPLES
+ || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
err = -EINVAL;
break;
}
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 48f3594a7458..79bd102c9bbc 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -124,7 +124,7 @@ static int ptp_clock_gettime(struct posix_clock *pc, struct timespec64 *tp)
return err;
}
-static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx)
+static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
{
struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
struct ptp_clock_info *ops;
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index fdd49c26bbcc..53775362aac6 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -22,7 +22,6 @@
#include <linux/device.h>
#include <linux/hrtimer.h>
-#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -37,152 +36,188 @@
* Register access functions
*/
-/* Caller must hold qoriq_ptp->lock. */
-static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
+/* Caller must hold ptp_qoriq->lock. */
+static u64 tmr_cnt_read(struct ptp_qoriq *ptp_qoriq)
{
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
u64 ns;
u32 lo, hi;
- lo = qoriq_read(&regs->ctrl_regs->tmr_cnt_l);
- hi = qoriq_read(&regs->ctrl_regs->tmr_cnt_h);
+ lo = ptp_qoriq->read(&regs->ctrl_regs->tmr_cnt_l);
+ hi = ptp_qoriq->read(&regs->ctrl_regs->tmr_cnt_h);
ns = ((u64) hi) << 32;
ns |= lo;
return ns;
}
-/* Caller must hold qoriq_ptp->lock. */
-static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
+/* Caller must hold ptp_qoriq->lock. */
+static void tmr_cnt_write(struct ptp_qoriq *ptp_qoriq, u64 ns)
{
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
u32 hi = ns >> 32;
u32 lo = ns & 0xffffffff;
- qoriq_write(&regs->ctrl_regs->tmr_cnt_l, lo);
- qoriq_write(&regs->ctrl_regs->tmr_cnt_h, hi);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_cnt_l, lo);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_cnt_h, hi);
}
-/* Caller must hold qoriq_ptp->lock. */
-static void set_alarm(struct qoriq_ptp *qoriq_ptp)
+/* Caller must hold ptp_qoriq->lock. */
+static void set_alarm(struct ptp_qoriq *ptp_qoriq)
{
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
u64 ns;
u32 lo, hi;
- ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL;
+ ns = tmr_cnt_read(ptp_qoriq) + 1500000000ULL;
ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
- ns -= qoriq_ptp->tclk_period;
+ ns -= ptp_qoriq->tclk_period;
hi = ns >> 32;
lo = ns & 0xffffffff;
- qoriq_write(&regs->alarm_regs->tmr_alarm1_l, lo);
- qoriq_write(&regs->alarm_regs->tmr_alarm1_h, hi);
+ ptp_qoriq->write(&regs->alarm_regs->tmr_alarm1_l, lo);
+ ptp_qoriq->write(&regs->alarm_regs->tmr_alarm1_h, hi);
}
-/* Caller must hold qoriq_ptp->lock. */
-static void set_fipers(struct qoriq_ptp *qoriq_ptp)
+/* Caller must hold ptp_qoriq->lock. */
+static void set_fipers(struct ptp_qoriq *ptp_qoriq)
{
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
- set_alarm(qoriq_ptp);
- qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
+ set_alarm(ptp_qoriq);
+ ptp_qoriq->write(&regs->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1);
+ ptp_qoriq->write(&regs->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2);
+}
+
+static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index,
+ bool update_event)
+{
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+ struct ptp_clock_event event;
+ void __iomem *reg_etts_l;
+ void __iomem *reg_etts_h;
+ u32 valid, stat, lo, hi;
+
+ switch (index) {
+ case 0:
+ valid = ETS1_VLD;
+ reg_etts_l = &regs->etts_regs->tmr_etts1_l;
+ reg_etts_h = &regs->etts_regs->tmr_etts1_h;
+ break;
+ case 1:
+ valid = ETS2_VLD;
+ reg_etts_l = &regs->etts_regs->tmr_etts2_l;
+ reg_etts_h = &regs->etts_regs->tmr_etts2_h;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = index;
+
+ do {
+ lo = ptp_qoriq->read(reg_etts_l);
+ hi = ptp_qoriq->read(reg_etts_h);
+
+ if (update_event) {
+ event.timestamp = ((u64) hi) << 32;
+ event.timestamp |= lo;
+ ptp_clock_event(ptp_qoriq->clock, &event);
+ }
+
+ stat = ptp_qoriq->read(&regs->ctrl_regs->tmr_stat);
+ } while (ptp_qoriq->extts_fifo_support && (stat & valid));
+
+ return 0;
}
/*
* Interrupt service routine
*/
-static irqreturn_t isr(int irq, void *priv)
+irqreturn_t ptp_qoriq_isr(int irq, void *priv)
{
- struct qoriq_ptp *qoriq_ptp = priv;
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq *ptp_qoriq = priv;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
struct ptp_clock_event event;
u64 ns;
- u32 ack = 0, lo, hi, mask, val;
+ u32 ack = 0, lo, hi, mask, val, irqs;
+
+ spin_lock(&ptp_qoriq->lock);
+
+ val = ptp_qoriq->read(&regs->ctrl_regs->tmr_tevent);
+ mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);
+
+ spin_unlock(&ptp_qoriq->lock);
- val = qoriq_read(&regs->ctrl_regs->tmr_tevent);
+ irqs = val & mask;
- if (val & ETS1) {
+ if (irqs & ETS1) {
ack |= ETS1;
- hi = qoriq_read(&regs->etts_regs->tmr_etts1_h);
- lo = qoriq_read(&regs->etts_regs->tmr_etts1_l);
- event.type = PTP_CLOCK_EXTTS;
- event.index = 0;
- event.timestamp = ((u64) hi) << 32;
- event.timestamp |= lo;
- ptp_clock_event(qoriq_ptp->clock, &event);
+ extts_clean_up(ptp_qoriq, 0, true);
}
- if (val & ETS2) {
+ if (irqs & ETS2) {
ack |= ETS2;
- hi = qoriq_read(&regs->etts_regs->tmr_etts2_h);
- lo = qoriq_read(&regs->etts_regs->tmr_etts2_l);
- event.type = PTP_CLOCK_EXTTS;
- event.index = 1;
- event.timestamp = ((u64) hi) << 32;
- event.timestamp |= lo;
- ptp_clock_event(qoriq_ptp->clock, &event);
+ extts_clean_up(ptp_qoriq, 1, true);
}
- if (val & ALM2) {
+ if (irqs & ALM2) {
ack |= ALM2;
- if (qoriq_ptp->alarm_value) {
+ if (ptp_qoriq->alarm_value) {
event.type = PTP_CLOCK_ALARM;
event.index = 0;
- event.timestamp = qoriq_ptp->alarm_value;
- ptp_clock_event(qoriq_ptp->clock, &event);
+ event.timestamp = ptp_qoriq->alarm_value;
+ ptp_clock_event(ptp_qoriq->clock, &event);
}
- if (qoriq_ptp->alarm_interval) {
- ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval;
+ if (ptp_qoriq->alarm_interval) {
+ ns = ptp_qoriq->alarm_value + ptp_qoriq->alarm_interval;
hi = ns >> 32;
lo = ns & 0xffffffff;
- spin_lock(&qoriq_ptp->lock);
- qoriq_write(&regs->alarm_regs->tmr_alarm2_l, lo);
- qoriq_write(&regs->alarm_regs->tmr_alarm2_h, hi);
- spin_unlock(&qoriq_ptp->lock);
- qoriq_ptp->alarm_value = ns;
+ ptp_qoriq->write(&regs->alarm_regs->tmr_alarm2_l, lo);
+ ptp_qoriq->write(&regs->alarm_regs->tmr_alarm2_h, hi);
+ ptp_qoriq->alarm_value = ns;
} else {
- qoriq_write(&regs->ctrl_regs->tmr_tevent, ALM2);
- spin_lock(&qoriq_ptp->lock);
- mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
+ spin_lock(&ptp_qoriq->lock);
+ mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);
mask &= ~ALM2EN;
- qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
- spin_unlock(&qoriq_ptp->lock);
- qoriq_ptp->alarm_value = 0;
- qoriq_ptp->alarm_interval = 0;
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_temask, mask);
+ spin_unlock(&ptp_qoriq->lock);
+ ptp_qoriq->alarm_value = 0;
+ ptp_qoriq->alarm_interval = 0;
}
}
- if (val & PP1) {
+ if (irqs & PP1) {
ack |= PP1;
event.type = PTP_CLOCK_PPS;
- ptp_clock_event(qoriq_ptp->clock, &event);
+ ptp_clock_event(ptp_qoriq->clock, &event);
}
if (ack) {
- qoriq_write(&regs->ctrl_regs->tmr_tevent, ack);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_tevent, ack);
return IRQ_HANDLED;
} else
return IRQ_NONE;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_isr);
/*
* PTP clock operations
*/
-static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
u64 adj, diff;
u32 tmr_add;
int neg_adj = 0;
- struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
if (scaled_ppm < 0) {
neg_adj = 1;
scaled_ppm = -scaled_ppm;
}
- tmr_add = qoriq_ptp->tmr_add;
+ tmr_add = ptp_qoriq->tmr_add;
adj = tmr_add;
/* calculate diff as adj*(scaled_ppm/65536)/1000000
@@ -194,73 +229,76 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
- qoriq_write(&regs->ctrl_regs->tmr_add, tmr_add);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_add, tmr_add);
return 0;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_adjfine);
-static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
+int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
s64 now;
unsigned long flags;
- struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
+ spin_lock_irqsave(&ptp_qoriq->lock, flags);
- now = tmr_cnt_read(qoriq_ptp);
+ now = tmr_cnt_read(ptp_qoriq);
now += delta;
- tmr_cnt_write(qoriq_ptp, now);
- set_fipers(qoriq_ptp);
+ tmr_cnt_write(ptp_qoriq, now);
+ set_fipers(ptp_qoriq);
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
+ spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_adjtime);
-static int ptp_qoriq_gettime(struct ptp_clock_info *ptp,
- struct timespec64 *ts)
+int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
u64 ns;
unsigned long flags;
- struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
+ spin_lock_irqsave(&ptp_qoriq->lock, flags);
- ns = tmr_cnt_read(qoriq_ptp);
+ ns = tmr_cnt_read(ptp_qoriq);
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
+ spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
*ts = ns_to_timespec64(ns);
return 0;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_gettime);
-static int ptp_qoriq_settime(struct ptp_clock_info *ptp,
- const struct timespec64 *ts)
+int ptp_qoriq_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
{
u64 ns;
unsigned long flags;
- struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
ns = timespec64_to_ns(ts);
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
+ spin_lock_irqsave(&ptp_qoriq->lock, flags);
- tmr_cnt_write(qoriq_ptp, ns);
- set_fipers(qoriq_ptp);
+ tmr_cnt_write(ptp_qoriq, ns);
+ set_fipers(ptp_qoriq);
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
+ spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_settime);
-static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
- struct ptp_clock_request *rq, int on)
+int ptp_qoriq_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
{
- struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+ struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
unsigned long flags;
- u32 bit, mask;
+ u32 bit, mask = 0;
switch (rq->type) {
case PTP_CLK_REQ_EXTTS:
@@ -274,33 +312,34 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
default:
return -EINVAL;
}
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
- if (on)
- mask |= bit;
- else
- mask &= ~bit;
- qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
- return 0;
- case PTP_CLK_REQ_PPS:
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on)
- mask |= PP1EN;
- else
- mask &= ~PP1EN;
- qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
- return 0;
+ extts_clean_up(ptp_qoriq, rq->extts.index, false);
- default:
break;
+ case PTP_CLK_REQ_PPS:
+ bit = PP1EN;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ spin_lock_irqsave(&ptp_qoriq->lock, flags);
+
+ mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);
+ if (on) {
+ mask |= bit;
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_tevent, bit);
+ } else {
+ mask &= ~bit;
}
- return -EOPNOTSUPP;
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_temask, mask);
+
+ spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
+ return 0;
}
+EXPORT_SYMBOL_GPL(ptp_qoriq_enable);
static const struct ptp_clock_info ptp_qoriq_caps = {
.owner = THIS_MODULE,
@@ -319,7 +358,7 @@ static const struct ptp_clock_info ptp_qoriq_caps = {
};
/**
- * qoriq_ptp_nominal_freq - calculate nominal frequency according to
+ * ptp_qoriq_nominal_freq - calculate nominal frequency according to
* reference clock frequency
*
* @clk_src: reference clock frequency
@@ -330,7 +369,7 @@ static const struct ptp_clock_info ptp_qoriq_caps = {
*
* Return the nominal frequency
*/
-static u32 qoriq_ptp_nominal_freq(u32 clk_src)
+static u32 ptp_qoriq_nominal_freq(u32 clk_src)
{
u32 remainder = 0;
@@ -350,9 +389,9 @@ static u32 qoriq_ptp_nominal_freq(u32 clk_src)
}
/**
- * qoriq_ptp_auto_config - calculate a set of default configurations
+ * ptp_qoriq_auto_config - calculate a set of default configurations
*
- * @qoriq_ptp: pointer to qoriq_ptp
+ * @ptp_qoriq: pointer to ptp_qoriq
* @node: pointer to device_node
*
* If below dts properties are not provided, this function will be
@@ -366,7 +405,7 @@ static u32 qoriq_ptp_nominal_freq(u32 clk_src)
*
* Return 0 if success
*/
-static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp,
+static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq,
struct device_node *node)
{
struct clk *clk;
@@ -376,7 +415,7 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp,
u32 remainder = 0;
u32 clk_src = 0;
- qoriq_ptp->cksel = DEFAULT_CKSEL;
+ ptp_qoriq->cksel = DEFAULT_CKSEL;
clk = of_clk_get(node, 0);
if (!IS_ERR(clk)) {
@@ -389,12 +428,12 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp,
return -EINVAL;
}
- nominal_freq = qoriq_ptp_nominal_freq(clk_src);
+ nominal_freq = ptp_qoriq_nominal_freq(clk_src);
if (!nominal_freq)
return -EINVAL;
- qoriq_ptp->tclk_period = 1000000000UL / nominal_freq;
- qoriq_ptp->tmr_prsc = DEFAULT_TMR_PRSC;
+ ptp_qoriq->tclk_period = 1000000000UL / nominal_freq;
+ ptp_qoriq->tmr_prsc = DEFAULT_TMR_PRSC;
/* Calculate initial frequency compensation value for TMR_ADD register.
* freq_comp = ceil(2^32 / freq_ratio)
@@ -405,164 +444,193 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp,
if (remainder)
freq_comp++;
- qoriq_ptp->tmr_add = freq_comp;
- qoriq_ptp->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - qoriq_ptp->tclk_period;
- qoriq_ptp->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - qoriq_ptp->tclk_period;
+ ptp_qoriq->tmr_add = freq_comp;
+ ptp_qoriq->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - ptp_qoriq->tclk_period;
+ ptp_qoriq->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - ptp_qoriq->tclk_period;
/* max_adj = 1000000000 * (freq_ratio - 1.0) - 1
* freq_ratio = reference_clock_freq / nominal_freq
*/
max_adj = 1000000000ULL * (clk_src - nominal_freq);
max_adj = div_u64(max_adj, nominal_freq) - 1;
- qoriq_ptp->caps.max_adj = max_adj;
+ ptp_qoriq->caps.max_adj = max_adj;
return 0;
}
-static int qoriq_ptp_probe(struct platform_device *dev)
+int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base,
+ const struct ptp_clock_info *caps)
{
- struct device_node *node = dev->dev.of_node;
- struct qoriq_ptp *qoriq_ptp;
- struct qoriq_ptp_registers *regs;
+ struct device_node *node = ptp_qoriq->dev->of_node;
+ struct ptp_qoriq_registers *regs;
struct timespec64 now;
- int err = -ENOMEM;
- u32 tmr_ctrl;
unsigned long flags;
- void __iomem *base;
-
- qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
- if (!qoriq_ptp)
- goto no_memory;
+ u32 tmr_ctrl;
- err = -EINVAL;
+ ptp_qoriq->base = base;
+ ptp_qoriq->caps = *caps;
- qoriq_ptp->caps = ptp_qoriq_caps;
+ if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel))
+ ptp_qoriq->cksel = DEFAULT_CKSEL;
- if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel))
- qoriq_ptp->cksel = DEFAULT_CKSEL;
+ if (of_property_read_bool(node, "fsl,extts-fifo"))
+ ptp_qoriq->extts_fifo_support = true;
+ else
+ ptp_qoriq->extts_fifo_support = false;
if (of_property_read_u32(node,
- "fsl,tclk-period", &qoriq_ptp->tclk_period) ||
+ "fsl,tclk-period", &ptp_qoriq->tclk_period) ||
of_property_read_u32(node,
- "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) ||
+ "fsl,tmr-prsc", &ptp_qoriq->tmr_prsc) ||
of_property_read_u32(node,
- "fsl,tmr-add", &qoriq_ptp->tmr_add) ||
+ "fsl,tmr-add", &ptp_qoriq->tmr_add) ||
of_property_read_u32(node,
- "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) ||
+ "fsl,tmr-fiper1", &ptp_qoriq->tmr_fiper1) ||
of_property_read_u32(node,
- "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) ||
+ "fsl,tmr-fiper2", &ptp_qoriq->tmr_fiper2) ||
of_property_read_u32(node,
- "fsl,max-adj", &qoriq_ptp->caps.max_adj)) {
+ "fsl,max-adj", &ptp_qoriq->caps.max_adj)) {
pr_warn("device tree node missing required elements, try automatic configuration\n");
- if (qoriq_ptp_auto_config(qoriq_ptp, node))
- goto no_config;
+ if (ptp_qoriq_auto_config(ptp_qoriq, node))
+ return -ENODEV;
}
- err = -ENODEV;
+ if (of_property_read_bool(node, "little-endian")) {
+ ptp_qoriq->read = qoriq_read_le;
+ ptp_qoriq->write = qoriq_write_le;
+ } else {
+ ptp_qoriq->read = qoriq_read_be;
+ ptp_qoriq->write = qoriq_write_be;
+ }
+
+ /* The eTSEC uses differnt memory map with DPAA/ENETC */
+ if (of_device_is_compatible(node, "fsl,etsec-ptp")) {
+ ptp_qoriq->regs.ctrl_regs = base + ETSEC_CTRL_REGS_OFFSET;
+ ptp_qoriq->regs.alarm_regs = base + ETSEC_ALARM_REGS_OFFSET;
+ ptp_qoriq->regs.fiper_regs = base + ETSEC_FIPER_REGS_OFFSET;
+ ptp_qoriq->regs.etts_regs = base + ETSEC_ETTS_REGS_OFFSET;
+ } else {
+ ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
+ ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET;
+ ptp_qoriq->regs.fiper_regs = base + FIPER_REGS_OFFSET;
+ ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET;
+ }
+
+ ktime_get_real_ts64(&now);
+ ptp_qoriq_settime(&ptp_qoriq->caps, &now);
+
+ tmr_ctrl =
+ (ptp_qoriq->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
+ (ptp_qoriq->cksel & CKSEL_MASK) << CKSEL_SHIFT;
+
+ spin_lock_init(&ptp_qoriq->lock);
+ spin_lock_irqsave(&ptp_qoriq->lock, flags);
+
+ regs = &ptp_qoriq->regs;
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_add, ptp_qoriq->tmr_add);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc);
+ ptp_qoriq->write(&regs->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1);
+ ptp_qoriq->write(&regs->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2);
+ set_alarm(ptp_qoriq);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl,
+ tmr_ctrl|FIPERST|RTPE|TE|FRD);
+
+ spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
+
+ ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, ptp_qoriq->dev);
+ if (IS_ERR(ptp_qoriq->clock))
+ return PTR_ERR(ptp_qoriq->clock);
+
+ ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock);
+ ptp_qoriq_create_debugfs(ptp_qoriq);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ptp_qoriq_init);
- qoriq_ptp->irq = platform_get_irq(dev, 0);
+void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq)
+{
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_temask, 0);
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl, 0);
+
+ ptp_qoriq_remove_debugfs(ptp_qoriq);
+ ptp_clock_unregister(ptp_qoriq->clock);
+ iounmap(ptp_qoriq->base);
+ free_irq(ptp_qoriq->irq, ptp_qoriq);
+}
+EXPORT_SYMBOL_GPL(ptp_qoriq_free);
+
+static int ptp_qoriq_probe(struct platform_device *dev)
+{
+ struct ptp_qoriq *ptp_qoriq;
+ int err = -ENOMEM;
+ void __iomem *base;
+
+ ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
+ if (!ptp_qoriq)
+ goto no_memory;
- if (qoriq_ptp->irq < 0) {
+ ptp_qoriq->dev = &dev->dev;
+
+ err = -ENODEV;
+
+ ptp_qoriq->irq = platform_get_irq(dev, 0);
+ if (ptp_qoriq->irq < 0) {
pr_err("irq not in device tree\n");
goto no_node;
}
- if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) {
+ if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED,
+ DRIVER, ptp_qoriq)) {
pr_err("request_irq failed\n");
goto no_node;
}
- qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!qoriq_ptp->rsrc) {
+ ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!ptp_qoriq->rsrc) {
pr_err("no resource\n");
goto no_resource;
}
- if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) {
+ if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) {
pr_err("resource busy\n");
goto no_resource;
}
- spin_lock_init(&qoriq_ptp->lock);
-
- base = ioremap(qoriq_ptp->rsrc->start,
- resource_size(qoriq_ptp->rsrc));
+ base = ioremap(ptp_qoriq->rsrc->start,
+ resource_size(ptp_qoriq->rsrc));
if (!base) {
pr_err("ioremap ptp registers failed\n");
goto no_ioremap;
}
- qoriq_ptp->base = base;
-
- if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) {
- qoriq_ptp->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET;
- qoriq_ptp->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET;
- qoriq_ptp->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET;
- qoriq_ptp->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET;
- } else {
- qoriq_ptp->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
- qoriq_ptp->regs.alarm_regs = base + ALARM_REGS_OFFSET;
- qoriq_ptp->regs.fiper_regs = base + FIPER_REGS_OFFSET;
- qoriq_ptp->regs.etts_regs = base + ETTS_REGS_OFFSET;
- }
-
- ktime_get_real_ts64(&now);
- ptp_qoriq_settime(&qoriq_ptp->caps, &now);
-
- tmr_ctrl =
- (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
- (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT;
-
- spin_lock_irqsave(&qoriq_ptp->lock, flags);
-
- regs = &qoriq_ptp->regs;
- qoriq_write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl);
- qoriq_write(&regs->ctrl_regs->tmr_add, qoriq_ptp->tmr_add);
- qoriq_write(&regs->ctrl_regs->tmr_prsc, qoriq_ptp->tmr_prsc);
- qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
- set_alarm(qoriq_ptp);
- qoriq_write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
-
- spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
-
- qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev);
- if (IS_ERR(qoriq_ptp->clock)) {
- err = PTR_ERR(qoriq_ptp->clock);
+ err = ptp_qoriq_init(ptp_qoriq, base, &ptp_qoriq_caps);
+ if (err)
goto no_clock;
- }
- qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock);
-
- platform_set_drvdata(dev, qoriq_ptp);
+ platform_set_drvdata(dev, ptp_qoriq);
return 0;
no_clock:
- iounmap(qoriq_ptp->base);
+ iounmap(ptp_qoriq->base);
no_ioremap:
- release_resource(qoriq_ptp->rsrc);
+ release_resource(ptp_qoriq->rsrc);
no_resource:
- free_irq(qoriq_ptp->irq, qoriq_ptp);
-no_config:
+ free_irq(ptp_qoriq->irq, ptp_qoriq);
no_node:
- kfree(qoriq_ptp);
+ kfree(ptp_qoriq);
no_memory:
return err;
}
-static int qoriq_ptp_remove(struct platform_device *dev)
+static int ptp_qoriq_remove(struct platform_device *dev)
{
- struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
- struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
-
- qoriq_write(&regs->ctrl_regs->tmr_temask, 0);
- qoriq_write(&regs->ctrl_regs->tmr_ctrl, 0);
-
- ptp_clock_unregister(qoriq_ptp->clock);
- iounmap(qoriq_ptp->base);
- release_resource(qoriq_ptp->rsrc);
- free_irq(qoriq_ptp->irq, qoriq_ptp);
- kfree(qoriq_ptp);
+ struct ptp_qoriq *ptp_qoriq = platform_get_drvdata(dev);
+ ptp_qoriq_free(ptp_qoriq);
+ release_resource(ptp_qoriq->rsrc);
+ kfree(ptp_qoriq);
return 0;
}
@@ -573,16 +641,16 @@ static const struct of_device_id match_table[] = {
};
MODULE_DEVICE_TABLE(of, match_table);
-static struct platform_driver qoriq_ptp_driver = {
+static struct platform_driver ptp_qoriq_driver = {
.driver = {
.name = "ptp_qoriq",
.of_match_table = match_table,
},
- .probe = qoriq_ptp_probe,
- .remove = qoriq_ptp_remove,
+ .probe = ptp_qoriq_probe,
+ .remove = ptp_qoriq_remove,
};
-module_platform_driver(qoriq_ptp_driver);
+module_platform_driver(ptp_qoriq_driver);
MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer");
diff --git a/drivers/ptp/ptp_qoriq_debugfs.c b/drivers/ptp/ptp_qoriq_debugfs.c
new file mode 100644
index 000000000000..e8dddcedf288
--- /dev/null
+++ b/drivers/ptp/ptp_qoriq_debugfs.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2019 NXP
+ */
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/fsl/ptp_qoriq.h>
+
+static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val)
+{
+ struct ptp_qoriq *ptp_qoriq = data;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+ u32 ctrl;
+
+ ctrl = ptp_qoriq->read(&regs->ctrl_regs->tmr_ctrl);
+ *val = ctrl & PP1L ? 1 : 0;
+
+ return 0;
+}
+
+static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val)
+{
+ struct ptp_qoriq *ptp_qoriq = data;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+ u32 ctrl;
+
+ ctrl = ptp_qoriq->read(&regs->ctrl_regs->tmr_ctrl);
+ if (val == 0)
+ ctrl &= ~PP1L;
+ else
+ ctrl |= PP1L;
+
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl, ctrl);
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get,
+ ptp_qoriq_fiper1_lpbk_set, "%llu\n");
+
+static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val)
+{
+ struct ptp_qoriq *ptp_qoriq = data;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+ u32 ctrl;
+
+ ctrl = ptp_qoriq->read(&regs->ctrl_regs->tmr_ctrl);
+ *val = ctrl & PP2L ? 1 : 0;
+
+ return 0;
+}
+
+static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val)
+{
+ struct ptp_qoriq *ptp_qoriq = data;
+ struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
+ u32 ctrl;
+
+ ctrl = ptp_qoriq->read(&regs->ctrl_regs->tmr_ctrl);
+ if (val == 0)
+ ctrl &= ~PP2L;
+ else
+ ctrl |= PP2L;
+
+ ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl, ctrl);
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get,
+ ptp_qoriq_fiper2_lpbk_set, "%llu\n");
+
+void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq)
+{
+ struct dentry *root;
+
+ root = debugfs_create_dir(dev_name(ptp_qoriq->dev), NULL);
+ if (IS_ERR(root))
+ return;
+ if (!root)
+ goto err_root;
+
+ ptp_qoriq->debugfs_root = root;
+
+ if (!debugfs_create_file_unsafe("fiper1-loopback", 0600, root,
+ ptp_qoriq, &ptp_qoriq_fiper1_fops))
+ goto err_node;
+ if (!debugfs_create_file_unsafe("fiper2-loopback", 0600, root,
+ ptp_qoriq, &ptp_qoriq_fiper2_fops))
+ goto err_node;
+ return;
+
+err_node:
+ debugfs_remove_recursive(root);
+ ptp_qoriq->debugfs_root = NULL;
+err_root:
+ dev_err(ptp_qoriq->dev, "failed to initialize debugfs\n");
+}
+
+void ptp_qoriq_remove_debugfs(struct ptp_qoriq *ptp_qoriq)
+{
+ debugfs_remove_recursive(ptp_qoriq->debugfs_root);
+ ptp_qoriq->debugfs_root = NULL;
+}
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index bb655854713d..b64c56c33c3b 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -1382,9 +1382,9 @@ static int tsi721_doorbell_init(struct tsi721_device *priv)
INIT_WORK(&priv->idb_work, tsi721_db_dpc);
/* Allocate buffer for inbound doorbells queue */
- priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev,
- IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
- &priv->idb_dma, GFP_KERNEL);
+ priv->idb_base = dma_alloc_coherent(&priv->pdev->dev,
+ IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+ &priv->idb_dma, GFP_KERNEL);
if (!priv->idb_base)
return -ENOMEM;
@@ -1447,9 +1447,9 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT);
/* Allocate space for DMA descriptors */
- bd_ptr = dma_zalloc_coherent(&priv->pdev->dev,
- bd_num * sizeof(struct tsi721_dma_desc),
- &bd_phys, GFP_KERNEL);
+ bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
+ bd_num * sizeof(struct tsi721_dma_desc),
+ &bd_phys, GFP_KERNEL);
if (!bd_ptr)
return -ENOMEM;
@@ -1464,7 +1464,7 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
bd_num : TSI721_DMA_MINSTSSZ;
sts_size = roundup_pow_of_two(sts_size);
- sts_ptr = dma_zalloc_coherent(&priv->pdev->dev,
+ sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
sts_size * sizeof(struct tsi721_dma_sts),
&sts_phys, GFP_KERNEL);
if (!sts_ptr) {
@@ -1939,10 +1939,10 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id,
/* Outbound message descriptor status FIFO allocation */
priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1);
- priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev,
- priv->omsg_ring[mbox].sts_size *
- sizeof(struct tsi721_dma_sts),
- &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL);
+ priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev,
+ priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+ &priv->omsg_ring[mbox].sts_phys,
+ GFP_KERNEL);
if (priv->omsg_ring[mbox].sts_base == NULL) {
tsi_debug(OMSG, &priv->pdev->dev,
"ENOMEM for OB_MSG_%d status FIFO", mbox);
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index 006ea5a45020..7f5d4436f594 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -90,9 +90,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
* Allocate space for DMA descriptors
* (add an extra element for link descriptor)
*/
- bd_ptr = dma_zalloc_coherent(dev,
- (bd_num + 1) * sizeof(struct tsi721_dma_desc),
- &bd_phys, GFP_ATOMIC);
+ bd_ptr = dma_alloc_coherent(dev,
+ (bd_num + 1) * sizeof(struct tsi721_dma_desc),
+ &bd_phys, GFP_ATOMIC);
if (!bd_ptr)
return -ENOMEM;
@@ -108,7 +108,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ?
(bd_num + 1) : TSI721_DMA_MINSTSSZ;
sts_size = roundup_pow_of_two(sts_size);
- sts_ptr = dma_zalloc_coherent(dev,
+ sts_ptr = dma_alloc_coherent(dev,
sts_size * sizeof(struct tsi721_dma_sts),
&sts_phys, GFP_ATOMIC);
if (!sts_ptr) {
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 73e4b407f162..ad5e303dda05 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -290,8 +290,7 @@ const struct attribute_group *rio_dev_groups[] = {
NULL,
};
-static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
- size_t count)
+static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count)
{
long val;
int rc;
@@ -314,7 +313,7 @@ exit:
return rc;
}
-static BUS_ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store);
+static BUS_ATTR_WO(scan);
static struct attribute *rio_bus_attrs[] = {
&bus_attr_scan.attr,
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 28f55248eb90..753a6a1b30c3 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>
#include <linux/platform_device.h>
@@ -22,12 +21,7 @@
struct pm8607_regulator_info {
struct regulator_desc desc;
- struct pm860x_chip *chip;
- struct regulator_dev *regulator;
- struct i2c_client *i2c;
- struct i2c_client *i2c_8606;
- unsigned int *vol_table;
unsigned int *vol_suspend;
int slope_double;
@@ -210,13 +204,15 @@ static const unsigned int LDO14_suspend_table[] = {
static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- int ret = -EINVAL;
+ int ret;
+
+ ret = regulator_list_voltage_table(rdev, index);
+ if (ret < 0)
+ return ret;
+
+ if (info->slope_double)
+ ret <<= 1;
- if (info->vol_table && (index < rdev->desc->n_voltages)) {
- ret = info->vol_table[index];
- if (info->slope_double)
- ret <<= 1;
- }
return ret;
}
@@ -257,6 +253,7 @@ static const struct regulator_ops pm8606_preg_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_##vreg, \
.owner = THIS_MODULE, \
+ .volt_table = vreg##_table, \
.n_voltages = ARRAY_SIZE(vreg##_table), \
.vsel_reg = PM8607_##vreg, \
.vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \
@@ -266,7 +263,6 @@ static const struct regulator_ops pm8606_preg_ops = {
.enable_mask = 1 << (ebit), \
}, \
.slope_double = (0), \
- .vol_table = (unsigned int *)&vreg##_table, \
.vol_suspend = (unsigned int *)&vreg##_suspend_table, \
}
@@ -278,6 +274,7 @@ static const struct regulator_ops pm8606_preg_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_LDO##_id, \
.owner = THIS_MODULE, \
+ .volt_table = LDO##_id##_table, \
.n_voltages = ARRAY_SIZE(LDO##_id##_table), \
.vsel_reg = PM8607_##vreg, \
.vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
@@ -285,7 +282,6 @@ static const struct regulator_ops pm8606_preg_ops = {
.enable_mask = 1 << (ebit), \
}, \
.slope_double = (0), \
- .vol_table = (unsigned int *)&LDO##_id##_table, \
.vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
}
@@ -349,6 +345,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
struct pm8607_regulator_info *info = NULL;
struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
struct regulator_config config = { };
+ struct regulator_dev *rdev;
struct resource *res;
int i;
@@ -371,13 +368,9 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
/* i is used to check regulator ID */
i = -1;
}
- info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
- info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
- chip->client;
- info->chip = chip;
/* check DVC ramp slope double */
- if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
+ if ((i == PM8607_ID_BUCK3) && chip->buck3_double)
info->slope_double = 1;
config.dev = &pdev->dev;
@@ -392,12 +385,11 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
else
config.regmap = chip->regmap_companion;
- info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
- &config);
- if (IS_ERR(info->regulator)) {
+ rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+ if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
- return PTR_ERR(info->regulator);
+ return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, info);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index ee60a222f5eb..b7f249ee5e68 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -180,6 +180,17 @@ config REGULATOR_BCM590XX
BCM590xx PMUs. This will enable support for the software
controllable LDO/Switching regulators.
+config REGULATOR_BD70528
+ tristate "ROHM BD70528 Power Regulator"
+ depends on MFD_ROHM_BD70528
+ help
+ This driver supports voltage regulators on ROHM BD70528 PMIC.
+ This will enable support for the software controllable buck
+ and LDO regulators.
+
+ This driver can also be built as a module. If so, the module
+ will be called bd70528-regulator.
+
config REGULATOR_BD718XX
tristate "ROHM BD71837 Power Regulator"
depends on MFD_ROHM_BD718XX
@@ -457,6 +468,14 @@ config REGULATOR_MAX77620
chip to control Step-Down DC-DC and LDOs. Say Y here to
enable the regulator driver.
+config REGULATOR_MAX77650
+ tristate "Maxim MAX77650/77651 regulator support"
+ depends on MFD_MAX77650
+ help
+ Regulator driver for MAX77650/77651 PMIC from Maxim
+ Semiconductor. This device has a SIMO with three independent
+ power rails and an LDO.
+
config REGULATOR_MAX8649
tristate "Maxim 8649 voltage regulator"
depends on I2C
@@ -484,7 +503,7 @@ config REGULATOR_MAX8925
tristate "Maxim MAX8925 Power Management IC"
depends on MFD_MAX8925
help
- Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC.
+ Say y here to support the voltage regulator of Maxim MAX8925 PMIC.
config REGULATOR_MAX8952
tristate "Maxim MAX8952 Power Management IC"
@@ -501,7 +520,7 @@ config REGULATOR_MAX8973
select REGMAP_I2C
help
The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
- switching regulator delievers up to 9A of output current. Each
+ switching regulator delivers up to 9A of output current. Each
phase operates at a 2MHz fixed frequency with a 120 deg shift
from the adjacent phase, allowing the use of small magnetic component.
@@ -646,7 +665,7 @@ config REGULATOR_PCF50633
tristate "NXP PCF50633 regulator driver"
depends on MFD_PCF50633
help
- Say Y here to support the voltage regulators and convertors
+ Say Y here to support the voltage regulators and converters
on PCF50633
config REGULATOR_PFUZE100
@@ -924,7 +943,7 @@ config REGULATOR_TPS65132
select REGMAP_I2C
help
This driver supports TPS65132 single inductor - dual output
- power supply specifcally designed for display panels.
+ power supply specifically designed for display panels.
config REGULATOR_TPS65217
tristate "TI TPS65217 Power regulators"
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index b12e1c9b2118..1169f8a27d91 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
+obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
@@ -60,6 +61,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
+obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 21e20483bd91..e0239cf3f56d 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -131,7 +131,7 @@
* ACT8865 voltage number
*/
#define ACT8865_VOLTAGE_NUM 64
-#define ACT8600_SUDCDC_VOLTAGE_NUM 255
+#define ACT8600_SUDCDC_VOLTAGE_NUM 256
struct act8865 {
struct regmap *regmap;
@@ -222,7 +222,8 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
- REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000),
+ REGULATOR_LINEAR_RANGE(19000000, 192, 247, 400000),
+ REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0),
};
static struct regulator_ops act8865_ops = {
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
index 603db77723b6..caa61d306a69 100644
--- a/drivers/regulator/act8945a-regulator.c
+++ b/drivers/regulator/act8945a-regulator.c
@@ -87,7 +87,8 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = {
static int act8945a_set_suspend_state(struct regulator_dev *rdev, bool enable)
{
struct regmap *regmap = rdev->regmap;
- int id = rdev->desc->id, reg, val;
+ int id = rdev_get_id(rdev);
+ int reg, val;
switch (id) {
case ACT8945A_ID_DCDC1:
@@ -159,7 +160,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
struct regmap *regmap = rdev->regmap;
- int id = rdev->desc->id;
+ int id = rdev_get_id(rdev);
int reg, ret, val = 0;
switch (id) {
@@ -190,11 +191,11 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
switch (mode) {
case REGULATOR_MODE_STANDBY:
- if (rdev->desc->id > ACT8945A_ID_DCDC3)
+ if (id > ACT8945A_ID_DCDC3)
val = BIT(5);
break;
case REGULATOR_MODE_NORMAL:
- if (rdev->desc->id <= ACT8945A_ID_DCDC3)
+ if (id <= ACT8945A_ID_DCDC3)
val = BIT(5);
break;
default:
@@ -213,7 +214,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
static unsigned int act8945a_get_mode(struct regulator_dev *rdev)
{
struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
- int id = rdev->desc->id;
+ int id = rdev_get_id(rdev);
if (id < ACT8945A_ID_DCDC1 || id >= ACT8945A_ID_MAX)
return -EINVAL;
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index b9a93049e41e..bf3ab405eed1 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -40,35 +40,10 @@ struct arizona_ldo1 {
struct gpio_desc *ena_gpiod;
};
-static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
- unsigned int selector)
-{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
-
- if (selector == rdev->desc->n_voltages - 1)
- return 1800000;
- else
- return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
-}
-
-static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int sel;
-
- sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
- if (sel >= rdev->desc->n_voltages)
- sel = rdev->desc->n_voltages - 1;
-
- return sel;
-}
-
static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
- struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
- struct regmap *regmap = ldo->regmap;
+ struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int val;
int ret;
@@ -85,16 +60,12 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
if (val)
return 0;
- val = sel << ARIZONA_LDO1_VSEL_SHIFT;
-
- return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
- ARIZONA_LDO1_VSEL_MASK, val);
+ return regulator_set_voltage_sel_regmap(rdev, sel);
}
static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
{
- struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
- struct regmap *regmap = ldo->regmap;
+ struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int val;
int ret;
@@ -105,32 +76,35 @@ static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
if (val & ARIZONA_LDO1_HI_PWR)
return rdev->desc->n_voltages - 1;
- ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
- if (ret != 0)
- return ret;
-
- return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+ return regulator_get_voltage_sel_regmap(rdev);
}
static const struct regulator_ops arizona_ldo1_hc_ops = {
- .list_voltage = arizona_ldo1_hc_list_voltage,
- .map_voltage = arizona_ldo1_hc_map_voltage,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
.set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
};
+static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = {
+ REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0),
+};
+
static const struct regulator_desc arizona_ldo1_hc = {
.name = "LDO1",
.supply_name = "LDOVDD",
.type = REGULATOR_VOLTAGE,
.ops = &arizona_ldo1_hc_ops,
+ .vsel_reg = ARIZONA_LDO1_CONTROL_1,
+ .vsel_mask = ARIZONA_LDO1_VSEL_MASK,
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
.bypass_mask = ARIZONA_LDO1_BYPASS,
- .min_uV = 900000,
- .uV_step = 50000,
+ .linear_ranges = arizona_ldo1_hc_ranges,
+ .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges),
.n_voltages = 8,
.enable_time = 1500,
.ramp_delay = 24000,
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index 66337e12719b..e5fed289b52d 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -886,7 +886,7 @@ static int as3722_regulator_probe(struct platform_device *pdev)
as3722_regs->desc[id].min_uV = 410000;
} else {
as3722_regs->desc[id].n_voltages =
- AS3722_SD0_VSEL_MAX + 1,
+ AS3722_SD0_VSEL_MAX + 1;
as3722_regs->desc[id].min_uV = 610000;
}
as3722_regs->desc[id].uV_step = 10000;
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 48af859fd053..fba8f58ab769 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -367,13 +367,12 @@ static const int axp209_dcdc2_ldo3_slew_rates[] = {
static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
{
struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
- const struct regulator_desc *desc = rdev->desc;
+ const struct regulator_desc *desc;
u8 reg, mask, enable, cfg = 0xff;
const int *slew_rates;
int rate_count = 0;
- if (!rdev)
- return -EINVAL;
+ desc = rdev->desc;
switch (axp20x->variant) {
case AXP209_ID:
@@ -436,11 +435,13 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev)
{
struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
- const struct regulator_desc *desc = rdev->desc;
+ const struct regulator_desc *desc;
if (!rdev)
return -EINVAL;
+ desc = rdev->desc;
+
switch (axp20x->variant) {
case AXP209_ID:
if ((desc->id == AXP20X_LDO3) &&
@@ -573,7 +574,7 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP22X_DCDC3_V_OUT, AXP22X_DCDC3_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC3_MASK),
AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20,
- AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT,
+ AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC4_MASK),
AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
AXP22X_DCDC5_V_OUT, AXP22X_DCDC5_V_OUT_MASK,
@@ -719,7 +720,7 @@ static const struct regulator_desc axp803_regulators[] = {
AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT,
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
@@ -729,7 +730,7 @@ static const struct regulator_desc axp803_regulators[] = {
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin",
axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
- AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT,
+ AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
@@ -744,7 +745,7 @@ static const struct regulator_desc axp803_regulators[] = {
AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
- AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT,
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
AXP803_FLDO1_V_OUT, AXP803_FLDO1_V_OUT_MASK,
@@ -791,7 +792,7 @@ static const struct regulator_desc axp806_regulators[] = {
AXP806_DCDCA_V_CTRL, AXP806_DCDCA_V_CTRL_MASK,
AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCA_MASK),
AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50,
- AXP806_DCDCB_V_CTRL, AXP806_DCDCB_V_CTRL,
+ AXP806_DCDCB_V_CTRL, AXP806_DCDCB_V_CTRL_MASK,
AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCB_MASK),
AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc",
axp806_dcdca_ranges, AXP806_DCDCA_NUM_VOLTAGES,
@@ -817,7 +818,7 @@ static const struct regulator_desc axp806_regulators[] = {
AXP806_BLDO1_V_CTRL, AXP806_BLDO1_V_CTRL_MASK,
AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO1_MASK),
AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100,
- AXP806_BLDO2_V_CTRL, AXP806_BLDO2_V_CTRL,
+ AXP806_BLDO2_V_CTRL, AXP806_BLDO2_V_CTRL_MASK,
AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO2_MASK),
AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100,
AXP806_BLDO3_V_CTRL, AXP806_BLDO3_V_CTRL_MASK,
@@ -952,7 +953,7 @@ static const struct regulator_desc axp813_regulators[] = {
AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT,
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
@@ -962,7 +963,7 @@ static const struct regulator_desc axp813_regulators[] = {
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin",
axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
- AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT,
+ AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
@@ -977,7 +978,7 @@ static const struct regulator_desc axp813_regulators[] = {
AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
- AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT,
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
/* to do / check ... */
AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 92d6d7b10cf7..e49c0a7d5dd5 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -242,8 +242,12 @@ static int bcm590xx_get_enable_register(int id)
case BCM590XX_REG_SDSR2:
reg = BCM590XX_SDSR2PMCTRL1;
break;
+ case BCM590XX_REG_VSR:
+ reg = BCM590XX_VSRPMCTRL1;
+ break;
case BCM590XX_REG_VBUS:
reg = BCM590XX_OTG_CTRL;
+ break;
}
diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c
new file mode 100644
index 000000000000..30e3ed430a8a
--- /dev/null
+++ b/drivers/regulator/bd70528-regulator.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 ROHM Semiconductors
+// bd70528-regulator.c ROHM BD70528MWV regulator driver
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rohm-bd70528.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+#define BUCK_RAMPRATE_250MV 0
+#define BUCK_RAMPRATE_125MV 1
+#define BUCK_RAMP_MAX 250
+
+static const struct regulator_linear_range bd70528_buck1_volts[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
+ REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
+};
+static const struct regulator_linear_range bd70528_buck2_volts[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
+ REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
+};
+static const struct regulator_linear_range bd70528_buck3_volts[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
+ REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
+};
+
+/* All LDOs have same voltage ranges */
+static const struct regulator_linear_range bd70528_ldo_volts[] = {
+ REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
+ REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
+ REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
+ REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0),
+};
+
+/* Also both LEDs support same voltages */
+static const unsigned int led_volts[] = {
+ 20000, 30000
+};
+
+static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) {
+ unsigned int ramp_value = BUCK_RAMPRATE_250MV;
+
+ if (ramp_delay <= 125)
+ ramp_value = BUCK_RAMPRATE_125MV;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+ BD70528_MASK_BUCK_RAMP,
+ ramp_value << BD70528_SIFT_BUCK_RAMP);
+ }
+ dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n",
+ rdev->desc->name, ramp_delay);
+ return -EINVAL;
+}
+
+static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int ret;
+
+ ret = regulator_is_enabled_regmap(rdev);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0)
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ dev_err(&rdev->dev,
+ "LED voltage change not allowed when led is enabled\n");
+
+ return -EBUSY;
+}
+
+static const struct regulator_ops bd70528_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = bd70528_set_ramp_delay,
+};
+
+static const struct regulator_ops bd70528_ldo_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = bd70528_set_ramp_delay,
+};
+
+static const struct regulator_ops bd70528_led_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = bd70528_led_set_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_desc bd70528_desc[] = {
+ {
+ .name = "buck1",
+ .of_match = of_match_ptr("BUCK1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK1,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck1_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK1_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK1_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "buck2",
+ .of_match = of_match_ptr("BUCK2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK2,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck2_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK2_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK2_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "buck3",
+ .of_match = of_match_ptr("BUCK3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK3,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck3_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK3_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK3_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO1,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO1_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO1_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO2,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO2_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO2_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO3,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO3_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO3_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo_led1",
+ .of_match = of_match_ptr("LDO_LED1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LED1,
+ .ops = &bd70528_led_ops,
+ .type = REGULATOR_VOLTAGE,
+ .volt_table = &led_volts[0],
+ .n_voltages = ARRAY_SIZE(led_volts),
+ .enable_reg = BD70528_REG_LED_EN,
+ .enable_mask = BD70528_MASK_LED1_EN,
+ .vsel_reg = BD70528_REG_LED_VOLT,
+ .vsel_mask = BD70528_MASK_LED1_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo_led2",
+ .of_match = of_match_ptr("LDO_LED2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LED2,
+ .ops = &bd70528_led_ops,
+ .type = REGULATOR_VOLTAGE,
+ .volt_table = &led_volts[0],
+ .n_voltages = ARRAY_SIZE(led_volts),
+ .enable_reg = BD70528_REG_LED_EN,
+ .enable_mask = BD70528_MASK_LED2_EN,
+ .vsel_reg = BD70528_REG_LED_VOLT,
+ .vsel_mask = BD70528_MASK_LED2_VOLT,
+ .owner = THIS_MODULE,
+ },
+
+};
+
+static int bd70528_probe(struct platform_device *pdev)
+{
+ struct rohm_regmap_dev *bd70528;
+ int i;
+ struct regulator_config config = {
+ .dev = pdev->dev.parent,
+ };
+
+ bd70528 = dev_get_drvdata(pdev->dev.parent);
+ if (!bd70528) {
+ dev_err(&pdev->dev, "No MFD driver data\n");
+ return -EINVAL;
+ }
+
+ config.regmap = bd70528->regmap;
+
+ for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) {
+ struct regulator_dev *rdev;
+
+ rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ bd70528_desc[i].name);
+ return PTR_ERR(rdev);
+ }
+ }
+ return 0;
+}
+
+static struct platform_driver bd70528_regulator = {
+ .driver = {
+ .name = "bd70528-pmic"
+ },
+ .probe = bd70528_probe,
+};
+
+module_platform_driver(bd70528_regulator);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD70528 voltage regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index b8dcdc21dc22..b2191be49670 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -79,7 +79,7 @@ static int bd718xx_set_voltage_sel_pickable_restricted(
return regulator_set_voltage_sel_pickable_regmap(rdev, sel);
}
-static struct regulator_ops bd718xx_pickable_range_ldo_ops = {
+static const struct regulator_ops bd718xx_pickable_range_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -88,7 +88,7 @@ static struct regulator_ops bd718xx_pickable_range_ldo_ops = {
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
};
-static struct regulator_ops bd718xx_pickable_range_buck_ops = {
+static const struct regulator_ops bd718xx_pickable_range_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -98,7 +98,7 @@ static struct regulator_ops bd718xx_pickable_range_buck_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_ldo_regulator_ops = {
+static const struct regulator_ops bd718xx_ldo_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -107,7 +107,7 @@ static struct regulator_ops bd718xx_ldo_regulator_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
-static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
+static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -116,7 +116,7 @@ static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
-static struct regulator_ops bd718xx_buck_regulator_ops = {
+static const struct regulator_ops bd718xx_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -126,7 +126,7 @@ static struct regulator_ops bd718xx_buck_regulator_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
+static const struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -137,7 +137,7 @@ static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
+static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -350,6 +350,135 @@ static const struct reg_init bd71837_ldo6_inits[] = {
},
};
+#define NUM_DVS_BUCKS 4
+
+struct of_dvs_setting {
+ const char *prop;
+ unsigned int reg;
+};
+
+static int set_dvs_levels(const struct of_dvs_setting *dvs,
+ struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regmap *regmap)
+{
+ int ret, i;
+ unsigned int uv;
+
+ ret = of_property_read_u32(np, dvs->prop, &uv);
+ if (ret) {
+ if (ret != -EINVAL)
+ return ret;
+ return 0;
+ }
+
+ for (i = 0; i < desc->n_voltages; i++) {
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ if (ret < 0)
+ continue;
+ if (ret == uv) {
+ i <<= ffs(desc->vsel_mask) - 1;
+ ret = regmap_update_bits(regmap, dvs->reg,
+ DVS_BUCK_RUN_MASK, i);
+ break;
+ }
+ }
+ return ret;
+}
+
+static int buck4_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD71837_REG_BUCK4_VOLT_RUN,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+static int buck3_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD71837_REG_BUCK3_VOLT_RUN,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static int buck2_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD718XX_REG_BUCK2_VOLT_RUN,
+ },
+ {
+ .prop = "rohm,dvs-idle-voltage",
+ .reg = BD718XX_REG_BUCK2_VOLT_IDLE,
+ },
+ };
+
+
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static int buck1_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_RUN,
+ },
+ {
+ .prop = "rohm,dvs-idle-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_IDLE,
+ },
+ {
+ .prop = "rohm,dvs-suspend-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_SUSP,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
static const struct bd718xx_regulator_data bd71847_regulators[] = {
{
.desc = {
@@ -368,6 +497,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_reg = BD718XX_REG_BUCK1_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck1_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -391,6 +521,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck2_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -662,6 +793,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK1_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck1_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -685,6 +817,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck2_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -708,6 +841,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK3_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck3_set_hw_dvs_levels,
},
.init = {
.reg = BD71837_REG_BUCK3_CTRL,
@@ -731,6 +865,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK4_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck4_set_hw_dvs_levels,
},
.init = {
.reg = BD71837_REG_BUCK4_CTRL,
@@ -1029,6 +1164,7 @@ static int bd718xx_probe(struct platform_device *pdev)
};
int i, j, err;
+ bool use_snvs;
mfd = dev_get_drvdata(pdev->dev.parent);
if (!mfd) {
@@ -1055,27 +1191,28 @@ static int bd718xx_probe(struct platform_device *pdev)
BD718XX_REG_REGLOCK);
}
- /* At poweroff transition PMIC HW disables EN bit for regulators but
- * leaves SEL bit untouched. So if state transition from POWEROFF
- * is done to SNVS - then all power rails controlled by SW (having
- * SEL bit set) stay disabled as EN is cleared. This may result boot
- * failure if any crucial systems are powered by these rails.
- *
+ use_snvs = of_property_read_bool(pdev->dev.parent->of_node,
+ "rohm,reset-snvs-powered");
+
+ /*
* Change the next stage from poweroff to be READY instead of SNVS
* for all reset types because OTP loading at READY will clear SEL
* bit allowing HW defaults for power rails to be used
*/
- err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1,
- BD718XX_ON_REQ_POWEROFF_MASK |
- BD718XX_SWRESET_POWEROFF_MASK |
- BD718XX_WDOG_POWEROFF_MASK |
- BD718XX_KEY_L_POWEROFF_MASK,
- BD718XX_POWOFF_TO_RDY);
- if (err) {
- dev_err(&pdev->dev, "Failed to change reset target\n");
- goto err;
- } else {
- dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n");
+ if (!use_snvs) {
+ err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1,
+ BD718XX_ON_REQ_POWEROFF_MASK |
+ BD718XX_SWRESET_POWEROFF_MASK |
+ BD718XX_WDOG_POWEROFF_MASK |
+ BD718XX_KEY_L_POWEROFF_MASK,
+ BD718XX_POWOFF_TO_RDY);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to change reset target\n");
+ goto err;
+ } else {
+ dev_dbg(&pdev->dev,
+ "Changed all resets from SVNS to READY\n");
+ }
}
for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) {
@@ -1098,19 +1235,33 @@ static int bd718xx_probe(struct platform_device *pdev)
err = PTR_ERR(rdev);
goto err;
}
- /* Regulator register gets the regulator constraints and
+
+ /*
+ * Regulator register gets the regulator constraints and
* applies them (set_machine_constraints). This should have
* turned the control register(s) to correct values and we
* can now switch the control from PMIC state machine to the
* register interface
+ *
+ * At poweroff transition PMIC HW disables EN bit for
+ * regulators but leaves SEL bit untouched. So if state
+ * transition from POWEROFF is done to SNVS - then all power
+ * rails controlled by SW (having SEL bit set) stay disabled
+ * as EN is cleared. This will result boot failure if any
+ * crucial systems are powered by these rails. We don't
+ * enable SW control for crucial regulators if snvs state is
+ * used
*/
- err = regmap_update_bits(mfd->regmap, r->init.reg,
- r->init.mask, r->init.val);
- if (err) {
- dev_err(&pdev->dev,
- "Failed to write BUCK/LDO SEL bit for (%s)\n",
- desc->name);
- goto err;
+ if (!use_snvs || !rdev->constraints->always_on ||
+ !rdev->constraints->boot_on) {
+ err = regmap_update_bits(mfd->regmap, r->init.reg,
+ r->init.mask, r->init.val);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to take control for (%s)\n",
+ desc->name);
+ goto err;
+ }
}
for (j = 0; j < r->additional_init_amnt; j++) {
err = regmap_update_bits(mfd->regmap,
diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c
index e12dd1f750f3..e690c2ce5b3c 100644
--- a/drivers/regulator/bd9571mwv-regulator.c
+++ b/drivers/regulator/bd9571mwv-regulator.c
@@ -100,7 +100,7 @@ static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev,
}
/* Operations permitted on AVS voltage regulator */
-static struct regulator_ops avs_ops = {
+static const struct regulator_ops avs_ops = {
.set_voltage_sel = bd9571mwv_avs_set_voltage_sel_regmap,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = bd9571mwv_avs_get_voltage_sel_regmap,
@@ -108,7 +108,7 @@ static struct regulator_ops avs_ops = {
};
/* Operations permitted on voltage regulators */
-static struct regulator_ops reg_ops = {
+static const struct regulator_ops reg_ops = {
.set_voltage_sel = bd9571mwv_reg_set_voltage_sel_regmap,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -116,13 +116,13 @@ static struct regulator_ops reg_ops = {
};
/* Operations permitted on voltage monitors */
-static struct regulator_ops vid_ops = {
+static const struct regulator_ops vid_ops = {
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f,
0x80, 600000, 10000, 0x3c),
BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf,
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b9d7b45c7295..68473d0cc57e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -23,7 +23,6 @@
#include <linux/mutex.h>
#include <linux/suspend.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/regmap.h>
@@ -82,7 +81,6 @@ struct regulator_enable_gpio {
struct gpio_desc *gpiod;
u32 enable_count; /* a number of enabled shared GPIO */
u32 request_count; /* a number of requested shared GPIO */
- unsigned int ena_gpio_invert:1;
};
/*
@@ -145,14 +143,6 @@ static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
return false;
}
-static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
-{
- if (rdev && rdev->supply)
- return rdev->supply->rdev;
-
- return NULL;
-}
-
/**
* regulator_lock_nested - lock a single regulator
* @rdev: regulator source
@@ -326,7 +316,7 @@ err_unlock:
* @rdev: regulator source
* @ww_ctx: w/w mutex acquire context
*
- * Unlock all regulators related with rdev by coupling or suppling.
+ * Unlock all regulators related with rdev by coupling or supplying.
*/
static void regulator_unlock_dependent(struct regulator_dev *rdev,
struct ww_acquire_ctx *ww_ctx)
@@ -341,7 +331,7 @@ static void regulator_unlock_dependent(struct regulator_dev *rdev,
* @ww_ctx: w/w mutex acquire context
*
* This function as a wrapper on regulator_lock_recursive(), which locks
- * all regulators related with rdev by coupling or suppling.
+ * all regulators related with rdev by coupling or supplying.
*/
static void regulator_lock_dependent(struct regulator_dev *rdev,
struct ww_acquire_ctx *ww_ctx)
@@ -924,14 +914,14 @@ static int drms_uA_update(struct regulator_dev *rdev)
int current_uA = 0, output_uV, input_uV, err;
unsigned int mode;
- lockdep_assert_held_once(&rdev->mutex.base);
-
/*
* first check to see if we can set modes at all, otherwise just
* tell the consumer everything is OK.
*/
- if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
+ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
+ rdev_dbg(rdev, "DRMS operation not allowed\n");
return 0;
+ }
if (!rdev->desc->ops->get_optimum_mode &&
!rdev->desc->ops->set_load)
@@ -1003,7 +993,7 @@ static int suspend_set_state(struct regulator_dev *rdev,
if (rstate == NULL)
return 0;
- /* If we have no suspend mode configration don't set anything;
+ /* If we have no suspend mode configuration don't set anything;
* only warn if the driver implements set_suspend_voltage or
* set_suspend_mode callback.
*/
@@ -1131,7 +1121,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
int current_uV = _regulator_get_voltage(rdev);
if (current_uV == -ENOTRECOVERABLE) {
- /* This regulator can't be read and must be initted */
+ /* This regulator can't be read and must be initialized */
rdev_info(rdev, "Setting %d-%duV\n",
rdev->constraints->min_uV,
rdev->constraints->max_uV);
@@ -1349,7 +1339,9 @@ static int set_machine_constraints(struct regulator_dev *rdev,
* We'll only apply the initial system load if an
* initial mode wasn't specified.
*/
+ regulator_lock(rdev);
drms_uA_update(rdev);
+ regulator_unlock(rdev);
}
if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
@@ -1780,7 +1772,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
struct device *dev = rdev->dev.parent;
int ret;
- /* No supply to resovle? */
+ /* No supply to resolve? */
if (!rdev->supply_name)
return 0;
@@ -2058,15 +2050,7 @@ static void _regulator_put(struct regulator *regulator)
debugfs_remove_recursive(regulator->debugfs);
if (regulator->dev) {
- int count = 0;
- struct regulator *r;
-
- list_for_each_entry(r, &rdev->consumer_list, list)
- if (r->dev == regulator->dev)
- count++;
-
- if (count == 1)
- device_link_remove(regulator->dev, &rdev->dev);
+ device_link_remove(regulator->dev, &rdev->dev);
/* remove any sysfs entries */
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
@@ -2237,38 +2221,21 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
{
struct regulator_enable_gpio *pin;
struct gpio_desc *gpiod;
- int ret;
- if (config->ena_gpiod)
- gpiod = config->ena_gpiod;
- else
- gpiod = gpio_to_desc(config->ena_gpio);
+ gpiod = config->ena_gpiod;
list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
if (pin->gpiod == gpiod) {
- rdev_dbg(rdev, "GPIO %d is already used\n",
- config->ena_gpio);
+ rdev_dbg(rdev, "GPIO is already used\n");
goto update_ena_gpio_to_rdev;
}
}
- if (!config->ena_gpiod) {
- ret = gpio_request_one(config->ena_gpio,
- GPIOF_DIR_OUT | config->ena_gpio_flags,
- rdev_get_name(rdev));
- if (ret)
- return ret;
- }
-
pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
- if (pin == NULL) {
- if (!config->ena_gpiod)
- gpio_free(config->ena_gpio);
+ if (pin == NULL)
return -ENOMEM;
- }
pin->gpiod = gpiod;
- pin->ena_gpio_invert = config->ena_gpio_invert;
list_add(&pin->list, &regulator_ena_gpio_list);
update_ena_gpio_to_rdev:
@@ -2289,7 +2256,6 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
if (pin->gpiod == rdev->ena_pin->gpiod) {
if (pin->request_count <= 1) {
pin->request_count = 0;
- gpiod_put(pin->gpiod);
list_del(&pin->list);
kfree(pin);
rdev->ena_pin = NULL;
@@ -2319,8 +2285,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
if (enable) {
/* Enable GPIO at initial use */
if (pin->enable_count == 0)
- gpiod_set_value_cansleep(pin->gpiod,
- !pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod, 1);
pin->enable_count++;
} else {
@@ -2331,8 +2296,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
/* Disable GPIO if not used */
if (pin->enable_count <= 1) {
- gpiod_set_value_cansleep(pin->gpiod,
- pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod, 0);
pin->enable_count = 0;
}
}
@@ -2409,7 +2373,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
* timer wrapping.
* in case of multiple timer wrapping, either it can be
* detected by out-of-range remaining, or it cannot be
- * detected and we gets a panelty of
+ * detected and we get a penalty of
* _regulator_enable_delay().
*/
remaining = intended - start_jiffy;
@@ -2809,7 +2773,7 @@ static void regulator_disable_work(struct work_struct *work)
/**
* regulator_disable_deferred - disable regulator output with delay
* @regulator: regulator source
- * @ms: miliseconds until the regulator is disabled
+ * @ms: milliseconds until the regulator is disabled
*
* Execute regulator_disable() on the regulator after a delay. This
* is intended for use with devices that require some time to quiesce.
@@ -4943,7 +4907,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
* device tree until we have handled it over to the core. If the
* config that was passed in to this function DOES NOT contain
* a descriptor, and the config after this call DOES contain
- * a descriptor, we definately got one from parsing the device
+ * a descriptor, we definitely got one from parsing the device
* tree.
*/
if (!cfg->ena_gpiod && config->ena_gpiod)
@@ -4975,15 +4939,13 @@ regulator_register(const struct regulator_desc *regulator_desc,
goto clean;
}
- if (config->ena_gpiod ||
- ((config->ena_gpio || config->ena_gpio_initialized) &&
- gpio_is_valid(config->ena_gpio))) {
+ if (config->ena_gpiod) {
mutex_lock(&regulator_list_mutex);
ret = regulator_ena_gpio_request(rdev, config);
mutex_unlock(&regulator_list_mutex);
if (ret != 0) {
- rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
- config->ena_gpio, ret);
+ rdev_err(rdev, "Failed to request enable GPIO: %d\n",
+ ret);
goto clean;
}
/* The regulator core took over the GPIO descriptor */
@@ -5251,6 +5213,12 @@ struct device *rdev_get_dev(struct regulator_dev *rdev)
}
EXPORT_SYMBOL_GPL(rdev_get_dev);
+struct regmap *rdev_get_regmap(struct regulator_dev *rdev)
+{
+ return rdev->regmap;
+}
+EXPORT_SYMBOL_GPL(rdev_get_regmap);
+
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
{
return reg_init_data->driver_data;
diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c
index 2131457937b7..e7dab5c4d1d1 100644
--- a/drivers/regulator/cpcap-regulator.c
+++ b/drivers/regulator/cpcap-regulator.c
@@ -100,12 +100,11 @@ struct cpcap_regulator {
struct regulator_desc rdesc;
const u16 assign_reg;
const u16 assign_mask;
- const u16 vsel_shift;
};
#define CPCAP_REG(_ID, reg, assignment_reg, assignment_mask, val_tbl, \
- mode_mask, volt_mask, volt_shft, \
- mode_val, off_val, volt_trans_time) { \
+ mode_mask, volt_mask, mode_val, off_val, \
+ volt_trans_time) { \
.rdesc = { \
.name = #_ID, \
.of_match = of_match_ptr(#_ID), \
@@ -127,7 +126,6 @@ struct cpcap_regulator {
}, \
.assign_reg = (assignment_reg), \
.assign_mask = (assignment_mask), \
- .vsel_shift = (volt_shft), \
}
struct cpcap_ddata {
@@ -336,155 +334,155 @@ static const unsigned int vaudio_val_tbl[] = { 0, 2775000, };
* SW1 to SW4 and SW6 seems to be unused for mapphone. Note that VSIM and
* VSIMCARD have a shared resource assignment bit.
*/
-static struct cpcap_regulator omap4_regulators[] = {
+static const struct cpcap_regulator omap4_regulators[] = {
CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW1_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW2_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW3_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW4_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW5_SEL, sw5_val_tbl,
- 0x28, 0, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
+ 0x28, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW6_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
- 0x47, 0x10, 4, 0x43, 0x41, 350),
+ 0x47, 0x10, 0x43, 0x41, 350),
CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
- 0x87, 0x30, 4, 0x82, 0, 420),
+ 0x87, 0x30, 0x82, 0, 420),
CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
- 0x80, 0xf, 0, 0x80, 0, 420),
+ 0x80, 0xf, 0x80, 0, 420),
CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
- 0x17, 0, 0, 0, 0x12, 0),
+ 0x17, 0, 0, 0x12, 0),
CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
- 0x87, 0x38, 3, 0x82, 0, 420),
+ 0x87, 0x38, 0x82, 0, 420),
CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
- 0x43, 0x18, 3, 0x2, 0, 420),
+ 0x43, 0x18, 0x2, 0, 420),
CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
- 0xac, 0x2, 1, 0x4, 0, 10),
+ 0xac, 0x2, 0x4, 0, 10),
CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
- 0x23, 0x8, 3, 0, 0, 10),
+ 0x23, 0x8, 0, 0, 10),
CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
- 0x23, 0x8, 3, 0, 0, 420),
+ 0x23, 0x8, 0, 0, 420),
CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
- 0x47, 0x10, 4, 0, 0, 420),
+ 0x47, 0x10, 0, 0, 420),
CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
- 0x20c, 0xc0, 6, 0x20c, 0, 420),
+ 0x20c, 0xc0, 0x20c, 0, 420),
CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsim_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsimcard_val_tbl,
- 0x1e80, 0x8, 3, 0x1e00, 0, 420),
+ 0x1e80, 0x8, 0x1e00, 0, 420),
CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
- 0x1, 0xc, 2, 0x1, 0, 500),
+ 0x1, 0xc, 0x1, 0, 500),
CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
- 0x11c, 0x40, 6, 0xc, 0, 0),
+ 0x11c, 0x40, 0xc, 0, 0),
CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
- 0x16, 0x1, 0, 0x4, 0, 0),
+ 0x16, 0x1, 0x4, 0, 0),
{ /* sentinel */ },
};
-static struct cpcap_regulator xoom_regulators[] = {
+static const struct cpcap_regulator xoom_regulators[] = {
CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW1_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl,
- 0xf00, 0x7f, 0, 0x800, 0, 120),
+ 0xf00, 0x7f, 0x800, 0, 120),
CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW3_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl,
- 0xf00, 0x7f, 0, 0x900, 0, 100),
+ 0xf00, 0x7f, 0x900, 0, 100),
CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW5_SEL, sw5_val_tbl,
- 0x2a, 0, 0, 0x22, 0, 0),
+ 0x2a, 0, 0x22, 0, 0),
CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW6_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
- 0x87, 0x30, 4, 0x7, 0, 420),
+ 0x87, 0x30, 0x7, 0, 420),
CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
- 0x47, 0x10, 4, 0x7, 0, 350),
+ 0x47, 0x10, 0x7, 0, 350),
CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
- 0x87, 0x30, 4, 0x5, 0, 420),
+ 0x87, 0x30, 0x5, 0, 420),
CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
- 0x80, 0xf, 0, 0x80, 0, 420),
+ 0x80, 0xf, 0x80, 0, 420),
CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
- 0x17, 0, 0, 0x2, 0, 0),
+ 0x17, 0, 0x2, 0, 0),
CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
- 0x87, 0x38, 3, 0x2, 0, 420),
+ 0x87, 0x38, 0x2, 0, 420),
CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
- 0x43, 0x18, 3, 0x1, 0, 420),
+ 0x43, 0x18, 0x1, 0, 420),
CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
- 0xac, 0x2, 1, 0xc, 0, 10),
+ 0xac, 0x2, 0xc, 0, 10),
CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 10),
+ 0x23, 0x8, 0x3, 0, 10),
CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
- 0x47, 0x10, 4, 0x5, 0, 420),
+ 0x47, 0x10, 0x5, 0, 420),
CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
- 0x20c, 0xc0, 6, 0x8, 0, 420),
+ 0x20c, 0xc0, 0x8, 0, 420),
CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsim_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsimcard_val_tbl,
- 0x1e80, 0x8, 3, 0x1e00, 0, 420),
+ 0x1e80, 0x8, 0x1e00, 0, 420),
CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
- 0x1, 0xc, 2, 0, 0x1, 500),
+ 0x1, 0xc, 0, 0x1, 500),
CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
- 0x11c, 0x40, 6, 0xc, 0, 0),
+ 0x11c, 0x40, 0xc, 0, 0),
CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
- 0x16, 0x1, 0, 0x4, 0, 0),
+ 0x16, 0x1, 0x4, 0, 0),
{ /* sentinel */ },
};
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 207cb3859dcc..cefa3558236d 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -290,10 +290,10 @@ static const struct regulator_ops da9052_ldo_ops = {
.disable = regulator_disable_regmap,
};
-#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
+#define DA9052_LDO(_id, _name, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = #_id,\
+ .name = #_name,\
.ops = &da9052_ldo_ops,\
.type = REGULATOR_VOLTAGE,\
.id = DA9052_ID_##_id,\
@@ -310,10 +310,10 @@ static const struct regulator_ops da9052_ldo_ops = {
.activate_bit = (abits),\
}
-#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
+#define DA9052_DCDC(_id, _name, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = #_id,\
+ .name = #_name,\
.ops = &da9052_dcdc_ops,\
.type = REGULATOR_VOLTAGE,\
.id = DA9052_ID_##_id,\
@@ -331,37 +331,37 @@ static const struct regulator_ops da9052_ldo_ops = {
}
static struct da9052_regulator_info da9052_regulator_info[] = {
- DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
- DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, buck4, 50, 1800, 3600, 5, 6, 0),
+ DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
};
static struct da9052_regulator_info da9053_regulator_info[] = {
- DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_DCDC(BUCK4, 25, 950, 2525, 6, 6, 0),
- DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, buck4, 25, 950, 2525, 6, 6, 0),
+ DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
};
static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index 588c3d2445cf..3c6fac793658 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -48,7 +48,9 @@
#define DA9055_ID_LDO6 7
/* DA9055 BUCK current limit */
-static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+static const unsigned int da9055_current_limits[] = {
+ 500000, 600000, 700000, 800000
+};
struct da9055_conf_reg {
int reg;
@@ -169,39 +171,6 @@ static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
val << volt.sl_shift);
}
-static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
-{
- struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9055_regulator_info *info = regulator->info;
- int ret;
-
- ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
- if (ret < 0)
- return ret;
-
- ret &= info->mode.mask;
- return da9055_current_limits[ret >> info->mode.shift];
-}
-
-static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA)
-{
- struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9055_regulator_info *info = regulator->info;
- int i;
-
- for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
- if ((min_uA <= da9055_current_limits[i]) &&
- (da9055_current_limits[i] <= max_uA))
- return da9055_reg_update(regulator->da9055,
- DA9055_REG_BUCK_LIM,
- info->mode.mask,
- i << info->mode.shift);
- }
-
- return -EINVAL;
-}
-
static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
@@ -329,8 +298,8 @@ static const struct regulator_ops da9055_buck_ops = {
.get_mode = da9055_buck_get_mode,
.set_mode = da9055_buck_set_mode,
- .get_current_limit = da9055_buck_get_current_limit,
- .set_current_limit = da9055_buck_set_current_limit,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
.get_voltage_sel = da9055_regulator_get_voltage_sel,
.set_voltage_sel = da9055_regulator_set_voltage_sel,
@@ -407,6 +376,10 @@ static const struct regulator_ops da9055_ldo_ops = {
.uV_step = (step) * 1000,\
.linear_min_sel = (voffset),\
.owner = THIS_MODULE,\
+ .curr_table = da9055_current_limits,\
+ .n_current_limits = ARRAY_SIZE(da9055_current_limits),\
+ .csel_reg = DA9055_REG_BUCK_LIM,\
+ .csel_mask = (mbits),\
},\
.conf = {\
.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
@@ -457,7 +430,6 @@ static int da9055_gpio_init(struct da9055_regulator *regulator,
int gpio_mux = pdata->gpio_ren[id];
config->ena_gpiod = pdata->ena_gpiods[id];
- config->ena_gpio_invert = 1;
/*
* GPI pin is muxed with regulator to control the
diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index 34a70d9dc450..b064d8a19d4c 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -126,7 +126,7 @@ static int da9062_set_current_limit(struct regulator_dev *rdev,
const struct da9062_regulator_info *rinfo = regl->info;
int n, tval;
- for (n = 0; n < rinfo->n_current_limits; n++) {
+ for (n = rinfo->n_current_limits - 1; n >= 0; n--) {
tval = rinfo->current_limits[n];
if (tval >= min_ua && tval <= max_ua)
return regmap_field_write(regl->ilimit, n);
@@ -992,7 +992,6 @@ static int da9062_regulator_probe(struct platform_device *pdev)
struct regulator_config config = { };
const struct da9062_regulator_info *rinfo;
int irq, n, ret;
- size_t size;
int max_regulators;
switch (chip->chip_type) {
@@ -1010,9 +1009,8 @@ static int da9062_regulator_probe(struct platform_device *pdev)
}
/* Allocate memory required by usable regulators */
- size = sizeof(struct da9062_regulators) +
- max_regulators * sizeof(struct da9062_regulator);
- regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ regulators = devm_kzalloc(&pdev->dev, struct_size(regulators, regulator,
+ max_regulators), GFP_KERNEL);
if (!regulators)
return -ENOMEM;
@@ -1029,31 +1027,50 @@ static int da9062_regulator_probe(struct platform_device *pdev)
regl->desc.type = REGULATOR_VOLTAGE;
regl->desc.owner = THIS_MODULE;
- if (regl->info->mode.reg)
+ if (regl->info->mode.reg) {
regl->mode = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->mode);
- if (regl->info->suspend.reg)
+ if (IS_ERR(regl->mode))
+ return PTR_ERR(regl->mode);
+ }
+
+ if (regl->info->suspend.reg) {
regl->suspend = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->suspend);
- if (regl->info->sleep.reg)
+ if (IS_ERR(regl->suspend))
+ return PTR_ERR(regl->suspend);
+ }
+
+ if (regl->info->sleep.reg) {
regl->sleep = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->sleep);
- if (regl->info->suspend_sleep.reg)
+ if (IS_ERR(regl->sleep))
+ return PTR_ERR(regl->sleep);
+ }
+
+ if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->suspend_sleep);
- if (regl->info->ilimit.reg)
+ if (IS_ERR(regl->suspend_sleep))
+ return PTR_ERR(regl->suspend_sleep);
+ }
+
+ if (regl->info->ilimit.reg) {
regl->ilimit = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->ilimit);
+ if (IS_ERR(regl->ilimit))
+ return PTR_ERR(regl->ilimit);
+ }
/* Register regulator */
memset(&config, 0, sizeof(config));
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 8cbcd2a3eb20..2b0c7a85306a 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -167,7 +167,7 @@ static int da9063_set_current_limit(struct regulator_dev *rdev,
const struct da9063_regulator_info *rinfo = regl->info;
int n, tval;
- for (n = 0; n < rinfo->n_current_limits; n++) {
+ for (n = rinfo->n_current_limits - 1; n >= 0; n--) {
tval = rinfo->current_limits[n];
if (tval >= min_uA && tval <= max_uA)
return regmap_field_write(regl->ilimit, n);
@@ -739,7 +739,6 @@ static int da9063_regulator_probe(struct platform_device *pdev)
struct regulator_config config;
bool bcores_merged, bmem_bio_merged;
int id, irq, n, n_regulators, ret, val;
- size_t size;
regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL;
@@ -784,9 +783,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
n_regulators--; /* remove BMEM_BIO_MERGED */
/* Allocate memory required by usable regulators */
- size = sizeof(struct da9063_regulators) +
- n_regulators * sizeof(struct da9063_regulator);
- regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ regulators = devm_kzalloc(&pdev->dev, struct_size(regulators,
+ regulator, n_regulators), GFP_KERNEL);
if (!regulators)
return -ENOMEM;
@@ -835,21 +833,40 @@ static int da9063_regulator_probe(struct platform_device *pdev)
regl->desc.type = REGULATOR_VOLTAGE;
regl->desc.owner = THIS_MODULE;
- if (regl->info->mode.reg)
+ if (regl->info->mode.reg) {
regl->mode = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->mode);
- if (regl->info->suspend.reg)
+ if (IS_ERR(regl->mode))
+ return PTR_ERR(regl->mode);
+ }
+
+ if (regl->info->suspend.reg) {
regl->suspend = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->suspend);
- if (regl->info->sleep.reg)
+ if (IS_ERR(regl->suspend))
+ return PTR_ERR(regl->suspend);
+ }
+
+ if (regl->info->sleep.reg) {
regl->sleep = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->sleep);
- if (regl->info->suspend_sleep.reg)
+ if (IS_ERR(regl->sleep))
+ return PTR_ERR(regl->sleep);
+ }
+
+ if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->suspend_sleep);
- if (regl->info->ilimit.reg)
+ if (IS_ERR(regl->suspend_sleep))
+ return PTR_ERR(regl->suspend_sleep);
+ }
+
+ if (regl->info->ilimit.reg) {
regl->ilimit = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->ilimit);
+ if (IS_ERR(regl->ilimit))
+ return PTR_ERR(regl->ilimit);
+ }
/* Register regulator */
memset(&config, 0, sizeof(config));
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 84dba64ed11e..528303771723 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -41,10 +41,6 @@ static const struct regmap_config da9210_regmap_config = {
.val_bits = 8,
};
-static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA);
-static int da9210_get_current_limit(struct regulator_dev *rdev);
-
static const struct regulator_ops da9210_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -52,8 +48,8 @@ static const struct regulator_ops da9210_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = da9210_set_current_limit,
- .get_current_limit = da9210_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
/* Default limits measured in millivolts and milliamps */
@@ -62,7 +58,7 @@ static const struct regulator_ops da9210_buck_ops = {
#define DA9210_STEP_MV 10
/* Current limits for buck (uA) indices corresponds with register values */
-static const int da9210_buck_limits[] = {
+static const unsigned int da9210_buck_limits[] = {
1600000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000,
3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000
};
@@ -80,47 +76,12 @@ static const struct regulator_desc da9210_reg = {
.enable_reg = DA9210_REG_BUCK_CONT,
.enable_mask = DA9210_BUCK_EN,
.owner = THIS_MODULE,
+ .curr_table = da9210_buck_limits,
+ .n_current_limits = ARRAY_SIZE(da9210_buck_limits),
+ .csel_reg = DA9210_REG_BUCK_ILIM,
+ .csel_mask = DA9210_BUCK_ILIM_MASK,
};
-static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA)
-{
- struct da9210 *chip = rdev_get_drvdata(rdev);
- unsigned int sel;
- int i;
-
- /* search for closest to maximum */
- for (i = ARRAY_SIZE(da9210_buck_limits)-1; i >= 0; i--) {
- if (min_uA <= da9210_buck_limits[i] &&
- max_uA >= da9210_buck_limits[i]) {
- sel = i;
- sel = sel << DA9210_BUCK_ILIM_SHIFT;
- return regmap_update_bits(chip->regmap,
- DA9210_REG_BUCK_ILIM,
- DA9210_BUCK_ILIM_MASK, sel);
- }
- }
-
- return -EINVAL;
-}
-
-static int da9210_get_current_limit(struct regulator_dev *rdev)
-{
- struct da9210 *chip = rdev_get_drvdata(rdev);
- unsigned int data;
- unsigned int sel;
- int ret;
-
- ret = regmap_read(chip->regmap, DA9210_REG_BUCK_ILIM, &data);
- if (ret < 0)
- return ret;
-
- /* select one of 16 values: 0000 (1600mA) to 1111 (4600mA) */
- sel = (data & DA9210_BUCK_ILIM_MASK) >> DA9210_BUCK_ILIM_SHIFT;
-
- return da9210_buck_limits[sel];
-}
-
static irqreturn_t da9210_irq_handler(int irq, void *data)
{
struct da9210 *chip = data;
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index a3bc8037153e..771a06d1900d 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -40,7 +40,6 @@
/* VSEL bit definitions */
#define VSEL_BUCK_EN (1 << 7)
#define VSEL_MODE (1 << 6)
-#define VSEL_NSEL_MASK 0x3F
/* Chip ID and Verison */
#define DIE_ID 0x0F /* ID1 */
#define DIE_REV 0x0F /* ID2 */
@@ -49,14 +48,26 @@
#define CTL_SLEW_MASK (0x7 << 4)
#define CTL_SLEW_SHIFT 4
#define CTL_RESET (1 << 2)
+#define CTL_MODE_VSEL0_MODE BIT(0)
+#define CTL_MODE_VSEL1_MODE BIT(1)
#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */
+#define FAN53526_NVOLTAGES 128
enum fan53555_vendor {
- FAN53555_VENDOR_FAIRCHILD = 0,
+ FAN53526_VENDOR_FAIRCHILD = 0,
+ FAN53555_VENDOR_FAIRCHILD,
FAN53555_VENDOR_SILERGY,
};
+enum {
+ FAN53526_CHIP_ID_01 = 1,
+};
+
+enum {
+ FAN53526_CHIP_REV_08 = 8,
+};
+
/* IC Type */
enum {
FAN53555_CHIP_ID_00 = 0,
@@ -94,8 +105,12 @@ struct fan53555_device_info {
/* Voltage range and step(linear) */
unsigned int vsel_min;
unsigned int vsel_step;
+ unsigned int vsel_count;
/* Voltage slew rate limiting */
unsigned int slew_rate;
+ /* Mode */
+ unsigned int mode_reg;
+ unsigned int mode_mask;
/* Sleep voltage cache */
unsigned int sleep_vol_cache;
};
@@ -111,7 +126,7 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
if (ret < 0)
return ret;
ret = regmap_update_bits(di->regmap, di->sleep_reg,
- VSEL_NSEL_MASK, ret);
+ di->desc.vsel_mask, ret);
if (ret < 0)
return ret;
/* Cache the sleep voltage setting.
@@ -143,11 +158,11 @@ static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
switch (mode) {
case REGULATOR_MODE_FAST:
- regmap_update_bits(di->regmap, di->vol_reg,
- VSEL_MODE, VSEL_MODE);
+ regmap_update_bits(di->regmap, di->mode_reg,
+ di->mode_mask, di->mode_mask);
break;
case REGULATOR_MODE_NORMAL:
- regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
+ regmap_update_bits(di->regmap, di->vol_reg, di->mode_mask, 0);
break;
default:
return -EINVAL;
@@ -161,10 +176,10 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
unsigned int val;
int ret = 0;
- ret = regmap_read(di->regmap, di->vol_reg, &val);
+ ret = regmap_read(di->regmap, di->mode_reg, &val);
if (ret < 0)
return ret;
- if (val & VSEL_MODE)
+ if (val & di->mode_mask)
return REGULATOR_MODE_FAST;
else
return REGULATOR_MODE_NORMAL;
@@ -219,6 +234,34 @@ static const struct regulator_ops fan53555_regulator_ops = {
.set_suspend_disable = fan53555_set_suspend_disable,
};
+static int fan53526_voltages_setup_fairchild(struct fan53555_device_info *di)
+{
+ /* Init voltage range and step */
+ switch (di->chip_id) {
+ case FAN53526_CHIP_ID_01:
+ switch (di->chip_rev) {
+ case FAN53526_CHIP_REV_08:
+ di->vsel_min = 600000;
+ di->vsel_step = 6250;
+ break;
+ default:
+ dev_err(di->dev,
+ "Chip ID %d with rev %d not supported!\n",
+ di->chip_id, di->chip_rev);
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(di->dev,
+ "Chip ID %d not supported!\n", di->chip_id);
+ return -EINVAL;
+ }
+
+ di->vsel_count = FAN53526_NVOLTAGES;
+
+ return 0;
+}
+
static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
{
/* Init voltage range and step */
@@ -257,6 +300,8 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
return -EINVAL;
}
+ di->vsel_count = FAN53555_NVOLTAGES;
+
return 0;
}
@@ -274,6 +319,8 @@ static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
return -EINVAL;
}
+ di->vsel_count = FAN53555_NVOLTAGES;
+
return 0;
}
@@ -302,7 +349,35 @@ static int fan53555_device_setup(struct fan53555_device_info *di,
return -EINVAL;
}
+ /* Setup mode control register */
+ switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ di->mode_reg = FAN53555_CONTROL;
+
+ switch (pdata->sleep_vsel_id) {
+ case FAN53555_VSEL_ID_0:
+ di->mode_mask = CTL_MODE_VSEL1_MODE;
+ break;
+ case FAN53555_VSEL_ID_1:
+ di->mode_mask = CTL_MODE_VSEL0_MODE;
+ break;
+ }
+ break;
+ case FAN53555_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_SILERGY:
+ di->mode_reg = di->vol_reg;
+ di->mode_mask = VSEL_MODE;
+ break;
+ default:
+ dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
+ return -EINVAL;
+ }
+
+ /* Setup voltage range */
switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ ret = fan53526_voltages_setup_fairchild(di);
+ break;
case FAN53555_VENDOR_FAIRCHILD:
ret = fan53555_voltages_setup_fairchild(di);
break;
@@ -326,13 +401,13 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
rdesc->supply_name = "vin";
rdesc->ops = &fan53555_regulator_ops;
rdesc->type = REGULATOR_VOLTAGE;
- rdesc->n_voltages = FAN53555_NVOLTAGES;
+ rdesc->n_voltages = di->vsel_count;
rdesc->enable_reg = di->vol_reg;
rdesc->enable_mask = VSEL_BUCK_EN;
rdesc->min_uV = di->vsel_min;
rdesc->uV_step = di->vsel_step;
rdesc->vsel_reg = di->vol_reg;
- rdesc->vsel_mask = VSEL_NSEL_MASK;
+ rdesc->vsel_mask = di->vsel_count - 1;
rdesc->owner = THIS_MODULE;
di->rdev = devm_regulator_register(di->dev, &di->desc, config);
@@ -368,6 +443,9 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
static const struct of_device_id fan53555_dt_ids[] = {
{
+ .compatible = "fcs,fan53526",
+ .data = (void *)FAN53526_VENDOR_FAIRCHILD,
+ }, {
.compatible = "fcs,fan53555",
.data = (void *)FAN53555_VENDOR_FAIRCHILD
}, {
@@ -412,11 +490,13 @@ static int fan53555_regulator_probe(struct i2c_client *client,
} else {
/* if no ramp constraint set, get the pdata ramp_delay */
if (!di->regulator->constraints.ramp_delay) {
- int slew_idx = (pdata->slew_rate & 0x7)
- ? pdata->slew_rate : 0;
+ if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) {
+ dev_err(&client->dev, "Invalid slew_rate\n");
+ return -EINVAL;
+ }
di->regulator->constraints.ramp_delay
- = slew_rates[slew_idx];
+ = slew_rates[pdata->slew_rate];
}
di->vendor = id->driver_data;
@@ -467,6 +547,9 @@ static int fan53555_regulator_probe(struct i2c_client *client,
static const struct i2c_device_id fan53555_id[] = {
{
+ .name = "fan53526",
+ .driver_data = FAN53526_VENDOR_FAIRCHILD
+ }, {
.name = "fan53555",
.driver_data = FAN53555_VENDOR_FAIRCHILD
}, {
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 9abdb9130766..b5afc9db2c61 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -79,15 +79,6 @@ of_get_fixed_voltage_config(struct device *dev,
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
- /*
- * FIXME: we pulled active low/high and open drain handling into
- * gpiolib so it will be handled there. Delete this in the second
- * step when we also remove the custom inversion handling for all
- * legacy boardfiles.
- */
- config->enable_high = 1;
- config->gpio_is_open_drain = 0;
-
if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin";
@@ -151,24 +142,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.fixed_uV = config->microvolts;
- cfg.ena_gpio_invert = !config->enable_high;
- if (config->enabled_at_boot) {
- if (config->enable_high)
- gflags = GPIOD_OUT_HIGH;
- else
- gflags = GPIOD_OUT_LOW;
- } else {
- if (config->enable_high)
- gflags = GPIOD_OUT_LOW;
- else
- gflags = GPIOD_OUT_HIGH;
- }
- if (config->gpio_is_open_drain) {
- if (gflags == GPIOD_OUT_HIGH)
- gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
- else
- gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
- }
+ /*
+ * The signal will be inverted by the GPIO core if flagged so in the
+ * decriptor.
+ */
+ if (config->enabled_at_boot)
+ gflags = GPIOD_OUT_HIGH;
+ else
+ gflags = GPIOD_OUT_LOW;
/*
* Some fixed regulators share the enable line between two
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index b2f5ec4f658a..6157001df0a4 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -30,16 +30,15 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/gpio-regulator.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
struct gpio_regulator_data {
struct regulator_desc desc;
struct regulator_dev *dev;
- struct gpio *gpios;
+ struct gpio_desc **gpiods;
int nr_gpios;
struct gpio_regulator_state *states;
@@ -82,7 +81,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
+ gpiod_set_value_cansleep(data->gpiods[ptr], state);
}
data->state = target;
@@ -119,7 +118,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
+ gpiod_set_value_cansleep(data->gpiods[ptr], state);
}
data->state = target;
@@ -138,7 +137,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
{
struct gpio_regulator_config *config;
const char *regtype;
- int proplen, gpio, i;
+ int proplen, i;
+ int ngpios;
int ret;
config = devm_kzalloc(dev,
@@ -153,59 +153,36 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
config->supply_name = config->init_data->constraints.name;
- if (of_property_read_bool(np, "enable-active-high"))
- config->enable_high = true;
-
if (of_property_read_bool(np, "enable-at-boot"))
config->enabled_at_boot = true;
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
- config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
- if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT)
- return ERR_PTR(config->enable_gpio);
-
- /* Fetch GPIOs. - optional property*/
- ret = of_gpio_count(np);
- if ((ret < 0) && (ret != -ENOENT))
- return ERR_PTR(ret);
-
- if (ret > 0) {
- config->nr_gpios = ret;
- config->gpios = devm_kcalloc(dev,
- config->nr_gpios, sizeof(struct gpio),
- GFP_KERNEL);
- if (!config->gpios)
+ /* Fetch GPIO init levels */
+ ngpios = gpiod_count(dev, NULL);
+ if (ngpios > 0) {
+ config->gflags = devm_kzalloc(dev,
+ sizeof(enum gpiod_flags)
+ * ngpios,
+ GFP_KERNEL);
+ if (!config->gflags)
return ERR_PTR(-ENOMEM);
- proplen = of_property_count_u32_elems(np, "gpios-states");
- /* optional property */
- if (proplen < 0)
- proplen = 0;
+ for (i = 0; i < ngpios; i++) {
+ u32 val;
- if (proplen > 0 && proplen != config->nr_gpios) {
- dev_warn(dev, "gpios <-> gpios-states mismatch\n");
- proplen = 0;
- }
+ ret = of_property_read_u32_index(np, "gpios-states", i,
+ &val);
- for (i = 0; i < config->nr_gpios; i++) {
- gpio = of_get_named_gpio(np, "gpios", i);
- if (gpio < 0) {
- if (gpio != -ENOENT)
- return ERR_PTR(gpio);
- break;
- }
- config->gpios[i].gpio = gpio;
- config->gpios[i].label = config->supply_name;
- if (proplen > 0) {
- of_property_read_u32_index(np, "gpios-states",
- i, &ret);
- if (ret)
- config->gpios[i].flags =
- GPIOF_OUT_INIT_HIGH;
- }
+ /* Default to high per specification */
+ if (ret)
+ config->gflags[i] = GPIOD_OUT_HIGH;
+ else
+ config->gflags[i] =
+ val ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
}
}
+ config->ngpios = ngpios;
/* Fetch states. */
proplen = of_property_count_u32_elems(np, "states");
@@ -251,59 +228,56 @@ static struct regulator_ops gpio_regulator_current_ops = {
static int gpio_regulator_probe(struct platform_device *pdev)
{
- struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev);
- struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct gpio_regulator_config *config = dev_get_platdata(dev);
+ struct device_node *np = dev->of_node;
struct gpio_regulator_data *drvdata;
struct regulator_config cfg = { };
- int ptr, ret, state;
+ enum gpiod_flags gflags;
+ int ptr, ret, state, i;
- drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
+ drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL);
if (drvdata == NULL)
return -ENOMEM;
if (np) {
- config = of_get_gpio_regulator_config(&pdev->dev, np,
+ config = of_get_gpio_regulator_config(dev, np,
&drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
}
- drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+ drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL);
if (drvdata->desc.name == NULL) {
- dev_err(&pdev->dev, "Failed to allocate supply name\n");
+ dev_err(dev, "Failed to allocate supply name\n");
return -ENOMEM;
}
- if (config->nr_gpios != 0) {
- drvdata->gpios = kmemdup(config->gpios,
- config->nr_gpios * sizeof(struct gpio),
- GFP_KERNEL);
- if (drvdata->gpios == NULL) {
- dev_err(&pdev->dev, "Failed to allocate gpio data\n");
- ret = -ENOMEM;
- goto err_name;
- }
-
- drvdata->nr_gpios = config->nr_gpios;
- ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "Could not obtain regulator setting GPIOs: %d\n",
- ret);
- goto err_memgpio;
- }
+ drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *),
+ GFP_KERNEL);
+ if (!drvdata->gpiods)
+ return -ENOMEM;
+ for (i = 0; i < config->ngpios; i++) {
+ drvdata->gpiods[i] = devm_gpiod_get_index(dev,
+ NULL,
+ i,
+ config->gflags[i]);
+ if (IS_ERR(drvdata->gpiods[i]))
+ return PTR_ERR(drvdata->gpiods[i]);
+ /* This is good to know */
+ gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name);
}
+ drvdata->nr_gpios = config->ngpios;
- drvdata->states = kmemdup(config->states,
- config->nr_states *
- sizeof(struct gpio_regulator_state),
- GFP_KERNEL);
+ drvdata->states = devm_kmemdup(dev,
+ config->states,
+ config->nr_states *
+ sizeof(struct gpio_regulator_state),
+ GFP_KERNEL);
if (drvdata->states == NULL) {
- dev_err(&pdev->dev, "Failed to allocate state data\n");
- ret = -ENOMEM;
- goto err_stategpio;
+ dev_err(dev, "Failed to allocate state data\n");
+ return -ENOMEM;
}
drvdata->nr_states = config->nr_states;
@@ -322,61 +296,46 @@ static int gpio_regulator_probe(struct platform_device *pdev)
drvdata->desc.ops = &gpio_regulator_current_ops;
break;
default:
- dev_err(&pdev->dev, "No regulator type set\n");
- ret = -EINVAL;
- goto err_memstate;
+ dev_err(dev, "No regulator type set\n");
+ return -EINVAL;
}
/* build initial state from gpio init data. */
state = 0;
for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
- if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH)
+ if (config->gflags[ptr] == GPIOD_OUT_HIGH)
state |= (1 << ptr);
}
drvdata->state = state;
- cfg.dev = &pdev->dev;
+ cfg.dev = dev;
cfg.init_data = config->init_data;
cfg.driver_data = drvdata;
cfg.of_node = np;
- if (gpio_is_valid(config->enable_gpio)) {
- cfg.ena_gpio = config->enable_gpio;
- cfg.ena_gpio_initialized = true;
- }
- cfg.ena_gpio_invert = !config->enable_high;
- if (config->enabled_at_boot) {
- if (config->enable_high)
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
- else
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
- } else {
- if (config->enable_high)
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
- else
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
- }
+ /*
+ * The signal will be inverted by the GPIO core if flagged so in the
+ * decriptor.
+ */
+ if (config->enabled_at_boot)
+ gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
+ else
+ gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
+
+ cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags);
+ if (IS_ERR(cfg.ena_gpiod))
+ return PTR_ERR(cfg.ena_gpiod);
drvdata->dev = regulator_register(&drvdata->desc, &cfg);
if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev);
- dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
- goto err_memstate;
+ dev_err(dev, "Failed to register regulator: %d\n", ret);
+ return ret;
}
platform_set_drvdata(pdev, drvdata);
return 0;
-
-err_memstate:
- kfree(drvdata->states);
-err_stategpio:
- gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-err_memgpio:
- kfree(drvdata->gpios);
-err_name:
- kfree(drvdata->desc.name);
- return ret;
}
static int gpio_regulator_remove(struct platform_device *pdev)
@@ -385,13 +344,6 @@ static int gpio_regulator_remove(struct platform_device *pdev)
regulator_unregister(drvdata->dev);
- gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-
- kfree(drvdata->states);
- kfree(drvdata->gpios);
-
- kfree(drvdata->desc.name);
-
return 0;
}
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 5686a1335bd3..32d3f0499e2d 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -594,28 +594,30 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
/**
- * regulator_list_voltage_linear_range - List voltages for linear ranges
+ * regulator_desc_list_voltage_linear_range - List voltages for linear ranges
*
- * @rdev: Regulator device
+ * @desc: Regulator desc for regulator which volatges are to be listed
* @selector: Selector to convert into a voltage
*
* Regulators with a series of simple linear mappings between voltages
- * and selectors can set linear_ranges in the regulator descriptor and
- * then use this function as their list_voltage() operation,
+ * and selectors who have set linear_ranges in the regulator descriptor
+ * can use this function prior regulator registration to list voltages.
+ * This is useful when voltages need to be listed during device-tree
+ * parsing.
*/
-int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
- unsigned int selector)
+int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
+ unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
- if (!rdev->desc->n_linear_ranges) {
- BUG_ON(!rdev->desc->n_linear_ranges);
+ if (!desc->n_linear_ranges) {
+ BUG_ON(!desc->n_linear_ranges);
return -EINVAL;
}
- for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
- range = &rdev->desc->linear_ranges[i];
+ for (i = 0; i < desc->n_linear_ranges; i++) {
+ range = &desc->linear_ranges[i];
if (!(selector >= range->min_sel &&
selector <= range->max_sel))
@@ -628,6 +630,23 @@ int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
+
+/**
+ * regulator_list_voltage_linear_range - List voltages for linear ranges
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a series of simple linear mappings between voltages
+ * and selectors can set linear_ranges in the regulator descriptor and
+ * then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ return regulator_desc_list_voltage_linear_range(rdev->desc, selector);
+}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
/**
@@ -761,3 +780,89 @@ int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
rdev->desc->active_discharge_mask, val);
}
EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);
+
+/**
+ * regulator_set_current_limit_regmap - set_current_limit for regmap users
+ *
+ * @rdev: regulator to operate on
+ * @min_uA: Lower bound for current limit
+ * @max_uA: Upper bound for current limit
+ *
+ * Regulators that use regmap for their register I/O can set curr_table,
+ * csel_reg and csel_mask fields in their descriptor and then use this
+ * as their set_current_limit operation, saving some code.
+ */
+int regulator_set_current_limit_regmap(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ unsigned int n_currents = rdev->desc->n_current_limits;
+ int i, sel = -1;
+
+ if (n_currents == 0)
+ return -EINVAL;
+
+ if (rdev->desc->curr_table) {
+ const unsigned int *curr_table = rdev->desc->curr_table;
+ bool ascend = curr_table[n_currents - 1] > curr_table[0];
+
+ /* search for closest to maximum */
+ if (ascend) {
+ for (i = n_currents - 1; i >= 0; i--) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < n_currents; i++) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (sel < 0)
+ return -EINVAL;
+
+ sel <<= ffs(rdev->desc->csel_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg,
+ rdev->desc->csel_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_current_limit_regmap);
+
+/**
+ * regulator_get_current_limit_regmap - get_current_limit for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * csel_reg and csel_mask fields in their descriptor and then use this
+ * as their get_current_limit operation, saving some code.
+ */
+int regulator_get_current_limit_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->csel_mask;
+ val >>= ffs(rdev->desc->csel_mask) - 1;
+
+ if (rdev->desc->curr_table) {
+ if (val >= rdev->desc->n_current_limits)
+ return -EINVAL;
+
+ return rdev->desc->curr_table[val];
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap);
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
index 36ae54b53814..bba24a6fdb1e 100644
--- a/drivers/regulator/hi655x-regulator.c
+++ b/drivers/regulator/hi655x-regulator.c
@@ -28,7 +28,6 @@
struct hi655x_regulator {
unsigned int disable_reg;
unsigned int status_reg;
- unsigned int ctrl_regs;
unsigned int ctrl_mask;
struct regulator_desc rdesc;
};
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 4abd8e9c81e5..6f28bba81d13 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -31,7 +31,6 @@
/* PMIC details */
struct isl_pmic {
struct i2c_client *client;
- struct regulator_dev *rdev[3];
struct mutex mtx;
};
@@ -66,14 +65,14 @@ static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
return err;
}
-static struct regulator_ops isl_core_ops = {
+static const struct regulator_ops isl_core_ops = {
.get_voltage_sel = isl6271a_get_voltage_sel,
.set_voltage_sel = isl6271a_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
};
-static struct regulator_ops isl_fixed_ops = {
+static const struct regulator_ops isl_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
};
@@ -109,6 +108,7 @@ static const struct regulator_desc isl_rd[] = {
static int isl6271a_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct regulator_dev *rdev;
struct regulator_config config = { };
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct isl_pmic *pmic;
@@ -133,11 +133,10 @@ static int isl6271a_probe(struct i2c_client *i2c,
config.init_data = NULL;
config.driver_data = pmic;
- pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
- &config);
- if (IS_ERR(pmic->rdev[i])) {
+ rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config);
+ if (IS_ERR(rdev)) {
dev_err(&i2c->dev, "failed to register %s\n", id->name);
- return PTR_ERR(pmic->rdev[i]);
+ return PTR_ERR(rdev);
}
}
diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c
index 8c0e8419c43f..c876e161052a 100644
--- a/drivers/regulator/lm363x-regulator.c
+++ b/drivers/regulator/lm363x-regulator.c
@@ -258,6 +258,9 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
* Register update is required if the pin is used.
*/
gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
if (gpiod) {
cfg.ena_gpiod = gpiod;
@@ -265,8 +268,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
LM3632_EXT_EN_MASK,
LM3632_EXT_EN_MASK);
if (ret) {
- if (gpiod)
- gpiod_put(gpiod);
+ gpiod_put(gpiod);
dev_err(dev, "External pin err: %d\n", ret);
return ret;
}
diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c
index 5a89e6d4b9a6..ff97cc50f2eb 100644
--- a/drivers/regulator/lochnagar-regulator.c
+++ b/drivers/regulator/lochnagar-regulator.c
@@ -194,7 +194,7 @@ static const struct regulator_desc lochnagar_regulators[] = {
.name = "VDDCORE",
.supply_name = "SYSVDD",
.type = REGULATOR_VOLTAGE,
- .n_voltages = 57,
+ .n_voltages = 66,
.ops = &lochnagar_vddcore_ops,
.id = LOCHNAGAR_VDDCORE,
@@ -226,14 +226,15 @@ static const struct of_device_id lochnagar_of_match[] = {
},
{
.compatible = "cirrus,lochnagar2-mic2vdd",
- .data = &lochnagar_regulators[LOCHNAGAR_MIC1VDD],
+ .data = &lochnagar_regulators[LOCHNAGAR_MIC2VDD],
},
{
.compatible = "cirrus,lochnagar2-vddcore",
.data = &lochnagar_regulators[LOCHNAGAR_VDDCORE],
},
- {},
+ {}
};
+MODULE_DEVICE_TABLE(of, lochnagar_of_match);
static int lochnagar_regulator_probe(struct platform_device *pdev)
{
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 204b5c5270e0..9e45112658ba 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -159,7 +159,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
selector << LDO_VOL_CONTR_SHIFT(ldo));
}
-static struct regulator_ops lp3971_ldo_ops = {
+static const struct regulator_ops lp3971_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_ldo_is_enabled,
@@ -233,7 +233,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
0 << BUCK_VOL_CHANGE_SHIFT(buck));
}
-static struct regulator_ops lp3971_dcdc_ops = {
+static const struct regulator_ops lp3971_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_dcdc_is_enabled,
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index ff0c275f902e..fb098198b688 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -305,7 +305,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
return ret;
}
-static struct regulator_ops lp3972_ldo_ops = {
+static const struct regulator_ops lp3972_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_ldo_is_enabled,
@@ -386,7 +386,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
LP3972_VOL_CHANGE_FLAG_MASK, 0);
}
-static struct regulator_ops lp3972_dcdc_ops = {
+static const struct regulator_ops lp3972_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_dcdc_is_enabled,
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 38992112fd6e..ca95257ce252 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -353,64 +353,6 @@ static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
return val & LP872X_VOUT_M;
}
-static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- struct lp872x *lp = rdev_get_drvdata(rdev);
- enum lp872x_regulator_id buck = rdev_get_id(rdev);
- int i;
- u8 addr;
-
- switch (buck) {
- case LP8725_ID_BUCK1:
- addr = LP8725_BUCK1_VOUT2;
- break;
- case LP8725_ID_BUCK2:
- addr = LP8725_BUCK2_VOUT2;
- break;
- default:
- return -EINVAL;
- }
-
- for (i = ARRAY_SIZE(lp8725_buck_uA) - 1; i >= 0; i--) {
- if (lp8725_buck_uA[i] >= min_uA &&
- lp8725_buck_uA[i] <= max_uA)
- return lp872x_update_bits(lp, addr,
- LP8725_BUCK_CL_M,
- i << LP8725_BUCK_CL_S);
- }
-
- return -EINVAL;
-}
-
-static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
-{
- struct lp872x *lp = rdev_get_drvdata(rdev);
- enum lp872x_regulator_id buck = rdev_get_id(rdev);
- u8 addr, val;
- int ret;
-
- switch (buck) {
- case LP8725_ID_BUCK1:
- addr = LP8725_BUCK1_VOUT2;
- break;
- case LP8725_ID_BUCK2:
- addr = LP8725_BUCK2_VOUT2;
- break;
- default:
- return -EINVAL;
- }
-
- ret = lp872x_read_byte(lp, addr, &val);
- if (ret)
- return ret;
-
- val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
-
- return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
- lp8725_buck_uA[val] : -EINVAL;
-}
-
static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct lp872x *lp = rdev_get_drvdata(rdev);
@@ -478,7 +420,7 @@ static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
-static struct regulator_ops lp872x_ldo_ops = {
+static const struct regulator_ops lp872x_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -489,7 +431,7 @@ static struct regulator_ops lp872x_ldo_ops = {
.enable_time = lp872x_regulator_enable_time,
};
-static struct regulator_ops lp8720_buck_ops = {
+static const struct regulator_ops lp8720_buck_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
@@ -502,7 +444,7 @@ static struct regulator_ops lp8720_buck_ops = {
.get_mode = lp872x_buck_get_mode,
};
-static struct regulator_ops lp8725_buck_ops = {
+static const struct regulator_ops lp8725_buck_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
@@ -513,11 +455,11 @@ static struct regulator_ops lp8725_buck_ops = {
.enable_time = lp872x_regulator_enable_time,
.set_mode = lp872x_buck_set_mode,
.get_mode = lp872x_buck_get_mode,
- .set_current_limit = lp8725_buck_set_current_limit,
- .get_current_limit = lp8725_buck_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
-static struct regulator_desc lp8720_regulator_desc[] = {
+static const struct regulator_desc lp8720_regulator_desc[] = {
{
.name = "ldo1",
.of_match = of_match_ptr("ldo1"),
@@ -602,7 +544,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
};
-static struct regulator_desc lp8725_regulator_desc[] = {
+static const struct regulator_desc lp8725_regulator_desc[] = {
{
.name = "ldo1",
.of_match = of_match_ptr("ldo1"),
@@ -712,6 +654,10 @@ static struct regulator_desc lp8725_regulator_desc[] = {
.owner = THIS_MODULE,
.enable_reg = LP872X_GENERAL_CFG,
.enable_mask = LP8725_BUCK1_EN_M,
+ .curr_table = lp8725_buck_uA,
+ .n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
+ .csel_reg = LP8725_BUCK1_VOUT2,
+ .csel_mask = LP8725_BUCK_CL_M,
},
{
.name = "buck2",
@@ -724,6 +670,10 @@ static struct regulator_desc lp8725_regulator_desc[] = {
.owner = THIS_MODULE,
.enable_reg = LP872X_GENERAL_CFG,
.enable_mask = LP8725_BUCK2_EN_M,
+ .curr_table = lp8725_buck_uA,
+ .n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
+ .csel_reg = LP8725_BUCK2_VOUT2,
+ .csel_mask = LP8725_BUCK_CL_M,
},
};
@@ -820,7 +770,7 @@ static struct regulator_init_data
static int lp872x_regulator_register(struct lp872x *lp)
{
- struct regulator_desc *desc;
+ const struct regulator_desc *desc;
struct regulator_config cfg = { };
struct regulator_dev *rdev;
int i;
diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c
index 70e3df653381..b55de293ca7a 100644
--- a/drivers/regulator/lp873x-regulator.c
+++ b/drivers/regulator/lp873x-regulator.c
@@ -39,6 +39,10 @@
.ramp_delay = _delay, \
.linear_ranges = _lr, \
.n_linear_ranges = ARRAY_SIZE(_lr), \
+ .curr_table = lp873x_buck_uA, \
+ .n_current_limits = ARRAY_SIZE(lp873x_buck_uA), \
+ .csel_reg = (_cr), \
+ .csel_mask = LP873X_BUCK0_CTRL_2_BUCK0_ILIM,\
}, \
.ctrl2_reg = _cr, \
}
@@ -61,7 +65,7 @@ static const struct regulator_linear_range ldo0_ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x19, 100000),
};
-static unsigned int lp873x_buck_ramp_delay[] = {
+static const unsigned int lp873x_buck_ramp_delay[] = {
30000, 15000, 10000, 7500, 3800, 1900, 940, 470
};
@@ -108,45 +112,8 @@ static int lp873x_buck_set_ramp_delay(struct regulator_dev *rdev,
return 0;
}
-static int lp873x_buck_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- int id = rdev_get_id(rdev);
- struct lp873x *lp873 = rdev_get_drvdata(rdev);
- int i;
-
- for (i = ARRAY_SIZE(lp873x_buck_uA) - 1; i >= 0; i--) {
- if (lp873x_buck_uA[i] >= min_uA &&
- lp873x_buck_uA[i] <= max_uA)
- return regmap_update_bits(lp873->regmap,
- regulators[id].ctrl2_reg,
- LP873X_BUCK0_CTRL_2_BUCK0_ILIM,
- i << __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM));
- }
-
- return -EINVAL;
-}
-
-static int lp873x_buck_get_current_limit(struct regulator_dev *rdev)
-{
- int id = rdev_get_id(rdev);
- struct lp873x *lp873 = rdev_get_drvdata(rdev);
- int ret;
- unsigned int val;
-
- ret = regmap_read(lp873->regmap, regulators[id].ctrl2_reg, &val);
- if (ret)
- return ret;
-
- val = (val & LP873X_BUCK0_CTRL_2_BUCK0_ILIM) >>
- __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM);
-
- return (val < ARRAY_SIZE(lp873x_buck_uA)) ?
- lp873x_buck_uA[val] : -EINVAL;
-}
-
/* Operations permitted on BUCK0, BUCK1 */
-static struct regulator_ops lp873x_buck01_ops = {
+static const struct regulator_ops lp873x_buck01_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -156,12 +123,12 @@ static struct regulator_ops lp873x_buck01_ops = {
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = lp873x_buck_set_ramp_delay,
- .set_current_limit = lp873x_buck_set_current_limit,
- .get_current_limit = lp873x_buck_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
/* Operations permitted on LDO0 and LDO1 */
-static struct regulator_ops lp873x_ldo01_ops = {
+static const struct regulator_ops lp873x_ldo01_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 244822bb63cd..14fd38807134 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -315,7 +315,7 @@ out_i2c_error:
.vsel_mask = LP8755_BUCK_VOUT_M,\
}
-static struct regulator_desc lp8755_regulators[] = {
+static const struct regulator_desc lp8755_regulators[] = {
lp8755_buck_desc(0),
lp8755_buck_desc(1),
lp8755_buck_desc(2),
@@ -386,7 +386,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data)
if (ret < 0)
goto err_i2c;
- /* send OCP event to all regualtor devices */
+ /* send OCP event to all regulator devices */
if ((flag1 & 0x01) && (pchip->irqmask & 0x01))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL)
@@ -394,7 +394,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data)
LP8755_EVENT_OCP,
NULL);
- /* send OVP event to all regualtor devices */
+ /* send OVP event to all regulator devices */
if ((flag1 & 0x02) && (pchip->irqmask & 0x02))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL)
diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c
index c192357d1dea..4ed41731a5b1 100644
--- a/drivers/regulator/lp87565-regulator.c
+++ b/drivers/regulator/lp87565-regulator.c
@@ -51,7 +51,7 @@ static const struct regulator_linear_range buck0_1_2_3_ranges[] = {
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
};
-static unsigned int lp87565_buck_ramp_delay[] = {
+static const unsigned int lp87565_buck_ramp_delay[] = {
30000, 15000, 10000, 7500, 3800, 1900, 940, 470
};
@@ -140,7 +140,7 @@ static int lp87565_buck_get_current_limit(struct regulator_dev *rdev)
}
/* Operations permitted on BUCK0, BUCK1 */
-static struct regulator_ops lp87565_buck_ops = {
+static const struct regulator_ops lp87565_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index ec46290b647e..a7d30550bb5f 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -95,12 +95,10 @@ struct lp8788_buck {
void *dvs;
};
-/* BUCK 1 ~ 4 voltage table */
-static const int lp8788_buck_vtbl[] = {
- 500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
- 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
- 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
- 1950000, 2000000,
+/* BUCK 1 ~ 4 voltage ranges */
+static const struct regulator_linear_range buck_volt_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0, 0),
+ REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000),
};
static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
@@ -345,8 +343,8 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
}
static const struct regulator_ops lp8788_buck12_ops = {
- .list_voltage = regulator_list_voltage_table,
- .map_voltage = regulator_map_voltage_ascend,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
.get_voltage_sel = lp8788_buck12_get_voltage_sel,
.enable = regulator_enable_regmap,
@@ -358,8 +356,8 @@ static const struct regulator_ops lp8788_buck12_ops = {
};
static const struct regulator_ops lp8788_buck34_ops = {
- .list_voltage = regulator_list_voltage_table,
- .map_voltage = regulator_map_voltage_ascend,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
@@ -370,13 +368,14 @@ static const struct regulator_ops lp8788_buck34_ops = {
.get_mode = lp8788_buck_get_mode,
};
-static struct regulator_desc lp8788_buck_desc[] = {
+static const struct regulator_desc lp8788_buck_desc[] = {
{
.name = "buck1",
.id = BUCK1,
.ops = &lp8788_buck12_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_BUCK,
@@ -386,8 +385,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck2",
.id = BUCK2,
.ops = &lp8788_buck12_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_BUCK,
@@ -397,8 +397,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck3",
.id = BUCK3,
.ops = &lp8788_buck34_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LP8788_BUCK3_VOUT,
@@ -410,8 +411,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck4",
.id = BUCK4,
.ops = &lp8788_buck34_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LP8788_BUCK4_VOUT,
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 2ee22e7ea675..a2ef146e6b3a 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -186,7 +186,7 @@ static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
.enable_time = lp8788_ldo_enable_time,
};
-static struct regulator_desc lp8788_dldo_desc[] = {
+static const struct regulator_desc lp8788_dldo_desc[] = {
{
.name = "dldo1",
.id = DLDO1,
@@ -343,7 +343,7 @@ static struct regulator_desc lp8788_dldo_desc[] = {
},
};
-static struct regulator_desc lp8788_aldo_desc[] = {
+static const struct regulator_desc lp8788_aldo_desc[] = {
{
.name = "aldo1",
.id = ALDO1,
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index 71fd0f2a4b76..e6d66e492b85 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -241,61 +241,10 @@ static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = {
LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2),
};
-static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg)
+static bool ltc3676_readable_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_BUCK1:
- case LTC3676_BUCK2:
- case LTC3676_BUCK3:
- case LTC3676_BUCK4:
- case LTC3676_LDOA:
- case LTC3676_LDOB:
- case LTC3676_SQD1:
- case LTC3676_SQD2:
- case LTC3676_CNTRL:
- case LTC3676_DVB1A:
- case LTC3676_DVB1B:
- case LTC3676_DVB2A:
- case LTC3676_DVB2B:
- case LTC3676_DVB3A:
- case LTC3676_DVB3B:
- case LTC3676_DVB4A:
- case LTC3676_DVB4B:
- case LTC3676_MSKIRQ:
- case LTC3676_MSKPG:
- case LTC3676_USER:
- case LTC3676_HRST:
- case LTC3676_CLIRQ:
- return true;
- }
- return false;
-}
-
-static bool ltc3676_readable_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_BUCK1:
- case LTC3676_BUCK2:
- case LTC3676_BUCK3:
- case LTC3676_BUCK4:
- case LTC3676_LDOA:
- case LTC3676_LDOB:
- case LTC3676_SQD1:
- case LTC3676_SQD2:
- case LTC3676_CNTRL:
- case LTC3676_DVB1A:
- case LTC3676_DVB1B:
- case LTC3676_DVB2A:
- case LTC3676_DVB2B:
- case LTC3676_DVB3A:
- case LTC3676_DVB3B:
- case LTC3676_DVB4A:
- case LTC3676_DVB4B:
- case LTC3676_MSKIRQ:
- case LTC3676_MSKPG:
- case LTC3676_USER:
+ case LTC3676_BUCK1 ... LTC3676_IRQSTAT:
case LTC3676_HRST:
case LTC3676_CLIRQ:
return true;
@@ -306,9 +255,7 @@ static bool ltc3676_readable_reg(struct device *dev, unsigned int reg)
static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_PGSTATL:
- case LTC3676_PGSTATRT:
+ case LTC3676_IRQSTAT ... LTC3676_PGSTATRT:
return true;
}
return false;
@@ -317,8 +264,8 @@ static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg)
static const struct regmap_config ltc3676_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .writeable_reg = ltc3676_writeable_reg,
- .readable_reg = ltc3676_readable_reg,
+ .writeable_reg = ltc3676_readable_writeable_reg,
+ .readable_reg = ltc3676_readable_writeable_reg,
.volatile_reg = ltc3676_volatile_reg,
.max_register = LTC3676_CLIRQ,
.use_single_read = true,
@@ -442,5 +389,5 @@ static struct i2c_driver ltc3676_driver = {
module_i2c_driver(ltc3676_driver);
MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>");
-MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376");
+MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3676");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c
index bc7f4751bf9c..85a88a9e4d42 100644
--- a/drivers/regulator/max14577-regulator.c
+++ b/drivers/regulator/max14577-regulator.c
@@ -324,4 +324,3 @@ module_exit(max14577_regulator_exit);
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:max14577-regulator");
diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c
index b94e3a721721..1607ac673e44 100644
--- a/drivers/regulator/max77620-regulator.c
+++ b/drivers/regulator/max77620-regulator.c
@@ -1,7 +1,7 @@
/*
* Maxim MAX77620 Regulator driver
*
- * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
* Laxman Dewangan <ldewangan@nvidia.com>
@@ -690,6 +690,7 @@ static const struct regulator_ops max77620_regulator_ops = {
.active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
.active_discharge_reg = MAX77620_REG_##_id##_CFG, \
.type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
}, \
}
@@ -721,6 +722,7 @@ static const struct regulator_ops max77620_regulator_ops = {
.active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
.active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
.type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
}, \
}
@@ -803,6 +805,14 @@ static int max77620_regulator_probe(struct platform_device *pdev)
rdesc = &rinfo[id].desc;
pmic->rinfo[id] = &max77620_regs_info[id];
pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+ pmic->reg_pdata[id].active_fps_src = -1;
+ pmic->reg_pdata[id].active_fps_pd_slot = -1;
+ pmic->reg_pdata[id].active_fps_pu_slot = -1;
+ pmic->reg_pdata[id].suspend_fps_src = -1;
+ pmic->reg_pdata[id].suspend_fps_pd_slot = -1;
+ pmic->reg_pdata[id].suspend_fps_pu_slot = -1;
+ pmic->reg_pdata[id].power_ok = -1;
+ pmic->reg_pdata[id].ramp_rate_setting = -1;
ret = max77620_read_slew_rate(pmic, id);
if (ret < 0)
diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c
new file mode 100644
index 000000000000..31ebf34b01ec
--- /dev/null
+++ b/drivers/regulator/max77650-regulator.c
@@ -0,0 +1,498 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Regulator driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/of.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0)
+#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
+ ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
+#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1)
+#define MAX77650_REGULATOR_DISABLED BIT(2)
+
+#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)
+#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)
+
+#define MAX77650_REGULATOR_AD_MASK BIT(3)
+#define MAX77650_REGULATOR_AD_DISABLED 0x00
+#define MAX77650_REGULATOR_AD_ENABLED BIT(3)
+
+#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6)
+
+enum {
+ MAX77650_REGULATOR_ID_LDO = 0,
+ MAX77650_REGULATOR_ID_SBB0,
+ MAX77650_REGULATOR_ID_SBB1,
+ MAX77650_REGULATOR_ID_SBB2,
+ MAX77650_REGULATOR_NUM_REGULATORS,
+};
+
+struct max77650_regulator_desc {
+ struct regulator_desc desc;
+ unsigned int regA;
+ unsigned int regB;
+};
+
+static const u32 max77651_sbb1_regulator_volt_table[] = {
+ 2400000, 3200000, 4000000, 4800000,
+ 2450000, 3250000, 4050000, 4850000,
+ 2500000, 3300000, 4100000, 4900000,
+ 2550000, 3350000, 4150000, 4950000,
+ 2600000, 3400000, 4200000, 5000000,
+ 2650000, 3450000, 4250000, 5050000,
+ 2700000, 3500000, 4300000, 5100000,
+ 2750000, 3550000, 4350000, 5150000,
+ 2800000, 3600000, 4400000, 5200000,
+ 2850000, 3650000, 4450000, 5250000,
+ 2900000, 3700000, 4500000, 0,
+ 2950000, 3750000, 4550000, 0,
+ 3000000, 3800000, 4600000, 0,
+ 3050000, 3850000, 4650000, 0,
+ 3100000, 3900000, 4700000, 0,
+ 3150000, 3950000, 4750000, 0,
+};
+
+#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \
+ (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4))
+#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \
+ (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2))
+
+#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \
+ do { \
+ _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
+ _val--; \
+ _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
+ } while (0)
+
+#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \
+ do { \
+ _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
+ _val++; \
+ _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
+ } while (0)
+
+static const unsigned int max77650_current_limit_table[] = {
+ 1000000, 866000, 707000, 500000,
+};
+
+static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+ int val, rv, en;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ rv = regmap_read(map, rdesc->regB, &val);
+ if (rv)
+ return rv;
+
+ en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
+
+ return en != MAX77650_REGULATOR_DISABLED;
+}
+
+static int max77650_regulator_enable(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ return regmap_update_bits(map, rdesc->regB,
+ MAX77650_REGULATOR_EN_CTRL_MASK,
+ MAX77650_REGULATOR_ENABLED);
+}
+
+static int max77650_regulator_disable(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ return regmap_update_bits(map, rdesc->regB,
+ MAX77650_REGULATOR_EN_CTRL_MASK,
+ MAX77650_REGULATOR_DISABLED);
+}
+
+static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int rv = 0, curr, diff;
+ bool ascending;
+
+ /*
+ * If the regulator is disabled, we can program the desired
+ * voltage right away.
+ */
+ if (!max77650_regulator_is_enabled(rdev))
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ /*
+ * Otherwise we need to manually ramp the output voltage up/down
+ * one step at a time.
+ */
+
+ curr = regulator_get_voltage_sel_regmap(rdev);
+ if (curr < 0)
+ return curr;
+
+ diff = curr - sel;
+ if (diff == 0)
+ return 0; /* Already there. */
+ else if (diff > 0)
+ ascending = false;
+ else
+ ascending = true;
+
+ /*
+ * Make sure we'll get to the right voltage and break the loop even if
+ * the selector equals 0.
+ */
+ for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) {
+ rv = regulator_set_voltage_sel_regmap(rdev, curr);
+ if (rv)
+ return rv;
+
+ if (curr == sel)
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Special case: non-linear voltage table for max77651 SBB1 - software
+ * must ensure the voltage is ramped in 50mV increments.
+ */
+static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int rv = 0, curr, vcurr, vdest, vdiff;
+
+ /*
+ * If the regulator is disabled, we can program the desired
+ * voltage right away.
+ */
+ if (!max77650_regulator_is_enabled(rdev))
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ curr = regulator_get_voltage_sel_regmap(rdev);
+ if (curr < 0)
+ return curr;
+
+ if (curr == sel)
+ return 0; /* Already there. */
+
+ vcurr = max77651_sbb1_regulator_volt_table[curr];
+ vdest = max77651_sbb1_regulator_volt_table[sel];
+ vdiff = vcurr - vdest;
+
+ for (;;) {
+ if (vdiff > 0)
+ MAX77650_REGULATOR_SBB1_SEL_DECR(curr);
+ else
+ MAX77650_REGULATOR_SBB1_SEL_INCR(curr);
+
+ rv = regulator_set_voltage_sel_regmap(rdev, curr);
+ if (rv)
+ return rv;
+
+ if (curr == sel)
+ break;
+ };
+
+ return 0;
+}
+
+static const struct regulator_ops max77650_regulator_LDO_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77650_regulator_set_voltage_sel,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static const struct regulator_ops max77650_regulator_SBB_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77650_regulator_set_voltage_sel,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+/* Special case for max77651 SBB1 - non-linear voltage mapping. */
+static const struct regulator_ops max77651_SBB1_regulator_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_table,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static struct max77650_regulator_desc max77650_LDO_desc = {
+ .desc = {
+ .name = "ldo",
+ .of_match = of_match_ptr("ldo"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-ldo",
+ .id = MAX77650_REGULATOR_ID_LDO,
+ .ops = &max77650_regulator_LDO_ops,
+ .min_uV = 1350000,
+ .uV_step = 12500,
+ .n_voltages = 128,
+ .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_LDO_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_LDO_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .regA = MAX77650_REG_CNFG_LDO_A,
+ .regB = MAX77650_REG_CNFG_LDO_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB0_desc = {
+ .desc = {
+ .name = "sbb0",
+ .of_match = of_match_ptr("sbb0"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB0,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 25000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB0_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB0_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB0_A,
+ .regB = MAX77650_REG_CNFG_SBB0_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB1_desc = {
+ .desc = {
+ .name = "sbb1",
+ .of_match = of_match_ptr("sbb1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb1",
+ .id = MAX77650_REGULATOR_ID_SBB1,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB1_A,
+ .regB = MAX77650_REG_CNFG_SBB1_B,
+};
+
+static struct max77650_regulator_desc max77651_SBB1_desc = {
+ .desc = {
+ .name = "sbb1",
+ .of_match = of_match_ptr("sbb1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb1",
+ .id = MAX77650_REGULATOR_ID_SBB1,
+ .ops = &max77651_SBB1_regulator_ops,
+ .volt_table = max77651_sbb1_regulator_volt_table,
+ .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table),
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB1_A,
+ .regB = MAX77650_REG_CNFG_SBB1_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB2_desc = {
+ .desc = {
+ .name = "sbb2",
+ .of_match = of_match_ptr("sbb2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB2,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 50000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB2_A,
+ .regB = MAX77650_REG_CNFG_SBB2_B,
+};
+
+static struct max77650_regulator_desc max77651_SBB2_desc = {
+ .desc = {
+ .name = "sbb2",
+ .of_match = of_match_ptr("sbb2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB2,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 2400000,
+ .uV_step = 50000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB2_A,
+ .regB = MAX77650_REG_CNFG_SBB2_B,
+};
+
+static int max77650_regulator_probe(struct platform_device *pdev)
+{
+ struct max77650_regulator_desc **rdescs;
+ struct max77650_regulator_desc *rdesc;
+ struct regulator_config config = { };
+ struct device *dev, *parent;
+ struct regulator_dev *rdev;
+ struct regmap *map;
+ unsigned int val;
+ int i, rv;
+
+ dev = &pdev->dev;
+ parent = dev->parent;
+
+ if (!dev->of_node)
+ dev->of_node = parent->of_node;
+
+ rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
+ sizeof(*rdescs), GFP_KERNEL);
+ if (!rdescs)
+ return -ENOMEM;
+
+ map = dev_get_regmap(parent, NULL);
+ if (!map)
+ return -ENODEV;
+
+ rv = regmap_read(map, MAX77650_REG_CID, &val);
+ if (rv)
+ return rv;
+
+ rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
+
+ switch (MAX77650_CID_BITS(val)) {
+ case MAX77650_CID_77650A:
+ case MAX77650_CID_77650C:
+ rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
+ break;
+ case MAX77650_CID_77651A:
+ case MAX77650_CID_77651B:
+ rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ config.dev = parent;
+
+ for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
+ rdesc = rdescs[i];
+ config.driver_data = rdesc;
+
+ rdev = devm_regulator_register(dev, &rdesc->desc, &config);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+static struct platform_driver max77650_regulator_driver = {
+ .driver = {
+ .name = "max77650-regulator",
+ },
+ .probe = max77650_regulator_probe,
+};
+module_platform_driver(max77650_regulator_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c
index c30cf5c9f2de..ea7b50397300 100644
--- a/drivers/regulator/max77802-regulator.c
+++ b/drivers/regulator/max77802-regulator.c
@@ -248,9 +248,9 @@ static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev,
unsigned int ramp_value;
if (id > MAX77802_BUCK4) {
- dev_warn(&rdev->dev,
- "%s: regulator: ramp delay not supported\n",
- rdev->desc->name);
+ dev_warn(&rdev->dev,
+ "%s: regulator: ramp delay not supported\n",
+ rdev->desc->name);
return -EINVAL;
}
ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit,
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 8fd1adc9c9a9..ab558b26cd7c 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -226,69 +226,69 @@ static const unsigned int mc13783_pwgtdrv_val[] = {
5500000,
};
-static struct regulator_ops mc13783_gpo_regulator_ops;
+static const struct regulator_ops mc13783_gpo_regulator_ops;
-#define MC13783_DEFINE(prefix, name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \
+#define MC13783_DEFINE(prefix, name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13783_REG_, name, node, reg, vsel_reg, voltages, \
mc13xxx_regulator_ops)
-#define MC13783_FIXED_DEFINE(prefix, name, reg, voltages) \
- MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \
+#define MC13783_FIXED_DEFINE(prefix, name, node, reg, voltages) \
+ MC13xxx_FIXED_DEFINE(MC13783_REG_, name, node, reg, voltages, \
mc13xxx_fixed_regulator_ops)
-#define MC13783_GPO_DEFINE(prefix, name, reg, voltages) \
- MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \
+#define MC13783_GPO_DEFINE(prefix, name, node, reg, voltages) \
+ MC13xxx_GPO_DEFINE(MC13783_REG_, name, node, reg, voltages, \
mc13783_gpo_regulator_ops)
-#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \
- MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
-#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \
- MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
+#define MC13783_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages) \
+ MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages)
+#define MC13783_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages) \
+ MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages)
static struct mc13xxx_regulator mc13783_regulators[] = {
- MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val),
- MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val),
- MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val),
- MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val),
- MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
-
- MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
- MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
- MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_SW(SW1A, sw1a, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val),
+ MC13783_DEFINE_SW(SW1B, sw1b, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val),
+ MC13783_DEFINE_SW(SW2A, sw2a, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val),
+ MC13783_DEFINE_SW(SW2B, sw2b, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val),
+ MC13783_DEFINE_SW(SW3, sw3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
+
+ MC13783_FIXED_DEFINE(REG, VAUDIO, vaudio, REGULATORMODE0, mc13783_vaudio_val),
+ MC13783_FIXED_DEFINE(REG, VIOHI, viohi, REGULATORMODE0, mc13783_viohi_val),
+ MC13783_DEFINE_REGU(VIOLO, violo, REGULATORMODE0, REGULATORSETTING0,
mc13783_violo_val),
- MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0,
mc13783_vdig_val),
- MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VGEN, vgen, REGULATORMODE0, REGULATORSETTING0,
mc13783_vgen_val),
- MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFDIG, vrfdig, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfdig_val),
- MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFREF, vrfref, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfref_val),
- MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFCP, vrfcp, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfcp_val),
- MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VSIM, vsim, REGULATORMODE1, REGULATORSETTING0,
mc13783_vsim_val),
- MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VESIM, vesim, REGULATORMODE1, REGULATORSETTING0,
mc13783_vesim_val),
- MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0,
mc13783_vcam_val),
- MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
- MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_FIXED_DEFINE(REG, VRFBG, vrfbg, REGULATORMODE1, mc13783_vrfbg_val),
+ MC13783_DEFINE_REGU(VVIB, vvib, REGULATORMODE1, REGULATORSETTING1,
mc13783_vvib_val),
- MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VRF1, vrf1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
- MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VRF2, vrf2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
- MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VMMC1, vmmc1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
- MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VMMC2, vmmc2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
- MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
- MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
+ MC13783_GPO_DEFINE(REG, GPO1, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO2, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO3, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO4, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, PWGT1SPI, pwgt1spi, POWERMISC, mc13783_pwgtdrv_val),
+ MC13783_GPO_DEFINE(REG, PWGT2SPI, pwgt2spi, POWERMISC, mc13783_pwgtdrv_val),
};
static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
@@ -380,7 +380,7 @@ static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
return (val & mc13xxx_regulators[id].enable_bit) != 0;
}
-static struct regulator_ops mc13783_gpo_regulator_ops = {
+static const struct regulator_ops mc13783_gpo_regulator_ops = {
.enable = mc13783_gpo_regulator_enable,
.disable = mc13783_gpo_regulator_disable,
.is_enabled = mc13783_gpo_regulator_is_enabled,
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index f3fba1cc1379..a731e826a037 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -242,61 +242,61 @@ static const unsigned int mc13892_pwgtdrv[] = {
5000000,
};
-static struct regulator_ops mc13892_gpo_regulator_ops;
-static struct regulator_ops mc13892_sw_regulator_ops;
+static const struct regulator_ops mc13892_gpo_regulator_ops;
+static const struct regulator_ops mc13892_sw_regulator_ops;
-#define MC13892_FIXED_DEFINE(name, reg, voltages) \
- MC13xxx_FIXED_DEFINE(MC13892_, name, reg, voltages, \
+#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \
+ MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \
mc13xxx_fixed_regulator_ops)
-#define MC13892_GPO_DEFINE(name, reg, voltages) \
- MC13xxx_GPO_DEFINE(MC13892_, name, reg, voltages, \
+#define MC13892_GPO_DEFINE(name, node, reg, voltages) \
+ MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \
mc13892_gpo_regulator_ops)
-#define MC13892_SW_DEFINE(name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
+#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \
mc13892_sw_regulator_ops)
-#define MC13892_DEFINE_REGU(name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
+#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \
mc13xxx_regulator_ops)
static struct mc13xxx_regulator mc13892_regulators[] = {
- MC13892_DEFINE_REGU(VCOINCELL, POWERCTL0, POWERCTL0, mc13892_vcoincell),
- MC13892_SW_DEFINE(SW1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
- MC13892_SW_DEFINE(SW2, SWITCHERS1, SWITCHERS1, mc13892_sw),
- MC13892_SW_DEFINE(SW3, SWITCHERS2, SWITCHERS2, mc13892_sw),
- MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw),
- MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst),
- MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi),
- MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell),
+ MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
+ MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw),
+ MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw),
+ MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw),
+ MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst),
+ MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi),
+ MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0,
mc13892_vpll),
- MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0,
mc13892_vdig),
- MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1,
mc13892_vsd),
- MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0,
mc13892_vusb2),
- MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1,
mc13892_vvideo),
- MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1,
mc13892_vaudio),
- MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0,
mc13892_vcam),
- MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0,
mc13892_vgen1),
- MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0,
mc13892_vgen2),
- MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0,
mc13892_vgen3),
- MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb),
- MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO2, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO3, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO4, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(PWGT1SPI, POWERMISC, mc13892_pwgtdrv),
- MC13892_GPO_DEFINE(PWGT2SPI, POWERMISC, mc13892_pwgtdrv),
+ MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb),
+ MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv),
+ MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv),
};
static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
@@ -387,7 +387,7 @@ static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev)
}
-static struct regulator_ops mc13892_gpo_regulator_ops = {
+static const struct regulator_ops mc13892_gpo_regulator_ops = {
.enable = mc13892_gpo_regulator_enable,
.disable = mc13892_gpo_regulator_disable,
.is_enabled = mc13892_gpo_regulator_is_enabled,
@@ -479,7 +479,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
-static struct regulator_ops mc13892_sw_regulator_ops = {
+static const struct regulator_ops mc13892_sw_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 2243138d8a58..8ff19150ca92 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -99,7 +99,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
return rdev->desc->volt_table[val];
}
-struct regulator_ops mc13xxx_regulator_ops = {
+const struct regulator_ops mc13xxx_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
@@ -127,7 +127,7 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
-struct regulator_ops mc13xxx_fixed_regulator_ops = {
+const struct regulator_ops mc13xxx_fixed_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h
index 2ab9bfd93b4e..ba7eff1070bd 100644
--- a/drivers/regulator/mc13xxx.h
+++ b/drivers/regulator/mc13xxx.h
@@ -53,13 +53,13 @@ static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
}
#endif
-extern struct regulator_ops mc13xxx_regulator_ops;
-extern struct regulator_ops mc13xxx_fixed_regulator_ops;
+extern const struct regulator_ops mc13xxx_regulator_ops;
+extern const struct regulator_ops mc13xxx_fixed_regulator_ops;
-#define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \
+#define MC13xxx_DEFINE(prefix, _name, _node, _reg, _vsel_reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -74,10 +74,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
}
-#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \
+#define MC13xxx_FIXED_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -89,10 +89,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
}
-#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \
+#define MC13xxx_GPO_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -104,9 +104,9 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
}
-#define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \
- MC13xxx_DEFINE(SW, _name, _reg, _vsel_reg, _voltages, ops)
-#define MC13xxx_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages, ops) \
- MC13xxx_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages, ops)
+#define MC13xxx_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages, ops) \
+ MC13xxx_DEFINE(SW, _name, _node, _reg, _vsel_reg, _voltages, ops)
+#define MC13xxx_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages, ops) \
+ MC13xxx_DEFINE(REGU, _name, _node, _reg, _vsel_reg, _voltages, ops)
#endif
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index 3479ae009b0b..3a8004abe044 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -17,6 +17,7 @@
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/suspend.h>
+#include <linux/gpio/consumer.h>
#define VDD_LOW_SEL 0x0D
#define VDD_HIGH_SEL 0x3F
@@ -546,7 +547,6 @@ static struct i2c_driver mcp16502_drv = {
module_i2c_driver(mcp16502_drv);
-MODULE_VERSION("1.0");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MCP16502 PMIC driver");
MODULE_AUTHOR("Andrei Stefanescu andrei.stefanescu@microchip.com");
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index 0495716fd35f..01d69f43d2b0 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -38,13 +38,9 @@ static const struct regmap_config mt6311_regmap_config = {
#define MT6311_MAX_UV 1393750
#define MT6311_STEP_UV 6250
-static const struct regulator_linear_range buck_volt_range[] = {
- REGULATOR_LINEAR_RANGE(MT6311_MIN_UV, 0, 0x7f, MT6311_STEP_UV),
-};
-
static const struct regulator_ops mt6311_buck_ops = {
- .list_voltage = regulator_list_voltage_linear_range,
- .map_voltage = regulator_map_voltage_linear_range,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
@@ -71,8 +67,6 @@ static const struct regulator_ops mt6311_ldo_ops = {
.min_uV = MT6311_MIN_UV,\
.uV_step = MT6311_STEP_UV,\
.owner = THIS_MODULE,\
- .linear_ranges = buck_volt_range, \
- .n_linear_ranges = ARRAY_SIZE(buck_volt_range), \
.enable_reg = MT6311_VDVFS11_CON9,\
.enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\
.vsel_reg = MT6311_VDVFS11_CON12,\
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index ffa5fc3724e4..7b6bf3536271 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -255,7 +255,7 @@ static void of_get_regulation_constraints(struct device_node *np,
* @desc: regulator description
*
* Populates regulator_init_data structure by extracting data from device
- * tree node, returns a pointer to the populated struture or NULL if memory
+ * tree node, returns a pointer to the populated structure or NULL if memory
* alloc fails.
*/
struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
@@ -547,7 +547,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev)
NULL);
if (c_n_phandles != n_phandles) {
- dev_err(&rdev->dev, "number of couped reg phandles mismatch\n");
+ dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n");
ret = false;
goto clean;
}
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index c2cc392a27d4..7fb9e8dd834e 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -382,7 +382,7 @@ static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = {
EXTERNAL_REQUESTOR_TPS65917(LDO5, 2, 4),
};
-static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
+static const unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
#define SMPS_CTRL_MODE_OFF 0x00
#define SMPS_CTRL_MODE_ON 0x01
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index a9446056435f..1600f9821891 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -53,10 +53,6 @@ enum {
struct pv88060_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int conf; /* buck configuration register */
};
@@ -75,7 +71,7 @@ static const struct regmap_config pv88060_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88060_buck1_limits[] = {
+static const unsigned int pv88060_buck1_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -128,40 +124,6 @@ static int pv88060_buck_set_mode(struct regulator_dev *rdev,
PV88060_BUCK_MODE_MASK, val);
}
-static int pv88060_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88060_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->conf,
- info->limit_mask,
- i << PV88060_BUCK_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88060_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88060_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->conf, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88060_BUCK_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88060_buck_ops = {
.get_mode = pv88060_buck_get_mode,
.set_mode = pv88060_buck_set_mode,
@@ -171,8 +133,8 @@ static const struct regulator_ops pv88060_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88060_set_current_limit,
- .get_current_limit = pv88060_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88060_ldo_ops = {
@@ -184,6 +146,12 @@ static const struct regulator_ops pv88060_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
};
+static const struct regulator_ops pv88060_sw_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
#define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \
{\
.desc = {\
@@ -201,10 +169,11 @@ static const struct regulator_ops pv88060_ldo_ops = {
.enable_mask = PV88060_BUCK_EN, \
.vsel_reg = PV88060_REG_##regl_name##_CONF0,\
.vsel_mask = PV88060_VBUCK_MASK,\
+ .curr_table = limits_array,\
+ .n_current_limits = ARRAY_SIZE(limits_array),\
+ .csel_reg = PV88060_REG_##regl_name##_CONF1,\
+ .csel_mask = PV88060_BUCK_ILIM_MASK,\
},\
- .current_limits = limits_array,\
- .n_current_limits = ARRAY_SIZE(limits_array),\
- .limit_mask = PV88060_BUCK_ILIM_MASK, \
.conf = PV88060_REG_##regl_name##_CONF1,\
}
@@ -237,9 +206,8 @@ static const struct regulator_ops pv88060_ldo_ops = {
.regulators_node = of_match_ptr("regulators"),\
.type = REGULATOR_VOLTAGE,\
.owner = THIS_MODULE,\
- .ops = &pv88060_ldo_ops,\
- .min_uV = max,\
- .uV_step = 0,\
+ .ops = &pv88060_sw_ops,\
+ .fixed_uV = max,\
.n_voltages = 1,\
.enable_reg = PV88060_REG_##regl_name##_CONF,\
.enable_mask = PV88060_SW_EN,\
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 9a08cb2de501..bdddacdbeb99 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -45,12 +45,7 @@ enum pv88080_types {
struct pv88080_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned int n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int mode_reg;
- unsigned int limit_reg;
unsigned int conf2;
unsigned int conf5;
};
@@ -102,11 +97,11 @@ static const struct regmap_config pv88080_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88080_buck1_limits[] = {
+static const unsigned int pv88080_buck1_limits[] = {
3230000, 5130000, 6960000, 8790000
};
-static const int pv88080_buck23_limits[] = {
+static const unsigned int pv88080_buck23_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -272,40 +267,6 @@ static int pv88080_buck_set_mode(struct regulator_dev *rdev,
PV88080_BUCK1_MODE_MASK, val);
}
-static int pv88080_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88080_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->limit_reg,
- info->limit_mask,
- i << PV88080_BUCK1_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88080_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88080_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->limit_reg, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88080_BUCK1_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88080_buck_ops = {
.get_mode = pv88080_buck_get_mode,
.set_mode = pv88080_buck_set_mode,
@@ -315,8 +276,8 @@ static const struct regulator_ops pv88080_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88080_set_current_limit,
- .get_current_limit = pv88080_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88080_hvbuck_ops = {
@@ -341,9 +302,9 @@ static const struct regulator_ops pv88080_hvbuck_ops = {
.min_uV = min, \
.uV_step = step, \
.n_voltages = ((max) - (min))/(step) + 1, \
+ .curr_table = limits_array, \
+ .n_current_limits = ARRAY_SIZE(limits_array), \
},\
- .current_limits = limits_array, \
- .n_current_limits = ARRAY_SIZE(limits_array), \
}
#define PV88080_HVBUCK(chip, regl_name, min, step, max) \
@@ -521,9 +482,9 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
if (init_data)
config.init_data = &init_data[i];
- pv88080_regulator_info[i].limit_reg
+ pv88080_regulator_info[i].desc.csel_reg
= regmap_config->buck_regmap[i].buck_limit_reg;
- pv88080_regulator_info[i].limit_mask
+ pv88080_regulator_info[i].desc.csel_mask
= regmap_config->buck_regmap[i].buck_limit_mask;
pv88080_regulator_info[i].mode_reg
= regmap_config->buck_regmap[i].buck_mode_reg;
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index 7a0c15957bd0..6e97cc6df2ee 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -42,10 +42,6 @@ enum {
struct pv88090_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned int n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int conf;
unsigned int conf2;
};
@@ -71,14 +67,14 @@ static const struct regmap_config pv88090_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88090_buck1_limits[] = {
+static const unsigned int pv88090_buck1_limits[] = {
220000, 440000, 660000, 880000, 1100000, 1320000, 1540000, 1760000,
1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000,
3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000,
5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000
};
-static const int pv88090_buck23_limits[] = {
+static const unsigned int pv88090_buck23_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -150,40 +146,6 @@ static int pv88090_buck_set_mode(struct regulator_dev *rdev,
PV88090_BUCK1_MODE_MASK, val);
}
-static int pv88090_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88090_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->conf,
- info->limit_mask,
- i << PV88090_BUCK1_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88090_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88090_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->conf, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88090_BUCK1_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88090_buck_ops = {
.get_mode = pv88090_buck_get_mode,
.set_mode = pv88090_buck_set_mode,
@@ -193,8 +155,8 @@ static const struct regulator_ops pv88090_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88090_set_current_limit,
- .get_current_limit = pv88090_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88090_ldo_ops = {
@@ -223,10 +185,11 @@ static const struct regulator_ops pv88090_ldo_ops = {
.enable_mask = PV88090_##regl_name##_EN, \
.vsel_reg = PV88090_REG_##regl_name##_CONF0, \
.vsel_mask = PV88090_V##regl_name##_MASK, \
+ .curr_table = limits_array, \
+ .n_current_limits = ARRAY_SIZE(limits_array), \
+ .csel_reg = PV88090_REG_##regl_name##_CONF1, \
+ .csel_mask = PV88090_##regl_name##_ILIM_MASK, \
},\
- .current_limits = limits_array, \
- .n_current_limits = ARRAY_SIZE(limits_array), \
- .limit_mask = PV88090_##regl_name##_ILIM_MASK, \
.conf = PV88090_REG_##regl_name##_CONF1, \
.conf2 = PV88090_REG_##regl_name##_CONF2, \
}
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index a2fd140eff81..3f53f9134b32 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -40,9 +40,6 @@ struct pwm_regulator_data {
/* regulator descriptor */
struct regulator_desc desc;
- /* Regulator ops */
- struct regulator_ops ops;
-
int state;
/* Enable GPIO */
@@ -231,7 +228,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
return 0;
}
-static struct regulator_ops pwm_regulator_voltage_table_ops = {
+static const struct regulator_ops pwm_regulator_voltage_table_ops = {
.set_voltage_sel = pwm_regulator_set_voltage_sel,
.get_voltage_sel = pwm_regulator_get_voltage_sel,
.list_voltage = pwm_regulator_list_voltage,
@@ -241,7 +238,7 @@ static struct regulator_ops pwm_regulator_voltage_table_ops = {
.is_enabled = pwm_regulator_is_enabled,
};
-static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
+static const struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.get_voltage = pwm_regulator_get_voltage,
.set_voltage = pwm_regulator_set_voltage,
.enable = pwm_regulator_enable,
@@ -249,7 +246,7 @@ static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.is_enabled = pwm_regulator_is_enabled,
};
-static struct regulator_desc pwm_regulator_desc = {
+static const struct regulator_desc pwm_regulator_desc = {
.name = "pwm-regulator",
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
@@ -287,9 +284,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
drvdata->state = -EINVAL;
drvdata->duty_cycle_table = duty_cycle_table;
- memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
- sizeof(drvdata->ops));
- drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.ops = &pwm_regulator_voltage_table_ops;
drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table);
return 0;
@@ -301,9 +296,7 @@ static int pwm_regulator_init_continuous(struct platform_device *pdev,
u32 dutycycle_range[2] = { 0, 100 };
u32 dutycycle_unit = 100;
- memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
- sizeof(drvdata->ops));
- drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops;
drvdata->desc.continuous_voltage_range = true;
of_property_read_u32_array(pdev->dev.of_node,
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index f5bca77d67c1..68bc23df4213 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -31,6 +31,11 @@ struct qcom_rpm_reg {
int is_enabled;
int uV;
+ u32 load;
+
+ unsigned int enabled_updated:1;
+ unsigned int uv_updated:1;
+ unsigned int load_updated:1;
};
struct rpm_regulator_req {
@@ -43,30 +48,59 @@ struct rpm_regulator_req {
#define RPM_KEY_UV 0x00007675 /* "uv" */
#define RPM_KEY_MA 0x0000616d /* "ma" */
-static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
- struct rpm_regulator_req *req,
- size_t size)
+static int rpm_reg_write_active(struct qcom_rpm_reg *vreg)
{
- return qcom_rpm_smd_write(vreg->rpm,
- QCOM_SMD_RPM_ACTIVE_STATE,
- vreg->type,
- vreg->id,
- req, size);
+ struct rpm_regulator_req req[3];
+ int reqlen = 0;
+ int ret;
+
+ if (vreg->enabled_updated) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->is_enabled);
+ reqlen++;
+ }
+
+ if (vreg->uv_updated && vreg->is_enabled) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_UV);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->uV);
+ reqlen++;
+ }
+
+ if (vreg->load_updated && vreg->is_enabled) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_MA);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->load / 1000);
+ reqlen++;
+ }
+
+ if (!reqlen)
+ return 0;
+
+ ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ vreg->type, vreg->id,
+ req, sizeof(req[0]) * reqlen);
+ if (!ret) {
+ vreg->enabled_updated = 0;
+ vreg->uv_updated = 0;
+ vreg->load_updated = 0;
+ }
+
+ return ret;
}
static int rpm_reg_enable(struct regulator_dev *rdev)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
int ret;
- req.key = cpu_to_le32(RPM_KEY_SWEN);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(1);
+ vreg->is_enabled = 1;
+ vreg->enabled_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->is_enabled = 1;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->is_enabled = 0;
return ret;
}
@@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
static int rpm_reg_disable(struct regulator_dev *rdev)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
int ret;
- req.key = cpu_to_le32(RPM_KEY_SWEN);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = 0;
+ vreg->is_enabled = 0;
+ vreg->enabled_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->is_enabled = 0;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->is_enabled = 1;
return ret;
}
@@ -108,16 +140,15 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
unsigned *selector)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
- int ret = 0;
+ int ret;
+ int old_uV = vreg->uV;
- req.key = cpu_to_le32(RPM_KEY_UV);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(min_uV);
+ vreg->uV = min_uV;
+ vreg->uv_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->uV = min_uV;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->uV = old_uV;
return ret;
}
@@ -125,13 +156,16 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
+ u32 old_load = vreg->load;
+ int ret;
- req.key = cpu_to_le32(RPM_KEY_MA);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(load_uA / 1000);
+ vreg->load = load_uA;
+ vreg->load_updated = 1;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->load = old_load;
- return rpm_reg_write_active(vreg, &req, sizeof(req));
+ return ret;
}
static const struct regulator_ops rpm_smps_ldo_ops = {
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 213b68743cc8..23713e16c286 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -1,5 +1,5 @@
/*
- * Regulator driver for Rockchip RK808/RK818
+ * Regulator driver for Rockchip RK805/RK808/RK818
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
@@ -363,28 +363,28 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
rdev->desc->enable_mask);
}
-static struct regulator_ops rk805_reg_ops = {
- .list_voltage = regulator_list_voltage_linear,
- .map_voltage = regulator_map_voltage_linear,
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
- .set_voltage_sel = regulator_set_voltage_sel_regmap,
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
- .set_suspend_voltage = rk808_set_suspend_voltage,
- .set_suspend_enable = rk805_set_suspend_enable,
- .set_suspend_disable = rk805_set_suspend_disable,
+static const struct regulator_ops rk805_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
};
-static struct regulator_ops rk805_switch_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
- .set_suspend_enable = rk805_set_suspend_enable,
- .set_suspend_disable = rk805_set_suspend_disable,
+static const struct regulator_ops rk805_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
};
-static struct regulator_ops rk808_buck1_2_ops = {
+static const struct regulator_ops rk808_buck1_2_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap,
@@ -399,7 +399,7 @@ static struct regulator_ops rk808_buck1_2_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_reg_ops = {
+static const struct regulator_ops rk808_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -412,7 +412,7 @@ static struct regulator_ops rk808_reg_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_reg_ops_ranges = {
+static const struct regulator_ops rk808_reg_ops_ranges = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -425,7 +425,7 @@ static struct regulator_ops rk808_reg_ops_ranges = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_switch_ops = {
+static const struct regulator_ops rk808_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -433,6 +433,12 @@ static struct regulator_ops rk808_switch_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
+static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500),
+ REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),
+ REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
+};
+
static const struct regulator_desc rk805_reg[] = {
{
.name = "DCDC_REG1",
@@ -440,11 +446,11 @@ static const struct regulator_desc rk805_reg[] = {
.of_match = of_match_ptr("DCDC_REG1"),
.regulators_node = of_match_ptr("regulators"),
.id = RK805_ID_DCDC1,
- .ops = &rk805_reg_ops,
+ .ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
- .min_uV = 712500,
- .uV_step = 12500,
.n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
.vsel_reg = RK805_BUCK1_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK805_DCDC_EN_REG,
@@ -456,11 +462,11 @@ static const struct regulator_desc rk805_reg[] = {
.of_match = of_match_ptr("DCDC_REG2"),
.regulators_node = of_match_ptr("regulators"),
.id = RK805_ID_DCDC2,
- .ops = &rk805_reg_ops,
+ .ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
- .min_uV = 712500,
- .uV_step = 12500,
.n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
.vsel_reg = RK805_BUCK2_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK805_DCDC_EN_REG,
@@ -796,7 +802,7 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
-MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs");
+MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c
index 96d2c18e051a..639cbadc044a 100644
--- a/drivers/regulator/rt5033-regulator.c
+++ b/drivers/regulator/rt5033-regulator.c
@@ -16,14 +16,14 @@
#include <linux/mfd/rt5033-private.h>
#include <linux/regulator/of_regulator.h>
-static struct regulator_ops rt5033_safe_ldo_ops = {
+static const struct regulator_ops rt5033_safe_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_ops rt5033_buck_ops = {
+static const struct regulator_ops rt5033_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
index 095d25f3d2ea..58a1fe583a6c 100644
--- a/drivers/regulator/s2mpa01.c
+++ b/drivers/regulator/s2mpa01.c
@@ -298,13 +298,13 @@ static const struct regulator_desc regulators[] = {
regulator_desc_ldo(2, STEP_50_MV),
regulator_desc_ldo(3, STEP_50_MV),
regulator_desc_ldo(4, STEP_50_MV),
- regulator_desc_ldo(5, STEP_50_MV),
+ regulator_desc_ldo(5, STEP_25_MV),
regulator_desc_ldo(6, STEP_25_MV),
regulator_desc_ldo(7, STEP_50_MV),
regulator_desc_ldo(8, STEP_50_MV),
regulator_desc_ldo(9, STEP_50_MV),
regulator_desc_ldo(10, STEP_50_MV),
- regulator_desc_ldo(11, STEP_25_MV),
+ regulator_desc_ldo(11, STEP_50_MV),
regulator_desc_ldo(12, STEP_50_MV),
regulator_desc_ldo(13, STEP_50_MV),
regulator_desc_ldo(14, STEP_50_MV),
@@ -315,11 +315,11 @@ static const struct regulator_desc regulators[] = {
regulator_desc_ldo(19, STEP_50_MV),
regulator_desc_ldo(20, STEP_50_MV),
regulator_desc_ldo(21, STEP_50_MV),
- regulator_desc_ldo(22, STEP_25_MV),
- regulator_desc_ldo(23, STEP_25_MV),
+ regulator_desc_ldo(22, STEP_50_MV),
+ regulator_desc_ldo(23, STEP_50_MV),
regulator_desc_ldo(24, STEP_50_MV),
regulator_desc_ldo(25, STEP_50_MV),
- regulator_desc_ldo(26, STEP_50_MV),
+ regulator_desc_ldo(26, STEP_25_MV),
regulator_desc_buck1_4(1),
regulator_desc_buck1_4(2),
regulator_desc_buck1_4(3),
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index ee4a23ab0663..134c62db36c5 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -362,7 +362,7 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_ldo(32, STEP_50_MV),
regulator_desc_s2mps11_ldo(33, STEP_50_MV),
regulator_desc_s2mps11_ldo(34, STEP_50_MV),
- regulator_desc_s2mps11_ldo(35, STEP_50_MV),
+ regulator_desc_s2mps11_ldo(35, STEP_25_MV),
regulator_desc_s2mps11_ldo(36, STEP_50_MV),
regulator_desc_s2mps11_ldo(37, STEP_50_MV),
regulator_desc_s2mps11_ldo(38, STEP_50_MV),
@@ -372,8 +372,8 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck1_4(4),
regulator_desc_s2mps11_buck5,
regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_12_5_MV),
+ regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_12_5_MV),
regulator_desc_s2mps11_buck9,
regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
};
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index b581f01f3395..bb9d1a083299 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -115,7 +115,7 @@ static const struct sec_voltage_desc *reg_voltage_map[] = {
[S5M8767_BUCK9] = &buck_voltage_val3,
};
-static unsigned int s5m8767_opmode_reg[][4] = {
+static const unsigned int s5m8767_opmode_reg[][4] = {
/* {OFF, ON, LOWPOWER, SUSPEND} */
/* LDO1 ... LDO28 */
{0x0, 0x3, 0x2, 0x1}, /* LDO1 */
@@ -339,13 +339,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int new_sel)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- const struct sec_voltage_desc *desc;
- int reg_id = rdev_get_id(rdev);
-
- desc = reg_voltage_map[reg_id];
if ((old_sel < new_sel) && s5m8767->ramp_delay)
- return DIV_ROUND_UP(desc->step * (new_sel - old_sel),
+ return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel),
s5m8767->ramp_delay * 1000);
return 0;
}
diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c
index e0a9c445ed67..ba2f24949dc9 100644
--- a/drivers/regulator/stm32-vrefbuf.c
+++ b/drivers/regulator/stm32-vrefbuf.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/pm_runtime.h>
/* STM32 VREFBUF registers */
#define STM32_VREFBUF_CSR 0x00
@@ -25,9 +26,12 @@
#define STM32_HIZ BIT(1)
#define STM32_ENVR BIT(0)
+#define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10
+
struct stm32_vrefbuf {
void __iomem *base;
struct clk *clk;
+ struct device *dev;
};
static const unsigned int stm32_vrefbuf_voltages[] = {
@@ -38,9 +42,16 @@ static const unsigned int stm32_vrefbuf_voltages[] = {
static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_HIZ) | STM32_ENVR;
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
@@ -59,45 +70,95 @@ static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
}
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return ret;
}
static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_ENVR) | STM32_HIZ;
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return 0;
}
static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+ int ret;
+
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
- return readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
}
static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return 0;
}
static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
- return FIELD_GET(STM32_VRS, val);
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ ret = FIELD_GET(STM32_VRS, val);
+
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
}
static const struct regulator_ops stm32_vrefbuf_volt_ops = {
@@ -130,6 +191,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
@@ -140,10 +202,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret);
- return ret;
+ goto err_pm_stop;
}
config.dev = &pdev->dev;
@@ -161,10 +230,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, rdev);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
return 0;
err_clk_dis:
clk_disable_unprepare(priv->clk);
+err_pm_stop:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
return ret;
}
@@ -174,12 +250,42 @@ static int stm32_vrefbuf_remove(struct platform_device *pdev)
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+ pm_runtime_get_sync(&pdev->dev);
regulator_unregister(rdev);
clk_disable_unprepare(priv->clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
return 0;
};
+static int __maybe_unused stm32_vrefbuf_runtime_suspend(struct device *dev)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+
+ return clk_prepare_enable(priv->clk);
+}
+
+static const struct dev_pm_ops stm32_vrefbuf_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend,
+ stm32_vrefbuf_runtime_resume,
+ NULL)
+};
+
static const struct of_device_id stm32_vrefbuf_of_match[] = {
{ .compatible = "st,stm32-vrefbuf", },
{},
@@ -192,6 +298,7 @@ static struct platform_driver stm32_vrefbuf_driver = {
.driver = {
.name = "stm32-vrefbuf",
.of_match_table = of_match_ptr(stm32_vrefbuf_of_match),
+ .pm = &stm32_vrefbuf_pm_ops,
},
};
module_platform_driver(stm32_vrefbuf_driver);
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
index 16ba0297f709..f09061473613 100644
--- a/drivers/regulator/stpmic1_regulator.c
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -12,8 +12,10 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
/**
- * stpmic1 regulator description
+ * stpmic1 regulator description: this structure is used as driver data
* @desc: regulator framework description
* @mask_reset_reg: mask reset register address
* @mask_reset_mask: mask rank and mask reset register mask
@@ -28,28 +30,9 @@ struct stpmic1_regulator_cfg {
u8 icc_mask;
};
-/**
- * stpmic1 regulator data: this structure is used as driver data
- * @regul_id: regulator id
- * @reg_node: DT node of regulator (unused on non-DT platforms)
- * @cfg: stpmic specific regulator description
- * @mask_reset: mask_reset bit value
- * @irq_curlim: current limit interrupt number
- * @regmap: point to parent regmap structure
- */
-struct stpmic1_regulator {
- unsigned int regul_id;
- struct device_node *reg_node;
- struct stpmic1_regulator_cfg *cfg;
- u8 mask_reset;
- int irq_curlim;
- struct regmap *regmap;
-};
-
static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode);
static unsigned int stpmic1_get_mode(struct regulator_dev *rdev);
static int stpmic1_set_icc(struct regulator_dev *rdev);
-static int stpmic1_regulator_parse_dt(void *driver_data);
static unsigned int stpmic1_map_mode(unsigned int mode);
enum {
@@ -72,15 +55,13 @@ enum {
/* Enable time worst case is 5000mV/(2250uV/uS) */
#define PMIC_ENABLE_TIME_US 2200
-#define STPMIC1_BUCK_MODE_NORMAL 0
-#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK
-
-struct regulator_linear_range buck1_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
- REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
+static const struct regulator_linear_range buck1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
+ REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
+ REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
};
-struct regulator_linear_range buck2_ranges[] = {
+static const struct regulator_linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
@@ -94,7 +75,7 @@ struct regulator_linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
};
-struct regulator_linear_range buck3_ranges[] = {
+static const struct regulator_linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
@@ -102,10 +83,9 @@ struct regulator_linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0),
REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000),
REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
-
};
-struct regulator_linear_range buck4_ranges[] = {
+static const struct regulator_linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
@@ -113,24 +93,21 @@ struct regulator_linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000),
REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
-
};
-struct regulator_linear_range ldo1_ranges[] = {
+static const struct regulator_linear_range ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
-
};
-struct regulator_linear_range ldo2_ranges[] = {
+static const struct regulator_linear_range ldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
-
};
-struct regulator_linear_range ldo3_ranges[] = {
+static const struct regulator_linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
@@ -138,18 +115,18 @@ struct regulator_linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
};
-struct regulator_linear_range ldo5_ranges[] = {
+static const struct regulator_linear_range ldo5_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
};
-struct regulator_linear_range ldo6_ranges[] = {
+static const struct regulator_linear_range ldo6_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
-static struct regulator_ops stpmic1_ldo_ops = {
+static const struct regulator_ops stpmic1_ldo_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.is_enabled = regulator_is_enabled_regmap,
@@ -157,11 +134,10 @@ static struct regulator_ops stpmic1_ldo_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_ldo3_ops = {
+static const struct regulator_ops stpmic1_ldo3_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_iterate,
.is_enabled = regulator_is_enabled_regmap,
@@ -169,21 +145,19 @@ static struct regulator_ops stpmic1_ldo3_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
+static const struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_buck_ops = {
+static const struct regulator_ops stpmic1_buck_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.is_enabled = regulator_is_enabled_regmap,
@@ -197,20 +171,27 @@ static struct regulator_ops stpmic1_buck_ops = {
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_vref_ddr_ops = {
+static const struct regulator_ops stpmic1_vref_ddr_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
};
-static struct regulator_ops stpmic1_switch_regul_ops = {
+static const struct regulator_ops stpmic1_boost_regul_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
+static const struct regulator_ops stpmic1_switch_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
#define REG_LDO(ids, base) { \
.name = #ids, \
.id = STPMIC1_##ids, \
@@ -227,8 +208,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -252,8 +231,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.bypass_mask = LDO_BYPASS_MASK, \
.bypass_val_on = LDO_BYPASS_MASK, \
.bypass_val_off = 0, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -271,8 +248,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -312,12 +287,47 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
-#define REG_SWITCH(ids, base, reg, mask, val) { \
+#define REG_BOOST(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_boost_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 0, \
+ .fixed_uV = 5000000, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = BOOST_ENABLED, \
+ .enable_val = BOOST_ENABLED, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .supply_name = #base, \
+}
+
+#define REG_VBUS_OTG(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_switch_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 0, \
+ .fixed_uV = 5000000, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = USBSW_OTG_SWITCH_ENABLED, \
+ .enable_val = USBSW_OTG_SWITCH_ENABLED, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .supply_name = #base, \
+ .active_discharge_reg = BST_SW_CR, \
+ .active_discharge_mask = VBUS_OTG_DISCHARGE, \
+ .active_discharge_on = VBUS_OTG_DISCHARGE, \
+}
+
+#define REG_SW_OUT(ids, base) { \
.name = #ids, \
.id = STPMIC1_##ids, \
.n_voltages = 1, \
@@ -326,15 +336,18 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.owner = THIS_MODULE, \
.min_uV = 0, \
.fixed_uV = 5000000, \
- .enable_reg = (reg), \
- .enable_mask = (mask), \
- .enable_val = (val), \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = SWIN_SWOUT_ENABLED, \
+ .enable_val = SWIN_SWOUT_ENABLED, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.supply_name = #base, \
+ .active_discharge_reg = BST_SW_CR, \
+ .active_discharge_mask = SW_OUT_DISCHARGE, \
+ .active_discharge_on = SW_OUT_DISCHARGE, \
}
-struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
+static const struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
[STPMIC1_BUCK1] = {
.desc = REG_BUCK(BUCK1, buck1),
.icc_reg = BUCKS_ICCTO_CR,
@@ -411,23 +424,17 @@ struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
.mask_reset_mask = BIT(6),
},
[STPMIC1_BOOST] = {
- .desc = REG_SWITCH(BOOST, boost, BST_SW_CR,
- BOOST_ENABLED,
- BOOST_ENABLED),
+ .desc = REG_BOOST(BOOST, boost),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(6),
},
[STPMIC1_VBUS_OTG] = {
- .desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR,
- USBSW_OTG_SWITCH_ENABLED,
- USBSW_OTG_SWITCH_ENABLED),
+ .desc = REG_VBUS_OTG(VBUS_OTG, pwr_sw1),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(4),
},
[STPMIC1_SW_OUT] = {
- .desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR,
- SWIN_SWOUT_ENABLED,
- SWIN_SWOUT_ENABLED),
+ .desc = REG_SW_OUT(SW_OUT, pwr_sw2),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(5),
},
@@ -448,8 +455,9 @@ static unsigned int stpmic1_map_mode(unsigned int mode)
static unsigned int stpmic1_get_mode(struct regulator_dev *rdev)
{
int value;
+ struct regmap *regmap = rdev_get_regmap(rdev);
- regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
+ regmap_read(regmap, rdev->desc->enable_reg, &value);
if (value & STPMIC1_BUCK_MODE_LP)
return REGULATOR_MODE_STANDBY;
@@ -460,6 +468,7 @@ static unsigned int stpmic1_get_mode(struct regulator_dev *rdev)
static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
int value;
+ struct regmap *regmap = rdev_get_regmap(rdev);
switch (mode) {
case REGULATOR_MODE_NORMAL:
@@ -472,17 +481,18 @@ static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode)
return -EINVAL;
}
- return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ return regmap_update_bits(regmap, rdev->desc->enable_reg,
STPMIC1_BUCK_MODE_LP, value);
}
static int stpmic1_set_icc(struct regulator_dev *rdev)
{
- struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
+ struct stpmic1_regulator_cfg *cfg = rdev_get_drvdata(rdev);
+ struct regmap *regmap = rdev_get_regmap(rdev);
/* enable switch off in case of over current */
- return regmap_update_bits(regul->regmap, regul->cfg->icc_reg,
- regul->cfg->icc_mask, regul->cfg->icc_mask);
+ return regmap_update_bits(regmap, cfg->icc_reg, cfg->icc_mask,
+ cfg->icc_mask);
}
static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
@@ -501,46 +511,13 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static int stpmic1_regulator_init(struct platform_device *pdev,
- struct regulator_dev *rdev)
-{
- struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
- int ret = 0;
-
- /* set mask reset */
- if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) {
- ret = regmap_update_bits(regul->regmap,
- regul->cfg->mask_reset_reg,
- regul->cfg->mask_reset_mask,
- regul->cfg->mask_reset_mask);
- if (ret) {
- dev_err(&pdev->dev, "set mask reset failed\n");
- return ret;
- }
- }
-
- /* setup an irq handler for over-current detection */
- if (regul->irq_curlim > 0) {
- ret = devm_request_threaded_irq(&pdev->dev,
- regul->irq_curlim, NULL,
- stpmic1_curlim_irq_handler,
- IRQF_ONESHOT | IRQF_SHARED,
- pdev->name, rdev);
- if (ret) {
- dev_err(&pdev->dev, "Request IRQ failed\n");
- return ret;
- }
- }
- return 0;
-}
-
#define MATCH(_name, _id) \
[STPMIC1_##_id] = { \
.name = #_name, \
.desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \
}
-static struct of_regulator_match stpmic1_regulators_matches[] = {
+static struct of_regulator_match stpmic1_matches[] = {
MATCH(buck1, BUCK1),
MATCH(buck2, BUCK2),
MATCH(buck3, BUCK3),
@@ -557,94 +534,75 @@ static struct of_regulator_match stpmic1_regulators_matches[] = {
MATCH(pwr_sw2, SW_OUT),
};
-static int stpmic1_regulator_parse_dt(void *driver_data)
-{
- struct stpmic1_regulator *regul =
- (struct stpmic1_regulator *)driver_data;
-
- if (!regul)
- return -EINVAL;
-
- if (of_get_property(regul->reg_node, "st,mask-reset", NULL))
- regul->mask_reset = 1;
-
- regul->irq_curlim = of_irq_get(regul->reg_node, 0);
-
- return 0;
-}
-
-static struct
-regulator_dev *stpmic1_regulator_register(struct platform_device *pdev, int id,
- struct regulator_init_data *init_data,
- struct stpmic1_regulator *regul)
+static int stpmic1_regulator_register(struct platform_device *pdev, int id,
+ struct of_regulator_match *match,
+ const struct stpmic1_regulator_cfg *cfg)
{
struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent);
struct regulator_dev *rdev;
struct regulator_config config = {};
+ int ret = 0;
+ int irq;
config.dev = &pdev->dev;
- config.init_data = init_data;
- config.of_node = stpmic1_regulators_matches[id].of_node;
+ config.init_data = match->init_data;
+ config.of_node = match->of_node;
config.regmap = pmic_dev->regmap;
- config.driver_data = regul;
-
- regul->regul_id = id;
- regul->reg_node = config.of_node;
- regul->cfg = &stpmic1_regulator_cfgs[id];
- regul->regmap = pmic_dev->regmap;
+ config.driver_data = (void *)cfg;
- rdev = devm_regulator_register(&pdev->dev, &regul->cfg->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s regulator\n",
- regul->cfg->desc.name);
+ cfg->desc.name);
+ return PTR_ERR(rdev);
+ }
+
+ /* set mask reset */
+ if (of_get_property(config.of_node, "st,mask-reset", NULL) &&
+ cfg->mask_reset_reg != 0) {
+ ret = regmap_update_bits(pmic_dev->regmap,
+ cfg->mask_reset_reg,
+ cfg->mask_reset_mask,
+ cfg->mask_reset_mask);
+ if (ret) {
+ dev_err(&pdev->dev, "set mask reset failed\n");
+ return ret;
+ }
}
- return rdev;
+ /* setup an irq handler for over-current detection */
+ irq = of_irq_get(config.of_node, 0);
+ if (irq > 0) {
+ ret = devm_request_threaded_irq(&pdev->dev,
+ irq, NULL,
+ stpmic1_curlim_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ pdev->name, rdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Request IRQ failed\n");
+ return ret;
+ }
+ }
+ return 0;
}
static int stpmic1_regulator_probe(struct platform_device *pdev)
{
- struct regulator_dev *rdev;
- struct stpmic1_regulator *regul;
- struct regulator_init_data *init_data;
- struct device_node *np;
int i, ret;
- np = pdev->dev.of_node;
-
- ret = of_regulator_match(&pdev->dev, np,
- stpmic1_regulators_matches,
- ARRAY_SIZE(stpmic1_regulators_matches));
+ ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches,
+ ARRAY_SIZE(stpmic1_matches));
if (ret < 0) {
dev_err(&pdev->dev,
"Error in PMIC regulator device tree node");
return ret;
}
- regul = devm_kzalloc(&pdev->dev, ARRAY_SIZE(stpmic1_regulator_cfgs) *
- sizeof(struct stpmic1_regulator),
- GFP_KERNEL);
- if (!regul)
- return -ENOMEM;
-
for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) {
- /* Parse DT & find regulators to register */
- init_data = stpmic1_regulators_matches[i].init_data;
- if (init_data)
- init_data->regulator_init = &stpmic1_regulator_parse_dt;
-
- rdev = stpmic1_regulator_register(pdev, i, init_data, regul);
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
- ret = stpmic1_regulator_init(pdev, rdev);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to initialize regulator %d\n", ret);
+ ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i],
+ &stpmic1_regulator_cfgs[i]);
+ if (ret < 0)
return ret;
- }
-
- regul++;
}
dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n");
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index 6209beee1018..95708d34876b 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -188,7 +188,8 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
.set_suspend_disable = tps65218_pmic_set_suspend_disable,
};
-static const int ls3_currents[] = { 100, 200, 500, 1000 };
+static const int ls3_currents[] = { 100000, 200000, 500000, 1000000 };
+
static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev,
int lim_uA)
@@ -204,7 +205,8 @@ static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev,
return -EINVAL;
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
- index << 2, TPS65218_PROTECT_L1);
+ index << __builtin_ctz(dev->desc->csel_mask),
+ TPS65218_PROTECT_L1);
}
static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
@@ -214,7 +216,7 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
unsigned int num_currents = ARRAY_SIZE(ls3_currents);
struct tps65218 *tps = rdev_get_drvdata(dev);
- while (index < num_currents && ls3_currents[index] < max_uA)
+ while (index < num_currents && ls3_currents[index] <= max_uA)
index++;
index--;
@@ -223,7 +225,8 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
return -EINVAL;
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
- index << 2, TPS65218_PROTECT_L1);
+ index << __builtin_ctz(dev->desc->csel_mask),
+ TPS65218_PROTECT_L1);
}
static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
@@ -236,12 +239,13 @@ static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
if (retval < 0)
return retval;
- index = (index & dev->desc->csel_mask) >> 2;
+ index = (index & dev->desc->csel_mask) >>
+ __builtin_ctz(dev->desc->csel_mask);
return ls3_currents[index];
}
-static struct regulator_ops tps65218_ls3_ops = {
+static struct regulator_ops tps65218_ls23_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = tps65218_pmic_enable,
.disable = tps65218_pmic_disable,
@@ -303,8 +307,13 @@ static const struct regulator_desc regulators[] = {
TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
2, 0, 0, TPS65218_REG_SEQ6,
TPS65218_SEQ6_LDO1_SEQ_MASK),
+ TPS65218_REGULATOR("LS2", "regulator-ls2", TPS65218_LS_2,
+ REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0,
+ TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS2_EN,
+ TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS2ILIM_MASK,
+ NULL, 0, 0, 0, 0, 0),
TPS65218_REGULATOR("LS3", "regulator-ls3", TPS65218_LS_3,
- REGULATOR_CURRENT, tps65218_ls3_ops, 0, 0, 0,
+ REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0,
TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS3_EN,
TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS3ILIM_MASK,
NULL, 0, 0, 0, 0, 0),
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 884c7505ed91..402ea43c77d1 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -576,14 +576,9 @@ static int twlreg_probe(struct platform_device *pdev)
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
- const struct of_device_id *match;
struct regulator_config config = { };
- match = of_match_device(twl_of_match, &pdev->dev);
- if (!match)
- return -ENODEV;
-
- template = match->data;
+ template = of_device_get_match_data(&pdev->dev);
if (!template)
return -ENODEV;
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
index 219cbd910dbf..15f19df6bc5d 100644
--- a/drivers/regulator/twl6030-regulator.c
+++ b/drivers/regulator/twl6030-regulator.c
@@ -31,9 +31,6 @@ struct twlreg_info {
/* twl resource ID, for resource control state machine */
u8 id;
- /* chip constraints on regulator behavior */
- u16 min_mV;
-
u8 flags;
/* used by regulator core */
@@ -247,32 +244,11 @@ static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
return -ENODEV;
}
-static struct regulator_ops twl6030coresmps_ops = {
+static const struct regulator_ops twl6030coresmps_ops = {
.set_voltage = twl6030coresmps_set_voltage,
.get_voltage = twl6030coresmps_get_voltage,
};
-static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- switch (sel) {
- case 0:
- return 0;
- case 1 ... 24:
- /* Linear mapping from 00000001 to 00011000:
- * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
- */
- return (info->min_mV + 100 * (sel - 1)) * 1000;
- case 25 ... 30:
- return -EINVAL;
- case 31:
- return 2750000;
- default:
- return -EINVAL;
- }
-}
-
static int
twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
@@ -290,8 +266,8 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
return vsel;
}
-static struct regulator_ops twl6030ldo_ops = {
- .list_voltage = twl6030ldo_list_voltage,
+static const struct regulator_ops twl6030ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = twl6030ldo_set_voltage_sel,
.get_voltage_sel = twl6030ldo_get_voltage_sel,
@@ -305,7 +281,7 @@ static struct regulator_ops twl6030ldo_ops = {
.get_status = twl6030reg_get_status,
};
-static struct regulator_ops twl6030fixed_ops = {
+static const struct regulator_ops twl6030fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = twl6030reg_enable,
@@ -496,7 +472,7 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
}
-static struct regulator_ops twlsmps_ops = {
+static const struct regulator_ops twlsmps_ops = {
.list_voltage = twl6030smps_list_voltage,
.map_voltage = twl6030smps_map_voltage,
@@ -513,6 +489,11 @@ static struct regulator_ops twlsmps_ops = {
};
/*----------------------------------------------------------------------*/
+static const struct regulator_linear_range twl6030ldo_linear_range[] = {
+ REGULATOR_LINEAR_RANGE(0, 0, 0, 0),
+ REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000),
+ REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0),
+};
#define TWL6030_ADJUSTABLE_SMPS(label) \
static const struct twlreg_info TWL6030_INFO_##label = { \
@@ -525,28 +506,30 @@ static const struct twlreg_info TWL6030_INFO_##label = { \
}, \
}
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+#define TWL6030_ADJUSTABLE_LDO(label, offset) \
static const struct twlreg_info TWL6030_INFO_##label = { \
.base = offset, \
- .min_mV = min_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
.n_voltages = 32, \
+ .linear_ranges = twl6030ldo_linear_range, \
+ .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
-#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+#define TWL6032_ADJUSTABLE_LDO(label, offset) \
static const struct twlreg_info TWL6032_INFO_##label = { \
.base = offset, \
- .min_mV = min_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6032_REG_##label, \
.n_voltages = 32, \
+ .linear_ranges = twl6030ldo_linear_range, \
+ .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
@@ -557,7 +540,6 @@ static const struct twlreg_info TWL6032_INFO_##label = { \
static const struct twlreg_info TWLFIXED_INFO_##label = { \
.base = offset, \
.id = 0, \
- .min_mV = mVolts, \
.desc = { \
.name = #label, \
.id = TWL6030##_REG_##label, \
@@ -574,7 +556,6 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
static const struct twlreg_info TWLSMPS_INFO_##label = { \
.base = offset, \
- .min_mV = 600, \
.desc = { \
.name = #label, \
.id = TWL6032_REG_##label, \
@@ -592,22 +573,22 @@ static const struct twlreg_info TWLSMPS_INFO_##label = { \
TWL6030_ADJUSTABLE_SMPS(VDD1);
TWL6030_ADJUSTABLE_SMPS(VDD2);
TWL6030_ADJUSTABLE_SMPS(VDD3);
-TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000);
-TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000);
-TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000);
-TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000);
-TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000);
-TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000);
+TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54);
+TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58);
+TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c);
+TWL6030_ADJUSTABLE_LDO(VMMC, 0x68);
+TWL6030_ADJUSTABLE_LDO(VPP, 0x6c);
+TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74);
/* 6025 are renamed compared to 6030 versions */
-TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000);
-TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000);
-TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO2, 0x54);
+TWL6032_ADJUSTABLE_LDO(LDO4, 0x58);
+TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c);
+TWL6032_ADJUSTABLE_LDO(LDO5, 0x68);
+TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c);
+TWL6032_ADJUSTABLE_LDO(LDO7, 0x74);
+TWL6032_ADJUSTABLE_LDO(LDO6, 0x60);
+TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64);
+TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70);
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
@@ -687,14 +668,9 @@ static int twlreg_probe(struct platform_device *pdev)
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
- const struct of_device_id *match;
struct regulator_config config = { };
- match = of_match_device(twl_of_match, &pdev->dev);
- if (!match)
- return -ENODEV;
-
- template = match->data;
+ template = of_device_get_match_data(&pdev->dev);
if (!template)
return -ENODEV;
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c
index abf22acbd13e..9026d5a3e964 100644
--- a/drivers/regulator/uniphier-regulator.c
+++ b/drivers/regulator/uniphier-regulator.c
@@ -32,7 +32,7 @@ struct uniphier_regulator_priv {
const struct uniphier_regulator_soc_data *data;
};
-static struct regulator_ops uniphier_regulator_ops = {
+static const struct regulator_ops uniphier_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -87,8 +87,10 @@ static int uniphier_regulator_probe(struct platform_device *pdev)
}
regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto out_rst_assert;
+ }
config.dev = dev;
config.driver_data = priv;
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 5a5bc4bb08d2..12b422373580 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -205,33 +205,10 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)
* BUCKV specifics
*/
-static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
- unsigned selector)
-{
- if (selector <= 0x8)
- return 600000;
- if (selector <= WM831X_BUCKV_MAX_SELECTOR)
- return 600000 + ((selector - 0x8) * 12500);
- return -EINVAL;
-}
-
-static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- u16 vsel;
-
- if (min_uV < 600000)
- vsel = 0;
- else if (min_uV <= 1800000)
- vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8;
- else
- return -EINVAL;
-
- if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV)
- return -EINVAL;
-
- return vsel;
-}
+static const struct regulator_linear_range wm831x_buckv_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
+ REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),
+};
static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
{
@@ -309,7 +286,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
int vsel;
- vsel = wm831x_buckv_map_voltage(rdev, uV, uV);
+ vsel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (vsel < 0)
return vsel;
@@ -327,52 +304,18 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)
}
/* Current limit options */
-static u16 wm831x_dcdc_ilim[] = {
- 125, 250, 375, 500, 625, 750, 875, 1000
+static const unsigned int wm831x_dcdc_ilim[] = {
+ 125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000
};
-static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2;
- int i;
-
- for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) {
- if ((min_uA <= wm831x_dcdc_ilim[i]) &&
- (wm831x_dcdc_ilim[i] <= max_uA))
- return wm831x_set_bits(wm831x, reg,
- WM831X_DC1_HC_THR_MASK,
- i << WM831X_DC1_HC_THR_SHIFT);
- }
-
- return -EINVAL;
-}
-
-static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2;
- int val;
-
- val = wm831x_reg_read(wm831x, reg);
- if (val < 0)
- return val;
-
- val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT;
- return wm831x_dcdc_ilim[val];
-}
-
static const struct regulator_ops wm831x_buckv_ops = {
.set_voltage_sel = wm831x_buckv_set_voltage_sel,
.get_voltage_sel = wm831x_buckv_get_voltage_sel,
- .list_voltage = wm831x_buckv_list_voltage,
- .map_voltage = wm831x_buckv_map_voltage,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
- .set_current_limit = wm831x_buckv_set_current_limit,
- .get_current_limit = wm831x_buckv_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
@@ -492,10 +435,16 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
dcdc->desc.id = id;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;
+ dcdc->desc.linear_ranges = wm831x_buckv_ranges;
+ dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges);
dcdc->desc.ops = &wm831x_buckv_ops;
dcdc->desc.owner = THIS_MODULE;
dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
dcdc->desc.enable_mask = 1 << id;
+ dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2;
+ dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK;
+ dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim);
+ dcdc->desc.curr_table = wm831x_dcdc_ilim;
ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
if (ret < 0) {
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 183fc42a510a..2d7cd344f3bf 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -153,10 +153,15 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
const bool * ctx,
struct irq_affinity *desc)
{
- int i, ret;
+ int i, ret, queue_idx = 0;
for (i = 0; i < nvqs; ++i) {
- vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
+ if (!names[i]) {
+ vqs[i] = NULL;
+ continue;
+ }
+
+ vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
ret = PTR_ERR(vqs[i]);
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c21da9fe51ec..2c8c23db92fb 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -40,6 +40,14 @@ config RESET_BERLIN
help
This enables the reset controller driver for Marvell Berlin SoCs.
+config RESET_BRCMSTB
+ tristate "Broadcom STB reset controller"
+ depends on ARCH_BRCMSTB || COMPILE_TEST
+ default ARCH_BRCMSTB
+ help
+ This enables the reset controller driver for Broadcom STB SoCs using
+ a SUN_TOP_CTRL_SW_INIT style controller.
+
config RESET_HSDK
bool "Synopsys HSDK Reset Driver"
depends on HAS_IOMEM
@@ -48,9 +56,9 @@ config RESET_HSDK
This enables the reset controller driver for HSDK board.
config RESET_IMX7
- bool "i.MX7 Reset Driver" if COMPILE_TEST
+ bool "i.MX7/8 Reset Driver" if COMPILE_TEST
depends on HAS_IOMEM
- default SOC_IMX7D
+ default SOC_IMX7D || (ARM64 && ARCH_MXC)
select MFD_SYSCON
help
This enables the reset controller driver for i.MX7 SoCs.
@@ -109,7 +117,7 @@ config RESET_QCOM_PDC
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
- default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
+ default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
help
This enables a simple reset controller driver for reset lines that
that can be asserted and deasserted by toggling bits in a contiguous,
@@ -128,6 +136,14 @@ config RESET_STM32MP157
help
This enables the RCC reset controller driver for STM32 MPUs.
+config RESET_SOCFPGA
+ bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
+ default ARCH_SOCFPGA
+ select RESET_SIMPLE
+ help
+ This enables the reset driver for the SoCFPGA ARMv7 platforms. This
+ driver gets initialized early during platform init calls.
+
config RESET_SUNXI
bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
default ARCH_SUNXI
@@ -163,15 +179,15 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block.
-config RESET_UNIPHIER_USB3
- tristate "USB3 reset driver for UniPhier SoCs"
+config RESET_UNIPHIER_GLUE
+ tristate "Reset driver in glue layer for UniPhier SoCs"
depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
default ARCH_UNIPHIER
select RESET_SIMPLE
help
- Support for the USB3 core reset on UniPhier SoCs.
- Say Y if you want to control reset signals provided by
- USB3 glue layer.
+ Support for peripheral core reset included in its own glue layer
+ on UniPhier SoCs. Say Y if you want to control reset signals
+ provided by the glue layer.
config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index d08e8b90046a..61456b8f659c 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
@@ -19,10 +20,12 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
+obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
-obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
+obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
+obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index d1887c0ed5d3..9582efb70025 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -795,3 +795,45 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
return rstc;
}
EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
+
+static int reset_control_get_count_from_lookup(struct device *dev)
+{
+ const struct reset_control_lookup *lookup;
+ const char *dev_id;
+ int count = 0;
+
+ if (!dev)
+ return -EINVAL;
+
+ dev_id = dev_name(dev);
+ mutex_lock(&reset_lookup_mutex);
+
+ list_for_each_entry(lookup, &reset_lookup_list, list) {
+ if (!strcmp(lookup->dev_id, dev_id))
+ count++;
+ }
+
+ mutex_unlock(&reset_lookup_mutex);
+
+ if (count == 0)
+ count = -ENOENT;
+
+ return count;
+}
+
+/**
+ * reset_control_get_count - Count number of resets available with a device
+ *
+ * @dev: device for which to return the number of resets
+ *
+ * Returns positive reset count on success, or error number on failure and
+ * on count being zero.
+ */
+int reset_control_get_count(struct device *dev)
+{
+ if (dev->of_node)
+ return of_reset_control_get_count(dev->of_node);
+
+ return reset_control_get_count_from_lookup(dev);
+}
+EXPORT_SYMBOL_GPL(reset_control_get_count);
diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c
new file mode 100644
index 000000000000..a608f445dad6
--- /dev/null
+++ b/drivers/reset/reset-brcmstb.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Broadcom STB generic reset controller for SW_INIT style reset controller
+ *
+ * Author: Florian Fainelli <f.fainelli@gmail.com>
+ * Copyright (C) 2018 Broadcom
+ */
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/types.h>
+
+struct brcmstb_reset {
+ void __iomem *base;
+ struct reset_controller_dev rcdev;
+};
+
+#define SW_INIT_SET 0x00
+#define SW_INIT_CLEAR 0x04
+#define SW_INIT_STATUS 0x08
+
+#define SW_INIT_BIT(id) BIT((id) & 0x1f)
+#define SW_INIT_BANK(id) ((id) >> 5)
+
+/* A full bank contains extra registers that we are not utilizing but still
+ * qualify as a single bank.
+ */
+#define SW_INIT_BANK_SIZE 0x18
+
+static inline
+struct brcmstb_reset *to_brcmstb(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct brcmstb_reset, rcdev);
+}
+
+static int brcmstb_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = to_brcmstb(rcdev);
+
+ writel_relaxed(SW_INIT_BIT(id), priv->base + off + SW_INIT_SET);
+
+ return 0;
+}
+
+static int brcmstb_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = to_brcmstb(rcdev);
+
+ writel_relaxed(SW_INIT_BIT(id), priv->base + off + SW_INIT_CLEAR);
+ /* Maximum reset delay after de-asserting a line and seeing block
+ * operation is typically 14us for the worst case, build some slack
+ * here.
+ */
+ usleep_range(100, 200);
+
+ return 0;
+}
+
+static int brcmstb_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ unsigned int off = SW_INIT_BANK(id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = to_brcmstb(rcdev);
+
+ return readl_relaxed(priv->base + off + SW_INIT_STATUS) &
+ SW_INIT_BIT(id);
+}
+
+static const struct reset_control_ops brcmstb_reset_ops = {
+ .assert = brcmstb_reset_assert,
+ .deassert = brcmstb_reset_deassert,
+ .status = brcmstb_reset_status,
+};
+
+static int brcmstb_reset_probe(struct platform_device *pdev)
+{
+ struct device *kdev = &pdev->dev;
+ struct brcmstb_reset *priv;
+ struct resource *res;
+
+ priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!IS_ALIGNED(res->start, SW_INIT_BANK_SIZE) ||
+ !IS_ALIGNED(resource_size(res), SW_INIT_BANK_SIZE)) {
+ dev_err(kdev, "incorrect register range\n");
+ return -EINVAL;
+ }
+
+ priv->base = devm_ioremap_resource(kdev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ dev_set_drvdata(kdev, priv);
+
+ priv->rcdev.owner = THIS_MODULE;
+ priv->rcdev.nr_resets = DIV_ROUND_DOWN_ULL(resource_size(res),
+ SW_INIT_BANK_SIZE) * 32;
+ priv->rcdev.ops = &brcmstb_reset_ops;
+ priv->rcdev.of_node = kdev->of_node;
+ /* Use defaults: 1 cell and simple xlate function */
+
+ return devm_reset_controller_register(kdev, &priv->rcdev);
+}
+
+static const struct of_device_id brcmstb_reset_of_match[] = {
+ { .compatible = "brcm,brcmstb-reset" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver brcmstb_reset_driver = {
+ .probe = brcmstb_reset_probe,
+ .driver = {
+ .name = "brcmstb-reset",
+ .of_match_table = brcmstb_reset_of_match,
+ },
+};
+module_platform_driver(brcmstb_reset_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom STB reset controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-hsdk.c b/drivers/reset/reset-hsdk.c
index 8bce391c6943..4c7b8647b49c 100644
--- a/drivers/reset/reset-hsdk.c
+++ b/drivers/reset/reset-hsdk.c
@@ -86,6 +86,7 @@ static int hsdk_reset_reset(struct reset_controller_dev *rcdev,
static const struct reset_control_ops hsdk_reset_ops = {
.reset = hsdk_reset_reset,
+ .deassert = hsdk_reset_reset,
};
static int hsdk_reset_probe(struct platform_device *pdev)
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
index 77911fa8f31d..aed76e33a0a9 100644
--- a/drivers/reset/reset-imx7.c
+++ b/drivers/reset/reset-imx7.c
@@ -17,14 +17,27 @@
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/regmap.h>
#include <dt-bindings/reset/imx7-reset.h>
+#include <dt-bindings/reset/imx8mq-reset.h>
+
+struct imx7_src_signal {
+ unsigned int offset, bit;
+};
+
+struct imx7_src_variant {
+ const struct imx7_src_signal *signals;
+ unsigned int signals_num;
+ struct reset_control_ops ops;
+};
struct imx7_src {
struct reset_controller_dev rcdev;
struct regmap *regmap;
+ const struct imx7_src_signal *signals;
};
enum imx7_src_registers {
@@ -39,9 +52,14 @@ enum imx7_src_registers {
SRC_DDRC_RCR = 0x1000,
};
-struct imx7_src_signal {
- unsigned int offset, bit;
-};
+static int imx7_reset_update(struct imx7_src *imx7src,
+ unsigned long id, unsigned int value)
+{
+ const struct imx7_src_signal *signal = &imx7src->signals[id];
+
+ return regmap_update_bits(imx7src->regmap,
+ signal->offset, signal->bit, value);
+}
static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
[IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
@@ -81,8 +99,8 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct imx7_src *imx7src = to_imx7_src(rcdev);
- const struct imx7_src_signal *signal = &imx7_src_signals[id];
- unsigned int value = assert ? signal->bit : 0;
+ const unsigned int bit = imx7src->signals[id].bit;
+ unsigned int value = assert ? bit : 0;
switch (id) {
case IMX7_RESET_PCIEPHY:
@@ -95,12 +113,11 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
break;
case IMX7_RESET_PCIE_CTRL_APPS_EN:
- value = (assert) ? 0 : signal->bit;
+ value = assert ? 0 : bit;
break;
}
- return regmap_update_bits(imx7src->regmap,
- signal->offset, signal->bit, value);
+ return imx7_reset_update(imx7src, id, value);
}
static int imx7_reset_assert(struct reset_controller_dev *rcdev,
@@ -115,9 +132,133 @@ static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
return imx7_reset_set(rcdev, id, false);
}
-static const struct reset_control_ops imx7_reset_ops = {
- .assert = imx7_reset_assert,
- .deassert = imx7_reset_deassert,
+static const struct imx7_src_variant variant_imx7 = {
+ .signals = imx7_src_signals,
+ .signals_num = ARRAY_SIZE(imx7_src_signals),
+ .ops = {
+ .assert = imx7_reset_assert,
+ .deassert = imx7_reset_deassert,
+ },
+};
+
+enum imx8mq_src_registers {
+ SRC_A53RCR0 = 0x0004,
+ SRC_HDMI_RCR = 0x0030,
+ SRC_DISP_RCR = 0x0034,
+ SRC_GPU_RCR = 0x0040,
+ SRC_VPU_RCR = 0x0044,
+ SRC_PCIE2_RCR = 0x0048,
+ SRC_MIPIPHY1_RCR = 0x004c,
+ SRC_MIPIPHY2_RCR = 0x0050,
+ SRC_DDRC2_RCR = 0x1004,
+};
+
+static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
+ [IMX8MQ_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) },
+ [IMX8MQ_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) },
+ [IMX8MQ_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) },
+ [IMX8MQ_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) },
+ [IMX8MQ_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) },
+ [IMX8MQ_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) },
+ [IMX8MQ_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) },
+ [IMX8MQ_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) },
+ [IMX8MQ_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) },
+ [IMX8MQ_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) },
+ [IMX8MQ_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) },
+ [IMX8MQ_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) },
+ [IMX8MQ_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) },
+ [IMX8MQ_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) },
+ [IMX8MQ_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) },
+ [IMX8MQ_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) },
+ [IMX8MQ_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) },
+ [IMX8MQ_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) },
+ [IMX8MQ_RESET_SW_NON_SCLR_M4C_RST] = { SRC_M4RCR, BIT(0) },
+ [IMX8MQ_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) },
+ [IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
+ [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
+ [IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) },
+ [IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
+ [IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
+ [IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
+ [IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR,
+ BIT(2) | BIT(1) },
+ [IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
+ [IMX8MQ_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
+ [IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
+ [IMX8MQ_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) },
+ [IMX8MQ_RESET_DISP_RESET] = { SRC_DISP_RCR, BIT(0) },
+ [IMX8MQ_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) },
+ [IMX8MQ_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) },
+ [IMX8MQ_RESET_PCIEPHY2] = { SRC_PCIE2_RCR,
+ BIT(2) | BIT(1) },
+ [IMX8MQ_RESET_PCIEPHY2_PERST] = { SRC_PCIE2_RCR, BIT(3) },
+ [IMX8MQ_RESET_PCIE2_CTRL_APPS_EN] = { SRC_PCIE2_RCR, BIT(6) },
+ [IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF] = { SRC_PCIE2_RCR, BIT(11) },
+ [IMX8MQ_RESET_MIPI_CSI1_CORE_RESET] = { SRC_MIPIPHY1_RCR, BIT(0) },
+ [IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET] = { SRC_MIPIPHY1_RCR, BIT(1) },
+ [IMX8MQ_RESET_MIPI_CSI1_ESC_RESET] = { SRC_MIPIPHY1_RCR, BIT(2) },
+ [IMX8MQ_RESET_MIPI_CSI2_CORE_RESET] = { SRC_MIPIPHY2_RCR, BIT(0) },
+ [IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET] = { SRC_MIPIPHY2_RCR, BIT(1) },
+ [IMX8MQ_RESET_MIPI_CSI2_ESC_RESET] = { SRC_MIPIPHY2_RCR, BIT(2) },
+ [IMX8MQ_RESET_DDRC1_PRST] = { SRC_DDRC_RCR, BIT(0) },
+ [IMX8MQ_RESET_DDRC1_CORE_RESET] = { SRC_DDRC_RCR, BIT(1) },
+ [IMX8MQ_RESET_DDRC1_PHY_RESET] = { SRC_DDRC_RCR, BIT(2) },
+ [IMX8MQ_RESET_DDRC2_PHY_RESET] = { SRC_DDRC2_RCR, BIT(0) },
+ [IMX8MQ_RESET_DDRC2_CORE_RESET] = { SRC_DDRC2_RCR, BIT(1) },
+ [IMX8MQ_RESET_DDRC2_PRST] = { SRC_DDRC2_RCR, BIT(2) },
+};
+
+static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct imx7_src *imx7src = to_imx7_src(rcdev);
+ const unsigned int bit = imx7src->signals[id].bit;
+ unsigned int value = assert ? bit : 0;
+
+ switch (id) {
+ case IMX8MQ_RESET_PCIEPHY:
+ case IMX8MQ_RESET_PCIEPHY2: /* fallthrough */
+ /*
+ * wait for more than 10us to release phy g_rst and
+ * btnrst
+ */
+ if (!assert)
+ udelay(10);
+ break;
+
+ case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
+ case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */
+ case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */
+ value = assert ? 0 : bit;
+ break;
+ }
+
+ return imx7_reset_update(imx7src, id, value);
+}
+
+static int imx8mq_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return imx8mq_reset_set(rcdev, id, true);
+}
+
+static int imx8mq_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return imx8mq_reset_set(rcdev, id, false);
+}
+
+static const struct imx7_src_variant variant_imx8mq = {
+ .signals = imx8mq_src_signals,
+ .signals_num = ARRAY_SIZE(imx8mq_src_signals),
+ .ops = {
+ .assert = imx8mq_reset_assert,
+ .deassert = imx8mq_reset_deassert,
+ },
};
static int imx7_reset_probe(struct platform_device *pdev)
@@ -125,11 +266,13 @@ static int imx7_reset_probe(struct platform_device *pdev)
struct imx7_src *imx7src;
struct device *dev = &pdev->dev;
struct regmap_config config = { .name = "src" };
+ const struct imx7_src_variant *variant = of_device_get_match_data(dev);
imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
if (!imx7src)
return -ENOMEM;
+ imx7src->signals = variant->signals;
imx7src->regmap = syscon_node_to_regmap(dev->of_node);
if (IS_ERR(imx7src->regmap)) {
dev_err(dev, "Unable to get imx7-src regmap");
@@ -138,15 +281,16 @@ static int imx7_reset_probe(struct platform_device *pdev)
regmap_attach_dev(dev, imx7src->regmap, &config);
imx7src->rcdev.owner = THIS_MODULE;
- imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
- imx7src->rcdev.ops = &imx7_reset_ops;
+ imx7src->rcdev.nr_resets = variant->signals_num;
+ imx7src->rcdev.ops = &variant->ops;
imx7src->rcdev.of_node = dev->of_node;
return devm_reset_controller_register(dev, &imx7src->rcdev);
}
static const struct of_device_id imx7_reset_dt_ids[] = {
- { .compatible = "fsl,imx7d-src", },
+ { .compatible = "fsl,imx7d-src", .data = &variant_imx7 },
+ { .compatible = "fsl,imx8mq-src", .data = &variant_imx8mq },
{ /* sentinel */ },
};
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index a91107fc9e27..77fbba3100c8 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -109,7 +109,7 @@ struct reset_simple_devdata {
#define SOCFPGA_NR_BANKS 8
static const struct reset_simple_devdata reset_simple_socfpga = {
- .reg_offset = 0x10,
+ .reg_offset = 0x20,
.nr_resets = SOCFPGA_NR_BANKS * 32,
.status_active_low = true,
};
@@ -120,7 +120,8 @@ static const struct reset_simple_devdata reset_simple_active_low = {
};
static const struct of_device_id reset_simple_dt_ids[] = {
- { .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga },
+ { .compatible = "altr,stratix10-rst-mgr",
+ .data = &reset_simple_socfpga },
{ .compatible = "st,stm32-rcc", },
{ .compatible = "allwinner,sun6i-a31-clock-reset",
.data = &reset_simple_active_low },
@@ -166,14 +167,6 @@ static int reset_simple_probe(struct platform_device *pdev)
data->status_active_low = devdata->status_active_low;
}
- if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") &&
- of_property_read_u32(dev->of_node, "altr,modrst-offset",
- &reg_offset)) {
- dev_warn(dev,
- "missing altr,modrst-offset property, assuming 0x%x!\n",
- reg_offset);
- }
-
data->membase += reg_offset;
return devm_reset_controller_register(dev, &data->rcdev);
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
new file mode 100644
index 000000000000..96953992c2bb
--- /dev/null
+++ b/drivers/reset/reset-socfpga.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, Intel Corporation
+ * Copied from reset-sunxi.c
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/reset/socfpga.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "reset-simple.h"
+
+#define SOCFPGA_NR_BANKS 8
+
+static int a10_reset_init(struct device_node *np)
+{
+ struct reset_simple_data *data;
+ struct resource res;
+ resource_size_t size;
+ int ret;
+ u32 reg_offset = 0x10;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ goto err_alloc;
+
+ size = resource_size(&res);
+ if (!request_mem_region(res.start, size, np->name)) {
+ ret = -EBUSY;
+ goto err_alloc;
+ }
+
+ data->membase = ioremap(res.start, size);
+ if (!data->membase) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ if (of_property_read_u32(np, "altr,modrst-offset", &reg_offset))
+ pr_warn("missing altr,modrst-offset property, assuming 0x10\n");
+ data->membase += reg_offset;
+
+ spin_lock_init(&data->lock);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = SOCFPGA_NR_BANKS * 32;
+ data->rcdev.ops = &reset_simple_ops;
+ data->rcdev.of_node = np;
+ data->status_active_low = true;
+
+ return reset_controller_register(&data->rcdev);
+
+err_alloc:
+ kfree(data);
+ return ret;
+};
+
+/*
+ * These are the reset controller we need to initialize early on in
+ * our system, before we can even think of using a regular device
+ * driver for it.
+ * The controllers that we can register through the regular device
+ * model are handled by the simple reset driver directly.
+ */
+static const struct of_device_id socfpga_early_reset_dt_ids[] __initconst = {
+ { .compatible = "altr,rst-mgr", },
+ { /* sentinel */ },
+};
+
+void __init socfpga_reset_init(void)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, socfpga_early_reset_dt_ids)
+ a10_reset_init(np);
+}
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index db9a1a75523f..b06d724d8f21 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -18,6 +18,7 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
+#include <linux/reset/sunxi.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-glue.c
index ffa1b19b594d..a45923f4df6d 100644
--- a/drivers/reset/reset-uniphier-usb3.c
+++ b/drivers/reset/reset-uniphier-glue.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
//
-// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
+// reset-uniphier-glue.c - Glue layer reset driver for UniPhier
// Copyright 2018 Socionext Inc.
// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
@@ -15,24 +15,24 @@
#define MAX_CLKS 2
#define MAX_RSTS 2
-struct uniphier_usb3_reset_soc_data {
+struct uniphier_glue_reset_soc_data {
int nclks;
const char * const *clock_names;
int nrsts;
const char * const *reset_names;
};
-struct uniphier_usb3_reset_priv {
+struct uniphier_glue_reset_priv {
struct clk_bulk_data clk[MAX_CLKS];
struct reset_control *rst[MAX_RSTS];
struct reset_simple_data rdata;
- const struct uniphier_usb3_reset_soc_data *data;
+ const struct uniphier_glue_reset_soc_data *data;
};
-static int uniphier_usb3_reset_probe(struct platform_device *pdev)
+static int uniphier_glue_reset_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct uniphier_usb3_reset_priv *priv;
+ struct uniphier_glue_reset_priv *priv;
struct resource *res;
resource_size_t size;
const char *name;
@@ -100,9 +100,9 @@ out_rst_assert:
return ret;
}
-static int uniphier_usb3_reset_remove(struct platform_device *pdev)
+static int uniphier_glue_reset_remove(struct platform_device *pdev)
{
- struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
+ struct uniphier_glue_reset_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->data->nrsts; i++)
@@ -117,7 +117,7 @@ static const char * const uniphier_pro4_clock_reset_names[] = {
"gio", "link",
};
-static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
+static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = {
.nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
.clock_names = uniphier_pro4_clock_reset_names,
.nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
@@ -128,14 +128,14 @@ static const char * const uniphier_pxs2_clock_reset_names[] = {
"link",
};
-static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
+static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = {
.nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
.clock_names = uniphier_pxs2_clock_reset_names,
.nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
.reset_names = uniphier_pxs2_clock_reset_names,
};
-static const struct of_device_id uniphier_usb3_reset_match[] = {
+static const struct of_device_id uniphier_glue_reset_match[] = {
{
.compatible = "socionext,uniphier-pro4-usb3-reset",
.data = &uniphier_pro4_data,
@@ -152,20 +152,32 @@ static const struct of_device_id uniphier_usb3_reset_match[] = {
.compatible = "socionext,uniphier-pxs3-usb3-reset",
.data = &uniphier_pxs2_data,
},
+ {
+ .compatible = "socionext,uniphier-pro4-ahci-reset",
+ .data = &uniphier_pro4_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs2-ahci-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs3-ahci-reset",
+ .data = &uniphier_pxs2_data,
+ },
{ /* Sentinel */ }
};
-MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
+MODULE_DEVICE_TABLE(of, uniphier_glue_reset_match);
-static struct platform_driver uniphier_usb3_reset_driver = {
- .probe = uniphier_usb3_reset_probe,
- .remove = uniphier_usb3_reset_remove,
+static struct platform_driver uniphier_glue_reset_driver = {
+ .probe = uniphier_glue_reset_probe,
+ .remove = uniphier_glue_reset_remove,
.driver = {
- .name = "uniphier-usb3-reset",
- .of_match_table = uniphier_usb3_reset_match,
+ .name = "uniphier-glue-reset",
+ .of_match_table = uniphier_glue_reset_match,
},
};
-module_platform_driver(uniphier_usb3_reset_driver);
+module_platform_driver(uniphier_glue_reset_driver);
MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
-MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
+MODULE_DESCRIPTION("UniPhier Glue layer reset driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
new file mode 100644
index 000000000000..2ef1f13aa47b
--- /dev/null
+++ b/drivers/reset/reset-zynqmp.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
+#define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START
+
+struct zynqmp_reset_data {
+ struct reset_controller_dev rcdev;
+ const struct zynqmp_eemi_ops *eemi_ops;
+};
+
+static inline struct zynqmp_reset_data *
+to_zynqmp_reset_data(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct zynqmp_reset_data, rcdev);
+}
+
+static int zynqmp_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
+
+ return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
+ PM_RESET_ACTION_ASSERT);
+}
+
+static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
+
+ return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
+ PM_RESET_ACTION_RELEASE);
+}
+
+static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
+ int val, err;
+
+ err = priv->eemi_ops->reset_get_status(ZYNQMP_RESET_ID + id, &val);
+ if (err)
+ return err;
+
+ return val;
+}
+
+static int zynqmp_reset_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
+
+ return priv->eemi_ops->reset_assert(ZYNQMP_RESET_ID + id,
+ PM_RESET_ACTION_PULSE);
+}
+
+static struct reset_control_ops zynqmp_reset_ops = {
+ .reset = zynqmp_reset_reset,
+ .assert = zynqmp_reset_assert,
+ .deassert = zynqmp_reset_deassert,
+ .status = zynqmp_reset_status,
+};
+
+static int zynqmp_reset_probe(struct platform_device *pdev)
+{
+ struct zynqmp_reset_data *priv;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ priv->eemi_ops = zynqmp_pm_get_eemi_ops();
+ if (!priv->eemi_ops)
+ return -ENXIO;
+
+ priv->rcdev.ops = &zynqmp_reset_ops;
+ priv->rcdev.owner = THIS_MODULE;
+ priv->rcdev.of_node = pdev->dev.of_node;
+ priv->rcdev.nr_resets = ZYNQMP_NR_RESETS;
+
+ return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
+}
+
+static const struct of_device_id zynqmp_reset_dt_ids[] = {
+ { .compatible = "xlnx,zynqmp-reset", },
+ { /* sentinel */ },
+};
+
+static struct platform_driver zynqmp_reset_driver = {
+ .probe = zynqmp_reset_probe,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = zynqmp_reset_dt_ids,
+ },
+};
+
+static int __init zynqmp_reset_init(void)
+{
+ return platform_driver_register(&zynqmp_reset_driver);
+}
+
+arch_initcall(zynqmp_reset_init);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 397af07e4d88..e03304fe25bb 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3965,13 +3965,11 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
EXPORT_SYMBOL_GPL(dasd_generic_restore_device);
static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
- void *rdc_buffer,
int rdc_buffer_size,
int magic)
{
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
- unsigned long *idaw;
cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device,
NULL);
@@ -3986,16 +3984,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
ccw = cqr->cpaddr;
ccw->cmd_code = CCW_CMD_RDC;
- if (idal_is_needed(rdc_buffer, rdc_buffer_size)) {
- idaw = (unsigned long *) (cqr->data);
- ccw->cda = (__u32)(addr_t) idaw;
- ccw->flags = CCW_FLAG_IDA;
- idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size);
- } else {
- ccw->cda = (__u32)(addr_t) rdc_buffer;
- ccw->flags = 0;
- }
-
+ ccw->cda = (__u32)(addr_t) cqr->data;
+ ccw->flags = 0;
ccw->count = rdc_buffer_size;
cqr->startdev = device;
cqr->memdev = device;
@@ -4013,12 +4003,13 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, int magic,
int ret;
struct dasd_ccw_req *cqr;
- cqr = dasd_generic_build_rdc(device, rdc_buffer, rdc_buffer_size,
- magic);
+ cqr = dasd_generic_build_rdc(device, rdc_buffer_size, magic);
if (IS_ERR(cqr))
return PTR_ERR(cqr);
ret = dasd_sleep_on(cqr);
+ if (ret == 0)
+ memcpy(rdc_buffer, cqr->data, rdc_buffer_size);
dasd_sfree_request(cqr, cqr->memdev);
return ret;
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 4e7b55a14b1a..6e294b4d3635 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -4469,6 +4469,14 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
usrparm.psf_data &= 0x7fffffffULL;
usrparm.rssd_result &= 0x7fffffffULL;
}
+ /* at least 2 bytes are accessed and should be allocated */
+ if (usrparm.psf_data_len < 2) {
+ DBF_DEV_EVENT(DBF_WARNING, device,
+ "Symmetrix ioctl invalid data length %d",
+ usrparm.psf_data_len);
+ rc = -EINVAL;
+ goto out;
+ }
/* alloc I/O data area */
psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index b3fcc24b1182..367e9d384d85 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -195,7 +195,9 @@ struct read_info_sccb {
u16 hcpua; /* 120-121 */
u8 _pad_122[124 - 122]; /* 122-123 */
u32 hmfai; /* 124-127 */
- u8 _pad_128[4096 - 128]; /* 128-4095 */
+ u8 _pad_128[134 - 128]; /* 128-133 */
+ u8 byte_134; /* 134 */
+ u8 _pad_135[4096 - 135]; /* 135-4095 */
} __packed __aligned(PAGE_SIZE);
struct read_storage_sccb {
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 194ffd5c8580..039b2074db7e 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
static void __ref sclp_cpu_change_notify(struct work_struct *work)
{
+ lock_device_hotplug();
smp_rescan_cpus();
+ unlock_device_hotplug();
}
static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index e792cee3b51c..8332788681c4 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -44,6 +44,8 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
if (sccb->fac91 & 0x40)
S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
+ if (sccb->cpuoff > 134)
+ sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
sclp.rzm <<= 20;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index e324d890a4f6..a59887fad13e 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -181,7 +181,7 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
}
static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
- void **sbals_array, int i)
+ struct qdio_buffer **sbals_array, int i)
{
struct qdio_q *prev;
int j;
@@ -212,8 +212,8 @@ static void setup_queues(struct qdio_irq *irq_ptr,
struct qdio_initialize *qdio_init)
{
struct qdio_q *q;
- void **input_sbal_array = qdio_init->input_sbal_addr_array;
- void **output_sbal_array = qdio_init->output_sbal_addr_array;
+ struct qdio_buffer **input_sbal_array = qdio_init->input_sbal_addr_array;
+ struct qdio_buffer **output_sbal_array = qdio_init->output_sbal_addr_array;
struct qdio_outbuf_state *output_sbal_state_array =
qdio_init->output_sbal_state_array;
int i;
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 70a006ba4d05..384b3987eeb4 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -283,6 +283,33 @@ static long copy_ccw_from_iova(struct channel_program *cp,
#define ccw_is_chain(_ccw) ((_ccw)->flags & (CCW_FLAG_CC | CCW_FLAG_DC))
+/*
+ * is_cpa_within_range()
+ *
+ * @cpa: channel program address being questioned
+ * @head: address of the beginning of a CCW chain
+ * @len: number of CCWs within the chain
+ *
+ * Determine whether the address of a CCW (whether a new chain,
+ * or the target of a TIC) falls within a range (including the end points).
+ *
+ * Returns 1 if yes, 0 if no.
+ */
+static inline int is_cpa_within_range(u32 cpa, u32 head, int len)
+{
+ u32 tail = head + (len - 1) * sizeof(struct ccw1);
+
+ return (head <= cpa && cpa <= tail);
+}
+
+static inline int is_tic_within_range(struct ccw1 *ccw, u32 head, int len)
+{
+ if (!ccw_is_tic(ccw))
+ return 0;
+
+ return is_cpa_within_range(ccw->cda, head, len);
+}
+
static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
{
struct ccwchain *chain;
@@ -392,7 +419,15 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
return -EOPNOTSUPP;
}
- if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))
+ /*
+ * We want to keep counting if the current CCW has the
+ * command-chaining flag enabled, or if it is a TIC CCW
+ * that loops back into the current chain. The latter
+ * is used for device orientation, where the CCW PRIOR to
+ * the TIC can either jump to the TIC or a CCW immediately
+ * after the TIC, depending on the results of its operation.
+ */
+ if (!ccw_is_chain(ccw) && !is_tic_within_range(ccw, iova, cnt))
break;
ccw++;
@@ -408,13 +443,11 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
static int tic_target_chain_exists(struct ccw1 *tic, struct channel_program *cp)
{
struct ccwchain *chain;
- u32 ccw_head, ccw_tail;
+ u32 ccw_head;
list_for_each_entry(chain, &cp->ccwchain_list, next) {
ccw_head = chain->ch_iova;
- ccw_tail = ccw_head + (chain->ch_len - 1) * sizeof(struct ccw1);
-
- if ((ccw_head <= tic->cda) && (tic->cda <= ccw_tail))
+ if (is_cpa_within_range(tic->cda, ccw_head, chain->ch_len))
return 1;
}
@@ -481,13 +514,11 @@ static int ccwchain_fetch_tic(struct ccwchain *chain,
{
struct ccw1 *ccw = chain->ch_ccw + idx;
struct ccwchain *iter;
- u32 ccw_head, ccw_tail;
+ u32 ccw_head;
list_for_each_entry(iter, &cp->ccwchain_list, next) {
ccw_head = iter->ch_iova;
- ccw_tail = ccw_head + (iter->ch_len - 1) * sizeof(struct ccw1);
-
- if ((ccw_head <= ccw->cda) && (ccw->cda <= ccw_tail)) {
+ if (is_cpa_within_range(ccw->cda, ccw_head, iter->ch_len)) {
ccw->cda = (__u32) (addr_t) (((char *)iter->ch_ccw) +
(ccw->cda - ccw_head));
return 0;
@@ -829,7 +860,7 @@ void cp_update_scsw(struct channel_program *cp, union scsw *scsw)
{
struct ccwchain *chain;
u32 cpa = scsw->cmd.cpa;
- u32 ccw_head, ccw_tail;
+ u32 ccw_head;
/*
* LATER:
@@ -839,9 +870,7 @@ void cp_update_scsw(struct channel_program *cp, union scsw *scsw)
*/
list_for_each_entry(chain, &cp->ccwchain_list, next) {
ccw_head = (u32)(u64)chain->ch_ccw;
- ccw_tail = (u32)(u64)(chain->ch_ccw + chain->ch_len - 1);
-
- if ((ccw_head <= cpa) && (cpa <= ccw_tail)) {
+ if (is_cpa_within_range(cpa, ccw_head, chain->ch_len)) {
/*
* (cpa - ccw_head) is the offset value of the host
* physical ccw to its chain head.
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 48ea0004a56d..e15816ff1265 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr)
static inline int ap_test_config_card_id(unsigned int id)
{
if (!ap_configuration) /* QCI not supported */
- return 1;
+ /* only ids 0...3F may be probed */
+ return id < 0x40 ? 1 : 0;
return ap_test_config(ap_configuration->apm, id);
}
@@ -1335,6 +1336,16 @@ static int __match_queue_device_with_qid(struct device *dev, void *data)
}
/*
+ * Helper function to be used with bus_find_dev
+ * matches any queue device with given queue id
+ */
+static int __match_queue_device_with_queue_id(struct device *dev, void *data)
+{
+ return is_queue_dev(dev)
+ && AP_QID_QUEUE(to_ap_queue(dev)->qid) == (int)(long) data;
+}
+
+/*
* Helper function for ap_scan_bus().
* Does the scan bus job for the given adapter id.
*/
@@ -1434,8 +1445,13 @@ static void _ap_scan_bus_adapter(int id)
borked = aq->state == AP_STATE_BORKED;
spin_unlock_bh(&aq->lock);
}
- if (borked) /* Remove broken device */
+ if (borked) {
+ /* Remove broken device */
+ AP_DBF(DBF_DEBUG,
+ "removing broken queue=%02x.%04x\n",
+ id, dom);
device_unregister(dev);
+ }
put_device(dev);
continue;
}
@@ -1505,7 +1521,7 @@ static void ap_scan_bus(struct work_struct *unused)
struct device *dev =
bus_find_device(&ap_bus_type, NULL,
(void *)(long) ap_domain_index,
- __match_queue_device_with_qid);
+ __match_queue_device_with_queue_id);
if (dev)
put_device(dev);
else
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index bfc66e4a9de1..d0059eae5d94 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -91,7 +91,8 @@ enum ap_state {
AP_STATE_WORKING,
AP_STATE_QUEUE_FULL,
AP_STATE_SUSPEND_WAIT,
- AP_STATE_BORKED,
+ AP_STATE_UNBOUND, /* momentary not bound to a driver */
+ AP_STATE_BORKED, /* broken */
NR_AP_STATES
};
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 576ac08777c5..ba261210c6da 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -420,6 +420,10 @@ static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = {
[AP_EVENT_POLL] = ap_sm_suspend_read,
[AP_EVENT_TIMEOUT] = ap_sm_nop,
},
+ [AP_STATE_UNBOUND] = {
+ [AP_EVENT_POLL] = ap_sm_nop,
+ [AP_EVENT_TIMEOUT] = ap_sm_nop,
+ },
[AP_STATE_BORKED] = {
[AP_EVENT_POLL] = ap_sm_nop,
[AP_EVENT_TIMEOUT] = ap_sm_nop,
@@ -725,6 +729,7 @@ static void __ap_flush_queue(struct ap_queue *aq)
ap_msg->rc = -EAGAIN;
ap_msg->receive(aq, ap_msg, NULL);
}
+ aq->queue_count = 0;
}
void ap_flush_queue(struct ap_queue *aq)
@@ -743,7 +748,7 @@ void ap_queue_remove(struct ap_queue *aq)
/* reset with zero, also clears irq registration */
spin_lock_bh(&aq->lock);
ap_zapq(aq->qid);
- aq->state = AP_STATE_BORKED;
+ aq->state = AP_STATE_UNBOUND;
spin_unlock_bh(&aq->lock);
}
EXPORT_SYMBOL(ap_queue_remove);
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index 2f92bbed4bf6..3e85d665c572 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -1079,7 +1079,7 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
rc = mkvp_cache_fetch(cardnr, domain, mkvp);
if (rc)
goto out;
- if (t->mkvp == mkvp[1]) {
+ if (t->mkvp == mkvp[1] && t->mkvp != mkvp[0]) {
DEBUG_DBG("%s secure key has old mkvp\n", __func__);
if (pattributes)
*pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c
index 31c6c847eaca..e9824c35c34f 100644
--- a/drivers/s390/crypto/vfio_ap_drv.c
+++ b/drivers/s390/crypto/vfio_ap_drv.c
@@ -15,7 +15,6 @@
#include "vfio_ap_private.h"
#define VFIO_AP_ROOT_NAME "vfio_ap"
-#define VFIO_AP_DEV_TYPE_NAME "ap_matrix"
#define VFIO_AP_DEV_NAME "matrix"
MODULE_AUTHOR("IBM Corporation");
@@ -24,10 +23,6 @@ MODULE_LICENSE("GPL v2");
static struct ap_driver vfio_ap_drv;
-static struct device_type vfio_ap_dev_type = {
- .name = VFIO_AP_DEV_TYPE_NAME,
-};
-
struct ap_matrix_dev *matrix_dev;
/* Only type 10 adapters (CEX4 and later) are supported
@@ -62,6 +57,22 @@ static void vfio_ap_matrix_dev_release(struct device *dev)
kfree(matrix_dev);
}
+static int matrix_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static struct bus_type matrix_bus = {
+ .name = "matrix",
+ .match = &matrix_bus_match,
+};
+
+static struct device_driver matrix_driver = {
+ .name = "vfio_ap",
+ .bus = &matrix_bus,
+ .suppress_bind_attrs = true,
+};
+
static int vfio_ap_matrix_dev_create(void)
{
int ret;
@@ -71,6 +82,10 @@ static int vfio_ap_matrix_dev_create(void)
if (IS_ERR(root_device))
return PTR_ERR(root_device);
+ ret = bus_register(&matrix_bus);
+ if (ret)
+ goto bus_register_err;
+
matrix_dev = kzalloc(sizeof(*matrix_dev), GFP_KERNEL);
if (!matrix_dev) {
ret = -ENOMEM;
@@ -87,30 +102,41 @@ static int vfio_ap_matrix_dev_create(void)
mutex_init(&matrix_dev->lock);
INIT_LIST_HEAD(&matrix_dev->mdev_list);
- matrix_dev->device.type = &vfio_ap_dev_type;
dev_set_name(&matrix_dev->device, "%s", VFIO_AP_DEV_NAME);
matrix_dev->device.parent = root_device;
+ matrix_dev->device.bus = &matrix_bus;
matrix_dev->device.release = vfio_ap_matrix_dev_release;
- matrix_dev->device.driver = &vfio_ap_drv.driver;
+ matrix_dev->vfio_ap_drv = &vfio_ap_drv;
ret = device_register(&matrix_dev->device);
if (ret)
goto matrix_reg_err;
+ ret = driver_register(&matrix_driver);
+ if (ret)
+ goto matrix_drv_err;
+
return 0;
+matrix_drv_err:
+ device_unregister(&matrix_dev->device);
matrix_reg_err:
put_device(&matrix_dev->device);
matrix_alloc_err:
+ bus_unregister(&matrix_bus);
+bus_register_err:
root_device_unregister(root_device);
-
return ret;
}
static void vfio_ap_matrix_dev_destroy(void)
{
+ struct device *root_device = matrix_dev->device.parent;
+
+ driver_unregister(&matrix_driver);
device_unregister(&matrix_dev->device);
- root_device_unregister(matrix_dev->device.parent);
+ bus_unregister(&matrix_bus);
+ root_device_unregister(root_device);
}
static int __init vfio_ap_init(void)
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 272ef427dcc0..900b9cf20ca5 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -198,8 +198,8 @@ static int vfio_ap_verify_queue_reserved(unsigned long *apid,
qres.apqi = apqi;
qres.reserved = false;
- ret = driver_for_each_device(matrix_dev->device.driver, NULL, &qres,
- vfio_ap_has_queue);
+ ret = driver_for_each_device(&matrix_dev->vfio_ap_drv->driver, NULL,
+ &qres, vfio_ap_has_queue);
if (ret)
return ret;
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 5675492233c7..76b7f98e47e9 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -40,6 +40,7 @@ struct ap_matrix_dev {
struct ap_config_info info;
struct list_head mdev_list;
struct mutex lock;
+ struct ap_driver *vfio_ap_drv;
};
extern struct ap_matrix_dev *matrix_dev;
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index f2d6bbe57a6f..bc55ec316adb 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o
obj-$(CONFIG_LCS) += lcs.o
-qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
+qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_ethtool.o
obj-$(CONFIG_QETH) += qeth.o
qeth_l2-y += qeth_l2_main.o qeth_l2_sys.o
obj-$(CONFIG_QETH_L2) += qeth_l2.o
diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
index dcbf5c857743..3e132592c1fe 100644
--- a/drivers/s390/net/ism_drv.c
+++ b/drivers/s390/net/ism_drv.c
@@ -89,8 +89,8 @@ static int register_sba(struct ism_dev *ism)
dma_addr_t dma_handle;
struct ism_sba *sba;
- sba = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
- &dma_handle, GFP_KERNEL);
+ sba = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+ GFP_KERNEL);
if (!sba)
return -ENOMEM;
@@ -116,8 +116,8 @@ static int register_ieq(struct ism_dev *ism)
dma_addr_t dma_handle;
struct ism_eq *ieq;
- ieq = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
- &dma_handle, GFP_KERNEL);
+ ieq = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+ GFP_KERNEL);
if (!ieq)
return -ENOMEM;
@@ -141,10 +141,13 @@ static int register_ieq(struct ism_dev *ism)
static int unregister_sba(struct ism_dev *ism)
{
+ int ret;
+
if (!ism->sba)
return 0;
- if (ism_cmd_simple(ism, ISM_UNREG_SBA))
+ ret = ism_cmd_simple(ism, ISM_UNREG_SBA);
+ if (ret && ret != ISM_ERROR)
return -EIO;
dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
@@ -158,10 +161,13 @@ static int unregister_sba(struct ism_dev *ism)
static int unregister_ieq(struct ism_dev *ism)
{
+ int ret;
+
if (!ism->ieq)
return 0;
- if (ism_cmd_simple(ism, ISM_UNREG_IEQ))
+ ret = ism_cmd_simple(ism, ISM_UNREG_IEQ);
+ if (ret && ret != ISM_ERROR)
return -EIO;
dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
@@ -234,10 +240,9 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb)
test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
return -EINVAL;
- dmb->cpu_addr = dma_zalloc_coherent(&ism->pdev->dev, dmb->dmb_len,
- &dmb->dma_addr, GFP_KERNEL |
- __GFP_NOWARN | __GFP_NOMEMALLOC |
- __GFP_COMP | __GFP_NORETRY);
+ dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
+ &dmb->dma_addr,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | __GFP_COMP | __GFP_NORETRY);
if (!dmb->cpu_addr)
clear_bit(dmb->sba_idx, ism->sba_bitmap);
@@ -288,7 +293,7 @@ static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)
cmd.request.dmb_tok = dmb->dmb_tok;
ret = ism_cmd(ism, &cmd);
- if (ret)
+ if (ret && ret != ISM_ERROR)
goto out;
ism_free_dmb(ism, dmb);
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 0ee026947f20..c851cf6e01c4 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -18,10 +18,10 @@
#include <linux/in6.h>
#include <linux/bitops.h>
#include <linux/seq_file.h>
-#include <linux/ethtool.h>
#include <linux/hashtable.h>
#include <linux/ip.h>
#include <linux/refcount.h>
+#include <linux/workqueue.h>
#include <net/ipv6.h>
#include <net/if_inet6.h>
@@ -34,6 +34,8 @@
#include <asm/ccwgroup.h>
#include <asm/sysinfo.h>
+#include <uapi/linux/if_link.h>
+
#include "qeth_core_mpc.h"
/**
@@ -112,59 +114,6 @@ static inline u32 qeth_get_device_id(struct ccw_device *cdev)
#define CCW_DEVID(cdev) (qeth_get_device_id(cdev))
#define CARD_DEVID(card) (CCW_DEVID(CARD_RDEV(card)))
-/**
- * card stuff
- */
-struct qeth_perf_stats {
- unsigned int bufs_rec;
- unsigned int bufs_sent;
- unsigned int buf_elements_sent;
-
- unsigned int skbs_sent_pack;
- unsigned int bufs_sent_pack;
-
- unsigned int sc_dp_p;
- unsigned int sc_p_dp;
- /* qdio_cq_handler: number of times called, time spent in */
- __u64 cq_start_time;
- unsigned int cq_cnt;
- unsigned int cq_time;
- /* qdio_input_handler: number of times called, time spent in */
- __u64 inbound_start_time;
- unsigned int inbound_cnt;
- unsigned int inbound_time;
- /* qeth_send_packet: number of times called, time spent in */
- __u64 outbound_start_time;
- unsigned int outbound_cnt;
- unsigned int outbound_time;
- /* qdio_output_handler: number of times called, time spent in */
- __u64 outbound_handler_start_time;
- unsigned int outbound_handler_cnt;
- unsigned int outbound_handler_time;
- /* number of calls to and time spent in do_QDIO for inbound queue */
- __u64 inbound_do_qdio_start_time;
- unsigned int inbound_do_qdio_cnt;
- unsigned int inbound_do_qdio_time;
- /* number of calls to and time spent in do_QDIO for outbound queues */
- __u64 outbound_do_qdio_start_time;
- unsigned int outbound_do_qdio_cnt;
- unsigned int outbound_do_qdio_time;
- unsigned int large_send_bytes;
- unsigned int large_send_cnt;
- unsigned int sg_skbs_sent;
- /* initial values when measuring starts */
- unsigned long initial_rx_packets;
- unsigned long initial_tx_packets;
- /* inbound scatter gather data */
- unsigned int sg_skbs_rx;
- unsigned int sg_frags_rx;
- unsigned int sg_alloc_page_rx;
- unsigned int tx_csum;
- unsigned int tx_lin;
- unsigned int tx_linfail;
- unsigned int rx_csum;
-};
-
/* Routing stuff */
struct qeth_routing_info {
enum qeth_routing_types type;
@@ -494,10 +443,53 @@ enum qeth_out_q_states {
QETH_OUT_Q_LOCKED_FLUSH,
};
+#define QETH_CARD_STAT_ADD(_c, _stat, _val) ((_c)->stats._stat += (_val))
+#define QETH_CARD_STAT_INC(_c, _stat) QETH_CARD_STAT_ADD(_c, _stat, 1)
+
+#define QETH_TXQ_STAT_ADD(_q, _stat, _val) ((_q)->stats._stat += (_val))
+#define QETH_TXQ_STAT_INC(_q, _stat) QETH_TXQ_STAT_ADD(_q, _stat, 1)
+
+struct qeth_card_stats {
+ u64 rx_bufs;
+ u64 rx_skb_csum;
+ u64 rx_sg_skbs;
+ u64 rx_sg_frags;
+ u64 rx_sg_alloc_page;
+
+ /* rtnl_link_stats64 */
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 rx_errors;
+ u64 rx_dropped;
+ u64 rx_multicast;
+ u64 tx_errors;
+};
+
+struct qeth_out_q_stats {
+ u64 bufs;
+ u64 bufs_pack;
+ u64 buf_elements;
+ u64 skbs_pack;
+ u64 skbs_sg;
+ u64 skbs_csum;
+ u64 skbs_tso;
+ u64 skbs_linearized;
+ u64 skbs_linearized_fail;
+ u64 tso_bytes;
+ u64 packing_mode_switch;
+
+ /* rtnl_link_stats64 */
+ u64 tx_packets;
+ u64 tx_bytes;
+ u64 tx_errors;
+ u64 tx_dropped;
+};
+
struct qeth_qdio_out_q {
struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qdio_outbuf_state *bufstates; /* convenience pointer */
+ struct qeth_out_q_stats stats;
int queue_no;
struct qeth_card *card;
atomic_t state;
@@ -527,7 +519,7 @@ struct qeth_qdio_info {
/* output */
int no_out_queues;
- struct qeth_qdio_out_q **out_qs;
+ struct qeth_qdio_out_q *out_qs[QETH_MAX_QUEUES];
struct qdio_outbuf_state *out_bufstates;
/* priority queueing */
@@ -559,8 +551,6 @@ enum qeth_card_states {
CARD_STATE_DOWN,
CARD_STATE_HARDSETUP,
CARD_STATE_SOFTSETUP,
- CARD_STATE_UP,
- CARD_STATE_RECOVER,
};
/**
@@ -594,8 +584,8 @@ struct qeth_channel;
struct qeth_cmd_buffer {
enum qeth_cmd_buffer_state state;
struct qeth_channel *channel;
+ struct qeth_reply *reply;
unsigned char *data;
- int rc;
void (*callback)(struct qeth_card *card, struct qeth_channel *channel,
struct qeth_cmd_buffer *iob);
};
@@ -672,6 +662,7 @@ struct qeth_card_info {
unsigned short chpid;
__u16 func_level;
char mcl_level[QETH_MCL_LENGTH + 1];
+ u8 open_when_online:1;
int guestlan;
int mac_bits;
enum qeth_card_types type;
@@ -701,7 +692,6 @@ struct qeth_card_options {
struct qeth_vnicc_info vnicc; /* VNICC options */
int fake_broadcast;
enum qeth_discipline_id layer;
- int performance_stats;
int rx_sg_cb;
enum qeth_ipa_isolation_modes isolation;
enum qeth_ipa_isolation_modes prev_isolation;
@@ -741,11 +731,6 @@ struct qeth_discipline {
struct qeth_ipa_cmd *cmd);
};
-struct qeth_vlan_vid {
- struct list_head list;
- unsigned short vid;
-};
-
enum qeth_addr_disposition {
QETH_DISP_ADDR_DELETE = 0,
QETH_DISP_ADDR_DO_NOTHING = 1,
@@ -782,18 +767,16 @@ struct qeth_card {
struct qeth_channel data;
struct net_device *dev;
- struct net_device_stats stats;
-
+ struct qeth_card_stats stats;
struct qeth_card_info info;
struct qeth_token token;
struct qeth_seqno seqno;
struct qeth_card_options options;
+ struct workqueue_struct *event_wq;
wait_queue_head_t wait_q;
spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- struct mutex vid_list_mutex; /* vid_list */
- struct list_head vid_list;
DECLARE_HASHTABLE(mac_htable, 4);
DECLARE_HASHTABLE(ip_htable, 4);
DECLARE_HASHTABLE(ip_mc_htable, 4);
@@ -802,13 +785,11 @@ struct qeth_card {
unsigned long thread_start_mask;
unsigned long thread_allowed_mask;
unsigned long thread_running_mask;
- struct task_struct *recovery_task;
spinlock_t ip_lock;
struct qeth_ipato ipato;
struct list_head cmd_waiter_list;
/* QDIO buffer handling */
struct qeth_qdio_info qdio;
- struct qeth_perf_stats perf_stats;
int read_or_write_problem;
struct qeth_osn_info osn_info;
struct qeth_discipline *discipline;
@@ -825,6 +806,11 @@ struct qeth_card {
struct work_struct close_dev_work;
};
+static inline bool qeth_card_hw_is_reachable(struct qeth_card *card)
+{
+ return card->state == CARD_STATE_SOFTSETUP;
+}
+
struct qeth_trap_id {
__u16 lparnr;
char vmname[8];
@@ -865,11 +851,6 @@ static inline int qeth_get_elements_for_range(addr_t start, addr_t end)
return PFN_UP(end) - PFN_DOWN(start);
}
-static inline int qeth_get_micros(void)
-{
- return (int) (get_tod_clock() >> 12);
-}
-
static inline int qeth_get_ip_version(struct sk_buff *skb)
{
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
@@ -894,8 +875,7 @@ static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb,
if ((card->dev->features & NETIF_F_RXCSUM) &&
(flags & QETH_HDR_EXT_CSUM_TRANSP_REQ)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
- if (card->options.performance_stats)
- card->perf_stats.rx_csum++;
+ QETH_CARD_STAT_INC(card, rx_skb_csum);
} else {
skb->ip_summed = CHECKSUM_NONE;
}
@@ -957,14 +937,14 @@ static inline struct qeth_qdio_out_q *qeth_get_tx_queue(struct qeth_card *card,
extern struct qeth_discipline qeth_l2_discipline;
extern struct qeth_discipline qeth_l3_discipline;
+extern const struct ethtool_ops qeth_ethtool_ops;
+extern const struct ethtool_ops qeth_osn_ethtool_ops;
extern const struct attribute_group *qeth_generic_attr_groups[];
extern const struct attribute_group *qeth_osn_attr_groups[];
extern const struct attribute_group qeth_device_attr_group;
extern const struct attribute_group qeth_device_blkt_group;
extern const struct device_type qeth_generic_devtype;
-extern struct workqueue_struct *qeth_wq;
-int qeth_card_hw_is_reachable(struct qeth_card *);
const char *qeth_get_cardname_short(struct qeth_card *);
int qeth_realloc_buffer_pool(struct qeth_card *, int);
int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
@@ -976,11 +956,8 @@ extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
struct net_device *qeth_clone_netdev(struct net_device *orig);
struct qeth_card *qeth_get_card_by_busid(char *bus_id);
-void qeth_set_recovery_task(struct qeth_card *);
-void qeth_clear_recovery_task(struct qeth_card *);
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
int qeth_threads_running(struct qeth_card *, unsigned long);
-int qeth_wait_for_threads(struct qeth_card *, unsigned long);
int qeth_do_run_thread(struct qeth_card *, unsigned long);
void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
@@ -1004,38 +981,29 @@ void qeth_clear_working_pool_list(struct qeth_card *);
void qeth_clear_cmd_buffers(struct qeth_channel *);
void qeth_clear_qdio_buffers(struct qeth_card *);
void qeth_setadp_promisc_mode(struct qeth_card *);
-struct net_device_stats *qeth_get_stats(struct net_device *);
int qeth_setadpparms_change_macaddr(struct qeth_card *);
void qeth_tx_timeout(struct net_device *);
void qeth_prepare_control_data(struct qeth_card *, int,
struct qeth_cmd_buffer *);
void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *);
-void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob);
+void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ u16 cmd_length);
struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
-int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
- int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
- void *reply_param);
+int qeth_query_card_info(struct qeth_card *card,
+ struct carrier_info *carrier_info);
unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
unsigned int offset, unsigned int hd_len,
int elements_needed);
int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int qeth_core_get_sset_count(struct net_device *, int);
-void qeth_core_get_ethtool_stats(struct net_device *,
- struct ethtool_stats *, u64 *);
-void qeth_core_get_strings(struct net_device *, u32, u8 *);
-void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
-int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd);
int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
void qeth_trace_features(struct qeth_card *);
-void qeth_close_dev(struct qeth_card *);
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
enum qeth_ipa_funcs,
@@ -1047,11 +1015,16 @@ netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
netdev_features_t qeth_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features);
+void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
+int qeth_open(struct net_device *dev);
+int qeth_stop(struct net_device *dev);
+
int qeth_vm_request_mac(struct qeth_card *card);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
- void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr,
- struct sk_buff *skb, int ipv, int cast_type,
+ void (*fill_header)(struct qeth_qdio_out_q *queue,
+ struct qeth_hdr *hdr, struct sk_buff *skb,
+ int ipv, int cast_type,
unsigned int data_len));
/* exports for OSN */
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e63e03143ca7..197b0f5b63e7 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -74,35 +74,15 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
-struct workqueue_struct *qeth_wq;
-EXPORT_SYMBOL_GPL(qeth_wq);
-
-int qeth_card_hw_is_reachable(struct qeth_card *card)
-{
- return (card->state == CARD_STATE_SOFTSETUP) ||
- (card->state == CARD_STATE_UP);
-}
-EXPORT_SYMBOL_GPL(qeth_card_hw_is_reachable);
-
static void qeth_close_dev_handler(struct work_struct *work)
{
struct qeth_card *card;
card = container_of(work, struct qeth_card, close_dev_work);
QETH_CARD_TEXT(card, 2, "cldevhdl");
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
ccwgroup_set_offline(card->gdev);
}
-void qeth_close_dev(struct qeth_card *card)
-{
- QETH_CARD_TEXT(card, 2, "cldevsubm");
- queue_work(qeth_wq, &card->close_dev_work);
-}
-EXPORT_SYMBOL_GPL(qeth_close_dev);
-
static const char *qeth_get_cardname(struct qeth_card *card)
{
if (card->info.guestlan) {
@@ -193,23 +173,6 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
return "n/a";
}
-void qeth_set_recovery_task(struct qeth_card *card)
-{
- card->recovery_task = current;
-}
-EXPORT_SYMBOL_GPL(qeth_set_recovery_task);
-
-void qeth_clear_recovery_task(struct qeth_card *card)
-{
- card->recovery_task = NULL;
-}
-EXPORT_SYMBOL_GPL(qeth_clear_recovery_task);
-
-static bool qeth_is_recovery_task(const struct qeth_card *card)
-{
- return card->recovery_task == current;
-}
-
void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
int clear_start_mask)
{
@@ -236,15 +199,6 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads)
}
EXPORT_SYMBOL_GPL(qeth_threads_running);
-int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
-{
- if (qeth_is_recovery_task(card))
- return 0;
- return wait_event_interruptible(card->wait_q,
- qeth_threads_running(card, threads) == 0);
-}
-EXPORT_SYMBOL_GPL(qeth_wait_for_threads);
-
void qeth_clear_working_pool_list(struct qeth_card *card)
{
struct qeth_buffer_pool_entry *pool_entry, *tmp;
@@ -292,8 +246,7 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
{
QETH_CARD_TEXT(card, 2, "realcbp");
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
+ if (card->state != CARD_STATE_DOWN)
return -EPERM;
/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
@@ -566,6 +519,7 @@ static int __qeth_issue_next_read(struct qeth_card *card)
QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0);
+ qeth_release_buffer(channel, iob);
card->read_or_write_problem = 1;
qeth_schedule_recovery(card);
wake_up(&card->wait_q);
@@ -592,6 +546,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
if (reply) {
refcount_set(&reply->refcnt, 1);
atomic_set(&reply->received, 0);
+ init_waitqueue_head(&reply->wait_q);
}
return reply;
}
@@ -607,6 +562,26 @@ static void qeth_put_reply(struct qeth_reply *reply)
kfree(reply);
}
+static void qeth_enqueue_reply(struct qeth_card *card, struct qeth_reply *reply)
+{
+ spin_lock_irq(&card->lock);
+ list_add_tail(&reply->list, &card->cmd_waiter_list);
+ spin_unlock_irq(&card->lock);
+}
+
+static void qeth_dequeue_reply(struct qeth_card *card, struct qeth_reply *reply)
+{
+ spin_lock_irq(&card->lock);
+ list_del(&reply->list);
+ spin_unlock_irq(&card->lock);
+}
+
+static void qeth_notify_reply(struct qeth_reply *reply)
+{
+ atomic_inc(&reply->received);
+ wake_up(&reply->wait_q);
+}
+
static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
struct qeth_card *card)
{
@@ -644,7 +619,7 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
dev_err(&card->gdev->dev,
"Interface %s is down because the adjacent port is no longer in reflective relay mode\n",
QETH_CARD_IFNAME(card));
- qeth_close_dev(card);
+ schedule_work(&card->close_dev_work);
} else {
dev_warn(&card->gdev->dev,
"The link for interface %s on CHPID 0x%X failed\n",
@@ -683,19 +658,15 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
void qeth_clear_ipacmd_list(struct qeth_card *card)
{
- struct qeth_reply *reply, *r;
+ struct qeth_reply *reply;
unsigned long flags;
QETH_CARD_TEXT(card, 4, "clipalst");
spin_lock_irqsave(&card->lock, flags);
- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
- qeth_get_reply(reply);
+ list_for_each_entry(reply, &card->cmd_waiter_list, list) {
reply->rc = -EIO;
- atomic_inc(&reply->received);
- list_del_init(&reply->list);
- wake_up(&reply->wait_q);
- qeth_put_reply(reply);
+ qeth_notify_reply(reply);
}
spin_unlock_irqrestore(&card->lock, flags);
}
@@ -752,7 +723,10 @@ void qeth_release_buffer(struct qeth_channel *channel,
spin_lock_irqsave(&channel->iob_lock, flags);
iob->state = BUF_STATE_FREE;
iob->callback = qeth_send_control_data_cb;
- iob->rc = 0;
+ if (iob->reply) {
+ qeth_put_reply(iob->reply);
+ iob->reply = NULL;
+ }
spin_unlock_irqrestore(&channel->iob_lock, flags);
wake_up(&channel->wait_q);
}
@@ -765,6 +739,17 @@ static void qeth_release_buffer_cb(struct qeth_card *card,
qeth_release_buffer(channel, iob);
}
+static void qeth_cancel_cmd(struct qeth_cmd_buffer *iob, int rc)
+{
+ struct qeth_reply *reply = iob->reply;
+
+ if (reply) {
+ reply->rc = rc;
+ qeth_notify_reply(reply);
+ }
+ qeth_release_buffer(iob->channel, iob);
+}
+
static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
{
struct qeth_cmd_buffer *buffer = NULL;
@@ -800,9 +785,9 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
struct qeth_cmd_buffer *iob)
{
struct qeth_ipa_cmd *cmd = NULL;
- struct qeth_reply *reply, *r;
+ struct qeth_reply *reply = NULL;
+ struct qeth_reply *r;
unsigned long flags;
- int keep_reply;
int rc = 0;
QETH_CARD_TEXT(card, 4, "sndctlcb");
@@ -834,44 +819,40 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
goto out;
}
+ /* match against pending cmd requests */
spin_lock_irqsave(&card->lock, flags);
- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
- if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
- ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
+ list_for_each_entry(r, &card->cmd_waiter_list, list) {
+ if ((r->seqno == QETH_IDX_COMMAND_SEQNO) ||
+ (cmd && (r->seqno == cmd->hdr.seqno))) {
+ reply = r;
+ /* take the object outside the lock */
qeth_get_reply(reply);
- list_del_init(&reply->list);
- spin_unlock_irqrestore(&card->lock, flags);
- keep_reply = 0;
- if (reply->callback != NULL) {
- if (cmd) {
- reply->offset = (__u16)((char *)cmd -
- (char *)iob->data);
- keep_reply = reply->callback(card,
- reply,
- (unsigned long)cmd);
- } else
- keep_reply = reply->callback(card,
- reply,
- (unsigned long)iob);
- }
- if (cmd)
- reply->rc = (u16) cmd->hdr.return_code;
- else if (iob->rc)
- reply->rc = iob->rc;
- if (keep_reply) {
- spin_lock_irqsave(&card->lock, flags);
- list_add_tail(&reply->list,
- &card->cmd_waiter_list);
- spin_unlock_irqrestore(&card->lock, flags);
- } else {
- atomic_inc(&reply->received);
- wake_up(&reply->wait_q);
- }
- qeth_put_reply(reply);
- goto out;
+ break;
}
}
spin_unlock_irqrestore(&card->lock, flags);
+
+ if (!reply)
+ goto out;
+
+ if (!reply->callback) {
+ rc = 0;
+ } else {
+ if (cmd) {
+ reply->offset = (u16)((char *)cmd - (char *)iob->data);
+ rc = reply->callback(card, reply, (unsigned long)cmd);
+ } else {
+ rc = reply->callback(card, reply, (unsigned long)iob);
+ }
+ }
+
+ if (rc <= 0) {
+ reply->rc = rc;
+ qeth_notify_reply(reply);
+ }
+
+ qeth_put_reply(reply);
+
out:
memcpy(&card->seqno.pdu_hdr_ack,
QETH_PDU_HEADER_SEQ_NO(iob->data),
@@ -1002,9 +983,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev,
return 0;
}
-static long qeth_check_irb_error(struct qeth_card *card,
- struct ccw_device *cdev, unsigned long intparm,
- struct irb *irb)
+static int qeth_check_irb_error(struct qeth_card *card, struct ccw_device *cdev,
+ unsigned long intparm, struct irb *irb)
{
if (!IS_ERR(irb))
return 0;
@@ -1015,7 +995,7 @@ static long qeth_check_irb_error(struct qeth_card *card,
CCW_DEVID(cdev));
QETH_CARD_TEXT(card, 2, "ckirberr");
QETH_CARD_TEXT_(card, 2, " rc%d", -EIO);
- break;
+ return -EIO;
case -ETIMEDOUT:
dev_warn(&cdev->dev, "A hardware operation timed out"
" on the device\n");
@@ -1027,14 +1007,14 @@ static long qeth_check_irb_error(struct qeth_card *card,
wake_up(&card->wait_q);
}
}
- break;
+ return -ETIMEDOUT;
default:
QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n",
PTR_ERR(irb), CCW_DEVID(cdev));
QETH_CARD_TEXT(card, 2, "ckirberr");
QETH_CARD_TEXT(card, 2, " rc???");
+ return PTR_ERR(irb);
}
- return PTR_ERR(irb);
}
static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
@@ -1069,10 +1049,11 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
if (qeth_intparm_is_iob(intparm))
iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
- if (qeth_check_irb_error(card, cdev, intparm, irb)) {
+ rc = qeth_check_irb_error(card, cdev, intparm, irb);
+ if (rc) {
/* IO was terminated, free its resources. */
if (iob)
- qeth_release_buffer(iob->channel, iob);
+ qeth_cancel_cmd(iob, rc);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
return;
@@ -1127,6 +1108,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
rc = qeth_get_problem(card, cdev, irb);
if (rc) {
card->read_or_write_problem = 1;
+ if (iob)
+ qeth_cancel_cmd(iob, rc);
qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
goto out;
@@ -1288,7 +1271,6 @@ static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers)
channel->iob[cnt].state = BUF_STATE_FREE;
channel->iob[cnt].channel = channel;
channel->iob[cnt].callback = qeth_send_control_data_cb;
- channel->iob[cnt].rc = 0;
}
if (cnt < QETH_CMD_BUFFER_NO) {
qeth_clean_channel(channel);
@@ -1430,7 +1412,6 @@ static void qeth_setup_card(struct qeth_card *card)
spin_lock_init(&card->thread_mask_lock);
mutex_init(&card->conf_mutex);
mutex_init(&card->discipline_mutex);
- mutex_init(&card->vid_list_mutex);
INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
INIT_LIST_HEAD(&card->cmd_waiter_list);
init_waitqueue_head(&card->wait_q);
@@ -1466,6 +1447,10 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
CARD_RDEV(card) = gdev->cdev[0];
CARD_WDEV(card) = gdev->cdev[1];
CARD_DDEV(card) = gdev->cdev[2];
+
+ card->event_wq = alloc_ordered_workqueue("%s", 0, dev_name(&gdev->dev));
+ if (!card->event_wq)
+ goto out_wq;
if (qeth_setup_channel(&card->read, true))
goto out_ip;
if (qeth_setup_channel(&card->write, true))
@@ -1481,6 +1466,8 @@ out_data:
out_channel:
qeth_clean_channel(&card->read);
out_ip:
+ destroy_workqueue(card->event_wq);
+out_wq:
dev_set_drvdata(&gdev->dev, NULL);
kfree(card);
out:
@@ -1809,6 +1796,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card,
QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
atomic_set(&channel->irq_pending, 0);
+ qeth_release_buffer(channel, iob);
wake_up(&card->wait_q);
return rc;
}
@@ -1878,6 +1866,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
rc);
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
atomic_set(&channel->irq_pending, 0);
+ qeth_release_buffer(channel, iob);
wake_up(&card->wait_q);
return rc;
}
@@ -2008,7 +1997,7 @@ void qeth_prepare_control_data(struct qeth_card *card, int len,
card->seqno.pdu_hdr++;
memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
&card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
- QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
+ QETH_DBF_HEX(CTRL, 2, iob->data, min(len, QETH_DBF_CTRL_LEN));
}
EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
@@ -2025,24 +2014,22 @@ EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
* for the IPA commands.
* @reply_param: private pointer passed to the callback
*
- * Returns the value of the `return_code' field of the response
- * block returned from the hardware, or other error indication.
- * Value of zero indicates successful execution of the command.
- *
* Callback function gets called one or more times, with cb_cmd
* pointing to the response returned by the hardware. Callback
- * function must return non-zero if more reply blocks are expected,
- * and zero if the last or only reply block is received. Callback
- * function can get the value of the reply_param pointer from the
+ * function must return
+ * > 0 if more reply blocks are expected,
+ * 0 if the last or only reply block is received, and
+ * < 0 on error.
+ * Callback function can get the value of the reply_param pointer from the
* field 'param' of the structure qeth_reply.
*/
-int qeth_send_control_data(struct qeth_card *card, int len,
- struct qeth_cmd_buffer *iob,
- int (*reply_cb)(struct qeth_card *cb_card,
- struct qeth_reply *cb_reply,
- unsigned long cb_cmd),
- void *reply_param)
+static int qeth_send_control_data(struct qeth_card *card, int len,
+ struct qeth_cmd_buffer *iob,
+ int (*reply_cb)(struct qeth_card *cb_card,
+ struct qeth_reply *cb_reply,
+ unsigned long cb_cmd),
+ void *reply_param)
{
struct qeth_channel *channel = iob->channel;
int rc;
@@ -2058,12 +2045,15 @@ int qeth_send_control_data(struct qeth_card *card, int len,
}
reply = qeth_alloc_reply(card);
if (!reply) {
+ qeth_release_buffer(channel, iob);
return -ENOMEM;
}
reply->callback = reply_cb;
reply->param = reply_param;
- init_waitqueue_head(&reply->wait_q);
+ /* pairs with qeth_release_buffer(): */
+ qeth_get_reply(reply);
+ iob->reply = reply;
while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ;
@@ -2078,9 +2068,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
}
qeth_prepare_control_data(card, len, iob);
- spin_lock_irq(&card->lock);
- list_add_tail(&reply->list, &card->cmd_waiter_list);
- spin_unlock_irq(&card->lock);
+ qeth_enqueue_reply(card, reply);
timeout = jiffies + event_timeout;
@@ -2093,10 +2081,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
CARD_DEVID(card), rc);
QETH_CARD_TEXT_(card, 2, " err%d", rc);
- spin_lock_irq(&card->lock);
- list_del_init(&reply->list);
+ qeth_dequeue_reply(card, reply);
qeth_put_reply(reply);
- spin_unlock_irq(&card->lock);
qeth_release_buffer(channel, iob);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
@@ -2118,21 +2104,16 @@ int qeth_send_control_data(struct qeth_card *card, int len,
}
}
+ qeth_dequeue_reply(card, reply);
rc = reply->rc;
qeth_put_reply(reply);
return rc;
time_err:
- reply->rc = -ETIME;
- spin_lock_irq(&card->lock);
- list_del_init(&reply->list);
- spin_unlock_irq(&card->lock);
- atomic_inc(&reply->received);
- rc = reply->rc;
+ qeth_dequeue_reply(card, reply);
qeth_put_reply(reply);
- return rc;
+ return -ETIME;
}
-EXPORT_SYMBOL_GPL(qeth_send_control_data);
static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
@@ -2337,9 +2318,8 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
QETH_DBF_TEXT(SETUP, 2, "olmlimit");
dev_err(&card->gdev->dev, "A connection could not be "
"established because of an OLM limit\n");
- iob->rc = -EMLINK;
+ return -EMLINK;
}
- QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
return 0;
}
@@ -2389,11 +2369,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
return 0;
}
-static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
{
if (!q)
return;
+ qeth_clear_outq_buffers(q, 1);
qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
kfree(q);
}
@@ -2432,12 +2413,6 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
goto out_freeinq;
/* outbound */
- card->qdio.out_qs =
- kcalloc(card->qdio.no_out_queues,
- sizeof(struct qeth_qdio_out_q *),
- GFP_KERNEL);
- if (!card->qdio.out_qs)
- goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
if (!card->qdio.out_qs[i])
@@ -2468,12 +2443,9 @@ out_freeoutqbufs:
}
out_freeoutq:
while (i > 0) {
- qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
- qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+ qeth_free_output_queue(card->qdio.out_qs[--i]);
+ card->qdio.out_qs[i] = NULL;
}
- kfree(card->qdio.out_qs);
- card->qdio.out_qs = NULL;
-out_freepool:
qeth_free_buffer_pool(card);
out_freeinq:
qeth_free_qdio_queue(card->qdio.in_q);
@@ -2502,13 +2474,9 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
/* inbound buffer pool */
qeth_free_buffer_pool(card);
/* free outbound qdio_qs */
- if (card->qdio.out_qs) {
- for (i = 0; i < card->qdio.no_out_queues; ++i) {
- qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
- qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
- }
- kfree(card->qdio.out_qs);
- card->qdio.out_qs = NULL;
+ for (i = 0; i < card->qdio.no_out_queues; i++) {
+ qeth_free_output_queue(card->qdio.out_qs[i]);
+ card->qdio.out_qs[i] = NULL;
}
}
@@ -2715,8 +2683,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
} else {
free_page((unsigned long)entry->elements[i]);
entry->elements[i] = page_address(page);
- if (card->options.performance_stats)
- card->perf_stats.sg_alloc_page_rx++;
+ QETH_CARD_STAT_INC(card, rx_sg_alloc_page);
}
}
}
@@ -2835,14 +2802,20 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card,
cmd->hdr.prot_version = prot;
}
-void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob)
+void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ u16 cmd_length)
{
+ u16 total_length = IPA_PDU_HEADER_SIZE + cmd_length;
u8 prot_type = qeth_mpc_select_prot_type(card);
memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2);
memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
+ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &cmd_length, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &cmd_length, 2);
memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
&card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &cmd_length, 2);
}
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
@@ -2853,7 +2826,7 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
iob = qeth_get_buffer(&card->write);
if (iob) {
- qeth_prepare_ipa_cmd(card, iob);
+ qeth_prepare_ipa_cmd(card, iob, sizeof(struct qeth_ipa_cmd));
qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot);
} else {
dev_warn(&card->gdev->dev,
@@ -2866,6 +2839,14 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
}
EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
+static int qeth_send_ipa_cmd_cb(struct qeth_card *card,
+ struct qeth_reply *reply, unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+
+ return (cmd->hdr.return_code) ? -EIO : 0;
+}
+
/**
* qeth_send_ipa_cmd() - send an IPA command
*
@@ -2877,11 +2858,15 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
unsigned long),
void *reply_param)
{
+ u16 length;
int rc;
QETH_CARD_TEXT(card, 4, "sendipa");
- rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
- iob, reply_cb, reply_param);
+
+ if (reply_cb == NULL)
+ reply_cb = qeth_send_ipa_cmd_cb;
+ memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2);
+ rc = qeth_send_control_data(card, length, iob, reply_cb, reply_param);
if (rc == -ETIME) {
qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
@@ -2890,9 +2875,19 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
}
EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
+static int qeth_send_startlan_cb(struct qeth_card *card,
+ struct qeth_reply *reply, unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+
+ if (cmd->hdr.return_code == IPA_RC_LAN_OFFLINE)
+ return -ENETDOWN;
+
+ return (cmd->hdr.return_code) ? -EIO : 0;
+}
+
static int qeth_send_startlan(struct qeth_card *card)
{
- int rc;
struct qeth_cmd_buffer *iob;
QETH_DBF_TEXT(SETUP, 2, "strtlan");
@@ -2900,8 +2895,7 @@ static int qeth_send_startlan(struct qeth_card *card)
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0);
if (!iob)
return -ENOMEM;
- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
- return rc;
+ return qeth_send_ipa_cmd(card, iob, qeth_send_startlan_cb, NULL);
}
static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd)
@@ -2919,7 +2913,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 3, "quyadpcb");
if (qeth_setadpparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
card->info.link_type =
@@ -2974,19 +2968,18 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
cmd = (struct qeth_ipa_cmd *) data;
switch (cmd->hdr.return_code) {
+ case IPA_RC_SUCCESS:
+ break;
case IPA_RC_NOTSUPP:
case IPA_RC_L2_UNSUPPORTED_CMD:
QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
- return 0;
+ return -EOPNOTSUPP;
default:
- if (cmd->hdr.return_code) {
- QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
- CARD_DEVID(card),
- cmd->hdr.return_code);
- return 0;
- }
+ QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
+ CARD_DEVID(card), cmd->hdr.return_code);
+ return -EIO;
}
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
@@ -3024,7 +3017,7 @@ static int qeth_query_switch_attributes_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "qswiatcb");
if (qeth_setadpparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
sw_info = (struct qeth_switch_info *)reply->param;
attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
@@ -3056,15 +3049,15 @@ int qeth_query_switch_attributes(struct qeth_card *card,
static int qeth_query_setdiagass_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct qeth_ipa_cmd *cmd;
- __u16 rc;
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+ u16 rc = cmd->hdr.return_code;
- cmd = (struct qeth_ipa_cmd *)data;
- rc = cmd->hdr.return_code;
- if (rc)
+ if (rc) {
QETH_CARD_TEXT_(card, 2, "diagq:%x", rc);
- else
- card->info.diagass_support = cmd->data.diagass.ext;
+ return -EIO;
+ }
+
+ card->info.diagass_support = cmd->data.diagass.ext;
return 0;
}
@@ -3111,13 +3104,13 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid)
static int qeth_hw_trap_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct qeth_ipa_cmd *cmd;
- __u16 rc;
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+ u16 rc = cmd->hdr.return_code;
- cmd = (struct qeth_ipa_cmd *)data;
- rc = cmd->hdr.return_code;
- if (rc)
+ if (rc) {
QETH_CARD_TEXT_(card, 2, "trapc:%x", rc);
+ return -EIO;
+ }
return 0;
}
@@ -3166,7 +3159,7 @@ static int qeth_check_qdio_errors(struct qeth_card *card,
buf->element[14].sflags);
QETH_CARD_TEXT_(card, 2, " qerr=%X", qdio_error);
if ((buf->element[15].sflags) == 0x12) {
- card->stats.rx_dropped++;
+ QETH_CARD_STAT_INC(card, rx_dropped);
return 0;
} else
return 1;
@@ -3230,17 +3223,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
* 'index') un-requeued -> this buffer is the first buffer that
* will be requeued the next time
*/
- if (card->options.performance_stats) {
- card->perf_stats.inbound_do_qdio_cnt++;
- card->perf_stats.inbound_do_qdio_start_time =
- qeth_get_micros();
- }
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0,
queue->next_buf_to_init, count);
- if (card->options.performance_stats)
- card->perf_stats.inbound_do_qdio_time +=
- qeth_get_micros() -
- card->perf_stats.inbound_do_qdio_start_time;
if (rc) {
QETH_CARD_TEXT(card, 2, "qinberr");
}
@@ -3317,8 +3301,7 @@ static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
>= QETH_HIGH_WATERMARK_PACK){
/* switch non-PACKING -> PACKING */
QETH_CARD_TEXT(queue->card, 6, "np->pack");
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.sc_dp_p++;
+ QETH_TXQ_STAT_INC(queue, packing_mode_switch);
queue->do_pack = 1;
}
}
@@ -3337,8 +3320,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
<= QETH_LOW_WATERMARK_PACK) {
/* switch PACKING -> non-PACKING */
QETH_CARD_TEXT(queue->card, 6, "pack->np");
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.sc_p_dp++;
+ QETH_TXQ_STAT_INC(queue, packing_mode_switch);
queue->do_pack = 0;
return qeth_prep_flush_pack_buffer(queue);
}
@@ -3392,25 +3374,16 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
}
}
+ QETH_TXQ_STAT_ADD(queue, bufs, count);
netif_trans_update(queue->card->dev);
- if (queue->card->options.performance_stats) {
- queue->card->perf_stats.outbound_do_qdio_cnt++;
- queue->card->perf_stats.outbound_do_qdio_start_time =
- qeth_get_micros();
- }
qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
if (atomic_read(&queue->set_pci_flags_count))
qdio_flags |= QDIO_FLAG_PCI_OUT;
atomic_add(count, &queue->used_buffers);
-
rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
queue->queue_no, index, count);
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.outbound_do_qdio_time +=
- qeth_get_micros() -
- queue->card->perf_stats.outbound_do_qdio_start_time;
if (rc) {
- queue->card->stats.tx_errors += count;
+ QETH_TXQ_STAT_ADD(queue, tx_errors, count);
/* ignore temporary SIGA errors without busy condition */
if (rc == -ENOBUFS)
return;
@@ -3425,8 +3398,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
qeth_schedule_recovery(queue->card);
return;
}
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.bufs_sent += count;
}
static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
@@ -3457,10 +3428,8 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
if (!flush_cnt &&
!atomic_read(&queue->set_pci_flags_count))
flush_cnt += qeth_prep_flush_pack_buffer(queue);
- if (queue->card->options.performance_stats &&
- q_was_packing)
- queue->card->perf_stats.bufs_sent_pack +=
- flush_cnt;
+ if (q_was_packing)
+ QETH_TXQ_STAT_ADD(queue, bufs_pack, flush_cnt);
if (flush_cnt)
qeth_flush_buffers(queue, index, flush_cnt);
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
@@ -3490,8 +3459,7 @@ int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
goto out;
}
- if (card->state != CARD_STATE_DOWN &&
- card->state != CARD_STATE_RECOVER) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -1;
goto out;
}
@@ -3515,7 +3483,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
int rc;
if (!qeth_is_cq(card, queue))
- goto out;
+ return;
QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element);
QETH_CARD_TEXT_(card, 5, "qcqhc%d", count);
@@ -3524,12 +3492,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
if (qdio_err) {
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
- goto out;
- }
-
- if (card->options.performance_stats) {
- card->perf_stats.cq_cnt++;
- card->perf_stats.cq_start_time = qeth_get_micros();
+ return;
}
for (i = first_element; i < first_element + count; ++i) {
@@ -3557,16 +3520,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
}
card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ count) % QDIO_MAX_BUFFERS_PER_Q;
-
- netif_wake_queue(card->dev);
-
- if (card->options.performance_stats) {
- int delta_t = qeth_get_micros();
- delta_t -= card->perf_stats.cq_start_time;
- card->perf_stats.cq_time += delta_t;
- }
-out:
- return;
}
static void qeth_qdio_input_handler(struct ccw_device *ccwdev,
@@ -3602,11 +3555,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_schedule_recovery(card);
return;
}
- if (card->options.performance_stats) {
- card->perf_stats.outbound_handler_cnt++;
- card->perf_stats.outbound_handler_start_time =
- qeth_get_micros();
- }
+
for (i = first_element; i < (first_element + count); ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = queue->bufs[bidx];
@@ -3652,9 +3601,6 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_check_outbound_queue(queue);
netif_wake_queue(queue->card->dev);
- if (card->options.performance_stats)
- card->perf_stats.outbound_handler_time += qeth_get_micros() -
- card->perf_stats.outbound_handler_start_time;
}
/* We cannot use outbound queue 3 for unicast packets on HiperSockets */
@@ -3775,11 +3721,12 @@ EXPORT_SYMBOL_GPL(qeth_count_elements);
* The number of needed buffer elements is returned in @elements.
* Error to create the hdr is indicated by returning with < 0.
*/
-static int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
- struct qeth_hdr **hdr, unsigned int hdr_len,
- unsigned int proto_len, unsigned int *elements)
+static int qeth_add_hw_header(struct qeth_qdio_out_q *queue,
+ struct sk_buff *skb, struct qeth_hdr **hdr,
+ unsigned int hdr_len, unsigned int proto_len,
+ unsigned int *elements)
{
- const unsigned int max_elements = QETH_MAX_BUFFER_ELEMENTS(card);
+ const unsigned int max_elements = QETH_MAX_BUFFER_ELEMENTS(queue->card);
const unsigned int contiguous = proto_len ? proto_len : 1;
unsigned int __elements;
addr_t start, end;
@@ -3818,15 +3765,12 @@ check_layout:
}
rc = skb_linearize(skb);
- if (card->options.performance_stats) {
- if (rc)
- card->perf_stats.tx_linfail++;
- else
- card->perf_stats.tx_lin++;
- }
- if (rc)
+ if (rc) {
+ QETH_TXQ_STAT_INC(queue, skbs_linearized_fail);
return rc;
+ }
+ QETH_TXQ_STAT_INC(queue, skbs_linearized);
/* Linearization changed the layout, re-evaluate: */
goto check_layout;
}
@@ -3928,7 +3872,6 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
{
struct qdio_buffer *buffer = buf->buffer;
bool is_first_elem = true;
- int flush_cnt = 0;
__skb_queue_tail(&buf->skb_list, skb);
@@ -3949,24 +3892,21 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
if (!queue->do_pack) {
QETH_CARD_TEXT(queue->card, 6, "fillbfnp");
- /* set state to PRIMED -> will be flushed */
- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
- flush_cnt = 1;
} else {
QETH_CARD_TEXT(queue->card, 6, "fillbfpa");
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.skbs_sent_pack++;
- if (buf->next_element_to_fill >=
- QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
- /*
- * packed buffer if full -> set state PRIMED
- * -> will be flushed
- */
- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
- flush_cnt = 1;
- }
+
+ QETH_TXQ_STAT_INC(queue, skbs_pack);
+ /* If the buffer still has free elements, keep using it. */
+ if (buf->next_element_to_fill <
+ QETH_MAX_BUFFER_ELEMENTS(queue->card))
+ return 0;
}
- return flush_cnt;
+
+ /* flush out the buffer */
+ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ return 1;
}
static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue,
@@ -3982,7 +3922,6 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue,
*/
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
return -EBUSY;
- queue->next_buf_to_fill = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
qeth_flush_buffers(queue, index, 1);
return 0;
@@ -4040,10 +3979,9 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
}
}
}
- tmp = qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
- queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
- QDIO_MAX_BUFFERS_PER_Q;
- flush_count += tmp;
+
+ flush_count += qeth_fill_buffer(queue, buffer, skb, hdr, offset,
+ hd_len);
if (flush_count)
qeth_flush_buffers(queue, start_index, flush_count);
else if (!atomic_read(&queue->set_pci_flags_count))
@@ -4071,8 +4009,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
}
out:
/* at this point the queue is UNLOCKED again */
- if (queue->card->options.performance_stats && do_pack)
- queue->card->perf_stats.bufs_sent_pack += flush_count;
+ if (do_pack)
+ QETH_TXQ_STAT_ADD(queue, bufs_pack, flush_count);
return rc;
}
@@ -4096,8 +4034,9 @@ static void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr,
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
- void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr,
- struct sk_buff *skb, int ipv, int cast_type,
+ void (*fill_header)(struct qeth_qdio_out_q *queue,
+ struct qeth_hdr *hdr, struct sk_buff *skb,
+ int ipv, int cast_type,
unsigned int data_len))
{
unsigned int proto_len, hw_hdr_len;
@@ -4122,7 +4061,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
if (rc)
return rc;
- push_len = qeth_add_hw_header(card, skb, &hdr, hw_hdr_len, proto_len,
+ push_len = qeth_add_hw_header(queue, skb, &hdr, hw_hdr_len, proto_len,
&elements);
if (push_len < 0)
return push_len;
@@ -4132,7 +4071,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
data_offset = push_len + proto_len;
}
memset(hdr, 0, hw_hdr_len);
- fill_header(card, hdr, skb, ipv, cast_type, frame_len);
+ fill_header(queue, hdr, skb, ipv, cast_type, frame_len);
if (is_tso)
qeth_fill_tso_ext((struct qeth_hdr_tso *) hdr,
frame_len - proto_len, skb, proto_len);
@@ -4149,14 +4088,12 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
}
if (!rc) {
- if (card->options.performance_stats) {
- card->perf_stats.buf_elements_sent += elements;
- if (is_sg)
- card->perf_stats.sg_skbs_sent++;
- if (is_tso) {
- card->perf_stats.large_send_bytes += frame_len;
- card->perf_stats.large_send_cnt++;
- }
+ QETH_TXQ_STAT_ADD(queue, buf_elements, elements);
+ if (is_sg)
+ QETH_TXQ_STAT_INC(queue, skbs_sg);
+ if (is_tso) {
+ QETH_TXQ_STAT_INC(queue, skbs_tso);
+ QETH_TXQ_STAT_ADD(queue, tso_bytes, frame_len);
}
} else {
if (!push_len)
@@ -4183,7 +4120,7 @@ static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
setparms->data.mode = SET_PROMISC_MODE_OFF;
}
card->info.promisc_mode = setparms->data.mode;
- return 0;
+ return (cmd->hdr.return_code) ? -EIO : 0;
}
void qeth_setadp_promisc_mode(struct qeth_card *card)
@@ -4215,18 +4152,6 @@ void qeth_setadp_promisc_mode(struct qeth_card *card)
}
EXPORT_SYMBOL_GPL(qeth_setadp_promisc_mode);
-struct net_device_stats *qeth_get_stats(struct net_device *dev)
-{
- struct qeth_card *card;
-
- card = dev->ml_priv;
-
- QETH_CARD_TEXT(card, 5, "getstat");
-
- return &card->stats;
-}
-EXPORT_SYMBOL_GPL(qeth_get_stats);
-
static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
@@ -4235,12 +4160,15 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "chgmaccb");
if (qeth_setadpparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
adp_cmd = &cmd->data.setadapterparms;
+ if (!is_valid_ether_addr(adp_cmd->data.change_addr.addr))
+ return -EADDRNOTAVAIL;
+
if (IS_LAYER2(card) && IS_OSD(card) && !IS_VM_NIC(card) &&
!(adp_cmd->hdr.flags & QETH_SETADP_FLAGS_VIRTUAL_MAC))
- return 0;
+ return -EADDRNOTAVAIL;
ether_addr_copy(card->dev->dev_addr, adp_cmd->data.change_addr.addr);
return 0;
@@ -4279,7 +4207,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "setaccb");
if (cmd->hdr.return_code)
- return 0;
+ return -EIO;
qeth_setadpparms_inspect_rc(cmd);
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
@@ -4353,7 +4281,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
card->options.isolation = card->options.prev_isolation;
break;
}
- return 0;
+ return (cmd->hdr.return_code) ? -EIO : 0;
}
static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
@@ -4417,7 +4345,7 @@ void qeth_tx_timeout(struct net_device *dev)
card = dev->ml_priv;
QETH_CARD_TEXT(card, 4, "txtimeo");
- card->stats.tx_errors++;
+ QETH_CARD_STAT_INC(card, tx_errors);
qeth_schedule_recovery(card);
}
EXPORT_SYMBOL_GPL(qeth_tx_timeout);
@@ -4487,27 +4415,6 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
return rc;
}
-static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,
- struct qeth_cmd_buffer *iob, int len,
- int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
- unsigned long),
- void *reply_param)
-{
- u16 s1, s2;
-
- QETH_CARD_TEXT(card, 4, "sendsnmp");
-
- /* adjust PDU length fields in IPA_PDU_HEADER */
- s1 = (u32) IPA_PDU_HEADER_SIZE + len;
- s2 = (u32) len;
- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
- return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
- reply_cb, reply_param);
-}
-
static int qeth_snmp_command_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long sdata)
{
@@ -4525,13 +4432,13 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
if (cmd->hdr.return_code) {
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
- return 0;
+ return -EIO;
}
if (cmd->data.setadapterparms.hdr.return_code) {
cmd->hdr.return_code =
cmd->data.setadapterparms.hdr.return_code;
QETH_CARD_TEXT_(card, 4, "scer2%x", cmd->hdr.return_code);
- return 0;
+ return -EIO;
}
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
@@ -4546,9 +4453,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
/* check if there is enough room in userspace */
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
- QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM);
- cmd->hdr.return_code = IPA_RC_ENOMEM;
- return 0;
+ QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOSPC);
+ return -ENOSPC;
}
QETH_CARD_TEXT_(card, 4, "snore%i",
cmd->data.setadapterparms.hdr.used_total);
@@ -4613,10 +4519,13 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
rc = -ENOMEM;
goto out;
}
+
+ /* for large requests, fix-up the length fields: */
+ qeth_prepare_ipa_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len);
+
cmd = __ipa_cmd(iob);
memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
- rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
- qeth_snmp_command_cb, (void *)&qinfo);
+ rc = qeth_send_ipa_cmd(card, iob, qeth_snmp_command_cb, &qinfo);
if (rc)
QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n",
CARD_DEVID(card), rc);
@@ -4640,16 +4549,14 @@ static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 3, "qoatcb");
if (qeth_setadpparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
priv = (struct qeth_qoat_priv *)reply->param;
resdatalen = cmd->data.setadapterparms.hdr.cmdlength;
resdata = (char *)data + 28;
- if (resdatalen > (priv->buffer_len - priv->response_len)) {
- cmd->hdr.return_code = IPA_RC_FFFF;
- return 0;
- }
+ if (resdatalen > (priv->buffer_len - priv->response_len))
+ return -ENOSPC;
memcpy((priv->buffer + priv->response_len), resdata,
resdatalen);
@@ -4722,9 +4629,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
if (copy_to_user(udata, &oat_data,
sizeof(struct qeth_query_oat_data)))
rc = -EFAULT;
- } else
- if (rc == IPA_RC_FFFF)
- rc = -EFAULT;
+ }
out_free:
vfree(priv.buffer);
@@ -4741,7 +4646,7 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "qcrdincb");
if (qeth_setadpparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
card_info = &cmd->data.setadapterparms.data.card_info;
carrier_info->card_type = card_info->card_type;
@@ -4750,8 +4655,8 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
return 0;
}
-static int qeth_query_card_info(struct qeth_card *card,
- struct carrier_info *carrier_info)
+int qeth_query_card_info(struct qeth_card *card,
+ struct carrier_info *carrier_info)
{
struct qeth_cmd_buffer *iob;
@@ -4979,8 +4884,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.output_handler = qeth_qdio_output_handler;
init_data.queue_start_poll_array = queue_start_poll;
init_data.int_parm = (unsigned long) card;
- init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
- init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+ init_data.input_sbal_addr_array = in_sbal_ptrs;
+ init_data.output_sbal_addr_array = out_sbal_ptrs;
init_data.output_sbal_state_array = card->qdio.out_bufstates;
init_data.scan_threshold =
(card->info.type == QETH_CARD_TYPE_IQD) ? 1 : 32;
@@ -5028,6 +4933,7 @@ static void qeth_core_free_card(struct qeth_card *card)
qeth_clean_channel(&card->read);
qeth_clean_channel(&card->write);
qeth_clean_channel(&card->data);
+ destroy_workqueue(card->event_wq);
qeth_free_qdio_buffers(card);
unregister_service_level(&card->qeth_service_level);
dev_set_drvdata(&card->gdev->dev, NULL);
@@ -5142,25 +5048,16 @@ retriable:
rc = qeth_send_startlan(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
- if (rc == IPA_RC_LAN_OFFLINE) {
- dev_warn(&card->gdev->dev,
- "The LAN is offline\n");
+ if (rc == -ENETDOWN) {
+ dev_warn(&card->gdev->dev, "The LAN is offline\n");
*carrier_ok = false;
} else {
- rc = -ENODEV;
goto out;
}
} else {
*carrier_ok = true;
}
- if (qeth_netdev_is_registered(card->dev)) {
- if (*carrier_ok)
- netif_carrier_on(card->dev);
- else
- netif_carrier_off(card->dev);
- }
-
card->options.ipa4.supported_funcs = 0;
card->options.ipa6.supported_funcs = 0;
card->options.adp.supported_funcs = 0;
@@ -5306,7 +5203,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "unexeob");
QETH_CARD_HEX(card, 2, buffer, sizeof(void *));
dev_kfree_skb_any(skb);
- card->stats.rx_errors++;
+ QETH_CARD_STAT_INC(card, rx_errors);
return NULL;
}
element++;
@@ -5318,16 +5215,17 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
}
*__element = element;
*__offset = offset;
- if (use_rx_sg && card->options.performance_stats) {
- card->perf_stats.sg_skbs_rx++;
- card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+ if (use_rx_sg) {
+ QETH_CARD_STAT_INC(card, rx_sg_skbs);
+ QETH_CARD_STAT_ADD(card, rx_sg_frags,
+ skb_shinfo(skb)->nr_frags);
}
return skb;
no_mem:
if (net_ratelimit()) {
QETH_CARD_TEXT(card, 2, "noskbmem");
}
- card->stats.rx_dropped++;
+ QETH_CARD_STAT_INC(card, rx_dropped);
return NULL;
}
EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
@@ -5340,11 +5238,6 @@ int qeth_poll(struct napi_struct *napi, int budget)
int done;
int new_budget = budget;
- if (card->options.performance_stats) {
- card->perf_stats.inbound_cnt++;
- card->perf_stats.inbound_start_time = qeth_get_micros();
- }
-
while (1) {
if (!card->rx.b_count) {
card->rx.qdio_err = 0;
@@ -5373,8 +5266,7 @@ int qeth_poll(struct napi_struct *napi, int budget)
done = 1;
if (done) {
- if (card->options.performance_stats)
- card->perf_stats.bufs_rec++;
+ QETH_CARD_STAT_INC(card, rx_bufs);
qeth_put_buffer_pool_entry(card,
buffer->pool_entry);
qeth_queue_input_buffer(card, card->rx.b_index);
@@ -5402,9 +5294,6 @@ int qeth_poll(struct napi_struct *napi, int budget)
if (qdio_start_irq(card->data.ccwdev, 0))
napi_schedule(&card->napi);
out:
- if (card->options.performance_stats)
- card->perf_stats.inbound_time += qeth_get_micros() -
- card->perf_stats.inbound_start_time;
return work_done;
}
EXPORT_SYMBOL_GPL(qeth_poll);
@@ -5424,7 +5313,7 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
struct qeth_ipa_caps *caps = reply->param;
if (qeth_setassparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
caps->supported = cmd->data.setassparms.data.caps.supported;
caps->enabled = cmd->data.setassparms.data.caps.enabled;
@@ -5434,18 +5323,18 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
int qeth_setassparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct qeth_ipa_cmd *cmd;
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
QETH_CARD_TEXT(card, 4, "defadpcb");
- cmd = (struct qeth_ipa_cmd *) data;
- if (cmd->hdr.return_code == 0) {
- cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
- if (cmd->hdr.prot_version == QETH_PROT_IPV4)
- card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
- if (cmd->hdr.prot_version == QETH_PROT_IPV6)
- card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
- }
+ if (cmd->hdr.return_code)
+ return -EIO;
+
+ cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+ if (cmd->hdr.prot_version == QETH_PROT_IPV4)
+ card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+ if (cmd->hdr.prot_version == QETH_PROT_IPV6)
+ card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
return 0;
}
EXPORT_SYMBOL_GPL(qeth_setassparms_cb);
@@ -5691,7 +5580,10 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
SET_NETDEV_DEV(dev, &card->gdev->dev);
netif_carrier_off(dev);
- if (!IS_OSN(card)) {
+ if (IS_OSN(card)) {
+ dev->ethtool_ops = &qeth_osn_ethtool_ops;
+ } else {
+ dev->ethtool_ops = &qeth_ethtool_ops;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->hw_features |= NETIF_F_SG;
dev->vlan_features |= NETIF_F_SG;
@@ -5937,12 +5829,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!card)
return -ENODEV;
- if (!qeth_card_hw_is_reachable(card))
- return -ENODEV;
-
- if (card->info.type == QETH_CARD_TYPE_OSN)
- return -EPERM;
-
switch (cmd) {
case SIOC_QETH_ADP_SET_SNMP_CONTROL:
rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
@@ -5982,454 +5868,91 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
EXPORT_SYMBOL_GPL(qeth_do_ioctl);
-static struct {
- const char str[ETH_GSTRING_LEN];
-} qeth_ethtool_stats_keys[] = {
-/* 0 */{"rx skbs"},
- {"rx buffers"},
- {"tx skbs"},
- {"tx buffers"},
- {"tx skbs no packing"},
- {"tx buffers no packing"},
- {"tx skbs packing"},
- {"tx buffers packing"},
- {"tx sg skbs"},
- {"tx buffer elements"},
-/* 10 */{"rx sg skbs"},
- {"rx sg frags"},
- {"rx sg page allocs"},
- {"tx large kbytes"},
- {"tx large count"},
- {"tx pk state ch n->p"},
- {"tx pk state ch p->n"},
- {"tx pk watermark low"},
- {"tx pk watermark high"},
- {"queue 0 buffer usage"},
-/* 20 */{"queue 1 buffer usage"},
- {"queue 2 buffer usage"},
- {"queue 3 buffer usage"},
- {"rx poll time"},
- {"rx poll count"},
- {"rx do_QDIO time"},
- {"rx do_QDIO count"},
- {"tx handler time"},
- {"tx handler count"},
- {"tx time"},
-/* 30 */{"tx count"},
- {"tx do_QDIO time"},
- {"tx do_QDIO count"},
- {"tx csum"},
- {"tx lin"},
- {"tx linfail"},
- {"cq handler count"},
- {"cq handler time"},
- {"rx csum"}
-};
-
-int qeth_core_get_sset_count(struct net_device *dev, int stringset)
-{
- switch (stringset) {
- case ETH_SS_STATS:
- return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_sset_count);
-
-void qeth_core_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct qeth_card *card = dev->ml_priv;
- data[0] = card->stats.rx_packets -
- card->perf_stats.initial_rx_packets;
- data[1] = card->perf_stats.bufs_rec;
- data[2] = card->stats.tx_packets -
- card->perf_stats.initial_tx_packets;
- data[3] = card->perf_stats.bufs_sent;
- data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
- - card->perf_stats.skbs_sent_pack;
- data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
- data[6] = card->perf_stats.skbs_sent_pack;
- data[7] = card->perf_stats.bufs_sent_pack;
- data[8] = card->perf_stats.sg_skbs_sent;
- data[9] = card->perf_stats.buf_elements_sent;
- data[10] = card->perf_stats.sg_skbs_rx;
- data[11] = card->perf_stats.sg_frags_rx;
- data[12] = card->perf_stats.sg_alloc_page_rx;
- data[13] = (card->perf_stats.large_send_bytes >> 10);
- data[14] = card->perf_stats.large_send_cnt;
- data[15] = card->perf_stats.sc_dp_p;
- data[16] = card->perf_stats.sc_p_dp;
- data[17] = QETH_LOW_WATERMARK_PACK;
- data[18] = QETH_HIGH_WATERMARK_PACK;
- data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
- data[20] = (card->qdio.no_out_queues > 1) ?
- atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
- data[21] = (card->qdio.no_out_queues > 2) ?
- atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
- data[22] = (card->qdio.no_out_queues > 3) ?
- atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
- data[23] = card->perf_stats.inbound_time;
- data[24] = card->perf_stats.inbound_cnt;
- data[25] = card->perf_stats.inbound_do_qdio_time;
- data[26] = card->perf_stats.inbound_do_qdio_cnt;
- data[27] = card->perf_stats.outbound_handler_time;
- data[28] = card->perf_stats.outbound_handler_cnt;
- data[29] = card->perf_stats.outbound_time;
- data[30] = card->perf_stats.outbound_cnt;
- data[31] = card->perf_stats.outbound_do_qdio_time;
- data[32] = card->perf_stats.outbound_do_qdio_cnt;
- data[33] = card->perf_stats.tx_csum;
- data[34] = card->perf_stats.tx_lin;
- data[35] = card->perf_stats.tx_linfail;
- data[36] = card->perf_stats.cq_cnt;
- data[37] = card->perf_stats.cq_time;
- data[38] = card->perf_stats.rx_csum;
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
-
-void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
- switch (stringset) {
- case ETH_SS_STATS:
- memcpy(data, &qeth_ethtool_stats_keys,
- sizeof(qeth_ethtool_stats_keys));
- break;
- default:
- WARN_ON(1);
- break;
- }
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_strings);
-
-void qeth_core_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct qeth_card *card = dev->ml_priv;
-
- strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
- sizeof(info->driver));
- strlcpy(info->version, "1.0", sizeof(info->version));
- strlcpy(info->fw_version, card->info.mcl_level,
- sizeof(info->fw_version));
- snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
- CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
-
-/* Helper function to fill 'advertising' and 'supported' which are the same. */
-/* Autoneg and full-duplex are supported and advertised unconditionally. */
-/* Always advertise and support all speeds up to specified, and only one */
-/* specified port type. */
-static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
- int maxspeed, int porttype)
-{
- ethtool_link_ksettings_zero_link_mode(cmd, supported);
- ethtool_link_ksettings_zero_link_mode(cmd, advertising);
- ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
-
- ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
-
- switch (porttype) {
- case PORT_TP:
- ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
- break;
- case PORT_FIBRE:
- ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
- break;
- default:
- ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
- WARN_ON_ONCE(1);
- }
-
- /* partially does fall through, to also select lower speeds */
- switch (maxspeed) {
- case SPEED_25000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 25000baseSR_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 25000baseSR_Full);
- break;
- case SPEED_10000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10000baseT_Full);
- case SPEED_1000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 1000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 1000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 1000baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 1000baseT_Half);
- case SPEED_100:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 100baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 100baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 100baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 100baseT_Half);
- case SPEED_10:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Half);
- /* end fallthrough */
- break;
- default:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Half);
- WARN_ON_ONCE(1);
- }
-}
-
-int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd)
-{
- struct qeth_card *card = netdev->ml_priv;
- enum qeth_link_types link_type;
- struct carrier_info carrier_info;
- int rc;
-
- if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
- link_type = QETH_LINK_TYPE_10GBIT_ETH;
- else
- link_type = card->info.link_type;
-
- cmd->base.duplex = DUPLEX_FULL;
- cmd->base.autoneg = AUTONEG_ENABLE;
- cmd->base.phy_address = 0;
- cmd->base.mdio_support = 0;
- cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
- cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
-
- switch (link_type) {
- case QETH_LINK_TYPE_FAST_ETH:
- case QETH_LINK_TYPE_LANE_ETH100:
- cmd->base.speed = SPEED_100;
- cmd->base.port = PORT_TP;
- break;
- case QETH_LINK_TYPE_GBIT_ETH:
- case QETH_LINK_TYPE_LANE_ETH1000:
- cmd->base.speed = SPEED_1000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_10GBIT_ETH:
- cmd->base.speed = SPEED_10000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_25GBIT_ETH:
- cmd->base.speed = SPEED_25000;
- cmd->base.port = PORT_FIBRE;
- break;
- default:
- cmd->base.speed = SPEED_10;
- cmd->base.port = PORT_TP;
- }
- qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
-
- /* Check if we can obtain more accurate information. */
- /* If QUERY_CARD_INFO command is not supported or fails, */
- /* just return the heuristics that was filled above. */
- if (!qeth_card_hw_is_reachable(card))
- return -ENODEV;
- rc = qeth_query_card_info(card, &carrier_info);
- if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
- return 0;
- if (rc) /* report error from the hardware operation */
- return rc;
- /* on success, fill in the information got from the hardware */
-
- netdev_dbg(netdev,
- "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
- carrier_info.card_type,
- carrier_info.port_mode,
- carrier_info.port_speed);
-
- /* Update attributes for which we've obtained more authoritative */
- /* information, leave the rest the way they where filled above. */
- switch (carrier_info.card_type) {
- case CARD_INFO_TYPE_1G_COPPER_A:
- case CARD_INFO_TYPE_1G_COPPER_B:
- cmd->base.port = PORT_TP;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_1G_FIBRE_A:
- case CARD_INFO_TYPE_1G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_10G_FIBRE_A:
- case CARD_INFO_TYPE_10G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
- break;
- }
-
- switch (carrier_info.port_mode) {
- case CARD_INFO_PORTM_FULLDUPLEX:
- cmd->base.duplex = DUPLEX_FULL;
- break;
- case CARD_INFO_PORTM_HALFDUPLEX:
- cmd->base.duplex = DUPLEX_HALF;
- break;
- }
-
- switch (carrier_info.port_speed) {
- case CARD_INFO_PORTS_10M:
- cmd->base.speed = SPEED_10;
- break;
- case CARD_INFO_PORTS_100M:
- cmd->base.speed = SPEED_100;
- break;
- case CARD_INFO_PORTS_1G:
- cmd->base.speed = SPEED_1000;
- break;
- case CARD_INFO_PORTS_10G:
- cmd->base.speed = SPEED_10000;
- break;
- case CARD_INFO_PORTS_25G:
- cmd->base.speed = SPEED_25000;
- break;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_link_ksettings);
-
-/* Callback to handle checksum offload command reply from OSA card.
- * Verify that required features have been enabled on the card.
- * Return error in hdr->return_code as this value is checked by caller.
- *
- * Always returns zero to indicate no further messages from the OSA card.
- */
-static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card,
- struct qeth_reply *reply,
- unsigned long data)
+static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply,
+ unsigned long data)
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
- struct qeth_checksum_cmd *chksum_cb =
- (struct qeth_checksum_cmd *)reply->param;
+ u32 *features = reply->param;
- QETH_CARD_TEXT(card, 4, "chkdoccb");
if (qeth_setassparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
- memset(chksum_cb, 0, sizeof(*chksum_cb));
- if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
- chksum_cb->supported =
- cmd->data.setassparms.data.chksum.supported;
- QETH_CARD_TEXT_(card, 3, "strt:%x", chksum_cb->supported);
- }
- if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_ENABLE) {
- chksum_cb->supported =
- cmd->data.setassparms.data.chksum.supported;
- chksum_cb->enabled =
- cmd->data.setassparms.data.chksum.enabled;
- QETH_CARD_TEXT_(card, 3, "supp:%x", chksum_cb->supported);
- QETH_CARD_TEXT_(card, 3, "enab:%x", chksum_cb->enabled);
- }
+ *features = cmd->data.setassparms.data.flags_32bit;
return 0;
}
-/* Send command to OSA card and check results. */
-static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
- enum qeth_ipa_funcs ipa_func,
- __u16 cmd_code, long data,
- struct qeth_checksum_cmd *chksum_cb,
- enum qeth_prot_versions prot)
+static int qeth_set_csum_off(struct qeth_card *card, enum qeth_ipa_funcs cstype,
+ enum qeth_prot_versions prot)
{
- struct qeth_cmd_buffer *iob;
-
- QETH_CARD_TEXT(card, 4, "chkdocmd");
- iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
- sizeof(__u32), prot);
- if (!iob)
- return -ENOMEM;
-
- __ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data;
- return qeth_send_ipa_cmd(card, iob, qeth_ipa_checksum_run_cmd_cb,
- chksum_cb);
+ return qeth_send_simple_setassparms_prot(card, cstype,
+ IPA_CMD_ASS_STOP, 0, prot);
}
-static int qeth_send_checksum_on(struct qeth_card *card, int cstype,
- enum qeth_prot_versions prot)
+static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype,
+ enum qeth_prot_versions prot)
{
u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
- struct qeth_checksum_cmd chksum_cb;
+ struct qeth_cmd_buffer *iob;
+ struct qeth_ipa_caps caps;
+ u32 features;
int rc;
- if (prot == QETH_PROT_IPV4)
+ /* some L3 HW requires combined L3+L4 csum offload: */
+ if (IS_LAYER3(card) && prot == QETH_PROT_IPV4 &&
+ cstype == IPA_OUTBOUND_CHECKSUM)
required_features |= QETH_IPA_CHECKSUM_IP_HDR;
- rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0,
- &chksum_cb, prot);
- if (!rc) {
- if ((required_features & chksum_cb.supported) !=
- required_features)
- rc = -EIO;
- else if (!(QETH_IPA_CHECKSUM_LP2LP & chksum_cb.supported) &&
- cstype == IPA_INBOUND_CHECKSUM)
- dev_warn(&card->gdev->dev,
- "Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n",
- QETH_CARD_IFNAME(card));
- }
- if (rc) {
- qeth_send_simple_setassparms_prot(card, cstype,
- IPA_CMD_ASS_STOP, 0, prot);
- dev_warn(&card->gdev->dev,
- "Starting HW IPv%d checksumming for %s failed, using SW checksumming\n",
- prot, QETH_CARD_IFNAME(card));
+
+ iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_START, 0,
+ prot);
+ if (!iob)
+ return -ENOMEM;
+
+ rc = qeth_send_ipa_cmd(card, iob, qeth_start_csum_cb, &features);
+ if (rc)
return rc;
+
+ if ((required_features & features) != required_features) {
+ qeth_set_csum_off(card, cstype, prot);
+ return -EOPNOTSUPP;
}
- rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE,
- chksum_cb.supported, &chksum_cb,
+
+ iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_ENABLE, 4,
prot);
- if (!rc) {
- if ((required_features & chksum_cb.enabled) !=
- required_features)
- rc = -EIO;
+ if (!iob) {
+ qeth_set_csum_off(card, cstype, prot);
+ return -ENOMEM;
}
+
+ if (features & QETH_IPA_CHECKSUM_LP2LP)
+ required_features |= QETH_IPA_CHECKSUM_LP2LP;
+ __ipa_cmd(iob)->data.setassparms.data.flags_32bit = required_features;
+ rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_get_caps_cb, &caps);
if (rc) {
- qeth_send_simple_setassparms_prot(card, cstype,
- IPA_CMD_ASS_STOP, 0, prot);
- dev_warn(&card->gdev->dev,
- "Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n",
- prot, QETH_CARD_IFNAME(card));
+ qeth_set_csum_off(card, cstype, prot);
return rc;
}
+ if (!qeth_ipa_caps_supported(&caps, required_features) ||
+ !qeth_ipa_caps_enabled(&caps, required_features)) {
+ qeth_set_csum_off(card, cstype, prot);
+ return -EOPNOTSUPP;
+ }
+
dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n",
cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot);
+ if (!qeth_ipa_caps_enabled(&caps, QETH_IPA_CHECKSUM_LP2LP) &&
+ cstype == IPA_OUTBOUND_CHECKSUM)
+ dev_warn(&card->gdev->dev,
+ "Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n",
+ QETH_CARD_IFNAME(card));
return 0;
}
static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype,
enum qeth_prot_versions prot)
{
- int rc = (on) ? qeth_send_checksum_on(card, cstype, prot)
- : qeth_send_simple_setassparms_prot(card, cstype,
- IPA_CMD_ASS_STOP, 0,
- prot);
- return rc ? -EIO : 0;
+ return on ? qeth_set_csum_on(card, cstype, prot) :
+ qeth_set_csum_off(card, cstype, prot);
}
static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
@@ -6439,7 +5962,7 @@ static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
struct qeth_tso_start_data *tso_data = reply->param;
if (qeth_setassparms_inspect_rc(cmd))
- return 0;
+ return -EIO;
tso_data->mss = cmd->data.setassparms.data.tso.mss;
tso_data->supported = cmd->data.setassparms.data.tso.supported;
@@ -6505,10 +6028,7 @@ static int qeth_set_tso_on(struct qeth_card *card,
static int qeth_set_ipa_tso(struct qeth_card *card, bool on,
enum qeth_prot_versions prot)
{
- int rc = on ? qeth_set_tso_on(card, prot) :
- qeth_set_tso_off(card, prot);
-
- return rc ? -EIO : 0;
+ return on ? qeth_set_tso_on(card, prot) : qeth_set_tso_off(card, prot);
}
static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
@@ -6534,8 +6054,6 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
return (rc_ipv6) ? rc_ipv6 : rc_ipv4;
}
-#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
- NETIF_F_IPV6_CSUM | NETIF_F_TSO6)
/**
* qeth_enable_hw_features() - (Re-)Enable HW functions for device features
* @dev: a net_device
@@ -6545,17 +6063,20 @@ void qeth_enable_hw_features(struct net_device *dev)
struct qeth_card *card = dev->ml_priv;
netdev_features_t features;
- rtnl_lock();
features = dev->features;
- /* force-off any feature that needs an IPA sequence.
+ /* force-off any feature that might need an IPA sequence.
* netdev_update_features() will restart them.
*/
- dev->features &= ~QETH_HW_FEATURES;
+ dev->features &= ~dev->hw_features;
+ /* toggle VLAN filter, so that VIDs are re-programmed: */
+ if (IS_LAYER2(card) && IS_VM_NIC(card)) {
+ dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+ dev->wanted_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ }
netdev_update_features(dev);
if (features != dev->features)
dev_warn(&card->gdev->dev,
"Device recovery failed to restore all offload features\n");
- rtnl_unlock();
}
EXPORT_SYMBOL_GPL(qeth_enable_hw_features);
@@ -6624,10 +6145,7 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
features &= ~NETIF_F_TSO;
if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO))
features &= ~NETIF_F_TSO6;
- /* if the card isn't up, remove features that require hw changes */
- if (card->state == CARD_STATE_DOWN ||
- card->state == CARD_STATE_RECOVER)
- features &= ~QETH_HW_FEATURES;
+
QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
return features;
}
@@ -6659,18 +6177,70 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(qeth_features_check);
+void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+ struct qeth_card *card = dev->ml_priv;
+ struct qeth_qdio_out_q *queue;
+ unsigned int i;
+
+ QETH_CARD_TEXT(card, 5, "getstat");
+
+ stats->rx_packets = card->stats.rx_packets;
+ stats->rx_bytes = card->stats.rx_bytes;
+ stats->rx_errors = card->stats.rx_errors;
+ stats->rx_dropped = card->stats.rx_dropped;
+ stats->multicast = card->stats.rx_multicast;
+ stats->tx_errors = card->stats.tx_errors;
+
+ for (i = 0; i < card->qdio.no_out_queues; i++) {
+ queue = card->qdio.out_qs[i];
+
+ stats->tx_packets += queue->stats.tx_packets;
+ stats->tx_bytes += queue->stats.tx_bytes;
+ stats->tx_errors += queue->stats.tx_errors;
+ stats->tx_dropped += queue->stats.tx_dropped;
+ }
+}
+EXPORT_SYMBOL_GPL(qeth_get_stats64);
+
+int qeth_open(struct net_device *dev)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ QETH_CARD_TEXT(card, 4, "qethopen");
+
+ if (qdio_stop_irq(CARD_DDEV(card), 0) < 0)
+ return -EIO;
+
+ card->data.state = CH_STATE_UP;
+ netif_start_queue(dev);
+
+ napi_enable(&card->napi);
+ local_bh_disable();
+ napi_schedule(&card->napi);
+ /* kick-start the NAPI softirq: */
+ local_bh_enable();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_open);
+
+int qeth_stop(struct net_device *dev)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ QETH_CARD_TEXT(card, 4, "qethstop");
+ netif_tx_disable(dev);
+ napi_disable(&card->napi);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_stop);
+
static int __init qeth_core_init(void)
{
int rc;
pr_info("loading core functions\n");
- qeth_wq = create_singlethread_workqueue("qeth_wq");
- if (!qeth_wq) {
- rc = -ENOMEM;
- goto out_err;
- }
-
rc = qeth_register_dbf_views();
if (rc)
goto dbf_err;
@@ -6712,8 +6282,6 @@ slab_err:
register_err:
qeth_unregister_dbf_views();
dbf_err:
- destroy_workqueue(qeth_wq);
-out_err:
pr_err("Initializing the qeth device driver failed\n");
return rc;
}
@@ -6721,7 +6289,6 @@ out_err:
static void __exit qeth_core_exit(void)
{
qeth_clear_dbf_list();
- destroy_workqueue(qeth_wq);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
ccw_driver_unregister(&qeth_ccw_driver);
kmem_cache_destroy(qeth_qdio_outbuf_cache);
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
index 16fc51ad0514..e3f4866c158e 100644
--- a/drivers/s390/net/qeth_core_mpc.c
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -125,24 +125,13 @@ unsigned char DM_ACT[] = {
unsigned char IPA_PDU_HEADER[] = {
0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
- 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
- (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
- (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0xc1, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
- sizeof(struct qeth_ipa_cmd) / 256,
- sizeof(struct qeth_ipa_cmd) % 256,
- 0x00,
- sizeof(struct qeth_ipa_cmd) / 256,
- sizeof(struct qeth_ipa_cmd) % 256,
- 0x05,
- 0x77, 0x77, 0x77, 0x77,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x77, 0x77, 0x77, 0x77,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00,
- sizeof(struct qeth_ipa_cmd) / 256,
- sizeof(struct qeth_ipa_cmd) % 256,
- 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
};
struct ipa_rc_msg {
@@ -212,12 +201,10 @@ static const struct ipa_rc_msg qeth_ipa_rc_msg[] = {
{IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
{IPA_RC_VEPA_TO_VEB_TRANSITION, "Adj. switch disabled port mode RR"},
{IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
- {IPA_RC_ENOMEM, "Memory problem"},
+ /* default for qeth_get_ipa_msg(): */
{IPA_RC_FFFF, "Unknown Error"}
};
-
-
const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
{
int x;
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 1ab321926f64..f8c5d4a9be13 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -21,8 +21,6 @@
extern unsigned char IPA_PDU_HEADER[];
#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
-#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
-
#define QETH_SEQ_NO_LENGTH 4
#define QETH_MPC_TOKEN_LENGTH 4
#define QETH_MCL_LENGTH 4
@@ -81,7 +79,9 @@ enum qeth_card_types {
#define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD)
#define IS_OSD(card) ((card)->info.type == QETH_CARD_TYPE_OSD)
+#define IS_OSM(card) ((card)->info.type == QETH_CARD_TYPE_OSM)
#define IS_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN)
+#define IS_OSX(card) ((card)->info.type == QETH_CARD_TYPE_OSX)
#define IS_VM_NIC(card) ((card)->info.guestlan)
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -230,7 +230,6 @@ enum qeth_ipa_return_codes {
IPA_RC_LAN_OFFLINE = 0xe080,
IPA_RC_VEPA_TO_VEB_TRANSITION = 0xe090,
IPA_RC_INVALID_IP_VERSION2 = 0xf001,
- IPA_RC_ENOMEM = 0xfffe,
IPA_RC_FFFF = 0xffff
};
/* for VNIC Characteristics */
@@ -418,12 +417,6 @@ enum qeth_ipa_checksum_bits {
QETH_IPA_CHECKSUM_LP2LP = 0x0020
};
-/* IPA Assist checksum offload reply layout. */
-struct qeth_checksum_cmd {
- __u32 supported;
- __u32 enabled;
-} __packed;
-
enum qeth_ipa_large_send_caps {
QETH_IPA_LARGE_SEND_TCP = 0x00000001,
};
@@ -439,7 +432,6 @@ struct qeth_ipacmd_setassparms {
union {
__u32 flags_32bit;
struct qeth_ipa_caps caps;
- struct qeth_checksum_cmd chksum;
struct qeth_arp_cache_entry arp_entry;
struct qeth_arp_query_data query_arp;
struct qeth_tso_start_data tso;
@@ -833,15 +825,10 @@ enum qeth_ipa_arp_return_codes {
extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
-#define QETH_SETASS_BASE_LEN (IPA_PDU_HEADER_SIZE + \
- sizeof(struct qeth_ipacmd_hdr) + \
- sizeof(struct qeth_ipacmd_setassparms_hdr))
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16
-#define QETH_ARP_DATA_SIZE 3968
-#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 30f61608fa22..56deeb6f7bc0 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -29,13 +29,11 @@ static ssize_t qeth_dev_state_show(struct device *dev,
case CARD_STATE_HARDSETUP:
return sprintf(buf, "HARDSETUP\n");
case CARD_STATE_SOFTSETUP:
+ if (card->dev->flags & IFF_UP)
+ return sprintf(buf, "UP (LAN %s)\n",
+ netif_carrier_ok(card->dev) ? "ONLINE" :
+ "OFFLINE");
return sprintf(buf, "SOFTSETUP\n");
- case CARD_STATE_UP:
- return sprintf(buf, "UP (LAN %s)\n",
- netif_carrier_ok(card->dev) ? "ONLINE" :
- "OFFLINE");
- case CARD_STATE_RECOVER:
- return sprintf(buf, "RECOVER\n");
default:
return sprintf(buf, "UNKNOWN\n");
}
@@ -126,8 +124,7 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
@@ -202,8 +199,7 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
@@ -285,8 +281,7 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
@@ -316,7 +311,7 @@ static ssize_t qeth_dev_recover_store(struct device *dev,
if (!card)
return -EINVAL;
- if (card->state != CARD_STATE_UP)
+ if (!qeth_card_hw_is_reachable(card))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
@@ -336,35 +331,36 @@ static ssize_t qeth_dev_performance_stats_show(struct device *dev,
if (!card)
return -EINVAL;
- return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+ return sprintf(buf, "1\n");
}
static ssize_t qeth_dev_performance_stats_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
- char *tmp;
- int i, rc = 0;
+ struct qeth_qdio_out_q *queue;
+ unsigned int i;
+ bool reset;
+ int rc;
if (!card)
return -EINVAL;
- mutex_lock(&card->conf_mutex);
- i = simple_strtoul(buf, &tmp, 16);
- if ((i == 0) || (i == 1)) {
- if (i == card->options.performance_stats)
- goto out;
- card->options.performance_stats = i;
- if (i == 0)
- memset(&card->perf_stats, 0,
- sizeof(struct qeth_perf_stats));
- card->perf_stats.initial_rx_packets = card->stats.rx_packets;
- card->perf_stats.initial_tx_packets = card->stats.tx_packets;
- } else
- rc = -EINVAL;
-out:
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
+ rc = kstrtobool(buf, &reset);
+ if (rc)
+ return rc;
+
+ if (reset) {
+ memset(&card->stats, 0, sizeof(card->stats));
+ for (i = 0; i < card->qdio.no_out_queues; i++) {
+ queue = card->qdio.out_qs[i];
+ if (!queue)
+ break;
+ memset(&queue->stats, 0, sizeof(queue->stats));
+ }
+ }
+
+ return count;
}
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
@@ -420,7 +416,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
goto out;
}
- card->info.mac_bits = 0;
if (card->discipline) {
/* start with a new, pristine netdevice: */
ndev = qeth_clone_netdev(card->dev);
@@ -633,8 +628,7 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
new file mode 100644
index 000000000000..93a53fed4cf8
--- /dev/null
+++ b/drivers/s390/net/qeth_ethtool.c
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 2018
+ */
+
+#define KMSG_COMPONENT "qeth"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/ethtool.h>
+#include "qeth_core.h"
+
+
+#define QETH_TXQ_STAT(_name, _stat) { \
+ .name = _name, \
+ .offset = offsetof(struct qeth_out_q_stats, _stat) \
+}
+
+#define QETH_CARD_STAT(_name, _stat) { \
+ .name = _name, \
+ .offset = offsetof(struct qeth_card_stats, _stat) \
+}
+
+struct qeth_stats {
+ char name[ETH_GSTRING_LEN];
+ unsigned int offset;
+};
+
+static const struct qeth_stats txq_stats[] = {
+ QETH_TXQ_STAT("IO buffers", bufs),
+ QETH_TXQ_STAT("IO buffer elements", buf_elements),
+ QETH_TXQ_STAT("packed IO buffers", bufs_pack),
+ QETH_TXQ_STAT("skbs", tx_packets),
+ QETH_TXQ_STAT("packed skbs", skbs_pack),
+ QETH_TXQ_STAT("SG skbs", skbs_sg),
+ QETH_TXQ_STAT("HW csum skbs", skbs_csum),
+ QETH_TXQ_STAT("TSO skbs", skbs_tso),
+ QETH_TXQ_STAT("linearized skbs", skbs_linearized),
+ QETH_TXQ_STAT("linearized+error skbs", skbs_linearized_fail),
+ QETH_TXQ_STAT("TSO bytes", tso_bytes),
+ QETH_TXQ_STAT("Packing mode switches", packing_mode_switch),
+};
+
+static const struct qeth_stats card_stats[] = {
+ QETH_CARD_STAT("rx0 IO buffers", rx_bufs),
+ QETH_CARD_STAT("rx0 HW csum skbs", rx_skb_csum),
+ QETH_CARD_STAT("rx0 SG skbs", rx_sg_skbs),
+ QETH_CARD_STAT("rx0 SG page frags", rx_sg_frags),
+ QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page),
+};
+
+#define TXQ_STATS_LEN ARRAY_SIZE(txq_stats)
+#define CARD_STATS_LEN ARRAY_SIZE(card_stats)
+
+static void qeth_add_stat_data(u64 **dst, void *src,
+ const struct qeth_stats stats[],
+ unsigned int size)
+{
+ unsigned int i;
+ char *stat;
+
+ for (i = 0; i < size; i++) {
+ stat = (char *)src + stats[i].offset;
+ **dst = *(u64 *)stat;
+ (*dst)++;
+ }
+}
+
+static void qeth_add_stat_strings(u8 **data, const char *prefix,
+ const struct qeth_stats stats[],
+ unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ snprintf(*data, ETH_GSTRING_LEN, "%s%s", prefix, stats[i].name);
+ *data += ETH_GSTRING_LEN;
+ }
+}
+
+static int qeth_get_sset_count(struct net_device *dev, int stringset)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return CARD_STATS_LEN +
+ card->qdio.no_out_queues * TXQ_STATS_LEN;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void qeth_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct qeth_card *card = dev->ml_priv;
+ unsigned int i;
+
+ qeth_add_stat_data(&data, &card->stats, card_stats, CARD_STATS_LEN);
+ for (i = 0; i < card->qdio.no_out_queues; i++)
+ qeth_add_stat_data(&data, &card->qdio.out_qs[i]->stats,
+ txq_stats, TXQ_STATS_LEN);
+}
+
+static void qeth_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *param)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ param->rx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
+ param->rx_mini_max_pending = 0;
+ param->rx_jumbo_max_pending = 0;
+ param->tx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
+
+ param->rx_pending = card->qdio.in_buf_pool.buf_count;
+ param->rx_mini_pending = 0;
+ param->rx_jumbo_pending = 0;
+ param->tx_pending = QDIO_MAX_BUFFERS_PER_Q;
+}
+
+static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ struct qeth_card *card = dev->ml_priv;
+ char prefix[ETH_GSTRING_LEN] = "";
+ unsigned int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ qeth_add_stat_strings(&data, prefix, card_stats,
+ CARD_STATS_LEN);
+ for (i = 0; i < card->qdio.no_out_queues; i++) {
+ snprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i);
+ qeth_add_stat_strings(&data, prefix, txq_stats,
+ TXQ_STATS_LEN);
+ }
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+static void qeth_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
+ sizeof(info->driver));
+ strlcpy(info->version, "1.0", sizeof(info->version));
+ strlcpy(info->fw_version, card->info.mcl_level,
+ sizeof(info->fw_version));
+ snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
+ CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
+}
+
+/* Helper function to fill 'advertising' and 'supported' which are the same. */
+/* Autoneg and full-duplex are supported and advertised unconditionally. */
+/* Always advertise and support all speeds up to specified, and only one */
+/* specified port type. */
+static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
+ int maxspeed, int porttype)
+{
+ ethtool_link_ksettings_zero_link_mode(cmd, supported);
+ ethtool_link_ksettings_zero_link_mode(cmd, advertising);
+ ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
+
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
+
+ switch (porttype) {
+ case PORT_TP:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
+ break;
+ case PORT_FIBRE:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
+ break;
+ default:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
+ WARN_ON_ONCE(1);
+ }
+
+ /* partially does fall through, to also select lower speeds */
+ switch (maxspeed) {
+ case SPEED_25000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 25000baseSR_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 25000baseSR_Full);
+ break;
+ case SPEED_10000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10000baseT_Full);
+ /* fall through */
+ case SPEED_1000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 1000baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 1000baseT_Half);
+ /* fall through */
+ case SPEED_100:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 100baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 100baseT_Half);
+ /* fall through */
+ case SPEED_10:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Half);
+ break;
+ default:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Half);
+ WARN_ON_ONCE(1);
+ }
+}
+
+
+static int qeth_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct qeth_card *card = netdev->ml_priv;
+ enum qeth_link_types link_type;
+ struct carrier_info carrier_info;
+ int rc;
+
+ if (IS_IQD(card) || IS_VM_NIC(card))
+ link_type = QETH_LINK_TYPE_10GBIT_ETH;
+ else
+ link_type = card->info.link_type;
+
+ cmd->base.duplex = DUPLEX_FULL;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+ cmd->base.phy_address = 0;
+ cmd->base.mdio_support = 0;
+ cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
+ cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
+
+ switch (link_type) {
+ case QETH_LINK_TYPE_FAST_ETH:
+ case QETH_LINK_TYPE_LANE_ETH100:
+ cmd->base.speed = SPEED_100;
+ cmd->base.port = PORT_TP;
+ break;
+ case QETH_LINK_TYPE_GBIT_ETH:
+ case QETH_LINK_TYPE_LANE_ETH1000:
+ cmd->base.speed = SPEED_1000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_10GBIT_ETH:
+ cmd->base.speed = SPEED_10000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_25GBIT_ETH:
+ cmd->base.speed = SPEED_25000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ default:
+ cmd->base.speed = SPEED_10;
+ cmd->base.port = PORT_TP;
+ }
+ qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
+
+ /* Check if we can obtain more accurate information. */
+ /* If QUERY_CARD_INFO command is not supported or fails, */
+ /* just return the heuristics that was filled above. */
+ rc = qeth_query_card_info(card, &carrier_info);
+ if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
+ return 0;
+ if (rc) /* report error from the hardware operation */
+ return rc;
+ /* on success, fill in the information got from the hardware */
+
+ netdev_dbg(netdev,
+ "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
+ carrier_info.card_type,
+ carrier_info.port_mode,
+ carrier_info.port_speed);
+
+ /* Update attributes for which we've obtained more authoritative */
+ /* information, leave the rest the way they where filled above. */
+ switch (carrier_info.card_type) {
+ case CARD_INFO_TYPE_1G_COPPER_A:
+ case CARD_INFO_TYPE_1G_COPPER_B:
+ cmd->base.port = PORT_TP;
+ qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
+ break;
+ case CARD_INFO_TYPE_1G_FIBRE_A:
+ case CARD_INFO_TYPE_1G_FIBRE_B:
+ cmd->base.port = PORT_FIBRE;
+ qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
+ break;
+ case CARD_INFO_TYPE_10G_FIBRE_A:
+ case CARD_INFO_TYPE_10G_FIBRE_B:
+ cmd->base.port = PORT_FIBRE;
+ qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
+ break;
+ }
+
+ switch (carrier_info.port_mode) {
+ case CARD_INFO_PORTM_FULLDUPLEX:
+ cmd->base.duplex = DUPLEX_FULL;
+ break;
+ case CARD_INFO_PORTM_HALFDUPLEX:
+ cmd->base.duplex = DUPLEX_HALF;
+ break;
+ }
+
+ switch (carrier_info.port_speed) {
+ case CARD_INFO_PORTS_10M:
+ cmd->base.speed = SPEED_10;
+ break;
+ case CARD_INFO_PORTS_100M:
+ cmd->base.speed = SPEED_100;
+ break;
+ case CARD_INFO_PORTS_1G:
+ cmd->base.speed = SPEED_1000;
+ break;
+ case CARD_INFO_PORTS_10G:
+ cmd->base.speed = SPEED_10000;
+ break;
+ case CARD_INFO_PORTS_25G:
+ cmd->base.speed = SPEED_25000;
+ break;
+ }
+
+ return 0;
+}
+
+const struct ethtool_ops qeth_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = qeth_get_ringparam,
+ .get_strings = qeth_get_strings,
+ .get_ethtool_stats = qeth_get_ethtool_stats,
+ .get_sset_count = qeth_get_sset_count,
+ .get_drvinfo = qeth_get_drvinfo,
+ .get_link_ksettings = qeth_get_link_ksettings,
+};
+
+const struct ethtool_ops qeth_osn_ethtool_ops = {
+ .get_strings = qeth_get_strings,
+ .get_ethtool_stats = qeth_get_ethtool_stats,
+ .get_sset_count = qeth_get_sset_count,
+ .get_drvinfo = qeth_get_drvinfo,
+};
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index f108d4b44605..8efb2e8ff8f4 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -25,7 +25,6 @@
#include "qeth_l2.h"
static int qeth_l2_set_offline(struct ccwgroup_device *);
-static int qeth_l2_stop(struct net_device *);
static void qeth_bridgeport_query_support(struct qeth_card *card);
static void qeth_bridge_state_change(struct qeth_card *card,
struct qeth_ipa_cmd *cmd);
@@ -36,7 +35,7 @@ static void qeth_l2_vnicc_init(struct qeth_card *card);
static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
u32 *timeout);
-static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
+static int qeth_l2_setdelmac_makerc(struct qeth_card *card, u16 retcode)
{
int rc;
@@ -63,9 +62,6 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
case IPA_RC_L2_MAC_NOT_FOUND:
rc = -ENOENT;
break;
- case -ENOMEM:
- rc = -ENOMEM;
- break;
default:
rc = -EIO;
break;
@@ -73,6 +69,15 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
return rc;
}
+static int qeth_l2_send_setdelmac_cb(struct qeth_card *card,
+ struct qeth_reply *reply,
+ unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+
+ return qeth_l2_setdelmac_makerc(card, cmd->hdr.return_code);
+}
+
static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
enum qeth_ipa_cmds ipacmd)
{
@@ -86,8 +91,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
cmd = __ipa_cmd(iob);
cmd->data.setdelmac.mac_length = ETH_ALEN;
ether_addr_copy(cmd->data.setdelmac.mac, mac);
- return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob,
- NULL, NULL));
+ return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelmac_cb, NULL);
}
static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
@@ -98,8 +102,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
if (rc == 0) {
dev_info(&card->gdev->dev,
- "MAC address %pM successfully registered on device %s\n",
- mac, card->dev->name);
+ "MAC address %pM successfully registered\n", mac);
} else {
switch (rc) {
case -EEXIST:
@@ -171,9 +174,9 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
return RTN_UNICAST;
}
-static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
- struct sk_buff *skb, int ipv, int cast_type,
- unsigned int data_len)
+static void qeth_l2_fill_header(struct qeth_qdio_out_q *queue,
+ struct qeth_hdr *hdr, struct sk_buff *skb,
+ int ipv, int cast_type, unsigned int data_len)
{
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
@@ -185,8 +188,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
- if (card->options.performance_stats)
- card->perf_stats.tx_csum++;
+ QETH_TXQ_STAT_INC(queue, skbs_csum);
}
}
@@ -207,7 +209,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
}
-static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
+static int qeth_l2_setdelvlan_makerc(struct qeth_card *card, u16 retcode)
{
if (retcode)
QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
@@ -223,8 +225,6 @@ static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
return -ENOENT;
case IPA_RC_L2_VLAN_ID_NOT_ALLOWED:
return -EPERM;
- case -ENOMEM:
- return -ENOMEM;
default:
return -EIO;
}
@@ -242,9 +242,8 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
cmd->data.setdelvlan.vlan_id,
CARD_DEVID(card), cmd->hdr.return_code);
QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
- QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
}
- return 0;
+ return qeth_l2_setdelvlan_makerc(card, cmd->hdr.return_code);
}
static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
@@ -259,101 +258,40 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
return -ENOMEM;
cmd = __ipa_cmd(iob);
cmd->data.setdelvlan.vlan_id = i;
- return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob,
- qeth_l2_send_setdelvlan_cb, NULL));
-}
-
-static void qeth_l2_process_vlans(struct qeth_card *card)
-{
- struct qeth_vlan_vid *id;
-
- QETH_CARD_TEXT(card, 3, "L2prcvln");
- mutex_lock(&card->vid_list_mutex);
- list_for_each_entry(id, &card->vid_list, list) {
- qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
- }
- mutex_unlock(&card->vid_list_mutex);
+ return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelvlan_cb, NULL);
}
static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
__be16 proto, u16 vid)
{
struct qeth_card *card = dev->ml_priv;
- struct qeth_vlan_vid *id;
- int rc;
QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
if (!vid)
return 0;
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "aidREC");
- return 0;
- }
- id = kmalloc(sizeof(*id), GFP_KERNEL);
- if (id) {
- id->vid = vid;
- rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
- if (rc) {
- kfree(id);
- return rc;
- }
- mutex_lock(&card->vid_list_mutex);
- list_add_tail(&id->list, &card->vid_list);
- mutex_unlock(&card->vid_list_mutex);
- } else {
- return -ENOMEM;
- }
- return 0;
+
+ return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
}
static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
__be16 proto, u16 vid)
{
- struct qeth_vlan_vid *id, *tmpid = NULL;
struct qeth_card *card = dev->ml_priv;
- int rc = 0;
QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "kidREC");
+ if (!vid)
return 0;
- }
- mutex_lock(&card->vid_list_mutex);
- list_for_each_entry(id, &card->vid_list, list) {
- if (id->vid == vid) {
- list_del(&id->list);
- tmpid = id;
- break;
- }
- }
- mutex_unlock(&card->vid_list_mutex);
- if (tmpid) {
- rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
- kfree(tmpid);
- }
- return rc;
+
+ return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
}
-static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l2_stop_card(struct qeth_card *card)
{
QETH_DBF_TEXT(SETUP , 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
qeth_set_allowed_threads(card, 0, 1);
- if (card->read.state == CH_STATE_UP &&
- card->write.state == CH_STATE_UP &&
- (card->state == CARD_STATE_UP)) {
- if (recovery_mode &&
- card->info.type != QETH_CARD_TYPE_OSN) {
- qeth_l2_stop(card->dev);
- } else {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
- }
- card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
- card->state = CARD_STATE_SOFTSETUP;
- }
+
if (card->state == CARD_STATE_SOFTSETUP) {
qeth_l2_del_all_macs(card);
qeth_clear_ipacmd_list(card);
@@ -369,6 +307,9 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
+
+ flush_workqueue(card->event_wq);
+ card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
}
static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -416,8 +357,8 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
}
work_done++;
budget--;
- card->stats.rx_packets++;
- card->stats.rx_bytes += len;
+ QETH_CARD_STAT_INC(card, rx_packets);
+ QETH_CARD_STAT_ADD(card, rx_bytes, len);
}
return work_done;
}
@@ -441,7 +382,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
if (!IS_OSN(card)) {
rc = qeth_setadpparms_change_macaddr(card);
- if (!rc && is_valid_ether_addr(card->dev->dev_addr))
+ if (!rc)
goto out;
QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n",
CARD_DEVID(card), rc);
@@ -460,6 +401,26 @@ out:
return 0;
}
+static void qeth_l2_register_dev_addr(struct qeth_card *card)
+{
+ if (!is_valid_ether_addr(card->dev->dev_addr))
+ qeth_l2_request_initial_mac(card);
+
+ if (!IS_OSN(card) && !qeth_l2_send_setmac(card, card->dev->dev_addr))
+ card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
+}
+
+static int qeth_l2_validate_addr(struct net_device *dev)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
+ return eth_validate_addr(dev);
+
+ QETH_CARD_TEXT(card, 4, "nomacadr");
+ return -EPERM;
+}
+
static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
@@ -469,9 +430,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
QETH_CARD_TEXT(card, 3, "setmac");
- if (card->info.type == QETH_CARD_TYPE_OSN ||
- card->info.type == QETH_CARD_TYPE_OSM ||
- card->info.type == QETH_CARD_TYPE_OSX) {
+ if (IS_OSM(card) || IS_OSX(card)) {
QETH_CARD_TEXT(card, 3, "setmcTYP");
return -EOPNOTSUPP;
}
@@ -479,39 +438,22 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "setmcREC");
- return -ERESTARTSYS;
- }
-
- /* avoid racing against concurrent state change: */
- if (!mutex_trylock(&card->conf_mutex))
- return -EAGAIN;
-
- if (!qeth_card_hw_is_reachable(card)) {
- ether_addr_copy(dev->dev_addr, addr->sa_data);
- goto out_unlock;
- }
-
/* don't register the same address twice */
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
- goto out_unlock;
+ return 0;
/* add the new address, switch over, drop the old */
rc = qeth_l2_send_setmac(card, addr->sa_data);
if (rc)
- goto out_unlock;
+ return rc;
ether_addr_copy(old_addr, dev->dev_addr);
ether_addr_copy(dev->dev_addr, addr->sa_data);
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
qeth_l2_remove_mac(card, old_addr);
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
-
-out_unlock:
- mutex_unlock(&card->conf_mutex);
- return rc;
+ return 0;
}
static void qeth_promisc_to_bridge(struct qeth_card *card)
@@ -582,13 +524,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
int i;
int rc;
- if (card->info.type == QETH_CARD_TYPE_OSN)
- return;
-
QETH_CARD_TEXT(card, 3, "setmulti");
- if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
- (card->state != CARD_STATE_UP))
- return;
spin_lock_bh(&card->mclock);
@@ -673,17 +609,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
int tx_bytes = skb->len;
int rc;
- if (card->state != CARD_STATE_UP) {
- card->stats.tx_carrier_errors++;
- goto tx_drop;
- }
-
queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
- if (card->options.performance_stats) {
- card->perf_stats.outbound_cnt++;
- card->perf_stats.outbound_start_time = qeth_get_micros();
- }
netif_stop_queue(dev);
if (IS_OSN(card))
@@ -693,81 +620,21 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
qeth_l2_fill_header);
if (!rc) {
- card->stats.tx_packets++;
- card->stats.tx_bytes += tx_bytes;
- if (card->options.performance_stats)
- card->perf_stats.outbound_time += qeth_get_micros() -
- card->perf_stats.outbound_start_time;
+ QETH_TXQ_STAT_INC(queue, tx_packets);
+ QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes);
netif_wake_queue(dev);
return NETDEV_TX_OK;
} else if (rc == -EBUSY) {
return NETDEV_TX_BUSY;
} /* else fall through */
-tx_drop:
- card->stats.tx_dropped++;
- card->stats.tx_errors++;
+ QETH_TXQ_STAT_INC(queue, tx_dropped);
+ QETH_TXQ_STAT_INC(queue, tx_errors);
dev_kfree_skb_any(skb);
netif_wake_queue(dev);
return NETDEV_TX_OK;
}
-static int __qeth_l2_open(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
- int rc = 0;
-
- QETH_CARD_TEXT(card, 4, "qethopen");
- if (card->state == CARD_STATE_UP)
- return rc;
- if (card->state != CARD_STATE_SOFTSETUP)
- return -ENODEV;
-
- if ((card->info.type != QETH_CARD_TYPE_OSN) &&
- (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
- QETH_CARD_TEXT(card, 4, "nomacadr");
- return -EPERM;
- }
- card->data.state = CH_STATE_UP;
- card->state = CARD_STATE_UP;
- netif_start_queue(dev);
-
- if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
- napi_enable(&card->napi);
- local_bh_disable();
- napi_schedule(&card->napi);
- /* kick-start the NAPI softirq: */
- local_bh_enable();
- } else
- rc = -EIO;
- return rc;
-}
-
-static int qeth_l2_open(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT(card, 5, "qethope_");
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "openREC");
- return -ERESTARTSYS;
- }
- return __qeth_l2_open(dev);
-}
-
-static int qeth_l2_stop(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT(card, 4, "qethstop");
- netif_tx_disable(dev);
- if (card->state == CARD_STATE_UP) {
- card->state = CARD_STATE_SOFTSETUP;
- napi_disable(&card->napi);
- }
- return 0;
-}
-
static const struct device_type qeth_l2_devtype = {
.name = "qeth_layer2",
.groups = qeth_l2_attr_groups,
@@ -783,7 +650,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
if (rc)
return rc;
}
- INIT_LIST_HEAD(&card->vid_list);
+
hash_init(card->mac_htable);
card->info.hwtrap = 0;
qeth_l2_vnicc_set_defaults(card);
@@ -801,33 +668,19 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE)
qeth_l2_set_offline(cgdev);
+
+ cancel_work_sync(&card->close_dev_work);
if (qeth_netdev_is_registered(card->dev))
unregister_netdev(card->dev);
}
-static const struct ethtool_ops qeth_l2_ethtool_ops = {
- .get_link = ethtool_op_get_link,
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
- .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
-};
-
-static const struct ethtool_ops qeth_l2_osn_ops = {
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
-};
-
static const struct net_device_ops qeth_l2_netdev_ops = {
- .ndo_open = qeth_l2_open,
- .ndo_stop = qeth_l2_stop,
- .ndo_get_stats = qeth_get_stats,
+ .ndo_open = qeth_open,
+ .ndo_stop = qeth_stop,
+ .ndo_get_stats64 = qeth_get_stats64,
.ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_features_check = qeth_features_check,
- .ndo_validate_addr = eth_validate_addr,
+ .ndo_validate_addr = qeth_l2_validate_addr,
.ndo_set_rx_mode = qeth_l2_set_rx_mode,
.ndo_do_ioctl = qeth_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address,
@@ -838,27 +691,36 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_set_features = qeth_set_features
};
+static const struct net_device_ops qeth_osn_netdev_ops = {
+ .ndo_open = qeth_open,
+ .ndo_stop = qeth_stop,
+ .ndo_get_stats64 = qeth_get_stats64,
+ .ndo_start_xmit = qeth_l2_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = qeth_tx_timeout,
+};
+
static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
{
int rc;
- if (qeth_netdev_is_registered(card->dev))
- return 0;
-
- card->dev->priv_flags |= IFF_UNICAST_FLT;
- card->dev->netdev_ops = &qeth_l2_netdev_ops;
- if (card->info.type == QETH_CARD_TYPE_OSN) {
- card->dev->ethtool_ops = &qeth_l2_osn_ops;
+ if (IS_OSN(card)) {
+ card->dev->netdev_ops = &qeth_osn_netdev_ops;
card->dev->flags |= IFF_NOARP;
- } else {
- card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
- card->dev->needed_headroom = sizeof(struct qeth_hdr);
+ goto add_napi;
}
- if (card->info.type == QETH_CARD_TYPE_OSM)
+ card->dev->needed_headroom = sizeof(struct qeth_hdr);
+ card->dev->netdev_ops = &qeth_l2_netdev_ops;
+ card->dev->priv_flags |= IFF_UNICAST_FLT;
+
+ if (IS_OSM(card)) {
card->dev->features |= NETIF_F_VLAN_CHALLENGED;
- else
+ } else {
+ if (!IS_VM_NIC(card))
+ card->dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ }
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
card->dev->features |= NETIF_F_SG;
@@ -892,8 +754,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1));
}
- if (!is_valid_ether_addr(card->dev->dev_addr))
- qeth_l2_request_initial_mac(card);
+add_napi:
netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
rc = register_netdev(card->dev);
if (!rc && carrier_ok)
@@ -924,11 +785,11 @@ static void qeth_l2_trace_features(struct qeth_card *card)
sizeof(card->options.vnicc.sup_chars));
}
-static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+static int qeth_l2_set_online(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+ struct net_device *dev = card->dev;
int rc = 0;
- enum qeth_card_states recover_flag;
bool carrier_ok;
mutex_lock(&card->discipline_mutex);
@@ -936,25 +797,12 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
- recover_flag = card->state;
rc = qeth_core_hardsetup_card(card, &carrier_ok);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
rc = -ENODEV;
goto out_remove;
}
- qeth_bridgeport_query_support(card);
- if (card->options.sbp.supported_funcs)
- dev_info(&card->gdev->dev,
- "The device represents a Bridge Capable Port\n");
-
- rc = qeth_l2_setup_netdev(card, carrier_ok);
- if (rc)
- goto out_remove;
-
- if (card->info.type != QETH_CARD_TYPE_OSN &&
- !qeth_l2_send_setmac(card, card->dev->dev_addr))
- card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap &&
@@ -963,6 +811,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
} else
card->info.hwtrap = 0;
+ qeth_bridgeport_query_support(card);
+ if (card->options.sbp.supported_funcs)
+ dev_info(&card->gdev->dev,
+ "The device represents a Bridge Capable Port\n");
+
+ qeth_l2_register_dev_addr(card);
+
/* for the rx_bcast characteristic, init VNICC after setmac */
qeth_l2_vnicc_init(card);
@@ -984,11 +839,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
goto out_remove;
}
- if (card->info.type != QETH_CARD_TYPE_OSN)
- qeth_l2_process_vlans(card);
-
- netif_tx_disable(card->dev);
-
rc = qeth_init_qdio_queues(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
@@ -999,17 +849,25 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_set_allowed_threads(card, 0xffffffff, 0);
- qeth_enable_hw_features(card->dev);
- if (recover_flag == CARD_STATE_RECOVER) {
- if (recovery_mode &&
- card->info.type != QETH_CARD_TYPE_OSN) {
- __qeth_l2_open(card->dev);
- qeth_l2_set_rx_mode(card->dev);
- } else {
- rtnl_lock();
- dev_open(card->dev, NULL);
- rtnl_unlock();
+ if (!qeth_netdev_is_registered(dev)) {
+ rc = qeth_l2_setup_netdev(card, carrier_ok);
+ if (rc)
+ goto out_remove;
+ } else {
+ rtnl_lock();
+ if (carrier_ok)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
+
+ netif_device_attach(dev);
+ qeth_enable_hw_features(dev);
+
+ if (card->info.open_when_online) {
+ card->info.open_when_online = 0;
+ dev_open(dev, NULL);
}
+ rtnl_unlock();
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
@@ -1018,44 +876,42 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
return 0;
out_remove:
- qeth_l2_stop_card(card, 0);
+ qeth_l2_stop_card(card);
ccw_device_set_offline(CARD_DDEV(card));
ccw_device_set_offline(CARD_WDEV(card));
ccw_device_set_offline(CARD_RDEV(card));
qdio_free(CARD_DDEV(card));
- if (recover_flag == CARD_STATE_RECOVER)
- card->state = CARD_STATE_RECOVER;
- else
- card->state = CARD_STATE_DOWN;
+ card->state = CARD_STATE_DOWN;
+
mutex_unlock(&card->conf_mutex);
mutex_unlock(&card->discipline_mutex);
return rc;
}
-static int qeth_l2_set_online(struct ccwgroup_device *gdev)
-{
- return __qeth_l2_set_online(gdev, 0);
-}
-
static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
int recovery_mode)
{
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
int rc = 0, rc2 = 0, rc3 = 0;
- enum qeth_card_states recover_flag;
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
- netif_carrier_off(card->dev);
- recover_flag = card->state;
if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
card->info.hwtrap = 1;
}
- qeth_l2_stop_card(card, recovery_mode);
+
+ rtnl_lock();
+ card->info.open_when_online = card->dev->flags & IFF_UP;
+ dev_close(card->dev);
+ netif_device_detach(card->dev);
+ netif_carrier_off(card->dev);
+ rtnl_unlock();
+
+ qeth_l2_stop_card(card);
rc = ccw_device_set_offline(CARD_DDEV(card));
rc2 = ccw_device_set_offline(CARD_WDEV(card));
rc3 = ccw_device_set_offline(CARD_RDEV(card));
@@ -1064,8 +920,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
qdio_free(CARD_DDEV(card));
- if (recover_flag == CARD_STATE_UP)
- card->state = CARD_STATE_RECOVER;
+
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&card->conf_mutex);
@@ -1090,18 +945,16 @@ static int qeth_l2_recover(void *ptr)
QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n");
- qeth_set_recovery_task(card);
__qeth_l2_set_offline(card->gdev, 1);
- rc = __qeth_l2_set_online(card->gdev, 1);
+ rc = qeth_l2_set_online(card->gdev);
if (!rc)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
else {
- qeth_close_dev(card);
+ ccwgroup_set_offline(card->gdev);
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
- qeth_clear_recovery_task(card);
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
@@ -1122,37 +975,23 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- netif_device_detach(card->dev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE)
return 0;
- if (card->state == CARD_STATE_UP) {
- if (card->info.hwtrap)
- qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
- __qeth_l2_set_offline(card->gdev, 1);
- } else
- __qeth_l2_set_offline(card->gdev, 0);
+
+ qeth_l2_set_offline(gdev);
return 0;
}
static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- int rc = 0;
+ int rc;
- if (card->state == CARD_STATE_RECOVER) {
- rc = __qeth_l2_set_online(card->gdev, 1);
- if (rc) {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
- }
- } else
- rc = __qeth_l2_set_online(card->gdev, 0);
+ rc = qeth_l2_set_online(gdev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
- netif_device_attach(card->dev);
if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
@@ -1224,20 +1063,14 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
}
static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
- struct qeth_cmd_buffer *iob, int data_len)
+ struct qeth_cmd_buffer *iob)
{
- u16 s1, s2;
+ u16 length;
QETH_CARD_TEXT(card, 4, "osndipa");
- qeth_prepare_ipa_cmd(card, iob);
- s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
- s2 = (u16)data_len;
- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
- return qeth_osn_send_control_data(card, s1, iob);
+ memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2);
+ return qeth_osn_send_control_data(card, length, iob);
}
int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
@@ -1254,8 +1087,9 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
if (!qeth_card_hw_is_reachable(card))
return -ENODEV;
iob = qeth_wait_for_buffer(&card->write);
+ qeth_prepare_ipa_cmd(card, iob, (u16) data_len);
memcpy(__ipa_cmd(iob), data, data_len);
- return qeth_osn_send_ipa_cmd(card, iob, data_len);
+ return qeth_osn_send_ipa_cmd(card, iob);
}
EXPORT_SYMBOL(qeth_osn_assist);
@@ -1434,7 +1268,7 @@ static void qeth_bridge_state_change(struct qeth_card *card,
data->card = card;
memcpy(&data->qports, qports,
sizeof(struct qeth_sbp_state_change) + extrasize);
- queue_work(qeth_wq, &data->worker);
+ queue_work(card->event_wq, &data->worker);
}
struct qeth_bridge_host_data {
@@ -1506,14 +1340,12 @@ static void qeth_bridge_host_event(struct qeth_card *card,
data->card = card;
memcpy(&data->hostevs, hostevs,
sizeof(struct qeth_ipacmd_addr_change) + extrasize);
- queue_work(qeth_wq, &data->worker);
+ queue_work(card->event_wq, &data->worker);
}
/* SETBRIDGEPORT support; sending commands */
struct _qeth_sbp_cbctl {
- u16 ipa_rc;
- u16 cmd_rc;
union {
u32 supported;
struct {
@@ -1523,23 +1355,21 @@ struct _qeth_sbp_cbctl {
} data;
};
-/**
- * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
- * @card: qeth_card structure pointer, for debug messages.
- * @cbctl: state structure with hardware return codes.
- * @setcmd: IPA command code
- *
- * Returns negative errno-compatible error indication or 0 on success.
- */
static int qeth_bridgeport_makerc(struct qeth_card *card,
- struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
+ struct qeth_ipa_cmd *cmd)
{
+ struct qeth_ipacmd_setbridgeport *sbp = &cmd->data.sbp;
+ enum qeth_ipa_sbp_cmd setcmd = sbp->hdr.command_code;
+ u16 ipa_rc = cmd->hdr.return_code;
+ u16 sbp_rc = sbp->hdr.return_code;
int rc;
- int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
- if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
- (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
- switch (cbctl->cmd_rc) {
+ if (ipa_rc == IPA_RC_SUCCESS && sbp_rc == IPA_RC_SUCCESS)
+ return 0;
+
+ if ((IS_IQD(card) && ipa_rc == IPA_RC_SUCCESS) ||
+ (!IS_IQD(card) && ipa_rc == sbp_rc)) {
+ switch (sbp_rc) {
case IPA_RC_SUCCESS:
rc = 0;
break;
@@ -1603,8 +1433,8 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
default:
rc = -EIO;
}
- else
- switch (cbctl->ipa_rc) {
+ } else {
+ switch (ipa_rc) {
case IPA_RC_NOTSUPP:
rc = -EOPNOTSUPP;
break;
@@ -1614,10 +1444,11 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
default:
rc = -EIO;
}
+ }
if (rc) {
- QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
- QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
+ QETH_CARD_TEXT_(card, 2, "SBPi%04x", ipa_rc);
+ QETH_CARD_TEXT_(card, 2, "SBPc%04x", sbp_rc);
}
return rc;
}
@@ -1649,15 +1480,15 @@ static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
+ int rc;
+
QETH_CARD_TEXT(card, 2, "brqsupcb");
- cbctl->ipa_rc = cmd->hdr.return_code;
- cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
- if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
- cbctl->data.supported =
- cmd->data.sbp.data.query_cmds_supp.supported_cmds;
- } else {
- cbctl->data.supported = 0;
- }
+ rc = qeth_bridgeport_makerc(card, cmd);
+ if (rc)
+ return rc;
+
+ cbctl->data.supported =
+ cmd->data.sbp.data.query_cmds_supp.supported_cmds;
return 0;
}
@@ -1678,12 +1509,11 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
sizeof(struct qeth_sbp_query_cmds_supp));
if (!iob)
return;
+
if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
- (void *)&cbctl) ||
- qeth_bridgeport_makerc(card, &cbctl,
- IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
- /* non-zero makerc signifies failure, and produce messages */
+ &cbctl)) {
card->options.sbp.role = QETH_SBP_ROLE_NONE;
+ card->options.sbp.supported_funcs = 0;
return;
}
card->options.sbp.supported_funcs = cbctl.data.supported;
@@ -1695,16 +1525,16 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
+ int rc;
QETH_CARD_TEXT(card, 2, "brqprtcb");
- cbctl->ipa_rc = cmd->hdr.return_code;
- cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
- if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
- return 0;
+ rc = qeth_bridgeport_makerc(card, cmd);
+ if (rc)
+ return rc;
+
if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
- cbctl->cmd_rc = 0xffff;
QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
- return 0;
+ return -EINVAL;
}
/* first entry contains the state of the local port */
if (qports->num_entries > 0) {
@@ -1729,7 +1559,6 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
int qeth_bridgeport_query_ports(struct qeth_card *card,
enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
{
- int rc = 0;
struct qeth_cmd_buffer *iob;
struct _qeth_sbp_cbctl cbctl = {
.data = {
@@ -1746,22 +1575,18 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_BRIDGE_PORTS, 0);
if (!iob)
return -ENOMEM;
- rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
- (void *)&cbctl);
- if (rc < 0)
- return rc;
- return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
+
+ return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
+ &cbctl);
}
static int qeth_bridgeport_set_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
- struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
+
QETH_CARD_TEXT(card, 2, "brsetrcb");
- cbctl->ipa_rc = cmd->hdr.return_code;
- cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
- return 0;
+ return qeth_bridgeport_makerc(card, cmd);
}
/**
@@ -1773,10 +1598,8 @@ static int qeth_bridgeport_set_cb(struct qeth_card *card,
*/
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
{
- int rc = 0;
int cmdlength;
struct qeth_cmd_buffer *iob;
- struct _qeth_sbp_cbctl cbctl;
enum qeth_ipa_sbp_cmd setcmd;
QETH_CARD_TEXT(card, 2, "brsetrol");
@@ -1801,11 +1624,8 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
iob = qeth_sbp_build_cmd(card, setcmd, cmdlength);
if (!iob)
return -ENOMEM;
- rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
- (void *)&cbctl);
- if (rc < 0)
- return rc;
- return qeth_bridgeport_makerc(card, &cbctl, setcmd);
+
+ return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb, NULL);
}
/**
@@ -1909,7 +1729,7 @@ static bool qeth_bridgeport_is_in_use(struct qeth_card *card)
/* VNIC Characteristics support */
/* handle VNICC IPA command return codes; convert to error codes */
-static int qeth_l2_vnicc_makerc(struct qeth_card *card, int ipa_rc)
+static int qeth_l2_vnicc_makerc(struct qeth_card *card, u16 ipa_rc)
{
int rc;
@@ -1967,7 +1787,7 @@ static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "vniccrcb");
if (cmd->hdr.return_code)
- return 0;
+ return qeth_l2_vnicc_makerc(card, cmd->hdr.return_code);
/* return results to caller */
card->options.vnicc.sup_chars = rep->hdr.sup;
card->options.vnicc.cur_chars = rep->hdr.cur;
@@ -1988,7 +1808,6 @@ static int qeth_l2_vnicc_request(struct qeth_card *card,
struct qeth_ipacmd_vnicc *req;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
- int rc;
QETH_CARD_TEXT(card, 2, "vniccreq");
@@ -2031,10 +1850,7 @@ static int qeth_l2_vnicc_request(struct qeth_card *card,
}
/* send request */
- rc = qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb,
- (void *) cbctl);
-
- return qeth_l2_vnicc_makerc(card, rc);
+ return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, cbctl);
}
/* VNICC query VNIC characteristics request */
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 42a7cdc59b76..7e68d9d16859 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -40,7 +40,6 @@
static int qeth_l3_set_offline(struct ccwgroup_device *);
-static int qeth_l3_stop(struct net_device *);
static void qeth_l3_set_rx_mode(struct net_device *dev);
static int qeth_l3_register_addr_entry(struct qeth_card *,
struct qeth_ipaddr *);
@@ -254,8 +253,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
} else
rc = qeth_l3_register_addr_entry(card, addr);
- if (!rc || (rc == IPA_RC_DUPLICATE_IP_ADDRESS) ||
- (rc == IPA_RC_LAN_OFFLINE)) {
+ if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
if (addr->ref_counter < 1) {
qeth_l3_deregister_addr_entry(card, addr);
@@ -339,10 +337,28 @@ static void qeth_l3_recover_ip(struct qeth_card *card)
}
+static int qeth_l3_setdelip_cb(struct qeth_card *card, struct qeth_reply *reply,
+ unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+
+ switch (cmd->hdr.return_code) {
+ case IPA_RC_SUCCESS:
+ return 0;
+ case IPA_RC_DUPLICATE_IP_ADDRESS:
+ return -EADDRINUSE;
+ case IPA_RC_MC_ADDR_NOT_FOUND:
+ return -ENOENT;
+ case IPA_RC_LAN_OFFLINE:
+ return -ENETDOWN;
+ default:
+ return -EIO;
+ }
+}
+
static int qeth_l3_send_setdelmc(struct qeth_card *card,
struct qeth_ipaddr *addr, int ipacmd)
{
- int rc;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
@@ -359,9 +375,7 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
else
memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
- return rc;
+ return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
}
static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
@@ -423,7 +437,7 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
cmd->data.setdelip4.flags = flags;
}
- return qeth_send_ipa_cmd(card, iob, NULL, NULL);
+ return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
}
static int qeth_l3_send_setrouting(struct qeth_card *card,
@@ -943,12 +957,13 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct qeth_ipa_cmd *cmd;
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
- cmd = (struct qeth_ipa_cmd *) data;
- if (cmd->hdr.return_code == 0)
- ether_addr_copy(card->dev->dev_addr,
- cmd->data.create_destroy_addr.unique_id);
+ if (cmd->hdr.return_code)
+ return -EIO;
+
+ ether_addr_copy(card->dev->dev_addr,
+ cmd->data.create_destroy_addr.unique_id);
return 0;
}
@@ -976,19 +991,18 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct qeth_ipa_cmd *cmd;
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
- cmd = (struct qeth_ipa_cmd *) data;
- if (cmd->hdr.return_code == 0)
+ if (cmd->hdr.return_code == 0) {
card->info.unique_id = *((__u16 *)
&cmd->data.create_destroy_addr.unique_id[6]);
- else {
- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
- UNIQUE_ID_NOT_BY_CARD;
- dev_warn(&card->gdev->dev, "The network adapter failed to "
- "generate a unique ID\n");
+ return 0;
}
- return 0;
+
+ card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+ UNIQUE_ID_NOT_BY_CARD;
+ dev_warn(&card->gdev->dev, "The network adapter failed to generate a unique ID\n");
+ return -EIO;
}
static int qeth_l3_get_unique_id(struct qeth_card *card)
@@ -1071,7 +1085,7 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
cmd->data.diagass.action, CARD_DEVID(card));
}
- return 0;
+ return rc ? -EIO : 0;
}
static int
@@ -1281,10 +1295,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "kidREC");
- return 0;
- }
clear_bit(vid, card->active_vlans);
qeth_l3_set_rx_mode(dev);
return 0;
@@ -1305,12 +1315,11 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr);
else
ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr);
-
- card->stats.multicast++;
+ QETH_CARD_STAT_INC(card, rx_multicast);
break;
case QETH_CAST_BROADCAST:
ether_addr_copy(tg_addr, card->dev->broadcast);
- card->stats.multicast++;
+ QETH_CARD_STAT_INC(card, rx_multicast);
break;
default:
if (card->options.sniffer)
@@ -1391,33 +1400,23 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
}
work_done++;
budget--;
- card->stats.rx_packets++;
- card->stats.rx_bytes += len;
+ QETH_CARD_STAT_INC(card, rx_packets);
+ QETH_CARD_STAT_ADD(card, rx_bytes, len);
}
return work_done;
}
-static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l3_stop_card(struct qeth_card *card)
{
QETH_DBF_TEXT(SETUP, 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
qeth_set_allowed_threads(card, 0, 1);
+
if (card->options.sniffer &&
(card->info.promisc_mode == SET_PROMISC_MODE_ON))
qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
- if (card->read.state == CH_STATE_UP &&
- card->write.state == CH_STATE_UP &&
- (card->state == CARD_STATE_UP)) {
- if (recovery_mode)
- qeth_l3_stop(card->dev);
- else {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
- }
- card->state = CARD_STATE_SOFTSETUP;
- }
+
if (card->state == CARD_STATE_SOFTSETUP) {
qeth_l3_clear_ip_htable(card, 1);
qeth_clear_ipacmd_list(card);
@@ -1433,6 +1432,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
+
+ flush_workqueue(card->event_wq);
}
/*
@@ -1473,9 +1474,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
int i, rc;
QETH_CARD_TEXT(card, 3, "setmulti");
- if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
- (card->state != CARD_STATE_UP))
- return;
+
if (!card->options.sniffer) {
spin_lock_bh(&card->mclock);
@@ -1486,14 +1485,14 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
switch (addr->disp_flag) {
case QETH_DISP_ADDR_DELETE:
rc = qeth_l3_deregister_addr_entry(card, addr);
- if (!rc || rc == IPA_RC_MC_ADDR_NOT_FOUND) {
+ if (!rc || rc == -ENOENT) {
hash_del(&addr->hnode);
kfree(addr);
}
break;
case QETH_DISP_ADDR_ADD:
rc = qeth_l3_register_addr_entry(card, addr);
- if (rc && rc != IPA_RC_LAN_OFFLINE) {
+ if (rc && rc != -ENETDOWN) {
hash_del(&addr->hnode);
kfree(addr);
break;
@@ -1514,7 +1513,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
qeth_l3_handle_promisc_mode(card);
}
-static int qeth_l3_arp_makerc(int rc)
+static int qeth_l3_arp_makerc(u16 rc)
{
switch (rc) {
case IPA_RC_SUCCESS:
@@ -1531,8 +1530,18 @@ static int qeth_l3_arp_makerc(int rc)
}
}
+static int qeth_l3_arp_cmd_cb(struct qeth_card *card, struct qeth_reply *reply,
+ unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+
+ qeth_setassparms_cb(card, reply, data);
+ return qeth_l3_arp_makerc(cmd->hdr.return_code);
+}
+
static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
{
+ struct qeth_cmd_buffer *iob;
int rc;
QETH_CARD_TEXT(card, 3, "arpstnoe");
@@ -1547,13 +1556,19 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
- IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
- no_entries);
+
+ iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+ IPA_CMD_ASS_ARP_SET_NO_ENTRIES, 4,
+ QETH_PROT_IPV4);
+ if (!iob)
+ return -ENOMEM;
+
+ __ipa_cmd(iob)->data.setassparms.data.flags_32bit = (u32) no_entries;
+ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
if (rc)
QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n",
CARD_DEVID(card), rc);
- return qeth_l3_arp_makerc(rc);
+ return rc;
}
static __u32 get_arp_entry_size(struct qeth_card *card,
@@ -1604,7 +1619,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
struct qeth_ipa_cmd *cmd;
struct qeth_arp_query_data *qdata;
struct qeth_arp_query_info *qinfo;
- int i;
int e;
int entrybytes_done;
int stripped_bytes;
@@ -1618,13 +1632,13 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
if (cmd->hdr.return_code) {
QETH_CARD_TEXT(card, 4, "arpcberr");
QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
- return 0;
+ return qeth_l3_arp_makerc(cmd->hdr.return_code);
}
if (cmd->data.setassparms.hdr.return_code) {
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
QETH_CARD_TEXT(card, 4, "setaperr");
QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
- return 0;
+ return qeth_l3_arp_makerc(cmd->hdr.return_code);
}
qdata = &cmd->data.setassparms.data.query_arp;
QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries);
@@ -1651,9 +1665,9 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
break;
if ((qinfo->udata_len - qinfo->udata_offset) < esize) {
- QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM);
- cmd->hdr.return_code = IPA_RC_ENOMEM;
- goto out_error;
+ QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOSPC);
+ memset(qinfo->udata, 0, 4);
+ return -ENOSPC;
}
memcpy(qinfo->udata + qinfo->udata_offset,
@@ -1676,10 +1690,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
QETH_CARD_TEXT_(card, 4, "rc%i", 0);
return 0;
-out_error:
- i = 0;
- memcpy(qinfo->udata, &i, 4);
- return 0;
}
static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
@@ -1701,13 +1711,11 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
return -ENOMEM;
cmd = __ipa_cmd(iob);
cmd->data.setassparms.data.query_arp.request_bits = 0x000F;
- rc = qeth_send_control_data(card,
- QETH_SETASS_BASE_LEN + QETH_ARP_CMD_LEN,
- iob, qeth_l3_arp_query_cb, qinfo);
+ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_query_cb, qinfo);
if (rc)
QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n",
CARD_DEVID(card), rc);
- return qeth_l3_arp_makerc(rc);
+ return rc;
}
static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
@@ -1789,16 +1797,16 @@ static int qeth_l3_arp_modify_entry(struct qeth_card *card,
cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry;
ether_addr_copy(cmd_entry->macaddr, entry->macaddr);
memcpy(cmd_entry->ipaddr, entry->ipaddr, 4);
- rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
+ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
if (rc)
QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n",
arp_cmd, CARD_DEVID(card), rc);
-
- return qeth_l3_arp_makerc(rc);
+ return rc;
}
static int qeth_l3_arp_flush_cache(struct qeth_card *card)
{
+ struct qeth_cmd_buffer *iob;
int rc;
QETH_CARD_TEXT(card, 3, "arpflush");
@@ -1813,12 +1821,18 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
- IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
+
+ iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+ IPA_CMD_ASS_ARP_FLUSH_CACHE, 0,
+ QETH_PROT_IPV4);
+ if (!iob)
+ return -ENOMEM;
+
+ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
if (rc)
QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n",
CARD_DEVID(card), rc);
- return qeth_l3_arp_makerc(rc);
+ return rc;
}
static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1920,12 +1934,13 @@ static u8 qeth_l3_cast_type_to_flag(int cast_type)
return QETH_CAST_UNICAST;
}
-static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
- struct sk_buff *skb, int ipv, int cast_type,
- unsigned int data_len)
+static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
+ struct qeth_hdr *hdr, struct sk_buff *skb,
+ int ipv, int cast_type, unsigned int data_len)
{
struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
+ struct qeth_card *card = queue->card;
hdr->hdr.l3.length = data_len;
@@ -1947,8 +1962,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
/* some HW requires combined L3+L4 csum offload: */
if (ipv == 4)
hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
- if (card->options.performance_stats)
- card->perf_stats.tx_csum++;
+ QETH_TXQ_STAT_INC(queue, skbs_csum);
}
}
@@ -2049,6 +2063,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
int tx_bytes = skb->len;
int rc;
+ queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
+
if (IS_IQD(card)) {
if (card->options.sniffer)
goto tx_drop;
@@ -2058,20 +2074,9 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
goto tx_drop;
}
- if (card->state != CARD_STATE_UP) {
- card->stats.tx_carrier_errors++;
- goto tx_drop;
- }
-
if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable)
goto tx_drop;
- queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
-
- if (card->options.performance_stats) {
- card->perf_stats.outbound_cnt++;
- card->perf_stats.outbound_start_time = qeth_get_micros();
- }
netif_stop_queue(dev);
if (ipv == 4 || IS_IQD(card))
@@ -2081,11 +2086,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
qeth_l3_fill_header);
if (!rc) {
- card->stats.tx_packets++;
- card->stats.tx_bytes += tx_bytes;
- if (card->options.performance_stats)
- card->perf_stats.outbound_time += qeth_get_micros() -
- card->perf_stats.outbound_start_time;
+ QETH_TXQ_STAT_INC(queue, tx_packets);
+ QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes);
netif_wake_queue(dev);
return NETDEV_TX_OK;
} else if (rc == -EBUSY) {
@@ -2093,72 +2095,13 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
} /* else fall through */
tx_drop:
- card->stats.tx_dropped++;
- card->stats.tx_errors++;
+ QETH_TXQ_STAT_INC(queue, tx_dropped);
+ QETH_TXQ_STAT_INC(queue, tx_errors);
dev_kfree_skb_any(skb);
netif_wake_queue(dev);
return NETDEV_TX_OK;
}
-static int __qeth_l3_open(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
- int rc = 0;
-
- QETH_CARD_TEXT(card, 4, "qethopen");
- if (card->state == CARD_STATE_UP)
- return rc;
- if (card->state != CARD_STATE_SOFTSETUP)
- return -ENODEV;
- card->data.state = CH_STATE_UP;
- card->state = CARD_STATE_UP;
- netif_start_queue(dev);
-
- if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
- napi_enable(&card->napi);
- local_bh_disable();
- napi_schedule(&card->napi);
- /* kick-start the NAPI softirq: */
- local_bh_enable();
- } else
- rc = -EIO;
- return rc;
-}
-
-static int qeth_l3_open(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT(card, 5, "qethope_");
- if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
- QETH_CARD_TEXT(card, 3, "openREC");
- return -ERESTARTSYS;
- }
- return __qeth_l3_open(dev);
-}
-
-static int qeth_l3_stop(struct net_device *dev)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT(card, 4, "qethstop");
- netif_tx_disable(dev);
- if (card->state == CARD_STATE_UP) {
- card->state = CARD_STATE_SOFTSETUP;
- napi_disable(&card->napi);
- }
- return 0;
-}
-
-static const struct ethtool_ops qeth_l3_ethtool_ops = {
- .get_link = ethtool_op_get_link,
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
- .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
-};
-
/*
* we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
* NOARP on the netdevice is no option because it also turns off neighbor
@@ -2193,9 +2136,9 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
}
static const struct net_device_ops qeth_l3_netdev_ops = {
- .ndo_open = qeth_l3_open,
- .ndo_stop = qeth_l3_stop,
- .ndo_get_stats = qeth_get_stats,
+ .ndo_open = qeth_open,
+ .ndo_stop = qeth_stop,
+ .ndo_get_stats64 = qeth_get_stats64,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = qeth_l3_set_rx_mode,
@@ -2208,9 +2151,9 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
};
static const struct net_device_ops qeth_l3_osa_netdev_ops = {
- .ndo_open = qeth_l3_open,
- .ndo_stop = qeth_l3_stop,
- .ndo_get_stats = qeth_get_stats,
+ .ndo_open = qeth_open,
+ .ndo_stop = qeth_stop,
+ .ndo_get_stats64 = qeth_get_stats64,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_features_check = qeth_l3_osa_features_check,
.ndo_validate_addr = eth_validate_addr,
@@ -2229,9 +2172,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
unsigned int headroom;
int rc;
- if (qeth_netdev_is_registered(card->dev))
- return 0;
-
if (card->info.type == QETH_CARD_TYPE_OSD ||
card->info.type == QETH_CARD_TYPE_OSX) {
if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
@@ -2283,7 +2223,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
return -ENODEV;
card->dev->needed_headroom = headroom;
- card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -2338,17 +2277,18 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE)
qeth_l3_set_offline(cgdev);
+ cancel_work_sync(&card->close_dev_work);
if (qeth_netdev_is_registered(card->dev))
unregister_netdev(card->dev);
qeth_l3_clear_ip_htable(card, 0);
qeth_l3_clear_ipato_list(card);
}
-static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+static int qeth_l3_set_online(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+ struct net_device *dev = card->dev;
int rc = 0;
- enum qeth_card_states recover_flag;
bool carrier_ok;
mutex_lock(&card->discipline_mutex);
@@ -2356,7 +2296,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
- recover_flag = card->state;
rc = qeth_core_hardsetup_card(card, &carrier_ok);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
@@ -2364,10 +2303,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
goto out_remove;
}
- rc = qeth_l3_setup_netdev(card, carrier_ok);
- if (rc)
- goto out_remove;
-
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap &&
qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
@@ -2397,7 +2332,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "5err%04x", rc);
}
- netif_tx_disable(card->dev);
rc = qeth_init_qdio_queues(card);
if (rc) {
@@ -2410,14 +2344,23 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_set_allowed_threads(card, 0xffffffff, 0);
qeth_l3_recover_ip(card);
- qeth_enable_hw_features(card->dev);
- if (recover_flag == CARD_STATE_RECOVER) {
+ if (!qeth_netdev_is_registered(dev)) {
+ rc = qeth_l3_setup_netdev(card, carrier_ok);
+ if (rc)
+ goto out_remove;
+ } else {
rtnl_lock();
- if (recovery_mode) {
- __qeth_l3_open(card->dev);
- qeth_l3_set_rx_mode(card->dev);
- } else {
- dev_open(card->dev, NULL);
+ if (carrier_ok)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
+
+ netif_device_attach(dev);
+ qeth_enable_hw_features(dev);
+
+ if (card->info.open_when_online) {
+ card->info.open_when_online = 0;
+ dev_open(dev, NULL);
}
rtnl_unlock();
}
@@ -2428,45 +2371,43 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
mutex_unlock(&card->discipline_mutex);
return 0;
out_remove:
- qeth_l3_stop_card(card, 0);
+ qeth_l3_stop_card(card);
ccw_device_set_offline(CARD_DDEV(card));
ccw_device_set_offline(CARD_WDEV(card));
ccw_device_set_offline(CARD_RDEV(card));
qdio_free(CARD_DDEV(card));
- if (recover_flag == CARD_STATE_RECOVER)
- card->state = CARD_STATE_RECOVER;
- else
- card->state = CARD_STATE_DOWN;
+ card->state = CARD_STATE_DOWN;
+
mutex_unlock(&card->conf_mutex);
mutex_unlock(&card->discipline_mutex);
return rc;
}
-static int qeth_l3_set_online(struct ccwgroup_device *gdev)
-{
- return __qeth_l3_set_online(gdev, 0);
-}
-
static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
int recovery_mode)
{
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
int rc = 0, rc2 = 0, rc3 = 0;
- enum qeth_card_states recover_flag;
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
- netif_carrier_off(card->dev);
- recover_flag = card->state;
if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
card->info.hwtrap = 1;
}
- qeth_l3_stop_card(card, recovery_mode);
- if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) {
+
+ rtnl_lock();
+ card->info.open_when_online = card->dev->flags & IFF_UP;
+ dev_close(card->dev);
+ netif_device_detach(card->dev);
+ netif_carrier_off(card->dev);
+ rtnl_unlock();
+
+ qeth_l3_stop_card(card);
+ if (card->options.cq == QETH_CQ_ENABLED) {
rtnl_lock();
call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
rtnl_unlock();
@@ -2479,8 +2420,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
qdio_free(CARD_DDEV(card));
- if (recover_flag == CARD_STATE_UP)
- card->state = CARD_STATE_RECOVER;
+
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&card->conf_mutex);
@@ -2506,18 +2446,16 @@ static int qeth_l3_recover(void *ptr)
QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n");
- qeth_set_recovery_task(card);
__qeth_l3_set_offline(card->gdev, 1);
- rc = __qeth_l3_set_online(card->gdev, 1);
+ rc = qeth_l3_set_online(card->gdev);
if (!rc)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
else {
- qeth_close_dev(card);
+ ccwgroup_set_offline(card->gdev);
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
- qeth_clear_recovery_task(card);
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
@@ -2527,37 +2465,23 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- netif_device_detach(card->dev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE)
return 0;
- if (card->state == CARD_STATE_UP) {
- if (card->info.hwtrap)
- qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
- __qeth_l3_set_offline(card->gdev, 1);
- } else
- __qeth_l3_set_offline(card->gdev, 0);
+
+ qeth_l3_set_offline(gdev);
return 0;
}
static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- int rc = 0;
+ int rc;
- if (card->state == CARD_STATE_RECOVER) {
- rc = __qeth_l3_set_online(card->gdev, 1);
- if (rc) {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
- }
- } else
- rc = __qeth_l3_set_online(card->gdev, 0);
+ rc = qeth_l3_set_online(gdev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
- netif_device_attach(card->dev);
if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index 45ac6d8705c6..cff518b0f904 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -167,8 +167,7 @@ static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
@@ -213,8 +212,7 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
return -EPERM;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
@@ -280,8 +278,7 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
- if (card->state != CARD_STATE_DOWN &&
- card->state != CARD_STATE_RECOVER)
+ if (card->state != CARD_STATE_DOWN)
return -EPERM;
if (card->options.sniffer)
return -EPERM;
@@ -356,8 +353,7 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
return -EINVAL;
mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
+ if (card->state != CARD_STATE_DOWN) {
rc = -EPERM;
goto out;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 9cf30d124b9e..e390f8c6d5f3 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -403,7 +403,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
goto failed;
/* report size limit per scatter-gather segment */
- adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 10c4e8e3fd59..661436a92f8e 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -294,8 +294,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
id->input_handler = zfcp_qdio_int_resp;
id->output_handler = zfcp_qdio_int_req;
id->int_parm = (unsigned long) qdio;
- id->input_sbal_addr_array = (void **) (qdio->res_q);
- id->output_sbal_addr_array = (void **) (qdio->req_q);
+ id->input_sbal_addr_array = qdio->res_q;
+ id->output_sbal_addr_array = qdio->req_q;
id->scan_threshold =
QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 00acc7144bbc..f4f6a07c5222 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -428,6 +428,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
* ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
/* GCD, adjusted later */
+ /* report size limit per scatter-gather segment */
+ .max_segment_size = ZFCP_QDIO_SBALE_LEN,
.dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
.shost_attrs = zfcp_sysfs_shost_attrs,
.sdev_attrs = zfcp_sysfs_sdev_attrs,
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index fc9dbad476c0..ae1d56da671d 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -635,7 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
{
struct virtio_ccw_device *vcdev = to_vc_device(vdev);
unsigned long *indicatorp = NULL;
- int ret, i;
+ int ret, i, queue_idx = 0;
struct ccw1 *ccw;
ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
@@ -643,8 +643,14 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
return -ENOMEM;
for (i = 0; i < nvqs; ++i) {
- vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i],
- ctx ? ctx[i] : false, ccw);
+ if (!names[i]) {
+ vqs[i] = NULL;
+ continue;
+ }
+
+ vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i],
+ names[i], ctx ? ctx[i] : false,
+ ccw);
if (IS_ERR(vqs[i])) {
ret = PTR_ERR(vqs[i]);
vqs[i] = NULL;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index a3c20e3a8b7c..3337b1e80412 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -2009,7 +2009,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
struct Scsi_Host *host = NULL;
TW_Device_Extension *tw_dev;
unsigned long mem_addr, mem_len;
- int retval = -ENODEV;
+ int retval;
retval = pci_enable_device(pdev);
if (retval) {
@@ -2020,8 +2020,10 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (retval)
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
retval = -ENODEV;
goto out_disable_device;
@@ -2240,8 +2242,10 @@ static int twa_resume(struct pci_dev *pdev)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (retval)
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume");
retval = -ENODEV;
goto out_disable_device;
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index e8f5f7c63190..dda6fa857709 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -646,8 +646,9 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
unsigned long *cpu_addr;
int retval = 1;
- cpu_addr = dma_zalloc_coherent(&tw_dev->tw_pci_dev->dev,
- size * TW_Q_LENGTH, &dma_handle, GFP_KERNEL);
+ cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev,
+ size * TW_Q_LENGTH, &dma_handle,
+ GFP_KERNEL);
if (!cpu_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
goto out;
@@ -1572,8 +1573,10 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (retval)
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask");
retval = -ENODEV;
goto out_disable_device;
@@ -1804,8 +1807,10 @@ static int twl_resume(struct pci_dev *pdev)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (retval)
+ retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume");
retval = -ENODEV;
goto out_disable_device;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 128d658d472a..16957d7ac414 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -295,7 +295,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
if(tpnt->sdev_attrs == NULL)
tpnt->sdev_attrs = NCR_700_dev_attrs;
- memory = dma_alloc_attrs(hostdata->dev, TOTAL_MEM_SIZE, &pScript,
+ memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript,
GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
if(memory == NULL) {
printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n");
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index f38882f6f37d..8f9d9e9fa695 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1369,14 +1369,14 @@ config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI
select SCSI_SPI_ATTRS
- select NVRAM
---help---
If you have an Atari with built-in NCR5380 SCSI controller (TT,
Falcon, ...) say Y to get it supported. Of course also, if you have
a compatible SCSI controller (e.g. for Medusa).
- To compile this driver as a module, choose M here: the
- module will be called atari_scsi.
+ To compile this driver as a module, choose M here: the module will
+ be called atari_scsi. If you also enable NVRAM support, the SCSI
+ host's ID is taken from the setting in TT RTC NVRAM.
This driver supports both styles of NCR integration into the
system: the TT style (separate DMA), and the Falcon style (via
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index ff53fd0d12f2..66c514310f3c 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1123,8 +1123,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
/* Get total memory needed for SCB */
sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
- host->scb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->scb_phys,
- GFP_KERNEL);
+ host->scb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->scb_phys,
+ GFP_KERNEL);
if (!host->scb_virt) {
printk("inia100: SCB memory allocation error\n");
goto out_host_put;
@@ -1132,8 +1132,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
/* Get total memory needed for ESCB */
sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
- host->escb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->escb_phys,
- GFP_KERNEL);
+ host->escb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->escb_phys,
+ GFP_KERNEL);
if (!host->escb_virt) {
printk("inia100: ESCB memory allocation error\n");
goto out_free_scb_array;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 634ddb90e7aa..7e56a11836c1 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1747,11 +1747,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
shost->max_sectors = (shost->sg_tablesize * 8) + 112;
}
- error = dma_set_max_seg_size(&pdev->dev,
- (aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
- (shost->max_sectors << 9) : 65536);
- if (error)
- goto out_deinit;
+ if (aac->adapter_info.options & AAC_OPT_NEW_COMM)
+ shost->max_segment_size = shost->max_sectors << 9;
+ else
+ shost->max_segment_size = 65536;
/*
* Firmware printf works only with older firmware.
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index f83f79b07b50..bbdae67774f0 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -280,7 +280,7 @@ static ssize_t asd_show_dev_rev(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n",
asd_dev_rev[asd_ha->revision_id]);
}
-static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL);
+static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
static ssize_t asd_show_dev_bios_build(struct device *dev,
struct device_attribute *attr,char *buf)
@@ -477,7 +477,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
{
int err;
- err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+ err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
if (err)
return err;
@@ -499,13 +499,13 @@ err_update_bios:
err_biosb:
device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
err_rev:
- device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+ device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
return err;
}
static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
{
- device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+ device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
@@ -769,9 +769,11 @@ static int asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (err)
goto Err_remove;
- err = -ENODEV;
- if (dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32))) {
+ err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64));
+ if (err)
+ err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ err = -ENODEV;
asd_printk("no suitable DMA mask for %s\n", pci_name(dev));
goto Err_remove;
}
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 0f6751b0a633..57c6fa388bf6 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -587,8 +587,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg;
acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_B), 32);
- dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
- &dma_coherent_handle, GFP_KERNEL);
+ dma_coherent = dma_alloc_coherent(&pdev->dev,
+ acb->roundup_ccbsize,
+ &dma_coherent_handle,
+ GFP_KERNEL);
if (!dma_coherent) {
pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
return false;
@@ -617,8 +619,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
struct MessageUnit_D *reg;
acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32);
- dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
- &dma_coherent_handle, GFP_KERNEL);
+ dma_coherent = dma_alloc_coherent(&pdev->dev,
+ acb->roundup_ccbsize,
+ &dma_coherent_handle,
+ GFP_KERNEL);
if (!dma_coherent) {
pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
return false;
@@ -659,8 +663,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
uint32_t completeQ_size;
completeQ_size = sizeof(struct deliver_completeQ) * ARCMSR_MAX_HBE_DONEQUEUE + 128;
acb->roundup_ccbsize = roundup(completeQ_size, 32);
- dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
- &dma_coherent_handle, GFP_KERNEL);
+ dma_coherent = dma_alloc_coherent(&pdev->dev,
+ acb->roundup_ccbsize,
+ &dma_coherent_handle,
+ GFP_KERNEL);
if (!dma_coherent){
pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
return false;
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index a503dc50c4f8..e809493d0d06 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -757,15 +757,17 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
if (setup_hostid >= 0) {
atari_scsi_template.this_id = setup_hostid & 7;
- } else {
+ } else if (IS_REACHABLE(CONFIG_NVRAM)) {
/* Test if a host id is set in the NVRam */
- if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
- unsigned char b = nvram_read_byte(16);
+ if (ATARIHW_PRESENT(TT_CLK)) {
+ unsigned char b;
+ loff_t offset = 16;
+ ssize_t count = nvram_read(&b, 1, &offset);
/* Arbitration enabled? (for TOS)
* If yes, use configured host ID
*/
- if (b & 0x80)
+ if ((count == 1) && (b & 0x80))
atari_scsi_template.this_id = b & 7;
}
}
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 39f3820572b4..76e49d902609 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -3321,8 +3321,8 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
q->len = len;
q->entry_size = entry_size;
mem->size = len * entry_size;
- mem->va = dma_zalloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
- GFP_KERNEL);
+ mem->va = dma_alloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
+ GFP_KERNEL);
if (!mem->va)
return -ENOMEM;
return 0;
@@ -3566,7 +3566,7 @@ static void be2iscsi_enable_msix(struct beiscsi_hba *phba)
/* if eqid_count == 1 fall back to INTX */
if (enable_msix && nvec > 1) {
- const struct irq_affinity desc = { .post_vectors = 1 };
+ struct irq_affinity desc = { .post_vectors = 1 };
if (pci_alloc_irq_vectors_affinity(phba->pcidev, 2, nvec,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc) < 0) {
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index ca7b7bbc8371..d4febaadfaa3 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -293,8 +293,8 @@ static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
struct be_dma_mem *cmd,
u8 subsystem, u8 opcode, u32 size)
{
- cmd->va = dma_zalloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
- GFP_KERNEL);
+ cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
+ GFP_KERNEL);
if (!cmd->va) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BG_%d : Failed to allocate memory for if info\n");
@@ -1510,10 +1510,9 @@ int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
return -EINVAL;
nonemb_cmd.size = sizeof(union be_invldt_cmds_params);
- nonemb_cmd.va = dma_zalloc_coherent(&phba->ctrl.pdev->dev,
- nonemb_cmd.size,
- &nonemb_cmd.dma,
- GFP_KERNEL);
+ nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
+ nonemb_cmd.size, &nonemb_cmd.dma,
+ GFP_KERNEL);
if (!nonemb_cmd.va) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
"BM_%d : invldt_cmds_params alloc failed\n");
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 42a0caf6740d..88880a66a189 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -727,7 +727,7 @@ bfad_init_timer(struct bfad_s *bfad)
int
bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
{
- int rc = -ENODEV;
+ int rc = -ENODEV;
if (pci_enable_device(pdev)) {
printk(KERN_ERR "pci_enable_device fail %p\n", pdev);
@@ -739,8 +739,12 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
pci_set_master(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (rc)
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+
+ if (rc) {
+ rc = -ENODEV;
printk(KERN_ERR "dma_set_mask_and_coherent fail %p\n", pdev);
goto out_release_region;
}
@@ -1534,6 +1538,7 @@ bfad_pci_slot_reset(struct pci_dev *pdev)
{
struct bfad_s *bfad = pci_get_drvdata(pdev);
u8 byte;
+ int rc;
dev_printk(KERN_ERR, &pdev->dev,
"bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags);
@@ -1561,8 +1566,11 @@ bfad_pci_slot_reset(struct pci_dev *pdev)
pci_save_state(pdev);
pci_set_master(pdev);
- if (dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(32)))
+ rc = dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(64));
+ if (rc)
+ rc = dma_set_mask_and_coherent(&bfad->pcidev->dev,
+ DMA_BIT_MASK(32));
+ if (rc)
goto out_disable_device;
if (restart_bfa(bfad) == -1)
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 5d163ca1b366..d8e6d7480f35 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3264,9 +3264,9 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
/* Allocate dma coherent memory */
buf_info = buf_base;
buf_info->size = payload_len;
- buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
- buf_info->size, &buf_info->phys,
- GFP_KERNEL);
+ buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev,
+ buf_info->size, &buf_info->phys,
+ GFP_KERNEL);
if (!buf_info->virt)
goto out_free_mem;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index e8ae4d671d23..039328d9ef13 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1857,10 +1857,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
* entries. Hence the limit with one page is 8192 task context
* entries.
*/
- hba->task_ctx_bd_tbl = dma_zalloc_coherent(&hba->pcidev->dev,
- PAGE_SIZE,
- &hba->task_ctx_bd_dma,
- GFP_KERNEL);
+ hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+ PAGE_SIZE,
+ &hba->task_ctx_bd_dma,
+ GFP_KERNEL);
if (!hba->task_ctx_bd_tbl) {
printk(KERN_ERR PFX "unable to allocate task context BDT\n");
rc = -1;
@@ -1894,10 +1894,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
for (i = 0; i < task_ctx_arr_sz; i++) {
- hba->task_ctx[i] = dma_zalloc_coherent(&hba->pcidev->dev,
- PAGE_SIZE,
- &hba->task_ctx_dma[i],
- GFP_KERNEL);
+ hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
+ PAGE_SIZE,
+ &hba->task_ctx_dma[i],
+ GFP_KERNEL);
if (!hba->task_ctx[i]) {
printk(KERN_ERR PFX "unable to alloc task context\n");
rc = -1;
@@ -2031,19 +2031,19 @@ static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba)
}
for (i = 0; i < segment_count; ++i) {
- hba->hash_tbl_segments[i] = dma_zalloc_coherent(&hba->pcidev->dev,
- BNX2FC_HASH_TBL_CHUNK_SIZE,
- &dma_segment_array[i],
- GFP_KERNEL);
+ hba->hash_tbl_segments[i] = dma_alloc_coherent(&hba->pcidev->dev,
+ BNX2FC_HASH_TBL_CHUNK_SIZE,
+ &dma_segment_array[i],
+ GFP_KERNEL);
if (!hba->hash_tbl_segments[i]) {
printk(KERN_ERR PFX "hash segment alloc failed\n");
goto cleanup_dma;
}
}
- hba->hash_tbl_pbl = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
- &hba->hash_tbl_pbl_dma,
- GFP_KERNEL);
+ hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+ &hba->hash_tbl_pbl_dma,
+ GFP_KERNEL);
if (!hba->hash_tbl_pbl) {
printk(KERN_ERR PFX "hash table pbl alloc failed\n");
goto cleanup_dma;
@@ -2104,10 +2104,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
return -ENOMEM;
mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
- hba->t2_hash_tbl_ptr = dma_zalloc_coherent(&hba->pcidev->dev,
- mem_size,
- &hba->t2_hash_tbl_ptr_dma,
- GFP_KERNEL);
+ hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+ &hba->t2_hash_tbl_ptr_dma,
+ GFP_KERNEL);
if (!hba->t2_hash_tbl_ptr) {
printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n");
bnx2fc_free_fw_resc(hba);
@@ -2116,9 +2115,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
mem_size = BNX2FC_NUM_MAX_SESS *
sizeof(struct fcoe_t2_hash_table_entry);
- hba->t2_hash_tbl = dma_zalloc_coherent(&hba->pcidev->dev, mem_size,
- &hba->t2_hash_tbl_dma,
- GFP_KERNEL);
+ hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+ &hba->t2_hash_tbl_dma,
+ GFP_KERNEL);
if (!hba->t2_hash_tbl) {
printk(KERN_ERR PFX "unable to allocate t2 hash table\n");
bnx2fc_free_fw_resc(hba);
@@ -2140,9 +2139,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
return -ENOMEM;
}
- hba->stats_buffer = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
- &hba->stats_buf_dma,
- GFP_KERNEL);
+ hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+ &hba->stats_buf_dma,
+ GFP_KERNEL);
if (!hba->stats_buffer) {
printk(KERN_ERR PFX "unable to alloc Stats Buffer\n");
bnx2fc_free_fw_resc(hba);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 350257c13a5b..bc9f2a2365f4 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -240,6 +240,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
return NULL;
}
+ cmgr->hba = hba;
cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list),
GFP_KERNEL);
if (!cmgr->free_list) {
@@ -256,7 +257,6 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
goto mem_err;
}
- cmgr->hba = hba;
cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
for (i = 0; i < arr_sz; i++) {
@@ -295,7 +295,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
/* Allocate pool of io_bdts - one for each bnx2fc_cmd */
mem_size = num_ios * sizeof(struct io_bdt *);
- cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+ cmgr->io_bdt_pool = kzalloc(mem_size, GFP_KERNEL);
if (!cmgr->io_bdt_pool) {
printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
goto mem_err;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index e3d1c7c440c8..d735e87e416a 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -672,8 +672,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->sq_mem_size = (tgt->sq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->sq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
- &tgt->sq_dma, GFP_KERNEL);
+ tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+ &tgt->sq_dma, GFP_KERNEL);
if (!tgt->sq) {
printk(KERN_ERR PFX "unable to allocate SQ memory %d\n",
tgt->sq_mem_size);
@@ -685,8 +685,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->cq_mem_size = (tgt->cq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->cq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
- &tgt->cq_dma, GFP_KERNEL);
+ tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+ &tgt->cq_dma, GFP_KERNEL);
if (!tgt->cq) {
printk(KERN_ERR PFX "unable to allocate CQ memory %d\n",
tgt->cq_mem_size);
@@ -698,8 +698,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->rq_mem_size = (tgt->rq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->rq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
- &tgt->rq_dma, GFP_KERNEL);
+ tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+ &tgt->rq_dma, GFP_KERNEL);
if (!tgt->rq) {
printk(KERN_ERR PFX "unable to allocate RQ memory %d\n",
tgt->rq_mem_size);
@@ -710,8 +710,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->rq_pbl_size = (tgt->rq_pbl_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->rq_pbl = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
- &tgt->rq_pbl_dma, GFP_KERNEL);
+ tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+ &tgt->rq_pbl_dma, GFP_KERNEL);
if (!tgt->rq_pbl) {
printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n",
tgt->rq_pbl_size);
@@ -735,9 +735,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->xferq_mem_size = (tgt->xferq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->xferq = dma_zalloc_coherent(&hba->pcidev->dev,
- tgt->xferq_mem_size, &tgt->xferq_dma,
- GFP_KERNEL);
+ tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev,
+ tgt->xferq_mem_size, &tgt->xferq_dma,
+ GFP_KERNEL);
if (!tgt->xferq) {
printk(KERN_ERR PFX "unable to allocate XFERQ %d\n",
tgt->xferq_mem_size);
@@ -749,9 +749,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->confq_mem_size = (tgt->confq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->confq = dma_zalloc_coherent(&hba->pcidev->dev,
- tgt->confq_mem_size, &tgt->confq_dma,
- GFP_KERNEL);
+ tgt->confq = dma_alloc_coherent(&hba->pcidev->dev,
+ tgt->confq_mem_size, &tgt->confq_dma,
+ GFP_KERNEL);
if (!tgt->confq) {
printk(KERN_ERR PFX "unable to allocate CONFQ %d\n",
tgt->confq_mem_size);
@@ -763,9 +763,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->confq_pbl_size =
(tgt->confq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
- tgt->confq_pbl = dma_zalloc_coherent(&hba->pcidev->dev,
- tgt->confq_pbl_size,
- &tgt->confq_pbl_dma, GFP_KERNEL);
+ tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+ tgt->confq_pbl_size,
+ &tgt->confq_pbl_dma, GFP_KERNEL);
if (!tgt->confq_pbl) {
printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n",
tgt->confq_pbl_size);
@@ -787,9 +787,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
/* Allocate and map ConnDB */
tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db);
- tgt->conn_db = dma_zalloc_coherent(&hba->pcidev->dev,
- tgt->conn_db_mem_size,
- &tgt->conn_db_dma, GFP_KERNEL);
+ tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev,
+ tgt->conn_db_mem_size,
+ &tgt->conn_db_dma, GFP_KERNEL);
if (!tgt->conn_db) {
printk(KERN_ERR PFX "unable to allocate conn_db %d\n",
tgt->conn_db_mem_size);
@@ -802,8 +802,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
tgt->lcq_mem_size = (tgt->lcq_mem_size + (CNIC_PAGE_SIZE - 1)) &
CNIC_PAGE_MASK;
- tgt->lcq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
- &tgt->lcq_dma, GFP_KERNEL);
+ tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+ &tgt->lcq_dma, GFP_KERNEL);
if (!tgt->lcq) {
printk(KERN_ERR PFX "unable to allocate lcq %d\n",
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 91f5316aa3ab..fae6f71e677d 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1070,8 +1070,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
/* Allocate memory area for actual SQ element */
ep->qp.sq_virt =
- dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
- &ep->qp.sq_phys, GFP_KERNEL);
+ dma_alloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
+ &ep->qp.sq_phys, GFP_KERNEL);
if (!ep->qp.sq_virt) {
printk(KERN_ALERT "bnx2i: unable to alloc SQ BD memory %d\n",
ep->qp.sq_mem_size);
@@ -1106,8 +1106,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
/* Allocate memory area for actual CQ element */
ep->qp.cq_virt =
- dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
- &ep->qp.cq_phys, GFP_KERNEL);
+ dma_alloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
+ &ep->qp.cq_phys, GFP_KERNEL);
if (!ep->qp.cq_virt) {
printk(KERN_ALERT "bnx2i: unable to alloc CQ BD memory %d\n",
ep->qp.cq_mem_size);
diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c
index 8a004036e3d7..9bd2bd8dc2be 100644
--- a/drivers/scsi/csiostor/csio_attr.c
+++ b/drivers/scsi/csiostor/csio_attr.c
@@ -594,12 +594,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable)
}
fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+ ln->fc_vport = fc_vport;
if (csio_fcoe_alloc_vnp(hw, ln))
goto error;
*(struct csio_lnode **)fc_vport->dd_data = ln;
- ln->fc_vport = fc_vport;
if (!fc_vport->node_name)
fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
if (!fc_vport->port_name)
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index cf629380a981..616b25bf7941 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -210,8 +210,11 @@ csio_pci_init(struct pci_dev *pdev, int *bars)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (rv)
+ rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (rv) {
+ rv = -ENODEV;
dev_err(&pdev->dev, "No suitable DMA available.\n");
goto err_release_regions;
}
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index dc12933533d5..66bbd21819ae 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -233,8 +233,8 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
q = wrm->q_arr[free_idx];
- q->vstart = dma_zalloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
- GFP_KERNEL);
+ q->vstart = dma_alloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
+ GFP_KERNEL);
if (!q->vstart) {
csio_err(hw,
"Failed to allocate DMA memory for "
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index 8a20411699d9..75e1273a44b3 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm,
}
static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
- unsigned int tid, int pg_idx, bool reply)
+ unsigned int tid, int pg_idx)
{
struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
GFP_KERNEL);
@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
req = (struct cpl_set_tcb_field *)skb->head;
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
- req->reply = V_NO_REPLY(reply ? 0 : 1);
+ req->reply = V_NO_REPLY(1);
req->cpu_idx = 0;
req->word = htons(31);
req->mask = cpu_to_be64(0xF0000000);
@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
* @tid: connection id
* @hcrc: header digest enabled
* @dcrc: data digest enabled
- * @reply: request reply from h/w
* set up the iscsi digest settings for a connection identified by tid
*/
static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
- int hcrc, int dcrc, int reply)
+ int hcrc, int dcrc)
{
struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
GFP_KERNEL);
@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head;
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
- req->reply = V_NO_REPLY(reply ? 0 : 1);
+ req->reply = V_NO_REPLY(1);
req->cpu_idx = 0;
req->word = htons(31);
req->mask = cpu_to_be64(0x0F000000);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 49f8028ac524..d26f50af00ea 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
struct cxgbi_sock *csk;
csk = lookup_tid(t, tid);
- if (!csk)
+ if (!csk) {
pr_err("can't find conn. for tid %u.\n", tid);
+ return;
+ }
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p,%u,%lx,%u, status 0x%x.\n",
csk, csk->state, csk->flags, csk->tid, rpl->status);
- if (rpl->status != CPL_ERR_NONE)
+ if (rpl->status != CPL_ERR_NONE) {
pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
csk, tid, rpl->status);
+ csk->err = -EINVAL;
+ }
+
+ complete(&csk->cmpl);
__kfree_skb(skb);
}
@@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk,
}
static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
- int pg_idx, bool reply)
+ int pg_idx)
{
struct sk_buff *skb;
struct cpl_set_tcb_field *req;
@@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head;
INIT_TP_WR(req, csk->tid);
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
- req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+ req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
req->word_cookie = htons(0);
req->mask = cpu_to_be64(0x3 << 8);
req->val = cpu_to_be64(pg_idx << 8);
@@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
+ reinit_completion(&csk->cmpl);
cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
- return 0;
+ wait_for_completion(&csk->cmpl);
+
+ return csk->err;
}
static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
- int hcrc, int dcrc, int reply)
+ int hcrc, int dcrc)
{
struct sk_buff *skb;
struct cpl_set_tcb_field *req;
@@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head;
INIT_TP_WR(req, tid);
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
- req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+ req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
req->word_cookie = htons(0);
req->mask = cpu_to_be64(0x3 << 4);
req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
@@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
+ reinit_completion(&csk->cmpl);
cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
- return 0;
+ wait_for_completion(&csk->cmpl);
+
+ return csk->err;
}
static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev)
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 75f876409fb9..245742557c03 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
skb_queue_head_init(&csk->receive_queue);
skb_queue_head_init(&csk->write_queue);
timer_setup(&csk->retry_timer, NULL, 0);
+ init_completion(&csk->cmpl);
rwlock_init(&csk->callback_lock);
csk->cdev = cdev;
csk->flags = 0;
@@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
if (!err && conn->hdrdgst_en)
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
conn->hdrdgst_en,
- conn->datadgst_en, 0);
+ conn->datadgst_en);
break;
case ISCSI_PARAM_DATADGST_EN:
err = iscsi_set_param(cls_conn, param, buf, buflen);
if (!err && conn->datadgst_en)
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
conn->hdrdgst_en,
- conn->datadgst_en, 0);
+ conn->datadgst_en);
break;
case ISCSI_PARAM_MAX_R2T:
return iscsi_tcp_set_max_r2t(conn, buf);
@@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
ppm = csk->cdev->cdev2ppm(csk->cdev);
err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
- ppm->tformat.pgsz_idx_dflt, 0);
+ ppm->tformat.pgsz_idx_dflt);
if (err < 0)
return err;
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 5d5d8b50d842..1917ff57651d 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -149,6 +149,7 @@ struct cxgbi_sock {
struct sk_buff_head receive_queue;
struct sk_buff_head write_queue;
struct timer_list retry_timer;
+ struct completion cmpl;
int err;
rwlock_t callback_lock;
void *user_data;
@@ -490,9 +491,9 @@ struct cxgbi_device {
struct cxgbi_ppm *,
struct cxgbi_task_tag_info *);
int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
- unsigned int, int, int, int);
+ unsigned int, int, int);
int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
- unsigned int, int, bool);
+ unsigned int, int);
void (*csk_release_offload_resources)(struct cxgbi_sock *);
int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index bfa13e3b191c..c8bad2c093b8 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3687,6 +3687,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
host->max_cmd_len = CXLFLASH_MAX_CDB_LEN;
cfg = shost_priv(host);
+ cfg->state = STATE_PROBING;
cfg->host = host;
rc = alloc_mem(cfg);
if (rc) {
@@ -3775,6 +3776,7 @@ out:
return rc;
out_remove:
+ cfg->state = STATE_PROBED;
cxlflash_remove(pdev);
goto out;
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index eed7fc5b3389..bc17fa0d8375 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -2323,6 +2323,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
struct Scsi_Host *shost;
struct hisi_hba *hisi_hba;
struct device *dev = &pdev->dev;
+ int error;
shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba));
if (!shost) {
@@ -2343,8 +2344,11 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
if (hisi_sas_get_fw_info(hisi_hba) < 0)
goto err_out;
- if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
- dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
+ error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (error)
+ error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+
+ if (error) {
dev_err(dev, "No usable DMA addressing method\n");
goto err_out;
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index e2420a810e99..e0570fd8466e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -2447,10 +2447,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
goto err_out_disable_device;
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (rc)
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (rc) {
dev_err(dev, "No usable DMA addressing method\n");
- rc = -EIO;
+ rc = -ENODEV;
goto err_out_regions;
}
@@ -2507,6 +2509,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
}
+ if (hisi_hba->prot_mask) {
+ dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
+ prot_mask);
+ scsi_host_set_prot(hisi_hba->shost, prot_mask);
+ }
+
rc = scsi_add_host(shost, dev);
if (rc)
goto err_out_ha;
@@ -2519,12 +2527,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
goto err_out_register_ha;
- if (hisi_hba->prot_mask) {
- dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
- prot_mask);
- scsi_host_set_prot(hisi_hba->shost, prot_mask);
- }
-
scsi_scan_host(shost);
return 0;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 3eedfd4f8f57..251c084a6ff0 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -1292,6 +1292,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
dma_addr_t start_phy;
void *start_virt;
u32 offset, i, req_size;
+ int rc;
dprintk("hptiop_probe(%p)\n", pcidev);
@@ -1308,9 +1309,12 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
/* Enable 64bit DMA if possible */
iop_ops = (struct hptiop_adapter_ops *)id->driver_data;
- if (dma_set_mask(&pcidev->dev,
- DMA_BIT_MASK(iop_ops->hw_dma_bit_mask)) ||
- dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32))) {
+ rc = dma_set_mask(&pcidev->dev,
+ DMA_BIT_MASK(iop_ops->hw_dma_bit_mask));
+ if (rc)
+ rc = dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32));
+
+ if (rc) {
printk(KERN_ERR "hptiop: fail to set dma_mask\n");
goto disable_pci_device;
}
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 68b90c4f79a3..1727d0c71b12 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -576,6 +576,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
shost->max_lun = ~0;
shost->max_cmd_len = MAX_COMMAND_SIZE;
+ /* turn on DIF support */
+ scsi_host_set_prot(shost,
+ SHOST_DIF_TYPE1_PROTECTION |
+ SHOST_DIF_TYPE2_PROTECTION |
+ SHOST_DIF_TYPE3_PROTECTION);
+ scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
err = scsi_add_host(shost, &pdev->dev);
if (err)
goto err_shost;
@@ -663,13 +670,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_host_alloc;
}
pci_info->hosts[i] = h;
-
- /* turn on DIF support */
- scsi_host_set_prot(to_shost(h),
- SHOST_DIF_TYPE1_PROTECTION |
- SHOST_DIF_TYPE2_PROTECTION |
- SHOST_DIF_TYPE3_PROTECTION);
- scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
}
err = isci_setup_interrupts(pdev);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index be83590ed955..ff943f477d6f 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1726,14 +1726,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
fc_frame_payload_op(fp) != ELS_LS_ACC) {
FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
fc_lport_error(lport, fp);
- goto err;
+ goto out;
}
flp = fc_frame_payload_get(fp, sizeof(*flp));
if (!flp) {
FC_LPORT_DBG(lport, "FLOGI bad response\n");
fc_lport_error(lport, fp);
- goto err;
+ goto out;
}
mfs = ntohs(flp->fl_csp.sp_bb_data) &
@@ -1743,7 +1743,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
"lport->mfs:%hu\n", mfs, lport->mfs);
fc_lport_error(lport, fp);
- goto err;
+ goto out;
}
if (mfs <= lport->mfs) {
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 9192a1d9dec6..dfba4921b265 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -184,7 +184,6 @@ void fc_rport_destroy(struct kref *kref)
struct fc_rport_priv *rdata;
rdata = container_of(kref, struct fc_rport_priv, kref);
- WARN_ON(!list_empty(&rdata->peers));
kfree_rcu(rdata, rcu);
}
EXPORT_SYMBOL(fc_rport_destroy);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index b8d325ce8754..120fc520f27a 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1459,7 +1459,13 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx))
return -ENODATA;
+ spin_lock_bh(&conn->session->back_lock);
+ if (conn->task == NULL) {
+ spin_unlock_bh(&conn->session->back_lock);
+ return -ENODATA;
+ }
__iscsi_get_task(task);
+ spin_unlock_bh(&conn->session->back_lock);
spin_unlock_bh(&conn->session->frwd_lock);
rc = conn->session->tt->xmit_task(task);
spin_lock_bh(&conn->session->frwd_lock);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 17eb4185f29d..f21c93bbb35c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -828,6 +828,7 @@ static struct domain_device *sas_ex_discover_end_dev(
rphy = sas_end_device_alloc(phy->port);
if (!rphy)
goto out_free;
+ rphy->identify.phy_identifier = phy_id;
child->rphy = rphy;
get_device(&rphy->dev);
@@ -854,6 +855,7 @@ static struct domain_device *sas_ex_discover_end_dev(
child->rphy = rphy;
get_device(&rphy->dev);
+ rphy->identify.phy_identifier = phy_id;
sas_fill_in_rphy(child, rphy);
list_add_tail(&child->disco_list_node, &parent->port->disco_list);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 8698af86485d..2dc564e59430 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2730,8 +2730,8 @@ lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)
INIT_LIST_HEAD(&dmabuf->list);
/* now, allocate dma buffer */
- dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
- &(dmabuf->phys), GFP_KERNEL);
+ dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
+ &(dmabuf->phys), GFP_KERNEL);
if (!dmabuf->virt) {
kfree(dmabuf);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index c1c36812c3d2..e1129260ed18 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -6973,9 +6973,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
if (!dmabuf)
return NULL;
- dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
- LPFC_HDR_TEMPLATE_SIZE,
- &dmabuf->phys, GFP_KERNEL);
+ dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+ LPFC_HDR_TEMPLATE_SIZE,
+ &dmabuf->phys, GFP_KERNEL);
if (!dmabuf->virt) {
rpi_hdr = NULL;
goto err_free_dmabuf;
@@ -7361,15 +7361,18 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
unsigned long bar0map_len, bar2map_len;
int i, hbq_count;
void *ptr;
- int error = -ENODEV;
+ int error;
if (!pdev)
- return error;
+ return -ENODEV;
/* Set the device DMA mask size */
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
+ error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (error)
+ error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (error)
return error;
+ error = -ENODEV;
/* Get the bus address of Bar0 and Bar2 and the number of bytes
* required by each mapping.
@@ -7397,8 +7400,8 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
}
/* Allocate memory for SLI-2 structures */
- phba->slim2p.virt = dma_zalloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
- &phba->slim2p.phys, GFP_KERNEL);
+ phba->slim2p.virt = dma_alloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+ &phba->slim2p.phys, GFP_KERNEL);
if (!phba->slim2p.virt)
goto out_iounmap;
@@ -7816,8 +7819,8 @@ lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
* plus an alignment restriction of 16 bytes.
*/
bmbx_size = sizeof(struct lpfc_bmbx_create) + (LPFC_ALIGN_16_BYTE - 1);
- dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, bmbx_size,
- &dmabuf->phys, GFP_KERNEL);
+ dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, bmbx_size,
+ &dmabuf->phys, GFP_KERNEL);
if (!dmabuf->virt) {
kfree(dmabuf);
return -ENOMEM;
@@ -9742,11 +9745,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
uint32_t if_type;
if (!pdev)
- return error;
+ return -ENODEV;
/* Set the device DMA mask size */
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) ||
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
+ error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (error)
+ error = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (error)
return error;
/*
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index f6a5083a621e..4d3b94317515 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1827,9 +1827,9 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
* page, this is used as a priori size of SLI4_PAGE_SIZE for
* the later DMA memory free.
*/
- viraddr = dma_zalloc_coherent(&phba->pcidev->dev,
- SLI4_PAGE_SIZE, &phyaddr,
- GFP_KERNEL);
+ viraddr = dma_alloc_coherent(&phba->pcidev->dev,
+ SLI4_PAGE_SIZE, &phyaddr,
+ GFP_KERNEL);
/* In case of malloc fails, proceed with whatever we have */
if (!viraddr)
break;
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 4c66b19e6199..8c9f79042228 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -297,7 +297,8 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport)
lport);
/* release any threads waiting for the unreg to complete */
- complete(&lport->lport_unreg_done);
+ if (lport->vport->localport)
+ complete(lport->lport_unreg_cmp);
}
/* lpfc_nvme_remoteport_delete
@@ -2545,7 +2546,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
*/
void
lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
- struct lpfc_nvme_lport *lport)
+ struct lpfc_nvme_lport *lport,
+ struct completion *lport_unreg_cmp)
{
#if (IS_ENABLED(CONFIG_NVME_FC))
u32 wait_tmo;
@@ -2557,8 +2559,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
*/
wait_tmo = msecs_to_jiffies(LPFC_NVME_WAIT_TMO * 1000);
while (true) {
- ret = wait_for_completion_timeout(&lport->lport_unreg_done,
- wait_tmo);
+ ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo);
if (unlikely(!ret)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
"6176 Lport %p Localport %p wait "
@@ -2592,12 +2593,12 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_ctrl_stat *cstat;
int ret;
+ DECLARE_COMPLETION_ONSTACK(lport_unreg_cmp);
if (vport->nvmei_support == 0)
return;
localport = vport->localport;
- vport->localport = NULL;
lport = (struct lpfc_nvme_lport *)localport->private;
cstat = lport->cstat;
@@ -2608,13 +2609,14 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
/* lport's rport list is clear. Unregister
* lport and release resources.
*/
- init_completion(&lport->lport_unreg_done);
+ lport->lport_unreg_cmp = &lport_unreg_cmp;
ret = nvme_fc_unregister_localport(localport);
/* Wait for completion. This either blocks
* indefinitely or succeeds
*/
- lpfc_nvme_lport_unreg_wait(vport, lport);
+ lpfc_nvme_lport_unreg_wait(vport, lport, &lport_unreg_cmp);
+ vport->localport = NULL;
kfree(cstat);
/* Regardless of the unregister upcall response, clear
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
index cfd4719be25c..b234d0298994 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.h
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
@@ -50,7 +50,7 @@ struct lpfc_nvme_ctrl_stat {
/* Declare nvme-based local and remote port definitions. */
struct lpfc_nvme_lport {
struct lpfc_vport *vport;
- struct completion lport_unreg_done;
+ struct completion *lport_unreg_cmp;
/* Add stats counters here */
struct lpfc_nvme_ctrl_stat *cstat;
atomic_t fc4NvmeLsRequests;
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 6245f442d784..95fee83090eb 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1003,7 +1003,8 @@ lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
struct lpfc_nvmet_tgtport *tport = targetport->private;
/* release any threads waiting for the unreg to complete */
- complete(&tport->tport_unreg_done);
+ if (tport->phba->targetport)
+ complete(tport->tport_unreg_cmp);
}
static void
@@ -1692,6 +1693,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
struct lpfc_nvmet_tgtport *tgtp;
struct lpfc_queue *wq;
uint32_t qidx;
+ DECLARE_COMPLETION_ONSTACK(tport_unreg_cmp);
if (phba->nvmet_support == 0)
return;
@@ -1701,9 +1703,9 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
wq = phba->sli4_hba.nvme_wq[qidx];
lpfc_nvmet_wqfull_flush(phba, wq, NULL);
}
- init_completion(&tgtp->tport_unreg_done);
+ tgtp->tport_unreg_cmp = &tport_unreg_cmp;
nvmet_fc_unregister_targetport(phba->targetport);
- wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+ wait_for_completion_timeout(&tport_unreg_cmp, 5);
lpfc_nvmet_cleanup_io_context(phba);
}
phba->targetport = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
index 1aaff63f1f41..0ec1082ce7ef 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.h
+++ b/drivers/scsi/lpfc/lpfc_nvmet.h
@@ -34,7 +34,7 @@
/* Used for NVME Target */
struct lpfc_nvmet_tgtport {
struct lpfc_hba *phba;
- struct completion tport_unreg_done;
+ struct completion *tport_unreg_cmp;
/* Stats counters - lpfc_nvmet_unsol_ls_buffer */
atomic_t rcv_ls_req_in;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 30734caf77e1..2242e9b3ca12 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5362,8 +5362,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
* mailbox command.
*/
dma_size = *vpd_size;
- dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, dma_size,
- &dmabuf->phys, GFP_KERNEL);
+ dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, dma_size,
+ &dmabuf->phys, GFP_KERNEL);
if (!dmabuf->virt) {
kfree(dmabuf);
return -ENOMEM;
@@ -6300,10 +6300,9 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba,
goto free_mem;
}
- dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
+ dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
LPFC_RAS_MAX_ENTRY_SIZE,
- &dmabuf->phys,
- GFP_KERNEL);
+ &dmabuf->phys, GFP_KERNEL);
if (!dmabuf->virt) {
kfree(dmabuf);
rc = -ENOMEM;
@@ -9408,6 +9407,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
cmnd = CMD_XMIT_SEQUENCE64_CR;
if (phba->link_flag & LS_LOOPBACK_MODE)
bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
+ /* fall through */
case CMD_XMIT_SEQUENCE64_CR:
/* word3 iocb=io_tag32 wqe=reserved */
wqe->xmit_sequence.rsvd3 = 0;
@@ -13529,6 +13529,7 @@ 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");
+ /* fall through */
case FC_STATUS_RQ_SUCCESS:
spin_lock_irqsave(&phba->hbalock, iflags);
lpfc_sli4_rq_release(hrq, drq);
@@ -13938,7 +13939,7 @@ 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");
- /* Drop thru */
+ /* fall through */
case FC_STATUS_RQ_SUCCESS:
spin_lock_irqsave(&phba->hbalock, iflags);
lpfc_sli4_rq_release(hrq, drq);
@@ -14613,9 +14614,9 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size,
dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (!dmabuf)
goto out_fail;
- dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
- hw_page_size, &dmabuf->phys,
- GFP_KERNEL);
+ dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+ hw_page_size, &dmabuf->phys,
+ GFP_KERNEL);
if (!dmabuf->virt) {
kfree(dmabuf);
goto out_fail;
@@ -14850,7 +14851,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
eq->entry_count);
if (eq->entry_count < 256)
return -EINVAL;
- /* otherwise default to smallest count (drop through) */
+ /* fall through - otherwise default to smallest count */
case 256:
bf_set(lpfc_eq_context_count, &eq_create->u.request.context,
LPFC_EQ_CNT_256);
@@ -14981,7 +14982,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
LPFC_CQ_CNT_WORD7);
break;
}
- /* Fall Thru */
+ /* fall through */
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0361 Unsupported CQ count: "
@@ -14992,7 +14993,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
status = -EINVAL;
goto out;
}
- /* otherwise default to smallest count (drop through) */
+ /* fall through - otherwise default to smallest count */
case 256:
bf_set(lpfc_cq_context_count, &cq_create->u.request.context,
LPFC_CQ_CNT_256);
@@ -15152,7 +15153,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
LPFC_CQ_CNT_WORD7);
break;
}
- /* Fall Thru */
+ /* fall through */
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3118 Bad CQ count. (%d)\n",
@@ -15161,7 +15162,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
status = -EINVAL;
goto out;
}
- /* otherwise default to smallest (drop thru) */
+ /* fall through - otherwise default to smallest */
case 256:
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request, LPFC_CQ_CNT_256);
@@ -15433,7 +15434,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
status = -EINVAL;
goto out;
}
- /* otherwise default to smallest count (drop through) */
+ /* fall through - otherwise default to smallest count */
case 16:
bf_set(lpfc_mq_context_ring_size,
&mq_create_ext->u.request.context,
@@ -15852,7 +15853,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
status = -EINVAL;
goto out;
}
- /* otherwise default to smallest count (drop through) */
+ /* fall through - otherwise default to smallest count */
case 512:
bf_set(lpfc_rq_context_rqe_count,
&rq_create->u.request.context,
@@ -15989,7 +15990,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
status = -EINVAL;
goto out;
}
- /* otherwise default to smallest count (drop through) */
+ /* fall through - otherwise default to smallest count */
case 512:
bf_set(lpfc_rq_context_rqe_count,
&rq_create->u.request.context,
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index e836392b75e8..f112458023ff 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -967,9 +967,10 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
* Allocate the common 16-byte aligned memory for the handshake
* mailbox.
*/
- raid_dev->una_mbox64 = dma_zalloc_coherent(&adapter->pdev->dev,
- sizeof(mbox64_t), &raid_dev->una_mbox64_dma,
- GFP_KERNEL);
+ raid_dev->una_mbox64 = dma_alloc_coherent(&adapter->pdev->dev,
+ sizeof(mbox64_t),
+ &raid_dev->una_mbox64_dma,
+ GFP_KERNEL);
if (!raid_dev->una_mbox64) {
con_log(CL_ANN, (KERN_WARNING
@@ -995,8 +996,8 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
align;
// Allocate memory for commands issued internally
- adapter->ibuf = dma_zalloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
- &adapter->ibuf_dma_h, GFP_KERNEL);
+ adapter->ibuf = dma_alloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
+ &adapter->ibuf_dma_h, GFP_KERNEL);
if (!adapter->ibuf) {
con_log(CL_ANN, (KERN_WARNING
@@ -2897,8 +2898,8 @@ megaraid_mbox_product_info(adapter_t *adapter)
* Issue an ENQUIRY3 command to find out certain adapter parameters,
* e.g., max channels, max commands etc.
*/
- pinfo = dma_zalloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
- &pinfo_dma_h, GFP_KERNEL);
+ pinfo = dma_alloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
+ &pinfo_dma_h, GFP_KERNEL);
if (pinfo == NULL) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __func__,
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index f7bdd783360a..fcbff83c0097 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -2273,9 +2273,9 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
sizeof(struct MR_LD_VF_AFFILIATION_111));
else {
new_affiliation_111 =
- dma_zalloc_coherent(&instance->pdev->dev,
- sizeof(struct MR_LD_VF_AFFILIATION_111),
- &new_affiliation_111_h, GFP_KERNEL);
+ dma_alloc_coherent(&instance->pdev->dev,
+ sizeof(struct MR_LD_VF_AFFILIATION_111),
+ &new_affiliation_111_h, GFP_KERNEL);
if (!new_affiliation_111) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
"memory for new affiliation for scsi%d\n",
@@ -2380,10 +2380,9 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
sizeof(struct MR_LD_VF_AFFILIATION));
else {
new_affiliation =
- dma_zalloc_coherent(&instance->pdev->dev,
- (MAX_LOGICAL_DRIVES + 1) *
- sizeof(struct MR_LD_VF_AFFILIATION),
- &new_affiliation_h, GFP_KERNEL);
+ dma_alloc_coherent(&instance->pdev->dev,
+ (MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION),
+ &new_affiliation_h, GFP_KERNEL);
if (!new_affiliation) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
"memory for new affiliation for scsi%d\n",
@@ -2546,9 +2545,10 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
if (initial) {
instance->hb_host_mem =
- dma_zalloc_coherent(&instance->pdev->dev,
- sizeof(struct MR_CTRL_HB_HOST_MEM),
- &instance->hb_host_mem_h, GFP_KERNEL);
+ dma_alloc_coherent(&instance->pdev->dev,
+ sizeof(struct MR_CTRL_HB_HOST_MEM),
+ &instance->hb_host_mem_h,
+ GFP_KERNEL);
if (!instance->hb_host_mem) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate"
" memory for heartbeat host memory for scsi%d\n",
@@ -5816,9 +5816,9 @@ megasas_get_seq_num(struct megasas_instance *instance,
}
dcmd = &cmd->frame->dcmd;
- el_info = dma_zalloc_coherent(&instance->pdev->dev,
- sizeof(struct megasas_evt_log_info), &el_info_h,
- GFP_KERNEL);
+ el_info = dma_alloc_coherent(&instance->pdev->dev,
+ sizeof(struct megasas_evt_log_info),
+ &el_info_h, GFP_KERNEL);
if (!el_info) {
megasas_return_cmd(instance, cmd);
return -ENOMEM;
@@ -6236,7 +6236,7 @@ megasas_set_dma_mask(struct megasas_instance *instance)
instance->consistent_mask_64bit = true;
dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n",
- ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"),
+ ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"),
(instance->consistent_mask_64bit ? "63" : "32"));
return 0;
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 211c17c33aa0..647f48a28f85 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance)
/*
* Check if it is our interrupt
*/
- status = readl(&regs->outbound_intr_status);
+ status = megasas_readl(instance,
+ &regs->outbound_intr_status);
if (status & 1) {
writel(status, &regs->outbound_intr_status);
@@ -689,8 +690,9 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
MAX_MSIX_QUEUES_FUSION;
- fusion->rdpq_virt = dma_zalloc_coherent(&instance->pdev->dev,
- array_size, &fusion->rdpq_phys, GFP_KERNEL);
+ fusion->rdpq_virt = dma_alloc_coherent(&instance->pdev->dev,
+ array_size, &fusion->rdpq_phys,
+ GFP_KERNEL);
if (!fusion->rdpq_virt) {
dev_err(&instance->pdev->dev,
"Failed from %s %d\n", __func__, __LINE__);
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index f3e182eb0970..c9dc7740e9e7 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1915,8 +1915,9 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
/* We use the PCI APIs for now until the generic one gets fixed
* enough or until we get some macio-specific versions
*/
- dma_cmd_space = dma_zalloc_coherent(&macio_get_pci_dev(mdev)->dev,
- ms->dma_cmd_size, &dma_cmd_bus, GFP_KERNEL);
+ dma_cmd_space = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
+ ms->dma_cmd_size, &dma_cmd_bus,
+ GFP_KERNEL);
if (dma_cmd_space == NULL) {
printk(KERN_ERR "mesh: can't allocate DMA table\n");
goto out_unmap;
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index dbe753fba486..36f64205ecfa 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -143,8 +143,9 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
case RESOURCE_UNCACHED_MEMORY:
size = round_up(size, 8);
- res->virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size,
- &res->bus_addr, GFP_KERNEL);
+ res->virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size,
+ &res->bus_addr,
+ GFP_KERNEL);
if (!res->virt_addr) {
dev_err(&mhba->pdev->dev,
"unable to allocate consistent mem,"
@@ -246,8 +247,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
if (size == 0)
return 0;
- virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size, &phy_addr,
- GFP_KERNEL);
+ virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size, &phy_addr,
+ GFP_KERNEL);
if (!virt_addr)
return -1;
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index b3be49d41375..084f2fcced0a 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -116,8 +116,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
u64 align_offset = 0;
if (align)
align_offset = (dma_addr_t)align - 1;
- mem_virt_alloc = dma_zalloc_coherent(&pdev->dev, mem_size + align,
- &mem_dma_handle, GFP_KERNEL);
+ mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
+ &mem_dma_handle, GFP_KERNEL);
if (!mem_virt_alloc) {
pm8001_printk("memory allocation error\n");
return -1;
@@ -657,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
if (dev->dev_type == SAS_SATA_DEV) {
pm8001_device->attached_phy =
dev->rphy->identify.phy_identifier;
- flag = 1; /* directly sata*/
+ flag = 1; /* directly sata */
}
} /*register this device to HBA*/
PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index edcaf4b0cb0b..9bbc19fc190b 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -1050,16 +1050,17 @@ static int qedf_alloc_sq(struct qedf_ctx *qedf, struct qedf_rport *fcport)
sizeof(void *);
fcport->sq_pbl_size = fcport->sq_pbl_size + QEDF_PAGE_SIZE;
- fcport->sq = dma_zalloc_coherent(&qedf->pdev->dev,
- fcport->sq_mem_size, &fcport->sq_dma, GFP_KERNEL);
+ fcport->sq = dma_alloc_coherent(&qedf->pdev->dev, fcport->sq_mem_size,
+ &fcport->sq_dma, GFP_KERNEL);
if (!fcport->sq) {
QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue.\n");
rval = 1;
goto out;
}
- fcport->sq_pbl = dma_zalloc_coherent(&qedf->pdev->dev,
- fcport->sq_pbl_size, &fcport->sq_pbl_dma, GFP_KERNEL);
+ fcport->sq_pbl = dma_alloc_coherent(&qedf->pdev->dev,
+ fcport->sq_pbl_size,
+ &fcport->sq_pbl_dma, GFP_KERNEL);
if (!fcport->sq_pbl) {
QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue PBL.\n");
rval = 1;
@@ -2680,8 +2681,10 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf)
}
/* Allocate list of PBL pages */
- qedf->bdq_pbl_list = dma_zalloc_coherent(&qedf->pdev->dev,
- QEDF_PAGE_SIZE, &qedf->bdq_pbl_list_dma, GFP_KERNEL);
+ qedf->bdq_pbl_list = dma_alloc_coherent(&qedf->pdev->dev,
+ QEDF_PAGE_SIZE,
+ &qedf->bdq_pbl_list_dma,
+ GFP_KERNEL);
if (!qedf->bdq_pbl_list) {
QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL pages.\n");
return -ENOMEM;
@@ -2770,9 +2773,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
ALIGN(qedf->global_queues[i]->cq_pbl_size, QEDF_PAGE_SIZE);
qedf->global_queues[i]->cq =
- dma_zalloc_coherent(&qedf->pdev->dev,
- qedf->global_queues[i]->cq_mem_size,
- &qedf->global_queues[i]->cq_dma, GFP_KERNEL);
+ dma_alloc_coherent(&qedf->pdev->dev,
+ qedf->global_queues[i]->cq_mem_size,
+ &qedf->global_queues[i]->cq_dma,
+ GFP_KERNEL);
if (!qedf->global_queues[i]->cq) {
QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq.\n");
@@ -2781,9 +2785,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
}
qedf->global_queues[i]->cq_pbl =
- dma_zalloc_coherent(&qedf->pdev->dev,
- qedf->global_queues[i]->cq_pbl_size,
- &qedf->global_queues[i]->cq_pbl_dma, GFP_KERNEL);
+ dma_alloc_coherent(&qedf->pdev->dev,
+ qedf->global_queues[i]->cq_pbl_size,
+ &qedf->global_queues[i]->cq_pbl_dma,
+ GFP_KERNEL);
if (!qedf->global_queues[i]->cq_pbl) {
QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq PBL.\n");
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index 4da660c1c431..6d6d6013e35b 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -953,6 +953,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
qedi_ep = ep->dd_data;
if (qedi_ep->state == EP_STATE_IDLE ||
+ qedi_ep->state == EP_STATE_OFLDCONN_NONE ||
qedi_ep->state == EP_STATE_OFLDCONN_FAILED)
return -1;
@@ -1035,6 +1036,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
switch (qedi_ep->state) {
case EP_STATE_OFLDCONN_START:
+ case EP_STATE_OFLDCONN_NONE:
goto ep_release_conn;
case EP_STATE_OFLDCONN_FAILED:
break;
@@ -1225,6 +1227,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
+ qedi_ep->state = EP_STATE_OFLDCONN_NONE;
ret = -EIO;
goto set_path_exit;
}
diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h
index 11260776212f..892d70d54553 100644
--- a/drivers/scsi/qedi/qedi_iscsi.h
+++ b/drivers/scsi/qedi/qedi_iscsi.h
@@ -59,6 +59,7 @@ enum {
EP_STATE_OFLDCONN_FAILED = 0x2000,
EP_STATE_CONNECT_FAILED = 0x4000,
EP_STATE_DISCONN_TIMEDOUT = 0x8000,
+ EP_STATE_OFLDCONN_NONE = 0x10000,
};
struct qedi_conn;
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 5c53409a8cea..e74a62448ba4 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -1394,10 +1394,9 @@ static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi)
{
struct qedi_nvm_iscsi_image nvm_image;
- qedi->iscsi_image = dma_zalloc_coherent(&qedi->pdev->dev,
- sizeof(nvm_image),
- &qedi->nvm_buf_dma,
- GFP_KERNEL);
+ qedi->iscsi_image = dma_alloc_coherent(&qedi->pdev->dev,
+ sizeof(nvm_image),
+ &qedi->nvm_buf_dma, GFP_KERNEL);
if (!qedi->iscsi_image) {
QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n");
return -ENOMEM;
@@ -1510,10 +1509,10 @@ static int qedi_alloc_bdq(struct qedi_ctx *qedi)
}
/* Allocate list of PBL pages */
- qedi->bdq_pbl_list = dma_zalloc_coherent(&qedi->pdev->dev,
- QEDI_PAGE_SIZE,
- &qedi->bdq_pbl_list_dma,
- GFP_KERNEL);
+ qedi->bdq_pbl_list = dma_alloc_coherent(&qedi->pdev->dev,
+ QEDI_PAGE_SIZE,
+ &qedi->bdq_pbl_list_dma,
+ GFP_KERNEL);
if (!qedi->bdq_pbl_list) {
QEDI_ERR(&qedi->dbg_ctx,
"Could not allocate list of PBL pages.\n");
@@ -1609,10 +1608,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
(qedi->global_queues[i]->cq_pbl_size +
(QEDI_PAGE_SIZE - 1));
- qedi->global_queues[i]->cq = dma_zalloc_coherent(&qedi->pdev->dev,
- qedi->global_queues[i]->cq_mem_size,
- &qedi->global_queues[i]->cq_dma,
- GFP_KERNEL);
+ qedi->global_queues[i]->cq = dma_alloc_coherent(&qedi->pdev->dev,
+ qedi->global_queues[i]->cq_mem_size,
+ &qedi->global_queues[i]->cq_dma,
+ GFP_KERNEL);
if (!qedi->global_queues[i]->cq) {
QEDI_WARN(&qedi->dbg_ctx,
@@ -1620,10 +1619,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
status = -ENOMEM;
goto mem_alloc_failure;
}
- qedi->global_queues[i]->cq_pbl = dma_zalloc_coherent(&qedi->pdev->dev,
- qedi->global_queues[i]->cq_pbl_size,
- &qedi->global_queues[i]->cq_pbl_dma,
- GFP_KERNEL);
+ qedi->global_queues[i]->cq_pbl = dma_alloc_coherent(&qedi->pdev->dev,
+ qedi->global_queues[i]->cq_pbl_size,
+ &qedi->global_queues[i]->cq_pbl_dma,
+ GFP_KERNEL);
if (!qedi->global_queues[i]->cq_pbl) {
QEDI_WARN(&qedi->dbg_ctx,
@@ -1691,16 +1690,16 @@ int qedi_alloc_sq(struct qedi_ctx *qedi, struct qedi_endpoint *ep)
ep->sq_pbl_size = (ep->sq_mem_size / QEDI_PAGE_SIZE) * sizeof(void *);
ep->sq_pbl_size = ep->sq_pbl_size + QEDI_PAGE_SIZE;
- ep->sq = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
- &ep->sq_dma, GFP_KERNEL);
+ ep->sq = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
+ &ep->sq_dma, GFP_KERNEL);
if (!ep->sq) {
QEDI_WARN(&qedi->dbg_ctx,
"Could not allocate send queue.\n");
rval = -ENOMEM;
goto out;
}
- ep->sq_pbl = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
- &ep->sq_pbl_dma, GFP_KERNEL);
+ ep->sq_pbl = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
+ &ep->sq_pbl_dma, GFP_KERNEL);
if (!ep->sq_pbl) {
QEDI_WARN(&qedi->dbg_ctx,
"Could not allocate send queue PBL.\n");
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index a414f51302b7..6856dfdfa473 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -4248,7 +4248,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->devnum = devnum; /* specifies microcode load address */
#ifdef QLA_64BIT_PTR
- if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
+ if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) {
if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32))) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 00444dc79756..ac504a1ff0ff 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2415,8 +2415,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
if (qla2x00_chip_is_down(vha))
goto done;
- stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
- &stats_dma, GFP_KERNEL);
+ stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+ GFP_KERNEL);
if (!stats) {
ql_log(ql_log_warn, vha, 0x707d,
"Failed to allocate memory for stats.\n");
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 4a9fd8d944d6..17d42658ad9a 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2312,8 +2312,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job)
if (!IS_FWI2_CAPABLE(ha))
return -EPERM;
- stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
- &stats_dma, GFP_KERNEL);
+ stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+ GFP_KERNEL);
if (!stats) {
ql_log(ql_log_warn, vha, 0x70e2,
"Failed to allocate memory for stats.\n");
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 26b93c563f92..d1fc4958222a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4394,6 +4394,8 @@ typedef struct scsi_qla_host {
uint16_t n2n_id;
struct list_head gpnid_list;
struct fab_scan scan;
+
+ unsigned int irq_offset;
} scsi_qla_host_t;
struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 90cfa394f942..cbc3bc49d4d1 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -4147,9 +4147,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
return rval;
}
- sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(
- &vha->hw->pdev->dev, sizeof(struct ct_sns_pkt),
- &sp->u.iocb_cmd.u.ctarg.req_dma, GFP_KERNEL);
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ &sp->u.iocb_cmd.u.ctarg.req_dma,
+ GFP_KERNEL);
sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
if (!sp->u.iocb_cmd.u.ctarg.req) {
ql_log(ql_log_warn, vha, 0xffff,
@@ -4165,9 +4166,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
((vha->hw->max_fibre_devices - 1) *
sizeof(struct ct_sns_gpn_ft_data));
- sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(
- &vha->hw->pdev->dev, rspsz,
- &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
+ sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+ rspsz,
+ &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+ GFP_KERNEL);
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
ql_log(ql_log_warn, vha, 0xffff,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 364bb52ed2a6..8d1acc802a67 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1785,13 +1785,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
/* Issue Marker IOCB */
qla2x00_marker(vha, vha->hw->req_q_map[0],
- vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
+ vha->hw->rsp_q_map[0], fcport->loop_id, lun,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
}
done_free_sp:
sp->free(sp);
- sp->fcport->flags &= ~FCF_ASYNC_SENT;
+ fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
}
@@ -3099,8 +3099,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
FCE_SIZE, ha->fce, ha->fce_dma);
/* Allocate memory for Fibre Channel Event Buffer. */
- tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
- GFP_KERNEL);
+ tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+ GFP_KERNEL);
if (!tc) {
ql_log(ql_log_warn, vha, 0x00be,
"Unable to allocate (%d KB) for FCE.\n",
@@ -3131,8 +3131,8 @@ try_eft:
EFT_SIZE, ha->eft, ha->eft_dma);
/* Allocate memory for Extended Trace Buffer. */
- tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
- GFP_KERNEL);
+ tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+ GFP_KERNEL);
if (!tc) {
ql_log(ql_log_warn, vha, 0x00c1,
"Unable to allocate (%d KB) for EFT.\n",
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 30d3090842f8..8507c43b918c 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3446,6 +3446,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
"Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
}
}
+ vha->irq_offset = desc.pre_vectors;
ha->msix_entries = kcalloc(ha->msix_count,
sizeof(struct qla_msix_entry),
GFP_KERNEL);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index ea69dafc9774..c6ef83d0d99b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -6939,7 +6939,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost)
if (USER_CTRL_IRQ(vha->hw))
rc = blk_mq_map_queues(qmap);
else
- rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0);
+ rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset);
return rc;
}
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 1ef74aa2d00a..2bf5e3e639e1 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -153,8 +153,8 @@ int qla4xxx_get_sys_info(struct scsi_qla_host *ha)
dma_addr_t sys_info_dma;
int status = QLA_ERROR;
- sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
- &sys_info_dma, GFP_KERNEL);
+ sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+ &sys_info_dma, GFP_KERNEL);
if (sys_info == NULL) {
DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
ha->host_no, __func__));
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 5d56904687b9..dac9a7013208 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -625,9 +625,9 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
uint32_t mbox_sts[MBOX_REG_COUNT];
int status = QLA_ERROR;
- init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
- sizeof(struct addr_ctrl_blk),
- &init_fw_cb_dma, GFP_KERNEL);
+ init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk),
+ &init_fw_cb_dma, GFP_KERNEL);
if (init_fw_cb == NULL) {
DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
ha->host_no, __func__));
@@ -709,9 +709,9 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
- init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
- sizeof(struct addr_ctrl_blk),
- &init_fw_cb_dma, GFP_KERNEL);
+ init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk),
+ &init_fw_cb_dma, GFP_KERNEL);
if (init_fw_cb == NULL) {
printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
__func__);
@@ -1340,9 +1340,9 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
uint32_t mbox_sts[MBOX_REG_COUNT];
int status = QLA_ERROR;
- about_fw = dma_zalloc_coherent(&ha->pdev->dev,
- sizeof(struct about_fw_info),
- &about_fw_dma, GFP_KERNEL);
+ about_fw = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct about_fw_info),
+ &about_fw_dma, GFP_KERNEL);
if (!about_fw) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
"for about_fw\n", __func__));
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index d2b333d629be..5a31877c9d04 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -4052,8 +4052,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
dma_addr_t sys_info_dma;
int status = QLA_ERROR;
- sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
- &sys_info_dma, GFP_KERNEL);
+ sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+ &sys_info_dma, GFP_KERNEL);
if (sys_info == NULL) {
DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
ha->host_no, __func__));
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 949e186cc5d7..a77bfb224248 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -2704,9 +2704,9 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
uint32_t rem = len;
struct nlattr *attr;
- init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
- sizeof(struct addr_ctrl_blk),
- &init_fw_cb_dma, GFP_KERNEL);
+ init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk),
+ &init_fw_cb_dma, GFP_KERNEL);
if (!init_fw_cb) {
ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
__func__);
@@ -4206,8 +4206,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
sizeof(struct shadow_regs) +
MEM_ALIGN_VALUE +
(PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
- ha->queues = dma_zalloc_coherent(&ha->pdev->dev, ha->queues_len,
- &ha->queues_dma, GFP_KERNEL);
+ ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
+ &ha->queues_dma, GFP_KERNEL);
if (ha->queues == NULL) {
ql4_printk(KERN_WARNING, ha,
"Memory Allocation failed - queues.\n");
@@ -7232,6 +7232,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
fw_ddb_entry);
+ if (rc)
+ goto free_sess;
ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
__func__, fnode_sess->dev.kobj.name);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 661512bec3ac..e27f4df24021 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -62,7 +62,7 @@
/* make sure inq_product_rev string corresponds to this version */
#define SDEBUG_VERSION "0188" /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20180128";
+static const char *sdebug_version_date = "20190125";
#define MY_NAME "scsi_debug"
@@ -735,7 +735,7 @@ static inline bool scsi_debug_lbp(void)
(sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
}
-static void *fake_store(unsigned long long lba)
+static void *lba2fake_store(unsigned long long lba)
{
lba = do_div(lba, sdebug_store_sectors);
@@ -2514,8 +2514,8 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
return ret;
}
-/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
- * arr into fake_store(lba,num) and return true. If comparison fails then
+/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of
+ * arr into lba2fake_store(lba,num) and return true. If comparison fails then
* return false. */
static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
{
@@ -2643,7 +2643,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
if (sdt->app_tag == cpu_to_be16(0xffff))
continue;
- ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
+ ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba);
if (ret) {
dif_errors++;
return ret;
@@ -3261,10 +3261,12 @@ err_out:
static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
u32 ei_lba, bool unmap, bool ndob)
{
+ int ret;
unsigned long iflags;
unsigned long long i;
- int ret;
- u64 lba_off;
+ u32 lb_size = sdebug_sector_size;
+ u64 block, lbaa;
+ u8 *fs1p;
ret = check_device_access_params(scp, lba, num);
if (ret)
@@ -3276,31 +3278,30 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
unmap_region(lba, num);
goto out;
}
-
- lba_off = lba * sdebug_sector_size;
+ lbaa = lba;
+ block = do_div(lbaa, sdebug_store_sectors);
/* if ndob then zero 1 logical block, else fetch 1 logical block */
+ fs1p = fake_storep + (block * lb_size);
if (ndob) {
- memset(fake_storep + lba_off, 0, sdebug_sector_size);
+ memset(fs1p, 0, lb_size);
ret = 0;
} else
- ret = fetch_to_dev_buffer(scp, fake_storep + lba_off,
- sdebug_sector_size);
+ ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
if (-1 == ret) {
write_unlock_irqrestore(&atomic_rw, iflags);
return DID_ERROR << 16;
- } else if (sdebug_verbose && !ndob && (ret < sdebug_sector_size))
+ } else if (sdebug_verbose && !ndob && (ret < lb_size))
sdev_printk(KERN_INFO, scp->device,
"%s: %s: lb size=%u, IO sent=%d bytes\n",
- my_name, "write same",
- sdebug_sector_size, ret);
+ my_name, "write same", lb_size, ret);
/* Copy first sector to remaining blocks */
- for (i = 1 ; i < num ; i++)
- memcpy(fake_storep + ((lba + i) * sdebug_sector_size),
- fake_storep + lba_off,
- sdebug_sector_size);
-
+ for (i = 1 ; i < num ; i++) {
+ lbaa = lba + i;
+ block = do_div(lbaa, sdebug_store_sectors);
+ memmove(fake_storep + (block * lb_size), fs1p, lb_size);
+ }
if (scsi_debug_lbp())
map_region(lba, num);
out:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b13cc9288ba0..a6828391d6b3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -655,6 +655,7 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
set_host_byte(cmd, DID_OK);
return BLK_STS_TARGET;
case DID_NEXUS_FAILURE:
+ set_host_byte(cmd, DID_OK);
return BLK_STS_NEXUS;
case DID_ALLOC_FAILURE:
set_host_byte(cmd, DID_OK);
@@ -1842,8 +1843,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
blk_queue_segment_boundary(q, shost->dma_boundary);
dma_set_seg_boundary(dev, shost->dma_boundary);
- blk_queue_max_segment_size(q,
- min(shost->max_segment_size, dma_get_max_seg_size(dev)));
+ blk_queue_max_segment_size(q, shost->max_segment_size);
+ dma_set_max_seg_size(dev, shost->max_segment_size);
/*
* Set a reasonable default alignment: The larger of 32-byte (dword),
@@ -2597,7 +2598,6 @@ void scsi_device_resume(struct scsi_device *sdev)
* device deleted during suspend)
*/
mutex_lock(&sdev->state_mutex);
- WARN_ON_ONCE(!sdev->quiesced_by);
sdev->quiesced_by = NULL;
blk_clear_pm_only(sdev->request_queue);
if (sdev->sdev_state == SDEV_QUIESCE)
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index a2b4179bfdf7..7639df91b110 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -80,8 +80,22 @@ static int scsi_dev_type_resume(struct device *dev,
if (err == 0) {
pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
+ err = pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+
+ /*
+ * Forcibly set runtime PM status of request queue to "active"
+ * to make sure we can again get requests from the queue
+ * (see also blk_pm_peek_request()).
+ *
+ * The resume hook will correct runtime PM status of the disk.
+ */
+ if (!err && scsi_is_sdev_device(dev)) {
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (sdev->request_queue->dev)
+ blk_set_runtime_active(sdev->request_queue);
+ }
}
return err;
@@ -140,16 +154,6 @@ static int scsi_bus_resume_common(struct device *dev,
else
fn = NULL;
- /*
- * Forcibly set runtime PM status of request queue to "active" to
- * make sure we can again get requests from the queue (see also
- * blk_pm_peek_request()).
- *
- * The resume hook will correct runtime PM status of the disk.
- */
- if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev))
- blk_set_runtime_active(to_scsi_device(dev)->request_queue);
-
if (fn) {
async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a1a44f52e0e8..5464d467e23e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
sp = buffer_data[0] & 0x80 ? 1 : 0;
buffer_data[0] &= ~0x80;
+ /*
+ * Ensure WP, DPOFUA, and RESERVED fields are cleared in
+ * received mode parameter buffer before doing MODE SELECT.
+ */
+ data.device_specific = 0;
+
if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
SD_MAX_RETRIES, &data, &sshdr)) {
if (scsi_sense_valid(&sshdr))
@@ -2945,9 +2951,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
if (rot == 1) {
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
- } else {
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
- blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
}
if (sdkp->device->type == TYPE_ZBC) {
@@ -3084,6 +3087,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
if (sdkp->media_present) {
sd_read_capacity(sdkp, buffer);
+ /*
+ * set the default to rotational. All non-rotational devices
+ * support the block characteristics VPD page, which will
+ * cause this to be updated correctly and any device which
+ * doesn't support it should be treated as rotational.
+ */
+ blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+ blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
+
if (scsi_device_supports_vpd(sdp)) {
sd_read_block_provisioning(sdkp);
sd_read_block_limits(sdkp);
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 83365b29a4d8..a340af797a85 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -142,10 +142,12 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
return -EOPNOTSUPP;
/*
- * Get a reply buffer for the number of requested zones plus a header.
- * For ATA, buffers must be aligned to 512B.
+ * Get a reply buffer for the number of requested zones plus a header,
+ * without exceeding the device maximum command size. For ATA disks,
+ * buffers must be aligned to 512B.
*/
- buflen = roundup((nrz + 1) * 64, 512);
+ buflen = min(queue_max_hw_sectors(disk->queue) << 9,
+ roundup((nrz + 1) * 64, 512));
buf = kmalloc(buflen, gfp_mask);
if (!buf)
return -ENOMEM;
@@ -462,12 +464,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
sdkp->device->use_10_for_rw = 0;
/*
- * If something changed, revalidate the disk zone bitmaps once we have
- * the capacity, that is on the second revalidate execution during disk
- * scan and always during normal revalidate.
+ * Revalidate the disk zone bitmaps once the block device capacity is
+ * set on the second revalidate execution during disk scan and if
+ * something changed when executing a normal revalidate.
*/
- if (sdkp->first_scan)
+ if (sdkp->first_scan) {
+ sdkp->zone_blocks = zone_blocks;
+ sdkp->nr_zones = nr_zones;
return 0;
+ }
+
if (sdkp->zone_blocks != zone_blocks ||
sdkp->nr_zones != nr_zones ||
disk->queue->nr_zones != nr_zones) {
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index e2fa3f476227..f564af8949e8 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -323,7 +323,7 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device)
static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device)
{
- return device->in_remove & !ctrl_info->in_shutdown;
+ return device->in_remove && !ctrl_info->in_shutdown;
}
static inline void pqi_schedule_rescan_worker_with_delay(
@@ -3576,9 +3576,9 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
alloc_length += PQI_EXTRA_SGL_MEMORY;
ctrl_info->queue_memory_base =
- dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
- alloc_length,
- &ctrl_info->queue_memory_base_dma_handle, GFP_KERNEL);
+ dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+ &ctrl_info->queue_memory_base_dma_handle,
+ GFP_KERNEL);
if (!ctrl_info->queue_memory_base)
return -ENOMEM;
@@ -3715,10 +3715,9 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info)
PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT;
ctrl_info->admin_queue_memory_base =
- dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
- alloc_length,
- &ctrl_info->admin_queue_memory_base_dma_handle,
- GFP_KERNEL);
+ dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+ &ctrl_info->admin_queue_memory_base_dma_handle,
+ GFP_KERNEL);
if (!ctrl_info->admin_queue_memory_base)
return -ENOMEM;
@@ -4602,9 +4601,10 @@ static void pqi_free_all_io_requests(struct pqi_ctrl_info *ctrl_info)
static inline int pqi_alloc_error_buffer(struct pqi_ctrl_info *ctrl_info)
{
- ctrl_info->error_buffer = dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
- ctrl_info->error_buffer_length,
- &ctrl_info->error_buffer_dma_handle, GFP_KERNEL);
+ ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev,
+ ctrl_info->error_buffer_length,
+ &ctrl_info->error_buffer_dma_handle,
+ GFP_KERNEL);
if (!ctrl_info->error_buffer)
return -ENOMEM;
@@ -7487,8 +7487,8 @@ static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info,
dma_addr_t dma_handle;
ctrl_info->pqi_ofa_chunk_virt_addr[i] =
- dma_zalloc_coherent(dev, chunk_size, &dma_handle,
- GFP_KERNEL);
+ dma_alloc_coherent(dev, chunk_size, &dma_handle,
+ GFP_KERNEL);
if (!ctrl_info->pqi_ofa_chunk_virt_addr[i])
break;
@@ -7545,10 +7545,10 @@ static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info *ctrl_info,
struct device *dev;
dev = &ctrl_info->pci_dev->dev;
- pqi_ofa_memory = dma_zalloc_coherent(dev,
- PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
- &ctrl_info->pqi_ofa_mem_dma_handle,
- GFP_KERNEL);
+ pqi_ofa_memory = dma_alloc_coherent(dev,
+ PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
+ &ctrl_info->pqi_ofa_mem_dma_handle,
+ GFP_KERNEL);
if (!pqi_ofa_memory)
return;
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index dd65fea07687..6d176815e6ce 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -195,7 +195,7 @@ enum ufs_desc_def_size {
QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90,
QUERY_DESC_UNIT_DEF_SIZE = 0x23,
QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
- QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44,
+ QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48,
QUERY_DESC_POWER_DEF_SIZE = 0x62,
QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
};
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9ba7671b84f8..2ddf24466a62 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -108,13 +108,19 @@
int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
const char *prefix)
{
- u8 *regs;
+ u32 *regs;
+ size_t pos;
+
+ if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */
+ return -EINVAL;
regs = kzalloc(len, GFP_KERNEL);
if (!regs)
return -ENOMEM;
- memcpy_fromio(regs, hba->mmio_base + offset, len);
+ for (pos = 0; pos < len; pos += 4)
+ regs[pos / 4] = ufshcd_readl(hba, offset + pos);
+
ufshcd_hex_dump(prefix, regs, len);
kfree(regs);
@@ -8001,6 +8007,8 @@ out:
trace_ufshcd_system_resume(dev_name(hba->dev), ret,
ktime_to_us(ktime_sub(ktime_get(), start)),
hba->curr_dev_pwr_mode, hba->uic_link_state);
+ if (!ret)
+ hba->is_sys_suspended = false;
return ret;
}
EXPORT_SYMBOL(ufshcd_system_resume);
diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c
index 55eda5863a6b..b2f07d2043eb 100644
--- a/drivers/slimbus/core.c
+++ b/drivers/slimbus/core.c
@@ -21,7 +21,9 @@ static const struct slim_device_id *slim_match(const struct slim_device_id *id,
{
while (id->manf_id != 0 || id->prod_code != 0) {
if (id->manf_id == sbdev->e_addr.manf_id &&
- id->prod_code == sbdev->e_addr.prod_code)
+ id->prod_code == sbdev->e_addr.prod_code &&
+ id->dev_index == sbdev->e_addr.dev_index &&
+ id->instance == sbdev->e_addr.instance)
return id;
id++;
}
@@ -40,6 +42,23 @@ static int slim_device_match(struct device *dev, struct device_driver *drv)
return !!slim_match(sbdrv->id_table, sbdev);
}
+static void slim_device_update_status(struct slim_device *sbdev,
+ enum slim_device_status status)
+{
+ struct slim_driver *sbdrv;
+
+ if (sbdev->status == status)
+ return;
+
+ sbdev->status = status;
+ if (!sbdev->dev.driver)
+ return;
+
+ sbdrv = to_slim_driver(sbdev->dev.driver);
+ if (sbdrv->device_status)
+ sbdrv->device_status(sbdev, sbdev->status);
+}
+
static int slim_device_probe(struct device *dev)
{
struct slim_device *sbdev = to_slim_device(dev);
@@ -53,8 +72,7 @@ static int slim_device_probe(struct device *dev)
/* try getting the logical address after probe */
ret = slim_get_logical_addr(sbdev);
if (!ret) {
- if (sbdrv->device_status)
- sbdrv->device_status(sbdev, sbdev->status);
+ slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP);
} else {
dev_err(&sbdev->dev, "Failed to get logical address\n");
ret = -EPROBE_DEFER;
@@ -256,6 +274,7 @@ int slim_register_controller(struct slim_controller *ctrl)
mutex_init(&ctrl->lock);
mutex_init(&ctrl->sched.m_reconf);
init_completion(&ctrl->sched.pause_comp);
+ spin_lock_init(&ctrl->txn_lock);
dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n",
ctrl->name, ctrl->dev);
@@ -295,23 +314,6 @@ int slim_unregister_controller(struct slim_controller *ctrl)
}
EXPORT_SYMBOL_GPL(slim_unregister_controller);
-static void slim_device_update_status(struct slim_device *sbdev,
- enum slim_device_status status)
-{
- struct slim_driver *sbdrv;
-
- if (sbdev->status == status)
- return;
-
- sbdev->status = status;
- if (!sbdev->dev.driver)
- return;
-
- sbdrv = to_slim_driver(sbdev->dev.driver);
- if (sbdrv->device_status)
- sbdrv->device_status(sbdev, sbdev->status);
-}
-
/**
* slim_report_absent() - Controller calls this function when a device
* reports absent, OR when the device cannot be communicated with
@@ -464,6 +466,7 @@ static int slim_device_alloc_laddr(struct slim_device *sbdev,
sbdev->laddr = laddr;
sbdev->is_laddr_valid = true;
+ mutex_unlock(&ctrl->lock);
slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP);
@@ -471,6 +474,8 @@ static int slim_device_alloc_laddr(struct slim_device *sbdev,
laddr, sbdev->e_addr.manf_id, sbdev->e_addr.prod_code,
sbdev->e_addr.dev_index, sbdev->e_addr.instance);
+ return 0;
+
err:
mutex_unlock(&ctrl->lock);
return ret;
diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c
index fce33ca76bb6..be95a37c3fec 100644
--- a/drivers/soc/amlogic/meson-canvas.c
+++ b/drivers/soc/amlogic/meson-canvas.c
@@ -51,16 +51,30 @@ struct meson_canvas *meson_canvas_get(struct device *dev)
{
struct device_node *canvas_node;
struct platform_device *canvas_pdev;
+ struct meson_canvas *canvas;
canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0);
if (!canvas_node)
return ERR_PTR(-ENODEV);
canvas_pdev = of_find_device_by_node(canvas_node);
- if (!canvas_pdev)
+ if (!canvas_pdev) {
+ of_node_put(canvas_node);
return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ of_node_put(canvas_node);
+
+ /*
+ * If priv is NULL, it's probably because the canvas hasn't
+ * properly initialized. Bail out with -EINVAL because, in the
+ * current state, this driver probe cannot return -EPROBE_DEFER
+ */
+ canvas = dev_get_drvdata(&canvas_pdev->dev);
+ if (!canvas)
+ return ERR_PTR(-EINVAL);
- return dev_get_drvdata(&canvas_pdev->dev);
+ return canvas;
}
EXPORT_SYMBOL_GPL(meson_canvas_get);
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
index daea191a66fa..19d4cbc93a17 100644
--- a/drivers/soc/amlogic/meson-clk-measure.c
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -165,6 +165,194 @@ static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
CLK_MSR_ID(82, "ge2d"),
};
+static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
+ CLK_MSR_ID(0, "ring_osc_out_ee_0"),
+ CLK_MSR_ID(1, "ring_osc_out_ee_1"),
+ CLK_MSR_ID(2, "ring_osc_out_ee_2"),
+ CLK_MSR_ID(3, "a53_ring_osc"),
+ CLK_MSR_ID(4, "gp0_pll"),
+ CLK_MSR_ID(5, "gp1_pll"),
+ CLK_MSR_ID(7, "clk81"),
+ CLK_MSR_ID(9, "encl"),
+ CLK_MSR_ID(17, "sys_pll_div16"),
+ CLK_MSR_ID(18, "sys_cpu_div16"),
+ CLK_MSR_ID(20, "rtc_osc_out"),
+ CLK_MSR_ID(23, "mmc_clk"),
+ CLK_MSR_ID(28, "sar_adc"),
+ CLK_MSR_ID(31, "mpll_test_out"),
+ CLK_MSR_ID(40, "mod_eth_tx_clk"),
+ CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"),
+ CLK_MSR_ID(42, "mp0_out"),
+ CLK_MSR_ID(43, "fclk_div5"),
+ CLK_MSR_ID(44, "pwm_b"),
+ CLK_MSR_ID(45, "pwm_a"),
+ CLK_MSR_ID(46, "vpu"),
+ CLK_MSR_ID(47, "ddr_dpll_pt"),
+ CLK_MSR_ID(48, "mp1_out"),
+ CLK_MSR_ID(49, "mp2_out"),
+ CLK_MSR_ID(50, "mp3_out"),
+ CLK_MSR_ID(51, "sd_emmm_c"),
+ CLK_MSR_ID(52, "sd_emmc_b"),
+ CLK_MSR_ID(61, "gpio_msr"),
+ CLK_MSR_ID(66, "audio_slv_lrclk_c"),
+ CLK_MSR_ID(67, "audio_slv_lrclk_b"),
+ CLK_MSR_ID(68, "audio_slv_lrclk_a"),
+ CLK_MSR_ID(69, "audio_slv_sclk_c"),
+ CLK_MSR_ID(70, "audio_slv_sclk_b"),
+ CLK_MSR_ID(71, "audio_slv_sclk_a"),
+ CLK_MSR_ID(72, "pwm_d"),
+ CLK_MSR_ID(73, "pwm_c"),
+ CLK_MSR_ID(74, "wifi_beacon"),
+ CLK_MSR_ID(75, "tdmin_lb_lrcl"),
+ CLK_MSR_ID(76, "tdmin_lb_sclk"),
+ CLK_MSR_ID(77, "rng_ring_osc_0"),
+ CLK_MSR_ID(78, "rng_ring_osc_1"),
+ CLK_MSR_ID(79, "rng_ring_osc_2"),
+ CLK_MSR_ID(80, "rng_ring_osc_3"),
+ CLK_MSR_ID(81, "vapb"),
+ CLK_MSR_ID(82, "ge2d"),
+ CLK_MSR_ID(84, "audio_resample"),
+ CLK_MSR_ID(85, "audio_pdm_sys"),
+ CLK_MSR_ID(86, "audio_spdifout"),
+ CLK_MSR_ID(87, "audio_spdifin"),
+ CLK_MSR_ID(88, "audio_lrclk_f"),
+ CLK_MSR_ID(89, "audio_lrclk_e"),
+ CLK_MSR_ID(90, "audio_lrclk_d"),
+ CLK_MSR_ID(91, "audio_lrclk_c"),
+ CLK_MSR_ID(92, "audio_lrclk_b"),
+ CLK_MSR_ID(93, "audio_lrclk_a"),
+ CLK_MSR_ID(94, "audio_sclk_f"),
+ CLK_MSR_ID(95, "audio_sclk_e"),
+ CLK_MSR_ID(96, "audio_sclk_d"),
+ CLK_MSR_ID(97, "audio_sclk_c"),
+ CLK_MSR_ID(98, "audio_sclk_b"),
+ CLK_MSR_ID(99, "audio_sclk_a"),
+ CLK_MSR_ID(100, "audio_mclk_f"),
+ CLK_MSR_ID(101, "audio_mclk_e"),
+ CLK_MSR_ID(102, "audio_mclk_d"),
+ CLK_MSR_ID(103, "audio_mclk_c"),
+ CLK_MSR_ID(104, "audio_mclk_b"),
+ CLK_MSR_ID(105, "audio_mclk_a"),
+ CLK_MSR_ID(106, "pcie_refclk_n"),
+ CLK_MSR_ID(107, "pcie_refclk_p"),
+ CLK_MSR_ID(108, "audio_locker_out"),
+ CLK_MSR_ID(109, "audio_locker_in"),
+};
+
+static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
+ CLK_MSR_ID(0, "ring_osc_out_ee_0"),
+ CLK_MSR_ID(1, "ring_osc_out_ee_1"),
+ CLK_MSR_ID(2, "ring_osc_out_ee_2"),
+ CLK_MSR_ID(3, "sys_cpu_ring_osc"),
+ CLK_MSR_ID(4, "gp0_pll"),
+ CLK_MSR_ID(6, "enci"),
+ CLK_MSR_ID(7, "clk81"),
+ CLK_MSR_ID(8, "encp"),
+ CLK_MSR_ID(9, "encl"),
+ CLK_MSR_ID(10, "vdac"),
+ CLK_MSR_ID(11, "eth_tx"),
+ CLK_MSR_ID(12, "hifi_pll"),
+ CLK_MSR_ID(13, "mod_tcon"),
+ CLK_MSR_ID(14, "fec_0"),
+ CLK_MSR_ID(15, "fec_1"),
+ CLK_MSR_ID(16, "fec_2"),
+ CLK_MSR_ID(17, "sys_pll_div16"),
+ CLK_MSR_ID(18, "sys_cpu_div16"),
+ CLK_MSR_ID(19, "lcd_an_ph2"),
+ CLK_MSR_ID(20, "rtc_osc_out"),
+ CLK_MSR_ID(21, "lcd_an_ph3"),
+ CLK_MSR_ID(22, "eth_phy_ref"),
+ CLK_MSR_ID(23, "mpll_50m"),
+ CLK_MSR_ID(24, "eth_125m"),
+ CLK_MSR_ID(25, "eth_rmii"),
+ CLK_MSR_ID(26, "sc_int"),
+ CLK_MSR_ID(27, "in_mac"),
+ CLK_MSR_ID(28, "sar_adc"),
+ CLK_MSR_ID(29, "pcie_inp"),
+ CLK_MSR_ID(30, "pcie_inn"),
+ CLK_MSR_ID(31, "mpll_test_out"),
+ CLK_MSR_ID(32, "vdec"),
+ CLK_MSR_ID(33, "sys_cpu_ring_osc_1"),
+ CLK_MSR_ID(34, "eth_mpll_50m"),
+ CLK_MSR_ID(35, "mali"),
+ CLK_MSR_ID(36, "hdmi_tx_pixel"),
+ CLK_MSR_ID(37, "cdac"),
+ CLK_MSR_ID(38, "vdin_meas"),
+ CLK_MSR_ID(39, "bt656"),
+ CLK_MSR_ID(41, "eth_rx_or_rmii"),
+ CLK_MSR_ID(42, "mp0_out"),
+ CLK_MSR_ID(43, "fclk_div5"),
+ CLK_MSR_ID(44, "pwm_b"),
+ CLK_MSR_ID(45, "pwm_a"),
+ CLK_MSR_ID(46, "vpu"),
+ CLK_MSR_ID(47, "ddr_dpll_pt"),
+ CLK_MSR_ID(48, "mp1_out"),
+ CLK_MSR_ID(49, "mp2_out"),
+ CLK_MSR_ID(50, "mp3_out"),
+ CLK_MSR_ID(51, "sd_emmc_c"),
+ CLK_MSR_ID(52, "sd_emmc_b"),
+ CLK_MSR_ID(53, "sd_emmc_a"),
+ CLK_MSR_ID(54, "vpu_clkc"),
+ CLK_MSR_ID(55, "vid_pll_div_out"),
+ CLK_MSR_ID(56, "wave420l_a"),
+ CLK_MSR_ID(57, "wave420l_c"),
+ CLK_MSR_ID(58, "wave420l_b"),
+ CLK_MSR_ID(59, "hcodec"),
+ CLK_MSR_ID(61, "gpio_msr"),
+ CLK_MSR_ID(62, "hevcb"),
+ CLK_MSR_ID(63, "dsi_meas"),
+ CLK_MSR_ID(64, "spicc_1"),
+ CLK_MSR_ID(65, "spicc_0"),
+ CLK_MSR_ID(66, "vid_lock"),
+ CLK_MSR_ID(67, "dsi_phy"),
+ CLK_MSR_ID(68, "hdcp22_esm"),
+ CLK_MSR_ID(69, "hdcp22_skp"),
+ CLK_MSR_ID(70, "pwm_f"),
+ CLK_MSR_ID(71, "pwm_e"),
+ CLK_MSR_ID(72, "pwm_d"),
+ CLK_MSR_ID(73, "pwm_c"),
+ CLK_MSR_ID(75, "hevcf"),
+ CLK_MSR_ID(77, "rng_ring_osc_0"),
+ CLK_MSR_ID(78, "rng_ring_osc_1"),
+ CLK_MSR_ID(79, "rng_ring_osc_2"),
+ CLK_MSR_ID(80, "rng_ring_osc_3"),
+ CLK_MSR_ID(81, "vapb"),
+ CLK_MSR_ID(82, "ge2d"),
+ CLK_MSR_ID(83, "co_rx"),
+ CLK_MSR_ID(84, "co_tx"),
+ CLK_MSR_ID(89, "hdmi_todig"),
+ CLK_MSR_ID(90, "hdmitx_sys"),
+ CLK_MSR_ID(94, "eth_phy_rx"),
+ CLK_MSR_ID(95, "eth_phy_pll"),
+ CLK_MSR_ID(96, "vpu_b"),
+ CLK_MSR_ID(97, "cpu_b_tmp"),
+ CLK_MSR_ID(98, "ts"),
+ CLK_MSR_ID(99, "ring_osc_out_ee_3"),
+ CLK_MSR_ID(100, "ring_osc_out_ee_4"),
+ CLK_MSR_ID(101, "ring_osc_out_ee_5"),
+ CLK_MSR_ID(102, "ring_osc_out_ee_6"),
+ CLK_MSR_ID(103, "ring_osc_out_ee_7"),
+ CLK_MSR_ID(104, "ring_osc_out_ee_8"),
+ CLK_MSR_ID(105, "ring_osc_out_ee_9"),
+ CLK_MSR_ID(106, "ephy_test"),
+ CLK_MSR_ID(107, "au_dac_g128x"),
+ CLK_MSR_ID(108, "audio_locker_out"),
+ CLK_MSR_ID(109, "audio_locker_in"),
+ CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
+ CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
+ CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
+ CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
+ CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
+ CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
+ CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
+ CLK_MSR_ID(117, "audio_resample"),
+ CLK_MSR_ID(118, "audio_pdm_sys"),
+ CLK_MSR_ID(119, "audio_spdifout_b"),
+ CLK_MSR_ID(120, "audio_spdifout"),
+ CLK_MSR_ID(121, "audio_spdifin"),
+ CLK_MSR_ID(122, "audio_pdm_dclk"),
+};
+
static int meson_measure_id(struct meson_msr_id *clk_msr_id,
unsigned int duration)
{
@@ -337,6 +525,14 @@ static const struct of_device_id meson_msr_match_table[] = {
.compatible = "amlogic,meson8b-clk-measure",
.data = (void *)clk_msr_m8,
},
+ {
+ .compatible = "amlogic,meson-axg-clk-measure",
+ .data = (void *)clk_msr_axg,
+ },
+ {
+ .compatible = "amlogic,meson-g12a-clk-measure",
+ .data = (void *)clk_msr_g12a,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 055a845ed979..03fa91fbe2da 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -1,5 +1,17 @@
menu "Broadcom SoC drivers"
+config BCM2835_POWER
+ bool "BCM2835 power domain driver"
+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
+ default y if ARCH_BCM2835
+ select PM_GENERIC_DOMAINS if PM
+ select RESET_CONTROLLER
+ help
+ This enables support for the BCM2835 power domains and reset
+ controller. Any usage of power domains by the Raspberry Pi
+ firmware means that Linux usage of the same power domain
+ must be accessed using the RASPBERRYPI_POWER driver
+
config RASPBERRYPI_POWER
bool "Raspberry Pi power domain driver"
depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index dc4fced72d21..c81df4b2403c 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1,2 +1,3 @@
+obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
new file mode 100644
index 000000000000..9351349cf0a9
--- /dev/null
+++ b/drivers/soc/bcm/bcm2835-power.c
@@ -0,0 +1,661 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Power domain driver for Broadcom BCM2835
+ *
+ * Copyright (C) 2018 Broadcom
+ */
+
+#include <dt-bindings/soc/bcm2835-pm.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/bcm2835-pm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/reset-controller.h>
+#include <linux/types.h>
+
+#define PM_GNRIC 0x00
+#define PM_AUDIO 0x04
+#define PM_STATUS 0x18
+#define PM_RSTC 0x1c
+#define PM_RSTS 0x20
+#define PM_WDOG 0x24
+#define PM_PADS0 0x28
+#define PM_PADS2 0x2c
+#define PM_PADS3 0x30
+#define PM_PADS4 0x34
+#define PM_PADS5 0x38
+#define PM_PADS6 0x3c
+#define PM_CAM0 0x44
+#define PM_CAM0_LDOHPEN BIT(2)
+#define PM_CAM0_LDOLPEN BIT(1)
+#define PM_CAM0_CTRLEN BIT(0)
+
+#define PM_CAM1 0x48
+#define PM_CAM1_LDOHPEN BIT(2)
+#define PM_CAM1_LDOLPEN BIT(1)
+#define PM_CAM1_CTRLEN BIT(0)
+
+#define PM_CCP2TX 0x4c
+#define PM_CCP2TX_LDOEN BIT(1)
+#define PM_CCP2TX_CTRLEN BIT(0)
+
+#define PM_DSI0 0x50
+#define PM_DSI0_LDOHPEN BIT(2)
+#define PM_DSI0_LDOLPEN BIT(1)
+#define PM_DSI0_CTRLEN BIT(0)
+
+#define PM_DSI1 0x54
+#define PM_DSI1_LDOHPEN BIT(2)
+#define PM_DSI1_LDOLPEN BIT(1)
+#define PM_DSI1_CTRLEN BIT(0)
+
+#define PM_HDMI 0x58
+#define PM_HDMI_RSTDR BIT(19)
+#define PM_HDMI_LDOPD BIT(1)
+#define PM_HDMI_CTRLEN BIT(0)
+
+#define PM_USB 0x5c
+/* The power gates must be enabled with this bit before enabling the LDO in the
+ * USB block.
+ */
+#define PM_USB_CTRLEN BIT(0)
+
+#define PM_PXLDO 0x60
+#define PM_PXBG 0x64
+#define PM_DFT 0x68
+#define PM_SMPS 0x6c
+#define PM_XOSC 0x70
+#define PM_SPAREW 0x74
+#define PM_SPARER 0x78
+#define PM_AVS_RSTDR 0x7c
+#define PM_AVS_STAT 0x80
+#define PM_AVS_EVENT 0x84
+#define PM_AVS_INTEN 0x88
+#define PM_DUMMY 0xfc
+
+#define PM_IMAGE 0x108
+#define PM_GRAFX 0x10c
+#define PM_PROC 0x110
+#define PM_ENAB BIT(12)
+#define PM_ISPRSTN BIT(8)
+#define PM_H264RSTN BIT(7)
+#define PM_PERIRSTN BIT(6)
+#define PM_V3DRSTN BIT(6)
+#define PM_ISFUNC BIT(5)
+#define PM_MRDONE BIT(4)
+#define PM_MEMREP BIT(3)
+#define PM_ISPOW BIT(2)
+#define PM_POWOK BIT(1)
+#define PM_POWUP BIT(0)
+#define PM_INRUSH_SHIFT 13
+#define PM_INRUSH_3_5_MA 0
+#define PM_INRUSH_5_MA 1
+#define PM_INRUSH_10_MA 2
+#define PM_INRUSH_20_MA 3
+#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
+
+#define PM_PASSWORD 0x5a000000
+
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define PM_READ(reg) readl(power->base + (reg))
+#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
+
+#define ASB_BRDG_VERSION 0x00
+#define ASB_CPR_CTRL 0x04
+
+#define ASB_V3D_S_CTRL 0x08
+#define ASB_V3D_M_CTRL 0x0c
+#define ASB_ISP_S_CTRL 0x10
+#define ASB_ISP_M_CTRL 0x14
+#define ASB_H264_S_CTRL 0x18
+#define ASB_H264_M_CTRL 0x1c
+
+#define ASB_REQ_STOP BIT(0)
+#define ASB_ACK BIT(1)
+#define ASB_EMPTY BIT(2)
+#define ASB_FULL BIT(3)
+
+#define ASB_AXI_BRDG_ID 0x20
+
+#define ASB_READ(reg) readl(power->asb + (reg))
+#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
+
+struct bcm2835_power_domain {
+ struct generic_pm_domain base;
+ struct bcm2835_power *power;
+ u32 domain;
+ struct clk *clk;
+};
+
+struct bcm2835_power {
+ struct device *dev;
+ /* PM registers. */
+ void __iomem *base;
+ /* AXI Async bridge registers. */
+ void __iomem *asb;
+
+ struct genpd_onecell_data pd_xlate;
+ struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
+ struct reset_controller_dev reset;
+};
+
+static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
+{
+ u64 start = ktime_get_ns();
+
+ /* Enable the module's async AXI bridges. */
+ ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
+ while (ASB_READ(reg) & ASB_ACK) {
+ cpu_relax();
+ if (ktime_get_ns() - start >= 1000)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
+{
+ u64 start = ktime_get_ns();
+
+ /* Enable the module's async AXI bridges. */
+ ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
+ while (!(ASB_READ(reg) & ASB_ACK)) {
+ cpu_relax();
+ if (ktime_get_ns() - start >= 1000)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
+{
+ struct bcm2835_power *power = pd->power;
+
+ /* Enable functional isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
+
+ /* Enable electrical isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+
+ /* Open the power switches. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
+
+ return 0;
+}
+
+static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
+{
+ struct bcm2835_power *power = pd->power;
+ struct device *dev = power->dev;
+ u64 start;
+ int ret;
+ int inrush;
+ bool powok;
+
+ /* If it was already powered on by the fw, leave it that way. */
+ if (PM_READ(pm_reg) & PM_POWUP)
+ return 0;
+
+ /* Enable power. Allowing too much current at once may result
+ * in POWOK never getting set, so start low and ramp it up as
+ * necessary to succeed.
+ */
+ powok = false;
+ for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
+ PM_WRITE(pm_reg,
+ (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
+ (inrush << PM_INRUSH_SHIFT) |
+ PM_POWUP);
+
+ start = ktime_get_ns();
+ while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
+ cpu_relax();
+ if (ktime_get_ns() - start >= 3000)
+ break;
+ }
+ }
+ if (!powok) {
+ dev_err(dev, "Timeout waiting for %s power OK\n",
+ pd->base.name);
+ ret = -ETIMEDOUT;
+ goto err_disable_powup;
+ }
+
+ /* Disable electrical isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
+
+ /* Repair memory */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
+ start = ktime_get_ns();
+ while (!(PM_READ(pm_reg) & PM_MRDONE)) {
+ cpu_relax();
+ if (ktime_get_ns() - start >= 1000) {
+ dev_err(dev, "Timeout waiting for %s memory repair\n",
+ pd->base.name);
+ ret = -ETIMEDOUT;
+ goto err_disable_ispow;
+ }
+ }
+
+ /* Disable functional isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
+
+ return 0;
+
+err_disable_ispow:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+err_disable_powup:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
+ return ret;
+}
+
+static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
+ u32 pm_reg,
+ u32 asb_m_reg,
+ u32 asb_s_reg,
+ u32 reset_flags)
+{
+ struct bcm2835_power *power = pd->power;
+ int ret;
+
+ ret = clk_prepare_enable(pd->clk);
+ if (ret) {
+ dev_err(power->dev, "Failed to enable clock for %s\n",
+ pd->base.name);
+ return ret;
+ }
+
+ /* Wait 32 clocks for reset to propagate, 1 us will be enough */
+ udelay(1);
+
+ clk_disable_unprepare(pd->clk);
+
+ /* Deassert the resets. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
+
+ ret = clk_prepare_enable(pd->clk);
+ if (ret) {
+ dev_err(power->dev, "Failed to enable clock for %s\n",
+ pd->base.name);
+ goto err_enable_resets;
+ }
+
+ ret = bcm2835_asb_enable(power, asb_m_reg);
+ if (ret) {
+ dev_err(power->dev, "Failed to enable ASB master for %s\n",
+ pd->base.name);
+ goto err_disable_clk;
+ }
+ ret = bcm2835_asb_enable(power, asb_s_reg);
+ if (ret) {
+ dev_err(power->dev, "Failed to enable ASB slave for %s\n",
+ pd->base.name);
+ goto err_disable_asb_master;
+ }
+
+ return 0;
+
+err_disable_asb_master:
+ bcm2835_asb_disable(power, asb_m_reg);
+err_disable_clk:
+ clk_disable_unprepare(pd->clk);
+err_enable_resets:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+ return ret;
+}
+
+static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
+ u32 pm_reg,
+ u32 asb_m_reg,
+ u32 asb_s_reg,
+ u32 reset_flags)
+{
+ struct bcm2835_power *power = pd->power;
+ int ret;
+
+ ret = bcm2835_asb_disable(power, asb_s_reg);
+ if (ret) {
+ dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
+ pd->base.name);
+ return ret;
+ }
+ ret = bcm2835_asb_disable(power, asb_m_reg);
+ if (ret) {
+ dev_warn(power->dev, "Failed to disable ASB master for %s\n",
+ pd->base.name);
+ bcm2835_asb_enable(power, asb_s_reg);
+ return ret;
+ }
+
+ clk_disable_unprepare(pd->clk);
+
+ /* Assert the resets. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+
+ return 0;
+}
+
+static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
+{
+ struct bcm2835_power_domain *pd =
+ container_of(domain, struct bcm2835_power_domain, base);
+ struct bcm2835_power *power = pd->power;
+
+ switch (pd->domain) {
+ case BCM2835_POWER_DOMAIN_GRAFX:
+ return bcm2835_power_power_on(pd, PM_GRAFX);
+
+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+ return bcm2835_asb_power_on(pd, PM_GRAFX,
+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
+ PM_V3DRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE:
+ return bcm2835_power_power_on(pd, PM_IMAGE);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+ return bcm2835_asb_power_on(pd, PM_IMAGE,
+ 0, 0,
+ PM_PERIRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+ return bcm2835_asb_power_on(pd, PM_IMAGE,
+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
+ PM_ISPRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
+ return bcm2835_asb_power_on(pd, PM_IMAGE,
+ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
+ PM_H264RSTN);
+
+ case BCM2835_POWER_DOMAIN_USB:
+ PM_WRITE(PM_USB, PM_USB_CTRLEN);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_DSI0:
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_DSI1:
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_CCP2TX:
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_HDMI:
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
+ usleep_range(100, 200);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
+ return 0;
+
+ default:
+ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
+ return -EINVAL;
+ }
+}
+
+static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
+{
+ struct bcm2835_power_domain *pd =
+ container_of(domain, struct bcm2835_power_domain, base);
+ struct bcm2835_power *power = pd->power;
+
+ switch (pd->domain) {
+ case BCM2835_POWER_DOMAIN_GRAFX:
+ return bcm2835_power_power_off(pd, PM_GRAFX);
+
+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+ return bcm2835_asb_power_off(pd, PM_GRAFX,
+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
+ PM_V3DRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE:
+ return bcm2835_power_power_off(pd, PM_IMAGE);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+ return bcm2835_asb_power_off(pd, PM_IMAGE,
+ 0, 0,
+ PM_PERIRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+ return bcm2835_asb_power_off(pd, PM_IMAGE,
+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
+ PM_ISPRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
+ return bcm2835_asb_power_off(pd, PM_IMAGE,
+ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
+ PM_H264RSTN);
+
+ case BCM2835_POWER_DOMAIN_USB:
+ PM_WRITE(PM_USB, 0);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_DSI0:
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+ PM_WRITE(PM_DSI0, 0);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_DSI1:
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+ PM_WRITE(PM_DSI1, 0);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_CCP2TX:
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+ PM_WRITE(PM_CCP2TX, 0);
+ return 0;
+
+ case BCM2835_POWER_DOMAIN_HDMI:
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
+ return 0;
+
+ default:
+ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
+ return -EINVAL;
+ }
+}
+
+static void
+bcm2835_init_power_domain(struct bcm2835_power *power,
+ int pd_xlate_index, const char *name)
+{
+ struct device *dev = power->dev;
+ struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
+
+ dom->clk = devm_clk_get(dev->parent, name);
+
+ dom->base.name = name;
+ dom->base.power_on = bcm2835_power_pd_power_on;
+ dom->base.power_off = bcm2835_power_pd_power_off;
+
+ dom->domain = pd_xlate_index;
+ dom->power = power;
+
+ /* XXX: on/off at boot? */
+ pm_genpd_init(&dom->base, NULL, true);
+
+ power->pd_xlate.domains[pd_xlate_index] = &dom->base;
+}
+
+/** bcm2835_reset_reset - Resets a block that has a reset line in the
+ * PM block.
+ *
+ * The consumer of the reset controller must have the power domain up
+ * -- there's no reset ability with the power domain down. To reset
+ * the sub-block, we just disable its access to memory through the
+ * ASB, reset, and re-enable.
+ */
+static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
+ reset);
+ struct bcm2835_power_domain *pd;
+ int ret;
+
+ switch (id) {
+ case BCM2835_RESET_V3D:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
+ break;
+ case BCM2835_RESET_H264:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
+ break;
+ case BCM2835_RESET_ISP:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
+ break;
+ default:
+ dev_err(power->dev, "Bad reset id %ld\n", id);
+ return -EINVAL;
+ }
+
+ ret = bcm2835_power_pd_power_off(&pd->base);
+ if (ret)
+ return ret;
+
+ return bcm2835_power_pd_power_on(&pd->base);
+}
+
+static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
+ reset);
+
+ switch (id) {
+ case BCM2835_RESET_V3D:
+ return !PM_READ(PM_GRAFX & PM_V3DRSTN);
+ case BCM2835_RESET_H264:
+ return !PM_READ(PM_IMAGE & PM_H264RSTN);
+ case BCM2835_RESET_ISP:
+ return !PM_READ(PM_IMAGE & PM_ISPRSTN);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct reset_control_ops bcm2835_reset_ops = {
+ .reset = bcm2835_reset_reset,
+ .status = bcm2835_reset_status,
+};
+
+static const char *const power_domain_names[] = {
+ [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
+ [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
+
+ [BCM2835_POWER_DOMAIN_IMAGE] = "image",
+ [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
+ [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
+ [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
+
+ [BCM2835_POWER_DOMAIN_USB] = "usb",
+ [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
+ [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
+ [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
+ [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
+ [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
+ [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
+};
+
+static int bcm2835_power_probe(struct platform_device *pdev)
+{
+ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct bcm2835_power *power;
+ static const struct {
+ int parent, child;
+ } domain_deps[] = {
+ { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
+ };
+ int ret, i;
+ u32 id;
+
+ power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
+ if (!power)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, power);
+
+ power->dev = dev;
+ power->base = pm->base;
+ power->asb = pm->asb;
+
+ id = ASB_READ(ASB_AXI_BRDG_ID);
+ if (id != 0x62726467 /* "BRDG" */) {
+ dev_err(dev, "ASB register ID returned 0x%08x\n", id);
+ return -ENODEV;
+ }
+
+ power->pd_xlate.domains = devm_kcalloc(dev,
+ ARRAY_SIZE(power_domain_names),
+ sizeof(*power->pd_xlate.domains),
+ GFP_KERNEL);
+ if (!power->pd_xlate.domains)
+ return -ENOMEM;
+
+ power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
+
+ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
+ bcm2835_init_power_domain(power, i, power_domain_names[i]);
+
+ for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
+ pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
+ &power->domains[domain_deps[i].child].base);
+ }
+
+ power->reset.owner = THIS_MODULE;
+ power->reset.nr_resets = BCM2835_RESET_COUNT;
+ power->reset.ops = &bcm2835_reset_ops;
+ power->reset.of_node = dev->parent->of_node;
+
+ ret = devm_reset_controller_register(dev, &power->reset);
+ if (ret)
+ return ret;
+
+ of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
+
+ dev_info(dev, "Broadcom BCM2835 power domains driver");
+ return 0;
+}
+
+static int bcm2835_power_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver bcm2835_power_driver = {
+ .probe = bcm2835_power_probe,
+ .remove = bcm2835_power_remove,
+ .driver = {
+ .name = "bcm2835-power",
+ },
+};
+module_platform_driver(bcm2835_power_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 8f80e8bbf29e..61f8e1433d0a 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -22,6 +22,7 @@ config FSL_GUTS
config FSL_MC_DPIO
tristate "QorIQ DPAA2 DPIO driver"
depends on FSL_MC_BUS
+ select SOC_BUS
help
Driver for the DPAA2 DPIO object. A DPIO provides queue and
buffer management facilities for software to interact with
diff --git a/drivers/soc/fsl/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h
index ab8f82ee7ee5..e13fd3ac1939 100644
--- a/drivers/soc/fsl/dpio/dpio-cmd.h
+++ b/drivers/soc/fsl/dpio/dpio-cmd.h
@@ -25,6 +25,8 @@
#define DPIO_CMDID_ENABLE DPIO_CMD(0x002)
#define DPIO_CMDID_DISABLE DPIO_CMD(0x003)
#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004)
+#define DPIO_CMDID_RESET DPIO_CMD(0x005)
+#define DPIO_CMDID_SET_STASHING_DEST DPIO_CMD(0x120)
struct dpio_cmd_open {
__le32 dpio_id;
@@ -46,4 +48,8 @@ struct dpio_rsp_get_attr {
__le32 qbman_version;
};
+struct dpio_stashing_dest {
+ u8 sdest;
+};
+
#endif /* _FSL_DPIO_CMD_H */
diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c
index e58fcc9096e8..c0cdc8946031 100644
--- a/drivers/soc/fsl/dpio/dpio-driver.c
+++ b/drivers/soc/fsl/dpio/dpio-driver.c
@@ -14,6 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/sys_soc.h>
#include <linux/fsl/mc.h>
#include <soc/fsl/dpaa2-io.h>
@@ -30,6 +31,48 @@ struct dpio_priv {
struct dpaa2_io *io;
};
+static cpumask_var_t cpus_unused_mask;
+
+static const struct soc_device_attribute ls1088a_soc[] = {
+ {.family = "QorIQ LS1088A"},
+ { /* sentinel */ }
+};
+
+static const struct soc_device_attribute ls2080a_soc[] = {
+ {.family = "QorIQ LS2080A"},
+ { /* sentinel */ }
+};
+
+static const struct soc_device_attribute ls2088a_soc[] = {
+ {.family = "QorIQ LS2088A"},
+ { /* sentinel */ }
+};
+
+static const struct soc_device_attribute lx2160a_soc[] = {
+ {.family = "QorIQ LX2160A"},
+ { /* sentinel */ }
+};
+
+static int dpaa2_dpio_get_cluster_sdest(struct fsl_mc_device *dpio_dev, int cpu)
+{
+ int cluster_base, cluster_size;
+
+ if (soc_device_match(ls1088a_soc)) {
+ cluster_base = 2;
+ cluster_size = 4;
+ } else if (soc_device_match(ls2080a_soc) ||
+ soc_device_match(ls2088a_soc) ||
+ soc_device_match(lx2160a_soc)) {
+ cluster_base = 0;
+ cluster_size = 2;
+ } else {
+ dev_err(&dpio_dev->dev, "unknown SoC version\n");
+ return -1;
+ }
+
+ return cluster_base + cpu / cluster_size;
+}
+
static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
{
struct device *dev = (struct device *)arg;
@@ -86,7 +129,8 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
struct dpio_priv *priv;
int err = -ENOMEM;
struct device *dev = &dpio_dev->dev;
- static int next_cpu = -1;
+ int possible_next_cpu;
+ int sdest;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -108,6 +152,12 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
goto err_open;
}
+ err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+ if (err) {
+ dev_err(dev, "dpio_reset() failed\n");
+ goto err_reset;
+ }
+
err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle,
&dpio_attrs);
if (err) {
@@ -128,17 +178,24 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
desc.dpio_id = dpio_dev->obj_desc.id;
/* get the cpu to use for the affinity hint */
- if (next_cpu == -1)
- next_cpu = cpumask_first(cpu_online_mask);
- else
- next_cpu = cpumask_next(next_cpu, cpu_online_mask);
-
- if (!cpu_possible(next_cpu)) {
+ possible_next_cpu = cpumask_first(cpus_unused_mask);
+ if (possible_next_cpu >= nr_cpu_ids) {
dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n");
err = -ERANGE;
goto err_allocate_irqs;
}
- desc.cpu = next_cpu;
+ desc.cpu = possible_next_cpu;
+ cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask);
+
+ sdest = dpaa2_dpio_get_cluster_sdest(dpio_dev, desc.cpu);
+ if (sdest >= 0) {
+ err = dpio_set_stashing_destination(dpio_dev->mc_io, 0,
+ dpio_dev->mc_handle,
+ sdest);
+ if (err)
+ dev_err(dev, "dpio_set_stashing_destination failed for cpu%d\n",
+ desc.cpu);
+ }
/*
* Set the CENA regs to be the cache inhibited area of the portal to
@@ -171,7 +228,7 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
if (err)
goto err_register_dpio_irq;
- priv->io = dpaa2_io_create(&desc);
+ priv->io = dpaa2_io_create(&desc, dev);
if (!priv->io) {
dev_err(dev, "dpaa2_io_create failed\n");
err = -ENOMEM;
@@ -182,7 +239,6 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
dev_dbg(dev, " receives_notifications = %d\n",
desc.receives_notifications);
dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
- fsl_mc_portal_free(dpio_dev->mc_io);
return 0;
@@ -193,6 +249,7 @@ err_register_dpio_irq:
err_allocate_irqs:
dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
err_get_attr:
+err_reset:
dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
err_open:
fsl_mc_portal_free(dpio_dev->mc_io);
@@ -211,20 +268,17 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
{
struct device *dev;
struct dpio_priv *priv;
- int err;
+ int err = 0, cpu;
dev = &dpio_dev->dev;
priv = dev_get_drvdata(dev);
+ cpu = dpaa2_io_get_cpu(priv->io);
dpaa2_io_down(priv->io);
dpio_teardown_irqs(dpio_dev);
- err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
- if (err) {
- dev_err(dev, "MC portal allocation failed\n");
- goto err_mcportal;
- }
+ cpumask_set_cpu(cpu, cpus_unused_mask);
err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
&dpio_dev->mc_handle);
@@ -243,7 +297,7 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
err_open:
fsl_mc_portal_free(dpio_dev->mc_io);
-err_mcportal:
+
return err;
}
@@ -267,11 +321,16 @@ static struct fsl_mc_driver dpaa2_dpio_driver = {
static int dpio_driver_init(void)
{
+ if (!zalloc_cpumask_var(&cpus_unused_mask, GFP_KERNEL))
+ return -ENOMEM;
+ cpumask_copy(cpus_unused_mask, cpu_online_mask);
+
return fsl_mc_driver_register(&dpaa2_dpio_driver);
}
static void dpio_driver_exit(void)
{
+ free_cpumask_var(cpus_unused_mask);
fsl_mc_driver_unregister(&dpaa2_dpio_driver);
}
module_init(dpio_driver_init);
diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index ec0837ff039a..b9539ef2c3cd 100644
--- a/drivers/soc/fsl/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -27,6 +27,7 @@ struct dpaa2_io {
/* protect notifications list */
spinlock_t lock_notifications;
struct list_head notifications;
+ struct device *dev;
};
struct dpaa2_io_store {
@@ -98,13 +99,15 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_select);
/**
* dpaa2_io_create() - create a dpaa2_io object.
* @desc: the dpaa2_io descriptor
+ * @dev: the actual DPIO device
*
* Activates a "struct dpaa2_io" corresponding to the given config of an actual
* DPIO object.
*
* Return a valid dpaa2_io object for success, or NULL for failure.
*/
-struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
+struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc,
+ struct device *dev)
{
struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
@@ -146,6 +149,8 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
dpio_by_cpu[desc->cpu] = obj;
spin_unlock(&dpio_list_lock);
+ obj->dev = dev;
+
return obj;
}
@@ -160,6 +165,11 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
*/
void dpaa2_io_down(struct dpaa2_io *d)
{
+ spin_lock(&dpio_list_lock);
+ dpio_by_cpu[d->dpio_desc.cpu] = NULL;
+ list_del(&d->node);
+ spin_unlock(&dpio_list_lock);
+
kfree(d);
}
@@ -210,10 +220,24 @@ done:
}
/**
+ * dpaa2_io_get_cpu() - get the cpu associated with a given DPIO object
+ *
+ * @d: the given DPIO object.
+ *
+ * Return the cpu associated with the DPIO object
+ */
+int dpaa2_io_get_cpu(struct dpaa2_io *d)
+{
+ return d->dpio_desc.cpu;
+}
+EXPORT_SYMBOL(dpaa2_io_get_cpu);
+
+/**
* dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN
* notifications on the given DPIO service.
* @d: the given DPIO service.
* @ctx: the notification context.
+ * @dev: the device that requests the register
*
* The caller should make the MC command to attach a DPAA2 object to
* a DPIO after this function completes successfully. In that way:
@@ -228,14 +252,20 @@ done:
* Return 0 for success, or -ENODEV for failure.
*/
int dpaa2_io_service_register(struct dpaa2_io *d,
- struct dpaa2_io_notification_ctx *ctx)
+ struct dpaa2_io_notification_ctx *ctx,
+ struct device *dev)
{
+ struct device_link *link;
unsigned long irqflags;
d = service_select_by_cpu(d, ctx->desired_cpu);
if (!d)
return -ENODEV;
+ link = device_link_add(dev, d->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!link)
+ return -EINVAL;
+
ctx->dpio_id = d->dpio_desc.dpio_id;
ctx->qman64 = (u64)(uintptr_t)ctx;
ctx->dpio_private = d;
@@ -256,12 +286,14 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_register);
* dpaa2_io_service_deregister - The opposite of 'register'.
* @service: the given DPIO service.
* @ctx: the notification context.
+ * @dev: the device that requests to be deregistered
*
* This function should be called only after sending the MC command to
* to detach the notification-producing device from the DPIO.
*/
void dpaa2_io_service_deregister(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx)
+ struct dpaa2_io_notification_ctx *ctx,
+ struct device *dev)
{
struct dpaa2_io *d = ctx->dpio_private;
unsigned long irqflags;
@@ -272,6 +304,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
spin_lock_irqsave(&d->lock_notifications, irqflags);
list_del(&ctx->node);
spin_unlock_irqrestore(&d->lock_notifications, irqflags);
+
+ if (dev)
+ device_link_remove(dev, d->dev);
}
EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
@@ -438,7 +473,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd);
* Return 0 for success, and negative error code for failure.
*/
int dpaa2_io_service_release(struct dpaa2_io *d,
- u32 bpid,
+ u16 bpid,
const u64 *buffers,
unsigned int num_buffers)
{
@@ -467,7 +502,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_release);
* Eg. if the buffer pool is empty, this will return zero.
*/
int dpaa2_io_service_acquire(struct dpaa2_io *d,
- u32 bpid,
+ u16 bpid,
u64 *buffers,
unsigned int num_buffers)
{
@@ -595,6 +630,7 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME))
ret = NULL;
} else {
+ prefetch(&s->vaddr[s->idx]);
*is_last = 0;
}
diff --git a/drivers/soc/fsl/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c
index ff37c80e11a0..af74c597a675 100644
--- a/drivers/soc/fsl/dpio/dpio.c
+++ b/drivers/soc/fsl/dpio/dpio.c
@@ -166,6 +166,22 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
return 0;
}
+int dpio_set_stashing_destination(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 sdest)
+{
+ struct fsl_mc_command cmd = { 0 };
+ struct dpio_stashing_dest *dpio_cmd;
+
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_STASHING_DEST,
+ cmd_flags, token);
+ dpio_cmd = (struct dpio_stashing_dest *)cmd.params;
+ dpio_cmd->sdest = sdest;
+
+ return mc_send_command(mc_io, &cmd);
+}
+
/**
* dpio_get_api_version - Get Data Path I/O API version
* @mc_io: Pointer to MC portal's DPIO object
@@ -196,3 +212,26 @@ int dpio_get_api_version(struct fsl_mc_io *mc_io,
return 0;
}
+
+/**
+ * dpio_reset() - Reset the DPIO, returns the object to initial state.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_reset(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token)
+{
+ struct fsl_mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
diff --git a/drivers/soc/fsl/dpio/dpio.h b/drivers/soc/fsl/dpio/dpio.h
index 49194c8e45f1..da06f7258098 100644
--- a/drivers/soc/fsl/dpio/dpio.h
+++ b/drivers/soc/fsl/dpio/dpio.h
@@ -75,9 +75,18 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
u16 token,
struct dpio_attr *attr);
+int dpio_set_stashing_destination(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 dest);
+
int dpio_get_api_version(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 *major_ver,
u16 *minor_ver);
+int dpio_reset(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token);
+
#endif /* __FSL_DPIO_H */
diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c
index 0bddb85c0ae5..d02013556a1b 100644
--- a/drivers/soc/fsl/dpio/qbman-portal.c
+++ b/drivers/soc/fsl/dpio/qbman-portal.c
@@ -169,9 +169,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
3, /* RPM: Valid bit mode, RCR in array mode */
2, /* DCM: Discrete consumption ack mode */
3, /* EPM: Valid bit mode, EQCR in array mode */
- 0, /* mem stashing drop enable == FALSE */
+ 1, /* mem stashing drop enable == TRUE */
1, /* mem stashing priority == TRUE */
- 0, /* mem stashing enable == FALSE */
+ 1, /* mem stashing enable == TRUE */
1, /* dequeue stashing priority == TRUE */
0, /* dequeue stashing enable == FALSE */
0); /* EQCR_CI stashing priority == FALSE */
@@ -180,6 +180,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
if (!reg) {
pr_err("qbman: the portal is not enabled!\n");
+ kfree(p);
return NULL;
}
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 302e0c8d69d9..63f6df86f9e5 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -32,6 +32,7 @@ struct fsl_soc_die_attr {
static struct guts *guts;
static struct soc_device_attribute soc_dev_attr;
static struct soc_device *soc_dev;
+static struct device_node *root;
/* SoC die attribute definition for QorIQ platform */
@@ -114,7 +115,7 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match(
return NULL;
}
-u32 fsl_guts_get_svr(void)
+static u32 fsl_guts_get_svr(void)
{
u32 svr = 0;
@@ -128,11 +129,10 @@ u32 fsl_guts_get_svr(void)
return svr;
}
-EXPORT_SYMBOL(fsl_guts_get_svr);
static int fsl_guts_probe(struct platform_device *pdev)
{
- struct device_node *root, *np = pdev->dev.of_node;
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct resource *res;
const struct fsl_soc_die_attr *soc_die;
@@ -155,9 +155,8 @@ static int fsl_guts_probe(struct platform_device *pdev)
root = of_find_node_by_path("/");
if (of_property_read_string(root, "model", &machine))
of_property_read_string_index(root, "compatible", 0, &machine);
- of_node_put(root);
if (machine)
- soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
+ soc_dev_attr.machine = machine;
svr = fsl_guts_get_svr();
soc_die = fsl_soc_die_match(svr, fsl_soc_die);
@@ -192,6 +191,7 @@ static int fsl_guts_probe(struct platform_device *pdev)
static int fsl_guts_remove(struct platform_device *dev)
{
soc_device_unregister(soc_dev);
+ of_node_put(root);
return 0;
}
diff --git a/drivers/soc/fsl/qbman/dpaa_sys.c b/drivers/soc/fsl/qbman/dpaa_sys.c
index 9436aa83ff1b..e6d48dccb8d5 100644
--- a/drivers/soc/fsl/qbman/dpaa_sys.c
+++ b/drivers/soc/fsl/qbman/dpaa_sys.c
@@ -62,7 +62,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
return -ENODEV;
}
- if (!dma_zalloc_coherent(dev, *size, addr, 0)) {
+ if (!dma_alloc_coherent(dev, *size, addr, 0)) {
dev_err(dev, "DMA Alloc memory failed\n");
return -ENODEV;
}
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index 52c153cd795a..636f83f781f5 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work);
static irqreturn_t portal_isr(int irq, void *ptr)
{
struct qman_portal *p = ptr;
-
- u32 clear = QM_DQAVAIL_MASK | p->irq_sources;
u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources;
+ u32 clear = 0;
if (unlikely(!is))
return IRQ_NONE;
/* DQRR-handling if it's interrupt-driven */
- if (is & QM_PIRQ_DQRI)
+ if (is & QM_PIRQ_DQRI) {
__poll_portal_fast(p, QMAN_POLL_LIMIT);
+ clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI;
+ }
/* Handling of anything else that's interrupt-driven */
- clear |= __poll_portal_slow(p, is);
+ clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW;
qm_out(&p->p, QM_REG_ISR, clear);
return IRQ_HANDLED;
}
diff --git a/drivers/soc/fsl/qe/qe_tdm.c b/drivers/soc/fsl/qe/qe_tdm.c
index f78c34647ca2..76480df195a8 100644
--- a/drivers/soc/fsl/qe/qe_tdm.c
+++ b/drivers/soc/fsl/qe/qe_tdm.c
@@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
const char *sprop;
int ret = 0;
u32 val;
- struct resource *res;
- struct device_node *np2;
- static int siram_init_flag;
- struct platform_device *pdev;
sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
if (sprop) {
@@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
utdm->siram_entry_id = val;
set_si_param(utdm, ut_info);
-
- np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si");
- if (!np2)
- return -EINVAL;
-
- pdev = of_find_device_by_node(np2);
- if (!pdev) {
- pr_err("%pOFn: failed to lookup pdev\n", np2);
- of_node_put(np2);
- return -EINVAL;
- }
-
- of_node_put(np2);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- utdm->si_regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(utdm->si_regs)) {
- ret = PTR_ERR(utdm->si_regs);
- goto err_miss_siram_property;
- }
-
- np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram");
- if (!np2) {
- ret = -EINVAL;
- goto err_miss_siram_property;
- }
-
- pdev = of_find_device_by_node(np2);
- if (!pdev) {
- ret = -EINVAL;
- pr_err("%pOFn: failed to lookup pdev\n", np2);
- of_node_put(np2);
- goto err_miss_siram_property;
- }
-
- of_node_put(np2);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- utdm->siram = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(utdm->siram)) {
- ret = PTR_ERR(utdm->siram);
- goto err_miss_siram_property;
- }
-
- if (siram_init_flag == 0) {
- memset_io(utdm->siram, 0, resource_size(res));
- siram_init_flag = 1;
- }
-
- return ret;
-
-err_miss_siram_property:
- devm_iounmap(&pdev->dev, utdm->si_regs);
return ret;
}
EXPORT_SYMBOL(ucc_of_parse_tdm);
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index 2112d18dbb7b..d80f899d22f9 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -2,7 +2,7 @@ menu "i.MX SoC drivers"
config IMX_GPCV2_PM_DOMAINS
bool "i.MX GPCv2 PM domains"
- depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
+ depends on ARCH_MXC || (COMPILE_TEST && OF)
depends on PM
select PM_GENERIC_DOMAINS
default y if SOC_IMX7D
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 8b4f48a2ca57..176f473127b6 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -8,6 +8,7 @@
* Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
*/
+#include <linux/clk.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
@@ -65,6 +66,12 @@
#define GPC_M4_PU_PDN_FLG 0x1bc
+#define GPC_PU_PWRHSK 0x1fc
+
+#define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
+#define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
+#define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
+
/*
* The PGC offset values in Reference Manual
* (Rev. 1, 01/2018 and the older ones) GPC chapter's
@@ -92,16 +99,21 @@
#define GPC_PGC_CTRL_PCR BIT(0)
+#define GPC_CLK_MAX 6
+
struct imx_pgc_domain {
struct generic_pm_domain genpd;
struct regmap *regmap;
struct regulator *regulator;
+ struct clk *clk[GPC_CLK_MAX];
+ int num_clks;
unsigned int pgc;
const struct {
u32 pxx;
u32 map;
+ u32 hsk;
} bits;
const int voltage;
@@ -125,7 +137,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
const bool enable_power_control = !on;
const bool has_regulator = !IS_ERR(domain->regulator);
unsigned long deadline;
- int ret = 0;
+ int i, ret = 0;
regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
domain->bits.map, domain->bits.map);
@@ -138,10 +150,18 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
}
}
+ /* Enable reset clocks for all devices in the domain */
+ for (i = 0; i < domain->num_clks; i++)
+ clk_prepare_enable(domain->clk[i]);
+
if (enable_power_control)
regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+ if (domain->bits.hsk)
+ regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
+ domain->bits.hsk, on ? domain->bits.hsk : 0);
+
regmap_update_bits(domain->regmap, offset,
domain->bits.pxx, domain->bits.pxx);
@@ -179,6 +199,10 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
GPC_PGC_CTRL_PCR, 0);
+ /* Disable reset clocks for all devices in the domain */
+ for (i = 0; i < domain->num_clks; i++)
+ clk_disable_unprepare(domain->clk[i]);
+
if (has_regulator && !on) {
int err;
@@ -328,6 +352,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.bits = {
.pxx = IMX8M_GPU_SW_Pxx_REQ,
.map = IMX8M_GPU_A53_DOMAIN,
+ .hsk = IMX8M_GPU_HSK_PWRDNREQN,
},
.pgc = IMX8M_PGC_GPU,
},
@@ -339,6 +364,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.bits = {
.pxx = IMX8M_VPU_SW_Pxx_REQ,
.map = IMX8M_VPU_A53_DOMAIN,
+ .hsk = IMX8M_VPU_HSK_PWRDNREQN,
},
.pgc = IMX8M_PGC_VPU,
},
@@ -350,6 +376,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.bits = {
.pxx = IMX8M_DISP_SW_Pxx_REQ,
.map = IMX8M_DISP_A53_DOMAIN,
+ .hsk = IMX8M_DISP_HSK_PWRDNREQN,
},
.pgc = IMX8M_PGC_DISP,
},
@@ -390,7 +417,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
static const struct regmap_range imx8m_yes_ranges[] = {
regmap_reg_range(GPC_LPCR_A_CORE_BSC,
- GPC_M4_PU_PDN_FLG),
+ GPC_PU_PWRHSK),
regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
GPC_PGC_SR(IMX8M_PGC_MIPI)),
regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
@@ -426,6 +453,41 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
.reg_access_table = &imx8m_access_table,
};
+static int imx_pgc_get_clocks(struct imx_pgc_domain *domain)
+{
+ int i, ret;
+
+ for (i = 0; ; i++) {
+ struct clk *clk = of_clk_get(domain->dev->of_node, i);
+ if (IS_ERR(clk))
+ break;
+ if (i >= GPC_CLK_MAX) {
+ dev_err(domain->dev, "more than %d clocks\n",
+ GPC_CLK_MAX);
+ ret = -EINVAL;
+ goto clk_err;
+ }
+ domain->clk[i] = clk;
+ }
+ domain->num_clks = i;
+
+ return 0;
+
+clk_err:
+ while (i--)
+ clk_put(domain->clk[i]);
+
+ return ret;
+}
+
+static void imx_pgc_put_clocks(struct imx_pgc_domain *domain)
+{
+ int i;
+
+ for (i = domain->num_clks - 1; i >= 0; i--)
+ clk_put(domain->clk[i]);
+}
+
static int imx_pgc_domain_probe(struct platform_device *pdev)
{
struct imx_pgc_domain *domain = pdev->dev.platform_data;
@@ -445,9 +507,17 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
domain->voltage, domain->voltage);
}
+ ret = imx_pgc_get_clocks(domain);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(domain->dev, "Failed to get domain's clocks\n");
+ return ret;
+ }
+
ret = pm_genpd_init(&domain->genpd, NULL, true);
if (ret) {
dev_err(domain->dev, "Failed to init power domain\n");
+ imx_pgc_put_clocks(domain);
return ret;
}
@@ -456,6 +526,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
if (ret) {
dev_err(domain->dev, "Failed to add genpd provider\n");
pm_genpd_remove(&domain->genpd);
+ imx_pgc_put_clocks(domain);
}
return ret;
@@ -467,6 +538,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
of_genpd_del_provider(domain->dev->of_node);
pm_genpd_remove(&domain->genpd);
+ imx_pgc_put_clocks(domain);
return 0;
}
diff --git a/drivers/soc/lantiq/Makefile b/drivers/soc/lantiq/Makefile
index be9e866d53e5..35aa86bd1023 100644
--- a/drivers/soc/lantiq/Makefile
+++ b/drivers/soc/lantiq/Makefile
@@ -1,2 +1 @@
obj-y += fpi-bus.o
-obj-$(CONFIG_XRX200_PHY_FW) += gphy.o
diff --git a/drivers/soc/lantiq/gphy.c b/drivers/soc/lantiq/gphy.c
deleted file mode 100644
index feeb17cebc25..000000000000
--- a/drivers/soc/lantiq/gphy.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2012 John Crispin <blogic@phrozen.org>
- * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
- * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/firmware.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/property.h>
-#include <dt-bindings/mips/lantiq_rcu_gphy.h>
-
-#include <lantiq_soc.h>
-
-#define XRX200_GPHY_FW_ALIGN (16 * 1024)
-
-struct xway_gphy_priv {
- struct clk *gphy_clk_gate;
- struct reset_control *gphy_reset;
- struct reset_control *gphy_reset2;
- void __iomem *membase;
- char *fw_name;
-};
-
-struct xway_gphy_match_data {
- char *fe_firmware_name;
- char *ge_firmware_name;
-};
-
-static const struct xway_gphy_match_data xrx200a1x_gphy_data = {
- .fe_firmware_name = "lantiq/xrx200_phy22f_a14.bin",
- .ge_firmware_name = "lantiq/xrx200_phy11g_a14.bin",
-};
-
-static const struct xway_gphy_match_data xrx200a2x_gphy_data = {
- .fe_firmware_name = "lantiq/xrx200_phy22f_a22.bin",
- .ge_firmware_name = "lantiq/xrx200_phy11g_a22.bin",
-};
-
-static const struct xway_gphy_match_data xrx300_gphy_data = {
- .fe_firmware_name = "lantiq/xrx300_phy22f_a21.bin",
- .ge_firmware_name = "lantiq/xrx300_phy11g_a21.bin",
-};
-
-static const struct of_device_id xway_gphy_match[] = {
- { .compatible = "lantiq,xrx200a1x-gphy", .data = &xrx200a1x_gphy_data },
- { .compatible = "lantiq,xrx200a2x-gphy", .data = &xrx200a2x_gphy_data },
- { .compatible = "lantiq,xrx300-gphy", .data = &xrx300_gphy_data },
- { .compatible = "lantiq,xrx330-gphy", .data = &xrx300_gphy_data },
- {},
-};
-MODULE_DEVICE_TABLE(of, xway_gphy_match);
-
-static int xway_gphy_load(struct device *dev, struct xway_gphy_priv *priv,
- dma_addr_t *dev_addr)
-{
- const struct firmware *fw;
- void *fw_addr;
- dma_addr_t dma_addr;
- size_t size;
- int ret;
-
- ret = request_firmware(&fw, priv->fw_name, dev);
- if (ret) {
- dev_err(dev, "failed to load firmware: %s, error: %i\n",
- priv->fw_name, ret);
- return ret;
- }
-
- /*
- * GPHY cores need the firmware code in a persistent and contiguous
- * memory area with a 16 kB boundary aligned start address.
- */
- size = fw->size + XRX200_GPHY_FW_ALIGN;
-
- fw_addr = dmam_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
- if (fw_addr) {
- fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
- *dev_addr = ALIGN(dma_addr, XRX200_GPHY_FW_ALIGN);
- memcpy(fw_addr, fw->data, fw->size);
- } else {
- dev_err(dev, "failed to alloc firmware memory\n");
- ret = -ENOMEM;
- }
-
- release_firmware(fw);
-
- return ret;
-}
-
-static int xway_gphy_of_probe(struct platform_device *pdev,
- struct xway_gphy_priv *priv)
-{
- struct device *dev = &pdev->dev;
- const struct xway_gphy_match_data *gphy_fw_name_cfg;
- u32 gphy_mode;
- int ret;
- struct resource *res_gphy;
-
- gphy_fw_name_cfg = of_device_get_match_data(dev);
-
- priv->gphy_clk_gate = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->gphy_clk_gate)) {
- dev_err(dev, "Failed to lookup gate clock\n");
- return PTR_ERR(priv->gphy_clk_gate);
- }
-
- res_gphy = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->membase = devm_ioremap_resource(dev, res_gphy);
- if (IS_ERR(priv->membase))
- return PTR_ERR(priv->membase);
-
- priv->gphy_reset = devm_reset_control_get(dev, "gphy");
- if (IS_ERR(priv->gphy_reset)) {
- if (PTR_ERR(priv->gphy_reset) != -EPROBE_DEFER)
- dev_err(dev, "Failed to lookup gphy reset\n");
- return PTR_ERR(priv->gphy_reset);
- }
-
- priv->gphy_reset2 = devm_reset_control_get_optional(dev, "gphy2");
- if (IS_ERR(priv->gphy_reset2))
- return PTR_ERR(priv->gphy_reset2);
-
- ret = device_property_read_u32(dev, "lantiq,gphy-mode", &gphy_mode);
- /* Default to GE mode */
- if (ret)
- gphy_mode = GPHY_MODE_GE;
-
- switch (gphy_mode) {
- case GPHY_MODE_FE:
- priv->fw_name = gphy_fw_name_cfg->fe_firmware_name;
- break;
- case GPHY_MODE_GE:
- priv->fw_name = gphy_fw_name_cfg->ge_firmware_name;
- break;
- default:
- dev_err(dev, "Unknown GPHY mode %d\n", gphy_mode);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int xway_gphy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct xway_gphy_priv *priv;
- dma_addr_t fw_addr = 0;
- int ret;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- ret = xway_gphy_of_probe(pdev, priv);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(priv->gphy_clk_gate);
- if (ret)
- return ret;
-
- ret = xway_gphy_load(dev, priv, &fw_addr);
- if (ret) {
- clk_disable_unprepare(priv->gphy_clk_gate);
- return ret;
- }
-
- reset_control_assert(priv->gphy_reset);
- reset_control_assert(priv->gphy_reset2);
-
- iowrite32be(fw_addr, priv->membase);
-
- reset_control_deassert(priv->gphy_reset);
- reset_control_deassert(priv->gphy_reset2);
-
- platform_set_drvdata(pdev, priv);
-
- return ret;
-}
-
-static int xway_gphy_remove(struct platform_device *pdev)
-{
- struct xway_gphy_priv *priv = platform_get_drvdata(pdev);
-
- iowrite32be(0, priv->membase);
-
- clk_disable_unprepare(priv->gphy_clk_gate);
-
- return 0;
-}
-
-static struct platform_driver xway_gphy_driver = {
- .probe = xway_gphy_probe,
- .remove = xway_gphy_remove,
- .driver = {
- .name = "xway-rcu-gphy",
- .of_match_table = xway_gphy_match,
- },
-};
-
-module_platform_driver(xway_gphy_driver);
-
-MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin");
-MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin");
-MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin");
-MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin");
-MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin");
-MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin");
-MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
-MODULE_DESCRIPTION("Lantiq XWAY GPHY Firmware Loader");
-MODULE_LICENSE("GPL");
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index fcbf8a2e4080..1ee298f6bf17 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -98,6 +98,24 @@ config QCOM_RPMH
of hardware components aggregate requests for these resources and
help apply the aggregated state on the resource.
+config QCOM_RPMHPD
+ bool "Qualcomm RPMh Power domain driver"
+ depends on QCOM_RPMH && QCOM_COMMAND_DB
+ help
+ QCOM RPMh Power domain driver to support power-domains with
+ performance states. The driver communicates a performance state
+ value to RPMh which then translates it into corresponding voltage
+ for the voltage rail.
+
+config QCOM_RPMPD
+ bool "Qualcomm RPM Power domain driver"
+ depends on QCOM_SMD_RPM=y
+ help
+ QCOM RPM Power domain driver to support power-domains with
+ performance states. The driver communicates a performance state
+ value to RPM which then translates it into corresponding voltage
+ for the voltage rail.
+
config QCOM_SMEM
tristate "Qualcomm Shared Memory Manager (SMEM)"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f25b54cd6cf8..ffe519b0cb66 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -21,3 +21,5 @@ obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
+obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
+obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 2e1e4f0a5db8..86600d97c36d 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -71,6 +71,11 @@ static struct llcc_slice_config sdm845_data[] = {
SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0),
};
+static int sdm845_qcom_llcc_remove(struct platform_device *pdev)
+{
+ return qcom_llcc_remove(pdev);
+}
+
static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
{
return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data));
@@ -87,6 +92,7 @@ static struct platform_driver sdm845_qcom_llcc_driver = {
.of_match_table = sdm845_qcom_llcc_of_match,
},
.probe = sdm845_qcom_llcc_probe,
+ .remove = sdm845_qcom_llcc_remove,
};
module_platform_driver(sdm845_qcom_llcc_driver);
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 80667f7be52c..9090ea12eaf3 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -46,7 +46,7 @@
#define BANK_OFFSET_STRIDE 0x80000
-static struct llcc_drv_data *drv_data;
+static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
static const struct regmap_config llcc_regmap_config = {
.reg_bits = 32,
@@ -68,6 +68,9 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid)
struct llcc_slice_desc *desc;
u32 sz, count;
+ if (IS_ERR(drv_data))
+ return ERR_CAST(drv_data);
+
cfg = drv_data->cfg;
sz = drv_data->cfg_size;
@@ -108,6 +111,9 @@ static int llcc_update_act_ctrl(u32 sid,
u32 slice_status;
int ret;
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
status_reg = LLCC_TRP_STATUSn(sid);
@@ -143,6 +149,9 @@ int llcc_slice_activate(struct llcc_slice_desc *desc)
int ret;
u32 act_ctrl_val;
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
if (IS_ERR_OR_NULL(desc))
return -EINVAL;
@@ -180,6 +189,9 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc)
u32 act_ctrl_val;
int ret;
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
if (IS_ERR_OR_NULL(desc))
return -EINVAL;
@@ -289,46 +301,62 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
return ret;
}
+int qcom_llcc_remove(struct platform_device *pdev)
+{
+ /* Set the global pointer to a error code to avoid referencing it */
+ drv_data = ERR_PTR(-ENODEV);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_llcc_remove);
+
+static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
+ const char *name)
+{
+ struct resource *res;
+ void __iomem *base;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+ if (!res)
+ return ERR_PTR(-ENODEV);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return ERR_CAST(base);
+
+ return devm_regmap_init_mmio(&pdev->dev, base, &llcc_regmap_config);
+}
+
int qcom_llcc_probe(struct platform_device *pdev,
const struct llcc_slice_config *llcc_cfg, u32 sz)
{
u32 num_banks;
struct device *dev = &pdev->dev;
- struct resource *llcc_banks_res, *llcc_bcast_res;
- void __iomem *llcc_banks_base, *llcc_bcast_base;
int ret, i;
struct platform_device *llcc_edac;
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
- if (!drv_data)
- return -ENOMEM;
-
- llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "llcc_base");
- llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
- if (IS_ERR(llcc_banks_base))
- return PTR_ERR(llcc_banks_base);
-
- drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
- &llcc_regmap_config);
- if (IS_ERR(drv_data->regmap))
- return PTR_ERR(drv_data->regmap);
-
- llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "llcc_broadcast_base");
- llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
- if (IS_ERR(llcc_bcast_base))
- return PTR_ERR(llcc_bcast_base);
-
- drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
- &llcc_regmap_config);
- if (IS_ERR(drv_data->bcast_regmap))
- return PTR_ERR(drv_data->bcast_regmap);
+ if (!drv_data) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
+ if (IS_ERR(drv_data->regmap)) {
+ ret = PTR_ERR(drv_data->regmap);
+ goto err;
+ }
+
+ drv_data->bcast_regmap =
+ qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
+ if (IS_ERR(drv_data->bcast_regmap)) {
+ ret = PTR_ERR(drv_data->bcast_regmap);
+ goto err;
+ }
ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
&num_banks);
if (ret)
- return ret;
+ goto err;
num_banks &= LLCC_LB_CNT_MASK;
num_banks >>= LLCC_LB_CNT_SHIFT;
@@ -340,8 +368,10 @@ int qcom_llcc_probe(struct platform_device *pdev,
drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
GFP_KERNEL);
- if (!drv_data->offsets)
- return -ENOMEM;
+ if (!drv_data->offsets) {
+ ret = -ENOMEM;
+ goto err;
+ }
for (i = 0; i < num_banks; i++)
drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
@@ -349,8 +379,10 @@ int qcom_llcc_probe(struct platform_device *pdev,
drv_data->bitmap = devm_kcalloc(dev,
BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
GFP_KERNEL);
- if (!drv_data->bitmap)
- return -ENOMEM;
+ if (!drv_data->bitmap) {
+ ret = -ENOMEM;
+ goto err;
+ }
drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz;
@@ -359,7 +391,7 @@ int qcom_llcc_probe(struct platform_device *pdev,
ret = qcom_llcc_cfg_program(pdev);
if (ret)
- return ret;
+ goto err;
drv_data->ecc_irq = platform_get_irq(pdev, 0);
if (drv_data->ecc_irq >= 0) {
@@ -370,6 +402,9 @@ int qcom_llcc_probe(struct platform_device *pdev,
dev_err(dev, "Failed to register llcc edac driver\n");
}
+ return 0;
+err:
+ drv_data = ERR_PTR(-ENODEV);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_llcc_probe);
diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c
index 09c669e70d63..038abc377fdb 100644
--- a/drivers/soc/qcom/qcom_gsbi.c
+++ b/drivers/soc/qcom/qcom_gsbi.c
@@ -138,7 +138,7 @@ static int gsbi_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *base;
struct gsbi_info *gsbi;
- int i;
+ int i, ret;
u32 mask, gsbi_num;
const struct crci_config *config = NULL;
@@ -221,7 +221,10 @@ static int gsbi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, gsbi);
- return of_platform_populate(node, NULL, NULL, &pdev->dev);
+ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+ if (ret)
+ clk_disable_unprepare(gsbi->hclk);
+ return ret;
}
static int gsbi_remove(struct platform_device *pdev)
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 97bb5989aa21..7200d762a951 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -45,9 +45,9 @@ static ssize_t qcom_rmtfs_mem_show(struct device *dev,
struct device_attribute *attr,
char *buf);
-static DEVICE_ATTR(phys_addr, 0400, qcom_rmtfs_mem_show, NULL);
-static DEVICE_ATTR(size, 0400, qcom_rmtfs_mem_show, NULL);
-static DEVICE_ATTR(client_id, 0400, qcom_rmtfs_mem_show, NULL);
+static DEVICE_ATTR(phys_addr, 0444, qcom_rmtfs_mem_show, NULL);
+static DEVICE_ATTR(size, 0444, qcom_rmtfs_mem_show, NULL);
+static DEVICE_ATTR(client_id, 0444, qcom_rmtfs_mem_show, NULL);
static ssize_t qcom_rmtfs_mem_show(struct device *dev,
struct device_attribute *attr,
@@ -132,6 +132,11 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp)
return 0;
}
+static struct class rmtfs_class = {
+ .owner = THIS_MODULE,
+ .name = "rmtfs",
+};
+
static const struct file_operations qcom_rmtfs_mem_fops = {
.owner = THIS_MODULE,
.open = qcom_rmtfs_mem_open,
@@ -199,6 +204,7 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
dev_set_name(&rmtfs_mem->dev, "qcom_rmtfs_mem%d", client_id);
rmtfs_mem->dev.id = client_id;
+ rmtfs_mem->dev.class = &rmtfs_class;
rmtfs_mem->dev.devt = MKDEV(MAJOR(qcom_rmtfs_mem_major), client_id);
ret = cdev_device_add(&rmtfs_mem->cdev, &rmtfs_mem->dev);
@@ -277,32 +283,42 @@ static struct platform_driver qcom_rmtfs_mem_driver = {
},
};
-static int qcom_rmtfs_mem_init(void)
+static int __init qcom_rmtfs_mem_init(void)
{
int ret;
+ ret = class_register(&rmtfs_class);
+ if (ret)
+ return ret;
+
ret = alloc_chrdev_region(&qcom_rmtfs_mem_major, 0,
QCOM_RMTFS_MEM_DEV_MAX, "qcom_rmtfs_mem");
if (ret < 0) {
pr_err("qcom_rmtfs_mem: failed to allocate char dev region\n");
- return ret;
+ goto unregister_class;
}
ret = platform_driver_register(&qcom_rmtfs_mem_driver);
if (ret < 0) {
pr_err("qcom_rmtfs_mem: failed to register rmtfs_mem driver\n");
- unregister_chrdev_region(qcom_rmtfs_mem_major,
- QCOM_RMTFS_MEM_DEV_MAX);
+ goto unregister_chrdev;
}
+ return 0;
+
+unregister_chrdev:
+ unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
+unregister_class:
+ class_unregister(&rmtfs_class);
return ret;
}
module_init(qcom_rmtfs_mem_init);
-static void qcom_rmtfs_mem_exit(void)
+static void __exit qcom_rmtfs_mem_exit(void)
{
platform_driver_unregister(&qcom_rmtfs_mem_driver);
unregister_chrdev_region(qcom_rmtfs_mem_major, QCOM_RMTFS_MEM_DEV_MAX);
+ class_unregister(&rmtfs_class);
}
module_exit(qcom_rmtfs_mem_exit);
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index c7beb6841289..035091fd44b8 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -80,6 +80,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
msg);
struct completion *compl = rpm_msg->completion;
+ bool free = rpm_msg->needs_free;
rpm_msg->err = r;
@@ -94,7 +95,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
complete(compl);
exit:
- if (rpm_msg->needs_free)
+ if (free)
kfree(rpm_msg);
}
@@ -192,9 +193,8 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state,
WARN_ON(irqs_disabled());
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
} else {
- ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
- &rpm_msg->msg);
/* Clean up our call by spoofing tx_done */
+ ret = 0;
rpmh_tx_done(&rpm_msg->msg, ret);
}
@@ -348,11 +348,12 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
{
struct batch_cache_req *req;
struct rpmh_request *rpm_msgs;
- DECLARE_COMPLETION_ONSTACK(compl);
+ struct completion *compls;
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
unsigned long time_left;
int count = 0;
- int ret, i, j;
+ int ret, i;
+ void *ptr;
if (!cmd || !n)
return -EINVAL;
@@ -362,10 +363,15 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
if (!count)
return -EINVAL;
- req = kzalloc(sizeof(*req) + count * sizeof(req->rpm_msgs[0]),
+ ptr = kzalloc(sizeof(*req) +
+ count * (sizeof(req->rpm_msgs[0]) + sizeof(*compls)),
GFP_ATOMIC);
- if (!req)
+ if (!ptr)
return -ENOMEM;
+
+ req = ptr;
+ compls = ptr + sizeof(*req) + count * sizeof(*rpm_msgs);
+
req->count = count;
rpm_msgs = req->rpm_msgs;
@@ -380,25 +386,26 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
}
for (i = 0; i < count; i++) {
- rpm_msgs[i].completion = &compl;
+ struct completion *compl = &compls[i];
+
+ init_completion(compl);
+ rpm_msgs[i].completion = compl;
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg);
if (ret) {
pr_err("Error(%d) sending RPMH message addr=%#x\n",
ret, rpm_msgs[i].msg.cmds[0].addr);
- for (j = i; j < count; j++)
- rpmh_tx_done(&rpm_msgs[j].msg, ret);
break;
}
}
time_left = RPMH_TIMEOUT_MS;
- for (i = 0; i < count; i++) {
- time_left = wait_for_completion_timeout(&compl, time_left);
+ while (i--) {
+ time_left = wait_for_completion_timeout(&compls[i], time_left);
if (!time_left) {
/*
* Better hope they never finish because they'll signal
- * the completion on our stack and that's bad once
- * we've returned from the function.
+ * the completion that we're going to free once
+ * we've returned from this function.
*/
WARN_ON(1);
ret = -ETIMEDOUT;
@@ -407,7 +414,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
}
exit:
- kfree(req);
+ kfree(ptr);
return ret;
}
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
new file mode 100644
index 000000000000..5741ec3fa814
--- /dev/null
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/cmd-db.h>
+#include <soc/qcom/rpmh.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
+
+#define RPMH_ARC_MAX_LEVELS 16
+
+/**
+ * struct rpmhpd - top level RPMh power domain resource data structure
+ * @dev: rpmh power domain controller device
+ * @pd: generic_pm_domain corrresponding to the power domain
+ * @peer: A peer power domain in case Active only Voting is
+ * supported
+ * @active_only: True if it represents an Active only peer
+ * @level: An array of level (vlvl) to corner (hlvl) mappings
+ * derived from cmd-db
+ * @level_count: Number of levels supported by the power domain. max
+ * being 16 (0 - 15)
+ * @enabled: true if the power domain is enabled
+ * @res_name: Resource name used for cmd-db lookup
+ * @addr: Resource address as looped up using resource name from
+ * cmd-db
+ */
+struct rpmhpd {
+ struct device *dev;
+ struct generic_pm_domain pd;
+ struct generic_pm_domain *parent;
+ struct rpmhpd *peer;
+ const bool active_only;
+ unsigned int corner;
+ unsigned int active_corner;
+ u32 level[RPMH_ARC_MAX_LEVELS];
+ size_t level_count;
+ bool enabled;
+ const char *res_name;
+ u32 addr;
+};
+
+struct rpmhpd_desc {
+ struct rpmhpd **rpmhpds;
+ size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmhpd_lock);
+
+/* SDM845 RPMH powerdomains */
+
+static struct rpmhpd sdm845_ebi = {
+ .pd = { .name = "ebi", },
+ .res_name = "ebi.lvl",
+};
+
+static struct rpmhpd sdm845_lmx = {
+ .pd = { .name = "lmx", },
+ .res_name = "lmx.lvl",
+};
+
+static struct rpmhpd sdm845_lcx = {
+ .pd = { .name = "lcx", },
+ .res_name = "lcx.lvl",
+};
+
+static struct rpmhpd sdm845_gfx = {
+ .pd = { .name = "gfx", },
+ .res_name = "gfx.lvl",
+};
+
+static struct rpmhpd sdm845_mss = {
+ .pd = { .name = "mss", },
+ .res_name = "mss.lvl",
+};
+
+static struct rpmhpd sdm845_mx_ao;
+static struct rpmhpd sdm845_mx = {
+ .pd = { .name = "mx", },
+ .peer = &sdm845_mx_ao,
+ .res_name = "mx.lvl",
+};
+
+static struct rpmhpd sdm845_mx_ao = {
+ .pd = { .name = "mx_ao", },
+ .peer = &sdm845_mx,
+ .res_name = "mx.lvl",
+};
+
+static struct rpmhpd sdm845_cx_ao;
+static struct rpmhpd sdm845_cx = {
+ .pd = { .name = "cx", },
+ .peer = &sdm845_cx_ao,
+ .parent = &sdm845_mx.pd,
+ .res_name = "cx.lvl",
+};
+
+static struct rpmhpd sdm845_cx_ao = {
+ .pd = { .name = "cx_ao", },
+ .peer = &sdm845_cx,
+ .parent = &sdm845_mx_ao.pd,
+ .res_name = "cx.lvl",
+};
+
+static struct rpmhpd *sdm845_rpmhpds[] = {
+ [SDM845_EBI] = &sdm845_ebi,
+ [SDM845_MX] = &sdm845_mx,
+ [SDM845_MX_AO] = &sdm845_mx_ao,
+ [SDM845_CX] = &sdm845_cx,
+ [SDM845_CX_AO] = &sdm845_cx_ao,
+ [SDM845_LMX] = &sdm845_lmx,
+ [SDM845_LCX] = &sdm845_lcx,
+ [SDM845_GFX] = &sdm845_gfx,
+ [SDM845_MSS] = &sdm845_mss,
+};
+
+static const struct rpmhpd_desc sdm845_desc = {
+ .rpmhpds = sdm845_rpmhpds,
+ .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
+};
+
+static const struct of_device_id rpmhpd_match_table[] = {
+ { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
+ { }
+};
+
+static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
+ unsigned int corner, bool sync)
+{
+ struct tcs_cmd cmd = {
+ .addr = pd->addr,
+ .data = corner,
+ };
+
+ /*
+ * Wait for an ack only when we are increasing the
+ * perf state of the power domain
+ */
+ if (sync)
+ return rpmh_write(pd->dev, state, &cmd, 1);
+ else
+ return rpmh_write_async(pd->dev, state, &cmd, 1);
+}
+
+static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
+ unsigned int *active, unsigned int *sleep)
+{
+ *active = corner;
+
+ if (pd->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+/*
+ * This function is used to aggregate the votes across the active only
+ * resources and its peers. The aggregated votes are sent to RPMh as
+ * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
+ * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
+ * on system sleep).
+ * We send ACTIVE_ONLY votes for resources without any peers. For others,
+ * which have an active only peer, all 3 votes are sent.
+ */
+static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
+{
+ int ret;
+ struct rpmhpd *peer = pd->peer;
+ unsigned int active_corner, sleep_corner;
+ unsigned int this_active_corner = 0, this_sleep_corner = 0;
+ unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+ to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
+
+ if (peer && peer->enabled)
+ to_active_sleep(peer, peer->corner, &peer_active_corner,
+ &peer_sleep_corner);
+
+ active_corner = max(this_active_corner, peer_active_corner);
+
+ ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
+ active_corner > pd->active_corner);
+ if (ret)
+ return ret;
+
+ pd->active_corner = active_corner;
+
+ if (peer) {
+ peer->active_corner = active_corner;
+
+ ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
+ active_corner, false);
+ if (ret)
+ return ret;
+
+ sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+ return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
+ false);
+ }
+
+ return ret;
+}
+
+static int rpmhpd_power_on(struct generic_pm_domain *domain)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0;
+
+ mutex_lock(&rpmhpd_lock);
+
+ if (pd->corner)
+ ret = rpmhpd_aggregate_corner(pd, pd->corner);
+
+ if (!ret)
+ pd->enabled = true;
+
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static int rpmhpd_power_off(struct generic_pm_domain *domain)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0;
+
+ mutex_lock(&rpmhpd_lock);
+
+ ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
+
+ if (!ret)
+ pd->enabled = false;
+
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
+ unsigned int level)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0, i;
+
+ mutex_lock(&rpmhpd_lock);
+
+ for (i = 0; i < pd->level_count; i++)
+ if (level <= pd->level[i])
+ break;
+
+ /*
+ * If the level requested is more than that supported by the
+ * max corner, just set it to max anyway.
+ */
+ if (i == pd->level_count)
+ i--;
+
+ if (pd->enabled) {
+ ret = rpmhpd_aggregate_corner(pd, i);
+ if (ret)
+ goto out;
+ }
+
+ pd->corner = i;
+out:
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
+ struct dev_pm_opp *opp)
+{
+ return dev_pm_opp_get_level(opp);
+}
+
+static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
+{
+ int i;
+ const u16 *buf;
+
+ buf = cmd_db_read_aux_data(rpmhpd->res_name, &rpmhpd->level_count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ /* 2 bytes used for each command DB aux data entry */
+ rpmhpd->level_count >>= 1;
+
+ if (rpmhpd->level_count > RPMH_ARC_MAX_LEVELS)
+ return -EINVAL;
+
+ for (i = 0; i < rpmhpd->level_count; i++) {
+ rpmhpd->level[i] = buf[i];
+
+ /*
+ * The AUX data may be zero padded. These 0 valued entries at
+ * the end of the map must be ignored.
+ */
+ if (i > 0 && rpmhpd->level[i] == 0) {
+ rpmhpd->level_count = i;
+ break;
+ }
+ pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
+ rpmhpd->level[i]);
+ }
+
+ return 0;
+}
+
+static int rpmhpd_probe(struct platform_device *pdev)
+{
+ int i, ret;
+ size_t num_pds;
+ struct device *dev = &pdev->dev;
+ struct genpd_onecell_data *data;
+ struct rpmhpd **rpmhpds;
+ const struct rpmhpd_desc *desc;
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpmhpds = desc->rpmhpds;
+ num_pds = desc->num_pds;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
+ GFP_KERNEL);
+ if (!data->domains)
+ return -ENOMEM;
+
+ data->num_domains = num_pds;
+
+ for (i = 0; i < num_pds; i++) {
+ if (!rpmhpds[i]) {
+ dev_warn(dev, "rpmhpds[%d] is empty\n", i);
+ continue;
+ }
+
+ rpmhpds[i]->dev = dev;
+ rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
+ if (!rpmhpds[i]->addr) {
+ dev_err(dev, "Could not find RPMh address for resource %s\n",
+ rpmhpds[i]->res_name);
+ return -ENODEV;
+ }
+
+ ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
+ if (ret != CMD_DB_HW_ARC) {
+ dev_err(dev, "RPMh slave ID mismatch\n");
+ return -EINVAL;
+ }
+
+ ret = rpmhpd_update_level_mapping(rpmhpds[i]);
+ if (ret)
+ return ret;
+
+ rpmhpds[i]->pd.power_off = rpmhpd_power_off;
+ rpmhpds[i]->pd.power_on = rpmhpd_power_on;
+ rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
+ rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
+ pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
+
+ data->domains[i] = &rpmhpds[i]->pd;
+ }
+
+ /* Add subdomains */
+ for (i = 0; i < num_pds; i++) {
+ if (!rpmhpds[i])
+ continue;
+ if (rpmhpds[i]->parent)
+ pm_genpd_add_subdomain(rpmhpds[i]->parent,
+ &rpmhpds[i]->pd);
+ }
+
+ return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmhpd_driver = {
+ .driver = {
+ .name = "qcom-rpmhpd",
+ .of_match_table = rpmhpd_match_table,
+ .suppress_bind_attrs = true,
+ },
+ .probe = rpmhpd_probe,
+};
+
+static int __init rpmhpd_init(void)
+{
+ return platform_driver_register(&rpmhpd_driver);
+}
+core_initcall(rpmhpd_init);
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
new file mode 100644
index 000000000000..005326050c23
--- /dev/null
+++ b/drivers/soc/qcom/rpmpd.c
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
+
+/* Resource types */
+#define RPMPD_SMPA 0x61706d73
+#define RPMPD_LDOA 0x616f646c
+
+/* Operation Keys */
+#define KEY_CORNER 0x6e726f63 /* corn */
+#define KEY_ENABLE 0x6e657773 /* swen */
+#define KEY_FLOOR_CORNER 0x636676 /* vfc */
+
+#define MAX_RPMPD_STATE 6
+
+#define DEFINE_RPMPD_CORNER_SMPA(_platform, _name, _active, r_id) \
+ static struct rpmpd _platform##_##_active; \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .peer = &_platform##_##_active, \
+ .res_type = RPMPD_SMPA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }; \
+ static struct rpmpd _platform##_##_active = { \
+ .pd = { .name = #_active, }, \
+ .peer = &_platform##_##_name, \
+ .active_only = true, \
+ .res_type = RPMPD_SMPA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }
+
+#define DEFINE_RPMPD_CORNER_LDOA(_platform, _name, r_id) \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .res_type = RPMPD_LDOA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }
+
+#define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type) \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .res_type = r_type, \
+ .res_id = r_id, \
+ .key = KEY_FLOOR_CORNER, \
+ }
+
+#define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id) \
+ DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA)
+
+#define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id) \
+ DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA)
+
+struct rpmpd_req {
+ __le32 key;
+ __le32 nbytes;
+ __le32 value;
+};
+
+struct rpmpd {
+ struct generic_pm_domain pd;
+ struct rpmpd *peer;
+ const bool active_only;
+ unsigned int corner;
+ bool enabled;
+ const char *res_name;
+ const int res_type;
+ const int res_id;
+ struct qcom_smd_rpm *rpm;
+ __le32 key;
+};
+
+struct rpmpd_desc {
+ struct rpmpd **rpmpds;
+ size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmpd_lock);
+
+/* msm8996 RPM Power domains */
+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddcx, vddcx_ao, 1);
+DEFINE_RPMPD_CORNER_SMPA(msm8996, vddmx, vddmx_ao, 2);
+DEFINE_RPMPD_CORNER_LDOA(msm8996, vddsscx, 26);
+
+DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1);
+DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26);
+
+static struct rpmpd *msm8996_rpmpds[] = {
+ [MSM8996_VDDCX] = &msm8996_vddcx,
+ [MSM8996_VDDCX_AO] = &msm8996_vddcx_ao,
+ [MSM8996_VDDCX_VFC] = &msm8996_vddcx_vfc,
+ [MSM8996_VDDMX] = &msm8996_vddmx,
+ [MSM8996_VDDMX_AO] = &msm8996_vddmx_ao,
+ [MSM8996_VDDSSCX] = &msm8996_vddsscx,
+ [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
+};
+
+static const struct rpmpd_desc msm8996_desc = {
+ .rpmpds = msm8996_rpmpds,
+ .num_pds = ARRAY_SIZE(msm8996_rpmpds),
+};
+
+static const struct of_device_id rpmpd_match_table[] = {
+ { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
+ { }
+};
+
+static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
+{
+ struct rpmpd_req req = {
+ .key = KEY_ENABLE,
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(enable),
+ };
+
+ return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ pd->res_type, pd->res_id, &req, sizeof(req));
+}
+
+static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
+{
+ struct rpmpd_req req = {
+ .key = pd->key,
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(corner),
+ };
+
+ return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
+ &req, sizeof(req));
+};
+
+static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
+ unsigned int *active, unsigned int *sleep)
+{
+ *active = corner;
+
+ if (pd->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+static int rpmpd_aggregate_corner(struct rpmpd *pd)
+{
+ int ret;
+ struct rpmpd *peer = pd->peer;
+ unsigned int active_corner, sleep_corner;
+ unsigned int this_active_corner = 0, this_sleep_corner = 0;
+ unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+ to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
+
+ if (peer && peer->enabled)
+ to_active_sleep(peer, peer->corner, &peer_active_corner,
+ &peer_sleep_corner);
+
+ active_corner = max(this_active_corner, peer_active_corner);
+
+ ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
+ if (ret)
+ return ret;
+
+ sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+ return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
+}
+
+static int rpmpd_power_on(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ mutex_lock(&rpmpd_lock);
+
+ ret = rpmpd_send_enable(pd, true);
+ if (ret)
+ goto out;
+
+ pd->enabled = true;
+
+ if (pd->corner)
+ ret = rpmpd_aggregate_corner(pd);
+
+out:
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static int rpmpd_power_off(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ mutex_lock(&rpmpd_lock);
+
+ ret = rpmpd_send_enable(pd, false);
+ if (!ret)
+ pd->enabled = false;
+
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static int rpmpd_set_performance(struct generic_pm_domain *domain,
+ unsigned int state)
+{
+ int ret = 0;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ if (state > MAX_RPMPD_STATE)
+ goto out;
+
+ mutex_lock(&rpmpd_lock);
+
+ pd->corner = state;
+
+ if (!pd->enabled && pd->key != KEY_FLOOR_CORNER)
+ goto out;
+
+ ret = rpmpd_aggregate_corner(pd);
+
+out:
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
+ struct dev_pm_opp *opp)
+{
+ return dev_pm_opp_get_level(opp);
+}
+
+static int rpmpd_probe(struct platform_device *pdev)
+{
+ int i;
+ size_t num;
+ struct genpd_onecell_data *data;
+ struct qcom_smd_rpm *rpm;
+ struct rpmpd **rpmpds;
+ const struct rpmpd_desc *desc;
+
+ rpm = dev_get_drvdata(pdev->dev.parent);
+ if (!rpm) {
+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+ return -ENODEV;
+ }
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpmpds = desc->rpmpds;
+ num = desc->num_pds;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
+ GFP_KERNEL);
+ data->num_domains = num;
+
+ for (i = 0; i < num; i++) {
+ if (!rpmpds[i]) {
+ dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
+ i);
+ continue;
+ }
+
+ rpmpds[i]->rpm = rpm;
+ rpmpds[i]->pd.power_off = rpmpd_power_off;
+ rpmpds[i]->pd.power_on = rpmpd_power_on;
+ rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
+ rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
+ pm_genpd_init(&rpmpds[i]->pd, NULL, true);
+
+ data->domains[i] = &rpmpds[i]->pd;
+ }
+
+ return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmpd_driver = {
+ .driver = {
+ .name = "qcom-rpmpd",
+ .of_match_table = rpmpd_match_table,
+ .suppress_bind_attrs = true,
+ },
+ .probe = rpmpd_probe,
+};
+
+static int __init rpmpd_init(void)
+{
+ return platform_driver_register(&rpmpd_driver);
+}
+core_initcall(rpmpd_init);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index b8e63724a49d..9956bb2c63f2 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -227,6 +227,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-msm8974" },
{ .compatible = "qcom,rpm-msm8996" },
{ .compatible = "qcom,rpm-msm8998" },
+ { .compatible = "qcom,rpm-sdm660" },
{ .compatible = "qcom,rpm-qcs404" },
{}
};
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 4d8012e1205c..68bfca6f20dd 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -44,7 +44,7 @@ config ARCH_RZN1
bool
select ARM_AMBA
-if ARM
+if ARM && ARCH_RENESAS
#comment "Renesas ARM SoCs System Type"
diff --git a/drivers/soc/renesas/r8a774c0-sysc.c b/drivers/soc/renesas/r8a774c0-sysc.c
index e1ac4c0f6640..11050e17ea81 100644
--- a/drivers/soc/renesas/r8a774c0-sysc.c
+++ b/drivers/soc/renesas/r8a774c0-sysc.c
@@ -28,19 +28,6 @@ static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
{ "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A },
};
-static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
- unsigned int num_areas, u8 id,
- int new_parent)
-{
- unsigned int i;
-
- for (i = 0; i < num_areas; i++)
- if (areas[i].isr_bit == id) {
- areas[i].parent = new_parent;
- return;
- }
-}
-
/* Fixups for RZ/G2E ES1.0 revision */
static const struct soc_device_attribute r8a774c0[] __initconst = {
{ .soc_id = "r8a774c0", .revision = "ES1.0" },
@@ -50,12 +37,10 @@ static const struct soc_device_attribute r8a774c0[] __initconst = {
static int __init r8a774c0_sysc_init(void)
{
if (soc_device_match(r8a774c0)) {
- rcar_sysc_fix_parent(r8a774c0_areas,
- ARRAY_SIZE(r8a774c0_areas),
- R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B);
- rcar_sysc_fix_parent(r8a774c0_areas,
- ARRAY_SIZE(r8a774c0_areas),
- R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON);
+ /* Fix incorrect 3DG hierarchy */
+ swap(r8a774c0_areas[6], r8a774c0_areas[7]);
+ r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
+ r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
}
return 0;
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index fe4481676da6..a0b03443d8c1 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -76,6 +76,7 @@ config ARCH_TEGRA_210_SOC
select PINCTRL_TEGRA210
select SOC_TEGRA_FLOWCTRL
select SOC_TEGRA_PMC
+ select TEGRA_TIMER
help
Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index a33ee8ef8b6b..51625703399e 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -137,13 +137,17 @@ static int tegra_fuse_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
fuse->phys = res->start;
fuse->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(fuse->base))
- return PTR_ERR(fuse->base);
+ if (IS_ERR(fuse->base)) {
+ err = PTR_ERR(fuse->base);
+ fuse->base = base;
+ return err;
+ }
fuse->clk = devm_clk_get(&pdev->dev, "fuse");
if (IS_ERR(fuse->clk)) {
dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
PTR_ERR(fuse->clk));
+ fuse->base = base;
return PTR_ERR(fuse->clk);
}
@@ -152,8 +156,10 @@ static int tegra_fuse_probe(struct platform_device *pdev)
if (fuse->soc->probe) {
err = fuse->soc->probe(fuse);
- if (err < 0)
+ if (err < 0) {
+ fuse->base = base;
return err;
+ }
}
if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c
index 5373f4c16b54..8ed35d9851f8 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra210.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra210.c
@@ -131,7 +131,7 @@ void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info)
soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
soc_speedo[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1);
- soc_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
+ soc_speedo[2] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_2);
cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4;
soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4;
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 7ea3280279ff..0df258518693 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -20,7 +20,7 @@
#define pr_fmt(fmt) "tegra-pmc: " fmt
-#include <linux/kernel.h>
+#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/debugfs.h>
@@ -30,16 +30,17 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
-#include <linux/irq.h>
#include <linux/irqdomain.h>
-#include <linux/of.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_clk.h>
+#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/reboot.h>
@@ -145,6 +146,11 @@
#define WAKE_AOWAKE_CTRL 0x4f4
#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
+/* for secure PMC */
+#define TEGRA_SMC_PMC 0xc2fffe00
+#define TEGRA_SMC_PMC_READ 0xaa
+#define TEGRA_SMC_PMC_WRITE 0xbb
+
struct tegra_powergate {
struct generic_pm_domain genpd;
struct tegra_pmc *pmc;
@@ -216,6 +222,7 @@ struct tegra_pmc_soc {
bool has_gpu_clamps;
bool needs_mbist_war;
bool has_impl_33v_pwr;
+ bool maybe_tz_only;
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
@@ -273,8 +280,12 @@ static const char * const tegra30_reset_sources[] = {
* struct tegra_pmc - NVIDIA Tegra PMC
* @dev: pointer to PMC device structure
* @base: pointer to I/O remapped register region
+ * @wake: pointer to I/O remapped region for WAKE registers
+ * @aotag: pointer to I/O remapped region for AOTAG registers
+ * @scratch: pointer to I/O remapped region for scratch registers
* @clk: pointer to pclk clock
* @soc: pointer to SoC data structure
+ * @tz_only: flag specifying if the PMC can only be accessed via TrustZone
* @debugfs: pointer to debugfs entry
* @rate: currently configured rate of pclk
* @suspend_mode: lowest suspend mode available
@@ -291,6 +302,9 @@ static const char * const tegra30_reset_sources[] = {
* @lp0_vec_size: size of the LP0 warm boot code
* @powergates_available: Bitmap of available power gates
* @powergates_lock: mutex for power gate register access
+ * @pctl_dev: pin controller exposed by the PMC
+ * @domain: IRQ domain provided by the PMC
+ * @irq: chip implementation for the IRQ domain
*/
struct tegra_pmc {
struct device *dev;
@@ -302,6 +316,7 @@ struct tegra_pmc {
struct dentry *debugfs;
const struct tegra_pmc_soc *soc;
+ bool tz_only;
unsigned long rate;
@@ -338,30 +353,85 @@ to_powergate(struct generic_pm_domain *domain)
return container_of(domain, struct tegra_powergate, genpd);
}
-static u32 tegra_pmc_readl(unsigned long offset)
+static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
{
+ struct arm_smccc_res res;
+
+ if (pmc->tz_only) {
+ arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
+ 0, 0, 0, &res);
+ if (res.a0) {
+ if (pmc->dev)
+ dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
+ __func__, res.a0);
+ else
+ pr_warn("%s(): SMC failed: %lu\n", __func__,
+ res.a0);
+ }
+
+ return res.a1;
+ }
+
return readl(pmc->base + offset);
}
-static void tegra_pmc_writel(u32 value, unsigned long offset)
+static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
+ unsigned long offset)
{
- writel(value, pmc->base + offset);
+ struct arm_smccc_res res;
+
+ if (pmc->tz_only) {
+ arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
+ value, 0, 0, 0, 0, &res);
+ if (res.a0) {
+ if (pmc->dev)
+ dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
+ __func__, res.a0);
+ else
+ pr_warn("%s(): SMC failed: %lu\n", __func__,
+ res.a0);
+ }
+ } else {
+ writel(value, pmc->base + offset);
+ }
}
+static u32 tegra_pmc_scratch_readl(struct tegra_pmc *pmc, unsigned long offset)
+{
+ if (pmc->tz_only)
+ return tegra_pmc_readl(pmc, offset);
+
+ return readl(pmc->scratch + offset);
+}
+
+static void tegra_pmc_scratch_writel(struct tegra_pmc *pmc, u32 value,
+ unsigned long offset)
+{
+ if (pmc->tz_only)
+ tegra_pmc_writel(pmc, value, offset);
+ else
+ writel(value, pmc->scratch + offset);
+}
+
+/*
+ * TODO Figure out a way to call this with the struct tegra_pmc * passed in.
+ * This currently doesn't work because readx_poll_timeout() can only operate
+ * on functions that take a single argument.
+ */
static inline bool tegra_powergate_state(int id)
{
if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
- return (tegra_pmc_readl(GPU_RG_CNTRL) & 0x1) == 0;
+ return (tegra_pmc_readl(pmc, GPU_RG_CNTRL) & 0x1) == 0;
else
- return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0;
+ return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
}
-static inline bool tegra_powergate_is_valid(int id)
+static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
{
return (pmc->soc && pmc->soc->powergates[id]);
}
-static inline bool tegra_powergate_is_available(int id)
+static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
{
return test_bit(id, pmc->powergates_available);
}
@@ -374,7 +444,7 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
return -EINVAL;
for (i = 0; i < pmc->soc->num_powergates; i++) {
- if (!tegra_powergate_is_valid(i))
+ if (!tegra_powergate_is_valid(pmc, i))
continue;
if (!strcmp(name, pmc->soc->powergates[i]))
@@ -386,10 +456,12 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
/**
* tegra_powergate_set() - set the state of a partition
+ * @pmc: power management controller
* @id: partition ID
* @new_state: new state of the partition
*/
-static int tegra_powergate_set(unsigned int id, bool new_state)
+static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
+ bool new_state)
{
bool status;
int err;
@@ -404,7 +476,7 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
return 0;
}
- tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
+ tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
err = readx_poll_timeout(tegra_powergate_state, id, status,
status == new_state, 10, 100000);
@@ -414,7 +486,8 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
return err;
}
-static int __tegra_powergate_remove_clamping(unsigned int id)
+static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
+ unsigned int id)
{
u32 mask;
@@ -426,7 +499,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
*/
if (id == TEGRA_POWERGATE_3D) {
if (pmc->soc->has_gpu_clamps) {
- tegra_pmc_writel(0, GPU_RG_CNTRL);
+ tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
goto out;
}
}
@@ -442,7 +515,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
else
mask = (1 << id);
- tegra_pmc_writel(mask, REMOVE_CLAMPING);
+ tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
out:
mutex_unlock(&pmc->powergates_lock);
@@ -494,7 +567,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
usleep_range(10, 20);
- err = tegra_powergate_set(pg->id, true);
+ err = tegra_powergate_set(pg->pmc, pg->id, true);
if (err < 0)
return err;
@@ -506,7 +579,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
usleep_range(10, 20);
- err = __tegra_powergate_remove_clamping(pg->id);
+ err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
if (err)
goto disable_clks;
@@ -533,7 +606,7 @@ disable_clks:
usleep_range(10, 20);
powergate_off:
- tegra_powergate_set(pg->id, false);
+ tegra_powergate_set(pg->pmc, pg->id, false);
return err;
}
@@ -558,7 +631,7 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg)
usleep_range(10, 20);
- err = tegra_powergate_set(pg->id, false);
+ err = tegra_powergate_set(pg->pmc, pg->id, false);
if (err)
goto assert_resets;
@@ -579,12 +652,13 @@ disable_clks:
static int tegra_genpd_power_on(struct generic_pm_domain *domain)
{
struct tegra_powergate *pg = to_powergate(domain);
+ struct device *dev = pg->pmc->dev;
int err;
err = tegra_powergate_power_up(pg, true);
if (err)
- pr_err("failed to turn on PM domain %s: %d\n", pg->genpd.name,
- err);
+ dev_err(dev, "failed to turn on PM domain %s: %d\n",
+ pg->genpd.name, err);
return err;
}
@@ -592,12 +666,13 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
static int tegra_genpd_power_off(struct generic_pm_domain *domain)
{
struct tegra_powergate *pg = to_powergate(domain);
+ struct device *dev = pg->pmc->dev;
int err;
err = tegra_powergate_power_down(pg);
if (err)
- pr_err("failed to turn off PM domain %s: %d\n",
- pg->genpd.name, err);
+ dev_err(dev, "failed to turn off PM domain %s: %d\n",
+ pg->genpd.name, err);
return err;
}
@@ -608,10 +683,10 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
*/
int tegra_powergate_power_on(unsigned int id)
{
- if (!tegra_powergate_is_available(id))
+ if (!tegra_powergate_is_available(pmc, id))
return -EINVAL;
- return tegra_powergate_set(id, true);
+ return tegra_powergate_set(pmc, id, true);
}
/**
@@ -620,20 +695,21 @@ int tegra_powergate_power_on(unsigned int id)
*/
int tegra_powergate_power_off(unsigned int id)
{
- if (!tegra_powergate_is_available(id))
+ if (!tegra_powergate_is_available(pmc, id))
return -EINVAL;
- return tegra_powergate_set(id, false);
+ return tegra_powergate_set(pmc, id, false);
}
EXPORT_SYMBOL(tegra_powergate_power_off);
/**
* tegra_powergate_is_powered() - check if partition is powered
+ * @pmc: power management controller
* @id: partition ID
*/
-int tegra_powergate_is_powered(unsigned int id)
+static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
{
- if (!tegra_powergate_is_valid(id))
+ if (!tegra_powergate_is_valid(pmc, id))
return -EINVAL;
return tegra_powergate_state(id);
@@ -645,10 +721,10 @@ int tegra_powergate_is_powered(unsigned int id)
*/
int tegra_powergate_remove_clamping(unsigned int id)
{
- if (!tegra_powergate_is_available(id))
+ if (!tegra_powergate_is_available(pmc, id))
return -EINVAL;
- return __tegra_powergate_remove_clamping(id);
+ return __tegra_powergate_remove_clamping(pmc, id);
}
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
@@ -666,7 +742,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
struct tegra_powergate *pg;
int err;
- if (!tegra_powergate_is_available(id))
+ if (!tegra_powergate_is_available(pmc, id))
return -EINVAL;
pg = kzalloc(sizeof(*pg), GFP_KERNEL);
@@ -681,7 +757,8 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
err = tegra_powergate_power_up(pg, false);
if (err)
- pr_err("failed to turn on partition %d: %d\n", id, err);
+ dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id,
+ err);
kfree(pg);
@@ -691,12 +768,14 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
/**
* tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
+ * @pmc: power management controller
* @cpuid: CPU partition ID
*
* Returns the partition ID corresponding to the CPU partition ID or a
* negative error code on failure.
*/
-static int tegra_get_cpu_powergate_id(unsigned int cpuid)
+static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
+ unsigned int cpuid)
{
if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
return pmc->soc->cpu_powergates[cpuid];
@@ -712,11 +791,11 @@ bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
{
int id;
- id = tegra_get_cpu_powergate_id(cpuid);
+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
if (id < 0)
return false;
- return tegra_powergate_is_powered(id);
+ return tegra_powergate_is_powered(pmc, id);
}
/**
@@ -727,11 +806,11 @@ int tegra_pmc_cpu_power_on(unsigned int cpuid)
{
int id;
- id = tegra_get_cpu_powergate_id(cpuid);
+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
if (id < 0)
return id;
- return tegra_powergate_set(id, true);
+ return tegra_powergate_set(pmc, id, true);
}
/**
@@ -742,7 +821,7 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
{
int id;
- id = tegra_get_cpu_powergate_id(cpuid);
+ id = tegra_get_cpu_powergate_id(pmc, cpuid);
if (id < 0)
return id;
@@ -755,7 +834,7 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
const char *cmd = data;
u32 value;
- value = readl(pmc->scratch + pmc->soc->regs->scratch0);
+ value = tegra_pmc_scratch_readl(pmc, pmc->soc->regs->scratch0);
value &= ~PMC_SCRATCH0_MODE_MASK;
if (cmd) {
@@ -769,12 +848,12 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
value |= PMC_SCRATCH0_MODE_RCM;
}
- writel(value, pmc->scratch + pmc->soc->regs->scratch0);
+ tegra_pmc_scratch_writel(pmc, value, pmc->soc->regs->scratch0);
/* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
value |= PMC_CNTRL_MAIN_RST;
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
return NOTIFY_DONE;
}
@@ -793,7 +872,7 @@ static int powergate_show(struct seq_file *s, void *data)
seq_printf(s, "------------------\n");
for (i = 0; i < pmc->soc->num_powergates; i++) {
- status = tegra_powergate_is_powered(i);
+ status = tegra_powergate_is_powered(pmc, i);
if (status < 0)
continue;
@@ -855,12 +934,13 @@ err:
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
struct device_node *np, bool off)
{
+ struct device *dev = pg->pmc->dev;
int err;
pg->reset = of_reset_control_array_get_exclusive(np);
if (IS_ERR(pg->reset)) {
err = PTR_ERR(pg->reset);
- pr_err("failed to get device resets: %d\n", err);
+ dev_err(dev, "failed to get device resets: %d\n", err);
return err;
}
@@ -877,6 +957,7 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
{
+ struct device *dev = pmc->dev;
struct tegra_powergate *pg;
int id, err;
bool off;
@@ -887,7 +968,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
id = tegra_powergate_lookup(pmc, np->name);
if (id < 0) {
- pr_err("powergate lookup failed for %pOFn: %d\n", np, id);
+ dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
goto free_mem;
}
@@ -903,17 +984,17 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
pg->genpd.power_on = tegra_genpd_power_on;
pg->pmc = pmc;
- off = !tegra_powergate_is_powered(pg->id);
+ off = !tegra_powergate_is_powered(pmc, pg->id);
err = tegra_powergate_of_get_clks(pg, np);
if (err < 0) {
- pr_err("failed to get clocks for %pOFn: %d\n", np, err);
+ dev_err(dev, "failed to get clocks for %pOFn: %d\n", np, err);
goto set_available;
}
err = tegra_powergate_of_get_resets(pg, np, off);
if (err < 0) {
- pr_err("failed to get resets for %pOFn: %d\n", np, err);
+ dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err);
goto remove_clks;
}
@@ -926,19 +1007,19 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
err = pm_genpd_init(&pg->genpd, NULL, off);
if (err < 0) {
- pr_err("failed to initialise PM domain %pOFn: %d\n", np,
+ dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np,
err);
goto remove_resets;
}
err = of_genpd_add_provider_simple(np, &pg->genpd);
if (err < 0) {
- pr_err("failed to add PM domain provider for %pOFn: %d\n",
- np, err);
+ dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
+ np, err);
goto remove_genpd;
}
- pr_debug("added PM domain %s\n", pg->genpd.name);
+ dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
return;
@@ -994,7 +1075,8 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
return NULL;
}
-static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
+static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
+ enum tegra_io_pad id,
unsigned long *request,
unsigned long *status,
u32 *mask)
@@ -1003,7 +1085,7 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
pad = tegra_io_pad_find(pmc, id);
if (!pad) {
- pr_err("invalid I/O pad ID %u\n", id);
+ dev_err(pmc->dev, "invalid I/O pad ID %u\n", id);
return -ENOENT;
}
@@ -1023,43 +1105,44 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
return 0;
}
-static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
- unsigned long *status, u32 *mask)
+static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
+ unsigned long *request, unsigned long *status,
+ u32 *mask)
{
unsigned long rate, value;
int err;
- err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask);
+ err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask);
if (err)
return err;
if (pmc->clk) {
rate = clk_get_rate(pmc->clk);
if (!rate) {
- pr_err("failed to get clock rate\n");
+ dev_err(pmc->dev, "failed to get clock rate\n");
return -ENODEV;
}
- tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
+ tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
/* must be at least 200 ns, in APB (PCLK) clock cycles */
value = DIV_ROUND_UP(1000000000, rate);
value = DIV_ROUND_UP(200, value);
- tegra_pmc_writel(value, SEL_DPD_TIM);
+ tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
}
return 0;
}
-static int tegra_io_pad_poll(unsigned long offset, u32 mask,
- u32 val, unsigned long timeout)
+static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
+ u32 mask, u32 val, unsigned long timeout)
{
u32 value;
timeout = jiffies + msecs_to_jiffies(timeout);
while (time_after(timeout, jiffies)) {
- value = tegra_pmc_readl(offset);
+ value = tegra_pmc_readl(pmc, offset);
if ((value & mask) == val)
return 0;
@@ -1069,10 +1152,10 @@ static int tegra_io_pad_poll(unsigned long offset, u32 mask,
return -ETIMEDOUT;
}
-static void tegra_io_pad_unprepare(void)
+static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
{
if (pmc->clk)
- tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
+ tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
}
/**
@@ -1089,21 +1172,21 @@ int tegra_io_pad_power_enable(enum tegra_io_pad id)
mutex_lock(&pmc->powergates_lock);
- err = tegra_io_pad_prepare(id, &request, &status, &mask);
+ err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
if (err < 0) {
- pr_err("failed to prepare I/O pad: %d\n", err);
+ dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
goto unlock;
}
- tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request);
+ tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
- err = tegra_io_pad_poll(status, mask, 0, 250);
+ err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
if (err < 0) {
- pr_err("failed to enable I/O pad: %d\n", err);
+ dev_err(pmc->dev, "failed to enable I/O pad: %d\n", err);
goto unlock;
}
- tegra_io_pad_unprepare();
+ tegra_io_pad_unprepare(pmc);
unlock:
mutex_unlock(&pmc->powergates_lock);
@@ -1125,21 +1208,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
mutex_lock(&pmc->powergates_lock);
- err = tegra_io_pad_prepare(id, &request, &status, &mask);
+ err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
if (err < 0) {
- pr_err("failed to prepare I/O pad: %d\n", err);
+ dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
goto unlock;
}
- tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request);
+ tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
- err = tegra_io_pad_poll(status, mask, mask, 250);
+ err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
if (err < 0) {
- pr_err("failed to disable I/O pad: %d\n", err);
+ dev_err(pmc->dev, "failed to disable I/O pad: %d\n", err);
goto unlock;
}
- tegra_io_pad_unprepare();
+ tegra_io_pad_unprepare(pmc);
unlock:
mutex_unlock(&pmc->powergates_lock);
@@ -1147,22 +1230,24 @@ unlock:
}
EXPORT_SYMBOL(tegra_io_pad_power_disable);
-static int tegra_io_pad_is_powered(enum tegra_io_pad id)
+static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
{
unsigned long request, status;
u32 mask, value;
int err;
- err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask);
+ err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status,
+ &mask);
if (err)
return err;
- value = tegra_pmc_readl(status);
+ value = tegra_pmc_readl(pmc, status);
return !(value & mask);
}
-static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
+static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
+ int voltage)
{
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1177,29 +1262,29 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
mutex_lock(&pmc->powergates_lock);
if (pmc->soc->has_impl_33v_pwr) {
- value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+ value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
- tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
+ tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
} else {
/* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
- value = tegra_pmc_readl(PMC_PWR_DET);
+ value = tegra_pmc_readl(pmc, PMC_PWR_DET);
value |= BIT(pad->voltage);
- tegra_pmc_writel(value, PMC_PWR_DET);
+ tegra_pmc_writel(pmc, value, PMC_PWR_DET);
/* update I/O voltage */
- value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+ value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
- tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+ tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
}
mutex_unlock(&pmc->powergates_lock);
@@ -1209,7 +1294,7 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
return 0;
}
-static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
{
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1222,9 +1307,9 @@ static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
return -ENOTSUPP;
if (pmc->soc->has_impl_33v_pwr)
- value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+ value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
else
- value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+ value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
if ((value & BIT(pad->voltage)) == 0)
return TEGRA_IO_PAD_VOLTAGE_1V8;
@@ -1296,21 +1381,21 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
do_div(ticks, USEC_PER_SEC);
- tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
+ tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
do_div(ticks, USEC_PER_SEC);
- tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
+ tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
wmb();
pmc->rate = rate;
}
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
value |= PMC_CNTRL_CPU_PWRREQ_OE;
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
}
#endif
@@ -1432,13 +1517,13 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
pinmux = 0;
- value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+ value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
- tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+ tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
(reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
- tegra_pmc_writel(value, PMC_SCRATCH54);
+ tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
value = PMC_SCRATCH55_RESET_TEGRA;
value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
@@ -1456,11 +1541,11 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
- tegra_pmc_writel(value, PMC_SCRATCH55);
+ tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
- value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+ value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
value |= PMC_SENSOR_CTRL_ENABLE_RST;
- tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+ tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
dev_info(pmc->dev, "emergency thermal reset enabled\n");
@@ -1470,12 +1555,16 @@ out:
static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
{
+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
+
return pmc->soc->num_io_pads;
}
-static const char *tegra_io_pad_pinctrl_get_group_name(
- struct pinctrl_dev *pctl, unsigned int group)
+static const char *tegra_io_pad_pinctrl_get_group_name(struct pinctrl_dev *pctl,
+ unsigned int group)
{
+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
+
return pmc->soc->io_pads[group].name;
}
@@ -1484,8 +1573,11 @@ static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
const unsigned int **pins,
unsigned int *num_pins)
{
+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
+
*pins = &pmc->soc->io_pads[group].id;
*num_pins = 1;
+
return 0;
}
@@ -1500,27 +1592,33 @@ static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
unsigned int pin, unsigned long *config)
{
- const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
enum pin_config_param param = pinconf_to_config_param(*config);
+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
+ const struct tegra_io_pad_soc *pad;
int ret;
u32 arg;
+ pad = tegra_io_pad_find(pmc, pin);
if (!pad)
return -EINVAL;
switch (param) {
case PIN_CONFIG_POWER_SOURCE:
- ret = tegra_io_pad_get_voltage(pad->id);
+ ret = tegra_io_pad_get_voltage(pmc, pad->id);
if (ret < 0)
return ret;
+
arg = ret;
break;
+
case PIN_CONFIG_LOW_POWER_MODE:
- ret = tegra_io_pad_is_powered(pad->id);
+ ret = tegra_io_pad_is_powered(pmc, pad->id);
if (ret < 0)
return ret;
+
arg = !ret;
break;
+
default:
return -EINVAL;
}
@@ -1534,12 +1632,14 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
unsigned int pin, unsigned long *configs,
unsigned int num_configs)
{
- const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+ struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
+ const struct tegra_io_pad_soc *pad;
enum pin_config_param param;
unsigned int i;
int err;
u32 arg;
+ pad = tegra_io_pad_find(pmc, pin);
if (!pad)
return -EINVAL;
@@ -1560,7 +1660,7 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
arg != TEGRA_IO_PAD_VOLTAGE_3V3)
return -EINVAL;
- err = tegra_io_pad_set_voltage(pad->id, arg);
+ err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
if (err)
return err;
break;
@@ -1585,7 +1685,7 @@ static struct pinctrl_desc tegra_pmc_pctl_desc = {
static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
{
- int err = 0;
+ int err;
if (!pmc->soc->num_pin_descs)
return 0;
@@ -1598,18 +1698,20 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
pmc);
if (IS_ERR(pmc->pctl_dev)) {
err = PTR_ERR(pmc->pctl_dev);
- dev_err(pmc->dev, "unable to register pinctrl, %d\n", err);
+ dev_err(pmc->dev, "failed to register pin controller: %d\n",
+ err);
+ return err;
}
- return err;
+ return 0;
}
static ssize_t reset_reason_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
u32 value, rst_src;
- value = tegra_pmc_readl(pmc->soc->regs->rst_status);
+ value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
rst_src = (value & pmc->soc->regs->rst_source_mask) >>
pmc->soc->regs->rst_source_shift;
@@ -1619,11 +1721,11 @@ static ssize_t reset_reason_show(struct device *dev,
static DEVICE_ATTR_RO(reset_reason);
static ssize_t reset_level_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
u32 value, rst_lvl;
- value = tegra_pmc_readl(pmc->soc->regs->rst_status);
+ value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
pmc->soc->regs->rst_level_shift;
@@ -1641,16 +1743,16 @@ static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
err = device_create_file(dev, &dev_attr_reset_reason);
if (err < 0)
dev_warn(dev,
- "failed to create attr \"reset_reason\": %d\n",
- err);
+ "failed to create attr \"reset_reason\": %d\n",
+ err);
}
if (pmc->soc->reset_levels) {
err = device_create_file(dev, &dev_attr_reset_level);
if (err < 0)
dev_warn(dev,
- "failed to create attr \"reset_level\": %d\n",
- err);
+ "failed to create attr \"reset_level\": %d\n",
+ err);
}
}
@@ -1920,6 +2022,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
pmc->base = base;
mutex_unlock(&pmc->powergates_lock);
+ platform_set_drvdata(pdev, pmc);
+
return 0;
cleanup_restart_handler:
@@ -1932,14 +2036,18 @@ cleanup_debugfs:
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
static int tegra_pmc_suspend(struct device *dev)
{
- tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
+ struct tegra_pmc *pmc = dev_get_drvdata(dev);
+
+ tegra_pmc_writel(pmc, virt_to_phys(tegra_resume), PMC_SCRATCH41);
return 0;
}
static int tegra_pmc_resume(struct device *dev)
{
- tegra_pmc_writel(0x0, PMC_SCRATCH41);
+ struct tegra_pmc *pmc = dev_get_drvdata(dev);
+
+ tegra_pmc_writel(pmc, 0x0, PMC_SCRATCH41);
return 0;
}
@@ -1976,11 +2084,11 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
u32 value;
/* Always enable CPU power request */
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
value |= PMC_CNTRL_CPU_PWRREQ_OE;
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
if (pmc->sysclkreq_high)
value &= ~PMC_CNTRL_SYSCLK_POLARITY;
@@ -1988,12 +2096,12 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
value |= PMC_CNTRL_SYSCLK_POLARITY;
/* configure the output polarity while the request is tristated */
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
/* now enable the request */
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
value |= PMC_CNTRL_SYSCLK_OE;
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
}
static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
@@ -2002,14 +2110,14 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
{
u32 value;
- value = tegra_pmc_readl(PMC_CNTRL);
+ value = tegra_pmc_readl(pmc, PMC_CNTRL);
if (invert)
value |= PMC_CNTRL_INTR_POLARITY;
else
value &= ~PMC_CNTRL_INTR_POLARITY;
- tegra_pmc_writel(value, PMC_CNTRL);
+ tegra_pmc_writel(pmc, value, PMC_CNTRL);
}
static const struct tegra_pmc_soc tegra20_pmc_soc = {
@@ -2019,6 +2127,9 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.cpu_powergates = NULL,
.has_tsense_reset = false,
.has_gpu_clamps = false,
+ .needs_mbist_war = false,
+ .has_impl_33v_pwr = false,
+ .maybe_tz_only = false,
.num_io_pads = 0,
.io_pads = NULL,
.num_pin_descs = 0,
@@ -2063,7 +2174,9 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.cpu_powergates = tegra30_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+ .needs_mbist_war = false,
.has_impl_33v_pwr = false,
+ .maybe_tz_only = false,
.num_io_pads = 0,
.io_pads = NULL,
.num_pin_descs = 0,
@@ -2112,7 +2225,9 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.cpu_powergates = tegra114_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+ .needs_mbist_war = false,
.has_impl_33v_pwr = false,
+ .maybe_tz_only = false,
.num_io_pads = 0,
.io_pads = NULL,
.num_pin_descs = 0,
@@ -2221,7 +2336,9 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.cpu_powergates = tegra124_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+ .needs_mbist_war = false,
.has_impl_33v_pwr = false,
+ .maybe_tz_only = false,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
.num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
@@ -2325,8 +2442,9 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.cpu_powergates = tegra210_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
- .has_impl_33v_pwr = false,
.needs_mbist_war = true,
+ .has_impl_33v_pwr = false,
+ .maybe_tz_only = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
.num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
@@ -2413,7 +2531,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
index = of_property_match_string(np, "reg-names", "wake");
if (index < 0) {
- pr_err("failed to find PMC wake registers\n");
+ dev_err(pmc->dev, "failed to find PMC wake registers\n");
return;
}
@@ -2421,7 +2539,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
wake = ioremap_nocache(regs.start, resource_size(&regs));
if (!wake) {
- pr_err("failed to map PMC wake registers\n");
+ dev_err(pmc->dev, "failed to map PMC wake registers\n");
return;
}
@@ -2438,7 +2556,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
}
static const struct tegra_wake_event tegra186_wake_events[] = {
- TEGRA_WAKE_GPIO("power", 29, 1, TEGRA_AON_GPIO(FF, 0)),
+ TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)),
TEGRA_WAKE_IRQ("rtc", 73, 10),
};
@@ -2449,7 +2567,9 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.cpu_powergates = NULL,
.has_tsense_reset = false,
.has_gpu_clamps = false,
+ .needs_mbist_war = false,
.has_impl_33v_pwr = true,
+ .maybe_tz_only = false,
.num_io_pads = ARRAY_SIZE(tegra186_io_pads),
.io_pads = tegra186_io_pads,
.num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
@@ -2527,6 +2647,9 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
.cpu_powergates = NULL,
.has_tsense_reset = false,
.has_gpu_clamps = false,
+ .needs_mbist_war = false,
+ .has_impl_33v_pwr = false,
+ .maybe_tz_only = false,
.num_io_pads = ARRAY_SIZE(tegra194_io_pads),
.io_pads = tegra194_io_pads,
.regs = &tegra186_pmc_regs,
@@ -2561,6 +2684,32 @@ static struct platform_driver tegra_pmc_driver = {
};
builtin_platform_driver(tegra_pmc_driver);
+static bool __init tegra_pmc_detect_tz_only(struct tegra_pmc *pmc)
+{
+ u32 value, saved;
+
+ saved = readl(pmc->base + pmc->soc->regs->scratch0);
+ value = saved ^ 0xffffffff;
+
+ if (value == 0xffffffff)
+ value = 0xdeadbeef;
+
+ /* write pattern and read it back */
+ writel(value, pmc->base + pmc->soc->regs->scratch0);
+ value = readl(pmc->base + pmc->soc->regs->scratch0);
+
+ /* if we read all-zeroes, access is restricted to TZ only */
+ if (value == 0) {
+ pr_info("access to PMC is restricted to TZ\n");
+ return true;
+ }
+
+ /* restore original value */
+ writel(saved, pmc->base + pmc->soc->regs->scratch0);
+
+ return false;
+}
+
/*
* Early initialization to allow access to registers in the very early boot
* process.
@@ -2623,6 +2772,9 @@ static int __init tegra_pmc_early_init(void)
if (np) {
pmc->soc = match->data;
+ if (pmc->soc->maybe_tz_only)
+ pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
+
tegra_powergate_init(pmc, np);
/*
diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c
index e05ab16d9a9e..6285cd8efb21 100644
--- a/drivers/soc/ti/knav_dma.c
+++ b/drivers/soc/ti/knav_dma.c
@@ -598,7 +598,7 @@ static int pktdma_init_chan(struct knav_dma_device *dma,
INIT_LIST_HEAD(&chan->list);
chan->dma = dma;
- chan->direction = DMA_NONE;
+ chan->direction = DMA_TRANS_NONE;
atomic_set(&chan->ref_count, 0);
spin_lock_init(&chan->lock);
diff --git a/drivers/soc/xilinx/Kconfig b/drivers/soc/xilinx/Kconfig
index 687c8f3cd955..01e76b58dd78 100644
--- a/drivers/soc/xilinx/Kconfig
+++ b/drivers/soc/xilinx/Kconfig
@@ -17,4 +17,24 @@ config XILINX_VCU
To compile this driver as a module, choose M here: the
module will be called xlnx_vcu.
+config ZYNQMP_POWER
+ bool "Enable Xilinx Zynq MPSoC Power Management driver"
+ depends on PM && ARCH_ZYNQMP
+ default y
+ help
+ Say yes to enable power management support for ZyqnMP SoC.
+ This driver uses firmware driver as an interface for power
+ management request to firmware. It registers isr to handle
+ power management callbacks from firmware.
+ If in doubt, say N.
+
+config ZYNQMP_PM_DOMAINS
+ bool "Enable Zynq MPSoC generic PM domains"
+ default y
+ depends on PM && ARCH_ZYNQMP && ZYNQMP_FIRMWARE
+ select PM_GENERIC_DOMAINS
+ help
+ Say yes to enable device power management through PM domains
+ If in doubt, say N.
+
endmenu
diff --git a/drivers/soc/xilinx/Makefile b/drivers/soc/xilinx/Makefile
index dee8fd51e303..f66bfea5de17 100644
--- a/drivers/soc/xilinx/Makefile
+++ b/drivers/soc/xilinx/Makefile
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o
+obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o
+obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o
diff --git a/drivers/soc/xilinx/zynqmp_pm_domains.c b/drivers/soc/xilinx/zynqmp_pm_domains.c
new file mode 100644
index 000000000000..354d256e6e00
--- /dev/null
+++ b/drivers/soc/xilinx/zynqmp_pm_domains.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP Generic PM domain support
+ *
+ * Copyright (C) 2015-2018 Xilinx, Inc.
+ *
+ * Davorin Mista <davorin.mista@aggios.com>
+ * Jolly Shah <jollys@xilinx.com>
+ * Rajan Vaja <rajan.vaja@xilinx.com>
+ */
+
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define ZYNQMP_NUM_DOMAINS (100)
+/* Flag stating if PM nodes mapped to the PM domain has been requested */
+#define ZYNQMP_PM_DOMAIN_REQUESTED BIT(0)
+
+/**
+ * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
+ * @gpd: Generic power domain
+ * @node_id: PM node ID corresponding to device inside PM domain
+ * @flags: ZynqMP PM domain flags
+ */
+struct zynqmp_pm_domain {
+ struct generic_pm_domain gpd;
+ u32 node_id;
+ u8 flags;
+};
+
+/**
+ * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source
+ * path
+ * @dev: Device to check for wakeup source path
+ * @not_used: Data member (not required)
+ *
+ * This function is checks device's child hierarchy and checks if any device is
+ * set as wakeup source.
+ *
+ * Return: 1 if device is in wakeup source path else 0
+ */
+static int zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used)
+{
+ int may_wakeup;
+
+ may_wakeup = device_may_wakeup(dev);
+ if (may_wakeup)
+ return may_wakeup;
+
+ return device_for_each_child(dev, NULL,
+ zynqmp_gpd_is_active_wakeup_path);
+}
+
+/**
+ * zynqmp_gpd_power_on() - Power on PM domain
+ * @domain: Generic PM domain
+ *
+ * This function is called before devices inside a PM domain are resumed, to
+ * power on PM domain.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct zynqmp_pm_domain *pd;
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->set_requirement)
+ return -ENXIO;
+
+ pd = container_of(domain, struct zynqmp_pm_domain, gpd);
+ ret = eemi_ops->set_requirement(pd->node_id,
+ ZYNQMP_PM_CAPABILITY_ACCESS,
+ ZYNQMP_PM_MAX_QOS,
+ ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ if (ret) {
+ pr_err("%s() %s set requirement for node %d failed: %d\n",
+ __func__, domain->name, pd->node_id, ret);
+ return ret;
+ }
+
+ pr_debug("%s() Powered on %s domain\n", __func__, domain->name);
+ return 0;
+}
+
+/**
+ * zynqmp_gpd_power_off() - Power off PM domain
+ * @domain: Generic PM domain
+ *
+ * This function is called after devices inside a PM domain are suspended, to
+ * power off PM domain.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct pm_domain_data *pdd, *tmp;
+ struct zynqmp_pm_domain *pd;
+ u32 capabilities = 0;
+ bool may_wakeup;
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->set_requirement)
+ return -ENXIO;
+
+ pd = container_of(domain, struct zynqmp_pm_domain, gpd);
+
+ /* If domain is already released there is nothing to be done */
+ if (!(pd->flags & ZYNQMP_PM_DOMAIN_REQUESTED)) {
+ pr_debug("%s() %s domain is already released\n",
+ __func__, domain->name);
+ return 0;
+ }
+
+ list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) {
+ /* If device is in wakeup path, set capability to WAKEUP */
+ may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL);
+ if (may_wakeup) {
+ dev_dbg(pdd->dev, "device is in wakeup path in %s\n",
+ domain->name);
+ capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP;
+ break;
+ }
+ }
+
+ ret = eemi_ops->set_requirement(pd->node_id, capabilities, 0,
+ ZYNQMP_PM_REQUEST_ACK_NO);
+ /**
+ * If powering down of any node inside this domain fails,
+ * report and return the error
+ */
+ if (ret) {
+ pr_err("%s() %s set requirement for node %d failed: %d\n",
+ __func__, domain->name, pd->node_id, ret);
+ return ret;
+ }
+
+ pr_debug("%s() Powered off %s domain\n", __func__, domain->name);
+ return 0;
+}
+
+/**
+ * zynqmp_gpd_attach_dev() - Attach device to the PM domain
+ * @domain: Generic PM domain
+ * @dev: Device to attach
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ int ret;
+ struct zynqmp_pm_domain *pd;
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->request_node)
+ return -ENXIO;
+
+ pd = container_of(domain, struct zynqmp_pm_domain, gpd);
+
+ /* If this is not the first device to attach there is nothing to do */
+ if (domain->device_count)
+ return 0;
+
+ ret = eemi_ops->request_node(pd->node_id, 0, 0,
+ ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ /* If requesting a node fails print and return the error */
+ if (ret) {
+ pr_err("%s() %s request failed for node %d: %d\n",
+ __func__, domain->name, pd->node_id, ret);
+ return ret;
+ }
+
+ pd->flags |= ZYNQMP_PM_DOMAIN_REQUESTED;
+
+ pr_debug("%s() %s attached to %s domain\n", __func__,
+ dev_name(dev), domain->name);
+ return 0;
+}
+
+/**
+ * zynqmp_gpd_detach_dev() - Detach device from the PM domain
+ * @domain: Generic PM domain
+ * @dev: Device to detach
+ */
+static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ int ret;
+ struct zynqmp_pm_domain *pd;
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->release_node)
+ return;
+
+ pd = container_of(domain, struct zynqmp_pm_domain, gpd);
+
+ /* If this is not the last device to detach there is nothing to do */
+ if (domain->device_count)
+ return;
+
+ ret = eemi_ops->release_node(pd->node_id);
+ /* If releasing a node fails print the error and return */
+ if (ret) {
+ pr_err("%s() %s release failed for node %d: %d\n",
+ __func__, domain->name, pd->node_id, ret);
+ return;
+ }
+
+ pd->flags &= ~ZYNQMP_PM_DOMAIN_REQUESTED;
+
+ pr_debug("%s() %s detached from %s domain\n", __func__,
+ dev_name(dev), domain->name);
+}
+
+static struct generic_pm_domain *zynqmp_gpd_xlate
+ (struct of_phandle_args *genpdspec, void *data)
+{
+ struct genpd_onecell_data *genpd_data = data;
+ unsigned int i, idx = genpdspec->args[0];
+ struct zynqmp_pm_domain *pd;
+
+ pd = container_of(genpd_data->domains[0], struct zynqmp_pm_domain, gpd);
+
+ if (genpdspec->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ /* Check for existing pm domains */
+ for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
+ if (pd[i].node_id == idx)
+ goto done;
+ }
+
+ /**
+ * Add index in empty node_id of power domain list as no existing
+ * power domain found for current index.
+ */
+ for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
+ if (pd[i].node_id == 0) {
+ pd[i].node_id = idx;
+ break;
+ }
+ }
+
+done:
+ if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS)
+ return ERR_PTR(-ENOENT);
+
+ return genpd_data->domains[i];
+}
+
+static int zynqmp_gpd_probe(struct platform_device *pdev)
+{
+ int i;
+ struct genpd_onecell_data *zynqmp_pd_data;
+ struct generic_pm_domain **domains;
+ struct zynqmp_pm_domain *pd;
+ struct device *dev = &pdev->dev;
+
+ pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ zynqmp_pd_data = devm_kzalloc(dev, sizeof(*zynqmp_pd_data), GFP_KERNEL);
+ if (!zynqmp_pd_data)
+ return -ENOMEM;
+
+ zynqmp_pd_data->xlate = zynqmp_gpd_xlate;
+
+ domains = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*domains),
+ GFP_KERNEL);
+ if (!domains)
+ return -ENOMEM;
+
+ for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++, pd++) {
+ pd->node_id = 0;
+ pd->gpd.name = kasprintf(GFP_KERNEL, "domain%d", i);
+ pd->gpd.power_off = zynqmp_gpd_power_off;
+ pd->gpd.power_on = zynqmp_gpd_power_on;
+ pd->gpd.attach_dev = zynqmp_gpd_attach_dev;
+ pd->gpd.detach_dev = zynqmp_gpd_detach_dev;
+
+ domains[i] = &pd->gpd;
+
+ /* Mark all PM domains as initially powered off */
+ pm_genpd_init(&pd->gpd, NULL, true);
+ }
+
+ zynqmp_pd_data->domains = domains;
+ zynqmp_pd_data->num_domains = ZYNQMP_NUM_DOMAINS;
+ of_genpd_add_provider_onecell(dev->parent->of_node, zynqmp_pd_data);
+
+ return 0;
+}
+
+static int zynqmp_gpd_remove(struct platform_device *pdev)
+{
+ of_genpd_del_provider(pdev->dev.parent->of_node);
+
+ return 0;
+}
+
+static struct platform_driver zynqmp_power_domain_driver = {
+ .driver = {
+ .name = "zynqmp_power_controller",
+ },
+ .probe = zynqmp_gpd_probe,
+ .remove = zynqmp_gpd_remove,
+};
+module_platform_driver(zynqmp_power_domain_driver);
+
+MODULE_ALIAS("platform:zynqmp_power_controller");
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
new file mode 100644
index 000000000000..771cb59b9d22
--- /dev/null
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Zynq MPSoC Power Management
+ *
+ * Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ * Davorin Mista <davorin.mista@aggios.com>
+ * Jolly Shah <jollys@xilinx.com>
+ * Rajan Vaja <rajan.vaja@xilinx.com>
+ */
+
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/suspend.h>
+
+#include <linux/firmware/xlnx-zynqmp.h>
+
+enum pm_suspend_mode {
+ PM_SUSPEND_MODE_FIRST = 0,
+ PM_SUSPEND_MODE_STD = PM_SUSPEND_MODE_FIRST,
+ PM_SUSPEND_MODE_POWER_OFF,
+};
+
+#define PM_SUSPEND_MODE_FIRST PM_SUSPEND_MODE_STD
+
+static const char *const suspend_modes[] = {
+ [PM_SUSPEND_MODE_STD] = "standard",
+ [PM_SUSPEND_MODE_POWER_OFF] = "power-off",
+};
+
+static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD;
+
+enum pm_api_cb_id {
+ PM_INIT_SUSPEND_CB = 30,
+ PM_ACKNOWLEDGE_CB,
+ PM_NOTIFY_CB,
+};
+
+static void zynqmp_pm_get_callback_data(u32 *buf)
+{
+ zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, 0, 0, 0, 0, buf);
+}
+
+static irqreturn_t zynqmp_pm_isr(int irq, void *data)
+{
+ u32 payload[CB_PAYLOAD_SIZE];
+
+ zynqmp_pm_get_callback_data(payload);
+
+ /* First element is callback API ID, others are callback arguments */
+ if (payload[0] == PM_INIT_SUSPEND_CB) {
+ switch (payload[1]) {
+ case SUSPEND_SYSTEM_SHUTDOWN:
+ orderly_poweroff(true);
+ break;
+ case SUSPEND_POWER_REQUEST:
+ pm_suspend(PM_SUSPEND_MEM);
+ break;
+ default:
+ pr_err("%s Unsupported InitSuspendCb reason "
+ "code %d\n", __func__, payload[1]);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t suspend_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char *s = buf;
+ int md;
+
+ for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
+ if (suspend_modes[md]) {
+ if (md == suspend_mode)
+ s += sprintf(s, "[%s] ", suspend_modes[md]);
+ else
+ s += sprintf(s, "%s ", suspend_modes[md]);
+ }
+
+ /* Convert last space to newline */
+ if (s != buf)
+ *(s - 1) = '\n';
+ return (s - buf);
+}
+
+static ssize_t suspend_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int md, ret = -EINVAL;
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->set_suspend_mode)
+ return ret;
+
+ for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
+ if (suspend_modes[md] &&
+ sysfs_streq(suspend_modes[md], buf)) {
+ ret = 0;
+ break;
+ }
+
+ if (!ret && md != suspend_mode) {
+ ret = eemi_ops->set_suspend_mode(md);
+ if (likely(!ret))
+ suspend_mode = md;
+ }
+
+ return ret ? ret : count;
+}
+
+static DEVICE_ATTR_RW(suspend_mode);
+
+static int zynqmp_pm_probe(struct platform_device *pdev)
+{
+ int ret, irq;
+ u32 pm_api_version;
+
+ const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+ if (!eemi_ops || !eemi_ops->get_api_version || !eemi_ops->init_finalize)
+ return -ENXIO;
+
+ eemi_ops->init_finalize();
+ eemi_ops->get_api_version(&pm_api_version);
+
+ /* Check PM API version number */
+ if (pm_api_version < ZYNQMP_PM_VERSION)
+ return -ENODEV;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return -ENXIO;
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, zynqmp_pm_isr,
+ IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ dev_name(&pdev->dev), &pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "devm_request_threaded_irq '%d' failed "
+ "with %d\n", irq, ret);
+ return ret;
+ }
+
+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to create sysfs interface\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zynqmp_pm_remove(struct platform_device *pdev)
+{
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
+
+ return 0;
+}
+
+static const struct of_device_id pm_of_match[] = {
+ { .compatible = "xlnx,zynqmp-power", },
+ { /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, pm_of_match);
+
+static struct platform_driver zynqmp_pm_platform_driver = {
+ .probe = zynqmp_pm_probe,
+ .remove = zynqmp_pm_remove,
+ .driver = {
+ .name = "zynqmp_power",
+ .of_match_table = pm_of_match,
+ },
+};
+module_platform_driver(zynqmp_pm_platform_driver);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9f89cb134549..f761655e2a36 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -63,7 +63,7 @@ config SPI_ALTERA
config SPI_ATH79
tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
- depends on ATH79 && GPIOLIB
+ depends on ATH79 || COMPILE_TEST
select SPI_BITBANG
help
This enables support for the SPI controller present on the
@@ -268,6 +268,27 @@ config SPI_FSL_LPSPI
help
This enables Freescale i.MX LPSPI controllers in master mode.
+config SPI_FSL_QUADSPI
+ tristate "Freescale QSPI controller"
+ depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This enables support for the Quad SPI controller in master mode.
+ Up to four flash chips can be connected on two buses with two
+ chipselects each.
+ This controller does not support generic SPI messages. It only
+ supports the high-level SPI memory interface.
+
+config SPI_NXP_FLEXSPI
+ tristate "NXP Flex SPI controller"
+ depends on ARCH_LAYERSCAPE || HAS_IOMEM
+ help
+ This enables support for the Flex SPI controller in master mode.
+ Up to four slave devices can be connected on two buses with two
+ chipselects each.
+ This controller does not support generic SPI messages and only
+ supports the high-level SPI memory interface.
+
config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master"
depends on GPIOLIB || COMPILE_TEST
@@ -296,8 +317,7 @@ config SPI_IMX
depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
help
- This enables using the Freescale i.MX SPI controllers in master
- mode.
+ This enables support for the Freescale i.MX SPI controllers.
config SPI_JCORE
tristate "J-Core SPI Master"
@@ -372,7 +392,7 @@ config SPI_FSL_DSPI
depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || M5441x || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
- mode. VF610 platform uses the controller.
+ mode. VF610, LS1021A and ColdFire platforms uses the controller.
config SPI_FSL_ESPI
tristate "Freescale eSPI controller"
@@ -631,6 +651,12 @@ config SPI_SH_HSPI
help
SPI driver for SuperH HSPI blocks.
+config SPI_SIFIVE
+ tristate "SiFive SPI controller"
+ depends on HAS_IOMEM
+ help
+ This exposes the SPI controller IP from SiFive.
+
config SPI_SIRF
tristate "CSR SiRFprimaII SPI controller"
depends on SIRF_DMA
@@ -665,7 +691,7 @@ config SPI_STM32
tristate "STMicroelectronics STM32 SPI controller"
depends on ARCH_STM32 || COMPILE_TEST
help
- SPI driver for STMicroelectonics STM32 SoCs.
+ SPI driver for STMicroelectronics STM32 SoCs.
STM32 SPI controller supports DMA and PIO modes. When DMA
is not available, the driver automatically falls back to
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f29627040dfb..d8fc03c9faa2 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o
+obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
+obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o
obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o
@@ -93,6 +95,7 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o
obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
+obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o
obj-$(CONFIG_SPI_SPRD) += spi-sprd.o
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index ddc712410812..fffc21cd5f79 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Atmel QSPI Controller
*
@@ -7,31 +8,19 @@
* Author: Cyrille Pitchen <cyrille.pitchen@atmel.com>
* Author: Piotr Bugalski <bugalski.piotr@gmail.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.
- *
- * 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 driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale.
*/
-#include <linux/kernel.h>
#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
-#include <linux/of.h>
-
#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/spi/spi-mem.h>
/* QSPI register offsets */
@@ -47,7 +36,9 @@
#define QSPI_IAR 0x0030 /* Instruction Address Register */
#define QSPI_ICR 0x0034 /* Instruction Code Register */
+#define QSPI_WICR 0x0034 /* Write Instruction Code Register */
#define QSPI_IFR 0x0038 /* Instruction Frame Register */
+#define QSPI_RICR 0x003C /* Read Instruction Code Register */
#define QSPI_SMR 0x0040 /* Scrambling Mode Register */
#define QSPI_SKR 0x0044 /* Scrambling Key Register */
@@ -100,7 +91,7 @@
#define QSPI_SCR_DLYBS_MASK GENMASK(23, 16)
#define QSPI_SCR_DLYBS(n) (((n) << 16) & QSPI_SCR_DLYBS_MASK)
-/* Bitfields in QSPI_ICR (Instruction Code Register) */
+/* Bitfields in QSPI_ICR (Read/Write Instruction Code Register) */
#define QSPI_ICR_INST_MASK GENMASK(7, 0)
#define QSPI_ICR_INST(inst) (((inst) << 0) & QSPI_ICR_INST_MASK)
#define QSPI_ICR_OPT_MASK GENMASK(23, 16)
@@ -125,14 +116,12 @@
#define QSPI_IFR_OPTL_4BIT (2 << 8)
#define QSPI_IFR_OPTL_8BIT (3 << 8)
#define QSPI_IFR_ADDRL BIT(10)
-#define QSPI_IFR_TFRTYP_MASK GENMASK(13, 12)
-#define QSPI_IFR_TFRTYP_TRSFR_READ (0 << 12)
-#define QSPI_IFR_TFRTYP_TRSFR_READ_MEM (1 << 12)
-#define QSPI_IFR_TFRTYP_TRSFR_WRITE (2 << 12)
-#define QSPI_IFR_TFRTYP_TRSFR_WRITE_MEM (3 << 13)
+#define QSPI_IFR_TFRTYP_MEM BIT(12)
+#define QSPI_IFR_SAMA5D2_WRITE_TRSFR BIT(13)
#define QSPI_IFR_CRM BIT(14)
#define QSPI_IFR_NBDUM_MASK GENMASK(20, 16)
#define QSPI_IFR_NBDUM(n) (((n) << 16) & QSPI_IFR_NBDUM_MASK)
+#define QSPI_IFR_APBTFRTYP_READ BIT(24) /* Defined in SAM9X60 */
/* Bitfields in QSPI_SMR (Scrambling Mode Register) */
#define QSPI_SMR_SCREN BIT(0)
@@ -148,24 +137,31 @@
#define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8)
#define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC)
+struct atmel_qspi_caps {
+ bool has_qspick;
+ bool has_ricr;
+};
struct atmel_qspi {
void __iomem *regs;
void __iomem *mem;
- struct clk *clk;
+ struct clk *pclk;
+ struct clk *qspick;
struct platform_device *pdev;
+ const struct atmel_qspi_caps *caps;
u32 pending;
+ u32 mr;
struct completion cmd_completion;
};
-struct qspi_mode {
+struct atmel_qspi_mode {
u8 cmd_buswidth;
u8 addr_buswidth;
u8 data_buswidth;
u32 config;
};
-static const struct qspi_mode sama5d2_qspi_modes[] = {
+static const struct atmel_qspi_mode atmel_qspi_modes[] = {
{ 1, 1, 1, QSPI_IFR_WIDTH_SINGLE_BIT_SPI },
{ 1, 1, 2, QSPI_IFR_WIDTH_DUAL_OUTPUT },
{ 1, 1, 4, QSPI_IFR_WIDTH_QUAD_OUTPUT },
@@ -175,19 +171,8 @@ static const struct qspi_mode sama5d2_qspi_modes[] = {
{ 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD },
};
-/* Register access functions */
-static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg)
-{
- return readl_relaxed(aq->regs + reg);
-}
-
-static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value)
-{
- writel_relaxed(value, aq->regs + reg);
-}
-
-static inline bool is_compatible(const struct spi_mem_op *op,
- const struct qspi_mode *mode)
+static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op,
+ const struct atmel_qspi_mode *mode)
{
if (op->cmd.buswidth != mode->cmd_buswidth)
return false;
@@ -201,21 +186,21 @@ static inline bool is_compatible(const struct spi_mem_op *op,
return true;
}
-static int find_mode(const struct spi_mem_op *op)
+static int atmel_qspi_find_mode(const struct spi_mem_op *op)
{
u32 i;
- for (i = 0; i < ARRAY_SIZE(sama5d2_qspi_modes); i++)
- if (is_compatible(op, &sama5d2_qspi_modes[i]))
+ for (i = 0; i < ARRAY_SIZE(atmel_qspi_modes); i++)
+ if (atmel_qspi_is_compatible(op, &atmel_qspi_modes[i]))
return i;
- return -1;
+ return -ENOTSUPP;
}
static bool atmel_qspi_supports_op(struct spi_mem *mem,
const struct spi_mem_op *op)
{
- if (find_mode(op) < 0)
+ if (atmel_qspi_find_mode(op) < 0)
return false;
/* special case not supported by hardware */
@@ -226,29 +211,37 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
return true;
}
-static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
+ const struct spi_mem_op *op, u32 *offset)
{
- struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master);
- int mode;
+ u32 iar, icr, ifr;
u32 dummy_cycles = 0;
- u32 iar, icr, ifr, sr;
- int err = 0;
+ int mode;
iar = 0;
icr = QSPI_ICR_INST(op->cmd.opcode);
ifr = QSPI_IFR_INSTEN;
- qspi_writel(aq, QSPI_MR, QSPI_MR_SMM);
-
- mode = find_mode(op);
+ mode = atmel_qspi_find_mode(op);
if (mode < 0)
- return -ENOTSUPP;
-
- ifr |= sama5d2_qspi_modes[mode].config;
+ return mode;
+ ifr |= atmel_qspi_modes[mode].config;
if (op->dummy.buswidth && op->dummy.nbytes)
dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
+ /*
+ * The controller allows 24 and 32-bit addressing while NAND-flash
+ * requires 16-bit long. Handling 8-bit long addresses is done using
+ * the option field. For the 16-bit addresses, the workaround depends
+ * of the number of requested dummy bits. If there are 8 or more dummy
+ * cycles, the address is shifted and sent with the first dummy byte.
+ * Otherwise opcode is disabled and the first byte of the address
+ * contains the command opcode (works only if the opcode and address
+ * use the same buswidth). The limitation is when the 16-bit address is
+ * used without enough dummy cycles and the opcode is using a different
+ * buswidth than the address.
+ */
if (op->addr.buswidth) {
switch (op->addr.nbytes) {
case 0:
@@ -282,6 +275,9 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
}
}
+ /* offset of the data access in the QSPI memory space */
+ *offset = iar;
+
/* Set number of dummy cycles */
if (dummy_cycles)
ifr |= QSPI_IFR_NBDUM(dummy_cycles);
@@ -290,49 +286,82 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
if (op->data.nbytes)
ifr |= QSPI_IFR_DATAEN;
- if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes)
- ifr |= QSPI_IFR_TFRTYP_TRSFR_READ;
- else
- ifr |= QSPI_IFR_TFRTYP_TRSFR_WRITE;
+ /*
+ * If the QSPI controller is set in regular SPI mode, set it in
+ * Serial Memory Mode (SMM).
+ */
+ if (aq->mr != QSPI_MR_SMM) {
+ writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
+ aq->mr = QSPI_MR_SMM;
+ }
/* Clear pending interrupts */
- (void)qspi_readl(aq, QSPI_SR);
+ (void)readl_relaxed(aq->regs + QSPI_SR);
+
+ if (aq->caps->has_ricr) {
+ if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN)
+ ifr |= QSPI_IFR_APBTFRTYP_READ;
- /* Set QSPI Instruction Frame registers */
- qspi_writel(aq, QSPI_IAR, iar);
- qspi_writel(aq, QSPI_ICR, icr);
- qspi_writel(aq, QSPI_IFR, ifr);
+ /* Set QSPI Instruction Frame registers */
+ writel_relaxed(iar, aq->regs + QSPI_IAR);
+ if (op->data.dir == SPI_MEM_DATA_IN)
+ writel_relaxed(icr, aq->regs + QSPI_RICR);
+ else
+ writel_relaxed(icr, aq->regs + QSPI_WICR);
+ writel_relaxed(ifr, aq->regs + QSPI_IFR);
+ } else {
+ if (op->data.dir == SPI_MEM_DATA_OUT)
+ ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR;
+
+ /* Set QSPI Instruction Frame registers */
+ writel_relaxed(iar, aq->regs + QSPI_IAR);
+ writel_relaxed(icr, aq->regs + QSPI_ICR);
+ writel_relaxed(ifr, aq->regs + QSPI_IFR);
+ }
+
+ return 0;
+}
+
+static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master);
+ u32 sr, offset;
+ int err;
+
+ err = atmel_qspi_set_cfg(aq, op, &offset);
+ if (err)
+ return err;
/* Skip to the final steps if there is no data */
if (op->data.nbytes) {
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
- (void)qspi_readl(aq, QSPI_IFR);
+ (void)readl_relaxed(aq->regs + QSPI_IFR);
/* Send/Receive data */
if (op->data.dir == SPI_MEM_DATA_IN)
- _memcpy_fromio(op->data.buf.in,
- aq->mem + iar, op->data.nbytes);
+ _memcpy_fromio(op->data.buf.in, aq->mem + offset,
+ op->data.nbytes);
else
- _memcpy_toio(aq->mem + iar,
- op->data.buf.out, op->data.nbytes);
+ _memcpy_toio(aq->mem + offset, op->data.buf.out,
+ op->data.nbytes);
/* Release the chip-select */
- qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER);
+ writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR);
}
/* Poll INSTRuction End status */
- sr = qspi_readl(aq, QSPI_SR);
+ sr = readl_relaxed(aq->regs + QSPI_SR);
if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
return err;
/* Wait for INSTRuction End interrupt */
reinit_completion(&aq->cmd_completion);
aq->pending = sr & QSPI_SR_CMD_COMPLETED;
- qspi_writel(aq, QSPI_IER, QSPI_SR_CMD_COMPLETED);
+ writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER);
if (!wait_for_completion_timeout(&aq->cmd_completion,
msecs_to_jiffies(1000)))
err = -ETIMEDOUT;
- qspi_writel(aq, QSPI_IDR, QSPI_SR_CMD_COMPLETED);
+ writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR);
return err;
}
@@ -361,7 +390,7 @@ static int atmel_qspi_setup(struct spi_device *spi)
if (!spi->max_speed_hz)
return -EINVAL;
- src_rate = clk_get_rate(aq->clk);
+ src_rate = clk_get_rate(aq->pclk);
if (!src_rate)
return -EINVAL;
@@ -371,7 +400,7 @@ static int atmel_qspi_setup(struct spi_device *spi)
scbr--;
scr = QSPI_SCR_SCBR(scbr);
- qspi_writel(aq, QSPI_SCR, scr);
+ writel_relaxed(scr, aq->regs + QSPI_SCR);
return 0;
}
@@ -379,21 +408,25 @@ static int atmel_qspi_setup(struct spi_device *spi)
static int atmel_qspi_init(struct atmel_qspi *aq)
{
/* Reset the QSPI controller */
- qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST);
+ writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR);
+
+ /* Set the QSPI controller by default in Serial Memory Mode */
+ writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
+ aq->mr = QSPI_MR_SMM;
/* Enable the QSPI controller */
- qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIEN);
+ writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR);
return 0;
}
static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
{
- struct atmel_qspi *aq = (struct atmel_qspi *)dev_id;
+ struct atmel_qspi *aq = dev_id;
u32 status, mask, pending;
- status = qspi_readl(aq, QSPI_SR);
- mask = qspi_readl(aq, QSPI_IMR);
+ status = readl_relaxed(aq->regs + QSPI_SR);
+ mask = readl_relaxed(aq->regs + QSPI_IMR);
pending = status & mask;
if (!pending)
@@ -449,44 +482,74 @@ static int atmel_qspi_probe(struct platform_device *pdev)
}
/* Get the peripheral clock */
- aq->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(aq->clk)) {
+ aq->pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(aq->pclk))
+ aq->pclk = devm_clk_get(&pdev->dev, NULL);
+
+ if (IS_ERR(aq->pclk)) {
dev_err(&pdev->dev, "missing peripheral clock\n");
- err = PTR_ERR(aq->clk);
+ err = PTR_ERR(aq->pclk);
goto exit;
}
/* Enable the peripheral clock */
- err = clk_prepare_enable(aq->clk);
+ err = clk_prepare_enable(aq->pclk);
if (err) {
dev_err(&pdev->dev, "failed to enable the peripheral clock\n");
goto exit;
}
+ aq->caps = of_device_get_match_data(&pdev->dev);
+ if (!aq->caps) {
+ dev_err(&pdev->dev, "Could not retrieve QSPI caps\n");
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (aq->caps->has_qspick) {
+ /* Get the QSPI system clock */
+ aq->qspick = devm_clk_get(&pdev->dev, "qspick");
+ if (IS_ERR(aq->qspick)) {
+ dev_err(&pdev->dev, "missing system clock\n");
+ err = PTR_ERR(aq->qspick);
+ goto disable_pclk;
+ }
+
+ /* Enable the QSPI system clock */
+ err = clk_prepare_enable(aq->qspick);
+ if (err) {
+ dev_err(&pdev->dev,
+ "failed to enable the QSPI system clock\n");
+ goto disable_pclk;
+ }
+ }
+
/* Request the IRQ */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "missing IRQ\n");
err = irq;
- goto disable_clk;
+ goto disable_qspick;
}
err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt,
0, dev_name(&pdev->dev), aq);
if (err)
- goto disable_clk;
+ goto disable_qspick;
err = atmel_qspi_init(aq);
if (err)
- goto disable_clk;
+ goto disable_qspick;
err = spi_register_controller(ctrl);
if (err)
- goto disable_clk;
+ goto disable_qspick;
return 0;
-disable_clk:
- clk_disable_unprepare(aq->clk);
+disable_qspick:
+ clk_disable_unprepare(aq->qspick);
+disable_pclk:
+ clk_disable_unprepare(aq->pclk);
exit:
spi_controller_put(ctrl);
@@ -499,8 +562,9 @@ static int atmel_qspi_remove(struct platform_device *pdev)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
spi_unregister_controller(ctrl);
- qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIDIS);
- clk_disable_unprepare(aq->clk);
+ writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR);
+ clk_disable_unprepare(aq->qspick);
+ clk_disable_unprepare(aq->pclk);
return 0;
}
@@ -508,7 +572,8 @@ static int __maybe_unused atmel_qspi_suspend(struct device *dev)
{
struct atmel_qspi *aq = dev_get_drvdata(dev);
- clk_disable_unprepare(aq->clk);
+ clk_disable_unprepare(aq->qspick);
+ clk_disable_unprepare(aq->pclk);
return 0;
}
@@ -517,7 +582,8 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
{
struct atmel_qspi *aq = dev_get_drvdata(dev);
- clk_prepare_enable(aq->clk);
+ clk_prepare_enable(aq->pclk);
+ clk_prepare_enable(aq->qspick);
return atmel_qspi_init(aq);
}
@@ -525,8 +591,22 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(atmel_qspi_pm_ops, atmel_qspi_suspend,
atmel_qspi_resume);
+static const struct atmel_qspi_caps atmel_sama5d2_qspi_caps = {};
+
+static const struct atmel_qspi_caps atmel_sam9x60_qspi_caps = {
+ .has_qspick = true,
+ .has_ricr = true,
+};
+
static const struct of_device_id atmel_qspi_dt_ids[] = {
- { .compatible = "atmel,sama5d2-qspi" },
+ {
+ .compatible = "atmel,sama5d2-qspi",
+ .data = &atmel_sama5d2_qspi_caps,
+ },
+ {
+ .compatible = "microchip,sam9x60-qspi",
+ .data = &atmel_sam9x60_qspi_caps,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 3f6b657394de..847f354ebef1 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -21,18 +21,26 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/bitops.h>
-#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/err.h>
-
-#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ath79_spi_platform.h>
+#include <linux/platform_data/spi-ath79.h>
#define DRV_NAME "ath79-spi"
#define ATH79_SPI_RRW_DELAY_FACTOR 12000
#define MHZ (1000 * 1000)
+#define AR71XX_SPI_REG_FS 0x00 /* Function Select */
+#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */
+#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */
+#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */
+
+#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */
+
+#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */
+#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */
+#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n))
+
struct ath79_spi {
struct spi_bitbang bitbang;
u32 ioc_base;
@@ -67,31 +75,14 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
+ u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
- if (is_active) {
- /* set initial clock polarity */
- if (spi->mode & SPI_CPOL)
- sp->ioc_base |= AR71XX_SPI_IOC_CLK;
- else
- sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
-
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
-
- if (gpio_is_valid(spi->cs_gpio)) {
- /* SPI is normally active-low */
- gpio_set_value_cansleep(spi->cs_gpio, cs_high);
- } else {
- u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
-
- if (cs_high)
- sp->ioc_base |= cs_bit;
- else
- sp->ioc_base &= ~cs_bit;
-
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
+ if (cs_high)
+ sp->ioc_base |= cs_bit;
+ else
+ sp->ioc_base &= ~cs_bit;
+ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
}
static void ath79_spi_enable(struct ath79_spi *sp)
@@ -103,6 +94,9 @@ static void ath79_spi_enable(struct ath79_spi *sp)
sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
+ /* clear clk and mosi in the base state */
+ sp->ioc_base &= ~(AR71XX_SPI_IOC_DO | AR71XX_SPI_IOC_CLK);
+
/* TODO: setup speed? */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
}
@@ -115,66 +109,6 @@ static void ath79_spi_disable(struct ath79_spi *sp)
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
}
-static int ath79_spi_setup_cs(struct spi_device *spi)
-{
- struct ath79_spi *sp = ath79_spidev_to_sp(spi);
- int status;
-
- status = 0;
- if (gpio_is_valid(spi->cs_gpio)) {
- unsigned long flags;
-
- flags = GPIOF_DIR_OUT;
- if (spi->mode & SPI_CS_HIGH)
- flags |= GPIOF_INIT_LOW;
- else
- flags |= GPIOF_INIT_HIGH;
-
- status = gpio_request_one(spi->cs_gpio, flags,
- dev_name(&spi->dev));
- } else {
- u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
-
- if (spi->mode & SPI_CS_HIGH)
- sp->ioc_base &= ~cs_bit;
- else
- sp->ioc_base |= cs_bit;
-
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
-
- return status;
-}
-
-static void ath79_spi_cleanup_cs(struct spi_device *spi)
-{
- if (gpio_is_valid(spi->cs_gpio))
- gpio_free(spi->cs_gpio);
-}
-
-static int ath79_spi_setup(struct spi_device *spi)
-{
- int status = 0;
-
- if (!spi->controller_state) {
- status = ath79_spi_setup_cs(spi);
- if (status)
- return status;
- }
-
- status = spi_bitbang_setup(spi);
- if (status && !spi->controller_state)
- ath79_spi_cleanup_cs(spi);
-
- return status;
-}
-
-static void ath79_spi_cleanup(struct spi_device *spi)
-{
- ath79_spi_cleanup_cs(spi);
- spi_bitbang_cleanup(spi);
-}
-
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
u32 word, u8 bits, unsigned flags)
{
@@ -225,9 +159,10 @@ static int ath79_spi_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev);
+ master->use_gpio_descriptors = true;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
- master->setup = ath79_spi_setup;
- master->cleanup = ath79_spi_cleanup;
+ master->setup = spi_bitbang_setup;
+ master->cleanup = spi_bitbang_cleanup;
if (pdata) {
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
@@ -236,7 +171,6 @@ static int ath79_spi_probe(struct platform_device *pdev)
sp->bitbang.master = master;
sp->bitbang.chipselect = ath79_spi_chipselect;
sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
- sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
sp->bitbang.flags = SPI_CS_HIGH;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 74fddcd3282b..4954f0ab1606 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -23,8 +23,7 @@
#include <linux/of.h>
#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
@@ -312,7 +311,7 @@ struct atmel_spi {
/* Controller-specific per-slave state */
struct atmel_spi_device {
- unsigned int npcs_pin;
+ struct gpio_desc *npcs_pin;
u32 csr;
};
@@ -355,7 +354,6 @@ static bool atmel_spi_is_v2(struct atmel_spi *as)
static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{
struct atmel_spi_device *asd = spi->controller_state;
- unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr;
if (atmel_spi_is_v2(as)) {
@@ -379,7 +377,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
mr = spi_readl(as, MR);
if (as->use_cs_gpios)
- gpio_set_value(asd->npcs_pin, active);
+ gpiod_set_value(asd->npcs_pin, 1);
} else {
u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
int i;
@@ -396,19 +394,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
mr = spi_readl(as, MR);
mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
if (as->use_cs_gpios && spi->chip_select != 0)
- gpio_set_value(asd->npcs_pin, active);
+ gpiod_set_value(asd->npcs_pin, 1);
spi_writel(as, MR, mr);
}
- dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
- asd->npcs_pin, active ? " (high)" : "",
- mr);
+ dev_dbg(&spi->dev, "activate NPCS, mr %08x\n", mr);
}
static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{
struct atmel_spi_device *asd = spi->controller_state;
- unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr;
/* only deactivate *this* device; sometimes transfers to
@@ -420,14 +415,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
spi_writel(as, MR, mr);
}
- dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
- asd->npcs_pin, active ? " (low)" : "",
- mr);
+ dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr);
if (!as->use_cs_gpios)
spi_writel(as, CR, SPI_BIT(LASTXFER));
else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
- gpio_set_value(asd->npcs_pin, !active);
+ gpiod_set_value(asd->npcs_pin, 0);
}
static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
@@ -1188,7 +1181,6 @@ static int atmel_spi_setup(struct spi_device *spi)
struct atmel_spi_device *asd;
u32 csr;
unsigned int bits = spi->bits_per_word;
- unsigned int npcs_pin;
as = spi_master_get_devdata(spi->master);
@@ -1209,21 +1201,14 @@ static int atmel_spi_setup(struct spi_device *spi)
csr |= SPI_BIT(CSAAT);
/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
- *
- * DLYBCT would add delays between words, slowing down transfers.
- * It could potentially be useful to cope with DMA bottlenecks, but
- * in those cases it's probably best to just use a lower bitrate.
*/
csr |= SPI_BF(DLYBS, 0);
- csr |= SPI_BF(DLYBCT, 0);
-
- /* chipselect must have been muxed as GPIO (e.g. in board setup) */
- npcs_pin = (unsigned long)spi->controller_data;
- if (!as->use_cs_gpios)
- npcs_pin = spi->chip_select;
- else if (gpio_is_valid(spi->cs_gpio))
- npcs_pin = spi->cs_gpio;
+ /* DLYBCT adds delays between words. This is useful for slow devices
+ * that need a bit of time to setup the next transfer.
+ */
+ csr |= SPI_BF(DLYBCT,
+ (as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5);
asd = spi->controller_state;
if (!asd) {
@@ -1231,11 +1216,21 @@ static int atmel_spi_setup(struct spi_device *spi)
if (!asd)
return -ENOMEM;
- if (as->use_cs_gpios)
- gpio_direction_output(npcs_pin,
- !(spi->mode & SPI_CS_HIGH));
+ /*
+ * If use_cs_gpios is true this means that we have "cs-gpios"
+ * defined in the device tree node so we should have
+ * gotten the GPIO lines from the device tree inside the
+ * SPI core. Warn if this is not the case but continue since
+ * CS GPIOs are after all optional.
+ */
+ if (as->use_cs_gpios) {
+ if (!spi->cs_gpiod) {
+ dev_err(&spi->dev,
+ "host claims to use CS GPIOs but no CS found in DT by the SPI core\n");
+ }
+ asd->npcs_pin = spi->cs_gpiod;
+ }
- asd->npcs_pin = npcs_pin;
spi->controller_state = asd;
}
@@ -1473,41 +1468,6 @@ static void atmel_get_caps(struct atmel_spi *as)
as->caps.has_pdc_support = version < 0x212;
}
-/*-------------------------------------------------------------------------*/
-static int atmel_spi_gpio_cs(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct atmel_spi *as = spi_master_get_devdata(master);
- struct device_node *np = master->dev.of_node;
- int i;
- int ret = 0;
- int nb = 0;
-
- if (!as->use_cs_gpios)
- return 0;
-
- if (!np)
- return 0;
-
- nb = of_gpio_named_count(np, "cs-gpios");
- for (i = 0; i < nb; i++) {
- int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
- "cs-gpios", i);
-
- if (cs_gpio == -EPROBE_DEFER)
- return cs_gpio;
-
- if (gpio_is_valid(cs_gpio)) {
- ret = devm_gpio_request(&pdev->dev, cs_gpio,
- dev_name(&pdev->dev));
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-
static void atmel_spi_init(struct atmel_spi *as)
{
spi_writel(as, CR, SPI_BIT(SWRST));
@@ -1560,6 +1520,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
goto out_free;
/* the spi->mode bits understood by this driver: */
+ master->use_gpio_descriptors = true;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
master->dev.of_node = pdev->dev.of_node;
@@ -1592,6 +1553,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
atmel_get_caps(as);
+ /*
+ * If there are chip selects in the device tree, those will be
+ * discovered by the SPI core when registering the SPI master
+ * and assigned to each SPI device.
+ */
as->use_cs_gpios = true;
if (atmel_spi_is_v2(as) &&
pdev->dev.of_node &&
@@ -1600,10 +1566,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
master->num_chipselect = 4;
}
- ret = atmel_spi_gpio_cs(pdev);
- if (ret)
- goto out_unmap_regs;
-
as->use_dma = false;
as->use_pdc = false;
if (as->caps.has_dma_support) {
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index 671e374e1b01..f7e054848ca5 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -456,7 +456,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
}
bs->clk = devm_clk_get(&pdev->dev, NULL);
- if ((!bs->clk) || (IS_ERR(bs->clk))) {
+ if (IS_ERR(bs->clk)) {
err = PTR_ERR(bs->clk);
dev_err(&pdev->dev, "could not get clk: %d\n", err);
goto out_master_put;
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index f29176000b8d..dd9a8c54a693 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -213,19 +213,6 @@ int spi_bitbang_setup(struct spi_device *spi)
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
- /* NOTE we _need_ to call chipselect() early, ideally with adapter
- * setup, unless the hardware defaults cooperate to avoid confusion
- * between normal (active low) and inverted chipselects.
- */
-
- /* deselect chip (low or high) */
- mutex_lock(&bitbang->lock);
- if (!bitbang->busy) {
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(cs->nsecs);
- }
- mutex_unlock(&bitbang->lock);
-
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_setup);
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index 7c88f74f7f47..43d0e79842ac 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -13,7 +13,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -128,10 +128,6 @@ struct cdns_spi {
u32 is_decoded_cs;
};
-struct cdns_spi_device_data {
- bool gpio_requested;
-};
-
/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
@@ -176,16 +172,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
/**
* cdns_spi_chipselect - Select or deselect the chip select line
* @spi: Pointer to the spi_device structure
- * @is_high: Select(0) or deselect (1) the chip select line
+ * @enable: Select (1) or deselect (0) the chip select line
*/
-static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
+static void cdns_spi_chipselect(struct spi_device *spi, bool enable)
{
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
u32 ctrl_reg;
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
- if (is_high) {
+ if (!enable) {
/* Deselect the slave */
ctrl_reg |= CDNS_SPI_CR_SSCTRL;
} else {
@@ -469,64 +465,6 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master)
return 0;
}
-static int cdns_spi_setup(struct spi_device *spi)
-{
-
- int ret = -EINVAL;
- struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
-
- /* this is a pin managed by the controller, leave it alone */
- if (spi->cs_gpio == -ENOENT)
- return 0;
-
- /* this seems to be the first time we're here */
- if (!cdns_spi_data) {
- cdns_spi_data = kzalloc(sizeof(*cdns_spi_data), GFP_KERNEL);
- if (!cdns_spi_data)
- return -ENOMEM;
- cdns_spi_data->gpio_requested = false;
- spi_set_ctldata(spi, cdns_spi_data);
- }
-
- /* if we haven't done so, grab the gpio */
- if (!cdns_spi_data->gpio_requested && gpio_is_valid(spi->cs_gpio)) {
- ret = gpio_request_one(spi->cs_gpio,
- (spi->mode & SPI_CS_HIGH) ?
- GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
- dev_name(&spi->dev));
- if (ret)
- dev_err(&spi->dev, "can't request chipselect gpio %d\n",
- spi->cs_gpio);
- else
- cdns_spi_data->gpio_requested = true;
- } else {
- if (gpio_is_valid(spi->cs_gpio)) {
- int mode = ((spi->mode & SPI_CS_HIGH) ?
- GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
-
- ret = gpio_direction_output(spi->cs_gpio, mode);
- if (ret)
- dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
- spi->cs_gpio, ret);
- }
- }
-
- return ret;
-}
-
-static void cdns_spi_cleanup(struct spi_device *spi)
-{
- struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
-
- if (cdns_spi_data) {
- if (cdns_spi_data->gpio_requested)
- gpio_free(spi->cs_gpio);
- kfree(cdns_spi_data);
- spi_set_ctldata(spi, NULL);
- }
-
-}
-
/**
* cdns_spi_probe - Probe method for the SPI driver
* @pdev: Pointer to the platform_device structure
@@ -584,11 +522,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb;
}
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
@@ -603,8 +536,10 @@ static int cdns_spi_probe(struct platform_device *pdev)
/* SPI controller initializations */
cdns_spi_init_hw(xspi);
- pm_runtime_mark_last_busy(&pdev->dev);
- pm_runtime_put_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
@@ -621,13 +556,12 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_all;
}
+ master->use_gpio_descriptors = true;
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
master->prepare_message = cdns_prepare_message;
master->transfer_one = cdns_transfer_one;
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
master->set_cs = cdns_spi_chipselect;
- master->setup = cdns_spi_setup;
- master->cleanup = cdns_spi_cleanup;
master->auto_runtime_pm = true;
master->mode_bits = SPI_CPOL | SPI_CPHA;
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 18193df2eba8..8c03c409fc07 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -11,7 +11,7 @@
#include <linux/io.h>
#include <linux/clk.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
@@ -36,25 +36,6 @@ struct spi_clps711x_data {
int len;
};
-static int spi_clps711x_setup(struct spi_device *spi)
-{
- if (!spi->controller_state) {
- int ret;
-
- ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio,
- dev_name(&spi->master->dev));
- if (ret)
- return ret;
-
- spi->controller_state = spi;
- }
-
- /* We are expect that SPI-device is not selected */
- gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
-
- return 0;
-}
-
static int spi_clps711x_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
@@ -125,11 +106,11 @@ static int spi_clps711x_probe(struct platform_device *pdev)
if (!master)
return -ENOMEM;
+ master->use_gpio_descriptors = true;
master->bus_num = -1;
master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
master->dev.of_node = pdev->dev.of_node;
- master->setup = spi_clps711x_setup;
master->prepare_message = spi_clps711x_prepare_message;
master->transfer_one = spi_clps711x_transfer_one;
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 56adec83f8fc..eb246ebcfa3a 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -15,7 +15,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
@@ -25,7 +25,6 @@
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/slab.h>
@@ -222,12 +221,17 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
* Board specific chip select logic decides the polarity and cs
* line for the controller
*/
- if (spi->cs_gpio >= 0) {
+ if (spi->cs_gpiod) {
+ /*
+ * FIXME: is this code ever executed? This host does not
+ * set SPI_MASTER_GPIO_SS so this chipselect callback should
+ * not get called from the SPI core when we are using
+ * GPIOs for chip select.
+ */
if (value == BITBANG_CS_ACTIVE)
- gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH);
+ gpiod_set_value(spi->cs_gpiod, 1);
else
- gpio_set_value(spi->cs_gpio,
- !(spi->mode & SPI_CS_HIGH));
+ gpiod_set_value(spi->cs_gpiod, 0);
} else {
if (value == BITBANG_CS_ACTIVE) {
if (!(spi->mode & SPI_CS_WORD))
@@ -418,30 +422,18 @@ static int davinci_spi_of_setup(struct spi_device *spi)
*/
static int davinci_spi_setup(struct spi_device *spi)
{
- int retval = 0;
struct davinci_spi *dspi;
- struct spi_master *master = spi->master;
struct device_node *np = spi->dev.of_node;
bool internal_cs = true;
dspi = spi_master_get_devdata(spi->master);
if (!(spi->mode & SPI_NO_CS)) {
- if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
- retval = gpio_direction_output(
- spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+ if (np && spi->cs_gpiod)
internal_cs = false;
- }
-
- if (retval) {
- dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
- spi->cs_gpio, retval);
- return retval;
- }
- if (internal_cs) {
+ if (internal_cs)
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
- }
}
if (spi->mode & SPI_READY)
@@ -962,6 +954,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
if (ret)
goto free_master;
+ master->use_gpio_descriptors = true;
master->dev.of_node = pdev->dev.of_node;
master->bus_num = pdev->id;
master->num_chipselect = pdata->num_chipselect;
@@ -980,27 +973,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
if (dspi->version == SPI_VERSION_2)
dspi->bitbang.flags |= SPI_READY;
- if (pdev->dev.of_node) {
- int i;
-
- for (i = 0; i < pdata->num_chipselect; i++) {
- int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
- "cs-gpios", i);
-
- if (cs_gpio == -EPROBE_DEFER) {
- ret = cs_gpio;
- goto free_clk;
- }
-
- if (gpio_is_valid(cs_gpio)) {
- ret = devm_gpio_request(&pdev->dev, cs_gpio,
- dev_name(&pdev->dev));
- if (ret)
- goto free_clk;
- }
- }
- }
-
dspi->bitbang.txrx_bufs = davinci_spi_bufs;
ret = davinci_spi_request_dma(dspi);
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0dd7814e997..4bd59a93d988 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -18,7 +18,6 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/acpi.h>
#include <linux/property.h>
@@ -185,27 +184,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->num_cs = num_cs;
- if (pdev->dev.of_node) {
- int i;
-
- for (i = 0; i < dws->num_cs; i++) {
- int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
- "cs-gpios", i);
-
- if (cs_gpio == -EPROBE_DEFER) {
- ret = cs_gpio;
- goto out;
- }
-
- if (gpio_is_valid(cs_gpio)) {
- ret = devm_gpio_request(&pdev->dev, cs_gpio,
- dev_name(&pdev->dev));
- if (ret)
- goto out;
- }
- }
- }
-
init_func = device_get_match_data(&pdev->dev);
if (init_func) {
ret = init_func(pdev, dwsmmio);
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 2e822a56576a..ac81025f86ab 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -20,7 +20,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include <linux/gpio.h>
#include "spi-dw.h"
@@ -54,41 +53,41 @@ static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf,
if (!buf)
return 0;
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"%s registers:\n", dev_name(&dws->master->dev));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n");
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+ len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
@@ -138,11 +137,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
struct chip_data *chip = spi_get_ctldata(spi);
- /* Chip select logic is inverted from spi_set_cs() */
if (chip && chip->cs_control)
- chip->cs_control(!enable);
+ chip->cs_control(enable);
- if (!enable)
+ if (enable)
dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
else if (dws->cs_override)
dw_writel(dws, DW_SPI_SER, 0);
@@ -317,7 +315,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
/* Default SPI mode is SCPOL = 0, SCPH = 0 */
cr0 = (transfer->bits_per_word - 1)
| (chip->type << SPI_FRF_OFFSET)
- | (spi->mode << SPI_MODE_OFFSET)
+ | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) |
+ (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET))
| (chip->tmode << SPI_TMOD_OFFSET);
/*
@@ -397,7 +396,6 @@ static int dw_spi_setup(struct spi_device *spi)
{
struct dw_spi_chip *chip_info = NULL;
struct chip_data *chip;
- int ret;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
@@ -425,13 +423,6 @@ static int dw_spi_setup(struct spi_device *spi)
chip->tmode = SPI_TMOD_TR;
- if (gpio_is_valid(spi->cs_gpio)) {
- ret = gpio_direction_output(spi->cs_gpio,
- !(spi->mode & SPI_CS_HIGH));
- if (ret)
- return ret;
- }
-
return 0;
}
@@ -496,6 +487,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
goto err_free_master;
}
+ master->use_gpio_descriptors = true;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->bus_num = dws->bus_num;
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 5e10dc5c93a5..53335ccc98f6 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -67,7 +67,7 @@
#define SPI_SR 0x2c
#define SPI_SR_EOQF 0x10000000
#define SPI_SR_TCFQF 0x80000000
-#define SPI_SR_CLEAR 0xdaad0000
+#define SPI_SR_CLEAR 0x9aaf0000
#define SPI_RSER_TFFFE BIT(25)
#define SPI_RSER_TFFFD BIT(24)
@@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
{
u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
+ if (spi_controller_is_slave(dspi->master))
+ return data;
+
if (dspi->len > 0)
cmd |= SPI_PUSHR_CMD_CONT;
return cmd << 16 | data;
@@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
dma_async_issue_pending(dma->chan_rx);
dma_async_issue_pending(dma->chan_tx);
+ if (spi_controller_is_slave(dspi->master)) {
+ wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete);
+ return 0;
+ }
+
time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
DMA_COMPLETION_TIMEOUT);
if (time_left == 0) {
@@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi)
ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
- | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
- | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
- | SPI_CTAR_PCSSCK(pcssck)
- | SPI_CTAR_CSSCK(cssck)
- | SPI_CTAR_PASC(pasc)
- | SPI_CTAR_ASC(asc)
- | SPI_CTAR_PBR(pbr)
- | SPI_CTAR_BR(br);
+ | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0);
+
+ if (!spi_controller_is_slave(dspi->master)) {
+ chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode &
+ SPI_LSB_FIRST ? 1 : 0)
+ | SPI_CTAR_PCSSCK(pcssck)
+ | SPI_CTAR_CSSCK(cssck)
+ | SPI_CTAR_PASC(pasc)
+ | SPI_CTAR_ASC(asc)
+ | SPI_CTAR_PBR(pbr)
+ | SPI_CTAR_BR(br);
+ }
spi_set_ctldata(spi, chip);
@@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = {
static void dspi_init(struct fsl_dspi *dspi)
{
- regmap_write(dspi->regmap, SPI_MCR, SPI_MCR_MASTER | SPI_MCR_PCSIS |
- (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0));
+ unsigned int mcr = SPI_MCR_PCSIS |
+ (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0);
+
+ if (!spi_controller_is_slave(dspi->master))
+ mcr |= SPI_MCR_MASTER;
+
+ regmap_write(dspi->regmap, SPI_MCR, mcr);
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
if (dspi->devtype_data->xspi_mode)
regmap_write(dspi->regmap, SPI_CTARE(0),
@@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev)
}
master->bus_num = bus_num;
+ if (of_property_read_bool(np, "spi-slave"))
+ master->slave = true;
+
dspi->devtype_data = of_device_get_match_data(&pdev->dev);
if (!dspi->devtype_data) {
dev_err(&pdev->dev, "can't get devtype_data\n");
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 08dcc3c22e88..391863914043 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -48,10 +48,13 @@
#define CR_RTF BIT(8)
#define CR_RST BIT(1)
#define CR_MEN BIT(0)
+#define SR_MBF BIT(24)
#define SR_TCF BIT(10)
+#define SR_FCF BIT(9)
#define SR_RDF BIT(1)
#define SR_TDF BIT(0)
#define IER_TCIE BIT(10)
+#define IER_FCIE BIT(9)
#define IER_RDIE BIT(1)
#define IER_TDIE BIT(0)
#define CFGR1_PCSCFG BIT(27)
@@ -59,6 +62,7 @@
#define CFGR1_PCSPOL BIT(8)
#define CFGR1_NOSTALL BIT(3)
#define CFGR1_MASTER BIT(0)
+#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18))
#define RSR_RXEMPTY BIT(1)
#define TCR_CPOL BIT(31)
#define TCR_CPHA BIT(30)
@@ -161,28 +165,10 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
return 0;
}
-static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi)
-{
- u32 txcnt;
- unsigned long orig_jiffies = jiffies;
-
- do {
- txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
-
- if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
- dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n");
- return -ETIMEDOUT;
- }
- cond_resched();
-
- } while (txcnt);
-
- return 0;
-}
-
static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
{
u8 txfifo_cnt;
+ u32 temp;
txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
@@ -193,9 +179,15 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
txfifo_cnt++;
}
- if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize))
- writel(0, fsl_lpspi->base + IMX7ULP_TDR);
- else
+ if (txfifo_cnt < fsl_lpspi->txfifosize) {
+ if (!fsl_lpspi->is_slave) {
+ temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
+ temp &= ~TCR_CONTC;
+ writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
+ }
+
+ fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
+ } else
fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE);
}
@@ -276,10 +268,6 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
u32 temp;
int ret;
- temp = CR_RST;
- writel(temp, fsl_lpspi->base + IMX7ULP_CR);
- writel(0, fsl_lpspi->base + IMX7ULP_CR);
-
if (!fsl_lpspi->is_slave) {
ret = fsl_lpspi_set_bitrate(fsl_lpspi);
if (ret)
@@ -370,6 +358,24 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller)
return 0;
}
+static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi)
+{
+ u32 temp;
+
+ /* Disable all interrupt */
+ fsl_lpspi_intctrl(fsl_lpspi, 0);
+
+ /* W1C for all flags in SR */
+ temp = 0x3F << 8;
+ writel(temp, fsl_lpspi->base + IMX7ULP_SR);
+
+ /* Clear FIFO and disable module */
+ temp = CR_RRF | CR_RTF;
+ writel(temp, fsl_lpspi->base + IMX7ULP_CR);
+
+ return 0;
+}
+
static int fsl_lpspi_transfer_one(struct spi_controller *controller,
struct spi_device *spi,
struct spi_transfer *t)
@@ -391,11 +397,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
if (ret)
return ret;
- ret = fsl_lpspi_txfifo_empty(fsl_lpspi);
- if (ret)
- return ret;
-
- fsl_lpspi_read_rx_fifo(fsl_lpspi);
+ fsl_lpspi_reset(fsl_lpspi);
return 0;
}
@@ -408,7 +410,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
struct spi_device *spi = msg->spi;
struct spi_transfer *xfer;
bool is_first_xfer = true;
- u32 temp;
int ret = 0;
msg->status = 0;
@@ -428,13 +429,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
}
complete:
- if (!fsl_lpspi->is_slave) {
- /* de-assert SS, then finalize current message */
- temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
- temp &= ~TCR_CONTC;
- writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
- }
-
msg->status = ret;
spi_finalize_current_message(controller);
@@ -443,20 +437,30 @@ complete:
static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
{
+ u32 temp_SR, temp_IER;
struct fsl_lpspi_data *fsl_lpspi = dev_id;
- u32 temp;
+ temp_IER = readl(fsl_lpspi->base + IMX7ULP_IER);
fsl_lpspi_intctrl(fsl_lpspi, 0);
- temp = readl(fsl_lpspi->base + IMX7ULP_SR);
+ temp_SR = readl(fsl_lpspi->base + IMX7ULP_SR);
fsl_lpspi_read_rx_fifo(fsl_lpspi);
- if (temp & SR_TDF) {
+ if ((temp_SR & SR_TDF) && (temp_IER & IER_TDIE)) {
fsl_lpspi_write_tx_fifo(fsl_lpspi);
+ return IRQ_HANDLED;
+ }
- if (!fsl_lpspi->remain)
- complete(&fsl_lpspi->xfer_done);
+ if (temp_SR & SR_MBF ||
+ readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) {
+ writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
+ fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
+ return IRQ_HANDLED;
+ }
+ if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) {
+ writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
+ complete(&fsl_lpspi->xfer_done);
return IRQ_HANDLED;
}
diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
new file mode 100644
index 000000000000..6a713f78a62e
--- /dev/null
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -0,0 +1,966 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Freescale QuadSPI driver.
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2018 Bootlin
+ * Copyright (C) 2018 exceet electronics GmbH
+ * Copyright (C) 2018 Kontron Electronics GmbH
+ *
+ * Transition to SPI MEM interface:
+ * Authors:
+ * Boris Brezillon <bbrezillon@kernel.org>
+ * Frieder Schrempf <frieder.schrempf@kontron.de>
+ * Yogesh Gaur <yogeshnarayan.gaur@nxp.com>
+ * Suresh Gupta <suresh.gupta@nxp.com>
+ *
+ * Based on the original fsl-quadspi.c spi-nor driver:
+ * Author: Freescale Semiconductor, Inc.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/sizes.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+/*
+ * The driver only uses one single LUT entry, that is updated on
+ * each call of exec_op(). Index 0 is preset at boot with a basic
+ * read operation, so let's use the last entry (15).
+ */
+#define SEQID_LUT 15
+
+/* Registers used by the driver */
+#define QUADSPI_MCR 0x00
+#define QUADSPI_MCR_RESERVED_MASK GENMASK(19, 16)
+#define QUADSPI_MCR_MDIS_MASK BIT(14)
+#define QUADSPI_MCR_CLR_TXF_MASK BIT(11)
+#define QUADSPI_MCR_CLR_RXF_MASK BIT(10)
+#define QUADSPI_MCR_DDR_EN_MASK BIT(7)
+#define QUADSPI_MCR_END_CFG_MASK GENMASK(3, 2)
+#define QUADSPI_MCR_SWRSTHD_MASK BIT(1)
+#define QUADSPI_MCR_SWRSTSD_MASK BIT(0)
+
+#define QUADSPI_IPCR 0x08
+#define QUADSPI_IPCR_SEQID(x) ((x) << 24)
+
+#define QUADSPI_BUF3CR 0x1c
+#define QUADSPI_BUF3CR_ALLMST_MASK BIT(31)
+#define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8)
+#define QUADSPI_BUF3CR_ADATSZ_MASK GENMASK(15, 8)
+
+#define QUADSPI_BFGENCR 0x20
+#define QUADSPI_BFGENCR_SEQID(x) ((x) << 12)
+
+#define QUADSPI_BUF0IND 0x30
+#define QUADSPI_BUF1IND 0x34
+#define QUADSPI_BUF2IND 0x38
+#define QUADSPI_SFAR 0x100
+
+#define QUADSPI_SMPR 0x108
+#define QUADSPI_SMPR_DDRSMP_MASK GENMASK(18, 16)
+#define QUADSPI_SMPR_FSDLY_MASK BIT(6)
+#define QUADSPI_SMPR_FSPHS_MASK BIT(5)
+#define QUADSPI_SMPR_HSENA_MASK BIT(0)
+
+#define QUADSPI_RBCT 0x110
+#define QUADSPI_RBCT_WMRK_MASK GENMASK(4, 0)
+#define QUADSPI_RBCT_RXBRD_USEIPS BIT(8)
+
+#define QUADSPI_TBDR 0x154
+
+#define QUADSPI_SR 0x15c
+#define QUADSPI_SR_IP_ACC_MASK BIT(1)
+#define QUADSPI_SR_AHB_ACC_MASK BIT(2)
+
+#define QUADSPI_FR 0x160
+#define QUADSPI_FR_TFF_MASK BIT(0)
+
+#define QUADSPI_SPTRCLR 0x16c
+#define QUADSPI_SPTRCLR_IPPTRC BIT(8)
+#define QUADSPI_SPTRCLR_BFPTRC BIT(0)
+
+#define QUADSPI_SFA1AD 0x180
+#define QUADSPI_SFA2AD 0x184
+#define QUADSPI_SFB1AD 0x188
+#define QUADSPI_SFB2AD 0x18c
+#define QUADSPI_RBDR(x) (0x200 + ((x) * 4))
+
+#define QUADSPI_LUTKEY 0x300
+#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0
+
+#define QUADSPI_LCKCR 0x304
+#define QUADSPI_LCKER_LOCK BIT(0)
+#define QUADSPI_LCKER_UNLOCK BIT(1)
+
+#define QUADSPI_RSER 0x164
+#define QUADSPI_RSER_TFIE BIT(0)
+
+#define QUADSPI_LUT_BASE 0x310
+#define QUADSPI_LUT_OFFSET (SEQID_LUT * 4 * 4)
+#define QUADSPI_LUT_REG(idx) \
+ (QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4)
+
+/* Instruction set for the LUT register */
+#define LUT_STOP 0
+#define LUT_CMD 1
+#define LUT_ADDR 2
+#define LUT_DUMMY 3
+#define LUT_MODE 4
+#define LUT_MODE2 5
+#define LUT_MODE4 6
+#define LUT_FSL_READ 7
+#define LUT_FSL_WRITE 8
+#define LUT_JMP_ON_CS 9
+#define LUT_ADDR_DDR 10
+#define LUT_MODE_DDR 11
+#define LUT_MODE2_DDR 12
+#define LUT_MODE4_DDR 13
+#define LUT_FSL_READ_DDR 14
+#define LUT_FSL_WRITE_DDR 15
+#define LUT_DATA_LEARN 16
+
+/*
+ * The PAD definitions for LUT register.
+ *
+ * The pad stands for the number of IO lines [0:3].
+ * For example, the quad read needs four IO lines,
+ * so you should use LUT_PAD(4).
+ */
+#define LUT_PAD(x) (fls(x) - 1)
+
+/*
+ * Macro for constructing the LUT entries with the following
+ * register layout:
+ *
+ * ---------------------------------------------------
+ * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
+ * ---------------------------------------------------
+ */
+#define LUT_DEF(idx, ins, pad, opr) \
+ ((((ins) << 10) | ((pad) << 8) | (opr)) << (((idx) % 2) * 16))
+
+/* Controller needs driver to swap endianness */
+#define QUADSPI_QUIRK_SWAP_ENDIAN BIT(0)
+
+/* Controller needs 4x internal clock */
+#define QUADSPI_QUIRK_4X_INT_CLK BIT(1)
+
+/*
+ * TKT253890, the controller needs the driver to fill the txfifo with
+ * 16 bytes at least to trigger a data transfer, even though the extra
+ * data won't be transferred.
+ */
+#define QUADSPI_QUIRK_TKT253890 BIT(2)
+
+/* TKT245618, the controller cannot wake up from wait mode */
+#define QUADSPI_QUIRK_TKT245618 BIT(3)
+
+/*
+ * Controller adds QSPI_AMBA_BASE (base address of the mapped memory)
+ * internally. No need to add it when setting SFXXAD and SFAR registers
+ */
+#define QUADSPI_QUIRK_BASE_INTERNAL BIT(4)
+
+struct fsl_qspi_devtype_data {
+ unsigned int rxfifo;
+ unsigned int txfifo;
+ unsigned int ahb_buf_size;
+ unsigned int quirks;
+ bool little_endian;
+};
+
+static const struct fsl_qspi_devtype_data vybrid_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_64,
+ .ahb_buf_size = SZ_1K,
+ .quirks = QUADSPI_QUIRK_SWAP_ENDIAN,
+ .little_endian = true,
+};
+
+static const struct fsl_qspi_devtype_data imx6sx_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_512,
+ .ahb_buf_size = SZ_1K,
+ .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618,
+ .little_endian = true,
+};
+
+static const struct fsl_qspi_devtype_data imx7d_data = {
+ .rxfifo = SZ_512,
+ .txfifo = SZ_512,
+ .ahb_buf_size = SZ_1K,
+ .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
+ .little_endian = true,
+};
+
+static const struct fsl_qspi_devtype_data imx6ul_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_512,
+ .ahb_buf_size = SZ_1K,
+ .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
+ .little_endian = true,
+};
+
+static const struct fsl_qspi_devtype_data ls1021a_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_64,
+ .ahb_buf_size = SZ_1K,
+ .quirks = 0,
+ .little_endian = false,
+};
+
+static const struct fsl_qspi_devtype_data ls2080a_data = {
+ .rxfifo = SZ_128,
+ .txfifo = SZ_64,
+ .ahb_buf_size = SZ_1K,
+ .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL,
+ .little_endian = true,
+};
+
+struct fsl_qspi {
+ void __iomem *iobase;
+ void __iomem *ahb_addr;
+ u32 memmap_phy;
+ struct clk *clk, *clk_en;
+ struct device *dev;
+ struct completion c;
+ const struct fsl_qspi_devtype_data *devtype_data;
+ struct mutex lock;
+ struct pm_qos_request pm_qos_req;
+ int selected;
+};
+
+static inline int needs_swap_endian(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN;
+}
+
+static inline int needs_4x_clock(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK;
+}
+
+static inline int needs_fill_txfifo(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890;
+}
+
+static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618;
+}
+
+static inline int needs_amba_base_offset(struct fsl_qspi *q)
+{
+ return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL);
+}
+
+/*
+ * An IC bug makes it necessary to rearrange the 32-bit data.
+ * Later chips, such as IMX6SLX, have fixed this bug.
+ */
+static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a)
+{
+ return needs_swap_endian(q) ? __swab32(a) : a;
+}
+
+/*
+ * R/W functions for big- or little-endian registers:
+ * The QSPI controller's endianness is independent of
+ * the CPU core's endianness. So far, although the CPU
+ * core is little-endian the QSPI controller can use
+ * big-endian or little-endian.
+ */
+static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr)
+{
+ if (q->devtype_data->little_endian)
+ iowrite32(val, addr);
+ else
+ iowrite32be(val, addr);
+}
+
+static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr)
+{
+ if (q->devtype_data->little_endian)
+ return ioread32(addr);
+
+ return ioread32be(addr);
+}
+
+static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id)
+{
+ struct fsl_qspi *q = dev_id;
+ u32 reg;
+
+ /* clear interrupt */
+ reg = qspi_readl(q, q->iobase + QUADSPI_FR);
+ qspi_writel(q, reg, q->iobase + QUADSPI_FR);
+
+ if (reg & QUADSPI_FR_TFF_MASK)
+ complete(&q->c);
+
+ dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", 0, reg);
+ return IRQ_HANDLED;
+}
+
+static int fsl_qspi_check_buswidth(struct fsl_qspi *q, u8 width)
+{
+ switch (width) {
+ case 1:
+ case 2:
+ case 4:
+ return 0;
+ }
+
+ return -ENOTSUPP;
+}
+
+static bool fsl_qspi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
+ int ret;
+
+ ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth);
+
+ if (op->addr.nbytes)
+ ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth);
+
+ if (op->dummy.nbytes)
+ ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth);
+
+ if (op->data.nbytes)
+ ret |= fsl_qspi_check_buswidth(q, op->data.buswidth);
+
+ if (ret)
+ return false;
+
+ /*
+ * The number of instructions needed for the op, needs
+ * to fit into a single LUT entry.
+ */
+ if (op->addr.nbytes +
+ (op->dummy.nbytes ? 1:0) +
+ (op->data.nbytes ? 1:0) > 6)
+ return false;
+
+ /* Max 64 dummy clock cycles supported */
+ if (op->dummy.nbytes &&
+ (op->dummy.nbytes * 8 / op->dummy.buswidth > 64))
+ return false;
+
+ /* Max data length, check controller limits and alignment */
+ if (op->data.dir == SPI_MEM_DATA_IN &&
+ (op->data.nbytes > q->devtype_data->ahb_buf_size ||
+ (op->data.nbytes > q->devtype_data->rxfifo - 4 &&
+ !IS_ALIGNED(op->data.nbytes, 8))))
+ return false;
+
+ if (op->data.dir == SPI_MEM_DATA_OUT &&
+ op->data.nbytes > q->devtype_data->txfifo)
+ return false;
+
+ return true;
+}
+
+static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = q->iobase;
+ u32 lutval[4] = {};
+ int lutidx = 1, i;
+
+ lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
+ op->cmd.opcode);
+
+ /*
+ * For some unknown reason, using LUT_ADDR doesn't work in some
+ * cases (at least with only one byte long addresses), so
+ * let's use LUT_MODE to write the address bytes one by one
+ */
+ for (i = 0; i < op->addr.nbytes; i++) {
+ u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
+
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE,
+ LUT_PAD(op->addr.buswidth),
+ addrbyte);
+ lutidx++;
+ }
+
+ if (op->dummy.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
+ LUT_PAD(op->dummy.buswidth),
+ op->dummy.nbytes * 8 /
+ op->dummy.buswidth);
+ lutidx++;
+ }
+
+ if (op->data.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx,
+ op->data.dir == SPI_MEM_DATA_IN ?
+ LUT_FSL_READ : LUT_FSL_WRITE,
+ LUT_PAD(op->data.buswidth),
+ 0);
+ lutidx++;
+ }
+
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0);
+
+ /* unlock LUT */
+ qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
+ qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
+
+ /* fill LUT */
+ for (i = 0; i < ARRAY_SIZE(lutval); i++)
+ qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i));
+
+ /* lock LUT */
+ qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
+ qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
+}
+
+static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q)
+{
+ int ret;
+
+ ret = clk_prepare_enable(q->clk_en);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(q->clk);
+ if (ret) {
+ clk_disable_unprepare(q->clk_en);
+ return ret;
+ }
+
+ if (needs_wakeup_wait_mode(q))
+ pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0);
+
+ return 0;
+}
+
+static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q)
+{
+ if (needs_wakeup_wait_mode(q))
+ pm_qos_remove_request(&q->pm_qos_req);
+
+ clk_disable_unprepare(q->clk);
+ clk_disable_unprepare(q->clk_en);
+}
+
+/*
+ * If we have changed the content of the flash by writing or erasing, or if we
+ * read from flash with a different offset into the page buffer, we need to
+ * invalidate the AHB buffer. If we do not do so, we may read out the wrong
+ * data. The spec tells us reset the AHB domain and Serial Flash domain at
+ * the same time.
+ */
+static void fsl_qspi_invalidate(struct fsl_qspi *q)
+{
+ u32 reg;
+
+ reg = qspi_readl(q, q->iobase + QUADSPI_MCR);
+ reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
+ qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
+
+ /*
+ * The minimum delay : 1 AHB + 2 SFCK clocks.
+ * Delay 1 us is enough.
+ */
+ udelay(1);
+
+ reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
+ qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
+}
+
+static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi)
+{
+ unsigned long rate = spi->max_speed_hz;
+ int ret;
+
+ if (q->selected == spi->chip_select)
+ return;
+
+ if (needs_4x_clock(q))
+ rate *= 4;
+
+ fsl_qspi_clk_disable_unprep(q);
+
+ ret = clk_set_rate(q->clk, rate);
+ if (ret)
+ return;
+
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret)
+ return;
+
+ q->selected = spi->chip_select;
+
+ fsl_qspi_invalidate(q);
+}
+
+static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
+{
+ memcpy_fromio(op->data.buf.in,
+ q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size,
+ op->data.nbytes);
+}
+
+static void fsl_qspi_fill_txfifo(struct fsl_qspi *q,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = q->iobase;
+ int i;
+ u32 val;
+
+ for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) {
+ memcpy(&val, op->data.buf.out + i, 4);
+ val = fsl_qspi_endian_xchg(q, val);
+ qspi_writel(q, val, base + QUADSPI_TBDR);
+ }
+
+ if (i < op->data.nbytes) {
+ memcpy(&val, op->data.buf.out + i, op->data.nbytes - i);
+ val = fsl_qspi_endian_xchg(q, val);
+ qspi_writel(q, val, base + QUADSPI_TBDR);
+ }
+
+ if (needs_fill_txfifo(q)) {
+ for (i = op->data.nbytes; i < 16; i += 4)
+ qspi_writel(q, 0, base + QUADSPI_TBDR);
+ }
+}
+
+static void fsl_qspi_read_rxfifo(struct fsl_qspi *q,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = q->iobase;
+ int i;
+ u8 *buf = op->data.buf.in;
+ u32 val;
+
+ for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 4); i += 4) {
+ val = qspi_readl(q, base + QUADSPI_RBDR(i / 4));
+ val = fsl_qspi_endian_xchg(q, val);
+ memcpy(buf + i, &val, 4);
+ }
+
+ if (i < op->data.nbytes) {
+ val = qspi_readl(q, base + QUADSPI_RBDR(i / 4));
+ val = fsl_qspi_endian_xchg(q, val);
+ memcpy(buf + i, &val, op->data.nbytes - i);
+ }
+}
+
+static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op)
+{
+ void __iomem *base = q->iobase;
+ int err = 0;
+
+ init_completion(&q->c);
+
+ /*
+ * Always start the sequence at the same index since we update
+ * the LUT at each exec_op() call. And also specify the DATA
+ * length, since it's has not been specified in the LUT.
+ */
+ qspi_writel(q, op->data.nbytes | QUADSPI_IPCR_SEQID(SEQID_LUT),
+ base + QUADSPI_IPCR);
+
+ /* Wait for the interrupt. */
+ if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000)))
+ err = -ETIMEDOUT;
+
+ if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN)
+ fsl_qspi_read_rxfifo(q, op);
+
+ return err;
+}
+
+static int fsl_qspi_readl_poll_tout(struct fsl_qspi *q, void __iomem *base,
+ u32 mask, u32 delay_us, u32 timeout_us)
+{
+ u32 reg;
+
+ if (!q->devtype_data->little_endian)
+ mask = (u32)cpu_to_be32(mask);
+
+ return readl_poll_timeout(base, reg, !(reg & mask), delay_us,
+ timeout_us);
+}
+
+static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
+ void __iomem *base = q->iobase;
+ u32 addr_offset = 0;
+ int err = 0;
+
+ mutex_lock(&q->lock);
+
+ /* wait for the controller being ready */
+ fsl_qspi_readl_poll_tout(q, base + QUADSPI_SR, (QUADSPI_SR_IP_ACC_MASK |
+ QUADSPI_SR_AHB_ACC_MASK), 10, 1000);
+
+ fsl_qspi_select_mem(q, mem->spi);
+
+ if (needs_amba_base_offset(q))
+ addr_offset = q->memmap_phy;
+
+ qspi_writel(q,
+ q->selected * q->devtype_data->ahb_buf_size + addr_offset,
+ base + QUADSPI_SFAR);
+
+ qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
+ QUADSPI_MCR_CLR_RXF_MASK | QUADSPI_MCR_CLR_TXF_MASK,
+ base + QUADSPI_MCR);
+
+ qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC,
+ base + QUADSPI_SPTRCLR);
+
+ fsl_qspi_prepare_lut(q, op);
+
+ /*
+ * If we have large chunks of data, we read them through the AHB bus
+ * by accessing the mapped memory. In all other cases we use
+ * IP commands to access the flash.
+ */
+ if (op->data.nbytes > (q->devtype_data->rxfifo - 4) &&
+ op->data.dir == SPI_MEM_DATA_IN) {
+ fsl_qspi_read_ahb(q, op);
+ } else {
+ qspi_writel(q, QUADSPI_RBCT_WMRK_MASK |
+ QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT);
+
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
+ fsl_qspi_fill_txfifo(q, op);
+
+ err = fsl_qspi_do_op(q, op);
+ }
+
+ /* Invalidate the data in the AHB buffer. */
+ fsl_qspi_invalidate(q);
+
+ mutex_unlock(&q->lock);
+
+ return err;
+}
+
+static int fsl_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+ struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
+
+ if (op->data.dir == SPI_MEM_DATA_OUT) {
+ if (op->data.nbytes > q->devtype_data->txfifo)
+ op->data.nbytes = q->devtype_data->txfifo;
+ } else {
+ if (op->data.nbytes > q->devtype_data->ahb_buf_size)
+ op->data.nbytes = q->devtype_data->ahb_buf_size;
+ else if (op->data.nbytes > (q->devtype_data->rxfifo - 4))
+ op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8);
+ }
+
+ return 0;
+}
+
+static int fsl_qspi_default_setup(struct fsl_qspi *q)
+{
+ void __iomem *base = q->iobase;
+ u32 reg, addr_offset = 0;
+ int ret;
+
+ /* disable and unprepare clock to avoid glitch pass to controller */
+ fsl_qspi_clk_disable_unprep(q);
+
+ /* the default frequency, we will change it later if necessary. */
+ ret = clk_set_rate(q->clk, 66000000);
+ if (ret)
+ return ret;
+
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret)
+ return ret;
+
+ /* Reset the module */
+ qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
+ base + QUADSPI_MCR);
+ udelay(1);
+
+ /* Disable the module */
+ qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
+ base + QUADSPI_MCR);
+
+ reg = qspi_readl(q, base + QUADSPI_SMPR);
+ qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK
+ | QUADSPI_SMPR_FSPHS_MASK
+ | QUADSPI_SMPR_HSENA_MASK
+ | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
+
+ /* We only use the buffer3 for AHB read */
+ qspi_writel(q, 0, base + QUADSPI_BUF0IND);
+ qspi_writel(q, 0, base + QUADSPI_BUF1IND);
+ qspi_writel(q, 0, base + QUADSPI_BUF2IND);
+
+ qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
+ q->iobase + QUADSPI_BFGENCR);
+ qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT);
+ qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
+ QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8),
+ base + QUADSPI_BUF3CR);
+
+ if (needs_amba_base_offset(q))
+ addr_offset = q->memmap_phy;
+
+ /*
+ * In HW there can be a maximum of four chips on two buses with
+ * two chip selects on each bus. We use four chip selects in SW
+ * to differentiate between the four chips.
+ * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
+ * SFB2AD accordingly.
+ */
+ qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset,
+ base + QUADSPI_SFA1AD);
+ qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset,
+ base + QUADSPI_SFA2AD);
+ qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset,
+ base + QUADSPI_SFB1AD);
+ qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset,
+ base + QUADSPI_SFB2AD);
+
+ q->selected = -1;
+
+ /* Enable the module */
+ qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
+ base + QUADSPI_MCR);
+
+ /* clear all interrupt status */
+ qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR);
+
+ /* enable the interrupt */
+ qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
+
+ return 0;
+}
+
+static const char *fsl_qspi_get_name(struct spi_mem *mem)
+{
+ struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
+ struct device *dev = &mem->spi->dev;
+ const char *name;
+
+ /*
+ * In order to keep mtdparts compatible with the old MTD driver at
+ * mtd/spi-nor/fsl-quadspi.c, we set a custom name derived from the
+ * platform_device of the controller.
+ */
+ if (of_get_available_child_count(q->dev->of_node) == 1)
+ return dev_name(q->dev);
+
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ "%s-%d", dev_name(q->dev),
+ mem->spi->chip_select);
+
+ if (!name) {
+ dev_err(dev, "failed to get memory for custom flash name\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return name;
+}
+
+static const struct spi_controller_mem_ops fsl_qspi_mem_ops = {
+ .adjust_op_size = fsl_qspi_adjust_op_size,
+ .supports_op = fsl_qspi_supports_op,
+ .exec_op = fsl_qspi_exec_op,
+ .get_name = fsl_qspi_get_name,
+};
+
+static int fsl_qspi_probe(struct platform_device *pdev)
+{
+ struct spi_controller *ctlr;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ struct fsl_qspi *q;
+ int ret;
+
+ ctlr = spi_alloc_master(&pdev->dev, sizeof(*q));
+ if (!ctlr)
+ return -ENOMEM;
+
+ ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD |
+ SPI_TX_DUAL | SPI_TX_QUAD;
+
+ q = spi_controller_get_devdata(ctlr);
+ q->dev = dev;
+ q->devtype_data = of_device_get_match_data(dev);
+ if (!q->devtype_data) {
+ ret = -ENODEV;
+ goto err_put_ctrl;
+ }
+
+ platform_set_drvdata(pdev, q);
+
+ /* find the resources */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
+ q->iobase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(q->iobase)) {
+ ret = PTR_ERR(q->iobase);
+ goto err_put_ctrl;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "QuadSPI-memory");
+ q->ahb_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(q->ahb_addr)) {
+ ret = PTR_ERR(q->ahb_addr);
+ goto err_put_ctrl;
+ }
+
+ q->memmap_phy = res->start;
+
+ /* find the clocks */
+ q->clk_en = devm_clk_get(dev, "qspi_en");
+ if (IS_ERR(q->clk_en)) {
+ ret = PTR_ERR(q->clk_en);
+ goto err_put_ctrl;
+ }
+
+ q->clk = devm_clk_get(dev, "qspi");
+ if (IS_ERR(q->clk)) {
+ ret = PTR_ERR(q->clk);
+ goto err_put_ctrl;
+ }
+
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret) {
+ dev_err(dev, "can not enable the clock\n");
+ goto err_put_ctrl;
+ }
+
+ /* find the irq */
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to get the irq: %d\n", ret);
+ goto err_disable_clk;
+ }
+
+ ret = devm_request_irq(dev, ret,
+ fsl_qspi_irq_handler, 0, pdev->name, q);
+ if (ret) {
+ dev_err(dev, "failed to request irq: %d\n", ret);
+ goto err_disable_clk;
+ }
+
+ mutex_init(&q->lock);
+
+ ctlr->bus_num = -1;
+ ctlr->num_chipselect = 4;
+ ctlr->mem_ops = &fsl_qspi_mem_ops;
+
+ fsl_qspi_default_setup(q);
+
+ ctlr->dev.of_node = np;
+
+ ret = spi_register_controller(ctlr);
+ if (ret)
+ goto err_destroy_mutex;
+
+ return 0;
+
+err_destroy_mutex:
+ mutex_destroy(&q->lock);
+
+err_disable_clk:
+ fsl_qspi_clk_disable_unprep(q);
+
+err_put_ctrl:
+ spi_controller_put(ctlr);
+
+ dev_err(dev, "Freescale QuadSPI probe failed\n");
+ return ret;
+}
+
+static int fsl_qspi_remove(struct platform_device *pdev)
+{
+ struct fsl_qspi *q = platform_get_drvdata(pdev);
+
+ /* disable the hardware */
+ qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
+ qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
+
+ fsl_qspi_clk_disable_unprep(q);
+
+ mutex_destroy(&q->lock);
+
+ return 0;
+}
+
+static int fsl_qspi_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int fsl_qspi_resume(struct device *dev)
+{
+ struct fsl_qspi *q = dev_get_drvdata(dev);
+
+ fsl_qspi_default_setup(q);
+
+ return 0;
+}
+
+static const struct of_device_id fsl_qspi_dt_ids[] = {
+ { .compatible = "fsl,vf610-qspi", .data = &vybrid_data, },
+ { .compatible = "fsl,imx6sx-qspi", .data = &imx6sx_data, },
+ { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, },
+ { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
+ { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, },
+ { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);
+
+static const struct dev_pm_ops fsl_qspi_pm_ops = {
+ .suspend = fsl_qspi_suspend,
+ .resume = fsl_qspi_resume,
+};
+
+static struct platform_driver fsl_qspi_driver = {
+ .driver = {
+ .name = "fsl-quadspi",
+ .of_match_table = fsl_qspi_dt_ids,
+ .pm = &fsl_qspi_pm_ops,
+ },
+ .probe = fsl_qspi_probe,
+ .remove = fsl_qspi_remove,
+};
+module_platform_driver(fsl_qspi_driver);
+
+MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver");
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_AUTHOR("Boris Brezillon <bbrezillon@kernel.org>");
+MODULE_AUTHOR("Frieder Schrempf <frieder.schrempf@kontron.de>");
+MODULE_AUTHOR("Yogesh Gaur <yogeshnarayan.gaur@nxp.com>");
+MODULE_AUTHOR("Suresh Gupta <suresh.gupta@nxp.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index fdb7cb88fb56..5f0b0d5bfef4 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -89,9 +89,6 @@ struct spi_geni_master {
int irq;
};
-static void handle_fifo_timeout(struct spi_master *spi,
- struct spi_message *msg);
-
static int get_spi_clk_cfg(unsigned int speed_hz,
struct spi_geni_master *mas,
unsigned int *clk_idx,
@@ -122,6 +119,32 @@ static int get_spi_clk_cfg(unsigned int speed_hz,
return ret;
}
+static void handle_fifo_timeout(struct spi_master *spi,
+ struct spi_message *msg)
+{
+ struct spi_geni_master *mas = spi_master_get_devdata(spi);
+ unsigned long time_left, flags;
+ struct geni_se *se = &mas->se;
+
+ spin_lock_irqsave(&mas->lock, flags);
+ reinit_completion(&mas->xfer_done);
+ mas->cur_mcmd = CMD_CANCEL;
+ geni_se_cancel_m_cmd(se);
+ writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
+ spin_unlock_irqrestore(&mas->lock, flags);
+ time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
+ if (time_left)
+ return;
+
+ spin_lock_irqsave(&mas->lock, flags);
+ reinit_completion(&mas->xfer_done);
+ geni_se_abort_m_cmd(se);
+ spin_unlock_irqrestore(&mas->lock, flags);
+ time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
+ if (!time_left)
+ dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
+}
+
static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
{
struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
@@ -233,7 +256,6 @@ static int spi_geni_prepare_message(struct spi_master *spi,
struct geni_se *se = &mas->se;
geni_se_select_mode(se, GENI_SE_FIFO);
- reinit_completion(&mas->xfer_done);
ret = setup_fifo_params(spi_msg->spi, spi);
if (ret)
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
@@ -357,32 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
}
-static void handle_fifo_timeout(struct spi_master *spi,
- struct spi_message *msg)
-{
- struct spi_geni_master *mas = spi_master_get_devdata(spi);
- unsigned long time_left, flags;
- struct geni_se *se = &mas->se;
-
- spin_lock_irqsave(&mas->lock, flags);
- reinit_completion(&mas->xfer_done);
- mas->cur_mcmd = CMD_CANCEL;
- geni_se_cancel_m_cmd(se);
- writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
- spin_unlock_irqrestore(&mas->lock, flags);
- time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
- if (time_left)
- return;
-
- spin_lock_irqsave(&mas->lock, flags);
- reinit_completion(&mas->xfer_done);
- geni_se_abort_m_cmd(se);
- spin_unlock_irqrestore(&mas->lock, flags);
- time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
- if (!time_left)
- dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
-}
-
static int spi_geni_transfer_one(struct spi_master *spi,
struct spi_device *slv,
struct spi_transfer *xfer)
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index a4aee26028cd..53b35c56a557 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -428,7 +428,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
return status;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
- master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL;
+ master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
+ SPI_CS_HIGH;
master->flags = master_flags;
master->bus_num = pdev->id;
/* The master needs to think there is a chipselect even if not connected */
@@ -455,7 +456,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
}
spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
- spi_gpio->bitbang.flags = SPI_CS_HIGH;
status = spi_bitbang_start(&spi_gpio->bitbang);
if (status)
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 5217a5628be2..a4d8d19ecff9 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -537,7 +537,6 @@ EXPORT_SYMBOL_GPL(spi_mem_dirmap_create);
/**
* spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor
* @desc: the direct mapping descriptor to destroy
- * @info: direct mapping information
*
* This function destroys a direct mapping descriptor previously created by
* spi_mem_dirmap_create().
@@ -548,9 +547,80 @@ void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc)
if (!desc->nodirmap && ctlr->mem_ops && ctlr->mem_ops->dirmap_destroy)
ctlr->mem_ops->dirmap_destroy(desc);
+
+ kfree(desc);
}
EXPORT_SYMBOL_GPL(spi_mem_dirmap_destroy);
+static void devm_spi_mem_dirmap_release(struct device *dev, void *res)
+{
+ struct spi_mem_dirmap_desc *desc = *(struct spi_mem_dirmap_desc **)res;
+
+ spi_mem_dirmap_destroy(desc);
+}
+
+/**
+ * devm_spi_mem_dirmap_create() - Create a direct mapping descriptor and attach
+ * it to a device
+ * @dev: device the dirmap desc will be attached to
+ * @mem: SPI mem device this direct mapping should be created for
+ * @info: direct mapping information
+ *
+ * devm_ variant of the spi_mem_dirmap_create() function. See
+ * spi_mem_dirmap_create() for more details.
+ *
+ * Return: a valid pointer in case of success, and ERR_PTR() otherwise.
+ */
+struct spi_mem_dirmap_desc *
+devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem,
+ const struct spi_mem_dirmap_info *info)
+{
+ struct spi_mem_dirmap_desc **ptr, *desc;
+
+ ptr = devres_alloc(devm_spi_mem_dirmap_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ desc = spi_mem_dirmap_create(mem, info);
+ if (IS_ERR(desc)) {
+ devres_free(ptr);
+ } else {
+ *ptr = desc;
+ devres_add(dev, ptr);
+ }
+
+ return desc;
+}
+EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_create);
+
+static int devm_spi_mem_dirmap_match(struct device *dev, void *res, void *data)
+{
+ struct spi_mem_dirmap_desc **ptr = res;
+
+ if (WARN_ON(!ptr || !*ptr))
+ return 0;
+
+ return *ptr == data;
+}
+
+/**
+ * devm_spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor attached
+ * to a device
+ * @dev: device the dirmap desc is attached to
+ * @desc: the direct mapping descriptor to destroy
+ *
+ * devm_ variant of the spi_mem_dirmap_destroy() function. See
+ * spi_mem_dirmap_destroy() for more details.
+ */
+void devm_spi_mem_dirmap_destroy(struct device *dev,
+ struct spi_mem_dirmap_desc *desc)
+{
+ devres_release(dev, devm_spi_mem_dirmap_release,
+ devm_spi_mem_dirmap_match, desc);
+}
+EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_destroy);
+
/**
* spi_mem_dirmap_dirmap_read() - Read data through a direct mapping
* @desc: direct mapping descriptor
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 6ac95a2a21ce..7bf53cfc25d6 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -39,6 +39,7 @@
#include <linux/stmp_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/mxs-spi.h>
+#include <trace/events/spi.h>
#define DRIVER_NAME "mxs-spi"
@@ -374,6 +375,8 @@ static int mxs_spi_transfer_one(struct spi_master *master,
list_for_each_entry(t, &m->transfers, transfer_list) {
+ trace_spi_transfer_start(m, t);
+
status = mxs_spi_setup_transfer(m->spi, t);
if (status)
break;
@@ -419,6 +422,8 @@ static int mxs_spi_transfer_one(struct spi_master *master,
flag);
}
+ trace_spi_transfer_stop(m, t);
+
if (status) {
stmp_reset_block(ssp->base);
break;
diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
index e1dca79b9090..734a2b956959 100644
--- a/drivers/spi/spi-npcm-pspi.c
+++ b/drivers/spi/spi-npcm-pspi.c
@@ -465,7 +465,8 @@ out_master_put:
static int npcm_pspi_remove(struct platform_device *pdev)
{
- struct npcm_pspi *priv = platform_get_drvdata(pdev);
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct npcm_pspi *priv = spi_master_get_devdata(master);
npcm_pspi_reset_hw(priv);
clk_disable_unprepare(priv->clk);
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
new file mode 100644
index 000000000000..8894f98cc99c
--- /dev/null
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -0,0 +1,1106 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * NXP FlexSPI(FSPI) controller driver.
+ *
+ * Copyright 2019 NXP.
+ *
+ * FlexSPI is a flexsible SPI host controller which supports two SPI
+ * channels and up to 4 external devices. Each channel supports
+ * Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional
+ * data lines).
+ *
+ * FlexSPI controller is driven by the LUT(Look-up Table) registers
+ * LUT registers are a look-up-table for sequences of instructions.
+ * A valid sequence consists of four LUT registers.
+ * Maximum 32 LUT sequences can be programmed simultaneously.
+ *
+ * LUTs are being created at run-time based on the commands passed
+ * from the spi-mem framework, thus using single LUT index.
+ *
+ * Software triggered Flash read/write access by IP Bus.
+ *
+ * Memory mapped read access by AHB Bus.
+ *
+ * Based on SPI MEM interface and spi-fsl-qspi.c driver.
+ *
+ * Author:
+ * Yogesh Narayan Gaur <yogeshnarayan.gaur@nxp.com>
+ * Boris Brezillon <bbrezillon@kernel.org>
+ * Frieder Schrempf <frieder.schrempf@kontron.de>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/sizes.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+/*
+ * The driver only uses one single LUT entry, that is updated on
+ * each call of exec_op(). Index 0 is preset at boot with a basic
+ * read operation, so let's use the last entry (31).
+ */
+#define SEQID_LUT 31
+
+/* Registers used by the driver */
+#define FSPI_MCR0 0x00
+#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24)
+#define FSPI_MCR0_IP_TIMEOUT(x) ((x) << 16)
+#define FSPI_MCR0_LEARN_EN BIT(15)
+#define FSPI_MCR0_SCRFRUN_EN BIT(14)
+#define FSPI_MCR0_OCTCOMB_EN BIT(13)
+#define FSPI_MCR0_DOZE_EN BIT(12)
+#define FSPI_MCR0_HSEN BIT(11)
+#define FSPI_MCR0_SERCLKDIV BIT(8)
+#define FSPI_MCR0_ATDF_EN BIT(7)
+#define FSPI_MCR0_ARDF_EN BIT(6)
+#define FSPI_MCR0_RXCLKSRC(x) ((x) << 4)
+#define FSPI_MCR0_END_CFG(x) ((x) << 2)
+#define FSPI_MCR0_MDIS BIT(1)
+#define FSPI_MCR0_SWRST BIT(0)
+
+#define FSPI_MCR1 0x04
+#define FSPI_MCR1_SEQ_TIMEOUT(x) ((x) << 16)
+#define FSPI_MCR1_AHB_TIMEOUT(x) (x)
+
+#define FSPI_MCR2 0x08
+#define FSPI_MCR2_IDLE_WAIT(x) ((x) << 24)
+#define FSPI_MCR2_SAMEDEVICEEN BIT(15)
+#define FSPI_MCR2_CLRLRPHS BIT(14)
+#define FSPI_MCR2_ABRDATSZ BIT(8)
+#define FSPI_MCR2_ABRLEARN BIT(7)
+#define FSPI_MCR2_ABR_READ BIT(6)
+#define FSPI_MCR2_ABRWRITE BIT(5)
+#define FSPI_MCR2_ABRDUMMY BIT(4)
+#define FSPI_MCR2_ABR_MODE BIT(3)
+#define FSPI_MCR2_ABRCADDR BIT(2)
+#define FSPI_MCR2_ABRRADDR BIT(1)
+#define FSPI_MCR2_ABR_CMD BIT(0)
+
+#define FSPI_AHBCR 0x0c
+#define FSPI_AHBCR_RDADDROPT BIT(6)
+#define FSPI_AHBCR_PREF_EN BIT(5)
+#define FSPI_AHBCR_BUFF_EN BIT(4)
+#define FSPI_AHBCR_CACH_EN BIT(3)
+#define FSPI_AHBCR_CLRTXBUF BIT(2)
+#define FSPI_AHBCR_CLRRXBUF BIT(1)
+#define FSPI_AHBCR_PAR_EN BIT(0)
+
+#define FSPI_INTEN 0x10
+#define FSPI_INTEN_SCLKSBWR BIT(9)
+#define FSPI_INTEN_SCLKSBRD BIT(8)
+#define FSPI_INTEN_DATALRNFL BIT(7)
+#define FSPI_INTEN_IPTXWE BIT(6)
+#define FSPI_INTEN_IPRXWA BIT(5)
+#define FSPI_INTEN_AHBCMDERR BIT(4)
+#define FSPI_INTEN_IPCMDERR BIT(3)
+#define FSPI_INTEN_AHBCMDGE BIT(2)
+#define FSPI_INTEN_IPCMDGE BIT(1)
+#define FSPI_INTEN_IPCMDDONE BIT(0)
+
+#define FSPI_INTR 0x14
+#define FSPI_INTR_SCLKSBWR BIT(9)
+#define FSPI_INTR_SCLKSBRD BIT(8)
+#define FSPI_INTR_DATALRNFL BIT(7)
+#define FSPI_INTR_IPTXWE BIT(6)
+#define FSPI_INTR_IPRXWA BIT(5)
+#define FSPI_INTR_AHBCMDERR BIT(4)
+#define FSPI_INTR_IPCMDERR BIT(3)
+#define FSPI_INTR_AHBCMDGE BIT(2)
+#define FSPI_INTR_IPCMDGE BIT(1)
+#define FSPI_INTR_IPCMDDONE BIT(0)
+
+#define FSPI_LUTKEY 0x18
+#define FSPI_LUTKEY_VALUE 0x5AF05AF0
+
+#define FSPI_LCKCR 0x1C
+
+#define FSPI_LCKER_LOCK 0x1
+#define FSPI_LCKER_UNLOCK 0x2
+
+#define FSPI_BUFXCR_INVALID_MSTRID 0xE
+#define FSPI_AHBRX_BUF0CR0 0x20
+#define FSPI_AHBRX_BUF1CR0 0x24
+#define FSPI_AHBRX_BUF2CR0 0x28
+#define FSPI_AHBRX_BUF3CR0 0x2C
+#define FSPI_AHBRX_BUF4CR0 0x30
+#define FSPI_AHBRX_BUF5CR0 0x34
+#define FSPI_AHBRX_BUF6CR0 0x38
+#define FSPI_AHBRX_BUF7CR0 0x3C
+#define FSPI_AHBRXBUF0CR7_PREF BIT(31)
+
+#define FSPI_AHBRX_BUF0CR1 0x40
+#define FSPI_AHBRX_BUF1CR1 0x44
+#define FSPI_AHBRX_BUF2CR1 0x48
+#define FSPI_AHBRX_BUF3CR1 0x4C
+#define FSPI_AHBRX_BUF4CR1 0x50
+#define FSPI_AHBRX_BUF5CR1 0x54
+#define FSPI_AHBRX_BUF6CR1 0x58
+#define FSPI_AHBRX_BUF7CR1 0x5C
+
+#define FSPI_FLSHA1CR0 0x60
+#define FSPI_FLSHA2CR0 0x64
+#define FSPI_FLSHB1CR0 0x68
+#define FSPI_FLSHB2CR0 0x6C
+#define FSPI_FLSHXCR0_SZ_KB 10
+#define FSPI_FLSHXCR0_SZ(x) ((x) >> FSPI_FLSHXCR0_SZ_KB)
+
+#define FSPI_FLSHA1CR1 0x70
+#define FSPI_FLSHA2CR1 0x74
+#define FSPI_FLSHB1CR1 0x78
+#define FSPI_FLSHB2CR1 0x7C
+#define FSPI_FLSHXCR1_CSINTR(x) ((x) << 16)
+#define FSPI_FLSHXCR1_CAS(x) ((x) << 11)
+#define FSPI_FLSHXCR1_WA BIT(10)
+#define FSPI_FLSHXCR1_TCSH(x) ((x) << 5)
+#define FSPI_FLSHXCR1_TCSS(x) (x)
+
+#define FSPI_FLSHA1CR2 0x80
+#define FSPI_FLSHA2CR2 0x84
+#define FSPI_FLSHB1CR2 0x88
+#define FSPI_FLSHB2CR2 0x8C
+#define FSPI_FLSHXCR2_CLRINSP BIT(24)
+#define FSPI_FLSHXCR2_AWRWAIT BIT(16)
+#define FSPI_FLSHXCR2_AWRSEQN_SHIFT 13
+#define FSPI_FLSHXCR2_AWRSEQI_SHIFT 8
+#define FSPI_FLSHXCR2_ARDSEQN_SHIFT 5
+#define FSPI_FLSHXCR2_ARDSEQI_SHIFT 0
+
+#define FSPI_IPCR0 0xA0
+
+#define FSPI_IPCR1 0xA4
+#define FSPI_IPCR1_IPAREN BIT(31)
+#define FSPI_IPCR1_SEQNUM_SHIFT 24
+#define FSPI_IPCR1_SEQID_SHIFT 16
+#define FSPI_IPCR1_IDATSZ(x) (x)
+
+#define FSPI_IPCMD 0xB0
+#define FSPI_IPCMD_TRG BIT(0)
+
+#define FSPI_DLPR 0xB4
+
+#define FSPI_IPRXFCR 0xB8
+#define FSPI_IPRXFCR_CLR BIT(0)
+#define FSPI_IPRXFCR_DMA_EN BIT(1)
+#define FSPI_IPRXFCR_WMRK(x) ((x) << 2)
+
+#define FSPI_IPTXFCR 0xBC
+#define FSPI_IPTXFCR_CLR BIT(0)
+#define FSPI_IPTXFCR_DMA_EN BIT(1)
+#define FSPI_IPTXFCR_WMRK(x) ((x) << 2)
+
+#define FSPI_DLLACR 0xC0
+#define FSPI_DLLACR_OVRDEN BIT(8)
+
+#define FSPI_DLLBCR 0xC4
+#define FSPI_DLLBCR_OVRDEN BIT(8)
+
+#define FSPI_STS0 0xE0
+#define FSPI_STS0_DLPHB(x) ((x) << 8)
+#define FSPI_STS0_DLPHA(x) ((x) << 4)
+#define FSPI_STS0_CMD_SRC(x) ((x) << 2)
+#define FSPI_STS0_ARB_IDLE BIT(1)
+#define FSPI_STS0_SEQ_IDLE BIT(0)
+
+#define FSPI_STS1 0xE4
+#define FSPI_STS1_IP_ERRCD(x) ((x) << 24)
+#define FSPI_STS1_IP_ERRID(x) ((x) << 16)
+#define FSPI_STS1_AHB_ERRCD(x) ((x) << 8)
+#define FSPI_STS1_AHB_ERRID(x) (x)
+
+#define FSPI_AHBSPNST 0xEC
+#define FSPI_AHBSPNST_DATLFT(x) ((x) << 16)
+#define FSPI_AHBSPNST_BUFID(x) ((x) << 1)
+#define FSPI_AHBSPNST_ACTIVE BIT(0)
+
+#define FSPI_IPRXFSTS 0xF0
+#define FSPI_IPRXFSTS_RDCNTR(x) ((x) << 16)
+#define FSPI_IPRXFSTS_FILL(x) (x)
+
+#define FSPI_IPTXFSTS 0xF4
+#define FSPI_IPTXFSTS_WRCNTR(x) ((x) << 16)
+#define FSPI_IPTXFSTS_FILL(x) (x)
+
+#define FSPI_RFDR 0x100
+#define FSPI_TFDR 0x180
+
+#define FSPI_LUT_BASE 0x200
+#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4)
+#define FSPI_LUT_REG(idx) \
+ (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4)
+
+/* register map end */
+
+/* Instruction set for the LUT register. */
+#define LUT_STOP 0x00
+#define LUT_CMD 0x01
+#define LUT_ADDR 0x02
+#define LUT_CADDR_SDR 0x03
+#define LUT_MODE 0x04
+#define LUT_MODE2 0x05
+#define LUT_MODE4 0x06
+#define LUT_MODE8 0x07
+#define LUT_NXP_WRITE 0x08
+#define LUT_NXP_READ 0x09
+#define LUT_LEARN_SDR 0x0A
+#define LUT_DATSZ_SDR 0x0B
+#define LUT_DUMMY 0x0C
+#define LUT_DUMMY_RWDS_SDR 0x0D
+#define LUT_JMP_ON_CS 0x1F
+#define LUT_CMD_DDR 0x21
+#define LUT_ADDR_DDR 0x22
+#define LUT_CADDR_DDR 0x23
+#define LUT_MODE_DDR 0x24
+#define LUT_MODE2_DDR 0x25
+#define LUT_MODE4_DDR 0x26
+#define LUT_MODE8_DDR 0x27
+#define LUT_WRITE_DDR 0x28
+#define LUT_READ_DDR 0x29
+#define LUT_LEARN_DDR 0x2A
+#define LUT_DATSZ_DDR 0x2B
+#define LUT_DUMMY_DDR 0x2C
+#define LUT_DUMMY_RWDS_DDR 0x2D
+
+/*
+ * Calculate number of required PAD bits for LUT register.
+ *
+ * The pad stands for the number of IO lines [0:7].
+ * For example, the octal read needs eight IO lines,
+ * so you should use LUT_PAD(8). This macro
+ * returns 3 i.e. use eight (2^3) IP lines for read.
+ */
+#define LUT_PAD(x) (fls(x) - 1)
+
+/*
+ * Macro for constructing the LUT entries with the following
+ * register layout:
+ *
+ * ---------------------------------------------------
+ * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
+ * ---------------------------------------------------
+ */
+#define PAD_SHIFT 8
+#define INSTR_SHIFT 10
+#define OPRND_SHIFT 16
+
+/* Macros for constructing the LUT register. */
+#define LUT_DEF(idx, ins, pad, opr) \
+ ((((ins) << INSTR_SHIFT) | ((pad) << PAD_SHIFT) | \
+ (opr)) << (((idx) % 2) * OPRND_SHIFT))
+
+#define POLL_TOUT 5000
+#define NXP_FSPI_MAX_CHIPSELECT 4
+
+struct nxp_fspi_devtype_data {
+ unsigned int rxfifo;
+ unsigned int txfifo;
+ unsigned int ahb_buf_size;
+ unsigned int quirks;
+ bool little_endian;
+};
+
+static const struct nxp_fspi_devtype_data lx2160a_data = {
+ .rxfifo = SZ_512, /* (64 * 64 bits) */
+ .txfifo = SZ_1K, /* (128 * 64 bits) */
+ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
+ .quirks = 0,
+ .little_endian = true, /* little-endian */
+};
+
+struct nxp_fspi {
+ void __iomem *iobase;
+ void __iomem *ahb_addr;
+ u32 memmap_phy;
+ u32 memmap_phy_size;
+ struct clk *clk, *clk_en;
+ struct device *dev;
+ struct completion c;
+ const struct nxp_fspi_devtype_data *devtype_data;
+ struct mutex lock;
+ struct pm_qos_request pm_qos_req;
+ int selected;
+};
+
+/*
+ * R/W functions for big- or little-endian registers:
+ * The FSPI controller's endianness is independent of
+ * the CPU core's endianness. So far, although the CPU
+ * core is little-endian the FSPI controller can use
+ * big-endian or little-endian.
+ */
+static void fspi_writel(struct nxp_fspi *f, u32 val, void __iomem *addr)
+{
+ if (f->devtype_data->little_endian)
+ iowrite32(val, addr);
+ else
+ iowrite32be(val, addr);
+}
+
+static u32 fspi_readl(struct nxp_fspi *f, void __iomem *addr)
+{
+ if (f->devtype_data->little_endian)
+ return ioread32(addr);
+ else
+ return ioread32be(addr);
+}
+
+static irqreturn_t nxp_fspi_irq_handler(int irq, void *dev_id)
+{
+ struct nxp_fspi *f = dev_id;
+ u32 reg;
+
+ /* clear interrupt */
+ reg = fspi_readl(f, f->iobase + FSPI_INTR);
+ fspi_writel(f, FSPI_INTR_IPCMDDONE, f->iobase + FSPI_INTR);
+
+ if (reg & FSPI_INTR_IPCMDDONE)
+ complete(&f->c);
+
+ return IRQ_HANDLED;
+}
+
+static int nxp_fspi_check_buswidth(struct nxp_fspi *f, u8 width)
+{
+ switch (width) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return 0;
+ }
+
+ return -ENOTSUPP;
+}
+
+static bool nxp_fspi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
+ int ret;
+
+ ret = nxp_fspi_check_buswidth(f, op->cmd.buswidth);
+
+ if (op->addr.nbytes)
+ ret |= nxp_fspi_check_buswidth(f, op->addr.buswidth);
+
+ if (op->dummy.nbytes)
+ ret |= nxp_fspi_check_buswidth(f, op->dummy.buswidth);
+
+ if (op->data.nbytes)
+ ret |= nxp_fspi_check_buswidth(f, op->data.buswidth);
+
+ if (ret)
+ return false;
+
+ /*
+ * The number of address bytes should be equal to or less than 4 bytes.
+ */
+ if (op->addr.nbytes > 4)
+ return false;
+
+ /*
+ * If requested address value is greater than controller assigned
+ * memory mapped space, return error as it didn't fit in the range
+ * of assigned address space.
+ */
+ if (op->addr.val >= f->memmap_phy_size)
+ return false;
+
+ /* Max 64 dummy clock cycles supported */
+ if (op->dummy.buswidth &&
+ (op->dummy.nbytes * 8 / op->dummy.buswidth > 64))
+ return false;
+
+ /* Max data length, check controller limits and alignment */
+ if (op->data.dir == SPI_MEM_DATA_IN &&
+ (op->data.nbytes > f->devtype_data->ahb_buf_size ||
+ (op->data.nbytes > f->devtype_data->rxfifo - 4 &&
+ !IS_ALIGNED(op->data.nbytes, 8))))
+ return false;
+
+ if (op->data.dir == SPI_MEM_DATA_OUT &&
+ op->data.nbytes > f->devtype_data->txfifo)
+ return false;
+
+ return true;
+}
+
+/* Instead of busy looping invoke readl_poll_timeout functionality. */
+static int fspi_readl_poll_tout(struct nxp_fspi *f, void __iomem *base,
+ u32 mask, u32 delay_us,
+ u32 timeout_us, bool c)
+{
+ u32 reg;
+
+ if (!f->devtype_data->little_endian)
+ mask = (u32)cpu_to_be32(mask);
+
+ if (c)
+ return readl_poll_timeout(base, reg, (reg & mask),
+ delay_us, timeout_us);
+ else
+ return readl_poll_timeout(base, reg, !(reg & mask),
+ delay_us, timeout_us);
+}
+
+/*
+ * If the slave device content being changed by Write/Erase, need to
+ * invalidate the AHB buffer. This can be achieved by doing the reset
+ * of controller after setting MCR0[SWRESET] bit.
+ */
+static inline void nxp_fspi_invalid(struct nxp_fspi *f)
+{
+ u32 reg;
+ int ret;
+
+ reg = fspi_readl(f, f->iobase + FSPI_MCR0);
+ fspi_writel(f, reg | FSPI_MCR0_SWRST, f->iobase + FSPI_MCR0);
+
+ /* w1c register, wait unit clear */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0,
+ FSPI_MCR0_SWRST, 0, POLL_TOUT, false);
+ WARN_ON(ret);
+}
+
+static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = f->iobase;
+ u32 lutval[4] = {};
+ int lutidx = 1, i;
+
+ /* cmd */
+ lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
+ op->cmd.opcode);
+
+ /* addr bytes */
+ if (op->addr.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
+ LUT_PAD(op->addr.buswidth),
+ op->addr.nbytes * 8);
+ lutidx++;
+ }
+
+ /* dummy bytes, if needed */
+ if (op->dummy.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
+ /*
+ * Due to FlexSPI controller limitation number of PAD for dummy
+ * buswidth needs to be programmed as equal to data buswidth.
+ */
+ LUT_PAD(op->data.buswidth),
+ op->dummy.nbytes * 8 /
+ op->dummy.buswidth);
+ lutidx++;
+ }
+
+ /* read/write data bytes */
+ if (op->data.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx,
+ op->data.dir == SPI_MEM_DATA_IN ?
+ LUT_NXP_READ : LUT_NXP_WRITE,
+ LUT_PAD(op->data.buswidth),
+ 0);
+ lutidx++;
+ }
+
+ /* stop condition. */
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_STOP, 0, 0);
+
+ /* unlock LUT */
+ fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY);
+ fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR);
+
+ /* fill LUT */
+ for (i = 0; i < ARRAY_SIZE(lutval); i++)
+ fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i));
+
+ dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n",
+ op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]);
+
+ /* lock LUT */
+ fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY);
+ fspi_writel(f, FSPI_LCKER_LOCK, f->iobase + FSPI_LCKCR);
+}
+
+static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f)
+{
+ int ret;
+
+ ret = clk_prepare_enable(f->clk_en);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(f->clk);
+ if (ret) {
+ clk_disable_unprepare(f->clk_en);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
+{
+ clk_disable_unprepare(f->clk);
+ clk_disable_unprepare(f->clk_en);
+}
+
+/*
+ * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
+ * register and start base address of the slave device.
+ *
+ * (Higher address)
+ * -------- <-- FLSHB2CR0
+ * | B2 |
+ * | |
+ * B2 start address --> -------- <-- FLSHB1CR0
+ * | B1 |
+ * | |
+ * B1 start address --> -------- <-- FLSHA2CR0
+ * | A2 |
+ * | |
+ * A2 start address --> -------- <-- FLSHA1CR0
+ * | A1 |
+ * | |
+ * A1 start address --> -------- (Lower address)
+ *
+ *
+ * Start base address defines the starting address range for given CS and
+ * FSPI_FLSHXXCR0 defines the size of the slave device connected at given CS.
+ *
+ * But, different targets are having different combinations of number of CS,
+ * some targets only have single CS or two CS covering controller's full
+ * memory mapped space area.
+ * Thus, implementation is being done as independent of the size and number
+ * of the connected slave device.
+ * Assign controller memory mapped space size as the size to the connected
+ * slave device.
+ * Mark FLSHxxCR0 as zero initially and then assign value only to the selected
+ * chip-select Flash configuration register.
+ *
+ * For e.g. to access CS2 (B1), FLSHB1CR0 register would be equal to the
+ * memory mapped size of the controller.
+ * Value for rest of the CS FLSHxxCR0 register would be zero.
+ *
+ */
+static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
+{
+ unsigned long rate = spi->max_speed_hz;
+ int ret;
+ uint64_t size_kb;
+
+ /*
+ * Return, if previously selected slave device is same as current
+ * requested slave device.
+ */
+ if (f->selected == spi->chip_select)
+ return;
+
+ /* Reset FLSHxxCR0 registers */
+ fspi_writel(f, 0, f->iobase + FSPI_FLSHA1CR0);
+ fspi_writel(f, 0, f->iobase + FSPI_FLSHA2CR0);
+ fspi_writel(f, 0, f->iobase + FSPI_FLSHB1CR0);
+ fspi_writel(f, 0, f->iobase + FSPI_FLSHB2CR0);
+
+ /* Assign controller memory mapped space as size, KBytes, of flash. */
+ size_kb = FSPI_FLSHXCR0_SZ(f->memmap_phy_size);
+
+ fspi_writel(f, size_kb, f->iobase + FSPI_FLSHA1CR0 +
+ 4 * spi->chip_select);
+
+ dev_dbg(f->dev, "Slave device [CS:%x] selected\n", spi->chip_select);
+
+ nxp_fspi_clk_disable_unprep(f);
+
+ ret = clk_set_rate(f->clk, rate);
+ if (ret)
+ return;
+
+ ret = nxp_fspi_clk_prep_enable(f);
+ if (ret)
+ return;
+
+ f->selected = spi->chip_select;
+}
+
+static void nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
+{
+ u32 len = op->data.nbytes;
+
+ /* Read out the data directly from the AHB buffer. */
+ memcpy_fromio(op->data.buf.in, (f->ahb_addr + op->addr.val), len);
+}
+
+static void nxp_fspi_fill_txfifo(struct nxp_fspi *f,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = f->iobase;
+ int i, ret;
+ u8 *buf = (u8 *) op->data.buf.out;
+
+ /* clear the TX FIFO. */
+ fspi_writel(f, FSPI_IPTXFCR_CLR, base + FSPI_IPTXFCR);
+
+ /*
+ * Default value of water mark level is 8 bytes, hence in single
+ * write request controller can write max 8 bytes of data.
+ */
+
+ for (i = 0; i < ALIGN_DOWN(op->data.nbytes, 8); i += 8) {
+ /* Wait for TXFIFO empty */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR,
+ FSPI_INTR_IPTXWE, 0,
+ POLL_TOUT, true);
+ WARN_ON(ret);
+
+ fspi_writel(f, *(u32 *) (buf + i), base + FSPI_TFDR);
+ fspi_writel(f, *(u32 *) (buf + i + 4), base + FSPI_TFDR + 4);
+ fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR);
+ }
+
+ if (i < op->data.nbytes) {
+ u32 data = 0;
+ int j;
+ /* Wait for TXFIFO empty */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR,
+ FSPI_INTR_IPTXWE, 0,
+ POLL_TOUT, true);
+ WARN_ON(ret);
+
+ for (j = 0; j < ALIGN(op->data.nbytes - i, 4); j += 4) {
+ memcpy(&data, buf + i + j, 4);
+ fspi_writel(f, data, base + FSPI_TFDR + j);
+ }
+ fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR);
+ }
+}
+
+static void nxp_fspi_read_rxfifo(struct nxp_fspi *f,
+ const struct spi_mem_op *op)
+{
+ void __iomem *base = f->iobase;
+ int i, ret;
+ int len = op->data.nbytes;
+ u8 *buf = (u8 *) op->data.buf.in;
+
+ /*
+ * Default value of water mark level is 8 bytes, hence in single
+ * read request controller can read max 8 bytes of data.
+ */
+ for (i = 0; i < ALIGN_DOWN(len, 8); i += 8) {
+ /* Wait for RXFIFO available */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR,
+ FSPI_INTR_IPRXWA, 0,
+ POLL_TOUT, true);
+ WARN_ON(ret);
+
+ *(u32 *)(buf + i) = fspi_readl(f, base + FSPI_RFDR);
+ *(u32 *)(buf + i + 4) = fspi_readl(f, base + FSPI_RFDR + 4);
+ /* move the FIFO pointer */
+ fspi_writel(f, FSPI_INTR_IPRXWA, base + FSPI_INTR);
+ }
+
+ if (i < len) {
+ u32 tmp;
+ int size, j;
+
+ buf = op->data.buf.in + i;
+ /* Wait for RXFIFO available */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_INTR,
+ FSPI_INTR_IPRXWA, 0,
+ POLL_TOUT, true);
+ WARN_ON(ret);
+
+ len = op->data.nbytes - i;
+ for (j = 0; j < op->data.nbytes - i; j += 4) {
+ tmp = fspi_readl(f, base + FSPI_RFDR + j);
+ size = min(len, 4);
+ memcpy(buf + j, &tmp, size);
+ len -= size;
+ }
+ }
+
+ /* invalid the RXFIFO */
+ fspi_writel(f, FSPI_IPRXFCR_CLR, base + FSPI_IPRXFCR);
+ /* move the FIFO pointer */
+ fspi_writel(f, FSPI_INTR_IPRXWA, base + FSPI_INTR);
+}
+
+static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op)
+{
+ void __iomem *base = f->iobase;
+ int seqnum = 0;
+ int err = 0;
+ u32 reg;
+
+ reg = fspi_readl(f, base + FSPI_IPRXFCR);
+ /* invalid RXFIFO first */
+ reg &= ~FSPI_IPRXFCR_DMA_EN;
+ reg = reg | FSPI_IPRXFCR_CLR;
+ fspi_writel(f, reg, base + FSPI_IPRXFCR);
+
+ init_completion(&f->c);
+
+ fspi_writel(f, op->addr.val, base + FSPI_IPCR0);
+ /*
+ * Always start the sequence at the same index since we update
+ * the LUT at each exec_op() call. And also specify the DATA
+ * length, since it's has not been specified in the LUT.
+ */
+ fspi_writel(f, op->data.nbytes |
+ (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) |
+ (seqnum << FSPI_IPCR1_SEQNUM_SHIFT),
+ base + FSPI_IPCR1);
+
+ /* Trigger the LUT now. */
+ fspi_writel(f, FSPI_IPCMD_TRG, base + FSPI_IPCMD);
+
+ /* Wait for the interrupt. */
+ if (!wait_for_completion_timeout(&f->c, msecs_to_jiffies(1000)))
+ err = -ETIMEDOUT;
+
+ /* Invoke IP data read, if request is of data read. */
+ if (!err && op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN)
+ nxp_fspi_read_rxfifo(f, op);
+
+ return err;
+}
+
+static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
+ int err = 0;
+
+ mutex_lock(&f->lock);
+
+ /* Wait for controller being ready. */
+ err = fspi_readl_poll_tout(f, f->iobase + FSPI_STS0,
+ FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true);
+ WARN_ON(err);
+
+ nxp_fspi_select_mem(f, mem->spi);
+
+ nxp_fspi_prepare_lut(f, op);
+ /*
+ * If we have large chunks of data, we read them through the AHB bus
+ * by accessing the mapped memory. In all other cases we use
+ * IP commands to access the flash.
+ */
+ if (op->data.nbytes > (f->devtype_data->rxfifo - 4) &&
+ op->data.dir == SPI_MEM_DATA_IN) {
+ nxp_fspi_read_ahb(f, op);
+ } else {
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
+ nxp_fspi_fill_txfifo(f, op);
+
+ err = nxp_fspi_do_op(f, op);
+ }
+
+ /* Invalidate the data in the AHB buffer. */
+ nxp_fspi_invalid(f);
+
+ mutex_unlock(&f->lock);
+
+ return err;
+}
+
+static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+ struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
+
+ if (op->data.dir == SPI_MEM_DATA_OUT) {
+ if (op->data.nbytes > f->devtype_data->txfifo)
+ op->data.nbytes = f->devtype_data->txfifo;
+ } else {
+ if (op->data.nbytes > f->devtype_data->ahb_buf_size)
+ op->data.nbytes = f->devtype_data->ahb_buf_size;
+ else if (op->data.nbytes > (f->devtype_data->rxfifo - 4))
+ op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8);
+ }
+
+ return 0;
+}
+
+static int nxp_fspi_default_setup(struct nxp_fspi *f)
+{
+ void __iomem *base = f->iobase;
+ int ret, i;
+ u32 reg;
+
+ /* disable and unprepare clock to avoid glitch pass to controller */
+ nxp_fspi_clk_disable_unprep(f);
+
+ /* the default frequency, we will change it later if necessary. */
+ ret = clk_set_rate(f->clk, 20000000);
+ if (ret)
+ return ret;
+
+ ret = nxp_fspi_clk_prep_enable(f);
+ if (ret)
+ return ret;
+
+ /* Reset the module */
+ /* w1c register, wait unit clear */
+ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0,
+ FSPI_MCR0_SWRST, 0, POLL_TOUT, false);
+ WARN_ON(ret);
+
+ /* Disable the module */
+ fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0);
+
+ /* Reset the DLL register to default value */
+ fspi_writel(f, FSPI_DLLACR_OVRDEN, base + FSPI_DLLACR);
+ fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR);
+
+ /* enable module */
+ fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) | FSPI_MCR0_IP_TIMEOUT(0xFF),
+ base + FSPI_MCR0);
+
+ /*
+ * Disable same device enable bit and configure all slave devices
+ * independently.
+ */
+ reg = fspi_readl(f, f->iobase + FSPI_MCR2);
+ reg = reg & ~(FSPI_MCR2_SAMEDEVICEEN);
+ fspi_writel(f, reg, base + FSPI_MCR2);
+
+ /* AHB configuration for access buffer 0~7. */
+ for (i = 0; i < 7; i++)
+ fspi_writel(f, 0, base + FSPI_AHBRX_BUF0CR0 + 4 * i);
+
+ /*
+ * Set ADATSZ with the maximum AHB buffer size to improve the read
+ * performance.
+ */
+ fspi_writel(f, (f->devtype_data->ahb_buf_size / 8 |
+ FSPI_AHBRXBUF0CR7_PREF), base + FSPI_AHBRX_BUF7CR0);
+
+ /* prefetch and no start address alignment limitation */
+ fspi_writel(f, FSPI_AHBCR_PREF_EN | FSPI_AHBCR_RDADDROPT,
+ base + FSPI_AHBCR);
+
+ /* AHB Read - Set lut sequence ID for all CS. */
+ fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2);
+ fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2);
+ fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2);
+ fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2);
+
+ f->selected = -1;
+
+ /* enable the interrupt */
+ fspi_writel(f, FSPI_INTEN_IPCMDDONE, base + FSPI_INTEN);
+
+ return 0;
+}
+
+static const char *nxp_fspi_get_name(struct spi_mem *mem)
+{
+ struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
+ struct device *dev = &mem->spi->dev;
+ const char *name;
+
+ // Set custom name derived from the platform_device of the controller.
+ if (of_get_available_child_count(f->dev->of_node) == 1)
+ return dev_name(f->dev);
+
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ "%s-%d", dev_name(f->dev),
+ mem->spi->chip_select);
+
+ if (!name) {
+ dev_err(dev, "failed to get memory for custom flash name\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return name;
+}
+
+static const struct spi_controller_mem_ops nxp_fspi_mem_ops = {
+ .adjust_op_size = nxp_fspi_adjust_op_size,
+ .supports_op = nxp_fspi_supports_op,
+ .exec_op = nxp_fspi_exec_op,
+ .get_name = nxp_fspi_get_name,
+};
+
+static int nxp_fspi_probe(struct platform_device *pdev)
+{
+ struct spi_controller *ctlr;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ struct nxp_fspi *f;
+ int ret;
+
+ ctlr = spi_alloc_master(&pdev->dev, sizeof(*f));
+ if (!ctlr)
+ return -ENOMEM;
+
+ ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL |
+ SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL;
+
+ f = spi_controller_get_devdata(ctlr);
+ f->dev = dev;
+ f->devtype_data = of_device_get_match_data(dev);
+ if (!f->devtype_data) {
+ ret = -ENODEV;
+ goto err_put_ctrl;
+ }
+
+ platform_set_drvdata(pdev, f);
+
+ /* find the resources - configuration register address space */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fspi_base");
+ f->iobase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(f->iobase)) {
+ ret = PTR_ERR(f->iobase);
+ goto err_put_ctrl;
+ }
+
+ /* find the resources - controller memory mapped space */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fspi_mmap");
+ f->ahb_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(f->ahb_addr)) {
+ ret = PTR_ERR(f->ahb_addr);
+ goto err_put_ctrl;
+ }
+
+ /* assign memory mapped starting address and mapped size. */
+ f->memmap_phy = res->start;
+ f->memmap_phy_size = resource_size(res);
+
+ /* find the clocks */
+ f->clk_en = devm_clk_get(dev, "fspi_en");
+ if (IS_ERR(f->clk_en)) {
+ ret = PTR_ERR(f->clk_en);
+ goto err_put_ctrl;
+ }
+
+ f->clk = devm_clk_get(dev, "fspi");
+ if (IS_ERR(f->clk)) {
+ ret = PTR_ERR(f->clk);
+ goto err_put_ctrl;
+ }
+
+ ret = nxp_fspi_clk_prep_enable(f);
+ if (ret) {
+ dev_err(dev, "can not enable the clock\n");
+ goto err_put_ctrl;
+ }
+
+ /* find the irq */
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to get the irq: %d\n", ret);
+ goto err_disable_clk;
+ }
+
+ ret = devm_request_irq(dev, ret,
+ nxp_fspi_irq_handler, 0, pdev->name, f);
+ if (ret) {
+ dev_err(dev, "failed to request irq: %d\n", ret);
+ goto err_disable_clk;
+ }
+
+ mutex_init(&f->lock);
+
+ ctlr->bus_num = -1;
+ ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
+ ctlr->mem_ops = &nxp_fspi_mem_ops;
+
+ nxp_fspi_default_setup(f);
+
+ ctlr->dev.of_node = np;
+
+ ret = spi_register_controller(ctlr);
+ if (ret)
+ goto err_destroy_mutex;
+
+ return 0;
+
+err_destroy_mutex:
+ mutex_destroy(&f->lock);
+
+err_disable_clk:
+ nxp_fspi_clk_disable_unprep(f);
+
+err_put_ctrl:
+ spi_controller_put(ctlr);
+
+ dev_err(dev, "NXP FSPI probe failed\n");
+ return ret;
+}
+
+static int nxp_fspi_remove(struct platform_device *pdev)
+{
+ struct nxp_fspi *f = platform_get_drvdata(pdev);
+
+ /* disable the hardware */
+ fspi_writel(f, FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
+
+ nxp_fspi_clk_disable_unprep(f);
+
+ mutex_destroy(&f->lock);
+
+ return 0;
+}
+
+static int nxp_fspi_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int nxp_fspi_resume(struct device *dev)
+{
+ struct nxp_fspi *f = dev_get_drvdata(dev);
+
+ nxp_fspi_default_setup(f);
+
+ return 0;
+}
+
+static const struct of_device_id nxp_fspi_dt_ids[] = {
+ { .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);
+
+static const struct dev_pm_ops nxp_fspi_pm_ops = {
+ .suspend = nxp_fspi_suspend,
+ .resume = nxp_fspi_resume,
+};
+
+static struct platform_driver nxp_fspi_driver = {
+ .driver = {
+ .name = "nxp-fspi",
+ .of_match_table = nxp_fspi_dt_ids,
+ .pm = &nxp_fspi_pm_ops,
+ },
+ .probe = nxp_fspi_probe,
+ .remove = nxp_fspi_remove,
+};
+module_platform_driver(nxp_fspi_driver);
+
+MODULE_DESCRIPTION("NXP FSPI Controller Driver");
+MODULE_AUTHOR("NXP Semiconductor");
+MODULE_AUTHOR("Yogesh Narayan Gaur <yogeshnarayan.gaur@nxp.com>");
+MODULE_AUTHOR("Boris Brezillon <bbrezillon@kernel.org>");
+MODULE_AUTHOR("Frieder Schrempf <frieder.schrempf@kontron.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 2fd8881fcd65..8be304379628 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -623,8 +623,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
cfg.src_addr_width = width;
cfg.dst_addr_width = width;
- cfg.src_maxburst = es;
- cfg.dst_maxburst = es;
+ cfg.src_maxburst = 1;
+ cfg.dst_maxburst = 1;
rx = xfer->rx_buf;
tx = xfer->tx_buf;
diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c
index d7e4e18ec3df..1ae9af5f17ec 100644
--- a/drivers/spi/spi-pic32-sqi.c
+++ b/drivers/spi/spi-pic32-sqi.c
@@ -466,9 +466,9 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi)
int i;
/* allocate coherent DMAable memory for hardware buffer descriptors. */
- sqi->bd = dma_zalloc_coherent(&sqi->master->dev,
- sizeof(*bd) * PESQI_BD_COUNT,
- &sqi->bd_dma, GFP_KERNEL);
+ sqi->bd = dma_alloc_coherent(&sqi->master->dev,
+ sizeof(*bd) * PESQI_BD_COUNT,
+ &sqi->bd_dma, GFP_KERNEL);
if (!sqi->bd) {
dev_err(&sqi->master->dev, "failed allocating dma buffer\n");
return -ENOMEM;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 0c793e31d60f..26684178786f 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -253,6 +253,7 @@
#define STATE_RUNNING ((void *) 1)
#define STATE_DONE ((void *) 2)
#define STATE_ERROR ((void *) -1)
+#define STATE_TIMEOUT ((void *) -2)
/*
* SSP State - Whether Enabled or Disabled
@@ -1484,6 +1485,30 @@ err_config_dma:
writew(irqflags, SSP_IMSC(pl022->virtbase));
}
+static void print_current_status(struct pl022 *pl022)
+{
+ u32 read_cr0;
+ u16 read_cr1, read_dmacr, read_sr;
+
+ if (pl022->vendor->extended_cr)
+ read_cr0 = readl(SSP_CR0(pl022->virtbase));
+ else
+ read_cr0 = readw(SSP_CR0(pl022->virtbase));
+ read_cr1 = readw(SSP_CR1(pl022->virtbase));
+ read_dmacr = readw(SSP_DMACR(pl022->virtbase));
+ read_sr = readw(SSP_SR(pl022->virtbase));
+
+ dev_warn(&pl022->adev->dev, "spi-pl022 CR0: %x\n", read_cr0);
+ dev_warn(&pl022->adev->dev, "spi-pl022 CR1: %x\n", read_cr1);
+ dev_warn(&pl022->adev->dev, "spi-pl022 DMACR: %x\n", read_dmacr);
+ dev_warn(&pl022->adev->dev, "spi-pl022 SR: %x\n", read_sr);
+ dev_warn(&pl022->adev->dev,
+ "spi-pl022 exp_fifo_level/fifodepth: %u/%d\n",
+ pl022->exp_fifo_level,
+ pl022->vendor->fifodepth);
+
+}
+
static void do_polling_transfer(struct pl022 *pl022)
{
struct spi_message *message = NULL;
@@ -1535,7 +1560,8 @@ static void do_polling_transfer(struct pl022 *pl022)
if (time_after(time, timeout)) {
dev_warn(&pl022->adev->dev,
"%s: timeout!\n", __func__);
- message->state = STATE_ERROR;
+ message->state = STATE_TIMEOUT;
+ print_current_status(pl022);
goto out;
}
cpu_relax();
@@ -1553,6 +1579,8 @@ out:
/* Handle end of message */
if (message->state == STATE_DONE)
message->status = 0;
+ else if (message->state == STATE_TIMEOUT)
+ message->status = -EAGAIN;
else
message->status = -EIO;
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index 2fa7f4b43492..15592598273e 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -23,7 +23,7 @@
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
bool error)
{
- struct spi_message *msg = drv_data->master->cur_msg;
+ struct spi_message *msg = drv_data->controller->cur_msg;
/*
* It is possible that one CPU is handling ROR interrupt and other
@@ -59,7 +59,7 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
msg->status = -EIO;
}
- spi_finalize_current_transfer(drv_data->master);
+ spi_finalize_current_transfer(drv_data->controller);
}
}
@@ -74,7 +74,7 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
struct spi_transfer *xfer)
{
struct chip_data *chip =
- spi_get_ctldata(drv_data->master->cur_msg->spi);
+ spi_get_ctldata(drv_data->controller->cur_msg->spi);
enum dma_slave_buswidth width;
struct dma_slave_config cfg;
struct dma_chan *chan;
@@ -102,14 +102,14 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
cfg.dst_maxburst = chip->dma_burst_size;
sgt = &xfer->tx_sg;
- chan = drv_data->master->dma_tx;
+ chan = drv_data->controller->dma_tx;
} else {
cfg.src_addr = drv_data->ssdr_physical;
cfg.src_addr_width = width;
cfg.src_maxburst = chip->dma_burst_size;
sgt = &xfer->rx_sg;
- chan = drv_data->master->dma_rx;
+ chan = drv_data->controller->dma_rx;
}
ret = dmaengine_slave_config(chan, &cfg);
@@ -130,8 +130,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
if (status & SSSR_ROR) {
dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
- dmaengine_terminate_async(drv_data->master->dma_rx);
- dmaengine_terminate_async(drv_data->master->dma_tx);
+ dmaengine_terminate_async(drv_data->controller->dma_rx);
+ dmaengine_terminate_async(drv_data->controller->dma_tx);
pxa2xx_spi_dma_transfer_complete(drv_data, true);
return IRQ_HANDLED;
@@ -171,15 +171,15 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data,
return 0;
err_rx:
- dmaengine_terminate_async(drv_data->master->dma_tx);
+ dmaengine_terminate_async(drv_data->controller->dma_tx);
err_tx:
return err;
}
void pxa2xx_spi_dma_start(struct driver_data *drv_data)
{
- dma_async_issue_pending(drv_data->master->dma_rx);
- dma_async_issue_pending(drv_data->master->dma_tx);
+ dma_async_issue_pending(drv_data->controller->dma_rx);
+ dma_async_issue_pending(drv_data->controller->dma_tx);
atomic_set(&drv_data->dma_running, 1);
}
@@ -187,30 +187,30 @@ void pxa2xx_spi_dma_start(struct driver_data *drv_data)
void pxa2xx_spi_dma_stop(struct driver_data *drv_data)
{
atomic_set(&drv_data->dma_running, 0);
- dmaengine_terminate_sync(drv_data->master->dma_rx);
- dmaengine_terminate_sync(drv_data->master->dma_tx);
+ dmaengine_terminate_sync(drv_data->controller->dma_rx);
+ dmaengine_terminate_sync(drv_data->controller->dma_tx);
}
int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{
- struct pxa2xx_spi_master *pdata = drv_data->master_info;
+ struct pxa2xx_spi_controller *pdata = drv_data->controller_info;
struct device *dev = &drv_data->pdev->dev;
- struct spi_controller *master = drv_data->master;
+ struct spi_controller *controller = drv_data->controller;
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- master->dma_tx = dma_request_slave_channel_compat(mask,
+ controller->dma_tx = dma_request_slave_channel_compat(mask,
pdata->dma_filter, pdata->tx_param, dev, "tx");
- if (!master->dma_tx)
+ if (!controller->dma_tx)
return -ENODEV;
- master->dma_rx = dma_request_slave_channel_compat(mask,
+ controller->dma_rx = dma_request_slave_channel_compat(mask,
pdata->dma_filter, pdata->rx_param, dev, "rx");
- if (!master->dma_rx) {
- dma_release_channel(master->dma_tx);
- master->dma_tx = NULL;
+ if (!controller->dma_rx) {
+ dma_release_channel(controller->dma_tx);
+ controller->dma_tx = NULL;
return -ENODEV;
}
@@ -219,17 +219,17 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
void pxa2xx_spi_dma_release(struct driver_data *drv_data)
{
- struct spi_controller *master = drv_data->master;
+ struct spi_controller *controller = drv_data->controller;
- if (master->dma_rx) {
- dmaengine_terminate_sync(master->dma_rx);
- dma_release_channel(master->dma_rx);
- master->dma_rx = NULL;
+ if (controller->dma_rx) {
+ dmaengine_terminate_sync(controller->dma_rx);
+ dma_release_channel(controller->dma_rx);
+ controller->dma_rx = NULL;
}
- if (master->dma_tx) {
- dmaengine_terminate_sync(master->dma_tx);
- dma_release_channel(master->dma_tx);
- master->dma_tx = NULL;
+ if (controller->dma_tx) {
+ dmaengine_terminate_sync(controller->dma_tx);
+ dma_release_channel(controller->dma_tx);
+ controller->dma_tx = NULL;
}
}
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 869f188b02eb..1727fdfbac28 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -197,7 +197,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
struct platform_device_info pi;
int ret;
struct platform_device *pdev;
- struct pxa2xx_spi_master spi_pdata;
+ struct pxa2xx_spi_controller spi_pdata;
struct ssp_device *ssp;
struct pxa_spi_info *c;
char buf[40];
@@ -265,7 +265,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{
struct platform_device *pdev = pci_get_drvdata(dev);
- struct pxa2xx_spi_master *spi_pdata;
+ struct pxa2xx_spi_controller *spi_pdata;
spi_pdata = dev_get_platdata(&pdev->dev);
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index d84b893a64d7..b6ddba833d02 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -328,7 +328,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
__lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
/* Enable multiblock DMA transfers */
- if (drv_data->master_info->enable_dma) {
+ if (drv_data->controller_info->enable_dma) {
__lpss_ssp_write_priv(drv_data, config->reg_ssp, 1);
if (config->reg_general >= 0) {
@@ -368,7 +368,7 @@ static void lpss_ssp_select_cs(struct spi_device *spi,
__lpss_ssp_write_priv(drv_data,
config->reg_cs_ctrl, value);
ndelay(1000000000 /
- (drv_data->master->max_speed_hz / 2));
+ (drv_data->controller->max_speed_hz / 2));
}
}
@@ -567,7 +567,7 @@ static int u32_reader(struct driver_data *drv_data)
static void reset_sccr1(struct driver_data *drv_data)
{
struct chip_data *chip =
- spi_get_ctldata(drv_data->master->cur_msg->spi);
+ spi_get_ctldata(drv_data->controller->cur_msg->spi);
u32 sccr1_reg;
sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1;
@@ -599,8 +599,8 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
dev_err(&drv_data->pdev->dev, "%s\n", msg);
- drv_data->master->cur_msg->status = -EIO;
- spi_finalize_current_transfer(drv_data->master);
+ drv_data->controller->cur_msg->status = -EIO;
+ spi_finalize_current_transfer(drv_data->controller);
}
static void int_transfer_complete(struct driver_data *drv_data)
@@ -611,7 +611,7 @@ static void int_transfer_complete(struct driver_data *drv_data)
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
- spi_finalize_current_transfer(drv_data->master);
+ spi_finalize_current_transfer(drv_data->controller);
}
static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
@@ -747,7 +747,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg & ~drv_data->int_cr1);
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
- if (!drv_data->master->cur_msg) {
+ if (!drv_data->controller->cur_msg) {
handle_bad_msg(drv_data);
/* Never fail */
return IRQ_HANDLED;
@@ -879,7 +879,7 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
{
- unsigned long ssp_clk = drv_data->master->max_speed_hz;
+ unsigned long ssp_clk = drv_data->controller->max_speed_hz;
const struct ssp_device *ssp = drv_data->ssp;
rate = min_t(int, ssp_clk, rate);
@@ -894,7 +894,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
int rate)
{
struct chip_data *chip =
- spi_get_ctldata(drv_data->master->cur_msg->spi);
+ spi_get_ctldata(drv_data->controller->cur_msg->spi);
unsigned int clk_div;
switch (drv_data->ssp_type) {
@@ -908,7 +908,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
return clk_div << 8;
}
-static bool pxa2xx_spi_can_dma(struct spi_controller *master,
+static bool pxa2xx_spi_can_dma(struct spi_controller *controller,
struct spi_device *spi,
struct spi_transfer *xfer)
{
@@ -919,12 +919,12 @@ static bool pxa2xx_spi_can_dma(struct spi_controller *master,
xfer->len >= chip->dma_burst_size;
}
-static int pxa2xx_spi_transfer_one(struct spi_controller *master,
+static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
struct spi_device *spi,
struct spi_transfer *transfer)
{
- struct driver_data *drv_data = spi_controller_get_devdata(master);
- struct spi_message *message = master->cur_msg;
+ struct driver_data *drv_data = spi_controller_get_devdata(controller);
+ struct spi_message *message = controller->cur_msg;
struct chip_data *chip = spi_get_ctldata(message->spi);
u32 dma_thresh = chip->dma_threshold;
u32 dma_burst = chip->dma_burst_size;
@@ -1006,9 +1006,9 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master,
"DMA burst size reduced to match bits_per_word\n");
}
- dma_mapped = master->can_dma &&
- master->can_dma(master, message->spi, transfer) &&
- master->cur_msg_mapped;
+ dma_mapped = controller->can_dma &&
+ controller->can_dma(controller, message->spi, transfer) &&
+ controller->cur_msg_mapped;
if (dma_mapped) {
/* Ensure we have the correct interrupt handler */
@@ -1036,12 +1036,12 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master,
cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
if (!pxa25x_ssp_comp(drv_data))
dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
- master->max_speed_hz
+ controller->max_speed_hz
/ (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)),
dma_mapped ? "DMA" : "PIO");
else
dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
- master->max_speed_hz / 2
+ controller->max_speed_hz / 2
/ (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)),
dma_mapped ? "DMA" : "PIO");
@@ -1092,7 +1092,7 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master,
}
}
- if (spi_controller_is_slave(master)) {
+ if (spi_controller_is_slave(controller)) {
while (drv_data->write(drv_data))
;
if (drv_data->gpiod_ready) {
@@ -1111,9 +1111,9 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *master,
return 1;
}
-static int pxa2xx_spi_slave_abort(struct spi_master *master)
+static int pxa2xx_spi_slave_abort(struct spi_controller *controller)
{
- struct driver_data *drv_data = spi_controller_get_devdata(master);
+ struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Stop and reset SSP */
write_SSSR_CS(drv_data, drv_data->clear_sr);
@@ -1126,16 +1126,16 @@ static int pxa2xx_spi_slave_abort(struct spi_master *master)
dev_dbg(&drv_data->pdev->dev, "transfer aborted\n");
- drv_data->master->cur_msg->status = -EINTR;
- spi_finalize_current_transfer(drv_data->master);
+ drv_data->controller->cur_msg->status = -EINTR;
+ spi_finalize_current_transfer(drv_data->controller);
return 0;
}
-static void pxa2xx_spi_handle_err(struct spi_controller *master,
+static void pxa2xx_spi_handle_err(struct spi_controller *controller,
struct spi_message *msg)
{
- struct driver_data *drv_data = spi_controller_get_devdata(master);
+ struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Disable the SSP */
pxa2xx_spi_write(drv_data, SSCR0,
@@ -1159,9 +1159,9 @@ static void pxa2xx_spi_handle_err(struct spi_controller *master,
pxa2xx_spi_dma_stop(drv_data);
}
-static int pxa2xx_spi_unprepare_transfer(struct spi_controller *master)
+static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller)
{
- struct driver_data *drv_data = spi_controller_get_devdata(master);
+ struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Disable the SSP now */
pxa2xx_spi_write(drv_data, SSCR0,
@@ -1260,7 +1260,7 @@ static int setup(struct spi_device *spi)
break;
default:
tx_hi_thres = 0;
- if (spi_controller_is_slave(drv_data->master)) {
+ if (spi_controller_is_slave(drv_data->controller)) {
tx_thres = 1;
rx_thres = 2;
} else {
@@ -1287,7 +1287,7 @@ static int setup(struct spi_device *spi)
chip->frm = spi->chip_select;
}
- chip->enable_dma = drv_data->master_info->enable_dma;
+ chip->enable_dma = drv_data->controller_info->enable_dma;
chip->timeout = TIMOUT_DFLT;
}
@@ -1310,7 +1310,7 @@ static int setup(struct spi_device *spi)
if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM;
}
- if (spi_controller_is_slave(drv_data->master)) {
+ if (spi_controller_is_slave(drv_data->controller)) {
chip->cr1 |= SSCR1_SCFR;
chip->cr1 |= SSCR1_SCLKDIR;
chip->cr1 |= SSCR1_SFRMDIR;
@@ -1497,10 +1497,10 @@ static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
#endif /* CONFIG_PCI */
-static struct pxa2xx_spi_master *
+static struct pxa2xx_spi_controller *
pxa2xx_spi_init_pdata(struct platform_device *pdev)
{
- struct pxa2xx_spi_master *pdata;
+ struct pxa2xx_spi_controller *pdata;
struct acpi_device *adev;
struct ssp_device *ssp;
struct resource *res;
@@ -1568,10 +1568,10 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
return pdata;
}
-static int pxa2xx_spi_fw_translate_cs(struct spi_controller *master,
+static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller,
unsigned int cs)
{
- struct driver_data *drv_data = spi_controller_get_devdata(master);
+ struct driver_data *drv_data = spi_controller_get_devdata(controller);
if (has_acpi_companion(&drv_data->pdev->dev)) {
switch (drv_data->ssp_type) {
@@ -1595,8 +1595,8 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_controller *master,
static int pxa2xx_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct pxa2xx_spi_master *platform_info;
- struct spi_controller *master;
+ struct pxa2xx_spi_controller *platform_info;
+ struct spi_controller *controller;
struct driver_data *drv_data;
struct ssp_device *ssp;
const struct lpss_config *config;
@@ -1622,37 +1622,37 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
if (platform_info->is_slave)
- master = spi_alloc_slave(dev, sizeof(struct driver_data));
+ controller = spi_alloc_slave(dev, sizeof(struct driver_data));
else
- master = spi_alloc_master(dev, sizeof(struct driver_data));
+ controller = spi_alloc_master(dev, sizeof(struct driver_data));
- if (!master) {
- dev_err(&pdev->dev, "cannot alloc spi_master\n");
+ if (!controller) {
+ dev_err(&pdev->dev, "cannot alloc spi_controller\n");
pxa_ssp_free(ssp);
return -ENOMEM;
}
- drv_data = spi_controller_get_devdata(master);
- drv_data->master = master;
- drv_data->master_info = platform_info;
+ drv_data = spi_controller_get_devdata(controller);
+ drv_data->controller = controller;
+ drv_data->controller_info = platform_info;
drv_data->pdev = pdev;
drv_data->ssp = ssp;
- master->dev.of_node = pdev->dev.of_node;
+ controller->dev.of_node = pdev->dev.of_node;
/* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
-
- master->bus_num = ssp->port_id;
- master->dma_alignment = DMA_ALIGNMENT;
- master->cleanup = cleanup;
- master->setup = setup;
- master->set_cs = pxa2xx_spi_set_cs;
- master->transfer_one = pxa2xx_spi_transfer_one;
- master->slave_abort = pxa2xx_spi_slave_abort;
- master->handle_err = pxa2xx_spi_handle_err;
- master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
- master->fw_translate_cs = pxa2xx_spi_fw_translate_cs;
- master->auto_runtime_pm = true;
- master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
+ controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+
+ controller->bus_num = ssp->port_id;
+ controller->dma_alignment = DMA_ALIGNMENT;
+ controller->cleanup = cleanup;
+ controller->setup = setup;
+ controller->set_cs = pxa2xx_spi_set_cs;
+ controller->transfer_one = pxa2xx_spi_transfer_one;
+ controller->slave_abort = pxa2xx_spi_slave_abort;
+ controller->handle_err = pxa2xx_spi_handle_err;
+ controller->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
+ controller->fw_translate_cs = pxa2xx_spi_fw_translate_cs;
+ controller->auto_runtime_pm = true;
+ controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
drv_data->ssp_type = ssp->type;
@@ -1661,10 +1661,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
if (pxa25x_ssp_comp(drv_data)) {
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+ controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
break;
default:
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+ controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
break;
}
@@ -1673,7 +1673,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->clear_sr = SSSR_ROR;
drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
} else {
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+ controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
drv_data->dma_cr1 = DEFAULT_DMA_CR1;
drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
@@ -1685,7 +1685,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data);
if (status < 0) {
dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
- goto out_error_master_alloc;
+ goto out_error_controller_alloc;
}
/* Setup DMA if requested */
@@ -1695,7 +1695,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
dev_dbg(dev, "no DMA channels available, using PIO\n");
platform_info->enable_dma = false;
} else {
- master->can_dma = pxa2xx_spi_can_dma;
+ controller->can_dma = pxa2xx_spi_can_dma;
+ controller->max_dma_len = MAX_DMA_LEN;
}
}
@@ -1704,7 +1705,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
if (status)
goto out_error_dma_irq_alloc;
- master->max_speed_hz = clk_get_rate(ssp->clk);
+ controller->max_speed_hz = clk_get_rate(ssp->clk);
/* Load default SSP configuration */
pxa2xx_spi_write(drv_data, SSCR0, 0);
@@ -1727,7 +1728,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
break;
default:
- if (spi_controller_is_slave(master)) {
+ if (spi_controller_is_slave(controller)) {
tmp = SSCR1_SCFR |
SSCR1_SCLKDIR |
SSCR1_SFRMDIR |
@@ -1740,7 +1741,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
pxa2xx_spi_write(drv_data, SSCR1, tmp);
tmp = SSCR0_Motorola | SSCR0_DataSize(8);
- if (!spi_controller_is_slave(master))
+ if (!spi_controller_is_slave(controller))
tmp |= SSCR0_SCR(2);
pxa2xx_spi_write(drv_data, SSCR0, tmp);
break;
@@ -1765,24 +1766,24 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
platform_info->num_chipselect = config->cs_num;
}
}
- master->num_chipselect = platform_info->num_chipselect;
+ controller->num_chipselect = platform_info->num_chipselect;
count = gpiod_count(&pdev->dev, "cs");
if (count > 0) {
int i;
- master->num_chipselect = max_t(int, count,
- master->num_chipselect);
+ controller->num_chipselect = max_t(int, count,
+ controller->num_chipselect);
drv_data->cs_gpiods = devm_kcalloc(&pdev->dev,
- master->num_chipselect, sizeof(struct gpio_desc *),
+ controller->num_chipselect, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!drv_data->cs_gpiods) {
status = -ENOMEM;
goto out_error_clock_enabled;
}
- for (i = 0; i < master->num_chipselect; i++) {
+ for (i = 0; i < controller->num_chipselect; i++) {
struct gpio_desc *gpiod;
gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS);
@@ -1815,9 +1816,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
/* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data);
- status = devm_spi_register_controller(&pdev->dev, master);
+ status = devm_spi_register_controller(&pdev->dev, controller);
if (status != 0) {
- dev_err(&pdev->dev, "problem registering spi master\n");
+ dev_err(&pdev->dev, "problem registering spi controller\n");
goto out_error_clock_enabled;
}
@@ -1832,8 +1833,8 @@ out_error_dma_irq_alloc:
pxa2xx_spi_dma_release(drv_data);
free_irq(ssp->irq, drv_data);
-out_error_master_alloc:
- spi_controller_put(master);
+out_error_controller_alloc:
+ spi_controller_put(controller);
pxa_ssp_free(ssp);
return status;
}
@@ -1854,7 +1855,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(ssp->clk);
/* Release DMA */
- if (drv_data->master_info->enable_dma)
+ if (drv_data->controller_info->enable_dma)
pxa2xx_spi_dma_release(drv_data);
pm_runtime_put_noidle(&pdev->dev);
@@ -1876,7 +1877,7 @@ static int pxa2xx_spi_suspend(struct device *dev)
struct ssp_device *ssp = drv_data->ssp;
int status;
- status = spi_controller_suspend(drv_data->master);
+ status = spi_controller_suspend(drv_data->controller);
if (status != 0)
return status;
pxa2xx_spi_write(drv_data, SSCR0, 0);
@@ -1901,7 +1902,7 @@ static int pxa2xx_spi_resume(struct device *dev)
}
/* Start the queue running */
- return spi_controller_resume(drv_data->master);
+ return spi_controller_resume(drv_data->controller);
}
#endif
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 4e324da66ef7..aba777b4502d 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -31,10 +31,10 @@ struct driver_data {
/* SPI framework hookup */
enum pxa_ssp_type ssp_type;
- struct spi_controller *master;
+ struct spi_controller *controller;
/* PXA hookup */
- struct pxa2xx_spi_master *master_info;
+ struct pxa2xx_spi_controller *controller_info;
/* SSP register addresses */
void __iomem *ioaddr;
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index a4ef641b5227..556870dcdf79 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -180,7 +180,7 @@
struct rspi_data {
void __iomem *addr;
u32 max_speed_hz;
- struct spi_master *master;
+ struct spi_controller *ctlr;
wait_queue_head_t wait;
struct clk *clk;
u16 spcmd;
@@ -237,8 +237,8 @@ static u16 rspi_read_data(const struct rspi_data *rspi)
/* optional functions */
struct spi_ops {
int (*set_config_register)(struct rspi_data *rspi, int access_size);
- int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
- struct spi_transfer *xfer);
+ int (*transfer_one)(struct spi_controller *ctlr,
+ struct spi_device *spi, struct spi_transfer *xfer);
u16 mode_bits;
u16 flags;
u16 fifo_size;
@@ -466,7 +466,7 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data)
{
int error = rspi_wait_for_tx_empty(rspi);
if (error < 0) {
- dev_err(&rspi->master->dev, "transmit timeout\n");
+ dev_err(&rspi->ctlr->dev, "transmit timeout\n");
return error;
}
rspi_write_data(rspi, data);
@@ -480,7 +480,7 @@ static int rspi_data_in(struct rspi_data *rspi)
error = rspi_wait_for_rx_full(rspi);
if (error < 0) {
- dev_err(&rspi->master->dev, "receive timeout\n");
+ dev_err(&rspi->ctlr->dev, "receive timeout\n");
return error;
}
data = rspi_read_data(rspi);
@@ -526,8 +526,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
/* First prepare and submit the DMA request(s), as this may fail */
if (rx) {
- desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
- rx->sgl, rx->nents, DMA_DEV_TO_MEM,
+ desc_rx = dmaengine_prep_slave_sg(rspi->ctlr->dma_rx, rx->sgl,
+ rx->nents, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx) {
ret = -EAGAIN;
@@ -546,8 +546,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
}
if (tx) {
- desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
- tx->sgl, tx->nents, DMA_MEM_TO_DEV,
+ desc_tx = dmaengine_prep_slave_sg(rspi->ctlr->dma_tx, tx->sgl,
+ tx->nents, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) {
ret = -EAGAIN;
@@ -584,9 +584,9 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
/* Now start DMA */
if (rx)
- dma_async_issue_pending(rspi->master->dma_rx);
+ dma_async_issue_pending(rspi->ctlr->dma_rx);
if (tx)
- dma_async_issue_pending(rspi->master->dma_tx);
+ dma_async_issue_pending(rspi->ctlr->dma_tx);
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
@@ -594,13 +594,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
ret = 0;
} else {
if (!ret) {
- dev_err(&rspi->master->dev, "DMA timeout\n");
+ dev_err(&rspi->ctlr->dev, "DMA timeout\n");
ret = -ETIMEDOUT;
}
if (tx)
- dmaengine_terminate_all(rspi->master->dma_tx);
+ dmaengine_terminate_all(rspi->ctlr->dma_tx);
if (rx)
- dmaengine_terminate_all(rspi->master->dma_rx);
+ dmaengine_terminate_all(rspi->ctlr->dma_rx);
}
rspi_disable_irq(rspi, irq_mask);
@@ -614,12 +614,12 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
no_dma_tx:
if (rx)
- dmaengine_terminate_all(rspi->master->dma_rx);
+ dmaengine_terminate_all(rspi->ctlr->dma_rx);
no_dma_rx:
if (ret == -EAGAIN) {
pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
- dev_driver_string(&rspi->master->dev),
- dev_name(&rspi->master->dev));
+ dev_driver_string(&rspi->ctlr->dev),
+ dev_name(&rspi->ctlr->dev));
}
return ret;
}
@@ -660,10 +660,10 @@ static bool __rspi_can_dma(const struct rspi_data *rspi,
return xfer->len > rspi->ops->fifo_size;
}
-static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
+static bool rspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi,
struct spi_transfer *xfer)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
return __rspi_can_dma(rspi, xfer);
}
@@ -671,7 +671,7 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
static int rspi_dma_check_then_transfer(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
- if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer))
+ if (!rspi->ctlr->can_dma || !__rspi_can_dma(rspi, xfer))
return -EAGAIN;
/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
@@ -698,10 +698,10 @@ static int rspi_common_transfer(struct rspi_data *rspi,
return 0;
}
-static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
- struct spi_transfer *xfer)
+static int rspi_transfer_one(struct spi_controller *ctlr,
+ struct spi_device *spi, struct spi_transfer *xfer)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
u8 spcr;
spcr = rspi_read8(rspi, RSPI_SPCR);
@@ -716,11 +716,11 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
return rspi_common_transfer(rspi, xfer);
}
-static int rspi_rz_transfer_one(struct spi_master *master,
+static int rspi_rz_transfer_one(struct spi_controller *ctlr,
struct spi_device *spi,
struct spi_transfer *xfer)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
rspi_rz_receive_init(rspi);
@@ -739,7 +739,7 @@ static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
if (n == QSPI_BUFFER_SIZE) {
ret = rspi_wait_for_tx_empty(rspi);
if (ret < 0) {
- dev_err(&rspi->master->dev, "transmit timeout\n");
+ dev_err(&rspi->ctlr->dev, "transmit timeout\n");
return ret;
}
for (i = 0; i < n; i++)
@@ -747,7 +747,7 @@ static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
ret = rspi_wait_for_rx_full(rspi);
if (ret < 0) {
- dev_err(&rspi->master->dev, "receive timeout\n");
+ dev_err(&rspi->ctlr->dev, "receive timeout\n");
return ret;
}
for (i = 0; i < n; i++)
@@ -785,7 +785,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
unsigned int i, len;
int ret;
- if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
+ if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) {
ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
if (ret != -EAGAIN)
return ret;
@@ -796,7 +796,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
if (len == QSPI_BUFFER_SIZE) {
ret = rspi_wait_for_tx_empty(rspi);
if (ret < 0) {
- dev_err(&rspi->master->dev, "transmit timeout\n");
+ dev_err(&rspi->ctlr->dev, "transmit timeout\n");
return ret;
}
for (i = 0; i < len; i++)
@@ -822,7 +822,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
unsigned int i, len;
int ret;
- if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
+ if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) {
int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
if (ret != -EAGAIN)
return ret;
@@ -833,7 +833,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
if (len == QSPI_BUFFER_SIZE) {
ret = rspi_wait_for_rx_full(rspi);
if (ret < 0) {
- dev_err(&rspi->master->dev, "receive timeout\n");
+ dev_err(&rspi->ctlr->dev, "receive timeout\n");
return ret;
}
for (i = 0; i < len; i++)
@@ -849,10 +849,10 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
return 0;
}
-static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
- struct spi_transfer *xfer)
+static int qspi_transfer_one(struct spi_controller *ctlr,
+ struct spi_device *spi, struct spi_transfer *xfer)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
if (spi->mode & SPI_LOOP) {
return qspi_transfer_out_in(rspi, xfer);
@@ -870,7 +870,7 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
static int rspi_setup(struct spi_device *spi)
{
- struct rspi_data *rspi = spi_master_get_devdata(spi->master);
+ struct rspi_data *rspi = spi_controller_get_devdata(spi->controller);
rspi->max_speed_hz = spi->max_speed_hz;
@@ -955,10 +955,10 @@ static int qspi_setup_sequencer(struct rspi_data *rspi,
return 0;
}
-static int rspi_prepare_message(struct spi_master *master,
+static int rspi_prepare_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
int ret;
if (msg->spi->mode &
@@ -974,10 +974,10 @@ static int rspi_prepare_message(struct spi_master *master,
return 0;
}
-static int rspi_unprepare_message(struct spi_master *master,
+static int rspi_unprepare_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
- struct rspi_data *rspi = spi_master_get_devdata(master);
+ struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
/* Disable SPI function */
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
@@ -1081,7 +1081,7 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
return chan;
}
-static int rspi_request_dma(struct device *dev, struct spi_master *master,
+static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr,
const struct resource *res)
{
const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
@@ -1099,37 +1099,37 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master,
return 0;
}
- master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
- res->start + RSPI_SPDR);
- if (!master->dma_tx)
+ ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
+ res->start + RSPI_SPDR);
+ if (!ctlr->dma_tx)
return -ENODEV;
- master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
- res->start + RSPI_SPDR);
- if (!master->dma_rx) {
- dma_release_channel(master->dma_tx);
- master->dma_tx = NULL;
+ ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
+ res->start + RSPI_SPDR);
+ if (!ctlr->dma_rx) {
+ dma_release_channel(ctlr->dma_tx);
+ ctlr->dma_tx = NULL;
return -ENODEV;
}
- master->can_dma = rspi_can_dma;
+ ctlr->can_dma = rspi_can_dma;
dev_info(dev, "DMA available");
return 0;
}
-static void rspi_release_dma(struct spi_master *master)
+static void rspi_release_dma(struct spi_controller *ctlr)
{
- if (master->dma_tx)
- dma_release_channel(master->dma_tx);
- if (master->dma_rx)
- dma_release_channel(master->dma_rx);
+ if (ctlr->dma_tx)
+ dma_release_channel(ctlr->dma_tx);
+ if (ctlr->dma_rx)
+ dma_release_channel(ctlr->dma_rx);
}
static int rspi_remove(struct platform_device *pdev)
{
struct rspi_data *rspi = platform_get_drvdata(pdev);
- rspi_release_dma(rspi->master);
+ rspi_release_dma(rspi->ctlr);
pm_runtime_disable(&pdev->dev);
return 0;
@@ -1139,7 +1139,7 @@ static const struct spi_ops rspi_ops = {
.set_config_register = rspi_set_config_register,
.transfer_one = rspi_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
- .flags = SPI_MASTER_MUST_TX,
+ .flags = SPI_CONTROLLER_MUST_TX,
.fifo_size = 8,
};
@@ -1147,7 +1147,7 @@ static const struct spi_ops rspi_rz_ops = {
.set_config_register = rspi_rz_set_config_register,
.transfer_one = rspi_rz_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
- .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
+ .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
.fifo_size = 8, /* 8 for TX, 32 for RX */
};
@@ -1157,7 +1157,7 @@ static const struct spi_ops qspi_ops = {
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP |
SPI_TX_DUAL | SPI_TX_QUAD |
SPI_RX_DUAL | SPI_RX_QUAD,
- .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
+ .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
.fifo_size = 32,
};
@@ -1174,7 +1174,7 @@ static const struct of_device_id rspi_of_match[] = {
MODULE_DEVICE_TABLE(of, rspi_of_match);
-static int rspi_parse_dt(struct device *dev, struct spi_master *master)
+static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
{
u32 num_cs;
int error;
@@ -1186,12 +1186,12 @@ static int rspi_parse_dt(struct device *dev, struct spi_master *master)
return error;
}
- master->num_chipselect = num_cs;
+ ctlr->num_chipselect = num_cs;
return 0;
}
#else
#define rspi_of_match NULL
-static inline int rspi_parse_dt(struct device *dev, struct spi_master *master)
+static inline int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
{
return -EINVAL;
}
@@ -1212,28 +1212,28 @@ static int rspi_request_irq(struct device *dev, unsigned int irq,
static int rspi_probe(struct platform_device *pdev)
{
struct resource *res;
- struct spi_master *master;
+ struct spi_controller *ctlr;
struct rspi_data *rspi;
int ret;
const struct rspi_plat_data *rspi_pd;
const struct spi_ops *ops;
- master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
- if (master == NULL)
+ ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
+ if (ctlr == NULL)
return -ENOMEM;
ops = of_device_get_match_data(&pdev->dev);
if (ops) {
- ret = rspi_parse_dt(&pdev->dev, master);
+ ret = rspi_parse_dt(&pdev->dev, ctlr);
if (ret)
goto error1;
} else {
ops = (struct spi_ops *)pdev->id_entry->driver_data;
rspi_pd = dev_get_platdata(&pdev->dev);
if (rspi_pd && rspi_pd->num_chipselect)
- master->num_chipselect = rspi_pd->num_chipselect;
+ ctlr->num_chipselect = rspi_pd->num_chipselect;
else
- master->num_chipselect = 2; /* default */
+ ctlr->num_chipselect = 2; /* default */
}
/* ops parameter check */
@@ -1243,10 +1243,10 @@ static int rspi_probe(struct platform_device *pdev)
goto error1;
}
- rspi = spi_master_get_devdata(master);
+ rspi = spi_controller_get_devdata(ctlr);
platform_set_drvdata(pdev, rspi);
rspi->ops = ops;
- rspi->master = master;
+ rspi->ctlr = ctlr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rspi->addr = devm_ioremap_resource(&pdev->dev, res);
@@ -1266,15 +1266,15 @@ static int rspi_probe(struct platform_device *pdev)
init_waitqueue_head(&rspi->wait);
- master->bus_num = pdev->id;
- master->setup = rspi_setup;
- master->auto_runtime_pm = true;
- master->transfer_one = ops->transfer_one;
- master->prepare_message = rspi_prepare_message;
- master->unprepare_message = rspi_unprepare_message;
- master->mode_bits = ops->mode_bits;
- master->flags = ops->flags;
- master->dev.of_node = pdev->dev.of_node;
+ ctlr->bus_num = pdev->id;
+ ctlr->setup = rspi_setup;
+ ctlr->auto_runtime_pm = true;
+ ctlr->transfer_one = ops->transfer_one;
+ ctlr->prepare_message = rspi_prepare_message;
+ ctlr->unprepare_message = rspi_unprepare_message;
+ ctlr->mode_bits = ops->mode_bits;
+ ctlr->flags = ops->flags;
+ ctlr->dev.of_node = pdev->dev.of_node;
ret = platform_get_irq_byname(pdev, "rx");
if (ret < 0) {
@@ -1311,13 +1311,13 @@ static int rspi_probe(struct platform_device *pdev)
goto error2;
}
- ret = rspi_request_dma(&pdev->dev, master, res);
+ ret = rspi_request_dma(&pdev->dev, ctlr, res);
if (ret < 0)
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
- ret = devm_spi_register_master(&pdev->dev, master);
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_master error.\n");
+ dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
goto error3;
}
@@ -1326,11 +1326,11 @@ static int rspi_probe(struct platform_device *pdev)
return 0;
error3:
- rspi_release_dma(master);
+ rspi_release_dma(ctlr);
error2:
pm_runtime_disable(&pdev->dev);
error1:
- spi_master_put(master);
+ spi_controller_put(ctlr);
return ret;
}
@@ -1349,14 +1349,14 @@ static int rspi_suspend(struct device *dev)
{
struct rspi_data *rspi = dev_get_drvdata(dev);
- return spi_master_suspend(rspi->master);
+ return spi_controller_suspend(rspi->ctlr);
}
static int rspi_resume(struct device *dev)
{
struct rspi_data *rspi = dev_get_drvdata(dev);
- return spi_master_resume(rspi->master);
+ return spi_controller_resume(rspi->ctlr);
}
static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume);
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index dc0926e43665..7f73f91d412a 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -35,7 +35,7 @@
struct hspi_priv {
void __iomem *addr;
- struct spi_master *master;
+ struct spi_controller *ctlr;
struct device *dev;
struct clk *clk;
};
@@ -140,10 +140,10 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */
}
-static int hspi_transfer_one_message(struct spi_master *master,
+static int hspi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
- struct hspi_priv *hspi = spi_master_get_devdata(master);
+ struct hspi_priv *hspi = spi_controller_get_devdata(ctlr);
struct spi_transfer *t;
u32 tx;
u32 rx;
@@ -205,7 +205,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
ndelay(nsecs);
hspi_hw_cs_disable(hspi);
}
- spi_finalize_current_message(master);
+ spi_finalize_current_message(ctlr);
return ret;
}
@@ -213,7 +213,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
static int hspi_probe(struct platform_device *pdev)
{
struct resource *res;
- struct spi_master *master;
+ struct spi_controller *ctlr;
struct hspi_priv *hspi;
struct clk *clk;
int ret;
@@ -225,11 +225,9 @@ static int hspi_probe(struct platform_device *pdev)
return -EINVAL;
}
- master = spi_alloc_master(&pdev->dev, sizeof(*hspi));
- if (!master) {
- dev_err(&pdev->dev, "spi_alloc_master error.\n");
+ ctlr = spi_alloc_master(&pdev->dev, sizeof(*hspi));
+ if (!ctlr)
return -ENOMEM;
- }
clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
@@ -238,33 +236,32 @@ static int hspi_probe(struct platform_device *pdev)
goto error0;
}
- hspi = spi_master_get_devdata(master);
+ hspi = spi_controller_get_devdata(ctlr);
platform_set_drvdata(pdev, hspi);
/* init hspi */
- hspi->master = master;
+ hspi->ctlr = ctlr;
hspi->dev = &pdev->dev;
hspi->clk = clk;
hspi->addr = devm_ioremap(hspi->dev,
res->start, resource_size(res));
if (!hspi->addr) {
- dev_err(&pdev->dev, "ioremap error.\n");
ret = -ENOMEM;
goto error1;
}
pm_runtime_enable(&pdev->dev);
- master->bus_num = pdev->id;
- master->mode_bits = SPI_CPOL | SPI_CPHA;
- master->dev.of_node = pdev->dev.of_node;
- master->auto_runtime_pm = true;
- master->transfer_one_message = hspi_transfer_one_message;
- master->bits_per_word_mask = SPI_BPW_MASK(8);
+ ctlr->bus_num = pdev->id;
+ ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
+ ctlr->dev.of_node = pdev->dev.of_node;
+ ctlr->auto_runtime_pm = true;
+ ctlr->transfer_one_message = hspi_transfer_one_message;
+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
- ret = devm_spi_register_master(&pdev->dev, master);
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_master error.\n");
+ dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
goto error2;
}
@@ -275,7 +272,7 @@ static int hspi_probe(struct platform_device *pdev)
error1:
clk_put(clk);
error0:
- spi_master_put(master);
+ spi_controller_put(ctlr);
return ret;
}
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index d14b407cc800..e2eb466db10a 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * SuperH MSIOF SPI Master Interface
+ * SuperH MSIOF SPI Controller Interface
*
* Copyright (c) 2009 Magnus Damm
* Copyright (C) 2014 Renesas Electronics Corporation
@@ -32,14 +32,15 @@
#include <asm/unaligned.h>
struct sh_msiof_chipdata {
+ u32 bits_per_word_mask;
u16 tx_fifo_size;
u16 rx_fifo_size;
- u16 master_flags;
+ u16 ctlr_flags;
u16 min_div_pow;
};
struct sh_msiof_spi_priv {
- struct spi_master *master;
+ struct spi_controller *ctlr;
void __iomem *mapbase;
struct clk *clk;
struct platform_device *pdev;
@@ -287,7 +288,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
scr = sh_msiof_spi_div_array[div_pow] | SCR_BRPS(brps);
sh_msiof_write(p, TSCR, scr);
- if (!(p->master->flags & SPI_MASTER_MUST_TX))
+ if (!(p->ctlr->flags & SPI_CONTROLLER_MUST_TX))
sh_msiof_write(p, RSCR, scr);
}
@@ -351,14 +352,14 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss,
tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
tmp |= lsb_first << MDR1_BITLSB_SHIFT;
tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p);
- if (spi_controller_is_slave(p->master)) {
+ if (spi_controller_is_slave(p->ctlr)) {
sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON);
} else {
sh_msiof_write(p, TMDR1,
tmp | MDR1_TRMD | TMDR1_PCON |
(ss < MAX_SS ? ss : 0) << TMDR1_SYNCCH_SHIFT);
}
- if (p->master->flags & SPI_MASTER_MUST_TX) {
+ if (p->ctlr->flags & SPI_CONTROLLER_MUST_TX) {
/* These bits are reserved if RX needs TX */
tmp &= ~0x0000ffff;
}
@@ -382,7 +383,7 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
{
u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words);
- if (tx_buf || (p->master->flags & SPI_MASTER_MUST_TX))
+ if (tx_buf || (p->ctlr->flags & SPI_CONTROLLER_MUST_TX))
sh_msiof_write(p, TMDR2, dr2);
else
sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1);
@@ -539,8 +540,9 @@ static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
static int sh_msiof_spi_setup(struct spi_device *spi)
{
- struct device_node *np = spi->master->dev.of_node;
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
+ struct device_node *np = spi->controller->dev.of_node;
+ struct sh_msiof_spi_priv *p =
+ spi_controller_get_devdata(spi->controller);
u32 clr, set, tmp;
if (!np) {
@@ -556,7 +558,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi)
return 0;
}
- if (spi_controller_is_slave(p->master))
+ if (spi_controller_is_slave(p->ctlr))
return 0;
if (p->native_cs_inited &&
@@ -581,10 +583,10 @@ static int sh_msiof_spi_setup(struct spi_device *spi)
return 0;
}
-static int sh_msiof_prepare_message(struct spi_master *master,
+static int sh_msiof_prepare_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+ struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr);
const struct spi_device *spi = msg->spi;
u32 ss, cs_high;
@@ -605,7 +607,7 @@ static int sh_msiof_prepare_message(struct spi_master *master,
static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf)
{
- bool slave = spi_controller_is_slave(p->master);
+ bool slave = spi_controller_is_slave(p->ctlr);
int ret = 0;
/* setup clock and rx/tx signals */
@@ -625,7 +627,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf)
static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf)
{
- bool slave = spi_controller_is_slave(p->master);
+ bool slave = spi_controller_is_slave(p->ctlr);
int ret = 0;
/* shut down frame, rx/tx and clock signals */
@@ -641,9 +643,9 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf)
return ret;
}
-static int sh_msiof_slave_abort(struct spi_master *master)
+static int sh_msiof_slave_abort(struct spi_controller *ctlr)
{
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+ struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr);
p->slave_aborted = true;
complete(&p->done);
@@ -654,7 +656,7 @@ static int sh_msiof_slave_abort(struct spi_master *master)
static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p,
struct completion *x)
{
- if (spi_controller_is_slave(p->master)) {
+ if (spi_controller_is_slave(p->ctlr)) {
if (wait_for_completion_interruptible(x) ||
p->slave_aborted) {
dev_dbg(&p->pdev->dev, "interrupted\n");
@@ -754,7 +756,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
/* First prepare and submit the DMA request(s), as this may fail */
if (rx) {
ier_bits |= IER_RDREQE | IER_RDMAE;
- desc_rx = dmaengine_prep_slave_single(p->master->dma_rx,
+ desc_rx = dmaengine_prep_slave_single(p->ctlr->dma_rx,
p->rx_dma_addr, len, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx)
@@ -769,9 +771,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
if (tx) {
ier_bits |= IER_TDREQE | IER_TDMAE;
- dma_sync_single_for_device(p->master->dma_tx->device->dev,
+ dma_sync_single_for_device(p->ctlr->dma_tx->device->dev,
p->tx_dma_addr, len, DMA_TO_DEVICE);
- desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
+ desc_tx = dmaengine_prep_slave_single(p->ctlr->dma_tx,
p->tx_dma_addr, len, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) {
@@ -803,9 +805,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
/* Now start DMA */
if (rx)
- dma_async_issue_pending(p->master->dma_rx);
+ dma_async_issue_pending(p->ctlr->dma_rx);
if (tx)
- dma_async_issue_pending(p->master->dma_tx);
+ dma_async_issue_pending(p->ctlr->dma_tx);
ret = sh_msiof_spi_start(p, rx);
if (ret) {
@@ -845,9 +847,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
}
if (rx)
- dma_sync_single_for_cpu(p->master->dma_rx->device->dev,
- p->rx_dma_addr, len,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(p->ctlr->dma_rx->device->dev,
+ p->rx_dma_addr, len, DMA_FROM_DEVICE);
return 0;
@@ -856,10 +857,10 @@ stop_reset:
sh_msiof_spi_stop(p, rx);
stop_dma:
if (tx)
- dmaengine_terminate_all(p->master->dma_tx);
+ dmaengine_terminate_all(p->ctlr->dma_tx);
no_dma_tx:
if (rx)
- dmaengine_terminate_all(p->master->dma_rx);
+ dmaengine_terminate_all(p->ctlr->dma_rx);
sh_msiof_write(p, IER, 0);
return ret;
}
@@ -907,11 +908,11 @@ static void copy_plain32(u32 *dst, const u32 *src, unsigned int words)
memcpy(dst, src, words * 4);
}
-static int sh_msiof_transfer_one(struct spi_master *master,
+static int sh_msiof_transfer_one(struct spi_controller *ctlr,
struct spi_device *spi,
struct spi_transfer *t)
{
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+ struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr);
void (*copy32)(u32 *, const u32 *, unsigned int);
void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
@@ -926,10 +927,10 @@ static int sh_msiof_transfer_one(struct spi_master *master,
int ret;
/* setup clocks (clock already enabled in chipselect()) */
- if (!spi_controller_is_slave(p->master))
+ if (!spi_controller_is_slave(p->ctlr))
sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
- while (master->dma_tx && len > 15) {
+ while (ctlr->dma_tx && len > 15) {
/*
* DMA supports 32-bit words only, hence pack 8-bit and 16-bit
* words, with byte resp. word swapping.
@@ -937,17 +938,13 @@ static int sh_msiof_transfer_one(struct spi_master *master,
unsigned int l = 0;
if (tx_buf)
- l = min(len, p->tx_fifo_size * 4);
+ l = min(round_down(len, 4), p->tx_fifo_size * 4);
if (rx_buf)
- l = min(len, p->rx_fifo_size * 4);
+ l = min(round_down(len, 4), p->rx_fifo_size * 4);
if (bits <= 8) {
- if (l & 3)
- break;
copy32 = copy_bswap32;
} else if (bits <= 16) {
- if (l & 3)
- break;
copy32 = copy_wswap32;
} else {
copy32 = copy_plain32;
@@ -1052,23 +1049,28 @@ static int sh_msiof_transfer_one(struct spi_master *master,
}
static const struct sh_msiof_chipdata sh_data = {
+ .bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32),
.tx_fifo_size = 64,
.rx_fifo_size = 64,
- .master_flags = 0,
+ .ctlr_flags = 0,
.min_div_pow = 0,
};
static const struct sh_msiof_chipdata rcar_gen2_data = {
+ .bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) |
+ SPI_BPW_MASK(24) | SPI_BPW_MASK(32),
.tx_fifo_size = 64,
.rx_fifo_size = 64,
- .master_flags = SPI_MASTER_MUST_TX,
+ .ctlr_flags = SPI_CONTROLLER_MUST_TX,
.min_div_pow = 0,
};
static const struct sh_msiof_chipdata rcar_gen3_data = {
+ .bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) |
+ SPI_BPW_MASK(24) | SPI_BPW_MASK(32),
.tx_fifo_size = 64,
.rx_fifo_size = 64,
- .master_flags = SPI_MASTER_MUST_TX,
+ .ctlr_flags = SPI_CONTROLLER_MUST_TX,
.min_div_pow = 1,
};
@@ -1136,7 +1138,7 @@ static int sh_msiof_get_cs_gpios(struct sh_msiof_spi_priv *p)
if (ret <= 0)
return 0;
- num_cs = max_t(unsigned int, ret, p->master->num_chipselect);
+ num_cs = max_t(unsigned int, ret, p->ctlr->num_chipselect);
for (i = 0; i < num_cs; i++) {
struct gpio_desc *gpiod;
@@ -1206,10 +1208,10 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
{
struct platform_device *pdev = p->pdev;
struct device *dev = &pdev->dev;
- const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
+ const struct sh_msiof_spi_info *info = p->info;
unsigned int dma_tx_id, dma_rx_id;
const struct resource *res;
- struct spi_master *master;
+ struct spi_controller *ctlr;
struct device *tx_dev, *rx_dev;
if (dev->of_node) {
@@ -1229,17 +1231,15 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
if (!res)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- master = p->master;
- master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV,
- dma_tx_id,
- res->start + TFDR);
- if (!master->dma_tx)
+ ctlr = p->ctlr;
+ ctlr->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV,
+ dma_tx_id, res->start + TFDR);
+ if (!ctlr->dma_tx)
return -ENODEV;
- master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM,
- dma_rx_id,
- res->start + RFDR);
- if (!master->dma_rx)
+ ctlr->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM,
+ dma_rx_id, res->start + RFDR);
+ if (!ctlr->dma_rx)
goto free_tx_chan;
p->tx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
@@ -1250,13 +1250,13 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
if (!p->rx_dma_page)
goto free_tx_page;
- tx_dev = master->dma_tx->device->dev;
+ tx_dev = ctlr->dma_tx->device->dev;
p->tx_dma_addr = dma_map_single(tx_dev, p->tx_dma_page, PAGE_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(tx_dev, p->tx_dma_addr))
goto free_rx_page;
- rx_dev = master->dma_rx->device->dev;
+ rx_dev = ctlr->dma_rx->device->dev;
p->rx_dma_addr = dma_map_single(rx_dev, p->rx_dma_page, PAGE_SIZE,
DMA_FROM_DEVICE);
if (dma_mapping_error(rx_dev, p->rx_dma_addr))
@@ -1272,34 +1272,34 @@ free_rx_page:
free_tx_page:
free_page((unsigned long)p->tx_dma_page);
free_rx_chan:
- dma_release_channel(master->dma_rx);
+ dma_release_channel(ctlr->dma_rx);
free_tx_chan:
- dma_release_channel(master->dma_tx);
- master->dma_tx = NULL;
+ dma_release_channel(ctlr->dma_tx);
+ ctlr->dma_tx = NULL;
return -ENODEV;
}
static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
{
- struct spi_master *master = p->master;
+ struct spi_controller *ctlr = p->ctlr;
- if (!master->dma_tx)
+ if (!ctlr->dma_tx)
return;
- dma_unmap_single(master->dma_rx->device->dev, p->rx_dma_addr,
- PAGE_SIZE, DMA_FROM_DEVICE);
- dma_unmap_single(master->dma_tx->device->dev, p->tx_dma_addr,
- PAGE_SIZE, DMA_TO_DEVICE);
+ dma_unmap_single(ctlr->dma_rx->device->dev, p->rx_dma_addr, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(ctlr->dma_tx->device->dev, p->tx_dma_addr, PAGE_SIZE,
+ DMA_TO_DEVICE);
free_page((unsigned long)p->rx_dma_page);
free_page((unsigned long)p->tx_dma_page);
- dma_release_channel(master->dma_rx);
- dma_release_channel(master->dma_tx);
+ dma_release_channel(ctlr->dma_rx);
+ dma_release_channel(ctlr->dma_tx);
}
static int sh_msiof_spi_probe(struct platform_device *pdev)
{
struct resource *r;
- struct spi_master *master;
+ struct spi_controller *ctlr;
const struct sh_msiof_chipdata *chipdata;
struct sh_msiof_spi_info *info;
struct sh_msiof_spi_priv *p;
@@ -1320,18 +1320,18 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
}
if (info->mode == MSIOF_SPI_SLAVE)
- master = spi_alloc_slave(&pdev->dev,
- sizeof(struct sh_msiof_spi_priv));
+ ctlr = spi_alloc_slave(&pdev->dev,
+ sizeof(struct sh_msiof_spi_priv));
else
- master = spi_alloc_master(&pdev->dev,
- sizeof(struct sh_msiof_spi_priv));
- if (master == NULL)
+ ctlr = spi_alloc_master(&pdev->dev,
+ sizeof(struct sh_msiof_spi_priv));
+ if (ctlr == NULL)
return -ENOMEM;
- p = spi_master_get_devdata(master);
+ p = spi_controller_get_devdata(ctlr);
platform_set_drvdata(pdev, p);
- p->master = master;
+ p->ctlr = ctlr;
p->info = info;
p->min_div_pow = chipdata->min_div_pow;
@@ -1378,31 +1378,31 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->rx_fifo_size = p->info->rx_fifo_override;
/* Setup GPIO chip selects */
- master->num_chipselect = p->info->num_chipselect;
+ ctlr->num_chipselect = p->info->num_chipselect;
ret = sh_msiof_get_cs_gpios(p);
if (ret)
goto err1;
- /* init master code */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
- master->flags = chipdata->master_flags;
- master->bus_num = pdev->id;
- master->dev.of_node = pdev->dev.of_node;
- master->setup = sh_msiof_spi_setup;
- master->prepare_message = sh_msiof_prepare_message;
- master->slave_abort = sh_msiof_slave_abort;
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
- master->auto_runtime_pm = true;
- master->transfer_one = sh_msiof_transfer_one;
+ /* init controller code */
+ ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ ctlr->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
+ ctlr->flags = chipdata->ctlr_flags;
+ ctlr->bus_num = pdev->id;
+ ctlr->dev.of_node = pdev->dev.of_node;
+ ctlr->setup = sh_msiof_spi_setup;
+ ctlr->prepare_message = sh_msiof_prepare_message;
+ ctlr->slave_abort = sh_msiof_slave_abort;
+ ctlr->bits_per_word_mask = chipdata->bits_per_word_mask;
+ ctlr->auto_runtime_pm = true;
+ ctlr->transfer_one = sh_msiof_transfer_one;
ret = sh_msiof_request_dma(p);
if (ret < 0)
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
- ret = devm_spi_register_master(&pdev->dev, master);
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_master error.\n");
+ dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
goto err2;
}
@@ -1412,7 +1412,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
sh_msiof_release_dma(p);
pm_runtime_disable(&pdev->dev);
err1:
- spi_master_put(master);
+ spi_controller_put(ctlr);
return ret;
}
@@ -1436,14 +1436,14 @@ static int sh_msiof_spi_suspend(struct device *dev)
{
struct sh_msiof_spi_priv *p = dev_get_drvdata(dev);
- return spi_master_suspend(p->master);
+ return spi_controller_suspend(p->ctlr);
}
static int sh_msiof_spi_resume(struct device *dev)
{
struct sh_msiof_spi_priv *p = dev_get_drvdata(dev);
- return spi_master_resume(p->master);
+ return spi_controller_resume(p->ctlr);
}
static SIMPLE_DEV_PM_OPS(sh_msiof_spi_pm_ops, sh_msiof_spi_suspend,
@@ -1465,7 +1465,7 @@ static struct platform_driver sh_msiof_spi_drv = {
};
module_platform_driver(sh_msiof_spi_drv);
-MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
+MODULE_DESCRIPTION("SuperH MSIOF SPI Controller Interface Driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spi_sh_msiof");
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
new file mode 100644
index 000000000000..93ec2c6cdbfd
--- /dev/null
+++ b/drivers/spi/spi-sifive.c
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2018 SiFive, Inc.
+//
+// SiFive SPI controller driver (master mode only)
+//
+// Author: SiFive, Inc.
+// sifive@sifive.com
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+
+#define SIFIVE_SPI_DRIVER_NAME "sifive_spi"
+
+#define SIFIVE_SPI_MAX_CS 32
+#define SIFIVE_SPI_DEFAULT_DEPTH 8
+#define SIFIVE_SPI_DEFAULT_MAX_BITS 8
+
+/* register offsets */
+#define SIFIVE_SPI_REG_SCKDIV 0x00 /* Serial clock divisor */
+#define SIFIVE_SPI_REG_SCKMODE 0x04 /* Serial clock mode */
+#define SIFIVE_SPI_REG_CSID 0x10 /* Chip select ID */
+#define SIFIVE_SPI_REG_CSDEF 0x14 /* Chip select default */
+#define SIFIVE_SPI_REG_CSMODE 0x18 /* Chip select mode */
+#define SIFIVE_SPI_REG_DELAY0 0x28 /* Delay control 0 */
+#define SIFIVE_SPI_REG_DELAY1 0x2c /* Delay control 1 */
+#define SIFIVE_SPI_REG_FMT 0x40 /* Frame format */
+#define SIFIVE_SPI_REG_TXDATA 0x48 /* Tx FIFO data */
+#define SIFIVE_SPI_REG_RXDATA 0x4c /* Rx FIFO data */
+#define SIFIVE_SPI_REG_TXMARK 0x50 /* Tx FIFO watermark */
+#define SIFIVE_SPI_REG_RXMARK 0x54 /* Rx FIFO watermark */
+#define SIFIVE_SPI_REG_FCTRL 0x60 /* SPI flash interface control */
+#define SIFIVE_SPI_REG_FFMT 0x64 /* SPI flash instruction format */
+#define SIFIVE_SPI_REG_IE 0x70 /* Interrupt Enable Register */
+#define SIFIVE_SPI_REG_IP 0x74 /* Interrupt Pendings Register */
+
+/* sckdiv bits */
+#define SIFIVE_SPI_SCKDIV_DIV_MASK 0xfffU
+
+/* sckmode bits */
+#define SIFIVE_SPI_SCKMODE_PHA BIT(0)
+#define SIFIVE_SPI_SCKMODE_POL BIT(1)
+#define SIFIVE_SPI_SCKMODE_MODE_MASK (SIFIVE_SPI_SCKMODE_PHA | \
+ SIFIVE_SPI_SCKMODE_POL)
+
+/* csmode bits */
+#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U
+#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U
+#define SIFIVE_SPI_CSMODE_MODE_OFF 3U
+
+/* delay0 bits */
+#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x))
+#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU
+#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16)
+#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16)
+
+/* delay1 bits */
+#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x))
+#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU
+#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16)
+#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16)
+
+/* fmt bits */
+#define SIFIVE_SPI_FMT_PROTO_SINGLE 0U
+#define SIFIVE_SPI_FMT_PROTO_DUAL 1U
+#define SIFIVE_SPI_FMT_PROTO_QUAD 2U
+#define SIFIVE_SPI_FMT_PROTO_MASK 3U
+#define SIFIVE_SPI_FMT_ENDIAN BIT(2)
+#define SIFIVE_SPI_FMT_DIR BIT(3)
+#define SIFIVE_SPI_FMT_LEN(x) ((u32)(x) << 16)
+#define SIFIVE_SPI_FMT_LEN_MASK (0xfU << 16)
+
+/* txdata bits */
+#define SIFIVE_SPI_TXDATA_DATA_MASK 0xffU
+#define SIFIVE_SPI_TXDATA_FULL BIT(31)
+
+/* rxdata bits */
+#define SIFIVE_SPI_RXDATA_DATA_MASK 0xffU
+#define SIFIVE_SPI_RXDATA_EMPTY BIT(31)
+
+/* ie and ip bits */
+#define SIFIVE_SPI_IP_TXWM BIT(0)
+#define SIFIVE_SPI_IP_RXWM BIT(1)
+
+struct sifive_spi {
+ void __iomem *regs; /* virt. address of control registers */
+ struct clk *clk; /* bus clock */
+ unsigned int fifo_depth; /* fifo depth in words */
+ u32 cs_inactive; /* level of the CS pins when inactive */
+ struct completion done; /* wake-up from interrupt */
+};
+
+static void sifive_spi_write(struct sifive_spi *spi, int offset, u32 value)
+{
+ iowrite32(value, spi->regs + offset);
+}
+
+static u32 sifive_spi_read(struct sifive_spi *spi, int offset)
+{
+ return ioread32(spi->regs + offset);
+}
+
+static void sifive_spi_init(struct sifive_spi *spi)
+{
+ /* Watermark interrupts are disabled by default */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0);
+
+ /* Default watermark FIFO threshold values */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_TXMARK, 1);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK, 0);
+
+ /* Set CS/SCK Delays and Inactive Time to defaults */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY0,
+ SIFIVE_SPI_DELAY0_CSSCK(1) |
+ SIFIVE_SPI_DELAY0_SCKCS(1));
+ sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY1,
+ SIFIVE_SPI_DELAY1_INTERCS(1) |
+ SIFIVE_SPI_DELAY1_INTERXFR(0));
+
+ /* Exit specialized memory-mapped SPI flash mode */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_FCTRL, 0);
+}
+
+static int
+sifive_spi_prepare_message(struct spi_master *master, struct spi_message *msg)
+{
+ struct sifive_spi *spi = spi_master_get_devdata(master);
+ struct spi_device *device = msg->spi;
+
+ /* Update the chip select polarity */
+ if (device->mode & SPI_CS_HIGH)
+ spi->cs_inactive &= ~BIT(device->chip_select);
+ else
+ spi->cs_inactive |= BIT(device->chip_select);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive);
+
+ /* Select the correct device */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_CSID, device->chip_select);
+
+ /* Set clock mode */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_SCKMODE,
+ device->mode & SIFIVE_SPI_SCKMODE_MODE_MASK);
+
+ return 0;
+}
+
+static void sifive_spi_set_cs(struct spi_device *device, bool is_high)
+{
+ struct sifive_spi *spi = spi_master_get_devdata(device->master);
+
+ /* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */
+ if (device->mode & SPI_CS_HIGH)
+ is_high = !is_high;
+
+ sifive_spi_write(spi, SIFIVE_SPI_REG_CSMODE, is_high ?
+ SIFIVE_SPI_CSMODE_MODE_AUTO :
+ SIFIVE_SPI_CSMODE_MODE_HOLD);
+}
+
+static int
+sifive_spi_prep_transfer(struct sifive_spi *spi, struct spi_device *device,
+ struct spi_transfer *t)
+{
+ u32 cr;
+ unsigned int mode;
+
+ /* Calculate and program the clock rate */
+ cr = DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, t->speed_hz) - 1;
+ cr &= SIFIVE_SPI_SCKDIV_DIV_MASK;
+ sifive_spi_write(spi, SIFIVE_SPI_REG_SCKDIV, cr);
+
+ mode = max_t(unsigned int, t->rx_nbits, t->tx_nbits);
+
+ /* Set frame format */
+ cr = SIFIVE_SPI_FMT_LEN(t->bits_per_word);
+ switch (mode) {
+ case SPI_NBITS_QUAD:
+ cr |= SIFIVE_SPI_FMT_PROTO_QUAD;
+ break;
+ case SPI_NBITS_DUAL:
+ cr |= SIFIVE_SPI_FMT_PROTO_DUAL;
+ break;
+ default:
+ cr |= SIFIVE_SPI_FMT_PROTO_SINGLE;
+ break;
+ }
+ if (device->mode & SPI_LSB_FIRST)
+ cr |= SIFIVE_SPI_FMT_ENDIAN;
+ if (!t->rx_buf)
+ cr |= SIFIVE_SPI_FMT_DIR;
+ sifive_spi_write(spi, SIFIVE_SPI_REG_FMT, cr);
+
+ /* We will want to poll if the time we need to wait is
+ * less than the context switching time.
+ * Let's call that threshold 5us. The operation will take:
+ * (8/mode) * fifo_depth / hz <= 5 * 10^-6
+ * 1600000 * fifo_depth <= hz * mode
+ */
+ return 1600000 * spi->fifo_depth <= t->speed_hz * mode;
+}
+
+static irqreturn_t sifive_spi_irq(int irq, void *dev_id)
+{
+ struct sifive_spi *spi = dev_id;
+ u32 ip = sifive_spi_read(spi, SIFIVE_SPI_REG_IP);
+
+ if (ip & (SIFIVE_SPI_IP_TXWM | SIFIVE_SPI_IP_RXWM)) {
+ /* Disable interrupts until next transfer */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0);
+ complete(&spi->done);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static void sifive_spi_wait(struct sifive_spi *spi, u32 bit, int poll)
+{
+ if (poll) {
+ u32 cr;
+
+ do {
+ cr = sifive_spi_read(spi, SIFIVE_SPI_REG_IP);
+ } while (!(cr & bit));
+ } else {
+ reinit_completion(&spi->done);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, bit);
+ wait_for_completion(&spi->done);
+ }
+}
+
+static void sifive_spi_tx(struct sifive_spi *spi, const u8 *tx_ptr)
+{
+ WARN_ON_ONCE((sifive_spi_read(spi, SIFIVE_SPI_REG_TXDATA)
+ & SIFIVE_SPI_TXDATA_FULL) != 0);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_TXDATA,
+ *tx_ptr & SIFIVE_SPI_TXDATA_DATA_MASK);
+}
+
+static void sifive_spi_rx(struct sifive_spi *spi, u8 *rx_ptr)
+{
+ u32 data = sifive_spi_read(spi, SIFIVE_SPI_REG_RXDATA);
+
+ WARN_ON_ONCE((data & SIFIVE_SPI_RXDATA_EMPTY) != 0);
+ *rx_ptr = data & SIFIVE_SPI_RXDATA_DATA_MASK;
+}
+
+static int
+sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device,
+ struct spi_transfer *t)
+{
+ struct sifive_spi *spi = spi_master_get_devdata(master);
+ int poll = sifive_spi_prep_transfer(spi, device, t);
+ const u8 *tx_ptr = t->tx_buf;
+ u8 *rx_ptr = t->rx_buf;
+ unsigned int remaining_words = t->len;
+
+ while (remaining_words) {
+ unsigned int n_words = min(remaining_words, spi->fifo_depth);
+ unsigned int i;
+
+ /* Enqueue n_words for transmission */
+ for (i = 0; i < n_words; i++)
+ sifive_spi_tx(spi, tx_ptr++);
+
+ if (rx_ptr) {
+ /* Wait for transmission + reception to complete */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK,
+ n_words - 1);
+ sifive_spi_wait(spi, SIFIVE_SPI_IP_RXWM, poll);
+
+ /* Read out all the data from the RX FIFO */
+ for (i = 0; i < n_words; i++)
+ sifive_spi_rx(spi, rx_ptr++);
+ } else {
+ /* Wait for transmission to complete */
+ sifive_spi_wait(spi, SIFIVE_SPI_IP_TXWM, poll);
+ }
+
+ remaining_words -= n_words;
+ }
+
+ return 0;
+}
+
+static int sifive_spi_probe(struct platform_device *pdev)
+{
+ struct sifive_spi *spi;
+ struct resource *res;
+ int ret, irq, num_cs;
+ u32 cs_bits, max_bits_per_word;
+ struct spi_master *master;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(struct sifive_spi));
+ if (!master) {
+ dev_err(&pdev->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ spi = spi_master_get_devdata(master);
+ init_completion(&spi->done);
+ platform_set_drvdata(pdev, master);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ spi->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(spi->regs)) {
+ ret = PTR_ERR(spi->regs);
+ goto put_master;
+ }
+
+ spi->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(spi->clk)) {
+ dev_err(&pdev->dev, "Unable to find bus clock\n");
+ ret = PTR_ERR(spi->clk);
+ goto put_master;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Unable to find interrupt\n");
+ ret = irq;
+ goto put_master;
+ }
+
+ /* Optional parameters */
+ ret =
+ of_property_read_u32(pdev->dev.of_node, "sifive,fifo-depth",
+ &spi->fifo_depth);
+ if (ret < 0)
+ spi->fifo_depth = SIFIVE_SPI_DEFAULT_DEPTH;
+
+ ret =
+ of_property_read_u32(pdev->dev.of_node, "sifive,max-bits-per-word",
+ &max_bits_per_word);
+
+ if (!ret && max_bits_per_word < 8) {
+ dev_err(&pdev->dev, "Only 8bit SPI words supported by the driver\n");
+ ret = -EINVAL;
+ goto put_master;
+ }
+
+ /* Spin up the bus clock before hitting registers */
+ ret = clk_prepare_enable(spi->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable bus clock\n");
+ goto put_master;
+ }
+
+ /* probe the number of CS lines */
+ spi->cs_inactive = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, 0xffffffffU);
+ cs_bits = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF);
+ sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive);
+ if (!cs_bits) {
+ dev_err(&pdev->dev, "Could not auto probe CS lines\n");
+ ret = -EINVAL;
+ goto put_master;
+ }
+
+ num_cs = ilog2(cs_bits) + 1;
+ if (num_cs > SIFIVE_SPI_MAX_CS) {
+ dev_err(&pdev->dev, "Invalid number of spi slaves\n");
+ ret = -EINVAL;
+ goto put_master;
+ }
+
+ /* Define our master */
+ master->dev.of_node = pdev->dev.of_node;
+ master->bus_num = pdev->id;
+ master->num_chipselect = num_cs;
+ master->mode_bits = SPI_CPHA | SPI_CPOL
+ | SPI_CS_HIGH | SPI_LSB_FIRST
+ | SPI_TX_DUAL | SPI_TX_QUAD
+ | SPI_RX_DUAL | SPI_RX_QUAD;
+ /* TODO: add driver support for bits_per_word < 8
+ * we need to "left-align" the bits (unless SPI_LSB_FIRST)
+ */
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->flags = SPI_CONTROLLER_MUST_TX | SPI_MASTER_GPIO_SS;
+ master->prepare_message = sifive_spi_prepare_message;
+ master->set_cs = sifive_spi_set_cs;
+ master->transfer_one = sifive_spi_transfer_one;
+
+ pdev->dev.dma_mask = NULL;
+ /* Configure the SPI master hardware */
+ sifive_spi_init(spi);
+
+ /* Register for SPI Interrupt */
+ ret = devm_request_irq(&pdev->dev, irq, sifive_spi_irq, 0,
+ dev_name(&pdev->dev), spi);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to bind to interrupt\n");
+ goto put_master;
+ }
+
+ dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n",
+ irq, master->num_chipselect);
+
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "spi_register_master failed\n");
+ goto put_master;
+ }
+
+ return 0;
+
+put_master:
+ spi_master_put(master);
+
+ return ret;
+}
+
+static int sifive_spi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct sifive_spi *spi = spi_master_get_devdata(master);
+
+ /* Disable all the interrupts just in case */
+ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0);
+
+ return 0;
+}
+
+static const struct of_device_id sifive_spi_of_match[] = {
+ { .compatible = "sifive,spi0", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sifive_spi_of_match);
+
+static struct platform_driver sifive_spi_driver = {
+ .probe = sifive_spi_probe,
+ .remove = sifive_spi_remove,
+ .driver = {
+ .name = SIFIVE_SPI_DRIVER_NAME,
+ .of_match_table = sifive_spi_of_match,
+ },
+};
+module_platform_driver(sifive_spi_driver);
+
+MODULE_AUTHOR("SiFive, Inc. <sifive@sifive.com>");
+MODULE_DESCRIPTION("SiFive SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c
index 8daa24eec624..1b7eebb72c07 100644
--- a/drivers/spi/spi-sprd.c
+++ b/drivers/spi/spi-sprd.c
@@ -2,6 +2,9 @@
// Copyright (C) 2018 Spreadtrum Communications Inc.
#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/sprd-dma.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -9,6 +12,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_dma.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
@@ -128,11 +132,28 @@
#define SPRD_SPI_DEFAULT_SOURCE 26000000
#define SPRD_SPI_MAX_SPEED_HZ 48000000
#define SPRD_SPI_AUTOSUSPEND_DELAY 100
+#define SPRD_SPI_DMA_STEP 8
+
+enum sprd_spi_dma_channel {
+ SPRD_SPI_RX,
+ SPRD_SPI_TX,
+ SPRD_SPI_MAX,
+};
+
+struct sprd_spi_dma {
+ bool enable;
+ struct dma_chan *dma_chan[SPRD_SPI_MAX];
+ enum dma_slave_buswidth width;
+ u32 fragmens_len;
+ u32 rx_len;
+};
struct sprd_spi {
void __iomem *base;
+ phys_addr_t phy_base;
struct device *dev;
struct clk *clk;
+ int irq;
u32 src_clk;
u32 hw_mode;
u32 trans_len;
@@ -141,6 +162,8 @@ struct sprd_spi {
u32 hw_speed_hz;
u32 len;
int status;
+ struct sprd_spi_dma dma;
+ struct completion xfer_completion;
const void *tx_buf;
void *rx_buf;
int (*read_bufs)(struct sprd_spi *ss, u32 len);
@@ -380,7 +403,7 @@ static int sprd_spi_txrx_bufs(struct spi_device *sdev, struct spi_transfer *t)
{
struct sprd_spi *ss = spi_controller_get_devdata(sdev->controller);
u32 trans_len = ss->trans_len, len;
- int ret, write_size = 0;
+ int ret, write_size = 0, read_size = 0;
while (trans_len) {
len = trans_len > SPRD_SPI_FIFO_SIZE ? SPRD_SPI_FIFO_SIZE :
@@ -416,19 +439,223 @@ static int sprd_spi_txrx_bufs(struct spi_device *sdev, struct spi_transfer *t)
goto complete;
if (ss->trans_mode & SPRD_SPI_RX_MODE)
- ss->read_bufs(ss, len);
+ read_size += ss->read_bufs(ss, len);
trans_len -= len;
}
- ret = write_size;
-
+ if (ss->trans_mode & SPRD_SPI_TX_MODE)
+ ret = write_size;
+ else
+ ret = read_size;
complete:
sprd_spi_enter_idle(ss);
return ret;
}
+static void sprd_spi_irq_enable(struct sprd_spi *ss)
+{
+ u32 val;
+
+ /* Clear interrupt status before enabling interrupt. */
+ writel_relaxed(SPRD_SPI_TX_END_CLR | SPRD_SPI_RX_END_CLR,
+ ss->base + SPRD_SPI_INT_CLR);
+ /* Enable SPI interrupt only in DMA mode. */
+ val = readl_relaxed(ss->base + SPRD_SPI_INT_EN);
+ writel_relaxed(val | SPRD_SPI_TX_END_INT_EN |
+ SPRD_SPI_RX_END_INT_EN,
+ ss->base + SPRD_SPI_INT_EN);
+}
+
+static void sprd_spi_irq_disable(struct sprd_spi *ss)
+{
+ writel_relaxed(0, ss->base + SPRD_SPI_INT_EN);
+}
+
+static void sprd_spi_dma_enable(struct sprd_spi *ss, bool enable)
+{
+ u32 val = readl_relaxed(ss->base + SPRD_SPI_CTL2);
+
+ if (enable)
+ val |= SPRD_SPI_DMA_EN;
+ else
+ val &= ~SPRD_SPI_DMA_EN;
+
+ writel_relaxed(val, ss->base + SPRD_SPI_CTL2);
+}
+
+static int sprd_spi_dma_submit(struct dma_chan *dma_chan,
+ struct dma_slave_config *c,
+ struct sg_table *sg,
+ enum dma_transfer_direction dir)
+{
+ struct dma_async_tx_descriptor *desc;
+ dma_cookie_t cookie;
+ unsigned long flags;
+ int ret;
+
+ ret = dmaengine_slave_config(dma_chan, c);
+ if (ret < 0)
+ return ret;
+
+ flags = SPRD_DMA_FLAGS(SPRD_DMA_CHN_MODE_NONE, SPRD_DMA_NO_TRG,
+ SPRD_DMA_FRAG_REQ, SPRD_DMA_TRANS_INT);
+ desc = dmaengine_prep_slave_sg(dma_chan, sg->sgl, sg->nents, dir, flags);
+ if (!desc)
+ return -ENODEV;
+
+ cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie))
+ return dma_submit_error(cookie);
+
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int sprd_spi_dma_rx_config(struct sprd_spi *ss, struct spi_transfer *t)
+{
+ struct dma_chan *dma_chan = ss->dma.dma_chan[SPRD_SPI_RX];
+ struct dma_slave_config config = {
+ .src_addr = ss->phy_base,
+ .src_addr_width = ss->dma.width,
+ .dst_addr_width = ss->dma.width,
+ .dst_maxburst = ss->dma.fragmens_len,
+ };
+ int ret;
+
+ ret = sprd_spi_dma_submit(dma_chan, &config, &t->rx_sg, DMA_DEV_TO_MEM);
+ if (ret)
+ return ret;
+
+ return ss->dma.rx_len;
+}
+
+static int sprd_spi_dma_tx_config(struct sprd_spi *ss, struct spi_transfer *t)
+{
+ struct dma_chan *dma_chan = ss->dma.dma_chan[SPRD_SPI_TX];
+ struct dma_slave_config config = {
+ .dst_addr = ss->phy_base,
+ .src_addr_width = ss->dma.width,
+ .dst_addr_width = ss->dma.width,
+ .src_maxburst = ss->dma.fragmens_len,
+ };
+ int ret;
+
+ ret = sprd_spi_dma_submit(dma_chan, &config, &t->tx_sg, DMA_MEM_TO_DEV);
+ if (ret)
+ return ret;
+
+ return t->len;
+}
+
+static int sprd_spi_dma_request(struct sprd_spi *ss)
+{
+ ss->dma.dma_chan[SPRD_SPI_RX] = dma_request_chan(ss->dev, "rx_chn");
+ if (IS_ERR_OR_NULL(ss->dma.dma_chan[SPRD_SPI_RX])) {
+ if (PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]) == -EPROBE_DEFER)
+ return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]);
+
+ dev_err(ss->dev, "request RX DMA channel failed!\n");
+ return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_RX]);
+ }
+
+ ss->dma.dma_chan[SPRD_SPI_TX] = dma_request_chan(ss->dev, "tx_chn");
+ if (IS_ERR_OR_NULL(ss->dma.dma_chan[SPRD_SPI_TX])) {
+ if (PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]) == -EPROBE_DEFER)
+ return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]);
+
+ dev_err(ss->dev, "request TX DMA channel failed!\n");
+ dma_release_channel(ss->dma.dma_chan[SPRD_SPI_RX]);
+ return PTR_ERR(ss->dma.dma_chan[SPRD_SPI_TX]);
+ }
+
+ return 0;
+}
+
+static void sprd_spi_dma_release(struct sprd_spi *ss)
+{
+ if (ss->dma.dma_chan[SPRD_SPI_RX])
+ dma_release_channel(ss->dma.dma_chan[SPRD_SPI_RX]);
+
+ if (ss->dma.dma_chan[SPRD_SPI_TX])
+ dma_release_channel(ss->dma.dma_chan[SPRD_SPI_TX]);
+}
+
+static int sprd_spi_dma_txrx_bufs(struct spi_device *sdev,
+ struct spi_transfer *t)
+{
+ struct sprd_spi *ss = spi_master_get_devdata(sdev->master);
+ u32 trans_len = ss->trans_len;
+ int ret, write_size = 0;
+
+ reinit_completion(&ss->xfer_completion);
+ sprd_spi_irq_enable(ss);
+ if (ss->trans_mode & SPRD_SPI_TX_MODE) {
+ write_size = sprd_spi_dma_tx_config(ss, t);
+ sprd_spi_set_tx_length(ss, trans_len);
+
+ /*
+ * For our 3 wires mode or dual TX line mode, we need
+ * to request the controller to transfer.
+ */
+ if (ss->hw_mode & SPI_3WIRE || ss->hw_mode & SPI_TX_DUAL)
+ sprd_spi_tx_req(ss);
+ } else {
+ sprd_spi_set_rx_length(ss, trans_len);
+
+ /*
+ * For our 3 wires mode or dual TX line mode, we need
+ * to request the controller to read.
+ */
+ if (ss->hw_mode & SPI_3WIRE || ss->hw_mode & SPI_TX_DUAL)
+ sprd_spi_rx_req(ss);
+ else
+ write_size = ss->write_bufs(ss, trans_len);
+ }
+
+ if (write_size < 0) {
+ ret = write_size;
+ dev_err(ss->dev, "failed to write, ret = %d\n", ret);
+ goto trans_complete;
+ }
+
+ if (ss->trans_mode & SPRD_SPI_RX_MODE) {
+ /*
+ * Set up the DMA receive data length, which must be an
+ * integral multiple of fragment length. But when the length
+ * of received data is less than fragment length, DMA can be
+ * configured to receive data according to the actual length
+ * of received data.
+ */
+ ss->dma.rx_len = t->len > ss->dma.fragmens_len ?
+ (t->len - t->len % ss->dma.fragmens_len) :
+ t->len;
+ ret = sprd_spi_dma_rx_config(ss, t);
+ if (ret < 0) {
+ dev_err(&sdev->dev,
+ "failed to configure rx DMA, ret = %d\n", ret);
+ goto trans_complete;
+ }
+ }
+
+ sprd_spi_dma_enable(ss, true);
+ wait_for_completion(&(ss->xfer_completion));
+
+ if (ss->trans_mode & SPRD_SPI_TX_MODE)
+ ret = write_size;
+ else
+ ret = ss->dma.rx_len;
+
+trans_complete:
+ sprd_spi_dma_enable(ss, false);
+ sprd_spi_enter_idle(ss);
+ sprd_spi_irq_disable(ss);
+
+ return ret;
+}
+
static void sprd_spi_set_speed(struct sprd_spi *ss, u32 speed_hz)
{
/*
@@ -514,16 +741,22 @@ static int sprd_spi_setup_transfer(struct spi_device *sdev,
ss->trans_len = t->len;
ss->read_bufs = sprd_spi_read_bufs_u8;
ss->write_bufs = sprd_spi_write_bufs_u8;
+ ss->dma.width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ ss->dma.fragmens_len = SPRD_SPI_DMA_STEP;
break;
case 16:
ss->trans_len = t->len >> 1;
ss->read_bufs = sprd_spi_read_bufs_u16;
ss->write_bufs = sprd_spi_write_bufs_u16;
+ ss->dma.width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ ss->dma.fragmens_len = SPRD_SPI_DMA_STEP << 1;
break;
case 32:
ss->trans_len = t->len >> 2;
ss->read_bufs = sprd_spi_read_bufs_u32;
ss->write_bufs = sprd_spi_write_bufs_u32;
+ ss->dma.width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ ss->dma.fragmens_len = SPRD_SPI_DMA_STEP << 2;
break;
default:
return -EINVAL;
@@ -561,7 +794,11 @@ static int sprd_spi_transfer_one(struct spi_controller *sctlr,
if (ret)
goto setup_err;
- ret = sprd_spi_txrx_bufs(sdev, t);
+ if (sctlr->can_dma(sctlr, sdev, t))
+ ret = sprd_spi_dma_txrx_bufs(sdev, t);
+ else
+ ret = sprd_spi_txrx_bufs(sdev, t);
+
if (ret == t->len)
ret = 0;
else if (ret >= 0)
@@ -573,6 +810,53 @@ setup_err:
return ret;
}
+static irqreturn_t sprd_spi_handle_irq(int irq, void *data)
+{
+ struct sprd_spi *ss = (struct sprd_spi *)data;
+ u32 val = readl_relaxed(ss->base + SPRD_SPI_INT_MASK_STS);
+
+ if (val & SPRD_SPI_MASK_TX_END) {
+ writel_relaxed(SPRD_SPI_TX_END_CLR, ss->base + SPRD_SPI_INT_CLR);
+ if (!(ss->trans_mode & SPRD_SPI_RX_MODE))
+ complete(&ss->xfer_completion);
+
+ return IRQ_HANDLED;
+ }
+
+ if (val & SPRD_SPI_MASK_RX_END) {
+ writel_relaxed(SPRD_SPI_RX_END_CLR, ss->base + SPRD_SPI_INT_CLR);
+ if (ss->dma.rx_len < ss->len) {
+ ss->rx_buf += ss->dma.rx_len;
+ ss->dma.rx_len +=
+ ss->read_bufs(ss, ss->len - ss->dma.rx_len);
+ }
+ complete(&ss->xfer_completion);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss)
+{
+ int ret;
+
+ ss->irq = platform_get_irq(pdev, 0);
+ if (ss->irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq resource\n");
+ return ss->irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq,
+ 0, pdev->name, ss);
+ if (ret)
+ dev_err(&pdev->dev, "failed to request spi irq %d, ret = %d\n",
+ ss->irq, ret);
+
+ return ret;
+}
+
static int sprd_spi_clk_init(struct platform_device *pdev, struct sprd_spi *ss)
{
struct clk *clk_spi, *clk_parent;
@@ -603,6 +887,35 @@ static int sprd_spi_clk_init(struct platform_device *pdev, struct sprd_spi *ss)
return 0;
}
+static bool sprd_spi_can_dma(struct spi_controller *sctlr,
+ struct spi_device *spi, struct spi_transfer *t)
+{
+ struct sprd_spi *ss = spi_controller_get_devdata(sctlr);
+
+ return ss->dma.enable && (t->len > SPRD_SPI_FIFO_SIZE);
+}
+
+static int sprd_spi_dma_init(struct platform_device *pdev, struct sprd_spi *ss)
+{
+ int ret;
+
+ ret = sprd_spi_dma_request(ss);
+ if (ret) {
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ dev_warn(&pdev->dev,
+ "failed to request dma, enter no dma mode, ret = %d\n",
+ ret);
+
+ return 0;
+ }
+
+ ss->dma.enable = true;
+
+ return 0;
+}
+
static int sprd_spi_probe(struct platform_device *pdev)
{
struct spi_controller *sctlr;
@@ -623,25 +936,36 @@ static int sprd_spi_probe(struct platform_device *pdev)
goto free_controller;
}
+ ss->phy_base = res->start;
ss->dev = &pdev->dev;
sctlr->dev.of_node = pdev->dev.of_node;
sctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE | SPI_TX_DUAL;
sctlr->bus_num = pdev->id;
sctlr->set_cs = sprd_spi_chipselect;
sctlr->transfer_one = sprd_spi_transfer_one;
+ sctlr->can_dma = sprd_spi_can_dma;
sctlr->auto_runtime_pm = true;
sctlr->max_speed_hz = min_t(u32, ss->src_clk >> 1,
SPRD_SPI_MAX_SPEED_HZ);
+ init_completion(&ss->xfer_completion);
platform_set_drvdata(pdev, sctlr);
ret = sprd_spi_clk_init(pdev, ss);
if (ret)
goto free_controller;
- ret = clk_prepare_enable(ss->clk);
+ ret = sprd_spi_irq_init(pdev, ss);
if (ret)
goto free_controller;
+ ret = sprd_spi_dma_init(pdev, ss);
+ if (ret)
+ goto free_controller;
+
+ ret = clk_prepare_enable(ss->clk);
+ if (ret)
+ goto release_dma;
+
ret = pm_runtime_set_active(&pdev->dev);
if (ret < 0)
goto disable_clk;
@@ -670,6 +994,8 @@ err_rpm_put:
pm_runtime_disable(&pdev->dev);
disable_clk:
clk_disable_unprepare(ss->clk);
+release_dma:
+ sprd_spi_dma_release(ss);
free_controller:
spi_controller_put(sctlr);
@@ -688,6 +1014,10 @@ static int sprd_spi_remove(struct platform_device *pdev)
return ret;
}
+ spi_controller_suspend(sctlr);
+
+ if (ss->dma.enable)
+ sprd_spi_dma_release(ss);
clk_disable_unprepare(ss->clk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -700,6 +1030,9 @@ static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev)
struct spi_controller *sctlr = dev_get_drvdata(dev);
struct sprd_spi *ss = spi_controller_get_devdata(sctlr);
+ if (ss->dma.enable)
+ sprd_spi_dma_release(ss);
+
clk_disable_unprepare(ss->clk);
return 0;
@@ -715,7 +1048,14 @@ static int __maybe_unused sprd_spi_runtime_resume(struct device *dev)
if (ret)
return ret;
- return 0;
+ if (!ss->dma.enable)
+ return 0;
+
+ ret = sprd_spi_dma_request(ss);
+ if (ret)
+ clk_disable_unprepare(ss->clk);
+
+ return ret;
}
static const struct dev_pm_ops sprd_spi_pm_ops = {
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index ad1e55d3d5d5..4186ed20d796 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -1,23 +1,10 @@
-/*
- * STMicroelectronics STM32 SPI Controller driver (master mode only)
- *
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
- *
- * License terms: GPL V2.0.
- *
- * spi_stm32 driver 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.
- *
- * spi_stm32 driver 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
- * spi_stm32 driver. If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// STMicroelectronics STM32 SPI Controller driver (master mode only)
+//
+// Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+// Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
+
#include <linux/debugfs.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -33,99 +20,251 @@
#define DRIVER_NAME "spi_stm32"
-/* STM32 SPI registers */
-#define STM32_SPI_CR1 0x00
-#define STM32_SPI_CR2 0x04
-#define STM32_SPI_CFG1 0x08
-#define STM32_SPI_CFG2 0x0C
-#define STM32_SPI_IER 0x10
-#define STM32_SPI_SR 0x14
-#define STM32_SPI_IFCR 0x18
-#define STM32_SPI_TXDR 0x20
-#define STM32_SPI_RXDR 0x30
-#define STM32_SPI_I2SCFGR 0x50
-
-/* STM32_SPI_CR1 bit fields */
-#define SPI_CR1_SPE BIT(0)
-#define SPI_CR1_MASRX BIT(8)
-#define SPI_CR1_CSTART BIT(9)
-#define SPI_CR1_CSUSP BIT(10)
-#define SPI_CR1_HDDIR BIT(11)
-#define SPI_CR1_SSI BIT(12)
-
-/* STM32_SPI_CR2 bit fields */
-#define SPI_CR2_TSIZE_SHIFT 0
-#define SPI_CR2_TSIZE GENMASK(15, 0)
-
-/* STM32_SPI_CFG1 bit fields */
-#define SPI_CFG1_DSIZE_SHIFT 0
-#define SPI_CFG1_DSIZE GENMASK(4, 0)
-#define SPI_CFG1_FTHLV_SHIFT 5
-#define SPI_CFG1_FTHLV GENMASK(8, 5)
-#define SPI_CFG1_RXDMAEN BIT(14)
-#define SPI_CFG1_TXDMAEN BIT(15)
-#define SPI_CFG1_MBR_SHIFT 28
-#define SPI_CFG1_MBR GENMASK(30, 28)
-#define SPI_CFG1_MBR_MIN 0
-#define SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28)
-
-/* STM32_SPI_CFG2 bit fields */
-#define SPI_CFG2_MIDI_SHIFT 4
-#define SPI_CFG2_MIDI GENMASK(7, 4)
-#define SPI_CFG2_COMM_SHIFT 17
-#define SPI_CFG2_COMM GENMASK(18, 17)
-#define SPI_CFG2_SP_SHIFT 19
-#define SPI_CFG2_SP GENMASK(21, 19)
-#define SPI_CFG2_MASTER BIT(22)
-#define SPI_CFG2_LSBFRST BIT(23)
-#define SPI_CFG2_CPHA BIT(24)
-#define SPI_CFG2_CPOL BIT(25)
-#define SPI_CFG2_SSM BIT(26)
-#define SPI_CFG2_AFCNTR BIT(31)
-
-/* STM32_SPI_IER bit fields */
-#define SPI_IER_RXPIE BIT(0)
-#define SPI_IER_TXPIE BIT(1)
-#define SPI_IER_DXPIE BIT(2)
-#define SPI_IER_EOTIE BIT(3)
-#define SPI_IER_TXTFIE BIT(4)
-#define SPI_IER_OVRIE BIT(6)
-#define SPI_IER_MODFIE BIT(9)
-#define SPI_IER_ALL GENMASK(10, 0)
-
-/* STM32_SPI_SR bit fields */
-#define SPI_SR_RXP BIT(0)
-#define SPI_SR_TXP BIT(1)
-#define SPI_SR_EOT BIT(3)
-#define SPI_SR_OVR BIT(6)
-#define SPI_SR_MODF BIT(9)
-#define SPI_SR_SUSP BIT(11)
-#define SPI_SR_RXPLVL_SHIFT 13
-#define SPI_SR_RXPLVL GENMASK(14, 13)
-#define SPI_SR_RXWNE BIT(15)
-
-/* STM32_SPI_IFCR bit fields */
-#define SPI_IFCR_ALL GENMASK(11, 3)
-
-/* STM32_SPI_I2SCFGR bit fields */
-#define SPI_I2SCFGR_I2SMOD BIT(0)
-
-/* SPI Master Baud Rate min/max divisor */
-#define SPI_MBR_DIV_MIN (2 << SPI_CFG1_MBR_MIN)
-#define SPI_MBR_DIV_MAX (2 << SPI_CFG1_MBR_MAX)
-
-/* SPI Communication mode */
+/* STM32F4 SPI registers */
+#define STM32F4_SPI_CR1 0x00
+#define STM32F4_SPI_CR2 0x04
+#define STM32F4_SPI_SR 0x08
+#define STM32F4_SPI_DR 0x0C
+#define STM32F4_SPI_I2SCFGR 0x1C
+
+/* STM32F4_SPI_CR1 bit fields */
+#define STM32F4_SPI_CR1_CPHA BIT(0)
+#define STM32F4_SPI_CR1_CPOL BIT(1)
+#define STM32F4_SPI_CR1_MSTR BIT(2)
+#define STM32F4_SPI_CR1_BR_SHIFT 3
+#define STM32F4_SPI_CR1_BR GENMASK(5, 3)
+#define STM32F4_SPI_CR1_SPE BIT(6)
+#define STM32F4_SPI_CR1_LSBFRST BIT(7)
+#define STM32F4_SPI_CR1_SSI BIT(8)
+#define STM32F4_SPI_CR1_SSM BIT(9)
+#define STM32F4_SPI_CR1_RXONLY BIT(10)
+#define STM32F4_SPI_CR1_DFF BIT(11)
+#define STM32F4_SPI_CR1_CRCNEXT BIT(12)
+#define STM32F4_SPI_CR1_CRCEN BIT(13)
+#define STM32F4_SPI_CR1_BIDIOE BIT(14)
+#define STM32F4_SPI_CR1_BIDIMODE BIT(15)
+#define STM32F4_SPI_CR1_BR_MIN 0
+#define STM32F4_SPI_CR1_BR_MAX (GENMASK(5, 3) >> 3)
+
+/* STM32F4_SPI_CR2 bit fields */
+#define STM32F4_SPI_CR2_RXDMAEN BIT(0)
+#define STM32F4_SPI_CR2_TXDMAEN BIT(1)
+#define STM32F4_SPI_CR2_SSOE BIT(2)
+#define STM32F4_SPI_CR2_FRF BIT(4)
+#define STM32F4_SPI_CR2_ERRIE BIT(5)
+#define STM32F4_SPI_CR2_RXNEIE BIT(6)
+#define STM32F4_SPI_CR2_TXEIE BIT(7)
+
+/* STM32F4_SPI_SR bit fields */
+#define STM32F4_SPI_SR_RXNE BIT(0)
+#define STM32F4_SPI_SR_TXE BIT(1)
+#define STM32F4_SPI_SR_CHSIDE BIT(2)
+#define STM32F4_SPI_SR_UDR BIT(3)
+#define STM32F4_SPI_SR_CRCERR BIT(4)
+#define STM32F4_SPI_SR_MODF BIT(5)
+#define STM32F4_SPI_SR_OVR BIT(6)
+#define STM32F4_SPI_SR_BSY BIT(7)
+#define STM32F4_SPI_SR_FRE BIT(8)
+
+/* STM32F4_SPI_I2SCFGR bit fields */
+#define STM32F4_SPI_I2SCFGR_I2SMOD BIT(11)
+
+/* STM32F4 SPI Baud Rate min/max divisor */
+#define STM32F4_SPI_BR_DIV_MIN (2 << STM32F4_SPI_CR1_BR_MIN)
+#define STM32F4_SPI_BR_DIV_MAX (2 << STM32F4_SPI_CR1_BR_MAX)
+
+/* STM32H7 SPI registers */
+#define STM32H7_SPI_CR1 0x00
+#define STM32H7_SPI_CR2 0x04
+#define STM32H7_SPI_CFG1 0x08
+#define STM32H7_SPI_CFG2 0x0C
+#define STM32H7_SPI_IER 0x10
+#define STM32H7_SPI_SR 0x14
+#define STM32H7_SPI_IFCR 0x18
+#define STM32H7_SPI_TXDR 0x20
+#define STM32H7_SPI_RXDR 0x30
+#define STM32H7_SPI_I2SCFGR 0x50
+
+/* STM32H7_SPI_CR1 bit fields */
+#define STM32H7_SPI_CR1_SPE BIT(0)
+#define STM32H7_SPI_CR1_MASRX BIT(8)
+#define STM32H7_SPI_CR1_CSTART BIT(9)
+#define STM32H7_SPI_CR1_CSUSP BIT(10)
+#define STM32H7_SPI_CR1_HDDIR BIT(11)
+#define STM32H7_SPI_CR1_SSI BIT(12)
+
+/* STM32H7_SPI_CR2 bit fields */
+#define STM32H7_SPI_CR2_TSIZE_SHIFT 0
+#define STM32H7_SPI_CR2_TSIZE GENMASK(15, 0)
+
+/* STM32H7_SPI_CFG1 bit fields */
+#define STM32H7_SPI_CFG1_DSIZE_SHIFT 0
+#define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0)
+#define STM32H7_SPI_CFG1_FTHLV_SHIFT 5
+#define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5)
+#define STM32H7_SPI_CFG1_RXDMAEN BIT(14)
+#define STM32H7_SPI_CFG1_TXDMAEN BIT(15)
+#define STM32H7_SPI_CFG1_MBR_SHIFT 28
+#define STM32H7_SPI_CFG1_MBR GENMASK(30, 28)
+#define STM32H7_SPI_CFG1_MBR_MIN 0
+#define STM32H7_SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28)
+
+/* STM32H7_SPI_CFG2 bit fields */
+#define STM32H7_SPI_CFG2_MIDI_SHIFT 4
+#define STM32H7_SPI_CFG2_MIDI GENMASK(7, 4)
+#define STM32H7_SPI_CFG2_COMM_SHIFT 17
+#define STM32H7_SPI_CFG2_COMM GENMASK(18, 17)
+#define STM32H7_SPI_CFG2_SP_SHIFT 19
+#define STM32H7_SPI_CFG2_SP GENMASK(21, 19)
+#define STM32H7_SPI_CFG2_MASTER BIT(22)
+#define STM32H7_SPI_CFG2_LSBFRST BIT(23)
+#define STM32H7_SPI_CFG2_CPHA BIT(24)
+#define STM32H7_SPI_CFG2_CPOL BIT(25)
+#define STM32H7_SPI_CFG2_SSM BIT(26)
+#define STM32H7_SPI_CFG2_AFCNTR BIT(31)
+
+/* STM32H7_SPI_IER bit fields */
+#define STM32H7_SPI_IER_RXPIE BIT(0)
+#define STM32H7_SPI_IER_TXPIE BIT(1)
+#define STM32H7_SPI_IER_DXPIE BIT(2)
+#define STM32H7_SPI_IER_EOTIE BIT(3)
+#define STM32H7_SPI_IER_TXTFIE BIT(4)
+#define STM32H7_SPI_IER_OVRIE BIT(6)
+#define STM32H7_SPI_IER_MODFIE BIT(9)
+#define STM32H7_SPI_IER_ALL GENMASK(10, 0)
+
+/* STM32H7_SPI_SR bit fields */
+#define STM32H7_SPI_SR_RXP BIT(0)
+#define STM32H7_SPI_SR_TXP BIT(1)
+#define STM32H7_SPI_SR_EOT BIT(3)
+#define STM32H7_SPI_SR_OVR BIT(6)
+#define STM32H7_SPI_SR_MODF BIT(9)
+#define STM32H7_SPI_SR_SUSP BIT(11)
+#define STM32H7_SPI_SR_RXPLVL_SHIFT 13
+#define STM32H7_SPI_SR_RXPLVL GENMASK(14, 13)
+#define STM32H7_SPI_SR_RXWNE BIT(15)
+
+/* STM32H7_SPI_IFCR bit fields */
+#define STM32H7_SPI_IFCR_ALL GENMASK(11, 3)
+
+/* STM32H7_SPI_I2SCFGR bit fields */
+#define STM32H7_SPI_I2SCFGR_I2SMOD BIT(0)
+
+/* STM32H7 SPI Master Baud Rate min/max divisor */
+#define STM32H7_SPI_MBR_DIV_MIN (2 << STM32H7_SPI_CFG1_MBR_MIN)
+#define STM32H7_SPI_MBR_DIV_MAX (2 << STM32H7_SPI_CFG1_MBR_MAX)
+
+/* STM32H7 SPI Communication mode */
+#define STM32H7_SPI_FULL_DUPLEX 0
+#define STM32H7_SPI_SIMPLEX_TX 1
+#define STM32H7_SPI_SIMPLEX_RX 2
+#define STM32H7_SPI_HALF_DUPLEX 3
+
+/* SPI Communication type */
#define SPI_FULL_DUPLEX 0
#define SPI_SIMPLEX_TX 1
#define SPI_SIMPLEX_RX 2
-#define SPI_HALF_DUPLEX 3
+#define SPI_3WIRE_TX 3
+#define SPI_3WIRE_RX 4
#define SPI_1HZ_NS 1000000000
+/*
+ * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers
+ * without fifo buffers.
+ */
+#define SPI_DMA_MIN_BYTES 16
+
+/**
+ * stm32_spi_reg - stm32 SPI register & bitfield desc
+ * @reg: register offset
+ * @mask: bitfield mask
+ * @shift: left shift
+ */
+struct stm32_spi_reg {
+ int reg;
+ int mask;
+ int shift;
+};
+
+/**
+ * stm32_spi_regspec - stm32 registers definition, compatible dependent data
+ * en: enable register and SPI enable bit
+ * dma_rx_en: SPI DMA RX enable register end SPI DMA RX enable bit
+ * dma_tx_en: SPI DMA TX enable register end SPI DMA TX enable bit
+ * cpol: clock polarity register and polarity bit
+ * cpha: clock phase register and phase bit
+ * lsb_first: LSB transmitted first register and bit
+ * br: baud rate register and bitfields
+ * rx: SPI RX data register
+ * tx: SPI TX data register
+ */
+struct stm32_spi_regspec {
+ const struct stm32_spi_reg en;
+ const struct stm32_spi_reg dma_rx_en;
+ const struct stm32_spi_reg dma_tx_en;
+ const struct stm32_spi_reg cpol;
+ const struct stm32_spi_reg cpha;
+ const struct stm32_spi_reg lsb_first;
+ const struct stm32_spi_reg br;
+ const struct stm32_spi_reg rx;
+ const struct stm32_spi_reg tx;
+};
+
+struct stm32_spi;
+
+/**
+ * stm32_spi_cfg - stm32 compatible configuration data
+ * @regs: registers descriptions
+ * @get_fifo_size: routine to get fifo size
+ * @get_bpw_mask: routine to get bits per word mask
+ * @disable: routine to disable controller
+ * @config: routine to configure controller as SPI Master
+ * @set_bpw: routine to configure registers to for bits per word
+ * @set_mode: routine to configure registers to desired mode
+ * @set_data_idleness: optional routine to configure registers to desired idle
+ * time between frames (if driver has this functionality)
+ * set_number_of_data: optional routine to configure registers to desired
+ * number of data (if driver has this functionality)
+ * @can_dma: routine to determine if the transfer is eligible for DMA use
+ * @transfer_one_dma_start: routine to start transfer a single spi_transfer
+ * using DMA
+ * @dma_rx cb: routine to call after DMA RX channel operation is complete
+ * @dma_tx cb: routine to call after DMA TX channel operation is complete
+ * @transfer_one_irq: routine to configure interrupts for driver
+ * @irq_handler_event: Interrupt handler for SPI controller events
+ * @irq_handler_thread: thread of interrupt handler for SPI controller
+ * @baud_rate_div_min: minimum baud rate divisor
+ * @baud_rate_div_max: maximum baud rate divisor
+ * @has_fifo: boolean to know if fifo is used for driver
+ * @has_startbit: boolean to know if start bit is used to start transfer
+ */
+struct stm32_spi_cfg {
+ const struct stm32_spi_regspec *regs;
+ int (*get_fifo_size)(struct stm32_spi *spi);
+ int (*get_bpw_mask)(struct stm32_spi *spi);
+ void (*disable)(struct stm32_spi *spi);
+ int (*config)(struct stm32_spi *spi);
+ void (*set_bpw)(struct stm32_spi *spi);
+ int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type);
+ void (*set_data_idleness)(struct stm32_spi *spi, u32 length);
+ int (*set_number_of_data)(struct stm32_spi *spi, u32 length);
+ void (*transfer_one_dma_start)(struct stm32_spi *spi);
+ void (*dma_rx_cb)(void *data);
+ void (*dma_tx_cb)(void *data);
+ int (*transfer_one_irq)(struct stm32_spi *spi);
+ irqreturn_t (*irq_handler_event)(int irq, void *dev_id);
+ irqreturn_t (*irq_handler_thread)(int irq, void *dev_id);
+ unsigned int baud_rate_div_min;
+ unsigned int baud_rate_div_max;
+ bool has_fifo;
+};
+
/**
* struct stm32_spi - private data of the SPI controller
* @dev: driver model representation of the controller
* @master: controller master interface
+ * @cfg: compatible configuration data
* @base: virtual memory area
* @clk: hw kernel clock feeding the SPI clock generator
* @clk_rate: rate of the hw kernel clock feeding the SPI clock generator
@@ -151,6 +290,7 @@
struct stm32_spi {
struct device *dev;
struct spi_master *master;
+ const struct stm32_spi_cfg *cfg;
void __iomem *base;
struct clk *clk;
u32 clk_rate;
@@ -176,6 +316,40 @@ struct stm32_spi {
dma_addr_t phys_addr;
};
+static const struct stm32_spi_regspec stm32f4_spi_regspec = {
+ .en = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE },
+
+ .dma_rx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_RXDMAEN },
+ .dma_tx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN },
+
+ .cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL },
+ .cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA },
+ .lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST },
+ .br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT },
+
+ .rx = { STM32F4_SPI_DR },
+ .tx = { STM32F4_SPI_DR },
+};
+
+static const struct stm32_spi_regspec stm32h7_spi_regspec = {
+ /* SPI data transfer is enabled but spi_ker_ck is idle.
+ * CFG1 and CFG2 registers are write protected when SPE is enabled.
+ */
+ .en = { STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE },
+
+ .dma_rx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN },
+ .dma_tx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN },
+
+ .cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL },
+ .cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA },
+ .lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST },
+ .br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR,
+ STM32H7_SPI_CFG1_MBR_SHIFT },
+
+ .rx = { STM32H7_SPI_RXDR },
+ .tx = { STM32H7_SPI_TXDR },
+};
+
static inline void stm32_spi_set_bits(struct stm32_spi *spi,
u32 offset, u32 bits)
{
@@ -191,22 +365,22 @@ static inline void stm32_spi_clr_bits(struct stm32_spi *spi,
}
/**
- * stm32_spi_get_fifo_size - Return fifo size
+ * stm32h7_spi_get_fifo_size - Return fifo size
* @spi: pointer to the spi controller data structure
*/
-static int stm32_spi_get_fifo_size(struct stm32_spi *spi)
+static int stm32h7_spi_get_fifo_size(struct stm32_spi *spi)
{
unsigned long flags;
u32 count = 0;
spin_lock_irqsave(&spi->lock, flags);
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
- while (readl_relaxed(spi->base + STM32_SPI_SR) & SPI_SR_TXP)
- writeb_relaxed(++count, spi->base + STM32_SPI_TXDR);
+ while (readl_relaxed(spi->base + STM32H7_SPI_SR) & STM32H7_SPI_SR_TXP)
+ writeb_relaxed(++count, spi->base + STM32H7_SPI_TXDR);
- stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE);
+ stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
spin_unlock_irqrestore(&spi->lock, flags);
@@ -216,10 +390,20 @@ static int stm32_spi_get_fifo_size(struct stm32_spi *spi)
}
/**
- * stm32_spi_get_bpw_mask - Return bits per word mask
+ * stm32f4_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
*/
-static int stm32_spi_get_bpw_mask(struct stm32_spi *spi)
+static int stm32f4_spi_get_bpw_mask(struct stm32_spi *spi)
+{
+ dev_dbg(spi->dev, "8-bit or 16-bit data frame supported\n");
+ return SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
+}
+
+/**
+ * stm32h7_spi_get_bpw_mask - Return bits per word mask
+ * @spi: pointer to the spi controller data structure
+ */
+static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi)
{
unsigned long flags;
u32 cfg1, max_bpw;
@@ -230,10 +414,11 @@ static int stm32_spi_get_bpw_mask(struct stm32_spi *spi)
* The most significant bit at DSIZE bit field is reserved when the
* maximum data size of periperal instances is limited to 16-bit
*/
- stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_DSIZE);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_DSIZE);
- cfg1 = readl_relaxed(spi->base + STM32_SPI_CFG1);
- max_bpw = (cfg1 & SPI_CFG1_DSIZE) >> SPI_CFG1_DSIZE_SHIFT;
+ cfg1 = readl_relaxed(spi->base + STM32H7_SPI_CFG1);
+ max_bpw = (cfg1 & STM32H7_SPI_CFG1_DSIZE) >>
+ STM32H7_SPI_CFG1_DSIZE_SHIFT;
max_bpw += 1;
spin_unlock_irqrestore(&spi->lock, flags);
@@ -244,13 +429,16 @@ static int stm32_spi_get_bpw_mask(struct stm32_spi *spi)
}
/**
- * stm32_spi_prepare_mbr - Determine SPI_CFG1.MBR value
+ * stm32_spi_prepare_mbr - Determine baud rate divisor value
* @spi: pointer to the spi controller data structure
* @speed_hz: requested speed
+ * @min_div: minimum baud rate divisor
+ * @max_div: maximum baud rate divisor
*
- * Return SPI_CFG1.MBR value in case of success or -EINVAL
+ * Return baud rate divisor value in case of success or -EINVAL
*/
-static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz)
+static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,
+ u32 min_div, u32 max_div)
{
u32 div, mbrdiv;
@@ -263,8 +451,7 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz)
* no need to check it there.
* However, we need to ensure the following calculations.
*/
- if (div < SPI_MBR_DIV_MIN ||
- div > SPI_MBR_DIV_MAX)
+ if ((div < min_div) || (div > max_div))
return -EINVAL;
/* Determine the first power of 2 greater than or equal to div */
@@ -279,10 +466,10 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz)
}
/**
- * stm32_spi_prepare_fthlv - Determine FIFO threshold level
+ * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level
* @spi: pointer to the spi controller data structure
*/
-static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi)
+static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi)
{
u32 fthlv, half_fifo;
@@ -306,32 +493,62 @@ static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi)
}
/**
- * stm32_spi_write_txfifo - Write bytes in Transmit Data Register
+ * stm32f4_spi_write_tx - Write bytes to Transmit Data Register
* @spi: pointer to the spi controller data structure
*
* Read from tx_buf depends on remaining bytes to avoid to read beyond
* tx_buf end.
*/
-static void stm32_spi_write_txfifo(struct stm32_spi *spi)
+static void stm32f4_spi_write_tx(struct stm32_spi *spi)
+{
+ if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
+ STM32F4_SPI_SR_TXE)) {
+ u32 offs = spi->cur_xferlen - spi->tx_len;
+
+ if (spi->cur_bpw == 16) {
+ const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs);
+
+ writew_relaxed(*tx_buf16, spi->base + STM32F4_SPI_DR);
+ spi->tx_len -= sizeof(u16);
+ } else {
+ const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs);
+
+ writeb_relaxed(*tx_buf8, spi->base + STM32F4_SPI_DR);
+ spi->tx_len -= sizeof(u8);
+ }
+ }
+
+ dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len);
+}
+
+/**
+ * stm32h7_spi_write_txfifo - Write bytes in Transmit Data Register
+ * @spi: pointer to the spi controller data structure
+ *
+ * Read from tx_buf depends on remaining bytes to avoid to read beyond
+ * tx_buf end.
+ */
+static void stm32h7_spi_write_txfifo(struct stm32_spi *spi)
{
while ((spi->tx_len > 0) &&
- (readl_relaxed(spi->base + STM32_SPI_SR) & SPI_SR_TXP)) {
+ (readl_relaxed(spi->base + STM32H7_SPI_SR) &
+ STM32H7_SPI_SR_TXP)) {
u32 offs = spi->cur_xferlen - spi->tx_len;
if (spi->tx_len >= sizeof(u32)) {
const u32 *tx_buf32 = (const u32 *)(spi->tx_buf + offs);
- writel_relaxed(*tx_buf32, spi->base + STM32_SPI_TXDR);
+ writel_relaxed(*tx_buf32, spi->base + STM32H7_SPI_TXDR);
spi->tx_len -= sizeof(u32);
} else if (spi->tx_len >= sizeof(u16)) {
const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs);
- writew_relaxed(*tx_buf16, spi->base + STM32_SPI_TXDR);
+ writew_relaxed(*tx_buf16, spi->base + STM32H7_SPI_TXDR);
spi->tx_len -= sizeof(u16);
} else {
const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs);
- writeb_relaxed(*tx_buf8, spi->base + STM32_SPI_TXDR);
+ writeb_relaxed(*tx_buf8, spi->base + STM32H7_SPI_TXDR);
spi->tx_len -= sizeof(u8);
}
}
@@ -340,43 +557,74 @@ static void stm32_spi_write_txfifo(struct stm32_spi *spi)
}
/**
- * stm32_spi_read_rxfifo - Read bytes in Receive Data Register
+ * stm32f4_spi_read_rx - Read bytes from Receive Data Register
+ * @spi: pointer to the spi controller data structure
+ *
+ * Write in rx_buf depends on remaining bytes to avoid to write beyond
+ * rx_buf end.
+ */
+static void stm32f4_spi_read_rx(struct stm32_spi *spi)
+{
+ if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
+ STM32F4_SPI_SR_RXNE)) {
+ u32 offs = spi->cur_xferlen - spi->rx_len;
+
+ if (spi->cur_bpw == 16) {
+ u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);
+
+ *rx_buf16 = readw_relaxed(spi->base + STM32F4_SPI_DR);
+ spi->rx_len -= sizeof(u16);
+ } else {
+ u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs);
+
+ *rx_buf8 = readb_relaxed(spi->base + STM32F4_SPI_DR);
+ spi->rx_len -= sizeof(u8);
+ }
+ }
+
+ dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->rx_len);
+}
+
+/**
+ * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register
* @spi: pointer to the spi controller data structure
*
* Write in rx_buf depends on remaining bytes to avoid to write beyond
* rx_buf end.
*/
-static void stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
+static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
{
- u32 sr = readl_relaxed(spi->base + STM32_SPI_SR);
- u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+ u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
+ u32 rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >>
+ STM32H7_SPI_SR_RXPLVL_SHIFT;
while ((spi->rx_len > 0) &&
- ((sr & SPI_SR_RXP) ||
- (flush && ((sr & SPI_SR_RXWNE) || (rxplvl > 0))))) {
+ ((sr & STM32H7_SPI_SR_RXP) ||
+ (flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) {
u32 offs = spi->cur_xferlen - spi->rx_len;
if ((spi->rx_len >= sizeof(u32)) ||
- (flush && (sr & SPI_SR_RXWNE))) {
+ (flush && (sr & STM32H7_SPI_SR_RXWNE))) {
u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs);
- *rx_buf32 = readl_relaxed(spi->base + STM32_SPI_RXDR);
+ *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR);
spi->rx_len -= sizeof(u32);
} else if ((spi->rx_len >= sizeof(u16)) ||
(flush && (rxplvl >= 2 || spi->cur_bpw > 8))) {
u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);
- *rx_buf16 = readw_relaxed(spi->base + STM32_SPI_RXDR);
+ *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR);
spi->rx_len -= sizeof(u16);
} else {
u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs);
- *rx_buf8 = readb_relaxed(spi->base + STM32_SPI_RXDR);
+ *rx_buf8 = readb_relaxed(spi->base + STM32H7_SPI_RXDR);
spi->rx_len -= sizeof(u8);
}
- sr = readl_relaxed(spi->base + STM32_SPI_SR);
- rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+ sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
+ rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >>
+ STM32H7_SPI_SR_RXPLVL_SHIFT;
}
dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__,
@@ -386,26 +634,76 @@ static void stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
/**
* stm32_spi_enable - Enable SPI controller
* @spi: pointer to the spi controller data structure
- *
- * SPI data transfer is enabled but spi_ker_ck is idle.
- * SPI_CFG1 and SPI_CFG2 are now write protected.
*/
static void stm32_spi_enable(struct stm32_spi *spi)
{
dev_dbg(spi->dev, "enable controller\n");
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE);
+ stm32_spi_set_bits(spi, spi->cfg->regs->en.reg,
+ spi->cfg->regs->en.mask);
}
/**
- * stm32_spi_disable - Disable SPI controller
+ * stm32f4_spi_disable - Disable SPI controller
+ * @spi: pointer to the spi controller data structure
+ */
+static void stm32f4_spi_disable(struct stm32_spi *spi)
+{
+ unsigned long flags;
+ u32 sr;
+
+ dev_dbg(spi->dev, "disable controller\n");
+
+ spin_lock_irqsave(&spi->lock, flags);
+
+ if (!(readl_relaxed(spi->base + STM32F4_SPI_CR1) &
+ STM32F4_SPI_CR1_SPE)) {
+ spin_unlock_irqrestore(&spi->lock, flags);
+ return;
+ }
+
+ /* Disable interrupts */
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXEIE |
+ STM32F4_SPI_CR2_RXNEIE |
+ STM32F4_SPI_CR2_ERRIE);
+
+ /* Wait until BSY = 0 */
+ if (readl_relaxed_poll_timeout_atomic(spi->base + STM32F4_SPI_SR,
+ sr, !(sr & STM32F4_SPI_SR_BSY),
+ 10, 100000) < 0) {
+ dev_warn(spi->dev, "disabling condition timeout\n");
+ }
+
+ if (spi->cur_usedma && spi->dma_tx)
+ dmaengine_terminate_all(spi->dma_tx);
+ if (spi->cur_usedma && spi->dma_rx)
+ dmaengine_terminate_all(spi->dma_rx);
+
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE);
+
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN |
+ STM32F4_SPI_CR2_RXDMAEN);
+
+ /* Sequence to clear OVR flag */
+ readl_relaxed(spi->base + STM32F4_SPI_DR);
+ readl_relaxed(spi->base + STM32F4_SPI_SR);
+
+ spin_unlock_irqrestore(&spi->lock, flags);
+}
+
+/**
+ * stm32h7_spi_disable - Disable SPI controller
* @spi: pointer to the spi controller data structure
*
* RX-Fifo is flushed when SPI controller is disabled. To prevent any data
- * loss, use stm32_spi_read_rxfifo(flush) to read the remaining bytes in
+ * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in
* RX-Fifo.
+ * Normally, if TSIZE has been configured, we should relax the hardware at the
+ * reception of the EOT interrupt. But in case of error, EOT will not be
+ * raised. So the subsystem unprepare_message call allows us to properly
+ * complete the transfer from an hardware point of view.
*/
-static void stm32_spi_disable(struct stm32_spi *spi)
+static void stm32h7_spi_disable(struct stm32_spi *spi)
{
unsigned long flags;
u32 cr1, sr;
@@ -414,23 +712,23 @@ static void stm32_spi_disable(struct stm32_spi *spi)
spin_lock_irqsave(&spi->lock, flags);
- cr1 = readl_relaxed(spi->base + STM32_SPI_CR1);
+ cr1 = readl_relaxed(spi->base + STM32H7_SPI_CR1);
- if (!(cr1 & SPI_CR1_SPE)) {
+ if (!(cr1 & STM32H7_SPI_CR1_SPE)) {
spin_unlock_irqrestore(&spi->lock, flags);
return;
}
/* Wait on EOT or suspend the flow */
- if (readl_relaxed_poll_timeout_atomic(spi->base + STM32_SPI_SR,
- sr, !(sr & SPI_SR_EOT),
+ if (readl_relaxed_poll_timeout_atomic(spi->base + STM32H7_SPI_SR,
+ sr, !(sr & STM32H7_SPI_SR_EOT),
10, 100000) < 0) {
- if (cr1 & SPI_CR1_CSTART) {
- writel_relaxed(cr1 | SPI_CR1_CSUSP,
- spi->base + STM32_SPI_CR1);
+ if (cr1 & STM32H7_SPI_CR1_CSTART) {
+ writel_relaxed(cr1 | STM32H7_SPI_CR1_CSUSP,
+ spi->base + STM32H7_SPI_CR1);
if (readl_relaxed_poll_timeout_atomic(
- spi->base + STM32_SPI_SR,
- sr, !(sr & SPI_SR_SUSP),
+ spi->base + STM32H7_SPI_SR,
+ sr, !(sr & STM32H7_SPI_SR_SUSP),
10, 100000) < 0)
dev_warn(spi->dev,
"Suspend request timeout\n");
@@ -438,21 +736,21 @@ static void stm32_spi_disable(struct stm32_spi *spi)
}
if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0))
- stm32_spi_read_rxfifo(spi, true);
+ stm32h7_spi_read_rxfifo(spi, true);
- if (spi->cur_usedma && spi->tx_buf)
+ if (spi->cur_usedma && spi->dma_tx)
dmaengine_terminate_all(spi->dma_tx);
- if (spi->cur_usedma && spi->rx_buf)
+ if (spi->cur_usedma && spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
- stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_SPE);
+ stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
- stm32_spi_clr_bits(spi, STM32_SPI_CFG1, SPI_CFG1_TXDMAEN |
- SPI_CFG1_RXDMAEN);
+ stm32_spi_clr_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN |
+ STM32H7_SPI_CFG1_RXDMAEN);
/* Disable interrupts and clear status flags */
- writel_relaxed(0, spi->base + STM32_SPI_IER);
- writel_relaxed(SPI_IFCR_ALL, spi->base + STM32_SPI_IFCR);
+ writel_relaxed(0, spi->base + STM32H7_SPI_IER);
+ writel_relaxed(STM32H7_SPI_IFCR_ALL, spi->base + STM32H7_SPI_IFCR);
spin_unlock_irqrestore(&spi->lock, flags);
}
@@ -460,26 +758,136 @@ static void stm32_spi_disable(struct stm32_spi *spi)
/**
* stm32_spi_can_dma - Determine if the transfer is eligible for DMA use
*
- * If the current transfer size is greater than fifo size, use DMA.
+ * If driver has fifo and the current transfer size is greater than fifo size,
+ * use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes.
*/
static bool stm32_spi_can_dma(struct spi_master *master,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
+ unsigned int dma_size;
struct stm32_spi *spi = spi_master_get_devdata(master);
+ if (spi->cfg->has_fifo)
+ dma_size = spi->fifo_size;
+ else
+ dma_size = SPI_DMA_MIN_BYTES;
+
dev_dbg(spi->dev, "%s: %s\n", __func__,
- (transfer->len > spi->fifo_size) ? "true" : "false");
+ (transfer->len > dma_size) ? "true" : "false");
+
+ return (transfer->len > dma_size);
+}
+
+/**
+ * stm32f4_spi_irq_event - Interrupt handler for SPI controller events
+ * @irq: interrupt line
+ * @dev_id: SPI controller master interface
+ */
+static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
+{
+ struct spi_master *master = dev_id;
+ struct stm32_spi *spi = spi_master_get_devdata(master);
+ u32 sr, mask = 0;
+ unsigned long flags;
+ bool end = false;
+
+ spin_lock_irqsave(&spi->lock, flags);
+
+ sr = readl_relaxed(spi->base + STM32F4_SPI_SR);
+ /*
+ * BSY flag is not handled in interrupt but it is normal behavior when
+ * this flag is set.
+ */
+ sr &= ~STM32F4_SPI_SR_BSY;
+
+ if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX ||
+ spi->cur_comm == SPI_3WIRE_TX)) {
+ /* OVR flag shouldn't be handled for TX only mode */
+ sr &= ~STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE;
+ mask |= STM32F4_SPI_SR_TXE;
+ }
+
+ if (!spi->cur_usedma && spi->cur_comm == SPI_FULL_DUPLEX) {
+ /* TXE flag is set and is handled when RXNE flag occurs */
+ sr &= ~STM32F4_SPI_SR_TXE;
+ mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR;
+ }
+
+ if (!(sr & mask)) {
+ dev_dbg(spi->dev, "spurious IT (sr=0x%08x)\n", sr);
+ spin_unlock_irqrestore(&spi->lock, flags);
+ return IRQ_NONE;
+ }
+
+ if (sr & STM32F4_SPI_SR_OVR) {
+ dev_warn(spi->dev, "Overrun: received value discarded\n");
+
+ /* Sequence to clear OVR flag */
+ readl_relaxed(spi->base + STM32F4_SPI_DR);
+ readl_relaxed(spi->base + STM32F4_SPI_SR);
+
+ /*
+ * If overrun is detected, it means that something went wrong,
+ * so stop the current transfer. Transfer can wait for next
+ * RXNE but DR is already read and end never happens.
+ */
+ end = true;
+ goto end_irq;
+ }
+
+ if (sr & STM32F4_SPI_SR_TXE) {
+ if (spi->tx_buf)
+ stm32f4_spi_write_tx(spi);
+ if (spi->tx_len == 0)
+ end = true;
+ }
+
+ if (sr & STM32F4_SPI_SR_RXNE) {
+ stm32f4_spi_read_rx(spi);
+ if (spi->rx_len == 0)
+ end = true;
+ else /* Load data for discontinuous mode */
+ stm32f4_spi_write_tx(spi);
+ }
+
+end_irq:
+ if (end) {
+ /* Immediately disable interrupts to do not generate new one */
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR2,
+ STM32F4_SPI_CR2_TXEIE |
+ STM32F4_SPI_CR2_RXNEIE |
+ STM32F4_SPI_CR2_ERRIE);
+ spin_unlock_irqrestore(&spi->lock, flags);
+ return IRQ_WAKE_THREAD;
+ }
+
+ spin_unlock_irqrestore(&spi->lock, flags);
+ return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller
+ * @irq: interrupt line
+ * @dev_id: SPI controller master interface
+ */
+static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
+{
+ struct spi_master *master = dev_id;
+ struct stm32_spi *spi = spi_master_get_devdata(master);
+
+ spi_finalize_current_transfer(master);
+ stm32f4_spi_disable(spi);
- return (transfer->len > spi->fifo_size);
+ return IRQ_HANDLED;
}
/**
- * stm32_spi_irq - Interrupt handler for SPI controller events
+ * stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller master interface
*/
-static irqreturn_t stm32_spi_irq(int irq, void *dev_id)
+static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
@@ -489,19 +897,19 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id)
spin_lock_irqsave(&spi->lock, flags);
- sr = readl_relaxed(spi->base + STM32_SPI_SR);
- ier = readl_relaxed(spi->base + STM32_SPI_IER);
+ sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
+ ier = readl_relaxed(spi->base + STM32H7_SPI_IER);
mask = ier;
/* EOTIE is triggered on EOT, SUSP and TXC events. */
- mask |= SPI_SR_SUSP;
+ mask |= STM32H7_SPI_SR_SUSP;
/*
* When TXTF is set, DXPIE and TXPIE are cleared. So in case of
* Full-Duplex, need to poll RXP event to know if there are remaining
* data, before disabling SPI.
*/
if (spi->rx_buf && !spi->cur_usedma)
- mask |= SPI_SR_RXP;
+ mask |= STM32H7_SPI_SR_RXP;
if (!(sr & mask)) {
dev_dbg(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n",
@@ -510,10 +918,10 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id)
return IRQ_NONE;
}
- if (sr & SPI_SR_SUSP) {
+ if (sr & STM32H7_SPI_SR_SUSP) {
dev_warn(spi->dev, "Communication suspended\n");
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
- stm32_spi_read_rxfifo(spi, false);
+ stm32h7_spi_read_rxfifo(spi, false);
/*
* If communication is suspended while using DMA, it means
* that something went wrong, so stop the current transfer
@@ -522,15 +930,15 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id)
end = true;
}
- if (sr & SPI_SR_MODF) {
+ if (sr & STM32H7_SPI_SR_MODF) {
dev_warn(spi->dev, "Mode fault: transfer aborted\n");
end = true;
}
- if (sr & SPI_SR_OVR) {
+ if (sr & STM32H7_SPI_SR_OVR) {
dev_warn(spi->dev, "Overrun: received value discarded\n");
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
- stm32_spi_read_rxfifo(spi, false);
+ stm32h7_spi_read_rxfifo(spi, false);
/*
* If overrun is detected while using DMA, it means that
* something went wrong, so stop the current transfer
@@ -539,27 +947,27 @@ static irqreturn_t stm32_spi_irq(int irq, void *dev_id)
end = true;
}
- if (sr & SPI_SR_EOT) {
+ if (sr & STM32H7_SPI_SR_EOT) {
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
- stm32_spi_read_rxfifo(spi, true);
+ stm32h7_spi_read_rxfifo(spi, true);
end = true;
}
- if (sr & SPI_SR_TXP)
+ if (sr & STM32H7_SPI_SR_TXP)
if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0)))
- stm32_spi_write_txfifo(spi);
+ stm32h7_spi_write_txfifo(spi);
- if (sr & SPI_SR_RXP)
+ if (sr & STM32H7_SPI_SR_RXP)
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
- stm32_spi_read_rxfifo(spi, false);
+ stm32h7_spi_read_rxfifo(spi, false);
- writel_relaxed(mask, spi->base + STM32_SPI_IFCR);
+ writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR);
spin_unlock_irqrestore(&spi->lock, flags);
if (end) {
spi_finalize_current_transfer(master);
- stm32_spi_disable(spi);
+ stm32h7_spi_disable(spi);
}
return IRQ_HANDLED;
@@ -598,7 +1006,7 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
struct spi_device *spi_dev = msg->spi;
struct device_node *np = spi_dev->dev.of_node;
unsigned long flags;
- u32 cfg2_clrb = 0, cfg2_setb = 0;
+ u32 clrb = 0, setb = 0;
/* SPI slave device may need time between data frames */
spi->cur_midi = 0;
@@ -606,19 +1014,19 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
dev_dbg(spi->dev, "%dns inter-data idleness\n", spi->cur_midi);
if (spi_dev->mode & SPI_CPOL)
- cfg2_setb |= SPI_CFG2_CPOL;
+ setb |= spi->cfg->regs->cpol.mask;
else
- cfg2_clrb |= SPI_CFG2_CPOL;
+ clrb |= spi->cfg->regs->cpol.mask;
if (spi_dev->mode & SPI_CPHA)
- cfg2_setb |= SPI_CFG2_CPHA;
+ setb |= spi->cfg->regs->cpha.mask;
else
- cfg2_clrb |= SPI_CFG2_CPHA;
+ clrb |= spi->cfg->regs->cpha.mask;
if (spi_dev->mode & SPI_LSB_FIRST)
- cfg2_setb |= SPI_CFG2_LSBFRST;
+ setb |= spi->cfg->regs->lsb_first.mask;
else
- cfg2_clrb |= SPI_CFG2_LSBFRST;
+ clrb |= spi->cfg->regs->lsb_first.mask;
dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n",
spi_dev->mode & SPI_CPOL,
@@ -628,11 +1036,12 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
spin_lock_irqsave(&spi->lock, flags);
- if (cfg2_clrb || cfg2_setb)
+ /* CPOL, CPHA and LSB FIRST bits have common register */
+ if (clrb || setb)
writel_relaxed(
- (readl_relaxed(spi->base + STM32_SPI_CFG2) &
- ~cfg2_clrb) | cfg2_setb,
- spi->base + STM32_SPI_CFG2);
+ (readl_relaxed(spi->base + spi->cfg->regs->cpol.reg) &
+ ~clrb) | setb,
+ spi->base + spi->cfg->regs->cpol.reg);
spin_unlock_irqrestore(&spi->lock, flags);
@@ -640,12 +1049,40 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
}
/**
- * stm32_spi_dma_cb - dma callback
+ * stm32f4_spi_dma_tx_cb - dma callback
+ *
+ * DMA callback is called when the transfer is complete for DMA TX channel.
+ */
+static void stm32f4_spi_dma_tx_cb(void *data)
+{
+ struct stm32_spi *spi = data;
+
+ if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
+ spi_finalize_current_transfer(spi->master);
+ stm32f4_spi_disable(spi);
+ }
+}
+
+/**
+ * stm32f4_spi_dma_rx_cb - dma callback
+ *
+ * DMA callback is called when the transfer is complete for DMA RX channel.
+ */
+static void stm32f4_spi_dma_rx_cb(void *data)
+{
+ struct stm32_spi *spi = data;
+
+ spi_finalize_current_transfer(spi->master);
+ stm32f4_spi_disable(spi);
+}
+
+/**
+ * stm32h7_spi_dma_cb - dma callback
*
* DMA callback is called when the transfer is complete or when an error
* occurs. If the transfer is complete, EOT flag is raised.
*/
-static void stm32_spi_dma_cb(void *data)
+static void stm32h7_spi_dma_cb(void *data)
{
struct stm32_spi *spi = data;
unsigned long flags;
@@ -653,11 +1090,11 @@ static void stm32_spi_dma_cb(void *data)
spin_lock_irqsave(&spi->lock, flags);
- sr = readl_relaxed(spi->base + STM32_SPI_SR);
+ sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
spin_unlock_irqrestore(&spi->lock, flags);
- if (!(sr & SPI_SR_EOT))
+ if (!(sr & STM32H7_SPI_SR_EOT))
dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr);
/* Now wait for EOT, or SUSP or OVR in case of error */
@@ -681,23 +1118,27 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
else
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- /* Valid for DMA Half or Full Fifo threshold */
- if (spi->cur_fthlv == 2)
+ if (spi->cfg->has_fifo) {
+ /* Valid for DMA Half or Full Fifo threshold */
+ if (spi->cur_fthlv == 2)
+ maxburst = 1;
+ else
+ maxburst = spi->cur_fthlv;
+ } else {
maxburst = 1;
- else
- maxburst = spi->cur_fthlv;
+ }
memset(dma_conf, 0, sizeof(struct dma_slave_config));
dma_conf->direction = dir;
if (dma_conf->direction == DMA_DEV_TO_MEM) { /* RX */
- dma_conf->src_addr = spi->phys_addr + STM32_SPI_RXDR;
+ dma_conf->src_addr = spi->phys_addr + spi->cfg->regs->rx.reg;
dma_conf->src_addr_width = buswidth;
dma_conf->src_maxburst = maxburst;
dev_dbg(spi->dev, "Rx DMA config buswidth=%d, maxburst=%d\n",
buswidth, maxburst);
} else if (dma_conf->direction == DMA_MEM_TO_DEV) { /* TX */
- dma_conf->dst_addr = spi->phys_addr + STM32_SPI_TXDR;
+ dma_conf->dst_addr = spi->phys_addr + spi->cfg->regs->tx.reg;
dma_conf->dst_addr_width = buswidth;
dma_conf->dst_maxburst = maxburst;
@@ -707,27 +1148,68 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
}
/**
- * stm32_spi_transfer_one_irq - transfer a single spi_transfer using
- * interrupts
+ * stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using
+ * interrupts
*
* It must returns 0 if the transfer is finished or 1 if the transfer is still
* in progress.
*/
-static int stm32_spi_transfer_one_irq(struct stm32_spi *spi)
+static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
+{
+ unsigned long flags;
+ u32 cr2 = 0;
+
+ /* Enable the interrupts relative to the current communication mode */
+ if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
+ cr2 |= STM32F4_SPI_CR2_TXEIE;
+ } else if (spi->cur_comm == SPI_FULL_DUPLEX) {
+ /* In transmit-only mode, the OVR flag is set in the SR register
+ * since the received data are never read. Therefore set OVR
+ * interrupt only when rx buffer is available.
+ */
+ cr2 |= STM32F4_SPI_CR2_RXNEIE | STM32F4_SPI_CR2_ERRIE;
+ } else {
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&spi->lock, flags);
+
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR2, cr2);
+
+ stm32_spi_enable(spi);
+
+ /* starting data transfer when buffer is loaded */
+ if (spi->tx_buf)
+ stm32f4_spi_write_tx(spi);
+
+ spin_unlock_irqrestore(&spi->lock, flags);
+
+ return 1;
+}
+
+/**
+ * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using
+ * interrupts
+ *
+ * It must returns 0 if the transfer is finished or 1 if the transfer is still
+ * in progress.
+ */
+static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
{
unsigned long flags;
u32 ier = 0;
/* Enable the interrupts relative to the current communication mode */
if (spi->tx_buf && spi->rx_buf) /* Full Duplex */
- ier |= SPI_IER_DXPIE;
+ ier |= STM32H7_SPI_IER_DXPIE;
else if (spi->tx_buf) /* Half-Duplex TX dir or Simplex TX */
- ier |= SPI_IER_TXPIE;
+ ier |= STM32H7_SPI_IER_TXPIE;
else if (spi->rx_buf) /* Half-Duplex RX dir or Simplex RX */
- ier |= SPI_IER_RXPIE;
+ ier |= STM32H7_SPI_IER_RXPIE;
/* Enable the interrupts relative to the end of transfer */
- ier |= SPI_IER_EOTIE | SPI_IER_TXTFIE | SPI_IER_OVRIE | SPI_IER_MODFIE;
+ ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE |
+ STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE;
spin_lock_irqsave(&spi->lock, flags);
@@ -735,11 +1217,11 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi)
/* Be sure to have data in fifo before starting data transfer */
if (spi->tx_buf)
- stm32_spi_write_txfifo(spi);
+ stm32h7_spi_write_txfifo(spi);
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_CSTART);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
- writel_relaxed(ier, spi->base + STM32_SPI_IER);
+ writel_relaxed(ier, spi->base + STM32H7_SPI_IER);
spin_unlock_irqrestore(&spi->lock, flags);
@@ -747,6 +1229,43 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi)
}
/**
+ * stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start
+ * transfer using DMA
+ */
+static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi)
+{
+ /* In DMA mode end of transfer is handled by DMA TX or RX callback. */
+ if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX ||
+ spi->cur_comm == SPI_FULL_DUPLEX) {
+ /*
+ * In transmit-only mode, the OVR flag is set in the SR register
+ * since the received data are never read. Therefore set OVR
+ * interrupt only when rx buffer is available.
+ */
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_ERRIE);
+ }
+
+ stm32_spi_enable(spi);
+}
+
+/**
+ * stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start
+ * transfer using DMA
+ */
+static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)
+{
+ /* Enable the interrupts relative to the end of transfer */
+ stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE |
+ STM32H7_SPI_IER_TXTFIE |
+ STM32H7_SPI_IER_OVRIE |
+ STM32H7_SPI_IER_MODFIE);
+
+ stm32_spi_enable(spi);
+
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
+}
+
+/**
* stm32_spi_transfer_one_dma - transfer a single spi_transfer using DMA
*
* It must returns 0 if the transfer is finished or 1 if the transfer is still
@@ -758,17 +1277,17 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
struct dma_slave_config tx_dma_conf, rx_dma_conf;
struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc;
unsigned long flags;
- u32 ier = 0;
spin_lock_irqsave(&spi->lock, flags);
rx_dma_desc = NULL;
- if (spi->rx_buf) {
+ if (spi->rx_buf && spi->dma_rx) {
stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM);
dmaengine_slave_config(spi->dma_rx, &rx_dma_conf);
/* Enable Rx DMA request */
- stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_RXDMAEN);
+ stm32_spi_set_bits(spi, spi->cfg->regs->dma_rx_en.reg,
+ spi->cfg->regs->dma_rx_en.mask);
rx_dma_desc = dmaengine_prep_slave_sg(
spi->dma_rx, xfer->rx_sg.sgl,
@@ -778,7 +1297,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
}
tx_dma_desc = NULL;
- if (spi->tx_buf) {
+ if (spi->tx_buf && spi->dma_tx) {
stm32_spi_dma_config(spi, &tx_dma_conf, DMA_MEM_TO_DEV);
dmaengine_slave_config(spi->dma_tx, &tx_dma_conf);
@@ -789,12 +1308,15 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
DMA_PREP_INTERRUPT);
}
- if ((spi->tx_buf && !tx_dma_desc) ||
- (spi->rx_buf && !rx_dma_desc))
+ if ((spi->tx_buf && spi->dma_tx && !tx_dma_desc) ||
+ (spi->rx_buf && spi->dma_rx && !rx_dma_desc))
+ goto dma_desc_error;
+
+ if (spi->cur_comm == SPI_FULL_DUPLEX && (!tx_dma_desc || !rx_dma_desc))
goto dma_desc_error;
if (rx_dma_desc) {
- rx_dma_desc->callback = stm32_spi_dma_cb;
+ rx_dma_desc->callback = spi->cfg->dma_rx_cb;
rx_dma_desc->callback_param = spi;
if (dma_submit_error(dmaengine_submit(rx_dma_desc))) {
@@ -806,8 +1328,9 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
}
if (tx_dma_desc) {
- if (spi->cur_comm == SPI_SIMPLEX_TX) {
- tx_dma_desc->callback = stm32_spi_dma_cb;
+ if (spi->cur_comm == SPI_SIMPLEX_TX ||
+ spi->cur_comm == SPI_3WIRE_TX) {
+ tx_dma_desc->callback = spi->cfg->dma_tx_cb;
tx_dma_desc->callback_param = spi;
}
@@ -819,130 +1342,278 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dma_async_issue_pending(spi->dma_tx);
/* Enable Tx DMA request */
- stm32_spi_set_bits(spi, STM32_SPI_CFG1, SPI_CFG1_TXDMAEN);
+ stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg,
+ spi->cfg->regs->dma_tx_en.mask);
}
- /* Enable the interrupts relative to the end of transfer */
- ier |= SPI_IER_EOTIE | SPI_IER_TXTFIE | SPI_IER_OVRIE | SPI_IER_MODFIE;
- writel_relaxed(ier, spi->base + STM32_SPI_IER);
-
- stm32_spi_enable(spi);
-
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_CSTART);
+ spi->cfg->transfer_one_dma_start(spi);
spin_unlock_irqrestore(&spi->lock, flags);
return 1;
dma_submit_error:
- if (spi->rx_buf)
+ if (spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
dma_desc_error:
- stm32_spi_clr_bits(spi, STM32_SPI_CFG1, SPI_CFG1_RXDMAEN);
+ stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg,
+ spi->cfg->regs->dma_rx_en.mask);
spin_unlock_irqrestore(&spi->lock, flags);
dev_info(spi->dev, "DMA issue: fall back to irq transfer\n");
- return stm32_spi_transfer_one_irq(spi);
+ spi->cur_usedma = false;
+ return spi->cfg->transfer_one_irq(spi);
}
/**
- * stm32_spi_transfer_one_setup - common setup to transfer a single
- * spi_transfer either using DMA or
- * interrupts.
+ * stm32f4_spi_set_bpw - Configure bits per word
+ * @spi: pointer to the spi controller data structure
*/
-static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
- struct spi_device *spi_dev,
- struct spi_transfer *transfer)
+static void stm32f4_spi_set_bpw(struct stm32_spi *spi)
{
- unsigned long flags;
- u32 cfg1_clrb = 0, cfg1_setb = 0, cfg2_clrb = 0, cfg2_setb = 0;
- u32 mode, nb_words;
- int ret = 0;
-
- spin_lock_irqsave(&spi->lock, flags);
+ if (spi->cur_bpw == 16)
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF);
+ else
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF);
+}
- if (spi->cur_bpw != transfer->bits_per_word) {
- u32 bpw, fthlv;
+/**
+ * stm32h7_spi_set_bpw - configure bits per word
+ * @spi: pointer to the spi controller data structure
+ */
+static void stm32h7_spi_set_bpw(struct stm32_spi *spi)
+{
+ u32 bpw, fthlv;
+ u32 cfg1_clrb = 0, cfg1_setb = 0;
- spi->cur_bpw = transfer->bits_per_word;
- bpw = spi->cur_bpw - 1;
+ bpw = spi->cur_bpw - 1;
- cfg1_clrb |= SPI_CFG1_DSIZE;
- cfg1_setb |= (bpw << SPI_CFG1_DSIZE_SHIFT) & SPI_CFG1_DSIZE;
+ cfg1_clrb |= STM32H7_SPI_CFG1_DSIZE;
+ cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) &
+ STM32H7_SPI_CFG1_DSIZE;
- spi->cur_fthlv = stm32_spi_prepare_fthlv(spi);
- fthlv = spi->cur_fthlv - 1;
+ spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi);
+ fthlv = spi->cur_fthlv - 1;
- cfg1_clrb |= SPI_CFG1_FTHLV;
- cfg1_setb |= (fthlv << SPI_CFG1_FTHLV_SHIFT) & SPI_CFG1_FTHLV;
- }
+ cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV;
+ cfg1_setb |= (fthlv << STM32H7_SPI_CFG1_FTHLV_SHIFT) &
+ STM32H7_SPI_CFG1_FTHLV;
- if (spi->cur_speed != transfer->speed_hz) {
- int mbr;
+ writel_relaxed(
+ (readl_relaxed(spi->base + STM32H7_SPI_CFG1) &
+ ~cfg1_clrb) | cfg1_setb,
+ spi->base + STM32H7_SPI_CFG1);
+}
- /* Update spi->cur_speed with real clock speed */
- mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz);
- if (mbr < 0) {
- ret = mbr;
- goto out;
- }
+/**
+ * stm32_spi_set_mbr - Configure baud rate divisor in master mode
+ * @spi: pointer to the spi controller data structure
+ * @mbrdiv: baud rate divisor value
+ */
+static void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv)
+{
+ u32 clrb = 0, setb = 0;
- transfer->speed_hz = spi->cur_speed;
+ clrb |= spi->cfg->regs->br.mask;
+ setb |= ((u32)mbrdiv << spi->cfg->regs->br.shift) &
+ spi->cfg->regs->br.mask;
- cfg1_clrb |= SPI_CFG1_MBR;
- cfg1_setb |= ((u32)mbr << SPI_CFG1_MBR_SHIFT) & SPI_CFG1_MBR;
- }
+ writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) &
+ ~clrb) | setb,
+ spi->base + spi->cfg->regs->br.reg);
+}
- if (cfg1_clrb || cfg1_setb)
- writel_relaxed((readl_relaxed(spi->base + STM32_SPI_CFG1) &
- ~cfg1_clrb) | cfg1_setb,
- spi->base + STM32_SPI_CFG1);
+/**
+ * stm32_spi_communication_type - return transfer communication type
+ * @spi_dev: pointer to the spi device
+ * transfer: pointer to spi transfer
+ */
+static unsigned int stm32_spi_communication_type(struct spi_device *spi_dev,
+ struct spi_transfer *transfer)
+{
+ unsigned int type = SPI_FULL_DUPLEX;
- mode = SPI_FULL_DUPLEX;
if (spi_dev->mode & SPI_3WIRE) { /* MISO/MOSI signals shared */
/*
* SPI_3WIRE and xfer->tx_buf != NULL and xfer->rx_buf != NULL
- * is forbidden und unvalidated by SPI subsystem so depending
+ * is forbidden and unvalidated by SPI subsystem so depending
* on the valid buffer, we can determine the direction of the
* transfer.
*/
- mode = SPI_HALF_DUPLEX;
if (!transfer->tx_buf)
- stm32_spi_clr_bits(spi, STM32_SPI_CR1, SPI_CR1_HDDIR);
- else if (!transfer->rx_buf)
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_HDDIR);
+ type = SPI_3WIRE_RX;
+ else
+ type = SPI_3WIRE_TX;
} else {
if (!transfer->tx_buf)
- mode = SPI_SIMPLEX_RX;
+ type = SPI_SIMPLEX_RX;
else if (!transfer->rx_buf)
- mode = SPI_SIMPLEX_TX;
+ type = SPI_SIMPLEX_TX;
+ }
+
+ return type;
+}
+
+/**
+ * stm32f4_spi_set_mode - configure communication mode
+ * @spi: pointer to the spi controller data structure
+ * @comm_type: type of communication to configure
+ */
+static int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
+{
+ if (comm_type == SPI_3WIRE_TX || comm_type == SPI_SIMPLEX_TX) {
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
+ STM32F4_SPI_CR1_BIDIMODE |
+ STM32F4_SPI_CR1_BIDIOE);
+ } else if (comm_type == SPI_FULL_DUPLEX) {
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
+ STM32F4_SPI_CR1_BIDIMODE |
+ STM32F4_SPI_CR1_BIDIOE);
+ } else {
+ return -EINVAL;
}
- if (spi->cur_comm != mode) {
- spi->cur_comm = mode;
- cfg2_clrb |= SPI_CFG2_COMM;
- cfg2_setb |= (mode << SPI_CFG2_COMM_SHIFT) & SPI_CFG2_COMM;
+ return 0;
+}
+
+/**
+ * stm32h7_spi_set_mode - configure communication mode
+ * @spi: pointer to the spi controller data structure
+ * @comm_type: type of communication to configure
+ */
+static int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
+{
+ u32 mode;
+ u32 cfg2_clrb = 0, cfg2_setb = 0;
+
+ if (comm_type == SPI_3WIRE_RX) {
+ mode = STM32H7_SPI_HALF_DUPLEX;
+ stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR);
+ } else if (comm_type == SPI_3WIRE_TX) {
+ mode = STM32H7_SPI_HALF_DUPLEX;
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR);
+ } else if (comm_type == SPI_SIMPLEX_RX) {
+ mode = STM32H7_SPI_SIMPLEX_RX;
+ } else if (comm_type == SPI_SIMPLEX_TX) {
+ mode = STM32H7_SPI_SIMPLEX_TX;
+ } else {
+ mode = STM32H7_SPI_FULL_DUPLEX;
}
- cfg2_clrb |= SPI_CFG2_MIDI;
- if ((transfer->len > 1) && (spi->cur_midi > 0)) {
+ cfg2_clrb |= STM32H7_SPI_CFG2_COMM;
+ cfg2_setb |= (mode << STM32H7_SPI_CFG2_COMM_SHIFT) &
+ STM32H7_SPI_CFG2_COMM;
+
+ writel_relaxed(
+ (readl_relaxed(spi->base + STM32H7_SPI_CFG2) &
+ ~cfg2_clrb) | cfg2_setb,
+ spi->base + STM32H7_SPI_CFG2);
+
+ return 0;
+}
+
+/**
+ * stm32h7_spi_data_idleness - configure minimum time delay inserted between two
+ * consecutive data frames in master mode
+ * @spi: pointer to the spi controller data structure
+ * @len: transfer len
+ */
+static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len)
+{
+ u32 cfg2_clrb = 0, cfg2_setb = 0;
+
+ cfg2_clrb |= STM32H7_SPI_CFG2_MIDI;
+ if ((len > 1) && (spi->cur_midi > 0)) {
u32 sck_period_ns = DIV_ROUND_UP(SPI_1HZ_NS, spi->cur_speed);
u32 midi = min((u32)DIV_ROUND_UP(spi->cur_midi, sck_period_ns),
- (u32)SPI_CFG2_MIDI >> SPI_CFG2_MIDI_SHIFT);
+ (u32)STM32H7_SPI_CFG2_MIDI >>
+ STM32H7_SPI_CFG2_MIDI_SHIFT);
dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n",
sck_period_ns, midi, midi * sck_period_ns);
+ cfg2_setb |= (midi << STM32H7_SPI_CFG2_MIDI_SHIFT) &
+ STM32H7_SPI_CFG2_MIDI;
+ }
+
+ writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG2) &
+ ~cfg2_clrb) | cfg2_setb,
+ spi->base + STM32H7_SPI_CFG2);
+}
+
+/**
+ * stm32h7_spi_number_of_data - configure number of data at current transfer
+ * @spi: pointer to the spi controller data structure
+ * @len: transfer length
+ */
+static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words)
+{
+ u32 cr2_clrb = 0, cr2_setb = 0;
+
+ if (nb_words <= (STM32H7_SPI_CR2_TSIZE >>
+ STM32H7_SPI_CR2_TSIZE_SHIFT)) {
+ cr2_clrb |= STM32H7_SPI_CR2_TSIZE;
+ cr2_setb = nb_words << STM32H7_SPI_CR2_TSIZE_SHIFT;
+ writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CR2) &
+ ~cr2_clrb) | cr2_setb,
+ spi->base + STM32H7_SPI_CR2);
+ } else {
+ return -EMSGSIZE;
+ }
+
+ return 0;
+}
+
+/**
+ * stm32_spi_transfer_one_setup - common setup to transfer a single
+ * spi_transfer either using DMA or
+ * interrupts.
+ */
+static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
+ struct spi_device *spi_dev,
+ struct spi_transfer *transfer)
+{
+ unsigned long flags;
+ unsigned int comm_type;
+ int nb_words, ret = 0;
+
+ spin_lock_irqsave(&spi->lock, flags);
+
+ if (spi->cur_bpw != transfer->bits_per_word) {
+ spi->cur_bpw = transfer->bits_per_word;
+ spi->cfg->set_bpw(spi);
+ }
- cfg2_setb |= (midi << SPI_CFG2_MIDI_SHIFT) & SPI_CFG2_MIDI;
+ if (spi->cur_speed != transfer->speed_hz) {
+ int mbr;
+
+ /* Update spi->cur_speed with real clock speed */
+ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
+ spi->cfg->baud_rate_div_min,
+ spi->cfg->baud_rate_div_max);
+ if (mbr < 0) {
+ ret = mbr;
+ goto out;
+ }
+
+ transfer->speed_hz = spi->cur_speed;
+ stm32_spi_set_mbr(spi, mbr);
}
- if (cfg2_clrb || cfg2_setb)
- writel_relaxed((readl_relaxed(spi->base + STM32_SPI_CFG2) &
- ~cfg2_clrb) | cfg2_setb,
- spi->base + STM32_SPI_CFG2);
+ comm_type = stm32_spi_communication_type(spi_dev, transfer);
+ if (spi->cur_comm != comm_type) {
+ ret = spi->cfg->set_mode(spi, comm_type);
+
+ if (ret < 0)
+ goto out;
+
+ spi->cur_comm = comm_type;
+ }
+
+ if (spi->cfg->set_data_idleness)
+ spi->cfg->set_data_idleness(spi, transfer->len);
if (spi->cur_bpw <= 8)
nb_words = transfer->len;
@@ -950,13 +1621,11 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
nb_words = DIV_ROUND_UP(transfer->len * 8, 16);
else
nb_words = DIV_ROUND_UP(transfer->len * 8, 32);
- nb_words <<= SPI_CR2_TSIZE_SHIFT;
- if (nb_words <= SPI_CR2_TSIZE) {
- writel_relaxed(nb_words, spi->base + STM32_SPI_CR2);
- } else {
- ret = -EMSGSIZE;
- goto out;
+ if (spi->cfg->set_number_of_data) {
+ ret = spi->cfg->set_number_of_data(spi, nb_words);
+ if (ret < 0)
+ goto out;
}
spi->cur_xferlen = transfer->len;
@@ -997,7 +1666,7 @@ static int stm32_spi_transfer_one(struct spi_master *master,
spi->rx_len = spi->rx_buf ? transfer->len : 0;
spi->cur_usedma = (master->can_dma &&
- stm32_spi_can_dma(master, spi_dev, transfer));
+ master->can_dma(master, spi_dev, transfer));
ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer);
if (ret) {
@@ -1008,47 +1677,73 @@ static int stm32_spi_transfer_one(struct spi_master *master,
if (spi->cur_usedma)
return stm32_spi_transfer_one_dma(spi, transfer);
else
- return stm32_spi_transfer_one_irq(spi);
+ return spi->cfg->transfer_one_irq(spi);
}
/**
* stm32_spi_unprepare_msg - relax the hardware
- *
- * Normally, if TSIZE has been configured, we should relax the hardware at the
- * reception of the EOT interrupt. But in case of error, EOT will not be
- * raised. So the subsystem unprepare_message call allows us to properly
- * complete the transfer from an hardware point of view.
*/
static int stm32_spi_unprepare_msg(struct spi_master *master,
struct spi_message *msg)
{
struct stm32_spi *spi = spi_master_get_devdata(master);
- stm32_spi_disable(spi);
+ spi->cfg->disable(spi);
+
+ return 0;
+}
+
+/**
+ * stm32f4_spi_config - Configure SPI controller as SPI master
+ */
+static int stm32f4_spi_config(struct stm32_spi *spi)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spi->lock, flags);
+
+ /* Ensure I2SMOD bit is kept cleared */
+ stm32_spi_clr_bits(spi, STM32F4_SPI_I2SCFGR,
+ STM32F4_SPI_I2SCFGR_I2SMOD);
+
+ /*
+ * - SS input value high
+ * - transmitter half duplex direction
+ * - Set the master mode (default Motorola mode)
+ * - Consider 1 master/n slaves configuration and
+ * SS input value is determined by the SSI bit
+ */
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SSI |
+ STM32F4_SPI_CR1_BIDIOE |
+ STM32F4_SPI_CR1_MSTR |
+ STM32F4_SPI_CR1_SSM);
+
+ spin_unlock_irqrestore(&spi->lock, flags);
return 0;
}
/**
- * stm32_spi_config - Configure SPI controller as SPI master
+ * stm32h7_spi_config - Configure SPI controller as SPI master
*/
-static int stm32_spi_config(struct stm32_spi *spi)
+static int stm32h7_spi_config(struct stm32_spi *spi)
{
unsigned long flags;
spin_lock_irqsave(&spi->lock, flags);
/* Ensure I2SMOD bit is kept cleared */
- stm32_spi_clr_bits(spi, STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD);
+ stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR,
+ STM32H7_SPI_I2SCFGR_I2SMOD);
/*
* - SS input value high
* - transmitter half duplex direction
* - automatic communication suspend when RX-Fifo is full
*/
- stm32_spi_set_bits(spi, STM32_SPI_CR1, SPI_CR1_SSI |
- SPI_CR1_HDDIR |
- SPI_CR1_MASRX);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI |
+ STM32H7_SPI_CR1_HDDIR |
+ STM32H7_SPI_CR1_MASRX);
/*
* - Set the master mode (default Motorola mode)
@@ -1056,17 +1751,56 @@ static int stm32_spi_config(struct stm32_spi *spi)
* SS input value is determined by the SSI bit
* - keep control of all associated GPIOs
*/
- stm32_spi_set_bits(spi, STM32_SPI_CFG2, SPI_CFG2_MASTER |
- SPI_CFG2_SSM |
- SPI_CFG2_AFCNTR);
+ stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER |
+ STM32H7_SPI_CFG2_SSM |
+ STM32H7_SPI_CFG2_AFCNTR);
spin_unlock_irqrestore(&spi->lock, flags);
return 0;
}
+static const struct stm32_spi_cfg stm32f4_spi_cfg = {
+ .regs = &stm32f4_spi_regspec,
+ .get_bpw_mask = stm32f4_spi_get_bpw_mask,
+ .disable = stm32f4_spi_disable,
+ .config = stm32f4_spi_config,
+ .set_bpw = stm32f4_spi_set_bpw,
+ .set_mode = stm32f4_spi_set_mode,
+ .transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start,
+ .dma_tx_cb = stm32f4_spi_dma_tx_cb,
+ .dma_rx_cb = stm32f4_spi_dma_rx_cb,
+ .transfer_one_irq = stm32f4_spi_transfer_one_irq,
+ .irq_handler_event = stm32f4_spi_irq_event,
+ .irq_handler_thread = stm32f4_spi_irq_thread,
+ .baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN,
+ .baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX,
+ .has_fifo = false,
+};
+
+static const struct stm32_spi_cfg stm32h7_spi_cfg = {
+ .regs = &stm32h7_spi_regspec,
+ .get_fifo_size = stm32h7_spi_get_fifo_size,
+ .get_bpw_mask = stm32h7_spi_get_bpw_mask,
+ .disable = stm32h7_spi_disable,
+ .config = stm32h7_spi_config,
+ .set_bpw = stm32h7_spi_set_bpw,
+ .set_mode = stm32h7_spi_set_mode,
+ .set_data_idleness = stm32h7_spi_data_idleness,
+ .set_number_of_data = stm32h7_spi_number_of_data,
+ .transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start,
+ .dma_rx_cb = stm32h7_spi_dma_cb,
+ .dma_tx_cb = stm32h7_spi_dma_cb,
+ .transfer_one_irq = stm32h7_spi_transfer_one_irq,
+ .irq_handler_thread = stm32h7_spi_irq_thread,
+ .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN,
+ .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX,
+ .has_fifo = true,
+};
+
static const struct of_device_id stm32_spi_of_match[] = {
- { .compatible = "st,stm32h7-spi", },
+ { .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg },
+ { .compatible = "st,stm32f4-spi", .data = (void *)&stm32f4_spi_cfg },
{},
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);
@@ -1090,12 +1824,17 @@ static int stm32_spi_probe(struct platform_device *pdev)
spi->master = master;
spin_lock_init(&spi->lock);
+ spi->cfg = (const struct stm32_spi_cfg *)
+ of_match_device(pdev->dev.driver->of_match_table,
+ &pdev->dev)->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spi->base)) {
ret = PTR_ERR(spi->base);
goto err_master_put;
}
+
spi->phys_addr = (dma_addr_t)res->start;
spi->irq = platform_get_irq(pdev, 0);
@@ -1104,16 +1843,17 @@ static int stm32_spi_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err_master_put;
}
- ret = devm_request_threaded_irq(&pdev->dev, spi->irq, NULL,
- stm32_spi_irq, IRQF_ONESHOT,
- pdev->name, master);
+ ret = devm_request_threaded_irq(&pdev->dev, spi->irq,
+ spi->cfg->irq_handler_event,
+ spi->cfg->irq_handler_thread,
+ IRQF_ONESHOT, pdev->name, master);
if (ret) {
dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq,
ret);
goto err_master_put;
}
- spi->clk = devm_clk_get(&pdev->dev, 0);
+ spi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(spi->clk)) {
ret = PTR_ERR(spi->clk);
dev_err(&pdev->dev, "clk get failed: %d\n", ret);
@@ -1139,9 +1879,10 @@ static int stm32_spi_probe(struct platform_device *pdev)
reset_control_deassert(spi->rst);
}
- spi->fifo_size = stm32_spi_get_fifo_size(spi);
+ if (spi->cfg->has_fifo)
+ spi->fifo_size = spi->cfg->get_fifo_size(spi);
- ret = stm32_spi_config(spi);
+ ret = spi->cfg->config(spi);
if (ret) {
dev_err(&pdev->dev, "controller configuration failed: %d\n",
ret);
@@ -1151,11 +1892,11 @@ static int stm32_spi_probe(struct platform_device *pdev)
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
master->bus_num = pdev->id;
- master->mode_bits = SPI_MODE_3 | SPI_CS_HIGH | SPI_LSB_FIRST |
- SPI_3WIRE | SPI_LOOP;
- master->bits_per_word_mask = stm32_spi_get_bpw_mask(spi);
- master->max_speed_hz = spi->clk_rate / SPI_MBR_DIV_MIN;
- master->min_speed_hz = spi->clk_rate / SPI_MBR_DIV_MAX;
+ master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
+ SPI_3WIRE;
+ master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
+ master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
+ master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
master->setup = stm32_spi_setup;
master->prepare_message = stm32_spi_prepare_msg;
master->transfer_one = stm32_spi_transfer_one;
@@ -1233,7 +1974,7 @@ static int stm32_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct stm32_spi *spi = spi_master_get_devdata(master);
- stm32_spi_disable(spi);
+ spi->cfg->disable(spi);
if (master->dma_tx)
dma_release_channel(master->dma_tx);
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 5f19016bbf10..b9fb6493cd6b 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -490,8 +490,8 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi)
ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG);
if (qspi->ctrl_base) {
regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
- MEM_CS_EN(spi->chip_select),
- MEM_CS_MASK);
+ MEM_CS_MASK,
+ MEM_CS_EN(spi->chip_select));
}
qspi->mmap_enabled = true;
}
@@ -503,7 +503,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi)
ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG);
if (qspi->ctrl_base)
regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
- 0, MEM_CS_MASK);
+ MEM_CS_MASK, 0);
qspi->mmap_enabled = false;
}
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 97d137591b18..e7e8ea1edcce 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1008,6 +1008,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
/* RX */
dma->sg_rx_p = kcalloc(num, sizeof(*dma->sg_rx_p), GFP_ATOMIC);
+ if (!dma->sg_rx_p)
+ return;
+
sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
/* offset, length setting */
sg = dma->sg_rx_p;
@@ -1068,6 +1071,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
}
dma->sg_tx_p = kcalloc(num, sizeof(*dma->sg_tx_p), GFP_ATOMIC);
+ if (!dma->sg_tx_p)
+ return;
+
sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
/* offset, length setting */
sg = dma->sg_tx_p;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9a7def7c3237..93986f879b09 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -19,6 +19,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/property.h>
@@ -578,7 +579,10 @@ int spi_add_device(struct spi_device *spi)
goto done;
}
- if (ctlr->cs_gpios)
+ /* Descriptors take precedence */
+ if (ctlr->cs_gpiods)
+ spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select];
+ else if (ctlr->cs_gpios)
spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
/* Drivers may modify this initial i/o setup, but will
@@ -772,10 +776,21 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
if (spi->mode & SPI_CS_HIGH)
enable = !enable;
- if (gpio_is_valid(spi->cs_gpio)) {
- /* Honour the SPI_NO_CS flag */
- if (!(spi->mode & SPI_NO_CS))
- gpio_set_value(spi->cs_gpio, !enable);
+ if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
+ /*
+ * Honour the SPI_NO_CS flag and invert the enable line, as
+ * active low is default for SPI. Execution paths that handle
+ * polarity inversion in gpiolib (such as device tree) will
+ * enforce active high using the SPI_CS_HIGH resulting in a
+ * double inversion through the code above.
+ */
+ if (!(spi->mode & SPI_NO_CS)) {
+ if (spi->cs_gpiod)
+ gpiod_set_value_cansleep(spi->cs_gpiod,
+ !enable);
+ else
+ gpio_set_value_cansleep(spi->cs_gpio, !enable);
+ }
/* Some SPI masters need both GPIO CS & slave_select */
if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
spi->controller->set_cs)
@@ -1615,13 +1630,21 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
spi->mode |= SPI_CPHA;
if (of_property_read_bool(nc, "spi-cpol"))
spi->mode |= SPI_CPOL;
- if (of_property_read_bool(nc, "spi-cs-high"))
- spi->mode |= SPI_CS_HIGH;
if (of_property_read_bool(nc, "spi-3wire"))
spi->mode |= SPI_3WIRE;
if (of_property_read_bool(nc, "spi-lsb-first"))
spi->mode |= SPI_LSB_FIRST;
+ /*
+ * For descriptors associated with the device, polarity inversion is
+ * handled in the gpiolib, so all chip selects are "active high" in
+ * the logical sense, the gpiolib will invert the line if need be.
+ */
+ if (ctlr->use_gpio_descriptors)
+ spi->mode |= SPI_CS_HIGH;
+ else if (of_property_read_bool(nc, "spi-cs-high"))
+ spi->mode |= SPI_CS_HIGH;
+
/* Device DUAL/QUAD mode */
if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
switch (value) {
@@ -2137,6 +2160,60 @@ static int of_spi_register_master(struct spi_controller *ctlr)
}
#endif
+/**
+ * spi_get_gpio_descs() - grab chip select GPIOs for the master
+ * @ctlr: The SPI master to grab GPIO descriptors for
+ */
+static int spi_get_gpio_descs(struct spi_controller *ctlr)
+{
+ int nb, i;
+ struct gpio_desc **cs;
+ struct device *dev = &ctlr->dev;
+
+ nb = gpiod_count(dev, "cs");
+ ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect);
+
+ /* No GPIOs at all is fine, else return the error */
+ if (nb == 0 || nb == -ENOENT)
+ return 0;
+ else if (nb < 0)
+ return nb;
+
+ cs = devm_kcalloc(dev, ctlr->num_chipselect, sizeof(*cs),
+ GFP_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+ ctlr->cs_gpiods = cs;
+
+ for (i = 0; i < nb; i++) {
+ /*
+ * Most chipselects are active low, the inverted
+ * semantics are handled by special quirks in gpiolib,
+ * so initializing them GPIOD_OUT_LOW here means
+ * "unasserted", in most cases this will drive the physical
+ * line high.
+ */
+ cs[i] = devm_gpiod_get_index_optional(dev, "cs", i,
+ GPIOD_OUT_LOW);
+
+ if (cs[i]) {
+ /*
+ * If we find a CS GPIO, name it after the device and
+ * chip select line.
+ */
+ char *gpioname;
+
+ gpioname = devm_kasprintf(dev, GFP_KERNEL, "%s CS%d",
+ dev_name(dev), i);
+ if (!gpioname)
+ return -ENOMEM;
+ gpiod_set_consumer_name(cs[i], gpioname);
+ }
+ }
+
+ return 0;
+}
+
static int spi_controller_check_ops(struct spi_controller *ctlr)
{
/*
@@ -2199,9 +2276,21 @@ int spi_register_controller(struct spi_controller *ctlr)
return status;
if (!spi_controller_is_slave(ctlr)) {
- status = of_spi_register_master(ctlr);
- if (status)
- return status;
+ if (ctlr->use_gpio_descriptors) {
+ status = spi_get_gpio_descs(ctlr);
+ if (status)
+ return status;
+ /*
+ * A controller using GPIO descriptors always
+ * supports SPI_CS_HIGH if need be.
+ */
+ ctlr->mode_bits |= SPI_CS_HIGH;
+ } else {
+ /* Legacy code path for GPIOs from DT */
+ status = of_spi_register_master(ctlr);
+ if (status)
+ return status;
+ }
}
/* even if it's just one always-selected device, there must
@@ -2915,6 +3004,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
* cs_change is set for each transfer.
*/
if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) ||
+ spi->cs_gpiod ||
gpio_is_valid(spi->cs_gpio))) {
size_t maxsize;
int ret;
@@ -2961,6 +3051,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
* it is not set for this transfer.
* Set transfer tx_nbits and rx_nbits as single transfer default
* (SPI_NBITS_SINGLE) if it is not set for this transfer.
+ * Ensure transfer word_delay is at least as long as that required by
+ * device itself.
*/
message->frame_length = 0;
list_for_each_entry(xfer, &message->transfers, transfer_list) {
@@ -3031,6 +3123,9 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
!(spi->mode & SPI_RX_QUAD))
return -EINVAL;
}
+
+ if (xfer->word_delay_usecs < spi->word_delay_usecs)
+ xfer->word_delay_usecs = spi->word_delay_usecs;
}
message->status = -EINPROGRESS;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index e4f608815c05..c0901b96cfe4 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -56,8 +56,6 @@ source "drivers/staging/iio/Kconfig"
source "drivers/staging/sm750fb/Kconfig"
-source "drivers/staging/xgifb/Kconfig"
-
source "drivers/staging/emxx_udc/Kconfig"
source "drivers/staging/speakup/Kconfig"
@@ -104,12 +102,16 @@ source "drivers/staging/pi433/Kconfig"
source "drivers/staging/mt7621-pci/Kconfig"
+source "drivers/staging/mt7621-pci-phy/Kconfig"
+
source "drivers/staging/mt7621-pinctrl/Kconfig"
source "drivers/staging/mt7621-spi/Kconfig"
source "drivers/staging/mt7621-dma/Kconfig"
+source "drivers/staging/ralink-gdma/Kconfig"
+
source "drivers/staging/mt7621-mmc/Kconfig"
source "drivers/staging/mt7621-eth/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 5868631e8f1b..57c6bce13ff4 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM750) += sm750fb/
-obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_MFD_NVEC) += nvec/
@@ -41,12 +40,14 @@ obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
obj-$(CONFIG_PI433) += pi433/
-obj-$(CONFIG_SOC_MT7621) += mt7621-pci/
-obj-$(CONFIG_SOC_MT7621) += mt7621-pinctrl/
-obj-$(CONFIG_SOC_MT7621) += mt7621-spi/
+obj-$(CONFIG_PCI_MT7621) += mt7621-pci/
+obj-$(CONFIG_PCI_MT7621_PHY) += mt7621-pci-phy/
+obj-$(CONFIG_PINCTRL_RT2880) += mt7621-pinctrl/
+obj-$(CONFIG_SPI_MT7621) += mt7621-spi/
obj-$(CONFIG_SOC_MT7621) += mt7621-dma/
-obj-$(CONFIG_SOC_MT7621) += mt7621-mmc/
-obj-$(CONFIG_SOC_MT7621) += mt7621-eth/
+obj-$(CONFIG_DMA_RALINK) += ralink-gdma/
+obj-$(CONFIG_MTK_MMC) += mt7621-mmc/
+obj-$(CONFIG_NET_MEDIATEK_SOC_STAGING) += mt7621-eth/
obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 90a8a9f1ac7d..74d497d39c5a 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -75,6 +75,9 @@ struct ashmem_range {
/* LRU list of unpinned pages, protected by ashmem_mutex */
static LIST_HEAD(ashmem_lru_list);
+static atomic_t ashmem_shrink_inflight = ATOMIC_INIT(0);
+static DECLARE_WAIT_QUEUE_HEAD(ashmem_shrink_wait);
+
/*
* long lru_count - The count of pages on our LRU list.
*
@@ -126,7 +129,8 @@ static inline bool page_range_in_range(struct ashmem_range *range,
page_range_subsumes_range(range, start, end);
}
-static inline bool range_before_page(struct ashmem_range *range, size_t page)
+static inline bool range_before_page(struct ashmem_range *range,
+ size_t page)
{
return range->pgend < page;
}
@@ -168,19 +172,15 @@ static inline void lru_del(struct ashmem_range *range)
* @end: The ending page (inclusive)
*
* This function is protected by ashmem_mutex.
- *
- * Return: 0 if successful, or -ENOMEM if there is an error
*/
-static int range_alloc(struct ashmem_area *asma,
- struct ashmem_range *prev_range, unsigned int purged,
- size_t start, size_t end)
+static void range_alloc(struct ashmem_area *asma,
+ struct ashmem_range *prev_range, unsigned int purged,
+ size_t start, size_t end,
+ struct ashmem_range **new_range)
{
- struct ashmem_range *range;
-
- range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
- if (!range)
- return -ENOMEM;
+ struct ashmem_range *range = *new_range;
+ *new_range = NULL;
range->asma = asma;
range->pgstart = start;
range->pgend = end;
@@ -190,8 +190,6 @@ static int range_alloc(struct ashmem_area *asma,
if (range_on_lru(range))
lru_add(range);
-
- return 0;
}
/**
@@ -438,7 +436,6 @@ out:
static unsigned long
ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
- struct ashmem_range *range, *next;
unsigned long freed = 0;
/* We might recurse into filesystem code, so bail out if necessary */
@@ -448,21 +445,33 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
if (!mutex_trylock(&ashmem_mutex))
return -1;
- list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
+ while (!list_empty(&ashmem_lru_list)) {
+ struct ashmem_range *range =
+ list_first_entry(&ashmem_lru_list, typeof(*range), lru);
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;
+ struct file *f = range->asma->file;
- range->asma->file->f_op->fallocate(range->asma->file,
- FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- start, end - start);
+ get_file(f);
+ atomic_inc(&ashmem_shrink_inflight);
range->purged = ASHMEM_WAS_PURGED;
lru_del(range);
freed += range_size(range);
+ mutex_unlock(&ashmem_mutex);
+ f->f_op->fallocate(f,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ start, end - start);
+ fput(f);
+ if (atomic_dec_and_test(&ashmem_shrink_inflight))
+ wake_up_all(&ashmem_shrink_wait);
+ if (!mutex_trylock(&ashmem_mutex))
+ goto out;
if (--sc->nr_to_scan <= 0)
break;
}
mutex_unlock(&ashmem_mutex);
+out:
return freed;
}
@@ -582,7 +591,8 @@ static int get_name(struct ashmem_area *asma, void __user *name)
*
* Caller must hold ashmem_mutex.
*/
-static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
+static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend,
+ struct ashmem_range **new_range)
{
struct ashmem_range *range, *next;
int ret = ASHMEM_NOT_PURGED;
@@ -635,7 +645,7 @@ static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
* second half and adjust the first chunk's endpoint.
*/
range_alloc(asma, range, range->purged,
- pgend + 1, range->pgend);
+ pgend + 1, range->pgend, new_range);
range_shrink(range, range->pgstart, pgstart - 1);
break;
}
@@ -649,7 +659,8 @@ static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
*
* Caller must hold ashmem_mutex.
*/
-static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
+static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend,
+ struct ashmem_range **new_range)
{
struct ashmem_range *range, *next;
unsigned int purged = ASHMEM_NOT_PURGED;
@@ -675,7 +686,8 @@ restart:
}
}
- return range_alloc(asma, range, purged, pgstart, pgend);
+ range_alloc(asma, range, purged, pgstart, pgend, new_range);
+ return 0;
}
/*
@@ -708,11 +720,19 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
struct ashmem_pin pin;
size_t pgstart, pgend;
int ret = -EINVAL;
+ struct ashmem_range *range = NULL;
if (copy_from_user(&pin, p, sizeof(pin)))
return -EFAULT;
+ if (cmd == ASHMEM_PIN || cmd == ASHMEM_UNPIN) {
+ range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+ }
+
mutex_lock(&ashmem_mutex);
+ wait_event(ashmem_shrink_wait, !atomic_read(&ashmem_shrink_inflight));
if (!asma->file)
goto out_unlock;
@@ -735,10 +755,10 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
switch (cmd) {
case ASHMEM_PIN:
- ret = ashmem_pin(asma, pgstart, pgend);
+ ret = ashmem_pin(asma, pgstart, pgend, &range);
break;
case ASHMEM_UNPIN:
- ret = ashmem_unpin(asma, pgstart, pgend);
+ ret = ashmem_unpin(asma, pgstart, pgend, &range);
break;
case ASHMEM_GET_PIN_STATUS:
ret = ashmem_get_pin_status(asma, pgstart, pgend);
@@ -747,6 +767,8 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
out_unlock:
mutex_unlock(&ashmem_mutex);
+ if (range)
+ kmem_cache_free(ashmem_range_cachep, range);
return ret;
}
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index bb30bf8774a0..17f3a7569e3d 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o
+obj-$(CONFIG_ION) += ion.o ion_heap.o
obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o
obj-$(CONFIG_ION_CARVEOUT_HEAP) += ion_carveout_heap.o
obj-$(CONFIG_ION_CHUNK_HEAP) += ion_chunk_heap.o
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c
deleted file mode 100644
index a8d3cc412fb9..000000000000
--- a/drivers/staging/android/ion/ion-ioctl.c
+++ /dev/null
@@ -1,98 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2011 Google, Inc.
- */
-
-#include <linux/kernel.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-
-#include "ion.h"
-
-union ion_ioctl_arg {
- struct ion_allocation_data allocation;
- struct ion_heap_query query;
-};
-
-static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg)
-{
- switch (cmd) {
- case ION_IOC_HEAP_QUERY:
- if (arg->query.reserved0 ||
- arg->query.reserved1 ||
- arg->query.reserved2)
- return -EINVAL;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-/* fix up the cases where the ioctl direction bits are incorrect */
-static unsigned int ion_ioctl_dir(unsigned int cmd)
-{
- switch (cmd) {
- default:
- return _IOC_DIR(cmd);
- }
-}
-
-long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int ret = 0;
- unsigned int dir;
- union ion_ioctl_arg data;
-
- dir = ion_ioctl_dir(cmd);
-
- if (_IOC_SIZE(cmd) > sizeof(data))
- return -EINVAL;
-
- /*
- * The copy_from_user is unconditional here for both read and write
- * to do the validate. If there is no write for the ioctl, the
- * buffer is cleared
- */
- if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd)))
- return -EFAULT;
-
- ret = validate_ioctl_arg(cmd, &data);
- if (ret) {
- pr_warn_once("%s: ioctl validate failed\n", __func__);
- return ret;
- }
-
- if (!(dir & _IOC_WRITE))
- memset(&data, 0, sizeof(data));
-
- switch (cmd) {
- case ION_IOC_ALLOC:
- {
- int fd;
-
- fd = ion_alloc(data.allocation.len,
- data.allocation.heap_id_mask,
- data.allocation.flags);
- if (fd < 0)
- return fd;
-
- data.allocation.fd = fd;
-
- break;
- }
- case ION_IOC_HEAP_QUERY:
- ret = ion_query_heaps(&data.query);
- break;
- default:
- return -ENOTTY;
- }
-
- if (dir & _IOC_READ) {
- if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd)))
- return -EFAULT;
- }
- return ret;
-}
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index a0802de8c3a1..92c2914239e3 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion.c
+ * ION Memory Allocator
*
* Copyright (C) 2011 Google, Inc.
*/
-#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
@@ -14,10 +13,8 @@
#include <linux/file.h>
#include <linux/freezer.h>
#include <linux/fs.h>
-#include <linux/idr.h>
#include <linux/kthread.h>
#include <linux/list.h>
-#include <linux/memblock.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
@@ -248,10 +245,10 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
struct ion_dma_buf_attachment *a = attachment->priv;
struct ion_buffer *buffer = dmabuf->priv;
- free_duped_table(a->table);
mutex_lock(&buffer->lock);
list_del(&a->list);
mutex_unlock(&buffer->lock);
+ free_duped_table(a->table);
kfree(a);
}
@@ -390,7 +387,7 @@ static const struct dma_buf_ops dma_buf_ops = {
.unmap = ion_dma_buf_kunmap,
};
-int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
+static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
{
struct ion_device *dev = internal_dev;
struct ion_buffer *buffer = NULL;
@@ -447,7 +444,7 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
return fd;
}
-int ion_query_heaps(struct ion_heap_query *query)
+static int ion_query_heaps(struct ion_heap_query *query)
{
struct ion_device *dev = internal_dev;
struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps);
@@ -492,6 +489,81 @@ out:
return ret;
}
+union ion_ioctl_arg {
+ struct ion_allocation_data allocation;
+ struct ion_heap_query query;
+};
+
+static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg)
+{
+ switch (cmd) {
+ case ION_IOC_HEAP_QUERY:
+ if (arg->query.reserved0 ||
+ arg->query.reserved1 ||
+ arg->query.reserved2)
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ union ion_ioctl_arg data;
+
+ if (_IOC_SIZE(cmd) > sizeof(data))
+ return -EINVAL;
+
+ /*
+ * The copy_from_user is unconditional here for both read and write
+ * to do the validate. If there is no write for the ioctl, the
+ * buffer is cleared
+ */
+ if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd)))
+ return -EFAULT;
+
+ ret = validate_ioctl_arg(cmd, &data);
+ if (ret) {
+ pr_warn_once("%s: ioctl validate failed\n", __func__);
+ return ret;
+ }
+
+ if (!(_IOC_DIR(cmd) & _IOC_WRITE))
+ memset(&data, 0, sizeof(data));
+
+ switch (cmd) {
+ case ION_IOC_ALLOC:
+ {
+ int fd;
+
+ fd = ion_alloc(data.allocation.len,
+ data.allocation.heap_id_mask,
+ data.allocation.flags);
+ if (fd < 0)
+ return fd;
+
+ data.allocation.fd = fd;
+
+ break;
+ }
+ case ION_IOC_HEAP_QUERY:
+ ret = ion_query_heaps(&data.query);
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_READ) {
+ if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd)))
+ return -EFAULT;
+ }
+ return ret;
+}
+
static const struct file_operations ion_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = ion_ioctl,
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index 47b594cf1ac9..e291299fd35f 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * drivers/staging/android/ion/ion.h
+ * ION Memory Allocator kernel interface header
*
* Copyright (C) 2011 Google, Inc.
*/
@@ -22,32 +22,9 @@
#include "../uapi/ion.h"
/**
- * struct ion_platform_heap - defines a heap in the given platform
- * @type: type of the heap from ion_heap_type enum
- * @id: unique identifier for heap. When allocating higher numb ers
- * will be allocated from first. At allocation these are passed
- * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS.
- * @name: used for debug purposes
- * @base: base address of heap in physical memory if applicable
- * @size: size of the heap in bytes if applicable
- * @priv: private info passed from the board file
- *
- * Provided by the board file.
- */
-struct ion_platform_heap {
- enum ion_heap_type type;
- unsigned int id;
- const char *name;
- phys_addr_t base;
- size_t size;
- phys_addr_t align;
- void *priv;
-};
-
-/**
* struct ion_buffer - metadata for a particular buffer
- * @ref: reference count
* @node: node in the ion_device buffers tree
+ * @list: element in list of deferred freeable buffers
* @dev: back pointer to the ion_device
* @heap: back pointer to the heap the buffer came from
* @flags: buffer specific flags
@@ -58,7 +35,8 @@ struct ion_platform_heap {
* @lock: protects the buffers cnt fields
* @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
+ * @sg_table: the sg table for the buffer
+ * @attachments: list of devices attached to this buffer
*/
struct ion_buffer {
union {
@@ -174,12 +152,16 @@ struct ion_heap {
unsigned long flags;
unsigned int id;
const char *name;
+
+ /* deferred free support */
struct shrinker shrinker;
struct list_head free_list;
size_t free_list_size;
spinlock_t free_lock;
wait_queue_head_t waitqueue;
struct task_struct *task;
+
+ /* heap statistics */
u64 num_of_buffers;
u64 num_of_alloc_bytes;
u64 alloc_bytes_wm;
@@ -205,10 +187,6 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
int ion_heap_buffer_zero(struct ion_buffer *buffer);
int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
-int ion_alloc(size_t len,
- unsigned int heap_id_mask,
- unsigned int flags);
-
/**
* ion_heap_init_shrinker
* @heap: the heap
@@ -330,8 +308,4 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page);
int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
int nr_to_scan);
-long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-
-int ion_query_heaps(struct ion_heap_query *query);
-
#endif /* _ION_H */
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index e129237a0417..bb9d614767a2 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_carveout_heap.c
+ * ION Memory Allocator carveout heap helper
*
* Copyright (C) 2011 Google, Inc.
*/
-#include <linux/spinlock.h>
+
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/genalloc.h>
@@ -12,7 +12,7 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
+
#include "ion.h"
#define ION_CARVEOUT_ALLOCATE_FAIL -1
@@ -20,7 +20,6 @@
struct ion_carveout_heap {
struct ion_heap heap;
struct gen_pool *pool;
- phys_addr_t base;
};
static phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
@@ -44,6 +43,7 @@ static void ion_carveout_free(struct ion_heap *heap, phys_addr_t addr,
if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
return;
+
gen_pool_free(carveout_heap->pool, addr, size);
}
@@ -103,17 +103,14 @@ static struct ion_heap_ops carveout_heap_ops = {
.unmap_kernel = ion_heap_unmap_kernel,
};
-struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
+struct ion_heap *ion_carveout_heap_create(phys_addr_t base, size_t size)
{
struct ion_carveout_heap *carveout_heap;
int ret;
struct page *page;
- size_t size;
-
- page = pfn_to_page(PFN_DOWN(heap_data->base));
- size = heap_data->size;
+ page = pfn_to_page(PFN_DOWN(base));
ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
if (ret)
return ERR_PTR(ret);
@@ -127,9 +124,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
kfree(carveout_heap);
return ERR_PTR(-ENOMEM);
}
- carveout_heap->base = heap_data->base;
- gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size,
- -1);
+ gen_pool_add(carveout_heap->pool, base, size, -1);
carveout_heap->heap.ops = &carveout_heap_ops;
carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 159d72f5bc42..3cdde9c1a717 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -1,23 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_chunk_heap.c
+ * ION memory allocator chunk heap helper
*
* Copyright (C) 2012 Google, Inc.
*/
+
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/genalloc.h>
-#include <linux/io.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
+
#include "ion.h"
struct ion_chunk_heap {
struct ion_heap heap;
struct gen_pool *pool;
- phys_addr_t base;
unsigned long chunk_size;
unsigned long size;
unsigned long allocated;
@@ -108,16 +107,13 @@ static struct ion_heap_ops chunk_heap_ops = {
.unmap_kernel = ion_heap_unmap_kernel,
};
-struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
+struct ion_heap *ion_chunk_heap_create(phys_addr_t base, size_t size, size_t chunk_size)
{
struct ion_chunk_heap *chunk_heap;
int ret;
struct page *page;
- size_t size;
-
- page = pfn_to_page(PFN_DOWN(heap_data->base));
- size = heap_data->size;
+ page = pfn_to_page(PFN_DOWN(base));
ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
if (ret)
return ERR_PTR(ret);
@@ -126,23 +122,21 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
if (!chunk_heap)
return ERR_PTR(-ENOMEM);
- chunk_heap->chunk_size = (unsigned long)heap_data->priv;
+ chunk_heap->chunk_size = chunk_size;
chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) +
PAGE_SHIFT, -1);
if (!chunk_heap->pool) {
ret = -ENOMEM;
goto error_gen_pool_create;
}
- chunk_heap->base = heap_data->base;
- chunk_heap->size = heap_data->size;
+ chunk_heap->size = size;
chunk_heap->allocated = 0;
- gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1);
+ gen_pool_add(chunk_heap->pool, base, size, -1);
chunk_heap->heap.ops = &chunk_heap_ops;
chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
- pr_debug("%s: base %pa size %zu\n", __func__,
- &chunk_heap->base, heap_data->size);
+ pr_debug("%s: base %pa size %zu\n", __func__, &base, size);
return &chunk_heap->heap;
@@ -150,4 +144,3 @@ error_gen_pool_create:
kfree(chunk_heap);
return ERR_PTR(ret);
}
-
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index 3fafd013d80a..bf65e67ef9d8 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_cma_heap.c
+ * ION Memory Allocator CMA heap exporter
*
* Copyright (C) Linaro 2012
* Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
@@ -111,10 +111,6 @@ static struct ion_heap *__ion_cma_heap_create(struct cma *cma)
return ERR_PTR(-ENOMEM);
cma_heap->heap.ops = &ion_cma_ops;
- /*
- * get device from private heaps data, later it will be
- * used to make the link with reserved CMA memory
- */
cma_heap->cma = cma;
cma_heap->heap.type = ION_HEAP_TYPE_DMA;
return &cma_heap->heap;
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index 31db510018a9..473b465724f1 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_heap.c
+ * ION Memory Allocator generic heap helpers
*
* Copyright (C) 2011 Google, Inc.
*/
@@ -14,6 +14,7 @@
#include <uapi/linux/sched/types.h>
#include <linux/scatterlist.h>
#include <linux/vmalloc.h>
+
#include "ion.h"
void *ion_heap_map_kernel(struct ion_heap *heap,
@@ -92,6 +93,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
if (addr >= vma->vm_end)
return 0;
}
+
return 0;
}
@@ -254,6 +256,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap)
return PTR_ERR_OR_ZERO(heap->task);
}
sched_setscheduler(heap->task, SCHED_IDLE, &param);
+
return 0;
}
@@ -265,8 +268,10 @@ static unsigned long ion_heap_shrink_count(struct shrinker *shrinker,
int total = 0;
total = ion_heap_freelist_size(heap) / PAGE_SIZE;
+
if (heap->ops->shrink)
total += heap->ops->shrink(heap, sc->gfp_mask, 0);
+
return total;
}
@@ -295,6 +300,7 @@ static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
if (heap->ops->shrink)
freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan);
+
return freed;
}
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index 0d2a95957ee8..fd4995fb676e 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_mem_pool.c
+ * ION Memory Allocator page pool helpers
*
* Copyright (C) 2011 Google, Inc.
*/
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 0383f7548d48..aa8d8425be25 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/staging/android/ion/ion_system_heap.c
+ * ION Memory Allocator system heap exporter
*
* Copyright (C) 2011 Google, Inc.
*/
@@ -13,6 +13,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+
#include "ion.h"
#define NUM_ORDERS ARRAY_SIZE(orders)
@@ -223,10 +224,10 @@ static void ion_system_heap_destroy_pools(struct ion_page_pool **pools)
static int ion_system_heap_create_pools(struct ion_page_pool **pools)
{
int i;
- gfp_t gfp_flags = low_order_gfp_flags;
for (i = 0; i < NUM_ORDERS; i++) {
struct ion_page_pool *pool;
+ gfp_t gfp_flags = low_order_gfp_flags;
if (orders[i] > 4)
gfp_flags = high_order_gfp_flags;
@@ -236,6 +237,7 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools)
goto err_create_pool;
pools[i] = pool;
}
+
return 0;
err_create_pool:
@@ -274,6 +276,7 @@ static int ion_system_heap_create(void)
heap->name = "ion_system_heap";
ion_device_add_heap(heap);
+
return 0;
}
device_initcall(ion_system_heap_create);
@@ -355,6 +358,7 @@ static struct ion_heap *__ion_system_contig_heap_create(void)
heap->ops = &kmalloc_ops;
heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
heap->name = "ion_system_contig_heap";
+
return heap;
}
@@ -367,7 +371,7 @@ static int ion_system_contig_heap_create(void)
return PTR_ERR(heap);
ion_device_add_heap(heap);
+
return 0;
}
device_initcall(ion_system_contig_heap_create);
-
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index 5d7009884c13..46c93fcb46d6 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* drivers/staging/android/uapi/ion.h
*
diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c
index 22571abcaa4e..8a75bd27c413 100644
--- a/drivers/staging/android/vsoc.c
+++ b/drivers/staging/android/vsoc.c
@@ -29,7 +29,6 @@
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
-#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/file.h>
#include "uapi/vsoc_shm.h"
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 5d2fcbfe02af..0caae4a5c471 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1605,9 +1605,8 @@ static int do_insn_ioctl(struct comedi_device *dev,
unsigned int n_data = MIN_SAMPLES;
int ret = 0;
- if (copy_from_user(&insn, arg, sizeof(insn))) {
+ if (copy_from_user(&insn, arg, sizeof(insn)))
return -EFAULT;
- }
n_data = max(n_data, insn.n);
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 4e72a0778086..a9d052bfda38 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -252,9 +252,9 @@ static int cb_pcimdas_di_insn_bits(struct comedi_device *dev,
}
static int cb_pcimdas_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcimdas_private *devpriv = dev->private;
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index e70a461e723f..405573e927cf 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -656,6 +656,7 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev,
case NI_660X_PFI_OUTPUT_DIO:
if (chan > 31)
return -EINVAL;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index b9a0dc6eac44..4bdef87d5dd7 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -49,116 +49,117 @@
/* defines for the PCI-DIO-32HS */
-#define Window_Address 4 /* W */
-#define Interrupt_And_Window_Status 4 /* R */
-#define IntStatus1 BIT(0)
-#define IntStatus2 BIT(1)
-#define WindowAddressStatus_mask 0x7c
-
-#define Master_DMA_And_Interrupt_Control 5 /* W */
-#define InterruptLine(x) ((x) & 3)
-#define OpenInt BIT(2)
-#define Group_Status 5 /* R */
-#define DataLeft BIT(0)
-#define Req BIT(2)
-#define StopTrig BIT(3)
-
-#define Group_1_Flags 6 /* R */
-#define Group_2_Flags 7 /* R */
-#define TransferReady BIT(0)
-#define CountExpired BIT(1)
-#define Waited BIT(5)
-#define PrimaryTC BIT(6)
-#define SecondaryTC BIT(7)
+#define WINDOW_ADDRESS 4 /* W */
+#define INTERRUPT_AND_WINDOW_STATUS 4 /* R */
+#define INT_STATUS_1 BIT(0)
+#define INT_STATUS_2 BIT(1)
+#define WINDOW_ADDRESS_STATUS_MASK 0x7c
+
+#define MASTER_DMA_AND_INTERRUPT_CONTROL 5 /* W */
+#define INTERRUPT_LINE(x) ((x) & 3)
+#define OPEN_INT BIT(2)
+#define GROUP_STATUS 5 /* R */
+#define DATA_LEFT BIT(0)
+#define REQ BIT(2)
+#define STOP_TRIG BIT(3)
+
+#define GROUP_1_FLAGS 6 /* R */
+#define GROUP_2_FLAGS 7 /* R */
+#define TRANSFER_READY BIT(0)
+#define COUNT_EXPIRED BIT(1)
+#define WAITED BIT(5)
+#define PRIMARY_TC BIT(6)
+#define SECONDARY_TC BIT(7)
/* #define SerialRose */
/* #define ReqRose */
/* #define Paused */
-#define Group_1_First_Clear 6 /* W */
-#define Group_2_First_Clear 7 /* W */
-#define ClearWaited BIT(3)
-#define ClearPrimaryTC BIT(4)
-#define ClearSecondaryTC BIT(5)
-#define DMAReset BIT(6)
-#define FIFOReset BIT(7)
-#define ClearAll 0xf8
-
-#define Group_1_FIFO 8 /* W */
-#define Group_2_FIFO 12 /* W */
-
-#define Transfer_Count 20
-#define Chip_ID_D 24
-#define Chip_ID_I 25
-#define Chip_ID_O 26
-#define Chip_Version 27
-#define Port_IO(x) (28 + (x))
-#define Port_Pin_Directions(x) (32 + (x))
-#define Port_Pin_Mask(x) (36 + (x))
-#define Port_Pin_Polarities(x) (40 + (x))
-
-#define Master_Clock_Routing 45
-#define RTSIClocking(x) (((x) & 3) << 4)
-
-#define Group_1_Second_Clear 46 /* W */
-#define Group_2_Second_Clear 47 /* W */
-#define ClearExpired BIT(0)
-
-#define Port_Pattern(x) (48 + (x))
-
-#define Data_Path 64
-#define FIFOEnableA BIT(0)
-#define FIFOEnableB BIT(1)
-#define FIFOEnableC BIT(2)
-#define FIFOEnableD BIT(3)
-#define Funneling(x) (((x) & 3) << 4)
-#define GroupDirection BIT(7)
-
-#define Protocol_Register_1 65
-#define OpMode Protocol_Register_1
-#define RunMode(x) ((x) & 7)
-#define Numbered BIT(3)
-
-#define Protocol_Register_2 66
-#define ClockReg Protocol_Register_2
-#define ClockLine(x) (((x) & 3) << 5)
-#define InvertStopTrig BIT(7)
-#define DataLatching(x) (((x) & 3) << 5)
-
-#define Protocol_Register_3 67
-#define Sequence Protocol_Register_3
-
-#define Protocol_Register_14 68 /* 16 bit */
-#define ClockSpeed Protocol_Register_14
-
-#define Protocol_Register_4 70
-#define ReqReg Protocol_Register_4
-#define ReqConditioning(x) (((x) & 7) << 3)
-
-#define Protocol_Register_5 71
-#define BlockMode Protocol_Register_5
+#define GROUP_1_FIRST_CLEAR 6 /* W */
+#define GROUP_2_FIRST_CLEAR 7 /* W */
+#define CLEAR_WAITED BIT(3)
+#define CLEAR_PRIMARY_TC BIT(4)
+#define CLEAR_SECONDARY_TC BIT(5)
+#define DMA_RESET BIT(6)
+#define FIFO_RESET BIT(7)
+#define CLEAR_ALL 0xf8
+
+#define GROUP_1_FIFO 8 /* W */
+#define GROUP_2_FIFO 12 /* W */
+
+#define TRANSFER_COUNT 20
+#define CHIP_ID_D 24
+#define CHIP_ID_I 25
+#define CHIP_ID_O 26
+#define CHIP_VERSION 27
+#define PORT_IO(x) (28 + (x))
+#define PORT_PIN_DIRECTIONS(x) (32 + (x))
+#define PORT_PIN_MASK(x) (36 + (x))
+#define PORT_PIN_POLARITIES(x) (40 + (x))
+
+#define MASTER_CLOCK_ROUTING 45
+#define RTSI_CLOCKING(x) (((x) & 3) << 4)
+
+#define GROUP_1_SECOND_CLEAR 46 /* W */
+#define GROUP_2_SECOND_CLEAR 47 /* W */
+#define CLEAR_EXPIRED BIT(0)
+
+#define PORT_PATTERN(x) (48 + (x))
+
+#define DATA_PATH 64
+#define FIFO_ENABLE_A BIT(0)
+#define FIFO_ENABLE_B BIT(1)
+#define FIFO_ENABLE_C BIT(2)
+#define FIFO_ENABLE_D BIT(3)
+#define FUNNELING(x) (((x) & 3) << 4)
+#define GROUP_DIRECTION BIT(7)
+
+#define PROTOCOL_REGISTER_1 65
+#define OP_MODE PROTOCOL_REGISTER_1
+#define RUN_MODE(x) ((x) & 7)
+#define NUMBERED BIT(3)
+
+#define PROTOCOL_REGISTER_2 66
+#define CLOCK_REG PROTOCOL_REGISTER_2
+#define CLOCK_LINE(x) (((x) & 3) << 5)
+#define INVERT_STOP_TRIG BIT(7)
+#define DATA_LATCHING(x) (((x) & 3) << 5)
+
+#define PROTOCOL_REGISTER_3 67
+#define SEQUENCE PROTOCOL_REGISTER_3
+
+#define PROTOCOL_REGISTER_14 68 /* 16 bit */
+#define CLOCK_SPEED PROTOCOL_REGISTER_14
+
+#define PROTOCOL_REGISTER_4 70
+#define REQ_REG PROTOCOL_REGISTER_4
+#define REQ_CONDITIONING(x) (((x) & 7) << 3)
+
+#define PROTOCOL_REGISTER_5 71
+#define BLOCK_MODE PROTOCOL_REGISTER_5
#define FIFO_Control 72
-#define ReadyLevel(x) ((x) & 7)
-
-#define Protocol_Register_6 73
-#define LinePolarities Protocol_Register_6
-#define InvertAck BIT(0)
-#define InvertReq BIT(1)
-#define InvertClock BIT(2)
-#define InvertSerial BIT(3)
-#define OpenAck BIT(4)
-#define OpenClock BIT(5)
-
-#define Protocol_Register_7 74
-#define AckSer Protocol_Register_7
-#define AckLine(x) (((x) & 3) << 2)
-#define ExchangePins BIT(7)
-
-#define Interrupt_Control 75
- /* bits same as flags */
-
-#define DMA_Line_Control_Group1 76
-#define DMA_Line_Control_Group2 108
+#define READY_LEVEL(x) ((x) & 7)
+
+#define PROTOCOL_REGISTER_6 73
+#define LINE_POLARITIES PROTOCOL_REGISTER_6
+#define INVERT_ACK BIT(0)
+#define INVERT_REQ BIT(1)
+#define INVERT_CLOCK BIT(2)
+#define INVERT_SERIAL BIT(3)
+#define OPEN_ACK BIT(4)
+#define OPEN_CLOCK BIT(5)
+
+#define PROTOCOL_REGISTER_7 74
+#define ACK_SER PROTOCOL_REGISTER_7
+#define ACK_LINE(x) (((x) & 3) << 2)
+#define EXCHANGE_PINS BIT(7)
+
+#define INTERRUPT_CONTROL 75
+/* bits same as flags */
+
+#define DMA_LINE_CONTROL_GROUP1 76
+#define DMA_LINE_CONTROL_GROUP2 108
+
/* channel zero is none */
static inline unsigned int primary_DMAChannel_bits(unsigned int channel)
{
@@ -170,41 +171,41 @@ static inline unsigned int secondary_DMAChannel_bits(unsigned int channel)
return (channel << 2) & 0xc;
}
-#define Transfer_Size_Control 77
-#define TransferWidth(x) ((x) & 3)
-#define TransferLength(x) (((x) & 3) << 3)
-#define RequireRLevel BIT(5)
+#define TRANSFER_SIZE_CONTROL 77
+#define TRANSFER_WIDTH(x) ((x) & 3)
+#define TRANSFER_LENGTH(x) (((x) & 3) << 3)
+#define REQUIRE_R_LEVEL BIT(5)
-#define Protocol_Register_15 79
-#define DAQOptions Protocol_Register_15
-#define StartSource(x) ((x) & 0x3)
-#define InvertStart BIT(2)
-#define StopSource(x) (((x) & 0x3) << 3)
-#define ReqStart BIT(6)
-#define PreStart BIT(7)
+#define PROTOCOL_REGISTER_15 79
+#define DAQ_OPTIONS PROTOCOL_REGISTER_15
+#define START_SOURCE(x) ((x) & 0x3)
+#define INVERT_START BIT(2)
+#define STOP_SOURCE(x) (((x) & 0x3) << 3)
+#define REQ_START BIT(6)
+#define PRE_START BIT(7)
-#define Pattern_Detection 81
-#define DetectionMethod BIT(0)
-#define InvertMatch BIT(1)
-#define IE_Pattern_Detection BIT(2)
+#define PATTERN_DETECTION 81
+#define DETECTION_METHOD BIT(0)
+#define INVERT_MATCH BIT(1)
+#define IE_PATTERN_DETECTION BIT(2)
-#define Protocol_Register_9 82
-#define ReqDelay Protocol_Register_9
+#define PROTOCOL_REGISTER_9 82
+#define REQ_DELAY PROTOCOL_REGISTER_9
-#define Protocol_Register_10 83
-#define ReqNotDelay Protocol_Register_10
+#define PROTOCOL_REGISTER_10 83
+#define REQ_NOT_DELAY PROTOCOL_REGISTER_10
-#define Protocol_Register_11 84
-#define AckDelay Protocol_Register_11
+#define PROTOCOL_REGISTER_11 84
+#define ACK_DELAY PROTOCOL_REGISTER_11
-#define Protocol_Register_12 85
-#define AckNotDelay Protocol_Register_12
+#define PROTOCOL_REGISTER_12 85
+#define ACK_NOT_DELAY PROTOCOL_REGISTER_12
-#define Protocol_Register_13 86
-#define Data1Delay Protocol_Register_13
+#define PROTOCOL_REGISTER_13 86
+#define DATA_1_DELAY PROTOCOL_REGISTER_13
-#define Protocol_Register_8 88 /* 32 bit */
-#define StartDelay Protocol_Register_8
+#define PROTOCOL_REGISTER_8 88 /* 32 bit */
+#define START_DELAY PROTOCOL_REGISTER_8
/* Firmware files for PCI-6524 */
#define FW_PCI_6534_MAIN "ni6534a.bin"
@@ -246,9 +247,10 @@ enum FPGA_Control_Bits {
#define TIMER_BASE 50 /* nanoseconds */
#ifdef USE_DMA
-#define IntEn (CountExpired | Waited | PrimaryTC | SecondaryTC)
+#define INT_EN (COUNT_EXPIRED | WAITED | PRIMARY_TC | SECONDARY_TC)
#else
-#define IntEn (TransferReady | CountExpired | Waited | PrimaryTC | SecondaryTC)
+#define INT_EN (TRANSFER_READY | COUNT_EXPIRED | WAITED \
+ | PRIMARY_TC | SECONDARY_TC)
#endif
enum nidio_boardid {
@@ -283,7 +285,7 @@ struct nidio96_private {
struct mite *mite;
int boardtype;
int dio;
- unsigned short OpModeBits;
+ unsigned short OP_MODEBits;
struct mite_channel *di_mite_chan;
struct mite_ring *di_mite_ring;
spinlock_t mite_channel_lock;
@@ -307,7 +309,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
devpriv->di_mite_chan->dir = COMEDI_INPUT;
writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
- dev->mmio + DMA_Line_Control_Group1);
+ dev->mmio + DMA_LINE_CONTROL_GROUP1);
mmiowb();
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
@@ -324,7 +326,7 @@ static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
devpriv->di_mite_chan = NULL;
writeb(primary_DMAChannel_bits(0) |
secondary_DMAChannel_bits(0),
- dev->mmio + DMA_Line_Control_Group1);
+ dev->mmio + DMA_LINE_CONTROL_GROUP1);
mmiowb();
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
@@ -391,8 +393,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
/* Lock to avoid race with comedi_poll */
spin_lock(&dev->spinlock);
- status = readb(dev->mmio + Interrupt_And_Window_Status);
- flags = readb(dev->mmio + Group_1_Flags);
+ status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS);
+ flags = readb(dev->mmio + GROUP_1_FLAGS);
spin_lock(&devpriv->mite_channel_lock);
if (devpriv->di_mite_chan) {
@@ -401,63 +403,63 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
}
spin_unlock(&devpriv->mite_channel_lock);
- while (status & DataLeft) {
+ while (status & DATA_LEFT) {
work++;
if (work > 20) {
dev_dbg(dev->class_dev, "too much work in interrupt\n");
writeb(0x00,
- dev->mmio + Master_DMA_And_Interrupt_Control);
+ dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
break;
}
- flags &= IntEn;
+ flags &= INT_EN;
- if (flags & TransferReady) {
- while (flags & TransferReady) {
+ if (flags & TRANSFER_READY) {
+ while (flags & TRANSFER_READY) {
work++;
if (work > 100) {
dev_dbg(dev->class_dev,
"too much work in interrupt\n");
writeb(0x00, dev->mmio +
- Master_DMA_And_Interrupt_Control
+ MASTER_DMA_AND_INTERRUPT_CONTROL
);
goto out;
}
- auxdata = readl(dev->mmio + Group_1_FIFO);
+ auxdata = readl(dev->mmio + GROUP_1_FIFO);
comedi_buf_write_samples(s, &auxdata, 1);
- flags = readb(dev->mmio + Group_1_Flags);
+ flags = readb(dev->mmio + GROUP_1_FLAGS);
}
}
- if (flags & CountExpired) {
- writeb(ClearExpired, dev->mmio + Group_1_Second_Clear);
+ if (flags & COUNT_EXPIRED) {
+ writeb(CLEAR_EXPIRED, dev->mmio + GROUP_1_SECOND_CLEAR);
async->events |= COMEDI_CB_EOA;
- writeb(0x00, dev->mmio + OpMode);
+ writeb(0x00, dev->mmio + OP_MODE);
break;
- } else if (flags & Waited) {
- writeb(ClearWaited, dev->mmio + Group_1_First_Clear);
+ } else if (flags & WAITED) {
+ writeb(CLEAR_WAITED, dev->mmio + GROUP_1_FIRST_CLEAR);
async->events |= COMEDI_CB_ERROR;
break;
- } else if (flags & PrimaryTC) {
- writeb(ClearPrimaryTC,
- dev->mmio + Group_1_First_Clear);
+ } else if (flags & PRIMARY_TC) {
+ writeb(CLEAR_PRIMARY_TC,
+ dev->mmio + GROUP_1_FIRST_CLEAR);
async->events |= COMEDI_CB_EOA;
- } else if (flags & SecondaryTC) {
- writeb(ClearSecondaryTC,
- dev->mmio + Group_1_First_Clear);
+ } else if (flags & SECONDARY_TC) {
+ writeb(CLEAR_SECONDARY_TC,
+ dev->mmio + GROUP_1_FIRST_CLEAR);
async->events |= COMEDI_CB_EOA;
}
- flags = readb(dev->mmio + Group_1_Flags);
- status = readb(dev->mmio + Interrupt_And_Window_Status);
+ flags = readb(dev->mmio + GROUP_1_FLAGS);
+ status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS);
}
out:
comedi_handle_events(dev, s);
#if 0
if (!tag)
- writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
+ writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
#endif
spin_unlock(&dev->spinlock);
@@ -484,7 +486,7 @@ static int ni_pcidio_insn_config(struct comedi_device *dev,
if (ret)
return ret;
- writel(s->io_bits, dev->mmio + Port_Pin_Directions(0));
+ writel(s->io_bits, dev->mmio + PORT_PIN_DIRECTIONS(0));
return insn->n;
}
@@ -495,9 +497,9 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
if (comedi_dio_update_state(s, data))
- writel(s->state, dev->mmio + Port_IO(0));
+ writel(s->state, dev->mmio + PORT_IO(0));
- data[1] = readl(dev->mmio + Port_IO(0));
+ data[1] = readl(dev->mmio + PORT_IO(0));
return insn->n;
}
@@ -609,7 +611,7 @@ static int ni_pcidio_inttrig(struct comedi_device *dev,
if (trig_num != cmd->start_arg)
return -EINVAL;
- writeb(devpriv->OpModeBits, dev->mmio + OpMode);
+ writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE);
s->async->inttrig = NULL;
return 1;
@@ -621,78 +623,78 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
struct comedi_cmd *cmd = &s->async->cmd;
/* XXX configure ports for input */
- writel(0x0000, dev->mmio + Port_Pin_Directions(0));
+ writel(0x0000, dev->mmio + PORT_PIN_DIRECTIONS(0));
if (1) {
/* enable fifos A B C D */
- writeb(0x0f, dev->mmio + Data_Path);
+ writeb(0x0f, dev->mmio + DATA_PATH);
/* set transfer width a 32 bits */
- writeb(TransferWidth(0) | TransferLength(0),
- dev->mmio + Transfer_Size_Control);
+ writeb(TRANSFER_WIDTH(0) | TRANSFER_LENGTH(0),
+ dev->mmio + TRANSFER_SIZE_CONTROL);
} else {
- writeb(0x03, dev->mmio + Data_Path);
- writeb(TransferWidth(3) | TransferLength(0),
- dev->mmio + Transfer_Size_Control);
+ writeb(0x03, dev->mmio + DATA_PATH);
+ writeb(TRANSFER_WIDTH(3) | TRANSFER_LENGTH(0),
+ dev->mmio + TRANSFER_SIZE_CONTROL);
}
/* protocol configuration */
if (cmd->scan_begin_src == TRIG_TIMER) {
/* page 4-5, "input with internal REQs" */
- writeb(0, dev->mmio + OpMode);
- writeb(0x00, dev->mmio + ClockReg);
- writeb(1, dev->mmio + Sequence);
- writeb(0x04, dev->mmio + ReqReg);
- writeb(4, dev->mmio + BlockMode);
- writeb(3, dev->mmio + LinePolarities);
- writeb(0xc0, dev->mmio + AckSer);
+ writeb(0, dev->mmio + OP_MODE);
+ writeb(0x00, dev->mmio + CLOCK_REG);
+ writeb(1, dev->mmio + SEQUENCE);
+ writeb(0x04, dev->mmio + REQ_REG);
+ writeb(4, dev->mmio + BLOCK_MODE);
+ writeb(3, dev->mmio + LINE_POLARITIES);
+ writeb(0xc0, dev->mmio + ACK_SER);
writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
CMDF_ROUND_NEAREST),
- dev->mmio + StartDelay);
- writeb(1, dev->mmio + ReqDelay);
- writeb(1, dev->mmio + ReqNotDelay);
- writeb(1, dev->mmio + AckDelay);
- writeb(0x0b, dev->mmio + AckNotDelay);
- writeb(0x01, dev->mmio + Data1Delay);
+ dev->mmio + START_DELAY);
+ writeb(1, dev->mmio + REQ_DELAY);
+ writeb(1, dev->mmio + REQ_NOT_DELAY);
+ writeb(1, dev->mmio + ACK_DELAY);
+ writeb(0x0b, dev->mmio + ACK_NOT_DELAY);
+ writeb(0x01, dev->mmio + DATA_1_DELAY);
/*
* manual, page 4-5:
- * ClockSpeed comment is incorrectly listed on DAQOptions
+ * CLOCK_SPEED comment is incorrectly listed on DAQ_OPTIONS
*/
- writew(0, dev->mmio + ClockSpeed);
- writeb(0, dev->mmio + DAQOptions);
+ writew(0, dev->mmio + CLOCK_SPEED);
+ writeb(0, dev->mmio + DAQ_OPTIONS);
} else {
/* TRIG_EXT */
/* page 4-5, "input with external REQs" */
- writeb(0, dev->mmio + OpMode);
- writeb(0x00, dev->mmio + ClockReg);
- writeb(0, dev->mmio + Sequence);
- writeb(0x00, dev->mmio + ReqReg);
- writeb(4, dev->mmio + BlockMode);
+ writeb(0, dev->mmio + OP_MODE);
+ writeb(0x00, dev->mmio + CLOCK_REG);
+ writeb(0, dev->mmio + SEQUENCE);
+ writeb(0x00, dev->mmio + REQ_REG);
+ writeb(4, dev->mmio + BLOCK_MODE);
if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */
- writeb(0, dev->mmio + LinePolarities);
+ writeb(0, dev->mmio + LINE_POLARITIES);
else /* Trailing Edge */
- writeb(2, dev->mmio + LinePolarities);
- writeb(0x00, dev->mmio + AckSer);
- writel(1, dev->mmio + StartDelay);
- writeb(1, dev->mmio + ReqDelay);
- writeb(1, dev->mmio + ReqNotDelay);
- writeb(1, dev->mmio + AckDelay);
- writeb(0x0C, dev->mmio + AckNotDelay);
- writeb(0x10, dev->mmio + Data1Delay);
- writew(0, dev->mmio + ClockSpeed);
- writeb(0x60, dev->mmio + DAQOptions);
+ writeb(2, dev->mmio + LINE_POLARITIES);
+ writeb(0x00, dev->mmio + ACK_SER);
+ writel(1, dev->mmio + START_DELAY);
+ writeb(1, dev->mmio + REQ_DELAY);
+ writeb(1, dev->mmio + REQ_NOT_DELAY);
+ writeb(1, dev->mmio + ACK_DELAY);
+ writeb(0x0C, dev->mmio + ACK_NOT_DELAY);
+ writeb(0x10, dev->mmio + DATA_1_DELAY);
+ writew(0, dev->mmio + CLOCK_SPEED);
+ writeb(0x60, dev->mmio + DAQ_OPTIONS);
}
if (cmd->stop_src == TRIG_COUNT) {
writel(cmd->stop_arg,
- dev->mmio + Transfer_Count);
+ dev->mmio + TRANSFER_COUNT);
} else {
/* XXX */
}
#ifdef USE_DMA
- writeb(ClearPrimaryTC | ClearSecondaryTC,
- dev->mmio + Group_1_First_Clear);
+ writeb(CLEAR_PRIMARY_TC | CLEAR_SECONDARY_TC,
+ dev->mmio + GROUP_1_FIRST_CLEAR);
{
int retval = setup_mite_dma(dev, s);
@@ -701,25 +703,25 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return retval;
}
#else
- writeb(0x00, dev->mmio + DMA_Line_Control_Group1);
+ writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP1);
#endif
- writeb(0x00, dev->mmio + DMA_Line_Control_Group2);
+ writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP2);
/* clear and enable interrupts */
- writeb(0xff, dev->mmio + Group_1_First_Clear);
- /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */
+ writeb(0xff, dev->mmio + GROUP_1_FIRST_CLEAR);
+ /* writeb(CLEAR_EXPIRED, dev->mmio+GROUP_1_SECOND_CLEAR); */
- writeb(IntEn, dev->mmio + Interrupt_Control);
- writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
+ writeb(INT_EN, dev->mmio + INTERRUPT_CONTROL);
+ writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
if (cmd->stop_src == TRIG_NONE) {
- devpriv->OpModeBits = DataLatching(0) | RunMode(7);
+ devpriv->OP_MODEBits = DATA_LATCHING(0) | RUN_MODE(7);
} else { /* TRIG_TIMER */
- devpriv->OpModeBits = Numbered | RunMode(7);
+ devpriv->OP_MODEBits = NUMBERED | RUN_MODE(7);
}
if (cmd->start_src == TRIG_NOW) {
/* start */
- writeb(devpriv->OpModeBits, dev->mmio + OpMode);
+ writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE);
s->async->inttrig = NULL;
} else {
/* TRIG_INT */
@@ -732,7 +734,7 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
static int ni_pcidio_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control);
+ writeb(0x00, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
ni_pcidio_release_di_mite_channel(dev);
return 0;
@@ -869,12 +871,12 @@ static int pci_6534_upload_firmware(struct comedi_device *dev)
static void nidio_reset_board(struct comedi_device *dev)
{
- writel(0, dev->mmio + Port_IO(0));
- writel(0, dev->mmio + Port_Pin_Directions(0));
- writel(0, dev->mmio + Port_Pin_Mask(0));
+ writel(0, dev->mmio + PORT_IO(0));
+ writel(0, dev->mmio + PORT_PIN_DIRECTIONS(0));
+ writel(0, dev->mmio + PORT_PIN_MASK(0));
/* disable interrupts on board */
- writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control);
+ writeb(0, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
}
static int nidio_auto_attach(struct comedi_device *dev,
@@ -925,7 +927,7 @@ static int nidio_auto_attach(struct comedi_device *dev,
return ret;
dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
- readb(dev->mmio + Chip_Version));
+ readb(dev->mmio + CHIP_VERSION));
s = &dev->subdevices[0];
diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
index 0eb388c0e1f0..048cb35723ad 100644
--- a/drivers/staging/comedi/drivers/ni_tio.c
+++ b/drivers/staging/comedi/drivers/ni_tio.c
@@ -224,13 +224,16 @@ static void ni_tio_set_bits_transient(struct ni_gpct *counter,
unsigned int transient)
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
+ unsigned int chip = counter->chip_index;
unsigned long flags;
- if (reg < NITIO_NUM_REGS) {
+ if (reg < NITIO_NUM_REGS && chip < counter_dev->num_chips) {
+ unsigned int *regs = counter_dev->regs[chip];
+
spin_lock_irqsave(&counter_dev->regs_lock, flags);
- counter_dev->regs[reg] &= ~mask;
- counter_dev->regs[reg] |= (value & mask);
- ni_tio_write(counter, counter_dev->regs[reg] | transient, reg);
+ regs[reg] &= ~mask;
+ regs[reg] |= (value & mask);
+ ni_tio_write(counter, regs[reg] | transient, reg);
mmiowb();
spin_unlock_irqrestore(&counter_dev->regs_lock, flags);
}
@@ -267,12 +270,13 @@ unsigned int ni_tio_get_soft_copy(const struct ni_gpct *counter,
enum ni_gpct_register reg)
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
+ unsigned int chip = counter->chip_index;
unsigned int value = 0;
unsigned long flags;
- if (reg < NITIO_NUM_REGS) {
+ if (reg < NITIO_NUM_REGS && chip < counter_dev->num_chips) {
spin_lock_irqsave(&counter_dev->regs_lock, flags);
- value = counter_dev->regs[reg];
+ value = counter_dev->regs[chip][reg];
spin_unlock_irqrestore(&counter_dev->regs_lock, flags);
}
return value;
@@ -302,6 +306,7 @@ static int ni_m_series_clock_src_select(const struct ni_gpct *counter,
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
unsigned int second_gate_reg = NITIO_GATE2_REG(cidx);
unsigned int clock_source = 0;
unsigned int src;
@@ -318,7 +323,7 @@ static int ni_m_series_clock_src_select(const struct ni_gpct *counter,
clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS;
break;
case NI_M_TIMEBASE_3_CLK:
- if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL)
+ if (counter_dev->regs[chip][second_gate_reg] & GI_SRC_SUBSEL)
clock_source =
NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS;
else
@@ -328,7 +333,7 @@ static int ni_m_series_clock_src_select(const struct ni_gpct *counter,
clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS;
break;
case NI_M_NEXT_GATE_CLK:
- if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL)
+ if (counter_dev->regs[chip][second_gate_reg] & GI_SRC_SUBSEL)
clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS;
else
clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS;
@@ -721,6 +726,7 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter,
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
unsigned int second_gate_reg = NITIO_GATE2_REG(cidx);
if (counter_dev->variant != ni_gpct_variant_m_series)
@@ -729,18 +735,18 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter,
/* Gi_Source_Subselect is zero */
case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS:
case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
- counter_dev->regs[second_gate_reg] &= ~GI_SRC_SUBSEL;
+ counter_dev->regs[chip][second_gate_reg] &= ~GI_SRC_SUBSEL;
break;
/* Gi_Source_Subselect is one */
case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS:
case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS:
- counter_dev->regs[second_gate_reg] |= GI_SRC_SUBSEL;
+ counter_dev->regs[chip][second_gate_reg] |= GI_SRC_SUBSEL;
break;
/* Gi_Source_Subselect doesn't matter */
default:
return;
}
- ni_tio_write(counter, counter_dev->regs[second_gate_reg],
+ ni_tio_write(counter, counter_dev->regs[chip][second_gate_reg],
second_gate_reg);
}
@@ -1116,6 +1122,7 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index,
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
unsigned int abz_reg, shift, mask;
if (counter_dev->variant != ni_gpct_variant_m_series)
@@ -1141,9 +1148,9 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index,
if (source > 0x1f)
source = 0x1f; /* Disable gate */
- counter_dev->regs[abz_reg] &= ~mask;
- counter_dev->regs[abz_reg] |= (source << shift) & mask;
- ni_tio_write(counter, counter_dev->regs[abz_reg], abz_reg);
+ counter_dev->regs[chip][abz_reg] &= ~mask;
+ counter_dev->regs[chip][abz_reg] |= (source << shift) & mask;
+ ni_tio_write(counter, counter_dev->regs[chip][abz_reg], abz_reg);
return 0;
}
@@ -1632,6 +1639,7 @@ int ni_tio_insn_read(struct comedi_device *dev,
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int channel = CR_CHAN(insn->chanspec);
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
int i;
for (i = 0; i < insn->n; i++) {
@@ -1640,10 +1648,12 @@ int ni_tio_insn_read(struct comedi_device *dev,
data[i] = ni_tio_read_sw_save_reg(dev, s);
break;
case 1:
- data[i] = counter_dev->regs[NITIO_LOADA_REG(cidx)];
+ data[i] =
+ counter_dev->regs[chip][NITIO_LOADA_REG(cidx)];
break;
case 2:
- data[i] = counter_dev->regs[NITIO_LOADB_REG(cidx)];
+ data[i] =
+ counter_dev->regs[chip][NITIO_LOADB_REG(cidx)];
break;
}
}
@@ -1670,6 +1680,7 @@ int ni_tio_insn_write(struct comedi_device *dev,
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int channel = CR_CHAN(insn->chanspec);
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
unsigned int load_reg;
if (insn->n < 1)
@@ -1690,14 +1701,15 @@ int ni_tio_insn_write(struct comedi_device *dev,
ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx),
0, 0, GI_LOAD);
/* restore load reg */
- ni_tio_write(counter, counter_dev->regs[load_reg], load_reg);
+ ni_tio_write(counter, counter_dev->regs[chip][load_reg],
+ load_reg);
break;
case 1:
- counter_dev->regs[NITIO_LOADA_REG(cidx)] = data[0];
+ counter_dev->regs[chip][NITIO_LOADA_REG(cidx)] = data[0];
ni_tio_write(counter, data[0], NITIO_LOADA_REG(cidx));
break;
case 2:
- counter_dev->regs[NITIO_LOADB_REG(cidx)] = data[0];
+ counter_dev->regs[chip][NITIO_LOADB_REG(cidx)] = data[0];
ni_tio_write(counter, data[0], NITIO_LOADB_REG(cidx));
break;
default:
@@ -1711,11 +1723,12 @@ void ni_tio_init_counter(struct ni_gpct *counter)
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
unsigned int cidx = counter->counter_index;
+ unsigned int chip = counter->chip_index;
ni_tio_reset_count_and_disarm(counter);
/* initialize counter registers */
- counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0;
+ counter_dev->regs[chip][NITIO_AUTO_INC_REG(cidx)] = 0x0;
ni_tio_write(counter, 0x0, NITIO_AUTO_INC_REG(cidx));
ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
@@ -1723,10 +1736,10 @@ void ni_tio_init_counter(struct ni_gpct *counter)
ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0);
- counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0;
+ counter_dev->regs[chip][NITIO_LOADA_REG(cidx)] = 0x0;
ni_tio_write(counter, 0x0, NITIO_LOADA_REG(cidx));
- counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0;
+ counter_dev->regs[chip][NITIO_LOADB_REG(cidx)] = 0x0;
ni_tio_write(counter, 0x0, NITIO_LOADB_REG(cidx));
ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0);
@@ -1735,7 +1748,7 @@ void ni_tio_init_counter(struct ni_gpct *counter)
ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0);
if (ni_tio_has_gate2_registers(counter_dev)) {
- counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0;
+ counter_dev->regs[chip][NITIO_GATE2_REG(cidx)] = 0x0;
ni_tio_write(counter, 0x0, NITIO_GATE2_REG(cidx));
}
@@ -1776,9 +1789,16 @@ ni_gpct_device_construct(struct comedi_device *dev,
spin_lock_init(&counter_dev->regs_lock);
+ counter_dev->num_counters = num_counters;
+ counter_dev->num_chips = DIV_ROUND_UP(num_counters, counters_per_chip);
+
counter_dev->counters = kcalloc(num_counters, sizeof(*counter),
GFP_KERNEL);
- if (!counter_dev->counters) {
+ counter_dev->regs = kcalloc(counter_dev->num_chips,
+ sizeof(*counter_dev->regs), GFP_KERNEL);
+ if (!counter_dev->regs || !counter_dev->counters) {
+ kfree(counter_dev->regs);
+ kfree(counter_dev->counters);
kfree(counter_dev);
return NULL;
}
@@ -1790,8 +1810,6 @@ ni_gpct_device_construct(struct comedi_device *dev,
counter->counter_index = i % counters_per_chip;
spin_lock_init(&counter->lock);
}
- counter_dev->num_counters = num_counters;
- counter_dev->counters_per_chip = counters_per_chip;
return counter_dev;
}
@@ -1801,6 +1819,7 @@ void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev)
{
if (!counter_dev)
return;
+ kfree(counter_dev->regs);
kfree(counter_dev->counters);
kfree(counter_dev);
}
diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
index 1e85d0a53715..e7b05718df9b 100644
--- a/drivers/staging/comedi/drivers/ni_tio.h
+++ b/drivers/staging/comedi/drivers/ni_tio.h
@@ -107,8 +107,8 @@ struct ni_gpct_device {
enum ni_gpct_variant variant;
struct ni_gpct *counters;
unsigned int num_counters;
- unsigned int counters_per_chip;
- unsigned int regs[NITIO_NUM_REGS];
+ unsigned int num_chips;
+ unsigned int (*regs)[NITIO_NUM_REGS]; /* [num_chips][NITIO_NUM_REGS] */
spinlock_t regs_lock; /* protects 'regs' */
const struct ni_route_tables *routing_tables; /* link to routes */
};
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index e18c0723b760..0d54f394dbd2 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -61,7 +61,7 @@
#define USBDUXFASTSUB_CPUCS 0xE600
/*
- * max lenghth of the transfer-buffer for software upload
+ * max length of the transfer-buffer for software upload
*/
#define TB_LEN 0x2000
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 8e8f57c4f029..a913d40f0801 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -27,7 +27,7 @@
#include <linux/usb/gadget.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include "emxx_udc.h"
@@ -2220,7 +2220,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
mdelay(VBUS_CHATTERING_MDELAY); /* wait (ms) */
/* VBUS ON Check*/
- reg_dt = gpio_get_value(VBUS_VALUE);
+ reg_dt = gpiod_get_value(vbus_gpio);
if (reg_dt == 0) {
udc->linux_suspended = 0;
@@ -2247,7 +2247,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
}
} else {
mdelay(5); /* wait (5ms) */
- reg_dt = gpio_get_value(VBUS_VALUE);
+ reg_dt = gpiod_get_value(vbus_gpio);
if (reg_dt == 0)
return;
@@ -2311,7 +2311,7 @@ static inline void _nbu2ss_int_usb_suspend(struct nbu2ss_udc *udc)
u32 reg_dt;
if (udc->usb_suspended == 0) {
- reg_dt = gpio_get_value(VBUS_VALUE);
+ reg_dt = gpiod_get_value(vbus_gpio);
if (reg_dt == 0)
return;
@@ -2351,7 +2351,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
struct nbu2ss_udc *udc = (struct nbu2ss_udc *)_udc;
struct fc_regs __iomem *preg = udc->p_regs;
- if (gpio_get_value(VBUS_VALUE) == 0) {
+ if (gpiod_get_value(vbus_gpio) == 0) {
_nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
_nbu2ss_writel(&preg->USB_INT_ENA, 0);
return IRQ_HANDLED;
@@ -2360,7 +2360,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
spin_lock(&udc->lock);
for (;;) {
- if (gpio_get_value(VBUS_VALUE) == 0) {
+ if (gpiod_get_value(vbus_gpio) == 0) {
_nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
_nbu2ss_writel(&preg->USB_INT_ENA, 0);
status = 0;
@@ -2750,7 +2750,7 @@ static int nbu2ss_ep_fifo_status(struct usb_ep *_ep)
preg = udc->p_regs;
- data = gpio_get_value(VBUS_VALUE);
+ data = gpiod_get_value(vbus_gpio);
if (data == 0)
return -EINVAL;
@@ -2790,7 +2790,7 @@ static void nbu2ss_ep_fifo_flush(struct usb_ep *_ep)
return;
}
- data = gpio_get_value(VBUS_VALUE);
+ data = gpiod_get_value(vbus_gpio);
if (data == 0)
return;
@@ -2832,7 +2832,7 @@ static int nbu2ss_gad_get_frame(struct usb_gadget *pgadget)
}
udc = container_of(pgadget, struct nbu2ss_udc, gadget);
- data = gpio_get_value(VBUS_VALUE);
+ data = gpiod_get_value(vbus_gpio);
if (data == 0)
return -EINVAL;
@@ -2854,7 +2854,7 @@ static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget)
udc = container_of(pgadget, struct nbu2ss_udc, gadget);
- data = gpio_get_value(VBUS_VALUE);
+ data = gpiod_get_value(vbus_gpio);
if (data == 0) {
dev_warn(&pgadget->dev, "VBUS LEVEL = %d\n", data);
return -EINVAL;
@@ -3119,12 +3119,13 @@ static int nbu2ss_drv_probe(struct platform_device *pdev)
}
/* VBUS Interrupt */
- irq_set_irq_type(INT_VBUS, IRQ_TYPE_EDGE_BOTH);
- status = request_irq(INT_VBUS,
+ vbus_irq = gpiod_to_irq(vbus_gpio);
+ irq_set_irq_type(vbus_irq, IRQ_TYPE_EDGE_BOTH);
+ status = request_irq(vbus_irq,
_nbu2ss_vbus_irq, IRQF_SHARED, driver_name, udc);
if (status != 0) {
- dev_err(udc->dev, "request_irq(INT_VBUS) failed\n");
+ dev_err(udc->dev, "request_irq(vbus_irq) failed\n");
return status;
}
@@ -3160,7 +3161,7 @@ static int nbu2ss_drv_remove(struct platform_device *pdev)
}
/* Interrupt Handler - Release */
- free_irq(INT_VBUS, udc);
+ free_irq(vbus_irq, udc);
return 0;
}
@@ -3201,7 +3202,7 @@ static int nbu2ss_drv_resume(struct platform_device *pdev)
if (!udc)
return 0;
- data = gpio_get_value(VBUS_VALUE);
+ data = gpiod_get_value(vbus_gpio);
if (data) {
udc->vbus_active = 1;
udc->devstate = USB_STATE_POWERED;
diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h
index e28a74da9633..b8c3dee5626c 100644
--- a/drivers/staging/emxx_udc/emxx_udc.h
+++ b/drivers/staging/emxx_udc/emxx_udc.h
@@ -30,6 +30,8 @@
/* below hacked up for staging integration */
#define GPIO_VBUS 0 /* GPIO_P153 on KZM9D */
#define INT_VBUS 0 /* IRQ for GPIO_P153 */
+struct gpio_desc *vbus_gpio;
+int vbus_irq;
/*------------ Board dependence(Wait) */
diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt
new file mode 100644
index 000000000000..961ec4da7705
--- /dev/null
+++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt
@@ -0,0 +1,208 @@
+Overview
+========
+
+EROFS file-system stands for Enhanced Read-Only File System. Different
+from other read-only file systems, it aims to be designed for flexibility,
+scalability, but be kept simple and high performance.
+
+It is designed as a better filesystem solution for the following scenarios:
+ - read-only storage media or
+
+ - part of a fully trusted read-only solution, which means it needs to be
+ immutable and bit-for-bit identical to the official golden image for
+ their releases due to security and other considerations and
+
+ - hope to save some extra storage space with guaranteed end-to-end performance
+ by using reduced metadata and transparent file compression, especially
+ for those embedded devices with limited memory (ex, smartphone);
+
+Here is the main features of EROFS:
+ - Little endian on-disk design;
+
+ - Currently 4KB block size (nobh) and therefore maximum 16TB address space;
+
+ - Metadata & data could be mixed by design;
+
+ - 2 inode versions for different requirements:
+ v1 v2
+ Inode metadata size: 32 bytes 64 bytes
+ Max file size: 4 GB 16 EB (also limited by max. vol size)
+ Max uids/gids: 65536 4294967296
+ File creation time: no yes (64 + 32-bit timestamp)
+ Max hardlinks: 65536 4294967296
+ Metadata reserved: 4 bytes 14 bytes
+
+ - Support extended attributes (xattrs) as an option;
+
+ - Support xattr inline and tail-end data inline for all files;
+
+ - Support POSIX.1e ACLs by using xattrs;
+
+ - Support transparent file compression as an option:
+ LZ4 algorithm with 4 KB fixed-output compression for high performance;
+
+The following git tree provides the file system user-space tools under
+development (ex, formatting tool mkfs.erofs):
+>> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
+
+Bugs and patches are welcome, please kindly help us and send to the following
+linux-erofs mailing list:
+>> linux-erofs mailing list <linux-erofs@lists.ozlabs.org>
+
+Note that EROFS is still working in progress as a Linux staging driver,
+Cc the staging mailing list as well is highly recommended:
+>> Linux Driver Project Developer List <devel@driverdev.osuosl.org>
+
+Mount options
+=============
+
+fault_injection=%d Enable fault injection in all supported types with
+ specified injection rate. Supported injection type:
+ Type_Name Type_Value
+ FAULT_KMALLOC 0x000000001
+(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled
+ by default if CONFIG_EROFS_FS_XATTR is selected.
+(no)acl Setup POSIX Access Control List. Note: acl is enabled
+ by default if CONFIG_EROFS_FS_POSIX_ACL is selected.
+
+On-disk details
+===============
+
+Summary
+-------
+Different from other read-only file systems, an EROFS volume is designed
+to be as simple as possible:
+
+ |-> aligned with the block size
+ ____________________________________________________________
+ | |SB| | ... | Metadata | ... | Data | Metadata | ... | Data |
+ |_|__|_|_____|__________|_____|______|__________|_____|______|
+ 0 +1K
+
+All data areas should be aligned with the block size, but metadata areas
+may not. All metadatas can be now observed in two different spaces (views):
+ 1. Inode metadata space
+ Each valid inode should be aligned with an inode slot, which is a fixed
+ value (32 bytes) and designed to be kept in line with v1 inode size.
+
+ Each inode can be directly found with the following formula:
+ inode offset = meta_blkaddr * block_size + 32 * nid
+
+ |-> aligned with 8B
+ |-> followed closely
+ + meta_blkaddr blocks |-> another slot
+ _____________________________________________________________________
+ | ... | inode | xattrs | extents | data inline | ... | inode ...
+ |________|_______|(optional)|(optional)|__(optional)_|_____|__________
+ |-> aligned with the inode slot size
+ . .
+ . .
+ . .
+ . .
+ . .
+ . .
+ .____________________________________________________|-> aligned with 4B
+ | xattr_ibody_header | shared xattrs | inline xattrs |
+ |____________________|_______________|_______________|
+ |-> 12 bytes <-|->x * 4 bytes<-| .
+ . . .
+ . . .
+ . . .
+ ._______________________________.______________________.
+ | id | id | id | id | ... | id | ent | ... | ent| ... |
+ |____|____|____|____|______|____|_____|_____|____|_____|
+ |-> aligned with 4B
+ |-> aligned with 4B
+
+ Inode could be 32 or 64 bytes, which can be distinguished from a common
+ field which all inode versions have -- i_advise:
+
+ __________________ __________________
+ | i_advise | | i_advise |
+ |__________________| |__________________|
+ | ... | | ... |
+ | | | |
+ |__________________| 32 bytes | |
+ | |
+ |__________________| 64 bytes
+
+ Xattrs, extents, data inline are followed by the corresponding inode with
+ proper alignes, and they could be optional for different data mappings,
+ _currently_ there are totally 3 valid data mappings supported:
+
+ 1) flat file data without data inline (no extent);
+ 2) fixed-output size data compression (must have extents);
+ 3) flat file data with tail-end data inline (no extent);
+
+ The size of the optional xattrs is indicated by i_xattr_count in inode
+ header. Large xattrs or xattrs shared by many different files can be
+ stored in shared xattrs metadata rather than inlined right after inode.
+
+ 2. Shared xattrs metadata space
+ Shared xattrs space is similar to the above inode space, started with
+ a specific block indicated by xattr_blkaddr, organized one by one with
+ proper align.
+
+ Each share xattr can also be directly found by the following formula:
+ xattr offset = xattr_blkaddr * block_size + 4 * xattr_id
+
+ |-> aligned by 4 bytes
+ + xattr_blkaddr blocks |-> aligned with 4 bytes
+ _________________________________________________________________________
+ | ... | xattr_entry | xattr data | ... | xattr_entry | xattr data ...
+ |________|_____________|_____________|_____|______________|_______________
+
+Directories
+-----------
+All directories are now organized in a compact on-disk format. Note that
+each directory block is divided into index and name areas in order to support
+random file lookup, and all directory entries are _strictly_ recorded in
+alphabetical order in order to support improved prefix binary search
+algorithm (could refer to the related source code).
+
+ ___________________________
+ / |
+ / ______________|________________
+ / / | nameoff1 | nameoffN-1
+ ____________.______________._______________v________________v__________
+| dirent | dirent | ... | dirent | filename | filename | ... | filename |
+|___.0___|____1___|_____|___N-1__|____0_____|____1_____|_____|___N-1____|
+ \ ^
+ \ | * could have
+ \ | trailing '\0'
+ \________________________| nameoff0
+
+ Directory block
+
+Note that apart from the offset of the first filename, nameoff0 also indicates
+the total number of directory entries in this block since it is no need to
+introduce another on-disk field at all.
+
+Compression
+-----------
+Currently, EROFS supports 4KB fixed-output clustersize transparent file
+compression, as illustrated below:
+
+ |---- Variant-Length Extent ----|-------- VLE --------|----- VLE -----
+ clusterofs clusterofs clusterofs
+ | | | logical data
+_________v_______________________________v_____________________v_______________
+... | . | | . | | . | ...
+____|____.________|_____________|________.____|_____________|__.__________|____
+ |-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-|
+ size size size size size
+ . . . .
+ . . . .
+ . . . .
+ _______._____________._____________._____________._____________________
+ ... | | | | ... physical data
+ _______|_____________|_____________|_____________|_____________________
+ |-> cluster <-|-> cluster <-|-> cluster <-|
+ size size size
+
+Currently each on-disk physical cluster can contain 4KB (un)compressed data
+at most. For each logical cluster, there is a corresponding on-disk index to
+describe its cluster type, physical cluster address, etc.
+
+See "struct z_erofs_vle_decompressed_index" in erofs_fs.h for more details.
+
diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile
index c91b65223f99..38ab344a285e 100644
--- a/drivers/staging/erofs/Makefile
+++ b/drivers/staging/erofs/Makefile
@@ -6,7 +6,7 @@ ccflags-y += -Wall -DEROFS_VERSION=\"$(EROFS_VERSION)\"
obj-$(CONFIG_EROFS_FS) += erofs.o
# staging requirement: to be self-contained in its own directory
-ccflags-y += -I$(src)/include
+ccflags-y += -I $(srctree)/$(src)/include
erofs-objs := super.o inode.o data.o namei.o dir.o utils.o
erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o
erofs-$(CONFIG_EROFS_FS_ZIP) += unzip_vle.o unzip_vle_lz4.o
diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c
index 5a55f0bfdfbb..9c471f08ffd4 100644
--- a/drivers/staging/erofs/data.c
+++ b/drivers/staging/erofs/data.c
@@ -165,43 +165,16 @@ err_out:
return err;
}
-#ifdef CONFIG_EROFS_FS_ZIP
-extern int z_erofs_map_blocks_iter(struct inode *,
- struct erofs_map_blocks *,
- struct page **, int);
-#endif
-
-int erofs_map_blocks_iter(struct inode *inode,
- struct erofs_map_blocks *map,
- struct page **mpage_ret, int flags)
-{
- /* by default, reading raw data never use erofs_map_blocks_iter */
- if (unlikely(!is_inode_layout_compression(inode))) {
- if (*mpage_ret)
- put_page(*mpage_ret);
- *mpage_ret = NULL;
-
- return erofs_map_blocks(inode, map, flags);
- }
-
-#ifdef CONFIG_EROFS_FS_ZIP
- return z_erofs_map_blocks_iter(inode, map, mpage_ret, flags);
-#else
- /* data compression is not available */
- return -ENOTSUPP;
-#endif
-}
-
int erofs_map_blocks(struct inode *inode,
struct erofs_map_blocks *map, int flags)
{
if (unlikely(is_inode_layout_compression(inode))) {
- struct page *mpage = NULL;
- int err;
+ int err = z_erofs_map_blocks_iter(inode, map, flags);
- err = erofs_map_blocks_iter(inode, map, &mpage, flags);
- if (mpage)
- put_page(mpage);
+ if (map->mpage) {
+ put_page(map->mpage);
+ map->mpage = NULL;
+ }
return err;
}
return erofs_map_blocks_flatmode(inode, map, flags);
diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c
index 833f052f79d0..829f7b12e0dc 100644
--- a/drivers/staging/erofs/dir.c
+++ b/drivers/staging/erofs/dir.c
@@ -24,8 +24,8 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = {
};
static int erofs_fill_dentries(struct dir_context *ctx,
- void *dentry_blk, unsigned int *ofs,
- unsigned int nameoff, unsigned int maxsize)
+ void *dentry_blk, unsigned int *ofs,
+ unsigned int nameoff, unsigned int maxsize)
{
struct erofs_dirent *de = dentry_blk;
const struct erofs_dirent *end = dentry_blk + nameoff;
@@ -98,15 +98,14 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
if (IS_ERR(dentry_page))
continue;
- lock_page(dentry_page);
de = (struct erofs_dirent *)kmap(dentry_page);
nameoff = le16_to_cpu(de->nameoff);
if (unlikely(nameoff < sizeof(struct erofs_dirent) ||
- nameoff >= PAGE_SIZE)) {
+ nameoff >= PAGE_SIZE)) {
errln("%s, invalid de[0].nameoff %u",
- __func__, nameoff);
+ __func__, nameoff);
err = -EIO;
goto skip_this;
@@ -128,7 +127,6 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
skip_this:
kunmap(dentry_page);
- unlock_page(dentry_page);
put_page(dentry_page);
ctx->pos = blknr_to_addr(i) + ofs;
@@ -144,6 +142,6 @@ skip_this:
const struct file_operations erofs_dir_fops = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
- .iterate = erofs_readdir,
+ .iterate_shared = erofs_readdir,
};
diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c
index d7fbf5f4600f..924b8dfc7a8f 100644
--- a/drivers/staging/erofs/inode.c
+++ b/drivers/staging/erofs/inode.c
@@ -184,32 +184,18 @@ static int fill_inode(struct inode *inode, int isdir)
if (!err) {
/* setup the new inode */
if (S_ISREG(inode->i_mode)) {
-#ifdef CONFIG_EROFS_FS_XATTR
- if (vi->xattr_isize)
- inode->i_op = &erofs_generic_xattr_iops;
-#endif
+ inode->i_op = &erofs_generic_iops;
inode->i_fop = &generic_ro_fops;
} else if (S_ISDIR(inode->i_mode)) {
- inode->i_op =
-#ifdef CONFIG_EROFS_FS_XATTR
- vi->xattr_isize ? &erofs_dir_xattr_iops :
-#endif
- &erofs_dir_iops;
+ inode->i_op = &erofs_dir_iops;
inode->i_fop = &erofs_dir_fops;
} else if (S_ISLNK(inode->i_mode)) {
/* by default, page_get_link is used for symlink */
- inode->i_op =
-#ifdef CONFIG_EROFS_FS_XATTR
- &erofs_symlink_xattr_iops,
-#else
- &page_symlink_inode_operations;
-#endif
+ inode->i_op = &erofs_symlink_iops;
inode_nohighmem(inode);
} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
-#ifdef CONFIG_EROFS_FS_XATTR
- inode->i_op = &erofs_special_inode_operations;
-#endif
+ inode->i_op = &erofs_generic_iops;
init_special_inode(inode, inode->i_mode, inode->i_rdev);
} else {
err = -EIO;
@@ -297,23 +283,26 @@ struct inode *erofs_iget(struct super_block *sb,
return inode;
}
+const struct inode_operations erofs_generic_iops = {
#ifdef CONFIG_EROFS_FS_XATTR
-const struct inode_operations erofs_generic_xattr_iops = {
.listxattr = erofs_listxattr,
+#endif
+ .get_acl = erofs_get_acl,
};
-const struct inode_operations erofs_symlink_xattr_iops = {
+const struct inode_operations erofs_symlink_iops = {
.get_link = page_get_link,
+#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
+#endif
+ .get_acl = erofs_get_acl,
};
-const struct inode_operations erofs_special_inode_operations = {
- .listxattr = erofs_listxattr,
-};
-
-const struct inode_operations erofs_fast_symlink_xattr_iops = {
+const struct inode_operations erofs_fast_symlink_iops = {
.get_link = simple_get_link,
+#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
-};
#endif
+ .get_acl = erofs_get_acl,
+};
diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index e049d00c087a..e3bfde00c7d2 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -252,47 +252,20 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
}
#endif
-static inline bool erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt)
-{
- int o;
-
-repeat:
- o = erofs_wait_on_workgroup_freezed(grp);
-
- if (unlikely(o <= 0))
- return -1;
-
- if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o))
- goto repeat;
-
- *ocnt = o;
- return 0;
-}
-
-#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount)
-#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount)
-
-extern int erofs_workgroup_put(struct erofs_workgroup *grp);
-
-extern struct erofs_workgroup *erofs_find_workgroup(
- struct super_block *sb, pgoff_t index, bool *tag);
-
-extern int erofs_register_workgroup(struct super_block *sb,
- struct erofs_workgroup *grp, bool tag);
-
-extern unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi,
- unsigned long nr_shrink, bool cleanup);
-
-static inline void erofs_workstation_cleanup_all(struct super_block *sb)
-{
- erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true);
-}
+int erofs_workgroup_put(struct erofs_workgroup *grp);
+struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb,
+ pgoff_t index, bool *tag);
+int erofs_register_workgroup(struct super_block *sb,
+ struct erofs_workgroup *grp, bool tag);
+unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi,
+ unsigned long nr_shrink, bool cleanup);
+void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
#ifdef EROFS_FS_HAS_MANAGED_CACHE
-extern int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
- struct erofs_workgroup *egrp);
-extern int erofs_try_to_free_cached_page(struct address_space *mapping,
- struct page *page);
+int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
+ struct erofs_workgroup *egrp);
+int erofs_try_to_free_cached_page(struct address_space *mapping,
+ struct page *page);
#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping)
#else
@@ -354,12 +327,17 @@ static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid)
return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits);
}
-#define inode_set_inited_xattr(inode) (EROFS_V(inode)->flags |= 1)
-#define inode_has_inited_xattr(inode) (EROFS_V(inode)->flags & 1)
+/* atomic flag definitions */
+#define EROFS_V_EA_INITED_BIT 0
+
+/* bitlock definitions (arranged in reverse order) */
+#define EROFS_V_BL_XATTR_BIT (BITS_PER_LONG - 1)
struct erofs_vnode {
erofs_nid_t nid;
- unsigned int flags;
+
+ /* atomic flags (including bitlocks) */
+ unsigned long flags;
unsigned char data_mapping_mode;
/* inline size in bytes */
@@ -412,8 +390,6 @@ static inline bool is_inode_layout_inline(struct inode *inode)
}
extern const struct super_operations erofs_sops;
-extern const struct inode_operations erofs_dir_iops;
-extern const struct file_operations erofs_dir_fops;
extern const struct address_space_operations erofs_raw_access_aops;
#ifdef CONFIG_EROFS_FS_ZIP
@@ -461,11 +437,26 @@ struct erofs_map_blocks {
u64 m_plen, m_llen;
unsigned int m_flags;
+
+ struct page *mpage;
};
/* Flags used by erofs_map_blocks() */
#define EROFS_GET_BLOCKS_RAW 0x0001
+#ifdef CONFIG_EROFS_FS_ZIP
+int z_erofs_map_blocks_iter(struct inode *inode,
+ struct erofs_map_blocks *map,
+ int flags);
+#else
+static inline int z_erofs_map_blocks_iter(struct inode *inode,
+ struct erofs_map_blocks *map,
+ int flags)
+{
+ return -ENOTSUPP;
+}
+#endif
+
/* data.c */
static inline struct bio *
erofs_grab_bio(struct super_block *sb,
@@ -506,8 +497,8 @@ static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags)
#define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES
#endif
-extern struct page *__erofs_get_meta_page(struct super_block *sb,
- erofs_blk_t blkaddr, bool prio, bool nofail);
+struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr,
+ bool prio, bool nofail);
static inline struct page *erofs_get_meta_page(struct super_block *sb,
erofs_blk_t blkaddr, bool prio)
@@ -521,15 +512,7 @@ static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb,
return __erofs_get_meta_page(sb, blkaddr, prio, true);
}
-extern int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int);
-extern int erofs_map_blocks_iter(struct inode *, struct erofs_map_blocks *,
- struct page **, int);
-
-struct erofs_map_blocks_iter {
- struct erofs_map_blocks map;
- struct page *mpage;
-};
-
+int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int);
static inline struct page *
erofs_get_inline_page(struct inode *inode,
@@ -549,41 +532,31 @@ static inline unsigned long erofs_inode_hash(erofs_nid_t nid)
#endif
}
-extern struct inode *erofs_iget(struct super_block *sb,
- erofs_nid_t nid, bool dir);
-
-/* dir.c */
-int erofs_namei(struct inode *dir, struct qstr *name,
- erofs_nid_t *nid, unsigned *d_type);
-
-#ifdef CONFIG_EROFS_FS_XATTR
-/* xattr.c */
-extern const struct xattr_handler *erofs_xattr_handlers[];
-
-/* symlink and special inode */
-extern const struct inode_operations erofs_symlink_xattr_iops;
-extern const struct inode_operations erofs_fast_symlink_xattr_iops;
-extern const struct inode_operations erofs_special_inode_operations;
-#endif
+extern const struct inode_operations erofs_generic_iops;
+extern const struct inode_operations erofs_symlink_iops;
+extern const struct inode_operations erofs_fast_symlink_iops;
static inline void set_inode_fast_symlink(struct inode *inode)
{
-#ifdef CONFIG_EROFS_FS_XATTR
- inode->i_op = &erofs_fast_symlink_xattr_iops;
-#else
- inode->i_op = &simple_symlink_inode_operations;
-#endif
+ inode->i_op = &erofs_fast_symlink_iops;
}
static inline bool is_inode_fast_symlink(struct inode *inode)
{
-#ifdef CONFIG_EROFS_FS_XATTR
- return inode->i_op == &erofs_fast_symlink_xattr_iops;
-#else
- return inode->i_op == &simple_symlink_inode_operations;
-#endif
+ return inode->i_op == &erofs_fast_symlink_iops;
}
+struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir);
+
+/* namei.c */
+extern const struct inode_operations erofs_dir_iops;
+
+int erofs_namei(struct inode *dir, struct qstr *name,
+ erofs_nid_t *nid, unsigned int *d_type);
+
+/* dir.c */
+extern const struct file_operations erofs_dir_fops;
+
static inline void *erofs_vmap(struct page **pages, unsigned int count)
{
#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM
@@ -612,15 +585,11 @@ static inline void erofs_vunmap(const void *mem, unsigned int count)
}
/* utils.c */
-extern struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp);
-
-extern void erofs_register_super(struct super_block *sb);
-extern void erofs_unregister_super(struct super_block *sb);
+extern struct shrinker erofs_shrinker_info;
-extern unsigned long erofs_shrink_count(struct shrinker *shrink,
- struct shrink_control *sc);
-extern unsigned long erofs_shrink_scan(struct shrinker *shrink,
- struct shrink_control *sc);
+struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp);
+void erofs_register_super(struct super_block *sb);
+void erofs_unregister_super(struct super_block *sb);
#ifndef lru_to_page
#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c
index 5596c52e246d..3f4fa52c10fa 100644
--- a/drivers/staging/erofs/namei.c
+++ b/drivers/staging/erofs/namei.c
@@ -15,74 +15,77 @@
#include <trace/events/erofs.h>
-/* based on the value of qn->len is accurate */
-static inline int dirnamecmp(struct qstr *qn,
- struct qstr *qd, unsigned int *matched)
+struct erofs_qstr {
+ const unsigned char *name;
+ const unsigned char *end;
+};
+
+/* based on the end of qn is accurate and it must have the trailing '\0' */
+static inline int dirnamecmp(const struct erofs_qstr *qn,
+ const struct erofs_qstr *qd,
+ unsigned int *matched)
{
- unsigned int i = *matched, len = min(qn->len, qd->len);
-loop:
- if (unlikely(i >= len)) {
- *matched = i;
- if (qn->len < qd->len) {
- /*
- * actually (qn->len == qd->len)
- * when qd->name[i] == '\0'
- */
- return qd->name[i] == '\0' ? 0 : -1;
+ unsigned int i = *matched;
+
+ /*
+ * on-disk error, let's only BUG_ON in the debugging mode.
+ * otherwise, it will return 1 to just skip the invalid name
+ * and go on (in consideration of the lookup performance).
+ */
+ DBG_BUGON(qd->name > qd->end);
+
+ /* qd could not have trailing '\0' */
+ /* However it is absolutely safe if < qd->end */
+ while (qd->name + i < qd->end && qd->name[i] != '\0') {
+ if (qn->name[i] != qd->name[i]) {
+ *matched = i;
+ return qn->name[i] > qd->name[i] ? 1 : -1;
}
- return (qn->len > qd->len);
- }
-
- if (qn->name[i] != qd->name[i]) {
- *matched = i;
- return qn->name[i] > qd->name[i] ? 1 : -1;
+ ++i;
}
-
- ++i;
- goto loop;
+ *matched = i;
+ /* See comments in __d_alloc on the terminating NUL character */
+ return qn->name[i] == '\0' ? 0 : 1;
}
-static struct erofs_dirent *find_target_dirent(
- struct qstr *name,
- u8 *data, int maxsize)
+#define nameoff_from_disk(off, sz) (le16_to_cpu(off) & ((sz) - 1))
+
+static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
+ u8 *data,
+ unsigned int dirblksize,
+ const int ndirents)
{
- unsigned int ndirents, head, back;
+ int head, back;
unsigned int startprfx, endprfx;
struct erofs_dirent *const de = (struct erofs_dirent *)data;
- /* make sure that maxsize is valid */
- BUG_ON(maxsize < sizeof(struct erofs_dirent));
-
- ndirents = le16_to_cpu(de->nameoff) / sizeof(*de);
-
- /* corrupted dir (may be unnecessary...) */
- BUG_ON(!ndirents);
-
- head = 0;
+ /* since the 1st dirent has been evaluated previously */
+ head = 1;
back = ndirents - 1;
startprfx = endprfx = 0;
while (head <= back) {
- unsigned int mid = head + (back - head) / 2;
- unsigned int nameoff = le16_to_cpu(de[mid].nameoff);
+ const int mid = head + (back - head) / 2;
+ const int nameoff = nameoff_from_disk(de[mid].nameoff,
+ dirblksize);
unsigned int matched = min(startprfx, endprfx);
-
- struct qstr dname = QSTR_INIT(data + nameoff,
- unlikely(mid >= ndirents - 1) ?
- maxsize - nameoff :
- le16_to_cpu(de[mid + 1].nameoff) - nameoff);
+ struct erofs_qstr dname = {
+ .name = data + nameoff,
+ .end = unlikely(mid >= ndirents - 1) ?
+ data + dirblksize :
+ data + nameoff_from_disk(de[mid + 1].nameoff,
+ dirblksize)
+ };
/* string comparison without already matched prefix */
int ret = dirnamecmp(name, &dname, &matched);
- if (unlikely(!ret))
+ if (unlikely(!ret)) {
return de + mid;
- else if (ret > 0) {
+ } else if (ret > 0) {
head = mid + 1;
startprfx = matched;
- } else if (unlikely(mid < 1)) /* fix "mid" overflow */
- break;
- else {
+ } else {
back = mid - 1;
endprfx = matched;
}
@@ -91,12 +94,12 @@ static struct erofs_dirent *find_target_dirent(
return ERR_PTR(-ENOENT);
}
-static struct page *find_target_block_classic(
- struct inode *dir,
- struct qstr *name, int *_diff)
+static struct page *find_target_block_classic(struct inode *dir,
+ struct erofs_qstr *name,
+ int *_ndirents)
{
unsigned int startprfx, endprfx;
- unsigned int head, back;
+ int head, back;
struct address_space *const mapping = dir->i_mapping;
struct page *candidate = ERR_PTR(-ENOENT);
@@ -105,89 +108,97 @@ static struct page *find_target_block_classic(
back = inode_datablocks(dir) - 1;
while (head <= back) {
- unsigned int mid = head + (back - head) / 2;
+ const int mid = head + (back - head) / 2;
struct page *page = read_mapping_page(mapping, mid, NULL);
- if (IS_ERR(page)) {
-exact_out:
- if (!IS_ERR(candidate)) /* valid candidate */
- put_page(candidate);
- return page;
- } else {
- int diff;
- unsigned int ndirents, matched;
- struct qstr dname;
+ if (!IS_ERR(page)) {
struct erofs_dirent *de = kmap_atomic(page);
- unsigned int nameoff = le16_to_cpu(de->nameoff);
-
- ndirents = nameoff / sizeof(*de);
+ const int nameoff = nameoff_from_disk(de->nameoff,
+ EROFS_BLKSIZ);
+ const int ndirents = nameoff / sizeof(*de);
+ int diff;
+ unsigned int matched;
+ struct erofs_qstr dname;
- /* corrupted dir (should have one entry at least) */
- BUG_ON(!ndirents || nameoff > PAGE_SIZE);
+ if (unlikely(!ndirents)) {
+ DBG_BUGON(1);
+ kunmap_atomic(de);
+ put_page(page);
+ page = ERR_PTR(-EIO);
+ goto out;
+ }
matched = min(startprfx, endprfx);
dname.name = (u8 *)de + nameoff;
- dname.len = ndirents == 1 ?
- /* since the rest of the last page is 0 */
- EROFS_BLKSIZ - nameoff
- : le16_to_cpu(de[1].nameoff) - nameoff;
+ if (ndirents == 1)
+ dname.end = (u8 *)de + EROFS_BLKSIZ;
+ else
+ dname.end = (u8 *)de +
+ nameoff_from_disk(de[1].nameoff,
+ EROFS_BLKSIZ);
/* string comparison without already matched prefix */
diff = dirnamecmp(name, &dname, &matched);
kunmap_atomic(de);
if (unlikely(!diff)) {
- *_diff = 0;
- goto exact_out;
+ *_ndirents = 0;
+ goto out;
} else if (diff > 0) {
head = mid + 1;
startprfx = matched;
- if (likely(!IS_ERR(candidate)))
+ if (!IS_ERR(candidate))
put_page(candidate);
candidate = page;
+ *_ndirents = ndirents;
} else {
put_page(page);
- if (unlikely(mid < 1)) /* fix "mid" overflow */
- break;
-
back = mid - 1;
endprfx = matched;
}
+ continue;
}
+out: /* free if the candidate is valid */
+ if (!IS_ERR(candidate))
+ put_page(candidate);
+ return page;
}
- *_diff = 1;
return candidate;
}
int erofs_namei(struct inode *dir,
- struct qstr *name,
- erofs_nid_t *nid, unsigned int *d_type)
+ struct qstr *name,
+ erofs_nid_t *nid, unsigned int *d_type)
{
- int diff;
+ int ndirents;
struct page *page;
- u8 *data;
+ void *data;
struct erofs_dirent *de;
+ struct erofs_qstr qn;
if (unlikely(!dir->i_size))
return -ENOENT;
- diff = 1;
- page = find_target_block_classic(dir, name, &diff);
+ qn.name = name->name;
+ qn.end = name->name + name->len;
+
+ ndirents = 0;
+ page = find_target_block_classic(dir, &qn, &ndirents);
- if (unlikely(IS_ERR(page)))
+ if (IS_ERR(page))
return PTR_ERR(page);
data = kmap_atomic(page);
/* the target page has been mapped */
- de = likely(diff) ?
- /* since the rest of the last page is 0 */
- find_target_dirent(name, data, EROFS_BLKSIZ) :
- (struct erofs_dirent *)data;
+ if (ndirents)
+ de = find_target_dirent(&qn, data, EROFS_BLKSIZ, ndirents);
+ else
+ de = (struct erofs_dirent *)data;
- if (likely(!IS_ERR(de))) {
+ if (!IS_ERR(de)) {
*nid = le64_to_cpu(de->nid);
*d_type = de->file_type;
}
@@ -235,12 +246,9 @@ static struct dentry *erofs_lookup(struct inode *dir,
const struct inode_operations erofs_dir_iops = {
.lookup = erofs_lookup,
-};
-
-const struct inode_operations erofs_dir_xattr_iops = {
- .lookup = erofs_lookup,
#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
#endif
+ .get_acl = erofs_get_acl,
};
diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c
index 1c2eb69682ef..15c784fba879 100644
--- a/drivers/staging/erofs/super.c
+++ b/drivers/staging/erofs/super.c
@@ -16,6 +16,7 @@
#include <linux/parser.h>
#include <linux/seq_file.h>
#include "internal.h"
+#include "xattr.h"
#define CREATE_TRACE_POINTS
#include <trace/events/erofs.h>
@@ -397,6 +398,11 @@ static int erofs_read_super(struct super_block *sb,
if (!silent)
infoln("root inode @ nid %llu", ROOT_NID(sbi));
+ if (test_opt(sbi, POSIX_ACL))
+ sb->s_flags |= SB_POSIXACL;
+ else
+ sb->s_flags &= ~SB_POSIXACL;
+
#ifdef CONFIG_EROFS_FS_ZIP
INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC);
#endif
@@ -420,13 +426,14 @@ static int erofs_read_super(struct super_block *sb,
errln("rootino(nid %llu) is not a directory(i_mode %o)",
ROOT_NID(sbi), inode->i_mode);
err = -EINVAL;
- goto err_isdir;
+ iput(inode);
+ goto err_iget;
}
sb->s_root = d_make_root(inode);
if (sb->s_root == NULL) {
err = -ENOMEM;
- goto err_makeroot;
+ goto err_iget;
}
/* save the device name to sbi */
@@ -452,10 +459,6 @@ static int erofs_read_super(struct super_block *sb,
*/
err_devname:
dput(sb->s_root);
-err_makeroot:
-err_isdir:
- if (sb->s_root == NULL)
- iput(inode);
err_iget:
#ifdef EROFS_FS_HAS_MANAGED_CACHE
iput(sbi->managed_cache);
@@ -493,7 +496,8 @@ static void erofs_put_super(struct super_block *sb)
mutex_lock(&sbi->umount_mutex);
#ifdef CONFIG_EROFS_FS_ZIP
- erofs_workstation_cleanup_all(sb);
+ /* clean up the compression space of this sb */
+ erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true);
#endif
erofs_unregister_super(sb);
@@ -537,12 +541,6 @@ static void erofs_kill_sb(struct super_block *sb)
kill_block_super(sb);
}
-static struct shrinker erofs_shrinker_info = {
- .scan_objects = erofs_shrink_scan,
- .count_objects = erofs_shrink_count,
- .seeks = DEFAULT_SEEKS,
-};
-
static struct file_system_type erofs_fs_type = {
.owner = THIS_MODULE,
.name = "erofs",
@@ -653,6 +651,11 @@ static int erofs_remount(struct super_block *sb, int *flags, char *data)
if (err)
goto out;
+ if (test_opt(sbi, POSIX_ACL))
+ sb->s_flags |= SB_POSIXACL;
+ else
+ sb->s_flags &= ~SB_POSIXACL;
+
*flags |= SB_RDONLY;
return 0;
out:
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 4ac1099a39c6..02f34a83147d 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -107,15 +107,30 @@ enum z_erofs_vle_work_role {
Z_EROFS_VLE_WORK_SECONDARY,
Z_EROFS_VLE_WORK_PRIMARY,
/*
- * The current work has at least been linked with the following
- * processed chained works, which means if the processing page
- * is the tail partial page of the work, the current work can
- * safely use the whole page, as illustrated below:
- * +--------------+-------------------------------------------+
- * | tail page | head page (of the previous work) |
- * +--------------+-------------------------------------------+
- * /\ which belongs to the current work
- * [ (*) this page can be used for the current work itself. ]
+ * The current work was the tail of an exist chain, and the previous
+ * processed chained works are all decided to be hooked up to it.
+ * A new chain should be created for the remaining unprocessed works,
+ * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED,
+ * the next work cannot reuse the whole page in the following scenario:
+ * ________________________________________________________________
+ * | tail (partial) page | head (partial) page |
+ * | (belongs to the next work) | (belongs to the current work) |
+ * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________|
+ */
+ Z_EROFS_VLE_WORK_PRIMARY_HOOKED,
+ /*
+ * The current work has been linked with the processed chained works,
+ * and could be also linked with the potential remaining works, which
+ * means if the processing page is the tail partial page of the work,
+ * the current work can safely use the whole page (since the next work
+ * is under control) for in-place decompression, as illustrated below:
+ * ________________________________________________________________
+ * | tail (partial) page | head (partial) page |
+ * | (of the current work) | (of the previous work) |
+ * | PRIMARY_FOLLOWED or | |
+ * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________|
+ *
+ * [ (*) the above page can be used for the current work itself. ]
*/
Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED,
Z_EROFS_VLE_WORK_MAX
@@ -238,14 +253,9 @@ int erofs_try_to_free_cached_page(struct address_space *mapping,
{
struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb);
const unsigned int clusterpages = erofs_clusterpages(sbi);
-
- struct z_erofs_vle_workgroup *grp;
+ struct z_erofs_vle_workgroup *const grp = (void *)page_private(page);
int ret = 0; /* 0 - busy */
- /* prevent the workgroup from being freed */
- rcu_read_lock();
- grp = (void *)page_private(page);
-
if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) {
unsigned int i;
@@ -257,12 +267,11 @@ int erofs_try_to_free_cached_page(struct address_space *mapping,
}
}
erofs_workgroup_unfreeze(&grp->obj, 1);
- }
- rcu_read_unlock();
- if (ret) {
- ClearPagePrivate(page);
- put_page(page);
+ if (ret) {
+ ClearPagePrivate(page);
+ put_page(page);
+ }
}
return ret;
}
@@ -315,10 +324,10 @@ static int z_erofs_vle_work_add_page(
return ret ? 0 : -EAGAIN;
}
-static inline bool try_to_claim_workgroup(
- struct z_erofs_vle_workgroup *grp,
- z_erofs_vle_owned_workgrp_t *owned_head,
- bool *hosted)
+static enum z_erofs_vle_work_role
+try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp,
+ z_erofs_vle_owned_workgrp_t *owned_head,
+ bool *hosted)
{
DBG_BUGON(*hosted == true);
@@ -332,6 +341,9 @@ retry:
*owned_head = &grp->next;
*hosted = true;
+ /* lucky, I am the followee :) */
+ return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED;
+
} else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) {
/*
* type 2, link to the end of a existing open chain,
@@ -341,12 +353,11 @@ retry:
if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL,
*owned_head) != Z_EROFS_VLE_WORKGRP_TAIL)
goto retry;
-
*owned_head = Z_EROFS_VLE_WORKGRP_TAIL;
- } else
- return false; /* :( better luck next time */
+ return Z_EROFS_VLE_WORK_PRIMARY_HOOKED;
+ }
- return true; /* lucky, I am the followee :) */
+ return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */
}
struct z_erofs_vle_work_finder {
@@ -424,12 +435,9 @@ z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f)
*f->hosted = false;
if (!primary)
*f->role = Z_EROFS_VLE_WORK_SECONDARY;
- /* claim the workgroup if possible */
- else if (try_to_claim_workgroup(grp, f->owned_head, f->hosted))
- *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED;
- else
- *f->role = Z_EROFS_VLE_WORK_PRIMARY;
-
+ else /* claim the workgroup if possible */
+ *f->role = try_to_claim_workgroup(grp, f->owned_head,
+ f->hosted);
return work;
}
@@ -493,6 +501,9 @@ z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f,
return work;
}
+#define builder_is_hooked(builder) \
+ ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED)
+
#define builder_is_followed(builder) \
((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED)
@@ -539,7 +550,7 @@ repeat:
if (unlikely(work == ERR_PTR(-EAGAIN)))
goto repeat;
- if (unlikely(IS_ERR(work)))
+ if (IS_ERR(work))
return PTR_ERR(work);
got_it:
z_erofs_pagevec_ctor_init(&builder->vector,
@@ -589,7 +600,7 @@ static void __z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp,
erofs_workgroup_put(&grp->obj);
}
-void z_erofs_vle_work_release(struct z_erofs_vle_work *work)
+static void z_erofs_vle_work_release(struct z_erofs_vle_work *work)
{
struct z_erofs_vle_workgroup *grp =
z_erofs_vle_work_workgroup(work, true);
@@ -636,7 +647,7 @@ struct z_erofs_vle_frontend {
struct inode *const inode;
struct z_erofs_vle_work_builder builder;
- struct erofs_map_blocks_iter m_iter;
+ struct erofs_map_blocks map;
z_erofs_vle_owned_workgrp_t owned_head;
@@ -647,8 +658,9 @@ struct z_erofs_vle_frontend {
#define VLE_FRONTEND_INIT(__i) { \
.inode = __i, \
- .m_iter = { \
- { .m_llen = 0, .m_plen = 0 }, \
+ .map = { \
+ .m_llen = 0, \
+ .m_plen = 0, \
.mpage = NULL \
}, \
.builder = VLE_WORK_BUILDER_INIT(), \
@@ -681,12 +693,11 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
{
struct super_block *const sb = fe->inode->i_sb;
struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb);
- struct erofs_map_blocks_iter *const m = &fe->m_iter;
- struct erofs_map_blocks *const map = &m->map;
+ struct erofs_map_blocks *const map = &fe->map;
struct z_erofs_vle_work_builder *const builder = &fe->builder;
const loff_t offset = page_offset(page);
- bool tight = builder_is_followed(builder);
+ bool tight = builder_is_hooked(builder);
struct z_erofs_vle_work *work = builder->work;
enum z_erofs_cache_alloctype cache_strategy;
@@ -704,8 +715,12 @@ repeat:
/* lucky, within the range of the current map_blocks */
if (offset + cur >= map->m_la &&
- offset + cur < map->m_la + map->m_llen)
+ offset + cur < map->m_la + map->m_llen) {
+ /* didn't get a valid unzip work previously (very rare) */
+ if (!builder->work)
+ goto restart_now;
goto hitted;
+ }
/* go ahead the next map_blocks */
debugln("%s: [out-of-range] pos %llu", __func__, offset + cur);
@@ -715,10 +730,11 @@ repeat:
map->m_la = offset + cur;
map->m_llen = 0;
- err = erofs_map_blocks_iter(fe->inode, map, &m->mpage, 0);
+ err = z_erofs_map_blocks_iter(fe->inode, map, 0);
if (unlikely(err))
goto err_out;
+restart_now:
if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED)))
goto hitted;
@@ -740,7 +756,7 @@ repeat:
map->m_plen / PAGE_SIZE,
cache_strategy, page_pool, GFP_KERNEL);
- tight &= builder_is_followed(builder);
+ tight &= builder_is_hooked(builder);
work = builder->work;
hitted:
cur = end - min_t(unsigned int, offset + end - map->m_la, end);
@@ -755,6 +771,9 @@ hitted:
(tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE :
Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED));
+ if (cur)
+ tight &= builder_is_followed(builder);
+
retry:
err = z_erofs_vle_work_add_page(builder, page, page_type);
/* should allocate an additional staging page for pagevec */
@@ -992,11 +1011,10 @@ repeat:
if (llen > grp->llen)
llen = grp->llen;
- err = z_erofs_vle_unzip_fast_percpu(compressed_pages,
- clusterpages, pages, llen, work->pageofs,
- z_erofs_onlinepage_endio);
+ err = z_erofs_vle_unzip_fast_percpu(compressed_pages, clusterpages,
+ pages, llen, work->pageofs);
if (err != -ENOTSUPP)
- goto out_percpu;
+ goto out;
if (sparsemem_pages >= nr_pages)
goto skip_allocpage;
@@ -1017,8 +1035,25 @@ skip_allocpage:
erofs_vunmap(vout, nr_pages);
out:
+ /* must handle all compressed pages before endding pages */
+ for (i = 0; i < clusterpages; ++i) {
+ page = compressed_pages[i];
+
+#ifdef EROFS_FS_HAS_MANAGED_CACHE
+ if (page->mapping == MNGD_MAPPING(sbi))
+ continue;
+#endif
+ /* recycle all individual staging pages */
+ (void)z_erofs_gather_if_stagingpage(page_pool, page);
+
+ WRITE_ONCE(compressed_pages[i], NULL);
+ }
+
for (i = 0; i < nr_pages; ++i) {
page = pages[i];
+ if (!page)
+ continue;
+
DBG_BUGON(!page->mapping);
/* recycle all individual staging pages */
@@ -1031,20 +1066,6 @@ out:
z_erofs_onlinepage_endio(page);
}
-out_percpu:
- for (i = 0; i < clusterpages; ++i) {
- page = compressed_pages[i];
-
-#ifdef EROFS_FS_HAS_MANAGED_CACHE
- if (page->mapping == MNGD_MAPPING(sbi))
- continue;
-#endif
- /* recycle all individual staging pages */
- (void)z_erofs_gather_if_stagingpage(page_pool, page);
-
- WRITE_ONCE(compressed_pages[i], NULL);
- }
-
if (pages == z_pagemap_global)
mutex_unlock(&z_pagemap_global_lock);
else if (unlikely(pages != pages_onstack))
@@ -1484,8 +1505,8 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file,
z_erofs_submit_and_unzip(&f, &pagepool, true);
out:
- if (f.m_iter.mpage)
- put_page(f.m_iter.mpage);
+ if (f.map.mpage)
+ put_page(f.map.mpage);
/* clean up the remaining free pages */
put_pages_list(&pagepool);
@@ -1555,8 +1576,8 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp,
z_erofs_submit_and_unzip(&f, &pagepool, sync);
- if (f.m_iter.mpage)
- put_page(f.m_iter.mpage);
+ if (f.map.mpage)
+ put_page(f.map.mpage);
/* clean up the remaining free pages */
put_pages_list(&pagepool);
@@ -1701,14 +1722,14 @@ vle_get_logical_extent_head(const struct vle_map_blocks_iter_ctx *ctx,
int z_erofs_map_blocks_iter(struct inode *inode,
struct erofs_map_blocks *map,
- struct page **mpage_ret, int flags)
+ int flags)
{
void *kaddr;
const struct vle_map_blocks_iter_ctx ctx = {
.inode = inode,
.sb = inode->i_sb,
.clusterbits = EROFS_I_SB(inode)->clusterbits,
- .mpage_ret = mpage_ret,
+ .mpage_ret = &map->mpage,
.kaddr_ret = &kaddr
};
const unsigned int clustersize = 1 << ctx.clusterbits;
@@ -1722,7 +1743,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* initialize `pblk' to keep gcc from printing foolish warnings */
erofs_blk_t mblk, pblk = 0;
- struct page *mpage = *mpage_ret;
+ struct page *mpage = map->mpage;
struct z_erofs_vle_decompressed_index *di;
unsigned int cluster_type, logical_cluster_ofs;
int err = 0;
@@ -1758,7 +1779,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
err = PTR_ERR(mpage);
goto out;
}
- *mpage_ret = mpage;
+ map->mpage = mpage;
} else {
lock_page(mpage);
DBG_BUGON(!PageUptodate(mpage));
@@ -1818,7 +1839,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* get the correspoinding first chunk */
err = vle_get_logical_extent_head(&ctx, lcn, &ofs,
&pblk, &map->m_flags);
- mpage = *mpage_ret;
+ mpage = map->mpage;
if (unlikely(err)) {
if (mpage)
diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h
index 5a4e1b62c0d1..517e5ce8c5e9 100644
--- a/drivers/staging/erofs/unzip_vle.h
+++ b/drivers/staging/erofs/unzip_vle.h
@@ -212,18 +212,17 @@ static inline void z_erofs_onlinepage_endio(struct page *page)
#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048
/* unzip_vle_lz4.c */
-extern int z_erofs_vle_plain_copy(struct page **compressed_pages,
- unsigned clusterpages, struct page **pages,
- unsigned nr_pages, unsigned short pageofs);
-
-extern int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
- unsigned clusterpages, struct page **pages,
- unsigned outlen, unsigned short pageofs,
- void (*endio)(struct page *));
-
-extern int z_erofs_vle_unzip_vmap(struct page **compressed_pages,
- unsigned clusterpages, void *vaddr, unsigned llen,
- unsigned short pageofs, bool overlapped);
+int z_erofs_vle_plain_copy(struct page **compressed_pages,
+ unsigned int clusterpages, struct page **pages,
+ unsigned int nr_pages, unsigned short pageofs);
+int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
+ unsigned int clusterpages,
+ struct page **pages, unsigned int outlen,
+ unsigned short pageofs);
+int z_erofs_vle_unzip_vmap(struct page **compressed_pages,
+ unsigned int clusterpages,
+ void *vaddr, unsigned int llen,
+ unsigned short pageofs, bool overlapped);
#endif
diff --git a/drivers/staging/erofs/unzip_vle_lz4.c b/drivers/staging/erofs/unzip_vle_lz4.c
index 52797bd89da1..48b263a2731a 100644
--- a/drivers/staging/erofs/unzip_vle_lz4.c
+++ b/drivers/staging/erofs/unzip_vle_lz4.c
@@ -13,7 +13,7 @@
#include "unzip_vle.h"
#include <linux/lz4.h>
-int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen)
+static int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen)
{
int ret = LZ4_decompress_safe_partial(in, out, inlen, outlen, outlen);
@@ -125,8 +125,7 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
unsigned int clusterpages,
struct page **pages,
unsigned int outlen,
- unsigned short pageofs,
- void (*endio)(struct page *))
+ unsigned short pageofs)
{
void *vin, *vout;
unsigned int nr_pages, i, j;
@@ -148,19 +147,16 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
ret = z_erofs_unzip_lz4(vin, vout + pageofs,
clusterpages * PAGE_SIZE, outlen);
- if (ret >= 0) {
- outlen = ret;
- ret = 0;
- }
+ if (ret < 0)
+ goto out;
+ ret = 0;
for (i = 0; i < nr_pages; ++i) {
j = min((unsigned int)PAGE_SIZE - pageofs, outlen);
if (pages[i]) {
- if (ret < 0) {
- SetPageError(pages[i]);
- } else if (clusterpages == 1 &&
- pages[i] == compressed_pages[0]) {
+ if (clusterpages == 1 &&
+ pages[i] == compressed_pages[0]) {
memcpy(vin + pageofs, vout + pageofs, j);
} else {
void *dst = kmap_atomic(pages[i]);
@@ -168,12 +164,13 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
memcpy(dst + pageofs, vout + pageofs, j);
kunmap_atomic(dst);
}
- endio(pages[i]);
}
vout += PAGE_SIZE;
outlen -= j;
pageofs = 0;
}
+
+out:
preempt_enable();
if (clusterpages == 1)
diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c
index b535898ca753..5f61f99f4c10 100644
--- a/drivers/staging/erofs/utils.c
+++ b/drivers/staging/erofs/utils.c
@@ -31,13 +31,32 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp)
static atomic_long_t erofs_global_shrink_cnt;
#ifdef CONFIG_EROFS_FS_ZIP
+#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount)
+#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount)
-struct erofs_workgroup *erofs_find_workgroup(
- struct super_block *sb, pgoff_t index, bool *tag)
+static int erofs_workgroup_get(struct erofs_workgroup *grp)
+{
+ int o;
+
+repeat:
+ o = erofs_wait_on_workgroup_freezed(grp);
+ if (unlikely(o <= 0))
+ return -1;
+
+ if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o))
+ goto repeat;
+
+ /* decrease refcount paired by erofs_workgroup_put */
+ if (unlikely(o == 1))
+ atomic_long_dec(&erofs_global_shrink_cnt);
+ return 0;
+}
+
+struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb,
+ pgoff_t index, bool *tag)
{
struct erofs_sb_info *sbi = EROFS_SB(sb);
struct erofs_workgroup *grp;
- int oldcount;
repeat:
rcu_read_lock();
@@ -46,15 +65,12 @@ repeat:
*tag = xa_pointer_tag(grp);
grp = xa_untag_pointer(grp);
- if (erofs_workgroup_get(grp, &oldcount)) {
+ if (erofs_workgroup_get(grp)) {
/* prefer to relax rcu read side */
rcu_read_unlock();
goto repeat;
}
- /* decrease refcount added by erofs_workgroup_put */
- if (unlikely(oldcount == 1))
- atomic_long_dec(&erofs_global_shrink_cnt);
DBG_BUGON(index != grp->index);
}
rcu_read_unlock();
@@ -104,8 +120,6 @@ int erofs_register_workgroup(struct super_block *sb,
return err;
}
-extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
-
static void __erofs_workgroup_free(struct erofs_workgroup *grp)
{
atomic_long_dec(&erofs_global_shrink_cnt);
@@ -131,9 +145,9 @@ static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp)
__erofs_workgroup_free(grp);
}
-bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
- struct erofs_workgroup *grp,
- bool cleanup)
+static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
+ struct erofs_workgroup *grp,
+ bool cleanup)
{
/*
* for managed cache enabled, the refcount of workgroups
@@ -172,9 +186,9 @@ bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
#else
/* for nocache case, no customized reclaim path at all */
-bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
- struct erofs_workgroup *grp,
- bool cleanup)
+static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
+ struct erofs_workgroup *grp,
+ bool cleanup)
{
int cnt = atomic_read(&grp->refcount);
@@ -256,14 +270,14 @@ void erofs_unregister_super(struct super_block *sb)
spin_unlock(&erofs_sb_list_lock);
}
-unsigned long erofs_shrink_count(struct shrinker *shrink,
- struct shrink_control *sc)
+static unsigned long erofs_shrink_count(struct shrinker *shrink,
+ struct shrink_control *sc)
{
return atomic_long_read(&erofs_global_shrink_cnt);
}
-unsigned long erofs_shrink_scan(struct shrinker *shrink,
- struct shrink_control *sc)
+static unsigned long erofs_shrink_scan(struct shrinker *shrink,
+ struct shrink_control *sc)
{
struct erofs_sb_info *sbi;
struct list_head *p;
@@ -319,3 +333,9 @@ unsigned long erofs_shrink_scan(struct shrinker *shrink,
return freed;
}
+struct shrinker erofs_shrinker_info = {
+ .scan_objects = erofs_shrink_scan,
+ .count_objects = erofs_shrink_count,
+ .seeks = DEFAULT_SEEKS,
+};
+
diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c
index 80dca6a4adbe..f716ab0446e5 100644
--- a/drivers/staging/erofs/xattr.c
+++ b/drivers/staging/erofs/xattr.c
@@ -44,19 +44,48 @@ static inline void xattr_iter_end_final(struct xattr_iter *it)
static int init_inode_xattrs(struct inode *inode)
{
+ struct erofs_vnode *const vi = EROFS_V(inode);
struct xattr_iter it;
unsigned int i;
struct erofs_xattr_ibody_header *ih;
struct super_block *sb;
struct erofs_sb_info *sbi;
- struct erofs_vnode *vi;
bool atomic_map;
+ int ret = 0;
- if (likely(inode_has_inited_xattr(inode)))
+ /* the most case is that xattrs of this inode are initialized. */
+ if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags))
return 0;
- vi = EROFS_V(inode);
- BUG_ON(!vi->xattr_isize);
+ if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_XATTR_BIT, TASK_KILLABLE))
+ return -ERESTARTSYS;
+
+ /* someone has initialized xattrs for us? */
+ if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags))
+ goto out_unlock;
+
+ /*
+ * bypass all xattr operations if ->xattr_isize is not greater than
+ * sizeof(struct erofs_xattr_ibody_header), in detail:
+ * 1) it is not enough to contain erofs_xattr_ibody_header then
+ * ->xattr_isize should be 0 (it means no xattr);
+ * 2) it is just to contain erofs_xattr_ibody_header, which is on-disk
+ * undefined right now (maybe use later with some new sb feature).
+ */
+ if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) {
+ errln("xattr_isize %d of nid %llu is not supported yet",
+ vi->xattr_isize, vi->nid);
+ ret = -ENOTSUPP;
+ goto out_unlock;
+ } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) {
+ if (unlikely(vi->xattr_isize)) {
+ DBG_BUGON(1);
+ ret = -EIO;
+ goto out_unlock; /* xattr ondisk layout error */
+ }
+ ret = -ENOATTR;
+ goto out_unlock;
+ }
sb = inode->i_sb;
sbi = EROFS_SB(sb);
@@ -64,8 +93,10 @@ static int init_inode_xattrs(struct inode *inode)
it.ofs = erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize);
it.page = erofs_get_inline_page(inode, it.blkaddr);
- if (IS_ERR(it.page))
- return PTR_ERR(it.page);
+ if (IS_ERR(it.page)) {
+ ret = PTR_ERR(it.page);
+ goto out_unlock;
+ }
/* read in shared xattr array (non-atomic, see kmalloc below) */
it.kaddr = kmap(it.page);
@@ -78,7 +109,8 @@ static int init_inode_xattrs(struct inode *inode)
sizeof(uint), GFP_KERNEL);
if (vi->xattr_shared_xattrs == NULL) {
xattr_iter_end(&it, atomic_map);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_unlock;
}
/* let's skip ibody header */
@@ -92,8 +124,12 @@ static int init_inode_xattrs(struct inode *inode)
it.page = erofs_get_meta_page(sb,
++it.blkaddr, S_ISDIR(inode->i_mode));
- if (IS_ERR(it.page))
- return PTR_ERR(it.page);
+ if (IS_ERR(it.page)) {
+ kfree(vi->xattr_shared_xattrs);
+ vi->xattr_shared_xattrs = NULL;
+ ret = PTR_ERR(it.page);
+ goto out_unlock;
+ }
it.kaddr = kmap_atomic(it.page);
atomic_map = true;
@@ -105,8 +141,11 @@ static int init_inode_xattrs(struct inode *inode)
}
xattr_iter_end(&it, atomic_map);
- inode_set_inited_xattr(inode);
- return 0;
+ set_bit(EROFS_V_EA_INITED_BIT, &vi->flags);
+
+out_unlock:
+ clear_and_wake_up_bit(EROFS_V_BL_XATTR_BIT, &vi->flags);
+ return ret;
}
/*
@@ -117,10 +156,12 @@ static int init_inode_xattrs(struct inode *inode)
* and need to be handled
*/
struct xattr_iter_handlers {
- int (*entry)(struct xattr_iter *, struct erofs_xattr_entry *);
- int (*name)(struct xattr_iter *, unsigned int, char *, unsigned int);
- int (*alloc_buffer)(struct xattr_iter *, unsigned int);
- void (*value)(struct xattr_iter *, unsigned int, char *, unsigned int);
+ int (*entry)(struct xattr_iter *_it, struct erofs_xattr_entry *entry);
+ int (*name)(struct xattr_iter *_it, unsigned int processed, char *buf,
+ unsigned int len);
+ int (*alloc_buffer)(struct xattr_iter *_it, unsigned int value_sz);
+ void (*value)(struct xattr_iter *_it, unsigned int processed, char *buf,
+ unsigned int len);
};
static inline int xattr_iter_fixup(struct xattr_iter *it)
@@ -422,7 +463,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *name, void *buffer, size_t size)
{
- struct erofs_vnode *const vi = EROFS_V(inode);
struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
switch (handler->flags) {
@@ -440,9 +480,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
return -EINVAL;
}
- if (!vi->xattr_isize)
- return -ENOATTR;
-
return erofs_getxattr(inode, handler->flags, name, buffer, size);
}
@@ -503,8 +540,7 @@ static int xattr_entrylist(struct xattr_iter *_it,
if (h == NULL || (h->list != NULL && !h->list(it->dentry)))
return 1;
- /* Note that at least one of 'prefix' and 'name' should be non-NULL */
- prefix = h->prefix != NULL ? h->prefix : h->name;
+ prefix = xattr_prefix(h);
prefix_len = strlen(prefix);
if (it->buffer == NULL) {
@@ -627,3 +663,40 @@ ssize_t erofs_listxattr(struct dentry *dentry,
return shared_listxattr(&it);
}
+#ifdef CONFIG_EROFS_FS_POSIX_ACL
+struct posix_acl *erofs_get_acl(struct inode *inode, int type)
+{
+ struct posix_acl *acl;
+ int prefix, rc;
+ char *value = NULL;
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ prefix = EROFS_XATTR_INDEX_POSIX_ACL_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ prefix = EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ rc = erofs_getxattr(inode, prefix, "", NULL, 0);
+ if (rc > 0) {
+ value = kmalloc(rc, GFP_KERNEL);
+ if (!value)
+ return ERR_PTR(-ENOMEM);
+ rc = erofs_getxattr(inode, prefix, "", value, rc);
+ }
+
+ if (rc == -ENOATTR)
+ acl = NULL;
+ else if (rc < 0)
+ acl = ERR_PTR(rc);
+ else
+ acl = posix_acl_from_xattr(&init_user_ns, value, rc);
+ kfree(value);
+ return acl;
+}
+#endif
+
diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h
index 0c7379282fc5..35ba5ac2139a 100644
--- a/drivers/staging/erofs/xattr.h
+++ b/drivers/staging/erofs/xattr.h
@@ -68,9 +68,7 @@ static const struct xattr_handler *xattr_handler_map[] = {
}
#ifdef CONFIG_EROFS_FS_XATTR
-
-extern const struct inode_operations erofs_generic_xattr_iops;
-extern const struct inode_operations erofs_dir_xattr_iops;
+extern const struct xattr_handler *erofs_xattr_handlers[];
int erofs_getxattr(struct inode *, int, const char *, void *, size_t);
ssize_t erofs_listxattr(struct dentry *, char *, size_t);
@@ -89,5 +87,11 @@ static ssize_t __maybe_unused erofs_listxattr(struct dentry *dentry,
}
#endif
+#ifdef CONFIG_EROFS_FS_POSIX_ACL
+struct posix_acl *erofs_get_acl(struct inode *inode, int type);
+#else
+#define erofs_get_acl (NULL)
+#endif
+
#endif
diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c
index f6f30f5bf15a..8f27bd8da17d 100644
--- a/drivers/staging/fbtft/fb_agm1264k-fl.c
+++ b/drivers/staging/fbtft/fb_agm1264k-fl.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -79,14 +79,14 @@ static int init_display(struct fbtft_par *par)
static void reset(struct fbtft_par *par)
{
- if (par->gpio.reset == -1)
+ if (!par->gpio.reset)
return;
dev_dbg(par->info->device, "%s()\n", __func__);
- gpio_set_value(par->gpio.reset, 0);
+ gpiod_set_value(par->gpio.reset, 0);
udelay(20);
- gpio_set_value(par->gpio.reset, 1);
+ gpiod_set_value(par->gpio.reset, 1);
mdelay(120);
}
@@ -98,30 +98,30 @@ static int verify_gpios(struct fbtft_par *par)
dev_dbg(par->info->device,
"%s()\n", __func__);
- if (par->EPIN < 0) {
+ if (!par->EPIN) {
dev_err(par->info->device,
"Missing info about 'wr' (aka E) gpio. Aborting.\n");
return -EINVAL;
}
for (i = 0; i < 8; ++i) {
- if (par->gpio.db[i] < 0) {
+ if (!par->gpio.db[i]) {
dev_err(par->info->device,
"Missing info about 'db[%i]' gpio. Aborting.\n",
i);
return -EINVAL;
}
}
- if (par->CS0 < 0) {
+ if (!par->CS0) {
dev_err(par->info->device,
"Missing info about 'cs0' gpio. Aborting.\n");
return -EINVAL;
}
- if (par->CS1 < 0) {
+ if (!par->CS1) {
dev_err(par->info->device,
"Missing info about 'cs1' gpio. Aborting.\n");
return -EINVAL;
}
- if (par->RW < 0) {
+ if (!par->RW) {
dev_err(par->info->device,
"Missing info about 'rw' gpio. Aborting.\n");
return -EINVAL;
@@ -139,22 +139,22 @@ request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio)
if (strcasecmp(gpio->name, "wr") == 0) {
/* left ks0108 E pin */
par->EPIN = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
+ return GPIOD_OUT_LOW;
} else if (strcasecmp(gpio->name, "cs0") == 0) {
/* left ks0108 controller pin */
par->CS0 = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
+ return GPIOD_OUT_HIGH;
} else if (strcasecmp(gpio->name, "cs1") == 0) {
/* right ks0108 controller pin */
par->CS1 = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
+ return GPIOD_OUT_HIGH;
}
/* if write (rw = 0) e(1->0) perform write */
/* if read (rw = 1) e(0->1) set data on D0-7*/
else if (strcasecmp(gpio->name, "rw") == 0) {
par->RW = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
+ return GPIOD_OUT_LOW;
}
return FBTFT_GPIO_NO_MATCH;
@@ -194,15 +194,15 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
/* select chip */
if (*buf) {
/* cs1 */
- gpio_set_value(par->CS0, 1);
- gpio_set_value(par->CS1, 0);
+ gpiod_set_value(par->CS0, 1);
+ gpiod_set_value(par->CS1, 0);
} else {
/* cs0 */
- gpio_set_value(par->CS0, 0);
- gpio_set_value(par->CS1, 1);
+ gpiod_set_value(par->CS0, 0);
+ gpiod_set_value(par->CS1, 1);
}
- gpio_set_value(par->RS, 0); /* RS->0 (command mode) */
+ gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */
len--;
if (len) {
@@ -364,7 +364,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
write_reg(par, 0x00, (0x17 << 3) | (u8)y);
/* write bitmap */
- gpio_set_value(par->RS, 1); /* RS->1 (data mode) */
+ gpiod_set_value(par->RS, 1); /* RS->1 (data mode) */
ret = par->fbtftops.write(par, buf, len);
if (ret < 0)
dev_err(par->info->device,
@@ -387,7 +387,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
write_reg(par, 0x01, (0x17 << 3) | (u8)y);
/* write bitmap */
- gpio_set_value(par->RS, 1); /* RS->1 (data mode) */
+ gpiod_set_value(par->RS, 1); /* RS->1 (data mode) */
par->fbtftops.write(par, buf, len);
if (ret < 0)
dev_err(par->info->device,
@@ -397,8 +397,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
kfree(convert_buf);
- gpio_set_value(par->CS0, 1);
- gpio_set_value(par->CS1, 1);
+ gpiod_set_value(par->CS0, 1);
+ gpiod_set_value(par->CS1, 1);
return ret;
}
@@ -408,7 +408,7 @@ static int write(struct fbtft_par *par, void *buf, size_t len)
fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
"%s(len=%d): ", __func__, len);
- gpio_set_value(par->RW, 0); /* set write mode */
+ gpiod_set_value(par->RW, 0); /* set write mode */
while (len--) {
u8 i, data;
@@ -417,12 +417,12 @@ static int write(struct fbtft_par *par, void *buf, size_t len)
/* set data bus */
for (i = 0; i < 8; ++i)
- gpio_set_value(par->gpio.db[i], data & (1 << i));
+ gpiod_set_value(par->gpio.db[i], data & (1 << i));
/* set E */
- gpio_set_value(par->EPIN, 1);
+ gpiod_set_value(par->EPIN, 1);
udelay(5);
/* unset E - write */
- gpio_set_value(par->EPIN, 0);
+ gpiod_set_value(par->EPIN, 0);
udelay(1);
}
diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c
index a58c514f4721..b6c6d66e4eb1 100644
--- a/drivers/staging/fbtft/fb_bd663474.c
+++ b/drivers/staging/fbtft/fb_bd663474.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -24,8 +24,8 @@
static int init_display(struct fbtft_par *par)
{
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
par->fbtftops.reset(par);
diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c
index 86e140244aab..d609a2b67db9 100644
--- a/drivers/staging/fbtft/fb_ili9163.c
+++ b/drivers/staging/fbtft/fb_ili9163.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <video/mipi_display.h>
@@ -77,8 +77,8 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
mdelay(500);
diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c
index 740c0acbecd8..ea6e001288ce 100644
--- a/drivers/staging/fbtft/fb_ili9320.c
+++ b/drivers/staging/fbtft/fb_ili9320.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c
index 2cf75f2e03e2..b090e7ab6fdd 100644
--- a/drivers/staging/fbtft/fb_ili9325.c
+++ b/drivers/staging/fbtft/fb_ili9325.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -85,8 +85,8 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
bt &= 0x07;
vc &= 0x07;
diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c
index 430f21e50f4d..415183c7054a 100644
--- a/drivers/staging/fbtft/fb_ili9340.c
+++ b/drivers/staging/fbtft/fb_ili9340.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <video/mipi_display.h>
diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c
index 32172f8f79f0..ad49973ad594 100644
--- a/drivers/staging/fbtft/fb_pcd8544.c
+++ b/drivers/staging/fbtft/fb_pcd8544.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -119,7 +119,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
/* Write data */
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
ret = par->fbtftops.write(par, par->txbuf.buf, 6 * 84);
if (ret < 0)
dev_err(par->info->device, "write failed and returned: %d\n",
diff --git a/drivers/staging/fbtft/fb_ra8875.c b/drivers/staging/fbtft/fb_ra8875.c
index 5d3b76ca74d8..70b37fc7fb66 100644
--- a/drivers/staging/fbtft/fb_ra8875.c
+++ b/drivers/staging/fbtft/fb_ra8875.c
@@ -9,7 +9,7 @@
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include "fbtft.h"
#define DRVNAME "fb_ra8875"
@@ -39,7 +39,7 @@ static int write_spi(struct fbtft_par *par, void *buf, size_t len)
static int init_display(struct fbtft_par *par)
{
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
"%s()\n", __func__);
diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c
index aa716f33420a..b3d0701880fe 100644
--- a/drivers/staging/fbtft/fb_s6d1121.c
+++ b/drivers/staging/fbtft/fb_s6d1121.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -29,8 +29,8 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
/* Initialization sequence from Lib_UTFT */
diff --git a/drivers/staging/fbtft/fb_sh1106.c b/drivers/staging/fbtft/fb_sh1106.c
index 00096f8d249a..6f7249493ea3 100644
--- a/drivers/staging/fbtft/fb_sh1106.c
+++ b/drivers/staging/fbtft/fb_sh1106.c
@@ -9,7 +9,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c
index c9b18b3ba4ab..bbf75f795234 100644
--- a/drivers/staging/fbtft/fb_ssd1289.c
+++ b/drivers/staging/fbtft/fb_ssd1289.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include "fbtft.h"
@@ -28,8 +28,8 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
write_reg(par, 0x00, 0x0001);
write_reg(par, 0x03, 0xA8A4);
diff --git a/drivers/staging/fbtft/fb_ssd1305.c b/drivers/staging/fbtft/fb_ssd1305.c
index 3515888d94c9..020fe48fed0b 100644
--- a/drivers/staging/fbtft/fb_ssd1305.c
+++ b/drivers/staging/fbtft/fb_ssd1305.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -168,7 +168,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
/* Write data */
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
ret = par->fbtftops.write(par, par->txbuf.buf,
par->info->var.xres * par->info->var.yres /
8);
diff --git a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c
index 50172ddd94ae..d7c5e2e0eee9 100644
--- a/drivers/staging/fbtft/fb_ssd1306.c
+++ b/drivers/staging/fbtft/fb_ssd1306.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -190,7 +190,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
/* Write data */
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
ret = par->fbtftops.write(par, par->txbuf.buf, xres * yres / 8);
if (ret < 0)
dev_err(par->info->device, "write failed and returned: %d\n",
diff --git a/drivers/staging/fbtft/fb_ssd1325.c b/drivers/staging/fbtft/fb_ssd1325.c
index f974f7fc4d79..8a3140d41d8b 100644
--- a/drivers/staging/fbtft/fb_ssd1325.c
+++ b/drivers/staging/fbtft/fb_ssd1325.c
@@ -6,7 +6,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -35,7 +35,7 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- gpio_set_value(par->gpio.cs, 0);
+ gpiod_set_value(par->gpio.cs, 0);
write_reg(par, 0xb3);
write_reg(par, 0xf0);
@@ -155,7 +155,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
}
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
/* Write data */
ret = par->fbtftops.write(par, par->txbuf.buf,
diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c
index 0b614c84822e..9f54fe28d511 100644
--- a/drivers/staging/fbtft/fb_ssd1331.c
+++ b/drivers/staging/fbtft/fb_ssd1331.c
@@ -2,7 +2,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -80,8 +80,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
va_start(args, len);
*buf = (u8)va_arg(args, unsigned int);
- if (par->gpio.dc != -1)
- gpio_set_value(par->gpio.dc, 0);
+ if (!par->gpio.dc)
+ gpiod_set_value(par->gpio.dc, 0);
ret = par->fbtftops.write(par, par->buf, sizeof(u8));
if (ret < 0) {
va_end(args);
@@ -103,8 +103,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
return;
}
}
- if (par->gpio.dc != -1)
- gpio_set_value(par->gpio.dc, 1);
+ if (!par->gpio.dc)
+ gpiod_set_value(par->gpio.dc, 1);
va_end(args);
}
diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c
index 3da091b4d297..9ac78ce30619 100644
--- a/drivers/staging/fbtft/fb_ssd1351.c
+++ b/drivers/staging/fbtft/fb_ssd1351.c
@@ -2,7 +2,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -164,7 +164,7 @@ static int set_gamma(struct fbtft_par *par, u32 *curves)
static int blank(struct fbtft_par *par, bool on)
{
fbtft_par_dbg(DEBUG_BLANK, par, "(%s=%s)\n",
- __func__, on ? "true" : "false");
+ __func__, on ? "true" : "false");
if (on)
write_reg(par, 0xAE);
else
diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c
index e463b0ddf16d..9469248f2c50 100644
--- a/drivers/staging/fbtft/fb_tinylcd.c
+++ b/drivers/staging/fbtft/fb_tinylcd.c
@@ -38,7 +38,7 @@ static int init_display(struct fbtft_par *par)
write_reg(par, 0xE5, 0x00);
write_reg(par, 0xF0, 0x36, 0xA5, 0x53);
write_reg(par, 0xE0, 0x00, 0x35, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x35, 0x33, 0x00, 0x00, 0x00);
+ 0x00, 0x35, 0x33, 0x00, 0x00, 0x00);
write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
udelay(250);
diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c
index 277b6ed9c725..bec6dd0ffb01 100644
--- a/drivers/staging/fbtft/fb_tls8204.c
+++ b/drivers/staging/fbtft/fb_tls8204.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -94,7 +94,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
/* The display is 102x68 but the LCD is 84x48.
* Set the write pointer at the start of each row.
*/
- gpio_set_value(par->gpio.dc, 0);
+ gpiod_set_value(par->gpio.dc, 0);
write_reg(par, 0x80 | 0);
write_reg(par, 0x40 | y);
@@ -109,7 +109,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
*buf++ = ch;
}
/* Write the row */
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
if (ret < 0) {
dev_err(par->info->device,
diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c
index dfaf8bc70f73..65681d0fe200 100644
--- a/drivers/staging/fbtft/fb_uc1611.c
+++ b/drivers/staging/fbtft/fb_uc1611.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -251,7 +251,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
}
break;
}
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
/* Write data */
ret = par->fbtftops.write(par, par->txbuf.buf, len / 2);
diff --git a/drivers/staging/fbtft/fb_uc1701.c b/drivers/staging/fbtft/fb_uc1701.c
index 0a3531d6eb39..e4ccc73868a7 100644
--- a/drivers/staging/fbtft/fb_uc1701.c
+++ b/drivers/staging/fbtft/fb_uc1701.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -136,9 +136,9 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
write_reg(par, LCD_PAGE_ADDRESS | (u8)y);
write_reg(par, 0x00);
write_reg(par, LCD_COL_ADDRESS);
- gpio_set_value(par->gpio.dc, 1);
+ gpiod_set_value(par->gpio.dc, 1);
ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
- gpio_set_value(par->gpio.dc, 0);
+ gpiod_set_value(par->gpio.dc, 0);
}
if (ret < 0)
diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c
index acc425fdf34e..564a38e34440 100644
--- a/drivers/staging/fbtft/fb_upd161704.c
+++ b/drivers/staging/fbtft/fb_upd161704.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -26,8 +26,8 @@ static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
/* Initialization sequence from Lib_UTFT */
diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c
index e77178157f1b..0a5206d28da4 100644
--- a/drivers/staging/fbtft/fb_watterott.c
+++ b/drivers/staging/fbtft/fb_watterott.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include "fbtft.h"
@@ -213,7 +213,7 @@ static int set_var(struct fbtft_par *par)
static int verify_gpios(struct fbtft_par *par)
{
- if (par->gpio.reset < 0) {
+ if (!par->gpio.reset) {
dev_err(par->info->device, "Missing 'reset' gpio. Aborting.\n");
return -EINVAL;
}
diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c
index 8ce1ff9b6c2a..2ea814d0dca5 100644
--- a/drivers/staging/fbtft/fbtft-bus.c
+++ b/drivers/staging/fbtft/fbtft-bus.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/export.h>
#include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include "fbtft.h"
@@ -135,8 +135,8 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
remain = len / 2;
vmem16 = (u16 *)(par->info->screen_buffer + offset);
- if (par->gpio.dc != -1)
- gpio_set_value(par->gpio.dc, 1);
+ if (!par->gpio.dc)
+ gpiod_set_value(par->gpio.dc, 1);
/* non buffered write */
if (!par->txbuf.buf)
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index a2df02d97a8e..9b07badf4c6c 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -16,7 +16,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
@@ -24,7 +24,6 @@
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <video/mipi_display.h>
#include "fbtft.h"
@@ -38,8 +37,8 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc)
{
int ret;
- if (gpio_is_valid(par->gpio.dc))
- gpio_set_value(par->gpio.dc, dc);
+ if (par->gpio.dc)
+ gpiod_set_value(par->gpio.dc, dc);
ret = par->fbtftops.write(par, buf, len);
if (ret < 0)
@@ -71,127 +70,26 @@ void fbtft_dbg_hex(const struct device *dev, int groupsize,
}
EXPORT_SYMBOL(fbtft_dbg_hex);
-static unsigned long fbtft_request_gpios_match(struct fbtft_par *par,
- const struct fbtft_gpio *gpio)
-{
- int ret;
- unsigned int val;
-
- fbtft_par_dbg(DEBUG_REQUEST_GPIOS_MATCH, par, "%s('%s')\n",
- __func__, gpio->name);
-
- if (strcasecmp(gpio->name, "reset") == 0) {
- par->gpio.reset = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
- } else if (strcasecmp(gpio->name, "dc") == 0) {
- par->gpio.dc = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
- } else if (strcasecmp(gpio->name, "cs") == 0) {
- par->gpio.cs = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
- } else if (strcasecmp(gpio->name, "wr") == 0) {
- par->gpio.wr = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
- } else if (strcasecmp(gpio->name, "rd") == 0) {
- par->gpio.rd = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
- } else if (strcasecmp(gpio->name, "latch") == 0) {
- par->gpio.latch = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
- } else if (gpio->name[0] == 'd' && gpio->name[1] == 'b') {
- ret = kstrtouint(&gpio->name[2], 10, &val);
- if (ret == 0 && val < 16) {
- par->gpio.db[val] = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
- }
- } else if (strcasecmp(gpio->name, "led") == 0) {
- par->gpio.led[0] = gpio->gpio;
- return GPIOF_OUT_INIT_LOW;
- } else if (strcasecmp(gpio->name, "led_") == 0) {
- par->gpio.led[0] = gpio->gpio;
- return GPIOF_OUT_INIT_HIGH;
- }
-
- return FBTFT_GPIO_NO_MATCH;
-}
-
-static int fbtft_request_gpios(struct fbtft_par *par)
-{
- struct fbtft_platform_data *pdata = par->pdata;
- const struct fbtft_gpio *gpio;
- unsigned long flags;
- int ret;
-
- if (!(pdata && pdata->gpios))
- return 0;
-
- gpio = pdata->gpios;
- while (gpio->name[0]) {
- flags = FBTFT_GPIO_NO_MATCH;
- /* if driver provides match function, try it first,
- * if no match use our own
- */
- if (par->fbtftops.request_gpios_match)
- flags = par->fbtftops.request_gpios_match(par, gpio);
- if (flags == FBTFT_GPIO_NO_MATCH)
- flags = fbtft_request_gpios_match(par, gpio);
- if (flags != FBTFT_GPIO_NO_MATCH) {
- ret = devm_gpio_request_one(par->info->device,
- gpio->gpio, flags,
- par->info->device->driver->name);
- if (ret < 0) {
- dev_err(par->info->device,
- "%s: gpio_request_one('%s'=%d) failed with %d\n",
- __func__, gpio->name,
- gpio->gpio, ret);
- return ret;
- }
- fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par,
- "%s: '%s' = GPIO%d\n",
- __func__, gpio->name, gpio->gpio);
- }
- gpio++;
- }
-
- return 0;
-}
-
#ifdef CONFIG_OF
static int fbtft_request_one_gpio(struct fbtft_par *par,
- const char *name, int index, int *gpiop)
+ const char *name, int index,
+ struct gpio_desc **gpiop)
{
struct device *dev = par->info->device;
struct device_node *node = dev->of_node;
- int gpio, flags, ret = 0;
- enum of_gpio_flags of_flags;
+ int ret = 0;
if (of_find_property(node, name, NULL)) {
- gpio = of_get_named_gpio_flags(node, name, index, &of_flags);
- if (gpio == -ENOENT)
- return 0;
- if (gpio == -EPROBE_DEFER)
- return gpio;
- if (gpio < 0) {
- dev_err(dev,
- "failed to get '%s' from DT\n", name);
- return gpio;
- }
-
- /* active low translates to initially low */
- flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW :
- GPIOF_OUT_INIT_HIGH;
- ret = devm_gpio_request_one(dev, gpio, flags,
- dev->driver->name);
- if (ret) {
+ *gpiop = devm_gpiod_get_index(dev, dev->driver->name, index,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(*gpiop)) {
+ ret = PTR_ERR(*gpiop);
dev_err(dev,
- "gpio_request_one('%s'=%d) failed with %d\n",
- name, gpio, ret);
+ "Failed to request %s GPIO:%d\n", name, ret);
return ret;
}
- if (gpiop)
- *gpiop = gpio;
- fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n",
- __func__, name, gpio);
+ fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
+ __func__, name);
}
return ret;
@@ -254,9 +152,9 @@ static int fbtft_backlight_update_status(struct backlight_device *bd)
if ((bd->props.power == FB_BLANK_UNBLANK) &&
(bd->props.fb_blank == FB_BLANK_UNBLANK))
- gpio_set_value(par->gpio.led[0], polarity);
+ gpiod_set_value(par->gpio.led[0], polarity);
else
- gpio_set_value(par->gpio.led[0], !polarity);
+ gpiod_set_value(par->gpio.led[0], !polarity);
return 0;
}
@@ -286,7 +184,7 @@ void fbtft_register_backlight(struct fbtft_par *par)
struct backlight_device *bd;
struct backlight_properties bl_props = { 0, };
- if (par->gpio.led[0] == -1) {
+ if (!par->gpio.led[0]) {
fbtft_par_dbg(DEBUG_BACKLIGHT, par,
"%s(): led pin not set, exiting.\n", __func__);
return;
@@ -295,7 +193,7 @@ void fbtft_register_backlight(struct fbtft_par *par)
bl_props.type = BACKLIGHT_RAW;
/* Assume backlight is off, get polarity from current state of pin */
bl_props.power = FB_BLANK_POWERDOWN;
- if (!gpio_get_value(par->gpio.led[0]))
+ if (!gpiod_get_value(par->gpio.led[0]))
par->polarity = true;
bd = backlight_device_register(dev_driver_string(par->info->device),
@@ -333,12 +231,12 @@ static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe,
static void fbtft_reset(struct fbtft_par *par)
{
- if (par->gpio.reset == -1)
+ if (!par->gpio.reset)
return;
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
- gpio_set_value_cansleep(par->gpio.reset, 0);
+ gpiod_set_value_cansleep(par->gpio.reset, 0);
usleep_range(20, 40);
- gpio_set_value_cansleep(par->gpio.reset, 1);
+ gpiod_set_value_cansleep(par->gpio.reset, 1);
msleep(120);
}
@@ -538,9 +436,9 @@ static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
return chan << bf->offset;
}
-static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
- unsigned int blue, unsigned int transp,
- struct fb_info *info)
+static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
{
unsigned int val;
int ret = 1;
@@ -663,7 +561,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
int txbuflen = display->txbuflen;
unsigned int bpp = display->bpp;
unsigned int fps = display->fps;
- int vmem_size, i;
+ int vmem_size;
const s16 *init_sequence = display->init_sequence;
char *gamma = display->gamma;
u32 *gamma_curves = NULL;
@@ -841,19 +739,6 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
par->txbuf.len = txbuflen;
}
- /* Initialize gpios to disabled */
- par->gpio.reset = -1;
- par->gpio.dc = -1;
- par->gpio.rd = -1;
- par->gpio.wr = -1;
- par->gpio.cs = -1;
- par->gpio.latch = -1;
- for (i = 0; i < 16; i++) {
- par->gpio.db[i] = -1;
- par->gpio.led[i] = -1;
- par->gpio.aux[i] = -1;
- }
-
/* default fbtft operations */
par->fbtftops.write = fbtft_write_spi;
par->fbtftops.read = fbtft_read_spi;
@@ -863,7 +748,6 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
par->fbtftops.reset = fbtft_reset;
par->fbtftops.mkdirty = fbtft_mkdirty;
par->fbtftops.update_display = fbtft_update_display;
- par->fbtftops.request_gpios = fbtft_request_gpios;
if (display->backlight)
par->fbtftops.register_backlight = fbtft_register_backlight;
@@ -1035,8 +919,8 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
return -EINVAL;
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
while (p) {
if (val & FBTFT_OF_INIT_CMD) {
@@ -1126,8 +1010,8 @@ int fbtft_init_display(struct fbtft_par *par)
}
par->fbtftops.reset(par);
- if (par->gpio.cs != -1)
- gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+ if (!par->gpio.cs)
+ gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
i = 0;
while (i < FBTFT_MAX_INIT_SEQUENCE) {
@@ -1227,7 +1111,7 @@ static int fbtft_verify_gpios(struct fbtft_par *par)
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
if (pdata->display.buswidth != 9 && par->startbyte == 0 &&
- par->gpio.dc < 0) {
+ !par->gpio.dc) {
dev_err(par->info->device,
"Missing info about 'dc' gpio. Aborting.\n");
return -EINVAL;
@@ -1236,12 +1120,12 @@ static int fbtft_verify_gpios(struct fbtft_par *par)
if (!par->pdev)
return 0;
- if (par->gpio.wr < 0) {
+ if (!par->gpio.wr) {
dev_err(par->info->device, "Missing 'wr' gpio. Aborting.\n");
return -EINVAL;
}
for (i = 0; i < pdata->display.buswidth; i++) {
- if (par->gpio.db[i] < 0) {
+ if (!par->gpio.db[i]) {
dev_err(par->info->device,
"Missing 'db%02d' gpio. Aborting.\n", i);
return -EINVAL;
diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c
index b5051d3d46a6..38cdad6203ea 100644
--- a/drivers/staging/fbtft/fbtft-io.c
+++ b/drivers/staging/fbtft/fbtft-io.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/export.h>
#include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include "fbtft.h"
@@ -142,30 +142,30 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
data = *(u8 *)buf;
/* Start writing by pulling down /WR */
- gpio_set_value(par->gpio.wr, 0);
+ gpiod_set_value(par->gpio.wr, 0);
/* Set data */
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
if (data == prev_data) {
- gpio_set_value(par->gpio.wr, 0); /* used as delay */
+ gpiod_set_value(par->gpio.wr, 0); /* used as delay */
} else {
for (i = 0; i < 8; i++) {
if ((data & 1) != (prev_data & 1))
- gpio_set_value(par->gpio.db[i],
- data & 1);
+ gpiod_set_value(par->gpio.db[i],
+ data & 1);
data >>= 1;
prev_data >>= 1;
}
}
#else
for (i = 0; i < 8; i++) {
- gpio_set_value(par->gpio.db[i], data & 1);
+ gpiod_set_value(par->gpio.db[i], data & 1);
data >>= 1;
}
#endif
/* Pullup /WR */
- gpio_set_value(par->gpio.wr, 1);
+ gpiod_set_value(par->gpio.wr, 1);
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
prev_data = *(u8 *)buf;
@@ -192,30 +192,30 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
data = *(u16 *)buf;
/* Start writing by pulling down /WR */
- gpio_set_value(par->gpio.wr, 0);
+ gpiod_set_value(par->gpio.wr, 0);
/* Set data */
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
if (data == prev_data) {
- gpio_set_value(par->gpio.wr, 0); /* used as delay */
+ gpiod_set_value(par->gpio.wr, 0); /* used as delay */
} else {
for (i = 0; i < 16; i++) {
if ((data & 1) != (prev_data & 1))
- gpio_set_value(par->gpio.db[i],
- data & 1);
+ gpiod_set_value(par->gpio.db[i],
+ data & 1);
data >>= 1;
prev_data >>= 1;
}
}
#else
for (i = 0; i < 16; i++) {
- gpio_set_value(par->gpio.db[i], data & 1);
+ gpiod_set_value(par->gpio.db[i], data & 1);
data >>= 1;
}
#endif
/* Pullup /WR */
- gpio_set_value(par->gpio.wr, 1);
+ gpiod_set_value(par->gpio.wr, 1);
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
prev_data = *(u16 *)buf;
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index ac427baa464a..7fdd3b0851ef 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -27,7 +27,7 @@
*/
struct fbtft_gpio {
char name[FBTFT_GPIO_NAME_SIZE];
- unsigned int gpio;
+ struct gpio_desc *gpio;
};
struct fbtft_par;
@@ -134,7 +134,6 @@ struct fbtft_display {
*/
struct fbtft_platform_data {
struct fbtft_display display;
- const struct fbtft_gpio *gpios;
unsigned int rotate;
bool bgr;
unsigned int fps;
@@ -207,15 +206,15 @@ struct fbtft_par {
unsigned int dirty_lines_start;
unsigned int dirty_lines_end;
struct {
- int reset;
- int dc;
- int rd;
- int wr;
- int latch;
- int cs;
- int db[16];
- int led[16];
- int aux[16];
+ struct gpio_desc *reset;
+ struct gpio_desc *dc;
+ struct gpio_desc *rd;
+ struct gpio_desc *wr;
+ struct gpio_desc *latch;
+ struct gpio_desc *cs;
+ struct gpio_desc *db[16];
+ struct gpio_desc *led[16];
+ struct gpio_desc *aux[16];
} gpio;
const s16 *init_sequence;
struct {
diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c
index 046f9d355ecb..5f6cd0816d58 100644
--- a/drivers/staging/fbtft/fbtft_device.c
+++ b/drivers/staging/fbtft/fbtft_device.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <video/mipi_display.h>
@@ -45,11 +45,6 @@ static int mode = -1;
module_param(mode, int, 0000);
MODULE_PARM_DESC(mode, "SPI mode (override device default)");
-static char *gpios;
-module_param(gpios, charp, 0000);
-MODULE_PARM_DESC(gpios,
- "List of gpios. Comma separated with the form: reset:23,dc:24 (when overriding the default, all gpios must be specified)");
-
static unsigned int fps;
module_param(fps, uint, 0000);
MODULE_PARM_DESC(fps, "Frames per second (override driver default)");
@@ -101,7 +96,7 @@ MODULE_PARM_DESC(debug,
static unsigned int verbose = 3;
module_param(verbose, uint, 0000);
MODULE_PARM_DESC(verbose,
- "0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)");
+ "0 silent, >1 show devices, >2 show devices before (default=3)");
struct fbtft_device_display {
char *name;
@@ -279,12 +274,6 @@ static struct fbtft_device_display displays[] = {
.buswidth = 8,
.backlight = 1,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
.gamma = ADAFRUIT18_GAMMA,
}
}
@@ -302,12 +291,6 @@ static struct fbtft_device_display displays[] = {
adafruit18_green_tab_set_addr_win,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
.gamma = ADAFRUIT18_GAMMA,
}
}
@@ -323,11 +306,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "led", 23 },
- {},
- },
}
}
}, {
@@ -342,12 +320,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -362,12 +334,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -380,11 +346,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -399,12 +360,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
.init_sequence = cberry28_init_sequence,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 22 },
- { "led", 18 },
- {},
- },
.gamma = CBERRY28_GAMMA,
}
}
@@ -420,9 +375,6 @@ static struct fbtft_device_display displays[] = {
.buswidth = 8,
.backlight = FBTFT_ONBOARD_BACKLIGHT,
},
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
}
}
@@ -437,11 +389,6 @@ static struct fbtft_device_display displays[] = {
.buswidth = 8,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 13 },
- { "dc", 6 },
- {},
- },
}
}
}, {
@@ -458,11 +405,6 @@ static struct fbtft_device_display displays[] = {
.height = 272,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -479,11 +421,6 @@ static struct fbtft_device_display displays[] = {
.height = 480,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -496,10 +433,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -512,9 +445,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 9,
},
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
}
}
}, {
@@ -523,13 +453,6 @@ static struct fbtft_device_display displays[] = {
.modalias = "flexfb",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
- .platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
- }
}
}, {
.name = "flexpfb",
@@ -538,24 +461,6 @@ static struct fbtft_device_display displays[] = {
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
- .platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 17 },
- { "dc", 1 },
- { "wr", 0 },
- { "cs", 21 },
- { "db00", 9 },
- { "db01", 11 },
- { "db02", 18 },
- { "db03", 23 },
- { "db04", 24 },
- { "db05", 25 },
- { "db06", 8 },
- { "db07", 7 },
- { "led", 4 },
- {},
- },
- },
}
}
}, {
@@ -570,11 +475,6 @@ static struct fbtft_device_display displays[] = {
.backlight = FBTFT_ONBOARD_BACKLIGHT,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 24 },
- { "dc", 25 },
- {},
- },
}
}
}, {
@@ -588,12 +488,6 @@ static struct fbtft_device_display displays[] = {
.buswidth = 8,
.backlight = 1,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 23 },
- {},
- },
}
}
}, {
@@ -609,11 +503,6 @@ static struct fbtft_device_display displays[] = {
},
.startbyte = 0x70,
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -631,11 +520,6 @@ static struct fbtft_device_display displays[] = {
.startbyte = 0x70,
.bgr = true,
.fps = 50,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "led", 18 },
- {},
- },
.gamma = HY28B_GAMMA,
}
}
@@ -652,12 +536,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 22 },
- {},
- },
}
}
}, {
@@ -673,22 +551,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = false,
- .gpios = (const struct fbtft_gpio []) {
- /* Wiring for LCD adapter kit */
- { "reset", 7 },
- { "dc", 0 }, /* rev 2: 2 */
- { "wr", 1 }, /* rev 2: 3 */
- { "cs", 8 },
- { "db00", 17 },
- { "db01", 18 },
- { "db02", 21 }, /* rev 2: 27 */
- { "db03", 22 },
- { "db04", 23 },
- { "db05", 24 },
- { "db06", 25 },
- { "db07", 4 },
- {}
- },
},
}
}
@@ -705,9 +567,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
}
}
@@ -723,11 +582,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -743,12 +597,6 @@ static struct fbtft_device_display displays[] = {
},
.startbyte = 0x70,
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -763,11 +611,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -777,10 +620,6 @@ static struct fbtft_device_display displays[] = {
.max_speed_hz = 4000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- {},
- },
}
}
}, {
@@ -793,12 +632,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 23 },
- {},
- },
}
}
}, {
@@ -811,12 +644,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 23 },
- {},
- },
}
}
}, {
@@ -831,9 +658,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
}
}
}, {
@@ -849,12 +673,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 22 },
- {},
- },
}
}
}, {
@@ -871,10 +689,6 @@ static struct fbtft_device_display displays[] = {
.init_sequence = pitft_init_sequence,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "dc", 25 },
- {},
- },
}
}
}, {
@@ -888,11 +702,6 @@ static struct fbtft_device_display displays[] = {
.buswidth = 8,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 24 },
- { "dc", 25 },
- {},
- },
.gamma = PIOLED_GAMMA
}
}
@@ -908,12 +717,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 23 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -928,12 +731,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 23 },
- {},
- },
}
}
}, {
@@ -946,11 +743,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -968,9 +760,6 @@ static struct fbtft_device_display displays[] = {
.fbtftops.write = write_gpio16_wr_slow,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
},
}
@@ -988,9 +777,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
},
}
@@ -1010,9 +796,6 @@ static struct fbtft_device_display displays[] = {
fbtft_write_gpio16_wr_latched,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
},
}
@@ -1028,11 +811,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- {},
- },
}
}
}, {
@@ -1044,9 +822,6 @@ static struct fbtft_device_display displays[] = {
.chip_select = 0,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
}
}
}, {
@@ -1059,11 +834,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 24 },
- { "dc", 25 },
- {},
- },
}
}
}, {
@@ -1078,12 +848,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -1098,12 +862,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 25 },
- { "dc", 24 },
- { "led", 18 },
- {},
- },
}
}
}, {
@@ -1118,12 +876,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 15 },
- { "dc", 25 },
- { "led_", 18 },
- {},
- },
}
}
}, {
@@ -1138,12 +890,6 @@ static struct fbtft_device_display displays[] = {
.backlight = 1,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 15 },
- { "dc", 25 },
- { "led_", 18 },
- {},
- },
}
}
}, {
@@ -1156,11 +902,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 24 },
- { "dc", 25 },
- {},
- },
}
}
}, {
@@ -1177,11 +918,6 @@ static struct fbtft_device_display displays[] = {
waveshare32b_init_sequence,
},
.bgr = true,
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 27 },
- { "dc", 22 },
- {},
- },
}
}
}, {
@@ -1194,11 +930,6 @@ static struct fbtft_device_display displays[] = {
.display = {
.buswidth = 8,
},
- .gpios = (const struct fbtft_gpio []) {
- { "reset", 24 },
- { "dc", 25 },
- {},
- },
}
}
}, {
@@ -1211,9 +942,6 @@ static struct fbtft_device_display displays[] = {
.max_speed_hz = 0,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
}
},
.pdev = &(struct platform_device) {
@@ -1222,9 +950,6 @@ static struct fbtft_device_display displays[] = {
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
- .gpios = (const struct fbtft_gpio []) {
- {},
- },
},
},
},
@@ -1246,30 +971,30 @@ static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len)
data = *(u16 *)buf;
/* Start writing by pulling down /WR */
- gpio_set_value(par->gpio.wr, 0);
+ gpiod_set_value(par->gpio.wr, 0);
/* Set data */
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
if (data == prev_data) {
- gpio_set_value(par->gpio.wr, 0); /* used as delay */
+ gpiod_set_value(par->gpio.wr, 0); /* used as delay */
} else {
for (i = 0; i < 16; i++) {
if ((data & 1) != (prev_data & 1))
- gpio_set_value(par->gpio.db[i],
- data & 1);
+ gpiod_set_value(par->gpio.db[i],
+ data & 1);
data >>= 1;
prev_data >>= 1;
}
}
#else
for (i = 0; i < 16; i++) {
- gpio_set_value(par->gpio.db[i], data & 1);
+ gpiod_set_value(par->gpio.db[i], data & 1);
data >>= 1;
}
#endif
/* Pullup /WR */
- gpio_set_value(par->gpio.wr, 1);
+ gpiod_set_value(par->gpio.wr, 1);
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
prev_data = *(u16 *)buf;
@@ -1289,9 +1014,6 @@ static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
write_reg(par, 0x2C);
}
-/* used if gpios parameter is present */
-static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { };
-
static void fbtft_device_pdev_release(struct device *dev)
{
/* Needed to silence this message:
@@ -1382,11 +1104,8 @@ static int __init fbtft_device_init(void)
{
struct spi_board_info *spi = NULL;
struct fbtft_platform_data *pdata;
- const struct fbtft_gpio *gpio = NULL;
- char *p_gpio, *p_name, *p_num;
bool found = false;
int i = 0;
- long val;
int ret = 0;
if (!name) {
@@ -1404,38 +1123,6 @@ static int __init fbtft_device_init(void)
return -EINVAL;
}
- /* parse module parameter: gpios */
- while ((p_gpio = strsep(&gpios, ","))) {
- if (!strchr(p_gpio, ':')) {
- pr_err("error: missing ':' in gpios parameter: %s\n",
- p_gpio);
- return -EINVAL;
- }
- p_num = p_gpio;
- p_name = strsep(&p_num, ":");
- if (!p_name || !p_num) {
- pr_err("something bad happened parsing gpios parameter: %s\n",
- p_gpio);
- return -EINVAL;
- }
- ret = kstrtol(p_num, 10, &val);
- if (ret) {
- pr_err("could not parse number in gpios parameter: %s:%s\n",
- p_name, p_num);
- return -EINVAL;
- }
- strncpy(fbtft_device_param_gpios[i].name, p_name,
- FBTFT_GPIO_NAME_SIZE - 1);
- fbtft_device_param_gpios[i++].gpio = (int)val;
- if (i == MAX_GPIOS) {
- pr_err("gpios parameter: exceeded max array size: %d\n",
- MAX_GPIOS);
- return -EINVAL;
- }
- }
- if (fbtft_device_param_gpios[0].name[0])
- gpio = fbtft_device_param_gpios;
-
if (verbose > 2) {
pr_spi_devices(); /* print list of registered SPI devices */
pr_p_devices(); /* print list of 'fb' platform devices */
@@ -1516,8 +1203,6 @@ static int __init fbtft_device_init(void)
pdata->txbuflen = txbuflen;
if (init_num)
pdata->display.init_sequence = init;
- if (gpio)
- pdata->gpios = gpio;
if (custom) {
pdata->display.width = width;
pdata->display.height = height;
@@ -1549,19 +1234,6 @@ static int __init fbtft_device_init(void)
return -EINVAL;
}
- if (verbose && pdata && pdata->gpios) {
- gpio = pdata->gpios;
- pr_info("GPIOS used by '%s':\n", name);
- found = false;
- while (verbose && gpio->name[0]) {
- pr_info("'%s' = GPIO%d\n", gpio->name, gpio->gpio);
- gpio++;
- found = true;
- }
- if (!found)
- pr_info("(none)\n");
- }
-
if (spi_device && (verbose > 1))
pr_spi_devices();
if (p_device && (verbose > 1))
diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c
index 2af474469e7d..c5fa59105a43 100644
--- a/drivers/staging/fbtft/flexfb.c
+++ b/drivers/staging/fbtft/flexfb.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
@@ -521,7 +521,7 @@ static int flexfb_verify_gpios_dc(struct fbtft_par *par)
{
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
- if (par->gpio.dc < 0) {
+ if (!par->gpio.dc) {
dev_err(par->info->device,
"Missing info about 'dc' gpio. Aborting.\n");
return -EINVAL;
@@ -537,22 +537,22 @@ static int flexfb_verify_gpios_db(struct fbtft_par *par)
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
- if (par->gpio.dc < 0) {
+ if (!par->gpio.dc) {
dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n");
return -EINVAL;
}
- if (par->gpio.wr < 0) {
+ if (!par->gpio.wr) {
dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n");
return -EINVAL;
}
- if (latched && (par->gpio.latch < 0)) {
+ if (latched && !par->gpio.latch) {
dev_err(par->info->device, "Missing info about 'latch' gpio. Aborting.\n");
return -EINVAL;
}
if (latched)
num_db = buswidth / 2;
for (i = 0; i < num_db; i++) {
- if (par->gpio.db[i] < 0) {
+ if (!par->gpio.db[i]) {
dev_err(par->info->device,
"Missing info about 'db%02d' gpio. Aborting.\n",
i);
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
index da744f2b0ee6..14b974defa3a 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2014-2016 Freescale Semiconductor Inc.
* Copyright 2017-2018 NXP
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
index db43fa3782b8..25635259ce44 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2014-2016 Freescale Semiconductor Inc.
* Copyright 2017-2018 NXP
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index daabaceeea52..ad577beeb052 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -505,6 +505,17 @@ static netdev_tx_t port_dropframe(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static int swdev_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct ethsw_port_priv *port_priv = netdev_priv(dev);
+
+ ppid->id_len = 1;
+ ppid->id[0] = port_priv->ethsw_data->dev_id;
+
+ return 0;
+}
+
static const struct net_device_ops ethsw_port_ops = {
.ndo_open = port_open,
.ndo_stop = port_stop,
@@ -515,6 +526,7 @@ static const struct net_device_ops ethsw_port_ops = {
.ndo_get_offload_stats = port_get_offload_stats,
.ndo_start_xmit = port_dropframe,
+ .ndo_get_port_parent_id = swdev_get_port_parent_id,
};
static void ethsw_links_state_update(struct ethsw_core *ethsw)
@@ -628,31 +640,6 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
fsl_mc_free_irqs(sw_dev);
}
-static int swdev_port_attr_get(struct net_device *netdev,
- struct switchdev_attr *attr)
-{
- struct ethsw_port_priv *port_priv = netdev_priv(netdev);
-
- switch (attr->id) {
- case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
- attr->u.ppid.id_len = 1;
- attr->u.ppid.id[0] = port_priv->ethsw_data->dev_id;
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
- attr->u.brport_flags =
- (port_priv->ethsw_data->learning ? BR_LEARNING : 0) |
- (port_priv->flood ? BR_FLOOD : 0);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
- attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
static int port_attr_stp_state_set(struct net_device *netdev,
struct switchdev_trans *trans,
u8 state)
@@ -665,6 +652,16 @@ static int port_attr_stp_state_set(struct net_device *netdev,
return ethsw_port_set_stp_state(port_priv, state);
}
+static int port_attr_br_flags_pre_set(struct net_device *netdev,
+ struct switchdev_trans *trans,
+ unsigned long flags)
+{
+ if (flags & ~(BR_LEARNING | BR_FLOOD))
+ return -EINVAL;
+
+ return 0;
+}
+
static int port_attr_br_flags_set(struct net_device *netdev,
struct switchdev_trans *trans,
unsigned long flags)
@@ -697,6 +694,10 @@ static int swdev_port_attr_set(struct net_device *netdev,
err = port_attr_stp_state_set(netdev, trans,
attr->u.stp_state);
break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ err = port_attr_br_flags_pre_set(netdev, trans,
+ attr->u.brport_flags);
+ break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = port_attr_br_flags_set(netdev, trans,
attr->u.brport_flags);
@@ -924,10 +925,18 @@ static int swdev_port_obj_del(struct net_device *netdev,
return err;
}
-static const struct switchdev_ops ethsw_port_switchdev_ops = {
- .switchdev_port_attr_get = swdev_port_attr_get,
- .switchdev_port_attr_set = swdev_port_attr_set,
-};
+static int
+ethsw_switchdev_port_attr_set_event(struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err;
+
+ err = swdev_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
/* For the moment, only flood setting needs to be updated */
static int port_bridge_join(struct net_device *netdev,
@@ -1047,6 +1056,12 @@ static int port_switchdev_event(struct notifier_block *unused,
struct ethsw_switchdev_event_work *switchdev_work;
struct switchdev_notifier_fdb_info *fdb_info = ptr;
+ if (!ethsw_port_dev_check(dev))
+ return NOTIFY_DONE;
+
+ if (event == SWITCHDEV_PORT_ATTR_SET)
+ return ethsw_switchdev_port_attr_set_event(dev, ptr);
+
switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
if (!switchdev_work)
return NOTIFY_BAD;
@@ -1115,6 +1130,8 @@ static int port_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
case SWITCHDEV_PORT_OBJ_DEL:
return ethsw_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET:
+ return ethsw_switchdev_port_attr_set_event(dev, ptr);
}
return NOTIFY_DONE;
@@ -1434,7 +1451,6 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx)
SET_NETDEV_DEV(port_netdev, dev);
port_netdev->netdev_ops = &ethsw_port_ops;
port_netdev->ethtool_ops = &ethsw_port_ethtool_ops;
- port_netdev->switchdev_ops = &ethsw_port_switchdev_ops;
/* Set MTU limits */
port_netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h
index 069c99bfba74..c48783680a05 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* DPAA2 Ethernet Switch declarations
*
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 3e416f5bbcba..a1b90ea7fcb8 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -1213,6 +1213,7 @@ static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct fwtty_port *port = tty->driver_data;
+
mutex_lock(&port->port.mutex);
ss->type = PORT_UNKNOWN;
ss->line = port->port.tty->index;
diff --git a/drivers/staging/gasket/gasket_interrupt.c b/drivers/staging/gasket/gasket_interrupt.c
index ad5657d213f0..ff61b782df30 100644
--- a/drivers/staging/gasket/gasket_interrupt.c
+++ b/drivers/staging/gasket/gasket_interrupt.c
@@ -9,7 +9,6 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/printk.h>
-#include <linux/version.h>
#ifdef GASKET_KERNEL_TRACE_SUPPORT
#define CREATE_TRACE_POINTS
#include <trace/events/gasket_interrupt.h>
diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c
index d4520490cf6d..24a738238f9f 100644
--- a/drivers/staging/goldfish/goldfish_audio.c
+++ b/drivers/staging/goldfish/goldfish_audio.c
@@ -4,16 +4,6 @@
*
* Copyright (C) 2007 Google, Inc.
* Copyright (C) 2012 Intel, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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>
diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig
index ab096bcef98c..b571e4e8060b 100644
--- a/drivers/staging/greybus/Kconfig
+++ b/drivers/staging/greybus/Kconfig
@@ -148,6 +148,7 @@ if GREYBUS_BRIDGED_PHY
config GREYBUS_GPIO
tristate "Greybus GPIO Bridged PHY driver"
depends on GPIOLIB
+ select GPIOLIB_IRQCHIP
---help---
Select this option if you have a device that follows the
Greybus GPIO Bridged PHY Class specification.
diff --git a/drivers/staging/greybus/TODO b/drivers/staging/greybus/TODO
index 3b90a5711998..31f1f2cb401c 100644
--- a/drivers/staging/greybus/TODO
+++ b/drivers/staging/greybus/TODO
@@ -1,5 +1,3 @@
* Convert all uses of the old GPIO API from <linux/gpio.h> to the
GPIO descriptor API in <linux/gpio/consumer.h> and look up GPIO
lines from device tree or ACPI.
-* Convert the GPIO driver to use the GPIO irqchip library
- GPIOLIB_IRQCHIP instead of reimplementing the same.
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index be5ffed90bcf..bbf3ba744fc4 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -8,9 +8,8 @@
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
-#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
@@ -24,12 +23,12 @@ 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;
- int boot_ret_gpio;
- int pwroff_gpio;
- int wake_in_gpio;
- int wake_out_gpio;
- int pwrdn_gpio;
+ struct gpio_desc *resetn;
+ struct gpio_desc *boot_ret;
+ struct gpio_desc *pwroff;
+ struct gpio_desc *wake_in;
+ struct gpio_desc *wake_out;
+ struct gpio_desc *pwrdn;
enum arche_platform_state state;
bool init_disabled;
@@ -37,28 +36,28 @@ struct arche_apb_ctrl_drvdata {
struct regulator *vcore;
struct regulator *vio;
- int clk_en_gpio;
+ struct gpio_desc *clk_en;
struct clk *clk;
struct pinctrl *pinctrl;
struct pinctrl_state *pin_default;
/* V2: SPI Bus control */
- int spi_en_gpio;
+ struct gpio_desc *spi_en;
bool spi_en_polarity_high;
};
/*
* Note that these low level api's are active high
*/
-static inline void deassert_reset(unsigned int gpio)
+static inline void deassert_reset(struct gpio_desc *gpio)
{
- gpio_set_value(gpio, 1);
+ gpiod_set_raw_value(gpio, 1);
}
-static inline void assert_reset(unsigned int gpio)
+static inline void assert_reset(struct gpio_desc *gpio)
{
- gpio_set_value(gpio, 0);
+ gpiod_set_raw_value(gpio, 0);
}
/*
@@ -75,11 +74,10 @@ static int coldboot_seq(struct platform_device *pdev)
return 0;
/* Hold APB in reset state */
- assert_reset(apb->resetn_gpio);
+ assert_reset(apb->resetn);
- if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
- gpio_is_valid(apb->spi_en_gpio))
- devm_gpio_free(dev, apb->spi_en_gpio);
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
+ devm_gpiod_put(dev, apb->spi_en);
/* Enable power to APB */
if (!IS_ERR(apb->vcore)) {
@@ -101,13 +99,13 @@ static int coldboot_seq(struct platform_device *pdev)
apb_bootret_deassert(dev);
/* On DB3 clock was not mandatory */
- if (gpio_is_valid(apb->clk_en_gpio))
- gpio_set_value(apb->clk_en_gpio, 1);
+ if (apb->clk_en)
+ gpiod_set_value(apb->clk_en, 1);
usleep_range(100, 200);
/* deassert reset to APB : Active-low signal */
- deassert_reset(apb->resetn_gpio);
+ deassert_reset(apb->resetn);
apb->state = ARCHE_PLATFORM_STATE_ACTIVE;
@@ -136,25 +134,25 @@ static int fw_flashing_seq(struct platform_device *pdev)
return ret;
}
- if (gpio_is_valid(apb->spi_en_gpio)) {
+ if (apb->spi_en) {
unsigned long flags;
if (apb->spi_en_polarity_high)
- flags = GPIOF_OUT_INIT_HIGH;
+ flags = GPIOD_OUT_HIGH;
else
- flags = GPIOF_OUT_INIT_LOW;
+ flags = GPIOD_OUT_LOW;
- ret = devm_gpio_request_one(dev, apb->spi_en_gpio,
- flags, "apb_spi_en");
- if (ret) {
- dev_err(dev, "Failed requesting SPI bus en gpio %d\n",
- apb->spi_en_gpio);
+ apb->spi_en = devm_gpiod_get(dev, "spi-en", flags);
+ if (IS_ERR(apb->spi_en)) {
+ ret = PTR_ERR(apb->spi_en);
+ dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n",
+ ret);
return ret;
}
}
/* for flashing device should be in reset state */
- assert_reset(apb->resetn_gpio);
+ assert_reset(apb->resetn);
apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
return 0;
@@ -176,9 +174,8 @@ static int standby_boot_seq(struct platform_device *pdev)
apb->state == ARCHE_PLATFORM_STATE_OFF)
return 0;
- if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
- gpio_is_valid(apb->spi_en_gpio))
- devm_gpio_free(dev, apb->spi_en_gpio);
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
+ devm_gpiod_put(dev, apb->spi_en);
/*
* As per WDM spec, do nothing
@@ -201,13 +198,12 @@ static void poweroff_seq(struct platform_device *pdev)
if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF)
return;
- if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
- gpio_is_valid(apb->spi_en_gpio))
- devm_gpio_free(dev, apb->spi_en_gpio);
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
+ devm_gpiod_put(dev, apb->spi_en);
/* disable the clock */
- if (gpio_is_valid(apb->clk_en_gpio))
- gpio_set_value(apb->clk_en_gpio, 0);
+ if (apb->clk_en)
+ gpiod_set_value(apb->clk_en, 0);
if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0)
regulator_disable(apb->vcore);
@@ -216,7 +212,7 @@ static void poweroff_seq(struct platform_device *pdev)
regulator_disable(apb->vio);
/* As part of exit, put APB back in reset state */
- assert_reset(apb->resetn_gpio);
+ assert_reset(apb->resetn);
apb->state = ARCHE_PLATFORM_STATE_OFF;
/* TODO: May have to send an event to SVC about this exit */
@@ -226,7 +222,7 @@ static void apb_bootret_deassert(struct device *dev)
{
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
- gpio_set_value(apb->boot_ret_gpio, 0);
+ gpiod_set_value(apb->boot_ret, 0);
}
int apb_ctrl_coldboot(struct device *dev)
@@ -322,66 +318,44 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
struct arche_apb_ctrl_drvdata *apb)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
int ret;
- apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
- if (apb->resetn_gpio < 0) {
- dev_err(dev, "failed to get reset gpio\n");
- return apb->resetn_gpio;
- }
- ret = devm_gpio_request_one(dev, apb->resetn_gpio,
- GPIOF_OUT_INIT_LOW, "apb-reset");
- if (ret) {
- dev_err(dev, "Failed requesting reset gpio %d\n",
- apb->resetn_gpio);
+ apb->resetn = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(apb->resetn)) {
+ ret = PTR_ERR(apb->resetn);
+ dev_err(dev, "Failed requesting reset GPIO: %d\n", ret);
return ret;
}
- apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0);
- if (apb->boot_ret_gpio < 0) {
- dev_err(dev, "failed to get boot retention gpio\n");
- return apb->boot_ret_gpio;
- }
- ret = devm_gpio_request_one(dev, apb->boot_ret_gpio,
- GPIOF_OUT_INIT_LOW, "boot retention");
- if (ret) {
- dev_err(dev, "Failed requesting bootret gpio %d\n",
- apb->boot_ret_gpio);
+ apb->boot_ret = devm_gpiod_get(dev, "boot-ret", GPIOD_OUT_LOW);
+ if (IS_ERR(apb->boot_ret)) {
+ ret = PTR_ERR(apb->boot_ret);
+ dev_err(dev, "Failed requesting bootret GPIO: %d\n", ret);
return ret;
}
/* It's not mandatory to support power management interface */
- apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0);
- if (apb->pwroff_gpio < 0) {
- dev_err(dev, "failed to get power off gpio\n");
- return apb->pwroff_gpio;
- }
- ret = devm_gpio_request_one(dev, apb->pwroff_gpio,
- GPIOF_IN, "pwroff_n");
- if (ret) {
- dev_err(dev, "Failed requesting pwroff_n gpio %d\n",
- apb->pwroff_gpio);
+ apb->pwroff = devm_gpiod_get_optional(dev, "pwr-off", GPIOD_IN);
+ if (IS_ERR(apb->pwroff)) {
+ ret = PTR_ERR(apb->pwroff);
+ dev_err(dev, "Failed requesting pwroff_n GPIO: %d\n", ret);
return ret;
}
/* Do not make clock mandatory as of now (for DB3) */
- apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0);
- if (apb->clk_en_gpio < 0) {
- dev_warn(dev, "failed to get clock en gpio\n");
- } else if (gpio_is_valid(apb->clk_en_gpio)) {
- ret = devm_gpio_request_one(dev, apb->clk_en_gpio,
- GPIOF_OUT_INIT_LOW, "apb_clk_en");
- if (ret) {
- dev_warn(dev, "Failed requesting APB clock en gpio %d\n",
- apb->clk_en_gpio);
- return ret;
- }
+ apb->clk_en = devm_gpiod_get_optional(dev, "clock-en", GPIOD_OUT_LOW);
+ if (IS_ERR(apb->clk_en)) {
+ ret = PTR_ERR(apb->clk_en);
+ dev_err(dev, "Failed requesting APB clock en GPIO: %d\n", ret);
+ return ret;
}
- apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0);
- if (apb->pwrdn_gpio < 0)
- dev_warn(dev, "failed to get power down gpio\n");
+ apb->pwrdn = devm_gpiod_get(dev, "pwr-down", GPIOD_OUT_LOW);
+ if (IS_ERR(apb->pwrdn)) {
+ ret = PTR_ERR(apb->pwrdn);
+ dev_warn(dev, "Failed requesting power down GPIO: %d\n", ret);
+ return ret;
+ }
/* Regulators are optional, as we may have fixed supply coming in */
apb->vcore = devm_regulator_get(dev, "vcore");
@@ -404,12 +378,8 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
}
/* Only applicable for platform >= V2 */
- apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0);
- if (apb->spi_en_gpio >= 0) {
- if (of_property_read_bool(pdev->dev.of_node,
- "spi-en-active-high"))
- apb->spi_en_polarity_high = true;
- }
+ if (of_property_read_bool(pdev->dev.of_node, "gb,spi-en-active-high"))
+ apb->spi_en_polarity_high = true;
return 0;
}
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index 4c36e88766e7..6eb842040c22 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -8,10 +8,9 @@
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@@ -45,14 +44,14 @@ enum svc_wakedetect_state {
struct arche_platform_drvdata {
/* Control GPIO signals to and from AP <=> SVC */
- int svc_reset_gpio;
+ struct gpio_desc *svc_reset;
bool is_reset_act_hi;
- int svc_sysboot_gpio;
- int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
+ struct gpio_desc *svc_sysboot;
+ struct gpio_desc *wake_detect; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
enum arche_platform_state state;
- int svc_refclk_req;
+ struct gpio_desc *svc_refclk_req;
struct clk *svc_ref_clk;
struct pinctrl *pinctrl;
@@ -85,9 +84,9 @@ static void arche_platform_set_wake_detect_state(
arche_pdata->wake_detect_state = state;
}
-static inline void svc_reset_onoff(unsigned int gpio, bool onoff)
+static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
{
- gpio_set_value(gpio, onoff);
+ gpiod_set_raw_value(gpio, onoff);
}
static int apb_cold_boot(struct device *dev, void *data)
@@ -116,7 +115,6 @@ static int apb_poweroff(struct device *dev, void *data)
static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata)
{
/* Enable interrupt here, to read event back from SVC */
- gpio_direction_input(arche_pdata->wake_detect_gpio);
enable_irq(arche_pdata->wake_detect_irq);
}
@@ -160,7 +158,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid)
spin_lock_irqsave(&arche_pdata->wake_lock, flags);
- if (gpio_get_value(arche_pdata->wake_detect_gpio)) {
+ if (gpiod_get_value(arche_pdata->wake_detect)) {
/* wake/detect rising */
/*
@@ -224,10 +222,9 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata)
dev_info(arche_pdata->dev, "Booting from cold boot state\n");
- svc_reset_onoff(arche_pdata->svc_reset_gpio,
- arche_pdata->is_reset_act_hi);
+ svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
- gpio_set_value(arche_pdata->svc_sysboot_gpio, 0);
+ gpiod_set_value(arche_pdata->svc_sysboot, 0);
usleep_range(100, 200);
ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
@@ -238,8 +235,7 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata)
}
/* bring SVC out of reset */
- svc_reset_onoff(arche_pdata->svc_reset_gpio,
- !arche_pdata->is_reset_act_hi);
+ svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi);
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE);
@@ -259,10 +255,9 @@ arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata)
dev_info(arche_pdata->dev, "Switching to FW flashing state\n");
- svc_reset_onoff(arche_pdata->svc_reset_gpio,
- arche_pdata->is_reset_act_hi);
+ svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
- gpio_set_value(arche_pdata->svc_sysboot_gpio, 1);
+ gpiod_set_value(arche_pdata->svc_sysboot, 1);
usleep_range(100, 200);
@@ -273,8 +268,7 @@ arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata)
return ret;
}
- svc_reset_onoff(arche_pdata->svc_reset_gpio,
- !arche_pdata->is_reset_act_hi);
+ svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi);
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING);
@@ -305,8 +299,7 @@ arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata)
clk_disable_unprepare(arche_pdata->svc_ref_clk);
/* As part of exit, put APB back in reset state */
- svc_reset_onoff(arche_pdata->svc_reset_gpio,
- arche_pdata->is_reset_act_hi);
+ svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
}
@@ -435,6 +428,7 @@ static int arche_platform_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
+ unsigned int flags;
arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata),
GFP_KERNEL);
@@ -444,61 +438,33 @@ static int arche_platform_probe(struct platform_device *pdev)
/* setup svc reset gpio */
arche_pdata->is_reset_act_hi = of_property_read_bool(np,
"svc,reset-active-high");
- arche_pdata->svc_reset_gpio = of_get_named_gpio(np,
- "svc,reset-gpio",
- 0);
- if (!gpio_is_valid(arche_pdata->svc_reset_gpio)) {
- dev_err(dev, "failed to get reset-gpio\n");
- return arche_pdata->svc_reset_gpio;
- }
- ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset");
- if (ret) {
- dev_err(dev, "failed to request svc-reset gpio:%d\n", ret);
- return ret;
- }
- ret = gpio_direction_output(arche_pdata->svc_reset_gpio,
- arche_pdata->is_reset_act_hi);
- if (ret) {
- dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
+ if (arche_pdata->is_reset_act_hi)
+ flags = GPIOD_OUT_HIGH;
+ else
+ flags = GPIOD_OUT_LOW;
+
+ arche_pdata->svc_reset = devm_gpiod_get(dev, "svc,reset", flags);
+ if (IS_ERR(arche_pdata->svc_reset)) {
+ ret = PTR_ERR(arche_pdata->svc_reset);
+ dev_err(dev, "failed to request svc-reset GPIO: %d\n", ret);
return ret;
}
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
- arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np,
- "svc,sysboot-gpio",
- 0);
- if (!gpio_is_valid(arche_pdata->svc_sysboot_gpio)) {
- dev_err(dev, "failed to get sysboot gpio\n");
- return arche_pdata->svc_sysboot_gpio;
- }
- ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0");
- if (ret) {
- dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret);
- return ret;
- }
- ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0);
- if (ret) {
- dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
+ arche_pdata->svc_sysboot = devm_gpiod_get(dev, "svc,sysboot",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(arche_pdata->svc_sysboot)) {
+ ret = PTR_ERR(arche_pdata->svc_sysboot);
+ dev_err(dev, "failed to request sysboot0 GPIO: %d\n", ret);
return ret;
}
/* setup the clock request gpio first */
- arche_pdata->svc_refclk_req = of_get_named_gpio(np,
- "svc,refclk-req-gpio",
- 0);
- if (!gpio_is_valid(arche_pdata->svc_refclk_req)) {
- dev_err(dev, "failed to get svc clock-req gpio\n");
- return arche_pdata->svc_refclk_req;
- }
- ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req,
- "svc-clk-req");
- if (ret) {
- dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret);
- return ret;
- }
- ret = gpio_direction_input(arche_pdata->svc_refclk_req);
- if (ret) {
- dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret);
+ arche_pdata->svc_refclk_req = devm_gpiod_get(dev, "svc,refclk-req",
+ GPIOD_IN);
+ if (IS_ERR(arche_pdata->svc_refclk_req)) {
+ ret = PTR_ERR(arche_pdata->svc_refclk_req);
+ dev_err(dev, "failed to request svc-clk-req GPIO: %d\n", ret);
return ret;
}
@@ -515,19 +481,11 @@ static int arche_platform_probe(struct platform_device *pdev)
arche_pdata->num_apbs = of_get_child_count(np);
dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs);
- arche_pdata->wake_detect_gpio = of_get_named_gpio(np,
- "svc,wake-detect-gpio",
- 0);
- if (arche_pdata->wake_detect_gpio < 0) {
- dev_err(dev, "failed to get wake detect gpio\n");
- return arche_pdata->wake_detect_gpio;
- }
-
- ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio,
- "wake detect");
- if (ret) {
- dev_err(dev, "Failed requesting wake_detect gpio %d\n",
- arche_pdata->wake_detect_gpio);
+ arche_pdata->wake_detect = devm_gpiod_get(dev, "svc,wake-detect",
+ GPIOD_IN);
+ if (IS_ERR(arche_pdata->wake_detect)) {
+ ret = PTR_ERR(arche_pdata->wake_detect);
+ dev_err(dev, "Failed requesting wake_detect GPIO: %d\n", ret);
return ret;
}
@@ -538,7 +496,7 @@ static int arche_platform_probe(struct platform_device *pdev)
spin_lock_init(&arche_pdata->wake_lock);
mutex_init(&arche_pdata->platform_state_mutex);
arche_pdata->wake_detect_irq =
- gpio_to_irq(arche_pdata->wake_detect_gpio);
+ gpiod_to_irq(arche_pdata->wake_detect);
ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq,
arche_platform_wd_irq,
diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c
index 8bcbc3c4588c..4ac30accf226 100644
--- a/drivers/staging/greybus/audio_topology.c
+++ b/drivers/staging/greybus/audio_topology.c
@@ -923,7 +923,6 @@ static int gbaudio_tplg_create_wcontrol(struct gbaudio_module_info *gb,
break;
default:
return -EINVAL;
-
}
dev_dbg(gb->dev, "%s:%d DAPM control created, ret:%d\n", ctl->name,
diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c
index 81c018da1248..e97b2b87ba47 100644
--- a/drivers/staging/greybus/bundle.c
+++ b/drivers/staging/greybus/bundle.c
@@ -65,7 +65,7 @@ static struct attribute *bundle_attrs[] = {
ATTRIBUTE_GROUPS(bundle);
static struct gb_bundle *gb_bundle_find(struct gb_interface *intf,
- u8 bundle_id)
+ u8 bundle_id)
{
struct gb_bundle *bundle;
diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h
index 8deeb1d5f008..5ca3befc0636 100644
--- a/drivers/staging/greybus/connection.h
+++ b/drivers/staging/greybus/connection.h
@@ -88,7 +88,7 @@ void gb_connection_mode_switch_prepare(struct gb_connection *connection);
void gb_connection_mode_switch_complete(struct gb_connection *connection);
void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
- u8 *data, size_t length);
+ u8 *data, size_t length);
void gb_connection_latency_tag_enable(struct gb_connection *connection);
void gb_connection_latency_tag_disable(struct gb_connection *connection);
diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c
index ffa41d31896d..a9e8b6036cac 100644
--- a/drivers/staging/greybus/control.c
+++ b/drivers/staging/greybus/control.c
@@ -15,7 +15,6 @@
#define GB_CONTROL_VERSION_MAJOR 0
#define GB_CONTROL_VERSION_MINOR 1
-
static int gb_control_get_version(struct gb_control *control)
{
struct gb_interface *intf = control->connection->intf;
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 412337daf45c..d6b0d49130c0 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -266,7 +266,7 @@ static int greybus_remove(struct device *dev)
}
int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
- const char *mod_name)
+ const char *mod_name)
{
int retval;
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index e110681e6f86..3151004d26fb 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -9,9 +9,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
+#include <linux/gpio/driver.h>
#include <linux/mutex.h>
#include "greybus.h"
@@ -39,11 +39,6 @@ struct gb_gpio_controller {
struct gpio_chip chip;
struct irq_chip irqc;
- struct irq_chip *irqchip;
- struct irq_domain *irqdomain;
- unsigned int irq_base;
- irq_flow_handler_t irq_handler;
- unsigned int irq_default_type;
struct mutex irq_lock;
};
#define gpio_chip_to_gb_gpio_controller(chip) \
@@ -391,7 +386,7 @@ static int gb_gpio_request_handler(struct gb_operation *op)
return -EINVAL;
}
- irq = irq_find_mapping(ggc->irqdomain, event->which);
+ irq = irq_find_mapping(ggc->chip.irq.domain, event->which);
if (!irq) {
dev_err(dev, "failed to find IRQ\n");
return -EINVAL;
@@ -506,135 +501,6 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc)
return ret;
}
-/**
- * gb_gpio_irq_map() - maps an IRQ into a GB gpio irqchip
- * @d: the irqdomain used by this irqchip
- * @irq: the global irq number used by this GB gpio irqchip irq
- * @hwirq: the local IRQ/GPIO line offset on this GB gpio
- *
- * This function will set up the mapping for a certain IRQ line on a
- * GB gpio by assigning the GB gpio as chip data, and using the irqchip
- * stored inside the GB gpio.
- */
-static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct gpio_chip *chip = domain->host_data;
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
-
- irq_set_chip_data(irq, ggc);
- irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler);
- irq_set_noprobe(irq);
- /*
- * No set-up of the hardware will happen if IRQ_TYPE_NONE
- * is passed as default type.
- */
- if (ggc->irq_default_type != IRQ_TYPE_NONE)
- irq_set_irq_type(irq, ggc->irq_default_type);
-
- return 0;
-}
-
-static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
-}
-
-static const struct irq_domain_ops gb_gpio_domain_ops = {
- .map = gb_gpio_irq_map,
- .unmap = gb_gpio_irq_unmap,
-};
-
-/**
- * gb_gpio_irqchip_remove() - removes an irqchip added to a gb_gpio_controller
- * @ggc: the gb_gpio_controller to remove the irqchip from
- *
- * This is called only from gb_gpio_remove()
- */
-static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc)
-{
- unsigned int offset;
-
- /* Remove all IRQ mappings and delete the domain */
- if (ggc->irqdomain) {
- for (offset = 0; offset < (ggc->line_max + 1); offset++)
- irq_dispose_mapping(irq_find_mapping(ggc->irqdomain,
- offset));
- irq_domain_remove(ggc->irqdomain);
- }
-
- if (ggc->irqchip)
- ggc->irqchip = NULL;
-}
-
-/**
- * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip
- * @chip: the gpio chip to add the irqchip to
- * @irqchip: the irqchip to add to the adapter
- * @first_irq: if not dynamically assigned, the base (first) IRQ to
- * allocate gpio irqs from
- * @handler: the irq handler to use (often a predefined irq core function)
- * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
- * to have the core avoid setting up any default type in the hardware.
- *
- * This function closely associates a certain irqchip with a certain
- * gpio chip, providing an irq domain to translate the local IRQs to
- * global irqs, and making sure that the gpio chip
- * is passed as chip data to all related functions. Driver callbacks
- * need to use container_of() to get their local state containers back
- * from the gpio chip passed as chip data. An irqdomain will be stored
- * in the gpio chip that shall be used by the driver to handle IRQ number
- * translation. The gpio chip will need to be initialized and registered
- * before calling this function.
- */
-static int gb_gpio_irqchip_add(struct gpio_chip *chip,
- struct irq_chip *irqchip,
- unsigned int first_irq,
- irq_flow_handler_t handler,
- unsigned int type)
-{
- struct gb_gpio_controller *ggc;
- unsigned int offset;
- unsigned int irq_base;
-
- if (!chip || !irqchip)
- return -EINVAL;
-
- ggc = gpio_chip_to_gb_gpio_controller(chip);
-
- ggc->irqchip = irqchip;
- ggc->irq_handler = handler;
- ggc->irq_default_type = type;
- ggc->irqdomain = irq_domain_add_simple(NULL,
- ggc->line_max + 1, first_irq,
- &gb_gpio_domain_ops, chip);
- if (!ggc->irqdomain) {
- ggc->irqchip = NULL;
- return -EINVAL;
- }
-
- /*
- * Prepare the mapping since the irqchip shall be orthogonal to
- * any gpio calls. If the first_irq was zero, this is
- * necessary to allocate descriptors for all IRQs.
- */
- for (offset = 0; offset < (ggc->line_max + 1); offset++) {
- irq_base = irq_create_mapping(ggc->irqdomain, offset);
- if (offset == 0)
- ggc->irq_base = irq_base;
- }
-
- return 0;
-}
-
-static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
-
- return irq_find_mapping(ggc->irqdomain, offset);
-}
-
static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
const struct gbphy_device_id *id)
{
@@ -694,7 +560,6 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
gpio->get = gb_gpio_get;
gpio->set = gb_gpio_set;
gpio->set_config = gb_gpio_set_config;
- gpio->to_irq = gb_gpio_to_irq;
gpio->base = -1; /* Allocate base dynamically */
gpio->ngpio = ggc->line_max + 1;
gpio->can_sleep = true;
@@ -703,24 +568,24 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
if (ret)
goto exit_line_free;
- ret = gb_gpio_irqchip_add(gpio, irqc, 0,
- handle_level_irq, IRQ_TYPE_NONE);
+ ret = gpiochip_add(gpio);
if (ret) {
- dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret);
+ dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
goto exit_line_free;
}
- ret = gpiochip_add(gpio);
+ ret = gpiochip_irqchip_add(gpio, irqc, 0, handle_level_irq,
+ IRQ_TYPE_NONE);
if (ret) {
- dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
- goto exit_gpio_irqchip_remove;
+ dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret);
+ goto exit_gpiochip_remove;
}
gbphy_runtime_put_autosuspend(gbphy_dev);
return 0;
-exit_gpio_irqchip_remove:
- gb_gpio_irqchip_remove(ggc);
+exit_gpiochip_remove:
+ gpiochip_remove(gpio);
exit_line_free:
kfree(ggc->lines);
exit_connection_disable:
@@ -744,7 +609,6 @@ static void gb_gpio_remove(struct gbphy_device *gbphy_dev)
gb_connection_disable_rx(connection);
gpiochip_remove(&ggc->chip);
- gb_gpio_irqchip_remove(ggc);
gb_connection_disable(connection);
gb_connection_destroy(connection);
kfree(ggc->lines);
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
index fa8b27e091a2..3e154562c64d 100644
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
index 986e841f6b5e..5cf12c14cca4 100644
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
#include <linux/firmware.h>
diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c
index 83a13ca7259a..80903ec36b76 100644
--- a/drivers/staging/gs_fpgaboot/io.c
+++ b/drivers/staging/gs_fpgaboot/io.c
@@ -1,15 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+
#include <linux/kernel.h>
#include <linux/init.h>
@@ -50,8 +39,7 @@ int xl_supported_prog_bus_width(enum wbus bus_bytes)
case bus_2byte:
break;
default:
- pr_err("unsupported program bus width %d\n",
- bus_bytes);
+ pr_err("unsupported program bus width %d\n", bus_bytes);
return 0;
}
diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h
index bc5d99cbda8f..9bd86a92e90f 100644
--- a/drivers/staging/gs_fpgaboot/io.h
+++ b/drivers/staging/gs_fpgaboot/io.h
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
#define GPDIR 0
#define GPCFG 4 /* open drain or not */
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index fc23059f1673..7a93d3a5c113 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -3,40 +3,6 @@
#
menu "Analog to digital converters"
-config AD7606
- tristate "Analog Devices AD7606 ADC driver"
- depends on GPIOLIB || COMPILE_TEST
- depends on HAS_IOMEM
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
- help
- Say yes here to build support for Analog Devices:
- ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
-
- To compile this driver as a module, choose M here: the
- module will be called ad7606.
-
-config AD7606_IFACE_PARALLEL
- tristate "parallel interface support"
- depends on AD7606
- help
- Say yes here to include parallel interface support on the AD7606
- ADC driver.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7606_parallel.
-
-config AD7606_IFACE_SPI
- tristate "spi interface support"
- depends on AD7606
- depends on SPI
- help
- Say yes here to include parallel interface support on the AD7606
- ADC driver.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7606_spi.
-
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index ebe83c1ad362..7a421088ff82 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -3,10 +3,6 @@
# Makefile for industrial I/O ADC drivers
#
-obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
-obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
-obj-$(CONFIG_AD7606) += ad7606.o
-
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_AD7192) += ad7192.o
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index 14f6a3ced060..d9df12665176 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -97,6 +97,10 @@
#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \
AD7280A_CELL_VOLTAGE_1 + 1)
+#define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) ((d * AD7280A_CELLS_PER_DEV) + c)
+#define AD7280A_CALC_TEMP_CHAN_NUM(d, c) ((d * AD7280A_CELLS_PER_DEV) + \
+ c - AD7280A_CELLS_PER_DEV)
+
#define AD7280A_DEVADDR_MASTER 0
#define AD7280A_DEVADDR_ALL 0x1F
/* 5-bit device address is sent LSB first */
@@ -496,72 +500,171 @@ static const struct attribute_group ad7280_attrs_group = {
.attrs = ad7280_attributes,
};
+static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i)
+{
+ chan->type = IIO_VOLTAGE;
+ chan->differential = 1;
+ chan->channel = i;
+ chan->channel2 = chan->channel + 1;
+}
+
+static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i)
+{
+ chan->type = IIO_TEMP;
+ chan->channel = i;
+}
+
+static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr,
+ int cnt)
+{
+ chan->indexed = 1;
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+ chan->address = addr;
+ chan->scan_index = cnt;
+ chan->scan_type.sign = 'u';
+ chan->scan_type.realbits = 12;
+ chan->scan_type.storagebits = 32;
+}
+
+static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan,
+ int cnt, int dev)
+{
+ chan->type = IIO_VOLTAGE;
+ chan->differential = 1;
+ chan->channel = 0;
+ chan->channel2 = dev * AD7280A_CELLS_PER_DEV;
+ chan->address = AD7280A_ALL_CELLS;
+ chan->indexed = 1;
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+ chan->scan_index = cnt;
+ chan->scan_type.sign = 'u';
+ chan->scan_type.realbits = 32;
+ chan->scan_type.storagebits = 32;
+}
+
+static void ad7280_timestamp_channel_init(struct iio_chan_spec *chan, int cnt)
+{
+ chan->type = IIO_TIMESTAMP;
+ chan->channel = -1;
+ chan->scan_index = cnt;
+ chan->scan_type.sign = 's';
+ chan->scan_type.realbits = 64;
+ chan->scan_type.storagebits = 64;
+}
+
+static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt)
+{
+ int addr, ch, i;
+ struct iio_chan_spec *chan;
+
+ for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++) {
+ chan = &st->channels[*cnt];
+
+ if (ch < AD7280A_AUX_ADC_1) {
+ i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch);
+ ad7280_voltage_channel_init(chan, i);
+ } else {
+ i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch);
+ ad7280_temp_channel_init(chan, i);
+ }
+
+ addr = ad7280a_devaddr(dev) << 8 | ch;
+ ad7280_common_fields_init(chan, addr, *cnt);
+
+ (*cnt)++;
+ }
+}
+
static int ad7280_channel_init(struct ad7280_state *st)
{
- int dev, ch, cnt;
+ int dev, cnt = 0;
st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 2,
sizeof(*st->channels), GFP_KERNEL);
if (!st->channels)
return -ENOMEM;
- for (dev = 0, cnt = 0; dev <= st->slave_num; dev++)
- for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6;
- ch++, cnt++) {
- if (ch < AD7280A_AUX_ADC_1) {
- st->channels[cnt].type = IIO_VOLTAGE;
- st->channels[cnt].differential = 1;
- st->channels[cnt].channel = (dev * 6) + ch;
- st->channels[cnt].channel2 =
- st->channels[cnt].channel + 1;
- } else {
- st->channels[cnt].type = IIO_TEMP;
- st->channels[cnt].channel = (dev * 6) + ch - 6;
- }
- st->channels[cnt].indexed = 1;
- st->channels[cnt].info_mask_separate =
- BIT(IIO_CHAN_INFO_RAW);
- st->channels[cnt].info_mask_shared_by_type =
- BIT(IIO_CHAN_INFO_SCALE);
- st->channels[cnt].address =
- ad7280a_devaddr(dev) << 8 | ch;
- st->channels[cnt].scan_index = cnt;
- st->channels[cnt].scan_type.sign = 'u';
- st->channels[cnt].scan_type.realbits = 12;
- st->channels[cnt].scan_type.storagebits = 32;
- st->channels[cnt].scan_type.shift = 0;
- }
+ for (dev = 0; dev <= st->slave_num; dev++)
+ ad7280_init_dev_channels(st, dev, &cnt);
- st->channels[cnt].type = IIO_VOLTAGE;
- st->channels[cnt].differential = 1;
- st->channels[cnt].channel = 0;
- st->channels[cnt].channel2 = dev * 6;
- st->channels[cnt].address = AD7280A_ALL_CELLS;
- st->channels[cnt].indexed = 1;
- st->channels[cnt].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
- st->channels[cnt].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
- st->channels[cnt].scan_index = cnt;
- st->channels[cnt].scan_type.sign = 'u';
- st->channels[cnt].scan_type.realbits = 32;
- st->channels[cnt].scan_type.storagebits = 32;
- st->channels[cnt].scan_type.shift = 0;
+ ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev);
cnt++;
- st->channels[cnt].type = IIO_TIMESTAMP;
- st->channels[cnt].channel = -1;
- st->channels[cnt].scan_index = cnt;
- st->channels[cnt].scan_type.sign = 's';
- st->channels[cnt].scan_type.realbits = 64;
- st->channels[cnt].scan_type.storagebits = 64;
- st->channels[cnt].scan_type.shift = 0;
+ ad7280_timestamp_channel_init(&st->channels[cnt], cnt);
return cnt + 1;
}
-static int ad7280_attr_init(struct ad7280_state *st)
+static int ad7280_balance_switch_attr_init(struct iio_dev_attr *attr,
+ struct device *dev, int addr, int i)
{
- int dev, ch, cnt;
- unsigned int index;
+ attr->address = addr;
+ attr->dev_attr.attr.mode = 0644;
+ attr->dev_attr.show = ad7280_show_balance_sw;
+ attr->dev_attr.store = ad7280_store_balance_sw;
+ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+ "in%d-in%d_balance_switch_en",
+ i, i + 1);
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int ad7280_balance_timer_attr_init(struct iio_dev_attr *attr,
+ struct device *dev, int addr, int i)
+{
+ attr->address = addr;
+ attr->dev_attr.attr.mode = 0644;
+ attr->dev_attr.show = ad7280_show_balance_timer;
+ attr->dev_attr.store = ad7280_store_balance_timer;
+ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+ "in%d-in%d_balance_timer",
+ i, i + 1);
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int ad7280_init_dev_attrs(struct ad7280_state *st, int dev, int *cnt)
+{
+ int addr, ch, i, ret;
struct iio_dev_attr *iio_attr;
+ struct device *sdev = &st->spi->dev;
+
+ for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; ch++) {
+ iio_attr = &st->iio_attr[*cnt];
+ addr = ad7280a_devaddr(dev) << 8 | ch;
+ i = dev * AD7280A_CELLS_PER_DEV + ch;
+
+ ret = ad7280_balance_switch_attr_init(iio_attr, sdev, addr, i);
+ if (ret < 0)
+ return ret;
+
+ ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr;
+
+ (*cnt)++;
+ iio_attr = &st->iio_attr[*cnt];
+ addr = ad7280a_devaddr(dev) << 8 | (AD7280A_CB1_TIMER + ch);
+
+ ret = ad7280_balance_timer_attr_init(iio_attr, sdev, addr, i);
+ if (ret < 0)
+ return ret;
+
+ ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr;
+ (*cnt)++;
+ }
+
+ ad7280_attributes[*cnt] = NULL;
+
+ return 0;
+}
+
+static int ad7280_attr_init(struct ad7280_state *st)
+{
+ int dev, cnt = 0, ret;
st->iio_attr = devm_kcalloc(&st->spi->dev, 2, sizeof(*st->iio_attr) *
(st->slave_num + 1) * AD7280A_CELLS_PER_DEV,
@@ -569,41 +672,11 @@ static int ad7280_attr_init(struct ad7280_state *st)
if (!st->iio_attr)
return -ENOMEM;
- for (dev = 0, cnt = 0; dev <= st->slave_num; dev++)
- for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6;
- ch++, cnt++) {
- iio_attr = &st->iio_attr[cnt];
- index = dev * AD7280A_CELLS_PER_DEV + ch;
- iio_attr->address = ad7280a_devaddr(dev) << 8 | ch;
- iio_attr->dev_attr.attr.mode = 0644;
- iio_attr->dev_attr.show = ad7280_show_balance_sw;
- iio_attr->dev_attr.store = ad7280_store_balance_sw;
- iio_attr->dev_attr.attr.name =
- devm_kasprintf(&st->spi->dev, GFP_KERNEL,
- "in%d-in%d_balance_switch_en",
- index, index + 1);
- if (!iio_attr->dev_attr.attr.name)
- return -ENOMEM;
-
- ad7280_attributes[cnt] = &iio_attr->dev_attr.attr;
- cnt++;
- iio_attr = &st->iio_attr[cnt];
- iio_attr->address = ad7280a_devaddr(dev) << 8 |
- (AD7280A_CB1_TIMER + ch);
- iio_attr->dev_attr.attr.mode = 0644;
- iio_attr->dev_attr.show = ad7280_show_balance_timer;
- iio_attr->dev_attr.store = ad7280_store_balance_timer;
- iio_attr->dev_attr.attr.name =
- devm_kasprintf(&st->spi->dev, GFP_KERNEL,
- "in%d-in%d_balance_timer",
- index, index + 1);
- if (!iio_attr->dev_attr.attr.name)
- return -ENOMEM;
-
- ad7280_attributes[cnt] = &iio_attr->dev_attr.attr;
- }
-
- ad7280_attributes[cnt] = NULL;
+ for (dev = 0; dev <= st->slave_num; dev++) {
+ ret = ad7280_init_dev_attrs(st, dev, &cnt);
+ if (ret < 0)
+ return ret;
+ }
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 5209651a1b25..ee50e7296795 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -65,7 +65,7 @@ enum ad7816_type {
static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
{
struct spi_device *spi_dev = chip->spi_dev;
- int ret = 0;
+ int ret;
__be16 buf;
gpiod_set_value(chip->rdwr_pin, 1);
@@ -106,7 +106,7 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
static int ad7816_spi_write(struct ad7816_chip_info *chip, u8 data)
{
struct spi_device *spi_dev = chip->spi_dev;
- int ret = 0;
+ int ret;
gpiod_set_value(chip->rdwr_pin, 1);
gpiod_set_value(chip->rdwr_pin, 0);
@@ -354,8 +354,7 @@ static int ad7816_probe(struct spi_device *spi_dev)
{
struct ad7816_chip_info *chip;
struct iio_dev *indio_dev;
- int ret = 0;
- int i;
+ int i, ret;
indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip));
if (!indio_dev)
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 2d51bd425662..0f26bc38edc6 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -43,7 +43,7 @@ static int adt7316_i2c_read(void *client, u8 reg, u8 *data)
static int adt7316_i2c_write(void *client, u8 reg, u8 data)
{
struct i2c_client *cl = client;
- int ret = 0;
+ int ret;
ret = i2c_smbus_write_byte_data(cl, reg, data);
if (ret < 0)
@@ -55,7 +55,7 @@ static int adt7316_i2c_write(void *client, u8 reg, u8 data)
static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data)
{
struct i2c_client *cl = client;
- int i, ret = 0;
+ int i, ret;
if (count > ADT7316_REG_MAX_ADDR)
count = ADT7316_REG_MAX_ADDR;
@@ -74,7 +74,7 @@ static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data)
static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data)
{
struct i2c_client *cl = client;
- int i, ret = 0;
+ int i, ret;
if (count > ADT7316_REG_MAX_ADDR)
count = ADT7316_REG_MAX_ADDR;
diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
index e75827e326a6..8294b9c1e3c2 100644
--- a/drivers/staging/iio/addac/adt7316-spi.c
+++ b/drivers/staging/iio/addac/adt7316-spi.c
@@ -27,7 +27,7 @@ static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data)
{
struct spi_device *spi_dev = client;
u8 cmd[2];
- int ret = 0;
+ int ret;
if (count > ADT7316_REG_MAX_ADDR)
count = ADT7316_REG_MAX_ADDR;
@@ -56,7 +56,7 @@ static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data)
{
struct spi_device *spi_dev = client;
u8 buf[ADT7316_REG_MAX_ADDR + 2];
- int i, ret = 0;
+ int i, ret;
if (count > ADT7316_REG_MAX_ADDR)
count = ADT7316_REG_MAX_ADDR;
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index dc93e85808e0..6f7891b567b9 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -47,6 +47,8 @@
#define ADT7516_MSB_AIN3 0xA
#define ADT7516_MSB_AIN4 0xB
#define ADT7316_DA_DATA_BASE 0x10
+#define ADT7316_DA_10_BIT_LSB_SHIFT 6
+#define ADT7316_DA_12_BIT_LSB_SHIFT 4
#define ADT7316_DA_MSB_DATA_REGS 4
#define ADT7316_LSB_DAC_A 0x10
#define ADT7316_MSB_DAC_A 0x11
@@ -59,8 +61,8 @@
#define ADT7316_CONFIG1 0x18
#define ADT7316_CONFIG2 0x19
#define ADT7316_CONFIG3 0x1A
-#define ADT7316_LDAC_CONFIG 0x1B
-#define ADT7316_DAC_CONFIG 0x1C
+#define ADT7316_DAC_CONFIG 0x1B
+#define ADT7316_LDAC_CONFIG 0x1C
#define ADT7316_INT_MASK1 0x1D
#define ADT7316_INT_MASK2 0x1E
#define ADT7316_IN_TEMP_OFFSET 0x1F
@@ -117,7 +119,7 @@
*/
#define ADT7316_ADCLK_22_5 0x1
#define ADT7316_DA_HIGH_RESOLUTION 0x2
-#define ADT7316_DA_EN_VIA_DAC_LDCA 0x4
+#define ADT7316_DA_EN_VIA_DAC_LDAC 0x8
#define ADT7516_AIN_IN_VREF 0x10
#define ADT7316_EN_IN_TEMP_PROP_DACA 0x20
#define ADT7316_EN_EX_TEMP_PROP_DACB 0x40
@@ -127,6 +129,7 @@
*/
#define ADT7316_DA_2VREF_CH_MASK 0xF
#define ADT7316_DA_EN_MODE_MASK 0x30
+#define ADT7316_DA_EN_MODE_SHIFT 4
#define ADT7316_DA_EN_MODE_SINGLE 0x00
#define ADT7316_DA_EN_MODE_AB_CD 0x10
#define ADT7316_DA_EN_MODE_ABCD 0x20
@@ -632,9 +635,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev,
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) {
- if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
- return sprintf(buf, "1 (12 bits)\n");
- if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517)
+ if (chip->id != ID_ADT7318 && chip->id != ID_ADT7519)
return sprintf(buf, "1 (10 bits)\n");
}
@@ -651,17 +652,12 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
u8 config3;
int ret;
- chip->dac_bits = 8;
+ if (chip->id == ID_ADT7318 || chip->id == ID_ADT7519)
+ return -EPERM;
- if (buf[0] == '1') {
- config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION;
- if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
- chip->dac_bits = 12;
- else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517)
- chip->dac_bits = 10;
- } else {
- config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION);
- }
+ config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION);
+ if (buf[0] == '1')
+ config3 |= ADT7316_DA_HIGH_RESOLUTION;
ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
if (ret)
@@ -851,7 +847,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
+ if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC))
return sprintf(buf, "manual\n");
switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) {
@@ -880,15 +876,15 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
u8 data;
int ret;
- if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
+ if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC))
return -EPERM;
ret = kstrtou8(buf, 10, &data);
- if (ret || data > ADT7316_DA_EN_MODE_MASK)
+ if (ret || data > (ADT7316_DA_EN_MODE_MASK >> ADT7316_DA_EN_MODE_SHIFT))
return -EINVAL;
dac_config = chip->dac_config & (~ADT7316_DA_EN_MODE_MASK);
- dac_config |= data;
+ dac_config |= data << ADT7316_DA_EN_MODE_SHIFT;
ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config);
if (ret)
@@ -911,7 +907,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)
+ if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC)
return sprintf(buf, "0 - auto at any MSB DAC writing\n"
"1 - auto at MSB DAC AB and CD writing\n"
"2 - auto at MSB DAC ABCD writing\n"
@@ -933,7 +929,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
u8 data;
int ret;
- if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) {
+ if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC) {
if ((chip->dac_config & ADT7316_DA_EN_MODE_MASK) !=
ADT7316_DA_EN_MODE_LDAC)
return -EPERM;
@@ -969,9 +965,6 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- return -EPERM;
-
return sprintf(buf, "%d\n",
!!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_AB));
}
@@ -986,9 +979,6 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
u8 dac_config;
int ret;
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- return -EPERM;
-
dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_AB);
if (buf[0] == '1')
dac_config |= ADT7316_VREF_BYPASS_DAC_AB;
@@ -1014,9 +1004,6 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- return -EPERM;
-
return sprintf(buf, "%d\n",
!!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_CD));
}
@@ -1031,9 +1018,6 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
u8 dac_config;
int ret;
- if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
- return -EPERM;
-
dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_CD);
if (buf[0] == '1')
dac_config |= ADT7316_VREF_BYPASS_DAC_CD;
@@ -1061,10 +1045,10 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev,
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
return sprintf(buf, "0x%x\n",
- (chip->dac_config & ADT7516_DAC_IN_VREF_MASK) >>
+ (chip->ldac_config & ADT7516_DAC_IN_VREF_MASK) >>
ADT7516_DAC_IN_VREF_OFFSET);
return sprintf(buf, "%d\n",
- !!(chip->dac_config & ADT7316_DAC_IN_VREF));
+ !!(chip->ldac_config & ADT7316_DAC_IN_VREF));
}
static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
@@ -1086,7 +1070,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
ldac_config = chip->ldac_config & (~ADT7516_DAC_IN_VREF_MASK);
if (data & 0x1)
ldac_config |= ADT7516_DAC_AB_IN_VREF;
- else if (data & 0x2)
+ if (data & 0x2)
ldac_config |= ADT7516_DAC_CD_IN_VREF;
} else {
ret = kstrtou8(buf, 16, &data);
@@ -1410,7 +1394,7 @@ static IIO_DEVICE_ATTR(ex_analog_temp_offset, 0644,
static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip,
int channel, char *buf)
{
- u16 data;
+ u16 data = 0;
u8 msb, lsb, offset;
int ret;
@@ -1435,7 +1419,11 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip,
if (ret)
return -EIO;
- data = (msb << offset) + (lsb & ((1 << offset) - 1));
+ if (chip->dac_bits == 12)
+ data = lsb >> ADT7316_DA_12_BIT_LSB_SHIFT;
+ else if (chip->dac_bits == 10)
+ data = lsb >> ADT7316_DA_10_BIT_LSB_SHIFT;
+ data |= msb << offset;
return sprintf(buf, "%d\n", data);
}
@@ -1443,7 +1431,7 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip,
static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip,
int channel, const char *buf, size_t len)
{
- u8 msb, lsb, offset;
+ u8 msb, lsb, lsb_reg, offset;
u16 data;
int ret;
@@ -1461,9 +1449,13 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip,
return -EINVAL;
if (chip->dac_bits > 8) {
- lsb = data & (1 << offset);
+ lsb = data & ((1 << offset) - 1);
+ if (chip->dac_bits == 12)
+ lsb_reg = lsb << ADT7316_DA_12_BIT_LSB_SHIFT;
+ else
+ lsb_reg = lsb << ADT7316_DA_10_BIT_LSB_SHIFT;
ret = chip->bus.write(chip->bus.client,
- ADT7316_DA_DATA_BASE + channel * 2, lsb);
+ ADT7316_DA_DATA_BASE + channel * 2, lsb_reg);
if (ret)
return -EIO;
}
@@ -1710,8 +1702,6 @@ static struct attribute *adt7516_attributes[] = {
&iio_dev_attr_DAC_update_mode.dev_attr.attr,
&iio_dev_attr_all_DAC_update_modes.dev_attr.attr,
&iio_dev_attr_update_DAC.dev_attr.attr,
- &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr,
- &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr,
&iio_dev_attr_DAC_internal_Vref.dev_attr.attr,
&iio_dev_attr_VDD.dev_attr.attr,
&iio_dev_attr_in_temp.dev_attr.attr,
@@ -1809,6 +1799,43 @@ static irqreturn_t adt7316_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
+static int adt7316_setup_irq(struct iio_dev *indio_dev)
+{
+ struct adt7316_chip_info *chip = iio_priv(indio_dev);
+ int irq_type, ret;
+
+ irq_type = irqd_get_trigger_type(irq_get_irq_data(chip->bus.irq));
+
+ switch (irq_type) {
+ case IRQF_TRIGGER_HIGH:
+ case IRQF_TRIGGER_RISING:
+ break;
+ case IRQF_TRIGGER_LOW:
+ case IRQF_TRIGGER_FALLING:
+ break;
+ default:
+ dev_info(&indio_dev->dev, "mode %d unsupported, using IRQF_TRIGGER_LOW\n",
+ irq_type);
+ irq_type = IRQF_TRIGGER_LOW;
+ break;
+ }
+
+ ret = devm_request_threaded_irq(&indio_dev->dev, chip->bus.irq,
+ NULL, adt7316_event_handler,
+ irq_type | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret) {
+ dev_err(&indio_dev->dev, "failed to request irq %d\n",
+ chip->bus.irq);
+ return ret;
+ }
+
+ if (irq_type & IRQF_TRIGGER_HIGH)
+ chip->config1 |= ADT7316_INT_POLARITY;
+
+ return 0;
+}
+
/*
* Show mask of enabled interrupts in Hex.
*/
@@ -2103,9 +2130,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
{
struct adt7316_chip_info *chip;
struct iio_dev *indio_dev;
- unsigned short *adt7316_platform_data = dev->platform_data;
- int irq_type = IRQF_TRIGGER_LOW;
- int ret = 0;
+ int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*chip));
if (!indio_dev)
@@ -2123,6 +2148,13 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
else
return -ENODEV;
+ if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
+ chip->dac_bits = 12;
+ else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517)
+ chip->dac_bits = 10;
+ else
+ chip->dac_bits = 8;
+
chip->ldac_pin = devm_gpiod_get_optional(dev, "adi,ldac", GPIOD_OUT_LOW);
if (IS_ERR(chip->ldac_pin)) {
ret = PTR_ERR(chip->ldac_pin);
@@ -2130,8 +2162,8 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
return ret;
}
- if (chip->ldac_pin) {
- chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDCA;
+ if (!chip->ldac_pin) {
+ chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDAC;
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
chip->config1 |= ADT7516_SEL_AIN3;
}
@@ -2148,20 +2180,9 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
indio_dev->modes = INDIO_DIRECT_MODE;
if (chip->bus.irq > 0) {
- if (adt7316_platform_data[0])
- irq_type = adt7316_platform_data[0];
-
- ret = devm_request_threaded_irq(dev, chip->bus.irq,
- NULL,
- adt7316_event_handler,
- irq_type | IRQF_ONESHOT,
- indio_dev->name,
- indio_dev);
+ ret = adt7316_setup_irq(indio_dev);
if (ret)
return ret;
-
- if (irq_type & IRQF_TRIGGER_HIGH)
- chip->config1 |= ADT7316_INT_POLARITY;
}
ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1);
diff --git a/drivers/staging/iio/cdc/Kconfig b/drivers/staging/iio/cdc/Kconfig
index 80211df8c577..b97478e7cbd0 100644
--- a/drivers/staging/iio/cdc/Kconfig
+++ b/drivers/staging/iio/cdc/Kconfig
@@ -13,16 +13,6 @@ config AD7150
To compile this driver as a module, choose M here: the
module will be called ad7150.
-config AD7152
- tristate "Analog Devices ad7152/3 capacitive sensor driver"
- depends on I2C
- help
- Say yes here to build support for Analog Devices capacitive sensors.
- (ad7152, ad7153) Provides direct access via sysfs.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7152.
-
config AD7746
tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver"
depends on I2C
diff --git a/drivers/staging/iio/cdc/Makefile b/drivers/staging/iio/cdc/Makefile
index a5fbabf5c8bf..1466bc31f244 100644
--- a/drivers/staging/iio/cdc/Makefile
+++ b/drivers/staging/iio/cdc/Makefile
@@ -3,5 +3,4 @@
#
obj-$(CONFIG_AD7150) += ad7150.o
-obj-$(CONFIG_AD7152) += ad7152.o
obj-$(CONFIG_AD7746) += ad7746.o
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
deleted file mode 100644
index 25f51db05d2d..000000000000
--- a/drivers/staging/iio/cdc/ad7152.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * AD7152 capacitive sensor driver supporting AD7152/3
- *
- * Copyright 2010-2011a Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-/*
- * TODO: Check compliance of calibbias with abi (units)
- */
-/*
- * AD7152 registers definition
- */
-
-#define AD7152_REG_STATUS 0
-#define AD7152_REG_CH1_DATA_HIGH 1
-#define AD7152_REG_CH2_DATA_HIGH 3
-#define AD7152_REG_CH1_OFFS_HIGH 5
-#define AD7152_REG_CH2_OFFS_HIGH 7
-#define AD7152_REG_CH1_GAIN_HIGH 9
-#define AD7152_REG_CH1_SETUP 11
-#define AD7152_REG_CH2_GAIN_HIGH 12
-#define AD7152_REG_CH2_SETUP 14
-#define AD7152_REG_CFG 15
-#define AD7152_REG_RESEVERD 16
-#define AD7152_REG_CAPDAC_POS 17
-#define AD7152_REG_CAPDAC_NEG 18
-#define AD7152_REG_CFG2 26
-
-/* Status Register Bit Designations (AD7152_REG_STATUS) */
-#define AD7152_STATUS_RDY1 BIT(0)
-#define AD7152_STATUS_RDY2 BIT(1)
-#define AD7152_STATUS_C1C2 BIT(2)
-#define AD7152_STATUS_PWDN BIT(7)
-
-/* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */
-#define AD7152_SETUP_CAPDIFF BIT(5)
-#define AD7152_SETUP_RANGE_2pF (0 << 6)
-#define AD7152_SETUP_RANGE_0_5pF (1 << 6)
-#define AD7152_SETUP_RANGE_1pF (2 << 6)
-#define AD7152_SETUP_RANGE_4pF (3 << 6)
-#define AD7152_SETUP_RANGE(x) ((x) << 6)
-
-/* Config Register Bit Designations (AD7152_REG_CFG) */
-#define AD7152_CONF_CH2EN BIT(3)
-#define AD7152_CONF_CH1EN BIT(4)
-#define AD7152_CONF_MODE_IDLE (0 << 0)
-#define AD7152_CONF_MODE_CONT_CONV (1 << 0)
-#define AD7152_CONF_MODE_SINGLE_CONV (2 << 0)
-#define AD7152_CONF_MODE_OFFS_CAL (5 << 0)
-#define AD7152_CONF_MODE_GAIN_CAL (6 << 0)
-
-/* Capdac Register Bit Designations (AD7152_REG_CAPDAC_XXX) */
-#define AD7152_CAPDAC_DACEN BIT(7)
-#define AD7152_CAPDAC_DACP(x) ((x) & 0x1F)
-
-/* CFG2 Register Bit Designations (AD7152_REG_CFG2) */
-#define AD7152_CFG2_OSR(x) (((x) & 0x3) << 4)
-
-enum {
- AD7152_DATA,
- AD7152_OFFS,
- AD7152_GAIN,
- AD7152_SETUP
-};
-
-/*
- * struct ad7152_chip_info - chip specific information
- */
-
-struct ad7152_chip_info {
- struct i2c_client *client;
- /*
- * Capacitive channel digital filter setup;
- * conversion time/update rate setup per channel
- */
- u8 filter_rate_setup;
- u8 setup[2];
- struct mutex state_lock; /* protect hardware state */
-};
-
-static inline ssize_t ad7152_start_calib(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len,
- u8 regval)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7152_chip_info *chip = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- bool doit;
- int ret, timeout = 10;
-
- ret = strtobool(buf, &doit);
- if (ret < 0)
- return ret;
-
- if (!doit)
- return 0;
-
- if (this_attr->address == 0)
- regval |= AD7152_CONF_CH1EN;
- else
- regval |= AD7152_CONF_CH2EN;
-
- mutex_lock(&chip->state_lock);
- ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval);
- if (ret < 0)
- goto unlock;
-
- do {
- mdelay(20);
- ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG);
- if (ret < 0)
- goto unlock;
-
- } while ((ret == regval) && timeout--);
-
- mutex_unlock(&chip->state_lock);
- return len;
-
-unlock:
- mutex_unlock(&chip->state_lock);
- return ret;
-}
-
-static ssize_t ad7152_start_offset_calib(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return ad7152_start_calib(dev, attr, buf, len,
- AD7152_CONF_MODE_OFFS_CAL);
-}
-
-static ssize_t ad7152_start_gain_calib(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- return ad7152_start_calib(dev, attr, buf, len,
- AD7152_CONF_MODE_GAIN_CAL);
-}
-
-static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration,
- 0200, NULL, ad7152_start_offset_calib, 0);
-static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration,
- 0200, NULL, ad7152_start_offset_calib, 1);
-static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration,
- 0200, NULL, ad7152_start_gain_calib, 0);
-static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration,
- 0200, NULL, ad7152_start_gain_calib, 1);
-
-/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/
-static const unsigned char ad7152_filter_rate_table[][2] = {
- {200, 5 + 1}, {50, 20 + 1}, {20, 50 + 1}, {17, 60 + 1},
-};
-
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("200 50 20 17");
-
-static IIO_CONST_ATTR(in_capacitance_scale_available,
- "0.000061050 0.000030525 0.000015263 0.000007631");
-
-static struct attribute *ad7152_attributes[] = {
- &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr,
- &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr,
- &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr,
- &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr,
- &iio_const_attr_in_capacitance_scale_available.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ad7152_attribute_group = {
- .attrs = ad7152_attributes,
-};
-
-static const u8 ad7152_addresses[][4] = {
- { AD7152_REG_CH1_DATA_HIGH, AD7152_REG_CH1_OFFS_HIGH,
- AD7152_REG_CH1_GAIN_HIGH, AD7152_REG_CH1_SETUP },
- { AD7152_REG_CH2_DATA_HIGH, AD7152_REG_CH2_OFFS_HIGH,
- AD7152_REG_CH2_GAIN_HIGH, AD7152_REG_CH2_SETUP },
-};
-
-/* Values are nano relative to pf base. */
-static const int ad7152_scale_table[] = {
- 30525, 7631, 15263, 61050
-};
-
-/**
- * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ
- *
- * lock must be held
- **/
-static int ad7152_read_raw_samp_freq(struct device *dev, int *val)
-{
- struct ad7152_chip_info *chip = iio_priv(dev_to_iio_dev(dev));
-
- *val = ad7152_filter_rate_table[chip->filter_rate_setup][0];
-
- return 0;
-}
-
-/**
- * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ
- *
- * lock must be held
- **/
-static int ad7152_write_raw_samp_freq(struct device *dev, int val)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7152_chip_info *chip = iio_priv(indio_dev);
- int ret, i;
-
- for (i = 0; i < ARRAY_SIZE(ad7152_filter_rate_table); i++)
- if (val >= ad7152_filter_rate_table[i][0])
- break;
-
- if (i >= ARRAY_SIZE(ad7152_filter_rate_table))
- i = ARRAY_SIZE(ad7152_filter_rate_table) - 1;
-
- ret = i2c_smbus_write_byte_data(chip->client,
- AD7152_REG_CFG2, AD7152_CFG2_OSR(i));
- if (ret < 0)
- return ret;
-
- chip->filter_rate_setup = i;
-
- return ret;
-}
-
-static int ad7152_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val,
- int val2,
- long mask)
-{
- struct ad7152_chip_info *chip = iio_priv(indio_dev);
- int ret, i;
-
- mutex_lock(&chip->state_lock);
-
- switch (mask) {
- case IIO_CHAN_INFO_CALIBSCALE:
- if (val != 1) {
- ret = -EINVAL;
- goto out;
- }
-
- val = (val2 * 1024) / 15625;
-
- ret = i2c_smbus_write_word_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_GAIN],
- swab16(val));
- if (ret < 0)
- goto out;
-
- ret = 0;
- break;
-
- case IIO_CHAN_INFO_CALIBBIAS:
- if ((val < 0) | (val > 0xFFFF)) {
- ret = -EINVAL;
- goto out;
- }
- ret = i2c_smbus_write_word_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_OFFS],
- swab16(val));
- if (ret < 0)
- goto out;
-
- ret = 0;
- break;
- case IIO_CHAN_INFO_SCALE:
- if (val) {
- ret = -EINVAL;
- goto out;
- }
- for (i = 0; i < ARRAY_SIZE(ad7152_scale_table); i++)
- if (val2 == ad7152_scale_table[i])
- break;
-
- chip->setup[chan->channel] &= ~AD7152_SETUP_RANGE_4pF;
- chip->setup[chan->channel] |= AD7152_SETUP_RANGE(i);
-
- ret = i2c_smbus_write_byte_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_SETUP],
- chip->setup[chan->channel]);
- if (ret < 0)
- goto out;
-
- ret = 0;
- break;
- case IIO_CHAN_INFO_SAMP_FREQ:
- if (val2) {
- ret = -EINVAL;
- goto out;
- }
- ret = ad7152_write_raw_samp_freq(&indio_dev->dev, val);
- if (ret < 0)
- goto out;
-
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- }
-
-out:
- mutex_unlock(&chip->state_lock);
- return ret;
-}
-
-static int ad7152_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2,
- long mask)
-{
- struct ad7152_chip_info *chip = iio_priv(indio_dev);
- int ret;
- u8 regval = 0;
-
- mutex_lock(&chip->state_lock);
-
- switch (mask) {
- case IIO_CHAN_INFO_RAW:
- /* First set whether in differential mode */
-
- regval = chip->setup[chan->channel];
-
- if (chan->differential)
- chip->setup[chan->channel] |= AD7152_SETUP_CAPDIFF;
- else
- chip->setup[chan->channel] &= ~AD7152_SETUP_CAPDIFF;
-
- if (regval != chip->setup[chan->channel]) {
- ret = i2c_smbus_write_byte_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_SETUP],
- chip->setup[chan->channel]);
- if (ret < 0)
- goto out;
- }
- /* Make sure the channel is enabled */
- if (chan->channel == 0)
- regval = AD7152_CONF_CH1EN;
- else
- regval = AD7152_CONF_CH2EN;
-
- /* Trigger a single read */
- regval |= AD7152_CONF_MODE_SINGLE_CONV;
- ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG,
- regval);
- if (ret < 0)
- goto out;
-
- msleep(ad7152_filter_rate_table[chip->filter_rate_setup][1]);
- /* Now read the actual register */
- ret = i2c_smbus_read_word_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_DATA]);
- if (ret < 0)
- goto out;
- *val = swab16(ret);
-
- if (chan->differential)
- *val -= 0x8000;
-
- ret = IIO_VAL_INT;
- break;
- case IIO_CHAN_INFO_CALIBSCALE:
-
- ret = i2c_smbus_read_word_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_GAIN]);
- if (ret < 0)
- goto out;
- /* 1 + gain_val / 2^16 */
- *val = 1;
- *val2 = (15625 * swab16(ret)) / 1024;
-
- ret = IIO_VAL_INT_PLUS_MICRO;
- break;
- case IIO_CHAN_INFO_CALIBBIAS:
- ret = i2c_smbus_read_word_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_OFFS]);
- if (ret < 0)
- goto out;
- *val = swab16(ret);
-
- ret = IIO_VAL_INT;
- break;
- case IIO_CHAN_INFO_SCALE:
- ret = i2c_smbus_read_byte_data(chip->client,
- ad7152_addresses[chan->channel][AD7152_SETUP]);
- if (ret < 0)
- goto out;
- *val = 0;
- *val2 = ad7152_scale_table[ret >> 6];
-
- ret = IIO_VAL_INT_PLUS_NANO;
- break;
- case IIO_CHAN_INFO_SAMP_FREQ:
- ret = ad7152_read_raw_samp_freq(&indio_dev->dev, val);
- if (ret < 0)
- goto out;
-
- ret = IIO_VAL_INT;
- break;
- default:
- ret = -EINVAL;
- }
-out:
- mutex_unlock(&chip->state_lock);
- return ret;
-}
-
-static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- long mask)
-{
- switch (mask) {
- case IIO_CHAN_INFO_SCALE:
- return IIO_VAL_INT_PLUS_NANO;
- default:
- return IIO_VAL_INT_PLUS_MICRO;
- }
-}
-
-static const struct iio_info ad7152_info = {
- .attrs = &ad7152_attribute_group,
- .read_raw = ad7152_read_raw,
- .write_raw = ad7152_write_raw,
- .write_raw_get_fmt = ad7152_write_raw_get_fmt,
-};
-
-static const struct iio_chan_spec ad7152_channels[] = {
- {
- .type = IIO_CAPACITANCE,
- .indexed = 1,
- .channel = 0,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_CALIBSCALE) |
- BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }, {
- .type = IIO_CAPACITANCE,
- .differential = 1,
- .indexed = 1,
- .channel = 0,
- .channel2 = 2,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_CALIBSCALE) |
- BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }, {
- .type = IIO_CAPACITANCE,
- .indexed = 1,
- .channel = 1,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_CALIBSCALE) |
- BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }, {
- .type = IIO_CAPACITANCE,
- .differential = 1,
- .indexed = 1,
- .channel = 1,
- .channel2 = 3,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_CALIBSCALE) |
- BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }
-};
-
-/*
- * device probe and remove
- */
-
-static int ad7152_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int ret = 0;
- struct ad7152_chip_info *chip;
- struct iio_dev *indio_dev;
-
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
- if (!indio_dev)
- return -ENOMEM;
- chip = iio_priv(indio_dev);
- /* this is only used for device removal purposes */
- i2c_set_clientdata(client, indio_dev);
-
- chip->client = client;
- mutex_init(&chip->state_lock);
-
- /* Establish that the iio_dev is a child of the i2c device */
- indio_dev->name = id->name;
- indio_dev->dev.parent = &client->dev;
- indio_dev->info = &ad7152_info;
- indio_dev->channels = ad7152_channels;
- if (id->driver_data == 0)
- indio_dev->num_channels = ARRAY_SIZE(ad7152_channels);
- else
- indio_dev->num_channels = 2;
- indio_dev->num_channels = ARRAY_SIZE(ad7152_channels);
- indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
- if (ret)
- return ret;
-
- dev_err(&client->dev, "%s capacitive sensor registered\n", id->name);
-
- return 0;
-}
-
-static const struct i2c_device_id ad7152_id[] = {
- { "ad7152", 0 },
- { "ad7153", 1 },
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, ad7152_id);
-
-static struct i2c_driver ad7152_driver = {
- .driver = {
- .name = KBUILD_MODNAME,
- },
- .probe = ad7152_probe,
- .id_table = ad7152_id,
-};
-module_i2c_driver(ad7152_driver);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices AD7152/3 capacitive sensor driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 1e977014fe5f..0b0287503fb4 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -6,6 +6,7 @@
* Licensed under the GPL-2.
*/
+#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/device.h>
@@ -71,7 +72,7 @@
struct ad9834_state {
struct spi_device *spi;
struct regulator *reg;
- unsigned int mclk;
+ struct clk *mclk;
unsigned short control;
unsigned short devid;
struct spi_transfer xfer;
@@ -110,12 +111,15 @@ static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout)
static int ad9834_write_frequency(struct ad9834_state *st,
unsigned long addr, unsigned long fout)
{
+ unsigned long clk_freq;
unsigned long regval;
- if (fout > (st->mclk / 2))
+ clk_freq = clk_get_rate(st->mclk);
+
+ if (fout > (clk_freq / 2))
return -EINVAL;
- regval = ad9834_calc_freqreg(st->mclk, fout);
+ regval = ad9834_calc_freqreg(clk_freq, fout);
st->freq_data[0] = cpu_to_be16(addr | (regval &
RES_MASK(AD9834_FREQ_BITS / 2)));
@@ -389,16 +393,11 @@ static const struct iio_info ad9833_info = {
static int ad9834_probe(struct spi_device *spi)
{
- struct ad9834_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad9834_state *st;
struct iio_dev *indio_dev;
struct regulator *reg;
int ret;
- if (!pdata) {
- dev_dbg(&spi->dev, "no platform data?\n");
- return -ENODEV;
- }
reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(reg))
@@ -418,7 +417,14 @@ static int ad9834_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
mutex_init(&st->lock);
- st->mclk = pdata->mclk;
+ st->mclk = devm_clk_get(&spi->dev, NULL);
+
+ ret = clk_prepare_enable(st->mclk);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable master clock\n");
+ goto error_disable_reg;
+ }
+
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
st->reg = reg;
@@ -454,42 +460,41 @@ static int ad9834_probe(struct spi_device *spi)
spi_message_add_tail(&st->freq_xfer[1], &st->freq_msg);
st->control = AD9834_B28 | AD9834_RESET;
+ st->control |= AD9834_DIV2;
- if (!pdata->en_div2)
- st->control |= AD9834_DIV2;
-
- if (!pdata->en_signbit_msb_out && (st->devid == ID_AD9834))
+ if (st->devid == ID_AD9834)
st->control |= AD9834_SIGN_PIB;
st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
ret = spi_sync(st->spi, &st->msg);
if (ret) {
dev_err(&spi->dev, "device init failed\n");
- goto error_disable_reg;
+ goto error_clock_unprepare;
}
- ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0);
+ ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, 1000000);
if (ret)
- goto error_disable_reg;
+ goto error_clock_unprepare;
- ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1);
+ ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, 5000000);
if (ret)
- goto error_disable_reg;
+ goto error_clock_unprepare;
- ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0);
+ ret = ad9834_write_phase(st, AD9834_REG_PHASE0, 512);
if (ret)
- goto error_disable_reg;
+ goto error_clock_unprepare;
- ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1);
+ ret = ad9834_write_phase(st, AD9834_REG_PHASE1, 1024);
if (ret)
- goto error_disable_reg;
+ goto error_clock_unprepare;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_disable_reg;
+ goto error_clock_unprepare;
return 0;
-
+error_clock_unprepare:
+ clk_disable_unprepare(st->mclk);
error_disable_reg:
regulator_disable(reg);
@@ -502,6 +507,7 @@ static int ad9834_remove(struct spi_device *spi)
struct ad9834_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
+ clk_disable_unprepare(st->mclk);
regulator_disable(st->reg);
return 0;
diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h
index ae620f38eb49..da7e83ceedad 100644
--- a/drivers/staging/iio/frequency/ad9834.h
+++ b/drivers/staging/iio/frequency/ad9834.h
@@ -8,32 +8,4 @@
#ifndef IIO_DDS_AD9834_H_
#define IIO_DDS_AD9834_H_
-/*
- * TODO: struct ad7887_platform_data needs to go into include/linux/iio
- */
-
-/**
- * struct ad9834_platform_data - platform specific information
- * @mclk: master clock in Hz
- * @freq0: power up freq0 tuning word in Hz
- * @freq1: power up freq1 tuning word in Hz
- * @phase0: power up phase0 value [0..4095] correlates with 0..2PI
- * @phase1: power up phase1 value [0..4095] correlates with 0..2PI
- * @en_div2: digital output/2 is passed to the SIGN BIT OUT pin
- * @en_signbit_msb_out: the MSB (or MSB/2) of the DAC data is connected to the
- * SIGN BIT OUT pin. en_div2 controls whether it is the MSB
- * or MSB/2 that is output. if en_signbit_msb_out=false,
- * the on-board comparator is connected to SIGN BIT OUT
- */
-
-struct ad9834_platform_data {
- unsigned int mclk;
- unsigned int freq0;
- unsigned int freq1;
- unsigned short phase0;
- unsigned short phase1;
- bool en_div2;
- bool en_signbit_msb_out;
-};
-
#endif /* IIO_DDS_AD9834_H_ */
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 9e52384f5370..3134295f014f 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/clk.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -82,21 +83,10 @@
#define AD5933_POLL_TIME_ms 10
#define AD5933_INIT_EXCITATION_TIME_ms 100
-/**
- * struct ad5933_platform_data - platform specific data
- * @ext_clk_hz: the external clock frequency in Hz, if not set
- * the driver uses the internal clock (16.776 MHz)
- * @vref_mv: the external reference voltage in millivolt
- */
-
-struct ad5933_platform_data {
- unsigned long ext_clk_hz;
- unsigned short vref_mv;
-};
-
struct ad5933_state {
struct i2c_client *client;
struct regulator *reg;
+ struct clk *mclk;
struct delayed_work work;
struct mutex lock; /* Protect sensor state */
unsigned long mclk_hz;
@@ -112,10 +102,6 @@ struct ad5933_state {
unsigned int poll_time_jiffies;
};
-static struct ad5933_platform_data ad5933_default_pdata = {
- .vref_mv = 3300,
-};
-
#define AD5933_CHANNEL(_type, _extend_name, _info_mask_separate, _address, \
_scan_index, _realbits) { \
.type = (_type), \
@@ -691,10 +677,10 @@ static void ad5933_work(struct work_struct *work)
static int ad5933_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int ret, voltage_uv = 0;
- struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev);
+ int ret;
struct ad5933_state *st;
struct iio_dev *indio_dev;
+ unsigned long ext_clk_hz = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (!indio_dev)
@@ -706,9 +692,6 @@ static int ad5933_probe(struct i2c_client *client,
mutex_init(&st->lock);
- if (!pdata)
- pdata = &ad5933_default_pdata;
-
st->reg = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
@@ -718,15 +701,28 @@ static int ad5933_probe(struct i2c_client *client,
dev_err(&client->dev, "Failed to enable specified VDD supply\n");
return ret;
}
- voltage_uv = regulator_get_voltage(st->reg);
+ ret = regulator_get_voltage(st->reg);
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- st->vref_mv = pdata->vref_mv;
+ if (ret < 0)
+ goto error_disable_reg;
+
+ st->vref_mv = ret / 1000;
+
+ st->mclk = devm_clk_get(&client->dev, "mclk");
+ if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) {
+ ret = PTR_ERR(st->mclk);
+ goto error_disable_reg;
+ }
- if (pdata->ext_clk_hz) {
- st->mclk_hz = pdata->ext_clk_hz;
+ if (!IS_ERR(st->mclk)) {
+ ret = clk_prepare_enable(st->mclk);
+ if (ret < 0)
+ goto error_disable_reg;
+ ext_clk_hz = clk_get_rate(st->mclk);
+ }
+
+ if (ext_clk_hz) {
+ st->mclk_hz = ext_clk_hz;
st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK;
} else {
st->mclk_hz = AD5933_INT_OSC_FREQ_Hz;
@@ -746,7 +742,7 @@ static int ad5933_probe(struct i2c_client *client,
ret = ad5933_register_ring_funcs_and_init(indio_dev);
if (ret)
- goto error_disable_reg;
+ goto error_disable_mclk;
ret = ad5933_setup(st);
if (ret)
@@ -760,6 +756,8 @@ static int ad5933_probe(struct i2c_client *client,
error_unreg_ring:
iio_kfifo_free(indio_dev->buffer);
+error_disable_mclk:
+ clk_disable_unprepare(st->mclk);
error_disable_reg:
regulator_disable(st->reg);
@@ -774,6 +772,7 @@ static int ad5933_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_kfifo_free(indio_dev->buffer);
regulator_disable(st->reg);
+ clk_disable_unprepare(st->mclk);
return 0;
}
diff --git a/drivers/staging/ks7010/Makefile b/drivers/staging/ks7010/Makefile
index 07dc16cc86f5..412e2105a3a5 100644
--- a/drivers/staging/ks7010/Makefile
+++ b/drivers/staging/ks7010/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_KS7010) += ks7010.o
-ks7010-y := michael_mic.o ks_hostif.o ks_wlan_net.o ks7010_sdio.o
+ks7010-y := ks_hostif.o ks_wlan_net.o ks7010_sdio.o
diff --git a/drivers/staging/ks7010/TODO b/drivers/staging/ks7010/TODO
index d393ca58e231..87a6dac4890d 100644
--- a/drivers/staging/ks7010/TODO
+++ b/drivers/staging/ks7010/TODO
@@ -27,8 +27,6 @@ Now the TODOs:
- fix the 'card removal' event when card is inserted when booting
- check what other upstream wireless mechanisms can be used instead of the
custom ones here
-- replace custom Michael MIC implementation with the kernel
- implementation. This task is only required for a *clean* WEXT interface.
Please send any patches to:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
index 065bce193fac..06ebea0be118 100644
--- a/drivers/staging/ks7010/ks_hostif.c
+++ b/drivers/staging/ks7010/ks_hostif.c
@@ -6,15 +6,18 @@
* Copyright (C) 2009 Renesas Technology Corp.
*/
+#include <crypto/hash.h>
#include <linux/circ_buf.h>
#include <linux/if_arp.h>
#include <net/iw_handler.h>
#include <uapi/linux/llc.h>
#include "eap_packet.h"
#include "ks_wlan.h"
-#include "michael_mic.h"
#include "ks_hostif.h"
+#define MICHAEL_MIC_KEY_LEN 8
+#define MICHAEL_MIC_LEN 8
+
static inline void inc_smeqhead(struct ks_wlan_private *priv)
{
priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE;
@@ -35,7 +38,7 @@ static inline u8 get_byte(struct ks_wlan_private *priv)
{
u8 data;
- data = *(priv->rxp)++;
+ data = *priv->rxp++;
/* length check in advance ! */
--(priv->rx_size);
return data;
@@ -171,7 +174,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info *ap_info)
"- rate_set_size=%d\n",
ap->bssid[0], ap->bssid[1], ap->bssid[2],
ap->bssid[3], ap->bssid[4], ap->bssid[5],
- &(ap->ssid.body[0]),
+ &ap->ssid.body[0],
ap->rate_set.body[0], ap->rate_set.body[1],
ap->rate_set.body[2], ap->rate_set.body[3],
ap->rate_set.body[4], ap->rate_set.body[5],
@@ -191,6 +194,68 @@ static u8 read_ie(unsigned char *bp, u8 max, u8 *body)
return size;
}
+static int
+michael_mic(u8 *key, u8 *data, unsigned int len, u8 priority, u8 *result)
+{
+ u8 pad_data[4] = { priority, 0, 0, 0 };
+ struct crypto_shash *tfm = NULL;
+ struct shash_desc *desc = NULL;
+ int ret;
+
+ tfm = crypto_alloc_shash("michael_mic", 0, 0);
+ if (IS_ERR(tfm)) {
+ ret = PTR_ERR(tfm);
+ goto err;
+ }
+
+ ret = crypto_shash_setkey(tfm, key, MICHAEL_MIC_KEY_LEN);
+ if (ret < 0)
+ goto err_free_tfm;
+
+ desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
+ if (!desc) {
+ ret = -ENOMEM;
+ goto err_free_tfm;
+ }
+
+ desc->tfm = tfm;
+ desc->flags = 0;
+
+ ret = crypto_shash_init(desc);
+ if (ret < 0)
+ goto err_free_desc;
+
+ // Compute the MIC value
+ /*
+ * IEEE802.11i page 47
+ * Figure 43g TKIP MIC processing format
+ * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
+ * |6 |6 |1 |3 |M |1 |1 |1 |1 |1 |1 |1 |1 | Octet
+ * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
+ * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7|
+ * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
+ */
+
+ ret = crypto_shash_update(desc, data, 12);
+ if (ret < 0)
+ goto err_free_desc;
+
+ ret = crypto_shash_update(desc, pad_data, 4);
+ if (ret < 0)
+ goto err_free_desc;
+
+ ret = crypto_shash_finup(desc, data + 12, len - 12, result);
+
+err_free_desc:
+ kzfree(desc);
+
+err_free_tfm:
+ crypto_free_shash(tfm);
+
+err:
+ return ret;
+}
+
static
int get_ap_information(struct ks_wlan_private *priv, struct ap_info *ap_info,
struct local_ap *ap)
@@ -273,11 +338,11 @@ int hostif_data_indication_wpa(struct ks_wlan_private *priv,
{
struct ether_hdr *eth_hdr;
unsigned short eth_proto;
- unsigned char recv_mic[8];
+ unsigned char recv_mic[MICHAEL_MIC_LEN];
char buf[128];
unsigned long now;
struct mic_failure *mic_failure;
- struct michael_mic michael_mic;
+ u8 mic[MICHAEL_MIC_LEN];
union iwreq_data wrqu;
unsigned int key_index = auth_type - 1;
struct wpa_key *key = &priv->wpa.key[key_index];
@@ -300,14 +365,20 @@ int hostif_data_indication_wpa(struct ks_wlan_private *priv,
netdev_dbg(priv->net_dev, "TKIP: protocol=%04X: size=%u\n",
eth_proto, priv->rx_size);
/* MIC save */
- memcpy(&recv_mic[0], (priv->rxp) + ((priv->rx_size) - 8), 8);
- priv->rx_size = priv->rx_size - 8;
+ memcpy(&recv_mic[0],
+ (priv->rxp) + ((priv->rx_size) - sizeof(recv_mic)),
+ sizeof(recv_mic));
+ priv->rx_size = priv->rx_size - sizeof(recv_mic);
if (auth_type > 0 && auth_type < 4) { /* auth_type check */
- michael_mic_function(&michael_mic, key->rx_mic_key,
- priv->rxp, priv->rx_size,
- 0, michael_mic.result);
+ int ret;
+
+ ret = michael_mic(key->rx_mic_key,
+ priv->rxp, priv->rx_size,
+ 0, mic);
+ if (ret < 0)
+ return ret;
}
- if (memcmp(michael_mic.result, recv_mic, 8) != 0) {
+ if (memcmp(mic, recv_mic, sizeof(mic)) != 0) {
now = jiffies;
mic_failure = &priv->wpa.mic_failure;
/* MIC FAILURE */
@@ -730,9 +801,9 @@ void hostif_scan_indication(struct ks_wlan_private *priv)
priv->scan_ind_count++;
if (priv->scan_ind_count < LOCAL_APLIST_MAX + 1) {
netdev_dbg(priv->net_dev, " scan_ind_count=%d :: aplist.size=%d\n",
- priv->scan_ind_count, priv->aplist.size);
+ priv->scan_ind_count, priv->aplist.size);
get_ap_information(priv, (struct ap_info *)(priv->rxp),
- &(priv->aplist.ap[priv->scan_ind_count - 1]));
+ &priv->aplist.ap[priv->scan_ind_count - 1]);
priv->aplist.size = priv->scan_ind_count;
} else {
netdev_dbg(priv->net_dev, " count over :: scan_ind_count=%d\n",
@@ -1002,7 +1073,6 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *skb)
int result = 0;
unsigned short eth_proto;
struct ether_hdr *eth_hdr;
- struct michael_mic michael_mic;
unsigned short keyinfo = 0;
struct ieee802_1x_hdr *aa1x_hdr;
struct wpa_eapol_key *eap_key;
@@ -1109,17 +1179,20 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *skb)
pp->auth_type = cpu_to_le16(TYPE_AUTH);
} else {
if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) {
- michael_mic_function(&michael_mic,
- priv->wpa.key[0].tx_mic_key,
- &pp->data[0], skb_len,
- 0, michael_mic.result);
- memcpy(p, michael_mic.result, 8);
- length += 8;
- skb_len += 8;
- p += 8;
+ u8 mic[MICHAEL_MIC_LEN];
+
+ ret = michael_mic(priv->wpa.key[0].tx_mic_key,
+ &pp->data[0], skb_len,
+ 0, mic);
+ if (ret < 0)
+ goto err_kfree;
+
+ memcpy(p, mic, sizeof(mic));
+ length += sizeof(mic);
+ skb_len += sizeof(mic);
+ p += sizeof(mic);
pp->auth_type =
cpu_to_le16(TYPE_DATA);
-
} else if (priv->wpa.pairwise_suite ==
IW_AUTH_CIPHER_CCMP) {
pp->auth_type =
diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c
index dc5459ae0b51..3cffc8be6656 100644
--- a/drivers/staging/ks7010/ks_wlan_net.c
+++ b/drivers/staging/ks7010/ks_wlan_net.c
@@ -182,7 +182,7 @@ static int ks_wlan_set_freq(struct net_device *dev,
/* for SLEEP MODE */
/* If setting by frequency, convert to a channel */
if ((fwrq->freq.e == 1) &&
- (fwrq->freq.m >= (int)2.412e8) && (fwrq->freq.m <= (int)2.487e8)) {
+ (fwrq->freq.m >= 241200000) && (fwrq->freq.m <= 248700000)) {
int f = fwrq->freq.m / 100000;
int c = 0;
diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c
deleted file mode 100644
index 3acd79615f98..000000000000
--- a/drivers/staging/ks7010/michael_mic.c
+++ /dev/null
@@ -1,127 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Driver for KeyStream wireless LAN
- *
- * Copyright (C) 2005-2008 KeyStream Corp.
- * Copyright (C) 2009 Renesas Technology Corp.
- */
-
-#include <asm/unaligned.h>
-#include <linux/bitops.h>
-#include <linux/string.h>
-#include "michael_mic.h"
-
-// Reset the state to the empty message.
-static inline void michael_clear(struct michael_mic *mic)
-{
- mic->l = mic->k0;
- mic->r = mic->k1;
- mic->m_bytes = 0;
-}
-
-static void michael_init(struct michael_mic *mic, u8 *key)
-{
- // Set the key
- mic->k0 = get_unaligned_le32(key);
- mic->k1 = get_unaligned_le32(key + 4);
-
- //clear();
- michael_clear(mic);
-}
-
-static inline void michael_block(struct michael_mic *mic)
-{
- mic->r ^= rol32(mic->l, 17);
- mic->l += mic->r;
- mic->r ^= ((mic->l & 0xff00ff00) >> 8) |
- ((mic->l & 0x00ff00ff) << 8);
- mic->l += mic->r;
- mic->r ^= rol32(mic->l, 3);
- mic->l += mic->r;
- mic->r ^= ror32(mic->l, 2);
- mic->l += mic->r;
-}
-
-static void michael_append(struct michael_mic *mic, u8 *src, int bytes)
-{
- int addlen;
-
- if (mic->m_bytes) {
- addlen = 4 - mic->m_bytes;
- if (addlen > bytes)
- addlen = bytes;
- memcpy(&mic->m[mic->m_bytes], src, addlen);
- mic->m_bytes += addlen;
- src += addlen;
- bytes -= addlen;
-
- if (mic->m_bytes < 4)
- return;
-
- mic->l ^= get_unaligned_le32(mic->m);
- michael_block(mic);
- mic->m_bytes = 0;
- }
-
- while (bytes >= 4) {
- mic->l ^= get_unaligned_le32(src);
- michael_block(mic);
- src += 4;
- bytes -= 4;
- }
-
- if (bytes > 0) {
- mic->m_bytes = bytes;
- memcpy(mic->m, src, bytes);
- }
-}
-
-static void michael_get_mic(struct michael_mic *mic, u8 *dst)
-{
- u8 *data = mic->m;
-
- switch (mic->m_bytes) {
- case 0:
- mic->l ^= 0x5a;
- break;
- case 1:
- mic->l ^= data[0] | 0x5a00;
- break;
- case 2:
- mic->l ^= data[0] | (data[1] << 8) | 0x5a0000;
- break;
- case 3:
- mic->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
- 0x5a000000;
- break;
- }
- michael_block(mic);
- michael_block(mic);
- // The appendByte function has already computed the result.
- put_unaligned_le32(mic->l, dst);
- put_unaligned_le32(mic->r, dst + 4);
-
- // Reset to the empty message.
- michael_clear(mic);
-}
-
-void michael_mic_function(struct michael_mic *mic, u8 *key,
- u8 *data, unsigned int len, u8 priority, u8 *result)
-{
- u8 pad_data[4] = { priority, 0, 0, 0 };
- // Compute the MIC value
- /*
- * IEEE802.11i page 47
- * Figure 43g TKIP MIC processing format
- * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
- * |6 |6 |1 |3 |M |1 |1 |1 |1 |1 |1 |1 |1 | Octet
- * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
- * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7|
- * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
- */
- michael_init(mic, key);
- michael_append(mic, data, 12); /* |DA|SA| */
- michael_append(mic, pad_data, 4); /* |Priority|0|0|0| */
- michael_append(mic, data + 12, len - 12); /* |Data| */
- michael_get_mic(mic, result);
-}
diff --git a/drivers/staging/ks7010/michael_mic.h b/drivers/staging/ks7010/michael_mic.h
deleted file mode 100644
index f0ac164b999b..000000000000
--- a/drivers/staging/ks7010/michael_mic.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Driver for KeyStream wireless LAN
- *
- * Copyright (C) 2005-2008 KeyStream Corp.
- * Copyright (C) 2009 Renesas Technology Corp.
- */
-
-/* MichaelMIC routine define */
-struct michael_mic {
- u32 k0; // Key
- u32 k1; // Key
- u32 l; // Current state
- u32 r; // Current state
- u8 m[4]; // Message accumulator (single word)
- int m_bytes; // # bytes in M
- u8 result[8];
-};
-
-void michael_mic_function(struct michael_mic *mic, u8 *key,
- u8 *data, unsigned int len, u8 priority, u8 *result);
diff --git a/drivers/staging/media/davinci_vpfe/Makefile b/drivers/staging/media/davinci_vpfe/Makefile
index 9c57042c877d..9268e507f791 100644
--- a/drivers/staging/media/davinci_vpfe/Makefile
+++ b/drivers/staging/media/davinci_vpfe/Makefile
@@ -6,5 +6,5 @@ davinci-vfpe-objs := \
# Allow building it with COMPILE_TEST on other archs
ifndef CONFIG_ARCH_DAVINCI
-ccflags-y += -Iarch/arm/mach-davinci/include/
+ccflags-y += -I $(srctree)/arch/arm/mach-davinci/include/
endif
diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile
index f8bcf488ecf2..c7662f65f6db 100644
--- a/drivers/staging/most/Makefile
+++ b/drivers/staging/most/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_MOST) += most_core.o
most_core-y := core.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
obj-$(CONFIG_MOST_CDEV) += cdev/
obj-$(CONFIG_MOST_NET) += net/
diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile
index afb9870eb50f..21b0bd72c01d 100644
--- a/drivers/staging/most/cdev/Makefile
+++ b/drivers/staging/most/cdev/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_CDEV) += most_cdev.o
most_cdev-objs := cdev.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
index ea64aabda94e..f2b347cda8b7 100644
--- a/drivers/staging/most/cdev/cdev.c
+++ b/drivers/staging/most/cdev/cdev.c
@@ -453,7 +453,9 @@ static int comp_probe(struct most_interface *iface, int channel_id,
c->devno = MKDEV(comp.major, current_minor);
cdev_init(&c->cdev, &channel_fops);
c->cdev.owner = THIS_MODULE;
- cdev_add(&c->cdev, c->devno, 1);
+ retval = cdev_add(&c->cdev, c->devno, 1);
+ if (retval < 0)
+ goto err_free_c;
c->iface = iface;
c->cfg = cfg;
c->channel_id = channel_id;
@@ -485,6 +487,7 @@ err_free_kfifo_and_del_list:
list_del(&c->list);
err_del_cdev_and_free_channel:
cdev_del(&c->cdev);
+err_free_c:
kfree(c);
err_remove_ida:
ida_simple_remove(&comp.minor_id, current_minor);
diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile
index 66676f5907ee..6d15f045a767 100644
--- a/drivers/staging/most/dim2/Makefile
+++ b/drivers/staging/most/dim2/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_DIM2) += most_dim2.o
most_dim2-objs := dim2.o hal.o sysfs.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile
index a7d094c1e1c2..c032fea979b3 100644
--- a/drivers/staging/most/i2c/Makefile
+++ b/drivers/staging/most/i2c/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_I2C) += most_i2c.o
most_i2c-objs := i2c.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile
index 54500aa77be8..820faec6b296 100644
--- a/drivers/staging/most/net/Makefile
+++ b/drivers/staging/most/net/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_NET) += most_net.o
most_net-objs := net.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile
index eee8774e38cb..5bb55bb108fb 100644
--- a/drivers/staging/most/sound/Makefile
+++ b/drivers/staging/most/sound/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_SOUND) += most_sound.o
most_sound-objs := sound.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile
index 18d28cba4fbf..910cd08bad7c 100644
--- a/drivers/staging/most/usb/Makefile
+++ b/drivers/staging/most/usb/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_USB) += most_usb.o
most_usb-objs := usb.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile
index 1c8e520e02a2..c6e01b6ecfe6 100644
--- a/drivers/staging/most/video/Makefile
+++ b/drivers/staging/most/video/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_MOST_VIDEO) += most_video.o
most_video-objs := video.o
-ccflags-y += -Idrivers/staging/
+ccflags-y += -I $(srctree)/drivers/staging/
diff --git a/drivers/staging/mt7621-dma/Kconfig b/drivers/staging/mt7621-dma/Kconfig
index 2423c40099d1..b6e48a682c44 100644
--- a/drivers/staging/mt7621-dma/Kconfig
+++ b/drivers/staging/mt7621-dma/Kconfig
@@ -1,9 +1,3 @@
-config DMA_RALINK
- tristate "RALINK DMA support"
- depends on RALINK && !SOC_RT288X
- select DMA_ENGINE
- select DMA_VIRTUAL_CHANNELS
-
config MTK_HSDMA
tristate "MTK HSDMA support"
depends on RALINK && SOC_MT7621
diff --git a/drivers/staging/mt7621-dma/Makefile b/drivers/staging/mt7621-dma/Makefile
index d3152d45cf45..c9e3e1619ab0 100644
--- a/drivers/staging/mt7621-dma/Makefile
+++ b/drivers/staging/mt7621-dma/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o
obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
ccflags-y += -I$(srctree)/drivers/dma
diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c
index d67a2504adb1..97571f1d697b 100644
--- a/drivers/staging/mt7621-dma/mtk-hsdma.c
+++ b/drivers/staging/mt7621-dma/mtk-hsdma.c
@@ -1,12 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015, Michael Lee <igvtee@gmail.com>
* MTK HSDMA support
- *
- * 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/dmaengine.h>
@@ -191,7 +186,7 @@ static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg)
}
static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma,
- unsigned reg, u32 val)
+ unsigned int reg, u32 val)
{
writel(val, hsdma->base + reg);
}
@@ -242,7 +237,7 @@ static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma,
int i;
dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n",
- chan->tx_idx, chan->rx_idx);
+ chan->tx_idx, chan->rx_idx);
for (i = 0; i < HSDMA_DESCS_NUM; i++) {
tx_desc = &chan->tx_ring[i];
diff --git a/drivers/staging/mt7621-dts/gbpc1.dts b/drivers/staging/mt7621-dts/gbpc1.dts
index 6a1699ce9455..b73385540216 100644
--- a/drivers/staging/mt7621-dts/gbpc1.dts
+++ b/drivers/staging/mt7621-dts/gbpc1.dts
@@ -136,8 +136,8 @@
&pinctrl {
state_default: pinctrl0 {
gpio {
- ralink,group = "wdt", "rgmii2", "uart3";
- ralink,function = "gpio";
+ groups = "wdt", "rgmii2", "uart3";
+ function = "gpio";
};
};
};
diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
index 71f069d59ad8..6aff3680ce4b 100644
--- a/drivers/staging/mt7621-dts/mt7621.dtsi
+++ b/drivers/staging/mt7621-dts/mt7621.dtsi
@@ -204,82 +204,82 @@
i2c_pins: i2c0 {
i2c0 {
- group = "i2c";
+ groups = "i2c";
function = "i2c";
};
};
spi_pins: spi0 {
spi0 {
- group = "spi";
+ groups = "spi";
function = "spi";
};
};
uart1_pins: uart1 {
uart1 {
- group = "uart1";
+ groups = "uart1";
function = "uart1";
};
};
uart2_pins: uart2 {
uart2 {
- group = "uart2";
+ groups = "uart2";
function = "uart2";
};
};
uart3_pins: uart3 {
uart3 {
- group = "uart3";
+ groups = "uart3";
function = "uart3";
};
};
rgmii1_pins: rgmii1 {
rgmii1 {
- group = "rgmii1";
+ groups = "rgmii1";
function = "rgmii1";
};
};
rgmii2_pins: rgmii2 {
rgmii2 {
- group = "rgmii2";
+ groups = "rgmii2";
function = "rgmii2";
};
};
mdio_pins: mdio0 {
mdio0 {
- group = "mdio";
+ groups = "mdio";
function = "mdio";
};
};
pcie_pins: pcie0 {
pcie0 {
- group = "pcie";
+ groups = "pcie";
function = "pcie rst";
};
};
nand_pins: nand0 {
spi-nand {
- group = "spi";
+ groups = "spi";
function = "nand1";
};
sdhci-nand {
- group = "sdhci";
+ groups = "sdhci";
function = "nand2";
};
};
sdhci_pins: sdhci0 {
sdhci0 {
- group = "sdhci";
+ groups = "sdhci";
function = "sdhci";
};
};
@@ -420,10 +420,12 @@
status = "disabled";
- resets = <&rstctrl 24 &rstctrl 25 &rstctrl 26>;
- reset-names = "pcie0", "pcie1", "pcie2";
+ resets = <&rstctrl 23 &rstctrl 24 &rstctrl 25 &rstctrl 26>;
+ reset-names = "pcie", "pcie0", "pcie1", "pcie2";
clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>;
clock-names = "pcie0", "pcie1", "pcie2";
+ phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
+ phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
pcie@0,0 {
reg = <0x0000 0 0 0 0>;
@@ -449,4 +451,33 @@
bus-range = <0x00 0xff>;
};
};
+
+ pcie0_phy: pcie-phy@1e149000 {
+ compatible = "mediatek,mt7621-pci-phy";
+ reg = <0x1e149000 0x0700>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcie0_port: pcie-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ pcie1_port: pcie-phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+ };
+
+ pcie1_phy: pcie-phy@1e14a000 {
+ compatible = "mediatek,mt7621-pci-phy";
+ reg = <0x1e14a000 0x0700>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcie2_port: pcie-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+ };
};
diff --git a/drivers/staging/mt7621-eth/ethtool.c b/drivers/staging/mt7621-eth/ethtool.c
index 40a7d47be913..8c4228e2c987 100644
--- a/drivers/staging/mt7621-eth/ethtool.c
+++ b/drivers/staging/mt7621-eth/ethtool.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/* 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 of the License
diff --git a/drivers/staging/mt7621-eth/ethtool.h b/drivers/staging/mt7621-eth/ethtool.h
index 40b4cf011660..0071469aea6c 100644
--- a/drivers/staging/mt7621-eth/ethtool.h
+++ b/drivers/staging/mt7621-eth/ethtool.h
@@ -1,12 +1,5 @@
-/* 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 of the License
- *
- * 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.
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
diff --git a/drivers/staging/mt7621-eth/mtk_eth_soc.c b/drivers/staging/mt7621-eth/mtk_eth_soc.c
index 21a76a8ccc26..6027b19f7bc2 100644
--- a/drivers/staging/mt7621-eth/mtk_eth_soc.c
+++ b/drivers/staging/mt7621-eth/mtk_eth_soc.c
@@ -1396,8 +1396,7 @@ static int mtk_qdma_tx_alloc_tx(struct mtk_eth *eth)
if (!ring->tx_buf)
goto no_tx_mem;
- ring->tx_dma = dma_zalloc_coherent(eth->dev,
- ring->tx_ring_size * sz,
+ ring->tx_dma = dma_alloc_coherent(eth->dev, ring->tx_ring_size * sz,
&ring->tx_phys,
GFP_ATOMIC | __GFP_ZERO);
if (!ring->tx_dma)
diff --git a/drivers/staging/mt7621-mmc/Kconfig b/drivers/staging/mt7621-mmc/Kconfig
index c6dfe8c637dc..1eb79cd6e22f 100644
--- a/drivers/staging/mt7621-mmc/Kconfig
+++ b/drivers/staging/mt7621-mmc/Kconfig
@@ -1,6 +1,6 @@
config MTK_MMC
tristate "MTK SD/MMC"
- depends on !MTD_NAND_RALINK && MMC
+ depends on RALINK && MMC
config MTK_AEE_KDUMP
bool "MTK AEE KDUMP"
diff --git a/drivers/staging/mt7621-mmc/dbg.c b/drivers/staging/mt7621-mmc/dbg.c
index eabe0595978b..c7c091fa1da0 100644
--- a/drivers/staging/mt7621-mmc/dbg.c
+++ b/drivers/staging/mt7621-mmc/dbg.c
@@ -36,7 +36,6 @@
* Inc.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kthread.h>
diff --git a/drivers/staging/mt7621-mmc/mt6575_sd.h b/drivers/staging/mt7621-mmc/mt6575_sd.h
index 4e287c140acb..038a484a9476 100644
--- a/drivers/staging/mt7621-mmc/mt6575_sd.h
+++ b/drivers/staging/mt7621-mmc/mt6575_sd.h
@@ -363,7 +363,7 @@ enum {
#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F << 10)
#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 << 7)
#define MSDC_CKGEN_MSDC_CK_SEL (0x1 << 6)
-#define CARD_READY_FOR_DATA (1 << 8)
+#define CARD_READY_FOR_DATA BIT(8)
#define CARD_CURRENT_STATE(x) ((x & 0x00001E00) >> 9)
/*--------------------------------------------------------------------------*/
diff --git a/drivers/staging/mt7621-pci-phy/Kconfig b/drivers/staging/mt7621-pci-phy/Kconfig
new file mode 100644
index 000000000000..b9f6ab784ee8
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/Kconfig
@@ -0,0 +1,7 @@
+config PCI_MT7621_PHY
+ tristate "MediaTek MT7621 PCI PHY Driver"
+ depends on RALINK && OF
+ select GENERIC_PHY
+ help
+ Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver,
+
diff --git a/drivers/staging/mt7621-pci-phy/Makefile b/drivers/staging/mt7621-pci-phy/Makefile
new file mode 100644
index 000000000000..a970056f05c1
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PCI_MT7621_PHY) += pci-mt7621-phy.o
diff --git a/drivers/staging/mt7621-pci-phy/TODO b/drivers/staging/mt7621-pci-phy/TODO
new file mode 100644
index 000000000000..a255e8f753eb
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/TODO
@@ -0,0 +1,4 @@
+
+- general code review and cleanup
+
+Cc: NeilBrown <neil@brown.name> and Sergio Paracuellos <sergio.paracuellos@gmail.com>
diff --git a/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
new file mode 100644
index 000000000000..33a8a698bdd0
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
@@ -0,0 +1,54 @@
+Mediatek Mt7621 PCIe PHY
+
+Required properties:
+- compatible: must be "mediatek,mt7621-pci-phy"
+- reg: base address and length of the PCIe PHY block
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Each PCIe PHY should be represented by a child node
+
+Required properties For the child node:
+- reg: the PHY ID
+0 - PCIe RC 0
+1 - PCIe RC 1
+- #phy-cells: must be 0
+
+Example:
+ pcie0_phy: pcie-phy@1a149000 {
+ compatible = "mediatek,mt7621-pci-phy";
+ reg = <0x1a149000 0x0700>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcie0_port: pcie-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ pcie1_port: pcie-phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+ };
+
+ pcie1_phy: pcie-phy@1a14a000 {
+ compatible = "mediatek,mt7621-pci-phy";
+ reg = <0x1a14a000 0x0700>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcie2_port: pcie-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+ };
+
+ /* users of the PCIe phy */
+
+ pcie: pcie@1e140000 {
+ ...
+ ...
+ phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
+ phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
+ }; \ No newline at end of file
diff --git a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
new file mode 100644
index 000000000000..d3ca2f019112
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Mediatek MT7621 PCI PHY Driver
+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <mt7621.h>
+#include <ralink_regs.h>
+
+#define RALINK_CLKCFG1 0x30
+#define CHIP_REV_MT7621_E2 0x0101
+
+#define PCIE_PORT_CLK_EN(x) BIT(24 + (x))
+
+#define RG_PE1_PIPE_REG 0x02c
+#define RG_PE1_PIPE_RST BIT(12)
+#define RG_PE1_PIPE_CMD_FRC BIT(4)
+
+#define RG_P0_TO_P1_WIDTH 0x100
+#define RG_PE1_H_LCDDS_REG 0x49c
+#define RG_PE1_H_LCDDS_PCW GENMASK(30, 0)
+#define RG_PE1_H_LCDDS_PCW_VAL(x) ((0x7fffffff & (x)) << 0)
+
+#define RG_PE1_FRC_H_XTAL_REG 0x400
+#define RG_PE1_FRC_H_XTAL_TYPE BIT(8)
+#define RG_PE1_H_XTAL_TYPE GENMASK(10, 9)
+#define RG_PE1_H_XTAL_TYPE_VAL(x) ((0x3 & (x)) << 9)
+
+#define RG_PE1_FRC_PHY_REG 0x000
+#define RG_PE1_FRC_PHY_EN BIT(4)
+#define RG_PE1_PHY_EN BIT(5)
+
+#define RG_PE1_H_PLL_REG 0x490
+#define RG_PE1_H_PLL_BC GENMASK(23, 22)
+#define RG_PE1_H_PLL_BC_VAL(x) ((0x3 & (x)) << 22)
+#define RG_PE1_H_PLL_BP GENMASK(21, 18)
+#define RG_PE1_H_PLL_BP_VAL(x) ((0xf & (x)) << 18)
+#define RG_PE1_H_PLL_IR GENMASK(15, 12)
+#define RG_PE1_H_PLL_IR_VAL(x) ((0xf & (x)) << 12)
+#define RG_PE1_H_PLL_IC GENMASK(11, 8)
+#define RG_PE1_H_PLL_IC_VAL(x) ((0xf & (x)) << 8)
+#define RG_PE1_H_PLL_PREDIV GENMASK(7, 6)
+#define RG_PE1_H_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
+#define RG_PE1_PLL_DIVEN GENMASK(3, 1)
+#define RG_PE1_PLL_DIVEN_VAL(x) ((0x7 & (x)) << 1)
+
+#define RG_PE1_H_PLL_FBKSEL_REG 0x4bc
+#define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4)
+#define RG_PE1_H_PLL_FBKSEL_VAL(x) ((0x3 & (x)) << 4)
+
+#define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4
+#define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0)
+#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x) ((0xffff & (x)) << 0)
+
+#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8
+#define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0)
+#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
+#define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16)
+#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
+
+#define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0
+#define RG_PE1_LCDDS_CLK_PH_INV BIT(5)
+
+#define RG_PE1_H_PLL_BR_REG 0x4ac
+#define RG_PE1_H_PLL_BR GENMASK(18, 16)
+#define RG_PE1_H_PLL_BR_VAL(x) ((0x7 & (x)) << 16)
+
+#define RG_PE1_MSTCKDIV_REG 0x414
+#define RG_PE1_MSTCKDIV GENMASK(7, 6)
+#define RG_PE1_MSTCKDIV_VAL(x) ((0x3 & (x)) << 6)
+
+#define RG_PE1_FRC_MSTCKDIV BIT(5)
+
+/**
+ * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
+ * @phy: pointer to the kernel PHY device
+ * @port_base: base register
+ * @index: internal ID to identify the Mt7621 PCIe PHY
+ */
+struct mt7621_pci_phy_instance {
+ struct phy *phy;
+ void __iomem *port_base;
+ u32 index;
+};
+
+/**
+ * struct mt7621_pci_phy - Mt7621 Pcie PHY core
+ * @dev: pointer to device
+ * @phys: pointer to Mt7621 PHY device
+ * @nphys: number of PHY devices for this core
+ */
+struct mt7621_pci_phy {
+ struct device *dev;
+ struct mt7621_pci_phy_instance **phys;
+ int nphys;
+};
+
+static inline u32 phy_read(struct mt7621_pci_phy_instance *instance, u32 reg)
+{
+ return readl(instance->port_base + reg);
+}
+
+static inline void phy_write(struct mt7621_pci_phy_instance *instance,
+ u32 val, u32 reg)
+{
+ writel(val, instance->port_base + reg);
+}
+
+static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy,
+ struct mt7621_pci_phy_instance *instance)
+{
+ u32 offset = (instance->index != 1) ?
+ RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
+ u32 reg;
+
+ reg = phy_read(instance, offset);
+ reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
+ reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
+ phy_write(instance, reg, offset);
+}
+
+static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy,
+ struct mt7621_pci_phy_instance *instance)
+{
+ struct device *dev = phy->dev;
+ u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
+ u32 offset;
+ u32 val;
+
+ reg = (reg >> 6) & 0x7;
+ /* Set PCIe Port PHY to disable SSC */
+ /* Debug Xtal Type */
+ val = phy_read(instance, RG_PE1_FRC_H_XTAL_REG);
+ val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
+ val |= RG_PE1_FRC_H_XTAL_TYPE;
+ val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
+ phy_write(instance, val, RG_PE1_FRC_H_XTAL_REG);
+
+ /* disable port */
+ offset = (instance->index != 1) ?
+ RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+ val = phy_read(instance, offset);
+ val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+ val |= RG_PE1_FRC_PHY_EN;
+ phy_write(instance, val, offset);
+
+ /* Set Pre-divider ratio (for host mode) */
+ val = phy_read(instance, RG_PE1_H_PLL_REG);
+ val &= ~(RG_PE1_H_PLL_PREDIV);
+
+ if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
+ val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
+ phy_write(instance, val, RG_PE1_H_PLL_REG);
+ dev_info(dev, "Xtal is 40MHz\n");
+ } else { /* 25MHz | 20MHz Xtal */
+ val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
+ phy_write(instance, val, RG_PE1_H_PLL_REG);
+ if (reg >= 6) {
+ dev_info(dev, "Xtal is 25MHz\n");
+
+ /* Select feedback clock */
+ val = phy_read(instance, RG_PE1_H_PLL_FBKSEL_REG);
+ val &= ~(RG_PE1_H_PLL_FBKSEL);
+ val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
+ phy_write(instance, val, RG_PE1_H_PLL_FBKSEL_REG);
+
+ /* DDS NCPO PCW (for host mode) */
+ val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
+ val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
+ val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
+ phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
+
+ /* DDS SSC dither period control */
+ val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
+ val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
+ val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
+ phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
+
+ /* DDS SSC dither amplitude control */
+ val = phy_read(instance, RG_PE1_H_LCDDS_SSC_DELTA_REG);
+ val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
+ RG_PE1_H_LCDDS_SSC_DELTA1);
+ val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
+ val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
+ phy_write(instance, val, RG_PE1_H_LCDDS_SSC_DELTA_REG);
+ } else {
+ dev_info(dev, "Xtal is 20MHz\n");
+ }
+ }
+
+ /* DDS clock inversion */
+ val = phy_read(instance, RG_PE1_LCDDS_CLK_PH_INV_REG);
+ val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
+ val |= RG_PE1_LCDDS_CLK_PH_INV;
+ phy_write(instance, val, RG_PE1_LCDDS_CLK_PH_INV_REG);
+
+ /* Set PLL bits */
+ val = phy_read(instance, RG_PE1_H_PLL_REG);
+ val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
+ RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
+ val |= RG_PE1_H_PLL_BC_VAL(0x02);
+ val |= RG_PE1_H_PLL_BP_VAL(0x06);
+ val |= RG_PE1_H_PLL_IR_VAL(0x02);
+ val |= RG_PE1_H_PLL_IC_VAL(0x01);
+ val |= RG_PE1_PLL_DIVEN_VAL(0x02);
+ phy_write(instance, val, RG_PE1_H_PLL_REG);
+
+ val = phy_read(instance, RG_PE1_H_PLL_BR_REG);
+ val &= ~(RG_PE1_H_PLL_BR);
+ val |= RG_PE1_H_PLL_BR_VAL(0x00);
+ phy_write(instance, val, RG_PE1_H_PLL_BR_REG);
+
+ if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
+ /* set force mode enable of da_pe1_mstckdiv */
+ val = phy_read(instance, RG_PE1_MSTCKDIV_REG);
+ val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
+ val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
+ phy_write(instance, val, RG_PE1_MSTCKDIV_REG);
+ }
+}
+
+static int mt7621_pci_phy_init(struct phy *phy)
+{
+ struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+ struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
+ u32 chip_rev_id = rt_sysc_r32(SYSC_REG_CHIP_REV);
+
+ if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
+ mt7621_bypass_pipe_rst(mphy, instance);
+
+ mt7621_set_phy_for_ssc(mphy, instance);
+
+ return 0;
+}
+
+static int mt7621_pci_phy_power_on(struct phy *phy)
+{
+ struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+ u32 offset = (instance->index != 1) ?
+ RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+ u32 val;
+
+ /* Enable PHY and disable force mode */
+ val = phy_read(instance, offset);
+ val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+ val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+ phy_write(instance, val, offset);
+
+ return 0;
+}
+
+static int mt7621_pci_phy_power_off(struct phy *phy)
+{
+ struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+ u32 offset = (instance->index != 1) ?
+ RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+ u32 val;
+
+ /* Disable PHY */
+ val = phy_read(instance, offset);
+ val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+ val |= RG_PE1_FRC_PHY_EN;
+ phy_write(instance, val, offset);
+
+ return 0;
+}
+
+static int mt7621_pci_phy_exit(struct phy *phy)
+{
+ struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+
+ rt_sysc_m32(PCIE_PORT_CLK_EN(instance->index), 0, RALINK_CLKCFG1);
+
+ return 0;
+}
+
+static const struct phy_ops mt7621_pci_phy_ops = {
+ .init = mt7621_pci_phy_init,
+ .exit = mt7621_pci_phy_exit,
+ .power_on = mt7621_pci_phy_power_on,
+ .power_off = mt7621_pci_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int mt7621_pci_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *child_np;
+ struct phy_provider *provider;
+ struct mt7621_pci_phy *phy;
+ struct resource res;
+ int port, ret;
+ void __iomem *port_base;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ phy->nphys = of_get_child_count(np);
+ phy->phys = devm_kcalloc(dev, phy->nphys,
+ sizeof(*phy->phys), GFP_KERNEL);
+ if (!phy->phys)
+ return -ENOMEM;
+
+ phy->dev = dev;
+ platform_set_drvdata(pdev, phy);
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ dev_err(dev, "failed to get address resource(id-%d)\n", port);
+ return ret;
+ }
+
+ port_base = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(port_base)) {
+ dev_err(dev, "failed to remap phy regs\n");
+ return PTR_ERR(port_base);
+ }
+
+ port = 0;
+ for_each_child_of_node(np, child_np) {
+ struct mt7621_pci_phy_instance *instance;
+ struct phy *pphy;
+
+ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+ if (!instance) {
+ ret = -ENOMEM;
+ goto put_child;
+ }
+
+ phy->phys[port] = instance;
+
+ pphy = devm_phy_create(dev, child_np, &mt7621_pci_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create phy\n");
+ ret = PTR_ERR(phy);
+ goto put_child;
+ }
+
+ instance->port_base = port_base;
+ instance->phy = pphy;
+ instance->index = port;
+ phy_set_drvdata(pphy, instance);
+ port++;
+ }
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+
+put_child:
+ of_node_put(child_np);
+ return ret;
+}
+
+static const struct of_device_id mt7621_pci_phy_ids[] = {
+ { .compatible = "mediatek,mt7621-pci-phy" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
+
+static struct platform_driver mt7621_pci_phy_driver = {
+ .probe = mt7621_pci_phy_probe,
+ .driver = {
+ .name = "mt7621-pci-phy",
+ .of_match_table = of_match_ptr(mt7621_pci_phy_ids),
+ },
+};
+
+static int __init mt7621_pci_phy_drv_init(void)
+{
+ return platform_driver_register(&mt7621_pci_phy_driver);
+}
+
+module_init(mt7621_pci_phy_drv_init);
+
+MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/mt7621-pci/Makefile b/drivers/staging/mt7621-pci/Makefile
index 607b84bedcc3..d4655a726b61 100644
--- a/drivers/staging/mt7621-pci/Makefile
+++ b/drivers/staging/mt7621-pci/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o
+obj-$(CONFIG_PCI_MT7621) += pci-mt7621.o
diff --git a/drivers/staging/mt7621-pci/TODO b/drivers/staging/mt7621-pci/TODO
index cf30f629b9fd..ccfd266db4ca 100644
--- a/drivers/staging/mt7621-pci/TODO
+++ b/drivers/staging/mt7621-pci/TODO
@@ -1,12 +1,4 @@
- general code review and cleanup
-- can this be converted to not require PCI_DRIVERS_LEGACY ??
- The irq returned by pcibios_map_irq is a "hwirq" (hardware irq number)
- and pci_assign_irq() assigns this directly to dev->irq, which
- expects a "virq" (virtual irq number). These numbers are different
- on MIPS. There is a gross hack to make it work on one
- specific platform, so it can be tested.
-- Should this be merged with arch/mips/pci/pci-mt7620.c ??
-- ensure device-tree requirements are documented
Cc: NeilBrown <neil@brown.name>
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index 31310b6fb7db..379ae780c691 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -25,6 +25,7 @@
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <mt7621.h>
@@ -34,13 +35,8 @@
/* sysctl */
#define MT7621_CHIP_REV_ID 0x0c
-#define RALINK_CLKCFG1 0x30
-#define RALINK_RSTCTRL 0x34
#define CHIP_REV_MT7621_E2 0x0101
-/* RALINK_RSTCTRL bits */
-#define RALINK_PCIE_RST BIT(23)
-
/* MediaTek specific configuration registers */
#define PCIE_FTS_NUM 0x70c
#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
@@ -90,81 +86,16 @@
#define PCIE_CLK_GEN_EN BIT(31)
#define PCIE_CLK_GEN_DIS 0
-#define PCIE_CLK_GEN1_DIS GENMASK(30,24)
+#define PCIE_CLK_GEN1_DIS GENMASK(30, 24)
#define PCIE_CLK_GEN1_EN (BIT(27) | BIT(25))
-#define RALINK_PCI_IO_MAP_BASE 0x1e160000
#define MEMORY_BASE 0x0
-/* pcie phy related macros */
-#define RALINK_PCIEPHY_P0P1_CTL_OFFSET 0x9000
-#define RALINK_PCIEPHY_P2_CTL_OFFSET 0xA000
-
-#define RG_P0_TO_P1_WIDTH 0x100
-
-#define RG_PE1_PIPE_REG 0x02c
-#define RG_PE1_PIPE_RST BIT(12)
-#define RG_PE1_PIPE_CMD_FRC BIT(4)
-
-#define RG_PE1_H_LCDDS_REG 0x49c
-#define RG_PE1_H_LCDDS_PCW GENMASK(30, 0)
-#define RG_PE1_H_LCDDS_PCW_VAL(x) ((0x7fffffff & (x)) << 0)
-
-#define RG_PE1_FRC_H_XTAL_REG 0x400
-#define RG_PE1_FRC_H_XTAL_TYPE BIT(8)
-#define RG_PE1_H_XTAL_TYPE GENMASK(10, 9)
-#define RG_PE1_H_XTAL_TYPE_VAL(x) ((0x3 & (x)) << 9)
-
-#define RG_PE1_FRC_PHY_REG 0x000
-#define RG_PE1_FRC_PHY_EN BIT(4)
-#define RG_PE1_PHY_EN BIT(5)
-
-#define RG_PE1_H_PLL_REG 0x490
-#define RG_PE1_H_PLL_BC GENMASK(23, 22)
-#define RG_PE1_H_PLL_BC_VAL(x) ((0x3 & (x)) << 22)
-#define RG_PE1_H_PLL_BP GENMASK(21, 18)
-#define RG_PE1_H_PLL_BP_VAL(x) ((0xf & (x)) << 18)
-#define RG_PE1_H_PLL_IR GENMASK(15, 12)
-#define RG_PE1_H_PLL_IR_VAL(x) ((0xf & (x)) << 12)
-#define RG_PE1_H_PLL_IC GENMASK(11, 8)
-#define RG_PE1_H_PLL_IC_VAL(x) ((0xf & (x)) << 8)
-#define RG_PE1_H_PLL_PREDIV GENMASK(7, 6)
-#define RG_PE1_H_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
-#define RG_PE1_PLL_DIVEN GENMASK(3, 1)
-#define RG_PE1_PLL_DIVEN_VAL(x) ((0x7 & (x)) << 1)
-
-#define RG_PE1_H_PLL_FBKSEL_REG 0x4bc
-#define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4)
-#define RG_PE1_H_PLL_FBKSEL_VAL(x) ((0x3 & (x)) << 4)
-
-#define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4
-#define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0)
-#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x) ((0xffff & (x)) << 0)
-
-#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8
-#define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0)
-#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
-#define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16)
-#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
-
-#define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0
-#define RG_PE1_LCDDS_CLK_PH_INV BIT(5)
-
-#define RG_PE1_H_PLL_BR_REG 0x4ac
-#define RG_PE1_H_PLL_BR GENMASK(18, 16)
-#define RG_PE1_H_PLL_BR_VAL(x) ((0x7 & (x)) << 16)
-
-#define RG_PE1_MSTCKDIV_REG 0x414
-#define RG_PE1_MSTCKDIV GENMASK(7, 6)
-#define RG_PE1_MSTCKDIV_VAL(x) ((0x3 & (x)) << 6)
-
-#define RG_PE1_FRC_MSTCKDIV BIT(5)
-
/**
* struct mt7621_pcie_port - PCIe port information
* @base: I/O mapped register base
* @list: port list
* @pcie: pointer to PCIe host info
- * @phy_reg_offset: offset to related phy registers
+ * @phy: pointer to PHY control block
* @pcie_rst: pointer to port reset control
* @slot: port slot
* @enabled: indicates if port is enabled
@@ -173,7 +104,7 @@ struct mt7621_pcie_port {
void __iomem *base;
struct list_head list;
struct mt7621_pcie *pcie;
- u32 phy_reg_offset;
+ struct phy *phy;
struct reset_control *pcie_rst;
u32 slot;
bool enabled;
@@ -188,6 +119,7 @@ struct mt7621_pcie_port {
* @offset: IO / Memory offset
* @dev: Pointer to PCIe device
* @ports: pointer to PCIe port information
+ * @rst: pointer to pcie reset
*/
struct mt7621_pcie {
void __iomem *base;
@@ -200,6 +132,7 @@ struct mt7621_pcie {
resource_size_t io;
} offset;
struct list_head ports;
+ struct reset_control *rst;
};
static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg)
@@ -265,150 +198,6 @@ static void write_config(struct mt7621_pcie *pcie, unsigned int dev,
pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA);
}
-static void bypass_pipe_rst(struct mt7621_pcie_port *port)
-{
- struct mt7621_pcie *pcie = port->pcie;
- u32 phy_offset = port->phy_reg_offset;
- u32 offset = (port->slot != 1) ?
- phy_offset + RG_PE1_PIPE_REG :
- phy_offset + RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
- u32 reg = pcie_read(pcie, offset);
-
- reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
- reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
- pcie_write(pcie, reg, offset);
-}
-
-static void set_phy_for_ssc(struct mt7621_pcie_port *port)
-{
- struct mt7621_pcie *pcie = port->pcie;
- struct device *dev = pcie->dev;
- u32 phy_offset = port->phy_reg_offset;
- u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
- u32 offset;
- u32 val;
-
- reg = (reg >> 6) & 0x7;
- /* Set PCIe Port PHY to disable SSC */
- /* Debug Xtal Type */
- offset = phy_offset + RG_PE1_FRC_H_XTAL_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
- val |= RG_PE1_FRC_H_XTAL_TYPE;
- val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
- pcie_write(pcie, val, offset);
-
- /* disable port */
- offset = (port->slot != 1) ?
- phy_offset + RG_PE1_FRC_PHY_REG :
- phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
- val |= RG_PE1_FRC_PHY_EN;
- pcie_write(pcie, val, offset);
-
- /* Set Pre-divider ratio (for host mode) */
- offset = phy_offset + RG_PE1_H_PLL_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_PLL_PREDIV);
-
- if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
- val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
- pcie_write(pcie, val, offset);
- dev_info(dev, "Xtal is 40MHz\n");
- } else { /* 25MHz | 20MHz Xtal */
- val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
- pcie_write(pcie, val, offset);
- if (reg >= 6) {
- dev_info(dev, "Xtal is 25MHz\n");
-
- /* Select feedback clock */
- offset = phy_offset + RG_PE1_H_PLL_FBKSEL_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_PLL_FBKSEL);
- val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
- pcie_write(pcie, val, offset);
-
- /* DDS NCPO PCW (for host mode) */
- offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
- val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
- pcie_write(pcie, val, offset);
-
- /* DDS SSC dither period control */
- offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
- val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
- pcie_write(pcie, val, offset);
-
- /* DDS SSC dither amplitude control */
- offset = phy_offset + RG_PE1_H_LCDDS_SSC_DELTA_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
- RG_PE1_H_LCDDS_SSC_DELTA1);
- val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
- val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
- pcie_write(pcie, val, offset);
- } else {
- dev_info(dev, "Xtal is 20MHz\n");
- }
- }
-
- /* DDS clock inversion */
- offset = phy_offset + RG_PE1_LCDDS_CLK_PH_INV_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
- val |= RG_PE1_LCDDS_CLK_PH_INV;
- pcie_write(pcie, val, offset);
-
- /* Set PLL bits */
- offset = phy_offset + RG_PE1_H_PLL_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
- RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
- val |= RG_PE1_H_PLL_BC_VAL(0x02);
- val |= RG_PE1_H_PLL_BP_VAL(0x06);
- val |= RG_PE1_H_PLL_IR_VAL(0x02);
- val |= RG_PE1_H_PLL_IC_VAL(0x01);
- val |= RG_PE1_PLL_DIVEN_VAL(0x02);
- pcie_write(pcie, val, offset);
-
- offset = phy_offset + RG_PE1_H_PLL_BR_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_H_PLL_BR);
- val |= RG_PE1_H_PLL_BR_VAL(0x00);
- pcie_write(pcie, val, offset);
-
- if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
- /* set force mode enable of da_pe1_mstckdiv */
- offset = phy_offset + RG_PE1_MSTCKDIV_REG;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
- val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
- pcie_write(pcie, val, offset);
- }
-
- /* Enable PHY and disable force mode */
- offset = (port->slot != 1) ?
- phy_offset + RG_PE1_FRC_PHY_REG :
- phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
- val = pcie_read(pcie, offset);
- val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
- val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
- pcie_write(pcie, val, offset);
-}
-
-static void mt7621_enable_phy(struct mt7621_pcie_port *port)
-{
- u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
-
- if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
- bypass_pipe_rst(port);
- set_phy_for_ssc(port);
-}
-
static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
{
u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
@@ -510,7 +299,7 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
struct device *dev = pcie->dev;
struct device_node *pnode = dev->of_node;
struct resource regs;
- char name[6];
+ char name[10];
int err;
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
@@ -534,11 +323,13 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
return PTR_ERR(port->pcie_rst);
}
+ snprintf(name, sizeof(name), "pcie-phy%d", slot);
+ port->phy = devm_phy_get(dev, name);
+ if (IS_ERR(port->phy))
+ return PTR_ERR(port->phy);
+
port->slot = slot;
port->pcie = pcie;
- port->phy_reg_offset = (slot != 2) ?
- RALINK_PCIEPHY_P0P1_CTL_OFFSET :
- RALINK_PCIEPHY_P2_CTL_OFFSET;
INIT_LIST_HEAD(&port->list);
list_add_tail(&port->list, &pcie->ports);
@@ -563,6 +354,12 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie)
if (IS_ERR(pcie->base))
return PTR_ERR(pcie->base);
+ pcie->rst = devm_reset_control_get_exclusive(dev, "pcie");
+ if (PTR_ERR(pcie->rst) == -EPROBE_DEFER) {
+ dev_err(dev, "failed to get pcie reset control\n");
+ return PTR_ERR(pcie->rst);
+ }
+
for_each_available_child_of_node(node, child) {
int slot;
@@ -588,6 +385,7 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
struct device *dev = pcie->dev;
u32 slot = port->slot;
u32 val = 0;
+ int err;
/*
* Any MT7621 Ralink pcie controller that doesn't have 0x0101 at
@@ -598,18 +396,36 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
val = read_config(pcie, slot, PCIE_FTS_NUM);
dev_info(dev, "Port %d N_FTS = %x\n", (unsigned int)val, slot);
+ err = phy_init(port->phy);
+ if (err) {
+ dev_err(dev, "failed to initialize port%d phy\n", slot);
+ goto err_phy_init;
+ }
+
+ err = phy_power_on(port->phy);
+ if (err) {
+ dev_err(dev, "failed to power on port%d phy\n", slot);
+ goto err_phy_on;
+ }
+
if ((pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) == 0) {
dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot);
mt7621_control_assert(port);
- rt_sysc_m32(PCIE_PORT_CLK_EN(slot), 0, RALINK_CLKCFG1);
port->enabled = false;
- } else {
- port->enabled = true;
+ err = -ENODEV;
+ goto err_no_link_up;
}
- mt7621_enable_phy(port);
+ port->enabled = true;
return 0;
+
+err_no_link_up:
+ phy_power_off(port->phy);
+err_phy_on:
+ phy_exit(port->phy);
+err_phy_init:
+ return err;
}
static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
@@ -628,13 +444,13 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
}
}
- rt_sysc_m32(0, RALINK_PCIE_RST, RALINK_RSTCTRL);
+ reset_control_assert(pcie->rst);
rt_sysc_m32(0x30, 2 << 4, SYSC_REG_SYSTEM_CONFIG1);
rt_sysc_m32(PCIE_CLK_GEN_EN, PCIE_CLK_GEN_DIS, RALINK_PCIE_CLK_GEN);
rt_sysc_m32(PCIE_CLK_GEN1_DIS, PCIE_CLK_GEN1_EN, RALINK_PCIE_CLK_GEN1);
rt_sysc_m32(PCIE_CLK_GEN_DIS, PCIE_CLK_GEN_EN, RALINK_PCIE_CLK_GEN);
msleep(50);
- rt_sysc_m32(RALINK_PCIE_RST, 0, RALINK_RSTCTRL);
+ reset_control_deassert(pcie->rst);
}
static int mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
@@ -690,7 +506,7 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
list_for_each_entry(port, &pcie->ports, list) {
if (port->enabled) {
- if (!mt7621_pcie_enable_port(port)) {
+ if (mt7621_pcie_enable_port(port)) {
dev_err(dev, "de-assert port %d PERST_N\n",
port->slot);
continue;
@@ -701,8 +517,9 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
}
for (slot = 0; slot < num_slots_enabled; slot++) {
- val = read_config(pcie, slot, 0x4);
- write_config(pcie, slot, 0x4, val | 0x4);
+ val = read_config(pcie, slot, PCI_COMMAND);
+ val |= PCI_COMMAND_MASTER;
+ write_config(pcie, slot, PCI_COMMAND, val);
/* configure RC FTS number to 250 when it leaves L0s */
val = read_config(pcie, slot, PCIE_FTS_NUM);
val &= ~PCIE_FTS_NUM_MASK;
@@ -714,7 +531,7 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie)
static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
{
u32 pcie_link_status = 0;
- u32 val= 0;
+ u32 val = 0;
struct mt7621_pcie_port *port;
list_for_each_entry(port, &pcie->ports, list) {
@@ -728,15 +545,15 @@ static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie)
return -1;
/*
- * pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num
- * 3'b000 x x x
- * 3'b001 x x 0
- * 3'b010 x 0 x
- * 3'b011 x 1 0
- * 3'b100 0 x x
- * 3'b101 1 x 0
- * 3'b110 1 0 x
- * 3'b111 2 1 0
+ * pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num
+ * 3'b000 x x x
+ * 3'b001 x x 0
+ * 3'b010 x 0 x
+ * 3'b011 x 1 0
+ * 3'b100 0 x x
+ * 3'b101 1 x 0
+ * 3'b110 1 0 x
+ * 3'b111 2 1 0
*/
switch (pcie_link_status) {
case 2:
@@ -848,9 +665,6 @@ static int mt7621_pci_probe(struct platform_device *pdev)
return 0;
}
- pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE);
- pcie_write(pcie, RALINK_PCI_IO_MAP_BASE, RALINK_PCI_IOBASE);
-
mt7621_pcie_enable_ports(pcie);
err = mt7621_pci_parse_request_of_pci_ranges(pcie);
diff --git a/drivers/staging/mt7621-pinctrl/Kconfig b/drivers/staging/mt7621-pinctrl/Kconfig
index 37cf9c3273be..fc3612711307 100644
--- a/drivers/staging/mt7621-pinctrl/Kconfig
+++ b/drivers/staging/mt7621-pinctrl/Kconfig
@@ -2,3 +2,4 @@ config PINCTRL_RT2880
bool "RT2800 pinctrl driver for RALINK/Mediatek SOCs"
depends on RALINK
select PINMUX
+ select GENERIC_PINCONF
diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
index aa98fbb17013..9b52d44abef1 100644
--- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
+++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
@@ -73,48 +74,12 @@ static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev,
return 0;
}
-static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
- struct device_node *np_config,
- struct pinctrl_map **map,
- unsigned int *num_maps)
-{
- struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
- struct property *prop;
- const char *function_name, *group_name;
- int ret;
- int ngroups = 0;
- unsigned int reserved_maps = 0;
-
- for_each_node_with_property(np_config, "group")
- ngroups++;
-
- *map = NULL;
- ret = pinctrl_utils_reserve_map(pctrldev, map, &reserved_maps,
- num_maps, ngroups);
- if (ret) {
- dev_err(p->dev, "can't reserve map: %d\n", ret);
- return ret;
- }
-
- of_property_for_each_string(np_config, "group", prop, group_name) {
- ret = pinctrl_utils_add_map_mux(pctrldev, map, &reserved_maps,
- num_maps, group_name,
- function_name);
- if (ret) {
- dev_err(p->dev, "can't add map: %d\n", ret);
- return ret;
- }
- }
-
- return 0;
-}
-
static const struct pinctrl_ops rt2880_pctrl_ops = {
.get_groups_count = rt2880_get_group_count,
.get_group_name = rt2880_get_group_name,
.get_group_pins = rt2880_get_group_pins,
- .dt_node_to_map = rt2880_pinctrl_dt_node_to_map,
- .dt_free_map = pinctrl_utils_free_map,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
};
static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev)
@@ -385,7 +350,6 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") {
const __be32 *ngpio, *gpiobase;
struct pinctrl_gpio_range *range;
- char *name;
if (!of_device_is_available(np))
continue;
@@ -397,9 +361,10 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
return -EINVAL;
}
- range = devm_kzalloc(p->dev, sizeof(*range) + 4, GFP_KERNEL);
- range->name = name = (char *) &range[1];
- sprintf(name, "pio");
+ range = devm_kzalloc(p->dev, sizeof(*range), GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+ range->name = "pio";
range->npins = __be32_to_cpu(*ngpio);
range->base = __be32_to_cpu(*gpiobase);
range->pin_base = range->base;
diff --git a/drivers/staging/mt7621-spi/spi-mt7621.c b/drivers/staging/mt7621-spi/spi-mt7621.c
index 513b6e79b985..b509f9fe3346 100644
--- a/drivers/staging/mt7621-spi/spi-mt7621.c
+++ b/drivers/staging/mt7621-spi/spi-mt7621.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* spi-mt7621.c -- MediaTek MT7621 SPI controller driver
*
@@ -8,34 +9,23 @@
* Some parts are based on spi-orion.c:
* Author: Shadi Ammouri <shadi@marvell.com>
* Copyright (C) 2007-2008 Marvell Ltd.
- *
- * 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/init.h>
-#include <linux/module.h>
#include <linux/clk.h>
-#include <linux/err.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/reset.h>
#include <linux/spi/spi.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/swab.h>
-
-#include <ralink_regs.h>
-#define SPI_BPW_MASK(bits) BIT((bits) - 1)
+#define DRIVER_NAME "spi-mt7621"
-#define DRIVER_NAME "spi-mt7621"
/* in usec */
-#define RALINK_SPI_WAIT_MAX_LOOP 2000
+#define RALINK_SPI_WAIT_MAX_LOOP 2000
/* SPISTAT register bit field */
-#define SPISTAT_BUSY BIT(0)
+#define SPISTAT_BUSY BIT(0)
#define MT7621_SPI_TRANS 0x00
#define SPITRANS_BUSY BIT(16)
@@ -46,17 +36,21 @@
#define SPI_CTL_TX_RX_CNT_MASK 0xff
#define SPI_CTL_START BIT(8)
-#define MT7621_SPI_POLAR 0x38
#define MT7621_SPI_MASTER 0x28
+#define MASTER_MORE_BUFMODE BIT(2)
+#define MASTER_FULL_DUPLEX BIT(10)
+#define MASTER_RS_CLK_SEL GENMASK(27, 16)
+#define MASTER_RS_CLK_SEL_SHIFT 16
+#define MASTER_RS_SLAVE_SEL GENMASK(31, 29)
+
#define MT7621_SPI_MOREBUF 0x2c
+#define MT7621_SPI_POLAR 0x38
#define MT7621_SPI_SPACE 0x3c
#define MT7621_CPHA BIT(5)
#define MT7621_CPOL BIT(4)
#define MT7621_LSB_FIRST BIT(3)
-struct mt7621_spi;
-
struct mt7621_spi {
struct spi_master *master;
void __iomem *base;
@@ -87,9 +81,13 @@ static void mt7621_spi_reset(struct mt7621_spi *rs)
{
u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER);
- master |= 7 << 29;
- master |= 1 << 2;
- master &= ~(1 << 10);
+ /*
+ * Select SPI device 7, enable "more buffer mode" and disable
+ * full-duplex (only half-duplex really works on this chip
+ * reliably)
+ */
+ master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE;
+ master &= ~MASTER_FULL_DUPLEX;
mt7621_spi_write(rs, MT7621_SPI_MASTER, master);
rs->pending_write = 0;
@@ -125,18 +123,18 @@ static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed)
rate = 2;
reg = mt7621_spi_read(rs, MT7621_SPI_MASTER);
- reg &= ~(0xfff << 16);
- reg |= (rate - 2) << 16;
+ reg &= ~MASTER_RS_CLK_SEL;
+ reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT;
rs->speed = speed;
reg &= ~MT7621_LSB_FIRST;
if (spi->mode & SPI_LSB_FIRST)
reg |= MT7621_LSB_FIRST;
- /* This SPI controller seems to be tested on SPI flash only
- * and some bits are swizzled under other SPI modes probably
- * due to incorrect wiring inside the silicon. Only mode 0
- * works correctly.
+ /*
+ * This SPI controller seems to be tested on SPI flash only and some
+ * bits are swizzled under other SPI modes probably due to incorrect
+ * wiring inside the silicon. Only mode 0 works correctly.
*/
reg &= ~(MT7621_CPHA | MT7621_CPOL);
@@ -165,9 +163,10 @@ static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
int rx_len, u8 *buf)
{
- /* Combine with any pending write, and perform one or
- * more half-duplex transactions reading 'len' bytes.
- * Data to be written is already in MT7621_SPI_DATA*
+ /*
+ * Combine with any pending write, and perform one or more half-duplex
+ * transactions reading 'len' bytes. Data to be written is already in
+ * MT7621_SPI_DATA.
*/
int tx_len = rs->pending_write;
@@ -197,6 +196,7 @@ static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
*buf++ = val & 0xff;
val >>= 8;
}
+
rx_len -= i;
}
}
@@ -290,6 +290,7 @@ static int mt7621_spi_transfer_one_message(struct spi_master *master,
mt7621_spi_flush(rs);
mt7621_spi_set_cs(spi, 0);
+
msg_done:
m->status = status;
spi_finalize_current_message(master);
@@ -330,6 +331,7 @@ static int mt7621_spi_probe(struct platform_device *pdev)
int status = 0;
struct clk *clk;
struct mt7621_spi_ops *ops;
+ int ret;
match = of_match_device(mt7621_spi_match, &pdev->dev);
if (!match)
@@ -353,7 +355,7 @@ static int mt7621_spi_probe(struct platform_device *pdev)
return status;
master = spi_alloc_master(&pdev->dev, sizeof(*rs));
- if (master == NULL) {
+ if (!master) {
dev_info(&pdev->dev, "master allocation failed\n");
return -ENOMEM;
}
@@ -377,7 +379,11 @@ static int mt7621_spi_probe(struct platform_device *pdev)
rs->pending_write = 0;
dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
- device_reset(&pdev->dev);
+ ret = device_reset(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "SPI reset failed!\n");
+ return ret;
+ }
mt7621_spi_reset(rs);
diff --git a/drivers/staging/netlogic/Kconfig b/drivers/staging/netlogic/Kconfig
index d660de51b541..c25a00dd2d5f 100644
--- a/drivers/staging/netlogic/Kconfig
+++ b/drivers/staging/netlogic/Kconfig
@@ -2,6 +2,6 @@ config NETLOGIC_XLR_NET
tristate "Netlogic XLR/XLS network device"
depends on CPU_XLR
select PHYLIB
- ---help---
+ help
This driver support Netlogic XLR/XLS on chip gigabit
Ethernet.
diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c
index abf4c71ee66b..8be9d0b0c22c 100644
--- a/drivers/staging/netlogic/platform_net.c
+++ b/drivers/staging/netlogic/platform_net.c
@@ -1,36 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * 1. Redistributions of source code must retain the above copyright
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the Broadcom
- * license below:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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 <linux/device.h>
@@ -107,8 +78,9 @@ static struct platform_device *gmac_controller2_init(void *gmac0_addr)
.dev.platform_data = &ndata1,
};
- gmac4_addr = ioremap(CPHYSADDR(
- nlm_mmio_base(NETLOGIC_IO_GMAC_4_OFFSET)), 0xfff);
+ gmac4_addr =
+ ioremap(CPHYSADDR(nlm_mmio_base(NETLOGIC_IO_GMAC_4_OFFSET)),
+ 0xfff);
ndata1.serdes_addr = gmac4_addr;
ndata1.pcs_addr = gmac4_addr;
ndata1.mii_addr = gmac0_addr;
@@ -134,8 +106,9 @@ static void xls_gmac_init(void)
{
int mac;
struct platform_device *xlr_net_dev1;
- void __iomem *gmac0_addr = ioremap(CPHYSADDR(
- nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)), 0xfff);
+ void __iomem *gmac0_addr =
+ ioremap(CPHYSADDR(nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)),
+ 0xfff);
static struct xlr_net_data ndata0 = {
.rfr_station = FMN_STNID_GMACRFR_0,
@@ -153,8 +126,9 @@ static void xls_gmac_init(void)
ndata0.mii_addr = gmac0_addr;
/* Passing GPIO base for serdes init. Only needed on sgmii ports */
- gpio_addr = ioremap(CPHYSADDR(
- nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET)), 0xfff);
+ gpio_addr =
+ ioremap(CPHYSADDR(nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET)),
+ 0xfff);
ndata0.gpio_addr = gpio_addr;
ndata0.cpu_mask = nlm_current_node()->coremask;
@@ -214,8 +188,9 @@ static void xlr_gmac_init(void)
.id = 0,
.dev.platform_data = &ndata0,
};
- ndata0.mii_addr = ioremap(CPHYSADDR(
- nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)), 0xfff);
+ ndata0.mii_addr =
+ ioremap(CPHYSADDR(nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)),
+ 0xfff);
ndata0.cpu_mask = nlm_current_node()->coremask;
diff --git a/drivers/staging/netlogic/platform_net.h b/drivers/staging/netlogic/platform_net.h
index e1b27f649590..f152d84099a2 100644
--- a/drivers/staging/netlogic/platform_net.h
+++ b/drivers/staging/netlogic/platform_net.h
@@ -1,35 +1,7 @@
-/*
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+ *
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the Broadcom
- * license below:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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.
*/
#define PORTS_PER_CONTROLLER 4
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
index 4e6611e4c59b..8554fcf4321b 100644
--- a/drivers/staging/netlogic/xlr_net.c
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -1,36 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the Broadcom
- * license below:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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 <linux/phy.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
diff --git a/drivers/staging/netlogic/xlr_net.h b/drivers/staging/netlogic/xlr_net.h
index f76e16cfd15d..518ea809b8fa 100644
--- a/drivers/staging/netlogic/xlr_net.h
+++ b/drivers/staging/netlogic/xlr_net.h
@@ -1,36 +1,9 @@
-/*
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+ *
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the Broadcom
- * license below:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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.
*/
+
/* #define MAC_SPLIT_MODE */
#define MAC_SPACING 0x400
diff --git a/drivers/staging/octeon-usb/octeon-hcd.h b/drivers/staging/octeon-usb/octeon-hcd.h
index 769c36cf6614..ae7ae50071ae 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.h
+++ b/drivers/staging/octeon-usb/octeon-hcd.h
@@ -1797,7 +1797,7 @@ union cvmx_usbnx_usbp_ctl_status {
* This is a test signal. When the USB Core is
* powered up (not in Susned Mode), an automatic
* tester can use this to disable phy_clock and
- * free_clk, then re-eanable them with an aligned
+ * free_clk, then re-enable them with an aligned
* phase.
* '1': The phy_clk and free_clk outputs are
* disabled. "0": The phy_clock and free_clk outputs
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 2848fa71a33d..d6248eecf123 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -170,7 +170,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
return -ENODEV;
priv->last_link = 0;
- phy_start_aneg(phydev);
+ phy_start(phydev);
return 0;
no_phy:
diff --git a/drivers/staging/ralink-gdma/Kconfig b/drivers/staging/ralink-gdma/Kconfig
new file mode 100644
index 000000000000..a12b2c672d48
--- /dev/null
+++ b/drivers/staging/ralink-gdma/Kconfig
@@ -0,0 +1,6 @@
+config DMA_RALINK
+ tristate "RALINK DMA support"
+ depends on RALINK && !SOC_RT288X
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+
diff --git a/drivers/staging/ralink-gdma/Makefile b/drivers/staging/ralink-gdma/Makefile
new file mode 100644
index 000000000000..5d917e0729bb
--- /dev/null
+++ b/drivers/staging/ralink-gdma/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o
+
+ccflags-y += -I$(srctree)/drivers/dma
diff --git a/drivers/staging/mt7621-dma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c
index 792a63bd55d4..d78042eba6dd 100644
--- a/drivers/staging/mt7621-dma/ralink-gdma.c
+++ b/drivers/staging/ralink-gdma/ralink-gdma.c
@@ -821,9 +821,9 @@ static int gdma_dma_probe(struct platform_device *pdev)
return -EINVAL;
data = (struct gdma_data *) match->data;
- dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev) +
- (sizeof(struct gdma_dmaengine_chan) * data->chancnt),
- GFP_KERNEL);
+ dma_dev = devm_kzalloc(&pdev->dev,
+ struct_size(dma_dev, chan, data->chancnt),
+ GFP_KERNEL);
if (!dma_dev) {
dev_err(&pdev->dev, "alloc dma device failed\n");
return -EINVAL;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 1f232ba6651c..94c9d9f8ee5c 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -82,7 +82,7 @@ static void update_BCNTIM(struct adapter *padapter)
/* calculate head_len */
offset = _FIXED_IE_LENGTH_;
- offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
+ offset += pnetwork_mlmeext->ssid.ssid_length + 2;
/* get supported rates len */
p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_,
@@ -785,9 +785,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
/* SSID */
p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
if (p && ie_len > 0) {
- memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
- pbss_network->Ssid.SsidLength = ie_len;
+ memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(pbss_network->ssid.ssid, (p + 2), ie_len);
+ pbss_network->ssid.ssid_length = ie_len;
}
/* channel */
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 407f65cf7150..83a2e58aef53 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -263,7 +263,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
int i;
for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (ssid[i].SsidLength) {
+ if (ssid[i].ssid_length) {
memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
psurveyPara->ssid_num++;
}
@@ -316,10 +316,10 @@ u8 rtw_createbss_cmd(struct adapter *padapter)
led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
- if (pmlmepriv->assoc_ssid.SsidLength == 0)
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
else
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
if (!pcmd) {
@@ -358,10 +358,10 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
- if (pmlmepriv->assoc_ssid.SsidLength == 0)
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
else
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.ssid));
pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
if (!pcmd) {
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index b7be71f904ed..51c3dd6d7ffb 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -88,7 +88,9 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf)
if (!efuseTbl)
return;
- tmp = kzalloc(EFUSE_MAX_SECTION_88E * (sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16)), GFP_KERNEL);
+ tmp = kcalloc(EFUSE_MAX_SECTION_88E,
+ sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16),
+ GFP_KERNEL);
if (!tmp) {
DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
goto eFuseWord_failed;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index 5c4ff81987bd..094e8e78f0e8 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -234,7 +234,7 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv)
ie += 2;
/* SSID */
- ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
+ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz);
/* supported rates */
if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
@@ -927,7 +927,7 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
if (pbuf && (wpa_ielen > 0)) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_ielen: %d", __func__, wpa_ielen));
- if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
+ if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
pnetwork->BcnInfo.group_cipher = group_cipher;
pnetwork->BcnInfo.is_8021x = is8021x;
@@ -940,7 +940,7 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
if (pbuf && (wpa_ielen > 0)) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n"));
- if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
+ if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE OK!!!\n"));
pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
pnetwork->BcnInfo.group_cipher = group_cipher;
@@ -975,9 +975,9 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork)
pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
}
rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
if (rsn_len > 0) {
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
index 0b3eb0b40975..7d56767cdff6 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -77,7 +77,7 @@ u8 rtw_do_join(struct adapter *padapter)
pibss = padapter->registrypriv.dev_network.MacAddress;
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(padapter);
@@ -208,7 +208,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
struct wlan_network *pnetwork = &pmlmepriv->cur_network;
DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
- ssid->Ssid, get_fwstate(pmlmepriv));
+ ssid->ssid, get_fwstate(pmlmepriv));
if (!padapter->hw_init_completed) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
@@ -229,8 +229,8 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
- if (pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength &&
- !memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength)) {
+ if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length &&
+ !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) {
if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
("Set SSID is the same ssid, fw_state = 0x%08x\n",
@@ -257,8 +257,8 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
}
} else {
RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n"));
- RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength));
- RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->ssid, (unsigned int)ssid->ssid_length));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.ssid, (unsigned int)pmlmepriv->assoc_ssid.ssid_length));
rtw_disassoc_cmd(padapter, 0, true);
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 714f7a70ed64..ca0cf8a86671 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -300,8 +300,8 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
{
- return (a->Ssid.SsidLength == b->Ssid.SsidLength) &&
- !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
+ return (a->ssid.ssid_length == b->ssid.ssid_length) &&
+ !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length);
}
int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
@@ -315,9 +315,9 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
s_cap = le16_to_cpu(le_scap);
d_cap = le16_to_cpu(le_dcap);
- return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
+ return ((src->ssid.ssid_length == dst->ssid.ssid_length) &&
(!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) &&
- (!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) &&
+ (!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length)) &&
((s_cap & WLAN_CAPABILITY_IBSS) ==
(d_cap & WLAN_CAPABILITY_IBSS)) &&
((s_cap & WLAN_CAPABILITY_ESS) ==
@@ -558,7 +558,7 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
pnetwork = (struct wlan_bssid_ex *)pbuf;
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
- ("%s, ssid=%s\n", __func__, pnetwork->Ssid.Ssid));
+ ("%s, ssid=%s\n", __func__, pnetwork->ssid.ssid));
len = get_wlan_bssid_ex_sz(pnetwork);
if (len > (sizeof(struct wlan_bssid_ex))) {
@@ -587,8 +587,8 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
/* lock pmlmepriv->lock when you accessing network_q */
if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- if (pnetwork->Ssid.Ssid[0] == 0)
- pnetwork->Ssid.SsidLength = 0;
+ if (pnetwork->ssid.ssid[0] == 0)
+ pnetwork->ssid.ssid_length = 0;
rtw_add_network(adapter, pnetwork);
}
@@ -636,7 +636,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
rtw_generate_random_ibss(pibss);
@@ -741,7 +741,7 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
("tgt_network->network.MacAddress=%pM ssid=%s\n",
- tgt_network->network.MacAddress, tgt_network->network.Ssid.Ssid));
+ tgt_network->network.MacAddress, tgt_network->network.ssid.ssid));
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
struct sta_info *psta;
@@ -975,10 +975,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
rtw_get_encrypt_decrypt_from_registrypriv(adapter);
- if (pmlmepriv->assoc_ssid.SsidLength == 0)
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n"));
else
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
@@ -1279,7 +1279,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
@@ -1422,9 +1422,9 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
}
/* check ssid, if needed */
- if (pmlmepriv->assoc_ssid.SsidLength) {
- if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength ||
- memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength))
+ if (pmlmepriv->assoc_ssid.ssid_length) {
+ if (competitor->network.ssid.ssid_length != pmlmepriv->assoc_ssid.ssid_length ||
+ memcmp(competitor->network.ssid.ssid, pmlmepriv->assoc_ssid.ssid, pmlmepriv->assoc_ssid.ssid_length))
goto exit;
}
@@ -1445,8 +1445,8 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
if (updated) {
DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n",
pmlmepriv->assoc_by_bssid,
- pmlmepriv->assoc_ssid.Ssid,
- (*candidate)->network.Ssid.Ssid,
+ pmlmepriv->assoc_ssid.ssid,
+ (*candidate)->network.ssid.ssid,
(*candidate)->network.MacAddress,
(int)(*candidate)->network.Rssi);
DBG_88E("[to_roaming:%u]\n", pmlmepriv->to_roaming);
@@ -1493,7 +1493,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
goto exit;
} else {
DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__,
- candidate->network.Ssid.Ssid, candidate->network.MacAddress,
+ candidate->network.ssid.ssid, candidate->network.MacAddress,
candidate->network.Configuration.DSConfig);
}
@@ -1772,7 +1772,7 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter)
memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
- memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config);
pdev_network->Configuration.BeaconPeriod = 100;
@@ -2049,9 +2049,9 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
if (pmlmepriv->to_roaming > 0) {
DBG_88E("roaming from %s(%pM length:%d\n",
- pnetwork->network.Ssid.Ssid, pnetwork->network.MacAddress,
- pnetwork->network.Ssid.SsidLength);
- memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
+ pnetwork->network.ssid.ssid, pnetwork->network.MacAddress,
+ pnetwork->network.ssid.ssid_length);
+ memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid));
pmlmepriv->assoc_by_bssid = false;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index 7a36661ebbed..8f28aefbe6f9 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -402,7 +402,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms)
pattrib->pktlen += 2;
/* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
@@ -562,7 +562,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da)
/* below for ad-hoc mode */
/* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
@@ -652,7 +652,7 @@ static int issue_probereq(struct adapter *padapter,
pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
if (pssid)
- pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->ssid_length, pssid->ssid, &pattrib->pktlen);
else
pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
@@ -1059,7 +1059,7 @@ static void issue_assocreq(struct adapter *padapter)
pattrib->pktlen += 2;
/* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &pattrib->pktlen);
/* supported rate & extended supported rate */
@@ -1929,7 +1929,7 @@ static void site_survey(struct adapter *padapter)
int i;
for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
+ if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
/* todo: to issue two probe req??? */
issue_probereq(padapter,
&(pmlmeext->sitesurvey_res.ssid[i]),
@@ -2071,10 +2071,10 @@ static u8 collect_bss_info(struct adapter *padapter,
DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
return _FAIL;
}
- memcpy(bssid->Ssid.Ssid, (p + 2), len);
- bssid->Ssid.SsidLength = len;
+ memcpy(bssid->ssid.ssid, (p + 2), len);
+ bssid->ssid.ssid_length = len;
} else {
- bssid->Ssid.SsidLength = 0;
+ bssid->ssid.ssid_length = 0;
}
memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
@@ -2526,7 +2526,7 @@ static unsigned int OnProbeReq(struct adapter *padapter,
/* check (wildcard) SSID */
if (p) {
- if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
+ if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length)) ||
(ielen == 0 && pmlmeinfo->hidden_ssid_mode))
return _SUCCESS;
@@ -2975,10 +2975,10 @@ static unsigned int OnAssocReq(struct adapter *padapter,
goto OnAssocReqFail;
} else {
/* check if ssid match */
- if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
+ if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length))
status = _STATS_FAILURE_;
- if (ie_len != cur->Ssid.SsidLength)
+ if (ie_len != cur->ssid.ssid_length)
status = _STATS_FAILURE_;
}
@@ -4658,7 +4658,7 @@ void linked_status_chk(struct adapter *padapter)
}
if (rx_chk != _SUCCESS)
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
+ issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, psta->hwaddr, 3, 1);
if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
@@ -4674,15 +4674,15 @@ void linked_status_chk(struct adapter *padapter)
if (rx_chk != _SUCCESS) {
if (pmlmeext->retry == 0) {
issue_probereq(padapter,
- &pmlmeinfo->network.Ssid,
+ &pmlmeinfo->network.ssid,
pmlmeinfo->network.MacAddress,
false);
issue_probereq(padapter,
- &pmlmeinfo->network.Ssid,
+ &pmlmeinfo->network.ssid,
pmlmeinfo->network.MacAddress,
false);
issue_probereq(padapter,
- &pmlmeinfo->network.Ssid,
+ &pmlmeinfo->network.ssid,
pmlmeinfo->network.MacAddress,
false);
}
@@ -5136,11 +5136,11 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
pmlmeext->sitesurvey_res.channel_idx = 0;
for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pparm->ssid[i].SsidLength) {
- memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
- pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
+ if (pparm->ssid[i].ssid_length) {
+ memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
} else {
- pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
}
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
index 364d6ea14bf8..2f90f60f1681 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -154,7 +154,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
- crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+ crypto_ops = lib80211_get_crypto_ops("WEP");
if (!crypto_ops)
return;
@@ -210,7 +210,7 @@ int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
void *crypto_private = NULL;
int status = _SUCCESS;
const int keyindex = prxattrib->key_index;
- struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+ struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP");
char iv[4], icv[4];
if (!crypto_ops) {
@@ -1291,7 +1291,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
void *crypto_private = NULL;
u8 *key, *pframe = skb->data;
- struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("CCMP"), "lib80211_crypt_ccmp");
+ struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP");
struct security_priv *psecuritypriv = &padapter->securitypriv;
char iv[8], icv[8];
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 5f9c9de1f1da..4480deef95a1 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -935,17 +935,17 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
if (ssid_len > NDIS_802_11_LENGTH_SSID)
ssid_len = 0;
}
- memcpy(bssid->Ssid.Ssid, (p + 2), ssid_len);
- bssid->Ssid.SsidLength = ssid_len;
+ memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
+ bssid->ssid.ssid_length = ssid_len;
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
- "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid,
- bssid->Ssid.SsidLength, cur_network->network.Ssid.Ssid,
- cur_network->network.Ssid.SsidLength));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.ssid.ssid:%s bssid.ssid.ssid_length:%d "
+ "cur_network->network.ssid.ssid:%s len:%d\n", __func__, bssid->ssid.ssid,
+ bssid->ssid.ssid_length, cur_network->network.ssid.ssid,
+ cur_network->network.ssid.ssid_length));
- if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
- bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) {
- if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */
+ if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
+ bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) {
+ if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) { /* not hidden ssid */
DBG_88E("%s(), SSID is not match return FAIL\n", __func__);
goto _mismatch;
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index 3b1ccd138c3f..1723a47a96b4 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -626,7 +626,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
if (pframe[1] & 2) /* From Ds == 1 */
rtw_secmicappend(&micdata, &pframe[24], 6);
else
- rtw_secmicappend(&micdata, &pframe[10], 6);
+ rtw_secmicappend(&micdata, &pframe[10], 6);
} else { /* ToDS == 0 */
rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */
if (pframe[1] & 2) /* From Ds == 1 */
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
index 1165ee278536..ba3c3e5a8216 100644
--- a/drivers/staging/rtl8188eu/hal/odm.c
+++ b/drivers/staging/rtl8188eu/hal/odm.c
@@ -209,17 +209,8 @@ void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm)
void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue)
{
- /* Hook call by reference pointer. */
- switch (CmnInfo) {
- /* Dynamic call by reference pointer. */
- case ODM_CMNINFO_STA_STATUS:
+ if (CmnInfo == ODM_CMNINFO_STA_STATUS)
pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
- break;
- /* To remove the compiler warning, must add an empty default statement to handle the other values. */
- default:
- /* do nothing */
- break;
- }
}
void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index 7022221136f6..47352f210c0b 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -22,7 +22,7 @@
static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
{
u8 read_down = false;
- int retry_cnts = 100;
+ int retry_cnts = 100;
u8 valid;
@@ -118,7 +118,6 @@ exit:
void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
{
struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv;
-
u8 macid, init_rate, raid, shortGIrate = false;
macid = arg&0x1f;
@@ -211,9 +210,9 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
struct ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u32 rate_len, pktlen;
- struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
pwlanhdr = (struct ieee80211_hdr *)pframe;
@@ -222,7 +221,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
*(fctrl) = 0;
ether_addr_copy(pwlanhdr->addr1, bc_addr);
- ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)));
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
@@ -257,7 +256,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
/* below for ad-hoc mode */
/* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
@@ -294,10 +293,10 @@ _ConstructBeacon:
static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
{
struct ieee80211_hdr *pwlanhdr;
- struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
__le16 *fctrl;
- struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
pwlanhdr = (struct ieee80211_hdr *)pframe;
@@ -314,7 +313,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
/* TA. */
- ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)));
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
*pLength = 16;
}
@@ -331,10 +330,10 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
__le16 *fctrl;
u32 pktlen;
struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
pwlanhdr = (struct ieee80211_hdr *)pframe;
@@ -347,19 +346,19 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
case Ndis802_11Infrastructure:
SetToDs(fctrl);
ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)));
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
ether_addr_copy(pwlanhdr->addr3, StaAddr);
break;
case Ndis802_11APMode:
SetFrDs(fctrl);
ether_addr_copy(pwlanhdr->addr1, StaAddr);
ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)));
+ ether_addr_copy(pwlanhdr->addr3, myid(&adapt->eeprompriv));
break;
case Ndis802_11IBSS:
default:
ether_addr_copy(pwlanhdr->addr1, StaAddr);
- ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)));
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
break;
}
@@ -391,13 +390,13 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u
__le16 *fctrl;
u8 *mac, *bssid;
u32 pktlen;
- struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
pwlanhdr = (struct ieee80211_hdr *)pframe;
- mac = myid(&(adapt->eeprompriv));
+ mac = myid(&adapt->eeprompriv);
bssid = cur_network->MacAddress;
fctrl = &pwlanhdr->frame_control;
@@ -434,11 +433,11 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
- struct mlme_ext_info *pmlmeinfo;
+ struct mlme_ext_info *pmlmeinfo;
u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
u32 NullDataLength, QosNullLength;
u8 *ReservedPagePacket;
@@ -458,7 +457,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
pxmitpriv = &adapt->xmitpriv;
pmlmeext = &adapt->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
- pnetwork = &(pmlmeinfo->network);
+ pnetwork = &pmlmeinfo->network;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
@@ -476,7 +475,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
PageNum += PageNeed;
adapt->HalData->FwRsvdPageStartOffset = PageNum;
- BufIndex += PageNeed*128;
+ BufIndex += PageNeed * 128;
/* 3 (2) ps-poll *1 page */
RsvdPageLoc.LocPsPoll = PageNum;
@@ -486,7 +485,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
PageNum += PageNeed;
- BufIndex += PageNeed*128;
+ BufIndex += PageNeed * 128;
/* 3 (3) null data * 1 page */
RsvdPageLoc.LocNullData = PageNum;
@@ -496,7 +495,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
- BufIndex += PageNeed*128;
+ BufIndex += PageNeed * 128;
/* 3 (4) probe response * 1page */
RsvdPageLoc.LocProbeRsp = PageNum;
@@ -506,7 +505,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
PageNum += PageNeed;
- BufIndex += PageNeed*128;
+ BufIndex += PageNeed * 128;
/* 3 (5) Qos null data */
RsvdPageLoc.LocQosNull = PageNum;
@@ -542,10 +541,10 @@ exit:
void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
{
struct hal_data_8188e *haldata = adapt->HalData;
- struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- bool bSendBeacon = false;
- bool bcn_valid = false;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ bool bSendBeacon = false;
+ bool bcn_valid = false;
u8 DLBcnCount = 0;
u32 poll = 0;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
index a72e069269b8..9e5f23392d58 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -440,14 +440,14 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
- if (pxmitbuf == NULL)
+ if (!pxmitbuf)
return false;
/* 3 1. pick up first frame */
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
- if (pxmitframe == NULL) {
+ if (!pxmitframe) {
/* no more xmit frame, release xmit buffer */
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
return false;
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
index 947481de9cb1..8245cea2feef 100644
--- a/drivers/staging/rtl8188eu/include/odm.h
+++ b/drivers/staging/rtl8188eu/include/odm.h
@@ -1045,7 +1045,6 @@ extern u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8];
void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal);
void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm);
-void odm_DIGbyRSSI_LPS(struct odm_dm_struct *pDM_Odm);
void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres);
bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI,
bool bForceUpdate, u8 *pRATRState);
diff --git a/drivers/staging/rtl8188eu/include/odm_hwconfig.h b/drivers/staging/rtl8188eu/include/odm_hwconfig.h
index 8cef32dc6350..2cd8a47a3673 100644
--- a/drivers/staging/rtl8188eu/include/odm_hwconfig.h
+++ b/drivers/staging/rtl8188eu/include/odm_hwconfig.h
@@ -93,18 +93,9 @@ struct phy_status_rpt {
#endif
};
-void odm_Init_RSSIForDM(struct odm_dm_struct *pDM_Odm);
-
void ODM_PhyStatusQuery(struct odm_dm_struct *pDM_Odm,
struct odm_phy_status_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_per_pkt_info *pPktinfo);
-void ODM_MacStatusQuery(struct odm_dm_struct *pDM_Odm,
- u8 *pMacStatus,
- u8 MacID,
- bool bPacketMatchBSSID,
- bool bPacketToSelf,
- bool bPacketBeacon);
-
#endif
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
index 0664d5f30a96..5e91b9428c16 100644
--- a/drivers/staging/rtl8188eu/include/wifi.h
+++ b/drivers/staging/rtl8188eu/include/wifi.h
@@ -791,18 +791,6 @@ enum ht_cap_ampdu_factor {
#define WPS_CM_SW_DISPLAY_P 0x2008
#define WPS_CM_LCD_DISPLAY_P 0x4008
-#define P2P_PRIVATE_IOCTL_SET_LEN 64
-
-enum P2P_PROTO_WK_ID {
- P2P_FIND_PHASE_WK = 0,
- P2P_RESTORE_STATE_WK = 1,
- P2P_PRE_TX_PROVDISC_PROCESS_WK = 2,
- P2P_PRE_TX_NEGOREQ_PROCESS_WK = 3,
- P2P_PRE_TX_INVITEREQ_PROCESS_WK = 4,
- P2P_AP_P2P_CH_SWITCH_PROCESS_WK = 5,
- P2P_RO_CH_WK = 6,
-};
-
/* =====================WFD Section===================== */
/* For Wi-Fi Display */
#define WFD_ATTR_DEVICE_INFO 0x00
diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h
index 5e13a6ddf083..8462c9c2fd39 100644
--- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h
+++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h
@@ -17,8 +17,8 @@
#define NDIS_802_11_RSSI long /* in dBm */
struct ndis_802_11_ssid {
- u32 SsidLength;
- u8 Ssid[32];
+ u32 ssid_length;
+ u8 ssid[32];
};
enum NDIS_802_11_NETWORK_TYPE {
@@ -180,7 +180,7 @@ struct wlan_bssid_ex {
u32 Length;
unsigned char MacAddress[ETH_ALEN];
u8 Reserved[2];/* 0]: IS beacon frame */
- struct ndis_802_11_ssid Ssid;
+ struct ndis_802_11_ssid ssid;
u32 Privacy;
NDIS_802_11_RSSI Rssi;/* in dBM,raw data ,get from PHY) */
enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index efaa1c779f4b..eaa4adb32a0d 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -116,8 +116,8 @@ static char *translate_scan(struct adapter *padapter,
/* Add the ESSID */
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
- iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
+ iwe.u.data.length = min_t(u16, pnetwork->network.ssid.ssid_length, 32);
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
/* parsing HT_CAP_IE */
p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length-12);
@@ -195,7 +195,7 @@ static char *translate_scan(struct adapter *padapter,
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
/*Add basic and extended rates */
max_rate = 0;
@@ -235,7 +235,7 @@ static char *translate_scan(struct adapter *padapter,
u8 *p;
rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.ssid.ssid));
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
if (wpa_len > 0) {
@@ -1124,8 +1124,8 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
int len = min_t(int, req->essid_len,
IW_ESSID_MAX_SIZE);
- memcpy(ssid[0].Ssid, req->essid, len);
- ssid[0].SsidLength = len;
+ memcpy(ssid[0].ssid, req->essid, len);
+ ssid[0].ssid_length = len;
DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
@@ -1158,8 +1158,8 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
}
sec_len = *(pos++); len -= 1;
if (sec_len > 0 && sec_len <= len) {
- ssid[ssid_index].SsidLength = sec_len;
- memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
+ ssid[ssid_index].ssid_length = sec_len;
+ memcpy(ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length);
ssid_index++;
}
pos += sec_len;
@@ -1310,9 +1310,9 @@ static int rtw_wx_set_essid(struct net_device *dev,
DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = len;
- memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
+ ndis_ssid.ssid_length = len;
+ memcpy(ndis_ssid.ssid, extra, len);
+ src_ssid = ndis_ssid.ssid;
RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
spin_lock_bh(&queue->lock);
@@ -1324,14 +1324,14 @@ static int rtw_wx_set_essid(struct net_device *dev,
pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- dst_ssid = pnetwork->network.Ssid.Ssid;
+ dst_ssid = pnetwork->network.ssid.ssid;
RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
("rtw_wx_set_essid: dst_ssid =%s\n",
- pnetwork->network.Ssid.Ssid));
+ pnetwork->network.ssid.ssid));
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
- (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
+ if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) &&
+ (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) {
RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
("rtw_wx_set_essid: find match, set infra mode\n"));
@@ -1378,8 +1378,8 @@ static int rtw_wx_get_essid(struct net_device *dev,
if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
- len = pcur_bss->Ssid.SsidLength;
- memcpy(extra, pcur_bss->Ssid.Ssid, len);
+ len = pcur_bss->ssid.ssid_length;
+ memcpy(extra, pcur_bss->ssid.ssid, len);
} else {
len = 0;
*extra = 0;
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
index d5ceb3beabbc..9db11b16cb93 100644
--- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
@@ -13,7 +13,7 @@
void rtw_init_mlme_timer(struct adapter *padapter)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
timer_setup(&pmlmepriv->assoc_timer, _rtw_join_timeout_handler, 0);
timer_setup(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler, 0);
@@ -36,34 +36,38 @@ static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE];
void rtw_reset_securitypriv(struct adapter *adapter)
{
- u8 backup_index = 0;
- u8 backup_counter = 0x00;
- u32 backup_time = 0;
-
- if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
- /* 802.1x */
- /* We have to backup the PMK information for WiFi PMK Caching test item. */
- /* Backup the btkip_countermeasure information. */
- /* When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */
- memcpy(&backup_pmkid[0], &adapter->securitypriv.PMKIDList[0], sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- backup_index = adapter->securitypriv.PMKIDIndex;
- backup_counter = adapter->securitypriv.btkip_countermeasure;
- backup_time = adapter->securitypriv.btkip_countermeasure_time;
- memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv));
-
- /* Restore the PMK information to securitypriv structure for the following connection. */
- memcpy(&adapter->securitypriv.PMKIDList[0],
- &backup_pmkid[0],
- sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- adapter->securitypriv.PMKIDIndex = backup_index;
- adapter->securitypriv.btkip_countermeasure = backup_counter;
- adapter->securitypriv.btkip_countermeasure_time = backup_time;
- adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
- adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+ u8 backup_index;
+ u8 backup_counter;
+ u32 backup_time;
+ struct security_priv *psec_priv = &adapter->securitypriv;
+
+ if (psec_priv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
+ /* 802.1x
+ * We have to backup the PMK information for WiFi PMK Caching
+ * test item. Backup the btkip_countermeasure information. When
+ * the countermeasure is trigger, the driver have to disconnect
+ * with AP for 60 seconds.
+ */
+ memcpy(backup_pmkid, psec_priv->PMKIDList,
+ sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ backup_index = psec_priv->PMKIDIndex;
+ backup_counter = psec_priv->btkip_countermeasure;
+ backup_time = psec_priv->btkip_countermeasure_time;
+
+ memset(psec_priv, 0, sizeof(*psec_priv));
+
+ /* Restore the PMK information to securitypriv structure
+ * for the following connection.
+ */
+ memcpy(psec_priv->PMKIDList, backup_pmkid,
+ sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ psec_priv->PMKIDIndex = backup_index;
+ psec_priv->btkip_countermeasure = backup_counter;
+ psec_priv->btkip_countermeasure_time = backup_time;
+ psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
} else {
/* reset values in securitypriv */
- struct security_priv *psec_priv = &adapter->securitypriv;
-
psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
psec_priv->dot11PrivacyKeyIndex = 0;
@@ -76,15 +80,16 @@ void rtw_reset_securitypriv(struct adapter *adapter)
void rtw_os_indicate_disconnect(struct adapter *adapter)
{
- netif_carrier_off(adapter->pnetdev); /* Do it first for tx broadcast pkt after disconnection issue! */
+ /* Do it first for tx broadcast pkt after disconnection issue! */
+ netif_carrier_off(adapter->pnetdev);
rtw_indicate_wx_disassoc_event(adapter);
rtw_reset_securitypriv(adapter);
}
void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
{
- uint len;
- u8 *buff, *p, i;
+ uint len;
+ u8 *buff, *p, i;
union iwreq_data wrqu;
RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
@@ -99,14 +104,13 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
memset(buff, 0, IW_CUSTOM_MAX);
p = buff;
p += sprintf(p, "ASSOCINFO(ReqIEs =");
- len = sec_ie[1]+2;
+ len = sec_ie[1] + 2;
len = min_t(uint, len, IW_CUSTOM_MAX);
for (i = 0; i < len; i++)
p += sprintf(p, "%02x", sec_ie[i]);
p += sprintf(p, ")");
memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = p-buff;
- wrqu.data.length = min_t(__u16, wrqu.data.length, IW_CUSTOM_MAX);
+ wrqu.data.length = min_t(__u16, p - buff, IW_CUSTOM_MAX);
wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
kfree(buff);
}
@@ -119,7 +123,7 @@ void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
void init_mlme_ext_timer(struct adapter *padapter)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
timer_setup(&pmlmeext->survey_timer, survey_timer_hdl, 0);
timer_setup(&pmlmeext->link_timer, link_timer_hdl, 0);
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index abcce2240f15..8dde5a40e253 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -137,12 +137,12 @@ static int netdev_close(struct net_device *pnetdev);
static void loadparam(struct adapter *padapter, struct net_device *pnetdev)
{
- struct registry_priv *registry_par = &padapter->registrypriv;
+ struct registry_priv *registry_par = &padapter->registrypriv;
GlobalDebugLevel = rtw_debug;
- memcpy(registry_par->ssid.Ssid, "ANY", 3);
- registry_par->ssid.SsidLength = 3;
+ memcpy(registry_par->ssid.ssid, "ANY", 3);
+ registry_par->ssid.ssid_length = 3;
registry_par->channel = (u8)rtw_channel;
registry_par->wireless_mode = (u8)rtw_wireless_mode;
@@ -198,8 +198,8 @@ static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
{
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct recv_priv *precvpriv = &(padapter->recvpriv);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
padapter->stats.tx_packets = pxmitpriv->tx_pkts;
padapter->stats.rx_packets = precvpriv->rx_pkts;
@@ -248,7 +248,7 @@ static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev,
select_queue_fallback_t fallback)
{
- struct adapter *padapter = rtw_netdev_priv(dev);
+ struct adapter *padapter = rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
skb->priority = rtw_classify8021d(skb);
@@ -263,15 +263,15 @@ u16 rtw_recv_select_queue(struct sk_buff *skb)
{
struct iphdr *piphdr;
unsigned int dscp;
- __be16 eth_type;
+ __be16 eth_type;
u32 priority;
u8 *pdata = skb->data;
- memcpy(&eth_type, pdata+(ETH_ALEN<<1), 2);
+ memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
switch (eth_type) {
case htons(ETH_P_IP):
- piphdr = (struct iphdr *)(pdata+ETH_HLEN);
+ piphdr = (struct iphdr *)(pdata + ETH_HLEN);
dscp = piphdr->tos & 0xfc;
priority = dscp >> 5;
break;
@@ -286,7 +286,7 @@ static const struct net_device_ops rtw_netdev_ops = {
.ndo_open = netdev_open,
.ndo_stop = netdev_close,
.ndo_start_xmit = rtw_xmit_entry,
- .ndo_select_queue = rtw_select_queue,
+ .ndo_select_queue = rtw_select_queue,
.ndo_set_mac_address = rtw_net_set_mac_address,
.ndo_get_stats = rtw_net_get_stats,
.ndo_do_ioctl = rtw_ioctl,
@@ -323,7 +323,7 @@ struct net_device *rtw_init_netdev(struct adapter *old_padapter)
padapter->pnetdev = pnetdev;
DBG_88E("register rtw_netdev_ops to netdev_ops\n");
pnetdev->netdev_ops = &rtw_netdev_ops;
- pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */
+ pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
loadparam(padapter, pnetdev);
@@ -361,7 +361,7 @@ void rtw_stop_drv_threads(struct adapter *padapter)
static u8 rtw_init_default_value(struct adapter *padapter)
{
struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
@@ -431,7 +431,7 @@ u8 rtw_reset_drv_sw(struct adapter *padapter)
u8 rtw_init_drv_sw(struct adapter *padapter)
{
- u8 ret8 = _SUCCESS;
+ u8 ret8 = _SUCCESS;
RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw\n"));
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
index 2ea2af3286bc..7a090615dcbc 100644
--- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
@@ -84,7 +84,7 @@ static int rtw_android_get_rssi(struct net_device *net, char *command,
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
bytes_written += snprintf(&command[bytes_written], total_len,
"%s rssi %d",
- pcur_network->network.Ssid.Ssid,
+ pcur_network->network.ssid.ssid,
padapter->recvpriv.rssi);
}
return bytes_written;
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 28cbd6b3d26c..664d93a7f90d 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -35,6 +35,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
{USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
@@ -227,10 +228,10 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
check_fwstate(pmlmepriv, _FW_LINKED)) {
pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
__func__, __LINE__,
- pmlmepriv->cur_network.network.Ssid.Ssid,
+ pmlmepriv->cur_network.network.ssid.ssid,
pmlmepriv->cur_network.network.MacAddress,
- pmlmepriv->cur_network.network.Ssid.SsidLength,
- pmlmepriv->assoc_ssid.SsidLength);
+ pmlmepriv->cur_network.network.ssid.ssid_length,
+ pmlmepriv->assoc_ssid.ssid_length);
pmlmepriv->to_roaming = 1;
}
diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c
index a1c096124683..68f53013cb95 100644
--- a/drivers/staging/rtl8192e/dot11d.c
+++ b/drivers/staging/rtl8192e/dot11d.c
@@ -15,11 +15,11 @@
#include "dot11d.h"
struct channel_list {
- u8 Channel[32];
- u8 Len;
+ u8 channel[32];
+ u8 len;
};
-static struct channel_list ChannelPlan[] = {
+static struct channel_list channel_array[] = {
{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64,
149, 153, 157, 161, 165}, 24},
{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
@@ -44,130 +44,130 @@ static struct channel_list ChannelPlan[] = {
void dot11d_init(struct rtllib_device *ieee)
{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
+ struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
- pDot11dInfo->bEnabled = false;
+ dot11d_info->enabled = false;
- pDot11dInfo->State = DOT11D_STATE_NONE;
- pDot11dInfo->CountryIeLen = 0;
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1);
+ dot11d_info->state = DOT11D_STATE_NONE;
+ dot11d_info->country_len = 0;
+ memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
+ memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
RESET_CIE_WATCHDOG(ieee);
}
EXPORT_SYMBOL(dot11d_init);
-void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee)
+void dot11d_channel_map(u8 channel_plan, struct rtllib_device *ieee)
{
int i, max_chan = 14, min_chan = 1;
- ieee->bGlobalDomain = false;
+ ieee->global_domain = false;
- if (ChannelPlan[channel_plan].Len != 0) {
+ if (channel_array[channel_plan].len != 0) {
memset(GET_DOT11D_INFO(ieee)->channel_map, 0,
sizeof(GET_DOT11D_INFO(ieee)->channel_map));
- for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
- if (ChannelPlan[channel_plan].Channel[i] < min_chan ||
- ChannelPlan[channel_plan].Channel[i] > max_chan)
+ for (i = 0; i < channel_array[channel_plan].len; i++) {
+ if (channel_array[channel_plan].channel[i] < min_chan ||
+ channel_array[channel_plan].channel[i] > max_chan)
break;
- GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan
- [channel_plan].Channel[i]] = 1;
+ GET_DOT11D_INFO(ieee)->channel_map[channel_array
+ [channel_plan].channel[i]] = 1;
}
}
switch (channel_plan) {
case COUNTRY_CODE_GLOBAL_DOMAIN:
- ieee->bGlobalDomain = true;
+ ieee->global_domain = true;
for (i = 12; i <= 14; i++)
GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
- ieee->IbssStartChnl = 10;
+ ieee->bss_start_channel = 10;
ieee->ibss_maxjoin_chal = 11;
break;
case COUNTRY_CODE_WORLD_WIDE_13:
for (i = 12; i <= 13; i++)
GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
- ieee->IbssStartChnl = 10;
+ ieee->bss_start_channel = 10;
ieee->ibss_maxjoin_chal = 11;
break;
default:
- ieee->IbssStartChnl = 1;
+ ieee->bss_start_channel = 1;
ieee->ibss_maxjoin_chal = 14;
break;
}
}
-EXPORT_SYMBOL(Dot11d_Channelmap);
+EXPORT_SYMBOL(dot11d_channel_map);
-void Dot11d_Reset(struct rtllib_device *ieee)
+void dot11d_reset(struct rtllib_device *ieee)
{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
+ struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
u32 i;
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1);
+ memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
+ memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
for (i = 1; i <= 11; i++)
- (pDot11dInfo->channel_map)[i] = 1;
+ (dot11d_info->channel_map)[i] = 1;
for (i = 12; i <= 14; i++)
- (pDot11dInfo->channel_map)[i] = 2;
- pDot11dInfo->State = DOT11D_STATE_NONE;
- pDot11dInfo->CountryIeLen = 0;
+ (dot11d_info->channel_map)[i] = 2;
+ dot11d_info->state = DOT11D_STATE_NONE;
+ dot11d_info->country_len = 0;
RESET_CIE_WATCHDOG(ieee);
}
-void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
- u16 CoutryIeLen, u8 *pCoutryIe)
+void dot11d_update_country(struct rtllib_device *dev, u8 *address,
+ u16 country_len, u8 *country)
{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 i, j, NumTriples, MaxChnlNum;
- struct chnl_txpow_triple *pTriple;
-
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1);
- MaxChnlNum = 0;
- NumTriples = (CoutryIeLen - 3) / 3;
- pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3);
- for (i = 0; i < NumTriples; i++) {
- if (MaxChnlNum >= pTriple->FirstChnl) {
+ struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
+ u8 i, j, number_of_triples, max_channel_number;
+ struct chnl_txpow_triple *triple;
+
+ memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
+ memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
+ max_channel_number = 0;
+ number_of_triples = (country_len - 3) / 3;
+ triple = (struct chnl_txpow_triple *)(country + 3);
+ for (i = 0; i < number_of_triples; i++) {
+ if (max_channel_number >= triple->first_channel) {
netdev_info(dev->dev,
"%s: Invalid country IE, skip it......1\n",
__func__);
return;
}
- if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl +
- pTriple->NumChnls)) {
+ if (MAX_CHANNEL_NUMBER < (triple->first_channel +
+ triple->num_channels)) {
netdev_info(dev->dev,
"%s: Invalid country IE, skip it......2\n",
__func__);
return;
}
- for (j = 0; j < pTriple->NumChnls; j++) {
- pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
- pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] =
- pTriple->MaxTxPowerInDbm;
- MaxChnlNum = pTriple->FirstChnl + j;
+ for (j = 0; j < triple->num_channels; j++) {
+ dot11d_info->channel_map[triple->first_channel + j] = 1;
+ dot11d_info->max_tx_power_list[triple->first_channel + j] =
+ triple->max_tx_power;
+ max_channel_number = triple->first_channel + j;
}
- pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3);
+ triple = (struct chnl_txpow_triple *)((u8 *)triple + 3);
}
- UPDATE_CIE_SRC(dev, pTaddr);
+ UPDATE_CIE_SRC(dev, address);
- pDot11dInfo->CountryIeLen = CoutryIeLen;
- memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
- pDot11dInfo->State = DOT11D_STATE_LEARNED;
+ dot11d_info->country_len = country_len;
+ memcpy(dot11d_info->country_buffer, country, country_len);
+ dot11d_info->state = DOT11D_STATE_LEARNED;
}
-void DOT11D_ScanComplete(struct rtllib_device *dev)
+void dot11d_scan_complete(struct rtllib_device *dev)
{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
+ struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
- switch (pDot11dInfo->State) {
+ switch (dot11d_info->state) {
case DOT11D_STATE_LEARNED:
- pDot11dInfo->State = DOT11D_STATE_DONE;
+ dot11d_info->state = DOT11D_STATE_DONE;
break;
case DOT11D_STATE_DONE:
- Dot11d_Reset(dev);
+ dot11d_reset(dev);
break;
case DOT11D_STATE_NONE:
break;
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 7fa3c4d963c4..6d2b93acfa43 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -1,14 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/******************************************************************************
* Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
*
- * 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.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
* Contact Information:
* wlanfae <wlanfae@realtek.com>
******************************************************************************/
@@ -18,9 +11,9 @@
#include "rtllib.h"
struct chnl_txpow_triple {
- u8 FirstChnl;
- u8 NumChnls;
- u8 MaxTxPowerInDbm;
+ u8 first_channel;
+ u8 num_channels;
+ u8 max_tx_power;
};
enum dot11d_state {
@@ -30,62 +23,62 @@ enum dot11d_state {
};
/**
- * struct rt_dot11d_info * @CountryIeLen: value greater than 0 if
- * @CountryIeBuf contains valid country information element.
+ * struct rt_dot11d_info * @country_len: value greater than 0 if
+ * @country_buffer contains valid country information element.
* @channel_map: holds channel values
* 0 - invalid,
* 1 - valid (active scan),
* 2 - valid (passive scan)
- * @CountryIeSrcAddr - Source AP of the country IE
+ * @country_src_addr - Source AP of the country IE
*/
struct rt_dot11d_info {
- bool bEnabled;
+ bool enabled;
- u16 CountryIeLen;
- u8 CountryIeBuf[MAX_IE_LEN];
- u8 CountryIeSrcAddr[6];
- u8 CountryIeWatchdog;
+ u16 country_len;
+ u8 country_buffer[MAX_IE_LEN];
+ u8 country_src_addr[6];
+ u8 country_watchdog;
u8 channel_map[MAX_CHANNEL_NUMBER + 1];
- u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER + 1];
+ u8 max_tx_power_list[MAX_CHANNEL_NUMBER + 1];
- enum dot11d_state State;
+ enum dot11d_state state;
};
-static inline void cpMacAddr(unsigned char *des, unsigned char *src)
+static inline void copy_mac_addr(unsigned char *des, unsigned char *src)
{
memcpy(des, src, 6);
}
-#define GET_DOT11D_INFO(__pIeeeDev) \
- ((struct rt_dot11d_info *)((__pIeeeDev)->pDot11dInfo))
+#define GET_DOT11D_INFO(__ieee_dev) \
+ ((struct rt_dot11d_info *)((__ieee_dev)->dot11d_info))
-#define IS_DOT11D_ENABLE(__pIeeeDev) \
- (GET_DOT11D_INFO(__pIeeeDev)->bEnabled)
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) \
- (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
+#define IS_DOT11D_ENABLE(__ieee_dev) \
+ (GET_DOT11D_INFO(__ieee_dev)->enabled)
+#define IS_COUNTRY_IE_VALID(__ieee_dev) \
+ (GET_DOT11D_INFO(__ieee_dev)->country_len > 0)
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) \
+#define IS_EQUAL_CIE_SRC(__ieee_dev, __address) \
ether_addr_equal_unaligned( \
- GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) \
- cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+ GET_DOT11D_INFO(__ieee_dev)->country_src_addr, __address)
+#define UPDATE_CIE_SRC(__ieee_dev, __address) \
+ copy_mac_addr(GET_DOT11D_INFO(__ieee_dev)->country_src_addr, __address)
-#define GET_CIE_WATCHDOG(__pIeeeDev) \
- (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
-static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev)
+#define GET_CIE_WATCHDOG(__ieee_dev) \
+ (GET_DOT11D_INFO(__ieee_dev)->country_watchdog)
+static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__ieee_dev)
{
- GET_CIE_WATCHDOG(__pIeeeDev) = 0;
+ GET_CIE_WATCHDOG(__ieee_dev) = 0;
}
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
+#define UPDATE_CIE_WATCHDOG(__ieee_dev) (++GET_CIE_WATCHDOG(__ieee_dev))
void dot11d_init(struct rtllib_device *dev);
-void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee);
-void Dot11d_Reset(struct rtllib_device *dev);
-void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
- u16 CoutryIeLen, u8 *pCoutryIe);
-void DOT11D_ScanComplete(struct rtllib_device *dev);
+void dot11d_channel_map(u8 channel_plan, struct rtllib_device *ieee);
+void dot11d_reset(struct rtllib_device *dev);
+void dot11d_update_country(struct rtllib_device *dev, u8 *address,
+ u16 country_len, u8 *country);
+void dot11d_scan_complete(struct rtllib_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 1c6ed5b2a6f9..19bb04b3f097 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -660,9 +660,9 @@ static void _rtl92e_hwconfig(struct net_device *dev)
case WIRELESS_MODE_AUTO:
case WIRELESS_MODE_N_24G:
regBwOpMode = BW_OPMODE_20MHZ;
- regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
- RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
- regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
+ RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+ regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
break;
case WIRELESS_MODE_N_5G:
regBwOpMode = BW_OPMODE_5G;
@@ -961,7 +961,7 @@ static void _rtl92e_net_update(struct net_device *dev)
net = &priv->rtllib->current_network;
rtl92e_config_rate(dev, &rate_config);
priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
- priv->basic_rate = rate_config &= 0x15f;
+ priv->basic_rate = rate_config &= 0x15f;
rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 96f265eee007..253f1911a3f4 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -436,7 +436,7 @@ static int _rtl92e_qos_handle_probe_response(struct r8192_priv *priv,
network->qos_data.param_count)) {
network->qos_data.old_param_count =
network->qos_data.param_count;
- priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
+ priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
schedule_work(&priv->qos_activate);
RT_TRACE(COMP_QOS,
"QoS parameters change call qos_activate\n");
@@ -1049,7 +1049,7 @@ static short _rtl92e_get_channel_map(struct net_device *dev)
}
RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
dot11d_init(priv->rtllib);
- Dot11d_Channelmap(priv->ChannelPlan, priv->rtllib);
+ dot11d_channel_map(priv->ChannelPlan, priv->rtllib);
for (i = 1; i <= 11; i++)
(priv->rtllib->active_channel_map)[i] = 1;
(priv->rtllib->active_channel_map)[12] = 2;
@@ -1573,7 +1573,7 @@ static void _rtl92e_free_rx_ring(struct net_device *dev)
pci_unmap_single(priv->pdev,
*((dma_addr_t *)skb->cb),
priv->rxbuffersize, PCI_DMA_FROMDEVICE);
- kfree_skb(skb);
+ kfree_skb(skb);
}
pci_free_consistent(priv->pdev,
@@ -1728,8 +1728,7 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb)
MAX_DEV_ADDR_SIZE);
struct tx_desc *pdesc = NULL;
struct rtllib_hdr_1addr *header = NULL;
- u16 fc = 0, type = 0, stype = 0;
- bool multi_addr = false, broad_addr = false, uni_addr = false;
+ u16 fc = 0, type = 0;
u8 *pda_addr = NULL;
int idx;
u32 fwinfo_size = 0;
@@ -1747,22 +1746,14 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb)
header = (struct rtllib_hdr_1addr *)(((u8 *)skb->data) + fwinfo_size);
fc = le16_to_cpu(header->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
- stype = WLAN_FC_GET_STYPE(fc);
pda_addr = header->addr1;
if (is_broadcast_ether_addr(pda_addr))
- broad_addr = true;
+ priv->stats.txbytesbroadcast += skb->len - fwinfo_size;
else if (is_multicast_ether_addr(pda_addr))
- multi_addr = true;
- else
- uni_addr = true;
-
- if (uni_addr)
- priv->stats.txbytesunicast += skb->len - fwinfo_size;
- else if (multi_addr)
priv->stats.txbytesmulticast += skb->len - fwinfo_size;
else
- priv->stats.txbytesbroadcast += skb->len - fwinfo_size;
+ priv->stats.txbytesunicast += skb->len - fwinfo_size;
spin_lock_irqsave(&priv->irq_th_lock, flags);
ring = &priv->tx_ring[tcb_desc->queue_index];
@@ -2515,7 +2506,7 @@ static int _rtl92e_pci_probe(struct pci_dev *pdev,
if (dev_alloc_name(dev, ifname) < 0) {
RT_TRACE(COMP_INIT,
"Oops: devname already taken! Trying wlan%%d...\n");
- dev_alloc_name(dev, ifname);
+ dev_alloc_name(dev, ifname);
}
RT_TRACE(COMP_INIT, "Driver probe completed1\n");
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index 9bf95bd0ad13..157bcee34067 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -996,7 +996,7 @@ static void _rtl92e_dm_check_tx_power_tracking_tssi(struct net_device *dev)
tx_power_track_counter++;
- if (tx_power_track_counter >= 180) {
+ if (tx_power_track_counter >= 180) {
schedule_delayed_work(&priv->txpower_tracking_wq, 0);
tx_power_track_counter = 0;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 843e874b8a06..44e06cba7b7b 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -738,7 +738,7 @@ static int _rtl92e_wx_set_enc(struct net_device *dev,
else if (wrqu->encoding.length == 0xd) {
ieee->pairwise_key_type = KEY_TYPE_WEP104;
- rtl92e_enable_hw_security_config(dev);
+ rtl92e_enable_hw_security_config(dev);
rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104,
zero_addr[key_idx], 0, hwkey);
rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
@@ -1049,9 +1049,9 @@ static int _rtl92e_wx_set_promisc_mode(struct net_device *dev,
(bPromiscuousOn) ? (true) : (false);
ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame =
(bFilterSourceStationFrame) ? (true) : (false);
- (bPromiscuousOn) ?
- (rtllib_EnableIntelPromiscuousMode(dev, false)) :
- (rtllib_DisableIntelPromiscuousMode(dev, false));
+ (bPromiscuousOn) ?
+ (rtllib_EnableIntelPromiscuousMode(dev, false)) :
+ (rtllib_DisableIntelPromiscuousMode(dev, false));
netdev_info(dev,
"=======>%s(), on = %d, filter src sta = %d\n",
diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c
index 687dbb04ed2e..2d330d2bbf6d 100644
--- a/drivers/staging/rtl8192e/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c
@@ -139,7 +139,7 @@ static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
{
union delba_param_set DelbaParamSet;
struct sk_buff *skb = NULL;
- struct rtllib_hdr_3addr *Delba = NULL;
+ struct rtllib_hdr_3addr *Delba = NULL;
u8 *tag = NULL;
u16 len = 6 + ieee->tx_headroom;
@@ -316,7 +316,7 @@ OnADDBAReq_Fail:
int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
{
- struct rtllib_hdr_3addr *rsp = NULL;
+ struct rtllib_hdr_3addr *rsp = NULL;
struct ba_record *pPendingBA, *pAdmittedBA;
struct tx_ts_record *pTS = NULL;
u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
@@ -420,7 +420,7 @@ OnADDBARsp_Reject:
int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
{
- struct rtllib_hdr_3addr *delba = NULL;
+ struct rtllib_hdr_3addr *delba = NULL;
union delba_param_set *pDelBaParamSet = NULL;
u8 *dst = NULL;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index c01474a6db1e..61ebd12831c3 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -1560,11 +1560,11 @@ struct rtllib_device {
u16 scan_watch_dog;
/* map of allowed channels. 0 is dummy */
- void *pDot11dInfo;
- bool bGlobalDomain;
+ void *dot11d_info;
+ bool global_domain;
u8 active_channel_map[MAX_CHANNEL_NUMBER+1];
- u8 IbssStartChnl;
+ u8 bss_start_channel;
u8 ibss_maxjoin_chal;
int rate; /* current rate */
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
index f38f1f74fcd6..55da8c9dfe50 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
@@ -285,7 +285,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct rtllib_tkip_data *tkey = priv;
- int len;
+ int len;
u8 *pos;
struct rtllib_hdr_4addr *hdr;
struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index fa580ce1cf43..debc2e40af00 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -913,7 +913,7 @@ static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee,
rx_stats->bContainHTC = true;
}
- if (RTLLIB_QOS_HAS_SEQ(fc))
+ if (RTLLIB_QOS_HAS_SEQ(fc))
rx_stats->bIsQosData = true;
return hdrlen;
@@ -1812,7 +1812,7 @@ static inline void rtllib_extract_country_ie(
netdev_info(ieee->dev,
"Received beacon ContryIE, SSID: <%s>\n",
network->ssid);
- Dot11d_UpdateCountryIe(ieee, addr2,
+ dot11d_update_country(ieee, addr2,
info_element->len,
info_element->data);
}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index 287d0c11fa38..ee275857868f 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -564,7 +564,7 @@ out:
if (ieee->state >= RTLLIB_LINKED) {
if (IS_DOT11D_ENABLE(ieee))
- DOT11D_ScanComplete(ieee);
+ dot11d_scan_complete(ieee);
}
mutex_unlock(&ieee->scan_mutex);
@@ -623,7 +623,7 @@ static void rtllib_softmac_scan_wq(void *data)
out:
if (IS_DOT11D_ENABLE(ieee))
- DOT11D_ScanComplete(ieee);
+ dot11d_scan_complete(ieee);
ieee->current_network.channel = last_channel;
out1:
@@ -1688,8 +1688,8 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
ieee->current_network.ssid_len);
tmp_ssid_len = ieee->current_network.ssid_len;
}
- memcpy(&ieee->current_network, net,
- sizeof(ieee->current_network));
+ memcpy(&ieee->current_network, net,
+ sizeof(ieee->current_network));
if (!ssidbroad) {
memcpy(ieee->current_network.ssid, tmp_ssid,
tmp_ssid_len);
@@ -2627,7 +2627,7 @@ static void rtllib_start_ibss_wq(void *data)
/* the network definitively is not here.. create a new cell */
if (ieee->state == RTLLIB_NOLINK) {
netdev_info(ieee->dev, "creating new IBSS cell\n");
- ieee->current_network.channel = ieee->IbssStartChnl;
+ ieee->current_network.channel = ieee->bss_start_channel;
if (!ieee->wap_set)
eth_random_addr(ieee->current_network.bssid);
@@ -2719,7 +2719,7 @@ static void rtllib_start_bss(struct rtllib_device *ieee)
unsigned long flags;
if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
- if (!ieee->bGlobalDomain)
+ if (!ieee->global_domain)
return;
}
/* check if we have already found the net we
@@ -2759,7 +2759,7 @@ void rtllib_disassociate(struct rtllib_device *ieee)
if (ieee->data_hard_stop)
ieee->data_hard_stop(ieee->dev);
if (IS_DOT11D_ENABLE(ieee))
- Dot11d_Reset(ieee);
+ dot11d_reset(ieee);
ieee->state = RTLLIB_NOLINK;
ieee->is_set_key = false;
ieee->wap_set = 0;
@@ -2974,8 +2974,8 @@ void rtllib_softmac_init(struct rtllib_device *ieee)
ieee->state = RTLLIB_NOLINK;
for (i = 0; i < 5; i++)
ieee->seq_ctrl[i] = 0;
- ieee->pDot11dInfo = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
- if (!ieee->pDot11dInfo)
+ ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
+ if (!ieee->dot11d_info)
netdev_err(ieee->dev, "Can't alloc memory for DOT11D\n");
ieee->LinkDetectInfo.SlotIndex = 0;
ieee->LinkDetectInfo.SlotNum = 2;
@@ -3049,8 +3049,8 @@ void rtllib_softmac_init(struct rtllib_device *ieee)
void rtllib_softmac_free(struct rtllib_device *ieee)
{
mutex_lock(&ieee->wx_mutex);
- kfree(ieee->pDot11dInfo);
- ieee->pDot11dInfo = NULL;
+ kfree(ieee->dot11d_info);
+ ieee->dot11d_info = NULL;
del_timer_sync(&ieee->associate_timer);
cancel_delayed_work_sync(&ieee->associate_retry_wq);
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index 74d4d2df3eb3..4f4904a300e0 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -541,8 +541,8 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
if (idx < 1 || idx > NUM_WEP_KEYS)
return -EINVAL;
idx--;
- } else{
- idx = ieee->crypt_info.tx_keyidx;
+ } else {
+ idx = ieee->crypt_info.tx_keyidx;
}
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
crypt = &ieee->crypt_info.crypt[idx];
diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile
index 3022728a364c..dcd51bf4aed3 100644
--- a/drivers/staging/rtl8192u/Makefile
+++ b/drivers/staging/rtl8192u/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -O2
ccflags-y += -DCONFIG_FORCE_HARD_FLOAT=y
ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
ccflags-y += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO
-ccflags-y += -Idrivers/staging/rtl8192u/ieee80211
+ccflags-y += -I $(srctree)/$(src)/ieee80211
r8192u_usb-y := r8192U_core.o r8180_93cx6.o r8192U_wx.o \
r8190_rtl8256.o r819xU_phy.o r819xU_firmware.o \
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 0ac0bbf7d923..f1eaab337dca 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -4957,20 +4957,18 @@ static void rtl8192_usb_disconnect(struct usb_interface *intf)
struct net_device *dev = usb_get_intfdata(intf);
struct r8192_priv *priv = ieee80211_priv(dev);
- if (dev) {
- unregister_netdev(dev);
-
- RT_TRACE(COMP_DOWN,
- "=============>wlan driver to be removed\n");
- rtl8192_proc_remove_one(dev);
-
- rtl8192_down(dev);
- kfree(priv->pFirmware);
- priv->pFirmware = NULL;
- rtl8192_usb_deleteendpoints(dev);
- usleep_range(10000, 11000);
- }
+ unregister_netdev(dev);
+
+ RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
+ rtl8192_proc_remove_one(dev);
+
+ rtl8192_down(dev);
+ kfree(priv->pFirmware);
+ priv->pFirmware = NULL;
+ rtl8192_usb_deleteendpoints(dev);
+ usleep_range(10000, 11000);
free_ieee80211(dev);
+
RT_TRACE(COMP_DOWN, "wlan driver removed\n");
}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
index bb4f56a5fb01..2eae11dd6b42 100644
--- a/drivers/staging/rtl8712/ieee80211.c
+++ b/drivers/staging/rtl8712/ieee80211.c
@@ -408,7 +408,7 @@ int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
match = true;
break;
}
- cnt += in_ie[cnt + 1] + 2; /* goto next */
+ cnt += in_ie[cnt + 1] + 2; /* goto next */
}
return match;
}
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
index 8bc45ffd3029..39eb74374d0b 100644
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ b/drivers/staging/rtl8712/rtl8712_efuse.c
@@ -358,7 +358,7 @@ u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset,
u8 pg_header = 0;
u16 efuse_addr = 0, curr_size = 0;
u8 efuse_data, target_word_cnts = 0;
- static int repeat_times;
+ int repeat_times;
int sub_repeat;
u8 bResult = true;
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index 5b1004b2df47..07fcf9b9b811 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -939,7 +939,7 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
+ pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
@@ -991,7 +991,7 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
+ pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
@@ -1018,7 +1018,7 @@ static void SwLedControlMode1(struct _adapter *padapter,
}
if (pLed->bLedLinkBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
+ pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress) {
del_timer(&pLed->BlinkTimer);
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index 986a1d526918..3f17ef6f7e39 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -259,7 +259,7 @@ int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
static int is_same_network(struct wlan_bssid_ex *src,
struct wlan_bssid_ex *dst)
{
- u16 s_cap, d_cap;
+ u16 s_cap, d_cap;
memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index f10896df094b..28f736913292 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -54,7 +54,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv,
sint i;
union recv_frame *precvframe;
- memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv));
+ memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv));
spin_lock_init(&precvpriv->lock);
_init_queue(&precvpriv->free_recv_queue);
_init_queue(&precvpriv->recv_pending_queue);
@@ -325,7 +325,7 @@ static sint sta2sta_data_frame(struct _adapter *adapter,
*/
if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
return _FAIL;
- sta_addr = pattrib->bssid;
+ sta_addr = pattrib->bssid;
} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
if (bmcast) {
/* For AP mode, if DA == MCAST, then BSSID should
@@ -404,7 +404,7 @@ static sint ap2sta_data_frame(struct _adapter *adapter,
if (bmcast)
*psta = r8712_get_bcmc_stainfo(adapter);
else
- *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
+ *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
if (*psta == NULL)
return _FAIL;
} else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 9648ee15b40e..7c30b9e68e70 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -25,7 +25,7 @@
static void _init_stainfo(struct sta_info *psta)
{
memset((u8 *)psta, 0, sizeof(struct sta_info));
- spin_lock_init(&psta->lock);
+ spin_lock_init(&psta->lock);
INIT_LIST_HEAD(&psta->list);
INIT_LIST_HEAD(&psta->hash_list);
_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index 5c7dc9c6f76b..7c8857409916 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -193,8 +193,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
pattrib->ether_type = ntohs(etherhdr.h_proto);
-{
- /*If driver xmit ARP packet, driver can set ps mode to initial
+ /*
+ * If driver xmit ARP packet, driver can set ps mode to initial
* setting. It stands for getting DHCP or fix IP.
*/
if (pattrib->ether_type == 0x0806) {
@@ -206,7 +206,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
padapter->registrypriv.smart_ps);
}
}
-}
+
memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
pattrib->pctrl = 0;
@@ -949,7 +949,7 @@ static void alloc_hwxmits(struct _adapter *padapter)
pxmitpriv->vo_txqueue.head = 0;
hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
- pxmitpriv->vi_txqueue.head = 0;
+ pxmitpriv->vi_txqueue.head = 0;
hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
pxmitpriv->bk_txqueue.head = 0;
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 92d75d7c51ae..005010de9997 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -196,10 +196,6 @@ static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Suspending...\n");
- if (!pnetdev || !netif_running(pnetdev)) {
- netdev_info(pnetdev, "Unable to suspend\n");
- return 0;
- }
padapter->bSuspended = true;
rtl871x_intf_stop(padapter);
if (pnetdev->netdev_ops->ndo_stop)
@@ -221,10 +217,6 @@ static int r871x_resume(struct usb_interface *pusb_intf)
struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Resuming...\n");
- if (!pnetdev || !netif_running(pnetdev)) {
- netdev_info(pnetdev, "Unable to resume\n");
- return 0;
- }
netif_device_attach(pnetdev);
if (pnetdev->netdev_ops->ndo_open)
pnetdev->netdev_ops->ndo_open(pnetdev);
@@ -232,13 +224,6 @@ static int r871x_resume(struct usb_interface *pusb_intf)
rtl871x_intf_resume(padapter);
return 0;
}
-
-static int r871x_reset_resume(struct usb_interface *pusb_intf)
-{
- /* dummy routine */
- return 0;
-}
-
#endif
static struct drv_priv drvpriv = {
@@ -249,7 +234,6 @@ static struct drv_priv drvpriv = {
#ifdef CONFIG_PM
.r871xu_drv.suspend = r871x_suspend,
.r871xu_drv.resume = r871x_resume,
- .r871xu_drv.reset_resume = r871x_reset_resume,
#endif
};
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
index ea2c187e56bd..91520ca3bbad 100644
--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -835,14 +835,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
}
psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
- if (psecnetwork == NULL) {
- kfree(pcmd);
- res = _FAIL;
-
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
-
- goto exit;
- }
memset(psecnetwork, 0, t_len);
diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
index 625e67f39889..094d61bcb469 100644
--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
@@ -2389,7 +2389,7 @@ sint xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fr
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false) {
DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_fwstate);
- return ret;
+ return ret;
}
/*
if (pattrib->psta)
diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h
index 062fda9962be..bafb2c30e7fb 100644
--- a/drivers/staging/rtl8723bs/include/drv_types.h
+++ b/drivers/staging/rtl8723bs/include/drv_types.h
@@ -65,7 +65,6 @@ enum _NIC_VERSION {
#include <rtw_event.h>
#include <rtw_mlme_ext.h>
#include <rtw_ap.h>
-#include <rtw_efuse.h>
#include <rtw_version.h>
#include <rtw_odm.h>
diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h
index bcc8dfa8e672..9efb4dcb9d3a 100644
--- a/drivers/staging/rtl8723bs/include/ieee80211.h
+++ b/drivers/staging/rtl8723bs/include/ieee80211.h
@@ -850,18 +850,18 @@ enum ieee80211_state {
#define IP_FMT "%pI4"
#define IP_ARG(x) (x)
-extern __inline int is_multicast_mac_addr(const u8 *addr)
+static inline int is_multicast_mac_addr(const u8 *addr)
{
return ((addr[0] != 0xff) && (0x01 & addr[0]));
}
-extern __inline int is_broadcast_mac_addr(const u8 *addr)
+static inline int is_broadcast_mac_addr(const u8 *addr)
{
return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \
(addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
}
-extern __inline int is_zero_mac_addr(const u8 *addr)
+static inline int is_zero_mac_addr(const u8 *addr)
{
return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \
(addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
index e14d7cc411c9..73b87da15eb2 100644
--- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
@@ -137,7 +137,7 @@ static int isFileReadable(char *path)
ret = PTR_ERR(fp);
}
else {
- oldfs = get_fs(); set_fs(get_ds());
+ oldfs = get_fs(); set_fs(KERNEL_DS);
if (1!=readFile(fp, &buf, 1))
ret = -EINVAL;
@@ -165,7 +165,7 @@ static int retriveFromFile(char *path, u8 *buf, u32 sz)
if (0 == (ret =openFile(&fp, path, O_RDONLY, 0))) {
DBG_871X("%s openFile path:%s fp =%p\n", __func__, path , fp);
- oldfs = get_fs(); set_fs(get_ds());
+ oldfs = get_fs(); set_fs(KERNEL_DS);
ret =readFile(fp, buf, sz);
set_fs(oldfs);
closeFile(fp);
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
index 7c03b69b8ed3..6d02904de63f 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
@@ -22,7 +22,7 @@ static const struct sdio_device_id sdio_ids[] =
{ SDIO_DEVICE(0x024c, 0xb723), },
{ /* end: all zeroes */ },
};
-static const struct acpi_device_id acpi_ids[] __used = {
+static const struct acpi_device_id acpi_ids[] = {
{"OBDA8723", 0x0000},
{}
};
diff --git a/drivers/staging/rtlwifi/Kconfig b/drivers/staging/rtlwifi/Kconfig
index 7b4276f5c41f..28286a87a601 100644
--- a/drivers/staging/rtlwifi/Kconfig
+++ b/drivers/staging/rtlwifi/Kconfig
@@ -2,7 +2,7 @@ config R8822BE
tristate "Realtek RTL8822BE Wireless Network Adapter"
depends on PCI && MAC80211 && m
select FW_LOADER
- ---help---
+ help
This is the staging driver for Realtek RTL8822BE 802.11ac PCIe
wireless network adapters.
diff --git a/drivers/staging/rtlwifi/efuse.c b/drivers/staging/rtlwifi/efuse.c
index abb0f720cf21..a7c9e186f2b2 100644
--- a/drivers/staging/rtlwifi/efuse.c
+++ b/drivers/staging/rtlwifi/efuse.c
@@ -919,7 +919,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct pgpkt_struct target_pkt;
u8 write_state = PG_STATE_HEADER;
- int continual = true, dataempty = true, result = true;
+ int continual = true, result = true;
u16 efuse_addr = 0;
u8 efuse_data;
u8 target_word_cnts = 0;
@@ -946,7 +946,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
if (write_state == PG_STATE_HEADER) {
- dataempty = true;
badworden = 0x0F;
RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
"efuse PG_STATE_HEADER\n");
@@ -1182,13 +1181,12 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)
{
int continual = true;
u16 efuse_addr = 0;
- u8 hoffset, hworden;
+ u8 hworden;
u8 efuse_data, word_cnts;
while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
(efuse_addr < EFUSE_MAX_SIZE)) {
if (efuse_data != 0xFF) {
- hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
word_cnts = efuse_calculate_word_cnts(hworden);
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c
index 53f55f129a76..ddbeff8224ab 100644
--- a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c
+++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c
@@ -2466,8 +2466,11 @@ halmac_parse_psd_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
segment_size = (u8)PSD_DATA_GET_SEGMENT_SIZE(c2h_buf);
psd_set->data_size = total_size;
- if (!psd_set->data)
+ if (!psd_set->data) {
psd_set->data = kzalloc(psd_set->data_size, GFP_KERNEL);
+ if (!psd_set->data)
+ return HALMAC_RET_MALLOC_FAIL;
+ }
if (segment_id == 0)
psd_set->segment_size = segment_size;
diff --git a/drivers/staging/rtlwifi/pci.h b/drivers/staging/rtlwifi/pci.h
index 7535ac24bfbb..0e55baec95a8 100644
--- a/drivers/staging/rtlwifi/pci.h
+++ b/drivers/staging/rtlwifi/pci.h
@@ -205,7 +205,8 @@ struct rtl_pci {
/*Bcn control register setting */
u32 reg_bcn_ctrl_val;
- /*ASPM*/ u8 const_pci_aspm;
+ /*ASPM*/
+ u8 const_pci_aspm;
u8 const_amdpci_aspm;
u8 const_hwsw_rfoff_d3;
u8 const_support_pciaspm;
diff --git a/drivers/staging/rtlwifi/phydm/phydm_rainfo.c b/drivers/staging/rtlwifi/phydm/phydm_rainfo.c
index b46791a727c7..ed740a93c8b6 100644
--- a/drivers/staging/rtlwifi/phydm/phydm_rainfo.c
+++ b/drivers/staging/rtlwifi/phydm/phydm_rainfo.c
@@ -124,7 +124,7 @@ void odm_c2h_ra_para_report_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
ODM_RT_TRACE(dm, ODM_FW_DEBUG_TRACE, "%5s %d\n",
"VHT_EN =", cmd_buf[4]);
ODM_RT_TRACE(dm, ODM_FW_DEBUG_TRACE, "%5s %d\n",
- "Hightest rate =", cmd_buf[5]);
+ "Highest rate =", cmd_buf[5]);
ODM_RT_TRACE(dm, ODM_FW_DEBUG_TRACE, "%5s 0x%x\n",
"Lowest rate =", cmd_buf[6]);
ODM_RT_TRACE(dm, ODM_FW_DEBUG_TRACE, "%5s 0x%x\n",
diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c
index a40396614814..f061dd1382aa 100644
--- a/drivers/staging/rtlwifi/rtl8822be/fw.c
+++ b/drivers/staging/rtlwifi/rtl8822be/fw.c
@@ -486,6 +486,8 @@ bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
/* without GFP_DMA, pci_map_single() may not work */
skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
+ if (!skb)
+ return false;
memcpy((u8 *)skb_put(skb, size), buf, size);
return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index e43f92080c20..1128eec3bd08 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -1665,7 +1665,10 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
return STATUS_FAIL;
}
- ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
+ retval = ms_read_extra_data(chip, old_blk, i, extra,
+ MS_EXTRA_SIZE);
+ if (retval != STATUS_SUCCESS)
+ return STATUS_FAIL;
retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
MS_EXTRA_SIZE, SystemParm, 6);
diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
index 2c47ae613ea1..c256a2398651 100644
--- a/drivers/staging/rts5208/sd.c
+++ b/drivers/staging/rts5208/sd.c
@@ -4437,7 +4437,12 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
- rtsx_send_cmd(chip, SD_CARD, 250);
+ retval = rtsx_send_cmd(chip, SD_CARD, 250);
+ if (retval < 0) {
+ write_err = true;
+ rtsx_clear_sd_error(chip);
+ goto sd_execute_write_cmd_failed;
+ }
retval = sd_update_lock_status(chip);
if (retval != STATUS_SUCCESS) {
diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c
index 1273e7d18925..f38051eedb6c 100644
--- a/drivers/staging/sm750fb/ddk750_display.c
+++ b/drivers/staging/sm750fb/ddk750_display.c
@@ -5,7 +5,7 @@
#include "ddk750_power.h"
#include "ddk750_dvi.h"
-static void setDisplayControl(int ctrl, int disp_state)
+static void set_display_control(int ctrl, int disp_state)
{
/* state != 0 means turn on both timing & plane en_bit */
unsigned long reg, val, reserved;
@@ -137,12 +137,12 @@ void ddk750_setLogicalDispOut(enum disp_output output)
if (output & PRI_TP_USAGE) {
/* set primary timing and plane en_bit */
- setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
+ set_display_control(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
}
if (output & SEC_TP_USAGE) {
/* set secondary timing and plane en_bit*/
- setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
+ set_display_control(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
}
if (output & PNL_SEQ_USAGE) {
diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig
index efd6f4560d3e..d8ec780f7741 100644
--- a/drivers/staging/speakup/Kconfig
+++ b/drivers/staging/speakup/Kconfig
@@ -3,7 +3,7 @@ menu "Speakup console speech"
config SPEAKUP
depends on VT
tristate "Speakup core"
- ---help---
+ help
This is the Speakup screen reader. Think of it as a
video console for blind people. If built in to the
kernel, it can speak everything on the text console from
@@ -43,7 +43,7 @@ config SPEAKUP
if SPEAKUP
config SPEAKUP_SYNTH_ACNTSA
tristate "Accent SA synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Accent SA
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
@@ -52,7 +52,7 @@ config SPEAKUP_SYNTH_ACNTSA
config SPEAKUP_SYNTH_ACNTPC
tristate "Accent PC synthesizer support"
depends on ISA || COMPILE_TEST
- ---help---
+ help
This is the Speakup driver for the accent pc
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
@@ -60,7 +60,7 @@ config SPEAKUP_SYNTH_ACNTPC
config SPEAKUP_SYNTH_APOLLO
tristate "Apollo II synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Apollo II
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
@@ -68,7 +68,7 @@ config SPEAKUP_SYNTH_APOLLO
config SPEAKUP_SYNTH_AUDPTR
tristate "Audapter synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Audapter synthesizer.
You can say y to build it into the kernel, or m to
build it as a module. See the configuration help on the
@@ -76,7 +76,7 @@ config SPEAKUP_SYNTH_AUDPTR
config SPEAKUP_SYNTH_BNS
tristate "Braille 'n' Speak synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Braille 'n' Speak
synthesizer. You can say y to build it into the kernel,
or m to build it as a module. See the configuration
@@ -84,7 +84,7 @@ config SPEAKUP_SYNTH_BNS
config SPEAKUP_SYNTH_DECTLK
tristate "DECtalk Express synthesizer support"
- ---help---
+ help
This is the Speakup driver for the DecTalk Express
synthesizer. You can say y to build it into the kernel,
@@ -93,7 +93,7 @@ config SPEAKUP_SYNTH_DECTLK
config SPEAKUP_SYNTH_DECEXT
tristate "DECtalk External (old) synthesizer support"
- ---help---
+ help
This is the Speakup driver for the DecTalk External
(old) synthesizer. You can say y to build it into the
@@ -105,7 +105,7 @@ config SPEAKUP_SYNTH_DECPC
depends on m
depends on ISA || COMPILE_TEST
tristate "DECtalk PC (big ISA card) synthesizer support"
- ---help---
+ help
This is the Speakup driver for the DecTalk PC (full
length ISA) synthesizer. You can say m to build it as
@@ -127,7 +127,7 @@ config SPEAKUP_SYNTH_DECPC
config SPEAKUP_SYNTH_DTLK
tristate "DoubleTalk PC synthesizer support"
depends on ISA || COMPILE_TEST
- ---help---
+ help
This is the Speakup driver for the internal DoubleTalk
PC synthesizer. You can say y to build it into the
@@ -138,7 +138,7 @@ config SPEAKUP_SYNTH_DTLK
config SPEAKUP_SYNTH_KEYPC
tristate "Keynote Gold PC synthesizer support"
depends on ISA || COMPILE_TEST
- ---help---
+ help
This is the Speakup driver for the Keynote Gold
PC synthesizer. You can say y to build it into the
@@ -148,7 +148,7 @@ config SPEAKUP_SYNTH_KEYPC
config SPEAKUP_SYNTH_LTLK
tristate "DoubleTalk LT/LiteTalk synthesizer support"
----help---
+help
This is the Speakup driver for the LiteTalk/DoubleTalk
LT synthesizer. You can say y to build it into the
@@ -158,7 +158,7 @@ config SPEAKUP_SYNTH_LTLK
config SPEAKUP_SYNTH_SOFT
tristate "Userspace software synthesizer support"
- ---help---
+ help
This is the software synthesizer device node. It will
register a device /dev/softsynth which midware programs
@@ -169,7 +169,7 @@ config SPEAKUP_SYNTH_SOFT
config SPEAKUP_SYNTH_SPKOUT
tristate "Speak Out synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Speakout synthesizer.
You can say y to build it into the kernel, or m to
@@ -178,7 +178,7 @@ config SPEAKUP_SYNTH_SPKOUT
config SPEAKUP_SYNTH_TXPRT
tristate "Transport synthesizer support"
- ---help---
+ help
This is the Speakup driver for the Transport
synthesizer. You can say y to build it into the kernel,
@@ -187,7 +187,7 @@ config SPEAKUP_SYNTH_TXPRT
config SPEAKUP_SYNTH_DUMMY
tristate "Dummy synthesizer driver (for testing)"
- ---help---
+ help
This is a dummy Speakup driver for plugging a mere serial
terminal. This is handy if you want to test speakup but
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 2e36d872662c..11c704b27c3c 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -154,6 +154,7 @@ static ssize_t chars_chartab_store(struct kobject *kobj,
continue;
}
+ /* Do not replace with kstrtoul: here we need temp to be updated */
index = simple_strtoul(cp, &temp, 10);
if (index > 255) {
rejected++;
@@ -787,6 +788,7 @@ static ssize_t message_store_helper(const char *buf, size_t count,
continue;
}
+ /* Do not replace with kstrtoul: here we need temp to be updated */
index = simple_strtoul(cp, &temp, 10);
while ((temp < linefeed) && (*temp == ' ' || *temp == '\t'))
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 869f40ebf1a7..b6a65b0c1896 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -901,7 +901,8 @@ static int get_sentence_buf(struct vc_data *vc, int read_punc)
while (start < end) {
sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
if (i > 0) {
- if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.' &&
+ if (sentbuf[bn][i] == SPACE &&
+ sentbuf[bn][i - 1] == '.' &&
numsentences[bn] < 9) {
/* Sentence Marker */
numsentences[bn]++;
@@ -1235,7 +1236,8 @@ int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
key_data_len = (states + 1) * (num_keys + 1);
if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) {
pr_debug("too many key_infos (%d over %u)\n",
- key_data_len + SHIFT_TBL_SIZE + 4, (unsigned int)(sizeof(spk_key_buf)));
+ key_data_len + SHIFT_TBL_SIZE + 4,
+ (unsigned int)(sizeof(spk_key_buf)));
return -EINVAL;
}
memset(k_buffer, 0, SHIFT_TBL_SIZE);
@@ -1249,8 +1251,8 @@ int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
for (i = 1; i <= states; i++) {
ch = *cp1++;
if (ch >= SHIFT_TBL_SIZE) {
- pr_debug("(%d) not valid shift state (max_allowed = %d)\n", ch,
- SHIFT_TBL_SIZE);
+ pr_debug("(%d) not valid shift state (max_allowed = %d)\n",
+ ch, SHIFT_TBL_SIZE);
return -EINVAL;
}
spk_shift_table[ch] = i;
@@ -1258,7 +1260,8 @@ int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
keymap_flags = *cp1++;
while ((ch = *cp1)) {
if (ch >= MAX_KEY) {
- pr_debug("(%d), not valid key, (max_allowed = %d)\n", ch, MAX_KEY);
+ pr_debug("(%d), not valid key, (max_allowed = %d)\n",
+ ch, MAX_KEY);
return -EINVAL;
}
spk_our_keys[ch] = cp1;
@@ -1979,6 +1982,7 @@ oops:
return 1;
}
+ /* Do not replace with kstrtoul: here we need cp to be updated */
goto_pos = simple_strtoul(goto_buf, &cp, 10);
if (*cp == 'x') {
diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c
index 3741c0fcf5bb..ddbb7e97d118 100644
--- a/drivers/staging/speakup/speakup_decext.c
+++ b/drivers/staging/speakup/speakup_decext.c
@@ -192,7 +192,8 @@ static void do_catch_up(struct spk_synth *synth)
synth->io_ops->synth_out(synth, PROCSPEECH);
if (time_after_eq(jiffies, jiff_max)) {
if (!in_escape)
- synth->io_ops->synth_out(synth, PROCSPEECH);
+ synth->io_ops->synth_out(synth,
+ PROCSPEECH);
spin_lock_irqsave(&speakup_info.spinlock,
flags);
jiffy_delta_val = jiffy_delta->u.n.value;
diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c
index a144f28ee1a8..dccb4ea29d37 100644
--- a/drivers/staging/speakup/speakup_dectlk.c
+++ b/drivers/staging/speakup/speakup_dectlk.c
@@ -260,7 +260,8 @@ static void do_catch_up(struct spk_synth *synth)
synth->io_ops->synth_out(synth, PROCSPEECH);
if (time_after_eq(jiffies, jiff_max)) {
if (!in_escape)
- synth->io_ops->synth_out(synth, PROCSPEECH);
+ synth->io_ops->synth_out(synth,
+ PROCSPEECH);
spin_lock_irqsave(&speakup_info.spinlock,
flags);
jiffy_delta_val = jiffy_delta->u.n.value;
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index 947c79532e10..edff6ce85655 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -12,7 +12,9 @@
#include <linux/unistd.h>
#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */
#include <linux/poll.h> /* for poll_wait() */
-#include <linux/sched/signal.h> /* schedule(), signal_pending(), TASK_INTERRUPTIBLE */
+
+/* schedule(), signal_pending(), TASK_INTERRUPTIBLE */
+#include <linux/sched/signal.h>
#include "spk_priv.h"
#include "speakup.h"
diff --git a/drivers/staging/speakup/spk_priv_keyinfo.h b/drivers/staging/speakup/spk_priv_keyinfo.h
index cc99fcd1bc6e..1f789bd1c678 100644
--- a/drivers/staging/speakup/spk_priv_keyinfo.h
+++ b/drivers/staging/speakup/spk_priv_keyinfo.h
@@ -61,11 +61,16 @@
#define SPEAKUP_HELP 0x2d
#define TOGGLE_CURSORING 0x2e
#define READ_ALL_DOC 0x2f
-#define SPKUP_MAX_FUNC 0x30 /* one greater than the last func handler */
+
+/* one greater than the last func handler */
+#define SPKUP_MAX_FUNC 0x30
+
#define SPK_KEY 0x80
#define FIRST_EDIT_BITS 0x22
#define FIRST_SET_VAR SPELL_DELAY
-#define VAR_START 0x40 /* increase if adding more than 0x3f functions */
+
+/* increase if adding more than 0x3f functions */
+#define VAR_START 0x40
/* keys for setting variables, must be ordered same as the enum for var_ids */
/* with dec being even and inc being 1 greater */
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index c92bbd05516e..0057eb980bec 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -128,7 +128,8 @@ struct spk_io_ops spk_ttyio_ops = {
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
-static inline void get_termios(struct tty_struct *tty, struct ktermios *out_termios)
+static inline void get_termios(struct tty_struct *tty,
+ struct ktermios *out_termios)
{
down_read(&tty->termios_rwsem);
*out_termios = tty->termios;
@@ -167,8 +168,9 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
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.
+ * 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))
@@ -207,10 +209,11 @@ static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
/* 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
+ 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();
@@ -265,7 +268,8 @@ static void spk_ttyio_send_xchar(char ch)
return;
}
- speakup_tty->ops->send_xchar(speakup_tty, ch);
+ if (speakup_tty->ops->send_xchar)
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
mutex_unlock(&speakup_tty_mutex);
}
@@ -277,7 +281,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
return;
}
- speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+ if (speakup_tty->ops->tiocmset)
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
mutex_unlock(&speakup_tty_mutex);
}
@@ -369,7 +374,8 @@ const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff)
while ((ch = *buff)) {
if (ch == '\n')
ch = synth->procspeech;
- if (tty_write_room(speakup_tty) < 1 || !synth->io_ops->synth_out(synth, ch))
+ if (tty_write_room(speakup_tty) < 1 ||
+ !synth->io_ops->synth_out(synth, ch))
return buff;
buff++;
}
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
index 1b545152cc49..5741d1cb6227 100644
--- a/drivers/staging/speakup/varhandlers.c
+++ b/drivers/staging/speakup/varhandlers.c
@@ -238,7 +238,8 @@ int spk_set_num_var(int input, struct st_var_header *var, int how)
if (!var_data->u.n.out_str)
sprintf(cp, var_data->u.n.synth_fmt, (int)val);
else
- sprintf(cp, var_data->u.n.synth_fmt, var_data->u.n.out_str[val]);
+ sprintf(cp, var_data->u.n.synth_fmt,
+ var_data->u.n.out_str[val]);
synth_printf("%s", cp);
return 0;
}
@@ -328,6 +329,7 @@ char *spk_s2uchar(char *start, char *dest)
{
int val;
+ /* Do not replace with kstrtoul: here we need start to be updated */
val = simple_strtoul(skip_spaces(start), &start, 10);
if (*start == ',')
start++;
diff --git a/drivers/staging/unisys/visorhba/Makefile b/drivers/staging/unisys/visorhba/Makefile
index a8a8e0e0fb09..97e48757944a 100644
--- a/drivers/staging/unisys/visorhba/Makefile
+++ b/drivers/staging/unisys/visorhba/Makefile
@@ -6,5 +6,4 @@ obj-$(CONFIG_UNISYS_VISORHBA) += visorhba.o
visorhba-y := visorhba_main.o
-ccflags-y += -Idrivers/staging/unisys/include
-
+ccflags-y += -I $(srctree)/$(src)/../include
diff --git a/drivers/staging/unisys/visornic/Makefile b/drivers/staging/unisys/visornic/Makefile
index 439e95e03300..336a746f793b 100644
--- a/drivers/staging/unisys/visornic/Makefile
+++ b/drivers/staging/unisys/visornic/Makefile
@@ -6,5 +6,4 @@ obj-$(CONFIG_UNISYS_VISORNIC) += visornic.o
visornic-y := visornic_main.o
-ccflags-y += -Idrivers/staging/unisys/include
-
+ccflags-y += -I $(srctree)/$(src)/../include
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 5eeb4b93b45b..1c1a470d2e50 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -896,9 +896,7 @@ static netdev_tx_t visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
((skb_end_pointer(skb) - skb->data) >= ETH_MIN_PACKET_SIZE)) {
/* pad the packet out to minimum size */
padlen = ETH_MIN_PACKET_SIZE - len;
- memset(&skb->data[len], 0, padlen);
- skb->tail += padlen;
- skb->len += padlen;
+ skb_put_zero(skb, padlen);
len += padlen;
firstfraglen += padlen;
}
diff --git a/drivers/staging/vc04_services/bcm2835-audio/Makefile b/drivers/staging/vc04_services/bcm2835-audio/Makefile
index d7b88d164d15..536bd0c11ddb 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/Makefile
+++ b/drivers/staging/vc04_services/bcm2835-audio/Makefile
@@ -1,5 +1,4 @@
obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o
snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
-ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
-
+ccflags-y += -I $(srctree)/$(src)/.. -D__VCCOREVER__=0x04000000
diff --git a/drivers/staging/vc04_services/bcm2835-camera/Makefile b/drivers/staging/vc04_services/bcm2835-camera/Makefile
index 2a4565e682d8..472f21e1f2a1 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
+++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
@@ -7,5 +7,5 @@ bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
ccflags-y += \
- -Idrivers/staging/vc04_services \
+ -I $(srctree)/$(src)/.. \
-D__VCCOREVER__=0x04000000
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 338b6e952515..dd4898861b83 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
@@ -407,10 +407,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
/* Allocate enough storage to hold the page pointers and the page
* list
*/
- pagelist = dma_zalloc_coherent(g_dev,
- pagelist_size,
- &dma_addr,
- GFP_KERNEL);
+ pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr,
+ GFP_KERNEL);
vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist);
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 9e17ec651bde..53f5a1cb4636 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -446,6 +446,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
static inline void
remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event)
{
+ event->fired = 1;
event->armed = 0;
wake_up_all(wq);
}
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
index b5ba0c76fb43..b4cdc0b7fee7 100644
--- a/drivers/staging/vt6655/baseband.c
+++ b/drivers/staging/vt6655/baseband.c
@@ -1704,13 +1704,9 @@ static const unsigned short awcFrameTime[MAX_RATE] = {
* Return Value: FrameTime
*
*/
-unsigned int
-BBuGetFrameTime(
- unsigned char byPreambleType,
- unsigned char byPktType,
- unsigned int cbFrameLength,
- unsigned short wRate
-)
+unsigned int BBuGetFrameTime(unsigned char byPreambleType,
+ unsigned char byPktType,
+ unsigned int cbFrameLength, unsigned short wRate)
{
unsigned int uFrameTime;
unsigned int uPreamble;
diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h
index 30d9e9d20a39..0cc2e07829c5 100644
--- a/drivers/staging/vt6655/baseband.h
+++ b/drivers/staging/vt6655/baseband.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 52e9e6b90b56..6ecbe925026d 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -60,14 +60,9 @@ static const unsigned short cwRXBCNTSFOff[MAX_RATE] = {
/*--------------------- Static Functions --------------------------*/
-static
-void
-s_vCalculateOFDMRParameter(
- unsigned char byRate,
- u8 bb_type,
- unsigned char *pbyTxRate,
- unsigned char *pbyRsvTime
-);
+static void s_vCalculateOFDMRParameter(unsigned char byRate, u8 bb_type,
+ unsigned char *pbyTxRate,
+ unsigned char *pbyRsvTime);
/*--------------------- Export Functions --------------------------*/
@@ -506,10 +501,7 @@ bool CARDbRadioPowerOn(struct vnt_private *priv)
return bResult;
}
-void
-CARDvSafeResetTx(
- struct vnt_private *priv
-)
+void CARDvSafeResetTx(struct vnt_private *priv)
{
unsigned int uu;
struct vnt_tx_desc *pCurrTD;
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index 5884fd56153e..d71022aa3f86 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 1ab0e8562d40..b370985b58a1 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -440,12 +440,9 @@ static bool device_init_rings(struct vnt_private *priv)
void *vir_pool;
/*allocate all RD/TD rings a single pool*/
- vir_pool = dma_zalloc_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- 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);
+ vir_pool = dma_alloc_coherent(&priv->pcid->dev,
+ priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + 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) {
dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
return false;
@@ -459,13 +456,9 @@ static bool device_init_rings(struct vnt_private *priv)
priv->rd1_pool_dma = priv->rd0_pool_dma +
priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
- priv->tx0_bufs = dma_zalloc_coherent(&priv->pcid->dev,
- priv->opts.tx_descs[0] * PKT_BUF_SZ +
- priv->opts.tx_descs[1] * PKT_BUF_SZ +
- CB_BEACON_BUF_SIZE +
- CB_MAX_BUF_SIZE,
- &priv->tx_bufs_dma0,
- GFP_ATOMIC);
+ priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev,
+ priv->opts.tx_descs[0] * PKT_BUF_SZ + priv->opts.tx_descs[1] * PKT_BUF_SZ + CB_BEACON_BUF_SIZE + CB_MAX_BUF_SIZE,
+ &priv->tx_bufs_dma0, GFP_ATOMIC);
if (!priv->tx0_bufs) {
dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
@@ -812,12 +805,12 @@ static bool device_alloc_rx_buf(struct vnt_private *priv,
}
static void device_free_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd)
+ struct vnt_rx_desc *rd)
{
struct vnt_rd_info *rd_info = rd->rd_info;
dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
- priv->rx_buf_sz, DMA_FROM_DEVICE);
+ priv->rx_buf_sz, DMA_FROM_DEVICE);
dev_kfree_skb(rd_info->skb);
}
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 91dede54cc1f..dcd933a6b66e 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -63,17 +63,19 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
}
switch (key_type) {
- /* fallthrough */
case VNT_KEY_DEFAULTKEY:
/* default key last entry */
entry = MAX_KEY_TABLE - 1;
key->hw_key_idx = entry;
+ /* fall through */
case VNT_KEY_ALLGROUP:
key_mode |= VNT_KEY_ALLGROUP;
if (onfly_latch)
key_mode |= VNT_KEY_ONFLY_ALL;
+ /* fall through */
case VNT_KEY_GROUP_ADDRESS:
key_mode |= mode;
+ /* fall through */
case VNT_KEY_GROUP:
key_mode |= (mode << 4);
key_mode |= VNT_KEY_GROUP;
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index 94e700fcd0b6..3fd87f95c524 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile
index 72a4daa05fdb..2ad3feed9725 100644
--- a/drivers/staging/wilc1000/Makefile
+++ b/drivers/staging/wilc1000/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_WILC1000) += wilc1000.o
ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \
-DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\"
-wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
+wilc1000-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \
host_interface.o wilc_wlan_cfg.o wilc_wlan.o
obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 70c854d939ce..4dd9a20f6a0b 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -6,25 +6,23 @@
#include "wilc_wfi_netdevice.h"
-#define HOST_IF_SCAN_TIMEOUT 4000
-#define HOST_IF_CONNECT_TIMEOUT 9500
+#define WILC_HIF_SCAN_TIMEOUT_MS 4000
+#define WILC_HIF_CONNECT_TIMEOUT_MS 9500
-#define FALSE_FRMWR_CHANNEL 100
+#define WILC_FALSE_FRMWR_CHANNEL 100
+#define WILC_MAX_RATES_SUPPORTED 12
-#define REAL_JOIN_REQ 0
-
-struct rcvd_async_info {
- u8 *buffer;
- u32 len;
+struct wilc_rcvd_mac_info {
+ u8 status;
};
-struct set_multicast {
- bool enabled;
+struct wilc_set_multicast {
+ u32 enabled;
u32 cnt;
u8 *mc_list;
};
-struct del_all_sta {
+struct wilc_del_all_sta {
u8 assoc_sta;
u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
};
@@ -36,7 +34,7 @@ struct wilc_op_mode {
struct wilc_reg_frame {
bool reg;
u8 reg_id;
- __le32 frame_type;
+ __le16 frame_type;
} __packed;
struct wilc_drv_handler {
@@ -71,16 +69,16 @@ struct wilc_gtk_key {
u8 key[0];
} __packed;
-union message_body {
- struct rcvd_net_info net_info;
- struct rcvd_async_info async_info;
- struct set_multicast multicast_info;
- struct remain_ch remain_on_ch;
+union wilc_message_body {
+ struct wilc_rcvd_net_info net_info;
+ struct wilc_rcvd_mac_info mac_info;
+ struct wilc_set_multicast mc_info;
+ struct wilc_remain_ch remain_on_ch;
char *data;
};
struct host_if_msg {
- union message_body body;
+ union wilc_message_body body;
struct wilc_vif *vif;
struct work_struct work;
void (*fn)(struct work_struct *ws);
@@ -88,37 +86,50 @@ struct host_if_msg {
bool is_sync;
};
-struct join_bss_param {
- enum bss_types bss_type;
+struct wilc_noa_opp_enable {
+ u8 ct_window;
+ u8 cnt;
+ __le32 duration;
+ __le32 interval;
+ __le32 start_time;
+} __packed;
+
+struct wilc_noa_opp_disable {
+ u8 cnt;
+ __le32 duration;
+ __le32 interval;
+ __le32 start_time;
+} __packed;
+
+struct wilc_join_bss_param {
+ char ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_terminator;
+ u8 bss_type;
+ u8 ch;
+ __le16 cap_info;
+ u8 sa[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ __le16 beacon_period;
u8 dtim_period;
- u16 beacon_period;
- u16 cap_info;
- u8 bssid[6];
- char ssid[MAX_SSID_LEN];
- u8 ssid_len;
- u8 supp_rates[MAX_RATES_SUPPORTED + 1];
- u8 ht_capable;
+ u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
u8 wmm_cap;
u8 uapsd_cap;
- bool rsn_found;
+ u8 ht_capable;
+ u8 rsn_found;
u8 rsn_grp_policy;
u8 mode_802_11i;
- u8 rsn_pcip_policy[3];
- u8 rsn_auth_policy[3];
+ u8 p_suites[3];
+ u8 akm_suites[3];
u8 rsn_cap[2];
- u32 tsf;
u8 noa_enabled;
- u8 opp_enabled;
- u8 ct_window;
- u8 cnt;
+ __le32 tsf_lo;
u8 idx;
- u8 duration[4];
- u8 interval[4];
- u8 start_time[4];
-};
-
-static struct host_if_drv *terminated_handle;
-static struct mutex hif_deinit_lock;
+ u8 opp_enabled;
+ union {
+ struct wilc_noa_opp_disable opp_dis;
+ struct wilc_noa_opp_enable opp_en;
+ };
+} __packed;
/* 'msg' should be free by the caller for syc */
static struct host_if_msg*
@@ -185,7 +196,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
u8 abort_running_scan;
struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
- struct user_scan_req *scan_req;
+ struct wilc_user_scan_req *scan_req;
if (evt == SCAN_EVENT_ABORTED) {
abort_running_scan = 1;
@@ -210,7 +221,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
scan_req = &hif_drv->usr_scan_req;
if (scan_req->scan_result) {
- scan_req->scan_result(evt, NULL, scan_req->arg, NULL);
+ scan_req->scan_result(evt, NULL, scan_req->arg);
scan_req->scan_result = NULL;
}
@@ -218,9 +229,10 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
}
int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
- u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
- size_t ies_len, wilc_scan_result scan_result, void *user_arg,
- struct hidden_network *hidden_net)
+ u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len,
+ void (*scan_result_fn)(enum scan_event,
+ struct wilc_rcvd_net_info *, void *),
+ void *user_arg, struct wilc_probe_ssid *search)
{
int result = 0;
struct wid wid_list[5];
@@ -228,7 +240,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
u32 i;
u8 *buffer;
u8 valuesize = 0;
- u8 *hdn_ntwk_wid_val = NULL;
+ u8 *search_ssid_vals = NULL;
struct host_if_drv *hif_drv = vif->hif_drv;
if (hif_drv->hif_state >= HOST_IF_SCANNING &&
@@ -246,26 +258,24 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
hif_drv->usr_scan_req.ch_cnt = 0;
- if (hidden_net) {
- wid_list[index].id = WID_SSID_PROBE_REQ;
- wid_list[index].type = WID_STR;
-
- for (i = 0; i < hidden_net->n_ssids; i++)
- valuesize += ((hidden_net->net_info[i].ssid_len) + 1);
- hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL);
- wid_list[index].val = hdn_ntwk_wid_val;
- if (wid_list[index].val) {
+ if (search) {
+ for (i = 0; i < search->n_ssids; i++)
+ valuesize += ((search->ssid_info[i].ssid_len) + 1);
+ search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
+ if (search_ssid_vals) {
+ wid_list[index].id = WID_SSID_PROBE_REQ;
+ wid_list[index].type = WID_STR;
+ wid_list[index].val = search_ssid_vals;
buffer = wid_list[index].val;
- *buffer++ = hidden_net->n_ssids;
+ *buffer++ = search->n_ssids;
- for (i = 0; i < hidden_net->n_ssids; i++) {
- *buffer++ = hidden_net->net_info[i].ssid_len;
- memcpy(buffer, hidden_net->net_info[i].ssid,
- hidden_net->net_info[i].ssid_len);
- buffer += hidden_net->net_info[i].ssid_len;
+ for (i = 0; i < search->n_ssids; i++) {
+ *buffer++ = search->ssid_info[i].ssid_len;
+ memcpy(buffer, search->ssid_info[i].ssid,
+ search->ssid_info[i].ssid_len);
+ buffer += search->ssid_info[i].ssid_len;
}
-
wid_list[index].size = (s32)(valuesize + 1);
index++;
}
@@ -311,16 +321,16 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
goto error;
}
- hif_drv->usr_scan_req.scan_result = scan_result;
+ hif_drv->usr_scan_req.scan_result = scan_result_fn;
hif_drv->usr_scan_req.arg = user_arg;
hif_drv->scan_timer_vif = vif;
mod_timer(&hif_drv->scan_timer,
- jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
+ jiffies + msecs_to_jiffies(WILC_HIF_SCAN_TIMEOUT_MS));
error:
- if (hidden_net) {
- kfree(hidden_net->net_info);
- kfree(hdn_ntwk_wid_val);
+ if (search) {
+ kfree(search->ssid_info);
+ kfree(search_ssid_vals);
}
return result;
@@ -329,35 +339,16 @@ error:
static int wilc_send_connect_wid(struct wilc_vif *vif)
{
int result = 0;
- struct wid wid_list[8];
- u32 wid_cnt = 0, dummyval = 0;
- u8 *cur_byte = NULL;
+ struct wid wid_list[4];
+ u32 wid_cnt = 0;
struct host_if_drv *hif_drv = vif->hif_drv;
- struct user_conn_req *conn_attr = &hif_drv->usr_conn_req;
- struct join_bss_param *bss_param = hif_drv->usr_conn_req.param;
-
- wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
- wid_list[wid_cnt].type = WID_INT;
- wid_list[wid_cnt].size = sizeof(u32);
- wid_list[wid_cnt].val = (s8 *)(&(dummyval));
- wid_cnt++;
-
- wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
- wid_list[wid_cnt].type = WID_INT;
- wid_list[wid_cnt].size = sizeof(u32);
- wid_list[wid_cnt].val = (s8 *)(&(dummyval));
- wid_cnt++;
-
- wid_list[wid_cnt].id = WID_FAILED_COUNT;
- wid_list[wid_cnt].type = WID_INT;
- wid_list[wid_cnt].size = sizeof(u32);
- wid_list[wid_cnt].val = (s8 *)(&(dummyval));
- wid_cnt++;
+ struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
+ struct wilc_join_bss_param *bss_param = conn_attr->param;
wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
wid_list[wid_cnt].type = WID_BIN_DATA;
- wid_list[wid_cnt].val = conn_attr->ies;
- wid_list[wid_cnt].size = conn_attr->ies_len;
+ wid_list[wid_cnt].val = conn_attr->req_ies;
+ wid_list[wid_cnt].size = conn_attr->req_ies_len;
wid_cnt++;
wid_list[wid_cnt].id = WID_11I_MODE;
@@ -374,97 +365,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif)
wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
wid_list[wid_cnt].type = WID_STR;
- wid_list[wid_cnt].size = 112;
- wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL);
-
- if (!wid_list[wid_cnt].val) {
- result = -EFAULT;
- goto error;
- }
-
- cur_byte = wid_list[wid_cnt].val;
-
- if (conn_attr->ssid) {
- memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len);
- cur_byte[conn_attr->ssid_len] = '\0';
- }
- cur_byte += MAX_SSID_LEN;
- *(cur_byte++) = WILC_FW_BSS_TYPE_INFRA;
-
- if (conn_attr->ch >= 1 && conn_attr->ch <= 14) {
- *(cur_byte++) = conn_attr->ch;
- } else {
- netdev_err(vif->ndev, "Channel out of range\n");
- *(cur_byte++) = 0xFF;
- }
- put_unaligned_le16(bss_param->cap_info, cur_byte);
- cur_byte += 2;
-
- if (conn_attr->bssid)
- memcpy(cur_byte, conn_attr->bssid, 6);
- cur_byte += 6;
-
- if (conn_attr->bssid)
- memcpy(cur_byte, conn_attr->bssid, 6);
- cur_byte += 6;
-
- put_unaligned_le16(bss_param->beacon_period, cur_byte);
- cur_byte += 2;
- *(cur_byte++) = bss_param->dtim_period;
-
- memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1);
- cur_byte += (MAX_RATES_SUPPORTED + 1);
-
- *(cur_byte++) = bss_param->wmm_cap;
- *(cur_byte++) = bss_param->uapsd_cap;
-
- *(cur_byte++) = bss_param->ht_capable;
- conn_attr->ht_capable = bss_param->ht_capable;
-
- *(cur_byte++) = bss_param->rsn_found;
- *(cur_byte++) = bss_param->rsn_grp_policy;
- *(cur_byte++) = bss_param->mode_802_11i;
-
- memcpy(cur_byte, bss_param->rsn_pcip_policy,
- sizeof(bss_param->rsn_pcip_policy));
- cur_byte += sizeof(bss_param->rsn_pcip_policy);
-
- memcpy(cur_byte, bss_param->rsn_auth_policy,
- sizeof(bss_param->rsn_auth_policy));
- cur_byte += sizeof(bss_param->rsn_auth_policy);
-
- memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap));
- cur_byte += sizeof(bss_param->rsn_cap);
-
- *(cur_byte++) = REAL_JOIN_REQ;
- *(cur_byte++) = bss_param->noa_enabled;
-
- if (bss_param->noa_enabled) {
- put_unaligned_le32(bss_param->tsf, cur_byte);
- cur_byte += 4;
-
- *(cur_byte++) = bss_param->opp_enabled;
- *(cur_byte++) = bss_param->idx;
-
- if (bss_param->opp_enabled)
- *(cur_byte++) = bss_param->ct_window;
-
- *(cur_byte++) = bss_param->cnt;
-
- memcpy(cur_byte, bss_param->duration,
- sizeof(bss_param->duration));
- cur_byte += sizeof(bss_param->duration);
-
- memcpy(cur_byte, bss_param->interval,
- sizeof(bss_param->interval));
- cur_byte += sizeof(bss_param->interval);
-
- memcpy(cur_byte, bss_param->start_time,
- sizeof(bss_param->start_time));
- cur_byte += sizeof(bss_param->start_time);
- }
-
- cur_byte = wid_list[wid_cnt].val;
+ wid_list[wid_cnt].size = sizeof(*bss_param);
+ wid_list[wid_cnt].val = (u8 *)bss_param;
wid_cnt++;
result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
@@ -472,25 +374,17 @@ static int wilc_send_connect_wid(struct wilc_vif *vif)
wilc_get_vif_idx(vif));
if (result) {
netdev_err(vif->ndev, "failed to send config packet\n");
- kfree(cur_byte);
goto error;
} else {
hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
}
- kfree(cur_byte);
return 0;
error:
- kfree(conn_attr->bssid);
- conn_attr->bssid = NULL;
-
- kfree(conn_attr->ssid);
- conn_attr->ssid = NULL;
-
- kfree(conn_attr->ies);
- conn_attr->ies = NULL;
+ kfree(conn_attr->req_ies);
+ conn_attr->req_ies = NULL;
return result;
}
@@ -500,7 +394,6 @@ static void handle_connect_timeout(struct work_struct *work)
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
struct wilc_vif *vif = msg->vif;
int result;
- struct connect_info info;
struct wid wid;
u16 dummy_reason_code = 0;
struct host_if_drv *hif_drv = vif->hif_drv;
@@ -512,31 +405,11 @@ static void handle_connect_timeout(struct work_struct *work)
hif_drv->hif_state = HOST_IF_IDLE;
- memset(&info, 0, sizeof(struct connect_info));
+ if (hif_drv->conn_info.conn_result) {
+ hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
+ WILC_MAC_STATUS_DISCONNECTED,
+ hif_drv->conn_info.arg);
- if (hif_drv->usr_conn_req.conn_result) {
- if (hif_drv->usr_conn_req.bssid) {
- memcpy(info.bssid,
- hif_drv->usr_conn_req.bssid, 6);
- }
-
- if (hif_drv->usr_conn_req.ies) {
- info.req_ies_len = hif_drv->usr_conn_req.ies_len;
- info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
- hif_drv->usr_conn_req.ies_len,
- GFP_KERNEL);
- if (!info.req_ies)
- goto out;
- }
-
- hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
- &info,
- WILC_MAC_STATUS_DISCONNECTED,
- NULL,
- hif_drv->usr_conn_req.arg);
-
- kfree(info.req_ies);
- info.req_ies = NULL;
} else {
netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
}
@@ -551,346 +424,174 @@ static void handle_connect_timeout(struct work_struct *work)
if (result)
netdev_err(vif->ndev, "Failed to send disconnect\n");
- hif_drv->usr_conn_req.ssid_len = 0;
- kfree(hif_drv->usr_conn_req.ssid);
- hif_drv->usr_conn_req.ssid = NULL;
- kfree(hif_drv->usr_conn_req.bssid);
- hif_drv->usr_conn_req.bssid = NULL;
- hif_drv->usr_conn_req.ies_len = 0;
- kfree(hif_drv->usr_conn_req.ies);
- hif_drv->usr_conn_req.ies = NULL;
+ hif_drv->conn_info.req_ies_len = 0;
+ kfree(hif_drv->conn_info.req_ies);
+ hif_drv->conn_info.req_ies = NULL;
out:
kfree(msg);
}
-static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies,
- u16 *out_index, u8 *pcipher_tc,
- u8 *auth_total_cnt, u32 tsf_lo,
- u8 *rates_no)
+void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ struct cfg80211_crypto_settings *crypto)
{
- u8 ext_rates_no;
- u16 offset;
- u8 pcipher_cnt;
- u8 auth_cnt;
- u8 i, j;
- u16 index = *out_index;
-
- if (ies[index] == WLAN_EID_SUPP_RATES) {
- *rates_no = ies[index + 1];
- param->supp_rates[0] = *rates_no;
- index += 2;
-
- for (i = 0; i < *rates_no; i++)
- param->supp_rates[i + 1] = ies[index + i];
-
- index += *rates_no;
- } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) {
- ext_rates_no = ies[index + 1];
- if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no))
- param->supp_rates[0] = MAX_RATES_SUPPORTED;
- else
- param->supp_rates[0] += ext_rates_no;
- index += 2;
- for (i = 0; i < (param->supp_rates[0] - *rates_no); i++)
- param->supp_rates[*rates_no + i + 1] = ies[index + i];
-
- index += ext_rates_no;
- } else if (ies[index] == WLAN_EID_HT_CAPABILITY) {
- param->ht_capable = true;
- index += ies[index + 1] + 2;
- } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
- (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) &&
- (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) &&
- ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) &&
- (ies[index + 7] == 0x01)) {
- param->wmm_cap = true;
-
- if (ies[index + 8] & BIT(7))
- param->uapsd_cap = true;
- index += ies[index + 1] + 2;
- } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
- (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) &&
- (ies[index + 4] == 0x9a) &&
- (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) {
- u16 p2p_cnt;
-
- param->tsf = tsf_lo;
- param->noa_enabled = 1;
- param->idx = ies[index + 9];
-
- if (ies[index + 10] & BIT(7)) {
- param->opp_enabled = 1;
- param->ct_window = ies[index + 10];
- } else {
- param->opp_enabled = 0;
- }
-
- param->cnt = ies[index + 11];
- p2p_cnt = index + 12;
-
- memcpy(param->duration, ies + p2p_cnt, 4);
- p2p_cnt += 4;
-
- memcpy(param->interval, ies + p2p_cnt, 4);
- p2p_cnt += 4;
-
- memcpy(param->start_time, ies + p2p_cnt, 4);
-
- index += ies[index + 1] + 2;
- } else if ((ies[index] == WLAN_EID_RSN) ||
- ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
- (ies[index + 2] == 0x00) &&
- (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) &&
- (ies[index + 5] == 0x01))) {
- u16 rsn_idx = index;
-
- if (ies[rsn_idx] == WLAN_EID_RSN) {
- param->mode_802_11i = 2;
- } else {
- if (param->mode_802_11i == 0)
- param->mode_802_11i = 1;
- rsn_idx += 4;
- }
-
- rsn_idx += 7;
- param->rsn_grp_policy = ies[rsn_idx];
- rsn_idx++;
- offset = ies[rsn_idx] * 4;
- pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
- rsn_idx += 2;
-
- i = *pcipher_tc;
- j = 0;
- for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) {
- u8 *policy = &param->rsn_pcip_policy[i];
-
- *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
- }
-
- *pcipher_tc += pcipher_cnt;
- rsn_idx += offset;
-
- offset = ies[rsn_idx] * 4;
-
- auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
- rsn_idx += 2;
- i = *auth_total_cnt;
- j = 0;
- for (; i < (*auth_total_cnt + auth_cnt); i++, j++) {
- u8 *policy = &param->rsn_auth_policy[i];
-
- *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
- }
-
- *auth_total_cnt += auth_cnt;
- rsn_idx += offset;
-
- if (ies[index] == WLAN_EID_RSN) {
- param->rsn_cap[0] = ies[rsn_idx];
- param->rsn_cap[1] = ies[rsn_idx + 1];
- rsn_idx += 2;
- }
- param->rsn_found = true;
- index += ies[index + 1] + 2;
- } else {
- index += ies[index + 1] + 2;
- }
-
- *out_index = index;
-}
-
-static void *host_int_parse_join_bss_param(struct network_info *info)
-{
- struct join_bss_param *param;
- u16 index = 0;
- u8 rates_no = 0;
- u8 pcipher_total_cnt = 0;
- u8 auth_total_cnt = 0;
+ struct wilc_join_bss_param *param;
+ struct ieee80211_p2p_noa_attr noa_attr;
+ u8 rates_len = 0;
+ const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
+ const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
+ int ret;
+ const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
param = kzalloc(sizeof(*param), GFP_KERNEL);
if (!param)
return NULL;
- param->dtim_period = info->dtim_period;
- param->beacon_period = info->beacon_period;
- param->cap_info = info->cap_info;
- memcpy(param->bssid, info->bssid, 6);
- memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1);
- param->ssid_len = info->ssid_len;
- memset(param->rsn_pcip_policy, 0xFF, 3);
- memset(param->rsn_auth_policy, 0xFF, 3);
-
- while (index < info->ies_len)
- host_int_fill_join_bss_param(param, info->ies, &index,
- &pcipher_total_cnt,
- &auth_total_cnt, info->tsf_lo,
- &rates_no);
-
- return (void *)param;
-}
-
-static inline u8 *get_bssid(struct ieee80211_mgmt *mgmt)
-{
- if (ieee80211_has_fromds(mgmt->frame_control))
- return mgmt->sa;
- else if (ieee80211_has_tods(mgmt->frame_control))
- return mgmt->da;
- else
- return mgmt->bssid;
-}
+ param->beacon_period = cpu_to_le16(bss->beacon_interval);
+ param->cap_info = cpu_to_le16(bss->capability);
+ param->bss_type = WILC_FW_BSS_TYPE_INFRA;
+ param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
+ ether_addr_copy(param->bssid, bss->bssid);
-static s32 wilc_parse_network_info(u8 *msg_buffer,
- struct network_info **ret_network_info)
-{
- struct network_info *info;
- struct ieee80211_mgmt *mgt;
- u8 *wid_val, *msa, *ies;
- u16 wid_len, rx_len, ies_len;
- u8 msg_type;
- size_t offset;
- const u8 *ch_elm, *tim_elm, *ssid_elm;
-
- msg_type = msg_buffer[0];
- if ('N' != msg_type)
- return -EFAULT;
+ ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
+ if (ssid_elm) {
+ if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
+ memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
+ }
- wid_len = get_unaligned_le16(&msg_buffer[6]);
- wid_val = &msg_buffer[8];
+ tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
+ if (tim_elm && tim_elm[1] >= 2)
+ param->dtim_period = tim_elm[3];
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
+ memset(param->p_suites, 0xFF, 3);
+ memset(param->akm_suites, 0xFF, 3);
- info->rssi = wid_val[0];
+ rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
+ if (rates_ie) {
+ rates_len = rates_ie[1];
+ param->supp_rates[0] = rates_len;
+ memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
+ }
- msa = &wid_val[1];
- mgt = (struct ieee80211_mgmt *)&wid_val[1];
- rx_len = wid_len - 1;
+ supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data,
+ ies->len);
+ if (supp_rates_ie) {
+ if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len))
+ param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
+ else
+ param->supp_rates[0] += supp_rates_ie[1];
- if (ieee80211_is_probe_resp(mgt->frame_control)) {
- info->cap_info = le16_to_cpu(mgt->u.probe_resp.capab_info);
- info->beacon_period = le16_to_cpu(mgt->u.probe_resp.beacon_int);
- info->tsf = le64_to_cpu(mgt->u.probe_resp.timestamp);
- info->tsf_lo = (u32)info->tsf;
- offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
- } else if (ieee80211_is_beacon(mgt->frame_control)) {
- info->cap_info = le16_to_cpu(mgt->u.beacon.capab_info);
- info->beacon_period = le16_to_cpu(mgt->u.beacon.beacon_int);
- info->tsf = le64_to_cpu(mgt->u.beacon.timestamp);
- info->tsf_lo = (u32)info->tsf;
- offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
- } else {
- /* only process probe response and beacon frame */
- kfree(info);
- return -EIO;
+ memcpy(&param->supp_rates[rates_len + 1], supp_rates_ie + 2,
+ (param->supp_rates[0] - rates_len));
}
- ether_addr_copy(info->bssid, get_bssid(mgt));
+ ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
+ if (ht_ie)
+ param->ht_capable = true;
- ies = mgt->u.beacon.variable;
- ies_len = rx_len - offset;
- if (ies_len <= 0) {
- kfree(info);
- return -EIO;
+ ret = cfg80211_get_p2p_attr(ies->data, ies->len,
+ IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+ (u8 *)&noa_attr, sizeof(noa_attr));
+ if (ret > 0) {
+ param->tsf_lo = cpu_to_le32(ies->tsf);
+ param->noa_enabled = 1;
+ param->idx = noa_attr.index;
+ if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
+ param->opp_enabled = 1;
+ param->opp_en.ct_window = noa_attr.oppps_ctwindow;
+ param->opp_en.cnt = noa_attr.desc[0].count;
+ param->opp_en.duration = noa_attr.desc[0].duration;
+ param->opp_en.interval = noa_attr.desc[0].interval;
+ param->opp_en.start_time = noa_attr.desc[0].start_time;
+ } else {
+ param->opp_enabled = 0;
+ param->opp_dis.cnt = noa_attr.desc[0].count;
+ param->opp_dis.duration = noa_attr.desc[0].duration;
+ param->opp_dis.interval = noa_attr.desc[0].interval;
+ param->opp_dis.start_time = noa_attr.desc[0].start_time;
+ }
+ }
+ wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WMM,
+ ies->data, ies->len);
+ if (wmm_ie) {
+ struct ieee80211_wmm_param_ie *ie;
+
+ ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
+ if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
+ ie->version == 1) {
+ param->wmm_cap = true;
+ if (ie->qos_info & BIT(7))
+ param->uapsd_cap = true;
+ }
}
- info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
- if (!info->ies) {
- kfree(info);
- return -ENOMEM;
+ wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WPA,
+ ies->data, ies->len);
+ if (wpa_ie) {
+ param->mode_802_11i = 1;
+ param->rsn_found = true;
}
- info->ies_len = ies_len;
+ rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
+ if (rsn_ie) {
+ int offset = 8;
- ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
- if (ssid_elm) {
- info->ssid_len = ssid_elm[1];
- if (info->ssid_len <= IEEE80211_MAX_SSID_LEN)
- memcpy(info->ssid, ssid_elm + 2, info->ssid_len);
- else
- info->ssid_len = 0;
+ param->mode_802_11i = 2;
+ param->rsn_found = true;
+ //extract RSN capabilities
+ offset += (rsn_ie[offset] * 4) + 2;
+ offset += (rsn_ie[offset] * 4) + 2;
+ memcpy(param->rsn_cap, &rsn_ie[offset], 2);
}
- ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
- if (ch_elm && ch_elm[1] > 0)
- info->ch = ch_elm[2];
+ if (param->rsn_found) {
+ int i;
- tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
- if (tim_elm && tim_elm[1] >= 2)
- info->dtim_period = tim_elm[3];
+ param->rsn_grp_policy = crypto->cipher_group & 0xFF;
+ for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
+ param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
- *ret_network_info = info;
+ for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
+ param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
+ }
- return 0;
+ return (void *)param;
}
static void handle_rcvd_ntwrk_info(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
- struct wilc_vif *vif = msg->vif;
- struct rcvd_net_info *rcvd_info = &msg->body.net_info;
- u32 i;
- bool found;
- struct network_info *info = NULL;
- void *params;
- struct host_if_drv *hif_drv = vif->hif_drv;
- struct user_scan_req *scan_req = &hif_drv->usr_scan_req;
-
- found = true;
+ struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
+ struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
+ const u8 *ch_elm;
+ u8 *ies;
+ int ies_len;
+ size_t offset;
- if (!scan_req->scan_result)
+ if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
+ offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
+ offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ else
goto done;
- wilc_parse_network_info(rcvd_info->buffer, &info);
- if (!info || !scan_req->scan_result) {
- netdev_err(vif->ndev, "%s: info or scan result NULL\n",
- __func__);
+ ies = rcvd_info->mgmt->u.beacon.variable;
+ ies_len = rcvd_info->frame_len - offset;
+ if (ies_len <= 0)
goto done;
- }
-
- for (i = 0; i < scan_req->ch_cnt; i++) {
- if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) {
- if (info->rssi <= scan_req->net_info[i].rssi) {
- goto done;
- } else {
- scan_req->net_info[i].rssi = info->rssi;
- found = false;
- break;
- }
- }
- }
-
- if (found) {
- if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
- scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi;
-
- memcpy(scan_req->net_info[scan_req->ch_cnt].bssid,
- info->bssid, 6);
-
- scan_req->ch_cnt++;
- info->new_network = true;
- params = host_int_parse_join_bss_param(info);
+ ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
+ if (ch_elm && ch_elm[1] > 0)
+ rcvd_info->ch = ch_elm[2];
- scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
- scan_req->arg, params);
- }
- } else {
- info->new_network = false;
- scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
- scan_req->arg, NULL);
- }
+ if (scan_req->scan_result)
+ scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
+ scan_req->arg);
done:
- kfree(rcvd_info->buffer);
- rcvd_info->buffer = NULL;
-
- if (info) {
- kfree(info->ies);
- kfree(info);
- }
-
+ kfree(rcvd_info->mgmt);
kfree(msg);
}
@@ -918,20 +619,8 @@ static void host_int_get_assoc_res_info(struct wilc_vif *vif,
*rcvd_assoc_resp_info_len = wid.size;
}
-static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv)
-{
- hif_drv->usr_conn_req.ssid_len = 0;
- kfree(hif_drv->usr_conn_req.ssid);
- hif_drv->usr_conn_req.ssid = NULL;
- kfree(hif_drv->usr_conn_req.bssid);
- hif_drv->usr_conn_req.bssid = NULL;
- hif_drv->usr_conn_req.ies_len = 0;
- kfree(hif_drv->usr_conn_req.ies);
- hif_drv->usr_conn_req.ies = NULL;
-}
-
static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
- struct connect_info *ret_conn_info)
+ struct wilc_conn_info *ret_conn_info)
{
u8 *ies;
u16 ies_len;
@@ -955,10 +644,8 @@ static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
u8 mac_status)
{
- struct connect_info conn_info;
struct host_if_drv *hif_drv = vif->hif_drv;
-
- memset(&conn_info, 0, sizeof(struct connect_info));
+ struct wilc_conn_info *conn_info = &hif_drv->conn_info;
if (mac_status == WILC_MAC_STATUS_CONNECTED) {
u32 assoc_resp_info_len;
@@ -974,7 +661,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
assoc_resp_info_len,
- &conn_info);
+ conn_info);
if (err)
netdev_err(vif->ndev,
"wilc_parse_assoc_resp_info() returned error %d\n",
@@ -982,31 +669,13 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
}
}
- if (hif_drv->usr_conn_req.bssid) {
- memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6);
-
- if (mac_status == WILC_MAC_STATUS_CONNECTED &&
- conn_info.status == WLAN_STATUS_SUCCESS) {
- memcpy(hif_drv->assoc_bssid,
- hif_drv->usr_conn_req.bssid, ETH_ALEN);
- }
- }
-
- if (hif_drv->usr_conn_req.ies) {
- conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
- hif_drv->usr_conn_req.ies_len,
- GFP_KERNEL);
- if (conn_info.req_ies)
- conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len;
- }
-
del_timer(&hif_drv->connect_timer);
- hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
- &conn_info, mac_status, NULL,
- hif_drv->usr_conn_req.arg);
+ conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
+ hif_drv->conn_info.arg);
if (mac_status == WILC_MAC_STATUS_CONNECTED &&
- conn_info.status == WLAN_STATUS_SUCCESS) {
+ conn_info->status == WLAN_STATUS_SUCCESS) {
+ ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
wilc_set_power_mgmt(vif, 0, 0);
hif_drv->hif_state = HOST_IF_CONNECTED;
@@ -1018,44 +687,39 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
hif_drv->hif_state = HOST_IF_IDLE;
}
- kfree(conn_info.resp_ies);
- conn_info.resp_ies = NULL;
+ kfree(conn_info->resp_ies);
+ conn_info->resp_ies = NULL;
+ conn_info->resp_ies_len = 0;
- kfree(conn_info.req_ies);
- conn_info.req_ies = NULL;
- host_int_free_user_conn_req(hif_drv);
+ kfree(conn_info->req_ies);
+ conn_info->req_ies = NULL;
+ conn_info->req_ies_len = 0;
}
static inline void host_int_handle_disconnect(struct wilc_vif *vif)
{
- struct disconnect_info disconn_info;
struct host_if_drv *hif_drv = vif->hif_drv;
- wilc_connect_result conn_result = hif_drv->usr_conn_req.conn_result;
-
- memset(&disconn_info, 0, sizeof(struct disconnect_info));
if (hif_drv->usr_scan_req.scan_result) {
del_timer(&hif_drv->scan_timer);
handle_scan_done(vif, SCAN_EVENT_ABORTED);
}
- disconn_info.reason = 0;
- disconn_info.ie = NULL;
- disconn_info.ie_len = 0;
-
- if (conn_result) {
+ if (hif_drv->conn_info.conn_result) {
vif->obtaining_ip = false;
wilc_set_power_mgmt(vif, 0, 0);
- conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0,
- &disconn_info, hif_drv->usr_conn_req.arg);
+ hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
+ 0, hif_drv->conn_info.arg);
} else {
netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
}
eth_zero_addr(hif_drv->assoc_bssid);
- host_int_free_user_conn_req(hif_drv);
+ hif_drv->conn_info.req_ies_len = 0;
+ kfree(hif_drv->conn_info.req_ies);
+ hif_drv->conn_info.req_ies = NULL;
hif_drv->hif_state = HOST_IF_IDLE;
}
@@ -1063,55 +727,30 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
struct wilc_vif *vif = msg->vif;
- struct rcvd_async_info *rcvd_info = &msg->body.async_info;
- u8 msg_type;
- u8 mac_status;
+ struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
struct host_if_drv *hif_drv = vif->hif_drv;
- if (!rcvd_info->buffer) {
- netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__);
- goto free_msg;
- }
-
if (!hif_drv) {
netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
- goto free_rcvd_info;
+ goto free_msg;
}
- if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
- hif_drv->hif_state == HOST_IF_CONNECTED ||
- hif_drv->usr_scan_req.scan_result) {
- if (!hif_drv->usr_conn_req.conn_result) {
- netdev_err(vif->ndev, "%s: conn_result is NULL\n",
- __func__);
- goto free_rcvd_info;
- }
-
- msg_type = rcvd_info->buffer[0];
-
- if ('I' != msg_type) {
- netdev_err(vif->ndev, "Received Message incorrect.\n");
- goto free_rcvd_info;
- }
+ if (!hif_drv->conn_info.conn_result) {
+ netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
+ goto free_msg;
+ }
- mac_status = rcvd_info->buffer[7];
- if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
- host_int_parse_assoc_resp_info(vif, mac_status);
- } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) &&
- (hif_drv->hif_state == HOST_IF_CONNECTED)) {
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
+ host_int_parse_assoc_resp_info(vif, mac_info->status);
+ } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
+ if (hif_drv->hif_state == HOST_IF_CONNECTED) {
host_int_handle_disconnect(vif);
- } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) &&
- (hif_drv->usr_scan_req.scan_result)) {
+ } else if (hif_drv->usr_scan_req.scan_result) {
del_timer(&hif_drv->scan_timer);
- if (hif_drv->usr_scan_req.scan_result)
- handle_scan_done(vif, SCAN_EVENT_ABORTED);
+ handle_scan_done(vif, SCAN_EVENT_ABORTED);
}
}
-free_rcvd_info:
- kfree(rcvd_info->buffer);
- rcvd_info->buffer = NULL;
-
free_msg:
kfree(msg);
}
@@ -1120,9 +759,8 @@ int wilc_disconnect(struct wilc_vif *vif)
{
struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
- struct disconnect_info disconn_info;
- struct user_scan_req *scan_req;
- struct user_conn_req *conn_req;
+ struct wilc_user_scan_req *scan_req;
+ struct wilc_conn_info *conn_info;
int result;
u16 dummy_reason_code = 0;
@@ -1141,27 +779,21 @@ int wilc_disconnect(struct wilc_vif *vif)
return result;
}
- memset(&disconn_info, 0, sizeof(struct disconnect_info));
-
- disconn_info.reason = 0;
- disconn_info.ie = NULL;
- disconn_info.ie_len = 0;
scan_req = &hif_drv->usr_scan_req;
- conn_req = &hif_drv->usr_conn_req;
+ conn_info = &hif_drv->conn_info;
if (scan_req->scan_result) {
del_timer(&hif_drv->scan_timer);
- scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg,
- NULL);
+ scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
scan_req->scan_result = NULL;
}
- if (conn_req->conn_result) {
+ if (conn_info->conn_result) {
if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
del_timer(&hif_drv->connect_timer);
- conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
- 0, &disconn_info, conn_req->arg);
+ conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
+ conn_info->arg);
} else {
netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
}
@@ -1170,14 +802,9 @@ int wilc_disconnect(struct wilc_vif *vif)
eth_zero_addr(hif_drv->assoc_bssid);
- conn_req->ssid_len = 0;
- kfree(conn_req->ssid);
- conn_req->ssid = NULL;
- kfree(conn_req->bssid);
- conn_req->bssid = NULL;
- conn_req->ies_len = 0;
- kfree(conn_req->ies);
- conn_req->ies = NULL;
+ conn_info->req_ies_len = 0;
+ kfree(conn_info->req_ies);
+ conn_info->req_ies = NULL;
return 0;
}
@@ -1285,47 +912,29 @@ static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
}
static int handle_remain_on_chan(struct wilc_vif *vif,
- struct remain_ch *hif_remain_ch)
+ struct wilc_remain_ch *hif_remain_ch)
{
int result;
u8 remain_on_chan_flag;
struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
- if (!hif_drv->remain_on_ch_pending) {
- hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
- hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
- hif_drv->remain_on_ch.ready = hif_remain_ch->ready;
- hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
- hif_drv->remain_on_ch.id = hif_remain_ch->id;
- } else {
- hif_remain_ch->ch = hif_drv->remain_on_ch.ch;
- }
+ if (hif_drv->usr_scan_req.scan_result)
+ return -EBUSY;
- if (hif_drv->usr_scan_req.scan_result) {
- hif_drv->remain_on_ch_pending = 1;
- result = -EBUSY;
- goto error;
- }
- if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
- result = -EBUSY;
- goto error;
- }
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
+ return -EBUSY;
- if (vif->obtaining_ip || vif->connecting) {
- result = -EBUSY;
- goto error;
- }
+ if (vif->obtaining_ip || vif->connecting)
+ return -EBUSY;
remain_on_chan_flag = true;
wid.id = WID_REMAIN_ON_CHAN;
wid.type = WID_STR;
wid.size = 2;
wid.val = kmalloc(wid.size, GFP_KERNEL);
- if (!wid.val) {
- result = -ENOMEM;
- goto error;
- }
+ if (!wid.val)
+ return -ENOMEM;
wid.val[0] = remain_on_chan_flag;
wid.val[1] = (s8)hif_remain_ch->ch;
@@ -1333,28 +942,23 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
kfree(wid.val);
- if (result != 0)
- netdev_err(vif->ndev, "Failed to set remain on channel\n");
+ if (result)
+ return -EBUSY;
-error:
+ hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
+ hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
+ hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
+ hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
hif_drv->remain_on_ch_timer_vif = vif;
- mod_timer(&hif_drv->remain_on_ch_timer,
- jiffies + msecs_to_jiffies(hif_remain_ch->duration));
-
- if (hif_drv->remain_on_ch.ready)
- hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
-
- if (hif_drv->remain_on_ch_pending)
- hif_drv->remain_on_ch_pending = 0;
- return result;
+ return 0;
}
static void handle_listen_state_expired(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
struct wilc_vif *vif = msg->vif;
- struct remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
+ struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
u8 remain_on_chan_flag;
struct wid wid;
int result;
@@ -1372,7 +976,7 @@ static void handle_listen_state_expired(struct work_struct *work)
goto free_msg;
wid.val[0] = remain_on_chan_flag;
- wid.val[1] = FALSE_FRMWR_CHANNEL;
+ wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
@@ -1384,7 +988,7 @@ static void handle_listen_state_expired(struct work_struct *work)
if (hif_drv->remain_on_ch.expired) {
hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
- hif_remain_ch->id);
+ hif_remain_ch->cookie);
}
} else {
netdev_dbg(vif->ndev, "Not in listen state\n");
@@ -1408,7 +1012,7 @@ static void listen_timer_cb(struct timer_list *t)
if (IS_ERR(msg))
return;
- msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
+ msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
result = wilc_enqueue_work(msg);
if (result) {
@@ -1421,32 +1025,27 @@ static void handle_set_mcast_filter(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
struct wilc_vif *vif = msg->vif;
- struct set_multicast *hif_set_mc = &msg->body.multicast_info;
+ struct wilc_set_multicast *set_mc = &msg->body.mc_info;
int result;
struct wid wid;
u8 *cur_byte;
wid.id = WID_SETUP_MULTICAST_FILTER;
wid.type = WID_BIN;
- wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN);
+ wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
wid.val = kmalloc(wid.size, GFP_KERNEL);
if (!wid.val)
goto error;
cur_byte = wid.val;
- *cur_byte++ = (hif_set_mc->enabled & 0xFF);
- *cur_byte++ = 0;
- *cur_byte++ = 0;
- *cur_byte++ = 0;
+ put_unaligned_le32(set_mc->enabled, cur_byte);
+ cur_byte += 4;
- *cur_byte++ = (hif_set_mc->cnt & 0xFF);
- *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF);
- *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF);
- *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF);
+ put_unaligned_le32(set_mc->cnt, cur_byte);
+ cur_byte += 4;
- if (hif_set_mc->cnt > 0 && hif_set_mc->mc_list)
- memcpy(cur_byte, hif_set_mc->mc_list,
- ((hif_set_mc->cnt) * ETH_ALEN));
+ if (set_mc->cnt > 0 && set_mc->mc_list)
+ memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
@@ -1454,7 +1053,7 @@ static void handle_set_mcast_filter(struct work_struct *work)
netdev_err(vif->ndev, "Failed to send setup multicast\n");
error:
- kfree(hif_set_mc->mc_list);
+ kfree(set_mc->mc_list);
kfree(wid.val);
kfree(msg);
}
@@ -1479,9 +1078,6 @@ static void handle_scan_complete(struct work_struct *work)
handle_scan_done(msg->vif, SCAN_EVENT_DONE);
- if (msg->vif->hif_drv->remain_on_ch_pending)
- handle_remain_on_chan(msg->vif,
- &msg->vif->hif_drv->remain_on_ch);
kfree(msg);
}
@@ -1629,7 +1225,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
u8 mode, u8 cipher_mode, u8 index)
{
int result = 0;
- u8 t_key_len = ptk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN;
+ u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
if (mode == WILC_AP_MODE) {
struct wid wid_list[2];
@@ -1651,11 +1247,11 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
if (rx_mic)
memcpy(&key_buf->key[ptk_key_len], rx_mic,
- RX_MIC_KEY_LEN);
+ WILC_RX_MIC_KEY_LEN);
if (tx_mic)
- memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN],
- tx_mic, TX_MIC_KEY_LEN);
+ memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
+ tx_mic, WILC_TX_MIC_KEY_LEN);
wid_list[1].id = WID_ADD_PTK;
wid_list[1].type = WID_STR;
@@ -1679,11 +1275,11 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
if (rx_mic)
memcpy(&key_buf->key[ptk_key_len], rx_mic,
- RX_MIC_KEY_LEN);
+ WILC_RX_MIC_KEY_LEN);
if (tx_mic)
- memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN],
- tx_mic, TX_MIC_KEY_LEN);
+ memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
+ tx_mic, WILC_TX_MIC_KEY_LEN);
wid.id = WID_ADD_PTK;
wid.type = WID_STR;
@@ -1704,7 +1300,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
{
int result = 0;
struct wilc_gtk_key *gtk_key;
- int t_key_len = gtk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN;
+ int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
if (!gtk_key)
@@ -1722,11 +1318,11 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
if (rx_mic)
- memcpy(&gtk_key->key[gtk_key_len], rx_mic, RX_MIC_KEY_LEN);
+ memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
if (tx_mic)
- memcpy(&gtk_key->key[gtk_key_len + RX_MIC_KEY_LEN],
- tx_mic, TX_MIC_KEY_LEN);
+ memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
+ tx_mic, WILC_TX_MIC_KEY_LEN);
if (mode == WILC_AP_MODE) {
struct wid wid_list[2];
@@ -1744,7 +1340,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
ARRAY_SIZE(wid_list),
wilc_get_vif_idx(vif));
- kfree(gtk_key);
} else if (mode == WILC_STATION_MODE) {
struct wid wid;
@@ -1754,9 +1349,9 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
wid.val = (u8 *)gtk_key;
result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
- kfree(gtk_key);
}
+ kfree(gtk_key);
return result;
}
@@ -1794,61 +1389,22 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
return result;
}
-int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
- size_t ssid_len, const u8 *ies, size_t ies_len,
- wilc_connect_result connect_result, void *user_arg,
- u8 security, enum authtype auth_type,
- u8 channel, void *join_params)
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
+ size_t ies_len)
{
int result;
struct host_if_drv *hif_drv = vif->hif_drv;
- struct user_conn_req *con_info = &hif_drv->usr_conn_req;
+ struct wilc_conn_info *conn_info = &hif_drv->conn_info;
- if (!hif_drv || !connect_result) {
- netdev_err(vif->ndev,
- "%s: hif driver or connect result is NULL",
- __func__);
- return -EFAULT;
- }
-
- if (!join_params) {
- netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__);
- return -EFAULT;
- }
-
- if (hif_drv->usr_scan_req.scan_result) {
- netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);
- return -EBUSY;
- }
-
- con_info->security = security;
- con_info->auth_type = auth_type;
- con_info->ch = channel;
- con_info->conn_result = connect_result;
- con_info->arg = user_arg;
- con_info->param = join_params;
-
- if (bssid) {
- con_info->bssid = kmemdup(bssid, 6, GFP_KERNEL);
- if (!con_info->bssid)
- return -ENOMEM;
- }
-
- if (ssid) {
- con_info->ssid_len = ssid_len;
- con_info->ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
- if (!con_info->ssid) {
- result = -ENOMEM;
- goto free_bssid;
- }
- }
+ if (bssid)
+ ether_addr_copy(conn_info->bssid, bssid);
if (ies) {
- con_info->ies_len = ies_len;
- con_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
- if (!con_info->ies) {
+ conn_info->req_ies_len = ies_len;
+ conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
+ if (!conn_info->req_ies) {
result = -ENOMEM;
- goto free_ssid;
+ return result;
}
}
@@ -1858,18 +1414,12 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
hif_drv->connect_timer_vif = vif;
mod_timer(&hif_drv->connect_timer,
- jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
+ jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
return 0;
free_ies:
- kfree(con_info->ies);
-
-free_ssid:
- kfree(con_info->ssid);
-
-free_bssid:
- kfree(con_info->bssid);
+ kfree(conn_info->req_ies);
return result;
}
@@ -1900,6 +1450,9 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
int result;
struct wilc_drv_handler drv;
+ if (!hif_drv)
+ return -EFAULT;
+
wid.id = WID_SET_DRV_HANDLER;
wid.type = WID_STR;
wid.size = sizeof(drv);
@@ -1992,7 +1545,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
return result;
}
-int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
+static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
{
int result;
struct host_if_msg *msg;
@@ -2091,7 +1644,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
vif->obtaining_ip = false;
if (wilc->clients_count == 0)
- mutex_init(&hif_deinit_lock);
+ mutex_init(&wilc->deinit_lock);
timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
@@ -2119,9 +1672,7 @@ int wilc_deinit(struct wilc_vif *vif)
return -EFAULT;
}
- mutex_lock(&hif_deinit_lock);
-
- terminated_handle = hif_drv;
+ mutex_lock(&vif->wilc->deinit_lock);
del_timer_sync(&hif_drv->scan_timer);
del_timer_sync(&hif_drv->connect_timer);
@@ -2132,18 +1683,16 @@ int wilc_deinit(struct wilc_vif *vif)
if (hif_drv->usr_scan_req.scan_result) {
hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
- hif_drv->usr_scan_req.arg,
- NULL);
+ hif_drv->usr_scan_req.arg);
hif_drv->usr_scan_req.scan_result = NULL;
}
hif_drv->hif_state = HOST_IF_IDLE;
kfree(hif_drv);
-
+ vif->hif_drv = NULL;
vif->wilc->clients_count--;
- terminated_handle = NULL;
- mutex_unlock(&hif_deinit_lock);
+ mutex_unlock(&vif->wilc->deinit_lock);
return result;
}
@@ -2155,16 +1704,13 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
struct host_if_drv *hif_drv;
struct wilc_vif *vif;
- id = buffer[length - 4];
- id |= (buffer[length - 3] << 8);
- id |= (buffer[length - 2] << 16);
- id |= (buffer[length - 1] << 24);
+ id = get_unaligned_le32(&buffer[length - 4]);
vif = wilc_get_vif_from_idx(wilc, id);
if (!vif)
return;
hif_drv = vif->hif_drv;
- if (!hif_drv || hif_drv == terminated_handle) {
+ if (!hif_drv) {
netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
return;
}
@@ -2173,9 +1719,12 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
if (IS_ERR(msg))
return;
- msg->body.net_info.len = length;
- msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
- if (!msg->body.net_info.buffer) {
+ msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
+ msg->body.net_info.rssi = buffer[8];
+ msg->body.net_info.mgmt = kmemdup(&buffer[9],
+ msg->body.net_info.frame_len,
+ GFP_KERNEL);
+ if (!msg->body.net_info.mgmt) {
kfree(msg);
return;
}
@@ -2183,7 +1732,7 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
result = wilc_enqueue_work(msg);
if (result) {
netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
- kfree(msg->body.net_info.buffer);
+ kfree(msg->body.net_info.mgmt);
kfree(msg);
}
}
@@ -2196,53 +1745,42 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
struct host_if_drv *hif_drv;
struct wilc_vif *vif;
- mutex_lock(&hif_deinit_lock);
+ mutex_lock(&wilc->deinit_lock);
- id = buffer[length - 4];
- id |= (buffer[length - 3] << 8);
- id |= (buffer[length - 2] << 16);
- id |= (buffer[length - 1] << 24);
+ id = get_unaligned_le32(&buffer[length - 4]);
vif = wilc_get_vif_from_idx(wilc, id);
if (!vif) {
- mutex_unlock(&hif_deinit_lock);
+ mutex_unlock(&wilc->deinit_lock);
return;
}
hif_drv = vif->hif_drv;
- if (!hif_drv || hif_drv == terminated_handle) {
- mutex_unlock(&hif_deinit_lock);
+ if (!hif_drv) {
+ mutex_unlock(&wilc->deinit_lock);
return;
}
- if (!hif_drv->usr_conn_req.conn_result) {
+ if (!hif_drv->conn_info.conn_result) {
netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
- mutex_unlock(&hif_deinit_lock);
+ mutex_unlock(&wilc->deinit_lock);
return;
}
msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
if (IS_ERR(msg)) {
- mutex_unlock(&hif_deinit_lock);
- return;
- }
-
- msg->body.async_info.len = length;
- msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
- if (!msg->body.async_info.buffer) {
- kfree(msg);
- mutex_unlock(&hif_deinit_lock);
+ mutex_unlock(&wilc->deinit_lock);
return;
}
+ msg->body.mac_info.status = buffer[7];
result = wilc_enqueue_work(msg);
if (result) {
netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
- kfree(msg->body.async_info.buffer);
kfree(msg);
}
- mutex_unlock(&hif_deinit_lock);
+ mutex_unlock(&wilc->deinit_lock);
}
void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
@@ -2252,16 +1790,13 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
struct host_if_drv *hif_drv;
struct wilc_vif *vif;
- id = buffer[length - 4];
- id |= buffer[length - 3] << 8;
- id |= buffer[length - 2] << 16;
- id |= buffer[length - 1] << 24;
+ id = get_unaligned_le32(&buffer[length - 4]);
vif = wilc_get_vif_from_idx(wilc, id);
if (!vif)
return;
hif_drv = vif->hif_drv;
- if (!hif_drv || hif_drv == terminated_handle)
+ if (!hif_drv)
return;
if (hif_drv->usr_scan_req.scan_result) {
@@ -2280,21 +1815,19 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
}
}
-int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
u32 duration, u16 chan,
- wilc_remain_on_chan_expired expired,
- wilc_remain_on_chan_ready ready,
+ void (*expired)(void *, u64),
void *user_arg)
{
- struct remain_ch roc;
+ struct wilc_remain_ch roc;
int result;
roc.ch = chan;
roc.expired = expired;
- roc.ready = ready;
roc.arg = user_arg;
roc.duration = duration;
- roc.id = session_id;
+ roc.cookie = cookie;
result = handle_remain_on_chan(vif, &roc);
if (result)
netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
@@ -2303,7 +1836,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
return result;
}
-int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
{
int result;
struct host_if_msg *msg;
@@ -2320,7 +1853,7 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
if (IS_ERR(msg))
return PTR_ERR(msg);
- msg->body.remain_on_ch.id = session_id;
+ msg->body.remain_on_ch.cookie = cookie;
result = wilc_enqueue_work(msg);
if (result) {
@@ -2485,7 +2018,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
int result;
int i;
u8 assoc_sta = 0;
- struct del_all_sta del_sta;
+ struct wilc_del_all_sta del_sta;
memset(&del_sta, 0x0, sizeof(del_sta));
for (i = 0; i < WILC_MAX_NUM_STA; i++) {
@@ -2564,7 +2097,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
return result;
}
-int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count,
+int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
u8 *mc_list)
{
int result;
@@ -2574,9 +2107,9 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count,
if (IS_ERR(msg))
return PTR_ERR(msg);
- msg->body.multicast_info.enabled = enabled;
- msg->body.multicast_info.cnt = count;
- msg->body.multicast_info.mc_list = mc_list;
+ msg->body.mc_info.enabled = enabled;
+ msg->body.mc_info.cnt = count;
+ msg->body.mc_info.mc_list = mc_list;
result = wilc_enqueue_work(msg);
if (result) {
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
index 9b396a79b144..678e62312215 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -18,19 +18,16 @@ enum {
};
#define WILC_MAX_NUM_STA 9
-#define MAX_NUM_SCANNED_NETWORKS 100
-#define MAX_NUM_SCANNED_NETWORKS_SHADOW 130
+#define WILC_MAX_NUM_SCANNED_CH 14
#define WILC_MAX_NUM_PROBED_SSID 10
-#define TX_MIC_KEY_LEN 8
-#define RX_MIC_KEY_LEN 8
+#define WILC_TX_MIC_KEY_LEN 8
+#define WILC_RX_MIC_KEY_LEN 8
#define WILC_MAX_NUM_PMKIDS 16
#define WILC_ADD_STA_LENGTH 40
#define WILC_NUM_CONCURRENT_IFC 2
-#define NUM_RSSI 5
-
enum {
WILC_SET_CFG = 0,
WILC_GET_CFG
@@ -38,48 +35,6 @@ enum {
#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256
-struct rssi_history_buffer {
- bool full;
- u8 index;
- s8 samples[NUM_RSSI];
-};
-
-struct network_info {
- s8 rssi;
- u16 cap_info;
- u8 ssid[MAX_SSID_LEN];
- u8 ssid_len;
- u8 bssid[6];
- u16 beacon_period;
- u8 dtim_period;
- u8 ch;
- unsigned long time_scan_cached;
- unsigned long time_scan;
- bool new_network;
- u8 found;
- u32 tsf_lo;
- u8 *ies;
- u16 ies_len;
- void *join_params;
- struct rssi_history_buffer rssi_history;
- u64 tsf;
-};
-
-struct connect_info {
- u8 bssid[6];
- u8 *req_ies;
- size_t req_ies_len;
- u8 *resp_ies;
- u16 resp_ies_len;
- u16 status;
-};
-
-struct disconnect_info {
- u16 reason;
- u8 *ie;
- size_t ie_len;
-};
-
struct assoc_resp {
__le16 capab_info;
__le16 status_code;
@@ -129,11 +84,6 @@ enum cfg_param {
WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3)
};
-struct found_net_info {
- u8 bssid[6];
- s8 rssi;
-};
-
enum scan_event {
SCAN_EVENT_NETWORK_FOUND = 0,
SCAN_EVENT_DONE = 1,
@@ -147,72 +97,71 @@ enum conn_event {
CONN_DISCONN_EVENT_FORCE_32BIT = 0xFFFFFFFF
};
-typedef void (*wilc_scan_result)(enum scan_event, struct network_info *,
- void *, void *);
-
-typedef void (*wilc_connect_result)(enum conn_event,
- struct connect_info *,
- u8,
- struct disconnect_info *,
- void *);
+enum {
+ WILC_HIF_SDIO = 0,
+ WILC_HIF_SPI = BIT(0)
+};
-typedef void (*wilc_remain_on_chan_expired)(void *, u32);
-typedef void (*wilc_remain_on_chan_ready)(void *);
+enum {
+ WILC_MAC_STATUS_INIT = -1,
+ WILC_MAC_STATUS_DISCONNECTED = 0,
+ WILC_MAC_STATUS_CONNECTED = 1
+};
-struct rcvd_net_info {
- u8 *buffer;
- u32 len;
+struct wilc_rcvd_net_info {
+ s8 rssi;
+ u8 ch;
+ u16 frame_len;
+ struct ieee80211_mgmt *mgmt;
};
-struct hidden_net_info {
- u8 *ssid;
+struct wilc_probe_ssid_info {
u8 ssid_len;
+ u8 *ssid;
};
-struct hidden_network {
- struct hidden_net_info *net_info;
+struct wilc_probe_ssid {
+ struct wilc_probe_ssid_info *ssid_info;
u8 n_ssids;
+ u32 size;
};
-struct user_scan_req {
- wilc_scan_result scan_result;
+struct wilc_user_scan_req {
+ void (*scan_result)(enum scan_event evt,
+ struct wilc_rcvd_net_info *info, void *priv);
void *arg;
u32 ch_cnt;
- struct found_net_info net_info[MAX_NUM_SCANNED_NETWORKS];
};
-struct user_conn_req {
- u8 *bssid;
- u8 *ssid;
+struct wilc_conn_info {
+ u8 bssid[ETH_ALEN];
u8 security;
enum authtype auth_type;
- size_t ssid_len;
- u8 *ies;
- size_t ies_len;
- wilc_connect_result conn_result;
- bool ht_capable;
u8 ch;
+ u8 *req_ies;
+ size_t req_ies_len;
+ u8 *resp_ies;
+ u16 resp_ies_len;
+ u16 status;
+ void (*conn_result)(enum conn_event evt, u8 status, void *priv_data);
void *arg;
void *param;
};
-struct remain_ch {
+struct wilc_remain_ch {
u16 ch;
u32 duration;
- wilc_remain_on_chan_expired expired;
- wilc_remain_on_chan_ready ready;
+ void (*expired)(void *priv, u64 cookie);
void *arg;
- u32 id;
+ u32 cookie;
};
struct wilc;
struct host_if_drv {
- struct user_scan_req usr_scan_req;
- struct user_conn_req usr_conn_req;
- struct remain_ch remain_on_ch;
- u8 remain_on_ch_pending;
+ struct wilc_user_scan_req usr_scan_req;
+ struct wilc_conn_info conn_info;
+ struct wilc_remain_ch remain_on_ch;
u64 p2p_timeout;
- u8 p2p_connect;
enum host_if_state hif_state;
@@ -232,17 +181,6 @@ struct host_if_drv {
u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
};
-struct add_sta_param {
- u8 bssid[ETH_ALEN];
- u16 aid;
- u8 rates_len;
- const u8 *rates;
- bool ht_supported;
- struct ieee80211_ht_cap ht_capa;
- u16 flags_mask;
- u16 flags_set;
-};
-
struct wilc_vif;
int wilc_remove_wep_key(struct wilc_vif *vif, u8 index);
int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index);
@@ -261,18 +199,16 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
u8 cipher_mode);
int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
-int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
- size_t ssid_len, const u8 *ies, size_t ies_len,
- wilc_connect_result connect_result, void *user_arg,
- u8 security, enum authtype auth_type,
- u8 channel, void *join_params);
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
+ size_t ies_len);
int wilc_disconnect(struct wilc_vif *vif);
int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
- u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
- size_t ies_len, wilc_scan_result scan_result, void *user_arg,
- struct hidden_network *hidden_network);
+ u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len,
+ void (*scan_result_fn)(enum scan_event,
+ struct wilc_rcvd_net_info *, void *),
+ void *user_arg, struct wilc_probe_ssid *search);
int wilc_hif_set_cfg(struct wilc_vif *vif,
struct cfg_param_attr *cfg_param);
int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler);
@@ -287,14 +223,13 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr);
int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
struct station_parameters *params);
int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
-int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count,
+int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
u8 *mc_list);
-int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
u32 duration, u16 chan,
- wilc_remain_on_chan_expired expired,
- wilc_remain_on_chan_ready ready,
+ void (*expired)(void *, u64),
void *user_arg);
-int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id);
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie);
void 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 mode,
u8 ifc_id);
@@ -307,4 +242,6 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length);
void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
+void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ struct cfg80211_crypto_settings *crypto);
#endif
diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/wilc_mon.c
index a63446818eac..9fe19a3e1dd4 100644
--- a/drivers/staging/wilc1000/linux_mon.c
+++ b/drivers/staging/wilc1000/wilc_mon.c
@@ -18,28 +18,20 @@ struct wilc_wfi_radiotap_cb_hdr {
u16 tx_flags;
} __packed;
-static struct net_device *wilc_wfi_mon; /* global monitor netdev */
-
-static u8 srcadd[6];
-static u8 bssid[6];
-
-#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
-#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
-
#define TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_TX_FLAGS))
-void wilc_wfi_monitor_rx(u8 *buff, u32 size)
+void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size)
{
u32 header, pkt_offset;
struct sk_buff *skb = NULL;
struct wilc_wfi_radiotap_hdr *hdr;
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
- if (!wilc_wfi_mon)
+ if (!mon_dev)
return;
- if (!netif_running(wilc_wfi_mon))
+ if (!netif_running(mon_dev))
return;
/* Get WILC header */
@@ -94,7 +86,7 @@ void wilc_wfi_monitor_rx(u8 *buff, u32 size)
hdr->rate = 5;
}
- skb->dev = wilc_wfi_mon;
+ skb->dev = mon_dev;
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
@@ -155,13 +147,13 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb,
struct wilc_wfi_mon_priv *mon_priv;
struct sk_buff *skb2;
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
+ u8 srcadd[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
- if (!wilc_wfi_mon)
- return -EFAULT;
-
- mon_priv = netdev_priv(wilc_wfi_mon);
+ mon_priv = netdev_priv(dev);
if (!mon_priv)
return -EFAULT;
+
rtap_len = ieee80211_get_radiotap_len(skb->data);
if (skb->len < rtap_len)
return -1;
@@ -187,7 +179,7 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb,
cb_hdr->rate = 5;
cb_hdr->tx_flags = 0x0004;
- skb2->dev = wilc_wfi_mon;
+ skb2->dev = dev;
skb_reset_mac_header(skb2);
skb2->ip_summed = CHECKSUM_UNNECESSARY;
skb2->pkt_type = PACKET_OTHERHOST;
@@ -200,8 +192,8 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb,
}
skb->dev = mon_priv->real_ndev;
- memcpy(srcadd, &skb->data[10], 6);
- memcpy(bssid, &skb->data[16], 6);
+ ether_addr_copy(srcadd, &skb->data[10]);
+ ether_addr_copy(bssid, &skb->data[16]);
/*
* Identify if data or mgmt packet, if source address and bssid
* fields are equal send it to mgmt frames handler
@@ -223,51 +215,44 @@ static const struct net_device_ops wilc_wfi_netdev_ops = {
};
-struct net_device *wilc_wfi_init_mon_interface(const char *name,
+struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
+ const char *name,
struct net_device *real_dev)
{
struct wilc_wfi_mon_priv *priv;
/*If monitor interface is already initialized, return it*/
- if (wilc_wfi_mon)
- return wilc_wfi_mon;
+ if (wl->monitor_dev)
+ return wl->monitor_dev;
- wilc_wfi_mon = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv));
- if (!wilc_wfi_mon)
+ wl->monitor_dev = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv));
+ if (!wl->monitor_dev)
return NULL;
- wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
- strncpy(wilc_wfi_mon->name, name, IFNAMSIZ);
- wilc_wfi_mon->name[IFNAMSIZ - 1] = 0;
- wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops;
- if (register_netdevice(wilc_wfi_mon)) {
+ wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP;
+ strncpy(wl->monitor_dev->name, name, IFNAMSIZ);
+ wl->monitor_dev->name[IFNAMSIZ - 1] = 0;
+ wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
+
+ if (register_netdevice(wl->monitor_dev)) {
netdev_err(real_dev, "register_netdevice failed\n");
return NULL;
}
- priv = netdev_priv(wilc_wfi_mon);
+ priv = netdev_priv(wl->monitor_dev);
if (!priv)
return NULL;
priv->real_ndev = real_dev;
- return wilc_wfi_mon;
+ return wl->monitor_dev;
}
-void wilc_wfi_deinit_mon_interface(void)
+void wilc_wfi_deinit_mon_interface(struct wilc *wl)
{
- bool rollback_lock = false;
-
- if (wilc_wfi_mon) {
- if (rtnl_is_locked()) {
- rtnl_unlock();
- rollback_lock = true;
- }
- unregister_netdev(wilc_wfi_mon);
+ if (!wl->monitor_dev)
+ return;
- if (rollback_lock) {
- rtnl_lock();
- rollback_lock = false;
- }
- wilc_wfi_mon = NULL;
- }
+ unregister_netdev(wl->monitor_dev);
+ free_netdev(wl->monitor_dev);
+ wl->monitor_dev = NULL;
}
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/wilc_netdev.c
index 721689048648..1787154ee088 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/wilc_netdev.c
@@ -12,86 +12,7 @@
#include "wilc_wfi_cfgoperations.h"
-static int dev_state_ev_handler(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- struct in_ifaddr *dev_iface = ptr;
- struct wilc_priv *priv;
- struct host_if_drv *hif_drv;
- struct net_device *dev;
- u8 *ip_addr_buf;
- struct wilc_vif *vif;
- u8 null_ip[4] = {0};
- char wlan_dev_name[5] = "wlan0";
-
- if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev)
- return NOTIFY_DONE;
-
- if (memcmp(dev_iface->ifa_label, "wlan0", 5) &&
- memcmp(dev_iface->ifa_label, "p2p0", 4))
- return NOTIFY_DONE;
-
- dev = (struct net_device *)dev_iface->ifa_dev->dev;
- if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
- return NOTIFY_DONE;
-
- priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- if (!priv)
- return NOTIFY_DONE;
-
- hif_drv = (struct host_if_drv *)priv->hif_drv;
- vif = netdev_priv(dev);
- if (!vif || !hif_drv)
- return NOTIFY_DONE;
-
- switch (event) {
- case NETDEV_UP:
- if (vif->iftype == WILC_STATION_MODE ||
- vif->iftype == WILC_CLIENT_MODE) {
- hif_drv->ifc_up = 1;
- vif->obtaining_ip = false;
- del_timer(&vif->during_ip_timer);
- }
-
- if (vif->wilc->enable_ps)
- wilc_set_power_mgmt(vif, 1, 0);
-
- netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label);
-
- ip_addr_buf = (char *)&dev_iface->ifa_address;
- netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
- ip_addr_buf[0], ip_addr_buf[1],
- ip_addr_buf[2], ip_addr_buf[3]);
-
- break;
-
- case NETDEV_DOWN:
- if (vif->iftype == WILC_STATION_MODE ||
- vif->iftype == WILC_CLIENT_MODE) {
- hif_drv->ifc_up = 0;
- vif->obtaining_ip = false;
- }
-
- if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
- wilc_set_power_mgmt(vif, 0, 0);
-
- wilc_resolve_disconnect_aberration(vif);
-
- netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label);
-
- ip_addr_buf = null_ip;
- netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
- ip_addr_buf[0], ip_addr_buf[1],
- ip_addr_buf[2], ip_addr_buf[3]);
-
- break;
-
- default:
- break;
- }
-
- return NOTIFY_DONE;
-}
+#define WILC_MULTICAST_TABLE_SIZE 8
static irqreturn_t isr_uh_routine(int irq, void *user_data)
{
@@ -198,7 +119,11 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
{
struct wilc_vif *vif = netdev_priv(wilc_netdev);
- memcpy(vif->bssid, bssid, 6);
+ if (bssid)
+ ether_addr_copy(vif->bssid, bssid);
+ else
+ eth_zero_addr(vif->bssid);
+
vif->mode = mode;
}
@@ -214,7 +139,7 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
return ret_val;
}
-static int linux_wlan_txq_task(void *vp)
+static int wilc_txq_task(void *vp)
{
int ret;
u32 txq_count;
@@ -236,9 +161,11 @@ static int linux_wlan_txq_task(void *vp)
do {
ret = wilc_wlan_handle_txq(dev, &txq_count);
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
- if (netif_queue_stopped(wl->vif[0]->ndev))
+ if (wl->vif[0]->mac_opened &&
+ netif_queue_stopped(wl->vif[0]->ndev))
netif_wake_queue(wl->vif[0]->ndev);
- if (netif_queue_stopped(wl->vif[1]->ndev))
+ if (wl->vif[1]->mac_opened &&
+ netif_queue_stopped(wl->vif[1]->ndev))
netif_wake_queue(wl->vif[1]->ndev);
}
} while (ret == -ENOBUFS && !wl->close);
@@ -275,7 +202,7 @@ fail:
return ret;
}
-static int linux_wlan_start_firmware(struct net_device *dev)
+static int wilc_start_firmware(struct net_device *dev)
{
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
@@ -316,204 +243,169 @@ static int wilc1000_firmware_download(struct net_device *dev)
return 0;
}
-static int linux_wlan_init_test_config(struct net_device *dev,
- struct wilc_vif *vif)
+static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
{
- unsigned char c_val[64];
- struct wilc *wilc = vif->wilc;
struct wilc_priv *priv;
struct host_if_drv *hif_drv;
+ u8 b;
+ u16 hw;
+ u32 w;
netdev_dbg(dev, "Start configuring Firmware\n");
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
hif_drv = (struct host_if_drv *)priv->hif_drv;
netdev_dbg(dev, "Host = %p\n", hif_drv);
- wilc_get_chipid(wilc, false);
-
- *(int *)c_val = 1;
-
- if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
- goto fail;
-
- c_val[0] = 0;
- if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
- goto fail;
- c_val[0] = WILC_FW_BSS_TYPE_INFRA;
- if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0))
- goto fail;
-
- c_val[0] = WILC_FW_TX_RATE_AUTO;
- if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
- goto fail;
-
- c_val[0] = WILC_FW_OPER_MODE_G_MIXED_11B_2;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0,
- 0))
- goto fail;
-
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
- goto fail;
-
- c_val[0] = WILC_FW_PREAMBLE_SHORT;
- if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0))
+ w = vif->iftype;
+ cpu_to_le32s(&w);
+ if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4,
+ 0, 0))
goto fail;
- c_val[0] = WILC_FW_11N_PROT_AUTO;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
+ b = WILC_FW_BSS_TYPE_INFRA;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_ACTIVE_SCAN;
- if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0))
+ b = WILC_FW_TX_RATE_AUTO;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_SITE_SURVEY_OFF;
- if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0))
+ b = WILC_FW_OPER_MODE_G_MIXED_11B_2;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0))
goto fail;
- *((int *)c_val) = 0xffff;
- if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
+ b = WILC_FW_PREAMBLE_SHORT;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0))
goto fail;
- *((int *)c_val) = 2346;
- if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
+ b = WILC_FW_11N_PROT_AUTO;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0))
goto fail;
- c_val[0] = 0;
- if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0))
+ b = WILC_FW_ACTIVE_SCAN;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0))
+ b = WILC_FW_SITE_SURVEY_OFF;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_NO_POWERSAVE;
- if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
+ hw = 0xffff;
+ cpu_to_le16s(&hw);
+ if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0))
goto fail;
- c_val[0] = WILC_FW_SEC_NO;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0))
+ hw = 2346;
+ cpu_to_le16s(&hw);
+ if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0))
goto fail;
- c_val[0] = WILC_FW_AUTH_OPEN_SYSTEM;
- if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0))
+ b = 0;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0))
goto fail;
- strcpy(c_val, "123456790abcdef1234567890");
- if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val,
- (strlen(c_val) + 1), 0, 0))
+ b = 1;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0))
goto fail;
- strcpy(c_val, "12345678");
- if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0,
- 0))
+ b = WILC_FW_NO_POWERSAVE;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0))
goto fail;
- strcpy(c_val, "password");
- if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1),
- 0, 0))
+ b = WILC_FW_SEC_NO;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 192;
- c_val[1] = 168;
- c_val[2] = 1;
- c_val[3] = 112;
- if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
+ b = WILC_FW_AUTH_OPEN_SYSTEM;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 3;
- if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
+ b = 3;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0))
goto fail;
- c_val[0] = 3;
- if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
+ b = 3;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_ACK_POLICY_NORMAL;
- if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0))
+ b = WILC_FW_ACK_POLICY_NORMAL;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0))
goto fail;
- c_val[0] = 0;
- if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1,
+ b = 0;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1,
0, 0))
goto fail;
- c_val[0] = 48;
- if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0,
- 0))
+ b = 48;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0))
goto fail;
- c_val[0] = 28;
- if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0,
- 0))
+ b = 28;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0))
goto fail;
- *((int *)c_val) = 100;
- if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
+ hw = 100;
+ cpu_to_le16s(&hw);
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0))
goto fail;
- c_val[0] = WILC_FW_REKEY_POLICY_DISABLE;
- if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0))
+ b = WILC_FW_REKEY_POLICY_DISABLE;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0))
goto fail;
- *((int *)c_val) = 84600;
- if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
+ w = 84600;
+ cpu_to_le32s(&w);
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0))
goto fail;
- *((int *)c_val) = 500;
- if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0,
+ w = 500;
+ cpu_to_le32s(&w);
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0,
0))
goto fail;
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0,
+ b = 1;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0,
0))
goto fail;
- c_val[0] = WILC_FW_ERP_PROT_SELF_CTS;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
+ b = WILC_FW_ERP_PROT_SELF_CTS;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0))
+ b = 1;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_11N_OP_MODE_HT_MIXED;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0,
- 0))
+ b = WILC_FW_11N_OP_MODE_HT_MIXED;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0,
- 0))
+ b = 1;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0))
goto fail;
- c_val[0] = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1,
+ b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1,
0, 0))
goto fail;
- c_val[0] = WILC_FW_HT_PROT_RTS_CTS_NONHT;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
+ b = WILC_FW_HT_PROT_RTS_CTS_NONHT;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0))
goto fail;
- c_val[0] = 0;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0,
+ b = 0;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0,
0))
goto fail;
- c_val[0] = WILC_FW_SMPS_MODE_MIMO;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
- goto fail;
-
- c_val[0] = 7;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0,
- 0))
+ b = 7;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0))
goto fail;
- c_val[0] = 1;
- if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1,
+ b = 1;
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1,
1, 1))
goto fail;
@@ -609,7 +501,7 @@ static int wlan_initialize_threads(struct net_device *dev)
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
- wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
+ wilc->txq_thread = kthread_run(wilc_txq_task, (void *)dev,
"K_TXQ_TASK");
if (IS_ERR(wilc->txq_thread)) {
netdev_err(dev, "couldn't create TXQ thread\n");
@@ -667,7 +559,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
goto fail_irq_enable;
}
- ret = linux_wlan_start_firmware(dev);
+ ret = wilc_start_firmware(dev);
if (ret < 0) {
ret = -EIO;
goto fail_irq_enable;
@@ -683,7 +575,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
firmware_ver[size] = '\0';
netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
}
- ret = linux_wlan_init_test_config(dev, vif);
+ ret = wilc_init_fw_config(dev, vif);
if (ret < 0) {
netdev_err(dev, "Failed to configure firmware\n");
@@ -807,12 +699,12 @@ static void wilc_set_multicast_list(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI ||
dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
- wilc_setup_multicast_filter(vif, false, 0, NULL);
+ wilc_setup_multicast_filter(vif, 0, 0, NULL);
return;
}
if (dev->mc.count == 0) {
- wilc_setup_multicast_filter(vif, true, 0, NULL);
+ wilc_setup_multicast_filter(vif, 1, 0, NULL);
return;
}
@@ -829,11 +721,11 @@ static void wilc_set_multicast_list(struct net_device *dev)
cur_mc += ETH_ALEN;
}
- if (wilc_setup_multicast_filter(vif, true, dev->mc.count, mc_list))
+ if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))
kfree(mc_list);
}
-static void linux_wlan_tx_complete(void *priv, int status)
+static void wilc_tx_complete(void *priv, int status)
{
struct tx_complete_data *pv_data = priv;
@@ -847,9 +739,6 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
struct wilc *wilc = vif->wilc;
struct tx_complete_data *tx_data = NULL;
int queue_count;
- char *udp_buf;
- struct iphdr *ih;
- struct ethhdr *eth_h;
if (skb->dev != ndev) {
netdev_err(ndev, "Packet not destined to this device\n");
@@ -867,28 +756,18 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
tx_data->size = skb->len;
tx_data->skb = skb;
- eth_h = (struct ethhdr *)(skb->data);
- if (eth_h->h_proto == cpu_to_be16(0x8e88))
- netdev_dbg(ndev, "EAPOL transmitted\n");
-
- ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
-
- udp_buf = (char *)ih + sizeof(struct iphdr);
- if ((udp_buf[1] == 68 && udp_buf[3] == 67) ||
- (udp_buf[1] == 67 && udp_buf[3] == 68))
- netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n",
- udp_buf[248], udp_buf[249], udp_buf[250]);
-
vif->netstats.tx_packets++;
vif->netstats.tx_bytes += tx_data->size;
tx_data->bssid = wilc->vif[vif->idx]->bssid;
queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
tx_data->buff, tx_data->size,
- linux_wlan_tx_complete);
+ wilc_tx_complete);
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
- netif_stop_queue(wilc->vif[0]->ndev);
- netif_stop_queue(wilc->vif[1]->ndev);
+ if (wilc->vif[0]->mac_opened)
+ netif_stop_queue(wilc->vif[0]->ndev);
+ if (wilc->vif[1]->mac_opened)
+ netif_stop_queue(wilc->vif[1]->ndev);
}
return 0;
@@ -916,7 +795,6 @@ static int wilc_mac_close(struct net_device *ndev)
netdev_dbg(ndev, "Deinitializing wilc1000\n");
wl->close = 1;
wilc_wlan_deinitialize(ndev);
- wilc_wfi_deinit_mon_interface();
}
vif->mac_opened = 0;
@@ -924,7 +802,8 @@ static int wilc_mac_close(struct net_device *ndev)
return 0;
}
-void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset)
+void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
+ u32 pkt_offset)
{
unsigned int frame_len = 0;
int stats;
@@ -972,7 +851,7 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
for (i = 0; i < wilc->vif_num; i++) {
vif = netdev_priv(wilc->vif[i]->ndev);
if (vif->monitor_flag) {
- wilc_wfi_monitor_rx(buff, size);
+ wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
return;
}
}
@@ -983,6 +862,76 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
wilc_wfi_p2p_rx(wilc->vif[1]->ndev, buff, size);
}
+static const struct net_device_ops wilc_netdev_ops = {
+ .ndo_init = mac_init_fn,
+ .ndo_open = wilc_mac_open,
+ .ndo_stop = wilc_mac_close,
+ .ndo_start_xmit = wilc_mac_xmit,
+ .ndo_get_stats = mac_stats,
+ .ndo_set_rx_mode = wilc_set_multicast_list,
+};
+
+static int dev_state_ev_handler(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct in_ifaddr *dev_iface = ptr;
+ struct wilc_priv *priv;
+ struct host_if_drv *hif_drv;
+ struct net_device *dev;
+ struct wilc_vif *vif;
+
+ if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev)
+ return NOTIFY_DONE;
+
+ dev = (struct net_device *)dev_iface->ifa_dev->dev;
+ if (dev->netdev_ops != &wilc_netdev_ops)
+ return NOTIFY_DONE;
+
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+ return NOTIFY_DONE;
+
+ priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
+ if (!priv)
+ return NOTIFY_DONE;
+
+ hif_drv = (struct host_if_drv *)priv->hif_drv;
+ vif = netdev_priv(dev);
+ if (!vif || !hif_drv)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_UP:
+ if (vif->iftype == WILC_STATION_MODE ||
+ vif->iftype == WILC_CLIENT_MODE) {
+ hif_drv->ifc_up = 1;
+ vif->obtaining_ip = false;
+ del_timer(&vif->during_ip_timer);
+ }
+
+ if (vif->wilc->enable_ps)
+ wilc_set_power_mgmt(vif, 1, 0);
+
+ break;
+
+ case NETDEV_DOWN:
+ if (vif->iftype == WILC_STATION_MODE ||
+ vif->iftype == WILC_CLIENT_MODE) {
+ hif_drv->ifc_up = 0;
+ vif->obtaining_ip = false;
+ wilc_set_power_mgmt(vif, 0, 0);
+ }
+
+ wilc_resolve_disconnect_aberration(vif);
+
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static struct notifier_block g_dev_notifier = {
.notifier_call = dev_state_ev_handler
};
@@ -1002,19 +951,15 @@ void wilc_netdev_cleanup(struct wilc *wilc)
wilc->firmware = NULL;
}
- if (wilc->vif[0]->ndev || wilc->vif[1]->ndev) {
- for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++)
- if (wilc->vif[i]->ndev)
- if (wilc->vif[i]->mac_opened)
- wilc_mac_close(wilc->vif[i]->ndev);
-
- for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
+ for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
+ if (wilc->vif[i] && wilc->vif[i]->ndev) {
unregister_netdev(wilc->vif[i]->ndev);
wilc_free_wiphy(wilc->vif[i]->ndev);
free_netdev(wilc->vif[i]->ndev);
}
}
+ wilc_wfi_deinit_mon_interface(wilc);
flush_workqueue(wilc->hif_workqueue);
destroy_workqueue(wilc->hif_workqueue);
wilc_wlan_cfg_deinit(wilc);
@@ -1023,15 +968,6 @@ void wilc_netdev_cleanup(struct wilc *wilc)
}
EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
-static const struct net_device_ops wilc_netdev_ops = {
- .ndo_init = mac_init_fn,
- .ndo_open = wilc_mac_open,
- .ndo_stop = wilc_mac_close,
- .ndo_start_xmit = wilc_mac_xmit,
- .ndo_get_stats = mac_stats,
- .ndo_set_rx_mode = wilc_set_multicast_list,
-};
-
int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
const struct wilc_hif_func *ops)
{
@@ -1086,8 +1022,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
vif->wilc = *wilc;
vif->ndev = ndev;
wl->vif[i] = vif;
- wl->vif_num = i;
- vif->idx = wl->vif_num;
+ wl->vif_num = i + 1;
+ vif->idx = i;
ndev->netdev_ops = &wilc_netdev_ops;
diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c
index e2f739fef21c..b789c57d7e80 100644
--- a/drivers/staging/wilc1000/wilc_sdio.c
+++ b/drivers/staging/wilc1000/wilc_sdio.c
@@ -51,10 +51,6 @@ struct sdio_cmd53 {
static const struct wilc_hif_func wilc_hif_sdio;
-static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data);
-static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data);
-static int sdio_init(struct wilc *wilc, bool resume);
-
static void wilc_sdio_interrupt(struct sdio_func *func)
{
sdio_release_host(func);
@@ -121,8 +117,8 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
return ret;
}
-static int linux_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+static int wilc_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
{
struct wilc *wilc;
int ret;
@@ -160,7 +156,7 @@ static int linux_sdio_probe(struct sdio_func *func,
return 0;
}
-static void linux_sdio_remove(struct sdio_func *func)
+static void wilc_sdio_remove(struct sdio_func *func)
{
struct wilc *wilc = sdio_get_drvdata(func);
@@ -170,7 +166,7 @@ static void linux_sdio_remove(struct sdio_func *func)
wilc_netdev_cleanup(wilc);
}
-static int sdio_reset(struct wilc *wilc)
+static int wilc_sdio_reset(struct wilc *wilc)
{
struct sdio_cmd52 cmd;
int ret;
@@ -205,7 +201,7 @@ static int wilc_sdio_suspend(struct device *dev)
chip_allow_sleep(wilc);
}
- ret = sdio_reset(wilc);
+ ret = wilc_sdio_reset(wilc);
if (ret) {
dev_err(&func->dev, "Fail reset sdio\n");
return ret;
@@ -215,50 +211,6 @@ static int wilc_sdio_suspend(struct device *dev)
return 0;
}
-static int wilc_sdio_resume(struct device *dev)
-{
- struct sdio_func *func = dev_to_sdio_func(dev);
- struct wilc *wilc = sdio_get_drvdata(func);
-
- dev_info(dev, "sdio resume\n");
- sdio_release_host(func);
- chip_wakeup(wilc);
- sdio_init(wilc, true);
-
- if (wilc->suspend_event)
- host_wakeup_notify(wilc);
-
- chip_allow_sleep(wilc);
-
- return 0;
-}
-
-static const struct of_device_id wilc_of_match[] = {
- { .compatible = "microchip,wilc1000-sdio", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, wilc_of_match);
-
-static const struct dev_pm_ops wilc_sdio_pm_ops = {
- .suspend = wilc_sdio_suspend,
- .resume = wilc_sdio_resume,
-};
-
-static struct sdio_driver wilc_sdio_driver = {
- .name = SDIO_MODALIAS,
- .id_table = wilc_sdio_ids,
- .probe = linux_sdio_probe,
- .remove = linux_sdio_remove,
- .drv = {
- .pm = &wilc_sdio_pm_ops,
- .of_match_table = wilc_of_match,
- }
-};
-module_driver(wilc_sdio_driver,
- sdio_register_driver,
- sdio_unregister_driver);
-MODULE_LICENSE("GPL");
-
static int wilc_sdio_enable_interrupt(struct wilc *dev)
{
struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev);
@@ -293,7 +245,7 @@ static void wilc_sdio_disable_interrupt(struct wilc *dev)
*
********************************************/
-static int sdio_set_func0_csa_address(struct wilc *wilc, u32 adr)
+static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct sdio_cmd52 cmd;
@@ -334,7 +286,7 @@ fail:
return 0;
}
-static int sdio_set_func0_block_size(struct wilc *wilc, u32 block_size)
+static int wilc_sdio_set_func0_block_size(struct wilc *wilc, u32 block_size)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct sdio_cmd52 cmd;
@@ -370,7 +322,7 @@ fail:
*
********************************************/
-static int sdio_set_func1_block_size(struct wilc *wilc, u32 block_size)
+static int wilc_sdio_set_func1_block_size(struct wilc *wilc, u32 block_size)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct sdio_cmd52 cmd;
@@ -404,7 +356,7 @@ fail:
* Sdio interfaces
*
********************************************/
-static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
+static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -432,7 +384,7 @@ static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
/**
* set the AHB address
**/
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
cmd.read_write = 1;
@@ -458,7 +410,7 @@ fail:
return 0;
}
-static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
+static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -507,7 +459,7 @@ static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
cmd.buffer = buf;
cmd.block_size = block_size;
if (addr > 0) {
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
}
ret = wilc_sdio_cmd53(wilc, &cmd);
@@ -530,7 +482,7 @@ static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
cmd.block_size = block_size;
if (addr > 0) {
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
}
ret = wilc_sdio_cmd53(wilc, &cmd);
@@ -548,7 +500,7 @@ fail:
return 0;
}
-static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
+static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -571,7 +523,7 @@ static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
} else {
struct sdio_cmd53 cmd;
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
cmd.read_write = 0;
@@ -600,7 +552,7 @@ fail:
return 0;
}
-static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
+static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -649,7 +601,7 @@ static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
cmd.buffer = buf;
cmd.block_size = block_size;
if (addr > 0) {
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
}
ret = wilc_sdio_cmd53(wilc, &cmd);
@@ -672,7 +624,7 @@ static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
cmd.block_size = block_size;
if (addr > 0) {
- if (!sdio_set_func0_csa_address(wilc, addr))
+ if (!wilc_sdio_set_func0_csa_address(wilc, addr))
goto fail;
}
ret = wilc_sdio_cmd53(wilc, &cmd);
@@ -696,12 +648,12 @@ fail:
*
********************************************/
-static int sdio_deinit(struct wilc *wilc)
+static int wilc_sdio_deinit(struct wilc *wilc)
{
return 1;
}
-static int sdio_init(struct wilc *wilc, bool resume)
+static int wilc_sdio_init(struct wilc *wilc, bool resume)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -729,7 +681,7 @@ static int sdio_init(struct wilc *wilc, bool resume)
/**
* function 0 block size
**/
- if (!sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) {
+ if (!wilc_sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) {
dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n");
goto fail;
}
@@ -778,7 +730,7 @@ static int sdio_init(struct wilc *wilc, bool resume)
/**
* func 1 is ready, set func 1 block size
**/
- if (!sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) {
+ if (!wilc_sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) {
dev_err(&func->dev, "Fail set func 1 block size...\n");
goto fail;
}
@@ -801,7 +753,7 @@ static int sdio_init(struct wilc *wilc, bool resume)
* make sure can read back chip id correctly
**/
if (!resume) {
- if (!sdio_read_reg(wilc, 0x1000, &chipid)) {
+ if (!wilc_sdio_read_reg(wilc, 0x1000, &chipid)) {
dev_err(&func->dev, "Fail cmd read chip id...\n");
goto fail;
}
@@ -821,7 +773,7 @@ fail:
return 0;
}
-static int sdio_read_size(struct wilc *wilc, u32 *size)
+static int wilc_sdio_read_size(struct wilc *wilc, u32 *size)
{
u32 tmp;
struct sdio_cmd52 cmd;
@@ -846,14 +798,14 @@ static int sdio_read_size(struct wilc *wilc, u32 *size)
return 1;
}
-static int sdio_read_int(struct wilc *wilc, u32 *int_status)
+static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
u32 tmp;
struct sdio_cmd52 cmd;
- sdio_read_size(wilc, &tmp);
+ wilc_sdio_read_size(wilc, &tmp);
/**
* Read IRQ flags
@@ -905,7 +857,7 @@ static int sdio_read_int(struct wilc *wilc, u32 *int_status)
return 1;
}
-static int sdio_clear_int_ext(struct wilc *wilc, u32 val)
+static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -1030,7 +982,7 @@ fail:
return 0;
}
-static int sdio_sync_ext(struct wilc *wilc, int nint)
+static int wilc_sdio_sync_ext(struct wilc *wilc, int nint)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
struct wilc_sdio *sdio_priv = wilc->bus_data;
@@ -1051,13 +1003,13 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
/**
* Disable power sequencer
**/
- if (!sdio_read_reg(wilc, WILC_MISC, &reg)) {
+ if (!wilc_sdio_read_reg(wilc, WILC_MISC, &reg)) {
dev_err(&func->dev, "Failed read misc reg...\n");
return 0;
}
reg &= ~BIT(8);
- if (!sdio_write_reg(wilc, WILC_MISC, reg)) {
+ if (!wilc_sdio_write_reg(wilc, WILC_MISC, reg)) {
dev_err(&func->dev, "Failed write misc reg...\n");
return 0;
}
@@ -1069,14 +1021,14 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
/**
* interrupt pin mux select
**/
- ret = sdio_read_reg(wilc, WILC_PIN_MUX_0, &reg);
+ ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, &reg);
if (!ret) {
dev_err(&func->dev, "Failed read reg (%08x)...\n",
WILC_PIN_MUX_0);
return 0;
}
reg |= BIT(8);
- ret = sdio_write_reg(wilc, WILC_PIN_MUX_0, reg);
+ ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg);
if (!ret) {
dev_err(&func->dev, "Failed write reg (%08x)...\n",
WILC_PIN_MUX_0);
@@ -1086,7 +1038,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
/**
* interrupt enable
**/
- ret = sdio_read_reg(wilc, WILC_INTR_ENABLE, &reg);
+ ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, &reg);
if (!ret) {
dev_err(&func->dev, "Failed read reg (%08x)...\n",
WILC_INTR_ENABLE);
@@ -1095,14 +1047,14 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
for (i = 0; (i < 5) && (nint > 0); i++, nint--)
reg |= BIT((27 + i));
- ret = sdio_write_reg(wilc, WILC_INTR_ENABLE, reg);
+ ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg);
if (!ret) {
dev_err(&func->dev, "Failed write reg (%08x)...\n",
WILC_INTR_ENABLE);
return 0;
}
if (nint) {
- ret = sdio_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
+ ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
if (!ret) {
dev_err(&func->dev,
"Failed read reg (%08x)...\n",
@@ -1113,7 +1065,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
for (i = 0; (i < 3) && (nint > 0); i++, nint--)
reg |= BIT(i);
- ret = sdio_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
+ ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
if (!ret) {
dev_err(&func->dev,
"Failed write reg (%08x)...\n",
@@ -1127,19 +1079,62 @@ static int sdio_sync_ext(struct wilc *wilc, int nint)
/* Global sdio HIF function table */
static const struct wilc_hif_func wilc_hif_sdio = {
- .hif_init = sdio_init,
- .hif_deinit = sdio_deinit,
- .hif_read_reg = sdio_read_reg,
- .hif_write_reg = sdio_write_reg,
- .hif_block_rx = sdio_read,
- .hif_block_tx = sdio_write,
- .hif_read_int = sdio_read_int,
- .hif_clear_int_ext = sdio_clear_int_ext,
- .hif_read_size = sdio_read_size,
- .hif_block_tx_ext = sdio_write,
- .hif_block_rx_ext = sdio_read,
- .hif_sync_ext = sdio_sync_ext,
+ .hif_init = wilc_sdio_init,
+ .hif_deinit = wilc_sdio_deinit,
+ .hif_read_reg = wilc_sdio_read_reg,
+ .hif_write_reg = wilc_sdio_write_reg,
+ .hif_block_rx = wilc_sdio_read,
+ .hif_block_tx = wilc_sdio_write,
+ .hif_read_int = wilc_sdio_read_int,
+ .hif_clear_int_ext = wilc_sdio_clear_int_ext,
+ .hif_read_size = wilc_sdio_read_size,
+ .hif_block_tx_ext = wilc_sdio_write,
+ .hif_block_rx_ext = wilc_sdio_read,
+ .hif_sync_ext = wilc_sdio_sync_ext,
.enable_interrupt = wilc_sdio_enable_interrupt,
.disable_interrupt = wilc_sdio_disable_interrupt,
};
+static int wilc_sdio_resume(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct wilc *wilc = sdio_get_drvdata(func);
+
+ dev_info(dev, "sdio resume\n");
+ sdio_release_host(func);
+ chip_wakeup(wilc);
+ wilc_sdio_init(wilc, true);
+
+ if (wilc->suspend_event)
+ host_wakeup_notify(wilc);
+
+ chip_allow_sleep(wilc);
+
+ return 0;
+}
+
+static const struct of_device_id wilc_of_match[] = {
+ { .compatible = "microchip,wilc1000-sdio", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, wilc_of_match);
+
+static const struct dev_pm_ops wilc_sdio_pm_ops = {
+ .suspend = wilc_sdio_suspend,
+ .resume = wilc_sdio_resume,
+};
+
+static struct sdio_driver wilc_sdio_driver = {
+ .name = SDIO_MODALIAS,
+ .id_table = wilc_sdio_ids,
+ .probe = wilc_sdio_probe,
+ .remove = wilc_sdio_remove,
+ .drv = {
+ .pm = &wilc_sdio_pm_ops,
+ .of_match_table = wilc_of_match,
+ }
+};
+module_driver(wilc_sdio_driver,
+ sdio_register_driver,
+ sdio_unregister_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
index 153e120eff00..4a1be9e60d74 100644
--- a/drivers/staging/wilc1000/wilc_spi.c
+++ b/drivers/staging/wilc1000/wilc_spi.c
@@ -814,7 +814,7 @@ static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
*
********************************************/
-static int _wilc_spi_deinit(struct wilc *wilc)
+static int wilc_spi_deinit(struct wilc *wilc)
{
/*
* TODO:
@@ -1122,7 +1122,7 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint)
/* Global spi HIF function table */
static const struct wilc_hif_func wilc_hif_spi = {
.hif_init = wilc_spi_init,
- .hif_deinit = _wilc_spi_deinit,
+ .hif_deinit = wilc_spi_deinit,
.hif_read_reg = wilc_spi_read_reg,
.hif_write_reg = wilc_spi_write_reg,
.hif_block_rx = wilc_spi_read,
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index ac47dda510e0..5e7a4676324e 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -27,10 +27,7 @@
#define GAS_INITIAL_REQ 0x0a
#define GAS_INITIAL_RSP 0x0b
-#define INVALID_CHANNEL 0
-
-#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ)
-#define SCAN_RESULT_EXPIRE (40 * HZ)
+#define WILC_INVALID_CHANNEL 0
static const struct ieee80211_txrx_stypes
wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
@@ -65,124 +62,15 @@ static const struct wiphy_wowlan_support wowlan_support = {
.flags = WIPHY_WOWLAN_ANY
};
-struct p2p_mgmt_data {
+struct wilc_p2p_mgmt_data {
int size;
u8 *buff;
};
-static u8 wlan_channel = INVALID_CHANNEL;
-static u8 curr_channel;
-static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
-static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
-
-#define AGING_TIME (9 * 1000)
-#define DURING_IP_TIME_OUT 15000
-
-static void clear_shadow_scan(struct wilc_priv *priv)
-{
- int i;
-
- for (i = 0; i < priv->scanned_cnt; i++) {
- kfree(priv->scanned_shadow[i].ies);
- priv->scanned_shadow[i].ies = NULL;
-
- kfree(priv->scanned_shadow[i].join_params);
- priv->scanned_shadow[i].join_params = NULL;
- }
- priv->scanned_cnt = 0;
-}
-
-static u32 get_rssi_avg(struct network_info *network_info)
-{
- u8 i;
- int rssi_v = 0;
- u8 num_rssi = (network_info->rssi_history.full) ?
- NUM_RSSI : (network_info->rssi_history.index);
-
- for (i = 0; i < num_rssi; i++)
- rssi_v += network_info->rssi_history.samples[i];
-
- rssi_v /= num_rssi;
- return rssi_v;
-}
-
-static void refresh_scan(struct wilc_priv *priv, bool direct_scan)
-{
- struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy;
- int i;
-
- for (i = 0; i < priv->scanned_cnt; i++) {
- struct network_info *network_info;
- s32 freq;
- struct ieee80211_channel *channel;
- int rssi;
- struct cfg80211_bss *bss;
-
- network_info = &priv->scanned_shadow[i];
-
- if (!memcmp("DIRECT-", network_info->ssid, 7) && !direct_scan)
- continue;
-
- freq = ieee80211_channel_to_frequency((s32)network_info->ch,
- NL80211_BAND_2GHZ);
- channel = ieee80211_get_channel(wiphy, freq);
- rssi = get_rssi_avg(network_info);
- bss = cfg80211_inform_bss(wiphy,
- channel,
- CFG80211_BSS_FTYPE_UNKNOWN,
- network_info->bssid,
- network_info->tsf,
- network_info->cap_info,
- network_info->beacon_period,
- (const u8 *)network_info->ies,
- (size_t)network_info->ies_len,
- (s32)rssi * 100,
- GFP_KERNEL);
- cfg80211_put_bss(wiphy, bss);
- }
-}
-
-static void reset_shadow_found(struct wilc_priv *priv)
-{
- int i;
-
- for (i = 0; i < priv->scanned_cnt; i++)
- priv->scanned_shadow[i].found = 0;
-}
-
-static void update_scan_time(struct wilc_priv *priv)
-{
- int i;
-
- for (i = 0; i < priv->scanned_cnt; i++)
- priv->scanned_shadow[i].time_scan = jiffies;
-}
-
-static void remove_network_from_shadow(struct timer_list *t)
-{
- struct wilc_priv *priv = from_timer(priv, t, aging_timer);
- unsigned long now = jiffies;
- int i, j;
-
- for (i = 0; i < priv->scanned_cnt; i++) {
- if (!time_after(now, priv->scanned_shadow[i].time_scan +
- (unsigned long)(SCAN_RESULT_EXPIRE)))
- continue;
- kfree(priv->scanned_shadow[i].ies);
- priv->scanned_shadow[i].ies = NULL;
-
- kfree(priv->scanned_shadow[i].join_params);
+static const u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
+static const u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
- for (j = i; (j < priv->scanned_cnt - 1); j++)
- priv->scanned_shadow[j] = priv->scanned_shadow[j + 1];
-
- priv->scanned_cnt--;
- }
-
- if (priv->scanned_cnt != 0)
- mod_timer(&priv->aging_timer,
- jiffies + msecs_to_jiffies(AGING_TIME));
-}
+#define WILC_IP_TIMEOUT_MS 15000
static void clear_during_ip(struct timer_list *t)
{
@@ -191,151 +79,36 @@ static void clear_during_ip(struct timer_list *t)
vif->obtaining_ip = false;
}
-static int is_network_in_shadow(struct network_info *nw_info,
- struct wilc_priv *priv)
-{
- int state = -1;
- int i;
-
- if (priv->scanned_cnt == 0) {
- mod_timer(&priv->aging_timer,
- jiffies + msecs_to_jiffies(AGING_TIME));
- state = -1;
- } else {
- for (i = 0; i < priv->scanned_cnt; i++) {
- if (memcmp(priv->scanned_shadow[i].bssid,
- nw_info->bssid, 6) == 0) {
- state = i;
- break;
- }
- }
- }
- return state;
-}
-
-static void add_network_to_shadow(struct network_info *nw_info,
- struct wilc_priv *priv, void *join_params)
-{
- int ap_found = is_network_in_shadow(nw_info, priv);
- u32 ap_index = 0;
- u8 rssi_index = 0;
- struct network_info *shadow_nw_info;
-
- if (priv->scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW)
- return;
-
- if (ap_found == -1) {
- ap_index = priv->scanned_cnt;
- priv->scanned_cnt++;
- } else {
- ap_index = ap_found;
- }
- shadow_nw_info = &priv->scanned_shadow[ap_index];
- rssi_index = shadow_nw_info->rssi_history.index;
- shadow_nw_info->rssi_history.samples[rssi_index++] = nw_info->rssi;
- if (rssi_index == NUM_RSSI) {
- rssi_index = 0;
- shadow_nw_info->rssi_history.full = true;
- }
- shadow_nw_info->rssi_history.index = rssi_index;
- shadow_nw_info->rssi = nw_info->rssi;
- shadow_nw_info->cap_info = nw_info->cap_info;
- shadow_nw_info->ssid_len = nw_info->ssid_len;
- memcpy(shadow_nw_info->ssid, nw_info->ssid, nw_info->ssid_len);
- memcpy(shadow_nw_info->bssid, nw_info->bssid, ETH_ALEN);
- shadow_nw_info->beacon_period = nw_info->beacon_period;
- shadow_nw_info->dtim_period = nw_info->dtim_period;
- shadow_nw_info->ch = nw_info->ch;
- shadow_nw_info->tsf = nw_info->tsf;
- if (ap_found != -1)
- kfree(shadow_nw_info->ies);
- shadow_nw_info->ies = kmemdup(nw_info->ies, nw_info->ies_len,
- GFP_KERNEL);
- if (shadow_nw_info->ies)
- shadow_nw_info->ies_len = nw_info->ies_len;
- else
- shadow_nw_info->ies_len = 0;
- shadow_nw_info->time_scan = jiffies;
- shadow_nw_info->time_scan_cached = jiffies;
- shadow_nw_info->found = 1;
- if (ap_found != -1)
- kfree(shadow_nw_info->join_params);
- shadow_nw_info->join_params = join_params;
-}
-
static void cfg_scan_result(enum scan_event scan_event,
- struct network_info *network_info,
- void *user_void, void *join_params)
+ struct wilc_rcvd_net_info *info, void *user_void)
{
- struct wilc_priv *priv;
- struct wiphy *wiphy;
- s32 freq;
- struct ieee80211_channel *channel;
- struct cfg80211_bss *bss = NULL;
+ struct wilc_priv *priv = user_void;
- priv = user_void;
if (!priv->cfg_scanning)
return;
if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
- wiphy = priv->dev->ieee80211_ptr->wiphy;
-
- if (!wiphy || !network_info)
- return;
+ s32 freq;
+ struct ieee80211_channel *channel;
+ struct cfg80211_bss *bss;
+ struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy;
- if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
- (((s32)network_info->rssi * 100) < 0 ||
- ((s32)network_info->rssi * 100) > 100))
+ if (!wiphy || !info)
return;
- freq = ieee80211_channel_to_frequency((s32)network_info->ch,
+ freq = ieee80211_channel_to_frequency((s32)info->ch,
NL80211_BAND_2GHZ);
channel = ieee80211_get_channel(wiphy, freq);
-
if (!channel)
return;
- if (network_info->new_network) {
- if (priv->rcvd_ch_cnt >= MAX_NUM_SCANNED_NETWORKS)
- return;
-
- priv->rcvd_ch_cnt++;
-
- add_network_to_shadow(network_info, priv, join_params);
-
- if (memcmp("DIRECT-", network_info->ssid, 7))
- return;
-
- bss = cfg80211_inform_bss(wiphy,
- channel,
- CFG80211_BSS_FTYPE_UNKNOWN,
- network_info->bssid,
- network_info->tsf,
- network_info->cap_info,
- network_info->beacon_period,
- (const u8 *)network_info->ies,
- (size_t)network_info->ies_len,
- (s32)network_info->rssi * 100,
- GFP_KERNEL);
+ bss = cfg80211_inform_bss_frame(wiphy, channel, info->mgmt,
+ info->frame_len,
+ (s32)info->rssi * 100,
+ GFP_KERNEL);
+ if (!bss)
cfg80211_put_bss(wiphy, bss);
- } else {
- u32 i;
-
- for (i = 0; i < priv->rcvd_ch_cnt; i++) {
- if (memcmp(priv->scanned_shadow[i].bssid,
- network_info->bssid, 6) == 0)
- break;
- }
-
- if (i >= priv->rcvd_ch_cnt)
- return;
-
- priv->scanned_shadow[i].rssi = network_info->rssi;
- priv->scanned_shadow[i].time_scan = jiffies;
- }
} else if (scan_event == SCAN_EVENT_DONE) {
- refresh_scan(priv, false);
-
mutex_lock(&priv->scan_req_lock);
if (priv->scan_req) {
@@ -344,7 +117,6 @@ static void cfg_scan_result(enum scan_event scan_event,
};
cfg80211_scan_done(priv->scan_req, &info);
- priv->rcvd_ch_cnt = 0;
priv->cfg_scanning = false;
priv->scan_req = NULL;
}
@@ -357,9 +129,6 @@ static void cfg_scan_result(enum scan_event scan_event,
.aborted = false,
};
- update_scan_time(priv);
- refresh_scan(priv, false);
-
cfg80211_scan_done(priv->scan_req, &info);
priv->cfg_scanning = false;
priv->scan_req = NULL;
@@ -368,21 +137,7 @@ static void cfg_scan_result(enum scan_event scan_event,
}
}
-static inline bool wilc_cfg_scan_time_expired(struct wilc_priv *priv, int i)
-{
- unsigned long now = jiffies;
-
- if (time_after(now, priv->scanned_shadow[i].time_scan_cached +
- (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
- return true;
- else
- return false;
-}
-
-static void cfg_connect_result(enum conn_event conn_disconn_evt,
- struct connect_info *conn_info,
- u8 mac_status,
- struct disconnect_info *disconn_info,
+static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
void *priv_data)
{
struct wilc_priv *priv = priv_data;
@@ -390,49 +145,28 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wl = vif->wilc;
struct host_if_drv *wfi_drv = priv->hif_drv;
- u8 null_bssid[ETH_ALEN] = {0};
+ struct wilc_conn_info *conn_info = &wfi_drv->conn_info;
vif->connecting = false;
if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) {
- u16 connect_status;
-
- connect_status = conn_info->status;
+ u16 connect_status = conn_info->status;
if (mac_status == WILC_MAC_STATUS_DISCONNECTED &&
- conn_info->status == WLAN_STATUS_SUCCESS) {
+ connect_status == WLAN_STATUS_SUCCESS) {
connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- wilc_wlan_set_bssid(priv->dev, null_bssid,
- WILC_STATION_MODE);
+ wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);
- if (!wfi_drv->p2p_connect)
- wlan_channel = INVALID_CHANNEL;
+ if (vif->iftype != WILC_CLIENT_MODE)
+ wl->sta_ch = WILC_INVALID_CHANNEL;
netdev_err(dev, "Unspecified failure\n");
}
- if (connect_status == WLAN_STATUS_SUCCESS) {
- bool scan_refresh = false;
- u32 i;
-
+ if (connect_status == WLAN_STATUS_SUCCESS)
memcpy(priv->associated_bss, conn_info->bssid,
ETH_ALEN);
- for (i = 0; i < priv->scanned_cnt; i++) {
- if (memcmp(priv->scanned_shadow[i].bssid,
- conn_info->bssid,
- ETH_ALEN) == 0) {
- if (wilc_cfg_scan_time_expired(priv, i))
- scan_refresh = true;
-
- break;
- }
- }
-
- if (scan_refresh)
- refresh_scan(priv, true);
- }
-
cfg80211_connect_result(dev, conn_info->bssid,
conn_info->req_ies,
conn_info->req_ies_len,
@@ -440,23 +174,24 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
conn_info->resp_ies_len, connect_status,
GFP_KERNEL);
} else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
+ u16 reason = 0;
+
vif->obtaining_ip = false;
priv->p2p.local_random = 0x01;
priv->p2p.recv_random = 0x00;
priv->p2p.is_wilc_ie = false;
eth_zero_addr(priv->associated_bss);
- wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE);
+ wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);
+
+ if (vif->iftype != WILC_CLIENT_MODE)
+ wl->sta_ch = WILC_INVALID_CHANNEL;
- if (!wfi_drv->p2p_connect)
- wlan_channel = INVALID_CHANNEL;
if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
- disconn_info->reason = 3;
+ reason = 3;
else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
- disconn_info->reason = 1;
+ reason = 1;
- cfg80211_disconnected(dev, disconn_info->reason,
- disconn_info->ie, disconn_info->ie_len,
- false, GFP_KERNEL);
+ cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL);
}
}
@@ -470,7 +205,7 @@ static int set_channel(struct wiphy *wiphy,
channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
- curr_channel = channelnum;
+ vif->wilc->op_ch = channelnum;
result = wilc_set_mac_chnl_num(vif, channelnum);
if (result != 0)
@@ -481,22 +216,23 @@ static int set_channel(struct wiphy *wiphy,
static inline int
wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request,
- struct hidden_network *ntwk)
+ struct wilc_probe_ssid *search)
{
int i;
int slot_id = 0;
- ntwk->net_info = kcalloc(request->n_ssids, sizeof(*ntwk->net_info),
- GFP_KERNEL);
- if (!ntwk->net_info)
+ search->ssid_info = kcalloc(request->n_ssids,
+ sizeof(*search->ssid_info), GFP_KERNEL);
+ if (!search->ssid_info)
goto out;
- ntwk->n_ssids = request->n_ssids;
+ search->n_ssids = request->n_ssids;
for (i = 0; i < request->n_ssids; i++) {
if (request->ssids[i].ssid_len > 0) {
- struct hidden_net_info *info = &ntwk->net_info[slot_id];
+ struct wilc_probe_ssid_info *info;
+ info = &search->ssid_info[slot_id];
info->ssid = kmemdup(request->ssids[i].ssid,
request->ssids[i].ssid_len,
GFP_KERNEL);
@@ -506,7 +242,7 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request,
info->ssid_len = request->ssids[i].ssid_len;
slot_id++;
} else {
- ntwk->n_ssids -= 1;
+ search->n_ssids -= 1;
}
}
return 0;
@@ -514,9 +250,9 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request,
out_free:
for (i = 0; i < slot_id; i++)
- kfree(ntwk->net_info[i].ssid);
+ kfree(search->ssid_info[i].ssid);
- kfree(ntwk->net_info);
+ kfree(search->ssid_info);
out:
return -ENOMEM;
@@ -528,46 +264,41 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
struct wilc_vif *vif = netdev_priv(priv->dev);
u32 i;
int ret = 0;
- u8 scan_ch_list[MAX_NUM_SCANNED_NETWORKS];
- struct hidden_network hidden_ntwk;
-
- priv->scan_req = request;
+ u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];
+ struct wilc_probe_ssid probe_ssid;
- priv->rcvd_ch_cnt = 0;
-
- reset_shadow_found(priv);
+ if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) {
+ netdev_err(priv->dev, "Requested scanned channels over\n");
+ return -EINVAL;
+ }
+ priv->scan_req = request;
priv->cfg_scanning = true;
- if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
- for (i = 0; i < request->n_channels; i++) {
- u16 freq = request->channels[i]->center_freq;
+ for (i = 0; i < request->n_channels; i++) {
+ u16 freq = request->channels[i]->center_freq;
- scan_ch_list[i] = ieee80211_frequency_to_channel(freq);
- }
-
- if (request->n_ssids >= 1) {
- if (wilc_wfi_cfg_alloc_fill_ssid(request,
- &hidden_ntwk)) {
- ret = -ENOMEM;
- goto out;
- }
+ scan_ch_list[i] = ieee80211_frequency_to_channel(freq);
+ }
- ret = wilc_scan(vif, WILC_FW_USER_SCAN,
- WILC_FW_ACTIVE_SCAN, scan_ch_list,
- request->n_channels,
- (const u8 *)request->ie,
- request->ie_len, cfg_scan_result,
- (void *)priv, &hidden_ntwk);
- } else {
- ret = wilc_scan(vif, WILC_FW_USER_SCAN,
- WILC_FW_ACTIVE_SCAN, scan_ch_list,
- request->n_channels,
- (const u8 *)request->ie,
- request->ie_len, cfg_scan_result,
- (void *)priv, NULL);
+ if (request->n_ssids >= 1) {
+ if (wilc_wfi_cfg_alloc_fill_ssid(request, &probe_ssid)) {
+ ret = -ENOMEM;
+ goto out;
}
+
+ ret = wilc_scan(vif, WILC_FW_USER_SCAN,
+ WILC_FW_ACTIVE_SCAN, scan_ch_list,
+ request->n_channels,
+ (const u8 *)request->ie,
+ request->ie_len, cfg_scan_result,
+ (void *)priv, &probe_ssid);
} else {
- netdev_err(priv->dev, "Requested scanned channels over\n");
+ ret = wilc_scan(vif, WILC_FW_USER_SCAN,
+ WILC_FW_ACTIVE_SCAN, scan_ch_list,
+ request->n_channels,
+ (const u8 *)request->ie,
+ request->ie_len, cfg_scan_result,
+ (void *)priv, NULL);
}
out:
@@ -585,54 +316,17 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
struct host_if_drv *wfi_drv = priv->hif_drv;
- struct network_info *nw_info;
int ret;
u32 i;
- u32 sel_bssi_idx = UINT_MAX;
u8 security = WILC_FW_SEC_NO;
enum authtype auth_type = WILC_FW_AUTH_ANY;
u32 cipher_group;
+ struct cfg80211_bss *bss;
+ void *join_params;
+ u8 ch;
vif->connecting = true;
- if (!(strncmp(sme->ssid, "DIRECT-", 7)))
- wfi_drv->p2p_connect = 1;
- else
- wfi_drv->p2p_connect = 0;
-
- for (i = 0; i < priv->scanned_cnt; i++) {
- if (sme->ssid_len == priv->scanned_shadow[i].ssid_len &&
- memcmp(priv->scanned_shadow[i].ssid,
- sme->ssid,
- sme->ssid_len) == 0) {
- if (!sme->bssid) {
- if (sel_bssi_idx == UINT_MAX ||
- priv->scanned_shadow[i].rssi >
- priv->scanned_shadow[sel_bssi_idx].rssi)
- sel_bssi_idx = i;
- } else {
- if (memcmp(priv->scanned_shadow[i].bssid,
- sme->bssid,
- ETH_ALEN) == 0) {
- sel_bssi_idx = i;
- break;
- }
- }
- }
- }
-
- if (sel_bssi_idx < priv->scanned_cnt) {
- nw_info = &priv->scanned_shadow[sel_bssi_idx];
- } else {
- ret = -ENOENT;
- goto out_error;
- }
-
- if (ether_addr_equal_unaligned(vif->bssid, nw_info->bssid)) {
- ret = -EALREADY;
- goto out_error;
- }
-
memset(priv->wep_key, 0, sizeof(priv->wep_key));
memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
@@ -706,31 +400,65 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
auth_type = WILC_FW_AUTH_IEEE8021;
}
- curr_channel = nw_info->ch;
+ if (wfi_drv->usr_scan_req.scan_result) {
+ netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);
+ ret = -EBUSY;
+ goto out_error;
+ }
- if (!wfi_drv->p2p_connect)
- wlan_channel = nw_info->ch;
+ bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid,
+ sme->ssid_len, IEEE80211_BSS_TYPE_ANY,
+ IEEE80211_PRIVACY(sme->privacy));
+ if (!bss) {
+ ret = -EINVAL;
+ goto out_error;
+ }
- wilc_wlan_set_bssid(dev, nw_info->bssid, WILC_STATION_MODE);
+ if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) {
+ ret = -EALREADY;
+ goto out_put_bss;
+ }
- ret = wilc_set_join_req(vif, nw_info->bssid, sme->ssid,
- sme->ssid_len, sme->ie, sme->ie_len,
- cfg_connect_result, (void *)priv,
- security, auth_type,
- nw_info->ch,
- nw_info->join_params);
- if (ret) {
- u8 null_bssid[ETH_ALEN] = {0};
+ join_params = wilc_parse_join_bss_param(bss, &sme->crypto);
+ if (!join_params) {
+ netdev_err(dev, "%s: failed to construct join param\n",
+ __func__);
+ ret = -EINVAL;
+ goto out_put_bss;
+ }
+
+ ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
+ vif->wilc->op_ch = ch;
+ if (vif->iftype != WILC_CLIENT_MODE)
+ vif->wilc->sta_ch = ch;
+
+ wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE);
+ wfi_drv->conn_info.security = security;
+ wfi_drv->conn_info.auth_type = auth_type;
+ wfi_drv->conn_info.ch = ch;
+ wfi_drv->conn_info.conn_result = cfg_connect_result;
+ wfi_drv->conn_info.arg = priv;
+ wfi_drv->conn_info.param = join_params;
+
+ ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len);
+ if (ret) {
netdev_err(dev, "wilc_set_join_req(): Error\n");
ret = -ENOENT;
- if (!wfi_drv->p2p_connect)
- wlan_channel = INVALID_CHANNEL;
- wilc_wlan_set_bssid(dev, null_bssid, WILC_STATION_MODE);
- goto out_error;
- }
+ if (vif->iftype != WILC_CLIENT_MODE)
+ vif->wilc->sta_ch = WILC_INVALID_CHANNEL;
+ wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE);
+ wfi_drv->conn_info.conn_result = NULL;
+ kfree(join_params);
+ goto out_put_bss;
+ }
+ kfree(join_params);
+ cfg80211_put_bss(wiphy, bss);
return 0;
+out_put_bss:
+ cfg80211_put_bss(wiphy, bss);
+
out_error:
vif->connecting = false;
return ret;
@@ -742,9 +470,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev,
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
struct wilc *wilc = vif->wilc;
- struct host_if_drv *wfi_drv;
int ret;
- u8 null_bssid[ETH_ALEN] = {0};
vif->connecting = false;
@@ -757,15 +483,14 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
- wfi_drv = (struct host_if_drv *)priv->hif_drv;
- if (!wfi_drv->p2p_connect)
- wlan_channel = INVALID_CHANNEL;
- wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE);
+ if (vif->iftype != WILC_CLIENT_MODE)
+ wilc->sta_ch = WILC_INVALID_CHANNEL;
+ wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);
priv->p2p.local_random = 0x01;
priv->p2p.recv_random = 0x00;
priv->p2p.is_wilc_ie = false;
- wfi_drv->p2p_timeout = 0;
+ priv->hif_drv->p2p_timeout = 0;
ret = wilc_disconnect(vif);
if (ret != 0) {
@@ -1210,7 +935,7 @@ static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
}
static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx,
- u8 op_ch_attr_idx)
+ u8 op_ch_attr_idx, u8 sta_ch)
{
int i = 0;
int j = 0;
@@ -1221,7 +946,7 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx,
for (i = ch_list_attr_idx + 3; i < limit; i++) {
if (buf[i] == 0x51) {
for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
- buf[j] = wlan_channel;
+ buf[j] = sta_ch;
break;
}
}
@@ -1229,11 +954,11 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx,
if (op_ch_attr_idx) {
buf[op_ch_attr_idx + 6] = 0x51;
- buf[op_ch_attr_idx + 7] = wlan_channel;
+ buf[op_ch_attr_idx + 7] = sta_ch;
}
}
-static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len)
+static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len, u8 sta_ch)
{
u32 index = 0;
u8 op_channel_attr_index = 0;
@@ -1249,13 +974,13 @@ static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len)
op_channel_attr_index = index;
index += buf[index + 1] + 3;
}
- if (wlan_channel != INVALID_CHANNEL)
+ if (sta_ch != WILC_INVALID_CHANNEL)
wilc_wfi_cfg_parse_ch_attr(buf, channel_list_attr_index,
- op_channel_attr_index);
+ op_channel_attr_index, sta_ch);
}
static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch,
- u8 iftype)
+ u8 iftype, u8 sta_ch)
{
u32 index = 0;
u8 op_channel_attr_index = 0;
@@ -1274,9 +999,9 @@ static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch,
op_channel_attr_index = index;
index += buf[index + 1] + 3;
}
- if (wlan_channel != INVALID_CHANNEL && oper_ch)
+ if (sta_ch != WILC_INVALID_CHANNEL && oper_ch)
wilc_wfi_cfg_parse_ch_attr(buf, channel_list_attr_index,
- op_channel_attr_index);
+ op_channel_attr_index, sta_ch);
}
static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
@@ -1311,7 +1036,8 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
if (buff[i] == P2PELEM_ATTR_ID &&
!(memcmp(p2p_oui, &buff[i + 2], 4))) {
wilc_wfi_cfg_parse_rx_action(&buff[i + 6],
- size - (i + 6));
+ size - (i + 6),
+ vif->wilc->sta_ch);
break;
}
}
@@ -1322,6 +1048,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
{
struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
struct host_if_drv *wfi_drv = priv->hif_drv;
+ struct wilc_vif *vif = netdev_priv(dev);
+ struct wilc *wl = vif->wilc;
u32 header, pkt_offset;
s32 freq;
__le16 fc;
@@ -1342,7 +1070,7 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
return;
}
- freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ);
+ freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);
fc = ((struct ieee80211_hdr *)buff)->frame_control;
if (!ieee80211_is_action(fc)) {
@@ -1387,33 +1115,18 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
{
- struct p2p_mgmt_data *pv_data = priv;
+ struct wilc_p2p_mgmt_data *pv_data = priv;
kfree(pv_data->buff);
kfree(pv_data);
}
-static void wilc_wfi_remain_on_channel_ready(void *priv_data)
-{
- struct wilc_priv *priv;
-
- priv = priv_data;
-
- priv->p2p_listen_state = true;
-
- cfg80211_ready_on_channel(priv->wdev,
- priv->remain_on_ch_params.listen_cookie,
- priv->remain_on_ch_params.listen_ch,
- priv->remain_on_ch_params.listen_duration,
- GFP_KERNEL);
-}
-
-static void wilc_wfi_remain_on_channel_expired(void *data, u32 session_id)
+static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
{
struct wilc_priv *priv = data;
struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;
- if (session_id != params->listen_session_id)
+ if (cookie != params->listen_cookie)
return;
priv->p2p_listen_state = false;
@@ -1430,24 +1143,36 @@ static int remain_on_channel(struct wiphy *wiphy,
int ret = 0;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
+ u64 id;
if (wdev->iftype == NL80211_IFTYPE_AP) {
netdev_dbg(vif->ndev, "Required while in AP mode\n");
return ret;
}
- curr_channel = chan->hw_value;
+ id = ++priv->inc_roc_cookie;
+ if (id == 0)
+ id = ++priv->inc_roc_cookie;
+
+ ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
+ wilc_wfi_remain_on_channel_expired,
+ (void *)priv);
+ if (ret)
+ return ret;
+
+ vif->wilc->op_ch = chan->hw_value;
priv->remain_on_ch_params.listen_ch = chan;
- priv->remain_on_ch_params.listen_cookie = *cookie;
+ priv->remain_on_ch_params.listen_cookie = id;
+ *cookie = id;
+ priv->p2p_listen_state = true;
priv->remain_on_ch_params.listen_duration = duration;
- priv->remain_on_ch_params.listen_session_id++;
- return wilc_remain_on_channel(vif,
- priv->remain_on_ch_params.listen_session_id,
- duration, chan->hw_value,
- wilc_wfi_remain_on_channel_expired,
- wilc_wfi_remain_on_channel_ready, (void *)priv);
+ cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);
+ mod_timer(&vif->hif_drv->remain_on_ch_timer,
+ jiffies + msecs_to_jiffies(duration));
+
+ return ret;
}
static int cancel_remain_on_channel(struct wiphy *wiphy,
@@ -1457,12 +1182,14 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
- return wilc_listen_state_expired(vif,
- priv->remain_on_ch_params.listen_session_id);
+ if (cookie != priv->remain_on_ch_params.listen_cookie)
+ return -ENOENT;
+
+ return wilc_listen_state_expired(vif, cookie);
}
static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
- struct p2p_mgmt_data *mgmt_tx,
+ struct wilc_p2p_mgmt_data *mgmt_tx,
struct cfg80211_mgmt_tx_params *params,
u8 iftype, u32 buf_len)
{
@@ -1470,6 +1197,7 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
size_t len = params->len;
u32 i;
u8 subtype = buf[P2P_PUB_ACTION_SUBTYPE];
+ struct wilc_vif *vif = netdev_priv(priv->dev);
if (subtype == GO_NEG_REQ || subtype == GO_NEG_RSP) {
if (priv->p2p.local_random == 1 &&
@@ -1494,7 +1222,8 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
oper_ch = true;
wilc_wfi_cfg_parse_tx_action(tx_buff, len - (i + 6),
- oper_ch, iftype);
+ oper_ch, iftype,
+ vif->wilc->sta_ch);
break;
}
@@ -1520,14 +1249,14 @@ static int mgmt_tx(struct wiphy *wiphy,
const u8 *buf = params->buf;
size_t len = params->len;
const struct ieee80211_mgmt *mgmt;
- struct p2p_mgmt_data *mgmt_tx;
+ struct wilc_p2p_mgmt_data *mgmt_tx;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct host_if_drv *wfi_drv = priv->hif_drv;
struct wilc_vif *vif = netdev_priv(wdev->netdev);
u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(priv->p2p.local_random);
int ret = 0;
- *cookie = (unsigned long)buf;
+ *cookie = prandom_u32();
priv->tx_cookie = *cookie;
mgmt = (const struct ieee80211_mgmt *)buf;
@@ -1552,7 +1281,7 @@ static int mgmt_tx(struct wiphy *wiphy,
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
wilc_set_mac_chnl_num(vif, chan->hw_value);
- curr_channel = chan->hw_value;
+ vif->wilc->op_ch = chan->hw_value;
goto out_txq_add_pkt;
}
@@ -1563,7 +1292,7 @@ static int mgmt_tx(struct wiphy *wiphy,
if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
wilc_set_mac_chnl_num(vif, chan->hw_value);
- curr_channel = chan->hw_value;
+ vif->wilc->op_ch = chan->hw_value;
}
switch (buf[ACTION_SUBTYPE_ID]) {
case GAS_INITIAL_REQ:
@@ -1755,7 +1484,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_P2P_GO:
vif->obtaining_ip = true;
mod_timer(&vif->during_ip_timer,
- jiffies + msecs_to_jiffies(DURING_IP_TIME_OUT));
+ jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS));
wilc_set_operation_mode(vif, WILC_AP_MODE);
dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type;
@@ -1805,9 +1534,8 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
int ret;
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
- u8 null_bssid[ETH_ALEN] = {0};
- wilc_wlan_set_bssid(dev, null_bssid, WILC_AP_MODE);
+ wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);
ret = wilc_del_beacon(vif);
@@ -1884,7 +1612,8 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
struct net_device *new_ifc;
if (type == NL80211_IFTYPE_MONITOR) {
- new_ifc = wilc_wfi_init_mon_interface(name, vif->ndev);
+ new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name,
+ vif->ndev);
if (new_ifc) {
vif = netdev_priv(priv->wdev->netdev);
vif->monitor_flag = 1;
@@ -2102,7 +1831,6 @@ int wilc_init_host_int(struct net_device *net)
struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
struct wilc_vif *vif = netdev_priv(priv->dev);
- timer_setup(&priv->aging_timer, remove_network_from_shadow, 0);
timer_setup(&vif->during_ip_timer, clear_during_ip, 0);
priv->p2p_listen_state = false;
@@ -2126,8 +1854,6 @@ void wilc_deinit_host_int(struct net_device *net)
mutex_destroy(&priv->scan_req_lock);
ret = wilc_deinit(vif);
- del_timer_sync(&priv->aging_timer);
- clear_shadow_scan(priv);
del_timer_sync(&vif->during_ip_timer);
if (ret)
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
index 4812c8e2c79b..31dfa1f141f1 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
@@ -13,9 +13,10 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net,
void wilc_free_wiphy(struct net_device *net);
void wilc_deinit_host_int(struct net_device *net);
int wilc_init_host_int(struct net_device *net);
-void wilc_wfi_monitor_rx(u8 *buff, u32 size);
-void wilc_wfi_deinit_mon_interface(void);
-struct net_device *wilc_wfi_init_mon_interface(const char *name,
+void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
+void wilc_wfi_deinit_mon_interface(struct wilc *wl);
+struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
+ const char *name,
struct net_device *real_dev);
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
u16 frame_type, bool reg);
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index c6685c0c238b..df00762487c0 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -65,7 +65,6 @@ struct wilc_wfi_p2p_listen_params {
struct ieee80211_channel *listen_ch;
u32 listen_duration;
u64 listen_cookie;
- u32 listen_session_id;
};
struct wilc_p2p_var {
@@ -137,7 +136,6 @@ struct wilc_priv {
u64 tx_cookie;
bool cfg_scanning;
- u32 rcvd_ch_cnt;
u8 associated_bss[ETH_ALEN];
struct sta_info assoc_stainfo;
@@ -155,8 +153,6 @@ struct wilc_priv {
/* mutexes */
struct mutex scan_req_lock;
bool p2p_listen_state;
- struct timer_list aging_timer;
- struct network_info scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
int scanned_cnt;
struct wilc_p2p_var p2p;
@@ -164,6 +160,7 @@ struct wilc_priv {
struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
struct ieee80211_supported_band band;
u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
+ u64 inc_roc_cookie;
};
struct frame_reg {
@@ -251,7 +248,7 @@ struct wilc {
struct mutex cfg_cmd_lock;
struct wilc_cfg_frame cfg_frame;
u32 cfg_frame_offset;
- int cfg_seq_no;
+ u8 cfg_seq_no;
u8 *rx_buffer;
u32 rx_buffer_offset;
@@ -273,13 +270,18 @@ struct wilc {
enum chip_ps_states chip_ps_state;
struct wilc_cfg cfg;
void *bus_data;
+ struct net_device *monitor_dev;
+ /* deinit lock */
+ struct mutex deinit_lock;
+ u8 sta_ch;
+ u8 op_ch;
};
struct wilc_wfi_mon_priv {
struct net_device *real_ndev;
};
-void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
+void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
void wilc_mac_indicate(struct wilc *wilc);
void wilc_netdev_cleanup(struct wilc *wilc);
int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index 3c5e9e030cad..c2389695fe20 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -274,7 +274,8 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
}
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
- u32 buffer_size, wilc_tx_complete_func_t func)
+ u32 buffer_size,
+ void (*tx_complete_fn)(void *, int))
{
struct txq_entry_t *tqe;
struct wilc_vif *vif = netdev_priv(dev);
@@ -292,7 +293,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->type = WILC_NET_PKT;
tqe->buffer = buffer;
tqe->buffer_size = buffer_size;
- tqe->tx_complete_func = func;
+ tqe->tx_complete_func = tx_complete_fn;
tqe->priv = priv;
tqe->ack_idx = NOT_TCP_ACK;
@@ -303,7 +304,8 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
}
int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
- u32 buffer_size, wilc_tx_complete_func_t func)
+ u32 buffer_size,
+ void (*tx_complete_fn)(void *, int))
{
struct txq_entry_t *tqe;
struct wilc_vif *vif = netdev_priv(dev);
@@ -321,7 +323,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->type = WILC_MGMT_PKT;
tqe->buffer = buffer;
tqe->buffer_size = buffer_size;
- tqe->tx_complete_func = func;
+ tqe->tx_complete_func = tx_complete_fn;
tqe->priv = priv;
tqe->ack_idx = NOT_TCP_ACK;
wilc_wlan_txq_add_to_tail(dev, tqe);
@@ -521,7 +523,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
if (vmm_sz & 0x3)
vmm_sz = (vmm_sz + 4) & ~0x3;
- if ((sum + vmm_sz) > LINUX_TX_SIZE)
+ if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE)
break;
vmm_table[i] = vmm_sz / 4;
@@ -715,9 +717,8 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
} else {
if (!is_cfg_packet) {
if (pkt_len > 0) {
- wilc_frmw_to_linux(wilc, buff_ptr,
- pkt_len,
- pkt_offset);
+ wilc_frmw_to_host(wilc, buff_ptr,
+ pkt_len, pkt_offset);
}
} else {
struct wilc_cfg_rsp rsp;
@@ -809,7 +810,7 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
if (size <= 0)
return;
- if (LINUX_RX_SIZE - offset < size)
+ if (WILC_RX_BUFF_SIZE - offset < size)
offset = 0;
buffer = &wilc->rx_buffer[offset];
@@ -1092,24 +1093,19 @@ static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type,
{
struct wilc *wilc = vif->wilc;
struct wilc_cfg_frame *cfg = &wilc->cfg_frame;
- int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
- int seq_no = wilc->cfg_seq_no % 256;
- int driver_handler = (u32)drv_handler;
+ int t_len = wilc->cfg_frame_offset + sizeof(struct wilc_cfg_cmd_hdr);
if (type == WILC_CFG_SET)
- cfg->wid_header[0] = 'W';
+ cfg->hdr.cmd_type = 'W';
else
- cfg->wid_header[0] = 'Q';
- cfg->wid_header[1] = seq_no;
- cfg->wid_header[2] = (u8)total_len;
- cfg->wid_header[3] = (u8)(total_len >> 8);
- cfg->wid_header[4] = (u8)driver_handler;
- cfg->wid_header[5] = (u8)(driver_handler >> 8);
- cfg->wid_header[6] = (u8)(driver_handler >> 16);
- cfg->wid_header[7] = (u8)(driver_handler >> 24);
- wilc->cfg_seq_no = seq_no;
-
- if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len))
+ cfg->hdr.cmd_type = 'Q';
+
+ cfg->hdr.seq_no = wilc->cfg_seq_no % 256;
+ cfg->hdr.total_len = cpu_to_le16(t_len);
+ cfg->hdr.driver_handler = cpu_to_le32(drv_handler);
+ wilc->cfg_seq_no = cfg->hdr.seq_no;
+
+ if (!wilc_wlan_txq_add_cfg_pkt(vif, (u8 *)&cfg->hdr, t_len))
return -1;
return 0;
@@ -1144,7 +1140,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
ret_size = 0;
if (!wait_for_completion_timeout(&wilc->cfg_event,
- msecs_to_jiffies(CFG_PKTS_TIMEOUT))) {
+ WILC_CFG_PKTS_TIMEOUT)) {
netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);
ret_size = 0;
}
@@ -1182,7 +1178,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
ret_size = 0;
if (!wait_for_completion_timeout(&wilc->cfg_event,
- msecs_to_jiffies(CFG_PKTS_TIMEOUT))) {
+ WILC_CFG_PKTS_TIMEOUT)) {
netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);
ret_size = 0;
}
@@ -1252,21 +1248,22 @@ static u32 init_chip(struct net_device *dev)
ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
if (!ret) {
netdev_err(dev, "fail read reg 0x1118\n");
- return ret;
+ goto release;
}
reg |= BIT(0);
ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
if (!ret) {
netdev_err(dev, "fail write reg 0x1118\n");
- return ret;
+ goto release;
}
ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
if (!ret) {
netdev_err(dev, "fail write reg 0xc0000\n");
- return ret;
+ goto release;
}
}
+release:
release_bus(wilc, WILC_BUS_RELEASE_ONLY);
return ret;
@@ -1316,7 +1313,7 @@ int wilc_wlan_init(struct net_device *dev)
}
if (!wilc->tx_buffer)
- wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
+ wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
if (!wilc->tx_buffer) {
ret = -ENOBUFS;
@@ -1324,7 +1321,7 @@ int wilc_wlan_init(struct net_device *dev)
}
if (!wilc->rx_buffer)
- wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
+ wilc->rx_buffer = kmalloc(WILC_RX_BUFF_SIZE, GFP_KERNEL);
if (!wilc->rx_buffer) {
ret = -ENOBUFS;
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index 27667131de1a..1a27f62589a2 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -14,7 +14,6 @@
* Mac eth header length
*
********************************************/
-#define DRIVER_HANDLER_SIZE 4
#define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */
#define SUB_MSDU_HEADER_LENGTH 14
#define SNAP_HDR_LEN 8
@@ -132,8 +131,8 @@
#define WILC_PLL_TO_SPI 2
#define ABORT_INT BIT(31)
-#define LINUX_RX_SIZE (96 * 1024)
-#define LINUX_TX_SIZE (64 * 1024)
+#define WILC_RX_BUFF_SIZE (96 * 1024)
+#define WILC_TX_BUFF_SIZE (64 * 1024)
#define MODALIAS "WILC_SPI"
#define GPIO_NUM 0x44
@@ -197,7 +196,7 @@
#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM)
#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM)
/*time for expiring the completion of cfg packets*/
-#define CFG_PKTS_TIMEOUT 2000
+#define WILC_CFG_PKTS_TIMEOUT msecs_to_jiffies(2000)
#define IS_MANAGMEMENT 0x100
#define IS_MANAGMEMENT_CALLBACK 0x080
@@ -249,16 +248,30 @@ struct wilc_hif_func {
void (*disable_interrupt)(struct wilc *nic);
};
-#define MAX_CFG_FRAME_SIZE 1468
+#define WILC_MAX_CFG_FRAME_SIZE 1468
+
+struct tx_complete_data {
+ int size;
+ void *buff;
+ u8 *bssid;
+ struct sk_buff *skb;
+};
+
+struct wilc_cfg_cmd_hdr {
+ u8 cmd_type;
+ u8 seq_no;
+ __le16 total_len;
+ __le32 driver_handler;
+};
struct wilc_cfg_frame {
- u8 wid_header[8];
- u8 frame[MAX_CFG_FRAME_SIZE];
+ struct wilc_cfg_cmd_hdr hdr;
+ u8 frame[WILC_MAX_CFG_FRAME_SIZE];
};
struct wilc_cfg_rsp {
- int type;
- u32 seq_no;
+ u8 type;
+ u8 seq_no;
};
struct wilc;
@@ -269,7 +282,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
int wilc_wlan_start(struct wilc *wilc);
int wilc_wlan_stop(struct wilc *wilc);
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
- u32 buffer_size, wilc_tx_complete_func_t func);
+ u32 buffer_size,
+ void (*tx_complete_fn)(void *, int));
int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count);
void wilc_handle_isr(struct wilc *wilc);
void wilc_wlan_cleanup(struct net_device *dev);
@@ -280,7 +294,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer,
u32 buffer_size);
int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
- u32 buffer_size, wilc_tx_complete_func_t func);
+ u32 buffer_size, void (*func)(void *, int));
void wilc_chip_sleep_manually(struct wilc *wilc);
void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value);
@@ -294,4 +308,6 @@ void chip_allow_sleep(struct wilc *wilc);
void chip_wakeup(struct wilc *wilc);
int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
u32 count, u32 drv);
+int wilc_wlan_init(struct net_device *dev);
+u32 wilc_get_chipid(struct wilc *wilc, bool update);
#endif
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c
index 8390766358da..9dc5de4eb08d 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.c
+++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c
@@ -54,7 +54,7 @@ static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
{
u8 *buf;
- if ((offset + 4) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -71,7 +71,7 @@ static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
{
u8 *buf;
- if ((offset + 5) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -90,7 +90,7 @@ static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
{
u8 *buf;
- if ((offset + 7) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -112,7 +112,7 @@ static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
{
u8 *buf;
- if ((offset + size + 4) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -134,7 +134,7 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
u32 i;
u8 checksum = 0;
- if ((offset + size + 5) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -168,7 +168,7 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
while (size > 0) {
i = 0;
- wid = info[0] | (info[1] << 8);
+ wid = get_unaligned_le16(info);
switch (GET_WID_TYPE(wid)) {
case WID_CHAR:
@@ -187,12 +187,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
case WID_SHORT:
do {
- if (wl->cfg.hw[i].id == WID_NIL)
+ struct wilc_cfg_hword *hw = &wl->cfg.hw[i];
+
+ if (hw->id == WID_NIL)
break;
- if (wl->cfg.hw[i].id == wid) {
- wl->cfg.hw[i].val = (info[4] |
- (info[5] << 8));
+ if (hw->id == wid) {
+ hw->val = get_unaligned_le16(&info[4]);
break;
}
i++;
@@ -202,14 +203,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
case WID_INT:
do {
- if (wl->cfg.w[i].id == WID_NIL)
+ struct wilc_cfg_word *w = &wl->cfg.w[i];
+
+ if (w->id == WID_NIL)
break;
- if (wl->cfg.w[i].id == wid) {
- wl->cfg.w[i].val = (info[4] |
- (info[5] << 8) |
- (info[6] << 16) |
- (info[7] << 24));
+ if (w->id == wid) {
+ w->val = get_unaligned_le32(&info[4]);
break;
}
i++;
@@ -244,7 +244,7 @@ static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info)
{
u32 wid, len;
- wid = info[0] | (info[1] << 8);
+ wid = get_unaligned_le16(info);
len = info[2];
@@ -309,7 +309,7 @@ int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id)
{
u8 *buf;
- if ((offset + 2) >= MAX_CFG_FRAME_SIZE)
+ if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE)
return 0;
buf = &frame[offset];
@@ -371,8 +371,7 @@ int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer,
break;
if (id == wid) {
- u32 size = (wl->cfg.s[i].str[0] |
- (wl->cfg.s[i].str[1] << 8));
+ u16 size = get_unaligned_le16(wl->cfg.s[i].str);
if (buffer_size >= size) {
memcpy(buffer, &wl->cfg.s[i].str[2],
diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h
index e2310d860291..b15de36e32e0 100644
--- a/drivers/staging/wilc1000/wilc_wlan_if.h
+++ b/drivers/staging/wilc1000/wilc_wlan_if.h
@@ -11,44 +11,9 @@
/********************************************
*
- * Host Interface Defines
- *
- ********************************************/
-
-enum {
- WILC_HIF_SDIO = 0,
- WILC_HIF_SPI = BIT(0)
-};
-
-/********************************************
- *
- * Wlan Interface Defines
- *
- ********************************************/
-
-enum {
- WILC_MAC_STATUS_INIT = -1,
- WILC_MAC_STATUS_DISCONNECTED = 0,
- WILC_MAC_STATUS_CONNECTED = 1
-};
-
-struct tx_complete_data {
- int size;
- void *buff;
- u8 *bssid;
- struct sk_buff *skb;
-};
-
-typedef void (*wilc_tx_complete_func_t)(void *, int);
-
-/********************************************
- *
* Wlan Configuration ID
*
********************************************/
-#define WILC_MULTICAST_TABLE_SIZE 8
-#define MAX_SSID_LEN 33
-#define MAX_RATES_SUPPORTED 12
enum bss_types {
WILC_FW_BSS_TYPE_INFRA = 0,
@@ -689,7 +654,6 @@ enum {
WID_TX_POWER_LEVEL_11N = 0x00B1,
/* Custom Character WID list */
- WID_PC_TEST_MODE = 0x00C8,
/* SCAN Complete notification WID*/
WID_SCAN_COMPLETE = 0x00C9,
@@ -836,8 +800,4 @@ enum {
WID_MAX = 0xFFFF
};
-struct wilc;
-int wilc_wlan_init(struct net_device *dev);
-u32 wilc_get_chipid(struct wilc *wilc, bool update);
-
#endif
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
index 426d4efbabc3..97238018b315 100644
--- a/drivers/staging/wlan-ng/Kconfig
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -4,7 +4,7 @@ config PRISM2_USB
select WIRELESS_EXT
select WEXT_PRIV
default n
- ---help---
+ help
This is the wlan-ng prism 2.5/3 USB driver for a wide range of
old USB wireless devices.
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index e5d7def1f366..8a862f718d5c 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -70,7 +70,8 @@ static int prism2_result2err(int prism2_result)
return err;
}
-static int prism2_domibset_uint32(struct wlandevice *wlandev, u32 did, u32 data)
+static int prism2_domibset_uint32(struct wlandevice *wlandev,
+ u32 did, u32 data)
{
struct p80211msg_dot11req_mibset msg;
struct p80211item_uint32 *mibitem =
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index bb572b7fdfee..94800c007162 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -556,10 +556,9 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt)
/* Allocate buffer space for chunks */
for (i = 0; i < *ccnt; i++) {
clist[i].data = kzalloc(clist[i].len, GFP_KERNEL);
- if (!clist[i].data) {
- pr_err("failed to allocate image space, exiting.\n");
+ if (!clist[i].data)
return 1;
- }
+
pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
i, clist[i].addr, clist[i].len);
}
diff --git a/drivers/staging/xgifb/Kconfig b/drivers/staging/xgifb/Kconfig
deleted file mode 100644
index bb0ca5974ea0..000000000000
--- a/drivers/staging/xgifb/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-config FB_XGI
- tristate "XGI display support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This driver supports notebooks with XGI Z7,Z9,Z11 PCI chips.
- Say Y if you have such a graphics card.
- To compile this driver as a module, choose M here: the
- module will be called xgifb.ko
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
deleted file mode 100644
index 964a843c4521..000000000000
--- a/drivers/staging/xgifb/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_FB_XGI) += xgifb.o
-
-xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o
-
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
deleted file mode 100644
index 7eb99140a399..000000000000
--- a/drivers/staging/xgifb/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-This drivers still needs a lot of work. I can list all cleanups to do but it's
-going to be long. So, I'm writing "cleanups" and not the list.
-
-Arnaud
-
-TODO:
-- clean ups
-- sort out dup ids with SiS driver
-- remove useless/wrong/unused code...
-- get rid of non-linux related stuff
-
-Please send patches to:
-Arnaud Patard <arnaud.patard@rtp-net.org>
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
deleted file mode 100644
index e19a8291cb2a..000000000000
--- a/drivers/staging/xgifb/XGI_main.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _XGIFB_MAIN
-#define _XGIFB_MAIN
-/* ------------------- Constant Definitions ------------------------- */
-#include "XGIfb.h"
-#include "vb_def.h"
-
-#define PCI_DEVICE_ID_XGI_42 0x042
-#define PCI_DEVICE_ID_XGI_27 0x027
-
-static const struct pci_device_id xgifb_pci_table[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_20)},
- {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_27)},
- {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_40)},
- {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_42)},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
-
-#define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */
-#define IND_XGI_SCRATCH_REG_CR31 0x31
-#define IND_XGI_SCRATCH_REG_CR32 0x32
-#define IND_XGI_SCRATCH_REG_CR33 0x33
-#define IND_XGI_LCD_PANEL 0x36
-#define IND_XGI_SCRATCH_REG_CR37 0x37
-
-#define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */
-#define XGI_DRAM_SIZE_1MB 0x00
-#define XGI_DRAM_SIZE_2MB 0x01
-#define XGI_DRAM_SIZE_4MB 0x02
-#define XGI_DRAM_SIZE_8MB 0x03
-#define XGI_DRAM_SIZE_16MB 0x04
-#define XGI_DRAM_SIZE_32MB 0x05
-#define XGI_DRAM_SIZE_64MB 0x06
-#define XGI_DRAM_SIZE_128MB 0x07
-#define XGI_DRAM_SIZE_256MB 0x08
-
-/* ------------------- Global Variables ----------------------------- */
-
-/* display status */
-static int XGIfb_crt1off;
-static int XGIfb_forcecrt1 = -1;
-
-/* global flags */
-static int XGIfb_tvmode;
-static int enable_dstn;
-static int XGIfb_ypan = -1;
-
-/* TW: CRT2 type (for overriding autodetection) */
-static int XGIfb_crt2type = -1;
-/* PR: Tv plug type (for overriding autodetection) */
-static int XGIfb_tvplug = -1;
-
-#define MD_XGI315 1
-
-/* mode table */
-static const struct _XGIbios_mode {
- u8 mode_no;
- u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */
- u16 vesa_mode_no_2; /* Real VESA mode numbers */
- u16 xres;
- u16 yres;
- u16 bpp;
- u8 chipset;
-} XGIbios_mode[] = {
- { 0x56, 0x0000, 0x0000, 320, 240, 16, MD_XGI315 },
- { 0x5A, 0x0000, 0x0000, 320, 480, 8, MD_XGI315 },
- { 0x5B, 0x0000, 0x0000, 320, 480, 16, MD_XGI315 },
- { 0x2E, 0x0101, 0x0101, 640, 480, 8, MD_XGI315 },
- { 0x44, 0x0111, 0x0111, 640, 480, 16, MD_XGI315 },
- { 0x62, 0x013a, 0x0112, 640, 480, 32, MD_XGI315 },
- { 0x31, 0x0000, 0x0000, 720, 480, 8, MD_XGI315 },
- { 0x33, 0x0000, 0x0000, 720, 480, 16, MD_XGI315 },
- { 0x35, 0x0000, 0x0000, 720, 480, 32, MD_XGI315 },
- { 0x32, 0x0000, 0x0000, 720, 576, 8, MD_XGI315 },
- { 0x34, 0x0000, 0x0000, 720, 576, 16, MD_XGI315 },
- { 0x36, 0x0000, 0x0000, 720, 576, 32, MD_XGI315 },
- { 0x36, 0x0000, 0x0000, 720, 576, 32, MD_XGI315 },
- { 0x70, 0x0000, 0x0000, 800, 480, 8, MD_XGI315 },
- { 0x7a, 0x0000, 0x0000, 800, 480, 16, MD_XGI315 },
- { 0x76, 0x0000, 0x0000, 800, 480, 32, MD_XGI315 },
- { 0x30, 0x0103, 0x0103, 800, 600, 8, MD_XGI315 },
-#define DEFAULT_MODE 17 /* index for 800x600x16 */
- { 0x47, 0x0114, 0x0114, 800, 600, 16, MD_XGI315 },
- { 0x63, 0x013b, 0x0115, 800, 600, 32, MD_XGI315 },
- { 0x71, 0x0000, 0x0000, 1024, 576, 8, MD_XGI315 },
- { 0x74, 0x0000, 0x0000, 1024, 576, 16, MD_XGI315 },
- { 0x77, 0x0000, 0x0000, 1024, 576, 32, MD_XGI315 },
- { 0x77, 0x0000, 0x0000, 1024, 576, 32, MD_XGI315 },
- { 0x20, 0x0000, 0x0000, 1024, 600, 8, },
- { 0x21, 0x0000, 0x0000, 1024, 600, 16, },
- { 0x22, 0x0000, 0x0000, 1024, 600, 32, },
- { 0x38, 0x0105, 0x0105, 1024, 768, 8, MD_XGI315 },
- { 0x4A, 0x0117, 0x0117, 1024, 768, 16, MD_XGI315 },
- { 0x64, 0x013c, 0x0118, 1024, 768, 32, MD_XGI315 },
- { 0x64, 0x013c, 0x0118, 1024, 768, 32, MD_XGI315 },
- { 0x23, 0x0000, 0x0000, 1152, 768, 8, },
- { 0x24, 0x0000, 0x0000, 1152, 768, 16, },
- { 0x25, 0x0000, 0x0000, 1152, 768, 32, },
- { 0x79, 0x0000, 0x0000, 1280, 720, 8, MD_XGI315 },
- { 0x75, 0x0000, 0x0000, 1280, 720, 16, MD_XGI315 },
- { 0x78, 0x0000, 0x0000, 1280, 720, 32, MD_XGI315 },
- { 0x23, 0x0000, 0x0000, 1280, 768, 8, MD_XGI315 },
- { 0x24, 0x0000, 0x0000, 1280, 768, 16, MD_XGI315 },
- { 0x25, 0x0000, 0x0000, 1280, 768, 32, MD_XGI315 },
- { 0x7C, 0x0000, 0x0000, 1280, 960, 8, MD_XGI315 },
- { 0x7D, 0x0000, 0x0000, 1280, 960, 16, MD_XGI315 },
- { 0x7E, 0x0000, 0x0000, 1280, 960, 32, MD_XGI315 },
- { 0x3A, 0x0107, 0x0107, 1280, 1024, 8, MD_XGI315 },
- { 0x4D, 0x011a, 0x011a, 1280, 1024, 16, MD_XGI315 },
- { 0x65, 0x013d, 0x011b, 1280, 1024, 32, MD_XGI315 },
- { 0x26, 0x0000, 0x0000, 1400, 1050, 8, MD_XGI315 },
- { 0x27, 0x0000, 0x0000, 1400, 1050, 16, MD_XGI315 },
- { 0x28, 0x0000, 0x0000, 1400, 1050, 32, MD_XGI315 },
- { 0x3C, 0x0130, 0x011c, 1600, 1200, 8, MD_XGI315 },
- { 0x3D, 0x0131, 0x011e, 1600, 1200, 16, MD_XGI315 },
- { 0x66, 0x013e, 0x011f, 1600, 1200, 32, MD_XGI315 },
- { 0x68, 0x013f, 0x0000, 1920, 1440, 8, MD_XGI315 },
- { 0x69, 0x0140, 0x0000, 1920, 1440, 16, MD_XGI315 },
- { 0x6B, 0x0141, 0x0000, 1920, 1440, 32, MD_XGI315 },
- { 0x6c, 0x0000, 0x0000, 2048, 1536, 8, MD_XGI315 },
- { 0x6d, 0x0000, 0x0000, 2048, 1536, 16, MD_XGI315 },
- { 0x6e, 0x0000, 0x0000, 2048, 1536, 32, MD_XGI315 },
- { 0 },
-};
-
-static const unsigned short XGI310paneltype[] = {
- LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
- LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
- LCD_1024x768, LCD_1024x768, LCD_1024x768};
-
-static const struct _XGI_crt2type {
- char name[10];
- int type_no;
- int tvplug_no;
-} XGI_crt2type[] = {
- {"NONE", 0, -1},
- {"LCD", XGIFB_DISP_LCD, -1},
- {"TV", XGIFB_DISP_TV, -1},
- {"VGA", XGIFB_DISP_CRT, -1},
- {"SVIDEO", XGIFB_DISP_TV, TVPLUG_SVIDEO},
- {"COMPOSITE", XGIFB_DISP_TV, TVPLUG_COMPOSITE},
- {"SCART", XGIFB_DISP_TV, TVPLUG_SCART},
- {"none", 0, -1},
- {"lcd", XGIFB_DISP_LCD, -1},
- {"tv", XGIFB_DISP_TV, -1},
- {"vga", XGIFB_DISP_CRT, -1},
- {"svideo", XGIFB_DISP_TV, TVPLUG_SVIDEO},
- {"composite", XGIFB_DISP_TV, TVPLUG_COMPOSITE},
- {"scart", XGIFB_DISP_TV, TVPLUG_SCART},
- {"\0", -1, -1}
-};
-
-/* TV standard */
-static const struct _XGI_tvtype {
- char name[6];
- int type_no;
-} XGI_tvtype[] = {
- {"PAL", 1},
- {"NTSC", 2},
- {"pal", 1},
- {"ntsc", 2},
- {"\0", -1}
-};
-
-static const struct _XGI_vrate {
- u16 idx;
- u16 xres;
- u16 yres;
- u16 refresh;
-} XGIfb_vrate[] = {
- {1, 640, 480, 60}, {2, 640, 480, 72},
- {3, 640, 480, 75}, {4, 640, 480, 85},
-
- {5, 640, 480, 100}, {6, 640, 480, 120},
- {7, 640, 480, 160}, {8, 640, 480, 200},
-
- {1, 720, 480, 60},
- {1, 720, 576, 58},
- {1, 800, 480, 60}, {2, 800, 480, 75}, {3, 800, 480, 85},
- {1, 800, 600, 60}, {2, 800, 600, 72}, {3, 800, 600, 75},
- {4, 800, 600, 85}, {5, 800, 600, 100},
- {6, 800, 600, 120}, {7, 800, 600, 160},
-
- {1, 1024, 768, 60}, {2, 1024, 768, 70}, {3, 1024, 768, 75},
- {4, 1024, 768, 85}, {5, 1024, 768, 100}, {6, 1024, 768, 120},
- {1, 1024, 576, 60}, {2, 1024, 576, 75}, {3, 1024, 576, 85},
- {1, 1024, 600, 60},
- {1, 1152, 768, 60},
- {1, 1280, 720, 60}, {2, 1280, 720, 75}, {3, 1280, 720, 85},
- {1, 1280, 768, 60},
- {1, 1280, 1024, 60}, {2, 1280, 1024, 75}, {3, 1280, 1024, 85},
- {1, 1280, 960, 70},
- {1, 1400, 1050, 60},
- {1, 1600, 1200, 60}, {2, 1600, 1200, 65},
- {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
-
- {5, 1600, 1200, 85}, {6, 1600, 1200, 100},
- {7, 1600, 1200, 120},
-
- {1, 1920, 1440, 60}, {2, 1920, 1440, 65},
- {3, 1920, 1440, 70}, {4, 1920, 1440, 75},
-
- {5, 1920, 1440, 85}, {6, 1920, 1440, 100},
- {1, 2048, 1536, 60}, {2, 2048, 1536, 65},
- {3, 2048, 1536, 70}, {4, 2048, 1536, 75},
-
- {5, 2048, 1536, 85},
- {0, 0, 0, 0}
-};
-
-static const struct _XGI_TV_filter {
- u8 filter[9][4];
-} XGI_TV_filter[] = {
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_0 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_1 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_2 */
- {0xF5, 0xEE, 0x1B, 0x44},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xEB, 0x04, 0x25, 0x18},
- {0xF1, 0x05, 0x1F, 0x16},
- {0xF6, 0x06, 0x1A, 0x14},
- {0xFA, 0x06, 0x16, 0x14},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_3 */
- {0xF1, 0x04, 0x1F, 0x18},
- {0xEE, 0x0D, 0x22, 0x06},
- {0xF7, 0x06, 0x19, 0x14},
- {0xF4, 0x0B, 0x1C, 0x0A},
- {0xFA, 0x07, 0x16, 0x12},
- {0xF9, 0x0A, 0x17, 0x0C},
- {0x00, 0x07, 0x10, 0x12},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_4 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_5 */
- {0xF5, 0xEE, 0x1B, 0x44},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xEB, 0x04, 0x25, 0x18},
- {0xF1, 0x05, 0x1F, 0x16},
- {0xF6, 0x06, 0x1A, 0x14},
- {0xFA, 0x06, 0x16, 0x14},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_6 */
- {0xEB, 0x04, 0x25, 0x18},
- {0xE7, 0x0E, 0x29, 0x04},
- {0xEE, 0x0C, 0x22, 0x08},
- {0xF6, 0x0B, 0x1A, 0x0A},
- {0xF9, 0x0A, 0x17, 0x0C},
- {0xFC, 0x0A, 0x14, 0x0C},
- {0x00, 0x08, 0x10, 0x10},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* NTSCFilter_7 */
- {0xEC, 0x02, 0x24, 0x1C},
- {0xF2, 0x04, 0x1E, 0x18},
- {0xEB, 0x15, 0x25, 0xF6},
- {0xF4, 0x10, 0x1C, 0x00},
- {0xF8, 0x0F, 0x18, 0x02},
- {0x00, 0x04, 0x10, 0x18},
- {0x01, 0x06, 0x0F, 0x14},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_0 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_1 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_2 */
- {0xF5, 0xEE, 0x1B, 0x44},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xF1, 0xF7, 0x01, 0x32},
- {0xF5, 0xFB, 0x1B, 0x2A},
- {0xF9, 0xFF, 0x17, 0x22},
- {0xFB, 0x01, 0x15, 0x1E},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_3 */
- {0xF5, 0xFB, 0x1B, 0x2A},
- {0xEE, 0xFE, 0x22, 0x24},
- {0xF3, 0x00, 0x1D, 0x20},
- {0xF9, 0x03, 0x17, 0x1A},
- {0xFB, 0x02, 0x14, 0x1E},
- {0xFB, 0x04, 0x15, 0x18},
- {0x00, 0x06, 0x10, 0x14},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_4 */
- {0x00, 0xE0, 0x10, 0x60},
- {0x00, 0xEE, 0x10, 0x44},
- {0x00, 0xF4, 0x10, 0x38},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0x00, 0x00, 0x10, 0x20},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_5 */
- {0xF5, 0xEE, 0x1B, 0x44},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xF1, 0xF7, 0x1F, 0x32},
- {0xF5, 0xFB, 0x1B, 0x2A},
- {0xF9, 0xFF, 0x17, 0x22},
- {0xFB, 0x01, 0x15, 0x1E},
- {0x00, 0x04, 0x10, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_6 */
- {0xF5, 0xEE, 0x1B, 0x2A},
- {0xEE, 0xFE, 0x22, 0x24},
- {0xF3, 0x00, 0x1D, 0x20},
- {0xF9, 0x03, 0x17, 0x1A},
- {0xFB, 0x02, 0x14, 0x1E},
- {0xFB, 0x04, 0x15, 0x18},
- {0x00, 0x06, 0x10, 0x14},
- {0xFF, 0xFF, 0xFF, 0xFF} } },
- { { {0x00, 0x00, 0x00, 0x40}, /* PALFilter_7 */
- {0xF5, 0xEE, 0x1B, 0x44},
- {0xF8, 0xF4, 0x18, 0x38},
- {0xFC, 0xFB, 0x14, 0x2A},
- {0xEB, 0x05, 0x25, 0x16},
- {0xF1, 0x05, 0x1F, 0x16},
- {0xFA, 0x07, 0x16, 0x12},
- {0x00, 0x07, 0x10, 0x12},
- {0xFF, 0xFF, 0xFF, 0xFF} } }
-};
-
-static int filter = -1;
-
-#endif
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
deleted file mode 100644
index 217c6bb82c0d..000000000000
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ /dev/null
@@ -1,2084 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * XG20, XG21, XG40, XG42 frame buffer device
- * for Linux kernels 2.5.x, 2.6.x
- * Base on TW's sis fbdev code.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/sizes.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "XGI_main.h"
-#include "vb_init.h"
-#include "vb_util.h"
-#include "vb_setmode.h"
-
-#define Index_CR_GPIO_Reg1 0x48
-#define Index_CR_GPIO_Reg3 0x4a
-
-#define GPIOG_EN BIT(6)
-#define GPIOG_READ BIT(1)
-
-static char *forcecrt2type;
-static char *mode;
-static int vesa = -1;
-static unsigned int refresh_rate;
-
-/* -------------------- Macro definitions ---------------------------- */
-
-#ifdef DEBUG
-static void dumpVGAReg(struct xgifb_video_info *xgifb_info)
-{
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 i, reg;
-
- xgifb_reg_set(vb->P3c4, 0x05, 0x86);
-
- for (i = 0; i < 0x4f; i++) {
- reg = xgifb_reg_get(vb->P3c4, i);
- pr_debug("o 3c4 %x\n", i);
- pr_debug("i 3c5 => %x\n", reg);
- }
-
- for (i = 0; i < 0xF0; i++) {
- reg = xgifb_reg_get(vb->P3d4, i);
- pr_debug("o 3d4 %x\n", i);
- pr_debug("i 3d5 => %x\n", reg);
- }
-}
-#else
-static inline void dumpVGAReg(struct xgifb_video_info *xgifb_info)
-{
-}
-#endif
-
-/* --------------- Hardware Access Routines -------------------------- */
-
-static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned char modeno)
-{
- unsigned short ModeNo = modeno;
- unsigned short ModeIdIndex = 0, ClockIndex = 0;
- unsigned short RefreshRateTableIndex = 0;
-
- InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
-
- XGI_SearchModeID(ModeNo, &ModeIdIndex);
-
- RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
- ModeIdIndex, XGI_Pr);
-
- ClockIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-
- return XGI_VCLKData[ClockIndex].CLOCK * 1000;
-}
-
-static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned char modeno, u32 *left_margin,
- u32 *right_margin, u32 *upper_margin,
- u32 *lower_margin, u32 *hsync_len,
- u32 *vsync_len, u32 *sync, u32 *vmode)
-{
- unsigned short ModeNo = modeno;
- unsigned short ModeIdIndex, index = 0;
- unsigned short RefreshRateTableIndex = 0;
-
- unsigned short VRE, VBE, VRS, VDE;
- unsigned short HRE, HBE, HRS, HDE;
- unsigned char sr_data, cr_data, cr_data2;
- int B, C, D, F, temp, j;
-
- InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
- if (!XGI_SearchModeID(ModeNo, &ModeIdIndex))
- return 0;
- RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
- ModeIdIndex, XGI_Pr);
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- sr_data = XGI_CRT1Table[index].CR[5];
-
- HDE = XGI330_RefIndex[RefreshRateTableIndex].XRes >> 3;
-
- cr_data = XGI_CRT1Table[index].CR[3];
-
- /* Horizontal retrace (=sync) start */
- HRS = (cr_data & 0xff) | ((unsigned short)(sr_data & 0xC0) << 2);
- F = HRS - HDE - 3;
-
- sr_data = XGI_CRT1Table[index].CR[6];
-
- cr_data = XGI_CRT1Table[index].CR[2];
-
- cr_data2 = XGI_CRT1Table[index].CR[4];
-
- /* Horizontal blank end */
- HBE = (cr_data & 0x1f) | ((unsigned short)(cr_data2 & 0x80) >> 2)
- | ((unsigned short)(sr_data & 0x03) << 6);
-
- /* Horizontal retrace (=sync) end */
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
- temp = HBE - ((HDE - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
-
- temp = HRE - ((HDE + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
-
- D = B - F - C;
-
- *left_margin = D * 8;
- *right_margin = F * 8;
- *hsync_len = C * 8;
-
- sr_data = XGI_CRT1Table[index].CR[14];
-
- cr_data2 = XGI_CRT1Table[index].CR[9];
-
- VDE = XGI330_RefIndex[RefreshRateTableIndex].YRes;
-
- cr_data = XGI_CRT1Table[index].CR[10];
-
- /* Vertical retrace (=sync) start */
- VRS = (cr_data & 0xff) | ((unsigned short)(cr_data2 & 0x04) << 6)
- | ((unsigned short)(cr_data2 & 0x80) << 2)
- | ((unsigned short)(sr_data & 0x08) << 7);
- F = VRS + 1 - VDE;
-
- cr_data = XGI_CRT1Table[index].CR[13];
-
- /* Vertical blank end */
- VBE = (cr_data & 0xff) | ((unsigned short)(sr_data & 0x10) << 4);
- temp = VBE - ((VDE - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- cr_data = XGI_CRT1Table[index].CR[11];
-
- /* Vertical retrace (=sync) end */
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((VDE + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- *upper_margin = D;
- *lower_margin = F;
- *vsync_len = C;
-
- if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
- *sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- *sync |= FB_SYNC_VERT_HIGH_ACT;
-
- if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
- *sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- *sync |= FB_SYNC_HOR_HIGH_ACT;
-
- *vmode = FB_VMODE_NONINTERLACED;
- if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080) {
- *vmode = FB_VMODE_INTERLACED;
- } else {
- j = 0;
- while (XGI330_EModeIDTable[j].Ext_ModeID != 0xff) {
- if (XGI330_EModeIDTable[j].Ext_ModeID ==
- XGI330_RefIndex[RefreshRateTableIndex].ModeID) {
- if (XGI330_EModeIDTable[j].Ext_ModeFlag &
- DoubleScanMode) {
- *vmode = FB_VMODE_DOUBLE;
- }
- break;
- }
- j++;
- }
- }
-
- return 1;
-}
-
-void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
-{
- XGI_Pr->P3c4 = BaseAddr + 0x14;
- XGI_Pr->P3d4 = BaseAddr + 0x24;
- XGI_Pr->P3c0 = BaseAddr + 0x10;
- XGI_Pr->P3ce = BaseAddr + 0x1e;
- XGI_Pr->P3c2 = BaseAddr + 0x12;
- XGI_Pr->P3cc = BaseAddr + 0x1c;
- XGI_Pr->P3ca = BaseAddr + 0x1a;
- XGI_Pr->P3c6 = BaseAddr + 0x16;
- XGI_Pr->P3c7 = BaseAddr + 0x17;
- XGI_Pr->P3c8 = BaseAddr + 0x18;
- XGI_Pr->P3c9 = BaseAddr + 0x19;
- XGI_Pr->P3da = BaseAddr + 0x2A;
- XGI_Pr->Part0Port = BaseAddr + XGI_CRT2_PORT_00;
- /* Digital video interface registers (LCD) */
- XGI_Pr->Part1Port = BaseAddr + SIS_CRT2_PORT_04;
- /* 301 TV Encoder registers */
- XGI_Pr->Part2Port = BaseAddr + SIS_CRT2_PORT_10;
- /* 301 Macrovision registers */
- XGI_Pr->Part3Port = BaseAddr + SIS_CRT2_PORT_12;
- /* 301 VGA2 (and LCD) registers */
- XGI_Pr->Part4Port = BaseAddr + SIS_CRT2_PORT_14;
- /* 301 palette address port registers */
- XGI_Pr->Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
-}
-
-/* ------------------ Internal helper routines ----------------- */
-
-static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
-{
- int i = 0;
-
- while ((XGIbios_mode[i].mode_no != 0) &&
- (XGIbios_mode[i].xres <= xgifb_info->lvds_data.LVDSHDE)) {
- if ((XGIbios_mode[i].xres == xgifb_info->lvds_data.LVDSHDE) &&
- (XGIbios_mode[i].yres == xgifb_info->lvds_data.LVDSVDE) &&
- (XGIbios_mode[i].bpp == 8)) {
- return i;
- }
- i++;
- }
-
- return -1;
-}
-
-static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
- const char *name)
-{
- unsigned int xres;
- unsigned int yres;
- unsigned int bpp;
- int i;
-
- if (sscanf(name, "%ux%ux%u", &xres, &yres, &bpp) != 3)
- goto invalid_mode;
-
- if (bpp == 24)
- bpp = 32; /* That's for people who mix up color and fb depth. */
-
- for (i = 0; XGIbios_mode[i].mode_no != 0; i++)
- if (XGIbios_mode[i].xres == xres &&
- XGIbios_mode[i].yres == yres &&
- XGIbios_mode[i].bpp == bpp) {
- xgifb_info->mode_idx = i;
- return;
- }
-invalid_mode:
- pr_info("Invalid mode '%s'\n", name);
-}
-
-static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
- unsigned int vesamode)
-{
- int i = 0;
-
- if (vesamode == 0)
- goto invalid;
-
- vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
-
- while (XGIbios_mode[i].mode_no != 0) {
- if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
- (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
- xgifb_info->mode_idx = i;
- return;
- }
- i++;
- }
-
-invalid:
- pr_info("Invalid VESA mode 0x%x'\n", vesamode);
-}
-
-static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
-{
- u16 xres, yres;
- struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
- unsigned long required_mem;
-
- if (xgifb_info->chip == XG21) {
- if (xgifb_info->display2 == XGIFB_DISP_LCD) {
- xres = xgifb_info->lvds_data.LVDSHDE;
- yres = xgifb_info->lvds_data.LVDSVDE;
- if (XGIbios_mode[myindex].xres > xres)
- return -1;
- if (XGIbios_mode[myindex].yres > yres)
- return -1;
- if ((XGIbios_mode[myindex].xres < xres) &&
- (XGIbios_mode[myindex].yres < yres)) {
- if (XGIbios_mode[myindex].bpp > 8)
- return -1;
- }
- }
- goto check_memory;
- }
-
- /* FIXME: for now, all is valid on XG27 */
- if (xgifb_info->chip == XG27)
- goto check_memory;
-
- if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
- return -1;
-
- switch (xgifb_info->display2) {
- case XGIFB_DISP_LCD:
- switch (hw_info->ulCRT2LCDType) {
- case LCD_640x480:
- xres = 640;
- yres = 480;
- break;
- case LCD_800x600:
- xres = 800;
- yres = 600;
- break;
- case LCD_1024x600:
- xres = 1024;
- yres = 600;
- break;
- case LCD_1024x768:
- xres = 1024;
- yres = 768;
- break;
- case LCD_1152x768:
- xres = 1152;
- yres = 768;
- break;
- case LCD_1280x960:
- xres = 1280;
- yres = 960;
- break;
- case LCD_1280x768:
- xres = 1280;
- yres = 768;
- break;
- case LCD_1280x1024:
- xres = 1280;
- yres = 1024;
- break;
- case LCD_1400x1050:
- xres = 1400;
- yres = 1050;
- break;
- case LCD_1600x1200:
- xres = 1600;
- yres = 1200;
- break;
- default:
- xres = 0;
- yres = 0;
- break;
- }
- if (XGIbios_mode[myindex].xres > xres)
- return -1;
- if (XGIbios_mode[myindex].yres > yres)
- return -1;
- if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
- (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
- switch (XGIbios_mode[myindex].xres) {
- case 512:
- if (XGIbios_mode[myindex].yres != 512)
- return -1;
- if (hw_info->ulCRT2LCDType == LCD_1024x600)
- return -1;
- break;
- case 640:
- if ((XGIbios_mode[myindex].yres != 400) &&
- (XGIbios_mode[myindex].yres != 480))
- return -1;
- break;
- case 800:
- if (XGIbios_mode[myindex].yres != 600)
- return -1;
- break;
- case 1024:
- if ((XGIbios_mode[myindex].yres != 600) &&
- (XGIbios_mode[myindex].yres != 768))
- return -1;
- if ((XGIbios_mode[myindex].yres == 600) &&
- (hw_info->ulCRT2LCDType != LCD_1024x600))
- return -1;
- break;
- case 1152:
- if ((XGIbios_mode[myindex].yres) != 768)
- return -1;
- if (hw_info->ulCRT2LCDType != LCD_1152x768)
- return -1;
- break;
- case 1280:
- if ((XGIbios_mode[myindex].yres != 768) &&
- (XGIbios_mode[myindex].yres != 1024))
- return -1;
- if ((XGIbios_mode[myindex].yres == 768) &&
- (hw_info->ulCRT2LCDType != LCD_1280x768))
- return -1;
- break;
- case 1400:
- if (XGIbios_mode[myindex].yres != 1050)
- return -1;
- break;
- case 1600:
- if (XGIbios_mode[myindex].yres != 1200)
- return -1;
- break;
- default:
- return -1;
- }
- } else {
- switch (XGIbios_mode[myindex].xres) {
- case 512:
- if (XGIbios_mode[myindex].yres != 512)
- return -1;
- break;
- case 640:
- if ((XGIbios_mode[myindex].yres != 400) &&
- (XGIbios_mode[myindex].yres != 480))
- return -1;
- break;
- case 800:
- if (XGIbios_mode[myindex].yres != 600)
- return -1;
- break;
- case 1024:
- if (XGIbios_mode[myindex].yres != 768)
- return -1;
- break;
- case 1280:
- if ((XGIbios_mode[myindex].yres != 960) &&
- (XGIbios_mode[myindex].yres != 1024))
- return -1;
- if (XGIbios_mode[myindex].yres == 960) {
- if (hw_info->ulCRT2LCDType ==
- LCD_1400x1050)
- return -1;
- }
- break;
- case 1400:
- if (XGIbios_mode[myindex].yres != 1050)
- return -1;
- break;
- case 1600:
- if (XGIbios_mode[myindex].yres != 1200)
- return -1;
- break;
- default:
- return -1;
- }
- }
- break;
- case XGIFB_DISP_TV:
- switch (XGIbios_mode[myindex].xres) {
- case 512:
- case 640:
- case 800:
- break;
- case 720:
- if (xgifb_info->TV_type == TVMODE_NTSC) {
- if (XGIbios_mode[myindex].yres != 480)
- return -1;
- } else if (xgifb_info->TV_type == TVMODE_PAL) {
- if (XGIbios_mode[myindex].yres != 576)
- return -1;
- }
- /* LVDS/CHRONTEL does not support 720 */
- if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
- xgifb_info->hasVB == HASVB_CHRONTEL) {
- return -1;
- }
- break;
- case 1024:
- if (xgifb_info->TV_type == TVMODE_NTSC) {
- if (XGIbios_mode[myindex].bpp == 32)
- return -1;
- }
- break;
- default:
- return -1;
- }
- break;
- case XGIFB_DISP_CRT:
- if (XGIbios_mode[myindex].xres > 1280)
- return -1;
- break;
- case XGIFB_DISP_NONE:
- break;
- }
-
-check_memory:
- required_mem = XGIbios_mode[myindex].xres * XGIbios_mode[myindex].yres *
- XGIbios_mode[myindex].bpp / 8;
- if (required_mem > xgifb_info->video_size)
- return -1;
- return myindex;
-}
-
-static void XGIfb_search_crt2type(const char *name)
-{
- int i = 0;
-
- if (!name)
- return;
-
- while (XGI_crt2type[i].type_no != -1) {
- if (!strcmp(name, XGI_crt2type[i].name)) {
- XGIfb_crt2type = XGI_crt2type[i].type_no;
- XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
- break;
- }
- i++;
- }
- if (XGIfb_crt2type < 0)
- pr_info("Invalid CRT2 type: %s\n", name);
-}
-
-static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
- unsigned int rate)
-{
- u16 xres, yres;
- int i = 0;
-
- xres = XGIbios_mode[xgifb_info->mode_idx].xres;
- yres = XGIbios_mode[xgifb_info->mode_idx].yres;
-
- xgifb_info->rate_idx = 0;
-
- while (XGIfb_vrate[i].idx != 0 && XGIfb_vrate[i].xres <= xres) {
- /* Skip values with xres or yres less than specified */
- if ((XGIfb_vrate[i].yres != yres) ||
- (XGIfb_vrate[i].xres != xres)) {
- i++;
- continue;
- }
- if (XGIfb_vrate[i].refresh == rate) {
- xgifb_info->rate_idx = XGIfb_vrate[i].idx;
- break;
- } else if (XGIfb_vrate[i].refresh > rate) {
- if (XGIfb_vrate[i].refresh - rate <= 3) {
- pr_debug("Adjusting rate from %d up to %d\n",
- rate, XGIfb_vrate[i].refresh);
- xgifb_info->rate_idx = XGIfb_vrate[i].idx;
- xgifb_info->refresh_rate =
- XGIfb_vrate[i].refresh;
- } else if ((XGIfb_vrate[i].idx != 1) &&
- (rate - XGIfb_vrate[i - 1].refresh <= 2)) {
- pr_debug("Adjusting rate from %d down to %d\n",
- rate, XGIfb_vrate[i - 1].refresh);
- xgifb_info->rate_idx = XGIfb_vrate[i - 1].idx;
- xgifb_info->refresh_rate =
- XGIfb_vrate[i - 1].refresh;
- }
- break;
- } else if (rate - XGIfb_vrate[i].refresh <= 2) {
- pr_debug("Adjusting rate from %d down to %d\n",
- rate, XGIfb_vrate[i].refresh);
- xgifb_info->rate_idx = XGIfb_vrate[i].idx;
- break;
- }
- i++;
- }
-
- if (xgifb_info->rate_idx > 0)
- return xgifb_info->rate_idx;
- pr_info("Unsupported rate %d for %dx%d\n",
- rate, xres, yres);
- return 0;
-}
-
-static void XGIfb_search_tvstd(const char *name)
-{
- int i = 0;
-
- if (!name)
- return;
-
- while (XGI_tvtype[i].type_no != -1) {
- if (!strcmp(name, XGI_tvtype[i].name)) {
- XGIfb_tvmode = XGI_tvtype[i].type_no;
- break;
- }
- i++;
- }
-}
-
-/* ----------- FBDev related routines for all series ----------- */
-
-static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
- struct fb_var_screeninfo *var)
-{
- switch (var->bits_per_pixel) {
- case 8:
- var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- xgifb_info->video_cmap_len = 256;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- xgifb_info->video_cmap_len = 16;
- break;
- case 32:
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- xgifb_info->video_cmap_len = 16;
- break;
- }
-}
-
-/* --------------------- SetMode routines ------------------------- */
-
-static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
-{
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 cr30 = 0, cr31 = 0;
-
- cr31 = xgifb_reg_get(vb->P3d4, 0x31);
- cr31 &= ~0x60;
-
- switch (xgifb_info->display2) {
- case XGIFB_DISP_CRT:
- cr30 = SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= SIS_DRIVER_MODE;
- break;
- case XGIFB_DISP_LCD:
- cr30 = SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= SIS_DRIVER_MODE;
- break;
- case XGIFB_DISP_TV:
- if (xgifb_info->TV_type == TVMODE_HIVISION)
- cr30 = SIS_VB_OUTPUT_HIVISION
- | SIS_SIMULTANEOUS_VIEW_ENABLE;
- else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
- cr30 = SIS_VB_OUTPUT_SVIDEO
- | SIS_SIMULTANEOUS_VIEW_ENABLE;
- else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
- cr30 = SIS_VB_OUTPUT_COMPOSITE
- | SIS_SIMULTANEOUS_VIEW_ENABLE;
- else if (xgifb_info->TV_plug == TVPLUG_SCART)
- cr30 = SIS_VB_OUTPUT_SCART
- | SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= SIS_DRIVER_MODE;
-
- if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
- cr31 |= 0x01;
- else
- cr31 &= ~0x01;
- break;
- default: /* disable CRT2 */
- cr30 = 0x00;
- cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
- }
-
- xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR30, cr30);
- xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR31, cr31);
- xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR33,
- (xgifb_info->rate_idx & 0x0F));
-}
-
-static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
-{
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 reg;
- unsigned char doit = 1;
-
- if (xgifb_info->video_bpp == 8) {
- /*
- * We can't switch off CRT1 on LVDS/Chrontel
- * in 8bpp Modes
- */
- if ((xgifb_info->hasVB == HASVB_LVDS) ||
- (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
- doit = 0;
- }
- /*
- * We can't switch off CRT1 on 301B-DH
- * in 8bpp Modes if using LCD
- */
- if (xgifb_info->display2 == XGIFB_DISP_LCD)
- doit = 0;
- }
-
- /* We can't switch off CRT1 if bridge is in slave mode */
- if (xgifb_info->hasVB != HASVB_NONE) {
- reg = xgifb_reg_get(vb->Part1Port, 0x00);
-
- if ((reg & 0x50) == 0x10)
- doit = 0;
-
- } else {
- XGIfb_crt1off = 0;
- }
-
- reg = xgifb_reg_get(vb->P3d4, 0x17);
- if ((XGIfb_crt1off) && (doit))
- reg &= ~0x80;
- else
- reg |= 0x80;
- xgifb_reg_set(vb->P3d4, 0x17, reg);
-
- xgifb_reg_and(vb->P3c4, IND_SIS_RAMDAC_CONTROL, ~0x04);
-
- if (xgifb_info->display2 == XGIFB_DISP_TV &&
- xgifb_info->hasVB == HASVB_301) {
- reg = xgifb_reg_get(vb->Part4Port, 0x01);
-
- if (reg < 0xB0) { /* Set filter for XGI301 */
- int filter_tb;
-
- switch (xgifb_info->video_width) {
- case 320:
- filter_tb = (xgifb_info->TV_type ==
- TVMODE_NTSC) ? 4 : 12;
- break;
- case 640:
- filter_tb = (xgifb_info->TV_type ==
- TVMODE_NTSC) ? 5 : 13;
- break;
- case 720:
- filter_tb = (xgifb_info->TV_type ==
- TVMODE_NTSC) ? 6 : 14;
- break;
- case 800:
- filter_tb = (xgifb_info->TV_type ==
- TVMODE_NTSC) ? 7 : 15;
- break;
- default:
- filter_tb = 0;
- filter = -1;
- break;
- }
- xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01);
-
- if (xgifb_info->TV_type == TVMODE_NTSC) {
- xgifb_reg_and(vb->Part2Port, 0x3a, 0x1f);
-
- if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
- xgifb_reg_and(vb->Part2Port, 0x30, 0xdf);
-
- } else if (xgifb_info->TV_plug
- == TVPLUG_COMPOSITE) {
- xgifb_reg_or(vb->Part2Port, 0x30, 0x20);
-
- switch (xgifb_info->video_width) {
- case 640:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xEB);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0x04);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x25);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0x18);
- break;
- case 720:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xEE);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0x0C);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x22);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0x08);
- break;
- case 800:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xEB);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0x15);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x25);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0xF6);
- break;
- }
- }
-
- } else if (xgifb_info->TV_type == TVMODE_PAL) {
- xgifb_reg_and(vb->Part2Port, 0x3A, 0x1F);
-
- if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
- xgifb_reg_and(vb->Part2Port, 0x30, 0xDF);
-
- } else if (xgifb_info->TV_plug
- == TVPLUG_COMPOSITE) {
- xgifb_reg_or(vb->Part2Port, 0x30, 0x20);
-
- switch (xgifb_info->video_width) {
- case 640:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xF1);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0xF7);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x1F);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0x32);
- break;
- case 720:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xF3);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0x00);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x1D);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0x20);
- break;
- case 800:
- xgifb_reg_set(vb->Part2Port,
- 0x35,
- 0xFC);
- xgifb_reg_set(vb->Part2Port,
- 0x36,
- 0xFB);
- xgifb_reg_set(vb->Part2Port,
- 0x37,
- 0x14);
- xgifb_reg_set(vb->Part2Port,
- 0x38,
- 0x2A);
- break;
- }
- }
- }
-
- if ((filter >= 0) && (filter <= 7)) {
- const u8 *f = XGI_TV_filter[filter_tb].filter[filter];
-
- pr_debug("FilterTable[%d]-%d: %*ph\n",
- filter_tb, filter, 4, f);
- xgifb_reg_set(vb->Part2Port, 0x35, f[0]);
- xgifb_reg_set(vb->Part2Port, 0x36, f[1]);
- xgifb_reg_set(vb->Part2Port, 0x37, f[2]);
- xgifb_reg_set(vb->Part2Port, 0x38, f[3]);
- }
- }
- }
-}
-
-static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
- struct vb_device_info *vb = &xgifb_info->dev_info;
- struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
- unsigned int htotal = var->left_margin + var->xres + var->right_margin
- + var->hsync_len;
- unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
- + var->vsync_len;
-#if defined(__BIG_ENDIAN)
- u8 cr_data;
-#endif
- unsigned int drate = 0, hrate = 0;
- int found_mode = 0;
- int old_mode;
-
- info->var.xres_virtual = var->xres_virtual;
- info->var.yres_virtual = var->yres_virtual;
- info->var.bits_per_pixel = var->bits_per_pixel;
-
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
- vtotal <<= 1;
- else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
- vtotal <<= 2;
-
- if (!htotal || !vtotal) {
- pr_debug("Invalid 'var' information\n");
- return -EINVAL;
- }
- pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n",
- var->pixclock, htotal, vtotal);
-
- if (var->pixclock) {
- drate = 1000000000 / var->pixclock;
- hrate = (drate * 1000) / htotal;
- xgifb_info->refresh_rate = (unsigned int)(hrate * 2
- / vtotal);
- } else {
- xgifb_info->refresh_rate = 60;
- }
-
- pr_debug("Change mode to %dx%dx%d-%dHz\n",
- var->xres, var->yres, var->bits_per_pixel,
- xgifb_info->refresh_rate);
-
- old_mode = xgifb_info->mode_idx;
- xgifb_info->mode_idx = 0;
-
- while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
- (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
- if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
- (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
- (XGIbios_mode[xgifb_info->mode_idx].bpp
- == var->bits_per_pixel)) {
- found_mode = 1;
- break;
- }
- xgifb_info->mode_idx++;
- }
-
- if (found_mode)
- xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
- xgifb_info->mode_idx);
- else
- xgifb_info->mode_idx = -1;
-
- if (xgifb_info->mode_idx < 0) {
- pr_err("Mode %dx%dx%d not supported\n",
- var->xres, var->yres, var->bits_per_pixel);
- xgifb_info->mode_idx = old_mode;
- return -EINVAL;
- }
-
- if (XGIfb_search_refresh_rate(xgifb_info,
- xgifb_info->refresh_rate) == 0) {
- xgifb_info->rate_idx = 1;
- xgifb_info->refresh_rate = 60;
- }
-
- if (isactive) {
- XGIfb_pre_setmode(xgifb_info);
- if (XGISetModeNew(xgifb_info, hw_info,
- XGIbios_mode[xgifb_info->mode_idx].mode_no)
- == 0) {
- pr_err("Setting mode[0x%x] failed\n",
- XGIbios_mode[xgifb_info->mode_idx].mode_no);
- return -EINVAL;
- }
- info->fix.line_length = (info->var.xres_virtual
- * info->var.bits_per_pixel) >> 6;
-
- xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD);
-
- xgifb_reg_set(vb->P3d4, 0x13, (info->fix.line_length & 0x00ff));
- xgifb_reg_set(vb->P3c4, 0x0E,
- (info->fix.line_length & 0xff00) >> 8);
-
- XGIfb_post_setmode(xgifb_info);
-
- pr_debug("Set new mode: %dx%dx%d-%d\n",
- XGIbios_mode[xgifb_info->mode_idx].xres,
- XGIbios_mode[xgifb_info->mode_idx].yres,
- XGIbios_mode[xgifb_info->mode_idx].bpp,
- xgifb_info->refresh_rate);
-
- xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
- xgifb_info->video_vwidth = info->var.xres_virtual;
- xgifb_info->video_width =
- XGIbios_mode[xgifb_info->mode_idx].xres;
- xgifb_info->video_vheight = info->var.yres_virtual;
- xgifb_info->video_height =
- XGIbios_mode[xgifb_info->mode_idx].yres;
- xgifb_info->org_x = 0;
- xgifb_info->org_y = 0;
- xgifb_info->video_linelength = info->var.xres_virtual
- * (xgifb_info->video_bpp >> 3);
- switch (xgifb_info->video_bpp) {
- case 8:
- xgifb_info->DstColor = 0x0000;
- xgifb_info->XGI310_AccelDepth = 0x00000000;
- xgifb_info->video_cmap_len = 256;
-#if defined(__BIG_ENDIAN)
- cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
- xgifb_reg_set(vb->P3d4, 0x4D, (cr_data & 0xE0));
-#endif
- break;
- case 16:
- xgifb_info->DstColor = 0x8000;
- xgifb_info->XGI310_AccelDepth = 0x00010000;
-#if defined(__BIG_ENDIAN)
- cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
- xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x0B));
-#endif
- xgifb_info->video_cmap_len = 16;
- break;
- case 32:
- xgifb_info->DstColor = 0xC000;
- xgifb_info->XGI310_AccelDepth = 0x00020000;
- xgifb_info->video_cmap_len = 16;
-#if defined(__BIG_ENDIAN)
- cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
- xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x15));
-#endif
- break;
- default:
- xgifb_info->video_cmap_len = 16;
- pr_err("Unsupported depth %d\n",
- xgifb_info->video_bpp);
- break;
- }
- }
- XGIfb_bpp_to_var(xgifb_info, var); /* update ARGB info */
-
- dumpVGAReg(xgifb_info);
- return 0;
-}
-
-static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
- struct vb_device_info *vb = &xgifb_info->dev_info;
- unsigned int base;
-
- base = var->yoffset * info->var.xres_virtual + var->xoffset;
-
- /* calculate base bpp dep. */
- switch (info->var.bits_per_pixel) {
- case 16:
- base >>= 1;
- break;
- case 32:
- break;
- case 8:
- default:
- base >>= 2;
- break;
- }
-
- xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD);
-
- xgifb_reg_set(vb->P3d4, 0x0D, base & 0xFF);
- xgifb_reg_set(vb->P3d4, 0x0C, (base >> 8) & 0xFF);
- xgifb_reg_set(vb->P3c4, 0x0D, (base >> 16) & 0xFF);
- xgifb_reg_set(vb->P3c4, 0x37, (base >> 24) & 0x03);
- xgifb_reg_and_or(vb->P3c4, 0x37, 0xDF, (base >> 21) & 0x04);
-
- if (xgifb_info->display2 != XGIFB_DISP_NONE) {
- xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01);
- xgifb_reg_set(vb->Part1Port, 0x06, (base & 0xFF));
- xgifb_reg_set(vb->Part1Port, 0x05, ((base >> 8) & 0xFF));
- xgifb_reg_set(vb->Part1Port, 0x04, ((base >> 16) & 0xFF));
- xgifb_reg_and_or(vb->Part1Port, 0x02, 0x7F,
- ((base >> 24) & 0x01) << 7);
- }
- return 0;
-}
-
-static int XGIfb_open(struct fb_info *info, int user)
-{
- return 0;
-}
-
-static int XGIfb_release(struct fb_info *info, int user)
-{
- return 0;
-}
-
-/* similar to sisfb_get_cmap_len */
-static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
-{
- return (var->bits_per_pixel == 8) ? 256 : 16;
-}
-
-static int XGIfb_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
- struct vb_device_info *vb = &xgifb_info->dev_info;
-
- if (regno >= XGIfb_get_cmap_len(&info->var))
- return 1;
-
- switch (info->var.bits_per_pixel) {
- case 8:
- outb(regno, vb->P3c8);
- outb((red >> 10), vb->P3c9);
- outb((green >> 10), vb->P3c9);
- outb((blue >> 10), vb->P3c9);
- if (xgifb_info->display2 != XGIFB_DISP_NONE) {
- outb(regno, vb->Part5Port);
- outb((red >> 8), (vb->Part5Port + 1));
- outb((green >> 8), (vb->Part5Port + 1));
- outb((blue >> 8), (vb->Part5Port + 1));
- }
- break;
- case 16:
- ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xf800))
- | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
- >> 11);
- break;
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] = (red << 16) | (green
- << 8) | (blue);
- break;
- }
- return 0;
-}
-
-/* ----------- FBDev related routines for all series ---------- */
-
-static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
-
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
- strncpy(fix->id, "XGI", sizeof(fix->id) - 1);
-
- /* if register_framebuffer has been called, we must lock */
- if (atomic_read(&info->count))
- mutex_lock(&info->mm_lock);
-
- fix->smem_start = xgifb_info->video_base;
- fix->smem_len = xgifb_info->video_size;
-
- /* if register_framebuffer has been called, we can unlock */
- if (atomic_read(&info->count))
- mutex_unlock(&info->mm_lock);
-
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- if (xgifb_info->video_bpp == 8)
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- else
- fix->visual = FB_VISUAL_DIRECTCOLOR;
- fix->xpanstep = 0;
- if (XGIfb_ypan)
- fix->ypanstep = 1;
- fix->ywrapstep = 0;
- fix->line_length = xgifb_info->video_linelength;
- fix->mmio_start = xgifb_info->mmio_base;
- fix->mmio_len = xgifb_info->mmio_size;
- fix->accel = FB_ACCEL_SIS_XABRE;
-
- return 0;
-}
-
-static int XGIfb_set_par(struct fb_info *info)
-{
- int err;
-
- err = XGIfb_do_set_var(&info->var, 1, info);
- if (err)
- return err;
- XGIfb_get_fix(&info->fix, -1, info);
- return 0;
-}
-
-static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
- unsigned int htotal = var->left_margin + var->xres + var->right_margin
- + var->hsync_len;
- unsigned int vtotal = 0;
- unsigned int drate = 0, hrate = 0;
- int found_mode = 0;
- int search_idx;
-
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
- vtotal = var->upper_margin + var->yres + var->lower_margin
- + var->vsync_len;
- vtotal <<= 1;
- } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vtotal = var->upper_margin + var->yres + var->lower_margin
- + var->vsync_len;
- vtotal <<= 2;
- } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vtotal = var->upper_margin + (var->yres / 2)
- + var->lower_margin + var->vsync_len;
- } else
- vtotal = var->upper_margin + var->yres + var->lower_margin
- + var->vsync_len;
-
- if (!(htotal) || !(vtotal)) {
- pr_debug("No valid timing data\n");
- return -EINVAL;
- }
-
- if (var->pixclock && htotal && vtotal) {
- drate = 1000000000 / var->pixclock;
- hrate = (drate * 1000) / htotal;
- xgifb_info->refresh_rate =
- (unsigned int)(hrate * 2 / vtotal);
- pr_debug(
- "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
- "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
- __func__, var->pixclock, htotal, vtotal,
- __func__, drate, hrate, xgifb_info->refresh_rate);
- } else {
- xgifb_info->refresh_rate = 60;
- }
-
- search_idx = 0;
- while ((XGIbios_mode[search_idx].mode_no != 0) &&
- (XGIbios_mode[search_idx].xres <= var->xres)) {
- if ((XGIbios_mode[search_idx].xres == var->xres) &&
- (XGIbios_mode[search_idx].yres == var->yres) &&
- (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
- found_mode = 1;
- break;
- }
- }
- search_idx++;
- }
-
- if (!found_mode) {
- pr_err("%dx%dx%d is no valid mode\n",
- var->xres, var->yres, var->bits_per_pixel);
- search_idx = 0;
- while (XGIbios_mode[search_idx].mode_no != 0) {
- if ((var->xres <= XGIbios_mode[search_idx].xres) &&
- (var->yres <= XGIbios_mode[search_idx].yres) &&
- (var->bits_per_pixel ==
- XGIbios_mode[search_idx].bpp)) {
- if (XGIfb_validate_mode(xgifb_info,
- search_idx) > 0) {
- found_mode = 1;
- break;
- }
- }
- search_idx++;
- }
- if (found_mode) {
- var->xres = XGIbios_mode[search_idx].xres;
- var->yres = XGIbios_mode[search_idx].yres;
- pr_debug("Adapted to mode %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel);
-
- } else {
- pr_err("Failed to find similar mode to %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
- }
-
- /* Adapt RGB settings */
- XGIfb_bpp_to_var(xgifb_info, var);
-
- if (!XGIfb_ypan) {
- if (var->xres != var->xres_virtual)
- var->xres_virtual = var->xres;
- if (var->yres != var->yres_virtual)
- var->yres_virtual = var->yres;
- }
-
- /* Truncate offsets to maximum if too high */
- if (var->xoffset > var->xres_virtual - var->xres)
- var->xoffset = var->xres_virtual - var->xres - 1;
-
- if (var->yoffset > var->yres_virtual - var->yres)
- var->yoffset = var->yres_virtual - var->yres - 1;
-
- /* Set everything else to 0 */
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
-
- return 0;
-}
-
-static int XGIfb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- int err;
-
- if (var->xoffset > (info->var.xres_virtual - info->var.xres))
- return -EINVAL;
- if (var->yoffset > (info->var.yres_virtual - info->var.yres))
- return -EINVAL;
-
- if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset >= info->var.yres_virtual || var->xoffset)
- return -EINVAL;
- } else if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual) {
- return -EINVAL;
- }
- err = XGIfb_pan_var(var, info);
- if (err < 0)
- return err;
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
-
- return 0;
-}
-
-static int XGIfb_blank(int blank, struct fb_info *info)
-{
- struct xgifb_video_info *xgifb_info = info->par;
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 reg;
-
- reg = xgifb_reg_get(vb->P3d4, 0x17);
-
- if (blank > 0)
- reg &= 0x7f;
- else
- reg |= 0x80;
-
- xgifb_reg_set(vb->P3d4, 0x17, reg);
- xgifb_reg_set(vb->P3c4, 0x00, 0x01); /* Synchronous Reset */
- xgifb_reg_set(vb->P3c4, 0x00, 0x03); /* End Reset */
- return 0;
-}
-
-static struct fb_ops XGIfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = XGIfb_open,
- .fb_release = XGIfb_release,
- .fb_check_var = XGIfb_check_var,
- .fb_set_par = XGIfb_set_par,
- .fb_setcolreg = XGIfb_setcolreg,
- .fb_pan_display = XGIfb_pan_display,
- .fb_blank = XGIfb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
-
-/* ---------------- Chip generation dependent routines ---------------- */
-
-/* for XGI 315/550/650/740/330 */
-
-static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
-{
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 ChannelNum, tmp;
- u8 reg = 0;
-
- /* xorg driver sets 32MB * 1 channel */
- if (xgifb_info->chip == XG27)
- xgifb_reg_set(vb->P3c4, IND_SIS_DRAM_SIZE, 0x51);
-
- reg = xgifb_reg_get(vb->P3c4, IND_SIS_DRAM_SIZE);
- if (!reg)
- return -1;
-
- switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
- case XGI_DRAM_SIZE_1MB:
- xgifb_info->video_size = 0x100000;
- break;
- case XGI_DRAM_SIZE_2MB:
- xgifb_info->video_size = 0x200000;
- break;
- case XGI_DRAM_SIZE_4MB:
- xgifb_info->video_size = 0x400000;
- break;
- case XGI_DRAM_SIZE_8MB:
- xgifb_info->video_size = 0x800000;
- break;
- case XGI_DRAM_SIZE_16MB:
- xgifb_info->video_size = 0x1000000;
- break;
- case XGI_DRAM_SIZE_32MB:
- xgifb_info->video_size = 0x2000000;
- break;
- case XGI_DRAM_SIZE_64MB:
- xgifb_info->video_size = 0x4000000;
- break;
- case XGI_DRAM_SIZE_128MB:
- xgifb_info->video_size = 0x8000000;
- break;
- case XGI_DRAM_SIZE_256MB:
- xgifb_info->video_size = 0x10000000;
- break;
- default:
- return -1;
- }
-
- tmp = (reg & 0x0c) >> 2;
- switch (xgifb_info->chip) {
- case XG20:
- case XG21:
- case XG27:
- ChannelNum = 1;
- break;
-
- case XG42:
- if (reg & 0x04)
- ChannelNum = 2;
- else
- ChannelNum = 1;
- break;
-
- case XG40:
- default:
- if (tmp == 2)
- ChannelNum = 2;
- else if (tmp == 3)
- ChannelNum = 3;
- else
- ChannelNum = 1;
- break;
- }
-
- xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
-
- pr_info("SR14=%x DramSzie %x ChannelNum %x\n",
- reg, xgifb_info->video_size, ChannelNum);
- return 0;
-}
-
-static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
-{
- struct vb_device_info *vb = &xgifb_info->dev_info;
- u8 cr32, temp = 0;
-
- xgifb_info->TV_plug = 0;
- xgifb_info->TV_type = 0;
-
- cr32 = xgifb_reg_get(vb->P3d4, IND_XGI_SCRATCH_REG_CR32);
-
- if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) {
- XGIfb_crt1off = 0;
- } else {
- if (cr32 & 0x5F)
- XGIfb_crt1off = 1;
- else
- XGIfb_crt1off = 0;
- }
-
- if (!xgifb_info->display2_force) {
- if (cr32 & SIS_VB_TV)
- xgifb_info->display2 = XGIFB_DISP_TV;
- else if (cr32 & SIS_VB_LCD)
- xgifb_info->display2 = XGIFB_DISP_LCD;
- else if (cr32 & SIS_VB_CRT2)
- xgifb_info->display2 = XGIFB_DISP_CRT;
- else
- xgifb_info->display2 = XGIFB_DISP_NONE;
- }
-
- if (XGIfb_tvplug != -1) {
- /* Override with option */
- xgifb_info->TV_plug = XGIfb_tvplug;
- } else if (cr32 & SIS_VB_HIVISION) {
- xgifb_info->TV_type = TVMODE_HIVISION;
- xgifb_info->TV_plug = TVPLUG_SVIDEO;
- } else if (cr32 & SIS_VB_SVIDEO) {
- xgifb_info->TV_plug = TVPLUG_SVIDEO;
- } else if (cr32 & SIS_VB_COMPOSITE) {
- xgifb_info->TV_plug = TVPLUG_COMPOSITE;
- } else if (cr32 & SIS_VB_SCART) {
- xgifb_info->TV_plug = TVPLUG_SCART;
- }
-
- if (xgifb_info->TV_type == 0) {
- temp = xgifb_reg_get(vb->P3d4, 0x38);
- if (temp & 0x10)
- xgifb_info->TV_type = TVMODE_PAL;
- else
- xgifb_info->TV_type = TVMODE_NTSC;
- }
-
- /* Copy forceCRT1 option to CRT1off if option is given */
- if (XGIfb_forcecrt1 != -1) {
- if (XGIfb_forcecrt1)
- XGIfb_crt1off = 0;
- else
- XGIfb_crt1off = 1;
- }
-}
-
-static bool XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
-{
- u8 vb_chipid;
-
- vb_chipid = xgifb_reg_get(xgifb_info->dev_info.Part4Port, 0x00);
- switch (vb_chipid) {
- case 0x01:
- xgifb_info->hasVB = HASVB_301;
- break;
- case 0x02:
- xgifb_info->hasVB = HASVB_302;
- break;
- default:
- xgifb_info->hasVB = HASVB_NONE;
- return false;
- }
- return true;
-}
-
-static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
-{
- u8 reg;
-
- if (!XGIfb_has_VB(xgifb_info)) {
- reg = xgifb_reg_get(xgifb_info->dev_info.P3d4,
- IND_XGI_SCRATCH_REG_CR37);
- switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
- case SIS_EXTERNAL_CHIP_LVDS:
- xgifb_info->hasVB = HASVB_LVDS;
- break;
- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
- xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
- break;
- default:
- break;
- }
- }
-}
-
-static int __init xgifb_optval(char *fullopt, int validx)
-{
- unsigned long lres;
-
- if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
- pr_err("Invalid value for option: %s\n", fullopt);
- return 0;
- }
- return lres;
-}
-
-static int __init XGIfb_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- pr_info("Options: %s\n", options);
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
-
- if (!strncmp(this_opt, "mode:", 5)) {
- mode = this_opt + 5;
- } else if (!strncmp(this_opt, "vesa:", 5)) {
- vesa = xgifb_optval(this_opt, 5);
- } else if (!strncmp(this_opt, "vrate:", 6)) {
- refresh_rate = xgifb_optval(this_opt, 6);
- } else if (!strncmp(this_opt, "rate:", 5)) {
- refresh_rate = xgifb_optval(this_opt, 5);
- } else if (!strncmp(this_opt, "crt1off", 7)) {
- XGIfb_crt1off = 1;
- } else if (!strncmp(this_opt, "filter:", 7)) {
- filter = xgifb_optval(this_opt, 7);
- } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
- XGIfb_search_crt2type(this_opt + 14);
- } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
- XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
- } else if (!strncmp(this_opt, "tvmode:", 7)) {
- XGIfb_search_tvstd(this_opt + 7);
- } else if (!strncmp(this_opt, "tvstandard:", 11)) {
- XGIfb_search_tvstd(this_opt + 7);
- } else if (!strncmp(this_opt, "dstn", 4)) {
- enable_dstn = 1;
- /* DSTN overrules forcecrt2type */
- XGIfb_crt2type = XGIFB_DISP_LCD;
- } else if (!strncmp(this_opt, "noypan", 6)) {
- XGIfb_ypan = 0;
- } else {
- mode = this_opt;
- }
- }
- return 0;
-}
-
-static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- u8 reg, reg1;
- u8 CR48, CR38;
- int ret;
- struct fb_info *fb_info;
- struct xgifb_video_info *xgifb_info;
- struct vb_device_info *vb;
- struct xgi_hw_device_info *hw_info;
- unsigned long video_size_max;
-
- fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
- if (!fb_info)
- return -ENOMEM;
-
- xgifb_info = fb_info->par;
- vb = &xgifb_info->dev_info;
- hw_info = &xgifb_info->hw_info;
- xgifb_info->fb_info = fb_info;
- xgifb_info->chip_id = pdev->device;
- pci_read_config_byte(pdev,
- PCI_REVISION_ID,
- &xgifb_info->revision_id);
- hw_info->jChipRevision = xgifb_info->revision_id;
-
- xgifb_info->pcibus = pdev->bus->number;
- xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
- xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
- xgifb_info->subsysvendor = pdev->subsystem_vendor;
- xgifb_info->subsysdevice = pdev->subsystem_device;
-
- video_size_max = pci_resource_len(pdev, 0);
- xgifb_info->video_base = pci_resource_start(pdev, 0);
- xgifb_info->mmio_base = pci_resource_start(pdev, 1);
- xgifb_info->mmio_size = pci_resource_len(pdev, 1);
- xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
- dev_info(&pdev->dev, "Relocate IO address: %llx [%08lx]\n",
- (u64)pci_resource_start(pdev, 2),
- xgifb_info->vga_base);
-
- if (pci_enable_device(pdev)) {
- ret = -EIO;
- goto error;
- }
-
- if (XGIfb_crt2type != -1) {
- xgifb_info->display2 = XGIfb_crt2type;
- xgifb_info->display2_force = true;
- }
-
- XGIRegInit(vb, xgifb_info->vga_base);
-
- xgifb_reg_set(vb->P3c4,
- IND_SIS_PASSWORD, SIS_PASSWORD);
- reg1 = xgifb_reg_get(vb->P3c4, IND_SIS_PASSWORD);
-
- if (reg1 != 0xa1) { /* I/O error */
- dev_err(&pdev->dev, "I/O error\n");
- ret = -EIO;
- goto error_disable;
- }
-
- switch (xgifb_info->chip_id) {
- case PCI_DEVICE_ID_XGI_20:
- xgifb_reg_or(vb->P3d4,
- Index_CR_GPIO_Reg3, GPIOG_EN);
- CR48 = xgifb_reg_get(vb->P3d4,
- Index_CR_GPIO_Reg1);
- if (CR48 & GPIOG_READ)
- xgifb_info->chip = XG21;
- else
- xgifb_info->chip = XG20;
- break;
- case PCI_DEVICE_ID_XGI_40:
- xgifb_info->chip = XG40;
- break;
- case PCI_DEVICE_ID_XGI_42:
- xgifb_info->chip = XG42;
- break;
- case PCI_DEVICE_ID_XGI_27:
- xgifb_info->chip = XG27;
- break;
- default:
- ret = -ENODEV;
- goto error_disable;
- }
-
- dev_info(&pdev->dev, "chipid = %x\n", xgifb_info->chip);
- hw_info->jChipType = xgifb_info->chip;
-
- if (XGIfb_get_dram_size(xgifb_info)) {
- xgifb_info->video_size = min_t(unsigned long, video_size_max,
- SZ_16M);
- } else if (xgifb_info->video_size > video_size_max) {
- xgifb_info->video_size = video_size_max;
- }
-
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- xgifb_reg_or(vb->P3c4,
- IND_SIS_PCI_ADDRESS_SET,
- (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- xgifb_reg_or(vb->P3c4,
- IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
-
- hw_info->ulVideoMemorySize = xgifb_info->video_size;
-
- if (!request_mem_region(xgifb_info->video_base,
- xgifb_info->video_size,
- "XGIfb FB")) {
- dev_err(&pdev->dev, "Unable request memory size %x\n",
- xgifb_info->video_size);
- dev_err(&pdev->dev,
- "Fatal error: Unable to reserve frame buffer memory. Is there another framebuffer driver active?\n");
- ret = -ENODEV;
- goto error_disable;
- }
-
- if (!request_mem_region(xgifb_info->mmio_base,
- xgifb_info->mmio_size,
- "XGIfb MMIO")) {
- dev_err(&pdev->dev,
- "Fatal error: Unable to reserve MMIO region\n");
- ret = -ENODEV;
- goto error_0;
- }
-
- xgifb_info->video_vbase =
- ioremap_wc(xgifb_info->video_base, xgifb_info->video_size);
- hw_info->pjVideoMemoryAddress =
- ioremap_wc(xgifb_info->video_base, xgifb_info->video_size);
- xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
- xgifb_info->mmio_size);
-
- dev_info(&pdev->dev,
- "Framebuffer at 0x%llx, mapped to 0x%p, size %dk\n",
- (u64)xgifb_info->video_base,
- xgifb_info->video_vbase,
- xgifb_info->video_size / 1024);
-
- dev_info(&pdev->dev,
- "MMIO at 0x%llx, mapped to 0x%p, size %ldk\n",
- (u64)xgifb_info->mmio_base, xgifb_info->mmio_vbase,
- xgifb_info->mmio_size / 1024);
-
- pci_set_drvdata(pdev, xgifb_info);
- if (!XGIInitNew(pdev))
- dev_err(&pdev->dev, "XGIInitNew() failed!\n");
-
- xgifb_info->mtrr = -1;
-
- xgifb_info->hasVB = HASVB_NONE;
- if ((xgifb_info->chip == XG20) ||
- (xgifb_info->chip == XG27)) {
- xgifb_info->hasVB = HASVB_NONE;
- } else if (xgifb_info->chip == XG21) {
- CR38 = xgifb_reg_get(vb->P3d4, 0x38);
- if ((CR38 & 0xE0) == 0xC0)
- xgifb_info->display2 = XGIFB_DISP_LCD;
- else if ((CR38 & 0xE0) == 0x60)
- xgifb_info->hasVB = HASVB_CHRONTEL;
- else
- xgifb_info->hasVB = HASVB_NONE;
- } else {
- XGIfb_get_VB_type(xgifb_info);
- }
-
- hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
-
- hw_info->ulExternalChip = 0;
-
- switch (xgifb_info->hasVB) {
- case HASVB_301:
- reg = xgifb_reg_get(vb->Part4Port, 0x01);
- if (reg >= 0xE0) {
- hw_info->ujVBChipID = VB_CHIP_302LV;
- dev_info(&pdev->dev,
- "XGI302LV bridge detected (revision 0x%02x)\n",
- reg);
- } else if (reg >= 0xD0) {
- hw_info->ujVBChipID = VB_CHIP_301LV;
- dev_info(&pdev->dev,
- "XGI301LV bridge detected (revision 0x%02x)\n",
- reg);
- } else {
- hw_info->ujVBChipID = VB_CHIP_301;
- dev_info(&pdev->dev, "XGI301 bridge detected\n");
- }
- break;
- case HASVB_302:
- reg = xgifb_reg_get(vb->Part4Port, 0x01);
- if (reg >= 0xE0) {
- hw_info->ujVBChipID = VB_CHIP_302LV;
- dev_info(&pdev->dev,
- "XGI302LV bridge detected (revision 0x%02x)\n",
- reg);
- } else if (reg >= 0xD0) {
- hw_info->ujVBChipID = VB_CHIP_301LV;
- dev_info(&pdev->dev,
- "XGI302LV bridge detected (revision 0x%02x)\n",
- reg);
- } else if (reg >= 0xB0) {
- reg1 = xgifb_reg_get(vb->Part4Port,
- 0x23);
-
- hw_info->ujVBChipID = VB_CHIP_302B;
-
- } else {
- hw_info->ujVBChipID = VB_CHIP_302;
- dev_info(&pdev->dev, "XGI302 bridge detected\n");
- }
- break;
- case HASVB_LVDS:
- hw_info->ulExternalChip = 0x1;
- dev_info(&pdev->dev, "LVDS transmitter detected\n");
- break;
- case HASVB_TRUMPION:
- hw_info->ulExternalChip = 0x2;
- dev_info(&pdev->dev, "Trumpion Zurac LVDS scaler detected\n");
- break;
- case HASVB_CHRONTEL:
- hw_info->ulExternalChip = 0x4;
- dev_info(&pdev->dev, "Chrontel TV encoder detected\n");
- break;
- case HASVB_LVDS_CHRONTEL:
- hw_info->ulExternalChip = 0x5;
- dev_info(&pdev->dev,
- "LVDS transmitter and Chrontel TV encoder detected\n");
- break;
- default:
- dev_info(&pdev->dev, "No or unknown bridge type detected\n");
- break;
- }
-
- if (xgifb_info->hasVB != HASVB_NONE)
- XGIfb_detect_VB(xgifb_info);
- else if (xgifb_info->chip != XG21)
- xgifb_info->display2 = XGIFB_DISP_NONE;
-
- if (xgifb_info->display2 == XGIFB_DISP_LCD) {
- if (!enable_dstn) {
- reg = xgifb_reg_get(vb->P3d4,
- IND_XGI_LCD_PANEL);
- reg &= 0x0f;
- hw_info->ulCRT2LCDType = XGI310paneltype[reg];
- }
- }
-
- xgifb_info->mode_idx = -1;
-
- if (mode)
- XGIfb_search_mode(xgifb_info, mode);
- else if (vesa != -1)
- XGIfb_search_vesamode(xgifb_info, vesa);
-
- if (xgifb_info->mode_idx >= 0)
- xgifb_info->mode_idx =
- XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
-
- if (xgifb_info->mode_idx < 0) {
- if (xgifb_info->display2 == XGIFB_DISP_LCD &&
- xgifb_info->chip == XG21)
- xgifb_info->mode_idx =
- XGIfb_GetXG21DefaultLVDSModeIdx(xgifb_info);
- else
- xgifb_info->mode_idx = DEFAULT_MODE;
- }
-
- if (xgifb_info->mode_idx < 0) {
- dev_err(&pdev->dev, "No supported video mode found\n");
- ret = -EINVAL;
- goto error_1;
- }
-
- /* set default refresh rate */
- xgifb_info->refresh_rate = refresh_rate;
- if (xgifb_info->refresh_rate == 0)
- xgifb_info->refresh_rate = 60;
- if (XGIfb_search_refresh_rate(xgifb_info, xgifb_info->refresh_rate) == 0) {
- xgifb_info->rate_idx = 1;
- xgifb_info->refresh_rate = 60;
- }
-
- xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
- xgifb_info->video_vwidth =
- xgifb_info->video_width =
- XGIbios_mode[xgifb_info->mode_idx].xres;
- xgifb_info->video_vheight =
- xgifb_info->video_height =
- XGIbios_mode[xgifb_info->mode_idx].yres;
- xgifb_info->org_x = 0;
- xgifb_info->org_y = 0;
- xgifb_info->video_linelength =
- xgifb_info->video_width *
- (xgifb_info->video_bpp >> 3);
- switch (xgifb_info->video_bpp) {
- case 8:
- xgifb_info->DstColor = 0x0000;
- xgifb_info->XGI310_AccelDepth = 0x00000000;
- xgifb_info->video_cmap_len = 256;
- break;
- case 16:
- xgifb_info->DstColor = 0x8000;
- xgifb_info->XGI310_AccelDepth = 0x00010000;
- xgifb_info->video_cmap_len = 16;
- break;
- case 32:
- xgifb_info->DstColor = 0xC000;
- xgifb_info->XGI310_AccelDepth = 0x00020000;
- xgifb_info->video_cmap_len = 16;
- break;
- default:
- xgifb_info->video_cmap_len = 16;
- pr_info("Unsupported depth %d\n",
- xgifb_info->video_bpp);
- break;
- }
-
- pr_info("Default mode is %dx%dx%d (%dHz)\n",
- xgifb_info->video_width, xgifb_info->video_height,
- xgifb_info->video_bpp, xgifb_info->refresh_rate);
-
- fb_info->var.red.length = 8;
- fb_info->var.green.length = 8;
- fb_info->var.blue.length = 8;
- fb_info->var.activate = FB_ACTIVATE_NOW;
- fb_info->var.height = -1;
- fb_info->var.width = -1;
- fb_info->var.vmode = FB_VMODE_NONINTERLACED;
- fb_info->var.xres = xgifb_info->video_width;
- fb_info->var.xres_virtual = xgifb_info->video_width;
- fb_info->var.yres = xgifb_info->video_height;
- fb_info->var.yres_virtual = xgifb_info->video_height;
- fb_info->var.bits_per_pixel = xgifb_info->video_bpp;
-
- XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
-
- fb_info->var.pixclock = (u32)(1000000000 / XGIfb_mode_rate_to_dclock
- (vb, hw_info,
- XGIbios_mode[xgifb_info->mode_idx].mode_no));
-
- if (XGIfb_mode_rate_to_ddata(vb, hw_info,
- XGIbios_mode[xgifb_info->mode_idx].mode_no,
- &fb_info->var.left_margin,
- &fb_info->var.right_margin,
- &fb_info->var.upper_margin,
- &fb_info->var.lower_margin,
- &fb_info->var.hsync_len,
- &fb_info->var.vsync_len,
- &fb_info->var.sync,
- &fb_info->var.vmode)) {
- if ((fb_info->var.vmode & FB_VMODE_MASK) ==
- FB_VMODE_INTERLACED) {
- fb_info->var.yres <<= 1;
- fb_info->var.yres_virtual <<= 1;
- } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
- FB_VMODE_DOUBLE) {
- fb_info->var.pixclock >>= 1;
- fb_info->var.yres >>= 1;
- fb_info->var.yres_virtual >>= 1;
- }
- }
-
- fb_info->flags = FBINFO_FLAG_DEFAULT;
- fb_info->screen_base = xgifb_info->video_vbase;
- fb_info->fbops = &XGIfb_ops;
- XGIfb_get_fix(&fb_info->fix, -1, fb_info);
- fb_info->pseudo_palette = xgifb_info->pseudo_palette;
-
- fb_alloc_cmap(&fb_info->cmap, 256, 0);
-
- xgifb_info->mtrr = arch_phys_wc_add(xgifb_info->video_base,
- xgifb_info->video_size);
-
- if (register_framebuffer(fb_info) < 0) {
- ret = -EINVAL;
- goto error_mtrr;
- }
-
- dumpVGAReg(xgifb_info);
-
- return 0;
-
-error_mtrr:
- arch_phys_wc_del(xgifb_info->mtrr);
-error_1:
- iounmap(xgifb_info->mmio_vbase);
- iounmap(xgifb_info->video_vbase);
- release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
-error_0:
- release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
-error_disable:
- pci_disable_device(pdev);
-error:
- framebuffer_release(fb_info);
- return ret;
-}
-
-/* -------------------- PCI DEVICE HANDLING -------------------- */
-
-static void xgifb_remove(struct pci_dev *pdev)
-{
- struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
- struct fb_info *fb_info = xgifb_info->fb_info;
-
- unregister_framebuffer(fb_info);
- arch_phys_wc_del(xgifb_info->mtrr);
- iounmap(xgifb_info->mmio_vbase);
- iounmap(xgifb_info->video_vbase);
- release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
- release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
- pci_disable_device(pdev);
- framebuffer_release(fb_info);
-}
-
-static struct pci_driver xgifb_driver = {
- .name = "xgifb",
- .id_table = xgifb_pci_table,
- .probe = xgifb_probe,
- .remove = xgifb_remove
-};
-
-/* -------------------- MODULE -------------------- */
-
-module_param(mode, charp, 0000);
-MODULE_PARM_DESC(mode,
- "Selects the desired default display mode in the format XxYxDepth (eg. 1024x768x16).");
-
-module_param(forcecrt2type, charp, 0000);
-MODULE_PARM_DESC(forcecrt2type,
- "Force the second display output type. Possible values are NONE, LCD, TV, VGA, SVIDEO or COMPOSITE.");
-
-module_param(vesa, int, 0000);
-MODULE_PARM_DESC(vesa,
- "Selects the desired default display mode by VESA mode number (eg. 0x117).");
-
-module_param(filter, int, 0000);
-MODULE_PARM_DESC(filter,
- "Selects TV flicker filter type (only for systems with a SiS301 video bridge). Possible values 0-7. Default: [no filter]).");
-
-static int __init xgifb_init(void)
-{
- char *option = NULL;
-
- if (forcecrt2type)
- XGIfb_search_crt2type(forcecrt2type);
- if (fb_get_options("xgifb", &option))
- return -ENODEV;
- XGIfb_setup(option);
-
- return pci_register_driver(&xgifb_driver);
-}
-
-static void __exit xgifb_remove_module(void)
-{
- pci_unregister_driver(&xgifb_driver);
- pr_debug("Module unloaded\n");
-}
-
-MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("XGITECH , Others");
-module_init(xgifb_init);
-module_exit(xgifb_remove_module);
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
deleted file mode 100644
index 982c676c16c6..000000000000
--- a/drivers/staging/xgifb/XGIfb.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LINUX_XGIFB
-#define _LINUX_XGIFB
-#include "vgatypes.h"
-#include "vb_struct.h"
-
-enum xgifb_display_type {
- XGIFB_DISP_NONE = 0,
- XGIFB_DISP_CRT,
- XGIFB_DISP_LCD,
- XGIFB_DISP_TV,
-};
-
-#define HASVB_NONE 0x00
-#define HASVB_301 0x01
-#define HASVB_LVDS 0x02
-#define HASVB_TRUMPION 0x04
-#define HASVB_LVDS_CHRONTEL 0x10
-#define HASVB_302 0x20
-#define HASVB_CHRONTEL 0x80
-
-enum XGI_CHIP_TYPE {
- XG40 = 32,
- XG42,
- XG20 = 48,
- XG21,
- XG27,
-};
-
-enum xgi_tvtype {
- TVMODE_NTSC = 0,
- TVMODE_PAL,
- TVMODE_HIVISION,
- TVTYPE_PALM,
- TVTYPE_PALN,
- TVTYPE_NTSCJ,
- TVMODE_TOTAL
-};
-
-enum xgi_tv_plug {
- TVPLUG_UNKNOWN = 0,
- TVPLUG_COMPOSITE = 1,
- TVPLUG_SVIDEO = 2,
- TVPLUG_COMPOSITE_AND_SVIDEO = 3,
- TVPLUG_SCART = 4,
- TVPLUG_YPBPR_525i = 5,
- TVPLUG_YPBPR_525P = 6,
- TVPLUG_YPBPR_750P = 7,
- TVPLUG_YPBPR_1080i = 8,
- TVPLUG_TOTAL
-};
-
-struct xgifb_video_info {
- struct fb_info *fb_info;
- struct xgi_hw_device_info hw_info;
- struct vb_device_info dev_info;
-
- int mode_idx;
- int rate_idx;
-
- u32 pseudo_palette[17];
-
- int chip_id;
- unsigned int video_size;
- phys_addr_t video_base;
- void __iomem *video_vbase;
- phys_addr_t mmio_base;
- unsigned long mmio_size;
- void __iomem *mmio_vbase;
- unsigned long vga_base;
- int mtrr;
-
- int video_bpp;
- int video_cmap_len;
- int video_width;
- int video_height;
- int video_vwidth;
- int video_vheight;
- int org_x;
- int org_y;
- int video_linelength;
- unsigned int refresh_rate;
-
- enum xgifb_display_type display2; /* the second display output type */
- bool display2_force;
- unsigned char hasVB;
- unsigned char TV_type;
- unsigned char TV_plug;
-
- struct XGI21_LVDSCapStruct lvds_data;
-
- enum XGI_CHIP_TYPE chip;
- unsigned char revision_id;
-
- unsigned short DstColor;
- unsigned long XGI310_AccelDepth;
- unsigned long CommandReg;
-
- unsigned int pcibus;
- unsigned int pcislot;
- unsigned int pcifunc;
-
- unsigned short subsysvendor;
- unsigned short subsysdevice;
-
- char reserved[236];
-};
-
-#endif
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
deleted file mode 100644
index 0311e2682d27..000000000000
--- a/drivers/staging/xgifb/vb_def.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VB_DEF_
-#define _VB_DEF_
-#include "../../video/fbdev/sis/initdef.h"
-
-#define VB_XGI301C 0x0020 /* for 301C */
-
-#define SupportCRT2in301C 0x0100 /* for 301C */
-#define SetCHTVOverScan 0x8000
-
-#define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */
-#define Panel_1024x768x75 0x22
-#define Panel_1280x1024x75 0x23
-
-#define PanelRef60Hz 0x00
-#define PanelRef75Hz 0x20
-
-#define YPbPr525iVCLK 0x03B
-#define YPbPr525iVCLK_2 0x03A
-
-#define XGI_CRT2_PORT_00 (0x00 - 0x030)
-
-#define SupportAllCRT2 0x0078
-#define NoSupportTV 0x0070
-#define NoSupportHiVisionTV 0x0060
-#define NoSupportLCD 0x0058
-
-/* -------------- SetMode Stack/Scratch */
-#define XGI_SetCRT2ToLCDA 0x0100
-#define SetCRT2ToDualEdge 0x8000
-
-#define ReserveTVOption 0x0008
-
-#define SetTVLowResolution 0x0400
-#define TVSimuMode 0x0800
-#define RPLLDIV2XO 0x1000
-#define NTSC1024x768 0x2000
-#define SetTVLockMode 0x4000
-
-#define XGI_LCDVESATiming 0x0001 /* LCD Info/CR37 */
-#define XGI_EnableLVDSDDA 0x0002
-#define EnableScalingLCD 0x0008
-#define SetPWDEnable 0x0004
-#define SetLCDtoNonExpanding 0x0010
-#define SetLCDDualLink 0x0100
-#define SetLCDLowResolution 0x0200
-
-/* LCD Capability shampoo */
-#define DefaultLCDCap 0x80ea
-#define EnableLCD24bpp 0x0004 /* default */
-#define LCDPolarity 0x00c0 /* default: SyncNN */
-#define XGI_LCDDualLink 0x0100
-#define EnableSpectrum 0x0200
-#define PWDEnable 0x0400
-#define EnableVBCLKDRVLOW 0x4000
-#define EnablePLLSPLOW 0x8000
-
-#define AVIDEOSense 0x01 /* CR32 */
-#define SVIDEOSense 0x02
-#define SCARTSense 0x04
-#define LCDSense 0x08
-#define Monitor2Sense 0x10
-#define Monitor1Sense 0x20
-#define HiTVSense 0x40
-
-#define YPbPrSense 0x80 /* NEW SCRATCH */
-
-#define TVSense 0xc7
-
-#define YPbPrMode 0xe0
-#define YPbPrMode525i 0x00
-#define YPbPrMode525p 0x20
-#define YPbPrMode750p 0x40
-#define YPbPrMode1080i 0x60
-
-#define ScalingLCD 0x08
-
-#define SetYPbPr 0x04
-
-/* ---------------------- VUMA Information */
-#define DisplayDeviceFromCMOS 0x10
-
-/* ---------------------- HK Evnet Definition */
-#define XGI_ModeSwitchStatus 0xf0
-#define ActiveCRT1 0x10
-#define ActiveLCD 0x0020
-#define ActiveTV 0x40
-#define ActiveCRT2 0x80
-
-#define ActiveAVideo 0x01
-#define ActiveSVideo 0x02
-#define ActiveSCART 0x04
-#define ActiveHiTV 0x08
-#define ActiveYPbPr 0x10
-
-#define NTSC1024x768HT 1908
-
-#define YPbPrTV525iHT 1716 /* YPbPr */
-#define YPbPrTV525iVT 525
-#define YPbPrTV525pHT 1716
-#define YPbPrTV525pVT 525
-#define YPbPrTV750pHT 1650
-#define YPbPrTV750pVT 750
-
-#define VCLK25_175 0x00
-#define VCLK28_322 0x01
-#define VCLK31_5 0x02
-#define VCLK36 0x03
-#define VCLK43_163 0x05
-#define VCLK44_9 0x06
-#define VCLK49_5 0x07
-#define VCLK50 0x08
-#define VCLK52_406 0x09
-#define VCLK56_25 0x0A
-#define VCLK68_179 0x0D
-#define VCLK72_852 0x0E
-#define VCLK75 0x0F
-#define VCLK78_75 0x11
-#define VCLK79_411 0x12
-#define VCLK83_95 0x13
-#define VCLK86_6 0x15
-#define VCLK94_5 0x16
-#define VCLK113_309 0x1B
-#define VCLK116_406 0x1C
-#define VCLK135_5 0x1E
-#define VCLK139_054 0x1F
-#define VCLK157_5 0x20
-#define VCLK162 0x21
-#define VCLK175 0x22
-#define VCLK189 0x23
-#define VCLK202_5 0x25
-#define VCLK229_5 0x26
-#define VCLK234 0x27
-#define VCLK254_817 0x29
-#define VCLK266_952 0x2B
-#define VCLK269_655 0x2C
-#define VCLK277_015 0x2E
-#define VCLK291_132 0x30
-#define VCLK291_766 0x31
-#define VCLK315_195 0x33
-#define VCLK323_586 0x34
-#define VCLK330_615 0x35
-#define VCLK340_477 0x37
-#define VCLK375_847 0x38
-#define VCLK388_631 0x39
-#define VCLK125_999 0x51
-#define VCLK148_5 0x52
-#define VCLK217_325 0x55
-#define XGI_YPbPr750pVCLK 0x57
-
-#define VCLK39_77 0x40
-#define YPbPr525pVCLK 0x3A
-#define NTSC1024VCLK 0x41
-#define VCLK35_2 0x49 /* ; 800x480 */
-#define VCLK122_61 0x4A
-#define VCLK80_350 0x4B
-#define VCLK107_385 0x4C
-
-#define RES320x200 0x00
-#define RES320x240 0x01
-#define RES400x300 0x02
-#define RES512x384 0x03
-#define RES640x400 0x04
-#define RES640x480x60 0x05
-#define RES640x480x72 0x06
-#define RES640x480x75 0x07
-#define RES640x480x85 0x08
-#define RES640x480x100 0x09
-#define RES640x480x120 0x0A
-#define RES640x480x160 0x0B
-#define RES640x480x200 0x0C
-#define RES800x600x56 0x0D
-#define RES800x600x60 0x0E
-#define RES800x600x72 0x0F
-#define RES800x600x75 0x10
-#define RES800x600x85 0x11
-#define RES800x600x100 0x12
-#define RES800x600x120 0x13
-#define RES800x600x160 0x14
-#define RES1024x768x43 0x15
-#define RES1024x768x60 0x16
-#define RES1024x768x70 0x17
-#define RES1024x768x75 0x18
-#define RES1024x768x85 0x19
-#define RES1024x768x100 0x1A
-#define RES1024x768x120 0x1B
-#define RES1280x1024x43 0x1C
-#define RES1280x1024x60 0x1D
-#define RES1280x1024x75 0x1E
-#define RES1280x1024x85 0x1F
-#define RES1600x1200x60 0x20
-#define RES1600x1200x65 0x21
-#define RES1600x1200x70 0x22
-#define RES1600x1200x75 0x23
-#define RES1600x1200x85 0x24
-#define RES1600x1200x100 0x25
-#define RES1600x1200x120 0x26
-#define RES1920x1440x60 0x27
-#define RES1920x1440x65 0x28
-#define RES1920x1440x70 0x29
-#define RES1920x1440x75 0x2A
-#define RES1920x1440x85 0x2B
-#define RES1920x1440x100 0x2C
-#define RES2048x1536x60 0x2D
-#define RES2048x1536x65 0x2E
-#define RES2048x1536x70 0x2F
-#define RES2048x1536x75 0x30
-#define RES2048x1536x85 0x31
-#define RES800x480x60 0x32
-#define RES800x480x75 0x33
-#define RES800x480x85 0x34
-#define RES1024x576x60 0x35
-#define RES1024x576x75 0x36
-#define RES1024x576x85 0x37
-#define RES1280x720x60 0x38
-#define RES1280x720x75 0x39
-#define RES1280x720x85 0x3A
-#define RES1280x960x60 0x3B
-#define RES720x480x60 0x3C
-#define RES720x576x56 0x3D
-#define RES856x480x79I 0x3E
-#define RES856x480x60 0x3F
-#define RES1280x768x60 0x40
-#define RES1400x1050x60 0x41
-#define RES1152x864x60 0x42
-#define RES1152x864x75 0x43
-#define RES1024x768x160 0x44
-#define RES1280x960x75 0x45
-#define RES1280x960x85 0x46
-#define RES1280x960x120 0x47
-
-#define XG27_CR8F 0x0C
-#define XG27_SR36 0x30
-#define XG27_SR40 0x04
-#define XG27_SR41 0x00
-#define XG40_CRCF 0x13
-#define XGI330_CRT2Data_1_2 0
-#define XGI330_CRT2Data_4_D 0
-#define XGI330_CRT2Data_4_E 0
-#define XGI330_CRT2Data_4_10 0x80
-#define XGI330_SR07 0x18
-#define XGI330_SR1F 0
-#define XGI330_SR23 0xf6
-#define XGI330_SR24 0x0d
-#define XGI330_SR31 0xc0
-#define XGI330_SR32 0x11
-#define XGI330_SR33 0
-
-extern const struct XGI_ExtStruct XGI330_EModeIDTable[];
-extern const struct XGI_Ext2Struct XGI330_RefIndex[];
-extern const struct XGI_CRT1TableStruct XGI_CRT1Table[];
-extern const struct XGI_ECLKDataStruct XGI340_ECLKData[];
-extern const struct SiS_VCLKData XGI_VCLKData[];
-extern const unsigned char XGI340_CR6B[][4];
-extern const unsigned char XGI340_AGPReg[];
-
-#endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
deleted file mode 100644
index ac1c815a3c5e..000000000000
--- a/drivers/staging/xgifb/vb_init.c
+++ /dev/null
@@ -1,1367 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-
-#include "XGIfb.h"
-#include "vb_def.h"
-#include "vb_util.h"
-#include "vb_setmode.h"
-#include "vb_init.h"
-static const unsigned short XGINew_DDRDRAM_TYPE340[4][2] = {
- { 16, 0x45},
- { 8, 0x35},
- { 4, 0x31},
- { 2, 0x21} };
-
-static const unsigned short XGINew_DDRDRAM_TYPE20[12][2] = {
- { 128, 0x5D},
- { 64, 0x59},
- { 64, 0x4D},
- { 32, 0x55},
- { 32, 0x49},
- { 32, 0x3D},
- { 16, 0x51},
- { 16, 0x45},
- { 16, 0x39},
- { 8, 0x41},
- { 8, 0x35},
- { 4, 0x31} };
-
-#define XGIFB_ROM_SIZE 65536
-
-static unsigned char
-XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned char data, temp;
-
- if (HwDeviceExtension->jChipType < XG20) {
- data = xgifb_reg_get(pVBInfo->P3c4, 0x39) & 0x02;
- if (data == 0)
- data = (xgifb_reg_get(pVBInfo->P3c4, 0x3A) &
- 0x02) >> 1;
- return data;
- } else if (HwDeviceExtension->jChipType == XG27) {
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
- /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
- if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
- data = 0; /* DDR */
- else
- data = 1; /* DDRII */
- return data;
- } else if (HwDeviceExtension->jChipType == XG21) {
- /* Independent GPIO control */
- xgifb_reg_and(pVBInfo->P3d4, 0xB4, ~0x02);
- usleep_range(800, 1800);
- xgifb_reg_or(pVBInfo->P3d4, 0x4A, 0x80); /* Enable GPIOH read */
- /* GPIOF 0:DVI 1:DVO */
- data = xgifb_reg_get(pVBInfo->P3d4, 0x48);
- /*
- * HOTPLUG_SUPPORT
- * for current XG20 & XG21, GPIOH is floating, driver will
- * fix DDR temporarily
- */
- /* DVI read GPIOH */
- data &= 0x01; /* 1=DDRII, 0=DDR */
- /* ~HOTPLUG_SUPPORT */
- xgifb_reg_or(pVBInfo->P3d4, 0xB4, 0x02);
- return data;
- }
- data = xgifb_reg_get(pVBInfo->P3d4, 0x97) & 0x01;
-
- if (data == 1)
- data++;
-
- return data;
-}
-
-static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
- struct vb_device_info *pVBInfo)
-{
- xgifb_reg_set(P3c4, 0x18, 0x01);
- xgifb_reg_set(P3c4, 0x19, 0x20);
- xgifb_reg_set(P3c4, 0x16, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x80);
-
- usleep_range(3, 1003);
- xgifb_reg_set(P3c4, 0x18, 0x00);
- xgifb_reg_set(P3c4, 0x19, 0x20);
- xgifb_reg_set(P3c4, 0x16, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x80);
-
- usleep_range(60, 1060);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
- xgifb_reg_set(P3c4, 0x19, 0x01);
- xgifb_reg_set(P3c4, 0x16, 0x03);
- xgifb_reg_set(P3c4, 0x16, 0x83);
- usleep_range(1, 1001);
- xgifb_reg_set(P3c4, 0x1B, 0x03);
- usleep_range(500, 1500);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
- xgifb_reg_set(P3c4, 0x19, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x03);
- xgifb_reg_set(P3c4, 0x16, 0x83);
- xgifb_reg_set(P3c4, 0x1B, 0x00);
-}
-
-static void XGINew_SetMemoryClock(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_set(pVBInfo->P3c4,
- 0x28,
- pVBInfo->MCLKData[pVBInfo->ram_type].SR28);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x29,
- pVBInfo->MCLKData[pVBInfo->ram_type].SR29);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2A,
- pVBInfo->MCLKData[pVBInfo->ram_type].SR2A);
-
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2E,
- XGI340_ECLKData[pVBInfo->ram_type].SR2E);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2F,
- XGI340_ECLKData[pVBInfo->ram_type].SR2F);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x30,
- XGI340_ECLKData[pVBInfo->ram_type].SR30);
-}
-
-static void XGINew_DDRII_Bootup_XG27(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned long P3c4, struct vb_device_info *pVBInfo)
-{
- unsigned long P3d4 = P3c4 + 0x10;
-
- pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
- XGINew_SetMemoryClock(pVBInfo);
-
- /* Set Double Frequency */
- xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */
-
- usleep_range(200, 1200);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS2 */
- xgifb_reg_set(P3c4, 0x19, 0x80); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
- usleep_range(15, 1015);
- xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- usleep_range(15, 1015);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS3 */
- xgifb_reg_set(P3c4, 0x19, 0xC0); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
- usleep_range(15, 1015);
- xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- usleep_range(15, 1015);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS1 */
- xgifb_reg_set(P3c4, 0x19, 0x40); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- usleep_range(15, 1015);
-
- xgifb_reg_set(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Enable */
- xgifb_reg_set(P3c4, 0x19, 0x0A); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
- xgifb_reg_set(P3c4, 0x16, 0x80); /* Set SR16 */
-
- xgifb_reg_set(P3c4, 0x1B, 0x04); /* Set SR1B */
- usleep_range(60, 1060);
- xgifb_reg_set(P3c4, 0x1B, 0x00); /* Set SR1B */
-
- xgifb_reg_set(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Reset */
- xgifb_reg_set(P3c4, 0x19, 0x08); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
-
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x16, 0x83); /* Set SR16 */
- usleep_range(15, 1015);
-
- xgifb_reg_set(P3c4, 0x18, 0x80); /* Set SR18 */ /* MRS, ODT */
- xgifb_reg_set(P3c4, 0x19, 0x46); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- usleep_range(15, 1015);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS */
- xgifb_reg_set(P3c4, 0x19, 0x40); /* Set SR19 */
- xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
- usleep_range(15, 1015);
-
- /* Set SR1B refresh control 000:close; 010:open */
- xgifb_reg_set(P3c4, 0x1B, 0x04);
- usleep_range(200, 1200);
-}
-
-static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
- unsigned long P3c4,
- struct vb_device_info *pVBInfo)
-{
- unsigned long P3d4 = P3c4 + 0x10;
-
- pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
- XGINew_SetMemoryClock(pVBInfo);
-
- xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */
-
- usleep_range(200, 1200);
- xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS2 */
- xgifb_reg_set(P3c4, 0x19, 0x80);
- xgifb_reg_set(P3c4, 0x16, 0x05);
- xgifb_reg_set(P3c4, 0x16, 0x85);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS3 */
- xgifb_reg_set(P3c4, 0x19, 0xC0);
- xgifb_reg_set(P3c4, 0x16, 0x05);
- xgifb_reg_set(P3c4, 0x16, 0x85);
-
- xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS1 */
- xgifb_reg_set(P3c4, 0x19, 0x40);
- xgifb_reg_set(P3c4, 0x16, 0x05);
- xgifb_reg_set(P3c4, 0x16, 0x85);
-
- xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */
- xgifb_reg_set(P3c4, 0x19, 0x02);
- xgifb_reg_set(P3c4, 0x16, 0x05);
- xgifb_reg_set(P3c4, 0x16, 0x85);
-
- usleep_range(15, 1015);
- xgifb_reg_set(P3c4, 0x1B, 0x04); /* SR1B */
- usleep_range(30, 1030);
- xgifb_reg_set(P3c4, 0x1B, 0x00); /* SR1B */
- usleep_range(100, 1100);
-
- xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */
- xgifb_reg_set(P3c4, 0x19, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x05);
- xgifb_reg_set(P3c4, 0x16, 0x85);
-
- usleep_range(200, 1200);
-}
-
-static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
- struct vb_device_info *pVBInfo)
-{
- xgifb_reg_set(P3c4, 0x18, 0x01);
- xgifb_reg_set(P3c4, 0x19, 0x40);
- xgifb_reg_set(P3c4, 0x16, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x80);
- usleep_range(60, 1060);
-
- xgifb_reg_set(P3c4, 0x18, 0x00);
- xgifb_reg_set(P3c4, 0x19, 0x40);
- xgifb_reg_set(P3c4, 0x16, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x80);
- usleep_range(60, 1060);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
- xgifb_reg_set(P3c4, 0x19, 0x01);
- xgifb_reg_set(P3c4, 0x16, 0x03);
- xgifb_reg_set(P3c4, 0x16, 0x83);
- usleep_range(1, 1001);
- xgifb_reg_set(P3c4, 0x1B, 0x03);
- usleep_range(500, 1500);
- xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
- xgifb_reg_set(P3c4, 0x19, 0x00);
- xgifb_reg_set(P3c4, 0x16, 0x03);
- xgifb_reg_set(P3c4, 0x16, 0x83);
- xgifb_reg_set(P3c4, 0x1B, 0x00);
-}
-
-static void XGINew_DDR1x_DefaultRegister(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned long Port, struct vb_device_info *pVBInfo)
-{
- unsigned long P3d4 = Port, P3c4 = Port - 0x10;
-
- if (HwDeviceExtension->jChipType >= XG20) {
- XGINew_SetMemoryClock(pVBInfo);
- xgifb_reg_set(P3d4,
- 0x82,
- pVBInfo->CR40[11][pVBInfo->ram_type]); /* CR82 */
- xgifb_reg_set(P3d4,
- 0x85,
- pVBInfo->CR40[12][pVBInfo->ram_type]); /* CR85 */
- xgifb_reg_set(P3d4,
- 0x86,
- pVBInfo->CR40[13][pVBInfo->ram_type]); /* CR86 */
-
- xgifb_reg_set(P3d4, 0x98, 0x01);
- xgifb_reg_set(P3d4, 0x9A, 0x02);
-
- XGINew_DDR1x_MRS_XG20(P3c4, pVBInfo);
- } else {
- XGINew_SetMemoryClock(pVBInfo);
-
- switch (HwDeviceExtension->jChipType) {
- case XG42:
- /* CR82 */
- xgifb_reg_set(P3d4,
- 0x82,
- pVBInfo->CR40[11][pVBInfo->ram_type]);
- /* CR85 */
- xgifb_reg_set(P3d4,
- 0x85,
- pVBInfo->CR40[12][pVBInfo->ram_type]);
- /* CR86 */
- xgifb_reg_set(P3d4,
- 0x86,
- pVBInfo->CR40[13][pVBInfo->ram_type]);
- break;
- default:
- xgifb_reg_set(P3d4, 0x82, 0x88);
- xgifb_reg_set(P3d4, 0x86, 0x00);
- /* Insert read command for delay */
- xgifb_reg_get(P3d4, 0x86);
- xgifb_reg_set(P3d4, 0x86, 0x88);
- xgifb_reg_get(P3d4, 0x86);
- xgifb_reg_set(P3d4,
- 0x86,
- pVBInfo->CR40[13][pVBInfo->ram_type]);
- xgifb_reg_set(P3d4, 0x82, 0x77);
- xgifb_reg_set(P3d4, 0x85, 0x00);
-
- /* Insert read command for delay */
- xgifb_reg_get(P3d4, 0x85);
- xgifb_reg_set(P3d4, 0x85, 0x88);
-
- /* Insert read command for delay */
- xgifb_reg_get(P3d4, 0x85);
- /* CR85 */
- xgifb_reg_set(P3d4,
- 0x85,
- pVBInfo->CR40[12][pVBInfo->ram_type]);
- /* CR82 */
- xgifb_reg_set(P3d4,
- 0x82,
- pVBInfo->CR40[11][pVBInfo->ram_type]);
- break;
- }
-
- xgifb_reg_set(P3d4, 0x97, 0x00);
- xgifb_reg_set(P3d4, 0x98, 0x01);
- xgifb_reg_set(P3d4, 0x9A, 0x02);
- XGINew_DDR1x_MRS_340(P3c4, pVBInfo);
- }
-}
-
-static void XGINew_DDR2_DefaultRegister(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned long Port, struct vb_device_info *pVBInfo)
-{
- unsigned long P3d4 = Port, P3c4 = Port - 0x10;
- /*
- * keep following setting sequence, each setting in
- * the same reg insert idle
- */
- xgifb_reg_set(P3d4, 0x82, 0x77);
- xgifb_reg_set(P3d4, 0x86, 0x00);
- xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
- xgifb_reg_set(P3d4, 0x86, 0x88);
- xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
- /* CR86 */
- xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][pVBInfo->ram_type]);
- xgifb_reg_set(P3d4, 0x82, 0x77);
- xgifb_reg_set(P3d4, 0x85, 0x00);
- xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
- xgifb_reg_set(P3d4, 0x85, 0x88);
- xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
- xgifb_reg_set(P3d4,
- 0x85,
- pVBInfo->CR40[12][pVBInfo->ram_type]); /* CR85 */
- if (HwDeviceExtension->jChipType == XG27)
- /* CR82 */
- xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][pVBInfo->ram_type]);
- else
- xgifb_reg_set(P3d4, 0x82, 0xA8); /* CR82 */
-
- xgifb_reg_set(P3d4, 0x98, 0x01);
- xgifb_reg_set(P3d4, 0x9A, 0x02);
- if (HwDeviceExtension->jChipType == XG27)
- XGINew_DDRII_Bootup_XG27(HwDeviceExtension, P3c4, pVBInfo);
- else
- XGINew_DDR2_MRS_XG20(HwDeviceExtension, P3c4, pVBInfo);
-}
-
-static void XGI_SetDRAM_Helper(unsigned long P3d4, u8 seed, u8 temp2, u8 reg,
- u8 shift_factor, u8 mask1, u8 mask2)
-{
- u8 j;
-
- for (j = 0; j < 4; j++) {
- temp2 |= (((seed >> (2 * j)) & 0x03) << shift_factor);
- xgifb_reg_set(P3d4, reg, temp2);
- xgifb_reg_get(P3d4, reg);
- temp2 &= mask1;
- temp2 += mask2;
- }
-}
-
-static void XGINew_SetDRAMDefaultRegister340(
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned long Port, struct vb_device_info *pVBInfo)
-{
- unsigned char temp, temp1, temp2, temp3, j, k;
-
- unsigned long P3d4 = Port, P3c4 = Port - 0x10;
-
- xgifb_reg_set(P3d4, 0x6D, pVBInfo->CR40[8][pVBInfo->ram_type]);
- xgifb_reg_set(P3d4, 0x68, pVBInfo->CR40[5][pVBInfo->ram_type]);
- xgifb_reg_set(P3d4, 0x69, pVBInfo->CR40[6][pVBInfo->ram_type]);
- xgifb_reg_set(P3d4, 0x6A, pVBInfo->CR40[7][pVBInfo->ram_type]);
-
- /* CR6B DQS fine tune delay */
- temp = 0xaa;
- XGI_SetDRAM_Helper(P3d4, temp, 0, 0x6B, 2, 0xF0, 0x10);
-
- /* CR6E DQM fine tune delay */
- XGI_SetDRAM_Helper(P3d4, 0, 0, 0x6E, 2, 0xF0, 0x10);
-
- temp3 = 0;
- for (k = 0; k < 4; k++) {
- /* CR6E_D[1:0] select channel */
- xgifb_reg_and_or(P3d4, 0x6E, 0xFC, temp3);
- XGI_SetDRAM_Helper(P3d4, 0, 0, 0x6F, 0, 0xF8, 0x08);
- temp3 += 0x01;
- }
-
- xgifb_reg_set(P3d4,
- 0x80,
- pVBInfo->CR40[9][pVBInfo->ram_type]); /* CR80 */
- xgifb_reg_set(P3d4,
- 0x81,
- pVBInfo->CR40[10][pVBInfo->ram_type]); /* CR81 */
-
- temp2 = 0x80;
- /* CR89 terminator type select */
- XGI_SetDRAM_Helper(P3d4, 0, temp2, 0x89, 0, 0xF0, 0x10);
-
- temp = 0;
- temp1 = temp & 0x03;
- temp2 |= temp1;
- xgifb_reg_set(P3d4, 0x89, temp2);
-
- temp = pVBInfo->CR40[3][pVBInfo->ram_type];
- temp1 = temp & 0x0F;
- temp2 = (temp >> 4) & 0x07;
- temp3 = temp & 0x80;
- xgifb_reg_set(P3d4, 0x45, temp1); /* CR45 */
- xgifb_reg_set(P3d4, 0x99, temp2); /* CR99 */
- xgifb_reg_or(P3d4, 0x40, temp3); /* CR40_D[7] */
- xgifb_reg_set(P3d4,
- 0x41,
- pVBInfo->CR40[0][pVBInfo->ram_type]); /* CR41 */
-
- if (HwDeviceExtension->jChipType == XG27)
- xgifb_reg_set(P3d4, 0x8F, XG27_CR8F); /* CR8F */
-
- for (j = 0; j <= 6; j++) /* CR90 - CR96 */
- xgifb_reg_set(P3d4, (0x90 + j),
- pVBInfo->CR40[14 + j][pVBInfo->ram_type]);
-
- for (j = 0; j <= 2; j++) /* CRC3 - CRC5 */
- xgifb_reg_set(P3d4, (0xC3 + j),
- pVBInfo->CR40[21 + j][pVBInfo->ram_type]);
-
- for (j = 0; j < 2; j++) /* CR8A - CR8B */
- xgifb_reg_set(P3d4, (0x8A + j),
- pVBInfo->CR40[1 + j][pVBInfo->ram_type]);
-
- if (HwDeviceExtension->jChipType == XG42)
- xgifb_reg_set(P3d4, 0x8C, 0x87);
-
- xgifb_reg_set(P3d4,
- 0x59,
- pVBInfo->CR40[4][pVBInfo->ram_type]); /* CR59 */
-
- xgifb_reg_set(P3d4, 0x83, 0x09); /* CR83 */
- xgifb_reg_set(P3d4, 0x87, 0x00); /* CR87 */
- xgifb_reg_set(P3d4, 0xCF, XG40_CRCF); /* CRCF */
- if (pVBInfo->ram_type) {
- xgifb_reg_set(P3c4, 0x17, 0x80); /* SR17 DDRII */
- if (HwDeviceExtension->jChipType == XG27)
- xgifb_reg_set(P3c4, 0x17, 0x02); /* SR17 DDRII */
-
- } else {
- xgifb_reg_set(P3c4, 0x17, 0x00); /* SR17 DDR */
- }
- xgifb_reg_set(P3c4, 0x1A, 0x87); /* SR1A */
-
- temp = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
- if (temp == 0) {
- XGINew_DDR1x_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
- } else {
- xgifb_reg_set(P3d4, 0xB0, 0x80); /* DDRII Dual frequency mode */
- XGINew_DDR2_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
- }
- xgifb_reg_set(P3c4, 0x1B, 0x03); /* SR1B */
-}
-
-static unsigned short XGINew_SetDRAMSize20Reg(
- unsigned short dram_size,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data = 0, memsize = 0;
- int RankSize;
- unsigned char ChannelNo;
-
- RankSize = dram_size * pVBInfo->ram_bus / 8;
- data = xgifb_reg_get(pVBInfo->P3c4, 0x13);
- data &= 0x80;
-
- if (data == 0x80)
- RankSize *= 2;
-
- data = 0;
-
- if (pVBInfo->ram_channel == 3)
- ChannelNo = 4;
- else
- ChannelNo = pVBInfo->ram_channel;
-
- if (ChannelNo * RankSize <= 256) {
- while ((RankSize >>= 1) > 0)
- data += 0x10;
-
- memsize = data >> 4;
-
- /* Fix DRAM Sizing Error */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x14,
- (xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) |
- (data & 0xF0));
- usleep_range(15, 1015);
- }
- return memsize;
-}
-
-static int XGINew_ReadWriteRest(unsigned short StopAddr,
- unsigned short StartAddr,
- struct vb_device_info *pVBInfo)
-{
- int i;
- unsigned long Position = 0;
- void __iomem *fbaddr = pVBInfo->FBAddr;
-
- writel(Position, fbaddr + Position);
-
- for (i = StartAddr; i <= StopAddr; i++) {
- Position = 1 << i;
- writel(Position, fbaddr + Position);
- }
-
- /* Fix #1759 Memory Size error in Multi-Adapter. */
- usleep_range(500, 1500);
-
- Position = 0;
-
- if (readl(fbaddr + Position) != Position)
- return 0;
-
- for (i = StartAddr; i <= StopAddr; i++) {
- Position = 1 << i;
- if (readl(fbaddr + Position) != Position)
- return 0;
- }
- return 1;
-}
-
-static unsigned char XGINew_CheckFrequence(struct vb_device_info *pVBInfo)
-{
- unsigned char data;
-
- data = xgifb_reg_get(pVBInfo->P3d4, 0x97);
-
- if ((data & 0x10) == 0) {
- data = xgifb_reg_get(pVBInfo->P3c4, 0x39);
- return (data & 0x02) >> 1;
- }
- return data & 0x01;
-}
-
-static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned char data;
-
- switch (HwDeviceExtension->jChipType) {
- case XG20:
- case XG21:
- data = xgifb_reg_get(pVBInfo->P3d4, 0x97);
- data = data & 0x01;
- pVBInfo->ram_channel = 1; /* XG20 "JUST" one channel */
-
- if (data == 0) { /* Single_32_16 */
-
- if ((HwDeviceExtension->ulVideoMemorySize - 1)
- > 0x1000000) {
- pVBInfo->ram_bus = 32; /* 32 bits */
- /* 22bit + 2 rank + 32bit */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- if ((HwDeviceExtension->ulVideoMemorySize - 1) >
- 0x800000) {
- /* 22bit + 1 rank + 32bit */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x13,
- 0x31);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x14,
- 0x42);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(23,
- 23,
- pVBInfo) == 1)
- return;
- }
- }
-
- if ((HwDeviceExtension->ulVideoMemorySize - 1) >
- 0x800000) {
- pVBInfo->ram_bus = 16; /* 16 bits */
- /* 22bit + 2 rank + 16bit */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
- return;
- xgifb_reg_set(pVBInfo->P3c4,
- 0x13,
- 0x31);
- usleep_range(15, 1015);
- }
-
- } else { /* Dual_16_8 */
- if ((HwDeviceExtension->ulVideoMemorySize - 1) >
- 0x800000) {
- pVBInfo->ram_bus = 16; /* 16 bits */
- /* (0x31:12x8x2) 22bit + 2 rank */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
- /* 0x41:16Mx16 bit */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
- return;
-
- if ((HwDeviceExtension->ulVideoMemorySize - 1) >
- 0x400000) {
- /* (0x31:12x8x2) 22bit + 1 rank */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x13,
- 0x31);
- /* 0x31:8Mx16 bit */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x14,
- 0x31);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(22,
- 22,
- pVBInfo) == 1)
- return;
- }
- }
-
- if ((HwDeviceExtension->ulVideoMemorySize - 1) >
- 0x400000) {
- pVBInfo->ram_bus = 8; /* 8 bits */
- /* (0x31:12x8x2) 22bit + 2 rank */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1);
- /* 0x30:8Mx8 bit */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30);
- usleep_range(15, 1015);
-
- if (XGINew_ReadWriteRest(22, 21, pVBInfo) == 1)
- return;
-
- /* (0x31:12x8x2) 22bit + 1 rank */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x13,
- 0x31);
- usleep_range(15, 1015);
- }
- }
- break;
-
- case XG27:
- pVBInfo->ram_bus = 16; /* 16 bits */
- pVBInfo->ram_channel = 1; /* Single channel */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x51); /* 32Mx16 bit */
- break;
- case XG42:
- /*
- * XG42 SR14 D[3] Reserve
- * D[2] = 1, Dual Channel
- * = 0, Single Channel
- *
- * It's Different from Other XG40 Series.
- */
- if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII, DDR2x */
- pVBInfo->ram_bus = 32; /* 32 bits */
- pVBInfo->ram_channel = 2; /* 2 Channel */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x44);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x34);
- if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 1; /* Single Channel */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x40);
-
- if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
- return;
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30);
- } else { /* DDR */
- pVBInfo->ram_bus = 64; /* 64 bits */
- pVBInfo->ram_channel = 1; /* 1 channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
- }
-
- break;
-
- default: /* XG40 */
-
- if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII */
- pVBInfo->ram_bus = 32; /* 32 bits */
- pVBInfo->ram_channel = 3;
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
-
- if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 2; /* 2 channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1) {
- pVBInfo->ram_channel = 3; /* 4 channels */
- } else {
- pVBInfo->ram_channel = 2; /* 2 channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x38);
- }
- } else { /* DDR */
- pVBInfo->ram_bus = 64; /* 64 bits */
- pVBInfo->ram_channel = 2; /* 2 channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
-
- if (XGINew_ReadWriteRest(25, 24, pVBInfo) == 1)
- return;
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4A);
- }
- break;
- }
-}
-
-static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- u8 i, size;
- unsigned short memsize, start_addr;
- const unsigned short (*dram_table)[2];
-
- xgifb_reg_set(pVBInfo->P3c4, 0x15, 0x00); /* noninterleaving */
- xgifb_reg_set(pVBInfo->P3c4, 0x1C, 0x00); /* nontiling */
- XGINew_CheckChannel(HwDeviceExtension, pVBInfo);
-
- if (HwDeviceExtension->jChipType >= XG20) {
- dram_table = XGINew_DDRDRAM_TYPE20;
- size = ARRAY_SIZE(XGINew_DDRDRAM_TYPE20);
- start_addr = 5;
- } else {
- dram_table = XGINew_DDRDRAM_TYPE340;
- size = ARRAY_SIZE(XGINew_DDRDRAM_TYPE340);
- start_addr = 9;
- }
-
- for (i = 0; i < size; i++) {
- /* SetDRAMSizingType */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, dram_table[i][1]);
- usleep_range(50, 1050); /* should delay 50 ns */
-
- memsize = XGINew_SetDRAMSize20Reg(dram_table[i][0], pVBInfo);
-
- if (memsize == 0)
- continue;
-
- memsize += (pVBInfo->ram_channel - 2) + 20;
- if ((HwDeviceExtension->ulVideoMemorySize - 1) <
- (unsigned long)(1 << memsize))
- continue;
-
- if (XGINew_ReadWriteRest(memsize, start_addr, pVBInfo) == 1)
- return 1;
- }
- return 0;
-}
-
-static void XGINew_SetDRAMSize_340(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data;
-
- pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-
- XGISetModeNew(xgifb_info, HwDeviceExtension, 0x2e);
-
- data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
- /* disable read cache */
- xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short)(data & 0xDF));
- XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
-
- XGINew_DDRSizing340(HwDeviceExtension, pVBInfo);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
- /* enable read cache */
- xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short)(data | 0x20));
-}
-
-static u8 *xgifb_copy_rom(struct pci_dev *dev, size_t *rom_size)
-{
- void __iomem *rom_address;
- u8 *rom_copy;
-
- rom_address = pci_map_rom(dev, rom_size);
- if (!rom_address)
- return NULL;
-
- rom_copy = vzalloc(XGIFB_ROM_SIZE);
- if (!rom_copy)
- goto done;
-
- *rom_size = min_t(size_t, *rom_size, XGIFB_ROM_SIZE);
- memcpy_fromio(rom_copy, rom_address, *rom_size);
-
-done:
- pci_unmap_rom(dev, rom_address);
- return rom_copy;
-}
-
-static bool xgifb_read_vbios(struct pci_dev *pdev)
-{
- struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
- u8 *vbios;
- unsigned long i;
- unsigned char j;
- struct XGI21_LVDSCapStruct *lvds;
- size_t vbios_size;
- int entry;
-
- vbios = xgifb_copy_rom(pdev, &vbios_size);
- if (!vbios) {
- dev_err(&pdev->dev, "Video BIOS not available\n");
- return false;
- }
- if (vbios_size <= 0x65)
- goto error;
- /*
- * The user can ignore the LVDS bit in the BIOS and force the display
- * type.
- */
- if (!(vbios[0x65] & 0x1) &&
- (!xgifb_info->display2_force ||
- xgifb_info->display2 != XGIFB_DISP_LCD)) {
- vfree(vbios);
- return false;
- }
- if (vbios_size <= 0x317)
- goto error;
- i = vbios[0x316] | (vbios[0x317] << 8);
- if (vbios_size <= i - 1)
- goto error;
- j = vbios[i - 1];
- if (j == 0)
- goto error;
- if (j == 0xff)
- j = 1;
-
- /* Read the LVDS table index scratch register set by the BIOS. */
-
- entry = xgifb_reg_get(xgifb_info->dev_info.P3d4, 0x36);
- if (entry >= j)
- entry = 0;
- i += entry * 25;
- lvds = &xgifb_info->lvds_data;
- if (vbios_size <= i + 24)
- goto error;
- lvds->LVDS_Capability = vbios[i] | (vbios[i + 1] << 8);
- lvds->LVDSHT = vbios[i + 2] | (vbios[i + 3] << 8);
- lvds->LVDSVT = vbios[i + 4] | (vbios[i + 5] << 8);
- lvds->LVDSHDE = vbios[i + 6] | (vbios[i + 7] << 8);
- lvds->LVDSVDE = vbios[i + 8] | (vbios[i + 9] << 8);
- lvds->LVDSHFP = vbios[i + 10] | (vbios[i + 11] << 8);
- lvds->LVDSVFP = vbios[i + 12] | (vbios[i + 13] << 8);
- lvds->LVDSHSYNC = vbios[i + 14] | (vbios[i + 15] << 8);
- lvds->LVDSVSYNC = vbios[i + 16] | (vbios[i + 17] << 8);
- lvds->VCLKData1 = vbios[i + 18];
- lvds->VCLKData2 = vbios[i + 19];
- lvds->PSC_S1 = vbios[i + 20];
- lvds->PSC_S2 = vbios[i + 21];
- lvds->PSC_S3 = vbios[i + 22];
- lvds->PSC_S4 = vbios[i + 23];
- lvds->PSC_S5 = vbios[i + 24];
- vfree(vbios);
- return true;
-error:
- dev_err(&pdev->dev, "Video BIOS corrupted\n");
- vfree(vbios);
- return false;
-}
-
-static void XGINew_ChkSenseStatus(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx = 0, temp, tempcx, CR3CData;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x32);
-
- if (temp & Monitor1Sense)
- tempbx |= ActiveCRT1;
- if (temp & LCDSense)
- tempbx |= ActiveLCD;
- if (temp & Monitor2Sense)
- tempbx |= ActiveCRT2;
- if (temp & TVSense) {
- tempbx |= ActiveTV;
- if (temp & AVIDEOSense)
- tempbx |= (ActiveAVideo << 8);
- if (temp & SVIDEOSense)
- tempbx |= (ActiveSVideo << 8);
- if (temp & SCARTSense)
- tempbx |= (ActiveSCART << 8);
- if (temp & HiTVSense)
- tempbx |= (ActiveHiTV << 8);
- if (temp & YPbPrSense)
- tempbx |= (ActiveYPbPr << 8);
- }
-
- tempcx = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
- tempcx |= (xgifb_reg_get(pVBInfo->P3d4, 0x3e) << 8);
-
- if (tempbx & tempcx) {
- CR3CData = xgifb_reg_get(pVBInfo->P3d4, 0x3c);
- if (!(CR3CData & DisplayDeviceFromCMOS))
- tempcx = 0x1FF0;
- } else {
- tempcx = 0x1FF0;
- }
-
- tempbx &= tempcx;
- xgifb_reg_set(pVBInfo->P3d4, 0x3d, (tempbx & 0x00FF));
- xgifb_reg_set(pVBInfo->P3d4, 0x3e, ((tempbx & 0xFF00) >> 8));
-}
-
-static void XGINew_SetModeScratch(struct vb_device_info *pVBInfo)
-{
- unsigned short temp, tempcl = 0, tempch = 0, CR31Data, CR38Data;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
- temp |= xgifb_reg_get(pVBInfo->P3d4, 0x3e) << 8;
- temp |= (xgifb_reg_get(pVBInfo->P3d4, 0x31) & (DriverMode >> 8)) << 8;
-
- if (pVBInfo->IF_DEF_CRT2Monitor == 1) {
- if (temp & ActiveCRT2)
- tempcl = SetCRT2ToRAMDAC;
- }
-
- if (temp & ActiveLCD) {
- tempcl |= SetCRT2ToLCD;
- if (temp & DriverMode) {
- if (temp & ActiveTV) {
- tempch = SetToLCDA | EnableDualEdge;
- temp ^= SetCRT2ToLCD;
-
- if ((temp >> 8) & ActiveAVideo)
- tempcl |= SetCRT2ToAVIDEO;
- if ((temp >> 8) & ActiveSVideo)
- tempcl |= SetCRT2ToSVIDEO;
- if ((temp >> 8) & ActiveSCART)
- tempcl |= SetCRT2ToSCART;
-
- if (pVBInfo->IF_DEF_HiVision == 1) {
- if ((temp >> 8) & ActiveHiTV)
- tempcl |= SetCRT2ToHiVision;
- }
-
- if (pVBInfo->IF_DEF_YPbPr == 1) {
- if ((temp >> 8) & ActiveYPbPr)
- tempch |= SetYPbPr;
- }
- }
- }
- } else {
- if ((temp >> 8) & ActiveAVideo)
- tempcl |= SetCRT2ToAVIDEO;
- if ((temp >> 8) & ActiveSVideo)
- tempcl |= SetCRT2ToSVIDEO;
- if ((temp >> 8) & ActiveSCART)
- tempcl |= SetCRT2ToSCART;
-
- if (pVBInfo->IF_DEF_HiVision == 1) {
- if ((temp >> 8) & ActiveHiTV)
- tempcl |= SetCRT2ToHiVision;
- }
-
- if (pVBInfo->IF_DEF_YPbPr == 1) {
- if ((temp >> 8) & ActiveYPbPr)
- tempch |= SetYPbPr;
- }
- }
-
- tempcl |= SetSimuScanMode;
- if ((!(temp & ActiveCRT1)) && ((temp & ActiveLCD) ||
- (temp & ActiveTV) ||
- (temp & ActiveCRT2)))
- tempcl ^= (SetSimuScanMode | SwitchCRT2);
- if ((temp & ActiveLCD) && (temp & ActiveTV))
- tempcl ^= (SetSimuScanMode | SwitchCRT2);
- xgifb_reg_set(pVBInfo->P3d4, 0x30, tempcl);
-
- CR31Data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
- CR31Data &= ~(SetNotSimuMode >> 8);
- if (!(temp & ActiveCRT1))
- CR31Data |= (SetNotSimuMode >> 8);
- CR31Data &= ~(DisableCRT2Display >> 8);
- if (!((temp & ActiveLCD) || (temp & ActiveTV) || (temp & ActiveCRT2)))
- CR31Data |= (DisableCRT2Display >> 8);
- xgifb_reg_set(pVBInfo->P3d4, 0x31, CR31Data);
-
- CR38Data = xgifb_reg_get(pVBInfo->P3d4, 0x38);
- CR38Data &= ~SetYPbPr;
- CR38Data |= tempch;
- xgifb_reg_set(pVBInfo->P3d4, 0x38, CR38Data);
-}
-
-static unsigned short XGINew_SenseLCD(struct xgi_hw_device_info
- *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp = HwDeviceExtension->ulCRT2LCDType;
-
- switch (HwDeviceExtension->ulCRT2LCDType) {
- case LCD_640x480:
- case LCD_1024x600:
- case LCD_1152x864:
- case LCD_1280x960:
- case LCD_1152x768:
- case LCD_1920x1440:
- case LCD_2048x1536:
- temp = 0; /* overwrite used ulCRT2LCDType */
- break;
- case LCD_UNKNOWN: /* unknown lcd, do nothing */
- return 0;
- }
- xgifb_reg_and_or(pVBInfo->P3d4, 0x36, 0xF0, temp);
- return 1;
-}
-
-static void XGINew_GetXG21Sense(struct pci_dev *pdev,
- struct vb_device_info *pVBInfo)
-{
- struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
- unsigned char Temp;
-
- if (xgifb_read_vbios(pdev)) { /* For XG21 LVDS */
- xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
- /* LVDS on chip */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
- } else {
- /* Enable GPIOA/B read */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03);
- Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0xC0;
- if (Temp == 0xC0) { /* DVI & DVO GPIOA/B pull high */
- XGINew_SenseLCD(&xgifb_info->hw_info, pVBInfo);
- xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
- /* Enable read GPIOF */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x20, 0x20);
- if (xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0x04)
- Temp = 0xA0; /* Only DVO on chip */
- else
- Temp = 0x80; /* TMDS on chip */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, Temp);
- /* Disable read GPIOF */
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x20);
- }
- }
-}
-
-static void XGINew_GetXG27Sense(struct vb_device_info *pVBInfo)
-{
- unsigned char Temp, bCR4A;
-
- bCR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- /* Enable GPIOA/B/C read */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x07, 0x07);
- Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0x07;
- xgifb_reg_set(pVBInfo->P3d4, 0x4A, bCR4A);
-
- if (Temp <= 0x02) {
- /* LVDS setting */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
- xgifb_reg_set(pVBInfo->P3d4, 0x30, 0x21);
- } else {
- /* TMDS/DVO setting */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xA0);
- }
- xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
-}
-
-static unsigned char GetXG21FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char CR38, CR4A, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- /* enable GPIOE read */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x10, 0x10);
- CR38 = xgifb_reg_get(pVBInfo->P3d4, 0x38);
- temp = 0;
- if ((CR38 & 0xE0) > 0x80) {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
- temp &= 0x08;
- temp >>= 3;
- }
-
- xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
-
- return temp;
-}
-
-static unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- /* enable GPIOA/B/C read */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03);
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
- if (temp > 2)
- temp = ((temp & 0x04) >> 1) | ((~temp) & 0x01);
-
- xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
-
- return temp;
-}
-
-static bool xgifb_bridge_is_on(struct vb_device_info *vb_info)
-{
- u8 flag;
-
- flag = xgifb_reg_get(vb_info->Part4Port, 0x00);
- return flag == 1 || flag == 2;
-}
-
-unsigned char XGIInitNew(struct pci_dev *pdev)
-{
- struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
- struct xgi_hw_device_info *HwDeviceExtension = &xgifb_info->hw_info;
- struct vb_device_info VBINF;
- struct vb_device_info *pVBInfo = &VBINF;
- unsigned char i, temp = 0, temp1;
-
- pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-
- if (!pVBInfo->FBAddr) {
- dev_dbg(&pdev->dev, "pVBInfo->FBAddr == 0\n");
- return 0;
- }
-
- XGIRegInit(pVBInfo, xgifb_info->vga_base);
-
- outb(0x67, pVBInfo->P3c2);
-
- InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-
- /* Openkey */
- xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
-
- /* GetXG21Sense (GPIO) */
- if (HwDeviceExtension->jChipType == XG21)
- XGINew_GetXG21Sense(pdev, pVBInfo);
-
- if (HwDeviceExtension->jChipType == XG27)
- XGINew_GetXG27Sense(pVBInfo);
-
- /* Reset Extended register */
-
- for (i = 0x06; i < 0x20; i++)
- xgifb_reg_set(pVBInfo->P3c4, i, 0);
-
- for (i = 0x21; i <= 0x27; i++)
- xgifb_reg_set(pVBInfo->P3c4, i, 0);
-
- for (i = 0x31; i <= 0x3B; i++)
- xgifb_reg_set(pVBInfo->P3c4, i, 0);
-
- /* Auto over driver for XG42 */
- if (HwDeviceExtension->jChipType == XG42)
- xgifb_reg_set(pVBInfo->P3c4, 0x3B, 0xC0);
-
- for (i = 0x79; i <= 0x7C; i++)
- xgifb_reg_set(pVBInfo->P3d4, i, 0);
-
- if (HwDeviceExtension->jChipType >= XG20)
- xgifb_reg_set(pVBInfo->P3d4, 0x97, pVBInfo->XGINew_CR97);
-
- /* SetDefExt1Regs begin */
- xgifb_reg_set(pVBInfo->P3c4, 0x07, XGI330_SR07);
- if (HwDeviceExtension->jChipType == XG27) {
- xgifb_reg_set(pVBInfo->P3c4, 0x40, XG27_SR40);
- xgifb_reg_set(pVBInfo->P3c4, 0x41, XG27_SR41);
- }
- xgifb_reg_set(pVBInfo->P3c4, 0x11, 0x0F);
- xgifb_reg_set(pVBInfo->P3c4, 0x1F, XGI330_SR1F);
- /* Frame buffer can read/write SR20 */
- xgifb_reg_set(pVBInfo->P3c4, 0x20, 0xA0);
- /* H/W request for slow corner chip */
- xgifb_reg_set(pVBInfo->P3c4, 0x36, 0x70);
- if (HwDeviceExtension->jChipType == XG27)
- xgifb_reg_set(pVBInfo->P3c4, 0x36, XG27_SR36);
-
- if (HwDeviceExtension->jChipType < XG20) {
- u32 Temp;
-
- /* Set AGP customize registers (in SetDefAGPRegs) Start */
- for (i = 0x47; i <= 0x4C; i++)
- xgifb_reg_set(pVBInfo->P3d4,
- i,
- XGI340_AGPReg[i - 0x47]);
-
- for (i = 0x70; i <= 0x71; i++)
- xgifb_reg_set(pVBInfo->P3d4,
- i,
- XGI340_AGPReg[6 + i - 0x70]);
-
- for (i = 0x74; i <= 0x77; i++)
- xgifb_reg_set(pVBInfo->P3d4,
- i,
- XGI340_AGPReg[8 + i - 0x74]);
-
- pci_read_config_dword(pdev, 0x50, &Temp);
- Temp >>= 20;
- Temp &= 0xF;
-
- if (Temp == 1)
- xgifb_reg_set(pVBInfo->P3d4, 0x48, 0x20); /* CR48 */
- } /* != XG20 */
-
- /* Set PCI */
- xgifb_reg_set(pVBInfo->P3c4, 0x23, XGI330_SR23);
- xgifb_reg_set(pVBInfo->P3c4, 0x24, XGI330_SR24);
- xgifb_reg_set(pVBInfo->P3c4, 0x25, 0);
-
- if (HwDeviceExtension->jChipType < XG20) {
- /* Set VB */
- XGI_UnLockCRT2(pVBInfo);
- /* disable VideoCapture */
- xgifb_reg_and_or(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00);
- xgifb_reg_set(pVBInfo->Part1Port, 0x00, 0x00);
- /* chk if BCLK>=100MHz */
- temp1 = xgifb_reg_get(pVBInfo->P3d4, 0x7B);
-
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x02, XGI330_CRT2Data_1_2);
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x2E, 0x08); /* use VB */
- } /* != XG20 */
-
- xgifb_reg_set(pVBInfo->P3c4, 0x27, 0x1F);
-
- if ((HwDeviceExtension->jChipType == XG42) &&
- XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) != 0) {
- /* Not DDR */
- xgifb_reg_set(pVBInfo->P3c4,
- 0x31,
- (XGI330_SR31 & 0x3F) | 0x40);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x32,
- (XGI330_SR32 & 0xFC) | 0x01);
- } else {
- xgifb_reg_set(pVBInfo->P3c4, 0x31, XGI330_SR31);
- xgifb_reg_set(pVBInfo->P3c4, 0x32, XGI330_SR32);
- }
- xgifb_reg_set(pVBInfo->P3c4, 0x33, XGI330_SR33);
-
- if (HwDeviceExtension->jChipType < XG20) {
- if (xgifb_bridge_is_on(pVBInfo)) {
- xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C);
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x0D, XGI330_CRT2Data_4_D);
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x0E, XGI330_CRT2Data_4_E);
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x10, XGI330_CRT2Data_4_10);
- xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F);
- XGI_LockCRT2(pVBInfo);
- }
- } /* != XG20 */
-
- XGI_SenseCRT1(pVBInfo);
-
- if (HwDeviceExtension->jChipType == XG21) {
- xgifb_reg_and_or(pVBInfo->P3d4,
- 0x32,
- ~Monitor1Sense,
- Monitor1Sense); /* Z9 default has CRT */
- temp = GetXG21FPBits(pVBInfo);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x01, temp);
- }
- if (HwDeviceExtension->jChipType == XG27) {
- xgifb_reg_and_or(pVBInfo->P3d4,
- 0x32,
- ~Monitor1Sense,
- Monitor1Sense); /* Z9 default has CRT */
- temp = GetXG27FPBits(pVBInfo);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x03, temp);
- }
-
- pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-
- XGINew_SetDRAMDefaultRegister340(HwDeviceExtension,
- pVBInfo->P3d4,
- pVBInfo);
-
- XGINew_SetDRAMSize_340(xgifb_info, HwDeviceExtension, pVBInfo);
-
- xgifb_reg_set(pVBInfo->P3c4, 0x22, 0xfa);
- xgifb_reg_set(pVBInfo->P3c4, 0x21, 0xa3);
-
- XGINew_ChkSenseStatus(pVBInfo);
- XGINew_SetModeScratch(pVBInfo);
-
- xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87);
-
- return 1;
-} /* end of init */
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
deleted file mode 100644
index 2f8a70133ebd..000000000000
--- a/drivers/staging/xgifb/vb_init.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VBINIT_
-#define _VBINIT_
-unsigned char XGIInitNew(struct pci_dev *pdev);
-void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr);
-#endif
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
deleted file mode 100644
index 3782f8641bf2..000000000000
--- a/drivers/staging/xgifb/vb_setmode.c
+++ /dev/null
@@ -1,5528 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/delay.h>
-#include "XGIfb.h"
-
-#include "vb_def.h"
-#include "vb_init.h"
-#include "vb_util.h"
-#include "vb_table.h"
-#include "vb_setmode.h"
-
-#define IndexMask 0xff
-#define TVCLKBASE_315_25 (TVCLKBASE_315 + 25)
-
-static const unsigned short XGINew_VGA_DAC[] = {
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
- 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
- 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
- 0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
- 0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
- 0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
- 0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
- 0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
- 0x0B, 0x0C, 0x0D, 0x0F, 0x10};
-
-void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
-{
- pVBInfo->MCLKData = XGI340New_MCLKData;
-
- pVBInfo->LCDResInfo = 0;
- pVBInfo->LCDTypeInfo = 0;
- pVBInfo->LCDInfo = 0;
- pVBInfo->VBInfo = 0;
- pVBInfo->TVInfo = 0;
-
- pVBInfo->SR18 = XGI340_SR18;
- pVBInfo->CR40 = XGI340_cr41;
-
- if (ChipType < XG20)
- XGI_GetVBType(pVBInfo);
-
- /* 310 customization related */
- if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
- pVBInfo->LCDCapList = XGI_LCDDLCapList;
- else
- pVBInfo->LCDCapList = XGI_LCDCapList;
-
- if (ChipType >= XG20)
- pVBInfo->XGINew_CR97 = 0x10;
-
- if (ChipType == XG27) {
- unsigned char temp;
-
- pVBInfo->MCLKData = XGI27New_MCLKData;
- pVBInfo->CR40 = XGI27_cr41;
- pVBInfo->XGINew_CR97 = 0xc1;
- pVBInfo->SR18 = XG27_SR18;
-
- /* Z11m DDR */
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
- /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
- if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
- pVBInfo->XGINew_CR97 = 0x80;
- }
-}
-
-static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo)
-{
- unsigned char SRdata, i;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
-
- for (i = 0; i < 4; i++) {
- /* Get SR1,2,3,4 from file */
- /* SR1 is with screen off 0x20 */
- SRdata = XGI330_StandTable.SR[i];
- /* Set SR 1 2 3 4 */
- xgifb_reg_set(pVBInfo->P3c4, i + 1, SRdata);
- }
-}
-
-static void XGI_SetCRTCRegs(struct vb_device_info *pVBInfo)
-{
- unsigned char CRTCdata;
- unsigned short i;
-
- CRTCdata = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- CRTCdata &= 0x7f;
- xgifb_reg_set(pVBInfo->P3d4, 0x11, CRTCdata); /* Unlock CRTC */
-
- for (i = 0; i <= 0x18; i++) {
- /* Get CRTC from file */
- CRTCdata = XGI330_StandTable.CRTC[i];
- xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
- }
-}
-
-static void XGI_SetATTRegs(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char ARdata;
- unsigned short i, modeflag;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- for (i = 0; i <= 0x13; i++) {
- ARdata = XGI330_StandTable.ATTR[i];
-
- if ((modeflag & Charx8Dot) && i == 0x13) { /* ifndef Dot9 */
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- ARdata = 0;
- } else if ((pVBInfo->VBInfo &
- (SetCRT2ToTV | SetCRT2ToLCD)) &&
- (pVBInfo->VBInfo & SetInSlaveMode)) {
- ARdata = 0;
- }
- }
-
- inb(pVBInfo->P3da); /* reset 3da */
- outb(i, pVBInfo->P3c0); /* set index */
- outb(ARdata, pVBInfo->P3c0); /* set data */
- }
-
- inb(pVBInfo->P3da); /* reset 3da */
- outb(0x14, pVBInfo->P3c0); /* set index */
- outb(0x00, pVBInfo->P3c0); /* set data */
- inb(pVBInfo->P3da); /* Enable Attribute */
- outb(0x20, pVBInfo->P3c0);
-}
-
-static void XGI_SetGRCRegs(struct vb_device_info *pVBInfo)
-{
- unsigned char GRdata;
- unsigned short i;
-
- for (i = 0; i <= 0x08; i++) {
- /* Get GR from file */
- GRdata = XGI330_StandTable.GRC[i];
- xgifb_reg_set(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
- }
-
- if (pVBInfo->ModeType > ModeVGA) {
- GRdata = xgifb_reg_get(pVBInfo->P3ce, 0x05);
- GRdata &= 0xBF; /* 256 color disable */
- xgifb_reg_set(pVBInfo->P3ce, 0x05, GRdata);
- }
-}
-
-static void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo)
-{
- unsigned short i;
-
- for (i = 0x0A; i <= 0x0E; i++)
- xgifb_reg_set(pVBInfo->P3c4, i, 0x00); /* Clear SR0A-SR0E */
-}
-
-static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x20);
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[0].SR2B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[0].SR2C);
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x10);
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[1].SR2B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[1].SR2C);
-
- xgifb_reg_and(pVBInfo->P3c4, 0x31, ~0x30);
- return 0;
-}
-
-static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- unsigned short *i,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- tempbx = XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
- tempax = 0;
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
- tempax |= SupportRAMDAC2;
-
- if (pVBInfo->VBType & VB_XGI301C)
- tempax |= SupportCRT2in301C;
- }
-
- /* 301b */
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- tempax |= SupportLCD;
-
- if (pVBInfo->LCDResInfo != Panel_1280x1024 &&
- pVBInfo->LCDResInfo != Panel_1280x960 &&
- (pVBInfo->LCDInfo & LCDNonExpanding) &&
- resinfo >= 9)
- return 0;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */
- tempax |= SupportHiVision;
- if ((pVBInfo->VBInfo & SetInSlaveMode) &&
- ((resinfo == 4) ||
- (resinfo == 3 && (pVBInfo->SetFlag & TVSimuMode)) ||
- (resinfo > 7)))
- return 0;
- } else if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO |
- SetCRT2ToSCART | SetCRT2ToYPbPr525750 |
- SetCRT2ToHiVision)) {
- tempax |= SupportTV;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
- VB_SIS302LV | VB_XGI301C))
- tempax |= SupportTV1024;
-
- if (!(pVBInfo->VBInfo & TVSetPAL) &&
- (modeflag & NoSupportSimuTV) &&
- (pVBInfo->VBInfo & SetInSlaveMode) &&
- !(pVBInfo->VBInfo & SetNotSimuMode))
- return 0;
- }
-
- for (; XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID ==
- tempbx; (*i)--) {
- infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
- if (infoflag & tempax)
- return 1;
-
- if ((*i) == 0)
- break;
- }
-
- for ((*i) = 0;; (*i)++) {
- infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
- if (XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID
- != tempbx) {
- return 0;
- }
-
- if (infoflag & tempax)
- return 1;
- }
- return 1;
-}
-
-static void XGI_SetSync(unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short sync, temp;
-
- /* di+0x00 */
- sync = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
- sync &= 0xC0;
- temp = 0x2F;
- temp |= sync;
- outb(temp, pVBInfo->P3c2); /* Set Misc(3c2) */
-}
-
-static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
- struct xgi_hw_device_info *HwDeviceExtension)
-{
- unsigned char data, data1, pushax;
- unsigned short i, j;
-
- /* unlock cr0-7 */
- data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- data &= 0x7F;
- xgifb_reg_set(pVBInfo->P3d4, 0x11, data);
-
- data = pVBInfo->TimingH.data[0];
- xgifb_reg_set(pVBInfo->P3d4, 0, data);
-
- for (i = 0x01; i <= 0x04; i++) {
- data = pVBInfo->TimingH.data[i];
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 1), data);
- }
-
- for (i = 0x05; i <= 0x06; i++) {
- data = pVBInfo->TimingH.data[i];
- xgifb_reg_set(pVBInfo->P3c4, (unsigned short)(i + 6), data);
- }
-
- j = xgifb_reg_get(pVBInfo->P3c4, 0x0e);
- j &= 0x1F;
- data = pVBInfo->TimingH.data[7];
- data &= 0xE0;
- data |= j;
- xgifb_reg_set(pVBInfo->P3c4, 0x0e, data);
-
- if (HwDeviceExtension->jChipType >= XG20) {
- data = xgifb_reg_get(pVBInfo->P3d4, 0x04);
- data = data - 1;
- xgifb_reg_set(pVBInfo->P3d4, 0x04, data);
- data = xgifb_reg_get(pVBInfo->P3d4, 0x05);
- data1 = data;
- data1 &= 0xE0;
- data &= 0x1F;
- if (data == 0) {
- pushax = data;
- data = xgifb_reg_get(pVBInfo->P3c4, 0x0c);
- data &= 0xFB;
- xgifb_reg_set(pVBInfo->P3c4, 0x0c, data);
- data = pushax;
- }
- data = data - 1;
- data |= data1;
- xgifb_reg_set(pVBInfo->P3d4, 0x05, data);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x0e);
- data >>= 5;
- data = data + 3;
- if (data > 7)
- data = data - 7;
- data <<= 5;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0e, ~0xE0, data);
- }
-}
-
-static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char data;
- unsigned short i, j;
-
- for (i = 0x00; i <= 0x01; i++) {
- data = pVBInfo->TimingV.data[i];
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 6), data);
- }
-
- for (i = 0x02; i <= 0x03; i++) {
- data = pVBInfo->TimingV.data[i];
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 0x0e), data);
- }
-
- for (i = 0x04; i <= 0x05; i++) {
- data = pVBInfo->TimingV.data[i];
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 0x11), data);
- }
-
- j = xgifb_reg_get(pVBInfo->P3c4, 0x0a);
- j &= 0xC0;
- data = pVBInfo->TimingV.data[6];
- data &= 0x3F;
- data |= j;
- xgifb_reg_set(pVBInfo->P3c4, 0x0a, data);
-
- data = pVBInfo->TimingV.data[6];
- data &= 0x80;
- data >>= 2;
-
- i = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- i &= DoubleScanMode;
- if (i)
- data |= 0x80;
-
- j = xgifb_reg_get(pVBInfo->P3d4, 0x09);
- j &= 0x5F;
- data |= j;
- xgifb_reg_set(pVBInfo->P3d4, 0x09, data);
-}
-
-static void XGI_SetCRT1CRTC(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo,
- struct xgi_hw_device_info *HwDeviceExtension)
-{
- unsigned char index, data;
- unsigned short i;
-
- /* Get index */
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- index = index & IndexMask;
-
- data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- data &= 0x7F;
- xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
-
- for (i = 0; i < 8; i++)
- pVBInfo->TimingH.data[i]
- = XGI_CRT1Table[index].CR[i];
-
- for (i = 0; i < 7; i++)
- pVBInfo->TimingV.data[i]
- = XGI_CRT1Table[index].CR[i + 8];
-
- XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
-
- XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
-
- if (pVBInfo->ModeType > 0x03)
- xgifb_reg_set(pVBInfo->P3d4, 0x14, 0x4F);
-}
-
-/*
- * Function : XGI_SetXG21CRTC
- * Input : Stand or enhance CRTC table
- * Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F
- * Description : Set LCD timing
- */
-static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char index, Tempax, Tempbx, Tempcx, Tempdx;
- unsigned short Temp1, Temp2, Temp3;
-
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- /* Tempax: CR4 HRS */
- Tempax = XGI_CRT1Table[index].CR[3];
- Tempcx = Tempax; /* Tempcx: HRS */
- /* SR2E[7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
-
- Tempdx = XGI_CRT1Table[index].CR[5]; /* SRB */
- Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
- Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
- Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
- Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
-
- Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
- Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
-
- Tempbx = XGI_CRT1Table[index].CR[6]; /* SRC */
- Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
- Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
- Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
-
- Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
- Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
-
- Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
- if (Tempax < Tempcx) /* HRE < HRS */
- Temp2 |= 0x40; /* Temp2 + 0x40 */
-
- Temp2 &= 0xFF;
- Tempax = (unsigned char)Temp2; /* Tempax: HRE[7:0] */
- Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
- Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
- Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
- /* SR2F D[7:2]->HRE, D[1:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* CR10 VRS */
- Tempax = XGI_CRT1Table[index].CR[10];
- Tempbx = Tempax; /* Tempbx: VRS */
- Tempax &= 0x01; /* Tempax[0]: VRS[0] */
- xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
- /* CR7[2][7] VRE */
- Tempax = XGI_CRT1Table[index].CR[9];
- Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
- Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
- Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
- Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
-
- Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
- Temp1 <<= 1; /* Temp1[8]: VRS[8] */
- Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
- Tempax &= 0x80;
- Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
- Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
- /* Tempax: SRA */
- Tempax = XGI_CRT1Table[index].CR[14];
- Tempax &= 0x08; /* Tempax[3]: VRS[3] */
- Temp2 = Tempax;
- Temp2 <<= 7; /* Temp2[10]: VRS[10] */
- Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
-
- /* Tempax: CR11 VRE */
- Tempax = XGI_CRT1Table[index].CR[11];
- Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
- /* Tempbx: SRA */
- Tempbx = XGI_CRT1Table[index].CR[14];
- Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
- Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
- Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
- Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
- Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
-
- Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
- if (Tempax < Temp3) /* VRE < VRS */
- Temp2 |= 0x20; /* VRE + 0x20 */
-
- Temp2 &= 0xFF;
- Tempax = (unsigned char)Temp2; /* Tempax: VRE[7:0] */
- Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
- Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
- Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
- Tempbx = (unsigned char)Temp1;
- Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
- Tempax &= 0x7F;
- /* SR3F D[7:2]->VRE D[1:0]->VRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
-}
-
-static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short index, Tempax, Tempbx, Tempcx;
-
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- /* Tempax: CR4 HRS */
- Tempax = XGI_CRT1Table[index].CR[3];
- Tempbx = Tempax; /* Tempbx: HRS[7:0] */
- /* SR2E[7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
-
- /* SR0B */
- Tempax = XGI_CRT1Table[index].CR[5];
- Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8] */
- Tempbx |= Tempax << 2; /* Tempbx: HRS[9:0] */
-
- Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
- Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
- Tempcx = Tempax; /* Tempcx: HRE[4:0] */
-
- Tempax = XGI_CRT1Table[index].CR[6]; /* SRC */
- Tempax &= 0x04; /* Tempax[2]: HRE[5] */
- Tempax <<= 3; /* Tempax[5]: HRE[5] */
- Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
-
- Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
- Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
-
- /* Tempax: CR4 HRS */
- Tempax = XGI_CRT1Table[index].CR[3];
- Tempax &= 0x3F; /* Tempax: HRS[5:0] */
- if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
- Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
-
- Tempax = XGI_CRT1Table[index].CR[5]; /* SR0B */
- Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
- Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
- Tempax |= (Tempbx << 2) & 0xFF; /* Tempax[7:2]: HRE[5:0] */
- /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* CR10 VRS */
- Tempax = XGI_CRT1Table[index].CR[10];
- /* SR34[7:0]->VRS[7:0] */
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax);
-
- Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
- /* CR7[7][2] VRS[9][8] */
- Tempax = XGI_CRT1Table[index].CR[9];
- Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
- Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
- Tempax >>= 2; /* Tempax[0]: VRS[8] */
- /* SR35[0]: VRS[8] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax);
- Tempcx |= Tempax << 8; /* Tempcx <= VRS[8:0] */
- Tempcx |= (Tempbx & 0x80) << 2; /* Tempcx <= VRS[9:0] */
- /* Tempax: SR0A */
- Tempax = XGI_CRT1Table[index].CR[14];
- Tempax &= 0x08; /* SR0A[3] VRS[10] */
- Tempcx |= Tempax << 7; /* Tempcx <= VRS[10:0] */
-
- /* Tempax: CR11 VRE */
- Tempax = XGI_CRT1Table[index].CR[11];
- Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
- /* Tempbx: SR0A */
- Tempbx = XGI_CRT1Table[index].CR[14];
- Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
- Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
- Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
- Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
- Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
- Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
-
- if (Tempbx <= Tempcx) /* VRE <= VRS */
- Tempbx |= 0x20; /* VRE + 0x20 */
-
- /* Tempax: Tempax[7:0]; VRE[5:0]00 */
- Tempax = (Tempbx << 2) & 0xFF;
- /* SR3F[7:2]:VRE[5:0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax);
- Tempax = Tempcx >> 8;
- /* SR35[2:0]:VRS[10:8] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, Tempax);
-}
-
-static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char temp;
-
- /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
- temp = (temp & 3) << 6;
- /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80);
- /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
-}
-
-static void xgifb_set_lcd(int chip_id,
- struct vb_device_info *pVBInfo,
- unsigned short RefreshRateTableIndex)
-{
- unsigned short temp;
-
- xgifb_reg_set(pVBInfo->P3d4, 0x2E, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x2F, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
- xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
-
- if (chip_id == XG27) {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
- if ((temp & 0x03) == 0) { /* dual 12 */
- xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x13);
- xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x13);
- }
- }
-
- if (chip_id == XG27) {
- XGI_SetXG27FPBits(pVBInfo);
- } else {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
- if (temp & 0x01) {
- /* 18 bits FP */
- xgifb_reg_or(pVBInfo->P3c4, 0x06, 0x40);
- xgifb_reg_or(pVBInfo->P3c4, 0x09, 0x40);
- }
- }
-
- xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
-
- xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
- xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
-
- temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- if (temp & 0x4000) {
- /* Hsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
- }
- if (temp & 0x8000) {
- /* Vsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
- }
-}
-
-/*
- * Function : XGI_UpdateXG21CRTC
- * Input :
- * Output : CRT1 CRTC
- * Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing
- */
-static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
- struct vb_device_info *pVBInfo,
- unsigned short RefreshRateTableIndex)
-{
- int index = -1;
-
- xgifb_reg_and(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
- if (ModeNo == 0x2E &&
- (XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
- RES640x480x60))
- index = 12;
- else if (ModeNo == 0x2E &&
- (XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
- RES640x480x72))
- index = 13;
- else if (ModeNo == 0x2F)
- index = 14;
- else if (ModeNo == 0x50)
- index = 15;
- else if (ModeNo == 0x59)
- index = 16;
-
- if (index != -1) {
- xgifb_reg_set(pVBInfo->P3d4, 0x02,
- XGI_UpdateCRT1Table[index].CR02);
- xgifb_reg_set(pVBInfo->P3d4, 0x03,
- XGI_UpdateCRT1Table[index].CR03);
- xgifb_reg_set(pVBInfo->P3d4, 0x15,
- XGI_UpdateCRT1Table[index].CR15);
- xgifb_reg_set(pVBInfo->P3d4, 0x16,
- XGI_UpdateCRT1Table[index].CR16);
- }
-}
-
-static void XGI_SetCRT1DE(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
-
- unsigned char data;
-
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- tempax = XGI330_ModeResInfo[resindex].HTotal;
- tempbx = XGI330_ModeResInfo[resindex].VTotal;
-
- if (modeflag & HalfDCLK)
- tempax >>= 1;
-
- if (modeflag & HalfDCLK)
- tempax <<= 1;
-
- temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-
- if (temp & InterlaceMode)
- tempbx >>= 1;
-
- if (modeflag & DoubleScanMode)
- tempbx <<= 1;
-
- tempcx = 8;
-
- tempax /= tempcx;
- tempax -= 1;
- tempbx -= 1;
- tempcx = tempax;
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- data &= 0x7F;
- xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
- xgifb_reg_set(pVBInfo->P3d4, 0x01, (unsigned short)(tempcx & 0xff));
- xgifb_reg_and_or(pVBInfo->P3d4, 0x0b, ~0x0c,
- (unsigned short)((tempcx & 0x0ff00) >> 10));
- xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short)(tempbx & 0xff));
- tempax = 0;
- tempbx >>= 8;
-
- if (tempbx & 0x01)
- tempax |= 0x02;
-
- if (tempbx & 0x02)
- tempax |= 0x40;
-
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x42, tempax);
- data = xgifb_reg_get(pVBInfo->P3d4, 0x07);
- tempax = 0;
-
- if (tempbx & 0x04)
- tempax |= 0x02;
-
- xgifb_reg_and_or(pVBInfo->P3d4, 0x0a, ~0x02, tempax);
- xgifb_reg_set(pVBInfo->P3d4, 0x11, temp);
-}
-
-static void XGI_SetCRT1Offset(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp, ah, al, temp2, i, DisplayUnit;
-
- /* GetOffset */
- temp = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
- temp >>= 8;
- temp = XGI330_ScreenOffset[temp];
-
- temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- temp2 &= InterlaceMode;
-
- if (temp2)
- temp <<= 1;
-
- temp2 = pVBInfo->ModeType - ModeEGA;
-
- switch (temp2) {
- case 0:
- temp2 = 1;
- break;
- case 1:
- temp2 = 2;
- break;
- case 2:
- temp2 = 4;
- break;
- case 3:
- temp2 = 4;
- break;
- case 4:
- temp2 = 6;
- break;
- case 5:
- temp2 = 8;
- break;
- default:
- break;
- }
-
- if ((ModeNo >= 0x26) && (ModeNo <= 0x28))
- temp = temp * temp2 + temp2 / 2;
- else
- temp *= temp2;
-
- /* SetOffset */
- DisplayUnit = temp;
- temp2 = temp;
- temp >>= 8; /* ah */
- temp &= 0x0F;
- i = xgifb_reg_get(pVBInfo->P3c4, 0x0E);
- i &= 0xF0;
- i |= temp;
- xgifb_reg_set(pVBInfo->P3c4, 0x0E, i);
-
- temp = (unsigned char)temp2;
- temp &= 0xFF; /* al */
- xgifb_reg_set(pVBInfo->P3d4, 0x13, temp);
-
- /* SetDisplayUnit */
- temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- temp2 &= InterlaceMode;
- if (temp2)
- DisplayUnit >>= 1;
-
- DisplayUnit <<= 5;
- ah = (DisplayUnit & 0xff00) >> 8;
- al = DisplayUnit & 0x00ff;
- if (al == 0)
- ah += 1;
- else
- ah += 2;
-
- if (HwDeviceExtension->jChipType >= XG20)
- if ((ModeNo == 0x4A) | (ModeNo == 0x49))
- ah -= 1;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x10, ah);
-}
-
-static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short VCLKIndex, modeflag;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /* 301b */
- if (pVBInfo->LCDResInfo != Panel_1024x768)
- /* LCDXlat2VCLK */
- VCLKIndex = VCLK108_2_315 + 5;
- else
- VCLKIndex = VCLK65_315 + 2; /* LCDXlat1VCLK */
- } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (pVBInfo->SetFlag & RPLLDIV2XO)
- VCLKIndex = TVCLKBASE_315_25 + HiTVVCLKDIV2;
- else
- VCLKIndex = TVCLKBASE_315_25 + HiTVVCLK;
-
- if (pVBInfo->SetFlag & TVSimuMode) {
- if (modeflag & Charx8Dot)
- VCLKIndex = TVCLKBASE_315_25 + HiTVSimuVCLK;
- else
- VCLKIndex = TVCLKBASE_315_25 + HiTVTextVCLK;
- }
-
- /* 301lv */
- if (pVBInfo->VBType & VB_SIS301LV) {
- if (pVBInfo->SetFlag & RPLLDIV2XO)
- VCLKIndex = YPbPr525iVCLK_2;
- else
- VCLKIndex = YPbPr525iVCLK;
- }
- } else if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->SetFlag & RPLLDIV2XO)
- VCLKIndex = TVCLKBASE_315_25 + TVVCLKDIV2;
- else
- VCLKIndex = TVCLKBASE_315_25 + TVVCLK;
- } else { /* for CRT2 */
- /* di+Ext_CRTVCLK */
- VCLKIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- VCLKIndex &= IndexMask;
- }
-
- return VCLKIndex;
-}
-
-static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char index, data;
- unsigned short vclkindex;
-
- if ((pVBInfo->IF_DEF_LVDS == 0) &&
- (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
- VB_SIS302LV | VB_XGI301C)) &&
- (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
- vclkindex = XGI_GetVCLK2Ptr(ModeIdIndex, RefreshRateTableIndex,
- pVBInfo);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
- xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
- data = XGI_VBVCLKData[vclkindex].Part4_A;
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
- data = XGI_VBVCLKData[vclkindex].Part4_B;
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
- xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
- } else {
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
- xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[index].SR2B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[index].SR2C);
- xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
- }
-
- if (HwDeviceExtension->jChipType >= XG20) {
- if (XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag &
- HalfDCLK) {
- data = xgifb_reg_get(pVBInfo->P3c4, 0x2B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x2C);
- index = data;
- index &= 0xE0;
- data &= 0x1F;
- data <<= 1;
- data += 1;
- data |= index;
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
- }
- }
-}
-
-static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char temp;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
- temp = (temp & 1) << 6;
- /* SR06[6] 18bit Dither */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp);
- /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
-}
-
-static void XGI_SetCRT1FIFO(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data;
-
- data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
- data &= 0xfe;
- xgifb_reg_set(pVBInfo->P3c4, 0x3D, data); /* disable auto-threshold */
-
- xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x34);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
- data &= 0xC0;
- xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x30);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
- data |= 0x01;
- xgifb_reg_set(pVBInfo->P3c4, 0x3D, data);
-
- if (HwDeviceExtension->jChipType == XG21)
- XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
-}
-
-static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data, data2 = 0;
- short VCLK;
-
- unsigned char index;
-
- index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= IndexMask;
- VCLK = XGI_VCLKData[index].CLOCK;
-
- data = xgifb_reg_get(pVBInfo->P3c4, 0x32);
- data &= 0xf3;
- if (VCLK >= 200)
- data |= 0x0c; /* VCLK > 200 */
-
- if (HwDeviceExtension->jChipType >= XG20)
- data &= ~0x04; /* 2 pixel mode */
-
- xgifb_reg_set(pVBInfo->P3c4, 0x32, data);
-
- if (HwDeviceExtension->jChipType < XG20) {
- data = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
- data &= 0xE7;
- if (VCLK < 200)
- data |= 0x10;
- xgifb_reg_set(pVBInfo->P3c4, 0x1F, data);
- }
-
- data2 = 0x00;
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x07, 0xFC, data2);
- if (HwDeviceExtension->jChipType >= XG27)
- xgifb_reg_and_or(pVBInfo->P3c4, 0x40, 0xFC, data2 & 0x03);
-}
-
-static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short data, data2, data3, infoflag = 0, modeflag, resindex,
- xres;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-
- if (xgifb_reg_get(pVBInfo->P3d4, 0x31) & 0x01)
- xgifb_reg_and_or(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
-
- data = infoflag;
- data2 = 0;
- data2 |= 0x02;
- data3 = pVBInfo->ModeType - ModeVGA;
- data3 <<= 2;
- data2 |= data3;
- data &= InterlaceMode;
-
- if (data)
- data2 |= 0x20;
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
-
- data = 0x0000;
- if (infoflag & InterlaceMode) {
- if (xres == 1024)
- data = 0x0035;
- else if (xres == 1280)
- data = 0x0048;
- }
-
- xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFF, data);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFC, 0);
-
- if (modeflag & HalfDCLK)
- xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xF7, 0x08);
-
- data2 = 0;
-
- if (modeflag & LineCompareOff)
- data2 |= 0x08;
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0F, ~0x48, data2);
- data = 0x60;
- data = data ^ 0x60;
- data = data ^ 0xA0;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data);
-
- XGI_SetVCLKState(HwDeviceExtension, RefreshRateTableIndex, pVBInfo);
-
- data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
-
- if (HwDeviceExtension->jChipType == XG27) {
- if (data & 0x40)
- data = 0x2c;
- else
- data = 0x6c;
- xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
- xgifb_reg_or(pVBInfo->P3d4, 0x51, 0x10);
- } else if (HwDeviceExtension->jChipType >= XG20) {
- if (data & 0x40)
- data = 0x33;
- else
- data = 0x73;
- xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
- xgifb_reg_set(pVBInfo->P3d4, 0x51, 0x02);
- } else {
- if (data & 0x40)
- data = 0x2c;
- else
- data = 0x6c;
- xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
- }
-}
-
-static void XGI_WriteDAC(unsigned short dl,
- unsigned short ah,
- unsigned short al,
- unsigned short dh,
- struct vb_device_info *pVBInfo)
-{
- unsigned short bh, bl;
-
- bh = ah;
- bl = al;
-
- if (dl != 0) {
- swap(bh, dh);
- if (dl == 1)
- swap(bl, dh);
- else
- swap(bl, bh);
- }
- outb((unsigned short)dh, pVBInfo->P3c9);
- outb((unsigned short)bh, pVBInfo->P3c9);
- outb((unsigned short)bl, pVBInfo->P3c9);
-}
-
-static void XGI_LoadDAC(struct vb_device_info *pVBInfo)
-{
- unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh;
- const unsigned short *table = XGINew_VGA_DAC;
-
- outb(0xFF, pVBInfo->P3c6);
- outb(0x00, pVBInfo->P3c8);
-
- for (i = 0; i < 16; i++) {
- data = table[i];
-
- for (k = 0; k < 3; k++) {
- data2 = 0;
-
- if (data & 0x01)
- data2 = 0x2A;
-
- if (data & 0x02)
- data2 += 0x15;
-
- outb(data2, pVBInfo->P3c9);
- data >>= 2;
- }
- }
-
- for (i = 16; i < 32; i++) {
- data = table[i];
-
- for (k = 0; k < 3; k++)
- outb(data, pVBInfo->P3c9);
- }
-
- si = 32;
-
- for (m = 0; m < 9; m++) {
- di = si;
- bx = si + 0x04;
- dl = 0;
-
- for (n = 0; n < 3; n++) {
- for (o = 0; o < 5; o++) {
- dh = table[si];
- ah = table[di];
- al = table[bx];
- si++;
- XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
- }
-
- si -= 2;
-
- for (o = 0; o < 3; o++) {
- dh = table[bx];
- ah = table[di];
- al = table[si];
- si--;
- XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
- }
-
- dl++;
- }
-
- si += 5;
- }
-}
-
-static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short resindex, xres, yres, modeflag;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
- /* si+Ext_ResInfo */
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
- xres = XGI330_ModeResInfo[resindex].HTotal;
- yres = XGI330_ModeResInfo[resindex].VTotal;
-
- if (modeflag & HalfDCLK)
- xres <<= 1;
-
- if (modeflag & DoubleScanMode)
- yres <<= 1;
-
- if (xres == 720)
- xres = 640;
-
- pVBInfo->VGAHDE = xres;
- pVBInfo->HDE = xres;
- pVBInfo->VGAVDE = yres;
- pVBInfo->VDE = yres;
-}
-
-static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short i, tempdx, tempbx, modeflag;
-
- tempbx = 0;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- i = 0;
-
- while (table[i].PANELID != 0xff) {
- tempdx = pVBInfo->LCDResInfo;
- if (tempbx & 0x0080) { /* OEMUtil */
- tempbx &= ~0x0080;
- tempdx = pVBInfo->LCDTypeInfo;
- }
-
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempdx &= ~PanelResInfo;
-
- if (table[i].PANELID == tempdx) {
- tempbx = table[i].MASK;
- tempdx = pVBInfo->LCDInfo;
-
- if (modeflag & HalfDCLK)
- tempdx |= SetLCDLowResolution;
-
- tempbx &= tempdx;
- if (tempbx == table[i].CAP)
- break;
- }
- i++;
- }
-
- return table[i].DATAPTR;
-}
-
-static struct SiS_TVData const *XGI_GetTVPtr(
- unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short i, tempdx, tempal, modeflag;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- tempal = tempal & 0x3f;
- tempdx = pVBInfo->TVInfo;
-
- if (pVBInfo->VBInfo & SetInSlaveMode)
- tempdx = tempdx | SetTVLockMode;
-
- if (modeflag & HalfDCLK)
- tempdx = tempdx | SetTVLowResolution;
-
- i = 0;
-
- while (XGI_TVDataTable[i].MASK != 0xffff) {
- if ((tempdx & XGI_TVDataTable[i].MASK) ==
- XGI_TVDataTable[i].CAP)
- break;
- i++;
- }
-
- return &XGI_TVDataTable[i].DATAPTR[tempal];
-}
-
-static void XGI_GetLVDSData(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- struct SiS_LVDSData const *LCDPtr;
-
- if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
- return;
-
- LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, pVBInfo);
- pVBInfo->VGAHT = LCDPtr->VGAHT;
- pVBInfo->VGAVT = LCDPtr->VGAVT;
- pVBInfo->HT = LCDPtr->LCDHT;
- pVBInfo->VT = LCDPtr->LCDVT;
-
- if (pVBInfo->LCDInfo & (SetLCDtoNonExpanding | EnableScalingLCD))
- return;
-
- if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
- (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
- pVBInfo->HDE = 1024;
- pVBInfo->VDE = 768;
- } else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
- (pVBInfo->LCDResInfo == Panel_1280x1024x75)) {
- pVBInfo->HDE = 1280;
- pVBInfo->VDE = 1024;
- } else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
- pVBInfo->HDE = 1400;
- pVBInfo->VDE = 1050;
- } else {
- pVBInfo->HDE = 1600;
- pVBInfo->VDE = 1200;
- }
-}
-
-static void XGI_ModCRT1Regs(unsigned short ModeIdIndex,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short i;
- struct XGI_LVDSCRT1HDataStruct const *LCDPtr = NULL;
- struct XGI_LVDSCRT1VDataStruct const *LCDPtr1 = NULL;
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeIdIndex,
- pVBInfo);
-
- for (i = 0; i < 8; i++)
- pVBInfo->TimingH.data[i] = LCDPtr[0].Reg[i];
- }
-
- XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeIdIndex,
- pVBInfo);
- for (i = 0; i < 7; i++)
- pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i];
- }
-
- XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
-}
-
-static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
-{
- unsigned char tempal, tempah, tempbl, i;
-
- tempah = xgifb_reg_get(pVBInfo->P3d4, 0x36);
- tempal = tempah & 0x0F;
- tempah = tempah & 0xF0;
- i = 0;
- tempbl = pVBInfo->LCDCapList[i].LCD_ID;
-
- while (tempbl != 0xFF) {
- if (tempbl & 0x80) { /* OEMUtil */
- tempal = tempah;
- tempbl = tempbl & ~(0x80);
- }
-
- if (tempal == tempbl)
- break;
-
- i++;
-
- tempbl = pVBInfo->LCDCapList[i].LCD_ID;
- }
-
- return i;
-}
-
-static unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo)
-{
- unsigned short tempah, tempal, tempbl, i;
-
- tempal = pVBInfo->LCDResInfo;
- tempah = pVBInfo->LCDTypeInfo;
-
- i = 0;
- tempbl = pVBInfo->LCDCapList[i].LCD_ID;
-
- while (tempbl != 0xFF) {
- if ((tempbl & 0x80) && (tempbl != 0x80)) {
- tempal = tempah;
- tempbl &= ~0x80;
- }
-
- if (tempal == tempbl)
- break;
-
- i++;
- tempbl = pVBInfo->LCDCapList[i].LCD_ID;
- }
-
- if (tempbl == 0xFF) {
- pVBInfo->LCDResInfo = Panel_1024x768;
- pVBInfo->LCDTypeInfo = 0;
- i = 0;
- }
-
- return i;
-}
-
-static void XGI_GetLCDSync(unsigned short *HSyncWidth,
- unsigned short *VSyncWidth,
- struct vb_device_info *pVBInfo)
-{
- unsigned short Index;
-
- Index = XGI_GetLCDCapPtr(pVBInfo);
- *HSyncWidth = pVBInfo->LCDCapList[Index].LCD_HSyncWidth;
- *VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth;
-}
-
-static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
- unsigned long temp, temp1, temp2, temp3, push3;
- struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, pVBInfo);
-
- XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
- push1 = tempbx;
- push2 = tempax;
-
- /* GetLCDResInfo */
- if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
- (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
- tempax = 1024;
- tempbx = 768;
- } else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
- (pVBInfo->LCDResInfo == Panel_1280x1024x75)) {
- tempax = 1280;
- tempbx = 1024;
- } else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
- tempax = 1400;
- tempbx = 1050;
- } else {
- tempax = 1600;
- tempbx = 1200;
- }
-
- if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
- pVBInfo->HDE = tempax;
- pVBInfo->VDE = tempbx;
- pVBInfo->VGAHDE = tempax;
- pVBInfo->VGAVDE = tempbx;
- }
-
- tempax = pVBInfo->HT;
-
- tempbx = LCDPtr1->LCDHDES;
-
- tempcx = pVBInfo->HDE;
- tempbx = tempbx & 0x0fff;
- tempcx += tempbx;
-
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
-
- tempcx >>= 3;
- tempbx >>= 3;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x16,
- (unsigned short)(tempbx & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x17,
- (unsigned short)(tempcx & 0xff));
-
- tempax = pVBInfo->HT;
-
- tempbx = LCDPtr1->LCDHRS;
-
- tempcx = push2;
-
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempcx = LCDPtr1->LCDHSync;
-
- tempcx += tempbx;
-
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- tempax = tempbx & 0x07;
- tempax >>= 5;
- tempcx >>= 3;
- tempbx >>= 3;
-
- tempcx &= 0x1f;
- tempax |= tempcx;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x15, tempax);
- xgifb_reg_set(pVBInfo->Part1Port, 0x14,
- (unsigned short)(tempbx & 0xff));
-
- tempax = pVBInfo->VT;
- tempbx = LCDPtr1->LCDVDES;
- tempcx = pVBInfo->VDE;
-
- tempbx = tempbx & 0x0fff;
- tempcx += tempbx;
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
- (unsigned short)(tempbx & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
- (unsigned short)(tempcx & 0xff));
-
- tempbx = (tempbx >> 8) & 0x07;
- tempcx = (tempcx >> 8) & 0x07;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
- (unsigned short)((tempcx << 3) | tempbx));
-
- tempax = pVBInfo->VT;
- tempbx = LCDPtr1->LCDVRS;
-
- tempcx = push1;
-
- if (pVBInfo->LCDInfo & EnableScalingLCD)
- tempcx = LCDPtr1->LCDVSync;
-
- tempcx += tempbx;
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x18,
- (unsigned short)(tempbx & 0xff));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
- (unsigned short)(tempcx & 0x0f));
-
- tempax = ((tempbx >> 8) & 0x07) << 3;
-
- tempbx = pVBInfo->VGAVDE;
- if (tempbx != pVBInfo->VDE)
- tempax |= 0x40;
-
- if (pVBInfo->LCDInfo & XGI_EnableLVDSDDA)
- tempax |= 0x40;
-
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07, tempax);
-
- tempbx = pVBInfo->VDE;
- tempax = pVBInfo->VGAVDE;
-
- temp = tempax; /* 0430 ylshieh */
- temp1 = (temp << 18) / tempbx;
-
- tempdx = (unsigned short)((temp << 18) % tempbx);
-
- if (tempdx != 0)
- temp1 += 1;
-
- temp2 = temp1;
- push3 = temp2;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x37, (unsigned short)(temp2 & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x36, (unsigned short)((temp2 >> 8) & 0xff));
-
- tempbx = (unsigned short)(temp2 >> 16);
- tempax = tempbx & 0x03;
-
- tempbx = pVBInfo->VGAVDE;
- if (tempbx == pVBInfo->VDE)
- tempax |= 0x04;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x35, tempax);
-
- if (pVBInfo->VBType & VB_XGI301C) {
- temp2 = push3;
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x3c,
- (unsigned short)(temp2 & 0xff));
- xgifb_reg_set(pVBInfo->Part4Port,
- 0x3b,
- (unsigned short)((temp2 >> 8) &
- 0xff));
- tempbx = (unsigned short)(temp2 >> 16);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x3a, ~0xc0,
- (unsigned short)((tempbx & 0xff) << 6));
-
- tempcx = pVBInfo->VGAVDE;
- if (tempcx == pVBInfo->VDE)
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x30, ~0x0c, 0x00);
- else
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x30, ~0x0c, 0x08);
- }
-
- tempcx = pVBInfo->VGAHDE;
- tempbx = pVBInfo->HDE;
-
- temp1 = tempcx << 16;
-
- tempax = (unsigned short)(temp1 / tempbx);
-
- if ((tempbx & 0xffff) == (tempcx & 0xffff))
- tempax = 65535;
-
- temp3 = tempax;
- temp1 = pVBInfo->VGAHDE << 16;
-
- temp1 /= temp3;
- temp3 <<= 16;
- temp1 -= 1;
-
- temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
-
- tempax = (unsigned short)(temp3 & 0xff);
- xgifb_reg_set(pVBInfo->Part1Port, 0x1f, tempax);
-
- temp1 = pVBInfo->VGAVDE << 18;
- temp1 = temp1 / push3;
- tempbx = (unsigned short)(temp1 & 0xffff);
-
- if (pVBInfo->LCDResInfo == Panel_1024x768)
- tempbx -= 1;
-
- tempax = ((tempbx >> 8) & 0xff) << 3;
- tempax |= (unsigned short)((temp3 >> 8) & 0x07);
- xgifb_reg_set(pVBInfo->Part1Port, 0x20,
- (unsigned short)(tempax & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x21,
- (unsigned short)(tempbx & 0xff));
-
- temp3 >>= 16;
-
- if (modeflag & HalfDCLK)
- temp3 >>= 1;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x22,
- (unsigned short)((temp3 >> 8) & 0xff));
- xgifb_reg_set(pVBInfo->Part1Port, 0x23,
- (unsigned short)(temp3 & 0xff));
-}
-
-/*
- * Function : XGI_GETLCDVCLKPtr
- * Input :
- * Output : al -> VCLK Index
- * Description :
- */
-static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
- struct vb_device_info *pVBInfo)
-{
- unsigned short index;
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- index = XGI_GetLCDCapPtr1(pVBInfo);
-
- if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */
- *di_0 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData1;
- *di_1 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData2;
- } else { /* LCDA */
- *di_0 = pVBInfo->LCDCapList[index].LCDA_VCLKData1;
- *di_1 = pVBInfo->LCDCapList[index].LCDA_VCLKData2;
- }
- }
-}
-
-static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short index, modeflag;
- unsigned char tempal;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if ((pVBInfo->SetFlag & ProgrammingCRT2) &&
- !(pVBInfo->LCDInfo & EnableScalingLCD)) { /* {LCDA/LCDB} */
- index = XGI_GetLCDCapPtr(pVBInfo);
- tempal = pVBInfo->LCDCapList[index].LCD_VCLK;
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
- return tempal;
-
- /* {TV} */
- if (pVBInfo->VBType &
- (VB_SIS301B |
- VB_SIS302B |
- VB_SIS301LV |
- VB_SIS302LV |
- VB_XGI301C)) {
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- tempal = TVCLKBASE_315 + HiTVVCLKDIV2;
- if (!(pVBInfo->TVInfo & RPLLDIV2XO))
- tempal = TVCLKBASE_315 + HiTVVCLK;
- if (pVBInfo->TVInfo & TVSimuMode) {
- tempal = TVCLKBASE_315 + HiTVSimuVCLK;
- if (!(modeflag & Charx8Dot))
- tempal = TVCLKBASE_315 +
- HiTVTextVCLK;
- }
- return tempal;
- }
-
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- return XGI_YPbPr750pVCLK;
-
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- return YPbPr525pVCLK;
-
- tempal = NTSC1024VCLK;
-
- if (!(pVBInfo->TVInfo & NTSC1024x768)) {
- tempal = TVCLKBASE_315 + TVVCLKDIV2;
- if (!(pVBInfo->TVInfo & RPLLDIV2XO))
- tempal = TVCLKBASE_315 + TVVCLK;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- return tempal;
- }
- } /* {End of VB} */
-
- inb((pVBInfo->P3ca + 0x02));
- return XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-}
-
-static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
- unsigned char *di_1, struct vb_device_info *pVBInfo)
-{
- if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B
- | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
- if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
- (pVBInfo->SetFlag & ProgrammingCRT2)) {
- *di_0 = XGI_VBVCLKData[tempal].Part4_A;
- *di_1 = XGI_VBVCLKData[tempal].Part4_B;
- }
- } else {
- *di_0 = XGI_VCLKData[tempal].SR2B;
- *di_1 = XGI_VCLKData[tempal].SR2C;
- }
-}
-
-static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char di_0, di_1, tempal;
- int i;
-
- tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
- XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
- XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
-
- for (i = 0; i < 4; i++) {
- xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30,
- (unsigned short)(0x10 * i));
- if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
- !(pVBInfo->VBInfo & SetInSlaveMode)) {
- xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0);
- xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1);
- } else {
- xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
- xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
- }
- }
-}
-
-static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo)
-{
- unsigned short tempcl, tempch, temp, tempbl, tempax;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- tempcl = 0;
- tempch = 0;
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x01);
-
- if (!(temp & 0x20)) {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x17);
- if (temp & 0x80) {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x53);
- if (!(temp & 0x40))
- tempcl |= ActiveCRT1;
- }
- }
-
- temp = xgifb_reg_get(pVBInfo->Part1Port, 0x2e);
- temp &= 0x0f;
-
- if (!(temp == 0x08)) {
- /* Check ChannelA */
- tempax = xgifb_reg_get(pVBInfo->Part1Port, 0x13);
- if (tempax & 0x04)
- tempcl = tempcl | ActiveLCD;
-
- temp &= 0x05;
-
- if (!(tempcl & ActiveLCD)) {
- if (temp == 0x01)
- tempcl |= ActiveCRT2;
- }
-
- if (temp == 0x04)
- tempcl |= ActiveLCD;
-
- if (temp == 0x05) {
- temp = xgifb_reg_get(pVBInfo->Part2Port, 0x00);
-
- if (!(temp & 0x08))
- tempch |= ActiveAVideo;
-
- if (!(temp & 0x04))
- tempch |= ActiveSVideo;
-
- if (temp & 0x02)
- tempch |= ActiveSCART;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (temp & 0x01)
- tempch |= ActiveHiTV;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- temp = xgifb_reg_get(
- pVBInfo->Part2Port,
- 0x4d);
-
- if (temp & 0x10)
- tempch |= ActiveYPbPr;
- }
-
- if (tempch != 0)
- tempcl |= ActiveTV;
- }
- }
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
- if (tempcl & ActiveLCD) {
- if ((pVBInfo->SetFlag & ReserveTVOption)) {
- if (temp & ActiveTV)
- tempcl |= ActiveTV;
- }
- }
- temp = tempcl;
- tempbl = ~XGI_ModeSwitchStatus;
- xgifb_reg_and_or(pVBInfo->P3d4, 0x3d, tempbl, temp);
-
- if (!(pVBInfo->SetFlag & ReserveTVOption))
- xgifb_reg_set(pVBInfo->P3d4, 0x3e, tempch);
- }
-}
-
-void XGI_GetVBType(struct vb_device_info *pVBInfo)
-{
- unsigned short flag, tempbx, tempah;
-
- tempbx = VB_SIS302B;
- flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
- if (flag == 0x02)
- goto finish;
-
- tempbx = VB_SIS301;
- flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
- if (flag < 0xB0)
- goto finish;
-
- tempbx = VB_SIS301B;
- if (flag < 0xC0)
- goto bigger_than_0xB0;
-
- tempbx = VB_XGI301C;
- if (flag < 0xD0)
- goto bigger_than_0xB0;
-
- tempbx = VB_SIS301LV;
- if (flag < 0xE0)
- goto bigger_than_0xB0;
-
- tempbx = VB_SIS302LV;
- tempah = xgifb_reg_get(pVBInfo->Part4Port, 0x39);
- if (tempah != 0xFF)
- tempbx = VB_XGI301C;
-
-bigger_than_0xB0:
- if (tempbx & (VB_SIS301B | VB_SIS302B)) {
- flag = xgifb_reg_get(pVBInfo->Part4Port, 0x23);
- if (!(flag & 0x02))
- tempbx = tempbx | VB_NoLCD;
- }
-
-finish:
- pVBInfo->VBType = tempbx;
-}
-
-static void XGI_GetVBInfo(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax, push, tempbx, temp, modeflag;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- pVBInfo->SetFlag = 0;
- pVBInfo->ModeType = modeflag & ModeTypeMask;
- tempbx = 0;
-
- if (!(pVBInfo->VBType & 0xFFFF))
- return;
-
- /* Check Display Device */
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x30);
- tempbx = tempbx | temp;
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x31);
- push = temp;
- push <<= 8;
- tempax = temp << 8;
- tempbx = tempbx | tempax;
- temp = SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA
- | SetInSlaveMode | DisableCRT2Display;
- temp = 0xFFFF ^ temp;
- tempbx &= temp;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
-
- if (pVBInfo->VBType & (VB_SIS302B | VB_SIS301LV | VB_SIS302LV |
- VB_XGI301C)) {
- if (temp & EnableDualEdge) {
- tempbx |= SetCRT2ToDualEdge;
- if (temp & SetToLCDA)
- tempbx |= XGI_SetCRT2ToLCDA;
- }
- }
-
- if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
- if (temp & SetYPbPr) {
- /* shampoo add for new scratch */
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
- temp &= YPbPrMode;
- tempbx |= SetCRT2ToHiVision;
-
- if (temp != YPbPrMode1080i) {
- tempbx &= ~SetCRT2ToHiVision;
- tempbx |= SetCRT2ToYPbPr525750;
- }
- }
- }
-
- tempax = push; /* restore CR31 */
-
- temp = 0x09FC;
-
- if (!(tempbx & temp)) {
- tempax |= DisableCRT2Display;
- tempbx = 0;
- }
-
- if (!(pVBInfo->VBType & VB_NoLCD)) {
- if (tempbx & XGI_SetCRT2ToLCDA) {
- if (tempbx & SetSimuScanMode)
- tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
- SwitchCRT2));
- else
- tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
- SetCRT2ToTV | SwitchCRT2));
- }
- }
-
- /* shampoo add */
- /* for driver abnormal */
- if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
- if (tempbx & SetCRT2ToRAMDAC) {
- tempbx &= (0xFF00 | SetCRT2ToRAMDAC |
- SwitchCRT2 | SetSimuScanMode);
- tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
- }
- }
-
- if (!(pVBInfo->VBType & VB_NoLCD)) {
- if (tempbx & SetCRT2ToLCD) {
- tempbx &= (0xFF00 | SetCRT2ToLCD | SwitchCRT2 |
- SetSimuScanMode);
- tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
- }
- }
-
- if (tempbx & SetCRT2ToSCART) {
- tempbx &= (0xFF00 | SetCRT2ToSCART | SwitchCRT2 |
- SetSimuScanMode);
- tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
- }
-
- if (tempbx & SetCRT2ToYPbPr525750)
- tempbx &= (0xFF00 | SwitchCRT2 | SetSimuScanMode);
-
- if (tempbx & SetCRT2ToHiVision)
- tempbx &= (0xFF00 | SetCRT2ToHiVision | SwitchCRT2 |
- SetSimuScanMode);
-
- if (tempax & DisableCRT2Display) { /* Set Display Device Info */
- if (!(tempbx & (SwitchCRT2 | SetSimuScanMode)))
- tempbx = DisableCRT2Display;
- }
-
- if (!(tempbx & DisableCRT2Display)) {
- if (!(tempbx & DriverMode) || !(modeflag & CRT2Mode)) {
- if (!(tempbx & XGI_SetCRT2ToLCDA))
- tempbx |= (SetInSlaveMode | SetSimuScanMode);
- }
-
- /* LCD+TV can't support in slave mode
- * (Force LCDA+TV->LCDB)
- */
- if ((tempbx & SetInSlaveMode) && (tempbx & XGI_SetCRT2ToLCDA)) {
- tempbx ^= (SetCRT2ToLCD | XGI_SetCRT2ToLCDA |
- SetCRT2ToDualEdge);
- pVBInfo->SetFlag |= ReserveTVOption;
- }
- }
-
- pVBInfo->VBInfo = tempbx;
-}
-
-static void XGI_GetTVInfo(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx = 0, resinfo = 0, modeflag, index1;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
- tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
- if (tempbx & TVSetPAL) {
- tempbx &= (SetCHTVOverScan |
- TVSetPALM |
- TVSetPALN |
- TVSetPAL);
- if (tempbx & TVSetPALM)
- /* set to NTSC if PAL-M */
- tempbx &= ~TVSetPAL;
- } else {
- tempbx &= (SetCHTVOverScan |
- TVSetNTSCJ |
- TVSetPAL);
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToSCART)
- tempbx |= TVSetPAL;
-
- if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- index1 = xgifb_reg_get(pVBInfo->P3d4, 0x35);
- index1 &= YPbPrMode;
-
- if (index1 == YPbPrMode525i)
- tempbx |= TVSetYPbPr525i;
-
- if (index1 == YPbPrMode525p)
- tempbx = tempbx | TVSetYPbPr525p;
- if (index1 == YPbPrMode750p)
- tempbx = tempbx | TVSetYPbPr750p;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision)
- tempbx = tempbx | TVSetHiVision | TVSetPAL;
-
- if ((pVBInfo->VBInfo & SetInSlaveMode) &&
- (!(pVBInfo->VBInfo & SetNotSimuMode)))
- tempbx |= TVSimuMode;
-
- if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8)) {
- /* NTSC 1024x768, */
- tempbx |= NTSC1024x768;
- }
-
- tempbx |= RPLLDIV2XO;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (pVBInfo->VBInfo & SetInSlaveMode)
- tempbx &= (~RPLLDIV2XO);
- } else if (tempbx & (TVSetYPbPr525p | TVSetYPbPr750p)) {
- tempbx &= (~RPLLDIV2XO);
- } else if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B |
- VB_SIS301LV | VB_SIS302LV |
- VB_XGI301C))) {
- if (tempbx & TVSimuMode)
- tempbx &= (~RPLLDIV2XO);
- }
- }
- pVBInfo->TVInfo = tempbx;
-}
-
-static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp, tempax, tempbx, resinfo = 0, LCDIdIndex;
-
- pVBInfo->LCDResInfo = 0;
- pVBInfo->LCDTypeInfo = 0;
- pVBInfo->LCDInfo = 0;
-
- /* si+Ext_ResInfo */
- resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
- tempbx = temp & 0x0F;
-
- if (tempbx == 0)
- tempbx = Panel_1024x768; /* default */
-
- /* LCD75 */
- if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) {
- if (pVBInfo->VBInfo & DriverMode) {
- tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33);
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
- tempax &= 0x0F;
- else
- tempax >>= 4;
-
- if ((resinfo == 6) || (resinfo == 9)) {
- if (tempax >= 3)
- tempbx |= PanelRef75Hz;
- } else if ((resinfo == 7) || (resinfo == 8)) {
- if (tempax >= 4)
- tempbx |= PanelRef75Hz;
- }
- }
- }
-
- pVBInfo->LCDResInfo = tempbx;
-
- /* End of LCD75 */
-
- if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
- return 0;
-
- tempbx = 0;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
-
- temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
-
- tempbx |= temp;
-
- LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
-
- tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability;
-
- if (((pVBInfo->VBType & VB_SIS302LV) ||
- (pVBInfo->VBType & VB_XGI301C)) && (tempax & XGI_LCDDualLink))
- tempbx |= SetLCDDualLink;
-
- if ((pVBInfo->LCDResInfo == Panel_1400x1050) &&
- (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) &&
- !(tempbx & EnableScalingLCD))
- /*
- * set to center in 1280x1024 LCDB
- * for Panel_1400x1050
- */
- tempbx |= SetLCDtoNonExpanding;
-
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (pVBInfo->VBInfo & SetNotSimuMode)
- tempbx |= XGI_LCDVESATiming;
- } else {
- tempbx |= XGI_LCDVESATiming;
- }
-
- pVBInfo->LCDInfo = tempbx;
-
- return 1;
-}
-
-unsigned char XGI_SearchModeID(unsigned short ModeNo,
- unsigned short *ModeIdIndex)
-{
- for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
- if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
- break;
- if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
- return 0;
- }
-
- return 1;
-}
-
-static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
-{
- unsigned char ujRet = 0;
- unsigned char i = 0;
-
- for (i = 0; i < 8; i++) {
- ujRet <<= 1;
- ujRet |= (ujDate >> i) & 1;
- }
-
- return ujRet;
-}
-
-/*
- * output
- * bl[5] : LVDS signal
- * bl[1] : LVDS backlight
- * bl[0] : LVDS VDD
- */
-static unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x23); /* enable GPIO write */
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
-
- temp = XG21GPIODataTransfer(temp);
- temp &= 0x23;
- xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
- return temp;
-}
-
-/*
- * output
- * bl[5] : LVDS signal
- * bl[1] : LVDS backlight
- * bl[0] : LVDS VDD
- */
-static unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, CRB4, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x0C); /* enable GPIO write */
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
-
- temp &= 0x0C;
- temp >>= 2;
- xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
- CRB4 = xgifb_reg_get(pVBInfo->P3d4, 0xB4);
- temp |= ((CRB4 & 0x04) << 3);
- return temp;
-}
-
-/*
- * input
- * bl[5] : 1;LVDS signal on
- * bl[1] : 1;LVDS backlight on
- * bl[0] : 1:LVDS VDD on
- * bh: 100000b : clear bit 5, to set bit5
- * 000010b : clear bit 1, to set bit1
- * 000001b : clear bit 0, to set bit0
- */
-static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
- struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- tempbh &= 0x23;
- tempbl &= 0x23;
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
-
- if (tempbh & 0x20) {
- temp = (tempbl >> 4) & 0x02;
-
- /* CR B4[1] */
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
- }
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
-
- temp = XG21GPIODataTransfer(temp);
- temp &= ~tempbh;
- temp |= tempbl;
- xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
-}
-
-static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
- struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
- unsigned short tempbh0, tempbl0;
-
- tempbh0 = tempbh;
- tempbl0 = tempbl;
- tempbh0 &= 0x20;
- tempbl0 &= 0x20;
- tempbh0 >>= 3;
- tempbl0 >>= 3;
-
- if (tempbh & 0x20) {
- temp = (tempbl >> 4) & 0x02;
-
- /* CR B4[1] */
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
- }
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- tempbh &= 0x03;
- tempbl &= 0x03;
- tempbh <<= 2;
- tempbl <<= 2; /* GPIOC,GPIOD */
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
-}
-
-static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *pXGIHWDE,
- struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00);
- if (pXGIHWDE->jChipType == XG21) {
- if (pVBInfo->IF_DEF_LVDS == 1) {
- if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
- /* LVDS VDD on */
- XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S2);
- }
- if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
- /* LVDS signal on */
- XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S3);
- /* LVDS backlight on */
- XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo);
- } else {
- /* DVO/DVI signal on */
- XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
- }
- }
-
- if (pXGIHWDE->jChipType == XG27) {
- if (pVBInfo->IF_DEF_LVDS == 1) {
- if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
- /* LVDS VDD on */
- XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S2);
- }
- if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
- /* LVDS signal on */
- XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S3);
- /* LVDS backlight on */
- XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo);
- } else {
- /* DVO/DVI signal on */
- XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
- }
- }
-}
-
-void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *pXGIHWDE,
- struct vb_device_info *pVBInfo)
-{
- if (pXGIHWDE->jChipType == XG21) {
- if (pVBInfo->IF_DEF_LVDS == 1) {
- /* LVDS backlight off */
- XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S3);
- } else {
- /* DVO/DVI signal off */
- XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo);
- }
- }
-
- if (pXGIHWDE->jChipType == XG27) {
- if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
- /* LVDS backlight off */
- XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo);
- mdelay(xgifb_info->lvds_data.PSC_S3);
- }
-
- if (pVBInfo->IF_DEF_LVDS == 0) {
- /* DVO/DVI signal off */
- XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo);
- }
- }
-
- xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
-}
-
-static void XGI_WaitDisply(struct vb_device_info *pVBInfo)
-{
- while ((inb(pVBInfo->P3da) & 0x01))
- break;
-
- while (!(inb(pVBInfo->P3da) & 0x01))
- break;
-}
-
-static void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
-}
-
-static void XGI_SaveCRT2Info(unsigned short ModeNo,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp1, temp2;
-
- /* reserve CR34 for CRT1 Mode No */
- xgifb_reg_set(pVBInfo->P3d4, 0x34, ModeNo);
- temp1 = (pVBInfo->VBInfo & SetInSlaveMode) >> 8;
- temp2 = ~(SetInSlaveMode >> 8);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1);
-}
-
-static void XGI_GetCRT2ResInfo(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short xres, yres, modeflag, resindex;
-
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if (modeflag & HalfDCLK)
- xres *= 2;
-
- if (modeflag & DoubleScanMode)
- yres *= 2;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
- goto exit;
-
- if (pVBInfo->LCDResInfo == Panel_1600x1200) {
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (yres == 1024)
- yres = 1056;
- }
- }
-
- if (pVBInfo->LCDResInfo == Panel_1280x1024) {
- if (yres == 400)
- yres = 405;
- else if (yres == 350)
- yres = 360;
-
- if (pVBInfo->LCDInfo & XGI_LCDVESATiming) {
- if (yres == 360)
- yres = 375;
- }
- }
-
- if (pVBInfo->LCDResInfo == Panel_1024x768) {
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (!(pVBInfo->LCDInfo & LCDNonExpanding)) {
- if (yres == 350)
- yres = 357;
- else if (yres == 400)
- yres = 420;
- else if (yres == 480)
- yres = 525;
- }
- }
- }
-
- if (xres == 720)
- xres = 640;
-
-exit:
- pVBInfo->VGAHDE = xres;
- pVBInfo->HDE = xres;
- pVBInfo->VGAVDE = yres;
- pVBInfo->VDE = yres;
-}
-
-static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
-{
- if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) &&
- (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */
- return 1;
-
- return 0;
-}
-
-static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
- CRT1Index;
-
- pVBInfo->RVBHCMAX = 1;
- pVBInfo->RVBHCFACT = 1;
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- temp1 = (unsigned short)XGI_CRT1Table[CRT1Index].CR[0];
- temp2 = (unsigned short)XGI_CRT1Table[CRT1Index].CR[5];
- tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
- tempbx = (unsigned short)XGI_CRT1Table[CRT1Index].CR[8];
- tempcx = (unsigned short)XGI_CRT1Table[CRT1Index].CR[14] << 8;
- tempcx &= 0x0100;
- tempcx <<= 2;
- tempbx |= tempcx;
- temp1 = (unsigned short)XGI_CRT1Table[CRT1Index].CR[9];
-
- if (temp1 & 0x01)
- tempbx |= 0x0100;
-
- if (temp1 & 0x20)
- tempbx |= 0x0200;
- tempax += 5;
-
- if (modeflag & Charx8Dot)
- tempax *= 8;
- else
- tempax *= 9;
-
- pVBInfo->VGAHT = tempax;
- pVBInfo->HT = tempax;
- tempbx++;
- pVBInfo->VGAVT = tempbx;
- pVBInfo->VT = tempbx;
-}
-
-static void XGI_GetCRT2Data(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax = 0, tempbx = 0, modeflag, resinfo;
-
- struct SiS_LCDData const *LCDPtr = NULL;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- pVBInfo->NewFlickerMode = 0;
- pVBInfo->RVBHRS = 50;
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
- XGI_GetRAMDAC2DATA(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- return;
- }
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex,
- pVBInfo);
-
- pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
- pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
- pVBInfo->VGAHT = LCDPtr->VGAHT;
- pVBInfo->VGAVT = LCDPtr->VGAVT;
- pVBInfo->HT = LCDPtr->LCDHT;
- pVBInfo->VT = LCDPtr->LCDVT;
-
- if (pVBInfo->LCDResInfo == Panel_1024x768) {
- tempax = 1024;
- tempbx = 768;
-
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (pVBInfo->VGAVDE == 357)
- tempbx = 527;
- else if (pVBInfo->VGAVDE == 420)
- tempbx = 620;
- else if (pVBInfo->VGAVDE == 525)
- tempbx = 775;
- else if (pVBInfo->VGAVDE == 600)
- tempbx = 775;
- }
- } else if (pVBInfo->LCDResInfo == Panel_1024x768x75) {
- tempax = 1024;
- tempbx = 768;
- } else if (pVBInfo->LCDResInfo == Panel_1280x1024) {
- tempax = 1280;
- if (pVBInfo->VGAVDE == 360)
- tempbx = 768;
- else if (pVBInfo->VGAVDE == 375)
- tempbx = 800;
- else if (pVBInfo->VGAVDE == 405)
- tempbx = 864;
- else
- tempbx = 1024;
- } else if (pVBInfo->LCDResInfo == Panel_1280x1024x75) {
- tempax = 1280;
- tempbx = 1024;
- } else if (pVBInfo->LCDResInfo == Panel_1280x960) {
- tempax = 1280;
- if (pVBInfo->VGAVDE == 350)
- tempbx = 700;
- else if (pVBInfo->VGAVDE == 400)
- tempbx = 800;
- else if (pVBInfo->VGAVDE == 1024)
- tempbx = 960;
- else
- tempbx = 960;
- } else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
- tempax = 1400;
- tempbx = 1050;
-
- if (pVBInfo->VGAVDE == 1024) {
- tempax = 1280;
- tempbx = 1024;
- }
- } else if (pVBInfo->LCDResInfo == Panel_1600x1200) {
- tempax = 1600;
- tempbx = 1200; /* alan 10/14/2003 */
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (pVBInfo->VGAVDE == 350)
- tempbx = 875;
- else if (pVBInfo->VGAVDE == 400)
- tempbx = 1000;
- }
- }
-
- if (pVBInfo->LCDInfo & LCDNonExpanding) {
- tempax = pVBInfo->VGAHDE;
- tempbx = pVBInfo->VGAVDE;
- }
-
- pVBInfo->HDE = tempax;
- pVBInfo->VDE = tempbx;
- return;
- }
-
- if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
- struct SiS_TVData const *TVPtr;
-
- TVPtr = XGI_GetTVPtr(ModeIdIndex, RefreshRateTableIndex,
- pVBInfo);
-
- pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
- pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT;
- pVBInfo->VGAHT = TVPtr->VGAHT;
- pVBInfo->VGAVT = TVPtr->VGAVT;
- pVBInfo->HDE = TVPtr->TVHDE;
- pVBInfo->VDE = TVPtr->TVVDE;
- pVBInfo->RVBHRS = TVPtr->RVBHRS;
- pVBInfo->NewFlickerMode = TVPtr->FlickerMode;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (resinfo == 0x08)
- pVBInfo->NewFlickerMode = 0x40;
- else if (resinfo == 0x09)
- pVBInfo->NewFlickerMode = 0x40;
- else if (resinfo == 0x12)
- pVBInfo->NewFlickerMode = 0x40;
-
- if (pVBInfo->VGAVDE == 350)
- pVBInfo->TVInfo |= TVSimuMode;
-
- tempax = ExtHiTVHT;
- tempbx = ExtHiTVVT;
-
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (pVBInfo->TVInfo & TVSimuMode) {
- tempax = StHiTVHT;
- tempbx = StHiTVVT;
-
- if (!(modeflag & Charx8Dot)) {
- tempax = StHiTextTVHT;
- tempbx = StHiTextTVVT;
- }
- }
- }
- } else if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- if (pVBInfo->TVInfo & TVSetYPbPr750p) {
- tempax = YPbPrTV750pHT; /* Ext750pTVHT */
- tempbx = YPbPrTV750pVT; /* Ext750pTVVT */
- }
-
- if (pVBInfo->TVInfo & TVSetYPbPr525p) {
- tempax = YPbPrTV525pHT; /* Ext525pTVHT */
- tempbx = YPbPrTV525pVT; /* Ext525pTVVT */
- } else if (pVBInfo->TVInfo & TVSetYPbPr525i) {
- tempax = YPbPrTV525iHT; /* Ext525iTVHT */
- tempbx = YPbPrTV525iVT; /* Ext525iTVVT */
- if (pVBInfo->TVInfo & NTSC1024x768)
- tempax = NTSC1024x768HT;
- }
- } else {
- tempax = PALHT;
- tempbx = PALVT;
- if (!(pVBInfo->TVInfo & TVSetPAL)) {
- tempax = NTSCHT;
- tempbx = NTSCVT;
- if (pVBInfo->TVInfo & NTSC1024x768)
- tempax = NTSC1024x768HT;
- }
- }
-
- pVBInfo->HT = tempax;
- pVBInfo->VT = tempbx;
- }
-}
-
-static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char di_0, di_1, tempal;
-
- tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
- XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
- XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
-
- if (pVBInfo->VBType & VB_SIS301) { /* shampoo 0129 */
- /* 301 */
- xgifb_reg_set(pVBInfo->Part4Port, 0x0A, 0x10);
- xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
- xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
- } else { /* 301b/302b/301lv/302lv */
- xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
- xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
- }
-
- xgifb_reg_set(pVBInfo->Part4Port, 0x00, 0x12);
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
- xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x28);
- else
- xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08);
-}
-
-static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex)
-{
- unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
- short index;
- unsigned short modeflag;
-
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- index = (modeflag & ModeTypeMask) - ModeEGA;
-
- if (index < 0)
- index = 0;
-
- return ColorDepth[index];
-}
-
-static unsigned short XGI_GetOffset(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex)
-{
- unsigned short temp, colordepth, modeinfo, index, infoflag,
- ColorDepth[] = { 0x01, 0x02, 0x04 };
-
- modeinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
- infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-
- index = (modeinfo >> 8) & 0xFF;
-
- temp = XGI330_ScreenOffset[index];
-
- if (infoflag & InterlaceMode)
- temp <<= 1;
-
- colordepth = XGI_GetColorDepth(ModeIdIndex);
-
- if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
- temp = ModeNo - 0x7C;
- colordepth = ColorDepth[temp];
- temp = 0x6B;
- if (infoflag & InterlaceMode)
- temp <<= 1;
- }
- return temp * colordepth;
-}
-
-static void XGI_SetCRT2Offset(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short offset;
- unsigned char temp;
-
- if (pVBInfo->VBInfo & SetInSlaveMode)
- return;
-
- offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex);
- temp = (unsigned char)(offset & 0xFF);
- xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
- temp = (unsigned char)((offset & 0xFF00) >> 8);
- xgifb_reg_set(pVBInfo->Part1Port, 0x09, temp);
- temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
- xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
-}
-
-static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
-{
- /* threshold high ,disable auto threshold */
- xgifb_reg_set(pVBInfo->Part1Port, 0x01, 0x3B);
- /* threshold low default 04h */
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x02, ~(0x3F), 0x04);
-}
-
-static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- u8 tempcx;
-
- XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetCRT2FIFO(pVBInfo);
-
- for (tempcx = 4; tempcx < 7; tempcx++)
- xgifb_reg_set(pVBInfo->Part1Port, tempcx, 0x0);
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x50, 0x00);
- xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
-}
-
-static void XGI_SetGroup1(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
- pushbx = 0, CRT1Index, modeflag;
-
- CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- /* bainy change table name */
- if (modeflag & HalfDCLK) {
- /* BTVGA2HT 0x08,0x09 */
- temp = (pVBInfo->VGAHT / 2 - 1) & 0x0FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
- temp = (((pVBInfo->VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
- /* BTVGA2HDEE 0x0A,0x0C */
- temp = (pVBInfo->VGAHDE / 2 + 16) & 0x0FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
- tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
- pushbx = pVBInfo->VGAHDE / 2 + 16;
- tempcx >>= 1;
- tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
- tempcx += tempbx;
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
- tempbx = XGI_CRT1Table[CRT1Index].CR[4];
- tempbx |= ((XGI_CRT1Table[CRT1Index].CR[14] &
- 0xC0) << 2);
- tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
- tempcx = XGI_CRT1Table[CRT1Index].CR[5];
- tempcx &= 0x1F;
- temp = XGI_CRT1Table[CRT1Index].CR[15];
- temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
- tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
- }
-
- tempbx += 4;
- tempcx += 4;
-
- if (tempcx > (pVBInfo->VGAHT / 2))
- tempcx = pVBInfo->VGAHT / 2;
-
- temp = tempbx & 0x00FF;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
- } else {
- temp = (pVBInfo->VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
- xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
- temp = (((pVBInfo->VGAHT - 1) & 0xFF00) >> 8) << 4;
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
- /* BTVGA2HDEE 0x0A,0x0C */
- temp = (pVBInfo->VGAHDE + 16) & 0x0FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
- tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
- pushbx = pVBInfo->VGAHDE + 16;
- tempcx >>= 1;
- tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
- tempcx += tempbx;
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
- tempbx = XGI_CRT1Table[CRT1Index].CR[3];
- tempbx |= ((XGI_CRT1Table[CRT1Index].CR[5] &
- 0xC0) << 2);
- tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
- tempcx = XGI_CRT1Table[CRT1Index].CR[4];
- tempcx &= 0x1F;
- temp = XGI_CRT1Table[CRT1Index].CR[6];
- temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
- tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
- tempbx += 16;
- tempcx += 16;
- }
-
- if (tempcx > pVBInfo->VGAHT)
- tempcx = pVBInfo->VGAHT;
-
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
- }
-
- tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
- tempbx = pushbx;
- tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
- tempax |= (tempbx & 0xFF00);
- temp = (tempax & 0xFF00) >> 8;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
- tempcx = pVBInfo->VGAVT - 1;
- temp = tempcx & 0x00FF;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
- tempbx = pVBInfo->VGAVDE - 1;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0F, temp);
- temp = ((tempbx & 0xFF00) << 3) >> 8;
- temp |= ((tempcx & 0xFF00) >> 8);
- xgifb_reg_set(pVBInfo->Part1Port, 0x12, temp);
-
- /* BTVGA2VRS 0x10,0x11 */
- tempbx = (pVBInfo->VGAVT + pVBInfo->VGAVDE) >> 1;
- /* BTVGA2VRE 0x11 */
- tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1;
-
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
- tempbx = XGI_CRT1Table[CRT1Index].CR[10];
- temp = XGI_CRT1Table[CRT1Index].CR[9];
-
- if (temp & 0x04)
- tempbx |= 0x0100;
-
- if (temp & 0x080)
- tempbx |= 0x0200;
-
- temp = XGI_CRT1Table[CRT1Index].CR[14];
-
- if (temp & 0x08)
- tempbx |= 0x0400;
-
- temp = XGI_CRT1Table[CRT1Index].CR[11];
- tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
- }
-
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
- temp = ((tempbx & 0xFF00) >> 8) << 4;
- temp = (tempcx & 0x000F) | (temp);
- xgifb_reg_set(pVBInfo->Part1Port, 0x11, temp);
- tempax = 0;
-
- if (modeflag & DoubleScanMode)
- tempax |= 0x80;
-
- if (modeflag & HalfDCLK)
- tempax |= 0x40;
-
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x2C, ~0x0C0, tempax);
-}
-
-static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
-{
- unsigned long tempax, tempbx;
-
- tempbx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) * pVBInfo->RVBHCMAX)
- & 0xFFFF;
- tempax = (pVBInfo->VT - pVBInfo->VDE) * pVBInfo->RVBHCFACT;
- tempax = (tempax * pVBInfo->HT) / tempbx;
-
- return (unsigned short)tempax;
-}
-
-static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
- modeflag;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
- if (!(pVBInfo->VBInfo & SetInSlaveMode))
- return;
-
- temp = 0xFF; /* set MAX HT */
- xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
- tempcx = 0x08;
-
- if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
- modeflag |= Charx8Dot;
-
- tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
-
- if (modeflag & HalfDCLK)
- tempax >>= 1;
-
- tempax = (tempax / tempcx) - 1;
- tempbx |= ((tempax & 0x00FF) << 8);
- temp = tempax & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x04, temp);
-
- temp = (tempbx & 0xFF00) >> 8;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)))
- temp += 2;
-
- if ((pVBInfo->VBInfo & SetCRT2ToHiVision) &&
- !(pVBInfo->VBType & VB_SIS301LV) && (resinfo == 7))
- temp -= 2;
- }
-
- /* 0x05 Horizontal Display Start */
- xgifb_reg_set(pVBInfo->Part1Port, 0x05, temp);
- /* 0x06 Horizontal Blank end */
- xgifb_reg_set(pVBInfo->Part1Port, 0x06, 0x03);
-
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) { /* 030226 bainy */
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- tempax = pVBInfo->VGAHT;
- else
- tempax = XGI_GetVGAHT2(pVBInfo);
- }
-
- if (tempax >= pVBInfo->VGAHT)
- tempax = pVBInfo->VGAHT;
-
- if (modeflag & HalfDCLK)
- tempax >>= 1;
-
- tempax = (tempax / tempcx) - 5;
- tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- temp = (tempbx & 0x00FF) - 1;
- if (!(modeflag & HalfDCLK)) {
- temp -= 6;
- if (pVBInfo->TVInfo & TVSimuMode) {
- temp -= 4;
- temp -= 10;
- }
- }
- } else {
- tempbx = (tempbx & 0xFF00) >> 8;
- tempcx = (tempcx + tempbx) >> 1;
- temp = (tempcx & 0x00FF) + 2;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- temp -= 1;
- if (!(modeflag & HalfDCLK)) {
- if ((modeflag & Charx8Dot)) {
- temp += 4;
- if (pVBInfo->VGAHDE >= 800)
- temp -= 6;
- }
- }
- } else if (!(modeflag & HalfDCLK)) {
- temp -= 4;
- if (pVBInfo->LCDResInfo != Panel_1280x960 &&
- pVBInfo->VGAHDE >= 800) {
- temp -= 7;
- if (pVBInfo->VGAHDE >= 1280 &&
- pVBInfo->LCDResInfo != Panel_1280x960 &&
- (pVBInfo->LCDInfo & LCDNonExpanding))
- temp += 28;
- }
- }
- }
-
- /* 0x07 Horizontal Retrace Start */
- xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
- /* 0x08 Horizontal Retrace End */
- xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0);
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->TVInfo & TVSimuMode) {
- if (ModeNo == 0x50) {
- if (pVBInfo->TVInfo == SetNTSCTV) {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x30);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x03);
- } else {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x2f);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x02);
- }
- }
- }
- }
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x18, 0x03); /* 0x18 SR0B */
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0xF0, 0x00);
- xgifb_reg_set(pVBInfo->Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
-
- tempbx = pVBInfo->VGAVT;
- push1 = tempbx;
- tempcx = 0x121;
- tempbx = pVBInfo->VGAVDE; /* 0x0E Vertical Display End */
-
- if (tempbx == 357)
- tempbx = 350;
- if (tempbx == 360)
- tempbx = 350;
- if (tempbx == 375)
- tempbx = 350;
- if (tempbx == 405)
- tempbx = 400;
- if (tempbx == 525)
- tempbx = 480;
-
- push2 = tempbx;
-
- if (pVBInfo->VBInfo & SetCRT2ToLCD) {
- if (pVBInfo->LCDResInfo == Panel_1024x768) {
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (tempbx == 350)
- tempbx += 5;
- if (tempbx == 480)
- tempbx += 5;
- }
- }
- }
- tempbx--;
- tempbx--;
- temp = tempbx & 0x00FF;
- /* 0x10 vertical Blank Start */
- xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
- tempbx = push2;
- tempbx--;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
-
- if (tempbx & 0x0100)
- tempcx |= 0x0002;
-
- tempax = 0x000B;
-
- if (modeflag & DoubleScanMode)
- tempax |= 0x08000;
-
- if (tempbx & 0x0200)
- tempcx |= 0x0040;
-
- temp = (tempax & 0xFF00) >> 8;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
-
- if (tempbx & 0x0400)
- tempcx |= 0x0600;
-
- /* 0x11 Vertical Blank End */
- xgifb_reg_set(pVBInfo->Part1Port, 0x11, 0x00);
-
- tempax = push1;
- tempax -= tempbx; /* 0x0C Vertical Retrace Start */
- tempax >>= 2;
- push1 = tempax; /* push ax */
-
- if (resinfo != 0x09) {
- tempax <<= 1;
- tempbx += tempax;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if ((pVBInfo->VBType & VB_SIS301LV) &&
- !(pVBInfo->TVInfo & TVSetHiVision)) {
- if ((pVBInfo->TVInfo & TVSimuMode) &&
- (pVBInfo->TVInfo & TVSetPAL)) {
- if (!(pVBInfo->VBType & VB_SIS301LV) ||
- !(pVBInfo->TVInfo &
- (TVSetYPbPr525p |
- TVSetYPbPr750p |
- TVSetHiVision)))
- tempbx += 40;
- }
- } else {
- tempbx -= 10;
- }
- } else if (pVBInfo->TVInfo & TVSimuMode) {
- if (pVBInfo->TVInfo & TVSetPAL) {
- if (pVBInfo->VBType & VB_SIS301LV) {
- if (!(pVBInfo->TVInfo &
- (TVSetYPbPr525p |
- TVSetYPbPr750p |
- TVSetHiVision)))
- tempbx += 40;
- } else {
- tempbx += 40;
- }
- }
- }
- tempax = push1;
- tempax >>= 2;
- tempax++;
- tempax += tempbx;
- push1 = tempax; /* push ax */
-
- if ((pVBInfo->TVInfo & TVSetPAL)) {
- if (tempbx <= 513) {
- if (tempax >= 513)
- tempbx = 513;
- }
- }
-
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
- tempbx--;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
-
- if (tempbx & 0x0100)
- tempcx |= 0x0008;
-
- if (tempbx & 0x0200)
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x0B, 0x0FF, 0x20);
-
- tempbx++;
-
- if (tempbx & 0x0100)
- tempcx |= 0x0004;
-
- if (tempbx & 0x0200)
- tempcx |= 0x0080;
-
- if (tempbx & 0x0400)
- tempcx |= 0x0C00;
-
- tempbx = push1; /* pop ax */
- temp = tempbx & 0x00FF;
- temp &= 0x0F;
- /* 0x0D vertical Retrace End */
- xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
-
- if (tempbx & 0x0010)
- tempcx |= 0x2000;
-
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp); /* 0x0A CR07 */
- temp = (tempcx & 0x0FF00) >> 8;
- xgifb_reg_set(pVBInfo->Part1Port, 0x17, temp); /* 0x17 SR0A */
- tempax = modeflag;
- temp = (tempax & 0xFF00) >> 8;
-
- temp = (temp >> 1) & 0x09;
-
- if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
- temp |= 0x01;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */
- xgifb_reg_set(pVBInfo->Part1Port, 0x0F, 0); /* 0x0F CR14 */
- xgifb_reg_set(pVBInfo->Part1Port, 0x12, 0); /* 0x12 CR17 */
-
- if (pVBInfo->LCDInfo & LCDRGB18Bit)
- temp = 0x80;
- else
- temp = 0x00;
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x1A, temp); /* 0x1A SR0E */
-}
-
-static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
- modeflag;
- unsigned char const *TimingPoint;
-
- unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- tempax = 0;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToAVIDEO))
- tempax |= 0x0800;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
- tempax |= 0x0400;
-
- if (pVBInfo->VBInfo & SetCRT2ToSCART)
- tempax |= 0x0200;
-
- if (!(pVBInfo->TVInfo & TVSetPAL))
- tempax |= 0x1000;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision)
- tempax |= 0x0100;
-
- if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
- tempax &= 0xfe00;
-
- tempax = (tempax & 0xff00) >> 8;
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax);
- TimingPoint = XGI330_NTSCTiming;
-
- if (pVBInfo->TVInfo & TVSetPAL)
- TimingPoint = XGI330_PALTiming;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- TimingPoint = XGI330_HiTVExtTiming;
-
- if (pVBInfo->VBInfo & SetInSlaveMode)
- TimingPoint = XGI330_HiTVSt2Timing;
-
- if (pVBInfo->SetFlag & TVSimuMode)
- TimingPoint = XGI330_HiTVSt1Timing;
-
- if (!(modeflag & Charx8Dot))
- TimingPoint = XGI330_HiTVTextTiming;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- if (pVBInfo->TVInfo & TVSetYPbPr525i)
- TimingPoint = XGI330_YPbPr525iTiming;
-
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- TimingPoint = XGI330_YPbPr525pTiming;
-
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- TimingPoint = XGI330_YPbPr750pTiming;
- }
-
- for (i = 0x01, j = 0; i <= 0x2D; i++, j++)
- xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
-
- for (i = 0x39; i <= 0x45; i++, j++)
- /* di->temp2[j] */
- xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
-
- if (pVBInfo->VBInfo & SetCRT2ToTV)
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, 0x00);
-
- temp = pVBInfo->NewFlickerMode;
- temp &= 0x80;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xFF, temp);
-
- if (pVBInfo->TVInfo & TVSetPAL)
- tempax = 520;
- else
- tempax = 440;
-
- if (pVBInfo->VDE <= tempax) {
- tempax -= pVBInfo->VDE;
- tempax >>= 2;
- tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
- push1 = tempax;
- temp = (tempax & 0xFF00) >> 8;
- temp += (unsigned short)TimingPoint[0];
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
- | SetCRT2ToSVIDEO | SetCRT2ToSCART
- | SetCRT2ToYPbPr525750)) {
- tempcx = pVBInfo->VGAHDE;
- if (tempcx >= 1024) {
- temp = 0x17; /* NTSC */
- if (pVBInfo->TVInfo & TVSetPAL)
- temp = 0x19; /* PAL */
- }
- }
- }
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
- tempax = push1;
- temp = (tempax & 0xFF00) >> 8;
- temp += TimingPoint[1];
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO
- | SetCRT2ToSVIDEO | SetCRT2ToSCART
- | SetCRT2ToYPbPr525750))) {
- tempcx = pVBInfo->VGAHDE;
- if (tempcx >= 1024) {
- temp = 0x1D; /* NTSC */
- if (pVBInfo->TVInfo & TVSetPAL)
- temp = 0x52; /* PAL */
- }
- }
- }
- xgifb_reg_set(pVBInfo->Part2Port, 0x02, temp);
- }
-
- /* 301b */
- tempcx = pVBInfo->HT;
-
- if (XGI_IsLCDDualLink(pVBInfo))
- tempcx >>= 1;
-
- tempcx -= 2;
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x1B, temp);
-
- temp = (tempcx & 0xFF00) >> 8;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F, temp);
-
- tempcx = pVBInfo->HT >> 1;
- push1 = tempcx; /* push cx */
- tempcx += 7;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision)
- tempcx -= 4;
-
- temp = tempcx & 0x00FF;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x22, 0x0F, temp);
-
- tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
- tempbx += tempcx;
- push2 = tempbx;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x24, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x25, 0x0F, temp);
-
- tempbx = push2;
- tempbx = tempbx + 8;
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- tempbx = tempbx - 4;
- tempcx = tempbx;
- }
-
- temp = (tempbx & 0x00FF) << 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x29, 0x0F, temp);
-
- j += 2;
- tempcx += (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x27, temp);
- temp = ((tempcx & 0xFF00) >> 8) << 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x28, 0x0F, temp);
-
- tempcx += 8;
- if (pVBInfo->VBInfo & SetCRT2ToHiVision)
- tempcx -= 4;
-
- temp = tempcx & 0xFF;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
-
- tempcx = push1; /* pop cx */
- j += 2;
- temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
- tempcx -= temp;
- temp = tempcx & 0x00FF;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
-
- tempcx -= 11;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
- tempax = XGI_GetVGAHT2(pVBInfo);
- tempcx = tempax - 1;
- }
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x2E, temp);
-
- tempbx = pVBInfo->VDE;
-
- if (pVBInfo->VGAVDE == 360)
- tempbx = 746;
- if (pVBInfo->VGAVDE == 375)
- tempbx = 746;
- if (pVBInfo->VGAVDE == 405)
- tempbx = 853;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->VBType &
- (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
- if (!(pVBInfo->TVInfo &
- (TVSetYPbPr525p | TVSetYPbPr750p)))
- tempbx >>= 1;
- } else {
- tempbx >>= 1;
- }
- }
-
- tempbx -= 2;
- temp = tempbx & 0x00FF;
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (pVBInfo->VBType & VB_SIS301LV) {
- if (pVBInfo->TVInfo & TVSetHiVision) {
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (ModeNo == 0x2f)
- temp += 1;
- }
- }
- } else if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (ModeNo == 0x2f)
- temp += 1;
- }
- }
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x2F, temp);
-
- temp = (tempcx & 0xFF00) >> 8;
- temp |= ((tempbx & 0xFF00) >> 8) << 6;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToHiVision)) {
- if (pVBInfo->VBType & VB_SIS301LV) {
- if (pVBInfo->TVInfo & TVSetHiVision) {
- temp |= 0x10;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
- temp |= 0x20;
- }
- } else {
- temp |= 0x10;
- if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
- temp |= 0x20;
- }
- }
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x30, temp);
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) { /* TV gatingno */
- tempbx = pVBInfo->VDE;
- tempcx = tempbx - 2;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (!(pVBInfo->TVInfo & (TVSetYPbPr525p
- | TVSetYPbPr750p)))
- tempbx >>= 1;
- }
-
- if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
- temp = 0;
- if (tempcx & 0x0400)
- temp |= 0x20;
-
- if (tempbx & 0x0400)
- temp |= 0x40;
-
- xgifb_reg_set(pVBInfo->Part4Port, 0x10, temp);
- }
-
- temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
- xgifb_reg_set(pVBInfo->Part2Port, 0x46, temp);
- temp = (tempbx - 3) & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x47, temp);
- }
-
- tempbx = tempbx & 0x00FF;
-
- if (!(modeflag & HalfDCLK)) {
- tempcx = pVBInfo->VGAHDE;
- if (tempcx >= pVBInfo->HDE) {
- tempbx |= 0x2000;
- tempax &= 0x00FF;
- }
- }
-
- tempcx = 0x0101;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) { /* 301b */
- if (pVBInfo->VGAHDE >= 1024) {
- tempcx = 0x1920;
- if (pVBInfo->VGAHDE >= 1280) {
- tempcx = 0x1420;
- tempbx = tempbx & 0xDFFF;
- }
- }
- }
-
- if (!(tempbx & 0x2000)) {
- if (modeflag & HalfDCLK)
- tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
-
- push1 = tempbx;
- tempeax = pVBInfo->VGAHDE;
- tempebx = (tempcx & 0xFF00) >> 8;
- longtemp = tempeax * tempebx;
- tempecx = tempcx & 0x00FF;
- longtemp = longtemp / tempecx;
-
- /* 301b */
- tempecx = 8 * 1024;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- tempecx = tempecx * 8;
- }
-
- longtemp = longtemp * tempecx;
- tempecx = pVBInfo->HDE;
- temp2 = longtemp % tempecx;
- tempeax = longtemp / tempecx;
- if (temp2 != 0)
- tempeax += 1;
-
- tempax = (unsigned short)tempeax;
-
- /* 301b */
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- tempcx = ((tempax & 0xFF00) >> 5) >> 8;
- }
- /* end 301b */
-
- tempbx = push1;
- tempbx = (unsigned short)(((tempeax & 0x0000FF00) & 0x1F00)
- | (tempbx & 0x00FF));
- tempax = (unsigned short)(((tempeax & 0x000000FF) << 8)
- | (tempax & 0x00FF));
- temp = (tempax & 0xFF00) >> 8;
- } else {
- temp = (tempax & 0x00FF) >> 8;
- }
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x44, temp);
- temp = (tempbx & 0xFF00) >> 8;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x45, ~0x03F, temp);
- temp = tempcx & 0x00FF;
-
- if (tempbx & 0x2000)
- temp = 0;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
- temp |= 0x18;
-
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x46, ~0x1F, temp);
- if (pVBInfo->TVInfo & TVSetPAL) {
- tempbx = 0x0382;
- tempcx = 0x007e;
- } else {
- tempbx = 0x0369;
- tempcx = 0x0061;
- }
-
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x4b, temp);
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x4c, temp);
-
- temp = ((tempcx & 0xFF00) >> 8) & 0x03;
- temp <<= 2;
- temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
-
- if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- temp |= 0x10;
-
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- temp |= 0x20;
-
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- temp |= 0x60;
- }
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x4d, temp);
- temp = xgifb_reg_get(pVBInfo->Part2Port, 0x43); /* 301b change */
- xgifb_reg_set(pVBInfo->Part2Port, 0x43, (unsigned short)(temp - 3));
-
- if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) {
- if (pVBInfo->TVInfo & NTSC1024x768) {
- TimingPoint = XGI_NTSC1024AdjTime;
- for (i = 0x1c, j = 0; i <= 0x30; i++, j++) {
- xgifb_reg_set(pVBInfo->Part2Port, i,
- TimingPoint[j]);
- }
- xgifb_reg_set(pVBInfo->Part2Port, 0x43, 0x72);
- }
- }
-
- /* Modify for 301C PALM Support */
- if (pVBInfo->VBType & VB_XGI301C) {
- if (pVBInfo->TVInfo & TVSetPALM)
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08,
- 0x08); /* PALM Mode */
- }
-
- if (pVBInfo->TVInfo & TVSetPALM) {
- tempax = xgifb_reg_get(pVBInfo->Part2Port, 0x01);
- tempax--;
- xgifb_reg_and(pVBInfo->Part2Port, 0x01, tempax);
-
- xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF);
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
- if (!(pVBInfo->VBInfo & SetInSlaveMode))
- xgifb_reg_set(pVBInfo->Part2Port, 0x0B, 0x00);
- }
-}
-
-static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah,
- tempbh, tempch;
-
- struct XGI_LCDDesStruct const *LCDBDesPtr = NULL;
-
- /* si+Ext_ResInfo */
- if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
- return;
-
- tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
-
- if (XGI_IsLCDDualLink(pVBInfo))
- tempbx >>= 1;
-
- tempbx -= 1;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x2C, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
- temp = 0x01;
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x0B, temp);
- tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
- tempbx--;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x03, temp);
- temp = ((tempbx & 0xFF00) >> 8) & 0x07;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x0C, ~0x07, temp);
-
- tempcx = pVBInfo->VT - 1;
- temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
- xgifb_reg_set(pVBInfo->Part2Port, 0x19, temp);
- temp = (tempcx & 0xFF00) >> 8;
- temp <<= 5;
- xgifb_reg_set(pVBInfo->Part2Port, 0x1A, temp);
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
-
- /* Customized LCDB Does not add */
- if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
- LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex,
- pVBInfo);
- else
- LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex,
- pVBInfo);
-
- tempah = pVBInfo->LCDResInfo;
- tempah &= PanelResInfo;
-
- if ((tempah == Panel_1024x768) || (tempah == Panel_1024x768x75)) {
- tempbx = 1024;
- tempcx = 768;
- } else if ((tempah == Panel_1280x1024) ||
- (tempah == Panel_1280x1024x75)) {
- tempbx = 1280;
- tempcx = 1024;
- } else if (tempah == Panel_1400x1050) {
- tempbx = 1400;
- tempcx = 1050;
- } else {
- tempbx = 1600;
- tempcx = 1200;
- }
-
- if (pVBInfo->LCDInfo & EnableScalingLCD) {
- tempbx = pVBInfo->HDE;
- tempcx = pVBInfo->VDE;
- }
-
- pushbx = tempbx;
- tempax = pVBInfo->VT;
- pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES;
- pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS;
- pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES;
- pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS;
- tempbx = pVBInfo->LCDVDES;
- tempcx += tempbx;
-
- if (tempcx >= tempax)
- tempcx -= tempax; /* lcdvdes */
-
- temp = tempbx & 0x00FF; /* RVEQ1EQ=lcdvdes */
- xgifb_reg_set(pVBInfo->Part2Port, 0x05, temp);
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x06, temp);
- tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
- tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
- tempah = tempch;
- tempah <<= 3;
- tempah |= tempbh;
- xgifb_reg_set(pVBInfo->Part2Port, 0x02, tempah);
-
- /* getlcdsync() */
- XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
- tempcx = tempbx;
- tempax = pVBInfo->VT;
- tempbx = pVBInfo->LCDVRS;
-
- tempcx += tempbx;
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
- xgifb_reg_set(pVBInfo->Part2Port, 0x04, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp <<= 4;
- temp |= (tempcx & 0x000F);
- xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
- tempcx = pushbx;
- tempax = pVBInfo->HT;
- tempbx = pVBInfo->LCDHDES;
- tempbx &= 0x0FFF;
-
- if (XGI_IsLCDDualLink(pVBInfo)) {
- tempax >>= 1;
- tempbx >>= 1;
- tempcx >>= 1;
- }
-
- if (pVBInfo->VBType & VB_SIS302LV)
- tempbx += 1;
-
- if (pVBInfo->VBType & VB_XGI301C) /* tap4 */
- tempbx += 1;
-
- tempcx += tempbx;
-
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
- temp = ((tempbx & 0xFF00) >> 8) << 4;
- xgifb_reg_set(pVBInfo->Part2Port, 0x20, temp);
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part2Port, 0x23, temp); /* RHEQPLE=lcdhdee */
- temp = (tempcx & 0xFF00) >> 8;
- xgifb_reg_set(pVBInfo->Part2Port, 0x25, temp);
-
- XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
- tempcx = tempax;
- tempax = pVBInfo->HT;
- tempbx = pVBInfo->LCDHRS;
- if (XGI_IsLCDDualLink(pVBInfo)) {
- tempax >>= 1;
- tempbx >>= 1;
- tempcx >>= 1;
- }
-
- if (pVBInfo->VBType & VB_SIS302LV)
- tempbx += 1;
-
- tempcx += tempbx;
-
- if (tempcx >= tempax)
- tempcx -= tempax;
-
- temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
- xgifb_reg_set(pVBInfo->Part2Port, 0x1C, temp);
-
- temp = (tempbx & 0xFF00) >> 8;
- temp <<= 4;
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
- temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
- xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp);
-
- if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
- if (pVBInfo->VGAVDE == 525) {
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
- | VB_SIS301LV | VB_SIS302LV
- | VB_XGI301C))
- temp = 0xC6;
- else
- temp = 0xC4;
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
- xgifb_reg_set(pVBInfo->Part2Port, 0x30, 0xB3);
- }
-
- if (pVBInfo->VGAVDE == 420) {
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
- | VB_SIS301LV | VB_SIS302LV
- | VB_XGI301C))
- temp = 0x4F;
- else
- temp = 0x4E;
- xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
- }
- }
-}
-
-/*
- * Function : XGI_GetTap4Ptr
- * Input :
- * Output : di -> Tap4 Reg. Setting Pointer
- * Description :
- */
-static struct XGI301C_Tap4TimingStruct const
-*XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo)
-{
- unsigned short tempax, tempbx, i;
- struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
-
- if (tempcx == 0) {
- tempax = pVBInfo->VGAHDE;
- tempbx = pVBInfo->HDE;
- } else {
- tempax = pVBInfo->VGAVDE;
- tempbx = pVBInfo->VDE;
- }
-
- if (tempax <= tempbx)
- return &xgifb_tap4_timing[0];
- Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; /* NTSC */
-
- if (pVBInfo->TVInfo & TVSetPAL)
- Tap4TimingPtr = PALTap4Timing;
-
- if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
- if ((pVBInfo->TVInfo & TVSetYPbPr525i) ||
- (pVBInfo->TVInfo & TVSetYPbPr525p))
- Tap4TimingPtr = xgifb_ntsc_525_tap4_timing;
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- Tap4TimingPtr = YPbPr750pTap4Timing;
- }
-
- if (pVBInfo->VBInfo & SetCRT2ToHiVision)
- Tap4TimingPtr = xgifb_tap4_timing;
-
- i = 0;
- while (Tap4TimingPtr[i].DE != 0xFFFF) {
- if (Tap4TimingPtr[i].DE == tempax)
- break;
- i++;
- }
- return &Tap4TimingPtr[i];
-}
-
-static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
-{
- unsigned short i, j;
- struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
-
- if (!(pVBInfo->VBType & VB_XGI301C))
- return;
-
- Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
- for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
- xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
-
- if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
- !(pVBInfo->VBInfo & SetCRT2ToHiVision)) {
- /* Set Vertical Scaling */
- Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo);
- for (i = 0xC0, j = 0; i < 0xFF; i++, j++)
- xgifb_reg_set(pVBInfo->Part2Port,
- i,
- Tap4TimingPtr->Reg[j]);
- }
-
- if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
- !(pVBInfo->VBInfo & SetCRT2ToHiVision))
- /* Enable V.Scaling */
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04);
- else
- /* Enable H.Scaling */
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10);
-}
-
-static void XGI_SetGroup3(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short i;
- unsigned char const *tempdi;
- unsigned short modeflag;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
- if (pVBInfo->TVInfo & TVSetPAL) {
- xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
- xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
- } else {
- xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xF5);
- xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xB7);
- }
-
- if (!(pVBInfo->VBInfo & SetCRT2ToTV))
- return;
-
- if (pVBInfo->TVInfo & TVSetPALM) {
- xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
- xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
- xgifb_reg_set(pVBInfo->Part3Port, 0x3D, 0xA8);
- }
-
- if ((pVBInfo->VBInfo & SetCRT2ToHiVision) || (pVBInfo->VBInfo
- & SetCRT2ToYPbPr525750)) {
- if (pVBInfo->TVInfo & TVSetYPbPr525i)
- return;
-
- tempdi = XGI330_HiTVGroup3Data;
- if (pVBInfo->SetFlag & TVSimuMode) {
- tempdi = XGI330_HiTVGroup3Simu;
- if (!(modeflag & Charx8Dot))
- tempdi = XGI330_HiTVGroup3Text;
- }
-
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- tempdi = XGI330_Ren525pGroup3;
-
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- tempdi = XGI330_Ren750pGroup3;
-
- for (i = 0; i <= 0x3E; i++)
- xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]);
-
- if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- xgifb_reg_set(pVBInfo->Part3Port, 0x28, 0x3f);
- }
- }
-}
-
-static void XGI_SetGroup4(unsigned short ModeIdIndex,
- unsigned short RefreshRateTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
-
- unsigned long tempebx, tempeax, templong;
-
- /* si+Ext_ResInfo */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- temp = pVBInfo->RVBHCFACT;
- xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
-
- tempbx = pVBInfo->RVBHCMAX;
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x14, temp);
- temp2 = ((tempbx & 0xFF00) >> 8) << 7;
- tempcx = pVBInfo->VGAHT - 1;
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x16, temp);
-
- temp = ((tempcx & 0xFF00) >> 8) << 3;
- temp2 |= temp;
-
- tempcx = pVBInfo->VGAVT - 1;
- if (!(pVBInfo->VBInfo & SetCRT2ToTV))
- tempcx -= 5;
-
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x17, temp);
- temp = temp2 | ((tempcx & 0xFF00) >> 8);
- xgifb_reg_set(pVBInfo->Part4Port, 0x15, temp);
- xgifb_reg_or(pVBInfo->Part4Port, 0x0D, 0x08);
- tempcx = pVBInfo->VBInfo;
- tempbx = pVBInfo->VGAHDE;
-
- if (modeflag & HalfDCLK)
- tempbx >>= 1;
-
- if (XGI_IsLCDDualLink(pVBInfo))
- tempbx >>= 1;
-
- if (tempcx & SetCRT2ToHiVision) {
- temp = 0;
- if (tempbx <= 1024)
- temp = 0xA0;
- if (tempbx == 1280)
- temp = 0xC0;
- } else if (tempcx & SetCRT2ToTV) {
- temp = 0xA0;
- if (tempbx <= 800)
- temp = 0x80;
- } else {
- temp = 0x80;
- if (pVBInfo->VBInfo & SetCRT2ToLCD) {
- temp = 0;
- if (tempbx > 800)
- temp = 0x60;
- }
- }
-
- if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) {
- temp = 0x00;
- if (pVBInfo->VGAHDE == 1280)
- temp = 0x40;
- if (pVBInfo->VGAHDE == 1024)
- temp = 0x20;
- }
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x0E, ~0xEF, temp);
-
- tempebx = pVBInfo->VDE;
-
- tempcx = pVBInfo->RVBHRS;
- temp = tempcx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x18, temp);
-
- tempeax = pVBInfo->VGAVDE;
- tempcx |= 0x04000;
-
- if (tempeax <= tempebx) {
- tempcx = tempcx & (~0x4000);
- tempeax = pVBInfo->VGAVDE;
- } else {
- tempeax -= tempebx;
- }
-
- templong = (tempeax * 256 * 1024) % tempebx;
- tempeax = (tempeax * 256 * 1024) / tempebx;
- tempebx = tempeax;
-
- if (templong != 0)
- tempebx++;
-
- temp = (unsigned short)(tempebx & 0x000000FF);
- xgifb_reg_set(pVBInfo->Part4Port, 0x1B, temp);
-
- temp = (unsigned short)((tempebx & 0x0000FF00) >> 8);
- xgifb_reg_set(pVBInfo->Part4Port, 0x1A, temp);
- tempbx = (unsigned short)(tempebx >> 16);
- temp = tempbx & 0x00FF;
- temp <<= 4;
- temp |= ((tempcx & 0xFF00) >> 8);
- xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp);
-
- /* 301b */
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- temp = 0x0028;
- xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp);
- tempax = pVBInfo->VGAHDE;
- if (modeflag & HalfDCLK)
- tempax >>= 1;
-
- if (XGI_IsLCDDualLink(pVBInfo))
- tempax >>= 1;
-
- if (pVBInfo->VBInfo & SetCRT2ToLCD) {
- if (tempax > 800)
- tempax -= 800;
- } else if (pVBInfo->VGAHDE > 800) {
- if (pVBInfo->VGAHDE == 1024)
- tempax = (tempax * 25 / 32) - 1;
- else
- tempax = (tempax * 20 / 32) - 1;
- }
- tempax -= 1;
-
- temp = (tempax & 0xFF00) >> 8;
- temp = (temp & 0x0003) << 4;
- xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp);
- temp = tempax & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp);
-
- if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) {
- if (pVBInfo->VGAHDE > 800)
- xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08);
- }
- temp = 0x0036;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (!(pVBInfo->TVInfo & (NTSC1024x768
- | TVSetYPbPr525p | TVSetYPbPr750p
- | TVSetHiVision))) {
- temp |= 0x0001;
- if ((pVBInfo->VBInfo & SetInSlaveMode) &&
- !(pVBInfo->TVInfo & TVSimuMode))
- temp &= (~0x0001);
- }
- }
-
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
- tempbx = pVBInfo->HT;
- if (XGI_IsLCDDualLink(pVBInfo))
- tempbx >>= 1;
- tempbx = (tempbx >> 1) - 2;
- temp = ((tempbx & 0x0700) >> 8) << 3;
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
- temp = tempbx & 0x00FF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x22, temp);
- }
- /* end 301b */
-
- XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-}
-
-static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
-}
-
-static void XGI_SetGroup5(struct vb_device_info *pVBInfo)
-{
- if (pVBInfo->ModeType == ModeVGA) {
- if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
- | DisableCRT2Display))) {
- XGINew_EnableCRT2(pVBInfo);
- }
- }
-}
-
-static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
-}
-
-static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
- unsigned short ModeNo,
- unsigned short ModeIdIndex)
-{
- unsigned short xres, yres, colordepth, modeflag, resindex;
-
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if (!(modeflag & Charx8Dot)) {
- xres /= 9;
- xres *= 8;
- }
-
- if ((ModeNo > 0x13) && (modeflag & HalfDCLK))
- xres *= 2;
-
- if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
- yres *= 2;
-
- if (xres > xgifb_info->lvds_data.LVDSHDE)
- return 0;
-
- if (yres > xgifb_info->lvds_data.LVDSVDE)
- return 0;
-
- if (xres != xgifb_info->lvds_data.LVDSHDE ||
- yres != xgifb_info->lvds_data.LVDSVDE) {
- colordepth = XGI_GetColorDepth(ModeIdIndex);
- if (colordepth > 2)
- return 0;
- }
- return 1;
-}
-
-static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
- int chip_id,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char temp, Miscdata;
- unsigned short xres, yres, modeflag, resindex;
- unsigned short LVDSHT, LVDSHBS, LVDSHRS, LVDSHRE, LVDSHBE;
- unsigned short LVDSVT, LVDSVBS, LVDSVRS, LVDSVRE, LVDSVBE;
- unsigned short value;
-
- temp = (unsigned char)((xgifb_info->lvds_data.LVDS_Capability &
- (LCDPolarity << 8)) >> 8);
- temp &= LCDPolarity;
- Miscdata = inb(pVBInfo->P3cc);
-
- outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
-
- temp = xgifb_info->lvds_data.LVDS_Capability & LCDPolarity;
- /* SR35[7] FP VSync polarity */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80);
- /* SR30[5] FP HSync polarity */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1);
-
- if (chip_id == XG27)
- XGI_SetXG27FPBits(pVBInfo);
- else
- XGI_SetXG21FPBits(pVBInfo);
-
- resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if (!(modeflag & Charx8Dot))
- xres = xres * 8 / 9;
-
- LVDSHT = xgifb_info->lvds_data.LVDSHT;
-
- LVDSHBS = xres + (xgifb_info->lvds_data.LVDSHDE - xres) / 2;
-
- if (LVDSHBS > LVDSHT)
- LVDSHBS -= LVDSHT;
-
- LVDSHRS = LVDSHBS + xgifb_info->lvds_data.LVDSHFP;
- if (LVDSHRS > LVDSHT)
- LVDSHRS -= LVDSHT;
-
- LVDSHRE = LVDSHRS + xgifb_info->lvds_data.LVDSHSYNC;
- if (LVDSHRE > LVDSHT)
- LVDSHRE -= LVDSHT;
-
- LVDSHBE = LVDSHBS + LVDSHT - xgifb_info->lvds_data.LVDSHDE;
-
- LVDSVT = xgifb_info->lvds_data.LVDSVT;
-
- LVDSVBS = yres + (xgifb_info->lvds_data.LVDSVDE - yres) / 2;
- if (modeflag & DoubleScanMode)
- LVDSVBS += yres / 2;
-
- if (LVDSVBS > LVDSVT)
- LVDSVBS -= LVDSVT;
-
- LVDSVRS = LVDSVBS + xgifb_info->lvds_data.LVDSVFP;
- if (LVDSVRS > LVDSVT)
- LVDSVRS -= LVDSVT;
-
- LVDSVRE = LVDSVRS + xgifb_info->lvds_data.LVDSVSYNC;
- if (LVDSVRE > LVDSVT)
- LVDSVRE -= LVDSVT;
-
- LVDSVBE = LVDSVBS + LVDSVT - xgifb_info->lvds_data.LVDSVDE;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x11);
- xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
-
- if (!(modeflag & Charx8Dot))
- xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
-
- /* HT SR0B[1:0] CR00 */
- value = (LVDSHT >> 3) - 5;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
- xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
-
- /* HBS SR0B[5:4] CR02 */
- value = (LVDSHBS >> 3) - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
- xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
-
- /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
- value = (LVDSHBE >> 3) - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
-
- /* HRS SR0B[7:6] CR04 */
- value = (LVDSHRS >> 3) + 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
- xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
-
- /* Panel HRS SR2F[1:0] SR2E[7:0] */
- value--;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
-
- /* HRE SR0C[2] CR05[4:0] */
- value = (LVDSHRE >> 3) + 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
-
- /* Panel HRE SR2F[7:2] */
- value--;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
-
- /* VT SR0A[0] CR07[5][0] CR06 */
- value = LVDSVT - 2;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
- xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
-
- /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
- value = LVDSVBS - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
- xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
-
- /* VBE SR0A[4] CR16 */
- value = LVDSVBE - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
- xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
-
- /* VRS SR0A[3] CR7[7][2] CR10 */
- value = LVDSVRS - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
- xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
-
- if (chip_id == XG27) {
- /* Panel VRS SR35[2:0] SR34[7:0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07,
- (value & 0x700) >> 8);
- xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
- } else {
- /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03,
- (value & 0x600) >> 9);
- xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
- }
-
- /* VRE SR0A[5] CR11[3:0] */
- value = LVDSVRE - 1;
- xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
-
- /* Panel VRE SR3F[7:2] */
- if (chip_id == XG27)
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
- (value << 2) & 0xFC);
- else
- /* SR3F[7] has to be 0, h/w bug */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
- (value << 2) & 0x7C);
-
- for (temp = 0, value = 0; temp < 3; temp++) {
- xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2B, xgifb_info->lvds_data.VCLKData1);
- xgifb_reg_set(pVBInfo->P3c4,
- 0x2C, xgifb_info->lvds_data.VCLKData2);
- value += 0x10;
- }
-
- if (!(modeflag & Charx8Dot)) {
- inb(pVBInfo->P3da); /* reset 3da */
- outb(0x13, pVBInfo->P3c0); /* set index */
- /* set data, panning = 0, shift left 1 dot*/
- outb(0x00, pVBInfo->P3c0);
-
- inb(pVBInfo->P3da); /* Enable Attribute */
- outb(0x20, pVBInfo->P3c0);
-
- inb(pVBInfo->P3da); /* reset 3da */
- }
-}
-
-/*
- * Function : XGI_IsLCDON
- * Input :
- * Output : 0 : Skip PSC Control
- * 1: Disable PSC
- * Description :
- */
-static unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo)
-{
- unsigned short tempax;
-
- tempax = pVBInfo->VBInfo;
- if (tempax & SetCRT2ToDualEdge)
- return 0;
- else if (tempax & (DisableCRT2Display | SwitchCRT2 | SetSimuScanMode))
- return 1;
-
- return 0;
-}
-
-static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempah = 0;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- tempah = 0x3F;
- if (!(pVBInfo->VBInfo &
- (DisableCRT2Display | SetSimuScanMode))) {
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
- tempah = 0x7F; /* Disable Channel A */
- }
- }
-
- /* disable part4_1f */
- xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah);
-
- if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
- if (((pVBInfo->VBInfo &
- (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) ||
- (XGI_IsLCDON(pVBInfo)))
- /* LVDS Driver power down */
- xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x80);
- }
-
- if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA |
- SetSimuScanMode))
- XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
-
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
- /* Power down */
- xgifb_reg_and(pVBInfo->Part1Port, 0x1e, 0xdf);
-
- /* disable TV as primary VGA swap */
- xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xdf);
-
- if ((pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToDualEdge)))
- xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xdf);
-
- if ((pVBInfo->VBInfo &
- (DisableCRT2Display | SetSimuScanMode)) ||
- (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
- (pVBInfo->VBInfo &
- (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))))
- xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
-
- if ((pVBInfo->VBInfo &
- (DisableCRT2Display | SetSimuScanMode)) ||
- (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) ||
- (pVBInfo->VBInfo &
- (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))) {
- /* save Part1 index 0 */
- tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
- /* BTDAC = 1, avoid VB reset */
- xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x10);
- /* disable CRT2 */
- xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
- /* restore Part1 index 0 */
- xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
- }
- } else { /* {301} */
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
- /* Disable CRT2 */
- xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
- /* Disable TV asPrimary VGA swap */
- xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xDF);
- }
-
- if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA
- | SetSimuScanMode))
- XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
- }
-}
-
-/*
- * Function : XGI_GetTVPtrIndex
- * Input :
- * Output :
- * Description : bx 0 : ExtNTSC
- * 1 : StNTSC
- * 2 : ExtPAL
- * 3 : StPAL
- * 4 : ExtHiTV
- * 5 : StHiTV
- * 6 : Ext525i
- * 7 : St525i
- * 8 : Ext525p
- * 9 : St525p
- * A : Ext750p
- * B : St750p
- */
-static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx = 0;
-
- if (pVBInfo->TVInfo & TVSetPAL)
- tempbx = 2;
- if (pVBInfo->TVInfo & TVSetHiVision)
- tempbx = 4;
- if (pVBInfo->TVInfo & TVSetYPbPr525i)
- tempbx = 6;
- if (pVBInfo->TVInfo & TVSetYPbPr525p)
- tempbx = 8;
- if (pVBInfo->TVInfo & TVSetYPbPr750p)
- tempbx = 10;
- if (pVBInfo->TVInfo & TVSimuMode)
- tempbx++;
-
- return tempbx;
-}
-
-/*
- * Function : XGI_GetTVPtrIndex2
- * Input :
- * Output : bx 0 : NTSC
- * 1 : PAL
- * 2 : PALM
- * 3 : PALN
- * 4 : NTSC1024x768
- * 5 : PAL-M 1024x768
- * 6-7: reserved
- * cl 0 : YFilter1
- * 1 : YFilter2
- * ch 0 : 301A
- * 1 : 301B/302B/301LV/302LV
- * Description :
- */
-static void XGI_GetTVPtrIndex2(unsigned short *tempbx,
- unsigned char *tempcl,
- unsigned char *tempch,
- struct vb_device_info *pVBInfo)
-{
- *tempbx = 0;
- *tempcl = 0;
- *tempch = 0;
-
- if (pVBInfo->TVInfo & TVSetPAL)
- *tempbx = 1;
-
- if (pVBInfo->TVInfo & TVSetPALM)
- *tempbx = 2;
-
- if (pVBInfo->TVInfo & TVSetPALN)
- *tempbx = 3;
-
- if (pVBInfo->TVInfo & NTSC1024x768) {
- *tempbx = 4;
- if (pVBInfo->TVInfo & TVSetPALM)
- *tempbx = 5;
- }
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if (!(pVBInfo->VBInfo & SetInSlaveMode) || (pVBInfo->TVInfo
- & TVSimuMode)) {
- *tempbx += 8;
- *tempcl += 1;
- }
- }
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C))
- (*tempch)++;
-}
-
-static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
-{
- unsigned char tempah, tempbl, tempbh;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA
- | SetCRT2ToTV | SetCRT2ToRAMDAC)) {
- tempbh = 0;
- tempbl = XGI301TVDelay;
-
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
- tempbl >>= 4;
- if (pVBInfo->VBInfo &
- (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- tempbh = XGI301LCDDelay;
-
- if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA))
- tempbl = tempbh;
- }
-
- tempbl &= 0x0F;
- tempbh &= 0xF0;
- tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2D);
-
- if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD
- | SetCRT2ToTV)) { /* Channel B */
- tempah &= 0xF0;
- tempah |= tempbl;
- }
-
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- /* Channel A */
- tempah &= 0x0F;
- tempah |= tempbh;
- }
- xgifb_reg_set(pVBInfo->Part1Port, 0x2D, tempah);
- }
- }
-}
-
-static void XGI_SetLCDCap_A(unsigned short tempcx,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
-
- if (temp & LCDRGB18Bit) {
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
- /* Enable Dither */
- (unsigned short)(0x20 | (tempcx & 0x00C0)));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
- } else {
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
- (unsigned short)(0x30 | (tempcx & 0x00C0)));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
- }
-}
-
-/*
- * Function : XGI_SetLCDCap_B
- * Input : cx -> LCD Capability
- * Output :
- * Description :
- */
-static void XGI_SetLCDCap_B(unsigned short tempcx,
- struct vb_device_info *pVBInfo)
-{
- if (tempcx & EnableLCD24bpp) { /* 24bits */
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
- (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x0c));
- } else {
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
- (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x18));
- /* Enable Dither */
- }
-}
-
-static void XGI_LongWait(struct vb_device_info *pVBInfo)
-{
- unsigned short i;
-
- i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
-
- if (!(i & 0xC0)) {
- for (i = 0; i < 0xFFFF; i++) {
- if (!(inb(pVBInfo->P3da) & 0x08))
- break;
- }
-
- for (i = 0; i < 0xFFFF; i++) {
- if ((inb(pVBInfo->P3da) & 0x08))
- break;
- }
- }
-}
-
-static void SetSpectrum(struct vb_device_info *pVBInfo)
-{
- unsigned short index;
-
- index = XGI_GetLCDCapPtr(pVBInfo);
-
- /* disable down spectrum D[4] */
- xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x8F);
- XGI_LongWait(pVBInfo);
- xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x20); /* reset spectrum */
- XGI_LongWait(pVBInfo);
-
- xgifb_reg_set(pVBInfo->Part4Port, 0x31,
- pVBInfo->LCDCapList[index].Spectrum_31);
- xgifb_reg_set(pVBInfo->Part4Port, 0x32,
- pVBInfo->LCDCapList[index].Spectrum_32);
- xgifb_reg_set(pVBInfo->Part4Port, 0x33,
- pVBInfo->LCDCapList[index].Spectrum_33);
- xgifb_reg_set(pVBInfo->Part4Port, 0x34,
- pVBInfo->LCDCapList[index].Spectrum_34);
- XGI_LongWait(pVBInfo);
- xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x40); /* enable spectrum */
-}
-
-static void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
-{
- unsigned short tempcx;
-
- tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
- VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBType &
- (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
- /* Set 301LV Capability */
- xgifb_reg_set(pVBInfo->Part4Port, 0x24,
- (unsigned char)(tempcx & 0x1F));
- }
- /* VB Driving */
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D,
- ~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
- (unsigned short)((tempcx & (EnableVBCLKDRVLOW |
- EnablePLLSPLOW)) >> 8));
-
- if (pVBInfo->VBInfo & SetCRT2ToLCD)
- XGI_SetLCDCap_B(tempcx, pVBInfo);
- else if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
- XGI_SetLCDCap_A(tempcx, pVBInfo);
-
- if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
- if (tempcx & EnableSpectrum)
- SetSpectrum(pVBInfo);
- }
- } else {
- /* LVDS,CH7017 */
- XGI_SetLCDCap_A(tempcx, pVBInfo);
- }
-}
-
-/*
- * Function : XGI_SetAntiFlicker
- * Input :
- * Output :
- * Description : Set TV Customized Param.
- */
-static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx;
-
- unsigned char tempah;
-
- if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
- return;
-
- tempbx = XGI_GetTVPtrIndex(pVBInfo);
- tempbx &= 0xFE;
- tempah = TVAntiFlickList[tempbx];
- tempah <<= 4;
-
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
-}
-
-static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx;
-
- unsigned char tempah;
-
- tempbx = XGI_GetTVPtrIndex(pVBInfo);
- tempbx &= 0xFE;
- tempah = TVEdgeList[tempbx];
- tempah <<= 5;
-
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
-}
-
-static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx;
-
- unsigned char tempcl, tempch;
-
- unsigned long tempData;
-
- XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
- tempData = TVPhaseList[tempbx];
-
- xgifb_reg_set(pVBInfo->Part2Port, 0x31, (unsigned short)(tempData
- & 0x000000FF));
- xgifb_reg_set(pVBInfo->Part2Port, 0x32, (unsigned short)((tempData
- & 0x0000FF00) >> 8));
- xgifb_reg_set(pVBInfo->Part2Port, 0x33, (unsigned short)((tempData
- & 0x00FF0000) >> 16));
- xgifb_reg_set(pVBInfo->Part2Port, 0x34, (unsigned short)((tempData
- & 0xFF000000) >> 24));
-}
-
-static void XGI_SetYFilter(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx, index;
- unsigned char const *filterPtr;
- unsigned char tempcl, tempch, tempal;
-
- XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
-
- switch (tempbx) {
- case 0x00:
- case 0x04:
- filterPtr = NTSCYFilter1;
- break;
-
- case 0x01:
- filterPtr = PALYFilter1;
- break;
-
- case 0x02:
- case 0x05:
- case 0x0D:
- case 0x03:
- filterPtr = xgifb_palmn_yfilter1;
- break;
-
- case 0x08:
- case 0x0C:
- case 0x0A:
- case 0x0B:
- case 0x09:
- filterPtr = xgifb_yfilter2;
- break;
-
- default:
- return;
- }
-
- tempal = XGI330_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
- if (tempcl == 0)
- index = tempal * 4;
- else
- index = tempal * 7;
-
- if ((tempcl == 0) && (tempch == 1)) {
- xgifb_reg_set(pVBInfo->Part2Port, 0x35, 0);
- xgifb_reg_set(pVBInfo->Part2Port, 0x36, 0);
- xgifb_reg_set(pVBInfo->Part2Port, 0x37, 0);
- xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
- } else {
- xgifb_reg_set(pVBInfo->Part2Port, 0x35, filterPtr[index++]);
- xgifb_reg_set(pVBInfo->Part2Port, 0x36, filterPtr[index++]);
- xgifb_reg_set(pVBInfo->Part2Port, 0x37, filterPtr[index++]);
- xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
- }
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- xgifb_reg_set(pVBInfo->Part2Port, 0x48, filterPtr[index++]);
- xgifb_reg_set(pVBInfo->Part2Port, 0x49, filterPtr[index++]);
- xgifb_reg_set(pVBInfo->Part2Port, 0x4A, filterPtr[index++]);
- }
-}
-
-/*
- * Function : XGI_OEM310Setting
- * Input :
- * Output :
- * Description : Customized Param. for 301
- */
-static void XGI_OEM310Setting(unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- XGI_SetDelayComp(pVBInfo);
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
- XGI_SetLCDCap(pVBInfo);
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- XGI_SetPhaseIncr(pVBInfo);
- XGI_SetYFilter(ModeIdIndex, pVBInfo);
- XGI_SetAntiFlicker(pVBInfo);
-
- if (pVBInfo->VBType & VB_SIS301)
- XGI_SetEdgeEnhance(pVBInfo);
- }
-}
-
-/*
- * Function : XGI_SetCRT2ModeRegs
- * Input :
- * Output :
- * Description : Origin code for crt2group
- */
-static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo)
-{
- unsigned short tempbl;
- short tempcl;
-
- unsigned char tempah;
-
- tempah = 0;
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
- tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
- tempah &= ~0x10; /* BTRAMDAC */
- tempah |= 0x40; /* BTRAM */
-
- if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
- | SetCRT2ToLCD)) {
- tempah = 0x40; /* BTDRAM */
- tempcl = pVBInfo->ModeType;
- tempcl -= ModeVGA;
- if (tempcl >= 0) {
- /* BT Color */
- tempah = 0x008 >> tempcl;
- if (tempah == 0)
- tempah = 1;
- tempah |= 0x040;
- }
- if (pVBInfo->VBInfo & SetInSlaveMode)
- tempah ^= 0x50; /* BTDAC */
- }
- }
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
- tempah = 0x08;
- tempbl = 0xf0;
-
- if (pVBInfo->VBInfo & DisableCRT2Display)
- goto reg_and_or;
-
- tempah = 0x00;
- tempbl = 0xff;
-
- if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV |
- SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
- goto reg_and_or;
-
- if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
- (!(pVBInfo->VBInfo & SetSimuScanMode))) {
- tempbl &= 0xf7;
- tempah |= 0x01;
- goto reg_and_or;
- }
-
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- tempbl &= 0xf7;
- tempah |= 0x01;
- }
-
- if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)))
- goto reg_and_or;
-
- tempbl &= 0xf8;
- tempah = 0x01;
-
- if (!(pVBInfo->VBInfo & SetInSlaveMode))
- tempah |= 0x02;
-
- if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
- tempah = tempah ^ 0x05;
- if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
- tempah = tempah ^ 0x01;
- }
-
- if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
- tempah |= 0x08;
-
-reg_and_or:
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah);
-
- if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD
- | XGI_SetCRT2ToLCDA)) {
- tempah &= (~0x08);
- if ((pVBInfo->ModeType == ModeVGA) && !(pVBInfo->VBInfo
- & SetInSlaveMode)) {
- tempah |= 0x010;
- }
- tempah |= 0x080;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- tempah |= 0x020;
- if (pVBInfo->VBInfo & DriverMode)
- tempah = tempah ^ 0x20;
- }
-
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
- tempah = 0;
-
- if (pVBInfo->LCDInfo & SetLCDDualLink)
- tempah |= 0x40;
-
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->TVInfo & RPLLDIV2XO)
- tempah |= 0x40;
- }
-
- if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
- (pVBInfo->LCDResInfo == Panel_1280x1024x75))
- tempah |= 0x80;
-
- if (pVBInfo->LCDResInfo == Panel_1280x960)
- tempah |= 0x80;
-
- xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah);
- }
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- tempah = 0;
- tempbl = 0xfb;
-
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
- tempbl = 0xff;
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
- tempah |= 0x04; /* shampoo 0129 */
- }
-
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x13, tempbl, tempah);
- tempah = 0x00;
- tempbl = 0xcf;
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
- tempah |= 0x30;
- }
-
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x2c, tempbl, tempah);
- tempah = 0;
- tempbl = 0x3f;
-
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
- tempah |= 0xc0;
- }
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, tempbl, tempah);
- }
-
- tempah = 0;
- tempbl = 0x7f;
- if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
- tempbl = 0xff;
- if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
- tempah |= 0x80;
- }
-
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x23, tempbl, tempah);
-
- if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->LCDInfo & SetLCDDualLink) {
- xgifb_reg_or(pVBInfo->Part4Port, 0x27, 0x20);
- xgifb_reg_or(pVBInfo->Part4Port, 0x34, 0x10);
- }
- }
-}
-
-void XGI_UnLockCRT2(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
-}
-
-void XGI_LockCRT2(struct vb_device_info *pVBInfo)
-{
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
-}
-
-unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
- unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- static const u8 LCDARefreshIndex[] = {
- 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00 };
-
- unsigned short RefreshRateTableIndex, i, index, temp;
-
- index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
- index >>= pVBInfo->SelectCRT2Rate;
- index &= 0x0F;
-
- if (pVBInfo->LCDInfo & LCDNonExpanding)
- index = 0;
-
- if (index > 0)
- index--;
-
- if (pVBInfo->SetFlag & ProgrammingCRT2) {
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
- temp = LCDARefreshIndex[pVBInfo->LCDResInfo & 0x07];
-
- if (index > temp)
- index = temp;
- }
- }
-
- RefreshRateTableIndex = XGI330_EModeIDTable[ModeIdIndex].REFindex;
- ModeNo = XGI330_RefIndex[RefreshRateTableIndex].ModeID;
- if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
- if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 800) &&
- (XGI330_RefIndex[RefreshRateTableIndex].YRes == 600)) {
- index++;
- }
- /* do the similar adjustment like XGISearchCRT1Rate() */
- if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1024) &&
- (XGI330_RefIndex[RefreshRateTableIndex].YRes == 768)) {
- index++;
- }
- if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
- (XGI330_RefIndex[RefreshRateTableIndex].YRes == 1024)) {
- index++;
- }
- }
-
- i = 0;
- do {
- if (XGI330_RefIndex[RefreshRateTableIndex + i].ModeID != ModeNo)
- break;
- temp = XGI330_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
- temp &= ModeTypeMask;
- if (temp < pVBInfo->ModeType)
- break;
- i++;
- index--;
-
- } while (index != 0xFFFF);
- if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- temp = XGI330_RefIndex[RefreshRateTableIndex + i - 1].Ext_InfoFlag;
- if (temp & InterlaceMode)
- i++;
- }
- }
- i--;
- if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
- temp = XGI_AjustCRT2Rate(ModeIdIndex, RefreshRateTableIndex,
- &i, pVBInfo);
- }
- return RefreshRateTableIndex + i;
-}
-
-static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short RefreshRateTableIndex;
-
- pVBInfo->SetFlag |= ProgrammingCRT2;
- RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
- ModeIdIndex, pVBInfo);
- XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo);
- XGI_GetLVDSData(ModeIdIndex, pVBInfo);
- XGI_ModCRT1Regs(ModeIdIndex, HwDeviceExtension, pVBInfo);
- XGI_SetLVDSRegs(ModeIdIndex, pVBInfo);
- XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-}
-
-static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short ModeIdIndex, RefreshRateTableIndex;
-
- pVBInfo->SetFlag |= ProgrammingCRT2;
- XGI_SearchModeID(ModeNo, &ModeIdIndex);
- pVBInfo->SelectCRT2Rate = 4;
- RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
- ModeIdIndex, pVBInfo);
- XGI_SaveCRT2Info(ModeNo, pVBInfo);
- XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo);
- XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetLockRegs(ModeNo, ModeIdIndex, pVBInfo);
- XGI_SetGroup2(ModeNo, ModeIdIndex, pVBInfo);
- XGI_SetLCDRegs(ModeIdIndex, pVBInfo);
- XGI_SetTap4Regs(pVBInfo);
- XGI_SetGroup3(ModeIdIndex, pVBInfo);
- XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetGroup5(pVBInfo);
- XGI_AutoThreshold(pVBInfo);
- return 1;
-}
-
-void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
-{
- unsigned char CRTCData[17] = { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81,
- 0x0B, 0x3E, 0xE9, 0x0B, 0xDF, 0xE7, 0x04, 0x00, 0x00,
- 0x05, 0x00 };
-
- unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
-
- unsigned char CR17, CR63, SR31;
- unsigned short temp;
-
- int i;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
-
- /* to fix XG42 single LCD sense to CRT+LCD */
- xgifb_reg_set(pVBInfo->P3d4, 0x57, 0x4A);
- xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
- pVBInfo->P3d4, 0x53) | 0x02));
-
- SR31 = xgifb_reg_get(pVBInfo->P3c4, 0x31);
- CR63 = xgifb_reg_get(pVBInfo->P3d4, 0x63);
- SR01 = xgifb_reg_get(pVBInfo->P3c4, 0x01);
-
- xgifb_reg_set(pVBInfo->P3c4, 0x01, (unsigned char)(SR01 & 0xDF));
- xgifb_reg_set(pVBInfo->P3d4, 0x63, (unsigned char)(CR63 & 0xBF));
-
- CR17 = xgifb_reg_get(pVBInfo->P3d4, 0x17);
- xgifb_reg_set(pVBInfo->P3d4, 0x17, (unsigned char)(CR17 | 0x80));
-
- SR1F = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
- xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char)(SR1F | 0x04));
-
- SR07 = xgifb_reg_get(pVBInfo->P3c4, 0x07);
- xgifb_reg_set(pVBInfo->P3c4, 0x07, (unsigned char)(SR07 & 0xFB));
- SR06 = xgifb_reg_get(pVBInfo->P3c4, 0x06);
- xgifb_reg_set(pVBInfo->P3c4, 0x06, (unsigned char)(SR06 & 0xC3));
-
- xgifb_reg_set(pVBInfo->P3d4, 0x11, 0x00);
-
- for (i = 0; i < 8; i++)
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)i, CRTCData[i]);
-
- for (i = 8; i < 11; i++)
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 8),
- CRTCData[i]);
-
- for (i = 11; i < 13; i++)
- xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 4),
- CRTCData[i]);
-
- for (i = 13; i < 16; i++)
- xgifb_reg_set(pVBInfo->P3c4, (unsigned short)(i - 3),
- CRTCData[i]);
-
- xgifb_reg_set(pVBInfo->P3c4, 0x0E, (unsigned char)(CRTCData[16]
- & 0xE0));
-
- xgifb_reg_set(pVBInfo->P3c4, 0x31, 0x00);
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE1);
-
- outb(0x00, pVBInfo->P3c8);
-
- for (i = 0; i < 256 * 3; i++)
- outb(0x0F, (pVBInfo->P3c8 + 1)); /* DAC_TEST_PARMS */
-
- mdelay(1);
-
- XGI_WaitDisply(pVBInfo);
- temp = inb(pVBInfo->P3c2);
-
- if (temp & 0x10)
- xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x20);
- else
- xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x00);
-
- /* avoid display something, set BLACK DAC if not restore DAC */
- outb(0x00, pVBInfo->P3c8);
-
- for (i = 0; i < 256 * 3; i++)
- outb(0, (pVBInfo->P3c8 + 1));
-
- xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01);
- xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63);
- xgifb_reg_set(pVBInfo->P3c4, 0x31, SR31);
-
- xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
- pVBInfo->P3d4, 0x53) & 0xFD));
- xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char)SR1F);
-}
-
-static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempah;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
- /* Power on */
- xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20);
-
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV |
- SetCRT2ToRAMDAC)) {
- tempah = xgifb_reg_get(pVBInfo->P3c4, 0x32);
- tempah &= 0xDF;
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC))
- tempah |= 0x20;
- }
- xgifb_reg_set(pVBInfo->P3c4, 0x32, tempah);
- xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x20);
-
- tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
-
- if (!(tempah & 0x80))
- xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
- xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
- }
-
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
- xgifb_reg_and_or(pVBInfo->Part2Port, 0x00, ~0xE0,
- 0x20); /* shampoo 0129 */
- if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBInfo &
- (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
- /* LVDS PLL power on */
- xgifb_reg_and(pVBInfo->Part4Port, 0x2A,
- 0x7F);
- /* LVDS Driver power on */
- xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x7F);
- }
- }
-
- tempah = 0x00;
-
- if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
- tempah = 0xc0;
-
- if (!(pVBInfo->VBInfo & SetSimuScanMode) &&
- (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
- (pVBInfo->VBInfo & SetCRT2ToDualEdge)) {
- tempah = tempah & 0x40;
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
- tempah = tempah ^ 0xC0;
- }
- }
-
- /* EnablePart4_1F */
- xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
-
- XGI_DisableGatingCRT(pVBInfo);
- XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
- } /* 301 */
- else { /* LVDS */
- if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD
- | XGI_SetCRT2ToLCDA))
- /* enable CRT2 */
- xgifb_reg_or(pVBInfo->Part1Port, 0x1E, 0x20);
-
- tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
- if (!(tempah & 0x80))
- xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
-
- xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
- XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
- } /* End of VB */
-}
-
-static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo, unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned short RefreshRateTableIndex, temp;
-
- XGI_SetSeqRegs(pVBInfo);
- outb(XGI330_StandTable.MISC, pVBInfo->P3c2);
- XGI_SetCRTCRegs(pVBInfo);
- XGI_SetATTRegs(ModeIdIndex, pVBInfo);
- XGI_SetGRCRegs(pVBInfo);
- XGI_ClearExt1Regs(pVBInfo);
-
- if (HwDeviceExtension->jChipType == XG27) {
- if (pVBInfo->IF_DEF_LVDS == 0)
- XGI_SetDefaultVCLK(pVBInfo);
- }
-
- temp = ~ProgrammingCRT2;
- pVBInfo->SetFlag &= temp;
- pVBInfo->SelectCRT2Rate = 0;
-
- if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
- | VB_SIS302LV | VB_XGI301C)) {
- if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA
- | SetInSlaveMode)) {
- pVBInfo->SetFlag |= ProgrammingCRT2;
- }
- }
-
- RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
- ModeIdIndex, pVBInfo);
- if (RefreshRateTableIndex != 0xFFFF) {
- XGI_SetSync(RefreshRateTableIndex, pVBInfo);
- XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex,
- pVBInfo, HwDeviceExtension);
- XGI_SetCRT1DE(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
- XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
- HwDeviceExtension, pVBInfo);
- XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension,
- RefreshRateTableIndex, pVBInfo);
- }
-
- if (HwDeviceExtension->jChipType >= XG21) {
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
- if (temp & 0xA0) {
- if (HwDeviceExtension->jChipType == XG27)
- XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo);
- else
- XGI_SetXG21CRTC(RefreshRateTableIndex, pVBInfo);
-
- XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
- RefreshRateTableIndex);
-
- xgifb_set_lcd(HwDeviceExtension->jChipType,
- pVBInfo, RefreshRateTableIndex);
-
- if (pVBInfo->IF_DEF_LVDS == 1)
- xgifb_set_lvds(xgifb_info,
- HwDeviceExtension->jChipType,
- ModeIdIndex, pVBInfo);
- }
- }
-
- pVBInfo->SetFlag &= (~ProgrammingCRT2);
- XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo);
- XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex,
- RefreshRateTableIndex, pVBInfo);
- XGI_LoadDAC(pVBInfo);
-}
-
-unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo)
-{
- unsigned short ModeIdIndex;
- struct vb_device_info VBINF;
- struct vb_device_info *pVBInfo = &VBINF;
-
- pVBInfo->IF_DEF_LVDS = 0;
-
- if (HwDeviceExtension->jChipType >= XG20)
- pVBInfo->VBType = 0; /* set VBType default 0 */
-
- XGIRegInit(pVBInfo, xgifb_info->vga_base);
-
- /* for x86 Linux, XG21 LVDS */
- if (HwDeviceExtension->jChipType == XG21) {
- if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0)
- pVBInfo->IF_DEF_LVDS = 1;
- }
- if (HwDeviceExtension->jChipType == XG27) {
- if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
- if (xgifb_reg_get(pVBInfo->P3d4, 0x30) & 0x20)
- pVBInfo->IF_DEF_LVDS = 1;
- }
- }
-
- InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
- if (ModeNo & 0x80)
- ModeNo = ModeNo & 0x7F;
- xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
-
- if (HwDeviceExtension->jChipType < XG20)
- XGI_UnLockCRT2(pVBInfo);
-
- XGI_SearchModeID(ModeNo, &ModeIdIndex);
-
- if (HwDeviceExtension->jChipType < XG20) {
- XGI_GetVBInfo(ModeIdIndex, pVBInfo);
- XGI_GetTVInfo(ModeIdIndex, pVBInfo);
- XGI_GetLCDInfo(ModeIdIndex, pVBInfo);
- XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
-
- if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) ||
- !(pVBInfo->VBInfo & SwitchCRT2)) {
- XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
- ModeIdIndex, pVBInfo);
-
- if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
- HwDeviceExtension, pVBInfo);
- }
- }
-
- if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchCRT2)) {
- switch (HwDeviceExtension->ujVBChipID) {
- case VB_CHIP_301: /* fall through */
- case VB_CHIP_302:
- /* add for CRT2 */
- XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
- pVBInfo);
- break;
-
- default:
- break;
- }
- }
-
- XGI_SetCRT2ModeRegs(pVBInfo);
- XGI_OEM310Setting(ModeIdIndex, pVBInfo); /* 0212 */
- XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
- } /* !XG20 */
- else {
- if (pVBInfo->IF_DEF_LVDS == 1)
- if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo,
- ModeIdIndex))
- return 0;
-
- pVBInfo->ModeType =
- XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag
- & ModeTypeMask;
-
- pVBInfo->SetFlag = 0;
- pVBInfo->VBInfo = DisableCRT2Display;
-
- XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
-
- XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
- ModeIdIndex, pVBInfo);
-
- XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
- }
-
- XGI_UpdateModeInfo(pVBInfo);
-
- if (HwDeviceExtension->jChipType < XG20)
- XGI_LockCRT2(pVBInfo);
-
- return 1;
-}
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
deleted file mode 100644
index 5904ed1f2686..000000000000
--- a/drivers/staging/xgifb/vb_setmode.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VBSETMODE_
-#define _VBSETMODE_
-
-void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo);
-void XGI_UnLockCRT2(struct vb_device_info *pVBInfo);
-void XGI_LockCRT2(struct vb_device_info *pVBInfo);
-void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *pXGIHWDE,
- struct vb_device_info *pVBInfo);
-void XGI_GetVBType(struct vb_device_info *pVBInfo);
-void XGI_SenseCRT1(struct vb_device_info *pVBInfo);
-unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo);
-
-unsigned char XGI_SearchModeID(unsigned short ModeNo,
- unsigned short *ModeIdIndex);
-unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
- unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo);
-
-#endif
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
deleted file mode 100644
index e256f72f6d8a..000000000000
--- a/drivers/staging/xgifb/vb_struct.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VB_STRUCT_
-#define _VB_STRUCT_
-#include "../../video/fbdev/sis/vstruct.h"
-
-struct XGI_LVDSCRT1HDataStruct {
- unsigned char Reg[8];
-};
-
-struct XGI_LVDSCRT1VDataStruct {
- unsigned char Reg[7];
-};
-
-struct XGI_ExtStruct {
- unsigned char Ext_ModeID;
- unsigned short Ext_ModeFlag;
- unsigned short Ext_ModeInfo;
- unsigned char Ext_RESINFO;
- unsigned char VB_ExtTVYFilterIndex;
- unsigned char REFindex;
-};
-
-struct XGI_Ext2Struct {
- unsigned short Ext_InfoFlag;
- unsigned char Ext_CRT1CRTC;
- unsigned char Ext_CRTVCLK;
- unsigned char Ext_CRT2CRTC;
- unsigned char Ext_CRT2CRTC2;
- unsigned char ModeID;
- unsigned short XRes;
- unsigned short YRes;
-};
-
-struct XGI_ECLKDataStruct {
- unsigned char SR2E, SR2F, SR30;
- unsigned short CLOCK;
-};
-
-/*add for new UNIVGABIOS*/
-struct XGI_LCDDesStruct {
- unsigned short LCDHDES;
- unsigned short LCDHRS;
- unsigned short LCDVDES;
- unsigned short LCDVRS;
-};
-
-struct XGI330_LCDDataDesStruct2 {
- unsigned short LCDHDES;
- unsigned short LCDHRS;
- unsigned short LCDVDES;
- unsigned short LCDVRS;
- unsigned short LCDHSync;
- unsigned short LCDVSync;
-};
-
-struct XGI330_LCDDataTablStruct {
- unsigned char PANELID;
- unsigned short MASK;
- unsigned short CAP;
- void const *DATAPTR;
-};
-
-struct XGI330_TVDataTablStruct {
- unsigned short MASK;
- unsigned short CAP;
- struct SiS_TVData const *DATAPTR;
-};
-
-struct XGI_TimingHStruct {
- unsigned char data[8];
-};
-
-struct XGI_TimingVStruct {
- unsigned char data[7];
-};
-
-struct XGI_XG21CRT1Struct {
- unsigned char ModeID, CR02, CR03, CR15, CR16;
-};
-
-struct XGI330_LCDCapStruct {
- unsigned char LCD_ID;
- unsigned short LCD_Capability;
- unsigned char LCD_HSyncWidth;
- unsigned char LCD_VSyncWidth;
- unsigned char LCD_VCLK;
- unsigned char LCDA_VCLKData1;
- unsigned char LCDA_VCLKData2;
- unsigned char LCUCHAR_VCLKData1;
- unsigned char LCUCHAR_VCLKData2;
- unsigned char Spectrum_31;
- unsigned char Spectrum_32;
- unsigned char Spectrum_33;
- unsigned char Spectrum_34;
-};
-
-struct XGI21_LVDSCapStruct {
- unsigned short LVDS_Capability;
- unsigned short LVDSHT;
- unsigned short LVDSVT;
- unsigned short LVDSHDE;
- unsigned short LVDSVDE;
- unsigned short LVDSHFP;
- unsigned short LVDSVFP;
- unsigned short LVDSHSYNC;
- unsigned short LVDSVSYNC;
- unsigned char VCLKData1;
- unsigned char VCLKData2;
- unsigned char PSC_S1; /* Duration between CPL on and signal on */
- unsigned char PSC_S2; /* Duration signal on and Vdd on */
- unsigned char PSC_S3; /* Duration between CPL off and signal off */
- unsigned char PSC_S4; /* Duration signal off and Vdd off */
- unsigned char PSC_S5;
-};
-
-struct XGI_CRT1TableStruct {
- unsigned char CR[16];
-};
-
-struct XGI301C_Tap4TimingStruct {
- unsigned short DE;
- unsigned char Reg[64]; /* C0-FF */
-};
-
-struct vb_device_info {
- unsigned long P3c4, P3d4, P3c0, P3ce, P3c2, P3cc;
- unsigned long P3ca, P3c6, P3c7, P3c8, P3c9, P3da;
- unsigned long Part0Port, Part1Port, Part2Port;
- unsigned long Part3Port, Part4Port, Part5Port;
- unsigned short RVBHCFACT, RVBHCMAX, RVBHRS;
- unsigned short VGAVT, VGAHT, VGAVDE, VGAHDE;
- unsigned short VT, HT, VDE, HDE;
- unsigned short LCDHRS, LCDVRS, LCDHDES, LCDVDES;
-
- unsigned short ModeType;
- unsigned short IF_DEF_LVDS;
- unsigned short IF_DEF_CRT2Monitor;
- unsigned short IF_DEF_YPbPr;
- unsigned short IF_DEF_HiVision;
- unsigned short LCDResInfo, LCDTypeInfo, VBType;/*301b*/
- unsigned short VBInfo, TVInfo, LCDInfo;
- unsigned short SetFlag;
- unsigned short NewFlickerMode;
- unsigned short SelectCRT2Rate;
-
- void __iomem *FBAddr;
-
- unsigned char const *SR18;
- unsigned char const (*CR40)[3];
-
- struct SiS_MCLKData const *MCLKData;
-
- unsigned char XGINew_CR97;
-
- struct XGI330_LCDCapStruct const *LCDCapList;
-
- struct XGI_TimingHStruct TimingH;
- struct XGI_TimingVStruct TimingV;
-
- int ram_type;
- int ram_channel;
- int ram_bus;
-}; /* _struct vb_device_info */
-
-#endif /* _VB_STRUCT_ */
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
deleted file mode 100644
index 42ecf7fe6766..000000000000
--- a/drivers/staging/xgifb/vb_table.h
+++ /dev/null
@@ -1,2513 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VB_TABLE_
-#define _VB_TABLE_
-static const struct SiS_MCLKData XGI340New_MCLKData[] = {
- {0x16, 0x01, 0x01, 166},
- {0x19, 0x02, 0x01, 124},
- {0x7C, 0x08, 0x01, 200},
-};
-
-static const struct SiS_MCLKData XGI27New_MCLKData[] = {
- {0x5c, 0x23, 0x01, 166},
- {0x19, 0x02, 0x01, 124},
- {0x7C, 0x08, 0x80, 200},
-};
-
-const struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
- {0x5c, 0x23, 0x01, 166},
- {0x55, 0x84, 0x01, 123},
- {0x7C, 0x08, 0x01, 200},
-};
-
-static const unsigned char XG27_SR18[3] = {
- 0x32, 0x32, 0x42 /* SR18 */
-};
-
-static const unsigned char XGI340_SR18[3] = {
- 0x31, 0x42, 0x42 /* SR18 */
-};
-
-static const unsigned char XGI340_cr41[24][3] = {
- {0x20, 0x50, 0x60}, /* 0 CR41 */
- {0xc4, 0x40, 0x84}, /* 1 CR8A */
- {0xc4, 0x40, 0x84}, /* 2 CR8B */
- {0xb5, 0xa4, 0xa4},
- {0xf0, 0xf0, 0xf0},
- {0x90, 0x90, 0x24}, /* 5 CR68 */
- {0x77, 0x77, 0x44}, /* 6 CR69 */
- {0x77, 0x77, 0x44}, /* 7 CR6A */
- {0xff, 0xff, 0xff}, /* 8 CR6D */
- {0x55, 0x55, 0x55}, /* 9 CR80 */
- {0x00, 0x00, 0x00}, /* 10 CR81 */
- {0x88, 0xa8, 0x48}, /* 11 CR82 */
- {0x44, 0x44, 0x77}, /* 12 CR85 */
- {0x48, 0x48, 0x88}, /* 13 CR86 */
- {0x54, 0x54, 0x44}, /* 14 CR90 */
- {0x54, 0x54, 0x44}, /* 15 CR91 */
- {0x0a, 0x0a, 0x07}, /* 16 CR92 */
- {0x44, 0x44, 0x44}, /* 17 CR93 */
- {0x10, 0x10, 0x0A}, /* 18 CR94 */
- {0x11, 0x11, 0x0a}, /* 19 CR95 */
- {0x05, 0x05, 0x05}, /* 20 CR96 */
- {0xf0, 0xf0, 0xf0}, /* 21 CRC3 */
- {0x05, 0x00, 0x02}, /* 22 CRC4 */
- {0x00, 0x00, 0x00} /* 23 CRC5 */
-};
-
-static const unsigned char XGI27_cr41[24][3] = {
- {0x20, 0x40, 0x60}, /* 0 CR41 */
- {0xC4, 0x40, 0x84}, /* 1 CR8A */
- {0xC4, 0x40, 0x84}, /* 2 CR8B */
- {0xB3, 0x13, 0xa4}, /* 3 CR40[7],
- * CR99[2:0],
- * CR45[3:0]
- */
- {0xf0, 0xf5, 0xf0}, /* 4 CR59 */
- {0x90, 0x90, 0x24}, /* 5 CR68 */
- {0x77, 0x67, 0x44}, /* 6 CR69 */
- {0x77, 0x77, 0x44}, /* 7 CR6A */
- {0xff, 0xff, 0xff}, /* 8 CR6D */
- {0x55, 0x55, 0x55}, /* 9 CR80 */
- {0x00, 0x00, 0x00}, /* 10 CR81 */
- {0x88, 0xcc, 0x48}, /* 11 CR82 */
- {0x44, 0x88, 0x77}, /* 12 CR85 */
- {0x48, 0x88, 0x88}, /* 13 CR86 */
- {0x54, 0x32, 0x44}, /* 14 CR90 */
- {0x54, 0x33, 0x44}, /* 15 CR91 */
- {0x0a, 0x07, 0x07}, /* 16 CR92 */
- {0x44, 0x63, 0x44}, /* 17 CR93 */
- {0x10, 0x14, 0x0A}, /* 18 CR94 */
- {0x11, 0x0B, 0x0C}, /* 19 CR95 */
- {0x05, 0x22, 0x05}, /* 20 CR96 */
- {0xf0, 0xf0, 0x00}, /* 21 CRC3 */
- {0x05, 0x00, 0x02}, /* 22 CRC4 */
- {0x00, 0x00, 0x00} /* 23 CRC5 */
-};
-
-/* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
-const unsigned char XGI340_AGPReg[12] = {
- 0x28, 0x23, 0x00, 0x20, 0x00, 0x20,
- 0x00, 0x05, 0xd0, 0x10, 0x10, 0x00
-};
-
-const struct XGI_ExtStruct XGI330_EModeIDTable[] = {
- {0x2e, 0x0a1b, 0x0306, 0x06, 0x05, 0x06},
- {0x2f, 0x0a1b, 0x0305, 0x05, 0x05, 0x05},
- {0x30, 0x2a1b, 0x0407, 0x07, 0x07, 0x0e},
- {0x31, 0x0a1b, 0x030d, 0x0d, 0x06, 0x3d},
- {0x32, 0x0a1b, 0x0a0e, 0x0e, 0x06, 0x3e},
- {0x33, 0x0a1d, 0x0a0d, 0x0d, 0x06, 0x3d},
- {0x34, 0x2a1d, 0x0a0e, 0x0e, 0x06, 0x3e},
- {0x35, 0x0a1f, 0x0a0d, 0x0d, 0x06, 0x3d},
- {0x36, 0x2a1f, 0x0a0e, 0x0e, 0x06, 0x3e},
- {0x38, 0x0a1b, 0x0508, 0x08, 0x00, 0x16},
- {0x3a, 0x0e3b, 0x0609, 0x09, 0x00, 0x1e},
- {0x3c, 0x0e3b, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
- * add CRT2MODE [2003/10/07]
- */
- {0x3d, 0x0e7d, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
- * add CRT2MODE
- */
- {0x40, 0x9a1c, 0x0000, 0x00, 0x04, 0x00},
- {0x41, 0x9a1d, 0x0000, 0x00, 0x04, 0x00},
- {0x43, 0x0a1c, 0x0306, 0x06, 0x05, 0x06},
- {0x44, 0x0a1d, 0x0306, 0x06, 0x05, 0x06},
- {0x46, 0x2a1c, 0x0407, 0x07, 0x07, 0x0e},
- {0x47, 0x2a1d, 0x0407, 0x07, 0x07, 0x0e},
- {0x49, 0x0a3c, 0x0508, 0x08, 0x00, 0x16},
- {0x4a, 0x0a3d, 0x0508, 0x08, 0x00, 0x16},
- {0x4c, 0x0e7c, 0x0609, 0x09, 0x00, 0x1e},
- {0x4d, 0x0e7d, 0x0609, 0x09, 0x00, 0x1e},
- {0x50, 0x9a1b, 0x0001, 0x01, 0x04, 0x02},
- {0x51, 0xba1b, 0x0103, 0x03, 0x07, 0x03},
- {0x52, 0x9a1b, 0x0204, 0x04, 0x00, 0x04},
- {0x56, 0x9a1d, 0x0001, 0x01, 0x04, 0x02},
- {0x57, 0xba1d, 0x0103, 0x03, 0x07, 0x03},
- {0x58, 0x9a1d, 0x0204, 0x04, 0x00, 0x04},
- {0x59, 0x9a1b, 0x0000, 0x00, 0x04, 0x00},
- {0x5A, 0x021b, 0x0014, 0x01, 0x04, 0x3f},
- {0x5B, 0x0a1d, 0x0014, 0x01, 0x04, 0x3f},
- {0x5d, 0x0a1d, 0x0305, 0x05, 0x07, 0x05},
- {0x62, 0x0a3f, 0x0306, 0x06, 0x05, 0x06},
- {0x63, 0x2a3f, 0x0407, 0x07, 0x07, 0x0e},
- {0x64, 0x0a7f, 0x0508, 0x08, 0x00, 0x16},
- {0x65, 0x0eff, 0x0609, 0x09, 0x00, 0x1e},
- {0x66, 0x0eff, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
- * add CRT2MODE
- */
- {0x68, 0x067b, 0x080b, 0x0b, 0x00, 0x29},
- {0x69, 0x06fd, 0x080b, 0x0b, 0x00, 0x29},
- {0x6b, 0x07ff, 0x080b, 0x0b, 0x00, 0x29},
- {0x6c, 0x067b, 0x090c, 0x0c, 0x00, 0x2f},
- {0x6d, 0x06fd, 0x090c, 0x0c, 0x00, 0x2f},
- {0x6e, 0x07ff, 0x090c, 0x0c, 0x00, 0x2f},
- {0x70, 0x2a1b, 0x0410, 0x10, 0x07, 0x34},
- {0x71, 0x0a1b, 0x0511, 0x11, 0x00, 0x37},
- {0x74, 0x0a1d, 0x0511, 0x11, 0x00, 0x37},
- {0x75, 0x0a3d, 0x0612, 0x12, 0x00, 0x3a},
- {0x76, 0x2a1f, 0x0410, 0x10, 0x07, 0x34},
- {0x77, 0x0a1f, 0x0511, 0x11, 0x00, 0x37},
- {0x78, 0x0a3f, 0x0612, 0x12, 0x00, 0x3a},
- {0x79, 0x0a3b, 0x0612, 0x12, 0x00, 0x3a},
- {0x7a, 0x2a1d, 0x0410, 0x10, 0x07, 0x34},
- {0x7b, 0x0e3b, 0x060f, 0x0f, 0x00, 0x1d},
- {0x7c, 0x0e7d, 0x060f, 0x0f, 0x00, 0x1d},
- {0x7d, 0x0eff, 0x060f, 0x0f, 0x00, 0x1d},
- {0x20, 0x0e3b, 0x0D16, 0x16, 0x00, 0x43},
- {0x21, 0x0e7d, 0x0D16, 0x16, 0x00, 0x43},
- {0x22, 0x0eff, 0x0D16, 0x16, 0x00, 0x43},
- {0x23, 0x0e3b, 0x0614, 0x14, 0x00, 0x41},
- {0x24, 0x0e7d, 0x0614, 0x14, 0x00, 0x41},
- {0x25, 0x0eff, 0x0614, 0x14, 0x00, 0x41},
- {0x26, 0x063b, 0x0c15, 0x15, 0x00, 0x42},
- {0x27, 0x067d, 0x0c15, 0x15, 0x00, 0x42},
- {0x28, 0x06ff, 0x0c15, 0x15, 0x00, 0x42},
- {0xff, 0x0000, 0x0000, 0x00, 0x00, 0x00}
-};
-
-static const struct SiS_StandTable_S XGI330_StandTable = {
-/* ExtVGATable */
- 0x00, 0x00, 0x00, 0x0000,
- {0x21, 0x0f, 0x00, 0x0e}, /* 0x21 = 0x01 | (0x20 = screen off) */
- 0x23,
- {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x01, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
- 0xff}
-};
-
-static const struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] = {
- {0x01, 0x27, 0x91, 0x8f, 0xc0}, /* 00 */
- {0x03, 0x4f, 0x83, 0x8f, 0xc0}, /* 01 */
- {0x05, 0x27, 0x91, 0x8f, 0xc0}, /* 02 */
- {0x06, 0x4f, 0x83, 0x8f, 0xc0}, /* 03 */
- {0x07, 0x4f, 0x83, 0x8f, 0xc0}, /* 04 */
- {0x0d, 0x27, 0x91, 0x8f, 0xc0}, /* 05 */
- {0x0e, 0x4f, 0x83, 0x8f, 0xc0}, /* 06 */
- {0x0f, 0x4f, 0x83, 0x5d, 0xc0}, /* 07 */
- {0x10, 0x4f, 0x83, 0x5d, 0xc0}, /* 08 */
- {0x11, 0x4f, 0x83, 0xdf, 0x0c}, /* 09 */
- {0x12, 0x4f, 0x83, 0xdf, 0x0c}, /* 10 */
- {0x13, 0x4f, 0x83, 0x8f, 0xc0}, /* 11 */
- {0x2e, 0x4f, 0x83, 0xdf, 0x0c}, /* 12 */
- {0x2e, 0x4f, 0x87, 0xdf, 0xc0}, /* 13 */
- {0x2f, 0x4f, 0x83, 0x8f, 0xc0}, /* 14 */
- {0x50, 0x27, 0x91, 0xdf, 0x0c}, /* 15 */
- {0x59, 0x27, 0x91, 0x8f, 0xc0} /* 16 */
-};
-
-const struct XGI_CRT1TableStruct XGI_CRT1Table[] = {
- { {0x2d, 0x28, 0x90, 0x2c, 0x90, 0x00, 0x04, 0x00,
- 0xbf, 0x1f, 0x9c, 0x8e, 0x96, 0xb9, 0x30} }, /* 0x0 */
- { {0x2d, 0x28, 0x90, 0x2c, 0x90, 0x00, 0x04, 0x00,
- 0x0b, 0x3e, 0xe9, 0x8b, 0xe7, 0x04, 0x00} }, /* 0x1 */
- { {0x3D, 0x31, 0x81, 0x37, 0x1F, 0x00, 0x05, 0x00,
- 0x72, 0xF0, 0x58, 0x8C, 0x57, 0x73, 0xA0} }, /* 0x2 */
- { {0x4F, 0x3F, 0x93, 0x45, 0x0D, 0x00, 0x01, 0x00,
- 0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} }, /* 0x3 */
- { {0x5F, 0x50, 0x82, 0x55, 0x81, 0x00, 0x05, 0x00,
- 0xBF, 0x1F, 0x9C, 0x8E, 0x96, 0xB9, 0x30} }, /* 0x4 */
- { {0x5F, 0x50, 0x82, 0x55, 0x81, 0x00, 0x05, 0x00,
- 0x0B, 0x3E, 0xE9, 0x8B, 0xE7, 0x04, 0x00} }, /* 0x5 */
- { {0x63, 0x50, 0x86, 0x56, 0x9B, 0x00, 0x01, 0x00,
- 0x06, 0x3E, 0xE8, 0x8B, 0xE7, 0xFF, 0x10} }, /* 0x6 */
- { {0x64, 0x4F, 0x88, 0x55, 0x9D, 0x00, 0x01, 0x00,
- 0xF2, 0x1F, 0xE0, 0x83, 0xDF, 0xF3, 0x10} }, /* 0x7 */
- { {0x63, 0x4F, 0x87, 0x5A, 0x81, 0x00, 0x05, 0x00,
- 0xFB, 0x1F, 0xE0, 0x83, 0xDF, 0xFC, 0x10} }, /* 0x8 */
- { {0x65, 0x4F, 0x89, 0x58, 0x80, 0x00, 0x05, 0x60,
- 0xFB, 0x1F, 0xE0, 0x83, 0xDF, 0xFC, 0x80} }, /* 0x9 */
- { {0x65, 0x4F, 0x89, 0x58, 0x80, 0x00, 0x05, 0x60,
- 0x01, 0x3E, 0xE0, 0x83, 0xDF, 0x02, 0x80} }, /* 0xa */
- { {0x67, 0x4F, 0x8B, 0x58, 0x81, 0x00, 0x05, 0x60,
- 0x0D, 0x3E, 0xE0, 0x83, 0xDF, 0x0E, 0x90} }, /* 0xb */
- { {0x65, 0x4F, 0x89, 0x57, 0x9F, 0x00, 0x01, 0x00,
- 0xFB, 0x1F, 0xE6, 0x8A, 0xDF, 0xFC, 0x10} }, /* 0xc */
- /* 0D (800x600,56Hz) */
- { {0x7B, 0x63, 0x9F, 0x6A, 0x93, 0x00, 0x05, 0x00,
- /* (VCLK 36.0MHz) */
- 0x6F, 0xF0, 0x58, 0x8A, 0x57, 0x70, 0xA0} },
- /* 0E (800x600,60Hz) */
- { {0x7F, 0x63, 0x83, 0x6C, 0x1C, 0x00, 0x06, 0x00,
- /* (VCLK 40.0MHz) */
- 0x72, 0xF0, 0x58, 0x8C, 0x57, 0x73, 0xA0} },
- /* 0F (800x600,72Hz) */
- { {0x7D, 0x63, 0x81, 0x6E, 0x1D, 0x00, 0x06, 0x00,
- /* (VCLK 50.0MHz) */
- 0x98, 0xF0, 0x7C, 0x82, 0x57, 0x99, 0x80} },
- /* 10 (800x600,75Hz) */
- { {0x7F, 0x63, 0x83, 0x69, 0x13, 0x00, 0x06, 0x00,
- /* (VCLK 49.5MHz) */
- 0x6F, 0xF0, 0x58, 0x8B, 0x57, 0x70, 0xA0} },
- /* 11 (800x600,85Hz) */
- { {0x7E, 0x63, 0x82, 0x6B, 0x13, 0x00, 0x06, 0x00,
- /* (VCLK 56.25MHz) */
- 0x75, 0xF0, 0x58, 0x8B, 0x57, 0x76, 0xA0} },
- /* 12 (800x600,100Hz) */
- { {0x81, 0x63, 0x85, 0x6D, 0x18, 0x00, 0x06, 0x60,
- /* (VCLK 75.8MHz) */
- 0x7A, 0xF0, 0x58, 0x8B, 0x57, 0x7B, 0xA0} },
- /* 13 (800x600,120Hz) */
- { {0x83, 0x63, 0x87, 0x6E, 0x19, 0x00, 0x06, 0x60,
- /* (VCLK 79.411MHz) */
- 0x81, 0xF0, 0x58, 0x8B, 0x57, 0x82, 0xA0} },
- /* 14 (800x600,160Hz) */
- { {0x85, 0x63, 0x89, 0x6F, 0x1A, 0x00, 0x06, 0x60,
- /* (VCLK 105.822MHz) */
- 0x91, 0xF0, 0x58, 0x8B, 0x57, 0x92, 0xA0} },
- { {0x99, 0x7F, 0x9D, 0x84, 0x1A, 0x00, 0x02, 0x00,
- 0x96, 0x1F, 0x7F, 0x83, 0x7F, 0x97, 0x10} }, /* 0x15 */
- { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00,
- 0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} }, /* 0x16 */
- { {0xA1, 0x7F, 0x85, 0x86, 0x97, 0x00, 0x02, 0x00,
- 0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} }, /* 0x17 */
- { {0x9F, 0x7F, 0x83, 0x85, 0x91, 0x00, 0x02, 0x00,
- 0x1E, 0xF5, 0x00, 0x83, 0xFF, 0x1F, 0x90} }, /* 0x18 */
- { {0xA7, 0x7F, 0x8B, 0x89, 0x95, 0x00, 0x02, 0x00,
- 0x26, 0xF5, 0x00, 0x83, 0xFF, 0x27, 0x90} }, /* 0x19 */
- { {0xA9, 0x7F, 0x8D, 0x8C, 0x9A, 0x00, 0x02, 0x62,
- 0x2C, 0xF5, 0x00, 0x83, 0xFF, 0x2D, 0x14} }, /* 0x1a */
- { {0xAB, 0x7F, 0x8F, 0x8D, 0x9B, 0x00, 0x02, 0x62,
- 0x35, 0xF5, 0x00, 0x83, 0xFF, 0x36, 0x14} }, /* 0x1b */
- { {0xCF, 0x9F, 0x93, 0xB2, 0x01, 0x00, 0x03, 0x00,
- 0x14, 0xBA, 0x00, 0x83, 0xFF, 0x15, 0x00} }, /* 0x1c */
- { {0xCE, 0x9F, 0x92, 0xA9, 0x17, 0x00, 0x07, 0x00,
- 0x28, 0x5A, 0x00, 0x83, 0xFF, 0x29, 0x89} }, /* 0x1d */
- { {0xCE, 0x9F, 0x92, 0xA5, 0x17, 0x00, 0x07, 0x00,
- 0x28, 0x5A, 0x00, 0x83, 0xFF, 0x29, 0x89} }, /* 0x1e */
- { {0xD3, 0x9F, 0x97, 0xAB, 0x1F, 0x00, 0x07, 0x00,
- 0x2E, 0x5A, 0x00, 0x83, 0xFF, 0x2F, 0x89} }, /* 0x1f */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x20 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x21 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x22 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x23 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x24 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x25 */
- { {0x09, 0xC7, 0x8D, 0xD3, 0x0B, 0x01, 0x04, 0x00,
- 0xE0, 0x10, 0xB0, 0x83, 0xAF, 0xE1, 0x2F} }, /* 0x26 */
- { {0x40, 0xEF, 0x84, 0x03, 0x1D, 0x41, 0x01, 0x00,
- 0xDA, 0x1F, 0xA0, 0x83, 0x9F, 0xDB, 0x1F} }, /* 0x27 */
- { {0x43, 0xEF, 0x87, 0x06, 0x00, 0x41, 0x05, 0x62,
- 0xD4, 0x1F, 0xA0, 0x83, 0x9F, 0xD5, 0x9F} }, /* 0x28 */
- { {0x45, 0xEF, 0x89, 0x07, 0x01, 0x41, 0x05, 0x62,
- 0xD9, 0x1F, 0xA0, 0x83, 0x9F, 0xDA, 0x9F} }, /* 0x29 */
- { {0x40, 0xEF, 0x84, 0x03, 0x1D, 0x41, 0x01, 0x00,
- 0xDA, 0x1F, 0xA0, 0x83, 0x9F, 0xDB, 0x1F} }, /* 0x2a */
- { {0x40, 0xEF, 0x84, 0x03, 0x1D, 0x41, 0x01, 0x00,
- 0xDA, 0x1F, 0xA0, 0x83, 0x9F, 0xDB, 0x1F} }, /* 0x2b */
- { {0x40, 0xEF, 0x84, 0x03, 0x1D, 0x41, 0x01, 0x00,
- 0xDA, 0x1F, 0xA0, 0x83, 0x9F, 0xDB, 0x1F} }, /* 0x2c */
- { {0x59, 0xFF, 0x9D, 0x17, 0x13, 0x41, 0x05, 0x44,
- 0x33, 0xBA, 0x00, 0x83, 0xFF, 0x34, 0x0F} }, /* 0x2d */
- { {0x5B, 0xFF, 0x9F, 0x18, 0x14, 0x41, 0x05, 0x44,
- 0x38, 0xBA, 0x00, 0x83, 0xFF, 0x39, 0x0F} }, /* 0x2e */
- { {0x5B, 0xFF, 0x9F, 0x18, 0x14, 0x41, 0x05, 0x44,
- 0x3D, 0xBA, 0x00, 0x83, 0xFF, 0x3E, 0x0F} }, /* 0x2f */
- { {0x5D, 0xFF, 0x81, 0x19, 0x95, 0x41, 0x05, 0x44,
- 0x41, 0xBA, 0x00, 0x84, 0xFF, 0x42, 0x0F} }, /* 0x30 */
- { {0x55, 0xFF, 0x99, 0x0D, 0x0C, 0x41, 0x05, 0x00,
- 0x3E, 0xBA, 0x00, 0x84, 0xFF, 0x3F, 0x0F} }, /* 0x31 */
- { {0x7F, 0x63, 0x83, 0x6C, 0x1C, 0x00, 0x06, 0x00,
- 0x72, 0xBA, 0x27, 0x8B, 0xDF, 0x73, 0x80} }, /* 0x32 */
- { {0x7F, 0x63, 0x83, 0x69, 0x13, 0x00, 0x06, 0x00,
- 0x6F, 0xBA, 0x26, 0x89, 0xDF, 0x6F, 0x80} }, /* 0x33 */
- { {0x7F, 0x63, 0x82, 0x6B, 0x13, 0x00, 0x06, 0x00,
- 0x75, 0xBA, 0x29, 0x8C, 0xDF, 0x75, 0x80} }, /* 0x34 */
- { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00,
- 0x24, 0xF1, 0xAF, 0x85, 0x3F, 0x25, 0xB0} }, /* 0x35 */
- { {0x9F, 0x7F, 0x83, 0x85, 0x91, 0x00, 0x02, 0x00,
- 0x1E, 0xF1, 0xAD, 0x81, 0x3F, 0x1F, 0xB0} }, /* 0x36 */
- { {0xA7, 0x7F, 0x88, 0x89, 0x15, 0x00, 0x02, 0x00,
- 0x26, 0xF1, 0xB1, 0x85, 0x3F, 0x27, 0xB0} }, /* 0x37 */
- { {0xCE, 0x9F, 0x92, 0xA9, 0x17, 0x00, 0x07, 0x00,
- 0x28, 0xC4, 0x7A, 0x8E, 0xCF, 0x29, 0xA1} }, /* 0x38 */
- { {0xCE, 0x9F, 0x92, 0xA5, 0x17, 0x00, 0x07, 0x00,
- 0x28, 0xD4, 0x7A, 0x8E, 0xCF, 0x29, 0xA1} }, /* 0x39 */
- { {0xD3, 0x9F, 0x97, 0xAB, 0x1F, 0x00, 0x07, 0x00,
- 0x2E, 0xD4, 0x7D, 0x81, 0xCF, 0x2F, 0xA1} }, /* 0x3a */
- { {0xDC, 0x9F, 0x00, 0xAB, 0x19, 0x00, 0x07, 0x00,
- 0xE6, 0xEF, 0xC0, 0xC3, 0xBF, 0xE7, 0x90} }, /* 0x3b */
- { {0x6B, 0x59, 0x8F, 0x5E, 0x8C, 0x00, 0x05, 0x00,
- 0x0B, 0x3E, 0xE9, 0x8B, 0xE7, 0x04, 0x00} }, /* 0x3c */
- { {0x7B, 0x63, 0x9F, 0x6A, 0x93, 0x00, 0x05, 0x00,
- 0x6F, 0xF0, 0x58, 0x8A, 0x57, 0x70, 0xA0} }, /* 0x3d */
- { {0x86, 0x6A, 0x8a, 0x74, 0x06, 0x00, 0x02, 0x00,
- 0x8c, 0x15, 0x4f, 0x83, 0xef, 0x8d, 0x30} }, /* 0x3e */
- { {0x81, 0x6A, 0x85, 0x70, 0x00, 0x00, 0x02, 0x00,
- 0x0f, 0x3e, 0xeb, 0x8e, 0xdf, 0x10, 0x00} }, /* 0x3f */
- { {0xCE, 0x9F, 0x92, 0xA9, 0x17, 0x00, 0x07, 0x00,
- 0x20, 0xF5, 0x03, 0x88, 0xFF, 0x21, 0x90} }, /* 0x40 */
- { {0xE6, 0xAE, 0x8A, 0xBD, 0x90, 0x00, 0x03, 0x00,
- 0x3D, 0x10, 0x1A, 0x8D, 0x19, 0x3E, 0x2F} }, /* 0x41 */
- { {0xB9, 0x8F, 0x9D, 0x9B, 0x8A, 0x00, 0x06, 0x00,
- 0x7D, 0xFF, 0x60, 0x83, 0x5F, 0x7E, 0x90} }, /* 0x42 */
- { {0xC3, 0x8F, 0x87, 0x9B, 0x0B, 0x00, 0x07, 0x00,
- 0x82, 0xFF, 0x60, 0x83, 0x5F, 0x83, 0x90} }, /* 0x43 */
- { {0xAD, 0x7F, 0x91, 0x8E, 0x9C, 0x00, 0x02, 0x82,
- 0x49, 0xF5, 0x00, 0x83, 0xFF, 0x4A, 0x90} }, /* 0x44 */
- { {0xCD, 0x9F, 0x91, 0xA7, 0x19, 0x00, 0x07, 0x60,
- 0xE6, 0xFF, 0xC0, 0x83, 0xBF, 0xE7, 0x90} }, /* 0x45 */
- { {0xD3, 0x9F, 0x97, 0xAB, 0x1F, 0x00, 0x07, 0x60,
- 0xF1, 0xFF, 0xC0, 0x83, 0xBF, 0xF2, 0x90} }, /* 0x46 */
- { {0xD7, 0x9F, 0x9B, 0xAC, 0x1E, 0x00, 0x07, 0x00,
- 0x03, 0xDE, 0xC0, 0x84, 0xBF, 0x04, 0x90} } /* 0x47 */
-};
-
-/*add for new UNIVGABIOS*/
-static const struct SiS_LCDData XGI_StLCD1024x768Data[] = {
- {62, 25, 800, 546, 1344, 806},
- {32, 15, 930, 546, 1344, 806},
- {62, 25, 800, 546, 1344, 806}, /*chiawenfordot9->dot8*/
- {104, 45, 945, 496, 1344, 806},
- {62, 25, 800, 546, 1344, 806},
- {31, 18, 1008, 624, 1344, 806},
- {1, 1, 1344, 806, 1344, 806}
-};
-
-static const struct SiS_LCDData XGI_ExtLCD1024x768Data[] = {
- {42, 25, 1536, 419, 1344, 806},
- {48, 25, 1536, 369, 1344, 806},
- {42, 25, 1536, 419, 1344, 806},
- {48, 25, 1536, 369, 1344, 806},
- {12, 5, 896, 500, 1344, 806},
- {42, 25, 1024, 625, 1344, 806},
- {1, 1, 1344, 806, 1344, 806},
- {12, 5, 896, 500, 1344, 806},
- {42, 25, 1024, 625, 1344, 806},
- {1, 1, 1344, 806, 1344, 806},
- {12, 5, 896, 500, 1344, 806},
- {42, 25, 1024, 625, 1344, 806},
- {1, 1, 1344, 806, 1344, 806}
-};
-
-static const struct SiS_LCDData XGI_CetLCD1024x768Data[] = {
- {1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {1, 1, 1344, 806, 1344, 806}, /* 01 (320x350,640x350) */
- {1, 1, 1344, 806, 1344, 806}, /* 02 (360x400,720x400) */
- {1, 1, 1344, 806, 1344, 806}, /* 03 (720x350) */
- {1, 1, 1344, 806, 1344, 806}, /* 04 (640x480x60Hz) */
- {1, 1, 1344, 806, 1344, 806}, /* 05 (800x600x60Hz) */
- {1, 1, 1344, 806, 1344, 806} /* 06 (1024x768x60Hz) */
-};
-
-static const struct SiS_LCDData XGI_StLCD1280x1024Data[] = {
- {22, 5, 800, 510, 1650, 1088},
- {22, 5, 800, 510, 1650, 1088},
- {176, 45, 900, 510, 1650, 1088},
- {176, 45, 900, 510, 1650, 1088},
- {22, 5, 800, 510, 1650, 1088},
- {13, 5, 1024, 675, 1560, 1152},
- {16, 9, 1266, 804, 1688, 1072},
- {1, 1, 1688, 1066, 1688, 1066}
-};
-
-static const struct SiS_LCDData XGI_ExtLCD1280x1024Data[] = {
- {211, 60, 1024, 501, 1688, 1066},
- {211, 60, 1024, 508, 1688, 1066},
- {211, 60, 1024, 501, 1688, 1066},
- {211, 60, 1024, 508, 1688, 1066},
- {211, 60, 1024, 500, 1688, 1066},
- {211, 75, 1024, 625, 1688, 1066},
- {211, 120, 1280, 798, 1688, 1066},
- {1, 1, 1688, 1066, 1688, 1066}
-};
-
-static const struct SiS_LCDData XGI_CetLCD1280x1024Data[] = {
- {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 02 (360x400,720x400) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 03 (720x350) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 04 (640x480x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 05 (800x600x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 06 (1024x768x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct SiS_LCDData xgifb_lcd_1400x1050[] = {
- {211, 100, 2100, 408, 1688, 1066}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {211, 64, 1536, 358, 1688, 1066}, /* 01 (320x350,640x350) */
- {211, 100, 2100, 408, 1688, 1066}, /* 02 (360x400,720x400) */
- {211, 64, 1536, 358, 1688, 1066}, /* 03 (720x350) */
- {211, 48, 840, 488, 1688, 1066}, /* 04 (640x480x60Hz) */
- {211, 72, 1008, 609, 1688, 1066}, /* 05 (800x600x60Hz) */
- {211, 128, 1400, 776, 1688, 1066}, /* 06 (1024x768x60Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz
- * w/o Scaling)
- */
- {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = {
- {4, 1, 1620, 420, 2160, 1250}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {27, 7, 1920, 375, 2160, 1250}, /* 01 (320x350,640x350) */
- {4, 1, 1620, 420, 2160, 1250}, /* 02 (360x400,720x400)*/
- {27, 7, 1920, 375, 2160, 1250}, /* 03 (720x350) */
- {27, 4, 800, 500, 2160, 1250}, /* 04 (640x480x60Hz) */
- {4, 1, 1080, 625, 2160, 1250}, /* 05 (800x600x60Hz) */
- {5, 2, 1350, 800, 2160, 1250}, /* 06 (1024x768x60Hz) */
- {27, 16, 1500, 1064, 2160, 1250}, /* 07 (1280x1024x60Hz) */
- {9, 7, 1920, 1106, 2160, 1250}, /* 08 (1400x1050x60Hz) */
- {1, 1, 2160, 1250, 2160, 1250} /* 09 (1600x1200x60Hz) ;302lv */
-};
-
-static const struct SiS_LCDData XGI_StLCD1600x1200Data[] = {
- {27, 4, 800, 500, 2160, 1250}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {27, 4, 800, 500, 2160, 1250}, /* 01 (320x350,640x350) */
- {27, 4, 800, 500, 2160, 1250}, /* 02 (360x400,720x400) */
- {27, 4, 800, 500, 2160, 1250}, /* 03 (720x350) */
- {27, 4, 800, 500, 2160, 1250}, /* 04 (320x240,640x480) */
- {4, 1, 1080, 625, 2160, 1250}, /* 05 (400x300,800x600) */
- {5, 2, 1350, 800, 2160, 1250}, /* 06 (512x384,1024x768) */
- {135, 88, 1600, 1100, 2160, 1250}, /* 07 (1280x1024) */
- {1, 1, 1800, 1500, 2160, 1250}, /* 08 (1400x1050) */
- {1, 1, 2160, 1250, 2160, 1250} /* 09 (1600x1200) */
-};
-
-#define XGI_CetLCD1400x1050Data XGI_CetLCD1280x1024Data
-
-static const struct SiS_LCDData XGI_NoScalingData[] = {
- {1, 1, 800, 449, 800, 449},
- {1, 1, 800, 449, 800, 449},
- {1, 1, 900, 449, 900, 449},
- {1, 1, 900, 449, 900, 449},
- {1, 1, 800, 525, 800, 525},
- {1, 1, 1056, 628, 1056, 628},
- {1, 1, 1344, 806, 1344, 806},
- {1, 1, 1688, 1066, 1688, 1066}
-};
-
-static const struct SiS_LCDData XGI_ExtLCD1024x768x75Data[] = {
- {42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */
- {42, 25, 1536, 419, 1344, 806}, /* ; 02 (360x400,720x400) */
- {48, 25, 1536, 369, 1344, 806}, /* ; 03 (720x350) */
- {8, 5, 1312, 500, 1312, 800}, /* ; 04 (640x480x75Hz) */
- {41, 25, 1024, 625, 1312, 800}, /* ; 05 (800x600x75Hz) */
- {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */
-};
-
-static const struct SiS_LCDData XGI_CetLCD1024x768x75Data[] = {
- {1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {1, 1, 1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */
- {1, 1, 1312, 800, 1312, 800}, /* ; 02 (360x400,720x400) */
- {1, 1, 1312, 800, 1312, 800}, /* ; 03 (720x350) */
- {1, 1, 1312, 800, 1312, 800}, /* ; 04 (640x480x75Hz) */
- {1, 1, 1312, 800, 1312, 800}, /* ; 05 (800x600x75Hz) */
- {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */
-};
-
-static const struct SiS_LCDData xgifb_lcd_1280x1024x75[] = {
- {211, 60, 1024, 501, 1688, 1066}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {211, 60, 1024, 508, 1688, 1066}, /* ; 01 (320x350,640x350) */
- {211, 60, 1024, 501, 1688, 1066}, /* ; 02 (360x400,720x400) */
- {211, 60, 1024, 508, 1688, 1066}, /* ; 03 (720x350) */
- {211, 45, 768, 498, 1688, 1066}, /* ; 04 (640x480x75Hz) */
- {211, 75, 1024, 625, 1688, 1066}, /* ; 05 (800x600x75Hz) */
- {211, 120, 1280, 798, 1688, 1066}, /* ; 06 (1024x768x75Hz) */
- {1, 1, 1688, 1066, 1688, 1066} /* ; 07 (1280x1024x75Hz) */
-};
-
-#define XGI_CetLCD1280x1024x75Data XGI_CetLCD1280x1024Data
-
-static const struct SiS_LCDData XGI_NoScalingDatax75[] = {
- {1, 1, 800, 449, 800, 449}, /* ; 00 (320x200, 320x400,
- * 640x200, 640x400)
- */
- {1, 1, 800, 449, 800, 449}, /* ; 01 (320x350, 640x350) */
- {1, 1, 900, 449, 900, 449}, /* ; 02 (360x400, 720x400) */
- {1, 1, 900, 449, 900, 449}, /* ; 03 (720x350) */
- {1, 1, 840, 500, 840, 500}, /* ; 04 (640x480x75Hz) */
- {1, 1, 1056, 625, 1056, 625}, /* ; 05 (800x600x75Hz) */
- {1, 1, 1312, 800, 1312, 800}, /* ; 06 (1024x768x75Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* ; 07 (1280x1024x75Hz) */
- {1, 1, 1688, 1066, 1688, 1066}, /* ; 08 (1400x1050x75Hz)*/
- {1, 1, 2160, 1250, 2160, 1250}, /* ; 09 (1600x1200x75Hz) */
- {1, 1, 1688, 806, 1688, 806} /* ; 0A (1280x768x75Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_ExtLCDDes1024x768Data[] = {
- {9, 1057, 0, 771}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1057, 0, 771}, /* ; 01 (320x350,640x350) */
- {9, 1057, 0, 771}, /* ; 02 (360x400,720x400) */
- {9, 1057, 0, 771}, /* ; 03 (720x350) */
- {9, 1057, 0, 771}, /* ; 04 (640x480x60Hz) */
- {9, 1057, 0, 771}, /* ; 05 (800x600x60Hz) */
- {9, 1057, 805, 770} /* ; 06 (1024x768x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_StLCDDes1024x768Data[] = {
- {9, 1057, 737, 703}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1057, 686, 651}, /* ; 01 (320x350,640x350) */
- {9, 1057, 737, 703}, /* ; 02 (360x400,720x400) */
- {9, 1057, 686, 651}, /* ; 03 (720x350) */
- {9, 1057, 776, 741}, /* ; 04 (640x480x60Hz) */
- {9, 1057, 0, 771}, /* ; 05 (800x600x60Hz) */
- {9, 1057, 805, 770} /* ; 06 (1024x768x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1024x768Data[] = {
- {1152, 856, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1152, 856, 597, 562}, /* ; 01 (320x350,640x350) */
- {1152, 856, 622, 587}, /* ; 02 (360x400,720x400) */
- {1152, 856, 597, 562}, /* ; 03 (720x350) */
- {1152, 856, 662, 627}, /* ; 04 (640x480x60Hz) */
- {1232, 936, 722, 687}, /* ; 05 (800x600x60Hz) */
- {0, 1048, 805, 770} /* ; 06 (1024x768x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
- {18, 1346, 981, 940}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1346, 926, 865}, /* 01 (320x350,640x350) */
- {18, 1346, 981, 940}, /* 02 (360x400,720x400) */
- {18, 1346, 926, 865}, /* 03 (720x350) */
- {18, 1346, 0, 1025}, /* 04 (640x480x60Hz) */
- {18, 1346, 0, 1025}, /* 05 (800x600x60Hz) */
- {18, 1346, 1065, 1024}, /* 06 (1024x768x60Hz) */
- {18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_StLCDDLDes1280x1024Data[] = {
- {18, 1346, 970, 907}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1346, 917, 854}, /* 01 (320x350,640x350) */
- {18, 1346, 970, 907}, /* 02 (360x400,720x400) */
- {18, 1346, 917, 854}, /* 03 (720x350) */
- {18, 1346, 0, 1025}, /* 04 (640x480x60Hz) */
- {18, 1346, 0, 1025}, /* 05 (800x600x60Hz) */
- {18, 1346, 1065, 1024}, /* 06 (1024x768x60Hz) */
- {18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
- {1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
- {1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
- {1368, 1008, 752, 711}, /* 02 (360x400,720x400) */
- {1368, 1008, 729, 688}, /* 03 (720x350) */
- {1368, 1008, 794, 753}, /* 04 (640x480x60Hz) */
- {1448, 1068, 854, 813}, /* 05 (800x600x60Hz) */
- {1560, 1200, 938, 897}, /* 06 (1024x768x60Hz) */
- {18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_ExtLCDDes1280x1024Data[] = {
- {9, 1337, 981, 940}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1337, 926, 884}, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
- {9, 1337, 981, 940}, /* ; 02 (360x400,720x400) */
- {9, 1337, 926, 884}, /* ; 03 (720x350) alan, 2003/09/30 */
- {9, 1337, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {9, 1337, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {9, 1337, 1065, 1024}, /* ; 06 (1024x768x60Hz) */
- {9, 1337, 1065, 1024} /* ; 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_StLCDDes1280x1024Data[] = {
- {9, 1337, 970, 907}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1337, 917, 854}, /* ; 01 (320x350,640x350) */
- {9, 1337, 970, 907}, /* ; 02 (360x400,720x400) */
- {9, 1337, 917, 854}, /* ; 03 (720x350) */
- {9, 1337, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {9, 1337, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {9, 1337, 1065, 1024}, /* ; 06 (1024x768x60Hz) */
- {9, 1337, 1065, 1024} /* ; 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024Data[] = {
- {1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
- {1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
- {1368, 1008, 752, 711}, /* 02 (360x400,720x400) */
- {1368, 1008, 729, 688}, /* 03 (720x350) */
- {1368, 1008, 794, 753}, /* 04 (640x480x60Hz) */
- {1448, 1068, 854, 813}, /* 05 (800x600x60Hz) */
- {1560, 1200, 938, 897}, /* 06 (1024x768x60Hz) */
- {9, 1337, 1065, 1024} /* 07 (1280x1024x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct xgifb_lcddldes_1400x1050[] = {
- {18, 1464, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1464, 0, 1051}, /* 01 (320x350,640x350) */
- {18, 1464, 0, 1051}, /* 02 (360x400,720x400) */
- {18, 1464, 0, 1051}, /* 03 (720x350) */
- {18, 1464, 0, 1051}, /* 04 (640x480x60Hz) */
- {18, 1464, 0, 1051}, /* 05 (800x600x60Hz) */
- {18, 1464, 0, 1051}, /* 06 (1024x768x60Hz) */
- {1646, 1406, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- {18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct xgifb_lcddes_1400x1050[] = {
- {9, 1455, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {9, 1455, 0, 1051}, /* 01 (320x350,640x350) */
- {9, 1455, 0, 1051}, /* 02 (360x400,720x400) */
- {9, 1455, 0, 1051}, /* 03 (720x350) */
- {9, 1455, 0, 1051}, /* 04 (640x480x60Hz) */
- {9, 1455, 0, 1051}, /* 05 (800x600x60Hz) */
- {9, 1455, 0, 1051}, /* 06 (1024x768x60Hz) */
- {1637, 1397, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- {9, 1455, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data[] = {
- {1308, 1068, 781, 766}, /* 00 (320x200,320x400,640x200,640x400) */
- {1308, 1068, 781, 766}, /* 01 (320x350,640x350) */
- {1308, 1068, 781, 766}, /* 02 (360x400,720x400) */
- {1308, 1068, 781, 766}, /* 03 (720x350) */
- {1308, 1068, 781, 766}, /* 04 (640x480x60Hz) */
- {1388, 1148, 841, 826}, /* 05 (800x600x60Hz) */
- {1490, 1250, 925, 910}, /* 06 (1024x768x60Hz) */
- {1646, 1406, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- {18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data2[] = {
- {0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {0, 1448, 0, 1051}, /* 01 (320x350,640x350) */
- {0, 1448, 0, 1051}, /* 02 (360x400,720x400) */
- {0, 1448, 0, 1051}, /* 03 (720x350) */
- {0, 1448, 0, 1051} /* 04 (640x480x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
- {18, 1682, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1682, 0, 1201}, /* 01 (320x350,640x350) */
- {18, 1682, 0, 1201}, /* 02 (360x400,720x400) */
- {18, 1682, 0, 1201}, /* 03 (720x350) */
- {18, 1682, 0, 1201}, /* 04 (640x480x60Hz) */
- {18, 1682, 0, 1201}, /* 05 (800x600x60Hz) */
- {18, 1682, 0, 1201}, /* 06 (1024x768x60Hz) */
- {18, 1682, 0, 1201}, /* 07 (1280x1024x60Hz) */
- {18, 1682, 0, 1201}, /* 08 (1400x1050x60Hz) */
- {18, 1682, 0, 1201} /* 09 (1600x1200x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_StLCDDLDes1600x1200Data[] = {
- {18, 1682, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
- {18, 1682, 1083, 1034}, /* 01 (320x350,640x350) */
- {18, 1682, 1150, 1101}, /* 02 (360x400,720x400) */
- {18, 1682, 1083, 1034}, /* 03 (720x350) */
- {18, 1682, 0, 1201}, /* 04 (640x480x60Hz) */
- {18, 1682, 0, 1201}, /* 05 (800x600x60Hz) */
- {18, 1682, 0, 1201}, /* 06 (1024x768x60Hz) */
- {18, 1682, 1232, 1183}, /* 07 (1280x1024x60Hz) */
- {18, 1682, 0, 1201}, /* 08 (1400x1050x60Hz) */
- {18, 1682, 0, 1201} /* 09 (1600x1200x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_ExtLCDDes1600x1200Data[] = {
- {9, 1673, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
- {9, 1673, 0, 1201}, /* 01 (320x350,640x350) */
- {9, 1673, 0, 1201}, /* 02 (360x400,720x400) */
- {9, 1673, 0, 1201}, /* 03 (720x350) */
- {9, 1673, 0, 1201}, /* 04 (640x480x60Hz) */
- {9, 1673, 0, 1201}, /* 05 (800x600x60Hz) */
- {9, 1673, 0, 1201}, /* 06 (1024x768x60Hz) */
- {9, 1673, 0, 1201}, /* 07 (1280x1024x60Hz) */
- {9, 1673, 0, 1201}, /* 08 (1400x1050x60Hz) */
- {9, 1673, 0, 1201} /* 09 (1600x1200x60Hz) */
-};
-
-static const struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = {
- {9, 1673, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
- {9, 1673, 1083, 1034}, /* 01 (320x350,640x350) */
- {9, 1673, 1150, 1101}, /* 02 (360x400,720x400) */
- {9, 1673, 1083, 1034}, /* 03 (720x350) */
- {9, 1673, 0, 1201}, /* 04 (640x480x60Hz) */
- {9, 1673, 0, 1201}, /* 05 (800x600x60Hz) */
- {9, 1673, 0, 1201}, /* 06 (1024x768x60Hz) */
- {9, 1673, 1232, 1183}, /* 07 (1280x1024x60Hz) */
- {9, 1673, 0, 1201}, /* 08 (1400x1050x60Hz) */
- {9, 1673, 0, 1201} /* 09 (1600x1200x60Hz) */
-};
-
-static const struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[] = {
- {9, 657, 448, 405, 96, 2}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {9, 657, 448, 355, 96, 2}, /* 01 (320x350,640x350) */
- {9, 657, 448, 405, 96, 2}, /* 02 (360x400,720x400) */
- {9, 657, 448, 355, 96, 2}, /* 03 (720x350) */
- {9, 657, 1, 483, 96, 2}, /* 04 (640x480x60Hz) */
- {9, 849, 627, 600, 128, 4}, /* 05 (800x600x60Hz) */
- {9, 1057, 805, 770, 0136, 6}, /* 06 (1024x768x60Hz) */
- {9, 1337, 0, 1025, 112, 3}, /* 07 (1280x1024x60Hz) */
- {9, 1457, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz)*/
- {9, 1673, 0, 1201, 192, 3}, /* 09 (1600x1200x60Hz) */
- {9, 1337, 0, 771, 112, 6} /* 0A (1280x768x60Hz) */
-};
-
-/* ;;1024x768x75Hz */
-static const struct XGI_LCDDesStruct xgifb_lcddes_1024x768x75[] = {
- {9, 1049, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1049, 0, 769}, /* ; 01 (320x350,640x350) */
- {9, 1049, 0, 769}, /* ; 02 (360x400,720x400) */
- {9, 1049, 0, 769}, /* ; 03 (720x350) */
- {9, 1049, 0, 769}, /* ; 04 (640x480x75Hz) */
- {9, 1049, 0, 769}, /* ; 05 (800x600x75Hz) */
- {9, 1049, 0, 769} /* ; 06 (1024x768x75Hz) */
-};
-
-/* ;;1024x768x75Hz */
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1024x768x75Data[] = {
- {1152, 856, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1152, 856, 597, 562}, /* ; 01 (320x350,640x350) */
- {1192, 896, 622, 587}, /* ; 02 (360x400,720x400) */
- {1192, 896, 597, 562}, /* ; 03 (720x350) */
- {1129, 857, 656, 625}, /* ; 04 (640x480x75Hz) */
- {1209, 937, 716, 685}, /* ; 05 (800x600x75Hz) */
- {9, 1049, 0, 769} /* ; 06 (1024x768x75Hz) */
-};
-
-/* ;;1280x1024x75Hz */
-static const struct XGI_LCDDesStruct xgifb_lcddldes_1280x1024x75[] = {
- {18, 1314, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {18, 1314, 0, 1025}, /* ; 01 (320x350,640x350) */
- {18, 1314, 0, 1025}, /* ; 02 (360x400,720x400) */
- {18, 1314, 0, 1025}, /* ; 03 (720x350) */
- {18, 1314, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {18, 1314, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {18, 1314, 0, 1025}, /* ; 06 (1024x768x60Hz) */
- {18, 1314, 0, 1025} /* ; 07 (1280x1024x60Hz) */
-};
-
-/* 1280x1024x75Hz */
-static const struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
- {1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
- {1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
- {1408, 1048, 729, 688}, /* ; 03 (720x350) */
- {1377, 985, 794, 753}, /* ; 04 (640x480x75Hz) */
- {1457, 1065, 854, 813}, /* ; 05 (800x600x75Hz) */
- {1569, 1177, 938, 897}, /* ; 06 (1024x768x75Hz) */
- {18, 1314, 0, 1025} /* ; 07 (1280x1024x75Hz) */
-};
-
-/* ;;1280x1024x75Hz */
-static const struct XGI_LCDDesStruct xgifb_lcddes_1280x1024x75[] = {
- {9, 1305, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {9, 1305, 0, 1025}, /* ; 01 (320x350,640x350) */
- {9, 1305, 0, 1025}, /* ; 02 (360x400,720x400) */
- {9, 1305, 0, 1025}, /* ; 03 (720x350) */
- {9, 1305, 0, 1025}, /* ; 04 (640x480x60Hz) */
- {9, 1305, 0, 1025}, /* ; 05 (800x600x60Hz) */
- {9, 1305, 0, 1025}, /* ; 06 (1024x768x60Hz) */
- {9, 1305, 0, 1025} /* ; 07 (1280x1024x60Hz) */
-};
-
-/* 1280x1024x75Hz */
-static const struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
- {1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
- {1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
- {1408, 1048, 729, 688}, /* ; 03 (720x350) */
- {1377, 985, 794, 753}, /* ; 04 (640x480x75Hz) */
- {1457, 1065, 854, 813}, /* ; 05 (800x600x75Hz) */
- {1569, 1177, 938, 897}, /* ; 06 (1024x768x75Hz) */
- {9, 1305, 0, 1025} /* ; 07 (1280x1024x75Hz) */
-};
-
-/* Scaling LCD 75Hz */
-static const struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] = {
- {9, 657, 448, 405, 96, 2}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {9, 657, 448, 355, 96, 2}, /* ; 01 (320x350,640x350) */
- {9, 738, 448, 405, 108, 2}, /* ; 02 (360x400,720x400) */
- {9, 738, 448, 355, 108, 2}, /* ; 03 (720x350) */
- {9, 665, 0, 481, 64, 3}, /* ; 04 (640x480x75Hz) */
- {9, 825, 0, 601, 80, 3}, /* ; 05 (800x600x75Hz) */
- {9, 1049, 0, 769, 96, 3}, /* ; 06 (1024x768x75Hz) */
- {9, 1305, 0, 1025, 144, 3}, /* ; 07 (1280x1024x75Hz) */
- {9, 1457, 0, 1051, 112, 3}, /* ; 08 (1400x1050x60Hz)*/
- {9, 1673, 0, 1201, 192, 3}, /* ; 09 (1600x1200x75Hz) */
- {9, 1337, 0, 771, 112, 6} /* ; 0A (1280x768x60Hz) */
-};
-
-static const struct SiS_TVData XGI_StPALData[] = {
- {1, 1, 864, 525, 1270, 400, 100, 0, 760},
- {1, 1, 864, 525, 1270, 350, 100, 0, 760},
- {1, 1, 864, 525, 1270, 400, 0, 0, 720},
- {1, 1, 864, 525, 1270, 350, 0, 0, 720},
- {1, 1, 864, 525, 1270, 480, 50, 0, 760},
- {1, 1, 864, 525, 1270, 600, 50, 0, 0}
-};
-
-static const struct SiS_TVData XGI_ExtPALData[] = {
- {2, 1, 1080, 463, 1270, 500, 50, 0, 50},
- {15, 7, 1152, 413, 1270, 500, 50, 0, 50},
- {2, 1, 1080, 463, 1270, 500, 50, 0, 50},
- {15, 7, 1152, 413, 1270, 500, 50, 0, 50},
- {2, 1, 900, 543, 1270, 500, 0, 0, 50},
- {4, 3, 1080, 663, 1270, 500, 438, 0, 438},
- {1, 1, 1125, 831, 1270, 500, 686, 0, 686}, /*301b*/
- {3, 2, 1080, 619, 1270, 540, 438, 0, 438}
-};
-
-static const struct SiS_TVData XGI_StNTSCData[] = {
- {1, 1, 858, 525, 1270, 400, 50, 0, 760},
- {1, 1, 858, 525, 1270, 350, 50, 0, 640},
- {1, 1, 858, 525, 1270, 400, 0, 0, 720},
- {1, 1, 858, 525, 1270, 350, 0, 0, 720},
- {1, 1, 858, 525, 1270, 480, 0, 0, 760}
-};
-
-static const struct SiS_TVData XGI_ExtNTSCData[] = {
- {9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- {12, 5, 858, 403, 1270, 420, 171, 0, 171},
- {9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- {12, 5, 858, 403, 1270, 420, 171, 0, 171},
- {143, 80, 836, 523, 1270, 420, 224, 0, 0},
- {143, 120, 1008, 643, 1270, 420, 0, 1, 0},
- {1, 1, 1120, 821, 1516, 420, 0, 1, 0}, /*301b*/
- {2, 1, 858, 503, 1584, 480, 0, 1, 0},
- {3, 2, 1001, 533, 1270, 420, 0, 0, 0}
-};
-
-static const struct SiS_TVData XGI_St1HiTVData[] = {
- {1, 1, 892, 563, 690, 800, 0, 0, 0}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */
- {1, 1, 1000, 563, 785, 800, 0, 0, 0}, /* 02 (360x400,720x400) */
- {1, 1, 1000, 563, 785, 700, 0, 0, 0}, /* 03 (720x350) */
- {1, 1, 892, 563, 690, 960, 0, 0, 0}, /* 04 (320x240,640x480) */
- {8, 5, 1050, 683, 1648, 960, 0x150, 1, 0} /* 05 (400x300,800x600) */
-};
-
-static const struct SiS_TVData XGI_St2HiTVData[] = {
- {3, 1, 840, 483, 1648, 960, 0x032, 0, 0}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */
- {3, 1, 840, 483, 1648, 960, 0x032, 0, 0}, /* 02 (360x400,720x400) */
- {1, 1, 1000, 563, 785, 700, 0, 0, 0}, /* 03 (720x350) */
- {5, 2, 840, 563, 1648, 960, 0x08D, 1, 0}, /* 04 (320x240,640x480) */
- {8, 5, 1050, 683, 1648, 960, 0x17C, 1, 0} /* 05 (400x300,800x600) */
-};
-
-static const struct SiS_TVData XGI_ExtHiTVData[] = {
- {6, 1, 840, 563, 1632, 960, 0, 0, 0}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {3, 1, 960, 563, 1632, 960, 0, 0, 0}, /* 01 (320x350,640x350) */
- {3, 1, 840, 483, 1632, 960, 0, 0, 0}, /* 02 (360x400,720x400) */
- {3, 1, 960, 563, 1632, 960, 0, 0, 0}, /* 03 (720x350) */
- {5, 1, 840, 563, 1648, 960, 0x166, 1, 0}, /* 04 (320x240,640x480) */
- {16, 5, 1050, 683, 1648, 960, 0x143, 1, 0}, /* 05 (400x300,800x600) */
- {25, 12, 1260, 851, 1648, 960, 0x032, 0, 0}, /* 06 (512x384,1024x768)*/
- {5, 4, 1575, 1124, 1648, 960, 0x128, 0, 0}, /* 07 (1280x1024) */
- {4, 1, 1050, 563, 1548, 960, 0x143, 1, 0}, /* 08 (800x480) */
- {5, 2, 1400, 659, 1648, 960, 0x032, 0, 0}, /* 09 (1024x576) */
- {8, 5, 1750, 803, 1648, 960, 0x128, 0, 0} /* 0A (1280x720) */
-};
-
-static const struct SiS_TVData XGI_ExtYPbPr525iData[] = {
- { 9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- { 12, 5, 858, 403, 1270, 420, 171, 0, 171},
- { 9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- { 12, 5, 858, 403, 1270, 420, 171, 0, 171},
- {143, 80, 836, 523, 1250, 420, 224, 0, 0},
- {143, 120, 1008, 643, 1250, 420, 0, 1, 0},
- { 1, 1, 1120, 821, 1516, 420, 0, 1, 0}, /*301b*/
- { 2, 1, 858, 503, 1584, 480, 0, 1, 0},
- { 3, 2, 1001, 533, 1250, 420, 0, 0, 0}
-};
-
-static const struct SiS_TVData XGI_StYPbPr525iData[] = {
- {1, 1, 858, 525, 1270, 400, 50, 0, 760},
- {1, 1, 858, 525, 1270, 350, 50, 0, 640},
- {1, 1, 858, 525, 1270, 400, 0, 0, 720},
- {1, 1, 858, 525, 1270, 350, 0, 0, 720},
- {1, 1, 858, 525, 1270, 480, 0, 0, 760},
-};
-
-static const struct SiS_TVData XGI_ExtYPbPr525pData[] = {
- { 9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- { 12, 5, 858, 403, 1270, 420, 171, 0, 171},
- { 9, 5, 1001, 453, 1270, 420, 171, 0, 171},
- { 12, 5, 858, 403, 1270, 420, 171, 0, 171},
- {143, 80, 836, 523, 1270, 420, 224, 0, 0},
- {143, 120, 1008, 643, 1270, 420, 0, 1, 0},
- { 1, 1, 1120, 821, 1516, 420, 0, 1, 0}, /*301b*/
- { 2, 1, 858, 503, 1584, 480, 0, 1, 0},
- { 3, 2, 1001, 533, 1270, 420, 0, 0, 0}
-};
-
-static const struct SiS_TVData XGI_StYPbPr525pData[] = {
- {1, 1, 1716, 525, 1270, 400, 50, 0, 760},
- {1, 1, 1716, 525, 1270, 350, 50, 0, 640},
- {1, 1, 1716, 525, 1270, 400, 0, 0, 720},
- {1, 1, 1716, 525, 1270, 350, 0, 0, 720},
- {1, 1, 1716, 525, 1270, 480, 0, 0, 760},
-};
-
-static const struct SiS_TVData XGI_ExtYPbPr750pData[] = {
- { 3, 1, 935, 470, 1130, 680, 50, 0, 0}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {24, 7, 935, 420, 1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */
- { 3, 1, 935, 470, 1130, 680, 50, 0, 0}, /* 02 (360x400,720x400) */
- {24, 7, 935, 420, 1130, 680, 50, 0, 0}, /* 03 (720x350) */
- { 2, 1, 1100, 590, 1130, 640, 50, 0, 0}, /* 04 (320x240,640x480) */
- { 3, 2, 1210, 690, 1130, 660, 50, 0, 0}, /* 05 (400x300,800x600) */
- { 1, 1, 1375, 878, 1130, 640, 638, 0, 0}, /* 06 (1024x768) */
- { 2, 1, 858, 503, 1130, 480, 0, 1, 0}, /* 07 (720x480) */
- { 5, 4, 1815, 570, 1130, 660, 50, 0, 0},
- { 5, 3, 1100, 686, 1130, 640, 50, 1, 0},
- {10, 9, 1320, 830, 1130, 640, 50, 0, 0}
-};
-
-static const struct SiS_TVData XGI_StYPbPr750pData[] = {
- {1, 1, 1650, 750, 1280, 400, 50, 0, 760},
- {1, 1, 1650, 750, 1280, 350, 50, 0, 640},
- {1, 1, 1650, 750, 1280, 400, 0, 0, 720},
- {1, 1, 1650, 750, 1280, 350, 0, 0, 720},
- {1, 1, 1650, 750, 1280, 480, 0, 0, 760},
-};
-
-static const unsigned char XGI330_NTSCTiming[] = {
- 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c,
- 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a,
- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b,
- 0x0c, 0x50, 0x00, 0x97, 0x00, 0xda, 0x4a, 0x17,
- 0x7d, 0x05, 0x4b, 0x00, 0x00, 0xe2, 0x00, 0x02,
- 0x03, 0x0a, 0x65, 0x9d, 0x08, 0x92, 0x8f, 0x40,
- 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x50,
- 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00
-};
-
-static const unsigned char XGI330_PALTiming[] = {
- 0x21, 0x5A, 0x35, 0x6e, 0x04, 0x38, 0x3d, 0x70,
- 0x94, 0x49, 0x01, 0x12, 0x06, 0x3e, 0x35, 0x6d,
- 0x06, 0x14, 0x3e, 0x35, 0x6d, 0x00, 0x45, 0x2b,
- 0x70, 0x50, 0x00, 0x9b, 0x00, 0xd9, 0x5d, 0x17,
- 0x7d, 0x05, 0x45, 0x00, 0x00, 0xe8, 0x00, 0x02,
- 0x0d, 0x00, 0x68, 0xb0, 0x0b, 0x92, 0x8f, 0x40,
- 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x63,
- 0x00, 0x40, 0x3e, 0x00, 0xe1, 0x02, 0x28, 0x00
-};
-
-static const unsigned char XGI330_HiTVExtTiming[] = {
- 0x2D, 0x60, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x64,
- 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D,
- 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F,
- 0x64, 0x90, 0x33, 0x8C, 0x18, 0x36, 0x3E, 0x13,
- 0x2A, 0xDE, 0x2A, 0x44, 0x40, 0x2A, 0x44, 0x40,
- 0x8E, 0x8E, 0x82, 0x07, 0x0B,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x14, 0x3D, 0x63, 0x4F,
- 0x27, 0x00, 0xfc, 0xff, 0x6a, 0x00
-};
-
-static const unsigned char XGI330_HiTVSt1Timing[] = {
- 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x65,
- 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D,
- 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F,
- 0x65, 0x90, 0x7B, 0xA8, 0x03, 0xF0, 0x87, 0x03,
- 0x11, 0x15, 0x11, 0xCF, 0x10, 0x11, 0xCF, 0x10,
- 0x35, 0x35, 0x3B, 0x69, 0x1D,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x04, 0x86, 0xAF, 0x5D,
- 0x0E, 0x00, 0xfc, 0xff, 0x2d, 0x00
-};
-
-static const unsigned char XGI330_HiTVSt2Timing[] = {
- 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x64,
- 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D,
- 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F,
- 0x64, 0x90, 0x33, 0x8C, 0x18, 0x36, 0x3E, 0x13,
- 0x2A, 0xDE, 0x2A, 0x44, 0x40, 0x2A, 0x44, 0x40,
- 0x8E, 0x8E, 0x82, 0x07, 0x0B,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x14, 0x3D, 0x63, 0x4F,
- 0x27, 0x00, 0xFC, 0xff, 0x6a, 0x00
-};
-
-static const unsigned char XGI330_HiTVTextTiming[] = {
- 0x32, 0x65, 0x2C, 0x5F, 0x08, 0x31, 0x3A, 0x65,
- 0x28, 0x02, 0x01, 0x3D, 0x06, 0x3E, 0x35, 0x6D,
- 0x06, 0x14, 0x3E, 0x35, 0x6D, 0x00, 0xC5, 0x3F,
- 0x65, 0x90, 0xE7, 0xBC, 0x03, 0x0C, 0x97, 0x03,
- 0x14, 0x78, 0x14, 0x08, 0x20, 0x14, 0x08, 0x20,
- 0xC8, 0xC8, 0x3B, 0xD2, 0x26,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x04, 0x96, 0x72, 0x5C,
- 0x11, 0x00, 0xFC, 0xFF, 0x32, 0x00
-};
-
-static const unsigned char XGI330_YPbPr750pTiming[] = {
- 0x30, 0x1d, 0xe8, 0x09, 0x09, 0xed, 0x0c, 0x0c,
- 0x98, 0x0a, 0x01, 0x0c, 0x06, 0x0d, 0x04, 0x0a,
- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
- 0xed, 0x50, 0x70, 0x9f, 0x16, 0x59, 0x60, 0x13,
- 0x27, 0x0b, 0x27, 0xfc, 0x30, 0x27, 0x1c, 0xb0,
- 0x4b, 0x4b, 0x6f, 0x2f, 0x63,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x14, 0x73, 0x00, 0x40,
- 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00
-};
-
-static const unsigned char XGI330_YPbPr525pTiming[] = {
- 0x3E, 0x11, 0x06, 0x09, 0x0b, 0x0c, 0x0c, 0x0c,
- 0x98, 0x0a, 0x01, 0x0d, 0x06, 0x0d, 0x04, 0x0a,
- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
- 0x0c, 0x50, 0xb2, 0x9f, 0x16, 0x59, 0x4f, 0x13,
- 0xad, 0x11, 0xad, 0x1d, 0x40, 0x8a, 0x3d, 0xb8,
- 0x51, 0x5e, 0x60, 0x49, 0x7d,
- 0x92, 0x0F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x14, 0x4B, 0x43, 0x41,
- 0x11, 0x00, 0xFC, 0xFF, 0x32, 0x00
-};
-
-static const unsigned char XGI330_YPbPr525iTiming[] = {
- 0x1B, 0x21, 0x03, 0x09, 0x05, 0x06, 0x0C, 0x0C,
- 0x94, 0x49, 0x01, 0x0A, 0x06, 0x0D, 0x04, 0x0A,
- 0x06, 0x14, 0x0D, 0x04, 0x0A, 0x00, 0x85, 0x1B,
- 0x0C, 0x50, 0x00, 0x97, 0x00, 0xDA, 0x4A, 0x17,
- 0x7D, 0x05, 0x4B, 0x00, 0x00, 0xE2, 0x00, 0x02,
- 0x03, 0x0A, 0x65, 0x9D, 0x08,
- 0x92, 0x8F, 0x40, 0x60, 0x80, 0x14, 0x90, 0x8C,
- 0x60, 0x14, 0x4B, 0x00, 0x40,
- 0x44, 0x00, 0xDB, 0x02, 0x3B, 0x00
-};
-
-static const unsigned char XGI330_HiTVGroup3Data[] = {
- 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0x5F,
- 0x05, 0x21, 0xB2, 0xB2, 0x55, 0x77, 0x2A, 0xA6,
- 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20,
- 0x8C, 0x6E, 0x60, 0x2E, 0x58, 0x48, 0x72, 0x44,
- 0x56, 0x36, 0x4F, 0x6E, 0x3F, 0x80, 0x00, 0x80,
- 0x4F, 0x7F, 0x03, 0xA8, 0x7D, 0x20, 0x1A, 0xA9,
- 0x14, 0x05, 0x03, 0x7E, 0x64, 0x31, 0x14, 0x75,
- 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01
-};
-
-static const unsigned char XGI330_HiTVGroup3Simu[] = {
- 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0x95,
- 0xDB, 0x20, 0xB8, 0xB8, 0x55, 0x47, 0x2A, 0xA6,
- 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20,
- 0x8C, 0x6E, 0x60, 0x15, 0x26, 0xD3, 0xE4, 0x11,
- 0x56, 0x36, 0x4F, 0x6E, 0x3F, 0x80, 0x00, 0x80,
- 0x67, 0x36, 0x01, 0x47, 0x0E, 0x10, 0xBE, 0xB4,
- 0x01, 0x05, 0x03, 0x7E, 0x65, 0x31, 0x14, 0x75,
- 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01
-};
-
-static const unsigned char XGI330_HiTVGroup3Text[] = {
- 0x00, 0x1A, 0x22, 0x63, 0x62, 0x22, 0x08, 0xA7,
- 0xF5, 0x20, 0xCE, 0xCE, 0x55, 0x47, 0x2A, 0xA6,
- 0x25, 0x2F, 0x47, 0xFA, 0xC8, 0xFF, 0x8E, 0x20,
- 0x8C, 0x6E, 0x60, 0x18, 0x2C, 0x0C, 0x20, 0x22,
- 0x56, 0x36, 0x4F, 0x6E, 0x3F, 0x80, 0x00, 0x80,
- 0x93, 0x3C, 0x01, 0x50, 0x2F, 0x10, 0xF4, 0xCA,
- 0x01, 0x05, 0x03, 0x7E, 0x65, 0x31, 0x14, 0x75,
- 0x18, 0x05, 0x18, 0x05, 0x4C, 0xA8, 0x01
-};
-
-static const unsigned char XGI330_Ren525pGroup3[] = {
- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
- 0xB1, 0x41, 0x62, 0x62, 0xFF, 0xF4, 0x45, 0xa6,
- 0x25, 0x2F, 0x67, 0xF6, 0xbf, 0xFF, 0x8E, 0x20,
- 0xAC, 0xDA, 0x60, 0xFe, 0x6A, 0x9A, 0x06, 0x10,
- 0xd1, 0x04, 0x18, 0x0a, 0xFF, 0x80, 0x00, 0x80,
- 0x3c, 0x77, 0x00, 0xEF, 0xE0, 0x10, 0xB0, 0xE0,
- 0x10, 0x4F, 0x0F, 0x0F, 0x05, 0x0F, 0x08, 0x6E,
- 0x1a, 0x1F, 0x25, 0x2a, 0x4C, 0xAA, 0x01
-};
-
-static const unsigned char XGI330_Ren750pGroup3[] = {
- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
- 0x54, 0x41, 0xE7, 0xE7, 0xFF, 0xF4, 0x45, 0xa6,
- 0x25, 0x2F, 0x67, 0xF6, 0xbf, 0xFF, 0x8E, 0x20,
- 0xAC, 0x6A, 0x60, 0x2b, 0x52, 0xCD, 0x61, 0x10,
- 0x51, 0x04, 0x18, 0x0a, 0x1F, 0x80, 0x00, 0x80,
- 0xFF, 0xA4, 0x04, 0x2B, 0x94, 0x21, 0x72, 0x94,
- 0x26, 0x05, 0x01, 0x0F, 0xed, 0x0F, 0x0A, 0x64,
- 0x18, 0x1D, 0x23, 0x28, 0x4C, 0xAA, 0x01
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Data_1[] = {
- { 960, 438, 1344, 806}, /* 00 (320x200,320x400,640x200,640x400) */
- { 960, 388, 1344, 806}, /* 01 (320x350,640x350) */
- {1040, 438, 1344, 806}, /* 02 (360x400,720x400) */
- {1040, 388, 1344, 806}, /* 03 (720x350) */
- { 960, 518, 1344, 806}, /* 04 (320x240,640x480) */
- {1120, 638, 1344, 806}, /* 05 (400x300,800x600) */
- {1344, 806, 1344, 806} /* 06 (512x384,1024x768) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Data_2[] = {
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {1344, 806, 1344, 806},
- {800, 449, 1280, 801},
- {800, 525, 1280, 813}
-};
-
-static const struct SiS_LVDSData XGI_LVDS1280x1024Data_1[] = {
- {1048, 442, 1688, 1066},
- {1048, 392, 1688, 1066},
- {1048, 442, 1688, 1066},
- {1048, 392, 1688, 1066},
- {1048, 522, 1688, 1066},
- {1208, 642, 1688, 1066},
- {1432, 810, 1688, 1066},
- {1688, 1066, 1688, 1066}
-};
-
-#define XGI_LVDS1280x1024Data_2 XGI_LVDS1024x768Data_2
-
-static const struct SiS_LVDSData XGI_LVDS1400x1050Data_1[] = {
- {928, 416, 1688, 1066},
- {928, 366, 1688, 1066},
- {928, 416, 1688, 1066},
- {928, 366, 1688, 1066},
- {928, 496, 1688, 1066},
- {1088, 616, 1688, 1066},
- {1312, 784, 1688, 1066},
- {1568, 1040, 1688, 1066},
- {1688, 1066, 1688, 1066}
-};
-
-static const struct SiS_LVDSData XGI_LVDS1400x1050Data_2[] = {
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066},
- {1688, 1066, 1688, 1066}
-};
-
-/* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
-static const struct SiS_LVDSData XGI_LVDS1600x1200Data_1[] = {
- {1088, 520, 2048, 1320}, /* 00 (320x200,320x400,640x200,640x400) */
- {1088, 470, 2048, 1320}, /* 01 (320x350,640x350) */
- {1088, 520, 2048, 1320}, /* 02 (360x400,720x400) */
- {1088, 470, 2048, 1320}, /* 03 (720x350) */
- {1088, 600, 2048, 1320}, /* 04 (320x240,640x480) */
- {1248, 720, 2048, 1320}, /* 05 (400x300,800x600) */
- {1472, 888, 2048, 1320}, /* 06 (512x384,1024x768) */
- {1728, 1144, 2048, 1320}, /* 07 (640x512,1280x1024) */
- {1848, 1170, 2048, 1320}, /* 08 (1400x1050) */
- {2048, 1320, 2048, 1320} /* 09 (1600x1200) */
-};
-
-static const struct SiS_LVDSData XGI_LVDSNoScalingData[] = {
- { 800, 449, 800, 449}, /* 00 (320x200,320x400,640x200,640x400) */
- { 800, 449, 800, 449}, /* 01 (320x350,640x350) */
- { 800, 449, 800, 449}, /* 02 (360x400,720x400) */
- { 800, 449, 800, 449}, /* 03 (720x350) */
- { 800, 525, 800, 525}, /* 04 (640x480x60Hz) */
- {1056, 628, 1056, 628}, /* 05 (800x600x60Hz) */
- {1344, 806, 1344, 806}, /* 06 (1024x768x60Hz) */
- {1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz) */
- {1688, 1066, 1688, 1066}, /* 08 (1400x1050x60Hz) */
- {2160, 1250, 2160, 1250}, /* 09 (1600x1200x60Hz) */
- {1688, 806, 1688, 806} /* 0A (1280x768x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Data_1x75[] = {
- { 960, 438, 1312, 800}, /* 00 (320x200,320x400,640x200,640x400) */
- { 960, 388, 1312, 800}, /* 01 (320x350,640x350) */
- {1040, 438, 1312, 800}, /* 02 (360x400,720x400) */
- {1040, 388, 1312, 800}, /* 03 (720x350) */
- { 928, 512, 1312, 800}, /* 04 (320x240,640x480) */
- {1088, 632, 1312, 800}, /* 05 (400x300,800x600) */
- {1312, 800, 1312, 800}, /* 06 (512x384,1024x768) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Data_2x75[] = {
- {1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */
- {1312, 800, 1312, 800}, /* ; 02 (360x400,720x400) */
- {1312, 800, 1312, 800}, /* ; 03 (720x350) */
- {1312, 800, 1312, 800}, /* ; 04 (320x240,640x480) */
- {1312, 800, 1312, 800}, /* ; 05 (400x300,800x600) */
- {1312, 800, 1312, 800}, /* ; 06 (512x384,1024x768) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1280x1024Data_1x75[] = {
- {1048, 442, 1688, 1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1048, 392, 1688, 1066 }, /* ; 01 (320x350,640x350) */
- {1128, 442, 1688, 1066 }, /* ; 02 (360x400,720x400) */
- {1128, 392, 1688, 1066 }, /* ; 03 (720x350) */
- {1048, 522, 1688, 1066 }, /* ; 04 (320x240,640x480) */
- {1208, 642, 1688, 1066 }, /* ; 05 (400x300,800x600) */
- {1432, 810, 1688, 1066 }, /* ; 06 (512x384,1024x768) */
- {1688, 1066, 1688, 1066 }, /* ; 06; 07 (640x512,1280x1024) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1280x1024Data_2x75[] = {
- {1688, 1066, 1688, 1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1688, 1066, 1688, 1066 }, /* ; 01 (320x350,640x350) */
- {1688, 1066, 1688, 1066 }, /* ; 02 (360x400,720x400) */
- {1688, 1066, 1688, 1066 }, /* ; 03 (720x350) */
- {1688, 1066, 1688, 1066 }, /* ; 04 (320x240,640x480) */
- {1688, 1066, 1688, 1066 }, /* ; 05 (400x300,800x600) */
- {1688, 1066, 1688, 1066 }, /* ; 06 (512x384,1024x768) */
- {1688, 1066, 1688, 1066 }, /* ; 06; 07 (640x512,1280x1024) */
-};
-
-static const struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = {
- { 800, 449, 800, 449}, /* ; 00 (320x200,320x400,640x200,640x400) */
- { 800, 449, 800, 449}, /* ; 01 (320x350,640x350) */
- { 900, 449, 900, 449}, /* ; 02 (360x400,720x400) */
- { 900, 449, 900, 449}, /* ; 03 (720x350) */
- { 800, 500, 800, 500}, /* ; 04 (640x480x75Hz) */
- {1056, 625, 1056, 625}, /* ; 05 (800x600x75Hz) */
- {1312, 800, 1312, 800}, /* ; 06 (1024x768x75Hz) */
- {1688, 1066, 1688, 1066}, /* ; 07 (1280x1024x75Hz) */
- {1688, 1066, 1688, 1066}, /* ; 08 (1400x1050x75Hz)
- * ;;[ycchen] 12/19/02
- */
- {2160, 1250, 2160, 1250}, /* ; 09 (1600x1200x75Hz) */
- {1688, 806, 1688, 806}, /* ; 0A (1280x768x75Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = {
- {0, 1048, 0, 771}, /* 00 (320x200,320x400,640x200,640x400) */
- {0, 1048, 0, 771}, /* 01 (320x350,640x350) */
- {0, 1048, 0, 771}, /* 02 (360x400,720x400) */
- {0, 1048, 0, 771}, /* 03 (720x350) */
- {0, 1048, 0, 771}, /* 04 (640x480x60Hz) */
- {0, 1048, 0, 771}, /* 05 (800x600x60Hz) */
- {0, 1048, 805, 770} /* 06 (1024x768x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = {
- {1142, 856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
- {1142, 856, 597, 562}, /* 01 (320x350,640x350) */
- {1142, 856, 622, 587}, /* 02 (360x400,720x400) */
- {1142, 856, 597, 562}, /* 03 (720x350) */
- {1142, 1048, 722, 687}, /* 04 (640x480x60Hz) */
- {1232, 936, 722, 687}, /* 05 (800x600x60Hz) */
- { 0, 1048, 805, 771} /* 06 (1024x768x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_3[] = {
- {320, 24, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
- {320, 24, 597, 562}, /* 01 (320x350,640x350) */
- {320, 24, 622, 587}, /* 02 (360x400,720x400) */
- {320, 24, 597, 562}, /* 03 (720x350) */
- {320, 24, 722, 687} /* 04 (640x480x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1280x1024Des_1[] = {
- {0, 1328, 0, 1025}, /* 00 (320x200,320x400,640x200,640x400) */
- {0, 1328, 0, 1025}, /* 01 (320x350,640x350) */
- {0, 1328, 0, 1025}, /* 02 (360x400,720x400) */
- {0, 1328, 0, 1025}, /* 03 (720x350) */
- {0, 1328, 0, 1025}, /* 04 (640x480x60Hz) */
- {0, 1328, 0, 1025}, /* 05 (800x600x60Hz) */
- {0, 1328, 0, 1025}, /* 06 (1024x768x60Hz) */
- {0, 1328, 1065, 1024} /* 07 (1280x1024x60Hz) */
-};
-
- /* The Display setting for DE Mode Panel */
-static const struct SiS_LVDSData XGI_LVDS1280x1024Des_2[] = {
- {1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
- {1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
- {1408, 1048, 752, 711}, /* 02 (360x400,720x400) */
- {1408, 1048, 729, 688}, /* 03 (720x350) */
- {1368, 1008, 794, 753}, /* 04 (640x480x60Hz) */
- {1448, 1068, 854, 813}, /* 05 (800x600x60Hz) */
- {1560, 1200, 938, 897}, /* 06 (1024x768x60Hz) */
- {0000, 1328, 0, 1025} /* 07 (1280x1024x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1400x1050Des_1[] = {
- {0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
- {0, 1448, 0, 1051}, /* 01 (320x350,640x350) */
- {0, 1448, 0, 1051}, /* 02 (360x400,720x400) */
- {0, 1448, 0, 1051}, /* 03 (720x350) */
- {0, 1448, 0, 1051}, /* 04 (640x480x60Hz) */
- {0, 1448, 0, 1051}, /* 05 (800x600x60Hz) */
- {0, 1448, 0, 1051}, /* 06 (1024x768x60Hz) */
- {0, 1448, 0, 1051}, /* 07 (1280x1024x60Hz) */
- {0, 1448, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1400x1050Des_2[] = {
- {1308, 1068, 781, 766}, /* 00 (320x200,320x400,640x200,640x400) */
- {1308, 1068, 781, 766}, /* 01 (320x350,640x350) */
- {1308, 1068, 781, 766}, /* 02 (360x400,720x400) */
- {1308, 1068, 781, 766}, /* 03 (720x350) */
- {1308, 1068, 781, 766}, /* 04 (640x480x60Hz) */
- {1388, 1148, 841, 826}, /* 05 (800x600x60Hz) */
- {1490, 1250, 925, 910}, /* 06 (1024x768x60Hz) */
- {1608, 1368, 1053, 1038}, /* 07 (1280x1024x60Hz) */
- { 0, 1448, 0, 1051} /* 08 (1400x1050x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = {
- {0, 1664, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
- {0, 1664, 0, 1201}, /* 01 (320x350,640x350) */
- {0, 1664, 0, 1201}, /* 02 (360x400,720x400) */
- {0, 1664, 0, 1201}, /* 03 (720x350) */
- {0, 1664, 0, 1201}, /* 04 (640x480x60Hz) */
- {0, 1664, 0, 1201}, /* 05 (800x600x60Hz) */
- {0, 1664, 0, 1201}, /* 06 (1024x768x60Hz) */
- {0, 1664, 0, 1201}, /* 07 (1280x1024x60Hz) */
- {0, 1664, 0, 1201}, /* 08 (1400x1050x60Hz) */
- {0, 1664, 0, 1201} /* 09 (1600x1200x60Hz) */
-};
-
-static const struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[] = {
- {0, 648, 448, 405, 96, 2}, /* 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {0, 648, 448, 355, 96, 2}, /* 01 (320x350,640x350) */
- {0, 648, 448, 405, 96, 2}, /* 02 (360x400,720x400) */
- {0, 648, 448, 355, 96, 2}, /* 03 (720x350) */
- {0, 648, 1, 483, 96, 2}, /* 04 (640x480x60Hz) */
- {0, 840, 627, 600, 128, 4}, /* 05 (800x600x60Hz) */
- {0, 1048, 805, 770, 136, 6}, /* 06 (1024x768x60Hz) */
- {0, 1328, 0, 1025, 112, 3}, /* 07 (1280x1024x60Hz) */
- {0, 1438, 0, 1051, 112, 3}, /* 08 (1400x1050x60Hz)*/
- {0, 1664, 0, 1201, 192, 3}, /* 09 (1600x1200x60Hz) */
- {0, 1328, 0, 0771, 112, 6} /* 0A (1280x768x60Hz) */
-};
-
-/* ; 1024x768 Full-screen */
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_1x75[] = {
- {0, 1040, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {0, 1040, 0, 769}, /* ; 01 (320x350,640x350) */
- {0, 1040, 0, 769}, /* ; 02 (360x400,720x400) */
- {0, 1040, 0, 769}, /* ; 03 (720x350) */
- {0, 1040, 0, 769}, /* ; 04 (640x480x75Hz) */
- {0, 1040, 0, 769}, /* ; 05 (800x600x75Hz) */
- {0, 1040, 0, 769} /* ; 06 (1024x768x75Hz) */
-};
-
-/* ; 1024x768 center-screen (Enh. Mode) */
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_2x75[] = {
- {1142, 856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
- {1142, 856, 597, 562}, /* 01 (320x350,640x350) */
- {1142, 856, 622, 587}, /* 02 (360x400,720x400) */
- {1142, 856, 597, 562}, /* 03 (720x350) */
- {1142, 1048, 722, 687}, /* 04 (640x480x60Hz) */
- {1232, 936, 722, 687}, /* 05 (800x600x60Hz) */
- { 0, 1048, 805, 771} /* 06 (1024x768x60Hz) */
-};
-
-/* ; 1024x768 center-screen (St.Mode) */
-static const struct SiS_LVDSData XGI_LVDS1024x768Des_3x75[] = {
- {320, 24, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {320, 24, 597, 562}, /* ; 01 (320x350,640x350) */
- {320, 24, 622, 587}, /* ; 02 (360x400,720x400) */
- {320, 24, 597, 562}, /* ; 03 (720x350) */
- {320, 24, 722, 687} /* ; 04 (640x480x60Hz) */
-};
-
-static const struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = {
- {0, 1296, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {0, 1296, 0, 1025}, /* ; 01 (320x350,640x350) */
- {0, 1296, 0, 1025}, /* ; 02 (360x400,720x400) */
- {0, 1296, 0, 1025}, /* ; 03 (720x350) */
- {0, 1296, 0, 1025}, /* ; 04 (640x480x75Hz) */
- {0, 1296, 0, 1025}, /* ; 05 (800x600x75Hz) */
- {0, 1296, 0, 1025}, /* ; 06 (1024x768x75Hz) */
- {0, 1296, 0, 1025} /* ; 07 (1280x1024x75Hz) */
-};
-
-/* The Display setting for DE Mode Panel */
-/* Set DE as default */
-static const struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = {
- {1368, 976, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
- {1368, 976, 729, 688}, /* ; 01 (320x350,640x350) */
- {1408, 976, 752, 711}, /* ; 02 (360x400,720x400) */
- {1408, 976, 729, 688}, /* ; 03 (720x350) */
- {1368, 976, 794, 753}, /* ; 04 (640x480x75Hz) */
- {1448, 1036, 854, 813}, /* ; 05 (800x600x75Hz) */
- {1560, 1168, 938, 897}, /* ; 06 (1024x768x75Hz) */
- { 0, 1296, 0, 1025} /* ; 07 (1280x1024x75Hz) */
-};
-
-/* Scaling LCD 75Hz */
-static const struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = {
- {0, 648, 448, 405, 96, 2}, /* ; 00 (320x200,320x400,
- * 640x200,640x400)
- */
- {0, 648, 448, 355, 96, 2}, /* ; 01 (320x350,640x350) */
- {0, 729, 448, 405, 108, 2}, /* ; 02 (360x400,720x400) */
- {0, 729, 448, 355, 108, 2}, /* ; 03 (720x350) */
- {0, 656, 0, 481, 64, 3}, /* ; 04 (640x480x75Hz) */
- {0, 816, 0, 601, 80, 3}, /* ; 05 (800x600x75Hz) */
- {0, 1040, 0, 769, 96, 3}, /* ; 06 (1024x768x75Hz) */
- {0, 1296, 0, 1025, 144, 3}, /* ; 07 (1280x1024x75Hz) */
- {0, 1448, 0, 1051, 112, 3}, /* ; 08 (1400x1050x75Hz) */
- {0, 1664, 0, 1201, 192, 3}, /* ; 09 (1600x1200x75Hz) */
- {0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_H[] = {
- { {0x4B, 0x27, 0x8F, 0x32, 0x1B, 0x00, 0x45, 0x00} }, /* 00 (320x) */
- { {0x4B, 0x27, 0x8F, 0x2B, 0x03, 0x00, 0x44, 0x00} }, /* 01 (360x) */
- { {0x55, 0x31, 0x99, 0x46, 0x1D, 0x00, 0x55, 0x00} }, /* 02 (400x) */
- { {0x63, 0x3F, 0x87, 0x4A, 0x93, 0x00, 0x01, 0x00} }, /* 03 (512x) */
- { {0x73, 0x4F, 0x97, 0x55, 0x86, 0x00, 0x05, 0x00} }, /* 04 (640x) */
- { {0x73, 0x4F, 0x97, 0x55, 0x86, 0x00, 0x05, 0x00} }, /* 05 (720x) */
- { {0x87, 0x63, 0x8B, 0x69, 0x1A, 0x00, 0x26, 0x00} }, /* 06 (800x) */
- { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00} } /* 07 (1024x) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_H[] = {
- { {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00 } }, /* 00 (320x) */
- { {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00 } }, /* 01 (360x) */
- { {0x60, 0x31, 0x84, 0x3A, 0x88, 0x00, 0x01, 0x00 } }, /* 02 (400x) */
- { {0x6E, 0x3F, 0x92, 0x48, 0x96, 0x00, 0x01, 0x00 } }, /* 03 (512x) */
- { {0x7E, 0x4F, 0x82, 0x58, 0x06, 0x00, 0x06, 0x00 } }, /* 04 (640x) */
- { {0x7E, 0x4F, 0x82, 0x58, 0x06, 0x00, 0x06, 0x00 } }, /* 05 (720x) */
- { {0x92, 0x63, 0x96, 0x6C, 0x1A, 0x00, 0x06, 0x00 } }, /* 06 (800x) */
- { {0xAE, 0x7F, 0x92, 0x88, 0x96, 0x00, 0x02, 0x00 } }, /* 07 (1024x) */
- { {0xCE, 0x9F, 0x92, 0xA8, 0x16, 0x00, 0x07, 0x00 } } /* 08 (1280x) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_H[] = {
- { {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} }, /* 00 (320x) */
- { {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} }, /* 01 (360x) */
- { {0x63, 0x31, 0x87, 0x3D, 0x8E, 0x00, 0x01, 0x00} }, /* 02 (400x) */
- { {0x63, 0x3F, 0x87, 0x45, 0x96, 0x00, 0x01, 0x00} }, /* 03 (512x) */
- { {0xA3, 0x4F, 0x87, 0x6E, 0x9F, 0x00, 0x06, 0x00} }, /* 04 (640x) */
- { {0xA3, 0x4F, 0x87, 0x6E, 0x9F, 0x00, 0x06, 0x00} }, /* 05 (720x) */
- { {0xA3, 0x63, 0x87, 0x78, 0x89, 0x00, 0x02, 0x00} }, /* 06 (800x) */
- { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00} } /* 07 (1024x) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_H[] = {
- { {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} }, /* 00 (320x) */
- { {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} }, /* 01 (360x) */
- { {0x7E, 0x40, 0x84, 0x49, 0x91, 0x00, 0x01, 0x00} }, /* 02 (400x) */
- { {0x7E, 0x47, 0x93, 0x50, 0x9E, 0x00, 0x01, 0x00} }, /* 03 (512x) */
- { {0xCE, 0x77, 0x8A, 0x80, 0x8E, 0x00, 0x02, 0x00} }, /* 04 (640x) */
- { {0xCE, 0x77, 0x8A, 0x80, 0x8E, 0x00, 0x02, 0x00} }, /* 05 (720x) */
- { {0xCE, 0x81, 0x94, 0x8A, 0x98, 0x00, 0x02, 0x00} }, /* 06 (800x) */
- { {0xCE, 0x8F, 0x82, 0x98, 0x06, 0x00, 0x07, 0x00} }, /* 07 (1024x) */
- { {0xCE, 0x9F, 0x92, 0xA8, 0x16, 0x00, 0x07, 0x00} } /* 08 (1280x) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[] = {
- { {0x47, 0x27, 0x8B, 0x2C, 0x1A, 0x00, 0x05, 0x00} }, /* 00 (320x) */
- { {0x47, 0x27, 0x8B, 0x30, 0x1E, 0x00, 0x05, 0x00} }, /* 01 (360x) */
- { {0x51, 0x31, 0x95, 0x36, 0x04, 0x00, 0x01, 0x00} }, /* 02 (400x) */
- { {0x5F, 0x3F, 0x83, 0x44, 0x92, 0x00, 0x01, 0x00} }, /* 03 (512x) */
- { {0x6F, 0x4F, 0x93, 0x54, 0x82, 0x00, 0x05, 0x00} }, /* 04 (640x) */
- { {0x6F, 0x4F, 0x93, 0x54, 0x82, 0x00, 0x05, 0x00} }, /* 05 (720x) */
- { {0x83, 0x63, 0x87, 0x68, 0x16, 0x00, 0x06, 0x00} }, /* 06 (800x) */
- { {0x9F, 0x7F, 0x83, 0x84, 0x92, 0x00, 0x02, 0x00} }, /* 07 (1024x) */
- { {0xBF, 0x9F, 0x83, 0xA4, 0x12, 0x00, 0x07, 0x00} }, /* 08 (1280x) */
- { {0xCE, 0xAE, 0x92, 0xB3, 0x01, 0x00, 0x03, 0x00} } /* 09 (1400x) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[] = {
- { {0x76, 0x3F, 0x83, 0x45, 0x8C, 0x00, 0x41, 0x00} }, /* 00 (320x) */
- { {0x76, 0x3F, 0x83, 0x45, 0x8C, 0x00, 0x41, 0x00} }, /* 01 (360x) */
- { {0x76, 0x31, 0x9A, 0x48, 0x9F, 0x00, 0x41, 0x00} }, /* 02 (400x) */
- { {0x76, 0x3F, 0x9A, 0x4F, 0x96, 0x00, 0x41, 0x00} }, /* 03 (512x) */
- { {0xCE, 0x7E, 0x82, 0x87, 0x9E, 0x00, 0x02, 0x00} }, /* 04 (640x) */
- { {0xCE, 0x7E, 0x82, 0x87, 0x9E, 0x00, 0x02, 0x00} }, /* 05 (720x) */
- { {0xCE, 0x63, 0x92, 0x96, 0x04, 0x00, 0x07, 0x00} }, /* 06 (800x) */
- { {0xCE, 0x7F, 0x92, 0xA4, 0x12, 0x00, 0x07, 0x00} }, /* 07 (1024x) */
- { {0xCE, 0x9F, 0x92, 0xB4, 0x02, 0x00, 0x03, 0x00} }, /* 08 (1280x) */
- { {0xCE, 0xAE, 0x92, 0xBC, 0x0A, 0x00, 0x03, 0x00} } /* 09 (1400x) */
-};
-
-/* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
-/* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[] = {
- { {0x5B, 0x27, 0x9F, 0x32, 0x0A, 0x00, 0x01, 0x00} }, /* 00 (320x) */
- { {0x5B, 0x27, 0x9F, 0x32, 0x0A, 0x00, 0x01, 0x00} }, /* 01 (360x) */
- { {0x65, 0x31, 0x89, 0x3C, 0x94, 0x00, 0x01, 0x00} }, /* 02 (400x) */
- { {0x73, 0x3F, 0x97, 0x4A, 0x82, 0x00, 0x05, 0x00} }, /* 03 (512x) */
- { {0x83, 0x4F, 0x87, 0x51, 0x09, 0x00, 0x06, 0x00} }, /* 04 (640x) */
- { {0x83, 0x4F, 0x87, 0x51, 0x09, 0x00, 0x06, 0x00} }, /* 05 (720x) */
- { {0x97, 0x63, 0x9B, 0x65, 0x1D, 0x00, 0x06, 0xF0} }, /* 06 (800x) */
- { {0xB3, 0x7F, 0x97, 0x81, 0x99, 0x00, 0x02, 0x00} }, /* 07 (1024x) */
- { {0xD3, 0x9F, 0x97, 0xA1, 0x19, 0x00, 0x07, 0x00} }, /* 08 (1280x) */
- { {0xE2, 0xAE, 0x86, 0xB9, 0x91, 0x00, 0x03, 0x00} }, /* 09 (1400x) */
- { {0xFB, 0xC7, 0x9F, 0xC9, 0x81, 0x00, 0x07, 0x00} } /* 0A (1600x) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[] = {
- { {0x97, 0x1F, 0x60, 0x87, 0x5D, 0x83, 0x10} }, /* 00 (x350) */
- { {0xB4, 0x1F, 0x92, 0x89, 0x8F, 0xB5, 0x30} }, /* 01 (x400) */
- { {0x04, 0x3E, 0xE2, 0x89, 0xDF, 0x05, 0x00} }, /* 02 (x480) */
- { {0x7C, 0xF0, 0x5A, 0x8F, 0x57, 0x7D, 0xA0} }, /* 03 (x600) */
- { {0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} } /* 04 (x768) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[] = {
- { {0x24, 0xBB, 0x31, 0x87, 0x5D, 0x25, 0x30} }, /* 00 (x350) */
- { {0x24, 0xBB, 0x4A, 0x80, 0x8F, 0x25, 0x30} }, /* 01 (x400) */
- { {0x24, 0xBB, 0x72, 0x88, 0xDF, 0x25, 0x30} }, /* 02 (x480) */
- { {0x24, 0xF1, 0xAE, 0x84, 0x57, 0x25, 0xB0} }, /* 03 (x600) */
- { {0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} } /* 04 (x768) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[] = {
- { {0x86, 0x1F, 0x5E, 0x82, 0x5D, 0x87, 0x00} }, /* 00 (x350) */
- { {0xB8, 0x1F, 0x90, 0x84, 0x8F, 0xB9, 0x30} }, /* 01 (x400) */
- { {0x08, 0x3E, 0xE0, 0x84, 0xDF, 0x09, 0x00} }, /* 02 (x480) */
- { {0x80, 0xF0, 0x58, 0x8C, 0x57, 0x81, 0xA0} }, /* 03 (x600) */
- { {0x28, 0xF5, 0x00, 0x84, 0xFF, 0x29, 0x90} }, /* 04 (x768) */
- { {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* 05 (x1024) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[] = {
- { {0x28, 0xD2, 0xAF, 0x83, 0xAE, 0xD8, 0xA1} }, /* 00 (x350) */
- { {0x28, 0xD2, 0xC8, 0x8C, 0xC7, 0xF2, 0x81} }, /* 01 (x400) */
- { {0x28, 0xD2, 0xF0, 0x84, 0xEF, 0x1A, 0xB1} }, /* 02 (x480) */
- { {0x28, 0xDE, 0x2C, 0x8F, 0x2B, 0x56, 0x91} }, /* 03 (x600) */
- { {0x28, 0xDE, 0x80, 0x83, 0x7F, 0xAA, 0x91} }, /* 04 (x768) */
- { {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* 05 (x1024) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[] = {
- { {0x6C, 0x1F, 0x60, 0x84, 0x5D, 0x6D, 0x10} }, /* 00 (x350) */
- { {0x9E, 0x1F, 0x93, 0x86, 0x8F, 0x9F, 0x30} }, /* 01 (x400) */
- { {0xEE, 0x1F, 0xE2, 0x86, 0xDF, 0xEF, 0x10} }, /* 02 (x480) */
- { {0x66, 0xF0, 0x5A, 0x8e, 0x57, 0x67, 0xA0} }, /* 03 (x600) */
- { {0x0E, 0xF5, 0x02, 0x86, 0xFF, 0x0F, 0x90} }, /* 04 (x768) */
- { {0x0E, 0x5A, 0x02, 0x86, 0xFF, 0x0F, 0x89} }, /* 05 (x1024) */
- { {0x28, 0x10, 0x1A, 0x80, 0x19, 0x29, 0x0F} } /* 06 (x1050) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[] = {
- { {0x28, 0x92, 0xB6, 0x83, 0xB5, 0xCF, 0x81} }, /* 00 (x350) */
- { {0x28, 0x92, 0xD5, 0x82, 0xD4, 0xEE, 0x81} }, /* 01 (x400) */
- { {0x28, 0x92, 0xFD, 0x8A, 0xFC, 0x16, 0xB1} }, /* 02 (x480) */
- { {0x28, 0xD4, 0x39, 0x86, 0x57, 0x29, 0x81} }, /* 03 (x600) */
- { {0x28, 0xD4, 0x8D, 0x9A, 0xFF, 0x29, 0xA1} }, /* 04 (x768) */
- { {0x28, 0x5A, 0x0D, 0x9A, 0xFF, 0x29, 0xA9} }, /* 05 (x1024) */
- { {0x28, 0x10, 0x1A, 0x87, 0x19, 0x29, 0x8F} } /* 06 (x1050) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[] = {
- { {0xd4, 0x1F, 0x81, 0x84, 0x5D, 0xd5, 0x10} }, /* 00 (x350) */
- { {0x06, 0x3e, 0xb3, 0x86, 0x8F, 0x07, 0x20} }, /* 01 (x400) */
- { {0x56, 0xba, 0x03, 0x86, 0xDF, 0x57, 0x00} }, /* 02 (x480) */
- { {0xce, 0xF0, 0x7b, 0x8e, 0x57, 0xcf, 0xa0} }, /* 03 (x600) */
- { {0x76, 0xF5, 0x23, 0x86, 0xFF, 0x77, 0x90} }, /* 04 (x768) */
- { {0x76, 0x5A, 0x23, 0x86, 0xFF, 0x77, 0x89} }, /* 05 (x1024) */
- { {0x90, 0x10, 0x1A, 0x8E, 0x19, 0x91, 0x2F} }, /* 06 (x1050) */
- { {0x26, 0x11, 0xd3, 0x86, 0xaF, 0x27, 0x3f} } /* 07 (x1200) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[] = {
- { {0x4B, 0x27, 0x8F, 0x32, 0x1B, 0x00, 0x45, 0x00} },/* ; 00 (320x) */
- { {0x4B, 0x27, 0x8F, 0x2B, 0x03, 0x00, 0x44, 0x00} },/* ; 01 (360x) */
- { {0x55, 0x31, 0x99, 0x46, 0x1D, 0x00, 0x55, 0x00} },/* ; 02 (400x) */
- { {0x63, 0x3F, 0x87, 0x4A, 0x93, 0x00, 0x01, 0x00} },/* ; 03 (512x) */
- { {0x6F, 0x4F, 0x93, 0x54, 0x80, 0x00, 0x05, 0x00} },/* ; 04 (640x) */
- { {0x6F, 0x4F, 0x93, 0x54, 0x80, 0x00, 0x05, 0x00} },/* ; 05 (720x) */
- { {0x83, 0x63, 0x87, 0x68, 0x14, 0x00, 0x26, 0x00} },/* ; 06 (800x) */
- { {0x9F, 0x7F, 0x83, 0x85, 0x91, 0x00, 0x02, 0x00} } /* ; 07 (1024x) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[] = {
- { {0x97, 0x1F, 0x60, 0x87, 0x5D, 0x83, 0x10} },/* ; 00 (x350) */
- { {0xB4, 0x1F, 0x92, 0x89, 0x8F, 0xB5, 0x30} },/* ; 01 (x400) */
- { {0xFE, 0x1F, 0xE0, 0x84, 0xDF, 0xFF, 0x10} },/* ; 02 (x480) */
- { {0x76, 0xF0, 0x58, 0x8C, 0x57, 0x77, 0xA0} },/* ; 03 (x600) */
- { {0x1E, 0xF5, 0x00, 0x83, 0xFF, 0x1F, 0x90} } /* ; 04 (x768) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[] = {
- { {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} },/* ; 00 (320x) */
- { {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} },/* ; 01 (360x) */
- { {0x63, 0x31, 0x87, 0x3D, 0x8E, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
- { {0x63, 0x3F, 0x87, 0x45, 0x96, 0x00, 0x01, 0x00} },/* ; 03 (512x) */
- { {0xA3, 0x4F, 0x87, 0x6E, 0x9F, 0x00, 0x06, 0x00} },/* ; 04 (640x) */
- { {0xA3, 0x4F, 0x87, 0x6E, 0x9F, 0x00, 0x06, 0x00} },/* ; 05 (720x) */
- { {0xA3, 0x63, 0x87, 0x78, 0x89, 0x00, 0x02, 0x00} },/* ; 06 (800x) */
- { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00} } /* ; 07 (1024x) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[] = {
- { {0x24, 0xBB, 0x31, 0x87, 0x5D, 0x25, 0x30} },/* ; 00 (x350) */
- { {0x24, 0xBB, 0x4A, 0x80, 0x8F, 0x25, 0x30} },/* ; 01 (x400) */
- { {0x24, 0xBB, 0x72, 0x88, 0xDF, 0x25, 0x30} },/* ; 02 (x480) */
- { {0x24, 0xF1, 0xAE, 0x84, 0x57, 0x25, 0xB0} },/* ; 03 (x600) */
- { {0x24, 0xF5, 0x02, 0x88, 0xFF, 0x25, 0x90} } /* ; 04 (x768) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[] = {
- { {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00} },/* ; 00 (320x) */
- { {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00} },/* ; 01 (360x) */
- { {0x60, 0x31, 0x84, 0x3A, 0x88, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
- { {0x6E, 0x3F, 0x92, 0x48, 0x96, 0x00, 0x01, 0x00} },/* ; 03 (512x) */
- { {0x7E, 0x4F, 0x82, 0x54, 0x06, 0x00, 0x06, 0x00} },/* ; 04 (640x) */
- { {0x7E, 0x4F, 0x82, 0x54, 0x06, 0x00, 0x06, 0x00} },/* ; 05 (720x) */
- { {0x92, 0x63, 0x96, 0x68, 0x1A, 0x00, 0x06, 0x00} },/* ; 06 (800x) */
- { {0xAE, 0x7F, 0x92, 0x84, 0x96, 0x00, 0x02, 0x00} },/* ; 07 (1024x) */
- { {0xCE, 0x9F, 0x92, 0xA5, 0x17, 0x00, 0x07, 0x00} } /* ; 08 (1280x) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[] = {
- { {0x86, 0xD1, 0xBC, 0x80, 0xBB, 0xE5, 0x00} },/* ; 00 (x350) */
- { {0xB8, 0x1F, 0x90, 0x84, 0x8F, 0xB9, 0x30} },/* ; 01 (x400) */
- { {0x08, 0x3E, 0xE0, 0x84, 0xDF, 0x09, 0x00} },/* ; 02 (x480) */
- { {0x80, 0xF0, 0x58, 0x8C, 0x57, 0x81, 0xA0} },/* ; 03 (x600) */
- { {0x28, 0xF5, 0x00, 0x84, 0xFF, 0x29, 0x90} },/* ; 04 (x768) */
- { {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* ; 05 (x1024) */
-};
-
-/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[] = {
- { {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} },/* ; 00 (320x) */
- { {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} },/* ; 01 (360x) */
- { {0x7E, 0x40, 0x84, 0x49, 0x91, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
- { {0x7E, 0x47, 0x93, 0x50, 0x9E, 0x00, 0x01, 0x00} },/* ; 03 (512x) */
- { {0xCE, 0x77, 0x8A, 0x80, 0x8E, 0x00, 0x02, 0x00} },/* ; 04 (640x) */
- { {0xCE, 0x77, 0x8A, 0x80, 0x8E, 0x00, 0x02, 0x00} },/* ; 05 (720x) */
- { {0xCE, 0x81, 0x94, 0x8A, 0x98, 0x00, 0x02, 0x00} },/* ; 06 (800x) */
- { {0xCE, 0x8F, 0x82, 0x98, 0x06, 0x00, 0x07, 0x00} },/* ; 07 (1024x) */
- { {0xCE, 0x9F, 0x92, 0xA8, 0x16, 0x00, 0x07, 0x00} } /* ; 08 (1280x) */
-};
-
-/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = {
- { {0x28, 0xD2, 0xAF, 0x83, 0xAE, 0xD8, 0xA1} },/* ; 00 (x350) */
- { {0x28, 0xD2, 0xC8, 0x8C, 0xC7, 0xF2, 0x81} },/* ; 01 (x400) */
- { {0x28, 0xD2, 0xF0, 0x84, 0xEF, 0x1A, 0xB1} },/* ; 02 (x480) */
- { {0x28, 0xDE, 0x2C, 0x8F, 0x2B, 0x56, 0x91} },/* ; 03 (x600) */
- { {0x28, 0xDE, 0x80, 0x83, 0x7F, 0xAA, 0x91} },/* ; 04 (x768) */
- { {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* ; 05 (x1024) */
-};
-
-/*add for new UNIVGABIOS*/
-static const struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = {
- {Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCD1024x768Data },
- {Panel_1024x768, 0x0019, 0x0000, XGI_StLCD1024x768Data },
- {Panel_1024x768, 0x0018, 0x0010, XGI_CetLCD1024x768Data },
- {Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCD1280x1024Data },
- {Panel_1280x1024, 0x0019, 0x0000, XGI_StLCD1280x1024Data },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCD1280x1024Data },
- {Panel_1400x1050, 0x0019, 0x0001, xgifb_lcd_1400x1050 },
- {Panel_1400x1050, 0x0019, 0x0000, xgifb_lcd_1400x1050 },
- {Panel_1400x1050, 0x0018, 0x0010, XGI_CetLCD1400x1050Data },
- {Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCD1600x1200Data },
- {Panel_1600x1200, 0x0019, 0x0000, XGI_StLCD1600x1200Data },
- {PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingData },
- {Panel_1024x768x75, 0x0019, 0x0001, XGI_ExtLCD1024x768x75Data },
- {Panel_1024x768x75, 0x0019, 0x0000, XGI_ExtLCD1024x768x75Data },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCD1024x768x75Data },
- {Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcd_1280x1024x75 },
- {Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcd_1280x1024x75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCD1280x1024x75Data },
- {PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDatax75 },
- {0xFF, 0x0000, 0x0000, NULL } /* End of table */
-};
-
-static const struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = {
- {Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCDDes1024x768Data },
- {Panel_1024x768, 0x0019, 0x0000, XGI_StLCDDes1024x768Data },
- {Panel_1024x768, 0x0018, 0x0010, XGI_CetLCDDes1024x768Data },
- {Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCDDes1280x1024Data },
- {Panel_1280x1024, 0x0019, 0x0000, XGI_StLCDDes1280x1024Data },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCDDes1280x1024Data },
- {Panel_1400x1050, 0x0019, 0x0001, xgifb_lcddes_1400x1050 },
- {Panel_1400x1050, 0x0019, 0x0000, xgifb_lcddes_1400x1050 },
- {Panel_1400x1050, 0x0418, 0x0010, XGI_CetLCDDes1400x1050Data },
- {Panel_1400x1050, 0x0418, 0x0410, XGI_CetLCDDes1400x1050Data2 },
- {Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCDDes1600x1200Data },
- {Panel_1600x1200, 0x0019, 0x0000, XGI_StLCDDes1600x1200Data },
- {PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingDesData },
- {Panel_1024x768x75, 0x0019, 0x0001, xgifb_lcddes_1024x768x75 },
- {Panel_1024x768x75, 0x0019, 0x0000, xgifb_lcddes_1024x768x75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCDDes1024x768x75Data },
- {Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcddes_1280x1024x75 },
- {Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcddes_1280x1024x75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCDDes1280x1024x75Data },
- {PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDesDatax75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_LCDDataTablStruct xgifb_lcddldes[] = {
- {Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCDDes1024x768Data },
- {Panel_1024x768, 0x0019, 0x0000, XGI_StLCDDes1024x768Data },
- {Panel_1024x768, 0x0018, 0x0010, XGI_CetLCDDes1024x768Data },
- {Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCDDLDes1280x1024Data },
- {Panel_1280x1024, 0x0019, 0x0000, XGI_StLCDDLDes1280x1024Data },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCDDLDes1280x1024Data },
- {Panel_1400x1050, 0x0019, 0x0001, xgifb_lcddldes_1400x1050 },
- {Panel_1400x1050, 0x0019, 0x0000, xgifb_lcddldes_1400x1050 },
- {Panel_1400x1050, 0x0418, 0x0010, XGI_CetLCDDes1400x1050Data },
- {Panel_1400x1050, 0x0418, 0x0410, XGI_CetLCDDes1400x1050Data2 },
- {Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCDDLDes1600x1200Data },
- {Panel_1600x1200, 0x0019, 0x0000, XGI_StLCDDLDes1600x1200Data },
- {PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingDesData },
- {Panel_1024x768x75, 0x0019, 0x0001, xgifb_lcddes_1024x768x75 },
- {Panel_1024x768x75, 0x0019, 0x0000, xgifb_lcddes_1024x768x75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCDDes1024x768x75Data },
- {Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcddldes_1280x1024x75 },
- {Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcddldes_1280x1024x75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCDDLDes1280x1024x75Data },
- {PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDesDatax75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1_h[] = {
- {Panel_1024x768, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_H },
- {Panel_1024x768, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_H },
- {Panel_1280x1024, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_H },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_H },
- {Panel_1400x1050, 0x0018, 0x0000, XGI_LVDSCRT11400x1050_1_H },
- {Panel_1400x1050, 0x0018, 0x0010, XGI_LVDSCRT11400x1050_2_H },
- {Panel_1600x1200, 0x0018, 0x0000, XGI_LVDSCRT11600x1200_1_H },
- {Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_Hx75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_Hx75 },
- {Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_Hx75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_Hx75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1_v[] = {
- {Panel_1024x768, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_V },
- {Panel_1024x768, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_V },
- {Panel_1280x1024, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_V },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_V },
- {Panel_1400x1050, 0x0018, 0x0000, XGI_LVDSCRT11400x1050_1_V },
- {Panel_1400x1050, 0x0018, 0x0010, XGI_LVDSCRT11400x1050_2_V },
- {Panel_1600x1200, 0x0018, 0x0000, XGI_LVDSCRT11600x1200_1_V },
- {Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_Vx75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_Vx75 },
- {Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_Vx75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_Vx75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] = {
- {Panel_1024x768, 0x0018, 0x0000, XGI_LVDS1024x768Data_1 },
- {Panel_1024x768, 0x0018, 0x0010, XGI_LVDS1024x768Data_2 },
- {Panel_1280x1024, 0x0018, 0x0000, XGI_LVDS1280x1024Data_1 },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_LVDS1280x1024Data_2 },
- {Panel_1400x1050, 0x0018, 0x0000, XGI_LVDS1400x1050Data_1 },
- {Panel_1400x1050, 0x0018, 0x0010, XGI_LVDS1400x1050Data_2 },
- {Panel_1600x1200, 0x0018, 0x0000, XGI_LVDS1600x1200Data_1 },
- {PanelRef60Hz, 0x0008, 0x0008, XGI_LVDSNoScalingData },
- {Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDS1024x768Data_1x75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDS1024x768Data_2x75 },
- {Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDS1280x1024Data_1x75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDS1280x1024Data_2x75 },
- {PanelRef75Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDatax75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = {
- {Panel_1024x768, 0x0018, 0x0000, XGI_LVDS1024x768Des_1 },
- {Panel_1024x768, 0x0618, 0x0410, XGI_LVDS1024x768Des_3 },
- {Panel_1024x768, 0x0018, 0x0010, XGI_LVDS1024x768Des_2 },
- {Panel_1280x1024, 0x0018, 0x0000, XGI_LVDS1280x1024Des_1 },
- {Panel_1280x1024, 0x0018, 0x0010, XGI_LVDS1280x1024Des_2 },
- {Panel_1400x1050, 0x0018, 0x0000, XGI_LVDS1400x1050Des_1 },
- {Panel_1400x1050, 0x0018, 0x0010, XGI_LVDS1400x1050Des_2 },
- {Panel_1600x1200, 0x0018, 0x0000, XGI_LVDS1600x1200Des_1 },
- {PanelRef60Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDesData },
- {Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDS1024x768Des_1x75 },
- {Panel_1024x768x75, 0x0618, 0x0410, XGI_LVDS1024x768Des_3x75 },
- {Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDS1024x768Des_2x75 },
- {Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDS1280x1024Des_1x75 },
- {Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDS1280x1024Des_2x75 },
- {PanelRef75Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDesDatax75 },
- {0xFF, 0x0000, 0x0000, NULL }
-};
-
-static const struct XGI330_TVDataTablStruct XGI_TVDataTable[] = {
- {0x09E1, 0x0001, XGI_ExtPALData},
- {0x09E1, 0x0000, XGI_ExtNTSCData},
- {0x09E1, 0x0801, XGI_StPALData},
- {0x09E1, 0x0800, XGI_StNTSCData},
- {0x49E0, 0x0100, XGI_ExtHiTVData},
- {0x49E0, 0x4100, XGI_St2HiTVData},
- {0x49E0, 0x4900, XGI_St1HiTVData},
- {0x09E0, 0x0020, XGI_ExtYPbPr525iData},
- {0x09E0, 0x0040, XGI_ExtYPbPr525pData},
- {0x09E0, 0x0080, XGI_ExtYPbPr750pData},
- {0x09E0, 0x0820, XGI_StYPbPr525iData},
- {0x09E0, 0x0840, XGI_StYPbPr525pData},
- {0x09E0, 0x0880, XGI_StYPbPr750pData},
- {0xffff, 0x0000, XGI_ExtNTSCData},
-};
-
-/* Dual link only */
-static const struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = {
-/* LCDCap1024x768 */
- {Panel_1024x768, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
- 0x6C, 0xC3, 0x35, 0x62,
- 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024 */
- {Panel_1280x1024, XGI_LCDDualLink + DefaultLCDCap,
- 0x70, 0x03, VCLK108_2_315,
- 0x70, 0x44, 0xF8, 0x2F,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1400x1050 */
- {Panel_1400x1050, XGI_LCDDualLink + DefaultLCDCap,
- 0x70, 0x03, VCLK108_2_315,
- 0x70, 0x44, 0xF8, 0x2F,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1600x1200 */
- {Panel_1600x1200, XGI_LCDDualLink + DefaultLCDCap,
- 0xC0, 0x03, VCLK162,
- 0x43, 0x22, 0x70, 0x24,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1024x768x75 */
- {Panel_1024x768x75, DefaultLCDCap, 0x60, 0, VCLK78_75,
- 0x2B, 0x61, 0x2B, 0x61,
- 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024x75 */
- {Panel_1280x1024x75, XGI_LCDDualLink + DefaultLCDCap,
- 0x90, 0x03, VCLK135_5,
- 0x54, 0x42, 0x4A, 0x61,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCapDefault */
- {0xFF, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
- 0x6C, 0xC3, 0x35, 0x62,
- 0x0A, 0xC0, 0x28, 0x10}
-};
-
-static const struct XGI330_LCDCapStruct XGI_LCDCapList[] = {
-/* LCDCap1024x768 */
- {Panel_1024x768, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
- 0x6C, 0xC3, 0x35, 0x62,
- 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024 */
- {Panel_1280x1024, DefaultLCDCap,
- 0x70, 0x03, VCLK108_2_315,
- 0x70, 0x44, 0xF8, 0x2F,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1400x1050 */
- {Panel_1400x1050, DefaultLCDCap,
- 0x70, 0x03, VCLK108_2_315,
- 0x70, 0x44, 0xF8, 0x2F,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1600x1200 */
- {Panel_1600x1200, DefaultLCDCap,
- 0xC0, 0x03, VCLK162,
- 0x5A, 0x23, 0x5A, 0x23,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCap1024x768x75 */
- {Panel_1024x768x75, DefaultLCDCap, 0x60, 0, VCLK78_75,
- 0x2B, 0x61, 0x2B, 0x61,
- 0x0A, 0xC0, 0x28, 0x10},
-/* LCDCap1280x1024x75 */
- {Panel_1280x1024x75, DefaultLCDCap,
- 0x90, 0x03, VCLK135_5,
- 0x54, 0x42, 0x4A, 0x61,
- 0x0A, 0xC0, 0x30, 0x10},
-/* LCDCapDefault */
- {0xFF, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
- 0x6C, 0xC3, 0x35, 0x62,
- 0x0A, 0xC0, 0x28, 0x10}
-};
-
-const struct XGI_Ext2Struct XGI330_RefIndex[] = {
- {Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175,
- 0x00, 0x10, 0x59, 320, 200},/* 00 */
- {Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175,
- 0x00, 0x10, 0x00, 320, 400},/* 01 */
- {Mode32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175,
- 0x04, 0x20, 0x50, 320, 240},/* 02 */
- {Mode32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40,
- 0x05, 0x32, 0x51, 400, 300},/* 03 */
- {Mode32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384,
- VCLK65_315, 0x06, 0x43, 0x52, 512, 384},/* 04 */
- {Mode32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175,
- 0x00, 0x14, 0x2f, 640, 400},/* 05 */
- {Mode32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175,
- 0x04, 0x24, 0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */
- {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5,
- 0x04, 0x24, 0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */
- {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5,
- 0x47, 0x24, 0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */
- {Mode32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36,
- 0x8A, 0x24, 0x2e, 640, 480},/* 09 640x480x85Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163,
- 0x00, 0x24, 0x2e, 640, 480},/* 0a 640x480x100Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406,
- 0x00, 0x24, 0x2e, 640, 480},/* 0b 640x480x120Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852,
- 0x00, 0x24, 0x2e, 640, 480},/* 0c 640x480x160Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6,
- 0x00, 0x24, 0x2e, 640, 480},/* 0d 640x480x200Hz */
- {Mode32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36,
- 0x05, 0x36, 0x6a, 800, 600},/* 0e 800x600x56Hz */
- {Mode32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40,
- 0x05, 0x36, 0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */
- {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50,
- 0x48, 0x36, 0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */
- {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5,
- 0x8B, 0x36, 0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25,
- 0x00, 0x36, 0x6a, 800, 600},/* 12 800x600x85Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179,
- 0x00, 0x36, 0x6a, 800, 600},/* 13 800x600x100Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95,
- 0x00, 0x36, 0x6a, 800, 600},/* 14 800x600x120Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406,
- 0x00, 0x36, 0x6a, 800, 600},/* 15 800x600x160Hz */
- {Mode32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9,
- 0x00, 0x47, 0x37, 1024, 768},/* 16 1024x768x43Hz */
- /* 17 1024x768x60Hz (LCD 1024x768x60Hz) */
- {Mode32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60,
- VCLK65_315, 0x06, 0x47, 0x37, 1024, 768},
- {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75,
- 0x49, 0x47, 0x37, 1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */
- {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75,
- 0x00, 0x47, 0x37, 1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5,
- 0x8C, 0x47, 0x37, 1024, 768},/* 1a 1024x768x85Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309,
- 0x00, 0x47, 0x37, 1024, 768},/* 1b 1024x768x100Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054,
- 0x00, 0x47, 0x37, 1024, 768},/* 1c 1024x768x120Hz */
- {Mode32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2_315,
- 0x08, 0x58, 0x7b, 1280, 960},/* 1d 1280x960x60Hz */
- {Mode32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75,
- 0x00, 0x58, 0x3a, 1280, 1024},/* 1e 1280x1024x43Hz */
- {Mode32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2_315,
- 0x07, 0x58, 0x3a, 1280, 1024},/*1f 1280x1024x60Hz (LCD 1280x1024x60Hz)*/
- {Mode32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5,
- 0x00, 0x58, 0x3a, 1280, 1024},/*20 1280x1024x75Hz (LCD 1280x1024x75Hz)*/
- {Mode32Bpp + SyncPP, RES1280x1024x85, VCLK157_5,
- 0x00, 0x58, 0x3a, 1280, 1024},/* 21 1280x1024x85Hz */
- /* 22 1600x1200x60Hz */
- {Mode32Bpp + SupportLCD + SyncPP + SupportCRT2in301C,
- RES1600x1200x60, VCLK162, 0x09, 0x7A, 0x3c, 1600, 1200},
- {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 23 1600x1200x65Hz */
- {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 24 1600x1200x70Hz */
- {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 25 1600x1200x75Hz */
- {Mode32Bpp + SyncPP, RES1600x1200x85, VCLK229_5,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 26 1600x1200x85Hz */
- {Mode32Bpp + SyncPP, RES1600x1200x100, VCLK269_655,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 27 1600x1200x100Hz */
- {Mode32Bpp + SyncPP, RES1600x1200x120, VCLK323_586,
- 0x00, 0x69, 0x3c, 1600, 1200},/* 28 1600x1200x120Hz */
- {Mode32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234,
- 0x00, 0x00, 0x68, 1920, 1440},/* 29 1920x1440x60Hz */
- {Mode32Bpp + SyncPN, RES1920x1440x65, VCLK254_817,
- 0x00, 0x00, 0x68, 1920, 1440},/* 2a 1920x1440x65Hz */
- {Mode32Bpp + SyncPN, RES1920x1440x70, VCLK277_015,
- 0x00, 0x00, 0x68, 1920, 1440},/* 2b 1920x1440x70Hz */
- {Mode32Bpp + SyncPN, RES1920x1440x75, VCLK291_132,
- 0x00, 0x00, 0x68, 1920, 1440},/* 2c 1920x1440x75Hz */
- {Mode32Bpp + SyncPN, RES1920x1440x85, VCLK330_615,
- 0x00, 0x00, 0x68, 1920, 1440},/* 2d 1920x1440x85Hz */
- {Mode16Bpp + SyncPN, RES1920x1440x100, VCLK388_631,
- 0x00, 0x00, 0x68, 1920, 1440},/* 2e 1920x1440x100Hz */
- {Mode32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952,
- 0x00, 0x00, 0x6c, 2048, 1536},/* 2f 2048x1536x60Hz */
- {Mode32Bpp + SyncPN, RES2048x1536x65, VCLK291_766,
- 0x00, 0x00, 0x6c, 2048, 1536},/* 30 2048x1536x65Hz */
- {Mode32Bpp + SyncPN, RES2048x1536x70, VCLK315_195,
- 0x00, 0x00, 0x6c, 2048, 1536},/* 31 2048x1536x70Hz */
- {Mode32Bpp + SyncPN, RES2048x1536x75, VCLK340_477,
- 0x00, 0x00, 0x6c, 2048, 1536},/* 32 2048x1536x75Hz */
- {Mode16Bpp + SyncPN, RES2048x1536x85, VCLK375_847,
- 0x00, 0x00, 0x6c, 2048, 1536},/* 33 2048x1536x85Hz */
- {Mode32Bpp + SupportHiVision + SupportRAMDAC2 +
- SyncPP + SupportYPbPr750p, RES800x480x60, VCLK39_77,
- 0x08, 0x00, 0x70, 800, 480},/* 34 800x480x60Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5,
- 0x08, 0x00, 0x70, 800, 480},/* 35 800x480x75Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25,
- 0x08, 0x00, 0x70, 800, 480},/* 36 800x480x85Hz */
- {Mode32Bpp + SupportHiVision + SupportRAMDAC2 +
- SyncPP + SupportYPbPr750p, RES1024x576x60, VCLK65_315,
- 0x09, 0x00, 0x71, 1024, 576},/* 37 1024x576x60Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75,
- 0x09, 0x00, 0x71, 1024, 576},/* 38 1024x576x75Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5,
- 0x09, 0x00, 0x71, 1024, 576},/* 39 1024x576x85Hz */
- {Mode32Bpp + SupportHiVision + SupportRAMDAC2 +
- SyncPP + SupportYPbPr750p, RES1280x720x60, VCLK108_2_315,
- 0x0A, 0x00, 0x75, 1280, 720},/* 3a 1280x720x60Hz*/
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5,
- 0x0A, 0x00, 0x75, 1280, 720},/* 3b 1280x720x75Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5,
- 0x0A, 0x00, 0x75, 1280, 720},/* 3c 1280x720x85Hz */
- {Mode32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322,
- 0x06, 0x00, 0x31, 720, 480},/* 3d 720x480x60Hz */
- {Mode32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36,
- 0x06, 0x00, 0x32, 720, 576},/* 3e 720x576x56Hz */
- {Mode32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I,
- VCLK35_2, 0x00, 0x00, 0x00, 856, 480},/* 3f 856x480x79I */
- {Mode32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2,
- 0x00, 0x00, 0x00, 856, 480},/* 40 856x480x60Hz */
- {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60,
- VCLK79_411, 0x08, 0x48, 0x23, 1280, 768},/* 41 1280x768x60Hz */
- {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60,
- VCLK122_61, 0x08, 0x69, 0x26, 1400, 1050},/* 42 1400x1050x60Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350,
- 0x37, 0x00, 0x20, 1152, 864},/* 43 1152x864x60Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385,
- 0x37, 0x00, 0x20, 1152, 864},/* 44 1152x864x75Hz */
- {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75,
- VCLK125_999, 0x3A, 0x88, 0x7b, 1280, 960},/* 45 1280x960x75Hz */
- {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85,
- VCLK148_5, 0x0A, 0x88, 0x7b, 1280, 960},/* 46 1280x960x85Hz */
- {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120,
- VCLK217_325, 0x3A, 0x88, 0x7b, 1280, 960},/* 47 1280x960x120Hz */
- {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054,
- 0x30, 0x47, 0x37, 1024, 768},/* 48 1024x768x160Hz */
-};
-
-static const unsigned char XGI330_ScreenOffset[] = {
- 0x14, 0x19, 0x20, 0x28, 0x32, 0x40,
- 0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
- 0x57, 0x48
-};
-
-static const struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = {
- { 320, 200, 8, 8},
- { 320, 240, 8, 8},
- { 320, 400, 8, 8},
- { 400, 300, 8, 8},
- { 512, 384, 8, 8},
- { 640, 400, 8, 16},
- { 640, 480, 8, 16},
- { 800, 600, 8, 16},
- {1024, 768, 8, 16},
- {1280, 1024, 8, 16},
- {1600, 1200, 8, 16},
- {1920, 1440, 8, 16},
- {2048, 1536, 8, 16},
- { 720, 480, 8, 16},
- { 720, 576, 8, 16},
- {1280, 960, 8, 16},
- { 800, 480, 8, 16},
- {1024, 576, 8, 16},
- {1280, 720, 8, 16},
- { 856, 480, 8, 16},
- {1280, 768, 8, 16},
- {1400, 1050, 8, 16},
- {1152, 864, 8, 16}
-};
-
-const struct SiS_VCLKData XGI_VCLKData[] = {
- /* SR2B,SR2C,SR2D */
- {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */
- {0x4E, 0xE4, 28}, /* 01 (28.322MHz) */
- {0x57, 0xE4, 31}, /* 02 (31.500MHz) */
- {0xC3, 0xC8, 36}, /* 03 (36.000MHz) */
- {0x42, 0xE2, 40}, /* 04 (40.000MHz) */
- {0xFE, 0xCD, 43}, /* 05 (43.163MHz) */
- {0x5D, 0xC4, 44}, /* 06 (44.900MHz) */
- {0x52, 0xE2, 49}, /* 07 (49.500MHz) */
- {0x53, 0xE2, 50}, /* 08 (50.000MHz) */
- {0x74, 0x67, 52}, /* 09 (52.406MHz) */
- {0x6D, 0x66, 56}, /* 0A (56.250MHz) */
- {0x6C, 0xC3, 65}, /* 0B (65.000MHz) */
- {0x46, 0x44, 67}, /* 0C (67.765MHz) */
- {0xB1, 0x46, 68}, /* 0D (68.179MHz) */
- {0xD3, 0x4A, 72}, /* 0E (72.852MHz) */
- {0x29, 0x61, 75}, /* 0F (75.000MHz) */
- {0x6E, 0x46, 76}, /* 10 (75.800MHz) */
- {0x2B, 0x61, 78}, /* 11 (78.750MHz) */
- {0x31, 0x42, 79}, /* 12 (79.411MHz) */
- {0xAB, 0x44, 83}, /* 13 (83.950MHz) */
- {0x46, 0x25, 84}, /* 14 (84.800MHz) */
- {0x78, 0x29, 86}, /* 15 (86.600MHz) */
- {0x62, 0x44, 94}, /* 16 (94.500MHz) */
- {0x2B, 0x41, 104}, /* 17 (104.998MHz) */
- {0x3A, 0x23, 105}, /* 18 (105.882MHz) */
- {0x70, 0x44, 108}, /* 19 (107.862MHz) */
- {0x3C, 0x23, 109}, /* 1A (109.175MHz) */
- {0x5E, 0x43, 113}, /* 1B (113.309MHz) */
- {0xBC, 0x44, 116}, /* 1C (116.406MHz) */
- {0xE0, 0x46, 132}, /* 1D (132.258MHz) */
- {0x54, 0x42, 135}, /* 1E (135.500MHz) */
- {0x9C, 0x22, 139}, /* 1F (139.275MHz) */
- {0x41, 0x22, 157}, /* 20 (157.500MHz) */
- {0x70, 0x24, 162}, /* 21 (161.793MHz) */
- {0x30, 0x21, 175}, /* 22 (175.000MHz) */
- {0x4E, 0x22, 189}, /* 23 (188.520MHz) */
- {0xDE, 0x26, 194}, /* 24 (194.400MHz) */
- {0x62, 0x06, 202}, /* 25 (202.500MHz) */
- {0x3F, 0x03, 229}, /* 26 (229.500MHz) */
- {0xB8, 0x06, 234}, /* 27 (233.178MHz) */
- {0x34, 0x02, 253}, /* 28 (252.699MHz) */
- {0x58, 0x04, 255}, /* 29 (254.817MHz) */
- {0x24, 0x01, 265}, /* 2A (265.728MHz) */
- {0x9B, 0x02, 267}, /* 2B (266.952MHz) */
- {0x70, 0x05, 270}, /* 2C (269.65567MHz) */
- {0x25, 0x01, 272}, /* 2D (272.04199MHz) */
- {0x9C, 0x02, 277}, /* 2E (277.015MHz) */
- {0x27, 0x01, 286}, /* 2F (286.359985MHz) */
- {0xB3, 0x04, 291}, /* 30 (291.13266MHz) */
- {0xBC, 0x05, 292}, /* 31 (291.766MHz) */
- {0xF6, 0x0A, 310}, /* 32 (309.789459MHz) */
- {0x95, 0x01, 315}, /* 33 (315.195MHz) */
- {0xF0, 0x09, 324}, /* 34 (323.586792MHz) */
- {0xFE, 0x0A, 331}, /* 35 (330.615631MHz) */
- {0xF3, 0x09, 332}, /* 36 (332.177612MHz) */
- {0x5E, 0x03, 340}, /* 37 (340.477MHz) */
- {0xE8, 0x07, 376}, /* 38 (375.847504MHz) */
- {0xDE, 0x06, 389}, /* 39 (388.631439MHz) */
- {0x52, 0x2A, 54}, /* 3A (54.000MHz) */
- {0x52, 0x6A, 27}, /* 3B (27.000MHz) */
- {0x62, 0x24, 70}, /* 3C (70.874991MHz) */
- {0x62, 0x64, 70}, /* 3D (70.1048912MHz) */
- {0xA8, 0x4C, 30}, /* 3E (30.1048912MHz) */
- {0x20, 0x26, 33}, /* 3F (33.7499957MHz) */
- {0x31, 0xc2, 39}, /* 40 (39.77MHz) */
- {0x11, 0x21, 30}, /* 41 (30MHz) }// NTSC 1024X768 */
- {0x2E, 0x48, 25}, /* 42 (25.175MHz) }// ScaleLCD */
- {0x24, 0x46, 25}, /* 43 (25.175MHz) */
- {0x26, 0x64, 28}, /* 44 (28.322MHz) */
- {0x37, 0x64, 40}, /* 45 (40.000MHz) */
- {0xA1, 0x42, 108}, /* 46 (95.000MHz) }// QVGA */
- {0x37, 0x61, 100}, /* 47 (100.00MHz) */
- {0x78, 0x27, 108}, /* 48 (108.200MHz) */
- {0xBF, 0xC8, 35}, /* 49 (35.2MHz) */
- {0x66, 0x43, 123}, /* 4A (122.61Mhz) */
- {0x2C, 0x61, 80}, /* 4B (80.350Mhz) */
- {0x3B, 0x61, 108}, /* 4C (107.385Mhz) */
- {0x69, 0x61, 191}, /* 4D (190.96MHz ) */
- {0x4F, 0x22, 192}, /* 4E (192.069MHz) */
- {0x28, 0x26, 322}, /* 4F (322.273MHz) */
- {0x5C, 0x6B, 27}, /* 50 (27.74HMz) */
- {0x57, 0x24, 126}, /* 51 (125.999MHz) */
- {0x5C, 0x42, 148}, /* 52 (148.5MHz) */
- {0x42, 0x61, 120}, /* 53 (120.839MHz) */
- {0x62, 0x61, 178}, /* 54 (178.992MHz) */
- {0x59, 0x22, 217}, /* 55 (217.325MHz) */
- {0x29, 0x01, 300}, /* 56 (299.505Mhz) */
- {0x52, 0x63, 74}, /* 57 (74.25MHz) */
- {0xFF, 0x00, 0} /* End mark */
-};
-
-static const struct SiS_VBVCLKData XGI_VBVCLKData[] = {
- {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */
- {0x4E, 0xE4, 28}, /* 01 (28.322MHz) */
- {0x57, 0xE4, 31}, /* 02 (31.500MHz) */
- {0xC3, 0xC8, 36}, /* 03 (36.000MHz) */
- {0x42, 0x47, 40}, /* 04 (40.000MHz) */
- {0xFE, 0xCD, 43}, /* 05 (43.163MHz) */
- {0x5D, 0xC4, 44}, /* 06 (44.900MHz) */
- {0x52, 0x47, 49}, /* 07 (49.500MHz) */
- {0x53, 0x47, 50}, /* 08 (50.000MHz) */
- {0x74, 0x67, 52}, /* 09 (52.406MHz) */
- {0x6D, 0x66, 56}, /* 0A (56.250MHz) */
- {0x35, 0x62, 65}, /* 0B (65.000MHz) */
- {0x46, 0x44, 67}, /* 0C (67.765MHz) */
- {0xB1, 0x46, 68}, /* 0D (68.179MHz) */
- {0xD3, 0x4A, 72}, /* 0E (72.852MHz) */
- {0x29, 0x61, 75}, /* 0F (75.000MHz) */
- {0x6D, 0x46, 75}, /* 10 (75.800MHz) */
- {0x41, 0x43, 78}, /* 11 (78.750MHz) */
- {0x31, 0x42, 79}, /* 12 (79.411MHz) */
- {0xAB, 0x44, 83}, /* 13 (83.950MHz) */
- {0x46, 0x25, 84}, /* 14 (84.800MHz) */
- {0x78, 0x29, 86}, /* 15 (86.600MHz) */
- {0x62, 0x44, 94}, /* 16 (94.500MHz) */
- {0x2B, 0x22, 104}, /* 17 (104.998MHz) */
- {0x49, 0x24, 105}, /* 18 (105.882MHz) */
- {0xF8, 0x2F, 108}, /* 19 (108.279MHz) */
- {0x3C, 0x23, 109}, /* 1A (109.175MHz) */
- {0x5E, 0x43, 113}, /* 1B (113.309MHz) */
- {0xBC, 0x44, 116}, /* 1C (116.406MHz) */
- {0xE0, 0x46, 132}, /* 1D (132.258MHz) */
- {0xD4, 0x28, 135}, /* 1E (135.220MHz) */
- {0xEA, 0x2A, 139}, /* 1F (139.275MHz) */
- {0x41, 0x22, 157}, /* 20 (157.500MHz) */
- {0x70, 0x24, 162}, /* 21 (161.793MHz) */
- {0x30, 0x21, 175}, /* 22 (175.000MHz) */
- {0x4E, 0x22, 189}, /* 23 (188.520MHz) */
- {0xDE, 0x26, 194}, /* 24 (194.400MHz) */
- {0x70, 0x07, 202}, /* 25 (202.500MHz) */
- {0x3F, 0x03, 229}, /* 26 (229.500MHz) */
- {0xB8, 0x06, 234}, /* 27 (233.178MHz) */
- {0x34, 0x02, 253}, /* 28 (252.699997 MHz) */
- {0x58, 0x04, 255}, /* 29 (254.817MHz) */
- {0x24, 0x01, 265}, /* 2A (265.728MHz) */
- {0x9B, 0x02, 267}, /* 2B (266.952MHz) */
- {0x70, 0x05, 270}, /* 2C (269.65567 MHz) */
- {0x25, 0x01, 272}, /* 2D (272.041992 MHz) */
- {0x9C, 0x02, 277}, /* 2E (277.015MHz) */
- {0x27, 0x01, 286}, /* 2F (286.359985 MHz) */
- {0x3C, 0x02, 291}, /* 30 (291.132660 MHz) */
- {0xEF, 0x0A, 292}, /* 31 (291.766MHz) */
- {0xF6, 0x0A, 310}, /* 32 (309.789459 MHz) */
- {0x95, 0x01, 315}, /* 33 (315.195MHz) */
- {0xF0, 0x09, 324}, /* 34 (323.586792 MHz) */
- {0xFE, 0x0A, 331}, /* 35 (330.615631 MHz) */
- {0xF3, 0x09, 332}, /* 36 (332.177612 MHz) */
- {0xEA, 0x08, 340}, /* 37 (340.477MHz) */
- {0xE8, 0x07, 376}, /* 38 (375.847504 MHz) */
- {0xDE, 0x06, 389}, /* 39 (388.631439 MHz) */
- {0x52, 0x2A, 54}, /* 3A (54.000MHz) */
- {0x52, 0x6A, 27}, /* 3B (27.000MHz) */
- {0x62, 0x24, 70}, /* 3C (70.874991MHz) */
- {0x62, 0x64, 70}, /* 3D (70.1048912MHz) */
- {0xA8, 0x4C, 30}, /* 3E (30.1048912MHz) */
- {0x20, 0x26, 33}, /* 3F (33.7499957MHz) */
- {0x31, 0xc2, 39}, /* 40 (39.77MHz) */
- {0x11, 0x21, 30}, /* 41 (30MHz) }// NTSC 1024X768 */
- {0x2E, 0x48, 25}, /* 42 (25.175MHz) }// ScaleLCD */
- {0x24, 0x46, 25}, /* 43 (25.175MHz) */
- {0x26, 0x64, 28}, /* 44 (28.322MHz) */
- {0x37, 0x64, 40}, /* 45 (40.000MHz) */
- {0xA1, 0x42, 108}, /* 46 (95.000MHz) }// QVGA */
- {0x37, 0x61, 100}, /* 47 (100.00MHz) */
- {0x78, 0x27, 108}, /* 48 (108.200MHz) */
- {0xBF, 0xC8, 35 }, /* 49 (35.2MHz) */
- {0x66, 0x43, 123}, /* 4A (122.61Mhz) */
- {0x2C, 0x61, 80 }, /* 4B (80.350Mhz) */
- {0x3B, 0x61, 108}, /* 4C (107.385Mhz) */
- {0x69, 0x61, 191}, /* 4D (190.96MHz ) */
- {0x4F, 0x22, 192}, /* 4E (192.069MHz) */
- {0x28, 0x26, 322}, /* 4F (322.273MHz) */
- {0x5C, 0x6B, 27}, /* 50 (27.74HMz) */
- {0x57, 0x24, 126}, /* 51 (125.999MHz) */
- {0x5C, 0x42, 148}, /* 52 (148.5MHz) */
- {0x42, 0x61, 120}, /* 53 (120.839MHz) */
- {0x62, 0x61, 178}, /* 54 (178.992MHz) */
- {0x59, 0x22, 217}, /* 55 (217.325MHz) */
- {0x29, 0x01, 300}, /* 56 (299.505Mhz) */
- {0x52, 0x63, 74}, /* 57 (74.25MHz) */
- {0xFF, 0x00, 0} /* End mark */
-};
-
-#define XGI301TVDelay 0x22
-#define XGI301LCDDelay 0x12
-
-static const unsigned char TVAntiFlickList[] = {/* NTSCAntiFlicker */
- 0x04, /* ; 0 Adaptive */
- 0x00, /* ; 1 new anti-flicker ? */
-
- 0x04, /* ; 0 Adaptive */
- 0x08, /* ; 1 new anti-flicker ? */
-
- 0x04, /* ; 0 ? */
- 0x00 /* ; 1 new anti-flicker ? */
-};
-
-static const unsigned char TVEdgeList[] = {
- 0x00, /* ; 0 NTSC No Edge enhance */
- 0x04, /* ; 1 NTSC Adaptive Edge enhance */
- 0x00, /* ; 0 PAL No Edge enhance */
- 0x04, /* ; 1 PAL Adaptive Edge enhance */
- 0x00, /* ; 0 HiTV */
- 0x00 /* ; 1 HiTV */
-};
-
-static const unsigned long TVPhaseList[] = {
- 0x08BAED21, /* ; 0 NTSC phase */
- 0x00E3052A, /* ; 1 PAL phase */
- 0x9B2EE421, /* ; 2 PAL-M phase */
- 0xBA3EF421, /* ; 3 PAL-N phase */
- 0xA7A28B1E, /* ; 4 NTSC 1024x768 */
- 0xE00A831E, /* ; 5 PAL-M 1024x768 */
- 0x00000000, /* ; 6 reserved */
- 0x00000000, /* ; 7 reserved */
- 0xD67BF021, /* ; 8 NTSC phase */
- 0xE986092A, /* ; 9 PAL phase */
- 0xA4EFE621, /* ; A PAL-M phase */
- 0x4694F621, /* ; B PAL-N phase */
- 0x8BDE711C, /* ; C NTSC 1024x768 */
- 0xE00A831E /* ; D PAL-M 1024x768 */
-};
-
-static const unsigned char NTSCYFilter1[] = {
- 0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
- 0xEB, 0x04, 0x25, 0x18, /* 2 : 640x text mode */
- 0xF1, 0x04, 0x1F, 0x18, /* 3 : 720x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 4 : 320x gra. mode */
- 0xEB, 0x04, 0x25, 0x18, /* 5 : 640x gra. mode */
- 0xEB, 0x15, 0x25, 0xF6 /* 6 : 800x gra. mode */
-};
-
-static const unsigned char PALYFilter1[] = {
- 0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
- 0xF1, 0xF7, 0x1F, 0x32, /* 2 : 640x text mode */
- 0xF3, 0x00, 0x1D, 0x20, /* 3 : 720x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 4 : 320x gra. mode */
- 0xF1, 0xF7, 0x1F, 0x32, /* 5 : 640x gra. mode */
- 0xFC, 0xFB, 0x14, 0x2A /* 6 : 800x gra. mode */
-};
-
-static const unsigned char xgifb_palmn_yfilter1[] = {
- 0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
- 0xEB, 0x04, 0x10, 0x18, /* 2 : 640x text mode */
- 0xF7, 0x06, 0x19, 0x14, /* 3 : 720x text mode */
- 0x00, 0xF4, 0x10, 0x38, /* 4 : 320x gra. mode */
- 0xEB, 0x04, 0x25, 0x18, /* 5 : 640x gra. mode */
- 0xEB, 0x15, 0x25, 0xF6, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFF, 0xFF /* End of Table */
-};
-
-static const unsigned char xgifb_yfilter2[] = {
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
- 0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 3 : 720x text mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 4 : 320x gra. mode */
- 0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 5 : 640x gra. mode */
- 0x01, 0x01, 0xFC, 0xF8, 0x08, 0x26, 0x38, /* 6 : 800x gra. mode */
- 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28 /* 7 : 1024xgra. mode */
-};
-
-static const unsigned char XGI_NTSC1024AdjTime[] = {
- 0xa7, 0x07, 0xf2, 0x6e, 0x17, 0x8b, 0x73, 0x53,
- 0x13, 0x40, 0x34, 0xF4, 0x63, 0xBB, 0xCC, 0x7A,
- 0x58, 0xe4, 0x73, 0xd0, 0x13
-};
-
-static const struct XGI301C_Tap4TimingStruct xgifb_tap4_timing[] = {
- {0, {
- 0x00, 0x20, 0x00, 0x00, 0x7F, 0x20, 0x02, 0x7F, /* ; C0-C7 */
- 0x7D, 0x20, 0x04, 0x7F, 0x7D, 0x1F, 0x06, 0x7E, /* ; C8-CF */
- 0x7C, 0x1D, 0x09, 0x7E, 0x7C, 0x1B, 0x0B, 0x7E, /* ; D0-D7 */
- 0x7C, 0x19, 0x0E, 0x7D, 0x7C, 0x17, 0x11, 0x7C, /* ; D8-DF */
- 0x7C, 0x14, 0x14, 0x7C, 0x7C, 0x11, 0x17, 0x7C, /* ; E0-E7 */
- 0x7D, 0x0E, 0x19, 0x7C, 0x7E, 0x0B, 0x1B, 0x7C, /* ; EA-EF */
- 0x7E, 0x09, 0x1D, 0x7C, 0x7F, 0x06, 0x1F, 0x7C, /* ; F0-F7 */
- 0x7F, 0x04, 0x20, 0x7D, 0x00, 0x02, 0x20, 0x7E /* ; F8-FF */
- }
- }
-};
-
-static const struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
- {600, {
- 0x05, 0x19, 0x05, 0x7D, 0x03, 0x19, 0x06, 0x7E, /* ; C0-C7 */
- 0x02, 0x19, 0x08, 0x7D, 0x01, 0x18, 0x0A, 0x7D, /* ; C8-CF */
- 0x00, 0x18, 0x0C, 0x7C, 0x7F, 0x17, 0x0E, 0x7C, /* ; D0-D7 */
- 0x7E, 0x16, 0x0F, 0x7D, 0x7E, 0x14, 0x11, 0x7D, /* ; D8-DF */
- 0x7D, 0x13, 0x13, 0x7D, 0x7D, 0x11, 0x14, 0x7E, /* ; E0-E7 */
- 0x7D, 0x0F, 0x16, 0x7E, 0x7D, 0x0E, 0x17, 0x7E, /* ; EA-EF */
- 0x7D, 0x0C, 0x18, 0x7F, 0x7D, 0x0A, 0x18, 0x01, /* ; F0-F7 */
- 0x7D, 0x08, 0x19, 0x02, 0x7D, 0x06, 0x19, 0x04 /* ; F8-FF */
- }
- },
- {768, {
- 0x08, 0x12, 0x08, 0x7E, 0x07, 0x12, 0x09, 0x7E, /* ; C0-C7 */
- 0x06, 0x12, 0x0A, 0x7E, 0x05, 0x11, 0x0B, 0x7F, /* ; C8-CF */
- 0x04, 0x11, 0x0C, 0x7F, 0x03, 0x11, 0x0C, 0x00, /* ; D0-D7 */
- 0x03, 0x10, 0x0D, 0x00, 0x02, 0x0F, 0x0E, 0x01, /* ; D8-DF */
- 0x01, 0x0F, 0x0F, 0x01, 0x01, 0x0E, 0x0F, 0x02, /* ; E0-E7 */
- 0x00, 0x0D, 0x10, 0x03, 0x7F, 0x0C, 0x11, 0x04, /* ; EA-EF */
- 0x7F, 0x0C, 0x11, 0x04, 0x7F, 0x0B, 0x11, 0x05, /* ; F0-F7 */
- 0x7E, 0x0A, 0x12, 0x06, 0x7E, 0x09, 0x12, 0x07 /* ; F8-FF */
- }
- },
- {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 */
- }
- }
-};
-
-static const struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
- {480, {
- 0x04, 0x1A, 0x04, 0x7E, 0x03, 0x1A, 0x06, 0x7D, /* ; C0-C7 */
- 0x01, 0x1A, 0x08, 0x7D, 0x00, 0x19, 0x0A, 0x7D, /* ; C8-CF */
- 0x7F, 0x19, 0x0C, 0x7C, 0x7E, 0x18, 0x0E, 0x7C, /* ; D0-D7 */
- 0x7E, 0x17, 0x10, 0x7B, 0x7D, 0x15, 0x12, 0x7C, /* ; D8-DF */
- 0x7D, 0x13, 0x13, 0x7D, 0x7C, 0x12, 0x15, 0x7D, /* ; E0-E7 */
- 0x7C, 0x10, 0x17, 0x7D, 0x7C, 0x0E, 0x18, 0x7E, /* ; EA-EF */
- 0x7D, 0x0C, 0x19, 0x7E, 0x7D, 0x0A, 0x19, 0x00, /* ; F0-F7 */
- 0x7D, 0x08, 0x1A, 0x01, 0x7E, 0x06, 0x1A, 0x02 /* ; F8-FF */
- }
- },
- {600, {
- 0x07, 0x14, 0x07, 0x7E, 0x06, 0x14, 0x09, 0x7D, /* ; C0-C7 */
- 0x05, 0x14, 0x0A, 0x7D, 0x04, 0x13, 0x0B, 0x7E, /* ; C8-CF */
- 0x03, 0x13, 0x0C, 0x7E, 0x02, 0x12, 0x0D, 0x7F, /* ; D0-D7 */
- 0x01, 0x12, 0x0E, 0x7F, 0x01, 0x11, 0x0F, 0x7F, /* ; D8-DF */
- 0x01, 0x10, 0x10, 0x00, 0x7F, 0x0F, 0x11, 0x01, /* ; E0-E7 */
- 0x7F, 0x0E, 0x12, 0x01, 0x7E, 0x0D, 0x12, 0x03, /* ; EA-EF */
- 0x7E, 0x0C, 0x13, 0x03, 0x7E, 0x0B, 0x13, 0x04, /* ; F0-F7 */
- 0x7E, 0x0A, 0x14, 0x04, 0x7D, 0x09, 0x14, 0x06 /* ; F8-FF */
- }
- },
- {0xFFFF, {
- 0x09, 0x0F, 0x09, 0x7F, 0x08, 0x0F, 0x09, 0x00, /* ; C0-C7 */
- 0x07, 0x0F, 0x0A, 0x00, 0x06, 0x0F, 0x0A, 0x01, /* ; C8-CF */
- 0x06, 0x0E, 0x0B, 0x01, 0x05, 0x0E, 0x0B, 0x02, /* ; D0-D7 */
- 0x04, 0x0E, 0x0C, 0x02, 0x04, 0x0D, 0x0C, 0x03, /* ; D8-DF */
- 0x03, 0x0D, 0x0D, 0x03, 0x02, 0x0C, 0x0D, 0x05, /* ; E0-E7 */
- 0x02, 0x0C, 0x0E, 0x04, 0x01, 0x0B, 0x0E, 0x06, /* ; EA-EF */
- 0x01, 0x0B, 0x0E, 0x06, 0x00, 0x0A, 0x0F, 0x07, /* ; F0-F7 */
- 0x00, 0x0A, 0x0F, 0x07, 0x00, 0x09, 0x0F, 0x08 /* ; F8-FF */
- }
- }
-};
-
-static const struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = {
- {0xFFFF, {
- 0x05, 0x19, 0x05, 0x7D, 0x03, 0x19, 0x06, 0x7E, /* ; C0-C7 */
- 0x02, 0x19, 0x08, 0x7D, 0x01, 0x18, 0x0A, 0x7D, /* ; C8-CF */
- 0x00, 0x18, 0x0C, 0x7C, 0x7F, 0x17, 0x0E, 0x7C, /* ; D0-D7 */
- 0x7E, 0x16, 0x0F, 0x7D, 0x7E, 0x14, 0x11, 0x7D, /* ; D8-DF */
- 0x7D, 0x13, 0x13, 0x7D, 0x7D, 0x11, 0x14, 0x7E, /* ; E0-E7 */
- 0x7D, 0x0F, 0x16, 0x7E, 0x7D, 0x0E, 0x17, 0x7E, /* ; EA-EF */
- 0x7D, 0x0C, 0x18, 0x7F, 0x7D, 0x0A, 0x18, 0x01, /* ; F0-F7 */
- 0x7D, 0x08, 0x19, 0x02, 0x7D, 0x06, 0x19, 0x04 /* F8-FF */
- }
- }
-};
-#endif
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
deleted file mode 100644
index 0f6d5aac04f6..000000000000
--- a/drivers/staging/xgifb/vb_util.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VBUTIL_
-#define _VBUTIL_
-static inline void xgifb_reg_set(unsigned long port, u8 index, u8 data)
-{
- outb(index, port);
- outb(data, port + 1);
-}
-
-static inline u8 xgifb_reg_get(unsigned long port, u8 index)
-{
- outb(index, port);
- return inb(port + 1);
-}
-
-static inline void xgifb_reg_and_or(unsigned long port, u8 index,
- unsigned int data_and, unsigned int data_or)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index);
- temp = (u8)((temp & data_and) | data_or);
- xgifb_reg_set(port, index, temp);
-}
-
-static inline void xgifb_reg_and(unsigned long port, u8 index,
- unsigned int data_and)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index);
- temp = (u8)(temp & data_and);
- xgifb_reg_set(port, index, temp);
-}
-
-static inline void xgifb_reg_or(unsigned long port, u8 index,
- unsigned int data_or)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index);
- temp |= data_or;
- xgifb_reg_set(port, index, temp);
-}
-#endif
-
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
deleted file mode 100644
index 22919f2368d5..000000000000
--- a/drivers/staging/xgifb/vgatypes.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VGATYPES_
-#define _VGATYPES_
-
-#include <linux/fb.h> /* for struct fb_var_screeninfo for sis.h */
-#include "../../video/fbdev/sis/vgatypes.h"
-#include "../../video/fbdev/sis/sis.h" /* for LCD_TYPE */
-
-enum XGI_VB_CHIP_TYPE {
- VB_CHIP_Legacy = 0,
- VB_CHIP_301,
- VB_CHIP_301B,
- VB_CHIP_301LV,
- VB_CHIP_302,
- VB_CHIP_302B,
- VB_CHIP_302LV,
- VB_CHIP_301C,
- VB_CHIP_302ELV,
- VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
- MAX_VB_CHIP
-};
-
-struct xgi_hw_device_info {
- unsigned long ulExternalChip; /* NO VB or other video bridge*/
- /* if ujVBChipID = VB_CHIP_UNKNOWN, */
-
- void __iomem *pjVideoMemoryAddress;/* base virtual memory address */
- /* of Linear VGA memory */
-
- unsigned long ulVideoMemorySize; /* size, in bytes, of the
- * memory on the board
- */
-
- unsigned char jChipType; /* Used to Identify Graphics Chip */
- /* defined in the data structure type */
- /* "XGI_CHIP_TYPE" */
-
- unsigned char jChipRevision; /* Used to Identify Graphics
- * Chip Revision
- */
-
- unsigned char ujVBChipID; /* the ID of video bridge */
- /* defined in the data structure type */
- /* "XGI_VB_CHIP_TYPE" */
-
- unsigned long ulCRT2LCDType; /* defined in the data structure type */
-};
-
-/* Additional IOCTL for communication xgifb <> X driver */
-/* If changing this, xgifb.h must also be changed (for xgifb) */
-#endif
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 984941e036c8..bd15a564fe24 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -714,7 +714,7 @@ static int __init iscsi_target_init_module(void)
sizeof(struct iscsi_queue_req),
__alignof__(struct iscsi_queue_req), 0, NULL);
if (!lio_qr_cache) {
- pr_err("nable to kmem_cache_create() for"
+ pr_err("Unable to kmem_cache_create() for"
" lio_qr_cache\n");
goto bitmap_out;
}
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 72016d0dfca5..8e7fffbb8802 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -852,6 +852,12 @@ static ssize_t pi_prot_type_store(struct config_item *item,
return count;
}
+/* always zero, but attr needs to remain RW to avoid userspace breakage */
+static ssize_t pi_prot_format_show(struct config_item *item, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "0\n");
+}
+
static ssize_t pi_prot_format_store(struct config_item *item,
const char *page, size_t count)
{
@@ -1132,7 +1138,7 @@ CONFIGFS_ATTR(, emulate_3pc);
CONFIGFS_ATTR(, emulate_pr);
CONFIGFS_ATTR(, pi_prot_type);
CONFIGFS_ATTR_RO(, hw_pi_prot_type);
-CONFIGFS_ATTR_WO(, pi_prot_format);
+CONFIGFS_ATTR(, pi_prot_format);
CONFIGFS_ATTR(, pi_prot_verify);
CONFIGFS_ATTR(, enforce_pr_isids);
CONFIGFS_ATTR(, is_nonrot);
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 1e6d24943565..5831e0eecea1 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -148,7 +148,7 @@ struct tcmu_dev {
size_t ring_size;
struct mutex cmdr_lock;
- struct list_head cmdr_queue;
+ struct list_head qfull_queue;
uint32_t dbi_max;
uint32_t dbi_thresh;
@@ -159,6 +159,7 @@ struct tcmu_dev {
struct timer_list cmd_timer;
unsigned int cmd_time_out;
+ struct list_head inflight_queue;
struct timer_list qfull_timer;
int qfull_time_out;
@@ -179,7 +180,7 @@ struct tcmu_dev {
struct tcmu_cmd {
struct se_cmd *se_cmd;
struct tcmu_dev *tcmu_dev;
- struct list_head cmdr_queue_entry;
+ struct list_head queue_entry;
uint16_t cmd_id;
@@ -192,6 +193,7 @@ struct tcmu_cmd {
unsigned long deadline;
#define TCMU_CMD_BIT_EXPIRED 0
+#define TCMU_CMD_BIT_INFLIGHT 1
unsigned long flags;
};
/*
@@ -586,7 +588,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
if (!tcmu_cmd)
return NULL;
- INIT_LIST_HEAD(&tcmu_cmd->cmdr_queue_entry);
+ INIT_LIST_HEAD(&tcmu_cmd->queue_entry);
tcmu_cmd->se_cmd = se_cmd;
tcmu_cmd->tcmu_dev = udev;
@@ -915,11 +917,13 @@ setup_timer:
return 0;
tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo));
- mod_timer(timer, tcmu_cmd->deadline);
+ if (!timer_pending(timer))
+ mod_timer(timer, tcmu_cmd->deadline);
+
return 0;
}
-static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
+static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
{
struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
unsigned int tmo;
@@ -942,7 +946,7 @@ static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
if (ret)
return ret;
- list_add_tail(&tcmu_cmd->cmdr_queue_entry, &udev->cmdr_queue);
+ list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
pr_debug("adding cmd %u on dev %s to ring space wait queue\n",
tcmu_cmd->cmd_id, udev->name);
return 0;
@@ -999,7 +1003,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt);
command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
- if (!list_empty(&udev->cmdr_queue))
+ if (!list_empty(&udev->qfull_queue))
goto queue;
mb = udev->mb_addr;
@@ -1096,13 +1100,16 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
tcmu_flush_dcache_range(mb, sizeof(*mb));
+ list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue);
+ set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags);
+
/* TODO: only if FLUSH and FUA? */
uio_event_notify(&udev->uio_info);
return 0;
queue:
- if (add_to_cmdr_queue(tcmu_cmd)) {
+ if (add_to_qfull_queue(tcmu_cmd)) {
*scsi_err = TCM_OUT_OF_RESOURCES;
return -1;
}
@@ -1145,6 +1152,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
goto out;
+ list_del_init(&cmd->queue_entry);
+
tcmu_cmd_reset_dbi_cur(cmd);
if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
@@ -1194,9 +1203,29 @@ out:
tcmu_free_cmd(cmd);
}
+static void tcmu_set_next_deadline(struct list_head *queue,
+ struct timer_list *timer)
+{
+ struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
+ unsigned long deadline = 0;
+
+ list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) {
+ if (!time_after(jiffies, tcmu_cmd->deadline)) {
+ deadline = tcmu_cmd->deadline;
+ break;
+ }
+ }
+
+ if (deadline)
+ mod_timer(timer, deadline);
+ else
+ del_timer(timer);
+}
+
static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
{
struct tcmu_mailbox *mb;
+ struct tcmu_cmd *cmd;
int handled = 0;
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
@@ -1210,7 +1239,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned;
- struct tcmu_cmd *cmd;
tcmu_flush_dcache_range(entry, sizeof(*entry));
@@ -1243,7 +1271,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
/* no more pending commands */
del_timer(&udev->cmd_timer);
- if (list_empty(&udev->cmdr_queue)) {
+ if (list_empty(&udev->qfull_queue)) {
/*
* no more pending or waiting commands so try to
* reclaim blocks if needed.
@@ -1252,6 +1280,8 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
tcmu_global_max_blocks)
schedule_delayed_work(&tcmu_unmap_work, 0);
}
+ } else if (udev->cmd_time_out) {
+ tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
}
return handled;
@@ -1271,7 +1301,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
if (!time_after(jiffies, cmd->deadline))
return 0;
- is_running = list_empty(&cmd->cmdr_queue_entry);
+ is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags);
se_cmd = cmd->se_cmd;
if (is_running) {
@@ -1287,9 +1317,9 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
* target_complete_cmd will translate this to LUN COMM FAILURE
*/
scsi_status = SAM_STAT_CHECK_CONDITION;
+ list_del_init(&cmd->queue_entry);
} else {
- list_del_init(&cmd->cmdr_queue_entry);
-
+ list_del_init(&cmd->queue_entry);
idr_remove(&udev->commands, id);
tcmu_free_cmd(cmd);
scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -1372,7 +1402,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
INIT_LIST_HEAD(&udev->node);
INIT_LIST_HEAD(&udev->timedout_entry);
- INIT_LIST_HEAD(&udev->cmdr_queue);
+ INIT_LIST_HEAD(&udev->qfull_queue);
+ INIT_LIST_HEAD(&udev->inflight_queue);
idr_init(&udev->commands);
timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0);
@@ -1383,7 +1414,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
return &udev->se_dev;
}
-static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
+static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
{
struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
LIST_HEAD(cmds);
@@ -1391,15 +1422,15 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
sense_reason_t scsi_ret;
int ret;
- if (list_empty(&udev->cmdr_queue))
+ if (list_empty(&udev->qfull_queue))
return true;
pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail);
- list_splice_init(&udev->cmdr_queue, &cmds);
+ list_splice_init(&udev->qfull_queue, &cmds);
- list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, cmdr_queue_entry) {
- list_del_init(&tcmu_cmd->cmdr_queue_entry);
+ list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) {
+ list_del_init(&tcmu_cmd->queue_entry);
pr_debug("removing cmd %u on dev %s from queue\n",
tcmu_cmd->cmd_id, udev->name);
@@ -1437,14 +1468,13 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
* cmd was requeued, so just put all cmds back in
* the queue
*/
- list_splice_tail(&cmds, &udev->cmdr_queue);
+ list_splice_tail(&cmds, &udev->qfull_queue);
drained = false;
- goto done;
+ break;
}
}
- if (list_empty(&udev->cmdr_queue))
- del_timer(&udev->qfull_timer);
-done:
+
+ tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
return drained;
}
@@ -1454,7 +1484,7 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
mutex_lock(&udev->cmdr_lock);
tcmu_handle_completions(udev);
- run_cmdr_queue(udev, false);
+ run_qfull_queue(udev, false);
mutex_unlock(&udev->cmdr_lock);
return 0;
@@ -1982,7 +2012,7 @@ static void tcmu_block_dev(struct tcmu_dev *udev)
/* complete IO that has executed successfully */
tcmu_handle_completions(udev);
/* fail IO waiting to be queued */
- run_cmdr_queue(udev, true);
+ run_qfull_queue(udev, true);
unlock:
mutex_unlock(&udev->cmdr_lock);
@@ -1997,7 +2027,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
mutex_lock(&udev->cmdr_lock);
idr_for_each_entry(&udev->commands, cmd, i) {
- if (!list_empty(&cmd->cmdr_queue_entry))
+ if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags))
continue;
pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
@@ -2006,6 +2036,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
idr_remove(&udev->commands, i);
if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+ list_del_init(&cmd->queue_entry);
if (err_level == 1) {
/*
* Userspace was not able to start the
@@ -2666,6 +2697,10 @@ static void check_timedout_devices(void)
mutex_lock(&udev->cmdr_lock);
idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
+
+ tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
+ tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
+
mutex_unlock(&udev->cmdr_lock);
spin_lock_bh(&timed_out_udevs_lock);
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index 48d262ae2f04..56263ae3b1d7 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -5,3 +5,4 @@ optee-objs += call.o
optee-objs += rpc.o
optee-objs += supp.o
optee-objs += shm_pool.o
+optee-objs += device.o
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index e5efce3c08e2..0842b6e6af82 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -634,6 +634,10 @@ static struct optee *optee_probe(struct device_node *np)
if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
pr_info("dynamic shared memory is enabled\n");
+ rc = optee_enumerate_devices();
+ if (rc)
+ goto err;
+
pr_info("initialized driver\n");
return optee;
err:
@@ -699,8 +703,10 @@ static int __init optee_driver_init(void)
return -ENODEV;
np = of_find_matching_node(fw_np, optee_match);
- if (!np || !of_device_is_available(np))
+ if (!np || !of_device_is_available(np)) {
+ of_node_put(np);
return -ENODEV;
+ }
optee = optee_probe(np);
of_node_put(np);
diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c
new file mode 100644
index 000000000000..e3a148521ec1
--- /dev/null
+++ b/drivers/tee/optee/device.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Linaro Ltd.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+#include "optee_private.h"
+
+/*
+ * Get device UUIDs
+ *
+ * [out] memref[0] Array of device UUIDs
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required
+ */
+#define PTA_CMD_GET_DEVICES 0x0
+
+static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+ if (ver->impl_id == TEE_IMPL_ID_OPTEE)
+ return 1;
+ else
+ return 0;
+}
+
+static int get_devices(struct tee_context *ctx, u32 session,
+ struct tee_shm *device_shm, u32 *shm_size)
+{
+ int ret = 0;
+ struct tee_ioctl_invoke_arg inv_arg;
+ struct tee_param param[4];
+
+ memset(&inv_arg, 0, sizeof(inv_arg));
+ memset(&param, 0, sizeof(param));
+
+ /* Invoke PTA_CMD_GET_DEVICES function */
+ inv_arg.func = PTA_CMD_GET_DEVICES;
+ inv_arg.session = session;
+ inv_arg.num_params = 4;
+
+ /* Fill invoke cmd params */
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[0].u.memref.shm = device_shm;
+ param[0].u.memref.size = *shm_size;
+ param[0].u.memref.shm_offs = 0;
+
+ ret = tee_client_invoke_func(ctx, &inv_arg, param);
+ if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
+ (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
+ pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
+ inv_arg.ret);
+ return -EINVAL;
+ }
+
+ *shm_size = param[0].u.memref.size;
+
+ return 0;
+}
+
+static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
+{
+ struct tee_client_device *optee_device = NULL;
+ int rc;
+
+ optee_device = kzalloc(sizeof(*optee_device), GFP_KERNEL);
+ if (!optee_device)
+ return -ENOMEM;
+
+ optee_device->dev.bus = &tee_bus_type;
+ dev_set_name(&optee_device->dev, "optee-clnt%u", device_id);
+ uuid_copy(&optee_device->id.uuid, device_uuid);
+
+ rc = device_register(&optee_device->dev);
+ if (rc) {
+ pr_err("device registration failed, err: %d\n", rc);
+ kfree(optee_device);
+ }
+
+ return rc;
+}
+
+int optee_enumerate_devices(void)
+{
+ const uuid_t pta_uuid =
+ UUID_INIT(0x7011a688, 0xddde, 0x4053,
+ 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
+ struct tee_ioctl_open_session_arg sess_arg;
+ struct tee_shm *device_shm = NULL;
+ const uuid_t *device_uuid = NULL;
+ struct tee_context *ctx = NULL;
+ u32 shm_size = 0, idx, num_devices = 0;
+ int rc;
+
+ memset(&sess_arg, 0, sizeof(sess_arg));
+
+ /* Open context with OP-TEE driver */
+ ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
+ if (IS_ERR(ctx))
+ return -ENODEV;
+
+ /* Open session with device enumeration pseudo TA */
+ memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+ sess_arg.num_params = 0;
+
+ rc = tee_client_open_session(ctx, &sess_arg, NULL);
+ if ((rc < 0) || (sess_arg.ret != TEEC_SUCCESS)) {
+ /* Device enumeration pseudo TA not found */
+ rc = 0;
+ goto out_ctx;
+ }
+
+ rc = get_devices(ctx, sess_arg.session, NULL, &shm_size);
+ if (rc < 0 || !shm_size)
+ goto out_sess;
+
+ device_shm = tee_shm_alloc(ctx, shm_size,
+ TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ if (IS_ERR(device_shm)) {
+ pr_err("tee_shm_alloc failed\n");
+ rc = PTR_ERR(device_shm);
+ goto out_sess;
+ }
+
+ rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size);
+ if (rc < 0)
+ goto out_shm;
+
+ device_uuid = tee_shm_get_va(device_shm, 0);
+ if (IS_ERR(device_uuid)) {
+ pr_err("tee_shm_get_va failed\n");
+ rc = PTR_ERR(device_uuid);
+ goto out_shm;
+ }
+
+ num_devices = shm_size / sizeof(uuid_t);
+
+ for (idx = 0; idx < num_devices; idx++) {
+ rc = optee_register_device(&device_uuid[idx], idx);
+ if (rc)
+ goto out_shm;
+ }
+
+out_shm:
+ tee_shm_free(device_shm);
+out_sess:
+ tee_client_close_session(ctx, sess_arg.session);
+out_ctx:
+ tee_client_close_context(ctx);
+
+ return rc;
+}
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
index 30504901be80..795bc19ae17a 100644
--- a/drivers/tee/optee/optee_msg.h
+++ b/drivers/tee/optee/optee_msg.h
@@ -1,28 +1,6 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
/*
- * Copyright (c) 2015-2016, Linaro Limited
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 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 HOLDER 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.
+ * Copyright (c) 2015-2019, Linaro Limited
*/
#ifndef _OPTEE_MSG_H
#define _OPTEE_MSG_H
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 35e79386c556..a5e84afd5013 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -28,6 +28,7 @@
#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
+#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
#define TEEC_ORIGIN_COMMS 0x00000002
@@ -181,6 +182,8 @@ void optee_free_pages_list(void *array, size_t num_entries);
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
size_t page_offset);
+int optee_enumerate_devices(void);
+
/*
* Small helpers
*/
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
index bbf0cf028c16..c72122d9c997 100644
--- a/drivers/tee/optee/optee_smc.h
+++ b/drivers/tee/optee/optee_smc.h
@@ -1,28 +1,6 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
/*
- * Copyright (c) 2015-2016, Linaro Limited
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 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 HOLDER 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.
+ * Copyright (c) 2015-2019, Linaro Limited
*/
#ifndef OPTEE_SMC_H
#define OPTEE_SMC_H
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
index 43626e15703a..92f56b8645e3 100644
--- a/drivers/tee/optee/supp.c
+++ b/drivers/tee/optee/supp.c
@@ -88,10 +88,18 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
{
struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_supp *supp = &optee->supp;
- struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL);
+ struct optee_supp_req *req;
bool interruptable;
u32 ret;
+ /*
+ * Return in case there is no supplicant available and
+ * non-blocking request.
+ */
+ if (!supp->ctx && ctx->supp_nowait)
+ return TEEC_ERROR_COMMUNICATION;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return TEEC_ERROR_OUT_OF_MEMORY;
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 7b2bb4c50058..17c64fccbb10 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -15,7 +15,6 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/cdev.h>
-#include <linux/device.h>
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/module.h>
@@ -106,6 +105,11 @@ static int tee_open(struct inode *inode, struct file *filp)
if (IS_ERR(ctx))
return PTR_ERR(ctx);
+ /*
+ * Default user-space behaviour is to wait for tee-supplicant
+ * if not present for any requests in this context.
+ */
+ ctx->supp_nowait = false;
filp->private_data = ctx;
return 0;
}
@@ -982,6 +986,16 @@ tee_client_open_context(struct tee_context *start,
} while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM);
put_device(put_dev);
+ /*
+ * Default behaviour for in kernel client is to not wait for
+ * tee-supplicant if not present for any requests in this context.
+ * Also this flag could be configured again before call to
+ * tee_client_open_session() if any in kernel client requires
+ * different behaviour.
+ */
+ if (!IS_ERR(ctx))
+ ctx->supp_nowait = true;
+
return ctx;
}
EXPORT_SYMBOL_GPL(tee_client_open_context);
@@ -1027,6 +1041,48 @@ int tee_client_invoke_func(struct tee_context *ctx,
}
EXPORT_SYMBOL_GPL(tee_client_invoke_func);
+int tee_client_cancel_req(struct tee_context *ctx,
+ struct tee_ioctl_cancel_arg *arg)
+{
+ if (!ctx->teedev->desc->ops->cancel_req)
+ return -EINVAL;
+ return ctx->teedev->desc->ops->cancel_req(ctx, arg->cancel_id,
+ arg->session);
+}
+
+static int tee_client_device_match(struct device *dev,
+ struct device_driver *drv)
+{
+ const struct tee_client_device_id *id_table;
+ struct tee_client_device *tee_device;
+
+ id_table = to_tee_client_driver(drv)->id_table;
+ tee_device = to_tee_client_device(dev);
+
+ while (!uuid_is_null(&id_table->uuid)) {
+ if (uuid_equal(&tee_device->id.uuid, &id_table->uuid))
+ return 1;
+ id_table++;
+ }
+
+ return 0;
+}
+
+static int tee_client_device_uevent(struct device *dev,
+ struct kobj_uevent_env *env)
+{
+ uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid;
+
+ return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id);
+}
+
+struct bus_type tee_bus_type = {
+ .name = "tee",
+ .match = tee_client_device_match,
+ .uevent = tee_client_device_uevent,
+};
+EXPORT_SYMBOL_GPL(tee_bus_type);
+
static int __init tee_init(void)
{
int rc;
@@ -1040,18 +1096,32 @@ static int __init tee_init(void)
rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
if (rc) {
pr_err("failed to allocate char dev region\n");
- class_destroy(tee_class);
- tee_class = NULL;
+ goto out_unreg_class;
+ }
+
+ rc = bus_register(&tee_bus_type);
+ if (rc) {
+ pr_err("failed to register tee bus\n");
+ goto out_unreg_chrdev;
}
+ return 0;
+
+out_unreg_chrdev:
+ unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
+out_unreg_class:
+ class_destroy(tee_class);
+ tee_class = NULL;
+
return rc;
}
static void __exit tee_exit(void)
{
+ bus_unregister(&tee_bus_type);
+ unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
class_destroy(tee_class);
tee_class = NULL;
- unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
}
subsys_initcall(tee_init);
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 30323426902e..58bb7d72dc2b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -152,6 +152,7 @@ config CPU_THERMAL
bool "generic cpu cooling support"
depends on CPU_FREQ
depends on THERMAL_OF
+ depends on THERMAL=y
help
This implements the generic cpu cooling mechanism through frequency
reduction. An ACPI version of this already exists
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index dfd23245f778..6fff16113628 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -774,7 +774,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
cdev = __cpufreq_cooling_register(np, policy, capacitance);
if (IS_ERR(cdev)) {
- pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
+ pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n",
policy->cpu, PTR_ERR(cdev));
cdev = NULL;
}
diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig
index 0582bd12a239..0ca908d12750 100644
--- a/drivers/thermal/intel/int340x_thermal/Kconfig
+++ b/drivers/thermal/intel/int340x_thermal/Kconfig
@@ -4,7 +4,7 @@
config INT340X_THERMAL
tristate "ACPI INT340X thermal drivers"
- depends on X86 && ACPI
+ depends on X86 && ACPI && PCI
select THERMAL_GOV_USER_SPACE
select ACPI_THERMAL_REL
select ACPI_FAN
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index 284cf2c5a8fd..8e1cf4d789be 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -84,7 +84,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
struct pci_dev *pci_dev; \
struct platform_device *pdev; \
struct proc_thermal_device *proc_dev; \
-\
+ \
+ if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
+ dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
+ return 0; \
+ } \
+ \
if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
pdev = to_platform_device(dev); \
proc_dev = platform_get_drvdata(pdev); \
@@ -298,11 +303,6 @@ static int proc_thermal_add(struct device *dev,
*priv = proc_priv;
ret = proc_thermal_read_ppcc(proc_priv);
- if (!ret) {
- ret = sysfs_create_group(&dev->kobj,
- &power_limit_attribute_group);
-
- }
if (ret)
return ret;
@@ -316,8 +316,7 @@ static int proc_thermal_add(struct device *dev,
proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
if (IS_ERR(proc_priv->int340x_zone)) {
- ret = PTR_ERR(proc_priv->int340x_zone);
- goto remove_group;
+ return PTR_ERR(proc_priv->int340x_zone);
} else
ret = 0;
@@ -331,9 +330,6 @@ static int proc_thermal_add(struct device *dev,
remove_zone:
int340x_thermal_zone_remove(proc_priv->int340x_zone);
-remove_group:
- sysfs_remove_group(&proc_priv->dev->kobj,
- &power_limit_attribute_group);
return ret;
}
@@ -364,7 +360,10 @@ static int int3401_add(struct platform_device *pdev)
platform_set_drvdata(pdev, proc_priv);
proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
- return 0;
+ dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
+
+ return sysfs_create_group(&pdev->dev.kobj,
+ &power_limit_attribute_group);
}
static int int3401_remove(struct platform_device *pdev)
@@ -423,7 +422,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev,
proc_priv->soc_dts = intel_soc_dts_iosf_init(
INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
- if (proc_priv->soc_dts && pdev->irq) {
+ if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
ret = pci_enable_msi(pdev);
if (!ret) {
ret = request_threaded_irq(pdev->irq, NULL,
@@ -441,7 +440,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
}
- return 0;
+ dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
+
+ return sysfs_create_group(&pdev->dev.kobj,
+ &power_limit_attribute_group);
}
static void proc_thermal_pci_remove(struct pci_dev *pdev)
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 4bfdb4a1e47d..2df059cc07e2 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -867,14 +867,14 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
ret = of_property_read_u32(np, "polling-delay-passive", &prop);
if (ret < 0) {
- pr_err("missing polling-delay-passive property\n");
+ pr_err("%pOFn: missing polling-delay-passive property\n", np);
goto free_tz;
}
tz->passive_delay = prop;
ret = of_property_read_u32(np, "polling-delay", &prop);
if (ret < 0) {
- pr_err("missing polling-delay property\n");
+ pr_err("%pOFn: missing polling-delay property\n", np);
goto free_tz;
}
tz->polling_delay = prop;
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 0840d27381ea..e0a04bfc873e 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -441,4 +441,28 @@ config VCC
depends on SUN_LDOMS
help
Support for Sun logical domain consoles.
+
+config LDISC_AUTOLOAD
+ bool "Automatically load TTY Line Disciplines"
+ default y
+ help
+ Historically the kernel has always automatically loaded any
+ line discipline that is in a kernel module when a user asks
+ for it to be loaded with the TIOCSETD ioctl, or through other
+ means. This is not always the best thing to do on systems
+ where you know you will not be using some of the more
+ "ancient" line disciplines, so prevent the kernel from doing
+ this unless the request is coming from a process with the
+ CAP_SYS_MODULE permissions.
+
+ Say 'Y' here if you trust your userspace users to do the right
+ thing, or if you have only provided the line disciplines that
+ you know you will be using, or if you wish to continue to use
+ the traditional method of on-demand loading of these modules
+ by any user.
+
+ This functionality can be changed at runtime with the
+ dev.tty.ldisc_autoload sysctl, this configuration option will
+ only set the default value of this functionality.
+
endif # TTY
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index dc43fa96c3de..5ef08905fe05 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -492,7 +492,7 @@ static void xencons_backend_changed(struct xenbus_device *dev,
case XenbusStateClosed:
if (dev->state == XenbusStateClosed)
break;
- /* Missed the backend's CLOSING state -- fallthrough */
+ /* fall through - Missed the backend's CLOSING state. */
case XenbusStateClosing:
xenbus_frontend_closed(dev);
break;
diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c
index b0baa4ce10f9..6bbf35682d53 100644
--- a/drivers/tty/ipwireless/hardware.c
+++ b/drivers/tty/ipwireless/hardware.c
@@ -1516,6 +1516,8 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw)
sizeof(struct ipw_setup_get_version_query_packet),
ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
TL_SETUP_SIGNO_GET_VERSION_QRY);
+ if (!ver_packet)
+ return;
ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
/*
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 6f7da9a9d76f..c4e16b31f9ab 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -143,8 +143,8 @@ struct gsm_dlci {
struct sk_buff *skb; /* Frame being sent */
struct sk_buff_head skb_list; /* Queued frames */
/* Data handling callback */
- void (*data)(struct gsm_dlci *dlci, u8 *data, int len);
- void (*prev_data)(struct gsm_dlci *dlci, u8 *data, int len);
+ void (*data)(struct gsm_dlci *dlci, const u8 *data, int len);
+ void (*prev_data)(struct gsm_dlci *dlci, const u8 *data, int len);
struct net_device *net; /* network interface, if created */
};
@@ -988,7 +988,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
* Encode up and queue a UI/UIH frame containing our response.
*/
-static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,
+static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data,
int dlen)
{
struct gsm_msg *msg;
@@ -1073,14 +1073,14 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
* and if need be stuff a break message down the tty.
*/
-static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
+static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
{
unsigned int addr = 0;
unsigned int modem = 0;
unsigned int brk = 0;
struct gsm_dlci *dlci;
int len = clen;
- u8 *dp = data;
+ const u8 *dp = data;
struct tty_struct *tty;
while (gsm_read_ea(&addr, *dp++) == 0) {
@@ -1134,13 +1134,13 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
* this into the uplink tty if present
*/
-static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen)
+static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
{
struct tty_port *port;
unsigned int addr = 0;
u8 bits;
int len = clen;
- u8 *dp = data;
+ const u8 *dp = data;
while (gsm_read_ea(&addr, *dp++) == 0) {
len--;
@@ -1189,7 +1189,7 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci);
*/
static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
- u8 *data, int clen)
+ const u8 *data, int clen)
{
u8 buf[1];
unsigned long flags;
@@ -1261,7 +1261,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
*/
static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
- u8 *data, int clen)
+ const u8 *data, int clen)
{
struct gsm_control *ctrl;
unsigned long flags;
@@ -1553,7 +1553,7 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci)
* open we shovel the bits down it, if not we drop them.
*/
-static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen)
+static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
{
/* krefs .. */
struct tty_port *port = &dlci->port;
@@ -1565,14 +1565,11 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen)
pr_debug("%d bytes for tty\n", len);
switch (dlci->adaption) {
/* Unsupported types */
- /* Packetised interruptible data */
- case 4:
+ case 4: /* Packetised interruptible data */
break;
- /* Packetised uininterruptible voice/data */
- case 3:
+ case 3: /* Packetised uininterruptible voice/data */
break;
- /* Asynchronous serial with line state in each frame */
- case 2:
+ case 2: /* Asynchronous serial with line state in each frame */
while (gsm_read_ea(&modem, *data++) == 0) {
len--;
if (len == 0)
@@ -1583,8 +1580,8 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen)
gsm_process_modem(tty, dlci, modem, clen);
tty_kref_put(tty);
}
- /* Line state will go via DLCI 0 controls only */
- case 1:
+ /* Fall through */
+ case 1: /* Line state will go via DLCI 0 controls only */
default:
tty_insert_flip_string(port, data, len);
tty_flip_buffer_push(port);
@@ -1603,7 +1600,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen)
* and we divide up the work accordingly.
*/
-static void gsm_dlci_command(struct gsm_dlci *dlci, u8 *data, int len)
+static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len)
{
/* See what command is involved */
unsigned int command = 0;
@@ -1979,7 +1976,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
gsm->address = 0;
gsm->state = GSM_ADDRESS;
gsm->fcs = INIT_FCS;
- /* Drop through */
+ /* Fall through */
case GSM_ADDRESS: /* Address continuation */
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
if (gsm_read_ea(&gsm->address, c))
@@ -2214,6 +2211,111 @@ static struct gsm_mux *gsm_alloc_mux(void)
return gsm;
}
+static void gsm_copy_config_values(struct gsm_mux *gsm,
+ struct gsm_config *c)
+{
+ memset(c, 0, sizeof(*c));
+ c->adaption = gsm->adaption;
+ c->encapsulation = gsm->encoding;
+ c->initiator = gsm->initiator;
+ c->t1 = gsm->t1;
+ c->t2 = gsm->t2;
+ c->t3 = 0; /* Not supported */
+ c->n2 = gsm->n2;
+ if (gsm->ftype == UIH)
+ c->i = 1;
+ else
+ c->i = 2;
+ pr_debug("Ftype %d i %d\n", gsm->ftype, c->i);
+ c->mru = gsm->mru;
+ c->mtu = gsm->mtu;
+ c->k = 0;
+}
+
+static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
+{
+ int need_close = 0;
+ int need_restart = 0;
+
+ /* Stuff we don't support yet - UI or I frame transport, windowing */
+ if ((c->adaption != 1 && c->adaption != 2) || c->k)
+ return -EOPNOTSUPP;
+ /* Check the MRU/MTU range looks sane */
+ if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
+ return -EINVAL;
+ if (c->n2 < 3)
+ return -EINVAL;
+ if (c->encapsulation > 1) /* Basic, advanced, no I */
+ return -EINVAL;
+ if (c->initiator > 1)
+ return -EINVAL;
+ if (c->i == 0 || c->i > 2) /* UIH and UI only */
+ return -EINVAL;
+ /*
+ * See what is needed for reconfiguration
+ */
+
+ /* Timing fields */
+ if (c->t1 != 0 && c->t1 != gsm->t1)
+ need_restart = 1;
+ if (c->t2 != 0 && c->t2 != gsm->t2)
+ need_restart = 1;
+ if (c->encapsulation != gsm->encoding)
+ need_restart = 1;
+ if (c->adaption != gsm->adaption)
+ need_restart = 1;
+ /* Requires care */
+ if (c->initiator != gsm->initiator)
+ need_close = 1;
+ if (c->mru != gsm->mru)
+ need_restart = 1;
+ if (c->mtu != gsm->mtu)
+ need_restart = 1;
+
+ /*
+ * Close down what is needed, restart and initiate the new
+ * configuration
+ */
+
+ if (need_close || need_restart) {
+ int ret;
+
+ ret = gsm_disconnect(gsm);
+
+ if (ret)
+ return ret;
+ }
+ if (need_restart)
+ gsm_cleanup_mux(gsm);
+
+ gsm->initiator = c->initiator;
+ gsm->mru = c->mru;
+ gsm->mtu = c->mtu;
+ gsm->encoding = c->encapsulation;
+ gsm->adaption = c->adaption;
+ gsm->n2 = c->n2;
+
+ if (c->i == 1)
+ gsm->ftype = UIH;
+ else if (c->i == 2)
+ gsm->ftype = UI;
+
+ if (c->t1)
+ gsm->t1 = c->t1;
+ if (c->t2)
+ gsm->t2 = c->t2;
+
+ /*
+ * FIXME: We need to separate activation/deactivation from adding
+ * and removing from the mux array
+ */
+ if (need_restart)
+ gsm_activate_mux(gsm);
+ if (gsm->initiator && need_close)
+ gsm_dlci_begin_open(gsm->dlci[0]);
+ return 0;
+}
+
/**
* gsmld_output - write to link
* @gsm: our mux
@@ -2495,89 +2597,6 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file,
return mask;
}
-static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm,
- struct gsm_config *c)
-{
- int need_close = 0;
- int need_restart = 0;
-
- /* Stuff we don't support yet - UI or I frame transport, windowing */
- if ((c->adaption != 1 && c->adaption != 2) || c->k)
- return -EOPNOTSUPP;
- /* Check the MRU/MTU range looks sane */
- if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
- return -EINVAL;
- if (c->n2 < 3)
- return -EINVAL;
- if (c->encapsulation > 1) /* Basic, advanced, no I */
- return -EINVAL;
- if (c->initiator > 1)
- return -EINVAL;
- if (c->i == 0 || c->i > 2) /* UIH and UI only */
- return -EINVAL;
- /*
- * See what is needed for reconfiguration
- */
-
- /* Timing fields */
- if (c->t1 != 0 && c->t1 != gsm->t1)
- need_restart = 1;
- if (c->t2 != 0 && c->t2 != gsm->t2)
- need_restart = 1;
- if (c->encapsulation != gsm->encoding)
- need_restart = 1;
- if (c->adaption != gsm->adaption)
- need_restart = 1;
- /* Requires care */
- if (c->initiator != gsm->initiator)
- need_close = 1;
- if (c->mru != gsm->mru)
- need_restart = 1;
- if (c->mtu != gsm->mtu)
- need_restart = 1;
-
- /*
- * Close down what is needed, restart and initiate the new
- * configuration
- */
-
- if (need_close || need_restart) {
- int ret;
-
- ret = gsm_disconnect(gsm);
-
- if (ret)
- return ret;
- }
- if (need_restart)
- gsm_cleanup_mux(gsm);
-
- gsm->initiator = c->initiator;
- gsm->mru = c->mru;
- gsm->mtu = c->mtu;
- gsm->encoding = c->encapsulation;
- gsm->adaption = c->adaption;
- gsm->n2 = c->n2;
-
- if (c->i == 1)
- gsm->ftype = UIH;
- else if (c->i == 2)
- gsm->ftype = UI;
-
- if (c->t1)
- gsm->t1 = c->t1;
- if (c->t2)
- gsm->t2 = c->t2;
-
- /* FIXME: We need to separate activation/deactivation from adding
- and removing from the mux array */
- if (need_restart)
- gsm_activate_mux(gsm);
- if (gsm->initiator && need_close)
- gsm_dlci_begin_open(gsm->dlci[0]);
- return 0;
-}
-
static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -2586,29 +2605,14 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
switch (cmd) {
case GSMIOC_GETCONF:
- memset(&c, 0, sizeof(c));
- c.adaption = gsm->adaption;
- c.encapsulation = gsm->encoding;
- c.initiator = gsm->initiator;
- c.t1 = gsm->t1;
- c.t2 = gsm->t2;
- c.t3 = 0; /* Not supported */
- c.n2 = gsm->n2;
- if (gsm->ftype == UIH)
- c.i = 1;
- else
- c.i = 2;
- pr_debug("Ftype %d i %d\n", gsm->ftype, c.i);
- c.mru = gsm->mru;
- c.mtu = gsm->mtu;
- c.k = 0;
+ gsm_copy_config_values(gsm, &c);
if (copy_to_user((void *)arg, &c, sizeof(c)))
return -EFAULT;
return 0;
case GSMIOC_SETCONF:
if (copy_from_user(&c, (void *)arg, sizeof(c)))
return -EFAULT;
- return gsmld_config(tty, gsm, &c);
+ return gsm_config(gsm, &c);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
}
@@ -2695,7 +2699,7 @@ static void gsm_mux_net_tx_timeout(struct net_device *net)
}
static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
- unsigned char *in_buf, int size)
+ const unsigned char *in_buf, int size)
{
struct net_device *net = dlci->net;
struct sk_buff *skb;
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 4164414d4c64..e55c79eb6430 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
/* too large for caller's buffer */
ret = -EOVERFLOW;
} else {
+ __set_current_state(TASK_RUNNING);
if (copy_to_user(buf, rbuf->buf, rbuf->count))
ret = -EFAULT;
else
@@ -776,7 +777,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
case TCOFLUSH:
flush_tx_queue(tty);
}
- /* fall through to default */
+ /* fall through - to default */
default:
error = n_tty_ioctl_helper(tty, file, cmd, arg);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 5dc9686697cf..9cdb0fa3c4bf 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -50,8 +50,10 @@
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
-
-/* number of characters left in xmit buffer before select has we have room */
+/*
+ * Until this number of characters is queued in the xmit buffer, select will
+ * return "we have room for writes".
+ */
#define WAKEUP_CHARS 256
/*
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index fed820e9ab9d..3214e22e79f3 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -1317,7 +1317,6 @@ static void remove_sysfs_files(struct nozomi *dc)
static int nozomi_card_init(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- resource_size_t start;
int ret;
struct nozomi *dc = NULL;
int ndev_idx;
@@ -1357,17 +1356,10 @@ static int nozomi_card_init(struct pci_dev *pdev,
goto err_disable_device;
}
- start = pci_resource_start(dc->pdev, 0);
- if (start == 0) {
- dev_err(&pdev->dev, "No I/O address for card detected\n");
- ret = -ENODEV;
- goto err_rel_regs;
- }
-
/* Find out what card type it is */
nozomi_get_card_type(dc);
- dc->base_addr = ioremap_nocache(start, dc->card_type);
+ dc->base_addr = pci_iomap(dc->pdev, 0, dc->card_type);
if (!dc->base_addr) {
dev_err(&pdev->dev, "Unable to map card MMIO\n");
ret = -ENODEV;
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index fa1672993b4c..d1cdd2ab8b4c 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -233,7 +233,7 @@ static int ttyport_get_tiocm(struct serdev_controller *ctrl)
if (!tty->ops->tiocmget)
return -ENOTSUPP;
- return tty->driver->ops->tiocmget(tty);
+ return tty->ops->tiocmget(tty);
}
static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, unsigned int clear)
@@ -244,7 +244,7 @@ static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, u
if (!tty->ops->tiocmset)
return -ENOTSUPP;
- return tty->driver->ops->tiocmset(tty, set, clear);
+ return tty->ops->tiocmset(tty, set, clear);
}
static const struct serdev_controller_ops ctrl_ops = {
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 189ab1212d9a..e441221e04b9 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
ret = 0;
}
- }
- /* Initialise interrupt backoff work if required */
- if (up->overrun_backoff_time_ms > 0) {
- uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
- INIT_DELAYED_WORK(&uart->overrun_backoff,
- serial_8250_overrun_backoff_work);
- } else {
- uart->overrun_backoff_time_ms = 0;
+ /* Initialise interrupt backoff work if required */
+ if (up->overrun_backoff_time_ms > 0) {
+ uart->overrun_backoff_time_ms =
+ up->overrun_backoff_time_ms;
+ INIT_DELAYED_WORK(&uart->overrun_backoff,
+ serial_8250_overrun_backoff_work);
+ } else {
+ uart->overrun_backoff_time_ms = 0;
+ }
}
mutex_unlock(&serial_mutex);
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 15a8c8dfa92b..424c07c5f629 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -129,22 +129,21 @@ static int __init ingenic_early_console_setup(struct earlycon_device *dev,
return 0;
}
-EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",
ingenic_early_console_setup);
-EARLYCON_DECLARE(jz4770_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4770_uart, "ingenic,jz4770-uart",
ingenic_early_console_setup);
-EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
ingenic_early_console_setup);
-EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(x1000_uart, "ingenic,x1000-uart",
+ ingenic_early_console_setup);
+
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
{
int ier;
@@ -328,12 +327,18 @@ static const struct ingenic_uart_config jz4780_uart_config = {
.fifosize = 64,
};
+static const struct ingenic_uart_config x1000_uart_config = {
+ .tx_loadsz = 32,
+ .fifosize = 64,
+};
+
static const struct of_device_id of_match[] = {
{ .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config },
{ .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config },
{ .compatible = "ingenic,jz4770-uart", .data = &jz4760_uart_config },
{ .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config },
{ .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config },
+ { .compatible = "ingenic,x1000-uart", .data = &x1000_uart_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match);
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index e2c407656fa6..c1fdbc0b6840 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -357,6 +357,9 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
if (dmacnt == 2) {
data->dma = devm_kzalloc(&pdev->dev, sizeof(*data->dma),
GFP_KERNEL);
+ if (!data->dma)
+ return -ENOMEM;
+
data->dma->fn = mtk8250_dma_filter;
data->dma->rx_size = MTK_UART_RX_SIZE;
data->dma->rxconf.src_maxburst = MTK_UART_RX_TRIGGER;
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index a1a85805d010..0277479c87e9 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -130,6 +130,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
port->flags |= UPF_IOREMAP;
}
+ /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */
+ if (of_device_is_compatible(np, "mrvl,mmp-uart"))
+ port->regshift = 2;
+
/* Check for registers offset within the devices address range */
if (of_property_read_u32(np, "reg-shift", &prop) == 0)
port->regshift = prop;
@@ -327,6 +331,7 @@ static const struct of_device_id of_platform_serial_table[] = {
{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
{ .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
{ .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, },
+ { .compatible = "intel,xscale-uart", .data = (void *)PORT_XSCALE, },
{ .compatible = "altr,16550-FIFO32",
.data = (void *)PORT_ALTR_16550_F32, },
{ .compatible = "altr,16550-FIFO64",
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index ad7ba7d0f28d..0a8316632d75 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -12,6 +12,7 @@
#define SUPPORT_SYSRQ
#endif
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -1134,10 +1135,12 @@ static int omap8250_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ struct device_node *np = pdev->dev.of_node;
struct omap8250_priv *priv;
struct uart_8250_port up;
int ret;
void __iomem *membase;
+ const struct of_device_id *id;
if (!regs || !irq) {
dev_err(&pdev->dev, "missing registers or irq\n");
@@ -1194,27 +1197,31 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.unthrottle = omap_8250_unthrottle;
up.port.rs485_config = omap_8250_rs485_config;
- if (pdev->dev.of_node) {
- const struct of_device_id *id;
-
- ret = of_alias_get_id(pdev->dev.of_node, "serial");
-
- of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &up.port.uartclk);
- priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
-
- id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
- if (id && id->data)
- priv->habit |= *(u8 *)id->data;
- } else {
- ret = pdev->id;
- }
+ ret = of_alias_get_id(np, "serial");
if (ret < 0) {
- dev_err(&pdev->dev, "failed to get alias/pdev id\n");
+ dev_err(&pdev->dev, "failed to get alias\n");
return ret;
}
up.port.line = ret;
+ if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) {
+ struct clk *clk;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ } else {
+ up.port.uartclk = clk_get_rate(clk);
+ }
+ }
+
+ priv->wakeirq = irq_of_parse_and_map(np, 1);
+
+ id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
+ if (id && id->data)
+ priv->habit |= *(u8 *)id->data;
+
if (!up.port.uartclk) {
up.port.uartclk = DEFAULT_CLK_SPEED;
dev_warn(&pdev->dev,
@@ -1242,25 +1249,23 @@ static int omap8250_probe(struct platform_device *pdev)
omap_serial_fill_features_erratas(&up, priv);
up.port.handle_irq = omap8250_no_handle_irq;
#ifdef CONFIG_SERIAL_8250_DMA
- if (pdev->dev.of_node) {
- /*
- * Oh DMA support. If there are no DMA properties in the DT then
- * we will fall back to a generic DMA channel which does not
- * really work here. To ensure that we do not get a generic DMA
- * channel assigned, we have the the_no_dma_filter_fn() here.
- * To avoid "failed to request DMA" messages we check for DMA
- * properties in DT.
- */
- ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
- if (ret == 2) {
- up.dma = &priv->omap8250_dma;
- priv->omap8250_dma.fn = the_no_dma_filter_fn;
- priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
- priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
- priv->omap8250_dma.rx_size = RX_TRIGGER;
- priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
- priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
- }
+ /*
+ * Oh DMA support. If there are no DMA properties in the DT then
+ * we will fall back to a generic DMA channel which does not
+ * really work here. To ensure that we do not get a generic DMA
+ * channel assigned, we have the the_no_dma_filter_fn() here.
+ * To avoid "failed to request DMA" messages we check for DMA
+ * properties in DT.
+ */
+ ret = of_property_count_strings(np, "dma-names");
+ if (ret == 2) {
+ up.dma = &priv->omap8250_dma;
+ priv->omap8250_dma.fn = the_no_dma_filter_fn;
+ priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
+ priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
+ priv->omap8250_dma.rx_size = RX_TRIGGER;
+ priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
+ priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
}
#endif
ret = serial8250_register_8250_port(&up);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index f80a300b5d68..df41397de478 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -2027,6 +2027,111 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup,
.exit = pci_plx9050_exit,
},
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_ACCESIO,
+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
+ },
/*
* SBS Technologies, Inc., PMC-OCTALPRO 232
*/
@@ -3375,6 +3480,9 @@ static const struct pci_device_id blacklist[] = {
/* Exar devices */
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), },
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
+
+ /* End of the black list */
+ { }
};
static int serial_pci_is_class_communication(struct pci_dev *dev)
@@ -3392,25 +3500,6 @@ static int serial_pci_is_class_communication(struct pci_dev *dev)
return 0;
}
-static int serial_pci_is_blacklisted(struct pci_dev *dev)
-{
- const struct pci_device_id *bldev;
-
- /*
- * Do not access blacklisted devices that are known not to
- * feature serial ports or are handled by other modules.
- */
- for (bldev = blacklist;
- bldev < blacklist + ARRAY_SIZE(blacklist);
- bldev++) {
- if (dev->vendor == bldev->vendor &&
- dev->device == bldev->device)
- return -ENODEV;
- }
-
- return 0;
-}
-
/*
* Given a complete unknown PCI device, try to use some heuristics to
* guess what the configuration might be, based on the pitiful PCI
@@ -3420,6 +3509,11 @@ static int
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
int num_iomem, num_port, first_port = -1, i;
+ int rc;
+
+ rc = serial_pci_is_class_communication(dev);
+ if (rc)
+ return rc;
/*
* Should we try to make guesses for multiport serial devices later?
@@ -3629,6 +3723,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
struct pci_serial_quirk *quirk;
struct serial_private *priv;
const struct pciserial_board *board;
+ const struct pci_device_id *exclude;
struct pciserial_board tmp;
int rc;
@@ -3647,13 +3742,9 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
board = &pci_boards[ent->driver_data];
- rc = serial_pci_is_class_communication(dev);
- if (rc)
- return rc;
-
- rc = serial_pci_is_blacklisted(dev);
- if (rc)
- return rc;
+ exclude = pci_match_id(blacklist, dev);
+ if (exclude)
+ return -ENODEV;
rc = pcim_enable_device(dev);
pci_save_state(dev);
@@ -4574,10 +4665,10 @@ static const struct pci_device_id serial_pci_tbl[] = {
*/
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
@@ -4586,10 +4677,10 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
@@ -4598,10 +4689,10 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
@@ -4610,13 +4701,13 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7951 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
@@ -4625,16 +4716,16 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7954 },
@@ -4643,13 +4734,13 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
+ pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
+ pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
+ pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7958 },
@@ -4658,19 +4749,19 @@ static const struct pci_device_id serial_pci_tbl[] = {
pbn_pericom_PI7C9X7958 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
+ pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7958 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
+ pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pericom_PI7C9X7958 },
{ PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
+ pbn_pericom_PI7C9X7954 },
/*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
index b9bcbe20a2be..c47188860e32 100644
--- a/drivers/tty/serial/8250/8250_pxa.c
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -113,6 +113,10 @@ static int serial_pxa_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (ret >= 0)
+ uart.port.line = ret;
+
uart.port.type = PORT_XSCALE;
uart.port.iotype = UPIO_MEM32;
uart.port.mapbase = mmres->start;
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 67b9bf3b500e..72966bc0ac76 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -85,6 +85,18 @@ config SERIAL_EARLYCON_ARM_SEMIHOST
with "earlycon=smh" on the kernel command line. The console is
enabled when early_param is processed.
+config SERIAL_EARLYCON_RISCV_SBI
+ bool "Early console using RISC-V SBI"
+ depends on RISCV
+ select SERIAL_CORE
+ select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
+ help
+ Support for early debug console using RISC-V SBI. This enables
+ the console before standard serial driver is probed. This is enabled
+ with "earlycon=sbi" on the kernel command line. The console is
+ enabled when early_param is processed.
+
config SERIAL_SB1250_DUART
tristate "BCM1xxx on-chip DUART serial support"
depends on SIBYTE_SB1xxx_SOC=y
@@ -323,6 +335,28 @@ config SERIAL_TEGRA
are enabled). This driver uses the APB DMA to achieve higher baudrate
and better performance.
+config SERIAL_TEGRA_TCU
+ tristate "NVIDIA Tegra Combined UART"
+ depends on ARCH_TEGRA && TEGRA_HSP_MBOX
+ select SERIAL_CORE
+ help
+ Support for the mailbox-based TCU (Tegra Combined UART) serial port.
+ TCU is a virtual serial port that allows multiplexing multiple data
+ streams into a single hardware serial port.
+
+config SERIAL_TEGRA_TCU_CONSOLE
+ bool "Support for console on a Tegra TCU serial port"
+ depends on SERIAL_TEGRA_TCU=y
+ select SERIAL_CORE_CONSOLE
+ default y
+ ---help---
+ If you say Y here, it will be possible to use a the Tegra TCU 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).
+
+ If unsure, say Y.
+
config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 8c303736b7e8..40b702aaa85e 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o
obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
+obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
# These Sparc drivers have to appear before others such as 8250
# which share ttySx minor node space. Otherwise console device
@@ -76,6 +77,7 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 98f193a83392..061590795680 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -442,14 +442,10 @@ static struct console clps711x_console = {
static int uart_clps711x_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- int ret, index = np ? of_alias_get_id(np, "serial") : pdev->id;
struct clps711x_port *s;
struct resource *res;
struct clk *uart_clk;
- int irq;
-
- if (index < 0 || index >= UART_CLPS711X_NR)
- return -EINVAL;
+ int irq, ret;
s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
if (!s)
@@ -473,20 +469,11 @@ static int uart_clps711x_probe(struct platform_device *pdev)
if (s->rx_irq < 0)
return s->rx_irq;
- if (!np) {
- char syscon_name[9];
-
- sprintf(syscon_name, "syscon.%i", index + 1);
- s->syscon = syscon_regmap_lookup_by_pdevname(syscon_name);
- if (IS_ERR(s->syscon))
- return PTR_ERR(s->syscon);
- } else {
- s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
- if (IS_ERR(s->syscon))
- return PTR_ERR(s->syscon);
- }
+ s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
+ if (IS_ERR(s->syscon))
+ return PTR_ERR(s->syscon);
- s->port.line = index;
+ s->port.line = of_alias_get_id(np, "serial");
s->port.dev = &pdev->dev;
s->port.iotype = UPIO_MEM32;
s->port.mapbase = res->start;
diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c
new file mode 100644
index 000000000000..ce81523c3113
--- /dev/null
+++ b/drivers/tty/serial/earlycon-riscv-sbi.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RISC-V SBI based earlycon
+ *
+ * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
+ */
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <asm/sbi.h>
+
+static void sbi_putc(struct uart_port *port, int c)
+{
+ sbi_console_putchar(c);
+}
+
+static void sbi_console_write(struct console *con,
+ const char *s, unsigned n)
+{
+ struct earlycon_device *dev = con->data;
+ uart_console_write(&dev->port, s, n, sbi_putc);
+}
+
+static int __init early_sbi_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ device->con->write = sbi_console_write;
+ return 0;
+}
+EARLYCON_DECLARE(sbi, early_sbi_setup);
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 241a48e5052c..ea1c85e3b432 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -426,6 +426,17 @@ static void lpuart_dma_tx_complete(void *arg)
spin_unlock_irqrestore(&sport->port.lock, flags);
}
+static dma_addr_t lpuart_dma_datareg_addr(struct lpuart_port *sport)
+{
+ switch (sport->port.iotype) {
+ case UPIO_MEM32:
+ return sport->port.mapbase + UARTDATA;
+ case UPIO_MEM32BE:
+ return sport->port.mapbase + UARTDATA + sizeof(u32) - 1;
+ }
+ return sport->port.mapbase + UARTDR;
+}
+
static int lpuart_dma_tx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
@@ -433,7 +444,7 @@ static int lpuart_dma_tx_request(struct uart_port *port)
struct dma_slave_config dma_tx_sconfig = {};
int ret;
- dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
+ dma_tx_sconfig.dst_addr = lpuart_dma_datareg_addr(sport);
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_tx_sconfig.dst_maxburst = 1;
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
@@ -636,13 +647,19 @@ static void lpuart_start_tx(struct uart_port *port)
static void lpuart32_start_tx(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+ struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long temp;
- temp = lpuart32_read(port, UARTCTRL);
- lpuart32_write(port, temp | UARTCTRL_TIE, UARTCTRL);
+ if (sport->lpuart_dma_tx_use) {
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
+ lpuart_dma_tx(sport);
+ } else {
+ temp = lpuart32_read(port, UARTCTRL);
+ lpuart32_write(port, temp | UARTCTRL_TIE, UARTCTRL);
- if (lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE)
- lpuart32_transmit_buffer(sport);
+ if (lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE)
+ lpuart32_transmit_buffer(sport);
+ }
}
/* return TIOCSER_TEMT when transmitter is not busy */
@@ -664,8 +681,18 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
static unsigned int lpuart32_tx_empty(struct uart_port *port)
{
- return (lpuart32_read(port, UARTSTAT) & UARTSTAT_TC) ?
- TIOCSER_TEMT : 0;
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ unsigned long stat = lpuart32_read(port, UARTSTAT);
+ unsigned long sfifo = lpuart32_read(port, UARTFIFO);
+
+ if (sport->dma_tx_in_progress)
+ return 0;
+
+ if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
+ return TIOCSER_TEMT;
+
+ return 0;
}
static bool lpuart_is_32(struct lpuart_port *sport)
@@ -862,11 +889,10 @@ static irqreturn_t lpuart32_int(int irq, void *dev_id)
rxcount = lpuart32_read(&sport->port, UARTWATER);
rxcount = rxcount >> UARTWATER_RXCNT_OFF;
- if (sts & UARTSTAT_RDRF || rxcount > 0)
+ if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use)
lpuart32_rxint(irq, dev_id);
- if ((sts & UARTSTAT_TDRE) &&
- !(lpuart32_read(&sport->port, UARTBAUD) & UARTBAUD_TDMAE))
+ if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use)
lpuart_txint(irq, dev_id);
lpuart32_write(&sport->port, sts, UARTSTAT);
@@ -881,18 +907,31 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
struct circ_buf *ring = &sport->rx_ring;
unsigned long flags;
int count = 0;
- unsigned char sr;
- sr = readb(sport->port.membase + UARTSR1);
+ if (lpuart_is_32(sport)) {
+ unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
- if (sr & (UARTSR1_PE | UARTSR1_FE)) {
- /* Read DR to clear the error flags */
- readb(sport->port.membase + UARTDR);
+ if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
+ /* Read DR to clear the error flags */
+ lpuart32_read(&sport->port, UARTDATA);
+
+ if (sr & UARTSTAT_PE)
+ sport->port.icount.parity++;
+ else if (sr & UARTSTAT_FE)
+ sport->port.icount.frame++;
+ }
+ } else {
+ unsigned char sr = readb(sport->port.membase + UARTSR1);
- if (sr & UARTSR1_PE)
- sport->port.icount.parity++;
- else if (sr & UARTSR1_FE)
- sport->port.icount.frame++;
+ if (sr & (UARTSR1_PE | UARTSR1_FE)) {
+ /* Read DR to clear the error flags */
+ readb(sport->port.membase + UARTDR);
+
+ if (sr & UARTSR1_PE)
+ sport->port.icount.parity++;
+ else if (sr & UARTSR1_FE)
+ sport->port.icount.frame++;
+ }
}
async_tx_ack(sport->dma_rx_desc);
@@ -1015,7 +1054,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
return -EINVAL;
}
- dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
+ dma_rx_sconfig.src_addr = lpuart_dma_datareg_addr(sport);
dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_rx_sconfig.src_maxburst = 1;
dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
@@ -1043,8 +1082,14 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
dma_async_issue_pending(sport->dma_rx_chan);
- writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_RDMAS,
- sport->port.membase + UARTCR5);
+ if (lpuart_is_32(sport)) {
+ unsigned long temp = lpuart32_read(&sport->port, UARTBAUD);
+
+ lpuart32_write(&sport->port, temp | UARTBAUD_RDMAE, UARTBAUD);
+ } else {
+ writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_RDMAS,
+ sport->port.membase + UARTCR5);
+ }
return 0;
}
@@ -1334,6 +1379,8 @@ static int lpuart32_startup(struct uart_port *port)
sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK) - 1);
+ sport->port.fifosize = sport->txfifo_size;
+
sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK) - 1);
@@ -1342,8 +1389,41 @@ static int lpuart32_startup(struct uart_port *port)
lpuart32_setup_watermark(sport);
temp = lpuart32_read(&sport->port, UARTCTRL);
- temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
- temp |= UARTCTRL_ILIE;
+ temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
+ lpuart32_write(&sport->port, temp, UARTCTRL);
+
+ if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
+ /* set Rx DMA timeout */
+ sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
+ if (!sport->dma_rx_timeout)
+ sport->dma_rx_timeout = 1;
+
+ sport->lpuart_dma_rx_use = true;
+ rx_dma_timer_init(sport);
+ } else {
+ sport->lpuart_dma_rx_use = false;
+ }
+
+ if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
+ init_waitqueue_head(&sport->dma_wait);
+ sport->lpuart_dma_tx_use = true;
+ temp = lpuart32_read(&sport->port, UARTBAUD);
+ lpuart32_write(&sport->port, temp | UARTBAUD_TDMAE, UARTBAUD);
+ } else {
+ sport->lpuart_dma_tx_use = false;
+ }
+
+ if (sport->lpuart_dma_rx_use) {
+ /* RXWATER must be 0 */
+ temp = lpuart32_read(&sport->port, UARTWATER);
+ temp &= ~(UARTWATER_WATER_MASK << UARTWATER_RXWATER_OFF);
+ lpuart32_write(&sport->port, temp, UARTWATER);
+ }
+ temp = lpuart32_read(&sport->port, UARTCTRL);
+ if (!sport->lpuart_dma_rx_use)
+ temp |= UARTCTRL_RIE;
+ if (!sport->lpuart_dma_tx_use)
+ temp |= UARTCTRL_TIE;
lpuart32_write(&sport->port, temp, UARTCTRL);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1384,6 +1464,8 @@ static void lpuart_shutdown(struct uart_port *port)
static void lpuart32_shutdown(struct uart_port *port)
{
+ struct lpuart_port *sport =
+ container_of(port, struct lpuart_port, port);
unsigned long temp;
unsigned long flags;
@@ -1396,6 +1478,21 @@ static void lpuart32_shutdown(struct uart_port *port)
lpuart32_write(port, temp, UARTCTRL);
spin_unlock_irqrestore(&port->lock, flags);
+
+ if (sport->lpuart_dma_rx_use) {
+ del_timer_sync(&sport->lpuart_timer);
+ lpuart_dma_rx_free(&sport->port);
+ }
+
+ if (sport->lpuart_dma_tx_use) {
+ if (wait_event_interruptible(sport->dma_wait,
+ !sport->dma_tx_in_progress)) {
+ sport->dma_tx_in_progress = false;
+ dmaengine_terminate_all(sport->dma_tx_chan);
+ }
+
+ lpuart32_stop_tx(port);
+ }
}
static void
@@ -1621,7 +1718,10 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
tmp &= ~UARTBAUD_SBR_MASK;
tmp |= sbr & UARTBAUD_SBR_MASK;
- tmp &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+ if (!sport->lpuart_dma_rx_use)
+ tmp &= ~UARTBAUD_RDMAE;
+ if (!sport->lpuart_dma_tx_use)
+ tmp &= ~UARTBAUD_TDMAE;
lpuart32_write(&sport->port, tmp, UARTBAUD);
}
@@ -1697,7 +1797,19 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
}
/* ask the core to calculate the divisor */
- baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+ baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
+
+ /*
+ * Need to update the Ring buffer length according to the selected
+ * baud rate and restart Rx DMA path.
+ *
+ * Since timer function acqures sport->port.lock, need to stop before
+ * acquring same lock because otherwise del_timer_sync() can deadlock.
+ */
+ if (old && sport->lpuart_dma_rx_use) {
+ del_timer_sync(&sport->lpuart_timer);
+ lpuart_dma_rx_free(&sport->port);
+ }
spin_lock_irqsave(&sport->port.lock, flags);
@@ -1737,6 +1849,13 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(&sport->port, ctrl, UARTCTRL);
/* restore control register */
+ if (old && sport->lpuart_dma_rx_use) {
+ if (!lpuart_start_rx_dma(sport))
+ rx_dma_timer_init(sport);
+ else
+ sport->lpuart_dma_rx_use = false;
+ }
+
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -2306,8 +2425,14 @@ static int lpuart_suspend(struct device *dev)
}
/* Disable Rx DMA to use UART port as wakeup source */
- writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_RDMAS,
- sport->port.membase + UARTCR5);
+ if (lpuart_is_32(sport)) {
+ temp = lpuart32_read(&sport->port, UARTBAUD);
+ lpuart32_write(&sport->port, temp & ~UARTBAUD_RDMAE,
+ UARTBAUD);
+ } else {
+ writeb(readb(sport->port.membase + UARTCR5) &
+ ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+ }
}
if (sport->lpuart_dma_tx_use) {
@@ -2333,8 +2458,7 @@ static int lpuart_resume(struct device *dev)
if (lpuart_is_32(sport)) {
lpuart32_setup_watermark(sport);
temp = lpuart32_read(&sport->port, UARTCTRL);
- temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
- UARTCTRL_TE | UARTCTRL_ILIE);
+ temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
lpuart32_write(&sport->port, temp, UARTCTRL);
} else {
lpuart_setup_watermark(sport);
@@ -2353,14 +2477,36 @@ static int lpuart_resume(struct device *dev)
}
if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
- init_waitqueue_head(&sport->dma_wait);
- sport->lpuart_dma_tx_use = true;
+ init_waitqueue_head(&sport->dma_wait);
+ sport->lpuart_dma_tx_use = true;
+ if (lpuart_is_32(sport)) {
+ temp = lpuart32_read(&sport->port, UARTBAUD);
+ lpuart32_write(&sport->port,
+ temp | UARTBAUD_TDMAE, UARTBAUD);
+ } else {
writeb(readb(sport->port.membase + UARTCR5) |
UARTCR5_TDMAS, sport->port.membase + UARTCR5);
+ }
} else {
sport->lpuart_dma_tx_use = false;
}
+ if (lpuart_is_32(sport)) {
+ if (sport->lpuart_dma_rx_use) {
+ /* RXWATER must be 0 */
+ temp = lpuart32_read(&sport->port, UARTWATER);
+ temp &= ~(UARTWATER_WATER_MASK <<
+ UARTWATER_RXWATER_OFF);
+ lpuart32_write(&sport->port, temp, UARTWATER);
+ }
+ temp = lpuart32_read(&sport->port, UARTCTRL);
+ if (!sport->lpuart_dma_rx_use)
+ temp |= UARTCTRL_RIE;
+ if (!sport->lpuart_dma_tx_use)
+ temp |= UARTCTRL_TIE;
+ lpuart32_write(&sport->port, temp, UARTCTRL);
+ }
+
uart_resume_port(&lpuart_reg, &sport->port);
return 0;
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index e052b69ceb98..9de9f0f239a1 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -114,9 +114,9 @@ struct ltq_uart_port {
static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg)
{
- u32 tmp = readl(reg);
+ u32 tmp = __raw_readl(reg);
- writel((tmp & ~clear) | set, reg);
+ __raw_writel((tmp & ~clear) | set, reg);
}
static inline struct
@@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port)
static void
lqasc_stop_rx(struct uart_port *port)
{
- writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+ __raw_writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
}
static int
@@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port)
struct tty_port *tport = &port->state->port;
unsigned int ch = 0, rsr = 0, fifocnt;
- fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+ fifocnt = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+ ASCFSTAT_RXFFLMASK;
while (fifocnt--) {
u8 flag = TTY_NORMAL;
ch = readb(port->membase + LTQ_ASC_RBUF);
- rsr = (readl(port->membase + LTQ_ASC_STATE)
+ rsr = (__raw_readl(port->membase + LTQ_ASC_STATE)
& ASCSTATE_ANY) | UART_DUMMY_UER_RX;
tty_flip_buffer_push(tport);
port->icount.rx++;
@@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port)
return;
}
- while (((readl(port->membase + LTQ_ASC_FSTAT) &
+ while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
if (port->x_char) {
writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
@@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port)
unsigned long flags;
struct uart_port *port = (struct uart_port *)_port;
spin_lock_irqsave(&ltq_asc_lock, flags);
- writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+ __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
spin_unlock_irqrestore(&ltq_asc_lock, flags);
lqasc_start_tx(port);
return IRQ_HANDLED;
@@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port)
unsigned long flags;
struct uart_port *port = (struct uart_port *)_port;
spin_lock_irqsave(&ltq_asc_lock, flags);
- writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+ __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
lqasc_rx_chars(port);
spin_unlock_irqrestore(&ltq_asc_lock, flags);
return IRQ_HANDLED;
@@ -280,7 +281,8 @@ static unsigned int
lqasc_tx_empty(struct uart_port *port)
{
int status;
- status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+ status = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+ ASCFSTAT_TXFFLMASK;
return status ? 0 : TIOCSER_TEMT;
}
@@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port)
asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
port->membase + LTQ_ASC_CLC);
- writel(0, port->membase + LTQ_ASC_PISEL);
- writel(
+ __raw_writel(0, port->membase + LTQ_ASC_PISEL);
+ __raw_writel(
((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
port->membase + LTQ_ASC_TXFCON);
- writel(
+ __raw_writel(
((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
| ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
port->membase + LTQ_ASC_RXFCON);
@@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port)
goto err2;
}
- writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+ __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
port->membase + LTQ_ASC_IRNREN);
return 0;
@@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port)
free_irq(ltq_port->rx_irq, port);
free_irq(ltq_port->err_irq, port);
- writel(0, port->membase + LTQ_ASC_CON);
+ __raw_writel(0, port->membase + LTQ_ASC_CON);
asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
port->membase + LTQ_ASC_RXFCON);
asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
@@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port,
asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
/* now we can write the new baudrate into the register */
- writel(divisor, port->membase + LTQ_ASC_BG);
+ __raw_writel(divisor, port->membase + LTQ_ASC_BG);
/* turn the baudrate generator back on */
asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON);
/* enable rx */
- writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+ __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
spin_unlock_irqrestore(&ltq_asc_lock, flags);
@@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch)
return;
do {
- fifofree = (readl(port->membase + LTQ_ASC_FSTAT)
+ fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
& ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
} while (fifofree == 0);
writeb(ch, port->membase + LTQ_ASC_TBUF);
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index d1d73261575b..f4e27d0ad947 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -151,6 +151,8 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
local_irq_restore(flags);
}
+static void lpc32xx_loopback_set(resource_size_t mapbase, int state);
+
static int __init lpc32xx_hsuart_console_setup(struct console *co,
char *options)
{
@@ -170,6 +172,8 @@ static int __init lpc32xx_hsuart_console_setup(struct console *co,
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
+ lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
return uart_set_options(port, co, baud, parity, bits, flow);
}
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 4f479841769a..f5bdde405627 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -248,6 +248,7 @@
struct max310x_devtype {
char name[9];
int nr;
+ u8 mode1;
int (*detect)(struct device *);
void (*power)(struct uart_port *, int);
};
@@ -410,6 +411,7 @@ static void max14830_power(struct uart_port *port, int on)
static const struct max310x_devtype max3107_devtype = {
.name = "MAX3107",
.nr = 1,
+ .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
.detect = max3107_detect,
.power = max310x_power,
};
@@ -417,6 +419,7 @@ static const struct max310x_devtype max3107_devtype = {
static const struct max310x_devtype max3108_devtype = {
.name = "MAX3108",
.nr = 1,
+ .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
.detect = max3108_detect,
.power = max310x_power,
};
@@ -424,6 +427,7 @@ static const struct max310x_devtype max3108_devtype = {
static const struct max310x_devtype max3109_devtype = {
.name = "MAX3109",
.nr = 2,
+ .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
.detect = max3109_detect,
.power = max310x_power,
};
@@ -431,6 +435,7 @@ static const struct max310x_devtype max3109_devtype = {
static const struct max310x_devtype max14830_devtype = {
.name = "MAX14830",
.nr = 4,
+ .mode1 = MAX310X_MODE1_IRQSEL_BIT,
.detect = max14830_detect,
.power = max14830_power,
};
@@ -1197,8 +1202,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
return PTR_ERR(regmap);
/* Alloc port structure */
- s = devm_kzalloc(dev, sizeof(*s) +
- sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL);
+ s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
if (!s) {
dev_err(dev, "Error allocating port structure\n");
return -ENOMEM;
@@ -1258,9 +1262,8 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
MAX310X_BRGDIVLSB_REG + offs, &ret);
} while (ret != 0x01);
- regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs,
- MAX310X_MODE1_AUTOSLEEP_BIT,
- MAX310X_MODE1_AUTOSLEEP_BIT);
+ regmap_write(s->regmap, MAX310X_MODE1_REG + offs,
+ devtype->mode1);
}
uartclk = max310x_set_ref_clk(dev, s, freq, xtal);
@@ -1294,10 +1297,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0);
/* Clear IRQ status register */
max310x_port_read(&s->p[i].port, MAX310X_IRQSTS_REG);
- /* Enable IRQ pin */
- max310x_port_update(&s->p[i].port, MAX310X_MODE1_REG,
- MAX310X_MODE1_IRQSEL_BIT,
- MAX310X_MODE1_IRQSEL_BIT);
/* Initialize queue for start TX */
INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
/* Initialize queue for changing LOOPBACK mode */
@@ -1467,10 +1466,10 @@ static int __init max310x_uart_init(void)
return ret;
#ifdef CONFIG_SPI_MASTER
- spi_register_driver(&max310x_spi_driver);
+ ret = spi_register_driver(&max310x_spi_driver);
#endif
- return 0;
+ return ret;
}
module_init(max310x_uart_init);
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 8a842591b37c..fbc5bc022a39 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -72,7 +72,8 @@
#define AML_UART_BAUD_USE BIT(23)
#define AML_UART_BAUD_XTAL BIT(24)
-#define AML_UART_PORT_NUM 6
+#define AML_UART_PORT_NUM 12
+#define AML_UART_PORT_OFFSET 6
#define AML_UART_DEV_NAME "ttyAML"
@@ -654,10 +655,20 @@ static int meson_uart_probe(struct platform_device *pdev)
struct resource *res_mem, *res_irq;
struct uart_port *port;
int ret = 0;
+ int id = -1;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (pdev->id < 0) {
+ for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
+ if (!meson_ports[id]) {
+ pdev->id = id;
+ break;
+ }
+ }
+ }
+
if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM)
return -EINVAL;
diff --git a/drivers/tty/serial/mps2-uart.c b/drivers/tty/serial/mps2-uart.c
index 9f8f63719126..587b42f754cb 100644
--- a/drivers/tty/serial/mps2-uart.c
+++ b/drivers/tty/serial/mps2-uart.c
@@ -22,6 +22,7 @@
#include <linux/serial_core.h>
#include <linux/tty_flip.h>
#include <linux/types.h>
+#include <linux/idr.h>
#define SERIAL_NAME "ttyMPS"
#define DRIVER_NAME "mps2-uart"
@@ -65,11 +66,14 @@
#define MPS2_MAX_PORTS 3
+#define UART_PORT_COMBINED_IRQ BIT(0)
+
struct mps2_uart_port {
struct uart_port port;
struct clk *clk;
unsigned int tx_irq;
unsigned int rx_irq;
+ unsigned int flags;
};
static inline struct mps2_uart_port *to_mps2_port(struct uart_port *port)
@@ -264,6 +268,20 @@ static irqreturn_t mps2_uart_oerrirq(int irq, void *data)
return handled;
}
+static irqreturn_t mps2_uart_combinedirq(int irq, void *data)
+{
+ if (mps2_uart_rxirq(irq, data) == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ if (mps2_uart_txirq(irq, data) == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ if (mps2_uart_oerrirq(irq, data) == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+
static int mps2_uart_startup(struct uart_port *port)
{
struct mps2_uart_port *mps_port = to_mps2_port(port);
@@ -274,26 +292,37 @@ static int mps2_uart_startup(struct uart_port *port)
mps2_uart_write8(port, control, UARTn_CTRL);
- ret = request_irq(mps_port->rx_irq, mps2_uart_rxirq, 0,
- MAKE_NAME(-rx), mps_port);
- if (ret) {
- dev_err(port->dev, "failed to register rxirq (%d)\n", ret);
- return ret;
- }
+ if (mps_port->flags & UART_PORT_COMBINED_IRQ) {
+ ret = request_irq(port->irq, mps2_uart_combinedirq, 0,
+ MAKE_NAME(-combined), mps_port);
- ret = request_irq(mps_port->tx_irq, mps2_uart_txirq, 0,
- MAKE_NAME(-tx), mps_port);
- if (ret) {
- dev_err(port->dev, "failed to register txirq (%d)\n", ret);
- goto err_free_rxirq;
- }
+ if (ret) {
+ dev_err(port->dev, "failed to register combinedirq (%d)\n", ret);
+ return ret;
+ }
+ } else {
+ ret = request_irq(port->irq, mps2_uart_oerrirq, IRQF_SHARED,
+ MAKE_NAME(-overrun), mps_port);
+
+ if (ret) {
+ dev_err(port->dev, "failed to register oerrirq (%d)\n", ret);
+ return ret;
+ }
+
+ ret = request_irq(mps_port->rx_irq, mps2_uart_rxirq, 0,
+ MAKE_NAME(-rx), mps_port);
+ if (ret) {
+ dev_err(port->dev, "failed to register rxirq (%d)\n", ret);
+ goto err_free_oerrirq;
+ }
- ret = request_irq(port->irq, mps2_uart_oerrirq, IRQF_SHARED,
- MAKE_NAME(-overrun), mps_port);
+ ret = request_irq(mps_port->tx_irq, mps2_uart_txirq, 0,
+ MAKE_NAME(-tx), mps_port);
+ if (ret) {
+ dev_err(port->dev, "failed to register txirq (%d)\n", ret);
+ goto err_free_rxirq;
+ }
- if (ret) {
- dev_err(port->dev, "failed to register oerrirq (%d)\n", ret);
- goto err_free_txirq;
}
control |= UARTn_CTRL_RX_GRP | UARTn_CTRL_TX_GRP;
@@ -302,10 +331,10 @@ static int mps2_uart_startup(struct uart_port *port)
return 0;
-err_free_txirq:
- free_irq(mps_port->tx_irq, mps_port);
err_free_rxirq:
free_irq(mps_port->rx_irq, mps_port);
+err_free_oerrirq:
+ free_irq(port->irq, mps_port);
return ret;
}
@@ -319,8 +348,11 @@ static void mps2_uart_shutdown(struct uart_port *port)
mps2_uart_write8(port, control, UARTn_CTRL);
- free_irq(mps_port->rx_irq, mps_port);
- free_irq(mps_port->tx_irq, mps_port);
+ if (!(mps_port->flags & UART_PORT_COMBINED_IRQ)) {
+ free_irq(mps_port->rx_irq, mps_port);
+ free_irq(mps_port->tx_irq, mps_port);
+ }
+
free_irq(port->irq, mps_port);
}
@@ -397,7 +429,7 @@ static const struct uart_ops mps2_uart_pops = {
.verify_port = mps2_uart_verify_port,
};
-static struct mps2_uart_port mps2_uart_ports[MPS2_MAX_PORTS];
+static DEFINE_IDR(ports_idr);
#ifdef CONFIG_SERIAL_MPS2_UART_CONSOLE
static void mps2_uart_console_putchar(struct uart_port *port, int ch)
@@ -410,7 +442,8 @@ static void mps2_uart_console_putchar(struct uart_port *port, int ch)
static void mps2_uart_console_write(struct console *co, const char *s, unsigned int cnt)
{
- struct uart_port *port = &mps2_uart_ports[co->index].port;
+ struct mps2_uart_port *mps_port = idr_find(&ports_idr, co->index);
+ struct uart_port *port = &mps_port->port;
uart_console_write(port, s, cnt, mps2_uart_console_putchar);
}
@@ -426,7 +459,10 @@ static int mps2_uart_console_setup(struct console *co, char *options)
if (co->index < 0 || co->index >= MPS2_MAX_PORTS)
return -ENODEV;
- mps_port = &mps2_uart_ports[co->index];
+ mps_port = idr_find(&ports_idr, co->index);
+
+ if (!mps_port)
+ return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -487,27 +523,36 @@ static struct uart_driver mps2_uart_driver = {
.cons = MPS2_SERIAL_CONSOLE,
};
-static struct mps2_uart_port *mps2_of_get_port(struct platform_device *pdev)
+static int mps2_of_get_port(struct platform_device *pdev,
+ struct mps2_uart_port *mps_port)
{
struct device_node *np = pdev->dev.of_node;
int id;
if (!np)
- return NULL;
+ return -ENODEV;
id = of_alias_get_id(np, "serial");
+
if (id < 0)
- id = 0;
+ id = idr_alloc_cyclic(&ports_idr, (void *)mps_port, 0, MPS2_MAX_PORTS, GFP_KERNEL);
+ else
+ id = idr_alloc(&ports_idr, (void *)mps_port, id, MPS2_MAX_PORTS, GFP_KERNEL);
- if (WARN_ON(id >= MPS2_MAX_PORTS))
- return NULL;
+ if (id < 0)
+ return id;
+
+ /* Only combined irq is presesnt */
+ if (platform_irq_count(pdev) == 1)
+ mps_port->flags |= UART_PORT_COMBINED_IRQ;
+
+ mps_port->port.line = id;
- mps2_uart_ports[id].port.line = id;
- return &mps2_uart_ports[id];
+ return 0;
}
-static int mps2_init_port(struct mps2_uart_port *mps_port,
- struct platform_device *pdev)
+static int mps2_init_port(struct platform_device *pdev,
+ struct mps2_uart_port *mps_port)
{
struct resource *res;
int ret;
@@ -519,11 +564,6 @@ static int mps2_init_port(struct mps2_uart_port *mps_port,
mps_port->port.mapbase = res->start;
mps_port->port.mapsize = resource_size(res);
-
- mps_port->rx_irq = platform_get_irq(pdev, 0);
- mps_port->tx_irq = platform_get_irq(pdev, 1);
- mps_port->port.irq = platform_get_irq(pdev, 2);
-
mps_port->port.iotype = UPIO_MEM;
mps_port->port.flags = UPF_BOOT_AUTOCONF;
mps_port->port.fifosize = 1;
@@ -542,6 +582,15 @@ static int mps2_init_port(struct mps2_uart_port *mps_port,
clk_disable_unprepare(mps_port->clk);
+
+ if (mps_port->flags & UART_PORT_COMBINED_IRQ) {
+ mps_port->port.irq = platform_get_irq(pdev, 0);
+ } else {
+ mps_port->rx_irq = platform_get_irq(pdev, 0);
+ mps_port->tx_irq = platform_get_irq(pdev, 1);
+ mps_port->port.irq = platform_get_irq(pdev, 2);
+ }
+
return ret;
}
@@ -550,11 +599,16 @@ static int mps2_serial_probe(struct platform_device *pdev)
struct mps2_uart_port *mps_port;
int ret;
- mps_port = mps2_of_get_port(pdev);
- if (!mps_port)
- return -ENODEV;
+ mps_port = devm_kzalloc(&pdev->dev, sizeof(struct mps2_uart_port), GFP_KERNEL);
+
+ if (!mps_port)
+ return -ENOMEM;
+
+ ret = mps2_of_get_port(pdev, mps_port);
+ if (ret)
+ return ret;
- ret = mps2_init_port(mps_port, pdev);
+ ret = mps2_init_port(pdev, mps_port);
if (ret)
return ret;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 736b74fd6623..109096033bb1 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1634,7 +1634,7 @@ static void msm_console_write(struct console *co, const char *s,
__msm_console_write(port, s, count, msm_port->is_uartdm);
}
-static int __init msm_console_setup(struct console *co, char *options)
+static int msm_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 115200;
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index a72d6d9fb983..3bcec1c20219 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -89,7 +89,7 @@
#define DEF_FIFO_DEPTH_WORDS 16
#define DEF_TX_WM 2
#define DEF_FIFO_WIDTH_BITS 32
-#define UART_CONSOLE_RX_WM 2
+#define UART_RX_WM 2
#define MAX_LOOPBACK_CFG 3
#ifdef CONFIG_CONSOLE_POLL
@@ -105,10 +105,6 @@ struct qcom_geni_serial_port {
u32 tx_fifo_depth;
u32 tx_fifo_width;
u32 rx_fifo_depth;
- u32 tx_wm;
- u32 rx_wm;
- u32 rx_rfr;
- enum geni_se_xfer_mode xfer_mode;
bool setup;
int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop);
unsigned int baud;
@@ -225,10 +221,10 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
u32 geni_ios;
- if (uart_console(uport) || !uart_cts_enabled(uport)) {
+ if (uart_console(uport)) {
mctrl |= TIOCM_CTS;
} else {
- geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
+ geni_ios = readl(uport->membase + SE_GENI_IOS);
if (!(geni_ios & IO2_DATA_IN))
mctrl |= TIOCM_CTS;
}
@@ -241,12 +237,12 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
{
u32 uart_manual_rfr = 0;
- if (uart_console(uport) || !uart_cts_enabled(uport))
+ if (uart_console(uport))
return;
if (!(mctrl & TIOCM_RTS))
uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY;
- writel_relaxed(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR);
+ writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR);
}
static const char *qcom_geni_serial_get_type(struct uart_port *uport)
@@ -275,9 +271,6 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
unsigned int fifo_bits;
unsigned long timeout_us = 20000;
- /* Ensure polling is not re-ordered before the prior writes/reads */
- mb();
-
if (uport->private_data) {
port = to_dev_port(uport, uport);
baud = port->baud;
@@ -297,7 +290,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
*/
timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
while (timeout_us) {
- reg = readl_relaxed(uport->membase + offset);
+ reg = readl(uport->membase + offset);
if ((bool)(reg & field) == set)
return true;
udelay(10);
@@ -310,7 +303,7 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
{
u32 m_cmd;
- writel_relaxed(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN);
+ writel(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN);
m_cmd = UART_START_TX << M_OPCODE_SHFT;
writel(m_cmd, uport->membase + SE_GENI_M_CMD0);
}
@@ -323,13 +316,13 @@ static void qcom_geni_serial_poll_tx_done(struct uart_port *uport)
done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_DONE_EN, true);
if (!done) {
- writel_relaxed(M_GENI_CMD_ABORT, uport->membase +
+ writel(M_GENI_CMD_ABORT, uport->membase +
SE_GENI_M_CMD_CTRL_REG);
irq_clear |= M_CMD_ABORT_EN;
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_ABORT_EN, true);
}
- writel_relaxed(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR);
+ writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
static void qcom_geni_serial_abort_rx(struct uart_port *uport)
@@ -339,8 +332,8 @@ static void qcom_geni_serial_abort_rx(struct uart_port *uport)
writel(S_GENI_CMD_ABORT, uport->membase + SE_GENI_S_CMD_CTRL_REG);
qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
S_GENI_CMD_ABORT, false);
- writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
- writel_relaxed(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG);
+ writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
+ writel(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG);
}
#ifdef CONFIG_CONSOLE_POLL
@@ -349,19 +342,13 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
u32 rx_fifo;
u32 status;
- status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS);
- writel_relaxed(status, uport->membase + SE_GENI_M_IRQ_CLEAR);
+ status = readl(uport->membase + SE_GENI_M_IRQ_STATUS);
+ writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR);
- status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS);
- writel_relaxed(status, uport->membase + SE_GENI_S_IRQ_CLEAR);
+ status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
+ writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR);
- /*
- * Ensure the writes to clear interrupts is not re-ordered after
- * reading the data.
- */
- mb();
-
- status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS);
+ status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS);
if (!(status & RX_FIFO_WC_MSK))
return NO_POLL_CHAR;
@@ -372,15 +359,12 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
unsigned char c)
{
- struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
-
- writel_relaxed(port->tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG);
+ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
qcom_geni_serial_setup_tx(uport, 1);
WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_TX_FIFO_WATERMARK_EN, true));
- writel_relaxed(c, uport->membase + SE_GENI_TX_FIFOn);
- writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase +
- SE_GENI_M_IRQ_CLEAR);
+ writel(c, uport->membase + SE_GENI_TX_FIFOn);
+ writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_poll_tx_done(uport);
}
#endif
@@ -388,7 +372,7 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch)
{
- writel_relaxed(ch, uport->membase + SE_GENI_TX_FIFOn);
+ writel(ch, uport->membase + SE_GENI_TX_FIFOn);
}
static void
@@ -407,7 +391,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
bytes_to_send++;
}
- writel_relaxed(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
+ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
qcom_geni_serial_setup_tx(uport, bytes_to_send);
for (i = 0; i < count; ) {
size_t chars_to_write = 0;
@@ -425,7 +409,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
chars_to_write = min_t(size_t, count - i, avail / 2);
uart_console_write(uport, s + i, chars_to_write,
qcom_geni_serial_wr_char);
- writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase +
+ writel(M_TX_FIFO_WATERMARK_EN, uport->membase +
SE_GENI_M_IRQ_CLEAR);
i += chars_to_write;
}
@@ -454,7 +438,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
else
spin_lock_irqsave(&uport->lock, flags);
- geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS);
+ geni_status = readl(uport->membase + SE_GENI_STATUS);
/* Cancel the current write to log the fault */
if (!locked) {
@@ -464,11 +448,10 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
geni_se_abort_m_cmd(&port->se);
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_ABORT_EN, true);
- writel_relaxed(M_CMD_ABORT_EN, uport->membase +
+ writel(M_CMD_ABORT_EN, uport->membase +
SE_GENI_M_IRQ_CLEAR);
}
- writel_relaxed(M_CMD_CANCEL_EN, uport->membase +
- SE_GENI_M_IRQ_CLEAR);
+ writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
} else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) {
/*
* It seems we can't interrupt existing transfers if all data
@@ -477,9 +460,8 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
qcom_geni_serial_poll_tx_done(uport);
if (uart_circ_chars_pending(&uport->state->xmit)) {
- irq_en = readl_relaxed(uport->membase +
- SE_GENI_M_IRQ_EN);
- writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN,
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
}
}
@@ -567,29 +549,20 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
static void qcom_geni_serial_start_tx(struct uart_port *uport)
{
u32 irq_en;
- struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
u32 status;
- if (port->xfer_mode == GENI_SE_FIFO) {
- /*
- * readl ensures reading & writing of IRQ_EN register
- * is not re-ordered before checking the status of the
- * Serial Engine.
- */
- status = readl(uport->membase + SE_GENI_STATUS);
- if (status & M_GENI_CMD_ACTIVE)
- return;
+ status = readl(uport->membase + SE_GENI_STATUS);
+ if (status & M_GENI_CMD_ACTIVE)
+ return;
- if (!qcom_geni_serial_tx_empty(uport))
- return;
+ if (!qcom_geni_serial_tx_empty(uport))
+ return;
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
- irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
- writel_relaxed(port->tx_wm, uport->membase +
- SE_GENI_TX_WATERMARK_REG);
- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- }
+ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
+ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
}
static void qcom_geni_serial_stop_tx(struct uart_port *uport)
@@ -598,35 +571,24 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport)
u32 status;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
- irq_en &= ~M_CMD_DONE_EN;
- if (port->xfer_mode == GENI_SE_FIFO) {
- irq_en &= ~M_TX_FIFO_WATERMARK_EN;
- writel_relaxed(0, uport->membase +
- SE_GENI_TX_WATERMARK_REG);
- }
- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- status = readl_relaxed(uport->membase + SE_GENI_STATUS);
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
+ writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG);
+ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
+ status = readl(uport->membase + SE_GENI_STATUS);
/* Possible stop tx is called multiple times. */
if (!(status & M_GENI_CMD_ACTIVE))
return;
- /*
- * Ensure cancel command write is not re-ordered before checking
- * the status of the Primary Sequencer.
- */
- mb();
-
geni_se_cancel_m_cmd(&port->se);
if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_CANCEL_EN, true)) {
geni_se_abort_m_cmd(&port->se);
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_ABORT_EN, true);
- writel_relaxed(M_CMD_ABORT_EN, uport->membase +
- SE_GENI_M_IRQ_CLEAR);
+ writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
- writel_relaxed(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
+ writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
static void qcom_geni_serial_start_rx(struct uart_port *uport)
@@ -635,27 +597,19 @@ static void qcom_geni_serial_start_rx(struct uart_port *uport)
u32 status;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
- status = readl_relaxed(uport->membase + SE_GENI_STATUS);
+ status = readl(uport->membase + SE_GENI_STATUS);
if (status & S_GENI_CMD_ACTIVE)
qcom_geni_serial_stop_rx(uport);
- /*
- * Ensure setup command write is not re-ordered before checking
- * the status of the Secondary Sequencer.
- */
- mb();
-
geni_se_setup_s_cmd(&port->se, UART_START_READ, 0);
- if (port->xfer_mode == GENI_SE_FIFO) {
- irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN);
- irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
- writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN);
+ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
+ irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
+ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN);
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
- irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- }
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
+ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
}
static void qcom_geni_serial_stop_rx(struct uart_port *uport)
@@ -665,32 +619,24 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
u32 irq_clear = S_CMD_DONE_EN;
- if (port->xfer_mode == GENI_SE_FIFO) {
- irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN);
- irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
- writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN);
+ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
+ irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
+ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN);
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
- irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- }
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- status = readl_relaxed(uport->membase + SE_GENI_STATUS);
+ status = readl(uport->membase + SE_GENI_STATUS);
/* Possible stop rx is called multiple times. */
if (!(status & S_GENI_CMD_ACTIVE))
return;
- /*
- * Ensure cancel command write is not re-ordered before checking
- * the status of the Secondary Sequencer.
- */
- mb();
-
geni_se_cancel_s_cmd(&port->se);
qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
S_GENI_CMD_CANCEL, false);
- status = readl_relaxed(uport->membase + SE_GENI_STATUS);
- writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
+ status = readl(uport->membase + SE_GENI_STATUS);
+ writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
if (status & S_GENI_CMD_ACTIVE)
qcom_geni_serial_abort_rx(uport);
}
@@ -704,7 +650,7 @@ static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop)
u32 total_bytes;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
- status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS);
+ status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS);
word_cnt = status & RX_FIFO_WC_MSK;
last_word_partial = status & RX_LAST;
last_word_byte_cnt = (status & RX_LAST_BYTE_VALID_MSK) >>
@@ -734,7 +680,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
unsigned int chunk;
int tail;
- status = readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS);
+ status = readl(uport->membase + SE_GENI_TX_FIFO_STATUS);
/* Complete the current tx command before taking newly added data */
if (active)
@@ -760,9 +706,9 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
qcom_geni_serial_setup_tx(uport, pending);
port->tx_remaining = pending;
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
- writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN,
+ writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
}
@@ -795,14 +741,14 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
* cleared it in qcom_geni_serial_isr it will have already reasserted
* so we must clear it again here after our writes.
*/
- writel_relaxed(M_TX_FIFO_WATERMARK_EN,
+ writel(M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_CLEAR);
out_write_wakeup:
if (!port->tx_remaining) {
- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
+ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
if (irq_en & M_TX_FIFO_WATERMARK_EN)
- writel_relaxed(irq_en & ~M_TX_FIFO_WATERMARK_EN,
+ writel(irq_en & ~M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
}
@@ -812,12 +758,12 @@ out_write_wakeup:
static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
{
- unsigned int m_irq_status;
- unsigned int s_irq_status;
- unsigned int geni_status;
+ u32 m_irq_en;
+ u32 m_irq_status;
+ u32 s_irq_status;
+ u32 geni_status;
struct uart_port *uport = dev;
unsigned long flags;
- unsigned int m_irq_en;
bool drop_rx = false;
struct tty_port *tport = &uport->state->port;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
@@ -826,12 +772,12 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
return IRQ_NONE;
spin_lock_irqsave(&uport->lock, flags);
- m_irq_status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS);
- s_irq_status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS);
- geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS);
- m_irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
- writel_relaxed(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR);
- writel_relaxed(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
+ m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS);
+ s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
+ geni_status = readl(uport->membase + SE_GENI_STATUS);
+ m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+ writel(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR);
+ writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
if (WARN_ON(m_irq_status & M_ILLEGAL_CMD_EN))
goto out_unlock;
@@ -877,17 +823,6 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
(port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;
}
-static void set_rfr_wm(struct qcom_geni_serial_port *port)
-{
- /*
- * Set RFR (Flow off) to FIFO_DEPTH - 2.
- * RX WM level at 10% RX_FIFO_DEPTH.
- * TX WM level at 10% TX_FIFO_DEPTH.
- */
- port->rx_rfr = port->rx_fifo_depth - 2;
- port->rx_wm = UART_CONSOLE_RX_WM;
- port->tx_wm = DEF_TX_WM;
-}
static void qcom_geni_serial_shutdown(struct uart_port *uport)
{
@@ -907,7 +842,7 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
static int qcom_geni_serial_port_setup(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
- unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
+ u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
u32 proto;
if (uart_console(uport)) {
@@ -928,21 +863,19 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
get_tx_fifo_size(port);
- set_rfr_wm(port);
- writel_relaxed(rxstale, uport->membase + SE_UART_RX_STALE_CNT);
+ writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT);
/*
* Make an unconditional cancel on the main sequencer to reset
* it else we could end up in data loss scenarios.
*/
- port->xfer_mode = GENI_SE_FIFO;
if (uart_console(uport))
qcom_geni_serial_poll_tx_done(uport);
geni_se_config_packing(&port->se, BITS_PER_BYTE, port->tx_bytes_pw,
false, true, false);
geni_se_config_packing(&port->se, BITS_PER_BYTE, port->rx_bytes_pw,
false, false, true);
- geni_se_init(&port->se, port->rx_wm, port->rx_rfr);
- geni_se_select_mode(&port->se, port->xfer_mode);
+ geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2);
+ geni_se_select_mode(&port->se, GENI_SE_FIFO);
if (!uart_console(uport)) {
port->rx_fifo = devm_kcalloc(uport->dev,
port->rx_fifo_depth, sizeof(u32), GFP_KERNEL);
@@ -1008,14 +941,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
struct ktermios *termios, struct ktermios *old)
{
unsigned int baud;
- unsigned int bits_per_char;
- unsigned int tx_trans_cfg;
- unsigned int tx_parity_cfg;
- unsigned int rx_trans_cfg;
- unsigned int rx_parity_cfg;
- unsigned int stop_bit_len;
+ u32 bits_per_char;
+ u32 tx_trans_cfg;
+ u32 tx_parity_cfg;
+ u32 rx_trans_cfg;
+ u32 rx_parity_cfg;
+ u32 stop_bit_len;
unsigned int clk_div;
- unsigned long ser_clk_cfg;
+ u32 ser_clk_cfg;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
unsigned long clk_rate;
@@ -1033,10 +966,10 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
/* parity */
- tx_trans_cfg = readl_relaxed(uport->membase + SE_UART_TX_TRANS_CFG);
- tx_parity_cfg = readl_relaxed(uport->membase + SE_UART_TX_PARITY_CFG);
- rx_trans_cfg = readl_relaxed(uport->membase + SE_UART_RX_TRANS_CFG);
- rx_parity_cfg = readl_relaxed(uport->membase + SE_UART_RX_PARITY_CFG);
+ tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG);
+ tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG);
+ rx_trans_cfg = readl(uport->membase + SE_UART_RX_TRANS_CFG);
+ rx_parity_cfg = readl(uport->membase + SE_UART_RX_PARITY_CFG);
if (termios->c_cflag & PARENB) {
tx_trans_cfg |= UART_TX_PAR_EN;
rx_trans_cfg |= UART_RX_PAR_EN;
@@ -1092,17 +1025,17 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
uart_update_timeout(uport, termios->c_cflag, baud);
if (!uart_console(uport))
- writel_relaxed(port->loopback,
+ writel(port->loopback,
uport->membase + SE_UART_LOOPBACK_CFG);
- writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
- writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
- writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG);
- writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG);
- writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
- writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
- writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
- writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG);
- writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG);
+ writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
+ writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
+ writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG);
+ writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG);
+ writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
+ writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
+ writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
+ writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG);
+ writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG);
out_restart_rx:
qcom_geni_serial_start_rx(uport);
}
@@ -1193,13 +1126,13 @@ static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev,
geni_se_init(&se, DEF_FIFO_DEPTH_WORDS / 2, DEF_FIFO_DEPTH_WORDS - 2);
geni_se_select_mode(&se, GENI_SE_FIFO);
- writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
- writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
- writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG);
- writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG);
- writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
- writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
- writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
+ writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
+ writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
+ writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG);
+ writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG);
+ writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
+ writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
+ writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
dev->con->write = qcom_geni_serial_earlycon_write;
dev->con->setup = NULL;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 9fc3559f80d9..83fd51607741 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1694,6 +1694,42 @@ s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
}
#endif
+static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
+{
+ struct device *dev = ourport->port.dev;
+ struct s3c24xx_uart_info *info = ourport->info;
+ char clk_name[MAX_CLK_NAME_LENGTH];
+ unsigned int clk_sel;
+ struct clk *clk;
+ int clk_num;
+ int ret;
+
+ clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel;
+ for (clk_num = 0; clk_num < info->num_clks; clk_num++) {
+ if (!(clk_sel & (1 << clk_num)))
+ continue;
+
+ sprintf(clk_name, "clk_uart_baud%d", clk_num);
+ clk = clk_get(dev, clk_name);
+ if (IS_ERR(clk))
+ continue;
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ clk_put(clk);
+ continue;
+ }
+
+ ourport->baudclk = clk;
+ ourport->baudclk_rate = clk_get_rate(clk);
+ s3c24xx_serial_setsource(&ourport->port, clk_num);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
/* s3c24xx_serial_init_port
*
* initialise a single serial port from the platform device given
@@ -1788,6 +1824,10 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
goto err;
}
+ ret = s3c24xx_serial_enable_baudclk(ourport);
+ if (ret)
+ pr_warn("uart: failed to enable baudclk\n");
+
/* Keep all interrupts masked and cleared */
if (s3c24xx_serial_has_interrupt_mask(port)) {
wr_regl(port, S3C64XX_UINTM, 0xf);
@@ -1901,6 +1941,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
* and keeps the clock enabled in this case.
*/
clk_disable_unprepare(ourport->clk);
+ if (!IS_ERR(ourport->baudclk))
+ clk_disable_unprepare(ourport->baudclk);
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 268098681856..635178cf3eed 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1187,9 +1187,7 @@ static int sc16is7xx_probe(struct device *dev,
return PTR_ERR(regmap);
/* Alloc port structure */
- s = devm_kzalloc(dev, sizeof(*s) +
- sizeof(struct sc16is7xx_one) * devtype->nr_uart,
- GFP_KERNEL);
+ s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);
if (!s) {
dev_err(dev, "Error allocating port structure\n");
return -ENOMEM;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d4cca5bdaf1c..351843f847c0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -130,6 +130,9 @@ static void uart_start(struct tty_struct *tty)
struct uart_port *port;
unsigned long flags;
+ if (!state)
+ return;
+
port = uart_port_lock(state, flags);
__uart_start(tty);
uart_port_unlock(port, flags);
@@ -550,10 +553,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
int ret = 0;
circ = &state->xmit;
- if (!circ->buf)
+ port = uart_port_lock(state, flags);
+ if (!circ->buf) {
+ uart_port_unlock(port, flags);
return 0;
+ }
- port = uart_port_lock(state, flags);
if (port && uart_circ_chars_free(circ) != 0) {
circ->buf[circ->head] = c;
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -586,11 +591,13 @@ static int uart_write(struct tty_struct *tty,
return -EL3HLT;
}
+ port = uart_port_lock(state, flags);
circ = &state->xmit;
- if (!circ->buf)
+ if (!circ->buf) {
+ uart_port_unlock(port, flags);
return 0;
+ }
- port = uart_port_lock(state, flags);
while (port) {
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
if (count < c)
@@ -723,6 +730,9 @@ static void uart_unthrottle(struct tty_struct *tty)
upstat_t mask = UPSTAT_SYNC_FIFO;
struct uart_port *port;
+ if (!state)
+ return;
+
port = uart_port_ref(state);
if (!port)
return;
@@ -2834,7 +2844,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
*/
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))) {
+ if (!IS_ERR(tty_dev)) {
device_set_wakeup_capable(tty_dev, 1);
} else {
dev_err(uport->dev, "Cannot register tty device on line %d\n",
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 8df0fd824520..060fcd42b6d5 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1243,12 +1243,22 @@ static int sci_dma_rx_find_active(struct sci_port *s)
return -1;
}
-static void sci_rx_dma_release(struct sci_port *s)
+static void sci_dma_rx_chan_invalidate(struct sci_port *s)
+{
+ unsigned int i;
+
+ s->chan_rx = NULL;
+ for (i = 0; i < ARRAY_SIZE(s->cookie_rx); i++)
+ s->cookie_rx[i] = -EINVAL;
+ s->active_rx = 0;
+}
+
+static void sci_dma_rx_release(struct sci_port *s)
{
struct dma_chan *chan = s->chan_rx_saved;
- s->chan_rx_saved = s->chan_rx = NULL;
- s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
+ s->chan_rx_saved = NULL;
+ sci_dma_rx_chan_invalidate(s);
dmaengine_terminate_sync(chan);
dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
sg_dma_address(&s->sg_rx[0]));
@@ -1264,6 +1274,20 @@ static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
hrtimer_start(hrt, t, HRTIMER_MODE_REL);
}
+static void sci_dma_rx_reenable_irq(struct sci_port *s)
+{
+ struct uart_port *port = &s->port;
+ u16 scr;
+
+ /* Direct new serial port interrupts back to CPU */
+ scr = serial_port_in(port, SCSCR);
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ scr &= ~SCSCR_RDRQE;
+ enable_irq(s->irqs[SCIx_RXI_IRQ]);
+ }
+ serial_port_out(port, SCSCR, scr | SCSCR_RIE);
+}
+
static void sci_dma_rx_complete(void *arg)
{
struct sci_port *s = arg;
@@ -1313,12 +1337,13 @@ fail:
dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
/* Switch to PIO */
spin_lock_irqsave(&port->lock, flags);
- s->chan_rx = NULL;
- sci_start_rx(port);
+ dmaengine_terminate_async(chan);
+ sci_dma_rx_chan_invalidate(s);
+ sci_dma_rx_reenable_irq(s);
spin_unlock_irqrestore(&port->lock, flags);
}
-static void sci_tx_dma_release(struct sci_port *s)
+static void sci_dma_tx_release(struct sci_port *s)
{
struct dma_chan *chan = s->chan_tx_saved;
@@ -1331,7 +1356,7 @@ static void sci_tx_dma_release(struct sci_port *s)
dma_release_channel(chan);
}
-static int sci_submit_rx(struct sci_port *s, bool port_lock_held)
+static int sci_dma_rx_submit(struct sci_port *s, bool port_lock_held)
{
struct dma_chan *chan = s->chan_rx;
struct uart_port *port = &s->port;
@@ -1367,17 +1392,14 @@ fail:
spin_lock_irqsave(&port->lock, flags);
if (i)
dmaengine_terminate_async(chan);
- for (i = 0; i < 2; i++)
- s->cookie_rx[i] = -EINVAL;
- s->active_rx = 0;
- s->chan_rx = NULL;
+ sci_dma_rx_chan_invalidate(s);
sci_start_rx(port);
if (!port_lock_held)
spin_unlock_irqrestore(&port->lock, flags);
return -EAGAIN;
}
-static void work_fn_tx(struct work_struct *work)
+static void sci_dma_tx_work_fn(struct work_struct *work)
{
struct sci_port *s = container_of(work, struct sci_port, work_tx);
struct dma_async_tx_descriptor *desc;
@@ -1436,7 +1458,7 @@ switch_to_pio:
return;
}
-static enum hrtimer_restart rx_timer_fn(struct hrtimer *t)
+static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t)
{
struct sci_port *s = container_of(t, struct sci_port, rx_timer);
struct dma_chan *chan = s->chan_rx;
@@ -1446,7 +1468,6 @@ static enum hrtimer_restart rx_timer_fn(struct hrtimer *t)
unsigned long flags;
unsigned int read;
int active, count;
- u16 scr;
dev_dbg(port->dev, "DMA Rx timed out\n");
@@ -1494,15 +1515,9 @@ static enum hrtimer_restart rx_timer_fn(struct hrtimer *t)
}
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- sci_submit_rx(s, true);
+ sci_dma_rx_submit(s, true);
- /* Direct new serial port interrupts back to CPU */
- scr = serial_port_in(port, SCSCR);
- if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- scr &= ~SCSCR_RDRQE;
- enable_irq(s->irqs[SCIx_RXI_IRQ]);
- }
- serial_port_out(port, SCSCR, scr | SCSCR_RIE);
+ sci_dma_rx_reenable_irq(s);
spin_unlock_irqrestore(&port->lock, flags);
@@ -1580,7 +1595,7 @@ static void sci_request_dma(struct uart_port *port)
__func__, UART_XMIT_SIZE,
port->state->xmit.buf, &s->tx_dma_addr);
- INIT_WORK(&s->work_tx, work_fn_tx);
+ INIT_WORK(&s->work_tx, sci_dma_tx_work_fn);
s->chan_tx_saved = s->chan_tx = chan;
}
}
@@ -1615,12 +1630,12 @@ static void sci_request_dma(struct uart_port *port)
}
hrtimer_init(&s->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- s->rx_timer.function = rx_timer_fn;
+ s->rx_timer.function = sci_dma_rx_timer_fn;
s->chan_rx_saved = s->chan_rx = chan;
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
- sci_submit_rx(s, false);
+ sci_dma_rx_submit(s, false);
}
}
@@ -1629,9 +1644,9 @@ static void sci_free_dma(struct uart_port *port)
struct sci_port *s = to_sci_port(port);
if (s->chan_tx_saved)
- sci_tx_dma_release(s);
+ sci_dma_tx_release(s);
if (s->chan_rx_saved)
- sci_rx_dma_release(s);
+ sci_dma_rx_release(s);
}
static void sci_flush_buffer(struct uart_port *port)
@@ -1669,7 +1684,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
disable_irq_nosync(irq);
scr |= SCSCR_RDRQE;
} else {
- if (sci_submit_rx(s, false) < 0)
+ if (sci_dma_rx_submit(s, false) < 0)
goto handle_pio;
scr &= ~SCSCR_RIE;
@@ -1921,7 +1936,7 @@ out_nomem:
static void sci_free_irq(struct sci_port *port)
{
- int i;
+ int i, j;
/*
* Intentionally in reverse order so we iterate over the muxed
@@ -1937,6 +1952,13 @@ static void sci_free_irq(struct sci_port *port)
if (unlikely(irq < 0))
continue;
+ /* Check if already freed (irq was muxed) */
+ for (j = 0; j < i; j++)
+ if (port->irqs[j] == irq)
+ j = i + 1;
+ if (j > i)
+ continue;
+
free_irq(port->irqs[i], port);
kfree(port->irqstr[i]);
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 4287ca305b6b..1891a45ac05d 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -371,7 +371,7 @@ static void sprd_set_termios(struct uart_port *port,
/* ask the core to calculate the divisor for us */
baud = uart_get_baud_rate(port, termios, old, 0, SPRD_BAUD_IO_LIMIT);
- quot = (unsigned int)((port->uartclk + baud / 2) / baud);
+ quot = port->uartclk / baud;
/* set data length */
switch (termios->c_cflag & CSIZE) {
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
new file mode 100644
index 000000000000..aaf8748a6147
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <linux/console.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#define TCU_MBOX_BYTE(i, x) ((x) << (i * 8))
+#define TCU_MBOX_BYTE_V(x, i) (((x) >> (i * 8)) & 0xff)
+#define TCU_MBOX_NUM_BYTES(x) ((x) << 24)
+#define TCU_MBOX_NUM_BYTES_V(x) (((x) >> 24) & 0x3)
+
+struct tegra_tcu {
+ struct uart_driver driver;
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+ struct console console;
+#endif
+ struct uart_port port;
+
+ struct mbox_client tx_client, rx_client;
+ struct mbox_chan *tx, *rx;
+};
+
+static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port)
+{
+ return TIOCSER_TEMT;
+}
+
+static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port)
+{
+ return 0;
+}
+
+static void tegra_tcu_uart_stop_tx(struct uart_port *port)
+{
+}
+
+static void tegra_tcu_write_one(struct tegra_tcu *tcu, u32 value,
+ unsigned int count)
+{
+ void *msg;
+
+ value |= TCU_MBOX_NUM_BYTES(count);
+ msg = (void *)(unsigned long)value;
+ mbox_send_message(tcu->tx, msg);
+ mbox_flush(tcu->tx, 1000);
+}
+
+static void tegra_tcu_write(struct tegra_tcu *tcu, const char *s,
+ unsigned int count)
+{
+ unsigned int written = 0, i = 0;
+ bool insert_nl = false;
+ u32 value = 0;
+
+ while (i < count) {
+ if (insert_nl) {
+ value |= TCU_MBOX_BYTE(written++, '\n');
+ insert_nl = false;
+ i++;
+ } else if (s[i] == '\n') {
+ value |= TCU_MBOX_BYTE(written++, '\r');
+ insert_nl = true;
+ } else {
+ value |= TCU_MBOX_BYTE(written++, s[i++]);
+ }
+
+ if (written == 3) {
+ tegra_tcu_write_one(tcu, value, 3);
+ value = written = 0;
+ }
+ }
+
+ if (written)
+ tegra_tcu_write_one(tcu, value, written);
+}
+
+static void tegra_tcu_uart_start_tx(struct uart_port *port)
+{
+ struct tegra_tcu *tcu = port->private_data;
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned long count;
+
+ for (;;) {
+ count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ if (!count)
+ break;
+
+ tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count);
+ xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+ }
+
+ uart_write_wakeup(port);
+}
+
+static void tegra_tcu_uart_stop_rx(struct uart_port *port)
+{
+}
+
+static void tegra_tcu_uart_break_ctl(struct uart_port *port, int ctl)
+{
+}
+
+static int tegra_tcu_uart_startup(struct uart_port *port)
+{
+ return 0;
+}
+
+static void tegra_tcu_uart_shutdown(struct uart_port *port)
+{
+}
+
+static void tegra_tcu_uart_set_termios(struct uart_port *port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+}
+
+static const struct uart_ops tegra_tcu_uart_ops = {
+ .tx_empty = tegra_tcu_uart_tx_empty,
+ .set_mctrl = tegra_tcu_uart_set_mctrl,
+ .get_mctrl = tegra_tcu_uart_get_mctrl,
+ .stop_tx = tegra_tcu_uart_stop_tx,
+ .start_tx = tegra_tcu_uart_start_tx,
+ .stop_rx = tegra_tcu_uart_stop_rx,
+ .break_ctl = tegra_tcu_uart_break_ctl,
+ .startup = tegra_tcu_uart_startup,
+ .shutdown = tegra_tcu_uart_shutdown,
+ .set_termios = tegra_tcu_uart_set_termios,
+};
+
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+static void tegra_tcu_console_write(struct console *cons, const char *s,
+ unsigned int count)
+{
+ struct tegra_tcu *tcu = container_of(cons, struct tegra_tcu, console);
+
+ tegra_tcu_write(tcu, s, count);
+}
+
+static int tegra_tcu_console_setup(struct console *cons, char *options)
+{
+ return 0;
+}
+#endif
+
+static void tegra_tcu_receive(struct mbox_client *cl, void *msg)
+{
+ struct tegra_tcu *tcu = container_of(cl, struct tegra_tcu, rx_client);
+ struct tty_port *port = &tcu->port.state->port;
+ u32 value = (u32)(unsigned long)msg;
+ unsigned int num_bytes, i;
+
+ num_bytes = TCU_MBOX_NUM_BYTES_V(value);
+
+ for (i = 0; i < num_bytes; i++)
+ tty_insert_flip_char(port, TCU_MBOX_BYTE_V(value, i),
+ TTY_NORMAL);
+
+ tty_flip_buffer_push(port);
+}
+
+static int tegra_tcu_probe(struct platform_device *pdev)
+{
+ struct uart_port *port;
+ struct tegra_tcu *tcu;
+ int err;
+
+ tcu = devm_kzalloc(&pdev->dev, sizeof(*tcu), GFP_KERNEL);
+ if (!tcu)
+ return -ENOMEM;
+
+ tcu->tx_client.dev = &pdev->dev;
+ tcu->rx_client.dev = &pdev->dev;
+ tcu->rx_client.rx_callback = tegra_tcu_receive;
+
+ tcu->tx = mbox_request_channel_byname(&tcu->tx_client, "tx");
+ if (IS_ERR(tcu->tx)) {
+ err = PTR_ERR(tcu->tx);
+ dev_err(&pdev->dev, "failed to get tx mailbox: %d\n", err);
+ return err;
+ }
+
+ tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx");
+ if (IS_ERR(tcu->rx)) {
+ err = PTR_ERR(tcu->rx);
+ dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err);
+ goto free_tx;
+ }
+
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+ /* setup the console */
+ strcpy(tcu->console.name, "ttyTCU");
+ tcu->console.device = uart_console_device;
+ tcu->console.flags = CON_PRINTBUFFER | CON_ANYTIME;
+ tcu->console.index = -1;
+ tcu->console.write = tegra_tcu_console_write;
+ tcu->console.setup = tegra_tcu_console_setup;
+ tcu->console.data = &tcu->driver;
+#endif
+
+ /* setup the driver */
+ tcu->driver.owner = THIS_MODULE;
+ tcu->driver.driver_name = "tegra-tcu";
+ tcu->driver.dev_name = "ttyTCU";
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+ tcu->driver.cons = &tcu->console;
+#endif
+ tcu->driver.nr = 1;
+
+ err = uart_register_driver(&tcu->driver);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register UART driver: %d\n",
+ err);
+ goto free_rx;
+ }
+
+ /* setup the port */
+ port = &tcu->port;
+ spin_lock_init(&port->lock);
+ port->dev = &pdev->dev;
+ port->type = PORT_TEGRA_TCU;
+ port->ops = &tegra_tcu_uart_ops;
+ port->fifosize = 1;
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->private_data = tcu;
+
+ err = uart_add_one_port(&tcu->driver, port);
+ if (err) {
+ dev_err(&pdev->dev, "failed to add UART port: %d\n", err);
+ goto unregister_uart;
+ }
+
+ platform_set_drvdata(pdev, tcu);
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+ register_console(&tcu->console);
+#endif
+
+ return 0;
+
+unregister_uart:
+ uart_unregister_driver(&tcu->driver);
+free_rx:
+ mbox_free_channel(tcu->rx);
+free_tx:
+ mbox_free_channel(tcu->tx);
+
+ return err;
+}
+
+static int tegra_tcu_remove(struct platform_device *pdev)
+{
+ struct tegra_tcu *tcu = platform_get_drvdata(pdev);
+
+#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
+ unregister_console(&tcu->console);
+#endif
+ uart_remove_one_port(&tcu->driver, &tcu->port);
+ uart_unregister_driver(&tcu->driver);
+ mbox_free_channel(tcu->rx);
+ mbox_free_channel(tcu->tx);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_tcu_match[] = {
+ { .compatible = "nvidia,tegra194-tcu" },
+ { }
+};
+
+static struct platform_driver tegra_tcu_driver = {
+ .driver = {
+ .name = "tegra-tcu",
+ .of_match_table = tegra_tcu_match,
+ },
+ .probe = tegra_tcu_probe,
+ .remove = tegra_tcu_remove,
+};
+module_platform_driver(tegra_tcu_driver);
+
+MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver");
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 094f2958cb2b..74089f5e5b53 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -364,7 +364,13 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
cdns_uart_handle_tx(dev_id);
isrstatus &= ~CDNS_UART_IXR_TXEMPTY;
}
- if (isrstatus & CDNS_UART_IXR_RXMASK)
+
+ /*
+ * Skip RX processing if RX is disabled as RXEMPTY will never be set
+ * as read bytes will not be removed from the FIFO.
+ */
+ if (isrstatus & CDNS_UART_IXR_RXMASK &&
+ !(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS))
cdns_uart_handle_rx(dev_id, isrstatus);
spin_unlock(&port->lock);
@@ -1547,27 +1553,33 @@ static int cdns_uart_probe(struct platform_device *pdev)
}
cdns_uart_data->pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (PTR_ERR(cdns_uart_data->pclk) == -EPROBE_DEFER) {
+ rc = PTR_ERR(cdns_uart_data->pclk);
+ goto err_out_unregister_driver;
+ }
+
if (IS_ERR(cdns_uart_data->pclk)) {
cdns_uart_data->pclk = devm_clk_get(&pdev->dev, "aper_clk");
- if (!IS_ERR(cdns_uart_data->pclk))
- dev_err(&pdev->dev, "clock name 'aper_clk' is deprecated.\n");
+ if (IS_ERR(cdns_uart_data->pclk)) {
+ rc = PTR_ERR(cdns_uart_data->pclk);
+ goto err_out_unregister_driver;
+ }
+ dev_err(&pdev->dev, "clock name 'aper_clk' is deprecated.\n");
}
- if (IS_ERR(cdns_uart_data->pclk)) {
- dev_err(&pdev->dev, "pclk clock not found.\n");
- rc = PTR_ERR(cdns_uart_data->pclk);
+
+ cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "uart_clk");
+ if (PTR_ERR(cdns_uart_data->uartclk) == -EPROBE_DEFER) {
+ rc = PTR_ERR(cdns_uart_data->uartclk);
goto err_out_unregister_driver;
}
- cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "uart_clk");
if (IS_ERR(cdns_uart_data->uartclk)) {
cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "ref_clk");
- if (!IS_ERR(cdns_uart_data->uartclk))
- dev_err(&pdev->dev, "clock name 'ref_clk' is deprecated.\n");
- }
- if (IS_ERR(cdns_uart_data->uartclk)) {
- dev_err(&pdev->dev, "uart_clk clock not found.\n");
- rc = PTR_ERR(cdns_uart_data->uartclk);
- goto err_out_unregister_driver;
+ if (IS_ERR(cdns_uart_data->uartclk)) {
+ rc = PTR_ERR(cdns_uart_data->uartclk);
+ goto err_out_unregister_driver;
+ }
+ dev_err(&pdev->dev, "clock name 'ref_clk' is deprecated.\n");
}
rc = clk_prepare_enable(cdns_uart_data->pclk);
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index d55c858d6058..84f26e43b229 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -4325,41 +4325,6 @@ static int mgsl_init_tty(void)
return 0;
}
-/* enumerate user specified ISA adapters
- */
-static void mgsl_enum_isa_devices(void)
-{
- struct mgsl_struct *info;
- int i;
-
- /* Check for user specified ISA devices */
-
- for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
- io[i], irq[i], dma[i] );
-
- info = mgsl_allocate_device();
- if ( !info ) {
- /* error allocating device instance data */
- if ( debug_level >= DEBUG_LEVEL_ERROR )
- printk( "can't allocate device instance data.\n");
- continue;
- }
-
- /* Copy user configuration info to device instance data */
- info->io_base = (unsigned int)io[i];
- info->irq_level = (unsigned int)irq[i];
- info->irq_level = irq_canonicalize(info->irq_level);
- info->dma_level = (unsigned int)dma[i];
- info->bus_type = MGSL_BUS_TYPE_ISA;
- info->io_addr_size = 16;
- info->irq_flags = 0;
-
- mgsl_add_device( info );
- }
-}
-
static void synclink_cleanup(void)
{
int rc;
@@ -4403,7 +4368,6 @@ static int __init synclink_init(void)
printk("%s %s\n", driver_name, driver_version);
- mgsl_enum_isa_devices();
if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
else
@@ -5025,12 +4989,6 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
info->mbre_bit = BIT8;
outw( BIT8, info->io_base ); /* set Master Bus Enable (DCAR) */
- if (info->bus_type == MGSL_BUS_TYPE_ISA) {
- /* Enable DMAEN (Port 7, Bit 14) */
- /* This connects the DMA request signal to the ISA bus */
- usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
- }
-
/* DMA Control Register (DCR)
*
* <15..14> 10 Priority mode = Alternating Tx/Rx
@@ -6007,12 +5965,6 @@ static void usc_set_async_mode( struct mgsl_struct *info )
usc_EnableMasterIrqBit( info );
- if (info->bus_type == MGSL_BUS_TYPE_ISA) {
- /* Enable INTEN (Port 6, Bit12) */
- /* This connects the IRQ request signal to the ISA bus */
- usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
- }
-
if (info->params.loopback) {
info->loopback_bits = 0x300;
outw(0x0300, info->io_base + CCAR);
@@ -6107,12 +6059,6 @@ static void usc_set_sync_mode( struct mgsl_struct *info )
usc_loopback_frame( info );
usc_set_sdlc_mode( info );
- if (info->bus_type == MGSL_BUS_TYPE_ISA) {
- /* Enable INTEN (Port 6, Bit12) */
- /* This connects the IRQ request signal to the ISA bus */
- usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
- }
-
usc_enable_aux_clock(info, info->params.clock_speed);
if (info->params.loopback)
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 1f03078ec352..fa0ce7dd9e24 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -539,7 +539,6 @@ void __handle_sysrq(int key, bool check_mask)
*/
orig_log_level = console_loglevel;
console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
- pr_info("SysRq : ");
op_p = __sysrq_get_key_op(key);
if (op_p) {
@@ -548,14 +547,15 @@ void __handle_sysrq(int key, bool check_mask)
* should not) and is the invoked operation enabled?
*/
if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
- pr_cont("%s\n", op_p->action_msg);
+ pr_info("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key);
} else {
- pr_cont("This sysrq operation is disabled.\n");
+ pr_info("This sysrq operation is disabled.\n");
+ console_loglevel = orig_log_level;
}
} else {
- pr_cont("HELP : ");
+ pr_info("HELP : ");
/* Only print the help msg once per handler */
for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
if (sysrq_key_table[i]) {
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 77070c2d1240..ec145a59f199 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -26,7 +26,7 @@
* Byte threshold to limit memory consumption for flip buffers.
* The actual memory limit is > 2x this amount.
*/
-#define TTYB_DEFAULT_MEM_LIMIT 65536
+#define TTYB_DEFAULT_MEM_LIMIT (640 * 1024UL)
/*
* We default to dicing tty buffer allocations to this many characters
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index bfe9ad85b362..5fa250157025 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -513,6 +513,8 @@ static const struct file_operations hung_up_tty_fops = {
static DEFINE_SPINLOCK(redirect_lock);
static struct file *redirect;
+extern void tty_sysctl_init(void);
+
/**
* tty_wakeup - request more data
* @tty: terminal
@@ -1256,7 +1258,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
static int tty_reopen(struct tty_struct *tty)
{
struct tty_driver *driver = tty->driver;
- int retval;
+ struct tty_ldisc *ld;
+ int retval = 0;
if (driver->type == TTY_DRIVER_TYPE_PTY &&
driver->subtype == PTY_TYPE_MASTER)
@@ -1268,13 +1271,18 @@ static int tty_reopen(struct tty_struct *tty)
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
return -EBUSY;
- retval = tty_ldisc_lock(tty, 5 * HZ);
- if (retval)
- return retval;
+ ld = tty_ldisc_ref_wait(tty);
+ if (ld) {
+ tty_ldisc_deref(ld);
+ } else {
+ retval = tty_ldisc_lock(tty, 5 * HZ);
+ if (retval)
+ return retval;
- if (!tty->ldisc)
- retval = tty_ldisc_reinit(tty, tty->termios.c_line);
- tty_ldisc_unlock(tty);
+ if (!tty->ldisc)
+ retval = tty_ldisc_reinit(tty, tty->termios.c_line);
+ tty_ldisc_unlock(tty);
+ }
if (retval == 0)
tty->count++;
@@ -2183,7 +2191,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
ld = tty_ldisc_ref_wait(tty);
if (!ld)
return -EIO;
- ld->ops->receive_buf(tty, &ch, &mbz, 1);
+ if (ld->ops->receive_buf)
+ ld->ops->receive_buf(tty, &ch, &mbz, 1);
tty_ldisc_deref(ld);
return 0;
}
@@ -3476,6 +3485,7 @@ void console_sysfs_notify(void)
*/
int __init tty_init(void)
{
+ tty_sysctl_init();
cdev_init(&tty_cdev, &tty_fops);
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 45eda69b150c..e38f104db174 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -156,6 +156,13 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
* takes tty_ldiscs_lock to guard against ldisc races
*/
+#if defined(CONFIG_LDISC_AUTOLOAD)
+ #define INITIAL_AUTOLOAD_STATE 1
+#else
+ #define INITIAL_AUTOLOAD_STATE 0
+#endif
+static int tty_ldisc_autoload = INITIAL_AUTOLOAD_STATE;
+
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
{
struct tty_ldisc *ld;
@@ -170,6 +177,8 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
*/
ldops = get_ldops(disc);
if (IS_ERR(ldops)) {
+ if (!capable(CAP_SYS_MODULE) && !tty_ldisc_autoload)
+ return ERR_PTR(-EPERM);
request_module("tty-ldisc-%d", disc);
ldops = get_ldops(disc);
if (IS_ERR(ldops))
@@ -845,3 +854,41 @@ void tty_ldisc_deinit(struct tty_struct *tty)
tty_ldisc_put(tty->ldisc);
tty->ldisc = NULL;
}
+
+static int zero;
+static int one = 1;
+static struct ctl_table tty_table[] = {
+ {
+ .procname = "ldisc_autoload",
+ .data = &tty_ldisc_autoload,
+ .maxlen = sizeof(tty_ldisc_autoload),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ { }
+};
+
+static struct ctl_table tty_dir_table[] = {
+ {
+ .procname = "tty",
+ .mode = 0555,
+ .child = tty_table,
+ },
+ { }
+};
+
+static struct ctl_table tty_root_table[] = {
+ {
+ .procname = "dev",
+ .mode = 0555,
+ .child = tty_dir_table,
+ },
+ { }
+};
+
+void tty_sysctl_init(void)
+{
+ register_sysctl_table(tty_root_table);
+}
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index 2384ea85ffaf..160f46115aaa 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -80,7 +80,7 @@
struct vcs_poll_data {
struct notifier_block notifier;
unsigned int cons_num;
- bool seen_last_update;
+ int event;
wait_queue_head_t waitq;
struct fasync_struct *fasync;
};
@@ -93,9 +93,18 @@ vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
struct vcs_poll_data *poll =
container_of(nb, struct vcs_poll_data, notifier);
int currcons = poll->cons_num;
-
- if (code != VT_UPDATE)
+ int fa_band;
+
+ switch (code) {
+ case VT_UPDATE:
+ fa_band = POLL_PRI;
+ break;
+ case VT_DEALLOCATE:
+ fa_band = POLL_HUP;
+ break;
+ default:
return NOTIFY_DONE;
+ }
if (currcons == 0)
currcons = fg_console;
@@ -104,9 +113,9 @@ vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
if (currcons != vc->vc_num)
return NOTIFY_DONE;
- poll->seen_last_update = false;
+ poll->event = code;
wake_up_interruptible(&poll->waitq);
- kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+ kill_fasync(&poll->fasync, SIGIO, fa_band);
return NOTIFY_OK;
}
@@ -131,6 +140,15 @@ vcs_poll_data_get(struct file *file)
poll->cons_num = console(file_inode(file));
init_waitqueue_head(&poll->waitq);
poll->notifier.notifier_call = vcs_notifier;
+ /*
+ * In order not to lose any update event, we must pretend one might
+ * have occurred before we have a chance to register our notifier.
+ * This is also how user space has come to detect which kernels
+ * support POLLPRI on /dev/vcs* devices i.e. using poll() with
+ * POLLPRI and a zero timeout.
+ */
+ poll->event = VT_UPDATE;
+
if (register_vt_notifier(&poll->notifier) != 0) {
kfree(poll);
return NULL;
@@ -261,7 +279,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
poll = file->private_data;
if (count && poll)
- poll->seen_last_update = true;
+ poll->event = 0;
read = 0;
ret = 0;
while (count) {
@@ -335,8 +353,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (p < HEADER_SIZE) {
size_t tmp_count;
- con_buf0[0] = (char)vc->vc_rows;
- con_buf0[1] = (char)vc->vc_cols;
+ /* clamp header values if they don't fit */
+ con_buf0[0] = min(vc->vc_rows, 0xFFu);
+ con_buf0[1] = min(vc->vc_cols, 0xFFu);
getconsxy(vc, con_buf0 + 2);
con_buf_start += p;
@@ -615,12 +634,21 @@ static __poll_t
vcs_poll(struct file *file, poll_table *wait)
{
struct vcs_poll_data *poll = vcs_poll_data_get(file);
- __poll_t ret = DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI;
+ __poll_t ret = DEFAULT_POLLMASK|EPOLLERR;
if (poll) {
poll_wait(file, &poll->waitq, wait);
- if (poll->seen_last_update)
+ switch (poll->event) {
+ case VT_UPDATE:
+ ret = DEFAULT_POLLMASK|EPOLLPRI;
+ break;
+ case VT_DEALLOCATE:
+ ret = DEFAULT_POLLMASK|EPOLLHUP|EPOLLERR;
+ break;
+ case 0:
ret = DEFAULT_POLLMASK;
+ break;
+ }
}
return ret;
}
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 41ec8e5010f3..d34984aa646d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -935,8 +935,11 @@ static void flush_scrollback(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
+ set_origin(vc);
if (vc->vc_sw->con_flush_scrollback)
vc->vc_sw->con_flush_scrollback(vc);
+ else
+ vc->vc_sw->con_switch(vc);
}
/*
@@ -1272,6 +1275,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
if (con_is_visible(vc))
update_screen(vc);
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
+ notify_update(vc);
return err;
}
@@ -1341,6 +1345,8 @@ struct vc_data *vc_deallocate(unsigned int currcons)
* VT102 emulator
*/
+enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt};
+
#define set_kbd(vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x))
#define clr_kbd(vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x))
#define is_kbd(vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x))
@@ -1502,8 +1508,10 @@ static void csi_J(struct vc_data *vc, int vpar)
count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
start = (unsigned short *)vc->vc_origin;
break;
+ case 3: /* include scrollback */
+ flush_scrollback(vc);
+ /* fallthrough */
case 2: /* erase whole display */
- case 3: /* (and scrollback buffer later) */
vc_uniscr_clear_lines(vc, 0, vc->vc_rows);
count = vc->vc_cols * vc->vc_rows;
start = (unsigned short *)vc->vc_origin;
@@ -1512,13 +1520,7 @@ static void csi_J(struct vc_data *vc, int vpar)
return;
}
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
- if (vpar == 3) {
- set_origin(vc);
- flush_scrollback(vc);
- if (con_is_visible(vc))
- update_screen(vc);
- } else if (con_should_update(vc))
- do_update_region(vc, (unsigned long) start, count);
+ update_region(vc, (unsigned long) start, count);
vc->vc_need_wrap = 0;
}
@@ -1627,9 +1629,9 @@ static void rgb_background(struct vc_data *vc, const struct rgb *c)
/*
* ITU T.416 Higher colour modes. They break the usual properties of SGR codes
- * and thus need to be detected and ignored by hand. Strictly speaking, that
- * standard also wants : rather than ; as separators, contrary to ECMA-48, but
- * no one produces such codes and almost no one accepts them.
+ * and thus need to be detected and ignored by hand. That standard also
+ * wants : rather than ; as separators but sequences containing : are currently
+ * completely ignored by the parser.
*
* Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in
* supporting them.
@@ -1814,7 +1816,7 @@ static void set_mode(struct vc_data *vc, int on_off)
int i;
for (i = 0; i <= vc->vc_npar; i++)
- if (vc->vc_ques) {
+ if (vc->vc_priv == EPdec) {
switch(vc->vc_par[i]) { /* DEC private modes set/reset */
case 1: /* Cursor keys send ^[Ox/^[[x */
if (on_off)
@@ -2021,7 +2023,7 @@ static void restore_cur(struct vc_data *vc)
}
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
- EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
+ EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd,
ESpalette, ESosc };
/* console_lock is held (except via vc_init()) */
@@ -2030,7 +2032,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
vc->vc_top = 0;
vc->vc_bottom = vc->vc_rows;
vc->vc_state = ESnormal;
- vc->vc_ques = 0;
+ vc->vc_priv = EPecma;
vc->vc_translate = set_translate(LAT1_MAP, vc);
vc->vc_G0_charset = LAT1_MAP;
vc->vc_G1_charset = GRAF_MAP;
@@ -2111,6 +2113,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
lf(vc);
if (!is_kbd(vc, lnm))
return;
+ /* fall through */
case 13:
cr(vc);
return;
@@ -2233,9 +2236,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_state=ESfunckey;
return;
}
- vc->vc_ques = (c == '?');
- if (vc->vc_ques)
+ switch (c) {
+ case '?':
+ vc->vc_priv = EPdec;
return;
+ case '>':
+ vc->vc_priv = EPgt;
+ return;
+ case '=':
+ vc->vc_priv = EPeq;
+ return;
+ case '<':
+ vc->vc_priv = EPlt;
+ return;
+ }
+ vc->vc_priv = EPecma;
+ /* fall through */
case ESgetpars:
if (c == ';' && vc->vc_npar < NPAR - 1) {
vc->vc_npar++;
@@ -2245,16 +2261,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_par[vc->vc_npar] += c - '0';
return;
}
+ if (c >= 0x20 && c <= 0x3f) { /* 0x2x, 0x3a and 0x3c - 0x3f */
+ vc->vc_state = EScsiignore;
+ return;
+ }
vc->vc_state = ESnormal;
switch(c) {
case 'h':
- set_mode(vc, 1);
+ if (vc->vc_priv <= EPdec)
+ set_mode(vc, 1);
return;
case 'l':
- set_mode(vc, 0);
+ if (vc->vc_priv <= EPdec)
+ set_mode(vc, 0);
return;
case 'c':
- if (vc->vc_ques) {
+ if (vc->vc_priv == EPdec) {
if (vc->vc_par[0])
vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
else
@@ -2263,7 +2285,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
}
break;
case 'm':
- if (vc->vc_ques) {
+ if (vc->vc_priv == EPdec) {
clear_selection();
if (vc->vc_par[0])
vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
@@ -2273,7 +2295,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
}
break;
case 'n':
- if (!vc->vc_ques) {
+ if (vc->vc_priv == EPecma) {
if (vc->vc_par[0] == 5)
status_report(tty);
else if (vc->vc_par[0] == 6)
@@ -2281,8 +2303,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
}
return;
}
- if (vc->vc_ques) {
- vc->vc_ques = 0;
+ if (vc->vc_priv != EPecma) {
+ vc->vc_priv = EPecma;
return;
}
switch(c) {
@@ -2405,6 +2427,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
return;
}
return;
+ case EScsiignore:
+ if (c >= 20 && c <= 0x3f)
+ return;
+ vc->vc_state = ESnormal;
+ return;
case ESpercent:
vc->vc_state = ESnormal;
switch (c) {
@@ -2764,8 +2791,8 @@ rescan_last_byte:
con_flush(vc, draw_from, draw_to, &draw_x);
vc_uniscr_debug_check(vc);
console_conditional_schedule();
- console_unlock();
notify_update(vc);
+ console_unlock();
return n;
}
@@ -2884,8 +2911,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
unsigned char c;
static DEFINE_SPINLOCK(printing_lock);
const ushort *start;
- ushort cnt = 0;
- ushort myx;
+ ushort start_x, cnt;
int kmsg_console;
/* console busy or not yet initialized */
@@ -2898,10 +2924,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
vc = vc_cons[kmsg_console - 1].d;
- /* read `x' only after setting currcons properly (otherwise
- the `x' macro will read the x of the foreground console). */
- myx = vc->vc_x;
-
if (!vc_cons_allocated(fg_console)) {
/* impossible */
/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
@@ -2916,53 +2938,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
hide_cursor(vc);
start = (ushort *)vc->vc_pos;
-
- /* Contrived structure to try to emulate original need_wrap behaviour
- * Problems caused when we have need_wrap set on '\n' character */
+ start_x = vc->vc_x;
+ cnt = 0;
while (count--) {
c = *b++;
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
- if (cnt > 0) {
- if (con_is_visible(vc))
- vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
- vc->vc_x += cnt;
- if (vc->vc_need_wrap)
- vc->vc_x--;
- cnt = 0;
- }
+ if (cnt && con_is_visible(vc))
+ vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
+ cnt = 0;
if (c == 8) { /* backspace */
bs(vc);
start = (ushort *)vc->vc_pos;
- myx = vc->vc_x;
+ start_x = vc->vc_x;
continue;
}
if (c != 13)
lf(vc);
cr(vc);
start = (ushort *)vc->vc_pos;
- myx = vc->vc_x;
+ start_x = vc->vc_x;
if (c == 10 || c == 13)
continue;
}
+ vc_uniscr_putc(vc, c);
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
notify_write(vc, c);
cnt++;
- if (myx == vc->vc_cols - 1) {
- vc->vc_need_wrap = 1;
- continue;
- }
- vc->vc_pos += 2;
- myx++;
- }
- if (cnt > 0) {
- if (con_is_visible(vc))
- vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
- vc->vc_x += cnt;
- if (vc->vc_x == vc->vc_cols) {
- vc->vc_x--;
+ if (vc->vc_x == vc->vc_cols - 1) {
vc->vc_need_wrap = 1;
+ } else {
+ vc->vc_pos += 2;
+ vc->vc_x++;
}
}
+ if (cnt && con_is_visible(vc))
+ vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
set_cursor(vc);
notify_update(vc);
@@ -4607,8 +4617,9 @@ EXPORT_SYMBOL_GPL(screen_pos);
void getconsxy(struct vc_data *vc, unsigned char *p)
{
- p[0] = vc->vc_x;
- p[1] = vc->vc_y;
+ /* clamp values if they don't fit */
+ p[0] = min(vc->vc_x, 0xFFu);
+ p[1] = min(vc->vc_y, 0xFFu);
}
void putconsxy(struct vc_data *vc, unsigned char *p)
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 131342280b46..a57698985f9c 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -491,10 +491,10 @@ static int uio_open(struct inode *inode, struct file *filep)
if (!idev->info) {
mutex_unlock(&idev->info_lock);
ret = -EINVAL;
- goto err_alloc_listener;
+ goto err_infoopen;
}
- if (idev->info && idev->info->open)
+ if (idev->info->open)
ret = idev->info->open(idev->info, inode);
mutex_unlock(&idev->info_lock);
if (ret)
@@ -635,7 +635,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
goto out;
}
- if (!idev->info || !idev->info->irq) {
+ if (!idev->info->irq) {
retval = -EIO;
goto out;
}
@@ -940,9 +940,12 @@ int __uio_register_device(struct module *owner,
atomic_set(&idev->event, 0);
ret = uio_get_minor(idev);
- if (ret)
+ if (ret) {
+ kfree(idev);
return ret;
+ }
+ device_initialize(&idev->dev);
idev->dev.devt = MKDEV(uio_major, idev->minor);
idev->dev.class = &uio_class;
idev->dev.parent = parent;
@@ -953,7 +956,7 @@ int __uio_register_device(struct module *owner,
if (ret)
goto err_device_create;
- ret = device_register(&idev->dev);
+ ret = device_add(&idev->dev);
if (ret)
goto err_device_create;
@@ -985,9 +988,10 @@ int __uio_register_device(struct module *owner,
err_request_irq:
uio_dev_del_attributes(idev);
err_uio_dev_add_attributes:
- device_unregister(&idev->dev);
+ device_del(&idev->dev);
err_device_create:
uio_free_minor(idev);
+ put_device(&idev->dev);
return ret;
}
EXPORT_SYMBOL_GPL(__uio_register_device);
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 8773e373ffe5..dde5cbb27178 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -39,6 +39,22 @@ to_uio_pci_generic_dev(struct uio_info *info)
return container_of(info, struct uio_pci_generic_dev, info);
}
+static int release(struct uio_info *info, struct inode *inode)
+{
+ struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
+
+ /*
+ * This driver is insecure when used with devices doing DMA, but some
+  * people (mis)use it with such devices.
+  * Let's at least make sure DMA isn't left enabled after the userspace
+  * driver closes the fd.
+  * Note that there's a non-zero chance doing this will wedge the device
+  * at least until reset.
+ */
+ pci_clear_master(gdev->pdev);
+ return 0;
+}
+
/* Interrupt handler. Read/modify/write the command register to disable
* the interrupt. */
static irqreturn_t irqhandler(int irq, struct uio_info *info)
@@ -78,6 +94,7 @@ static int probe(struct pci_dev *pdev,
gdev->info.name = "uio_pci_generic";
gdev->info.version = DRIVER_VERSION;
+ gdev->info.release = release;
gdev->pdev = pdev;
if (pdev->irq) {
gdev->info.irq = pdev->irq;
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 70e6c956c23c..e4b27413f528 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB device configuration
#
diff --git a/drivers/usb/README b/drivers/usb/README
deleted file mode 100644
index 2144e7dbfa41..000000000000
--- a/drivers/usb/README
+++ /dev/null
@@ -1,54 +0,0 @@
-To understand all the Linux-USB framework, you'll use these resources:
-
- * This source code. This is necessarily an evolving work, and
- includes kerneldoc that should help you get a current overview.
- ("make pdfdocs", and then look at "usb.pdf" for host side and
- "gadget.pdf" for peripheral side.) Also, Documentation/usb has
- more information.
-
- * The USB 2.0 specification (from www.usb.org), with supplements
- such as those for USB OTG and the various device classes.
- The USB specification has a good overview chapter, and USB
- peripherals conform to the widely known "Chapter 9".
-
- * Chip specifications for USB controllers. Examples include
- host controllers (on PCs, servers, and more); peripheral
- controllers (in devices with Linux firmware, like printers or
- cell phones); and hard-wired peripherals like Ethernet adapters.
-
- * Specifications for other protocols implemented by USB peripheral
- functions. Some are vendor-specific; others are vendor-neutral
- but just standardized outside of the www.usb.org team.
-
-Here is a list of what each subdirectory here is, and what is contained in
-them.
-
-core/ - This is for the core USB host code, including the
- usbfs files and the hub class driver ("hub_wq").
-
-host/ - This is for USB host controller drivers. This
- includes UHCI, OHCI, EHCI, and others that might
- be used with more specialized "embedded" systems.
-
-gadget/ - This is for USB peripheral controller drivers and
- the various gadget drivers which talk to them.
-
-
-Individual USB driver directories. A new driver should be added to the
-first subdirectory in the list below that it fits into.
-
-image/ - This is for still image drivers, like scanners or
- digital cameras.
-../input/ - This is for any driver that uses the input subsystem,
- like keyboard, mice, touchscreens, tablets, etc.
-../media/ - This is for multimedia drivers, like video cameras,
- radios, and any other drivers that talk to the v4l
- subsystem.
-../net/ - This is for network drivers.
-serial/ - This is for USB to serial drivers.
-storage/ - This is for USB mass-storage drivers.
-class/ - This is for all USB device drivers that do not fit
- into any of the above categories, and work for a range
- of USB Class specified devices.
-misc/ - This is for all USB device drivers that do not fit
- into any of the above categories.
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index 0f922942a07a..989aaa3b080d 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB/ATM DSL configuration
#
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index ee34e9046f7e..eb37ebfcb123 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_CHIPIDEA
tristate "ChipIdea Highspeed Dual Role Controller"
depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index e81de9ca8729..ceec8d5985d4 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -7,10 +7,8 @@
#include <linux/module.h>
#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/dma-mapping.h>
#include <linux/usb/chipidea.h>
#include <linux/usb/of.h>
#include <linux/clk.h>
@@ -152,8 +150,8 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
dev_warn(dev, "No over current polarity defined\n");
}
- if (of_find_property(np, "external-vbus-divider", NULL))
- data->evdo = 1;
+ data->pwr_pol = of_property_read_bool(np, "power-active-high");
+ data->evdo = of_property_read_bool(np, "external-vbus-divider");
if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
data->ulpi = 1;
@@ -316,7 +314,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (IS_ERR(data->usbmisc_data))
return PTR_ERR(data->usbmisc_data);
- if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
+ if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC)
+ && data->usbmisc_data) {
pdata.flags |= CI_HDRC_IMX_IS_HSIC;
data->usbmisc_data->hsic = 1;
data->pinctrl = devm_pinctrl_get(dev);
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 7cc53e2ce564..c842e03f8767 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -18,6 +18,7 @@ struct imx_usbmisc_data {
/* true if dt specifies polarity */
unsigned int oc_pol_configured:1;
+ unsigned int pwr_pol:1; /* power polarity */
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
unsigned int hsic:1; /* HSIC controlller */
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 772851bee99b..12025358bb3c 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -130,6 +130,7 @@ static int tegra_udc_remove(struct platform_device *pdev)
{
struct tegra_udc *udc = platform_get_drvdata(pdev);
+ ci_hdrc_remove_device(udc->dev);
usb_phy_set_suspend(udc->phy, 1);
clk_disable_unprepare(udc->clk);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 7bfcbb23c2a4..27749ace2d93 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -954,25 +954,47 @@ static int ci_hdrc_probe(struct platform_device *pdev)
} else if (ci->platdata->usb_phy) {
ci->usb_phy = ci->platdata->usb_phy;
} else {
+ /* Look for a generic PHY first */
ci->phy = devm_phy_get(dev->parent, "usb-phy");
- ci->usb_phy = devm_usb_get_phy(dev->parent, USB_PHY_TYPE_USB2);
- /* if both generic PHY and USB PHY layers aren't enabled */
- if (PTR_ERR(ci->phy) == -ENOSYS &&
- PTR_ERR(ci->usb_phy) == -ENXIO) {
- ret = -ENXIO;
+ if (PTR_ERR(ci->phy) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
goto ulpi_exit;
+ } else if (IS_ERR(ci->phy)) {
+ ci->phy = NULL;
}
- if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) {
- ret = -EPROBE_DEFER;
- goto ulpi_exit;
+ /* Look for a legacy USB PHY from device-tree next */
+ if (!ci->phy) {
+ ci->usb_phy = devm_usb_get_phy_by_phandle(dev->parent,
+ "phys", 0);
+
+ if (PTR_ERR(ci->usb_phy) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto ulpi_exit;
+ } else if (IS_ERR(ci->usb_phy)) {
+ ci->usb_phy = NULL;
+ }
}
- if (IS_ERR(ci->phy))
- ci->phy = NULL;
- else if (IS_ERR(ci->usb_phy))
- ci->usb_phy = NULL;
+ /* Look for any registered legacy USB PHY as last resort */
+ if (!ci->phy && !ci->usb_phy) {
+ ci->usb_phy = devm_usb_get_phy(dev->parent,
+ USB_PHY_TYPE_USB2);
+
+ if (PTR_ERR(ci->usb_phy) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto ulpi_exit;
+ } else if (IS_ERR(ci->usb_phy)) {
+ ci->usb_phy = NULL;
+ }
+ }
+
+ /* No USB PHY was found in the end */
+ if (!ci->phy && !ci->usb_phy) {
+ ret = -ENXIO;
+ goto ulpi_exit;
+ }
}
ret = ci_usb_phy_init(ci);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 097ffbca0bd9..d8b67e150b12 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -63,6 +63,7 @@
#define MX6_BM_NON_BURST_SETTING BIT(1)
#define MX6_BM_OVER_CUR_DIS BIT(7)
#define MX6_BM_OVER_CUR_POLARITY BIT(8)
+#define MX6_BM_PWR_POLARITY BIT(9)
#define MX6_BM_WAKEUP_ENABLE BIT(10)
#define MX6_BM_UTMI_ON_CLOCK BIT(13)
#define MX6_BM_ID_WAKEUP BIT(16)
@@ -383,6 +384,9 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
else if (data->oc_pol_configured)
reg &= ~MX6_BM_OVER_CUR_POLARITY;
}
+ /* If the polarity is not set keep it as setup by the bootlader */
+ if (data->pwr_pol == 1)
+ reg |= MX6_BM_PWR_POLARITY;
writel(reg, usbmisc->base + data->index * 4);
/* SoC non-burst setting */
@@ -585,6 +589,9 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
else if (data->oc_pol_configured)
reg &= ~MX6_BM_OVER_CUR_POLARITY;
}
+ /* If the polarity is not set keep it as setup by the bootlader */
+ if (data->pwr_pol == 1)
+ reg |= MX6_BM_PWR_POLARITY;
writel(reg, usbmisc->base);
reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 971385fe9abc..52f3a531a82f 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Class driver configuration
#
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index ed8c62b2d9d1..739f8960811a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1865,6 +1865,13 @@ static const struct usb_device_id acm_ids[] = {
.driver_info = IGNORE_DEVICE,
},
+ { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */
+ .driver_info = SEND_ZERO_PACKET,
+ },
+ { USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */
+ .driver_info = SEND_ZERO_PACKET,
+ },
+
/* control interfaces without any protocol set */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_PROTO_NONE) },
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index bec581fb7c63..9e9caff905d5 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -1099,7 +1099,7 @@ static int wdm_post_reset(struct usb_interface *intf)
rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->wlock);
mutex_unlock(&desc->rlock);
- return 0;
+ return rv;
}
static struct usb_driver wdm_driver = {
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 4d75d9a80001..bdb6bd0b63a6 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Core configuration
#
@@ -90,3 +91,15 @@ config USB_LEDS_TRIGGER_USBPORT
This driver allows LEDs to be controlled by USB events. Enabling this
trigger allows specifying list of USB ports that should turn on LED
when some USB device gets connected.
+
+config USB_AUTOSUSPEND_DELAY
+ int "Default autosuspend delay"
+ depends on USB
+ default 2
+ help
+ The default autosuspend delay in seconds. Can be overridden
+ with the usbcore.autosuspend command line or module parameter.
+
+ The default value Linux has always had is 2 seconds. Change
+ this value if you want a different delay and cannot modify
+ the command line or module parameter.
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 7b5cb28ffb35..20ff036b4c22 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -552,7 +552,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
unsigned char *buffer2;
int size2;
struct usb_descriptor_header *header;
- int len, retval;
+ int retval;
u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
unsigned iad_num = 0;
@@ -707,8 +707,8 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
nalts[i] = j = USB_MAXALTSETTING;
}
- len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
- config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
+ intfc = kzalloc(struct_size(intfc, altsetting, j), GFP_KERNEL);
+ config->intf_cache[i] = intfc;
if (!intfc)
return -ENOMEM;
kref_init(&intfc->ref);
@@ -800,13 +800,11 @@ int usb_get_configuration(struct usb_device *dev)
{
struct device *ddev = &dev->dev;
int ncfg = dev->descriptor.bNumConfigurations;
- int result = 0;
+ int result = -ENOMEM;
unsigned int cfgno, length;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
- cfgno = 0;
- result = -ENOMEM;
if (ncfg > USB_MAXCONFIG) {
dev_warn(ddev, "too many configurations: %d, "
"using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
@@ -832,8 +830,7 @@ int usb_get_configuration(struct usb_device *dev)
if (!desc)
goto err2;
- result = 0;
- for (; cfgno < ncfg; cfgno++) {
+ for (cfgno = 0; cfgno < ncfg; cfgno++) {
/* We grab just the first descriptor so we know how long
* the whole configuration is */
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
@@ -889,7 +886,6 @@ int usb_get_configuration(struct usb_device *dev)
goto err;
}
}
- result = 0;
err:
kfree(desc);
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index d65566341dd1..fa783531ee88 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -604,7 +604,7 @@ static void async_completed(struct urb *urb)
snoop(&urb->dev->dev, "urb complete\n");
snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
as->status, COMPLETE, NULL, 0);
- if ((urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN)
+ if (usb_urb_dir_in(urb))
snoop_urb_data(urb, urb->actual_length);
if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
@@ -1564,12 +1564,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
}
for (totlen = u = 0; u < number_of_packets; u++) {
/*
- * arbitrary limit need for USB 3.0
- * bMaxBurst (0~15 allowed, 1~16 packets)
- * bmAttributes (bit 1:0, mult 0~2, 1~3 packets)
- * sizemax: 1024 * 16 * 3 = 49152
+ * arbitrary limit need for USB 3.1 Gen2
+ * sizemax: 96 DPs at SSP, 96 * 1024 = 98304
*/
- if (isopkt[u].length > 49152) {
+ if (isopkt[u].length > 98304) {
ret = -EINVAL;
goto error;
}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 53564386ed57..8987cec9549d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1896,14 +1896,11 @@ int usb_runtime_idle(struct device *dev)
return -EBUSY;
}
-int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
int ret = -EPERM;
- if (enable && !udev->usb2_hw_lpm_allowed)
- return 0;
-
if (hcd->driver->set_usb2_hw_lpm) {
ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
if (!ret)
@@ -1913,6 +1910,24 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
return ret;
}
+int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ if (!udev->usb2_hw_lpm_capable ||
+ !udev->usb2_hw_lpm_allowed ||
+ udev->usb2_hw_lpm_enabled)
+ return 0;
+
+ return usb_set_usb2_hardware_lpm(udev, 1);
+}
+
+int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ if (!udev->usb2_hw_lpm_enabled)
+ return 0;
+
+ return usb_set_usb2_hardware_lpm(udev, 0);
+}
+
#endif /* CONFIG_PM */
struct bus_type usb_bus_type = {
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 356b05c82dbc..1ac9c1e5f773 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -118,6 +118,31 @@ int usb_choose_configuration(struct usb_device *udev)
continue;
}
+ /*
+ * Select first configuration as default for audio so that
+ * devices that don't comply with UAC3 protocol are supported.
+ * But, still iterate through other configurations and
+ * select UAC3 compliant config if present.
+ */
+ if (desc && is_audio(desc)) {
+ /* Always prefer the first found UAC3 config */
+ if (is_uac3_config(desc)) {
+ best = c;
+ break;
+ }
+
+ /* If there is no UAC3 config, prefer the first config */
+ else if (i == 0)
+ best = c;
+
+ /* Unconditional continue, because the rest of the code
+ * in the loop is irrelevant for audio devices, and
+ * because it can reassign best, which for audio devices
+ * we don't want.
+ */
+ continue;
+ }
+
/* When the first config's first interface is one of Microsoft's
* pet nonstandard Ethernet-over-USB protocols, ignore it unless
* this kernel has enabled the necessary host side driver.
@@ -132,22 +157,6 @@ int usb_choose_configuration(struct usb_device *udev)
#endif
}
- /*
- * Select first configuration as default for audio so that
- * devices that don't comply with UAC3 protocol are supported.
- * But, still iterate through other configurations and
- * select UAC3 compliant config if present.
- */
- if (i == 0 && num_configs > 1 && desc && is_audio(desc)) {
- best = c;
- continue;
- }
-
- if (i > 0 && desc && is_audio(desc) && is_uac3_config(desc)) {
- best = c;
- break;
- }
-
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 015b126ce455..3189181bb628 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -373,13 +373,19 @@ static const u8 ss_rh_config_descriptor[] = {
* -1 is authorized for all devices except wireless (old behaviour)
* 0 is unauthorized for all devices
* 1 is authorized for all devices
+ * 2 is authorized for internal devices
*/
-static int authorized_default = -1;
+#define USB_AUTHORIZE_WIRED -1
+#define USB_AUTHORIZE_NONE 0
+#define USB_AUTHORIZE_ALL 1
+#define USB_AUTHORIZE_INTERNAL 2
+
+static int authorized_default = USB_AUTHORIZE_WIRED;
module_param(authorized_default, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(authorized_default,
"Default USB device authorization: 0 is not authorized, 1 is "
- "authorized, -1 is authorized except for wireless USB (default, "
- "old behaviour");
+ "authorized, 2 is authorized for internal devices, -1 is "
+ "authorized except for wireless USB (default, old behaviour)");
/*-------------------------------------------------------------------------*/
/**
@@ -884,7 +890,7 @@ static ssize_t authorized_default_show(struct device *dev,
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
- return snprintf(buf, PAGE_SIZE, "%u\n", !!HCD_DEV_AUTHORIZED(hcd));
+ return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
}
static ssize_t authorized_default_store(struct device *dev,
@@ -900,11 +906,8 @@ static ssize_t authorized_default_store(struct device *dev,
hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val);
if (result == 1) {
- if (val)
- set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
- else
- clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
-
+ hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
+ val : USB_DEVICE_AUTHORIZE_ALL;
result = size;
} else {
result = -EINVAL;
@@ -2736,6 +2739,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
if (retval)
return retval;
+ retval = usb_phy_roothub_set_mode(hcd->phy_roothub,
+ PHY_MODE_USB_HOST_SS);
+ if (retval)
+ goto err_usb_phy_roothub_power_on;
+
retval = usb_phy_roothub_power_on(hcd->phy_roothub);
if (retval)
goto err_usb_phy_roothub_power_on;
@@ -2743,18 +2751,26 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
- /* Keep old behaviour if authorized_default is not in [0, 1]. */
- if (authorized_default < 0 || authorized_default > 1) {
- if (hcd->wireless)
- clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
- else
- set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
- } else {
- if (authorized_default)
- set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
- else
- clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+ switch (authorized_default) {
+ case USB_AUTHORIZE_NONE:
+ hcd->dev_policy = USB_DEVICE_AUTHORIZE_NONE;
+ break;
+
+ case USB_AUTHORIZE_ALL:
+ hcd->dev_policy = USB_DEVICE_AUTHORIZE_ALL;
+ break;
+
+ case USB_AUTHORIZE_INTERNAL:
+ hcd->dev_policy = USB_DEVICE_AUTHORIZE_INTERNAL;
+ break;
+
+ case USB_AUTHORIZE_WIRED:
+ default:
+ hcd->dev_policy = hcd->wireless ?
+ USB_DEVICE_AUTHORIZE_NONE : USB_DEVICE_AUTHORIZE_ALL;
+ break;
}
+
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* per default all interfaces are authorized */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1d1e61e980f3..8d4631c81b9f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -108,6 +108,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
static void hub_release(struct kref *kref);
static int usb_reset_and_verify_device(struct usb_device *udev);
static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
+static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+ u16 portstatus);
static inline char *portspeed(struct usb_hub *hub, int portstatus)
{
@@ -607,6 +609,36 @@ static int hub_port_status(struct usb_hub *hub, int port1,
status, change, NULL);
}
+static void hub_resubmit_irq_urb(struct usb_hub *hub)
+{
+ unsigned long flags;
+ int status;
+
+ spin_lock_irqsave(&hub->irq_urb_lock, flags);
+
+ if (hub->quiescing) {
+ spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
+ return;
+ }
+
+ status = usb_submit_urb(hub->urb, GFP_ATOMIC);
+ if (status && status != -ENODEV && status != -EPERM &&
+ status != -ESHUTDOWN) {
+ dev_err(hub->intfdev, "resubmit --> %d\n", status);
+ mod_timer(&hub->irq_urb_retry, jiffies + HZ);
+ }
+
+ spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
+}
+
+static void hub_retry_irq_urb(struct timer_list *t)
+{
+ struct usb_hub *hub = from_timer(hub, t, irq_urb_retry);
+
+ hub_resubmit_irq_urb(hub);
+}
+
+
static void kick_hub_wq(struct usb_hub *hub)
{
struct usb_interface *intf;
@@ -709,12 +741,7 @@ static void hub_irq(struct urb *urb)
kick_hub_wq(hub);
resubmit:
- if (hub->quiescing)
- return;
-
- status = usb_submit_urb(hub->urb, GFP_ATOMIC);
- if (status != 0 && status != -ENODEV && status != -EPERM)
- dev_err(hub->intfdev, "resubmit --> %d\n", status);
+ hub_resubmit_irq_urb(hub);
}
/* USB 2.0 spec Section 11.24.2.3 */
@@ -1112,6 +1139,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
USB_PORT_FEAT_ENABLE);
}
+ /* Make sure a warm-reset request is handled by port_event */
+ if (type == HUB_RESUME &&
+ hub_port_warm_reset_required(hub, port1, portstatus))
+ set_bit(port1, hub->event_bits);
+
/*
* Add debounce if USB3 link is in polling/link training state.
* Link will automatically transition to Enabled state after
@@ -1264,10 +1296,13 @@ enum hub_quiescing_type {
static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
{
struct usb_device *hdev = hub->hdev;
+ unsigned long flags;
int i;
/* hub_wq and related activity won't re-trigger */
+ spin_lock_irqsave(&hub->irq_urb_lock, flags);
hub->quiescing = 1;
+ spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
if (type != HUB_SUSPEND) {
/* Disconnect all the children */
@@ -1278,6 +1313,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
}
/* Stop hub_wq and related activity */
+ del_timer_sync(&hub->irq_urb_retry);
usb_kill_urb(hub->urb);
if (hub->has_indicators)
cancel_delayed_work_sync(&hub->leds);
@@ -1810,6 +1846,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
INIT_DELAYED_WORK(&hub->leds, led_work);
INIT_DELAYED_WORK(&hub->init_work, NULL);
INIT_WORK(&hub->events, hub_event);
+ spin_lock_init(&hub->irq_urb_lock);
+ timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
usb_get_intf(intf);
usb_get_dev(hdev);
@@ -3220,8 +3258,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
}
/* disable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
if (usb_disable_ltm(udev)) {
dev_err(&udev->dev, "Failed to disable LTM before suspend\n");
@@ -3259,8 +3296,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
usb_enable_ltm(udev);
err_ltm:
/* Try to enable USB2 hardware LPM again */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
if (udev->do_remote_wakeup)
(void) usb_disable_remote_wakeup(udev);
@@ -3543,8 +3579,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
hub_port_logical_disconnect(hub, port1);
} else {
/* Try to enable USB2 hardware LPM */
- if (udev->usb2_hw_lpm_capable == 1)
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
/* Try to enable USB3 LTM */
usb_enable_ltm(udev);
@@ -4435,7 +4470,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
udev->usb2_hw_lpm_allowed = 1;
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
}
}
@@ -5649,8 +5684,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
/* Disable USB2 hardware LPM.
* It will be re-enabled by the enumeration process.
*/
- if (udev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(udev, 0);
+ usb_disable_usb2_hardware_lpm(udev);
/* Disable LPM while we reset the device and reinstall the alt settings.
* Device-initiated LPM, and system exit latency settings are cleared
@@ -5753,7 +5787,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
done:
/* Now that the alt settings are re-installed, enable LTM and LPM. */
- usb_set_usb2_hardware_lpm(udev, 1);
+ usb_enable_usb2_hardware_lpm(udev);
usb_unlocked_enable_lpm(udev);
usb_enable_ltm(udev);
usb_release_bos_descriptor(udev);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 4accfb63f7dc..a9e24e4b8df1 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -69,6 +69,8 @@ struct usb_hub {
struct delayed_work leds;
struct delayed_work init_work;
struct work_struct events;
+ spinlock_t irq_urb_lock;
+ struct timer_list irq_urb_retry;
struct usb_port **ports;
};
diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c
index dc7f7fd71684..c12ac56606c3 100644
--- a/drivers/usb/core/ledtrig-usbport.c
+++ b/drivers/usb/core/ledtrig-usbport.c
@@ -119,11 +119,6 @@ static const struct attribute_group ports_group = {
.attrs = ports_attrs,
};
-static const struct attribute_group *ports_groups[] = {
- &ports_group,
- NULL
-};
-
/***************************************
* Adding & removing ports
***************************************/
@@ -307,6 +302,7 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
static int usbport_trig_activate(struct led_classdev *led_cdev)
{
struct usbport_trig_data *usbport_data;
+ int err;
usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
if (!usbport_data)
@@ -315,6 +311,9 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
/* List of ports */
INIT_LIST_HEAD(&usbport_data->ports);
+ err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group);
+ if (err)
+ goto err_free;
usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
usbport_trig_update_count(usbport_data);
@@ -322,8 +321,11 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
usbport_data->nb.notifier_call = usbport_trig_notify;
led_set_trigger_data(led_cdev, usbport_data);
usb_register_notify(&usbport_data->nb);
-
return 0;
+
+err_free:
+ kfree(usbport_data);
+ return err;
}
static void usbport_trig_deactivate(struct led_classdev *led_cdev)
@@ -335,6 +337,8 @@ static void usbport_trig_deactivate(struct led_classdev *led_cdev)
usbport_trig_remove_port(usbport_data, port);
}
+ sysfs_remove_group(&led_cdev->dev->kobj, &ports_group);
+
usb_unregister_notify(&usbport_data->nb);
kfree(usbport_data);
@@ -344,7 +348,6 @@ static struct led_trigger usbport_led_trigger = {
.name = "usbport",
.activate = usbport_trig_activate,
.deactivate = usbport_trig_deactivate,
- .groups = ports_groups,
};
static int __init usbport_trig_init(void)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index bfa5eda0cc26..82239f27c4cc 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1243,8 +1243,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
dev->actconfig->interface[i] = NULL;
}
- if (dev->usb2_hw_lpm_enabled == 1)
- usb_set_usb2_hardware_lpm(dev, 0);
+ usb_disable_usb2_hardware_lpm(dev);
usb_unlocked_disable_lpm(dev);
usb_disable_ltm(dev);
@@ -2007,6 +2006,13 @@ free_interfaces:
for (i = 0; i < nintf; ++i) {
struct usb_interface *intf = cp->interface[i];
+ if (intf->dev.of_node &&
+ !of_device_is_available(intf->dev.of_node)) {
+ dev_info(&dev->dev, "skipping disabled interface %d\n",
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ continue;
+ }
+
dev_dbg(&dev->dev,
"adding %s (config #%d, interface %d)\n",
dev_name(&intf->dev), configuration,
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 38b2c776c4b4..7580493b867a 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -123,6 +123,34 @@ int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub)
}
EXPORT_SYMBOL_GPL(usb_phy_roothub_exit);
+int usb_phy_roothub_set_mode(struct usb_phy_roothub *phy_roothub,
+ enum phy_mode mode)
+{
+ struct usb_phy_roothub *roothub_entry;
+ struct list_head *head;
+ int err;
+
+ if (!phy_roothub)
+ return 0;
+
+ head = &phy_roothub->list;
+
+ list_for_each_entry(roothub_entry, head, list) {
+ err = phy_set_mode(roothub_entry->phy, mode);
+ if (err)
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ list_for_each_entry_continue_reverse(roothub_entry, head, list)
+ phy_power_off(roothub_entry->phy);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode);
+
int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub)
{
struct usb_phy_roothub *roothub_entry;
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index 88a3c037e9df..dad564e2d2d4 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -16,6 +16,8 @@ struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev);
int usb_phy_roothub_init(struct usb_phy_roothub *phy_roothub);
int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub);
+int usb_phy_roothub_set_mode(struct usb_phy_roothub *phy_roothub,
+ enum phy_mode mode);
int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub);
void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 514c5214ddb2..8bc35d53408b 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -394,7 +394,8 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET },
/* Corsair K70 RGB */
- { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
+ { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT |
+ USB_QUIRK_DELAY_CTRL_MSG },
/* Corsair Strafe */
{ USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index ea18284dfa9a..7e88fdfe3cf5 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -528,7 +528,10 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev,
if (!ret) {
udev->usb2_hw_lpm_allowed = value;
- ret = usb_set_usb2_hardware_lpm(udev, value);
+ if (value)
+ ret = usb_enable_usb2_hardware_lpm(udev);
+ else
+ ret = usb_disable_usb2_hardware_lpm(udev);
}
usb_unlock_device(udev);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index f51750bcd152..0eab79f82ce4 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -70,9 +70,8 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb;
- urb = kmalloc(sizeof(struct urb) +
- iso_packets * sizeof(struct usb_iso_packet_descriptor),
- mem_flags);
+ urb = kmalloc(struct_size(urb, iso_frame_desc, iso_packets),
+ mem_flags);
if (!urb)
return NULL;
usb_init_urb(urb);
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index e221861b3187..9043d7242d67 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -139,86 +139,123 @@ static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent,
return acpi_find_child_device(parent, raw, false);
}
-static struct acpi_device *usb_acpi_find_companion(struct device *dev)
+static struct acpi_device *
+usb_acpi_get_companion_for_port(struct usb_port *port_dev)
{
struct usb_device *udev;
struct acpi_device *adev;
acpi_handle *parent_handle;
+ int port1;
+
+ /* Get the struct usb_device point of port's hub */
+ udev = to_usb_device(port_dev->dev.parent->parent);
/*
- * In the ACPI DSDT table, only usb root hub and usb ports are
- * acpi device nodes. The hierarchy like following.
- * Device (EHC1)
- * Device (HUBN)
- * Device (PR01)
- * Device (PR11)
- * Device (PR12)
- * Device (PR13)
- * ...
- * So all binding process is divided into two parts. binding
- * root hub and usb ports.
+ * The root hub ports' parent is the root hub. The non-root-hub
+ * ports' parent is the parent hub port which the hub is
+ * connected to.
*/
- if (is_usb_device(dev)) {
- udev = to_usb_device(dev);
- if (udev->parent)
+ if (!udev->parent) {
+ adev = ACPI_COMPANION(&udev->dev);
+ port1 = usb_hcd_find_raw_port_number(bus_to_hcd(udev->bus),
+ port_dev->portnum);
+ } else {
+ parent_handle = usb_get_hub_port_acpi_handle(udev->parent,
+ udev->portnum);
+ if (!parent_handle)
return NULL;
- /* root hub is only child (_ADR=0) under its parent, the HC */
- adev = ACPI_COMPANION(dev->parent);
- return acpi_find_child_device(adev, 0, false);
- } else if (is_usb_port(dev)) {
- struct usb_port *port_dev = to_usb_port(dev);
- int port1 = port_dev->portnum;
- struct acpi_pld_info *pld;
- acpi_handle *handle;
- acpi_status status;
-
- /* Get the struct usb_device point of port's hub */
- udev = to_usb_device(dev->parent->parent);
-
- /*
- * The root hub ports' parent is the root hub. The non-root-hub
- * ports' parent is the parent hub port which the hub is
- * connected to.
- */
- if (!udev->parent) {
- struct usb_hcd *hcd = bus_to_hcd(udev->bus);
- int raw;
-
- raw = usb_hcd_find_raw_port_number(hcd, port1);
-
- adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev),
- raw);
-
- if (!adev)
- return NULL;
- } else {
- parent_handle =
- usb_get_hub_port_acpi_handle(udev->parent,
- udev->portnum);
- if (!parent_handle)
- return NULL;
-
- acpi_bus_get_device(parent_handle, &adev);
-
- adev = usb_acpi_find_port(adev, port1);
-
- if (!adev)
- return NULL;
- }
- handle = adev->handle;
- status = acpi_get_physical_device_location(handle, &pld);
- if (ACPI_FAILURE(status) || !pld)
- return adev;
+ acpi_bus_get_device(parent_handle, &adev);
+ port1 = port_dev->portnum;
+ }
+ return usb_acpi_find_port(adev, port1);
+}
+
+static struct acpi_device *
+usb_acpi_find_companion_for_port(struct usb_port *port_dev)
+{
+ struct acpi_device *adev;
+ struct acpi_pld_info *pld;
+ acpi_handle *handle;
+ acpi_status status;
+
+ adev = usb_acpi_get_companion_for_port(port_dev);
+ if (!adev)
+ return NULL;
+
+ handle = adev->handle;
+ status = acpi_get_physical_device_location(handle, &pld);
+ if (!ACPI_FAILURE(status) && pld) {
port_dev->location = USB_ACPI_LOCATION_VALID
| pld->group_token << 8 | pld->group_position;
port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
ACPI_FREE(pld);
+ }
- return adev;
+ return adev;
+}
+
+static struct acpi_device *
+usb_acpi_find_companion_for_device(struct usb_device *udev)
+{
+ struct acpi_device *adev;
+ struct usb_port *port_dev;
+ struct usb_hub *hub;
+
+ if (!udev->parent) {
+ /* root hub is only child (_ADR=0) under its parent, the HC */
+ adev = ACPI_COMPANION(udev->dev.parent);
+ return acpi_find_child_device(adev, 0, false);
}
+ hub = usb_hub_to_struct_hub(udev->parent);
+ if (!hub)
+ return NULL;
+
+ /*
+ * This is an embedded USB device connected to a port and such
+ * devices share port's ACPI companion.
+ */
+ port_dev = hub->ports[udev->portnum - 1];
+ return usb_acpi_get_companion_for_port(port_dev);
+}
+
+static struct acpi_device *usb_acpi_find_companion(struct device *dev)
+{
+ /*
+ * The USB hierarchy like following:
+ *
+ * Device (EHC1)
+ * Device (HUBN)
+ * Device (PR01)
+ * Device (PR11)
+ * Device (PR12)
+ * Device (FN12)
+ * Device (FN13)
+ * Device (PR13)
+ * ...
+ * where HUBN is root hub, and PRNN are USB ports and devices
+ * connected to them, and FNNN are individualk functions for
+ * connected composite USB devices. PRNN and FNNN may contain
+ * _CRS and other methods describing sideband resources for
+ * the connected device.
+ *
+ * On the kernel side both root hub and embedded USB devices are
+ * represented as instances of usb_device structure, and ports
+ * are represented as usb_port structures, so the whole process
+ * is split into 2 parts: finding companions for devices and
+ * finding companions for ports.
+ *
+ * Note that we do not handle individual functions of composite
+ * devices yet, for that we would need to assign companions to
+ * devices corresponding to USB interfaces.
+ */
+ if (is_usb_device(dev))
+ return usb_acpi_find_companion_for_device(to_usb_device(dev));
+ else if (is_usb_port(dev))
+ return usb_acpi_find_companion_for_port(to_usb_port(dev));
+
return NULL;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4ebfbd737905..7fcb9f782931 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -46,8 +46,7 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
-#include "usb.h"
-
+#include "hub.h"
const char *usbcore_name = "usbcore";
@@ -65,8 +64,8 @@ int usb_disabled(void)
EXPORT_SYMBOL_GPL(usb_disabled);
#ifdef CONFIG_PM
-static int usb_autosuspend_delay = 2; /* Default delay value,
- * in seconds */
+/* Default delay value, in seconds */
+static int usb_autosuspend_delay = CONFIG_USB_AUTOSUSPEND_DELAY;
module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
@@ -536,6 +535,27 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
return hcd->wireless;
}
+static bool usb_dev_authorized(struct usb_device *dev, struct usb_hcd *hcd)
+{
+ struct usb_hub *hub;
+
+ if (!dev->parent)
+ return true; /* Root hub always ok [and always wired] */
+
+ switch (hcd->dev_policy) {
+ case USB_DEVICE_AUTHORIZE_NONE:
+ default:
+ return false;
+
+ case USB_DEVICE_AUTHORIZE_ALL:
+ return true;
+
+ case USB_DEVICE_AUTHORIZE_INTERNAL:
+ hub = usb_hub_to_struct_hub(dev->parent);
+ return hub->ports[dev->portnum - 1]->connect_type ==
+ USB_PORT_CONNECT_TYPE_HARD_WIRED;
+ }
+}
/**
* usb_alloc_dev - usb device constructor (usbcore-internal)
@@ -663,12 +683,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->connect_time = jiffies;
dev->active_duration = -jiffies;
#endif
- if (root_hub) /* Root hub always ok [and always wired] */
- dev->authorized = 1;
- else {
- dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd);
+
+ dev->authorized = usb_dev_authorized(dev, usb_hcd);
+ if (!root_hub)
dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
- }
+
return dev;
}
EXPORT_SYMBOL_GPL(usb_alloc_dev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 546a2219454b..d95a5358f73d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -92,7 +92,8 @@ extern int usb_remote_wakeup(struct usb_device *dev);
extern int usb_runtime_suspend(struct device *dev);
extern int usb_runtime_resume(struct device *dev);
extern int usb_runtime_idle(struct device *dev);
-extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable);
+extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev);
+extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev);
#else
@@ -112,7 +113,12 @@ static inline int usb_autoresume_device(struct usb_device *udev)
return 0;
}
-static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+static inline int usb_enable_usb2_hardware_lpm(struct usb_device *udev)
+{
+ return 0;
+}
+
+static inline int usb_disable_usb2_hardware_lpm(struct usb_device *udev)
{
return 0;
}
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index b6a495e98fd8..68d095ae2865 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_DWC2
tristate "DesignWare USB2 DRD Core Support"
depends on HAS_DMA
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 68ad75a7460d..6812a8a3a98b 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -261,7 +261,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
- dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
+ dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
}
}
@@ -768,22 +768,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask)
return desc_size;
}
-/*
- * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain.
- * @hs_ep: The endpoint
- * @dma_buff: DMA address to use
- * @len: Length of the transfer
- *
- * This function will iterate over descriptor chain and fill its entries
- * with corresponding information based on transfer data.
- */
-static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
+static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep,
+ struct dwc2_dma_desc **desc,
dma_addr_t dma_buff,
- unsigned int len)
+ unsigned int len,
+ bool true_last)
{
- struct dwc2_hsotg *hsotg = hs_ep->parent;
int dir_in = hs_ep->dir_in;
- struct dwc2_dma_desc *desc = hs_ep->desc_list;
u32 mps = hs_ep->ep.maxpacket;
u32 maxsize = 0;
u32 offset = 0;
@@ -798,39 +789,77 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
hs_ep->desc_count = 1;
for (i = 0; i < hs_ep->desc_count; ++i) {
- desc->status = 0;
- desc->status |= (DEV_DMA_BUFF_STS_HBUSY
+ (*desc)->status = 0;
+ (*desc)->status |= (DEV_DMA_BUFF_STS_HBUSY
<< DEV_DMA_BUFF_STS_SHIFT);
if (len > maxsize) {
if (!hs_ep->index && !dir_in)
- desc->status |= (DEV_DMA_L | DEV_DMA_IOC);
+ (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC);
- desc->status |= (maxsize <<
- DEV_DMA_NBYTES_SHIFT & mask);
- desc->buf = dma_buff + offset;
+ (*desc)->status |=
+ maxsize << DEV_DMA_NBYTES_SHIFT & mask;
+ (*desc)->buf = dma_buff + offset;
len -= maxsize;
offset += maxsize;
} else {
- desc->status |= (DEV_DMA_L | DEV_DMA_IOC);
+ if (true_last)
+ (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC);
if (dir_in)
- desc->status |= (len % mps) ? DEV_DMA_SHORT :
- ((hs_ep->send_zlp) ? DEV_DMA_SHORT : 0);
- if (len > maxsize)
- dev_err(hsotg->dev, "wrong len %d\n", len);
+ (*desc)->status |= (len % mps) ? DEV_DMA_SHORT :
+ ((hs_ep->send_zlp && true_last) ?
+ DEV_DMA_SHORT : 0);
- desc->status |=
+ (*desc)->status |=
len << DEV_DMA_NBYTES_SHIFT & mask;
- desc->buf = dma_buff + offset;
+ (*desc)->buf = dma_buff + offset;
}
- desc->status &= ~DEV_DMA_BUFF_STS_MASK;
- desc->status |= (DEV_DMA_BUFF_STS_HREADY
+ (*desc)->status &= ~DEV_DMA_BUFF_STS_MASK;
+ (*desc)->status |= (DEV_DMA_BUFF_STS_HREADY
<< DEV_DMA_BUFF_STS_SHIFT);
- desc++;
+ (*desc)++;
+ }
+}
+
+/*
+ * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain.
+ * @hs_ep: The endpoint
+ * @ureq: Request to transfer
+ * @offset: offset in bytes
+ * @len: Length of the transfer
+ *
+ * This function will iterate over descriptor chain and fill its entries
+ * with corresponding information based on transfer data.
+ */
+static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
+ struct usb_request *ureq,
+ unsigned int offset,
+ unsigned int len)
+{
+ struct dwc2_dma_desc *desc = hs_ep->desc_list;
+ struct scatterlist *sg;
+ int i;
+ u8 desc_count = 0;
+
+ /* non-DMA sg buffer */
+ if (!ureq->num_sgs) {
+ dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
+ ureq->dma + offset, len, true);
+ return;
}
+
+ /* DMA sg buffer */
+ for_each_sg(ureq->sg, sg, ureq->num_sgs, i) {
+ dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
+ sg_dma_address(sg) + sg->offset, sg_dma_len(sg),
+ sg_is_last(sg));
+ desc_count += hs_ep->desc_count;
+ }
+
+ hs_ep->desc_count = desc_count;
}
/*
@@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
hs_ep->next_desc = 0;
list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) {
- ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma,
+ dma_addr_t dma_addr = hs_req->req.dma;
+
+ if (hs_req->req.num_sgs) {
+ WARN_ON(hs_req->req.num_sgs > 1);
+ dma_addr = sg_dma_address(hs_req->req.sg);
+ }
+ ret = dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr,
hs_req->req.length);
if (ret)
break;
@@ -1100,7 +1135,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
offset = ureq->actual;
/* Fill DDMA chain entries */
- dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq->dma + offset,
+ dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq, offset,
length);
/* write descriptor chain address to control register */
@@ -1399,7 +1434,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
*/
if (using_desc_dma(hs) && hs_ep->isochronous) {
if (hs_ep->target_frame != TARGET_FRAME_INITIAL) {
- dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma,
+ dma_addr_t dma_addr = hs_req->req.dma;
+
+ if (hs_req->req.num_sgs) {
+ WARN_ON(hs_req->req.num_sgs > 1);
+ dma_addr = sg_dma_address(hs_req->req.sg);
+ }
+ dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr,
hs_req->req.length);
}
return 0;
@@ -1987,13 +2028,12 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
index);
if (using_desc_dma(hsotg)) {
- /* Not specific buffer needed for ep0 ZLP */
- dma_addr_t dma = hs_ep->desc_list_dma;
-
if (!index)
dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
- dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
+ /* Not specific buffer needed for ep0 ZLP */
+ dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
+ hs_ep->desc_list_dma, 0, true);
} else {
dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
DXEPTSIZ_XFERSIZE(0),
@@ -4005,6 +4045,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
ret = -ENOMEM;
goto error1;
}
+ epctrl &= ~(DXEPCTL_TXFNUM_LIMIT << DXEPCTL_TXFNUM_SHIFT);
hsotg->fifo_map |= 1 << fifo_index;
epctrl |= DXEPCTL_TXFNUM(fifo_index);
hs_ep->fifo_index = fifo_index;
@@ -4385,6 +4426,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
hsotg->enabled = 0;
spin_unlock_irqrestore(&hsotg->lock, flags);
+ gadget->sg_supported = using_desc_dma(hsotg);
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
return 0;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index dd82fa516f3f..3f087962f498 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3981,10 +3981,8 @@ static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg,
gfp_t mem_flags)
{
struct dwc2_hcd_urb *urb;
- u32 size = sizeof(*urb) + iso_desc_count *
- sizeof(struct dwc2_hcd_iso_packet_desc);
- urb = kzalloc(size, mem_flags);
+ urb = kzalloc(struct_size(urb, iso_descs, iso_desc_count), mem_flags);
if (urb)
urb->packet_count = iso_desc_count;
return urb;
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 1a0404fda596..2b1494460d0c 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_DWC3
tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && HAS_DMA
@@ -86,11 +88,11 @@ config USB_DWC3_HAPS
platform, please say 'Y' or 'M' here.
config USB_DWC3_KEYSTONE
- tristate "Texas Instruments Keystone2 Platforms"
- depends on ARCH_KEYSTONE || COMPILE_TEST
+ tristate "Texas Instruments Keystone2/AM654 Platforms"
+ depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
default USB_DWC3
help
- Support of USB2/3 functionality in TI Keystone2 platforms.
+ Support of USB2/3 functionality in TI Keystone2 and AM654 platforms.
Say 'Y' or 'M' here if you have one such device
config USB_DWC3_OF_SIMPLE
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index df876418cb78..1528d395b156 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -692,7 +692,6 @@ struct dwc3_ep {
#define DWC3_EP_WEDGE BIT(2)
#define DWC3_EP_TRANSFER_STARTED BIT(3)
#define DWC3_EP_PENDING_REQUEST BIT(5)
-#define DWC3_EP_END_TRANSFER_PENDING BIT(7)
/* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN BIT(31)
@@ -863,6 +862,7 @@ struct dwc3_hwparams {
* @num_pending_sgs: counter to pending sgs
* @num_queued_sgs: counter to the number of sgs which already got queued
* @remaining: amount of data remaining
+ * @status: internal dwc3 request status tracking
* @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb
@@ -871,7 +871,6 @@ struct dwc3_hwparams {
* or unaligned OUT)
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
- * @started: request is started
*/
struct dwc3_request {
struct usb_request request;
@@ -883,6 +882,14 @@ struct dwc3_request {
unsigned num_pending_sgs;
unsigned int num_queued_sgs;
unsigned remaining;
+
+ unsigned int status;
+#define DWC3_REQUEST_STATUS_QUEUED 0
+#define DWC3_REQUEST_STATUS_STARTED 1
+#define DWC3_REQUEST_STATUS_CANCELLED 2
+#define DWC3_REQUEST_STATUS_COMPLETED 3
+#define DWC3_REQUEST_STATUS_UNKNOWN -1
+
u8 epnum;
struct dwc3_trb *trb;
dma_addr_t trb_dma;
@@ -892,7 +899,6 @@ struct dwc3_request {
unsigned needs_extra_trb:1;
unsigned direction:1;
unsigned mapped:1;
- unsigned started:1;
};
/*
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index 4f75ab3505b7..6759a7efd8d5 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -193,65 +193,69 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
* dwc3_gadget_event_string - returns event name
* @event: the event code
*/
-static inline const char *
-dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event)
+static inline const char *dwc3_gadget_event_string(char *str, size_t size,
+ const struct dwc3_event_devt *event)
{
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) {
case DWC3_DEVICE_EVENT_DISCONNECT:
- sprintf(str, "Disconnect: [%s]",
+ snprintf(str, size, "Disconnect: [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_RESET:
- sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "Reset [%s]",
+ dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CONNECT_DONE:
- sprintf(str, "Connection Done [%s]",
+ snprintf(str, size, "Connection Done [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
- sprintf(str, "Link Change [%s]",
+ snprintf(str, size, "Link Change [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_WAKEUP:
- sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "WakeUp [%s]",
+ dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_EOPF:
- sprintf(str, "End-Of-Frame [%s]",
+ snprintf(str, size, "End-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_SOF:
- sprintf(str, "Start-Of-Frame [%s]",
+ snprintf(str, size, "Start-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
- sprintf(str, "Erratic Error [%s]",
+ snprintf(str, size, "Erratic Error [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CMD_CMPL:
- sprintf(str, "Command Complete [%s]",
+ snprintf(str, size, "Command Complete [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_OVERFLOW:
- sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "Overflow [%s]",
+ dwc3_gadget_link_string(state));
break;
default:
- sprintf(str, "UNKNOWN");
+ snprintf(str, size, "UNKNOWN");
}
return str;
}
-static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
+static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str,
+ size_t size)
{
switch (t & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
- sprintf(str, "Get Interface Status(Intf = %d, Length = %d)",
- i, l);
+ snprintf(str, size, "Get Interface Status(Intf = %d, Length = %d)",
+ i, l);
break;
case USB_RECIP_ENDPOINT:
- sprintf(str, "Get Endpoint Status(ep%d%s)",
+ snprintf(str, size, "Get Endpoint Status(ep%d%s)",
i & ~USB_DIR_IN,
i & USB_DIR_IN ? "in" : "out");
break;
@@ -259,11 +263,11 @@ static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
}
static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
- __u16 i, char *str)
+ __u16 i, char *str, size_t size)
{
switch (t & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
- sprintf(str, "%s Device Feature(%s%s)",
+ snprintf(str, size, "%s Device Feature(%s%s)",
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
({char *s;
switch (v) {
@@ -311,13 +315,13 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
} s; }) : "");
break;
case USB_RECIP_INTERFACE:
- sprintf(str, "%s Interface Feature(%s)",
+ snprintf(str, size, "%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)",
+ snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)",
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
i & ~USB_DIR_IN,
@@ -326,15 +330,15 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
}
}
-static inline void dwc3_decode_set_address(__u16 v, char *str)
+static inline void dwc3_decode_set_address(__u16 v, char *str, size_t size)
{
- sprintf(str, "Set Address(Addr = %02x)", v);
+ snprintf(str, size, "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)
+ __u16 i, __u16 l, char *str, size_t size)
{
- sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)",
+ snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)",
b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
({ char *s;
switch (v >> 8) {
@@ -393,87 +397,92 @@ static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
}
-static inline void dwc3_decode_get_configuration(__u16 l, char *str)
+static inline void dwc3_decode_get_configuration(__u16 l, char *str,
+ size_t size)
{
- sprintf(str, "Get Configuration(Length = %d)", l);
+ snprintf(str, size, "Get Configuration(Length = %d)", l);
}
-static inline void dwc3_decode_set_configuration(__u8 v, char *str)
+static inline void dwc3_decode_set_configuration(__u8 v, char *str, size_t size)
{
- sprintf(str, "Set Configuration(Config = %d)", v);
+ snprintf(str, size, "Set Configuration(Config = %d)", v);
}
-static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str)
+static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str,
+ size_t size)
{
- sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l);
+ snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", i, l);
}
-static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str)
+static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str, size_t size)
{
- sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
+ snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
}
-static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str)
+static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str,
+ size_t size)
{
- sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
+ snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
}
-static inline void dwc3_decode_set_sel(__u16 l, char *str)
+static inline void dwc3_decode_set_sel(__u16 l, char *str, size_t size)
{
- sprintf(str, "Set SEL(Length = %d)", l);
+ snprintf(str, size, "Set SEL(Length = %d)", l);
}
-static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str)
+static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str, size_t size)
{
- sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v);
+ snprintf(str, size, "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)
+static inline const char *dwc3_decode_ctrl(char *str, size_t size,
+ __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);
+ dwc3_decode_get_status(bRequestType, wIndex, wLength, str,
+ size);
break;
case USB_REQ_CLEAR_FEATURE:
case USB_REQ_SET_FEATURE:
dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
- wIndex, str);
+ wIndex, str, size);
break;
case USB_REQ_SET_ADDRESS:
- dwc3_decode_set_address(wValue, str);
+ dwc3_decode_set_address(wValue, str, size);
break;
case USB_REQ_GET_DESCRIPTOR:
case USB_REQ_SET_DESCRIPTOR:
dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
- wIndex, wLength, str);
+ wIndex, wLength, str, size);
break;
case USB_REQ_GET_CONFIGURATION:
- dwc3_decode_get_configuration(wLength, str);
+ dwc3_decode_get_configuration(wLength, str, size);
break;
case USB_REQ_SET_CONFIGURATION:
- dwc3_decode_set_configuration(wValue, str);
+ dwc3_decode_set_configuration(wValue, str, size);
break;
case USB_REQ_GET_INTERFACE:
- dwc3_decode_get_intf(wIndex, wLength, str);
+ dwc3_decode_get_intf(wIndex, wLength, str, size);
break;
case USB_REQ_SET_INTERFACE:
- dwc3_decode_set_intf(wValue, wIndex, str);
+ dwc3_decode_set_intf(wValue, wIndex, str, size);
break;
case USB_REQ_SYNCH_FRAME:
- dwc3_decode_synch_frame(wIndex, wLength, str);
+ dwc3_decode_synch_frame(wIndex, wLength, str, size);
break;
case USB_REQ_SET_SEL:
- dwc3_decode_set_sel(wLength, str);
+ dwc3_decode_set_sel(wLength, str, size);
break;
case USB_REQ_SET_ISOCH_DELAY:
- dwc3_decode_set_isoch_delay(wValue, str);
+ dwc3_decode_set_isoch_delay(wValue, str, size);
break;
default:
- sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x",
+ snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x",
bRequestType, bRequest,
cpu_to_le16(wValue) & 0xff,
cpu_to_le16(wValue) >> 8,
@@ -490,16 +499,15 @@ static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
-static inline const char *
-dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
- u32 ep0state)
+static inline const char *dwc3_ep_event_string(char *str, size_t size,
+ const struct dwc3_event_depevt *event, u32 ep0state)
{
u8 epnum = event->endpoint_number;
size_t len;
int status;
int ret;
- ret = sprintf(str, "ep%d%s: ", epnum >> 1,
+ ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
(epnum & 1) ? "in" : "out");
if (ret < 0)
return "UNKNOWN";
@@ -509,7 +517,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
len = strlen(str);
- sprintf(str + len, "Transfer Complete (%c%c%c)",
+ snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
status & DEPEVT_STATUS_LST ? 'L' : 'l');
@@ -517,12 +525,13 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
len = strlen(str);
if (epnum <= 1)
- sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state));
+ snprintf(str + len, size - len, " [%s]",
+ dwc3_ep0_state_string(ep0state));
break;
case DWC3_DEPEVT_XFERINPROGRESS:
len = strlen(str);
- sprintf(str + len, "Transfer In Progress [%d] (%c%c%c)",
+ snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
event->parameters,
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
@@ -531,47 +540,51 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
case DWC3_DEPEVT_XFERNOTREADY:
len = strlen(str);
- sprintf(str + len, "Transfer Not Ready [%d]%s",
+ snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
event->parameters,
status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
" (Active)" : " (Not Active)");
+ len = strlen(str);
+
/* Control Endpoints */
if (epnum <= 1) {
int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
switch (phase) {
case DEPEVT_STATUS_CONTROL_DATA:
- strcat(str, " [Data Phase]");
+ snprintf(str + ret, size - ret,
+ " [Data Phase]");
break;
case DEPEVT_STATUS_CONTROL_STATUS:
- strcat(str, " [Status Phase]");
+ snprintf(str + ret, size - ret,
+ " [Status Phase]");
}
}
break;
case DWC3_DEPEVT_RXTXFIFOEVT:
- strcat(str, "FIFO");
+ snprintf(str + ret, size - ret, "FIFO");
break;
case DWC3_DEPEVT_STREAMEVT:
status = event->status;
switch (status) {
case DEPEVT_STREAMEVT_FOUND:
- sprintf(str + ret, " Stream %d Found",
+ snprintf(str + ret, size - ret, " Stream %d Found",
event->parameters);
break;
case DEPEVT_STREAMEVT_NOTFOUND:
default:
- strcat(str, " Stream Not Found");
+ snprintf(str + ret, size - ret, " Stream Not Found");
break;
}
break;
case DWC3_DEPEVT_EPCMDCMPLT:
- strcat(str, "Endpoint Command Complete");
+ snprintf(str + ret, size - ret, "Endpoint Command Complete");
break;
default:
- sprintf(str, "UNKNOWN");
+ snprintf(str, size, "UNKNOWN");
}
return str;
@@ -611,14 +624,15 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
}
}
-static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state)
+static inline const char *dwc3_decode_event(char *str, size_t size, u32 event,
+ u32 ep0state)
{
const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec)
- return dwc3_gadget_event_string(str, &evt.devt);
+ return dwc3_gadget_event_string(str, size, &evt.devt);
else
- return dwc3_ep_event_string(str, &evt.depevt, ep0state);
+ return dwc3_ep_event_string(str, size, &evt.depevt, ep0state);
}
static inline const char *dwc3_ep_cmd_status_string(int status)
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index 869725d15c74..726100d1ac0d 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -457,8 +457,13 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
* This device property is for kernel internal use only and
* is expected to be set by the glue code.
*/
- if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
- return extcon_get_extcon_dev(name);
+ if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
+ edev = extcon_get_extcon_dev(name);
+ if (!edev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ return edev;
+ }
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index cb7fcd7c0ad8..c1e9ea621f41 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -78,7 +78,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
for (i = 0; i < exynos->num_clks; i++) {
ret = clk_prepare_enable(exynos->clks[i]);
if (ret) {
- while (--i > 0)
+ while (i-- > 0)
clk_disable_unprepare(exynos->clks[i]);
return ret;
}
@@ -223,7 +223,7 @@ static int dwc3_exynos_resume(struct device *dev)
for (i = 0; i < exynos->num_clks; i++) {
ret = clk_prepare_enable(exynos->clks[i]);
if (ret) {
- while (--i > 0)
+ while (i-- > 0)
clk_disable_unprepare(exynos->clks[i]);
return ret;
}
diff --git a/drivers/usb/dwc3/dwc3-haps.c b/drivers/usb/dwc3/dwc3-haps.c
index 02d57d98ef9b..3cecbf169452 100644
--- a/drivers/usb/dwc3/dwc3-haps.c
+++ b/drivers/usb/dwc3/dwc3-haps.c
@@ -106,6 +106,15 @@ static const struct pci_device_id dwc3_haps_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
+ /*
+ * i.MX6QP and i.MX7D platform use a PCIe controller with the
+ * same VID and PID as this USB controller. The system may
+ * incorrectly match this driver to that PCIe controller. To
+ * workaround this, specifically use class type USB to prevent
+ * incorrect driver matching.
+ */
+ .class = (PCI_CLASS_SERIAL_USB << 8),
+ .class_mask = 0xffff00,
},
{
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 193a9a88222a..cbee5fb9b9fb 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -106,6 +106,10 @@ static int kdwc3_probe(struct platform_device *pdev)
goto err_irq;
}
+ /* IRQ processing not required currently for AM65 */
+ if (of_device_is_compatible(node, "ti,am654-dwc3"))
+ goto skip_irq;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "missing irq\n");
@@ -123,6 +127,7 @@ static int kdwc3_probe(struct platform_device *pdev)
kdwc3_enable_irqs(kdwc);
+skip_irq:
error = of_platform_populate(node, NULL, NULL, dev);
if (error) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
@@ -152,8 +157,11 @@ static int kdwc3_remove_core(struct device *dev, void *c)
static int kdwc3_remove(struct platform_device *pdev)
{
struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
+ struct device_node *node = pdev->dev.of_node;
+
+ if (!of_device_is_compatible(node, "ti,am654-dwc3"))
+ kdwc3_disable_irqs(kdwc);
- kdwc3_disable_irqs(kdwc);
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
pm_runtime_put_sync(kdwc->dev);
pm_runtime_disable(kdwc->dev);
@@ -165,6 +173,7 @@ static int kdwc3_remove(struct platform_device *pdev)
static const struct of_device_id kdwc3_of_match[] = {
{ .compatible = "ti,keystone-dwc3", },
+ { .compatible = "ti,am654-dwc3" },
{},
};
MODULE_DEVICE_TABLE(of, kdwc3_of_match);
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index a6d0203e40b6..184df4daa590 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -595,6 +595,7 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
static const struct of_device_id dwc3_qcom_of_match[] = {
{ .compatible = "qcom,dwc3" },
{ .compatible = "qcom,msm8996-dwc3" },
+ { .compatible = "qcom,msm8998-dwc3" },
{ .compatible = "qcom,sdm845-dwc3" },
{ }
};
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 07bd31bb2f8a..e293400cc6e9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -174,9 +174,9 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
{
struct dwc3 *dwc = dep->dwc;
- req->started = false;
list_del(&req->list);
req->remaining = 0;
+ req->needs_extra_trb = false;
if (req->request.status == -EINPROGRESS)
req->request.status = status;
@@ -208,6 +208,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
struct dwc3 *dwc = dep->dwc;
dwc3_gadget_del_and_unmap_request(dep, req, status);
+ req->status = DWC3_REQUEST_STATUS_COMPLETED;
spin_unlock(&dwc->lock);
usb_gadget_giveback_request(&dep->endpoint, &req->request);
@@ -383,19 +384,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
- if (ret == 0) {
- switch (DWC3_DEPCMD_CMD(cmd)) {
- case DWC3_DEPCMD_STARTTRANSFER:
- dep->flags |= DWC3_EP_TRANSFER_STARTED;
- dwc3_gadget_ep_get_transfer_index(dep);
- break;
- case DWC3_DEPCMD_ENDTRANSFER:
- dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
- break;
- default:
- /* nothing */
- break;
- }
+ if (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
+ dep->flags |= DWC3_EP_TRANSFER_STARTED;
+ dwc3_gadget_ep_get_transfer_index(dep);
}
if (saved_config) {
@@ -641,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
- dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number);
@@ -697,12 +687,13 @@ out:
return 0;
}
-static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force);
+static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+ bool interrupt);
static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_request *req;
- dwc3_stop_active_transfer(dep, true);
+ dwc3_stop_active_transfer(dep, true, false);
/* - giveback all requests to gadget driver */
while (!list_empty(&dep->started_list)) {
@@ -747,7 +738,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->stream_capable = false;
dep->type = 0;
- dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
+ dep->flags = 0;
/* Clear out the ep descriptors for non-ep0 */
if (dep->number > 1) {
@@ -846,6 +837,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
req->direction = dep->direction;
req->epnum = dep->number;
req->dep = dep;
+ req->status = DWC3_REQUEST_STATUS_UNKNOWN;
trace_dwc3_alloc_request(req);
@@ -1118,7 +1110,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
unsigned int rem = length % maxp;
- if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
+ if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
@@ -1359,7 +1351,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
* to wait for the next XferNotReady to test the command again
*/
if (cmd_status == 0) {
- dwc3_stop_active_transfer(dep, true);
+ dwc3_stop_active_transfer(dep, true, true);
return 0;
}
}
@@ -1434,6 +1426,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
&req->request, req->dep->name))
return -EINVAL;
+ if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED,
+ "%s: request %pK already in flight\n",
+ dep->name, &req->request))
+ return -EINVAL;
+
pm_runtime_get(dwc->dev);
req->request.actual = 0;
@@ -1442,6 +1439,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
trace_dwc3_ep_queue(req);
list_add_tail(&req->list, &dep->pending_list);
+ req->status = DWC3_REQUEST_STATUS_QUEUED;
/*
* NOTICE: Isochronous endpoints should NEVER be prestarted. We must
@@ -1505,6 +1503,8 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
}
+
+ req->num_trbs = 0;
}
static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
@@ -1546,13 +1546,16 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
}
if (r == req) {
/* wait until it is processed */
- dwc3_stop_active_transfer(dep, true);
+ dwc3_stop_active_transfer(dep, true, true);
if (!r->trb)
goto out0;
dwc3_gadget_move_cancelled_request(req);
- goto out0;
+ if (dep->flags & DWC3_EP_TRANSFER_STARTED)
+ goto out0;
+ else
+ goto out1;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
request, ep->name);
@@ -1560,6 +1563,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
goto out0;
}
+out1:
dwc3_gadget_giveback(dep, req, -ECONNRESET);
out0:
@@ -1984,6 +1988,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
+ dwc->link_state = DWC3_LINK_STATE_SS_DIS;
dwc3_ep0_out_start(dwc);
dwc3_gadget_enable_irq(dwc);
@@ -2498,7 +2503,7 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (stop) {
- dwc3_stop_active_transfer(dep, true);
+ dwc3_stop_active_transfer(dep, true, true);
dep->flags = DWC3_EP_ENABLED;
}
@@ -2545,7 +2550,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dep = dwc->eps[epnum];
if (!(dep->flags & DWC3_EP_ENABLED)) {
- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+ if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
return;
/* Handle only EPCMDCMPLT when EP disabled */
@@ -2569,7 +2574,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
cmd = DEPEVT_PARAMETER_CMD(event->parameters);
if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
- dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
+ dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
}
break;
@@ -2619,15 +2624,15 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
}
}
-static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
+static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+ bool interrupt)
{
struct dwc3 *dwc = dep->dwc;
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
- if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) ||
- !dep->resource_index)
+ if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
return;
/*
@@ -2663,17 +2668,15 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
cmd = DWC3_DEPCMD_ENDTRANSFER;
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
- cmd |= DWC3_DEPCMD_CMDIOC;
+ cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
WARN_ON_ONCE(ret);
dep->resource_index = 0;
- if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) {
- dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+ if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
udelay(100);
- }
}
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
@@ -3337,6 +3340,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err4;
}
+ dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
+
return 0;
err4:
@@ -3379,6 +3384,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
dwc3_disconnect_gadget(dwc);
__dwc3_gadget_stop(dwc);
+ synchronize_irq(dwc->irq_gadget);
+
return 0;
}
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 023a473648eb..3ed738e86ea7 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -75,7 +75,7 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{
struct dwc3_ep *dep = req->dep;
- req->started = true;
+ req->status = DWC3_REQUEST_STATUS_STARTED;
list_move_tail(&req->list, &dep->started_list);
}
@@ -90,7 +90,7 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req)
{
struct dwc3_ep *dep = req->dep;
- req->started = false;
+ req->status = DWC3_REQUEST_STATUS_CANCELLED;
list_move_tail(&req->list, &dep->cancelled_list);
}
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
index e97a00593dda..818a63da1a44 100644
--- a/drivers/usb/dwc3/trace.h
+++ b/drivers/usb/dwc3/trace.h
@@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
__entry->ep0state = dwc->ep0state;
),
TP_printk("event (%08x): %s", __entry->event,
- dwc3_decode_event(__get_str(str), __entry->event,
- __entry->ep0state))
+ dwc3_decode_event(__get_str(str), DWC3_MSG_MAX,
+ __entry->event, __entry->ep0state))
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
@@ -86,7 +86,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength);
),
- TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType,
+ TP_printk("%s", dwc3_decode_ctrl(__get_str(str), DWC3_MSG_MAX,
+ __entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
@@ -305,7 +306,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__entry->trb_enqueue = dep->trb_enqueue;
__entry->trb_dequeue = dep->trb_dequeue;
),
- TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c:%c",
+ TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
@@ -315,7 +316,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
- __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 31cce7805eb2..ec189d7855a0 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Gadget support on a system involves
# (a) a peripheral controller, and
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 71b15c65b90f..1eb4fa2e623f 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -67,9 +67,6 @@ struct usb_ep *usb_ep_autoconfig_ss(
)
{
struct usb_ep *ep;
- u8 type;
-
- type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (gadget->ops->match_ep) {
ep = gadget->ops->match_ep(gadget, desc, ep_comp);
@@ -109,16 +106,6 @@ found_ep:
desc->bEndpointAddress |= gadget->out_epnum;
}
- /* report (variable) full speed bulk maxpacket */
- if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
- int size = ep->maxpacket_limit;
-
- /* min() doesn't work on bitfields with gcc-3.5 */
- if (size > 64)
- size = 64;
- desc->wMaxPacketSize = cpu_to_le16(size);
- }
-
ep->address = desc->bEndpointAddress;
ep->desc = NULL;
ep->comp_desc = NULL;
@@ -152,9 +139,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
*
* On success, this returns an claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
- * is initialized as if the endpoint were used at full speed. To prevent
- * the endpoint from being returned by a later autoconfig call, claims it
- * by assigning ep->claimed to true.
+ * is initialized as if the endpoint were used at full speed. Because of
+ * that the users must consider adjusting the autoconfigured descriptor.
+ * To prevent the endpoint from being returned by a later autoconfig call,
+ * claims it by assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@@ -163,7 +151,26 @@ struct usb_ep *usb_ep_autoconfig(
struct usb_endpoint_descriptor *desc
)
{
- return usb_ep_autoconfig_ss(gadget, desc, NULL);
+ struct usb_ep *ep;
+ u8 type;
+
+ ep = usb_ep_autoconfig_ss(gadget, desc, NULL);
+ if (!ep)
+ return NULL;
+
+ type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+ /* report (variable) full speed bulk maxpacket */
+ if (type == USB_ENDPOINT_XFER_BULK) {
+ int size = ep->maxpacket_limit;
+
+ /* min() doesn't work on bitfields with gcc-3.5 */
+ if (size > 64)
+ size = 64;
+ desc->wMaxPacketSize = cpu_to_le16(size);
+ }
+
+ return ep;
}
EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 1e5430438703..20413c276c61 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1082,6 +1082,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
* condition with req->complete callback.
*/
usb_ep_dequeue(ep->ep, req);
+ wait_for_completion(&done);
interrupted = ep->status < 0;
}
@@ -2843,12 +2844,18 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
struct usb_request *req;
struct usb_ep *ep;
u8 bEndpointAddress;
+ u16 wMaxPacketSize;
/*
* We back up bEndpointAddress because autoconfig overwrites
* it with physical endpoint address.
*/
bEndpointAddress = ds->bEndpointAddress;
+ /*
+ * We back up wMaxPacketSize because autoconfig treats
+ * endpoint descriptors as if they were full speed.
+ */
+ wMaxPacketSize = ds->wMaxPacketSize;
pr_vdebug("autoconfig\n");
ep = usb_ep_autoconfig(func->gadget, ds);
if (unlikely(!ep))
@@ -2869,6 +2876,11 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
*/
if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
ds->bEndpointAddress = bEndpointAddress;
+ /*
+ * Restore wMaxPacketSize which was potentially
+ * overwritten by autoconfig.
+ */
+ ds->wMaxPacketSize = wMaxPacketSize;
}
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index 9cdef108fb1b..ed68a4860b7d 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -838,7 +838,7 @@ static struct usb_function *source_sink_alloc_func(
ss = kzalloc(sizeof(*ss), GFP_KERNEL);
if (!ss)
- return NULL;
+ return ERR_PTR(-ENOMEM);
ss_opts = container_of(fi, struct f_ss_opts, func_inst);
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 2746a926a8d9..00d346965f7a 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -459,10 +459,10 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} 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);
+ 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;
@@ -568,6 +568,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
as_out_interface_alt_0_desc.bInterfaceNumber = status;
as_out_interface_alt_1_desc.bInterfaceNumber = status;
+ ac_header_desc.baInterfaceNr[0] = status;
uac1->as_out_intf = status;
uac1->as_out_alt = 0;
@@ -576,6 +577,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
as_in_interface_alt_0_desc.bInterfaceNumber = status;
as_in_interface_alt_1_desc.bInterfaceNumber = status;
+ ac_header_desc.baInterfaceNr[1] = status;
uac1->as_in_intf = status;
uac1->as_in_alt = 0;
diff --git a/drivers/usb/gadget/function/u_ecm.h b/drivers/usb/gadget/function/u_ecm.h
index 050aa672ee7f..098ece573a5e 100644
--- a/drivers/usb/gadget/function/u_ecm.h
+++ b/drivers/usb/gadget/function/u_ecm.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_ECM_H
diff --git a/drivers/usb/gadget/function/u_eem.h b/drivers/usb/gadget/function/u_eem.h
index de3828d3e8f0..921386a375cf 100644
--- a/drivers/usb/gadget/function/u_eem.h
+++ b/drivers/usb/gadget/function/u_eem.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_EEM_H
diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
index cd33cee4d78b..d8b92485b727 100644
--- a/drivers/usb/gadget/function/u_ether_configfs.h
+++ b/drivers/usb/gadget/function/u_ether_configfs.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef __U_ETHER_CONFIGFS_H
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index c3aba4dfa958..f9b0cf67360d 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_FFS_H
diff --git a/drivers/usb/gadget/function/u_gether.h b/drivers/usb/gadget/function/u_gether.h
index 5b7e2eb90336..ce4f07626f96 100644
--- a/drivers/usb/gadget/function/u_gether.h
+++ b/drivers/usb/gadget/function/u_gether.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_GETHER_H
diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h
index 2f5ca4bfa7ff..1594bfa312eb 100644
--- a/drivers/usb/gadget/function/u_hid.h
+++ b/drivers/usb/gadget/function/u_hid.h
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_HID_H
diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/u_midi.h
index 5599aa5fc977..29bf006c0a13 100644
--- a/drivers/usb/gadget/function/u_midi.h
+++ b/drivers/usb/gadget/function/u_midi.h
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_MIDI_H
diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h
index 67324f983343..d483e45c0f77 100644
--- a/drivers/usb/gadget/function/u_ncm.h
+++ b/drivers/usb/gadget/function/u_ncm.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_NCM_H
diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h
index 6088ff744194..78797764f478 100644
--- a/drivers/usb/gadget/function/u_printer.h
+++ b/drivers/usb/gadget/function/u_printer.h
@@ -7,7 +7,7 @@
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_PRINTER_H
diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h
index d65fb4ebac3c..1e148b76f339 100644
--- a/drivers/usb/gadget/function/u_rndis.h
+++ b/drivers/usb/gadget/function/u_rndis.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_RNDIS_H
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 29436f75bbe0..65f634ec7fc2 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/tty.h>
@@ -26,6 +25,7 @@
#include <linux/module.h>
#include <linux/console.h>
#include <linux/kthread.h>
+#include <linux/workqueue.h>
#include <linux/kfifo.h>
#include "u_serial.h"
@@ -110,7 +110,7 @@ struct gs_port {
int read_allocated;
struct list_head read_queue;
unsigned n_read;
- struct tasklet_struct push;
+ struct delayed_work push;
struct list_head write_pool;
int write_started;
@@ -352,9 +352,10 @@ __acquires(&port->port_lock)
* So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
* can be buffered before the TTY layer's buffers (currently 64 KB).
*/
-static void gs_rx_push(unsigned long _port)
+static void gs_rx_push(struct work_struct *work)
{
- struct gs_port *port = (void *)_port;
+ struct delayed_work *w = to_delayed_work(work);
+ struct gs_port *port = container_of(w, struct gs_port, push);
struct tty_struct *tty;
struct list_head *queue = &port->read_queue;
bool disconnect = false;
@@ -429,21 +430,13 @@ static void gs_rx_push(unsigned long _port)
/* We want our data queue to become empty ASAP, keeping data
* in the tty and ldisc (not here). If we couldn't push any
- * this time around, there may be trouble unless there's an
- * implicit tty_unthrottle() call on its way...
+ * this time around, RX may be starved, so wait until next jiffy.
*
- * REVISIT we should probably add a timer to keep the tasklet
- * from starving ... but it's not clear that case ever happens.
+ * We may leave non-empty queue only when there is a tty, and
+ * either it is throttled or there is no more room in flip buffer.
*/
- if (!list_empty(queue) && tty) {
- if (!tty_throttled(tty)) {
- if (do_push)
- tasklet_schedule(&port->push);
- else
- pr_warn("ttyGS%d: RX not scheduled?\n",
- port->port_num);
- }
- }
+ if (!list_empty(queue) && !tty_throttled(tty))
+ schedule_delayed_work(&port->push, 1);
/* If we're still connected, refill the USB RX queue. */
if (!disconnect && port->port_usb)
@@ -459,7 +452,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
/* Queue all received data until the tty layer is ready for it. */
spin_lock(&port->port_lock);
list_add_tail(&req->list, &port->read_queue);
- tasklet_schedule(&port->push);
+ schedule_delayed_work(&port->push, 0);
spin_unlock(&port->port_lock);
}
@@ -854,8 +847,8 @@ static void gs_unthrottle(struct tty_struct *tty)
* rts/cts, or other handshaking with the host, but if the
* read queue backs up enough we'll be NAKing OUT packets.
*/
- tasklet_schedule(&port->push);
pr_vdebug("ttyGS%d: unthrottle\n", port->port_num);
+ schedule_delayed_work(&port->push, 0);
}
spin_unlock_irqrestore(&port->port_lock, flags);
}
@@ -1159,7 +1152,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
init_waitqueue_head(&port->drain_wait);
init_waitqueue_head(&port->close_wait);
- tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
+ INIT_DELAYED_WORK(&port->push, gs_rx_push);
INIT_LIST_HEAD(&port->read_pool);
INIT_LIST_HEAD(&port->read_queue);
@@ -1186,7 +1179,7 @@ static int gs_closed(struct gs_port *port)
static void gserial_free_port(struct gs_port *port)
{
- tasklet_kill(&port->push);
+ cancel_delayed_work_sync(&port->push);
/* wait for old opens to finish */
wait_event(port->close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index 8362ee572e1e..82048791eb6e 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_UAC2_H
diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h
index 5242d489e20a..16da49a2fcf2 100644
--- a/drivers/usb/gadget/function/u_uvc.h
+++ b/drivers/usb/gadget/function/u_uvc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef U_UVC_H
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 099d650082e5..1473d25ff17a 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -56,6 +56,8 @@ extern unsigned int uvc_gadget_trace_param;
dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_info(f, fmt, args...) \
dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
+#define uvcg_warn(f, fmt, args...) \
+ dev_warn(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_err(f, fmt, args...) \
dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index bc1e2af566c3..00fb58e50a15 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#include <linux/sort.h>
@@ -1570,10 +1570,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
if (ret) \
goto end; \
\
- if (num > 255) { \
- ret = -EINVAL; \
- goto end; \
- } \
u->desc.aname = num; \
ret = len; \
end: \
@@ -1767,10 +1763,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
if (ret) \
goto end; \
\
- if (num > 255) { \
- ret = -EINVAL; \
- goto end; \
- } \
u->desc.aname = num; \
ret = len; \
end: \
diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h
index 8549c0b27b9d..341391dbc81f 100644
--- a/drivers/usb/gadget/function/uvc_configfs.h
+++ b/drivers/usb/gadget/function/uvc_configfs.h
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef UVC_CONFIGFS_H
#define UVC_CONFIGFS_H
diff --git a/drivers/usb/gadget/function/uvc_v4l2.h b/drivers/usb/gadget/function/uvc_v4l2.h
index a75e9c397446..452d71059b3f 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.h
+++ b/drivers/usb/gadget/function/uvc_v4l2.h
@@ -7,7 +7,7 @@
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef __UVC_V4L2_H__
diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h
index 278dc52c7604..dff12103f696 100644
--- a/drivers/usb/gadget/function/uvc_video.h
+++ b/drivers/usb/gadget/function/uvc_video.h
@@ -7,7 +7,7 @@
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef __UVC_VIDEO_H__
#define __UVC_VIDEO_H__
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index 784bf86dad4f..d7c9e4fca895 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Gadget support on a system involves
# (a) a peripheral controller, and
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index 37ca0e669bd8..249277d0e53f 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1218,27 +1218,27 @@ ep0_poll (struct file *fd, poll_table *wait)
if (dev->state <= STATE_DEV_OPENED)
return DEFAULT_POLLMASK;
- poll_wait(fd, &dev->wait, wait);
-
- spin_lock_irq (&dev->lock);
-
- /* report fd mode change before acting on it */
- if (dev->setup_abort) {
- dev->setup_abort = 0;
- mask = EPOLLHUP;
- goto out;
- }
-
- if (dev->state == STATE_DEV_SETUP) {
- if (dev->setup_in || dev->setup_can_stall)
- mask = EPOLLOUT;
- } else {
- if (dev->ev_next != 0)
- mask = EPOLLIN;
- }
+ poll_wait(fd, &dev->wait, wait);
+
+ spin_lock_irq(&dev->lock);
+
+ /* report fd mode change before acting on it */
+ if (dev->setup_abort) {
+ dev->setup_abort = 0;
+ mask = EPOLLHUP;
+ goto out;
+ }
+
+ if (dev->state == STATE_DEV_SETUP) {
+ if (dev->setup_in || dev->setup_can_stall)
+ mask = EPOLLOUT;
+ } else {
+ if (dev->ev_next != 0)
+ mask = EPOLLIN;
+ }
out:
- spin_unlock_irq(&dev->lock);
- return mask;
+ spin_unlock_irq(&dev->lock);
+ return mask;
}
static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c
index dbaa46eee853..6aea1ecb3999 100644
--- a/drivers/usb/gadget/u_f.c
+++ b/drivers/usb/gadget/u_f.c
@@ -5,7 +5,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#include "u_f.h"
diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h
index 09f90447fed5..eaa13fd3dc7f 100644
--- a/drivers/usb/gadget/u_f.h
+++ b/drivers/usb/gadget/u_f.h
@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef __U_F_H__
diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h
index 8acd21779ac8..5d7d35c8cc31 100644
--- a/drivers/usb/gadget/u_os_desc.h
+++ b/drivers/usb/gadget/u_os_desc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
#ifndef __U_OS_DESC_H__
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 0a16cbd4e528..ef0259a950ba 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Gadget support on a system involves
# (a) a peripheral controller, and
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
index 4a28e3fbeb0b..83340f4fdc6e 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
@@ -120,7 +120,7 @@ static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep)
/* No current DMA ongoing */
req->active = false;
- /* Grab lenght out of HW */
+ /* Grab length out of HW */
len = VHUB_EP_DMA_TX_SIZE(stat);
/* If not using DMA, copy data out if needed */
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
index 35ba0e55a2e9..7c040f56100e 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
@@ -295,7 +295,7 @@ static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
dsize = AST_VHUB_HUB_DESC_SIZE;
memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc));
- BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
+ BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
break;
default:
return std_req_stall;
diff --git a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig
index c74ac25dddcd..3e88c7670b2e 100644
--- a/drivers/usb/gadget/udc/bdc/Kconfig
+++ b/drivers/usb/gadget/udc/bdc/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_BDC_UDC
tristate "Broadcom USB3.0 device controller IP driver(BDC)"
depends on USB_GADGET && HAS_DMA
diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c
index 6305bf2c8b59..44c2a5eef785 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_cmd.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c
@@ -311,8 +311,8 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum)
/* if the endpoint it not stallled */
if (!(ep->flags & BDC_EP_STALL)) {
ret = bdc_ep_set_stall(bdc, epnum);
- if (ret)
- return ret;
+ if (ret)
+ return ret;
}
}
/* Preserve the seq number for ep0 only */
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index 01b44e159623..ccbd1d34eb2a 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -172,8 +172,9 @@ static int scratchpad_setup(struct bdc *bdc)
/* Refer to BDC spec, Table 4 for description of SPB */
sp_buff_size = 1 << (sp_buff_size + 5);
dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
- bdc->scratchpad.buff = dma_zalloc_coherent(bdc->dev, sp_buff_size,
- &bdc->scratchpad.sp_dma, GFP_KERNEL);
+ bdc->scratchpad.buff = dma_alloc_coherent(bdc->dev, sp_buff_size,
+ &bdc->scratchpad.sp_dma,
+ GFP_KERNEL);
if (!bdc->scratchpad.buff)
goto fail;
@@ -202,11 +203,9 @@ static int setup_srr(struct bdc *bdc, int interrupter)
bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST);
bdc->srr.dqp_index = 0;
/* allocate the status report descriptors */
- bdc->srr.sr_bds = dma_zalloc_coherent(
- bdc->dev,
- NUM_SR_ENTRIES * sizeof(struct bdc_bd),
- &bdc->srr.dma_addr,
- GFP_KERNEL);
+ bdc->srr.sr_bds = dma_alloc_coherent(bdc->dev,
+ NUM_SR_ENTRIES * sizeof(struct bdc_bd),
+ &bdc->srr.dma_addr, GFP_KERNEL);
if (!bdc->srr.sr_bds)
return -ENOMEM;
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 87d6b12779f2..7cf34beb50df 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue);
* @ep:the endpoint associated with the request
* @req:the request being canceled
*
- * If the request is still active on the endpoint, it is dequeued and its
- * completion routine is called (with status -ECONNRESET); else a negative
- * error code is returned. This is guaranteed to happen before the call to
- * usb_ep_dequeue() returns.
+ * If the request is still active on the endpoint, it is dequeued and
+ * eventually its completion routine is called (with status -ECONNRESET);
+ * else a negative error code is returned. This routine is asynchronous,
+ * that is, it may return before the completion routine runs.
*
* Note that some hardware can't clear out write fifos (to unlink the request
* at the head of the queue) except as part of disconnecting from usb. Such
diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c
index bc6abaea907d..cec49294bac6 100644
--- a/drivers/usb/gadget/udc/fotg210-udc.c
+++ b/drivers/usb/gadget/udc/fotg210-udc.c
@@ -326,6 +326,7 @@ dma_reset:
static void fotg210_start_dma(struct fotg210_ep *ep,
struct fotg210_request *req)
{
+ struct device *dev = &ep->fotg210->gadget.dev;
dma_addr_t d;
u8 *buffer;
u32 length;
@@ -348,18 +349,14 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
length = req->req.length;
}
- d = dma_map_single(NULL, buffer, length,
+ d = dma_map_single(dev, buffer, length,
ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (dma_mapping_error(NULL, d)) {
+ if (dma_mapping_error(dev, d)) {
pr_err("dma_mapping_error\n");
return;
}
- dma_sync_single_for_device(NULL, d, length,
- ep->dir_in ? DMA_TO_DEVICE :
- DMA_FROM_DEVICE);
-
fotg210_enable_dma(ep, d, length);
/* check if dma is done */
@@ -370,7 +367,7 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
/* update actual transfer length */
req->req.actual += length;
- dma_unmap_single(NULL, d, length, DMA_TO_DEVICE);
+ dma_unmap_single(dev, d, length, DMA_TO_DEVICE);
}
static void fotg210_ep0_queue(struct fotg210_ep *ep,
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 660878a19505..b77f3126580e 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -2083,7 +2083,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
#if defined(PLX_PCI_RDK2)
/* see if PCI int for us by checking irqstat */
intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
- if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+ if (!(intcsr & (1 << NET2272_PCI_IRQ))) {
spin_unlock(&dev->lock);
return IRQ_NONE;
}
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index e7dae5379e04..f63f82450bf4 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -516,8 +516,8 @@ static int net2280_disable(struct usb_ep *_ep)
unsigned long flags;
ep = container_of(_ep, struct net2280_ep, ep);
- if (!_ep || !ep->desc || _ep->name == ep0name) {
- pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
+ if (!_ep || _ep->name == ep0name) {
+ pr_err("%s: Invalid ep=%p\n", __func__, _ep);
return -EINVAL;
}
spin_lock_irqsave(&ep->dev->lock, flags);
@@ -2279,7 +2279,7 @@ static void usb_reinit_338x(struct net2280 *dev)
* - It is safe to set for all connection speeds; all chip revisions.
* - R-M-W to leave other bits undisturbed.
* - Reference PLX TT-7372
- */
+ */
val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 6e34f9594159..7dc248546fd4 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -2630,6 +2630,10 @@ MODULE_DEVICE_TABLE(of, usb3_of_match);
static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
{
+ .soc_id = "r8a774c0",
+ .data = &renesas_usb3_priv_r8a77990,
+ },
+ {
.soc_id = "r8a7795", .revision = "ES1.*",
.data = &renesas_usb3_priv_r8a7795_es1,
},
diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c
index d4da47f4f6f4..3fcded31405a 100644
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -947,15 +947,14 @@ static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
UDC_DMA_STP_STS_BS_HOST_READY,
UDC_DMA_STP_STS_BS);
-
- /* clear NAK by writing CNAK */
- if (ep->naking) {
- tmp = readl(&ep->regs->ctl);
- tmp |= AMD_BIT(UDC_EPCTL_CNAK);
- writel(tmp, &ep->regs->ctl);
- ep->naking = 0;
- UDC_QUEUE_CNAK(ep, ep->num);
- }
+ /* clear NAK by writing CNAK */
+ if (ep->naking) {
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 0;
+ UDC_QUEUE_CNAK(ep, ep->num);
+ }
}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 16758b12a5e9..d809671c5fea 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Host Controller Drivers
#
@@ -69,13 +70,13 @@ config USB_XHCI_MTK
If unsure, say N.
config USB_XHCI_MVEBU
- tristate "xHCI support for Marvell Armada 375/38x"
+ tristate "xHCI support for Marvell Armada 375/38x/37xx"
select USB_XHCI_PLATFORM
depends on HAS_IOMEM
depends on ARCH_MVEBU || COMPILE_TEST
---help---
Say 'Y' to enable the support for the xHCI host controller
- found in Marvell Armada 375/38x ARM SOCs.
+ found in Marvell Armada 375/38x/37xx ARM SOCs.
config USB_XHCI_RCAR
tristate "xHCI support for Renesas R-Car SoCs"
@@ -179,8 +180,7 @@ config XPS_USB_HCD_XILINX
devices only.
config USB_EHCI_FSL
- tristate "Support for Freescale PPC on-chip EHCI USB controller"
- depends on FSL_SOC
+ tristate "Support for Freescale on-chip EHCI USB controller"
select USB_EHCI_ROOT_HUB_TT
---help---
Variation of ARC USB block used in some Freescale chips.
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0a9fd2022acf..e3d0c1c25160 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/of_platform.h>
+#include <linux/io.h>
#include "ehci.h"
#include "ehci-fsl.h"
@@ -50,6 +51,7 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
struct resource *res;
int irq;
int retval;
+ u32 tmp;
pr_debug("initializing FSL-SOC USB Controller\n");
@@ -114,17 +116,22 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
}
/* Enable USB controller, 83xx or 8536 */
- if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
- clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK, 0x4);
-
+ if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6) {
+ tmp = ioread32be(hcd->regs + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= 0x4;
+ iowrite32be(tmp, hcd->regs + FSL_SOC_USB_CTRL);
+ }
/*
* Enable UTMI phy and program PTS field in UTMI mode before asserting
* controller reset for USB Controller version 2.5
*/
if (pdata->has_fsl_erratum_a007792) {
- clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK, CTRL_UTMI_PHY_EN);
+ tmp = ioread32be(hcd->regs + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= CTRL_UTMI_PHY_EN;
+ iowrite32be(tmp, hcd->regs + FSL_SOC_USB_CTRL);
+
writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
}
@@ -174,7 +181,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset)
{
- u32 portsc;
+ u32 portsc, tmp;
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs;
struct device *dev = hcd->self.controller;
@@ -192,11 +199,16 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
case FSL_USB2_PHY_ULPI:
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
- clrbits32(non_ehci + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK,
- ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
+ /* turn off UTMI PHY first */
+ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
+ tmp &= ~(CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
+ iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
+
+ /* then turn on ULPI and enable USB controller */
+ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN;
+ iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
}
portsc |= PORT_PTS_ULPI;
break;
@@ -210,16 +222,21 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
case FSL_USB2_PHY_UTMI_DUAL:
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK, UTMI_PHY_EN);
+ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= UTMI_PHY_EN;
+ iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
+
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
become stable - 10ms*/
}
/* enable UTMI PHY */
- if (pdata->have_sysif_regs)
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK,
- CTRL_UTMI_PHY_EN);
+ if (pdata->have_sysif_regs) {
+ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= CTRL_UTMI_PHY_EN;
+ iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
+ }
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
@@ -241,9 +258,12 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
- if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK, USB_CTRL_USB_EN);
+ if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) {
+ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
+ tmp &= ~CONTROL_REGISTER_W1C_MASK;
+ tmp |= USB_CTRL_USB_EN;
+ iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
+ }
return 0;
}
@@ -284,14 +304,9 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
return -EINVAL;
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
- unsigned int chip, rev, svr;
-
- svr = mfspr(SPRN_SVR);
- chip = svr >> 16;
- rev = (svr >> 4) & 0xf;
/* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */
- if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055))
+ if (pdata->has_fsl_erratum_14 == 1)
ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index f26109eafdbf..66ec1fdf9fe7 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -302,3 +302,4 @@ MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>");
MODULE_ALIAS("mv-ehci");
MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids);
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 1ad72647a069..790acf3633e8 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -182,6 +182,23 @@ static int ehci_orion_drv_reset(struct usb_hcd *hcd)
return ret;
}
+static int __maybe_unused ehci_orion_drv_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+ return ehci_suspend(hcd, device_may_wakeup(dev));
+}
+
+static int __maybe_unused ehci_orion_drv_resume(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+ return ehci_resume(hcd, false);
+}
+
+static SIMPLE_DEV_PM_OPS(ehci_orion_pm_ops, ehci_orion_drv_suspend,
+ ehci_orion_drv_resume);
+
static const struct ehci_driver_overrides orion_overrides __initconst = {
.extra_priv_size = sizeof(struct orion_ehci_hcd),
.reset = ehci_orion_drv_reset,
@@ -257,15 +274,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
if (IS_ERR(priv->phy)) {
err = PTR_ERR(priv->phy);
if (err != -ENOSYS)
- goto err_phy_get;
- } else {
- err = phy_init(priv->phy);
- if (err)
- goto err_phy_init;
-
- err = phy_power_on(priv->phy);
- if (err)
- goto err_phy_power_on;
+ goto err_dis_clk;
}
/*
@@ -297,19 +306,12 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_add_hcd;
+ goto err_dis_clk;
device_wakeup_enable(hcd->self.controller);
return 0;
-err_add_hcd:
- if (!IS_ERR(priv->phy))
- phy_power_off(priv->phy);
-err_phy_power_on:
- if (!IS_ERR(priv->phy))
- phy_exit(priv->phy);
-err_phy_init:
-err_phy_get:
+err_dis_clk:
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
usb_put_hcd(hcd);
@@ -327,11 +329,6 @@ static int ehci_orion_drv_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
- if (!IS_ERR(priv->phy)) {
- phy_power_off(priv->phy);
- phy_exit(priv->phy);
- }
-
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
@@ -354,6 +351,7 @@ static struct platform_driver ehci_orion_driver = {
.driver = {
.name = "orion-ehci",
.of_match_table = ehci_orion_dt_ids,
+ .pm = &ehci_orion_pm_ops,
},
};
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 677f9d592109..4f8b8a08c914 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -225,6 +225,12 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
pdata->has_fsl_erratum_a005697 =
of_property_read_bool(np, "fsl,usb_erratum-a005697");
+ if (of_get_property(np, "fsl,usb_erratum_14", NULL))
+ pdata->has_fsl_erratum_14 = 1;
+ else
+ pdata->has_fsl_erratum_14 = 0;
+
+
/*
* Determine whether phy_clk_valid needs to be checked
* by reading property in device tree
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index ec6739ef3129..fc35a7993b7b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -141,8 +141,11 @@ static struct regmap *at91_dt_syscon_sfr(void)
struct regmap *regmap;
regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
- if (IS_ERR(regmap))
- regmap = NULL;
+ if (IS_ERR(regmap)) {
+ regmap = syscon_regmap_lookup_by_compatible("microchip,sam9x60-sfr");
+ if (IS_ERR(regmap))
+ regmap = NULL;
+ }
return regmap;
}
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index a55cbba40a5a..ca8a94f15ac0 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -9,6 +9,7 @@
*/
#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
@@ -40,6 +41,8 @@ struct da8xx_ohci_hcd {
struct regulator *vbus_reg;
struct notifier_block nb;
unsigned int reg_enabled;
+ struct gpio_desc *vbus_gpio;
+ struct gpio_desc *oc_gpio;
};
#define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
@@ -86,12 +89,13 @@ static void ohci_da8xx_disable(struct usb_hcd *hcd)
static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+ struct device *dev = hcd->self.controller;
int ret;
- if (hub && hub->set_power)
- return hub->set_power(1, on);
+ if (da8xx_ohci->vbus_gpio) {
+ gpiod_set_value_cansleep(da8xx_ohci->vbus_gpio, on);
+ return 0;
+ }
if (!da8xx_ohci->vbus_reg)
return 0;
@@ -119,11 +123,9 @@ static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
static int ohci_da8xx_get_power(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
- if (hub && hub->get_power)
- return hub->get_power(1);
+ if (da8xx_ohci->vbus_gpio)
+ return gpiod_get_value_cansleep(da8xx_ohci->vbus_gpio);
if (da8xx_ohci->vbus_reg)
return regulator_is_enabled(da8xx_ohci->vbus_reg);
@@ -134,13 +136,11 @@ static int ohci_da8xx_get_power(struct usb_hcd *hcd)
static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
unsigned int flags;
int ret;
- if (hub && hub->get_oci)
- return hub->get_oci(1);
+ if (da8xx_ohci->oc_gpio)
+ return gpiod_get_value_cansleep(da8xx_ohci->oc_gpio);
if (!da8xx_ohci->vbus_reg)
return 0;
@@ -158,10 +158,8 @@ static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
- if (hub && hub->set_power)
+ if (da8xx_ohci->vbus_gpio)
return 1;
if (da8xx_ohci->vbus_reg)
@@ -173,10 +171,8 @@ static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
- if (hub && hub->get_oci)
+ if (da8xx_ohci->oc_gpio)
return 1;
if (da8xx_ohci->vbus_reg)
@@ -196,19 +192,6 @@ static int ohci_da8xx_has_potpgt(struct usb_hcd *hcd)
return 0;
}
-/*
- * Handle the port over-current indicator change.
- */
-static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
- unsigned port)
-{
- ocic_mask |= 1 << port;
-
- /* Once over-current is detected, the port needs to be powered down */
- if (hub->get_oci(port) > 0)
- hub->set_power(port, 0);
-}
-
static int ohci_da8xx_regulator_event(struct notifier_block *nb,
unsigned long event, void *data)
{
@@ -223,16 +206,23 @@ static int ohci_da8xx_regulator_event(struct notifier_block *nb,
return 0;
}
+static irqreturn_t ohci_da8xx_oc_handler(int irq, void *data)
+{
+ struct da8xx_ohci_hcd *da8xx_ohci = data;
+
+ if (gpiod_get_value(da8xx_ohci->oc_gpio))
+ gpiod_set_value(da8xx_ohci->vbus_gpio, 0);
+
+ return IRQ_HANDLED;
+}
+
static int ohci_da8xx_register_notify(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
int ret = 0;
- if (hub && hub->ocic_notify) {
- ret = hub->ocic_notify(ohci_da8xx_ocic_handler);
- } else if (da8xx_ohci->vbus_reg) {
+ if (!da8xx_ohci->oc_gpio && da8xx_ohci->vbus_reg) {
da8xx_ohci->nb.notifier_call = ohci_da8xx_regulator_event;
ret = devm_regulator_register_notifier(da8xx_ohci->vbus_reg,
&da8xx_ohci->nb);
@@ -244,15 +234,6 @@ static int ohci_da8xx_register_notify(struct usb_hcd *hcd)
return ret;
}
-static void ohci_da8xx_unregister_notify(struct usb_hcd *hcd)
-{
- struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
-
- if (hub && hub->ocic_notify)
- hub->ocic_notify(NULL);
-}
-
static int ohci_da8xx_reset(struct usb_hcd *hcd)
{
struct device *dev = hcd->self.controller;
@@ -402,34 +383,35 @@ MODULE_DEVICE_TABLE(of, da8xx_ohci_ids);
static int ohci_da8xx_probe(struct platform_device *pdev)
{
struct da8xx_ohci_hcd *da8xx_ohci;
+ struct device *dev = &pdev->dev;
+ int error, hcd_irq, oc_irq;
struct usb_hcd *hcd;
struct resource *mem;
- int error, irq;
- hcd = usb_create_hcd(&ohci_da8xx_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
+
+ hcd = usb_create_hcd(&ohci_da8xx_hc_driver, dev, dev_name(dev));
if (!hcd)
return -ENOMEM;
da8xx_ohci = to_da8xx_ohci(hcd);
da8xx_ohci->hcd = hcd;
- da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, NULL);
+ da8xx_ohci->usb11_clk = devm_clk_get(dev, NULL);
if (IS_ERR(da8xx_ohci->usb11_clk)) {
error = PTR_ERR(da8xx_ohci->usb11_clk);
if (error != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Failed to get clock.\n");
+ dev_err(dev, "Failed to get clock.\n");
goto err;
}
- da8xx_ohci->usb11_phy = devm_phy_get(&pdev->dev, "usb-phy");
+ da8xx_ohci->usb11_phy = devm_phy_get(dev, "usb-phy");
if (IS_ERR(da8xx_ohci->usb11_phy)) {
error = PTR_ERR(da8xx_ohci->usb11_phy);
if (error != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Failed to get phy.\n");
+ dev_err(dev, "Failed to get phy.\n");
goto err;
}
- da8xx_ohci->vbus_reg = devm_regulator_get_optional(&pdev->dev, "vbus");
+ da8xx_ohci->vbus_reg = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(da8xx_ohci->vbus_reg)) {
error = PTR_ERR(da8xx_ohci->vbus_reg);
if (error == -ENODEV) {
@@ -437,13 +419,34 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
} else if (error == -EPROBE_DEFER) {
goto err;
} else {
- dev_err(&pdev->dev, "Failed to get regulator\n");
+ dev_err(dev, "Failed to get regulator\n");
goto err;
}
}
+ da8xx_ohci->vbus_gpio = devm_gpiod_get_optional(dev, "vbus",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(da8xx_ohci->vbus_gpio))
+ goto err;
+
+ da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
+ if (IS_ERR(da8xx_ohci->oc_gpio))
+ goto err;
+
+ if (da8xx_ohci->oc_gpio) {
+ oc_irq = gpiod_to_irq(da8xx_ohci->oc_gpio);
+ if (oc_irq < 0)
+ goto err;
+
+ error = devm_request_irq(dev, oc_irq, ohci_da8xx_oc_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "OHCI over-current indicator", da8xx_ohci);
+ if (error)
+ goto err;
+ }
+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hcd->regs = devm_ioremap_resource(&pdev->dev, mem);
+ hcd->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(hcd->regs)) {
error = PTR_ERR(hcd->regs);
goto err;
@@ -451,13 +454,13 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
hcd->rsrc_start = mem->start;
hcd->rsrc_len = resource_size(mem);
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
+ hcd_irq = platform_get_irq(pdev, 0);
+ if (hcd_irq < 0) {
error = -ENODEV;
goto err;
}
- error = usb_add_hcd(hcd, irq, 0);
+ error = usb_add_hcd(hcd, hcd_irq, 0);
if (error)
goto err;
@@ -480,7 +483,6 @@ static int ohci_da8xx_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- ohci_da8xx_unregister_notify(hcd);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index c5e6e8d0b5ef..47c5515a9ce4 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -1323,7 +1323,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu,
}
/* by default, enable interrupt on urb completion */
- qtd->hw_token |= cpu_to_le32(QTD_IOC);
+ qtd->hw_token |= cpu_to_le32(QTD_IOC);
return head;
cleanup:
@@ -2253,16 +2253,12 @@ static void scan_periodic(struct oxu_hcd *oxu)
for (;;) {
union ehci_shadow q, *q_p;
__le32 type, *hw_p;
- unsigned uframes;
/* don't scan past the live uframe */
frame = now_uframe >> 3;
- if (frame == (clock >> 3))
- uframes = now_uframe & 0x07;
- else {
+ if (frame != (clock >> 3)) {
/* safe to scan the whole frame at once */
now_uframe |= 0x07;
- uframes = 8;
}
restart:
@@ -2832,7 +2828,6 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
{
struct oxu_hcd *oxu = hcd_to_oxu(hcd);
int num, rem;
- int transfer_buffer_length;
void *transfer_buffer;
struct urb *murb;
int i, ret;
@@ -2843,7 +2838,6 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
/* Otherwise we should verify the USB transfer buffer size! */
transfer_buffer = urb->transfer_buffer;
- transfer_buffer_length = urb->transfer_buffer_length;
num = urb->transfer_buffer_length / 4096;
rem = urb->transfer_buffer_length % 4096;
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 5b8a3d9530c4..934584f0a20a 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2477,7 +2477,8 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
spin_unlock_irqrestore(&endp->queue_lock.slock,
irqs);
kfree(urbq);
- } urb->error_count = 0;
+ }
+ urb->error_count = 0;
usb_hcd_giveback_urb(hcd, urb, status);
return 0;
} else if (list_empty(&endp->urb_more)) {
@@ -2982,7 +2983,8 @@ static int u132_remove(struct platform_device *pdev)
while (rings-- > 0) {
struct u132_ring *ring = &u132->ring[rings];
u132_ring_cancel_work(u132, ring);
- } while (endps-- > 0) {
+ }
+ while (endps-- > 0) {
struct u132_endp *endp = u132->endp[endps];
if (endp)
u132_endp_cancel_work(u132, endp);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 6218bfe54f52..98deb5f64268 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -596,9 +596,9 @@ static int uhci_start(struct usb_hcd *hcd)
&uhci_debug_operations);
#endif
- uhci->frame = dma_zalloc_coherent(uhci_dev(uhci),
- UHCI_NUMFRAMES * sizeof(*uhci->frame),
- &uhci->frame_dma_handle, GFP_KERNEL);
+ uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+ UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ &uhci->frame_dma_handle, GFP_KERNEL);
if (!uhci->frame) {
dev_err(uhci_dev(uhci),
"unable to allocate consistent memory for frame list\n");
diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Makefile
index 26df0138079e..859d20079df6 100644
--- a/drivers/usb/host/whci/Kbuild
+++ b/drivers/usb/host/whci/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o
whci-hcd-y := \
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
index 86cff5c28eff..c78be578abb0 100644
--- a/drivers/usb/host/xhci-dbgcap.c
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -181,7 +181,7 @@ static void xhci_dbc_flush_endpoint_requests(struct dbc_ep *dep)
xhci_dbc_flush_single_request(req);
}
-static void xhci_dbc_flush_reqests(struct xhci_dbc *dbc)
+static void xhci_dbc_flush_requests(struct xhci_dbc *dbc)
{
xhci_dbc_flush_endpoint_requests(&dbc->eps[BULK_OUT]);
xhci_dbc_flush_endpoint_requests(&dbc->eps[BULK_IN]);
@@ -687,7 +687,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc)
!(portsc & DBC_PORTSC_CONN_STATUS)) {
xhci_info(xhci, "DbC cable unplugged\n");
dbc->state = DS_ENABLED;
- xhci_dbc_flush_reqests(dbc);
+ xhci_dbc_flush_requests(dbc);
return EVT_DISC;
}
@@ -697,7 +697,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc)
xhci_info(xhci, "DbC port reset\n");
writel(portsc, &dbc->regs->portsc);
dbc->state = DS_ENABLED;
- xhci_dbc_flush_reqests(dbc);
+ xhci_dbc_flush_requests(dbc);
return EVT_DISC;
}
diff --git a/drivers/usb/host/xhci-debugfs.h b/drivers/usb/host/xhci-debugfs.h
index ac5bc40f5c3a..f7a4e2492b00 100644
--- a/drivers/usb/host/xhci-debugfs.h
+++ b/drivers/usb/host/xhci-debugfs.h
@@ -80,7 +80,6 @@ struct xhci_regset {
char name[DEBUGFS_NAMELEN];
struct debugfs_regset32 regset;
size_t nregs;
- struct dentry *parent;
struct list_head list;
};
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 36a3eb8849f1..cf5e17962179 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -933,7 +933,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
* that tt_info, then free the child first. Recursive.
* We can't rely on udev at this point to find child-parent relationships.
*/
-void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id)
+static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id)
{
struct xhci_virt_device *vdev;
struct list_head *tt_list_head;
@@ -1672,8 +1672,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
for (i = 0; i < num_sp; i++) {
dma_addr_t dma;
- void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma,
- flags);
+ void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
+ flags);
if (!buf)
goto fail_sp4;
@@ -1799,8 +1799,8 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
struct xhci_erst_entry *entry;
size = sizeof(struct xhci_erst_entry) * evt_ring->num_segs;
- erst->entries = dma_zalloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
- size, &erst->erst_dma_addr, flags);
+ erst->entries = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
+ size, &erst->erst_dma_addr, flags);
if (!erst->entries)
return -ENOMEM;
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
index 32e158568788..60651a50770f 100644
--- a/drivers/usb/host/xhci-mvebu.c
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -13,6 +13,7 @@
#include <linux/usb/hcd.h>
#include "xhci-mvebu.h"
+#include "xhci.h"
#define USB3_MAX_WINDOWS 4
#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
@@ -72,3 +73,13 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
return 0;
}
+
+int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+ /* Without reset on resume, the HC won't work at all */
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
+
+ return 0;
+}
diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
index 09791df2cec0..ca0a3a5721dd 100644
--- a/drivers/usb/host/xhci-mvebu.h
+++ b/drivers/usb/host/xhci-mvebu.h
@@ -12,10 +12,16 @@ struct usb_hcd;
#if IS_ENABLED(CONFIG_USB_XHCI_MVEBU)
int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd);
+int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd);
#else
static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
{
return 0;
}
+
+static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
+{
+ return 0;
+}
#endif
#endif /* __LINUX_XHCI_MVEBU_H */
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a9ec7051f286..c2fe218e051f 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -194,6 +194,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
xhci->quirks |= XHCI_INTEL_USB_ROLE_SW;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ef09cb06212f..0ac4ec975547 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -98,6 +98,10 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = {
.init_quirk = xhci_mvebu_mbus_init_quirk,
};
+static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = {
+ .init_quirk = xhci_mvebu_a3700_init_quirk,
+};
+
static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = {
.firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1,
.init_quirk = xhci_rcar_init_quirk,
@@ -124,6 +128,9 @@ static const struct of_device_id usb_xhci_of_match[] = {
.compatible = "marvell,armada-380-xhci",
.data = &xhci_plat_marvell_armada,
}, {
+ .compatible = "marvell,armada3700-xhci",
+ .data = &xhci_plat_marvell_armada3700,
+ }, {
.compatible = "renesas,xhci-r8a7790",
.data = &xhci_plat_renesas_rcar_gen2,
}, {
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 938ff06c0349..efb0cad8710e 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -941,9 +941,9 @@ static void tegra_xusb_powerdomain_remove(struct device *dev,
device_link_del(tegra->genpd_dl_ss);
if (tegra->genpd_dl_host)
device_link_del(tegra->genpd_dl_host);
- if (tegra->genpd_dev_ss)
+ if (!IS_ERR_OR_NULL(tegra->genpd_dev_ss))
dev_pm_domain_detach(tegra->genpd_dev_ss, true);
- if (tegra->genpd_dev_host)
+ if (!IS_ERR_OR_NULL(tegra->genpd_dev_host))
dev_pm_domain_detach(tegra->genpd_dev_host, true);
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 005e65922608..7fa58c99f126 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1455,8 +1455,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
else
num_tds = 1;
- urb_priv = kzalloc(sizeof(struct urb_priv) +
- num_tds * sizeof(struct xhci_td), mem_flags);
+ urb_priv = kzalloc(struct_size(urb_priv, td, num_tds), mem_flags);
if (!urb_priv)
return -ENOMEM;
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
index 320d368c8dac..26c75f309da9 100644
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Imaging devices configuration
#
diff --git a/drivers/usb/isp1760/Kconfig b/drivers/usb/isp1760/Kconfig
index c94b7d953399..b1022cc490a2 100644
--- a/drivers/usb/isp1760/Kconfig
+++ b/drivers/usb/isp1760/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_ISP1760
tristate "NXP ISP 1760/1761 support"
depends on USB || USB_GADGET
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 68d2f2cd17dd..be04c117fe80 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Miscellaneous driver configuration
#
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 76c718ac8c78..257efacf3551 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -915,7 +915,6 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
int bytes_read = 0;
int retry_on_empty = 1;
int retry_on_timeout = 3;
- int empty_packets = 0;
read:{
int packet_bytes = 0;
int retval = usb_bulk_msg(ftdi->udev,
@@ -960,31 +959,6 @@ read:{
dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n",
retval, packet_bytes, bytes_read, diag);
return retval;
- } else if (packet_bytes == 2) {
- unsigned char s0 = ftdi->bulk_in_buffer[0];
- unsigned char s1 = ftdi->bulk_in_buffer[1];
- empty_packets += 1;
- if (s0 == 0x31 && s1 == 0x60) {
- if (retry_on_empty-- > 0) {
- goto more;
- } else
- return 0;
- } else if (s0 == 0x31 && s1 == 0x00) {
- if (retry_on_empty-- > 0) {
- goto more;
- } else
- return 0;
- } else {
- if (retry_on_empty-- > 0) {
- goto more;
- } else
- return 0;
- }
- } else if (packet_bytes == 1) {
- if (retry_on_empty-- > 0) {
- goto more;
- } else
- return 0;
} else {
if (retry_on_empty-- > 0) {
goto more;
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 36bc28c884ad..9b632ab24f03 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
config USB_SISUSBVGA
tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 6ed3a638261a..6551bce68ac5 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
-sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o
+sisusbvga-y := sisusb.o
+sisusbvga-$(CONFIG_USB_SISUSBVGA_CON) += sisusb_con.o sisusb_init.o
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 3198d0477cf8..9560fde621ee 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -53,7 +53,7 @@
#include "sisusb.h"
#include "sisusb_init.h"
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
#include <linux/font.h>
#endif
@@ -61,7 +61,7 @@
/* Forward declarations / clean-up routines */
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
static int sisusb_first_vc;
static int sisusb_last_vc;
module_param_named(first, sisusb_first_vc, int, 0);
@@ -1198,7 +1198,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
/* High level: Gfx (indexed) register access */
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
{
return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
@@ -1272,7 +1272,7 @@ int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
/* Write/read video ram */
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
{
return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
@@ -2255,7 +2255,7 @@ static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
}
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
/* Set up default text mode:
* - Set text mode (0x03)
@@ -2448,7 +2448,7 @@ void sisusb_delete(struct kref *kref)
sisusb->sisusb_dev = NULL;
sisusb_free_buffers(sisusb);
sisusb_free_urbs(sisusb);
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
kfree(sisusb->SiS_Pr);
#endif
kfree(sisusb);
@@ -2844,7 +2844,7 @@ static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
case SUCMD_HANDLETEXTMODE:
retval = 0;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
/* Gfx core must be initialized, SiS_Pr must exist */
if (!sisusb->gfxinit || !sisusb->SiS_Pr)
return -ENODEV;
@@ -2860,7 +2860,7 @@ static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
#endif
break;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
case SUCMD_SETMODE:
/* Gfx core must be initialized, SiS_Pr must exist */
if (!sisusb->gfxinit || !sisusb->SiS_Pr)
@@ -2944,7 +2944,7 @@ static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
x.sisusb_vramsize = sisusb->vramsize;
x.sisusb_minor = sisusb->minor;
x.sisusb_fbdevactive = 0;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
#else
x.sisusb_conactive = 0;
@@ -2975,7 +2975,7 @@ err_out:
return retval;
}
-#ifdef SISUSB_NEW_CONFIG_COMPAT
+#ifdef CONFIG_COMPAT
static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
unsigned long arg)
{
@@ -2998,7 +2998,7 @@ static const struct file_operations usb_sisusb_fops = {
.read = sisusb_read,
.write = sisusb_write,
.llseek = sisusb_lseek,
-#ifdef SISUSB_NEW_CONFIG_COMPAT
+#ifdef CONFIG_COMPAT
.compat_ioctl = sisusb_compat_ioctl,
#endif
.unlocked_ioctl = sisusb_ioctl
@@ -3091,7 +3091,7 @@ static int sisusb_probe(struct usb_interface *intf,
dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
sisusb->numobufs);
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
/* Allocate our SiS_Pr */
sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
if (!sisusb->SiS_Pr) {
@@ -3112,7 +3112,7 @@ static int sisusb_probe(struct usb_interface *intf,
if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
int initscreen = 1;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
sisusb_first_vc <= sisusb_last_vc &&
sisusb_last_vc <= MAX_NR_CONSOLES)
@@ -3134,7 +3134,7 @@ static int sisusb_probe(struct usb_interface *intf,
dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
#endif
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
#endif
@@ -3160,7 +3160,7 @@ static void sisusb_disconnect(struct usb_interface *intf)
if (!sisusb)
return;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
sisusb_console_exit(sisusb);
#endif
@@ -3210,7 +3210,7 @@ static struct usb_driver sisusb_driver = {
static int __init usb_sisusb_init(void)
{
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
sisusb_init_concode();
#endif
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 20f03ad0ea16..8a5e6bb07d05 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -38,17 +38,8 @@
#ifndef _SISUSB_H_
#define _SISUSB_H_
-#ifdef CONFIG_COMPAT
-#define SISUSB_NEW_CONFIG_COMPAT
-#endif
-
#include <linux/mutex.h>
-/* For older kernels, support for text consoles is by default
- * off. To enable text console support, change the following:
- */
-/* #define CONFIG_USB_SISUSBVGA_CON */
-
/* Version Information */
#define SISUSB_VERSION 0
@@ -57,10 +48,6 @@
/* Include console and mode switching code? */
-#ifdef CONFIG_USB_SISUSBVGA_CON
-#define INCL_SISUSB_CON 1
-#endif
-
#include <linux/console.h>
#include <linux/vt_kern.h>
#include "sisusb_struct.h"
@@ -139,7 +126,7 @@ struct sisusb_usb_data {
unsigned char gfxinit; /* graphics core initialized? */
unsigned short chipid, chipvendor;
unsigned short chiprevision;
-#ifdef INCL_SISUSB_CON
+#ifdef CONFIG_USB_SISUSBVGA_CON
struct SiS_Private *SiS_Pr;
unsigned long scrbuf;
unsigned int scrbuf_size;
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index c4f017e1d17a..cd0155310fea 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -70,13 +70,6 @@
#include "sisusb.h"
#include "sisusb_init.h"
-#ifdef INCL_SISUSB_CON
-
-#define sisusbcon_writew(val, addr) (*(addr) = (val))
-#define sisusbcon_readw(addr) (*(addr))
-#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
-#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
-
/* vc_data -> sisusb conversion table */
static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
@@ -86,9 +79,7 @@ static const struct consw sisusb_con;
static inline void
sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
{
- count /= 2;
- while (count--)
- sisusbcon_writew(c, s++);
+ memset16(s, c, count / 2);
}
static inline void
@@ -346,25 +337,30 @@ sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
*/
while (count--) {
- u16 a = sisusbcon_readw(p);
-
- a = ((a) & 0x88ff) |
- (((a) & 0x7000) >> 4) |
- (((a) & 0x0700) << 4);
+ u16 a = *p;
- sisusbcon_writew(a, p++);
+ *p++ = ((a) & 0x88ff) |
+ (((a) & 0x7000) >> 4) |
+ (((a) & 0x0700) << 4);
}
}
-#define SISUSB_VADDR(x,y) \
- ((u16 *)c->vc_origin + \
- (y) * sisusb->sisusb_num_columns + \
- (x))
+static inline void *sisusb_vaddr(const struct sisusb_usb_data *sisusb,
+ const struct vc_data *c, unsigned int x, unsigned int y)
+{
+ return (u16 *)c->vc_origin + y * sisusb->sisusb_num_columns + x;
+}
+
+static inline unsigned long sisusb_haddr(const struct sisusb_usb_data *sisusb,
+ const struct vc_data *c, unsigned int x, unsigned int y)
+{
+ unsigned long offset = c->vc_origin - sisusb->scrbuf;
-#define SISUSB_HADDR(x,y) \
- ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
- (y) * sisusb->sisusb_num_columns + \
- (x))
+ /* 2 bytes per each character */
+ offset += 2 * (y * sisusb->sisusb_num_columns + x);
+
+ return sisusb->vrambase + offset;
+}
/* Interface routine */
static void
@@ -382,9 +378,8 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
return;
}
-
- sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (long)SISUSB_HADDR(x, y), 2);
+ sisusb_copy_memory(sisusb, sisusb_vaddr(sisusb, c, x, y),
+ sisusb_haddr(sisusb, c, x, y), 2);
mutex_unlock(&sisusb->lock);
}
@@ -395,8 +390,6 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
int count, int y, int x)
{
struct sisusb_usb_data *sisusb;
- u16 *dest;
- int i;
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
if (!sisusb)
@@ -408,18 +401,15 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
* because the vt does this AFTER calling us.
*/
- dest = SISUSB_VADDR(x, y);
-
- for (i = count; i > 0; i--)
- sisusbcon_writew(sisusbcon_readw(s++), dest++);
+ memcpy(sisusb_vaddr(sisusb, c, x, y), s, count * 2);
if (sisusb_is_inactive(c, sisusb)) {
mutex_unlock(&sisusb->lock);
return;
}
- sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (long)SISUSB_HADDR(x, y), count * 2);
+ sisusb_copy_memory(sisusb, sisusb_vaddr(sisusb, c, x, y),
+ sisusb_haddr(sisusb, c, x, y), count * 2);
mutex_unlock(&sisusb->lock);
}
@@ -446,7 +436,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
* this AFTER calling us.
*/
- dest = SISUSB_VADDR(x, y);
+ dest = sisusb_vaddr(sisusb, c, x, y);
cols = sisusb->sisusb_num_columns;
@@ -472,8 +462,8 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
length = ((height * cols) - x - (cols - width - x)) * 2;
- sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
- (long)SISUSB_HADDR(x, y), length);
+ sisusb_copy_memory(sisusb, sisusb_vaddr(sisusb, c, x, y),
+ sisusb_haddr(sisusb, c, x, y), length);
mutex_unlock(&sisusb->lock);
}
@@ -517,12 +507,10 @@ sisusbcon_switch(struct vc_data *c)
(int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
/* Restore the screen contents */
- sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
- length);
+ memcpy((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf, length);
- sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
- (long)SISUSB_HADDR(0, 0),
- length);
+ sisusb_copy_memory(sisusb, (char *)c->vc_origin,
+ sisusb_haddr(sisusb, c, 0, 0), length);
mutex_unlock(&sisusb->lock);
@@ -556,8 +544,7 @@ sisusbcon_save_screen(struct vc_data *c)
(int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
/* Save the screen contents to vc's private buffer */
- sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
- length);
+ memcpy((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, length);
mutex_unlock(&sisusb->lock);
}
@@ -628,10 +615,8 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
sisusbcon_memsetw((u16 *)c->vc_origin,
c->vc_video_erase_char,
c->vc_screenbuf_size);
- sisusb_copy_memory(sisusb,
- (unsigned char *)c->vc_origin,
- (u32)(sisusb->vrambase +
- (c->vc_origin - sisusb->scrbuf)),
+ sisusb_copy_memory(sisusb, (char *)c->vc_origin,
+ sisusb_haddr(sisusb, c, 0, 0),
c->vc_screenbuf_size);
sisusb->con_blanked = 1;
ret = 1;
@@ -796,24 +781,24 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
switch (dir) {
case SM_UP:
- sisusbcon_memmovew(SISUSB_VADDR(0, t),
- SISUSB_VADDR(0, t + lines),
+ memmove(sisusb_vaddr(sisusb, c, 0, t),
+ sisusb_vaddr(sisusb, c, 0, t + lines),
(b - t - lines) * cols * 2);
- sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
- lines * cols * 2);
+ sisusbcon_memsetw(sisusb_vaddr(sisusb, c, 0, b - lines),
+ eattr, lines * cols * 2);
break;
case SM_DOWN:
- sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
- SISUSB_VADDR(0, t),
+ memmove(sisusb_vaddr(sisusb, c, 0, t + lines),
+ sisusb_vaddr(sisusb, c, 0, t),
(b - t - lines) * cols * 2);
- sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+ sisusbcon_memsetw(sisusb_vaddr(sisusb, c, 0, t), eattr,
lines * cols * 2);
break;
}
- sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
- (long)SISUSB_HADDR(0, t), length);
+ sisusb_copy_memory(sisusb, sisusb_vaddr(sisusb, c, 0, t),
+ sisusb_haddr(sisusb, c, 0, t), length);
mutex_unlock(&sisusb->lock);
@@ -830,7 +815,6 @@ sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
int copyall = 0;
unsigned long oldorigin;
unsigned int delta = lines * c->vc_size_row;
- u32 originoffset;
/* Returning != 0 means we have done the scrolling successfully.
* Returning 0 makes vt do the scrolling on its own.
@@ -874,7 +858,7 @@ sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
if (c->vc_scr_end + delta >=
sisusb->scrbuf + sisusb->scrbuf_size) {
- sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+ memcpy((u16 *)sisusb->scrbuf,
(u16 *)(oldorigin + delta),
c->vc_screenbuf_size - delta);
c->vc_origin = sisusb->scrbuf;
@@ -892,12 +876,10 @@ sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
case SM_DOWN:
if (oldorigin - delta < sisusb->scrbuf) {
- sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
- sisusb->scrbuf_size -
- c->vc_screenbuf_size +
- delta),
- (u16 *)oldorigin,
- c->vc_screenbuf_size - delta);
+ memmove((void *)sisusb->scrbuf + sisusb->scrbuf_size -
+ c->vc_screenbuf_size + delta,
+ (u16 *)oldorigin,
+ c->vc_screenbuf_size - delta);
c->vc_origin = sisusb->scrbuf +
sisusb->scrbuf_size -
c->vc_screenbuf_size;
@@ -913,23 +895,21 @@ sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
break;
}
- originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
-
if (copyall)
sisusb_copy_memory(sisusb,
(char *)c->vc_origin,
- (u32)(sisusb->vrambase + originoffset),
+ sisusb_haddr(sisusb, c, 0, 0),
c->vc_screenbuf_size);
else if (dir == SM_UP)
sisusb_copy_memory(sisusb,
(char *)c->vc_origin + c->vc_screenbuf_size - delta,
- (u32)sisusb->vrambase + originoffset +
+ sisusb_haddr(sisusb, c, 0, 0) +
c->vc_screenbuf_size - delta,
delta);
else
sisusb_copy_memory(sisusb,
(char *)c->vc_origin,
- (u32)(sisusb->vrambase + originoffset),
+ sisusb_haddr(sisusb, c, 0, 0),
delta);
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
@@ -1534,8 +1514,3 @@ void __init sisusb_init_concode(void)
for (i = 0; i < MAX_NR_CONSOLES; i++)
mysisusbs[i] = NULL;
}
-
-#endif /* INCL_CON */
-
-
-
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
index 6a30e8bd9221..66f6ab5acd97 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -44,9 +44,6 @@
#include <linux/spinlock.h>
#include "sisusb.h"
-
-#ifdef INCL_SISUSB_CON
-
#include "sisusb_init.h"
/*********************************************/
@@ -955,5 +952,3 @@ int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
return SiSUSBSetMode(SiS_Pr, ModeNo);
}
-
-#endif /* INCL_SISUSB_CON */
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
index a6efb9a72939..4d72b7d1d383 100644
--- a/drivers/usb/misc/usb251xb.c
+++ b/drivers/usb/misc/usb251xb.c
@@ -337,10 +337,12 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
struct device *dev = hub->dev;
struct device_node *np = dev->of_node;
int len, err, i;
- u32 property_u32 = 0;
+ u32 port, property_u32 = 0;
const u32 *cproperty_u32;
const char *cproperty_char;
char str[USB251XB_STRING_BUFSIZE / 2];
+ struct property *prop;
+ const __be32 *p;
if (!np) {
dev_err(dev, "failed to get ofdata\n");
@@ -539,6 +541,16 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
(wchar_t *)hub->serial,
USB251XB_STRING_BUFSIZE);
+ /*
+ * The datasheet documents the register as 'Port Swap' but in real the
+ * register controls the USB DP/DM signal swapping for each port.
+ */
+ hub->port_swap = USB251XB_DEF_PORT_SWAP;
+ of_property_for_each_u32(np, "swap-dx-lanes", prop, p, port) {
+ if ((port >= 0) && (port <= data->port_cnt))
+ hub->port_swap |= BIT(port);
+ }
+
/* The following parameters are currently not exposed to devicetree, but
* may be as soon as needed.
*/
@@ -546,7 +558,6 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
hub->boost_up = USB251XB_DEF_BOOST_UP;
hub->boost_57 = USB251XB_DEF_BOOST_57;
hub->boost_14 = USB251XB_DEF_BOOST_14;
- hub->port_swap = USB251XB_DEF_PORT_SWAP;
hub->port_map12 = USB251XB_DEF_PORT_MAP_12;
hub->port_map34 = USB251XB_DEF_PORT_MAP_34;
hub->port_map56 = USB251XB_DEF_PORT_MAP_56;
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index f723f7b8c9ac..d5141aa79dd4 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -355,11 +355,8 @@ static int usb3503_platform_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
-static int usb3503_i2c_suspend(struct device *dev)
+static int usb3503_suspend(struct usb3503 *hub)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct usb3503 *hub = i2c_get_clientdata(client);
-
usb3503_switch_mode(hub, USB3503_MODE_STANDBY);
if (hub->clk)
@@ -368,11 +365,8 @@ static int usb3503_i2c_suspend(struct device *dev)
return 0;
}
-static int usb3503_i2c_resume(struct device *dev)
+static int usb3503_resume(struct usb3503 *hub)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct usb3503 *hub = i2c_get_clientdata(client);
-
if (hub->clk)
clk_prepare_enable(hub->clk);
@@ -380,11 +374,38 @@ static int usb3503_i2c_resume(struct device *dev)
return 0;
}
+
+static int usb3503_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return usb3503_suspend(i2c_get_clientdata(client));
+}
+
+static int usb3503_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return usb3503_resume(i2c_get_clientdata(client));
+}
+
+static int usb3503_platform_suspend(struct device *dev)
+{
+ return usb3503_suspend(dev_get_drvdata(dev));
+}
+
+static int usb3503_platform_resume(struct device *dev)
+{
+ return usb3503_resume(dev_get_drvdata(dev));
+}
#endif
static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend,
usb3503_i2c_resume);
+static SIMPLE_DEV_PM_OPS(usb3503_platform_pm_ops, usb3503_platform_suspend,
+ usb3503_platform_resume);
+
static const struct i2c_device_id usb3503_id[] = {
{ USB3503_I2C_NAME, 0 },
{ }
@@ -415,6 +436,7 @@ static struct platform_driver usb3503_platform_driver = {
.driver = {
.name = USB3503_I2C_NAME,
.of_match_table = of_match_ptr(usb3503_of_match),
+ .pm = &usb3503_platform_pm_ops,
},
.probe = usb3503_platform_probe,
.remove = usb3503_platform_remove,
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index c7f82310e73e..98ada1a3425c 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -347,6 +347,14 @@ static unsigned get_maxpacket(struct usb_device *udev, int pipe)
return le16_to_cpup(&ep->desc.wMaxPacketSize);
}
+static int ss_isoc_get_packet_num(struct usb_device *udev, int pipe)
+{
+ struct usb_host_endpoint *ep = usb_pipe_endpoint(udev, pipe);
+
+ return USB_SS_MULT(ep->ss_ep_comp.bmAttributes)
+ * (1 + ep->ss_ep_comp.bMaxBurst);
+}
+
static void simple_fill_buf(struct urb *urb)
{
unsigned i;
@@ -1976,8 +1984,13 @@ static struct urb *iso_alloc_urb(
if (bytes < 0 || !desc)
return NULL;
+
maxp = usb_endpoint_maxp(desc);
- maxp *= usb_endpoint_maxp_mult(desc);
+ if (udev->speed >= USB_SPEED_SUPER)
+ maxp *= ss_isoc_get_packet_num(udev, pipe);
+ else
+ maxp *= usb_endpoint_maxp_mult(desc);
+
packets = DIV_ROUND_UP(bytes, maxp);
urb = usb_alloc_urb(packets, GFP_KERNEL);
@@ -2065,17 +2078,24 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
packets *= param->iterations;
if (context.is_iso) {
+ int transaction_num;
+
+ if (udev->speed >= USB_SPEED_SUPER)
+ transaction_num = ss_isoc_get_packet_num(udev, pipe);
+ else
+ transaction_num = usb_endpoint_maxp_mult(desc);
+
dev_info(&dev->intf->dev,
"iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
1 << (desc->bInterval - 1),
- (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
+ (udev->speed >= USB_SPEED_HIGH) ? "micro" : "",
usb_endpoint_maxp(desc),
- usb_endpoint_maxp_mult(desc));
+ transaction_num);
dev_info(&dev->intf->dev,
"total %lu msec (%lu packets)\n",
(packets * (1 << (desc->bInterval - 1)))
- / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
+ / ((udev->speed >= USB_SPEED_HIGH) ? 8 : 1),
packets);
}
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 5c6ffa2a612e..48f1b2dadb24 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Monitor configuration
#
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index 40bbf1f53337..bcc23486c4ed 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
# For MTK USB3.0 IP
config USB_MTU3
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895e78f9..f742fddc5e2c 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Dual Role (OTG-ready) Controller Drivers
# for silicon based on Mentor Graphics INVENTRA designs
@@ -111,9 +112,9 @@ config USB_MUSB_UX500
config USB_MUSB_JZ4740
tristate "JZ4740"
depends on NOP_USB_XCEIV
- depends on MACH_JZ4740 || COMPILE_TEST
+ depends on MIPS || COMPILE_TEST
depends on USB_MUSB_GADGET
- depends on USB_OTG_BLACKLIST_HUB
+ depends on USB=n || USB_OTG_BLACKLIST_HUB
config USB_MUSB_AM335X_CHILD
tristate
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index 04d8b2bc205a..a60627bf7be3 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/usb/usb_phy_generic.h>
@@ -188,11 +189,20 @@ static int jz4740_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id jz4740_musb_of_match[] = {
+ { .compatible = "ingenic,jz4740-musb" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
+#endif
+
static struct platform_driver jz4740_driver = {
.probe = jz4740_probe,
.remove = jz4740_remove,
.driver = {
.name = "musb-jz4740",
+ .of_match_table = of_match_ptr(jz4740_musb_of_match),
},
};
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index eae8b1b1b45b..ffe462a657b1 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
}
if (request) {
- u8 is_dma = 0;
- bool short_packet = false;
trace_musb_req_tx(req);
if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
- is_dma = 1;
csr |= MUSB_TXCSR_P_WZC_BITS;
csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
*/
if ((request->zero && request->length)
&& (request->length % musb_ep->packet_sz == 0)
- && (request->actual == request->length))
- short_packet = true;
+ && (request->actual == request->length)) {
- if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
- (is_dma && (!dma->desired_mode ||
- (request->actual &
- (musb_ep->packet_sz - 1)))))
- short_packet = true;
-
- if (short_packet) {
/*
* On DMA completion, FIFO may not be
* available yet...
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index b59ce9ad14ce..eb308ec35c66 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -378,7 +378,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
qh = first_qh(head);
break;
}
- /* else: fall through */
+ /* fall through */
case USB_ENDPOINT_XFER_ISOC:
case USB_ENDPOINT_XFER_INT:
@@ -1283,7 +1283,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
MUSB_TXCSR_H_WZC_BITS
| MUSB_TXCSR_TXPKTRDY);
}
- return;
+ return;
}
done:
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a688f7f87829..5fc6825745f2 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
channel->status = MUSB_DMA_STATUS_FREE;
/* completed */
- if ((devctl & MUSB_DEVCTL_HM)
- && (musb_channel->transmit)
- && ((channel->desired_mode == 0)
- || (channel->actual_len &
- (musb_channel->max_packet_sz - 1)))
- ) {
+ if (musb_channel->transmit &&
+ (!channel->desired_mode ||
+ (channel->actual_len %
+ musb_channel->max_packet_sz))) {
u8 epnum = musb_channel->epnum;
int offset = musb->io.ep_offset(epnum,
MUSB_TXCSR);
@@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
*/
musb_ep_select(mbase, epnum);
txcsr = musb_readw(mbase, offset);
- txcsr &= ~(MUSB_TXCSR_DMAENAB
+ if (channel->desired_mode == 1) {
+ txcsr &= ~(MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_AUTOSET);
- musb_writew(mbase, offset, txcsr);
- /* Send out the packet */
- txcsr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(mbase, offset, txcsr);
+ /* Send out the packet */
+ txcsr &= ~MUSB_TXCSR_DMAMODE;
+ txcsr |= MUSB_TXCSR_DMAENAB;
+ }
txcsr |= MUSB_TXCSR_TXPKTRDY;
musb_writew(mbase, offset, txcsr);
}
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index d7312eed6088..8c509b060c09 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Physical Layer USB driver configuration
#
@@ -21,7 +22,7 @@ config AB8500_USB
config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
- depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
+ depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
select USB_PHY
help
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 27bdb7222527..f5f0568d8533 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -61,9 +61,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
- if (ret)
- return ret;
am_phy->usb_phy_gen.phy.init = am335x_init;
am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
@@ -82,7 +79,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
device_set_wakeup_enable(dev, false);
phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
- return 0;
+ return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
}
static int am335x_phy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 183550b63faa..dade34d70419 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -400,7 +400,7 @@ static int twl6030_usb_remove(struct platform_device *pdev)
{
struct twl6030_usb *twl = platform_get_drvdata(pdev);
- cancel_delayed_work(&twl->get_status_work);
+ cancel_delayed_work_sync(&twl->get_status_work);
twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
REG_INT_MSK_LINE_C);
twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
index 4e59c649db81..ddd3be48f948 100644
--- a/drivers/usb/renesas_usbhs/mod_host.c
+++ b/drivers/usb/renesas_usbhs/mod_host.c
@@ -340,7 +340,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
pipe = usbhsh_uep_to_pipe(uep);
if (unlikely(!pipe)) {
- dev_err(dev, "uep doens't have pipe\n");
+ dev_err(dev, "uep doesn't have pipe\n");
} else if (1 == uep->counter--) { /* last user */
struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
diff --git a/drivers/usb/renesas_usbhs/rcar3.c b/drivers/usb/renesas_usbhs/rcar3.c
index aa3820448286..5e730e9b40ef 100644
--- a/drivers/usb/renesas_usbhs/rcar3.c
+++ b/drivers/usb/renesas_usbhs/rcar3.c
@@ -59,7 +59,7 @@ static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
if (enable) {
usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
/* The controller on R-Car Gen3 needs to wait up to 45 usec */
- udelay(45);
+ usleep_range(45, 90);
} else {
usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
}
diff --git a/drivers/usb/renesas_usbhs/rza.c b/drivers/usb/renesas_usbhs/rza.c
index 5b287257ec11..8c739bd24acd 100644
--- a/drivers/usb/renesas_usbhs/rza.c
+++ b/drivers/usb/renesas_usbhs/rza.c
@@ -35,7 +35,7 @@ static int usbhs_rza1_hardware_init(struct platform_device *pdev)
/* Enable USB PLL (NOTE: ch0 controls both ch0 and ch1) */
usbhs_bset(priv, SYSCFG, UPLLE, UPLLE);
- udelay(1000);
+ usleep_range(1000, 2000);
usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM);
return 0;
diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig
index e4194ac94510..f8b31aa67526 100644
--- a/drivers/usb/roles/Kconfig
+++ b/drivers/usb/roles/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USB_ROLE_SWITCH
tristate "USB Role Switch Support"
help
diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile
index c02873206fc1..757a7d2797eb 100644
--- a/drivers/usb/roles/Makefile
+++ b/drivers/usb/roles/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o
roles-y := class.o
obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index 99116af07f1d..f45d8df5cfb8 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -8,6 +8,7 @@
*/
#include <linux/usb/role.h>
+#include <linux/property.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -84,7 +85,12 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
}
EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
-static int __switch_match(struct device *dev, const void *name)
+static int switch_fwnode_match(struct device *dev, const void *fwnode)
+{
+ return dev_fwnode(dev) == fwnode;
+}
+
+static int switch_name_match(struct device *dev, const void *name)
{
return !strcmp((const char *)name, dev_name(dev));
}
@@ -94,8 +100,16 @@ static void *usb_role_switch_match(struct device_connection *con, int ep,
{
struct device *dev;
- dev = class_find_device(role_class, NULL, con->endpoint[ep],
- __switch_match);
+ if (con->fwnode) {
+ if (!fwnode_property_present(con->fwnode, con->id))
+ return NULL;
+
+ dev = class_find_device(role_class, NULL, con->fwnode,
+ switch_fwnode_match);
+ } else {
+ dev = class_find_device(role_class, NULL, con->endpoint[ep],
+ switch_name_match);
+ }
return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
@@ -266,6 +280,7 @@ usb_role_switch_register(struct device *parent,
sw->get = desc->get;
sw->dev.parent = parent;
+ sw->dev.fwnode = desc->fwnode;
sw->dev.class = role_class;
sw->dev.type = &usb_role_dev_type;
dev_set_name(&sw->dev, "%s-role-switch", dev_name(parent));
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 533f127c30ad..7d031911d04e 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Serial device configuration
#
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index c0777a374a88..fffe23ab0189 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -61,6 +61,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
{ USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */
+ { USB_DEVICE(0x0B00, 0x3070) }, /* Ingenico 3070 */
{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
@@ -245,6 +246,7 @@ struct cp210x_serial_private {
u8 gpio_input;
#endif
u8 partnum;
+ speed_t min_speed;
speed_t max_speed;
bool use_actual_rate;
};
@@ -443,10 +445,10 @@ struct cp210x_pin_mode {
#define CP210X_PIN_MODE_GPIO BIT(0)
/*
- * CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xf bytes.
- * Structure needs padding due to unused/unspecified bytes.
+ * CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xf bytes
+ * on a CP2105 chip. Structure needs padding due to unused/unspecified bytes.
*/
-struct cp210x_config {
+struct cp210x_dual_port_config {
__le16 gpio_mode;
u8 __pad0[2];
__le16 reset_state;
@@ -457,6 +459,19 @@ struct cp210x_config {
u8 device_cfg;
} __packed;
+/*
+ * CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0xd bytes
+ * on a CP2104 chip. Structure needs padding due to unused/unspecified bytes.
+ */
+struct cp210x_single_port_config {
+ __le16 gpio_mode;
+ u8 __pad0[2];
+ __le16 reset_state;
+ u8 __pad1[4];
+ __le16 suspend_state;
+ u8 device_cfg;
+} __packed;
+
/* GPIO modes */
#define CP210X_SCI_GPIO_MODE_OFFSET 9
#define CP210X_SCI_GPIO_MODE_MASK GENMASK(11, 9)
@@ -464,11 +479,19 @@ struct cp210x_config {
#define CP210X_ECI_GPIO_MODE_OFFSET 2
#define CP210X_ECI_GPIO_MODE_MASK GENMASK(3, 2)
+#define CP210X_GPIO_MODE_OFFSET 8
+#define CP210X_GPIO_MODE_MASK GENMASK(11, 8)
+
/* CP2105 port configuration values */
#define CP2105_GPIO0_TXLED_MODE BIT(0)
#define CP2105_GPIO1_RXLED_MODE BIT(1)
#define CP2105_GPIO1_RS485_MODE BIT(2)
+/* CP2104 port configuration values */
+#define CP2104_GPIO0_TXLED_MODE BIT(0)
+#define CP2104_GPIO1_RXLED_MODE BIT(1)
+#define CP2104_GPIO2_RS485_MODE BIT(2)
+
/* CP2102N configuration array indices */
#define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2
#define CP210X_2NCONFIG_GPIO_MODE_IDX 581
@@ -1051,14 +1074,11 @@ static speed_t cp210x_get_an205_rate(speed_t baud)
return cp210x_an205_table1[i].rate;
}
-static speed_t cp210x_get_actual_rate(struct usb_serial *serial, speed_t baud)
+static speed_t cp210x_get_actual_rate(speed_t baud)
{
- struct cp210x_serial_private *priv = usb_get_serial_data(serial);
unsigned int prescale = 1;
unsigned int div;
- baud = clamp(baud, 300u, priv->max_speed);
-
if (baud <= 365)
prescale = 4;
@@ -1101,20 +1121,18 @@ static void cp210x_change_speed(struct tty_struct *tty,
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
u32 baud;
- baud = tty->termios.c_ospeed;
-
/*
* This maps the requested rate to the actual rate, a valid rate on
* cp2102 or cp2103, or to an arbitrary rate in [1M, max_speed].
*
* NOTE: B0 is not implemented.
*/
+ baud = clamp(tty->termios.c_ospeed, priv->min_speed, priv->max_speed);
+
if (priv->use_actual_rate)
- baud = cp210x_get_actual_rate(serial, baud);
+ baud = cp210x_get_actual_rate(baud);
else if (baud < 1000000)
baud = cp210x_get_an205_rate(baud);
- else if (baud > priv->max_speed)
- baud = priv->max_speed;
dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud);
if (cp210x_write_u32_reg(port, CP210X_SET_BAUDRATE, baud)) {
@@ -1353,8 +1371,13 @@ static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio)
if (priv->partnum == CP210X_PARTNUM_CP2105)
req_type = REQTYPE_INTERFACE_TO_HOST;
+ result = usb_autopm_get_interface(serial->interface);
+ if (result)
+ return result;
+
result = cp210x_read_vendor_block(serial, req_type,
CP210X_READ_LATCH, &buf, sizeof(buf));
+ usb_autopm_put_interface(serial->interface);
if (result < 0)
return result;
@@ -1375,6 +1398,10 @@ static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
buf.mask = BIT(gpio);
+ result = usb_autopm_get_interface(serial->interface);
+ if (result)
+ goto out;
+
if (priv->partnum == CP210X_PARTNUM_CP2105) {
result = cp210x_write_vendor_block(serial,
REQTYPE_HOST_TO_INTERFACE,
@@ -1392,6 +1419,8 @@ static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
NULL, 0, USB_CTRL_SET_TIMEOUT);
}
+ usb_autopm_put_interface(serial->interface);
+out:
if (result < 0) {
dev_err(&serial->interface->dev, "failed to set GPIO value: %d\n",
result);
@@ -1470,7 +1499,7 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
{
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
struct cp210x_pin_mode mode;
- struct cp210x_config config;
+ struct cp210x_dual_port_config config;
u8 intf_num = cp210x_interface_num(serial);
u8 iface_config;
int result;
@@ -1529,6 +1558,56 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
return 0;
}
+static int cp2104_gpioconf_init(struct usb_serial *serial)
+{
+ struct cp210x_serial_private *priv = usb_get_serial_data(serial);
+ struct cp210x_single_port_config config;
+ u8 iface_config;
+ u8 gpio_latch;
+ int result;
+ u8 i;
+
+ result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST,
+ CP210X_GET_PORTCONFIG, &config,
+ sizeof(config));
+ if (result < 0)
+ return result;
+
+ priv->gc.ngpio = 4;
+
+ iface_config = config.device_cfg;
+ priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
+ CP210X_GPIO_MODE_MASK) >>
+ CP210X_GPIO_MODE_OFFSET);
+ gpio_latch = (u8)((le16_to_cpu(config.reset_state) &
+ CP210X_GPIO_MODE_MASK) >>
+ CP210X_GPIO_MODE_OFFSET);
+
+ /* mark all pins which are not in GPIO mode */
+ if (iface_config & CP2104_GPIO0_TXLED_MODE) /* GPIO 0 */
+ priv->gpio_altfunc |= BIT(0);
+ if (iface_config & CP2104_GPIO1_RXLED_MODE) /* GPIO 1 */
+ priv->gpio_altfunc |= BIT(1);
+ if (iface_config & CP2104_GPIO2_RS485_MODE) /* GPIO 2 */
+ priv->gpio_altfunc |= BIT(2);
+
+ /*
+ * Like CP2102N, CP2104 has also no strict input and output pin
+ * modes.
+ * Do the same input mode emulation as CP2102N.
+ */
+ for (i = 0; i < priv->gc.ngpio; ++i) {
+ /*
+ * Set direction to "input" iff pin is open-drain and reset
+ * value is 1.
+ */
+ if (!(priv->gpio_pushpull & BIT(i)) && (gpio_latch & BIT(i)))
+ priv->gpio_input |= BIT(i);
+ }
+
+ return 0;
+}
+
static int cp2102n_gpioconf_init(struct usb_serial *serial)
{
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
@@ -1574,12 +1653,6 @@ static int cp2102n_gpioconf_init(struct usb_serial *serial)
if (config_version != 0x01)
return -ENOTSUPP;
- /*
- * We only support 4 GPIOs even on the QFN28 package, because
- * config locations of GPIOs 4-6 determined using reverse
- * engineering revealed conflicting offsets with other
- * documented functions. So we'll just play it safe for now.
- */
priv->gc.ngpio = 4;
/*
@@ -1594,6 +1667,19 @@ static int cp2102n_gpioconf_init(struct usb_serial *serial)
/* 0 indicates GPIO mode, 1 is alternate function */
priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f;
+ if (priv->partnum == CP210X_PARTNUM_CP2102N_QFN28) {
+ /*
+ * For the QFN28 package, GPIO4-6 are controlled by
+ * the low three bits of the mode/latch fields.
+ * Contrary to the document linked above, the bits for
+ * the SUSPEND pins are elsewhere. No alternate
+ * function is available for these pins.
+ */
+ priv->gc.ngpio = 7;
+ gpio_latch |= (gpio_rst_latch & 7) << 4;
+ priv->gpio_pushpull |= (gpio_pushpull & 7) << 4;
+ }
+
/*
* The CP2102N does not strictly has input and output pin modes,
* it only knows open-drain and push-pull modes which is set at
@@ -1620,6 +1706,9 @@ static int cp210x_gpio_init(struct usb_serial *serial)
int result;
switch (priv->partnum) {
+ case CP210X_PARTNUM_CP2104:
+ result = cp2104_gpioconf_init(serial);
+ break;
case CP210X_PARTNUM_CP2105:
result = cp2105_gpioconf_init(serial);
break;
@@ -1716,6 +1805,7 @@ static void cp210x_init_max_speed(struct usb_serial *serial)
{
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
bool use_actual_rate = false;
+ speed_t min = 300;
speed_t max;
switch (priv->partnum) {
@@ -1738,6 +1828,7 @@ static void cp210x_init_max_speed(struct usb_serial *serial)
use_actual_rate = true;
max = 2000000; /* ECI */
} else {
+ min = 2400;
max = 921600; /* SCI */
}
break;
@@ -1752,6 +1843,7 @@ static void cp210x_init_max_speed(struct usb_serial *serial)
break;
}
+ priv->min_speed = min;
priv->max_speed = max;
priv->use_actual_rate = use_actual_rate;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 1ab2a6191013..8f5b17471759 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1025,6 +1025,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) },
{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) },
{ USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) },
+ /* EZPrototypes devices */
+ { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) },
{ } /* Terminating entry */
};
@@ -1783,6 +1785,10 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
int result;
u16 val;
+ result = usb_autopm_get_interface(serial->interface);
+ if (result)
+ return result;
+
val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value;
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
@@ -1795,6 +1801,8 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
val, result);
}
+ usb_autopm_put_interface(serial->interface);
+
return result;
}
@@ -1846,9 +1854,15 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
unsigned char *buf;
int result;
+ result = usb_autopm_get_interface(serial->interface);
+ if (result)
+ return result;
+
buf = kmalloc(1, GFP_KERNEL);
- if (!buf)
+ if (!buf) {
+ usb_autopm_put_interface(serial->interface);
return -ENOMEM;
+ }
result = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
@@ -1863,6 +1877,7 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
}
kfree(buf);
+ usb_autopm_put_interface(serial->interface);
return result;
}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 975d02666c5a..b863bedb55a1 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1309,6 +1309,12 @@
#define IONICS_PLUGCOMPUTER_PID 0x0102
/*
+ * EZPrototypes (PID reseller)
+ */
+#define EZPROTOTYPES_VID 0x1c40
+#define HJELMSLUND_USB485_ISO_PID 0x0477
+
+/*
* Dresden Elektronik Sensor Terminal Board
*/
#define DE_VID 0x1cf1 /* Vendor ID */
diff --git a/drivers/usb/serial/keyspan_usa26msg.h b/drivers/usb/serial/keyspan_usa26msg.h
index 09e21e84fc4e..a68f1fb25b8a 100644
--- a/drivers/usb/serial/keyspan_usa26msg.h
+++ b/drivers/usb/serial/keyspan_usa26msg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
usa26msg.h
diff --git a/drivers/usb/serial/keyspan_usa28msg.h b/drivers/usb/serial/keyspan_usa28msg.h
index dee454c4609a..a19f3fe5d98d 100644
--- a/drivers/usb/serial/keyspan_usa28msg.h
+++ b/drivers/usb/serial/keyspan_usa28msg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
usa28msg.h
diff --git a/drivers/usb/serial/keyspan_usa49msg.h b/drivers/usb/serial/keyspan_usa49msg.h
index 163b2dea2ec5..8c3970fdd868 100644
--- a/drivers/usb/serial/keyspan_usa49msg.h
+++ b/drivers/usb/serial/keyspan_usa49msg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
usa49msg.h
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h
index 20fa3e2f7187..dcf502fdbb44 100644
--- a/drivers/usb/serial/keyspan_usa67msg.h
+++ b/drivers/usb/serial/keyspan_usa67msg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
usa67msg.h
diff --git a/drivers/usb/serial/keyspan_usa90msg.h b/drivers/usb/serial/keyspan_usa90msg.h
index 86708ecd8735..c4ca0f631d20 100644
--- a/drivers/usb/serial/keyspan_usa90msg.h
+++ b/drivers/usb/serial/keyspan_usa90msg.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
usa90msg.h
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index aef15497ff31..11b21d9410f3 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1148,6 +1148,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
.driver_info = NCTRL(0) | RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1102, 0xff), /* Telit ME910 (ECM) */
+ .driver_info = NCTRL(0) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 98e7a5df0f6d..bb3f9aa4a909 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -46,6 +46,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 4e2554d55362..559941ca884d 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -8,6 +8,7 @@
#define PL2303_VENDOR_ID 0x067b
#define PL2303_PRODUCT_ID 0x2303
+#define PL2303_PRODUCT_ID_TB 0x2304
#define PL2303_PRODUCT_ID_RSAQ2 0x04bb
#define PL2303_PRODUCT_ID_DCU11 0x1234
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
@@ -20,6 +21,7 @@
#define PL2303_PRODUCT_ID_MOTOROLA 0x0307
#define PL2303_PRODUCT_ID_ZTEK 0xe1f1
+
#define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547
#define ATEN_PRODUCT_ID 0x2008
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 4d0273508043..edbbb13d6de6 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -85,7 +85,8 @@ DEVICE(moto_modem, MOTO_IDS);
/* Motorola Tetra driver */
#define MOTOROLA_TETRA_IDS() \
{ USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
- { USB_DEVICE(0x0cad, 0x9012) } /* MTP6550 */
+ { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+ { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */
DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
/* Novatel Wireless GPS driver */
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 6fd427284b12..59aad38b490a 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Storage driver configuration
#
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index edcf2be0e0eb..395cf8fb5870 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -167,6 +167,7 @@ static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
static void rio_karma_destructor(void *extra)
{
struct karma_data *data = (struct karma_data *) extra;
+
kfree(data->recv);
}
@@ -174,6 +175,7 @@ static int rio_karma_init(struct us_data *us)
{
int ret = 0;
struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+
if (!data)
goto out;
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index fde2e71a6ade..a73ea495d5a7 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -235,8 +235,12 @@ static int slave_configure(struct scsi_device *sdev)
if (!(us->fflags & US_FL_NEEDS_CAP16))
sdev->try_rc_10_first = 1;
- /* assume SPC3 or latter devices support sense size > 18 */
- if (sdev->scsi_level > SCSI_SPC_2)
+ /*
+ * assume SPC3 or latter devices support sense size > 18
+ * unless US_FL_BAD_SENSE quirk is specified.
+ */
+ if (sdev->scsi_level > SCSI_SPC_2 &&
+ !(us->fflags & US_FL_BAD_SENSE))
us->fflags |= US_FL_SANE_SENSE;
/*
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f7f83b21dc74..ea0d27a94afe 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1266,6 +1266,18 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
US_FL_FIX_CAPACITY ),
/*
+ * Reported by Icenowy Zheng <icenowy@aosc.io>
+ * The SMI SM3350 USB-UFS bridge controller will enter a wrong state
+ * that do not process read/write command if a long sense is requested,
+ * so force to use 18-byte sense.
+ */
+UNUSUAL_DEV( 0x090c, 0x3350, 0x0000, 0xffff,
+ "SMI",
+ "SM3350 UFS-to-USB-Mass-Storage bridge",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BAD_SENSE ),
+
+/*
* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
* This card reader returns "Illegal Request, Logical Block Address
* Out of Range" for the first READ(10) after a new card is inserted.
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 30a847c2089d..89d9193bd1cf 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
menuconfig TYPEC
tristate "USB Type-C Support"
diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig
index efef2a64bc51..ef2226eb7a33 100644
--- a/drivers/usb/typec/altmodes/Kconfig
+++ b/drivers/usb/typec/altmodes/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
menu "USB Type-C Alternate Mode drivers"
diff --git a/drivers/usb/typec/altmodes/Makefile b/drivers/usb/typec/altmodes/Makefile
index 5caf094ef71a..eda8456f1c92 100644
--- a/drivers/usb/typec/altmodes/Makefile
+++ b/drivers/usb/typec/altmodes/Makefile
@@ -1,2 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
obj-$(CONFIG_TYPEC_DP_ALTMODE) += typec_displayport.o
typec_displayport-y := displayport.o
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 3f06e94771a7..610d790bc9be 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -24,10 +24,6 @@ enum {
DP_CONF_DUAL_D,
};
-/* Helper for setting/getting the pin assignement value to the configuration */
-#define DP_CONF_SET_PIN_ASSIGN(_a_) ((_a_) << 8)
-#define DP_CONF_GET_PIN_ASSIGN(_conf_) (((_conf_) & GENMASK(15, 8)) >> 8)
-
/* Pin assignments that use USB3.1 Gen2 signaling to carry DP protocol */
#define DP_PIN_ASSIGN_GEN2_BR_MASK (BIT(DP_PIN_ASSIGN_A) | \
BIT(DP_PIN_ASSIGN_B))
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 5db0593ca0bd..2eb623841847 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include "bus.h"
@@ -204,15 +205,32 @@ static void typec_altmode_put_partner(struct altmode *altmode)
put_device(&adev->dev);
}
-static int __typec_port_match(struct device *dev, const void *name)
+static int typec_port_fwnode_match(struct device *dev, const void *fwnode)
+{
+ return dev_fwnode(dev) == fwnode;
+}
+
+static int typec_port_name_match(struct device *dev, const void *name)
{
return !strcmp((const char *)name, dev_name(dev));
}
static void *typec_port_match(struct device_connection *con, int ep, void *data)
{
- return class_find_device(typec_class, NULL, con->endpoint[ep],
- __typec_port_match);
+ struct device *dev;
+
+ /*
+ * FIXME: Check does the fwnode supports the requested SVID. If it does
+ * we need to return ERR_PTR(-PROBE_DEFER) when there is no device.
+ */
+ if (con->fwnode)
+ return class_find_device(typec_class, NULL, con->fwnode,
+ typec_port_fwnode_match);
+
+ dev = class_find_device(typec_class, NULL, con->endpoint[ep],
+ typec_port_name_match);
+
+ return dev ? dev : ERR_PTR(-EPROBE_DEFER);
}
struct typec_altmode *
@@ -277,7 +295,7 @@ void typec_altmode_update_active(struct typec_altmode *adev, bool active)
if (adev->active == active)
return;
- if (!is_typec_port(adev->dev.parent)) {
+ if (!is_typec_port(adev->dev.parent) && adev->dev.driver) {
if (!active)
module_put(adev->dev.driver->owner);
else
@@ -1496,11 +1514,8 @@ typec_port_register_altmode(struct typec_port *port,
{
struct typec_altmode *adev;
struct typec_mux *mux;
- char id[10];
-
- sprintf(id, "id%04xm%02x", desc->svid, desc->mode);
- mux = typec_mux_get(&port->dev, id);
+ mux = typec_mux_get(&port->dev, desc);
if (IS_ERR(mux))
return ERR_CAST(mux);
@@ -1593,7 +1608,7 @@ struct typec_port *typec_register_port(struct device *parent,
return ERR_CAST(port->sw);
}
- port->mux = typec_mux_get(&port->dev, "typec-mux");
+ port->mux = typec_mux_get(&port->dev, NULL);
if (IS_ERR(port->mux)) {
put_device(&port->dev);
return ERR_CAST(port->mux);
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index d990aa510fab..2ce54f3fc79c 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -11,6 +11,8 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/slab.h>
#include <linux/usb/typec_mux.h>
static DEFINE_MUTEX(switch_lock);
@@ -23,15 +25,25 @@ static void *typec_switch_match(struct device_connection *con, int ep,
{
struct typec_switch *sw;
- list_for_each_entry(sw, &switch_list, entry)
- if (!strcmp(con->endpoint[ep], dev_name(sw->dev)))
- return sw;
+ if (!con->fwnode) {
+ list_for_each_entry(sw, &switch_list, entry)
+ if (!strcmp(con->endpoint[ep], dev_name(sw->dev)))
+ return sw;
+ return ERR_PTR(-EPROBE_DEFER);
+ }
/*
- * We only get called if a connection was found, tell the caller to
- * wait for the switch to show up.
+ * With OF graph the mux node must have a boolean device property named
+ * "orientation-switch".
*/
- return ERR_PTR(-EPROBE_DEFER);
+ if (con->id && !fwnode_property_present(con->fwnode, con->id))
+ return NULL;
+
+ list_for_each_entry(sw, &switch_list, entry)
+ if (dev_fwnode(sw->dev) == con->fwnode)
+ return sw;
+
+ return con->id ? ERR_PTR(-EPROBE_DEFER) : NULL;
}
/**
@@ -48,7 +60,7 @@ struct typec_switch *typec_switch_get(struct device *dev)
struct typec_switch *sw;
mutex_lock(&switch_lock);
- sw = device_connection_find_match(dev, "typec-switch", NULL,
+ sw = device_connection_find_match(dev, "orientation-switch", NULL,
typec_switch_match);
if (!IS_ERR_OR_NULL(sw)) {
WARN_ON(!try_module_get(sw->dev->driver->owner));
@@ -112,35 +124,87 @@ EXPORT_SYMBOL_GPL(typec_switch_unregister);
static void *typec_mux_match(struct device_connection *con, int ep, void *data)
{
+ const struct typec_altmode_desc *desc = data;
struct typec_mux *mux;
+ int nval;
+ bool match;
+ u16 *val;
+ int i;
- list_for_each_entry(mux, &mux_list, entry)
- if (!strcmp(con->endpoint[ep], dev_name(mux->dev)))
- return mux;
+ if (!con->fwnode) {
+ list_for_each_entry(mux, &mux_list, entry)
+ if (!strcmp(con->endpoint[ep], dev_name(mux->dev)))
+ return mux;
+ return ERR_PTR(-EPROBE_DEFER);
+ }
/*
- * We only get called if a connection was found, tell the caller to
- * wait for the switch to show up.
+ * Check has the identifier already been "consumed". If it
+ * has, no need to do any extra connection identification.
*/
+ match = !con->id;
+ if (match)
+ goto find_mux;
+
+ /* Accessory Mode muxes */
+ if (!desc) {
+ match = fwnode_property_present(con->fwnode, "accessory");
+ if (match)
+ goto find_mux;
+ return NULL;
+ }
+
+ /* Alternate Mode muxes */
+ nval = fwnode_property_read_u16_array(con->fwnode, "svid", NULL, 0);
+ if (nval <= 0)
+ return NULL;
+
+ val = kcalloc(nval, sizeof(*val), GFP_KERNEL);
+ if (!val)
+ return ERR_PTR(-ENOMEM);
+
+ nval = fwnode_property_read_u16_array(con->fwnode, "svid", val, nval);
+ if (nval < 0) {
+ kfree(val);
+ return ERR_PTR(nval);
+ }
+
+ for (i = 0; i < nval; i++) {
+ match = val[i] == desc->svid;
+ if (match) {
+ kfree(val);
+ goto find_mux;
+ }
+ }
+ kfree(val);
+ return NULL;
+
+find_mux:
+ list_for_each_entry(mux, &mux_list, entry)
+ if (dev_fwnode(mux->dev) == con->fwnode)
+ return mux;
+
return ERR_PTR(-EPROBE_DEFER);
}
/**
* typec_mux_get - Find USB Type-C Multiplexer
* @dev: The caller device
- * @name: Mux identifier
+ * @desc: Alt Mode description
*
* Finds a mux linked to the caller. This function is primarily meant for the
* Type-C drivers. Returns a reference to the mux on success, NULL if no
* matching connection was found, or ERR_PTR(-EPROBE_DEFER) when a connection
* was found but the mux has not been enumerated yet.
*/
-struct typec_mux *typec_mux_get(struct device *dev, const char *name)
+struct typec_mux *typec_mux_get(struct device *dev,
+ const struct typec_altmode_desc *desc)
{
struct typec_mux *mux;
mutex_lock(&mux_lock);
- mux = device_connection_find_match(dev, name, NULL, typec_mux_match);
+ mux = device_connection_find_match(dev, "mode-switch", (void *)desc,
+ typec_mux_match);
if (!IS_ERR_OR_NULL(mux)) {
WARN_ON(!try_module_get(mux->dev->driver->owner));
get_device(mux->dev);
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index 9a954d2b8d8f..01ed0d5e10e8 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
menu "USB Type-C Multiplexer/DeMultiplexer Switch support"
config TYPEC_MUX_PI3USB30532
diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index f03ea8a61768..72481bbb2af3 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config TYPEC_TCPM
tristate "USB Type-C Port Controller Manager"
depends on USB
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 4bc29b586698..0f62db091d8d 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -2297,7 +2297,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
pdo_pps_apdo_max_voltage(snk));
port->pps_data.max_curr = min_pps_apdo_current(src, snk);
port->pps_data.out_volt = min(port->pps_data.max_volt,
- port->pps_data.out_volt);
+ max(port->pps_data.min_volt,
+ port->pps_data.out_volt));
port->pps_data.op_curr = min(port->pps_data.max_curr,
port->pps_data.op_curr);
}
@@ -4434,66 +4435,6 @@ sink:
return 0;
}
-int tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo,
- unsigned int nr_pdo)
-{
- if (tcpm_validate_caps(port, pdo, nr_pdo))
- return -EINVAL;
-
- mutex_lock(&port->lock);
- port->nr_src_pdo = tcpm_copy_pdos(port->src_pdo, pdo, nr_pdo);
- switch (port->state) {
- case SRC_UNATTACHED:
- case SRC_ATTACH_WAIT:
- case SRC_TRYWAIT:
- tcpm_set_cc(port, tcpm_rp_cc(port));
- break;
- case SRC_SEND_CAPABILITIES:
- case SRC_NEGOTIATE_CAPABILITIES:
- case SRC_READY:
- case SRC_WAIT_NEW_CAPABILITIES:
- tcpm_set_cc(port, tcpm_rp_cc(port));
- tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
- break;
- default:
- break;
- }
- mutex_unlock(&port->lock);
- return 0;
-}
-EXPORT_SYMBOL_GPL(tcpm_update_source_capabilities);
-
-int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo,
- unsigned int nr_pdo,
- unsigned int operating_snk_mw)
-{
- if (tcpm_validate_caps(port, pdo, nr_pdo))
- return -EINVAL;
-
- mutex_lock(&port->lock);
- port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, pdo, nr_pdo);
- port->operating_snk_mw = operating_snk_mw;
- port->update_sink_caps = true;
-
- switch (port->state) {
- case SNK_NEGOTIATE_CAPABILITIES:
- case SNK_NEGOTIATE_PPS_CAPABILITIES:
- case SNK_READY:
- case SNK_TRANSITION_SINK:
- case SNK_TRANSITION_SINK_VBUS:
- if (port->pps_data.active)
- tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0);
- else
- tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0);
- break;
- default:
- break;
- }
- mutex_unlock(&port->lock);
- return 0;
-}
-EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities);
-
/* Power Supply access to expose source power information */
enum tcpm_psy_online_states {
TCPM_PSY_OFFLINE = 0,
@@ -4810,12 +4751,12 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
err = devm_tcpm_psy_register(port);
if (err)
- goto out_destroy_wq;
+ goto out_role_sw_put;
port->typec_port = typec_register_port(port->dev, &port->typec_caps);
if (IS_ERR(port->typec_port)) {
err = PTR_ERR(port->typec_port);
- goto out_destroy_wq;
+ goto out_role_sw_put;
}
if (tcpc->config && tcpc->config->alt_modes) {
@@ -4848,8 +4789,10 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
tcpm_log(port, "%s: registered", dev_name(dev));
return port;
-out_destroy_wq:
+out_role_sw_put:
usb_role_switch_put(port->role_sw);
+out_destroy_wq:
+ tcpm_debugfs_exit(port);
destroy_workqueue(port->wq);
return ERR_PTR(err);
}
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 1c0033ad8738..c674abe3cf99 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -14,6 +14,8 @@
#include <linux/usb/typec.h>
/* Register offsets */
+#define TPS_REG_VID 0x00
+#define TPS_REG_MODE 0x03
#define TPS_REG_CMD1 0x08
#define TPS_REG_DATA1 0x09
#define TPS_REG_INT_EVENT1 0x14
@@ -66,6 +68,20 @@ struct tps6598x_rx_identity_reg {
#define TPS_TASK_TIMEOUT 1
#define TPS_TASK_REJECTED 3
+enum {
+ TPS_MODE_APP,
+ TPS_MODE_BOOT,
+ TPS_MODE_BIST,
+ TPS_MODE_DISC,
+};
+
+static const char *const modes[] = {
+ [TPS_MODE_APP] = "APP ",
+ [TPS_MODE_BOOT] = "BOOT",
+ [TPS_MODE_BIST] = "BIST",
+ [TPS_MODE_DISC] = "DISC",
+};
+
/* Unrecognized commands will be replaced with "!CMD" */
#define INVALID_CMD(_cmd_) (_cmd_ == 0x444d4321)
@@ -110,6 +126,20 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len)
return 0;
}
+static int tps6598x_block_write(struct tps6598x *tps, u8 reg,
+ void *val, size_t len)
+{
+ u8 data[TPS_MAX_LEN + 1];
+
+ if (!tps->i2c_protocol)
+ return regmap_raw_write(tps->regmap, reg, val, len);
+
+ data[0] = len;
+ memcpy(&data[1], val, len);
+
+ return regmap_raw_write(tps->regmap, reg, data, sizeof(data));
+}
+
static inline int tps6598x_read16(struct tps6598x *tps, u8 reg, u16 *val)
{
return tps6598x_block_read(tps, reg, val, sizeof(u16));
@@ -127,23 +157,23 @@ static inline int tps6598x_read64(struct tps6598x *tps, u8 reg, u64 *val)
static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val)
{
- return regmap_raw_write(tps->regmap, reg, &val, sizeof(u16));
+ return tps6598x_block_write(tps, reg, &val, sizeof(u16));
}
static inline int tps6598x_write32(struct tps6598x *tps, u8 reg, u32 val)
{
- return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32));
+ return tps6598x_block_write(tps, reg, &val, sizeof(u32));
}
static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val)
{
- return regmap_raw_write(tps->regmap, reg, &val, sizeof(u64));
+ return tps6598x_block_write(tps, reg, &val, sizeof(u64));
}
static inline int
tps6598x_write_4cc(struct tps6598x *tps, u8 reg, const char *val)
{
- return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32));
+ return tps6598x_block_write(tps, reg, &val, sizeof(u32));
}
static int tps6598x_read_partner_identity(struct tps6598x *tps)
@@ -229,8 +259,8 @@ static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd,
return -EBUSY;
if (in_len) {
- ret = regmap_raw_write(tps->regmap, TPS_REG_DATA1,
- in_data, in_len);
+ ret = tps6598x_block_write(tps, TPS_REG_DATA1,
+ in_data, in_len);
if (ret)
return ret;
}
@@ -384,6 +414,32 @@ err_unlock:
return IRQ_HANDLED;
}
+static int tps6598x_check_mode(struct tps6598x *tps)
+{
+ char mode[5] = { };
+ int ret;
+
+ ret = tps6598x_read32(tps, TPS_REG_MODE, (void *)mode);
+ if (ret)
+ return ret;
+
+ switch (match_string(modes, ARRAY_SIZE(modes), mode)) {
+ case TPS_MODE_APP:
+ return 0;
+ case TPS_MODE_BOOT:
+ dev_warn(tps->dev, "dead-battery condition\n");
+ return 0;
+ case TPS_MODE_BIST:
+ case TPS_MODE_DISC:
+ default:
+ dev_err(tps->dev, "controller in unsupported mode \"%s\"\n",
+ mode);
+ break;
+ }
+
+ return -ENODEV;
+}
+
static const struct regmap_config tps6598x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -409,10 +465,8 @@ static int tps6598x_probe(struct i2c_client *client)
if (IS_ERR(tps->regmap))
return PTR_ERR(tps->regmap);
- ret = tps6598x_read32(tps, 0, &vid);
- if (ret < 0)
- return ret;
- if (!vid)
+ ret = tps6598x_read32(tps, TPS_REG_VID, &vid);
+ if (ret < 0 || !vid)
return -ENODEV;
/*
@@ -425,6 +479,11 @@ static int tps6598x_probe(struct i2c_client *client)
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
tps->i2c_protocol = true;
+ /* Make sure the controller has application firmware running */
+ ret = tps6598x_check_mode(tps);
+ if (ret)
+ return ret;
+
ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
if (ret < 0)
return ret;
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index 78118883f96c..15c2ac7db02d 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config TYPEC_UCSI
tristate "USB Type-C Connector System Software Interface driver"
depends on !CPU_BIG_ENDIAN
diff --git a/drivers/usb/typec/ucsi/debug.h b/drivers/usb/typec/ucsi/debug.h
deleted file mode 100644
index fdeff39df120..000000000000
--- a/drivers/usb/typec/ucsi/debug.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#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
index d9a6ff6e673c..ffa3b4c3f338 100644
--- a/drivers/usb/typec/ucsi/trace.c
+++ b/drivers/usb/typec/ucsi/trace.c
@@ -1,3 +1,62 @@
// SPDX-License-Identifier: GPL-2.0
#define CREATE_TRACE_POINTS
+#include "ucsi.h"
#include "trace.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",
+};
+
+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",
+};
+
+const char *ucsi_ack_str(u8 ack)
+{
+ return ucsi_ack_strs[(ack >= ARRAY_SIZE(ucsi_ack_strs)) ? 0 : ack];
+}
+
+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 "";
+}
diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h
index d5092446ecc6..5e2906df2db7 100644
--- a/drivers/usb/typec/ucsi/trace.h
+++ b/drivers/usb/typec/ucsi/trace.h
@@ -7,8 +7,11 @@
#define __UCSI_TRACE_H
#include <linux/tracepoint.h>
-#include "ucsi.h"
-#include "debug.h"
+
+const char *ucsi_cmd_str(u64 raw_cmd);
+const char *ucsi_ack_str(u8 ack);
+const char *ucsi_cci_str(u32 cci);
+const char *ucsi_recipient_str(u8 recipient);
DECLARE_EVENT_CLASS(ucsi_log_ack,
TP_PROTO(u8 ack),
diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig
index a20b65cb6678..2f86b28fa3da 100644
--- a/drivers/usb/usbip/Kconfig
+++ b/drivers/usb/usbip/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
config USBIP_CORE
tristate "USB/IP support"
depends on NET
diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README
deleted file mode 100644
index 41a2cf2e77a6..000000000000
--- a/drivers/usb/usbip/README
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
- - more discussion about the protocol
- - testing
- - review of the userspace interface
- - document the protocol
-
-Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 1e592ec94ba4..f46ee1fefe02 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -702,8 +702,10 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
}
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);
+ if (!urb->transfer_buffer && urb->transfer_buffer_length) {
+ dev_dbg(dev, "Null URB transfer buffer\n");
+ return -EINVAL;
+ }
spin_lock_irqsave(&vhci->lock, flags);
diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c
index 1634d8698e15..a72c17ff1c6a 100644
--- a/drivers/usb/usbip/vudc_dev.c
+++ b/drivers/usb/usbip/vudc_dev.c
@@ -297,7 +297,8 @@ static void vep_free_request(struct usb_ep *_ep, struct usb_request *_req)
{
struct vrequest *req;
- if (WARN_ON(!_ep || !_req))
+ /* ep is always valid here - see usb_ep_free_request() */
+ if (!_req)
return;
req = to_vrequest(_req);
diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index 348de1d6726e..12e89189ca7d 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Wireless USB Core configuration
#
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index 222228c5c1e1..af77064c7456 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -302,10 +302,8 @@ static ssize_t cbaf_wusb_chid_show(struct device *dev,
{
struct usb_interface *iface = to_usb_interface(dev);
struct cbaf *cbaf = usb_get_intfdata(iface);
- char pr_chid[WUSB_CKHDID_STRSIZE];
- ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid);
- return scnprintf(buf, PAGE_SIZE, "%s\n", pr_chid);
+ return sprintf(buf, "%16ph\n", cbaf->chid.data);
}
static ssize_t cbaf_wusb_chid_store(struct device *dev,
@@ -415,10 +413,8 @@ static ssize_t cbaf_wusb_cdid_show(struct device *dev,
{
struct usb_interface *iface = to_usb_interface(dev);
struct cbaf *cbaf = usb_get_intfdata(iface);
- char pr_cdid[WUSB_CKHDID_STRSIZE];
- ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid);
- return scnprintf(buf, PAGE_SIZE, "%s\n", pr_cdid);
+ return sprintf(buf, "%16ph\n", cbaf->cdid.data);
}
static ssize_t cbaf_wusb_cdid_store(struct device *dev,
@@ -503,7 +499,6 @@ static int cbaf_cc_upload(struct cbaf *cbaf)
int result;
struct device *dev = &cbaf->usb_iface->dev;
struct wusb_cbaf_cc_data *ccd;
- char pr_cdid[WUSB_CKHDID_STRSIZE];
ccd = cbaf->buffer;
*ccd = cbaf_cc_data_defaults;
@@ -513,10 +508,8 @@ static int cbaf_cc_upload(struct cbaf *cbaf)
ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups);
dev_dbg(dev, "Trying to upload CC:\n");
- ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID);
- dev_dbg(dev, " CHID %s\n", pr_cdid);
- ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID);
- dev_dbg(dev, " CDID %s\n", pr_cdid);
+ dev_dbg(dev, " CHID %16ph\n", ccd->CHID.data);
+ dev_dbg(dev, " CDID %16ph\n", ccd->CDID.data);
dev_dbg(dev, " Bandgroups 0x%04x\n", cbaf->host_band_groups);
result = usb_control_msg(
diff --git a/drivers/usb/wusbcore/dev-sysfs.c b/drivers/usb/wusbcore/dev-sysfs.c
index 85a1acf3a729..67b0a4c412b2 100644
--- a/drivers/usb/wusbcore/dev-sysfs.c
+++ b/drivers/usb/wusbcore/dev-sysfs.c
@@ -50,10 +50,9 @@ static ssize_t wusb_cdid_show(struct device *dev,
wusb_dev = wusb_dev_get_by_usb_dev(to_usb_device(dev));
if (wusb_dev == NULL)
return -ENODEV;
- result = ckhdid_printf(buf, PAGE_SIZE, &wusb_dev->cdid);
- strcat(buf, "\n");
+ result = sprintf(buf, "%16ph\n", wusb_dev->cdid.data);
wusb_dev_put(wusb_dev);
- return result + 1;
+ return result;
}
static DEVICE_ATTR_RO(wusb_cdid);
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index fcb06aef2675..a93837d57d53 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -532,7 +532,7 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
}
dnc = container_of(dn_hdr, struct wusb_dn_connect, hdr);
- ckhdid_printf(pr_cdid, sizeof(pr_cdid), &dnc->CDID);
+ sprintf(pr_cdid, "%16ph", dnc->CDID.data);
dev_info(dev, "DN CONNECT: device %s @ %x (%s) wants to %s\n",
pr_cdid,
wusb_dn_connect_prev_dev_addr(dnc),
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 01f2f21830c0..abf88cea37bb 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -662,9 +662,9 @@ static void __wa_setup_isoc_packet_descr(
/* populate isoc packet descriptor. */
packet_desc->bPacketType = WA_XFER_ISO_PACKET_INFO;
- packet_desc->wLength = cpu_to_le16(sizeof(*packet_desc) +
- (sizeof(packet_desc->PacketLength[0]) *
- seg->isoc_frame_count));
+ packet_desc->wLength = cpu_to_le16(struct_size(packet_desc,
+ PacketLength,
+ seg->isoc_frame_count));
for (frame_index = 0; frame_index < seg->isoc_frame_count;
++frame_index) {
int offset_index = frame_index + seg->isoc_frame_offset;
@@ -2438,7 +2438,7 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
struct wa_rpipe *rpipe;
unsigned done = 0, dti_busy = 0, data_frame_count = 0, seg_index;
unsigned first_frame_index = 0, rpipe_ready = 0;
- int expected_size;
+ size_t expected_size;
/* We have a xfer result buffer; check it */
dev_dbg(dev, "DTI: isoc packet status %d bytes at %p\n",
@@ -2460,11 +2460,10 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
goto error_bad_seg;
seg = xfer->seg[wa->dti_isoc_xfer_seg];
rpipe = xfer->ep->hcpriv;
- expected_size = sizeof(*packet_status) +
- (sizeof(packet_status->PacketStatus[0]) *
- seg->isoc_frame_count);
+ expected_size = struct_size(packet_status, PacketStatus,
+ seg->isoc_frame_count);
if (urb->actual_length != expected_size) {
- dev_err(dev, "DTI Error: isoc packet status--bad urb length (%d bytes vs %d needed)\n",
+ dev_err(dev, "DTI Error: isoc packet status--bad urb length (%d bytes vs %zu needed)\n",
urb->actual_length, expected_size);
goto error_bad_seg;
}
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c
index e5ba6140c1ba..d0b404d258e8 100644
--- a/drivers/usb/wusbcore/wusbhc.c
+++ b/drivers/usb/wusbcore/wusbhc.c
@@ -80,17 +80,13 @@ static ssize_t wusb_chid_show(struct device *dev,
{
struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev);
const struct wusb_ckhdid *chid;
- ssize_t result = 0;
if (wusbhc->wuie_host_info != NULL)
chid = &wusbhc->wuie_host_info->CHID;
else
chid = &wusb_ckhdid_zero;
- result += ckhdid_printf(buf, PAGE_SIZE, chid);
- result += sprintf(buf + result, "\n");
-
- return result;
+ return sprintf(buf, "%16ph\n", chid->data);
}
/*
diff --git a/drivers/uwb/drp-ie.c b/drivers/uwb/drp-ie.c
index 1d2a939cfcf8..ed993e363472 100644
--- a/drivers/uwb/drp-ie.c
+++ b/drivers/uwb/drp-ie.c
@@ -125,9 +125,8 @@ static struct uwb_ie_drp *uwb_drp_ie_alloc(void)
{
struct uwb_ie_drp *drp_ie;
- drp_ie = kzalloc(sizeof(struct uwb_ie_drp) +
- UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc),
- GFP_KERNEL);
+ drp_ie = kzalloc(struct_size(drp_ie, allocs, UWB_NUM_ZONES),
+ GFP_KERNEL);
if (drp_ie)
drp_ie->hdr.element_id = UWB_IE_DRP;
return drp_ie;
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 0212f0ee8aea..b96fedc77ee5 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -60,9 +60,9 @@ struct mdev_device *mdev_from_dev(struct device *dev)
}
EXPORT_SYMBOL(mdev_from_dev);
-uuid_le mdev_uuid(struct mdev_device *mdev)
+const guid_t *mdev_uuid(struct mdev_device *mdev)
{
- return mdev->uuid;
+ return &mdev->uuid;
}
EXPORT_SYMBOL(mdev_uuid);
@@ -88,8 +88,7 @@ static void mdev_release_parent(struct kref *kref)
put_device(dev);
}
-static
-inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
+static inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
{
if (parent)
kref_get(&parent->ref);
@@ -276,7 +275,8 @@ static void mdev_device_release(struct device *dev)
kfree(mdev);
}
-int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
+int mdev_device_create(struct kobject *kobj,
+ struct device *dev, const guid_t *uuid)
{
int ret;
struct mdev_device *mdev, *tmp;
@@ -291,7 +291,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
/* Check for duplicate */
list_for_each_entry(tmp, &mdev_list, next) {
- if (!uuid_le_cmp(tmp->uuid, uuid)) {
+ if (guid_equal(&tmp->uuid, uuid)) {
mutex_unlock(&mdev_list_lock);
ret = -EEXIST;
goto mdev_fail;
@@ -305,7 +305,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
goto mdev_fail;
}
- memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
+ guid_copy(&mdev->uuid, uuid);
list_add(&mdev->next, &mdev_list);
mutex_unlock(&mdev_list_lock);
@@ -315,7 +315,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
mdev->dev.parent = dev;
mdev->dev.bus = &mdev_bus_type;
mdev->dev.release = mdev_device_release;
- dev_set_name(&mdev->dev, "%pUl", uuid.b);
+ dev_set_name(&mdev->dev, "%pUl", uuid);
ret = device_register(&mdev->dev);
if (ret) {
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index b5819b7d7ef7..379758c52b1b 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -28,7 +28,7 @@ struct mdev_parent {
struct mdev_device {
struct device dev;
struct mdev_parent *parent;
- uuid_le uuid;
+ guid_t uuid;
void *driver_data;
struct kref ref;
struct list_head next;
@@ -58,7 +58,8 @@ void parent_remove_sysfs_files(struct mdev_parent *parent);
int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type);
void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);
-int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid);
+int mdev_device_create(struct kobject *kobj,
+ struct device *dev, const guid_t *uuid);
int mdev_device_remove(struct device *dev, bool force_remove);
#endif /* MDEV_PRIVATE_H */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index ce5dd219f2c8..5193a0e0ce5a 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -55,7 +55,7 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev,
const char *buf, size_t count)
{
char *str;
- uuid_le uuid;
+ guid_t uuid;
int ret;
if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1))
@@ -65,12 +65,12 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev,
if (!str)
return -ENOMEM;
- ret = uuid_le_to_bin(str, &uuid);
+ ret = guid_parse(str, &uuid);
kfree(str);
if (ret)
return ret;
- ret = mdev_device_create(kobj, dev, uuid);
+ ret = mdev_device_create(kobj, dev, &uuid);
if (ret)
return ret;
diff --git a/drivers/vfio/pci/trace.h b/drivers/vfio/pci/trace.h
index 228ccdb8d1c8..b2aa986ab9ed 100644
--- a/drivers/vfio/pci/trace.h
+++ b/drivers/vfio/pci/trace.h
@@ -1,13 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* VFIO PCI mmap/mmap_fault tracepoints
*
* Copyright (C) 2018 IBM Corp. All rights reserved.
* Author: Alexey Kardashevskiy <aik@ozlabs.ru>
- *
- * 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.
*/
#undef TRACE_SYSTEM
@@ -94,7 +90,7 @@ TRACE_EVENT(vfio_pci_npu2_mmap,
#endif /* _TRACE_VFIO_PCI_H */
#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH ../../drivers/vfio/pci
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index ff60bd1ea587..a25659b5a5d1 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -209,6 +209,57 @@ static bool vfio_pci_nointx(struct pci_dev *pdev)
return false;
}
+static void vfio_pci_probe_power_state(struct vfio_pci_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ u16 pmcsr;
+
+ if (!pdev->pm_cap)
+ return;
+
+ pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr);
+
+ vdev->needs_pm_restore = !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET);
+}
+
+/*
+ * pci_set_power_state() wrapper handling devices which perform a soft reset on
+ * D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev,
+ * restore when returned to D0. Saved separately from pci_saved_state for use
+ * by PM capability emulation and separately from pci_dev internal saved state
+ * to avoid it being overwritten and consumed around other resets.
+ */
+int vfio_pci_set_power_state(struct vfio_pci_device *vdev, pci_power_t state)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ bool needs_restore = false, needs_save = false;
+ int ret;
+
+ if (vdev->needs_pm_restore) {
+ if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) {
+ pci_save_state(pdev);
+ needs_save = true;
+ }
+
+ if (pdev->current_state >= PCI_D3hot && state <= PCI_D0)
+ needs_restore = true;
+ }
+
+ ret = pci_set_power_state(pdev, state);
+
+ if (!ret) {
+ /* D3 might be unsupported via quirk, skip unless in D3 */
+ if (needs_save && pdev->current_state >= PCI_D3hot) {
+ vdev->pm_save = pci_store_saved_state(pdev);
+ } else if (needs_restore) {
+ pci_load_and_free_saved_state(pdev, &vdev->pm_save);
+ pci_restore_state(pdev);
+ }
+ }
+
+ return ret;
+}
+
static int vfio_pci_enable(struct vfio_pci_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
@@ -216,7 +267,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
u16 cmd;
u8 msix_pos;
- pci_set_power_state(pdev, PCI_D0);
+ vfio_pci_set_power_state(vdev, PCI_D0);
/* Don't allow our initial saved state to include busmaster */
pci_clear_master(pdev);
@@ -407,7 +458,7 @@ out:
vfio_pci_try_bus_reset(vdev);
if (!disable_idle_d3)
- pci_set_power_state(pdev, PCI_D3hot);
+ vfio_pci_set_power_state(vdev, PCI_D3hot);
}
static void vfio_pci_release(void *device_data)
@@ -708,6 +759,7 @@ static long vfio_pci_ioctl(void *device_data,
{
void __iomem *io;
size_t size;
+ u16 orig_cmd;
info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
info.flags = 0;
@@ -723,15 +775,23 @@ static long vfio_pci_ioctl(void *device_data,
break;
}
- /* Is it really there? */
+ /*
+ * Is it really there? Enable memory decode for
+ * implicit access in pci_map_rom().
+ */
+ pci_read_config_word(pdev, PCI_COMMAND, &orig_cmd);
+ pci_write_config_word(pdev, PCI_COMMAND,
+ orig_cmd | PCI_COMMAND_MEMORY);
+
io = pci_map_rom(pdev, &size);
- if (!io || !size) {
+ if (io) {
+ info.flags = VFIO_REGION_INFO_FLAG_READ;
+ pci_unmap_rom(pdev, io);
+ } else {
info.size = 0;
- break;
}
- pci_unmap_rom(pdev, io);
- info.flags = VFIO_REGION_INFO_FLAG_READ;
+ pci_write_config_word(pdev, PCI_COMMAND, orig_cmd);
break;
}
case VFIO_PCI_VGA_REGION_INDEX:
@@ -1286,6 +1346,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
vfio_pci_set_vga_decode(vdev, false));
}
+ vfio_pci_probe_power_state(vdev);
+
if (!disable_idle_d3) {
/*
* pci-core sets the device power state to an unknown value at
@@ -1296,8 +1358,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* be able to get to D3. Therefore first do a D0 transition
* before going to D3.
*/
- pci_set_power_state(pdev, PCI_D0);
- pci_set_power_state(pdev, PCI_D3hot);
+ vfio_pci_set_power_state(vdev, PCI_D0);
+ vfio_pci_set_power_state(vdev, PCI_D3hot);
}
return ret;
@@ -1316,6 +1378,11 @@ static void vfio_pci_remove(struct pci_dev *pdev)
vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
kfree(vdev->region);
mutex_destroy(&vdev->ioeventfds_lock);
+
+ if (!disable_idle_d3)
+ vfio_pci_set_power_state(vdev, PCI_D0);
+
+ kfree(vdev->pm_save);
kfree(vdev);
if (vfio_pci_is_vga(pdev)) {
@@ -1324,9 +1391,6 @@ static void vfio_pci_remove(struct pci_dev *pdev)
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
}
-
- if (!disable_idle_d3)
- pci_set_power_state(pdev, PCI_D0);
}
static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
@@ -1551,7 +1615,7 @@ put_devs:
tmp->needs_reset = false;
if (tmp != vdev && !disable_idle_d3)
- pci_set_power_state(tmp->pdev, PCI_D3hot);
+ vfio_pci_set_power_state(tmp, PCI_D3hot);
}
vfio_device_put(devs.devices[i]);
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 423ea1f98441..e82b51114687 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -691,7 +691,7 @@ static int vfio_pm_config_write(struct vfio_pci_device *vdev, int pos,
break;
}
- pci_set_power_state(vdev->pdev, state);
+ vfio_pci_set_power_state(vdev, state);
}
return count;
diff --git a/drivers/vfio/pci/vfio_pci_nvlink2.c b/drivers/vfio/pci/vfio_pci_nvlink2.c
index 054a2cf9dd8e..32f695ffe128 100644
--- a/drivers/vfio/pci/vfio_pci_nvlink2.c
+++ b/drivers/vfio/pci/vfio_pci_nvlink2.c
@@ -1,14 +1,10 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* VFIO PCI NVIDIA Whitherspoon GPU support a.k.a. NVLink2.
*
* Copyright (C) 2018 IBM Corp. All rights reserved.
* Author: Alexey Kardashevskiy <aik@ozlabs.ru>
*
- * 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.
- *
* Register an on-GPU RAM region for cacheable access.
*
* Derived from original vfio_pci_igd.c:
@@ -178,11 +174,11 @@ static int vfio_pci_nvgpu_add_capability(struct vfio_pci_device *vdev,
struct vfio_pci_region *region, struct vfio_info_cap *caps)
{
struct vfio_pci_nvgpu_data *data = region->data;
- struct vfio_region_info_cap_nvlink2_ssatgt cap = { 0 };
-
- cap.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
- cap.header.version = 1;
- cap.tgt = data->gpu_tgt;
+ struct vfio_region_info_cap_nvlink2_ssatgt cap = {
+ .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+ .header.version = 1,
+ .tgt = data->gpu_tgt
+ };
return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
}
@@ -365,18 +361,18 @@ static int vfio_pci_npu2_add_capability(struct vfio_pci_device *vdev,
struct vfio_pci_region *region, struct vfio_info_cap *caps)
{
struct vfio_pci_npu2_data *data = region->data;
- struct vfio_region_info_cap_nvlink2_ssatgt captgt = { 0 };
- struct vfio_region_info_cap_nvlink2_lnkspd capspd = { 0 };
+ struct vfio_region_info_cap_nvlink2_ssatgt captgt = {
+ .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+ .header.version = 1,
+ .tgt = data->gpu_tgt
+ };
+ struct vfio_region_info_cap_nvlink2_lnkspd capspd = {
+ .header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD,
+ .header.version = 1,
+ .link_speed = data->link_speed
+ };
int ret;
- captgt.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
- captgt.header.version = 1;
- captgt.tgt = data->gpu_tgt;
-
- capspd.header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD;
- capspd.header.version = 1;
- capspd.link_speed = data->link_speed;
-
ret = vfio_info_add_capability(caps, &captgt.header, sizeof(captgt));
if (ret)
return ret;
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 8c0009f00818..1812cf22fc4f 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -114,7 +114,9 @@ struct vfio_pci_device {
bool has_vga;
bool needs_reset;
bool nointx;
+ bool needs_pm_restore;
struct pci_saved_state *pci_saved_state;
+ struct pci_saved_state *pm_save;
struct vfio_pci_reflck *reflck;
int refcnt;
int ioeventfds_nr;
@@ -161,6 +163,10 @@ extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
unsigned int type, unsigned int subtype,
const struct vfio_pci_regops *ops,
size_t size, u32 flags, void *data);
+
+extern int vfio_pci_set_power_state(struct vfio_pci_device *vdev,
+ pci_power_t state);
+
#ifdef CONFIG_VFIO_PCI_IGD
extern int vfio_pci_igd_init(struct vfio_pci_device *vdev);
#else
diff --git a/drivers/vfio/platform/reset/Makefile b/drivers/vfio/platform/reset/Makefile
index 57abd4f0ac5b..7294c5ea122e 100644
--- a/drivers/vfio/platform/reset/Makefile
+++ b/drivers/vfio/platform/reset/Makefile
@@ -2,8 +2,6 @@
vfio-platform-calxedaxgmac-y := vfio_platform_calxedaxgmac.o
vfio-platform-amdxgbe-y := vfio_platform_amdxgbe.o
-ccflags-y += -Idrivers/vfio/platform
-
obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
obj-$(CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET) += vfio_platform_bcmflexrm.o
diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
index bcd419cfd79c..3ddb2704221d 100644
--- a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
+++ b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
@@ -25,7 +25,7 @@
#include <uapi/linux/mdio.h>
#include <linux/delay.h>
-#include "vfio_platform_private.h"
+#include "../vfio_platform_private.h"
#define DMA_MR 0x3000
#define MAC_VR 0x0110
diff --git a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
index d45c3be71198..16165a62b86d 100644
--- a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
+++ b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
@@ -23,7 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include "vfio_platform_private.h"
+#include "../vfio_platform_private.h"
/* FlexRM configuration */
#define RING_REGS_SIZE 0x10000
diff --git a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
index 49e5df6e8f29..e0356de5df54 100644
--- a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
+++ b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <linux/io.h>
-#include "vfio_platform_private.h"
+#include "../vfio_platform_private.h"
#define DRIVER_VERSION "0.1"
#define DRIVER_AUTHOR "Eric Auger <eric.auger@linaro.org>"
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 64833879f75d..a3030cdf3c18 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -2219,12 +2219,12 @@ static int __init vfio_init(void)
vfio.class->devnode = vfio_devnode;
- ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio");
+ ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK + 1, "vfio");
if (ret)
goto err_alloc_chrdev;
cdev_init(&vfio.group_cdev, &vfio_group_fops);
- ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK);
+ ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK + 1);
if (ret)
goto err_cdev_add;
@@ -2236,7 +2236,7 @@ static int __init vfio_init(void)
return 0;
err_cdev_add:
- unregister_chrdev_region(vfio.group_devt, MINORMASK);
+ unregister_chrdev_region(vfio.group_devt, MINORMASK + 1);
err_alloc_chrdev:
class_destroy(vfio.class);
vfio.class = NULL;
@@ -2254,7 +2254,7 @@ static void __exit vfio_cleanup(void)
#endif
idr_destroy(&vfio.group_idr);
cdev_del(&vfio.group_cdev);
- unregister_chrdev_region(vfio.group_devt, MINORMASK);
+ unregister_chrdev_region(vfio.group_devt, MINORMASK + 1);
class_destroy(vfio.class);
vfio.class = NULL;
misc_deregister(&vfio_dev);
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index c424913324e3..8dbb270998f4 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -1235,7 +1235,8 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container,
}
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
- table_group->ops->unset_window(table_group, i);
+ if (container->tables[i])
+ table_group->ops->unset_window(table_group, i);
table_group->ops->release_ownership(table_group);
}
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 7651cfb14836..73652e21efec 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -878,7 +878,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
return -EINVAL;
if (!unmap->size || unmap->size & mask)
return -EINVAL;
- if (unmap->iova + unmap->size < unmap->iova ||
+ if (unmap->iova + unmap->size - 1 < unmap->iova ||
unmap->size > SIZE_MAX)
return -EINVAL;
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 36f3d0f49e60..df51a35cf537 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
if (nvq->done_idx > VHOST_NET_BATCH)
vhost_net_signal_used(nvq);
if (unlikely(vq_log))
- vhost_log_write(vq, vq_log, log, vhost_len);
+ vhost_log_write(vq, vq_log, log, vhost_len,
+ vq->iov, in);
total_len += vhost_len;
if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
vhost_poll_queue(&vq->poll);
@@ -1336,7 +1337,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
n->vqs[i].rx_ring = NULL;
vhost_net_buf_init(&n->vqs[i].rxq);
}
- vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
+ vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
+ UIO_MAXIOV + VHOST_NET_BATCH);
vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 8e10ab436d1f..23593cb23dd0 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1127,16 +1127,18 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
struct vhost_virtqueue *vq,
struct vhost_scsi_ctx *vc)
{
- struct virtio_scsi_ctrl_tmf_resp __user *resp;
struct virtio_scsi_ctrl_tmf_resp rsp;
+ struct iov_iter iov_iter;
int ret;
pr_debug("%s\n", __func__);
memset(&rsp, 0, sizeof(rsp));
rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
- resp = vq->iov[vc->out].iov_base;
- ret = __copy_to_user(resp, &rsp, sizeof(rsp));
- if (!ret)
+
+ iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+ ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+ if (likely(ret == sizeof(rsp)))
vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
else
pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n");
@@ -1147,16 +1149,18 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs,
struct vhost_virtqueue *vq,
struct vhost_scsi_ctx *vc)
{
- struct virtio_scsi_ctrl_an_resp __user *resp;
struct virtio_scsi_ctrl_an_resp rsp;
+ struct iov_iter iov_iter;
int ret;
pr_debug("%s\n", __func__);
memset(&rsp, 0, sizeof(rsp)); /* event_actual = 0 */
rsp.response = VIRTIO_SCSI_S_OK;
- resp = vq->iov[vc->out].iov_base;
- ret = __copy_to_user(resp, &rsp, sizeof(rsp));
- if (!ret)
+
+ iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+ ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+ if (likely(ret == sizeof(rsp)))
vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
else
pr_err("Faulted on virtio_scsi_ctrl_an_resp\n");
@@ -1623,7 +1627,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
vqs[i] = &vs->vqs[i].vq;
vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
}
- vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
+ vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
vhost_scsi_init_inflight(vs, NULL);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9f7942cbcbb2..a2e5dc7716e2 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
vq->indirect = kmalloc_array(UIO_MAXIOV,
sizeof(*vq->indirect),
GFP_KERNEL);
- vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
+ vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log),
GFP_KERNEL);
- vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
+ vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads),
GFP_KERNEL);
if (!vq->indirect || !vq->log || !vq->heads)
goto err_nomem;
@@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
}
void vhost_dev_init(struct vhost_dev *dev,
- struct vhost_virtqueue **vqs, int nvqs)
+ struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
{
struct vhost_virtqueue *vq;
int i;
@@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev,
dev->iotlb = NULL;
dev->mm = NULL;
dev->worker = NULL;
+ dev->iov_limit = iov_limit;
init_llist_head(&dev->work_list);
init_waitqueue_head(&dev->wait);
INIT_LIST_HEAD(&dev->read_list);
@@ -1034,8 +1035,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
int type, ret;
ret = copy_from_iter(&type, sizeof(type), from);
- if (ret != sizeof(type))
+ if (ret != sizeof(type)) {
+ ret = -EINVAL;
goto done;
+ }
switch (type) {
case VHOST_IOTLB_MSG:
@@ -1054,8 +1057,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
iov_iter_advance(from, offset);
ret = copy_from_iter(&msg, sizeof(msg), from);
- if (ret != sizeof(msg))
+ if (ret != sizeof(msg)) {
+ ret = -EINVAL;
goto done;
+ }
if (vhost_process_iotlb_msg(dev, &msg)) {
ret = -EFAULT;
goto done;
@@ -1733,13 +1738,87 @@ static int log_write(void __user *log_base,
return r;
}
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+ struct vhost_umem *umem = vq->umem;
+ struct vhost_umem_node *u;
+ u64 start, end, l, min;
+ int r;
+ bool hit = false;
+
+ while (len) {
+ min = len;
+ /* More than one GPAs can be mapped into a single HVA. So
+ * iterate all possible umems here to be safe.
+ */
+ list_for_each_entry(u, &umem->umem_list, link) {
+ if (u->userspace_addr > hva - 1 + len ||
+ u->userspace_addr - 1 + u->size < hva)
+ continue;
+ start = max(u->userspace_addr, hva);
+ end = min(u->userspace_addr - 1 + u->size,
+ hva - 1 + len);
+ l = end - start + 1;
+ r = log_write(vq->log_base,
+ u->start + start - u->userspace_addr,
+ l);
+ if (r < 0)
+ return r;
+ hit = true;
+ min = min(l, min);
+ }
+
+ if (!hit)
+ return -EFAULT;
+
+ len -= min;
+ hva += min;
+ }
+
+ return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+ struct iovec iov[64];
+ int i, ret;
+
+ if (!vq->iotlb)
+ return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+ ret = translate_desc(vq, (uintptr_t)vq->used + used_offset,
+ len, iov, 64, VHOST_ACCESS_WO);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ret; i++) {
+ ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+ iov[i].iov_len);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
- unsigned int log_num, u64 len)
+ unsigned int log_num, u64 len, struct iovec *iov, int count)
{
int i, r;
/* Make sure data written is seen before log. */
smp_wmb();
+
+ if (vq->iotlb) {
+ for (i = 0; i < count; i++) {
+ r = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+ iov[i].iov_len);
+ if (r < 0)
+ return r;
+ }
+ return 0;
+ }
+
for (i = 0; i < log_num; ++i) {
u64 l = min(log[i].len, len);
r = log_write(vq->log_base, log[i].addr, l);
@@ -1769,9 +1848,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
smp_wmb();
/* Log used flag write. */
used = &vq->used->flags;
- log_write(vq->log_base, vq->log_addr +
- (used - (void __user *)vq->used),
- sizeof vq->used->flags);
+ log_used(vq, (used - (void __user *)vq->used),
+ sizeof vq->used->flags);
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
@@ -1789,9 +1867,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
smp_wmb();
/* Log avail event write */
used = vhost_avail_event(vq);
- log_write(vq->log_base, vq->log_addr +
- (used - (void __user *)vq->used),
- sizeof *vhost_avail_event(vq));
+ log_used(vq, (used - (void __user *)vq->used),
+ sizeof *vhost_avail_event(vq));
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
@@ -2191,10 +2268,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
/* Make sure data is seen before log. */
smp_wmb();
/* Log used ring entry write. */
- log_write(vq->log_base,
- vq->log_addr +
- ((void __user *)used - (void __user *)vq->used),
- count * sizeof *used);
+ log_used(vq, ((void __user *)used - (void __user *)vq->used),
+ count * sizeof *used);
}
old = vq->last_used_idx;
new = (vq->last_used_idx += count);
@@ -2236,9 +2311,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
/* Make sure used idx is seen before log. */
smp_wmb();
/* Log used index update. */
- log_write(vq->log_base,
- vq->log_addr + offsetof(struct vring_used, idx),
- sizeof vq->used->idx);
+ log_used(vq, offsetof(struct vring_used, idx),
+ sizeof vq->used->idx);
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 466ef7542291..9490e7ddb340 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -170,9 +170,11 @@ struct vhost_dev {
struct list_head read_list;
struct list_head pending_list;
wait_queue_head_t wait;
+ int iov_limit;
};
-void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
+void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
+ int nvqs, int iov_limit);
long vhost_dev_set_owner(struct vhost_dev *dev);
bool vhost_dev_has_owner(struct vhost_dev *dev);
long vhost_dev_check_owner(struct vhost_dev *);
@@ -205,7 +207,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
- unsigned int log_num, u64 len);
+ unsigned int log_num, u64 len,
+ struct iovec *iov, int count);
int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index bc42d38ae031..bb5fc0e9fbc2 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
- vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
+ vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
file->private_data = vsock;
spin_lock_init(&vsock->send_pkt_list_lock);
@@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
hash_del_rcu(&vsock->hash);
vsock->guest_cid = guest_cid;
- hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
+ hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid);
mutex_unlock(&vhost_vsock_mutex);
return 0;
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 6d8dc2c77520..51e0c4be08df 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -174,7 +174,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
return -ENODEV;
}
for_each_child_of_node(nproot, np) {
- if (!of_node_cmp(np->name, name)) {
+ if (of_node_name_eq(np, name)) {
of_property_read_u32(np, "marvell,88pm860x-iset",
&iset);
data->iset = PM8606_WLED_CURRENT(iset);
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index f9ef0673a083..feb90764a811 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -30,6 +30,7 @@ struct pwm_bl_data {
struct device *dev;
unsigned int lth_brightness;
unsigned int *levels;
+ bool enabled;
struct regulator *power_supply;
struct gpio_desc *enable_gpio;
unsigned int scale;
@@ -50,7 +51,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
int err;
pwm_get_state(pb->pwm, &state);
- if (state.enabled)
+ if (pb->enabled)
return;
err = regulator_enable(pb->power_supply);
@@ -65,6 +66,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
if (pb->enable_gpio)
gpiod_set_value_cansleep(pb->enable_gpio, 1);
+
+ pb->enabled = true;
}
static void pwm_backlight_power_off(struct pwm_bl_data *pb)
@@ -72,7 +75,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
struct pwm_state state;
pwm_get_state(pb->pwm, &state);
- if (!state.enabled)
+ if (!pb->enabled)
return;
if (pb->enable_gpio)
@@ -86,6 +89,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
pwm_apply_state(pb->pwm, &state);
regulator_disable(pb->power_supply);
+ pb->enabled = false;
}
static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
@@ -269,6 +273,16 @@ static int pwm_backlight_parse_dt(struct device *dev,
memset(data, 0, sizeof(*data));
/*
+ * These values are optional and set as 0 by default, the out values
+ * are modified only if a valid u32 value can be decoded.
+ */
+ of_property_read_u32(node, "post-pwm-on-delay-ms",
+ &data->post_pwm_on_delay);
+ of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
+
+ data->enable_gpio = -EINVAL;
+
+ /*
* Determine the number of brightness levels, if this property is not
* set a default table of brightness levels will be used.
*/
@@ -380,15 +394,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
data->max_brightness--;
}
- /*
- * These values are optional and set as 0 by default, the out values
- * are modified only if a valid u32 value can be decoded.
- */
- of_property_read_u32(node, "post-pwm-on-delay-ms",
- &data->post_pwm_on_delay);
- of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
-
- data->enable_gpio = -EINVAL;
return 0;
}
@@ -483,6 +488,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->check_fb = data->check_fb;
pb->exit = data->exit;
pb->dev = &pdev->dev;
+ pb->enabled = false;
pb->post_pwm_on_delay = data->post_pwm_on_delay;
pb->pwm_off_delay = data->pwm_off_delay;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 09731b2f6815..c6b3bdbbdbc9 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
static void vgacon_restore_screen(struct vc_data *c)
{
+ c->vc_origin = c->vc_visible_origin;
vgacon_scrollback_cur->save = 0;
if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
@@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
int start, end, count, soff;
if (!lines) {
- c->vc_visible_origin = c->vc_origin;
- vga_set_mem_top(c);
+ vgacon_restore_screen(c);
return;
}
@@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
if (!vgacon_scrollback_cur->save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
+ c->vc_origin = (unsigned long)c->vc_screenbuf;
vgacon_scrollback_cur->save = 1;
}
@@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
int copysize;
int diff = c->vc_rows - count;
- void *d = (void *) c->vc_origin;
+ void *d = (void *) c->vc_visible_origin;
void *s = (void *) c->vc_screenbuf;
count *= c->vc_size_row;
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index ae7712c9687a..58a9590c9db6 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -536,7 +536,7 @@ config FB_IMSTT
bool "IMS Twin Turbo display support"
depends on (FB = y) && PCI
select FB_CFB_IMAGEBLIT
- select FB_MACMODES if PPC
+ select FB_MACMODES if PPC_PMAC
help
The IMS Twin Turbo is a PCI-based frame buffer card bundled with
many Macintosh and compatible computers.
diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c
index 9cb0ef7ac29e..7af8db28bb80 100644
--- a/drivers/video/fbdev/controlfb.c
+++ b/drivers/video/fbdev/controlfb.c
@@ -411,35 +411,23 @@ static int __init init_control(struct fb_info_control *p)
full = p->total_vram == 0x400000;
/* Try to pick a video mode out of NVRAM if we have one. */
-#ifdef CONFIG_NVRAM
- if (default_cmode == CMODE_NVRAM) {
+ cmode = default_cmode;
+ if (IS_REACHABLE(CONFIG_NVRAM) && cmode == CMODE_NVRAM)
cmode = nvram_read_byte(NV_CMODE);
- if(cmode < CMODE_8 || cmode > CMODE_32)
- cmode = CMODE_8;
- } else
-#endif
- cmode=default_cmode;
-#ifdef CONFIG_NVRAM
- if (default_vmode == VMODE_NVRAM) {
+ if (cmode < CMODE_8 || cmode > CMODE_32)
+ cmode = CMODE_8;
+
+ vmode = default_vmode;
+ if (IS_REACHABLE(CONFIG_NVRAM) && vmode == VMODE_NVRAM)
vmode = nvram_read_byte(NV_VMODE);
- if (vmode < 1 || vmode > VMODE_MAX ||
- control_mac_modes[vmode - 1].m[full] < cmode) {
- sense = read_control_sense(p);
- printk("Monitor sense value = 0x%x, ", sense);
- vmode = mac_map_monitor_sense(sense);
- if (control_mac_modes[vmode - 1].m[full] < cmode)
- vmode = VMODE_640_480_60;
- }
- } else
-#endif
- {
- vmode=default_vmode;
- if (control_mac_modes[vmode - 1].m[full] < cmode) {
- if (cmode > CMODE_8)
- cmode--;
- else
- vmode = VMODE_640_480_60;
- }
+ if (vmode < 1 || vmode > VMODE_MAX ||
+ control_mac_modes[vmode - 1].m[full] < cmode) {
+ sense = read_control_sense(p);
+ printk(KERN_CONT "Monitor sense value = 0x%x, ", sense);
+ vmode = mac_map_monitor_sense(sense);
+ if (control_mac_modes[vmode - 1].m[full] < 0)
+ vmode = VMODE_640_480_60;
+ cmode = min(cmode, control_mac_modes[vmode - 1].m[full]);
}
/* Initialize info structure */
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 8976190b6c1f..bfa1360ec750 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -510,6 +510,13 @@ static int __init fb_console_setup(char *this_opt)
continue;
}
#endif
+
+ if (!strncmp(options, "logo-pos:", 9)) {
+ options += 9;
+ if (!strcmp(options, "center"))
+ fb_center_logo = true;
+ continue;
+ }
}
return 1;
}
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 558ed2ed3124..cb43a2258c51 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -53,6 +53,9 @@ EXPORT_SYMBOL(registered_fb);
int num_registered_fb __read_mostly;
EXPORT_SYMBOL(num_registered_fb);
+bool fb_center_logo __read_mostly;
+EXPORT_SYMBOL(fb_center_logo);
+
static struct fb_info *get_fb_info(unsigned int idx)
{
struct fb_info *fb_info;
@@ -506,8 +509,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
fb_set_logo(info, logo, logo_new, fb_logo.depth);
}
-#ifdef CONFIG_FB_LOGO_CENTER
- {
+ if (fb_center_logo) {
int xres = info->var.xres;
int yres = info->var.yres;
@@ -520,11 +522,11 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
--n;
image.dx = (xres - n * (logo->width + 8) - 8) / 2;
image.dy = y ?: (yres - logo->height) / 2;
+ } else {
+ image.dx = 0;
+ image.dy = y;
}
-#else
- image.dx = 0;
- image.dy = y;
-#endif
+
image.width = logo->width;
image.height = logo->height;
@@ -684,9 +686,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
}
height = fb_logo.logo->height;
-#ifdef CONFIG_FB_LOGO_CENTER
- height += (yres - fb_logo.logo->height) / 2;
-#endif
+ if (fb_center_logo)
+ height += (yres - fb_logo.logo->height) / 2;
return fb_prepare_extra_logos(info, height, yres);
}
diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
index a74096c53cb5..43f2a4816860 100644
--- a/drivers/video/fbdev/da8xx-fb.c
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -1446,9 +1446,9 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
- par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE,
- &par->p_palette_base,
- GFP_KERNEL | GFP_DMA);
+ par->v_palette_base = dma_alloc_coherent(NULL, PALETTE_SIZE,
+ &par->p_palette_base,
+ GFP_KERNEL | GFP_DMA);
if (!par->v_palette_base) {
dev_err(&device->dev,
"GLCD: kmalloc for palette buffer failed\n");
diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c
index 901ca4ed10e9..5d9670daf60e 100644
--- a/drivers/video/fbdev/imsttfb.c
+++ b/drivers/video/fbdev/imsttfb.c
@@ -30,9 +30,8 @@
#include <asm/io.h>
#include <linux/uaccess.h>
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC_PMAC)
#include <linux/nvram.h>
-#include <asm/prom.h>
#include "macmodes.h"
#endif
@@ -327,14 +326,13 @@ enum {
TVP = 1
};
-#define USE_NV_MODES 1
#define INIT_BPP 8
#define INIT_XRES 640
#define INIT_YRES 480
static int inverse = 0;
static char fontname[40] __initdata = { 0 };
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC_PMAC)
static signed char init_vmode = -1, init_cmode = -1;
#endif
@@ -1390,8 +1388,8 @@ static void init_imstt(struct fb_info *info)
}
}
-#if USE_NV_MODES && defined(CONFIG_PPC32)
- {
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
+ if (IS_REACHABLE(CONFIG_NVRAM) && machine_is(powermac)) {
int vmode = init_vmode, cmode = init_cmode;
if (vmode == -1) {
@@ -1409,12 +1407,13 @@ static void init_imstt(struct fb_info *info)
info->var.yres = info->var.yres_virtual = INIT_YRES;
info->var.bits_per_pixel = INIT_BPP;
}
- }
-#else
- info->var.xres = info->var.xres_virtual = INIT_XRES;
- info->var.yres = info->var.yres_virtual = INIT_YRES;
- info->var.bits_per_pixel = INIT_BPP;
+ } else
#endif
+ {
+ info->var.xres = info->var.xres_virtual = INIT_XRES;
+ info->var.yres = info->var.yres_virtual = INIT_YRES;
+ info->var.bits_per_pixel = INIT_BPP;
+ }
if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
|| !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
@@ -1565,7 +1564,7 @@ imsttfb_setup(char *options)
inverse = 1;
fb_invert_cmaps();
}
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC_PMAC)
else if (!strncmp(this_opt, "vmode:", 6)) {
int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
index 838869c6490c..d11b5e6210ed 100644
--- a/drivers/video/fbdev/matrox/matroxfb_base.c
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
@@ -111,12 +111,12 @@
#include "matroxfb_g450.h"
#include <linux/matroxfb.h>
#include <linux/interrupt.h>
+#include <linux/nvram.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/machdep.h>
-unsigned char nvram_read_byte(int);
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
#endif
@@ -1872,10 +1872,11 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
#ifndef MODULE
if (machine_is(powermac)) {
struct fb_var_screeninfo var;
+
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
-#ifdef CONFIG_NVRAM
- if (default_cmode == CMODE_NVRAM)
+#if defined(CONFIG_PPC32)
+ if (IS_REACHABLE(CONFIG_NVRAM) && default_cmode == CMODE_NVRAM)
default_cmode = nvram_read_byte(NV_CMODE);
#endif
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c
index 31f769d67195..057d3cdef92e 100644
--- a/drivers/video/fbdev/offb.c
+++ b/drivers/video/fbdev/offb.c
@@ -318,28 +318,28 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
}
static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
- const char *name, unsigned long address)
+ unsigned long address)
{
struct offb_par *par = (struct offb_par *) info->par;
- if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+ if (of_node_name_prefix(dp, "ATY,Rage128")) {
par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
if (par->cmap_adr)
par->cmap_type = cmap_r128;
- } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
- || !strncmp(name, "ATY,RageM3p12A", 14))) {
+ } else if (of_node_name_prefix(dp, "ATY,RageM3pA") ||
+ of_node_name_prefix(dp, "ATY,RageM3p12A")) {
par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
if (par->cmap_adr)
par->cmap_type = cmap_M3A;
- } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+ } else if (of_node_name_prefix(dp, "ATY,RageM3pB")) {
par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
if (par->cmap_adr)
par->cmap_type = cmap_M3B;
- } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+ } else if (of_node_name_prefix(dp, "ATY,Rage6")) {
par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
if (par->cmap_adr)
par->cmap_type = cmap_radeon;
- } else if (!strncmp(name, "ATY,", 4)) {
+ } else if (of_node_name_prefix(dp, "ATY,")) {
unsigned long base = address & 0xff000000UL;
par->cmap_adr =
ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
@@ -350,7 +350,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
if (par->cmap_adr)
par->cmap_type = cmap_gxt2000;
- } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+ } else if (of_node_name_prefix(dp, "vga,Display-")) {
/* Look for AVIVO initialized by SLOF */
struct device_node *pciparent = of_get_parent(dp);
const u32 *vid, *did;
@@ -438,7 +438,7 @@ static void __init offb_init_fb(const char *name,
par->cmap_type = cmap_unknown;
if (depth == 8)
- offb_init_palette_hacks(info, dp, name, address);
+ offb_init_palette_hacks(info, dp, address);
else
fix->visual = FB_VISUAL_TRUECOLOR;
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
index 53f93616c671..8e23160ec59f 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
int r = 0;
+ memset(&p, 0, sizeof(p));
+
switch (cmd) {
case OMAPFB_SYNC_GFX:
DBG("ioctl SYNC_GFX\n");
diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c
index bf6b7fb83cf4..76f299375a00 100644
--- a/drivers/video/fbdev/platinumfb.c
+++ b/drivers/video/fbdev/platinumfb.c
@@ -345,23 +345,18 @@ static int platinum_init_fb(struct fb_info *info)
sense = read_platinum_sense(pinfo);
printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense);
- if (default_vmode == VMODE_NVRAM) {
-#ifdef CONFIG_NVRAM
+
+ if (IS_REACHABLE(CONFIG_NVRAM) && default_vmode == VMODE_NVRAM)
default_vmode = nvram_read_byte(NV_VMODE);
- if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
- !platinum_reg_init[default_vmode-1])
-#endif
- default_vmode = VMODE_CHOOSE;
- }
- if (default_vmode == VMODE_CHOOSE) {
+ if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
+ !platinum_reg_init[default_vmode - 1]) {
default_vmode = mac_map_monitor_sense(sense);
+ if (!platinum_reg_init[default_vmode - 1])
+ default_vmode = VMODE_640_480_60;
}
- if (default_vmode <= 0 || default_vmode > VMODE_MAX)
- default_vmode = VMODE_640_480_60;
-#ifdef CONFIG_NVRAM
- if (default_cmode == CMODE_NVRAM)
+
+ if (IS_REACHABLE(CONFIG_NVRAM) && default_cmode == CMODE_NVRAM)
default_cmode = nvram_read_byte(NV_CMODE);
-#endif
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
default_cmode = CMODE_8;
/*
diff --git a/drivers/video/fbdev/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c
index d51c3a8009cb..e04fde9c1fcd 100644
--- a/drivers/video/fbdev/valkyriefb.c
+++ b/drivers/video/fbdev/valkyriefb.c
@@ -63,15 +63,8 @@
#include "macmodes.h"
#include "valkyriefb.h"
-#ifdef CONFIG_MAC
-/* We don't yet have functions to read the PRAM... perhaps we can
- adapt them from the PPC code? */
-static int default_vmode = VMODE_CHOOSE;
-static int default_cmode = CMODE_8;
-#else
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
-#endif
struct fb_par_valkyrie {
int vmode, cmode;
@@ -283,24 +276,21 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p)
printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense);
/* Try to pick a video mode out of NVRAM if we have one. */
-#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
- if (default_vmode == VMODE_NVRAM) {
+#ifdef CONFIG_PPC_PMAC
+ if (IS_REACHABLE(CONFIG_NVRAM) && default_vmode == VMODE_NVRAM)
default_vmode = nvram_read_byte(NV_VMODE);
- if (default_vmode <= 0
- || default_vmode > VMODE_MAX
- || !valkyrie_reg_init[default_vmode - 1])
- default_vmode = VMODE_CHOOSE;
- }
#endif
- if (default_vmode == VMODE_CHOOSE)
+ if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
+ !valkyrie_reg_init[default_vmode - 1]) {
default_vmode = mac_map_monitor_sense(p->sense);
- if (!valkyrie_reg_init[default_vmode - 1])
- default_vmode = VMODE_640_480_67;
-#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
- if (default_cmode == CMODE_NVRAM)
+ if (!valkyrie_reg_init[default_vmode - 1])
+ default_vmode = VMODE_640_480_67;
+ }
+
+#ifdef CONFIG_PPC_PMAC
+ if (IS_REACHABLE(CONFIG_NVRAM) && default_cmode == CMODE_NVRAM)
default_cmode = nvram_read_byte(NV_CMODE);
#endif
-
/*
* Reduce the pixel size if we don't have enough VRAM or bandwidth.
*/
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 1e972c4e88b1..d1f6196c8b9a 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -10,15 +10,6 @@ menuconfig LOGO
if LOGO
-config FB_LOGO_CENTER
- bool "Center the logo"
- depends on FB=y
- help
- When this option is selected, the bootup logo is centered both
- horizontally and vertically. If more than one logo is displayed
- due to multiple CPUs, the collected line of logos is centered
- as a whole.
-
config FB_LOGO_EXTRA
bool
depends on FB=y
diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c
index 1475ed5ffcde..df7d09409efe 100644
--- a/drivers/virt/vboxguest/vboxguest_core.c
+++ b/drivers/virt/vboxguest/vboxguest_core.c
@@ -1484,8 +1484,8 @@ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)
#ifdef CONFIG_COMPAT
case VBG_IOCTL_HGCM_CALL_32(0):
f32bit = true;
- /* Fall through */
#endif
+ /* Fall through */
case VBG_IOCTL_HGCM_CALL(0):
return vbg_ioctl_hgcm_call(gdev, session, f32bit, data);
case VBG_IOCTL_LOG(0):
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 728ecd1eea30..fb12fe205f86 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -61,6 +61,10 @@ enum virtio_balloon_vq {
VIRTIO_BALLOON_VQ_MAX
};
+enum virtio_balloon_config_read {
+ VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0,
+};
+
struct virtio_balloon {
struct virtio_device *vdev;
struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq;
@@ -77,14 +81,20 @@ struct virtio_balloon {
/* Prevent updating balloon when it is being canceled. */
spinlock_t stop_update_lock;
bool stop_update;
+ /* Bitmap to indicate if reading the related config fields are needed */
+ unsigned long config_read_bitmap;
/* The list of allocated free pages, waiting to be given back to mm */
struct list_head free_page_list;
spinlock_t free_page_list_lock;
/* The number of free page blocks on the above list */
unsigned long num_free_page_blocks;
- /* The cmd id received from host */
- u32 cmd_id_received;
+ /*
+ * The cmd id received from host.
+ * Read it via virtio_balloon_cmd_id_received to get the latest value
+ * sent from host.
+ */
+ u32 cmd_id_received_cache;
/* The cmd id that is actively in use */
__virtio32 cmd_id_active;
/* Buffer to store the stop sign */
@@ -390,37 +400,31 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
return num_returned;
}
+static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
+{
+ if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
+ return;
+
+ /* No need to queue the work if the bit was already set. */
+ if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+ &vb->config_read_bitmap))
+ return;
+
+ queue_work(vb->balloon_wq, &vb->report_free_page_work);
+}
+
static void virtballoon_changed(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
unsigned long flags;
- s64 diff = towards_target(vb);
-
- if (diff) {
- spin_lock_irqsave(&vb->stop_update_lock, flags);
- if (!vb->stop_update)
- queue_work(system_freezable_wq,
- &vb->update_balloon_size_work);
- spin_unlock_irqrestore(&vb->stop_update_lock, flags);
- }
- if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
- virtio_cread(vdev, struct virtio_balloon_config,
- free_page_report_cmd_id, &vb->cmd_id_received);
- if (vb->cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
- /* Pass ULONG_MAX to give back all the free pages */
- return_free_pages_to_mm(vb, ULONG_MAX);
- } else if (vb->cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
- vb->cmd_id_received !=
- virtio32_to_cpu(vdev, vb->cmd_id_active)) {
- spin_lock_irqsave(&vb->stop_update_lock, flags);
- if (!vb->stop_update) {
- queue_work(vb->balloon_wq,
- &vb->report_free_page_work);
- }
- spin_unlock_irqrestore(&vb->stop_update_lock, flags);
- }
+ spin_lock_irqsave(&vb->stop_update_lock, flags);
+ if (!vb->stop_update) {
+ queue_work(system_freezable_wq,
+ &vb->update_balloon_size_work);
+ virtio_balloon_queue_free_page_work(vb);
}
+ spin_unlock_irqrestore(&vb->stop_update_lock, flags);
}
static void update_balloon_size(struct virtio_balloon *vb)
@@ -527,6 +531,17 @@ static int init_vqs(struct virtio_balloon *vb)
return 0;
}
+static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
+{
+ if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+ &vb->config_read_bitmap))
+ virtio_cread(vb->vdev, struct virtio_balloon_config,
+ free_page_report_cmd_id,
+ &vb->cmd_id_received_cache);
+
+ return vb->cmd_id_received_cache;
+}
+
static int send_cmd_id_start(struct virtio_balloon *vb)
{
struct scatterlist sg;
@@ -537,7 +552,8 @@ static int send_cmd_id_start(struct virtio_balloon *vb)
while (virtqueue_get_buf(vq, &unused))
;
- vb->cmd_id_active = cpu_to_virtio32(vb->vdev, vb->cmd_id_received);
+ vb->cmd_id_active = virtio32_to_cpu(vb->vdev,
+ virtio_balloon_cmd_id_received(vb));
sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active));
err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL);
if (!err)
@@ -620,7 +636,8 @@ static int send_free_pages(struct virtio_balloon *vb)
* stop the reporting.
*/
cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active);
- if (cmd_id_active != vb->cmd_id_received)
+ if (unlikely(cmd_id_active !=
+ virtio_balloon_cmd_id_received(vb)))
break;
/*
@@ -637,11 +654,9 @@ static int send_free_pages(struct virtio_balloon *vb)
return 0;
}
-static void report_free_page_func(struct work_struct *work)
+static void virtio_balloon_report_free_page(struct virtio_balloon *vb)
{
int err;
- struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
- report_free_page_work);
struct device *dev = &vb->vdev->dev;
/* Start by sending the received cmd id to host with an outbuf. */
@@ -659,6 +674,23 @@ static void report_free_page_func(struct work_struct *work)
dev_err(dev, "Failed to send a stop id, err = %d\n", err);
}
+static void report_free_page_func(struct work_struct *work)
+{
+ struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
+ report_free_page_work);
+ u32 cmd_id_received;
+
+ cmd_id_received = virtio_balloon_cmd_id_received(vb);
+ if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
+ /* Pass ULONG_MAX to give back all the free pages */
+ return_free_pages_to_mm(vb, ULONG_MAX);
+ } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
+ cmd_id_received !=
+ virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) {
+ virtio_balloon_report_free_page(vb);
+ }
+}
+
#ifdef CONFIG_BALLOON_COMPACTION
/*
* virtballoon_migratepage - perform the balloon page migration on behalf of
@@ -885,7 +917,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
goto out_del_vqs;
}
INIT_WORK(&vb->report_free_page_work, report_free_page_func);
- vb->cmd_id_received = VIRTIO_BALLOON_CMD_ID_STOP;
+ vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP;
vb->cmd_id_active = cpu_to_virtio32(vb->vdev,
VIRTIO_BALLOON_CMD_ID_STOP);
vb->cmd_id_stop = cpu_to_virtio32(vb->vdev,
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 4cd9ea5c75be..d9dd0f789279 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -468,7 +468,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
{
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
- int i, err;
+ int i, err, queue_idx = 0;
err = request_irq(irq, vm_interrupt, IRQF_SHARED,
dev_name(&vdev->dev), vm_dev);
@@ -476,7 +476,12 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
return err;
for (i = 0; i < nvqs; ++i) {
- vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
+ if (!names[i]) {
+ vqs[i] = NULL;
+ continue;
+ }
+
+ vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
vm_del_vqs(vdev);
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 465a6f5142cc..d0584c040c60 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -285,7 +285,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
u16 msix_vec;
- int i, err, nvectors, allocated_vectors;
+ int i, err, nvectors, allocated_vectors, queue_idx = 0;
vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
if (!vp_dev->vqs)
@@ -321,7 +321,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
msix_vec = allocated_vectors++;
else
msix_vec = VP_MSIX_VQ_VECTOR;
- vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+ vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
ctx ? ctx[i] : false,
msix_vec);
if (IS_ERR(vqs[i])) {
@@ -356,7 +356,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
const char * const names[], const bool *ctx)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
- int i, err;
+ int i, err, queue_idx = 0;
vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
if (!vp_dev->vqs)
@@ -374,7 +374,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
vqs[i] = NULL;
continue;
}
- vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+ vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
ctx ? ctx[i] : false,
VIRTIO_MSI_NO_VECTOR);
if (IS_ERR(vqs[i])) {
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index cd7e755484e3..a0b07c331255 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -152,7 +152,12 @@ struct vring_virtqueue {
/* Available for packed ring */
struct {
/* Actual memory layout for this queue. */
- struct vring_packed vring;
+ struct {
+ unsigned int num;
+ struct vring_packed_desc *desc;
+ struct vring_packed_desc_event *driver;
+ struct vring_packed_desc_event *device;
+ } vring;
/* Driver ring wrap counter. */
bool avail_wrap_counter;
@@ -1609,6 +1614,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
!context;
vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
+ if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+ vq->weak_barriers = false;
+
vq->packed.ring_dma_addr = ring_dma_addr;
vq->packed.driver_event_dma_addr = driver_event_dma_addr;
vq->packed.device_event_dma_addr = device_event_dma_addr;
@@ -2079,6 +2087,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
!context;
vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
+ if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+ vq->weak_barriers = false;
+
vq->split.queue_dma_addr = 0;
vq->split.queue_size_in_bytes = 0;
@@ -2213,6 +2224,8 @@ void vring_transport_features(struct virtio_device *vdev)
break;
case VIRTIO_F_RING_PACKED:
break;
+ case VIRTIO_F_ORDER_PLATFORM:
+ break;
default:
/* We don't understand this bit. */
__virtio_clear_bit(vdev, i);
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index ed05514cc2dc..1834524ae373 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/types.h>
+#include <linux/mfd/bcm2835-pm.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/watchdog.h>
@@ -47,6 +48,8 @@ struct bcm2835_wdt {
spinlock_t lock;
};
+static struct bcm2835_wdt *bcm2835_power_off_wdt;
+
static unsigned int heartbeat;
static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -148,10 +151,7 @@ static struct watchdog_device bcm2835_wdt_wdd = {
*/
static void bcm2835_power_off(void)
{
- struct device_node *np =
- of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
- struct platform_device *pdev = of_find_device_by_node(np);
- struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
+ struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
u32 val;
/*
@@ -169,7 +169,7 @@ static void bcm2835_power_off(void)
static int bcm2835_wdt_probe(struct platform_device *pdev)
{
- struct resource *res;
+ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct bcm2835_wdt *wdt;
int err;
@@ -181,10 +181,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
spin_lock_init(&wdt->lock);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- wdt->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(wdt->base))
- return PTR_ERR(wdt->base);
+ wdt->base = pm->base;
watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
@@ -211,8 +208,10 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
return err;
}
- if (pm_power_off == NULL)
+ if (pm_power_off == NULL) {
pm_power_off = bcm2835_power_off;
+ bcm2835_power_off_wdt = wdt;
+ }
dev_info(dev, "Broadcom BCM2835 watchdog timer");
return 0;
@@ -226,18 +225,11 @@ static int bcm2835_wdt_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id bcm2835_wdt_of_match[] = {
- { .compatible = "brcm,bcm2835-pm-wdt", },
- {},
-};
-MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
-
static struct platform_driver bcm2835_wdt_driver = {
.probe = bcm2835_wdt_probe,
.remove = bcm2835_wdt_remove,
.driver = {
.name = "bcm2835-wdt",
- .of_match_table = bcm2835_wdt_of_match,
},
};
module_platform_driver(bcm2835_wdt_driver);
diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c
index 5c4a764717c4..81208cd3f4ec 100644
--- a/drivers/watchdog/mt7621_wdt.c
+++ b/drivers/watchdog/mt7621_wdt.c
@@ -17,6 +17,7 @@
#include <linux/watchdog.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
#include <asm/mach-ralink/ralink_regs.h>
diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c
index 98967f0a7d10..db7c57d82cfd 100644
--- a/drivers/watchdog/rt2880_wdt.c
+++ b/drivers/watchdog/rt2880_wdt.c
@@ -18,6 +18,7 @@
#include <linux/watchdog.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
#include <asm/mach-ralink/ralink_regs.h>
diff --git a/drivers/watchdog/tqmx86_wdt.c b/drivers/watchdog/tqmx86_wdt.c
index 0d3a0fbbd7a5..52941207a12a 100644
--- a/drivers/watchdog/tqmx86_wdt.c
+++ b/drivers/watchdog/tqmx86_wdt.c
@@ -79,13 +79,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (IS_ERR(res))
- return PTR_ERR(res);
+ if (!res)
+ return -ENODEV;
priv->io_base = devm_ioport_map(&pdev->dev, res->start,
resource_size(res));
- if (IS_ERR(priv->io_base))
- return PTR_ERR(priv->io_base);
+ if (!priv->io_base)
+ return -ENOMEM;
watchdog_set_drvdata(&priv->wdd, priv);
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index ceb5048de9a7..39b229f9e256 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -369,14 +369,20 @@ static enum bp_state reserve_additional_memory(void)
return BP_ECANCELED;
}
-static void xen_online_page(struct page *page)
+static void xen_online_page(struct page *page, unsigned int order)
{
- __online_page_set_limits(page);
+ unsigned long i, size = (1 << order);
+ unsigned long start_pfn = page_to_pfn(page);
+ struct page *p;
+ pr_debug("Online %lu pages starting at pfn 0x%lx\n", size, start_pfn);
mutex_lock(&balloon_mutex);
-
- __balloon_append(page);
-
+ for (i = 0; i < size; i++) {
+ p = pfn_to_page(start_pfn + i);
+ __online_page_set_limits(p);
+ __SetPageOffline(p);
+ __balloon_append(p);
+ }
mutex_unlock(&balloon_mutex);
}
@@ -441,6 +447,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
xenmem_reservation_va_mapping_update(1, &page, &frame_list[i]);
/* Relinquish the page back to the allocator. */
+ __ClearPageOffline(page);
free_reserved_page(page);
}
@@ -467,6 +474,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
state = BP_EAGAIN;
break;
}
+ __SetPageOffline(page);
adjust_managed_page_count(page, -1);
xenmem_reservation_scrub_page(page);
list_add(&page->lru, &pages);
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 93194f3e7540..117e76b2f939 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1650,7 +1650,7 @@ void xen_callback_vector(void)
xen_have_vector_callback = 0;
return;
}
- pr_info("Xen HVM callback vector for event delivery is enabled\n");
+ pr_info_once("Xen HVM callback vector for event delivery is enabled\n");
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
xen_hvm_callback_vector);
}
diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c
index 2e5d845b5091..7aa64d1b119c 100644
--- a/drivers/xen/pvcalls-back.c
+++ b/drivers/xen/pvcalls-back.c
@@ -160,9 +160,10 @@ static void pvcalls_conn_back_read(void *opaque)
/* write the data, then modify the indexes */
virt_wmb();
- if (ret < 0)
+ if (ret < 0) {
+ atomic_set(&map->read, 0);
intf->in_error = ret;
- else
+ } else
intf->in_prod = prod + ret;
/* update the indexes, then notify the other end */
virt_wmb();
@@ -282,13 +283,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev,
static void pvcalls_sk_state_change(struct sock *sock)
{
struct sock_mapping *map = sock->sk_user_data;
- struct pvcalls_data_intf *intf;
if (map == NULL)
return;
- intf = map->ring;
- intf->in_error = -ENOTCONN;
+ atomic_inc(&map->read);
notify_remote_via_irq(map->irq);
}
diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
index 77224d8f3e6f..8a249c95c193 100644
--- a/drivers/xen/pvcalls-front.c
+++ b/drivers/xen/pvcalls-front.c
@@ -31,6 +31,12 @@
#define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE)
#define PVCALLS_FRONT_MAX_SPIN 5000
+static struct proto pvcalls_proto = {
+ .name = "PVCalls",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct sock),
+};
+
struct pvcalls_bedata {
struct xen_pvcalls_front_ring ring;
grant_ref_t ref;
@@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock)
return ret;
}
+static void free_active_ring(struct sock_mapping *map)
+{
+ if (!map->active.ring)
+ return;
+
+ free_pages((unsigned long)map->active.data.in,
+ map->active.ring->ring_order);
+ free_page((unsigned long)map->active.ring);
+}
+
+static int alloc_active_ring(struct sock_mapping *map)
+{
+ void *bytes;
+
+ map->active.ring = (struct pvcalls_data_intf *)
+ get_zeroed_page(GFP_KERNEL);
+ if (!map->active.ring)
+ goto out;
+
+ map->active.ring->ring_order = PVCALLS_RING_ORDER;
+ bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ PVCALLS_RING_ORDER);
+ if (!bytes)
+ goto out;
+
+ map->active.data.in = bytes;
+ map->active.data.out = bytes +
+ XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
+
+ return 0;
+
+out:
+ free_active_ring(map);
+ return -ENOMEM;
+}
+
static int create_active(struct sock_mapping *map, int *evtchn)
{
void *bytes;
@@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn)
*evtchn = -1;
init_waitqueue_head(&map->active.inflight_conn_req);
- map->active.ring = (struct pvcalls_data_intf *)
- __get_free_page(GFP_KERNEL | __GFP_ZERO);
- if (map->active.ring == NULL)
- goto out_error;
- map->active.ring->ring_order = PVCALLS_RING_ORDER;
- bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- PVCALLS_RING_ORDER);
- if (bytes == NULL)
- goto out_error;
+ bytes = map->active.data.in;
for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
map->active.ring->ref[i] = gnttab_grant_foreign_access(
pvcalls_front_dev->otherend_id,
@@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
pvcalls_front_dev->otherend_id,
pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0);
- map->active.data.in = bytes;
- map->active.data.out = bytes +
- XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
-
ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn);
if (ret)
goto out_error;
@@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
out_error:
if (*evtchn >= 0)
xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
- free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
- free_page((unsigned long)map->active.ring);
return ret;
}
@@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
return PTR_ERR(map);
bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+ ret = alloc_active_ring(map);
+ if (ret < 0) {
+ pvcalls_exit_sock(sock);
+ return ret;
+ }
spin_lock(&bedata->socket_lock);
ret = get_request(bedata, &req_id);
if (ret < 0) {
spin_unlock(&bedata->socket_lock);
+ free_active_ring(map);
pvcalls_exit_sock(sock);
return ret;
}
ret = create_active(map, &evtchn);
if (ret < 0) {
spin_unlock(&bedata->socket_lock);
+ free_active_ring(map);
pvcalls_exit_sock(sock);
return ret;
}
@@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf,
virt_mb();
size = pvcalls_queued(prod, cons, array_size);
- if (size >= array_size)
+ if (size > array_size)
return -EINVAL;
+ if (size == array_size)
+ return 0;
if (len > array_size - size)
len = array_size - size;
@@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf,
error = intf->in_error;
/* get pointers before reading from the ring */
virt_rmb();
- if (error < 0)
- return error;
size = pvcalls_queued(prod, cons, array_size);
masked_prod = pvcalls_mask(prod, array_size);
masked_cons = pvcalls_mask(cons, array_size);
if (size == 0)
- return 0;
+ return error ?: size;
if (len > size)
len = size;
@@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
}
}
- spin_lock(&bedata->socket_lock);
- ret = get_request(bedata, &req_id);
- if (ret < 0) {
+ map2 = kzalloc(sizeof(*map2), GFP_KERNEL);
+ if (map2 == NULL) {
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags);
- spin_unlock(&bedata->socket_lock);
+ pvcalls_exit_sock(sock);
+ return -ENOMEM;
+ }
+ ret = alloc_active_ring(map2);
+ if (ret < 0) {
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags);
+ kfree(map2);
pvcalls_exit_sock(sock);
return ret;
}
- map2 = kzalloc(sizeof(*map2), GFP_ATOMIC);
- if (map2 == NULL) {
+ spin_lock(&bedata->socket_lock);
+ ret = get_request(bedata, &req_id);
+ if (ret < 0) {
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags);
spin_unlock(&bedata->socket_lock);
+ free_active_ring(map2);
+ kfree(map2);
pvcalls_exit_sock(sock);
- return -ENOMEM;
+ return ret;
}
+
ret = create_active(map2, &evtchn);
if (ret < 0) {
+ free_active_ring(map2);
kfree(map2);
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags);
@@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
received:
map2->sock = newsock;
- newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL);
+ newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false);
if (!newsock->sk) {
bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
map->passive.inflight_req_id = PVCALLS_INVALID_ID;
@@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock)
spin_lock(&bedata->socket_lock);
list_del(&map->list);
spin_unlock(&bedata->socket_lock);
- if (READ_ONCE(map->passive.inflight_req_id) !=
- PVCALLS_INVALID_ID) {
+ if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID &&
+ READ_ONCE(map->passive.inflight_req_id) != 0) {
pvcalls_front_free_map(bedata,
map->passive.accept_map);
}
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 989cf872b98c..bb7888429be6 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -645,7 +645,7 @@ xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
if (xen_get_dma_ops(dev)->mmap)
return xen_get_dma_ops(dev)->mmap(dev, vma, cpu_addr,
dma_addr, size, attrs);
@@ -662,7 +662,7 @@ xen_swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t handle, size_t size,
unsigned long attrs)
{
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
if (xen_get_dma_ops(dev)->get_sgtable) {
#if 0
/*